निर्भरता के साथ गतिशील पुस्तकालय के साथ जोड़ना


79

इस परिदृश्य पर विचार करें:

  • साझा पुस्तकालय libA.so, कोई निर्भरता के साथ।
  • साझा पुस्तकालय libB.so, libA.so के साथ इसकी निर्भरता के रूप में।

मैं एक बाइनरी फ़ाइल संकलित करना चाहता हूं जो कि libB के साथ लिंक करती है। क्या मुझे बाइनरी को केवल libB के साथ या liba के साथ जोड़ना चाहिए?

क्या केवल प्रत्यक्ष निर्भरता के साथ लिंक करने का कोई तरीका है, जिससे रनटाइम के लिए निर्भरता से अनसुलझे प्रतीकों का समाधान हो सके?

मैं इस तथ्य के बारे में चिंतित हूं कि भविष्य में पुस्तकालय libB कार्यान्वयन बदल सकता है, उदाहरण के लिए अन्य निर्भरताएं (libC, libD, libE)। क्या मुझे इससे कोई समस्या है?

दूसरे शब्दों में:

  • libA फ़ाइलें: a.cpp आह
  • libB फाइलें: b.cpp bh
  • मुख्य कार्यक्रम की फाइलें: main.cpp

बेशक, b.cpp में आह शामिल है और main.cpp में bh शामिल है

संकलन आदेश:

मुझे किस विकल्प का उपयोग करना चाहिए?

या

मैं पहले विकल्प का उपयोग नहीं कर सका। लिंकर पुस्तकालय लायब्रेरी से अनसुलझे प्रतीकों के बारे में शिकायत करता है। लेकिन यह मुझे थोड़ा अजीब लगता है।

बहुत बहुत धन्यवाद।

- अद्यतित टिप्पणियाँ:

जब मैं बाइनरी लिंक करता हूं, तो लिंकर मुख्य और libB से सभी प्रतीकों को हल करने का प्रयास करेगा। हालांकि, libB ने liba से अपरिभाषित प्रतीक हैं। इसलिए लिंकर उस बारे में शिकायत करता है।

इसलिए मुझे लिबास से भी जुड़ना होगा। हालाँकि मुझे साझा पुस्तकालयों से अनसुलझे प्रतीकों को अनदेखा करने का एक तरीका मिला। ऐसा लगता है कि मुझे निम्नलिखित कमांड लाइन का उपयोग करना चाहिए:

ऐसा लगता है कि -rpathविकल्प का उपयोग करना अभी भी संभव है । हालांकि मुझे इसे थोड़ा बेहतर समझने की जरूरत है।

क्या कोई -Wl,-unresolved-symbols=ignore-in-shared-libsविकल्प का उपयोग करते समय किसी भी संभावित नुकसान को जानता है?

- अपडेट किया गया 2:

-rpathइस उद्देश्य के लिए उपयोग नहीं किया जाना चाहिए। किसी दिए गए डायरेक्टरी में लाइब्रेरी को खोजने के लिए बाध्य करना उपयोगी है। -unresolved-symbolदृष्टिकोण बहुत बेहतर लग रहा है।

एक बार फिर धन्यवाद।


यहाँ इस तरह के सामान को
परखने की चाह

जवाबों:


42

ऐसा लगता है कि आप पहले से ही वहां सबसे ज्यादा हैं। अच्छी तरह से अपनी जांच के साथ किया। देखते हैं कि क्या मैं इसके पीछे 'क्यों' को स्पष्ट करने में मदद कर सकता हूं।

यहाँ लिंकर क्या कर रहा है। जब आप अपने निष्पादन योग्य ('मुख्य' को ऊपर) से जोड़ते हैं तो इसमें कुछ चिन्ह (कार्य और अन्य चीजें) होते हैं जो अनसुलझे होते हैं। यह उन पुस्तकालयों की सूची को देखेगा, जो अनसुलझे प्रतीकों को सुलझाने की कोशिश कर रहे हैं। साथ ही, यह पाता है कि कुछ प्रतीकों को libB.so द्वारा प्रदान किया गया है, इसलिए यह नोट करता है कि वे अब इस पुस्तकालय द्वारा हल किए गए हैं।

