CMCC का उपयोग करके GCC और Clang / LLVM के बीच स्विच करना


269

मेरे पास 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 में जोड़ना)?

इसके अलावा, क्या यह llvm-*सिस्टम डिफॉल्ट के बजाय प्रोग्राम का उपयोग करने के लिए आवश्यक है जब gcc के बजाय क्लैंग का उपयोग करते हुए संकलित किया जाता है? क्या फर्क पड़ता है?

जवाबों:


342

CMake का सम्मान वातावरण चर CCऔर CXXउपयोग करने के लिए सी और सी ++ संकलक का पता लगाने पर:

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

संकलक विशिष्ट झंडे को सिस्टम वाइड सीएमके फ़ाइल में डालकर और 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संगत *_FLAGSचर को इनिशियलाइज़ करेगा । फिर cmakeनिम्न तरीके से आह्वान करें :

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

अंत में एलएलवीएम बिन्यूटिल्स के उपयोग को मजबूर करने के लिए, आंतरिक चर सेट करें _CMAKE_TOOLCHAIN_PREFIX। इस चर को CMakeFindBinUtilsमॉड्यूल द्वारा सम्मानित किया जाता है :

$ cmake -D_CMAKE_TOOLCHAIN_PREFIX=llvm- ..

इस सबको एक साथ रखें आप एक खोल आवरण जो वातावरण चर सेट लिख सकते हैं CCऔर CXXऔर उसके बाद का आह्वान cmakeउल्लेख चर ओवरराइड के साथ।


1
मैंने आपके उत्तर और CMAKE_USER_MAKE_RULES_OVERRIDEकार्यों को छोड़कर सब कुछ का पालन किया है । ऐसा लगता है कि फ़ाइल को अनदेखा किया जा रहा है (यानी ओवरराइड फ़ाइल में CMAKE_C_FLAGS_RELEASEसेट होने के बावजूद -O4, यह -O3 -DNDEBUGcmake में डिफ़ॉल्ट मान दिखा रहा है )।
रिजेइ

18
ध्यान दें कि इस जानकारी का अधिकांश हिस्सा आपके बिल्ड ट्री के शीर्ष स्तर में CMakeCache.txt फ़ाइल में कैश्ड है। Gcc और clang के बीच स्विच करने के लिए, आपके पास दो पूरी तरह से अलग-अलग बिल्ड ट्री होने चाहिए, और कम्पाइलर्स को "स्विच" करने के लिए बस आगे और पीछे cd होना चाहिए। एक बार दिए गए कंपाइलर के साथ एक बिल्ड ट्री उत्पन्न होने के बाद, आप उस बिल्ड ट्री के लिए कंपाइलर को स्विच नहीं कर सकते।
DLRdave 22

@DLRdave दो अलग-अलग बिल्ड पेड़ों का उपयोग करना एक समझदार विचार है; एक जिसे मैंने नहीं माना था। उफ़ :) हालाँकि, एक नई src/build-clangनिर्देशिका में भी ऐसा करने से ओवरराइड को अनदेखा किया जा रहा है।
रिज्जी

1
@Rezzie ClangOverrides.txt में झंडे को प्रत्यय _INIT के साथ परिभाषित किया जाना है। अद्यतन उत्तर देखें।
सकर

8
पाठकों को ध्यान दें। यदि आप सीएमके CCऔर CXXवेरिएबल्स को सम्मानित नहीं करने से परेशान हैं , तो यह इसलिए हो सकता है कि आपको पहले बिल्ड डायरेक्टरी से सभी फाइलों को हटाने की आवश्यकता हो। rm CMakeCache.txtहो सकता है कि शिथिल न हो।
जॉन डिब्लिंग

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

इसके बाद सिर्फ क्लैंग ++ चुनें।


3
धन्यवाद, मुझे इस बारे में पता नहीं था! हालांकि मुझे लगता है कि यह इस बात पर निर्भर करता है कि सेमीकेक एक संकलक की तलाश में है, है ना?
इब्राहिम

1
@ इब्राहिम यह कॉन्फ़िगरेशन आपके द्वारा चुने गए कंपाइलर के लिए "c ++" सिम्लिंक सेट करता है और "c ++" को डिफ़ॉल्ट रूप से चेक करता है, न कि "g ++"। इसलिए जब तक कि सीमेक कॉन्फ़िगरेशन बहुत विशिष्ट नहीं है, यह ठीक काम करना चाहिए (और मेरे लिए करता है)।
जूमलेटर

2
मुझे एक उत्तर मिलता है कि "लिंक ग्रुप सी ++ में केवल एक ही विकल्प है"। कृपया इस सूची में क्लैंग को जोड़ने का तरीका शामिल करने के लिए अपने उत्तर का विस्तार करें
vedant

3
इस विकल्प के साथ सावधान रहें क्योंकि यह आपके सिस्टम के साथ दुष्प्रभाव पैदा कर सकता है। पहले से ही nvidia ड्राइवर जैसे संकुल के साथ समस्या थी जो कि अधिष्ठापन के दौरान कुछ कर्नेल मॉड्यूल को फिर से जोड़ देता है और क्लैंग के साथ संगत नहीं था।
फाल्को

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

