問題集錦

  1. makefile 中 .PYONY 的目的是什么
    默認(rèn)情況下铣揉,Makefile 目標(biāo)是「文件目標(biāo)」- 它們用于從其他文件構(gòu)建文件. 假設(shè)它的目標(biāo)是一個(gè)文件哪审,這使得編寫 Makefile 相對(duì)容易.

    foo: bar
        create_one_from_the_other foo bar
    

    但是蛾魄,有時(shí)你希望 Makefile 運(yùn)行一些命令而不是構(gòu)建一個(gè)在文件系統(tǒng)中的實(shí)際文件. 例如常用的目標(biāo)文件:clean, all.
    但有時(shí)情況并非如此,你可能在主目錄中有一個(gè)名為 clean 的文件湿滓,這時(shí)候 Make 會(huì)被混淆滴须,因?yàn)槟J(rèn)情況下,clean 目標(biāo)將與此文件關(guān)聯(lián)叽奥,而 Make 只會(huì)在這個(gè)文件根據(jù)它的依賴發(fā)現(xiàn)不是最新的時(shí)候才會(huì)執(zhí)行.

    這些特殊目標(biāo)稱為「虛假目標(biāo)」扔水,你可以明確告訴 Make 它們與文件無關(guān).

    .PHONY: clean
    clean:
        rm -rf *.o
    

    現(xiàn)在 make clean 將按預(yù)期運(yùn)行,即使你有一個(gè)名為 clean 的文件.

    Make 而言朝氓,「虛假目標(biāo)」是一個(gè)總是過時(shí)的目標(biāo)魔市,因此無論何時(shí) make <pyony_target>, 它都會(huì)運(yùn)行,獨(dú)立于文件系統(tǒng)的狀態(tài).
    一些常用的「虛假目標(biāo)」:all, install, clean, distclean, TAGS, info, check.

  2. GNU Makefile 變量賦值 =, ?=, := 和 += 之間有什么區(qū)別

    Lazy Set

    VARIABLE = value
    

    變量的正常設(shè)置 - 當(dāng)使用變量時(shí)膀篮,變量會(huì)「遞歸擴(kuò)展」嘹狞,而不是在聲明變量的時(shí)候擴(kuò)展.

    Immediate Set

    VARIABLE := value
    

    通過簡單擴(kuò)展內(nèi)部值來設(shè)置變量 - 其中的值在聲明時(shí)擴(kuò)展.(不會(huì)「遞歸擴(kuò)展」).

    Set If Absent

    VARIABLE ?= value
    

    如果變量沒有定義則設(shè)置變量.

    Append

    VARIABLE += value
    

    將提供的值附加到現(xiàn)有的值(如果變量不存在,則設(shè)置為該值).

  3. 從命令行傳遞其他變量給 make
    你有幾個(gè)選擇可以從 makefile 外部設(shè)置變量.

    1. 環(huán)境變量 - 每一個(gè)環(huán)境變量都轉(zhuǎn)化為具有相同名稱和值的 makefile 變量.

    你可能還想設(shè)置 -e 選項(xiàng)(或者 --environments-override)誓竿,并且你的環(huán)境變量會(huì)覆蓋 makefile 中的賦值(除非這些賦值本身使用 override
    指令. 但是不推薦使用它.
    而是推薦使用更好更靈活的 ?= 條件賦值(只有在尚沒定義變量時(shí)才有效).

    FOO ?= default_value_if_not_set_in_environment
    

    注意磅网,某些變量不是從環(huán)境變量繼承的

    • MAKE 從腳本的名字得到的
    • SHELL 要么設(shè)置在 makefile 中,要么默認(rèn)為 /bin/sh
    1. 從命令行 - make 可以將變量賦值作為命令行的一部分筷屡,與目標(biāo)混合.
    make target FOO=bar
    

    但是涧偷,除非在賦值中使用 override 指令,否則忽略 makefileFOO 變量的所有值.

    1. 從父 make 導(dǎo)出 - 如果從 makefile 調(diào)用 make, 通常不應(yīng)該這樣顯式地寫這樣的變量賦值
    # Don't do this!
    target:
        $(MAKE) -C target CC=$(CC) CFLAGS=$(CFLAGS)
    

    相反毙死,更好的方法是導(dǎo)出這些變量.
    導(dǎo)出變量使其進(jìn)入每個(gè) shell 調(diào)用的環(huán)境燎潮,并且使用這些命令將會(huì)調(diào)用這些環(huán)境變量,如上所述.

    # Do like this
    CFLAGS=-g
    export CFLAGS
    target:
        $(MAKE) -C target
    

    你也可以導(dǎo)出全部變量扼倘,直接使用 export 不帶參數(shù).

  4. makefile 中 $@ 和 $^ 是什么意思
    $@ 是要生成的目標(biāo)文件的名稱确封,而 $^ 是第一個(gè)先決條件(通常是源文件). 例如:

    all: library.cpp main.cpp
    

    $@ 相當(dāng)于 all
    $< 相當(dāng)于 library.cpp
    $^ 相當(dāng)于 library.cpp main.cpp

  5. makefile:4: *** missing separator. Stop
    makefile 與制表符有非常愚蠢的關(guān)系.
    每個(gè)規(guī)則的所有操作都由制表符標(biāo)識(shí)除呵,而不是4個(gè)空格,只有 tab 才能標(biāo)識(shí)為制表符.
    去檢查是否使用制表符爪喘,使用 cat -e -t -v makefile_name.
    它顯示了帶有 ^Itab 和帶有 $ 的行結(jié)尾颜曾,兩者確保了依賴關(guān)系正確結(jié)束以及制表符標(biāo)識(shí)規(guī)則的操作以使它們易于識(shí)別為 make 實(shí)用程序起到至關(guān)重要的作用.

    Kaizen ~/so_test $ cat -e -t -v  mk.t
    all:ll$      ## here the $ is end of line ...
    $
    ll:ll.c   $
    ^Igcc  -c  -Wall -Werror -02 c.c ll.c  -o  ll  $@  $<$
    ## the ^I above means a tab was there before the action part, so this line is ok .
    $
    clean :$
        \rm -fr ll$
    ## see here there is no ^I which means , tab is not present ....
    ## in this case you need to open the file again and edit/ensure a tab
    ## starts the action part
    
  6. 什么是 Makefile.am 和 Makefile.in
    Makefile.am 是程序員定義的文件,由 automake 用于生成 Makefile.in 文件(.am 代表 automake).
    通常在源碼包中可以看到 configure 腳本使用 Makefile.in 生成 Makefile.

    configure 腳本本身是從名為 configure.acconfigure.in(不建議使用)的程序員定義的文件生成的.
    我更喜歡 .ac (用于 autoconf)秉剑,因?yàn)樗鼘⑴c生成的 Makefile.in 文件區(qū)分開來泛豪,這樣我就可以使用 make dist-clean 等規(guī)則來運(yùn)行
    rm -f *.in.
    由于它是生成的文件,因此通常不會(huì)存儲(chǔ)在版本系統(tǒng)(Git侦鹏,Svn)中诡曙,而是存儲(chǔ)在 .ac 文件中.

  7. 如何在 makefile 中編寫 cd 命令
    它實(shí)際上是執(zhí)行命令,將目錄更改為 some_directory, 但是略水,這是在子進(jìn)程 shell 中執(zhí)行的价卤,并且既不影響 make 也不影響你正在使用的 shell.

    如果你想在 some_directory 中執(zhí)行更多任務(wù),則需要添加分號(hào)并附加其他命令.
    請注意聚请,你不能使用換行符荠雕,因?yàn)樗鼈儽?make 解釋為規(guī)則的結(jié)尾,因此為清晰起見而使用的任何換行都需要通過反斜杠進(jìn)行轉(zhuǎn)義.

    all:
        cd some_dir; echo "I'm in some_dir"; \
        gcc -Wall -o myTest myTest.c
    

    一個(gè)常見的用法是在子目錄中調(diào)用 make. 這有一個(gè)命令行選項(xiàng)驶赏,所以你不必自己調(diào)用 cd.

    all:
        $(MAKE) -C some_dir all
    

    將更改為 some_dir 目錄并執(zhí)行目標(biāo)為 allMakefile.
    作為最佳實(shí)踐,使用 $(MAKE) 而不是直接調(diào)用 make, 因?yàn)樗鼤?huì)注意調(diào)用正確的 make 實(shí)例(例如既鞠,如果你為構(gòu)建環(huán)境使用特殊的 make 版本)煤傍,并提供使用某些開關(guān)(例如,-t)運(yùn)行時(shí)略有不同的行為.

  8. 如何在 makefile 中打印變量
    你可以使用此方法(使用名為 var 的變量)在讀取 makefile 時(shí)打印出變量.

    $(info $$var is [${var}])
    

    你可以將此構(gòu)造添加到任何配方中嘱蛋,以查看將傳遞給 shell 的內(nèi)容

    .PYONY: all
    all: ; $(info $$var is [${var}])echo Hello World
    

    現(xiàn)在蚯姆,這里發(fā)生的是將整個(gè)配方($(info $$var is [${var}])echo Hello World)存儲(chǔ)為單個(gè)遞歸擴(kuò)展變量. 當(dāng) make 決定運(yùn)行配方時(shí)(例如,當(dāng)你告訴它構(gòu)建 all 時(shí))洒敏,它會(huì)擴(kuò)展變量龄恋,然后將每個(gè)結(jié)果行分別傳遞給 shell.

    所以,令人懊惱的細(xì)節(jié):

    • 擴(kuò)展 $(info $$var is [${var}])echo Hello World
    • 要做到這點(diǎn)凶伙,首先擴(kuò)展 $(info $$var is [${var}])
      • $$ 擴(kuò)展成 $
      • ${var} 擴(kuò)展成 :) (取決你變量本身的值)
      • 副作用是 $var is [:)] 出現(xiàn)在標(biāo)準(zhǔn)輸出(屏幕)上
      • $(info ...) 擴(kuò)展成空
    • Make 還剩下 echo Hello World
      • Make 首先輸出 echo Hello World 到標(biāo)準(zhǔn)輸出(屏幕)郭毕,讓你知道它要求 shell 做什么
    • shell 輸出 Hello World 到標(biāo)準(zhǔn)輸出(屏幕)上
  9. 如何在 makefile 中編寫循環(huán)
    假設(shè)你使用的是 UNIX 類型平臺(tái),如果運(yùn)行 ./a.out.

    for number in 1 2 3 4 ; do \
        ./a.out $$number ; \
    done
    

    測試如下

    target:
        for number in 1 2 3 4 ; do \
            echo $$number ; \
        done
    

    輸出

    1
    2
    3
    4
    

    對(duì)于更大的范圍函荣,使用

    target:
        number=1 ; while [[ $$number -le 10 ]] ; do \
            echo $$number ; \
            ((number = number + 1)) ; \
        done
    

    嵌套循環(huán)

    target:
        num1=1 ; while [[ $$num1 -le 4 ]] ; do \
            num2=1 ; while [[ $$num2 -le 3 ]] ; do \
                echo $$num1 $$num2 ; \
                ((num2 = num2 + 1)) ; \
                done ; \
            ((num1 = num1 + 1)) ; \
        done
    

    輸出

    1 1
    1 2
    1 3
    2 1
    2 2
    2 3
    3 1
    3 2
    3 3
    4 1
    4 2
    4 3
    
  10. 在 Unix 中显押,我可以在一個(gè)目錄中運(yùn)行 make 而不先 cd 到那個(gè)目錄嗎
    make -C /path/to/dir

  11. 如何將命令的輸出分配給 Makefile 變量
    使用 Make 內(nèi)建函數(shù) shell, 例如:MY_VAR = $(shell echo whatever)

    $ make
    MY_VAR IS whatever
    
    $ cat Makefile
    MY_VAR := $(shell echo whatever)
    
    all:
        @echo MY_VAR IS $(MY_VAR)
    
  12. 如何配置 makefile 為調(diào)試和發(fā)布版本
    使用特定于目標(biāo)的變量值,例如

    CXXFLAGS = -g3 -gdwarf2
    CCFLAGS = -g3 -gdwarf2
    
    all: executable
    
    debug: CXXFLAGS += -DDEBUG -g
    debug: CCFLAGS += -DDEBUG -g
    debug: executable
    
    executable: CommandParser.tab.o CommandParser.yy.o Command.o
        $(CXX) -o output CommandParser.yy.o CommandParser.tab.o Command.o -lfl
    
    CommandParser.yy.o: CommandParser.l
        flex -o CommandParser.yy.c CommandParser.l
        $(CC) -c CommandParser.yy.c
    

    請記住使用 $(CXX)$(CC) 作為編譯命令.
    然后傻挂,make debug 將會(huì)有額外的標(biāo)識(shí)乘碑,如:-DDEBUG-g, 而 make 不會(huì)有.

  13. 如何獲取 Makefile 的當(dāng)前相對(duì)目錄
    你可以使用 shell 函數(shù):current_dir = $(shell pwd).
    或者你需要絕對(duì)路徑,可以 shell 結(jié)合 notdir 使用, current_dir = $(notdir $(shell pwd)).
    上面的方法金拒,僅 makeMakefile 當(dāng)前目錄執(zhí)行有效.

    注意: 這將返回當(dāng)前工作目錄兽肤,而不是 Makefile 的父目錄.
    例如,如果運(yùn)行 cd /; make -f /home/username/project/Makefile, current_dir 返回的是 / 而不是 /home/username/project/

    以下代碼適用于任何目錄調(diào)用的 Makefile

    mkfile_path := $(abspath $(lastword $(MAKEFILE_LIST)))
    current_dir := $(notdir $(patsubst %/,%,$(dir $(mkfile_path))))
    
  14. 如果沒有指定目標(biāo),make 如何知道要構(gòu)建的默認(rèn)目標(biāo)
    默認(rèn)情況下资铡,make 首先處理不以 . 開頭的第一個(gè)目標(biāo)(又叫「默認(rèn)目標(biāo)」).
    也可以使用 .DEFAULT_GOAL 指定默認(rèn)目標(biāo)(make <= 3.80 將不起作用)

    .DEFAULT_GOAL := mytarget
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沉迹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子害驹,更是在濱河造成了極大的恐慌鞭呕,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宛官,死亡現(xiàn)場離奇詭異葫松,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)底洗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門腋么,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人亥揖,你說我怎么就攤上這事珊擂。” “怎么了费变?”我有些...
    開封第一講書人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵摧扇,是天一觀的道長。 經(jīng)常有香客問我挚歧,道長扛稽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任滑负,我火速辦了婚禮在张,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘矮慕。我一直安慰自己帮匾,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開白布痴鳄。 她就那樣靜靜地躺著瘟斜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪夏跷。 梳的紋絲不亂的頭發(fā)上哼转,一...
    開封第一講書人閱讀 51,245評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音槽华,去河邊找鬼壹蔓。 笑死,一個(gè)胖子當(dāng)著我的面吹牛猫态,可吹牛的內(nèi)容都是我干的佣蓉。 我是一名探鬼主播披摄,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼勇凭!你這毒婦竟也來了疚膊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤虾标,失蹤者是張志新(化名)和其女友劉穎寓盗,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體璧函,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡傀蚌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蘸吓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片善炫。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖库继,靈堂內(nèi)的尸體忽然破棺而出箩艺,到底是詐尸還是另有隱情,我是刑警寧澤宪萄,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布艺谆,位于F島的核電站,受9級(jí)特大地震影響雨膨,放射性物質(zhì)發(fā)生泄漏擂涛。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一聊记、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧恢暖,春花似錦排监、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至嫁佳,卻和暖如春挨队,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蒿往。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來泰國打工盛垦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人瓤漏。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓腾夯,卻偏偏與公主長得像颊埃,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蝶俱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354