CMAKE_BUILD_TYPE не використовується в CMakeLists.txt


79

У мене проблеми з налаштуванням моєї конфігурації збірки за замовчуванням на 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 .



@ usr1234567 Так, і я також прочитав цей файл. Напевно, я роблю щось дурне, що заважає CMAKE_BUILD_TYPEпрацювати ...
Синтаксична фруктоза

@ usr1234567 Все-таки не пощастило ... Також пробував, set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Configuration type" FORCE)що не спрацювало
Синтаксична фруктоза

4
3-й раз за останні 2 дні)) set(CMAKE_BUILD_TYPE Release)Це не так працює. Випадково це буде працювати для Makefileгенератора, для IDE, таких як Xcode та Visual Studio, цей рядок буде проігноровано, оскільки Release / Debug перемикається внутрішньо. Документація про це досить чітка. Якщо ви хочете обмежити варіанти збірки, вам потрібно встановити CMAKE_CONFIGURATION_TYPES

@ruslo Опублікуйте свій коментар як відповідь, будь ласка.
usr1234567

Відповіді:


209

Існує два типи генераторів: одноконфігураційні та багатоконфігураційні.

Поодинокі конфігурації

Генератори , подібні до макетів : Unix Makefiles , 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"

матиме той самий ефект:

Введіть тут опис зображення

Це відбувається тому , що всі зміни є внутрішнім (тобто, _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

Введіть тут опис зображення

Ви навіть можете визначити власний тип конфігурації:

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

Введіть тут опис зображення

І побудуйте:

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, я щасливий ...

Деякі цитати з приємної книги симпатичного хлопця, якого ви, напевно, знаєте (наголос на моєму):

Чому ти повинен турбуватись? Люди, які програмують на різноманітних системах або використовують різні компілятори, дуже піклуються, бо якщо цього не роблять, вони змушені витрачати час на пошук та виправлення незрозумілих помилок. Люди, які стверджують, що їм не байдужа портативність, зазвичай роблять це, оскільки вони використовують лише одну систему і відчувають, що можуть дозволити собі ставлення, що `` мова застосовується моїм компілятором ''. Це вузька і недалекогляднавид. Якщо ваша програма має успіх, вона, швидше за все, буде перенесена, тому комусь доведеться знаходити та виправляти проблеми, пов’язані із функціями, що залежать від реалізації. Крім того, програми часто потрібно компілювати з іншими компіляторами для тієї самої системи, і навіть у майбутньому випуску вашого улюбленого компілятора деякі дії можуть відрізнятися від поточного. Значно легше дізнатися та обмежити вплив залежностей реалізації, коли програма написана, ніж намагатися розплутати безлад потім.


10
вау, це заслуговує на щедру відповідь, як тільки стане доступним через 4 години. Дякуємо за таку поглиблену відповідь.
Синтаксична фруктоза

Будь ласка, вибачте моє незнання ... Як, власне , ми встановлюємо CMAKE_BUILD_TYPEдля звільнення CmakeList.txt? Я думаю, що це десь у розділі Контроль (?) , Але у мене виникають проблеми з його синтаксичним аналізом, оскільки я занадто недосвідчений. Також зверніть увагу, що ми хочемо встановити лише значення за замовчуванням; його штраф користувача замінює його з командного рядка.
jww

3
Я знайшов відповідь; -H.є недокументованою функцією .
Уоллі

1
Бачу, ви намагалися виправити проблему з документацією . Дякую за спробу. :) Досі немає задовільної відповіді, чому це неможливо ні задокументувати, ні видалити (якщо насправді існує ризик).
Уоллі

2
@Muscampester лише для вашої інформації найцікавіші посилання та пояснення можна знайти на цій сторінці

7

Ви також можете використовувати такий фрагмент:

if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
            "Default build type: RelWithDebInfo" FORCE)
endif()

1
Люди, якщо тоді ви проголосуєте за надану відповідь, знайдіть кілька слів, щоб вказати, чому ви це зробили. Оскільки з усіх запропонованих відповідей ця проста мені допомогла. А до цього я знайшов подібне "прийняте" рішення тут: blog.kitware.com/cmake-and-the-default-build-type
Алекс

6

Однією з можливих ситуацій є те, що один із підмодулів встановив CMAKE_BUILD_TYPEзначення в кеші, тобто:

SET(CMAKE_BUILD_TYPE Debug CACHE) 

Це означає, що це значення буде постійно оновлюватися з цієї точки до кінця запуску конфігурації.

Одним із чудових способів відстеження місця, що порушує, де це значення змінилося, є використання змінної_програми CMake . У свій основний CMakelists.txtфайл додайте наступний рядок

variable_watch(CMAKE_BUILD_TYPE)

Це буде друкувати із стандартною помилкою кожен доступ до цієї змінної. І щоб отримати його в журналі, виконайте щось на зразок:

cmake <your options> 2>variable_watch.log

Ви можете побачити щось на зразок:

Журнал налагодження CMake за адресою <...> / CMakeLists.txt: 184 (add_library): Змінна "CMAKE_BUILD_TYPE" отримувала доступ за допомогою READ_ACCESS зі значенням "Налагодження".

Тоді ви, швидше за все, побачите пункт (и), де CMAKE_BUILD_TYPE було вперше змінено. І звідси ви будете набагато ближче відслідковувати образливу лінію CMake.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.