gui - Copie un archivo al directorio de compilación después de compilar el proyecto con Qt
qt gui (5)
Después de haber tenido el placer de perder unas horas con esto, pensé en compartir mis hallazgos sobre el asunto. Esto en una variante modificada del método de Paglian here . Como estoy usando Windows (sin mingw) ese método no funciona. Entonces aquí está la variante modificada:
# 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
Como esto lo hace multiplataforma, por supuesto, también puedes utilizar este método en Linux, MacOS o lo que sea. Tenga en cuenta que estoy copiando un solo archivo, por lo que en lugar de $(COPY_DIR)
estoy usando $(COPY_FILE)
. Adaptarse según sea necesario.
Si desea que los archivos se copien en la ruta exacta de donde termina el binario (ya que el binario terminará en una subcarpeta de $$ OUT_PWD ( depuración o publicación , al menos cuando se compila con Qt Creator con MSVC 14 / cdb) .exe / Code :: Blocks Makefiles configuration) necesita esto:
# adapted from https://stackoverflow.com/a/2581068
CONFIG(debug, debug|release) {
VARIANT = debug
} else {
VARIANT = release
}
Tenga en cuenta que aunque el binario termine en una subcarpeta, QtCreator ejecuta el binario desde $$OUT_PWD
, por lo que espera encontrar recursos de archivos en $$OUT_PWD
, y NO el $$OUT_PWD
depuración . Eso significa que usted, por ejemplo, no puede hacer QIcon("archive.png")
y esperar que lo encuentre además del ejecutable.
Esto es, por supuesto, fácil de remediar haciendo:
QDir exeDir(QCoreApplication::applicationDirPath());
QIcon qIcon(exeDir.filePath("archive.png"));
Si decide que esto es lo que quiere, obviamente necesita editar el último argumento de $$(COPY_FILE)
(en .pro) de la siguiente manera: /"$$shell_path($$OUT_PWD)//$$VARIANT/"
Otra cosa a tener en cuenta es que (en mi caso, de todos modos) Qt Creator (4.0.1) no siempre crea el archivo .pro, ya que no está detectando ningún cambio en la configuración, por lo que los cambios anteriores se reflejan en el Makefile (y así ejecutar cuando construyes tu proyecto) tienes que construir el .pro manualmente ejecutando Build->run qmake
desde el menú de la aplicación. Para asegurarse de que todo funcione sin problemas, visualice la salida de compilación presionando Alt + 4 (en Windows de todos modos).
He visto varias sugerencias, pero nada realmente funcionó para mí como yo quería. Solo necesito copiar un archivo al directorio de destino deseado.
Diga, por ejemplo, de esta respuesta :
install_it.path = %{buildDir}
install_it.files += %{sourceDir}/settings.ini
INSTALLS += install_it
Las variables %{buildDir}
y %{sourceDir}
deben definir para que funcionen. Ok, no hay problema con %{sourceDir}
: es justo .
. ¿Pero cómo puedo obtener %{buildDir}
?
EDIT1
Diga, tengo un proyecto my_project
aquí:
/path/to/my_project
Entonces, la ruta de compilación de lanzamiento es esta: /path/to/my_project-build-Desktop-release
,
ruta de compilación de depuración es esta: /path/to/my_project-build-Desktop-debug
Tengo archivos para copiar al directorio de destino aquí: /path/to/my_project/copy_to_install_dir
Por lo tanto, quiero que todos los archivos de /path/to/my_project/copy_to_install_dir
se copien a /path/to/my_project-build-Desktop-release
cuando publique build. Y, de la misma manera para la construcción de depuración.
No puedo encontrar la variable que contiene la ruta de destino completa, es decir /path/to/my_project-build-Desktop-release
para la compilación de depuración.
Por las dudas: uso Windows, pero de todos modos estoy buscando una solución crossplatform.
EDIT2
Solución exacta, para lectores futuros:
install_it.path = $$OUT_PWD
install_it.files = copy_to_install_dir/*
INSTALLS += /
install_it
Esto es lo que estamos usando en 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
Básicamente, establece los archivos y la ruta para el destino, y luego lo INSTALLS
variable INSTALLS
. Lo que aún necesita es la variable $$OUT_PWD
, que también estamos utilizando ampliamente en QtSerialPort
. Eso le proporcionará la raíz del directorio de compilación.
Es una de esas características qmake no documentadas, pero es muy útil.
Además, para el directorio de origen en general, no debe suponer "." y demás, porque eso puede ser diferente cuando se ejecuta una aplicación envoltorio en la que el "." señalará eso y no lo que espera: la raíz del proyecto fuente qmake. En esos casos, es más seguro usar la variable PWD
que apunta a la fuente en oposición a OUT_PWD
que apunta a la carpeta de compilación.
Solo para dar un ejemplo aproximado sobre la diferencia de esas dos variables con un escenario del mundo real, aquí puede encontrar lo que estamos haciendo en QtSerialPort:
system("echo QTSERIALPORT_PROJECT_ROOT = $$PWD >> $$OUT_PWD/.qmake.cache")
system("echo QTSERIALPORT_BUILD_ROOT = $$OUT_PWD >> $$OUT_PWD/.qmake.cache")
donde el primero es la raíz del proyecto de origen y el segundo para el directorio de compilación. Pueden ser lo mismo, pero en muchos casos no lo son, por ejemplo cuando se compila a través de QtCreator solo para uno de esos.
La respuesta seleccionada es correcta, pero requiere llamar a make install
, que en mi opinión es molesto o propenso a errores. En su lugar, para copiar archivos al directorio de compilación use:
copydata.commands = $(COPY_DIR) $$PWD/required_files $$OUT_PWD
first.depends = $(first) copydata
export(first.depends)
export(copydata.commands)
QMAKE_EXTRA_TARGETS += first copydata
Donde required_files
debe ser reemplazado con su ruta correcta. $$PWD
es la ruta del archivo .pro
actual, es posible que no lo requiera.
Nota : Encontré esta solución here . Recomiendo leer todo el artículo, ya que explica cómo funciona.
Puede usar DESTDIR y PWD qmake variables o OUT_PWD: http://qt-project.org/doc/qt-5.1/qmake/qmake-variable-reference.html#destdir
Quizás el siguiente código de QMake ayude como punto de partida. Copia el binario recientemente construido a otro directorio "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}")