Kitaplık yolu tercihi nasıl belirlenir?


96

Ben kullanarak c ++ program derleme ediyorum g++ve ld. .soBağlanırken kullanmak istediğim bir kütüphanem var . Ancak, içinde aynı isimde bir kitaplık var /usr/local/libve lddoğrudan belirttiğim kitaplık yerine o kitaplığı seçiyor. Bunu nasıl düzeltebilirim?

Aşağıdaki örnekler için kitaplık dosyam /my/dir/libfoo.so.0. Çalışmayan denediğim şeyler:

  • benim g ++ komutum g++ -g -Wall -o my_binary -L/my/dir -lfoo bar.cpp
  • en` değişkenimin /my/dirbaşına veya sonuna ekleme$PATH
  • /my/dir/libfoo.so.0g ++ 'ya bağımsız değişken olarak ekleme

1
Başka hangi libfoo.*dosyaların mevcut ve - .sow / o .0, .avb vs?
Alex Martelli

Yanıtlar:


94

Yeni kitaplığınızın bulunduğu yerin yolunu ekleyin LD_LIBRARY_PATH(Mac'te biraz farklı bir adı vardır ...)

Çözümünüz -L/my/dir -lfooseçenekleri kullanarak çalışmalıdır , çalışma zamanında kitaplığınızın konumuna işaret etmek için LD_LIBRARY_PATH kullanın.

LD_LIBRARY_PATH kullanırken dikkatli olun - kısaca (bağlantıdan):

..implications ..:
Güvenlik : LD_LIBRARY_PATH'de belirtilen dizinlerin standart konumlardan (!) önce arandığını hatırlıyor musunuz? Bu şekilde, kötü bir kişi uygulamanızı kötü niyetli kod içeren paylaşılan bir kitaplığın bir sürümünü yüklemesini sağlayabilir! Bu, setuid / setgid çalıştırılabilir dosyalarının bu değişkeni ihmal etmelerinin bir nedeni!
Verim: Bağlantı yükleyici, paylaşılan kitaplığın bulunduğu dizini bulana kadar belirtilen tüm dizinleri aramalıdır - uygulamanın bağlantılı olduğu TÜM paylaşılan kitaplıklar için! Bu, open () 'a çok sayıda sistem çağrısı anlamına gelir ve "ENOENT (Böyle bir dosya veya dizin yok)" ile başarısız olur! Yol çok sayıda dizin içeriyorsa, başarısız çağrıların sayısı doğrusal olarak artacaktır ve bunu uygulamanın başlama zamanından anlayabilirsiniz. Dizinlerin bazıları (veya tümü) bir NFS ortamındaysa, uygulamalarınızın başlama süresi gerçekten uzun sürebilir - ve tüm sistemi yavaşlatabilir!
Tutarsızlık: Bu en yaygın sorundur. LD_LIBRARY_PATH, bir uygulamayı bağlantılı olmadığı paylaşılan bir kitaplığı yüklemeye zorlar ve bu büyük olasılıkla orijinal sürümle uyumlu değildir. Bu ya çok açık olabilir, yani uygulama çöker ya da alınan kitaplık orijinal sürümün yapacağı şeyi tam olarak yapmazsa yanlış sonuçlara yol açabilir. Özellikle ikincisinin hata ayıklaması bazen zordur.

VEYA

Bağlayıcıya gcc aracılığıyla rpath seçeneğini kullanın - çalışma zamanı kitaplığı arama yolu, standart dizine bakmak yerine kullanılacaktır (gcc seçeneği):

-Wl,-rpath,$(DEFAULT_LIB_INSTALL_PATH)

Bu geçici bir çözüm için iyidir. Bağlayıcı, standart dizinlere bakmadan önce ilk olarak LD_LIBRARY_PATH kitaplıklarını arar.

LD_LIBRARY_PATH'yi kalıcı olarak güncellemek istemiyorsanız, bunu komut satırında anında yapabilirsiniz:

LD_LIBRARY_PATH=/some/custom/dir ./fooo

Kitaplık bağlayıcısının (örnek) kullanma hakkında bildiklerini kontrol edebilirsiniz:

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

Ve uygulamanızın hangi kitaplığı kullandığını kontrol edebilirsiniz:

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)

23
LD_LIBRARY_PATHçalışma zamanında, ayarlamak istediğiniz derleme zamanında aranır LIBRARY_PATH. Bkz. Gcc.gnu.org/onlinedocs/gcc/Environment-Variables.html
Bjoern Dahlgren

1
Kitaplığınız sistem kitaplığından tamamen farklıysa, yani her zaman kullanılacaksa, lütfen rpath çözümünü kullanın. LD_LIBRARY_PATH, test amaçlı bir hack'tir ve bir yürütülebilir dosyanın düzgün çalışması için gerekli olmamalıdır.
user2746401

1
Mac için DYLD_LIBRARY_PATH
cbinder

İşte bu yanıta dayalı olarak çalışan eksiksiz bir örnek komut (C için):gcc myFile.c -o myFile.o -l myLibraryBaseName -Wl,-rpath,locationOfMyLibrary -L locationOfMyLibrary
Jet Blue

25

Bu eski bir soru, ancak kimse bundan bahsetmemiş gibi görünüyor.

Bu şey birbirine bağlandığı için şanslıydın.

Değişmen gerek

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

buna:

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

Bağlayıcınız, çözmesi gereken simgeleri izler. Önce kütüphaneyi okursa, gerekli sembolleri yoktur, bu nedenle içindeki sembolleri yok sayar. Bağlayıcınızın içinde bulması gereken semboller olması için kitaplıkları, onlara bağlanması gereken şeylerden sonra belirtin.

Ayrıca, -lfooözellikle adlandırılmış libfoo.aveya libfoo.sogerektiği gibi bir dosyayı aramasını sağlar . Değil libfoo.so.0. Bu yüzden yaln kitaplığı uygun olarak adlandırın veya yeniden adlandırın.

Gcc man sayfasından alıntı yapmak için:

-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.

Dosyayı doğrudan g++komut satırına eklemek işe yaramalıydı, tabii daha önce bar.cppkoymadığınız sürece , bağlayıcı gerekli semboller olmadığı için onu yok saymasına neden oluyordu, çünkü henüz hiçbir sembol gerekli değildi.


22

Kitaplığa giden mutlak yolu belirtmek iyi çalışmalıdır:

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

-lfooMutlak yolu ekledikten sonra kaldırmayı hatırladınız mı?


1
Bu çözüm benim için de iyi çalıştı - dağıtım geliştirme paketi dışında bir Qt5 sürümüne bağlanmaya çalışıyor. Teşekkürler.
2016

Bu, @versiyonlu semboller için nasıl çalıştırılır ? Minimum örnek: github.com/cirosantilli/cpp-cheat/blob/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

11

Alternatif olarak, ortam değişkenleri kullanabilirsiniz LIBRARY_PATHve CPLUS_INCLUDE_PATHsırasıyla kütüphaneler ve nerede (başlıklarına bakmak için aramaya göstermektedir CPATH-L ve -I seçenekleri belirtmeden de iş yapacak).

Düzenle: CPATHile -Ive CPLUS_INCLUDE_PATHile başlıkları içerir -isystem.


Kullanım için örnek ekleyebilir misiniz?
Hanna Khalil

export LIBRARY_PATH = /path/to/libEğer derleme aynı konsol oturumunda
Alexandre Hamez

0

Windows'ta DLL ile çalışmak için bir tane kullanılıyorsa ve linux / QT'de .so sürüm numaralarını atlamak istiyorsanız, ekleme CONFIG += pluginsürüm numaralarını çıkaracaktır. Bay Klatchko'nun da belirttiği gibi, .so'ya mutlak yolu kullanmak, bağlayıcıya vermek iyi çalışıyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.