निष्पादन योग्य के समान निर्देशिका में .so नहीं मिल सकता है?


45

मेरे पास एक निष्पादन योग्य है जिसे libtest.soगतिशील रूप से लिंक करने की आवश्यकता है , इसलिए मैंने उन्हें उसी निर्देशिका में रखा, फिर:

cd path_to_dir
./binary

लेकिन यह मिला:

error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory

यह खोजने में असमर्थ कैसे हो सकता है libtest.soजो पहले से ही निष्पादन योग्य के समान निर्देशिका में है?

जवाबों:


25

लोडर कभी भी साझा ऑब्जेक्ट के लिए वर्तमान निर्देशिका की जांच नहीं करता है जब तक कि यह स्पष्ट रूप से के माध्यम से निर्देशित न हो $LD_LIBRARY_PATH। देखें ld.so(8)अधिक जानकारी के लिए आदमी पेज।


echo $LD_LIBRARY_PATHमेरी मशीन पर खाली है :(
linuxer


2
यह लोडर को पुस्तकालयों के लिए देखने के लिए अतिरिक्त निर्देशिकाओं को निर्दिष्ट करता है।
इग्नासियो वाज़केज़-अब्राम्स

1
* निक्स में पथ एक बृहदान्त्र ( :) द्वारा अलग किए जाते हैं , अर्धविराम नहीं।
इग्नासियो वाज़केज़-अब्राम्स

3
LD_LIBRARY_PATH आमतौर पर उत्पादन में एक खराब विकल्प है। यह त्वरित हैक के लिए अच्छा है, और यूनिट परीक्षण चलाने के दौरान अनइंस्टॉल किए गए बायनेरिज़ को साझा करने में मदद करने जैसी चीज़ों पर विचार किया जाता है। अपने बाइनरी का निर्माण करते समय, आप या तो अपनी लाइब्रेरी को एक मानक स्थान (/etc/ld.so.conf पर सूचीबद्ध) में रख सकते हैं या बाइनरी को देखने के लिए बर्नर को पता करने के लिए -R ध्वज को पास कर सकते हैं।
ऑटोमेटिअस

57

जब आप डायनामिक लिंकर को यह बताने के लिए LD_LIBRARY_PATH सेट कर सकते हैं कि कहाँ देखना है, तो बेहतर विकल्प हैं। आप अपनी साझा लाइब्रेरी को मानक स्थानों में से एक में रख सकते हैं, देखें /etc/ld.so.conf(लिनक्स पर) और /usr/bin/crle(सोलारिस पर) इन स्थानों की सूची के लिए

-R <path>अपने बाइनरी का निर्माण करते समय आप लिंकर को पास कर सकते हैं , जो <path>आपके साझा पुस्तकालय के लिए स्कैन की गई निर्देशिकाओं की सूची में जोड़ देगा । यहाँ एक उदाहरण है। सबसे पहले, समस्या दिखाते हुए:

libtest.h:

void hello_world(void);

libtest.c:

#include <stdio.h>
void hello_world(void) {
  printf("Hello world, I'm a library!\n");
}

नमस्ते सी:

#include "libtest.h"
int main(int argc, char **argv) {
  hello_world();
}

मेकफाइल (टैब का उपयोग किया जाना चाहिए):

all: hello
hello: libtest.so.0
%.o: %.c
        $(CC) $(CFLAGS) -fPIC -c -o $@ $<
libtest.so.0.0.1: libtest.o
        $(CC) -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o
libtest.so.0: libtest.so.0.0.1
        ln -s $< $@
clean:
        rm -f hello libtest.o hello.o libtest.so.0.0.1 libtest.so.0

चलो इसे चलाते हैं:

$ make
cc  -fPIC -c -o libtest.o libtest.c
cc -shared -Wl,-soname,libtest.so.0 -o libtest.so.0.0.1 libtest.o
ln -s libtest.so.0.0.1 libtest.so.0
cc     hello.c libtest.so.0   -o hello
$ ./hello 
./hello: error while loading shared libraries: libtest.so.0: cannot open shared object file: No such file or directory

इसे कैसे जोड़ेंगे? -R <path>लिंकर झंडे में जोड़ें (यहां, सेटिंग करके LDFLAGS)।

$ make clean
(...)
$ make LDFLAGS="-Wl,-R -Wl,/home/maciej/src/tmp"
(...)
cc   -Wl,-R -Wl,/home/maciej/src/tmp  hello.c libtest.so.0   -o hello
$ ./hello 
Hello world, I'm a library!

बाइनरी को देखते हुए, आप देख सकते हैं कि इसकी आवश्यकता है libtest.so.0:

$ objdump -p hello | grep NEEDED
  NEEDED               libtest.so.0
  NEEDED               libc.so.6

बाइनरी अपने पुस्तकालयों के लिए, मानक निर्देशिका के अलावा, निर्दिष्ट निर्देशिका में देखेगा:

$ objdump -p hello | grep RPATH
  RPATH                /home/maciej/src/tmp

यदि आप बाइनरी को वर्तमान निर्देशिका में देखना चाहते हैं, तो आप RPATH को सेट कर सकते हैं $ORIGIN। यह थोड़ा मुश्किल है, क्योंकि आपको यह सुनिश्चित करने की आवश्यकता है कि डॉलर के संकेत की व्याख्या मेक द्वारा नहीं की गई है। यहाँ यह करने का एक तरीका है:

$ make CFLAGS="-fPIC" LDFLAGS="-Wl,-rpath '-Wl,\$\$ORIGIN'"
$ objdump -p hello | grep RPATH
  RPATH                $ORIGIN
$ ./hello 
Hello world, I'm a library!

1
यदि उपयोग नहीं किया जा रहा है make, जैसे कि मैन्युअल रूप से कॉल करते समय g++, कोशिश करें -Wl,-rpath='$ORIGIN'(सिंगल कोट्स को नोट करें) $ORIGINएक खाली स्ट्रिंग तक फैलने से रोकने के लिए।
मोरपार्क

14

अपने निष्पादन योग्य के रूप में एक ही निर्देशिका से साझा की गई वस्तुओं को लोड करने के लिए, बस निष्पादित करें:

$ LD_LIBRARY_PATH=. ./binary

नोट: यह आपके सिस्टम के LD_LIBRARY_PATH चर को संशोधित नहीं करेगा। परिवर्तन केवल इसे और केवल इसी को प्रभावित करता है, आपके कार्यक्रम का निष्पादन।


4

बिना किसी उत्तर के संघर्ष करने वाले किसी व्यक्ति के लिए मैंने खुद को निम्नलिखित सुझाव के साथ पाया:

आप का उपयोग करके ld.so.cache को अपडेट करने का प्रयास कर सकते हैं: sudo ldconfig -v

मेरे लिए काम किया।


मेरे लिए भी काम किया।
जोएल

3

अपने निर्माण के लिए CMake का उपयोग करने वाले किसी व्यक्ति के लिए, आप CMAKE_EXE_LINKER_FLAGSनिम्नलिखित को सेट कर सकते हैं :

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")

यह सभी बिल्ड प्रकारों (जैसे, डीबग, रिलीज़, आदि ...) के लिए लिंकर झंडे को ठीक से प्रचारित करेगा। वर्तमान कार्यशील निर्देशिका में .so फ़ाइलों को देखने के लिए।


0

डायनेमिक लिंकर तय करेगा कि पुस्तकालयों की तलाश कहां की जाए। लिनक्स के मामले में, डायनेमिक लिंकर आमतौर पर GNU ld.so(या एक विकल्प है जो आमतौर पर संगतता कारणों के लिए समान व्यवहार करेगा।

विकिपीडिया से उद्धरण के लिए:

GNU C लाइब्रेरी का डायनेमिक लिंकर निम्न स्थानों में साझा लाइब्रेरी की खोज करता है:

  1. DT_RPATHबाइनरी के डायनामिक सेक्शन की विशेषता में (कोलन-सेपरेटेड) पथ मौजूद है और DT_RUNPATHमौजूद नहीं है।
  2. पर्यावरण चर में (बृहदान्त्र-पृथक) पथ LD_LIBRARY_PATH, जब तक कि निष्पादन योग्य एक setuid/ setgidबाइनरी नहीं है, जिस स्थिति में इसे अनदेखा किया जाता है। LD_LIBRARY_PATHडायनेमिक लिंकर को ऑप्शन --library-path (जैसे /lib/ld-linux.so.2 --library-path $ HOME / mylibs myprogram) के साथ कॉल करके ओवरराइड किया जा सकता है।
  3. DT_RUNPATHबाइनरी के डायनामिक सेक्शन विशेषता में (कोलन-सेपरेटेड) पथ मौजूद होने पर।
  4. लुकअप कैश फ़ाइल (अक्सर स्थित /etc/ld.so.cache) पर आधारित लुकअप जिसमें पहले से संवर्धित पुस्तकालय पथ (द्वारा निर्धारित /etc/ld.so.conf) में पाए गए उम्मीदवार पुस्तकालयों की एक संकलित सूची है । यदि, हालांकि, बाइनरी को -z nodefaultlibलिंकर विकल्प के साथ जोड़ा गया था , तो डिफ़ॉल्ट लाइब्रेरी पथों में पुस्तकालयों को छोड़ दिया जाता है।
  5. विश्वसनीय डिफ़ॉल्ट पथ में /lib, और फिर /usr/lib। यदि बाइनरी -z नोडफॉल्टलिब लिंकर विकल्प के साथ जुड़ा हुआ था, तो यह कदम छोड़ दिया जाता है।

स्रोत: https://en.wikipedia.org/wiki/Rpath

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