to have feature parity with `configure.py`. we won't need this once we migrate to C++20 modules. but before that day comes, we need to stick with C++ headers. we generate a rule for each .hh files to create a corresponding .cc and then compile it, in order to verify the self-containness of that header. so the number of rule is quite large, to avoid the unnecessary overhead. the check-header target is enabled only if `Scylla_CHECK_HEADERS` option is enabled. Signed-off-by: Kefu Chai <kefu.chai@scylladb.com> Closes scylladb/scylladb#15913
105 lines
3.1 KiB
CMake
105 lines
3.1 KiB
CMake
function (check_headers check_headers_target target)
|
|
if(NOT TARGET ${check_headers_target})
|
|
return()
|
|
endif()
|
|
|
|
# "target" is required, so we can get the compiling options for compiling
|
|
# the headers.
|
|
cmake_parse_arguments (
|
|
parsed_args
|
|
""
|
|
"GLOB;GLOB_RECURSE;EXCLUDE;INCLUDE"
|
|
""
|
|
${ARGN})
|
|
|
|
set(sources "")
|
|
if(DEFINED parsed_args_GLOB)
|
|
file(GLOB sources
|
|
LIST_DIRECTORIES false
|
|
RELATIVE ${CMAKE_SOURCE_DIR}
|
|
"${parsed_args_GLOB}")
|
|
elseif(DEFINED parsed_args_GLOB_RECURSE)
|
|
file(GLOB_RECURSE sources
|
|
LIST_DIRECTORIES false
|
|
RELATIVE ${CMAKE_SOURCE_DIR}
|
|
"${parsed_args_RECURSIVE}")
|
|
else()
|
|
message(FATAL_ERROR "Please specify GLOB or GLOB_RECURSE.")
|
|
endif()
|
|
if(DEFINED parsed_args_INCLUDE)
|
|
list(FILTER sources INCLUDE REGEX "${parsed_args_INCLUDE}")
|
|
endif()
|
|
if(DEFINED parsed_args_EXCLUDE)
|
|
list(FILTER sources EXCLUDE REGEX "${parsed_args_EXCLUDE}")
|
|
endif()
|
|
|
|
foreach(fn ${sources})
|
|
get_filename_component(file_dir ${fn} DIRECTORY)
|
|
list(APPEND includes "${CMAKE_SOURCE_DIR}/${file_dir}")
|
|
set(src_dir "${CMAKE_BINARY_DIR}/check-headers/${file_dir}")
|
|
file(MAKE_DIRECTORY "${src_dir}")
|
|
get_filename_component(file_name ${fn} NAME)
|
|
set(src "${src_dir}/${file_name}.cc")
|
|
# CMake refuses to compile .hh files, so we need to rename them first.
|
|
add_custom_command(
|
|
OUTPUT ${src}
|
|
DEPENDS ${CMAKE_SOURCE_DIR}/${fn}
|
|
# silence "-Wpragma-once-outside-header"
|
|
COMMAND sed
|
|
-e "s/^#pragma once//"
|
|
"${fn}" > "${src}"
|
|
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
|
VERBATIM)
|
|
list(APPEND srcs "${src}")
|
|
endforeach()
|
|
|
|
if(NOT srcs)
|
|
# not headers to checks
|
|
return()
|
|
endif()
|
|
|
|
set(check_lib "${check_headers_target}-${target}")
|
|
add_library(${check_lib} EXCLUDE_FROM_ALL)
|
|
target_sources(${check_lib}
|
|
PRIVATE ${srcs})
|
|
# use ${target} as an interface library by consuming all of its
|
|
# compile time options
|
|
get_target_property(libraries ${target} LINK_LIBRARIES)
|
|
if (libraries)
|
|
target_link_libraries(${check_lib}
|
|
PRIVATE ${libraries})
|
|
endif()
|
|
|
|
# if header includes other header files with relative path,
|
|
# we should satisfy it.
|
|
list(REMOVE_DUPLICATES includes)
|
|
target_include_directories(${check_lib}
|
|
PRIVATE ${includes})
|
|
get_target_property(includes ${target} INCLUDE_DIRECTORIES)
|
|
if(includes)
|
|
target_include_directories(${check_lib}
|
|
PRIVATE ${includes})
|
|
endif()
|
|
|
|
get_target_property(compile_options ${target} COMPILE_OPTIONS)
|
|
if(compile_options)
|
|
target_compile_options(${check_lib}
|
|
PRIVATE ${compile_options})
|
|
endif ()
|
|
# symbols in header file should always be referenced, but these
|
|
# are just pure headers, so unused variables should be tolerated.
|
|
target_compile_options(${check_lib}
|
|
PRIVATE
|
|
-Wno-unused-const-variable
|
|
-Wno-unused-function
|
|
-Wno-unused-variable)
|
|
|
|
get_target_property(compile_definitions ${target} COMPILE_DEFINITIONS)
|
|
if(compile_definitions)
|
|
target_compile_definitions(${check_lib}
|
|
PRIVATE ${compile_definitions})
|
|
endif()
|
|
|
|
add_dependencies(${check_headers_target} ${check_lib})
|
|
endfunction ()
|