Makefile使用(學(xué)習(xí)筆記)

makefile的規(guī)則

組成

  • target
  • prerequisites
  • command
    target這一個(gè)或多個(gè)的目標(biāo)文件依賴于prerequisites中的文件,其生成規(guī)則定義在command中。說白一點(diǎn)就是說,prerequisites中如果有一個(gè)以上的文件比target文件要新的話,command所定義的命令就會被執(zhí)行。這就是Makefile的規(guī)則。也就是Makefile中最核心的內(nèi)容

文件名

“GNUmakefile”或“Makefile”或“makefile”的文件(也可以通過make -f或者make --file來指定文件)

makefile工作流程

  1.    讀入所有的Makefile。
    
  2.    讀入被include的其它Makefile。
    
  3.    初始化文件中的變量。
    
  4.    推導(dǎo)隱晦規(guī)則,并分析所有規(guī)則。
    
  5.    為所有的目標(biāo)文件創(chuàng)建依賴關(guān)系鏈。
    
  6.    根據(jù)依賴關(guān)系,決定哪些目標(biāo)要重新生成。
    
  7.    執(zhí)行生成命令。
    

編譯多個(gè)c文件過程例子
在默認(rèn)的方式下,也就是我們只輸入make命令。那么,

  • make會在當(dāng)前目錄下找名字叫“GNUmakefile”或“Makefile”或“makefile”的文件(也可以通過make -f或者make --file來指定文件)。
  • 如果找到,它會找文件中的第一個(gè)目標(biāo)文件(target),在上面的例子中,他會找到“edit”這個(gè)文件,并把這個(gè)文件作為最終的目標(biāo)文件。
  • 如果edit文件不存在,或是edit所依賴的后面的 .o 文件的文件修改時(shí)間要比edit這個(gè)文件新,那么,他就會執(zhí)行后面所定義的命令來生成edit這個(gè)文件。
  • 如果edit所依賴的.o文件也存在,那么make會在當(dāng)前文件中找目標(biāo)為.o文件的依賴性,如果找到則再根據(jù)那一個(gè)規(guī)則生成.o文件。(這有點(diǎn)像一個(gè)堆棧的過程)
  • 當(dāng)然,你的C文件和H文件是存在的啦,于是make會生成 .o 文件,然后再用 .o 文件聲明make的終極任務(wù),也就是執(zhí)行文件edit了。
    這就是整個(gè)make的依賴性,make會一層又一層地去找文件的依賴關(guān)系,直到最終編譯出第一個(gè)目標(biāo)文件。在找尋的過程中,如果出現(xiàn)錯誤,比如最后被依賴的文件找不到,那么make就會直接退出,并報(bào)錯,而對于所定義的命令的錯誤,或是編譯不成功,make根本不理。make只管文件的依賴性,即,如果在我找了依賴關(guān)系之后,冒號后面的文件還是不在,那么對不起,我就不工作啦。
    通過上述分析,我們知道,像clean這種,沒有被第一個(gè)目標(biāo)文件直接或間接關(guān)聯(lián),那么它后面所定義的命令將不會被自動執(zhí)行,不過,我們可以顯示要make執(zhí)行。即命令——“make clean”,以此來清除所有的目標(biāo)文件,以便重編譯。
    于是在我們編程中,如果這個(gè)工程已被編譯過了,當(dāng)我們修改了其中一個(gè)源文件,比如file.c,那么根據(jù)我們的依賴性,我們的目標(biāo)file.o會被重編譯(也就是在這個(gè)依性關(guān)系后面所定義的命令),于是file.o的文件也是最新的啦,于是file.o的文件修改時(shí)間要比edit要新,所以edit也會被重新鏈接了(詳見edit目標(biāo)文件后定義的命令)。
    而如果我們改變了“command.h”,那么,kdb.o、command.o和files.o都會被重編譯,并且,edit會被重鏈接。

語法

基本格式

target:prerequisites
    command

或者

