1-
1+ ####
2+ # implementation.cmake:
3+ #
4+ # This file handles enables deployments (and other executables) to choose implementations that resolve
5+ # at link time. This enables projects to choose different underlying implementations for specific concepts
6+ # (e.g. OS, Memory, etc.) at link time.
7+ ####
28include_guard ()
39include (config_assembler )
410
11+ ####
12+ # Function `fprime_target_implementations`:
13+ #
14+ # This function will calculate and add the implementations required for a target. It will use the default
15+ # implementations if no OVERRIDES are provided. Default implementations are the final set of chosen
16+ # implementations as specified in `register_fprime_config` using the CHOOSES_IMPLEMENTATIONS call.
17+ #
18+ # Choosing implementations ensures that there is some implementation of all globally required
19+ # implementations specified by `register_fprime_*` via the REQUIRED_IMPLEMENTATIONS argument.
20+ #
21+ # > [!WARNING]
22+ # > This function may only be called on targets that already exist
23+ #
24+ # > [!NOTE]
25+ # > Target will be updated with FPRIME_CHOSEN_IMPLEMENTATIONS property and FPRIME_CHOSEN_<IMPLEMENTATION>
26+ # > properties for each implementation. `target_link_libraries` will be updated.
27+ #
28+ # Args:
29+ # **BUILD_SYSTEM_TARGET**: the target in the build system to add implementations dependencies to
30+ # **ARGN**: a list of implementations to override the default implementations with
31+ ####
32+ function (fprime_target_implementations BUILD_SYSTEM_TARGET )
33+ append_list_property ("${ARGN} " TARGET "${BUILD_SYSTEM_TARGET} " PROPERTY FPRIME_CHOSEN_IMPLEMENTATIONS )
34+ fprime__internal_choose_implementations ("${BUILD_SYSTEM_TARGET} " INTERNAL_ALL_IMPLEMENTATIONS )
35+ fprime_target_dependencies ("${BUILD_SYSTEM_TARGET} " PRIVATE "${INTERNAL_ALL_IMPLEMENTATIONS} " )
36+ endfunction ()
537
38+ ####
39+ # Function `fprime__internal_implementation_detect_implementations`:
40+ #
41+ # This function will scan the list of global default implementations (detected via the config modules and set in
42+ # the sub-build) and the implementations chosen by the current module. It will then choose one implementation for
43+ # each "IMPLEMENTS" type.
44+ #
45+ # If IMPLEMENTS cannot be determined it is added to the list of unknown implementations.
46+ #
47+ # Args:
48+ # CURRENT_MODULE: the module to check for implementations
49+ ####
650function (fprime__internal_implementation_detect_implementations CURRENT_MODULE )
751 get_target_property (MODULE_CHOSEN "${CURRENT_MODULE} " FPRIME_CHOSEN_IMPLEMENTATIONS)
852 get_property (CONFIG_CHOSEN GLOBAL PROPERTY FPRIME_BASE_CHOSEN_IMPLEMENTATIONS)
@@ -28,7 +72,26 @@ function(fprime__internal_implementation_detect_implementations CURRENT_MODULE)
2872 endforeach ()
2973endfunction ()
3074
31-
75+ ####
76+ # Function `fprime__internal_choose_implementations`:
77+ #
78+ # This function will scan the list of global default implementations module choices via
79+ # `fprime__internal_implementation_detect_implementations`. It will then ensure that each REQUIRED implementation
80+ # has a chosen implementation.
81+ #
82+ # It is an error to not have a chosen implementation for required unless there is a set of unknown implementations
83+ # and in that case it is a warning.
84+ #
85+ # > [!WARNING]
86+ # > If UNKNOWN implementations are set, it is assumed that one of them fills any missing REQUIRED implementations
87+ # > but users should update those modules to explicitly set IMPLEMENTS flag to avoid this warning.
88+ # >
89+ # > If the UNKNOWN implementations do not provided the required implementations a linker error will occur.
90+ #
91+ # Args:
92+ # CURRENT_MODULE: the module to check for implementations
93+ # OUTPUT_VARIABLE: the variable to set with the list of chosen implementations
94+ ####
3295function (fprime__internal_choose_implementations CURRENT_MODULE OUTPUT_VARIABLE )
3396 set (IMPLEMENTATION_DEPENDENCIES)
3497 fprime__internal_implementation_detect_implementations ("${CURRENT_MODULE} " )
@@ -56,120 +119,3 @@ function(fprime__internal_choose_implementations CURRENT_MODULE OUTPUT_VARIABLE)
56119 append_list_property ("${IMPLEMENTATION_DEPENDENCIES} " TARGET "${CURRENT_MODULE} " PROPERTY FPRIME_CHOSEN_IMPLEMENTATIONS )
57120 set ("${OUTPUT_VARIABLE} " "${IMPLEMENTATION_DEPENDENCIES} " PARENT_SCOPE )
58121endfunction ()
59-
60-
61- # ####
62- # # implementation.cmake:
63- # #
64- # # Functions used to handle different registered implementations of various cmake packages within F´. The process breaks
65- # # down as follows:
66- # # 1. A module will "require" an implementation X
67- # # 2. A number of modules will "register" as an implementation of X
68- # # 3. A platform package will "choose" a single implementation for X
69- # # 4. Linked modules (executable, deployment, unit-test) may override and "choose" an alternate implementation for X
70- # #
71- # # For example: Os requires an implementation of Os_File. Os_File_Posix implements Os_File. The Linux platform chooses
72- # # Os_File_Posix as the implementation of Os_File. This applies to all linked modules in the system. Os_Baremetal_ut may
73- # # then override this choose using Os_File_MicroFs instead.
74- # #
75- # # > All required implementations apply system-wide. Platforms specifically disallowing use of a given package should
76- # # > "choose" the special implementation "None" to bypass the check.
77- # #
78- # # Internally this uses several properties. Each of these properties are GLOBAL such that these may be set before the
79- # # various targets have been explicitly created. These pro
80- # #
81- # #
82- # ####
83- # include_guard()
84-
85- # ####
86- # # Function `remap_implementation_choices`:
87- # #
88- # # When a target is declared with a different name than the module name, we need to pull the implementation choices into
89- # # a property for the declared target instead of the inferred target. This is done by reading each implementation choice
90- # # and setting the new property.
91- # #
92- # # Args:
93- # # INFERRED: inferred target name (FPRIME_CURRENT_MODULE)
94- # # DECLARED: real target name
95- # ####
96- # function(remap_implementation_choices INFERRED DECLARED)
97- # # Check and setup implementors
98- # get_property(GLOBAL_REQUIRED GLOBAL PROPERTY "REQUIRED_IMPLEMENTATIONS")
99- # if (GLOBAL_REQUIRED)
100- # foreach (IMPLEMENTATION IN LISTS GLOBAL_REQUIRED)
101- # get_property(IMPLEMENTOR GLOBAL PROPERTY "${INFERRED}_${IMPLEMENTATION}")
102- # if (IMPLEMENTOR)
103- # set_property(GLOBAL PROPERTY "${DECLARED}_${IMPLEMENTATION}" "${IMPLEMENTOR}")
104- # endif()
105- # endforeach()
106- # endif ()
107- # endfunction()
108-
109- # ####
110- # # Function `setup_executable_implementations`:
111- # #
112- # # Sets up all the needed implementations for the supplied module. This looks up the global set of required
113- # # implementations and delegates each to `setup_executable_implementation` for final setup.
114- # #
115- # # Args:
116- # # MODULE: module to setup implementation choices for
117- # #####
118- # function(setup_executable_implementations MODULE)
119- # # Check and setup implementors
120- # get_property(LOCAL_REQUIRED GLOBAL PROPERTY "REQUIRED_IMPLEMENTATIONS")
121- # if (LOCAL_REQUIRED)
122- # init_variables(IMPLEMENTATION_SOURCES IMPLEMENTATION_DEPENDENCIES)
123- # foreach (IMPLEMENTATION IN LISTS LOCAL_REQUIRED)
124- # setup_executable_implementation("${IMPLEMENTATION}" "${MODULE}")
125- # list(APPEND IMPLEMENTATION_SOURCES ${NEW_IMPLEMENTATION_SOURCES})
126- # list(APPEND IMPLEMENTATION_DEPENDENCIES ${NEW_IMPLEMENTATION_DEPENDENCIES})
127- # endforeach ()
128- # endif ()
129- # set(IMPLEMENTATION_SOURCES "${IMPLEMENTATION_SOURCES}" PARENT_SCOPE)
130- # set(IMPLEMENTATION_DEPENDENCIES "${IMPLEMENTATION_DEPENDENCIES}" PARENT_SCOPE)
131- # endfunction()
132-
133- # ####
134- # # Function `setup_executable_implementation`:
135- # #
136- # # Sets up the given implementation for the given module. Ensures that choices have been made and linking is setup
137- # # without causing global link dependencies.
138- # #
139- # # Args:
140- # # MODULE: module to setup implementation choices for
141- # #####
142- # function(setup_executable_implementation IMPLEMENTATION MODULE)
143- # # Get the chosen implementor for the module
144- # get_property(IMPLEMENTOR GLOBAL PROPERTY "${MODULE}_${IMPLEMENTATION}")
145- # # Fallback to the platform in the case that the module does not specify
146- # if (NOT IMPLEMENTOR)
147- # get_property(IMPLEMENTOR GLOBAL PROPERTY "${FPRIME_PLATFORM}_${IMPLEMENTATION}")
148- # endif()
149- # # Fallback to the FRAMEWORK_DEFAULT in the case that the platform does not specify
150- # if (NOT IMPLEMENTOR)
151- # get_property(IMPLEMENTOR GLOBAL PROPERTY "FRAMEWORK_DEFAULT_${IMPLEMENTATION}")
152- # endif()
153-
154- # # Handle a failure to choose anything
155- # if (NOT IMPLEMENTOR)
156- # get_property(LOCAL_IMPLEMENTATIONS GLOBAL PROPERTY "${IMPLEMENTATION}_IMPLEMENTORS")
157- # if (NOT LOCAL_IMPLEMENTATIONS)
158- # set(LOCAL_IMPLEMENTATIONS "")
159- # endif ()
160- # string(REPLACE ";" ", " POSSIBLE "${LOCAL_IMPLEMENTATIONS}")
161- # message(FATAL_ERROR "An implementation of ${IMPLEMENTATION} is required. Choose from: ${POSSIBLE}")
162- # elseif (IMPLEMENTOR STREQUAL "${IMPLEMENTATION}_None")
163- # if (CMAKE_DEBUG_OUTPUT)
164- # message(STATUS "[${MODULE}] Declining Implementation of ${IMPLEMENTATION}")
165- # endif ()
166- # return()
167- # endif ()
168- # if (CMAKE_DEBUG_OUTPUT)
169- # message(STATUS "[${MODULE}] Using Implementation: ${IMPLEMENTOR} for ${IMPLEMENTATION}")
170- # endif()
171- # target_sources("${MODULE}" PRIVATE "$<TARGET_PROPERTY:${IMPLEMENTOR},REQUIRED_SOURCE_FILES>")
172- # target_link_libraries("${MODULE}" PRIVATE ${IMPLEMENTOR})
173- # append_list_property("${IMPLEMENTOR}" TARGET "${MODULE}" PROPERTY FPRIME_DEPENDENCIES)
174- # add_dependencies("${MODULE}" ${IMPLEMENTOR})
175- # endfunction()
0 commit comments