feat(build): add idf.py support for CMake configuration presets

This commit adds a new idf.py --preset NAME argument, which allows
selecting the CMake configuration preset with a given name.
For idf.py, selecting the preset does two things:
- sets the build directory, which is specified in the preset itself
  using "binaryDir" field
- passes --preset argument to CMake configuration phase

The multi_config example is updated to illustrate how this feature is
expected to be used.
This commit is contained in:
Ivan Grokhotkov
2025-11-03 17:34:21 +01:00
committed by Frantisek Hrbata
parent 811e27118d
commit 6c01b6a324
10 changed files with 226 additions and 44 deletions
@@ -0,0 +1,34 @@
{
"version": 3,
"configurePresets": [
{
"name": "default",
"binaryDir": "build/default",
"displayName": "Default (development)",
"description": "Development configuration",
"cacheVariables": {
"SDKCONFIG": "./build/default/sdkconfig"
}
},
{
"name": "prod1",
"binaryDir": "build/prod1",
"displayName": "Product 1",
"description": "Production configuration for product 1",
"cacheVariables": {
"SDKCONFIG_DEFAULTS": "sdkconfig.defaults.prod_common;sdkconfig.defaults.prod1",
"SDKCONFIG": "./build/prod1/sdkconfig"
}
},
{
"name": "prod2",
"binaryDir": "build/prod2",
"displayName": "Product 2",
"description": "Production configuration for product 2",
"cacheVariables": {
"SDKCONFIG_DEFAULTS": "sdkconfig.defaults.prod_common;sdkconfig.defaults.prod2",
"SDKCONFIG": "./build/prod2/sdkconfig"
}
}
]
}
@@ -28,45 +28,48 @@ For each configuration, a few configuration options are set:
### Development build
In this example, Development configuration is specified in `sdkconfig.defaults`, so it is the default one. You can build the project as usual:
To build the development configuration (specified in `sdkconfig.defaults`), specify it using --preset argument:
```
idf.py build
idf.py --preset default build
```
To flash the project and see the output, run:
```
idf.py -p PORT flash monitor
idf.py --preset default -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
### Production build
To build one of the Production configurations, specify a different build directory and `SDKCONFIG_DEFAULTS` file. For example, to build `prod1` configuration:
To build one of the Production configurations, specify the name using idf.py --preset argument:
```
idf.py -B build_prod1 -D SDKCONFIG_DEFAULTS="sdkconfig.prod_common;sdkconfig.prod1" build
idf.py --preset prod1 build
```
* `-B build_prod1` sets the build directory to `build_prod1`
* `-D SDKCONFIG_DEFAULTS="sdkconfig.prod_common;sdkconfig.prod1"` selects `sdkconfig.prod_common` and `sdkconfig.prod1` files to be used for creating app configuration (sdkconfig), instead of the usual `sdkconfig.defaults`. See the section below on how these two default configuration files are combined.
To flash the project and see the output, run:
```
idf.py -B build_prod1 -p PORT flash monitor
```
Note that it is not necessary to repeat `-D SDKCONFIG_DEFAULTS=...` option once the build directory has been created and `sdkconfig` file generated. For example, to build the project again, run:
```
idf.py -B build_prod1 build
idf.py --preset prod1 -p PORT flash monitor
```
To build and run the app with `prod2` configuration, repeat the steps above, replacing `prod1` with `prod2`.
### Specifying the preset for multiple commands
To avoid having to specify `--preset` argument every time you run `idf.py`, you can set `IDF_PRESET` environment variable:
<!-- FIXME: Windows instructions -->
```shell
export IDF_PRESET=prod1
# subsequent commands will work with 'prod1' configuration:
idf.py build
idf.py flash monitor
```
### Combining multiple files in `SDKCONFIG_DEFAULTS`
`SDKCONFIG_DEFAULTS` build system variable selects the file which contains the default app configuration, used when no `sdkconfig` file is present. If not specified, `SDKCONFIG_DEFAULTS` is set to `"sdkconfig.defaults"`.
@@ -80,24 +83,6 @@ It is possible to specify multiple files in this variable, separating them with
This way the common options do not need to be repeated in each of `sdkconfig.prodN` files.
### Create configuration profile files via @filename
You can further enhance your build process by using configuration profile files. These profile files contain arguments that streamline the build process for specific scenarios. Let's have our example profile files:
- [profiles/prod](profiles/prod)
- [profiles/debug](profiles/debug)
You can use these profile files to quickly set up the build environment with specific configurations.
- To build with the production profile: `idf.py @profiles/prod build`
- To build with the debug profile: `idf.py @profiles/debug build`
This approach simplifies the process of specifying complex command-line arguments and allows for greater flexibility in managing different build scenarios.
Moreover, you can combine arguments from a profile file with additional command line arguments. Anywhere on the idf.py command line, you can specify a file as @filename.txt to read one or more arguments from the text file. Arguments in the file can be separated by newlines or spaces and are expanded exactly as if they had appeared in that order on the idf.py command line.
For example using [cutom_flash.txt](custom_flash.txt), you can expand the command: `idf.py -B build_production @custom_flash.txt monitor`
### Generated `sdkconfig` file
In this example, `sdkconfig` file is placed into the build directory, instead of the project root directory as it is done by default. This allows development and production builds to exist side by side. The location of `sdkconfig` file is set using `SDKCONFIG` variable in [project CMakeLists.txt](CMakeLists.txt) file.
@@ -1 +0,0 @@
-p PORT flash
@@ -1 +0,0 @@
-B build-debug -DSDKCONFIG=build-debug/sdkconfig -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.debug"
@@ -1 +0,0 @@
-B build-production -DSDKCONFIG=build-production/sdkconfig -DSDKCONFIG_DEFAULTS="sdkconfig.defaults;sdkconfig.prod"