File: VerifyHeaders.cmake

package info (click to toggle)
mongo-c-driver 2.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 47,088 kB
  • sloc: ansic: 193,670; python: 7,780; cpp: 1,493; sh: 659; makefile: 78
file content (116 lines) | stat: -rw-r--r-- 4,642 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
include_guard(DIRECTORY)

#[==[
Add header verification targets for given headers:

    mongo_verify_headers(
        <tag>
        [USES_LIBRARIES [<library> ...]]
        [HEADERS [<glob> ...]]
        [EXCLUDE_REGEX [<pattern> ...]]
    )

Here `<tag>` is an arbitrary string that is used to qualify the internal target
created for the verification. The `<glob>` expressions are used to automatically
collect sources files (relative to the current source directory). All files
collected by `<glob>` must live within the current source directory.

After collecting sources according to the `<glob>` patterns, sources are
excluded if the filepath contains any substring that matches any regular
expression in the `<pattern>` list. Each `<pattern>` is tested against the
relative path to the header file that was found by `<glob>`, and not the
absolute path to the file.

The header verification targets are compiled according to the usage requirements
from all `<library>` arguments.
]==]
function(mongo_verify_headers tag)
    list(APPEND CMAKE_MESSAGE_CONTEXT "${CMAKE_CURRENT_FUNCTION}(${tag})")
    cmake_parse_arguments(
        PARSE_ARGV 1 arg
        ""  # No flags
        ""  # No args
        "HEADERS;EXCLUDE_REGEX;USE_LIBRARIES"  # List args
    )
    if(arg_UNPARSED_ARGUMENTS)
        message(FATAL_ERROR "Unknown arguments: ${arg_UNPARSED_ARGUMENTS}")
    endif()

    # Collect headers according to our patterns
    set(headers_to_verify)
    foreach(pattern IN LISTS arg_HEADERS)
        # Use a recursive glob from the current source dir:
        file(GLOB_RECURSE more
            # Make the paths relative to the calling dir to prevent parent paths
            # from interfering with the exclusion regex logic below
            RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
            # We need to re-run configuration if any files are added/removed
            CONFIGURE_DEPENDS
            "${pattern}"
            )
        # Warn if this pattern didn't match anything. It is probably a mistake
        # in the caller's argument list.
        if(NOT more)
            message(WARNING "Globbing pattern “${pattern}” did not match any files")
        endif()
        list(APPEND headers_to_verify ${more})
    endforeach()

    # Exclude anything that matches any exclusion regex
    foreach(pattern IN LISTS arg_EXCLUDE_REGEX)
        list(FILTER headers_to_verify EXCLUDE REGEX "${pattern}")
    endforeach()

    # Drop duplicates since globs may grab a file more than once
    list(REMOVE_DUPLICATES headers_to_verify)
    list(SORT headers_to_verify)
    foreach(file IN LISTS headers_to_verify)
        message(DEBUG "Verify header file: ${file}")
    endforeach()

    # We create two targets: One for C and one for C++
    # C target
    set(c_target ${tag}-verify-headers-c)
    message(DEBUG "Defining header verification target “${c_target}” (C)")
    # Create object libraries. They will only have one empty compiled source file.
    # The source file language will tell CMake how to verify the associated header files.
    add_library(${c_target} OBJECT "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/empty.c")
    # Define the file set
    target_sources(${c_target} PUBLIC FILE_SET HEADERS)
    # Conditionally do the same thing for C++
    if(CMAKE_CXX_COMPILER)
        # C++ is available. define it
        set(cxx_target ${tag}-verify-headers-cxx)
        message(DEBUG "Defining header verification targets “${cxx_target}” (C++)")
        add_library(${cxx_target} OBJECT "${CMAKE_CURRENT_FUNCTION_LIST_DIR}/empty.cpp")
        target_sources(${cxx_target} PUBLIC FILE_SET HEADERS)
    else()
        message(AUTHOR_WARNING "No C++ compiler is available, so the header-check C++ targets won't be defined")
        unset(cxx_target)
    endif()
    # Populate the properties and file sets.
    set_target_properties(${c_target} ${cxx_target} PROPERTIES
        # The main header file set:
        HEADER_SET "${headers_to_verify}"
        # Enable header verification:
        VERIFY_INTERFACE_HEADER_SETS TRUE
        # Add the usage requirements that propagate to the generated compilation rules:
        INTERFACE_LINK_LIBRARIES "${arg_USE_LIBRARIES}"
        )
endfunction()

#[[
Variable set to TRUE if-and-only-if CMake supports header verification.
]]
set(MONGO_CAN_VERIFY_HEADERS FALSE)
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24")
    set(MONGO_CAN_VERIFY_HEADERS TRUE)
endif()

# Try to enable C++, but don't require it. This will be used to conditionally
# define the C++ header-check tests
include(CheckLanguage)
check_language(CXX)
if(CMAKE_CXX_COMPILER)
    enable_language(CXX)
endif()