實踐5 . Makefile文件編寫


1 簡介

Makefile是用來完成構(gòu)建距贷,編譯整個工程文件的工具柄冲。所以,Makefile定義了一系列的規(guī)則忠蝗,按照這個規(guī)則现横,即可生成可執(zhí)行文件或者中間文件等等。擴展開來什湘,與Makefile功能相似的工具有cmake,scons等等长赞。

在執(zhí)行make命令的時候,會在當前目錄下按順序查找文件名為"GNUmakefile"闽撤,"makefile"得哆,"Makefile"的文件。

1.1 參考資料

1.官方手冊:鏈接 (make 4.2版本)
2.從網(wǎng)絡上下載的Makefile教程:鏈接
3.簡單的Makefile文件編寫介紹:鏈接

1.2 環(huán)境

我使用的Make工具版本為:


Make工具版本信息

CPU等信息如下:


電腦配置

系統(tǒng)為64位的哟旗。

系統(tǒng)版本

我使用的代碼編輯工具為bluefish贩据。

需要額外安裝的工具為:

$ sudo apt-get install tree

2 開始編寫

2.1 示例

先看一個簡單的示例:
首先,我編寫兩個文件闸餐,一個是main.c饱亮,一個是Makefile文件,內(nèi)容分別如下:
main.c文件內(nèi)容:

#include <stdio.h>
static void main_show()
{
    printf("---main show---\r\n");
}
int main(int argc,char *argv[])
{
    main_show();
    return 0;   
}

Makefile內(nèi)容:

target:main.o
    gcc -o target main.o
    
main.o:main.c
#   gcc -c -o main.o main.c
    gcc -c main.c
clean:
    rm *.o target -rf

將它們保存在同一目錄位置下舍沙,然后執(zhí)行:

$ make
執(zhí)行make后生成可執(zhí)行文件target
執(zhí)行程序

通過這個示例近上,我們需要簡單的知道幾點:

1.Makefile的基本規(guī)則:

target(目標):prerequisites(依賴)
command(命令)

目標:
可以是可執(zhí)行文件,也可以僅僅是一個標簽而已拂铡。
依賴:
也就是要生成目標所需要的文件壹无。
命令:
也就是執(zhí)行make需要執(zhí)行的命令葱绒。
上面所列出了的內(nèi)容,如果構(gòu)成了一個整體斗锭,這也叫顯示規(guī)則地淀。

2.makefile的注釋是使用'#'。
3.make執(zhí)行的時機是依賴文件比目標文件新岖是。
4.Makefile中的command(命令)帮毁,需要以Tab開始。

2.2 進一步的示例

main.c程序如下所示:

#include <stdio.h>

static void main_show()
{
    printf("---main show---\r\n");
}

int main(int argc,char *argv[])
{
    main_show();

    return 0;   
}

Makefile文件格式如下:

CC = gcc

target:main.o
    $(CC) -o target main.o
    
main.o:main.c
#   gcc -c -o main.o main.c
#   gcc -c main.c
clean:
    rm *.o target -rf   
    @echo "---make end---"
make后的執(zhí)行結(jié)果

這里面所要說的就只要三個知識點:
1.自動推導豺撑,我們使用'#'注釋了gcc -c上的編譯內(nèi)容烈疚,然而,make中的自動推導前硫,還是會執(zhí)行注釋中的內(nèi)容胞得。
2.makefile中的變量,從上面的例子中屹电,可以看到阶剑,引用變量的值,需要使用$危号。

這里所使用的推導牧愁,也叫隱式規(guī)則。
3.在rm文件的時候外莲,使用了-rf標識猪半,這里是標識就算沒有文件,也不要在控制臺上報錯偷线,我們也可以將rm改為'-rm'磨确。這里對于inclulde <makefile>也是適用的,也就是說声邦,在當前目錄乏奥、/usr/local/bin、/usr/include等都未找到'makefile'文件的情況下亥曹,可以忽略致命錯誤邓了,繼續(xù)執(zhí)行下去。
4.可以適用@echo回顯內(nèi)容媳瞪,這對于我們調(diào)試一些makefile中的命令是很有幫助的骗炉,相當于我們在調(diào)試程序的時候使用printf。

2.3 自動化變量

自動化變量需要掌握的有幾個蛇受,分別為:$@ 句葵、$<、$^ 。
$@:
表示規(guī)則的目標文件名笼呆。
$<:
表示規(guī)則的第一個依賴文件名熊响。
$^:
表示規(guī)則的所有依賴文件列表。

