3 Tool-specific initialization for the Intel C/C++ compiler.
4 Supports Linux and Windows compilers, v7 and up.
6 There normally shouldn't be any need to import this module directly.
7 It will usually be imported through the generic SCons.Tool.Tool()
15 # Permission is hereby granted, free of charge, to any person obtaining
16 # a copy of this software and associated documentation files (the
17 # "Software"), to deal in the Software without restriction, including
18 # without limitation the rights to use, copy, modify, merge, publish,
19 # distribute, sublicense, and/or sell copies of the Software, and to
20 # permit persons to whom the Software is furnished to do so, subject to
21 # the following conditions:
23 # The above copyright notice and this permission notice shall be included
24 # in all copies or substantial portions of the Software.
26 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
27 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
28 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
37 import math, sys, os.path, glob, string, re
39 is_windows = sys.platform == 'win32'
40 is_win64 = is_windows and (os.environ['PROCESSOR_ARCHITECTURE'] == 'AMD64' or
41 ('PROCESSOR_ARCHITEW6432' in os.environ and
42 os.environ['PROCESSOR_ARCHITEW6432'] == 'AMD64'))
43 is_linux = sys.platform == 'linux2'
44 is_mac = sys.platform == 'darwin'
47 import SCons.Tool.msvc
55 # Exceptions for this tool
56 class IntelCError(SCons.Errors.InternalError):
58 class MissingRegistryError(IntelCError): # missing registry entry
60 class MissingDirError(IntelCError): # dir not found
62 class NoRegistryModuleError(IntelCError): # can't read registry at all
66 """Return a sequence containing only one copy of each unique element from input sequence s.
67 Does not preserve order.
68 Input sequence must be hashable (i.e. must be usable as a dictionary key)."""
74 def linux_ver_normalize(vstr):
75 """Normalize a Linux compiler version number.
76 Intel changed from "80" to "9.0" in 2005, so we assume if the number
77 is greater than 60 it's an old-style number and otherwise new-style.
78 Always returns an old-style float like 80 or 90 for compatibility with Windows.
80 # Check for version number like 9.1.026: return 91.026
81 m = re.match(r'([0-9]+)\.([0-9]+)\.([0-9]+)', vstr)
83 vmaj,vmin,build = m.groups()
84 return float(vmaj) * 10 + float(vmin) + float(build) / 1000.;
90 if f < 60: return f * 10.0
94 """Check for valid ABI (application binary interface) name,
95 and map into canonical one"""
99 # valid_abis maps input name to canonical name
101 valid_abis = {'ia32' : 'ia32',
107 valid_abis = {'ia32' : 'ia32',
113 valid_abis = {'ia32' : 'ia32',
118 abi = valid_abis[abi]
120 raise SCons.Errors.UserError, \
121 "Intel compiler: Invalid ABI %s, valid values are %s"% \
122 (abi, valid_abis.keys())
126 """Compare strings as floats,
127 but Intel changed Linux naming convention at 9.0"""
128 return cmp(linux_ver_normalize(b), linux_ver_normalize(a))
130 def get_version_from_list(v, vlist):
131 """See if we can match v (string) in vlist (list of strings)
132 Linux has to match in a fuzzy way."""
134 # Simple case, just find it in the list
135 if v in vlist: return v
138 # Fuzzy match: normalize version number first, but still return
139 # original non-normalized form.
142 if math.fabs(linux_ver_normalize(vi) - linux_ver_normalize(v)) < fuzz:
147 def get_intel_registry_value(valuename, version=None, abi=None):
149 Return a value from the Intel compiler registry tree. (Windows only)
153 K = 'Software\\Wow6432Node\\Intel\\Compilers\\C++\\' + version + '\\'+abi.upper()
155 K = 'Software\\Intel\\Compilers\\C++\\' + version + '\\'+abi.upper()
157 k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K)
158 except SCons.Util.RegError:
159 raise MissingRegistryError, \
160 "%s was not found in the registry, for Intel compiler version %s, abi='%s'"%(K, version,abi)
164 v = SCons.Util.RegQueryValueEx(k, valuename)[0]
165 return v # or v.encode('iso-8859-1', 'replace') to remove unicode?
166 except SCons.Util.RegError:
167 raise MissingRegistryError, \
168 "%s\\%s was not found in the registry."%(K, valuename)
171 def get_all_compiler_versions():
172 """Returns a sorted list of strings, like "70" or "80" or "9.0"
173 with most recent compiler version first.
178 keyname = 'Software\\WoW6432Node\\Intel\\Compilers\\C++'
180 keyname = 'Software\\Intel\\Compilers\\C++'
182 k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,
190 subkey = SCons.Util.RegEnumKey(k, i) # raises EnvironmentError
191 # Check that this refers to an existing dir.
192 # This is not 100% perfect but should catch common
193 # installation issues like when the compiler was installed
194 # and then the install directory deleted or moved (rather
195 # than uninstalling properly), so the registry values
198 for try_abi in ('IA32', 'IA32e', 'IA64', 'EM64T'):
200 d = get_intel_registry_value('ProductDir', subkey, try_abi)
201 except MissingRegistryError:
202 continue # not found in reg, keep going
203 if os.path.exists(d): ok = True
205 versions.append(subkey)
208 # Registry points to nonexistent dir. Ignore this
210 value = get_intel_registry_value('ProductDir', subkey, 'IA32')
211 except MissingRegistryError, e:
213 # Registry key is left dangling (potentially
214 # after uninstalling).
217 "scons: *** Ignoring the registry key for the Intel compiler version %s.\n" \
218 "scons: *** It seems that the compiler was uninstalled and that the registry\n" \
219 "scons: *** was not cleaned up properly.\n" % subkey
221 print "scons: *** Ignoring "+str(value)
224 except EnvironmentError:
228 for d in glob.glob('/opt/intel_cc_*'):
229 # Typical dir here is /opt/intel_cc_80.
230 m = re.search(r'cc_(.*)$', d)
232 versions.append(m.group(1))
233 for d in glob.glob('/opt/intel/cc*/*'):
234 # Typical dir here is /opt/intel/cc/9.0 for IA32,
235 # /opt/intel/cce/9.0 for EMT64 (AMD64)
236 m = re.search(r'([0-9.]+)$', d)
238 versions.append(m.group(1))
240 for d in glob.glob('/opt/intel/cc*/*'):
241 # Typical dir here is /opt/intel/cc/9.0 for IA32,
242 # /opt/intel/cce/9.0 for EMT64 (AMD64)
243 m = re.search(r'([0-9.]+)$', d)
245 versions.append(m.group(1))
246 versions = uniquify(versions) # remove dups
247 versions.sort(vercmp)
250 def get_intel_compiler_top(version, abi):
252 Return the main path to the top-level dir of the Intel compiler,
253 using the given version.
254 The compiler will be in <top>/bin/icl.exe (icc on linux),
255 the include dir is <top>/include, etc.
259 if not SCons.Util.can_read_reg:
260 raise NoRegistryModuleError, "No Windows registry module was found"
261 top = get_intel_registry_value('ProductDir', version, abi)
262 # pre-11, icl was in Bin. 11 and later, it's in Bin/<abi> apparently.
263 if not os.path.exists(os.path.join(top, "Bin", "icl.exe")) \
264 and not os.path.exists(os.path.join(top, "Bin", abi, "icl.exe")):
265 raise MissingDirError, \
266 "Can't find Intel compiler in %s"%(top)
267 elif is_mac or is_linux:
268 # first dir is new (>=9.0) style, second is old (8.0) style.
269 dirs=('/opt/intel/cc/%s', '/opt/intel_cc_%s')
271 dirs=('/opt/intel/cce/%s',) # 'e' stands for 'em64t', aka x86_64 aka amd64
274 if os.path.exists(os.path.join(d%version, "bin", "icc")):
278 raise MissingDirError, \
279 "Can't find version %s Intel compiler in %s (abi='%s')"%(version,top, abi)
283 def generate(env, version=None, abi=None, topdir=None, verbose=0):
284 """Add Builders and construction variables for Intel C/C++ compiler
287 version: (string) compiler version to use, like "80"
288 abi: (string) 'win32' or whatever Itanium version wants
289 topdir: (string) compiler top dir, like
290 "c:\Program Files\Intel\Compiler70"
291 If topdir is used, version and abi are ignored.
292 verbose: (int) if >0, prints compiler version used.
294 if not (is_mac or is_linux or is_windows):
295 # can't handle this platform
299 SCons.Tool.msvc.generate(env)
301 SCons.Tool.gcc.generate(env)
303 SCons.Tool.gcc.generate(env)
305 # if version is unspecified, use latest
306 vlist = get_all_compiler_versions()
311 # User may have specified '90' but we need to get actual dirname '9.0'.
312 # get_version_from_list does that mapping.
313 v = get_version_from_list(version, vlist)
315 raise SCons.Errors.UserError, \
316 "Invalid Intel compiler version %s: "%version + \
317 "installed versions are %s"%(', '.join(vlist))
320 # if abi is unspecified, use ia32
321 # alternatives are ia64 for Itanium, or amd64 or em64t or x86_64 (all synonyms here)
324 if is_mac or is_linux:
325 # Check if we are on 64-bit linux, default to 64 then.
326 uname_m = os.uname()[4]
327 if uname_m == 'x86_64':
337 if version and not topdir:
339 topdir = get_intel_compiler_top(version, abi)
340 except (SCons.Util.RegError, IntelCError):
344 # Normally this is an error, but it might not be if the compiler is
345 # on $PATH and the user is importing their env.
346 class ICLTopDirWarning(SCons.Warnings.Warning):
348 if (is_mac or is_linux) and not env.Detect('icc') or \
349 is_windows and not env.Detect('icl'):
351 SCons.Warnings.enableWarningClass(ICLTopDirWarning)
352 SCons.Warnings.warn(ICLTopDirWarning,
353 "Failed to find Intel compiler for version='%s', abi='%s'"%
354 (str(version), str(abi)))
356 # should be cleaned up to say what this other version is
357 # since in this case we have some other Intel compiler installed
358 SCons.Warnings.enableWarningClass(ICLTopDirWarning)
359 SCons.Warnings.warn(ICLTopDirWarning,
360 "Can't find Intel compiler top dir for version='%s', abi='%s'"%
361 (str(version), str(abi)))
365 print "Intel C compiler: using version %s (%g), abi %s, in '%s'"%\
366 (repr(version), linux_ver_normalize(version),abi,topdir)
368 # Show the actual compiler version by running the compiler.
369 os.system('%s/bin/icc --version'%topdir)
371 # Show the actual compiler version by running the compiler.
372 os.system('%s/bin/icc --version'%topdir)
374 env['INTEL_C_COMPILER_TOP'] = topdir
376 paths={'INCLUDE' : 'include',
379 'LD_LIBRARY_PATH' : 'lib'}
380 for p in paths.keys():
381 env.PrependENVPath(p, os.path.join(topdir, paths[p]))
383 paths={'INCLUDE' : 'include',
386 'LD_LIBRARY_PATH' : 'lib'}
387 for p in paths.keys():
388 env.PrependENVPath(p, os.path.join(topdir, paths[p]))
390 # env key reg valname default subdir of top
391 paths=(('INCLUDE', 'IncludeDir', 'Include'),
392 ('LIB' , 'LibDir', 'Lib'),
393 ('PATH' , 'BinDir', 'Bin'))
394 # We are supposed to ignore version if topdir is set, so set
395 # it to the emptry string if it's not already set.
398 # Each path has a registry entry, use that or default to subdir
401 path=get_intel_registry_value(p[1], version, abi)
402 # These paths may have $(ICInstallDir)
403 # which needs to be substituted with the topdir.
404 path=path.replace('$(ICInstallDir)', topdir + os.sep)
406 # Couldn't get it from registry: use default subdir of topdir
407 env.PrependENVPath(p[0], os.path.join(topdir, p[2]))
409 env.PrependENVPath(p[0], path.split(os.pathsep))
410 # print "ICL %s: %s, final=%s"%(p[0], path, str(env['ENV'][p[0]]))
415 env['LINK'] = 'xilink'
419 # Don't reset LINK here;
420 # use smart_link which should already be here from link.py.
423 env['LD'] = 'xild' # not used by default
425 # This is not the exact (detailed) compiler version,
426 # just the major version as determined above or specified
427 # by the user. It is a float like 80 or 90, in normalized form for Linux
428 # (i.e. even for Linux 9.0 compiler, still returns 90 rather than 9.0)
430 env['INTEL_C_COMPILER_VERSION']=linux_ver_normalize(version)
433 # Look for license file dir
434 # in system environment, registry, and default location.
435 envlicdir = os.environ.get("INTEL_LICENSE_FILE", '')
436 K = ('SOFTWARE\Intel\Licenses')
438 k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K)
439 reglicdir = SCons.Util.RegQueryValueEx(k, "w_cpp")[0]
440 except (AttributeError, SCons.Util.RegError):
442 defaultlicdir = r'C:\Program Files\Common Files\Intel\Licenses'
445 for ld in [envlicdir, reglicdir]:
446 # If the string contains an '@', then assume it's a network
447 # license (port@system) and good by definition.
448 if ld and (ld.find('@') != -1 or os.path.exists(ld)):
452 licdir = defaultlicdir
453 if not os.path.exists(licdir):
454 class ICLLicenseDirWarning(SCons.Warnings.Warning):
456 SCons.Warnings.enableWarningClass(ICLLicenseDirWarning)
457 SCons.Warnings.warn(ICLLicenseDirWarning,
458 "Intel license dir was not found."
459 " Tried using the INTEL_LICENSE_FILE environment variable (%s), the registry (%s) and the default path (%s)."
460 " Using the default path as a last resort."
461 % (envlicdir, reglicdir, defaultlicdir))
462 env['ENV']['INTEL_LICENSE_FILE'] = licdir
465 if not (is_mac or is_linux or is_windows):
466 # can't handle this platform
470 versions = get_all_compiler_versions()
471 except (SCons.Util.RegError, IntelCError):
473 detected = versions is not None and len(versions) > 0
475 # try env.Detect, maybe that will work
477 return env.Detect('icl')
479 return env.Detect('icc')
481 return env.Detect('icc')
488 # indent-tabs-mode:nil
490 # vim: set expandtab tabstop=4 shiftwidth=4: