Wie kann ich mit qmake eine Datei aus meinem Projekt in das Ausgabeverzeichnis kopieren?
Ich kompiliere unter Linux, aber in Zukunft werde ich es auf Mac und Windows kompilieren.
Hier ist ein Beispiel aus einem unserer Projekte. Es zeigt, wie Sie Dateien für Windows und Linux in die Variable DESTDIR
kopieren.
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))
}
}
Sie können eine qmake-Funktion für die Wiederverwendbarkeit verwenden:
# 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)
}
dann verwenden Sie es wie folgt:
copyToDestdir($$OTHER_FILES) # a variable containing multiple paths
copyToDestdir(run.sh) # a single filename
copyToDestdir(run.sh README) # multiple files
Wenn Sie make install verwenden, können Sie die INSTALLS-Variable von qmake verwenden. Hier ist ein Beispiel:
images.path = $${DESTDIR}/images
images.files += images/splashscreen.png
images.files += images/logo.png
INSTALLS += images
dann make install
ausführen.
Erstellen Sie eine Datei copy_files.prf
in einem der Pfade, die qmake für config features verwendet. Die Datei sollte so aussehen:
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}
Wie es funktioniert
Der erste Teil definiert einen zusätzlichen Compiler , der die Dateinamen der Eingabedateien aus der COPY_FILES
-Variablen liest. Der nächste Teil definiert die Funktion, mit der ein Ausgabedateiname synthetisiert wird, der jeder Eingabe entspricht. Dann definieren wir die Befehle, die zum Aufrufen dieses "Compilers" verwendet werden, abhängig von der Art der Shell, in der wir uns befinden.
Dann definieren wir ein zusätzliches Makefile-Zielcopy_files.cookie
, das vom Ziel compiler_copy_files_make_all
abhängt. Letzteres ist der Name des Ziels, das qmake für den zusätzlichen Compiler generiert, den wir im ersten Schritt definiert haben. Dies bedeutet, dass beim Erstellen des copy_files.cookie
-Ziels der zusätzliche Compiler aufgerufen wird, um die Dateien zu kopieren.
Wir geben einen Befehl an, der von diesem Ziel ausgeführt werden soll, und touch
die Dateien copy_files.cookie
und compiler_copy_files_make_all
. Durch das Berühren dieser Dateien stellen wir sicher, dass make
nicht versucht, die Dateien erneut zu kopieren, es sei denn, ihre Zeitstempel sind aktueller als die berührten Dateien. Schließlich fügen wir copy_files.cookie
zur Liste der Abhängigkeiten des make all
-Ziels hinzu.
Verwendung
Fügen Sie in Ihrer .pro
-Datei copy_files
zur Variable CONFIG
hinzu:
CONFIG += copy_files
Fügen Sie dann die Dateien der COPY_FILES
-Variablen hinzu:
COPY_FILES += docs/*.txt
Ich fand, dass ich die Antwort von sje397 ändern musste. für Qt5 Beta1 zusammen mit QtCreator 2.5.2 . Ich verwende dieses Skript, um die qml-Dateien nach Abschluss des Builds als zusätzlichen Schritt in das Zielverzeichnis zu kopieren.
Meine .pro-Datei enthält den folgenden Code
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))
}
}
Beachten Sie, dass ich mit $$ PWD_WIN den vollständigen Pfad zur Quelldatei für den Kopierbefehl angeben kann.
Qt 5.6 hinzugefügt dies als nicht dokumentiertes Feature:
CONFIG *= file_copies
Erfassen Sie einen Namen, um die Dateien zu beschreiben, die Sie kopieren möchten:
COPIES += myDocumentation
Listen Sie die Dateien auf, die Sie kopieren möchten, in ihrem Member .files
:
myDocumentation.files = $$files(text/docs/*.txt)
Geben Sie den Zielpfad im Member .path
an:
myDocumentation.path = $$OUT_PWD/documentation
Geben Sie optional einen Basispfad an, der von den Quellpfaden abgeschnitten werden soll:
myDocumentation.base = $$PWD/text/docs
Im Grunde funktioniert es, wenn Sie die gleichen Dinge wie viele der anderen Antworten hier tun. Siehe file_copies.prf für die blutigen Details.
Die Schnittstelle ist der für INSTALLS
sehr ähnlich.
Als Ergänzung zu Jakes Antwort und @Phlucious-Kommentar kann die Funktion qmake defineReplace
verwendet werden, die für diesen Anwendungsfall besser geeignet ist. Nachdem ich das bereitgestellte Beispiel verwendet hatte, trat ein Problem auf, bei dem qmake die letzte hinzugefügte Link-Aktion übersprang. Dies könnte ein Problem beim Export der Variablen sein, obwohl der Inhalt die ganze Zeit ziemlich gut aussah. Lange Geschichte, hier ist der modifizierte Code
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)
}
Diese allgemeine Kopierfunktion kann von einigen Komfortfunktionen wie dieser verwendet werden
defineReplace(copyToBuilddir) {
return($$copyToDir($$1, $$OUT_PWD))
}
Die zweite nimmt nur ein Argument (eine oder mehrere Dateien) und stellt einen festen Pfad bereit. Ziemlich das gleiche wie in den Referenzen.
Man beachte nun aber den Unterschied beim Aufruf
QMAKE_POST_LINK += $$copyToBuilddir(deploy.bat)
Wie Sie sehen, können Sie den zurückgegebenen Befehl an QMAKE_PRE_LINK anhängen, um noch mehr Flexibilität zu erhalten.
definieren Sie zuerst irgendwo unten (was aus XD
Rahmen besteht):
# --------------------------------------
# This file defines few useful functions
# --------------------------------------
#copyDir(source, destination)
# using "Shell_path()" to correct path depending on platform
# escaping quotes and backslashes for file paths
defineTest(copyDir) {
#append copy command
!isEmpty(xd_copydir.commands): xd_copydir.commands += && \\$$escape_expand(\n\t)
xd_copydir.commands += ( $(COPY_DIR) \"$$Shell_path($$1)\" \"$$Shell_path($$2)\" || echo \"copy failed\" )
#the qmake generated MakeFile contains "first" and we depend that on "xd_copydir"
first.depends *= xd_copydir
QMAKE_EXTRA_TARGETS *= first xd_copydir
export(first.depends)
export(xd_copydir.commands)
export(QMAKE_EXTRA_TARGETS)
}
#copy(source, destination) (i.e. the name "copyFile" was reserved)
defineTest(copy) {
#append copy command
!isEmpty(xd_copyfile.commands): xd_copyfile.commands += && \\$$escape_expand(\n\t)
xd_copyfile.commands += ( $(COPY_FILE) \"$$Shell_path($$1)\" \"$$Shell_path($$2)\" || echo \"copy failed\" )
#the qmake generated MakeFile contains "first" and we depend that on "xd_copyfile"
first.depends *= xd_copyfile
QMAKE_EXTRA_TARGETS *= first xd_copyfile
export(first.depends)
export(xd_copyfile.commands)
export(QMAKE_EXTRA_TARGETS)
}
und verwenden Sie es in Ihrem Projekt wie:
include($$PWD/functions.prf) #optional
copy($$PWD/myfile1.txt, $$DESTDIR/myfile1.txt)
copy($$PWD/README.txt, $$DESTDIR/README.txt)
copy($$PWD/LICENSE, $$DESTDIR/LICENSE)
copyDir($$PWD/redist, $$DESTDIR/redist) #copy "redist" folder to "$$DESTDIR"
beachten Sie, dass alle Dateien kopiert werden sollten, bevor der Link erstellt wird
Definieren Sie zunächst die folgenden beiden Funktionen zur Unterstützung von 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)
}
Anschließend können Sie den folgenden Code verwenden, um die zuvor definierten Funktionen aufzurufen, um Dateien in einen bestimmten Ordner zu kopieren und das Verzeichnis bei Bedarf zu erstellen. Dies wird unter Win32 getestet, Linux-Tests sind willkommen.
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)