From e5915089e915bafb3c3f43c5bde554f4b0fc2802 Mon Sep 17 00:00:00 2001 From: M Starch Date: Wed, 28 Jun 2023 20:28:29 -0700 Subject: [PATCH 01/10] Adding implementation in CMake and documentation --- .../test/ut/GroundInterfaceTester.hpp | 2 +- cmake/API.cmake | 66 ++++++++++- cmake/implementation.cmake | 103 ++++++++++++++++++ cmake/module.cmake | 11 +- cmake/platform/platform.cmake | 21 +++- cmake/target/build.cmake | 15 ++- cmake/toolchain/raspberrypi.cmake | 29 ++++- cmake/utilities.cmake | 4 +- docs/Design/package-implementations.md | 31 ++++++ 9 files changed, 264 insertions(+), 18 deletions(-) create mode 100644 cmake/implementation.cmake create mode 100644 docs/Design/package-implementations.md diff --git a/Svc/GroundInterface/test/ut/GroundInterfaceTester.hpp b/Svc/GroundInterface/test/ut/GroundInterfaceTester.hpp index ba7c4dd1a9..8e6aec7f9e 100644 --- a/Svc/GroundInterface/test/ut/GroundInterfaceTester.hpp +++ b/Svc/GroundInterface/test/ut/GroundInterfaceTester.hpp @@ -13,7 +13,7 @@ #ifndef TESTER_HPP #define TESTER_HPP -#include +#include #include "GroundInterfaceGTestBase.hpp" #include "Svc/GroundInterface/GroundInterface.hpp" diff --git a/cmake/API.cmake b/cmake/API.cmake index 823804212b..0b9573a1ff 100644 --- a/cmake/API.cmake +++ b/cmake/API.cmake @@ -12,6 +12,7 @@ # #### include_guard() +include(utilities) set(FPRIME_TARGET_LIST "" CACHE INTERNAL "FPRIME_TARGET_LIST: custom fprime targets" FORCE) set(FPRIME_UT_TARGET_LIST "" CACHE INTERNAL "FPRIME_UT_TARGET_LIST: custom fprime targets" FORCE) set(FPRIME_AUTOCODER_TARGET_LIST "" CACHE INTERNAL "FPRIME_AUTOCODER_TARGET_LIST: custom fprime targets" FORCE) @@ -96,6 +97,10 @@ function(add_fprime_subdirectory FP_SOURCE_DIR) get_module_name("${FP_SOURCE_DIR}") set(FPRIME_CURRENT_MODULE "${MODULE_NAME}") + # Unset all variables that carry special meaning as it is dangerous to pass them through + init_variables(SOURCE_FILES MOD_DEPS UT_SOURCE_FILES UT_MOD_DEPS EXECUTABLE_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) @@ -545,7 +550,7 @@ endmacro(register_fprime_list_helper) # the same thing. Note: make sure the directory is on the CMake include path to use the second form. # # **TARGET_FILE_PATH:** include path or file path file defining above functions -### +#### macro(register_fprime_build_autocoder TARGET_FILE_PATH) # Normal registered targets don't run in prescan if (CMAKE_DEBUG_OUTPUT) @@ -554,6 +559,65 @@ macro(register_fprime_build_autocoder TARGET_FILE_PATH) register_fprime_list_helper("${TARGET_FILE_PATH}" FPRIME_AUTOCODER_TARGET_LIST) endmacro(register_fprime_build_autocoder) + +#### +# Function `require_fprime_implementation`: +# +# Designates that the current module requires a separate implementation in order for it to function properly. As an +# example, Os requires an implementation of `Os_Task`. These implementations must be set via +# `choose_fprime_implementation` in the platform and may be overridden in in the executable/deployment. +# +# **IMPLEMENTATION:** implementation module name that must be covered +#### +function(require_fprime_implementation IMPLEMENTATION) + resolve_dependencies(IMPLEMENTATION "${IMPLEMENTATION}") + append_list_property("${IMPLEMENTATION}" GLOBAL PROPERTY "REQUIRED_IMPLEMENTATIONS") + append_list_property("${FPRIME_CURRENT_MODULE}" GLOBAL PROPERTY "${IMPLEMENTATION}_REQUESTERS") +endfunction() + +#### +# Function `register_fprime_implementation`: +# +# Designates that the given implementor implements the required implementation. As an example Os_Task_Posix implements +# Os_Task. These implementations must be set via +## `choose_fprime_implementation` in the platform and may be overridden in in the executable/deployment. +# +# **IMPLEMENTATION:** implementation module name that is implemented by IMPLEMENTOR +# **IMPLEMENTOR:** implementor of IMPLEMENTATION +#### +function(register_fprime_implementation IMPLEMENTATION IMPLEMENTOR) + resolve_dependencies(IMPLEMENTATION "${IMPLEMENTATION}") + resolve_dependencies(IMPLEMENTOR "${IMPLEMENTOR}") + append_list_property("${IMPLEMENTOR}" GLOBAL PROPERTY "${IMPLEMENTATION}_IMPLEMENTORS") +endfunction() +#### +# Function `choose_fprime_implementation`: +# +# Designates that the given implementor is the selected implementor for the needed implementation. Platforms must call +# this function once for each defined IMPLEMENTATION. An executable/deployment/unit-test may call this function to set +# a specific implementor for any needed implementation +# +# **IMPLEMENTATION:** implementation module name that is implemented by IMPLEMENTOR +# **IMPLEMENTOR:** implementor of IMPLEMENTATION +#### +function(choose_fprime_implementation IMPLEMENTATION IMPLEMENTOR) + resolve_dependencies(IMPLEMENTATION "${IMPLEMENTATION}") + resolve_dependencies(IMPLEMENTOR "${IMPLEMENTOR}") + # Check for passed in module name + if (ARGC EQUAL 3) + set(ACTIVE_MODULE "${ARGV2}") + elseif (FPRIME_CURRENT_MODULE) + set(ACTIVE_MODULE "${FPRIME_CURRENT_MODULE}") + elseif(FPRIME_PLATFORM) + set(ACTIVE_MODULE "${FPRIME_PLATFORM}") + else() + message(FATAL_ERROR "Cannot call 'choose_fprime_implementation' outside an fprime module or platform CMake file") + endif() + set_property(GLOBAL PROPERTY "${IMPLEMENTATION}_${ACTIVE_MODULE}" "${IMPLEMENTOR}") + append_list_property("${IMPLEMENTATION}" GLOBAL PROPERTY "REQUIRED_IMPLEMENTATIONS") + append_list_property("${IMPLEMENTOR}" GLOBAL PROPERTY "${IMPLEMENTATION}_IMPLEMENTORS") +endfunction() + #### Documentation links # Next Topics: # - Setting Options: [Options](Options.md) are used to vary a CMake build. diff --git a/cmake/implementation.cmake b/cmake/implementation.cmake new file mode 100644 index 0000000000..c0715d8e0e --- /dev/null +++ b/cmake/implementation.cmake @@ -0,0 +1,103 @@ +#### +# implementation.cmake: +# +# Functions used to handle different registered implementations of various cmake packages within F´. The process breaks +# down as follows: +# 1. A module will "require" an implementation X +# 2. A number of modules will "register" as an implementation of X +# 3. A platform package will "choose" a single implementation for X +# 4. Linked modules (executable, deployment, unit-test) may override and "choose" an alternate implementation for X +# +# For example: Os requires an implementation of Os_File. Os_File_Posix implements Os_File. The Linux platform chooses +# Os_File_Posix as the implementation of Os_File. This applies to all linked modules in the system. Os_Baremetal_ut may +# then override this choose using Os_File_MicroFs instead. +# +# > All required implementations apply system-wide. Platforms specifically disallowing use of a given package should +# > "choose" the special implementation "None" to bypass the check. +# +# Internally this uses several properties. Each of these properties are GLOBAL such that these may be set before the +# various targets have been explicitly created. These pro +# +# +#### +include_guard() + +#### +# Function `adjust_implementation_choices`: +# +# When a target is declared with a different name than the module name, we need to pull the implementation choices into +# a property for the declared target instead of the inferred target. This is done by reading each implementation choice +# and setting the new property. +# +# Args: +# INFERRED: inferred target name (FPRIME_CURRENT_MODULE) +# DECLARED: real target name +#### +function(remap_implementation_choices INFERRED DECLARED) + # Check and setup implementors + get_property(LOCAL_REQUIRED GLOBAL PROPERTY "REQUIRED_IMPLEMENTATIONS") + if (LOCAL_REQUIRED) + foreach (IMPLEMENTATION IN LISTS LOCAL_REQUIRED) + get_property(IMPLEMENTOR GLOBAL PROPERTY "${IMPLEMENTATION}_${INFERRED}") + if (IMPLEMENTOR) + set_property(GLOBAL PROPERTY "${IMPLEMENTATION}_${DECLARED}" "${IMPLEMENTOR}") + endif() + endforeach() + endif () +endfunction() + +#### +# Function `setup_executable_implementations`: +# +# Sets up all the needed implementations for the supplied module. This looks up the global set of required +# implementations and delegates each to `setup_executable_implementation` for final setup. +# +# Args: +# MODULE: module to setup implementation choices for +##### +function(setup_executable_implementations MODULE) + # Check and setup implementors + get_property(LOCAL_REQUIRED GLOBAL PROPERTY "REQUIRED_IMPLEMENTATIONS") + if (LOCAL_REQUIRED) + foreach (IMPLEMENTATION IN LISTS LOCAL_REQUIRED) + setup_executable_implementation("${IMPLEMENTATION}" "${MODULE}") + endforeach () + endif () +endfunction() + +#### +# Function `setup_executable_implementation`: +# +# Sets up the given implementation for the given module. Ensures that choices have been made and linking is setup +# without causing global link depdencies. +# +# Args: +# MODULE: module to setup implementation choices for +##### +function(setup_executable_implementation IMPLEMENTATION MODULE) + # Get thr chosen implementor and fallback to the platform choice + get_property(IMPLEMENTOR GLOBAL PROPERTY "${IMPLEMENTATION}_${MODULE}") + if (NOT IMPLEMENTOR) + get_property(IMPLEMENTOR GLOBAL PROPERTY "${IMPLEMENTATION}_${FPRIME_PLATFORM}") + endif() + # Handle a failure to choose anything + get_property(REQUESTERS GLOBAL PROPERTY "${IMPLEMENTATION}_REQUESTERS") + if (NOT REQUESTERS) + set(REQUESTERS) + endif () + string(REPLACE ";" ", " REQUESTERS_STRING "${REQUESTERS}") + if (NOT IMPLEMENTOR) + get_property(LOCAL_IMPLEMENTATIONS GLOBAL PROPERTY "${IMPLEMENTATION}_IMPLEMENTORS") + if (NOT LOCAL_IMPLEMENTATIONS) + set(LOCAL_IMPLEMENTATIONS "") + endif () + string(REPLACE ";" ", " POSSIBLE "${LOCAL_IMPLEMENTATIONS}") + message(FATAL_ERROR "An implementation of ${IMPLEMENTATION} is required. Choose from: ${POSSIBLE}") + endif () + if (CMAKE_DEBUG_OUTPUT) + message(STATUS "Using Implementation: ${IMPLEMENTOR} for ${IMPLEMENTATION}") + endif() + # Replicated order to solve the circular dependency issue without causing a hard-dependency + target_link_libraries("${MODULE}" PUBLIC ${REQUESTERS} "${IMPLEMENTOR}" ${REQUESTERS}) + add_dependencies("${MODULE}" "${IMPLEMENTOR}") +endfunction() \ No newline at end of file diff --git a/cmake/module.cmake b/cmake/module.cmake index 3f5a065a12..59f48c79f7 100644 --- a/cmake/module.cmake +++ b/cmake/module.cmake @@ -9,6 +9,7 @@ #### include_guard() include(target/target) +include(implementation) set(EMPTY "${FPRIME_FRAMEWORK_PATH}/cmake/empty.cpp") #### @@ -27,13 +28,19 @@ function(generate_base_module_properties TARGET_TYPE TARGET_NAME SOURCE_FILES DE if (TARGET_TYPE STREQUAL "Executable" OR TARGET_TYPE STREQUAL "Deployment") add_executable("${TARGET_NAME}" "${EMPTY}") elseif(TARGET_TYPE STREQUAL "Unit Test") - add_executable("${UT_EXE_NAME}" "${EMPTY}") + add_executable("${TARGET_NAME}" "${EMPTY}") elseif(TARGET_TYPE STREQUAL "Library") add_library("${TARGET_NAME}" "${EMPTY}") else() message(FATAL_ERROR "Module ${TARGET_NAME} cannot register object of type ${TARGET_TYPE}") endif() + # Handle updates when the types have diverged + if (NOT TARGET_NAME STREQUAL "${FPRIME_CURRENT_MODULE}") + # Update implementation choices + remap_implementation_choices("${FPRIME_CURRENT_MODULE}" "${TARGET_NAME}") + endif() + # Modules properties for posterity set_target_properties("${TARGET_NAME}" PROPERTIES FP_TYPE "${TARGET_TYPE}") set_property(GLOBAL APPEND PROPERTY FPRIME_MODULES "${TARGET_NAME}") @@ -96,7 +103,7 @@ function(generate_ut UT_EXE_NAME UT_SOURCES_FILE UT_DEPENDENCIES) # Only for BUILD_TESTING if (BUILD_TESTING) get_module_name("${CMAKE_CURRENT_LIST_DIR}") - generate_base_module_properties("Unit Test" "${MODULE_NAME}" "${UT_SOURCES_FILE}" "${UT_DEPENDENCIES}") + generate_base_module_properties("Unit Test" "${UT_EXE_NAME}" "${UT_SOURCES_FILE}" "${UT_DEPENDENCIES}") endif() endfunction(generate_ut) diff --git a/cmake/platform/platform.cmake b/cmake/platform/platform.cmake index 128bc91992..db1e8ffa6b 100644 --- a/cmake/platform/platform.cmake +++ b/cmake/platform/platform.cmake @@ -9,13 +9,24 @@ include_guard() # Basic definitions get_filename_component(TOOLCHAIN_NAME "${CMAKE_TOOLCHAIN_FILE}" NAME_WE) -# Setup fallback toolchain name -if ("${TOOLCHAIN_NAME}" STREQUAL "") +# Native toolchains use the system name for the toolchain and FPRIME_PLATFORM +if (NOT TOOLCHAIN_NAME) set(TOOLCHAIN_NAME "${CMAKE_SYSTEM_NAME}") + set(FPRIME_PLATFORM "${CMAKE_SYSTEM_NAME}") +# It is an error to use a "Generic" toolchain without setting FPRIME_PLATFORM correctly +elseif (CMAKE_SYSTEM_NAME STREQUAL "Generic" AND NOT FPRIME_PLATFORM) + message(FATAL_ERROR "Toolchain '${TOOLCHAIN_NAME}' set CMAKE_SYSTEM_NAME to 'Generic' without setting FPRIME_PLATFORM") +# It is an error to set neither of CMAKE_SYSTEM_NAME and FPRIME_PLATFORM +elseif (NOT CMAKE_SYSTEM_NAME AND NOT FPRIME_PLATFORM) + message(FATAL_ERROR "Toolchain '${TOOLCHAIN_NAME}' should set CMAKE_SYSTEM_NAME to 'Generic' and set FPRIME_PLATFORM") +# Fallback to CMAKE_SYSTEM_NAME when only CMAKE_SYSTEM_NAME is set +elseif (NOT FPRIME_PLATFORM) + message(WARNING "Toolchain '${TOOLCHAIN_NAME}' should set CMAKE_SYSTEM_NAME to 'Generic' and set FPRIME_PLATFORM") + set(FPRIME_PLATFORM "${CMAKE_SYSTEM_NAME}") endif() # Include platform file based on system name -message(STATUS "Target build toolchain/platform: ${TOOLCHAIN_NAME}/${CMAKE_SYSTEM_NAME}") +message(STATUS "Target build toolchain/platform: ${TOOLCHAIN_NAME}/${FPRIME_PLATFORM}") # Output directories set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/${TOOLCHAIN_NAME}") @@ -25,7 +36,7 @@ set(EXPECTED_PLATFORM_FILE "") # Loop over locations of platform files in order: project, libraries, then framework foreach(ROOT ${FPRIME_PROJECT_ROOT};${FPRIME_LIBRARY_LOCATIONS};${FPRIME_FRAMEWORK_PATH} ) - set(EXPECTED_PLATFORM_FILE "${ROOT}/cmake/platform/${CMAKE_SYSTEM_NAME}.cmake") + set(EXPECTED_PLATFORM_FILE "${ROOT}/cmake/platform/${FPRIME_PLATFORM}.cmake") # Include host machine settings if (EXISTS "${EXPECTED_PLATFORM_FILE}") message(STATUS "Including ${EXPECTED_PLATFORM_FILE}") @@ -35,5 +46,5 @@ foreach(ROOT ${FPRIME_PROJECT_ROOT};${FPRIME_LIBRARY_LOCATIONS};${FPRIME_FRAMEWO endforeach() # Ensure the last attempt for the platform file was successful, otherwise error. if (NOT EXISTS "${EXPECTED_PLATFORM_FILE}") - message(FATAL_ERROR "\n[F-PRIME] No platform config for '${CMAKE_SYSTEM_NAME}'. Please create: '${CMAKE_SYSTEM_NAME}.cmake'\n") + message(FATAL_ERROR "\n[F-PRIME] No platform config for '${FPRIME_PLATFORM}'. Please create: '${FPRIME_PLATFORM}.cmake'\n") endif() diff --git a/cmake/target/build.cmake b/cmake/target/build.cmake index 34ac0f0148..4aed885080 100644 --- a/cmake/target/build.cmake +++ b/cmake/target/build.cmake @@ -7,6 +7,7 @@ include_guard() include(autocoder/autocoder) include(utilities) +include(implementation) # Flags used when BUILD_TESTING is enabled set(FPRIME_TESTING_REQUIRED_COMPILE_FLAGS) @@ -62,7 +63,14 @@ function(build_setup_build_module MODULE SOURCES GENERATED DEPENDENCIES) endforeach() endif() # Includes the source, so that the Ac files can include source headers - target_include_directories("${MODULE}" PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + #target_include_directories("${MODULE}" PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + + + # Handle executable items' need for determined package implementation choices + is_target_library(IS_LIB "${MODULE}") + if (NOT IS_LIB) + setup_executable_implementations("${MODULE}") + endif () # For every detected dependency, add them to the supplied module. This enforces build order. # Also set the link dependencies on this module. CMake rolls-up link dependencies, and thus @@ -93,6 +101,11 @@ function(build_setup_build_module MODULE SOURCES GENERATED DEPENDENCIES) endif() endfunction() + + + + + #### # Function `add_deployment_target`: # diff --git a/cmake/toolchain/raspberrypi.cmake b/cmake/toolchain/raspberrypi.cmake index c23a5a828a..799ec18fa1 100644 --- a/cmake/toolchain/raspberrypi.cmake +++ b/cmake/toolchain/raspberrypi.cmake @@ -1,18 +1,35 @@ #### # Raspberry PI Toolchain # -# This is a toolchain for the Raspberry Pi. This toolchain can be used to build +# This is a toolchain for the Raspberry Pi. This toolchain can be used ot build # against the Raspberry Pi embedded Linux target. In order to use this toolchain, # the Raspberry Pi cross-compiler should be installed on a Linux host. These # tools are installable as follows: # sudo apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf gdb-multiarch #### -set(CMAKE_SYSTEM_PROCESSOR "arm") -set(ARM_TOOL_SUFFIX eabihf) +# Set the system information +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR arm) +set(CMAKE_SYSTEM_VERSION 1) +# Configure the find commands for cross-compiling: tools from host, libraries, includes, and packages from cross-compiler/sysroot +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -if(DEFINED ENV{RPI_TOOLCHAIN_DIR}) - set(ENV{ARM_TOOLS_PATH} "$ENV{RPI_TOOLCHAIN_DIR}") +# Check CMake sysroot +if (DEFINED CMAKE_SYSROOT) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT} ) endif() -include("${CMAKE_CURRENT_LIST_DIR}/helpers/arm-linux-base.cmake") +# Set the GNU ARM toolchain +find_program(CMAKE_AR NAMES arm-linux-gnueabihf-ar PATHS ENV RPI_TOOLCHAIN_DIR PATH_SUFFIXES bin REQUIRED) +find_program(CMAKE_C_COMPILER NAMES arm-linux-gnueabihf-gcc PATHS ENV RPI_TOOLCHAIN_DIR PATH_SUFFIXES bin REQUIRED) +find_program(CMAKE_CXX_COMPILER NAMES arm-linux-gnueabihf-g++ PATHS ENV RPI_TOOLCHAIN_DIR PATH_SUFFIXES bin REQUIRED) +message(STATUS "[arm-linux] C Compiler: ${CMAKE_C_COMPILER}") +message(STATUS "[arm-linux] CXX Compiler: ${CMAKE_CXX_COMPILER}") +find_program(CMAKE_ASM_COMPILER NAMES arm-linux-gnueabihf-as PATHS ENV RPI_TOOLCHAIN_DIR PATH_SUFFIXES bin REQUIRED) +find_program(CMAKE_OBJCOPY NAMES arm-linux-gnueabihf-objcopy PATHS ENV RPI_TOOLCHAIN_DIR PATH_SUFFIXES bin REQUIRED) +find_program(CMAKE_OBJDUMP NAMES arm-linux-gnueabihf-objdump PATHS ENV RPI_TOOLCHAIN_DIR PATH_SUFFIXES bin REQUIRED) + diff --git a/cmake/utilities.cmake b/cmake/utilities.cmake index ea998fad08..d4bba20bb8 100644 --- a/cmake/utilities.cmake +++ b/cmake/utilities.cmake @@ -266,7 +266,7 @@ endfunction() function(is_target_library OUTPUT TEST_TARGET) set("${OUTPUT}" FALSE PARENT_SCOPE) if (TARGET "${TEST_TARGET}") - get_target_property(TARGET_TYPE "${DEPENDENCY}" TYPE) + get_target_property(TARGET_TYPE "${TEST_TARGET}" TYPE) ends_with(IS_LIBRARY "${TARGET_TYPE}" "_LIBRARY") set("${OUTPUT}" "${IS_LIBRARY}" PARENT_SCOPE) endif() @@ -625,4 +625,4 @@ function (filter_lists EXCLUDE_LIST) endforeach() set(${SOURCE_LIST}_FILTERED "${${SOURCE_LIST}_FILTERED}" PARENT_SCOPE) endforeach() -endfunction(filter_lists) \ No newline at end of file +endfunction(filter_lists) diff --git a/docs/Design/package-implementations.md b/docs/Design/package-implementations.md new file mode 100644 index 0000000000..ec97b8639f --- /dev/null +++ b/docs/Design/package-implementations.md @@ -0,0 +1,31 @@ +# Package Implementations + +Certain parts of F´ have different implementations that a project may choose from. The canonical example of this is a file system implementation. Projects may wish to use the stubbed implementation of the file system, the platform supplied standard implementation, or something project-specific like a flash chip or SD card. + +These packages are must be fully specified. Thus, every platform must specify a specific implementation for every package. These specific implementations may be overridden for a specific executable deployment or unit test. + +## Requiring an Implementation + +Modules that require an implementation should call the CMake API function `require_fprime_implementation()` to declare a requirement on a specific implementation. For example, the Os module `require_fprime_implementation(Os/Task)` declares that some implementation of `Os/Task` is required. + +> Only `Os` requires an implementation of `Os/Task` as users of the `Os` package get the implementation through `Os` and should not specify it directly. + +## Choosing an Implementation + +Platform developers *must* specify an implementation of every package used in the system. Failing to do so means that a given functionality is undefined and impossible to link. Stub implementations are provided in the case that a platform does not support a given package's functionality. + +Choosing an implementation is done with a series of `choose_fprime_implementation` calls. One for each required implementation defined in the system. These calls are put in a platform CMake file. + +## Overriding an Implementation Choice + +Some executables, unit tests, and deployments may wish to use a different implementation than that specified by the platform. This can be done by a `choose_fprime_implementation` call in the deployment, executable, or unit test's module. For example, a unit test may which to choose `Os_File_Stub` as an implementation of `Os_File` to disable platform file system support for the given unit test. + +> A CMake target with the name of the chosen implementor *must* be defined somewhere in F´, an F´ library used by the project, or by the project itself. + +## Defining an Implementation + +To define an implementation, developers should declare an F´ module (using `register_fprime_module`) that implements the needed interface of the package. Then call `register_fprime_implementation` to specify this module is an implementation. + +## Conclusion + +F´ provides for various implementations for certain packages needed by the framework. See `cmake/API` and `Os` for API descriptions and Os implementations. \ No newline at end of file From 83df749aac0227efac852b4d478b04889bd61ea5 Mon Sep 17 00:00:00 2001 From: M Starch Date: Wed, 28 Jun 2023 20:38:07 -0700 Subject: [PATCH 02/10] Spelling and engaging actions for refactor/osal branch --- .github/actions/spelling/expect.txt | 1 + .github/workflows/build-test-macos.yml | 2 +- .github/workflows/build-test-rpi.yml | 2 +- .github/workflows/build-test.yml | 2 +- .github/workflows/codeql-jpl-standard.yml | 2 +- .github/workflows/codeql-security-scan.yml | 2 +- .github/workflows/cppcheck-scan.yml | 2 +- .github/workflows/cpplint-scan.yml | 2 +- cmake/implementation.cmake | 4 ++-- 9 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index d83c4f88d4..f8fb25280b 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -686,6 +686,7 @@ ORhex origfile origstatinfo ortega +osal OSAL osaves osets diff --git a/.github/workflows/build-test-macos.yml b/.github/workflows/build-test-macos.yml index 390804dbfa..3a094ee27e 100644 --- a/.github/workflows/build-test-macos.yml +++ b/.github/workflows/build-test-macos.yml @@ -8,7 +8,7 @@ on: push: branches: [ master, devel ] pull_request: - branches: [ master, devel, release/v3.0.0 ] + branches: [ master, devel, refactor/osal ] paths-ignore: - 'docs/**' - '**.md' diff --git a/.github/workflows/build-test-rpi.yml b/.github/workflows/build-test-rpi.yml index 6476d30b86..e3aaa1b30e 100644 --- a/.github/workflows/build-test-rpi.yml +++ b/.github/workflows/build-test-rpi.yml @@ -8,7 +8,7 @@ on: push: branches: [ master, devel ] pull_request: - branches: [ master, devel, release/v3.0.0 ] + branches: [ master, devel, refactor/osal ] paths-ignore: - 'docs/**' - '**.md' diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 6e3f40df19..9711e14210 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -8,7 +8,7 @@ on: push: branches: [ master, devel ] pull_request: - branches: [ master, devel, release/v3.0.0 ] + branches: [ master, devel, refactor/osal ] paths-ignore: - 'docs/**' - '**.md' diff --git a/.github/workflows/codeql-jpl-standard.yml b/.github/workflows/codeql-jpl-standard.yml index 042ab570f1..8dea9999a0 100644 --- a/.github/workflows/codeql-jpl-standard.yml +++ b/.github/workflows/codeql-jpl-standard.yml @@ -8,7 +8,7 @@ on: branches: [ master, devel ] pull_request: # The branches below must be a subset of the branches above - branches: [ master, devel ] + branches: [ master, devel, refactor/osal ] paths-ignore: - 'docs/**' - '**.md' diff --git a/.github/workflows/codeql-security-scan.yml b/.github/workflows/codeql-security-scan.yml index 90ec1a3b17..445fd2d601 100644 --- a/.github/workflows/codeql-security-scan.yml +++ b/.github/workflows/codeql-security-scan.yml @@ -8,7 +8,7 @@ on: branches: [ master, devel ] pull_request: # The branches below must be a subset of the branches above - branches: [ master, devel ] + branches: [ master, devel, refactor/osal ] paths-ignore: - 'docs/**' - '**.md' diff --git a/.github/workflows/cppcheck-scan.yml b/.github/workflows/cppcheck-scan.yml index 6d85692f3d..8523f8f08d 100644 --- a/.github/workflows/cppcheck-scan.yml +++ b/.github/workflows/cppcheck-scan.yml @@ -6,7 +6,7 @@ on: branches: [ master, devel ] pull_request: # The branches below must be a subset of the branches above - branches: [ master, devel ] + branches: [ master, devel, refactor/osal ] paths-ignore: - 'docs/**' - '**.md' diff --git a/.github/workflows/cpplint-scan.yml b/.github/workflows/cpplint-scan.yml index a64c7f174e..d5daf693cd 100644 --- a/.github/workflows/cpplint-scan.yml +++ b/.github/workflows/cpplint-scan.yml @@ -5,7 +5,7 @@ on: branches: [master, devel] pull_request: # The branches below must be a subset of the branches above - branches: [master, devel] + branches: [master, devel, refactor/osal ] paths-ignore: - 'docs/**' - '**.md' diff --git a/cmake/implementation.cmake b/cmake/implementation.cmake index c0715d8e0e..4c12ffb841 100644 --- a/cmake/implementation.cmake +++ b/cmake/implementation.cmake @@ -69,13 +69,13 @@ endfunction() # Function `setup_executable_implementation`: # # Sets up the given implementation for the given module. Ensures that choices have been made and linking is setup -# without causing global link depdencies. +# without causing global link dependencies. # # Args: # MODULE: module to setup implementation choices for ##### function(setup_executable_implementation IMPLEMENTATION MODULE) - # Get thr chosen implementor and fallback to the platform choice + # Get the chosen implementor and fallback to the platform choice get_property(IMPLEMENTOR GLOBAL PROPERTY "${IMPLEMENTATION}_${MODULE}") if (NOT IMPLEMENTOR) get_property(IMPLEMENTOR GLOBAL PROPERTY "${IMPLEMENTATION}_${FPRIME_PLATFORM}") From a78d29026832068f5b21b579aba99d4f5c2b5878 Mon Sep 17 00:00:00 2001 From: M Starch Date: Wed, 28 Jun 2023 21:15:31 -0700 Subject: [PATCH 03/10] Adding CMake unit test for implementations and overrides --- .../Deployment/CMakeLists.txt | 21 ++++++ .../test-implementations/Deployment/Main.cpp | 4 ++ .../Deployment/TestModule/CMakeLists.txt | 17 +++++ .../Deployment/TestModule/Empty.cpp | 0 .../Deployment/settings.ini | 4 ++ .../cmake/platform/Darwin.cmake | 9 +++ .../test-platforms/cmake/platform/Linux.cmake | 9 +++ cmake/test/src/test_implementation.py | 71 +++++++++++++++++++ 8 files changed, 135 insertions(+) create mode 100644 cmake/test/data/test-implementations/Deployment/CMakeLists.txt create mode 100644 cmake/test/data/test-implementations/Deployment/Main.cpp create mode 100644 cmake/test/data/test-implementations/Deployment/TestModule/CMakeLists.txt create mode 100644 cmake/test/data/test-implementations/Deployment/TestModule/Empty.cpp create mode 100644 cmake/test/data/test-implementations/Deployment/settings.ini create mode 100644 cmake/test/data/test-implementations/test-platforms/cmake/platform/Darwin.cmake create mode 100644 cmake/test/data/test-implementations/test-platforms/cmake/platform/Linux.cmake create mode 100644 cmake/test/src/test_implementation.py diff --git a/cmake/test/data/test-implementations/Deployment/CMakeLists.txt b/cmake/test/data/test-implementations/Deployment/CMakeLists.txt new file mode 100644 index 0000000000..6f49fd7a72 --- /dev/null +++ b/cmake/test/data/test-implementations/Deployment/CMakeLists.txt @@ -0,0 +1,21 @@ +#### +# 'TestDeployment' Deployment: +# +# A deployment used to test extra functions of the CMake setup. +#### + +# Base settings +cmake_minimum_required(VERSION 3.13) +cmake_policy(SET CMP0048 NEW) +project(TestImplementation VERSION 1.0.0 LANGUAGES C CXX) + +include("${CMAKE_CURRENT_LIST_DIR}/../../../../../cmake/FPrime.cmake") +# NOTE: register custom targets between these two lines +include("${FPRIME_FRAMEWORK_PATH}/cmake/FPrime-Code.cmake") + +add_fprime_subdirectory("${CMAKE_CURRENT_LIST_DIR}/TestModule") +set(FPRIME_CURRENT_MODULE Deployment) +set(SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/Main.cpp") +set(MOD_DEPS Deployment/TestModule) +choose_fprime_implementation(Test/Override Test/Override/Override) # Choose an override +register_fprime_executable() diff --git a/cmake/test/data/test-implementations/Deployment/Main.cpp b/cmake/test/data/test-implementations/Deployment/Main.cpp new file mode 100644 index 0000000000..b3a97bff5e --- /dev/null +++ b/cmake/test/data/test-implementations/Deployment/Main.cpp @@ -0,0 +1,4 @@ +// No operation executable +int main(int argc, char** argv) { + return 0; +} \ No newline at end of file diff --git a/cmake/test/data/test-implementations/Deployment/TestModule/CMakeLists.txt b/cmake/test/data/test-implementations/Deployment/TestModule/CMakeLists.txt new file mode 100644 index 0000000000..ed80199fcd --- /dev/null +++ b/cmake/test/data/test-implementations/Deployment/TestModule/CMakeLists.txt @@ -0,0 +1,17 @@ +# Build some module +set(SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/Empty.cpp") +register_fprime_module() +# Require some implementations +require_fprime_implementation(Test/Implementation) +require_fprime_implementation(Test/Override) + +# Now create some implementations. This happens to be a convenient place, but not required to be here. + +set(SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/Empty.cpp") +register_fprime_module(Test_Implementation_Platform) + +set(SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/Empty.cpp") +register_fprime_module(Test_Implementation_Override) + +set(SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/Empty.cpp") +register_fprime_module(Test_Override_Override) \ No newline at end of file diff --git a/cmake/test/data/test-implementations/Deployment/TestModule/Empty.cpp b/cmake/test/data/test-implementations/Deployment/TestModule/Empty.cpp new file mode 100644 index 0000000000..e69de29bb2 diff --git a/cmake/test/data/test-implementations/Deployment/settings.ini b/cmake/test/data/test-implementations/Deployment/settings.ini new file mode 100644 index 0000000000..9e5563e907 --- /dev/null +++ b/cmake/test/data/test-implementations/Deployment/settings.ini @@ -0,0 +1,4 @@ +[fprime] +framework_path: ../../../../.. +library_locations: ../test-platforms +project_root: .. diff --git a/cmake/test/data/test-implementations/test-platforms/cmake/platform/Darwin.cmake b/cmake/test/data/test-implementations/test-platforms/cmake/platform/Darwin.cmake new file mode 100644 index 0000000000..074acc6410 --- /dev/null +++ b/cmake/test/data/test-implementations/test-platforms/cmake/platform/Darwin.cmake @@ -0,0 +1,9 @@ +#### +# Darwin.cmake: +# +# Darwin based platform file used for Darwin (Mac OS X) targets. Note: this sets some OS X flags before calling into the common +# Linux implementations to use the posix types defined there. +#### +include("${FPRIME_FRAMEWORK_PATH}/cmake/platform/Darwin.cmake") +choose_fprime_implementation(Test/Implementation Test/Implementation/Platform) +choose_fprime_implementation(Test/Override Test/Implementation/Unused) diff --git a/cmake/test/data/test-implementations/test-platforms/cmake/platform/Linux.cmake b/cmake/test/data/test-implementations/test-platforms/cmake/platform/Linux.cmake new file mode 100644 index 0000000000..3a621ae7a8 --- /dev/null +++ b/cmake/test/data/test-implementations/test-platforms/cmake/platform/Linux.cmake @@ -0,0 +1,9 @@ +#### +# Linux.cmake: +# +# Linux platform file for standard linux targets. Merely defers to [./Linux-common.cmake](Linux-common.cmake). +#### +include("${FPRIME_FRAMEWORK_PATH}/cmake/platform/Linux.cmake") +choose_fprime_implementation(Test/Implementation Test/Implementation/Platform) +choose_fprime_implementation(Test/Override Test/Implementation/Unused) + diff --git a/cmake/test/src/test_implementation.py b/cmake/test/src/test_implementation.py new file mode 100644 index 0000000000..18bea73314 --- /dev/null +++ b/cmake/test/src/test_implementation.py @@ -0,0 +1,71 @@ +#### +# test_basic.py: +# +# Basic CMake tests. +# +#### +import platform + +import settings + +import cmake + +_ = cmake.get_build( + "IMPLEMENTATION_TEST", + settings.DATA_DIR / "test-implementations" / "Deployment", + { + "FPRIME_FRAMEWORK_PATH": settings.REF_APP_PATH.parent, + "FPRIME_PROJECT_ROOT": settings.DATA_DIR / "test-implementations", + "FPRIME_LIBRARY_LOCATIONS": ";".join( + [ + str(settings.DATA_DIR / "test-implementations" / "test-platforms"), + ] + ), + }, + make_targets=["Deployment"], +) + + +def test_platform_implementation(IMPLEMENTATION_TEST): + """Check the platform-specified implementation was produced""" + cmake.assert_process_success(IMPLEMENTATION_TEST) + output_path = ( + IMPLEMENTATION_TEST["build"] + / "lib" + / platform.system() + / "libTest_Implementation_Platform.a" + ) + assert ( + output_path.exists() + ), f"Failed to build the platform-specified implementation target" + + +def test_override_implementation(IMPLEMENTATION_TEST): + """Check the platform-specified implementation was produced""" + cmake.assert_process_success(IMPLEMENTATION_TEST) + output_path = ( + IMPLEMENTATION_TEST["build"] + / "lib" + / platform.system() + / "libTest_Override_Override.a" + ) + assert output_path.exists(), f"Failed to build the override implementation target" + + +def test_non_built_implementation(IMPLEMENTATION_TEST): + """Check the override target that wasn't use was not built along with the override platform target""" + cmake.assert_process_success(IMPLEMENTATION_TEST) + output_path = ( + IMPLEMENTATION_TEST["build"] + / "lib" + / platform.system() + / "libTest_Platform_Override.a" + ) + assert not output_path.exists(), f"Failed to ignore non-built override target" + output_path = ( + IMPLEMENTATION_TEST["build"] + / "lib" + / platform.system() + / "libTest_Override_Unused.a" + ) + assert not output_path.exists(), f"Failed to ignore overridden target" From 01d7f3ddbb41363c06345e58e7532ec6b8e0d701 Mon Sep 17 00:00:00 2001 From: Michael D Starch Date: Mon, 10 Jul 2023 11:52:29 -0700 Subject: [PATCH 04/10] Review fixes --- cmake/API.cmake | 5 +++-- cmake/implementation.cmake | 4 ++-- cmake/toolchain/raspberrypi.cmake | 29 ++++++----------------------- 3 files changed, 11 insertions(+), 27 deletions(-) diff --git a/cmake/API.cmake b/cmake/API.cmake index 0b9573a1ff..476430717c 100644 --- a/cmake/API.cmake +++ b/cmake/API.cmake @@ -621,9 +621,10 @@ endfunction() #### Documentation links # Next Topics: # - Setting Options: [Options](Options.md) are used to vary a CMake build. -# - Adding Deployment: [Deployments](deployment.md) create fprime builds. -# - Adding Module: [Modules](module.md) register fprime Ports, Components, etc. +# - Adding Deployments: [Deployments](deployment.md) create fprime builds. +# - Adding Modules: [Modules](module.md) register fprime Ports, Components, etc. # - Creating Toolchains: [Toolchains](toolchain.md) setup standard CMake Cross-Compiling. # - Adding Platforms: [Platforms](platform.md) help fprime set Cross-Compiling specific items. # - Adding Targets: [Targets](targets.md) for help defining custom build targets +# - Implementation Packages Design: [Implementation Packages](/Design/package-implementor.md) #### diff --git a/cmake/implementation.cmake b/cmake/implementation.cmake index 4c12ffb841..2e74fccbb1 100644 --- a/cmake/implementation.cmake +++ b/cmake/implementation.cmake @@ -23,7 +23,7 @@ include_guard() #### -# Function `adjust_implementation_choices`: +# Function `remap_implementation_choices`: # # When a target is declared with a different name than the module name, we need to pull the implementation choices into # a property for the declared target instead of the inferred target. This is done by reading each implementation choice @@ -100,4 +100,4 @@ function(setup_executable_implementation IMPLEMENTATION MODULE) # Replicated order to solve the circular dependency issue without causing a hard-dependency target_link_libraries("${MODULE}" PUBLIC ${REQUESTERS} "${IMPLEMENTOR}" ${REQUESTERS}) add_dependencies("${MODULE}" "${IMPLEMENTOR}") -endfunction() \ No newline at end of file +endfunction() diff --git a/cmake/toolchain/raspberrypi.cmake b/cmake/toolchain/raspberrypi.cmake index 799ec18fa1..c23a5a828a 100644 --- a/cmake/toolchain/raspberrypi.cmake +++ b/cmake/toolchain/raspberrypi.cmake @@ -1,35 +1,18 @@ #### # Raspberry PI Toolchain # -# This is a toolchain for the Raspberry Pi. This toolchain can be used ot build +# This is a toolchain for the Raspberry Pi. This toolchain can be used to build # against the Raspberry Pi embedded Linux target. In order to use this toolchain, # the Raspberry Pi cross-compiler should be installed on a Linux host. These # tools are installable as follows: # sudo apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf gdb-multiarch #### -# Set the system information -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_PROCESSOR arm) -set(CMAKE_SYSTEM_VERSION 1) -# Configure the find commands for cross-compiling: tools from host, libraries, includes, and packages from cross-compiler/sysroot -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) +set(CMAKE_SYSTEM_PROCESSOR "arm") +set(ARM_TOOL_SUFFIX eabihf) -# Check CMake sysroot -if (DEFINED CMAKE_SYSROOT) - set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT} ) +if(DEFINED ENV{RPI_TOOLCHAIN_DIR}) + set(ENV{ARM_TOOLS_PATH} "$ENV{RPI_TOOLCHAIN_DIR}") endif() -# Set the GNU ARM toolchain -find_program(CMAKE_AR NAMES arm-linux-gnueabihf-ar PATHS ENV RPI_TOOLCHAIN_DIR PATH_SUFFIXES bin REQUIRED) -find_program(CMAKE_C_COMPILER NAMES arm-linux-gnueabihf-gcc PATHS ENV RPI_TOOLCHAIN_DIR PATH_SUFFIXES bin REQUIRED) -find_program(CMAKE_CXX_COMPILER NAMES arm-linux-gnueabihf-g++ PATHS ENV RPI_TOOLCHAIN_DIR PATH_SUFFIXES bin REQUIRED) -message(STATUS "[arm-linux] C Compiler: ${CMAKE_C_COMPILER}") -message(STATUS "[arm-linux] CXX Compiler: ${CMAKE_CXX_COMPILER}") -find_program(CMAKE_ASM_COMPILER NAMES arm-linux-gnueabihf-as PATHS ENV RPI_TOOLCHAIN_DIR PATH_SUFFIXES bin REQUIRED) -find_program(CMAKE_OBJCOPY NAMES arm-linux-gnueabihf-objcopy PATHS ENV RPI_TOOLCHAIN_DIR PATH_SUFFIXES bin REQUIRED) -find_program(CMAKE_OBJDUMP NAMES arm-linux-gnueabihf-objdump PATHS ENV RPI_TOOLCHAIN_DIR PATH_SUFFIXES bin REQUIRED) - +include("${CMAKE_CURRENT_LIST_DIR}/helpers/arm-linux-base.cmake") From 7c48a74d040686be2b7f8a5203cdf4036088e6a4 Mon Sep 17 00:00:00 2001 From: Michael D Starch Date: Tue, 11 Jul 2023 09:39:14 -0700 Subject: [PATCH 05/10] Fixing broken deployment UT sets --- cmake/module.cmake | 2 +- cmake/target/ut.cmake | 23 +++++++++++++---------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/cmake/module.cmake b/cmake/module.cmake index 59f48c79f7..656361bcd5 100644 --- a/cmake/module.cmake +++ b/cmake/module.cmake @@ -32,7 +32,7 @@ function(generate_base_module_properties TARGET_TYPE TARGET_NAME SOURCE_FILES DE elseif(TARGET_TYPE STREQUAL "Library") add_library("${TARGET_NAME}" "${EMPTY}") else() - message(FATAL_ERROR "Module ${TARGET_NAME} cannot register object of type ${TARGET_TYPE}") + message(FATAL_ERROR "Module ${FPRIME_CURRENT_MODULE} cannot register object of type ${TARGET_TYPE}") endif() # Handle updates when the types have diverged diff --git a/cmake/target/ut.cmake b/cmake/target/ut.cmake index 397fabcf2d..0dc7b36a28 100644 --- a/cmake/target/ut.cmake +++ b/cmake/target/ut.cmake @@ -107,7 +107,10 @@ function(ut_add_module_target MODULE_NAME TARGET_NAME SOURCE_FILES DEPENDENCIES) if (NOT BUILD_TESTING OR NOT MODULE_TYPE STREQUAL "Unit Test") return() endif() - message(STATUS "Adding Unit Test: ${UT_EXE_NAME}") + # Set some local variables + set(UT_EXECUTABLE_TARGET "${MODULE_NAME}") + set(UT_MODULE_TARGET "${FPRIME_CURRENT_MODULE}_${UT_TARGET}") + message(STATUS "Adding Unit Test: ${UT_EXECUTABLE_TARGET}") set_property(DIRECTORY APPEND PROPERTY TEST_INCLUDE_FILES "${UT_CLEAN_SCRIPT}" ) @@ -119,23 +122,23 @@ function(ut_add_module_target MODULE_NAME TARGET_NAME SOURCE_FILES DEPENDENCIES) file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/module-ut-info.txt" "${UT_HEADER_FILES}\n${SOURCE_FILES_FILTERED}\n${AC_GENERATED}\n${AC_FILE_DEPENDENCIES}\n${DEPENDENCIES}" ) - build_setup_build_module("${UT_EXE_NAME}" "${SOURCE_FILES_FILTERED}" "${AC_GENERATED_FILTERED}" "${RESOLVED}") + build_setup_build_module("${UT_EXECUTABLE_TARGET}" "${SOURCE_FILES_FILTERED}" "${AC_GENERATED_FILTERED}" "${RESOLVED}") - ut_setup_unit_test_include_directories("${UT_EXE_NAME}" "${SOURCE_FILES}") - add_test(NAME ${UT_EXE_NAME} COMMAND ${UT_EXE_NAME}) + ut_setup_unit_test_include_directories("${UT_EXECUTABLE_TARGET}" "${SOURCE_FILES}") + add_test(NAME ${UT_EXECUTABLE_TARGET} COMMAND ${UT_EXECUTABLE_TARGET}) # Create a module-level target if not already done - if (NOT TARGET "${MODULE_NAME}_${UT_TARGET}" AND FPRIME_ENABLE_UTIL_TARGETS) - add_custom_target("${MODULE_NAME}_${UT_TARGET}") + if (NOT TARGET "${UT_MODULE_TARGET}" AND FPRIME_ENABLE_UTIL_TARGETS) + add_custom_target("${UT_MODULE_TARGET}") endif() # Add module level target dependencies to this UT if (FPRIME_ENABLE_UTIL_TARGETS) - add_dependencies("${MODULE_NAME}_${UT_TARGET}" "${UT_EXE_NAME}") - add_dependencies("${UT_TARGET}" "${UT_EXE_NAME}") - set_property(TARGET "${MODULE_NAME}" APPEND PROPERTY FPRIME_UTS "${UT_EXE_NAME}") + add_dependencies("${UT_MODULE_TARGET}" "${UT_EXECUTABLE_TARGET}") + add_dependencies("${UT_TARGET}" "${UT_EXECUTABLE_TARGET}") + set_property(TARGET "${FPRIME_CURRENT_MODULE}" APPEND PROPERTY FPRIME_UTS "${UT_MODULE_TARGET}") endif() # Link library list output on per-module basis if (CMAKE_DEBUG_OUTPUT) - introspect("${UT_EXE_NAME}") + introspect("${UT_MODULE_TARGET}") endif() endfunction(ut_add_module_target) From 6abc8fea20736622e8d96d6f09e2a2b8f0d767e7 Mon Sep 17 00:00:00 2001 From: Michael D Starch Date: Mon, 27 Nov 2023 11:58:22 -0800 Subject: [PATCH 06/10] Corrections for cmake UTs --- cmake/platform/platform.cmake | 1 + .../test/data/test-implementations/test-platforms/library.cmake | 0 2 files changed, 1 insertion(+) create mode 100644 cmake/test/data/test-implementations/test-platforms/library.cmake diff --git a/cmake/platform/platform.cmake b/cmake/platform/platform.cmake index db1e8ffa6b..2c34f4e030 100644 --- a/cmake/platform/platform.cmake +++ b/cmake/platform/platform.cmake @@ -7,6 +7,7 @@ # #### include_guard() +include(API) # Basic definitions get_filename_component(TOOLCHAIN_NAME "${CMAKE_TOOLCHAIN_FILE}" NAME_WE) # Native toolchains use the system name for the toolchain and FPRIME_PLATFORM diff --git a/cmake/test/data/test-implementations/test-platforms/library.cmake b/cmake/test/data/test-implementations/test-platforms/library.cmake new file mode 100644 index 0000000000..e69de29bb2 From a01cb68a62040381015cf696a199ef8646b7b3c0 Mon Sep 17 00:00:00 2001 From: Michael D Starch Date: Mon, 10 Jul 2023 11:52:29 -0700 Subject: [PATCH 07/10] Removing long-running feature branch --- .github/workflows/build-test-macos.yml | 2 +- .github/workflows/build-test-rpi.yml | 2 +- .github/workflows/build-test.yml | 2 +- .github/workflows/codeql-jpl-standard.yml | 2 +- .github/workflows/codeql-security-scan.yml | 2 +- .github/workflows/cppcheck-scan.yml | 2 +- .github/workflows/cpplint-scan.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build-test-macos.yml b/.github/workflows/build-test-macos.yml index 3a094ee27e..7a216add23 100644 --- a/.github/workflows/build-test-macos.yml +++ b/.github/workflows/build-test-macos.yml @@ -8,7 +8,7 @@ on: push: branches: [ master, devel ] pull_request: - branches: [ master, devel, refactor/osal ] + branches: [ master, devel ] paths-ignore: - 'docs/**' - '**.md' diff --git a/.github/workflows/build-test-rpi.yml b/.github/workflows/build-test-rpi.yml index e3aaa1b30e..bec381345c 100644 --- a/.github/workflows/build-test-rpi.yml +++ b/.github/workflows/build-test-rpi.yml @@ -8,7 +8,7 @@ on: push: branches: [ master, devel ] pull_request: - branches: [ master, devel, refactor/osal ] + branches: [ master, devel ] paths-ignore: - 'docs/**' - '**.md' diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 9711e14210..eebcc06df5 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -8,7 +8,7 @@ on: push: branches: [ master, devel ] pull_request: - branches: [ master, devel, refactor/osal ] + branches: [ master, devel ] paths-ignore: - 'docs/**' - '**.md' diff --git a/.github/workflows/codeql-jpl-standard.yml b/.github/workflows/codeql-jpl-standard.yml index 8dea9999a0..042ab570f1 100644 --- a/.github/workflows/codeql-jpl-standard.yml +++ b/.github/workflows/codeql-jpl-standard.yml @@ -8,7 +8,7 @@ on: branches: [ master, devel ] pull_request: # The branches below must be a subset of the branches above - branches: [ master, devel, refactor/osal ] + branches: [ master, devel ] paths-ignore: - 'docs/**' - '**.md' diff --git a/.github/workflows/codeql-security-scan.yml b/.github/workflows/codeql-security-scan.yml index 445fd2d601..90ec1a3b17 100644 --- a/.github/workflows/codeql-security-scan.yml +++ b/.github/workflows/codeql-security-scan.yml @@ -8,7 +8,7 @@ on: branches: [ master, devel ] pull_request: # The branches below must be a subset of the branches above - branches: [ master, devel, refactor/osal ] + branches: [ master, devel ] paths-ignore: - 'docs/**' - '**.md' diff --git a/.github/workflows/cppcheck-scan.yml b/.github/workflows/cppcheck-scan.yml index 8523f8f08d..6d85692f3d 100644 --- a/.github/workflows/cppcheck-scan.yml +++ b/.github/workflows/cppcheck-scan.yml @@ -6,7 +6,7 @@ on: branches: [ master, devel ] pull_request: # The branches below must be a subset of the branches above - branches: [ master, devel, refactor/osal ] + branches: [ master, devel ] paths-ignore: - 'docs/**' - '**.md' diff --git a/.github/workflows/cpplint-scan.yml b/.github/workflows/cpplint-scan.yml index d5daf693cd..7ad7289f4e 100644 --- a/.github/workflows/cpplint-scan.yml +++ b/.github/workflows/cpplint-scan.yml @@ -5,7 +5,7 @@ on: branches: [master, devel] pull_request: # The branches below must be a subset of the branches above - branches: [master, devel, refactor/osal ] + branches: [master, devel ] paths-ignore: - 'docs/**' - '**.md' From af16f60f181253675f14caa5dbd78e81f49f0390 Mon Sep 17 00:00:00 2001 From: Michael D Starch Date: Mon, 27 Nov 2023 12:29:31 -0800 Subject: [PATCH 08/10] sp --- .github/actions/spelling/expect.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index f8fb25280b..d83c4f88d4 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -686,7 +686,6 @@ ORhex origfile origstatinfo ortega -osal OSAL osaves osets From 4a36735a33c3071bfca76f7ce983708a925f575f Mon Sep 17 00:00:00 2001 From: Michael D Starch Date: Mon, 27 Nov 2023 13:30:46 -0800 Subject: [PATCH 09/10] Correcting FppTest failures --- FppTest/component/active/CMakeLists.txt | 2 ++ FppTest/component/active/test/ut/Tester.cpp | 2 +- FppTest/component/passive/CMakeLists.txt | 2 ++ FppTest/component/passive/test/ut/Tester.cpp | 2 +- FppTest/component/queued/CMakeLists.txt | 2 ++ FppTest/component/queued/test/ut/Tester.cpp | 2 +- FppTest/component/tests/AsyncPortTests.cpp | 2 +- FppTest/component/tests/AsyncTesterHelpers.cpp | 2 +- FppTest/component/tests/CmdTests.hpp | 2 +- FppTest/component/tests/EventTests.cpp | 2 +- FppTest/component/tests/InternalInterfaceTests.cpp | 2 +- FppTest/component/tests/InternalInterfaceTests.hpp | 2 +- FppTest/component/tests/ParamTests.cpp | 2 +- FppTest/component/tests/PortTests.cpp | 2 +- FppTest/component/tests/PortTests.hpp | 2 +- FppTest/component/tests/TesterHandlers.cpp | 2 +- FppTest/component/tests/TesterHelpers.cpp | 2 +- FppTest/component/tests/TimeTests.cpp | 2 +- FppTest/component/tests/TlmTests.cpp | 2 +- FppTest/typed_tests/ComponentTest.hpp | 2 +- FppTest/typed_tests/PortTest.hpp | 2 +- 21 files changed, 24 insertions(+), 18 deletions(-) diff --git a/FppTest/component/active/CMakeLists.txt b/FppTest/component/active/CMakeLists.txt index a88faac320..fa8ffbf3bd 100644 --- a/FppTest/component/active/CMakeLists.txt +++ b/FppTest/component/active/CMakeLists.txt @@ -54,4 +54,6 @@ set(UT_SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/../types/FormalParamTypes.cpp" "${CMAKE_CURRENT_LIST_DIR}/../../utils/Utils.cpp" ) +# Needed for compiling files using Tester.hpp from outside the directory +include_directories("${CMAKE_CURRENT_LIST_DIR}/test/ut") register_fprime_ut() diff --git a/FppTest/component/active/test/ut/Tester.cpp b/FppTest/component/active/test/ut/Tester.cpp index 70908d6262..c1e1308e74 100644 --- a/FppTest/component/active/test/ut/Tester.cpp +++ b/FppTest/component/active/test/ut/Tester.cpp @@ -5,7 +5,7 @@ // ====================================================================== #include "STest/Pick/Pick.hpp" -#include "test/ut/Tester.hpp" +#include "Tester.hpp" // ---------------------------------------------------------------------- // Construction and destruction diff --git a/FppTest/component/passive/CMakeLists.txt b/FppTest/component/passive/CMakeLists.txt index 84667b0eec..f9dfdd9665 100644 --- a/FppTest/component/passive/CMakeLists.txt +++ b/FppTest/component/passive/CMakeLists.txt @@ -43,4 +43,6 @@ set(UT_SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/../types/FormalParamTypes.cpp" "${CMAKE_CURRENT_LIST_DIR}/../../utils/Utils.cpp" ) +# Needed for compiling files using Tester.hpp from outside the directory +include_directories("${CMAKE_CURRENT_LIST_DIR}/test/ut") register_fprime_ut() diff --git a/FppTest/component/passive/test/ut/Tester.cpp b/FppTest/component/passive/test/ut/Tester.cpp index ac62fca4b1..e88fbb8bbd 100644 --- a/FppTest/component/passive/test/ut/Tester.cpp +++ b/FppTest/component/passive/test/ut/Tester.cpp @@ -5,7 +5,7 @@ // ====================================================================== #include "STest/Pick/Pick.hpp" -#include "test/ut/Tester.hpp" +#include "Tester.hpp" // ---------------------------------------------------------------------- // Construction and destruction diff --git a/FppTest/component/queued/CMakeLists.txt b/FppTest/component/queued/CMakeLists.txt index 35e598d802..d7bd850385 100644 --- a/FppTest/component/queued/CMakeLists.txt +++ b/FppTest/component/queued/CMakeLists.txt @@ -48,4 +48,6 @@ set(UT_SOURCE_FILES "${CMAKE_CURRENT_LIST_DIR}/../types/FormalParamTypes.cpp" "${CMAKE_CURRENT_LIST_DIR}/../../utils/Utils.cpp" ) +# Needed for compiling files using Tester.hpp from outside the directory +include_directories("${CMAKE_CURRENT_LIST_DIR}/test/ut") register_fprime_ut() diff --git a/FppTest/component/queued/test/ut/Tester.cpp b/FppTest/component/queued/test/ut/Tester.cpp index 808b3de3e2..fcd67b2d25 100644 --- a/FppTest/component/queued/test/ut/Tester.cpp +++ b/FppTest/component/queued/test/ut/Tester.cpp @@ -5,7 +5,7 @@ // ====================================================================== #include "STest/Pick/Pick.hpp" -#include "test/ut/Tester.hpp" +#include "Tester.hpp" // ---------------------------------------------------------------------- // Construction and destruction diff --git a/FppTest/component/tests/AsyncPortTests.cpp b/FppTest/component/tests/AsyncPortTests.cpp index e16048c9a9..3b45958a95 100644 --- a/FppTest/component/tests/AsyncPortTests.cpp +++ b/FppTest/component/tests/AsyncPortTests.cpp @@ -11,6 +11,6 @@ // ====================================================================== #include "PortTests.hpp" -#include "test/ut/Tester.hpp" +#include "Tester.hpp" PORT_TEST_DEFS_ASYNC diff --git a/FppTest/component/tests/AsyncTesterHelpers.cpp b/FppTest/component/tests/AsyncTesterHelpers.cpp index a396537f7e..7d2d201d53 100644 --- a/FppTest/component/tests/AsyncTesterHelpers.cpp +++ b/FppTest/component/tests/AsyncTesterHelpers.cpp @@ -10,7 +10,7 @@ // // ====================================================================== -#include "test/ut/Tester.hpp" +#include "Tester.hpp" void Tester ::connectAsyncPorts() { // arrayArgsAsync diff --git a/FppTest/component/tests/CmdTests.hpp b/FppTest/component/tests/CmdTests.hpp index fb227d2c33..2a0199b545 100644 --- a/FppTest/component/tests/CmdTests.hpp +++ b/FppTest/component/tests/CmdTests.hpp @@ -10,7 +10,7 @@ // // ====================================================================== -#include "test/ut/Tester.hpp" +#include "Tester.hpp" // ---------------------------------------------------------------------- // Command test declarations diff --git a/FppTest/component/tests/EventTests.cpp b/FppTest/component/tests/EventTests.cpp index be95da36f6..e335d821b3 100644 --- a/FppTest/component/tests/EventTests.cpp +++ b/FppTest/component/tests/EventTests.cpp @@ -10,7 +10,7 @@ // // ====================================================================== -#include "test/ut/Tester.hpp" +#include "Tester.hpp" // ---------------------------------------------------------------------- // Event tests diff --git a/FppTest/component/tests/InternalInterfaceTests.cpp b/FppTest/component/tests/InternalInterfaceTests.cpp index 8f15b7d39f..6daa24e62c 100644 --- a/FppTest/component/tests/InternalInterfaceTests.cpp +++ b/FppTest/component/tests/InternalInterfaceTests.cpp @@ -10,7 +10,7 @@ // // ====================================================================== -#include "test/ut/Tester.hpp" +#include "Tester.hpp" #include "Fw/Comp/QueuedComponentBase.hpp" diff --git a/FppTest/component/tests/InternalInterfaceTests.hpp b/FppTest/component/tests/InternalInterfaceTests.hpp index 0603b0d7ac..1d9721e15d 100644 --- a/FppTest/component/tests/InternalInterfaceTests.hpp +++ b/FppTest/component/tests/InternalInterfaceTests.hpp @@ -10,7 +10,7 @@ // // ====================================================================== -#include "test/ut/Tester.hpp" +#include "Tester.hpp" // ---------------------------------------------------------------------- // Internal interface test declarations diff --git a/FppTest/component/tests/ParamTests.cpp b/FppTest/component/tests/ParamTests.cpp index d8107f9cf6..00d45970b6 100644 --- a/FppTest/component/tests/ParamTests.cpp +++ b/FppTest/component/tests/ParamTests.cpp @@ -10,7 +10,7 @@ // // ====================================================================== -#include "test/ut/Tester.hpp" +#include "Tester.hpp" // ---------------------------------------------------------------------- // Parameter tests diff --git a/FppTest/component/tests/PortTests.cpp b/FppTest/component/tests/PortTests.cpp index 67ad504cda..63f585eec3 100644 --- a/FppTest/component/tests/PortTests.cpp +++ b/FppTest/component/tests/PortTests.cpp @@ -11,7 +11,7 @@ // ====================================================================== #include "PortTests.hpp" -#include "test/ut/Tester.hpp" +#include "Tester.hpp" PORT_TEST_DEFS(Sync) PORT_TEST_DEFS(Guarded) diff --git a/FppTest/component/tests/PortTests.hpp b/FppTest/component/tests/PortTests.hpp index 2f39434ff5..b909e54465 100644 --- a/FppTest/component/tests/PortTests.hpp +++ b/FppTest/component/tests/PortTests.hpp @@ -12,7 +12,7 @@ #include "FppTest/component/active/SerialPortIndexEnumAc.hpp" #include "FppTest/component/active/TypedPortIndexEnumAc.hpp" -#include "test/ut/Tester.hpp" +#include "Tester.hpp" // ---------------------------------------------------------------------- // Port test declarations diff --git a/FppTest/component/tests/TesterHandlers.cpp b/FppTest/component/tests/TesterHandlers.cpp index c8854da1cc..640e0ff348 100644 --- a/FppTest/component/tests/TesterHandlers.cpp +++ b/FppTest/component/tests/TesterHandlers.cpp @@ -10,7 +10,7 @@ // // ====================================================================== -#include "test/ut/Tester.hpp" +#include "Tester.hpp" // ---------------------------------------------------------------------- // Handlers for typed from ports diff --git a/FppTest/component/tests/TesterHelpers.cpp b/FppTest/component/tests/TesterHelpers.cpp index 9094ea68cf..61d7a9dca2 100644 --- a/FppTest/component/tests/TesterHelpers.cpp +++ b/FppTest/component/tests/TesterHelpers.cpp @@ -10,7 +10,7 @@ // // ====================================================================== -#include "test/ut/Tester.hpp" +#include "Tester.hpp" // ---------------------------------------------------------------------- // Helper methods diff --git a/FppTest/component/tests/TimeTests.cpp b/FppTest/component/tests/TimeTests.cpp index 41f034d085..ae93be7864 100644 --- a/FppTest/component/tests/TimeTests.cpp +++ b/FppTest/component/tests/TimeTests.cpp @@ -12,7 +12,7 @@ #include "Fw/Time/Time.hpp" #include "STest/Pick/Pick.hpp" -#include "test/ut/Tester.hpp" +#include "Tester.hpp" // ---------------------------------------------------------------------- // Time test diff --git a/FppTest/component/tests/TlmTests.cpp b/FppTest/component/tests/TlmTests.cpp index 2cedf185d0..23c29e40f8 100644 --- a/FppTest/component/tests/TlmTests.cpp +++ b/FppTest/component/tests/TlmTests.cpp @@ -11,6 +11,6 @@ // ====================================================================== #include "TlmTests.hpp" -#include "test/ut/Tester.hpp" +#include "Tester.hpp" TLM_TEST_DEFS diff --git a/FppTest/typed_tests/ComponentTest.hpp b/FppTest/typed_tests/ComponentTest.hpp index b4812169fb..a9cd746e12 100644 --- a/FppTest/typed_tests/ComponentTest.hpp +++ b/FppTest/typed_tests/ComponentTest.hpp @@ -13,7 +13,7 @@ #ifndef FPP_TEST_COMPONENT_TEST_HPP #define FPP_TEST_COMPONENT_TEST_HPP -#include "test/ut/Tester.hpp" +#include "Tester.hpp" #include "gtest/gtest.h" diff --git a/FppTest/typed_tests/PortTest.hpp b/FppTest/typed_tests/PortTest.hpp index b22f540fc5..a24cf9dcbd 100644 --- a/FppTest/typed_tests/PortTest.hpp +++ b/FppTest/typed_tests/PortTest.hpp @@ -13,7 +13,7 @@ #ifndef FPP_TEST_PORT_TEST_HPP #define FPP_TEST_PORT_TEST_HPP -#include "test/ut/Tester.hpp" +#include "Tester.hpp" #include "FppTest/component/active/TypedPortIndexEnumAc.hpp" #include "gtest/gtest.h" From 5afccdb688117ff47a6ad618f23251ef25a8fb31 Mon Sep 17 00:00:00 2001 From: Michael D Starch Date: Tue, 28 Nov 2023 11:23:12 -0800 Subject: [PATCH 10/10] Review feedback fixes --- docs/Design/general.md | 1 + docs/Design/package-implementations.md | 6 +++--- docs/_includes/toc.md | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/Design/general.md b/docs/Design/general.md index 3ac684eda6..9d9fb34860 100644 --- a/docs/Design/general.md +++ b/docs/Design/general.md @@ -9,3 +9,4 @@ viewed through F´. | [F´ Software Architecture](./fprime-architecture.md) | | [Numerical Types Design](./numerical-types.md) | | [Communication Adapter Interface](./communication-adapter-interface.md) | +| [Package Implementations](./package-implementations.md) | diff --git a/docs/Design/package-implementations.md b/docs/Design/package-implementations.md index ec97b8639f..2abb7c5b06 100644 --- a/docs/Design/package-implementations.md +++ b/docs/Design/package-implementations.md @@ -2,7 +2,7 @@ Certain parts of F´ have different implementations that a project may choose from. The canonical example of this is a file system implementation. Projects may wish to use the stubbed implementation of the file system, the platform supplied standard implementation, or something project-specific like a flash chip or SD card. -These packages are must be fully specified. Thus, every platform must specify a specific implementation for every package. These specific implementations may be overridden for a specific executable deployment or unit test. +These packages must be fully specified. Thus, every platform must specify a specific implementation for every package. These specific implementations may be overridden for a specific executable deployment or unit test. ## Requiring an Implementation @@ -18,7 +18,7 @@ Choosing an implementation is done with a series of `choose_fprime_implementatio ## Overriding an Implementation Choice -Some executables, unit tests, and deployments may wish to use a different implementation than that specified by the platform. This can be done by a `choose_fprime_implementation` call in the deployment, executable, or unit test's module. For example, a unit test may which to choose `Os_File_Stub` as an implementation of `Os_File` to disable platform file system support for the given unit test. +Some executables, unit tests, and deployments may wish to use a different implementation than that specified by the platform. This can be done by a `choose_fprime_implementation` call in the deployment, executable, or unit test's module. For example, a unit test may wish to choose `Os_File_Stub` as an implementation of `Os_File` to disable platform file system support for the given unit test. > A CMake target with the name of the chosen implementor *must* be defined somewhere in F´, an F´ library used by the project, or by the project itself. @@ -28,4 +28,4 @@ To define an implementation, developers should declare an F´ module (using `reg ## Conclusion -F´ provides for various implementations for certain packages needed by the framework. See `cmake/API` and `Os` for API descriptions and Os implementations. \ No newline at end of file +F´ provides for various implementations for certain packages needed by the framework. See `cmake/API` and `Os` for API descriptions and Os implementations. diff --git a/docs/_includes/toc.md b/docs/_includes/toc.md index 4f2f9a8b62..ec4854e1ea 100644 --- a/docs/_includes/toc.md +++ b/docs/_includes/toc.md @@ -97,4 +97,5 @@
  • F´ Software Architecture
  • Numerical Types Design
  • Communication Adapter Interface
  • +
  • Package Implementations