Скопируйте файл для сборки каталога после компиляции проекта с помощью 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
Ответы
Ответ 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).
Ответ 4
Вы можете использовать переменные qmake DESTDIR и PWD или OUT_PWD: http://qt-project.org/doc/qt-5.1/qmake/qmake-variable-reference.html#destdir
Ответ 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}")