Make 快速入门

1. Make

make 是 linux 系统的实用程序。它用于管理对于大型程序的自动编译任务,自动决定程序某一部分需要重新编译,并发出编译指令。虽然,我们最常见于 C 语言程序的编译。但是,make 不限于某一特定语言,凡是可以通过 shell 命令来运行编译器的语言都可以使用 make 。除此之外,你甚至可以用 make 描述任何构建任务,这些任务中,文件需要在其依赖的文件发生变动后自动更新。

2. Makefile

在使用 make 之前,你必须在当前目录下添加一个 Makefile 文件,它描述了文件之间的依赖(输入输出)关系,并提供更新文件的 Shell 命令。Makefile 文件名可以是 Makefile 也可以是 makefile ,推荐使用 Makefile

2.1 构成

简单的 Makefile 文件由若干如下格式的规则(rule)组成:

target: prerequisites
        recipe
  • target : 通常是程序生成(输出)的一个或多个文件名,例如:可执行文件或目标文件;它也可以是要执行任务的名称,例如用于清理生成文件的 clean 任务。
  • prerequisites: 先决条件是用于生成 target 文件的输入文件或是完成 target 任务前需要先执行的任务 。一个 target 可以没有先决条件,也可以有一个或多个先决条件。
  • recipe: 中文翻译为菜谱,它是 make 用于生成 target 文件或完成 target 任务而执行一系列 shell 命令。这些命令可以放在同一行里,也可以每个命令占一行。值得注意的是,recipe 默认以制表符开头,而不是空格。

2.2 运行 make

在当前目录下创建一个 Makefile 文件, 命名为 Makefile 。将以下内容复制到新建的 Makefile 文件中。

注意: recipe 默认是以制表符开头,不是空格。如果复制到文件是空格,需要手动将空格改成制表符,即按键盘 tab 键。

.PHONY: help clean mk

help :
	@echo "help info"

dist :
	@mkdir dist

clean :
	@rm -rf dist

.PHONY: help clean mk 用于告诉 make 指定 target 列表不是文件名。可以理解是纯粹的任务,而不生成文件。

在 Makefile 所在目录运行不带参数的 make 命令:

make

会启动 Makefile 文件中第一个 target ,本例是 help , make 将 Makefile 中第一个出现的 target 作为默认目标 。

要启动其他 target,需要在 make 命令后指定 target 名称。如下分别启动目标 dist 和 clean 。

make dist
make clean

*2.3 扩展:对比 npm scripts

对于前端的同学,最熟悉的构建方式莫过于 npm package.json 中 scripts 构建命令。在不使用项目中安装的包的情况下,即项目目录下 node_modules 里的包,完全可以使用 Makefile 来完成一些构建任务,make 的优势在于更好管理相互依赖的构建任务。

3. 变量

make 中的变量本质是一种宏替换,用于简化和维护重复出现的字符串和字符串列表。既可以出现在目标,先决条件,也可以出现在“菜谱”的 shell 命令中;可以是命令本身,也可以是命令的选项,或者输入输出文件;甚至也可以出现在另一个变量的引用中(计算变量)。

3.1 定义变量

make 变量定义和 shell 变量的定义非常相似。不同的是 make 变量的名称可以是任何不包含 :, #, = 和空字符的字符序列,并且等号两边可以有空格(shell 定义变量的等号两个不允许出现空格)。

如下定义一个变量 objs ,用于表示 c 语言编译器输出的一系列目标文件。

objs = main.o model.o view.o controller.o

3.2 使用变量

make 变量支持和 shell 变量一样,在变量标识符前加美元符 $ 来引用,因此,如果在”菜谱”中使用 shell 变量,需要使用双美元符 $$ 作为前缀加以区分;但更推荐的使用方式是使用美元符后跟一对圆括号的方式,例如使用上文创建的变量 objs ,可以这样 $(objs)

build: $(objs)
    cc -o app $(objs)

4. 函数

make 中的函数用于处理 Makefile 文件中的文本,例如:计算操作的文件列表,“菜谱”中使用的命令等。

4.1 函数调用

函数调用类似于变量引用,它可以出现在任何变量引用可以出现的地方。调用方式如下:

$(function arguments)

或者:

${function arguments}

其中,function 是函数名称,arguments 是函数的参数。函数名与参数之间用空格或制表符隔开,多个参数之间用逗号 , 隔开。

4.2 用于字符串替换和分析的函数

4.2.1 $(subst from,to,text)

text 上执行文本替换,将出现的所有 from 替换成 to

Makefile:

