blob: 845cf90a9a45b62cca713f20112571e8f8baca78 [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é Fonsecaefd33682008-02-25 14:46:53 +090067 #WINDDKdir = "C:\\WINDDK\\3790.1830"
68 WINDDKdir = "C:/WINDDK/3790.1830"
José Fonseca58a3d7d2008-02-23 19:49:08 +090069
70 exe_paths.append( os.path.join(WINDDKdir, 'bin') )
José Fonsecaefd33682008-02-25 14:46:53 +090071 exe_paths.append( os.path.join(WINDDKdir, 'bin/x86') )
72 include_paths.append( os.path.join(WINDDKdir, 'inc/wxp') )
José Fonseca58a3d7d2008-02-23 19:49:08 +090073 lib_paths.append( os.path.join(WINDDKdir, 'lib') )
74
José Fonsecaefd33682008-02-25 14:46:53 +090075 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
José Fonseca58a3d7d2008-02-23 19:49:08 +090088 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
93def 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
101def 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
122def 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
134def static_object_emitter(target, source, env):
135 return object_emitter(target, source, env,
136 SCons.Defaults.StaticObjectEmitter)
137
138def shared_object_emitter(target, source, env):
139 return object_emitter(target, source, env,
140 SCons.Defaults.SharedObjectEmitter)
141
142pch_action = SCons.Action.Action('$PCHCOM', '$PCHCOMSTR')
143pch_builder = SCons.Builder.Builder(action=pch_action, suffix='.pch',
144 emitter=pch_emitter,
145 source_scanner=SCons.Tool.SourceFileScanner)
146res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR')
147res_builder = SCons.Builder.Builder(action=res_action,
148 src_suffix='.rc',
149 suffix='.res',
150 src_builder=[],
151 source_scanner=SCons.Tool.SourceFileScanner)
152SCons.Tool.SourceFileScanner.add_scanner('.rc', SCons.Defaults.CScan)
153
154def 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
José Fonsecae70a4312008-02-24 16:43:07 +0900230 # See also:
José Fonseca2bebeef2008-02-24 17:58:18 +0900231 # - WINDDK's bin/makefile.new i386mk.inc for more info.
José Fonsecae70a4312008-02-24 16:43:07 +0900232 # - 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
José Fonseca2bebeef2008-02-24 17:58:18 +0900250 '/GX-', # Disable C++ Exceptions
José Fonsecae70a4312008-02-24 16:43:07 +0900251 '/Zp8', # 8bytes struct member alignment
252 #'/GS-', # No Buffer Security Check
José Fonseca2bebeef2008-02-24 17:58:18 +0900253 '/GR-', # Disable Run-Time Type Info
José Fonsecae70a4312008-02-24 16:43:07 +0900254 '/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
José Fonseca58a3d7d2008-02-23 19:49:08 +0900272 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
277def exists(env):
278 return env.Detect('cl')
279