1. 程式人生 > >makefile詳解 make 的執行 二十三

makefile詳解 make 的執行 二十三

make 的執行
——————

一般來說,最簡單的就是直接在命令列下輸入make命令,make命令會找當前目錄的makefile來執行,一切都是自動的。但也有時你也許只想讓make重編譯某些檔案,而不是整個工程,而又有的時候你有幾套編譯規則,你想在不同的時候使用不同的編譯規則,等等。本章節就是講述如何使用make命令的。

一、make的退出碼

make命令執行後有三個退出碼:

    0 —— 表示成功執行。
    1 —— 如果make執行時出現任何錯誤,其返回1。
    2 —— 如果你使用了make的“-q”選項,並且make使得一些目標不需要更新,那麼返回2。

Make的相關引數我們會在後續章節中講述。


二、指定Makefile

前面我們說過,GNU make找尋預設的Makefile的規則是在當前目錄下依次找三個檔案——“GNUmakefile”、“makefile”和“Makefile”。其按順序找這三個檔案,一旦找到,就開始讀取這個檔案並執行。

當前,我們也可以給make命令指定一個特殊名字的Makefile。要達到這個功能,我們要使用make的“-f”或是“--file”引數(“--makefile”引數也行)。例如,我們有個makefile的名字是“hchen.mk”,那麼,我們可以這樣來讓make來執行這個檔案:

    make –f hchen.mk

如果在make的命令列是,你不只一次地使用了“-f”引數,那麼,所有指定的makefile將會被連在一起傳遞給make執行。


三、指定目標

一般來說,make的最終目標是makefile中的第一個目標,而其它目標一般是由這個目標連帶出來的。這是make的預設行為。當然,一般來說,你的makefile中的第一個目標是由許多個目標組成,你可以指示make,讓其完成你所指定的目標。要達到這一目的很簡單,需在make命令後直接跟目標的名字就可以完成(如前面提到的“make clean”形式)

任何在makefile中的目標都可以被指定成終極目標,但是除了以“-”打頭,或是包含了“=”的目標,因為有這些字元的目標,會被解析成命令列引數或是變數。甚至沒有被我們明確寫出來的目標也可以成為make的終極目標,也就是說,只要make可以找到其隱含規則推導規則,那麼這個隱含目標同樣可以被指定成終極目標。

有一個make的環境變數叫“MAKECMDGOALS”,這個變數中會存放你所指定的終極目標的列表,如果在命令列上,你沒有指定目標,那麼,這個變數是空值。這個變數可以讓你使用在一些比較特殊的情形下。比如下面的例子:

    sources = foo.c bar.c
    ifneq ( $(MAKECMDGOALS),clean)
    include $(sources:.c=.d)
    endif

基於上面的這個例子,只要我們輸入的命令不是“make clean”,那麼makefile會自動包含“foo.d”和“bar.d”這兩個makefile。

使用指定終極目標的方法可以很方便地讓我們編譯我們的程式,例如下面這個例子:

    .PHONY: all
    all: prog1 prog2 prog3 prog4

從這個例子中,我們可以看到,這個makefile中有四個需要編譯的程式——“prog1”, “prog2”, “prog3”和 “prog4”,我們可以使用“make all”命令來編譯所有的目標(如果把all置成第一個目標,那麼只需執行“make”),我們也可以使用“make prog2”來單獨編譯目標“prog2”。

即然make可以指定所有makefile中的目標,那麼也包括“偽目標”,於是我們可以根據這種性質來讓我們的makefile根據指定的不同的目標來完成不同的事。在Unix世界中,軟體釋出時,特別是GNU這種開源軟體的釋出時,其makefile都包含了編譯、安裝、打包等功能。我們可以參照這種規則來書寫我們的makefile中的目標。

     “all”
        這個偽目標是所有目標的目標,其功能一般是編譯所有的目標。
     “clean”
        這個偽目標功能是刪除所有被make建立的檔案。
     “install”
        這個偽目標功能是安裝已編譯好的程式,其實就是把目標執行檔案拷貝到指定的目標中去。
     “print”
        這個偽目標的功能是例出改變過的原始檔。
     “tar”
        這個偽目標功能是把源程式打包備份。也就是一個tar檔案。
     “dist”
        這個偽目標功能是建立一個壓縮檔案,一般是把tar檔案壓成Z檔案。或是gz檔案。
     “TAGS”
        這個偽目標功能是更新所有的目標,以備完整地重編譯使用。
     “check”和“test”
        這兩個偽目標一般用來測試makefile的流程。

