Updating make file to link dependency files

805 views Asked by At

I am using the Unity C unit testing framework (http://www.throwtheswitch.org/unity). I am using the sample makefile that they provide (http://www.throwtheswitch.org/build/make).

My question is how do I declare dependencies in this makefile.

For example: I have a file a.c and it has the header b.h. I have a file b.c and it has the header b.h. b.c implements the function foo(). a.c uses the function foo(). How do I setup linking like this using the makefile below:

CLEANUP = rm -f
MKDIR = mkdir -p
TARGET_EXTENSION=out

.PHONY: clean
.PHONY: test

PATHU = unity/
PATHS = src/
PATHT = test/
PATHB = build/
PATHD = build/depends/
PATHO = build/objs/
PATHR = build/results/

BUILD_PATHS = $(PATHB) $(PATHD) $(PATHO) $(PATHR)

SRCT = $(wildcard $(PATHT)*.c)

COMPILE=gcc -c
LINK=gcc
DEPEND=gcc -MM -MG -MF
CFLAGS=-I. -I$(PATHU) -I$(PATHS) -DTEST

RESULTS = $(patsubst $(PATHT)Test%.c,$(PATHR)Test%.txt,$(SRCT) )

PASSED = `grep -s PASS $(PATHR)*.txt`
FAIL = `grep -s FAIL $(PATHR)*.txt`
IGNORE = `grep -s IGNORE $(PATHR)*.txt`

test: $(BUILD_PATHS) $(RESULTS)
    @echo "-----------------------\nIGNORES:\n-----------------------"
    @echo "$(IGNORE)"
    @echo "-----------------------\nFAILURES:\n-----------------------"
    @echo "$(FAIL)"
    @echo "-----------------------\nPASSED:\n-----------------------"
    @echo "$(PASSED)"
    @echo "\nDONE"

$(PATHR)%.txt: $(PATHB)%.$(TARGET_EXTENSION)
    -./$< > $@ 2>&1

$(PATHB)Test%.$(TARGET_EXTENSION): $(PATHO)Test%.o $(PATHO)%.o $(PATHU)unity.o #$(PATHD)Test%.d
    $(LINK) -o $@ $^

$(PATHO)%.o:: $(PATHT)%.c
    $(COMPILE) $(CFLAGS) $< -o $@

$(PATHO)%.o:: $(PATHS)%.c
    $(COMPILE) $(CFLAGS) $< -o $@

$(PATHO)%.o:: $(PATHU)%.c $(PATHU)%.h
    $(COMPILE) $(CFLAGS) $< -o $@

$(PATHD)%.d:: $(PATHT)%.c
    $(DEPEND) $@ $<

$(PATHB):
    $(MKDIR) $(PATHB)

$(PATHD):
    $(MKDIR) $(PATHD)

$(PATHO):
    $(MKDIR) $(PATHO)

$(PATHR):
    $(MKDIR) $(PATHR)

clean:
    $(CLEANUP) $(PATHO)*.o
    $(CLEANUP) $(PATHB)*.$(TARGET_EXTENSION)
    $(CLEANUP) $(PATHR)*.txt

.PRECIOUS: $(PATHB)Test%.$(TARGET_EXTENSION)
.PRECIOUS: $(PATHD)%.d
.PRECIOUS: $(PATHO)%.o
.PRECIOUS: $(PATHR)%.txt

So, far my project directory is setup with

  • src/node.c
  • src/node.h
  • src/lca.c
  • lca.c uses a function newNode defined in node.h (which is implemented in node.c)
  • test/Testlca.c is the test function which Unity tests lca.c with

I get the following error:

cc -I. -Iunity/ -Isrc/ -DTEST   -c -o unity/unity.o unity/unity.c
gcc -o build/Testlca.out build/objs/Testlca.o build/objs/lca.o unity/unity.o
Undefined symbols for architecture x86_64:
  "_newNode", referenced from:
      _test_newNode_should_nodePointer in Testlca.o
     (maybe you meant: _test_newNode_should_nodePointer)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see     invocation)
make: *** [build/Testlca.out] Error 1

I believe this is due to errors in the makefile and that I have to tweak the makefile.

1

There are 1 answers

0
Mark Vander Voord On BEST ANSWER

The first thing to point out is that you might be heading down a path of making some hard-to-manage tests. The purpose of unit testing is to test a single unit at a time, but you have a test here which is going to require two units to be compiled together to be tested properly. While occasionally that is a great solution (usually when the two units are overly tightly coupled and you can't really change them), it's usually not the best solution.

One option is to use a mock in place of node.c instead of calling the real version of the function. This gives you great control in testing lca.c as a unit by itself.

This doesn't directly solve your problem yet, but I just felt I should point it out before you get much further.

Getting to your main point, Job Vranish from Atomic Object wrote a really good article on writing a simple makefile with dependency tracking. You can find it here: https://spin.atomicobject.com/2016/08/26/makefile-c-projects/

He suggests that, if you're using Clang or gcc, that you generate dependency files as a side effect of compiling by adding the flags -MMD -MP. Then you need to pull the dependencies into your project as follows:

DEPS := $(OBJS:.o=.d)
-include $(DEPS)

That can just go at the bottom of your makefile and all of the dependencies (once generated) should get pulled in automatically.

If you're NOT using gcc, you'll want to add dependency generation to either your build step, or a step of its own.

Happy Testing!