[qt] How to specify different Debug/Release output directories in QMake .pro file

I have a Qt project and I would like to output compilation files outside the source tree.

I currently have the following directory structure:

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

Depending on the configuration (debug/release), I will like to output the resulting files inside the build directory under build/debug or build/release directories.

How can I do that using a .pro file?

This question is related to qt qmake

The answer is


The correct way to do this is the following (thanks QT Support Team):

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

More info here: 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


I use the same method suggested by 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"
}

1. Find Debug/Release in CONFIG

Get the current (debug | release).

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

(May be multiple, so keep only last specified in the build):

2. Set DESTDIR

Use it has the build subdir name

DESTDIR = $$PWD/build/$$build_subdir

Old question, but still worth an up-to-date answer. Today it's common to do what Qt Creator does when shadow builds are used (they are enabled by default when opening a new project).

For each different build target and type, the right qmake is run with right arguments in a different build directory. Then that is just built with simple make.

So, imaginary directory structure might look like this.

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

And the improtant thing is, a qmake is run in the build directory:

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

Then it generates makefiles in build directory, and then make will generate files under it too. There is no risk of different versions getting mixed up, as long as qmake is never run in the source directory (if it is, better clean it up well!).

And when done like this, the .pro file from currently accepted answer is even simpler:

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

It's also useful to have a slightly different name for the output executable. You can't use something like:

release: Target = ProgramName
debug: Target = ProgramName_d

Why it doesn't work is not clear, but it does not. But:

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

This does work as long as the CONFIG += line precedes it.


The new version of Qt Creator also has a "profile" build option between debug and release. Here's how I'm detecting that:

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

To change the directory for target dll/exe, use this in your pro file:

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

You might also want to change directories for other build targets like object files and moc files (check qmake variable reference for details or qmake CONFIG() function reference).


I have a more compact approach:

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

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

This is my Makefile for different debug/release output directories. This Makefile was tested successfully on Ubuntu linux. It should work seamlessly on Windows provided that Mingw-w64 is installed correctly.

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$@

For my Qt project, I use this scheme in *.pro file:

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

It`s simple, but nice! :)