在任何编译之前的qmake预构建步骤

时间:2013-04-07 16:24:10

标签: qt qmake

有关如何为qmake创建预构建步骤的SO有几个问题,我可以在我的.pro文件中执行此操作:

versionTarget.target = ../VersionData/versioning.h
versionTarget.depends = FORCE
win32: versionTarget.commands = cd $$PWD; python.exe ./version_getter.py -p $$TARGET
else:  versionTarget.commands = cd $$PWD; python ./version_getter.py -p $$TARGET

PRE_TARGETDEPS += ../VersionData/versioning.h
QMAKE_EXTRA_TARGETS += versionTarget

现在,问题是这种方法本身不是构建步骤而只是另一个构建目标,所以如果我为-j配置了make标志,它会在中运行我的脚本与其他构建作业并行。这是非常糟糕的,因为我的脚本创建/更新了一个头文件 - 在编译过程中改变它是不可接受的。

那么,无论如何我可以在运行任何编译之前执行此脚本吗?我知道我可以创建另一个脚本并按顺序调用version_getter.pyqmake,但这是不可取的,因为我必须从命令行而不是从Qt Creator中编译。


更新

每个子项目包含的完整.pri文件如下:

CONFIG += thread
QT += core \
      gui

versionTarget.target = ../VersionData/versioning.h
versionTarget.depends = FORCE
win32: versionTarget.commands = cd $$PWD; python.exe ./version_getter.py -p $$TARGET
else:  versionTarget.commands = cd $$PWD; python ./version_getter.py -p $$TARGET

PRE_TARGETDEPS += ../VersionData/versioning.h
QMAKE_EXTRA_TARGETS += versionTarget

DEPENDPATH += ../VersionData
INCLUDEPATH += ../VersionData
HEADERS += ../VersionData/versioning.h

UI_HEADERS_DIR = $${_PRO_FILE_PWD_}/include/Qui
DESTDIR = $(SYREN_PATH)

!win32-msvc {
    QMAKE_CXXFLAGS += -std=c++0x
}

但这仍然导致相同的并行行为。我认为这可能是由于我使用了ccache,但将其关闭没有任何区别(当然除了慢得多)。

3 个答案:

答案 0 :(得分:13)

另一种选择是从原始问题中的项目文件片段开始,并确保qmake知道versioning.h是项目文件中其他构建目标的依赖项 -

  • versioning.h的完整路径添加到HEADERS变量。
  • versioning.h所在的文件夹添加到DEPENDPATH变量。

(警告:如果你在versioning.h不存在时运行qmake,它会发出“警告:找不到:versioning.h” - the only workaround for that warning is to use the system() command,正如我在其他答案中所描述的那样。 )

实施例

创建包含以下内容的test.pro

versionTarget.target = ../versioning.h
versionTarget.depends = FORCE
versionTarget.commands = sleep 5s ; touch ../versioning.h
PRE_TARGETDEPS += ../versioning.h
QMAKE_EXTRA_TARGETS += versionTarget

SOURCES = test.c
HEADERS = ../versioning.h
DEPENDPATH = ..

创建包含以下内容的test.c

#include "../versioning.h"

运行qmake。它将输出WARNING: Failure to find: ../versioning.h

运行make -j9。它将运行versionTarget.commands(睡眠5秒以夸大任何多处理问题),然后,运行命令编译test.c

(如果你检查生成的Makefile,你会发现test.o取决于test.c../versioning.h,所以Make应该正确地指出它可以在创建/更新test.c命令之前运行命令编译../versioning.h。)

答案 1 :(得分:6)

使用system() qmake命令 - 它在您运行qmake make运行任何构建命令之前运行时运行。

win32: PYTHON=python.exe
else:  PYTHON=python
system(cd $$PWD; $$PYTHON ./version_getter.py -p ../VersionData/versioning.h)

答案 2 :(得分:0)

我注意到,如果您检查qmake生成的Makefile,则总是存在第一个名为“ first”的Makefile规则,该规则取决于另一个包含构建说明的规则调试(或发布)。像这样:

...
MAKEFILE      = Makefile
first: debug
...

为了创建一个预构建步骤,我们应该修改该规则以依赖于另一个优先级更高的规则。

类似

...
MAKEFILE      = Makefile
first: prebuild debug
prebuild:
    do_your_instructions
...

这实际上等于以下内容:

...
MAKEFILE      = Makefile
first: debug
...
first: prebuild 
prebuild:
    do_your_instructions
...

通过执行以下操作可以很容易地将其入侵qmake项目中:

# $$PWD/test_prebuild is a batch with the instructions to execute before every build
!build_pass:prebuild.commands = $$PWD/test_prebuild
!build_pass:first.depends = prebuild
QMAKE_EXTRA_TARGETS += prebuild first

请注意,“!build_pass:”可确保仅在Makefile中(而不是在Makefile.Debug或Makefile.Release中)编写此预构建规则,从而防止多次执行test_prebuild。 请注意,这是可能的,因为“ first”未保留(尽管名称为qmake primitive

就我而言,它运作良好:我希望这个技巧也能对其他人有所帮助。