diff options
-rw-r--r-- | src/home/pio/products.py | 15 | ||||
-rwxr-xr-x | src/pio_ini.py | 98 |
2 files changed, 96 insertions, 17 deletions
diff --git a/src/home/pio/products.py b/src/home/pio/products.py index 4cb3cf2..7649078 100644 --- a/src/home/pio/products.py +++ b/src/home/pio/products.py @@ -31,13 +31,17 @@ def get_products(): def platformio_ini(product_config: dict, target: str, - node_id: str, + # node_id: str, + build_specific_defines: dict, + build_specific_defines_enums: list[str], platform: str, framework: str = 'arduino', upload_port: str = '/dev/ttyUSB0', monitor_speed: int = 115200, debug=False, debug_network=False) -> str: + node_id = build_specific_defines['CONFIG_NODE_ID'] + # defines defines = { **product_config['common_defines'], @@ -60,6 +64,9 @@ def platformio_ini(product_config: dict, defines['DEBUG_ESP_SSL'] = True defines['DEBUG_ESP_PORT'] = 'Serial' build_type = 'debug' + if build_specific_defines: + for k, v in build_specific_defines.items(): + defines[k] = v defines = OrderedDict(sorted(defines.items(), key=lambda t: t[0])) # libs @@ -93,13 +100,15 @@ def platformio_ini(product_config: dict, if defines: for name, value in defines.items(): buf.write(f' -D{name}') + is_enum = name in build_specific_defines_enums if type(value) is not bool: buf.write('=') if type(value) is str: - buf.write('"\\"') + if not is_enum: + buf.write('"\\"') value = value.replace('"', '\\"') buf.write(f'{value}') - if type(value) is str: + if type(value) is str and not is_enum: buf.write('"\\"') buf.write('\n') buf.write(f' -I../common/include') diff --git a/src/pio_ini.py b/src/pio_ini.py index 2d9c7c6..19dd707 100755 --- a/src/pio_ini.py +++ b/src/pio_ini.py @@ -1,7 +1,9 @@ #!/usr/bin/env python3 import os import yaml +import re +from pprint import pprint from argparse import ArgumentParser, ArgumentError from home.pio import get_products, platformio_ini from home.pio.exceptions import ProductConfigNotFoundError @@ -19,22 +21,74 @@ def get_config(product: str) -> dict: return yaml.safe_load(f) +def bsd_walk(product_config: dict, + f: callable): + try: + for define_name, define_extra_params in product_config['build_specific_defines'].items(): + define_name = re.sub(r'^CONFIG_', '', define_name) + kwargs = {} + if isinstance(define_extra_params, dict): + kwargs = define_extra_params + f(define_name, **kwargs) + except KeyError: + pass + + +# 'bsd' means 'build_specific_defines' +def bsd_parser(product_config: dict, + parser: ArgumentParser): + def f(define_name, **kwargs): + arg_kwargs = {} + define_name = define_name.lower().replace('_', '-') + + if 'type' in kwargs: + if kwargs['type'] in ('str', 'enum'): + arg_kwargs['type'] = str + if kwargs['type'] == 'enum' and 'list_config_key' in kwargs: + if not isinstance(product_config[kwargs['list_config_key']], list): + raise TypeError(f'product_config[{kwargs["list_config_key"]}] enum is not list') + if not product_config[kwargs['list_config_key']]: + raise ValueError(f'product_config[{kwargs["list_config_key"]}] enum cannot be empty') + arg_kwargs['choices'] = product_config[kwargs['list_config_key']] + if isinstance(product_config[kwargs['list_config_key']][0], int): + arg_kwargs['type'] = int + elif kwargs['type'] == 'int': + arg_kwargs['type'] = int + else: + raise TypeError(f'unsupported type {kwargs["type"]} for define {define_name}') + else: + arg_kwargs['action'] = 'store_true' + + parser.add_argument(f'--{define_name}', required=True, **arg_kwargs) + + bsd_walk(product_config, f) + + +def bsd_get(product_config: dict, + arg: object): + defines = {} + enums = [] + def f(define_name, **kwargs): + attr_name = define_name.lower() + attr_value = getattr(arg, attr_name) + if 'type' in kwargs: + if kwargs['type'] == 'enum': + enums.append(f'CONFIG_{define_name}') + defines[f'CONFIG_{define_name}'] = f'HOMEKIT_{attr_value.upper()}' + return + defines[f'CONFIG_{define_name}'] = str(attr_value) + bsd_walk(product_config, f) + return defines, enums + + if __name__ == '__main__': products = get_products() - parser = ArgumentParser() - parser.add_argument('--product', type=str, choices=products, - help='PIO product name') - parser.add_argument('--target', type=str, required=True, - help='PIO build target') - parser.add_argument('--node-id', type=str) - parser.add_argument('--platform', default='espressif8266', type=str) - parser.add_argument('--framework', default='arduino', type=str) - parser.add_argument('--upload-port', default='/dev/ttyUSB0', type=str) - parser.add_argument('--monitor-speed', default=115200) - parser.add_argument('--debug', action='store_true') - parser.add_argument('--debug-network', action='store_true') - arg = parser.parse_args() + # first, get the product + product_parser = ArgumentParser(add_help=False) + product_parser.add_argument('--product', type=str, choices=products, required=True, + help='PIO product name') + arg, _ = product_parser.parse_known_args() if not arg.product: product = os.path.basename(os.path.realpath(os.getcwd())) if product not in products: @@ -43,12 +97,28 @@ if __name__ == '__main__': product = arg.product product_config = get_config(product) + + # then everythingm else + parser = ArgumentParser(parents=[product_parser]) + parser.add_argument('--target', type=str, required=True, choices=product_config['targets'], + help='PIO build target') + parser.add_argument('--platform', default='espressif8266', type=str) + parser.add_argument('--framework', default='arduino', type=str) + parser.add_argument('--upload-port', default='/dev/ttyUSB0', type=str) + parser.add_argument('--monitor-speed', default=115200) + parser.add_argument('--debug', action='store_true') + parser.add_argument('--debug-network', action='store_true') + bsd_parser(product_config, parser) + arg = parser.parse_args() + if arg.target not in product_config['targets']: raise ArgumentError(None, f'target {arg.target} not found for product {product}') + bsd, bsd_enums = bsd_get(product_config, arg) ini = platformio_ini(product_config=product_config, target=arg.target, - node_id=arg.node_id, + build_specific_defines=bsd, + build_specific_defines_enums=bsd_enums, platform=arg.platform, framework=arg.framework, upload_port=arg.upload_port, |