Merge remote branch 'nouveau/gallium-0.1' into nouveau-gallium-0.1
[profile/ivi/mesa.git] / winddk.py
1 """winddk
2
3 Tool-specific initialization for Microsoft Windows DDK.
4
5 Based on engine.SCons.Tool.msvc.
6
7 There normally shouldn't be any need to import this module directly.
8 It will usually be imported through the generic SCons.Tool.Tool()
9 selection method.
10
11 """
12
13 #
14 # Copyright (c) 2001-2007 The SCons Foundation
15 # Copyright (c) 2008 Tungsten Graphics, Inc.
16 #
17 # Permission is hereby granted, free of charge, to any person obtaining
18 # a copy of this software and associated documentation files (the
19 # "Software"), to deal in the Software without restriction, including
20 # without limitation the rights to use, copy, modify, merge, publish,
21 # distribute, sublicense, and/or sell copies of the Software, and to
22 # permit persons to whom the Software is furnished to do so, subject to
23 # the following conditions:
24 #
25 # The above copyright notice and this permission notice shall be included
26 # in all copies or substantial portions of the Software.
27 #
28 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
29 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
30 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 #
36
37 import os.path
38 import re
39 import string
40
41 import SCons.Action
42 import SCons.Builder
43 import SCons.Errors
44 import SCons.Platform.win32
45 import SCons.Tool
46 import SCons.Tool.mslib
47 import SCons.Tool.mslink
48 import SCons.Util
49 import SCons.Warnings
50
51 CSuffixes = ['.c', '.C']
52 CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++']
53
54 def get_winddk_paths(env, version=None):
55     """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values
56     of those three environment variables that should be set
57     in order to execute the MSVC tools properly."""
58     
59     WINDDKdir = None
60     exe_paths = []
61     lib_paths = []
62     include_paths = []
63
64     if 'BASEDIR' in os.environ:
65         WINDDKdir = os.environ['BASEDIR']
66     else:
67         #WINDDKdir = "C:\\WINDDK\\3790.1830"
68         WINDDKdir = "C:/WINDDK/3790.1830"
69
70     exe_paths.append( os.path.join(WINDDKdir, 'bin') )
71     exe_paths.append( os.path.join(WINDDKdir, 'bin/x86') )
72     include_paths.append( os.path.join(WINDDKdir, 'inc/wxp') )
73     lib_paths.append( os.path.join(WINDDKdir, 'lib') )
74
75     target_os = 'wxp'
76     target_cpu = 'i386'
77     
78     env['SDK_INC_PATH'] = os.path.join(WINDDKdir, 'inc', target_os) 
79     env['CRT_INC_PATH'] = os.path.join(WINDDKdir, 'inc/crt') 
80     env['DDK_INC_PATH'] = os.path.join(WINDDKdir, 'inc/ddk', target_os) 
81     env['WDM_INC_PATH'] = os.path.join(WINDDKdir, 'inc/ddk/wdm', target_os) 
82
83     env['SDK_LIB_PATH'] = os.path.join(WINDDKdir, 'lib', target_os, target_cpu) 
84     env['CRT_LIB_PATH'] = os.path.join(WINDDKdir, 'lib/crt', target_cpu) 
85     env['DDK_LIB_PATH'] = os.path.join(WINDDKdir, 'lib', target_os, target_cpu)
86     env['WDM_LIB_PATH'] = os.path.join(WINDDKdir, 'lib', target_os, target_cpu)
87                                      
88     include_path = string.join( include_paths, os.pathsep )
89     lib_path = string.join(lib_paths, os.pathsep )
90     exe_path = string.join(exe_paths, os.pathsep )
91     return (include_path, lib_path, exe_path)
92
93 def validate_vars(env):
94     """Validate the PCH and PCHSTOP construction variables."""
95     if env.has_key('PCH') and env['PCH']:
96         if not env.has_key('PCHSTOP'):
97             raise SCons.Errors.UserError, "The PCHSTOP construction must be defined if PCH is defined."
98         if not SCons.Util.is_String(env['PCHSTOP']):
99             raise SCons.Errors.UserError, "The PCHSTOP construction variable must be a string: %r"%env['PCHSTOP']
100
101 def pch_emitter(target, source, env):
102     """Adds the object file target."""
103
104     validate_vars(env)
105
106     pch = None
107     obj = None
108
109     for t in target:
110         if SCons.Util.splitext(str(t))[1] == '.pch':
111             pch = t
112         if SCons.Util.splitext(str(t))[1] == '.obj':
113             obj = t
114
115     if not obj:
116         obj = SCons.Util.splitext(str(pch))[0]+'.obj'
117
118     target = [pch, obj] # pch must be first, and obj second for the PCHCOM to work
119
120     return (target, source)
121
122 def object_emitter(target, source, env, parent_emitter):
123     """Sets up the PCH dependencies for an object file."""
124
125     validate_vars(env)
126
127     parent_emitter(target, source, env)
128
129     if env.has_key('PCH') and env['PCH']:
130         env.Depends(target, env['PCH'])
131
132     return (target, source)
133
134 def static_object_emitter(target, source, env):
135     return object_emitter(target, source, env,
136                           SCons.Defaults.StaticObjectEmitter)
137
138 def shared_object_emitter(target, source, env):
139     return object_emitter(target, source, env,
140                           SCons.Defaults.SharedObjectEmitter)
141
142 pch_action = SCons.Action.Action('$PCHCOM', '$PCHCOMSTR')
143 pch_builder = SCons.Builder.Builder(action=pch_action, suffix='.pch',
144                                     emitter=pch_emitter,
145                                     source_scanner=SCons.Tool.SourceFileScanner)
146 res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR')
147 res_builder = SCons.Builder.Builder(action=res_action,
148                                     src_suffix='.rc',
149                                     suffix='.res',
150                                     src_builder=[],
151                                     source_scanner=SCons.Tool.SourceFileScanner)
152 SCons.Tool.SourceFileScanner.add_scanner('.rc', SCons.Defaults.CScan)
153
154 def generate(env):
155     """Add Builders and construction variables for MSVC++ to an Environment."""
156     static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
157
158     for suffix in CSuffixes:
159         static_obj.add_action(suffix, SCons.Defaults.CAction)
160         shared_obj.add_action(suffix, SCons.Defaults.ShCAction)
161         static_obj.add_emitter(suffix, static_object_emitter)
162         shared_obj.add_emitter(suffix, shared_object_emitter)
163
164     for suffix in CXXSuffixes:
165         static_obj.add_action(suffix, SCons.Defaults.CXXAction)
166         shared_obj.add_action(suffix, SCons.Defaults.ShCXXAction)
167         static_obj.add_emitter(suffix, static_object_emitter)
168         shared_obj.add_emitter(suffix, shared_object_emitter)
169
170     env['CCPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Z7") or ""}'])
171     env['CCPCHFLAGS'] = SCons.Util.CLVar(['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}'])
172     env['CCCOMFLAGS'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET $CCPCHFLAGS $CCPDBFLAGS'
173     env['CC']         = 'cl'
174     env['CCFLAGS']    = SCons.Util.CLVar('/nologo')
175     env['CFLAGS']     = SCons.Util.CLVar('')
176     env['CCCOM']      = '$CC $CFLAGS $CCFLAGS $CCCOMFLAGS'
177     env['SHCC']       = '$CC'
178     env['SHCCFLAGS']  = SCons.Util.CLVar('$CCFLAGS')
179     env['SHCFLAGS']   = SCons.Util.CLVar('$CFLAGS')
180     env['SHCCCOM']    = '$SHCC $SHCFLAGS $SHCCFLAGS $CCCOMFLAGS'
181     env['CXX']        = '$CC'
182     env['CXXFLAGS']   = SCons.Util.CLVar('$CCFLAGS $( /TP $)')
183     env['CXXCOM']     = '$CXX $CXXFLAGS $CCCOMFLAGS'
184     env['SHCXX']      = '$CXX'
185     env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
186     env['SHCXXCOM']   = '$SHCXX $SHCXXFLAGS $CCCOMFLAGS'
187     env['CPPDEFPREFIX']  = '/D'
188     env['CPPDEFSUFFIX']  = ''
189     env['INCPREFIX']  = '/I'
190     env['INCSUFFIX']  = ''
191 #    env.Append(OBJEMITTER = [static_object_emitter])
192 #    env.Append(SHOBJEMITTER = [shared_object_emitter])
193     env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
194
195     env['RC'] = 'rc'
196     env['RCFLAGS'] = SCons.Util.CLVar('')
197     env['RCCOM'] = '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES'
198     env['BUILDERS']['RES'] = res_builder
199     env['OBJPREFIX']      = ''
200     env['OBJSUFFIX']      = '.obj'
201     env['SHOBJPREFIX']    = '$OBJPREFIX'
202     env['SHOBJSUFFIX']    = '$OBJSUFFIX'
203
204     try:
205         include_path, lib_path, exe_path = get_winddk_paths(env)
206
207         # since other tools can set these, we just make sure that the
208         # relevant stuff from MSVS is in there somewhere.
209         env.PrependENVPath('INCLUDE', include_path)
210         env.PrependENVPath('LIB', lib_path)
211         env.PrependENVPath('PATH', exe_path)
212     except (SCons.Util.RegError, SCons.Errors.InternalError):
213         pass
214
215     env['CFILESUFFIX'] = '.c'
216     env['CXXFILESUFFIX'] = '.cc'
217
218     env['PCHPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Yd") or ""}'])
219     env['PCHCOM'] = '$CXX $CXXFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo${TARGETS[1]} /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS'
220     env['BUILDERS']['PCH'] = pch_builder
221
222     env['AR']          = 'lib'
223     env['ARFLAGS']     = SCons.Util.CLVar('/nologo')
224     env['ARCOM']       = "${TEMPFILE('$AR $ARFLAGS /OUT:$TARGET $SOURCES')}"
225     env['LIBPREFIX']   = ''
226     env['LIBSUFFIX']   = '.lib'
227
228     SCons.Tool.mslink.generate(env)
229
230     # See also:
231     # - WINDDK's bin/makefile.new i386mk.inc for more info.
232     # - http://alter.org.ua/docs/nt_kernel/vc8_proj/
233     env.Append(CPPDEFINES = [
234         'WIN32', 
235         '_WINDOWS', 
236         ('i386', '1'), 
237         ('_X86_', '1'), 
238         'STD_CALL', 
239         ('CONDITION_HANDLING', '1'),
240         ('NT_INST', '0'), 
241         ('_NT1X_', '100'),
242         ('WINNT', '1'),
243         ('_WIN32_WINNT', '0x0500'), # minimum required OS version
244         ('WIN32_LEAN_AND_MEAN', '1'),
245         ('DEVL', '1'),
246         ('FPO', '1'),
247     ])
248     cflags = [
249         '/GF', # Enable String Pooling
250         '/GX-', # Disable C++ Exceptions
251         '/Zp8', # 8bytes struct member alignment
252         #'/GS-', # No Buffer Security Check
253         '/GR-', # Disable Run-Time Type Info
254         '/Gz', # __stdcall Calling convention
255     ]
256     env.Append(CFLAGS = cflags)
257     env.Append(CXXFLAGS = cflags)
258     
259     env.Append(LINKFLAGS = [
260         '/DEBUG',
261         '/NODEFAULTLIB',
262         '/SUBSYSTEM:NATIVE',
263         '/INCREMENTAL:NO',
264         #'/DRIVER', 
265     
266         #'-subsystem:native,4.00',
267         '-base:0x10000',
268         
269         '-entry:DrvEnableDriver',
270     ])
271     
272     if not env.has_key('ENV'):
273         env['ENV'] = {}
274     if not env['ENV'].has_key('SystemRoot'):    # required for dlls in the winsxs folders
275         env['ENV']['SystemRoot'] = SCons.Platform.win32.get_system_root()
276
277 def exists(env):
278     return env.Detect('cl')
279