我有一个Distutils setup.py脚本,它使用new_compiler()。compile()来编译测试程序,以确保系统上有某些功能(例如MPI)。
我的问题是有一种情况是compile()调用导致编译器错误,但手动编译相同的小测试程序却没有。错误在标准头文件(mpi.h)中。我所有的实际源文件也都包含这个标题,但它们编译得很好!这个特殊的检查对我来说非常有用,但我需要弄清楚为什么它不应该失败。
所以我的问题是,如何获得ccompiler.compile()使用的实际命令?
答案 0 :(得分:3)
Adam(Wagner)的评论是正确的开始:您必须通过Distutils源代码进行搜索。有很多抽象级别,所以你必须通过几个不同的文件来跟踪执行,但这里是要点:
distutils.ccompiler
包括一个抽象类CCompiler
,它处理调用实际的编译器。它具有编译器需要执行的各种任务的方法:preprocess
,compile
和link
。除CCompiler
之外,compile
本身不实现任何这些方法,但即使在那里,它也会将实际的编译器调用委托给方法_compile
。因此,您需要检查平台上使用的CCompiler
的子类,并查看其_compile
的实现。CCompiler
有几个不同的子类,每个子类都在自己的包中实现,但“big two”是distutils.unixccompiler.UnixCCompiler
(在类UNIX系统上调用本机编译器)和{{ 1}}(调用Visual Studio)。这两个都使用函数distutils.msvccompiler.MSVCCompiler
来实际运行外部进程。distutils.spawn.spawn
的源代码中,您会注意到每个命令在运行之前都会记录在distutils.spawn.spawn
级别。但问题是,这不使用Python的内置日志记录系统;而是使用Distutils在INFO
中实现的自定义记录器。如果您现在查看distutils.log
的来源,您会看到有一个设置日志记录级别的函数distutils.log
。不幸的是,它与Distutils中的任何其他调试基础结构无关(例如set_verbosity
环境变量),因此您需要手动调用
DISTUTILS_DEBUG
在运行任何编译命令之前,在安装脚本中的某处。一旦这样做,所有编译命令(以及谁知道其他信息)应该打印到标准输出。
答案 1 :(得分:2)
这已经很晚了,但是我发现如何在python中做这个(没有检查日志)以防万一有人想知道:
import distutils.sysconfig
import distutils.ccompiler
compiler = distutils.ccompiler.new_compiler()
distutils.sysconfig.customize_compiler(compiler)
print compiler.compiler_so # This attribute is what you want
“compiler_so”属性是distutils在编译时会使用的每个参数的列表。它在实际开始编译时添加了文件名和-c
(对于目标文件)。
EDIT2:我应该补充一下,它不是完整的命令,而只是distutils之前的参数处理任何Extension()实例。其余参数对于扩展是唯一的,并且取决于您在创建Extension类时提供的arguments,例如sources,include_dirs,define_macros。
如果你想要运行distutils的完整原始命令,我知道的唯一方法(不解析日志)是在所有处理之后的最后一分钟和the spawn function之前获取命令字符串。这是一种令人难以置信的hacky方式:
# Put this at the very top of all your imports
import distutils.spawn
old_spawn = distutils.spawn.spawn
def my_spawn(*args, **kwargs):
print " ".join(args[0]) # <-- this is your command right here
old_spawn(*args, **kwargs)
distutils.spawn.spawn = my_spawn
更优雅的事情是fork distutils并添加这个功能,但这就像这么多的工作和东西。
答案 2 :(得分:0)
此外,如果您想查看链接器标志,可以执行以下操作:
import distutils.sysconfig
import distutils.ccompiler
compiler = distutils.ccompiler.new_compiler()
distutils.sysconfig.customize_compiler(compiler)
print compiler.linker_so # This gives linker information