makefile入門

什麼是makefile ?

在一個項目中,會有大量的 .c 文件,.h文件.讓我們手動的編譯不僅麻煩,而且效率低.
makefile定義了一系列的規則來指定哪些文件需要先編譯,哪些文件需要後編譯,哪些文件需要重新編譯.
然後使用 make 工具,用來解釋makefile 中的規則.

現在有 3 個文件,分別是 main.c ,hello.h ,hello.c

main.c

#include<stdio.h>                                                                                                                                             
#include"hello.h"

int main()
{
        hello();
        return 0;
}

hello.h

void hello(void);

hello.c

#include"hello.h"
#include<stdio.h>

void hello(void)
{
	printf("hello world\n");
}

最直接的編譯方式: gcc main.c hello.c

使用 makefile 時,要在 makeflie(Makefile) 文件中編寫.

makefile 的 編寫由易到難.

makefile 的基本單元是規則.
一個規則的格式如下:
目標文件列表 分隔符 依賴文件列表 [; 命令]
(table)[命令]

最簡單的makefile就生成了

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

makefile解析:
main 爲 目標文件, : 爲分隔符,main.o 和 hello.o 爲 依賴文件
第二行 則爲一個命令

這個簡單的 makefile 解決了麻煩這個問題 ,但沒有解決 低效 的 問題.因爲每一次都要編譯 main.o,hello.o. 即使沒有改變hello.o.

main: main.o hello.o
        gcc  main.o hello.o -o main

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

hello.o:hello.c
        gcc -c hello.c

爲什麼說它能解決低效呢 ?

makefile 每次只執行一個目標文件,即 第一個 目標文件.然後檢查這個規則是否存在依賴,如果依賴存在,則執行命令,若依賴不存在則向下查找依賴.
找到依賴後 首先判斷是否要更新, 如果依賴的時間 比 目標時間 晚,則說明 依賴文件在 目標文件後修改過,需要更新,否則就跳過.所以提高了效率.

makefile 解析:
爲了生成main ,則需要main.o,hello.o ,向下查找,首先找到 main.o ,對比時間,判斷是否更新,然後查找第二個依賴並判斷,
如果所有依賴都檢查完畢,則執行 第一個規則中的命令.

但是,這又引出了一個問題,如果要修改一個makefile 的中使用的 編譯器,原來爲 gcc ,想變爲 g++,這時候,就要一個個 的修改.
爲了解決這個問題, 就引入了 變量.修改時,只要修改 變量就行了.
除此之外,makefile 中還定義了一組變量,它們的值在make 運行過程中可以動態的改變,稱爲 自動變量
例:

  1. $@: 表示規則中的目標文件名
  2. $<: 表示規則中的第一個依賴文件名
  3. $?: 所有比目標文件新的依賴文件列表
  4. $^: 表示規則中的所有依賴

還有一個 : makefile 中的匹配符 %

obj = main.o hello.o
CC = gcc 
target = main

$(target): $(obj)
        gcc $(obj) -o $(target)

%.o:%.c                                                                                                                                                       
        gcc -c $< -o $@

這次的makefile 使用了 變量替換,和自動變量,還有一個 匹配符 %

解釋一下 :

%.o:%.c

在這個makefile 中 相當於

main.o : main.c
hello.o : hello.c

makefile 的解析:

前三行就是簡單的變量替換, 在makefile 中 ,用 $() 對變量的引用. 可以將 變量替換 看成 字符串 替換.

第二個規則的命令中, 每次在 第一個規則中 檢查一個依賴, 就到第二個 規則中執行.
相當於 :

檢查 main.o 依賴時 , 第二個規則 執行

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

檢查 hello.o 依賴時,第二個規則執行

hello.o : hello.c 
	gcc -c hello.c -o hello.o

當然也可以將 第一個規則 命令 中的 變量 用自動變量替換

obj = main.o hello.o
CC = gcc 
target = main

$(target): $(obj)
        gcc $^ -o $@

%.o:%.c                                                                                                                                                       
        gcc -c $< -o $@

此時 你會發現多了 hello.o,main.o文件, 想一哈,如果 有特別多的 文件,就會生成 特別多的 .o文件,而且還可能會在不同的目錄裏,
這時,刪除他們可不是一個容易的事清.
但我們可以 用makefile 刪除

obj = main.o hello.o
CC = gcc 
target = main
                                                                                
$(target): $(obj)
        gcc $^ -o $@

%.o:%.c
        gcc -c $< -o $@
clean:
        rm *.o $(target)

上面提到過,makefile 只執行第一個 目標文件,其餘的是不執行的. 這時,我們只能通過自己指定 執行哪一個目標文件.

make clean

它就會執行 clean 這個規則;

除此之外,makefile 中也帶有函數.(過幾天 在補更)

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