中山野鬼 linux 下 C 編程和make的方法 (4、開始make)

終於開始make了
    make 是個命令,先談一下,爲何要make?
    首先的理由就是,你能夠將前面不少gcc的命令行,彙總起來,而且一次確認,多個命令自動運行。我相信不少人說我在忽悠。這就是個「批處理」,就是加上覆雜的變量替換,條件執行,也就是個腳本。沒錯,make首先就是個腳本分析執行的工做。
    但make有優點的地方在於依賴的檢查。什麼是依賴,初學者看GNU make之類的文檔,別說英文版,就是中文「依賴」也夠理解半天。這裏重複說個生成.o文件的意義。意義就是不要對沒有改動的過的C文件,進行再次編譯。 這裏隱含了「依賴」的概念。.o文件之因此不須要再編譯,是依賴一個前提,C文件沒有被改動過。可是C文件沒有被改動過,不表明其#include的.h 文件就沒有改動過啊。由此所謂「依賴」對於make而言,是一個操做存在的前提條件。當操做的前提條件沒有刷新時,本身也就沒有必要刷新。
    可是linux操做系統,只會孤立的判斷每一個文件是否被改動過了。你C文件裏#include了一個h文件,OS沒時間幫你慢慢分析,而make也不會幫你自動閱讀理解C文件。這些都是gcc的事情。得,你們把責任都推給GCC。
    GCC也很無辜,「關我毛事啊!你告訴我要編譯,我就編譯,你不告訴我要編譯,我爲何要編譯。個人預編譯系統只會識別#include 而後在對應的目錄裏找到文件,並打開,添加。這個文件有沒有被修改過,第一我不知道,第二我不須要知道。若是你把執行文件刪除了,我就是知道全部源文件沒 有被改動過,你讓我編譯,難道我告訴你‘哈哈,通過個人這麼這麼分析,發現文件沒有被修改過,因此我不會生成執行文件,若是執行文件被別人刪除,請找相關 部門,尋求找回,我很智能的’」。
    如今咱們討論下來,文件的依賴性,看來沒有任何工具能夠主動跳出來承擔責任,此時,make跑出來,很負責的說了一句「其實我能作,但須要你,設計者,願 意描述依賴關係,那麼我make能夠根據你的依賴關係進行檢查」。這就是make區別其餘shell下的普通腳本工具的價值。

    所以,對於make幾個基本概念,如今要有:
    一、咱們用make主要是針對文件進行處理的。由於依賴關係的做用域(有效範圍)是工程,工程內部有價值的依賴一般是多個文件之間的因果關係。
    二、make除了依次執行調用其餘工具或命令,作所謂批處理的事情外,依賴關係的檢查是他的一個重要特性。否則他跳出來主動擔責任就是一種「欺騙」,準確說是「行政不做爲」的表現。
    你把計劃和依賴,描述在一個文件裏,傳遞給make"。一般有兩類作法。
1 $make -f filename
    filename是一個文件名。但不是潛規則要求的文件名。這樣作一般用於臨時性的make使用,正式狀況,不須要如此折騰。潛規則有個好處,你被潛規則了,其餘人也會被潛規則。這樣下降你和其餘人的交流成本。
    由此,另外一個作法是將你的計劃,寫在名爲 GNUmakefile ,makefile ,Makefile這幾種文件名中任意一個。恩。make的潛規則文件名也有幾種寫法。但潛規則中的潛規則是,咱們都用Makefile。若是老師考你 make的潛規則,均可以識別哪幾個文件名,他們的依次順序時,你能夠絕不猶豫的向他豎中指。他若是問哪學的,你能夠說是野鬼教的,由於他沒有說是那個版 本的make。不過豎歸豎,爲了防止意外,你仍是要知道,GNU make是按照GNUmakefile ,makefile ,Makefile依次進行查找的,同時儘量的確保你的目錄下只有Makefile一個文件。
    須要特別說明的是,GNUmakefile人如其名,只有GNU make能夠識別,make也有不一樣的版本和來源和C的編譯器同樣,只不過linux上用GNU make的仍是比較多。但仍然建議使用 Makefile這個文件名。
    有了潛規則,你就不須要如此寫
