web-dev-qa-db-fra.com

Copiez un fichier dans le répertoire de construction après avoir compilé le projet avec Qt

J'ai vu plusieurs suggestions, mais rien n'a vraiment fonctionné pour moi comme je le souhaite. J'ai juste besoin de copier un fichier dans le répertoire de destination souhaité.

Dites, par exemple de cette réponse :

install_it.path = %{buildDir}
install_it.files += %{sourceDir}/settings.ini

INSTALLS += install_it

Variables %{buildDir} et %{sourceDir} doit être défini pour que cela fonctionne. Ok, il n'y a aucun problème avec %{sourceDir}: c'est juste .. Mais comment puis-je obtenir %{buildDir}?

EDIT1

Dis, j'ai un projet my_project ici:

/path/to/my_project

Ainsi, le chemin de génération de la version est le suivant: /path/to/my_project-build-Desktop-release,

le chemin de build de débogage est le suivant: /path/to/my_project-build-Desktop-debug

J'ai des fichiers à copier dans le répertoire de destination ici: /path/to/my_project/copy_to_install_dir

Donc, je veux tous les fichiers de /path/to/my_project/copy_to_install_dir à copier dans /path/to/my_project-build-Desktop-release quand je libère la build. Et, de la même manière pour la version de débogage.

Je ne trouve pas de variable contenant le chemin de destination complet, c'est-à-dire /path/to/my_project-build-Desktop-release pour la version de débogage.

Juste au cas où: j'utilise Windows, mais de toute façon je recherche une solution multiplateforme.

EDIT2

Solution exacte, pour les futurs lecteurs:

