Skip to content

Commit 228b914

Browse files
committed
Fix #1170, refactor target config objects
Rework the dynamic content so it is generated entirely via a CMake "configure_file()" command into a C source file (.c) that can be built as normal. This removes the need for inline `#include` statements to pull in data fragments to fill in the data.
1 parent 672b2dc commit 228b914

File tree

9 files changed

+624
-326
lines changed

9 files changed

+624
-326
lines changed

cmake/generate_build_env.cmake

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
##################################################################
2+
#
3+
# cFS version metadata collection script
4+
#
5+
# This small script runs at build time (as opposed to prep time)
6+
# and is intended to extract information about the current
7+
# build environment - this may change after initial makefile creation
8+
#
9+
##################################################################
10+
11+
# All 3 of these may be passed via environment variables to force a particular
12+
# date, user, or hostname i.e. if hoping to reproduce an exact binary of a prior build
13+
# They are free-form strings, will be built/linked into the final CONFIGDATA object.
14+
15+
# Get the current date and time
16+
set(BUILDDATE $ENV{BUILDDATE})
17+
if (NOT BUILDDATE)
18+
execute_process(
19+
COMMAND date "+%Y%m%d%H%M"
20+
OUTPUT_VARIABLE BUILDDATE
21+
OUTPUT_STRIP_TRAILING_WHITESPACE
22+
)
23+
endif(NOT BUILDDATE)
24+
25+
# Get the build host
26+
set(BUILDHOST $ENV{HOSTNAME})
27+
if (NOT BUILDHOST)
28+
execute_process(
29+
COMMAND hostname
30+
OUTPUT_VARIABLE BUILDHOST
31+
OUTPUT_STRIP_TRAILING_WHITESPACE
32+
)
33+
endif (NOT BUILDHOST)
34+
35+
# Get the user ID
36+
set(BUILDUSER $ENV{USER})
37+
if (NOT BUILDUSER)
38+
execute_process(
39+
COMMAND whoami
40+
OUTPUT_VARIABLE BUILDUSER
41+
OUTPUT_STRIP_TRAILING_WHITESPACE
42+
)
43+
endif (NOT BUILDUSER)
44+
45+
# Use configure_file() command to generate the final output file because this can detect
46+
# and only update it if it changes.
47+
set(CFE_KEYVALUE_TABLE_NAME "CFE_BUILD_ENV_TABLE")
48+
configure_file(${BIN}/cfe_build_env.in ${BIN}/src/cfe_build_env_table.c @ONLY)
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
##################################################################
2+
#
3+
# cFS version metadata collection script
4+
#
5+
# This small script runs at build time (as opposed to prep time)
6+
# and is intended to extract version metadata from the current source
7+
# tree. It is done each time that the code is built, since the
8+
# metadata could change at any time (i.e. a different branch could
9+
# be checked out, or additional changes committed)
10+
#
11+
# Currently only git is supported as a version control source, however
12+
# it could be extended to others by adding the appropriate command
13+
#
14+
##################################################################
15+
16+
set(GIT_EXECUTABLE git)
17+
18+
function(get_version DEP)
19+
if (DEP STREQUAL "MISSION")
20+
set(NAME ${MISSION_NAME})
21+
set(DIR ${MISSION_SOURCE_DIR})
22+
else()
23+
if(EXISTS ${${DEP}_MISSION_DIR}/version_info.cmake)
24+
include(${${DEP}_MISSION_DIR}/version_info.cmake)
25+
else()
26+
set(NAME ${DEP})
27+
endif()
28+
set(DIR ${${DEP}_MISSION_DIR})
29+
endif()
30+
message("inside get_version for ${DEP}")
31+
execute_process(
32+
COMMAND ${GIT_EXECUTABLE} describe --tags --always --dirty
33+
WORKING_DIRECTORY ${DIR}
34+
OUTPUT_VARIABLE GIT_DESC_OUTPUT
35+
RESULT_VARIABLE GIT_RESULT
36+
ERROR_QUIET
37+
OUTPUT_STRIP_TRAILING_WHITESPACE
38+
)
39+
40+
# Export output to parent scope
41+
set(${DEP}_NAME "${NAME}" PARENT_SCOPE)
42+
43+
# If result was successful, then string-ify it, otherwise use NULL
44+
if (GIT_RESULT EQUAL 0)
45+
set(${DEP}_VERSION "\"git:${GIT_DESC_OUTPUT}\"" PARENT_SCOPE)
46+
else()
47+
set(${DEP}_VERSION "NULL" PARENT_SCOPE)
48+
endif()
49+
50+
endfunction()
51+
52+
53+
# First read in any variables that are passed in from the parent process
54+
# There may be many of these and they may not all be passable via -D options
55+
file(STRINGS "${BIN}/mission_vars.cache" PARENTVARS)
56+
set(VARNAME)
57+
foreach(PV ${PARENTVARS})
58+
if (VARNAME)
59+
set(${VARNAME} ${PV})
60+
set(VARNAME)
61+
else()
62+
set(VARNAME ${PV})
63+
endif()
64+
endforeach(PV ${PARENTVARS})
65+
66+
# Get version for all mission apps/dependencies (they may be different)
67+
foreach(DEP "MISSION" ${MISSION_DEPS})
68+
get_version(${DEP})
69+
endforeach()
70+
71+
72+
# Use configure_file() command to generate the final output file because this can detect
73+
# and only update it if it changes.
74+
set(CFE_KEYVALUE_TABLE_NAME "CFE_MODULE_VERSION_TABLE")
75+
configure_file(${BIN}/cfe_module_version.in ${BIN}/src/cfe_module_version_table.c @ONLY)

