CMAKE_BUILD_TYPE не используется в CMakeLists.txt

У меня проблемы с настройкой конфигурации по умолчанию для версии Release. В моем файле CMakeLists.txt я установил CMAKE_BUILD_TYPE в верхней части файла с помощью:

#enable Release ALWAYS, configure vars
set(CMAKE_BUILD_TYPE Release)
set(EXECUTABLE_NAME "ParticleSimulator")
set(VERSION_MAJOR 0)
set(VERSION_MINOR 2)

Но при создании моего проекта и открытии решения мне всегда предоставляется режим отладки, в отличие от того, что я указал в моем файле CMakeLists. Что я делаю не так?

Я посмотрел на другой вопрос, но не увидел ничего конкретного для этого вопроса.

Суть CMakeLists.txt.

Ответ 1

Существует два типа генераторов: с одной конфигурацией и с несколькими конфигурациями.

Одиночные конфигурации

Make-like генераторы: Makefiles Unix, NMake Makefiles, MinGW Makefiles,...

Вы задаете тип конфигурации на шаге генерации:

cmake -H. -B_builds/Debug -DCMAKE_BUILD_TYPE=Debug "-GUnix Makefiles"

В этом случае этап сборки всегда Отладка:

> cmake --build _builds/Debug
/usr/bin/c++ -g ...
> cmake --build _builds/Debug --config Debug # '--config' ignored
/usr/bin/c++ -g ...
> cmake --build _builds/Debug --config Release # yep, ignored
/usr/bin/c++ -g ...

Мульти-конфигурации

Генераторы IDE: Visual Studio, Xcode

CMAKE_BUILD_TYPE на шаге генерации игнорируется:

> cmake -H. -B_builds -DCMAKE_BUILD_TYPE=Debug "-GVisual Studio 12 2013 Win64"

и

> cmake -H. -B_builds -DCMAKE_BUILD_TYPE=Release "-GVisual Studio 12 2013 Win64"

будет иметь тот же эффект:

Enter image description here

Это потому, что все конфигурации являются внутренними (то есть _builds/msvc-opaque/Release и _builds/msvc-opaque/Debug или что-то, не имеет значения). Вы можете использовать опции --config для переключения:

> cmake --build _builds --config Release
cl /O2 ...
> cmake --build _builds --config Debug
cl /Od ...

Контроль (?)

Да, ты можешь. Просто определите CMAKE_CONFIGURATION_TYPES:

# Somewhere in CMakeLists.txt
message("Generated with config types: ${CMAKE_CONFIGURATION_TYPES}")

Выход по умолчанию:

-- Detecting CXX compiler ABI info - done
Generated with config types: Debug;Release;MinSizeRel;RelWithDebInfo
-- Configuring done

Перепишите его:

> cmake -H. -B_builds -DCMAKE_CONFIGURATION_TYPES="Debug;Release" "-GVisual Studio 12 2013 Win64"
-- Detecting CXX compiler ABI info - done
Generated with config types: Debug;Release
-- Configuring done

Enter image description here

Вы даже можете определить свой собственный тип конфигурации:

> cmake -H. -B_builds -DCMAKE_CONFIGURATION_TYPES="Debug;MyRelease" -DCMAKE_CXX_FLAGS_MYRELEASE="/My-Rel-flag" -DCMAKE_EXE_LINKER_FLAGS_MYRELEASE="/My-Linker-flags" "-GVisual Studio 12 2013 Win64"

Enter image description here

И построить:

cmake --build _builds --config MyRelease

Грязный (?)

Вовсе нет, если вы знаете хитрость :) Вот как собрать/протестировать конфигурацию в скрипте/на сервере CI, в инструкциях по сборке документации и т. Д.:

> CONFIG=Debug
> cmake -H. -B_builds "-DCMAKE_BUILD_TYPE=${CONFIG}" # Set Debug to Makefile, ignored by IDE
> cmake --build _builds --config "${CONFIG}" # Build Debug in IDE, ignored by Makefile
> (cd _builds && ctest -VV -C "${CONFIG}") # Test Debug in IDE, ignored by Makefile

Плохая картина

if(CMAKE_BUILD_TYPE STREQUAL Debug) # Burn it with fire!!!
set(CMAKE_BUILD_TYPE MySuperRelease) # Be ready to catch a bug from IDE user...

Хороший

set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} --my-debug-flags")

Работает хорошо.

target_compile_definitions(MyTarget PUBLIC "$<$<CONFIG:Debug>:MYDEBUG_MACRO>")

Спасибо! :) Вы экономите день для одного программиста.

У меня работает с Makefile, я счастлив...

Некоторые цитаты из хорошей книги хорошего парня, которую вы, вероятно, знаете (выделение мое):

Почему ты должен беспокоиться? Люди, которые программируют на различных системах или используют     различные компиляторы очень заботятся, потому что если они этого не делают, они вынуждены тратить     время поиска и исправления неясных ошибок. Люди, которые утверждают, что они не заботятся о     мобильность обычно делают это, потому что они используют только одну систему и чувствуют, что они     может позволить себе такое отношение, что язык - это то, что реализует мой компилятор.     Это узкий и близорукий вид. Если ваша программа успешна, она     скорее всего, будет портирован, поэтому кому-то придется искать и устранять проблемы, связанные с     зависящие от реализации функции. Кроме того, программы часто должны быть     скомпилированы с другими компиляторами для той же системы, и даже в будущем выпуске     Ваш любимый компилятор может делать некоторые вещи не так, как текущий. Это     гораздо проще узнать и ограничить влияние зависимостей реализации, когда     Программа написана, чем пытаться распутать беспорядок впоследствии.

Ответ 2

Одна из возможных причин заключается в том, что один из субмодулей установил значение CMAKE_BUILD_TYPE в кэше, а именно:

SET(CMAKE_BUILD_TYPE Debug CACHE) 

Это означает, что это значение будет постоянно обновляться с этой точки до конца запуска конфигурации.

Один из отличных способов отследить место, в котором изменилось это значение, - CMake variable_watch. В свой основной файл CMakelists.txt добавьте следующую строку

variable_watch(CMAKE_BUILD_TYPE)

Это приведет к стандартной ошибке при каждом доступе к этой переменной. И чтобы получить его в лог файл, сделайте что-то вроде:

cmake <your options> 2>variable_watch.log

Вы можете увидеть что-то вроде:

Журнал отладки CMake в & lt;...>/CMakeLists.txt: 184 (add_library): Переменная "CMAKE_BUILD_TYPE" была получена с помощью READ_ACCESS со значением "Debug".

Тогда вы, скорее всего, увидите точки, в которых CMAKE_BUILD_TYPE был впервые изменен. И отсюда вы будете намного ближе, чтобы отследить оскорбительную строку CMake.