Linux Makefile文件編寫詳細步驟與實踐

Linux Makefile文件編寫詳細步驟與實踐

  

1.makefile概述

    Windows環境下IDE會幫你完成makefile文件的編寫,但在UNIX環境下你就必須自己寫makefile了,會不會寫makefile,從一個側面說明了一個人是否具備完成大型工程的能力。因爲,makefile關係到了整個工程的編譯規則。一個工程中的源文件不計數,其按類型、功能、模塊分別放在若干個目錄中,makefile定義了一系列的規則來指定,哪些文件需要先編譯,哪些文件需要後編譯,哪些文件需要重新編譯,甚至於進行更復雜的功能操作,因爲makefile中也可以執行操作系統的命令。makefile帶來的好處就是一旦寫好,只需要一個make命令,整個工程完全自動編譯,極大的提高了軟件開發的效率。make是一個命令工具,是一個解釋makefile中指令的命令工具。

2.makefile文件的基本結構

  1.需要由make工具創建的目標體,一般是目標文件或可執行文件,也可以是一個標籤,對於標籤這種特性,在後續的“僞目標”章節中會有敘述。
  2.目標文件或可執行文件所依賴的文件。
  3.創建每個目標體時所需要執行的命令,這一行必須以製表符(tab)開頭。
  target ... : prerequisites ...
  command
  ...
  ...

3.makefile變量

    變量是在makefile中定義的名字,用來代表一個文本字符串,該文本字符串稱爲該變量的值,引用時用$引用。
兩種變量定義形式:
1.遞歸定義展開方式:VAR=var,在引用該變量的時候進行替換,如果該變量中包含了對其他變量的引用,則在引用該變量的時候一次性將內嵌的變量全部展開。
2.簡單擴展方式:VAR:=var,在定義處展開,只展開一次,不包含對其他變量的引用,消除了嵌套引用。
重新編寫例程可以爲:
OBJS=talent.o hardwork.o
CC=gcc
CFLAGS=-Wall -O -g
success:$(OBJS)
        $(CC) $(CFLAGS) $^ -o success
talent.o:talent.c talent.h
        $(CC) $(CFLAGS) $^ -o talent.o
hardwork.o:hardwork.c hardwork.h
        $(CC) $(CFLAGS) $^ -o hardwork.o

說幾個makefile中幾個常見的預定義變量及其默認值:
  CC:C編譯器的名稱,默認cc;
  CFLAGS :C編譯器的選項,無默認值;
  CXXFLAGS:C++編譯器的選項,無默認值;
makefile中幾個常見的自動變量:
  $<:第一個依賴文件的名稱;
  $^:所有不重複的依賴文件,以空格分開;
  $@:目標文件的完整名稱;
  $?:所有時間戳比目標文件新的依賴文件,並以空格分開;
  當然還有幾個就不介紹啦!

   

4.一個簡單的makefile

   
  1. /*add.c*/  
  2. int add(int a,int b)  
  3. {  
  4.         return (a+b);  
  5. }  
  1. /*sub.c*/  
  2. int sub(int a,int b)  
  3. {  
  4.         return (a-b);  
  5. }  

  1. /*div.c*/  
  2. int div(int a,int b)  
  3. {  
  4.         return (a/b);  
  5. }  
  1. /*mul.c*/  
  2. int mul(int a,int b)  
  3. {  
  4.         return (a*b);  
  5. }  
  1. #include <stdio.h>  
  2. /*func_point.c*/  
  3. int process(int (*math_p)(int,int),int x,int y);  
  4. extern int add(int,int);  
  5. extern int sub(int,int);  
  6. extern int mul(int,int);  
  7. extern int div(int,int);  
  8.   
  9.   
  10. int main(void)  
  11. {  
  12.     int a=8,b=2;  
  13.   
  14.   
  15.       
  16.     printf("add(8,2)=%d\n",process(add,a,b));  
  17.         printf("sub(8,2)=%d\n",process(sub,a,b));  
  18.         printf("mul(8,2)=%d\n",process(mul,a,b));  
  19.         printf("div(8,2)=%d\n",process(div,a,b));  
  20.   
  21.   
  22.     return 0;  
  23. }  
  24. int process(int (*math_p)(int x,int y),int x,int y)  
  25. {  
  26.     return(math_p(x,y));  
  27. }  
  1. #makefile  
  2. func_point:func_point.o add.o sub.o mul.o div.o  
  3.         gcc func_point.o add.o sub.o mul.o div.o -o func_point  
  4. add.o:add.c  
  5.         gcc -c add.c  
  6. sub.o:sub.c  
  7.         gcc -c sub.c  
  8. div.o:div.c  
  9.         gcc -c div.c  
  10. mul.o:mul.c  
  11.         gcc -c mul.c  
  12. func_point.o:func_point.c  
  13.         gcc -c func_point.c  
         執行make命令的時候,找到缺省的target,即func_point。func_point之後是它的prerequisites文件,首先找到func_point.o這個文件,但這個文件又是後續的target文件,再找到func_point.o目標的prerequisites文件。然後執行func_point.o目標文件下的command,command執行完畢返回上級;找到add.o這個文件,add.o又是後續的目標文件,然後找到add.o目標文件的prerequisites文件,然後執行add.o目標文件的command,執行完畢...依次遞歸...最後執行func_point目標文件的command。到此爲止,這個文件就編譯完成了。#後面表示註釋。
   讀者仔細觀察,所有的target文件都要比prerequisites文件新。add.o、sub.o、mul.o、div.o比這些文件的prerequisites文件新。如果有任意一個prerequisites文件比target文件新,那target所對應的command就被執行。這就是Makefile的規則,也是Makefile的核心內容。
   通常Makefile有一個clean目標,用於清除編譯過程中產生的中間文件,保留源代碼。現在將目標clean加入到我們的Makefile中。
  1. #makefile  
  2. func_point:func_point.o add.o sub.o mul.o div.o  
  3.         gcc func_point.o add.o sub.o mul.o div.o -o func_point  
  4. add.o:add.c  
  5.         gcc -c add.c  
  6. sub.o:sub.c  
  7.         gcc -c sub.c  
  8. div.o:div.c  
  9.         gcc -c div.c  
  10. mul.o:mul.c  
  11.         gcc -c mul.c  
  12. func_point.o:func_point.c  
  13.         gcc -c func_point.c  
  14. clean:  
  15.         @echo "clean project"  
  16.         -rm *.o  
  17.         @echo "clean complete"  

    如果在make命令後邊跟一個target。那就從這個target開始,如果不指定,那就取默認的,就是第一個target。@符號屏蔽命令的顯示,只是將命令執行結果顯示到屏幕上。- 符號的意思是不管這條命令執行成功與否,都要繼續執行下邊的命令。clean目標比較特殊,沒有任何prerequisites文件,並且執行它的命令不會生成clean文件。再次次執行make clean,這時所有的目標文件已經清楚了,rm  *.o 這條命令會報錯,但是繼續執行後邊的echo命令。
   如果在當前工作路徑下有一個clean文件,我們makefile文件中的clean執行就會被忽略,在我們原來Makefile的最後一行加如下代碼就可以了:
  .PHONY:clean
    clean是一個約定俗稱的目標,像這樣的約定還有。
  all:通常爲缺省的目標,執行缺省的編譯工作。
  install:編譯後的安裝工作,將相應的文件拷貝到合適的位置。
  distclean:清除所有編譯中生成的文件,只保留源文件。
    好啦!下面我們對剛纔的makefile文件進行一下瘦身:
  1. #makefile  
  2. OBJ_FILE=func_point.o add.o sub.o div.o mul.o  
  3. func_point:$(OBJ_FILE)  
  4.         gcc $^ -o $@  
  5. clean:  
  6.         @echo "clean project"  
  7.         -rm *.o  
  8.         @echo "clean complete"  
  9. .PHONY:clean  

