字體:小 中 大 | |
|
|
2009/09/17 21:40:19瀏覽8827|回應0|推薦0 | |
本篇的內容,摘錄自筆者的著作 《C 語言之修練與實踐》之第一章。 就 makefile 的格式與意義,我們將由四個面向來做探討,分別為:一、comment;二、macro、三、explicit rule、四、suffix rule。 Comment 井字號 (pound sign) 是用來標示 comment 起始點的符號,只要是跟在 pound sign 後頭的文字,都會被 make utility 視為 comment。例如 Makefile.v1 的 line 1 就是一個 comment line,其中 pound sign 出現在 line 1 的 column 1,而後頭的 "This is my first Makefile" 就是 comment。請留意井字號不一定非得寫在 column 1 不可,它可以寫在行中的任何位置。 Macro (Variable Definition) macro 主要是用來代表一筆或多筆的文字組,其實質的功能等同於 variable definition。最常見的 macro 使用法就是用它來代表 compiler 的名稱、compiler 的 option,抑或是一組執行檔的名稱。例如: CC = gcc CFLAGS = -g TARGETS = print_novice compute_sum compute_sum_fi xed 上述的 CC、CFLAGS 以及 TARGETS 就是 macro,而其等號後的一筆或多筆的文字組就是它們的值。如果 macro 的值太長而寫不進一行時,抑或為了閱讀上的便利與美觀性而想換行書寫,但是邏輯上是要接續前一行,則可使用 backslash 來將它們標示成邏輯行。例如 Makefile.v1 中的 line 3 與 line 4 就是一個邏輯行,其中 line 3 尾端的 backslah 表示 line 4 是 line 3 的延續,這兩行在邏輯上是被視為同一行。以 dollar sign 為前導字元,並以 parenthesis 或 curly brace 將 macro 括起來,即可取得該 macro 的值。例如 Makefile.v1 line 8 與 20 中的 $(TARGETS),以及 line 11、14 與 17 中的 $(CC)。 除了使用者所定義的 macro 之外,makefile 自己也有一組事先定義好的 macro,我們稱之為 internal macro 或 automatic variable,其中最常被使用的有兩種:一、$@,它代表 current target 的名字;二、$<,它只能被用於 suffix rule,其代表意義為 implied source file。 Explicit Rule 由於 make 是個非常被動的 utility,沒被講明的工作它就不做,所以不論是執行檔的建構或是一組行動的執行,只要是我們想命令 make 去做的事情,都必須依照 makefile 的格式,把它們說得一清二楚,這就是 explicit rule 的意義。 在 makefile 中,把要做的事情講明白的格式為: target: dependent1 dependent2 ...... 上述中的 target,可以是執行檔的名稱,亦可為一組行動的名稱,而在冒號之後的 dependent1、dependent2 等等,則為該 target 的相依物,此「相依物」的意思為:如果相依物有所變化,則 target 也要跟著變化,如何變化則由後續的 shell command 所定義。至於相依物的變化與否,則是以其修改時間 (modification time) 來做為判斷的基準。以下列的 explicit rule 為例:{leading tab}shell_command {leading tab}shell_command ...... exercise_more: bmi_exceeds_24 waistline_exceeds_90CM 第一個 target 叫做 exercise_more,它有兩個相依物,分別為 bmi_exceeds_24 與 waistline_exceeds_90CM,它的 shell command 叫做 do_more_fast_walking;當 exercise_more 的兩個相依物之中,有一個的 modification time 比它的modification time 還要新時,則 exercise_more 就要依照 do_more_fast_walking的指示做改變。do_more_fast_walking bmi_exceeds_24: weight height compute_bmi waistline_exceeds_90CM: waistline compare_waistline 第二個 target 叫做 bmi_exceeds_24,它的兩個相依物為 weight 與 height,當這兩者有所改變時,bmi_exceeds_24 就要跟著做改變,如何改變就定義在 compute_bmi 之中。例如,如果計算出來的 bmi 沒有超過 24,就不更動 bmi_exceeds_24 的修改時間;如果計算出來的 bmi 超過 24,就將 bmi_exceeds_24 的修改時間做更新,如此才能驅動上層的 exercise_more 跟著做改變。 第三個 target 叫做 waistline_exceeds_90CM,它的相依物為 waistline,當它的值有所變化時,waistline_exceeds_90CM 就要跟著做變化,如何變化就定義在 compare_waistline 之中。例如,如果比較的結果是小於或等於 90 cm,就不更改該 target 的修改時間;如果比較的結果是大於 90 cm,就更新該 target 的修改時間,如此才能驅動與它有相依關係的上層 target 跟著做變化。 make utility 在掃瞄 makefile 時,它會將掃到的 dependent 當成 search pattern,去搜尋這些 dependent 是否也出現在 target 之中,如此不停地搜尋下去,直到再也找不到任何的 dependent 出現於 target 時為止;此時,make utility 的內部已經建立了一棵 dependency tree,其中的每一個 node 就是一個 target,而指定工作的執行順序則是從最底層的 target 開始做起,做完之後再執行上層 target 所指定的工作。以上述的 explicit rule 為例,其 dependency tree 與執行的順序則如圖 1.2-11 所示。 在 makefile 中,所有以 tab 為 leading character 的 line,都會被視為 command line,所以 shell command line 的開頭字元一定是 tab,但因為 tab 與 space 在一般的編輯模式下是無從區分的,所以初學者常犯的錯誤就是以 space 來做為 shell command line 的開頭字元,再加上部分的 make utility 針對 missing leading tab 所顯示的錯誤訊息有點文不對題,以致於經常令初學者搞不清楚出錯的原因。檢查 leading tab 的方法,除了 vi 的 list command 外,還可利用 cat -vet 指令來做檢查。 Suffix Rule (Implicit Rule) 顧名思義,suffix 就是結尾的意思,在本節中則是代表 file name 的 suffix,亦即我們所熟知的副檔名 (extension name)。在電腦的世界裡,有許多習以為常的副檔名慣用法,例如我們習慣以 .txt 來做為文字檔的副檔名,以 .c 來做為 C 程式檔的副檔名,以 .cpp 來做為 C++ 程式檔的副檔名,以 .o 來做為機器碼檔案的副檔名。不成文的副檔名慣用法,讓人們可從檔名的 suffix 得知該檔案的內容型態,而 makefile 中的 suffix rule (又稱為 implicit rule),就是用來指明或建立這種副檔名慣用法的規則。suffix rule 的格式如下: .SUFFIX: .output_ext .input_ext .input_ext.output_ext: shell_command 上述中的 ".SUFFIX" 是一個可被 make utility 所辨認的 special target,它的dependent line 是用來指明 input file name 與 output file name 的副檔名;接下來的 ".input_ext.output_ext" 這個 target,則是用來指明如何將 input file 轉換成 output file。以 C 的原始程式檔 (source file) 為例,它都是先被編譯成機器碼檔 (object file),然後 linker 再把若干個相關的機器碼檔組合成一個執行檔(executable)。因此,其 suffix rule 的常見寫法為: .SUFFIXES: .o .c .c.o: $(CC) $(CFLAGS) -c $< 上述中的 "c" 表示 "compile only, don't call linker" 之意,"$<" 則為 makefile 的 internal macro,它代表自動隱含的原始程式碼 (the implied source code)。總體來說,makefile 中的 variable definition (macro),大致上可分為三類,分別為:一、makefile 所需使用到的程式 (program) 或指令 (command);二、該程式或指令的選擇項 (option、flag);三、一組 source code file、object file 或 是 executable。 常見的第一類 variable definition 有: AR Archive maintaining programs, the typical value is ar. AS Program for compiling assembly programs. CC Program for compiling C programs. CXX Program for compiling C++ programs. RM Command to remove a fi le. 常見的第二類 variable definition 有: ARFLAGS extra flags to give to archive maintaining program ASFLAGS extra flags to give to assembler CFLAGS extra flags to give to C compiler CXXFLAGS extra flags to give to C++ compiler RMFLAGS extra flags to give to rm command |
|
( 創作|其他 ) |