target:prerequisites;command

! command 前面是tab鍵,不是空格,可以用\來分行,target、prerequisite、command都可以多個(gè)用空格隔開,后面的command要用前一條的結(jié)果需要使用分號隔開,比如

cd /home;pwd

cd home
pwd

是不同的,command可以多行

注釋

只支持行注釋,用#

默認(rèn)target

只輸入make,默認(rèn)執(zhí)行第一個(gè)target,也可以指定

default: modules

變量

VAR=......
$(VAR)
  • 大小寫敏感
  • 要使用$時(shí),用$$,不是\$
  • 除了用=,還可以用:=,這種方法,前面的變量不能使用后面的變量,只能使用前面已定義好了的變量
x := foo
y := $(x) bar
x := later

等價(jià)于

y := foo bar
x := later

如果使用定義在后面的變量,則沒有值

y := $(x) bar
x := foo

y=bar,x=foo

  • ?=:沒有定義這個(gè)變量就定義一個(gè)
  • $(var.a=b):替換 變量中的值
foo := a.o b.o c.o
bar := $(foo:.o=.c)
  • 變量的值當(dāng)成變量
x = y
y = z
a := $($(x))
  • 變量組合
first_second = Hello
a = first
b = second
all = $($a_$b)
  • 追加變量值
objects = main.o foo.o bar.o utils.o
objects += another.o
objects = main.o foo.o bar.o utils.o
objects := $(objects) another.o
  • 目標(biāo)變量(Target-specific Variable)
    只在這個(gè)目標(biāo)內(nèi)生效(類似C局部變量)
<target ...> : <variable-assignment>
<target ...> : overide <variable-assignment>
  • 模式變量(Pattern-specific Variable)
    make的“模式”一般是至少含有一個(gè)“%”的,所以,我們可以以如下方式給所有以[.o]結(jié)尾的目標(biāo)定義目標(biāo)變量:
%.o : CFLAGS = -O

同樣,模式變量的語法和“目標(biāo)變量”一樣:

<pattern ...> : <variable-assignment>
<pattern ...> : override <variable-assignment>

override同樣是針對于系統(tǒng)環(huán)境傳入的變量,或是make命令行指定的變量。

  • 自動化變量
    自動化變量,就是這種變量會把模式中所定義的一系列的文件自動地挨個(gè)取出,直至所有的符合模式的文件都取完了。這種自動化變量只應(yīng)出現(xiàn)在規(guī)則的命令中。

override指示符

如果有變量是通常make的命令行參數(shù)設(shè)置的,那么Makefile中對這個(gè)變量的賦值會被忽略。如果你想在Makefile中設(shè)置這類參數(shù)的值,那么,你可以使用“override”指示符。其語法是:

override <variable> = <value>
override <variable> := <value>
當(dāng)然,還可以追加:
override <variable> += <more text>
多行變量:
override define foo
bar
endef

.PHONY(偽目標(biāo))

target相同名的文件在makefile目錄下,執(zhí)行target而不是

.PHONY: modules
modules:

include

include<filename>
  • filename可以是當(dāng)前操作系統(tǒng)Shell的文件模式(可以保含路徑和通配符)
  • 在include前面可以有一些空字符,但是絕不能是[Tab]鍵開始。include和可以用一個(gè)或多個(gè)空格隔開。

忽略警告繼續(xù)執(zhí)行

clean:
   -rm not_exist.file exist.file

-include<filename>

環(huán)境變量MAKEFILES

所有makefile都會include它,影響到所有makefile,不建議使用

通配符

  • ~:當(dāng)前用戶
  • *
  • ?

轉(zhuǎn)義符、單行拆分成多行

clean:
   VAR=find ./ -name "a*"
   echo $(VAR)
   rm a &&\
   touch b

vpath

