【问题标题】:make: how to use a file as target and skip the target if that file already exists?make:如果该文件已经存在,如何将文件用作目标并跳过目标?
【发布时间】:2023-01-13 23:19:47
【问题描述】:

我的Makefile 看起来像这样(删除了一些不相关的目标,例如“调试”):

release: comprel
a2ssvr: release
libtelopa.so:
    cd telop/neta/lib && make && cp libtelopa.so ../../../
comprel: libtelopa.so
    go build -ldflags="-s -w" .
    upx --best --lzma a2ssvr
clean:
    cd telop/neta/lib && make clean
    git clean -fdX
distclean: clean
    rm -fr a2s_*.deb
deb: a2ssvr libtelopa.so
    rm -fr debian.deb
    cp libtelopa.so debian/opt/a2s/bin
    cp libjson/* debian/opt/a2s/bin
    cp a2ssvr debian/opt/a2s/bin/a2s
    dpkg-deb --build --root-owner-group debian
    rm -fr a2s*.deb
    dpkg-name debian.deb

如果我从 git 存储库签出一个新副本,它工作正常。但是,在我创建项目后,在项目根文件夹中生成了一个可执行文件a2ssvr,在这种情况下,如果我再次运行make deb,我希望release目标是不是叫。但是,每次我做make deb时都会调用它。奇怪的是,libtelopa.so 目标是不是如果文件已经存在则调用。

问题是什么,如果已经构建,我如何避免构建可执行文件?

【问题讨论】:

  • 标记非文件目标 .PHONY。 Target 仅在其早于其依赖项时才重建。
  • deb 依赖于a2ssvra2ssvr 依赖于release。如果依赖关系不正确,它们应该是什么?
  • 标题中的问题似乎是关于截然相反的问题(这也是 make 开箱即用的默认行为)所以这很令人困惑。
  • @tripleee,如果 a2ssvr 已经存在,它所依赖的应该无关紧要,对吧?如果我不添加a2ssvr: release,如果 a2ssvr 不存在,make 将失败,无论如何这是初始情况。
  • 这一切似乎都解决了古老的问题“我输入虚假依赖项是因为我很困惑,现在make也是。”

标签: makefile


【解决方案1】:

你在追求什么并不太清楚,但如果我理解正确,那么你只想构建 release 目标 iff a2ssvr 已过时? (其中 release 导致 comprel 运行,这反过来又创建了一个名为 a2ssvr 的工件......)

如果是这种情况,您所要做的就是将触发 a2ssvr 的虚假目标折叠到名为 a2ssvr... 的目标中(请注意,让目标名称与其配方生成的工件匹配是一种很好的做法)。所以现在你会有:

a2ssvr: libtelopa.so
    go build -ldflags="-s -w" .
    upx --best --lzma a2ssvr

libtelopa.so: telop/neta/lib/libtelopa.so
    cp $< $@

clean:
    cd telop/neta/lib && make clean
    git clean -fdX

distclean: clean
    rm -fr a2s_*.deb

deb: a2ssvr
    rm -fr debian.deb
    cp libtelopa.so debian/opt/a2s/bin
    cp libjson/* debian/opt/a2s/bin
    cp a2ssvr debian/opt/a2s/bin/a2s
    dpkg-deb --build --root-owner-group debian
    rm -fr a2s*.deb
    dpkg-name debian.deb

.PHONY: deb clean distclean

# for order only, you would need:
# deb: libtelopa.so | a2ssvr

现在,你的措辞暗示你不想重建a2ssrv如果它存在(与过时的情况相反)。如果是这种情况,您可以将 a2ssvr 依赖项切换为 order only。但是,这意味着如果它存在则不会重建它,但 libtelopa.so 已被修改(我猜这不是你想要的......)

【讨论】:

  • 是的,我的意图是只有在 a2ssvr 不存在的情况下才应该构建目标存在,我真的不在乎它是否过时。因为对于这个项目,很难确定目标是否过时,例如源代码引用了一个git子模块......但是,对于这个问题,我的意图是学习为什么libtelopa.so 目标按预期工作(即,如果 .so 文件已经存在,则不会触发),但即使文件已经存在,a2ssver 目标也会触发!
  • 我不明白为什么“存在”或“过时”这两个词会使您感到困惑。问题很明显,我第一次运行make,运行了a2ssvr target,生成了文件。然后我再次运行make立即地, 目标是仍然运行,不管文件是否已经存在——我不相信新生成的 a2ssvr 文件会过时!
  • 是的,但是如果您随后修改 libtelopa.so,然后再次运行 make,那么期望的行为是什么——它应该重新运行 a2ssvr 配方吗? (我猜它应该)。使用 order-only,只要文件存在,它就不会重建它。如果这是所需的行为,那么您可以将 deb 依赖项替换为评论中的依赖项。
  • 关于您的第一条评论:libtelopa.so 的规则指的是文件名。因为它没有依赖关系,当且仅当文件 libtelopa.so 不存在时才会构建它(注意:从技术上讲,它应该依赖于 telop/neta/lib/libtelopa.so,所以如果它被更新,它会重建......)。至于您的 comprel 目标,如果文件 comprel 不存在或其任何依赖项已过期,它将被重建。因为您没有生成名为 comprel 的文件,所以该目标始终被视为已过时并重新运行。
猜你喜欢
  • 2021-11-23
  • 1970-01-01
  • 1970-01-01
  • 2019-01-15
  • 2013-10-28
  • 2019-05-04
  • 1970-01-01
  • 2021-08-15
  • 2011-06-24
相关资源
最近更新 更多