Files
TheRock/cmake/therock_flag_utils.cmake
T
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

265 lines
12 KiB
CMake

# Copyright Advanced Micro Devices, Inc.
# SPDX-License-Identifier: MIT
# therock_flag_utils.cmake
# Centralized flag system for TheRock build infrastructure.
#
# Flags are build-system-level controls that affect how subprojects are
# configured. Unlike features (therock_features.cmake) which control
# subproject inclusion, flags control variable propagation and compiler
# defines within included subprojects.
#
# Each flag results in the following changes:
# THEROCK_FLAG_${NAME}: boolean cache variable controlling the flag state
# Optionally propagates CMAKE variables and CPP defines to all or specific
# subprojects via the project_init.cmake mechanism.
#
# See docs/development/flags.md for full documentation.
# Global property to track all declared flags.
set_property(GLOBAL PROPERTY THEROCK_ALL_FLAGS)
# therock_declare_flag
# Declares a build flag with optional variable and define propagation.
#
# Arguments:
# NAME - Unique flag identifier (creates THEROCK_FLAG_${NAME} cache var)
# DEFAULT_VALUE - ON or OFF
# DESCRIPTION - Short description for the cache variable
# ISSUE - (Optional) Tracking issue URL
# GLOBAL_PROPAGATE_FLAG
# - Propagate THEROCK_FLAG_${NAME} to all sub-projects
# regardless of whether the flag is enabled or disabled.
# GLOBAL_CMAKE_VARS - (Optional) VAR=VALUE pairs set in super-project and
# all sub-projects when the flag is enabled
# GLOBAL_CPP_DEFINES - (Optional) Preprocessor defines for all sub-projects
# when the flag is enabled
# CMAKE_VARS - (Optional) VAR=VALUE pairs set only in SUB_PROJECTS
# when the flag is enabled
# CPP_DEFINES - (Optional) Preprocessor defines only in SUB_PROJECTS
# when the flag is enabled
# SUB_PROJECTS - (Optional) List of sub-project target names for scoped
# CMAKE_VARS and CPP_DEFINES
function(therock_declare_flag)
cmake_parse_arguments(PARSE_ARGV 0 ARG
"GLOBAL_PROPAGATE_FLAG"
"NAME;DEFAULT_VALUE;DESCRIPTION;ISSUE"
"GLOBAL_CMAKE_VARS;GLOBAL_CPP_DEFINES;CMAKE_VARS;CPP_DEFINES;SUB_PROJECTS"
)
# Validate required arguments.
if(NOT ARG_NAME)
message(FATAL_ERROR "therock_declare_flag: NAME is required")
endif()
if(NOT DEFINED ARG_DEFAULT_VALUE)
message(FATAL_ERROR "therock_declare_flag: DEFAULT_VALUE is required for flag ${ARG_NAME}")
endif()
if(NOT ARG_DESCRIPTION)
message(FATAL_ERROR "therock_declare_flag: DESCRIPTION is required for flag ${ARG_NAME}")
endif()
# Check for duplicate flags.
get_property(_all_flags GLOBAL PROPERTY THEROCK_ALL_FLAGS)
if("${ARG_NAME}" IN_LIST _all_flags)
message(FATAL_ERROR "therock_declare_flag: Flag '${ARG_NAME}' already declared")
endif()
# Validate that scoped vars/defines require SUB_PROJECTS.
if((ARG_CMAKE_VARS OR ARG_CPP_DEFINES) AND NOT ARG_SUB_PROJECTS)
message(FATAL_ERROR
"therock_declare_flag: Flag '${ARG_NAME}' has CMAKE_VARS or CPP_DEFINES "
"but no SUB_PROJECTS. Use GLOBAL_CMAKE_VARS/GLOBAL_CPP_DEFINES for "
"project-wide settings, or specify SUB_PROJECTS for scoped settings."
)
endif()
# Register the flag (metadata only — no cache/global manipulation here).
# All cache variables and global state are created in therock_finalize_flags().
set_property(GLOBAL APPEND PROPERTY THEROCK_ALL_FLAGS "${ARG_NAME}")
# Store flag metadata in global properties for later retrieval.
set_property(GLOBAL PROPERTY _THEROCK_FLAG_${ARG_NAME}_DEFAULT_VALUE "${ARG_DEFAULT_VALUE}")
set_property(GLOBAL PROPERTY _THEROCK_FLAG_${ARG_NAME}_DESCRIPTION "${ARG_DESCRIPTION}")
set_property(GLOBAL PROPERTY _THEROCK_FLAG_${ARG_NAME}_GLOBAL_PROPAGATE_FLAG "${ARG_GLOBAL_PROPAGATE_FLAG}")
set_property(GLOBAL PROPERTY _THEROCK_FLAG_${ARG_NAME}_GLOBAL_CMAKE_VARS "${ARG_GLOBAL_CMAKE_VARS}")
set_property(GLOBAL PROPERTY _THEROCK_FLAG_${ARG_NAME}_GLOBAL_CPP_DEFINES "${ARG_GLOBAL_CPP_DEFINES}")
set_property(GLOBAL PROPERTY _THEROCK_FLAG_${ARG_NAME}_CMAKE_VARS "${ARG_CMAKE_VARS}")
set_property(GLOBAL PROPERTY _THEROCK_FLAG_${ARG_NAME}_CPP_DEFINES "${ARG_CPP_DEFINES}")
set_property(GLOBAL PROPERTY _THEROCK_FLAG_${ARG_NAME}_SUB_PROJECTS "${ARG_SUB_PROJECTS}")
if(ARG_ISSUE)
set_property(GLOBAL PROPERTY _THEROCK_FLAG_${ARG_NAME}_ISSUE "${ARG_ISSUE}")
endif()
endfunction()
# therock_override_flag_default
# Changes the default value of a previously declared flag. Only updates the
# stored default property — actual cache variable creation happens in
# therock_finalize_flags(). Intended for use in BRANCH_FLAGS.cmake on
# integration branches.
function(therock_override_flag_default flag_name new_default)
get_property(_all_flags GLOBAL PROPERTY THEROCK_ALL_FLAGS)
if(NOT "${flag_name}" IN_LIST _all_flags)
message(FATAL_ERROR
"therock_override_flag_default: Flag '${flag_name}' has not been declared"
)
endif()
message(STATUS "Flag ${flag_name} default overridden to ${new_default}")
set_property(GLOBAL PROPERTY _THEROCK_FLAG_${flag_name}_DEFAULT_VALUE "${new_default}")
endfunction()
# therock_finalize_flags
# Processes all declared flags: sets global variables, appends to
# THEROCK_DEFAULT_CMAKE_VARS, prepares per-subproject injection data, and
# generates the flag_settings.json file.
# Must be called after all flags are declared and before subprojects are activated.
function(therock_finalize_flags)
get_property(_all_flags GLOBAL PROPERTY THEROCK_ALL_FLAGS)
# Phase 1: Create cache variables from stored defaults.
# This is the single place where THEROCK_FLAG_* cache vars are created,
# ensuring no set-ordering issues between declare and override.
foreach(_flag_name ${_all_flags})
get_property(_default GLOBAL PROPERTY _THEROCK_FLAG_${_flag_name}_DEFAULT_VALUE)
get_property(_description GLOBAL PROPERTY _THEROCK_FLAG_${_flag_name}_DESCRIPTION)
set(THEROCK_FLAG_${_flag_name} "${_default}" CACHE BOOL "${_description}")
# Propagate the (possibly user-overridden) cache value to the caller's scope.
set(THEROCK_FLAG_${_flag_name} "${THEROCK_FLAG_${_flag_name}}" PARENT_SCOPE)
endforeach()
# Phase 2: Process enabled flags and build JSON.
set(_json_entries)
foreach(_flag_name ${_all_flags})
# Record flag state for JSON output.
if(THEROCK_FLAG_${_flag_name})
list(APPEND _json_entries "\"${_flag_name}\": true")
else()
list(APPEND _json_entries "\"${_flag_name}\": false")
endif()
get_property(_global_propagate_flag GLOBAL PROPERTY _THEROCK_FLAG_${_flag_name}_GLOBAL_PROPAGATE_FLAG)
if(_global_propagate_flag)
set_property(GLOBAL APPEND PROPERTY THEROCK_DEFAULT_CMAKE_VARS THEROCK_FLAG_${_flag_name})
endif()
if(NOT THEROCK_FLAG_${_flag_name})
continue() # Flag is OFF, skip enabled-only propagation processing.
endif()
# Process GLOBAL_CMAKE_VARS: set in super-project and add to default vars list.
get_property(_global_cmake_vars GLOBAL PROPERTY _THEROCK_FLAG_${_flag_name}_GLOBAL_CMAKE_VARS)
foreach(_var_pair ${_global_cmake_vars})
string(FIND "${_var_pair}" "=" _eq_pos)
if(_eq_pos EQUAL -1)
message(FATAL_ERROR
"Flag '${_flag_name}' GLOBAL_CMAKE_VARS entry '${_var_pair}' "
"must be in VAR=VALUE format"
)
endif()
string(SUBSTRING "${_var_pair}" 0 ${_eq_pos} _var_name)
math(EXPR _val_start "${_eq_pos} + 1")
string(SUBSTRING "${_var_pair}" ${_val_start} -1 _var_value)
# Set in super-project scope.
set(${_var_name} "${_var_value}" PARENT_SCOPE)
# Add to the default vars list so it propagates to all subprojects.
set_property(GLOBAL APPEND PROPERTY THEROCK_DEFAULT_CMAKE_VARS ${_var_name})
endforeach()
# Process GLOBAL_CPP_DEFINES.
get_property(_global_cpp_defines GLOBAL PROPERTY _THEROCK_FLAG_${_flag_name}_GLOBAL_CPP_DEFINES)
foreach(_define ${_global_cpp_defines})
set_property(GLOBAL APPEND PROPERTY THEROCK_FLAG_GLOBAL_CPP_DEFINES "${_define}")
endforeach()
# Process per-subproject CMAKE_VARS and CPP_DEFINES.
get_property(_cmake_vars GLOBAL PROPERTY _THEROCK_FLAG_${_flag_name}_CMAKE_VARS)
get_property(_cpp_defines GLOBAL PROPERTY _THEROCK_FLAG_${_flag_name}_CPP_DEFINES)
get_property(_sub_projects GLOBAL PROPERTY _THEROCK_FLAG_${_flag_name}_SUB_PROJECTS)
foreach(_subproject ${_sub_projects})
foreach(_var_pair ${_cmake_vars})
set_property(GLOBAL APPEND PROPERTY
_THEROCK_SUBPROJECT_FLAG_CMAKE_VARS_${_subproject} "${_var_pair}")
endforeach()
foreach(_define ${_cpp_defines})
set_property(GLOBAL APPEND PROPERTY
_THEROCK_SUBPROJECT_FLAG_CPP_DEFINES_${_subproject} "${_define}")
endforeach()
endforeach()
endforeach()
# Generate flag_settings.json in the build directory.
list(JOIN _json_entries ",\n " _json_body)
set(_json_content "{\n ${_json_body}\n}\n")
set(_flag_settings_file "${THEROCK_BINARY_DIR}/flag_settings.json")
file(WRITE "${_flag_settings_file}" "${_json_content}")
set(THEROCK_FLAG_SETTINGS_FILE "${_flag_settings_file}" PARENT_SCOPE)
endfunction()
# therock_report_flags
# Reports the status of all declared flags at the end of configure.
function(therock_report_flags)
get_property(_all_flags GLOBAL PROPERTY THEROCK_ALL_FLAGS)
if(NOT _all_flags)
return()
endif()
message(STATUS "Build flags:")
foreach(_flag_name ${_all_flags})
if(THEROCK_FLAG_${_flag_name})
message(STATUS " * ${_flag_name} = ON (-DTHEROCK_FLAG_${_flag_name}=ON)")
else()
message(STATUS " * ${_flag_name} = OFF (-DTHEROCK_FLAG_${_flag_name}=OFF)")
endif()
endforeach()
endfunction()
# _therock_get_flag_init_contents
# Internal function called from therock_cmake_subproject_activate() to get
# flag-injected content for a specific subproject's project_init.cmake.
# Sets ${out_var} in PARENT_SCOPE with the content to append.
function(_therock_get_flag_init_contents out_var target_name)
set(_contents "")
# Global CPP defines (apply to ALL subprojects).
get_property(_global_cpp_defines GLOBAL PROPERTY THEROCK_FLAG_GLOBAL_CPP_DEFINES)
if(_global_cpp_defines)
string(APPEND _contents "\n# Flag system: global CPP defines\n")
foreach(_define ${_global_cpp_defines})
string(APPEND _contents "add_compile_definitions(${_define})\n")
endforeach()
endif()
# Per-subproject CMAKE_VARS.
get_property(_has_cmake_vars GLOBAL PROPERTY _THEROCK_SUBPROJECT_FLAG_CMAKE_VARS_${target_name} SET)
if(_has_cmake_vars)
get_property(_cmake_vars GLOBAL PROPERTY _THEROCK_SUBPROJECT_FLAG_CMAKE_VARS_${target_name})
if(_cmake_vars)
string(APPEND _contents "\n# Flag system: per-subproject CMAKE vars\n")
foreach(_var_pair ${_cmake_vars})
string(FIND "${_var_pair}" "=" _eq_pos)
string(SUBSTRING "${_var_pair}" 0 ${_eq_pos} _var_name)
math(EXPR _val_start "${_eq_pos} + 1")
string(SUBSTRING "${_var_pair}" ${_val_start} -1 _var_value)
string(APPEND _contents "set(${_var_name} \"${_var_value}\" CACHE STRING \"\" FORCE)\n")
endforeach()
endif()
endif()
# Per-subproject CPP defines.
get_property(_has_cpp_defines GLOBAL PROPERTY _THEROCK_SUBPROJECT_FLAG_CPP_DEFINES_${target_name} SET)
if(_has_cpp_defines)
get_property(_cpp_defines GLOBAL PROPERTY _THEROCK_SUBPROJECT_FLAG_CPP_DEFINES_${target_name})
if(_cpp_defines)
string(APPEND _contents "\n# Flag system: per-subproject CPP defines\n")
foreach(_define ${_cpp_defines})
string(APPEND _contents "add_compile_definitions(${_define})\n")
endforeach()
endif()
endif()
set(${out_var} "${_contents}" PARENT_SCOPE)
endfunction()