Як вказати різні налагодження / випуск вихідних каталогів у файлі QMake .pro


106

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

В даний час у мене є така структура каталогів:

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

Залежно від конфігурації (налагодження / випуск), я хотів би вивести отримані файли всередині каталогу збирання під каталогами build / debug або build / release.

Як я можу це зробити за допомогою файлу .pro?


Те, як Qt ставиться до налагодження та випуску, будує внутрішньо змінені з часом. Тож ми виявили, що попередні робочі перемикачі між налагодженням та випуском зламалися в пізніших версіях. Дивіться моє рішення, яке працює на всіх платформах та на всіх версіях Qt до цих пір. stackoverflow.com/questions/32046181 / ...
adlag

2
Оскільки це старе питання, варто зазначити, що кращі відповіді набагато менше голосів.
Уорд

Відповіді:


5

Коротка відповідь: ви цього не робите .

Вам слід запустити, qmakeза яким слід makeу будь-який каталог збірки, в який ви хочете побудувати. Отже, запустіть його один раз у debugкаталозі, раз у releaseкаталозі.

Ось як очікує, що той, хто будує ваш проект, спрацює, і саме так Qt налаштований на створення, саме так Qt Creator очікує, що ваш .proфайл поводиться: він просто запускається, qmakeа потім - makeу папку збірки для вибраної конфігурації вашої цілі.

Якщо ви хочете створити ці папки та виконати дві (або більше) складання в них, вам знадобиться makefile верхнього рівня, можливо, створений з файлу проекту верхнього рівня через qmake.

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


151

Для мого проекту 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
Розум пояснює, як це використовується / що він робить? Схоже, це не має ніякого ефекту, коли я його реалізую. редагувати: якщо я зміню налагодження на налагодження (нижній регістр), він працює. Я підозрюю, що це річ чутливості випадку Windows проти Unix.
Нотлеш

9
Я проголосував за те, що він працює в Windows. У Linux (Ubuntu 15.04, Qt 5.5.0) мені довелося змінити , Debugщоб debugі Releaseв release.
Джепессен

Wth? Стільки перетнути платформу? @Jepessen ??
Нільс

2
Це працює лише тоді, коли у CONFIG ви маєте лише випуск або налагодження. Якщо обидва знаходяться в конфігурації, буде використано останнє.
веска

52

Щоб змінити каталог для цільового dll / exe, використовуйте це у своєму профі-файлі:

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

Ви також можете змінити каталоги для інших цілей побудови, таких як об'єктні файли та moc-файли (перевірте посилання на змінну qmake для детальної інформації або посилання на функцію qmake CONFIG () ).


5
Але я вважаю, що набагато приємніше включити до цього $$ OUT_PWD, тому DESTDIR = $$ OUT_PWD / налагодження
Іво

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 Поведінка творця могла змінитися з моменту опублікування цієї відповіді ...
ssc

1
Спробуйте додати "CONFIG - = налагодження" до додаткових аргументів qmake в режимі випуску
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_s similarly_what_is_the_the_2the


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запускається правильними аргументами в іншому каталозі збірки. Тоді це просто будується з простого 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

І найважливішим є те, що a qmakeзапускається в каталозі збірки:

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

Тоді він генерує makefiles у каталозі збирання, а потім makeтакож генерує файли під ним. Немає ризику змішування різних версій, доки qmake ніколи не запускається у вихідному каталозі (якщо він є, краще добре очистіть його!).

І коли це зроблено так, .proфайл із прийнятої відповіді ще простіше:

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

Добре працює для одного проекту, але що робити, якщо у вас є проект та бібліотека? Тоді вам потрібен спосіб, що залежить від побудови, включаючи бібліотечні афаіки.
Адверс

@Adversus Я не впевнений, що саме ти маєш на увазі, але, можливо, змінна Qmake $(OUT_PWD)- це рішення?
Гайд

Коли я застосовую своє запитання до вашого прикладу, це стає: який найчистіший спосіб подати заявку mylib? Мені б хотілося, щоб це було "витонченим" способом зробити це, я не бачу іншого способу, крім використання методів з інших відповідей: використовуйте тип збірки та конфігурацію, щоб заповнити LIBSрозумний спосіб, зводячи нанівець перевага тіньового нарощування.
Адверс

@Adversus Якщо mylib є субдірним проектом під тим самим проектом верхнього рівня, я зазвичай додаю файл mylib.pri і вкладаю туди все, що потрібно іншим проектам subdir, використовуючи змінні 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. Знайдіть налагодження / випуск у 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.