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 validate_vars(env
):
93 """Validate the PCH and PCHSTOP construction variables."""
94 if env
.has_key('PCH') and env
['PCH']:
95 if not env
.has_key('PCHSTOP'):
96 raise SCons
.Errors
.UserError
, "The PCHSTOP construction must be defined if PCH is defined."
97 if not SCons
.Util
.is_String(env
['PCHSTOP']):
98 raise SCons
.Errors
.UserError
, "The PCHSTOP construction variable must be a string: %r"%env
['PCHSTOP']
100 def pch_emitter(target
, source
, env
):
101 """Adds the object file target."""
109 if SCons
.Util
.splitext(str(t
))[1] == '.pch':
111 if SCons
.Util
.splitext(str(t
))[1] == '.obj':
115 obj
= SCons
.Util
.splitext(str(pch
))[0]+'.obj'
117 target
= [pch
, obj
] # pch must be first, and obj second for the PCHCOM to work
119 return (target
, source
)
121 def object_emitter(target
, source
, env
, parent_emitter
):
122 """Sets up the PCH dependencies for an object file."""
126 parent_emitter(target
, source
, env
)
128 if env
.has_key('PCH') and env
['PCH']:
129 env
.Depends(target
, env
['PCH'])
131 return (target
, source
)
133 def static_object_emitter(target
, source
, env
):
134 return object_emitter(target
, source
, env
,
135 SCons
.Defaults
.StaticObjectEmitter
)
137 def shared_object_emitter(target
, source
, env
):
138 return object_emitter(target
, source
, env
,
139 SCons
.Defaults
.SharedObjectEmitter
)
141 pch_action
= SCons
.Action
.Action('$PCHCOM', '$PCHCOMSTR')
142 pch_builder
= SCons
.Builder
.Builder(action
=pch_action
, suffix
='.pch',
144 source_scanner
=SCons
.Tool
.SourceFileScanner
)
145 res_action
= SCons
.Action
.Action('$RCCOM', '$RCCOMSTR')
146 res_builder
= SCons
.Builder
.Builder(action
=res_action
,
150 source_scanner
=SCons
.Tool
.SourceFileScanner
)
151 SCons
.Tool
.SourceFileScanner
.add_scanner('.rc', SCons
.Defaults
.CScan
)
154 """Add Builders and construction variables for MSVC++ to an Environment."""
155 static_obj
, shared_obj
= SCons
.Tool
.createObjBuilders(env
)
157 for suffix
in CSuffixes
:
158 static_obj
.add_action(suffix
, SCons
.Defaults
.CAction
)
159 shared_obj
.add_action(suffix
, SCons
.Defaults
.ShCAction
)
160 static_obj
.add_emitter(suffix
, static_object_emitter
)
161 shared_obj
.add_emitter(suffix
, shared_object_emitter
)
163 for suffix
in CXXSuffixes
:
164 static_obj
.add_action(suffix
, SCons
.Defaults
.CXXAction
)
165 shared_obj
.add_action(suffix
, SCons
.Defaults
.ShCXXAction
)
166 static_obj
.add_emitter(suffix
, static_object_emitter
)
167 shared_obj
.add_emitter(suffix
, shared_object_emitter
)
169 env
['CCPDBFLAGS'] = SCons
.Util
.CLVar(['${(PDB and "/Z7") or ""}'])
170 env
['CCPCHFLAGS'] = SCons
.Util
.CLVar(['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}'])
171 env
['CCCOMFLAGS'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET $CCPCHFLAGS $CCPDBFLAGS'
173 env
['CCFLAGS'] = SCons
.Util
.CLVar('/nologo')
174 env
['CFLAGS'] = SCons
.Util
.CLVar('')
175 env
['CCCOM'] = '$CC $CFLAGS $CCFLAGS $CCCOMFLAGS'
177 env
['SHCCFLAGS'] = SCons
.Util
.CLVar('$CCFLAGS')
178 env
['SHCFLAGS'] = SCons
.Util
.CLVar('$CFLAGS')
179 env
['SHCCCOM'] = '$SHCC $SHCFLAGS $SHCCFLAGS $CCCOMFLAGS'
181 env
['CXXFLAGS'] = SCons
.Util
.CLVar('$CCFLAGS $( /TP $)')
182 env
['CXXCOM'] = '$CXX $CXXFLAGS $CCCOMFLAGS'
183 env
['SHCXX'] = '$CXX'
184 env
['SHCXXFLAGS'] = SCons
.Util
.CLVar('$CXXFLAGS')
185 env
['SHCXXCOM'] = '$SHCXX $SHCXXFLAGS $CCCOMFLAGS'
186 env
['CPPDEFPREFIX'] = '/D'
187 env
['CPPDEFSUFFIX'] = ''
188 env
['INCPREFIX'] = '/I'
189 env
['INCSUFFIX'] = ''
190 # env.Append(OBJEMITTER = [static_object_emitter])
191 # env.Append(SHOBJEMITTER = [shared_object_emitter])
192 env
['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
195 env
['RCFLAGS'] = SCons
.Util
.CLVar('')
196 env
['RCCOM'] = '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES'
197 env
['BUILDERS']['RES'] = res_builder
198 env
['OBJPREFIX'] = ''
199 env
['OBJSUFFIX'] = '.obj'
200 env
['SHOBJPREFIX'] = '$OBJPREFIX'
201 env
['SHOBJSUFFIX'] = '$OBJSUFFIX'
203 env
['CFILESUFFIX'] = '.c'
204 env
['CXXFILESUFFIX'] = '.cc'
206 env
['PCHPDBFLAGS'] = SCons
.Util
.CLVar(['${(PDB and "/Yd") or ""}'])
207 env
['PCHCOM'] = '$CXX $CXXFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo${TARGETS[1]} /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS'
208 env
['BUILDERS']['PCH'] = pch_builder
211 env
['ARFLAGS'] = SCons
.Util
.CLVar('/nologo')
212 env
['ARCOM'] = "${TEMPFILE('$AR $ARFLAGS /OUT:$TARGET $SOURCES')}"
213 env
['LIBPREFIX'] = ''
214 env
['LIBSUFFIX'] = '.lib'
216 SCons
.Tool
.mslink
.generate(env
)
218 if not env
.has_key('ENV'):
222 include_path
, lib_path
, exe_path
= get_winddk_paths(env
)
224 # since other tools can set these, we just make sure that the
225 # relevant stuff from WINDDK is in there somewhere.
226 env
.PrependENVPath('INCLUDE', include_path
)
227 env
.PrependENVPath('LIB', lib_path
)
228 env
.PrependENVPath('PATH', exe_path
)
229 except (SCons
.Util
.RegError
, SCons
.Errors
.InternalError
):
234 return env
.Detect('cl')