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