2013-07-26 88 views
2

如何讓頂層Makefile調用子目錄Makefile中的所有目標?如何使makefile在子目錄makefile中找到目標

我的文件夾結構是這樣的

/Makefile 
/src/Makefile 

我的代碼/src/Makefile所有目標,但現在我要再寫/Makefile緩解我的工作。如何編寫這個頂級Makefile?

+0

你想要'makefile'調用子'makefile'嗎? –

+1

你是指所有目標,還是「全部」目標? – Beta

回答

4

你可以在你的頂層Makefile編寫使用

all: 
    @$(MAKE) -C src 

,如果你不子目錄使用的makefile,例如,你可以使用somename.mk,你可以使用

all: 
    @$(MAKE) -C src -f somename.mk 

我告訴你我的例子,我的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 

和我頂層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 

它將在編譯期間調用子目錄* .mk。子DIR的makefile,我只寫你引用一個簡單的例子:

LIB = $(MAKE_DIR)/libs/yourmodulename.a 
SRCS = $(wildcard *.c) 
OBJS = $(patsubst %.c, %.o, $(SRCS)) 

$(LIB): $(OBJS) 
    @mkdir -p ../libs 
    @$(AR) cr [email protected] $^ 
    @echo " Archive $(notdir [email protected])" 

$(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) 

的Makefile文件生成目標文件是有點不同,因爲我用的是子​​生成文件生成LIB文件,我用一個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 [email protected] 
    @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))" 
+0

非常感謝,但是「全部」匹配任何目標?或者「全部」只是一個目標的例子? –

+0

@guilin桂林,在我的'makefile'中,我想'all'匹配我的項目的任何目標 –

2

請注意,至少有兩種方法來做到這一點。

GNU Changedir選項

一種方法是使用GNU的特定功能時許,-C選項允許改變你的編譯目錄,並達到另一個問題:

all: 
    make -C dir 

make手冊說:

-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/目錄並調用makeclean目標:

clean: 
     @rm -f *.o 
     make -C src/ clean 

POSIX路

與做的GNU方式的問題是,它只能與GNU工程製作,而不是標準的製作。如果您可能使用其他品牌(無論出於何種原因),您最好考慮以更POSIX的方式進行。

在POSIX做,你必須更多地依靠cd命令,就像這樣:

all: 
     cd src/ && make 

需要注意的是,我用&&,而不是;。避免對make進行無限遞歸調用非常重要。實際上,cmd1 ; cmd2將按順序執行cmd1cmd2,無論每個命令的結果如何,其中cmd1 && cmd2將按順序執行cmd1cmd2將僅在cmd1返回EXIT_SUCCESS時執行。在我們的例子中,想象第一個cd因爲目錄已被刪除而失敗。然後,最初的makefile將在無限遞歸循環中一次又一次地執行。

無論如何,這種POSIX方式,是在子目錄中下降並執行其他Makefile的更健壯的方式。我建議你比使用與GNU Make相關的選項更好地使用它。