Makefile入门

本文详细介绍Makefile的基础概念、编写格式及实例,涵盖工作流程、通配符使用、变量定义与赋值、目标文件搜索和嵌套执行make等内容,是Linux环境下工程构建的实用教程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Makefile文件介绍

Makefile一般为Linux环境下的工程项目构建工具,描述了整个工程的编译和链接情况

二、Makefile文件的hello world编写

1、编写格式

规则的目标:依赖的文件
	执行的命令

其中,规则的目标可以为:中间文件/可执行文件/标签;
依赖的文件可以为:生成规则的目标所需要的文件或者目标或者是没有;
执行的命令可以为:任意的shell命令
注意:命令的开始用Tab隔开

2、实例

//Makefile 文件

test:test.cpp
        g++ -o test test.cpp

//test.cpp文件

#include<iostream>
using namespace std;
int main()
{
    cout<<"hello makefile."<<endl;
    return 0;
}

在当前目录中执行:make(自动寻找Makefile 文件);即可得到执行文件test。

二、Makefile的工作流程

1、工作流程

以下面的Makefile 文件为例
//Makefile 文件

test:test.o
        g++ -o test test.o
test.o:test.cpp
        g++ -o test.o -c test.cpp

这里有两个规则和两个命令,以第一个目标为终极目标,第一个目标的执行依赖test.o文件,而执行生成test.o文件需要第二个目标作为前提,执行过程是,假如test.o文件没有变化,则直接运行第一个目标结束,这样可以提高效率;假如test.o文件有变化继续执行下面的命令。

2、清除过程文件

当执行新的make命令的之前,可能想删除之前生成的test.o和test可执行文件,其Makefile 文件编写如下:
//Makefile 文件

test:test.o
        g++ -o test test.o
test.o:test.cpp
        g++ -o test.o -c test.cpp
.PHONY:clean
clean:
        rm -rf *.o test

其中,目标 clean 是一个伪目标(伪目标不会创建目标文件,但是会执行下面的命令);将一个目标声明称伪目标的方法是将它作为特殊的目标.PHONY的依赖。如上所示,clean是.PHONY的依赖,目标 clean的依赖为空(依赖的文件可以为:生成规则的目标所需要的文件或者目标或者是没有)。

由于clean是一个伪目标,不是一个具体的文件,与最终的目标test没有依赖的关联,因此执行make命令时候,不会执行它的命令。最后的效果为:(1)执行make命令会生成test和test.o,不会执行clean下的命令(2)执行make clean命令的时候,执行clean下的命令,删除之前生成的test.o和test可执行文件。

三、通配符的使用

1、通配符

与shell支持的通配符一致,有:
(1)*:0或任意个字符
(2)?:匹配任意一个字符
(3)[]:将指定匹配的字符放在 “[]” 中

2、实例

一共有文件:main.cpp 、 test01.cpp 、 test01.h 、 test02.cpp 、 test02.h

//main.cpp   ==========================
#include"test01.h"
#include"test02.h"
#include<iostream>
using namespace std;
int main()
{
    print01();
    print02();
    cout<<"hello makefile."<<endl;
    return 0;
}
//test01.cpp   ==========================
#include"test01.h"
#include<iostream>
using namespace std;
void print01()
{
  cout<<"I am test01!"<<endl;
}
//test01.h   ==========================
#ifndef __TEST01_H__
#define __TEST01_H__
void print01();
#endif
//test02.cpp   ==========================
#include"test02.h"
#include<iostream>
using namespace std;
void print02()
{
  cout<<"I am test02!"<<endl;
}
//test02.h   ==========================
#ifndef __TEST02_H__
#define __TEST02_H__
void print02();
#endif

Makefile 文件编辑如下:
//Makefile

main:*.cpp
        g++ -o $@ $^

其中,通配符出现在规则中;$@为自动化变量,表示规则的目标文件名(即main);$^也为自动化变量,表示所有依赖文件列表(即*.cpp,这里是main.cpp、test01.cpp、test02.cpp)

四、Makefile变量的定义和赋值

1、变量的定义与使用

格式:

变量的名称=值列表

其中,值列表可以0项或1项或多项

变量的使用:
$(VALUE_LIST)${VALUE_LIST}

例子:
//Makefile

OBJ = main.cpp test01.cpp test02.cpp
main:$(OBJ)
        g++ -o $@ $(OBJ)

2、变量的赋值

(1)简单赋值:=

只对当前语句的变量有效
例子:
//Makefile

x:=foo
y:=$(x)b
x:=new
test:
        @echo "y=>$(y)"
        @echo "x=>$(x)"

输出:

y=>foob
x=>new

第2行变量x已经赋值y,但是简单赋值只对当前语句的变量有效,因此执行x:=new后y的值不变

(2)递归赋值=

与目标变量相关的变量都会受到影响
例子:
//Makefile

x:=foo
y=$(x)b
x=new
test:
        @echo "y=>$(y)"
        @echo "x=>$(x)"

输出:

y=>newb
x=>new

注意: y=$(x)b中不能是:=,否则无法影响y

(3)条件赋值?=

如果变量未定义,则使用符号中的值去定义变量;如果该变量已经赋值,则赋值语句无效。
例子:

x:=foo
y:=$(x)b
x?=new
test:
        @echo "y=>$(y)"
        @echo "x=>$(x)"

输出:

y=>foob
x=>foo

可以看出x?=new赋值无效,因为变量x已经赋值

(3)追加赋值+=

追加的结果为:原来的值+空格+新值

五、目标文件的搜索(VPATH和vpath)

1、VPATH

VPATH是一个环境变量,与小写的vpath是有区别的,搜索的过程为:当前目录=》VPATH设置的目录
格式:

VPATH:=path1 path2 ...

或者

VPATH:=path1:path2:...

举例:
//Makefile

VPATH:=src
main:main.cpp test01.cpp test02.cpp
        g++ -o $@ $^

其中,Makefile文件与src目录在同一级目录中,所有的代码文件在子目录src目录中,执行make,则在当前目录生成main可执行文件

2、vpath

vpath 是关键字,按照模式搜索,给出了搜索的条件
格式:

(1) vpath PATTERN DIRECTORIES 
vpath test.cpp src // 在目录src中搜索test.cpp
(2  vpath PATTERN
//除符合文件PATTERN 的搜索目录
(3)  vpath
//除所有已被设置的文件搜索路径

六、嵌套执行make

嵌套执行make的作用在于可以将不同模块编写一个Makefile文件,然后做最外层写总的Makefile文件控制所有的Makefile文件执行
格式:

subsystem:
    cd subdir && $(MAKE)

或者

subsystem:
    $(MAKE) -C subdir

其中,subdir目录是一个子目录,里面也有个Makefile文件;上面的执行步骤即为进入到子目录subdir执行Makefile文件。

参考:http://c.biancheng.net/view/7097.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值