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

Скопируйте файл для сборки каталога после компиляции проекта с помощью Qt

Я видел несколько предложений, но ничего действительно не работало для меня, как я хочу. Мне просто нужно скопировать файл в нужный каталог.

Скажите, например, из этого ответа:

install_it.path = %{buildDir}
install_it.files += %{sourceDir}/settings.ini

INSTALLS += install_it

Переменные %{buildDir} и %{sourceDir} должны быть определены, чтобы сделать эту работу. Хорошо, нет проблем с %{sourceDir}: это просто .. Но как я могу получить %{buildDir}?

EDIT1

Скажем, у меня есть проект my_project здесь:

/path/to/my_project

Итак, путь сборки релиза таков: /path/to/my_project-build-Desktop-release,

путь сборки отладки таков: /path/to/my_project-build-Desktop-debug

У меня есть файлы, которые нужно скопировать в каталог назначения здесь: /path/to/my_project/copy_to_install_dir

Итак, я хочу, чтобы все файлы из /path/to/my_project/copy_to_install_dir были скопированы в /path/to/my_project-build-Desktop-release, когда я выпускаю сборку. И, таким же образом для сборки отладки.

Я не могу найти переменную, которая содержит полный путь назначения, т.е. /path/to/my_project-build-Desktop-release для сборки отладки.

На всякий случай: я использую Windows, но в любом случае я ищу кроссплатформенное решение.

EDIT2

Точное решение для будущих читателей:

