下面的內容是直接從個人ipython notebook中摘錄出來的因此可能不是很清楚,若是想查看完整版本以及例子,能夠訪問:html
git地址: git@github.com:liangz0707/WTF-makefile.gitpython
下載地址:https://github.com/liangz0707/WTF-makefile/archive/master.zipios
若是不能查看ipython notebook 能夠直接打開其中的lession.html 結果是同樣的 git
What is Compiler?程序員
Compiler=編譯器,就是將某種代碼編譯成機器語言,或者說編譯成可以由處理器直接執行的「代碼」。一個程序員會以一種語言在編輯器當中編寫語句。例如:c、Lisp。編寫完成後生成的文件就是源代碼。而後程序員運行具體的編譯器,把上述文件名做爲參數進行編譯。github
執行過程當中,編譯器會依照語法順序,逐一對語句進行解析。最終生成輸出代碼。通常的編譯器的輸出結果叫作object code或者object module(這裏的object和麪向對象中的object不一樣)。這裏的object code是機器語言。安全
在傳統的操做系統當中,在編譯以後每每還須要額外的步驟,由於當有多於一個Object Code時 他們的指令、和數據之間存在關係,因此須要進行連接,獲得的結果是。 load module。less
GCC是c語言的編譯器之一:編輯器
gcc is the "GNU" C Compiler, and g++ is the "GNU C++ compiler工具
咱們編寫一個hello.c文件(見目錄):
/#include "iostream.h"
int main()
{
cout << "Hello\n";
}
執行以下命令,輸出的結果就是可執行的機器碼(.exe可執行程序),默認文件名是a.exe
主要g++編譯的源文件中頭文件的引用通常爲#include< iostream>,而不是#include< iostream.h>,而且要注意使用命名空間。
!g++ hello.c -o hello
在實際的編譯過程當中,逐個的編譯源代碼過於冗雜,尤爲是當你須要包含不少源文件時,你不得不每一次都要打字輸入。
而是用Makefile就是爲了簡化不少源文件的編譯過程。 例如咱們有不少c問見須要編譯:
main.cpp
hello.cpp
factorial.cpp
functions.h 以上的文件都是經過頭文件串聯起來的
#若是須要手動的編譯,以下很是麻煩
!g++ main.cpp hello.cpp factorial.cpp -o hello
#執行上面獲得的文件
!hello
把source code轉換成object files
將不一樣的object files鏈接成可執行的機器碼(.exe) 下面使用最簡單的Makefile 來進行編譯,代替手工過程
基本的Makefile組成以下:
target: dependencies
[tab]system command
‘target’能夠理解爲要編譯的目標或任務(分號後的內容),dependencies表示要完成這個目標所須要的前提。編寫成咱們須要的格式以下:
all:
g++ main.cpp hello.cpp factorial.cpp -o hello
從makefile文件中能夠看出咱們的目的是‘all’,這是makefiles默認的目標。make工具在沒有特殊聲明的時候會有限執行‘all’,咱們看到all是沒有依賴的,因此能夠安全的執行。
有時候咱們會使用不一樣的‘target’。由於當咱們修改了一個文件的時候,不但願把全部的文件都進行從新編譯。
例如如下的例子:
all: hello
hello: main.o factorial.o hello.o
g++ main.o factorial.o hello.o -o hello main.o: main.cpp
g++ -c main.cpp factorial.o: factorial.cpp
g++ -c factorial.cpp hello.o: hello.cpp
g++ -c hello.cpp
clean:
del *o hello.exe
至關於把編譯的過程(上述的兩部,編譯、鏈接)拆分開。
咱們看到all只有一個依賴,而沒有命令,這是爲了讓make可以正確的執行。all必須執行才能完成。
對於每個可用的目標全部的依賴都會被搜索,若是找到則執行。
咱們還看到了一個clean的目標,他能夠快速的清楚全部的object和可執行程序,至於如何使用稍後解釋。
例子以下:
# I am a comment, and I want to say that the variable CC will be
# the compiler to use. CC=g++
# Hey!, I am comment number 2. I want to say that CFLAGS will be the
# options I'll pass to the compiler.
CFLAGS=-c -Wall
all: hello
hello: main.o factorial.o hello.o
$(CC) main.o factorial.o hello.o -o hello
main.o: main.cpp
$(CC) $(CFLAGS) main.cpp
factorial.o: factorial.cpp
$(CC) $(CFLAGS) factorial.cpp
hello.o: hello.cpp
$(CC) $(CFLAGS) hello.cpp
clean:
del *o hello.exe
如上所示,使用$(VAR)就能夠輕鬆的訪問變量。