Linux Makefile由淺入深剖析

2021-09-06 05:41:53 字數 4195 閱讀 8544

經過長時間學習linux makefile,於是和大家分享一下,看完本文你肯定有不少收穫,希望本文能教會你更多東西。

假設我們有乙個程式由5個檔案組成,源**如下:

/*main.c*/

#include "mytool1.h"

#include "mytool2.h"

int main()

/*mytool1.c*/

#include "mytool1.h"

#include

void mytool1_print(char *print_str)

/*mytool1.h*/

#ifndef _mytool_1_h

#define _mytool_1_h

void mytool1_print(char *print_str);

#endif

/*mytool2.c*/

#include "mytool2.h"

#include

void mytool2_print(char *print_str)

/*mytool2.h*/

#ifndef _mytool_2_h

#define _mytool_2_h

void mytool2_print(char *print_str);

#endif

首先了解一下make和linux makefile。gnu make是乙個工程管理器,它可以管理較多的檔案。我所使用的redhat 9.0的make版本為gnu make version 3.79.1。使用make的最大好處就是實現了「自動化編譯」。如果有乙個上百個檔案的**構成的專案,其中乙個或者幾個檔案進行了修改,make就能夠自動識別更新了的檔案**,不需要輸入冗長的命令列就可以完成最後的編譯工作。make執行時,自動尋找makefile(makefile)檔案,然後執行編譯工作。所以我們需要編寫makefile檔案,這樣可以提高實際專案的工作效率。

在乙個linux makefile中通常包含下面內容:

1、需要由make工具建立的目標體(target),通常是目標檔案或可執行檔案。

2、要建立的目標體所依賴的檔案(dependency_file)。

3、建立每個目標體時需要執行的命令(command)。

格式如下:

target:dependency_files

command

target:規則的目標。通常是程式中間或者最後需要生成的檔名,可以是.o檔案、也可以是最後的可執行程式的檔名。另外,目標也可以是乙個make執行的動作的名稱,如目標「clean」,這樣的目標稱為「偽目標」。dependency_files:規則的依賴。生成規則目標所需要的檔名列表。通常乙個目標依賴於乙個或者多個檔案。

command:規則的命令列。是make程式所有執行的動作(任意的shell命令或者可在shell下執行的程式)乙個規則可以有多個命令列,每一條命令佔一行。注意:每乙個命令列必須以[tab]字元開始,[tab]字元告訴make此行是乙個命令列。make按照命令完成相應的動作。這也是書寫makefile中容易產生,而且比較隱蔽的錯誤。命令就是在任何乙個目標的依賴檔案發生變化後重建目標的動作描述。乙個目標可以沒有依賴而只有動作(指定的命令)。比如makefile中的目標「clean」,此目標沒有依賴,只有命令。它所指定的命令用來刪除make過程產生的中間檔案(清理工作)。

在makefile中「規則」就是描述在什麼情況下、如何重建規則的目標檔案,通常規則中包括了目標的依賴關係(目標的依賴檔案)和重建目標的命令。make執行重建目標的命令,來建立或者重建規則的目標(此目標檔案也可以是觸發這個規則的上乙個規則中的依賴檔案)。規則包含了目標和依賴的關係以及更新目標所要求的命令。

makefile中可以包含除規則以外的部分。乙個最簡單的makefile可能只包含規則描述。規則在有些makefile中可能看起來非常複雜,但是無論規則的書寫是多麼的複雜,它都符合規則的基本格式。

下面就可以寫出第乙個makefile了。

main:main.o mytool1.o mytool2.o

gcc -o main main.o mytool1.o mytool2.o

main.o:main.c mytool1.h mytool2.h

gcc -c main.c

mytool1.o:mytool1.c mytool1.h

gcc -c mytool1.c

mytool2.o:mytool2.c mytool2.h

gcc -c mytool2.c

clean:

rm -f *.o main

在shell提示符下輸入make,執行顯示:

gcc -c main.c

gcc -c mytool1.c

gcc -c mytool2.c

gcc -o main main.o mytool1.o mytool2.o

執行結果如下:

[armlinux@lqm makefile-easy]$ ./main

this is mytool1 print : hello mytool1!

this is mytool2 print : hello mytool2!

這只是最為初級的makefile,現在來對這個makefile進行改進。

改進一:使用變數

一般在書寫makefile時,各部分變數引用的格式如下:

1. make變數(mak1. make變數(makefile中定義的或者是make的環境變數)的引用使用「$(var)」格式,無論「var」是單字元變數名還是多字元變數名。

2. 出現在規則命令列中shell變數(一般為執行命令過程中的臨時變數,它不屬於makefile變數,而是乙個shell變數)引用使用shell的「$tmp」格式。

3. 對出現在命令列中的make變數同樣使用「$(cmdvar)」 格式來引用。

obj=main.o mytool1.o mytool2.o

make:$(obj)

gcc -o main $(obj)

main.o:main.c mytool1.h mytool2.h

gcc -c main.c

mytool1.o:mytool1.c mytool1.h

gcc -c mytool1.c

mytool2.o:mytool2.c mytool2.h

gcc -c mytool2.c

clean:

rm -f main $(obj)

改進二:使用自動推導

讓make自動推導,只要make看到乙個.o檔案,它就會自動的把對應的.c檔案加到依賴檔案中,並且gcc -c .c也會被推導出來,所以makefile就簡化了。

cc = gcc

obj = main.o mytool1.o mytool2.o

make: $(obj)

$(cc) -o main $(obj)

main.o: mytool1.h mytool2.h

mytool1.o: mytool1.h

mytool2.o: mytool2.h

.phony: clean

clean:

rm -f main $(obj)

改進三:自動變數($^ $< $@)的應用

makefile 有三個非常有用的變數,分別是$@、$^、$<。代表的意義分別是:

$@--目標檔案,

$^--所有的依賴檔案,

$<--第乙個依賴檔案。

cc = gcc

obj = main.o mytool1.o mytool2.o

main: $(obj)

$(cc) -o $@ $^

main.o: main.c mytool1.h mytool2.h

$(cc) -c $<

mytool1.o: mytool1.c mytool1.h

$(cc) -c $<

mytool2.o: mytool2.c mytool2.h

$(cc) -c $<

.phony: clean

clean:

rm -f main $(obj)

這些是最為初級的知識,現在至少可以減少編譯時的工作量。細節方面的東西還需要在以後的工作和學習中不斷的總結,不斷的深化理解。可以 參考gnu make手冊,這裡講解的比較全面。

linux makefile檔案分析

cflags wall wstrict prototypes g fomit frame pointer ffreestanding all crt0.s leds.c arm linux gcc cflags c o crt0.o crt0.s arm linux gcc cflags c o l...

Linux Makefile簡單介紹

c exe linux 中 編譯器 gcc和g 預處理 e 彙編 s 編譯 c 鏈結 o hello gcc e hello.c o hello.i hello ls hello.c hello.i 來看一下hello.i的內容 巨集定義在與處理的時候就展開了 hello gcc s hello.i...

由淺而深入 氣泡排序

三 剖析氣泡排序 高階 四 成本 關於各種排序 詳情 1.起源 氣泡排序,冒泡,冒泡,顧名思義越大的元素會經由交換慢慢 浮 到數列的頂端 公升序或降序排列 就如同碳酸飲料中二氧化碳的氣泡最終會上浮到頂端一樣,故名 氣泡排序 2.原理 原理很重要,原理沒動何談實現 比較相鄰的元素。如果第乙個比第二個大...