16

Я новичок в distutils, и у меня есть проблема, которая действительно застряла. Я компиляции пакета, который требует расширения, так что я сделать расширение таким образом:Общие зависимости библиотек от 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"], 
    ) 

Затем я запустить метод установки:

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

Распределение пакета сделан правильно, и я могу «установки питона .py установить»нормально, но когда я пытаюсь импортировать мой пакет, я получаю сообщение об ошибке ImportError: liba.so.0: cannot open shared object file: No such file or directory

Я понимаю, что когда я добавляю расположение liba.so.0 моей LD_LIBRARY_PATH программа работает нормально. К сожалению, я не написал эти модули и не очень хорошо разбираюсь в компиляции. Я пытался понять это в течение нескольких дней безрезультатно.

UPDATE: Я попытался прохождения liba.a, libb.a и т.д. файлы extra_objects, но это не сработало, генерируя следующий errror: liba.a: не может прочитать символы: Плохое значение collect2: л.д. вернулся 1 статус выхода. То, что я пытаюсь сделать, это пакетный модуль python, который требует компиляции библиотеки, которая сама зависит от других библиотек, которые мне нужно каким-то образом включить в пакет. Я подозреваю, что моя проблема очень похожа на эту: http://mail.python.org/pipermail/distutils-sig/2009-February/010960.html, но это один не был разрешен, я подумал, возможно, с тех пор, как ему исполнилось два года, была найдена резолюция?

UPDATE 2: На данный момент я решил это делать:

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

То есть, я копирую библиотеки мне нужно в/USR/местные/Библиотека. Однако я не очень доволен этим решением, не в последнюю очередь потому, что он требует, чтобы мои пользователи имели права root, а также потому, что это может все еще не работать с дистрибутивами Redhat. Поэтому, если кто-нибудь может предложить что-то лучше этого исправления, пожалуйста, дайте мне знать.

ответ

14

Вы можете передать флаги компилятору или компоновщику, чтобы сообщить ему, где искать библиотеки во время выполнения, облегчая настройку LD_LIBRARY_PATH. Я иллюстрировать несколько примеров:

# 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/' 

В качестве объяснения, в случае, если это не было очевидно (так как я ненавижу ответы без объяснения):

  • пути, данные с -L являются используется только для поиска библиотек, когда вы ссылаетесь
  • пути, данные с -R используются только для поиска библиотек, когда исполнимый файл
+0

Фантастический ответ, объединив свой ответ с этим http: // sebsauvage. net/python/mingw.html Я смог построить необходимый модуль именно так, как нужно. Огромное спасибо. –

+0

Не проблема, я рад, что смог помочь –

+3

FYI: вместо добавления опции -R '$ ORIGIN /../ lib /' 'вы можете добавить' runtime_library_dirs = "$ ORIGIN /../ lib/«' к вашему определению «Расширение» (он делает то же самое на практике). –

7

extra_objects аргумент Extension класса не столько список библиотек связать в ваш добавочный номер, а список объектных файлов, которые будут переданы в компоновщик (и имена файлов не должны включать в себя расширения, так как Distutils добавит их.) Он не делает то, что вам кажется нужным.

Если вы хотите связать себя с отдельными разделяемыми библиотеками, так как имена этих файлов подсказывают, что вы хотите, вам нужно сделать две вещи: сообщить distutils, чтобы сообщить компилятору ссылку на эти общие библиотеки и сообщить динамическому компоновщику (обычно ld.so), где можно найти эти общие библиотеки. Вы можете сказать distutils, чтобы сообщить компилятору связать с библиотеками аргумент libraries с Extension, который должен быть списком имен библиотек (без префикса lib и .so). В вашем примере это выглядит как ['a', 'b', 'c'] (хотя это похоже, что 'b' упал из 'lib.so», и 'c' фактически конфликтовать с системой LIBC.)

Рассказывая компоновщик, где найти эти общие библиотеки можно сделать, установив переменную LD_LIBRARY_PATH среды, как вы делали, или изменение общесистемного параметра конфигурации (с ldconfig или путем редактирования /etc/ld.so.conf) или путем жесткого кодирования пути поиска в модуле расширения; вы можете сделать последнее, передав аргумент runtime_library_dirs в Extension.У Hardcoding у пути есть свои проблемы, однако - вы должны держать эти библиотеки в одном месте и доступны всем пользователям модуля расширения.

(В качестве альтернативы вы можете использовать статические вместо динамической компоновки, например, только предоставляя библиотеки в статической форме, архивы liba.a (в этом случае distutils будет автоматически ссылаться на них статически). Это в основном означает, что вся библиотека включена в расширительном модуле, который имеет различные недостатки и недостатки.)

+0

Спасибо вам много для вашего подробного и отличного ответа. Правильно ли я понимаю, что runtime_library_dirs должен быть установлен как относительный путь, иначе я не вижу, как это может быть жестко запрограммировано? Кроме того, следует передать статически связанные библиотеки (например, архивы liba.a) в библиотеки или ключевые слова extra_objects. К сожалению, документация не очень помогает мне в этих двух вопросах. –

+1

Передача относительного каталога как runtime_library_dirs может быть выполнена, но это не очень хорошая идея (поскольку модуль расширения перемещается во время процесса сборки, и тот же путь должен работать для всех.) Что касается связывания статически, вы можете попробовать пройти архивы '.a' как аргумент' extra_objects', хотя это не то, что для 'extra_objects', и я не уверен, что это сработает. Возможно, вам следует подробно остановиться на том, что вы на самом деле хотите сделать. –

+0

Спасибо за ваш ответ, я добавил несколько подробностей к моему оригинальному вопросу. –

Смежные вопросы