2010-02-24 11 views
6

मुझे एक ताजा ओएसएक्स 10.4.11 + एक्सकोड 2.5 स्थापना में एक बेहद अजीब समस्या का सामना करना पड़ रहा है। मैंने इसे कम से कम टेस्ट केस में घटा दिया है। यहाँ test.cpp है:g ++ रहस्यमय रूप से विफल रहता है अगर एक .h एक निश्चित निर्देशिका में है

#include "macros.h" 

int main (void) 
{ 
    return 1; 
} 

और यहाँ macros.h है:

#ifndef __JUST_TESTING__ 
#define __JUST_TESTING__ 

template<typename T> void swap (T& pT1, T& pT2) 
{ 
    T pTmp = pT1; 
    pT1 = pT2; 
    pT2 = pTmp; 
} 

#endif //__JUST_TESTING__ 

यह संकलित करता है तथा बस ठीक काम करता है अगर दोनों फ़ाइलें एक ही निर्देशिका में कर रहे हैं। हालांकि, अगर मैं में macros.h डाल/usr// gfc2 में शामिल हैं (यह मैं का उपयोग एक कस्टम पुस्तकालय का हिस्सा है) और test.cpp में #include बदलने के लिए, संकलन इस त्रुटि के साथ विफल:

/usr/include/gfc2/macros.h:4: error: template with C linkage 

मैं शोध किया वह त्रुटि और अधिकांश टिप्पणियां "लटकते बाहरी सी" को इंगित करती हैं, जो कि बिल्कुल भी प्रतीत नहीं होती है।

मैं यहां एक पूर्ण नुकसान पर हूं। क्या किसी कारण से g ++ /usr/include/gfc2 में सब कुछ मानने के लिए है, भले ही यह एक .cpp फ़ाइल से शामिल है जो बाहरी "सी" कहीं भी नहीं कहता है?

कोई भी विचार?

संपादित करें: अगर मैं #include में पूर्ण पथ का उपयोग यह संकलित करता है, यानी #include "/usr/include/gfc2/macros.h"

EDIT2: यह गलत हैडर सहित नहीं है। मैं प्रमाणित कर चुके हैं इस cpp, g++ -E, और नाम बदलने macros.hfoobarmacros.h

+0

यह कुल, निराशाजनक, अनौपचारिक मिलियन-टू-वन-इन-द-डार्क है, लेकिन निर्देशिका नाम से "सी" को हटाने का प्रयास करें। :) – datageist

+0

"set | grep -i शामिल" के परिणामों को पोस्ट करने का प्रयास करें। –

+0

@datageist - धन्यवाद, लेकिन इससे कोई फर्क नहीं पड़ता। विचित्र रूप से पर्याप्त, यह संकलित करता है अगर मैं इसे अपने पूर्ण पथ का उपयोग करके शामिल करता हूं। हमम ... – ggambett

उत्तर

7

जी ++ अच्छी तरह से वास्तव में यह सोचते हैं हो सकता है कि हर चीज में/usr/शामिल सी पूर्वप्रक्रमक उत्पादन में ई के साथ अपने कोड संकलन और लाइन मार्कर का अध्ययन कर प्रयास करें है:

g++ -E test.cpp | grep '^#' 

आप की संभावना बातें देखेंगे जैसे

# 1 "/usr/include/gfc2/macros.h" 1 3 4 

4 पूर्वप्रक्रमक ++ जी को इशारा है कि यह extern "C" में सब कुछ लपेटो चाहिए, अनुमान पर है कि अपने मंच के प्राचीन हेडर फाइल में/usr/शामिल से पहले बन सी ++। सीपीपी मैनुअल में Preprocessor Output देखें।

