向qmake现有目标中添加自定义命令

18
有没有办法在.pro文件中指定额外的命令添加到qmake生成的Makefile的标准目标中?例如,考虑distclean,可能需要添加额外的命令来:
  • 删除*~文件。
  • 从源树中清除运行时生成的输出文件。
  • 等等。
我想使用普通目标而不是自定义目标,因为我希望这在我的工作流程中完全透明。也就是说(再次以distclean为例),我不想要...
  • ...在多项目设置中需要了解某些Makefiles使用自定义规则而不是distclean
  • ...为独立项目记录自定义规则,因为distclean已经是众所周知的和直观的
我发现了如何在qmake生成的Makefile中添加自定义目标?,但这描述了添加自定义目标(已经有文档,甚至在4.6中就有了文档),而不是添加规则到现有目标。虽然它包含一些提示,但所有这些提示都需要添加新的自定义目标,因为在Makefile中多次指定相同的目标会替换(而不是添加)前一个目标的命令。

我能想到的唯一尝试就是在.pro文件中添加target.commands += new commands,作为一种猜测 (例如distclean.commands += rm \"*~\")。但这并没有效果。

如何使用qmake在现有目标中透明地添加自定义命令?


对于distclean示例:虽然maintainer-clean也在“标准目标”列表中,但实际上我发现它很少被使用,并且无论如何,qmake不会默认生成它;我认为它不太合适。


https://dev59.com/MW025IYBdhLWcg3wi2mw#5948236 - nyanpasu64
2个回答

27

有两种简单的方法可以实现这一点,取决于您希望您的解决方案是多么自包含/便携,并且您想要在命令执行顺序上有多宽松。


选项1

第一种方法是在.pro文件中为新命令创建自定义目标,然后将该目标作为您正在修改的标准目标的先决条件。以distclean示例为例,假设您想要添加一个命令来删除所有的*~文件:

  1. 在您的.pro文件中创建一个自定义目标。请注意,您必须在.pro文件中转义引号和斜杠。例如,添加:

    extraclean.commands = find . -name \"*~\" -exec rm -v {} \\;
    
  2. 将此目标添加为您正在修改的目标的依赖项:

  3. distclean.depends = extraclean
    

    这并不会修改distclean规则,因为该方法无法用于修改现有规则。然而...

  4. 将您要修改的目标和新目标都添加为额外目标:

  5. QMAKE_EXTRA_TARGETS += distclean extraclean
    

    这将会在Makefile中添加第二个distclean的规则,但这是可行的,因为你可以在独立规则中向现有目标添加依赖项,即使你不能通过这种方式添加命令。如果您还在.pro文件中指定了distclean.commands,那么将会通过替换默认配方来破坏现有的distclean

    因此,在.pro文件中:

    extraclean.commands = find . -name \"*~\" -exec rm -v {} \\;
    distclean.depends = extraclean
    QMAKE_EXTRA_TARGETS += distclean extraclean
    

    其中extraclean是您要添加的命令的自定义目标,而distclean则是您希望修改的现有目标。

    优点:

    • 完全包含在一个.pro文件中。
    • 尽可能便携,将实际的Makefile语法和生成留给qmake

    缺点:

    • 您的新命令不会被追加到现有配方中。相反,它们会在满足所有前置目标之后但在现有配方之前发生。在distclean示例中,使用我正在使用的qmake版本时,这将使命令在源树清理之后但在Makefile本身被删除之前执行(这是默认配方执行的唯一操作)。对于此示例,这不是问题,但对您可能会有影响。

    选项2

    第二个选项是更改qmake生成的Makefile的名称,并创建自己的自定义Makefile,使其延迟到生成的Makefile,而不是包含+覆盖它。这也是一个简单明了的选项;虽然不像选项1那样自包含,但它使您能够在默认生成的配方之前和之后执行命令。

    您不希望包含+覆盖现有的Makefile,因为您不想替换默认配方。如果这样做,您必须重新实现默认值,但这可能成为一个问题,因为默认值可能会改变(您必须跟上更改)。最好让qmake尽可能多地工作,而不要重复它的工作。

    要这样做:

    1. 首先,更改qmake生成的文件名称。这可以通过向.pro文件添加以下行来实现:

      MAKEFILE = RealMakefile
      

      这将导致qmake输出RealMakefile而不是Makefile

    2. 下一步是创建您自己的Makefile以及您自定义的命令。但是这里有一些注意事项。首先,再次使用distclean提供一个完整的示例。在名为Makefile的文件中:

    3. .DEFAULT_GOAL := all
      
      %:
          @$(MAKE) -f RealMakefile $@
      
      distclean:
          @$(MAKE) -f RealMakefile $@ 
          @find . -name "*~" -exec rm -v {} \;
      

      关于此事的一些注释:

      • 我们设置 .DEFAULT_GOAL ,因为否则 distclean 将是默认值。如果您不熟悉 .DEFAULT_GOAL ,可以使用 @$(MAKE) -f RealMakefile $@ 作为配方来指定 all 规则作为替代方法。
      • % 目标匹配在此 Makefile 中未定义的任何目标。它只是将处理委托给 RealMakefile
      • distclean 目标是我们添加命令的地方。我们仍然需要委派给 RealMakefile,但是在执行此步骤之前和之后都可以添加其他命令。

    优点:

    • 更多的命令控制。可以在默认配方之前和之后添加命令。

    缺点:

    • 不是一个自包含的.pro文件。
    • 不太便携:它并没有把全部的Makefile生成交给了qmake,而且我也不确定这里有哪些部分是特定于GNU make的(欢迎评论)。

    虽然这个回答可能有点长,但这两种方法都非常简单。除非命令执行顺序是一个问题,否则我会选择选项1。


2
你的解决方案是针对该问题以及“distclean”和“extraclean”的,但我发现它在更通用的方式下也很有用。顺便提一下,我使用了选项1。感谢!qmake非常难以做到这一点。 - Trevor Boyd Smith
2
我在这里用普通的 clean 替换了 distclean,以便通过QtCreator中的菜单选项触发我的自定义清理命令。 - BuvinJ

0
另一个解决方案是将要删除的文件添加到 QMAKE_CLEANQMAKE_DISTCLEAN qmake 变量中。
build_tests {
    TINYORM_SQLITE_DATABASE = $$quote($$TINYORM_BUILD_TREE/tests/q_tinyorm_test_1.sqlite3)

    QMAKE_CLEAN = $$TINYORM_SQLITE_DATABASE
    QMAKE_DISTCLEAN = $$TINYORM_SQLITE_DATABASE
}

只有在你知道要删除的文件时,这才相关。因此,在这种情况下,您不能使用rm命令或某种类型的通配符。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接