1# Copyright 2013 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""A module for the init command.""" 6 7import os 8 9import cr 10 11# The set of variables to store in the per output configuration. 12OUT_CONFIG_VARS = [ 13 'CR_VERSION', 14 cr.Platform.SELECTOR, cr.BuildType.SELECTOR, cr.Arch.SELECTOR, 15 'CR_OUT_BASE', 'CR_OUT_FULL', 16] 17 18 19class InitCommand(cr.Command): 20 """The implementation of the init command. 21 22 The init command builds or updates an output directory. 23 It then uses the Prepare and Select commands to get that directory 24 ready to use. 25 """ 26 27 def __init__(self): 28 super(InitCommand, self).__init__() 29 self.requires_build_dir = False 30 self.help = 'Create and configure an output directory' 31 self.description = (""" 32 If the .cr directory is not present, build it and add 33 the specified configuration. 34 If the file already exists, update the configuration with any 35 additional settings. 36 """) 37 self._settings = [] 38 39 def AddArguments(self, subparsers): 40 """Overridden from cr.Command.""" 41 parser = super(InitCommand, self).AddArguments(subparsers) 42 cr.Platform.AddArguments(parser) 43 cr.BuildType.AddArguments(parser) 44 cr.Arch.AddArguments(parser) 45 cr.SelectCommand.AddPrepareArguments(parser) 46 parser.add_argument( 47 '-s', '--set', dest='_settings', metavar='settings', 48 action='append', 49 help='Configuration overrides.' 50 ) 51 return parser 52 53 def EarlyArgProcessing(self): 54 base_settings = getattr(cr.context.args, '_settings', None) 55 if base_settings: 56 self._settings.extend(base_settings) 57 # Do not call super early processing, we do not want to apply 58 # the output arg... 59 out = cr.base.client.GetOutArgument() 60 if out: 61 # Output directory is fully specified 62 # We need to deduce other settings from it's name 63 base, buildtype = os.path.split(out) 64 if not (base and buildtype): 65 print 'Specified output directory must be two levels' 66 exit(1) 67 if not cr.BuildType.FindPlugin(buildtype): 68 print 'Specified build type', buildtype, 'is not valid' 69 print 'Must be one of', ','.join(p.name for p in cr.BuildType.Plugins()) 70 exit(1) 71 if (cr.context.args.CR_BUILDTYPE and 72 cr.context.args.CR_BUILDTYPE != buildtype): 73 print 'If --type and --out are both specified, they must match' 74 print 'Got', cr.context.args.CR_BUILDTYPE, 'and', buildtype 75 exit(1) 76 platform = cr.context.args.CR_PLATFORM 77 if not platform: 78 # Try to guess platform based on output name 79 platforms = [p.name for p in cr.Platform.AllPlugins()] 80 matches = [p for p in platforms if p in base] 81 if len(matches) != 1: 82 print 'Platform is not set, and could not be guessed from', base 83 print 'Should be one of', ','.join(platforms) 84 if len(matches) > 1: 85 print 'Matched all of', ','.join(matches) 86 exit(1) 87 platform = matches[0] 88 cr.context.derived.Set( 89 CR_OUT_FULL=out, 90 CR_OUT_BASE=base, 91 CR_PLATFORM=platform, 92 CR_BUILDTYPE=buildtype, 93 ) 94 if not 'CR_OUT_BASE' in cr.context: 95 cr.context.derived['CR_OUT_BASE'] = 'out_{CR_PLATFORM}' 96 if not 'CR_OUT_FULL' in cr.context: 97 cr.context.derived['CR_OUT_FULL'] = os.path.join( 98 '{CR_OUT_BASE}', '{CR_BUILDTYPE}') 99 100 def Run(self): 101 """Overridden from cr.Command.""" 102 src_path = cr.context.Get('CR_SRC') 103 if not os.path.isdir(src_path): 104 print cr.context.Substitute('Path {CR_SRC} is not a valid client') 105 exit(1) 106 107 # Ensure we have an output directory override ready to fill in 108 # This will only be missing if we are creating a brand new output 109 # directory 110 build_package = cr.auto.build 111 112 # Collect the old version (and float convert) 113 old_version = cr.context.Find('CR_VERSION') 114 try: 115 old_version = float(old_version) 116 except (ValueError, TypeError): 117 old_version = 0.0 118 is_new = not hasattr(build_package, 'config') 119 if is_new: 120 121 class FakeModule(object): 122 OVERRIDES = cr.Config('OVERRIDES') 123 124 def __init__(self): 125 self.__name__ = 'config' 126 127 old_version = None 128 config = FakeModule() 129 setattr(build_package, 'config', config) 130 cr.plugin.ChainModuleConfigs(config) 131 132 # Force override the version 133 build_package.config.OVERRIDES.Set(CR_VERSION=cr.base.client.VERSION) 134 # Add all the variables that we always want to have 135 for name in OUT_CONFIG_VARS: 136 value = cr.context.Find(name) 137 build_package.config.OVERRIDES[name] = value 138 # Apply the settings from the command line 139 for setting in self._settings: 140 name, separator, value = setting.partition('=') 141 name = name.strip() 142 if not separator: 143 value = True 144 else: 145 value = cr.Config.ParseValue(value.strip()) 146 build_package.config.OVERRIDES[name] = value 147 148 # Run all the output directory init hooks 149 for hook in cr.InitHook.Plugins(): 150 hook.Run(old_version, build_package.config) 151 # Redo activations, they might have changed 152 cr.plugin.Activate() 153 154 # Write out the new configuration, and select it as the default 155 cr.base.client.WriteConfig(cr.context.Get('CR_BUILD_DIR'), 156 build_package.config.OVERRIDES.exported) 157 # Prepare the platform in here, using the updated config 158 cr.Platform.Prepare() 159 cr.SelectCommand.Select() 160