summaryrefslogtreecommitdiffstats
path: root/src/boost/libs/hana/cmake/TestHeaders.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'src/boost/libs/hana/cmake/TestHeaders.cmake')
-rw-r--r--src/boost/libs/hana/cmake/TestHeaders.cmake128
1 files changed, 128 insertions, 0 deletions
diff --git a/src/boost/libs/hana/cmake/TestHeaders.cmake b/src/boost/libs/hana/cmake/TestHeaders.cmake
new file mode 100644
index 000000000..663c9f4e8
--- /dev/null
+++ b/src/boost/libs/hana/cmake/TestHeaders.cmake
@@ -0,0 +1,128 @@
+# Copyright Louis Dionne 2013-2017
+# Distributed under the Boost Software License, Version 1.0.
+# (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
+#
+#
+# This CMake module provides a function generating a unit test to make sure
+# that every public header can be included on its own.
+#
+# When a C++ library or application has many header files, it can happen that
+# a header does not include all the other headers it depends on. When this is
+# the case, it can happen that including that header file on its own will
+# break the compilation. This CMake module generates a dummy executable
+# comprised of many .cpp files, each of which includes a header file that
+# is part of the public API. In other words, the executable is comprised
+# of .cpp files of the form:
+#
+# #include <the/public/header.hpp>
+#
+# and then exactly one `main` function. If this succeeds to compile, it means
+# that the header can be included on its own, which is what clients expect.
+# Otherwise, you have a problem. Since writing these dumb unit tests by hand
+# is tedious and repetitive, you can use this CMake module to automate this
+# task.
+
+# add_header_test(<target> [EXCLUDE_FROM_ALL] [EXCLUDE excludes...] HEADERS headers...)
+#
+# Generates header-inclusion unit tests for all the specified headers.
+#
+# This function creates a target which builds a dummy executable including
+# each specified header file individually. If this target builds successfully,
+# it means that all the specified header files can be included individually.
+#
+# Parameters
+# ----------
+# <target>:
+# The name of the target to generate.
+#
+# HEADERS headers:
+# A list of header files to generate the inclusion tests for. All headers
+# in this list must be represented as relative paths from the root of the
+# include directory added to the compiler's header search path. In other
+# words, it should be possible to include all headers in this list as
+#
+# #include <${header}>
+#
+# For example, for a library with the following structure:
+#
+# project/
+# doc/
+# test/
+# ...
+# include/
+# boost/
+# hana.hpp
+# hana/
+# transform.hpp
+# tuple.hpp
+# pair.hpp
+# ...
+#
+# When building the unit tests for that library, we'll add `-I project/include'
+# to the compiler's arguments. The list of public headers should therefore contain
+#
+# boost/hana.hpp
+# boost/hana/transform.hpp
+# boost/hana/tuple.hpp
+# boost/hana/pair.hpp
+# ...
+#
+# Usually, all the 'public' header files of a library should be tested for
+# standalone inclusion. A header is considered 'public' if a client should
+# be able to include that header on its own.
+#
+# [EXCLUDE excludes]:
+# An optional list of headers or regexes for which no unit test should be
+# generated. Basically, any header in the list specified by the `HEADERS`
+# argument that matches anything in `EXCLUDE` will be skipped.
+#
+# [EXCLUDE_FROM_ALL]:
+# If provided, the generated target is excluded from the 'all' target.
+#
+function(add_header_test target)
+ cmake_parse_arguments(ARGS "EXCLUDE_FROM_ALL" # options
+ "" # 1 value args
+ "HEADERS;EXCLUDE" # multivalued args
+ ${ARGN})
+ if (NOT ARGS_HEADERS)
+ message(FATAL_ERROR "The `HEADERS` argument must be provided.")
+ endif()
+
+ if (ARGS_EXCLUDE_FROM_ALL)
+ set(ARGS_EXCLUDE_FROM_ALL "EXCLUDE_FROM_ALL")
+ else()
+ set(ARGS_EXCLUDE_FROM_ALL "")
+ endif()
+
+ foreach(header ${ARGS_HEADERS})
+ set(skip FALSE)
+ foreach(exclude ${ARGS_EXCLUDE})
+ if (${header} MATCHES ${exclude})
+ set(skip TRUE)
+ break()
+ endif()
+ endforeach()
+ if (skip)
+ continue()
+ endif()
+
+ get_filename_component(filename "${header}" NAME_WE)
+ get_filename_component(directory "${header}" DIRECTORY)
+
+ set(source "${CMAKE_CURRENT_BINARY_DIR}/headers/${directory}/${filename}.cpp")
+ if (NOT EXISTS "${source}")
+ file(WRITE "${source}" "#include <${header}>")
+ endif()
+ list(APPEND sources "${source}")
+ endforeach()
+
+ set(standalone_main "${CMAKE_CURRENT_BINARY_DIR}/headers/_standalone_main.cpp")
+ if (NOT EXISTS "${standalone_main}")
+ file(WRITE "${standalone_main}" "int main() { }")
+ endif()
+ add_executable(${target}
+ ${ARGS_EXCLUDE_FROM_ALL}
+ ${sources}
+ "${CMAKE_CURRENT_BINARY_DIR}/headers/_standalone_main.cpp"
+ )
+endfunction()