Makefile入門

0. 作用

Makefile文件告訴Make怎樣編譯和連接成一個(gè)程序扔茅。

1. Makefile基本語法與執(zhí)行

示例

編譯一個(gè)單文件HelloWorld.cpp

  • 編寫Makefile
HelloWorld : HelloWorld.cpp
  g++ HelloWorld.cpp -o HelloWorld
clean :
  rm HelloWorld
  • 編譯
make
  • 清空
make clean

構(gòu)成

Makefile主要由多條規(guī)則構(gòu)成已旧,每條規(guī)則由三部分構(gòu)成:目標(biāo)(target)、依賴(prerequiries)和命令(command)召娜。

格式

按如下格式編寫Makefile

目標(biāo)(target): 依賴(prerequiries)...
  命令(command)
  • 目標(biāo)(target)通常是要產(chǎn)生的文件的名稱运褪,目標(biāo)的例子是可執(zhí)行文件或OBJ文件。目標(biāo)也可是一個(gè)執(zhí)行的動作名稱玖瘸,諸如‘clean’(僅僅表達(dá)動作的目標(biāo)稱為假想目標(biāo))吐句。
  • 依賴是用來輸入從而產(chǎn)生目標(biāo)的文件,一個(gè)目標(biāo)經(jīng)常有幾個(gè)依賴店读。
  • 命令是Make執(zhí)行的動作,一個(gè)規(guī)則可以含有幾個(gè)命令攀芯,每個(gè)命令占一行屯断。

注意:每個(gè)命令行前面必須是一個(gè)Tab字符,即命令行第一個(gè)字符是Tab侣诺。這是不小心容易出錯的地方殖演。

說明

  1. 默認(rèn)情況下,make最先執(zhí)行第一條年鸳。
  2. 使用make 目標(biāo)名的方式趴久,執(zhí)行指定的規(guī)則。

2. Makefile多文件編譯

示例

  • String.h
#ifndef _STRING_H_
#define _STRING_H_
#include <iostream>
using namespace std;
#include <string.h>
class String{
public:
    String(const char* cstr = NULL);
    String(const String& str);
    String& operator=(const String& str);
    ~String();
    char* c_str() const {
        return m_data;
    }
private:
    char* m_data;
};
ostream& operator<<(ostream& os, const String& str);
#endif // _STRING_H_
  • String.cpp
#include "String.h"
String::String(const char* cstr /*= NULL*/) {
    if (cstr) {
        m_data = new char[strlen(cstr) + 1];
        strcpy(m_data, cstr);
    }
    else {
        m_data = new char[1];
        *m_data = '\0';
    }
}
String::String(const String& str) {
    m_data = new char[strlen(str.m_data) + 1];
    strcpy(m_data, str.m_data);
}
String& String::operator=(const String& str) {
    //檢測是否自我賦值
    if (this == &str)
        return *this;
    delete [] m_data;
    m_data = new char[strlen(str.m_data) + 1];
    strcpy(m_data, str.m_data);
    return *this;
}
String::~String() {
    delete[] m_data;
}
ostream& operator<<(ostream& os, const String& str) {
    os << str.c_str();
    return os;
}
  • StringTest.cpp
#include "String.h"
int main() {
    String s1;
    String s2("hello");
    String s3(s1);  //拷貝構(gòu)造函數(shù)
    cout << s3 << endl;
    s3 = s2;    //拷貝賦值函數(shù)
    cout << s3 << endl;
    return 0;
}
  • makefile
StringTest:StringTest.o String.o
  g++ -o StringTest StringTest.o String.o
StringTest.o:StringTest.cpp String.h
  g++ -c StringTest.cpp
String.o:String.cpp String.h
  g++ -c String.cpp
clean :
  rm StringTest StringTest.o String.o

說明

  1. make執(zhí)行規(guī)則之前搔确,檢查依賴是否存在或者是否最新的彼棍。如果不是則執(zhí)行依賴對應(yīng)的規(guī)則,創(chuàng)建或者更新依賴膳算。

3. 使用變量簡化makefile

每次增加新的文件座硕,需要在makefile的很多地方增加依賴,容易導(dǎo)致遺漏涕蜂』遥可以使用變量可以簡化,避免這種出錯的可能机隙。

  • 變量定義:變量 = 字符串
  • 變量使用:$(變量名)

示例

  • makefile
OBJS = StringTest.o String.o

