Come specificare diverse directory di output di debug / rilascio nel file QMake .pro


106

Ho un progetto Qt e vorrei produrre file di compilazione fuori dall'albero dei sorgenti.

Al momento ho la seguente struttura di directory:

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

A seconda della configurazione (debug / release), mi piacerebbe visualizzare i file risultanti all'interno della directory build sotto le directory build / debug o build / release.

Come posso farlo usando un file .pro?


Il modo in cui Qt tratta le build di debug e di rilascio è cambiato internamente nel tempo. Così abbiamo scoperto che il lavoro precedente passa dal debug al rilascio e non funziona nelle versioni successive. Guarda la mia soluzione che funziona su tutte le piattaforme e su tutte le versioni di Qt fino ad ora. stackoverflow.com/questions/32046181/...
adlag

2
Poiché questa è una vecchia domanda, vale la pena sottolineare che ci sono risposte migliori con molti meno voti.
wardw

Risposte:


5

La risposta breve è: non lo fai .

Dovresti eseguire qmakeseguito da makein qualsiasi directory di build in cui desideri compilare. Quindi, eseguilo una volta in una debugdirectory, una volta in una releasedirectory.

È così che chiunque costruisce il tuo progetto si aspetterebbe che funzioni, ed è così che Qt stesso è impostato per costruire, è anche così che Qt Creator si aspetta che il tuo .profile si comporti: si avvia semplicemente qmakee poi makenella cartella di build per la configurazione scelta dal tuo obiettivo.

Se desideri creare queste cartelle ed eseguire le due (o più) build in esse, avrai bisogno di un makefile di primo livello, possibilmente creato da un file di progetto di primo livello tramite qmake.

Non è raro avere più di due configurazioni di build, quindi ti impegni inutilmente a distinguere solo tra build e release; potresti avere build con diversi livelli di ottimizzazione, ecc. La dicotomia debug / rilascio è meglio lasciarla riposare in pace.


151

Per il mio progetto Qt, utilizzo questo schema nel file * .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

È semplice, ma carino! :)


18
Proprio quello di cui avevo bisogno! E una nota: Per rendere le cose ancora più facile per passare in giro, a definire soltanto i vostri DESTDIRs condizionale, e quindi utilizzare tale valore in tutti gli altri percorsi: OBJECTS_DIR = $${DESTDIR}/.obj. Saluti!
Xavier Holt

4
Ti dispiace spiegare come viene utilizzato / cosa fa? Sembra che non abbia alcun effetto quando lo implemento. modifica: se cambio Debug in debug (minuscolo) funziona. Sospetto che sia una questione di distinzione tra maiuscole e minuscole tra Windows e Unix.
notlesh

9
L'ho votato perché funziona su Windows. Su Linux (Ubuntu 15.04, Qt 5.5.0) ho dovuto passare Debuga debuge Releasea release.
Jepessen

Wth? Così tanto da cross platform? @Jepessen ??
Nils

2
Funziona solo quando hai solo il rilascio o il debug in CONFIG. Se entrambi sono in configurazione, verrà utilizzata l'ultima.
weeska

52

Per cambiare la directory per target dll / exe, usa questo nel tuo file pro:

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

Potresti anche voler cambiare directory per altri obiettivi di compilazione come file oggetto e file moc (controlla il riferimento alla variabile qmake per i dettagli o il riferimento alla funzione qmake CONFIG () ).


5
Ma ho trovato molto più carino includere $$ OUT_PWD in questo, quindi DESTDIR = $$ OUT_PWD / debug
Ivo

1
@Ivo: Ah! Grazie! Ho cercato ovunque quale variabile conteneva quel percorso! : D
Cameron

1
Dopo questo, puoi aggiungere linee come: OBJECTS_DIR = $$DESTDIR/.obj MOC_DIR = $$DESTDIR/.moc RCC_DIR = $$DESTDIR/.qrc UI_DIR = $$DESTDIR/.ui CONFIG()risulta per risolvere alcuni problemi di utilizzo release:edebug:
Carson Ip

Questo ha funzionato meglio della risposta selezionata. Quello selezionato funziona, ma se sono configurati sia il debug che il rilascio, il secondo blocco di impostazioni rimane.
Paulo Carvalho