इन दिनों जी ++ ज्यादातर इस संकेत को अनदेखा करते हैं, क्योंकि अधिकांश प्लेटफ़ॉर्म 'सी हेडर अब प्राचीन नहीं होते हैं। जीसीसी आंतरिक मैनुअल में NO_IMPLICIT_EXTERN_C लक्ष्य मैक्रो देखें। लेकिन हो सकता है कि एक्सकोड के इस पुराने संस्करण में जीसीसी को NO_IMPLICIT_EXTERN_C के बिना कॉन्फ़िगर किया गया है और इस प्रकार प्रीप्रोसेसर के संकेत को सुन रहा है। (यह सेट किया गया है जब जीसीसी स्वयं बनाया गया है - मुझे नहीं लगता कि इसे ओवरराइड करने के लिए कमांड लाइन स्विच है।)

आप extern "C++" में अपनी हेडर फ़ाइल की सामग्री को लपेटकर इस पर काम करने में सक्षम हो सकते हैं।

+0

संयोग से मुझे यह धागा मिला था, जो अनिवार्य रूप से वही कहता है जो आप कहते हैं: http://www.pixelglow.com/lists/archive/macstl-dev/2005- फरवरी /000015.html तो ऐसा लगता है कि यह एक कंपाइलर है " सुविधा "सब के बाद। यह एक राहत है, हालांकि मैं पागल हो रहा था! – ggambett

+0

यह भी देखें http://www.cocoabuilder.com/archive/xcode/247374-headers-in-usr-include.html#247468 – ggambett

+0

वह http://www.cocoabuilder.com/archive/xcode/247374-headers- in-usr-include.html लिंक दिलचस्प है: उसे 'बाहरी "सी ++" 'के साथ सफलता मिली है (और यह वास्तव में मानक है: 7.5/3 देखें); और जब उन्होंने सभी '# XX' संदर्भों पर टिप्पणी की, तो वह वास्तव में वास्तव में क्या कर रहा था, सभी प्रीप्रोसेसर के' 4' संकेतों को मिटा रहा था। यह वास्तव में उपयोगी * फीचर * है जब जीसीसी को टूटी सी-हेडर हेडर के साथ एक अनजान विक्रेता के मंच पर पोर्ट किया जाता है। हाँ, मैं कड़वी अनुभव से बात करता हूँ! हालांकि वास्तविक जवाब सिस्टम हेडर को ठीक करना और 'NO_IMPLICIT_EXTERN_C' पर स्विच करना है, जैसा कि ऐप्पल ने तब से किया है। –

0

खैर के लिए उपयोग कर, यह वास्तव में अजीब लग रहा है ...

XCode कैसे कहता है जी ++? मुझे नहीं लगता कि g ++ स्वचालित रूप से निर्णय लेता है कि एक फ़ाइल में सी लिंकेज है क्योंकि यह एक अलग निर्देशिका में है। क्या आपने अपनी परियोजना को हाथ से संकलित करने का प्रयास किया था? "g ++ main.cpp-I/usr/include/gfc2 /" का प्रयास करें। यदि यह आपकी समस्या को हल करता है तो यह g ++ नहीं है। शायद एक्सकोड प्रीकंपाइल हेडर करता है?

+0

मैं वास्तव में कमांड लाइन कंपाइलर का उपयोग कर रहा हूं, अधिक सटीक g ++ -o test test.cpp – ggambett

+0

क्या आपने "macros.h" को "macros.hpp" का नाम बदलने का प्रयास किया था? – neverlord

+0

