open - qt full
QMake: cómo copiar un archivo a la salida (7)
¿Cómo puedo copiar un archivo de mi proyecto al directorio de salida con qmake?
Estoy compilando en Linux, pero en el futuro lo compilaré en Mac y Windows.
Además de la respuesta de Jake y el comentario de @Phlucious, se puede usar la función qmake defineReplace
, que es mejor para este caso de uso. Después de usar el ejemplo proporcionado, encontré un problema, donde qmake saltó la última acción de enlace de publicación que agregué. Eso podría ser un problema con la exportación de la variable aunque el contenido se veía bastante bien todo el tiempo. Para resumir, aquí está el código modificado
defineReplace(copyToDir) {
files = $$1
DIR = $$2
LINK =
for(FILE, files) {
LINK += $$QMAKE_COPY $$shell_path($$FILE) $$shell_path($$DIR) $$escape_expand(//n//t)
}
return($$LINK)
}
Esta función de copia general puede ser utilizada por algunas funciones de conveniencia como esta
defineReplace(copyToBuilddir) {
return($$copyToDir($$1, $$OUT_PWD))
}
El segundo toma solo un argumento (uno o más archivos) y proporciona una ruta fija. Más o menos lo mismo que en la respuesta de referencias.
Pero ahora note la diferencia de invocación
QMAKE_POST_LINK += $$copyToBuilddir(deploy.bat)
Como puede ver, puede adjuntar el comando devuelto a QMAKE_PRE_LINK para una mayor flexibilidad.
Cree un archivo copy_files.prf
en una de las rutas que qmake usa para las características de configuración . El archivo debería verse así:
QMAKE_EXTRA_COMPILERS += copy_files
copy_files.name = COPY
copy_files.input = COPY_FILES
copy_files.CONFIG = no_link
copy_files.output_function = fileCopyDestination
defineReplace(fileCopyDestination) {
return($$shadowed($$1))
}
win32:isEmpty(MINGW_IN_SHELL) {
# Windows shell
copy_files.commands = copy /y ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
TOUCH = copy /y nul
}
else {
# Unix shell
copy_files.commands = mkdir -p `dirname ${QMAKE_FILE_OUT}` && cp ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
TOUCH = touch
}
QMAKE_EXTRA_TARGETS += copy_files_cookie
copy_files_cookie.target = copy_files.cookie
copy_files_cookie.depends = compiler_copy_files_make_all
win32:!mingw {
# NMake/MSBuild
copy_files_cookie.commands = $$TOUCH $** && $$TOUCH $@
}
else {
# GNU Make
copy_files_cookie.commands = $$TOUCH $< && $$TOUCH $@
}
PRE_TARGETDEPS += $${copy_files_cookie.target}
Cómo funciona
La primera parte define un compilador adicional que leerá los nombres de los archivos de entrada de la variable COPY_FILES
. La siguiente parte define la función que usará para sintetizar un nombre de archivo de salida correspondiente a cada entrada. Luego definimos los comandos utilizados para invocar este "compilador", dependiendo del tipo de shell en el que nos encontremos.
A continuación, definimos un objetivo de archivo adicional copy_files.cookie
, que depende del objetivo compiler_copy_files_make_all
. Este último es el nombre del objetivo que qmake genera para el compilador adicional que definimos en el primer paso. Esto significa que cuando se copy_files.cookie
objetivo copy_files.cookie
, invocará el compilador extra para copiar los archivos.
Especificamos un comando que ejecutará este objetivo, que touch
los archivos copy_files.cookie
y compiler_copy_files_make_all
. Al tocar estos archivos, nos aseguramos de que make
no intente copiar los archivos nuevamente a menos que sus marcas de tiempo sean más recientes que los archivos tocados. Finalmente, agregamos copy_files.cookie
a la lista de dependencias del objetivo make all
.
Cómo usarlo
En su archivo .pro
, agregue copy_files
a la variable CONFIG
:
CONFIG += copy_files
A continuación, agregue los archivos a la variable COPY_FILES
:
COPY_FILES += docs/*.txt
Descubrí que tenía que modificar la respuesta dada por sje397. para Qt5 Beta1 junto con QtCreator 2.5.2 . Uso esta secuencia de comandos para copiar los archivos qml en el directorio de destino como un paso adicional después de completar la compilación.
Mi archivo .pro tiene el siguiente código
OTHER_FILES += /
Application.qml
# Copy qml files post build
win32 {
DESTDIR_WIN = $${DESTDIR}
DESTDIR_WIN ~= s,/,//,g
PWD_WIN = $${PWD}
PWD_WIN ~= s,/,//,g
for(FILE, OTHER_FILES){
QMAKE_POST_LINK += $$quote(cmd /c copy /y $${PWD_WIN}//$${FILE} $${DESTDIR_WIN}$$escape_expand(//n//t))
}
}
unix {
for(FILE, OTHER_FILES){
QMAKE_POST_LINK += $$quote(cp $${PWD}/$${FILE} $${DESTDIR}$$escape_expand(//n//t))
}
}
Tenga en cuenta que utilizo $$ PWD_WIN para proporcionar la ruta completa al archivo de origen para el comando de copia.
Primero, defina las dos funciones siguientes para admitir Windows / Unix.
defineReplace(nativePath) {
OUT_NATIVE_PATH = $$1
# Replace slashes in paths with backslashes for Windows
win32:OUT_NATIVE_PATH ~= s,/,//,g
return($$OUT_NATIVE_PATH)
}
# Copies the given files to the destination directory
defineReplace(copyToDestDirCommands) {
variable_files = $$1
files = $$eval($$variable_files)
DDIR = $$nativePath($$2)
win32:DDIR ~= s,/,//,g
POST_LINK = echo "Copying files to $$DDIR" $$escape_expand(//n//t)
win32 {
POST_LINK += $$QMAKE_MKDIR $$quote($$DDIR) 2>&1 & set errorlevel=0 $$escape_expand(//n//t)
}
!win32 {
POST_LINK += $$QMAKE_MKDIR -p $$quote($$DDIR) $$escape_expand(//n//t)
}
for(ORIGINAL_FILE, files) {
FILE = $$nativePath($$ORIGINAL_FILE)
POST_LINK += $$QMAKE_COPY $$quote($$FILE) $$quote($$DDIR) $$escape_expand(//n//t)
}
return ($$POST_LINK)
}
Luego puede usar el siguiente código para llamar a los funcitons que se definieron antes para copiar archivos en una carpeta específica, y también crear el directorio cuando sea necesario. Esto se prueba en Win32, las pruebas de Linux son bienvenidas.
BATOS_FILES = /
$$BATOS_BIN_ROOT/batos-core.dll /
$$BATOS_BIN_ROOT/batos-pfw.dll /
$$BATOS_BIN_ROOT/dre.dll /
$$BATOS_BIN_ROOT/log4qt.dll
QMAKE_POST_LINK += $$copyToDestDirCommands(BATOS_FILES, $$DESTDIR)
BATOS_PLUGINS_FILES = /
$$BATOS_BIN_ROOT/plugins/com.xaf.plugin-manager.dll /
$$BATOS_BIN_ROOT/plugins/org.commontk.eventadmin.dll
QMAKE_POST_LINK += $$copyToDestDirCommands(BATOS_PLUGINS_FILES, $$DESTDIR/plugins)
Puede usar una función qmake para reutilizar:
# Copies the given files to the destination directory
defineTest(copyToDestdir) {
files = $$1
for(FILE, files) {
DDIR = $$DESTDIR
# Replace slashes in paths with backslashes for Windows
win32:FILE ~= s,/,//,g
win32:DDIR ~= s,/,//,g
QMAKE_POST_LINK += $$QMAKE_COPY $$quote($$FILE) $$quote($$DDIR) $$escape_expand(//n//t)
}
export(QMAKE_POST_LINK)
}
luego úsalo de la siguiente manera:
copyToDestdir($$OTHER_FILES) # a variable containing multiple paths
copyToDestdir(run.sh) # a single filename
copyToDestdir(run.sh README) # multiple files
Si usa make install, puede usar la variable INSTALLS de qmake . Aquí hay un ejemplo:
images.path = $${DESTDIR}/images
images.files += images/splashscreen.png
images.files += images/logo.png
INSTALLS += images
luego ejecuta ''make install''
Aquí hay un ejemplo de uno de nuestros proyectos. Muestra cómo copiar archivos a DESTDIR
para Windows y Linux.
linux-g++{
#...
EXTRA_BINFILES += /
$${THIRDPARTY_PATH}/gstreamer-0.10/linux/plugins/libgstrtp.so /
$${THIRDPARTY_PATH}/gstreamer-0.10/linux/plugins/libgstvideo4linux2.so
for(FILE,EXTRA_BINFILES){
QMAKE_POST_LINK += $$quote(cp $${FILE} $${DESTDIR}$$escape_expand(/n/t))
}
}
win32 {
#...
EXTRA_BINFILES += /
$${THIRDPARTY_PATH}/glib-2.0/win32/bin/libglib-2.0.dll /
$${THIRDPARTY_PATH}/glib-2.0/win32/bin/libgmodule-2.0.dll
EXTRA_BINFILES_WIN = $${EXTRA_BINFILES}
EXTRA_BINFILES_WIN ~= s,/,//,g
DESTDIR_WIN = $${DESTDIR}
DESTDIR_WIN ~= s,/,//,g
for(FILE,EXTRA_BINFILES_WIN){
QMAKE_POST_LINK +=$$quote(cmd /c copy /y $${FILE} $${DESTDIR_WIN}$$escape_expand(/n/t))
}
}