我們在同一目錄下诗赌,建立三個文件,一個是main.c秸弛,一個是main_a.c铭若,一個是Makefile文件。
main.c內(nèi)容如下:

#include <stdio.h>

static void main_show()
{
    printf("---main show---\r\n");
}

int main(int argc,char *argv[])
{
    main_show();
    main_a_show();
    return 0;   
}

main_a.c內(nèi)容為:

#include <stdio.h>

void main_a_show()
{
    printf("---main_a_show---\r\n");    
}

Makefile內(nèi)容為:

CC = gcc

requires = main.o main_a.o

target:$(requires)
    $(CC) -o target $^
    
$(requires):%.o:%.c
    $(CC) -c  $< -o  $@

clean:
    rm *.o target -rf   
    @echo "---make end---"

從這個makefile中提煉出來的規(guī)則是:

target(目標):target-pattern(目標模式):prereq-patterns(依賴模式)
commands(命令)

當然可以簡化為:

target-pattern(目標模式):prereq-patterns(依賴模式)
commands(命令)

上面使用的方式递览,我們稱為靜態(tài)模式規(guī)則叼屠。

2.4 自動生成依賴關(guān)系

這比較適用于那些需要根據(jù)條件,自己尋找相應的.h文件的情況绞铃。做一個簡單的說明镜雨,比如新建一個main_a.h文件,里面定義一個#define MAIN_A 4儿捧,但是在makefile中并不做多余的說明荚坞,那么第一次編譯,然后獲取結(jié)果菲盾,是能夠得到正確的結(jié)果的颓影,但是,如果我們修改main.c文件的內(nèi)容懒鉴,然后修改main_a.h的內(nèi)容诡挂,將4改為5,再次執(zhí)行整個文件临谱,會發(fā)現(xiàn)打印的值仍然是4璃俗,這就與實際情況相悖。歸根結(jié)底悉默,我們需要讓makefile自動去推斷有哪些.h文件城豁,然后更新之后,也需要重新做出更改麦牺。

這里就需要了解一個選項'-M'
如下圖所示的適用方法:


-M的使用
-MM操作

2.5 Makefile中的函數(shù)

包括filter钮蛛,wildcard,patsubst等函數(shù)剖膳,以及sed魏颓,tr,grep等linux工具函數(shù)的配合使用:
貼上一個包含多個.c文件的文件夾下的Makefile:

CC     = arm-linux-gnueabihf-gcc
CFLAGS = -lpthread -lm

FILES   = $(wildcard *.c)
OBJS    = $(patsubst %.c,%.o,$(FILES))
TARGET  = socket

$(TARGET):$(OBJS)
        $(CC) -o $@ $^ $(CFLAGS)
clean:
        -rm *.o -rf

在該文件生效后吱晒,會在該目錄下生成一個socket的可執(zhí)行程序甸饱。

接著這個來說,如果我們的目錄下有很多的文件夾,文件夾下有很多的C文件叹话,這個時候有一個笨方法偷遗,也是一個比較簡單的方法,就是一個個文件加進去即可驼壶。
比如氏豌,我有一個文件夾,文件夾下有兩個文件热凹,分別為spi.c和spi.h泵喘,文件夾為spi,如下圖所示的結(jié)構(gòu)(.o暫時不用看):


spi文件夾與文件夾下內(nèi)容

我們可以寫的一個很笨的Makefile如下所示:

CC     = arm-linux-gnueabihf-gcc
CFLAGS = -lpthread -lm

TARGET  = socket
OBJS    = $(patsubst %.c,%.o, $(wildcard *.c))

$(TARGET):$(OBJS) spi/spi.o
        $(CC) -o $@ $^ $(CFLAGS)

clean:
        rm $(TARGET)  *.o

按照這個思路般妙,我們繼續(xù)做(使用sed,awk,tr,grep等等字符串操作命令)
首先我們需要提取出目錄纪铺。
這個比較簡單,我們使用如下命令即可:

wityuan@ubuntu:~/Desktop/A20_driver/socket_spi_bak$ ls -l | grep '^d'
drwxrwxr-x 2 wityuan wityuan  4096  9月 12 21:54 spi
wityuan@ubuntu:~/Desktop/A20_driver/socket_spi_bak$

現(xiàn)在我們所要做的就是將spi提取出來碟渺。
按照上面的字符串格式鲜锚,我們可以按照空格將字符串進行分割,spi剛好是第九個部分苫拍。
所以使用awk的正則表達進行切分芜繁。