Makefile文件中的特殊變量“VPATH”就是完成這個(gè)功能的,如果沒有指明這個(gè)變量,make只會在當(dāng)前的目錄中去找尋依賴文件和目標(biāo)文件。如果定義了這個(gè)變量,那么,make就會在當(dāng)當(dāng)前目錄找不到的情況下,到所指定的目錄中去找尋文件了。

VPATH = src:../headers

上面的的定義指定兩個(gè)目錄,“src”和“../headers”,make會按照這個(gè)順序進(jìn)行搜索。目錄由“冒號”分隔。(當(dāng)然,當(dāng)前目錄永遠(yuǎn)是最高優(yōu)先搜索的地方)

另一個(gè)設(shè)置文件搜索路徑的方法是使用make的“vpath”關(guān)鍵字(注意,它是全小寫的),這不是變量,這是一個(gè)make的關(guān)鍵字,這和上面提到的那個(gè)VPATH變量很類似,但是它更為靈活。它可以指定不同的文件在不同的搜索目錄中。這是一個(gè)很靈活的功能。它的使用方法有三種:

  1.    vpath < pattern> < directories>    為符合模式< pattern>的文件指定搜索目錄<directories>。
    
  2.    vpath < pattern>                              清除符合模式< pattern>的文件的搜索目錄。
    
  3.    vpath                                                 清除所有已被設(shè)置好了的文件搜索目錄。
    

vapth使用方法中的< pattern>需要包含“%”字符?!?”的意思是匹配零或若干字符,例如,“%.h”表示所有以“.h”結(jié)尾的文件。< pattern>指定了要搜索的文件集,而< directories>則指定了的文件集的搜索的目錄。例如:
vpath %.h ../headers
可以連續(xù)地使用vpath語句,以指定不同搜索策略

   vpath %.c foo
   vpath %   blish
   vpath %.c bar

多target

$@:目前規(guī)則中所有的目標(biāo)集合

   bigoutput littleoutput : text.g
           generate text.g -$(subst output,,$@) > $@

上述規(guī)則等價(jià)于:

  bigoutput : text.g
          generate text.g -big > bigoutput
  littleoutput : text.g
          generate text.g -little > littleoutput

其中,-(subst output,,@)中的“”表示執(zhí)行一個(gè)Makefile的函數(shù),函數(shù)名為subst,后面的為參數(shù)。關(guān)于函數(shù),將在后面講述。這里的這個(gè)函數(shù)是截取字符串的意思,“@”表示目標(biāo)的集合,就像一個(gè)數(shù)組,“$@”依次取出目標(biāo),并執(zhí)于命令。

靜態(tài)模式

   objects = foo.o bar.o
 
   all: $(objects)
 
   $(objects): %.o: %.c
           $(CC) -c $(CFLAGS) $< -o $@

自動生成依賴性

cc -M main.c

其輸出是:

main.o : main.c defs.h

注意gcc

gcc -M main.c

相當(dāng)于

 main.o: main.c defs.h /usr/include/stdio.h /usr/include/features.h \
        /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h \
        /usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stddef.h \
        /usr/include/bits/types.h /usr/include/bits/pthreadtypes.h \
        /usr/include/bits/sched.h /usr/include/libio.h \
        /usr/include/_G_config.h /usr/include/wchar.h \
        /usr/include/bits/wchar.h /usr/include/gconv.h \
        /usr/lib/gcc-lib/i486-suse-linux/2.95.3/include/stdarg.h \
        /usr/include/bits/stdio_lim.h
gcc-MM main.c

相當(dāng)于

main.o: main.c defs.h

系統(tǒng)命令

可以使用系統(tǒng)的命令,默認(rèn)使用/bin/sh

命令顯示(回顯)

在命令前家@可以不顯示執(zhí)行的命令

@echo 'hello'

不會輸出echo `hello`,只輸出hello
使用make -n(或者--just-print),只顯示過程,真正執(zhí)行命令,用來調(diào)試makefile

嵌套makefile

subsystem:
 cd subdir && $(MAKE)

