build(cmake/kconfig): keep defconfigs after first configure

This commit is contained in:
André Costa
2026-09-10 12:01:03 +02:00
committed by Gabor Kiss-Vamosi
parent 123f870908
commit 8ac018e06e
3 changed files with 85 additions and 18 deletions
+1 -1
View File
@@ -215,7 +215,7 @@ Below is a list of the available options/variables
| LV_BUILD_CONF_DIR | PATH | Allows to set a directory containing `lv_conf.h` |
| LV_BUILD_USE_KCONFIG | BOOLEAN | When set KConfig is used as the configuration source. This option is disabled by default. |
| LV_BUILD_DOTCONFIG_PATH | PATH | Specify the path to a .config file when using Kconfig |
| LV_BUILD_DEFCONFIG_PATH | STRING | Specify to use a .defconfig file instead of the current .config in a Kconfig setup. Accepts a `;`-separated list of defconfigs, which are merged in the given order so that a later one overrides a value set by an earlier one. |
| LV_BUILD_DEFCONFIG_PATH | STRING | Use a `.defconfig` file instead of an existing `.config` in a Kconfig setup. Accepts a `;`-separated list of defconfigs, which are merged in the given order so that a later one overrides a value set by an earlier one. The merged result is written to `.config` in the build directory, which is the live configuration from then on: it can be edited by hand or with `menuconfig`, and is only regenerated when a defconfig changes. |
| LV_BUILD_DEFCONFIG_STRICT | BOOLEAN | When enabled, a defconfig that assigns an unknown or non-user-configurable symbol, or a value that ends up having no effect, fails the build instead of being ignored. This option is disabled by default. |
| LV_BUILD_KCONFIG_ROOT | PATH | Override the root Kconfig file that is parsed by LVGL's build system (defaults to LVGL's Kconfig file) |
| LV_BUILD_LVGL_H_SYSTEM_INCLUDE | BOOLEAN | Enable if LVGL will be installed to the system or your build system uses a sysroot. Turning this option on implies that the resources generated by the image generation script will include `lvgl.h` as a system include. i.e: `#include <lvgl.h>`. This option is disabled by default. |
+15
View File
@@ -205,6 +205,21 @@ cmake -B build -DLV_BUILD_USE_KCONFIG=ON \
cmake --build build
```
### Editing a configuration that came from a defconfig
When using one or multiple defconfigs, LVGL merges them into `build/.config`.
You can then edit that file by hand or with `menuconfig`. On the next
`cmake --build build` the change is picked up
```bash
KCONFIG_CONFIG=build/.config menuconfig # or edit the file directly
cmake --build build # re-runs the configuration
```
Editing one of the defconfigs, or changing the list of them, generates `build/.config`
again, which discards any edit made to it. If you want to revert any hand-made changes
to `build/.config`, simply delete it and LVGL will generate it again from the defconfigs.
### Empty configuration
`configs/defconfigs/empty.defconfig` strips LVGL to its smallest sensible
+69 -17
View File
@@ -16,30 +16,75 @@ macro(lv_normalize_config_path INPUT_PATH LABEL OUTPUT_VAR)
endif()
endmacro()
# Returns in OUTPUT_VAR a hash of the given defconfig fragments: their
# paths and their contents.
function(lv_defconfig_hash FRAGMENTS OUTPUT_VAR)
set(defconfig_list "strict=${LV_BUILD_DEFCONFIG_STRICT}")
foreach(fragment IN LISTS FRAGMENTS)
file(SHA256 ${fragment} fragment_hash)
string(APPEND defconfig_list ";${fragment}=${fragment_hash}")
endforeach()
string(SHA256 defconfig_hash "${defconfig_list}")
set(${OUTPUT_VAR} ${defconfig_hash} PARENT_SCOPE)
endfunction()
set(KCONFIG_INPUT_FLAGS)
if(LV_BUILD_DEFCONFIG_PATH AND LV_BUILD_DOTCONFIG_PATH)
message(WARNING "Both LV_BUILD_DEFCONFIG_PATH and LV_BUILD_DOTCONFIG_PATH are set, \
ignoring the latter. Pass -DLV_BUILD_DEFCONFIG_PATH= to drop the defconfigs.")
endif()
# Check if the user wants to use a defconfig, using the -DLV_BUILD_DEFCONFIG_PATH option
if(LV_BUILD_DEFCONFIG_PATH)
# Several defconfigs can be given as a ";"-separated list. They are merged in
# order, so a later fragment overrides the value set by an earlier one. This
# lets related configurations share a common base instead of duplicating it.
set(DOTCONFIG)
set(DEFCONFIGS)
foreach(defconfig IN LISTS LV_BUILD_DEFCONFIG_PATH)
lv_normalize_config_path(defconfig "defconfig" defconfig_abs)
list(APPEND DOTCONFIG ${defconfig_abs})
if(NOT EXISTS ${defconfig_abs})
message(FATAL_ERROR "lvgl: ${defconfig_abs} does not exist")
endif()
list(APPEND DEFCONFIGS ${defconfig_abs})
endforeach()
list(LENGTH DOTCONFIG defconfig_count)
if(LV_BUILD_DEFCONFIG_STRICT)
# Apply the stricter checks: assignments to unknown or promptless
# symbols, and values that end up not taking effect, become errors.
# Overriding a symbol set by an earlier fragment is allowed.
set(KCONFIG_INPUT_FLAGS --handwritten-input-configs)
elseif(defconfig_count GREATER 1)
# Merging without the strict checks needs this, otherwise overriding a
# symbol set by an earlier fragment is reported as an error.
set(KCONFIG_INPUT_FLAGS --forced-input-configs)
# The defconfig fragments are merged to create ${OUTPUT_DOTCONFIG}
# ${OUTPUT_DOTCONFIG} can be edited by hand or with menuconfig and the next
# build picks these updates instead of using the defconfig fragments we started with
# Editing a fragment, or changing the list of fragments, creates ${OUTPUT_DOTCONFIG} again.
lv_defconfig_hash("${DEFCONFIGS}" DEFCONFIG_HASH)
if(EXISTS ${OUTPUT_DOTCONFIG} AND "${DEFCONFIG_HASH}" STREQUAL "${LV_BUILD_DEFCONFIG_HASH}")
# No changes to defconfig fragments and ${OUTPUT_DOTCONFIG}
# already exist, just use it
set(DOTCONFIG ${OUTPUT_DOTCONFIG})
else()
if(EXISTS ${OUTPUT_DOTCONFIG})
message(STATUS "lvgl: defconfigs changed, regenerating ${OUTPUT_DOTCONFIG} from them")
endif()
set(DOTCONFIG ${DEFCONFIGS})
list(LENGTH DEFCONFIGS defconfig_count)
if(LV_BUILD_DEFCONFIG_STRICT)
# Apply the stricter checks: assignments to unknown or promptless
# symbols, and values that end up not taking effect, become errors.
# Overriding a symbol set by an earlier fragment is allowed.
set(KCONFIG_INPUT_FLAGS --handwritten-input-configs)
elseif(defconfig_count GREATER 1)
# Merging without the strict checks needs this, otherwise overriding a
# symbol set by an earlier fragment is reported as an error.
set(KCONFIG_INPUT_FLAGS --forced-input-configs)
endif()
endif()
# Both defconfig fragment and ${OUTPUT_DOTCONFIG} changes
# must trigger a cmake configuration
set(CONFIGURE_DEPENDS ${DEFCONFIGS} ${OUTPUT_DOTCONFIG})
elseif(LV_BUILD_DOTCONFIG_PATH)
lv_normalize_config_path(LV_BUILD_DOTCONFIG_PATH ".config" DOTCONFIG)
set(CONFIGURE_DEPENDS ${DOTCONFIG})
else()
# No explicit config file set
# Search, in order:
@@ -53,6 +98,7 @@ else()
else()
set(DOTCONFIG ${OUTPUT_DOTCONFIG})
endif()
set(CONFIGURE_DEPENDS ${DOTCONFIG})
endif()
foreach(config IN LISTS DOTCONFIG)
@@ -80,13 +126,19 @@ if(NOT "${ret}" STREQUAL "0")
message(FATAL_ERROR "command failed with return code: ${ret}")
endif()
if(DEFINED DEFCONFIG_HASH)
# store the defconfig hash in cache so we can use it on the next run
set(LV_BUILD_DEFCONFIG_HASH ${DEFCONFIG_HASH} CACHE INTERNAL
"Hash of the defconfigs ${OUTPUT_DOTCONFIG} was seeded from")
else()
# No defconfig in use any more, so the recorded hash would only make
# a later one look already applied.
unset(LV_BUILD_DEFCONFIG_HASH CACHE)
endif()
# Re-run CMake configuration (which regenerates autoconf.h) when the input
# .config/defconfig changes, so that `cmake --build` picks up config edits.
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${DOTCONFIG})
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${CONFIGURE_DEPENDS})
# Set the variable that can be used by the CMakeLists.txt including this file
set(KCONFIG_EXTERNAL_INCLUDE ${AUTOCONF_H})
# Ensure LV_BUILD_DEFCONFIG_PATH is not set in the path, to be able to call it without
# the -DLV_BUILD_DEFCONFIG_PATH after the first configuration, and to work with the .config
unset(LV_BUILD_DEFCONFIG_PATH CACHE)