Make概览

1.GNU Make 相关概念

GNU Make 是一个常用的构建工具,它的主要功能是自动化构建和管理软件项目。通过一个名为 “Makefile” 的配置文件,Make 工具能够根据预定义的规则和依赖关系,自动化执行编译、链接和其他构建任务,从而生成最终的可执行文件或其他目标文件。

Make 工具的核心思想是利用规则和依赖关系来决定是否需要重新构建某个目标文件。当目标文件的依赖文件发生变化时,Make 工具会根据预定义的规则重新构建相应的目标文件,从而保证项目的正确构建和更新。

Make 工具使用一种类似于脚本的语法,提供了一组命令和关键字,用于描述构建过程中的各个步骤。通过在 Makefile 中定义目标、依赖关系和命令,可以告诉 Make 工具如何构建目标文件。

所以当我们需要使用 Make 工具时,应当编写 Makefile,以便可以使用 Make 构建和安装该程序。

1.1Make 的功能

  • Make 使最终用户能够构建和安装您的软件包,而无需了解如何完成的详细信息 - 因为这些详细信息记录在您提供的 makefile 中。

  • Make 会根据已更改的源文件自动确定需要更新的文件。如果某个非源文件依赖于另一个非源文件,它还会自动确定更新文件的正确顺序。

    因此,如果您更改了一些源文件,然后运行 Make,它不需要重新编译所有程序。它只会更新那些直接或间接依赖于您更改的源文件的非源文件。

  • Make 不局限于任何特定语言。对于程序中的每个非源文件,makefile 指定用于计算它的 shell 命令。这些 shell 命令可以运行编译器来生成目标文件,运行链接器来生成可执行文件, ar更新库,或者运行 TeX 或 Makeinfo 来格式化文档。

  • Make 不仅限于构建软件包。您还可以使用 Make 来控制软件包的安装或卸载、为其生成标签表,或者其他您想经常做的事情,这样就值得写下来如何去做。

1.2Make 安装

检查是否已经安装了 make, 顺便查看 make 版本

make --version

若没有出现 make 版本,即 make 没有安装,执行 make 安装

yum -y install make

1.3Makefile 简介

Makefile 文件告诉 make 该如何编译和链接程序。

一个简单的 Makefile 的写法

target … : prerequisites …
        recipe
        …
        …

target:表示要程序生成的文件名称

prerequisites:表示生成文件所需的各种源文件,生成目标文件通常需要依赖多个文件,但也可以没有依赖文件

recipe:需要执行的命令,同样可以有多条命令或者没有命令。如果有多条命令,则建议每条命令写一行

**注意:**需要在每个 recipe 行的开头放置一个制表符!如果希望在 recipe 前面加上制表符以外的字符,则可以将变量设置为替代字符

1.4Make 相关命令

Usage: make [options] [target] ...
Options:
  -b, -m                      Ignored for compatibility.
  -B, --always-make           Unconditionally make all targets.
  -C DIRECTORY, --directory=DIRECTORY
                              Change to DIRECTORY before doing anything.
  -d                          Print lots of debugging information.
  --debug[=FLAGS]             Print various types of debugging information.
  -e, --environment-overrides
                              Environment variables override makefiles.
  --eval=STRING               Evaluate STRING as a makefile statement.
  -f FILE, --file=FILE, --makefile=FILE
                              Read FILE as a makefile.
  -h, --help                  Print this message and exit.
  -i, --ignore-errors         Ignore errors from recipes.
  -I DIRECTORY, --include-dir=DIRECTORY
                              Search DIRECTORY for included makefiles.
  -j [N], --jobs[=N]          Allow N jobs at once; infinite jobs with no arg.
  -k, --keep-going            Keep going when some targets can't be made.
  -l [N], --load-average[=N], --max-load[=N]
                              Don't start multiple jobs unless load is below N.
  -L, --check-symlink-times   Use the latest mtime between symlinks and target.
  -n, --just-print, --dry-run, --recon
                              Don't actually run any recipe; just print them.
  -o FILE, --old-file=FILE, --assume-old=FILE
                              Consider FILE to be very old and don't remake it.
  -p, --print-data-base       Print make's internal database.
  -q, --question              Run no recipe; exit status says if up to date.
  -r, --no-builtin-rules      Disable the built-in implicit rules.
  -R, --no-builtin-variables  Disable the built-in variable settings.
  -s, --silent, --quiet       Don't echo recipes.
  -S, --no-keep-going, --stop
                              Turns off -k.
  -t, --touch                 Touch targets instead of remaking them.
  -v, --version               Print the version number of make and exit.
  -w, --print-directory       Print the current directory.
  --no-print-directory        Turn off -w, even if it was turned on implicitly.
  -W FILE, --what-if=FILE, --new-file=FILE, --assume-new=FILE
                              Consider FILE to be infinitely new.
  --warn-undefined-variables  Warn when an undefined variable is referenced.
  --warn-undefined-functions  Warn when an undefined user function is called.