$ ls -l | grep "^d" | awk '/ /{print $9}'

最終,提取文件夾的Makefile測試程序可以如下操作:

DIRS = $(shell ls -l | grep '^d' | awk '/ /{if($$9 != "test") print $$9}')
file:
        @echo $(DIRS)

在這個思路的指導下怯疤,我寫出的一個Makefile如下:

CURRENT_DIR = $(shell pwd)

DIRS = $(shell ls -l | grep '^d' | awk '/ /{if($$9 != "test") print $$9}')

DIRS_FILE = $(foreach v,$(DIRS),-I $(CURRENT_DIR)/$v)

CC     = arm-linux-gnueabihf-gcc
CFLAGS = -lpthread -lm -I $(CURRENT_DIR) $(DIRS_FILE)

TARGET  = socket
OBJS    = $(patsubst %.c,%.o, $(wildcard *.c))

DIRS_C = $(patsubst %.c,%.o,$(wildcard $(DIRS)/*.c))

$(TARGET):$(OBJS) $(DIRS_C)
        $(CC) -o $@ $^ $(CFLAGS)
        
clean:
        rm $(TARGET)  *.o

其中DIRS_C目前支持1個文件夾浆洗。

解釋如下:
假若有一個文件夾,為spi集峦。則DIRS=spi伏社,DIRS_FILE為所有的類似DIRS文件。

2.6 待續(xù)塔淤。

http://www.cnblogs.com/Shirlies/p/4282182.html

3 學習開源項目的Makefile編寫

3.1 OSC

該源碼在官方上看起來已經(jīng)不好找了摘昌。
資源鏈接地址: 點我下載
這份源碼的Makefile最為簡單。

3.2 uboot

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末高蜂,一起剝皮案震驚了整個濱河市聪黎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌备恤,老刑警劉巖稿饰,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異露泊,居然都是意外死亡喉镰,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門惭笑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侣姆,“玉大人生真,你說我怎么就攤上這事∞嘧冢” “怎么了柱蟀?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蚜厉。 經(jīng)常有香客問我长已,道長,這世上最難降的妖魔是什么昼牛? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任痰哨,我火速辦了婚禮,結(jié)果婚禮上匾嘱,老公的妹妹穿的比我還像新娘。我一直安慰自己早抠,他們只是感情好霎烙,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蕊连,像睡著了一般悬垃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上甘苍,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天尝蠕,我揣著相機與錄音,去河邊找鬼载庭。 笑死看彼,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的囚聚。 我是一名探鬼主播靖榕,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼顽铸!你這毒婦竟也來了茁计?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤谓松,失蹤者是張志新(化名)和其女友劉穎星压,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鬼譬,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡娜膘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了拧簸。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片劲绪。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出贾富,到底是詐尸還是另有隱情歉眷,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布颤枪,位于F島的核電站汗捡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏畏纲。R本人自食惡果不足惜扇住,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望盗胀。 院中可真熱鬧艘蹋,春花似錦、人聲如沸票灰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽屑迂。三九已至浸策,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間惹盼,已是汗流浹背庸汗。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留手报,地道東北人蚯舱。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像昧诱,于是被迫代替她去往敵國和親晓淀。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理盏档,服務發(fā)現(xiàn)凶掰,斷路器,智...
    卡卡羅2017閱讀 134,637評論 18 139
  • 來自陳浩的一片老文蜈亩,但絕對營養(yǎng)懦窘。 示例工程:3 個頭文件*.h,和 8 個 C 文件*.c稚配。 初 編譯過程畅涂,源文件...
    周筱魯閱讀 4,690評論 0 17
  • makefile關(guān)系到整個工程的編譯規(guī)則,一個工程中的源文件不計其數(shù)道川,按其類型午衰、功能立宜、模塊分別放在若干的目錄當中,...
    Joe_HUST閱讀 1,876評論 0 3
  • Ubuntu的發(fā)音 Ubuntu灯帮,源于非洲祖魯人和科薩人的語言,發(fā)作 oo-boon-too 的音逻住。了解發(fā)音是有意...
    螢火蟲de夢閱讀 99,215評論 9 467
  • 你從窗臺的盛夏走來 敲著玻璃 問我索要一個理由 風從未能聽說的地方 走過我衣角 它不說話瞎访,就讓我難過 我來不及 牽...
    Damiel閱讀 208評論 0 0