使用 rpython 在 windows 下生成的程序无法运行

在 windows 用rpython编译出的文件总是无法运行,报
通过跟踪发现,rpython 每次都会将生成的C代码、Makefile 等放置在 %TEMP%\usession-release-2.0.x-17\testing_1 中(17是序号,每次都会自增),进去此目录,发现可执行文件是可以执行的——因为编译目录里是有manifest文件的。
 
Makefile 的生成是在 pypy-2.0.2-src\rpython\translator\c\genc.py 中的 CStandaloneBuilder::gen_makefile 中完成的,其间会调用平台相关的代码 pypy-2.0.2-src\rpython\translator\platform\windows.py 中的 MsvcPlatform::gen_makefile ,而 MsvcPlatform::gen_makefile 会试图在链接阶段嵌入manifest。代码如下——先判断编译器版本 self.version,如果大于等于 VC2005 就会在Makefile中输出 调用 mt.exe 嵌入manifest文件的步骤。
    def gen_makefile(self, cfiles, eci, exe_name=None, path=None,
                     shared=False):
        ……
        if self.version < 80:
            m.rule('$(TARGET)', '$(OBJECTS)',
                    create_obj_response_file + [\
                   '$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA)' + objects + ' /out:$@ $(LIBDIRS) $(LIBS)',
                   ])
        else:
            m.rule('$(TARGET)', '$(OBJECTS)',
                    create_obj_response_file + [\
                    '$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA)' + objects + ' $(LINKFILES) /out:$@ $(LIBDIRS) $(LIBS) /MANIFEST /MANIFESTFILE:$*.manifest',
                    'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1',
                    ])
至此,可以明白是 self.version 的值不正确。而执行命令 cl 获取编译器版本时,stderr的可能输出如下
中文版 VC2008输出
用于 80x86 的 Microsoft (R) 32 位 C/C++ 优化编译器 15.00.30729.01 版
版权所有(C) Microsoft Corporation。保留所有权利。
 
用法: cl [ 选项... ] 文件名... [ /link 链接选项... ]
 
英文版VC2010输出
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.30319.01 for 80x86
Copyright (C) Microsoft Corporation.  All rights reserved.

usage: cl [ option... ] filename... [ /link linkoption... ]
 
可见是解析 stderr 时出问题了。如下所示,只需将 match 改search 即可
 
    def __init__(self, cc=None, x64=False):
        self.x64 = x64
        msvc_compiler_environ = find_msvc_env(x64)
        Platform.__init__(self, 'cl.exe')
        if msvc_compiler_environ:
            self.c_environ = os.environ.copy()
            self.c_environ.update(msvc_compiler_environ)
            # XXX passing an environment to subprocess is not enough. Why?
            os.environ.update(msvc_compiler_environ)
 
        # detect version of current compiler
        returncode, stdout, stderr = _run_subprocess(self.cc, '',
                                                     env=self.c_environ)
        r = re.search(r'Microsoft.+C/C\+\+.+\s([0-9]+)\.([0-9]+).*', stderr)
        if r is not None:
            self.version = int(''.join(r.groups())) / 10 - 60
        else:

 见 https://bugs.pypy.org/issue1524

 
 

posted on 2013-07-02 17:41  JesseFang  阅读(751)  评论(0编辑  收藏  举报