Cómo especificar diferentes directorios de salida de depuración / liberación en el archivo .pro de QMake


106

Tengo un proyecto Qt y me gustaría generar archivos de compilación fuera del árbol de fuentes.

Actualmente tengo la siguiente estructura de directorio:

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

Dependiendo de la configuración (depuración / liberación), me gustaría generar los archivos resultantes dentro del directorio de compilación en los directorios de compilación / depuración o compilación / liberación.

¿Cómo puedo hacer eso usando un archivo .pro?


La forma en que Qt trata las compilaciones de depuración y publicación cambió internamente con el tiempo. Así que descubrimos que los cambios de trabajo anteriores entre depuración y lanzamiento se rompían en versiones posteriores. Vea mi solución que funciona en todas las plataformas y en todas las versiones de Qt hasta ahora. stackoverflow.com/questions/32046181/…
adlag

2
Dado que esta es una pregunta antigua, vale la pena señalar que hay mejores respuestas con muchos menos votos.
Wardw

Respuestas:


5

La respuesta corta es: no es así .

Debe ejecutar qmakeseguido de makeen cualquier directorio de compilación en el que desee compilar. Por lo tanto, ejecútelo una vez en un debugdirectorio, una vez en un releasedirectorio.

Así es como cualquiera que construya su proyecto esperaría que funcione, y así es como Qt está configurado para compilar, así es como Qt Creator espera .proque se comporte su archivo: simplemente comienza qmakey luego makeen la carpeta de compilación para la configuración elegida por su objetivo.

Si desea crear estas carpetas y realizar las dos (o más) compilaciones en ellas, necesitará un archivo MAKE de nivel superior, posiblemente creado a partir de un archivo de proyecto de nivel superior a través de qmake.

No es raro tener más de dos configuraciones de compilación, por lo que se está comprometiendo innecesariamente a diferenciar únicamente entre una compilación y una versión; puede tener compilaciones con diferentes niveles de optimización, etc. Es mejor dejar en paz la dicotomía depuración / liberación.


151

Para mi proyecto Qt, utilizo este esquema en el archivo * .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

¡Es simple, pero agradable! :)


18
¡Justo lo que necesitaba! Y una nota: Para hacer las cosas aún más fáciles de cambiar nada más, sólo definen sus DESTDIRs condicionalmente, y luego utilizar ese valor en todos los otros caminos: OBJECTS_DIR = $${DESTDIR}/.obj. ¡Salud!
Xavier Holt

4
¿Te importaría explicar cómo se usa esto / qué hace? Parece no tener ningún efecto cuando lo implemento. editar: si cambio Depurar a depurar (minúsculas), funciona. Sospecho que esto es una cuestión de sensibilidad a mayúsculas y minúsculas de Windows vs Unix.
notlesh

9
Lo voté porque funciona en Windows. En Linux (Ubuntu 15.04, Qt 5.5.0) que tenía que cambiar Debuga debugy Releasea release.
Jepessen

¿Qué? ¿Tanto para multiplataforma? @Jepessen ??
Nils

2
Esto solo funciona cuando solo tiene versión o depuración en CONFIG. Si ambos están en configuración, se usará el último.
weeska

52

Para cambiar el directorio de destino dll / exe, use esto en su archivo profesional:

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

Es posible que también desee cambiar directorios para otros destinos de compilación como archivos objeto y archivos moc (consulte la referencia de la variable qmake para obtener más detalles o la referencia de la función qmake CONFIG () ).


5
Pero me pareció mucho mejor incluir $$ OUT_PWD en esto, así que DESTDIR = $$ OUT_PWD / debug
Ivo

1
@Ivo: ¡Ah! ¡Gracias! ¡He estado buscando en todas partes qué variable contenía esa ruta! : D
Cameron

1
Después de esto, puede agregar líneas como: OBJECTS_DIR = $$DESTDIR/.obj MOC_DIR = $$DESTDIR/.moc RCC_DIR = $$DESTDIR/.qrc UI_DIR = $$DESTDIR/.ui CONFIG()resulta para resolver algunos problemas de uso release:ydebug:
Carson Ip

Este funcionó mejor que la respuesta seleccionada. El seleccionado funciona, pero si se configuran tanto la depuración como la liberación, el segundo bloque de configuraciones permanece.
Paulo Carvalho

42

Tengo un enfoque más compacto:

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
Su respuesta es la forma más reciente de poner la salida de la compilación del compilador en un directorio separado.
SIFE

1
¿Has probado esto recientemente para depurar y liberar? la salida de mi compilación siempre parece terminar en la carpeta de lanzamiento, sin importar la configuración; Sin embargo, el comportamiento de qmake / Qt Creator podría haber cambiado desde que publicó esta respuesta ...
ssc

1
Intente agregar "CONFIG - = debug" a los argumentos adicionales de qmake en el modo Release
Hola W

17

La forma correcta de hacerlo es la siguiente (gracias al equipo de soporte de 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

Más información aquí: 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_whatnd_is_the_


13

Utilizo el mismo método sugerido por 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

Pregunta antigua, pero aún así vale la pena una respuesta actualizada. Hoy en día es común hacer lo que hace Qt Creator cuando se utilizan compilaciones de sombra (están habilitadas de forma predeterminada al abrir un nuevo proyecto).

Para cada destino y tipo de compilación diferente, el derecho qmakese ejecuta con los argumentos correctos en un directorio de compilación diferente. Entonces eso solo se construye con simple make.

Entonces, la estructura de directorio imaginaria podría verse así.

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

Y lo importante es que qmakese ejecuta a en el directorio de compilación:

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

Luego genera archivos MAKE en el directorio de compilación, y luego make genera archivos también generará archivos debajo de él. No hay riesgo de que se mezclen diferentes versiones, siempre y cuando qmake nunca se ejecute en el directorio de origen (si es así, ¡mejor límpielo bien!).

Y cuando se hace así, el .proarchivo de la respuesta actualmente aceptada es aún más simple:

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

Funciona bien para un solo proyecto, pero ¿qué pasa si tienes un proyecto y una biblioteca? Entonces necesita una forma dependiente del tipo de compilación de incluir los afaics de la biblioteca.
Adversus

@Adversus No estoy seguro de qué quiere decir exactamente, pero ¿quizás la variable Qmake $(OUT_PWD)sea ​​la solución?
hyde

Cuando aplico mi pregunta a su ejemplo, se convierte en: ¿cuál es la forma más limpia para que una solicitud responda mylib? Me gustaría si hubiera una forma "elegante" de hacer esto, no veo otra forma que no sea usar las técnicas de las otras respuestas: use el tipo de compilación y la configuración para completar LIBSde una manera inteligente, anulando la ventaja de la construcción de sombra.
Adversus

@Adversus Si mylib es un proyecto de subdirectorio bajo el mismo proyecto de nivel superior, generalmente agregaría un archivo mylib.pri y pondría todo lo que otros proyectos de subdirectorios necesitan allí, usando variables de Qmake para obtener las rutas correctas siempre, incluso si es una compilación de sombra. Entonces otros archivos .pro de subdirectorio simplemente tendríaninclude(../mylib/mylib.pri)
hyde

gracias, eso es lo que estoy haciendo ahora, hubiera sido bueno tener una solución en la que esto se solucione automáticamente, como cuando tiene un proyecto con subproyectos en cmake y luego puede hacer fácilmente diferentes compilaciones fuente de todo el árbol.
Adversus

3

También es útil tener un nombre ligeramente diferente para el ejecutable de salida. No puedes usar algo como:

release: Target = ProgramName
debug: Target = ProgramName_d

No está claro por qué no funciona, pero no es así. Pero:

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

Esto funciona siempre que la CONFIG +=línea lo preceda.


1

La nueva versión de Qt Creator también tiene una opción de construcción de "perfil" entre depuración y publicación. Así es como lo estoy detectando:

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

0

1. Busque depuración / liberación en CONFIG

Obtenga la versión actual (depuración |).

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

(Puede ser múltiple, así que mantén solo el último especificado en la compilación):

2. Configure DESTDIR

Úselo tiene el nombre del subdirectorio de compilación

DESTDIR = $$PWD/build/$$build_subdir

0

Este es mi Makefile para diferentes directorios de salida de depuración / liberación. Este Makefile se probó con éxito en Ubuntu linux. Debería funcionar sin problemas en Windows siempre que Mingw-w64 esté instalado correctamente.

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$@
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.