Зависимости разделяемой библиотеки с помощью distutils - PullRequest
17 голосов
/ 21 марта 2012

Я новичок в 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 install" нормально, но когда я пытаюсь импортировать мой пакет, я получаю ошибку 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, но это не сработало, из-за чего произошла следующая ошибка: 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. Поэтому, если кто-то может предложить что-то лучше, чем это исправление, пожалуйста, дайте мне знать.

Ответы [ 2 ]

15 голосов
/ 20 апреля 2012

Вы можете передать флаги компилятору или компоновщику, чтобы он знал, где искать библиотеки во время выполнения, что устраняет необходимость правильной установки 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, используются только для поиска библиотек, когда исполняется двоичный файл
10 голосов
/ 21 марта 2012

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...