StringTest:$(OBJS)
  g++ -o StringTest $(OBJS)
StringTest.o:StringTest.cpp String.h
  g++ -c StringTest.cpp
String.o:String.cpp String.h
  g++ -c String.cpp
clean :
  rm StringTest $(OBJS)

在makefile文件中使用名為objects, OBJECTS, objs, OBJS, obj, 或 OBJ的變量代表所有OBJ文件已是約定成俗蜘拉。

說明

  1. 變量是定義一個(gè)字符串,在多處替代該字符串使用有鹿。

4. 命令自動推導(dǎo)

編譯.o文件這類非常普遍并且常用旭旭,規(guī)則也比較簡單

文件名.o:文件名.cpp 頭文件
  g++ -c 文件名.cpp

make提供一種簡化寫法,可以自動推導(dǎo)出該規(guī)則

文件名.o:頭文件

這種簡化規(guī)則稱為隱含規(guī)則印颤,非簡化規(guī)則成為具體規(guī)則您机。

示例

  • makefile
OBJS = StringTest.o String.o

StringTest:$(OBJS)
  g++ -o StringTest $(OBJS)
StringTest.o:String.h
String.o:String.h

clean :
  rm StringTest $(OBJS)
  • 小知識
    通常,規(guī)則按照目標(biāo)進(jìn)行分組。規(guī)則也可以按照依賴分組际看。例如咸产,例子中String.oStringTest.o都依賴String.h。那么仲闽,可以這兩個(gè)合并到一個(gè)規(guī)則中脑溢。
OBJS = StringTest.o String.o

StringTest:$(OBJS)
 g++ -o StringTest $(OBJS)
StringTest.o String.o:String.h

clean :
 rm StringTest $(OBJS)

按照依賴分組規(guī)則可以減少規(guī)則數(shù)量,規(guī)則按照目標(biāo)分組更符合我們?nèi)粘K季S習(xí)慣赖欣。


5. 假想目標(biāo)

表達(dá)動作的目標(biāo)稱為假想目標(biāo)屑彻。通常規(guī)則會生成或者更新與目標(biāo)的同名文件,但是假想目標(biāo)不生成文件顶吮,只是作為幾個(gè)命令組成特殊規(guī)則的名稱社牲。例如例子中的clean,只是執(zhí)行清理動作悴了。如果搏恤,makefile同級目錄存在與假象目標(biāo)同名的文件(例如:clean),那么會導(dǎo)致命令不會被執(zhí)行湃交。所以需要把目標(biāo)顯示聲明為假想目標(biāo)熟空。

.PHONY 目標(biāo)

示例

  • makefile
OBJS = StringTest.o String.o

.PHONY: all clean

all:StringTest

StringTest:$(OBJS)
  g++ -o StringTest $(OBJS)
StringTest.o:String.h
String.o:String.h

clean :
  rm StringTest $(OBJS)

  • 常用假想目標(biāo)
No. 假想目標(biāo) 功能
1 all 這所有目標(biāo)的目標(biāo),一般是編譯所有的目標(biāo)息罗。
2 clean 刪除所有被make創(chuàng)建的文件迈喉。
3 install 安裝已編譯好的程序弊添,就是把目標(biāo)執(zhí)行文件拷貝到指定的目標(biāo)中去。
4 print 列出改變過的源文件澈圈。
5 tar 源程序打tar包備份
6 dist 創(chuàng)建一個(gè)壓縮文件瞬女,一般是把tar文件壓成Z文件诽偷”剑或是gz文件眠冈。

6. 通配符與變量

編譯.o文件可以寫成更通用的方式蜗顽,使用我們之前已經(jīng)定義好的變量$(OBJS)雇盖,自動推導(dǎo)出需要生成的規(guī)則这弧。

  • makefile
OBJS = StringTest.o String.o

.PHONY: all clean

all:StringTest

StringTest:$(OBJS)
  g++ -o StringTest $^
$(OBJS):%.o:%.cpp
  $(CXX) -c $(CXXFLAGS) $< -o $@

.PHONY: clean

clean :
  rm StringTest $(OBJS)

說明

1. 通配符

通配符主要用于匹配文件名,makefile中使用%作為通配符卷哩。從匹配目標(biāo)格式的目標(biāo)名中依據(jù)通配符抽取部分字符串,再按照抽取字符串分配到每一個(gè)依賴格式中產(chǎn)生依賴名尊浓。例如栋齿,使用%.o:%.cpp

