2014-09-22 12 views
6

C++ 11 ve C++ 14 özelliklerinden yararlanmak için gcc (4.9.1) 'in daha yeni bir sürümünü kullanarak derlenmiş bir uygulama var. libstdC++ sürümü daha yeni. Uygulama ben yerine paylaşılan kitaplık olarak ++ libstdc ile bağlama am kadar çok küçük programlardan oluşmaktadır statik bir Ben yeni sürümü gemi isteyenLibstdC++ küçük bir sürümünün zorlanması veya engellenmesi

(I ++ -static-libstdc kullanmak istemeyen ie) libstdC++ altındaki uygulama ile/opt // lib64 (not: özel olarak GPL istisnasının altında bu özelliğin izin verildiği)

LibstdC++ 'nın yeni sürümü, hedef platformdaki sürümde yalnızca küçük sürümle farklıdır. libstdC++, mevcut programların kütüphanenin yeni sürümünü kullanabilmesi için ileriye dönük olacak şekilde tasarlanmıştır. Ancak, bazı programları eski sürümden ziyade yeni sürümü kullandığında, davranışlarda (örn. Hatalar) ince farklar gözlemledim. Bunu önlemek isterim.

Ayrıca ld uygulamasının LD_LIBRARY_PATH'de daha önce koydum/opt // lib64 kullanmamasına rağmen libstdC++ sistem sürümüyle uygulamamı bağlamayı deneyeceğim. -l:<library>.<version> kullanarak belirli bir sürüme karşı bağlama zorlayabilirsiniz, ancak, bu işe yaramaz. Bir kullanıcı için kütüphane oluşturduğundan şüpheleniyorum ama için libstd ++ gibi bir dil çalışma zamanı kitaplığı değil, çünkü gcc'nin kendisi de linker betiğini oluşturur. Ayrıca, hedef platformlarımdan birinde (RHEL5) gcc/ld tarafından bile anlaşılmadı. Bunun, -nostdlib'yi kullanarak ve benim gerekli olan (gc) gibi her şeyde (örneğin, -lgcc) yapı sistemimde 'u tercih etmek yerine, tercih ettiğim gcc'ye bırakmak yerine mümkün olduğunu farz ediyorum. Şimdiye kadar bunu denemedim.

Bunun için basit bir çözüm, LD_LIBRARY_PATH uygulamamın/opt // lib64 dosyasının benim uygulama 'u çalıştırdığımda sağladığından emin olmaktır. Aksi ya da eşit olmayan bir şekilde LD_PRELOAD'ı doğru kitaplık sürümüyle kullanabilirim. birisi karar verirse bu sorun, ince ve teşhis etmek zor problemlere yol açabilir benim tavsiye görmezden ve

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/<vendor>/lib64 

çalışır. Bu yüzden daha iyi bir yol arıyordum.

LibstdC++ 'yi lib_stdC++ olarak yeniden adlandırabileceğimi ve bunun yerine soname ile bağlantı kurabileceğimi merak ettim. Yeniden adlandırma libstdC++, dosyadaki soname'yi, kendisi tarafından verildiği gibi değiştirmek zorunda olduğunuz için yeterli değildir. Bu bile -l:stdc++.so.6.0.20 kullanılarak gcc ile bağlı normal bir program üzerinde yaparsanız bu majör sürüm değil spesifik alt sürüm verir göreceksiniz ki

0x000000000000000e (SONAME)    Library soname: [libstdc++.so.6] 

yani. yani

readelf -d <myapp> 
0x0000000e (SONAME)      Library soname: [libstdc++.so.6] 

ziyade: Yani

0x0000000e (SONAME)      Library soname: [libstdc++.so.6.0.20] 

şöyle yerine bir bağımlılık eklemek için bağımlı istediğiniz soname'i ile bir kukla paylaştı kütüphane oluşturduk:

gcc dummy.o -Wl,-soname,lib<vendor>_stdc++.so.6.0.20 -nostdlib -shared -o lib<vender>_dummycpp.so 

