cmake: kconfig: Keep symbol names sorted in EXTRA_KCONFIG_OPTIONS

This makes checksum calculation over Kconfig fragments more consistent,
which prevents writing a new `.config` when nothing really changes.

To explain this, consider the following sequence:

1. west build . -DCONFIG_XXXX=y -DCONFIG_YYYY=y
2. west build . -DCONFIG_YYYY=y
3. west build . -DCONFIG_XXXX=y

At (1), we set new values for XXXX and YYYY, so the `.config` changes.

At (2), we set a value for YYYY, but it's the same value as before, so
the `.config` doesn't get overwritten.

At (3), we set a value for XXXX, but it's the same value as before, so
the `.config` shouldn't get overwritten... but it does. What happened?

The reason is that the generated `extra_kconfig_options.conf` fragment,
which is included in the checksum calculation, was being populated using
two sets of CMake cache variables:

- past assignments, prefixed with `CLI_${KCONFIG_NAMESPACE}_`.
- new assignments, prefixed with just `${KCONFIG_NAMESPACE}_`.

Usually, past assignments would appear before new assignments, because
the default `${KCONFIG_NAMESPACE}` is CONFIG, which goes after CLI in
alphabetical order. As a result, the contents of EXTRA_KCONFIG_OPTIONS
at (1) and (2):

   CONFIG_XXXX=y
   CONFIG_YYYY=y

were not identical to its contents at (3):

   CONFIG_YYYY=y
   CONFIG_XXXX=y

resulting in a different checksum.

This is resolved by stripping out the CLI prefix first, then effectively
"mergesorting" the past and new assignments, before starting to populate
EXTRA_KCONFIG_OPTIONS.

Signed-off-by: Grzegorz Swiderski <grzegorz.swiderski@nordicsemi.no>
This commit is contained in:
Grzegorz Swiderski 2023-07-03 02:05:06 +02:00 committed by Carles Cufí
commit 0d12e1b5c0

View file

@ -210,19 +210,15 @@ if(SYSBUILD)
endforeach()
else()
get_cmake_property(cache_variable_names CACHE_VARIABLES)
list(FILTER cache_variable_names INCLUDE REGEX "^(CLI_)?${KCONFIG_NAMESPACE}_")
list(TRANSFORM cache_variable_names REPLACE "^CLI_" "")
list(REMOVE_DUPLICATES cache_variable_names)
endif()
# Sorting the variable names will make checksum calculation more stable.
list(SORT cache_variable_names)
foreach (name ${cache_variable_names})
if("${name}" MATCHES "^CLI_${KCONFIG_NAMESPACE}_")
# Variable was set by user in earlier invocation, let's append to extra
# config unless a new value has been given.
string(REGEX REPLACE "^CLI_" "" org_name ${name})
if(NOT DEFINED ${org_name})
set(EXTRA_KCONFIG_OPTIONS
"${EXTRA_KCONFIG_OPTIONS}\n${org_name}=${${name}}"
)
endif()
elseif("${name}" MATCHES "^${KCONFIG_NAMESPACE}_")
if(DEFINED ${name})
# When a cache variable starts with the 'KCONFIG_NAMESPACE' value, it is
# assumed to be a Kconfig symbol assignment from the CMake command line.
set(EXTRA_KCONFIG_OPTIONS
@ -230,6 +226,13 @@ foreach (name ${cache_variable_names})
)
set(CLI_${name} "${${name}}")
list(APPEND cli_config_list ${name})
elseif(DEFINED CLI_${name})
# An additional 'CLI_' prefix means that the value was set by the user in
# an earlier invocation. Append it to extra config only if no new value was
# assigned above.
set(EXTRA_KCONFIG_OPTIONS
"${EXTRA_KCONFIG_OPTIONS}\n${name}=${CLI_${name}}"
)
endif()
endforeach()