diff --git a/infra/.beman_submodule b/infra/.beman_submodule index 77d57dbd..9573b414 100644 --- a/infra/.beman_submodule +++ b/infra/.beman_submodule @@ -1,4 +1,4 @@ [beman_submodule] remote=https://github.com/bemanproject/infra.git -commit_hash=63cb577f6484f13ce3349de49ad5ce27e20bf1da +commit_hash=53a1500400203529bd6bc3c39119501a9f63ebea allow_untracked_files=True diff --git a/infra/README.md b/infra/README.md index eadd9fb8..bf9bbb06 100644 --- a/infra/README.md +++ b/infra/README.md @@ -53,20 +53,36 @@ Some options for the project and target will also be supported: (default: all packages) * `_INSTALL_CONFIG_FILE_PACKAGE` - a per-project option to enable/disable config file installation (default: `ON` if the project is top-level, `OFF` otherwise). For instance for `beman.something`, the option would be `BEMAN_SOMETHING_INSTALL_CONFIG_FILE_PACKAGE`. -#### `beman_cmake_instrumentation` +# BuildTelemetry -The cmake modules in this library are intended to provide access to CMake instrumentation data in Google Trace format which is visualizable with chrome://tracing and https://ui.perfetto.dev. +The cmake modules in this library provide access to CMake instrumentation data in Google Trace format which is visualizable with chrome://tracing and https://ui.perfetto.dev. -Instrumentation may be enabled either by adding to the CMAKE_PROJECT_TOP_LEVEL_INCLUDES -```sh --DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=infra/cmake/bemancmakeinstrumentation.cmake +Telemetry may be enabled in several ways: + +## `include` + +```cmake +include (infra/cmake/BuildTelemetry.cmake) +configure_build_telemetry() ``` -or by calling explicitly within the CMakeList.txt file. + +## `find_package` + ```cmake -find_package(BemanCMakeInstrumentation) -configure_beman_cmake_instrumentation() +find_package(BuildTelemetry) +configure_build_telemetry() +``` + +as long as [BuildTelemetryConfig.cmake](./cmake/BuildTelemetryConfig.cmake) is in your module path. + +## `CMAKE_PROJECT_TOP_LEVEL_INCLUDES` +A non-invasive way to inject this telemetry into a CMake build you do not want to modify. +Add: +```sh +-DCMAKE_PROJECT_TOP_LEVEL_INCLUDES=infra/cmake/BuildTelemetry.cmake ``` +To the cmake invocation. -In either form, CMake will call `instrumentation.sh` which will copy the trace data in json format into a `.trace` subdirectory within the build directory. +In any form, CMake will call `telemetry.sh` which will copy the trace data in json format into a `.trace` subdirectory within the build directory. -Multiple calls to `configure_beman_cmake_instrumentation` will only configure the callback hooks once, so it is safe to include multiple times, including by TOP_LEVEL_INCLUDE. +Multiple calls to `configure_build_telemetry` will only configure the callback hooks once, so it is safe to enable multiple times, including by TOP_LEVEL_INCLUDE. diff --git a/infra/cmake/BuildTelemetry.cmake b/infra/cmake/BuildTelemetry.cmake new file mode 100755 index 00000000..c2ff3433 --- /dev/null +++ b/infra/cmake/BuildTelemetry.cmake @@ -0,0 +1,4 @@ +include_guard(GLOBAL) + +include(${CMAKE_CURRENT_LIST_DIR}/BuildTelemetryConfig.cmake) +configure_build_telemetry() diff --git a/infra/cmake/BuildTelemetryConfig.cmake b/infra/cmake/BuildTelemetryConfig.cmake new file mode 100755 index 00000000..94b02833 --- /dev/null +++ b/infra/cmake/BuildTelemetryConfig.cmake @@ -0,0 +1,39 @@ +include_guard(GLOBAL) + +set(BUILD_TELEMETRY_DIR ${CMAKE_CURRENT_LIST_DIR}) + +function(configure_build_telemetry) + if(NOT BUILD_TELEMETRY_CONFIGURATION) + # Check if the CMake version is at least 4.3 + if(CMAKE_VERSION VERSION_LESS "4.3") + message( + STATUS + "CMake version is less than 4.3, configuring cmake_instrumentation is unavailable." + ) + return() + else() + message(STATUS "Configuring Build Telemetry") + endif() + + # Telemetry query + cmake_instrumentation( + API_VERSION 1 + DATA_VERSION 1 + + OPTIONS staticSystemInformation dynamicSystemInformation trace + HOOKS postGenerate preBuild postBuild preCMakeBuild postCMakeBuild postCMakeInstall postCTest + CALLBACK ${BUILD_TELEMETRY_DIR}/telemetry.sh + ) + message( + DEBUG + "using callback script ${BUILD_TELEMETRY_DIR}/telemetry.sh" + ) + + # Mark configuration as done in cache + set(BUILD_TELEMETRY_CONFIGURATION + TRUE + CACHE INTERNAL + "Flag to ensure Build Telemetry configured only once" + ) + endif() +endfunction(configure_build_telemetry) diff --git a/infra/cmake/Config.cmake.in b/infra/cmake/Config.cmake.in index 81adf800..3f1341ce 100644 --- a/infra/cmake/Config.cmake.in +++ b/infra/cmake/Config.cmake.in @@ -3,10 +3,10 @@ include(CMakeFindDependencyMacro) -@BEMAN_FIND_DEPENDENCIES@ +@BEMAN_INSTALL_FIND_DEPENDENCIES@ @PACKAGE_INIT@ -include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@-targets.cmake) +include(${CMAKE_CURRENT_LIST_DIR}/@BEMAN_INSTALL_BASE_PKG_NAME@-targets.cmake) -check_required_components(@PROJECT_NAME@) +check_required_components(@BEMAN_INSTALL_BASE_PKG_NAME@) diff --git a/infra/cmake/beman-install-library.cmake b/infra/cmake/beman-install-library.cmake index 8a6c5a1a..96305fad 100644 --- a/infra/cmake/beman-install-library.cmake +++ b/infra/cmake/beman-install-library.cmake @@ -56,7 +56,7 @@ include(GNUInstallDirs) # HEADERS to the default CMAKE install destination. # # It also handles the installation of the CMake config package files if -# needed. If the given targets has FILE_SET CXX_MODULE, it will also +# needed. If the given targets has a PUBLIC FILE_SET CXX_MODULE, it will also # installed to the given DESTINATION # # Cache variables: @@ -72,7 +72,7 @@ include(GNUInstallDirs) # Caveats # ------- # -# **Only one `FILE_SET CXX_MODULES` is yet supported to install with this +# **Only one `PUBLIC FILE_SET CXX_MODULES` is yet supported to install with this # function!** # # **Only header files contained in a `PUBLIC FILE_SET TYPE HEADERS` will be @@ -86,14 +86,14 @@ function(beman_install_library name) set(multiValueArgs TARGETS DEPENDENCIES) cmake_parse_arguments( - BEMAN + BEMAN_INSTALL "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) - if(NOT BEMAN_TARGETS) + if(NOT BEMAN_INSTALL_TARGETS) message( FATAL_ERROR "beman_install_library(${name}): TARGETS must be specified" @@ -103,7 +103,7 @@ function(beman_install_library name) if(CMAKE_SKIP_INSTALL_RULES) message( WARNING - "beman_install_library(${name}): not installing targets '${BEMAN_TARGETS}' due to CMAKE_SKIP_INSTALL_RULES" + "beman_install_library(${name}): not installing targets '${BEMAN_INSTALL_TARGETS}' due to CMAKE_SKIP_INSTALL_RULES" ) return() endif() @@ -113,16 +113,16 @@ function(beman_install_library name) # ---------------------------- # Defaults # ---------------------------- - if(NOT BEMAN_NAMESPACE) - set(BEMAN_NAMESPACE "beman::") + if(NOT BEMAN_INSTALL_NAMESPACE) + set(BEMAN_INSTALL_NAMESPACE "beman::") endif() - if(NOT BEMAN_EXPORT_NAME) - set(BEMAN_EXPORT_NAME "${name}-targets") + if(NOT BEMAN_INSTALL_EXPORT_NAME) + set(BEMAN_INSTALL_EXPORT_NAME "${name}-targets") endif() - if(NOT BEMAN_DESTINATION) - set(BEMAN_DESTINATION "${_config_install_dir}/modules") + if(NOT BEMAN_INSTALL_DESTINATION) + set(BEMAN_INSTALL_DESTINATION "${_config_install_dir}/modules") endif() string(REPLACE "beman." "" install_component_name "${name}") @@ -134,7 +134,7 @@ function(beman_install_library name) # -------------------------------------------------- # Install each target with all of its file sets # -------------------------------------------------- - foreach(_tgt IN LISTS BEMAN_TARGETS) + foreach(_tgt IN LISTS BEMAN_INSTALL_TARGETS) if(NOT TARGET "${_tgt}") message( WARNING @@ -189,16 +189,16 @@ function(beman_install_library name) set(_install_header_set_args FILE_SET HEADERS) # Note: empty FILE_SET in this case! CK endif() - # Detect presence of C++ module file sets, exact one expected! - get_target_property(_module_sets "${_tgt}" CXX_MODULE_SETS) + # Detect presence of PUBLIC C++ module file sets. Note: exact one is expected! + get_target_property(_module_sets "${_tgt}" INTERFACE_CXX_MODULE_SETS) if(_module_sets) message( VERBOSE - "beman-install-library(${name}): '${_tgt}' has CXX_MODULE_SETS=${_module_sets}" + "beman-install-library(${name}): '${_tgt}' has INTERFACE_CXX_MODULE_SETS=${_module_sets}" ) install( TARGETS "${_tgt}" - EXPORT ${BEMAN_EXPORT_NAME} + EXPORT ${BEMAN_INSTALL_EXPORT_NAME} ARCHIVE COMPONENT "${install_component_name}_Development" LIBRARY COMPONENT "${install_component_name}_Runtime" @@ -206,7 +206,7 @@ function(beman_install_library name) RUNTIME COMPONENT "${install_component_name}_Runtime" ${_install_header_set_args} FILE_SET ${_module_sets} - DESTINATION "${BEMAN_DESTINATION}" + DESTINATION "${BEMAN_INSTALL_DESTINATION}" COMPONENT "${install_component_name}_Development" # NOTE: There's currently no convention for this location! CK CXX_MODULES_BMI @@ -217,7 +217,7 @@ function(beman_install_library name) else() install( TARGETS "${_tgt}" - EXPORT ${BEMAN_EXPORT_NAME} + EXPORT ${BEMAN_INSTALL_EXPORT_NAME} ARCHIVE COMPONENT "${install_component_name}_Development" LIBRARY COMPONENT "${install_component_name}_Runtime" @@ -233,8 +233,8 @@ function(beman_install_library name) # -------------------------------------------------- # gersemi: off install( - EXPORT ${BEMAN_EXPORT_NAME} - NAMESPACE ${BEMAN_NAMESPACE} + EXPORT ${BEMAN_INSTALL_EXPORT_NAME} + NAMESPACE ${BEMAN_INSTALL_NAMESPACE} CXX_MODULES_DIRECTORY cxx-modules DESTINATION ${_config_install_dir} COMPONENT "${install_component_name}_Development" @@ -279,19 +279,20 @@ function(beman_install_library name) # expand dependencies # ---------------------------------------- set(_beman_find_deps "") - foreach(dep IN LISTS BEMAN_DEPENDENCIES) + foreach(dep IN LISTS BEMAN_INSTALL_DEPENDENCIES) message( VERBOSE "beman-install-library(${name}): Add find_dependency(${dep})" ) string(APPEND _beman_find_deps "find_dependency(${dep})\n") endforeach() - set(BEMAN_FIND_DEPENDENCIES "${_beman_find_deps}") + set(BEMAN_INSTALL_FIND_DEPENDENCIES "${_beman_find_deps}") # ---------------------------------------- # Generate + install config files # ---------------------------------------- if(_install_config) + set(BEMAN_INSTALL_BASE_PKG_NAME ${name}) configure_package_config_file( "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/Config.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/${name}-config.cmake" diff --git a/infra/cmake/bemancmakeinstrumentation-config.cmake b/infra/cmake/bemancmakeinstrumentation-config.cmake deleted file mode 100755 index 135b4922..00000000 --- a/infra/cmake/bemancmakeinstrumentation-config.cmake +++ /dev/null @@ -1,29 +0,0 @@ -include_guard(GLOBAL) - -cmake_minimum_required (VERSION 4.2) - -set(BEMAN_CMAKE_INSTRUMENTATION_DIR ${CMAKE_CURRENT_LIST_DIR}) - -function(configure_beman_cmake_instrumentation) - if(NOT BEMAN_CMAKE_INSTRUMENTATION_CONFIGURATION) - message(WARNING "Configuring Beman CMake Instrumentation") - - # Enable experimental feature!! - set(CMAKE_EXPERIMENTAL_INSTRUMENTATION ec7aa2dc-b87f-45a3-8022-fe01c5f59984) - - # Instrumentation query - cmake_instrumentation( - API_VERSION 1 - DATA_VERSION 1 - - OPTIONS staticSystemInformation dynamicSystemInformation trace - HOOKS postGenerate preBuild postBuild preCMakeBuild postCMakeBuild postCMakeInstall postCTest - CALLBACK ${BEMAN_CMAKE_INSTRUMENTATION_DIR}/instrumentation.sh - ) - message(WARNING "using callback script ${BB_CMAKE_INSTRUMENTATION_DIR}/instrumentation.sh") - - # Mark task as done in cache - set(BEMAN_CMAKE_INSTRUMENTATION_CONFIGURATION TRUE CACHE INTERNAL "Flag to ensure CMake Instrumentation configured only once") - endif() - -endfunction(configure_beman_cmake_instrumentation) diff --git a/infra/cmake/bemancmakeinstrumentation.cmake b/infra/cmake/bemancmakeinstrumentation.cmake deleted file mode 100755 index 7a171bd3..00000000 --- a/infra/cmake/bemancmakeinstrumentation.cmake +++ /dev/null @@ -1,6 +0,0 @@ -include_guard(GLOBAL) - -cmake_minimum_required (VERSION 4.2) - -find_package(BemanCMakeInstrumentation) -configure_beman_cmake_instrumentation() diff --git a/infra/cmake/instrumentation.sh b/infra/cmake/telemetry.sh similarity index 94% rename from infra/cmake/instrumentation.sh rename to infra/cmake/telemetry.sh index a1568bd1..307cc94c 100755 --- a/infra/cmake/instrumentation.sh +++ b/infra/cmake/telemetry.sh @@ -29,7 +29,7 @@ _ME="$(basename "${0}")" _print_help() { cat <&2 fi } diff --git a/infra/cmake/use-fetch-content.cmake b/infra/cmake/use-fetch-content.cmake index 4ed48397..eb22be4e 100644 --- a/infra/cmake/use-fetch-content.cmake +++ b/infra/cmake/use-fetch-content.cmake @@ -170,6 +170,18 @@ function(BemanExemplar_provideDependency method package_name) set(INSTALL_GTEST OFF) # Disable GoogleTest installation FetchContent_MakeAvailable("${BemanExemplar_name}") + # Catch2's CTest integration module isn't on CMAKE_MODULE_PATH + # when brought in via FetchContent. Add it so that + # `include(Catch)` works. + if(BemanExemplar_pkgName STREQUAL "Catch2") + list( + APPEND + CMAKE_MODULE_PATH + "${${BemanExemplar_name}_SOURCE_DIR}/extras" + ) + set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" PARENT_SCOPE) + endif() + # Important! _FOUND tells CMake that `find_package` is # not needed for this package anymore set("${BemanExemplar_pkgName}_FOUND" TRUE PARENT_SCOPE)