16

Jestem początkującym dla distutils i mam problem, który naprawdę mnie utknął. Ja kompilowania pakietów, które wymagają rozszerzenia, tak zrobię rozszerzenie tak:Zależności bibliotek współdzielonych z distutils

a_module = Extension(
      "amodule", 
      ["initmodule.cpp"], 
      library_dirs=libdirs, 
      extra_objects = [ 
        "unix/x86_64/lib/liba.so" 
        "unix/x86_64/lib/lib.so", 
        "unix/x86_64/lib/libc.so"], 
    ) 

I następnie uruchomić metodę konfiguracji:

setup(name="apackage", version="7.2", 
     package_dir = {'':instdir+'/a/b/python'}, 
     packages=['apackage','package.tests'], 
     ext_modules=[hoc_module] 
) 

Dystrybucja opakowanie jest wykonane prawidłowo i mogę „setup python .py zainstalować”w porządku, ale gdy próbuję i zaimportować pakiet pojawia się błąd ImportError: liba.so.0: cannot open shared object file: No such file or directory

Zdaję sobie sprawę, że kiedy dodać lokalizację liba.so.0 do mojego LD_LIBRARY_PATH program działa poprawnie. Niestety nie napisałem tych modułów i nie mam dobrej wiedzy na temat kompilacji. Próbowałem to rozgryźć przez kilka dni bezskutecznie.

UPDATE: Próbowałem przechodzącą liba.a, libb.a etc pliki extra_objects ale to nie działa, generując następujące errror: liba.a: Nie można odczytać symbole: zła jakość collect2: ld zwrócił 1 status wyjścia. Próbuję skompilować moduł Pythona, który wymaga kompilacji biblioteki, która sama zależy od innych bibliotek, które muszę w jakiś sposób uwzględnić w pakiecie. Podejrzewam, że mój problem jest bardzo podobny do tego: http://mail.python.org/pipermail/distutils-sig/2009-February/010960.html, ale to jeden nie został rozwiązany, myślałem, że być może odkąd ma dwa lata, znaleziono rezolucję?

UPDATE 2: Na razie mam to rozwiązać wykonując:

 data_files=[('/usr/local/lib', glob.glob('unix/x86_64/lib/*'))] 

To znaczy, jestem kopiowanie bibliotek muszę w/usr/local/lib. Nie jestem jednak bardzo zadowolony z tego rozwiązania, między innymi dlatego, że wymaga on od moich użytkowników uprawnień roota, a także dlatego, że nadal może nie działać dystrybucja Redhatów. Jeśli więc ktoś może zaproponować coś lepszego niż ta poprawka, proszę daj mi znać.

Odpowiedz

14

Możesz przekazać flagi do kompilatora lub łącznika, aby poinformować, gdzie znaleźć biblioteki w czasie wykonywania, zmniejszając potrzebę ustawiania odpowiednio LD_LIBRARY_PATH. będę zilustrować kilkoma przykładami:

# Will link just fine, then fail to find libpcap.so unless it's in LD_LIBRARY_PATH 
gcc -o blah blah.o -lpcap -L/opt/csw/lib 

# If libpcap is in LD_LIBRARY_PATH, it'll link fine. Other people who may not have 
# LD_LIBRARY_PATH set properly can still run it without fixing their environment 
gcc -o blah blah.o -lpcap -R/opt/csw/lib 

# This will allow me to link and execute the binary without having LD_LIBRARY_PATH 
# setup properly 
gcc -o blah blah.o -lpcap -{L,R}/opt/csw/lib 

# This makes it possible to use relative paths. The literal string `$ORIGIN/../lib/` 
# gets stored in the binary (`readelf -d binary_name` if you want to see the effect 
# it has), which causes `$ORIGIN` to resolve to the directory containing the binary 
# when it was executed. In a makefile, you'll see that written as `$$ORIGIN/../lib/` 
# to prevent `make` from expanding it. 
gcc -o blah blah.o -lsomelib -L/whatever/path/floats/your/boat -R'$ORIGIN/../lib/' 

