2016-03-22 6 views
10

हमने हाल ही में GCC 5.1, libstdc++ and Dual ABI की एक रिपोर्ट पकड़ी है। ऐसा लगता है कि Clang is not aware of the GCC inline namespace changes है, इसलिए यह नामस्थानों या प्रतीकों के एक सेट के आधार पर कोड उत्पन्न करता है, जबकि जीसीसी ने नामस्थानों या प्रतीकों का एक और सेट उपयोग किया है। लिंक समय पर, गायब प्रतीकों के कारण समस्याएं हैं।abi :: cxx11 के साथ प्रतीकों के कारण समस्याओं को जोड़ना?

यदि मैं Dual ABI पृष्ठ को सही ढंग से पार्स कर रहा हूं, तो यह कुछ अतिरिक्त कठिनाइयों के साथ _GLIBCXX_USE_CXX11_ABI और abi::cxx11 पर पिवोटिंग की बात की तरह दिखता है। अधिक पढ़ना Red Hat के ब्लॉग पर GCC5 and the C++11 ABI और The Case of GCC-5.1 and the Two C++ ABIs पर उपलब्ध है।

नीचे उबंटू 15 मशीन से है। मशीन जीसीसी 5.2.1 प्रदान करता है।

$ cat test.cxx 
#include <string> 

std::string foo __attribute__ ((visibility ("default"))); 
std::string bar __attribute__ ((visibility ("default"))); 

$ g++ -g3 -O2 -shared test.cxx -o test.so 

$ nm test.so | grep _Z3 
... 
0000201c B _Z3barB5cxx11 
00002034 B _Z3fooB5cxx11 

$ echo _Z3fooB5cxx11 _Z3barB5cxx11 | c++filt 
foo[abi:cxx11] bar[abi:cxx11] 

मैं दोनों सजावट का उपयोग कर ("सह-अस्तित्व" रेड हैट ब्लॉग यह कहता है के रूप में) प्रतीकों के साथ एक द्विआधारी कैसे बना सकता है?

या, हमारे लिए कौन से विकल्प उपलब्ध हैं?


मैं उपयोगकर्ताओं के लिए "यह सिर्फ काम करता है" प्राप्त करने की कोशिश कर रहा हूं। मुझे कोई परवाह नहीं है कि दो अलग-अलग व्यवहार हैं (std::string में कॉपी-ऑन-राइट की कमी है, जबकि std::string[abi:cxx11] कॉपी-ऑन-राइट प्रदान करता है)। या, एक दूसरे के लिए उपनाम हो सकता है।

डेबियन में Debian Bug report logs: Bugs tagged libstdc++-cxx11 पर समान बग का बोतलबंद है। उनका समाधान नई एबीआई के तहत सबकुछ पुनर्निर्माण करना था, लेकिन यह एबीआई परिवर्तनों के मिश्रण/मिलान करने वाले कंपाइलर्स मॉड्यूल के कोने मामले को संभाल नहीं पाया।

ऐप्पल दुनिया में, मुझे लगता है कि यह एक वसा बाइनरी के करीब है। लेकिन मुझे यकीन नहीं है कि लिनक्स/जीसीसी दुनिया में क्या करना है। अंत में, हम इस बात पर नियंत्रण नहीं करते कि डिस्ट्रो लाइब्रेरी का निर्माण कैसे करता है, और हम नियंत्रित नहीं करते कि लाइब्रेरी के साथ अनुप्रयोगों को जोड़ने के लिए कौन से कंपाइलर्स का उपयोग किया जाता है।

+0

आपका उत्पाद क्या है? एक पुस्तकालय या एक कार्यक्रम? –

+0

