Makefile入门

原创 2018年04月16日 15:55:00

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

makefile:简单入门

简单的入门操作,高手请无视. C.h 文件 #ifndef __C__HEADER #define __C__HEADER class C { public: C(); C(C& c...
  • AndroidBluetooth
  • AndroidBluetooth
  • 2015-03-28 22:28:47
  • 1183

makefile书写入门

首先声明,本篇文章是根据陈皓博客中的相关文章改写的。原因是那篇文章太全面了,而本文抽取了其中比较实用的几点,以一个使用者的角度来说明一下,makefile改怎么写,而且只限定是linux下的C语言的m...
  • cyfcsd
  • cyfcsd
  • 2016-07-29 16:54:06
  • 2959

Makefile 入门与基本语法

在我看来,学会写简单的Makefile,阅读较复杂的makefile,是每一个Linux程序员都必须拥有的基本素质。Makefile可以自动识别哪些源文件被更改过,需要重新编译,那些不需要。从而节省大...
  • Paul_C_V
  • Paul_C_V
  • 2015-05-18 11:16:09
  • 7875

【 Makefile 编程基础之一】详细介绍Makefile概念和其机制用途;

本站文章均为 李华明Himi 原创,转载务必在明显处注明:转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/gcc-makefile/766.html   ...
  • xiaominghimi
  • xiaominghimi
  • 2012-05-25 18:59:56
  • 3523

MakeFile入门详解

makefile很重要       什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和profess...
  • qq_15807167
  • qq_15807167
  • 2016-12-06 17:19:55
  • 665

eigen入门

一 简介 Eigen是一个高层次的C ++库,有效支持线性代数,矩阵和矢量运算,数值分析及其相关的算法。Eigen是一个开源库,从3.1.1版本开始遵从MPL2许可。 系统环境 : ubuntu1...
  • harbor1981
  • harbor1981
  • 2017-06-28 15:11:55
  • 180

makefile入门

  • 2014年05月06日 17:21
  • 95KB
  • 下载

跟我一起写+Makefile

  • 2011年03月14日 16:46
  • 265KB
  • 下载

C# 入门经典 XML Makefile

  • 2010年06月25日 00:46
  • 1.22MB
  • 下载

GCC和MakeFile入门代码一

  • 2009年11月17日 15:19
  • 963B
  • 下载
收藏助手
不良信息举报
您举报文章:Makefile入门
举报原因:
原因补充:

(最多只允许输入30个字)