Переключение между GCC и Clang / LLVM с использованием CMake - PullRequest
242 голосов
/ 11 августа 2011

У меня есть несколько проектов, созданных с использованием 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?Какая разница?

Ответы [ 9 ]

309 голосов
/ 11 августа 2011

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        "-O4 -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        "-O4 -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 с указаннымпеременные переопределения.

115 голосов
/ 11 октября 2012

Изменение всей системы C ++ в 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 ++.

21 голосов
/ 11 августа 2011

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

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

и затем обернуть настройки компилятора clang в if () s:

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

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

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

16 голосов
/ 26 июня 2014

Изменение всей системы C в Ubuntu:

sudo update-alternatives --config cc

Изменение всей системы C ++ в 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:
9 голосов
/ 12 августа 2011

Вам определенно не нужно использовать различные программы 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, так что флаг также необязательно нужен.

7 голосов
/ 12 ноября 2017

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

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

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

4 голосов
/ 31 марта 2016

Согласно справке 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's cmake listfiles.  The loaded entries take priority over the project's 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
3 голосов
/ 14 ноября 2017

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

$ mkdir build && cd build
$ CXX=clang++ CC=clang cmake ..
$ make -j2
3 голосов
/ 11 августа 2011

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

...