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