Makefile概述——常用操作記錄

一、導入

1、編寫文件a.c

#include <stdio.h>

int main(void)
{
	func();
	return 0;
}

2、編寫文件b.c

#include <stdio.h>

void func(void)
{
	printf("Hello World.\n");
}

3、linux環境下執行命令:

gcc -o test a.c b.c	

 

4、在當前目錄下會生成一個test的可執行文件,在linux環境下執行命令運行test

./test

5、分析:通過gcc -o test a.c b.c 命令行對a.c、b.c進行編譯、鏈接生成test可執行程序還是比較簡單的,這是因爲文件數量少,可以這樣用, 但是當文件數量很多時(如幾千幾萬個量級), 沒必要每次對所有文件都編譯、鏈接,可以僅對改動的文件進行編譯,生成.o文件, 然後再對所有.o文件進行鏈接生成可執行程序文件

6、上述分析,可以藉助編寫Makefile文件來實現。

 

 

二、Makefile語法及常用功能

1、Makefile的核心——規則:

目標:依賴1 依賴2...

[TAB]命令

 

2、執行場景:

當“目標文件”不存在,

某個依賴文件比目標文件“新”,

則:執行“命令”

 

3、對上述a.c b.c編寫Makefile文件

1) 在與a.c、b.c同級目錄下,新建Makefile文件,編寫內容如下:

test : a.o b.o
	gcc -o test a.o b.o
	
a.o : a.c
	gcc -c -o a.o a.c
	
b.o : b.c
	gcc -c -o b.o b.c
	
clean:
	rm *.o test

 

 

 

2)linux環境下執行 make 和 make clean命令,觀察目錄內文件變化:

運行make命令後,目錄內生成test可執行程序文件,通過./test命令即可運行該程序;

運行make clean 命令, 目錄內左右 .o 和 test 文件被清除。

 

4、Makefile的語法

1)通配符:%.o

  •  $@ 表示目標
  •  $< 表示第一個依賴文件
  • $^ 表示所有依賴文件

使用通配符修改上述Makefile文件,如下:

 

test: a.o b.o
	gcc -o test $^
	
%.o : %.c 
	gcc -c -o $@ $<
	
clean:
	rm *.o test

問題及分析:當前文件夾中若有同名的clean文件時,make clean命令將不會被執行,可以使用假想目標:.PHONY來解決。

2) 假想目標:.PHONY

如下:

test: a.o b.o
	gcc -o test $^
	
%.o : %.c 
	gcc -c -o $@ $<
	
clean:
	rm *.o test
	
.PHONY: clean

 

說明:添加 .PHONY: clean 後,就不會判斷名爲clean的文件是否存在,而是直接執行make clean命令。

 

3)即時變量、延時變量,export

簡單變量(即使變量):

A := xxx         # A的值即可確定,在定義時即確定

B = xxx          # B的值使用到時才確定

 

:=                   # 即時變量

=                    # 延時變量

?=                  # 延時變量,如果是第一次定義才起效果,如果在前面該變量已定義則忽略該句

+=                  # 附加, 它是即時變量還是延時變量取決於前面的定義

 

 

 

三、Makefile語法及常用功能

a.   $(foreach var, list, text)

b.   $(filter pattern..., text)                                                  #在text中取出符合pattern格式的值

      $(filter-out pattern..., text)                                            #在text中取出不符合pattern格式的值

c.   $(wildcard pattern)                                                       #pattern定義了文件名的格式,

                                                                                          #wildcard取出其中存在的文件

d.   $(patsubst pattern, replacement, $(var))                     #從列表中取出每一個值,

                                                                                          #如果符合pattern

                                                                                          #則替換爲replacement

 

 

四、Makefile實例

1、改進:支持頭文件依賴

(詳細介紹可以參考這篇博客: http://blog.csdn.net/qq1452008/article/details/50855810)

gcc -M c.c                                      //打印出依賴

gcc -M -MF c.d c.c                        //把依賴寫入文件c.d

gcc -c -o c.o c.c -MD -MF c.d        //編譯c.o, 把依賴寫入文件c.d

 

自動添加依賴文件, 舉例:

objs = a.o b.o c.o

#從objs列表中取出符合%的值(此處取出所有),然後替換爲替換爲.%.d
dep_files := $(patsubst %, .%.d, $(objs))	

#取出dep_files中存在的文件,即取出所有依賴文件
dep_files := $(wildcard $(dep_files))  

test: $(objs)
	gcc -o test $^
	
#判斷是否包含依賴文件,若不包含,則執行include包含依賴文件命令
ifneq ($(dep_files),)
include $(dep_files)
endif
	
c.o : c.c c.h

#編譯%.o,把依賴寫入文件%.d
%.o : %.c 
	gcc -c -o $@ $< -MD -MF [email protected]  
	
clean:
	rm *.o test
	
distclean:
	rm $(dep_files)
	
.PHONY: clean

 

2、添加CFLAGS

 

#將所有警告設置成錯誤提醒, 設置所有頭文件路徑到 ./ 即當前路徑查找 CFLAGS = -Werror -I./

objs = a.o b.o c.o

#從objs列表中取出符合%的值(此處取出所有),然後替換爲替換爲.%.d
dep_files := $(patsubst %, .%.d, $(objs))	

#取出dep_files中存在的文件,即取出所有依賴文件
dep_files := $(wildcard $(dep_files))  

#將所有警告設置成錯誤提醒, 設置所有頭文件路徑到 ./ 即當前路徑查找
CFLAGS = -Werror -I./	

test: $(objs)
	gcc -o test $^
	
#判斷是否包含依賴文件,若不包含,則執行include包含依賴文件命令
ifneq ($(dep_files),)
include $(dep_files)
endif
	
c.o : c.c c.h

#編譯%.o,把依賴寫入文件%.d
%.o : %.c 
	gcc -c -o $@ $< -MD -MF [email protected]  
	
clean:
	rm *.o test
	
distclean:
	rm $(dep_files)
	
.PHONY: clean

 

 

 

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