Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Как статически связать библиотеку при компиляции расширения модуля python

Автор вопроса: Matthew WalkerОтветов: 3

Я хотел бы изменить файл setup.py таким образом, чтобы команда "python setup.py build" компилировала модуль расширения на основе C, который статически (а не динамически) связан с библиотекой.

Расширение в настоящее время динамически связано с рядом библиотек. Я хотел бы оставить все без изменений, кроме статической привязки только к одной библиотеке. Я успешно сделал это, вручную изменив вызов gcc, который запускается distutils, хотя для этого требовалось, чтобы я явно перечислил зависимые библиотеки.

Возможно, это слишком много информации, но для ясности это последняя команда компоновки, которая была выполнена во время скрипта "python setup.py build":

gcc -pthread -shared -L/system/lib64 -L/system/lib/ -I/system/include build/temp.linux-x86_64-2.7/src/*.o -L/system/lib -L/usr/local/lib -L/usr/lib -ligraph -o build/lib.linux-x86_64-2.7/igraph/core.so

А это моя ручная модификация:

gcc -pthread -shared -L/system/lib64 -L/system/lib/ -I/system/include build/temp.linux-x86_64-2.7/src/*.o -L/system/lib -L/usr/local/lib -L/usr/lib /system/lib/libigraph.a -lxml2 -lz -lgmp -lstdc++ -lm -ldl -o build/lib.linux-x86_64-2.7/igraph/core.so

Раздел 2.3.4 Распространение модулей Python обсуждает спецификацию библиотек, но только "library_dirs" подходит, и эти библиотеки динамически связаны.

Я использую среду Linux для разработки, но пакет также будет скомпилирован и установлен в Windows, поэтому мне нужно портативное решение.

Может кто-нибудь сказать мне, где искать инструкции или как изменить сценарий setup.py? (Заранее спасибо!)

Я новичок в StackOverflow, поэтому приношу свои извинения, если я неправильно отметил этот вопрос или допустил какую-то другую ошибку в этом сообщении.

pythoncompilationstatic

Ответы

Ответ 1 · рейтинг 10 · detly

Если ничего не помогает, всегда есть малодокументированные варианты extra_compile_args и extra_link_args. в построитель Extension. (См. также здесь.)

Однако вам может потребоваться взломать некоторый код, зависящий от ОС, чтобы получить правильный формат аргумента для конкретной платформы.

Ответ 2 · рейтинг 28 · oekopez

Спустя 6-7 лет статическое связывание с расширениями Python все еще плохо документировано. Как указывает OP в комментарии, использование зависит от ОС.

В Linux/Юниксе

Статические библиотеки подключаются так же, как и объектные файлы, и должны идти с путем и расширением в extra_objects.

В Windows

Компилятор видит, является ли связанная библиотека статической или динамической, и имя статической библиотеки попадает в список библиотек, а каталоги - в library_dir.

Решение для обеих платформ

В приведенном ниже примере я буду использовать тот же сценарий библиотеки, что и OP, связывая igraph статические и z, xml2 и gmp динамические. Это решение немного хакерское, но, по крайней мере, подходит для каждой платформы.

static_libraries = ['igraph']
static_lib_dir = '/system/lib'
libraries = ['z', 'xml2', 'gmp']
library_dirs = ['/system/lib', '/system/lib64']

if sys.platform == 'win32':
    libraries.extend(static_libraries)
    library_dirs.append(static_lib_dir)
    extra_objects = []
else: # POSIX
    extra_objects = ['{}/lib{}.a'.format(static_lib_dir, l) for l in static_libraries]

ext = Extension('igraph.core',
                 sources=source_file_list,
                 libraries=libraries,
                 library_dirs=library_dirs,
                 include_dirs=include_dirs,
                 extra_objects=extra_objects)

На MacOS

Я предполагаю, что это работает и для MacOS (используя путь else), но я не проверял это.

Ответ 3 · Brian Bruggeman

Есть ли вероятность, что это может сработать?

g++ -Wl,-Bstatic -lfoo -Wl,-Bdynamic -lbar -Wl,--as-needed

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы