【问题标题】:Force compiler when running python setup.py install运行 python setup.py install 时强制编译
【发布时间】:2016-01-24 17:09:39
【问题描述】:

有没有办法在运行python setup.py install 时显式强制编译器构建 Cython 扩展?其中setup.py 的形式为:

import os.path
import numpy as np
from setuptools import setup, find_packages, Extension
from Cython.Distutils import build_ext

setup(name='test',
  packages=find_packages(),
  cmdclass={'build_ext': build_ext},
  ext_modules = [ Extension("test.func", ["test/func.pyx"]) ],
  include_dirs=[np.get_include()]
 )

我正在尝试使用 Anaconda 3.16、Python 3.4、setuptools 18、Numpy 1.9 和 Cython 0.24 在 Windows 8.1 x64 上安装软件包。部署脚本改编自 Cython wikithis Stack Overflow 答案。

Makefile.bat

:: create and activate a virtual environement with conda
conda create --yes -n test_env cython setuptools=18 pywin32 libpython numpy=1.9 python=3
call activate test_env

:: activate the MS SDK compiler as explained in the Cython wiki
cd C:\Program Files\Microsoft SDKs\Windows\v7.1\
set MSSdk=1
set DISTUTILS_USE_SDK=1
@call .\Bin\SetEnv /x64 /release 

cd C:\test
python setup.py install

问题在于,在这种情况下,setup.py install 仍然使用 conda 附带的 mingw 编译器,而不是 MS Windows SDK 7.1。

  • 所以DISTUTILS_USE_SDK=1MSSdk=1 似乎对构建没有影响。我不确定从 conda virtualenv 中激活 MS SDK 是否是个问题。

  • 运行 python setup.py build_ext --compiler=msvc 可以使用 MS 编译器正确构建扩展,但随后运行 setup.py install 会再次使用 mingw 重新编译它。同样适用于python setup.py build --compiler=msvc

  • 还尝试运行%COMSPEC% /E:ON /V:ON /K "%PROGRAMFILES%\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd",如上面链接的答案中所述,但对我来说,这会产生一个新的终端提示,以黄色着色,并停止安装过程。

有没有办法强制编译器构建这个包,例如,通过编辑setup.py

【问题讨论】:

  • 尝试使用python setup.py build_ext --compiler=msvc --force 强制编译器构建/重建包,看看会发生什么。
  • @romeric 所以build_ext 按预期使用MS VC 构建扩展(有和没有--force 标志)。问题是当我运行 install 时,它会用 mingw 重建。

标签: python cython setuptools anaconda


【解决方案1】:

您可以在名为 setup.cfg 的单独文件中为 distutils 提供(默认)命令行参数(与您的 setup.py 平行放置)。请参阅docs 了解更多信息。要设置编译器,请使用以下内容:

[build]
compiler=msvc

现在调用python setup.py build 等同于调用python setup.py build --compiler=msvc。 (您仍然可以通过调用 python setup.py build --compiler=someothercompiler 来指示 distutils 使用其他编译器)

现在你已经(成功指示 distutils 使用 a msvc 编译器。不幸的是,没有选项告诉它使用 哪个 msvc 编译器。基本上有两个选项:

一:什么都不做,distutils 将尝试定位 vcvarsall.bat 并使用它来设置环境。 vcvarsall.bat(以及它为其设置环境的编译器)是 Visual Studio 的一部分,因此您必须安装它才能使其工作。

二:安装 Windows SDK 并告诉 distutils 使用它。请注意,DISUTILS_USE_SDK 这个名字相当容易误导(至少在我看来)。它实际上并没有告诉 distutils 使用 SDK(它是 setenv.bat)来设置环境,而是意味着 distutils 应该假设环境已经设置。这就是为什么您必须使用某种Makefile.bat,正如您在 OP 中显示的那样。

旁注: VisualStudio 或 Windows SDK 的具体版本取决于目标 python 版本。

【讨论】:

  • 感谢您的回答,在 setup.cfg 中指定编译器确实可以解决 Windows 上的问题。问题是简单地添加这个文件也会破坏应该使用 gcc 编译器而不是 MS VC 的 Linux 上的安装。当然有可能在运行时生成setup.cfg,但我想知道是否可以通过setup.py 破解编译器选项,这会更灵活......
  • 作为事后的想法:我想,你可以破解 distutils 来做你想做的事,毕竟我们在这里谈论的是 Python。目标点可能是build_ext 命令,如重新创建修改版本或派生修改现有版本。然而,我的印象是整个 distutils 相当复杂(这可能源于事物的性质,并且是不可避免的),因此乍一看很难理解。 MS 编译器设置相当复杂,由于担心破坏向后兼容性(我的看法和猜测)而没有经常被触及
  • setup.cfg 是用户可以完全控制的文件。您不应将其与您的代码一起分发。
【解决方案2】:

备注:在 linux 上,您可以使用许多 autoconf 环境变量。对于编译器

CC=mpicc python setup.py build_ext -i

【讨论】:

    【解决方案3】:

    好吧,我在我的案例中发现了一个技巧:我想使用 MSVC14.0(来自 buildtools 2015)而不是 MSVC14.1(buildtools 2017)。我编辑了文件 Lib\distutils_msvccompiler.py。有一种方法

    _find_vcvarsall 
    

    正在调用

    best_version, best_dir = _find_vc2017()
    

    我把这个电话替换为

    best_version, best_dir = _find_vc2015()
    

    不要忘记在编译后撤消这个肮脏的把戏。

    【讨论】:

      【解决方案4】:

      我最终把它放在 setup.py 的开头来强制 visual2015

      在非 bat 环境中运行并且不能从外部启动 vcvarsall 时很有用

      if sys.platform == 'win32':
          # patch env with vcvarsall.bat from vs2015 (vc14)
          try:
              cmd = '"{}..\\..\\VC\\vcvarsall.bat" x86_amd64 >nul 2>&1 && set'.format(environ['VS140COMNTOOLS'])
              out = subprocess.check_output(cmd, stderr=subprocess.STDOUT, universal_newlines=True)
          except:
              print("Error executing {}".format(cmd))
              raise
      
          for key, _, value in (line.partition('=') for line in out.splitlines()):
              if key and value:
                  os.environ[key] = value
      
          # inform setuptools that the env is already set
          os.environ['DISTUTILS_USE_SDK'] = '1'
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-28
        • 2016-04-01
        • 2016-01-28
        • 1970-01-01
        • 2018-10-06
        • 1970-01-01
        相关资源
        最近更新 更多