Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Side by Side Diff: site_scons/site_init.py

Issue 6329: Dropping in software construction toolkit. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 12 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | site_scons/site_tools/atlmfc_vc80.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python2.4
2 # Copyright 2008, Google Inc.
3 # All rights reserved.
4 #
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met:
8 #
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
11 # * Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following disclaimer
13 # in the documentation and/or other materials provided with the
14 # distribution.
15 # * Neither the name of Google Inc. nor the names of its
16 # contributors may be used to endorse or promote products derived from
17 # this software without specific prior written permission.
18 #
19 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31 """Software construction toolkit site_scons configuration.
32
33 This module sets up SCons for use with this toolkit. This should contain setup
34 which occurs outside of environments. If a method operates within the context
35 of an environment, it should instead go in a tool in site_tools and be invoked
36 for the target environment.
37 """
38
39 import __builtin__
40 import sys
41 import SCons
42
43
44 # List of target groups for printing help; modified by AddTargetGroup(); used
45 # by BuildComponents().
46 __target_groups = {}
47
48
49 def _HostPlatform():
50 """Returns the current host platform.
51
52 That is, the platform we're actually running SCons on. You shouldn't use
53 this inside your SConscript files; instead, include the appropriate
54 target_platform tool for your environments. When you call BuildComponents(),
55 only environments with the current host platform will be built.
56
57 Returns:
58 The host platform name - one of ('WINDOWS', 'LINUX', 'MAC').
59 """
60
61 platform_map = {
62 'win32': 'WINDOWS',
63 'cygwin': 'WINDOWS',
64 'linux': 'LINUX',
65 'linux2': 'LINUX',
66 'darwin': 'MAC',
67 }
68
69 if sys.platform not in platform_map:
70 print ('site_init.py warning: platform "%s" is not in platfom map.' %
71 sys.platform)
72
73 return platform_map.get(sys.platform, sys.platform)
74
75
76 #------------------------------------------------------------------------------
77
78
79 def _CheckBuildModes(build_modes, environments, host_platform):
80 """Checks the build modes for the environments.
81
82 Args:
83 build_modes: List of build mode strings.
84 environments: List of SCons environments.
85 host_platform: Host platform string.
86
87 Raises:
88 ValueError: build groups and/or types invalid.
89 """
90 # Make sure the list of environments for the current host platform have
91 # unique BUILD_TYPE. This ensures they won't overwrite each others' build
92 # output. (It is ok for build types in different host platforms to overlap;
93 # that is, WINDOWS and MAC can both have a 'dbg' build type.)
94 all_build_types = []
95 all_build_groups = {}
96 build_desc = {}
97 for e in environments:
98 if not e.Overlap(e['HOST_PLATFORMS'], [host_platform, '*']):
99 continue
100 if e['BUILD_TYPE'] in all_build_types:
101 raise ValueError('Multiple environments have the same BUILD_TYPE=%s' %
102 e['BUILD_TYPE'])
103 else:
104 all_build_types.append(e['BUILD_TYPE'])
105 build_desc[e['BUILD_TYPE']] = e.get('BUILD_TYPE_DESCRIPTION')
106
107 # Keep track of build groups and the build types which belong to them
108 for g in e['BUILD_GROUPS']:
109 if g not in all_build_groups:
110 all_build_groups[g] = []
111 # Don't allow build types and groups to share names
112 if g in all_build_types:
113 raise ValueError('Build group %s also specified as BUILD_TYPE.' % g)
114 else:
115 all_build_types.append(g)
116 all_build_groups[g].append(e['BUILD_TYPE'])
117
118 # Add help for build types
119 xml_help = SCons.Script.GetOption('xml_help')
120 if xml_help:
121 help_mode_format = ' <build_mode name="%s"><![CDATA[%s]]></build_mode>\n'
122 help_text = '<mode_list>\n'
123 else:
124 help_text = '''
125 Use --mode=type to specify the type of build to perform. The following types
126 may be specified:
127 '''
128 help_mode_format = ' %-16s %s\n'
129
130 for build_type in all_build_types:
131 if build_type not in all_build_groups:
132 help_text += help_mode_format % (
133 build_type, build_desc.get(build_type, ''))
134
135 if xml_help:
136 help_group_format = (' <build_group name="%s"><![CDATA[%s]]>'
137 '</build_group>\n')
138 help_text += '</mode_list>\n<group_list>\n'
139 else:
140 help_group_format = ' %-16s %s\n'
141 help_text += '''
142 The following build groups may also be specified via --mode. Build groups
143 build one or more of the other build types. The available build groups are:
144 '''
145
146 groups_sorted = all_build_groups.keys()
147 groups_sorted.sort()
148 for g in groups_sorted:
149 help_text += help_group_format % (g, ','.join(all_build_groups[g]))
150
151 if xml_help:
152 help_text += '</group_list>\n'
153 else:
154 help_text += '''
155 Multiple modes may be specified, separated by commas: --mode=mode1,mode2. If
156 no mode is specified, the default group will be built. This is equivalent to
157 specifying --mode=default.
158 '''
159 SCons.Script.Help(help_text)
160
161 # Make sure all build modes specified by the user are ones which apply to
162 # the current environment.
163 for mode in build_modes:
164 if mode not in all_build_types and mode not in all_build_groups:
165 print ('Warning: Ignoring build mode "%s", which is not defined on this '
166 'platform.' % mode)
167
168
169 def _AddTargetHelp():
170 """Adds help for the target groups from the global __target_groups."""
171 xml_help = SCons.Script.GetOption('xml_help')
172 help_text = ''
173
174 for alias, description in __target_groups.items():
175 items = map(str, SCons.Script.Alias(alias)[0].sources)
176 # Remove duplicates from multiple environments
177 items = list(set(items))
178
179 if items:
180 colwidth = max(map(len, items)) + 2
181 cols = 77 / colwidth
182 rows = (len(items) + cols - 1) / cols
183 items.sort()
184 if xml_help:
185 help_text += '<target_group name="%s">\n' % alias
186 for i in items:
187 help_text += ' <build_target name="%s"/>\n' % i
188 help_text += '</target_group>\n'
189 else:
190 help_text += '\nThe following %s:' % description
191 for row in range(0, rows):
192 help_text += '\n '
193 for i in range(row, len(items), rows):
194 help_text += '%-*s' % (colwidth, items[i])
195 help_text += '\n %s (do all of the above)\n' % alias
196
197 SCons.Script.Help(help_text)
198
199 #------------------------------------------------------------------------------
200
201
202 def BuildComponents(environments):
203 """Build a collection of components under a collection of environments.
204
205 Only environments with HOST_PLATFORMS containing the platform specified by
206 --host-platform (or the native host platform, if --host-platform was not
207 specified) will be matched.
208
209 Each matching environment is checked against the modes passed to the --mode
210 command line argument (or 'default', if no mode(s) were specified). If any
211 of the modes match the environment's BUILD_TYPE or any of the environment's
212 BUILD_GROUPS, all the BUILD_COMPONENTS and BUILD_SCONSCRIPTS in that
213 environment will be built.
214
215 Args:
216 environments: List of SCons environments.
217 """
218 # Get options
219 xml_help = SCons.Script.GetOption('xml_help')
220 build_modes = SCons.Script.GetOption('build_mode')
221 # TODO(rspangler): Remove support legacy MODE= argument, once everyone has
222 # transitioned to --mode.
223 legacy_mode_option = SCons.Script.ARGUMENTS.get('MODE')
224 if legacy_mode_option:
225 build_modes = legacy_mode_option
226 build_modes = build_modes.split(',')
227
228 host_platform = SCons.Script.GetOption('host_platform')
229 if not host_platform:
230 host_platform = _HostPlatform()
231
232 # Check build modes
233 _CheckBuildModes(build_modes, environments, host_platform)
234
235 if xml_help:
236 SCons.Script.Help('<help_from_sconscripts>\n<![CDATA[\n')
237
238 for e in environments:
239 if not e.Overlap(e['HOST_PLATFORMS'], [host_platform, '*']):
240 continue # Environment requires a host platform which isn't us
241
242 if e.Overlap([e['BUILD_TYPE'], e['BUILD_GROUPS']], build_modes):
243 # Set up for deferred functions and published resources
244 e._InitializeComponentBuilders()
245 e._InitializeDefer()
246 e._InitializePublish()
247
248 # Read SConscript for each component
249 # TODO(rspangler): Remove BUILD_COMPONENTS once all projects have
250 # transitioned to the BUILD_SCONSCRIPTS nomenclature.
251 for c in e.get('BUILD_COMPONENTS', []) + e.get('BUILD_SCONSCRIPTS', []):
252 # Clone the environment so components can't interfere with each other
253 ec = e.Clone()
254
255 if ec.Entry(c).isdir():
256 # The component is a directory, so assume it contains a SConscript
257 # file.
258 c_dir = ec.Dir(c)
259
260 # Use 'build.scons' as the default filename, but if that doesn't
261 # exist, fall back to 'SConscript'.
262 c_script = c_dir.File('build.scons')
263 if not c_script.exists():
264 c_script = c_dir.File('SConscript')
265 else:
266 # The component is a SConscript file.
267 c_script = ec.File(c)
268 c_dir = c_script.dir
269
270 ec.SConscript(c_script,
271 build_dir='$OBJ_ROOT/' + str(c_dir),
272 exports={'env': ec},
273 duplicate=0)
274
275 # Execute deferred functions
276 e._ExecuteDefer()
277
278 if xml_help:
279 SCons.Script.Help(']]>\n</help_from_sconscripts>\n')
280
281 _AddTargetHelp()
282
283 # End final help tag
284 if xml_help:
285 SCons.Script.Help('</help>\n')
286
287
288 #------------------------------------------------------------------------------
289
290
291 def _ToolExists():
292 """Replacement for SCons tool module exists() function, if one isn't present.
293
294 Returns:
295 True. This enables modules which always exist not to need to include a
296 dummy exists() function.
297 """
298 return True
299
300
301 def _ToolModule(self):
302 """Thunk for SCons.Tool.Tool._tool_module to patch in exists() function.
303
304 Returns:
305 The module from the original SCons.Tool.Tool._tool_module call, with an
306 exists() method added if it wasn't present.
307 """
308 module = self._tool_module_orig()
309 if not hasattr(module, 'exists'):
310 module.exists = _ToolExists
311
312 return module
313
314 #------------------------------------------------------------------------------
315
316
317 def AddSiteDir(site_dir):
318 """Adds a site directory, as if passed to the --site-dir option.
319
320 Args:
321 site_dir: Site directory path to add, relative to the location of the
322 SConstruct file.
323
324 This may be called from the SConscript file to add a local site scons
325 directory for a project. This does the following:
326 * Adds site_dir/site_scons to sys.path.
327 * Imports site_dir/site_init.py.
328 * Adds site_dir/site_scons to the SCons tools path.
329 """
330 # Call the same function that SCons does for the --site-dir option.
331 SCons.Script.Main._load_site_scons_dir(
332 SCons.Node.FS.get_default_fs().SConstruct_dir, site_dir)
333
334
335 def AddTargetGroup(target_group, description):
336 """Adds a target group, used for printing help.
337
338 Args:
339 target_group: Name of target group. This should be the name of an alias
340 which points to other aliases for the specific targets.
341 description: Description of the target group.
342 """
343
344 __target_groups[target_group] = description
345
346 #------------------------------------------------------------------------------
347
348
349 _new_options_help = '''
350 Additional options for SCons:
351
352 --mode=MODE Specify build mode (see below).
353 --host-platform=PLATFORM Force SCons to use PLATFORM as the host platform,
354 instead of the actual platform on which SCons is
355 run. Useful for examining the dependency tree
356 which would be created, but not useful for
357 actually running the build because it'll attempt
358 to use the wrong tools for your actual platform.
359 --site-path=DIRLIST Comma-separated list of additional site
360 directory paths; each is processed as if passed
361 to --site-dir.
362 --xml-help Print help in XML format.
363 '''
364
365 def SiteInitMain():
366 """Main code executed in site_init."""
367
368 # Let people use new global methods directly.
369 __builtin__.AddSiteDir = AddSiteDir
370 __builtin__.BuildComponents = BuildComponents
371 __builtin__.AddTargetGroup = AddTargetGroup
372
373 # Set list of default tools for component_setup
374 __builtin__.component_setup_tools = [
375 'command_output',
376 'component_bits',
377 'component_builders',
378 'concat_source',
379 'defer',
380 'environment_tools',
381 'publish',
382 'replicate',
383 ]
384
385 # Patch Tool._tool_module method to fill in an exists() method for the
386 # module if it isn't present.
387 # TODO(sgk): This functionality should be patched into SCons itself by
388 # changing Tool.__init__().
389 SCons.Tool.Tool._tool_module_orig = SCons.Tool.Tool._tool_module
390 SCons.Tool.Tool._tool_module = _ToolModule
391
392 # Add our options
393 SCons.Script.AddOption(
394 '--mode', '--build-mode',
395 dest='build_mode',
396 nargs=1, type='string',
397 action='store',
398 metavar='MODE',
399 default='default',
400 help='build mode(s)')
401 SCons.Script.AddOption(
402 '--host-platform',
403 dest='host_platform',
404 nargs=1, type='string',
405 action='store',
406 metavar='PLATFORM',
407 help='build mode(s)')
408 SCons.Script.AddOption(
409 '--site-path',
410 dest='site_path',
411 nargs=1, type='string',
412 action='store',
413 metavar='PATH',
414 help='comma-separated list of site directories')
415 SCons.Script.AddOption(
416 '--xml-help',
417 dest='xml_help',
418 action='store_true',
419 help='print help in XML format')
420
421 if SCons.Script.GetOption('xml_help'):
422 SCons.Script.Help('<?xml version="1.0" encoding="UTF-8" ?>\n<help>\n')
423 else:
424 SCons.Script.Help(_new_options_help)
425
426 # Check for site path. This is a list of site directories which each are
427 # processed as if they were passed to --site-dir.
428 site_path = SCons.Script.GetOption('site_path')
429 if site_path:
430 for site_dir in site_path.split(','):
431 AddSiteDir(site_dir)
432
433 # Since our site dir was specified on the SCons command line, SCons will
434 # normally only look at our site dir. Add back checking for project-local
435 # site_scons directories.
436 if not SCons.Script.GetOption('no_site_dir'):
437 SCons.Script.Main._load_site_scons_dir(
438 SCons.Node.FS.get_default_fs().SConstruct_dir, None)
439
440 # Run main code
441 SiteInitMain()
OLDNEW
« no previous file with comments | « no previous file | site_scons/site_tools/atlmfc_vc80.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698