Eclipse CDT Hello World工程makefile分析

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變量,它指示了工程中所有包含源文件的子目錄,其內容如下:

################################################################################ 
# 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文件

################################################################################ 
# Automatically-generated file. Do not edit! 
################################################################################ 

USER_OBJS := 

LIBS := 

4 src/subdir.mk文件

該文件針對src目錄下的所有.c文件修改C_SRCSOBJSC_DEPS變量,並定義文件夾下所有.c文件的編譯規則。如這裏的src/%.o: ../src/%.c,就是針對src文件夾裏的每個.c文件,在makefile所在文件夾(即Debug)裏生成src文件夾及同名的.o文件。

Eclipse cdt會在所有包含源文件的文件夾下都生成這麼一個subdir.mk文件,所有Debug下存放.o的文件夾結構與存放.c文件的完全相同。

################################################################################ 
# 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文件的內容:

################################################################################ 
# 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] 等不可顯示字符),這些空格的位置可以位於字符串中字符單詞的前面,中間以及後面。去掉的結果是用一個空格代替多個原來的多個空格。

所以這個makefilemake目標不爲clean,並且C_DEPS包含有效字符時纔會-include $(C_DEPS)

在這個工程中,C_DEPS./src/hello.d,所以make all時要包含該文件,可src下並沒有改文件呀?執行make後,發現在src下多了hello.d文件,內容是:

src/hello.d src/hello.o: ../src/hello.c 

它是怎麼來的呢?內容爲何是這樣呢?這就需要搞明白src文件夾裏subdir.mk中的這條命令了:

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文件內容是:

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命令,將會看到下面輸出:

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





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章