Makefile入門

1.初識Makefile

Makefile的作用

Makefile文件告訴Make指令怎樣編譯和連接成一個程序。

Makefile的構成

Makefile主要由多條規則構成,每條規則由三部分構成:目標(target)、依賴(prerequiries)和命令(command)。

Makefile的格式

目標(target): 依賴(prerequiries)...
  命令(command)

_ 目標(target)通常是要產生的文件的名稱,目標的例子是可執行文件或OBJ文件。目標也可是一個執行的動作名稱,諸如‘clean’(僅僅表達動作的目標稱爲假想目標)。
_ 依賴是用來輸入從而產生目標的文件,一個目標經常有幾個依賴。
_ 命令是Make執行的動作,一個規則可以含有幾個命令,每個命令佔一行。
注意:每個命令行前面必須是一個Tab字符,即命令行第一個字符是Tab。這是不小心容易出錯的地方。

說明

1.默認情況下,make最先執行第一條。
2.使用make 目標名的方式,執行指定的規則。

2.Makefile多文件編譯

1.測試代碼
String.h

#ifndef _STRING_H_ 
#define _STRING_H_ 
#include <iostream> 
#include <string.h>
using namespace std;

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"
using namespace std;
int main() {
    String s1;
    String s2("hello");
    String s3(s1);  //拷貝構造函數
    cout << s3 << endl;
    s3 = s2;    //拷貝賦值函數
    cout << s3 << endl;
    return 0;
}

Makefile

**//目標:依賴**
StringTest:String.o StringTest.o String.h
**//命令**
    g++ -o StringTest StringTest.o String.o
String.o:String.cpp
    g++ -c String.cpp
StringTest.o:StringTest.cpp
    g++ -c StringTest.cpp
**//假想目標**
clean:
    rm String.o StringTest.o StringTest

說明

make執行規則之前,檢查依賴是否存在或者是否最新的。如果不是則執行依賴對應的規則,創建或者更新依賴。
實際項目中的cpp文件是很多的,所以我們要在makefile中分開使得cpp文件先生成.o文件,然後再鏈接,這樣可以避免修改文件導致所有文件都要重新的編譯,浪費時間。

3.Makefile的簡化

每次增加新的文件,需要在makefile的很多地方增加依賴,容易導致遺漏。可以使用變量可以簡化,避免這種出錯的可能。
_ 變量定義:變量 = 字符串
_ 變量使用:$(變量名)

//定義了一個變量OBJ
OBJ = StringTest
//$(OBJ)此時相當於宏替換,替換成StringTest
$(OBJ):String.o StringTest.o String.h

說明:
在makefile文件中使用名爲objects, OBJECTS, objs, OBJS, obj, 或 OBJ的變量代表所有OBJ文件已是約定成俗。
簡化後的Makefile

OBJ = StringTest.o String.o
StringTest:$(OBJ)
    g++ -o StringTest $(OBJ)
String.o:String.cpp
    g++ -c String.cpp
StringTest.o:StringTest.cpp
    g++ -c StringTest.cpp
clean:
    rm $(OBJ) StringTest

4. 命令自動推導

makefile提供了自動推導的規則,可以通過頭文件.h來推導其對應的.cpp文件並且生成.o文件

文件名.o:頭文件
這種簡化規則稱爲隱含規則,非簡化規則成爲具體規則。

簡化後的Makefile

OBJS = StringTest.o String.o 
StringTest:$(OBJS) 
    g++ -o StringTest $(OBJS) 
//根據頭文件自動推倒
StringTest.o String.o:String.h 
//按照依賴分組規則可以減少規則數量,規則按照目標分組更符合我們日常思維習慣。
clean : 
    rm StringTest $(OBJS)

5.假想目標

表達動作的目標稱爲假想目標。通常規則會生成或者更新與目標的同名文件,但是假想目標不生成文件,只是作爲幾個命令組成特殊規則的名稱。例如例子中的clean,只是執行清理動作。如果,makefile同級目錄存在與假想目標同名的文件(例如:clean),那麼會導致命令不會被執行。所以需要把目標顯示聲明爲假想目標。

.PHONY 目標

舉個栗子

OBJS = StringTest.o String.o 

.PHONY: all clean 

all:StringTest 

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

clean : 
    rm StringTest $(OBJS)
NO. 假想目標 功能
1 all 這所有目標的目標,一般是編譯所有的目標。
2 clean 刪除所有被make創建的文件。
3 install 安裝已編譯好的程序,就是把目標執行文件拷貝到指定的目標中去。
3 print 列出改變過的源文件。
3 tar 源程序打tar包備份
3 dist 創建一個壓縮文件,一般是把tar文件壓成Z文件。或是gz文件。

6.通配符與變量

6.1通配符

通配符主要用於匹配文件名,makefile中使用%作爲通配符。從匹配目標格式的目標名中依據通配符抽取部分字符串,再按照抽取字符串分配到每一個依賴格式中產生依賴名。例如,使用%.o:%.cpp

6.2自動變量

自動變量是在規則每次執行時都基於目標和依賴產生新值的變量。下面是常用的自動變量。

NO. 自動變量 含義
1 $< 表示第一個匹配的依賴
2 $@ 表示目標
3 $^ 所有依賴

6.3預定義變量

程序名變量

變量 程序 默認值
CC C語言編譯程序 cc
CXX C++編譯程序 g++
CPP 帶有標準輸出的C語言預處理程序 $(CC) -E

程序運行參數的變量

變量 程序參數
CFLAGS 用於C編譯器的額外標誌
CXXFLAGS 用於C++編譯器的額外標誌

簡化後的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)

匹配規則推倒

這裏寫圖片描述

其他

 註釋#
 換行\
 回顯命令@echo
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章