3 Tool-specific initialization for Microsoft Windows DDK.
5 Based on engine.SCons.Tool.msvc.
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()
14 # Copyright (c) 2001-2007 The SCons Foundation
15 # Copyright (c) 2008 Tungsten Graphics, Inc.
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:
25 # The above copyright notice and this permission notice shall be included
26 # in all copies or substantial portions of the Software.
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.
44 import SCons
.Platform
.win32
46 import SCons
.Tool
.mslib
47 import SCons
.Tool
.mslink
51 CSuffixes
= ['.c', '.C']
52 CXXSuffixes
= ['.cc', '.cpp', '.cxx', '.c++', '.C++']
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."""
64 if 'BASEDIR' in os
.environ
:
65 WINDDKdir
= os
.environ
['BASEDIR']
67 WINDDKdir
= "C:\\WINDDK\\3790.1830"
69 exe_paths
.append( os
.path
.join(WINDDKdir
, 'bin') )
70 exe_paths
.append( os
.path
.join(WINDDKdir
, 'bin', 'x86') )
71 include_paths
.append( os
.path
.join(WINDDKdir
, 'inc', 'wxp') )
72 lib_paths
.append( os
.path
.join(WINDDKdir
, 'lib') )
77 env
['SDK_INC_PATH'] = os
.path
.join(WINDDKdir
, 'inc', target_os
)
78 env
['CRT_INC_PATH'] = os
.path
.join(WINDDKdir
, 'inc', 'crt')
79 env
['DDK_INC_PATH'] = os
.path
.join(WINDDKdir
, 'inc', 'ddk', target_os
)
80 env
['WDM_INC_PATH'] = os
.path
.join(WINDDKdir
, 'inc', 'ddk', 'wdm', target_os
)
82 env
['SDK_LIB_PATH'] = os
.path
.join(WINDDKdir
, 'lib', target_os
, target_cpu
)
83 env
['CRT_LIB_PATH'] = os
.path
.join(WINDDKdir
, 'lib', 'crt', target_cpu
)
84 env
['DDK_LIB_PATH'] = os
.path
.join(WINDDKdir
, 'lib', target_os
, target_cpu
)
85 env
['WDM_LIB_PATH'] = os
.path
.join(WINDDKdir
, 'lib', target_os
, target_cpu
)
87 include_path
= string
.join( include_paths
, os
.pathsep
)
88 lib_path
= string
.join(lib_paths
, os
.pathsep
)
89 exe_path
= string
.join(exe_paths
, os
.pathsep
)
90 return (include_path
, lib_path
, exe_path
)
92 def set_winddk_flags(env
):
93 """Mimic WINDDK's builtin flags.
96 - WINDDK's bin/makefile.new i386mk.inc for more info.
97 - buildchk_wxp_x86.log files, generated by the WINDDK's build
98 - http://alter.org.ua/docs/nt_kernel/vc8_proj/
105 ('CONDITION_HANDLING', '1'),
110 ('_WIN32_WINNT', '0x0501'), # minimum required OS version
111 ('WINVER', '0x0501'),
112 ('_WIN32_IE', '0x0603'),
113 ('WIN32_LEAN_AND_MEAN', '1'),
115 ('__BUILDMACHINE__', 'WinDDK'),
118 if env
.get('DEBUG', False):
122 env
.Append(CPPDEFINES
= cppdefines
)
125 # - http://msdn2.microsoft.com/en-us/library/y0zzbyt4.aspx
128 '/Zl', # omit default library name in .OBJ
129 '/Zp8', # 8bytes struct member alignment
130 '/Gy', # separate functions for linker
131 '/Gm-', # disable minimal rebuild
132 '/W3', # warning level
133 '/WX', # treat warnings as errors
134 '/Gz', # __stdcall Calling convention
135 '/GX-', # disable C++ EH
136 '/GR-', # disable C++ RTTI
137 '/GF', # enable read-only string pooling
138 '/GS', # enable security checks
139 '/G6', # optimize for PPro, P-II, P-III
140 '/Ze', # enable extensions
142 '/QIfdiv-', # disable Pentium FDIV fix
144 #'/Z7', #enable old-style debug info
146 if env
.get('debug', False):
148 '/Od', # disable optimizations
149 '/Oi', # enable intrinsic functions
150 '/Oy-', # disable frame pointer omission
154 '/Ox', # maximum optimizations
155 '/Oi', # enable intrinsic functions
156 '/Os', # favor code space
158 env
.Append(CFLAGS
= cflags
)
159 env
.Append(CXXFLAGS
= cflags
)
162 # - http://msdn2.microsoft.com/en-us/library/y0zzbyt4.aspx
163 env
.Append(LINKFLAGS
= [
165 '/merge:_TEXT=.text',
169 '/ignore:4198,4010,4037,4039,4065,4070,4078,4087,4089,4221',
182 '/stack:0x40000,0x1000',
185 '/subsystem:native,5.01',
188 '/entry:DrvEnableDriver',
191 def validate_vars(env
):
192 """Validate the PCH and PCHSTOP construction variables."""
193 if env
.has_key('PCH') and env
['PCH']:
194 if not env
.has_key('PCHSTOP'):
195 raise SCons
.Errors
.UserError
, "The PCHSTOP construction must be defined if PCH is defined."
196 if not SCons
.Util
.is_String(env
['PCHSTOP']):
197 raise SCons
.Errors
.UserError
, "The PCHSTOP construction variable must be a string: %r"%env
['PCHSTOP']
199 def pch_emitter(target
, source
, env
):
200 """Adds the object file target."""
208 if SCons
.Util
.splitext(str(t
))[1] == '.pch':
210 if SCons
.Util
.splitext(str(t
))[1] == '.obj':
214 obj
= SCons
.Util
.splitext(str(pch
))[0]+'.obj'
216 target
= [pch
, obj
] # pch must be first, and obj second for the PCHCOM to work
218 return (target
, source
)
220 def object_emitter(target
, source
, env
, parent_emitter
):
221 """Sets up the PCH dependencies for an object file."""
225 parent_emitter(target
, source
, env
)
227 if env
.has_key('PCH') and env
['PCH']:
228 env
.Depends(target
, env
['PCH'])
230 return (target
, source
)
232 def static_object_emitter(target
, source
, env
):
233 return object_emitter(target
, source
, env
,
234 SCons
.Defaults
.StaticObjectEmitter
)
236 def shared_object_emitter(target
, source
, env
):
237 return object_emitter(target
, source
, env
,
238 SCons
.Defaults
.SharedObjectEmitter
)
240 pch_action
= SCons
.Action
.Action('$PCHCOM', '$PCHCOMSTR')
241 pch_builder
= SCons
.Builder
.Builder(action
=pch_action
, suffix
='.pch',
243 source_scanner
=SCons
.Tool
.SourceFileScanner
)
244 res_action
= SCons
.Action
.Action('$RCCOM', '$RCCOMSTR')
245 res_builder
= SCons
.Builder
.Builder(action
=res_action
,
249 source_scanner
=SCons
.Tool
.SourceFileScanner
)
250 SCons
.Tool
.SourceFileScanner
.add_scanner('.rc', SCons
.Defaults
.CScan
)
253 """Add Builders and construction variables for MSVC++ to an Environment."""
254 static_obj
, shared_obj
= SCons
.Tool
.createObjBuilders(env
)
256 for suffix
in CSuffixes
:
257 static_obj
.add_action(suffix
, SCons
.Defaults
.CAction
)
258 shared_obj
.add_action(suffix
, SCons
.Defaults
.ShCAction
)
259 static_obj
.add_emitter(suffix
, static_object_emitter
)
260 shared_obj
.add_emitter(suffix
, shared_object_emitter
)
262 for suffix
in CXXSuffixes
:
263 static_obj
.add_action(suffix
, SCons
.Defaults
.CXXAction
)
264 shared_obj
.add_action(suffix
, SCons
.Defaults
.ShCXXAction
)
265 static_obj
.add_emitter(suffix
, static_object_emitter
)
266 shared_obj
.add_emitter(suffix
, shared_object_emitter
)
268 env
['CCPDBFLAGS'] = SCons
.Util
.CLVar(['${(PDB and "/Z7") or ""}'])
269 env
['CCPCHFLAGS'] = SCons
.Util
.CLVar(['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}'])
270 env
['CCCOMFLAGS'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET $CCPCHFLAGS $CCPDBFLAGS'
272 env
['CCFLAGS'] = SCons
.Util
.CLVar('/nologo')
273 env
['CFLAGS'] = SCons
.Util
.CLVar('')
274 env
['CCCOM'] = '$CC $CFLAGS $CCFLAGS $CCCOMFLAGS'
276 env
['SHCCFLAGS'] = SCons
.Util
.CLVar('$CCFLAGS')
277 env
['SHCFLAGS'] = SCons
.Util
.CLVar('$CFLAGS')
278 env
['SHCCCOM'] = '$SHCC $SHCFLAGS $SHCCFLAGS $CCCOMFLAGS'
280 env
['CXXFLAGS'] = SCons
.Util
.CLVar('$CCFLAGS $( /TP $)')
281 env
['CXXCOM'] = '$CXX $CXXFLAGS $CCCOMFLAGS'
282 env
['SHCXX'] = '$CXX'
283 env
['SHCXXFLAGS'] = SCons
.Util
.CLVar('$CXXFLAGS')
284 env
['SHCXXCOM'] = '$SHCXX $SHCXXFLAGS $CCCOMFLAGS'
285 env
['CPPDEFPREFIX'] = '/D'
286 env
['CPPDEFSUFFIX'] = ''
287 env
['INCPREFIX'] = '/I'
288 env
['INCSUFFIX'] = ''
289 # env.Append(OBJEMITTER = [static_object_emitter])
290 # env.Append(SHOBJEMITTER = [shared_object_emitter])
291 env
['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
294 env
['RCFLAGS'] = SCons
.Util
.CLVar('')
295 env
['RCCOM'] = '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES'
296 env
['BUILDERS']['RES'] = res_builder
297 env
['OBJPREFIX'] = ''
298 env
['OBJSUFFIX'] = '.obj'
299 env
['SHOBJPREFIX'] = '$OBJPREFIX'
300 env
['SHOBJSUFFIX'] = '$OBJSUFFIX'
302 env
['CFILESUFFIX'] = '.c'
303 env
['CXXFILESUFFIX'] = '.cc'
305 env
['PCHPDBFLAGS'] = SCons
.Util
.CLVar(['${(PDB and "/Yd") or ""}'])
306 env
['PCHCOM'] = '$CXX $CXXFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo${TARGETS[1]} /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS'
307 env
['BUILDERS']['PCH'] = pch_builder
310 env
['ARFLAGS'] = SCons
.Util
.CLVar('/nologo')
311 env
['ARCOM'] = "${TEMPFILE('$AR $ARFLAGS /OUT:$TARGET $SOURCES')}"
312 env
['LIBPREFIX'] = ''
313 env
['LIBSUFFIX'] = '.lib'
315 SCons
.Tool
.mslink
.generate(env
)
317 set_winddk_flags(env
)
319 if not env
.has_key('ENV'):
323 include_path
, lib_path
, exe_path
= get_winddk_paths(env
)
325 # since other tools can set these, we just make sure that the
326 # relevant stuff from WINDDK is in there somewhere.
327 env
.PrependENVPath('INCLUDE', include_path
)
328 env
.PrependENVPath('LIB', lib_path
)
329 env
.PrependENVPath('PATH', exe_path
)
330 except (SCons
.Util
.RegError
, SCons
.Errors
.InternalError
):
335 return env
.Detect('cl')