diff options
| author | JGoutin <ginnungagap@free.fr> | 2016-02-14 20:15:36 +0000 | 
|---|---|---|
| committer | JGoutin <ginnungagap@free.fr> | 2016-02-14 20:15:36 +0000 | 
| commit | e8f5160ce40e05753d29ced35cf9b246ef12eb2d (patch) | |
| tree | a90978b53f57b9b6d78d9424937433bcf10b5579 /setuptools/msvc9_support.py | |
| parent | 8ccd428cd2a733891bffce13e017774ea82bd8d2 (diff) | |
| download | python-setuptools-git-e8f5160ce40e05753d29ced35cf9b246ef12eb2d.tar.gz | |
Improve support for standalones MVC++ 9.0/10.0 compilers by setting directly the environment if Vcvarsall.bat is missing or fail.
Diffstat (limited to 'setuptools/msvc9_support.py')
| -rw-r--r-- | setuptools/msvc9_support.py | 265 | 
1 files changed, 255 insertions, 10 deletions
diff --git a/setuptools/msvc9_support.py b/setuptools/msvc9_support.py index a69c7474..5dad8db2 100644 --- a/setuptools/msvc9_support.py +++ b/setuptools/msvc9_support.py @@ -48,16 +48,261 @@ def find_vcvarsall(version):      return unpatched['find_vcvarsall'](version)  def query_vcvarsall(version, *args, **kwargs): +    message = '' + +    # Try to get environement from vcvarsall.bat (Classical way)      try:          return unpatched['query_vcvarsall'](version, *args, **kwargs)      except distutils.errors.DistutilsPlatformError as exc: -        if exc and "vcvarsall.bat" in exc.args[0]: -            message = 'Microsoft Visual C++ %0.1f is required (%s).' % (version, exc.args[0]) -            if int(version) == 9: -                # This redirection link is maintained by Microsoft. -                # Contact vspython@microsoft.com if it needs updating. -                raise distutils.errors.DistutilsPlatformError( -                    message + ' Get it from http://aka.ms/vcpython27' -                ) -            raise distutils.errors.DistutilsPlatformError(message) -        raise +        # Error if Vcvarsall.bat is missing +        message = exc.args[0] +    except ValueError as exc: +        # Error if environment not set after executing vcvarsall.bat +        message = exc.args[0] + +    # If vcvarsall.bat fail, try to set environment directly +    try: +        return setvcenv(version, *args, **kwargs) +    except distutils.errors.DistutilsPlatformError as exc: +        # Error if MSVC++ directory not found or environment not set +        message = exc.args[0] + +    # Raise error +    if message and "vcvarsall.bat" in message: +        # Special error message if MSVC++ not installed +        message = 'Microsoft Visual C++ %0.1f is required (%s).' %\ +            (version, message) +        if int(version) == 9: +            # For VC++ 9.0 Redirect user to Vc++ for Python 2.7 : +            # This redirection link is maintained by Microsoft. +            # Contact vspython@microsoft.com if it needs updating. +            message += r' Get it from http://aka.ms/vcpython27' +        elif int(version) == 10: +            # For VC++ 10.0 Redirect user to Windows SDK 7.1 +            message += ' Get it with "Microsoft Windows SDK for Windows 7": ' +            message += r'www.microsoft.com/download/details.aspx?id=8279' +        raise distutils.errors.DistutilsPlatformError(message) +    raise(message) + +def setvcenv(VcVer, arch): +    """ +    Return environment variables for specified Microsoft Visual C++ version +    and platform. +    """ +    from os.path import join, isdir +    from os import environ +    from distutils.errors import DistutilsPlatformError + +    # Find current and target architecture +    CurrentCpu = environ['processor_architecture'].lower() +    TargetCpu = arch[arch.find('_') + 1:] + +    # Find "Windows" and "Program Files" system directories +    WinDir = environ['WinDir'] +    ProgramFiles = environ['ProgramFiles'] +    if CurrentCpu != 'x86': +        ProgramFilesX86 = environ['ProgramFiles(x86)'] +    else: +        ProgramFilesX86 = ProgramFiles + +    # Set registry base paths +    reg_value = distutils.msvc9compiler.Reg.get_value +    if CurrentCpu != 'x86': +        node = r'\Wow6432Node' +    else: +        node = '' +    VsReg = r'Software%s\Microsoft\VisualStudio\SxS\VS7' % node +    VcReg = r'Software%s\Microsoft\VisualStudio\SxS\VC7' % node +    VcForPythonReg = r'Software%s\Microsoft\DevDiv\VCForPython\%0.1f' %\ +        (node, VcVer) +    WindowsSdkReg = r'Software%s\Microsoft\Microsoft SDKs\Windows' % node + +    # Set Platform subdirectories +    if TargetCpu == 'amd64': +        pltsd1, pltsd2 = r'\amd64', r'\x64' +        if CurrentCpu == 'amd64': +            pltsd3 = r'\amd64' +        else: +            pltsd3 = r'\x86_amd64' +    elif TargetCpu == 'ia64': +        pltsd1, pltsd2 = r'\ia64', r'\ia64' +        if CurrentCpu == 'ia64': +            pltsd3 = r'\ia64' +        else: +            pltsd3 = r'\x86_ia64' +    else: +        pltsd1, pltsd2, pltsd3 = '', '', '' + +    # Find Microsoft Visual Studio directory +    try: +        # Try to get it from registry +        VsInstallDir = reg_value(VsReg, '%0.1f' % VcVer) +    except KeyError: +        # If fail, use default path +        VsInstallDir = join(ProgramFilesX86, +                            'Microsoft Visual Studio %0.1f' % VcVer) + +    # Find Microsoft Visual C++ directory +    try: +        # Try to get it from registry +        VcInstallDir = reg_value(VcReg, '%0.1f' % VcVer) +    except KeyError: +        try: +            # Try to get "VC++ for Python" version from registry +            VcInstallDir = join(reg_value(VcForPythonReg, 'installdir'), 'VC') +        except KeyError: +            # If fail, use default path +            VcInstallDir = join(ProgramFilesX86, +                                r'Microsoft Visual Studio %0.1f\VC' % VcVer) +    if not isdir(VcInstallDir): +        raise DistutilsPlatformError('vcvarsall.bat and Visual C++ ' +                                     'directory not found') + +    # Find Microsoft Windows SDK directory +    WindowsSdkDir = '' +    if VcVer == 9.0: +        WindowsSdkVer = ('7.0', '6.1', '6.0a') +    elif VcVer == 10.0: +        WindowsSdkVer = ('7.1', '7.0a') +    else: +        WindowsSdkVer = () +    for ver in WindowsSdkVer: +        # Try to get it from registry +        try: +            WindowsSdkDir = reg_value(join(WindowsSdkReg, 'v%s' % ver), +                                      'installationfolder') +            break +        except KeyError: +            pass +    if not WindowsSdkDir or not isdir(WindowsSdkDir): +        # Try to get "VC++ for Python" version from registry +        try: +            WindowsSdkDir = join(reg_value(VcForPythonReg, 'installdir'), +                                 'WinSDK') +        except: +            pass +    if not WindowsSdkDir or not isdir(WindowsSdkDir): +        # If fail, use default path +        for ver in WindowsSdkVer: +            d = join(ProgramFiles, r'Microsoft SDKs\Windows\v%s' % ver) +            if isdir(d): +                WindowsSdkDir = d +    if not WindowsSdkDir: +        # If fail, use Platform SDK +        WindowsSdkDir = join(VcInstallDir, 'PlatformSDK') + +    # Find Microsoft .NET Framework 32bit directory +    try: +        # Try to get it from registry +        FrameworkDir32 = reg_value(VcReg, 'frameworkdir32') +    except KeyError: +        # If fail, use default path +        FrameworkDir32 = join(WinDir, r'Microsoft.NET\Framework') + +    # Find Microsoft .NET Framework 64bit directory +    try: +        # Try to get it from registry +        FrameworkDir64 = reg_value(VcReg, 'frameworkdir64') +    except KeyError: +        # If fail, use default path +        FrameworkDir64 = join(WinDir, r'Microsoft.NET\Framework64') + +    # Find Microsoft .NET Framework Versions +    if VcVer == 10.0: +        try: +            # Try to get v4 from registry +            v4 = reg_value(VcReg, 'frameworkver32') +            if v4.lower()[:2] != 'v4': +                raise KeyError('Not the V4') +        except KeyError: +            # If fail, use last v4 version +            v4 = 'v4.0.30319' +        FrameworkVer = (v4, 'v3.5') +    elif VcVer == 9.0: +        FrameworkVer = ('v3.5', 'v2.0.50727') +    elif VcVer == 8.0: +        FrameworkVer = ('v3.0', 'v2.0.50727') + +    # Set Microsoft Visual Studio Tools +    VSTools = [join(VsInstallDir, r'Common7\IDE'), +               join(VsInstallDir, r'Common7\Tools')] + +    # Set Microsoft Visual C++ Includes +    VCIncludes = join(VcInstallDir, 'Include') + +    # Set Microsoft Visual C++ & Microsoft Foundation Class Libraries +    VCLibraries = [join(VcInstallDir, 'Lib' + pltsd1), +                   join(VcInstallDir, r'ATLMFC\LIB' + pltsd1)] + +    # Set Microsoft Visual C++ Tools +    VCTools = [join(VcInstallDir, 'VCPackages'), +               join(VcInstallDir, 'Bin' + pltsd3)] +    if pltsd3: +        VCTools.append(join(VcInstallDir, 'Bin')) + +    # Set Microsoft Windows SDK Include +    OSLibraries = join(WindowsSdkDir, 'Lib' + pltsd2) + +    # Set Microsoft Windows SDK Libraries +    OSIncludes = [join(WindowsSdkDir, 'Include'), +                  join(WindowsSdkDir, r'Include\gl')] + +    # Set Microsoft Windows SDK Tools +    SdkTools = [join(WindowsSdkDir, 'Bin')] +    if TargetCpu != 'x86': +        SdkTools.append(join(WindowsSdkDir, 'Bin' + pltsd2)) +    if VcVer == 10.0: +        SdkTools.append(join(WindowsSdkDir, r'Bin\NETFX 4.0 Tools' + pltsd2)) + +    # Set Microsoft Windows SDK Setup +    SdkSetup = join(WindowsSdkDir, 'Setup') + +    # Set Microsoft .NET Framework Tools +    FxTools = [] +    for ver in FrameworkVer: +        FxTools.append(join(FrameworkDir32, ver)) +    if TargetCpu != 'x86' and CurrentCpu != 'x86': +        for ver in FrameworkVer: +            FxTools.append(join(FrameworkDir64, ver)) + +    # Set Microsoft Visual Studio Team System Database +    VsTDb = join(VsInstallDir, r'VSTSDB\Deploy') + +    # Return Environment Variables +    env = {} +    env['include'] = [VCIncludes, OSIncludes] +    env['lib'] = [VCLibraries, OSLibraries, FxTools] +    env['libpath'] = [VCLibraries, FxTools] +    env['path'] = [VCTools, VSTools, VsTDb, SdkTools, SdkSetup, FxTools] + +    def checkpath(path, varlist): +        # Function that add valid paths in list in not already present +        if isdir(path) and path not in varlist: +            varlist.append(path) + +    for key in env.keys(): +        var = [] +        # Add valid paths +        for val in env[key]: +            if type(val) is str: +                # Path +                checkpath(val, var) +            else: +                # Paths list +                for subval in val: +                    checkpath(subval, var) + +        # Add values from actual environment +        try: +            for val in environ[key].split(';'): +                checkpath(val, var) +        except KeyError: +            pass + +        # Format paths to Environment Variable string +        if var: +            env[key] = ';'.join(var) +        else: +            raise DistutilsPlatformError("%s environment variable is empty" % +                                         key.upper()) +    return env  | 
