1. 程式人生 > 其它 >Linux系統程式設計(四)Makefile編寫

Linux系統程式設計(四)Makefile編寫

技術標籤:Linux環境程式設計makefilelinux

Linux系統程式設計(四)Makefile編寫

4.1 Makefile 檔案介紹

  在Winows 下,一般使用Visual Studio 進行編譯除錯,而在 LinuxC++ 工程中,編譯器一般使用 makefile 來編譯,如 Netbeans 編譯器。所以在 Linux 開發時,不可避免會對工程檔案的 Makefile 檔案進行修改,本文介紹 Makefile

的用法,學會使用並編寫Makefile 檔案。
  在大型工程中,檔案會根據其型別、實現功能、實現模組的不同放在不同的目錄中,Makefile 檔案可以指定哪些檔案需要先編譯,也可執行 shell 命令。其優勢為 自動化編譯 ,使得整個工程自動編譯,提高開發效率。

4.2 Makefile 命名與規則

  Makefile 檔案一般命名為 makefile 或者 Makefile。編寫規則如下

target ... : dependence ... 
	shell command
	...
  • 目標(target):編譯目標,最終要生成的檔案
  • 依賴(dependence):所需要的依賴目標,生成目標所需的檔案或目標
  • 命令(command):shell命令,通過執行命令對依賴操作生成目標(命令前必須有 tab

下面舉個栗子,編寫 Makefile 編譯運算庫工程。

準備工作:Linux系統程式設計(三)靜態庫與動態庫製作與使用 3.2 運算庫靜態庫例項
6個原始檔add.csub.cmult.cdiv.chead.hmain.c

開始編寫Makefile的 第一個版本, 檔案如下

app: main.c add.c sub.c mult.c div.c
        gcc main.c add.c sub.c mult.c div.c -o app

執行 make 命令,make 會執行我們編寫好的 gcc

命令,生成可執行檔案 app
編譯結果

4.3 Makefile 工作原理

   下面簡單分析下 Makefile 檔案的工作原理,在編寫或者修改 Makefile 也能更清楚其編譯過程。
  規則一Makefile 執行時,首先會查詢依賴 是否存在,如果存在,則繼續執行命令。如果不存在,則向下檢查其他規則,檢視是否有其他規則來生成依賴,如果找到,則執行該規則中的命令。 如上面所寫的 Makefile 版本一,首先檢查.c 檔案是否存在,如果存在,則執行 gcc 命令。

下面在改寫下之前的Makefile 檔案,更清楚看出依賴關係。

app: main.o add.o sub.o mult.o div.o
        gcc main.o add.o sub.o mult.o div.o -o app

sub.o: sub.c
        gcc -c sub.c -o sub.o

add.o: add.c
        gcc -c add.c -o add.o

mult.o: mult.c
        gcc -c mult.c -o mult.o

div.o: div.c
        gcc -c div.c -o div.o

main.o: main.c
        gcc -c main.c -o main.o

使用make 來編譯檔案,得到 可執行檔案 app
makefile-2
  規則二Makefile 檔案會檢查更新。在執行依賴時,會比較目標與依賴檔案的時間。如果生成依賴的時間比目標檔案的時間晚,則需要重新生成目標。如果依賴的時間比目標早,則目標不需要更新,對應的規則不需要執行。

版本二與版本一相比,對於修改的檔案才進行重新編譯,減少編譯的時間。

4.4 Makefile 變數

  Makefile 中變數分為兩種:自定義變數,預定義變數。可以通過 $[變數名] 獲取變數值。

  • 自定義變數:變數名 = 變數值
  • 預定義變數:Makefile 定義的變數,可以直接使用。
    • AR:歸檔維護程式的名稱,預設值為 ar
    • CC:C編譯器的名稱,預設值為 cc
    • CXX:C++ 編譯器的名稱,預設值為 g++
    • [email protected]:目標的完整名稱
    • $<:第一個依賴檔案的名稱
    • $^:所有依賴檔案

下面修改 Makefile ,使用變數來編譯工程。

src=main.o add.o sub.o mult.o div.o
target=app

$(target):$(src)
        $(CC) $(src) -o $(target)

sub.o: sub.c
        gcc -c sub.c -o sub.o

add.o: add.c
        gcc -c add.c -o add.o

mult.o: mult.c
        gcc -c mult.c -o mult.o

div.o: div.c
        gcc -c div.c -o div.o

main.o: main.c
        gcc -c main.c -o main.o

4.5 模式匹配

   在 Makefile 中,使用模式匹配符% 進行匹配字串。修改Makefile 檔案得到版本三。

src=main.o add.o sub.o mult.o div.o
target=app

$(target):$(src)
        $(CC) $(src) -o $(target)

%.o: %.c
        $(CC) -c $< -o [email protected]

4.6 函式用法

下面介紹兩個常用的函式:

  1. $(wildcard PATTERN ...)
  • 功能:獲取指定目錄下的指定型別的檔案列表
  • 引數:
    • PATTERN :指多個或多個目錄下對應的某種型別的檔案,多個目錄用空格隔開
  • 返回值:得到若干個檔案的檔案列表,檔名之間用空格間隔
$(wildcard *.c ./sub/*.c)
  1. $(patsubst <pattern>, <replacement>, <text>)
  • 功能:查詢 text 中單詞是否符合模式 pattern ,如果匹配,以 replacement 替換
  • 引數:
    • <pattern> :可以包含萬用字元% ,表示任意長度字串
    • <replacement> :當包含萬用字元 % 時,代表<pattern>% 匹配的字元
  • 返回值:函式返回被替換後的字串

使用萬用字元模式匹配修改Makefile ,如下

src=$(wildcard ./*.c)
objs=$(patsubst %.c, %.o, $(src))

target=app

$(target):$(objs)
        $(CC) $(objs) -o $(target)

%.o: %.c
        $(CC) -c $< -o [email protected]

編譯結果與上面的版本相同,如下所示
變數

Makefile 中新增目標 clean ,刪除中間生成檔案

src=$(wildcard ./*.c)
objs=$(patsubst %.c, %.o, $(src))

target=app

$(target):$(objs)
        $(CC) $(objs) -o $(target)

%.o: %.c
        $(CC) -c $< -o [email protected]

clean: 
        rm -f $(objs)