Przełączanie pomiędzy GCC i clang / LLVM za pomocą CMake

Mam wiele projektów zbudowanych przy użyciu CMake i chciałbym mieć możliwość łatwego przełączania się między GCC lub clang/LLVM, aby je skompilować. Wierzę (Proszę mnie poprawić, jeśli się mylę!), że aby użyć Clang muszę ustawić:

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

Czy istnieje łatwy sposób przełączania się między tymi i domyślnymi zmiennymi GCC, najlepiej jako zmiana dla całego systemu, a nie specyficzna dla projektu (tzn. nie tylko dodawanie ich do cmakelistów projektu.txt)?

Również, czy konieczne jest, aby używać programów llvm-* zamiast domyślnych systemowych podczas kompilacji przy użyciu clang zamiast gcc? Co za różnica?

Author: Rezzie, 2011-08-11

9 answers

CMake honoruje zmienne środowiskowe CC i CXX po wykryciu kompilatora C i C++ do użycia:

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

Flagi specyficzne dla kompilatora mogą zostać nadpisane przez umieszczenie ich w pliku CMake całego systemu i skierowanie do niego zmiennej CMAKE_USER_MAKE_RULES_OVERRIDE . Utwórz plik ~/ClangOverrides.txt o następującej treści:

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

Przyrostek _INIT spowoduje, że CMake zainicjalizuje odpowiednią zmienną *_FLAGS o podanej wartości. Następnie wywołaj cmake w następujący sposób:

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

Wreszcie, aby wymusić użycie binutils LLVM, Ustaw zmienną wewnętrzną _CMAKE_TOOLCHAIN_PREFIX. Zmienna ta jest honorowana przez moduł CMakeFindBinUtils:

$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- ..

Składając to wszystko razem, możesz napisać wrapper powłoki, który ustawia zmienne środowiskowe CC i CXX, a następnie wywołuje cmake ze wspomnianymi nadpisami zmiennych.

 277
Author: sakra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-26 08:16:27

Zmiana całego systemu C++ na Ubuntu:

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

Wydrukuje coś takiego:

  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

Następnie wybierz clang++.

 106
Author: Coder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-26 23:56:16

Możesz użyć polecenia option:

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

A następnie zawiń ustawienia kompilatora clang W if()S:

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

W ten sposób jest wyświetlana jako opcja cmake w narzędziach konfiguracyjnych gui.

Aby uczynić go ogólnoświatowym, możesz oczywiście użyć zmiennej środowiskowej jako wartości domyślnej lub pozostać przy odpowiedzi Ferruccio.

 21
Author: Tobias Schlegel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-11 19:16:34

Zmiana całego systemu C na Ubuntu:

sudo update-alternatives --config cc

Zmiana całego systemu C++ na Ubuntu:

sudo update-alternatives --config c++

Dla każdego z powyższych, naciśnij Selection number (1) i wprowadź, aby wybrać 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:
 16
Author: Victor Lyuboslavsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-26 00:21:13

Zdecydowanie nie musisz używać różnych programów 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")

Są one przeznaczone do pracy z wewnętrznym formatem llvm i jako takie nie są przydatne do budowania aplikacji.

Jako Uwaga-O4 wywoła LTO do twojego programu, którego możesz nie chcieć (znacznie wydłuży to czas kompilacji) i clang domyślnie ustawia tryb c99, więc flaga też nie jest potrzebna.

 9
Author: echristo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-11 21:52:25

Możesz użyć składni: $ENV{environment-variable} w swoim CMakeLists.txt Aby uzyskać dostęp do zmiennych środowiskowych. Można tworzyć skrypty, które odpowiednio inicjalizują zbiór zmiennych środowiskowych i zawierają odniesienia do tych zmiennych w plikach CMakeLists.txt.

 3
Author: Ferruccio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-11 19:00:48

Możesz w tym celu użyć mechanizmu pliku toolchain cmake, patrz np. Tutaj . Dla każdego kompilatora zapisywany jest plik toolchain zawierający odpowiednie definicje. W czasie konfiguracji uruchamiasz np.]}

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

I wszystkie informacje kompilatora zostaną ustawione podczas wywołania project () z pliku toolchain. Chociaż w dokumentacji jest mowa tylko w kontekście kompilacji krzyżowej, działa również dla różnych kompilatorów na tym samym systemie.

 2
Author: j_fu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-11 22:45:04

Jeśli domyślnym kompilatorem wybranym przez cmake jest gcc i zainstalowałeś clang, możesz w łatwy sposób skompilować swój projekt za pomocą clang:

$ mkdir build && cd build
$ CXX=clang++ CC=clang cmake ..
$ make -j2
 2
Author: xl4times,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-14 17:04:50

Według pomocy 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.

Możesz tworzyć pliki takie jak gcc_compiler.txt i clang_compiler.txt, aby zawierały całą relatywną konfigurację w składni CMake.

Przykład Clang (clang_compiler.txt):

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

Następnie uruchom go jako

GCC:

cmake -C gcc_compiler.txt XXXXXXXX

Clang:

cmake -C clang_compiler.txt XXXXXXXX
 1
Author: Enze Chi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-30 23:56:15