Makefile書寫命令相關內容

chenwr2018發表於2019-03-05

一、命令顯示

1.@關閉命令的回顯

2.make帶入引數“-n”或“--just-print”,只是顯示命令,但不會執行命令,這個功能方便除錯 Makefile。

3.make 引數“-s”或“--slient”全面禁止命令的顯示。

二、命令執行

make 逐條執行其後的命令。 如果打算上一條命令結果應用到下一條命令,需要把要執行的命令寫在同一行使用分號;隔開。

test:
    cd ./path1
    pwd
複製程式碼

執行結果:

root@chenwr-pc:/home/workspace/my_workspace/study/makefile# make test
cd ./path1
pwd
/home/workspace/my_workspace/study/makefile
複製程式碼
test:
    cd ./path1;pwd
複製程式碼

執行結果:

root@chenwr-pc:/home/workspace/my_workspace/study/makefile# make test
cd ./path1;pwd
/home/workspace/my_workspace/study/makefile/path1
複製程式碼

三、命令出錯

makefile使用mkdir建立目錄時,不存在時makefile正常執行,但是目錄存在則無法mkdir時出現報錯,這個並不應該影響到後面命令的執行。

test:
    @mkdir path1
    @echo continue
複製程式碼

執行結果:

root@chenwr-pc:/home/workspace/my_workspace/study/makefile# make test
mkdir: cannot create directory ‘path1’: File exists
make: *** [test] Error 1
複製程式碼

命令執行錯誤直接終止。 解決辦法 (1)Makefile命令列前加一個減號- (2)全域性的辦法,給 make 加上“-i”或是“--ignore-errors”引數。

test:
    -@mkdir path1
    @echo continue
複製程式碼

執行結果:

root@chenwr-pc:/home/workspace/my_workspace/study/makefile# make test
mkdir: cannot create directory ‘path1’: File exists
make: [test] Error 1 (ignored)
continue
複製程式碼
root@chenwr-pc:/home/workspace/my_workspace/study/makefile# make test --ignore-errors
mkdir: cannot create directory ‘path1’: File exists
make: [test] Error 1 (ignored)
continue
複製程式碼

如果一個規則是以“.IGNORE”作為目標的,那麼這個規則中的所有命令將會忽略錯誤。

.IGNORE: test
test:
    @mkdir path1
    @cat no_exist_file
    @echo continue
複製程式碼

執行結果:

root@chenwr-pc:/home/workspace/my_workspace/study/makefile# make test
mkdir: cannot create directory ‘path1’: File exists
make: [test] Error 1 (ignored)
cat: no_exist_file: No such file or directory
make: [test] Error 1 (ignored)
continue
複製程式碼

四、巢狀執行make

根據功能和模組將相關的檔案放置在不同的資料夾中,每個資料夾中單獨建立一個Makefile來進行管理維護。最外層有個總控Makefile,可以實現全編譯。

定義$(MAKE)巨集變數的意思是,定義成一個變數便於make引數傳遞,利於維護。

subdir = ./path1
test:
    cd $(subdir) && $(MAKE)
複製程式碼

執行結果:

root@chenwr-pc:/home/workspace/my_workspace/study/makefile# make test
cd ./path1 && make
make[1]: Entering directory `/home/workspace/my_workspace/study/makefile/path1'
gcc -c hello.c
make[1]: Leaving directory `/home/workspace/my_workspace/study/makefile/path1'
複製程式碼

總控Makefile中的引數要傳遞給子目錄下的Makefile。 只需在總控Makefile的變數前新增export即可,相反如果特定變數不想傳遞下去則使用unexport。

總控Makefile

export subdir = ./path1
test:
    cd $(subdir) && $(MAKE)
複製程式碼

子目錄path1中的Makefile

hello.o: hello.c
    gcc -c hello.c
    echo $(subdir)
複製程式碼

執行結果:

root@chenwr-pc:/home/workspace/my_workspace/study/makefile# make test
cd ./path1 && make
make[1]: Entering directory `/home/workspace/my_workspace/study/makefile/path1'
gcc -c hello.c
echo ./path1
./path1
make[1]: Leaving directory `/home/workspace/my_workspace/study/makefile/path1'
複製程式碼

如果很多變數要傳遞,只需要新增export關鍵字,後面不需要跟變數名。

export 
subdir = ./path1
other = 666
test:
    cd $(subdir) && $(MAKE) && rm *.o
複製程式碼

執行結果:

root@chenwr-pc:/home/workspace/my_workspace/study/makefile# make test
cd ./path1 && make && rm *.o
make[1]: Entering directory `/home/workspace/my_workspace/study/makefile/path1'
gcc -c hello.c
./path1
666
make[1]: Leaving directory `/home/workspace/my_workspace/study/makefile/path1'
複製程式碼

