我有以下文件夹结构:
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
每个条件
我的目标是在Makefile
下编写主TOPDIR
,在子文件夹中编写子文件*.mk
,include
文件夹包含一些常见的定义。 root
文件夹包含我的主文件(main
函数位于此处)。同时,在main.c
中,它会调用来自a.c
和b.c
的函数,c.c
与驱动程序相关,并将从a.c
和{{1}调用}
问题
我写的子makefile就像(例如我使用一个b.c
,其他的相同,只有a.mk
有一点不同):
root.mk
我写了#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))"
,如:
root.mk
我写了主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))"
,如:
Makefile
问题
在主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
中,我定义了我将使用哪个Makefile
文件,如果需要将其移至LIB
以获得更好的效果?
在sub-makefile中,我没有使用root.mk
生成依赖文件,如果这导致问题我无法更改-MM
的序列,我在{ {1}}评论。
好像我的makefile系统无法检测到我更新了一些头文件,例如,我先编译整个代码,然后,我修改了一个头文件,当我尝试重新编译时,没有编译源代码
如果:
lib*
需要添加到每个子makefile中吗?
答案 0 :(得分:3)
这条规则绝对是错误的:
$(OBJS): $(SRCS)
@$(CC) $(CFLAGS) -c $^
@echo " CC $(OBJS)"
目标线将扩展为:
a.o b.o c.o d.o : a.c b.c c.c d.c
那不对。这与写这个相同:
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
...
这意味着无论何时更改任何源文件,都将重建所有目标文件。你应该在这里使用模式规则:
%.o : %.c
@$(CC) $(CFLAGS) -o $@ -c $<
@echo " CC $@"
一次编译一个目标文件。
就你的问题而言,我不明白问题#1。
问题#2和#3(如果我理解正确的话)是相同的:#3(更改头文件时没有重新编译文件)的原因是你没有声明头文件的任何先决条件。 Make没有任何内置的支持,因此您必须手动执行(将a.o : a.c b.h c.h g.h
添加到makefile)或者自动生成依赖项。
依赖关系生成通常会使用-MM
或类似的标志,假设您的编译器支持这些标志。