Makefile-4-書寫命令

李柱明發表於2020-10-14


前言

  • 本筆記主要記錄Makefile一些概念要點。

概念

Chapter 4:書寫命令

  • 每條規則中的命令和作業系統 Shell 的命令列是一致的。
  • 每條命令必須以 Tab 鍵開頭,除非,命令是緊跟在依賴規則後面的分號後的。
  • make 一般是使用環境變數 SHELL 中所定義的系統 Shell 來執行命令,預設情況下是 /bin/sh —— UNIX 的標準 Shell 解釋執行的。

4.1 顯示命令

  • 是否顯示命令
    • 在命令列前使用 @ 字元,那麼該命令將不被make顯示出來
  • 只顯示,不執行
    • make 執行時,帶入 make 引數 -n--just-print
    • 作用:一般用於除錯,檢視make執行的順序。
  • 全面禁止,命令的顯示:
    • make 引數 -s--silent--quiet 則是全面禁止命令的顯示。

4.2 命令執行 *

  • 當依賴目標新於目標時,make 會一條一條的執行其後的命令。
  • 如果要讓上一條命令的結果應用在下一條命令時,你應該使用分號分隔這兩條命令。
    • 例子1:輸出為:【當前目錄路徑】
exec:
cd /home/lss
pwd
* 例子2:輸出為:/home/lss
exec:
cd /home/lss; pwd
  • 命令解析器尋找順序
    • 首先,在 SHELL 所指定的路徑中找尋 --> 在當前碟符中的當前目錄中尋找 --> 在 PATH 環境變數中所定義的所有路徑中尋找。
    • MS-DOS 中,如果定義的命令直譯器沒有找到,其會給你的命令直譯器加上諸如 .exe 、.com 、.bat 、.sh 等字尾。

4.3 命令出錯

  • 每當命令執行完後,make 會檢測每個命令的返回碼,碼為零則成功。
  • 忽略命令失敗
    • 方法一:減號
      • 在命令前( Tab 鍵後)加上一個減號 - 即可。
    • 方法二:全域性(分兩種)
      • make 加上 -i 或是 --ignore-errors 引數
      • 果一個規則是以 .IGNORE 作為目標的,該規則中的所有命令將會忽略錯誤。
  • 命令失敗,但只終止當前規則
    • make 的引數的是 -k 或是 --keep-going
      • 意思是:某規則中的命令出錯了,就終止該規則的執行,但繼續執行其它規則。

4.4 巢狀執行 make

  • 總控 Makefile + 各個子目錄 Makefile。
  • 父級 Makefile
    • -C 切換到其它目錄
subsystem:
    make -C subdir # 或者:cd subdir && make
  • 傳遞變數到下級,宣告方法:

    • export <variable ...>;
    • 注:注意 等號:(意思是 export 後,就不是 延時變數)
      • export variable = value 等價於 export variable := value
      • 傳遞時預設不覆蓋,加上 -e 即可覆蓋下級重新賦值的變數
  • 不想讓該變數傳遞到下級,宣告方法:

    • unexport <variable ...>;
  • 注意兩個變數 *

    • SHELLMAKEFLAGS 這兩個變數不管你是否 export,其總是要傳遞到下層 Makefile 中。
    • MAKEFLAGS
      • 包含了 make 的引數資訊。
    • 不想讓 MAKEFLAGS 往下傳遞的做法
subsystem:
   cd subdir && $(MAKE) MAKEFLAGS=
  • 不往下傳遞的 引數

    • make 命令中 -C , -f , -h, -o-W 引數是不往下傳遞的。
  • 資訊列印 *

    • -w 或是 --print-directory 會在 make 的過程中輸出目前的工作目錄。如:執行 make -w
# 進入該目錄時會答應如下資訊
make: Entering directory `/home/hchen/gnu/make'.

# 在完成下層 make 後離開目錄時:
make: Leaving directory `/home/hchen/gnu/make'
* 當你使用 **-C** 引數來指定 **make** 下層 **Makefile** 時,**-w** 會被自動開啟的。如果引數中有 **-s(--slient)**或是 **--no-print-directory** ,那麼,**-w** 總是失效的。

4.5 定義命令包

  • 相當於 C 中的函式。
  • 語法以 define 開始,以 endef 結束。
  • 例子:
    • run-yacc
      • 命令包名字
    • 中間兩句就是 命令包內容
define run-yacc
yacc $(firstword $^)
mv y.tab.c $@
endef
  • 呼叫方法
    • 採用 $
foo.c:foo.y
    $(run-yacc)

參考

  • 《GUN Makefile》
  • 《跟我一起寫Makefile》

相關文章