Подтвердить что ты не робот

Qmake pre-build step перед ЛЮБОЙ компиляцией

Есть несколько вопросов о том, как создать шаг предварительной сборки для 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, он запускает мой script параллельно с другой сборкой рабочие места. Это очень плохо, потому что мой script создает/обновляет заголовочный файл - если он меняет часть пути, компиляция неприемлема.

Итак, все-таки я могу запустить этот script до того, как будет запущена какая-либо компиляция? Я знаю, что могу создать еще один script и последовательно вызывать version_getter.py и qmake, но это нежелательно, поскольку мне пришлось бы компилироваться из командной строки, а не из Qt Creator.


Update

Полный .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, но отключение его не имело никакого значения (кроме, конечно, гораздо медленнее).

4b9b3361

Ответ 1

Другой вариант - начать с фрагмента файла проекта в исходном вопросе, а также убедиться, что qmake знает, что versioning.h является зависимостью для других целей сборки в файле проекта -

  • Добавьте полный путь к versioning.h в вашу переменную HEADERS.
  • Добавьте папку, в которой versioning.h находится в вашей переменной DEPENDPATH.

(Предостережение: если вы запустите qmake, когда versioning.h не существует, он выдаст "WARNING: Failure find: 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.)

Ответ 2

Используйте команду system() qmake - она запускается при запуске qmake, что происходит до make как make запускает любые команды сборки.

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

Ответ 3

Я заметил, что если вы проверяете Makefile, созданный qmake, всегда есть первое правило Makefile с именем "first", которое зависит от другого правила отладки (или выпуска), содержащего инструкции для сборки. То есть что-то вроде этого:

...
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.

В моем случае это работало нормально: я надеюсь, что этот трюк может помочь и другим.