乙個通用的makefile詳解

2021-08-21 04:48:07 字數 3875 閱讀 5076

一般整個工程的makefile分為3類:

1. 頂層目錄的makefile

2. 頂層目錄的makefile.build

3. 各級子目錄的makefile

(1)頂層目錄的makefile:

它除了定義obj-y來指定根目錄下要編程序式去的檔案、子目錄外,主要是定義工具鏈、編譯引數、鏈結引數──就是檔案中用export匯出的各變數。

部分示例**如下:

# 編譯器在編譯時的一些通用引數設定

cflags := -wall -o2 -g -ddebug

# 新增標頭檔案路徑,不新增的話include目錄下的標頭檔案編譯時找不到

cflags += -i $(shell pwd)/include -i/opt/libdecode/include

# 鏈結器的鏈結引數設定

ldflags := -ljpeg -lz -lpng -l/opt/libdecode/lib

export cflags ldflags            

(2)頂層目錄的makefile.build:

這是最複雜的部分,它的功能就是把某個目錄及它的所有子目錄中、需要編程序式去的檔案都編譯出來,打包為built-in.o

部分示例**如下:

all: 

make -c ./ -f $(topdir)/makefile.build

$(cc) $(ldflags) -o $(target) built-in.o

(3)各級子目錄的makefile:

它最簡單,形式如下:

obj-y += file.o

obj-y += subdir/

"obj-y += file.o"表示把當前目錄下的file.c編程序式裡,

"obj-y += subdir/"表示要進入subdir這個子目錄下去尋找檔案來編程序式裡,是哪些檔案由subdir目錄下的makefile決定。

注意: "subdir/"中的斜槓"/"不可省略

(4)怎麼使用這套makefile:

1.把頂層makefile, makefile.build放入程式的頂層目錄

2.修改頂層makefile

2.1 修改工具鏈

2.2 修改編譯選項、鏈結選項

2.3 修改obj-y決定頂層目錄下哪些檔案、哪些子目錄被編程序式

2.4 修改target,這是用來指定編譯出來的程式的名字

3. 在各乙個子目錄下都建乙個makefile,形式為:

obj-y += file1.o

obj-y += file2.o

obj-y += subdir1/

obj-y += subdir2/

(1)偽目標不是為了得到某個檔案或東西,而是單純為了執行這個目標下面的命令。

(2)偽目標一般都沒有依賴

(3)但是有時候為了明確宣告這個目標是偽目標會在偽目標的前面用.phony來明確宣告它是偽目標。  

示例**如下:   可以在cp上一行加上 .phony:clean all cp

標明下,更清楚

cp:cp ../testproject/ /root/rootfs/ -rf

clean:

rm -f $(shell find -name "*.o")

rm -f $(target)

(1)建立上層目錄

比如當然 /root 目錄下沒有任何目錄

mkdir -p /root/test/test

這樣就在 /root 目錄下建立了 test 目錄 ,並在 /root/test目錄下還建立了 /root/test/test 目錄

(1)= 最簡單的賦值

用=賦值的變數,在被解析時他的值取決於最後一次賦值時的值,所以看變數引用的值時不能只往前面看,還要往後面看。

(2):= 一般也是賦值

用:=來賦值的,則是就地直接解析,只用往前看即可。

(3)?= 如果變數前面並沒有賦值過則執行這條賦值,如果前面已經賦值過了則本行被忽略。

(4)+=  用來給乙個已經賦值的變數接續賦值,意思就是把這次的值加到原來的值的後面。(在shell makefile等檔案中,可以認為所有變數都是字串,+=就相當於給字串stcat接續內容)(注意乙個細節,+=續接的內容和原來的內容之間會自動加乙個空格隔開)

(5)* 若干個任意字元

(6)? 1個任意字元

(7)[ ] 將中的字元依次去和外面的結合匹配

(8)$(src:%.c=%.o)     將src變數中所有以.c結尾的檔名替換成對應的以.o結尾的檔名,然後賦回給src

(9)一般我們可以使用「$(wildcard *.c)」來獲取工作目錄下的所有的.c檔案列表

(1)常見自動變數:

$@ 規則的目標檔名

$< 規則的依賴檔名

$^ 依賴的檔案集合

cross_compile = /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-

as            = $(cross_compile)as

ld            = $(cross_compile)ld

cc            = $(cross_compile)gcc

cpp            = $(cc) -e

ar            = $(cross_compile)ar

nm            = $(cross_compile)nm

strip        = $(cross_compile)strip

objcopy        = $(cross_compile)objcopy

objdump        = $(cross_compile)objdump

# export匯出的變數是給子目錄下的makefile使用的

export as ld cc cpp ar nm strip objcopy objdump

# 編譯器在編譯時的引數設定 (比如列印出所有警告、除錯資訊)

cflags := -wall -o2 -g -ddebug

# 新增標頭檔案路徑,不新增的話include目錄下的標頭檔案編譯時找不到

cflags += -i $(shell pwd)/include 

# 鏈結器的鏈結引數設定

ldflags :=

export cflags ldflags

topdir := $(shell pwd)

export topdir

# 定義將來編譯生成的可執行程式的名字

target := imageplayer

# 新增專案中所有用到的原始檔,有頂層目錄下的.c檔案,和子資料夾

# 新增頂層目錄下的.c檔案

obj-y += main.o

# 新增頂層目錄下的子資料夾(注意目錄名後面加乙個/)

obj-y += display/

all: 

make -c ./ -f $(topdir)/makefile.build

$(cc) $(ldflags) -o $(target) built-in.o

cp:             

(../ 當前目錄是在makeflie裡面,需要../才能進入與makefile同級的目錄下)

cp ../lbwproject /root/porting_x210/rootfs/rootfs/ -rf

clean:

rm -f $(shell find -name "*.o")

rm -f $(target)

distclean:

rm -f $(shell find -name "*.o")

rm -f $(shell find -name "*.d")

rm -f $(target)

乙個通用的makefile(一)

最近在編寫android編譯系統時,需要遍歷每乙個目錄下每乙個資料夾下的makefile,網上的方法有些繁瑣 就直接貼上自己遍歷子目錄深度為1 for temporary 之後會繼續更新 下面是我的乙個簡單例項工程 資料夾目錄層次 獲取當前目錄下的子目錄名字 2 subdir shell ls l ...

乙個通用Makefile的編寫

我們在linux環境下開發程式,少不了要自己編寫makefile,乙個稍微大一些的工程下面都會包含很多.c的原始檔。如果我們用gcc去乙個乙個編譯每乙個原始檔的話,效率會低很多,但是如果我們可以寫乙個makefile,那麼只需要執行乙個make就ok了,這樣大大提高了開發效率。但是makefile的...

編寫乙個簡單通用的makefile

author 李超 date 2012 05 06 縱然makefile 的規則還是相當多的,編寫乙個大規模的軟體,良好的 makefile 架構是方便維護程式編譯的關鍵。學習 makefile 的時間週期還是比較長的,為了寫出規範的 需要在很短的時間內編寫乙個 makefile 這裡給給出乙個 m...