关于python:我可以对cythonize生成的.c文件的位置进行精确控制吗?

Can I achieve precise control over location of .c files generated by cythonize?

我正在使用Cython作为CMake驱动的大型项目的构建设置的一部分。
我似乎无法让Cython在合理的位置生成.c文件。

我的文件布局:

1
2
3
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看起来像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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的运行方式如下:

1
2
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.expdemo.lib都以C:\\mypath\\build\\projects\\src结尾。我希望它们在cyt中。
  • C文件demo.cC:\\mypath\\build\\src结尾。同样,我要在projects\\cyt中使用它。

setup.py中,我按照此答案中的建议设置了cythonizebuild_dir参数,但是它似乎不起作用。
我还尝试使用cython_c_in_temp作为该问题的另一个答案,但是没有效果(并且从我对Cython源代码的检查来看,根本不适用于cythonize调用)。

我尝试为source使用绝对路径,但这使事情变得更糟,因为C文件最终在源树内部(如C:\\src\\demo.c)紧挨demo.py的位置生成。

我的问题:如何确保所有生成的中间文件(C,obj和Friends)与生成的setup.py都位于同一目录中,或者在该目录下?

我可以针对我的情况考虑两种解决方法,但是它们都像黑客一样,我想避免:

  • 将所有Python源文件从它们在C:\\mypath\\src中的位置复制到生成的setup.py旁边,以便我可以在路径中没有..的情况下引用它们。
    那可能会解决该问题,但是我宁愿避免使用数十个其他文件复制操作来负担(已经很长的)构建过程的负担。
  • 由于文件结束的路径似乎是由" setup.py的目录,build_dir的值,source的值"串联而成的,因此我可以计算source路径中的..数并指定足够深的build_dir,以便评估得出我实际想要的路径。
    这既非常hacky,又非常脆弱。
  • 我希望有更好的解决方案。


    所以看来您遇到了一个错误。这是Cython中代码的相关部分。基本上,cythonize会尝试这样构建.c.o文件的路径:

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

    ,因此您没有很好地包含临时文件,而最终陷入了疯狂。使用demo.py的绝对路径也无济于事,因为相同的代码只会通过不变的方式传递绝对路径。

    在没有大量猴子修补程序的用户空间中,似乎没有办法解决此问题,因此我向Cython提出了一个拉动请求,并进行了实际修复。合并后,您应该可以运行:

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

    以获得所需的结果(-b-t--build-lib--build-temp的缩写)。