1 $make Makefile

  由於當你在當前目錄下存在Makefile時,make會自動查找,這就是在「默默的享受被潛規則」 linux

    因爲你對工程但願作不少事情,典型的幾個事情

    build :程序員

    只編譯那些修改過的,或新的文件shell

    rebuild all :函數

    無論有沒有修改過,我就是要所有重來,有過工程經驗的程序員,我相信大多數都吃過一個苦,由於疏忽,致使build並無實實在在的把最新的代碼給編譯到 最終文件中去,因而總問「爲何仍是不行!!」,因此沒有養成正確良好的make習慣的新手,rebuild仍是很必要的,特別是一個工程調用了另外一個工 程生成的庫,而當前工程並不會檢查另外一個工程生成的庫的變更性的時候。工具

    其實我我的的理解,之因此存在rebuild all是由於你的Makefile沒有寫好,理論上rebuild all是沒有存在的意義的,這引伸出不建議使用IDE的話題。我常常被VC6.0搞暈。特別是有些外部庫VC6.0沒法自動檢測依賴性關係,使得我必須 rebuild allui

    clean all:
    至少有兩個做用。第一,rebuild all能夠拆解成兩個動做。把全部obj 和最終文件都刪除,再build。第二,你想轉移你的有效代碼,好比打包COPY到另外一個機器時,一個大目錄下總體打包壓縮,更有效。可是obj和執行文 件還有不少其餘中間文件,都很大,並且對於代碼文本的轉移沒有必要。所以clean all .此時,你的目錄下,只有乾淨的源碼和一些說明文件,固然也包括Makefile,此時豈不是清爽的很?
    爲了有效區分不一樣的操做,make應能夠以下處理。
    $make clean //那麼咱們就調用clean的操做
    $make build //正常的帶依賴性檢測的build
    $make rebuild //咱們就調用rebuild的操做。
    由此,咱們引出了幾個關於makefile的設計目標。
    一、咱們要能在makefile裏面描述出依賴關係。

    二、咱們要能在makefile裏面區分不一樣的操做。固然一個操做,是由多個執行步驟組成的。
    三、能夠make ,make build ,make rebuild,make clean spa

   
    由此咱們如今寫第一個Makefile。其實很簡單,就是將前面的gcc命令彙總起來,放在Makefile裏。包括rm的命令。

以下: 操作系統

