1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved. 2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)# found in the LICENSE file. 4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)"""Module to hold the Target plugin.""" 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import operator 7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import re 8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)import cr 10effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochimport cr.base.context 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)DEFAULT = cr.Config.From( 13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CR_DEFAULT_TARGET='chrome', 14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)) 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochclass Target(cr.base.context.Context, cr.AutoExport): 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) """Base class for implementing cr targets. 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) A target is something that can be built and run. 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) """ 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # The default base priority 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PRIORITY = 0 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # The default pattern used to try to detect whether a target is a test and 26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # should use the test runner. 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TEST_PATTERN = re.compile('tests?$') 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # The special "test type" that means it's not a test. 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NOT_A_TEST = 'no' 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # The default choice for the type of test when it can't be determined. 31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NORMAL_TEST = 'gtest' 32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # TODO(iancottrell): support the other test types 33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) TEST_TYPES = [NOT_A_TEST, NORMAL_TEST] 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 35effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch def __init__(self, target_name): 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) super(Target, self).__init__(target_name) 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) test_type = None 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if self.TEST_PATTERN.search(target_name): 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) test_type = self.NORMAL_TEST 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) config = cr.Config('DEFAULTS').From( 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CR_TARGET=target_name, 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CR_TARGET_NAME='{CR_TARGET}', 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CR_BUILD_TARGET=cr.Config.Optional( 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) '{CR_TARGET}{CR_TARGET_SUFFIX}', '{CR_TARGET}'), 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CR_RUN_ARGUMENTS='', 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CR_TEST_TYPE=test_type, 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ) 48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch self._data = cr.context.data 49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch self.AddChildren(config, cr.context) 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if hasattr(self, 'CONFIG'): 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) self.AddChild(self.CONFIG) 52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if not self.valid: 53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) self.Set(CR_TARGET_SUFFIX='') 54f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) self.test_type = self.Find('CR_TEST_TYPE') 55f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) self.target_name = self.Find('CR_TARGET_NAME') 56f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) @property 58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) def build_target(self): 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return self.Get('CR_BUILD_TARGET') 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) @property 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) def valid(self): 63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return cr.Builder.IsTarget(self.build_target) 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) @property 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) def is_test(self): 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return self.test_type and self.test_type != self.NOT_A_TEST 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) @classmethod 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) def AddArguments(cls, command, parser, allow_multiple=False): 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) nargs = '?' 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) help_string = 'The target to {0}' 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if allow_multiple: 74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) nargs = '*' 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) help_string = 'The target(s) to {0}' 76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) parser.add_argument( 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) '_targets', metavar='target', 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) help=help_string.format(command.name), 79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) nargs=nargs 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ) 81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) @classmethod 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) def AllTargets(cls): 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) yield cls 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for child in cls.__subclasses__(): 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for t in child.AllTargets(): 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) yield t 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) @classmethod 90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch def CreateTarget(cls, target_name): 91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) """Attempts to build a target by name. 92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 93f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) This searches the set of installed targets in priority order to see if any 94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) of them are willing to handle the supplied name. 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) If a target cannot be found, the program will be aborted. 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Args: 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) target_name: The name of the target we are searching for. 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Returns: 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) The target that matched. 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) """ 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) target_clses = sorted( 102f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) cls.AllTargets(), 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) key=operator.attrgetter('PRIORITY'), 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) reverse=True 105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ) 106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for handler in target_clses: 107effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch target = handler.Build(target_name) 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if target: 109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if not target.valid: 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) print 'Invalid target {0} as {1}'.format( 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) target_name, target.build_target) 112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch guesses = cr.Builder.GuessTargets(target_name) 1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if guesses: 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) print 'Did you mean {0}?'.format( 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ', '.join(guesses[:-1]) + ' or ' + guesses[-1] 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if len(guesses) > 1 else guesses[0]) 117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) exit(1) 118f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return target 119f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) print 'Unknown target {0}'.format(target_name) 120f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) exit(1) 121f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 122f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) @classmethod 123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch def GetTargets(cls): 124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch target_names = getattr(cr.context.args, '_targets', None) 125f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if not target_names: 126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch target_names = [cr.context.Get('CR_DEFAULT_TARGET')] 127f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) elif hasattr(target_names, 'swapcase'): 128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) # deal with the single target case 129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) target_names = [target_names] 130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return [cls.CreateTarget(target_name) 131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for target_name in target_names] 132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) @classmethod 134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch def Build(cls, target_name): 135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return cls(target_name) 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)class NamedTarget(Target): 139f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) """A base class for explicit named targets. 140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 141f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Only matches a target if the name is an exact match. 142f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Up it's priority to come ahead of general purpose rule matches. 143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) """ 144f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) NAME = None 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PRIORITY = Target.PRIORITY + 1 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 147f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) @classmethod 148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch def Build(cls, target_name): 149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) try: 150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if target_name == cls.NAME: 151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return cls(target_name) 152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) except AttributeError: 153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pass 154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return None 155