傳遞變量:export <variable>
傳遞所有變量:export
始終會默認(rèn)傳遞的變量:MAKEFLAGS,SHELL
記錄嵌套層數(shù)的變量:MAKELEVEL

定義命令包(多行變量)

define run-yacc
yacc $(firstword $^)
mv y.tab.c $@
endef

foo.c : foo.y
    $(run-yacc)

命令包“run-yacc”中的“^”就是“foo.y”,“@”就是“foo.c”

條件判斷

ifeq(,) #ifeq ' ' ' '  或者ifeq " " " "或ifeq ' ' " "
...
else
...
endif

ifneq ( , )
...
endif

ifdef <...>
...
endif

函數(shù)

$開頭,參數(shù)之間用,隔開

$(<function> <arguments> )
或是
${<function> <arguments>}
  • 字符串操作函數(shù)
$(subst <from>,<to>,<text> )
名稱:字符串替換函數(shù)——subst。
功能:把字串<text>中的<from>字符串替換成<to>。
返回:函數(shù)返回被替換過后的字符串。
$(patsubst <pattern>,<replacement>,<text> )
名稱:模式字符串替換函數(shù)——patsubst。
功能:查找<text>中的單詞(單詞以“空格”、“Tab”或“回車”“換行”分隔)是否符合模式<pattern>,如果匹配的話,則以<replacement>替換。這里,<pattern>可以包括通配符“%”,表示任意長度的字串。如果<replacement>中也包含“%”,那么,<replacement>中的這個(gè)“%”將是<pattern>中的那個(gè)“%”所代表的字串。(可以用“\”來轉(zhuǎn)義,以“\%”來表示真實(shí)含義的“%”字符)返回:函數(shù)返回被替換過后的字符串。
$(strip <string> )


名稱:去空格函數(shù)——strip。
功能:去掉<string>字串中開頭和結(jié)尾的空字符。
返回:返回被去掉空格的字符串值。
$(findstring <find>,<in> )


名稱:查找字符串函數(shù)——findstring。
功能:在字串<in>中查找<find>字串。
返回:如果找到,那么返回<find>,否則返回空字符串。
$(filter <pattern...>,<text> )


名稱:過濾函數(shù)——filter。
功能:以<pattern>模式過濾<text>字符串中的單詞,保留符合模式<pattern>的單詞???以有多個(gè)模式。
返回:返回符合模式<pattern>的字串。
示例:


sources := foo.c bar.c baz.s ugh.h
foo: $(sources)
cc $(filter %.c %.s,$(sources)) -o foo
$(filter-out <pattern...>,<text> )


名稱:反過濾函數(shù)——filter-out。
功能:以<pattern>模式過濾<text>字符串中的單詞,去除符合模式<pattern>的單詞。可
以有多個(gè)模式。
返回:返回不符合模式<pattern>的字串。
$(sort <list> )


名稱:排序函數(shù)——sort。
功能:給字符串<list>中的單詞排序(升序)。
返回:返回排序后的字符串。
示例:$(sort foo bar lose)返回“bar foo lose” 。
備注:sort函數(shù)會去掉<list>中相同的單詞。
$(word <n>,<text> )


名稱:取單詞函數(shù)——word。
功能:取字符串<text>中第<n>個(gè)單詞。(從一開始)
返回:返回字符串<text>中第<n>個(gè)單詞。如果<n>比<text>中的單詞數(shù)要大,那么返回空
字符串。
$(wordlist <s>,<e>,<text> )


名稱:取單詞串函數(shù)——wordlist。
功能:從字符串<text>中取從<s>開始到<e>的單詞串。<s>和<e>是一個(gè)數(shù)字。
返回:返回字符串<text>中從<s>到<e>的單詞字串。如果<s>比<text>中的單詞數(shù)要大,那
么返回空字符串。如果<e>大于<text>的單詞數(shù),那么返回從<s>開始,到<text>結(jié)束的單
詞串。
示例: $(wordlist 2, 3, foo bar baz)返回值是“bar baz”。
$(words <text> )