हालांकि, यह भी पता चलता है कि उन प्रतीकों में से कुछ अन्य प्रतीकों का उपयोग करते हैं जो अभी तक आपके निष्पादन योग्य में हल नहीं किए गए हैं, इसलिए इसे अब उन लोगों को भी हल करने की आवश्यकता है। LibA.so के खिलाफ लिंक के बिना, आपका आवेदन अधूरा होगा। एक बार जब यह libA.so के खिलाफ लिंक हो जाता है, तो सभी प्रतीकों को हल कर दिया जाता है और लिंकिंग पूरा हो जाता है।

जैसा कि आपने देखा, का उपयोग -unresolved-symbols-in-shared-libs, समस्या को ठीक नहीं करता है। यह सिर्फ इतना है कि उन प्रतीकों को चलाने के समय में हल कर रहे हैं की रक्षा करता है। इसके लिए यही -rpathहै: पुस्तकालयों को चलाने के लिए निर्दिष्ट किया जाए। यदि उन प्रतीकों को हल नहीं किया जा सकता है, तो आपका ऐप शुरू करने में विफल रहेगा।

लाइब्रेरी की निर्भरता का पता लगाना आसान बात नहीं है क्योंकि एक प्रतीक को एक से अधिक लाइब्रेरी द्वारा प्रदान किया जा सकता है और उनमें से किसी एक के खिलाफ लिंक करके संतुष्ट किया जा सकता है।

इस प्रक्रिया का एक और विवरण यहां दिया गया है: क्यों जिस क्रम में पुस्तकालयों को जोड़ा जाता है वह क्रम कभी-कभी जीसीसी में त्रुटियों का कारण बनता है?


2
मुझे पता है कि यह बहुत समय पहले था, मैं इसे हल करना भूल गया। आपके उत्तर के लिए बहुत बहुत धन्यवाद।]
मार्कस

अद्भुत सवाल के लिए धन्यवाद दोस्तों, और एक शानदार जवाब! मेरा भी लगभग यही हाल है। मैं एक साझा साझा ऑब्जेक्ट में ओपनसीवी साझा की गई वस्तुओं को लपेटने की कोशिश कर रहा हूं। चलो कहते हैं कि C.so मेरा रिवाज है, और CV.so कुछ ओपनसीवी है। मैंने सफलतापूर्वक C.so को CV.so के विरुद्ध लिंक किया है, और मैं C.so के खिलाफ एक main.cpp (आप इसे प्राप्त करता हूं!) लिंक करना चाहता हूं, लेकिन बात यह है कि C.so से वस्तुओं का उपयोग करने के अलावा, main.cpp एक का उपयोग करता है ऑब्जेक्ट 'cv :: Mat' जिसे CV.so में परिभाषित किया गया है। इस मामले में main.cpp चलाने के लिए मुझे C.so और CV.so दोनों के खिलाफ लिंक करने की आवश्यकता है ?? मुझे अच्छा लगेगा अगर कोई इस पर प्रकाश डाले। धन्यवाद! :)
लेनी लिनुस

2
जब libB.so का उत्पादन होता है तो लिंकर सभी आवश्यक libA.so प्रतीकों का समाधान नहीं करता है? मुख्य आवेदन को लिवा से लिंक नहीं करना चाहिए क्योंकि यह पारदर्शी होना चाहिए, जैसे कि अप्रत्यक्ष रूप से परिवाद द्वारा परिरक्षित?
विल्सन

यह गलत है। लिंकर अधूरा निर्भरता श्रृंखला के एक उपयोगकर्ता को सूचित करने के अलावा libA.so के अलावा कोई उपयोग नहीं करता है। LibA.so प्रदान किए बिना, लेकिन -unresolved-प्रतीकों = अनदेखी-साझा-लिबास को पार करने के बजाय आपको वही सटीक निष्पादन योग्य मिलेगा।
listerreg

21

केवल प्रत्यक्ष निर्भरता के साथ डायनामिक लिंकिंग के लिए आप बाद-Wl,--as-needed में लिबास जोड़ने के साथ उपयोग कर सकते हैं : -Wl,--as-needed

