Reputation: 12374
To make it simple, say I have the following folders:
./src/
with many .c files./obj/
with many .obj files./output/
with my binaries I want to buildMy makefile is as follows:
all: init mybin
# init commands
init:
mkdir obj
mkdir output
mybin: project1 project2 project3
$(CC) src/misc.c ... etc
$(LK) obj/first.obj obj/second.obj obj/third.obj obj/four.obj obj/five.obj obj/six.obj obj/seven.obj obj/eight.obj obj/nine.obj -o output/myapp.bin
project1: obj/first.obj obj/second.obj obj/third.obj
obj/first.obj: src/first.c
$(CC) first.c ... etc
obj/second.obj: src/second.c
$(CC) obj/second.c ... etc
obj/third.obj: src/third.c
$(CC) obj/third.c ... etc
project2: obj/four.obj obj/five.obj obj/six.obj
obj/four.obj: src/four.c
$(CC) four.c ... etc
obj/five.obj: src/five.c
$(CC) obj/five.c ... etc
obj/six.obj: src/six.c
$(CC) obj/six.c ... etc
project3: obj/seven.obj obj/eight.obj obj/nine.obj
obj/seven.obj: src/seven.c
$(CC) seven.c ... etc
obj/eight.obj: src/eight.c
$(CC) obj/eight.c ... etc
obj/nine.obj: src/nine.c
$(CC) obj/nine.c ... etc
The first time I ran make all
, everything compiled find. Then I did:
$ touch src/four.c
$ make all
$
But make
exits without compiling anything. I guess it did not detect that one of the .c files had changed, however I don't see what's wrong with my dependencies.
What I expected:
touch
ing src/four.c
should have marked obj/four.obj
obsolete, and project2
aswell, hence marking mybin
obsolete too. This chain should trigger a new compilation of src/four.c
to obj/four.obj
and then a new linkage of the whole project.
Upvotes: 0
Views: 388
Reputation: 25483
Did you specify the output file of compilation (likely the -o
option)? By default (for most toolchains), compiling a .c
file produces an .o
file, not an .obj
one.
To get Make updating targets when some prerequisites change you have to provide an exact dependencies between files as far as Make use timestamps to determine whether a file has been changed.
That is, all
and init
could remain as so-called .PHONY
targets, but it is a good practice to make the rest targets to be files.
OUT_DIR := ./output
SRC_DIR := ./src
OBJ_DIR := ./obj
MYBIN := $(OUT_DIR)/myapp.bin
OBJS := $(addprefix $(OBJ_DIR)/, \
first.obj \
second.obj \
third.obj \
four.obj \
five.obj \
six.obj \
seven.obj \
eight.obj \
nine.obj)
.PHONY : all mkdir-output mkdir-obj
all : $(MYBIN)
mkdir-output :
@mkdir -p $(OUT_DIR)
mkdir-obj :
@mkdir -p $(OBJ_DIR)
$(MYBIN) : $(OBJS) | mkdir-output
$(LK) $^ -o $@
$(OBJS) : | mkdir-out
$(OBJS) : $(OBJ_DIR)/%.obj : $(SRC_DIR)/%.c
$(CC) $< -object=$@ $(CC_OPT)
The last rule is GNU Make's static pattern rule. And the mkdir-xxx
prerequisites after a pipe sign |
are order-only ones.
Upvotes: 1