[英]How to write a good and efficient makefile
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. 我的目标是在子文件夹中的TOPDIR
和子Makefile, *.mk
下写入主Makefile
, include
文件夹包含一些通用定义。 root
folder contain my main file( main
function located here). root
文件夹包含我的主文件( main
功能位于此处)。 Meanwhile, in main.c
, it will call function from ac
and bc
, cc
is driver related, and will be called from ac
and bc
同时,在main.c
,它将从ac
和bc
调用函数, cc
与驱动程序相关,并且将从ac
和bc
调用
Problem 问题
I wrote sub-makefile like(I use one a.mk
for example, others are same, ONLY root.mk
has little different): 我写了一个子makefile文件(例如,我使用一个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))"
I wrote root.mk
like: 我写的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))"
I wrote main Makefile
like: 我写了主要的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
Question 题
In main Makefile
, I define which LIB
file I will use, if need move it to root.mk
for better? 在主Makefile
,我定义了将使用的LIB
文件,是否需要将其移至root.mk
更好?
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. 在子makefile中,我没有使用-MM
来生成依赖文件,如果这引起了问题,那么我将无法更改lib*
的序列,我在Makefile
注释中也对此进行了描述。
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 似乎我的makefile系统无法检测到我更新了一些头文件,例如,我先编译了整个代码,然后修改了一个头文件,当我尝试重新编译时,没有源代码被编译
if: 如果:
#Automatic dependency magic:
%.d: src/%.c
$(CC) -MM -o$@ $<
-include (MYPROG_OBJECTS:%.o=%.d)
need add into each sub-makefile? 需要添加到每个子makefile中?
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. 问题2和问题3(如果我理解正确)是同一回事:问题3(更改头文件时没有重新编译文件)的原因是,您没有在头文件上声明任何先决条件。 Make doesn't have any built-in support for this, so you either have to do it by hand (add ao : ac bh ch gh
to your makefiles) or else automatically generate the dependencies. Make对此没有任何内置支持,因此您必须手工完成(将ao : ac bh ch gh
到您的makefile中)或自动生成依赖项。
The dependency generation will typically use the -MM
or similar flags, assuming your compiler supports these flags. 假设您的编译器支持这些标志,则依赖项生成通常将使用-MM
或类似的标志。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.