2012-07-17 10 views
5

मुझे स्कॉन्स के आधार पर एक बिल्ड सिस्टम को पुन: सक्रिय करने में कोई समस्या है। हमारे पास कई अलग-अलग आउटपुट ऑब्जेक्ट्स (डीएलएस, एक्जिक्यूटिव, टेस्ट एक्जिक्यूटिव) के साथ सी/सी ++ स्रोत पेड़ है, और हमारी स्रोत फ़ाइलों के लिए कुछ हद तक विषम लेआउट है (हालांकि इसमें से अधिकांश 'मॉड्यूल' निर्देशिकाओं में src/ और inc/ निर्देशिकाएं हैं)।स्कोन निर्माण पर्यावरण विरासत

वर्तमान सेटअप के साथ मेरे सबसे बड़े मुद्दों में से एक यह है कि हम वास्तव में इन सभी निर्माण उत्पादों को डिफ़ॉल्ट रूप से लगातार कंपाइलर विकल्पों के साथ निर्मित करना चाहते हैं। हमारे वर्तमान लेआउट में एक मास्टर स्कैनस्ट्रक्चर फ़ाइल है जो उप-निर्देशिकाओं में कई उप-स्कॉन्स्क्रिप्ट फ़ाइलों को बुलाती है जो तब बड़े निर्माण उत्पादों (.a उदाहरण के लिए) के टुकड़े बनाती हैं। डिफ़ॉल्ट रूप से, स्कैन में SConscript() फ़ंक्शन वर्तमान निर्माण पर्यावरण ऑब्जेक्ट को कॉल किया गया है जिसे स्कैनस्ट्रक्चर फ़ाइल कहा जाता है। इसका मतलब है कि वर्तमान में उन सभी उप-स्कैनस्ट्रिप फाइलें अपने स्वयं के विभिन्न निर्माण वातावरण का उपयोग कर रही हैं।

नया लेआउट जो मैं एक साथ रखने की कोशिश कर रहा हूं, उसके पास सभी आवश्यक CFLAGS के साथ स्रोत-वृक्ष रूट पर एक साथ एक मास्टर निर्माण वातावरण रखा जा रहा है और यह परिभाषित करता है कि हमें इसकी आवश्यकता है। मैं इस निर्माण पर्यावरण को सब-स्कॉन्स्क्रिप्ट फाइलों में पारित करना चाहता हूं ताकि मुझे पता चले कि हमारे निर्माण पेड़ में प्रत्येक .c और .cpp फ़ाइल समान कमांड लाइन के साथ बनाई जा रही है।

मुझे यकीन नहीं है कि स्कैन में ऐसा कैसे करें, हालांकि। Import() और Export() फ़ंक्शंस हैं, लेकिन वे मूल रूप से बदसूरत वैश्विक चर हैं - कॉलिंग स्कैनस्ट्रक्चर फ़ाइल में वैश्विक चर के साथ उप-स्कैनस्ट्रक्चर फ़ाइल क्या है, इस पर बहुत अधिक नियंत्रण नहीं है जो Export() 'ed है। क्या अनिवार्य रूप से सब-स्कॉन्स्क्रिप्ट फ़ाइल को मौजूदा निर्माण पर्यावरण को पैरामीटर के रूप में सौंपने का कोई साफ तरीका है, इसे आवश्यक रूप से संशोधित करने के बिना? कुछ हो सकता है की तरह है:

master_env = Environment() 
master_env.Append(CXXFLAGS=['-Wall', '-Werror', '-g', '-fPIC', ... ]) 

### add other stuff that we want everything to use 

SConscript('somelibrary/SConstruct', inherited_environment=master_env.Clone()) 

### master_env has now been used to build a 
### .dll in somelibrary/, but any variations 
### made to somelibrary/SConstruct's inherited 
### env haven't contaminated master_env 

मैं जानता हूँ कि मैं कुछ अनाड़ी और सकल की तरह इस तरह कर सकता है कि:

clobber_env = Environment() 
master_env = Environment() 
master_env.Append(CXXFLAGS=['-Wall', '-Werror', '-g', '-fPIC', ... ]) 

call_somelibrary_sconstruct(master_env) 

def call_somelibrary_sconstruct(env): 
    param_env = env.Clone() 
    Export('param_env') 
    SConstript('somelibrary/SConstruct') 

    # because we don't want any contamination of our global variable 
    # between SConscript calls. I'm not even sure if this is necessary 
    # or does what I think it does because I'm not sure how this ugly 
    # Export()'d global variable environment works with locals like 
    # param_env here. 
    param_env = clobber_env 
    Export('param_env') 

वहाँ ऐसा करने का एक सुंदर तरीका है?

अद्यतन:

तो मैं के साथ इस में कुछ और चारों ओर खेला है, और यह रूप में लंबे समय की तरह लग रहा जैसा कि मैंने मास्टर SConstruct फ़ाइल में ऐसा करते हैं:

def build_somelib(env): 
    Export(env=env.Clone()) 
    somelib = SConscript('somelib/SConscript') 
    return somelib 

master_env = Environment() 
master_env.Append(CXXFLAGS=['-Wall', '-Werror', '-g', '-fPIC', ... ]) 

build_somelib(master_env) 

और फिर somelib/SConscript

में
Import('env') 
env.Append(CXXFLAGS=['-weirdoption1', ... ]) 
lib = env.StaticLibrary('somelib', source=['source1.cpp', 'source2.cpp', ...]) 
Return("lib") 

