f979700f82f9526ead020ad963d3ea8def848ec6
[scons.git] / src / engine / SCons / Tool / intelc.py
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__
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 #
34
35 __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
36
37 import sys, os.path, glob, re
38
39 is_win32 = sys.platform == 'win32'
40 is_linux = sys.platform == 'linux2'
41
42 if is_win32:
43     import SCons.Tool.msvc
44 elif is_linux:
45     import SCons.Tool.gcc
46 import SCons.Util
47 import SCons.Warnings
48
49
50 def fltcmp(a, b):
51     """Compare strings as floats"""
52     return cmp(float(b), float(a))
53
54 def get_intel_registry_value(valuename, version=None, abi=None):
55     """
56     Return a value from the Intel compiler registry tree. (Win32 only)
57     """
58
59     # Open the key:
60     K = 'Software\\Intel\\Compilers\\C++\\' + version + '\\'+abi.upper()
61     try:
62         k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K)
63     except SCons.Util.RegError:
64         raise SCons.Errors.InternalError, \
65               "%s was not found in the registry, for Intel compiler version %s"%(K, version)
66
67     # Get the value:
68     try:
69         v = SCons.Util.RegQueryValueEx(k, valuename)[0]
70         return v  # or v.encode('iso-8859-1', 'replace') to remove unicode?
71     except SCons.Util.RegError:
72         raise SCons.Errors.InternalError, \
73               "%s\\%s was not found in the registry."%(K, value)
74
75
76 def get_all_compiler_versions():
77     """Returns a sorted list of strings, like "70" or "80"
78     with most recent compiler version first.
79     """
80     versions=[]
81     if is_win32:
82         keyname = 'Software\\Intel\\Compilers\\C++'
83         k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE,
84                                     keyname)
85         i = 0
86         versions = []
87         try:
88             while i < 100:
89                 subkey = SCons.Util.RegEnumKey(k, i) # raises EnvironmentError
90                 versions.append(subkey)
91                 i = i + 1
92         except EnvironmentError:
93             # no more subkeys
94             pass
95     elif is_linux:
96         # Typical dir here is /opt/intel_cc_80.
97         for d in glob.glob('/opt/intel_cc_*'):
98             versions.append(re.search(r'cc_(.*)$', d).group(1))
99     versions.sort(fltcmp)
100     return versions
101
102 def get_intel_compiler_top(version=None, abi=None):
103     """
104     Return the main path to the top-level dir of the Intel compiler,
105     using the given version or latest if None.
106     The compiler will be in <top>/bin/icl.exe (icc on linux),
107     the include dir is <top>/include, etc.
108     """
109
110     if is_win32:
111         if not SCons.Util.can_read_reg:
112             raise SCons.Errors.InternalError, "No Windows registry module was found"
113         top = get_intel_registry_value('ProductDir', version, abi)
114
115         if not os.path.exists(os.path.join(top, "Bin", "icl.exe")):
116             raise SCons.Errors.InternalError, \
117                   "Can't find Intel compiler in %s"%(top)
118     elif is_linux:
119         top = '/opt/intel_cc_%s'%version
120         if not os.path.exists(os.path.join(top, "bin", "icc")):
121             raise SCons.Errors.InternalError, \
122                   "Can't find version %s Intel compiler in %s"%(version,top)
123     return top
124
125
126 def generate(env, version=None, abi=None, topdir=None, verbose=1):
127     """Add Builders and construction variables for Intel C/C++ compiler
128     to an Environment.
129     args:
130       version: (string) compiler version to use, like "80"
131       abi:     (string) 'win32' or whatever Itanium version wants
132       topdir:  (string) compiler top dir, like
133                          "c:\Program Files\Intel\Compiler70"
134                         If topdir is used, version and abi are ignored.
135       verbose: (int)    if >0, prints compiler version used.
136     """
137     if not (is_linux or is_win32):
138         # can't handle this platform
139         return
140
141     if is_win32:
142         SCons.Tool.msvc.generate(env)
143     elif is_linux:
144         SCons.Tool.gcc.generate(env)
145         
146     # if version is unspecified, use latest
147     vlist = get_all_compiler_versions()
148     if not version:
149         if vlist:
150             version = vlist[0]
151     else:
152         if version not in vlist:
153             raise SCons.Errors.UserError, \
154                   "Invalid Intel compiler version %s: "%version + \
155                   "installed versions are %s"%(', '.join(vlist))
156
157     # if abi is unspecified, use ia32 (ia64 is another possibility)
158     if abi is None:
159         abi = "ia32"                    # or ia64, I believe
160
161     if topdir is None:
162         try:
163             topdir = get_intel_compiler_top(version, abi)
164         except (SCons.Util.RegError, SCons.Errors.InternalError):
165             topdir = None
166
167     if topdir:
168
169         if verbose:
170             print "Intel C compiler: using version %s, abi %s, in '%s'"%(version,abi,topdir)
171
172         env['INTEL_C_COMPILER_TOP'] = topdir
173         if is_linux:
174             paths={'INCLUDE'         : 'include',
175                    'LIB'             : 'lib',
176                    'PATH'            : 'bin',
177                    'LD_LIBRARY_PATH' : 'lib'}
178             for p in paths:
179                 env.PrependENVPath(p, os.path.join(topdir, paths[p]))
180         if is_win32:
181             #       env key    reg valname   default subdir of top
182             paths=(('INCLUDE', 'IncludeDir', 'Include'),
183                    ('LIB'    , 'LibDir',     'Lib'),
184                    ('PATH'   , 'BinDir',     'Bin'))
185             # Each path has a registry entry, use that or default to subdir
186             for p in paths:
187                 try:
188                     path=get_intel_registry_value(p[1], version, abi)
189                     env.PrependENVPath(p[0], ';'.split(path))
190                     # print "ICL %s: %s, final=%s"%(p[0], path, str(env['ENV'][p[0]]))
191                 except:
192                     env.PrependENVPath(p[0], os.path.join(topdir, p[2]))
193
194     if is_win32:
195         env['CC']        = 'icl'
196         env['CXX']       = 'icl'
197         env['LINK']      = 'xilink'
198     else:
199         env['CC']        = 'icc'
200         env['CXX']       = 'icpc'
201         env['LINK']      = '$CC'
202
203     if is_win32:
204         # Look for license file dir
205         # in system environment, registry, and default location.
206         envlicdir = os.environ.get("INTEL_LICENSE_FILE", '')
207         K = ('SOFTWARE\Intel\Licenses')
208         try:
209             k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K)
210             reglicdir = SCons.Util.RegQueryValueEx(k, "w_cpp")[0]
211         except (AttributeError, SCons.Util.RegError):
212             reglicdir = ""
213         defaultlicdir = r'C:\Program Files\Common Files\Intel\Licenses'
214
215         licdir = None
216         for ld in [envlicdir, reglicdir]:
217             if ld and os.path.exists(ld):
218                 licdir = ld
219                 break
220         if not licdir:
221             licdir = defaultlicdir
222             if not os.path.exists(licdir):
223                 class ICLLicenseDirWarning(SCons.Warnings.Warning):
224                     pass
225                 SCons.Warnings.enableWarningClass(ICLLicenseDirWarning)
226                 SCons.Warnings.warn(ICLLicenseDirWarning,
227                                     "Intel license dir was not found."
228                                     "  Tried using the INTEL_LICENSE_FILE environment variable (%s), the registry (%s) and the default path (%s)."
229                                     "  Using the default path as a last resort."
230                                         % (envlicdir, reglicdir, defaultlicdir))
231         env['ENV']['INTEL_LICENSE_FILE'] = licdir
232
233 def exists(env):
234     if not (is_linux or is_win32):
235         # can't handle this platform
236         return 0
237
238     try:
239         top = get_intel_compiler_top()
240     except (SCons.Util.RegError, SCons.Errors.InternalError):
241         top = None
242     if not top:
243         # try env.Detect, maybe that will work
244         if is_win32:
245             return env.Detect('icl')
246         elif is_linux:
247             return env.Detect('icc')
248     return top is not None
249
250 # end of file