cmake/mission_build.cmake

Lines changed: 91 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,95 @@ function(initialize_globals)
7272

7373
endfunction(initialize_globals)
7474

75+
##################################################################
76+
#
77+
# FUNCTION: generate_build_version_templates
78+
#
79+
# Generates file templates for use with configure_file() which is
80+
# invoked at build time to get the required information.
81+
#
82+
# Note that some information may change between generation and build
83+
# times, hence why only a template can be generated here, the final
84+
# file content must be generated via a build rule.
85+
#
86+
function(generate_build_version_templates)
87+
88+
# File header for build info template (tag file as auto-generated)
89+
string(CONCAT GENERATED_FILE_HEADER
90+
"/* This file is auto-generated from CMake build system. Do not manually edit! */\n"
91+
"#include \"target_config.h\"\n"
92+
"const CFE_ConfigKeyValue_t @CFE_KEYVALUE_TABLE_NAME@[] = {\n"
93+
)
94+
95+
# File trailer for build info template
96+
string(CONCAT GENERATED_FILE_TRAILER
97+
"{ NULL, NULL } /* End of list */\n"
98+
"};\n"
99+
"/* End of file */\n"
100+
)
101+
102+
# These variables are deferred until build time
103+
foreach (VAR BUILDDATE BUILDUSER BUILDHOST)
104+
list (APPEND GENERATED_FILE_CONTENT "{ \"${VAR}\", \"@${VAR}@\" },")
105+
endforeach ()
106+
string(REPLACE ";" "\n" GENERATED_FILE_CONTENT "${GENERATED_FILE_CONTENT}")
107+
108+
# Write a template for build/config information
109+
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/cfe_generated_file.h.in ${CMAKE_BINARY_DIR}/cfe_build_env.in)
110+
111+
# Content for version info - all are deferred until build time
112+
set(GENERATED_FILE_CONTENT)
113+
foreach(DEP "MISSION" ${MISSION_DEPS})
114+
list (APPEND GENERATED_FILE_CONTENT "{ \"${DEP}\", @${DEP}_VERSION@ },")
115+
endforeach()
116+
string(REPLACE ";" "\n" GENERATED_FILE_CONTENT "${GENERATED_FILE_CONTENT}")
117+
118+
# Write a template for version information
119+
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/cfe_generated_file.h.in ${CMAKE_BINARY_DIR}/cfe_module_version.in)
120+
121+
# The actual version information (to fill out the template above) is obtained at build time
122+
# via a script that is executed as a build target. If this script exists in the mission defs
123+
# directory (user-supplied) then use that. Otherwise a pre-canned "git" version is included
124+
# as a fallback, which should work for source trees assembled via git submodules or subtrees.
125+
if (EXISTS "${MISSION_DEFS}/generate_module_version.cmake")
126+
set(VERSION_SCRIPT "${MISSION_DEFS}/generate_module_version.cmake")
127+
else()
128+
set(VERSION_SCRIPT "${CFE_SOURCE_DIR}/cmake/generate_git_module_version.cmake")
129+
endif()
130+
131+
add_custom_target(cfe-module-version
132+
COMMAND
133+
${CMAKE_COMMAND} -D BIN=${CMAKE_BINARY_DIR}
134+
-P "${VERSION_SCRIPT}"
135+
WORKING_DIRECTORY
136+
${CMAKE_SOURCE_DIR}
137+
VERBATIM
138+
)
139+
140+
add_custom_target(cfe-build-env
141+
COMMAND
142+
${CMAKE_COMMAND} -D BIN=${CMAKE_BINARY_DIR}
143+
-P "${CFE_SOURCE_DIR}/cmake/generate_build_env.cmake"
144+
WORKING_DIRECTORY
145+
${CMAKE_SOURCE_DIR}
146+
VERBATIM
147+
)
148+
149+
# Content for build info - these vars can be evaulated right now, no need to defer
150+
set(GENERATED_FILE_HEADER "/* Automatically generated from CMake build system */")
151+
string(CONCAT GENERATED_FILE_CONTENT
152+
"const char CFE_MISSION_NAME[] = \"${MISSION_NAME}\";\n"
153+
"const char CFE_MISSION_CONFIG[] = \"${MISSIONCONFIG}\";\n"
154+
)
155+
set(GENERATED_FILE_TRAILER "/* End of file */")
156+
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/cfe_generated_file.h.in ${CMAKE_BINARY_DIR}/src/cfe_mission_strings.c)
157+
158+
add_custom_target(mission-version
159+
DEPENDS cfe-module-version cfe-build-env
160+
)
161+
162+
endfunction(generate_build_version_templates)
163+
75164