名稱:單詞個(gè)數(shù)統(tǒng)計(jì)函數(shù)——words。
功能:統(tǒng)計(jì)<text>中字符串中的單詞個(gè)數(shù)。
返回:返回<text>中的單詞數(shù)。
示例:$(words, foo bar baz)返回值是“3”。
備注:如果我們要取<text>中最后的一個(gè)單詞,我們可以這樣:$(word $(words <text> 
),<text> )。
$(firstword <text> )


名稱:首單詞函數(shù)——firstword。
功能:取字符串<text>中的第一個(gè)單詞。
返回:返回字符串<text>的第一個(gè)單詞。
示例:$(firstword foo bar)返回值是“foo”。
備注:這個(gè)函數(shù)可以用word函數(shù)來實(shí)現(xiàn):$(word 1,<text> )。
  • 文件名操作函數(shù)
$(dir <names...> )


名稱:取目錄函數(shù)——dir。
功能:從文件名序列<names>中取出目錄部分。目錄部分是指最后一個(gè)反斜杠(“/”)之
前的部分。如果沒有反斜杠,那么返回“./”。
返回:返回文件名序列<names>的目錄部分。
示例: $(dir src/foo.c hacks)返回值是“src/ ./”。
$(notdir <names...> )


名稱:取文件函數(shù)——notdir。
功能:從文件名序列<names>中取出非目錄部分。非目錄部分是指最后一個(gè)反斜杠(“/”
)之后的部分。
返回:返回文件名序列<names>的非目錄部分。
示例: $(notdir src/foo.c hacks)返回值是“foo.c hacks”。
$(suffix <names...> )


名稱:取后綴函數(shù)——suffix。
功能:從文件名序列<names>中取出各個(gè)文件名的后綴。
返回:返回文件名序列<names>的后綴序列,如果文件沒有后綴,則返回空字串。
示例:$(suffix src/foo.c src-1.0/bar.c hacks)返回值是“.c .c”。
$(basename <names...> )


名稱:取前綴函數(shù)——basename。
功能:從文件名序列<names>中取出各個(gè)文件名的前綴部分。
返回:返回文件名序列<names>的前綴序列,如果文件沒有前綴,則返回空字串。
示例:$(basename src/foo.c src-1.0/bar.c hacks)返回值是“src/foo src-1.0/bar h
acks”。
$(addsuffix <suffix>,<names...> )


名稱:加后綴函數(shù)——addsuffix。
功能:把后綴<suffix>加到<names>中的每個(gè)單詞后面。
返回:返回加過后綴的文件名序列。
示例:$(addsuffix .c,foo bar)返回值是“foo.c bar.c”。
$(addprefix <prefix>,<names...> )


名稱:加前綴函數(shù)——addprefix。
功能:把前綴<prefix>加到<names>中的每個(gè)單詞后面。
返回:返回加過前綴的文件名序列。
示例:$(addprefix src/,foo bar)返回值是“src/foo src/bar”。
$(join <list1>,<list2> )


名稱:連接函數(shù)——join。
功能:把<list2>中的單詞對應(yīng)地加到<list1>的單詞后面。如果<list1>的單詞個(gè)數(shù)要比<
list2>的多,那么,<list1>中的多出來的單詞將保持原樣。如果<list2>的單詞個(gè)數(shù)要比
<list1>多,那么,<list2>多出來的單詞將被復(fù)制到<list2>中。
返回:返回連接過后的字符串。
示例:$(join aaa bbb , 111 222 333)返回值是“aaa111 bbb222 333”。

foreach函數(shù)

$(foreach <var>,<list>,<text> )
names := a b c d


files := $(foreach n,$(names),$(n).o)

上面的例子中,$(name)中的單詞會被挨個(gè)取出,并存到變量“n”中,“$(n).o”每次根據(jù)“$(n)”計(jì)算出一個(gè)值,這些值以空格分隔,最后作為foreach函數(shù)的返回,所以,$(f
iles)的值是“a.o b.o c.o d.o”。


