CMake를 사용하여 GCC와 Clang / LLVM 간 전환


269

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-*gcc 대신 clang을 사용하여 컴파일 할 때 시스템 기본값 대신 프로그램 을 사용해야 합니까? 차이점이 뭐야?

답변:


342

CMake는 다음 CC과 같이 사용할 환경 변수 와 CXXC 및 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 ..

마지막으로 LLVM binutils를 강제로 사용하려면 내부 변수를 설정하십시오 _CMAKE_TOOLCHAIN_PREFIX. 이 변수는 CMakeFindBinUtils모듈에 의해 존중됩니다 :

$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- ..

모두 함께이 퍼팅 당신은 환경 변수를 설정하는 쉘 래퍼 쓸 수 있습니다 CCCXX다음과 원용 cmake언급 된 변수 대체에 있습니다.


1
나는 당신의 대답과 CMAKE_USER_MAKE_RULES_OVERRIDE작품을 제외한 모든 것을 따랐습니다 . 파일이 무시되는 것처럼 보입니다 (즉 , 재정의 파일에서 CMAKE_C_FLAGS_RELEASE설정되어 있음에도 불구하고 -O4기본값 -O3 -DNDEBUG은 cmake입니다).
Rezzie

18
이 정보의 대부분은 빌드 트리의 최상위 레벨에있는 CMakeCache.txt 파일에 캐시됩니다. gcc와 clang 사이를 전환하려면 완전히 분리 된 두 개의 빌드 트리가 있어야하고 단순히 컴파일러를 "전환"하기 위해 CD를왔다 갔다해야합니다. 주어진 컴파일러로 빌드 트리가 생성되면 해당 빌드 트리의 컴파일러를 전환 할 수 없습니다.
DLRdave

@DLRdave 두 개의 별도 빌드 트리를 사용하는 것이 현명한 아이디어입니다. 내가 고려하지 않은 것. 죄송합니다.) 그러나 새 src/build-clang디렉토리 에서 수행하더라도 재정의는 무시됩니다.
Rezzie

1
@Rezzie ClangOverrides.txt의 플래그는 접미사 _INIT로 정의해야합니다. 업데이트 된 답변을 참조하십시오.
sakra

8
독자에게 참고하십시오. CMake가 CCCXX변수 를 준수하지 않는 데 문제가있는 경우 먼저 빌드 디렉토리에서 모든 파일을 삭제해야하기 때문일 수 있습니다. rm CMakeCache.txt충분하지 않을 수 있습니다.
John Dibling

128

우분투의 시스템 전체 C ++ 변경 :

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
고마워, 나는 이것에 대해 몰랐다! cmake가 컴파일러를 찾는 위치에 달려 있다고 생각합니다.
Ibrahim

1
@Ibrahim이 구성은 "c ++"심볼릭 링크를 선택한 컴파일러로 설정하고 cmake는 "g ++"가 아닌 "c ++"를 기본적으로 확인합니다. 따라서 cmake 구성이 매우 구체적이지 않으면 제대로 작동합니다 (나를 위해).
Zoomulator

2
"링크 그룹 c ++에는 하나의 대안 만 있습니다"라는 회신을받습니다. 이 목록에 연타를 추가하는 방법을 포함하는 답변을 확장하십시오
vedant

3
이 대안은 시스템에 부작용을 일으킬 수 있으므로주의하십시오. 설치 중에 일부 커널 모듈을 다시 컴파일하는 nvidia 드라이버와 같은 패키지에 이미 문제가 있었으며 clang과 호환되지 않았습니다.
Falco

2
당신이 그 소리-3.5, 그 소리-3.6 등의 기본 설정이 사용 설치하려는 경우 stackoverflow.com/a/30742451/1427533을 , 그렇지 않으면 당신은 얻을 것이다으로There is only one alternative in link group cc (providing /usr/bin/cc): /usr/bin/gcc
miguel.martin

