Переключение между 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? Какая разница?

9 ответов


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

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

$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- ..

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


общесистемное изменение 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++.


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

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

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

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

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

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


общесистемное изменение C на Ubuntu:

sudo update-alternatives --config cc

общесистемное изменение C++ на Ubuntu:

sudo update-alternatives --config c++

для каждого из вышеперечисленных нажмите Selection number (1) и введите, чтобы выбрать 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:

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

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, так что флаг не обязательно нужен.


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


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

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

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


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

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

в соответствии с помощью 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 to включает всю относительную конфигурацию в синтаксисе CMake.

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

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

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

GCC:

cmake -C gcc_compiler.txt XXXXXXXX

лязг:

cmake -C clang_compiler.txt XXXXXXXX