简体   繁体   English

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

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

I am using Cython as part of my build setup for a large project, driven by CMake. 我使用Cython作为我的构建设置的一部分,由CMake驱动的大型项目。 I can't seem to get Cython to generate the .c files in a sensible location. 我似乎无法让Cython在合理的位置生成.c文件。

My file layout: 我的文件布局:

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

My setup.py is generated by CMake (a lot of it depends on configure_file ), in the location specified above. 我的setup.py是由CMake生成的(很多都取决于configure_file ),位于上面指定的位置。 This location conforms to the usual structure of the overarching project (which builds over a hundred libraries and executables) and is not something I want to (or can easily) change. 这个位置符合总体项目的常规结构(它构建了超过一百个库和可执行文件),并不是我想要(或可以轻易)改变的东西。

The generated setup.py looks like this: 生成的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)

(Note that this is heavily simplified compared to the real case, which passes many additional arguments in extension_args , and includes many source files, each with its own object in modules . Nevertheless, I have verified that the minimised version above reproduces my issue). (请注意,与实际情况相比,这大大简化了,它在extension_args传递了许多其他参数,并且包含许多source文件,每个文件在modules都有自己的对象。但是,我已经验证上面的最小化版本再现了我的问题)。

Cython is run like this: 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

Ideally, I would want all intermediary build artefacts from Cython (the generated C files, object files, exp files, etc.) to reside somewhere in or below C:\\mypath\\build\\projects\\cyt . 理想情况下,我希望Cython中的所有中间构建工件(生成的C文件,目标文件,exp文件等)都驻留在C:\\mypath\\build\\projects\\cyt或之下。 However, I can't seem to achieve that. 但是,我似乎无法实现这一目标。 Here is where build artefacts actually end up: 以下是构建文物最终的结果:

  • demo.pyd ends up in C:\\mypath\\build\\bin , where I want it. demo.pyd最终在C:\\mypath\\build\\bin ,我想要它。 No problem here. 这里没问题。
  • The object file demo.obj , along with the linked files demo.exp and demo.lib , end up in C:\\mypath\\build\\projects\\src . 目标文件demo.obj以及链接文件demo.expdemo.lib最终位于C:\\mypath\\build\\projects\\src I want them inside cyt . 我希望他们在cyt
  • The C file demo.c ends up in C:\\mypath\\build\\src . C文件demo.c最终在C:\\mypath\\build\\src Again, I want this in projects\\cyt . 再次,我想在projects\\cyt这个。

In the setup.py , I am setting the build_dir parameter for cythonize as suggested in this answer , but it doesn't seem to work as I would like. setup.py ,我按照本答案中的建议设置了build_dir参数,但它似乎没有按照我的cythonize工作。 I also tried using cython_c_in_temp as per another answer on that question, but that has no effect (and judging from my inspection of Cython source code, does not apply to cythonize calls at all). 我也尝试使用cython_c_in_temp作为该问题的另一个答案 ,但这没有效果(从我对Cython源代码的检查判断,根本不适用于cythonize调用)。

I tried using an absolute paths for source , but that made things even worse, as the C file ended up generated right next to demo.py , inside the source tree (as C:\\src\\demo.c ). 我尝试使用绝对路径作为source ,但这使事情变得更糟,因为C文件最终生成在源代码树demo.py旁边(如C:\\src\\demo.c )。

My question: How can I make sure that all the generated intermediary files (C, obj, and friends) end up in the same directory as the generated setup.py , or below that? 我的问题:如何确保所有生成的中间文件(C,obj和朋友)最终与生成的setup.py位于同一目录中,或者在下面?


I can think of two workarounds for my situation, but they both feel like hacks which I would like to avoid: 我可以为我的情况考虑两种解决方法,但它们都像我想要避免的黑客:

  1. Copy all the Python source files from their locations in C:\\mypath\\src to alongside the generated setup.py , so that I can refer to them without .. in the path. 将所有Python源文件从C:\\mypath\\src的位置复制到生成的setup.py旁边,这样我就可以在路径中引用它们而不用.. That would likely solve the issue, but burdens the (already long) build process with tens of additional file copy operations I'd rather avoid. 这可能会解决问题,但是(我已经很长时间)构建过程会增加数十个额外的文件复制操作,我宁愿避免。
  2. Since the path where the files end up seems to be composed by concatenating "the directory of setup.py + the value of build_dir + the value of source ", I could count the number of .. in the source path and specify build_dir deep enough so that the evaluation results in the path I actually want. 由于文件结尾的路径似乎是通过连接“ setup.py的目录+ build_dir的值+ source的值”来组成的,所以我可以计算source路径中的..的数量并指定build_dir足够深以便评估结果在我真正想要的路径上。 This is both extremely hacky and very fragile. 这非常hacky非常脆弱。

I hope a better solution exists. 我希望有更好的解决方案。

So it seems like you've run into a bug. 所以你好像遇到了一个bug。 Here's the relevant section of code in Cython . 这是Cython中相关的代码部分 Basically, cythonize will try to build the paths to your .c and .o files as so: 基本上, cythonize将尝试构建.c.o文件的路径,如下所示:

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

and so instead of nicely contained temporary files, you end up with insanity. 因此,你最终会有精神错乱,而不是很好地包含临时文件。 Using an absolute path to demo.py won't help either, since that same code will just pass absolute paths through unchanged. 使用demo.py的绝对路径也demo.py ,因为相同的代码只会传递绝对路径。

There doesn't seem to be a way to fix this in user-space short of extensive monkey-patching, so I submitted a pull-request to Cython with an actual fix . 似乎没有办法在用户空间中解决这个问题,而不是广泛的猴子修补,所以我向Cython提交了一个实际修复拉取请求 Once that's been merged in, you should then be able to run: 一旦合并,您应该能够运行:

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

to get the result you want ( -b and -t are the short forms of --build-lib and --build-temp ). 获得你想要的结果( -b-t--build-lib--build-temp的简短形式)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM