Topper Harley
Topper Harley

Reputation: 12374

GNU make dependency issue

To make it simple, say I have the following folders:

My 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:
touching 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

Answers (1)

Eldar Abusalimov
Eldar Abusalimov

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.

UPD.

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

Related Questions