Makefile, how to put OBJ files in separate directory?

Refresh

April 2019

Views

38 time

1

Currently my project has all files within a single directory. I am trying to reorganize it such that I have a src directory for *.c files, an include directory for *.h files, and an obj directory for *.o files as a subdirectory of src. My makefile with every file in one directory works fine and looks like this:

CC=gcc
CFLAGS=-I. -Wall -Wextra -Wpedantic -Werror
DEPS = Triangle.h
OBJ = Trianglecalc.o Triangle.o
TESTOBJ = area_of_triangle_test.o verify_triangle_test.o validate_input_test.o get_side_length_test.o Triangle.o
LIBS=-lm

%.o: %.c $(DEPS)
    $(CC) -c -o [email protected] $< $(CFLAGS)

Trianglecalc: $(OBJ)
    $(CC) -o [email protected] $^ $(CFLAGS) $(LIBS)

tests: $(TESTOBJ)
    $(CC) -o area_of_triangle_test area_of_triangle_test.o Triangle.o $(CFLAGS) $(LIBS)
    $(CC) -o verify_triangle_test verify_triangle_test.o Triangle.o $(CFLAGS) $(LIBS)
    $(CC) -o validate_input_test validate_input_test.o Triangle.o $(CFLAGS) $(LIBS)
    $(CC) -o get_side_length_test get_side_length_test.o Triangle.o $(CFLAGS) $(LIBS)

test-all:
    ./area_of_triangle_test > test_log.txt
    ./verify_triangle_test >> test_log.txt
    ./validate_input_test >> test_log.txt
    ./get_side_length_test >> test_log.txt

.PHONY: clean

clean:
     rm *.o $(objects) Trianglecalc area_of_triangle_test verify_triangle_test validate_input_test get_side_length_test

I have been following this guide to create my makefile: A Simple Makefile Tutorial

Here is what my makefile looks like after reorganizing my project as described above. This makefile is within the src directory:

CC=gcc
IDIR=../include
CFLAGS=-I$(IDIR) -Wall -Wextra -Wpedantic -Werror
ODIR=obj

_DEPS = Triangle.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))

_OBJ = Trianglecalc.o Triangle.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))

_TESTOBJ = area_of_triangle_test.o verify_triangle_test.o validate_input_test.o get_side_length_test.o Triangle.o
TESTOBJ = $(patsubst %,$(ODIR)/%,$(_TESTOBJ))

LIBS=-lm

$(OBJ): $(ODIR)/%o: %.c $(DEPS)
    $(CC) -c -o [email protected] $< $(CFLAGS)

Trianglecalc: $(OBJ)
    $(CC) -o [email protected] $^ $(CFLAGS) $(LIBS)

tests: $(TESTOBJ)
    $(CC) -o area_of_triangle_test area_of_triangle_test.o Triangle.o $(CFLAGS) $(LIBS)
    $(CC) -o verify_triangle_test verify_triangle_test.o Triangle.o $(CFLAGS) $(LIBS)
    $(CC) -o validate_input_test validate_input_test.o Triangle.o $(CFLAGS) $(LIBS)
    $(CC) -o get_side_length_test get_side_length_test.o Triangle.o $(CFLAGS) $(LIBS)

test-all:
    ./area_of_triangle_test > test_log.txt
    ./verify_triangle_test >> test_log.txt
    ./validate_input_test >> test_log.txt
    ./get_side_length_test >> test_log.txt

.PHONY: clean

clean:
    rm *.o $(objects) Trianglecalc area_of_triangle_test verify_triangle_test validate_input_test get_side_length_test

Following the guide linked above I originally had $(OBJ): $(ODIR)/%o: %.c $(DEPS) as $(ODIR)/%o: %.c $(DEPS), but then I got the error:

$ make
    make: *** No rule to make target 'obj/Trianglecalc.o', needed by 'Trianglecalc'. Stop.

I change the line to $(OBJ): $(ODIR)/%o: %.c $(DEPS) as suggested in this answer: Makefile C subdirectory rule to make obj but now I get:

$ make
    make: *** No rule to make target 'Trianglecalc..c', needed by 'obj/Trianglecalc.o'. Stop.

The previous post I linked suggests that this might be due to a spelling error, but I can't find it. I'm confused at how make ended up at Trianglecalc..c instead of Trianglecalc.c, the only place in the makefile with a .. is as part of the IDIR variable. Any suggestions?

P.S. I haven't gotten around to updating the tests: and clean: rules but I'm sure that at least the clean: rule will need to be fixed. As best I can tell the current problem is with the Trianglecalc: rule.

0 answers