複製鏈接
請複製以下鏈接發送給好友

make

(計算機程序)

鎖定
make是一條計算機指令,是在安裝有GNU Make的計算機上的可執行指令。該指令是讀入一個名為makefile [1]  的文件,然後執行這個文件中指定的指令。
有時make又指GNU MakeGNU Make 是一個用來控制可執行文件和其他一些從源文件來的非源代碼文件版本的軟件。
軟件名稱
Make(GNU Make)
開發商
Free Software Foundation, Inc.
軟件平台
linux,unix
軟件語言
C
軟件授權
免費

makeGNU Make

make定義

GNU Make是一個用來控制可執行文件和其他一些從源文件來的非源代碼文件版本的軟件 [2] 
Make可以從一個名為makefile的文件中獲得如何構建你所寫程序的依賴關係,Makefile中列出了每個目標文件以及如何由其他文件來生成它。 當你編寫一個程序時,你可以為它編寫一個makefile文件,這樣你就可以使用Make來編譯和安裝這個程序。

make功能

  1. Make 使最終用户可以在不知道構建細節的情況下構建和安裝你的軟件,因為這些細節都記錄在了你提供的Makefile中 [2] 
  2. 基於源文件的改動,Make可以自動知道那些文件需要更新;它也會自動決定文件更新的適當順序,以避免要更新的文件依賴於另一個同樣需要更新的文件。因此,在你修改了程序的源代碼並且執行Make後,你不必重新完全編譯你的所有文件,只需要重新編譯那些直接或間接受到影響的文件就好了。
  3. Make不限於任何一種特定的語言。對於程序中任何一種非源文件, makefile文件中可以指定shell指令去生成它。shell 指令可以執行編譯器生成目標文件,執行鏈接器生成可執行文件,執行ar更新庫文件,執行TeX(一個文本排版軟件)或Makeinfo去格式化文檔。
  4. Make不限於用來生成軟件包。你可以用make來控制安裝和卸載軟件包,或者用來生成標籤表,以及其他的任何你想要做的,當然前提是你寫好怎麼做(╬▔皿▔)凸。

makeMake的規則和目標

Makefile告訴Make怎樣執行一系列的指令去依靠源文件生成一個目標文件。Makefile中聲明瞭一個依賴關係的列表,這個列表應當包含所有文件(無論是源文件或者目標)作為輸入 [2] 
以下是個簡單的規則示例:
target:   dependencies ...          commands          ...
當你執行make的時候你可以指定特定的目標去更新,否則Make會更新Makefile目標列表中第一個目標。當然作為這個目標輸入的其他目標會先更新。make 用makefile確定那些目標文件應該被更新,然後那些目標文件實際上需要更新。如果一個目標文件比他的所有依賴都新,這樣他就是最新的了,不需要再去重新生成了。其他文件確實需要更新,要按照正確的順序,在用來生成其他文件之前先更新自己。

makeMakefiles和約定

GNU制訂了一些如何編寫Makefiles的約定,所用的GNU軟件包必須遵守。即使你不打算成為GNU軟件,在你的程序中遵循這些約定也是一個好主意,這樣用户就可以像其他許多軟件包一樣構建你的軟件包,而且不需要學習任何特殊的東西 [3] 
這些約定可以在章節``Makefile conventions'' (147 k characters)和章節GNU Coding Standards (147 k characters)中看到。 [4] 

make安卓mk與makefile的關係

Android.mk和Application.mk是基於makefile裝了一層封裝,編寫Android.mk和Application.mk之後可以通過ndk-build執行so的編譯,Android.mk中新增了一些對固定文件 固定的環境變量的的讀取
如APP_ABI := armeabi-v7a定義在Application.mk中然後執行ndk-build將只編譯armeabi-v7a的so在 當前目錄的上級目錄。
具體參考 [4] 

make通俗點的解釋

