2011-08-11 34 views
205

我有很多使用CMake構建的項目,我希望能夠輕鬆地在使用GCC或Clang/LLVM編譯它們之間切換。我相信(請糾正我,如果我錯了!),要使用鏘我需要設置如下:使用CMake在GCC和Clang/LLVM之間切換

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中)?

此外,使用clang而不是gcc編譯時,是否需要使用llvm-*程序而不是系統默認值?有什麼不同?

回答

258

CMake的在檢測到所述C和C++編譯器使用榮譽的環境變量CCCXX到它。使用以下內容創建一個文件~/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的binutils,設置內部變量_CMAKE_TOOLCHAIN_PREFIX。這個變量是由CMakeFindBinUtils模塊榮幸:

$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- .. 

把所有這些組合起來,你可以寫一個shell封裝程序設置環境變量CCCXX,然後調用與所提到的變量覆蓋cmake的。

+1

我已經遵循了你的回答,除了'CMAKE_USER_MAKE_RULES_OVERRIDE'以外的所有內容都能正常工作。看起來文件被忽略了(即,儘管CMAKE_C_FLAGS_RELEASE在覆蓋文件中被設置爲「-O4」,它在cmake中顯示了「-O3 -DNDEBUG」的默認值)。 – Rezzie

+11

請注意,大部分信息都緩存在構建樹頂層的CMakeCache.txt文件中。要在gcc和clang之間切換,你應該有兩個完全獨立的構建樹,並簡單地來回「切換」編譯器。一旦使用給定的編譯器生成構建樹,就無法切換該構建樹的編譯器。 – DLRdave

+0

@DLRdave使用兩個獨立的構建樹是一個明智的想法;有一個我沒有考慮過。糟糕:)但是,即使在新的'src/build-clang'目錄中執行,覆蓋被忽略。 – Rezzie

3

您可以在您的CMakeLists.txt中使用語法:$ENV{environment-variable}來訪問環境變量。您可以創建腳本來適當地初始化一組環境變量,並在CMakeLists.txt文件中引用這些變量。

+0

能不能請您詳細說明遠一點?你的意思是一個shell腳本在啓動cmake之前導出環境變量?需要設置哪些變量?或者你的意思是用'-DCMAKE_C_COMPILER ...'等調用cmake的腳本/別名? – Rezzie

+0

我的意思是一個腳本,只是出口適當的環境變量。您將編寫自己的環境變量並在CMakeLists中引用它們。txt文件。 – Ferruccio

+0

啊;我明白你的意思了。唯一需要通過每個項目的'CMakeLists.txt'並讓它查詢新變量。我希望在系統範圍內有一個方便的方法,而不必修改任何項目文件。類似於傳遞'CMAKE_TOOLCHAIN_FILE'。 – Rezzie

20

您可以使用此選項命令:

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

,然後如果(包裹鐺編譯器設置)S:

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

這種方式顯示爲一個cmake的選項gui配置工具。

爲了讓它在整個系統範圍內,你當然可以使用一個環境變量作爲默認值,或者留在Ferruccio的答案中。

$ 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變量被重寫:

+0

這就是我目前設置的方式,但顯然它需要在每個項目的基礎上進行。我希望能有一個像'cmake -DCMAKE_COMPILER_DEFINITIONS = MyLlvmDefinitions.cmake'這樣的命令。 – Rezzie

+0

現在我明白你想要完成什麼。我不知道該行爲是否由cmake提供,但是您可以嘗試在開始運行CMakeLists.txt之前似乎加載腳本的-C選項。還沒有嘗試過。 –

8

你肯定不需要使用各種不同的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,您可能不需要(它會大大增加編譯時間)並且鐺默認爲c99模式,因此標誌也不一定需要。

103

系統廣泛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 

然後,只需選擇鐺++。

+3

謝謝,我不知道這個!雖然我猜這取決於cmake在尋找編譯器的地方,對吧? – Ibrahim

+1

@Ibrahim此配置將「C++」符號鏈接設置爲您選擇的編譯器,cmake默認檢查「C++」,而不是「g ++」。所以除非cmake配置非常明確,否則這應該可以正常工作(而且對我來說也是如此)。 – Zoomulator

+0

對,我不知道我現在的意思是什麼:/好吧,如果你自己定義了CC和CXX的環境變量,那麼它有可能改變一些事情,那麼它可能會在別的地方。 – Ibrahim

13

系統範圍的碳變化在Ubuntu:

sudo update-alternatives --config cc

系統範圍的c + +改變在Ubuntu:

sudo update-alternatives --config c++

對於各上述,按選擇號的(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: 
+4

如果你已經手動安裝了你的clang,並把它放在一個非標準的地方,它可能不會顯示--config。例如,如果它在'/ opt/clang-llvm-3.5 /'中,那麼首先安裝一個新的替代方案: 'sudo update-alternatives --install/usr/bin/C++ C++ /opt/clang-llvm-3.5/ bin/clang ++ 30' – CodeKid

1

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_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 
1

可以使用工具鏈cma的文件機制爲此目的,參見例如here。您爲包含相應定義的每個編譯器編寫一個工具鏈文件。在配置時,您運行例如

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

並且所有編譯器信息都將在工具鏈文件的project()調用期間設置。雖然在文檔中只提到了交叉編譯的情況,但它適用於同一系統上的不同編譯器。

1

如果默認的編譯器選擇通過cmakegcc,並且您已經安裝了clang,你可以用最簡單的方式與clang編譯項目:

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