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

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


person Matthew Walker    schedule 04.01.2011    source источник


Ответы (3)


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

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

person detly    schedule 05.01.2011
comment
Я добавил параметр extra_objects в экземпляр Extension, указав libigraph.a (вопреки документации, в которой говорится, что не добавляйте расширение файла) и добавил все зависимости к параметру library. Это создает статически связанную библиотеку. Но, как вы указываете, это очень зависит от ОС, поэтому, если это единственный вариант, мне придется обратить внимание на то, что хочет Windows. Спасибо за вашу помощь. - person Matthew Walker; 06.01.2011
comment
@Matthew Walker - если вы найдете лучшее решение, вы должны опубликовать его здесь, потому что мне было бы очень интересно :) - person detly; 07.01.2011
comment
это работает: Extension('my.mod', ['src/file.c'], extra_link_args=['-static']) - person Mike T; 10.06.2013

Спустя 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), но я не проверял это.

person oekopez    schedule 06.03.2018
comment
Спасибо за это. Я могу подтвердить, что это действительно работает на MacOS. Верхний ответ не сработал для меня. - person Bob Barcklay; 25.03.2018

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

g++ -Wl,-Bstatic -lfoo -Wl,-Bdynamic -lbar -Wl,--as-needed
person Brian Bruggeman    schedule 05.06.2012