]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/hana/cmake/TestHeaders.cmake
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / libs / hana / cmake / TestHeaders.cmake
1 # Copyright Louis Dionne 2013-2017
2 # Distributed under the Boost Software License, Version 1.0.
3 # (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
4 #
5 #
6 # This CMake module provides a function generating a unit test to make sure
7 # that every public header can be included on its own.
8 #
9 # When a C++ library or application has many header files, it can happen that
10 # a header does not include all the other headers it depends on. When this is
11 # the case, it can happen that including that header file on its own will
12 # break the compilation. This CMake module generates a dummy executable
13 # comprised of many .cpp files, each of which includes a header file that
14 # is part of the public API. In other words, the executable is comprised
15 # of .cpp files of the form:
16 #
17 # #include <the/public/header.hpp>
18 #
19 # and then exactly one `main` function. If this succeeds to compile, it means
20 # that the header can be included on its own, which is what clients expect.
21 # Otherwise, you have a problem. Since writing these dumb unit tests by hand
22 # is tedious and repetitive, you can use this CMake module to automate this
23 # task.
24
25 # add_header_test(<target> [EXCLUDE_FROM_ALL] [EXCLUDE excludes...] HEADERS headers...)
26 #
27 # Generates header-inclusion unit tests for all the specified headers.
28 #
29 # This function creates a target which builds a dummy executable including
30 # each specified header file individually. If this target builds successfully,
31 # it means that all the specified header files can be included individually.
32 #
33 # Parameters
34 # ----------
35 # <target>:
36 # The name of the target to generate.
37 #
38 # HEADERS headers:
39 # A list of header files to generate the inclusion tests for. All headers
40 # in this list must be represented as relative paths from the root of the
41 # include directory added to the compiler's header search path. In other
42 # words, it should be possible to include all headers in this list as
43 #
44 # #include <${header}>
45 #
46 # For example, for a library with the following structure:
47 #
48 # project/
49 # doc/
50 # test/
51 # ...
52 # include/
53 # boost/
54 # hana.hpp
55 # hana/
56 # transform.hpp
57 # tuple.hpp
58 # pair.hpp
59 # ...
60 #
61 # When building the unit tests for that library, we'll add `-I project/include'
62 # to the compiler's arguments. The list of public headers should therefore contain
63 #
64 # boost/hana.hpp
65 # boost/hana/transform.hpp
66 # boost/hana/tuple.hpp
67 # boost/hana/pair.hpp
68 # ...
69 #
70 # Usually, all the 'public' header files of a library should be tested for
71 # standalone inclusion. A header is considered 'public' if a client should
72 # be able to include that header on its own.
73 #
74 # [EXCLUDE excludes]:
75 # An optional list of headers or regexes for which no unit test should be
76 # generated. Basically, any header in the list specified by the `HEADERS`
77 # argument that matches anything in `EXCLUDE` will be skipped.
78 #
79 # [EXCLUDE_FROM_ALL]:
80 # If provided, the generated target is excluded from the 'all' target.
81 #
82 function(add_header_test target)
83 cmake_parse_arguments(ARGS "EXCLUDE_FROM_ALL" # options
84 "" # 1 value args
85 "HEADERS;EXCLUDE" # multivalued args
86 ${ARGN})
87 if (NOT ARGS_HEADERS)
88 message(FATAL_ERROR "The `HEADERS` argument must be provided.")
89 endif()
90
91 if (ARGS_EXCLUDE_FROM_ALL)
92 set(ARGS_EXCLUDE_FROM_ALL "EXCLUDE_FROM_ALL")
93 else()
94 set(ARGS_EXCLUDE_FROM_ALL "")
95 endif()
96
97 foreach(header ${ARGS_HEADERS})
98 set(skip FALSE)
99 foreach(exclude ${ARGS_EXCLUDE})
100 if (${header} MATCHES ${exclude})
101 set(skip TRUE)
102 break()
103 endif()
104 endforeach()
105 if (skip)
106 continue()
107 endif()
108
109 get_filename_component(filename "${header}" NAME_WE)
110 get_filename_component(directory "${header}" DIRECTORY)
111
112 set(source "${CMAKE_CURRENT_BINARY_DIR}/headers/${directory}/${filename}.cpp")
113 if (NOT EXISTS "${source}")
114 file(WRITE "${source}" "#include <${header}>")
115 endif()
116 list(APPEND sources "${source}")
117 endforeach()
118
119 set(standalone_main "${CMAKE_CURRENT_BINARY_DIR}/headers/_standalone_main.cpp")
120 if (NOT EXISTS "${standalone_main}")
121 file(WRITE "${standalone_main}" "int main() { }")
122 endif()
123 add_executable(${target}
124 ${ARGS_EXCLUDE_FROM_ALL}
125 ${sources}
126 "${CMAKE_CURRENT_BINARY_DIR}/headers/_standalone_main.cpp"
127 )
128 endfunction()