注意,foreach中的<var>參數(shù)是一個(gè)臨時(shí)的局部變量,foreach函數(shù)執(zhí)行完后,參數(shù)<var>的變量將不在作用,其作用域只在foreach函數(shù)當(dāng)中。
  • if函數(shù)
$(if <condition>,<then-part> )

或是

$(if <condition>,<then-part>,<else-part> )
  • call函數(shù)
    call函數(shù)是唯一一個(gè)可以用來創(chuàng)建新的參數(shù)化的函數(shù)。你可以寫一個(gè)非常復(fù)雜的表達(dá)式,這個(gè)表達(dá)式中,你可以定義許多參數(shù),然后你可以用call函數(shù)來向這個(gè)表達(dá)式傳遞參數(shù)。其語法是:
$(call <expression>,<parm1>,<parm2>,<parm3>...)
reverse = $(1) $(2)
foo = $(call reverse,a,b)
(foo值:a b)
reverse = $(2) $(1)
foo = $(call reverse,a,b)
此時(shí)的foo的值就是“b a”。
  • origin函數(shù)
    origin函數(shù)不像其它的函數(shù),他并不操作變量的值,他只是告訴你你的這個(gè)變量是哪里來的?其語法是:
$(origin <variable> )

取值:

“undefined”


如果<variable>從來沒有定義過,origin函數(shù)返回這個(gè)值“undefined”。

“default”


如果<variable>是一個(gè)默認(rèn)的定義,比如“CC”這個(gè)變量,這種變量我們將在后面講述。

“environment”


如果<variable>是一個(gè)環(huán)境變量,并且當(dāng)Makefile被執(zhí)行時(shí),“-e”參數(shù)沒有被打開。


“file”


如果<variable>這個(gè)變量被定義在Makefile中。


“command line”


如果<variable>這個(gè)變量是被命令行定義的。

“override”


如果<variable>是被override指示符重新定義的。

“automatic”


