From 09cbe08cc659cc5b52003580d54caa16da72b1e8 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Fri, 19 Jun 2020 16:53:44 -0400 Subject: [PATCH] Fix #746, simplify dependency handling Put more dependencies into the "mission_defaults.cmake" file for more visibility and ease of configuration. This now includes all "implicit" modules such as cfe-core, osal, and psp. Also push the calls to "generate_config_includefile" to a sub-script which can be distributed with each app and evaluated as part of the build. This reduces dependencies on special naming conventions like "fsw/mission_inc" and "fsw/platform_inc", and apps can explicitly manage the files that users are expected to override. --- cmake/arch_build.cmake | 72 +++++++++---------- cmake/global_functions.cmake | 8 ++- cmake/mission_build.cmake | 117 ++++++------------------------- cmake/mission_defaults.cmake | 7 +- cmake/sample_defs/targets.cmake | 2 +- cmake/target/CMakeLists.txt | 8 +-- cmake/version.cmake | 2 +- fsw/cfe-core/CMakeLists.txt | 2 +- fsw/cfe-core/arch_build.cmake | 25 +++++++ fsw/cfe-core/mission_build.cmake | 24 +++++++ 10 files changed, 123 insertions(+), 144 deletions(-) create mode 100644 fsw/cfe-core/arch_build.cmake create mode 100644 fsw/cfe-core/mission_build.cmake diff --git a/cmake/arch_build.cmake b/cmake/arch_build.cmake index 04984f8b3..8cea4fc95 100644 --- a/cmake/arch_build.cmake +++ b/cmake/arch_build.cmake @@ -294,6 +294,19 @@ function(prepare) # Truncate the global TGTSYS_LIST to be only the target architecture set(TGTSYS_LIST ${TARGETSYSTEM} PARENT_SCOPE) + + # set the BUILD_CONFIG variable from the cached data + set(BUILD_CONFIG ${BUILD_CONFIG_${TARGETSYSTEM}}) + list(REMOVE_AT BUILD_CONFIG 0) + set(BUILD_CONFIG ${BUILD_CONFIG} PARENT_SCOPE) + + # Pull in any application-specific platform-scope configuration + # This may include user configuration files such as cfe_platform_cfg.h, + # or any other configuration/preparation that needs to happen at + # platform/arch scope. + foreach(DEP_NAME ${MISSION_DEPS}) + include("${${DEP_NAME}_MISSION_DIR}/arch_build.cmake" OPTIONAL) + endforeach(DEP_NAME ${MISSION_DEPS}) endfunction(prepare) @@ -344,7 +357,7 @@ function(process_arch SYSVAR) include_directories(${CMAKE_BINARY_DIR}/inc) # Configure OSAL target first, as it also determines important compiler flags - add_subdirectory(${MISSION_SOURCE_DIR}/osal osal) + add_subdirectory("${osal_MISSION_DIR}" osal) # The OSAL displays its selected OS, so it is logical to display the selected PSP # This can help with debugging if things go wrong. @@ -393,45 +406,40 @@ function(process_arch SYSVAR) set(INSTALL_SUBDIR cf) endif (NOT INSTALL_SUBDIR) - # Add any dependencies which MIGHT be required for subsequent apps/libs/tools - # The cfe-core and osal are handled explicitly since these have special extra config - foreach(DEP ${MISSION_DEPS}) - if (NOT DEP STREQUAL "cfe-core" AND - NOT DEP STREQUAL "osal") - add_subdirectory(${${DEP}_MISSION_DIR} ${DEP}) - endif() - endforeach(DEP ${MISSION_DEPS}) + # Add all core modules + # The osal is handled explicitly (above) since this has special extra config + foreach(DEP ${MISSION_CORE_MODULES}) + if(NOT DEP STREQUAL "osal") + message(STATUS "Building Core Module: ${DEP}") + add_subdirectory("${${DEP}_MISSION_DIR}" ${DEP}) + endif(NOT DEP STREQUAL "osal") + endforeach(DEP ${MISSION_CORE_MODULES}) + + # For the PSP it may define the FSW as either + # "psp-${CFE_SYSTEM_PSPNAME}" or just simply "psp" + if (NOT TARGET psp) + add_library(psp ALIAS psp-${CFE_SYSTEM_PSPNAME}) + endif (NOT TARGET psp) - # Clear the app lists - set(ARCH_APP_SRCS) - foreach(APP ${TGTSYS_${SYSVAR}_APPS}) - set(TGTLIST_${APP}) - endforeach() - foreach(DRV ${TGTSYS_${SYSVAR}_DRIVERS}) - set(TGTLIST_DRV_${DRV}) - endforeach() - # Process each PSP module that is referenced on this system architecture (any cpu) foreach(PSPMOD ${TGTSYS_${SYSVAR}_PSPMODULES}) message(STATUS "Building PSP Module: ${PSPMOD}") - add_subdirectory(${${PSPMOD}_MISSION_DIR} psp/${PSPMOD}) + add_subdirectory("${${PSPMOD}_MISSION_DIR}" psp/${PSPMOD}) endforeach() # Process each app that is used on this system architecture set(APP_INSTALL_LIST) foreach(APP ${TGTSYS_${SYSVAR}_STATICAPPS}) message(STATUS "Building Static App: ${APP}") - add_subdirectory(${${APP}_MISSION_DIR} apps/${APP}) + add_subdirectory("${${APP}_MISSION_DIR}" apps/${APP}) endforeach() - # Configure the selected PSP - # The naming convention allows more than one PSP per arch, - # however in practice this gets too complicated so it is - # currently a 1:1 relationship. This may change at some point. - add_subdirectory(${MISSION_SOURCE_DIR}/psp psp/${CFE_SYSTEM_PSPNAME}) - # Process each target that shares this system architecture # First Pass: Assemble the list of apps that should be compiled + foreach(APP ${TGTSYS_${SYSVAR}_APPS}) + set(TGTLIST_${APP}) + endforeach() + foreach(TGTID ${TGTSYS_${SYSVAR}}) set(TGTNAME ${TGT${TGTID}_NAME}) @@ -451,19 +459,11 @@ function(process_arch SYSVAR) foreach(APP ${TGTSYS_${SYSVAR}_APPS}) set(APP_INSTALL_LIST ${TGTLIST_${APP}}) message(STATUS "Building App: ${APP} install=${APP_INSTALL_LIST}") - add_subdirectory(${${APP}_MISSION_DIR} apps/${APP}) + add_subdirectory("${${APP}_MISSION_DIR}" apps/${APP}) endforeach() - # Actual core library is a subdirectory - add_subdirectory(${MISSION_SOURCE_DIR}/cfe/fsw/cfe-core cfe-core) - - # If unit test is enabled, build a generic ut stub library for CFE - if (ENABLE_UNIT_TESTS) - add_subdirectory(${cfe-core_MISSION_DIR}/ut-stubs ut_cfe_core_stubs) - endif (ENABLE_UNIT_TESTS) - # Process each target that shares this system architecture - # Second Pass: Build cfe-core and link final target executable + # Second Pass: Build and link final target executable foreach(TGTID ${TGTSYS_${SYSVAR}}) set(TGTNAME ${TGT${TGTID}_NAME}) diff --git a/cmake/global_functions.cmake b/cmake/global_functions.cmake index 8bcc91595..71813f397 100644 --- a/cmake/global_functions.cmake +++ b/cmake/global_functions.cmake @@ -65,7 +65,6 @@ endfunction(generate_c_headerfile) # source file for the wrapper. # # This function now accepts named parameters: -# OUTPUT_DIRECTORY - where the generated file will be written # FILE_NAME - the name of the file to write # FALLBACK_FILE - if no files are found in "defs" using the name match, this file will be used instead. # MATCH_SUFFIX - the suffix to match in the "defs" directory (optional) @@ -74,6 +73,9 @@ endfunction(generate_c_headerfile) function(generate_config_includefile) cmake_parse_arguments(GENCONFIG_ARG "" "OUTPUT_DIRECTORY;FILE_NAME;FALLBACK_FILE;MATCH_SUFFIX" "PREFIXES" ${ARGN} ) + if (NOT GENCONFIG_ARG_OUTPUT_DIRECTORY) + set(GENCONFIG_ARG_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/inc") + endif (NOT GENCONFIG_ARG_OUTPUT_DIRECTORY) set(WRAPPER_FILE_CONTENT) set(ITEM_FOUND FALSE) @@ -103,11 +105,15 @@ function(generate_config_includefile) # If _no_ files were found in the above loop, # then check for and use the fallback file. # (if specified by the caller it should always exist) + # Also produce a message on the console showing whether mission config or fallback was used if (NOT ITEM_FOUND AND GENCONFIG_ARG_FALLBACK_FILE) file(TO_NATIVE_PATH "${GENCONFIG_ARG_FALLBACK_FILE}" SRC_NATIVE_PATH) list(APPEND WRAPPER_FILE_CONTENT "\n\n/* No configuration for ${GENCONFIG_ARG_FILE_NAME}, using fallback */\n" "#include \"${GENCONFIG_ARG_FALLBACK_FILE}\"\n") + message(STATUS "Using ${GENCONFIG_ARG_FALLBACK_FILE} for ${GENCONFIG_ARG_FILE_NAME}") + else() + message(STATUS "Generated ${GENCONFIG_ARG_FILE_NAME} from ${MISSION_DEFS} configuration") endif() # Generate a header file diff --git a/cmake/mission_build.cmake b/cmake/mission_build.cmake index 6cdbaa067..66b0d43c1 100644 --- a/cmake/mission_build.cmake +++ b/cmake/mission_build.cmake @@ -73,31 +73,6 @@ function(initialize_globals) endfunction(initialize_globals) -################################################################## -# -# FUNCTION: add_static_dependencies -# -# Adds an entry to the depedency list during app search -# (Note apps can depend on other apps/libs) -# -function(add_static_dependencies TGT_DEPS) - - set(FULLDEPS ${MISSION_DEPS} ${FIND_DEP_LIST}) - set(NEWDEPS) - foreach(DEP ${TGT_DEPS} ${ARGN}) - list(FIND FULLDEPS ${DEP} DEPIDX) - if (DEPIDX LESS 0) - list(APPEND NEWDEPS ${DEP}) - list(APPEND FULLDEPS ${DEP}) - endif() - endforeach() - - set(FIND_DEP_LIST ${FIND_DEP_LIST} ${NEWDEPS} PARENT_SCOPE) - -endfunction(add_static_dependencies) - - - ################################################################## # # FUNCTION: prepare @@ -126,15 +101,19 @@ function(prepare) ) string(REPLACE ":" ";" CFS_APP_PATH "${CFS_APP_PATH}") set(MISSION_MODULE_SEARCH_PATH ${CFS_APP_PATH} ${MISSION_MODULE_SEARCH_PATH}) - - set(MISSION_DEPS "cfe-core" "osal" ${MISSION_CORE_MODULES}) + + # The "MISSION_DEPS" list is the complete set of all dependencies used in the build. + # This reflects all modules for all CPUs. It is set as a usage convenience + # for iterating through the full set of dependencies regardless of which level + # or context each dependency relates to (CFE, PSP, apps, etc). + set(MISSION_DEPS ${MISSION_APPS} ${MISSION_CORE_MODULES} ${MISSION_PSPMODULES}) set(APP_MISSING_COUNT 0) message(STATUS "Search path for modules: ${MISSION_MODULE_SEARCH_PATH}") # Now search for the rest of CFS applications/libraries/modules - these may exist in # any directory within the search path. - foreach(APP ${MISSION_APPS} ${MISSION_DEPS} ${MISSION_PSPMODULES}) + foreach(APP ${MISSION_DEPS}) set (APPFOUND FALSE) foreach(APPSRC ${MISSION_MODULE_SEARCH_PATH} ${${APP}_SEARCH_PATH}) if (NOT IS_ABSOLUTE "${APPSRC}") @@ -147,7 +126,6 @@ function(prepare) endforeach() if (APPFOUND) get_filename_component(${APP}_MISSION_DIR "${APPFOUND}" ABSOLUTE) - include("${APPFOUND}/mission_build.cmake" OPTIONAL) message(STATUS "Module '${APP}' found at ${${APP}_MISSION_DIR}") else() message("** Module ${APP} NOT found **") @@ -162,7 +140,7 @@ function(prepare) # Export the full set of dependencies to the parent build # including the individual dependency paths to each component set(MISSION_DEPS ${MISSION_DEPS} PARENT_SCOPE) - foreach(DEP ${MISSION_APPS} ${MISSION_DEPS} ${MISSION_PSPMODULES}) + foreach(DEP ${MISSION_DEPS}) set(${DEP}_MISSION_DIR ${${DEP}_MISSION_DIR} PARENT_SCOPE) endforeach(DEP ${MISSION_DEPS}) @@ -180,7 +158,7 @@ function(prepare) list(APPEND MISSION_DOXYFILE_USER_CONTENT "@INCLUDE = ${MISSION_SOURCE_DIR}/doc/Doxyfile\n") endif (EXISTS "${MISSION_SOURCE_DIR}/doc/Doxyfile") - foreach(APP ${MISSION_APPS} ${MISSION_DEPS} ${MISSION_PSPMODULES}) + foreach(APP ${MISSION_DEPS}) # OSAL is handled specially, as only part of it is used if (NOT APP STREQUAL "osal" AND NOT APP STREQUAL "cfe-core") if (EXISTS "${${APP}_MISSION_DIR}/docs/${APP}.doxyfile.in") @@ -246,39 +224,14 @@ function(prepare) add_custom_target(osalguide doxygen osalguide.doxyfile WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/doc") - - # Generate the cfe_mission_cfg.h wrapper file - generate_config_includefile( - OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/inc" - FILE_NAME "cfe_mission_cfg.h" - MATCH_SUFFIX "mission_cfg.h" - PREFIXES ${MISSIONCONFIG} # May be a list of items - ) - generate_config_includefile( - OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/inc" - FILE_NAME "cfe_perfids.h" - MATCH_SUFFIX "perfids.h" - PREFIXES ${MISSIONCONFIG} # May be a list of items - ) - - # Create wrappers for any files provided in an "fsw/mission_inc" subdirectory of each app - # These may be optionally overridden by providing a file of the same name in the defs directory - foreach(APP_NAME ${MISSION_APPS}) - set(APP_MISSION_CONFIG_DIR "${${APP_NAME}_MISSION_DIR}/fsw/mission_inc") - if (IS_DIRECTORY "${APP_MISSION_CONFIG_DIR}") - file(GLOB APP_MISSION_CONFIG_FILES RELATIVE "${APP_MISSION_CONFIG_DIR}" "${APP_MISSION_CONFIG_DIR}/*.h") - foreach(CONFIG_FILE ${APP_MISSION_CONFIG_FILES}) - generate_config_includefile( - OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/inc" - FILE_NAME "${CONFIG_FILE}" - FALLBACK_FILE "${APP_MISSION_CONFIG_DIR}/${CONFIG_FILE}" - MATCH_SUFFIX "${CONFIG_FILE}" - PREFIXES ${MISSIONCONFIG} - ) - endforeach() - endif() - endforeach() + # Pull in any application-specific mission-scope configuration + # This may include user configuration files such as cfe_mission_cfg.h, + # msgid definitions, or any other configuration/preparation that needs to + # happen at mission/global scope. + foreach(DEP_NAME ${MISSION_DEPS}) + include("${${DEP_NAME}_MISSION_DIR}/mission_build.cmake" OPTIONAL) + endforeach(DEP_NAME ${MISSION_DEPS}) # Certain runtime variables need to be "exported" to the subordinate build, such as # the specific arch settings and the location of all the apps. This is done by creating @@ -297,10 +250,14 @@ function(prepare) "MISSION_DEPS" "ENABLE_UNIT_TESTS" ) - foreach(APP ${MISSION_APPS} ${MISSION_PSPMODULES} ${MISSION_DEPS}) + foreach(APP ${MISSION_DEPS}) list(APPEND VARLIST "${APP}_MISSION_DIR") endforeach(APP ${MISSION_APPS}) + foreach(SYSVAR ${TGTSYS_LIST}) + list(APPEND VARLIST "BUILD_CONFIG_${SYSVAR}") + endforeach(SYSVAR ${TGTSYS_LIST}) + set(MISSION_VARCACHE) foreach(VARL ${VARLIST}) # It is important to avoid putting any blank lines in the output, @@ -377,38 +334,6 @@ function(process_arch TARGETSYSTEM) set(SELECTED_TOOLCHAIN_FILE) endif () - # Generate wrapper file for the requisite cfe_platform_cfg.h file - generate_config_includefile( - OUTPUT_DIRECTORY "${ARCH_BINARY_DIR}/inc" - FILE_NAME "cfe_msgids.h" - MATCH_SUFFIX "msgids.h" - PREFIXES ${BUILD_CONFIG} ${ARCH_TOOLCHAIN_NAME} - ) - generate_config_includefile( - OUTPUT_DIRECTORY "${ARCH_BINARY_DIR}/inc" - FILE_NAME "cfe_platform_cfg.h" - MATCH_SUFFIX "platform_cfg.h" - PREFIXES ${BUILD_CONFIG} ${ARCH_TOOLCHAIN_NAME} - ) - - # Create wrappers for any files provided in an "fsw/platform_inc" subdirectory of each app - # These may be optionally overridden by providing a file of the same name in the defs directory - foreach(APP_NAME ${MISSION_APPS}) - set(APP_PLATFORM_CONFIG_DIR "${${APP_NAME}_MISSION_DIR}/fsw/platform_inc") - if (IS_DIRECTORY "${APP_PLATFORM_CONFIG_DIR}") - file(GLOB APP_PLATFORM_CONFIG_FILES RELATIVE "${APP_PLATFORM_CONFIG_DIR}" "${APP_PLATFORM_CONFIG_DIR}/*.h") - foreach(CONFIG_FILE ${APP_PLATFORM_CONFIG_FILES}) - generate_config_includefile( - OUTPUT_DIRECTORY "${ARCH_BINARY_DIR}/inc" - FILE_NAME "${CONFIG_FILE}" - FALLBACK_FILE "${APP_PLATFORM_CONFIG_DIR}/${CONFIG_FILE}" - MATCH_SUFFIX "${CONFIG_FILE}" - PREFIXES ${BUILD_CONFIG} ${ARCH_TOOLCHAIN_NAME} - ) - endforeach() - endif() - endforeach() - # Execute CMake subprocess to create a binary build tree for the specific CPU architecture execute_process( COMMAND ${CMAKE_COMMAND} diff --git a/cmake/mission_defaults.cmake b/cmake/mission_defaults.cmake index f00faeb5b..8f49d54d5 100644 --- a/cmake/mission_defaults.cmake +++ b/cmake/mission_defaults.cmake @@ -10,7 +10,11 @@ # The "MISSION_CORE_MODULES" will be built and statically linked as part # of the CFE core executable on every target. These can be used to amend # or override parts of the CFE core on a mission-specific basis. -set(MISSION_CORE_MODULES) +set(MISSION_CORE_MODULES + "cfe-core" + "osal" + "psp" +) # The "MISSION_GLOBAL_APPLIST" is a set of apps/libs that will be built # for every defined and target. These are built as dynamic modules @@ -40,3 +44,4 @@ set(MISSION_MODULE_SEARCH_PATH # of the standard search path. set(cfe-core_SEARCH_PATH "cfe/fsw") set(osal_SEARCH_PATH ".") +set(psp_SEARCH_PATH ".") diff --git a/cmake/sample_defs/targets.cmake b/cmake/sample_defs/targets.cmake index 961b93d54..d43dcac02 100644 --- a/cmake/sample_defs/targets.cmake +++ b/cmake/sample_defs/targets.cmake @@ -78,7 +78,7 @@ SET(SPACECRAFT_ID 42) # The "MISSION_CORE_MODULES" will be built and statically linked as part # of the CFE core executable on every target. These can be used to amend # or override parts of the CFE core on a mission-specific basis. -set(MISSION_CORE_MODULES) +#list(APPEND MISSION_CORE_MODULES mymodule) # The "MISSION_GLOBAL_APPLIST" is a set of apps/libs that will be built # for every defined and target. These are built as dynamic modules diff --git a/cmake/target/CMakeLists.txt b/cmake/target/CMakeLists.txt index b71591c64..35935cb4a 100644 --- a/cmake/target/CMakeLists.txt +++ b/cmake/target/CMakeLists.txt @@ -102,18 +102,12 @@ endif (TGT${TGTID}_APPLIST) # This depends on whether any special features are included or not set(CFE_LINK_WHOLE_LIBS ${MISSION_CORE_MODULES} - cfe-core - psp-${CFE_SYSTEM_PSPNAME} - osal ) set(CFE_LINK_NORMAL_LIBS ${TGT${TGTID}_PSP_MODULELIST} + ${TGT${TGTID}_STATIC_APPLIST} ) -foreach(STATICAPP ${TGT${TGTID}_STATIC_APPLIST}) - list(APPEND CFE_LINK_NORMAL_LIBS ${STATICAPP}) -endforeach(STATICAPP ${TGT${TGTID}_STATIC_APPLIST}) - # Handle the list of "embedded files" that should be linked into CFE. # These are arbitrary files in the mission config that are converted # into C data structures and linked with the executable. This is diff --git a/cmake/version.cmake b/cmake/version.cmake index a80a80a30..5a0bdb8c7 100644 --- a/cmake/version.cmake +++ b/cmake/version.cmake @@ -71,7 +71,7 @@ file(WRITE ${BIN}/cfecfs_version_info.h.in "#define MISSION_NAME \"\@MISSION_NAME\@\"\n") # Get version for all mission apps/dependencies (they may be different) -foreach(DEP "MISSION" ${MISSION_APPS} ${MISSION_DEPS} ${MISSION_PSPMODULES}) +foreach(DEP "MISSION" ${MISSION_DEPS}) get_version(${DEP}) string(TOUPPER ${${DEP}_NAME} MACRONAME) string(REGEX REPLACE "[^A-Z0-9_]+" "_" MACRONAME "${MACRONAME}") diff --git a/fsw/cfe-core/CMakeLists.txt b/fsw/cfe-core/CMakeLists.txt index f9480a9e2..4aa275555 100644 --- a/fsw/cfe-core/CMakeLists.txt +++ b/fsw/cfe-core/CMakeLists.txt @@ -28,7 +28,7 @@ endforeach(MODULE ${CFE_CORE_MODULES}) add_library(cfe-core STATIC ${CFE_ALL_MODULE_SRCS}) if (ENABLE_UNIT_TESTS) + add_subdirectory(ut-stubs) add_subdirectory(unit-test) endif (ENABLE_UNIT_TESTS) - diff --git a/fsw/cfe-core/arch_build.cmake b/fsw/cfe-core/arch_build.cmake new file mode 100644 index 000000000..2f2f0d5d3 --- /dev/null +++ b/fsw/cfe-core/arch_build.cmake @@ -0,0 +1,25 @@ +########################################################### +# +# CFE arch/platform build setup +# +# This file is evaluated as part of the "prepare" stage +# and can be used to set up prerequisites for the build, +# such as generating header files +# +########################################################### + +# Generate the "cfe_platform_cfg.h" and "cfe_msgids.h" header files +# these must come from mission config + +generate_config_includefile( + FILE_NAME "cfe_platform_cfg.h" + MATCH_SUFFIX "platform_cfg.h" + PREFIXES ${BUILD_CONFIG} +) + +generate_config_includefile( + FILE_NAME "cfe_msgids.h" + MATCH_SUFFIX "msgids.h" + PREFIXES ${BUILD_CONFIG} +) + diff --git a/fsw/cfe-core/mission_build.cmake b/fsw/cfe-core/mission_build.cmake new file mode 100644 index 000000000..83b78a6aa --- /dev/null +++ b/fsw/cfe-core/mission_build.cmake @@ -0,0 +1,24 @@ +########################################################### +# +# CFE mission build setup +# +# This file is evaluated as part of the "prepare" stage +# and can be used to set up prerequisites for the build, +# such as generating header files +# +########################################################### + +# Generate the "cfe_mission_cfg.h" and "cfe_perfids.h" header files +# these must come from mission config +generate_config_includefile( + FILE_NAME "cfe_mission_cfg.h" + MATCH_SUFFIX "mission_cfg.h" + PREFIXES ${MISSIONCONFIG} +) + +generate_config_includefile( + FILE_NAME "cfe_perfids.h" + MATCH_SUFFIX "perfids.h" + PREFIXES ${MISSIONCONFIG} +) +