3 Tool-specific initialization for Microsoft Visual C/C++.
5 Based on SCons.Tool.msvc, without the MSVS detection.
10 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
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:
20 # The above copyright notice and this permission notice shall be included
21 # in all copies or substantial portions of the Software.
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.
39 import SCons
.Platform
.win32
43 import SCons
.Scanner
.RC
45 CSuffixes
= ['.c', '.C']
46 CXXSuffixes
= ['.cc', '.cpp', '.cxx', '.c++', '.C++']
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']
56 def pch_emitter(target
, source
, env
):
57 """Adds the object file target."""
65 if SCons
.Util
.splitext(str(t
))[1] == '.pch':
67 if SCons
.Util
.splitext(str(t
))[1] == '.obj':
71 obj
= SCons
.Util
.splitext(str(pch
))[0]+'.obj'
73 target
= [pch
, obj
] # pch must be first, and obj second for the PCHCOM to work
75 return (target
, source
)
77 def object_emitter(target
, source
, env
, parent_emitter
):
78 """Sets up the PCH dependencies for an object file."""
82 parent_emitter(target
, source
, env
)
84 if env
.has_key('PCH') and env
['PCH']:
85 env
.Depends(target
, env
['PCH'])
87 return (target
, source
)
89 def static_object_emitter(target
, source
, env
):
90 return object_emitter(target
, source
, env
,
91 SCons
.Defaults
.StaticObjectEmitter
)
93 def shared_object_emitter(target
, source
, env
):
94 return object_emitter(target
, source
, env
,
95 SCons
.Defaults
.SharedObjectEmitter
)
97 pch_action
= SCons
.Action
.Action('$PCHCOM', '$PCHCOMSTR')
98 pch_builder
= SCons
.Builder
.Builder(action
=pch_action
, suffix
='.pch',
100 source_scanner
=SCons
.Tool
.SourceFileScanner
)
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
,
110 source_scanner
=res_scanner
)
112 def msvc_batch_key(action
, env
, target
, source
):
114 Returns a key to identify unique batches of sources for compilation.
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
121 Returning None specifies that the specified target+source should not
122 be batched with other compilations.
124 b
= env
.subst('$MSVC_BATCH')
125 if b
in (None, '', '0'):
126 # We're not using batching; return no key.
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.
134 return (id(action
), id(env
), t
.dir, s
.dir)
136 def msvc_output_flag(target
, source
, env
, for_signature
):
138 Returns the correct /Fo flag for batching.
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).
145 b
= env
.subst('$MSVC_BATCH')
146 if b
in (None, '', '0') or len(source
) == 1:
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
154 return '/Fo${TARGET.dir}' + os
.sep
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')
170 """Add Builders and construction variables for MSVC++ to an Environment."""
171 static_obj
, shared_obj
= SCons
.Tool
.createObjBuilders(env
)
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
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
)
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
)
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'
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'
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'
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
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'
227 env
['CFILESUFFIX'] = '.c'
228 env
['CXXFILESUFFIX'] = '.cc'
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
234 if not env
.has_key('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()
240 return env
.Detect('cl')
244 # indent-tabs-mode:nil
246 # vim: set expandtab tabstop=4 shiftwidth=4: