intelc.py.svn-base
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:19k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. """SCons.Tool.icl
  2. Tool-specific initialization for the Intel C/C++ compiler.
  3. Supports Linux and Windows compilers, v7 and up.
  4. There normally shouldn't be any need to import this module directly.
  5. It will usually be imported through the generic SCons.Tool.Tool()
  6. selection method.
  7. """
  8. #
  9. # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
  10. #
  11. # Permission is hereby granted, free of charge, to any person obtaining
  12. # a copy of this software and associated documentation files (the
  13. # "Software"), to deal in the Software without restriction, including
  14. # without limitation the rights to use, copy, modify, merge, publish,
  15. # distribute, sublicense, and/or sell copies of the Software, and to
  16. # permit persons to whom the Software is furnished to do so, subject to
  17. # the following conditions:
  18. #
  19. # The above copyright notice and this permission notice shall be included
  20. # in all copies or substantial portions of the Software.
  21. #
  22. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
  23. # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  24. # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  25. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  26. # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  27. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  28. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  29. #
  30. __revision__ = "src/engine/SCons/Tool/intelc.py 3057 2008/06/09 22:21:00 knight"
  31. import math, sys, os.path, glob, string, re
  32. is_windows = sys.platform == 'win32'
  33. is_win64 = is_windows and (os.environ['PROCESSOR_ARCHITECTURE'] == 'AMD64' or 
  34.                            (os.environ.has_key('PROCESSOR_ARCHITEW6432') and
  35.                             os.environ['PROCESSOR_ARCHITEW6432'] == 'AMD64'))
  36. is_linux = sys.platform == 'linux2'
  37. is_mac     = sys.platform == 'darwin'
  38. if is_windows:
  39.     import SCons.Tool.msvc
  40. elif is_linux:
  41.     import SCons.Tool.gcc
  42. elif is_mac:
  43.     import SCons.Tool.gcc
  44. import SCons.Util
  45. import SCons.Warnings
  46. # Exceptions for this tool
  47. class IntelCError(SCons.Errors.InternalError):
  48.     pass
  49. class MissingRegistryError(IntelCError): # missing registry entry
  50.     pass
  51. class MissingDirError(IntelCError):     # dir not found
  52.     pass
  53. class NoRegistryModuleError(IntelCError): # can't read registry at all
  54.     pass
  55. def uniquify(s):
  56.     """Return a sequence containing only one copy of each unique element from input sequence s.
  57.     Does not preserve order.
  58.     Input sequence must be hashable (i.e. must be usable as a dictionary key)."""
  59.     u = {}
  60.     for x in s:
  61.         u[x] = 1
  62.     return u.keys()
  63. def linux_ver_normalize(vstr):
  64.     """Normalize a Linux compiler version number.
  65.     Intel changed from "80" to "9.0" in 2005, so we assume if the number
  66.     is greater than 60 it's an old-style number and otherwise new-style.
  67.     Always returns an old-style float like 80 or 90 for compatibility with Windows.
  68.     Shades of Y2K!"""
  69.     # Check for version number like 9.1.026: return 91.026
  70.     m = re.match(r'([0-9]+).([0-9]+).([0-9]+)', vstr)
  71.     if m:
  72.         vmaj,vmin,build = m.groups()
  73.         return float(vmaj) * 10 + float(vmin) + float(build) / 1000.;
  74.     else:
  75.         f = float(vstr)
  76.         if is_windows:
  77.             return f
  78.         else:
  79.             if f < 60: return f * 10.0
  80.             else: return f
  81. def check_abi(abi):
  82.     """Check for valid ABI (application binary interface) name,
  83.     and map into canonical one"""
  84.     if not abi:
  85.         return None
  86.     abi = abi.lower()
  87.     # valid_abis maps input name to canonical name
  88.     if is_windows:
  89.         valid_abis = {'ia32'  : 'ia32',
  90.                       'x86'   : 'ia32',
  91.                       'ia64'  : 'ia64',
  92.                       'em64t' : 'em64t',
  93.                       'amd64' : 'em64t'}
  94.     if is_linux:
  95.         valid_abis = {'ia32'   : 'ia32',
  96.                       'x86'    : 'ia32',
  97.                       'x86_64' : 'x86_64',
  98.                       'em64t'  : 'x86_64',
  99.                       'amd64'  : 'x86_64'}
  100.     if is_mac:
  101.         valid_abis = {'ia32'   : 'ia32',
  102.                       'x86'    : 'ia32',
  103.                       'x86_64' : 'x86_64',
  104.                       'em64t'  : 'x86_64'}
  105.     try:
  106.         abi = valid_abis[abi]
  107.     except KeyError:
  108.         raise SCons.Errors.UserError, 
  109.               "Intel compiler: Invalid ABI %s, valid values are %s"% 
  110.               (abi, valid_abis.keys())
  111.     return abi
  112. def vercmp(a, b):
  113.     """Compare strings as floats,
  114.     but Intel changed Linux naming convention at 9.0"""
  115.     return cmp(linux_ver_normalize(b), linux_ver_normalize(a))
  116. def get_version_from_list(v, vlist):
  117.     """See if we can match v (string) in vlist (list of strings)
  118.     Linux has to match in a fuzzy way."""
  119.     if is_windows:
  120.         # Simple case, just find it in the list
  121.         if v in vlist: return v
  122.         else: return None
  123.     else:
  124.         # Fuzzy match: normalize version number first, but still return
  125.         # original non-normalized form.
  126.         fuzz = 0.001
  127.         for vi in vlist:
  128.             if math.fabs(linux_ver_normalize(vi) - linux_ver_normalize(v)) < fuzz:
  129.                 return vi
  130.         # Not found
  131.         return None
  132. def get_intel_registry_value(valuename, version=None, abi=None):
  133.     """
  134.     Return a value from the Intel compiler registry tree. (Windows only)
  135.     """
  136.     # Open the key:
  137.     if is_win64:
  138.         K = 'Software\Wow6432Node\Intel\Compilers\C++\' + version + '\'+abi.upper()
  139.     else:
  140.         K = 'Software\Intel\Compilers\C++\' + version + '\'+abi.upper()
  141.     try:
  142.         k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K)
  143.     except SCons.Util.RegError:
  144.         raise MissingRegistryError, 
  145.               "%s was not found in the registry, for Intel compiler version %s, abi='%s'"%(K, version,abi)
  146.     # Get the value:
  147.     try:
  148.         v = SCons.Util.RegQueryValueEx(k, valuename)[0]
  149.         return v  # or v.encode('iso-8859-1', 'replace') to remove unicode?
  150.     except SCons.Util.RegError:
  151.         raise MissingRegistryError, 
  152.               "%s\%s was not found in the registry."%(K, valuename)
  153. def get_all_compiler_versions():
  154.     """Returns a sorted list of strings, like "70" or "80" or "9.0"
  155.     with most recent compiler version first.
  156.     """
  157.     versions=[]
  158.     if is_windows:
  159.         if is_win64:
  160.             keyname = 'Software\WoW6432Node\Intel\Compilers\C++'
  161.         else:
  162.             keyname = 'Software\Intel\Compilers\C++'
  163.         try:
  164.             k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,
  165.                                         keyname)
  166.         except WindowsError:
  167.             return []
  168.         i = 0
  169.         versions = []
  170.         try:
  171.             while i < 100:
  172.                 subkey = SCons.Util.RegEnumKey(k, i) # raises EnvironmentError
  173.                 # Check that this refers to an existing dir.
  174.                 # This is not 100% perfect but should catch common
  175.                 # installation issues like when the compiler was installed
  176.                 # and then the install directory deleted or moved (rather
  177.                 # than uninstalling properly), so the registry values
  178.                 # are still there.
  179.                 ok = False
  180.                 for try_abi in ('IA32', 'IA32e',  'IA64', 'EM64T'):
  181.                     try:
  182.                         d = get_intel_registry_value('ProductDir', subkey, try_abi)
  183.                     except MissingRegistryError:
  184.                         continue  # not found in reg, keep going
  185.                     if os.path.exists(d): ok = True
  186.                 if ok:
  187.                     versions.append(subkey)
  188.                 else:
  189.                     try:
  190.                         # Registry points to nonexistent dir.  Ignore this
  191.                         # version.
  192.                         value = get_intel_registry_value('ProductDir', subkey, 'IA32')
  193.                     except MissingRegistryError, e:
  194.                         # Registry key is left dangling (potentially
  195.                         # after uninstalling).
  196.                         print 
  197.                             "scons: *** Ignoring the registry key for the Intel compiler version %s.n" 
  198.                             "scons: *** It seems that the compiler was uninstalled and that the registryn" 
  199.                             "scons: *** was not cleaned up properly.n" % subkey
  200.                     else:
  201.                         print "scons: *** Ignoring "+str(value)
  202.                 i = i + 1
  203.         except EnvironmentError:
  204.             # no more subkeys
  205.             pass
  206.     elif is_linux:
  207.         for d in glob.glob('/opt/intel_cc_*'):
  208.             # Typical dir here is /opt/intel_cc_80.
  209.             m = re.search(r'cc_(.*)$', d)
  210.             if m:
  211.                 versions.append(m.group(1))
  212.         for d in glob.glob('/opt/intel/cc*/*'):
  213.             # Typical dir here is /opt/intel/cc/9.0 for IA32,
  214.             # /opt/intel/cce/9.0 for EMT64 (AMD64)
  215.             m = re.search(r'([0-9.]+)$', d)
  216.             if m:
  217.                 versions.append(m.group(1))
  218.     elif is_mac:
  219.         for d in glob.glob('/opt/intel/cc*/*'):
  220.             # Typical dir here is /opt/intel/cc/9.0 for IA32,
  221.             # /opt/intel/cce/9.0 for EMT64 (AMD64)
  222.             m = re.search(r'([0-9.]+)$', d)
  223.             if m:
  224.                 versions.append(m.group(1))
  225.     versions = uniquify(versions)       # remove dups
  226.     versions.sort(vercmp)
  227.     return versions
  228. def get_intel_compiler_top(version, abi):
  229.     """
  230.     Return the main path to the top-level dir of the Intel compiler,
  231.     using the given version.
  232.     The compiler will be in <top>/bin/icl.exe (icc on linux),
  233.     the include dir is <top>/include, etc.
  234.     """
  235.     if is_windows:
  236.         if not SCons.Util.can_read_reg:
  237.             raise NoRegistryModuleError, "No Windows registry module was found"
  238.         top = get_intel_registry_value('ProductDir', version, abi)
  239.         if not os.path.exists(os.path.join(top, "Bin", "icl.exe")):
  240.             raise MissingDirError, 
  241.                   "Can't find Intel compiler in %s"%(top)
  242.     elif is_mac or is_linux:
  243.         # first dir is new (>=9.0) style, second is old (8.0) style.
  244.         dirs=('/opt/intel/cc/%s', '/opt/intel_cc_%s')
  245.         if abi == 'x86_64':
  246.             dirs=('/opt/intel/cce/%s',)  # 'e' stands for 'em64t', aka x86_64 aka amd64
  247.         top=None
  248.         for d in dirs:
  249.             if os.path.exists(os.path.join(d%version, "bin", "icc")):
  250.                 top = d%version
  251.                 break
  252.         if not top:
  253.             raise MissingDirError, 
  254.                   "Can't find version %s Intel compiler in %s (abi='%s')"%(version,top, abi)
  255.     return top
  256. def generate(env, version=None, abi=None, topdir=None, verbose=0):
  257.     """Add Builders and construction variables for Intel C/C++ compiler
  258.     to an Environment.
  259.     args:
  260.       version: (string) compiler version to use, like "80"
  261.       abi:     (string) 'win32' or whatever Itanium version wants
  262.       topdir:  (string) compiler top dir, like
  263.                          "c:Program FilesIntelCompiler70"
  264.                         If topdir is used, version and abi are ignored.
  265.       verbose: (int)    if >0, prints compiler version used.
  266.     """
  267.     if not (is_mac or is_linux or is_windows):
  268.         # can't handle this platform
  269.         return
  270.     if is_windows:
  271.         SCons.Tool.msvc.generate(env)
  272.     elif is_linux:
  273.         SCons.Tool.gcc.generate(env)
  274.     elif is_mac:
  275.         SCons.Tool.gcc.generate(env)
  276.     # if version is unspecified, use latest
  277.     vlist = get_all_compiler_versions()
  278.     if not version:
  279.         if vlist:
  280.             version = vlist[0]
  281.     else:
  282.         # User may have specified '90' but we need to get actual dirname '9.0'.
  283.         # get_version_from_list does that mapping.
  284.         v = get_version_from_list(version, vlist)
  285.         if not v:
  286.             raise SCons.Errors.UserError, 
  287.                   "Invalid Intel compiler version %s: "%version + 
  288.                   "installed versions are %s"%(', '.join(vlist))
  289.         version = v
  290.     # if abi is unspecified, use ia32
  291.     # alternatives are ia64 for Itanium, or amd64 or em64t or x86_64 (all synonyms here)
  292.     abi = check_abi(abi)
  293.     if abi is None:
  294.         if is_mac or is_linux:
  295.             # Check if we are on 64-bit linux, default to 64 then.
  296.             uname_m = os.uname()[4]
  297.             if uname_m == 'x86_64':
  298.                 abi = 'x86_64'
  299.             else:
  300.                 abi = 'ia32'
  301.         else:
  302.             if is_win64:
  303.                 abi = 'em64t'
  304.             else:
  305.                 abi = 'ia32'
  306.     if version and not topdir:
  307.         try:
  308.             topdir = get_intel_compiler_top(version, abi)
  309.         except (SCons.Util.RegError, IntelCError):
  310.             topdir = None
  311.     if not topdir:
  312.         # Normally this is an error, but it might not be if the compiler is
  313.         # on $PATH and the user is importing their env.
  314.         class ICLTopDirWarning(SCons.Warnings.Warning):
  315.             pass
  316.         if (is_mac or is_linux) and not env.Detect('icc') or 
  317.            is_windows and not env.Detect('icl'):
  318.             SCons.Warnings.enableWarningClass(ICLTopDirWarning)
  319.             SCons.Warnings.warn(ICLTopDirWarning,
  320.                                 "Failed to find Intel compiler for version='%s', abi='%s'"%
  321.                                 (str(version), str(abi)))
  322.         else:
  323.             # should be cleaned up to say what this other version is
  324.             # since in this case we have some other Intel compiler installed
  325.             SCons.Warnings.enableWarningClass(ICLTopDirWarning)
  326.             SCons.Warnings.warn(ICLTopDirWarning,
  327.                                 "Can't find Intel compiler top dir for version='%s', abi='%s'"%
  328.                                     (str(version), str(abi)))
  329.     if topdir:
  330.         if verbose:
  331.             print "Intel C compiler: using version %s (%g), abi %s, in '%s'"%
  332.                   (repr(version), linux_ver_normalize(version),abi,topdir)
  333.             if is_linux:
  334.                 # Show the actual compiler version by running the compiler.
  335.                 os.system('%s/bin/icc --version'%topdir)
  336.             if is_mac:
  337.                 # Show the actual compiler version by running the compiler.
  338.                 os.system('%s/bin/icc --version'%topdir)
  339.         env['INTEL_C_COMPILER_TOP'] = topdir
  340.         if is_linux:
  341.             paths={'INCLUDE'         : 'include',
  342.                    'LIB'             : 'lib',
  343.                    'PATH'            : 'bin',
  344.                    'LD_LIBRARY_PATH' : 'lib'}
  345.             for p in paths.keys():
  346.                 env.PrependENVPath(p, os.path.join(topdir, paths[p]))
  347.         if is_mac:
  348.             paths={'INCLUDE'         : 'include',
  349.                    'LIB'             : 'lib',
  350.                    'PATH'            : 'bin',
  351.                    'LD_LIBRARY_PATH' : 'lib'}
  352.             for p in paths.keys():
  353.                 env.PrependENVPath(p, os.path.join(topdir, paths[p]))
  354.         if is_windows:
  355.             #       env key    reg valname   default subdir of top
  356.             paths=(('INCLUDE', 'IncludeDir', 'Include'),
  357.                    ('LIB'    , 'LibDir',     'Lib'),
  358.                    ('PATH'   , 'BinDir',     'Bin'))
  359.             # We are supposed to ignore version if topdir is set, so set
  360.             # it to the emptry string if it's not already set.
  361.             if version is None:
  362.                 version = ''
  363.             # Each path has a registry entry, use that or default to subdir
  364.             for p in paths:
  365.                 try:
  366.                     path=get_intel_registry_value(p[1], version, abi)
  367.                     # These paths may have $(ICInstallDir)
  368.                     # which needs to be substituted with the topdir.
  369.                     path=path.replace('$(ICInstallDir)', topdir + os.sep)
  370.                 except IntelCError:
  371.                     # Couldn't get it from registry: use default subdir of topdir
  372.                     env.PrependENVPath(p[0], os.path.join(topdir, p[2]))
  373.                 else:
  374.                     env.PrependENVPath(p[0], string.split(path, os.pathsep))
  375.                     # print "ICL %s: %s, final=%s"%(p[0], path, str(env['ENV'][p[0]]))
  376.     if is_windows:
  377.         env['CC']        = 'icl'
  378.         env['CXX']       = 'icl'
  379.         env['LINK']      = 'xilink'
  380.     else:
  381.         env['CC']        = 'icc'
  382.         env['CXX']       = 'icpc'
  383.         # Don't reset LINK here;
  384.         # use smart_link which should already be here from link.py.
  385.         #env['LINK']      = '$CC'
  386.         env['AR']        = 'xiar'
  387.         env['LD']        = 'xild' # not used by default
  388.     # This is not the exact (detailed) compiler version,
  389.     # just the major version as determined above or specified
  390.     # by the user.  It is a float like 80 or 90, in normalized form for Linux
  391.     # (i.e. even for Linux 9.0 compiler, still returns 90 rather than 9.0)
  392.     if version:
  393.         env['INTEL_C_COMPILER_VERSION']=linux_ver_normalize(version)
  394.     if is_windows:
  395.         # Look for license file dir
  396.         # in system environment, registry, and default location.
  397.         envlicdir = os.environ.get("INTEL_LICENSE_FILE", '')
  398.         K = ('SOFTWAREIntelLicenses')
  399.         try:
  400.             k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K)
  401.             reglicdir = SCons.Util.RegQueryValueEx(k, "w_cpp")[0]
  402.         except (AttributeError, SCons.Util.RegError):
  403.             reglicdir = ""
  404.         defaultlicdir = r'C:Program FilesCommon FilesIntelLicenses'
  405.         licdir = None
  406.         for ld in [envlicdir, reglicdir]:
  407.             # If the string contains an '@', then assume it's a network
  408.             # license (port@system) and good by definition.
  409.             if ld and (string.find(ld, '@') != -1 or os.path.exists(ld)):
  410.                 licdir = ld
  411.                 break
  412.         if not licdir:
  413.             licdir = defaultlicdir
  414.             if not os.path.exists(licdir):
  415.                 class ICLLicenseDirWarning(SCons.Warnings.Warning):
  416.                     pass
  417.                 SCons.Warnings.enableWarningClass(ICLLicenseDirWarning)
  418.                 SCons.Warnings.warn(ICLLicenseDirWarning,
  419.                                     "Intel license dir was not found."
  420.                                     "  Tried using the INTEL_LICENSE_FILE environment variable (%s), the registry (%s) and the default path (%s)."
  421.                                     "  Using the default path as a last resort."
  422.                                         % (envlicdir, reglicdir, defaultlicdir))
  423.         env['ENV']['INTEL_LICENSE_FILE'] = licdir
  424. def exists(env):
  425.     if not (is_mac or is_linux or is_windows):
  426.         # can't handle this platform
  427.         return 0
  428.     try:
  429.         versions = get_all_compiler_versions()
  430.     except (SCons.Util.RegError, IntelCError):
  431.         versions = None
  432.     detected = versions is not None and len(versions) > 0
  433.     if not detected:
  434.         # try env.Detect, maybe that will work
  435.         if is_windows:
  436.             return env.Detect('icl')
  437.         elif is_linux:
  438.             return env.Detect('icc')
  439.         elif is_mac:
  440.             return env.Detect('icc')
  441.     return detected
  442. # end of file