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 (debu开发者_开发问答g/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?
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! :)
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
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"
}
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
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.
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 }
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$@
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.
精彩评论