पुस्तकालय पथ की प्राथमिकता कैसे निर्दिष्ट करें?


94

मैं एक c ++ कार्यक्रम संकलन कर रहा हूँ का उपयोग कर g++और ld। मेरे पास एक .soपुस्तकालय है जिसे मैं लिंक करने के दौरान उपयोग करना चाहता हूं। हालाँकि, एक ही नाम का एक पुस्तकालय मौजूद है /usr/local/lib, और ldउस पुस्तकालय को चुन रहा है, जिस पर मैं सीधे निर्दिष्ट कर रहा हूँ। मैं इसे कैसे ठीक करूं?

नीचे दिए गए उदाहरणों के लिए, मेरी लाइब्रेरी फ़ाइल है /my/dir/libfoo.so.0। मैंने कोशिश की है कि काम न करें:

  • मेरी g ++ कमांड है g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp
  • जोड़ने /my/dirशुरुआत या मेरी के अंत तक $PATHen` चर
  • /my/dir/libfoo.so.0g ++ के तर्क के रूप में जोड़ना

1
क्या अन्य libfoo.*फ़ाइलें मौजूद हैं और जहां - .sow / ओ .0, .a, आदि आदि?
एलेक्स मार्टेली

जवाबों:


93

उस पथ को जोड़ें जहां आपकी नई लाइब्रेरी है LD_LIBRARY_PATH(यह मैक पर थोड़ा अलग नाम है ...)

आपके समाधान को -L/my/dir -lfooविकल्प का उपयोग करके काम करना चाहिए , रनटाइम पर LD_LIBRARY_PATH का उपयोग करके अपने पुस्तकालय के स्थान को इंगित करें।

LD_LIBRARY_PATH के उपयोग से सावधान - संक्षेप में (लिंक से):

..implication ..:: यह सबसे आम समस्या है। LD_LIBRARY_PATH एक साझा लाइब्रेरी को लोड करने के लिए एक एप्लिकेशन को इसके खिलाफ लिंक नहीं किया गया था, और यह मूल संस्करण के साथ संगत नहीं होने की संभावना है। यह या तो बहुत स्पष्ट हो सकता है, अर्थात एप्लिकेशन क्रैश हो सकता है, या यह गलत परिणाम दे सकता है, यदि उठाया गया पुस्तकालय काफी नहीं करता है जो मूल संस्करण ने किया होगा। विशेष रूप से उत्तरार्द्ध कभी-कभी डिबग करना कठिन होता है।
सुरक्षा : याद रखें कि LD_LIBRARY_PATH में निर्दिष्ट निर्देशिकाओं को मानक सिस्टम स्थानों से पहले (?) खोजा जाता है? इस तरह, एक बुरा व्यक्ति एक साझा पुस्तकालय के एक संस्करण को लोड करने के लिए आपका आवेदन प्राप्त कर सकता है जिसमें दुर्भावनापूर्ण कोड होता है! यही कारण है कि setuid / setgid निष्पादक उस चर की उपेक्षा करते हैं!
प्रदर्शन: लिंक लोडर को निर्दिष्ट सभी निर्देशिकाओं को खोजना होता है, जब तक कि वह निर्देशिका नहीं मिलती है जहां साझा पुस्तकालय रहता है - सभी साझा पुस्तकालयों के लिए आवेदन के खिलाफ लिंक किया गया है! इसका मतलब है कि बहुत सारे सिस्टम कॉल को खोलने के लिए (), जो "ENOENT (ऐसी कोई फ़ाइल या निर्देशिका नहीं)" के साथ विफल हो जाएगा! यदि पथ में कई निर्देशिकाएं हैं, तो विफल कॉल की संख्या रैखिक रूप से बढ़ जाएगी, और आप यह बता सकते हैं कि आवेदन के स्टार्ट-अप समय से। यदि निर्देशिकाओं में से कुछ (या सभी) एक एनएफएस वातावरण में हैं, तो आपके अनुप्रयोगों का स्टार्ट-अप समय वास्तव में लंबा हो सकता है - और यह पूरे सिस्टम को धीमा कर सकता है!
बेजोड़ता

या

लिंकर - रनटाइम लाइब्रेरी खोज पथ के लिए gcc के माध्यम से rpath विकल्प का उपयोग करें, मानक dir (gcc विकल्प) में देखने के बजाय उपयोग किया जाएगा:

-Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)

यह एक अस्थायी समाधान के लिए अच्छा है। लिंकर पहले मानक निर्देशिकाओं को देखने से पहले पुस्तकालयों के लिए LD_LIBRARY_PATH की खोज करता है।

यदि आप LD_LIBRARY_PATH को स्थायी रूप से अपडेट नहीं करना चाहते हैं, तो आप इसे कमांड लाइन पर फ्लाई पर कर सकते हैं:

LD_LIBRARY_PATH=/some/custom/dir ./fooo

आप देख सकते हैं कि पुस्तकालयों के लिंकर का उपयोग करने के बारे में क्या पता है (उदाहरण):

/sbin/ldconfig -p | grep libpthread
        libpthread.so.0 (libc6, OS ABI: Linux 2.6.4) => /lib/libpthread.so.0

और आप जांच सकते हैं कि आपका आवेदन किस पुस्तकालय का उपयोग कर रहा है:

ldd foo
        linux-gate.so.1 =>  (0xffffe000)
        libpthread.so.0 => /lib/libpthread.so.0 (0xb7f9e000)
        libxml2.so.2 => /usr/lib/libxml2.so.2 (0xb7e6e000)
        librt.so.1 => /lib/librt.so.1 (0xb7e65000)
        libm.so.6 => /lib/libm.so.6 (0xb7d5b000)
        libc.so.6 => /lib/libc.so.6 (0xb7c2e000)
        /lib/ld-linux.so.2 (0xb7fc7000)
        libdl.so.2 => /lib/libdl.so.2 (0xb7c2a000)
        libz.so.1 => /lib/libz.so.1 (0xb7c18000)

22
LD_LIBRARY_PATHरनटाइम में खोजा जाता है, संकलन समय पर आप सेट करना चाहते हैं LIBRARY_PATHGcc.gnu.org/onbuildocs/gcc/Environment-Variables.html
Bjoern Dahlgren

1
यदि आप लाइब्रेरी सिस्टम लाइब्रेरी से पूरी तरह से भिन्न हैं, अर्थात हमेशा उपयोग करने वाला है, तो कृपया rpath समाधान का उपयोग करें। LD_LIBRARY_PATH परीक्षण के लिए एक हैक है और इसे सही ढंग से निष्पादन योग्य कार्य करने के लिए आवश्यक नहीं होना चाहिए।
user2746401

1
मैक के लिए अपनी DYLD_LIBRARY_PATH
cbinder

यहां एक पूर्ण नमूना कमांड (सी के लिए) है जो इस उत्तर पर आधारित काम करता है:gcc myFile.c -o myFile.o -l myLibraryBaseName -Wl,-rpath,locationOfMyLibrary -L locationOfMyLibrary
जेट ब्लू

25

यह एक पुराना प्रश्न है, लेकिन किसी ने भी इसका उल्लेख नहीं किया है।

आप खुशकिस्मत हो रहे थे कि बात बिल्कुल जुड़ रही थी।

आपको बदलने की जरूरत है

g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp

इसके लिए:

g++ -g -Wall -o my_binary -L/my/dir bar.cpp -lfoo

आपका लिंकर उन प्रतीकों का ट्रैक रखता है जिन्हें इसे हल करने की आवश्यकता है। यदि यह पहले पुस्तकालय को पढ़ता है, तो इसके पास कोई आवश्यक प्रतीक नहीं है, इसलिए यह इसमें प्रतीकों की उपेक्षा करता है। उन चीज़ों के बाद पुस्तकालयों को निर्दिष्ट करें जिन्हें उन्हें लिंक करने की आवश्यकता है ताकि आपके लिंकर के पास उन्हें खोजने के लिए प्रतीक हों।

इसके अलावा, -lfooयह विशेष रूप से नामित फ़ाइल के लिए libfoo.aया libfoo.soआवश्यकतानुसार खोज करता है । नहीं है libfoo.so.0। तो या तो lnनाम या पुस्तकालय का नाम बदलकर एपोप्रीट रखें।

Gcc मैन पेज को उद्धृत करने के लिए:

-l library
   ...
   It makes a difference where in the command you 
   write this option; the linker searches and processes 
   libraries and object files in the order they are 
   specified.  Thus, foo.o -lz bar.o searches library z 
   after file foo.o but before bar.o.  If bar.o refers 
   to functions in z, those functions may not be loaded.

फ़ाइल को सीधे g++कमांड लाइन में जोड़ना चाहिए, जब तक कि निश्चित रूप से काम नहीं करना चाहिए, आप इसे पहले से डालते हैं bar.cpp, जिससे लिंकर को किसी भी आवश्यक प्रतीकों की कमी के लिए इसे अनदेखा करना पड़ता है, क्योंकि अभी तक कोई प्रतीकों की आवश्यकता नहीं थी।


22

पुस्तकालय के लिए पूर्ण पथ निर्दिष्ट करना ठीक काम करना चाहिए:

g++ /my/dir/libfoo.so.0  ...

क्या आपने -lfooनिरपेक्ष पथ को एक बार हटाने के लिए याद किया था ?


1
इस समाधान ने भी मेरे लिए ठीक काम किया - डिस्ट्रो डेवलपमेंट पैकेज के अलावा क्यूटी 5 के एक संस्करण के खिलाफ लिंक करने की कोशिश की। धन्यवाद।
wump

@संस्करण वाले प्रतीकों के लिए यह काम कैसे करें ? न्यूनतम उदाहरण: github.com/cirosantilli/cpp-cheat/blob/…
Ciro Santilli Sant i ith 六四

11

एक विकल्प के रूप में, आप पर्यावरण चर का उपयोग कर सकते हैं LIBRARY_PATHऔर CPLUS_INCLUDE_PATH, जो क्रमशः इंगित करते हैं कि कहां-कहां पुस्तकालयों की तलाश है और कहां-कहां शीर्षकों की तलाश है ( CPATHनौकरी भी करेंगे), -L और -I विकल्पों को निर्दिष्ट किए बिना।

संपादित करें: CPATHइसमें -Iऔर उसके CPLUS_INCLUDE_PATHसाथ हेडर शामिल हैं -isystem


क्या आप उपयोग के लिए उदाहरण जोड़ सकते हैं?
हन्ना खलील

export LIBRARY_PATH = /path/to/libएक ही कंसोल सत्र में जहाँ आप संकलन कर रहे हैं
अलेक्जेंड्रे हम्ज़

0

अगर किसी को विंडोज में DLL के साथ काम करने के लिए उपयोग किया जाता है और वह लिनक्स / क्यूटी में .so वर्जन नंबर्स को छोड़ना चाहेगा, तो वर्जन CONFIG += pluginवर्जन नंबरों को बाहर ले जाएगा। जैसा कि श्री क्लैचको ने उल्लेख किया है कि लिंकर को देना ठीक है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.