# SPDX-License-Identifier: GPL-3.0-only # Include after project(): IDF component targets and their final source lists exist. if(CMAKE_VERSION VERSION_LESS 3.18) message(FATAL_ERROR "Security overrides need CMake 3.18 source-property directory support") endif() set(_sak_security_script "${CMAKE_CURRENT_LIST_DIR}/../tools/security_overrides.py") get_filename_component(_sak_security_script "${_sak_security_script}" REALPATH) if(NOT PYTHON) find_package(Python3 REQUIRED COMPONENTS Interpreter) set(_sak_security_python "${Python3_EXECUTABLE}") else() set(_sak_security_python "${PYTHON}") endif() idf_build_get_property(_sak_security_idf IDF_PATH) execute_process( COMMAND "${_sak_security_python}" "${_sak_security_script}" --idf-path "${_sak_security_idf}" --project-dir "${PROJECT_SOURCE_DIR}" --binary-dir "${CMAKE_BINARY_DIR}" RESULT_VARIABLE _sak_security_result OUTPUT_VARIABLE _sak_security_stdout ERROR_VARIABLE _sak_security_stderr ) if(NOT _sak_security_result EQUAL 0) message(FATAL_ERROR "SDK security override generation failed:\n${_sak_security_stdout}${_sak_security_stderr}") endif() include("${CMAKE_BINARY_DIR}/security_overrides/manifest.cmake") set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${_sak_security_script}" "${SAK_SECURITY_VERSION_HEADER}") # Public extension point: the Python Entry registry supplies the mapping. This # function is backend-agnostic; a later pinned project/vendor source uses it too. function(sak_security_replace_source component original generated) idf_component_get_property(_target "${component}" COMPONENT_LIB) if(NOT TARGET "${_target}") message(FATAL_ERROR "Security override: missing component target ${component}") endif() get_target_property(_source_dir "${_target}" SOURCE_DIR) get_target_property(_sources "${_target}" SOURCES) get_filename_component(_expected "${original}" REALPATH) set(_matches 0) set(_replaced) foreach(_source IN LISTS _sources) if(_source MATCHES "\\$<") # An expression could hide an additional copy of the protected source. message(FATAL_ERROR "Security override: unaudited source expression in ${component}: ${_source}") endif() get_filename_component(_absolute "${_source}" ABSOLUTE BASE_DIR "${_source_dir}") get_filename_component(_absolute "${_absolute}" REALPATH) if(_absolute STREQUAL _expected) math(EXPR _matches "${_matches} + 1") list(APPEND _replaced "${generated}") else() list(APPEND _replaced "${_source}") endif() endforeach() if(NOT _matches EQUAL 1) message(FATAL_ERROR "Security override: ${component} needs exactly one ${original}; found ${_matches}") endif() # Target flags/includes/definitions are retained because the target is not # replaced. Preserve source-specific properties in the owning directory too. set(_properties COMPILE_FLAGS COMPILE_OPTIONS COMPILE_DEFINITIONS INCLUDE_DIRECTORIES OBJECT_DEPENDS OBJECT_OUTPUTS LANGUAGE SKIP_PRECOMPILE_HEADERS SKIP_UNITY_BUILD_INCLUSION SKIP_LINTING HEADER_FILE_ONLY) set(_configs DEBUG RELEASE RELWITHDEBINFO MINSIZEREL ${CMAKE_CONFIGURATION_TYPES} ${CMAKE_BUILD_TYPE}) foreach(_config IN LISTS _configs) string(TOUPPER "${_config}" _config) list(APPEND _properties "COMPILE_DEFINITIONS_${_config}") endforeach() foreach(_property IN LISTS _properties) get_property(_is_set SOURCE "${_expected}" DIRECTORY "${_source_dir}" PROPERTY "${_property}" SET) if(_is_set) get_property(_value SOURCE "${_expected}" DIRECTORY "${_source_dir}" PROPERTY "${_property}") set_property(SOURCE "${generated}" DIRECTORY "${_source_dir}" PROPERTY "${_property}" "${_value}") endif() endforeach() get_filename_component(_original_dir "${original}" DIRECTORY) get_property(_includes SOURCE "${generated}" DIRECTORY "${_source_dir}" PROPERTY INCLUDE_DIRECTORIES) # Restore the implicit quoted-include search directory lost by relocating C. set_property(SOURCE "${generated}" DIRECTORY "${_source_dir}" PROPERTY INCLUDE_DIRECTORIES "${_original_dir};${_includes}") set_property(TARGET "${_target}" PROPERTY SOURCES "${_replaced}") set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${original}" "${generated}") message(STATUS "Security override: ${component}: ${original} -> ${generated}") endfunction() foreach(_sak_security_id IN LISTS SAK_SECURITY_OVERRIDE_IDS) sak_security_replace_source( "${SAK_SECURITY_${_sak_security_id}_COMPONENT}" "${SAK_SECURITY_${_sak_security_id}_ORIGINAL}" "${SAK_SECURITY_${_sak_security_id}_GENERATED}") endforeach()