CMake kullanarak GCC ve Clang / LLVM arasında geçiş yapma


269

CMake kullanarak bir dizi projem var ve bunları derlemek için GCC veya Clang / LLVM kullanma arasında kolayca geçiş yapabilmek istiyorum. Clang kullanmak için aşağıdakileri ayarlamam gerektiğine inanıyorum (lütfen yanılıyorsam beni düzeltin!):

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

Bunlar ve varsayılan GCC değişkenleri arasında, özellikle projeye özgü olmaktan ziyade sistem çapında bir değişiklik olarak geçiş yapmanın kolay bir yolu var mıdır (yani, bunları yalnızca bir projenin CMakeLists.txt dosyasına eklemek değil)?

Ayrıca, llvm-*gcc yerine clang kullanarak derleme yaparken sistem varsayılanları yerine programları kullanmak gerekli midir? Fark ne?

Yanıtlar:


342

CKağıt ortam değişkenleri onur CCve CXXkullanımına C ve C ++ derleyici tespit edilmesi üzerine:

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

Derleyiciye özgü bayraklar, bunları sistem çapında bir CMake dosyasına koyarak ve CMAKE_USER_MAKE_RULES_OVERRIDEdeğişkeni ona işaret ederek geçersiz kılınabilir . ~/ClangOverrides.txtAşağıdaki içeriklere sahip bir dosya oluşturun :

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

Sonek _INIT, CMake'in karşılık gelen *_FLAGSdeğişkeni verilen değerle başlatmasını sağlayacaktır . Sonra cmakeaşağıdaki şekilde çağırın :

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

Son olarak, LLVM binutils kullanımını zorlamak için dahili değişkeni ayarlayın _CMAKE_TOOLCHAIN_PREFIX. Bu değişken CMakeFindBinUtilsmodül tarafından onurlandırılır :

$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- ..

Hep birlikte bu koyarak ortam değişkenleri kurar bir kabuk sarmalayıcı yazabilir CCve CXXsonra ve çağıran cmakebelirtilen değişken geçersiz kılma özelliği olan.


1
Cevabınızı ve CMAKE_USER_MAKE_RULES_OVERRIDEeserler hariç her şeyi takip ettim . Dosya yoksayılıyor gibi görünüyor (yani geçersiz kılmalar dosyasında CMAKE_C_FLAGS_RELEASEayarlanmış olmasına rağmen , cmake içinde -O4varsayılan değerini gösteriyor -O3 -DNDEBUG).
Rezzie

18
Bu bilgilerin çoğunun derleme ağacınızın en üst düzeyindeki CMakeCache.txt dosyasında önbelleğe alındığını unutmayın. Gcc ve clang arasında geçiş yapmak için, tamamen ayrı iki yapı ağacına sahip olmanız ve derleyicileri "değiştirmek" için cd'yi ileri geri hareket ettirmeniz gerekir. Belirli bir derleyici ile bir yapı ağacı oluşturulduktan sonra, o yapı ağacı için derleyiciyi değiştiremezsiniz.
DLRdave

@DLRdave İki ayrı yapı ağacı kullanmak mantıklı bir fikirdir; düşünmemiştim. Hata! Ancak, yeni bir src/build-clangdizinde bile geçersiz kılmalar yoksayılıyor.
Rezzie

1
@Rezzie ClangOverrides.txt dosyasındaki bayrakların _INIT soneki ile tanımlanması gerekir. Güncellenmiş cevaba bakınız.
sakra

8
Okuyuculara not. CM ile ilgili sorun yaşıyorsanız CCve CXXdeğişkenlerini onurlandırmıyorsanız , bunun nedeni önce tüm dosyaları derleme dizininden silmeniz gerekebilir. rm CMakeCache.txtzorlayıcı olmayabilir.
John Dibling

128

Ubuntu'da sistem genelinde C ++ değişikliği:

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

Bunun gibi bir şey yazdıracak:

  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

Sonra sadece clang ++ 'ı seçin.


3
Teşekkürler, bunu bilmiyordum! Her ne kadar sanırım cmake'nin bir derleyici aradığına bağlı, değil mi?
İbrahim

1
@Ibrahim Bu yapılandırma seçtiğiniz derleyiciye "c ++" sembolik bağını ayarlar ve cmake "g ++" değil, varsayılan olarak "c ++" kontrol eder. Yani cmake yapılandırması çok spesifik değilse, bu iyi çalışmalıdır (ve benim için yapar).
Zoomulator

2
"Bağlantı grubu c ++ 'da yalnızca bir alternatif var" yanıtını alıyorum. Bu listeye clang eklemek için lütfen cevabınızı genişletin
vedant

3
Sisteminizde yan etkilere neden olabileceğinden bu alternatife dikkat edin. Kurulum sırasında bazı çekirdek modüllerini yeniden derleyen ve clang ile uyumlu olmayan nvidia sürücüsü gibi paketlerde zaten sorun yaşadım.
Falco

