Make ncval-annotate and ncval-stubout executable
[nativeclient.git] / site_scons / site_tools / component_targets.py
blob02896f54ec64a231b65856c0a73afd1cc0c6d5ad
1 #!/usr/bin/python2.4
2 # Copyright 2008, Google Inc.
3 # All rights reserved.
5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
7 # met:
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.
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.
31 """Software construction toolkit target management for SCons."""
34 import __builtin__
35 import SCons.Script
38 # Dict of target groups (TargetGroup indexed by group name)
39 __target_groups = {}
41 # Dict of targets (Target indexed by target name)
42 __targets = {}
44 # Dict of target modes (TargetMode indexed by mode name)
45 __target_modes = {}
47 #------------------------------------------------------------------------------
50 class TargetGroup(object):
51 """Target group, as used by AddTargetGroup() and GetTargetGroups()."""
53 def __init__(self, name, description):
54 """Initializes the target group.
56 Args:
57 name: Name of the target group.
58 description: Description of group.
59 """
60 self.name = name
61 self.description = description
63 def GetTargetNames(self):
64 """Returns a list of target name strings for the group."""
65 items = map(str, SCons.Script.Alias(self.name)[0].sources)
66 # Remove duplicates from multiple environments
67 return list(set(items))
69 #------------------------------------------------------------------------------
72 class TargetMode(object):
73 """Target mode, as used by GetTargetModes()."""
75 def __init__(self, name, description):
76 """Initializes the target mode.
78 Args:
79 name: Name of the target mode.
80 description: Description of mode.
81 """
82 self.name = name
83 self.description = description
85 def GetTargetNames(self):
86 """Returns a list of target name strings for the group."""
87 items = map(str, SCons.Script.Alias(self.name)[0].sources)
88 # Remove duplicates from multiple environments
89 return list(set(items))
91 #------------------------------------------------------------------------------
94 class Target(object):
95 """Target object."""
97 def __init__(self, name):
98 """Initializes the target.
100 Args:
101 name: Name of the target.
103 self.name = name
104 self.properties = {} # Global properties
105 self.mode_properties = {} # Dict of modes to mode-specific properties
107 #------------------------------------------------------------------------------
110 def AddTargetGroup(name, description):
111 """Adds a target group, used for printing help.
113 Args:
114 name: Name of target group. This should be the name of an alias which
115 points to other aliases for the specific targets.
116 description: Description of the target group. Should read properly when
117 appended to 'The following ' - for example, 'programs can be built'.
120 # Warn if the target group already exists with a different description
121 if (name in __target_groups
122 and __target_groups[name].description != description):
123 print ('Warning: Changing description of target group "%s" from "%s" to '
124 '"%s"' % (name, __target_groups[name].description, description))
125 __target_groups[name].description = description
126 else:
127 __target_groups[name] = TargetGroup(name, description)
130 def GetTargetGroups():
131 """Gets the dict of target groups.
133 Returns:
134 The dict of target groups, indexed by group name.
136 This dict is not fully populated until after BuildEnvironments() has been
137 called.
139 return __target_groups
142 def GetTargetModes():
143 """Gets the dict of target modes.
145 Returns:
146 The dict of target modes, indexed by mode name.
148 This dict is not fully populated until after BuildEnvironments() has been
149 called.
151 # TODO: Better to rename this to # GetTargetBuildEnvironments()?
152 # That's a more description name.
153 return __target_modes
156 def GetTargets():
157 """Gets the dict of targets.
159 Returns:
160 The dict of targets, indexed by target name.
162 This dict is not fully populated until after BuildEnvironments() has been
163 called.
165 return __targets
168 def SetTargetProperty(self, target_name, all_modes=False, **kwargs):
169 """Sets one or more properties for a target.
171 Args:
172 self: Environment context.
173 target_name: Name of the target.
174 all_modes: If True, property applies to all modes. If false, it applies
175 only to the current mode (determined by self['BUILD_TYPE']).
176 kwargs: Keyword args are used to set properties. Properties will be
177 converted to strings via env.subst().
179 For example:
180 foo_test = env.Program(...)[0]
181 env.SetTargetProperty('foo_test', global=True, DESCRIPTION='Foo test')
182 env.SetTargetProperty('foo_test', EXE=foo_test)
184 # Get the target
185 if target_name not in __targets:
186 __targets[target_name] = Target(target_name)
187 target = __targets[target_name]
189 if all_modes:
190 add_to_dict = target.properties
191 else:
192 mode = self.get('BUILD_TYPE')
193 if mode not in target.mode_properties:
194 target.mode_properties[mode] = {}
195 add_to_dict = target.mode_properties[mode]
197 # Add values
198 for k, v in kwargs.items():
199 add_to_dict[k] = self.subst(str(v))
202 def AddTargetHelp():
203 """Adds SCons help for the targets, groups, and modes.
205 This is called automatically by BuildEnvironments()."""
206 help_text = ''
208 for group in GetTargetGroups().values():
209 items = group.GetTargetNames()
210 items.sort()
211 if items:
212 help_text += '\nThe following %s:' % group.description
213 colwidth = max(map(len, items)) + 2
214 cols = 77 / colwidth
215 if cols < 1:
216 cols = 1 # If target names are really long, one per line
217 rows = (len(items) + cols - 1) / cols
218 for row in range(0, rows):
219 help_text += '\n '
220 for i in range(row, len(items), rows):
221 help_text += '%-*s' % (colwidth, items[i])
222 help_text += '\n %s (do all of the above)\n' % group.name
224 SCons.Script.Help(help_text)
227 def SetTargetDescription(self, target_name, description):
228 """Convenience function to set a target's global DESCRIPTION property.
230 Args:
231 self: Environment context.
232 target_name: Name of the target.
233 description: Description of the target.
235 self.SetTargetProperty(target_name, all_modes=True, DESCRIPTION=description)
238 def AddTargetMode(env):
239 """Adds the environment as a target mode.
241 Args:
242 env: Environment context.
244 Called via env.Defer() for each build mode.
246 # Save the build mode and description
247 mode = env.get('BUILD_TYPE')
248 __target_modes[mode] = TargetMode(mode, env.get('BUILD_TYPE_DESCRIPTION'))
251 #------------------------------------------------------------------------------
254 def generate(env):
255 # NOTE: SCons requires the use of this name, which fails gpylint.
256 """SCons entry point for this tool."""
257 env = env # Silence gpylint
259 __builtin__.AddTargetGroup = AddTargetGroup
260 __builtin__.AddTargetHelp = AddTargetHelp
261 __builtin__.GetTargetGroups = GetTargetGroups
262 __builtin__.GetTargetModes = GetTargetModes
263 __builtin__.GetTargets = GetTargets
265 env.AddMethod(SetTargetDescription)
266 env.AddMethod(SetTargetProperty)
268 # Defer per-mode setup
269 env.Defer(AddTargetMode)