MakeFile基礎(chǔ)入門用法簡介

很久以前寫的一篇技術(shù)備忘了,隱約記得當(dāng)時(shí)是看了APUE 2nd Edition這本書后,下載的源碼在CentOS7以及MacOX10.X上都編譯不過。在解決編譯問題的同時(shí),被APUE源碼中的MakeFile中的天書給震驚后,學(xué)習(xí)了一些相關(guān)入門知識(shí)。并以看懂并向后來的好奇寶寶們解釋APUE的MakeFile含義作為小目標(biāo),記錄了這篇文章。

1. MakeFile的基礎(chǔ)格式

target...:prerequisites
    command
    ...

target 就是我們需要生成的目標(biāo)文件??梢允强蓤?zhí)行文件,也可以是object file中間文件,還可以是其他的標(biāo)簽
prerequisites 就是target所依賴的文件
command 就是生成target需要執(zhí)行的命令,特別注意的是所有的shell command都可以在這里執(zhí)行

下面就是一個(gè)最樸實(shí)的MakeFile文件,沒有使用任何技巧

all:foo
foo:hello.o world.o
    gcc -o foo hello.o world.o -I.
hello.o:hello.c hello.h world.h
    gcc -c hello.c
world.o:world.c world.h
    gcc -c world.c
clean:
    rm hello.o world.o

2. 隱晦(高級(jí))規(guī)則

我們可以給需要編譯的這些文件名稱用一個(gè)變量來代替,有點(diǎn)像常量的使用方法一樣
其實(shí)我們看到的那些開源代碼的Makefile用了很多隱晦規(guī)則
比如test.o一般來說對(duì)應(yīng)的源文件就是test.c,并且調(diào)用編譯器生成[.o]文件也是固定的。那么我們就不用像上面那樣這樣寫了,而是像下面一樣省略

objects=hello.o world.o
all:foo
foo:$(objects)
    gcc -o foo $(objects)
hello.o:hello.h world.h
world.o:world.h
.PHONY:clean
clean:
    rm $(objects)

注釋和shell腳本一樣用#號(hào),記得命令必須以tab開頭
命令前面加一個(gè)-減號(hào)是告訴make忽略這條命令可能引起的錯(cuò)誤
代表了$HOME目錄,fengzhao代表了某位

自動(dòng)化變量
$? 所有比target更新的prerequisites,以空格間隔,如下所示

print:*.c
    lpr -p $?

特別注意的是,make為變量賦值一個(gè)含有通配符的變量需要用上wildcard函數(shù),否則通配符就不會(huì)被解釋
objects=.o #objects真的就只是.o而已
objects:=$(wildcard *.o)#objects會(huì)用通配符去展開這個(gè)變量得到當(dāng)前目錄下面的中間文件
:= 和 = 的區(qū)別是

A=$(B)
B=hello.c world.c#上一行還沒有定義B,但是用=已經(jīng)可以引用到后面定義的B,然后給A賦值

B:=hello.c world.c
A:=$(B)#用:=進(jìn)行必須引用已經(jīng)定義了的變量

==?=== 的意思是 hello?=world 如果hello沒有定義的話,它就等于world。如果定義了的,那么什么都不做

3. 多個(gè)target的語法

target可以是多個(gè)
靜態(tài)模式的形式如下

target:target-pattern:prereq-pattern
    command
    ...

舉個(gè)例子來說明

objects=hello.o world.o
$(objects):%.o:%.c
    $(CC) -c $(CFLAGS) $< -o $@

第二行的意思就是目標(biāo)是objects里面那些[.o]文件,把xxx.o中的xxx取出來,找到的xxx.c就是其依賴的文件

==$<== 表示的 prereq-pattern 指代的文件,在這里就是 hello.c world.c
==$@== 表示的 target 指代的文件,在這里就是 hello.o world.o
再看一個(gè)加入了filter函數(shù)的例子

objects=hello.o foo.elc world.o
$(filter %.o, $(objects)):%.o:%.c
    $(CC) -c $(CFLAGS) $< -o $@
$(filter %.elc, $(objects)):%.elc:%el
    emacs -f batch-byte-compile $<

