|
1 | 1 | from utils import pioenv, sysenv, dotenv
|
2 | 2 |
|
3 |
| -Import('env') # type: ignore |
4 |
| -pio = pioenv.PioEnv(env) # type: ignore |
5 |
| - |
6 | 3 | # This file is invoked by PlatformIO during build.
|
7 | 4 | # See 'extra_scripts' in 'platformio.ini'.
|
8 | 5 |
|
| 6 | +####################################################### |
| 7 | +# DETERMINING THE ENVIRONMENT # |
| 8 | +####################################################### |
| 9 | + |
| 10 | +# Import the PlatformIO env and initialize our PioEnv wrapper. |
| 11 | +Import('env') # type: ignore |
| 12 | +pio = pioenv.PioEnv(env) # type: ignore |
| 13 | + |
9 | 14 | # Get PIO variables.
|
10 |
| -build_flags = pio.get_string_array('BUILD_FLAGS', []) |
11 | 15 | project_dir = pio.get_string('PROJECT_DIR')
|
12 | 16 |
|
13 | 17 | # By default, the build is run in DEVELOP mode.
|
|
25 | 29 | pio_build_type = 'release' if is_release_build else 'debug'
|
26 | 30 | dotenv_type = 'production' if is_release_build else 'development'
|
27 | 31 |
|
| 32 | +# Read the correct .env file. |
28 | 33 | dot = dotenv.DotEnv(project_dir, dotenv_type)
|
29 | 34 |
|
30 |
| -# Defines that will be passed to the compiler. |
31 |
| -cpp_defines: dict[str, str | int | bool] = {} |
| 35 | +####################################################### |
| 36 | +# UPDATING BUILD PARAMETERS # |
| 37 | +####################################################### |
32 | 38 |
|
33 |
| -# Gets the build flags from the PIO ini file, removes the -D prefix, splits on the first '=', and then converts to a dictionary. |
34 |
| -# (Intent: Remove everything from buildflags, then add everything as cppdefines, and readd the non-key-value build flags.) |
35 |
| -leftover_flags = [] |
36 |
| -for flag in build_flags: |
37 |
| - if flag.startswith('-D'): |
38 |
| - flag = flag[2::] |
39 |
| - if '=' in flag: |
40 |
| - (k, v) = flag.split('=', 1) |
41 | 39 |
|
42 |
| - cpp_defines[k] = v |
| 40 | +# Parse PIO build flags. |
| 41 | +# All CPP Defines, i.e. flags starting with "-D", are parsed for key/value and stored in a dictionary (first value). |
| 42 | +# All other build flags are returned in a list (second value) |
| 43 | +def parse_pio_build_flags(raw_flags: list[str]) -> tuple[dict[str, str | int | bool], list[str]]: |
| 44 | + flag_dict = {} |
| 45 | + leftover_flags = [] |
| 46 | + for flag in raw_flags: |
| 47 | + if flag.startswith('-D'): |
| 48 | + flag = flag[2::] |
| 49 | + if '=' in flag: |
| 50 | + (k, v) = flag.split('=', 1) |
| 51 | + flag_dict[k] = v |
| 52 | + else: |
| 53 | + flag_dict[flag] = True |
43 | 54 | else:
|
44 |
| - cpp_defines[flag] = True |
45 |
| - else: |
46 |
| - leftover_flags.append(flag) |
| 55 | + leftover_flags.append(flag) |
| 56 | + return (flag_dict, []) |
47 | 57 |
|
48 |
| -# Gets all the environment variables prefixed with 'OPENSHOCK_'. |
| 58 | + |
| 59 | +# Serialize CPP Defines. |
| 60 | +# Strings are escaped to be a correct CPP macro. |
| 61 | +# Booleans are turned into integers, True => 1 and False => 0. |
| 62 | +# Integers are kept as-is. |
| 63 | +def serialize_cpp_defines(raw_defines: dict[str, str | int | bool]) -> dict[str, str | int]: |
| 64 | + result_defines = {} |
| 65 | + for k, v in raw_defines.items(): |
| 66 | + try: |
| 67 | + v = int(v) |
| 68 | + except ValueError: |
| 69 | + pass |
| 70 | + if isinstance(v, str): |
| 71 | + result_defines[k] = env.StringifyMacro(v) |
| 72 | + else: |
| 73 | + result_defines[k] = v |
| 74 | + return result_defines |
| 75 | + |
| 76 | + |
| 77 | +# Fetch the current build flags and group them into (CPP Defines, Other Flags). |
| 78 | +raw_build_flags = pio.get_string_array('BUILD_FLAGS', []) |
| 79 | +(cpp_defines, remaining_build_flags) = parse_pio_build_flags(raw_build_flags) |
| 80 | + |
| 81 | +# Gets all the environment variables prefixed with 'OPENSHOCK_' and add them as CPP Defines. |
49 | 82 | openshock_vars = dot.get_all_prefixed('OPENSHOCK_')
|
50 | 83 | cpp_defines.update(openshock_vars)
|
51 | 84 |
|
52 | 85 | # Gets the log level from environment variables.
|
| 86 | +# TODO: Delete get_loglevel and use... something more generic. |
53 | 87 | log_level_int = dot.get_loglevel('LOG_LEVEL')
|
54 | 88 | if log_level_int is None:
|
55 | 89 | raise ValueError('LOG_LEVEL must be set in environment variables.')
|
56 | 90 | cpp_defines['CORE_DEBUG_LEVEL'] = log_level_int
|
57 | 91 |
|
58 |
| -# Convert all the string values to macros. |
59 |
| -for k, v in cpp_defines.items(): |
60 |
| - try: |
61 |
| - v = int(v) |
62 |
| - except ValueError: |
63 |
| - pass |
64 |
| - |
65 |
| - if isinstance(v, str): |
66 |
| - cpp_defines[k] = env.StringifyMacro(v) |
67 |
| - else: |
68 |
| - cpp_defines[k] = v |
69 |
| - |
70 | 92 | print('Build type: ' + pio_build_type)
|
71 | 93 | print('Build defines: ' + str(cpp_defines))
|
72 | 94 |
|
73 | 95 | # Set PIO variables.
|
74 | 96 | env['BUILD_TYPE'] = pio_build_type
|
75 |
| -env['BUILD_FLAGS'] = leftover_flags |
76 |
| -env.Append(CPPDEFINES=[(k, v) for k, v in cpp_defines.items()]) |
| 97 | +env['BUILD_FLAGS'] = remaining_build_flags |
| 98 | +env.Append(CPPDEFINES=list(cpp_defines.items())) |
0 commit comments