如果<variable>是一個(gè)命令運(yùn)行中的自動化變量。關(guān)于自動化變量將在后面講述。
  • shell 函數(shù)
    shell 函數(shù)也不像其它的函數(shù)。顧名思義,它的參數(shù)應(yīng)該就是操作系統(tǒng)Shell的命令。它和反引號“`”是相同的功能。這就是說,shell函數(shù)把執(zhí)行操作系統(tǒng)命令后的輸出作為函數(shù)
    返回。于是,我們可以用操作系統(tǒng)命令以及字符串處理命令awk,sed等等命令來生成一個(gè)變量,如:
contents := $(shell cat foo)
files := $(shell echo *.c)

! 注意,這個(gè)函數(shù)會新生成一個(gè)Shell程序來執(zhí)行命令,所以你要注意其運(yùn)行性能,如果你的Makefile中有一些比較復(fù)雜的規(guī)則,并大量使用了這個(gè)函數(shù),那么對于你的系統(tǒng)性能是有害的。特別是Makefile的隱晦的規(guī)則可能會讓你的shell函數(shù)執(zhí)行的次數(shù)比你想像的多得多。

  • 控制make的函數(shù)
$(error <text ...> )
$(warning <text ...> )

make退出碼

0 —— 表示成功執(zhí)行。
1 —— 如果make運(yùn)行時(shí)出現(xiàn)任何錯誤,其返回1。
2 —— 如果你使用了make的“-q”選項(xiàng),并且make使得一些目標(biāo)不需要更新,那么返回2。

make指定目標(biāo)

GNU這種開源軟件的發(fā)布時(shí),其 makefile都包含了編譯、安裝、打包等功能。我們可以參照這種規(guī)則來書寫我們的makefile中的目標(biāo)。
**“all” ** 這個(gè)偽目標(biāo)是所有目標(biāo)的目標(biāo),其功能一般是編譯所有的目標(biāo)。
**“clean” **這個(gè)偽目標(biāo)功能是刪除所有被make創(chuàng)建的文件。
**“install” **這個(gè)偽目標(biāo)功能是安裝已編譯好的程序,其實(shí)就是把目標(biāo)執(zhí)行文件拷貝到指定的目標(biāo)中去。
**“print” **這個(gè)偽目標(biāo)的功能是例出改變過的源文件。
**“tar” ** 這個(gè)偽目標(biāo)功能是把源程序打包備份。也就是一個(gè)tar文件。
**“dist” ** 這個(gè)偽目標(biāo)功能是創(chuàng)建一個(gè)壓縮文件,一般是把tar文件壓成Z文件。或是gz文件。
**“TAGS” ** 這個(gè)偽目標(biāo)功能是更新所有的目標(biāo),以備完整地重編譯使用。
**“check”和“test” **這兩個(gè)偽目標(biāo)一般用來測試makefile的流程。

make檢查規(guī)則 make調(diào)試

  • make時(shí)加參數(shù)
有時(shí)候,我們不想讓我們的makefile中的規(guī)則執(zhí)行起來,我們只想檢查一下我們的命令,或是執(zhí)行的序列。于是我們可以使用make命令的下述參數(shù):


“-n”
“--just-print”
“--dry-run”
“--recon”
不執(zhí)行參數(shù),這些參數(shù)只是打印命令,不管目標(biāo)是否更新,把規(guī)則和連帶規(guī)則下的命令打印出來,但不執(zhí)行,這些參數(shù)對于我們調(diào)試makefile很有用處。


“-t”
“--touch”
這個(gè)參數(shù)的意思就是把目標(biāo)文件的時(shí)間更新,但不更改目標(biāo)文件。也就是說,make假裝編譯目標(biāo),但不是真正的編譯目標(biāo),只是把目標(biāo)變成已編譯過的狀態(tài)。


“-q”
“--question”
這個(gè)參數(shù)的行為是找目標(biāo)的意思,也就是說,如果目標(biāo)存在,那么其什么也不會輸出,當(dāng)然也不會執(zhí)行編譯,如果目標(biāo)不存在,其會打印出一條出錯信息。


“-W <file>”
“--what-if=<file>”
“--assume-new=<file>”
“--new-file=<file>”
這個(gè)參數(shù)需要指定一個(gè)文件。一般是是源文件(或依賴文件),Make會根據(jù)規(guī)則推導(dǎo)來運(yùn)行依賴于這個(gè)文件的命令,一般來說,可以和“-n”參數(shù)一同使用,來查看這個(gè)依賴文件
所發(fā)生的規(guī)則命令。

另外一個(gè)很有意思的用法是結(jié)合“-p”和“-v”來輸出makefile被執(zhí)行時(shí)的信息(這個(gè)將在后面講述)。
  • 在makefile中添加調(diào)試信息
    使用
 $(`信息等級` `...調(diào)試信息..`)
如:
$(info "hello")
$(warning "hello")
$(error "hello")

或者使用

@echo ......

這種的局限就是只能在目標(biāo)后面使用

make參數(shù)

參見make --help或者man make

隱含規(guī)則

報(bào)錯立即停止

參考:makefile出現(xiàn)錯誤卻不停止,卻繼續(xù)運(yùn)行

makefile執(zhí)行錯誤,結(jié)果還會繼續(xù)執(zhí)行,此處是由于是上層makefile調(diào)用下層子makefile,子makefile執(zhí)行出錯,停止返回到上層后,上層沒有判斷返回值,導(dǎo)致還是會繼續(xù)執(zhí)行。

解決辦法是,對于子makefile調(diào)用,判斷返回值,
比如將:
make $@;
改為:
make $@ || exit "$$?";
這樣make執(zhí)行錯誤返回值為非0,然后就可以執(zhí)行后面的exit而退出了。

==================================

學(xué)習(xí)資料

Makefile經(jīng)典教程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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