Переключение между GCC и Clang/LLVM с помощью CMake

У меня есть ряд проектов, построенных с использованием CMake, и я хотел бы иметь возможность легко переключаться между GCC или Clang/LLVM для их компиляции. Я верю (пожалуйста, поправьте меня, если я ошибаюсь!), Что для использования Clang мне нужно установить следующее:

    SET (CMAKE_C_COMPILER             "/usr/bin/clang")
    SET (CMAKE_C_FLAGS                "-Wall -std=c99")
    SET (CMAKE_C_FLAGS_DEBUG          "-g")
    SET (CMAKE_C_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
    SET (CMAKE_C_FLAGS_RELEASE        "-O4 -DNDEBUG")
    SET (CMAKE_C_FLAGS_RELWITHDEBINFO "-O2 -g")

    SET (CMAKE_CXX_COMPILER             "/usr/bin/clang++")
    SET (CMAKE_CXX_FLAGS                "-Wall")
    SET (CMAKE_CXX_FLAGS_DEBUG          "-g")
    SET (CMAKE_CXX_FLAGS_MINSIZEREL     "-Os -DNDEBUG")
    SET (CMAKE_CXX_FLAGS_RELEASE        "-O4 -DNDEBUG")
    SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O2 -g")

    SET (CMAKE_AR      "/usr/bin/llvm-ar")
    SET (CMAKE_LINKER  "/usr/bin/llvm-ld")
    SET (CMAKE_NM      "/usr/bin/llvm-nm")
    SET (CMAKE_OBJDUMP "/usr/bin/llvm-objdump")
    SET (CMAKE_RANLIB  "/usr/bin/llvm-ranlib")

Есть ли простой способ переключения между этими и переменными GCC по умолчанию, желательно как общесистемное изменение, а не специфическое для проекта (т.е. не просто добавить их в проект CMakeLists.txt)?

Кроме того, необходимо ли использовать программы llvm-*, а не системные значения по умолчанию при компиляции с использованием clang вместо gcc? Какая разница?

Ответ 1

CMake учитывает переменные окружения CC и CXX при обнаружении компилятора C и C++ для использования:

$ export CC=/usr/bin/clang
$ export CXX=/usr/bin/clang++
$ cmake ..
-- The C compiler identification is Clang
-- The CXX compiler identification is Clang

Флаги, специфичные для компилятора, можно переопределить, поместив их в системный файл CMake и указав на него переменную CMAKE_USER_MAKE_RULES_OVERRIDE. Создайте файл ~/ClangOverrides.txt со следующим содержимым:

SET (CMAKE_C_FLAGS_INIT                "-Wall -std=c99")
SET (CMAKE_C_FLAGS_DEBUG_INIT          "-g")
SET (CMAKE_C_FLAGS_MINSIZEREL_INIT     "-Os -DNDEBUG")
SET (CMAKE_C_FLAGS_RELEASE_INIT        "-O3 -DNDEBUG")
SET (CMAKE_C_FLAGS_RELWITHDEBINFO_INIT "-O2 -g")

SET (CMAKE_CXX_FLAGS_INIT                "-Wall")
SET (CMAKE_CXX_FLAGS_DEBUG_INIT          "-g")
SET (CMAKE_CXX_FLAGS_MINSIZEREL_INIT     "-Os -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELEASE_INIT        "-O3 -DNDEBUG")
SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT "-O2 -g")

Суффикс _INIT заставит CMake инициализировать соответствующую переменную *_FLAGS с заданным значением. Затем вызовите cmake следующим образом:

$ cmake -DCMAKE_USER_MAKE_RULES_OVERRIDE=~/ClangOverrides.txt ..

Наконец, чтобы принудительно использовать binutils LLVM, установите внутреннюю переменную _CMAKE_TOOLCHAIN_PREFIX. Эта переменная учитывается модулем CMakeFindBinUtils:

$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- ..

Собрав все это вместе, вы можете написать оболочку оболочки, которая устанавливает переменные среды CC и CXX, а затем вызывает cmake с упомянутыми переопределениями переменных.

Ответ 2

Изменение в системе С++ на Ubuntu:

sudo apt-get install clang
sudo update-alternatives --config c++

Выведет что-то вроде этого:

  Selection    Path              Priority   Status
------------------------------------------------------------
* 0            /usr/bin/g++       20        auto mode
  1            /usr/bin/clang++   10        manual mode
  2            /usr/bin/g++       20        manual mode

Затем просто выберите clang++.

Ответ 3

Вы можете использовать команду option:

option(USE_CLANG "build application with clang" OFF) # OFF is the default

а затем заверните настройки clang-compiler в if() s:

if(USE_CLANG)
    SET (...)
    ....
endif(USE_CLANG)

Таким образом, он отображается как опция cmake в инструментах конфигурации gui.

Чтобы сделать его общедоступным, вы можете, конечно, использовать переменную среды в качестве значения по умолчанию или оставаться с ответом Ферруччо.

Ответ 4

Смена системы C на Ubuntu:

sudo update-alternatives --config cc

Изменение в системе С++ на Ubuntu:

sudo update-alternatives --config c++

Для каждого из вышеперечисленных, нажмите номер выбора (1) и Enter, чтобы выбрать Clang:

  Selection    Path            Priority   Status
------------------------------------------------------------
* 0            /usr/bin/gcc     20        auto mode
  1            /usr/bin/clang   10        manual mode
  2            /usr/bin/gcc     20        manual mode
Press enter to keep the current choice[*], or type selection number:

Ответ 5

Вам определенно не нужно использовать различные программы llvm-ar и т.д.

SET (CMAKE_AR      "/usr/bin/llvm-ar")
SET (CMAKE_LINKER  "/usr/bin/llvm-ld")
SET (CMAKE_NM      "/usr/bin/llvm-nm")
SET (CMAKE_OBJDUMP "/usr/bin/llvm-objdump")
SET (CMAKE_RANLIB  "/usr/bin/llvm-ranlib")

Они созданы для работы с внутренним форматом llvm и, как таковые, не полезны для сборки вашего приложения.

В качестве примечания -O4 вызовет LTO в вашей программе, который вам может не понадобиться (это значительно увеличит время компиляции), а clang по умолчанию - в режиме c99, так что флаг необязательно также нужен.

Ответ 6

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

 cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/clang-toolchain.cmake ..

и вся информация о компиляторе будет установлена во время вызова project() из файла цепочки инструментов. Хотя в документации упоминается только в контексте кросс-компиляции, он работает также для разных компиляторов в одной системе.

Ответ 7

В соответствии с помощью cmake:

-C <initial-cache>
     Pre-load a script to populate the cache.

     When cmake is first run in an empty build tree, it creates a CMakeCache.txt file and populates it with customizable settings for the project.  This option may be used to specify a  file  from
     which to load cache entries before the first pass through the project cmake listfiles.  The loaded entries take priority over the project default values.  The given file should be a CMake
     script containing SET commands that use the CACHE option, not a cache-format file.

Вы можете создавать файлы типа gcc_compiler.txt и clang_compiler.txt для включения всех относительных конфигураций в синтаксис CMake.

Пример Clang (clang_compiler.txt):

 set(CMAKE_C_COMPILER "/usr/bin/clang" CACHE string "clang compiler" FORCE)

Затем запустите его как

GCC:

cmake -C gcc_compiler.txt XXXXXXXX

Clang:

cmake -C clang_compiler.txt XXXXXXXX

Ответ 8

Если компилятором по умолчанию, выбранным cmake, является gcc, и вы установили clang, вы можете использовать простой способ компиляции вашего проекта с помощью clang:

$ mkdir build && cd build
$ CXX=clang++ CC=clang cmake ..
$ make -j2

Ответ 9

Вы можете использовать синтаксис: $ENV{environment-variable} в CMakeLists.txt для доступа к переменным среды. Вы можете создавать скрипты, которые соответствующим образом инициализируют набор переменных среды, и просто ссылаются на эти переменные в ваших файлах CMakeLists.txt.