這里的filter就是一個(gè)make build-in函數(shù)。函數(shù)名和參數(shù)用空格分隔,參數(shù)之間用,分隔

source=hello.c world.c
include ($source:.c=.d)

這個(gè)語法的意思是用.d來替換source中的.c(.c必須是結(jié)尾處的),然后形成新的新的集合

source=hello.c world.c
include ($source:%.c=%.d)

該語法的效果同上,只不過用的是靜態(tài)規(guī)則

在命了前面加上 @ 可以讓命令不顯示出來
如果要執(zhí)行多條(行)命令,且后面的命令依賴前面的命令,需要在命令之間加上 ; 號(hào),并且寫在一行
==$^== 表示 prereq 指代的文件集合并且去重
==$*== 表示模式 % 符號(hào)前面的部分

x=var1
var2=Hello
y=$(subst,1,2,$(x))

這里的函數(shù)subst是把$(x)中的1全部替換成2,所以y最后等于Hello

4. 其它更老的規(guī)則

模式變量

prog:CFLAGS=-g

目標(biāo)變量

%.o:CFLAGS=-O

這兩種變量都是,當(dāng)且僅當(dāng)特定的目標(biāo)需要被執(zhí)行打時(shí)候,用設(shè)置的變量取代環(huán)境變量的值

后綴規(guī)則,其實(shí)就是老式的隱含規(guī)則

.c.o:
$(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<

庫文件的目標(biāo)是

helloworld.a(hello.o world.o):hello.o world.o
    ar cr helloworld.a hello.o world.o

看APUE的make發(fā)現(xiàn)它的makefile寫的那叫一個(gè)簡單,能用隱含規(guī)則的全部用上了
比如 all: helloworld 就這么一句,合理推測(cè)的話,make會(huì)去自動(dòng)尋找helloworld.c并去調(diào)用對(duì)應(yīng)compile規(guī)則
比如 objs: hello.o world.o 也是一句,道理同上
還需要注意的是

編譯 .c 文件到可執(zhí)行文件的隱含規(guī)則的名字叫

COMPILE.c=$(CC) $(CFLAGS) $(CPPFLAGS) -c

鏈接 .c 文件到obj文件的隱含規(guī)則的名字叫

LINK.c=$(CC) $(CFLAGS) $(CPPFLAGS) $(LDDIR) $(LDFLAGS)

沒想到看了上面這么多的內(nèi)容,APUE的makefile還是遇到了小挑戰(zhàn),不過思考后還是解決了

GCC

gcc -c hello.c //將只生成 hello.o

鏈接

  • ar 命令的作用是把obj文件,打包成一個(gè) .a 庫文件,ar rv libtest.a hello.o fibo.o 便于其他的程序鏈接 libtest.a。其他程序通過 -ltest 就可以鏈接到這個(gè)庫
  • nm 命令的作用是查看 ar 命令打包好的 .a 庫文件里面由哪些符號(hào)構(gòu)成
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 來自陳浩的一片老文,但絕對(duì)營養(yǎng)。 示例工程:3 個(gè)頭文件*.h,和 8 個(gè) C 文件*.c。 初 編譯過程,源文件...
    周筱魯閱讀 4,787評(píng)論 0 17
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,568評(píng)論 19 139
  • makefile關(guān)系到整個(gè)工程的編譯規(guī)則,一個(gè)工程中的源文件不計(jì)其數(shù),按其類型、功能、模塊分別放在若干的目錄當(dāng)中,...
    Joe_HUST閱讀 1,985評(píng)論 0 3
  • @(linux 編程)[開發(fā)技能, 工具使用] What is GNU Make Make 是控制工程中通過源碼生...
    orientlu閱讀 11,619評(píng)論 0 26
  • 碧斯諾蘭深度了解 我現(xiàn)在所從事的是我們國產(chǎn)的碧斯諾蘭這個(gè)品牌。碧斯諾蘭是 一個(gè)非常 有實(shí)力的一個(gè)公司。在2004年...
    何蓉閱讀 435評(píng)論 0 3

友情鏈接更多精彩內(nèi)容