1
votes

I am trying to write a Makefile for a small C program. It's structure is

project_root

  • src (source files)
  • tests (test files)
  • build (program binary)

My make file is below.

CFLAGS = -g -Wall -Isrc $(OPTFLAGS)
LDLIBS = $(OPTLIBS)

PREFIX ?= /usr/local/
OPTVALGRIND="valgrind --track-origins=yes --log-file=tests/valgrind.log"

TARGET_SRC = src/hello_make.c
TARGET = build/hello_make

SOURCES := $(wildcard src/*.c)
SOURCES := $(filter-out $(TARGET_SRC),$(SOURCES))

OBJECTS = $(patsubst %.c,%.o,$(SOURCES))

TEST_SRC = $(wildcard tests/*_tests.c)
TESTS = $(patsubst %.c,%,$(TEST_SRC))
TEST_FILE ?= hello_make_tests

all: $(TARGET) tests

$(TARGET): build $(OBJECTS)
    $(CC) $(CFLAGS) $(TARGET_SRC) $(OBJECTS) $(LDLIBS) -o $@ 

.PHONY: compile_tests tests test testv valgrind build clean
compile_tests: LDLIBS += -lrt -lm
compile_tests: CFLAGS += $(OBJECTS)
compile_tests: build $(OBJECTS) $(TESTS)
    @echo "TARGET=$(TARGET), TESTS=$(TESTS)"
    @echo "compile_tests done"

tests: compile_tests
    sh ./tests/run_tests.sh

test: compile_tests
    sh ./tests/run_test.sh tests/$(TEST_FILE)

testv: compile_tests
    sh ./tests/run_test.sh tests/$(TEST_FILE)

valgrind:
    VALGRIND=$(OPTVALGRIND) $(MAKE) -s

clean:
    rm -rf $(OBJECTS)
    rm -rf $(TARGET)
    rm -rf $(TESTS)
    rm -rf build
    rm -rf tests/*.log

build:
    @mkdir -p build

I have a target test and testv(corresponding for running with valgrind). So when I do,

make test TEST_FILE=hello_make_tests

it should build anything needed for this test. Then run tests/hello_make_tests.

I have most of the Makefile working. It builds and compiles the source files to .o links those to the test program. $\

My problem is that this only works if I use make all first then followed by make test. When I do make clean followed by make test. I get the following error.

cc -g -Wall -Isrc  src/get_one.o src/get_three.o src/get_two.o   -c -o src/get_one.o src/get_one.c
cc: error: src/get_one.o: No such file or directory
cc: error: src/get_three.o: No such file or directory
cc: error: src/get_two.o: No such file or directory
make: *** [src/get_one.o] Error 1

The cc call seems to be wrong with object files acting as sources? I am pretty new to make and am unable to figure this out. Please help.

1

1 Answers

1
votes

This line

compile_tests: CFLAGS += $(OBJECTS)

adds all objects to the CFLAGS variable which will be used by the implicit rules (that are built into make) when compiling.

Try to keep source, compiler flags and resulting object files separate in your makefile to avoid this kind of confusion.

Have a quick look at the documentation for the makefile flags if you're uncertain of their usage.