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

猜你喜欢

转载自blog.csdn.net/linzetao233/article/details/79961580