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

时间:2018-12-12 14:01:26

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

setup.py中,我按照this answer的建议为build_dir设置了cythonize参数,但是它似乎并没有达到我想要的效果。 我还尝试在此问题上按照another answer使用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,以便评估得出我实际想要的路径。 这既骇人又脆弱。

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

1 个答案:

答案 0 :(得分:3)

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

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

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

在没有广泛的猴子补丁的用户空间中,似乎没有办法解决此问题,因此我提交了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的缩写)。