當你寫一個簡單的程序,只有一到兩個源文件的時候,輸入
% cc file1.c file2.c
就沒什麼問題,但如果有很多源文件就會很煩人──編譯的時間也會很長。
一個方法就是使用目標文件,只在源文件有改變的情況下才重新編譯源文件。因此你可以這樣做:
% cc file1.o file2.o ... file37.c ...
上次編譯後,file37.c 發生了改變,但其他文件沒有。這樣做可以讓編譯過程快很多,但是也不能解決累人的輸入問題。
或者我們可以使用一個shell script來解決輸入問題,但是也需要重新編譯所有文件,在大型項目上很沒有效率。
如果有成百上千的源文件的話怎麼辦?如果我們在與很多人合作寫程序,別人對源文件進行了修改,又沒有告訴你,該怎麼辦?
也許我們可以把以上兩種方法結合,寫一種像shellscript 一樣的東西。這種文件包含某種技巧可以決定什麼時候該對源文件進行編譯。如今所有我們要的就是一個程序可以懂得這種技巧,因為要懂得這種技巧,shell 還沒那麼大的能耐。
這個程序就叫 make。它讀入一個文件,叫makefile [1]  ,這個文件決定了源文件之間的依賴關係。而且決定了源文件什麼時候該編譯什麼時候不應該編譯。例如,某個規則可以説 “ 如果 fromboz.o 比 fromboz.c 要舊,意思就是有人修改了 fromboz.c,因此我們需要重新編譯這個文件。”這個makefile還有規則通知 make 該 怎麼 重新編譯源文件,因此 make 是一個強大得多的工具。
makefile通常和相關的源文件保存在同一個目錄下,可以叫做 makefile,Makefile 或者 MAKEFILE。大多數程序員會使用 Makefile 這個名字,因為這樣可以讓這個文件被放在目錄列 表的頂端,可以很容易得看見。

makemake命令

這是一個非常簡單的 make 文件:
foo: foo.c
cc -o foo foo.c
包含兩行,一行是依賴關係,一行是執行動作。
依賴關係的那一行包含了程序的名字 (叫做 target),緊跟着一個冒號,然後是空格,最後是源文件的 名字。當 make讀入這一行的時候,會檢查 foo 是否存在;如果存在,就比較 foo 和 foo.c 最後的修改時間有什 麼不同。如果 foo 不存在,或者比 foo.c 要舊,就檢查執行動作那一行看看該怎麼做。換句話 説,就是 foo.c 需要重新編譯的時候該怎麼辦。
執行動作那一行以一個 tab (按下 tab) 開始,然後是你在命令行下產生 foo 所執行的命令。如果 foo 過期了,或者不存在,make 就會 執行這個命令來產生foo。換句話説,這就是重新編譯 foo.c 的規則。
因此,當你輸入 make 時,它會確定 foo 和 foo.c 在修改時間上是否同步。這個原則可以在 Makefile 裏擴展到成百上千的目標文件上──實際上,在 FreeBSD 裏,你只要在合適的目錄下輸入 make world 就可以編譯整個操作系統!
makefile另一個有用的特點就是目標文件不一定就是程序。例如,我們可以 有這樣的 make 文件。
foo: foo.c
cc -o foo foo.c
install:
cp foo /home/me
我們可以輸入如下的命令告訴 make 該執行哪個目標:
% make target
make 會只執行這個目標而忽略其他的目標。例如,如果我們輸入 make foo,就只有 foo 被執行,必要的情況下重新編譯 foo 而不會繼續執行 install 這個目標。
如果我們只是輸入 make 這個命令,make 總會尋找第一個目標,並且在執行完以後就不管其他的目標了。例如,如果我們輸入 make foo,make 就會轉到 foo 這個目標,在必要的情況下重新編譯 foo,而不會執行 install 目標, 然後就停止了。
一定要注意,install 這個目標不依賴任何其他的東西!這意味着我們一旦輸入 make install,這個目標下的所有命令都將被執行。這種情況下,foo 將被安裝到用户的家目錄下。應用程序的makefile正是這樣寫的,以便程序在正確編譯後可以被安裝到正確的目錄。
要嘗試解釋的話會比較容易讓人混淆。如果你不太懂 make 是如何工作的,最好的辦法就是先寫一個簡單的程序例如 “hello world” 以及和上面的例子相同的 make 文件再去實驗。然後 再進一步,使用多個源文件,或者讓你的源文件包含一個頭文件。 touch 命令在這裏就非常有用了──它能讓在不改變文件內容的情況下改變文件的日期。
想進一步學習如何編寫makefile請參考引用4 [5]  .
參考資料