76165
##################################################################
77166
#
@@ -267,17 +356,8 @@ function(prepare)
267356
endif (NOT "${${VARL}}" STREQUAL "")
268357
endforeach(VARL ${VARLIST})
269358
file(WRITE "${CMAKE_BINARY_DIR}/mission_vars.cache" "${MISSION_VARCACHE}")
270-
271-
# Generate version information for the executable file. This is done by executing a small CMAKE
272-
# at _build_ time (not at prep time since it might change between now and then) that collects
273-
# the info out of the version control system in use (git is currently assumed).
274-
add_custom_target(mission-version
275-
COMMAND
276-
${CMAKE_COMMAND} -D BIN=${CMAKE_BINARY_DIR}
277-
-P ${CFE_SOURCE_DIR}/cmake/version.cmake
278-
WORKING_DIRECTORY
279-
${CMAKE_SOURCE_DIR}
280-
)
359+
360+
generate_build_version_templates()
281361

282362
# Generate the tools for the native (host) arch
283363
add_subdirectory(${MISSION_SOURCE_DIR}/tools tools)

cmake/target/CMakeLists.txt

Lines changed: 96 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,30 +21,108 @@ if (NOT DEFINED ${TGTNAME}_PROCESSORID)
2121
message(FATAL_ERROR "${TGTNAME}_PROCESSORID must be defined to link a final exe")
2222
endif (NOT DEFINED ${TGTNAME}_PROCESSORID)
2323