@ एनएम। - उत्पाद वेई दाई [क्रिप्टो ++] (http://www.cryptopp.com/) है। इसकी एक सी ++ लाइब्रेरी है। यह डेबियन द्वारा निर्मित और distro के हिस्से के रूप में आपूर्ति की। – jww

उत्तर

3

ऐसा करने का एक तरीका यहां है, लेकिन यह बहुत ही सुरुचिपूर्ण नहीं है। यह मुझे स्पष्ट नहीं है कि जीसीसी को स्वचालित कैसे करें ताकि मुझे दो बार चीजें न करें।

पहले, उदाहरण है कि एक पुस्तकालय में तब्दील किया जा रहा है:

$ cat test.cxx 
#include <string> 

std::string foo __attribute__ ((visibility ("default"))); 
std::string bar __attribute__ ((visibility ("default"))); 

तब:

$ g++ -D_GLIBCXX_USE_CXX11_ABI=0 -c test.cxx -o test-v1.o 
$ g++ -D_GLIBCXX_USE_CXX11_ABI=1 -c test.cxx -o test-v2.o 

$ ar cr test.a test-v1.o test-v2.o 
$ ranlib test.a 

$ g++ -shared test-v1.o test-v2.o -o test.so 

अंत में, देखने के लिए हम क्या मिला:

$ nm test.a 

test-v1.o: 
00000004 B bar 
     U __cxa_atexit 
     U __dso_handle 
00000000 B foo 
0000006c t _GLOBAL__sub_I_foo 
00000000 t _Z41__static_initialization_and_destruction_0ii 
     U _ZNSsC1Ev 
     U _ZNSsD1Ev 

test-v2.o: 
     U __cxa_atexit 
     U __dso_handle 
0000006c t _GLOBAL__sub_I__Z3fooB5cxx11 
00000018 B _Z3barB5cxx11 
00000000 B _Z3fooB5cxx11 
00000000 t _Z41__static_initialization_and_destruction_0ii 
     U _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1Ev 
     U _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEED1Ev 

और:

$ nm test.so 

00002020 B bar 
00002018 B __bss_start 
00002018 b completed.7181 
     U [email protected]@GLIBC_2.1.3 
     w [email protected]@GLIBC_2.1.3 
00000650 t deregister_tm_clones 
000006e0 t __do_global_dtors_aux 
00001ef4 t __do_global_dtors_aux_fini_array_entry 
00002014 d __dso_handle 
00001efc d _DYNAMIC 
00002018 D _edata 
00002054 B _end 
0000087c T _fini 
0000201c B foo 
00000730 t frame_dummy 
00001ee8 t __frame_dummy_init_array_entry 
00000980 r __FRAME_END__ 
00002000 d _GLOBAL_OFFSET_TABLE_ 
000007dc t _GLOBAL__sub_I_foo 
00000862 t _GLOBAL__sub_I__Z3fooB5cxx11 
     w __gmon_start__ 
000005e0 T _init 
     w _ITM_deregisterTMCloneTable 
     w _ITM_registerTMCloneTable 
00001ef8 d __JCR_END__ 
00001ef8 d __JCR_LIST__ 
     w _Jv_RegisterClasses 
00000690 t register_tm_clones 
00002018 d __TMC_END__ 
00000640 t __x86.get_pc_thunk.bx 
0000076c t __x86.get_pc_thunk.dx 
0000203c B _Z3barB5cxx11 
00002024 B _Z3fooB5cxx11 
00000770 t _Z41__static_initialization_and_destruction_0ii 
000007f6 t _Z41__static_initialization_and_destruction_0ii 
     U [email protected]@GLIBCXX_3.4 
     U [email protected]@GLIBCXX_3.4 
     U [email protected]@GLIBCXX_3.4.21 
     U [email protected]@GLIBCXX_3.4.21 
5

अस्वीकरण, निम्नलिखित उत्पादन में परीक्षण नहीं किया गया है, अपने जोखिम पर उपयोग करें।

आप अपने पुस्तकालय को दोहरी एबीआई के तहत जारी कर सकते हैं। यह ओएसएक्स "वसा बाइनरी" के समान या कम है, लेकिन पूरी तरह से सी ++ के साथ बनाया गया है।

ऐसा करने का सबसे आसान तरीका लाइब्रेरी को दो बार संकलित करना होगा: -D_GLIBCXX_USE_CXX11_ABI=0 और -D_GLIBCXX_USE_CXX11_ABI=1 के साथ।मैक्रो के मूल्य के आधार दो अलग नामस्थान के तहत पूरी लाइब्रेरी रखें:

#if _GLIBCXX_USE_CXX11_ABI 
# define DUAL_ABI cxx11 __attribute__((abi_tag("cxx11"))) 
#else 
# define DUAL_ABI cxx03 
#endif 

namespace CryptoPP { 
    inline namespace DUAL_ABI { 
    // library goes here 
    } 
} 

अब अपने उपयोगकर्ताओं CryptoPP::whatever हमेशा की तरह उपयोग कर सकते हैं, यह या तो CryptoPP::cxx11::whatever या CryptoPP::cxx03::whatever ABI चयनित के आधार पर करने के लिए मैप करता है।

नोट, जीसीसी मैनुअल का कहना है कि यह विधि टैग की गई इनलाइन नेमस्पेस में परिभाषित सब कुछ के उलझन वाले नामों को बदल देगी। मेरे अनुभव में ऐसा नहीं होता है।

अन्य विधि __attribute__((abi_tag("cxx11"))) के साथ प्रत्येक वर्ग, फ़ंक्शन और चर टैगिंग होगी यदि _GLIBCXX_USE_CXX11_ABI nonzero है। यह गुण अच्छी तरह से demangler के आउटपुट में [cxx11] जोड़ता है। मुझे लगता है कि नामस्थान का उपयोग करना ठीक उसी तरह काम करता है, और मौजूदा कोड में कम संशोधन की आवश्यकता है।

सिद्धांत रूप में आप पूरे पुस्तकालय, केवल कार्य करता है और कक्षाएं कि std::string और std::list, का उपयोग करें और कार्य करता है और कक्षाएं कि इन कार्य करता है और कक्षाएं, और इतने पर पुनरावर्ती का उपयोग नकल करने की जरूरत नहीं है। लेकिन व्यावहारिक रूप से यह संभवतः प्रयास के लायक नहीं है, खासकर अगर पुस्तकालय बहुत बड़ा नहीं है।

+0

धन्यवाद @ एनएम। साझा वस्तु गैर-जागरूक कंपाइलरों के लिए समस्याग्रस्त है, जैसे वर्तमान क्लैंग। साझा ऑब्जेक्ट जागरूक कंपाइलर्स के लिए ठीक है। गैर-जागरूक कंपाइलरों के लिए, साझा ऑब्जेक्ट को 'CryptoPP :: cxx11 :: जो भी' और' CryptoPP :: cxx03 :: जो कुछ भी 'दोनों के लिए प्रतीकों की आवश्यकता होती है। जैसा कि आप वर्णन करते हैं, हेडर में सामान ठीक होना चाहिए। मैं अभी भी गड़बड़ कर रहा हूं यह देखने के लिए कि गैर-जागरूक कंपाइलर्स की मदद करने के लिए क्या किया जा सकता है। – jww

+0

"साझा ऑब्जेक्ट को क्रिप्टोपीपी :: cxx11 दोनों के लिए प्रतीकों की आवश्यकता है :: जो कुछ भी और CryptoPP :: cxx03 :: जो कुछ भी" हाँ मैं यही कह रहा हूं। आप एक ही पुस्तकालय में दोनों संस्करणों को गठबंधन करते हैं। –

+0

यदि आप abi_tag से अनजान क्लैंग या अन्य कंपाइलर्स का समर्थन करना चाहते हैं, तो बस '__attribute __ ((abi_tag (" cxx11 ")) का उपयोग न करें। –

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