Как указать разные выходные каталоги Debug / Release в файле QMake .pro


106

У меня есть проект Qt, и я хотел бы выводить файлы компиляции за пределы дерева исходных текстов.

В настоящее время у меня следующая структура каталогов:

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

В зависимости от конфигурации (отладка / выпуск) я хотел бы вывести полученные файлы в каталог сборки в каталогах сборки / отладки или сборки / выпуска.

Как я могу это сделать с помощью файла .pro?


То, как Qt обрабатывает отладочные и выпускающие сборки, со временем изменилось внутри. Итак, мы обнаружили, что предыдущие рабочие переключатели между отладкой и выпуском не работали в более поздних версиях. Посмотрите мое решение, которое до сих пор работает на всех платформах и во всех версиях Qt. stackoverflow.com/questions/32046181/…
adlag

2
Поскольку это старый вопрос, стоит отметить, что есть лучшие ответы с гораздо меньшим количеством голосов.
wardw

Ответы:


4

Короткий ответ: нет .

Вы должны запустить с qmakeпоследующим makeв любом каталоге сборки, который хотите встроить. Итак, запустите его один раз в debugкаталоге, один раз в releaseкаталоге.

Вот как любой, кто создает ваш проект, ожидает, что он будет работать, и именно так Qt настроен для сборки, а также Qt Creator ожидает, что ваш .proфайл будет вести себя: он просто запускается, qmakeа затем находится makeв папке сборки для выбранной вами конфигурации.

Если вы хотите создать эти папки и выполнить в них две (или более) сборки, вам понадобится make-файл верхнего уровня, возможно, созданный из файла проекта верхнего уровня с помощью qmake.

Нередко наличие более двух конфигураций сборки, поэтому вы излишне обязуетесь проводить различие только между сборкой и выпуском; у вас могут быть сборки с разными уровнями оптимизации и т.д. Дихотомию отладка / выпуск лучше оставить в покое.


152

Для своего проекта Qt я использую эту схему в файле * .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

Это просто, но приятно! :)


18
Как раз то, что мне было нужно! И примечание: Для того, чтобы сделать вещи еще проще переключаться вокруг, только определять DESTDIRS условно, а затем использовать это значение во всех ваших других путях: OBJECTS_DIR = $${DESTDIR}/.obj. Ура!
Ксавье Холт

4
Не могли бы объяснить, как это используется / для чего это нужно? Похоже, что это не повлияло на мою реализацию. изменить: если я изменю Debug на debug (нижний регистр), он работает. Я подозреваю, что это проблема чувствительности к регистру Windows и Unix.
notlesh

9
Я проголосовал за него, потому что он работает в Windows. В Linux (Ubuntu 15.04, Qt 5.5.0) мне пришлось изменить , Debugчтобы debugи Releaseв release.
Jepessen

Что? Так много кроссплатформенности? @Jepessen ??
Нильс

2
Это работает только тогда, когда у вас есть только выпуск или отладка в CONFIG. Если оба находятся в конфигурации, будет использоваться последний.
weeska

52

Чтобы изменить каталог для целевой dll / exe, используйте это в своем файле pro:

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

Вы также можете изменить каталоги для других целей сборки, таких как объектные файлы и файлы moc ( подробности см. В справке по переменной qmake или в справочнике по функции qmake CONFIG () ).


5
Но мне показалось, что гораздо приятнее включить сюда $$ OUT_PWD, поэтому DESTDIR = $$ OUT_PWD / debug
Иво

1
@Ivo: Ах! Спасибо! Я везде искал, какая переменная содержит этот путь! : D
Кэмерон

1
После этого вы можете добавить такие строки, как: OBJECTS_DIR = $$DESTDIR/.obj MOC_DIR = $$DESTDIR/.moc RCC_DIR = $$DESTDIR/.qrc UI_DIR = $$DESTDIR/.ui CONFIG()оказывается, чтобы решить некоторые проблемы с использованием release:иdebug:
Carson Ip

