Общие зависимости библиотек от distutils - программирование
Подтвердить что ты не робот

Общие зависимости библиотек от 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]
)

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

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

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

ОБНОВЛЕНИЕ 2. На данный момент я решил это, выполнив:

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

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

4b9b3361

Ответ 1

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

# Will link just fine, then fail to find libpcap.so unless it 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, используются только для поиска библиотек при выполнении двоичного файла

Ответ 2

Аргумент 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 у пути есть свои проблемы, однако - вы должны держать эти библиотеки в одном месте и доступны всем пользователям модуля расширения.

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