diff options
Diffstat (limited to 'o3d/site_scons/site_tools/component_targets.py')
-rw-r--r-- | o3d/site_scons/site_tools/component_targets.py | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/o3d/site_scons/site_tools/component_targets.py b/o3d/site_scons/site_tools/component_targets.py new file mode 100644 index 0000000..582f6b9 --- /dev/null +++ b/o3d/site_scons/site_tools/component_targets.py @@ -0,0 +1,269 @@ +#!/usr/bin/python2.4 +# Copyright 2009, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"""Software construction toolkit target management for SCons.""" + + +import __builtin__ +import SCons.Script + + +# Dict of target groups (TargetGroup indexed by group name) +__target_groups = {} + +# Dict of targets (Target indexed by target name) +__targets = {} + +# Dict of target modes (TargetMode indexed by mode name) +__target_modes = {} + +#------------------------------------------------------------------------------ + + +class TargetGroup(object): + """Target group, as used by AddTargetGroup() and GetTargetGroups().""" + + def __init__(self, name, description): + """Initializes the target group. + + Args: + name: Name of the target group. + description: Description of group. + """ + self.name = name + self.description = description + + def GetTargetNames(self): + """Returns a list of target name strings for the group.""" + items = map(str, SCons.Script.Alias(self.name)[0].sources) + # Remove duplicates from multiple environments + return list(set(items)) + +#------------------------------------------------------------------------------ + + +class TargetMode(object): + """Target mode, as used by GetTargetModes().""" + + def __init__(self, name, description): + """Initializes the target mode. + + Args: + name: Name of the target mode. + description: Description of mode. + """ + self.name = name + self.description = description + + def GetTargetNames(self): + """Returns a list of target name strings for the group.""" + items = map(str, SCons.Script.Alias(self.name)[0].sources) + # Remove duplicates from multiple environments + return list(set(items)) + +#------------------------------------------------------------------------------ + + +class Target(object): + """Target object.""" + + def __init__(self, name): + """Initializes the target. + + Args: + name: Name of the target. + """ + self.name = name + self.properties = {} # Global properties + self.mode_properties = {} # Dict of modes to mode-specific properties + +#------------------------------------------------------------------------------ + + +def AddTargetGroup(name, description): + """Adds a target group, used for printing help. + + Args: + name: Name of target group. This should be the name of an alias which + points to other aliases for the specific targets. + description: Description of the target group. Should read properly when + appended to 'The following ' - for example, 'programs can be built'. + """ + + # Warn if the target group already exists with a different description + if (name in __target_groups + and __target_groups[name].description != description): + print ('Warning: Changing description of target group "%s" from "%s" to ' + '"%s"' % (name, __target_groups[name].description, description)) + __target_groups[name].description = description + else: + __target_groups[name] = TargetGroup(name, description) + + +def GetTargetGroups(): + """Gets the dict of target groups. + + Returns: + The dict of target groups, indexed by group name. + + This dict is not fully populated until after BuildEnvironments() has been + called. + """ + return __target_groups + + +def GetTargetModes(): + """Gets the dict of target modes. + + Returns: + The dict of target modes, indexed by mode name. + + This dict is not fully populated until after BuildEnvironments() has been + called. + """ + # TODO: Better to rename this to # GetTargetBuildEnvironments()? That's a + # more description name. + return __target_modes + + +def GetTargets(): + """Gets the dict of targets. + + Returns: + The dict of targets, indexed by target name. + + This dict is not fully populated until after BuildEnvironments() has been + called. + """ + return __targets + + +def SetTargetProperty(self, target_name, all_modes=False, **kwargs): + """Sets one or more properties for a target. + + Args: + self: Environment context. + target_name: Name of the target. + all_modes: If True, property applies to all modes. If false, it applies + only to the current mode (determined by self['BUILD_TYPE']). + kwargs: Keyword args are used to set properties. Properties will be + converted to strings via env.subst(). + + For example: + foo_test = env.Program(...)[0] + env.SetTargetProperty('foo_test', global=True, DESCRIPTION='Foo test') + env.SetTargetProperty('foo_test', EXE=foo_test) + """ + # Get the target + if target_name not in __targets: + __targets[target_name] = Target(target_name) + target = __targets[target_name] + + if all_modes: + add_to_dict = target.properties + else: + mode = self.get('BUILD_TYPE') + if mode not in target.mode_properties: + target.mode_properties[mode] = {} + add_to_dict = target.mode_properties[mode] + + # Add values + for k, v in kwargs.items(): + add_to_dict[k] = self.subst(str(v)) + + +def AddTargetHelp(): + """Adds SCons help for the targets, groups, and modes. + + This is called automatically by BuildEnvironments().""" + help_text = '' + + for group in GetTargetGroups().values(): + items = group.GetTargetNames() + items.sort() + if items: + help_text += '\nThe following %s:' % group.description + colwidth = max(map(len, items)) + 2 + cols = 77 / colwidth + if cols < 1: + cols = 1 # If target names are really long, one per line + rows = (len(items) + cols - 1) / cols + for row in range(0, rows): + help_text += '\n ' + for i in range(row, len(items), rows): + help_text += '%-*s' % (colwidth, items[i]) + help_text += '\n %s (do all of the above)\n' % group.name + + SCons.Script.Help(help_text) + + +def SetTargetDescription(self, target_name, description): + """Convenience function to set a target's global DESCRIPTION property. + + Args: + self: Environment context. + target_name: Name of the target. + description: Description of the target. + """ + self.SetTargetProperty(target_name, all_modes=True, DESCRIPTION=description) + + +def AddTargetMode(env): + """Adds the environment as a target mode. + + Args: + env: Environment context. + + Called via env.Defer() for each build mode. + """ + # Save the build mode and description + mode = env.get('BUILD_TYPE') + __target_modes[mode] = TargetMode(mode, env.get('BUILD_TYPE_DESCRIPTION')) + + +#------------------------------------------------------------------------------ + + +def generate(env): + # NOTE: SCons requires the use of this name, which fails gpylint. + """SCons entry point for this tool.""" + env = env # Silence gpylint + + __builtin__.AddTargetGroup = AddTargetGroup + __builtin__.AddTargetHelp = AddTargetHelp + __builtin__.GetTargetGroups = GetTargetGroups + __builtin__.GetTargetModes = GetTargetModes + __builtin__.GetTargets = GetTargets + + env.AddMethod(SetTargetDescription) + env.AddMethod(SetTargetProperty) + + # Defer per-mode setup + env.Defer(AddTargetMode) |