1# SPDX-License-Identifier: Apache-2.0 2# 3# Copyright (c) 2021, Nordic Semiconductor ASA 4 5# Snippets support 6# 7# This module: 8# 9# - searches for snippets in zephyr and any modules 10# - validates the SNIPPET input variable, if any 11# 12# If SNIPPET contains a snippet name that is not found, an error 13# will be raised, and the list of valid snippets will be printed. 14# 15# Outcome: 16# The following variables will be defined when this module completes: 17# 18# - SNIPPET_AS_LIST: CMake list of snippet names, created from the 19# SNIPPET variable 20# - SNIPPET_ROOT: CMake list of snippet roots, deduplicated and with 21# ZEPHYR_BASE appended at the end 22# 23# The following variables may be updated when this module completes: 24# - DTC_OVERLAY_FILE 25# - OVERLAY_CONFIG 26# 27# The following targets will be defined when this CMake module completes: 28# - snippets: when invoked, a list of valid snippets will be printed 29# 30# Optional variables: 31# - SNIPPET_ROOT: input CMake list of snippet roots (directories containing 32# additional snippet implementations); this should not include ZEPHYR_BASE, 33# as that will be added by this module 34 35include_guard(GLOBAL) 36 37include(extensions) 38 39# Warn the user if SNIPPET changes later. Such changes are ignored. 40zephyr_check_cache(SNIPPET WATCH) 41 42# Putting the body into a function prevents us from polluting the 43# parent scope. We'll set our outcome variables in the parent scope of 44# the function to ensure the outcome of the module. 45function(zephyr_process_snippets) 46 set(snippets_py ${ZEPHYR_BASE}/scripts/snippets.py) 47 set(snippets_generated ${CMAKE_BINARY_DIR}/zephyr/snippets_generated.cmake) 48 49 # Set SNIPPET_AS_LIST, removing snippets_generated.cmake if we are 50 # running cmake again and snippets are no longer requested. 51 if (NOT DEFINED SNIPPET) 52 set(SNIPPET_AS_LIST "" PARENT_SCOPE) 53 file(REMOVE ${snippets_generated}) 54 else() 55 string(REPLACE " " ";" SNIPPET_AS_LIST "${SNIPPET}") 56 set(SNIPPET_AS_LIST "${SNIPPET_AS_LIST}" PARENT_SCOPE) 57 endif() 58 59 # Set SNIPPET_ROOT. 60 list(APPEND SNIPPET_ROOT ${APPLICATION_SOURCE_DIR}) 61 list(APPEND SNIPPET_ROOT ${ZEPHYR_BASE}) 62 unset(real_snippet_root) 63 foreach(snippet_dir ${SNIPPET_ROOT}) 64 # The user might have put a symbolic link in here, for example. 65 file(REAL_PATH ${snippet_dir} real_snippet_dir) 66 list(APPEND real_snippet_root ${real_snippet_dir}) 67 endforeach() 68 set(SNIPPET_ROOT ${real_snippet_root}) 69 list(REMOVE_DUPLICATES SNIPPET_ROOT) 70 set(SNIPPET_ROOT "${SNIPPET_ROOT}" PARENT_SCOPE) 71 72 # Generate and include snippets_generated.cmake. 73 # The Python script is responsible for checking for unknown 74 # snippets. 75 set(snippet_root_args) 76 foreach(root IN LISTS SNIPPET_ROOT) 77 list(APPEND snippet_root_args --snippet-root "${root}") 78 endforeach() 79 set(requested_snippet_args) 80 foreach(snippet_name ${SNIPPET_AS_LIST}) 81 list(APPEND requested_snippet_args --snippet "${snippet_name}") 82 endforeach() 83 execute_process(COMMAND ${PYTHON_EXECUTABLE} 84 ${snippets_py} 85 ${snippet_root_args} 86 ${requested_snippet_args} 87 --cmake-out ${snippets_generated} 88 OUTPUT_VARIABLE output 89 ERROR_VARIABLE output 90 RESULT_VARIABLE ret) 91 if(${ret}) 92 message(FATAL_ERROR "${output}") 93 endif() 94 include(${snippets_generated}) 95 96 # Create the 'snippets' target. Each snippet is printed in a 97 # separate command because build system files are not fond of 98 # newlines. 99 list(TRANSFORM SNIPPET_NAMES PREPEND "COMMAND;${CMAKE_COMMAND};-E;echo;" 100 OUTPUT_VARIABLE snippets_target_cmd) 101 add_custom_target(snippets ${snippets_target_cmd} USES_TERMINAL) 102 103 # If snippets were requested, print messages for each one. 104 if(SNIPPET_AS_LIST) 105 # Print the requested snippets. 106 set(snippet_names "Snippet(s):") 107 foreach(snippet IN LISTS SNIPPET_AS_LIST) 108 string(APPEND snippet_names " ${snippet}") 109 endforeach() 110 message(STATUS "${snippet_names}") 111 endif() 112 113 # Re-run cmake if any files we depend on changed. 114 set_property(DIRECTORY APPEND PROPERTY 115 CMAKE_CONFIGURE_DEPENDS 116 ${snippets_py} 117 ${SNIPPET_PATHS} # generated variable 118 ) 119endfunction() 120 121zephyr_process_snippets() 122