博主要建立一個工程目錄,但願將全部的.c文件都編譯成.o並存放到out/目錄下。以下:shell
. ├── d1 │ ├── aa.c │ └── dd.c ├── main.c ├── Makefile └── out
通過一夜的嘗試,最終使用了foreach函數實現了這個目標:數組
TARGET=test ALL_SOURCES=$(shell find -name "*.c") SOURCE_TO_OBJECT = ./out/$(subst .c,.o,$(notdir $(1))) ALL_OBJECTS=$(foreach src,$(ALL_SOURCES),$(call SOURCE_TO_OBJECT,$(src))) define CREATE_OBJECT_TARGET $(call SOURCE_TO_OBJECT,$(1)) : $(1) gcc -c -o $$@ $$^ endef all: $(TARGET) clean: -rm $(ALL_OBJECTS) -rm $(TARGET) $(TARGET):$(ALL_OBJECTS) gcc -o $@ $^ $(foreach src,$(ALL_SOURCES),$(eval $(call CREATE_OBJECT_TARGET,$(src))))
大概思路是這樣的:
首先,ALL_SOURCES=$(shell find -name "*.c")
,我將當前目錄下的全部.c文件找到並賦值給ALL_SOURCE變量。
而後,ALL_OBJECTS=$(foreach src,$(ALL_SOURCES),$(call SOURCE_TO_OBJECT,$(src)))
,對每一個一ALL_SOURCE
中的源文件進行處理,將每一個文件名去除路徑,並將後綴.c替換成.o,再加上./out前綴就成了目標文件名。注意:函數調用中不能隨意地加空格!!
SOURCE_TO_OBJECT
是一個將源文件名轉換成目標文件名的函數。上面用$(call ...)
對它進行調用。函數
而後,我想爲每一個目標文件創建依賴關係,以下:code
./obj/main.o : main.c gcc -c -o $@ $^ ./obj/aa.o : d1/aa.c gcc -c -o $@ $^ ./obj/bb.o : d1/bb.c gcc -c -o $@ $^
文件個數少還好說,若是工程大了,上百個文件維護起來很吃力。因而想到要用 $(foreach ...)
函數來實現。建立這麼一個函數,用於生成目標與文件依賴關係:ip
define CREATE_OBJECT_TARGET $(call SOURCE_TO_OBJECT,$(1)) : $(1) gcc -c -o $$@ $$^ endef
轉入的一個參數$(1)是源文件全路徑。
注意:其中的 gcc -c -o $$@ $$^
,是雙 $ 符號。字符串
再用以下的$(foreach ...)函數達到對每個源文件都創建一個目標的目的:
$(foreach src,$(ALL_SOURCES),$(eval $(call CREATE_OBJECT_TARGET,$(src))))
編譯
其中用到的命令有:test
其它經常使用的函數還有:變量
若是你們還有別的什麼更好的方法,歡迎留言。gcc