You Should Add FeatureSummary to your CMake Projects
Here’s a common problem: your cmake build is failing with linker errors, and now your’re looking through your CMake logs and reading the compilation database to see what libraries were actually included.
What if I told you that there was a better way? Enter Feature Summary.
Basic Usage
The FeatureSummary module has two parts
add_feature_info(<name>, <condition>, <description>) to add entries to the summary.
feature_summary(WHAT ALL) to print the summary.
In short, add include(FeatureSummary) to make the commands available to downstream modules, then when declaring options, add them to the summary with add_feature_info.
cmake_minimum_required(VERSION 3.28)
project(FeatureSummaryExample)
include(FeatureSummary)
# Will be reported in the feature summary without further intervention
find_package(Threads REQUIRED)
find_package(Catch2 3)
# Create an option, and add it to feature summary
option(WERROR "Enable -Werror to turn warnings into errors" False)
add_feature_info(
Werror WERROR "Enable -Werror to turn warnings into errors"
)
option(RUN_CLANG_TIDY "Run clang-tidy as part of the build" False)
add_feature_info(
"Run Clang Tidy" RUN_CLANG_TIDY "Run clang tidy as part of the build"
)
# Print the feature summary
feature_summary(WHAT ALL)
When you run cmake, the options you set (or did not set) will be printed out:
-- The following features have been enabled:
* Werror, Enable -Werror to turn warnings into errors
-- The following REQUIRED packages have been found:
* Threads
-- The following features have been disabled:
* Run Clang Tidy, Run clang tidy as part of the build
-- The following OPTIONAL packages have not been found:
* Catch2 (required version >= 3)
-- Configuring done (0.2s)
Making it Less Verbose
Having to declare an option and then calling add_feature_info each time quickly becomes tedious. A quick script can improve this significantly.
include(FeatureSummary)
function(add_feature_option
_variable_name
_option_description
_option_default
)
if(NOT DEFINED default)
set(default OFF)
endif()
# option(<variable> "<help_text>" [value])
option(${_variable_name} ${_option_description} ${_option_default})
# add_feature_info(<name> <enabled> <description>)
set(_option_value ${${_variable_name}})
add_feature_info(
"${PROJECT_NAME}::${_variable_name}"
${_option_value}
${_option_description}
)
endfunction()
This function declares the option, and adds it to the feature summary in a single pass, saving us quite some typing (and ensuring that all options are always in the feature summary).
cmake_minimum_required(VERSION 3.28)
project(FeatureSummaryExample)
include(FeatureSummary)
include(AddFeatureOption)
# Will be reported in the feature summary without further intervention
find_package(Catch2 3 QUIET)
# Create an option, and add it to feature summary
add_feature_option(
WERROR "Enable -Werror to turn warnings into errors" False
)
add_feature_option(
RUN_CLANG_TIDY "Run clang-tidy as part of the build" False
)
# Print the feature summary
feature_summary(WHAT ALL)