Merge branch 'gallium-0.1' into gallium-tex-surfaces
[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
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') )
73
74 target_os = 'wxp'
75 target_cpu = 'i386'
76
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)
81
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)
86
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)
91
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']
99
100 def pch_emitter(target, source, env):
101 """Adds the object file target."""
102
103 validate_vars(env)
104
105 pch = None
106 obj = None
107
108 for t in target:
109 if SCons.Util.splitext(str(t))[1] == '.pch':
110 pch = t
111 if SCons.Util.splitext(str(t))[1] == '.obj':
112 obj = t
113
114 if not obj:
115 obj = SCons.Util.splitext(str(pch))[0]+'.obj'
116
117 target = [pch, obj] # pch must be first, and obj second for the PCHCOM to work
118
119 return (target, source)
120
121 def object_emitter(target, source, env, parent_emitter):
122 """Sets up the PCH dependencies for an object file."""
123
124 validate_vars(env)
125
126 parent_emitter(target, source, env)
127
128 if env.has_key('PCH') and env['PCH']:
129 env.Depends(target, env['PCH'])
130
131 return (target, source)
132
133 def static_object_emitter(target, source, env):
134 return object_emitter(target, source, env,
135 SCons.Defaults.StaticObjectEmitter)
136
137 def shared_object_emitter(target, source, env):
138 return object_emitter(target, source, env,
139 SCons.Defaults.SharedObjectEmitter)
140
141 pch_action = SCons.Action.Action('$PCHCOM', '$PCHCOMSTR')
142 pch_builder = SCons.Builder.Builder(action=pch_action, suffix='.pch',
143 emitter=pch_emitter,
144 source_scanner=SCons.Tool.SourceFileScanner)
145 res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR')
146 res_builder = SCons.Builder.Builder(action=res_action,
147 src_suffix='.rc',
148 suffix='.res',
149 src_builder=[],
150 source_scanner=SCons.Tool.SourceFileScanner)
151 SCons.Tool.SourceFileScanner.add_scanner('.rc', SCons.Defaults.CScan)
152
153 def generate(env):
154 """Add Builders and construction variables for MSVC++ to an Environment."""
155 static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
156
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)
162
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)
168
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'
172 env['CC'] = 'cl'
173 env['CCFLAGS'] = SCons.Util.CLVar('/nologo')
174 env['CFLAGS'] = SCons.Util.CLVar('')
175 env['CCCOM'] = '$CC $CFLAGS $CCFLAGS $CCCOMFLAGS'
176 env['SHCC'] = '$CC'
177 env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
178 env['SHCFLAGS'] = SCons.Util.CLVar('$CFLAGS')
179 env['SHCCCOM'] = '$SHCC $SHCFLAGS $SHCCFLAGS $CCCOMFLAGS'
180 env['CXX'] = '$CC'
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
193
194 env['RC'] = 'rc'
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'
202
203 env['CFILESUFFIX'] = '.c'
204 env['CXXFILESUFFIX'] = '.cc'
205
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
209
210 env['AR'] = 'lib'
211 env['ARFLAGS'] = SCons.Util.CLVar('/nologo')
212 env['ARCOM'] = "${TEMPFILE('$AR $ARFLAGS /OUT:$TARGET $SOURCES')}"
213 env['LIBPREFIX'] = ''
214 env['LIBSUFFIX'] = '.lib'
215
216 SCons.Tool.mslink.generate(env)
217
218 if not env.has_key('ENV'):
219 env['ENV'] = {}
220
221 try:
222 include_path, lib_path, exe_path = get_winddk_paths(env)
223
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):
230 pass
231
232
233 def exists(env):
234 return env.Detect('cl')
235
236 # vim:set sw=4 et: