makefile文件详解
1. make
- 编译:将源代码文件翻译成处理器可执行的二进制文件的过程,这个过程的时间区间称为编译时
- 构建:指定多个编译过程的先后顺序
make命令是常用的构建工具,诞生于1977年,主要用于C/C++项目工程的构建,make命令的适用场景:只要某一个或多个文件发生变动,就要重新构建项目
2. Makefile
make的语义是制作,制作出某样工件,工件可以是各种可执行文件、中间文件、镜像等,通过Makefile文件描叙构建工件的过程,构建过程由一个或多个规则组成
make 命令默认使用工程项目目录下的Makefile文件,可以通过
-f--file选项指定其位置的Makefile文件规则(rules)
<target>: <precondition> ...
|table|<command>
...
规则文法:
1. 冒号前面的 <target> 是构建的目标,可以是所构建对象的文件名,或者构建过程达成的目标名
2. 冒号后面的 <precondition> ... 是前置条件,判断目标是否重新构建,重新构建的条件为:只要有一个前置文件不存在或者有过更新(前置文件的mtime比目标的mtime新),跳过已经编译但未修改的文件,降低总编译时间
3. |table| 是一个缩进,必须以该字符起首
4. <command> 是命令,达成该目标需要执行的子命令
5. |table| <command> 可以有多个,是具体的执行过程,<prerequest> |table|<command> 至少存在一个
2.1 目标 -- target
一个目标构成一条规则
- 目标可以是文件名
# 会在目录下创建 a.txt b.txt文件,b.txt文件先于a.txt文件创建,若b.txt文件的mtime时间戳比a.txt文件的时间戳新则重新执行a.txt的构建过程
# 通过判断当前工程目录下的文件是否存在,判断是否重新执行目标的构建过程
a.txt: b.txt
cat b.txt > a.txt
b.txt:
echo "make comand" > b.txt
- 目标可以是某个操作名,若工程目录存在与操作同名的文件,就会跳过该目标的执行过程,可以通过 .PHONY声明为伪目标,不会检查目标名对应的文件是否存在
# 若当前工程目录下已存在clean文件,则跳过,可以通过 .PHONY指定该目标是一个非文件目标
.PHONY: clean
clean:
rm a.txt b.txt
2.2 前置条件 -- precondition
一组以空格隔开的文件名,用于判断目标是否重新构建,如果至少有一个文件不存在或者文件的最后修改时间比目标文件的最后修改时间新,则重新构建该目录
# 会首先依次构建前置条件中的目标文件,最后构建目标文件,反复构建,只要前置条件中的文件最后修改时间戳比目标文件小则跳过目标文件的构建过程
result.txt: file1.txt file2.txt file3.txt
cat file1.txt file2.txt file3.txt > result.txt
file1.txt:
echo "file1" > file1.txt
file2.txt:
echo "file2" > file2.txt
file3.txt:
echo "file3" > file3.txt
2. 3 命令 -- command
描叙目标是如何创建出来的,由一个或多个shell命令描叙,是构建目标的具体指令,每一行命令在一个进程中并行执行
- 每个构建命令在各自的shell进程中执行,通过 .ONESHELL指定目标的命令集合都在同一个shell进程中串行
# 看不到变量NAME的值,需要使用$进行$符号的转义,输出不了变量的值
var-get:
export NAME=cloud
echo $$NAME
# 写在一行的方式,以分号隔开shell指令
var-get:
export NAME=cloud;echo $$NAME
# export 与 echo 指令都在同一个shell进程中运行
.ONESHELL:
var-get:
export NAME=cloud
echo $$NAME
- 可以通过 .RECIPEPREFIX 修改命令的前缀,默认为Table字符
result.txt: file1.txt file2.txt file3.txt
cat file1.txt file2.txt file3.txt > result.txt
# 之后的构建目标的指令列表由 > 开头
.RECIPEPREFIX = >
file1.txt:
> echo "file1" > file1.txt
file2.txt:
> echo "file2" > file2.txt
file3.txt:
> echo "file3" > file3.txt
3. 文法
向make命令描叙字符文字的语法与语义
3.1 注释
以 # 开头,到行尾结束,Bash 与 Python语言 的注释也一样
# export 与 echo 指令都在同一个shell进程中运行
.ONESHELL:
var-get:
export NAME=cloud # 设置一个环境变量
echo $$NAME # 输出环境变量的值
3. 2 回声
echo -- 执行make命令会打印出每个目标的命令然后再执行,在命令的最开头添加
@关闭回声
# export 与 echo 指令都在同一个shell进程中运行
.ONESHELL:
var-get:
@export NAME=cloud
echo $$NAME
3.2 通配符
选定一组文件名符合通配符的文件,文法规则和bash一致
- 单个字符
? - 任意长度任意字符
* - 字符集中单个字符
[]
# 删除所有以 .0 结尾的文件
clean:
rm -f *.o
3.3 模式匹配
选定文件名相同,但文件类型不同的文件
# 所有 .c 结尾的文件通过命令生成同名的.o文件
%.o: %.c
3. 4 变量与赋值符
声明变量并存储值,在之后代码中访问并引用变量中值
- 赋值
=:=?=+=
VARIABLE = value
# 在执行时扩展,允许递归扩展。
VARIABLE := value
# 在定义时扩展。
VARIABLE ?= value
# 只有在该变量为空时才设置值。
VARIABLE += value
# 将值追加到变量的尾端。
- 访问值
通过 $()访问,访问bash变量需要加上$进行转义
# 访问定义的变量与bash变量
name = dream_flish
get-variable:
@echo $(name)
@echo $$HOME
- 内置变量
当前编辑器
CC,当前使用的make工具$(MAKE)
# 访问定义的变量与bash变量
name = dream_flish
get-variable:
@echo "$(CC) $(MAKE)"
@echo $$HOME
- 自动变量
变量的值与当前的规则的目标与前置条件相关
1. $@ 当前目标
2. $< 第一个前置条件
3. $? 比目标文件mtime时间戳更新的前置条件文件,多个以空格隔开
4. $^ 所有前置条件
5. $* 匹配 % 部分
6. $(@D) 目标当前目录名
7. $(@F) 目标当前文件名
8. $(<D) 第一个前置条件的目录名
9. $(<F) 第一个前置条件的文件名
a.txt: b.txt c.txt
echo $@ # 等价 echo a.txt
cat $^ > a.txt # 等价 cat b.txt c.txt > a.txt
b.txt:
echo "b" > b.txt
c.txt:
echo "c" > c.txt
3. 5 判断与循环
流程控制,满足条件时执行一段代码,不满足时执行另一段代码,利用Bash代码实现循环
BOY_NAMES = ALEX BEI XIXI
GIRL_NAMES = LANGLANG XUEXUE XIAOXIAO
CONDATION = BOY
# 等值判断
ifeq ($(CONDATION), BOY)
NAMES=$(BOY_NAMES)
else
NAMES=$(GIRL_NAMES)
endif
# 访问变量中的值
all:
for name in $(NAMES); do echo $$name; done
4. 函数
完成某项功能的指令集合,调用文法: $(函数名, 参数 ... )
- shell函数 -- 执行shell命令
files := $(shell seq 1 10)
all:
echo $(files)
- wildcard 通配符函数 -- 替换Bash的通配符
# 列出 src目录下所有以.tst后缀结尾的文件
files := $(wildcard src/*.txt)
all:
echo $(files)
- subst函数 -- 文本替换
# 小写的i换成大写的I
result := $(subst i,I,i Love C++)
all:
echo $(result)
5. 编译 C++代码
- 在工程目录创建
src目录,再在src目录下创建main.cpp文件,写入以下内容
#include <iostream>
int main() {
std::cout << "I Love C++\n";
}
- 在工程目录下创建
Makefile文件,写入以下规则
TARGET_DIR = bin
all:
[ ! -d $)TARGET_DIR ] && mkdir -p $(TARGET_DIR); \
c++ src/main.cpp -o $(TARGET_DIR)/main
clean:
rm -f bin/*
- 在工程目录执行构建命令并执行编译后的结果
# 编译,没有目标则默认找到的第一个目标
make
# 执行,会输出 I Love C++
./bin/main
# 清理,make命令中输出目标名,多个目标以空格隔开
make clean
makefile文件详解的更多相关文章
- MakeFile 文件详解
GNU的make工作时的执行步骤入下:(想来其它的make也是类似) 1.读入所有的Makefile. 2.读入被include的其它Makefile. 3.初始化文件中 ...
- Android.mk文件详解(转)
源:Android.mk文件详解 从对Makefile一无所知开始,折腾了一个多星期,终于对Android.mk有了一个全面些的了解.了解了标准的Makefile后,发现Android.mk其实是把真 ...
- Android.mk文件和Application.mk文件详解
Android.mk文件和Application.mk文件详解 相同点:都是轻量级 Makefile(Makefile文件定义一些列指令,指定文件编译顺序,类似shell脚本) Application ...
- web.xml文件详解
web.xml文件详解 Table of Contents 1 listener. filter.servlet 加载顺序 2 web.xml文件详解 3 相应元素配置 1 listener. f ...
- Linux中/proc目录下文件详解
转载于:http://blog.chinaunix.net/uid-10449864-id-2956854.html Linux中/proc目录下文件详解(一)/proc文件系统下的多种文件提供的系统 ...
- SUBLIME TEXT 2 设置文件详解
SUBLIME TEXT 2 设置文件详解 Preferences.sublime-settings文件: // While you can edit this file, it’s best to ...
- [转]AndroidManifest.xml文件详解
转自:http://www.cnblogs.com/greatverve/archive/2012/05/08/AndroidManifest-xml.html AndroidManifest.xml ...
- delphi 资源文件详解
delphi资源文件详解 一.引子: 现在的Windows应用程序几乎都使用图标.图片.光标.声音等,我们称它们为资源(Resource).最简单的使用资源的办法是把这些资源的源文件打入软件包,以方便 ...
- VSFTPD全攻略(/etc/vsftpd/vsftpd.conf文件详解)
/etc/vsftpd/vsftpd.conf文件详解,分好类,方便大家查找与学习 #################匿名权限控制############### anonymous_enable=YE ...
- jni.h头文件详解二
作者:左少华 博客:http://blog.csdn.net/shaohuazuo/article/details/42932813 转载请注明出处:http://blog.csdn.net/shao ...
随机推荐
- ElasticSearch之Index stats API
获取指定索引的统计数据. 获取指定索引的全部统计数据,命令样例如下: curl -X GET "https://localhost:9200/testindex_001/_stats?pre ...
- Shell的概念、shebang、bash的概念
什么是shell shell的作用是 解释执行用户输入的命令或程序等 用户输入一条命令,shell就解释一条 键盘输入命令,Linux给与响应的方式,称之为交互式 linux的计算机是如何跟用户进行交 ...
- Linux 逻辑卷管理
如果用标准分区在硬盘上创建了文件系统,为已有的文件系统添加额外的空间是一件十分痛苦的事情.只能在已有的硬盘上的可用空间范围内调整分区大小,如果硬盘空间不够的话,就只能换一个大容量的硬盘,然后手动将已有 ...
- MySQL基础篇:第八章_详解TCL语言
事务 一.含义 事务:一条或多条sql语句组成一个执行单位,一组sql语句要么都执行要么都不执行 二.特点(ACID) A 原子性:一个事务是不可再分割的整体,要么都执行要么都不执行 C 一致性:一个 ...
- 什么是MircoPython?
摘要:互联网玩家为了让Python这样的容易学,简单易学.社区API丰富的语言可以在嵌入式领域用上,逐渐开始了一轮Python上嵌入式的迁移,这样就有了今天的主角--MircoPython. 本文分享 ...
- Android和iOS应用程序加固方法详解:混淆、加壳、数据加密、动态加载和数字签名实现
目录 Android和iOS应用程序加固方法详解:混淆.加壳.数据加密.动态加载和数字签名实现 APP 加固方式 iOS APP加固代码实现 打开要处理的IPA文件 设置签名使用的证书和描述文件 ...
- 火山引擎 DataTester:A/B 测试,让企业摆脱广告投放“乱烧钱”
更多技术交流.求职机会,欢迎关注字节跳动数据平台微信公众号,回复[1]进入官方交流群 在广告投放的场景下,一线广告优化师通常会创建多个计划,去测试不同的广告素材效果.这套方法看似科学,实际上却存在诸多 ...
- ChatGPT 插件,组合后更妙了
ChatGPT 插件,组合后更妙 大家好,我是章北海mlpy 昨天极简介绍了一些热门的ChatGPT插件 我测试了一些组合玩法,感觉效率.效果都远超预期. 今天就演示一下如何利用多个插件,高速阅读.理 ...
- WCF 动态调用 动态代理
关键词:WCF动态调用.动态调用WCF.WCF使用动态代理精简代码架构.使用反射执行WCF接口 代码地址: https://gitee.com/s0611163/DynamicWCF https:// ...
- 【QT Tools】软件多语言国际化翻译的方法与步骤
在Qt的项目开发过程中,有时软件要翻译成多语言版本,这就涉及到国际化方面的操作.虽然Qt对这方面集成了很多工具,操作起来比较方便,本文还是总结一下国际化的方法和步骤,用以备忘和参考. 我们通常在写程序 ...