3 # Copyright The SCons Foundation
5 # Permission is hereby granted, free of charge, to any person obtaining
6 # a copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to
10 # permit persons to whom the Software is furnished to do so, subject to
11 # the following conditions:
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the Software.
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 """Tool-specific initialization for the Intel C/C++ compiler.
26 Supports Linux and Windows compilers, v7 and up.
28 There normally shouldn't be any need to import this module directly.
29 It will usually be imported through the generic SCons.Tool.Tool()
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
.startswith('linux')
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
65 def linux_ver_normalize(vstr
):
66 """Normalize a Linux compiler version number.
67 Intel changed from "80" to "9.0" in 2005, so we assume if the number
68 is greater than 60 it's an old-style number and otherwise new-style.
69 Always returns an old-style float like 80 or 90 for compatibility with Windows.
71 # Check for version number like 9.1.026: return 91.026
72 # XXX needs to be updated for 2011+ versions (like 2011.11.344 which is compiler v12.1.5)
73 m
= re
.match(r
'([0-9]+)\.([0-9]+)\.([0-9]+)', vstr
)
75 vmaj
,vmin
,build
= m
.groups()
76 return float(vmaj
) * 10. + float(vmin
) + float(build
) / 1000.
82 if f
< 60: return f
* 10.0
86 """Check for valid ABI (application binary interface) name,
87 and map into canonical one"""
91 # valid_abis maps input name to canonical name
93 valid_abis
= {'ia32' : 'ia32',
99 valid_abis
= {'ia32' : 'ia32',
105 valid_abis
= {'ia32' : 'ia32',
110 abi
= valid_abis
[abi
]
112 raise SCons
.Errors
.UserError("Intel compiler: Invalid ABI %s, valid values are %s"% \
113 (abi
, list(valid_abis
.keys())))
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."""
120 # Simple case, just find it in the list
121 if v
in vlist
: return v
124 # Fuzzy match: normalize version number first, but still return
125 # original non-normalized form.
128 if math
.fabs(linux_ver_normalize(vi
) - linux_ver_normalize(v
)) < fuzz
:
133 def get_intel_registry_value(valuename
, version
=None, abi
=None):
135 Return a value from the Intel compiler registry tree. (Windows only)
139 K
= 'Software\\Wow6432Node\\Intel\\Compilers\\C++\\' + version
+ '\\'+abi
.upper()
141 K
= 'Software\\Intel\\Compilers\\C++\\' + version
+ '\\'+abi
.upper()
143 k
= SCons
.Util
.RegOpenKeyEx(SCons
.Util
.HKEY_LOCAL_MACHINE
, K
)
144 except SCons
.Util
.RegError
:
145 # For version 13 and later, check UUID subkeys for valuename
147 K
= 'Software\\Wow6432Node\\Intel\\Suites\\' + version
+ "\\Defaults\\C++\\" + abi
.upper()
149 K
= 'Software\\Intel\\Suites\\' + version
+ "\\Defaults\\C++\\" + abi
.upper()
151 k
= SCons
.Util
.RegOpenKeyEx(SCons
.Util
.HKEY_LOCAL_MACHINE
, K
)
152 uuid
= SCons
.Util
.RegQueryValueEx(k
, 'SubKey')[0]
155 K
= 'Software\\Wow6432Node\\Intel\\Suites\\' + version
+ "\\" + uuid
+ "\\C++"
157 K
= 'Software\\Intel\\Suites\\' + version
+ "\\" + uuid
+ "\\C++"
158 k
= SCons
.Util
.RegOpenKeyEx(SCons
.Util
.HKEY_LOCAL_MACHINE
, K
)
161 v
= SCons
.Util
.RegQueryValueEx(k
, valuename
)[0]
162 return v
# or v.encode('iso-8859-1', 'replace') to remove unicode?
163 except SCons
.Util
.RegError
:
164 if abi
.upper() == 'EM64T':
167 K
= 'Software\\Wow6432Node\\Intel\\Suites\\' + version
+ "\\" + uuid
+ "\\C++\\" + abi
.upper()
169 K
= 'Software\\Intel\\Suites\\' + version
+ "\\" + uuid
+ "\\C++\\" + abi
.upper()
170 k
= SCons
.Util
.RegOpenKeyEx(SCons
.Util
.HKEY_LOCAL_MACHINE
, K
)
173 v
= SCons
.Util
.RegQueryValueEx(k
, valuename
)[0]
174 return v
# or v.encode('iso-8859-1', 'replace') to remove unicode?
175 except SCons
.Util
.RegError
:
176 raise MissingRegistryError("%s was not found in the registry, for Intel compiler version %s, abi='%s'"%(K
, version
,abi
))
178 except (SCons
.Util
.RegError
, OSError):
179 raise MissingRegistryError("%s was not found in the registry, for Intel compiler version %s, abi='%s'"%(K
, version
,abi
))
183 v
= SCons
.Util
.RegQueryValueEx(k
, valuename
)[0]
184 return v
# or v.encode('iso-8859-1', 'replace') to remove unicode?
185 except SCons
.Util
.RegError
:
186 raise MissingRegistryError("%s\\%s was not found in the registry."%(K
, valuename
))
189 def get_all_compiler_versions():
190 """Returns a sorted list of strings, like "70" or "80" or "9.0"
191 with most recent compiler version first.
196 keyname
= 'Software\\WoW6432Node\\Intel\\Compilers\\C++'
198 keyname
= 'Software\\Intel\\Compilers\\C++'
200 k
= SCons
.Util
.RegOpenKeyEx(SCons
.Util
.HKEY_LOCAL_MACHINE
,
203 # For version 13 or later, check for default instance UUID
205 keyname
= 'Software\\WoW6432Node\\Intel\\Suites'
207 keyname
= 'Software\\Intel\\Suites'
209 k
= SCons
.Util
.RegOpenKeyEx(SCons
.Util
.HKEY_LOCAL_MACHINE
,
217 subkey
= SCons
.Util
.RegEnumKey(k
, i
) # raises SConsEnvironmentError
218 # Check that this refers to an existing dir.
219 # This is not 100% perfect but should catch common
220 # installation issues like when the compiler was installed
221 # and then the install directory deleted or moved (rather
222 # than uninstalling properly), so the registry values
224 if subkey
== 'Defaults': # Ignore default instances
228 for try_abi
in ('IA32', 'IA32e', 'IA64', 'EM64T'):
230 d
= get_intel_registry_value('ProductDir', subkey
, try_abi
)
231 except MissingRegistryError
:
232 continue # not found in reg, keep going
233 if os
.path
.exists(d
): ok
= True
235 versions
.append(subkey
)
238 # Registry points to nonexistent dir. Ignore this
240 value
= get_intel_registry_value('ProductDir', subkey
, 'IA32')
241 except MissingRegistryError
as e
:
243 # Registry key is left dangling (potentially
244 # after uninstalling).
246 print("scons: *** Ignoring the registry key for the Intel compiler version %s.\n" \
247 "scons: *** It seems that the compiler was uninstalled and that the registry\n" \
248 "scons: *** was not cleaned up properly.\n" % subkey
)
250 print("scons: *** Ignoring "+str(value
))
253 except EnvironmentError:
256 elif is_linux
or is_mac
:
257 for d
in glob
.glob('/opt/intel_cc_*'):
258 # Typical dir here is /opt/intel_cc_80.
259 m
= re
.search(r
'cc_(.*)$', d
)
261 versions
.append(m
.group(1))
262 for d
in glob
.glob('/opt/intel/cc*/*'):
263 # Typical dir here is /opt/intel/cc/9.0 for IA32,
264 # /opt/intel/cce/9.0 for EMT64 (AMD64)
265 m
= re
.search(r
'([0-9][0-9.]*)$', d
)
267 versions
.append(m
.group(1))
268 for d
in glob
.glob('/opt/intel/Compiler/*'):
269 # Typical dir here is /opt/intel/Compiler/11.1
270 m
= re
.search(r
'([0-9][0-9.]*)$', d
)
272 versions
.append(m
.group(1))
273 for d
in glob
.glob('/opt/intel/composerxe-*'):
274 # Typical dir here is /opt/intel/composerxe-2011.4.184
275 m
= re
.search(r
'([0-9][0-9.]*)$', d
)
277 versions
.append(m
.group(1))
278 for d
in glob
.glob('/opt/intel/composer_xe_*'):
279 # Typical dir here is /opt/intel/composer_xe_2011_sp1.11.344
280 # The _sp1 is useless, the installers are named 2011.9.x, 2011.10.x, 2011.11.x
281 m
= re
.search(r
'([0-9]{0,4})(?:_sp\d*)?\.([0-9][0-9.]*)$', d
)
283 versions
.append("%s.%s"%(m
.group(1), m
.group(2)))
284 for d
in glob
.glob('/opt/intel/compilers_and_libraries_*'):
285 # JPA: For the new version of Intel compiler 2016.1.
286 m
= re
.search(r
'([0-9]{0,4})(?:_sp\d*)?\.([0-9][0-9.]*)$', d
)
288 versions
.append("%s.%s"%(m
.group(1), m
.group(2)))
291 """Given a dot-separated version string, return a tuple of ints representing it."""
292 return [int(x
) for x
in str.split('.')]
293 # split into ints, sort, then remove dups
294 return sorted(SCons
.Util
.unique(versions
), key
=keyfunc
, reverse
=True)
296 def get_intel_compiler_top(version
, abi
):
298 Return the main path to the top-level dir of the Intel compiler,
299 using the given version.
300 The compiler will be in <top>/bin/icl.exe (icc on linux),
301 the include dir is <top>/include, etc.
305 if not SCons
.Util
.can_read_reg
:
306 raise NoRegistryModuleError("No Windows registry module was found")
307 top
= get_intel_registry_value('ProductDir', version
, abi
)
308 archdir
={'x86_64': 'intel64',
314 }[abi
] # for v11 and greater
315 # pre-11, icl was in Bin. 11 and later, it's in Bin/<abi> apparently.
316 if not os
.path
.exists(os
.path
.join(top
, "Bin", "icl.exe")) \
317 and not os
.path
.exists(os
.path
.join(top
, "Bin", abi
, "icl.exe")) \
318 and not os
.path
.exists(os
.path
.join(top
, "Bin", archdir
, "icl.exe")):
319 raise MissingDirError("Can't find Intel compiler in %s" % top
)
320 elif is_mac
or is_linux
:
321 def find_in_2008style_dir(version
):
322 # first dir is new (>=9.0) style, second is old (8.0) style.
323 dirs
=('/opt/intel/cc/%s', '/opt/intel_cc_%s')
325 dirs
=('/opt/intel/cce/%s',) # 'e' stands for 'em64t', aka x86_64 aka amd64
328 if os
.path
.exists(os
.path
.join(d
%version
, "bin", "icc")):
332 def find_in_2010style_dir(version
):
333 dirs
=('/opt/intel/Compiler/%s/*'%version
)
334 # typically /opt/intel/Compiler/11.1/064 (then bin/intel64/icc)
336 # find highest sub-version number by reverse sorting and picking first existing one.
341 if (os
.path
.exists(os
.path
.join(d
, "bin", "ia32", "icc")) or
342 os
.path
.exists(os
.path
.join(d
, "bin", "intel64", "icc"))):
346 def find_in_2011style_dir(version
):
347 # The 2011 (compiler v12) dirs are inconsistent, so just redo the search from
348 # get_all_compiler_versions and look for a match (search the newest form first)
350 for d
in glob
.glob('/opt/intel/composer_xe_*'):
351 # Typical dir here is /opt/intel/composer_xe_2011_sp1.11.344
352 # The _sp1 is useless, the installers are named 2011.9.x, 2011.10.x, 2011.11.x
353 m
= re
.search(r
'([0-9]{0,4})(?:_sp\d*)?\.([0-9][0-9.]*)$', d
)
355 cur_ver
= "%s.%s"%(m
.group(1), m
.group(2))
356 if cur_ver
== version
and \
357 (os
.path
.exists(os
.path
.join(d
, "bin", "ia32", "icc")) or
358 os
.path
.exists(os
.path
.join(d
, "bin", "intel64", "icc"))):
362 for d
in glob
.glob('/opt/intel/composerxe-*'):
363 # Typical dir here is /opt/intel/composerxe-2011.4.184
364 m
= re
.search(r
'([0-9][0-9.]*)$', d
)
365 if m
and m
.group(1) == version
and \
366 (os
.path
.exists(os
.path
.join(d
, "bin", "ia32", "icc")) or
367 os
.path
.exists(os
.path
.join(d
, "bin", "intel64", "icc"))):
371 def find_in_2016style_dir(version
):
372 # The 2016 (compiler v16) dirs are inconsistent from previous.
374 for d
in glob
.glob('/opt/intel/compilers_and_libraries_%s/linux'%version
):
375 if os
.path
.exists(os
.path
.join(d
, "bin", "ia32", "icc")) or os
.path
.exists(os
.path
.join(d
, "bin", "intel64", "icc")):
380 top
= find_in_2016style_dir(version
) or find_in_2011style_dir(version
) or find_in_2010style_dir(version
) or find_in_2008style_dir(version
)
381 # print "INTELC: top=",top
383 raise MissingDirError("Can't find version %s Intel compiler in %s (abi='%s')"%(version
,top
, abi
))
387 def generate(env
, version
=None, abi
=None, topdir
=None, verbose
: int=0):
388 r
"""Add Builders and construction variables for Intel C/C++ compiler
392 version (str): compiler version to use, like "80"
393 abi (str): 'win32' or whatever Itanium version wants
394 topdir (str): directory containing compiler tree, e.g.
395 "c:\\Program Files\\Intel\\Compiler70".
396 If `topdir` is used, `version` and `abi` are ignored.
397 verbose: if >0, prints compiler version used.
400 if not (is_mac
or is_linux
or is_windows
):
401 # can't handle this platform
405 SCons
.Tool
.msvc
.generate(env
)
407 SCons
.Tool
.gcc
.generate(env
)
409 SCons
.Tool
.gcc
.generate(env
)
411 # if version is unspecified, use latest
412 vlist
= get_all_compiler_versions()
417 # User may have specified '90' but we need to get actual dirname '9.0'.
418 # get_version_from_list does that mapping.
419 v
= get_version_from_list(version
, vlist
)
421 raise SCons
.Errors
.UserError("Invalid Intel compiler version %s: "%version
+ \
422 "installed versions are %s"%(', '.join(vlist
)))
425 # if abi is unspecified, use ia32
426 # alternatives are ia64 for Itanium, or amd64 or em64t or x86_64 (all synonyms here)
429 if is_mac
or is_linux
:
430 # Check if we are on 64-bit linux, default to 64 then.
431 uname_m
= os
.uname()[4]
432 if uname_m
== 'x86_64':
442 if version
and not topdir
:
444 topdir
= get_intel_compiler_top(version
, abi
)
445 except (SCons
.Util
.RegError
, IntelCError
):
449 # Normally this is an error, but it might not be if the compiler is
450 # on $PATH and the user is importing their env.
451 class ICLTopDirWarning(SCons
.Warnings
.SConsWarning
):
455 ((is_mac
or is_linux
) and not env
.Detect('icc'))
456 or (is_windows
and not env
.Detect('icl'))
458 SCons
.Warnings
.enableWarningClass(ICLTopDirWarning
)
461 "Failed to find Intel compiler for version='%s', abi='%s'"
462 % (str(version
), str(abi
)),
465 # should be cleaned up to say what this other version is
466 # since in this case we have some other Intel compiler installed
467 SCons
.Warnings
.enableWarningClass(ICLTopDirWarning
)
470 "Can't find Intel compiler top dir for version='%s', abi='%s'"
471 % (str(version
), str(abi
)),
475 archdir
={'x86_64': 'intel64',
481 }[abi
] # for v11 and greater
482 if os
.path
.exists(os
.path
.join(topdir
, 'bin', archdir
)):
483 bindir
="bin/%s"%archdir
484 libdir
="lib/%s"%archdir
489 print("Intel C compiler: using version %s (%g), abi %s, in '%s/%s'"%\
490 (repr(version
), linux_ver_normalize(version
),abi
,topdir
,bindir
))
492 # Show the actual compiler version by running the compiler.
493 os
.system('%s/%s/icc --version'%(topdir
,bindir
))
495 # Show the actual compiler version by running the compiler.
496 os
.system('%s/%s/icc --version'%(topdir
,bindir
))
498 env
['INTEL_C_COMPILER_TOP'] = topdir
500 paths
={'INCLUDE' : 'include',
503 'LD_LIBRARY_PATH' : libdir
}
504 for p
, v
in paths
.items():
505 env
.PrependENVPath(p
, os
.path
.join(topdir
, v
))
507 paths
={'INCLUDE' : 'include',
510 'LD_LIBRARY_PATH' : libdir
}
511 for p
, v
in paths
.items():
512 env
.PrependENVPath(p
, os
.path
.join(topdir
, v
))
514 # env key reg valname default subdir of top
515 paths
=(('INCLUDE', 'IncludeDir', 'Include'),
516 ('LIB' , 'LibDir', 'Lib'),
517 ('PATH' , 'BinDir', 'Bin'))
518 # We are supposed to ignore version if topdir is set, so set
519 # it to the emptry string if it's not already set.
522 # Each path has a registry entry, use that or default to subdir
525 path
=get_intel_registry_value(p
[1], version
, abi
)
526 # These paths may have $(ICInstallDir)
527 # which needs to be substituted with the topdir.
528 path
=path
.replace('$(ICInstallDir)', topdir
+ os
.sep
)
530 # Couldn't get it from registry: use default subdir of topdir
531 env
.PrependENVPath(p
[0], os
.path
.join(topdir
, p
[2]))
533 env
.PrependENVPath(p
[0], path
.split(os
.pathsep
))
534 # print "ICL %s: %s, final=%s"%(p[0], path, str(env['ENV'][p[0]]))
539 env
['LINK'] = 'xilink'
543 # Don't reset LINK here;
544 # use smart_link which should already be here from link.py.
547 env
['LD'] = 'xild' # not used by default
549 # This is not the exact (detailed) compiler version,
550 # just the major version as determined above or specified
551 # by the user. It is a float like 80 or 90, in normalized form for Linux
552 # (i.e. even for Linux 9.0 compiler, still returns 90 rather than 9.0)
554 env
['INTEL_C_COMPILER_VERSION']=linux_ver_normalize(version
)
557 # Look for license file dir
558 # in system environment, registry, and default location.
559 envlicdir
= os
.environ
.get("INTEL_LICENSE_FILE", '')
560 K
= r
'SOFTWARE\Intel\Licenses'
562 k
= SCons
.Util
.RegOpenKeyEx(SCons
.Util
.HKEY_LOCAL_MACHINE
, K
)
563 reglicdir
= SCons
.Util
.RegQueryValueEx(k
, "w_cpp")[0]
564 except (AttributeError, SCons
.Util
.RegError
):
566 defaultlicdir
= r
'C:\Program Files\Common Files\Intel\Licenses'
569 for ld
in [envlicdir
, reglicdir
]:
570 # If the string contains an '@', then assume it's a network
571 # license (port@system) and good by definition.
572 if ld
and (ld
.find('@') != -1 or os
.path
.exists(ld
)):
576 licdir
= defaultlicdir
577 if not os
.path
.exists(licdir
):
578 class ICLLicenseDirWarning(SCons
.Warnings
.SConsWarning
):
580 SCons
.Warnings
.enableWarningClass(ICLLicenseDirWarning
)
582 ICLLicenseDirWarning
,
583 "Intel license dir was not found. "
584 "Tried using the INTEL_LICENSE_FILE environment variable "
585 "(%s), the registry (%s) and the default path (%s). "
586 "Using the default path as a last resort."
587 % (envlicdir
, reglicdir
, defaultlicdir
)
589 env
['ENV']['INTEL_LICENSE_FILE'] = licdir
592 if not (is_mac
or is_linux
or is_windows
):
593 # can't handle this platform
597 versions
= get_all_compiler_versions()
598 except (SCons
.Util
.RegError
, IntelCError
):
600 detected
= versions
is not None and len(versions
) > 0
602 # try env.Detect, maybe that will work
604 return env
.Detect('icl')
606 return env
.Detect('icc')
608 return env
.Detect('icc')
615 # indent-tabs-mode:nil
617 # vim: set expandtab tabstop=4 shiftwidth=4: