浏览代码

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
Kyle Edwards 3 年之前
父节点
当前提交
aadaac7f6d

+ 1 - 0
Help/manual/cmake-properties.7.rst

@@ -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

+ 13 - 0
Help/prop_tgt/INTERFACE_HEADER_SETS_TO_VERIFY.rst

@@ -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``.)

+ 3 - 0
Help/prop_tgt/VERIFY_INTERFACE_HEADER_SETS.rst

@@ -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`.

+ 3 - 0
Help/release/dev/verify-interface-header-sets.rst

@@ -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`.

+ 23 - 5
Source/cmGeneratorTarget.cxx

@@ -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) {

+ 5 - 0
Tests/RunCMake/VerifyHeaderSets/RunCMakeTest.cmake

@@ -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)

+ 10 - 0
Tests/RunCMake/VerifyHeaderSets/VerifyHeaderSets.cmake

@@ -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")

+ 1 - 0
Tests/RunCMake/VerifyHeaderSets/VerifyHeaderSetsNonexistent-result.txt

@@ -0,0 +1 @@
+1

+ 9 - 0
Tests/RunCMake/VerifyHeaderSets/VerifyHeaderSetsNonexistent-stderr.txt

@@ -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\.$

+ 5 - 0
Tests/RunCMake/VerifyHeaderSets/VerifyHeaderSetsNonexistent.cmake

@@ -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 - 0
Tests/RunCMake/VerifyHeaderSets/error.h

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