注意: SHELL、MAKEFLAGE這兩個變數比較特殊,不管是否export它們都會傳遞到子目錄Makefile中。MAKEFLAGE還是系統級別的環境變數。

總控Makefile定義的變數傳遞到下級Makefile中,如果下級Makefile有定義同名的變數。下級Makefile變數值不會被覆蓋。如果想要覆蓋,執行makefile的時傳遞引數-e -e, --environment-overrides Environment variables override makefiles. 覆蓋makefile環境變數。

make的引數還蠻多的

root@chenwr-pc:/home/workspace/my_workspace/study/makefile# make --help
Usage: make [options] [target] ...
Options:
  -b, -m                      Ignored for compatibility.
                              (忽略的相容性)
  -B, --always-make           Unconditionally make all targets.
                              (無條件完成所有目標)
  -C DIRECTORY, --directory=DIRECTORY
                              Change to DIRECTORY before doing anything.
                              (在做任何事情之前切換到目錄)
  -d                          Print lots of debugging information.
                              (列印大量除錯資訊)
  --debug[=FLAGS]             Print various types of debugging information.
                              (列印各種型別的除錯資訊)
  -e, --environment-overrides
                              Environment variables override makefiles.
                              (環境變數覆蓋makefile)
  -f FILE, --file=FILE, --makefile=FILE
                              Read FILE as a makefile.
                              (將檔案讀取為makefile)
  -h, --help                  Print this message and exit.
                              (列印該資訊並退出)
  -i, --ignore-errors         Ignore errors from commands.
                              (忽略來自命令的錯誤)
  -I DIRECTORY, --include-dir=DIRECTORY
                              Search DIRECTORY for included makefiles.
                              (搜尋包含makefile的目錄)
  -j [N], --jobs[=N]          Allow N jobs at once; infinite jobs with no arg.
                              (一次允許N個作業;沒有引數的無限作業)
  -k, --keep-going            Keep going when some targets can't be made.
                              (當一些目標無法達成時,繼續執行)
  -l [N], --load-average[=N], --max-load[=N]
                              Don't start multiple jobs unless load is below N.
                              (除非負載小於N,否則不要啟動多個作業)
  -L, --check-symlink-times   Use the latest mtime between symlinks and target.
                              (使用符號連結和目標之間的最新時間)
  -n, --just-print, --dry-run, --recon
                              Don't actually run any commands; just print them.
                              (不要實際執行任何命令;只是列印)
  -o FILE, --old-file=FILE, --assume-old=FILE
                              Consider FILE to be very old and don't remake it.
                              (考慮檔案是非常舊的,不要重新建立)
  -p, --print-data-base       Print make's internal database.
                              (列印make的內部資料庫)
  -q, --question              Run no commands; exit status says if up to date.
                              (執行任何命令;退出狀態表示是否最新)
  -r, --no-builtin-rules      Disable the built-in implicit rules.
                              (禁用內建的隱式規則)
  -R, --no-builtin-variables  Disable the built-in variable settings.
                              (禁用內建變數設定)
  -s, --silent, --quiet       Don't echo commands.
                              (不要echo命令)
  -S, --no-keep-going, --stop
                              Turns off -k.
  -t, --touch                 Touch targets instead of remaking them.
                              (觸控目標,而不是重做)
  -v, --version               Print the version number of make and exit.
                              (列印make和exit的版本號)
  -w, --print-directory       Print the current directory.
                              (列印當前目錄)
  --no-print-directory        Turn off -w, even if it was turned on implicitly.
                              (關閉-w,即使它是隱式開啟的)
  -W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE
                              Consider FILE to be infinitely new.
                              (認為檔案是無限新的)
  --warn-undefined-variables  Warn when an undefined variable is referenced.
                              (引用未定義的變數時發出警告)

This program built for x86_64-pc-linux-gnu
Report bugs to <bug-make@gnu.org>
複製程式碼

make 的引數“-k”或“--keep-going”,引數意思是,如果某規則中的命令出錯了,那麼就終目該規則的執行,但繼續執行其它規則。

但是 make 命令中的有幾個引數並不往下傳遞,它們是“-C”,“-f”,“-h”“-o”和“-W”。 當你使用“-C”引數來指定 make 下層 Makefile 時,“-w”會被自動開啟的。如果引數中有“-s”(“--slient”)或是“--no-print-directory”,那麼,“-w”總是失效的。

五、定義命令包

makefile中的命令包寫法類似C語言中的define

define my_action
touch smile
endef

test:
    $(my_action)
複製程式碼

定義一個my_action 它的功能是建立個smile檔案。呼叫方式也跟引用變數的方式是一樣的。make 在執行命令包時,命令包中的每個命令會被依次獨立執行。

相關文章