1 haha: #須要頂頭寫,表示一個操做的開始,用此來直接區分不一樣操做的描述範圍#自己是個註釋符號
2     gcc -Iinc -c src/learn_make.c -o obj/learn_make.o
3 #須要TAB一下,否則會當成其餘的含義,好比一個操做自己
4     gcc obj/learn_make.o -o bin/learn_make
5 heihei:
6     rm obj/*

這裏要作幾個解釋 命令行

    操做:只是個人口頭語,官方的說法叫「規則的目標」,我只是但願新手理解實際就是一個操做,並且操做裏面能夠有不少命令 依次組成依次執行,並且make一次只會對一個操做進行操做,除非其餘操做和這個操做有依賴關係。但操做一般都是有操做的結果(輸出的文件),因此叫規則 的目標
    頂頭寫:除了描述「規則的目標」外,還有不少其餘頂頭寫的事情,所以,不僅僅要頂頭寫,你還須要加上個‘:’,這樣,make就能夠知道,頂頭寫,同時存在一個‘:’則是一個操做的開始,也就是「規則的目標」。

    haha:我是在想不出什麼名詞,能說明「規則的目標」有什麼特殊的命名方式。用haha ,heihei 是但願你們理解,規則的目標的名字,並無什麼特殊約束,你愛怎麼寫怎麼寫,但存在一些潛規則和make的規矩會讓你吃苦頭,只是我在邊上 「haha,heihei,寫這個例子時,我確實在haha,heihei"。好比一般,heihei應該用 clean來實現。同時,你執行以下命令 設計

1 $make
2 $make haha
3 $make heihei



 你會發現,make沒有後面的參數時,執行了haha。不是由於haha的單詞更少。而是由於haha是第一個規則。所以,一般你須要將最經常使用的,固然 未 必是build操做,放在第一個。這樣能夠簡化你的操做。直接make就能夠。但這個最經常使用的,與你和你的小組第一直覺但願make作什麼有關係。一般程 序員之間會說「這樣這樣後,make一下」而不會解釋make what。
    你問「make what?"
    同事說:「對就是make what!"
    "make what what 啊?」
    「就是make what 啊,你what 什麼 what 啊?」
    這說明兩個問題,第一,make的第一個規則,儘量是大家小組的共識經常使用工做,第二,命名很重要。你和你的同夥"what"來「what"去,最多相互 懷疑智商問題。但若是你起名叫「love",而後和你的女同事說,記得tar -xvf後,make love一下。小心她告你性騷擾。

    如今回到haha上。繼續make haha

1 $make haha
2 $make haha


 執行兩邊,沒錯不是筆誤。你會發現,make有啥用?和普通的批處理同樣,同樣什麼都又運行了一遍。這不是make的錯。只是我挖了個坑,你不摔 一下,可 能不理解依賴怎麼實現的。make要求,對Makefile裏的依賴,在規則 ":"後面說明依賴關係。以下Makefile的清單。  

1 haha: src/learn_make.c  inc/learn_make.h
2     gcc -Iinc -c src/learn_make.c -o obj/learn_make.o
3     gcc obj/learn_make.o -o bin/learn_make
4 heihei:
5     rm obj/*

如今繼續執行

1 $make haha

哈哈,我又哈哈了。,你會發現,雖然存在依賴關係,並且個人src/learn_make.c  inc/learn_make.h沒有改動,怎麼仍是全部的都在執行啊。這不是咱們的目標。此時我須要再告訴你,make 對依賴的檢查是會判斷目標是否存在的,即使依賴的文件沒有更新,但目標(操做的輸出結果,一般就是文件)不存在,仍然會繼續執行。試想,你在 learn_make/下,實際的文件只有Makefile,沒有haha這個文件,make天然會努力的繼續工做。

    所以,若是你但願make的一個操做,是針對文件的最終造成,並且但願make能自動幫你檢測文件是否有必要改動,則你須要明確規則的目標就是文件的名 稱。不然,他如何判斷目標呢?修改爲這樣,咱們就比較爽了嗎?(須要註明,這是弱智版的說法,但願對新手能從原理上搞清楚make的工做機制)

1 learn_make: src/learn_make.c  inc/learn_make.h
2     gcc -Iinc -c src/learn_make.c -o obj/learn_make.o
3     gcc obj/learn_make.o -o bin/learn_make
4 heihei:
5     rm obj/*


    你能夠繼續執行發現仍然沒有改變。由於你忘了你的Makefile存哪了。你但願判斷的文件是否更新又存在哪裏。因此你得改爲這樣 

1 bin/learn_make: src/learn_make.c  inc/learn_make.h
2     gcc -Iinc -c src/learn_make.c -o obj/learn_make.o
3     gcc obj/learn_make.o -o bin/learn_make
4 heihei:
5    rm obj/*

你能夠再試試。我相信,絕大多數熟練使用make的朋友會說我「弱智」。實際的工程級的Makefile也不多這麼書寫。但我但願這樣的「弱智」Makefile能讓新手明確 規則的目標,一般是對文件的操做。 同時,根據上面一個例子,haha: 開頭的,你能夠知道,make的操做,首先判斷依賴的內容src/learn_make.c inc/learn_make.h是否被更新,雖然依賴即使沒有被更新,但當找不到目標時,仍然會努力嘗試建立目標。這個目標就是haha。惋惜haha 並非你最終的目標,learn_make也不是,由於存在路徑問題,因此你必須修改成bin/learn_make

    貌似如今,雖然寫法弱智,可是已經能夠開始爽make了。你能夠很HIGH的告訴不會make對人,我能夠針對src/learn_make.c  inc/learn_make.h是否修改,讓make動態的決定,是否進行後續操做。但這裏有個小BUG。你嘗試以下命令 

1 $rm obj/* //將learn_make.o刪除
2 $make

  此時,仍然提示,目標沒有被更新,而拒絕編譯。有人會說,「怕什麼,c文件若是改動,能更新就能夠了。中間文件,無關緊要。」可是這種依賴關係不明確描述時,會產生一些莫名其妙的錯誤。

    例如,你存在兩個C文件,當只有一個文件出現修改時,則另外一個文件不會進行編譯,這是你但願的目標。不然從新編譯浪費時間啊。由於你還年輕,沒有經歷過編 譯一個須要小時這個級別的系統。但當你將obj所有刪除時,那些沒有更新的C文件沒法自動生成obj。此時鏈接成可執行程序時,就會出錯。有人會說,我有 足夠的大腦知道只有兩個文件,而且不會刪除全部.o文件。可是當你的工程足夠大時,沒有嚴格規範的Makefile的依賴關係的描述,任何一個依賴關係的 遺漏,都會致使上述rebuild(須要rebuild啊,build不能自動所有更新)的問題發生。

    easy,一個目前所學到的知識告訴你,在:後面依次加上須要依賴的文件或目標就能夠了。你可能會以下修改。

1 bin/learn_make: src/learn_make.c  inc/learn_make.h obj/learn_make.o
2     gcc -Iinc -c src/learn_make.c -o obj/learn_make.o
3     gcc obj/learn_make.o -o bin/learn_make
4 heihei:
5     rm obj/*


      你run把,我能夠用已經告訴你的知識說明你的錯誤。
    :後面,確實是依賴,問題是,你的obj/learn_make.o是由src/learn_make.c生成的。你直接說明bin /learn_make須要依賴obj/learn_make.o是否更新,這是沒錯的。可是若是obj/learn_make.o不存在時,你並無告 訴make怎麼作。你可能會說,gcc -Iinc -c src/learn_make.c -o obj/learn_make.o 這不是擺明了寫出來了嗎?但你須要注意,這裏的位置,是基於make認爲bin/learn_make須要更新後,纔出現的。而在確認是否須要更新對依賴 文件進行檢查時,make就已經對obj/learn_make.o在哪的問題開始冒汗了。

    正確的作法以下,雖然個人舉例都很「弱智」但這裏重點強調的是Makefile中依賴關係。

 

1 bin/learn_make:  obj/learn_make.o
2     gcc obj/learn_make.o -o bin/learn_make
3 obj/learn_make.o: src/learn_make.c  inc/learn_make.h
4     gcc -Iinc -c src/learn_make.c -o obj/learn_make.o
5 heihei:
6     rm obj/*

此時,你再執行,或者執行後,刪除obj/*,再執行,此時會發

1 $make

現,如今的邏輯嚴謹了。並且你會發現一個規律。一般Makefile的內容,得反過來讀。 由於首先要處理的事情,一般在後面,而不是在前面,而書寫Makefile的邏輯一般是,先說果,再描述因。另外說一句,此時你實際上存在了兩個目標可操 做   

1 $make bin/learn_make
2 $make obj/learn_make.o

嘗試調換Makefile裏兩個規則的順序,再分別執行

 

1 $make

  你會對Makefile的規則有加深的認識。我就再也不廢話了。

不過做爲build命令咱們仍然存在問題。
    難道咱們make的目標,都要添加相對路徑嗎,  咱們如何經過build這個目標實現 bin/learn_make這個輸出呢?

   同時咱們不但願 make build會致使由於沒有生成build文件,而反覆作一樣的動做,如上面的錯誤?

   在設計 build這個操做時,我先談下clean,來解決第一個問題。爲說明問題,咱們繼續挖坑。在learn_work/下建立一個名爲clean的文件。

1 $:>clean //建立一個空文件,叫clean
2 $ls

咱們修改Makefile的代碼以下: 

1 bin/learn_make:   obj/learn_make.o
2    gcc obj/learn_make.o -o bin/learn_make
3 obj/learn_make.o:    src/learn_make.c  inc/learn_make.h
4    gcc -Iinc -c src/learn_make.c -o obj/learn_make.o
5 clean:
6     rm obj/*

執行

1 $make clean



沒錯,make很HIGH的告訴你,clean是最新的。由於Makefile裏的操做都是默認"假設操做的結果會產生個文件。"噹噹前目錄下,文件存在 時,就會有這種「文件沒有更改,而拒絕執行的狀況」。如今咱們在刪除clean以前不妨考慮一下,難道每次你make clean前都須要ls一下,當前目錄是否有clean文件嗎?make提供了「僞目標」幫助你省掉每次都有ls一下這麼繁瑣的事情。以下修改 Makefile 
1 bin/learn_make:   obj/learn_make.o
2     gcc obj/learn_make.o -o bin/learn_make
3 obj/learn_make.o:    src/learn_make.c  inc/learn_make.h
4     gcc -Iinc -c src/learn_make.c -o obj/learn_make.o
5 clean:
6 .PHONY:clean
7     rm obj/*

執行 

1 $make clean

呵呵,是否是發現錯誤了。這個錯誤是由於.PHONY頂頭寫了,先不談他什麼意義,.PHONY須要頂頭寫,不頂頭寫,會被認爲是一個操做的組成部 分。但 頂頭寫,又直接將clean的操做給截斷了。由於咱們說過。make認爲一個規則目標的執行,也就是個操做的全部執行部分,是須要【TAB】作前綴,當發 現一個頂頭寫的行時,則認爲命令的描述截止。此時make天然認爲 rm obj/* 不是clean的命令組成部分。

    正確作法,你能夠在clean申明以前,或總體操做命令以後描述,例如

1 bin/learn_make:   obj/learn_make.o
2     gcc obj/learn_make.o -o bin/learn_make
3 obj/learn_make.o:    src/learn_make.c  inc/learn_make.h
4    gcc -Iinc -c src/learn_make.c -o obj/learn_make.o
5 .PHONY:clean
6 clean:
7     rm obj/*

此時運行,則會出現兩種提示。正確運行或錯誤提示:「obj/下沒有文件可刪除」。如今能夠簡單的說一下.PHONY的做用。就是強制說明,後面的 clean是不存在輸出文件的。因此clean此時變成了「僞目標」也就是「僞操做」,「僞」只是說明他不會生成一個文件,所以,不會去考慮當前路徑下, 是否要判斷同名文件存在與否或是是否存在依賴,而始終是埋頭苦幹。此時你能夠刪除clean這個文件了。當你確認.PHONY做用以後。

1 $rm clean

可能有小朋友就琢磨了,若是是個僞目標,能夠迴避檢查文件的方式,那麼我把bin/learn_make改爲build,這樣make build實際就能夠處理bin/learn_make了。

    以下

1 .PHONY:build
2 build:   obj/learn_make.o
3     gcc obj/learn_make.o -o bin/learn_make
4 obj/learn_make.o:    src/learn_make.c  inc/learn_make.h
5     gcc -Iinc -c src/learn_make.c -o obj/learn_make.o
6 .PHONY:clean
7 clean:
8     rm obj/*
1 $make build
    一切正常,若是以前你make clean了。再執行
    $make build

    一切不正常,由於,又跑了一次。(我很是建議新學者,將全部錯誤的方式都操做一邊)。由於這樣作,雖然迴避了build須要檢測當前目錄下build的問 題,但仍然解決不了bin/learn_make是否存在,是否須要依賴性檢測的問題。因此正確作法應該以下

1 .PHONY:build
2 build:  bin/learn_make
3 bin/learn_make: obj/learn_make.o
4     gcc obj/learn_make.o -o bin/learn_make
5 obj/learn_make.o:    src/learn_make.c  inc/learn_make.h
6    gcc -Iinc -c src/learn_make.c -o obj/learn_make.o
7 .PHONY:clean
8 clean:
9     rm obj/*



    你執行兩次make build 

1 $make build
2 $make build

沒問題了吧。這是由於,咱們先用了.PHONY,讓build成爲一個不須要檢測文件僞目標。但同時,咱們將 build的實際輸出文件做爲一個依賴,讓build須要每次都進行檢查是否須要更新。同時不要被前面的僞目標clean誤導,認爲僞目標必定埋頭苦幹, 那是基於clean沒有依賴,而build存在依賴,當依賴發現不須要更新,build也就不會埋頭苦幹了。

    增補完整的包括rebuild的內容以下 

01 .PHONY:build
02 build:  bin/learn_make
03 bin/learn_make: obj/learn_make.o
04     gcc obj/learn_make.o -o bin/learn_make
05 obj/learn_make.o:    src/learn_make.c  inc/learn_make.h
06     gcc -Iinc -c src/learn_make.c -o obj/learn_make.o
07 rebuild: build clean
08 .PHONY:clean
09 clean:
10     rm obj/*

你們執行一下

1 $make rebuild
    哈,會出現兩種可能的錯。一種是隻有rm obj/*被執行,另外一種,先gcc了東西,隨後rm obj/*。不是我故意喜歡挖坑讓大家跳,由於個人職業經歷發現,尋找邊界錯誤臨界點更容易理解系統運行原理,這些錯誤都是我在琢磨 make的工做原理中本身挖本身跳的坑。上面這個錯誤,可讓你明確兩個道理。
    1,make對依賴的檢測,是從左到右,有順序的。你與其記住這句話,不如記住上面這個失敗的例子。
    二、make呼呼的向下run不表明正確。你的Makefile的邏輯關聯很重要。
    再次,分析一下兩種錯的緣由。
    只執行了rm obj/*,這是由於bin/learn_make通過檢測,沒有須要更新的。因此make直接無視,飄了過去。
    當因爲src/ inc/ 下面的源碼被改動了。或者obj/learn_make.o 或則bin/learn_make的 o被刪除了。make認爲須要從新更新bin/learn_make,所以執行了gcc部分。
    固然不管哪一種錯,最終都會執行clean ,你的 obj/下 o文件沒有了。

    所以,正確的作法以下:

01 .PHONY:build
02 build:  bin/learn_make
03 bin/learn_make: obj/learn_make.o
04     gcc obj/learn_make.o -o bin/learn_make
05 obj/learn_make.o:    src/learn_make.c  inc/learn_make.h
06    gcc -Iinc -c src/learn_make.c -o obj/learn_make.o
07 rebuild: clean build
08 .PHONY:clean
09 clean:
10     rm obj/*

     此處但願你們理解一個概念。看上去rebuild是在調用了clean 和build的函數。沒錯你這個理解是能夠。但你須要帶着更新檢測的思惟,這是make強大之處。真是由於存在更新檢測,你就要注意觀測clean ,和build是否爲「僞目標」,這對理解別人的Makefile和本身書寫Makefile都是有好處的。是否存在僞目標的定義,對於這個依賴關係的推 導會有不一樣的結果。

    回到最近的這個錯誤,clean build的順序寫反的錯誤。甚至可能有些新手發現並無什麼結果性的錯誤。由於我只要make rebuild兩邊,始終能獲得最新的bin/learn_make。由於當目前的全部依賴文件都沒有更新時,第一邊不會GCC,但會rm,由此致使第二 次由於obj/*.o都不存在,全部再次所有重編。
    這裏隱含了一個事實,你clean存在一個漏洞,只刪除了o。沒有刪除bin下的learn_make。致使莫名其妙的新手會認爲,make 弱智,須要兩邊make rebuild才能真正實現最新版本的執行文件。或者說,這個Makefile(若是它很大,你沒有信心去理解它)有問題,你須要執行兩邊才能確保嚴格正 確(其實更本就是不正確),甚至有人會去開罵make或GCC甚至是linux的版本問題,固然也可能會考慮鍵盤是否老化了等各類奇怪的責任者。實際上是 Makefile自身的錯誤+錯誤,致使兩次也獲得了最終結果。這樣的錯誤類型,在不少粗製濫造的應用軟件裏很常見,而用戶只能自發的想對策。所以你須要 修改Makefile 以下 
01 .PHONY:build
02 build:  bin/learn_make
03 bin/learn_make: obj/learn_make.o
04     gcc obj/learn_make.o -o bin/learn_make
05 obj/learn_make.o:    src/learn_make.c  inc/learn_make.h
06     gcc -Iinc -c src/learn_make.c -o obj/learn_make.o
07 rebuild: clean build
08 .PHONY:clean
09 clean:
10     rm obj/*
11     rm bin/*

此時你開始執行以下命令

1 $make  //build一下,確保obj/learn_make.o bin/learn_make都存在。
2 $make //哦。make 不執行了。好爽
3 $make clean //清除全部的生成文件
4 $make //哦,又爽了,由於又開始工做了。
5 $make rebuild //哦,爽完再爽,rebuild也行了。

沒錯。一切都讓你爽了。可是你嘗試以下命令 

1 $rm obj/* //沒錯,只刪掉obj/*下的東西。
2 $make rebuild //咱們先clean,再build

必定錯了。make異常退出了。當你準備罵make不智能時,其實make已經準備好了方案。就是以下修改 

01 .PHONY:build
02 build:  bin/learn_make
03 bin/learn_make: obj/learn_make.o
04     gcc obj/learn_make.o -o bin/learn_make
05 obj/learn_make.o:    src/learn_make.c  inc/learn_make.h
06     gcc -Iinc -c src/learn_make.c -o obj/learn_make.o
07 rebuild: clean build
08 .PHONY:clean
09 clean:
10     -rm obj/*
11     -rm bin/*

此時再試一下

1 $make rebuild

雖然仍然提示rm obj/*存在錯誤。可是會繼續作完其餘的事情。夠人性化吧。由此,咱們的一個完整簡單的弱智版本Makefile處理完畢了。

    不過之因此最後才說 ‘-’這個由於工具沒有問題,但操做不當就會有問題。必定要預防一些存在依賴關係的操做被你加上‘-’,這時你不少事情都會白作。一般只有你肯定,當該操 做即使出錯,對你的總體make工做沒有任何影響時,你才能使用 ‘-’。make的價值,不在於普通腳本的選擇性批處理命令,而在於每一個動做的相互依賴關係的檢測(一般是經過文件的依賴關係),你強迫忽視某個動做是否 錯誤,實際上在等同修改你的依賴關係(若是這個動做確實存在依賴關係的狀況下)。

相關文章
相關標籤/搜索