23

옵션 명령을 사용할 수 있습니다.

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

그런 다음 clang-compiler 설정을 if () s로 래핑하십시오.

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

이런 식으로 GUI 구성 도구에서 cmake 옵션으로 표시됩니다.

시스템 전체에서 환경 변수를 기본값으로 사용하거나 Ferruccio의 답변을 유지할 수 있습니다.


이것이 내가 현재 설정 한 방법이지만 분명히 프로젝트별로 수행해야합니다. 와 같은 명령이 있기를 바랐습니다 cmake -DCMAKE_COMPILER_DEFINITIONS=MyLlvmDefinitions.cmake.
Rezzie

1
이제 나는 당신이 성취하려는 것을 이해합니다. 그 동작이 cmake에 의해 제공되는지는 모르겠지만 CMakeLists.txt를 실행하기 전에 스크립트를로드하는 것처럼 보이는 -C 옵션을 시도 할 수 있습니다. 그래도 시도하지 않았습니다.
Tobias Schlegel

18

Ubuntu의 시스템 전체 C 변경 :

sudo update-alternatives --config cc

우분투의 시스템 전체 C ++ 변경 :

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:

7
clang을 수동으로 설치하고 비표준 위치에 배치하면 --config와 함께 표시되지 않을 수 있습니다. 예를 들어 /opt/clang-llvm-3.5/, 새로운 대안을 먼저 설치하십시오. sudo update-alternatives --install /usr/bin/c++ c++ /opt/clang-llvm-3.5/bin/clang++ 30
CodeKid

16

이를 위해 cmake의 툴체인 파일 메커니즘을 사용할 수 있습니다 (예 : here 참조) . 해당 정의가 포함 된 각 컴파일러에 대한 툴체인 파일을 작성합니다. 설정시, 당신은 예를 들어 실행

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

모든 컴파일러 정보는 toolchain 파일에서 project () 호출 중에 설정됩니다. 문서에는 크로스 컴파일 환경에서만 언급되었지만 동일한 시스템의 다른 컴파일러에서도 잘 작동합니다.


4
나는 여전히 정답이 SO의 스레드 하단에서만 발견되는 방법에 놀랐습니다.
Slava

10

다양한 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 모드로 설정되므로 플래그도 필요하지 않습니다.


7

가 선택한 기본 컴파일러 경우 cmake입니다 gcc당신이 설치 한 clang, 당신은 당신의 프로젝트를 컴파일하는 쉬운 방법을 사용할 수 있습니다 clang:

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

5

의 도움에 따르면 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.txtCMake 구문의 모든 관련 구성을 포함합니다.

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

3

$ENV{environment-variable}에서 CMakeLists.txt환경 변수에 액세스 하기 위해 구문 : 을 사용할 수 있습니다 . 환경 변수 세트를 적절히 초기화하고 CMakeLists.txt파일 에서 해당 변수에 대한 참조를 갖는 스크립트를 작성할 수 있습니다.


좀 더 자세히 설명해 주시겠습니까? cmake를 시작하기 전에 환경 변수를 내보내는 쉘 스크립트를 의미합니까? 어떤 변수를 설정해야합니까? 아니면 cmake -DCMAKE_C_COMPILER ...등을 호출하는 스크립트 / 별칭을 의미 합니까?
Rezzie

적절한 환경 변수를 내보내는 스크립트를 의미합니다. 자체 환경 변수를 구성하고 CMakeLists.txt 파일에서 참조하십시오.
Ferruccio

아; 무슨 말인지 알 겠어 유일한 것은 CMakeLists.txt모든 프로젝트를 거치고 새로운 변수를 쿼리해야한다는 것입니다. 프로젝트 파일을 수정하지 않고도 시스템 전체에서 편리한 방법이 있기를 바랐습니다. 를 전달하는 것과 비슷합니다 CMAKE_TOOLCHAIN_FILE.
Rezzie
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.