24-
# Create a file for the statically-linked module list for this target
25-
# do this for both PSP and CFS static modules
26-
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/psp_module_list.inc.tmp"
27-
"/* Automatically generated based on target config */\n")
24+
string(CONCAT GENERATED_FILE_HEADER
25+
"/* This file is auto-generated from CMake build system. Do not manually edit! */\n"
26+
"#include \"target_config.h\"\n"
27+
)
28+
29+
string(CONCAT GENERATED_FILE_TRAILER
30+
"/* End of file */\n"
31+
)
32+
33+
# Generate a list of PSP modules along with a pointer to its API structure/entry point
34+
set(GENERATED_EXTERNS)
35+
set(GENERATED_KEYVALS)
2836
foreach(PSPMOD ${${TGTNAME}_PSP_MODULELIST})
29-
file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/psp_module_list.inc.tmp" "LOAD_PSP_MODULE(${PSPMOD})\n")
37+
list(APPEND GENERATED_EXTERNS "extern char CFE_PSP_${PSPMOD}_API;\n")
38+
list(APPEND GENERATED_KEYVALS "{ .Name = \"${PSPMOD}\", .Api = &CFE_PSP_${PSPMOD}_API },\n")
3039
endforeach(PSPMOD ${${TGTNAME}_PSP_MODULELIST})
31-
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
32-
"${CMAKE_CURRENT_BINARY_DIR}/psp_module_list.inc.tmp"
33-
"${CMAKE_CURRENT_BINARY_DIR}/psp_module_list.inc")
34-
file (REMOVE "${CMAKE_CURRENT_BINARY_DIR}/psp_module_list.inc.tmp")
3540

36-
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/cfs_static_symbol_list.inc.tmp"
37-
"/* Automatically generated based on target config */\n")
41+
string(CONCAT GENERATED_FILE_CONTENT
42+
${GENERATED_EXTERNS}
43+
"const CFE_StaticModuleLoadEntry_t CFE_PSP_MODULE_LIST[] = {\n"
44+
${GENERATED_KEYVALS}
45+
"{ NULL } /* End of list */\n"
46+
"};\n"
47+
)
48+
49+
configure_file(${CFE_SOURCE_DIR}/cmake/cfe_generated_file.h.in ${CMAKE_CURRENT_BINARY_DIR}/cfe_psp_module_list.c)
50+
51+
# Generate lists of modules that will be statically linked into this CFE core target
52+
set(GENERATED_ENTRIES_CORE_MODULES)
53+
foreach(DEP ${MISSION_CORE_MODULES})
54+
list(APPEND GENERATED_ENTRIES_CORE_MODULES "{ \"${DEP}\" },\n")
55+
endforeach()
56+
57+
set(GENERATED_ENTRIES_STATIC_APPS)
58+
foreach(DEP ${${TGTNAME}_STATIC_APPLIST})
59+
list(APPEND GENERATED_ENTRIES_STATIC_APPS "{ \"${DEP}\" },\n")
60+
endforeach()
61+
62+
string(CONCAT GENERATED_FILE_CONTENT
63+
"CFE_ConfigName_t CFE_CORE_MODULE_LIST[] = {\n"
64+
${GENERATED_ENTRIES_CORE_MODULES}
65+
"{ NULL } /* End of list */\n"
66+
"};\n"
67+
"CFE_ConfigName_t CFE_STATIC_APP_LIST[] = {\n"
68+
${GENERATED_ENTRIES_STATIC_APPS}
69+
"{ NULL } /* End of list */\n"
70+
"};\n"
71+
)
72+
73+
configure_file(${CFE_SOURCE_DIR}/cmake/cfe_generated_file.h.in ${CMAKE_CURRENT_BINARY_DIR}/cfe_static_module_list.c)
74+
75+
# Generate a list of symbol names that must be known at runtime without OS loader support
76+
set(GENERATED_EXTERNS)
77+
set(GENERATED_KEYVALS)
3878
foreach(CFSSYM ${${TGTNAME}_STATIC_SYMLIST})
39-
file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/cfs_static_symbol_list.inc.tmp" "STATIC_CFS_SYMBOL(${CFSSYM})\n")
79+
string(REPLACE "," ";" CFSSYM "${CFSSYM}")
80+
list(GET CFSSYM 0 SYM_NAME)
81+
list(GET CFSSYM 1 SYM_MODULE)
82+
list(APPEND GENERATED_EXTERNS "extern void ${SYM_NAME} (void);\n")
83+
list(APPEND GENERATED_KEYVALS "{ .Name = \"${SYM_NAME}\", .Address = &{SYM_NAME}, .Module = \"${SYM_MODULE}\" },")
4084
endforeach(CFSSYM ${${TGTNAME}_STATIC_SYMLIST})
41-
execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different
42-
"${CMAKE_CURRENT_BINARY_DIR}/cfs_static_symbol_list.inc.tmp"
43-
"${CMAKE_CURRENT_BINARY_DIR}/cfs_static_symbol_list.inc")
44-
file (REMOVE "${CMAKE_CURRENT_BINARY_DIR}/cfs_static_symbol_list.inc.tmp")
85+
86+
string(CONCAT GENERATED_FILE_HEADER
87+
"/* This file is auto-generated from CMake build system. Do not manually edit! */\n"
88+
"#include \"osapi-module.h\"\n"
89+
)
90+
91+
string(CONCAT GENERATED_FILE_CONTENT
92+
${GENERATED_EXTERNS}
93+
"OS_static_symbol_record_t OS_STATIC_SYMBOL_TABLE[] = {\n"
94+
${GENERATED_KEYVALS}
95+
"{ NULL } /* End of list */\n"
96+
"};\n"
97+
)
98+
99+
configure_file(${CFE_SOURCE_DIR}/cmake/cfe_generated_file.h.in ${CMAKE_CURRENT_BINARY_DIR}/cfe_static_symbol_list.c)
100+
101+
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cfe_build_env_table.c
102+
COMMAND ${CMAKE_COMMAND} -E copy
103+
${MISSION_BINARY_DIR}/src/cfe_build_env_table.c
104+
${CMAKE_CURRENT_BINARY_DIR}/cfe_build_env_table.c
105+
DEPENDS
106+
${MISSION_BINARY_DIR}/src/cfe_build_env_table.c
107+
)
108+
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/cfe_module_version_table.c
109+
COMMAND ${CMAKE_COMMAND} -E copy
110+
${MISSION_BINARY_DIR}/src/cfe_module_version_table.c
111+
${CMAKE_CURRENT_BINARY_DIR}/cfe_module_version_table.c
112+
DEPENDS
113+
${MISSION_BINARY_DIR}/src/cfe_module_version_table.c
114+
)
45115

