af4335dbb010cd99a429b0f7c678ff33fa3baf75
[mesa.git] / winddk.py
1 """engine.SCons.Tool.msvc
2
3 Tool-specific initialization for Microsoft Visual C/C++.
4
5 There normally shouldn't be any need to import this module directly.
6 It will usually be imported through the generic SCons.Tool.Tool()
7 selection method.
8
9 """
10
11 #
12 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 The SCons Foundation
13 #
14 # Permission is hereby granted, free of charge, to any person obtaining
15 # a copy of this software and associated documentation files (the
16 # "Software"), to deal in the Software without restriction, including
17 # without limitation the rights to use, copy, modify, merge, publish,
18 # distribute, sublicense, and/or sell copies of the Software, and to
19 # permit persons to whom the Software is furnished to do so, subject to
20 # the following conditions:
21 #
22 # The above copyright notice and this permission notice shall be included
23 # in all copies or substantial portions of the Software.
24 #
25 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
26 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
27 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
29 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
30 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
31 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 #
33
34 __revision__ = "src/engine/SCons/Tool/msvc.py 2523 2007/12/12 09:37:41 knight"
35
36 import os.path
37 import re
38 import string
39
40 import SCons.Action
41 import SCons.Builder
42 import SCons.Errors
43 import SCons.Platform.win32
44 import SCons.Tool
45 import SCons.Tool.mslib
46 import SCons.Tool.mslink
47 import SCons.Util
48 import SCons.Warnings
49
50 CSuffixes = ['.c', '.C']
51 CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++']
52
53 def get_winddk_paths(env, version=None):
54 """Return a 3-tuple of (INCLUDE, LIB, PATH) as the values
55 of those three environment variables that should be set
56 in order to execute the MSVC tools properly."""
57
58 WINDDKdir = None
59 exe_paths = []
60 lib_paths = []
61 include_paths = []
62
63 if 'BASEDIR' in os.environ:
64 WINDDKdir = os.environ['BASEDIR']
65 else:
66 WINDDKdir = "C:\\WINDDK\\3790.1830"
67
68 exe_paths.append( os.path.join(WINDDKdir, 'bin') )
69 exe_paths.append( os.path.join(WINDDKdir, 'bin\\x86') )
70 include_paths.append( os.path.join(WINDDKdir, 'inc\\wxp') )
71 lib_paths.append( os.path.join(WINDDKdir, 'lib') )
72
73 include_path = string.join( include_paths, os.pathsep )
74 lib_path = string.join(lib_paths, os.pathsep )
75 exe_path = string.join(exe_paths, os.pathsep )
76 return (include_path, lib_path, exe_path)
77
78 def validate_vars(env):
79 """Validate the PCH and PCHSTOP construction variables."""
80 if env.has_key('PCH') and env['PCH']:
81 if not env.has_key('PCHSTOP'):
82 raise SCons.Errors.UserError, "The PCHSTOP construction must be defined if PCH is defined."
83 if not SCons.Util.is_String(env['PCHSTOP']):
84 raise SCons.Errors.UserError, "The PCHSTOP construction variable must be a string: %r"%env['PCHSTOP']
85
86 def pch_emitter(target, source, env):
87 """Adds the object file target."""
88
89 validate_vars(env)
90
91 pch = None
92 obj = None
93
94 for t in target:
95 if SCons.Util.splitext(str(t))[1] == '.pch':
96 pch = t
97 if SCons.Util.splitext(str(t))[1] == '.obj':
98 obj = t
99
100 if not obj:
101 obj = SCons.Util.splitext(str(pch))[0]+'.obj'
102
103 target = [pch, obj] # pch must be first, and obj second for the PCHCOM to work
104
105 return (target, source)
106
107 def object_emitter(target, source, env, parent_emitter):
108 """Sets up the PCH dependencies for an object file."""
109
110 validate_vars(env)
111
112 parent_emitter(target, source, env)
113
114 if env.has_key('PCH') and env['PCH']:
115 env.Depends(target, env['PCH'])
116
117 return (target, source)
118
119 def static_object_emitter(target, source, env):
120 return object_emitter(target, source, env,
121 SCons.Defaults.StaticObjectEmitter)
122
123 def shared_object_emitter(target, source, env):
124 return object_emitter(target, source, env,
125 SCons.Defaults.SharedObjectEmitter)
126
127 pch_action = SCons.Action.Action('$PCHCOM', '$PCHCOMSTR')
128 pch_builder = SCons.Builder.Builder(action=pch_action, suffix='.pch',
129 emitter=pch_emitter,
130 source_scanner=SCons.Tool.SourceFileScanner)
131 res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR')
132 res_builder = SCons.Builder.Builder(action=res_action,
133 src_suffix='.rc',
134 suffix='.res',
135 src_builder=[],
136 source_scanner=SCons.Tool.SourceFileScanner)
137 SCons.Tool.SourceFileScanner.add_scanner('.rc', SCons.Defaults.CScan)
138
139 def generate(env):
140 """Add Builders and construction variables for MSVC++ to an Environment."""
141 static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
142
143 for suffix in CSuffixes:
144 static_obj.add_action(suffix, SCons.Defaults.CAction)
145 shared_obj.add_action(suffix, SCons.Defaults.ShCAction)
146 static_obj.add_emitter(suffix, static_object_emitter)
147 shared_obj.add_emitter(suffix, shared_object_emitter)
148
149 for suffix in CXXSuffixes:
150 static_obj.add_action(suffix, SCons.Defaults.CXXAction)
151 shared_obj.add_action(suffix, SCons.Defaults.ShCXXAction)
152 static_obj.add_emitter(suffix, static_object_emitter)
153 shared_obj.add_emitter(suffix, shared_object_emitter)
154
155 env['CCPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Z7") or ""}'])
156 env['CCPCHFLAGS'] = SCons.Util.CLVar(['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}'])
157 env['CCCOMFLAGS'] = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET $CCPCHFLAGS $CCPDBFLAGS'
158 env['CC'] = 'cl'
159 env['CCFLAGS'] = SCons.Util.CLVar('/nologo')
160 env['CFLAGS'] = SCons.Util.CLVar('')
161 env['CCCOM'] = '$CC $CFLAGS $CCFLAGS $CCCOMFLAGS'
162 env['SHCC'] = '$CC'
163 env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
164 env['SHCFLAGS'] = SCons.Util.CLVar('$CFLAGS')
165 env['SHCCCOM'] = '$SHCC $SHCFLAGS $SHCCFLAGS $CCCOMFLAGS'
166 env['CXX'] = '$CC'
167 env['CXXFLAGS'] = SCons.Util.CLVar('$CCFLAGS $( /TP $)')
168 env['CXXCOM'] = '$CXX $CXXFLAGS $CCCOMFLAGS'
169 env['SHCXX'] = '$CXX'
170 env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
171 env['SHCXXCOM'] = '$SHCXX $SHCXXFLAGS $CCCOMFLAGS'
172 env['CPPDEFPREFIX'] = '/D'
173 env['CPPDEFSUFFIX'] = ''
174 env['INCPREFIX'] = '/I'
175 env['INCSUFFIX'] = ''
176 # env.Append(OBJEMITTER = [static_object_emitter])
177 # env.Append(SHOBJEMITTER = [shared_object_emitter])
178 env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
179
180 env['RC'] = 'rc'
181 env['RCFLAGS'] = SCons.Util.CLVar('')
182 env['RCCOM'] = '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES'
183 env['BUILDERS']['RES'] = res_builder
184 env['OBJPREFIX'] = ''
185 env['OBJSUFFIX'] = '.obj'
186 env['SHOBJPREFIX'] = '$OBJPREFIX'
187 env['SHOBJSUFFIX'] = '$OBJSUFFIX'
188
189 try:
190 include_path, lib_path, exe_path = get_winddk_paths(env)
191
192 # since other tools can set these, we just make sure that the
193 # relevant stuff from MSVS is in there somewhere.
194 env.PrependENVPath('INCLUDE', include_path)
195 env.PrependENVPath('LIB', lib_path)
196 env.PrependENVPath('PATH', exe_path)
197 except (SCons.Util.RegError, SCons.Errors.InternalError):
198 pass
199
200 env['CFILESUFFIX'] = '.c'
201 env['CXXFILESUFFIX'] = '.cc'
202
203 env['PCHPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Yd") or ""}'])
204 env['PCHCOM'] = '$CXX $CXXFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo${TARGETS[1]} /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS'
205 env['BUILDERS']['PCH'] = pch_builder
206
207 env['AR'] = 'lib'
208 env['ARFLAGS'] = SCons.Util.CLVar('/nologo')
209 env['ARCOM'] = "${TEMPFILE('$AR $ARFLAGS /OUT:$TARGET $SOURCES')}"
210 env['LIBPREFIX'] = ''
211 env['LIBSUFFIX'] = '.lib'
212
213 SCons.Tool.mslink.generate(env)
214
215 if not env.has_key('ENV'):
216 env['ENV'] = {}
217 if not env['ENV'].has_key('SystemRoot'): # required for dlls in the winsxs folders
218 env['ENV']['SystemRoot'] = SCons.Platform.win32.get_system_root()
219
220 def exists(env):
221 return env.Detect('cl')
222