install_it.path = $$OUT_PWD
install_it.files = copy_to_install_dir/*

INSTALLS += \
    install_it
29
Dmitry Frank

C'est ce que nous utilisons dans QtSerialPort:

target_headers.files  = $$PUBLIC_HEADERS
target_headers.path   = $$[QT_INSTALL_HEADERS]/QtSerialPort
INSTALLS              += target_headers

mkspecs_features.files    = $$QTSERIALPORT_PROJECT_ROOT/src/serialport/qt4support/serialport.prf
mkspecs_features.path     = $$[QT_INSTALL_DATA]/mkspecs/features
INSTALLS                  += mkspecs_features

Fondamentalement, vous définissez les fichiers et le chemin d'accès pour la cible, puis ajoutez cela dans la variable INSTALLS. Ce dont vous avez encore besoin est le $$OUT_PWD variable que nous utilisons également largement dans QtSerialPort. Cela vous fournira la racine du répertoire de construction.

C'est l'une de ces fonctionnalités qmake non documentées, mais elle est très utile.

En outre, pour le répertoire source en général, vous ne devez pas supposer "." et ainsi de suite car cela peut être différent lorsque vous exécutez une application wrapper dans laquelle le "." va pointer vers cela et non pas ce que vous attendez: la racine du projet source qmake. Dans ces cas, il est plus sûr d'utiliser la variable PWD qui pointe vers la source par opposition OUT_PWD qui pointe vers le dossier de construction.

Juste pour donner un exemple approximatif de la différence entre ces deux variables avec un scénario réel, vous pouvez trouver ici ce que nous faisons dans QtSerialPort:

system("echo QTSERIALPORT_PROJECT_ROOT = $$PWD >> $$OUT_PWD/.qmake.cache")
system("echo QTSERIALPORT_BUILD_ROOT = $$OUT_PWD >> $$OUT_PWD/.qmake.cache")

où le premier est la racine du projet source et le second le répertoire de construction. Ils peuvent être identiques, mais dans de nombreux cas, ils ne le sont pas, par exemple lors de la construction via QtCreator juste pour l'un d'entre eux.

13
lpapp

La réponse sélectionnée est correcte mais elle nécessite d'appeler make install, ce qui à mon avis est ennuyeux ou sujet aux erreurs. À la place, pour copier des fichiers dans le répertoire de construction, utilisez:

copydata.commands = $(COPY_DIR) $$PWD/required_files $$OUT_PWD
first.depends = $(first) copydata
export(first.depends)
export(copydata.commands)
QMAKE_EXTRA_TARGETS += first copydata

required_files doit être remplacé par votre chemin correct. $$PWD est le chemin du courant .pro fichier, vous n'en aurez peut-être pas besoin.

Remarque : J'ai trouvé cette solution ici . Je recommande de lire l'intégralité de l'article car il explique comment cela fonctionne.

31
Paglian

Ayant eu le plaisir de perdre quelques heures avec cela, j'ai pensé partager mes conclusions sur la question. Ceci dans une variante modifiée de la méthode de Paglian ici . Puisque j'utilise Windows (sans mingw), cette méthode ne fonctionne pas. Voici donc la variante modifiée:

# using Shell_path() to correct path depending on platform
# escaping quotes and backslashes for file paths
copydata.commands = $(COPY_FILE) \"$$Shell_path($$PWD\\archive.png)\" \"$$Shell_path($$OUT_PWD)\"
first.depends = $(first) copydata
export(first.depends)
export(copydata.commands)
QMAKE_EXTRA_TARGETS += first copydata

Étant donné que cela le rend multiplateforme, vous pouvez bien sûr également utiliser cette méthode sous Linux, MacOS ou autre. Notez que je copie un seul fichier, donc au lieu de $(COPY_DIR) j'utilise $(COPY_FILE). Adaptez au besoin.


Si vous voulez que le ou les fichiers soient copiés dans le chemin exact de l'endroit où le binaire se termine (car le binaire se retrouvera dans un sous-dossier de $$ OUT_PWD ( debug ou release , au moins lors de la construction avec Qt Creator avec la configuration MSVC 14/cdb.exe/Code :: Blocks Makefiles) vous avez besoin de ceci:

# adapted from https://stackoverflow.com/a/2581068
CONFIG(debug, debug|release) {
    VARIANT = debug
} else {
    VARIANT = release
}

Attention, même si le binaire se retrouve dans un sous-dossier, QtCreator exécute le binaire à partir de $$OUT_PWD, Il s'attend donc à trouver des ressources de fichier dans $$OUT_PWD, Et PAS le débogage sous-répertoire. Cela signifie par exemple que vous ne pouvez pas faire QIcon("archive.png") et vous attendre à ce qu'il le trouve en plus de l'exécutable.

Il est bien sûr facile d'y remédier en faisant:

QDir exeDir(QCoreApplication::applicationDirPath());
QIcon qIcon(exeDir.filePath("archive.png"));

SI vous décidez que c'est ce que vous voulez, vous devez évidemment modifier le dernier argument de $$(COPY_FILE) (dans .pro) comme ceci: \"$$Shell_path($$OUT_PWD)\\$$VARIANT\"


Une autre chose à noter est que (dans mon cas de toute façon) Qt Creator (4.0.1) ne construit pas toujours le fichier .pro, car il ne détecte aucun changement dans la configuration, donc pour que les changements ci-dessus soient reflétés dans le Makefile (et donc exécuté lorsque vous générez votre projet) vous devez réellement construire le .pro manuellement en exécutant Build->run qmake à partir du menu de l'application. Pour vous assurer que tout se passe bien, regardez comme la sortie de compilation en appuyant sur Alt + 4 (sous Windows de toute façon).

14
PKSWE

Vous pouvez utiliser les variables qmake DESTDIR et PWD ou OUT_PWD: http://qt-project.org/doc/qt-5.1/qmake/qmake-variable-reference.html#destdir

3
gbdivers

Peut-être que le code QMake suivant aide comme point de départ. Il copie le binaire récemment construit dans un autre répertoire "TARGET_DEST":

TARGET_SRC  = $${_PRO_FILE_PWD_}
TARGET_DEST = $${PWD}/src

CONFIG(debug, debug|release) {
    TARGET_SRC = $${TARGET_SRC}/debug
} else {
    TARGET_SRC = $${TARGET_SRC}/release
}

TARGET_SRC   = $${TARGET_SRC}/$${TARGET}
TARGET_DEST  = $${TARGET_DEST}/$${TARGET}

linux-g++{
    if( equals(TEMPLATE, app) || equals(TEMPLATE, vcapp) ){
        # nothing to do here
    }
    if( equals(TEMPLATE, lib) || equals(TEMPLATE, vclib) ){
        TARGET_SRC   = $${TARGET_SRC}.so
        TARGET_DEST  = $${TARGET_DEST}.so
    }
    QMAKE_POST_LINK += $$quote(cp $${TARGET_SRC} $${TARGET_DEST}$$escape_expand(\n\t))
}

win32 {
    if( equals(TEMPLATE, app) || equals(TEMPLATE, vcapp) ){
        TARGET_SRC   = $${TARGET_SRC}.exe
        TARGET_DEST  = $${TARGET_DEST}.exe
    }
    if( equals(TEMPLATE, lib) || equals(TEMPLATE, vclib) ){
        TARGET_SRC   = $${TARGET_SRC}.dll
        TARGET_DEST  = $${TARGET_DEST}.dll
    }
    TARGET_SRC  ~= s,/,\\,g # fix slashes 
    TARGET_DEST ~= s,/,\\,g # fix slashes
    QMAKE_POST_LINK +=$$quote(cmd /c copy /y $${TARGET_SRC} $${TARGET_DEST}$$escape_expand(\n\t))
}

message("[INFO] Will copy $${TARGET_SRC} to $${TARGET_DEST}")
3