Verifying header sets not supported for header-only interface libraries

Reading the docs for the VERIFY_INTERFACE_HEADER_SETS property (which seems to be the main place the feature is discussed), it appears that it can’t be used on interface libraries. That seems unexpected, since header-only libraries will often be implemented as an interface library, and these seem to be strong candidates for wanting to use this verification functionality. Was this intentional or an oversight? It seems odd to not support it.

@brad.king @kyle.edwards @bbrown105

I would say it’s an oversight.

My codebase doesn’t really use header-only libraries all that much, mostly because they don’t really add much value once you start packaging the library, shipping accurate package metadata alongside, etc.

I’m not opposed to it, though. Assuming there are no objections, I expect an issue is warranted.

Do the docs need work? Possibly we should have another issue to draft a new guide for this? Given the improvements in ergonomics and the developing C++ module support, I’m hoping FILE_SET becomes the new “modern CMake” way of describing a library to CMake.

I believe this is a relic from the time when it was VERIFY_HEADER_SETS rather than VERIFY_INTERFACE_HEADER_SETS. I will look at updating it.

The code and tests suggest that VERIFY_INTERFACE_HEADER_SETS do indeed support interface libraries, which I think I added during the review process but forgot to document. I will fix the documentation.

Please see cmake!7507.

Follow-up issue 23774 discusses a deficiency in the current behavior (as of 3.24.0-rc4).

The docs definitely need work. I found material on this feature to be quite fragmented, and there’s no clear place with a complete example for how to use it. I don’t know that I’d go so far as a separate guide though, that takes us down the path of many guides for individual features. I don’t think that’s a structure that best suits users.

… and a working example would help too!

if(PROJECT_IS_TOP_LEVEL)
  include(GNUInstallDirs) # for CMAKE_INSTALL_INCLUDEDIR
  set(CMAKE_VERIFY_INTERFACE_HEADER_SETS ON)
endif()

# ---- Declare library ----

file(GLOB headers "include/asio/*.hpp")

add_library(asio INTERFACE ${headers})
add_library(asio::asio ALIAS asio)

set_target_properties(asio PROPERTIES INTERFACE_HEADER_SETS_TO_VERIFY ${headers} )
# TODO(CK): this results in this cmake error!
#   following header sets that are nonexistent or not INTERFACE:
#
#   /Users/clausklein/Workspace/cpp/asio/asio/include/asio/any_io_executor.hpp
#

OK, this works:

# ---- Declare library ----

file(GLOB headers "include/asio/*.hpp")
file(GLOB_RECURSE implementation "include/asio/*/*.hpp" "include/asio/*.ipp")

add_library(asio INTERFACE ${implementation})
add_library(asio::asio ALIAS asio)

target_sources(asio INTERFACE FILE_SET HEADERS
                         BASE_DIRS include
                         FILES ${headers}
)

target_include_directories(
  asio # NO! SYSTEM # XXX ${warning_guard}
  INTERFACE "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>" #
            "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)

target_compile_definitions(asio INTERFACE ASIO_NO_DEPRECATED)
target_compile_features(asio INTERFACE cxx_std_17)