详细内容见 《GNU make》 9 How to Run make 章节。

说明如何重新编译程序的 makefile 可以通过多种方式使用。最简单的用法是重新编译所有过期的文件。通常,编写 makefile 时,如果您运行 make
而不带任何参数,它就会这样做。

但是您可能只想更新其中的一些文件;您可能需要使用不同的编译器或不同的编译器选项;您可能只想知道哪些文件过期了,而不需要更改它们。

当你运行 make 时,通过给出参数,你可以做这些事情,也可以做很多其他事情。

make 的退出状态始终是以下三个值之一:

*
0:如果 make 成功,则退出状态为零。

*
2:如果遇到任何错误,则退出状态为 2。它将打印描述特定错误的消息。

*
1:如果您使用 ‘-q’ 标志并确定某个目标不是最新的,则退出状态是一种状态。

<>一、指定Makefile的参数

指定 makefile 名称的方法是使用 ‘-f’ 或 ‘–file’ 选项( ‘–makefile’ 也可以)。例如,’-f altmake’ 说使用
altmake 文件作为 makefile。

如果您多次使用 ‘-f’ 标志,并在每个 ‘-f’ 后面跟着一个参数,那么所有指定的文件将联合用作 makefiles。

如果不使用 ‘-f’ 或 ‘–file’
标志,默认是按该顺序尝试使用GNUmakefile、makefile和makefile,并使用这三个存在或可以创建的文件中的第一个。

<>二、指定目标的参数

这些目标是 make 最终应该努力更新的目标。如果其他目标作为目标的先决条件或目标先决条件的先决条件出现,也会更新。

默认情况下,目标是 makefile 中的第一个目标(不计算以句点开头的目标)。因此,通常编写 makefile
时,第一个目标是编译整个程序或它们所描述的程序。如果 makefile
中的第一个规则有多个目标,则只有规则中的第一个目标成为默认目标,而不是整个列表。您可以使用 .DEFAULT_GOAL 变量从 makefile
中管理默认目标的选择。

您还可以通过命令行参数为 make 指定一个或多个不同的目标。使用目标的名称作为参数。如果你指定了几个目标,make 按照你命名的顺序依次处理它们。

makefile 中的任何目标都可以被指定为目标(除非它以 ‘-’ 开头或包含
‘=’,在这种情况下,它将分别被解析为开关或变量定义)。即使没有在makefile中指定目标,如果 make 可以找到隐式规则来说明如何创建它们。

Make 会将特殊变量 MAKECMDGOALS
设置为您在命令行上指定的目标列表。如果命令行中没有给出目标,则此变量为空。注意,这个变量只能在特殊情况下使用。

适当使用的一个示例是避免在清理规则期间包含 .d 文件,因此 make 不会创建它们,只是为了立即再次删除它们:
sources = foo.c bar.c ifneq ($(MAKECMDGOALS),clean) include $(sources:.c=.d)
endif

指定目标的一种用法是,如果只想编译程序的一部分,或者只编译几个程序中的一个。指定要重制的每个文件作为目标。例如,考虑一个包含多个程序的目录,其makefile的开头如下所示:
.PHONY: all all: size nm ld ar as
如果您正在处理程序大小,您可能想说 ‘make size’,以便只有该程序的文件被重新编译。

指定目标的另一个用途是制作通常不制作的文件。例如,可能有一个调试输出文件,或者一个专门为测试而编译的程序版本,在makefile中有一个规则,但不是默认目标的先决条件。

指定目标的另一个用途是运行与伪目标或空目标关联的配方。许多makefile包含一个名为 clean
的伪目标,它会删除除源文件之外的所有内容。自然,只有当您使用 ‘make clean’ 显式请求时才会这样做。下面是一个典型的虚假和空目标名的列表。

*
all:让makefile知道所有的顶级目标。

*
clean:删除 make 运行时创建的所有文件。

*
mostlyclean:像 ‘clean’ 一样,但是可能会避免删除一些人们通常不希望重新编译的文件。例如,GCC的 ‘mostlyclean’
目标不会删除 libgcc.a,因为很少需要重新编译它,而且需要很多时间。

