blob: c112329cd69f7ddf0a5089068564e4e8007cac96 [file] [log] [blame]
José Fonseca6ac14882008-02-27 16:05:57 +09001"""winddk
José Fonseca58a3d7d2008-02-23 19:49:08 +09002
José Fonseca6ac14882008-02-27 16:05:57 +09003Tool-specific initialization for Microsoft Windows DDK.
4
5Based on engine.SCons.Tool.msvc.
José Fonseca58a3d7d2008-02-23 19:49:08 +09006
7There normally shouldn't be any need to import this module directly.
8It will usually be imported through the generic SCons.Tool.Tool()
9selection method.
10
11"""
12
13#
José Fonseca6ac14882008-02-27 16:05:57 +090014# Copyright (c) 2001-2007 The SCons Foundation
15# Copyright (c) 2008 Tungsten Graphics, Inc.
José Fonseca58a3d7d2008-02-23 19:49:08 +090016#
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
José Fonseca58a3d7d2008-02-23 19:49:08 +090037import os.path
38import re
39import string
40
41import SCons.Action
42import SCons.Builder
43import SCons.Errors
44import SCons.Platform.win32
45import SCons.Tool
46import SCons.Tool.mslib
47import SCons.Tool.mslink
48import SCons.Util
49import SCons.Warnings
50
51CSuffixes = ['.c', '.C']
52CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++']
53
54def 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:
José Fonseca5d1fc692008-03-09 20:14:31 +000067 WINDDKdir = "C:\\WINDDK\\3790.1830"
José Fonseca58a3d7d2008-02-23 19:49:08 +090068
69 exe_paths.append( os.path.join(WINDDKdir, 'bin') )
José Fonseca5d1fc692008-03-09 20:14:31 +000070 exe_paths.append( os.path.join(WINDDKdir, 'bin', 'x86') )
71 include_paths.append( os.path.join(WINDDKdir, 'inc', 'wxp') )
José Fonseca58a3d7d2008-02-23 19:49:08 +090072 lib_paths.append( os.path.join(WINDDKdir, 'lib') )
73
José Fonsecaefd33682008-02-25 14:46:53 +090074 target_os = 'wxp'
75 target_cpu = 'i386'
76
77 env['SDK_INC_PATH'] = os.path.join(WINDDKdir, 'inc', target_os)
José Fonseca5d1fc692008-03-09 20:14:31 +000078 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)
José Fonsecaefd33682008-02-25 14:46:53 +090081
82 env['SDK_LIB_PATH'] = os.path.join(WINDDKdir, 'lib', target_os, target_cpu)
José Fonseca5d1fc692008-03-09 20:14:31 +000083 env['CRT_LIB_PATH'] = os.path.join(WINDDKdir, 'lib', 'crt', target_cpu)
José Fonsecaefd33682008-02-25 14:46:53 +090084 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)
86
José Fonseca58a3d7d2008-02-23 19:49:08 +090087 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)
91
José Fonseca4f17bd22008-03-12 13:34:30 +000092def set_winddk_flags(env):
93 """Mimic WINDDK's builtin flags.
94
95 See also:
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/
99 """
100
101 cppdefines = [
102 ('_X86_', '1'),
103 ('i386', '1'),
104 'STD_CALL',
105 ('CONDITION_HANDLING', '1'),
106 ('NT_INST', '0'),
107 ('WIN32', '100'),
108 ('_NT1X_', '100'),
109 ('WINNT', '1'),
110 ('_WIN32_WINNT', '0x0501'), # minimum required OS version
111 ('WINVER', '0x0501'),
112 ('_WIN32_IE', '0x0603'),
113 ('WIN32_LEAN_AND_MEAN', '1'),
114 ('DEVL', '1'),
115 ('__BUILDMACHINE__', 'WinDDK'),
116 ('FPO', '0'),
117 ]
118 if env.get('DEBUG', False):
119 cppdefines += [
120 ('DBG', 1),
121 ]
122 env.Append(CPPDEFINES = cppdefines)
123
124 # See also:
125 # - http://msdn2.microsoft.com/en-us/library/y0zzbyt4.aspx
126 # - cl /?
127 cflags = [
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
141 #'/Gi-', # ???
142 '/QIfdiv-', # disable Pentium FDIV fix
143 #'/hotpatch', # ???
144 #'/Z7', #enable old-style debug info
145 ]
146 if env.get('debug', False):
147 cflags += [
148 '/Od', # disable optimizations
149 '/Oi', # enable intrinsic functions
150 '/Oy-', # disable frame pointer omission
151 ]
152 else:
153 cflags += [
154 '/Ox', # maximum optimizations
155 '/Oi', # enable intrinsic functions
156 '/Os', # favor code space
157 ]
158 env.Append(CFLAGS = cflags)
159 env.Append(CXXFLAGS = cflags)
160
161 # See also:
162 # - http://msdn2.microsoft.com/en-us/library/y0zzbyt4.aspx
163 env.Append(LINKFLAGS = [
164 '/merge:_PAGE=PAGE',
165 '/merge:_TEXT=.text',
166 '/section:INIT,d',
167 '/opt:ref',
168 '/opt:icf',
169 '/ignore:4198,4010,4037,4039,4065,4070,4078,4087,4089,4221',
170 '/incremental:no',
171 '/fullbuild',
172 '/release',
173 '/nodefaultlib',
174 '/wx',
175 '/debug',
176 '/debugtype:cv',
177 '/version:5.1',
178 '/osversion:5.1',
179 '/functionpadmin:5',
180 '/safeseh',
181 '/pdbcompress',
182 '/stack:0x40000,0x1000',
183 '/driver',
184 '/align:0x80',
185 '/subsystem:native,5.01',
186 '/base:0x10000',
187
188 '/entry:DrvEnableDriver',
189 ])
190
José Fonseca58a3d7d2008-02-23 19:49:08 +0900191def 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']
198
199def pch_emitter(target, source, env):
200 """Adds the object file target."""
201
202 validate_vars(env)
203
204 pch = None
205 obj = None
206
207 for t in target:
208 if SCons.Util.splitext(str(t))[1] == '.pch':
209 pch = t
210 if SCons.Util.splitext(str(t))[1] == '.obj':
211 obj = t
212
213 if not obj:
214 obj = SCons.Util.splitext(str(pch))[0]+'.obj'
215
216 target = [pch, obj] # pch must be first, and obj second for the PCHCOM to work
217
218 return (target, source)
219
220def object_emitter(target, source, env, parent_emitter):
221 """Sets up the PCH dependencies for an object file."""
222
223 validate_vars(env)
224
225 parent_emitter(target, source, env)
226
227 if env.has_key('PCH') and env['PCH']:
228 env.Depends(target, env['PCH'])
229
230 return (target, source)
231
232def static_object_emitter(target, source, env):
233 return object_emitter(target, source, env,
234 SCons.Defaults.StaticObjectEmitter)
235
236def shared_object_emitter(target, source, env):
237 return object_emitter(target, source, env,
238 SCons.Defaults.SharedObjectEmitter)
239
240pch_action = SCons.Action.Action('$PCHCOM', '$PCHCOMSTR')
241pch_builder = SCons.Builder.Builder(action=pch_action, suffix='.pch',
242 emitter=pch_emitter,
243 source_scanner=SCons.Tool.SourceFileScanner)
244res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR')
245res_builder = SCons.Builder.Builder(action=res_action,
246 src_suffix='.rc',
247 suffix='.res',
248 src_builder=[],
249 source_scanner=SCons.Tool.SourceFileScanner)
250SCons.Tool.SourceFileScanner.add_scanner('.rc', SCons.Defaults.CScan)
251
252def generate(env):
253 """Add Builders and construction variables for MSVC++ to an Environment."""
254 static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
255
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)
261
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)
267
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'
271 env['CC'] = 'cl'
272 env['CCFLAGS'] = SCons.Util.CLVar('/nologo')
273 env['CFLAGS'] = SCons.Util.CLVar('')
274 env['CCCOM'] = '$CC $CFLAGS $CCFLAGS $CCCOMFLAGS'
275 env['SHCC'] = '$CC'
276 env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
277 env['SHCFLAGS'] = SCons.Util.CLVar('$CFLAGS')
278 env['SHCCCOM'] = '$SHCC $SHCFLAGS $SHCCFLAGS $CCCOMFLAGS'
279 env['CXX'] = '$CC'
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
292
293 env['RC'] = 'rc'
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'
301
José Fonseca58a3d7d2008-02-23 19:49:08 +0900302 env['CFILESUFFIX'] = '.c'
303 env['CXXFILESUFFIX'] = '.cc'
304
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
308
309 env['AR'] = 'lib'
310 env['ARFLAGS'] = SCons.Util.CLVar('/nologo')
311 env['ARCOM'] = "${TEMPFILE('$AR $ARFLAGS /OUT:$TARGET $SOURCES')}"
312 env['LIBPREFIX'] = ''
313 env['LIBSUFFIX'] = '.lib'
314
315 SCons.Tool.mslink.generate(env)
316
José Fonseca4f17bd22008-03-12 13:34:30 +0000317 set_winddk_flags(env)
José Fonsecae70a4312008-02-24 16:43:07 +0900318
José Fonseca58a3d7d2008-02-23 19:49:08 +0900319 if not env.has_key('ENV'):
320 env['ENV'] = {}
José Fonseca5d1fc692008-03-09 20:14:31 +0000321
322 try:
323 include_path, lib_path, exe_path = get_winddk_paths(env)
324
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):
331 pass
332
José Fonseca58a3d7d2008-02-23 19:49:08 +0900333
334def exists(env):
335 return env.Detect('cl')
336
José Fonseca4f17bd22008-03-12 13:34:30 +0000337# vim:set sw=4 et: