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

QtQmake

Qt Problem Overview


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?

Qt Solutions


Solution 1 - Qt

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! :)

Solution 2 - Qt

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).

Solution 3 - Qt

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

Solution 4 - Qt

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

Solution 5 - Qt

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"
}

Solution 6 - Qt

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

Solution 7 - Qt

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.

Solution 8 - Qt

The short answer is: you don't.

You should run qmake followed by make in whatever build directory you want to build in. So, run it once in a debug directory, once in a release directory.

That's how anyone building your project would expect it to work, and that's how Qt itself is set up to build, that's also how Qt Creator expects your .pro file to behave: it simply starts qmake and then make in the build folder for your target's chosen configuration.

If you wish to create these folders and perform the two (or more) builds in them, you'll need a top-level makefile, possibly created from a top-level project file via qmake.

It's not uncommon to have more than two build configurations, so you're unnecessarily committing yourself to only differentiating between a build and a release; you might have builds with different optimization levels, etc. The debug/release dichotomy is best left to rest in peace.

Solution 9 - Qt

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 }

Solution 10 - Qt

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

Solution 11 - Qt

Not sure if anyone will face issues like me, but I'd share my setup. I use a central proj.pri file to store general settings. I have PKG.pro in each subdirs which is already designed for debug mode. So when I try to build both debug and release, I don't want to modify every PKG.pro in each subdir. I added same

DESTDIR = $${SOMEOTHERPATH}
release: DESTDIR = $${DESTDIR}/release
debug:   DESTDIR = $${DESTDIR}/debug

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

which doesn't work since in each subdir, DESTDIR will get evaluated again. it ends a double debug or release. To avoid this, you have to use only one DESTDIR set, then in each subdir, you can include this proj.pri file. This way, you don't need to write one DIR setup. And "qmake CONFIG=debug" or "qmake CONFIG=release" is needed to build debug or release. Anyone has better solution, please share.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEtienne SavardView Question on Stackoverflow
Solution 1 - QtmosgView Answer on Stackoverflow
Solution 2 - QtchalupView Answer on Stackoverflow
Solution 3 - QtHello WView Answer on Stackoverflow
Solution 4 - QtABCplusView Answer on Stackoverflow
Solution 5 - QtSullaView Answer on Stackoverflow
Solution 6 - QthydeView Answer on Stackoverflow
Solution 7 - QtSteve BeschView Answer on Stackoverflow
Solution 8 - QtKuba hasn't forgotten MonicaView Answer on Stackoverflow
Solution 9 - QtBuvinJView Answer on Stackoverflow
Solution 10 - QtAhmed RashedView Answer on Stackoverflow
Solution 11 - Qtuser2189731View Answer on Stackoverflow