Makefile的寫法入門心得
Makefile的出現使得編譯過程極大地自動化了,省去了很多人工工作,非常方便。這里,小結一下寫Makefile的一點小心得。嗯,對了,差點忘了一件事,同一個Makefile在不同的內核版本和Linux發行版本中不一定能發揮一樣的作用,別人的Makefile可不見得就適用於自己的機器。
我先簡單說一下我自己的機器: Ubuntu12.04-Kernel-3.4.5,內核是根據我自己機器的配置裁剪過的,不過估計這個影響不大,當然,大神們就別批小弟了,咱的水平還不至於寫非常貼近底層的東西。
好了,開始介紹。
下面是一個在網上非常泛濫的模板,雖然泛濫,但就是沒有一個人把這個模版做一個剖析,我這個菜鳥就勉強試一試好了。事前說明:如果在每一段的最前面有空格的,記住那是tab鍵,是Makefile里面專門用於寫命令時固定的格式:
#Source file
SRC = ThreadQueue.cpp
#Object file
OBJ = $(SRC:.cpp=.o)
#Output execution file
PROGRAM = ThreadQueue
#Compiler
CC = g++
#Include
INCLUDE = -I/usr/include/ncurses –I/usr/include/
#Linker Parameter
LINKPARAM = -lpthread -lncurses
#Options for development
#CFLAGS = -g
#Options for release
CFLAGS = -o
all: $(PROGRAM)
$(PROGRAM): $(OBJ)
$(CC) -o $(PROGRAM) $(LINKPARAM) $(OBJ)
.SUFFIXES : .cpp
.cpp.o:
$(CC) $(INCLUDE) $(CFLAGS) -c $<
clean:
-rm *.o
下面一行一行的來解析這個makefile。
首先解釋第一行以及好多行都出現的“#”號,注釋,完全是注釋,跟C語言中的//是一樣的,在標准的Linux內核Makefile中有很多內容都是幫你理解的注釋。
第二行是一個變量的定義,變量名為SRC,變量定義為ThreadQueue.cpp,這樣要引用變量時寫作“$(變量名)”即可,就等價為變量的定義內容。
第三行注釋,讀讀就好。
第四行這里又定義了一個變量,請注意,它的定義引用了SRC變量,同時,用到了變量替換,這里
SRC:.cpp=.o的意思是指將SRC下所有以.cpp結尾的文件的.cpp替換為.o,也就定義了要輸出的所有文件。
第五行,注釋的說。
第六行是定義變量,這里順便再一提,這個就是我們在編譯過程中最后要得到的東西,即ThreadQueue.o。
第七行又是注釋的說。
第八行的變量定義是指CC代表的就是gcc編譯器。嗯,據我自己這幾天的經驗,絕大部分Makefile(包括標准的Linux Makefile)都是這么寫的。
第九行(這里是指有內容的第九行,不包括空行)注釋的說。
第十行,又是一個變量定義,這里就得交待一件事情了:在Makefile中變量的定義是很靈活的,基本可以理解為C語言下的宏定義,你定義神馬都可以,你可以用變量來定義一個文件名列表,定義一個可執行文件名,也可以把變量定義成編譯器命令選項。
第十一行,注釋的說。
第十二行,這里也是一個變量的定義,這個變量作為gcc編譯時的編譯器選項使用。
第十三至十五行皆是注釋,不過這三行以及下面的第十六行還是有其他作用的,待到十六行處再講。
第十六行,這里連帶着上面的三行一起講,看英文也應該看出來這里四行的作用了。是這樣的,如果你是想自己要調試用的話,你就保留“options for develop”下面的那一行,把之前的“#”號去掉,而你要是想生成不可調試的發行版,那就選擇讓第十六行生效。這里,為什么會有這樣的區別就涉及到gcc編譯器使用選項的問題了,留做他日再寫。
第十七行,all是一個標簽,你可以理解成一個跳轉符號,如果想讓make程序在編譯時執行某一個特定的指令,就可以把這個指令做成一個標簽,這樣在命令行里輸入“make Name_of_Your_Label”就可以執行某一特定部分的編譯了。
第十八、十九、二十行,來到這里就不得不提一般的Makefile的書寫格式了,這也是為什么我要把三行在一起交待,如下:
目標:依賴
命令
……
必須注意的是,命令前面的不是空格,而是制表符Tab,這是Makefile書寫時必須遵循的規則。那我們看到上面的模板中,我們要生成的是PROGRAM所代表的變量,而所需要的依賴就是OBJ中所有的.o文件,生成時的命令是“$(CC) -o $(PROGRAM) $(LINKPARAM) $(OBJ)”,根據他們各自的變量定義可知,之一段命令可以翻譯為“gcc –o ThreadQueue -lpthread –lncurses ThreadQueue.o”,其中前面帶有-的幾個字母都是gcc編譯時的選項,改天再總結一下gcc編譯器的使用。
第二十一行,這里的“.SUFFIXES”是一個偽目標,它的作用類似於一個標簽,在偽目標之后的所有內容將不會被檢查是否已經執行,而是將它直接執行。
第二十二、二十三行,這里.cpp.o是老式的“后綴規則”,編譯器將會自動將.cpp識別為源文件后綴,而.o識別為輸出文件后綴。,SUFFIXES也是習慣上用來定義后綴規則的偽目標。特別需要注意的是,后綴規則不允許任何依賴文件,但也不能沒有命令。
第二十四、二十五行,這里定義了clean命令的執行規則,以及所要清除的文件的后綴名,如果你還想在clean時清除什么后綴的文件的話,就再寫上”*.post_name”即可,非常方便。
小結:Makefile的寫法還是比較復雜的,我這一篇文章只提及了很少的一點,給大家推薦一個人的博客,他曾經寫過《跟我一起學寫Makefile》,希望該大神的博客能對你有所幫助:http://blog.csdn.net/haoel/article/details/2886
By Air_Figher
12.07.21