當然一個專案的makefile中也不一定要書寫這樣的目標,這些東西都是GNU的東西,但是我想,GNU搞出這些東西一定有其可取之處(等你的UNIX下的程式檔案一多時你就會發現這些功能很有用了),這裡只不過是說明了,如果你要書寫這種功能,最好使用這種名字命名你的目標,這樣規範一些,規範的好處就是——不用解釋,大家都明白。而且如果你的makefile中有這些功能,一是很實用,二是可以顯得你的makefile很專業(不是那種初學者的作品)。


四、檢查規則

有時候,我們不想讓我們的makefile中的規則執行起來,我們只想檢查一下我們的命令,或是執行的序列。於是我們可以使用make命令的下述引數:

    “-n”
    “--just-print”
    “--dry-run”
    “--recon”
    不執行引數,這些引數只是列印命令,不管目標是否更新,把規則和連帶規則下的命令打印出來,但不執行,這些引數對於我們除錯makefile很有用處。

    “-t”
    “--touch”
    這個引數的意思就是把目標檔案的時間更新,但不更改目標檔案。也就是說,make假裝編譯目標,但不是真正的編譯目標,只是把目標變成已編譯過的狀態。

    “-q”
    “--question”
    這個引數的行為是找目標的意思,也就是說,如果目標存在,那麼其什麼也不會輸出,當然也不會執行編譯,如果目標不存在,其會打印出一條出錯資訊。

    “-W <file>;”
    “--what-if=<file>;”
    “--assume-new=<file>;”
    “--new-file=<file>;”
    這個引數需要指定一個檔案。一般是是原始檔(或依賴檔案),Make會根據規則推導來執行依賴於這個檔案的命令,一般來說,可以和“-n”引數一同使用,來檢視這個依賴檔案所發生的規則命令。

另外一個很有意思的用法是結合“-p”和“-v”來輸出makefile被執行時的資訊(這個將在後面講述)。


五、make的引數

下面列舉了所有GNU make 3.80版的引數定義。其它版本和產商的make大同小異,不過其它產商的make的具體引數還是請參考各自的產品文件。

“-b”
“-m”
這兩個引數的作用是忽略和其它版本make的相容性。

“-B”
“--always-make”
認為所有的目標都需要更新(重編譯)。

“-C <dir>;”
“--directory=<dir>;”
指定讀取makefile的目錄。如果有多個“-C”引數,make的解釋是後面的路徑以前面的作為相對路徑,並以最後的目錄作為被指定目錄。如:“make –C ~hchen/test –C prog”等價於“make –C ~hchen/test/prog”。

“—debug[=<options>;]”
輸出make的除錯資訊。它有幾種不同的級別可供選擇,如果沒有引數,那就是輸出最簡單的除錯資訊。下面是<options>;的取值:
    a —— 也就是all,輸出所有的除錯資訊。(會非常的多)
    b —— 也就是basic,只輸出簡單的除錯資訊。即輸出不需要重編譯的目標。
    v —— 也就是verbose,在b選項的級別之上。輸出的資訊包括哪個makefile被解析,不需要被重編譯的依賴檔案(或是依賴目標)等。
    i —— 也就是implicit,輸出所以的隱含規則。
    j —— 也就是jobs,輸出執行規則中命令的詳細資訊,如命令的PID、返回碼等。
    m —— 也就是makefile,輸出make讀取makefile,更新makefile,執行makefile的資訊。

“-d”
相當於“--debug=a”。

“-e”
“--environment-overrides”
指明環境變數的值覆蓋makefile中定義的變數的值。

“-f=<file>;”
“--file=<file>;”
“--makefile=<file>;”
指定需要執行的makefile。

“-h”
“--help”
顯示幫助資訊。

“-i”
“--ignore-errors”
在執行時忽略所有的錯誤。

“-I <dir>;”
“--include-dir=<dir>;”
指定一個被包含makefile的搜尋目標。可以使用多個“-I”引數來指定多個目錄。

“-j [<jobsnum>;]”
“--jobs[=<jobsnum>;]”
指同時執行命令的個數。如果沒有這個引數,make執行命令時能執行多少就執行多少。如果有一個以上的“-j”引數,那麼僅最後一個“-j”才是有效的。(注意這個引數在MS-DOS中是無用的)

“-k”
“--keep-going”
出錯也不停止執行。如果生成一個目標失敗了,那麼依賴於其上的目標就不會被執行了。

“-l <load>;”
“--load-average[=<load]”
“—max-load[=<load>;]”
指定make執行命令的負載。

“-n”
“--just-print”
“--dry-run”
“--recon”
僅輸出執行過程中的命令序列,但並不執行。

