|
| 1 | +--- |
| 2 | +layout: default |
| 3 | +title: yotta Configuration System Reference |
| 4 | +section: reference/config |
| 5 | +--- |
| 6 | + |
| 7 | +# Configuration System Reference |
| 8 | + |
| 9 | +**NOTE: The configuration system is currently experimental. Some of the |
| 10 | +behaviour described below may change in backwards-icompatible ways with minor |
| 11 | +updates to yotta.** |
| 12 | + |
| 13 | +yotta provides a flexible configuration system that can be used to control how |
| 14 | +modules are built based on information provided by [target |
| 15 | +descriptions](/tutorial/targets.html), optionally extended by a `config.json` |
| 16 | +file in the application. |
| 17 | + |
| 18 | +This configuration information can be used to control a module's dependencies, |
| 19 | +and is also made available to code. |
| 20 | + |
| 21 | +<a name="defining"></a> |
| 22 | +## Defining Configuration Data |
| 23 | +Configuration data is defined in two places: [target descriptions](/tutorial/targets.html), and |
| 24 | +[executable applications](/tutorial/tutorial.html#Creating%20an%20Executable). |
| 25 | + |
| 26 | + |
| 27 | +### Target Config Data |
| 28 | +The config data defined by targets can be used to make software modules compile |
| 29 | +across a wide range of different target hardware. For example, it might |
| 30 | +describe things like the frequency of a |
| 31 | +[UART](https://en.wikipedia.org/wiki/Universal_asynchronous_receiver/transmitter) |
| 32 | +serial bus that the target hardware might have for communication. |
| 33 | + |
| 34 | +Software that uses this hardware can then run on different targets, choosing |
| 35 | +the correct frequency to use for the UART communication by reading it from the |
| 36 | +configuration data. |
| 37 | + |
| 38 | +#### Config Data in target.json |
| 39 | +To define config data in a target's target.json file, use the `"config":` |
| 40 | +property, for example: |
| 41 | + |
| 42 | +```json |
| 43 | +{ |
| 44 | + "name":"mytarget", |
| 45 | + "version":"1.2.3", |
| 46 | + "license":"Apache-2", |
| 47 | + "config":{ |
| 48 | + "devices":{ |
| 49 | + "foobar":"value", |
| 50 | + "volume":11 |
| 51 | + } |
| 52 | + } |
| 53 | +} |
| 54 | +``` |
| 55 | + |
| 56 | +#### Overriding Config Data in Derived Targets |
| 57 | +If a target [inherits](/tutorial/targets.html#inheriting) from a more generic |
| 58 | +target, then the config data in the more-derived target overrides data |
| 59 | +inherited from the base target. |
| 60 | + |
| 61 | +For example, given a base target with config data: |
| 62 | + |
| 63 | +```json |
| 64 | +{ |
| 65 | + "a":{ |
| 66 | + "foo": true, |
| 67 | + "bar": 123 |
| 68 | + } |
| 69 | +} |
| 70 | +``` |
| 71 | + |
| 72 | +And a derived target with config data: |
| 73 | + |
| 74 | +```json |
| 75 | +{ |
| 76 | + "a":{ |
| 77 | + "bar": 456 |
| 78 | + }, |
| 79 | + "b":{ |
| 80 | + "baz": "<whatever>" |
| 81 | + } |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +The merged config data (which you can display with the [`yotta |
| 86 | +config`](/reference/commands.html#yotta-config) subcommand), would be: |
| 87 | + |
| 88 | +```json |
| 89 | +{ |
| 90 | + "a":{ |
| 91 | + "foo": true, |
| 92 | + "bar": 456 |
| 93 | + }, |
| 94 | + "b":{ |
| 95 | + "baz": "<whatever>" |
| 96 | + } |
| 97 | +} |
| 98 | +``` |
| 99 | + |
| 100 | +### Application Config Data |
| 101 | +An executable application may define additional config data to that provided by |
| 102 | +the selected target. To do this, the application should include a file called |
| 103 | +`config.json` alongside its `module.json` file. |
| 104 | + |
| 105 | +The application's configuration data takes highest precedence, so can be used |
| 106 | +to override any values defined by the target data. This is useful for defining |
| 107 | +application-specific configuration, and when developing an application for |
| 108 | +one-off target hardware which is derived from a supported platform (it can |
| 109 | +eliminate the need to define your own target description just for one |
| 110 | +application). |
| 111 | + |
| 112 | +If you find yourself copying & pasting `config.json` data between many |
| 113 | +applications, consider if deriving and publishing [your own |
| 114 | +target](/tutorial/targets.html) would be preferable. |
| 115 | + |
| 116 | + |
| 117 | +### Config Data Syntax |
| 118 | +The yotta config system accepts almost any JSON data, apart from Array objects. |
| 119 | +Array objects are not supported due to the ambiguity of merging inherited array |
| 120 | +objects. |
| 121 | + |
| 122 | + |
| 123 | +<a name="using"></a> |
| 124 | +## Using Configuration Data |
| 125 | +Modules can use the configuration data that has been defined to change their |
| 126 | +behaviour. In general it is best to minimise the amount of configuration that |
| 127 | +your module requires to the absolute minimum possible. This makes it easier |
| 128 | +for people to re-use your module in different applications, and to use it on |
| 129 | +different target hardware, without having to define a lot of configuration. |
| 130 | + |
| 131 | +By convention, modules should only read configuration data from their own |
| 132 | +namespace in the config data, for example a module called `simplelog` might |
| 133 | +read a logging level set in the `simplelog` section of the config data: |
| 134 | + |
| 135 | +```json |
| 136 | +{ |
| 137 | + "mbed":{ |
| 138 | + ... |
| 139 | + }, |
| 140 | + "simplelog":{ |
| 141 | + "level":1 |
| 142 | + }, |
| 143 | + ... |
| 144 | +} |
| 145 | +``` |
| 146 | + |
| 147 | +It would be possible for any other module (say a `betterlog` logging module), |
| 148 | +to read this data and use it to configure itself, but doing so could cause |
| 149 | +things to break if `simplelog` directs its users to do something different with |
| 150 | +the config data than what `betterlog` expects. |
| 151 | + |
| 152 | +**NOTE: support for modules to define schemas on parts of the config data is |
| 153 | +currently being considered. This would formalise the constraints modules have |
| 154 | +on what configuration may be defined.** |
| 155 | + |
| 156 | +### Controlling Dependencies |
| 157 | + |
| 158 | +Config data can be used in the [targetDependencies |
| 159 | +section](/reference/module.html#targetDependencies) of `module.json` files. |
| 160 | + |
| 161 | +If a path in the config data matches the values defined on the left-hand side |
| 162 | +of the targetDependencies hash, then the dependencies declared in the object on |
| 163 | +the right-hand side will be used. |
| 164 | + |
| 165 | +For example, given the config data: |
| 166 | + |
| 167 | +```json |
| 168 | + { |
| 169 | + "a": { |
| 170 | + "enable": true |
| 171 | + }, |
| 172 | + "b": { |
| 173 | + "foobar": 123 |
| 174 | + }, |
| 175 | + "c": { |
| 176 | + "baz": { |
| 177 | + |
| 178 | + } |
| 179 | + }, |
| 180 | + "d": { |
| 181 | + "etc": "astring" |
| 182 | + }, |
| 183 | + "e": { |
| 184 | + "supported": null, |
| 185 | + "also-falsey": false |
| 186 | + } |
| 187 | + } |
| 188 | +``` |
| 189 | + |
| 190 | +And the targetDependencies: |
| 191 | + |
| 192 | +```json |
| 193 | + "targetDependencies": { |
| 194 | + "a.enable": { |
| 195 | + "module-1": "^1.2.3" |
| 196 | + }, |
| 197 | + "b.foobar": { |
| 198 | + "module-2": "^1.2.3" |
| 199 | + }, |
| 200 | + "c.baz": { |
| 201 | + "module-3": "^1.2.3" |
| 202 | + }, |
| 203 | + "d.etc": { |
| 204 | + "module-4": "^1.2.3" |
| 205 | + }, |
| 206 | + "e.supported": { |
| 207 | + "module-5": "^1.2.3" |
| 208 | + } |
| 209 | + } |
| 210 | +``` |
| 211 | + |
| 212 | +Then modules 1, 2, 3 and 4 will be included as dependencies, but `module-5` will not. |
| 213 | + |
| 214 | +### Using Configuration In Code |
| 215 | + |
| 216 | +The config data is made available as preprocessor definitions, so that it can |
| 217 | +be tested at compile-time. |
| 218 | + |
| 219 | +For the config data in the above dependencies example, the following |
| 220 | +definitions will be produced: |
| 221 | + |
| 222 | +```C |
| 223 | +#define YOTTA_CFG |
| 224 | +#define YOTTA_CFG_A |
| 225 | +#define YOTTA_CFG_A_ENABLE 1 |
| 226 | +#define YOTTA_CFG_B |
| 227 | +#define YOTTA_CFG_B_FOOBAR 123 |
| 228 | +#define YOTTA_CFG_C |
| 229 | +#define YOTTA_CFG_C_BAZ |
| 230 | +#define YOTTA_CFG_D |
| 231 | +#define YOTTA_CFG_D_ETC astring |
| 232 | +#define YOTTA_CFG_E |
| 233 | +#define YOTTA_CFG_E_SUPPORTED NULL |
| 234 | +#define YOTTA_CFG_E_ALSO_FALSEY 0 |
| 235 | +``` |
| 236 | +
|
| 237 | +Note that string values are not quoted. If you want a quoted string, |
| 238 | +either embed escaped quotes (`\"`) in the string value, or use the preprocessor |
| 239 | +[stringification |
| 240 | +trick](https://gcc.gnu.org/onlinedocs/cpp/Stringification.html). |
| 241 | +
|
| 242 | +JSON boolean values are converted to 1 or 0, and `null` values are converted to `NULL`. |
| 243 | +
|
| 244 | +These definitions are defined through a pre-include file called |
| 245 | +`yotta_config.h` which is generated in the root of the build directory. |
| 246 | +
|
| 247 | +### Using Configuration in CMakeLists |
| 248 | +
|
| 249 | +The config data is also made accessible to any custom CMakeLists.txt that have |
| 250 | +been written to control the build of a module. The CMake definitions are nearly |
| 251 | +the same as the C preprocessor definitions, except that empty definitions, and |
| 252 | +`null` definitions are converted to `set(YOTTA_CFG_<property> "")`, and no |
| 253 | +conversion is performed for boolean values. |
| 254 | +
|
| 255 | +
|
0 commit comments