fprime/cmake/autocoder/helpers.cmake
M Starch bcd4641c91
Scrub XML references from docs (#3718)
* Scrubbing XML

* sp
2025-06-11 14:14:02 -07:00

106 lines
4.9 KiB
CMake

####
# autocoder/helpers.cmake:
#
# Helper functions to make implementing custom autocoders easier! These codify some of the basic patterns for autocoders
# so that implementers can handle standard functions easily.
####
include_guard()
include("utilities")
####
# Macro `autocoder_support_by_suffix`:
#
# This sets up an autocoder to handle files based on a suffix. For example, passing in "*.fpp" will support all files
# ending in ".fpp" i.e. FPP files. It is implemented as a macro such that users need not do anything other than call it
# with the suffix to setup the system correctly. This performs raw ascii comparison, not regular expression matching.
#
# **Note:** this will set the appropriate variable in PARENT_SCOPE and since it is macro this will be the parent scope
# of the caller.
#
# **SUFFIX**: suffix to support
# **AC_INPUT_FILE**: file to check with suffix
# **REQUIRE_CMAKE_RESCAN:** (optional) this file should trigger a cmake rescan. Default: false
####
macro(autocoder_support_by_suffix SUFFIX AC_INPUT_FILE)
ends_with(IS_SUPPORTED "${AC_INPUT_FILE}" "${SUFFIX}")
# Note: set in PARENT_SCOPE in macro is intended. Caller **wants** to set IS_SUPPORTED in their parent's scope.
set(IS_SUPPORTED "${IS_SUPPORTED}" PARENT_SCOPE)
# Files that are supported may also be marked as requiring a rescan. This is done through an optional third argument
if (IS_SUPPORTED AND ${ARGC} GREATER 2)
# CMake weirdness, if ${ARGC} is <= 2 then ${ARGV2} is inherited not from this macro call, but rather from the
# calling function. Thus we need a 2-tier if statement to prevent an explosion.
# See: https://cmake.org/cmake/help/latest/command/macro.html#argument-caveats
if (${ARGV2})
requires_regeneration("${AC_INPUT_FILE}")
endif()
endif()
endmacro()
####
# Function `requires_regeneration`:
#
# Called by the autocoder when a source file needs to setup CMake to reconfigure when the source file changes.
#
# `AC_INPUT_FILE`: file to mark as tracked
####
function(requires_regeneration AC_INPUT_FILE)
get_source_file_property(IS_GENERATED "${AC_INPUT_FILE}" GENERATED)
if (NOT IS_GENERATED)
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${AC_INPUT_FILE}")
endif()
endfunction()
####
# Function `_set_autocoder_name`:
#
# Function to set AUTOCODER_NAME in parent scope. Helper to the below two function, not intended for users to call this
# function.
#
# FUNCTION_NAME: function name for producing error message
####
function(_set_autocoder_name FUNCTION_NAME)
get_filename_component(AUTOCODER_DIRPATH "${CMAKE_CURRENT_LIST_FILE}" DIRECTORY)
get_filename_component(AUTOCODER_DIRNAME "${AUTOCODER_DIRPATH}" NAME)
get_filename_component(AUTOCODER_NAME "${CMAKE_CURRENT_LIST_FILE}" NAME_WLE)
# Some basic check
if (AUTOCODE_NAME STREQUAL "CMakeList")
message(FATAL_ERROR "${FUNCTION_NAME} may only be called globally and from within an autocoder CMake file")
# ASSERT we are not getting the name from autocoder/autocoder.cmake
elseif(AUTOCODER_DIRNAME STREQUAL "autocoder" AND AUTOCODER_NAME STREQUAL "autocoder")
message(FATAL_ERROR "CMake code is inconsistent")
# ASSERT we are not getting the name from autocoder/helpers.cmake
elseif(AUTOCODER_DIRNAME STREQUAL "autocoder" AND AUTOCODER_NAME STREQUAL "helpers")
message(FATAL_ERROR "CMake code is inconsistent")
# ASSERT we are not getting the name from utilities.cmake
elseif(AUTOCODER_DIRNAME STREQUAL "cmake" AND AUTOCODER_NAME STREQUAL "utilities")
message(FATAL_ERROR "CMake code is inconsistent")
endif()
set(AUTOCODER_NAME "${AUTOCODER_NAME}" PARENT_SCOPE)
endfunction()
####
# Macro `autocoder_setup_for_individual_sources`:
#
# A helper to setup the autocoder to handle individual sources. Each source input to the autocoder will result in a new
# call through the autocoder. This handles setting the appropriate property such that this autocoder need not know nor
# care about the property itself. This may only be called from within an autocoder file.
###
function(autocoder_setup_for_individual_sources)
_set_autocoder_name(autocoder_setup_for_individual_sources)
set_property(GLOBAL PROPERTY "${AUTOCODER_NAME}_HANDLES_INDIVIDUAL_SOURCES" TRUE)
endfunction()
####
# Macro `autocoder_setup_for_multiple_sources`:
#
# A helper to setup the autocoder to handle multiple sources with one invocation. All supported source for the module
# will be supplied to a single invocation of the autocoder. This handles setting the appropriate property such that this
# autocoder need not know nor care about the property itself. This may only be called from within an autocoder file.
###
function(autocoder_setup_for_multiple_sources)
_set_autocoder_name(autocoder_setup_for_multiple_sources)
set_property(GLOBAL PROPERTY "${AUTOCODER_NAME}_HANDLES_INDIVIDUAL_SOURCES" FALSE)
endfunction()