blob: 4eb0b3f235f87c2f6ef817426e9006e8a3807413 [file] [log] [blame]
David Burger7fd1dbe2020-03-26 09:26:55 -06001#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright 2020 The Chromium OS Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6"""Transforms config from /config/proto/api proto format to platform JSON."""
7
8import argparse
9import json
10import pprint
C Shapiro90fda252020-04-17 14:34:57 -050011import os
David Burger7fd1dbe2020-03-26 09:26:55 -060012import sys
C Shapiro90fda252020-04-17 14:34:57 -050013import re
C Shapiro5bf23a72020-04-24 11:40:17 -050014import xml.etree.ElementTree as etree
David Burger7fd1dbe2020-03-26 09:26:55 -060015
16from collections import namedtuple
17
Prathmesh Prabhu72f8a002020-04-10 09:57:53 -070018from chromiumos.config.api import device_brand_pb2
David Burger92609a32020-04-23 10:38:50 -060019from chromiumos.config.api import topology_pb2
C Shapiro5bf23a72020-04-24 11:40:17 -050020from chromiumos.config.payload import config_bundle_pb2
Prathmesh Prabhu72f8a002020-04-10 09:57:53 -070021from chromiumos.config.api.software import brand_config_pb2
David Burger7fd1dbe2020-03-26 09:26:55 -060022
23Config = namedtuple('Config',
24 ['program',
25 'hw_design',
26 'odm',
27 'hw_design_config',
28 'device_brand',
C Shapiro2f0bb5d2020-04-14 10:07:47 -050029 'device_signer_config',
David Burger7fd1dbe2020-03-26 09:26:55 -060030 'oem',
31 'sw_config',
32 'brand_config',
33 'build_target'])
34
C Shapiro5bf23a72020-04-24 11:40:17 -050035ConfigFiles = namedtuple('ConfigFiles',
36 ['bluetooth',
37 'arc_hw_features'])
38
David Burger7fd1dbe2020-03-26 09:26:55 -060039
40def ParseArgs(argv):
41 """Parse the available arguments.
42
43 Invalid arguments or -h cause this function to print a message and exit.
44
45 Args:
46 argv: List of string arguments (excluding program name / argv[0])
47
48 Returns:
49 argparse.Namespace object containing the attributes.
50 """
51 parser = argparse.ArgumentParser(
52 description='Converts source proto config into platform JSON config.')
53 parser.add_argument(
54 '-c',
55 '--project_configs',
56 nargs='+',
57 type=str,
58 help='Space delimited list of source protobinary project config files.')
59 parser.add_argument(
60 '-p',
61 '--program_config',
62 type=str,
63 help='Path to the source program-level protobinary file')
64 parser.add_argument(
65 '-o',
66 '--output',
67 type=str,
68 help='Output file that will be generated')
69 return parser.parse_args(argv)
70
71
72def _Set(field, target, target_name):
73 if field:
74 target[target_name] = field
75
76
C Shapiro5bf23a72020-04-24 11:40:17 -050077def _BuildArc(config, config_files):
David Burger7fd1dbe2020-03-26 09:26:55 -060078 if config.build_target.arc:
79 build_properties = {
80 'device': config.build_target.arc.device,
81 'first-api-level': config.build_target.arc.first_api_level,
82 'marketing-name': config.device_brand.brand_name,
83 'metrics-tag': config.hw_design.name.lower(),
Andrew Lambb47b7dc2020-04-07 10:20:32 -060084 'product': config.build_target.id.value,
David Burger7fd1dbe2020-03-26 09:26:55 -060085 }
86 if config.oem:
87 build_properties['oem'] = config.oem.name
C Shapiro5bf23a72020-04-24 11:40:17 -050088 result = {
89 'build-properties': build_properties
90 }
91 feature_id = _ArcHardwareFeatureId(config.hw_design_config)
92 if feature_id in config_files.arc_hw_features:
93 result['hardware-features'] = config_files.arc_hw_features[feature_id]
94 return result
David Burger7fd1dbe2020-03-26 09:26:55 -060095
C Shapiro90fda252020-04-17 14:34:57 -050096def _BuildBluetooth(config, bluetooth_files):
97 bt_flags = config.sw_config.bluetooth_config.flags
98 # Convert to native map (from proto wrapper)
99 bt_flags_map = dict(bt_flags)
100 result = {}
101 if bt_flags_map:
102 result['flags'] = bt_flags_map
103 bt_comp = config.hw_design_config.hardware_features.bluetooth.component
104 if bt_comp.vendor_id:
105 bt_id = _BluetoothId(config.hw_design.name.lower(), bt_comp)
106 if bt_id in bluetooth_files:
107 result['config'] = bluetooth_files[bt_id]
108 return result
109
David Burger7fd1dbe2020-03-26 09:26:55 -0600110
111def _BuildFingerprint(hw_topology):
Andrew Lambc2c55462020-04-06 08:43:34 -0600112 if hw_topology.HasField('fingerprint'):
David Burger7fd1dbe2020-03-26 09:26:55 -0600113 fp = hw_topology.fingerprint.hardware_feature.fingerprint
David Burger92609a32020-04-23 10:38:50 -0600114 result = {}
115 if fp.location != topology_pb2.HardwareFeatures.Fingerprint.NOT_PRESENT:
116 location = fp.Location.DESCRIPTOR.values_by_number[fp.location].name
117 result['sensor-location'] = location.lower().replace('_', '-')
118 if fp.board:
119 result['board'] = fp.board
David Burger7fd1dbe2020-03-26 09:26:55 -0600120 return result
121
122
123def _FwBcsPath(payload):
124 if payload and payload.firmware_image_name:
125 return 'bcs://%s.%d.%d.0.tbz2' % (
126 payload.firmware_image_name,
127 payload.version.major,
128 payload.version.minor)
129
130
131def _FwBuildTarget(payload):
132 if payload:
133 return payload.build_target_name
134
135
136def _BuildFirmware(config):
Andrew Lamb3da156d2020-04-16 16:00:56 -0600137 fw_payload_config = config.sw_config.firmware
138 fw_build_config = config.sw_config.firmware_build_config
139 main_ro = fw_payload_config.main_ro_payload
140 main_rw = fw_payload_config.main_rw_payload
141 ec_ro = fw_payload_config.ec_ro_payload
142 pd_ro = fw_payload_config.pd_ro_payload
David Burger7fd1dbe2020-03-26 09:26:55 -0600143
144 build_targets = {}
Andrew Lamb3da156d2020-04-16 16:00:56 -0600145
Andrew Lambf8954ee2020-04-21 10:24:40 -0600146 _Set(fw_build_config.build_targets.depthcharge, build_targets, 'depthcharge')
147 _Set(fw_build_config.build_targets.coreboot, build_targets, 'coreboot')
148 _Set(fw_build_config.build_targets.ec, build_targets, 'ec')
149 _Set(
150 list(fw_build_config.build_targets.ec_extras), build_targets, 'ec_extras')
151 _Set(fw_build_config.build_targets.libpayload, build_targets, 'libpayload')
David Burger7fd1dbe2020-03-26 09:26:55 -0600152
153 result = {
154 'bcs-overlay': config.build_target.overlay_name,
155 'build-targets': build_targets,
David Burger7fd1dbe2020-03-26 09:26:55 -0600156 }
Andrew Lamb883fa042020-04-06 11:37:22 -0600157
158 _Set(main_ro.firmware_image_name.lower(), result, 'image-name')
159
160 if not any((
161 main_ro.firmware_image_name,
162 main_rw.firmware_image_name,
163 ec_ro.firmware_image_name,
164 pd_ro.firmware_image_name,
165 )):
Andrew Lambb9e660f2020-04-06 11:37:22 -0600166 result['no-firmware'] = True
Andrew Lamb883fa042020-04-06 11:37:22 -0600167
168 _Set(_FwBcsPath(main_ro), result, 'main-ro-image')
169 _Set(_FwBcsPath(main_rw), result, 'main-rw-image')
170 _Set(_FwBcsPath(ec_ro), result, 'ec-ro-image')
171 _Set(_FwBcsPath(pd_ro), result, 'pd-ro-image')
David Burger7fd1dbe2020-03-26 09:26:55 -0600172
Andrew Lambf39fbe82020-04-13 16:14:33 -0600173 _Set(
174 config.hw_design_config.hardware_features.fw_config.value,
175 result,
176 'firmware-config',
177 )
178
David Burger7fd1dbe2020-03-26 09:26:55 -0600179 return result
180
181
182def _BuildFwSigning(config):
C Shapiro2f0bb5d2020-04-14 10:07:47 -0500183 if config.sw_config.firmware and config.device_signer_config:
184 return {
185 'key-id': config.device_signer_config.key_id,
186 'signature-id': config.hw_design.name.lower(),
187 }
188 return {}
David Burger7fd1dbe2020-03-26 09:26:55 -0600189
190
191def _File(source, destination):
192 return {
193 'destination': destination,
194 'source': source
195 }
196
197
198def _BuildAudio(config):
199 alsa_path = '/usr/share/alsa/ucm'
200 cras_path = '/etc/cras'
201 project_name = config.hw_design.name.lower()
Andrew Lamb7d536782020-04-07 10:23:55 -0600202 if not config.sw_config.HasField('audio_config'):
David Burger7fd1dbe2020-03-26 09:26:55 -0600203 return {}
204 audio = config.sw_config.audio_config
205 card = audio.card_name
David Burger599ff7b2020-04-06 16:29:31 -0600206 card_with_suffix = audio.card_name
207 if audio.ucm_suffix:
208 card_with_suffix += '.' + audio.ucm_suffix
David Burger7fd1dbe2020-03-26 09:26:55 -0600209 files = []
210 if audio.ucm_file:
David Burger599ff7b2020-04-06 16:29:31 -0600211 files.append(_File(
212 audio.ucm_file,
213 '%s/%s/HiFi.conf' % (alsa_path, card_with_suffix)))
David Burger7fd1dbe2020-03-26 09:26:55 -0600214 if audio.ucm_master_file:
215 files.append(_File(
David Burger599ff7b2020-04-06 16:29:31 -0600216 audio.ucm_master_file,
217 '%s/%s/%s.conf' % (alsa_path, card_with_suffix, card_with_suffix)))
David Burger7fd1dbe2020-03-26 09:26:55 -0600218 if audio.card_config_file:
219 files.append(_File(
220 audio.card_config_file, '%s/%s/%s' % (cras_path, project_name, card)))
221 if audio.dsp_file:
222 files.append(
David Burger2e254902020-04-02 16:56:01 -0600223 _File(audio.dsp_file, '%s/%s/dsp.ini' % (cras_path, project_name)))
David Burger599ff7b2020-04-06 16:29:31 -0600224
225 result = {
David Burger7fd1dbe2020-03-26 09:26:55 -0600226 'main': {
227 'cras-config-dir': project_name,
228 'files': files,
229 }
230 }
David Burger599ff7b2020-04-06 16:29:31 -0600231 if audio.ucm_suffix:
David Burger03cdcbd2020-04-13 13:54:48 -0600232 result['main']['ucm-suffix'] = audio.ucm_suffix
David Burger599ff7b2020-04-06 16:29:31 -0600233
234 return result
David Burger7fd1dbe2020-03-26 09:26:55 -0600235
236
David Burger8aa8fa32020-04-14 08:30:34 -0600237def _BuildCamera(hw_topology):
238 if hw_topology.HasField('camera'):
239 camera = hw_topology.camera.hardware_feature.camera
240 result = {}
241 if camera.count.value:
242 result['count'] = camera.count.value
243 return result
244
245
Andrew Lamb7806ce92020-04-07 10:22:17 -0600246def _BuildIdentity(hw_scan_config, program, brand_scan_config=None):
David Burger7fd1dbe2020-03-26 09:26:55 -0600247 identity = {}
248 _Set(hw_scan_config.firmware_sku, identity, 'sku-id')
249 _Set(hw_scan_config.smbios_name_match, identity, 'smbios-name-match')
Andrew Lamb7806ce92020-04-07 10:22:17 -0600250 # 'platform-name' is needed to support 'mosys platform name'. Clients should
251 # longer require platform name, but set it here for backwards compatibility.
252 _Set(program.name, identity, 'platform-name')
David Burger7fd1dbe2020-03-26 09:26:55 -0600253 # ARM architecture
254 _Set(hw_scan_config.device_tree_compatible_match, identity,
255 'device-tree-compatible-match')
256
257 if brand_scan_config:
258 _Set(brand_scan_config.whitelabel_tag, identity, 'whitelabel-tag')
259
260 return identity
261
262
263def _Lookup(id_value, id_map):
264 if id_value.value:
265 key = id_value.value
266 if key in id_map:
267 return id_map[id_value.value]
268 error = 'Failed to lookup %s with value: %s' % (
269 id_value.__class__.__name__.replace('Id', ''), key)
270 print(error)
271 print('Check the config contents provided:')
272 pp = pprint.PrettyPrinter(indent=4)
273 pp.pprint(id_map)
274 raise Exception(error)
275
276
C Shapiro5bf23a72020-04-24 11:40:17 -0500277def _TransformBuildConfigs(config, config_files=ConfigFiles({}, {})):
David Burger7fd1dbe2020-03-26 09:26:55 -0600278 partners = dict([(x.id.value, x) for x in config.partners.value])
279 programs = dict([(x.id.value, x) for x in config.programs.value])
David Burger7fd1dbe2020-03-26 09:26:55 -0600280 sw_configs = list(config.software_configs)
281 brand_configs = dict([(x.brand_id.value, x) for x in config.brand_configs])
282
C Shapiroa0b766c2020-03-31 08:35:28 -0500283 if len(config.build_targets) != 1:
284 # Artifact of sharing the config_bundle for analysis and transforms.
285 # Integrated analysis of multiple programs/projects it the only time
286 # having multiple build targets would be valid.
287 raise Exception('Single build_target required for transform')
288
David Burger7fd1dbe2020-03-26 09:26:55 -0600289 results = {}
290 for hw_design in config.designs.value:
291 if config.device_brands.value:
292 device_brands = [x for x in config.device_brands.value
293 if x.design_id.value == hw_design.id.value]
294 else:
295 device_brands = [device_brand_pb2.DeviceBrand()]
296
297 for device_brand in device_brands:
298 # Brand config can be empty since platform JSON config allows it
299 brand_config = brand_config_pb2.BrandConfig()
300 if device_brand.id.value in brand_configs:
301 brand_config = brand_configs[device_brand.id.value]
302
303 for hw_design_config in hw_design.configs:
304 design_id = hw_design_config.id.value
305 sw_config_matches = [x for x in sw_configs
306 if x.design_config_id.value == design_id]
307 if len(sw_config_matches) == 1:
308 sw_config = sw_config_matches[0]
309 elif len(sw_config_matches) > 1:
310 raise Exception('Multiple software configs found for: %s' % design_id)
311 else:
312 raise Exception('Software config is required for: %s' % design_id)
313
C Shapiro2f0bb5d2020-04-14 10:07:47 -0500314 program = _Lookup(hw_design.program_id, programs)
315 signer_configs = dict(
316 [(x.brand_id.value, x) for x in program.device_signer_configs])
317 device_signer_config = None
318 if signer_configs:
319 device_signer_config = _Lookup(device_brand.id, signer_configs)
320
C Shapiro90fda252020-04-17 14:34:57 -0500321 transformed_config = _TransformBuildConfig(
322 Config(
323 program=program,
324 hw_design=hw_design,
325 odm=_Lookup(hw_design.odm_id, partners),
326 hw_design_config=hw_design_config,
327 device_brand=device_brand,
328 device_signer_config=device_signer_config,
329 oem=_Lookup(device_brand.oem_id, partners),
330 sw_config=sw_config,
331 brand_config=brand_config,
332 build_target=config.build_targets[0]),
C Shapiro5bf23a72020-04-24 11:40:17 -0500333 config_files)
David Burger7fd1dbe2020-03-26 09:26:55 -0600334
335 config_json = json.dumps(transformed_config,
336 sort_keys=True,
337 indent=2,
338 separators=(',', ': '))
339
340 if config_json not in results:
341 results[config_json] = transformed_config
342
343 return list(results.values())
344
345
C Shapiro5bf23a72020-04-24 11:40:17 -0500346def _TransformBuildConfig(config, config_files):
David Burger7fd1dbe2020-03-26 09:26:55 -0600347 """Transforms Config instance into target platform JSON schema.
348
349 Args:
350 config: Config namedtuple
C Shapiro5bf23a72020-04-24 11:40:17 -0500351 config_files: Map to look up the generated config files.
David Burger7fd1dbe2020-03-26 09:26:55 -0600352
353 Returns:
354 Unique config payload based on the platform JSON schema.
355 """
356 result = {
357 'identity': _BuildIdentity(
358 config.sw_config.id_scan_config,
Andrew Lamb7806ce92020-04-07 10:22:17 -0600359 config.program,
David Burger7fd1dbe2020-03-26 09:26:55 -0600360 config.brand_config.scan_config),
361 'name': config.hw_design.name.lower(),
362 }
363
C Shapiro5bf23a72020-04-24 11:40:17 -0500364 _Set(_BuildArc(config, config_files), result, 'arc')
David Burger7fd1dbe2020-03-26 09:26:55 -0600365 _Set(_BuildAudio(config), result, 'audio')
C Shapiro5bf23a72020-04-24 11:40:17 -0500366 _Set(_BuildBluetooth(config, config_files.bluetooth), result, 'bluetooth')
David Burger7fd1dbe2020-03-26 09:26:55 -0600367 _Set(config.device_brand.brand_code, result, 'brand-code')
David Burger8aa8fa32020-04-14 08:30:34 -0600368 _Set(_BuildCamera(
369 config.hw_design_config.hardware_topology), result, 'camera')
David Burger7fd1dbe2020-03-26 09:26:55 -0600370 _Set(_BuildFirmware(config), result, 'firmware')
371 _Set(_BuildFwSigning(config), result, 'firmware-signing')
372 _Set(_BuildFingerprint(
373 config.hw_design_config.hardware_topology), result, 'fingerprint')
374 power_prefs = config.sw_config.power_config.preferences
375 power_prefs_map = dict(
376 (x.replace('_', '-'),
377 power_prefs[x]) for x in power_prefs)
378 _Set(power_prefs_map, result, 'power')
379
380 return result
381
382
383def WriteOutput(configs, output=None):
384 """Writes a list of configs to platform JSON format.
385
386 Args:
387 configs: List of config dicts defined in cros_config_schema.yaml
388 output: Target file output (if None, prints to stdout)
389 """
390 json_output = json.dumps(
391 {'chromeos': {
392 'configs': configs,
393 }},
394 sort_keys=True,
395 indent=2,
396 separators=(',', ': '))
397 if output:
398 with open(output, 'w') as output_stream:
399 # Using print function adds proper trailing newline.
400 print(json_output, file=output_stream)
401 else:
402 print(json_output)
403
404
C Shapiro90fda252020-04-17 14:34:57 -0500405def _BluetoothId(project_name, bt_comp):
406 return '_'.join([project_name,
407 bt_comp.vendor_id,
408 bt_comp.product_id,
409 bt_comp.bcd_device])
410
411
C Shapiro5bf23a72020-04-24 11:40:17 -0500412def _Feature(name, present):
413 attrib = {'name': name}
414 if present:
415 return etree.Element('feature', attrib=attrib)
416 else:
417 return etree.Element('unavailable-feature', attrib=attrib)
418
419
420def _AnyPresent(features):
421 return topology_pb2.HardwareFeatures.PRESENT in features;
422
423
424def _ArcHardwareFeatureId(design_config):
425 return design_config.id.value.lower().replace(':', '_')
426
427
428def WriteArcHardwareFeatureFiles(config, output_dir):
429 """Writes ARC hardware_feature.xml files for each config
430
431 Args:
432 config: Source ConfigBundle to process.
433 output_dir: Path to the generated output.
434 Returns:
435 dict that maps the design_config_id onto the correct file.
436 """
437 project_gen_path = re.match(r'.*(generated.*)', output_dir).groups(1)[0]
438 result = {}
439 for hw_design in config.designs.value:
440 for design_config in hw_design.configs:
441 hw_features = design_config.hardware_features
442 multi_camera = hw_features.camera.count == 2
443 touchscreen = _AnyPresent([hw_features.screen.touch_support])
444 acc = hw_features.accelerometer
445 gyro = hw_features.gyroscope
446 compass = hw_features.magnetometer
447 ls = hw_features.light_sensor
448 root = etree.Element('permissions')
449 root.extend([
450 _Feature('android.hardware.camera', multi_camera),
451 _Feature('android.hardware.camera.autofocus', multi_camera),
452 _Feature('android.hardware.sensor.accelerometer',
453 _AnyPresent(
454 [acc.lid_accelerometer, acc.base_accelerometer])),
455 _Feature('android.hardware.sensor.gyroscope',
456 _AnyPresent(
457 [gyro.lid_gyroscope, gyro.base_gyroscope])),
458 _Feature('android.hardware.sensor.compass',
459 _AnyPresent(
460 [compass.lid_magnetometer, compass.base_magnetometer])),
461 _Feature('android.hardware.sensor.light',
462 _AnyPresent(
463 [ls.lid_lightsensor, ls.base_lightsensor])),
464 _Feature('android.hardware.touchscreen', touchscreen),
465 _Feature('android.hardware.touchscreen.multitouch', touchscreen),
466 _Feature(
467 'android.hardware.touchscreen.multitouch.distinct', touchscreen),
468 _Feature(
469 'android.hardware.touchscreen.multitouch.jazzhand', touchscreen),
470 ])
471
472 feature_id = _ArcHardwareFeatureId( design_config)
473
474 file_name = 'hardware_features_%s.xml' % feature_id
475 output = '%s/arc/%s' % (output_dir, file_name)
476 etree.ElementTree(root).write(output,
477 encoding="utf-8",
478 xml_declaration=True,
479 method="xml")
480 result[feature_id] = {
481 'build-path': '%s/arc/%s' % (project_gen_path, file_name),
482 'system-path': '/etc/%s' % file_name,
483 }
484 return result
485
486
C Shapiro90fda252020-04-17 14:34:57 -0500487def WriteBluetoothConfigFiles(config, output_dir):
488 """Writes bluetooth conf files for every unique bluetooth chip.
489
490 Args:
491 config: Source ConfigBundle to process.
492 output_dir: Path to the generated output.
493 Returns:
494 dict that maps the bluetooth component id onto the file config.
495 """
496 project_gen_path = re.match(r'.*(generated.*)', output_dir).groups(1)[0]
497 result = {}
498 for hw_design in config.designs.value:
499 project_name = hw_design.name.lower()
500 for design_config in hw_design.configs:
501 bt_comp = design_config.hardware_features.bluetooth.component
502 if bt_comp.vendor_id:
503 bt_id = _BluetoothId(project_name, bt_comp)
504 result[bt_id] = {
C Shapiro8556b2d2020-04-22 11:04:14 -0500505 'build-path': '%s/bluetooth/%s.conf' % (project_gen_path, bt_id),
C Shapiro90fda252020-04-17 14:34:57 -0500506 'system-path': '/etc/bluetooth/%s/main.conf' % bt_id,
507 }
508 bt_content = '''[General]
509DeviceID = bluetooth:%s:%s:%s''' % (bt_comp.vendor_id,
510 bt_comp.product_id,
511 bt_comp.bcd_device)
512
513 output = '%s/bluetooth/%s.conf' % (output_dir, bt_id)
514 with open(output, 'w') as output_stream:
515 # Using print function adds proper trailing newline.
516 print(bt_content, file=output_stream)
517 return result
518
519
David Burger7fd1dbe2020-03-26 09:26:55 -0600520def _ReadConfig(path):
521 """Reads a binary proto from a file.
522
523 Args:
524 path: Path to the binary proto.
525 """
526 config = config_bundle_pb2.ConfigBundle()
527 with open(path, 'rb') as f:
528 config.ParseFromString(f.read())
529 return config
530
531
532def _MergeConfigs(configs):
533 result = config_bundle_pb2.ConfigBundle()
534 for config in configs:
535 result.MergeFrom(config)
536
537 return result
538
539
540def Main(project_configs,
541 program_config,
542 output):
543 """Transforms source proto config into platform JSON.
544
545 Args:
546 project_configs: List of source project configs to transform.
547 program_config: Program config for the given set of projects.
548 output: Output file that will be generated by the transform.
549 """
C Shapiro90fda252020-04-17 14:34:57 -0500550 configs =_MergeConfigs(
551 [_ReadConfig(program_config)] +
552 [_ReadConfig(config) for config in project_configs])
C Shapiro5bf23a72020-04-24 11:40:17 -0500553 bluetooth_files = {}
554 arc_hw_feature_files = {}
555 output_dir = os.path.dirname(output)
556 if os.path.exists(os.path.join(output_dir, 'bluetooth')):
557 bluetooth_files = WriteBluetoothConfigFiles(configs, output_dir)
558 if os.path.exists(os.path.join(output_dir, 'arc')):
559 arc_hw_feature_files = WriteArcHardwareFeatureFiles(
560 configs, output_dir)
561 config_files = ConfigFiles(
562 bluetooth=bluetooth_files,
563 arc_hw_features=arc_hw_feature_files,
564 )
565 WriteOutput(_TransformBuildConfigs(configs, config_files), output)
David Burger7fd1dbe2020-03-26 09:26:55 -0600566
567
568def main(argv=None):
569 """Main program which parses args and runs
570
571 Args:
572 argv: List of command line arguments, if None uses sys.argv.
573 """
574 if argv is None:
575 argv = sys.argv[1:]
576 opts = ParseArgs(argv)
577 Main(opts.project_configs, opts.program_config, opts.output)
578
579
580if __name__ == '__main__':
581 sys.exit(main(sys.argv[1:]))