2

Is there a way around having to switch my project to use rake as its build system? I have a large project using Make as its build system and would like to add CMock functionality for unit testing (I'm already successfully using Unity), but have found no information about integrating CMock with Makefiles (instead, it seems the world has just accepted using Ruby's rake as their build system if they want CMock to work with their projects).

I have been able to run the CMock example tests, which include a (seemingly unfinished?) 'make' example.

I've modified the test code in the 'make_example' to the following:

#include "mock_foo.h"
#include "unity.h"

void setUp(void) {}

void tearDown(void) {}

void test_main_should_initialize_foo(void) {
        foo_init_Ignore();
        TEST_IGNORE_MESSAGE("TODO: Implement main!");
}

however, when running 'make' from the folder with the Makefile, it seems UNITY_LINE_TYPE is undefined (e.g. something is missing from my dependency chain):

make
mkdir -p ./build
mkdir -p ./build/obj
ruby ../../scripts/create_makefile.rb --silent
cc -o build/test/obj/test_main.o -c test/test_main.c -DTEST -I ./src -I /home/user/Documents/gitrepos/cmock/vendor/unity/src -I /home/user/Documents/gitrepos/cmock/src -I ./build/test/mocks 
In file included from test/test_main.c:1:0:
./build/test/mocks/mock_foo.h:27:27: error: unknown type name ‘UNITY_LINE_TYPE’
 void foo_init_CMockExpect(UNITY_LINE_TYPE cmock_line);
                           ^
build/test/MakefileTestSupport:29: recipe for target 'build/test/obj/test_main.o' failed
make: *** [build/test/obj/test_main.o] Error 1

Has anyone successfully implemented a project using Makefiles and CMock?

August Janse
  • 290
  • 1
  • 6
  • 18

3 Answers3

1

Turns out I was the victim of some of my own vim/clang-format configuration here.

The make_example (though not very useful out of the box) does compile and run tests properly using CMock's mocking framework if the 'unity.h' import is placed before the 'mock_xxx.h' in your test implementation (which I'm sure is called out in the documentation somewhere).

The following is an example of a working test (slightly modified test_main.c from cmock/examples/make_example):

#include "unity.h"
#include "mock_foo.h"

void setUp(void)
{
}

void tearDown(void)
{
}

void test_main_should_initialize_foo(void)
{
    foo_init_Expect();
    foo_init();
}

However, since my vim/clang format was set to 'SortIncludes: true', my includes were reordered to produce:

#include "mock_foo.h" // <---- the mocks must be included *after* unity.h
#include "unity.h"

void setUp(void)
{
}

void tearDown(void)
{
}

void test_main_should_initialize_foo(void)
{
    foo_init_Expect();
    foo_init();
}

just as I was :wq in vim.

This, of course, causes CMock problems, as it needs the unity.h definitions figured out before it tries to generate the mock_foo.h, so I was getting the error I posted above:

...
In file included from test/test_main.c:1:0:
./build/test/mocks/mock_foo.h:27:27: error: unknown type name ‘UNITY_LINE_TYPE’
 void foo_init_CMockExpect(UNITY_LINE_TYPE cmock_line);
...

My Makefile (untouched from the CMock example), for posterity:

CC ?= gcc
BUILD_DIR ?= ./build
SRC_DIR ?= ./src
TEST_DIR ?= ./test
TEST_BUILD_DIR ?= ${BUILD_DIR}/test
TEST_MAKEFILE = ${TEST_BUILD_DIR}/MakefileTestSupport
OBJ ?= ${BUILD_DIR}/obj
OBJ_DIR = ${OBJ}

default: all

all: setup test ${BUILD_DIR}/main run

setup:
    mkdir -p ${BUILD_DIR}
    mkdir -p ${OBJ}
    ruby ../../scripts/create_makefile.rb --silent

clean:
    rm -rf ${BUILD_DIR}

${BUILD_DIR}/main: ${SRC_DIR}/main.c ${SRC_DIR}/foo.c
    ${CC} $< -o $@

run:
    ./build/main || true

test: setup

-include ${TEST_MAKEFILE}

I found this was happening by finding that UNITY_LINE_TYPE was defined in unity.h and paid attention to how that unity.h was being included in my test, saw it was included after 'mock_foo.h' (no problem apparant to me yet), then compared to some working rake examples (in ../temp_sensor) where I noticed that all the 'unity.h' includes were before all the 'mock_xxx.h' includes (I hadn't touched these with vim yet.)

Don't let your tools be fools.

1

This bug has just been fixed: https://github.com/ThrowTheSwitch/CMock/pull/211

Now you do not need to keep specific order of #include directives.

merazmus
  • 11
  • 1
0

Your mileage may vary, but I've found that grouping my includes with newlines causes clang-format to sort within the groups, thus allowing me to preserve important headers at the beginning. Usually this makes a certain logical sense as well.

So for instance, in my test_xyz.c file:

#include "unity.h"

#include "support/logging.h"
#include "crc.h"
#include "mock_unistd.h"

Gets sorted to:

#include "unity.h"

#include "crc.h"
#include "mock_unistd.h"
#include "support/logging.h"
jmgregory
  • 84
  • 3