From a47a581ec5cf54842f6629ce461870378c51f375 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Tue, 18 May 2021 11:39:22 -0400 Subject: [PATCH] Fix #1538, add capability to generate multiple tables Adds a "install_custom.cmake" hook that can be put into a CPU-specific subdirectory under the "defs" directory, that can perform extra installation steps as required for the project/mission. Tweaks the "add_cfe_tables" function such that it can also be called from the install_custom.cmake script to generate additional/alternative table binary files for that CPU. The main update is that it uses the "APP_NAME" parameter to associate the table files with the app library, so the same set of include files can be used. This relies on the target-scope properties being used. Historically that string wasn't verified, it could have been any unique string, but now it should match the app if this is to work as expected. --- cmake/arch_build.cmake | 166 +++++++++++++++++++++---------------- cmake/generate_table.cmake | 1 + 2 files changed, 95 insertions(+), 72 deletions(-) diff --git a/cmake/arch_build.cmake b/cmake/arch_build.cmake index ce7513fc9..e8781da79 100644 --- a/cmake/arch_build.cmake +++ b/cmake/arch_build.cmake @@ -148,80 +148,100 @@ endfunction(add_cfe_app_dependency) # function(add_cfe_tables APP_NAME TBL_SRC_FILES) - # The table source must be compiled using the same "include_directories" - # as any other target, but it uses the "add_custom_command" so there is - # no automatic way to do this (at least in the older cmakes) - - # Create the intermediate table objects using the target compiler, - # then use "elf2cfetbl" to convert to a .tbl file - set(TBL_LIST) - foreach(TBL ${TBL_SRC_FILES} ${ARGN}) - - # Get name without extension (NAME_WE) and append to list of tables - get_filename_component(TBLWE ${TBL} NAME_WE) - - foreach(TGT ${APP_STATIC_TARGET_LIST} ${APP_DYNAMIC_TARGET_LIST}) - set(TABLE_DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/tables_${TGT}") - file(MAKE_DIRECTORY ${TABLE_DESTDIR}) - list(APPEND TBL_LIST "${TABLE_DESTDIR}/${TBLWE}.tbl") - - # Check if an override exists at the mission level (recommended practice) - # This allows a mission to implement a customized table without modifying - # the original - this also makes for easier merging/updating if needed. - if (EXISTS "${MISSION_DEFS}/tables/${TGT}_${TBLWE}.c") - set(TBL_SRC "${MISSION_DEFS}/tables/${TGT}_${TBLWE}.c") - elseif (EXISTS "${MISSION_SOURCE_DIR}/tables/${TGT}_${TBLWE}.c") - set(TBL_SRC "${MISSION_SOURCE_DIR}/tables/${TGT}_${TBLWE}.c") - elseif (EXISTS "${MISSION_DEFS}/tables/${TBLWE}.c") - set(TBL_SRC "${MISSION_DEFS}/tables/${TBLWE}.c") - elseif (EXISTS "${MISSION_SOURCE_DIR}/tables/${TBLWE}.c") - set(TBL_SRC "${MISSION_SOURCE_DIR}/tables/${TBLWE}.c") - elseif (EXISTS "${MISSION_DEFS}/${TGT}/tables/${TBLWE}.c") - set(TBL_SRC "${MISSION_DEFS}/${TGT}/tables/${TBLWE}.c") - elseif (IS_ABSOLUTE "${TBL}") - set(TBL_SRC "${TBL}") - else() - set(TBL_SRC "${CMAKE_CURRENT_SOURCE_DIR}/${TBL}") - endif() + if (TGTNAME) + set (TABLE_TGTLIST ${TGTNAME}) + else() + set (TABLE_TGTLIST ${TGTLIST_${APP_NAME}}) + endif() - if (NOT EXISTS "${TBL_SRC}") - message(FATAL_ERROR "ERROR: No source file for table ${TBLWE}") - else() - message("NOTE: Selected ${TBL_SRC} as source for ${TBLWE}") - endif() + # The first parameter should match the name of an app that was + # previously defined using "add_cfe_app". If target-scope properties + # are used for include directories and compile definitions, this is needed + # to compile tables with the same include path/definitions as the app has. + # However historically this could have been any string, which still works + # if directory-scope properties are used for includes, so this is not + # an error. + if (NOT TARGET ${APP_NAME}) + message("NOTE: \"${APP_NAME}\" passed to add_cfe_tables is not a previously-defined application target") + endif() + + # The table source must be compiled using the same "include_directories" + # as any other target, but it uses the "add_custom_command" so there is + # no automatic way to do this (at least in the older cmakes) + + # Create the intermediate table objects using the target compiler, + # then use "elf2cfetbl" to convert to a .tbl file + foreach(TBL ${TBL_SRC_FILES} ${ARGN}) + + # Get name without extension (NAME_WE) and append to list of tables + get_filename_component(TBLWE ${TBL} NAME_WE) + + foreach(TGT ${TABLE_TGTLIST}) + set(TABLE_LIBNAME "${TGT}_${APP_NAME}_${TBLWE}") + set(TABLE_DESTDIR "${CMAKE_CURRENT_BINARY_DIR}/${TABLE_LIBNAME}") + set(TABLE_BINARY "${TABLE_DESTDIR}/${TBLWE}.tbl") + file(MAKE_DIRECTORY ${TABLE_DESTDIR}) + + # Check if an override exists at the mission level (recommended practice) + # This allows a mission to implement a customized table without modifying + # the original - this also makes for easier merging/updating if needed. + if (EXISTS "${MISSION_DEFS}/tables/${TGT}_${TBLWE}.c") + set(TBL_SRC "${MISSION_DEFS}/tables/${TGT}_${TBLWE}.c") + elseif (EXISTS "${MISSION_SOURCE_DIR}/tables/${TGT}_${TBLWE}.c") + set(TBL_SRC "${MISSION_SOURCE_DIR}/tables/${TGT}_${TBLWE}.c") + elseif (EXISTS "${MISSION_DEFS}/${TGT}/tables/${TBLWE}.c") + set(TBL_SRC "${MISSION_DEFS}/${TGT}/tables/${TBLWE}.c") + elseif (EXISTS "${MISSION_DEFS}/tables/${TBLWE}.c") + set(TBL_SRC "${MISSION_DEFS}/tables/${TBLWE}.c") + elseif (EXISTS "${MISSION_SOURCE_DIR}/tables/${TBLWE}.c") + set(TBL_SRC "${MISSION_SOURCE_DIR}/tables/${TBLWE}.c") + elseif (IS_ABSOLUTE "${TBL}") + set(TBL_SRC "${TBL}") + else() + set(TBL_SRC "${CMAKE_CURRENT_SOURCE_DIR}/${TBL}") + endif() + + if (NOT EXISTS "${TBL_SRC}") + message(FATAL_ERROR "ERROR: No source file for table ${TBLWE}") + else() + message("NOTE: Selected ${TBL_SRC} as source for ${APP_NAME}.${TBLWE} on ${TGT}") + + # NOTE: On newer CMake versions this should become an OBJECT library which makes this simpler. + # On older versions one may not referece the TARGET_OBJECTS property from the custom command. + # As a workaround this is built into a static library, and then the desired object is extracted + # before passing to elf2cfetbl. It is roundabout but it works. + add_library(${TABLE_LIBNAME} STATIC ${TBL_SRC}) + target_link_libraries(${TABLE_LIBNAME} PRIVATE core_api) + if (TARGET ${APP_NAME}) + target_include_directories(${TABLE_LIBNAME} PRIVATE $) + target_compile_definitions(${TABLE_LIBNAME} PRIVATE $) + endif() + + # IMPORTANT: This rule assumes that the output filename of elf2cfetbl matches + # the input file name but with a different extension (.o -> .tbl) + # The actual output filename is embedded in the source file (.c), however + # this must match and if it does not the build will break. That's just the + # way it is, because NO make system supports changing rules based on the + # current content of a dependency (rightfully so). + add_custom_command( + OUTPUT ${TABLE_BINARY} + COMMAND ${CMAKE_COMMAND} + -DCMAKE_AR=${CMAKE_AR} + -DTBLTOOL=${MISSION_BINARY_DIR}/tools/elf2cfetbl/elf2cfetbl + -DLIB=$ + -P ${CFE_SOURCE_DIR}/cmake/generate_table.cmake + DEPENDS ${MISSION_BINARY_DIR}/tools/elf2cfetbl/elf2cfetbl ${TABLE_LIBNAME} + WORKING_DIRECTORY ${TABLE_DESTDIR} + ) + + # Add a custom target to invoke the elf2cfetbl tool to generate the tbl file, + # and install that binary file to the staging area. + add_custom_target(${TABLE_LIBNAME}_tbl ALL DEPENDS ${TABLE_BINARY}) + install(FILES ${TABLE_BINARY} DESTINATION ${TGT}/${INSTALL_SUBDIR}) + endif() + endforeach() + endforeach() - # NOTE: On newer CMake versions this should become an OBJECT library which makes this simpler. - # On older versions one may not referece the TARGET_OBJECTS property from the custom command. - # As a workaround this is built into a static library, and then the desired object is extracted - # before passing to elf2cfetbl. It is roundabout but it works. - add_library(${TGT}_${TBLWE}-obj STATIC ${TBL_SRC}) - target_link_libraries(${TGT}_${TBLWE}-obj PRIVATE core_api) - - # IMPORTANT: This rule assumes that the output filename of elf2cfetbl matches - # the input file name but with a different extension (.o -> .tbl) - # The actual output filename is embedded in the source file (.c), however - # this must match and if it does not the build will break. That's just the - # way it is, because NO make system supports changing rules based on the - # current content of a dependency (rightfully so). - add_custom_command( - OUTPUT "${TABLE_DESTDIR}/${TBLWE}.tbl" - COMMAND ${CMAKE_COMMAND} - -DCMAKE_AR=${CMAKE_AR} - -DTBLTOOL=${MISSION_BINARY_DIR}/tools/elf2cfetbl/elf2cfetbl - -DLIB=$ - -P ${CFE_SOURCE_DIR}/cmake/generate_table.cmake - DEPENDS ${MISSION_BINARY_DIR}/tools/elf2cfetbl/elf2cfetbl ${TGT}_${TBLWE}-obj - WORKING_DIRECTORY ${TABLE_DESTDIR} - ) - # Create the install targets for all the tables - install(FILES ${TABLE_DESTDIR}/${TBLWE}.tbl DESTINATION ${TGT}/${INSTALL_SUBDIR}) - endforeach(TGT ${APP_STATIC_TARGET_LIST} ${APP_DYNAMIC_TARGET_LIST}) - - - endforeach(TBL ${TBL_SRC_FILES} ${ARGN}) - - # Make a custom target that depends on all the tables - add_custom_target(${APP_NAME}_tables ALL DEPENDS ${TBL_LIST}) endfunction(add_cfe_tables) @@ -689,6 +709,8 @@ function(process_arch SYSVAR) # Target to generate the actual executable file add_subdirectory(cmake/target ${TGTNAME}) + include(${MISSION_DEFS}/${TGTNAME}/install_custom.cmake OPTIONAL) + foreach(INSTFILE ${${TGTNAME}_FILELIST}) if(EXISTS ${MISSION_DEFS}/${TGTNAME}/${INSTFILE}) set(FILESRC ${MISSION_DEFS}/${TGTNAME}/${INSTFILE}) diff --git a/cmake/generate_table.cmake b/cmake/generate_table.cmake index 521fd1a1a..b817ce6da 100644 --- a/cmake/generate_table.cmake +++ b/cmake/generate_table.cmake @@ -38,6 +38,7 @@ if (NOT RESULT EQUAL 0) endif() # Finally invoke the table tool (elf2cfetbl) on the object +message("Executing Process: ${TBLTOOL} ${OBJNAME}") execute_process(COMMAND ${TBLTOOL} "${OBJNAME}" RESULT_VARIABLE RESULT )