user2328414
user2328414

Reputation: 25

In Makefile how do I build seperate executable for each C file

I am using Check for my C unit tests. For each C library file I create there should be one test file which should generate a single executable that is linked from the test and the source code. This executable should then be run to make sure all tests pass.

When there is only 1 test file and 1 source file everything works great. As soon as I add a second source file with the corresponding test file, it tries to link them all into 1 executable.

How do I get the second rule to pull 1 TEST_SRC and the matching SRC and header file into a TEST_OBJ then compile the 2 object files into an executable? Below is my current Makefile

OUT_DIR=bin
BUILD_DIR=build
TEST_BUILD_DIR=test_build
SRC_DIR=src
TEST_SRC_DIR=tests
SRC= $(wildcard $(SRC_DIR)/*.c)
TEST_SRC= $(patsubst $(SRC_DIR)/%.c, $(TEST_SRC_DIR)/%_tests.c, $(SRC))
TEST_OBJ= $(patsubst $(TEST_SRC_DIR)/%.c, $(TEST_BUILD_DIR)/%.o, $(TEST_SRC))
OBJ= $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(SRC))

$(OUT_DIR)/string_calculator_tests: $(TEST_OBJ)
    gcc -o $@ $^ `pkg-config --cflags --libs check`

$(TEST_OBJ): $(TEST_SRC) $(SRC)
    gcc -c -o $@ $^ `pkg-config --cflags --libs check`

Any help would be appreciated.

Upvotes: 2

Views: 1219

Answers (1)

Beta
Beta

Reputation: 99084

It's a little unclear exactly how you want this makefile to behave, but we can take it in stages.

Look at this rule:

$(TEST_OBJ): $(TEST_SRC) $(SRC)
    gcc -c -o $@ $^ `pkg-config --cflags --libs check`

Each object is built out of all source files. And you don't seem to have a rule for OBJ. So let's replace this with two static pattern rules:

$(TEST_OBJ): $(TEST_BUILD_DIR)/%.o : $(TEST_SRC_DIR)/%.c
    gcc -c -o $@ $< `pkg-config --cflags --libs check`

$(OBJ): $(BUILD_DIR)/%.o : $(SRC_DIR)/%.c
    gcc -c -o $@ $< `pkg-config --cflags --libs check`

Then a rule to build an executable from a pair of object files:

TESTS = $(patsubst $(SRC_DIR)/%.c, $(TEST_BUILD_DIR)/%_test, $(SRC))

$(TESTS): $(TEST_BUILD_DIR)/%_test : $(BUILD_DIR)/%.o $(TEST_BUILD_DIR)/%_tests.o
    gcc -o $@ $^ `pkg-config --cflags --libs check`

Then a rule to build all tests:

.PHONY: all_tests

all_tests: $(TESTS)

That should be enough to get you started. Once this works, there are many possible improvements, such as targets to run the tests, and tidier ways to write the tests using advanced techniques like vpath. And we haven't even talked about header files and dependency handling...

Upvotes: 3

Related Questions