2012-07-07 23 views
5

मेरा प्रोजेक्ट बिल्ड प्रक्रिया को प्रबंधित करने के लिए स्कॉन्स का उपयोग करता है। मैं एकाधिक कंपाइलर्स का समर्थन करना चाहता हूं, इसलिए मैंने AddOption का उपयोग करने का निर्णय लिया ताकि उपयोगकर्ता निर्दिष्ट कर सकें कि कमांड लाइन पर किस कंपाइलर का उपयोग करना है (डिफ़ॉल्ट रूप से जो भी उनके वर्तमान कंपाइलर है)।यह निर्धारित करने के लिए कि किस कंपाइलर से अनुरोध किया गया था

AddOption('--compiler', dest = 'compiler', type = 'string', action = 'store', default = DefaultEnvironment()['CXX'], help = 'Name of the compiler to use.') 

मैं (जैसे कि विशेष रूप से संकलक के लिए अधिकतम चेतावनी स्तर के रूप में चीजों सहित) विभिन्न compilers के लिए निर्मित संकलक सेटिंग्स के लिए सक्षम होना चाहता हूँ।

if is_compiler('g++'): 
    from build_scripts.gcc.std import cxx_std 
    from build_scripts.gcc.warnings import warnings, warnings_debug, warnings_optimized 
    from build_scripts.gcc.optimizations import optimizations, preprocessor_optimizations, linker_optimizations 
elif is_compiler('clang++'): 
    from build_scripts.clang.std import cxx_std 
    from build_scripts.clang.warnings import warnings, warnings_debug, warnings_optimized 
    from build_scripts.clang.optimizations import optimizations, preprocessor_optimizations, linker_optimizations 

हालांकि, मैं नहीं यकीन है कि तरह is_compiler() समारोह देखो बनाने के लिए क्या कर रहा हूँ: यह क्या वर्तमान में मेरे एक समाधान का पहला प्रयास लग रहा है की तरह है। मेरा पहला विचार था कि उपयोगकर्ता क्या पास करता है उसके खिलाफ संकलक नाम (जैसे 'क्लैंग ++') की तुलना करना सीधे तुलना करना था। हालांकि, scons --compiler=~/data/llvm-3.1-obj/Release+Asserts/bin/clang++ का उपयोग करने का प्रयास करने पर यह तुरंत विफल हो गया।

तो मैंने सोचा कि मैं एक छोटे से बेहतर हो जाते हैं और संकलक स्ट्रिंग के अंत में इस समारोह

cxx = GetOption('compiler') 
def is_compiler (compiler): 
    return cxx[-len(compiler):] == compiler 

यह केवल लग रहा है का उपयोग करें, ताकि यह निर्देशिका ध्यान नहीं देता। दुर्भाग्यवश, 'clang ++' 'g ++' में समाप्त होता है, इसलिए मेरा कंपाइलर clang ++ के बजाय g ++ के रूप में देखा गया था।