(burada kukla.

readelf -d <myapp> 

0x0000000000000001 (NEEDED)    Shared library: [lib<vendor>_stdc++.so.6.0.20] 

yerine

: Şimdi elde arzu edildiği gibi

gcc <myapp> -l<vendor>_dummycpp 

: o boş kaynak dosya yapılmış boş bir nesne dosya daha sonra

) şikayetlerin giden -nostdlib durdurmaktır

0x0000000000000001 (NEEDED)    Shared library: [libstdc++.so.6] 

dummycpp kütüphanesi libstdC++ içindeki tüm sembolleri içerir çünkü bu libstd ++ 'dır; soneki libstdC++ ile bağlantı kurmak için gcc. Sorunu tamamen çözdüm.

Burada sormak istediğim sorular yüzden biraz hacky çözüm olarak beni çarptığı:

  • bu iyi bir fikir mi?

  • Değilse neden olmasın?

  • Daha iyi/daha doğru bir yol var mı?

Not: Bir RPM (ör. Lib_stdC++ so.6.0.20) farklı bir adla libstdC++ paket eğer üzerinde eksik bir bağımlılık almak ve --nodeps seçeneğini kullanarak yüklemeniz gerekir söyledi. Bunun nedeni RPM'nin bağlantı zamanı bağımlılıkları için taranmasıdır. Bunun geçici çözümü, kukla kütüphaneyi de kurmaktır. RPM daha sonra kukla kütüphaneden sonayı alacak ve eksik olduğunu iddia etmeyecektir.

+2

Önce aramak için standart olmayan bir yer belirtmek için '-rpath' (* linker option *) kullanmayı düşündünüz mü? yani: -Wl, -rpath =/opt/lib64' –

+1

sadece meraktan, gözlemlediğiniz ince farklar nelerdir? – Krizz

+0

@Krizz Ben de bunu merak ediyordum. OPs kodundaki gerçek hataların libstdC++ 'den tahmin edilebileceğini tahmin ediyorum. Sadece hatalar farklı bir kütüphane ile kendilerini gösterir. –

cevap

2

libstdC++ SSS girişi How do I insure that the dynamically linked library will be found bağlantılarına, bunun yerine RPATH'nin nasıl kullanılacağını açıklayan Finding Dynamic or Shared Libraries kılavuz bölümüne bağlantılar.

Tercih ettiğim yöntem, $ORIGIN numaralı bir RPATH kullanmaktır; bu, dinamik kitaplık bağımlılıklarının aranmasının ikiliyle aynı dizinde başladığını gösterir (bkz. ld.so(8)). Yani, '-Wl,-rpath,$ORIGIN' ile bağlantı kurarsanız (kabuk tarafından genişletilen $ ORIGIN'in önlenmesi için tırnaklara dikkat edin), paylaşımlı kütüphaneleri kurulu ikili dosyanızla aynı dizine yükleyebilir ve ikili çalıştırdığınızda bunlar bulunur. Ya da bazı yükleme önekinin altında ayrı bin ve lib dizinlerini tercih ederseniz '-Wl,-rpath,$ORIGIN/../lib' kullanın.

ldconfig tarama yapmaz bazı özel yolundaki ikili yanında yüklü kütüphanesi ile

ve çevreyi berbat hiçbir LD_LIBRARY_PATH, yeni libstdC++ bu sürümü kullanmaya gerekiyordu uygulamalar bulunabilir asla.

libstdc++.so.6 için DT_NEEDED dosyayı bulmak, böylece siz de libstdc++.so.6.0.20 dosyayı işaret libstdc++.so.6 sembolik yüklemek emin olun.

+0

Kullanıcıların LD_LIBRARY_PATH'yi güncelleştirmesi ve yükleme yolumu taraması durumunda yine de olası bir sorun var. Şu anda, $ ORIGIN kullanmadığım için aktif olarak teşvik ediyorum. Bu çözümü hacklerimde geliştirmesi gerektiği gibi test edeceğim. –

+0

Kullanıcılar, LD_LIBRARY_PATH değerini sorunlara neden olan farklı bir kitaplık bulmaya ayarlarsa, mutlaka her iki parçayı da saklarlar. –

+0

Ancak oldukça ince olabilir. –

İlgili konular