mirror of
https://github.com/nasa/fprime.git
synced 2025-12-10 00:44:37 -06:00
* Add FPRIME_CMAKE_QUIET option * Remove makefile deadcode * Attempt CI debug Add debugging message for FPRIME_SUB_BUILD_JOBS variable. * Fix argument passing for sub-build jobs * Update cmake/sub-build/sub-build.cmake * Update cmake/sub-build/sub-build.cmake --------- Co-authored-by: Thomas Boyer-Chammard <49786685+thomas-bc@users.noreply.github.com>
278 lines
14 KiB
CMake
278 lines
14 KiB
CMake
####
|
|
# autocoder/autocoder.cmake:
|
|
#
|
|
# Autocoder setup and support file. This performs all of the general autocoder functions, running the specific functions
|
|
# defined within the individual autocoders. This gives the ability to run a set of autocoders to produce files.
|
|
#
|
|
# Note: autocoders need to be run by targets. See target/target.cmake.
|
|
####
|
|
include_guard()
|
|
include(utilities)
|
|
include(autocoder/helpers)
|
|
|
|
# Allowed return values
|
|
set(FPRIME_AUTOCODER_UNSUPPORTED AUTOCODER_GENERATED AUTOCODER_SCRIPT AUTOCODER_INPUTS AUTOCODER_INCLUDES)
|
|
set(FPRIME_AUTOCODER_REQUIRED AUTOCODER_GENERATED_AUTOCODER_INPUTS AUTOCODER_GENERATED_BUILD_SOURCES AUTOCODER_GENERATED_OTHER)
|
|
set(FPRIME_AUTOCODER_OPTIONAL AUTOCODER_DEPENDENCIES)
|
|
|
|
####
|
|
# run_ac_set:
|
|
#
|
|
# Run a set of autocoder allowing back-to-back execution of a set of autocoders. SOURCES are the source files that are
|
|
# input into the autocoder filters. Extra arguments may be an include path for an autocoder (e.g. autocoder/fpp).
|
|
#
|
|
# BUILD_TARGET_NAME: name of the build target getting attached autocoding
|
|
# SOURCES: source file input list
|
|
# ...: autocoder include
|
|
####
|
|
function (run_ac_set BUILD_TARGET_NAME)
|
|
# Get all sources available for autocode processing
|
|
get_target_property(AUTOCODER_INPUT_SOURCES "${BUILD_TARGET_NAME}" AUTOCODER_INPUTS)
|
|
# Get the source list, if passed in
|
|
set(AC_LIST)
|
|
if (ARGN)
|
|
set(AC_LIST "${ARGN}")
|
|
endif()
|
|
# Do not init GENERATED_FILE_LIST as it is read from previous AC runs above
|
|
|
|
# Create a hash of the autocoder set to isolate results
|
|
string(SHA1 "AC_SET_HASH" "${AC_LIST}")
|
|
|
|
foreach(AC_CMAKE IN LISTS AC_LIST)
|
|
run_ac("${BUILD_TARGET_NAME}" "${AC_CMAKE}" "${AUTOCODER_INPUT_SOURCES}" "${GENERATED_FILE_LIST}" "${AC_SET_HASH}")
|
|
get_property(AUTOCODER_GENERATED_AUTOCODER_INPUTS_VALUES TARGET "${BUILD_TARGET_NAME}" PROPERTY "${AC_SET_HASH}_AUTOCODER_GENERATED_AUTOCODER_INPUTS")
|
|
list(APPEND AUTOCODER_INPUT_SOURCES ${AUTOCODER_GENERATED_AUTOCODER_INPUTS_VALUES})
|
|
endforeach()
|
|
|
|
|
|
# Read from hash-specific properties for this autocoder set
|
|
get_property(AUTOCODER_GENERATED_VALUES TARGET "${BUILD_TARGET_NAME}" PROPERTY "${AC_SET_HASH}_AUTOCODER_GENERATED")
|
|
get_property(AUTOCODER_GENERATED_BUILD_SOURCES_VALUES TARGET "${BUILD_TARGET_NAME}" PROPERTY "${AC_SET_HASH}_AUTOCODER_GENERATED_BUILD_SOURCES")
|
|
get_property(AUTOCODER_GENERATED_AUTOCODER_INPUTS_VALUES TARGET "${BUILD_TARGET_NAME}" PROPERTY "${AC_SET_HASH}_AUTOCODER_GENERATED_AUTOCODER_INPUTS")
|
|
get_property(AUTOCODER_DEPENDENCIES_VALUES TARGET "${BUILD_TARGET_NAME}" PROPERTY "${AC_SET_HASH}_AUTOCODER_DEPENDENCIES")
|
|
get_property(AUTOCODER_GENERATED_OTHER_VALUES TARGET "${BUILD_TARGET_NAME}" PROPERTY "${AC_SET_HASH}_AUTOCODER_GENERATED_OTHER")
|
|
|
|
# Append to final target properties (aggregate of all runs)
|
|
append_list_property("${AUTOCODER_GENERATED_VALUES}" TARGET "${BUILD_TARGET_NAME}" PROPERTY AC_GENERATED)
|
|
append_list_property("${AUTOCODER_GENERATED_AUTOCODER_INPUTS_VALUES}" TARGET "${BUILD_TARGET_NAME}" PROPERTY AUTOCODER_INPUTS)
|
|
# Cannot use `target_sources` as it does not respect the "GENERATED" flag. Thus the sources need to be added
|
|
# to the SOURCES property directly.
|
|
append_list_property("${AUTOCODER_GENERATED_BUILD_SOURCES_VALUES}" TARGET "${BUILD_TARGET_NAME}" PROPERTY SOURCES)
|
|
append_list_property("${AUTOCODER_DEPENDENCIES_VALUES}" TARGET "${BUILD_TARGET_NAME}" PROPERTY LINK_LIBRARIES)
|
|
append_list_property("${AUTOCODER_DEPENDENCIES_VALUES}" TARGET "${BUILD_TARGET_NAME}" PROPERTY INTERFACE_LINK_LIBRARIES)
|
|
append_list_property("${AUTOCODER_DEPENDENCIES_VALUES}" TARGET "${BUILD_TARGET_NAME}" PROPERTY FPRIME_DEPENDENCIES)
|
|
# Invalidate the TRANSITIVE_DEPENDENCIES on the target
|
|
if (AUTOCODER_DEPENDENCIES_VALUES)
|
|
set_property(TARGET "${BUILD_TARGET_NAME}" PROPERTY TRANSITIVE_DEPENDENCIES)
|
|
endif()
|
|
# CMake claims that all generated files are marked generated. This asserts this fact.
|
|
get_target_property(ALL_GENERATED "${BUILD_TARGET_NAME}" AC_GENERATED)
|
|
foreach(SOURCE IN LISTS ALL_GENERATED)
|
|
get_source_file_property(IS_GENERATED ${SOURCE} GENERATED)
|
|
fprime_cmake_ASSERT("${SOURCE} is not marked generated." IS_GENERATED)
|
|
endforeach()
|
|
|
|
# Set variables in parent scope for this run's results
|
|
set(AUTOCODER_GENERATED "${AUTOCODER_GENERATED_VALUES}" PARENT_SCOPE)
|
|
set(AUTOCODER_GENERATED_BUILD_SOURCES "${AUTOCODER_GENERATED_BUILD_SOURCES_VALUES}" PARENT_SCOPE)
|
|
set(AUTOCODER_GENERATED_AUTOCODER_INPUTS "${AUTOCODER_GENERATED_AUTOCODER_INPUTS_VALUES}" PARENT_SCOPE)
|
|
set(AUTOCODER_DEPENDENCIES "${AUTOCODER_DEPENDENCIES_VALUES}" PARENT_SCOPE)
|
|
set(AUTOCODER_GENERATED_OTHER "${AUTOCODER_GENERATED_OTHER_VALUES}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
####
|
|
# run_ac:
|
|
#
|
|
# Run the autocoder across the set of source files, SOURCES, and the previously generated sources, GENERATED_SOURCES.
|
|
# This will filter the SOURCES and GENERATED_SOURCES down to the handled set. Then for single-input autocoders, it runs
|
|
# the autocoder one input at a time, otherwise it runs the autocoder once on all inputs.
|
|
#
|
|
# AUTOCODER_CMAKE: cmake file containing autocoder definition
|
|
# SOURCES: sources input to run on the autocoder
|
|
####
|
|
function(run_ac BUILD_TARGET_NAME AUTOCODER_CMAKE SOURCES GENERATED_FILE_LIST HASH)
|
|
plugin_include_helper(AUTOCODER_NAME "${AUTOCODER_CMAKE}" is_supported setup_autocode get_generated_files get_dependencies)
|
|
# Normalize and filter source paths so that what we intend to run is in a standard form
|
|
normalize_paths(AC_INPUT_SOURCES "${SOURCES}")
|
|
_filter_sources(AC_INPUT_SOURCES "${AC_INPUT_SOURCES}")
|
|
|
|
# Break early if there are no sources, no need to autocode nothing
|
|
if (NOT AC_INPUT_SOURCES)
|
|
fprime_cmake_debug_message("[Autocode/${AUTOCODER_NAME}] No sources detected")
|
|
return()
|
|
endif()
|
|
|
|
# Check if this autocoder has been run before by comparing the hash of inputs. This allows us to skip running
|
|
# at a previous time. If so, skip autocoder and use old results
|
|
string(SHA1 "SRCS_HASH" "${AC_INPUT_SOURCES};${AUTOCODER_CMAKE}")
|
|
|
|
# Check if we have a previously stored hash and compare it
|
|
get_property(STORED_HASH TARGET "${BUILD_TARGET_NAME}" PROPERTY "${AUTOCODER_NAME}_SRCS_HASH")
|
|
get_property(HASH_SET TARGET "${BUILD_TARGET_NAME}" PROPERTY "${AUTOCODER_NAME}_SRCS_HASH" SET)
|
|
|
|
# If we have not run this autocoder before, or if the hash has changed, run the autocoder
|
|
if (NOT HASH_SET)
|
|
# Store the hash for future runs
|
|
set_property(TARGET "${BUILD_TARGET_NAME}" PROPERTY "${AUTOCODER_NAME}_SRCS_HASH" "${SRCS_HASH}")
|
|
|
|
_describe_autocoder_prep("${AUTOCODER_NAME}" "${AC_INPUT_SOURCES}")
|
|
|
|
# Find the one variable set in the autocoder
|
|
get_property(HANDLES_INDIVIDUAL_SOURCES_SET GLOBAL PROPERTY "${AUTOCODER_NAME}_HANDLES_INDIVIDUAL_SOURCES" SET)
|
|
if (NOT HANDLES_INDIVIDUAL_SOURCES_SET)
|
|
message(FATAL_ERROR "${AUTOCODER_CMAKE} did not call one of the autocoder_setup_for_*_sources functions")
|
|
endif()
|
|
get_property(HANDLES_INDIVIDUAL_SOURCES GLOBAL PROPERTY "${AUTOCODER_NAME}_HANDLES_INDIVIDUAL_SOURCES")
|
|
|
|
# Handles individual/multiple source handling
|
|
if (HANDLES_INDIVIDUAL_SOURCES)
|
|
foreach(SOURCE IN LISTS AC_INPUT_SOURCES)
|
|
__ac_process_sources("${BUILD_TARGET_NAME}" "${SOURCE}")
|
|
endforeach()
|
|
else()
|
|
__ac_process_sources("${BUILD_TARGET_NAME}" "${AC_INPUT_SOURCES}")
|
|
endif()
|
|
else()
|
|
# Assert runs are identical for the same autocoder
|
|
fprime_cmake_ASSERT("Hash mismatch for autocoder ${AUTOCODER_NAME}: stored '${STORED_HASH}' vs calculated '${SRCS_HASH}'"
|
|
"${STORED_HASH}" STREQUAL "${SRCS_HASH}")
|
|
endif()
|
|
|
|
# Read autocoder outputs from properties using the centralized variable lists
|
|
set(ALL_AUTOCODER_VARIABLES ${FPRIME_AUTOCODER_REQUIRED} ${FPRIME_AUTOCODER_OPTIONAL} AUTOCODER_GENERATED)
|
|
|
|
# Process each autocoder variable and append to target properties with the same name
|
|
foreach(VARIABLE_NAME IN LISTS ALL_AUTOCODER_VARIABLES)
|
|
get_property(VARIABLE_VALUES TARGET "${BUILD_TARGET_NAME}" PROPERTY "${AUTOCODER_NAME}_${VARIABLE_NAME}")
|
|
if (VARIABLE_VALUES)
|
|
append_list_property("${VARIABLE_VALUES}" TARGET "${BUILD_TARGET_NAME}" PROPERTY "${HASH}_${VARIABLE_NAME}")
|
|
endif()
|
|
endforeach()
|
|
_describe_autocoder_run("${AUTOCODER_NAME}")
|
|
|
|
endfunction(run_ac)
|
|
|
|
####
|
|
# Function `_describe_autocoder_prep`:
|
|
#
|
|
# Describes the inputs into an autocoder run. Does nothing unless CMAKE_DEBUG_OUTPUT is ON. Run before running the
|
|
# autocoder
|
|
#
|
|
# AUTOCODER_NAME: name of autocoder being run
|
|
# AC_INPUT_SOURCES: input files to autocoder
|
|
####
|
|
function(_describe_autocoder_prep AUTOCODER_NAME AC_INPUT_SOURCES)
|
|
# Start by displaying inputs to autocoders
|
|
fprime_cmake_debug_message("[Autocode/${AUTOCODER_NAME}] Autocoding Input Sources:")
|
|
foreach(SOURCE IN LISTS AC_INPUT_SOURCES)
|
|
fprime_cmake_debug_message("[Autocode/${AUTOCODER_NAME}] ${SOURCE}")
|
|
endforeach()
|
|
endfunction()
|
|
|
|
####
|
|
# Function `_describe_autocoder_run`:
|
|
#
|
|
# Describe the results of an autocoder run. Does nothing unless CMAKE_DEBUG_OUTPUT is ON. Must have run the autocoder
|
|
# already and set the properties.
|
|
#
|
|
# AUTOCODER_NAME: name of autocoder being described
|
|
####
|
|
function(_describe_autocoder_run AUTOCODER_NAME)
|
|
# When actually generating items, explain what is done and why
|
|
if (CMAKE_DEBUG_OUTPUT)
|
|
# Create a map of property names to display names
|
|
set(PROPERTY_DISPLAY_NAMES)
|
|
list(APPEND PROPERTY_DISPLAY_NAMES "AUTOCODER_GENERATED" "Generated Files")
|
|
list(APPEND PROPERTY_DISPLAY_NAMES "AUTOCODER_GENERATED_BUILD_SOURCES" "New Build Sources")
|
|
list(APPEND PROPERTY_DISPLAY_NAMES "AUTOCODER_GENERATED_AUTOCODER_INPUTS" "Additional Autocode Inputs")
|
|
list(APPEND PROPERTY_DISPLAY_NAMES "AUTOCODER_GENERATED_OTHER" "Other Generated Files")
|
|
list(APPEND PROPERTY_DISPLAY_NAMES "AUTOCODER_DEPENDENCIES" "Module Dependencies")
|
|
|
|
# Process all variables from the FPRIME_AUTOCODER lists plus AUTOCODER_GENERATED
|
|
set(ALL_AUTOCODER_VARIABLES ${FPRIME_AUTOCODER_REQUIRED} ${FPRIME_AUTOCODER_OPTIONAL} AUTOCODER_GENERATED)
|
|
|
|
foreach(VARIABLE_NAME IN LISTS ALL_AUTOCODER_VARIABLES)
|
|
# Find the display name for this variable
|
|
list(FIND PROPERTY_DISPLAY_NAMES "${VARIABLE_NAME}" NAME_INDEX)
|
|
if (NAME_INDEX GREATER_EQUAL 0)
|
|
math(EXPR DISPLAY_INDEX "${NAME_INDEX} + 1")
|
|
list(GET PROPERTY_DISPLAY_NAMES ${DISPLAY_INDEX} DISPLAY_NAME)
|
|
|
|
get_property(PROPERTY_VALUES TARGET "${BUILD_TARGET_NAME}" PROPERTY "${AUTOCODER_NAME}_${VARIABLE_NAME}")
|
|
if (PROPERTY_VALUES)
|
|
fprime_cmake_debug_message("[Autocode/${AUTOCODER_NAME}] ${DISPLAY_NAME}:")
|
|
foreach(VALUE IN LISTS PROPERTY_VALUES)
|
|
fprime_cmake_debug_message("[Autocode/${AUTOCODER_NAME}] ${VALUE}")
|
|
endforeach()
|
|
endif()
|
|
endif()
|
|
endforeach()
|
|
endif()
|
|
endfunction()
|
|
|
|
####
|
|
# _filter_sources:
|
|
#
|
|
# Filters sources down to the ones supported by the active autocoder. It is an error to call this helper function before
|
|
# including an autocoder's CMake file and thus setting the active autocoder. Helper function.
|
|
#
|
|
# OUTPUT_NAME: name of output variable to set in parent scope
|
|
# ...: any number of arguments containing lists of sources
|
|
####
|
|
function(_filter_sources OUTPUT_NAME)
|
|
set(OUTPUT_LIST)
|
|
# Loop over the list and check
|
|
foreach (SOURCE_LIST IN LISTS ARGN)
|
|
foreach(SOURCE IN LISTS SOURCE_LIST)
|
|
cmake_language(CALL "${AUTOCODER_NAME}_is_supported" "${SOURCE}")
|
|
if (IS_SUPPORTED)
|
|
list(APPEND OUTPUT_LIST "${SOURCE}")
|
|
endif()
|
|
endforeach()
|
|
endforeach()
|
|
set(${OUTPUT_NAME} "${OUTPUT_LIST}" PARENT_SCOPE)
|
|
endfunction(_filter_sources)
|
|
|
|
####
|
|
# __ac_process_sources:
|
|
#
|
|
# Process sources found in SOURCES list and sets up the autocoder to run on the sources by registering a rule to create
|
|
# those sources.
|
|
# SOURCES: source file list. Note: if the autocoder sets HANDLES_INDIVIDUAL_SOURCES this will be singular
|
|
####
|
|
function(__ac_process_sources BUILD_TARGET_NAME SOURCES)
|
|
# Loop through the variables from the various lists and make sure they are undefined
|
|
foreach(VARIABLE IN LISTS FPRIME_AUTOCODER_UNSUPPORTED FPRIME_AUTOCODER_REQUIRED FPRIME_AUTOCODER_OPTIONAL)
|
|
fprime_cmake_ASSERT("'${VARIABLE}' set to '${${VARIABLE}}' before call" NOT DEFINED ${VARIABLE})
|
|
endforeach()
|
|
# Run the generation setup when not requesting "info only"
|
|
cmake_language(CALL "${AUTOCODER_NAME}_setup_autocode" "${BUILD_TARGET_NAME}" "${SOURCES}")
|
|
|
|
# Check for removed support
|
|
foreach(VARIABLE IN LISTS FPRIME_AUTOCODER_UNSUPPORTED)
|
|
fprime_cmake_ASSERT("Unsupported '${VARIABLE}' set to '${${VARIABLE}}' by autocoder ${AUTOCODER_NAME}"
|
|
NOT DEFINED ${VARIABLE})
|
|
endforeach()
|
|
|
|
# Search through requirements ensuring one was set
|
|
set(AUTOCODER_MET_REQUIRED FALSE)
|
|
foreach(REQUIREMENT IN LISTS FPRIME_AUTOCODER_REQUIRED)
|
|
if (DEFINED ${REQUIREMENT})
|
|
list(APPEND AUTOCODER_GENERATED ${${REQUIREMENT}})
|
|
set(AUTOCODER_MET_REQUIRED TRUE)
|
|
endif()
|
|
endforeach()
|
|
fprime_cmake_ASSERT("Autocoder must define at least one of: ${FPRIME_AUTOCODER_REQUIRED}" AUTOCODER_MET_REQUIRED)
|
|
|
|
# Set autocoder output variables as target properties
|
|
foreach(VARIABLE IN LISTS FPRIME_AUTOCODER_REQUIRED FPRIME_AUTOCODER_OPTIONAL)
|
|
if (DEFINED ${VARIABLE})
|
|
append_list_property("${${VARIABLE}}" TARGET "${BUILD_TARGET_NAME}" PROPERTY "${AUTOCODER_NAME}_${VARIABLE}")
|
|
endif()
|
|
endforeach()
|
|
# Also set the calculated AUTOCODER_GENERATED
|
|
if (DEFINED AUTOCODER_GENERATED)
|
|
append_list_property("${AUTOCODER_GENERATED}" TARGET "${BUILD_TARGET_NAME}" PROPERTY "${AUTOCODER_NAME}_AUTOCODER_GENERATED")
|
|
endif()
|
|
endfunction()
|