मेरा अगला विचार पिछड़ा खोज करना था और पथ विभाजक ('\' या '/') की पहली घटना को देखना था, लेकिन तब मुझे एहसास हुआ कि यह उन लोगों के लिए काम नहीं करेगा जिनके पास एकाधिक कंपाइलर संस्करण हैं । 'G ++ - 4.7' के साथ संकलित कोई भी g ++ होने के रूप में पंजीकृत नहीं होगा।

तो, क्या यह निर्धारित करने का कोई आसान तरीका है कि किस कंपाइलर से अनुरोध किया गया था?

वर्तमान में, केवल सी ++ और क्लैंग ++ समर्थित हैं (और केवल उनके हाल ही में जारी संस्करण) उनके सी ++ 11 समर्थन के कारण, इसलिए एक समाधान जो केवल उन दोनों के लिए काम करता है, अब पर्याप्त होगा। हालांकि, मेरा अंतिम लक्ष्य कम से कम जी ++, क्लैंग ++, आईसीसी, और एमएसवीसी ++ (एक बार जब वे आवश्यक सी ++ 11 फीचर्स का समर्थन करते हैं) का समर्थन करना है, तो अधिक सामान्य समाधान पसंद किए जाते हैं।

+2

मैं यहां दो मुद्दों को अलग कर दूंगा। समस्या # 1) * जो * कंपाइलर से अनुरोध किया गया है और # 2) * जहां * अनुरोधित कंपाइलर स्थित है (इसके लिए आप ज्यादातर समय समझदार डिफ़ॉल्ट का उपयोग कर सकते हैं और केवल उन्हें निर्दिष्ट करने दें यदि वे डिफ़ॉल्ट क्लैंग/जीसीसी/जो कुछ भी)। दो चीजों में आम बात नहीं है, आखिर में मैं आसानी से 'एमएसवीसी' कहलाता हूं जिसे मैं चाहता हूं (वास्तव में कभी कोशिश नहीं की, लेकिन क्यों नहीं?) – Voo

+0

मैं सुझाव के साथ सहमत हूं @Voo ने आपको सुझाव दिया । इसे एक प्रश्न को कम करने के लिए संपादित करें, और उसके बाद एक नया प्रश्न बनाएं। आपके पास दो अच्छे प्रश्न हैं, यही कारण है कि मैंने आपके द्वारा बनाई गई (अब तक) को ऊपर उठाया है। – octopusgrabbus

+0

@Voo अगर आप इसे उत्तर के रूप में लिखते हैं, तो मैं इसे स्वीकार करूंगा, क्योंकि यह उस महत्वपूर्ण अंतर्दृष्टि थी जिसका उपयोग मैंने समस्या को हल करने के लिए किया था। –

उत्तर

1

यह सवाल एक SCons परियोजना है कि इस संभाल कर सकते हैं का विकास हुआ:

https://bitbucket.org/davidstone/scons-template/

प्रासंगिक कोड build_scripts/compiler_settings.py में है। SCons विकल्पों निम्नलिखित लाइनों के साथ SConstruct फ़ाइल में स्थापित कर रहे हैं:

AddOption('--compiler', dest = 'compiler', type = 'string', action = 'store', help = 'Name of the compiler to use.') 
AddOption('--compiler-command', dest = 'compiler_command', type = 'string', action = 'store', help = 'Command to launch the compiler.') 

उपयोगकर्ता 0, 1, या 2 कमांड लाइन विकल्प निर्दिष्ट कर सकते हैं।

यदि आप कुछ भी निर्दिष्ट नहीं करते हैं (scons), तो यह डिफ़ॉल्ट एंटरप्राइज़ से कंपाइलर के साथ बनाता है।

आप वैकल्पिक रूप से कंपाइलर का नाम निर्दिष्ट कर सकते हैं (scons --compiler=g++)। मेरी स्क्रिप्ट तब मानती है कि संकलन करने के लिए उपयोग किया गया आदेश नाम के समान है।

आप वैकल्पिक रूप से संकलित करने के लिए कमांड निर्दिष्ट कर सकते हैं (scons --compiler-command=~/llvm-3.1-obj/Release+Asserts/bin/clang++)। मेरी स्क्रिप्ट तब मान लेती है कि आप जिस कंपाइलर का उपयोग कर रहे हैं उसका नाम निष्पादन योग्य का नाम है (अंतिम निर्देशिका विभाजक के बाद सब कुछ, जैसा कि os.path.basename द्वारा निर्धारित किया गया है)।

आप दोनों निर्दिष्ट कर सकते हैं। यह आपको अजीब परिस्थितियों को संभालने की अनुमति देता है: scons --compiler-command=/path/to/executable/that/is/not/clang++ --compiler=g++

यह निर्धारित करने के लिए नाम का उपयोग करता है कि कौन सी चेतावनियां/अनुकूलन चालू हैं। मैंने नाम के लिए सामान्यीकरण का थोड़ा सा जोड़ा है, ताकि जी ++, जीसीसी और जीसीसी सभी को एक ही चीज़ के रूप में माना जा सके, जहां तक ​​कंपाइलर नाम का संबंध है।

इसमें अभी भी बहुत सारे काम बाकी हैं, जैसे कि अधिक कंपाइलर्स के लिए समर्थन, मिंगव कंपाइलर्स के लिए बेहतर समर्थन, और कंपाइलर संस्करणों का पता लगाने के लिए जो केवल x xy.z + में उपलब्ध झंडे के बेहतर हैंडलिंग की अनुमति देते हैं। यह अच्छा होगा अगर मैं scons --compiler-command=/path/to/gcc-4.7.1 जैसा कुछ कर सकता हूं और यह पता लगाता है कि संकलक मुझे बिना स्पष्ट रूप से बताए जीसीसी है।

हालांकि, इसने ठीक करने के लिए निर्धारित प्रारंभिक समस्या हल कर दी है। इसके लिए मुझे बहुत सारे क्रेडिट को सही रास्ते पर रखने के लिए टिप्पणियों में वू जाना है।

1

आप केवल here निर्दिष्ट अनुसार पाइथन os.path.basename() या os.path.split() फ़ंक्शंस का उपयोग कर सकते हैं।

आप इस सवाल को 2 अलग-अलग मुद्दों में विभाजित करके टिप्पणियों में सुझाव दे सकते थे, लेकिन मुझे लगता है कि संकलक के साथ पथ निर्दिष्ट करने में सक्षम होना एक अच्छा विचार हो सकता है, क्योंकि आपके पास g ++ के 2 संस्करण हो सकते हैं स्थापित, और यदि उपयोगकर्ता केवल g ++ निर्दिष्ट करता है, तो उन्हें अपेक्षित संस्करण नहीं मिल सकता है।

2

कंपाइलर बस निर्माण प्रक्रिया का हिस्सा हैं। इसके अलावा आपको लिंकर टूल की आवश्यकता है और अन्य अतिरिक्त प्रोग्राम भी हो सकते हैं। स्कैन में इसका नाम है - टूल। from box समर्थित टूल की सूची आप man page में देख सकते हैं, कथन द्वारा खोजें: SCons supports the following tool specifications out of the box: ... टूल आवश्यक स्कैन पर्यावरण चर सेट करता है, यह here दस्तावेज है।

स्कैन स्वचालित रूप से ओएस में कंपाइलर का पता लगाता है और उनमें से किसी एक को चुनने के लिए कुछ प्राथमिकता है, निश्चित रूप से ऑटोडेटेक्ट सही ढंग से काम करेगा यदि पाथ चर आवश्यक डीआईआरएस पर सेट हो। उदाहरण के लिए आपके पास विंडोज़ पर एमएसवीसी और मिंगव है, स्कैन एमएसवीसी उपकरण का चयन करें। उपकरण उपयोग उपकरण ('नाम') (एनवी) का उपयोग कर बल के लिए। उदाहरण के लिए:

env = Environment() 
Tool('mingw')(env) 

अब env मिंगव का उपयोग करके बल।

तो, क्लैंग उपकरण में से एक है जो वर्तमान में स्कैन द्वारा from box समर्थित नहीं है। आपको इसे कार्यान्वित करने की आवश्यकता है, या ऐसे सीसी, सीईओसी env vars सेट करें जो जेनर बिल्ड कमांड के लिए स्कोन का उपयोग करते हैं।

संबंधित मुद्दे

 संबंधित मुद्दे