天天看點

代碼片段--Makefile之大型工程項目子目錄Makefile的一種通用寫法

管理Linux環境下的C/C++大型項目,如果有一個智能的Build System會起到事半功倍的效果,本文描述Linux環境下大型工程項目子目錄Makefile的一種通用寫法,使用該方法,當該子目錄内的檔案有增删時無需對Makefile進行改動,可以說相當的智能。下面先貼代碼(為減小篇幅,一些非關鍵的代碼被去掉):

ROOTDIR = .

EXE_DIR = ./bin
CFLAGS = -I$(INCLUDE_DIR) -I$(LIB_INC) -Wall
LFLAGS = -L$(LIB_DIR)

objects := $(patsubst %.c,%.o,$(wildcard *.c))
executables := $(patsubst %.c,%,$(wildcard *.c))

$(objects) : %.o: %.c
    $(CROSS_COMPILE)gcc -c $(CFLAGS) $< -o $@
all : $(executables)
$(executables) : $(objects)
    @mkdir -p ./bin$
    (CROSS_COMPILE)gcc $(CFLAGS) $< -o $(EXE_DIR)/$@ $(LFLAGS) $(LIBS)
clean:
    @rm -f *.o rm -f ./bin/* 
    @rm -rf ./bin 
distclean: clean      

假如目前目錄裡面有a.c b.c兩個檔案

       Makefile 裡的函數跟它的變量很相似——使用的時候,你用一個$符号跟左圓括号,函數名,空格後跟一列由逗号分隔的參數,最後用右圓括号結束。例如,在 GNU Make裡有一個叫'wildcard' 的函數,它有一個參數,功能是展開成一列所有符合由其參數描述的檔案名,檔案間以空格間隔。像這個指令: 

objects= $(wildcard *.c)      

     會産生一個所有以'.c' 結尾的檔案清單(本例結果為a.c b.c),然後存入變量 objects裡。    

   另一個有用的函數是 patsubst ( patten substitude,比對替換的縮寫)函數。它需要3個參數——第一個是一個需要比對的式樣,第二個表示用什麼來替換它,第三個是一個需要處理由空格分隔的序列。我們将兩個函數合起來用:

objects := $(patsubst %.c,%.o,$(wildcard *.c))      

 會被處理為:

objects := a.o b.o

同理:

executables := $(patsubst %.c,%,$(wildcard *.c))      

 會被處理為:

executables := a b

%o:所有以“.o”結尾的目标,也就是a.o b.o

依賴模式“%.c”:取模式“%.o”的%,也就是foo bar,并為其加上.c字尾,即a.c,b.c

 $<:表示所有依賴目标集,也就是a.c b.c

$@:表示目标集,也就是a.o b.o

指令前加@,表示在終端中不列印,如@mkdir -p ./bin

$(objects) : %.o: %.c 
       $(CROSS_COMPILE)gcc -c $(CFLAGS) $< -o $@      

即可翻譯為:

a.o b.o : a.c b.c
       $(CROSS_COMPILE)gcc -c  $(CFLAGS)  (a.c b.c) -o (a.o b.o)      

明白了這些,這種Makefile的寫法就可以完全掌握了。

繼續閱讀