subst:
	@echo $(subst o,O,hello world)

make:

$ make subst
hellO wOrld

4.2.2 $(patsubst pattern,replacement,text)

text 中寻找空格分隔的单词,如果单词匹配 pattern , 就将匹配的单词替换成 replacementpatternreplacement 都可以包含通配符 %,匹配任意数量的任意字符。当 patternreplacement 同时包含通配符 %,则将 replacement% 替换成与 pattern% 匹配的文本。

Makefile:

patsubst:
	@echo $(patsubst %.c,%.o,hello.c.c world.c)

make:

$ make patsubst
hello.c.o world.o

4.2.3 $(strip string)

移除字符串 string 首尾空格,并且将字符串中的多个空格替换成一个空格。

Makefile:

strip:
	@echo $(strip    hello     world   !  )

make:

$ make strip
hello world !

4.2.4 $(sort list)

按英文字母表顺序对列表 list 中的单词进行排序,删除重复的单词。输出是由单个空格分隔的单词列表。

Makefile:

sort:
	@echo $(sort dog cat animal fox bear fox elephant)

make:

$ make sort
animal bear cat dog elephant fox

4.2.5 $(words text)

返回 text 中单词数量。

Makefile:

words:
	@echo $(words dog cat animal fox bear fox elephant)

make:

$ make words
7

4.2.6 $(word n,text)

返回 text 中第 n 个单词,n 从 1 开始计数。

Makefile:

animals = bear cat dog elephant fox
word:
	@echo $(word $(words $(animals)), $(animals))

make:

$ make word
fox

5. 隐式规则

某些重新生成目标文件的方式非常常用。例如,使用 C 编译器 cc.c 源文件编译生成 .o 目标文件。 隐式规则将告诉 make 如何使用常用的技术,让你在使用时不必给出全部细节,简化书写。例如,make 为 C 语言编译提供一个隐式规则。文件名决定将应用哪个隐式规则。比如,C 编译通常输入 .c 文件,输出 .o 文件。 因此,当看到文件名结尾符合这种组合时,make 将隐式规则应用于 C 编译。

Makefile:

app : main.o utils.o
	cc -o app main.o utils.o

main.o : main.c utils.h
	cc -c main.c

utils.o : utils.c
	cc -c utils.c

可以去掉编译命令,简写为:

app : main.o utils.o
	cc -o app main.o utils.o

main.o : main.c utils.h

utils.o : utils.c

make:

$ make
cc    -c -o main.o main.c
cc    -c -o utils.o utils.c
cc -o app main.o utils.o

参考

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Linux知识积累

使用元对象编译器

元对象编译器读取一个C++源文件。如果它发现其中的一个或多个类的声明中含有Q_OBJECT宏,它就会给这个使用Q_OBJECT宏的类生成另外一个包含元对象代码的...

10640
来自专栏技术向

在window上使用cmake

本文由腾讯云+社区自动同步,原文地址 https://stackoverflow.club/using-msys-make-in-windows/

5410
来自专栏指点的专栏

开篇:预备知识---2

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

6820
来自专栏nginx遇上redis

$(shell pwd)和$(pwd)

Makefile里面获取相对路径必须在pwd前面加shell,然后把shellpwd当一个变量来引用,书写形式是:$(shell pwd)

11410
来自专栏编程之路的专栏

程序员C语言快速上手——工程篇(十三)

当C语言工程很大,源码非常多时,如果还去使用GCC命令编译程序,几乎是不现实的。这时候,可以通过编写shell脚本去执行编译命令,当然这并不是一种好的方式。在L...

16530
来自专栏阿斯蒂芬斯的发送

nginx *** [objs/Makefile:886:objs/src/http/ngx_http_script.o] 错误 1

今天在一台新的服务器上 准备安装nginx 一开始装的扩展什么的都很顺利 但是make的时候出了问题 我确定所有需要的扩展都已经安装好了,出现问题如下:

5400
来自专栏云技术+云运维

CentOS6.5升级内核到3.10.28

本文适用于CentOS 6.4, CentOS 6.5,估计也适用于其他Linux发行版。

10220
来自专栏Linux内核及编程语言底层相关技术研究

为linux内核源码生成tags文件

一般来说,如果我们想要研究一个c/c++项目的源码,我们首先要做的是为该项目生成tags文件,linux内核是c写的,所以它也不例外。

7320
来自专栏科技分享

Linux Kernel PANIC(三)--Soft Panic/Oops调试及实例分析【转】

转自:https://blog.csdn.net/gatieme/article/details/73715860

11710

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励