我可以精确控制cythonize生成的.c文件的位置吗?

Can I achieve precise control over location of .c files generated by 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 文件,每个文件在 [=19= 中都有自己的对象]. 尽管如此,我已经确认上面的最小化版本重现了我的问题。

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 或以下的某个位置。 但是,我似乎无法做到这一点。 这是构建工件实际结束的地方:

setup.py 中,我按照 中的建议为 cythonize 设置了 build_dir 参数,但它似乎并没有像我希望的那样工作. 我还尝试根据 对该问题使用 cython_c_in_temp,但这没有任何效果(并且从我对 Cython 源代码的检查来看,根本不适用于 cythonize 调用)。

我尝试为 source 使用绝对路径,但这让事情变得更糟,因为 C 文件最终生成在 demo.py 内部 [=89] =] 源代码树(如 C:\src\demo.c)。

我的问题:如何确保所有生成的中间文件(C、obj 和朋友)最终与生成的目录位于同一目录中setup.py,还是低于这个?


对于我的情况,我可以想到两种解决方法,但它们都像是我想避免的黑客攻击:

  1. 将所有 Python 源文件从它们在 C:\mypath\src 中的位置复制到生成的 setup.py 旁边,这样我就可以在路径中没有 .. 的情况下引用它们. 这可能会解决问题,但会增加(已经很长的)构建过程的负担,因为我宁愿避免数十个额外的文件复制操作。
  2. 由于文件结束的路径似乎是由 "the directory of setup.py + the value of build_dir + the value of source" 串联而成,我可以计算 source 路径中 .. 的数量并指定 build_dir 足够深,以便评估结果符合我真正想要的路径。 这既非常骇人听闻又非常脆弱。

我希望有更好的解决方案。

看来您 运行 遇到了错误。这是相关的 section of code in Cython。基本上,cythonize 将尝试构建 .c.o 文件的路径,如下所示:

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

所以你最终会变得精神错乱,而不是很好地包含临时文件。使用 demo.py 的绝对路径也无济于事,因为相同的代码只会通过绝对路径而不改变。

除了广泛的猴子修补之外,似乎没有办法在用户 space 中解决这个问题,所以我提交了一个 pull-request to Cython with an actual fix。合并后,您应该可以 运行:

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

得到你想要的结果(-b-t--build-lib--build-temp的缩写形式)。