2013-08-28 9 views
5

Ho alcuni file di dati di grandi dimensioni che devono essere copiati dalle cartelle di origine per creare cartelle durante la nostra build Qmake/QtCreator. Dato che sono grandi, voglio solo che la copia avvenga per i file nuovi/modificati. E mi piacerebbe davvero evitare di elencarli tutti nello specifico nel file di progetto. Ecco cosa ho provato:Come ottenere QMake per copiare file di dati di grandi dimensioni solo se aggiornati

Questo tentativo di copiare i file di dati non riesce perché la cartella DemoData è la destinazione. Pertanto la copia non viene eseguita se i file all'interno della cartella vengono aggiunti o modificati. Solo se la cartella non esiste.

DemoData.commands = $$COPY_CMD $${SRC_DATA_DIR}DemoData $${BLD_DATA_DIR}DemoData 
DemoData.target += $${BLD_DATA_DIR}DemoData 
PRE_TARGETDEPS += $${BLD_DATA_DIR}DemoData 
QMAKE_EXTRA_TARGETS += DemoData 

Questo approccio fallisce perché l'elemento DemoData.target non dovrebbe avere un elenco di più elementi. QMake inserisce l'elenco tra virgolette nel makefile generato in modo che diventi un obiettivo.

DemoData.commands = $$COPY_CMD $${SRC_DATA_DIR}DemoData $${BLD_DATA_DIR}DemoData 
DEMO_DATA_FILES = $$files($${SRC_DATA_DIR}DemoData/*) 
for(FILE, DEMO_DATA_FILES){ 
    DemoData.target += $${BLD_DATA_DIR}DemoData\\$$basename(FILE) 
    PRE_TARGETDEPS += $${BLD_DATA_DIR}DemoData\\$$basename(FILE) 
} 
QMAKE_EXTRA_TARGETS += DemoData 

Questo tentativo fallisce perché (AFAICT) QMake non supporta i nomi delle variabili contenute in altre variabili. Sembra essere più una sostituzione di un livello. Viene generato un makefile, ma gli obiettivi DemoDataX non hanno linee di comando. Tutti i tentativi di visualizzare il contenuto del campo "comandi" generano errori di sintassi.

DEMO_DATA_FILES = $$files($${SRC_DATA_DIR}DemoData/*) 
DEMO_DATA_NAME = DemoData 
for(FILE, DEMO_DATA_FILES){ 
    $${DEMO_DATA_NAME}.target = $${FILE} 
    $${DEMO_DATA_NAME}.commands = $$COPY_CMD $${FILE} $${BLD_DATA_DIR}DemoData 
    PRE_TARGETDEPS += $${FILE} 
    QMAKE_EXTRA_TARGETS += $${DEMO_DATA_NAME} 
    DEMO_DATA_NAME = $${DEMO_DATA_NAME}X 
} 

Questo approccio funziona, ma con due difetti. Il minore è che deve essere eseguito un passaggio separato di "installazione". Il principale è che i file vengono sempre copiati incondizionatamente. Poiché i nostri file di dati sono grandi, questo è inaccettabile per il tempo.

DemoData.path = $${BLD_DATA_DIR}DemoData 
DemoData.files = $${SRC_DATA_DIR}DemoData/* 
INSTALLS += DemoData 

C'è un modo per fare questo, o sto lasciato con una sorta di script esterno o generato manualmente Makefile/mantenuto?

risposta

4

Utilizzare la funzione QMAKE_EXTRA_COMPILES.

# list your files in this variable. 
# Masks are available with $$files functions but 
# if your set of files changes (files added or removed) 
# your have to re-run qmake after that explicitly, not just make 
MYFILES = $$files($${PWD}/files/*.*) 

copy_files.name = copy large files 
copy_files.input = MYFILES 
# change datafiles to a directory you want to put the files to 
copy_files.output = $${OUT_PWD}/datafiles/${QMAKE_FILE_BASE}${QMAKE_FILE_EXT} 
copy_files.commands = ${COPY_FILE} ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} 
copy_files.CONFIG += no_link target_predeps 

QMAKE_EXTRA_COMPILERS += copy_files 

Aggiungi i tuoi file di grandi dimensioni alla variabile MYFILES. Per ogni file verrà generata una regola in Makefile che copia il file nella directory specificata (file di dati nell'esempio). Il file originale verrà elencato come dipendenza nella regola (questo è il comportamento predefinito di qmake) in modo che la copia si verifichi solo quando il file originale è più fresco della copia esistente. Le regole generate sono elencate come dipendenze nella regola del file di destinazione (copy_files.CONFIG + = target_predeps) in modo che la copia si verifichi automaticamente su ogni generazione.

L'unica avvertenza è questo: se il gruppo di file è dinamico (i file vengono aggiunti o rimossi) è possibile utilizzare le maschere, come nel mio esempio, ma bisogna stare attenti ad eseguire qmake dopo aver cambiato il set. Siate consapevoli del fatto che Qt Creator crea progetti avviando make, not qmake. Il modo più semplice per garantire il lancio di qmake è modificare il file .pro.

Per chi sa leggere russa c'è più informazioni QMAKE_EXTRA_COMPILERS here

+0

Sembra una buona opzione. Non avrò la possibilità di provare per un po '. –

2

Avete bisogno che lo script sia multipiattaforma? Personalmente non avrei usato il comando copia, ma robocopy su Windows e rsync su Mac/Linux.

win32: $${DEMO_DATA_NAME}.commands = robocopy $${SRC_DIR} $${DST_DIR} $${FILE} /MIR /XO 
!win32: $${DEMO_DATA_NAME}.commands = rsync -aru $${FILE} $${BLD_DATA_DIR} 

Io non sono davvero sicuro di quello che si desidera copiare qui, ma si ottiene l'idea, è possibile adattare i file e/o directory.

I parametri di Robocopy sono descritti here.

  • /MIR rispecchia una struttura di directory
  • /XO esclude i file più vecchi.

I parametri Rsync sono descritti here.

  • -a Archivio
  • -r ricorsivo
  • -u aggiornamento solo quando la sorgente è più recente

Come nota a margine, se non si desidera eseguire questo comando make install, è possibile impostare questo target extra come dipendenza dal progetto che necessita di questi file: theProjectNeedingThoseFiles.depends += DemoData.

+0

Si dovrebbe cambiare il comando 'robocopy' a' -robocopy' (aggiungere un pizzico di fronte), che in pratica dice "ignorare gli errori di questo comando "(allora vedrai ancora un messaggio di errore" ignorato ", ma continua). Il problema è che Robocopy restituisce il codice di uscita '1' se ha avuto successo - ma' make' lo interpreta come un errore e ferma l'esecuzione del Makefile ... Ci ho messo ore per capirlo ... In alternativa usa 'robocopy [...] || rem' che proverà Robocopy e se restituisce il codice di uscita 1 (che sarà), 'rem' (non fare nulla) verrà eseguito in seguito - make assumerà che tutto andava bene. – mozzbozz

+0

Ovviamente entrambe le soluzioni sono tutt'altro che ideali in quanto la prima inquinerà l'output con "errore ignorato [...]" - i messaggi e il secondo ignoreranno completamente qualsiasi errore. Suggerimenti di benvenuto;) – mozzbozz

Problemi correlati