Qt qmake在编译之前执行预构建步骤

Qt qmake在编译之前执行预构建步骤,qt,qmake,Qt,Qmake,关于如何为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; py

关于如何为
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
现在的问题是,这种方法本身不是一个构建步骤,而只是另一个构建目标,因此,如果我为
make
配置了
-j
标志,它将与其他构建作业并行运行我的脚本。这是非常糟糕的,因为我的脚本创建/更新了一个头文件-在编译过程中部分更改头文件是不可接受的

那么,在运行任何编译之前,我是否可以执行此脚本?我知道我可以创建另一个脚本,然后依次调用
version\u 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命令-它在运行
qmake
时运行,这发生在
make
运行任何构建命令之前

win32: PYTHON=python.exe
else:  PYTHON=python
system(cd $$PWD; $$PYTHON ./version_getter.py -p ../VersionData/versioning.h)
使用qmake命令-它在运行
qmake
时运行,这发生在
make
运行任何构建命令之前

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

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

  • versioning.h
    的完整路径添加到
    标题
    变量中
  • versioning.h
    所在的文件夹添加到
    DEPENDPATH
    变量中
(注意:如果在
versioning.h
不存在时运行qmake,它将发出“警告:找不到:versioning.h”-,正如我在另一个回答中所描述的那样。)

例子 创建包含以下内容的
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 = ..
#include "../versioning.h"
创建包含以下内容的
test.c

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 = ..
#include "../versioning.h"
运行
qmake
。它将输出
警告:查找失败:../versioning.h

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


(如果您检查生成的
Makefile
,您将看到
test.o
同时依赖于
test.c
。/versioning.h
,因此Make应该正确地指出,在创建/更新
。/versioning.h
的命令之前,它不能运行编译
test.c
的命令)

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

  • versioning.h
    的完整路径添加到
    标题
    变量中
  • versioning.h
    所在的文件夹添加到
    DEPENDPATH
    变量中
(注意:如果在
versioning.h
不存在时运行qmake,它将发出“警告:找不到:versioning.h”-,正如我在另一个回答中所描述的那样。)

例子 创建包含以下内容的
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 = ..
#include "../versioning.h"
创建包含以下内容的
test.c

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 = ..
#include "../versioning.h"
运行
qmake
。它将输出
警告:查找失败:../versioning.h

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


(如果您检查生成的
Makefile
,您将看到
test.o
同时依赖于
test.c
。/versioning.h
,因此Make应该正确地指出,在创建/更新
。/versioning.h
的命令之前,它不能运行编译
test.c
的命令)

我注意到,如果检查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)中编写此预编译规则,从而防止多次执行测试预编译。 请注意,这是可能的,因为“first”不是保留的(尽管是一个名称)


在我的例子中,它工作得很好:我希望这个技巧也能帮助其他人。

我注意到,如果检查由qmake生成的Makefile,总是会有第一个名为“first”的Makefile规则,它依赖于另一个包含build.Id est指令的规则调试(或发行版),类似这样:

...
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)中编写此预编译规则,从而防止多次执行测试预编译。 请注意,这是黑客是可能的,因为“第一”不是