install_it.path = $$OUT_PWD
install_it.files = copy_to_install_dir/*

INSTALLS += \
    install_it
4b9b3361

Ответ 1

Это то, что мы используем в QtSerialPort:

target_headers.files  = $$PUBLIC_HEADERS
target_headers.path   = $$[QT_INSTALL_HEADERS]/QtSerialPort
INSTALLS              += target_headers

mkspecs_features.files    = $$QTSERIALPORT_PROJECT_ROOT/src/serialport/qt4support/serialport.prf
mkspecs_features.path     = $$[QT_INSTALL_DATA]/mkspecs/features
INSTALLS                  += mkspecs_features

В принципе, вы устанавливаете файлы и путь для цели, а затем добавляете их в переменную INSTALLS. Вам все еще нужна переменная $$OUT_PWD, которую мы также широко используем в QtSerialPort. Это предоставит вам корень каталога сборки.

Это одна из тех недокументированных функций qmake, но она очень полезна.

Кроме того, для исходного каталога вообще в целом вы не должны предполагать ".". и т.д., потому что это может быть иначе, когда вы запускаете приложение-оболочку, в котором "." будет указывать на это, а не на то, что вы ожидаете: корень проекта источника qmake. В таких случаях безопаснее использовать переменную PWD, которая указывает на источник в отличие от OUT_PWD, который указывает на папку сборки.

Чтобы дать приблизительный пример о различии этих двух переменных с реалистичным сценарием, здесь вы можете найти то, что мы делаем в QtSerialPort:

system("echo QTSERIALPORT_PROJECT_ROOT = $$PWD >> $$OUT_PWD/.qmake.cache")
system("echo QTSERIALPORT_BUILD_ROOT = $$OUT_PWD >> $$OUT_PWD/.qmake.cache")

где первый является корнем для исходного проекта, а второй для каталога сборки. Они могут быть одинаковыми, но во многих случаях они не являются, например. при создании через QtCreator только для одного из них.

Ответ 2

Выбранный ответ правильный, но для него требуется вызвать make install, который, на мой взгляд, раздражает или подвержен ошибкам. Вместо этого для копирования файлов в каталог сборки используйте:

copydata.commands = $(COPY_DIR) $$PWD/required_files $$OUT_PWD
first.depends = $(first) copydata
export(first.depends)
export(copydata.commands)
QMAKE_EXTRA_TARGETS += first copydata

Где required_files должен быть заменен вашим правильным путем. $$PWD - это путь к текущему файлу .pro, вы можете не требовать этого.

Примечание. Я нашел это решение здесь. Я рекомендую прочитать всю статью, так как она объясняет, как это работает.

Ответ 3

Имея удовольствие потратить несколько часов на это, я подумал, что поделюсь своими выводами по этому вопросу. Это в модифицированном варианте Paglian method здесь. Поскольку я использую окна (без mingw), этот метод не работает. Итак, вот модифицированный вариант:

# using shell_path() to correct path depending on platform
# escaping quotes and backslashes for file paths
copydata.commands = $(COPY_FILE) \"$$shell_path($$PWD\\archive.png)\" \"$$shell_path($$OUT_PWD)\"
first.depends = $(first) copydata
export(first.depends)
export(copydata.commands)
QMAKE_EXTRA_TARGETS += first copydata

Так как это делает его кросс-платформой, вы, конечно же, можете использовать этот метод в Linux, MacOS или что у вас есть. Заметьте, что я копирую один файл, поэтому вместо $(COPY_DIR) я использую $(COPY_FILE). При необходимости адаптируйте.


Если вы хотите, чтобы файл скопировали на точный путь туда, где заканчивается двоичный файл (поскольку двоичный файл окажется в подпапке $$ OUT_PWD (отладка или выпуск, по крайней мере, при создании с помощью Qt Creator с MSVC 14/cdb.exe/Code:: Blocks Makefiles) вам нужно следующее:

# adapted from https://stackoverflow.com/a/2581068
CONFIG(debug, debug|release) {
    VARIANT = debug
} else {
    VARIANT = release
}

Помните, что даже если двоичный файл попадает во вложенную папку, QtCreator выполняет двоичный код из $$OUT_PWD, поэтому он ожидает найти файловые ресурсы в $$OUT_PWD, а НЕ - subdir debug. Это означает, что вы, например, не можете сделать QIcon("archive.png") и ожидать, что он найдет его помимо исполняемого файла.

Это, конечно, легко исправить, если:

QDir exeDir(QCoreApplication::applicationDirPath());
QIcon qIcon(exeDir.filePath("archive.png"));

Если вы решите, что это то, что вы хотите, вам, очевидно, нужно отредактировать последний аргумент $$(COPY_FILE) (в .pro) следующим образом: \"$$shell_path($$OUT_PWD)\\$$VARIANT\"


Еще одна вещь, которую следует отметить, - это то, что (в моем случае так или иначе) Qt Creator (4.0.1) не всегда создает файл .pro, так как он не обнаруживает никаких изменений в конфигурации, поэтому для отражения вышеуказанных изменений в Makefile (и, таким образом, запускается при создании проекта), вы должны фактически создать .pro вручную, запустив Build->run qmake в меню приложения. Чтобы все было гладко, посмотрите как результат компиляции, нажав Alt + 4 (в любом случае на Windows).

Ответ 5

Возможно, следующий код QMake помогает в качестве отправной точки. Он копирует недавно созданный двоичный файл в другой каталог "TARGET_DEST":

TARGET_SRC  = $${_PRO_FILE_PWD_}
TARGET_DEST = $${PWD}/src

CONFIG(debug, debug|release) {
    TARGET_SRC = $${TARGET_SRC}/debug
} else {
    TARGET_SRC = $${TARGET_SRC}/release
}

TARGET_SRC   = $${TARGET_SRC}/$${TARGET}
TARGET_DEST  = $${TARGET_DEST}/$${TARGET}

linux-g++{
    if( equals(TEMPLATE, app) || equals(TEMPLATE, vcapp) ){
        # nothing to do here
    }
    if( equals(TEMPLATE, lib) || equals(TEMPLATE, vclib) ){
        TARGET_SRC   = $${TARGET_SRC}.so
        TARGET_DEST  = $${TARGET_DEST}.so
    }
    QMAKE_POST_LINK += $$quote(cp $${TARGET_SRC} $${TARGET_DEST}$$escape_expand(\n\t))
}

win32 {
    if( equals(TEMPLATE, app) || equals(TEMPLATE, vcapp) ){
        TARGET_SRC   = $${TARGET_SRC}.exe
        TARGET_DEST  = $${TARGET_DEST}.exe
    }
    if( equals(TEMPLATE, lib) || equals(TEMPLATE, vclib) ){
        TARGET_SRC   = $${TARGET_SRC}.dll
        TARGET_DEST  = $${TARGET_DEST}.dll
    }
    TARGET_SRC  ~= s,/,\\,g # fix slashes 
    TARGET_DEST ~= s,/,\\,g # fix slashes
    QMAKE_POST_LINK +=$$quote(cmd /c copy /y $${TARGET_SRC} $${TARGET_DEST}$$escape_expand(\n\t))
}

message("[INFO] Will copy $${TARGET_SRC} to $${TARGET_DEST}")