diff -r ec3077e23b7d -r 218ef482e1e4 Lib/distutils/msvc9compiler.py --- a/Lib/distutils/msvc9compiler.py Sun Oct 05 21:20:51 2014 -0400 +++ b/Lib/distutils/msvc9compiler.py Sun Oct 05 12:55:17 2014 +0200 @@ -51,7 +51,7 @@ # A map keyed by get_platform() return values to values accepted by # 'vcvarsall.bat'. Note a cross-compile may combine these (eg, 'x86_amd64' is -# the param to cross-compile on x86 targetting amd64.) +# the param to cross-compile on x86 targeting amd64.) PLAT_TO_VCVARS = { 'win32' : 'x86', 'win-amd64' : 'amd64', @@ -248,25 +248,35 @@ log.debug("Unable to find vcvarsall.bat") return None -def query_vcvarsall(version, arch="x86"): - """Launch vcvarsall.bat and read the settings from its environment +def run_vcvarsall(vcvarsall, version, arch): + """Launch vcvarsall.bat and collect its environment as output """ - vcvarsall = find_vcvarsall(version) - interesting = set(("include", "lib", "libpath", "path")) - result = {} - - if vcvarsall is None: - raise DistutilsPlatformError("Unable to find vcvarsall.bat") log.debug("Calling 'vcvarsall.bat %s' (version=%s)", arch, version) popen = subprocess.Popen('"%s" %s & set' % (vcvarsall, arch), stdout=subprocess.PIPE, stderr=subprocess.PIPE) try: stdout, stderr = popen.communicate() - if popen.wait() != 0: - raise DistutilsPlatformError(stderr.decode("mbcs")) + finally: + popen.stdout.close() + popen.stderr.close() + if popen.returncode != 0: + stderr = stderr.decode("mbcs") + log.debug("'vcvarsall.bat %s' (version=%s) call failed - %s", arch, + version, stderr) + raise DistutilsPlatformError(stderr) + return stdout.decode("mbcs") - stdout = stdout.decode("mbcs") +def query_vcvarsall(version, archs=["x86"]): + """Launch vcvarsall.bat and read the settings from its environment + """ + vcvarsall = find_vcvarsall(version) + if vcvarsall is None: + raise DistutilsPlatformError("Unable to find vcvarsall.bat") + interesting = set(("include", "lib", "libpath", "path")) + for arch in archs: + stdout = run_vcvarsall(vcvarsall, version, arch) + result = {} for line in stdout.split("\n"): line = Reg.convert_mbcs(line) if '=' not in line: @@ -278,15 +288,11 @@ if value.endswith(os.pathsep): value = value[:-1] result[key] = removeDuplicates(value) - - finally: - popen.stdout.close() - popen.stderr.close() - - if len(result) != len(interesting): - raise ValueError(str(list(result.keys()))) - - return result + if len(result) == len(interesting): + return result + log.debug("'vcvarsall.bat %s' (version=%s) call collected unexpected " + "environment: %s", arch, version, list(result.keys())) + raise DistutilsPlatformError("vcvarsall.bat environment setup failure") # More globals VERSION = get_build_version() @@ -355,18 +361,26 @@ self.rc = "rc.exe" self.mc = "mc.exe" else: - # On x86, 'vcvars32.bat amd64' creates an env that doesn't work; - # to cross compile, you use 'x86_amd64'. - # On AMD64, 'vcvars32.bat amd64' is a native build env; to cross - # compile use 'x86' (ie, it runs the x86 compiler directly) + # On x86, 'vcvarsall.bat amd64' creates an env that doesn't work; + # to cross-compile, you use 'x86_amd64'. + # On AMD64, 'vcvarsall.bat amd64' is a native build env; to + # cross-compile use 'x86' (ie, it runs the x86 compiler directly) # No idea how itanium handles this, if at all. - if plat_name == get_platform() or plat_name == 'win32': - # native build or cross-compile to win32 - plat_spec = PLAT_TO_VCVARS[plat_name] + if plat_name == 'win32': + # native win32 build or cross-compile to win32 + plat_spec = [PLAT_TO_VCVARS[plat_name]] else: - # cross compile from win32 -> some 64bit - plat_spec = PLAT_TO_VCVARS[get_platform()] + '_' + \ - PLAT_TO_VCVARS[plat_name] + cross_plat_spec = PLAT_TO_VCVARS['win32'] + '_' + \ + PLAT_TO_VCVARS[plat_name] + if plat_name == get_platform(): + # native 64-bit build + # In case a native 64-bit compiler is not available, as is + # the case with Visual Studio Express edition, try to use a + # 32-bit --> 64-bit cross-compiler instead. + plat_spec = [PLAT_TO_VCVARS[plat_name], cross_plat_spec] + else: + # cross-compile to some 64-bit + plat_spec = [cross_plat_spec] vc_env = query_vcvarsall(VERSION, plat_spec)