2. Makefile 编写

2.1Makefile 执行顺序

  • 一个目标,正常执行一个目标内的命令
  • 多个目标没有互相依赖,默认执行第一个目标的命令,可用 make 指令改变执行的目标
  • 多个目标相互依赖,符合上条规则,再按照依赖的书写顺序依次执行该目标所需的依赖的命令,最后执行自己本身的命令

1721809866062

可在命令前@,隐藏命令的输出

1721810079838

2.2Makefile 语法

2.2.1使用自定义变量

variablename = value # 定义变量
${variablename}$(variablename) # 使用变量

2.2.2默认系统常量

AS: 汇编程序的名称,默认为 as; CC: C编译期名称,默认为 cc; CPP: C预编译期名称,默认为 cc -E; CXX: C++编译器名称,默认为 g++; RM: 文件删除程序别名,默认为 rm -f;SHELL:Shell 程序的路径,默认为 /bin/sh。

2.2.3系统变量

$*:不包括扩展名的目标文件名称; $+:所以的依赖文件,以空格分隔; $<:表示规则中的第一个条件; $?:所有时间戳比目标文件晚的依赖文件,以空格分隔; $@:目标文件的完整名称; $^:所有不重复的依赖文件,以空格分隔; $%:如果目标是归档成员,则该变量表示目标的归档成员名称;

2.2.4使用伪目标

# 伪目标用于表示不对应实际文件的目标,而是表示执行某些操作的目标。
# 伪目标语法:.PHONY: 关键字
如: 
.PHONY: clean
clean:
    rm -rf build

2.2.5模式匹配

# ① %:匹配任意长度的字符串;
# ② *:匹配零或多个字符;
# ③ ?:匹配任意单个字符。
如:
# %.o 表示任意匹配以 .o 结尾的目标文件。%.c 表示与目标文件同名的源文件。
%.o: %.c
    gcc -c $< -o $@

2.2.6使用 Makefile 内置函数

wildcard:获取满足给定模式的文件列表。例如:$(wildcard *.c);
patsubst:在给定的文本中替换匹配的模式。例如:$(patsubst %.c,%.o,$(wildcard *.c));
subst:在给定的文本中替换指定的字符串。例如:$(subst old,new,text);
strip:去除字符串两侧的空格字符。例如:$(strip hello );
foreach:遍历一个列表,并将指定的变量绑定到每个元素上。例如:$(foreach var, list, text);
shell:执行 shell 命令并返回结果。例如:$(shell echo "Hello");
file:获取文件的属性,例如文件大小、创建时间等。例如:$(file <attribute>,<filename>);
dir:获取路径中的目录部分。例如:$(dir src/main.c);
notdir:获取路径中的文件名部分。例如:$(notdir src/main.c);
basename:获取文件名的前缀部分(不包括后缀名)。例如:$(basename src/main.c);
suffix:获取文件名的后缀部分。例如:$(suffix src/main.c);
abspath:获取给定相对路径的绝对路径。例如:$(abspath src/main.c)

2.2.7使用条件语句

# ifeq:判断是否相等,相等返回 true,不等返回 false
# ifneq:判断是否不相等,不等返回 true,相等返回 true
# ifdef:判断变量是否存在,存在返回 true,不存在返回 false
# ifndef:判断变量是否不存在,不存在返回 true,存在返回 false
ifeq ($(DEBUG), 1)
    CFLAGS += -g
else
    CFLAGS += -O2
endif
# 上述代码表示如果传入变量 DEBUG 的值为 1,则添加 -g 调试选项;否则添加优化选项 -O2。

2.2.8包含其他文件

# 使用 include 命令将其他 Makefile 文件包含到当前 Makefile 中。
include common.mk
# 上述代码将名为 common.mk 的 Makefile 文件包含进本 Makefile 文件

2.2.9=和:=的区别

# = (等号赋值):当使用等号赋值时,变量的值是在变量使用时动态计算的。这意味着,如果在后续的规则中修改了等号赋值的变量,那么该变量的新值将在后续规则中重新计算。
# := (冒号等号赋值):当使用冒号等号赋值时,变量的值是在变量定义时即时计算的,并且这个值在整个 Makefile 执行过程中保持不变。这意味着变量的值不会受到后续规则中的修改影响。

2.2.10自定义函数

# 定义自定义函数
define Function
    @echo "This is my custom function."
    @echo "Hello, $(1)!"
endef
# 使用自定义函数
target:
    $(call function,World)

更多 Makefile 语法见 Makefile 手册

参考文献

https://www.gnu.org/software/make/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值