Как создать расширение .dylib C на mac os x с помощью distutils и/или setuptools?

Мне нужно сделать расширение C с distutils (и/или setuptools), которое можно использовать ОБА динамически во время выполнения и во время компиляции (для разных целей). Это не проблема в Linux, но это проблема в OS X. По умолчанию distutils создает «пакет» в OS X (и называет его .so), который можно использовать во время выполнения, но НЕ во время компиляции. Мне нужно создать .dylib, на который можно связать во время компиляции, и мне нужно сделать это в setup.py, который я могу упаковать для PyPI.

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

file libA.so
libA.so: Mach-O 64-bit bundle x86_64

Следующая команда cc дает мне то, что я хочу:

cc -fPIC -shared source1.o source2.o -o libA.so
file libA.so
libA.so: Mach-O 64-bit dynamically linked shared library x86_64

person Dan    schedule 06.09.2015    source источник


Ответы (1)


Вот что у меня сработало (добавлены строки в моем setup.py):

if sys.platform == 'darwin':
    from distutils import sysconfig
    vars = sysconfig.get_config_vars()
    vars['LDSHARED'] = vars['LDSHARED'].replace('-bundle', '-dynamiclib')

Эта конфигурация, кажется, зашита в модуль _sysconfigdata. Его также можно переопределить с помощью переменных среды, так что это тоже работает:

LDSHARED="cc -dynamiclib -undefined dynamic_lookup -arch x86_64 -arch i386 -Wl,-F." python setup.py install
person Uri Barkai    schedule 24.09.2015
comment
Извините за поздний ответ, но я только что попробовал это, и оба метода оставляют меня с «пакетом» после того, как я проверю с помощью file libA.so (или если я попытаюсь скомпилировать компоновку libA. Поэтому я получаю то же самое «не могу связать с пакетом, только ошибка dylibs). Какие-либо предложения? - person Dan; 21.12.2015
comment
В выводе setup.py build под running build_ext показаны фактические командные строки, используемые для компиляции и компоновки. Посмотрите на команду link (последняя, ​​которая создает файл .so), влияет ли на нее определение LDSHARED? Или другими переменными среды в sysconfig.get_config_vars()? Если это так, возможно, вы можете попробовать настроить эти переменные. Если ничего не помогает, вы можете отладить distutils/command/build_ext.py, чтобы увидеть, как он генерирует аргументы для self.compiler.link_shared_object(). Надеюсь это поможет. - person Uri Barkai; 22.12.2015
comment
Я явно упускаю что-то важное, потому что я попробовал еще раз, и теперь я не только получаю динамически подключаемую библиотеку, но и не могу сейчас получить пакет (мне нужны оба для разных целей). Я попробовал тот же код, но переключился на замену ('-dynamiclib', '-bundle') и все равно получил динамически связанную библиотеку. Когда я печатаю sysconfig.get_config_vars(), я получаю все -bundle и не -dynamiclib. Ваши предложения по отладке очень полезны, но когда я попробовал сборку python setup.py, я запустил build_ext, но без вывода под ним. Любые идеи? Большое спасибо за Вашу помощь. - person Dan; 22.12.2015
comment
Вы уверены, что сборка пройдет в этом случае? Возможно, вам нужно удалить папку build для повторной сборки? - person Uri Barkai; 22.12.2015
comment
Огромное спасибо! Это решает обе проблемы сразу. Удаление папки сборки вызывает все операторы печати (потому что что-то на самом деле создается!) И дает мне пакет или динамически подключаемую библиотеку, как я хочу, используя ваш код. Глупая ошибка! Является ли хорошей практикой для setup.py очищать каталог перед установкой? Большинство людей будут устанавливать мой пакет с помощью pip. - person Dan; 23.12.2015
comment
Нет. Обычно setup.py будет перестраиваться только в том случае, если фактический исходный код C изменился, и обычно это имеет смысл. Это произойдет только в том случае, если вы измените сам процесс сборки (как вы сделали во время его разработки). Если в вашем случае вы планируете поддерживать два режима сборки (пакетный и динамический), я бы предложил иметь разные выходные данные для каждого режима, чтобы избежать такой ошибки. - person Uri Barkai; 23.12.2015