【问题标题】:Adding custom commands to existing targets in qmake在 qmake 中向现有目标添加自定义命令
【发布时间】:2015-07-03 10:22:31
【问题描述】:

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

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

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

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

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

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

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


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

【问题讨论】:

标签: qt makefile target qmake


【解决方案1】:

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


选项 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

所以,把它们放在一起,放在 .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 不满意,则另一种方法是使用@$(MAKE) -f RealMakefile $@ 作为配方来指定all 规则。
    • % 目标与此Makefile 中未另行定义的任何目标匹配。它只是将处理委托给 RealMakefile
    • distclean 目标是我们添加命令的地方。我们仍然需要委托给 RealMakefile,但在此之前和之后都可以添加其他命令。

优点:

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

缺点:

  • .pro 中不是独立的。
  • 不那么便携:它不会将所有 Makefile 代留到qmake,而且我实际上不确定哪些部分是特定于 GNU make 的(欢迎 cmets) .

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

【讨论】:

  • 您的解决方案特定于问题和“distclean”和“extraclean”......但是我发现它以更通用的方式有用。仅供参考,我使用了选项 1。谢谢! qmake 很难做到这一点。
  • 我将这里的distclean 替换为普通的旧clean,以便通过QtCreator 中的菜单选项触发我的自定义清理命令。
【解决方案2】:

另一种解决方案是将要删除的文件添加到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 命令或某种通配符。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    相关资源
    最近更新 更多