在qmake

时间:2015-04-24 17:27:35

标签: qt makefile target qmake

有没有办法在 .pro 文件中指定要添加到{{1>}生成的 Makefile 中的标准目标的额外命令?例如,考虑qmake,可能需要额外的命令:

  • 删除 *〜文件。
  • 从源树中清除运行时生成的输出文件。

我想使用普通目标而不是自定义目标,因为我希望它在我的工作流程中完全透明。那是(再次以distclean为例),我不想......

  • ...需要在多项目设置中了解某些 Makefile 使用自定义规则而不是distclean
  • ...记录自定义规则,即使对于独立项目,因为distclean已经well-known且直观

我找到了How to add custom targets in a qmake generated Makefile?,但这描述了添加自定义目标(already documented,甚至是back in 4.6),而不是向现有目标添加规则。虽然它确实包含一些提示,但它们都需要添加新的自定义目标,因为在 Makefile 中多次指定同一目标会替换(不添加)来自前一目标的命令。

我唯一能想到的尝试是将distclean添加到 .pro 文件中作为一个疯狂的猜测(例如target.commands += new commands)。这没有效果。

如何使用distclean.commands += rm \"*~\"透明地向现有目标添加自定义命令?

对于qmake示例:虽然distclean也在"标准目标"列表,在实践中我发现它很少使用,并且在任何情况下maintainer-clean默认情况下都不会生成它;我认为它不合适。

2 个答案:

答案 0 :(得分:22)

有两种直接的方法可以实现这一点,具体取决于您希望解决方案的自包含/可移植性以及您希望对命令执行顺序的宽松程度。

选项1

第一个选项是在 .pro 文件中为新命令创建自定义目标,然后将该目标添加为要修改的标准目标的先决条件。回到distclean示例,假设您要添加一个命令来删除所有 *〜文件:

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

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

    distclean.depends = extraclean
    

    这实际上不会修改distclean规则,因为此方法不能用于修改现有规则。然而...

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

    QMAKE_EXTRA_TARGETS += distclean extraclean
    

    这会向distclean添加Makefile的第二个规范,但这可行,因为you can add dependencies to existing targets in make in separate rules, even though you can't add commands that way。如果您还要在 .pro 文件中指定distclean.commands,则可以通过替换其默认配方来中断现有distclean

  4. 所以,把它们放在一起,放在 .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 推迟 >生成的,而不是包括+覆盖它。这也是一个简单的选择;虽然不像选项1那样自包含,但它使您能够在默认生成的配方之前和之后执行命令。

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

    要做到这一点:

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

      MAKEFILE = RealMakefile
      

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

    2. 下一步是使用自定义命令创建自己的Makefile。但是,这里有一些警告。首先,再次使用distclean的完整示例。在名为Makefile的文件中:

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

      关于此的一些注意事项:

      • 我们设置.DEFAULT_GOAL,否则distclean将成为默认值。如果您对.DEFAULT_GOAL不满意,可以选择使用all作为配方来指定@$(MAKE) -f RealMakefile $@规则。
      • %目标匹配此 Makefile 中未另行定义的任何目标。它只是将处理委托给 RealMakefile
      • distclean目标是我们添加命令的地方。我们仍然需要委托 RealMakefile ,但可以在发生之前和之后添加其他命令。
    3. 优点:

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

      缺点:

      • .pro 中没有自包含。
      • 不是可移植的:它不会将所有 Makefile 生成保留到qmake,而且我实际上也不确定哪些部分特定于GNU make (欢迎评论)。

      所以,虽然这个答案可能有点长,但这两种方法都非常简单。除非命令执行顺序是个问题,否则我更喜欢选项1。

答案 1 :(得分: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 命令或某种通配符。