28

SO上有几个关于如何创建预构建步骤的问题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

那么,无论如何我可以在运行任何编译之前执行这个脚本吗?我知道我可以创建另一个脚本并从中按顺序调用version_getter.pyand 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,但将其关闭并没有什么不同(当然除了要慢得多)。

4

3 回答 3

14

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

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

(警告:如果您在versioning.h不存在时运行 qmake,它将发出“警告:无法找到:versioning.h” -该警告的唯一解决方法是使用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。)

于 2013-04-08T14:02:06.020 回答
7

使用system()qmake 命令——它在你运行时运行qmake,它发生在make运行任何构建命令之前。

win32: PYTHON=python.exe
else:  PYTHON=python
system(cd $$PWD; $$PYTHON ./version_getter.py -p ../VersionData/versioning.h)
于 2013-04-08T00:03:40.823 回答
0

我注意到,如果您检查 qmake 生成的 Makefile,总会有第一个名为“first”的 Makefile 规则,它依赖于包含构建指令的另一个规则调试(或发布)。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)中编写此预构建规则,以防止多次执行 test_prebuild。请注意,这是 hack 是可能的,因为“first”不是保留的(尽管它是一个qmake 原语

就我而言,它运行良好:我希望这个技巧也可以帮助其他人。

于 2019-09-09T12:25:26.693 回答