如何使顶级Makefile调用子目录Makefile中的所有目标?
我的文件夹结构是这样的
/Makefile
/src/Makefile
Run Code Online (Sandbox Code Playgroud)
我编写所有目标代码/src/Makefile,但现在我想写另一个目标/Makefile以简化我的工作.如何编写这个顶级Makefile?
您可以在TOP makefile中使用
all:
@$(MAKE) -C src
Run Code Online (Sandbox Code Playgroud)
例如,如果你不在子目录中使用makefile,你可以使用somename.mk
all:
@$(MAKE) -C src -f somename.mk
Run Code Online (Sandbox Code Playgroud)
我告诉你我的例子,我的DIR看起来像:
TOPDIR-- Makefile
|
|-- debug
| |-- debug.c
| |-- debug.h
| |-- debug.mk
| |-- instrument.c
| `-- uart_print.c
|-- driver
| |-- driver.c
| |-- driver_ddi.c
| |-- driver_ddi.h
| |-- driver.h
| `-- driver.mk
|-- include
| `-- common.h
|-- Makefile
|-- mw
| |-- manager.c
| `-- mw.mk
|-- root
| |-- main.c
| `-- root.mk
Run Code Online (Sandbox Code Playgroud)
我的TOP 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
COLOR_ON = color
COLOR_OFF =
CC = $(COLOR_ON)gcc
#CC = $(COLOR_OFF)gcc
LD = ld
LINT = splint
LIBS := -ldriver -ldebug -lmw -lm -lpthread
CFLAGS :=
CFLAGS += $(INC_SRCH_PATH) $(LIB_SRCH_PATH)
CFLAGS += -Wall -O -ggdb -Wstrict-prototypes -Wno-pointer-sign -finstrument-functions -fdump-rtl-expand
CFLAGS += -DDEBUG -D_REENTRANT
LDFLAGS :=
export MAKE_DIR CC LD CFLAGS LDFLAGS LIBS LINT INC_SRCH_PATH
all:
@$(MAKE) -C debug -f debug.mk
@$(MAKE) -C driver -f driver.mk
@$(MAKE) -C mw -f mw.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
.PHONY: lint
lint:
$(MAKE) -C debug -f debug.mk lint
Run Code Online (Sandbox Code Playgroud)
它会在编译期间调用sub DIR*.mk.子DIR makefile,我只是写一个简单的例子供你参考:
LIB = $(MAKE_DIR)/libs/yourmodulename.a
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c, %.o, $(SRCS))
$(LIB): $(OBJS)
@mkdir -p ../libs
@$(AR) cr $@ $^
@echo " Archive $(notdir $@)"
$(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))"
.PHONY: lint
lint:
$(LINT) $(INC_SRCH_PATH) $(SRCS)
Run Code Online (Sandbox Code Playgroud)
对于makefile,生成目标文件有点不同,因为我使用sub makefile生成LIB文件,而我使用a root.mk生成目标:
PROG = ../prog/DEMO
SRCS = $(wildcard *.c)
OBJS = $(patsubst %.c, %.o, $(SRCS))
$(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))"
Run Code Online (Sandbox Code Playgroud)
请注意,至少有两种方法可以做到这一点。
GNU 更改目录选项
一种方法是使用 GNU Make 的特定功能,该-C选项允许更改编译目录并到达另一个目录:
all:
make -C dir
Run Code Online (Sandbox Code Playgroud)
手册make说:
Run Code Online (Sandbox Code Playgroud)-C dir, --directory=dir Change to directory dir before reading the makefiles or doing anything else. If multiple -C options are specified, each is interpreted relative to the previous one: -C / -C etc is equivalent to -C /etc. This is typically used with recursive invocations of make.
您还可以通过调用目标目录中的特定目标来组合此选项。例如,以下目标将进入src/目录并make使用clean目标进行调用:
clean:
@rm -f *.o
make -C src/ clean
Run Code Online (Sandbox Code Playgroud)
POSIX方式
GNU 方法的问题在于它只适用于 GNU Make,而不适用于标准 Make。如果您可能使用另一个 Make(无论出于何种原因),您最好考虑以更 POSIX 的方式进行操作。
在 POSIX Make 中,你必须更多地依赖命令cd,像这样:
all:
cd src/ && make
Run Code Online (Sandbox Code Playgroud)
请注意,我使用了&&而不是;. 避免无限递归调用非常重要make。事实上,cmd1 ; cmd2将顺序执行cmd1,cmd2无论每个命令的结果是什么,其中cmd1 && cmd2将顺序执行cmd1,并且cmd2仅在cmd1返回EXIT_SUCCESS. 在我们的例子中,假设第一个cd失败是因为目录已被删除。然后,初始的 makefile 将在无限递归循环中一次又一次地执行。
无论如何,这种 POSIX 方式是下降到子目录并执行其他 Makefile 的更稳健的方式。我建议您更好地使用它,而不是依赖与 GNU Make 链接的选项。