*
distclean、realclean、clobber:这些目标中的任何一个都可以定义为删除比 ‘clean’
更多的文件。例如,这将删除您通常为编译做准备而创建的配置文件或链接,即使makefile本身不能创建这些文件。

*
install:将可执行文件复制到用户通常搜索命令的目录中;将可执行文件使用的任何辅助文件复制到它将查找它们的目录中。

*
print:打印已更改的源文件的列表。

*
tar:创建源文件的tar文件。

*
shar:为源文件创建一个shell存档(共享文件)。

*
dist:创建源文件的分发文件。这可能是一个tar文件,或一个shar文件,或上述一个文件的压缩版本,甚至是以上一个以上的多个文件。

*
TAGS:更新此程序的标签表。

*
check、test:对 makefile 生成的程序执行自我测试。

<>三、执行配方的选项

makefile 告诉 make 如何判断目标是否为最新,以及如何更新每个目标。但是,更新目标并不总是您想要的。某些选项指定 make 的其他活动。

<具体内容见 《GNU make》 9.3 Instead of Executing Recipes 章节 >

<>四、避免重新编译某些文件

有时,您可能已经更改了一个源文件,但您不希望重新编译依赖于它的所有文件。例如,假设您向许多其他文件依赖的头文件中添加了宏或声明。保守地说,make
假设头文件中的任何更改都需要重新编译所有依赖的文件,但您知道它们不需要重新编译,您宁愿不浪费时间等待它们编译。

如果在更改头文件之前预见到问题,可以使用’-t’标志。此标志告诉 make
不要在规则中运行配方,而是通过更改其上次修改日期将目标标记为最新。您将遵循以下过程:

1、使用命令 ‘make’ 重新编译真正需要重新编译的源文件,确保在开始之前对象文件是最新的。

2、在头文件中进行更改。

3、使用命令A将所有对象文件标记为最新的。下次运行 make 时,头文件中的更改不会导致任何重新编译。

如果在某些文件确实需要重新编译时已经更改了头文件,则执行此操作为时已晚。相反,您可以使用 ‘-o file’ 标志,它将指定的文件标记为
‘old’。这意味着文件本身不会被重做,其他任何东西也不会被重做。请按照以下步骤操作:

1、使用 ‘make -o headerfile’ 重新编译需要编译的源文件,其原因与特定的头文件无关。如果涉及多个头文件,则为每个头文件使用一个单独的
‘-o’ 选项。

2、用 ‘make -t’ Touch 所有的目标文件。

<>五、覆盖变量

详细内容见 “makefile 变量”。

<>六、测试程序的编译

通常,当执行shell命令出错时,make 会立即放弃,返回非零状态。不会对任何目标执行进一步的配方。该错误意味着无法正确重做目标,并且 make
会在知道后立即报告此情况。

当你在编译一个你刚刚修改过的程序时,这不是你想要的。相反,您宁愿 make 尝试编译所有可以尝试的文件,以显示尽可能多的编译错误。

在这些情况下,您应该使用 ‘-k’ 或 ‘–keep-going’ 标志。这告诉 make
在放弃并返回非零状态之前,继续考虑待定目标的其他先决条件,必要时重新创建它们。例如,在编译一个目标文件出错后,‘make -k’
将继续编译其他目标文件,即使它已经知道链接它们是不可能的。除了在shell命令失败后继续执行之外,‘make -k’
还会在发现它不知道如何创建目标或先决条件文件后尽可能地继续执行。这将总是导致一个错误消息,但没有 ‘-k’,它是一个致命错误。

make的通常行为假设你的目的是让目标保持最新状态;一旦 make
知道这是不可能的,它不妨立即报告故障。’-k’标志表示,真正的目的是尽可能多地测试程序中所做的更改,可能是为了找到几个独立的问题,以便在下次尝试编译之前将它们全部更正。这就是为什么Emacs的M-x编译命令默认传递
‘-k’ 标志的原因。

<>七、选项摘要

详细内容见《GUN make》 9.7 Summary of Options 章节。

技术
下载桌面版
GitHub
Gitee
SourceForge
百度网盘(提取码:draw)
云服务器优惠
华为云优惠券
腾讯云优惠券
阿里云优惠券
Vultr优惠券
站点信息
问题反馈
邮箱:[email protected]
吐槽一下
QQ群:766591547
关注微信