QMake-jak skopiować plik na wyjście
Jak mogę skopiować plik z mojego projektu do katalogu wyjściowego za pomocą qmake?
Kompiluję na Linuksie, ale w przyszłości skompiluję go na Mac i Windows.
9 answers
Oto przykład z jednego z naszych projektów. Pokazuje jak skopiować pliki do DESTDIR
Dla Windows i 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))
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-10-21 03:58:54
Możesz użyć funkcji qmake do ponownego użycia:
# 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)
}
Następnie użyj go w następujący sposób:
copyToDestdir($$OTHER_FILES) # a variable containing multiple paths
copyToDestdir(run.sh) # a single filename
copyToDestdir(run.sh README) # multiple files
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-07 22:03:20
Qt 5.6 Dodano to jako nieudokumentowana funkcja:
CONFIG += file_copies
Wymyśl nazwę opisującą pliki, które chcesz skopiować:
COPIES += myDocumentation
Lista plików, które chcesz skopiować, w jego członku .files
:
myDocumentation.files = $$files(text/docs/*.txt)
Określ ścieżkę docelową w elemencie .path
:
myDocumentation.path = $$OUT_PWD/documentation
Opcjonalnie określa ścieżkę bazową, która ma być przycięta ze ścieżek źródłowych:
myDocumentation.base = $$PWD/text/docs
Zasadniczo działa, robiąc te same rzeczy, co wiele innych odpowiedzi tutaj. Zobacz file_copies.prf dla krwawe szczegóły.
Interfejs jest bardzo podobny do tego dla INSTALLS
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-12 13:15:19
Jeśli używasz make install, możesz użyć zmiennej INSTALLS qmake . Oto przykład:
images.path = $${DESTDIR}/images
images.files += images/splashscreen.png
images.files += images/logo.png
INSTALLS += images
Następnie wykonaj make install
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-11 13:55:04
Stwierdziłem, że muszę zmodyfikować odpowiedź udzieloną przez sje397. dla Qt5 Beta1 razem z QtCreator 2.5.2. Używam tego skryptu do kopiowania plików qml do katalogu docelowego jako kroku dodawania po zakończeniu kompilacji.
Mój plik. pro ma następujący kod
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))
}
}
Zauważ, że używam use $ $ PWD_WIN aby podać pełną ścieżkę do pliku źródłowego do polecenia copy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-08 13:50:18
Utwórz plik copy_files.prf
w jednej ze ścieżek, których qmake używa do konfiguracji . Plik powinien wyglądać tak:
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}
Jak to działa
Pierwsza część definiuje dodatkowy kompilator , który będzie odczytywał nazwy plików wejściowych ze zmiennej COPY_FILES
. Następna część definiuje funkcję, której będzie używać do syntezy nazwy pliku wyjściowego odpowiadającej każdemu wejściu. Następnie definiujemy komendy użyte do wywołania tego "kompilatora", w zależności od tego jakiego rodzaju shell jesteśmy w.
Następnie definiujemy dodatkowy cel makefile copy_files.cookie
, co zależy od celu compiler_copy_files_make_all
. Ta ostatnia to nazwa celu, który qmake generuje dla dodatkowego kompilatora zdefiniowanego w pierwszym kroku. Oznacza to, że gdy obiekt docelowy copy_files.cookie
zostanie zbudowany, wywoła on dodatkowy kompilator do skopiowania plików.
Określamy polecenie, które ma być uruchomione przez ten cel, które będzie touch
plikami copy_files.cookie
i compiler_copy_files_make_all
. Dotykając tych plików, zapewniamy, że make
będzie nie próbuj ponownie kopiować plików, chyba że ich znaczniki czasu są nowsze niż dotknięte pliki. Na koniec dodajemy copy_files.cookie
do listy zależności celu make all
.
Jak go używać
W pliku .pro
dodaj copy_files
do zmiennej CONFIG
:
CONFIG += copy_files
Następnie dodaj pliki do zmiennej COPY_FILES
:
COPY_FILES += docs/*.txt
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-23 19:36:53
Jako dodatek do odpowiedzi Jake ' a i komentarza @ Phlucious można użyć funkcji qmake defineReplace
, która lepiej pasuje do tego przypadku użycia. Po użyciu podanego przykładu napotkałem problem, w którym qmake pominął dodaną akcję z linkiem do ostatniego postu. Może to być problem z eksportem zmiennej, choć zawartość wyglądała całkiem dobrze przez cały czas. Krótko mówiąc, Oto zmodyfikowany kod
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)
}
Ta ogólna funkcja kopiowania może być używana przez niektóre funkcje wygody, takie jak Ten
defineReplace(copyToBuilddir) {
return($$copyToDir($$1, $$OUT_PWD))
}
Drugi przyjmuje tylko jeden argument (jeden lub więcej plików) i zapewnia stałą ścieżkę. Prawie tak samo jak w referencjach.
Ale teraz zwróć uwagę na różnicę inwokacji
QMAKE_POST_LINK += $$copyToBuilddir(deploy.bat)
Jak widać, zwracane polecenie można dołączyć do QMAKE_PRE_LINK, aby uzyskać jeszcze większą elastyczność.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:00:32
Najpierw zdefiniuj dwie następujące funkcje do obsługi obu systemów 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)
}
Następnie możesz użyć poniższego kodu, aby wywołać zdefiniowane wcześniej funkcje, aby skopiować pliki do określonego folderu, a także utworzyć katalog w razie potrzeby. Jest to testowane pod Win32, testy Linuksa są mile widziane.
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)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-22 05:16:10
Najpierw zdefiniuj poniżej (który jest z XD
framework) gdzieś, jak w pliku functions.prf
:
# --------------------------------------
# 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(copyFile) {
#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)
}
I użyj go w swoim projekcie jak:
include($$PWD/functions.prf) #optional
copyFile($$PWD/myfile1.txt, $$DESTDIR/myfile1.txt)
copyFile($$PWD/README.txt, $$DESTDIR/README.txt)
copyFile($$PWD/LICENSE, $$DESTDIR/LICENSE)
copyDir($$PWD/redist, $$DESTDIR/redist) #copy "redist" folder to "$$DESTDIR"
Zauważ, że wszystkie pliki zostaną skopiowane przed wykonaniem operacji łącza (co może być przydatne).
xd_functions.prf
pełny skrypt
Ale jeśli potrzebujesz czegoś w rodzaju copyFileLater(source, destination)
, aby skopiować pliki tylko po zakończeniu kompilacji, rozważ użycie poniższego kodu (który pochodzi z XD
framework na licencji Apache 2.0
):
# --------------------------------------
# This file defines few useful functions
# --------------------------------------
xd_command_count = 0
#xd_prebuild(prefix, command)
defineTest(xd_prebuild) {
#generate target name with number
xd_command_count = $$num_add($$xd_command_count, 1)
name = $$1$$xd_command_count
#append command
eval( $${name}.commands += ( \$\$2 ) );
#the qmake generated "MakeFile" should contain "first"
# and we depend that on new command
!contains( first.depends, $$name ) {
!isEmpty(first.depends): first.depends += \\$$escape_expand(\\n)
first.depends += $$name
}
QMAKE_EXTRA_TARGETS *= first $$name
export(xd_command_count)
export($${name}.commands)
export(first.depends)
export(QMAKE_EXTRA_TARGETS)
#eval( warning(xd_push_command: $${name}.commands += \$\${$${name}.commands}) )
}
#xd_postbuild(command)
defineTest(xd_postbuild) {
!isEmpty(QMAKE_POST_LINK): QMAKE_POST_LINK = $$QMAKE_POST_LINK$$escape_expand(\\n\\t)
QMAKE_POST_LINK = $${QMAKE_POST_LINK}$$quote(-$$1)
export(QMAKE_POST_LINK)
}
#xd_escape(path)
# resolves path like built-in functions (i.e. counts input relative to $$PWD)
defineReplace(xd_escape) {
1 = $$absolute_path($$1)
#using "shell_path()" to correct path depending on platform
# escaping quotes and backslashes for file paths
1 = $$shell_path($$1)
return($$quote($$1))
}
#copyFile(source, destination)
# this will both copy and rename "source" to "destination", However like "copy_file()":
# if "destination" is path to existing directory or ends with slash (i.e. "/" or "\\"),
# will just copy to existing "destination" directory without any rename
#
# note: this is executed before build, but after qmake did exit
# so use "copy_file(...)" instead if the output file is required in qmake script
# like for example if "write_file(...)" is called on the output...
defineTest(copyFile) {
#note that "$(COPY_FILE)" is generated by qmake from "$$QMAKE_COPY_FILE"
xd_prebuild(xd_copyfile, $(COPY_FILE) $$xd_escape($$1) $$xd_escape($$2) || echo copyFile-failed)
}
#copyFileLater(source, destination = $(DESTDIR))
# note: this is executed after build is done, hence the name copy-later
defineTest(copyFileLater) {
destDir = $$2
isEmpty(destDir): destDir = $(DESTDIR)
#append copy command
xd_postbuild($(COPY_FILE) $$xd_escape($$1) $$xd_escape($$destDir) || echo copyFileLater-failed)
#!build_pass:warning(copyFile: $$1 to: $$destDir)
}
#copyDir(source, destination)
defineTest(copyDir) {
xd_prebuild(xd_copydir, $(COPY_DIR) $$xd_escape($$1) $$xd_escape($$2) || echo copyDir-failed)
}
#copyDirLater(source, destination = $(DESTDIR))
# note: this is executed after build is done, hence the name copy-later
defineTest(copyDirLater) {
destDir = $$2
isEmpty(destDir): destDir = $(DESTDIR)
#append copy command
xd_postbuild($(COPY_DIR) $$xd_escape($$1) $$xd_escape($$destDir) || echo copyDirLater-failed)
#!build_pass:warning(copyFile: $$1 to: $$destDir)
}
#makeDir(destination)
defineTest(makeDir) {
xd_prebuild(xd_makedir, $(MKDIR) $$xd_escape($$1) || echo makeDir-failed: \"$$1\")
}
defineTest(makeDirLater) {
xd_postbuild( $(MKDIR) $$xd_escape($$1) || echo makeDirLater-failed )
#!build_pass:warning(makeDirLater: $$1)
}
defineTest(deleteFile) {
xd_prebuild(xd_delfile, $(DEL_FILE) $$xd_escape($$1) || echo deleteFile-failed)
}
defineTest(deleteFileLater) {
xd_postbuild( $(DEL_FILE) $$xd_escape($$1) || echo deleteFileLater-failed )
#!build_pass:warning(deleteFileLater: $$1)
}
defineTest(deleteDir) {
xd_prebuild(xd_delfile, $(DEL_DIR) $$xd_escape($$1) || echo deleteDir-failed)
}
defineTest(deleteDirLater) {
xd_postbuild( $(DEL_DIR) $$xd_escape($$1) || echo deleteDirLater-failed )
#!build_pass:warning(deleteFileLater: $$1)
}
#qmakeLater(qmake-script-file-path-to-run)
# note that inside the script runned by this method
# $$OUT_PWD will be same as original $$OUT_PWD of qmakeLater(...) caller project
# since there is the "Makefile" that executes our custom qmake
defineTest(qmakeRun) {
xd_postbuild( $(QMAKE) $$xd_escape($$1) -r -spec \"$$shell_path($$QMAKESPEC)\" )
#!build_pass:warning(qmakeLater: $$1)
}
defineTest(qmakeLater) {
xd_postbuild( $(QMAKE) $$xd_escape($$1) -r -spec \"$$shell_path($$QMAKESPEC)\" )
#!build_pass:warning(qmakeLater: $$1)
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-28 04:10:23