1.?工程文件分析
使用eclipse新建一個Hello?World工程,假設工程名稱是hello,此時eclipse在工程目錄下新建了一個名為hello的文件夾:
hello/
????.cproject
????.project
????src/
????????hello.c
先build該工程,然后Clean該工程,清除生成的目標碼,這時hello文件夾下只多了eclipse為工程生成的makefile文件,其文件結構為:
hello/
????.cproject
????.project
????Debug/
????????src/
????????????subdir.mk
????????makefile
????????objects.mk
????????sources.mk
????src/
????????hello.c
2.?sources.mk文件
該文件中定義了makefile文件中使用的各種變量,最主要的就是SUBDIRS變量,它指示了工程中所有包含源文件的子目錄,其內容如下:
[html]?view plaincopy
################################################################################??? #?Automatically-generated?file.?Do?not?edit!??? ################################################################################??? ?? O_SRCS?:=??? C_SRCS?:=??? S_UPPER_SRCS?:=??? OBJ_SRCS?:=??? ASM_SRCS?:=??? OBJS?:=??? C_DEPS?:=??? EXECUTABLES?:=??? ?? #?Every?subdirectory?with?source?files?must?be?described?here??? SUBDIRS?:=?\??? src?\??
3 objects.mk文件
[html]?view plaincopy
################################################################################??? #?Automatically-generated?file.?Do?not?edit!??? ################################################################################??? ?? USER_OBJS?:=??? ?? LIBS?:=???
4 src/subdir.mk文件
該文件針對src目錄下的所有.c文件修改C_SRCS、OBJS和C_DEPS變量,并定義文件夾下所有.c文件的編譯規則。如這里的src/%.o:?../src/%.c,就是針對src文件夾里的每個.c文件,在makefile所在文件夾(即Debug)里生成src文件夾及同名的.o文件。
Eclipse?cdt會在所有包含源文件的文件夾下都生成這么一個subdir.mk文件,所有Debug下存放.o的文件夾結構與存放.c文件的完全相同。
[html]?view plaincopy
################################################################################??? #?Automatically-generated?file.?Do?not?edit!??? ################################################################################??? ?? #?Add?inputs?and?outputs?from?these?tool?invocations?to?the?build?variables??? C_SRCS?+=?\??? ../src/hello.c??? ?? OBJS?+=?\??? ./src/hello.o??? ?? C_DEPS?+=?\??? ./src/hello.d??? ?? ?? #?Each?subdirectory?must?supply?rules?for?building?sources?it?contributes??? src/%.o:?../src/%.c??? ????@echo?'Building?file:?$<'??? ????@echo?'Invoking:?GCC?C?Compiler'??? ????gcc?-O0?-g3?-Wall?-c?-fmessage-length=0?-MMD?-MP?-MF"$(@:%.o=%.d)"?-MT"$(@:%.o=%.d)"?-o?"$@"?"$<"??? ????@echo?'Finished?building:?$<'??? ????@echo?'?'??
5 makefile文件
makefile文件include包含了上面介紹的幾個文件,下面是makefile文件的內容:
[html]?view plaincopy
################################################################################??? #?Automatically-generated?file.?Do?not?edit!??? ################################################################################??? ?? -include?../makefile.init??? ?? RM?:=?rm?-rf??? ?? #?All?of?the?sources?participating?in?the?build?are?defined?here??? -include?sources.mk??? -include?src/subdir.mk??? -include?subdir.mk??? -include?objects.mk??? ?? ifneq?($(MAKECMDGOALS),clean)??? ifneq?($(strip?$(C_DEPS)),)??? -include?$(C_DEPS)??? endif??? endif??? ?? -include?../makefile.defs??? ?? #?Add?inputs?and?outputs?from?these?tool?invocations?to?the?build?variables??? ?? #?All?Target??? all:?hello??? ?? #?Tool?invocations??? hello:?$(OBJS)?$(USER_OBJS)??? ????@echo?'Building?target:?$@'??? ????@echo?'Invoking:?GCC?C?Linker'??? ????gcc??-o?"hello"?$(OBJS)?$(USER_OBJS)?$(LIBS)??? ????@echo?'Finished?building?target:?$@'??? ????@echo?'?'??? ?? #?Other?Targets??? clean:??? ????-$(RM)?$(OBJS)$(C_DEPS)$(EXECUTABLES)?hello??? ????-@echo?'?'??? ?? .PHONY:?all?clean?dependents??? .SECONDARY:??? ?? -include?../makefile.targets??
這里有必要說明以下MAKECMDGOALS?變量,make?在執行時設置的一個特殊變量,該變量記錄了命令行參數指定的目標列表,沒有通過參數指定終極目標時此變量為空。該變量僅限于用在特殊場合(比如判斷),在?Makefile?中最好不要對它進行重新定義。
而strip?函數可以用來去掉字符串中的空格(包括?[TAB]?等不可顯示字符),這些空格的位置可以位于字符串中字符單詞的前面,中間以及后面。去掉的結果是用一個空格代替多個原來的多個空格。
所以這個makefile中make目標不為clean,并且C_DEPS包含有效字符時才會-include?$(C_DEPS)
在這個工程中,C_DEPS為./src/hello.d,所以make?all時要包含該文件,可src下并沒有改文件呀?執行make后,發現在src下多了hello.d文件,內容是:
[html]?view plaincopy
src/hello.d?src/hello.o:?../src/hello.c???
它是怎么來的呢?內容為何是這樣呢?這就需要搞明白src文件夾里subdir.mk中的這條命令了:
[html]?view plaincopy
gcc?-O0?-g3?-Wall?-c?-fmessage-length=0?-MMD?-MP?-MF"$(@:%.o=%.d)"?-MT"$(@:%.o=%.d)"?-o?"$@"?"$<"??
-fmessage-length=0:默認情況下,GNU工具鏈編譯過程中,控制臺輸出的一行信息是不換行的,這樣,當輸出信息過長時(如編譯錯誤時的信息),會導致你無法看到完整的輸出信息,加入-fmessage-length=0后,輸出信息會根據控制臺的寬度自動換行,這樣就能看全輸出信息了。?
-MF?FILE:與-M或-MM一起使用,指定依賴關系寫到什么文件中,如果沒有-MF選項,則默認寫到預處理輸出中。當與-MD或-MMD一起使用時,-MF指定的文件會覆蓋默認依賴輸出文件。
-M:輸出源文件的依賴關系,其中隱含了-E和-w選項。
-MM:與-M類似,但忽略系統頭文件。
-MD:除了未隱含-E選項外,等價于-M?-MF?file。
-MMD:與-MD類似,但忽略系統頭文件。
-MP:為依賴的頭文件添加偽目標,目的是當刪除頭文件后如果makefile沒有更新,則提示錯誤。典型的輸出如:
????????test.o:?test.c?test.h?
????????test.h:
-MT:改變依賴規則目標,在這個Hello工程makefile中,如果去掉-MT"$(@:%.o=%.d)",那么輸出的hello.d文件內容是:
[html]?view plaincopy
src/hello.d?src/hello.o:?../src/hello.c???
根據以上分析,我們知道第一次執行make?all時并不會包含hello.d文件,因為那時它還不存在,hello.d也正是這次執行才生成的;以后再次執行make?all時,會將hello.d內容包括到makefile中,make會根據依賴關系有選擇性的進行編譯和鏈接操作。
6? make?all
在命令行下面進入Debug目錄,執行make?all命令,將會看到下面輸出:
[html]?view plaincopy
Building?file:?../src/hello.c?? Invoking:?GCC?C?Compiler?? gcc?-O0?-g3?-Wall?-c?-fmessage-length=0?-MMD?-MP?-MF"src/hello.d"?-MT"src/hello.d"?-o?"src/hello.o"?"../src/hello.c"?? Finished?building:?../src/hello.c?? ??? Building?target:?hello?? Invoking:?GCC?C?Linker?? gcc??-o?"hello"??./src/hello.o????? Finished?building?target:?hello??
其中上面一段是對源文件的編譯,規則在src/subdir.mk中定義;后面一段聲明目標文件,規則直接在makefile文件中定義。
7? 其他
除了上面分析的內容,makefile文件還有下面幾項:
-include?../makefile.init
-include?../makefile.defs
.PHONY:?dependents
-include?../makefile.targets
版權聲明:本文為博主原創文章,未經博主允許不得轉載。
總結
以上是生活随笔為你收集整理的Eclipse CDT Hello World工程makefile分析的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。