Этот сработал лучше, чем выбранный ответ. Выбранный работает, но если настроены и отладка, и выпуск, второй блок настроек остается.
Пауло Карвалью

42

У меня более компактный подход:

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
Ваш ответ - это более свежий способ поместить вывод сборки компилятора в отдельный каталог.
SIFE

1
Вы пробовали это недавно как для отладки, так и для выпуска? мои результаты сборки всегда оказываются в папке выпуска, независимо от конфигурации; Хотя поведение qmake / Qt Creator могло измениться с тех пор, как вы опубликовали этот ответ ...
ssc

1
Попробуйте добавить «CONFIG - = debug» к дополнительным аргументам qmake в режиме Release
Hello W

17

Правильный способ сделать это (спасибо команде поддержки 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

Подробнее здесь: 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


13

Я использую тот же метод, который предложил 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

Старый вопрос, но все же стоит дать актуальный ответ. Сегодня обычным делом является то, что делает Qt Creator, когда используются теневые сборки (они включены по умолчанию при открытии нового проекта).

Для каждой отдельной цели и типа сборки право qmakeзапускается с правильными аргументами в другом каталоге сборки. Тогда это просто построено с помощью simple make.

Итак, воображаемая структура каталогов может выглядеть так.

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

И что важно, qmakeв каталоге сборки запускается a :

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

Затем он генерирует make- makeфайлы в каталоге сборки, а затем также генерирует файлы в нем. Нет риска перепутать разные версии, если qmake никогда не запускается в исходном каталоге (если это так, лучше его хорошо очистить!).

И когда это делается таким образом, .proфайл из принятого в настоящее время ответа становится еще проще:

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

Отлично работает для одного проекта, но что делать, если у вас есть проект и библиотека? Тогда вам понадобится зависящий от типа сборки способ включения библиотеки afaics.
Adversus

@Adversus Я не уверен, что именно вы имеете в виду, но, возможно, переменная Qmake $(OUT_PWD)- это решение?
hyde

Когда я применяю свой вопрос к вашему примеру, он становится следующим: как лучше всего подобрать приложение mylib? Я бы хотел, чтобы был «изящный» способ сделать это, я не вижу другого способа, кроме использования методов из других ответов: используйте тип сборки и конфигурацию для LIBSразумного заполнения , сводя на нет Преимущество теневой сборки.
Adversus

@Adversus Если mylib является проектом подкаталога в рамках того же проекта верхнего уровня, я обычно добавляю файл mylib.pri и помещаю туда все, что нужно другим проектам подкаталога, используя переменные Qmake, чтобы всегда получать правильные пути, даже если это теневая сборка. Тогда другие файлы subdir .pro будут просто иметьinclude(../mylib/mylib.pri)
hyde

спасибо, это то, что я делаю сейчас, было бы неплохо иметь решение, в котором это делается автоматически, например, когда у вас есть проект с подпроектами в cmake, и затем вы можете легко создавать разные выходы из - исходные сборки всего дерева.
Adversus

3

Также полезно иметь немного другое имя для выходного исполняемого файла. Вы не можете использовать что-то вроде:

release: Target = ProgramName
debug: Target = ProgramName_d

Почему не работает - непонятно, но это не так. Но:

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

Это работает, если перед ним CONFIG +=стоит строка.


1

В новой версии Qt Creator также есть опция сборки «профиля» между отладкой и выпуском. Вот как я это обнаруживаю:

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

0

1. Найдите Debug / Release в CONFIG

Получить текущий (отладка | выпуск).

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

(Может быть несколько, поэтому оставьте только последний указанный в сборке):

2. Установите DESTDIR.

Используйте его с именем подкаталога сборки

DESTDIR = $$PWD/build/$$build_subdir

0

Это мой Makefile для разных выходных каталогов отладки / выпуска. Этот Makefile был успешно протестирован на Ubuntu linux. Он должен без проблем работать в Windows при условии, что Mingw-w64 установлен правильно.

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$@
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.