OSDN Git Service

Merge remote branch 'origin/master' into nv50-compiler
[android-x86/external-mesa.git] / scons / msvc_sa.py
1 """msvc_sa
2
3 Tool-specific initialization for Microsoft Visual C/C++.
4
5 Based on SCons.Tool.msvc, without the MSVS detection.
6
7 """
8
9 #
10 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
11 #
12 # Permission is hereby granted, free of charge, to any person obtaining
13 # a copy of this software and associated documentation files (the
14 # "Software"), to deal in the Software without restriction, including
15 # without limitation the rights to use, copy, modify, merge, publish,
16 # distribute, sublicense, and/or sell copies of the Software, and to
17 # permit persons to whom the Software is furnished to do so, subject to
18 # the following conditions:
19 #
20 # The above copyright notice and this permission notice shall be included
21 # in all copies or substantial portions of the Software.
22 #
23 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
24 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
25 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 #
31
32 import os.path
33 import re
34 import string
35
36 import SCons.Action
37 import SCons.Builder
38 import SCons.Errors
39 import SCons.Platform.win32
40 import SCons.Tool
41 import SCons.Util
42 import SCons.Warnings
43 import SCons.Scanner.RC
44
45 CSuffixes = ['.c', '.C']
46 CXXSuffixes = ['.cc', '.cpp', '.cxx', '.c++', '.C++']
47
48 def validate_vars(env):
49     """Validate the PCH and PCHSTOP construction variables."""
50     if env.has_key('PCH') and env['PCH']:
51         if not env.has_key('PCHSTOP'):
52             raise SCons.Errors.UserError, "The PCHSTOP construction must be defined if PCH is defined."
53         if not SCons.Util.is_String(env['PCHSTOP']):
54             raise SCons.Errors.UserError, "The PCHSTOP construction variable must be a string: %r"%env['PCHSTOP']
55
56 def pch_emitter(target, source, env):
57     """Adds the object file target."""
58
59     validate_vars(env)
60
61     pch = None
62     obj = None
63
64     for t in target:
65         if SCons.Util.splitext(str(t))[1] == '.pch':
66             pch = t
67         if SCons.Util.splitext(str(t))[1] == '.obj':
68             obj = t
69
70     if not obj:
71         obj = SCons.Util.splitext(str(pch))[0]+'.obj'
72
73     target = [pch, obj] # pch must be first, and obj second for the PCHCOM to work
74
75     return (target, source)
76
77 def object_emitter(target, source, env, parent_emitter):
78     """Sets up the PCH dependencies for an object file."""
79
80     validate_vars(env)
81
82     parent_emitter(target, source, env)
83
84     if env.has_key('PCH') and env['PCH']:
85         env.Depends(target, env['PCH'])
86
87     return (target, source)
88
89 def static_object_emitter(target, source, env):
90     return object_emitter(target, source, env,
91                           SCons.Defaults.StaticObjectEmitter)
92
93 def shared_object_emitter(target, source, env):
94     return object_emitter(target, source, env,
95                           SCons.Defaults.SharedObjectEmitter)
96
97 pch_action = SCons.Action.Action('$PCHCOM', '$PCHCOMSTR')
98 pch_builder = SCons.Builder.Builder(action=pch_action, suffix='.pch',
99                                     emitter=pch_emitter,
100                                     source_scanner=SCons.Tool.SourceFileScanner)
101
102
103 # Logic to build .rc files into .res files (resource files)
104 res_scanner = SCons.Scanner.RC.RCScan()
105 res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR')
106 res_builder = SCons.Builder.Builder(action=res_action,
107                                     src_suffix='.rc',
108                                     suffix='.res',
109                                     src_builder=[],
110                                     source_scanner=res_scanner)
111
112 def msvc_batch_key(action, env, target, source):
113     """
114     Returns a key to identify unique batches of sources for compilation.
115
116     If batching is enabled (via the $MSVC_BATCH setting), then all
117     target+source pairs that use the same action, defined by the same
118     environment, and have the same target and source directories, will
119     be batched.
120
121     Returning None specifies that the specified target+source should not
122     be batched with other compilations.
123     """
124     b = env.subst('$MSVC_BATCH')
125     if b in (None, '', '0'):
126         # We're not using batching; return no key.
127         return None
128     t = target[0]
129     s = source[0]
130     if os.path.splitext(t.name)[0] != os.path.splitext(s.name)[0]:
131         # The base names are different, so this *must* be compiled
132         # separately; return no key.
133         return None
134     return (id(action), id(env), t.dir, s.dir)
135
136 def msvc_output_flag(target, source, env, for_signature):
137     """
138     Returns the correct /Fo flag for batching.
139
140     If batching is disabled or there's only one source file, then we
141     return an /Fo string that specifies the target explicitly.  Otherwise,
142     we return an /Fo string that just specifies the first target's
143     directory (where the Visual C/C++ compiler will put the .obj files).
144     """
145     b = env.subst('$MSVC_BATCH')
146     if b in (None, '', '0') or len(source) == 1:
147         return '/Fo$TARGET'
148     else:
149         # The Visual C/C++ compiler requires a \ at the end of the /Fo
150         # option to indicate an output directory.  We use os.sep here so
151         # that the test(s) for this can be run on non-Windows systems
152         # without having a hard-coded backslash mess up command-line
153         # argument parsing.
154         return '/Fo${TARGET.dir}' + os.sep
155
156 CAction = SCons.Action.Action("$CCCOM", "$CCCOMSTR",
157                               batch_key=msvc_batch_key,
158                               targets='$CHANGED_TARGETS')
159 ShCAction = SCons.Action.Action("$SHCCCOM", "$SHCCCOMSTR",
160                                 batch_key=msvc_batch_key,
161                                 targets='$CHANGED_TARGETS')
162 CXXAction = SCons.Action.Action("$CXXCOM", "$CXXCOMSTR",
163                                 batch_key=msvc_batch_key,
164                                 targets='$CHANGED_TARGETS')
165 ShCXXAction = SCons.Action.Action("$SHCXXCOM", "$SHCXXCOMSTR",
166                                   batch_key=msvc_batch_key,
167                                   targets='$CHANGED_TARGETS')
168
169 def generate(env):
170     """Add Builders and construction variables for MSVC++ to an Environment."""
171     static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
172
173     # TODO(batch):  shouldn't reach in to cmdgen this way; necessary
174     # for now to bypass the checks in Builder.DictCmdGenerator.__call__()
175     # and allow .cc and .cpp to be compiled in the same command line.
176     static_obj.cmdgen.source_ext_match = False
177     shared_obj.cmdgen.source_ext_match = False
178
179     for suffix in CSuffixes:
180         static_obj.add_action(suffix, CAction)
181         shared_obj.add_action(suffix, ShCAction)
182         static_obj.add_emitter(suffix, static_object_emitter)
183         shared_obj.add_emitter(suffix, shared_object_emitter)
184
185     for suffix in CXXSuffixes:
186         static_obj.add_action(suffix, CXXAction)
187         shared_obj.add_action(suffix, ShCXXAction)
188         static_obj.add_emitter(suffix, static_object_emitter)
189         shared_obj.add_emitter(suffix, shared_object_emitter)
190
191     env['CCPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Z7") or ""}'])
192     env['CCPCHFLAGS'] = SCons.Util.CLVar(['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}'])
193     env['_MSVC_OUTPUT_FLAG'] = msvc_output_flag
194     env['_CCCOMCOM']  = '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $CCPCHFLAGS $CCPDBFLAGS'
195     env['CC']         = 'cl'
196     env['CCFLAGS']    = SCons.Util.CLVar('/nologo')
197     env['CFLAGS']     = SCons.Util.CLVar('')
198     env['CCCOM']      = '$CC $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $CFLAGS $CCFLAGS $_CCCOMCOM'
199     env['SHCC']       = '$CC'
200     env['SHCCFLAGS']  = SCons.Util.CLVar('$CCFLAGS')
201     env['SHCFLAGS']   = SCons.Util.CLVar('$CFLAGS')
202     env['SHCCCOM']    = '$SHCC $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $SHCFLAGS $SHCCFLAGS $_CCCOMCOM'
203     env['CXX']        = '$CC'
204     env['CXXFLAGS']   = SCons.Util.CLVar('$( /TP $)')
205     env['CXXCOM']     = '$CXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $CXXFLAGS $CCFLAGS $_CCCOMCOM'
206     env['SHCXX']      = '$CXX'
207     env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS')
208     env['SHCXXCOM']   = '$SHCXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM'
209     env['CPPDEFPREFIX']  = '/D'
210     env['CPPDEFSUFFIX']  = ''
211     env['INCPREFIX']  = '/I'
212     env['INCSUFFIX']  = ''
213 #    env.Append(OBJEMITTER = [static_object_emitter])
214 #    env.Append(SHOBJEMITTER = [shared_object_emitter])
215     env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
216
217     env['RC'] = 'rc'
218     env['RCFLAGS'] = SCons.Util.CLVar('')
219     env['RCSUFFIXES']=['.rc','.rc2']
220     env['RCCOM'] = '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES'
221     env['BUILDERS']['RES'] = res_builder
222     env['OBJPREFIX']      = ''
223     env['OBJSUFFIX']      = '.obj'
224     env['SHOBJPREFIX']    = '$OBJPREFIX'
225     env['SHOBJSUFFIX']    = '$OBJSUFFIX'
226
227     env['CFILESUFFIX'] = '.c'
228     env['CXXFILESUFFIX'] = '.cc'
229
230     env['PCHPDBFLAGS'] = SCons.Util.CLVar(['${(PDB and "/Yd") or ""}'])
231     env['PCHCOM'] = '$CXX /Fo${TARGETS[1]} $CXXFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS'
232     env['BUILDERS']['PCH'] = pch_builder
233
234     if not env.has_key('ENV'):
235         env['ENV'] = {}
236     if not env['ENV'].has_key('SystemRoot'):    # required for dlls in the winsxs folders
237         env['ENV']['SystemRoot'] = SCons.Platform.win32.get_system_root()
238
239 def exists(env):
240     return env.Detect('cl')
241
242 # Local Variables:
243 # tab-width:4
244 # indent-tabs-mode:nil
245 # End:
246 # vim: set expandtab tabstop=4 shiftwidth=4: