Comment spécifier différents répertoires de sortie Debug / Release dans le fichier .pro QMake

106

J'ai un projet Qt et je voudrais sortir des fichiers de compilation en dehors de l'arborescence des sources.

J'ai actuellement la structure de répertoires suivante:

/
|_/build
|_/mylib
  |_/include
  |_/src
  |_/resources

En fonction de la configuration (debug / release), j'aimerai sortir les fichiers résultants dans le répertoire build sous les répertoires build / debug ou build / release.

Comment puis-je faire cela en utilisant un fichier .pro?

Etienne Savard
la source
La façon dont Qt traite les versions de débogage et de publication a changé en interne au fil du temps. Nous avons donc découvert que les commutateurs de travail précédents entre le débogage et la publication étaient interrompus dans les versions ultérieures. Voir ma solution qui fonctionne sur toutes les plateformes et sur toutes les versions de Qt jusqu'à présent. stackoverflow.com/questions/32046181/…
adlag
2
Comme il s'agit d'une vieille question, il convient de souligner qu'il existe de meilleures réponses avec beaucoup moins de votes.
Wardw

Réponses:

4

La réponse courte est: vous ne le faites pas .

Vous devez exécuter qmakesuivi de makedans le répertoire de construction dans lequel vous voulez construire. Donc, exécutez-le une fois dans un debugrépertoire, une fois dans un releaserépertoire.

C'est ainsi que quiconque construit votre projet s'attend à ce qu'il fonctionne, et c'est ainsi que Qt lui-même est configuré pour construire, c'est aussi ainsi que Qt Creator s'attend à ce que votre .profichier se comporte: il démarre simplement qmake, puis makedans le dossier de construction pour la configuration choisie par votre cible.

Si vous souhaitez créer ces dossiers et y effectuer les deux (ou plus) builds, vous aurez besoin d'un makefile de niveau supérieur, éventuellement créé à partir d'un fichier de projet de niveau supérieur via qmake.

Il n'est pas rare d'avoir plus de deux configurations de build, donc vous vous engagez inutilement à ne faire la différence qu'entre une build et une release; vous pourriez avoir des builds avec différents niveaux d'optimisation, etc. La dichotomie débogage / version est préférable de laisser reposer en paix.

Réintégrer Monica
la source
152

Pour mon projet Qt, j'utilise ce schéma dans le fichier * .pro:

HEADERS += src/dialogs.h
SOURCES += src/main.cpp \
           src/dialogs.cpp

Release:DESTDIR = release
Release:OBJECTS_DIR = release/.obj
Release:MOC_DIR = release/.moc
Release:RCC_DIR = release/.rcc
Release:UI_DIR = release/.ui

Debug:DESTDIR = debug
Debug:OBJECTS_DIR = debug/.obj
Debug:MOC_DIR = debug/.moc
Debug:RCC_DIR = debug/.rcc
Debug:UI_DIR = debug/.ui

C'est simple mais sympa! :)

mosg
la source
18
Juste ce dont j'avais besoin! Et une note: Pour rendre les choses encore plus facile à passer autour, définir uniquement vos DESTDIRs sous condition, et ensuite utiliser cette valeur dans tous vos autres chemins: OBJECTS_DIR = $${DESTDIR}/.obj. À votre santé!
Xavier Holt
4
Ça vous dérange d'expliquer comment cela est utilisé / ce que cela fait? Il semble n'avoir aucun effet lorsque je le mets en œuvre. edit: si je change Debug en debug (minuscule) cela fonctionne. Je soupçonne que c'est une question de sensibilité à la casse Windows vs Unix.
notlesh
9
Je l'ai voté car il fonctionne sous Windows. Sous Linux (Ubuntu 15.04, Qt 5.5.0), j'ai dû passer Debugà debuget Releaseà release.
Jepessen
Wth? Tant de choses à multiplier par plateforme? @Jepessen ??
Nils
2
Cela ne fonctionne que lorsque vous avez uniquement la version ou le débogage dans CONFIG. Si les deux sont en configuration, ce dernier sera utilisé.
weeska
52

Pour changer le répertoire de la dll / exe cible, utilisez ceci dans votre fichier pro:

CONFIG(debug, debug|release) {
    DESTDIR = build/debug
} else {
    DESTDIR = build/release
}

Vous voudrez peut-être aussi changer de répertoire pour d'autres cibles de construction comme les fichiers objet et les fichiers moc (vérifiez la référence de la variable qmake pour plus de détails ou la référence de la fonction qmake CONFIG () ).

chalup
la source
5
Mais j'ai trouvé beaucoup plus agréable d'inclure $$ OUT_PWD dans ceci, donc DESTDIR = $$ OUT_PWD / debug
Ivo
1
@Ivo: Ah! Je vous remercie! J'ai cherché partout quelle variable contenait ce chemin! : D
Cameron
1
Après cela, vous pouvez ajouter des lignes comme: OBJECTS_DIR = $$DESTDIR/.obj MOC_DIR = $$DESTDIR/.moc RCC_DIR = $$DESTDIR/.qrc UI_DIR = $$DESTDIR/.ui CONFIG()s'avère résoudre certains problèmes d'utilisation release:etdebug:
Carson Ip
Celui-ci fonctionnait mieux que la réponse choisie. Celui sélectionné fonctionne, mais si le débogage et la version sont configurés, le deuxième bloc de paramètres reste.
Paulo Carvalho
42

J'ai une approche plus compacte:

release: DESTDIR = build/release
debug:   DESTDIR = build/debug

OBJECTS_DIR = $$DESTDIR/.obj
MOC_DIR = $$DESTDIR/.moc
RCC_DIR = $$DESTDIR/.qrc
UI_DIR = $$DESTDIR/.ui
Bonjour W
la source
2
Votre réponse est la manière la plus récente de placer la sortie de compilation du compilateur dans un répertoire séparé.
SIFE
1
avez-vous essayé cela récemment pour le débogage et la publication? ma sortie de build semble toujours se retrouver dans le dossier release, quelle que soit la configuration; Le comportement de qmake / Qt Creator a peut-être changé depuis que vous avez publié cette réponse ...
ssc
1
Essayez d'ajouter "CONFIG - = debug" aux arguments supplémentaires de qmake en mode Release
Bonjour W
17

La bonne façon de procéder est la suivante (merci l'équipe de support QT):

CONFIG(debug, debug|release) {
    DESTDIR = build/debug
}
CONFIG(release, debug|release) {
    DESTDIR = build/release
}

OBJECTS_DIR = $$DESTDIR/.obj
MOC_DIR = $$DESTDIR/.moc
RCC_DIR = $$DESTDIR/.qrc
UI_DIR = $$DESTDIR/.u

Plus d'informations ici: https://wiki.qt.io/Qt_project_org_faq#What_does_the_syntax_CONFIG.28debug.2Cdebug.7Crelease.29_mean_.3F_What_does_the_1st_argument_specify_and_similarly_nd_what_is_the_2

ABCplus
la source
13

J'utilise la même méthode suggérée par chalup,

ParentDirectory = <your directory>

RCC_DIR = "$$ParentDirectory\Build\RCCFiles"
UI_DIR = "$$ParentDirectory\Build\UICFiles"
MOC_DIR = "$$ParentDirectory\Build\MOCFiles"
OBJECTS_DIR = "$$ParentDirectory\Build\ObjFiles"

CONFIG(debug, debug|release) { 
    DESTDIR = "$$ParentDirectory\debug"
}
CONFIG(release, debug|release) { 
    DESTDIR = "$$ParentDirectory\release"
}
Sulla
la source
12

Ancienne question, mais qui mérite toujours une réponse à jour. Aujourd'hui, il est courant de faire ce que Qt Creator fait lorsque des builds shadow sont utilisés (ils sont activés par défaut lors de l'ouverture d'un nouveau projet).

Pour chaque cible et type de build différents, le droit qmakeest exécuté avec les bons arguments dans un répertoire de build différent. Ensuite, cela est simplement construit avec simple make.

Ainsi, la structure de répertoires imaginaire pourrait ressembler à ceci.

/
|_/build-mylib-qt5-mingw32-debug
|_/build-mylib-qt5-mingw32-release
|_/build-mylib-qt4-msvc2010-debug
|_/build-mylib-qt4-msvc2010-release
|_/build-mylib-qt5-arm-debug
|_/build-mylib-qt5-arm-release
|_/mylib
  |_/include
  |_/src
  |_/resources

Et la chose importante est, a qmakeest exécuté dans le répertoire de construction:

cd build-mylib-XXXX
/path/to/right/qmake ../mylib/mylib.pro CONFIG+=buildtype ...

Ensuite, il génère des makefiles dans le répertoire de construction, puis make des fichiers génère également des fichiers sous celui-ci. Il n'y a aucun risque que différentes versions se mélangent, tant que qmake n'est jamais exécuté dans le répertoire source (si c'est le cas, mieux vaut bien le nettoyer!).

Et une fois fait comme ça, le .profichier de la réponse actuellement acceptée est encore plus simple:

HEADERS += src/dialogs.h
SOURCES += src/main.cpp \
           src/dialogs.cpp
Hyde
la source
Fonctionne bien pour un seul projet, mais qu'en est-il si vous avez un projet et une bibliothèque? Ensuite, vous avez besoin d'un moyen dépendant du type de construction pour inclure les afaics de la bibliothèque.
Adversus
@Adversus Je ne suis pas sûr de ce que vous voulez dire exactement, mais peut-être que la variable Qmake $(OUT_PWD)est une solution?
hyde
Lorsque j'applique ma question à votre exemple, cela devient: quel est le moyen le plus propre pour une application de récupérer mylib? J'aimerais qu'il y ait une façon "gracieuse" de faire cela, je ne vois pas d'autre moyen que d'utiliser les techniques des autres réponses: utilisez le type de construction et la configuration pour remplir LIBSde manière intelligente, annulant l'avantage de la construction de l'ombre.
Adversus
@Adversus Si mylib est un projet de sous-répertoire sous le même projet de niveau supérieur, j'ajouterais généralement un fichier mylib.pri, et j'y mettrais tout ce dont les autres projets de sous-répertoire ont besoin, en utilisant les variables Qmake pour toujours obtenir les chemins corrects, même s'il s'agit d'une construction shadow. Ensuite, les autres fichiers .pro de sous-répertoire auraient simplementinclude(../mylib/mylib.pri)
hyde
merci, c'est un peu ce que je fais maintenant, cela aurait été bien d'avoir une solution où cela est pris en charge automatiquement, comme lorsque vous avez un projet avec des sous-projets dans cmake et que vous pouvez ensuite facilement en faire différents. source construit de l'arbre entier.
Adversus
3

Il est également utile d'avoir un nom légèrement différent pour l'exécutable de sortie. Vous ne pouvez pas utiliser quelque chose comme:

release: Target = ProgramName
debug: Target = ProgramName_d

Pourquoi cela ne fonctionne pas n'est pas clair, mais ce n'est pas le cas. Mais:

CONFIG(debug, debug|release) {
    TARGET = ProgramName
} else {
    TARGET = ProgramName_d
}

Cela fonctionne tant que la CONFIG +=ligne la précède.

Steve Besch
la source
1

La nouvelle version de Qt Creator a également une option de construction «profil» entre le débogage et la publication. Voici comment je détecte cela:

CONFIG(debug, debug|release) {  DEFINES += DEBUG_MODE }
else:CONFIG(force_debug_info) { DEFINES += PROFILE_MODE }
else {                          DEFINES += RELEASE_MODE }
BuvinJ
la source
0

1. Trouvez Debug / Release dans CONFIG

Obtenez le courant (debug | release).

specified_configs=$$find(CONFIG, "\b(debug|release)\b")
build_subdir=$$last(specified_configs)

(Peut être multiple, donc ne conserver que le dernier spécifié dans la construction):

2. Réglez DESTDIR

Utilisez-le a le nom du sous-répertoire de construction

DESTDIR = $$PWD/build/$$build_subdir
automorphe
la source
0

Ceci est mon Makefile pour différents répertoires de sortie de débogage / version. Ce Makefile a été testé avec succès sur Ubuntu Linux. Il devrait fonctionner de manière transparente sous Windows à condition que Mingw-w64 soit correctement installé.

ifeq ($(OS),Windows_NT)
    ObjExt=obj
    mkdir_CMD=mkdir
    rm_CMD=rmdir /S /Q
else
    ObjExt=o
    mkdir_CMD=mkdir -p
    rm_CMD=rm -rf
endif

CC     =gcc
CFLAGS =-Wall -ansi
LD     =gcc

OutRootDir=.
DebugDir  =Debug
ReleaseDir=Release


INSTDIR =./bin
INCLUDE =.

SrcFiles=$(wildcard *.c)
EXEC_main=myapp

OBJ_C_Debug   =$(patsubst %.c,  $(OutRootDir)/$(DebugDir)/%.$(ObjExt),$(SrcFiles))
OBJ_C_Release =$(patsubst %.c,  $(OutRootDir)/$(ReleaseDir)/%.$(ObjExt),$(SrcFiles))

.PHONY: Release Debug cleanDebug cleanRelease clean

# Target specific variables
release: CFLAGS += -O -DNDEBUG
debug:   CFLAGS += -g

################################################
#Callable Targets
release: $(OutRootDir)/$(ReleaseDir)/$(EXEC_main)
debug:   $(OutRootDir)/$(DebugDir)/$(EXEC_main)

cleanDebug:
    -$(rm_CMD) "$(OutRootDir)/$(DebugDir)"
    @echo cleanDebug done

cleanRelease:
    -$(rm_CMD) "$(OutRootDir)/$(ReleaseDir)"
    @echo cleanRelease done

clean: cleanDebug cleanRelease
################################################

# Pattern Rules
# Multiple targets cannot be used with pattern rules [https://www.gnu.org/software/make/manual/html_node/Multiple-Targets.html]
$(OutRootDir)/$(ReleaseDir)/%.$(ObjExt): %.c | $(OutRootDir)/$(ReleaseDir)
    $(CC) -I$(INCLUDE) $(CFLAGS) -c $< -o"$@"

$(OutRootDir)/$(DebugDir)/%.$(ObjExt):   %.c | $(OutRootDir)/$(DebugDir)
    $(CC) -I$(INCLUDE) $(CFLAGS) -c $< -o"$@"

# Create output directory
$(OutRootDir)/$(ReleaseDir) $(OutRootDir)/$(DebugDir) $(INSTDIR):
    -$(mkdir_CMD) $@

# Create the executable
# Multiple targets [https://www.gnu.org/software/make/manual/html_node/Multiple-Targets.html]
$(OutRootDir)/$(ReleaseDir)/$(EXEC_main): $(OBJ_C_Release)
$(OutRootDir)/$(DebugDir)/$(EXEC_main):   $(OBJ_C_Debug)
$(OutRootDir)/$(ReleaseDir)/$(EXEC_main) $(OutRootDir)/$(DebugDir)/$(EXEC_main):
    $(LD) $^ -o$@
Ahmed Rashed
la source