VERIFY_INTERFACE_HEADER_SETS: Add property for list of header sets

Add a new property, INTERFACE_HEADER_SETS_TO_VERIFY, which contains
a list of header sets that should be verified by
VERIFY_INTERFACE_HEADER_SETS.

Fixes: #23522
This commit is contained in:
Kyle Edwards
2022-05-25 14:33:38 -04:00
parent 5dcf505f63
commit aadaac7f6d
11 changed files with 76 additions and 5 deletions

View File

@@ -263,6 +263,7 @@ Properties on Targets
/prop_tgt/INTERFACE_COMPILE_FEATURES
/prop_tgt/INTERFACE_COMPILE_OPTIONS
/prop_tgt/INTERFACE_HEADER_SETS
/prop_tgt/INTERFACE_HEADER_SETS_TO_VERIFY
/prop_tgt/INTERFACE_INCLUDE_DIRECTORIES
/prop_tgt/INTERFACE_LINK_DEPENDS
/prop_tgt/INTERFACE_LINK_DIRECTORIES

View File

@@ -0,0 +1,13 @@
INTERFACE_HEADER_SETS_TO_VERIFY
-------------------------------
.. versionadded:: 3.24
Used to specify which ``PUBLIC`` and ``INTERFACE`` header sets of a target
should be verified.
This property contains a semicolon-separated list of header sets which
should be verified if :prop_tgt:`VERIFY_INTERFACE_HEADER_SETS` is set to
``TRUE``. If the list is empty, all ``PUBLIC`` and ``INTERFACE`` header sets
are verified. (If the project does not want to verify any header sets on the
target, simply set :prop_tgt:`VERIFY_INTERFACE_HEADER_SETS` to ``FALSE``.)

View File

@@ -23,3 +23,6 @@ is used to determine the language with which to compile the header file.
Otherwise, if the target has any C++ sources, the header is compiled as C++.
Otherwise, if the target has any C sources, the header is compiled as C.
Otherwise, the header file is not compiled.
If the project wishes to control which header sets are verified by this
property, you can set :prop_tgt:`INTERFACE_HEADER_SETS_TO_VERIFY`.

View File

@@ -7,3 +7,6 @@ verify-interface-header-sets
* A new :variable:`CMAKE_VERIFY_INTERFACE_HEADER_SETS` variable was added,
which is used to initialize the :prop_tgt:`VERIFY_INTERFACE_HEADER_SETS`
target property.
* A new :prop_tgt:`INTERFACE_HEADER_SETS_TO_VERIFY` target property was added,
which can be used to specify which header sets should be verified by
:prop_tgt:`VERIFY_INTERFACE_HEADER_SETS`.

View File

@@ -8525,19 +8525,37 @@ bool cmGeneratorTarget::AddHeaderSetVerification()
return true;
}
auto verifyValue = this->GetProperty("INTERFACE_HEADER_SETS_TO_VERIFY");
const bool all = verifyValue.IsEmpty();
std::set<std::string> verifySet;
if (!all) {
auto verifyList = cmExpandedList(verifyValue);
verifySet.insert(verifyList.begin(), verifyList.end());
}
cmTarget* verifyTarget = nullptr;
auto interfaceFileSetEntries = this->Target->GetInterfaceHeaderSetsEntries();
std::set<cmFileSet*> fileSets;
auto const addFileSets = [&fileSets, this](const cmBTStringRange& entries) {
for (auto const& entry : entries) {
for (auto const& name : cmExpandedList(entry.Value)) {
for (auto const& entry : interfaceFileSetEntries) {
for (auto const& name : cmExpandedList(entry.Value)) {
if (all || verifySet.count(name)) {
fileSets.insert(this->Target->GetFileSet(name));
verifySet.erase(name);
}
}
};
addFileSets(interfaceFileSetEntries);
}
if (!verifySet.empty()) {
this->Makefile->IssueMessage(
MessageType::FATAL_ERROR,
cmStrCat("Property INTERFACE_HEADER_SETS_TO_VERIFY of target \"",
this->GetName(),
"\" contained the following header sets that are nonexistent "
"or not INTERFACE:\n ",
cmJoin(verifySet, "\n ")));
return false;
}
cm::optional<std::set<std::string>> languages;
for (auto* fileSet : fileSets) {

View File

@@ -40,3 +40,8 @@ endif()
run_cmake_build(VerifyHeaderSets lang_test_c_verify_interface_header_sets)
run_cmake_build(VerifyHeaderSets lang_test_cxx_verify_interface_header_sets)
run_cmake_build(VerifyHeaderSets list_verify_interface_header_sets)
set(RunCMake_TEST_OPTIONS -DCMAKE_VERIFY_INTERFACE_HEADER_SETS=ON)
run_cmake(VerifyHeaderSetsNonexistent)
unset(RunCMake_TEST_OPTIONS)

View File

@@ -58,3 +58,13 @@ target_sources(lang_test_c INTERFACE FILE_SET HEADERS FILES lang_test.h)
add_library(lang_test_cxx STATIC lib.c lib.cxx)
target_compile_definitions(lang_test_cxx INTERFACE EXPECT_CXX)
target_sources(lang_test_cxx INTERFACE FILE_SET HEADERS FILES lang_test.h)
set_property(SOURCE error.h PROPERTY LANGUAGE C)
add_library(list STATIC lib.c)
target_sources(list INTERFACE
FILE_SET a TYPE HEADERS FILES a.h
FILE_SET c TYPE HEADERS FILES dir/c.h
FILE_SET error TYPE HEADERS FILES error.h
)
set_property(TARGET list PROPERTY INTERFACE_HEADER_SETS_TO_VERIFY "a;c")

View File

@@ -0,0 +1,9 @@
^CMake Error in CMakeLists\.txt:
Property INTERFACE_HEADER_SETS_TO_VERIFY of target "nonexistent" contained
the following header sets that are nonexistent or not INTERFACE:
b
c
CMake Generate step failed\. Build files cannot be regenerated correctly\.$

View File

@@ -0,0 +1,5 @@
enable_language(C)
add_library(nonexistent STATIC lib.c)
target_sources(nonexistent INTERFACE FILE_SET a TYPE HEADERS FILES a.h)
set_property(TARGET nonexistent PROPERTY INTERFACE_HEADER_SETS_TO_VERIFY "a;c;b")

View File

@@ -0,0 +1,3 @@
#error "This file should not be included"
extern void error_h(void);