配方更改后如何重建

时间:2018-07-30 22:07:19

标签: makefile gnu-make

如果这个问题已经被问到,我会道歉。搜索并不容易。

make的设计假定Makefile有点像上帝。它完全了解您的项目的未来,除添加新的源文件外,无需进行任何修改。显然这是不正确的。

过去,我使Makefile中的所有目标都取决于Makefile本身。这样,如果我更改Makefile中的任何内容,就会重建整个项目。

这有两个主要限制:

  1. 它经常重建。添加链接器选项或新的源文件将重建所有内容。
  2. 如果我在命令行上传递变量,如make CFLAGS=-O3,它将不会重建。

我看到了一些正确执行此操作的方法,但是乍一看,似乎都没有令人满意的方法。

  1. 使每个目标都依赖于包含食谱内容的文件。
  2. 将整个规则及其配方生成一个文件,该文件将包含在Makefile中。
  3. 有条件地向目标添加依赖项,以在必要时强制对其进行重建。
  4. 使用eval函数生成规则。

但是所有这些解决方案都需要一种不常见的编写食谱的方法。可以将整个规则作为字符串放入变量中,也可以将配方包裹在可以起到神奇作用的函数中。

我正在寻找的是一种以尽可能简单的方式编写规则的解决方案。尽可能减少额外的垃圾。人们通常如何做到这一点?

2 个答案:

答案 0 :(得分:1)

我有为多个平台编译的项目。当构建一个以前为不同体系结构编译的项目时,可以手动进行重新构建。但是,在为OpenWRT编译所有项目时,手动清理是难以管理的。

我的解决方案是创建一个标识平台的标记。如果丢失,一切都会重新编译。

ARCH ?= $(shell uname -m)
CROSS ?= $(shell uname -s).$(ARCH)

# marker for the last built architecture
BUILT_MARKER := out/$(CROSS).built

$(BUILT_MARKER) :
    @-rm -f out/*.built
    @touch $(BUILT_MARKER)

build: $(BUILT_MARKER)
# TODO: add your build commands here

如果标志太长,则可以将其减少为校验和。

答案 1 :(得分:0)

make的设计假设Makefile有点像上帝。它完全了解您的项目的未来,除添加新的源文件外,无需进行任何修改。

我不同意。 make的设计时间是将源树放在分层文件系统中,这是您需要了解的有关软件配置管理的全部知识,并且将这种想法带到了逻辑上的结果,也就是说,所有内容都是:一个文件(带有时间戳)。因此,在文件中具有链接器选项,定位器表,编译器标志以及除厨房接收器之外的所有其他文件,并将其依赖项也放入文件中,将产生一个一致,完整且无错误的构建环境,{{1 }} 被关注到。

这意味着将数据传递到进程(无非是说该进程依赖于该数据)必须通过文件完成-命令行参数,因为make变量滥用make的能力,并导致错误的结果。 make是针对系统不当行为的技术补救措施。如果软件工程师正确正确地设计了制造过程,则没有必要。

问题在于,干净的构建过程难以设计和维护。但是:在现代软件过程中,诸如make clean之类的瞬态/易变构建参数永远都不会占有一席之地,因为它们破坏了配置管理的所有良好基础。

唯一可以批评make all CFLAGS=O3的事情可能是,它并不是软件构建的全部解决方案。我质疑执行此任务的程序是否会达到make受欢迎程度的百分之一。

TL; DR

将编译器/链接器/定位器选项放入单独的文件中(在中央,突出,易于维护和理解的逻辑位置),通过信息的粒度(例如,一个文件中的编译器标志,链接器标记),并将所有文件的 true 依赖项放下,瞧,您将拥有完全必要的编译量和正确的构建。