Как статически связать библиотеку при компиляции расширения модуля Python - PullRequest
25 голосов
/ 04 января 2011

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

Ответы [ 3 ]

14 голосов
/ 06 марта 2018

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

В Linux / Unix

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

В Windows

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

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

Для приведенного ниже примера я использую сценарий библиотеки из 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)но я не проверял это.

9 голосов
/ 05 января 2011

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

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

0 голосов
/ 05 июня 2012

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

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