और फिर अगर () s में क्लैंग-कंपाइलर सेटिंग्स को लपेटें:

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

इस तरह से यह gui-configuration tools में cmake ऑप्शन के रूप में प्रदर्शित होता है।

इसे प्रणालीबद्ध बनाने के लिए आप निश्चित रूप से एक पर्यावरण चर का उपयोग डिफ़ॉल्ट मान के रूप में कर सकते हैं या फेर्रुकियो के उत्तर के साथ रह सकते हैं।


यही कारण है कि वर्तमान में मैंने इसे स्थापित किया है, लेकिन जाहिर है कि इसे प्रति-परियोजना के आधार पर करने की आवश्यकता है। मैं उम्मीद कर रहा था कि जैसे कोई आदेश होगा cmake -DCMAKE_COMPILER_DEFINITIONS=MyLlvmDefinitions.cmake
रिजेसी

1
अब मुझे समझ में आया कि आप क्या हासिल करना चाहते हैं। मुझे नहीं पता कि यह व्यवहार cmake द्वारा प्रदान किया गया है, लेकिन आप -C विकल्प की कोशिश कर सकते हैं जो CMakeLists.txt चलाने के लिए शुरू करने से पहले स्क्रिप्ट को लोड करने के लिए लगता है। हालांकि यह कोशिश नहीं की है।
तोबियस श्लेगेल

18

उबंटू पर सिस्टम वाइड सी परिवर्तन:

sudo update-alternatives --config cc

उबुन्टु पर सिस्टम चौड़ा C ++ परिवर्तन:

sudo update-alternatives --config c++

उपरोक्त प्रत्येक के लिए, चयन संख्या दबाएं (1) और क्लैंग का चयन करने के लिए दर्ज करें:

  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
यदि आपने अपने क्लैंग को मैन्युअल रूप से स्थापित किया है और इसे एक गैर मानक स्थान पर रखा है, तो यह --config के साथ दिखाई नहीं दे सकता है। उदाहरण के लिए अगर यह /opt/clang-llvm-3.5/पहले है तो एक नया विकल्प स्थापित करें: sudo update-alternatives --install /usr/bin/c++ c++ /opt/clang-llvm-3.5/bin/clang++ 30
कोडकिड

16

आप इस उद्देश्य के लिए cmake के टूलकिन फ़ाइल तंत्र का उपयोग कर सकते हैं, उदाहरण के लिए यहां देखें । आप प्रत्येक कंपाइलर के लिए टूलकिन फ़ाइल लिखते हैं जिसमें संबंधित परिभाषाएँ होती हैं। कॉन्फ़िगर समय पर, आप उदा

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

और सभी कंपाइलर जानकारी टूलचिन फ़ाइल से प्रोजेक्ट () कॉल के दौरान सेट की जाएगी। हालांकि दस्तावेज़ में केवल क्रॉस-संकलन के संदर्भ में उल्लेख है, यह एक ही सिस्टम पर विभिन्न संकलक के लिए भी काम करता है।


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 का आह्वान करेगा जो आप नहीं चाहते हैं (यह संकलन समय को बहुत बढ़ा देगा) और 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_compiler.txt):

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

फिर इसे चलाएं

जीसीसी:

cmake -C gcc_compiler.txt XXXXXXXX

बजना:

cmake -C clang_compiler.txt XXXXXXXX

3

आप सिंटैक्स का उपयोग कर सकते हैं: $ENV{environment-variable}अपने CMakeLists.txtपर्यावरण चर का उपयोग करने के लिए। आप ऐसी स्क्रिप्ट बना सकते हैं जो पर्यावरण चर का एक सेट उचित रूप से शुरू करते हैं और बस आपकी CMakeLists.txtफ़ाइलों में उन चर का संदर्भ देते हैं ।


क्या आप थोड़ा और विस्तृत कर सकते हैं? क्या आपको सेमीक लॉन्च करने से पहले पर्यावरण चर का निर्यात करने के लिए शेल स्क्रिप्ट का मतलब है? कौन से चर सेट करने की आवश्यकता होगी? या आप एक स्क्रिप्ट / उपनाम का मतलब है जो सिर्फ -DCMAKE_C_COMPILER ...आदि के साथ cmake कहते हैं ?
Rezzie

मेरा मतलब एक ऐसी स्क्रिप्ट है जो उचित पर्यावरण चर का निर्यात करती है। आप अपने स्वयं के पर्यावरण चर बनाएंगे और CMakeLists.txt फ़ाइल में उनका संदर्भ लेंगे।
फेर्रुकियो

आह; मुझे पता है तुम्हारा क्या मतलब है। केवल एक चीज यह है कि CMakeLists.txtहर परियोजना के माध्यम से जाने की आवश्यकता होगी और यह नए चर को क्वेरी करेगा। मैं उम्मीद कर रहा था कि किसी भी परियोजना फ़ाइलों को संशोधित किए बिना, इसे सिस्टम-वाइड करने का एक सुविधाजनक तरीका होगा। ए पास करने के समान CMAKE_TOOLCHAIN_FILE
रिज्जी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.