前言 :
make 是 UNIX 環境最有用的工具之一. 基本上它是一種用來將大量編譯工作自動化的程式語言. 適當的使用 make, 可以減少花在編譯程式上的時間, 因為需多不必要的重複編譯都可以避免. 適當的使用 make, 還可以保證程式會以正確的選項編譯, 連結的也都是最新版的程式模組及程式庫.
make 主要構想是讓你不必重新編譯一個已有新版物件檔的原始程式. 假如物件檔是在原始程式最後修改之後編譯的, 它就是新版的. 以下列情況為例 : 我們剛剛修改了 stimulate.c , 現在要作編譯並和 inputs.c 及 outputs.c 兩個模組連結. 參考下面的命令 :
% gcc stimulate.c inputs.c outputs.c
可以正確的將三個模組正確的編譯及連結. 假如 inputs.o 及 outputs.o 存在而且是新版本(原始程式在物件模組編譯後沒有改變), 我們可以用下面命令編譯 :
% gcc stimulate.c inputs.o outputs.o
這樣 gcc 只編譯 stimulate.c , 再與兩個物件檔案連結. 因為這次編譯只做一次而非三次, 時間上可以大為節省. 但這樣做需要程序員多費心, 程式設計師必須記住 (或去檢查) 上次編譯 inputs.c 及 outputs.c 是什麼時候, 然後知道哪些模組是否為新版. 這樣做可能造成混淆 : 雖然只編譯 stimulate.c 然後與現有模組連結比較快, 前提是這些模組都必須正確的.
make 可以將這些作業自動化, 降低錯誤編譯的可能性, 同時減少編譯的資源需求. 它會決定相關物件檔是否存在, 以及版本是否為最新的, 然後以最少的編譯來產生你要的結果. 要了解 make 是如何完成這些工作的, 我們需要先定義一些用語 :
* 目標 (target) :
* 依存關係(dependency) :
* 新版 (up to date) :
* make 檔 (makefile) :
使用 make 之前, 你需要先產生 make 檔, 描述如何正確的產生一個或多個程式, 然後執行 make 來完成 make 檔中的指定工作. 首先我們會在接下來介紹如何產生 make 檔. (可以參考 O'Reilly 出版的 Managing Projects with make 一書 得到有關 make 更多相關細節).
產生make 檔案 :
任何的 make 檔不管有多複雜, 其實只是一組描述如何建立目標的指令. 目標通常是一個檔案, 也可能是一件工作. 請參考如下make 檔範例, 描述如何去建立分別為執行版與除錯版的 stimulate 程式 :
* make 範例檔 :
這個 make 檔列出兩個不同版本 stimulate 的命令 :
% gcc -o stimulate -O stimulate.c inputs.c outputs.c <正確編譯出 stimulate 並進行最佳化, 但不進行除錯>
與
gcc -DDEBUG -g -o stimulate.db stimulate.c inputs.c outputs.c <正確編譯可供除錯的版本 stimulate.db>
DEBUG 選項是定義給前處理器看的, 要求它把原始程式中任何的除錯指令納入編譯. 不進行最佳化, 編譯器會產生 gdb 除錯時需要的擴大符號表.
這個make 檔案並沒有發揮 make 的特色, 特別是 make 檔沒有減少多餘的編譯, 只是執行最簡單 (而且最慢) 的命令來完成編譯.
Ps. 命令行的第一個字元必須是定位鍵, 不可以是一或多個空白. 以空白字元起頭是 make 檔中最常犯的錯誤 ; 這種錯誤很難找, 因為 make 檔看起來沒錯. 若你以空白而非定位鍵起頭, make 命令會顯示錯誤訊息 "Missing seperator".
make 檔案會以新的一層 shell 來執行 make 檔中的每一行 UNIX 命令. 因此由shell 直接執行的命令, 效果只同一UNIX 命令行. 還有你可以使用連續自元(\) 來延長一個UNIX 命令行使其跨越多行. 這樣做的時候, '\' 後面不能跟隨任何非命令字元, 包括空白及定位鍵. 最後要執行 make 的命令如下 :
% make target
target 是 make 檔中所定義的目標之一. 如果你沒給 target, make 會產生第一個目標. 例如我們前面的 make 檔可以由下面三種方式之一啟動 :
% make stimulate
或
% make stimulate.db
或
% make
第一個命令執行達成目標 stimulate 所需的命令, 第二個產生 stimulate.db, 第三個執行 make 檔中第一個目標 (本例中為 stimulate).
執行範例 :
[benjamin@localhost ~/src/test]$ make stimulate <執行 target : stimulate 產出程式 stimulate>
gcc -o stimulate -O stimulate.c inputs.c outputs.c
In file included from stimulate.c:1:
outputs.h:6:7: warning: no newline at end of file
In file included from stimulate.c:2:
inputs.h:5:7: warning: no newline at end of file
stimulate.c:8:2: warning: no newline at end of file
In file included from inputs.c:1:
inputs.h:5:7: warning: no newline at end of file
In file included from outputs.c:1:
outputs.h:6:7: warning: no newline at end of file
outputs.c:5:2: warning: no newline at end of file
[benjamin@localhost ~/src/test]$ ./stimulate <執行程式 stimulate>
Hello John
Hi, Peter
Byebye
[benjamin@localhost ~/src/test]$ make <執行 make 檔案第一個 target, 此處為 stimulate>
`stimulate' is up to date. <因為 stimulate 的修改時間晚於 stimulate.c inputs.c outputs.c 所以為 up to date>
make 是 UNIX 環境最有用的工具之一. 基本上它是一種用來將大量編譯工作自動化的程式語言. 適當的使用 make, 可以減少花在編譯程式上的時間, 因為需多不必要的重複編譯都可以避免. 適當的使用 make, 還可以保證程式會以正確的選項編譯, 連結的也都是最新版的程式模組及程式庫.
make 主要構想是讓你不必重新編譯一個已有新版物件檔的原始程式. 假如物件檔是在原始程式最後修改之後編譯的, 它就是新版的. 以下列情況為例 : 我們剛剛修改了 stimulate.c , 現在要作編譯並和 inputs.c 及 outputs.c 兩個模組連結. 參考下面的命令 :
% gcc stimulate.c inputs.c outputs.c
可以正確的將三個模組正確的編譯及連結. 假如 inputs.o 及 outputs.o 存在而且是新版本(原始程式在物件模組編譯後沒有改變), 我們可以用下面命令編譯 :
% gcc stimulate.c inputs.o outputs.o
這樣 gcc 只編譯 stimulate.c , 再與兩個物件檔案連結. 因為這次編譯只做一次而非三次, 時間上可以大為節省. 但這樣做需要程序員多費心, 程式設計師必須記住 (或去檢查) 上次編譯 inputs.c 及 outputs.c 是什麼時候, 然後知道哪些模組是否為新版. 這樣做可能造成混淆 : 雖然只編譯 stimulate.c 然後與現有模組連結比較快, 前提是這些模組都必須正確的.
make 可以將這些作業自動化, 降低錯誤編譯的可能性, 同時減少編譯的資源需求. 它會決定相關物件檔是否存在, 以及版本是否為最新的, 然後以最少的編譯來產生你要的結果. 要了解 make 是如何完成這些工作的, 我們需要先定義一些用語 :
* 目標 (target) :
* 依存關係(dependency) :
* 新版 (up to date) :
* make 檔 (makefile) :
使用 make 之前, 你需要先產生 make 檔, 描述如何正確的產生一個或多個程式, 然後執行 make 來完成 make 檔中的指定工作. 首先我們會在接下來介紹如何產生 make 檔. (可以參考 O'Reilly 出版的 Managing Projects with make 一書 得到有關 make 更多相關細節).
產生make 檔案 :
任何的 make 檔不管有多複雜, 其實只是一組描述如何建立目標的指令. 目標通常是一個檔案, 也可能是一件工作. 請參考如下make 檔範例, 描述如何去建立分別為執行版與除錯版的 stimulate 程式 :
* make 範例檔 :
- #A very simple makefile.
- #Lines beginning with # are comments
- #targets begin at the left margin, followed by:
- #Shell command lines must begin with a tab.
- stimulate:
- #One or more commands to create stimulate
- gcc -o stimulate -O stimulate.c inputs.c outputs.c
- stimulate.db:
- #One or more commands to create stimulate
- gcc -DDEBUG -g -o stimulate.db stimulate.c inputs.c outputs.c
這個 make 檔列出兩個不同版本 stimulate 的命令 :
% gcc -o stimulate -O stimulate.c inputs.c outputs.c <正確編譯出 stimulate 並進行最佳化, 但不進行除錯>
與
gcc -DDEBUG -g -o stimulate.db stimulate.c inputs.c outputs.c <正確編譯可供除錯的版本 stimulate.db>
DEBUG 選項是定義給前處理器看的, 要求它把原始程式中任何的除錯指令納入編譯. 不進行最佳化, 編譯器會產生 gdb 除錯時需要的擴大符號表.
這個make 檔案並沒有發揮 make 的特色, 特別是 make 檔沒有減少多餘的編譯, 只是執行最簡單 (而且最慢) 的命令來完成編譯.
Ps. 命令行的第一個字元必須是定位鍵, 不可以是一或多個空白. 以空白字元起頭是 make 檔中最常犯的錯誤 ; 這種錯誤很難找, 因為 make 檔看起來沒錯. 若你以空白而非定位鍵起頭, make 命令會顯示錯誤訊息 "Missing seperator".
make 檔案會以新的一層 shell 來執行 make 檔中的每一行 UNIX 命令. 因此由shell 直接執行的命令, 效果只同一UNIX 命令行. 還有你可以使用連續自元(\) 來延長一個UNIX 命令行使其跨越多行. 這樣做的時候, '\' 後面不能跟隨任何非命令字元, 包括空白及定位鍵. 最後要執行 make 的命令如下 :
% make target
target 是 make 檔中所定義的目標之一. 如果你沒給 target, make 會產生第一個目標. 例如我們前面的 make 檔可以由下面三種方式之一啟動 :
% make stimulate
或
% make stimulate.db
或
% make
第一個命令執行達成目標 stimulate 所需的命令, 第二個產生 stimulate.db, 第三個執行 make 檔中第一個目標 (本例中為 stimulate).
執行範例 :
[benjamin@localhost ~/src/test]$ make stimulate <執行 target : stimulate 產出程式 stimulate>
gcc -o stimulate -O stimulate.c inputs.c outputs.c
In file included from stimulate.c:1:
outputs.h:6:7: warning: no newline at end of file
In file included from stimulate.c:2:
inputs.h:5:7: warning: no newline at end of file
stimulate.c:8:2: warning: no newline at end of file
In file included from inputs.c:1:
inputs.h:5:7: warning: no newline at end of file
In file included from outputs.c:1:
outputs.h:6:7: warning: no newline at end of file
outputs.c:5:2: warning: no newline at end of file
[benjamin@localhost ~/src/test]$ ./stimulate <執行程式 stimulate>
Hello John
Hi, Peter
Byebye
[benjamin@localhost ~/src/test]$ make <執行 make 檔案第一個 target, 此處為 stimulate>
`stimulate' is up to date. <因為 stimulate 的修改時間晚於 stimulate.c inputs.c outputs.c 所以為 up to date>
This message was edited 4 times. Last update was at 21/02/2010 18:06:26
沒有留言:
張貼留言