42

Ho un approccio più compatto:

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

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

2
La tua risposta è il modo più recente per mettere l'output di compilazione del compilatore in una directory separata.
SIFE

1
l'hai provato di recente sia per il debug che per il rilascio? il mio output di build sembra sempre finire nella cartella di rilascio, indipendentemente dalla configurazione; Il comportamento di qmake / Qt Creator potrebbe essere cambiato da quando hai pubblicato questa risposta ...
ssc

1
Prova ad aggiungere "CONFIG - = debug" agli argomenti aggiuntivi di qmake nella modalità di rilascio
Ciao W

17

Il modo corretto per farlo è il seguente (grazie al team di supporto 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

Maggiori informazioni qui: 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_what_is_the_2nd_.3F


13

Uso lo stesso metodo suggerito da 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"
}

12

Vecchia domanda, ma merita comunque una risposta aggiornata. Oggi è comune fare ciò che fa Qt Creator quando vengono utilizzate le build shadow (sono abilitate per impostazione predefinita quando si apre un nuovo progetto).

Per ogni diverso target e tipo di build, il right qmakeviene eseguito con gli argomenti right in una diversa directory di build. Quindi è solo costruito con semplicità make.

Quindi, la struttura della directory immaginaria potrebbe assomigliare a questa.

/
|_/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

E la cosa importante è che a qmakeviene eseguito nella directory build:

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

Quindi genera i makefile nella directory di build e quindi makegenererà anche i file sotto di esso. Non c'è rischio che versioni differenti vengano confuse, a patto che qmake non venga mai eseguito nella directory dei sorgenti (se lo è, è meglio pulirlo bene!).

E una volta fatto in questo modo, il .profile dalla risposta attualmente accettata è ancora più semplice:

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

Funziona bene per un singolo progetto, ma se hai un progetto e una libreria? Quindi è necessario un modo dipendente dal tipo di build per includere l'afaics della libreria.
Adversus

@Adversus Non sono sicuro di cosa intendi esattamente, ma forse la variabile Qmake $(OUT_PWD)è la soluzione?
hyde

Quando applico la mia domanda al tuo esempio, diventa: qual è il modo più pulito per raccogliere un'applicazione mylib? Mi piacerebbe se ci fosse un modo "aggraziato" per farlo, non vedo altro che usare le tecniche delle altre risposte: usa il tipo di build e la configurazione per riempire LIBSin modo intelligente, annullando il vantaggio della build shadow.
Adversus

@Adversus Se mylib è un progetto subdir sotto lo stesso progetto di primo livello, di solito aggiungerei un file mylib.pri e mettere lì tutto ciò di cui gli altri progetti subdir hanno bisogno, usando le variabili Qmake per ottenere sempre i percorsi corretti, anche se è shadow build. Quindi altri file subdir .pro avrebbero semplicementeinclude(../mylib/mylib.pri)
hyde

grazie, è un po 'quello che sto facendo ora, sarebbe stato bello avere una soluzione in cui questo fosse gestito automaticamente, come quando hai un progetto con sottoprogetti in cmake e puoi facilmente creare diversi out-of- build di origine dell'intero albero.
Adversus

3

È anche utile avere un nome leggermente diverso per l'eseguibile di output. Non puoi usare qualcosa come:

release: Target = ProgramName
debug: Target = ProgramName_d

Perché non funziona non è chiaro, ma non lo è. Ma:

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

Questo funziona finché la CONFIG +=linea lo precede.


1

La nuova versione di Qt Creator ha anche un'opzione di creazione del "profilo" tra debug e rilascio. Ecco come lo rilevo:

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

0

1. Trova Debug / Release in CONFIG

Ottieni l'attuale (debug | release).

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

(Può essere multiplo, quindi mantieni solo l'ultimo specificato nella build):

2. Impostare DESTDIR

Usalo ha il nome della sottodirectory build

DESTDIR = $$PWD/build/$$build_subdir

0

Questo è il mio Makefile per diverse directory di output di debug / rilascio. Questo Makefile è stato testato con successo su Ubuntu Linux. Dovrebbe funzionare senza problemi su Windows a condizione che Mingw-w64 sia installato correttamente.

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$@
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.