关于如何为
qmake
创建预构建步骤有几个问题,我可以在我的.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
标志,它会与其他构建作业并行 运行我的脚本。 这非常糟糕,因为我的脚本创建/更新了一个头文件 - 在编译过程中对其进行部分更改是不可接受的。
那么,我是否可以在运行 any 编译之前执行此脚本? 我知道我可以创建另一个脚本并依次调用
version_getter.py
和 qmake
,但这并不可取,因为我必须从命令行而不是从 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
,但将其关闭并没有什么区别(当然除了速度慢得多)。
另一种选择是从原始问题中的项目文件片段开始,并确保 qmake 知道
versioning.h
是项目文件中其他构建目标的依赖项 -
versioning.h
的完整路径添加到 HEADERS
变量中。versioning.h
所在的文件夹添加到您的 DEPENDPATH
变量中。(警告:如果在
versioning.h
不存在时运行 qmake,它将发出“警告:找不到:versioning.h” - 该警告的唯一解决方法是使用 system()
命令,如我在另一个答案中描述过。)
创建
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
。)
system()
qmake 命令 — 它会在您运行 qmake
时运行,这会在 make
运行任何构建命令之前发生。
win32: PYTHON=python.exe
else: PYTHON=python
system(cd $$PWD; $$PYTHON ./version_getter.py -p ../VersionData/versioning.h)
我注意到,如果您检查 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 原语。
就我而言,效果很好:我希望这个技巧也能帮助其他人。
对此有更好的解决方案! 您可以利用
QMAKE_EXTRA_COMPILERS
强制同步预构建操作,这在使用 parallel 编译(make -j 标志)时有效!我不能相信这个解决方案,我在这个帖子中找到了它:https://stackoverflow.com/a/50619989/3220983