2011-10-28 15 views
7

जैसा कि विषय कहता है, मैं निर्माण के दौरान एक विशिष्ट कमांड चलाने में सक्षम होना चाहता हूं, और इसका आउटपुट प्रीप्रोसेसर मैक्रो की परिभाषा है।एक्सकोड के साथ, कमांड के आउटपुट से प्रीप्रोसेसर मैक्रोज़ को कैसे परिभाषित किया जाए?

अभी, मैं कई उपयोगकर्ता-निर्धारित वैरिएबल नहीं (project.pbxproj में) और मैं, उनके मानों का उपयोग करने के लिए मैक्रो परिभाषाओं को भरने के लिए कर रहा हूँ इस प्रकार है:

GCC_PREPROCESSOR_DEFINITIONS = (
"STRINGIFY (एक्स) = @ # x ",
" _MACRO = STRINGIFY ($ {MACRO}) ",
);
मैक्रो = foo;

मैं मैक्रो को प्रति योजना एक अलग मूल्य (जैसे डीबग बनाम रिलीज) पर सेट कर सकता हूं जो बहुत उपयोगी है। लेकिन, मैं यह नहीं समझ सकता कि कमांड चलाकर इसे कैसे सेट किया जाए।

उत्तर

11

मैं 3 विकल्प के बारे में सोच सकते हैं:

पर्यावरण चर: आप कमांड लाइन से निर्माण यदि आप निर्माण आदेश लागू करने से पहले एक चर (export ENVMACRO=superfoo) निर्यात और एक Xcode विन्यास फाइल OTHER_CFLAGS=-DMACRO=$(ENVMACRO) में इसका इस्तेमाल कर सकते हैं। आपको .xcconfig फ़ाइल के साथ लक्ष्य को कॉन्फ़िगर करने की आवश्यकता है।

रन स्क्रिप्ट बिल्ड चरण: कस्टम स्क्रिप्ट जो हेडर फ़ाइल उत्पन्न करती है।

MACROVALUE=$(run-command-to-obtain-value) 
echo "#define MACRO ($MACROVALUE)" > $(SRCROOT)/path/to/header.h 

मेरे परीक्षणों में आपको ठीक से संकलित करने में सक्षम होने के लिए एक खाली शीर्षलेख फ़ाइल की आवश्यकता है। sed या किसी अन्य कमांड का उपयोग कर मौजूदा फ़ाइल को संशोधित करने जैसे अन्य विकल्प हैं।

कस्टम बिल्ड नियम: कस्टम स्क्रिप्ट जो इनपुट फ़ाइल को संसाधित करती है और आउटपुट फ़ाइल बनाता है। के समान रन स्क्रिप्ट बिल्ड चरण लेकिन थोड़ा बेहतर है क्योंकि यह केवल तब ही स्क्रिप्ट चलाएगा जब इनपुट फ़ाइल संशोधित की गई हो। उदाहरण के लिए, .macro फ़ाइल बनाएं और इसे हेडर फ़ाइल अपडेट करने के लिए संसाधित करें।

एक्सकोड> लक्ष्य> नियम बनाएं, नया कस्टम नियम जोड़ें।

प्रक्रिया: *.macro

कस्टम स्क्रिप्ट:

HEADER="${SRCROOT}/Config.h" 
cd ${SRCROOT} 
echo "// Do not edit" > $HEADER 
cat "${INPUT_FILE_PATH}" | while read line 
do 
    macro="`echo $line | cut -d= -f1`" 
    cmd="`echo $line | cut -d= -f2-`" 
    value=$($cmd) 
    echo "#define ${macro} @\"${value}\"" >> $HEADER 
done 
echo "// Updated on "`date` >> $HEADER 

आउटपुट फ़ाइलों: $(SRCROOT)/Project.h

Project.macro जोड़े MACRO=one-liner-command शामिल हैं।इन दो गैर भावना उदाहरण की तरह:

COMMIT=git log --pretty=format:%h -n 1 
BUILDYEAR=date +%Y 

जनरेट किया गया फ़ाइल तरह दिखेगा:

// Do not edit 
#define COMMIT @"c486178" 
#define BUILDYEAR @"2011" 
// Updated on Sat Oct 29 14:40:41 CEST 2011 

हर बार Project.macro परिवर्तन, उत्पन्न हैडर अद्यतन किया जाएगा।

+0

धन्यवाद - दूसरा विकल्प अनिवार्य रूप से है जो मैंने साथ किया है - मेरे मामले में, मैं चाहता था कि प्रत्येक बिल्ड में कमांड चलाने के लिए। एकमात्र झुर्रियां यह है कि मैं वास्तविक हेडर फ़ाइल पर नहीं लिखता अगर इसकी सामग्री नई जेनरेट की गई सामग्री (निर्भरता परिवर्तन से बचने के लिए) के समान नहीं है। मैं विशेष रूप से तीसरे विकल्प की तरह करता हूं। – michael

0

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

+1

समाधान पर बधाई। अपने उत्तर को 'स्वीकृत' के रूप में चिह्नित करना सुनिश्चित करें ताकि अन्य आपकी सफलता से सीख सकें। चीयर्स ~ –

0

मुझे लगता है कि एक बेहतर समाधान परियोजना का निर्माण सेटिंग में सिर्फ एक पूर्वप्रक्रमक मैक्रो घोषित करने के लिए किया जाएगा (जैसे डिबग के लिए DEBUG, रिहाई के लिए RELEASE) और अपने Prefix.pch में तो फाइल आप तय करने के लिए में मूल्य के लिए जाँच कर सकते हैं परिभाषित करने के लिए अन्य मैक्रोज़, उदाहरण:

// Use NSLOG and NSASSERT so that they are only output in debug mode 
#ifdef DEBUG 

//#warning You are running in Debug mode 
#define NSLOG NSLog 
#define NSASSERT NSAssert 
#define NSASSERT1 NSAssert1 

#else 

#define NSLOG if(false)NSLog 
#define NSASSERT(X, Y) \ 
if(!(X)) {   \ 
NSLogOkay(Y);  \ 
}     
#define NSASSERT1(X, Y, Z) \ 
if(!(X)) {    \ 
NSLogOkay(Y, Z);  \ 
}      

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