प्रत्यक्ष निर्भरता की जाँच करने के लिए आपको ldd के बजाय readelf का उपयोग करना चाहिए क्योंकि ldd भी अप्रत्यक्ष निर्भरता को दर्शाता है।

ldd भी अप्रत्यक्ष निर्भरता दिखाता है:

यदि आप cmake का उपयोग करते हैं , तो आप केवल प्रत्यक्ष निर्भरता को शामिल करने के लिए निम्नलिखित पंक्तियों को जोड़ सकते हैं:


क्षमा करें, मैंने आपका उदाहरण c ++ के बजाय c प्रोग्रामम के रूप में बनाया है। इसलिए मैंने gcc कंपाइलर का उपयोग किया। लेकिन यह g ++ के साथ भी काम करता है।
user1047271

1
यह वास्तव में उपयोगी जानकारी है। मैं ldd के बजाय readelf उपयोग के बारे में पता नहीं था। बहुत बहुत धन्यवाद।
मार्कस

1

एक अन्य विकल्प का उपयोग करना है libtool

यदि आप g++कॉल को बदलते हैंlibtool --mode=compile g++ स्रोत कोड को संकलित करने और फिर libtool --mode=link g++एप्लिकेशन को बंद लिएlibB , तो libAस्वचालित रूप से लिंक हो जाएगा।


0

यह एक दिलचस्प पोस्ट है - मैं इसके साथ ही अपना सिर पीट रहा था, लेकिन मुझे लगता है कि आप यहां एक बिंदु याद करते हैं।

विचार इस प्रकार है, है ना?

आइए आगे विचार करें कि ।।

  • A.cpp (और केवल वहाँ) में आप एक वर्ग / चर को परिभाषित करते हैं, इसे "सिमा" कहते हैं
  • B.cpp (और केवल वहाँ) में आप एक वर्ग / चर को परिभाषित करते हैं, इसे "सिम्ब" कहते हैं।
  • सिंबल सिम्मा का उपयोग करता है
  • main.cpp सिम का उपयोग करता है

अब, libB.so और libA.so को ऊपर वर्णित के अनुसार संकलित किया गया है। उसके बाद, आपका पहला विकल्प काम करना चाहिए , अर्थात:

मुझे लगता है कि आपकी समस्या इस तथ्य से उत्पन्न होती है

main.cpp में आप सिमा को भी देखें

क्या मैं सही हूँ?

यदि आप अपने कोड में किसी प्रतीक का उपयोग करते हैं, तो उस प्रतीक को एक .so फ़ाइल में मिलना चाहिए

अंतर-संदर्भित साझा पुस्तकालयों (यानी एपीआई बनाने) का पूरा विचार यह है कि गहरी परतों में प्रतीक छिपे हुए हैं (प्याज को छीलने के बारे में सोचें) और उपयोग नहीं किए गए हैं। .. यानी अपने main.cpp में syma का संदर्भ न लें, बल्कि केवल symB के बजाय (और symb को केवल syma को देखें)।


1
आपने इसे गलत समझा। जाहिर है आपको तत्काल आवश्यक प्रतीकों को हल करने की आवश्यकता है। समस्या उन प्रतीकों से संबंधित है जिनकी आपके आश्रितों को आवश्यकता हो सकती है। जब लाइब्रेरी आपके उपयोगकर्ता द्वारा उपयोग की जाने वाली कार्यप्रणालियों को कार्यान्वयन प्रदान करने के लिए लाइब्रेरी पार्टी के साथ तीसरे पक्ष द्वारा उपयोग किए जाने वाले पुस्तकालयों को विकसित करना आम है। आप एक स्टब का उपयोग कर विकसित करते हैं, जिसमें कोई निर्भरता नहीं है और इंटीग्रेटर स्टब को बदलने के लिए एक लिब विकसित करेगा, फिर सब कुछ एक साथ लिंक करें। लोडर को सभी निर्भरता को हल करना होगा। हालाँकि आपकी संकलन स्क्रिप्ट (और आपके उपयोगकर्ता ') को इसका हिसाब देना चाहिए।
मार्कस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.