5.函數的使用

   在Makefile中可以使用函數來處理變量,從而讓我們的命令或是規則更爲的靈活和具有智能。make所支持的函數也不算很多,不過已經足夠我們的操作了。函數調用後,函數的返回值可以當做變量來使用。函數調用,很像變量的使用,也是以“$”來標識的,其語法如下:
  $(<function>; <arguments>;)或是${<function>; <arguments>;}
  這裏,<function>;就是函數名,make支持的函數不多。<arguments>;是函數的參數,參數間以逗號“,”分隔,而函數名和參數之間以“空格”分隔。函數調用以“$”開頭,以圓括號或花括號把函數名和參數括起。
   
  1. #makefile  
  2. SRC_FILE=$(wildcard *.c)  
  3. func_point:$(SRC_FILE)  
  4.         gcc $^ -o $@  
  5. clean:  
  6.         @echo "clean project"  
  7.         -rm *.o  
  8.         @echo "clean complete"  
  9. .PHONY:clean  
  1. /*wildcard是函數的名字,這是系統提供的函數,*.c 是函數的參數。這句話的意思是找出當前工作路徑下的所有的以.c結尾的源文件。然後將返回值初始化SRC_FILE變量。 
  2.    -n選項只打印要執行的命令,而不會真的執行命令,這個選項有助於我們檢查Makefile寫得是否正確,由於Makefile不是順序執行的,用這個選項可以先看看命令的執行順序,確認無誤了再真正執行命令。 
  3.    -C選項可以切換到另一個目錄執行那個目錄下的Makefile,比如先退到上一級目錄再執行我們的Makefile。 -C後邊跟那個目錄就行了。*/  

6.小項目實踐

   假設math目錄下有前面的add.c sub.c mul.c div.c源文件,與math同目錄下有func_point.c文件!
   math目錄下makefile文件如下:
  1. #Makefile  
  2. mymath:add.c sub.c div.c mul.c  
  3.         gcc -c -fPIC add.c sub.c div.c mul.c  
  4.         gcc -shared -o libmymath.so add.o sub.o mul.o div.o  
  5. #       gcc func_point.c -lmymath -o test  
  6. install:  
  7.         @sudo mv libmymath.so /usr/lib  
  8. #test:func_point.c  
  9. #       gcc func_point -lmymath  
  10.           
  11. clean:  
  12.         @echo "clean project"  
  13.         -rm *.o  
  14.         @echo "clean complete"  
  15. .PHONY:clean  

        與math同級目錄下makefile文件如下:
  1. all:  
  2.         make -C math  
  3.         make -C math install  
  4.         make -C math clean  
  5.         gcc func_point.c -Lmath -lmymath -o test  

           程序介紹:在math同級目錄下運行make命令時,它會把math目錄下的add.c sub.c mul.c div.c生成動態鏈接庫,並拷貝到/usr/lib中,後清除中間過程文件,在math同級目錄下可運行test可執行程序。
    如有錯誤,歡迎批評改正!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章