summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmake/script/feature_verification.cmake90
1 files changed, 90 insertions, 0 deletions
diff --git a/cmake/script/feature_verification.cmake b/cmake/script/feature_verification.cmake
new file mode 100644
index 0000000..2ec1eab
--- /dev/null
+++ b/cmake/script/feature_verification.cmake
@@ -0,0 +1,90 @@
+#[[
+ # Copyright (c) 2026 Alexey Gavrilov <alexey.gavrilov@mail.com>
+ #
+ # This file is part of ObjectiveOS.
+ #
+ # ObjectiveOS is free software: you can redistribute it and/or modify it under
+ # the terms of the GNU General Public License as published by the Free Software
+ # Foundation, either version 3 of the License, or (at your option) any later
+ # version.
+ #
+ # ObjectiveOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public License along with
+ # ObjectiveOS. If not, see <https://www.gnu.org/licenses/>.
+ ]]
+
+#[[
+ # This cmake script works like passed feature definitions handling.
+ # Parameters specify via command line -D option. FEATURE_OUT_FILEPATH is
+ # necessary, and means path to the features description file generated by
+ # correspondent module.
+ ]]
+
+#[[
+ # Read the out file created by the feature module, and instance populated
+ # variables in current cmake environment. Receive only one argument - path to the
+ # feature module file to read variables from
+ ]]
+function(readCacheFile filepath)
+ if(NOT EXISTS ${filepath} OR NOT IS_READABLE ${filepath})
+ message(FATAL_ERROR "${filepath} not exists")
+ endif()
+
+ file(STRINGS ${filepath} vardefines REGEX "^[^#|//][^:]*(:.*)?=(\".+\")")
+ foreach(line IN LISTS vardefines)
+ if(line MATCHES "^([^:]+)(:[A-Z]+)?=\"(.+)\"")
+ set(${CMAKE_MATCH_1} ${CMAKE_MATCH_3} PARENT_SCOPE)
+ endif()
+ endforeach()
+
+endfunction()
+
+#[[
+ # The feature dependency chain checks. Dependency chain is the sequence of
+ # features interconnected between themself by dependency property. Every this
+ # check means proper feature definition existence passed through command line.
+ # Checks are success when last feature has not features dependencies, and all
+ # options are set.
+# Loop dependencies are inappropriate this way.
+ ]]
+function(verify_feature_dependencies feature dependency)
+ # Through out the non-target dependency
+ if(NOT FEATURE_${dependency}_ID STREQUAL "${dependency}")
+ return()
+ elseif(dependency IN_LIST FEATURE_${feature}_DEPENDENCIES
+ AND NOT DEFINED FEATURE_${dependency}
+ )
+ message(FATAL_ERROR "${feature} has ${dependency} dependency, "
+ "but FEATURE_${dependency} is not set")
+ endif()
+
+ # Dive deep into subsequent recursive iteration
+ foreach(next_lvl_dep IN LISTS FEATURE_${dependency}_DEPENDENCIES)
+ verify_feature_dependencies(${dependency} ${next_lvl_dep})
+ endforeach()
+endfunction()
+
+#[[
+# Verification start point. Parse available features.
+# Forward features to further verifications.
+ ]]
+function(verify_features feature_metadata_filepath)
+ readCacheFile("${feature_metadata_filepath}")
+ get_directory_property(_cache_vars CACHE_VARIABLES)
+ list(FILTER _cache_vars INCLUDE REGEX "FEATURE_[A-Za-z0-9\.]+$")
+ foreach(enable_feature_def IN LISTS _cache_vars)
+ # Fetch feature name/id
+ string(REGEX MATCH "[^_][A-Za-z0-9\.]+$" enable_feature
+ "${enable_feature_def}"
+ )
+ # Dependencies checks
+ foreach(dependency IN LISTS FEATURE_${enable_feature}_DEPENDENCIES)
+ verify_feature_dependencies("${enable_feature}" "${dependency}")
+ endforeach()
+ # Put further verifications below
+ endforeach()
+endfunction()
+
+verify_features("${FEATURE_OUT_FILEPATH}")