“-o <file>;”
“--old-file=<file>;”
“--assume-old=<file>;”
不重新生成的指定的<file>;,即使這個目標的依賴檔案新於它。

“-p”
“--print-data-base”
輸出makefile中的所有資料,包括所有的規則和變數。這個引數會讓一個簡單的makefile都會輸出一堆資訊。如果你只是想輸出資訊而不想執行makefile,你可以使用“make -qp”命令。如果你想檢視執行makefile前的預設變數和規則,你可以使用“make –p –f /dev/null”。這個引數輸出的資訊會包含著你的makefile檔案的檔名和行號,所以,用這個引數來除錯你的makefile會是很有用的,特別是當你的環境變數很複雜的時候。

“-q”
“--question”
不執行命令,也不輸出。僅僅是檢查所指定的目標是否需要更新。如果是0則說明要更新,如果是2則說明有錯誤發生。

“-r”
“--no-builtin-rules”
禁止make使用任何隱含規則。

“-R”
“--no-builtin-variabes”
禁止make使用任何作用於變數上的隱含規則。

“-s”
“--silent”
“--quiet”
在命令執行時不輸出命令的輸出。

“-S”
“--no-keep-going”
“--stop”
取消“-k”選項的作用。因為有些時候,make的選項是從環境變數“MAKEFLAGS”中繼承下來的。所以你可以在命令列中使用這個引數來讓環境變數中的“-k”選項失效。

“-t”
“--touch”
相當於UNIX的touch命令,只是把目標的修改日期變成最新的,也就是阻止生成目標的命令執行。

“-v”
“--version”
輸出make程式的版本、版權等關於make的資訊。

“-w”
“--print-directory”
輸出執行makefile之前和之後的資訊。這個引數對於跟蹤巢狀式呼叫make時很有用。

“--no-print-directory”
禁止“-w”選項。

“-W <file>;”
“--what-if=<file>;”
“--new-file=<file>;”
“--assume-file=<file>;”
假定目標<file>;需要更新,如果和“-n”選項使用,那麼這個引數會輸出該目標更新時的執行動作。如果沒有“-n”那麼就像執行UNIX的“touch”命令一樣,使得<file>;的修改時間為當前時間。

“--warn-undefined-variables”
只要make發現有未定義的變數,那麼就輸出警告資訊。

相關推薦

makefile make執行 十三

make 的執行 —————— 一般來說,最簡單的就是直接在命令列下輸入make命令,make命令會找當前目錄的makefile來執行,一切都是自動的。但也有時你也許只想讓make重編譯某些檔案,而不是整個工程,而又有的時候你有幾套編譯規則,你想在不同的時候使用不同的編譯規則,等等。本章節就是講述如何使用ma

makefile 隱含規則 十四

隱含規則 ———— 在我們使用Makefile時,有一些我們會經常使用,而且使用頻率非常高的東西,比如,我們編譯C/C++的源程式為中間目標檔案(Unix下是[.o]檔案,Windows下是[.obj]檔案)。本章講述的就是一些在Makefile中的“隱含的”,早先約定了的,不需要我們再寫出來的規則。 “隱含

makefile 條件判斷

使用條件判斷 —————— 使用條件判斷,可以讓make根據執行時的不同情況選擇不同的執行分支。條件表示式可以是比較變數的值,或是比較變數和常量的值。 一、示例 下面的例子,判斷$(CC)變數是否“gcc”,如果是的話,則使用GNU函式編譯目標。     libs_for_gcc = -lgnu     no

makefile 使用make更新函式庫檔案(結束) 十六

使用make更新函式庫檔案 ——————————— 函式庫檔案也就是對Object檔案(程式編譯的中間檔案)的打包檔案。在Unix下,一般是由命令"ar"來完成打包工作。 一、函式庫檔案的成員 一個函式庫檔案由多個檔案組成。你可以以如下格式指定函式庫檔案及其組成:     archive(member) 這個

makefile 函式 foreach if call origin shell 控制make函式

