Makefile-4-書寫命令


前言

  • 本筆記主要記錄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》