Buildbot: fix for missing CUDA compute after recent changes
[blender.git] / build_files / scons / tools / mstoolkit.py
1 """tools.mstoolkit
2
3 Tool-specific initialization for Microsoft Visual C/C++ Toolkit Commandline
4
5 There normally shouldn't be any need to import this module directly.
6 It will usually be imported through the generic SCons.Tool.Tool()
7 selection method.
8
9 """
10
11 #
12 # Copyright (c) 2004 John Connors
13 #
14 # Permission is hereby granted, free of charge, to any person obtaining
15 # a copy of this software and associated documentation files (the
16 # "Software"), to deal in the Software without restriction, including
17 # without limitation the rights to use, copy, modify, merge, publish,
18 # distribute, sublicense, and/or sell copies of the Software, and to
19 # permit persons to whom the Software is furnished to do so, subject to
20 # the following conditions:
21 #
22 # The above copyright notice and this permission notice shall be included
23 # in all copies or substantial portions of the Software.
24 #
25 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
26 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
27 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 #
33
34
35 import os.path
36 import re
37 import string
38 import types
39
40 import SCons.Action
41 import SCons.Builder
42 import SCons.Errors
43 import SCons.Platform.win32
44 import SCons.Tool
45 import SCons.Util
46 import SCons.Warnings
47
48 CSuffixes = ['.c', '.C']
49 CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++']
50
51 def get_msvctoolkit_paths():
52     """Return a 4-tuple of (INCLUDE, LIB, PATH, TOOLKIT) as the values of those
53     three environment variables that should be set in order to execute
54     the MSVC .NET tools properly, if the information wasn't available
55     from the registry."""
56
57     MSToolkitDir = None
58     paths = {}
59     exe_path = ''
60     lib_path = ''
61     include_path = ''
62
63     # First, we get the shell folder for this user:
64     if not SCons.Util.can_read_reg:
65         raise SCons.Errors.InternalError, "No Windows registry module was found"
66
67     # look for toolkit
68     if os.environ.has_key('VCToolkitInstallDir'):
69         MSToolkitDir = os.path.normpath(os.environ['VCToolkitInstallDir'])
70     else:
71         # last resort -- default install location
72         MSToolkitDir = r'C:\Program Files\Microsoft Visual C++ Toolkit 2003'
73
74     # look for platform sdk
75     if os.environ.has_key('MSSdk'):
76         PlatformSDKDir = os.path.normpath(os.environ['MSSdk'])
77     else:
78         try:
79             PlatformSDKDir = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\MicrosoftSDK\Directories\Install Dir')[0]
80             PlatformSDKDir = str(PlatformSDKDir)
81         except SCons.Util.RegError:
82             raise SCons.Errors.InternalError, "The Platform SDK directory was not found in the registry or in the `MSSdk` environment variable."
83
84     # look for DX Sdk (expecting DX9)
85     # dxsdk docs have a directory key, look for it, extract path
86     #dxsdkdocs = ""
87     DXsdkDir = ""
88     #try:
89     #   dxsdkdocs = SCons.Util.RegGetValue(SCons.Util.HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\DirectX SDK\DX9SDK Doc Path')
90     #except SCons.Util.RegError:
91     #   raise SCons.Errors.InternalError, "The DXSDK directory was not found in the registry."
92     if os.environ.has_key('DXSDK_DIR'):
93         DXsdkDir = os.path.normpath(os.environ['DXSDK_DIR'])
94
95     #DXsdkDir = os.path.split(dxsdkdocs[0])[0]
96     DXsdkDir = os.path.split(DXsdkDir)[0]
97
98     include_path = r'%s\include;%s\include;%s\include' % (MSToolkitDir, PlatformSDKDir, DXsdkDir)
99     lib_path = r'%s\lib;%s\lib;%s\lib' % (MSToolkitDir, PlatformSDKDir, DXsdkDir)
100     exe_path = r'%s\bin;%s\bin\win95;%s\bin' % (MSToolkitDir, PlatformSDKDir, PlatformSDKDir)
101     return (include_path, lib_path, exe_path, PlatformSDKDir)
102
103 def validate_vars(env):
104     """Validate the PDB, PCH, and PCHSTOP construction variables."""
105     if env.has_key('PCH') and env['PCH']:
106         if not env.has_key('PCHSTOP'):
107             raise SCons.Errors.UserError, "The PCHSTOP construction must be defined if PCH is defined."
108         if not SCons.Util.is_String(env['PCHSTOP']):
109             raise SCons.Errors.UserError, "The PCHSTOP construction variable must be a string: %r"%env['PCHSTOP']
110
111 def pch_emitter(target, source, env):
112     """Sets up the PDB dependencies for a pch file, and adds the object
113     file target."""
114
115     validate_vars(env)
116
117     pch = None
118     obj = None
119
120     for t in target:
121         if SCons.Util.splitext(str(t))[1] == '.pch':
122             pch = t
123         if SCons.Util.splitext(str(t))[1] == '.obj':
124             obj = t
125
126     if not obj:
127         obj = SCons.Util.splitext(str(pch))[0]+'.obj'
128
129     target = [pch, obj] # pch must be first, and obj second for the PCHCOM to work
130
131     if env.has_key('PDB') and env['PDB']:
132         env.SideEffect(env['PDB'], target)
133         env.Precious(env['PDB'])
134
135     return (target, source)
136
137 def object_emitter(target, source, env, parent_emitter):
138     """Sets up the PDB and PCH dependencies for an object file."""
139
140     validate_vars(env)
141
142     parent_emitter(target, source, env)
143
144     if env.has_key('PDB') and env['PDB']:
145         env.SideEffect(env['PDB'], target)
146         env.Precious(env['PDB'])
147
148     if env.has_key('PCH') and env['PCH']:
149         env.Depends(target, env['PCH'])
150
151     return (target, source)
152
153 def static_object_emitter(target, source, env):
154     return object_emitter(target, source, env,
155                           SCons.Defaults.StaticObjectEmitter)
156
157 def shared_object_emitter(target, source, env):
158     return object_emitter(target, source, env,
159                           SCons.Defaults.SharedObjectEmitter)
160
161 pch_builder = SCons.Builder.Builder(action='$PCHCOM', suffix='.pch', emitter=pch_emitter)
162 res_builder = SCons.Builder.Builder(action='$RCCOM', suffix='.res')
163
164 def pdbGenerator(env, target, source, for_signature):
165     if target and env.has_key('PDB') and env['PDB']:
166         return ['/PDB:%s'%target[0].File(env['PDB']).get_string(for_signature),
167                 '/DEBUG']
168
169 def win32ShlinkTargets(target, source, env, for_signature):
170     listCmd = []
171     dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX')
172     if dll: listCmd.append("/out:%s"%dll.get_string(for_signature))
173
174     implib = env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX')
175     if implib: listCmd.append("/implib:%s"%implib.get_string(for_signature))
176
177     return listCmd
178
179 def win32ShlinkSources(target, source, env, for_signature):
180     listCmd = []
181
182     deffile = env.FindIxes(source, "WIN32DEFPREFIX", "WIN32DEFSUFFIX")
183     for src in source:
184         if src == deffile:
185             # Treat this source as a .def file.
186             listCmd.append("/def:%s" % src.get_string(for_signature))
187         else:
188             # Just treat it as a generic source file.
189             listCmd.append(src)
190     return listCmd
191
192 def win32LibEmitter(target, source, env):
193     # SCons.Tool.msvc.validate_vars(env)
194
195     dll = env.FindIxes(target, "SHLIBPREFIX", "SHLIBSUFFIX")
196     no_import_lib = env.get('no_import_lib', 0)
197
198     if not dll:
199         raise SCons.Errors.UserError, "A shared library should have exactly one target with the suffix: %s" % env.subst("$SHLIBSUFFIX")
200
201     if env.get("WIN32_INSERT_DEF", 0) and \
202        not env.FindIxes(source, "WIN32DEFPREFIX", "WIN32DEFSUFFIX"):
203
204         # append a def file to the list of sources
205         source.append(env.ReplaceIxes(dll,
206                                       "SHLIBPREFIX", "SHLIBSUFFIX",
207                                       "WIN32DEFPREFIX", "WIN32DEFSUFFIX"))
208
209     if env.has_key('PDB') and env['PDB']:
210         env.SideEffect(env['PDB'], target)
211         env.Precious(env['PDB'])
212
213     if not no_import_lib and \
214        not env.FindIxes(target, "LIBPREFIX", "LIBSUFFIX"):
215         # Append an import library to the list of targets.
216         target.append(env.ReplaceIxes(dll,
217                                       "SHLIBPREFIX", "SHLIBSUFFIX",
218                                       "LIBPREFIX", "LIBSUFFIX"))
219         # and .exp file is created if there are exports from a DLL
220         target.append(env.ReplaceIxes(dll,
221                                       "SHLIBPREFIX", "SHLIBSUFFIX",
222                                       "WIN32EXPPREFIX", "WIN32EXPSUFFIX"))
223
224     return (target, source)
225
226 def prog_emitter(target, source, env):
227     #SCons.Tool.msvc.validate_vars(env)
228
229     if env.has_key('PDB') and env['PDB']:
230         env.SideEffect(env['PDB'], target)
231         env.Precious(env['PDB'])
232
233     return (target,source)
234
235 def RegServerFunc(target, source, env):
236     if env.has_key('register') and env['register']:
237         ret = regServerAction([target[0]], [source[0]], env)
238         if ret:
239             raise SCons.Errors.UserError, "Unable to register %s" % target[0]
240         else:
241             print "Registered %s sucessfully" % target[0]
242         return ret
243     return 0
244
245 regServerAction = SCons.Action.Action("$REGSVRCOM")
246 regServerCheck = SCons.Action.Action(RegServerFunc, None)
247 shlibLinkAction = SCons.Action.Action('${TEMPFILE("$SHLINK $SHLINKFLAGS $_SHLINK_TARGETS $( $_LIBDIRFLAGS $) $_LIBFLAGS $_PDB $_SHLINK_SOURCES")}')
248 compositeLinkAction = shlibLinkAction + regServerCheck
249
250 def generate(env):
251     """Add Builders and construction variables for MSVC++ to an Environment."""
252     static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
253
254     for suffix in CSuffixes:
255         static_obj.add_action(suffix, SCons.Defaults.CAction)
256         shared_obj.add_action(suffix, SCons.Defaults.ShCAction)
257
258     for suffix in CXXSuffixes:
259         static_obj.add_action(suffix, SCons.Defaults.CXXAction)
260         shared_obj.add_action(suffix, SCons.Defaults.ShCXXAction)
261
262     SCons.Tool.createStaticLibBuilder(env)
263     SCons.Tool.createSharedLibBuilder(env)
264     SCons.Tool.createProgBuilder(env)
265
266     env['CCPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Zi /Fd%s"%File(PDB)) or ""}'])
267     env['CCPCHFLAGS'] = SCons.Util.CLVar(['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}'])
268     env['CCCOMFLAGS'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET $CCPCHFLAGS $CCPDBFLAGS'
269     env['CC']        = 'cl'
270     env['CCFLAGS']    = SCons.Util.CLVar('/nologo')
271     env['CCCOM']      = '$CC $CCFLAGS $CCCOMFLAGS'
272     env['SHCC']        = '$CC'
273     env['SHCCFLAGS']  = SCons.Util.CLVar('$CCFLAGS')
274     env['SHCCCOM']    = '$SHCC $SHCCFLAGS $CCCOMFLAGS'
275     env['CXX']      = '$CC'
276     env['CXXFLAGS']   = SCons.Util.CLVar('$CCFLAGS $( /TP $)')
277     env['CXXCOM']     = '$CXX $CXXFLAGS $CCCOMFLAGS'
278     env['SHCXX']      = '$CXX'
279     env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
280     env['SHCXXCOM']   = '$SHCXX $SHCXXFLAGS $CCCOMFLAGS'
281     env['CPPDEFPREFIX']  = '/D'
282     env['CPPDEFSUFFIX']  = ''
283     env['INCPREFIX']  = '/I'
284     env['INCSUFFIX']  = ''
285     env['OBJEMITTER'] = static_object_emitter
286     env['SHOBJEMITTER'] = shared_object_emitter
287     env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
288
289     env['RC'] = 'rc'
290     env['RCFLAGS'] = SCons.Util.CLVar('')
291     env['RCCOM'] = '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES'
292     CScan = env.get_scanner('.c')
293     if CScan:
294         CScan.add_skey('.rc')
295     env['BUILDERS']['RES'] = res_builder
296
297     include_path, lib_path, exe_path, sdk_path = get_msvctoolkit_paths()
298     env.PrependENVPath('INCLUDE', include_path)
299     env.PrependENVPath('LIB', lib_path)
300     env.PrependENVPath('PATH', exe_path)
301
302     env['ENV']['CPU'] = 'i386'
303     env['ENV']['MSSDK'] = sdk_path
304     env['ENV']['BkOffice'] = sdk_path
305     env['ENV']['Basemake'] = sdk_path + "\\Include\\BKOffice.Mak"
306     env['ENV']['INETSDK'] = sdk_path
307     env['ENV']['MSSDK'] = sdk_path
308     env['ENV']['MSTOOLS'] = sdk_path
309     env['ENV']['TARGETOS'] = 'WINNT'
310     env['ENV']['APPVER'] = '5.0'
311
312     env['CFILESUFFIX'] = '.c'
313     env['CXXFILESUFFIX'] = '.cc'
314
315     env['PCHCOM'] = '$CXX $CXXFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo${TARGETS[1]} /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS'
316     env['BUILDERS']['PCH'] = pch_builder
317
318     env['AR']     = 'lib.exe' #'"' +sdk_path + '\\bin\\Win64\\lib.exe"'
319     env['ARFLAGS']     = SCons.Util.CLVar('/nologo')
320     env['ARCOM']       = "${TEMPFILE('$AR $ARFLAGS /OUT:$TARGET $SOURCES')}"
321
322     env['SHLINK']      = '$LINK'
323     env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS /dll')
324     env['_SHLINK_TARGETS'] = win32ShlinkTargets
325     env['_SHLINK_SOURCES'] = win32ShlinkSources
326     env['SHLINKCOM']   =  compositeLinkAction
327     env['SHLIBEMITTER']= win32LibEmitter
328     env['LINK'] =  'link.exe' #'"' +sdk_path + '\\bin\\Win64\\' + 'link.exe"'
329     env['LINKFLAGS']   = SCons.Util.CLVar('/nologo')
330     env['_PDB'] = pdbGenerator
331     env["TEMPFILE"] = SCons.Platform.win32.TempFileMunge
332     env['LINKCOM'] = '${TEMPFILE("$LINK $LINKFLAGS /OUT:$TARGET $( $_LIBDIRFLAGS $) $_LIBFLAGS $_PDB $SOURCES")}'
333     env['PROGEMITTER'] = prog_emitter
334     env['LIBDIRPREFIX']='/LIBPATH:'
335     env['LIBDIRSUFFIX']=''
336     env['LIBLINKPREFIX']=''
337     env['LIBLINKSUFFIX']='$LIBSUFFIX'
338
339     env['WIN32DEFPREFIX']   = ''
340     env['WIN32DEFSUFFIX']   = '.def'
341     env['WIN32_INSERT_DEF']      = 0
342
343     env['WIN32EXPPREFIX']   = ''
344     env['WIN32EXPSUFFIX']   = '.exp'
345
346     env['REGSVRACTION'] = regServerCheck
347     env['REGSVR'] = os.path.join(SCons.Platform.win32.get_system_root(),'System32','regsvr32')
348     env['REGSVRFLAGS'] = '/s '
349     env['REGSVRCOM'] = '$REGSVR $REGSVRFLAGS $TARGET'
350
351
352 def exists(env):
353     return env.Detect('cl')