W drodze wyjaśnienia, w przypadku nie było oczywiste (od I hate odpowiedzi bez wyjaśnienia):

  • ścieżki podane są z -L tylko użyte do znalezienia bibliotek gdy łączysz
  • ścieżki podane z -R są wykorzystywane wyłącznie do znalezienia bibliotek gdy binarny jest wykonywany
+0

Fantastyczna odpowiedź, łącząc odpowiedź z tym http: // sebsauvage. net/python/mingw.html Udało mi się zbudować potrzebny moduł dokładnie w wymagany sposób. Dziękuję bardzo. –

+0

Nie ma problemu, cieszę się, że mogłem pomóc –

+3

FYI: Zamiast dodawać opcję '-R '$ ORIGIN /../ lib /'', można dodać 'runtime_library_dirs =" $ ORIGIN /../ lib/"do twojej definicji" Extension "(w praktyce robi to samo). –

7

extra_objects argumentem klasy Extension nie tyle lista bibliotek link do rozszerzenia, ale lista plików obiektowych, które zostaną przekazane do łącznika (i nazwy plików nie powinna zawierać rozszerzenia, ponieważ distutils doda te.) Nie robi tego, czego się chce.

Jeśli chcesz połączyć się z określonymi bibliotekami współdzielonymi, ponieważ nazwy tych plików sugerują, że chcesz, musisz zrobić dwie rzeczy: powiedz distutils, aby powiedział kompilatorowi, aby łączył się z bibliotekami współużytkowanymi, i powiedz dynamicznemu linkerowi (zwykle ld.so) gdzie znaleźć te udostępnione biblioteki. Możesz poinformować distutils, aby powiedział kompilatorowi, aby łączył się z bibliotekami przy użyciu argumentu libraries dla Extension, który powinien być listą nazw bibliotek (bez przedrostka lib i.) W twoim przykładzie, który wydaje się być ['a', 'b', 'c'] (chociaż wygląda 'b' spadł z 'lib.so”i 'c' rzeczywiście kolidować z libc systemu.)

powiem linker gdzie znaleźć te współdzielone biblioteki mogą być wykonane przez ustawienie zmiennej LD_LIBRARY_PATH środowiska, jak ty, albo przez zmiana ogólnosystemowego ustawienia konfiguracyjnego (z ldconfig lub przez edycję /etc/ld.so.conf) lub poprzez zakodowanie ścieżki wyszukiwania w module rozszerzenia; możesz to zrobić, przekazując argument runtime_library_dirs do Extension.Hardcoding ścieżka ma jednak własne problemy - musisz przechowywać te biblioteki w tym samym miejscu i być dostępne dla wszystkich użytkowników modułu rozszerzenia.

(Alternatywnie, można użyć statycznego zamiast dynamicznego łączenia, na przykład tylko dostarczając biblioteki w formie statycznej, archiwa liba.a (w takim przypadku distutils automatycznie połączy się z nimi statycznie.) Oznacza to w zasadzie, że cała biblioteka jest zawarta w module rozszerzającym, który ma różne wady i zalety.)

+0

Dziękuję wiele za szczegółową i doskonałą odpowiedź. Czy mam rację, rozumiejąc, że katalogi_czasu_reklamowego powinny być ustawione jako ścieżka względna, w przeciwnym razie nie widzę, jak można go na stałe? Ponadto, czy powinienem przekazać statycznie połączone biblioteki (tj. Archiwa liba.a) do słów kluczowych bibliotek lub extra_objects. Niestety dokumentacja nie pomaga mi w tych dwóch kwestiach. –

+1

Podawanie katalogu względnego jako katalogu runtime_library_dirs może być wykonane, ale nie jest to dobry pomysł (ponieważ moduł rozszerzenia porusza się podczas procesu budowania, a ta sama ścieżka musiałaby działać dla wszystkich.) Jeśli chodzi o statyczne połączenie, możesz spróbować przejść archiwa '.a' jako argument' extra_objects', chociaż nie jest to tym, czym jest 'extra_objects' i nie jestem pewien, czy to zadziała. Być może powinieneś rozwinąć to, co naprawdę chcesz robić. –

+0

Dziękuję za odpowiedź, dodałem trochę więcej szczegółów do mojego pierwotnego pytania. –