2
Clang-3.5, clang-3.6, vb. Yüklemek istiyorsanız, varsayılan stackoverflow.com/a/30742451/1427533There is only one alternative in link group cc (providing /usr/bin/cc): /usr/bin/gcc
adresini

23

Şu seçenek komutunu kullanabilirsiniz:

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

ve sonra clang-derleyici ayarlarını if () s:

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

Bu şekilde gui-yapılandırma araçlarında cmake seçeneği olarak görüntülenir.

Sistem çapında yapmak için elbette varsayılan değer olarak bir ortam değişkeni kullanabilir veya Ferruccio'nun cevabı ile kalabilirsiniz.


Şu anda bu şekilde ayarladım, ancak açıkçası proje başına yapması gerekiyor. Böyle bir emir olmasını umuyordum cmake -DCMAKE_COMPILER_DEFINITIONS=MyLlvmDefinitions.cmake.
Rezzie

1
Şimdi neyi başarmaya çalıştığınızı anlıyorum. Bu davranış cmake tarafından sağlanan olup olmadığını bilmiyorum, ama CMakeLists.txt çalıştırmadan önce bir komut dosyası yüklemek gibi görünüyor -C seçeneği deneyebilirsiniz. Yine de denemedim.
Tobias Schlegel

18

Ubuntu'da sistem genelinde C değişikliği:

sudo update-alternatives --config cc

Ubuntu'da sistem genelinde C ++ değişikliği:

sudo update-alternatives --config c++

Yukarıdakilerin her biri için Clang seçmek için Seçim numarası (1) ve Enter tuşuna basın:

  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'ınızı manuel olarak kurduysanız ve standart olmayan bir yere koyduysanız --config ile görünmeyebilir. Örneğin, /opt/clang-llvm-3.5/önce yeni bir alternatif yükleyin: sudo update-alternatives --install /usr/bin/c++ c++ /opt/clang-llvm-3.5/bin/clang++ 30
CodeKid

16

Bu amaçla cmake'nin toolchain dosya mekanizmasını kullanabilirsiniz, örneğin buraya bakın . Her derleyici için ilgili tanımları içeren bir araç zinciri dosyası yazarsınız. Yapılandırma zamanında,

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

ve tüm derleyici bilgileri toolchain dosyasından proje () çağrısı sırasında ayarlanır. Belgelerde sadece çapraz derleme bağlamında bahsedilmesine rağmen, aynı sistemdeki farklı derleyiciler için de çalışır.


4
Hala doğru cevaplar sadece burada SO bir iş parçacığının altında bulunabilir nasıl şaşırıyorum.
Slava

10

Kesinlikle çeşitli farklı llvm-ar vb programlarını kullanmanıza gerek yoktur:

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

Bunlar llvm dahili biçiminde çalışacak şekilde yapılmıştır ve bu nedenle uygulamanızın oluşturulması için yararlı değildir.

Not olarak -O4 programınızda istemediğiniz LTO'yu çağıracaktır (derleme süresini büyük ölçüde artıracaktır) ve bayrak varsayılan olarak c99 moduna geçecektir, böylece bayrak da gerekli değildir.


7

Tarafından seçilen varsayılan derleyici cmakeise gccve yüklediyseniz clang, projenizi aşağıdakilerle derlemenin kolay yolunu kullanabilirsiniz clang:

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

5

Yardımına göre 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.

Aşağıdaki gibi dosyalar oluşturabilirsiniz: gcc_compiler.txtclang_compiler.txtCMake sözdizimindeki tüm göreli yapılandırmayı ve bunları içeren .

Clang Örneği (clang_compiler.txt):

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

Sonra şu şekilde çalıştırın

GCC:

cmake -C gcc_compiler.txt XXXXXXXX

clang:

cmake -C clang_compiler.txt XXXXXXXX

3

Ortam değişkenlerine erişmek $ENV{environment-variable}için : sözdizimini kullanabilirsiniz CMakeLists.txt. Bir dizi ortam değişkenini uygun şekilde başlatan ve sadece CMakeLists.txtdosyalarınızdaki bu değişkenlere referansları olan komut dosyaları oluşturabilirsiniz .


Lütfen biraz daha ayrıntı verebilir misiniz? Cmake'yi başlatmadan önce ortam değişkenlerini dışa aktarmak için bir kabuk betiği mi demek istediniz? Hangi değişkenlerin ayarlanması gerekir? Yoksa sadece cmake ile çağıran bir betik / takma ad mı demek istediniz -DCMAKE_C_COMPILER ...?
Rezzie

Sadece uygun ortam değişkenlerini veren bir betik demek istiyorum. Kendi ortam değişkenlerinizi oluşturur ve CMakeLists.txt dosyasında bunlara başvurursunuz.
Ferruccio

Ahh; Ne demek istediğini anlıyorum. Tek şey, CMakeLists.txther projenin içinden geçmesini ve yeni değişkenleri sorgulamasını gerektirir . Herhangi bir proje dosyasını değiştirmek zorunda kalmadan sistem genelinde yapmanın uygun bir yolu olacağını umuyordum. Geçmeye benzer CMAKE_TOOLCHAIN_FILE.
Rezzie
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.