我的Makefile:的Makefile:無法獲得基本名稱與patsubst工作
compiler=g++
cflags=-g -Wall -I.
src=$(shell find . -name *.cc) #find all .cc files, with path name
srcBaseName=$(shell basename -a $(src)) # extract base names by stripping off the path
header=$(shell find . -name *.h) # all header files
obj=$(patsubst %.cc, %.o, $(srcBaseName)) # Problematic line
bin=bin/myProgram
all: $(bin)
$(bin): $(obj)
$(compiler) $^ -o [email protected]
%.o: %.cc
$(compiler) $(cflags) -c $^ -o [email protected]
clean:
rm $(obj) $(bin)
導致以下錯誤:
make: *** No rule to make target 'SomeObjectFile.o', needed by 'bin/myProgram'. Stop.
問題的行:
obj=$(patsubst %.cc, %.o, $(srcBaseName))
如果我改變$(srcBaseName)爲$(src),然後一切都很好。但在這種情況下,.o文件將被分散到相應的.cc文件中,我不想要這些文件。
我想有一個專用的(obj /)文件夾來存儲所有的.o文件。
我該怎麼辦?
首先嚐試:
obj=$(patsubst %.cc, %.o, obj/$(srcBaseName))
第二個嘗試:
obj=$(patsubst %.cc, %.o, obj\/$(srcBaseName))
他們爲什麼不工作?
/**********************編輯於2015年2月16日****************** ****/
基於對答案的建議,我更新了我的Makefile是這樣的:
compiler=g++
# source compilation flags
cflag=-g -Wall -std=gnu++0x -I./header/
# source link flags
lflag=
# lib used by proj
lib=
tflag=-g -Wall -std=gnu++0x
# test link flags
tlflag=
# test libs
testLib=lib/libgtest.a
# source code
src=$(shell find "./src" -name "*.cc")
srcBaseName=$(shell basename -a $(src))
obj=$(addprefix obj/, $(patsubst %.cc, %.o, $(srcBaseName)))
vpath %.cc $(dir $(src))
# header files
header=$(shell find "./header" -name "*.h")
# test files
testSrc=$(shell find "./test" -name "*.cc")
testSrcBase=$(shell basename -a $(testSrc))
testObj=$(addprefix obj/, $(patsubst %.cc, %.o, $(testSrcBase)))
vpath %.cc $(dir $(testSrc))
# binary files
bin=bin/Driver
testBin=bin/Test
all: prog test
prog: $(bin)
$(bin): $(obj)
$(compiler) $(lflag) $^ $(lib) -o [email protected]
#$(obj): $(src) $(header)
obj/%.o: %.cc $(header)
$(compiler) $(cflag) -c $< -o [email protected]
test: $(testBin)
$(testBin): $(testObj)
$(compiler) $(tlflag) $^ $(testLib) -o [email protected]
obj/%.o: %.cc
$(compiler) $(tflag) -c $< -o [email protected]
clean:
rm $(obj) $(bin) $(testObj) $(testBin)
這裏的化妝背後的意圖:
化妝PROG:
make應找到./src目錄下的所有源文件(.cc),並使用相同的命令生成.o文件文件名在./obj目錄中,對子目錄的級別不敏感,這樣我就可以自由添加新的cc文件而無需更新Makefile。每個.o文件都依賴於相應的(只是具有相同名稱的文件,而不是全部).cc文件和所有頭文件(make不會自動知道cc文件包含哪些頭文件而不解析該文件;如果您有聰明的方法來實現這一點,請讓我知道!)。例如,./src/subdirectory1/sample1.cc應該生成./obj/sample1.o,./obj/sample1.o取決於./src/subdirectory1/sample1.cc + ./header/sample1.h +。 /header/sample2.h + ...
化妝測試:
它應該做類似的事情來測試源文件的文件夾./test,不同之處在於有沒有參與頭。如果這個細節有幫助,我使用Google測試。
然而,我的Makefile倒不以預期的方式工作,因爲它具有以下問題:
1,如果我跑make test
,配方$(compiler) $(tflag) -c $< -o [email protected]
不執行(tflag手段「測試編譯標誌」,這沒有-I./header/部分; cflag表示'源代碼編譯標誌',它有-I./header/部分)。相反,執行phony prog $(compiler) $(cflag) -c $< -o [email protected]
中的配方。這個觀察結果來自'-I./header/'出現的輸出。我猜這是因爲phony prog中的cflag模式規則會覆蓋虛假測試中的tflag嗎?我隱約記得讓挑選最好的匹配模式規則 - 兩者基本上是相同的(我有這樣的意圖,即在假冒僞劣被執行時,特定假冒模式下的模式規則應該被執行,這似乎不可行?),所以總會選擇第一個。這個結論通過交換Makefile中兩個模式規則的順序來驗證,並且這次tflag規則總是被選中。 所以一個自然而然的問題是,當手機執行時,如何在特定的假冒模式下執行模式規則?
2,假設在第一點做我想做的事情是不可行的,我開始考慮替代方案。我可以做些什麼:#$(obj): $(src) $(header)
,這樣我就可以擺脫模式規則來解決方式選擇模式規則。但是,這顯然不正確,因爲它說$(obj)中的每個.o文件都取決於所有src文件和所有頭文件。 這是一個正確的方向嗎?
非常感謝,期待您的迴音。
3個關鍵問題以粗體和斜體標出。
嗨,下坡來自這裏:謝謝你的回答。關於vpath指令: 1,是每個Makefile特有的vpath設置(也就是我在每個make上設置的路徑)還是系統中所有Makefiles共享的全局指令(例如,我的操作系統中的其他項目的Makefiles將會選擇它也是)? 2,我假設,爲了讓vpath被所有make命令看到(假設我以後決定除了make all之外還要爲子系統編寫其他構建目標),我需要用變量設置vpath像Makefile開頭的src/cflags,是嗎? – h9uest 2014-10-19 11:20:56
嗨,不客氣。 1.我非常肯定它對於特定的make調用是本地的,但我不知道如果在Makefile中調用另一個make會發生什麼。 2.不完全確定你的意思,但是,我通常將它設置在Makefile的開頭。 – downhillFromHere 2014-10-19 12:12:49
請注意,您不應該使用'vpath%.o'。 VPATH僅用於查找_source_文件(「make」不會自行構建但已經存在的文件)。它不會使用它來查找派生文件('make'構建的文件)。我應該說:它會在那個make中找到它們,但它不會工作,因爲你的makefile不會正常工作。 – MadScientist 2014-10-19 14:57:55