2. 自動變量

自動變量是在規(guī)則每次執(zhí)行時(shí)都基于目標(biāo)和依賴產(chǎn)生新值的變量菇用。下面是常用的自動變量惋鸥。

No. 自動變量 含義
1 $< 表示第一個(gè)匹配的依賴
2 $@ 表示目標(biāo)
3 $^ 所有依賴
4 $? 所有依賴中更新的文件
5 $+ 所有依賴文件不去重
6 $(@D) 目標(biāo)文件路徑
7 $(@F) 目標(biāo)文件名稱
3. 預(yù)定義變量

預(yù)定義變量是makefile已經(jīng)定義好的變量,用戶可以在makefile文件中改變變量的值拴鸵。

  • 程序名變量
No. 變量 程序 默認(rèn)值
1 CC C語言編譯程序 cc
2 CXX C++編譯程序 g++
3 AR C++打包程序 ar
4 CPP 帶有標(biāo)準(zhǔn)輸出的C語言預(yù)處理程序 $(CC) -E
5 RM 刪除命令 rm
  • 程序運(yùn)行參數(shù)的變量
No. 變量 程序參數(shù)
1 CFLAGS 用于C編譯器的額外標(biāo)志
2 CXXFLAGS 用于C++編譯器的額外標(biāo)志
3 ARFLAGS 用于C/C++打包器的額外標(biāo)志
4 LDFLAGS 鏈接庫路徑-L
5 LDLIBS 鏈接庫-l

9. 其他

  • 注釋#
  • 換行\
  • 回顯命令@echo

10. 總結(jié)

參考

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市汰现,隨后出現(xiàn)的幾起案子瞎饲,更是在濱河造成了極大的恐慌嗅战,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異本讥,居然都是意外死亡拷沸,警方通過查閱死者的電腦和手機(jī)综慎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門示惊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來钧汹,“玉大人,你說我怎么就攤上這事塘秦∽鹛蓿” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長篷店。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么窃爷? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮逮京,結(jié)果婚禮上草描,老公的妹妹穿的比我還像新娘穗慕。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布份名。 她就那樣靜靜地躺著鲤孵,像睡著了一般普监。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死陆盘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的酸员。 我是一名探鬼主播沥潭,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼因谎,長吁一口氣:“原來是場噩夢啊……” “哼财岔!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起河爹,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤匠璧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后咸这,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體夷恍,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年炊苫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了裁厅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冰沙。...
    茶點(diǎn)故事閱讀 39,834評論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡侨艾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拓挥,到底是詐尸還是另有隱情唠梨,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布侥啤,位于F島的核電站当叭,受9級特大地震影響茬故,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蚁鳖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一磺芭、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧醉箕,春花似錦钾腺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至己英,卻和暖如春间螟,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背损肛。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工厢破, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人荧关。 一個(gè)月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓溉奕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親忍啤。 傳聞我的和親對象是個(gè)殘疾皇子加勤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評論 2 354

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

  • 一.makefile格式 1.makefile 文件一般命名 為makefile 即可,放在目錄下面同波,直接調(diào)出 t...
    浩林Leon閱讀 7,751評論 0 2
  • 來自陳浩的一片老文鳄梅,但絕對營養(yǎng)。 示例工程:3 個(gè)頭文件*.h未檩,和 8 個(gè) C 文件*.c戴尸。 初 編譯過程,源文件...
    周筱魯閱讀 4,696評論 0 17
  • 通常一個(gè)大型程序由多個(gè)模塊文件構(gòu)成的冤狡,按照其功能劃分孙蒙,模塊文件會分布在不同的目錄中,模塊文件之間有包含有頭文件悲雳,調(diào)...
    wayyyy閱讀 1,372評論 0 0
  • makefile關(guān)系到整個(gè)工程的編譯規(guī)則挎峦,一個(gè)工程中的源文件不計(jì)其數(shù),按其類型合瓢、功能坦胶、模塊分別放在若干的目錄當(dāng)中,...
    Joe_HUST閱讀 1,880評論 0 3
  • 洛陽王利華 堅(jiān)持分享第220(2017.12.18)天: 今天給學(xué)生們做了一個(gè)“猜猜看”的游戲。猜之前每...
    驕陽567閱讀 278評論 0 0