Могу ли я добиться точного контроля над расположением файлов .c, созданных cythonize?

Я использую Cython как часть настройки сборки для большого проекта, управляемого CMake. Кажется, я не могу заставить Cython генерировать файлы .c в разумном месте.

Мой макет файла:

C:\mypath\src\demo.py                   # Cython source file
C:\mypath\build\bin                     # I want demo.pyd to end up here
C:\mypath\build\projects\cyt\setup.py   # Generated by CMake

Мой setup.py генерируется CMake (многое зависит от configure_file) в месте, указанном выше. Это расположение соответствует обычной структуре всеобъемлющего проекта (в котором собрано более сотни библиотек и исполняемых файлов) и не является чем-то, что я хочу (или могу легко) изменить.

Сгенерированный setup.py выглядит так:

from distutils.core import setup, Extension
from Cython.Build import cythonize
import os.path

extension_args = {
    'extra_compile_args' : ['/DWIN32','/DWIN64'],
    'extra_link_args'    : ['/MACHINE:X64'],
}

source = '../../../src/demo.py'
modules = [Extension(
    os.path.splitext(os.path.basename(source))[0],
    sources = [source],
    **extension_args
    )]

modules = cythonize(
    modules,
    build_dir = 'BUILD_DIR',
    compiler_directives = {'language_level' : 2}
)

setup(name        = 'demo',
      version     = '0.1',
      description = '',
      ext_modules = modules)

(Обратите внимание, что это сильно упрощено по сравнению с реальным случаем, который передает много дополнительных аргументов в extension_args и включает много файлов source, каждый со своим собственным объектом в modules. Тем не менее, я убедился, что приведенная выше свернутая версия воспроизводит мою проблему).

Cython запускается следующим образом:

cd C:\mypath\build\projects\cyt
python setup.py build_ext --build-lib C:/mypath/build/bin --build-temp C:/mypath/build/projects/cyt

В идеале я хотел бы, чтобы все промежуточные артефакты сборки из Cython (сгенерированные файлы C, объектные файлы, файлы exp и т. д.) находились где-то в C:\mypath\build\projects\cyt или ниже. Однако я не могу этого добиться. Вот где на самом деле оказываются артефакты сборки:

  • demo.pyd оказывается в C:\mypath\build\bin, где я хочу. Здесь нет проблем.
  • Объектный файл demo.obj вместе со связанными файлами demo.exp и demo.lib попадает в C:\mypath\build\projects\src. Я хочу, чтобы они были внутри cyt.
  • Файл C demo.c заканчивается в C:\mypath\build\src. Опять же, я хочу это в projects\cyt.

В setup.py я устанавливаю параметр build_dir для cythonize, как это предлагается в этом ответе, но, похоже, это не работает как я хотел бы. Я также пытался использовать cython_c_in_temp в соответствии с другим ответом на этот вопрос, но это не имеет никакого эффекта (и, судя по моей проверке Cython исходный код, вообще не применяется к вызовам cythonize).

Я попытался использовать абсолютные пути для source, но это сделало ситуацию еще хуже, так как файл C был сгенерирован рядом с demo.py, внутри исходного дерева (как C:\src\demo.c).

Мой вопрос: как я могу убедиться, что все сгенерированные промежуточные файлы (C, obj и др.) оказываются в том же каталоге, что и сгенерированный setup.py, или ниже?


Я могу придумать два обходных пути для моей ситуации, но они оба кажутся хаками, которых я хотел бы избежать:

  1. Скопируйте все исходные файлы Python из их расположений в C:\mypath\src рядом с сгенерированным setup.py, чтобы я мог ссылаться на них без .. в пути. Это, вероятно, решило бы проблему, но обременяет (и без того длинный) процесс сборки десятками дополнительных операций копирования файлов, которых я бы предпочел избежать.
  2. Поскольку путь, по которому заканчиваются файлы, кажется, состоит из конкатенации «каталог setup.py + значение build_dir + значение source», я мог бы подсчитать количество .. в пути source и указать build_dir достаточно глубоко, чтобы результаты оценки по пути, который я действительно хочу. Это очень хакерский и очень хрупкий.

Я надеюсь, что существует лучшее решение.


person Angew is no longer proud of SO    schedule 12.12.2018    source источник
comment
Я подозреваю, что ваш вариант № 1 может быть лучшим выбором   -  person lxop    schedule 12.12.2018


Ответы (1)


Итак, похоже, вы столкнулись с ошибкой. Вот соответствующий раздел кода на Cython . По сути, cythonize попытается построить пути к вашим файлам .c и .o следующим образом:

C:/mypath/build/projects/cyt/BUILD_DIR/../../../src/demo.c

и поэтому вместо хорошо содержащихся временных файлов вы получаете безумие. Использование абсолютного пути к demo.py также не поможет, так как тот же код просто пропустит абсолютные пути без изменений.

Кажется, нет способа исправить это в пользовательском пространстве, кроме обширного исправления обезьян, поэтому я отправил запрос на добавление в Cython с актуальным исправлением. Как только это будет объединено, вы сможете запустить:

cd C:\mypath\build\projects\cyt
python setup.py build_ext -b C:/mypath/build/bin -t .

чтобы получить желаемый результат (-b и -t — это короткие формы --build-lib и --build-temp).

person tel    schedule 17.12.2018