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

Jas*_*n C 15 qt qmake makefile target

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

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

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

  • ...需要知道多项目设置,某些Makefile使用自定义规则而不是distclean.
  • ...文件自定义规则,即使是单机项目,distclean已经是众所周知的,直观.

我发现如何在qmake生成的Makefile中添加自定义目标?,但这描述了添加自定义目标(已经记录,甚至在4.6中),而不是向现有目标添加规则.虽然它确实包含一些提示,但它们都需要添加新的自定义目标,因为在Makefile中多次指定同一目标会替换(不添加)前一个目标的命令.

我真的想尝试的唯一的事情是添加target.commands += new commands的.pro文件作为胡乱猜测(如distclean.commands += rm \"*~\").这没有效果.

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


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

Jas*_*n C 23

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


选项1

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

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

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

    distclean.depends = extraclean
    
    Run Code Online (Sandbox Code Playgroud)

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

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

    QMAKE_EXTRA_TARGETS += distclean extraclean
    
    Run Code Online (Sandbox Code Playgroud)

    这将添加第二个规范,但这是distclean有效的Makefile,因为您可以make在单独的规则中向现有目标添加依赖项,即使您不能以这种方式添加命令.如果您还要distclean.commands.pro文件中指定,则可以distclean通过替换其默认配方来中断现有文件.

所以,将它们放在一起,放在.pro文件中:

extraclean.commands = find . -name \"*~\" -exec rm -v {} \\;
distclean.depends = extraclean
QMAKE_EXTRA_TARGETS += distclean extraclean
Run Code Online (Sandbox Code Playgroud)

extraclean某些自定义目标位于您要添加的命令的哪个位置,并且distclean是您要修改的现有目标.

优点:

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

缺点:

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

选项2

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

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

去做这个:

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

    MAKEFILE = RealMakefile
    
    Run Code Online (Sandbox Code Playgroud)

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

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

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

    一些关于此的说明:

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

优点:

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

缺点:

  • .pro中不是自包含的.
  • 不是那么便携:它不会让所有的Makefile生成qmake,而且我实际上也不确定哪些部分特定于GNU make(欢迎评论).

因此,尽管这个答案可能有点长,但这两种方法都非常简单.除非命令执行顺序是个问题,否则我更喜欢选项1.

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