diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index d5cd84256d2e6a..f98ae8c68b27e2 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -3231,6 +3231,7 @@ function(zephyr_get variable) # Keep current scope variables in internal variables. # This is needed to properly handle cases where we want to check value against # environment value or when appending with the MERGE operation. + zephyr_exists_scope(snippets_exists snippets) foreach(var ${GET_VAR_VAR}) set(current_${var} ${${var}}) set(${var}) @@ -3251,10 +3252,11 @@ function(zephyr_get variable) set(sysbuild_global_${var}) endif() - if(TARGET snippets_scope) - get_property(snippets_${var} TARGET snippets_scope PROPERTY ${var}) + if(snippets_exists) + zephyr_get_scoped(snippets_${var} snippets ${var}) endif() endforeach() + unset(snippets_exists) set(${variable} "") set(scopes "sysbuild_local;sysbuild_global;CACHE;snippets;ENV;current") @@ -3317,13 +3319,59 @@ endfunction(zephyr_get variable) # : Name of new scope. # function(zephyr_create_scope scope) - if(TARGET ${scope}_scope) + zephyr_exists_scope(scope_exists ${scope}) + if(scope_exists) message(FATAL_ERROR "zephyr_create_scope(${scope}) already exists.") endif() add_custom_target(${scope}_scope) endfunction() +# Usage: +# zephyr_exists_scope( ) +# +# Checks if is defined. Sets to TRUE or FALSE. +# +# : Output variable containing the result of the check +# : Scope to look up +# +macro(zephyr_exists_scope output scope) + if(TARGET ${scope}_scope) + set(${output} TRUE) + else() + set(${output} FALSE) + endif() +endmacro() + +# Usage: +# zephyr_get_scoped( ) +# +# Get the current value of in a specific , as defined by a +# previous zephyr_set() call. The value will be stored in the variable. +# +# : Name of variable to store the value in +# : Scope for the variable look up +# : Name of variable to look up in the specific scope +# +function(zephyr_get_scoped output scope variable) + zephyr_exists_scope(scope_exists ${scope}) + if(NOT scope_exists) + message(FATAL_ERROR "zephyr_get_scoped(): scope ${scope} doesn't exists.") + endif() + + if(CMAKE_SCRIPT_MODE_FILE) + set(kind SOURCE) + else() + set(kind TARGET) + endif() + get_property(value ${kind} ${scope}_scope PROPERTY ${variable}) + if(DEFINED value) + set(${output} "${value}" PARENT_SCOPE) + else() + unset(${output} PARENT_SCOPE) + endif() +endfunction() + # Usage: # zephyr_set( SCOPE [APPEND]) # @@ -3342,7 +3390,8 @@ function(zephyr_set variable) zephyr_check_arguments_required_all(zephyr_set SET_VAR SCOPE) - if(NOT TARGET ${SET_VAR_SCOPE}_scope) + zephyr_exists_scope(scope_exists ${SET_VAR_SCOPE}) + if(NOT scope_exists) message(FATAL_ERROR "zephyr_set(... SCOPE ${SET_VAR_SCOPE}) doesn't exists.") endif() @@ -3350,7 +3399,12 @@ function(zephyr_set variable) set(property_args APPEND) endif() - set_property(TARGET ${SET_VAR_SCOPE}_scope ${property_args} + if(CMAKE_SCRIPT_MODE_FILE) + set(kind SOURCE) + else() + set(kind TARGET) + endif() + set_property(${kind} ${SET_VAR_SCOPE}_scope ${property_args} PROPERTY ${variable} ${SET_VAR_UNPARSED_ARGUMENTS} ) endfunction() @@ -5871,10 +5925,6 @@ if(CMAKE_SCRIPT_MODE_FILE) # This silence the error: 'set_target_properties command is not scriptable' endfunction() - function(zephyr_set variable) - # This silence the error: zephyr_set(... SCOPE ) doesn't exists. - endfunction() - # Build info creates a custom target for handling of build info. # build_info is not needed in script mode but still called by Zephyr CMake # modules. Therefore disable build_info(...) in when including @@ -5883,4 +5933,27 @@ if(CMAKE_SCRIPT_MODE_FILE) # This silence the error: 'YAML context 'build_info' does not exist.' # 'Remember to create a YAML context' endfunction() + + # Script mode version, using SOURCE properties + function(zephyr_create_scope scope) + zephyr_exists_scope(scope_exists ${scope}) + if(scope_exists) + message(FATAL_ERROR "zephyr_create_scope(${scope}) already exists.") + endif() + + set_property(SOURCE ${scope}_scope PROPERTY ZEPHYR_SCOPE TRUE) + endfunction() + + # Script mode version, using SOURCE properties + macro(zephyr_exists_scope output scope) + get_property(zephyr_exists_scope_value SOURCE ${scope}_scope PROPERTY ZEPHYR_SCOPE) + if(DEFINED zephyr_exists_scope_value) + unset(zephyr_exists_scope_value) + set(${output} TRUE) + else() + set(${output} FALSE) + endif() + endmacro() + + # zephyr_get_scoped and zephyr_set support script mode as well endif() diff --git a/cmake/modules/yaml.cmake b/cmake/modules/yaml.cmake index 50d6c7cc74622d..61dc310b902bce 100644 --- a/cmake/modules/yaml.cmake +++ b/cmake/modules/yaml.cmake @@ -93,7 +93,8 @@ function(yaml_context) ) endif() - if(TARGET ${ARG_YAML_NAME}_scope) + zephyr_exists_scope(scope_exists ${ARG_YAML_NAME}) + if(scope_exists) list(POP_FRONT ARG_YAML_UNPARSED_ARGUMENTS out-var) set(${out-var} TRUE PARENT_SCOPE) else() @@ -183,7 +184,7 @@ function(yaml_get out_var) zephyr_check_arguments_required_all(${CMAKE_CURRENT_FUNCTION} ARG_YAML NAME KEY) internal_yaml_context_required(NAME ${ARG_YAML_NAME}) - get_property(json_content TARGET ${ARG_YAML_NAME}_scope PROPERTY JSON) + zephyr_get_scoped(json_content ${ARG_YAML_NAME} JSON) # We specify error variable to avoid a fatal error. # If key is not found, then type becomes '-NOTFOUND' and value handling is done below. @@ -224,7 +225,7 @@ function(yaml_length out_var) zephyr_check_arguments_required_all(${CMAKE_CURRENT_FUNCTION} ARG_YAML NAME KEY) internal_yaml_context_required(NAME ${ARG_YAML_NAME}) - get_property(json_content TARGET ${ARG_YAML_NAME}_scope PROPERTY JSON) + zephyr_get_scoped(json_content ${ARG_YAML_NAME} JSON) string(JSON type ERROR_VARIABLE error TYPE "${json_content}" ${ARG_YAML_KEY}) if(type STREQUAL ARRAY) @@ -262,7 +263,7 @@ function(yaml_set) zephyr_check_arguments_exclusive(${CMAKE_CURRENT_FUNCTION} ARG_YAML VALUE LIST) internal_yaml_context_required(NAME ${ARG_YAML_NAME}) - get_property(json_content TARGET ${ARG_YAML_NAME}_scope PROPERTY JSON) + zephyr_get_scoped(json_content ${ARG_YAML_NAME} JSON) set(yaml_key_undefined ${ARG_YAML_KEY}) foreach(k ${yaml_key_undefined}) @@ -335,7 +336,7 @@ function(yaml_remove) zephyr_check_arguments_required_all(${CMAKE_CURRENT_FUNCTION} ARG_YAML NAME KEY) internal_yaml_context_required(NAME ${ARG_YAML_NAME}) - get_property(json_content TARGET ${ARG_YAML_NAME}_scope PROPERTY JSON) + zephyr_get_scoped(json_content ${ARG_YAML_NAME} JSON) string(JSON json_content REMOVE "${json_content}" ${ARG_YAML_KEY}) zephyr_set(JSON "${json_content}" SCOPE ${ARG_YAML_NAME}) @@ -359,18 +360,16 @@ function(yaml_save) zephyr_check_arguments_required(${CMAKE_CURRENT_FUNCTION} ARG_YAML NAME) internal_yaml_context_required(NAME ${ARG_YAML_NAME}) - get_target_property(yaml_file ${ARG_YAML_NAME}_scope FILE) + zephyr_get_scoped(yaml_file ${ARG_YAML_NAME} FILE) if(NOT yaml_file) zephyr_check_arguments_required(${CMAKE_CURRENT_FUNCTION} ARG_YAML FILE) endif() - get_property(json_content TARGET ${ARG_YAML_NAME}_scope PROPERTY JSON) + zephyr_get_scoped(json_content ${ARG_YAML_NAME} JSON) to_yaml("${json_content}" 0 yaml_out) if(DEFINED ARG_YAML_FILE) set(yaml_file ${ARG_YAML_FILE}) - else() - get_property(yaml_file TARGET ${ARG_YAML_NAME}_scope PROPERTY FILE) endif() if(EXISTS ${yaml_file}) FILE(RENAME ${yaml_file} ${yaml_file}.bak) diff --git a/tests/cmake/zephyr_get/CMakeLists.txt b/tests/cmake/zephyr_get/CMakeLists.txt index a6516bfba735ce..447e1c76c253aa 100644 --- a/tests/cmake/zephyr_get/CMakeLists.txt +++ b/tests/cmake/zephyr_get/CMakeLists.txt @@ -2,9 +2,17 @@ cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(zephyr_get_test) -target_sources(app PRIVATE ${ZEPHYR_BASE}/misc/empty_file.c) +if(CMAKE_SCRIPT_MODE_FILE) + # Script mode initialization (re-run) + set(ZEPHYR_BASE ${CMAKE_CURRENT_LIST_DIR}/../../../) + list(APPEND CMAKE_MODULE_PATH "${ZEPHYR_BASE}/cmake/modules") + include(extensions) +else() + # Project mode initialization (main CMake invocation) + find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + project(zephyr_get_test) + target_sources(app PRIVATE ${ZEPHYR_BASE}/misc/empty_file.c) +endif() if(SYSBUILD) get_property(IMAGE_NAME TARGET sysbuild_cache PROPERTY SYSBUILD_NAME) @@ -73,6 +81,9 @@ function(assert_equal variable expected_value) endif() set(info "${TEST_NAME}: ${variable} == '${actual_value}'") + if(CMAKE_SCRIPT_MODE_FILE) + string(PREPEND info "script mode ") + endif() if("${actual_value}" STREQUAL "${expected_value}") message("PASS: ${info}") else() @@ -583,3 +594,8 @@ run_suite( test_merge_reverse test_snippets_scope ) + +if (NOT CMAKE_SCRIPT_MODE_FILE AND NOT SYSBUILD) + # Re-run this testsuite in plain script mode + execute_process(COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_LIST_FILE}) +endif()