四、foreach 函式   foreach函式和別的函式非常的不一樣。因為這個函式是用來做迴圈用的,Makefile中的foreach函式幾乎是仿照於Unix標準Shell(/bin/sh)中的for語句,或是C-Shell(/bin/csh)中的foreach語句而構建的。它的語法是:       $(f

MAKEFILE 多目標 靜態模式 十三

六、多目標 Makefile的規則中的目標可以不止一個,其支援多目標,有可能我們的多個目標同時依賴於一個檔案,並且其生成的命令大體類似。於是我們就能把其合併起來。當然,多個目標的生成規則的執行命令是同一個,這可能會可我們帶來麻煩,不過好在我們的可以使用一個自動化變數“[email protected

makefile 定義模式規則 十五

五、定義模式規則 你可以使用模式規則來定義一個隱含規則。一個模式規則就好像一個一般的規則,只是在規則中,目標的定義需要有"%"字元。"%"的意思是表示一個或多個任意字元。在依賴目標中同樣可以使用"%",只是依賴目標中的"%"的取值,取決於其目標。 有一點需要注意的是,"%"的展開發生在變數和函式的展開之後,變

makefile 函式 字串 檔名 十一

在Makefile中可以使用函式來處理變數,從而讓我們的命令或是規則更為的靈活和具有智慧。make所支援的函式也不算很多,不過已經足夠我們的操作了。函式呼叫後,函式的返回值可以當做變數來使用。 一、函式的呼叫語法 函式呼叫,很像變數的使用,也是以“$”來標識的,其語法如下:     $(<functio

SpringBoot開發(十) -- SpringBoot中執行定時任務

最近在專案中一直使用定時任務完成一些業務邏輯,比如天氣介面的資料獲取,定時傳送簡訊,郵件。以及商城中每天使用者的限額,定時自動收貨等等。定時器在專案中是我們常常會使用到的一個手段,今天我們就來看下在SpringBoot中如何整合定時任務。 定時任務在Sprin

微信和支付寶支付模式及實現

配置 其余 logs https 朋友 一個 target 多租戶 對比   繼上篇《微信和支付寶支付模式詳解及實現》到現在已經有半年時間了,這期間不少朋友在公號留言支付相關的問題,最近正好也在處理公司支付相關的對接,打算寫這篇來做一個更進一步的介紹,同時根據主要的幾個支付

tomcat中server.xml配置(轉載)(

lin power servlet容器 secure redirect tar 屬性 限制 man 轉載自:https://www.cnblogs.com/starhu/p/5599773.html 一:<Connector>元素 由Connector接口定義.

JDBC系列()之加載驅動

red mar mys ons try path 替換 host man ---[來自我的CSDN博客](http://blog.csdn.net/weixin_37139197/article/details/78838091)--- ??在JDBC詳解系列(一)之流程中

Zookeeper-基礎(

ima con 下一個序列 新的 簡單的 pos 列表 之前 集中 在深入了解ZooKeeper的運作之前,讓我們來看看ZooKeeper的基本概念。我們將在本章中討論以下主題: Architecture(架構) Hierarchical namespace(層次命名空間

makefile

makefile原文鏈接:https://blog.csdn.net/qq_38646470/article/details/79917494專欄鏈接:https://blog.csdn.net/column/details/20028.html    或許很多Wino

JAVA常用集合框架用法基礎篇之Colletion子介面List

接著上一篇,接著講講集合的知識。上一篇講了Collection介面。它可以說是集合的祖先了,我們這一篇就說說它的子孫們。 一、Collection的子介面 List:有序(存入和取出的順序一致),元素都有索引(即角標),元素可以重複。 Set:元素不能重複,無序的。 首先講講L

Hadoop偽分佈安裝+MapReduce執行原理+基於MapReduce的KNN演算法實現

本篇部落格將圍繞Hadoop偽分佈安裝+MapReduce執行原理+基於MapReduce的KNN演算法實現這三個方面進行敘述。 (一)Hadoop偽分佈安裝 1、簡述Hadoop的安裝模式中–偽分佈模式與叢集模式的區別與聯絡. Hadoop的安裝方式有三種:本地模式,偽分佈模式

Python程序、執行緒、協程執行效能、效率(tqdm)

多程序實踐——multiprocessing 筆者最近在實踐多程序發現multiprocessing,真心很好用,不僅加速了運算,同時可以GPU呼叫,而且互相之間無關聯,這樣可以很放心的進行計算。 譬如(參考:多程序): from multiprocessing import Pool

sip協議 系列(

Sip的核心請求訊息 INVITE、ACK、OPTIONS、BYE、CANCEL 和 REGISTER INVITE • INVITE可以在郵件正文中包含主叫方的媒體資訊。 • 如果INVITE已經接收到成功響應(2xx)或已經發送ACK,則會話被認為是建立的。 • 成功的INVIT

Linux下多資料夾編寫Makefile

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

【linux】Valgrind工具集(十):DHAT:動態堆分析器

一、概述 DHAT動態堆分析器。Massif(堆分析器)是在程式結束後輸出分析結果,而DHAT是實時輸出結果,所以叫做動態堆分析器。Massif只記錄堆記憶體的申請和釋放,DHAT還會分析堆空間的使用率、使用週期等資訊。 DHAT的功能:它首先記錄在堆上分配的塊,通過分析每次記憶體訪