Укажите альтернативный компоновщик при сборке расширений python / cython? - PullRequest
2 голосов
/ 03 марта 2020

В попытке ускорить процесс разработки, я пытался использовать компоновщик 'gold' или многопоточный компоновщик 'lld' вместо компоновщика GNU при компиляции некоторых расширений Cython. В моем файле setup.py я пробовал что-то вроде следующего:

lld_linker = shutil.which('ld.lld')
if lld_linker:
    print("Using LLD Linker in place of GNU LD")
    os.environ['LDSHARED'] = lld_linker    

Однако это приводит к сбою процесса компоновки с большим количеством "/ usr / bin / ld: ..... undefined ссылка на ..... "ошибки. (Сборка работает нормально, без добавления этого LDSHARED envvar). Поведение сбоя одинаково как при использовании этого внутреннего os.environ, так и при экспорте envvar перед вызовом setup.py. У меня есть предчувствие, что, возможно, многопроцессорный подход Cython к распределению заданий компиляции не позволяет везде хранить переменную среды, что приводит к такому сочетанию компоновщиков? Так же, как с компоновщиком GNU ld?

Здесь есть связанный вопрос: Как указать компоновщик при сборке python расширений? ; однако, это не решило мою проблему, как упомянуто ранее.

1 Ответ

1 голос
/ 03 марта 2020

Обычно distutils / setuptools не используют компоновщик напрямую, а вызывают внешний интерфейс, например gcc для c -расширения или g++ для c ++ - расширений.

Эти интерфейсы собрать всю необходимую информацию - например, какие библиотеки следует передать компоновщику, например, libstdc++ для расширений c ++ - и вызвать компоновщик с правильными параметрами командной строки. Это можно увидеть при передаче опции -v в gcc - g++ -фронтенда, например, через extra_link_args в setup.py.

Так что если вы нажмете distutuls / setuptools.py чтобы использовать ld напрямую, вы также должны предоставить все опции, собранные веб-интерфейсом в extra_link_args, в противном случае некоторые библиотеки будут отсутствовать, и компиляция, как вы видите, завершится неудачей.

Это довольно сложно разрешить setup.py, чтобы выбрать другой компоновщик, но есть несколько дешевых вариантов сделать это локально:

  1. Компоновщик по умолчанию (например, /usr/bin/ld) - это просто символическая ссылка, пусть он указывает на компоновщик Ваш выбор.
  2. Передача -B -опция через extra_link_args, т.е. -B/path/to/folder/with/my/linker. Тонкие детали: 1) компоновщик должен называться ld (при необходимости создайте символическую ссылку) 2) некоторые дистрибутивы (например, Anaconda) уже предоставляют опцию -B, которая имеет приоритет над путем, пройденным через extra_link_args , В этом случае одним из возможных решений было бы модифицировать выдаваемую командную строку, как описано в этом SO-post .
  3. , установить компоновщик напрямую через переменную окружения LDSHARED и предоставить все необходимые параметры в extra_link_args.

Вариант 2, вероятно, проще всего настроить для работы в любой системе:

  1. определить, есть ли ld.lld, если да:
  2. создать временную папку с символической ссылкой на нее (называемую ld)
  3. добавить эту временную папку как -B -опции в extra_link_args
  4. определить, использует ли уже дистрибутив Опция -B, манипулирование командной строкой (как описано здесь , например), чтобы обеспечить приоритет временной папки.
...