46116
# Target for the final executable
47-
add_executable(core-${TGTNAME} src/target_config.c)
117+
add_executable(core-${TGTNAME}
118+
${MISSION_BINARY_DIR}/src/cfe_mission_strings.c
119+
${CMAKE_CURRENT_BINARY_DIR}/cfe_module_version_table.c
120+
${CMAKE_CURRENT_BINARY_DIR}/cfe_build_env_table.c
121+
${CMAKE_CURRENT_BINARY_DIR}/cfe_psp_module_list.c
122+
${CMAKE_CURRENT_BINARY_DIR}/cfe_static_symbol_list.c
123+
${CMAKE_CURRENT_BINARY_DIR}/cfe_static_module_list.c
124+
src/target_config.c
125+
)
48126

49127
target_compile_definitions(core-${TGTNAME} PRIVATE
50128
CFE_DEFAULT_MODULE_EXTENSION="${CMAKE_SHARED_MODULE_SUFFIX}"
@@ -54,8 +132,7 @@ target_compile_definitions(core-${TGTNAME} PRIVATE
54132
CFE_CPU_ID_VALUE=${${TGTNAME}_PROCESSORID}
55133
)
56134

57-
target_include_directories(core-${TGTNAME} PRIVATE
58-
"${CMAKE_CURRENT_BINARY_DIR}"
135+
target_include_directories(core-${TGTNAME} PRIVATE
59136
"${CMAKE_BINARY_DIR}/${CFE_CORE_TARGET}/inc"
60137
)
61138

0 commit comments

Comments
 (0)