目錄下有test1.cpp, test2.cpp, test3.cpp三個獨立文件(彼此之間並無依賴與調用關系), 要編譯成三個可執行程序, 怎么搞呢? 我們看看makefile:
- test1: test1.cpp
- test2: test2.cpp
- test3: test3.cpp
- clean:
- rm -f test1 test2 test3
編譯一下:
- taoge@localhost Desktop> make
- g++ test1.cpp -o test1
- taoge@localhost Desktop>
可見, 只編譯了test1.cpp, 沒有達到效果。 為什么呢? 因為執行make命令時, 認為第一個test1是最終的目標文件, 且三個cpp文件確實相互獨立, 所以不會觸發test2和test3對應執行。
那改一下:
- test1 test2 test3: test1.cpp test2.cpp test3.cpp
- clean:
- rm -f test1 test2 test3
結果:
- taoge@localhost Desktop> make
- g++ test1.cpp test2.cpp test3.cpp -o test1
- /tmp/ccAX6NNB.o: In function `main':
- test2.cpp:(.text+0x72): multiple definition of `main'
- /tmp/ccaITY1Z.o:test1.cpp:(.text+0x72): first defined here
- /tmp/cc4Wsk9m.o: In function `main':
- test3.cpp:(.text+0x72): multiple definition of `main'
- /tmp/ccaITY1Z.o:test1.cpp:(.text+0x72): first defined here
- collect2: ld returned 1 exit status
- make: *** [test1] Error 1
- taoge@localhost Desktop>
顯然不行啊, 怎么能對三個獨立的cpp文件進行雜糅鏈接呢?
那怎么辦? 我們反思一下上面的兩次失敗:
在前一次中, 我們其實只定義了一個target文件(因cpp獨立), 也就是test1.
在后一次中, 我們定義了三個target文件, 可是, 雜糅鏈接了(依賴關系雜糅)。
那好, 我們來改進一下, 兼顧到上面兩種情況:
- all: test1 test2 test3
- test1: test1.cpp
- test2: test2.cpp
- test3: test3.cpp
- clean:
- rm -f test1 test2 test3
執行一下(如下用make命令也可以):
- taoge@localhost Desktop> make clean
- rm -f test1 test2 test3
- taoge@localhost Desktop> make all
- g++ test1.cpp -o test1
- g++ test2.cpp -o test2
- g++ test3.cpp -o test3
- taoge@localhost Desktop> ls
- makefile test1 test1.cpp test2 test2.cpp test3 test3.cpp
- taoge@localhost Desktop>
我們思考一下, 為什么這樣可以? make命令首先找到all標志, 發現了必須要生成test1, test2, test3, 於是就往下找, 去生成他們, 於是就達到了我們的目標。
這里有個疑問, 為什么沒有生成all文件呢? 因為all下面並沒有待執行的命令,也無法自動推導。 我們來看看改動的makefile:
- all: test1 test2 test3
- @echo testing
- test1: test1.cpp
- test2: test2.cpp
- test3: test3.cpp
- clean:
- rm -f test1 test2 test3
結果為(如下用make命令也可以):
- taoge@localhost Desktop> make all
- g++ test1.cpp -o test1
- g++ test2.cpp -o test2
- g++ test3.cpp -o test3
- testing
- taoge@localhost Desktop>
可見, 如果all后有命令, 也會被執行哈。
以上部分應該比較好動, 現在還有個問題, 如果有100個cpp文件, 那該怎么搞起呢? 寫到test100? 麻煩死了, 明顯不符合計算機的思維, 好, 那就搞個模式規則吧, 如下:
- all: test1 test2 test3
- %:%.cpp
- g++ $< -o $@
- clean:
- rm -f test1 test2 test3
結果(如下用make命令也可以):
- taoge@localhost Desktop> make clean
- rm -f test1 test2 test3
- taoge@localhost Desktop> make all
- g++ test1.cpp -o test1
- g++ test2.cpp -o test2
- g++ test3.cpp -o test3
- taoge@localhost Desktop>
%是通配的,看看如下這兩句:
- %:%.cpp
- g++ $< -o $@
意思是把所有的cpp文件, 都編譯成對應的最終文件。 無需都解釋了吧(當然, 你得了解$<和$@)。
其實, 如上程序還沒有解決根本問題, 繼續優化吧:
- CPPLIST = $(wildcard *.cpp) # get cpp file list
- TARGET = $(patsubst %.cpp, %, $(CPPLIST)) # get corresponding target file
- all: $(TARGET)
- @echo ------------------
- @echo log1: $(TARGET)
- @echo log2: $(CPPLIST)
- %:%.cpp
- g++ $< -o $@
- clean:
- rm -f $(TARGET)
看下結果(如下用make命令也可以):
- taoge@localhost Desktop> make clean
- rm -f test1 test2 test3
- taoge@localhost Desktop> make all
- g++ test1.cpp -o test1
- g++ test2.cpp -o test2
- g++ test3.cpp -o test3
- ------------------------
- log1: test1 test2 test3
- log2: test1.cpp test2.cpp test3.cpp
- taoge@localhost Desktop>
搞定。
本文所謂的模式規則, 其實就是:
- %:%.cpp
- g++ $< -o $@
其實, 這個還是很好理解的。
最后想說一下, 有點循環的感覺啊!