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
+1
View File
@@ -263,6 +263,7 @@ Properties on Targets
/prop_tgt/INTERFACE_COMPILE_FEATURES /prop_tgt/INTERFACE_COMPILE_FEATURES
/prop_tgt/INTERFACE_COMPILE_OPTIONS /prop_tgt/INTERFACE_COMPILE_OPTIONS
/prop_tgt/INTERFACE_HEADER_SETS /prop_tgt/INTERFACE_HEADER_SETS
/prop_tgt/INTERFACE_HEADER_SETS_TO_VERIFY
/prop_tgt/INTERFACE_INCLUDE_DIRECTORIES /prop_tgt/INTERFACE_INCLUDE_DIRECTORIES
/prop_tgt/INTERFACE_LINK_DEPENDS /prop_tgt/INTERFACE_LINK_DEPENDS
/prop_tgt/INTERFACE_LINK_DIRECTORIES /prop_tgt/INTERFACE_LINK_DIRECTORIES
@@ -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``.)
@@ -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, 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. 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`.
@@ -7,3 +7,6 @@ verify-interface-header-sets
* A new :variable:`CMAKE_VERIFY_INTERFACE_HEADER_SETS` variable was added, * A new :variable:`CMAKE_VERIFY_INTERFACE_HEADER_SETS` variable was added,
which is used to initialize the :prop_tgt:`VERIFY_INTERFACE_HEADER_SETS` which is used to initialize the :prop_tgt:`VERIFY_INTERFACE_HEADER_SETS`
target property. 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`.
+23 -5
View File
@@ -8525,19 +8525,37 @@ bool cmGeneratorTarget::AddHeaderSetVerification()
return true; 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; cmTarget* verifyTarget = nullptr;
auto interfaceFileSetEntries = this->Target->GetInterfaceHeaderSetsEntries(); auto interfaceFileSetEntries = this->Target->GetInterfaceHeaderSetsEntries();
std::set<cmFileSet*> fileSets; std::set<cmFileSet*> fileSets;
auto const addFileSets = [&fileSets, this](const cmBTStringRange& entries) { for (auto const& entry : interfaceFileSetEntries) {
for (auto const& entry : entries) { for (auto const& name : cmExpandedList(entry.Value)) {
for (auto const& name : cmExpandedList(entry.Value)) { if (all || verifySet.count(name)) {
fileSets.insert(this->Target->GetFileSet(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; cm::optional<std::set<std::string>> languages;
for (auto* fileSet : fileSets) { for (auto* fileSet : fileSets) {
@@ -40,3 +40,8 @@ endif()
run_cmake_build(VerifyHeaderSets lang_test_c_verify_interface_header_sets) 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 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)
@@ -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) add_library(lang_test_cxx STATIC lib.c lib.cxx)
target_compile_definitions(lang_test_cxx INTERFACE EXPECT_CXX) target_compile_definitions(lang_test_cxx INTERFACE EXPECT_CXX)
target_sources(lang_test_cxx INTERFACE FILE_SET HEADERS FILES lang_test.h) 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")
@@ -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\.$
@@ -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")
+3
View File
@@ -0,0 +1,3 @@
#error "This file should not be included"
extern void error_h(void);