तब मुख्य स्कैनस्ट्रक्चर में master_env अनियंत्रित छोड़ दिया गया है। मेरे लिए यह महत्वपूर्ण था कि Export(env=env.Clone()) काम करता है क्योंकि मैं सुरक्षा-क्लोन() 'आईएनजी - करने के लिए सभी उप-अनुसूचित जातियों पर भरोसा नहीं करना चाहता था - वह नीति माता-पिता स्कॉन्स्क्रिप्ट/स्कैनस्ट्रक्चर फाइलें होनी चाहिए।

फिर भी, यह नीति के पैरामीटर नाम के रूप में env होने के लिए थोड़ा बदसूरत है।

उत्तर

7

सबसे अच्छा तरीका है मुझे पता है की अपने गुरु SConstruct से है सिर्फ इस कार्य करें:

env = Environment() 

env.SConscript('src/SConscript', 'env') 
फिर अपने src/SConscript फ़ाइल में

:

Import('env') 

तो फिर तुम के रूप में env चर का उल्लेख कर सकते आप अपनी स्कैनस्ट्रक्चर फ़ाइल में करेंगे। आप src/SConscript में SConstruct के env उत्परिवर्तित नहीं करना चाहते, तो आयात के बाद यह सही डाल:

env = env.Clone() 

सुंदर लगता है कि इसके लिए बस इतना ही है।

+0

धन्यवाद टॉम। जोड़ने के लिए एक बात: यदि 'env' जरूरी नहीं है कि दूसरा तर्क, वाक्यविन्यास: 'export =' env'' का उपयोग किया जा सकता है। –

+0

दुर्भाग्यवश, यह अभी भी बाल मॉड्यूल विवेकानुसार क्लोनिंग छोड़ देता है, इसलिए कोई गारंटी नहीं है कि अगला मॉड्यूल ऐसा करेगा। –

1

मैं स्रोत को ग्रीन करता हूं (उबंटू 12.04 में स्कैन 2.1.0) और पता चलता है कि Export अपने कीवर्ड के साथ global_exports शब्दकोश अपडेट करें।

तो यह कोड शायद चलाने होगा:

Export(param_env=env.Clone()) 
SConscript('somelibrary/SConstruct') 
Export(param_env=clobber_env) 

दस्तावेज में के बारे में कुछ भी नहीं है, इसलिए यह एक सुविधा है।

Export और SConstript नाम से परिवर्तनीय प्राप्त करने के लिए फ्रेम जादू का उपयोग करें, भले ही यह उन उपयोगकर्ताओं के लिए अच्छा हो, जो पहले से ही पाइथन नहीं जानते हैं, यह बुरा है।

1

अद्यतन में ओपी द्वारा प्रस्तुत समाधान एक गंभीर मुद्दा (SCons-2.3.3 और SCons-2.3.4 के साथ परीक्षण किया है):

def build_somelib(env): 
    Export(env=env.Clone()) 
    somelib = SConscript('somelib/SConscript') 
    return somelib 

master_env = Environment() 
master_env.Append(CXXFLAGS=['-Wall', '-Werror', '-g', '-fPIC', ... ]) 

build_somelib(master_env) 

उपयोग ऊपर और CacheDir(some_dir) पर बारी (मैं भी प्रयुक्त VariantDir, अगर इससे कोई फर्क पड़ता है)। dir1 में, scons --cache-debug=log का उपयोग करके एक पूर्ण निर्माण करें। निर्माण समाप्त होने के बाद, dir2 में समान कोड के साथ, scons --cache-debug=log का उपयोग करके एक पूर्ण निर्माण भी करें। सभी फाइलों को बिल्ड कैश से कॉपी किया जाना चाहिए, लेकिन मैंने पाया कि विशाल बहुमत की प्रतिलिपि नहीं बनाई जा रही थी। अधिकांश फाइलें, लेकिन सभी नहीं, दोनों निर्देशिकाओं के बीच एमडी 5 हस्ताक्षर विसंगतियां थीं। इस समस्या को 'dir1' में एक फ़ाइल को संशोधित करके और पुनर्निर्माण करके भी ट्रिगर किया जा सकता है, फिर संशोधनों को 'dir2' में कॉपी करके, और पुनर्निर्माण भी किया जा सकता है। आप एक ही एमडी 5 विसंगति देखेंगे।

इस बिंदु पर, scons -c करें और फिर दोनों निर्देशिकाओं में .sconsign.dblite फ़ाइलों को हटाएं (और अच्छी माप के लिए बिल्ड कैश हटाएं)। पहले dir1 में पुनर्निर्माण करें, और जब यह खत्म हो जाए, तो 'dir2' में पुनर्निर्माण करें। आपको सही व्यवहार मिलेगा: एमडी 5 हस्ताक्षर मिलान होंगे और बिल्ड कैश से फ़ाइलों की प्रतिलिपि बनाई जाएगी।

मैं ओपी के समाधान को त्यागना समाप्त कर दिया, और टॉम के समाधान के अनुसार, सभी उपनिर्देशिकाओं में अभिभावक पर्यावरण को संरक्षित करने की ज़िम्मेदारी को स्थानांतरित कर दिया। बिल्कुल वही नहीं जो मैं करना चाहता था, लेकिन कम से कम बिल्ड कैश अब अपेक्षित काम करता है।

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