हाँ। वही त्रुटि :( – ggambett

0

आप बिल्कुल test.cpp फ़ाइल को नहीं बदलते कोशिश की, लेकिन इसके बजाय जब आप भी संकलन कहते हैं:

-I/usr/include/gfc2/ 
+0

धन्यवाद!यह काम करता है, लेकिन मैं इसे "वर्कअराउंड" श्रेणी में डाल दूंगा। मैं मूल कारण को ठीक करता हूं, क्योंकि यह सटीक कोड लिनक्स, मैक और विंडोज में हमेशा के लिए काम कर रहा है, इसलिए मुझे पूरा यकीन है कि यह इस विशेष स्थापना के साथ एक समस्या है। – ggambett

+0

(पूर्णता के लिए,) यह कारण यह है कि हेडर अब विशेष रूप से अंतर्निहित '/ usr/include' के बजाय इस विकल्प में नामित सामान्य निर्देशिका से आ रहा है। चूंकि हेडर किसी विशेष निर्देशिका से नहीं है, इसलिए प्रीप्रोसेसर अपने लाइन मार्करों पर '4' झंडे नहीं डालता है, इसलिए जी ++ इसे 'बाहरी' सी '' में लपेटने के लिए लुभाने वाला नहीं है। (इन झंडे के स्पष्टीकरण के लिए उपरोक्त मेरा उत्तर देखें।) –

1

यह अंधेरे में एक शॉट कहीं /usr/include तहत macros.h नामक एक अन्य फ़ाइल है, लेकिन है वहाँ या आपके जीसीसी स्थापना में? जीसीसी में हेडर को लपेटने की सुविधा है, जिसे #include_next कहा जाता है, जो आपकी समस्या का कारण हो सकता है।

एक बात आप कर सकते हैं को स्पष्ट करने के लिए अपने macros.h शामिल रास्ते में किसी अन्य macros.h से gfc2/macros.h के रूप में यह शामिल करने के लिए है। इस प्रकार, संकलक gfc2 नामक एक उपनिर्देशिका के लिए पथ शामिल करने में प्रत्येक निर्देशिका को खोजेगा जिसमें macros.h नाम की एक फ़ाइल शामिल है, जो टकराव की संभावना को कम करती है। यह आपको पथ शामिल करने के लिए /usr/include/gfc2 जोड़ने से रोकता है।

बीटीडब्ल्यू, #include "file.h" पहले वर्तमान निर्देशिका की खोज करता है। कि छोड़ सकते हैं और शामिल पथ पर सीधे जाने के लिए, #include <file.h> का उपयोग करें:

#include <stdio.h> 
#include <gfc2/macros.h> 

एक और दृष्टिकोण एक फ़ाइल नाम है कि और अधिक, अद्वितीय होना gfc2macros.h की तरह होने की संभावना है चुनने के लिए है।

+0

मैंने इसके बारे में भी सोचा, लेकिन सीपीपी का आउटपुट पुष्टि करता है कि g ++ सही macros.h खींच रहा है (इस तथ्य के अलावा कि त्रुटि संदेश में मेरी फ़ाइल का पूरा पथ है)।/Usr/include में कोई अन्य macros.h नहीं हैं। – ggambett

+0

क्या आपने 'cpp' चलाया था या आपने 'g ++ -E' चलाया था? g ++ डिफ़ॉल्ट रूप से निर्देशिका में निर्देशिका जोड़ सकता है, इसलिए परिणाम समान नहीं हो सकता है। – bk1e

0

आप देख सकते हैं, जहां ग्राम ++ की तलाश में है वर्बोज़ ध्वज के साथ शामिल हैं:

g++ -v -o test test.cpp 

और यह सिर्फ पूर्वप्रक्रमक चलाने के लिए और दिखाने के क्या वास्तव में फ़ाइल में शामिल और संकलित किया गया है जाएगा:

g++ -E test.cpp | less 

यदि गलत फाइलें शामिल हो रही हैं (या आपका हेडर दूसरे में लपेटा जा रहा है, क्योंकि बीके 1 ई सुझाव देता है) तो आप उस आउटपुट के साथ पता लगा पाएंगे।

+0

मुझे नहीं पता था- ई। इस मामले में जी ++ -E का आउटपुट सीपीपी जैसा ही है। – ggambett

0

मैं सी ++ प्रोजेक्ट को संकलित करते समय भी इस मुद्दे में भाग गया था जिसे हम आम तौर पर 10.5 पीपीसी मशीन पर 10.5 और 10.6 (एक्सकोड 3.0+) पर एक्सकोड 2.5 स्थापित करते हैं। ऐसा लगता है कि प्रीप्रोसेसर जीसीसी में जोड़े गए कुछ भी व्यवहार करता है जिसमें 'सिस्टम सिस्टम' के साथ पथ शामिल है जैसे कि यह "बाहरी सी" होना चाहिए। '-इसिस्टम' को '-आई' में बदलना इस मुद्दे को हल करता है।

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