【问题标题】:Make: Avoiding issues from having same targets in multiple MakefilesMake:避免在多个 Makefile 中具有相同目标的问题
【发布时间】:2019-08-28 17:36:38
【问题描述】:

我需要知道处理这个问题的最佳方法。您也可以回答这个问题——在阅读下面的示例之后——:查看package.make 中的makelib 目标,并告诉我是否有办法强制将其视为未更新,如果配方(make -C . ./lib/ -f lib.make) 报告为无事可做(不使用有序的先决条件)?

我需要用一个例子来解释这一点。我继承了这一点,我需要最好的方法来解决这个问题。

其他目标将依赖的目标:

File lib.make
--------------
.DEFAULT_GOAL = thelib.dll

%.dll: file1.obj file2.obj
      makelib file1.obj file2.obj -o thelib.dll

这本身就很可靠。您运行一次 (make -f lib.make) 并创建库。如果您随后运行它,并且没有修改过的文件,那么它会告诉您它无事可做。

现在我们将在其他地方以一种特殊的方式使用它:

File: package.make
------------------
.DEFAULT_GOAL: all

all: package

makelib: 
        @make -C ../lib/ -f lib.make

package: makelib file3 file4
        @package_files file3 file4 ../lib/out/*.dll -o package

这就是lib.makepackage.make 中的引用方式。

问题在于,即使在您调用 make -f package.make all make 时创建了包,也假定每次都需要重建 package 目标,因为它的依赖项之一 -- makelib -- 必须重新制作

Make 认为 makelib 已过期,尽管输入 lib.make 后会发生什么。

为了纠正这个问题,我想到了几个选择:

  • makelib 移动到有序的先决条件(在 | 之后)但这不太正确,因为在新建库的情况下,我的包不会被更新

  • 再次添加 dll (thelib.dll) 作为对 makelib 目标的依赖项,但这几乎会重复逻辑并破坏封装。

  • 删除makelib 目标并将@make -C ../lib/ -f lib.make 行移动到package 配方内部。这有一个问题,那就是我已经删除了包和lib之间的依赖关系。如果 lib 需要更新,包将不知道它并且不会更新。

  • 使用include lib.make,然后将package 规则重写为:package: thelib.dll file3 file4。这也有问题,其中最少的是要包含一个make文件,它必须这样写。否则会引入大量覆盖/冲突的目标和定义。

除了直接将dll列为依赖之外,还有什么建议吗?

【问题讨论】:

    标签: makefile gnu-make


    【解决方案1】:

    这有两种主要的工作方式:

    首先,如果您使用递归make(请记住始终使用$(MAKE)调用子make,而不是直接使用make),那么您应该使父makefile中的目标成为子生成的实际文件制作:

    package: lib/thelib.dll ...
             ...
    
    lib/thelib.dll: FORCE
            $(MAKE) -f lib
    FORCE:
    

    其次,您可以使用非递归 make,这意味着您将子 makefile 包含到父 make 中并编写它以使其期望。您可以使用变量等技巧来使其更通用,因此可以根据需要从父目录或子目录调用它。

    【讨论】:

    • 没有FORCE 喜欢将lib/thelib.dll 标记为PHONY 吗?这意味着无论它是否是最新的,它都会一直更新?哪个会导致package 也总是执行?
    • 它“喜欢”它,但不一样。如果你使用了.PHONY,那么有两件事是正确的:(a)配方将始终运行(我们想要这个)和(b)目标lib/thelib.dll 将始终被认为是过时的——我们不想要这是因为这意味着即使lib/thelib.dll 实际上没有改变,package 也将始终被重建。通过使用FORCE 技巧,我们仍然得到(a),因为FORCE 不存在,但是lib/thelib.dll 上的修改时间用于确定它是否已更新,而不是假设它总是更新。
    • 真的很有创意。它绝对有效。我只是需要时间来完全消化它
    • 它基于 make 的一个长期存在但不一定众所周知的特性:如果 make 决定构建一个目标并运行一个配方,它不会简单地假设目标已更新。 Make 将在配方完成后检查修改时间,以查看目标是否真的改变了。如果不是,那么在确定依赖它的目标是否需要更新时,make 不会认为它已更新。此功能经常用于更高级的 makefile 操作。
    • 我认为在使用 -d 运行了几次之后我会更好地理解它。这几乎是天才。由于 dll 的访问时间戳没有改变,所以我们正在更新包。非常感谢您!
    猜你喜欢
    • 2016-10-13
    • 1970-01-01
    • 1970-01-01
    • 2014-03-23
    • 2019-03-29
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    • 2017-07-26
    相关资源
    最近更新 更多