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を尊重し、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 ..

最後に、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 2011

18
この情報の多くは、ビルドツリーの最上位にあるCMakeCache.txtファイルにキャッシュされます。gccとclangを切り替えるには、2つの完全に独立したビルドツリーが必要です。コンパイラを「切り替える」には、前後にcdします。特定のコンパイラでビルドツリーが生成されると、そのビルドツリーのコンパイラを切り替えることはできません。
DLRdave 2011

@DLRdave 2つの個別のビルドツリーを使用することは賢明なアイデアです。私が考えていなかったもの。おっと:)ただし、新しいsrc/build-clangディレクトリで実行しても、オーバーライドは無視されます。
Rezzie 2011

1
@Rezzie ClangOverrides.txtのフラグは、サフィックス_INITで定義する必要があります。更新された回答を参照してください。
11

8
読者への注意。CMakeでCCCXX変数が有効にならないという問題がある場合は、最初にビルドディレクトリからすべてのファイルを削除する必要があることが原因である可能性があります。 rm CMakeCache.txt十分ではないかもしれません。
John Dibling 2014

128

Ubuntuでのシステム全体の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、2013年

2
「リンクグループc ++には1つの選択肢しかない」という返事が返ってきます。回答を拡張して、このリストにclangを追加する方法を含めてください
vedant

3
システムに副作用を引き起こす可能性があるため、この代替方法には注意してください。インストール中に一部のカーネルモジュールを再コンパイルするnvidiaドライバーなどのパッケージで既に問題があり、clangと互換性がありませんでした。
ファルコ

2
clang-3.5、clang-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オプションとして表示されます。

システム全体に適用するには、もちろん、環境変数をデフォルト値として使用するか、Ferlucioの回答をそのまま使用できます。


それは私が現在それをセットアップしている方法ですが、明らかにプロジェクトごとに行う必要があります。のようなコマンドがあることを望んでいましたcmake -DCMAKE_COMPILER_DEFINITIONS=MyLlvmDefinitions.cmake
Rezzie 2011

1
今、私はあなたが達成しようとしていることを理解しています。その動作がcmakeによって提供されるかどうかはわかりませんが、CMakeLists.txtの実行を開始する前にスクリプトをロードするように見える-Cオプションを試すことができます。まだ試していません。
Tobias Schlegel

18

Ubuntuでのシステム全体のCの変更:

sudo update-alternatives --config cc

Ubuntuでのシステム全体の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のツールチェーンファイルメカニズムを使用できます。たとえば、こちらを参照してください。対応する定義を含むコンパイラごとにツールチェーンファイルを記述します。設定時に、例えばを実行します

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

すべてのコンパイラ情報は、toolchainファイルからのproject()呼び出し中に設定されます。ドキュメントではクロスコンパイルの文脈でのみ言及されていますが、同じシステム上の異なるコンパイラでも同様に機能します。


4
私は、SOのスレッドの一番下にしか正しい答えが見つからないことに驚いています。
スラバ

10

さまざまな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

によって選択されたデフォルトのコンパイラ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.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

クラン:

cmake -C clang_compiler.txt XXXXXXXX

3

あなたは構文を使用できます。$ENV{environment-variable}あなたの中CMakeLists.txtへのアクセス環境変数。環境変数のセットを適切に初期化し、CMakeLists.txtファイル内のそれらの変数への参照のみを持つスクリプトを作成できます。


もう少し詳しく教えてください。cmakeを起動する前に環境変数をエクスポートするシェルスクリプトですか?どの変数を設定する必要がありますか?それとも、cmakeを呼び出すだけのスクリプトやエイリアス-DCMAKE_C_COMPILER ...などですか?
Rezzie、2011

適切な環境変数をエクスポートするだけのスクリプトです。独自の環境変数を作成し、CMakeLists.txtファイルでそれらを参照します。
Ferruccio 2011

ああ どういう意味かわかります。唯一のことはCMakeLists.txt、すべてのプロジェクトを調べて、新しい変数をクエリする必要があるということです。プロジェクトファイルを変更せずに、システム全体でこれを行う便利な方法があることを望んでいました。を渡すのと同じCMAKE_TOOLCHAIN_FILEです。
Rezzie 2011
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.