Reputation: 1370
I have following folder structure:
TOPDIR
|
├── a
│ ├── a.c
│ ├── a.h
│ └── a.mk
├── b
│ ├── b.c
│ ├── b.h
│ └── b.mk
├── c
│ ├── c.c
│ ├── c.h
│ └── c.mk
├── include
│ └── common.h
├── root
│ ├── main.c
│ └── root.mk
└── Makefile
per-condition
My target is to write main Makefile
under TOPDIR
and sub-makefile, *.mk
in sub folder, the include
folder contain some common defines. root
folder contain my main file(main
function located here). Meanwhile, in main.c
, it will call function from a.c
and b.c
, c.c
is driver related, and will be called from a.c
and b.c
Problem
I wrote sub-makefile like(I use one a.mk
for example, others are same, ONLY root.mk
has little different):
#MODULE will be modified for each sub folder
MODULE = a
LIB = $(MAKE_DIR)/libs/lib$(MODULE).a
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c, %.o, $(SRCS))
#generate lib file from obj file
$(LIB): $(OBJS)
@mkdir -p ../libs
@$(AR) cr $@ $^
@echo " Archive $(notdir $@)"
#compile obj file from source file
$(OBJS): $(SRCS)
@$(CC) $(CFLAGS) -c $^
@echo " CC $(OBJS)"
.PHONY: clean
clean:
@$(RM) -f $(LIB) $(OBJS)
@$(RM) -f *.expand
@echo " Remove Objects: $(OBJS)"
@echo " Remove Libraries: $(notdir $(LIB))"
I wrote root.mk
like:
PROG = ../prog/DEMO
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c, %.o, $(SRCS))
#generate finial target file for run
$(PROG): $(SRCS)
@mkdir -p ../prog
@$(CC) $^ $(CFLAGS) -Wl,-Map=$(PROG).map $(LIBS) -o $@
@echo " Generate Program $(notdir $(PROG)) from $^"
.PHONY: clean
clean:
@$(RM) -f $(OBJS) $(PROG)
@$(RM) -f *.expand
@$(RM) -rf ../prog ../libs
@echo " Remove Objects: $(OBJS)"
@echo " Remove Libraries: $(notdir $(PROG))"
I wrote main Makefile
like:
MAKE_DIR = $(PWD)
ROOT_DIR := $(MAKE_DIR)/root
DRV_DIR := $(MAKE_DIR)/driver
INCLUDE_DIR := $(MAKE_DIR)/include
DEBUG_DIR := $(MAKE_DIR)/debug
INC_SRCH_PATH :=
INC_SRCH_PATH += -I$(ROOT_DIR)
INC_SRCH_PATH += -I$(DRV_DIR)
INC_SRCH_PATH += -I$(INCLUDE_DIR)
INC_SRCH_PATH += -I$(DEBUG_DIR)
LIB_SRCH_PATH :=
LIB_SRCH_PATH += -L$(MAKE_DIR)/libs
CC = gcc
LD = ld
#problem happan here, if I change the sequence of LIB,
#during the finial link, it will find some function un-referenced,
#why can I put liba first?
LIBS := -lc -lb -la
CFLAGS :=
CFLAGS += $(INC_SRCH_PATH) $(LIB_SRCH_PATH)
CFLAGS += -Wall -O -ggdb
CFLAGS += -DDEBUG -D_REENTRANT
LDFLAGS :=
export MAKE_DIR CC LD CFLAGS LDFLAGS LIBS LINT INC_SRCH_PATH
all:
@$(MAKE) -C a -f a.mk
@$(MAKE) -C b -f b.mk
@$(MAKE) -C c -f c.mk
@$(MAKE) -C root -f root.mk
.PHONY: clean
clean:
@$(MAKE) -C debug -f debug.mk clean
@$(MAKE) -C driver -f driver.mk clean
@$(MAKE) -C mw -f mw.mk clean
@$(MAKE) -C root -f root.mk clean
Question
In main Makefile
, I define which LIB
file I will use, if need move it to root.mk
for better?
In sub-makefile, I did NOT use -MM
to generate depend file, if this cause the problem I can NOT change the sequence of my lib*
, which I also described in Makefile
comments.
Seems my makefile system can NOT detect I update some head file, for example, I first compiled whole code, and then, I modified one head file, when I try to re-compile, none of source is compiled
if:
#Automatic dependency magic:
%.d: src/%.c
$(CC) -MM -o$@ $<
-include (MYPROG_OBJECTS:%.o=%.d)
need add into each sub-makefile?
Upvotes: 3
Views: 3961
Reputation: 100926
This rule is definitely wrong:
$(OBJS): $(SRCS)
@$(CC) $(CFLAGS) -c $^
@echo " CC $(OBJS)"
The target line will expand to something like:
a.o b.o c.o d.o : a.c b.c c.c d.c
That's not right. It is identical to writing this:
a.o : a.c b.c c.c d.c
...
b.o : a.c b.c c.c d.c
...
c.o : a.c b.c c.c d.c
...
d.o : a.c b.c c.c d.c
...
This means that whenever you change any source file, ALL the object files will be rebuilt. You should use a pattern rule here:
%.o : %.c
@$(CC) $(CFLAGS) -o $@ -c $<
@echo " CC $@"
to compile the object files one at a time.
As far as your questions go, I don't understand question #1.
Questions #2 and #3 (if I understand correctly) are the same thing: the reason for #3 (no files are recompiled when you change a header file) is that you're not declaring any prerequisites on header files. Make doesn't have any built-in support for this, so you either have to do it by hand (add a.o : a.c b.h c.h g.h
to your makefiles) or else automatically generate the dependencies.
The dependency generation will typically use the -MM
or similar flags, assuming your compiler supports these flags.
Upvotes: 4