【问题标题】:Can I achieve precise control over location of .c files generated by cythonize?我可以精确控制 cythonize 生成的 .c 文件的位置吗?
【发布时间】:2019-05-13 15:48:46
【问题描述】:

我正在使用 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.pydC:\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 中的建议为cythonize 设置build_dir 参数,但它似乎没有按我的意愿工作。 我还尝试按照another answer 在该问题上使用cython_c_in_temp,但这没有效果(从我对 Cython 源代码的检查来看,根本不适用于cythonize 调用)。

我尝试为source 使用绝对路径,但这让事情变得更糟,因为 C 文件最终生成在 demo.py 旁边,在源代码树内部(如 @987654351 @)。

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


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

  1. 将所有 Python 源文件从它们在C:\mypath\src 中的位置复制到生成的setup.py 旁边,这样我就可以在路径中没有.. 的情况下引用它们。 这可能会解决问题,但会给(已经很长的)构建过程带来数十种我宁愿避免的额外文件复制操作的负担。
  2. 由于文件最终的路径似乎是通过连接“setup.py的目录+build_dir的值+source的值”组成的,我可以计算..的数量source 路径并指定 build_dir 足够深,以便评估结果为我真正想要的路径。 这既非常hacky又非常脆弱。

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

【问题讨论】:

  • 我怀疑你的选项 #1 可能是最好的选择

标签: python cython cythonize


【解决方案1】:

看来您遇到了错误。这是相关的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 的缩写形式)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 1970-01-01
    • 2017-08-19
    • 2012-02-11
    • 1970-01-01
    • 2018-07-19
    • 2012-06-17
    相关资源
    最近更新 更多