Removes 1-to-1 relation of deployments and projects (#1994)

* Removes 1-to-1 relation of deployments and projects

* Fixing CMake UTs

* Making deployment subject to toolchain

* Fixing CI and minimum tools version

* Python formatting and fixing integration test run

* Fixing RPI CI path

* Fixing RPI remote run integration test
This commit is contained in:
M Starch 2023-05-17 14:26:17 -07:00 committed by GitHub
parent 23fe2aa758
commit afacd2fe2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 90 additions and 107 deletions

View File

@ -11,7 +11,7 @@ on:
branches: [ master, devel, release/v3.0.0 ]
env:
RPI_TOOLCHAIN_DIR: /tmp/rpi-toolchain
DICTIONARY_PATH: build-artifacts/raspberrypi/dict/RPITopologyAppDictionary.xml
DICTIONARY_PATH: build-artifacts/raspberrypi/RPI/dict/RPITopologyAppDictionary.xml
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
RPI:
@ -53,7 +53,7 @@ jobs:
with:
name: rpi-build
- name: RPI Integration Tests
run: chmod +x RPI/build-artifacts/raspberrypi/bin/RPI; /bin/bash ci/tests/RPI-Ints.bash
run: chmod +x RPI/build-artifacts/raspberrypi/RPI/bin/RPI; /bin/bash ci/tests/RPI-Ints.bash
# Archive the outputs
- name: 'Archive Logs'
uses: actions/upload-artifact@v3

View File

@ -9,5 +9,7 @@ set(SOURCE_FILES
"${CMAKE_CURRENT_LIST_DIR}/TypeDemo.fpp"
"${CMAKE_CURRENT_LIST_DIR}/TypeDemo.cpp"
)
set(MOD_DEPS
Os
)
register_fprime_module()

View File

@ -69,7 +69,7 @@ function integration_test_run {
mkdir -p "${LOG_DIR}/gds-logs"
# Start the GDS layer and give it time to run
echo "[INFO] Starting headless GDS layer"
fprime-gds -n --dictionary "${ROOTDIR}/"*"/dict/${BINARY}TopologyAppDictionary.xml" -g none -l "${LOG_DIR}/gds-logs" 1>${LOG_DIR}/gds-logs/fprime-gds.stdout.log 2>${LOG_DIR}/gds-logs/fprime-gds.stderr.log &
fprime-gds -n --dictionary "${ROOTDIR}/"*"/${BINARY}/dict/${BINARY}TopologyAppDictionary.xml" -g none -l "${LOG_DIR}/gds-logs" 1>${LOG_DIR}/gds-logs/fprime-gds.stdout.log 2>${LOG_DIR}/gds-logs/fprime-gds.stderr.log &
GDS_PID=$!
# run the app with valgrind in the background
if command -v valgrind &> /dev/null
@ -82,9 +82,9 @@ function integration_test_run {
--show-leak-kinds=all \
--track-origins=yes \
--log-file=${LOG_DIR}/gds-logs/valgrind.log \
${ROOTDIR}/*/bin/${BINARY} -a 127.0.0.1 -p 50000 1>${LOG_DIR}/gds-logs/${BINARY}.stdout.log 2>${LOG_DIR}/gds-logs/${BINARY}.stderr.log &
${ROOTDIR}/*/${BINARY}/bin/${BINARY} -a 127.0.0.1 -p 50000 1>${LOG_DIR}/gds-logs/${BINARY}.stdout.log 2>${LOG_DIR}/gds-logs/${BINARY}.stderr.log &
else
${ROOTDIR}/*/bin/${BINARY} -a 127.0.0.1 -p 50000 1>${LOG_DIR}/gds-logs/${BINARY}.stdout.log 2>${LOG_DIR}/gds-logs/${BINARY}.stderr.log &
${ROOTDIR}/*/${BINARY}/bin/${BINARY} -a 127.0.0.1 -p 50000 1>${LOG_DIR}/gds-logs/${BINARY}.stdout.log 2>${LOG_DIR}/gds-logs/${BINARY}.stderr.log &
fi
VALGRIND_PID=$!

View File

@ -89,6 +89,9 @@ endmacro()
# https://cmake.org/cmake/help/latest/command/add_fprime_subdirectory.html
####
function(add_fprime_subdirectory FP_SOURCE_DIR)
get_module_name("${FP_SOURCE_DIR}")
set(FPRIME_CURRENT_MODULE "${MODULE_NAME}")
# Check if the binary and source directory are in agreement. If they agree, then normally add
# the directory, as no adjustments need be made.
get_filename_component(CBD_NAME "${CMAKE_CURRENT_BINARY_DIR}" NAME)
@ -115,13 +118,13 @@ endfunction(add_fprime_subdirectory)
#
# Required variables (defined in calling scope):
#
# - **SOURCE_FILES:** cmake list of input source files. Place any "*.fpp", "*Ai.xml", "*.c", "*.cpp"
# - **SOURCE_FILES:** cmake list of input source files. Place any "*.fpp", "*.c", "*.cpp"
# etc files here. This list will be split into autocoder inputs, and hand-coded sources based on the name/type.
#
# **i.e.:**
# ```
# set(SOURCE_FILES
# MyComponentAi.xml
# MyComponent.fpp
# SomeFile.cpp
# MyComponentImpl.cpp)
# ```
@ -148,7 +151,7 @@ endfunction(add_fprime_subdirectory)
#
# ```
# set(SOURCE_FILE
# MyComponentAi.xml
# MyComponent.fpp
# SomeFile.cpp
# MyComponentImpl.cpp)
#
@ -171,7 +174,7 @@ endfunction(add_fprime_subdirectory)
#
# ```
# set(SOURCE_FILE
# MyComponentAi.xml)
# MyComponent.fpp)
#
# register_fprime_module()
# ```
@ -184,7 +187,7 @@ endfunction(add_fprime_subdirectory)
#
# ```
# set(SOURCE_FILE
# MyComponentAi.xml
# MyComponent.fpp
# SomeFile.cpp
# MyComponentImpl.cpp)
#
@ -204,7 +207,12 @@ function(register_fprime_module)
if (${ARGC} GREATER 0)
set(MODULE_NAME ${ARGV0})
else()
get_module_name("${CMAKE_CURRENT_LIST_DIR}")
# Check to be sure before using
if (NOT DEFINED FPRIME_CURRENT_MODULE)
message(FATAL_ERROR "FPRIME_CURRENT_MODULE not defined. Please supply name to: register_fprime_module()")
endif()
set(MODULE_NAME ${FPRIME_CURRENT_MODULE})
endif()
# Explicit call to module register
generate_library("${MODULE_NAME}" "${SOURCE_FILES}" "${MOD_DEPS}")
@ -227,14 +235,14 @@ endfunction(register_fprime_module)
#
#
# - **EXECUTABLE_NAME:** (optional) executable name supplied. If not set, nor passed in, then
# PROJECT_NAME from the CMake definitions is used.
# FPRIME_CURRENT_MODULE from the CMake definitions is used.
#
# - **SOURCE_FILES:** cmake list of input source files. Place any "*Ai.xml", "*.c", "*.cpp"
# - **SOURCE_FILES:** cmake list of input source files. Place any "*.fpp", "*.c", "*.cpp"
# etc. files here. This list will be split into autocoder inputs and sources.
# **i.e.:**
# ```
# set(SOURCE_FILES
# MyComponentAi.xml
# MyComponent.fpp
# SomeFile.cpp
# MyComponentImpl.cpp)
# ```
@ -275,17 +283,20 @@ endfunction(register_fprime_module)
# ```
####
function(register_fprime_executable)
get_module_name("${CMAKE_CURRENT_LIST_DIR}")
if (NOT DEFINED SOURCE_FILES AND NOT DEFINED MOD_DEPS)
message(FATAL_ERROR "SOURCE_FILES or MOD_DEPS must be defined when registering an executable")
elseif (NOT DEFINED EXECUTABLE_NAME AND ARGC LESS 1 AND TARGET "${MODULE_NAME}")
elseif (NOT DEFINED EXECUTABLE_NAME AND ARGC LESS 1 AND TARGET "${FPRIME_CURRENT_MODULE}")
message(FATAL_ERROR "EXECUTABLE_NAME must be set or passed in. Use register_fprime_deployment() for deployments")
endif()
# MODULE_NAME is used for the executable name, unless otherwise specified.
if(NOT DEFINED EXECUTABLE_NAME AND ARGC GREATER 0)
set(EXECUTABLE_NAME "${ARGV0}")
elseif(NOT DEFINED EXECUTABLE_NAME)
set(EXECUTABLE_NAME "${MODULE_NAME}")
# Check to be sure before using
if (NOT DEFINED FPRIME_CURRENT_MODULE)
message(FATAL_ERROR "FPRIME_CURRENT_MODULE not defined. Please supply name to: register_fprime_executable()")
endif()
set(EXECUTABLE_NAME "${FPRIME_CURRENT_MODULE}")
endif()
get_nearest_build_root(${CMAKE_CURRENT_LIST_DIR})
generate_executable("${EXECUTABLE_NAME}" "${SOURCE_FILES}" "${MOD_DEPS}")
@ -307,12 +318,12 @@ endfunction(register_fprime_executable)
#
# Required variables (defined in calling scope):
#
# - **SOURCE_FILES:** cmake list of input source files. Place any "*Ai.xml", "*.c", "*.cpp"
# - **SOURCE_FILES:** cmake list of input source files. Place any "*.fpp", "*.c", "*.cpp"
# etc. files here. This list will be split into autocoder inputs and sources.
# **i.e.:**
# ```
# set(SOURCE_FILES
# MyComponentAi.xml
# MyComponent.fpp
# SomeFile.cpp
# MyComponentImpl.cpp)
# ```
@ -324,7 +335,7 @@ endfunction(register_fprime_executable)
# **i.e.:**
# ```
# set(MOD_DEPS
# ${PROJECT_NAME}/Top
# ${FPRIME_CURRENT_MODULE}/Top
# Module1
# Module2
# -lpthread)
@ -332,36 +343,34 @@ endfunction(register_fprime_executable)
#
# **Note:** this operates almost identically to `register_fprime_executable` and `register_fprime_module` with respect
# to the variable definitions. The difference is deployment targets will be run (e.g. dictionary generation), and the
# executable binary will be named for ${PROJECT_NAME}.
# executable binary will be named after the module, or if project when defined directly in a project CMakeLists.txt
#
# ### Standard fprime Deployment Example ###
#
# To create a standard fprime deployment, an executable needs to be created. This executable
# uses the CMake PROJECT_NAME as the executable name. Thus, it can be created with the following
# source lists. In most fprime deployments, some modules must be specified as they don't tie
# directly to an Ai.xml.
# To create a standard fprime deployment, an the user must call `register_fprime_deployment()` after defining
# SOURCE_FILES and MOD_DEPS.
#
# ```
# set(SOURCE_FILES
# "${CMAKE_CURRENT_LIST_DIR}/Main.cpp"
# )
# # Note: supply non-explicit dependencies here. These are implementations to an XML that is
# # defined in a different module.
# # Note: supply dependencies that cannot be detected via the model here.
# set(MOD_DEPS
# ${PROJECT_NAME}/Top
# ${FPRIME_CURRENT_MODULE}/Top
# )
# register_fprime_deployment()
# ```
####
function(register_fprime_deployment)
get_module_name("${CMAKE_CURRENT_LIST_DIR}")
if (NOT DEFINED SOURCE_FILES AND NOT DEFINED MOD_DEPS)
message(FATAL_ERROR "SOURCE_FILES or MOD_DEPS must be defined when registering an executable")
elseif(NOT MODULE_NAME STREQUAL PROJECT_NAME)
message(WARNING "Project name ${PROJECT_NAME} does not match expected name ${MODULE_NAME}")
endif()
# Fallback to PROJECT_NAME when it is not set
if (NOT DEFINED FPRIME_CURRENT_MODULE)
set(FPRIME_CURRENT_MODULE "${PROJECT_NAME}")
endif()
get_nearest_build_root(${CMAKE_CURRENT_LIST_DIR})
generate_deployment("${PROJECT_NAME}" "${SOURCE_FILES}" "${MOD_DEPS}")
generate_deployment("${FPRIME_CURRENT_MODULE}" "${SOURCE_FILES}" "${MOD_DEPS}")
endfunction(register_fprime_deployment)
@ -382,14 +391,14 @@ endfunction(register_fprime_deployment)
# - **UT_NAME:** (optional) executable name supplied. If not supplied, or passed in, then
# the <MODULE_NAME>_ut_exe will be used.
#
# - **UT_SOURCE_FILES:** cmake list of UT source files. Place any "*Ai.xml", "*.c", "*.cpp"
# - **UT_SOURCE_FILES:** cmake list of UT source files. Place any "*.fpp", "*.c", "*.cpp"
# etc. files here. This list will be split into autocoder inputs or sources. These sources only apply to the unit
# test.
#
# **i.e.:**
# ```
# set(UT_SOURCE_FILES
# MyComponentAi.xml
# MyComponent.fpp
# SomeFile.cpp
# MyComponentImpl.cpp)
# ```
@ -415,13 +424,12 @@ endfunction(register_fprime_deployment)
#
# ### Unit-Test Example ###
#
# A standard unit test defines only UT_SOURCES. These sources have the test cpp files and the module
# Ai.xml of the module being tested. This is used to generate the GTest and TesterBase files from this
# Ai.xml. The other UT source files define the implementation of the test.
# A standard unit test defines only UT_SOURCES. These sources have the test cpp files and the model
# .fpp of the module being tested. This is used to generate the GTest harness.
#
# ```
# set(UT_SOURCE_FILES
# "${FPRIME_FRAMEWORK_PATH}/Svc/CmdDispatcher/CommandDispatcherComponentAi.xml"
# "${FPRIME_FRAMEWORK_PATH}/Svc/CmdDispatcher/CommandDispatcher.fpp"
# "${CMAKE_CURRENT_LIST_DIR}/test/ut/CommandDispatcherTester.cpp"
# "${CMAKE_CURRENT_LIST_DIR}/test/ut/CommandDispatcherImplTester.cpp"
# )

View File

@ -26,13 +26,14 @@ if (FPRIME_ENABLE_FRAMEWORK_UTS)
endif()
# Faux libraries used as interfaces to non-autocoded fpp items
add_library(Fpp INTERFACE)
set(FPRIME_CURRENT_MODULE config)
add_subdirectory("${FPRIME_CONFIG_DIR}" "${CMAKE_BINARY_DIR}/config")
add_subdirectory("${FPRIME_FRAMEWORK_PATH}/Fw/" "${CMAKE_BINARY_DIR}/F-Prime/Fw")
add_subdirectory("${FPRIME_FRAMEWORK_PATH}/Svc/" "${CMAKE_BINARY_DIR}/F-Prime/Svc")
add_subdirectory("${FPRIME_FRAMEWORK_PATH}/Os/" "${CMAKE_BINARY_DIR}/F-Prime/Os")
add_subdirectory("${FPRIME_FRAMEWORK_PATH}/Drv/" "${CMAKE_BINARY_DIR}/F-Prime/Drv")
add_subdirectory("${FPRIME_FRAMEWORK_PATH}/CFDP/" "${CMAKE_BINARY_DIR}/F-Prime/CFDP")
add_subdirectory("${FPRIME_FRAMEWORK_PATH}/Utils/" "${CMAKE_BINARY_DIR}/F-Prime/Utils")
set(_FP_CORE_PACKAGES Fw Svc Os Drv CFDP Utils)
foreach (_FP_PACKAGE_DIR IN LISTS _FP_CORE_PACKAGES)
set(FPRIME_CURRENT_MODULE "${_FP_PACKAGE_DIR}")
add_subdirectory("${FPRIME_FRAMEWORK_PATH}/${_FP_PACKAGE_DIR}/" "${CMAKE_BINARY_DIR}/F-Prime/${_FP_PACKAGE_DIR}")
endforeach ()
unset(FPRIME_CURRENT_MODULE)
# Always enable UTs for a project
set(__FPRIME_NO_UT_GEN__ OFF)
foreach (LIBRARY_DIR IN LISTS FPRIME_LIBRARY_LOCATIONS)

View File

@ -69,7 +69,6 @@ register_fprime_target(target/fpp_locs)
register_fprime_target(target/build)
register_fprime_build_autocoder(autocoder/fpp)
register_fprime_build_autocoder(autocoder/ai_xml)
register_fprime_build_autocoder(autocoder/deployment_validation)
register_fprime_build_autocoder(autocoder/packets)
register_fprime_target(target/noop)
register_fprime_target(target/version)

View File

@ -94,8 +94,9 @@ function(ai_xml_setup_autocode AC_INPUT_FILE)
# Check type and respond
if(XML_LOWER_TYPE STREQUAL "topologyapp")
# Are we excluding the generated files or not
set_property(GLOBAL PROPERTY "${PROJECT_NAME}_FPRIME_DICTIONARY_FILE"
"${CMAKE_CURRENT_BINARY_DIR}/${OBJ_NAME}${XML_TYPE}Dictionary.xml")
set(FPRIME_CURRENT_DICTIONARY_FILE "${CMAKE_CURRENT_BINARY_DIR}/${OBJ_NAME}${XML_TYPE}Dictionary.xml"
CACHE INTERNAL "" FORCE
)
if (EXCLUDE_TOP_ACS)
set(REMOVALS "${GENERATED_FILES}")
set(GENERATED_FILES "${CMAKE_CURRENT_BINARY_DIR}/${OBJ_NAME}${XML_TYPE}Dictionary.xml")

View File

@ -1,47 +0,0 @@
####
# autocoder/deployment_validation.cmake
#
# An autocoder that performs validation steps on the deployment to ensure that it is well-formed. This will produce
# warning output when validation fails.
#
# Note: this autocoder is for validation purposes and DOES NOT produce any autocoded files.
#####
include(utilities)
include(autocoder/helpers)
autocoder_setup_for_multiple_sources()
####
# `deployment_validation_is_supported`:
#
# Required function, processes .fpp files
####
function(deployment_validation_is_supported AC_INPUT_FILE)
autocoder_support_by_suffix(".fpp" "${AC_INPUT_FILE}") # No re-scan, already done in FPP
endfunction (deployment_validation_is_supported)
####
# `deployment_validation_is_supported`:
#
# Required function, look for .fpp files defining a topology block and ensure the following equivalence:
# ${PROJECT_NAME} == topology name
# No files are produced by this autocoder. It runs to validate items as part of the autocoder system.
#
####
function(deployment_validation_setup_autocode AC_INPUT_FILES)
foreach(AC_FILE IN LISTS AC_INPUT_FILES)
file(READ "${AC_FILE}" FILE_TEXT)
# Does this file match the pattern (module { topology {} })
if (NOT FPRIME_SKIP_PROJECT_NAME_VALIDATION AND
FILE_TEXT MATCHES "^(.*\n)?[^\n#@]*topology +([a-zA-Z0-9_]+)" AND
NOT CMAKE_MATCH_2 STREQUAL "${PROJECT_NAME}")
message(WARNING
"Cmake project name '${PROJECT_NAME}' does not match topology name '${CMAKE_MATCH_2}'\n"
" Project CMakeLists.txt: ${PROJECT_SOURCE_DIR}/CMakeLists.txt\n"
" Topology FPP model: ${AC_FILE}\n"
)
endif()
endforeach()
# This autocoder specifically does not produce any autocoder output
set(AUTOCODER_GENERATED "" PARENT_SCOPE)
endfunction(deployment_validation_setup_autocode)

View File

@ -43,12 +43,16 @@ function(install_add_deployment_target MODULE TARGET SOURCES DEPENDENCIES FULL_D
set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY TRUE)
_install_real_helper(INSTALL_DEPENDENCIES "${FULL_DEPENDENCIES}")
install(TARGETS ${MODULE} ${INSTALL_DEPENDENCIES}
RUNTIME DESTINATION ${TOOLCHAIN_NAME}/bin
LIBRARY DESTINATION ${TOOLCHAIN_NAME}/lib
ARCHIVE DESTINATION ${TOOLCHAIN_NAME}/lib/static)
get_property(DICTIONARY GLOBAL PROPERTY "${PROJECT_NAME}_FPRIME_DICTIONARY_FILE")
install(FILES ${DICTIONARY} DESTINATION ${TOOLCHAIN_NAME}/dict)
add_custom_command(TARGET "${MODULE}" POST_BUILD COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --target install)
RUNTIME DESTINATION ${TOOLCHAIN_NAME}/${MODULE}/bin
COMPONENT ${MODULE}
LIBRARY DESTINATION ${TOOLCHAIN_NAME}/${MODULE}/lib
COMPONENT ${MODULE}
ARCHIVE DESTINATION ${TOOLCHAIN_NAME}/${MODULE}/lib/static
COMPONENT ${MODULE}
)
install(FILES ${FPRIME_CURRENT_DICTIONARY_FILE} DESTINATION ${TOOLCHAIN_NAME}/${MODULE}/dict COMPONENT ${MODULE})
add_custom_command(TARGET "${MODULE}" POST_BUILD COMMAND "${CMAKE_COMMAND}"
-DCMAKE_INSTALL_COMPONENT=${MODULE} -P${CMAKE_BINARY_DIR}/cmake_install.cmake)
endfunction()
# Install is per-deployment, a module-by-module variant does not make sense

View File

@ -87,6 +87,7 @@ def test_feature_targets(FEATURE_BUILD):
def test_feature_installation(FEATURE_BUILD):
"""Run reference and assert reference targets exit"""
cmake.assert_process_success(FEATURE_BUILD)
deployment_name = "TestDeployment"
for module in settings.FRAMEWORK_MODULES + [
"Svc_CmdDispatcher",
"TestLibrary_TestComponent",
@ -96,12 +97,17 @@ def test_feature_installation(FEATURE_BUILD):
output_path = (
FEATURE_BUILD["install"]
/ platform.system()
/ deployment_name
/ "lib"
/ "static"
/ library_name
)
assert output_path.exists(), f"Failed to locate {library_name} in build output"
output_path = (
FEATURE_BUILD["install"] / platform.system() / "bin" / "TestDeployment"
FEATURE_BUILD["install"]
/ platform.system()
/ deployment_name
/ "bin"
/ deployment_name
)
assert output_path.exists(), "Failed to locate TestDeployment in build output"

View File

@ -46,9 +46,11 @@ def test_ref_installation(REF_BUILD):
library_name = (
f"lib{module}{'.so' if platform.system() != 'Darwin' else '.dylib'}"
)
output_path = REF_BUILD["install"] / platform.system() / "lib" / library_name
output_path = (
REF_BUILD["install"] / platform.system() / "Ref" / "lib" / library_name
)
assert output_path.exists(), f"Failed to locate {library_name} in build output"
output_path = REF_BUILD["install"] / platform.system() / "bin" / "Ref"
output_path = REF_BUILD["install"] / platform.system() / "Ref" / "bin" / "Ref"
assert output_path.exists(), "Failed to locate Ref in build output"
@ -58,6 +60,7 @@ def test_ref_dictionary(REF_BUILD):
output_path = (
REF_BUILD["install"]
/ platform.system()
/ "Ref"
/ "dict"
/ "RefTopologyAppDictionary.xml"
)

View File

@ -87,10 +87,15 @@ def test_unittest_installation(UT_BUILD):
for module in MODULES:
library_name = f"lib{module}.a"
output_path = (
UT_BUILD["install"] / platform.system() / "lib" / "static" / library_name
UT_BUILD["install"]
/ platform.system()
/ "Ref"
/ "lib"
/ "static"
/ library_name
)
assert output_path.exists(), f"Failed to locate {library_name} in build output"
output_path = UT_BUILD["install"] / platform.system() / "bin" / "Ref"
output_path = UT_BUILD["install"] / platform.system() / "Ref" / "bin" / "Ref"
assert output_path.exists(), "Failed to locate Ref in build output"
@ -100,6 +105,7 @@ def test_unittest_dictionary(UT_BUILD):
output_path = (
UT_BUILD["install"]
/ platform.system()
/ "Ref"
/ "dict"
/ "RefTopologyAppDictionary.xml"
)

View File

@ -16,7 +16,7 @@ Flask==2.2.2
Flask-Compress==1.13
Flask-RESTful==0.3.9
fprime-fpp==1.2.0
fprime-gds==3.2.0
fprime-gds==3.2.1a1
fprime-tools==3.2.0
gcovr==5.2
idna==3.4