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_win32 = sys.platform == 'win32'
40 is_linux = sys.platform == 'linux2'
43 import SCons.Tool.msvc
49 # Exceptions for this tool
50 class IntelCError(SCons.Errors.InternalError):
52 class MissingRegistryError(IntelCError): # missing registry entry
54 class MissingDirError(IntelCError): # dir not found
56 class NoRegistryModuleError(IntelCError): # can't read registry at all
59 def linux_ver_normalize(vstr):
60 """Normalize a Linux compiler version number.
61 Intel changed from "80" to "9.0" in 2005, so we assume if the number
62 is greater than 60 it's an old-style number and otherwise new-style.
63 Always returns an old-style float like 80 or 90 for compatibility with Windows.
69 if f < 60: return f * 10.0
73 """Compare strings as floats,
74 but Intel changed Linux naming convention at 9.0"""
75 return cmp(linux_ver_normalize(b), linux_ver_normalize(a))
77 def get_version_from_list(v, vlist):
78 """See if we can match v (string) in vlist (list of strings)
79 Linux has to match in a fuzzy way."""
81 # Simple case, just find it in the list
82 if v in vlist: return v
85 # Fuzzy match: normalize version number first, but still return
86 # original non-normalized form.
89 if math.fabs(linux_ver_normalize(vi) - linux_ver_normalize(v)) < fuzz:
94 def get_intel_registry_value(valuename, version=None, abi=None):
96 Return a value from the Intel compiler registry tree. (Win32 only)
100 K = 'Software\\Intel\\Compilers\\C++\\' + version + '\\'+abi.upper()
102 k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K)
103 except SCons.Util.RegError:
104 raise MissingRegistryError, \
105 "%s was not found in the registry, for Intel compiler version %s"%(K, version)
109 v = SCons.Util.RegQueryValueEx(k, valuename)[0]
110 return v # or v.encode('iso-8859-1', 'replace') to remove unicode?
111 except SCons.Util.RegError:
112 raise MissingRegistryError, \
113 "%s\\%s was not found in the registry."%(K, value)
116 def get_all_compiler_versions():
117 """Returns a sorted list of strings, like "70" or "80" or "9.0"
118 with most recent compiler version first.
122 keyname = 'Software\\Intel\\Compilers\\C++'
124 k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,
132 subkey = SCons.Util.RegEnumKey(k, i) # raises EnvironmentError
133 # Check that this refers to an existing dir.
134 # This is not 100% perfect but should catch common
135 # installation issues like when the compiler was installed
136 # and then the install directory deleted or moved (rather
137 # than uninstalling properly), so the registry values
140 for check_abi in ('IA32', 'IA64'):
142 d = get_intel_registry_value('ProductDir', subkey, check_abi)
143 except MissingRegistryError:
144 continue # not found in reg, keep going
145 if os.path.exists(d): ok = True
147 versions.append(subkey)
149 # Registry points to nonexistent dir. Ignore this version.
150 print "Ignoring "+str(get_intel_registry_value('ProductDir', subkey, 'IA32'))
152 except EnvironmentError:
156 for d in glob.glob('/opt/intel_cc_*'):
157 # Typical dir here is /opt/intel_cc_80.
158 versions.append(re.search(r'cc_(.*)$', d).group(1))
159 for d in glob.glob('/opt/intel/cc/*'):
160 # Typical dir here is /opt/intel/cc/9.0.
161 versions.append(re.search(r'([0-9.]+)$', d).group(1))
162 versions.sort(vercmp)
165 def get_intel_compiler_top(version, abi):
167 Return the main path to the top-level dir of the Intel compiler,
168 using the given version.
169 The compiler will be in <top>/bin/icl.exe (icc on linux),
170 the include dir is <top>/include, etc.
174 if not SCons.Util.can_read_reg:
175 raise NoRegistryModuleError, "No Windows registry module was found"
176 top = get_intel_registry_value('ProductDir', version, abi)
178 if not os.path.exists(os.path.join(top, "Bin", "icl.exe")):
179 raise MissingDirError, \
180 "Can't find Intel compiler in %s"%(top)
182 # first dir is new (>=9.0) style, second is old (8.0) style.
183 dirs=('/opt/intel/cc/%s', '/opt/intel_cc_%s')
187 if os.path.exists(os.path.join(top, "bin", "icc")): break
189 raise MissingDirError, \
190 "Can't find version %s Intel compiler in %s"%(version,top)
194 def generate(env, version=None, abi=None, topdir=None, verbose=0):
195 """Add Builders and construction variables for Intel C/C++ compiler
198 version: (string) compiler version to use, like "80"
199 abi: (string) 'win32' or whatever Itanium version wants
200 topdir: (string) compiler top dir, like
201 "c:\Program Files\Intel\Compiler70"
202 If topdir is used, version and abi are ignored.
203 verbose: (int) if >0, prints compiler version used.
205 if not (is_linux or is_win32):
206 # can't handle this platform
210 SCons.Tool.msvc.generate(env)
212 SCons.Tool.gcc.generate(env)
214 # if version is unspecified, use latest
215 vlist = get_all_compiler_versions()
220 if not get_version_from_list(version, vlist):
221 raise SCons.Errors.UserError, \
222 "Invalid Intel compiler version %s: "%version + \
223 "installed versions are %s"%(', '.join(vlist))
225 # if abi is unspecified, use ia32 (ia64 is another possibility)
227 abi = "ia32" # or ia64, I believe
229 if topdir is None and version:
231 topdir = get_intel_compiler_top(version, abi)
232 except (SCons.Util.RegError, IntelCError):
238 print "Intel C compiler: using version '%s' (%g), abi %s, in '%s'"%\
239 (version, linux_ver_normalize(version),abi,topdir)
241 env['INTEL_C_COMPILER_TOP'] = topdir
243 paths={'INCLUDE' : 'include',
246 'LD_LIBRARY_PATH' : 'lib'}
248 env.PrependENVPath(p, os.path.join(topdir, paths[p]))
250 # env key reg valname default subdir of top
251 paths=(('INCLUDE', 'IncludeDir', 'Include'),
252 ('LIB' , 'LibDir', 'Lib'),
253 ('PATH' , 'BinDir', 'Bin'))
254 # Each path has a registry entry, use that or default to subdir
257 path=get_intel_registry_value(p[1], version, abi)
258 # These paths may have $(ICInstallDir)
259 # which needs to be substituted with the topdir.
260 path=path.replace('$(ICInstallDir)', topdir + os.sep)
262 # Couldn't get it from registry: use default subdir of topdir
263 env.PrependENVPath(p[0], os.path.join(topdir, p[2]))
265 env.PrependENVPath(p[0], string.split(path, os.pathsep))
266 # print "ICL %s: %s, final=%s"%(p[0], path, str(env['ENV'][p[0]]))
271 env['LINK'] = 'xilink'
276 # This is not the exact (detailed) compiler version,
277 # just the major version as determined above or specified
278 # by the user. It is a float like 80 or 90, in normalized form for Linux
279 # (i.e. even for Linux 9.0 compiler, still returns 90 rather than 9.0)
281 env['INTEL_C_COMPILER_VERSION']=linux_ver_normalize(version)
284 # Look for license file dir
285 # in system environment, registry, and default location.
286 envlicdir = os.environ.get("INTEL_LICENSE_FILE", '')
287 K = ('SOFTWARE\Intel\Licenses')
289 k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K)
290 reglicdir = SCons.Util.RegQueryValueEx(k, "w_cpp")[0]
291 except (AttributeError, SCons.Util.RegError):
293 defaultlicdir = r'C:\Program Files\Common Files\Intel\Licenses'
296 for ld in [envlicdir, reglicdir]:
297 if ld and os.path.exists(ld):
301 licdir = defaultlicdir
302 if not os.path.exists(licdir):
303 class ICLLicenseDirWarning(SCons.Warnings.Warning):
305 SCons.Warnings.enableWarningClass(ICLLicenseDirWarning)
306 SCons.Warnings.warn(ICLLicenseDirWarning,
307 "Intel license dir was not found."
308 " Tried using the INTEL_LICENSE_FILE environment variable (%s), the registry (%s) and the default path (%s)."
309 " Using the default path as a last resort."
310 % (envlicdir, reglicdir, defaultlicdir))
311 env['ENV']['INTEL_LICENSE_FILE'] = licdir
314 if not (is_linux or is_win32):
315 # can't handle this platform
319 versions = get_all_compiler_versions()
320 except (SCons.Util.RegError, IntelCError):
322 detected = versions is not None and len(versions) > 0
324 # try env.Detect, maybe that will work
326 return env.Detect('icl')
328 return env.Detect('icc')