makefile中"模式規則"的引入和介紹------%:%.cpp


        目錄下有test1.cpp, test2.cpp, test3.cpp三個獨立文件(彼此之間並無依賴與調用關系), 要編譯成三個可執行程序, 怎么搞呢? 我們看看makefile:

 

[plain]  view plain  copy
 
  1. test1: test1.cpp  
  2. test2: test2.cpp  
  3. test3: test3.cpp  
  4. clean:  
  5.     rm -f test1 test2 test3  

       編譯一下:

 

 

[plain]  view plain  copy
 
  1. taoge@localhost Desktop>  make  
  2. g++     test1.cpp   -o test1  
  3. taoge@localhost Desktop>    

        可見, 只編譯了test1.cpp,  沒有達到效果。  為什么呢? 因為執行make命令時, 認為第一個test1是最終的目標文件, 且三個cpp文件確實相互獨立, 所以不會觸發test2和test3對應執行。

 

      

         那改一下:

 

[plain]  view plain  copy
 
  1. test1 test2 test3: test1.cpp test2.cpp test3.cpp  
  2. clean:  
  3.     rm -f test1 test2 test3  

        結果:

 

 

[plain]  view plain  copy
 
  1. taoge@localhost Desktop>  make  
  2. g++     test1.cpp test2.cpp test3.cpp   -o test1  
  3. /tmp/ccAX6NNB.o: In function `main':  
  4. test2.cpp:(.text+0x72): multiple definition of `main'  
  5. /tmp/ccaITY1Z.o:test1.cpp:(.text+0x72): first defined here  
  6. /tmp/cc4Wsk9m.o: In function `main':  
  7. test3.cpp:(.text+0x72): multiple definition of `main'  
  8. /tmp/ccaITY1Z.o:test1.cpp:(.text+0x72): first defined here  
  9. collect2: ld returned 1 exit status  
  10. make: *** [test1] Error 1  
  11. taoge@localhost Desktop>     

       顯然不行啊, 怎么能對三個獨立的cpp文件進行雜糅鏈接呢?

 

 

        那怎么辦?  我們反思一下上面的兩次失敗:

        在前一次中, 我們其實只定義了一個target文件(因cpp獨立), 也就是test1.

        在后一次中, 我們定義了三個target文件, 可是, 雜糅鏈接了(依賴關系雜糅)。

 

        那好, 我們來改進一下, 兼顧到上面兩種情況:

 

[plain]  view plain  copy
 
  1. all: test1 test2 test3  
  2. test1: test1.cpp  
  3. test2: test2.cpp  
  4. test3: test3.cpp  
  5. clean:  
  6.     rm -f test1 test2 test3  

        執行一下(如下用make命令也可以):

 

 

[plain]  view plain  copy
 
  1. taoge@localhost Desktop>  make clean  
  2. rm -f test1 test2 test3  
  3. taoge@localhost Desktop>  make all  
  4. g++ test1.cpp -o test1  
  5. g++ test2.cpp -o test2  
  6. g++ test3.cpp -o test3  
  7. taoge@localhost Desktop>  ls  
  8. makefile  test1  test1.cpp  test2  test2.cpp  test3  test3.cpp  
  9. taoge@localhost Desktop>    


        我們思考一下, 為什么這樣可以?  make命令首先找到all標志, 發現了必須要生成test1, test2, test3, 於是就往下找, 去生成他們, 於是就達到了我們的目標。

 

        這里有個疑問, 為什么沒有生成all文件呢? 因為all下面並沒有待執行的命令,也無法自動推導。  我們來看看改動的makefile:

 

[plain]  view plain  copy
 
  1. all: test1 test2 test3  
  2.     @echo testing  
  3. test1: test1.cpp  
  4. test2: test2.cpp  
  5. test3: test3.cpp  
  6. clean:  
  7.     rm -f test1 test2 test3  

          結果為(如下用make命令也可以):

 

 

[plain]  view plain  copy
 
  1. taoge@localhost Desktop>  make all  
  2. g++     test1.cpp   -o test1  
  3. g++     test2.cpp   -o test2  
  4. g++     test3.cpp   -o test3  
  5. testing  
  6. taoge@localhost Desktop>    

         可見, 如果all后有命令, 也會被執行哈。

 

 

         以上部分應該比較好動, 現在還有個問題, 如果有100個cpp文件, 那該怎么搞起呢? 寫到test100? 麻煩死了, 明顯不符合計算機的思維, 好, 那就搞個模式規則吧, 如下:

 

[plain]  view plain  copy
 
  1. all: test1 test2 test3  
  2. %:%.cpp  
  3.     g++ $< -o $@  
  4. clean:  
  5.     rm -f test1 test2 test3  

        結果(如下用make命令也可以):

 

 

[plain]  view plain  copy
 
  1. taoge@localhost Desktop>  make clean  
  2. rm -f test1 test2 test3  
  3. taoge@localhost Desktop>  make all  
  4. g++ test1.cpp -o test1  
  5. g++ test2.cpp -o test2  
  6. g++ test3.cpp -o test3  
  7. taoge@localhost Desktop>    

        %是通配的,看看如下這兩句:

 

 

[plain]  view plain  copy
 
  1. %:%.cpp  
  2.     g++ $< -o $@  

        意思是把所有的cpp文件, 都編譯成對應的最終文件。 無需都解釋了吧(當然, 你得了解$<和$@)。

 

 

        其實, 如上程序還沒有解決根本問題, 繼續優化吧:

 

[plain]  view plain  copy
 
  1. CPPLIST = $(wildcard *.cpp)    # get cpp file list  
  2. TARGET = $(patsubst %.cpp, %, $(CPPLIST)) # get corresponding target file  
  3.   
  4. all: $(TARGET)  
  5.     @echo ------------------  
  6.     @echo log1: $(TARGET)  
  7.     @echo log2: $(CPPLIST)  
  8.   
  9. %:%.cpp  
  10.     g++ $< -o $@  
  11.       
  12. clean:  
  13.     rm -f $(TARGET)  

         看下結果(如下用make命令也可以):

 

 

[plain]  view plain  copy
 
  1. taoge@localhost Desktop>  make clean  
  2. rm -f  test1  test2  test3   
  3. taoge@localhost Desktop>  make all  
  4. g++ test1.cpp -o test1  
  5. g++ test2.cpp -o test2  
  6. g++ test3.cpp -o test3  
  7. ------------------------  
  8. log1: test1 test2 test3  
  9. log2: test1.cpp test2.cpp test3.cpp  
  10. taoge@localhost Desktop>    

        搞定。

 

 

        本文所謂的模式規則, 其實就是:

 

[plain]  view plain  copy
 
  1. %:%.cpp  
  2.     g++ $< -o $@  

       其實, 這個還是很好理解的。 

 

       最后想說一下, 有點循環的感覺啊!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM