Подтвердить что ты не робот

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

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

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

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

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 script? (Спасибо заранее!)

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

4b9b3361

Ответ 1

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

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

Ответ 2

6 - 7 лет спустя статическая связь с расширениями Python по-прежнему плохо документирована. Этот Q/A помог мне найти решение, но, как и сейчас, это не ясно.

В Linux/Unix

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

В Windows

Компилятор видит, является ли связанная библиотека статичной или динамической, а имя статической библиотеки переходит в список библиотек и каталоги в библиотеку_дир

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

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

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=cmf_files,
                 libraries=libraries,
                 library_dirs=library_dirs,
                 include_dirs=include_dirs,
                 extra_objects=extra_objects)

В MacOS

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

Ответ 3

Любая возможность, что это может сработать?

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