Come posso copiare un file dal mio progetto nella directory di output con qmake?QMake - come copiare un file nell'output
Sto compilando Linux ma in futuro lo compilerò su Mac e Windows.
Come posso copiare un file dal mio progetto nella directory di output con qmake?QMake - come copiare un file nell'output
Sto compilando Linux ma in futuro lo compilerò su Mac e Windows.
Ecco un esempio di uno dei nostri progetti. Mostra come copiare i file su DESTDIR
per Windows e 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))
}
}
Se si utilizza make install, è possibile utilizzare il INSTALLS variable of qmake. Ecco un esempio:
images.path = $${DESTDIR}/images
images.files += images/splashscreen.png
images.files += images/logo.png
INSTALLS += images
poi eseguire 'make install'
Posso in qualche modo chiamare automaticamente "make install" in QT Creator ogni volta che costruisco? Mi piace questo approccio indipendente dalla piattaforma, ma voglio che alcuni (pochi) file vengano sempre copiati ogni volta che costruisco in QT Creator. –
@HorstWalter: controlla la variabile QMAKE_POST_LINK. È possibile definire un comando personalizzato da eseguire. In particolare, tuttavia, dice che alcuni backend non lo supportano, quindi non so come sarebbe cross-platform. Se i file sono sempre in giro, puoi anche creare un target personalizzato e rendere il file eseguibile risultante dipendente dal target personalizzato, che copierà quei file. –
È possibile utilizzare una funzione di qmake per la riusabilità:
# 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)
}
quindi utilizzarlo come segue:
copyToDestdir($$OTHER_FILES) # a variable containing multiple paths
copyToDestdir(run.sh) # a single filename
copyToDestdir(run.sh README) # multiple files
Solo una nota: ho usato '$$ OUT_PWD' invece di' $$ DESTDIR' per farlo funzionare. Per il riferimento '$$ OUT_PWD' è la cartella su cui è costruito il programma, e' $$ PWD' è la cartella da cui viene costruito il programma - in altre parole è dove si trova il file .pro. – Logan
Perché questo ha 'defineTest' invece di' defineReplace'? Non ho potuto ottenere qmake per costruire questo con 'defineReplace', ma non capisco perché. I [docs] (http://doc.qt.io/qt-5/qmake-language.html#test-functions) dicono che "Questo tipo di funzione dovrebbe essere usato solo nelle espressioni condizionali" che non è vero in questo Astuccio. – Phlucious
Ho incontrato strani problemi di formattazione con la piattaforma MinGW quando è stato copiato più di un file. Ho dovuto modificare la riga 'QMAKE_POST_LINK' a' QMAKE_POST_LINK + = $$ QMAKE_COPY $$ preventivo ($$ FILE) $$ preventivo ($$ DDIR) $$ escape_expand (\\ n \\ t \\ n \\ t) 'Le nuove righe multiple erano necessarie perché un percorso di Windows può terminare con' \\ ', ma che sfugge alla linea e continua fino alla successiva. –
Ho trovato che dovevo modificare la risposta data da sje397. per Qt5 Beta1 insieme a QtCreator 2.5.2. Io uso questo script per copiare i file qml nella directory di destinazione come un passo aggiuntivo dopo che la compilazione è stata completata.
Il mio file .pro ha il seguente codice
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))
}
}
Nota che uso uso $$ PWD_WIN di fornire il percorso completo del file sorgente per il comando di copia.
Creare un file copy_files.prf
in uno dei percorsi che qmake utilizza per config features. Il file dovrebbe essere simile a questo:
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 [email protected]
}
else {
# GNU Make
copy_files_cookie.commands = $$TOUCH $< && $$TOUCH [email protected]
}
PRE_TARGETDEPS += $${copy_files_cookie.target}
Come funziona
La prima parte definisce un extra compiler, che leggerà i nomi dei file di input dalla variabile COPY_FILES
. La parte successiva definisce la funzione che utilizzerà per sintetizzare un nome file di output corrispondente a ciascun input. Quindi definiamo i comandi utilizzati per richiamare questa "compilatore", a seconda di quale tipo di shell ci troviamo.
allora definiamo un extra makefile targetcopy_files.cookie
, che dipende dal target compiler_copy_files_make_all
. Quest'ultimo è il nome del target che qmake genera per il compilatore extra definito nel primo passaggio. Ciò significa che quando viene creato il target copy_files.cookie
, verrà richiamato il compilatore aggiuntivo per copiare i file.
Specifichiamo un comando da eseguire da questa destinazione, che sarà touch
i file copy_files.cookie
e compiler_copy_files_make_all
. Toccando questi file, ci assicuriamo che make
non provi a copiare nuovamente i file a meno che i loro timestamp siano più recenti dei file toccati. Infine, aggiungiamo copy_files.cookie
all'elenco delle dipendenze della destinazione make all
.
Come usarlo
Nel file .pro
, aggiungere copy_files
alla CONFIG
variabile:
CONFIG += copy_files
quindi aggiungere i file alla variabile COPY_FILES
:
COPY_FILES += docs/*.txt
Come Oltre a Jake's answer e @Phlucious com si può usare la funzione qmake defineReplace
che si adatta meglio a questo caso d'uso. Dopo aver utilizzato l'esempio fornito, ho riscontrato un problema, in cui qmake ha saltato l'ultima azione del link post che ho aggiunto. Questo potrebbe essere un problema con l'esportazione della variabile anche se il contenuto sembrava abbastanza bene tutto il tempo. Per farla breve, qui ist il codice modificato
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)
}
Questa funzione generale di copia può essere utilizzato da alcune funzioni di convenienza come questo
defineReplace(copyToBuilddir) {
return($$copyToDir($$1, $$OUT_PWD))
}
Il secondo prende un solo argomento (uno o più file) e fornisce un percorso fisso. Praticamente come nella risposta ai riferimenti.
Ma ora si noti la differenza invocazione
QMAKE_POST_LINK += $$copyToBuilddir(deploy.bat)
Come si può vedere, è possibile collegare il comando tornato a QMAKE_PRE_LINK per una flessibilità ancora maggiore.
Sì. vale la pena avere la versione con la directory di destinazione. Ne avevo bisogno anche perché DESTDIR non è sempre impostato. –
Come può essere corretto? Su Linux Qt5.2.0 '$$ {DESTDIR}' si espande nella stringa vuota. Il percorso per '$ {FILE}' è relativo alla directory di build, non alla directory di origine. – Cuadue