developer might notice that when he/she builds 'check-headers', the whole tree is built. so let's explain this behavior. Signed-off-by: Kefu Chai <kefu.chai@scylladb.com> Closes scylladb/scylladb#16062
111 lines
3.5 KiB
CMake
111 lines
3.5 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)
|
|
# as a side effect, the libraries linked by the ${target} are also built as
|
|
# the dependencies of ${check_lib}. some of the libraries are scylla
|
|
# libraries. we could tell them from the 3rd party libraries, but we would
|
|
# have to recursively pull in their compiling options. so, since that
|
|
# we always build "check-headers" target along with "scylla", this does
|
|
# not incur overhead.
|
|
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 ()
|