summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2022-04-12 14:05:13 (GMT)
committerKitware Robot <kwrobot@kitware.com>2022-04-12 14:05:26 (GMT)
commitf6476ba3a6b13a5323dbcfb8c87acb866b5c9db1 (patch)
treea845cadd9cc1ec6018b642d1cb529f674a5510f5
parentb41f2695bcc4d93e963e20a5d407a01c97164150 (diff)
parent5fa15ec9f34d69b2a6b1ce08a6102f16c5d7ab9b (diff)
downloadCMake-f6476ba3a6b13a5323dbcfb8c87acb866b5c9db1.zip
CMake-f6476ba3a6b13a5323dbcfb8c87acb866b5c9db1.tar.gz
CMake-f6476ba3a6b13a5323dbcfb8c87acb866b5c9db1.tar.bz2
Merge topic 'file-set-repr-improvements'
5fa15ec9f3 Help: Document that target_sources defines [INTERFACE_]HEADER_SETS c5d4812f20 cmTarget: make HEADER_SETS and INTERFACE_HEADER_SETS read-only 05783b168d cmFileSet: store visibility with the fileset Acked-by: Kitware Robot <kwrobot@kitware.com> Merge-request: !7168
-rw-r--r--Help/prop_tgt/HEADER_SETS.rst13
-rw-r--r--Help/prop_tgt/INTERFACE_HEADER_SETS.rst8
-rw-r--r--Help/release/3.23.rst8
-rw-r--r--Source/cmFileSet.cxx62
-rw-r--r--Source/cmFileSet.h21
-rw-r--r--Source/cmTarget.cxx97
-rw-r--r--Source/cmTarget.h5
-rw-r--r--Source/cmTargetSourcesCommand.cxx52
-rw-r--r--Tests/RunCMake/target_sources/FileSetImport.cmake4
-rw-r--r--Tests/RunCMake/target_sources/FileSetNoExistInterface-result.txt1
-rw-r--r--Tests/RunCMake/target_sources/FileSetNoExistInterface-stderr.txt4
-rw-r--r--Tests/RunCMake/target_sources/FileSetNoExistPrivate-stderr.txt4
-rw-r--r--Tests/RunCMake/target_sources/FileSetNoExistPrivate.cmake7
-rw-r--r--Tests/RunCMake/target_sources/FileSetNoScope-stderr.txt4
-rw-r--r--Tests/RunCMake/target_sources/FileSetNoScope.cmake6
-rw-r--r--Tests/RunCMake/target_sources/FileSetProperties.cmake4
-rw-r--r--Tests/RunCMake/target_sources/FileSetReadOnlyInterface-result.txt (renamed from Tests/RunCMake/target_sources/FileSetNoScope-result.txt)0
-rw-r--r--Tests/RunCMake/target_sources/FileSetReadOnlyInterface-stderr.txt5
-rw-r--r--Tests/RunCMake/target_sources/FileSetReadOnlyInterface.cmake (renamed from Tests/RunCMake/target_sources/FileSetNoExistInterface.cmake)3
-rw-r--r--Tests/RunCMake/target_sources/FileSetReadOnlyPrivate-result.txt (renamed from Tests/RunCMake/target_sources/FileSetNoExistPrivate-result.txt)0
-rw-r--r--Tests/RunCMake/target_sources/FileSetReadOnlyPrivate-stderr.txt5
-rw-r--r--Tests/RunCMake/target_sources/FileSetReadOnlyPrivate.cmake4
-rw-r--r--Tests/RunCMake/target_sources/RunCMakeTest.cmake5
23 files changed, 172 insertions, 150 deletions
diff --git a/Help/prop_tgt/HEADER_SETS.rst b/Help/prop_tgt/HEADER_SETS.rst
index fcf723e..ceb1df5 100644
--- a/Help/prop_tgt/HEADER_SETS.rst
+++ b/Help/prop_tgt/HEADER_SETS.rst
@@ -3,14 +3,13 @@ HEADER_SETS
.. versionadded:: 3.23
-List of the target's ``PRIVATE`` and ``PUBLIC`` header sets (i.e. all
-file sets with the type ``HEADERS``). Files listed in these file sets
-are treated as source files for the purpose of IDE integration.
-The files also have their :prop_sf:`HEADER_FILE_ONLY` property set to
-``TRUE``.
+Read-only list of the target's ``PRIVATE`` and ``PUBLIC`` header sets (i.e.
+all file sets with the type ``HEADERS``). Files listed in these file sets are
+treated as source files for the purpose of IDE integration. The files also
+have their :prop_sf:`HEADER_FILE_ONLY` property set to ``TRUE``.
-This property is normally only set by :command:`target_sources(FILE_SET)`
-rather than being manipulated directly.
+Header sets may be defined using the :command:`target_sources` command
+``FILE_SET`` option with type ``HEADERS``.
See also :prop_tgt:`HEADER_SET_<NAME>`, :prop_tgt:`HEADER_SET` and
:prop_tgt:`INTERFACE_HEADER_SETS`.
diff --git a/Help/prop_tgt/INTERFACE_HEADER_SETS.rst b/Help/prop_tgt/INTERFACE_HEADER_SETS.rst
index 62db5b3..2d3bdac 100644
--- a/Help/prop_tgt/INTERFACE_HEADER_SETS.rst
+++ b/Help/prop_tgt/INTERFACE_HEADER_SETS.rst
@@ -3,12 +3,12 @@ INTERFACE_HEADER_SETS
.. versionadded:: 3.23
-List of the target's ``INTERFACE`` and ``PUBLIC`` header sets (i.e. all
-file sets with the type ``HEADERS``). Files listed in these header sets
+Read-only list of the target's ``INTERFACE`` and ``PUBLIC`` header sets (i.e.
+all file sets with the type ``HEADERS``). Files listed in these header sets
can be installed with :command:`install(TARGETS)` and exported with
:command:`install(EXPORT)` and :command:`export`.
-This property is normally only set by :command:`target_sources(FILE_SET)`
-rather than being manipulated directly.
+Header sets may be defined using the :command:`target_sources` command
+``FILE_SET`` option with type ``HEADERS``.
See also :prop_tgt:`HEADER_SETS`.
diff --git a/Help/release/3.23.rst b/Help/release/3.23.rst
index 257c3d5..2febbec 100644
--- a/Help/release/3.23.rst
+++ b/Help/release/3.23.rst
@@ -114,8 +114,8 @@ Variables
Properties
----------
-* The :prop_tgt:`HEADER_SETS` and :prop_tgt:`INTERFACE_HEADER_SETS` target
- properties were added to list header sets associated with a target.
+* The :prop_tgt:`HEADER_SETS` and :prop_tgt:`INTERFACE_HEADER_SETS` read-only
+ target properties were added to list header sets associated with a target.
* The :prop_tgt:`HEADER_SET` and :prop_tgt:`HEADER_SET_<NAME>` target
properties were added to list files in the default header set
@@ -278,3 +278,7 @@ Changes made since CMake 3.23.0 include the following.
targets. Pending further work in a future version of CMake, it is now
an error to add a ``FILE_SET`` of type ``HEADERS`` to such targets on
Apple platforms.
+
+* The :prop_tgt:`HEADER_SETS` and :prop_tgt:`INTERFACE_HEADER_SETS` target
+ properties added in CMake 3.23.0 are now read-only records of the header
+ sets created by the :command:`target_sources` command.
diff --git a/Source/cmFileSet.cxx b/Source/cmFileSet.cxx
index 2c06dc6..1d1d29e 100644
--- a/Source/cmFileSet.cxx
+++ b/Source/cmFileSet.cxx
@@ -7,19 +7,79 @@
#include <utility>
#include <vector>
+#include <cmext/string_view>
+
#include "cmsys/RegularExpression.hxx"
#include "cmGeneratorExpression.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
+#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmake.h"
-cmFileSet::cmFileSet(std::string name, std::string type)
+cm::static_string_view cmFileSetVisibilityToName(cmFileSetVisibility vis)
+{
+ switch (vis) {
+ case cmFileSetVisibility::Interface:
+ return "INTERFACE"_s;
+ case cmFileSetVisibility::Public:
+ return "PUBLIC"_s;
+ case cmFileSetVisibility::Private:
+ return "PRIVATE"_s;
+ }
+ return ""_s;
+}
+
+cmFileSetVisibility cmFileSetVisibilityFromName(cm::string_view name,
+ cmMakefile* mf)
+{
+ if (name == "INTERFACE"_s) {
+ return cmFileSetVisibility::Interface;
+ }
+ if (name == "PUBLIC"_s) {
+ return cmFileSetVisibility::Public;
+ }
+ if (name == "PRIVATE"_s) {
+ return cmFileSetVisibility::Private;
+ }
+ mf->IssueMessage(
+ MessageType::FATAL_ERROR,
+ cmStrCat("File set visibility \"", name, "\" is not valid."));
+ return cmFileSetVisibility::Private;
+}
+
+bool cmFileSetVisibilityIsForSelf(cmFileSetVisibility vis)
+{
+ switch (vis) {
+ case cmFileSetVisibility::Interface:
+ return false;
+ case cmFileSetVisibility::Public:
+ case cmFileSetVisibility::Private:
+ return true;
+ }
+ return false;
+}
+
+bool cmFileSetVisibilityIsForInterface(cmFileSetVisibility vis)
+{
+ switch (vis) {
+ case cmFileSetVisibility::Interface:
+ case cmFileSetVisibility::Public:
+ return true;
+ case cmFileSetVisibility::Private:
+ return false;
+ }
+ return false;
+}
+
+cmFileSet::cmFileSet(std::string name, std::string type,
+ cmFileSetVisibility visibility)
: Name(std::move(name))
, Type(std::move(type))
+ , Visibility(visibility)
{
}
diff --git a/Source/cmFileSet.h b/Source/cmFileSet.h
index 3aad75f..5357e77 100644
--- a/Source/cmFileSet.h
+++ b/Source/cmFileSet.h
@@ -7,20 +7,38 @@
#include <string>
#include <vector>
+#include <cm/string_view>
+#include <cmext/string_view>
+
#include "cmListFileCache.h"
class cmCompiledGeneratorExpression;
struct cmGeneratorExpressionDAGChecker;
class cmGeneratorTarget;
class cmLocalGenerator;
+class cmMakefile;
+
+enum class cmFileSetVisibility
+{
+ Private,
+ Public,
+ Interface,
+};
+cm::static_string_view cmFileSetVisibilityToName(cmFileSetVisibility vis);
+cmFileSetVisibility cmFileSetVisibilityFromName(cm::string_view name,
+ cmMakefile* mf);
+bool cmFileSetVisibilityIsForSelf(cmFileSetVisibility vis);
+bool cmFileSetVisibilityIsForInterface(cmFileSetVisibility vis);
class cmFileSet
{
public:
- cmFileSet(std::string name, std::string type);
+ cmFileSet(std::string name, std::string type,
+ cmFileSetVisibility visibility);
const std::string& GetName() const { return this->Name; }
const std::string& GetType() const { return this->Type; }
+ cmFileSetVisibility GetVisibility() const { return this->Visibility; }
void ClearDirectoryEntries();
void AddDirectoryEntry(BT<std::string> directories);
@@ -61,6 +79,7 @@ public:
private:
std::string Name;
std::string Type;
+ cmFileSetVisibility Visibility;
std::vector<BT<std::string>> DirectoryEntries;
std::vector<BT<std::string>> FileEntries;
};
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index e2314e2..5c43bc8 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -1484,37 +1484,14 @@ void cmTarget::StoreProperty(const std::string& prop, ValueType value)
BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
}
} else if (prop == propHEADER_SETS) {
- if (value) {
- for (auto const& name : cmExpandedList(value)) {
- if (!this->GetFileSet(name)) {
- this->impl->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("Header set \"", name, "\" has not yet been created."));
- return;
- }
- }
- }
- this->impl->HeaderSetsEntries.clear();
- if (!StringIsEmpty(value)) {
- this->impl->HeaderSetsEntries.emplace_back(
- value, this->impl->Makefile->GetBacktrace());
- }
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "HEADER_SETS property is read-only\n");
+ return;
} else if (prop == propINTERFACE_HEADER_SETS) {
- if (value) {
- for (auto const& name : cmExpandedList(value)) {
- if (!this->GetFileSet(name)) {
- this->impl->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("Header set \"", name, "\" has not yet been created."));
- return;
- }
- }
- }
- this->impl->InterfaceHeaderSetsEntries.clear();
- if (!StringIsEmpty(value)) {
- this->impl->InterfaceHeaderSetsEntries.emplace_back(
- value, this->impl->Makefile->GetBacktrace());
- }
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "INTERFACE_HEADER_SETS property is read-only\n");
+ return;
} else {
this->impl->Properties.SetProperty(prop, value);
}
@@ -1680,27 +1657,14 @@ void cmTarget::AppendProperty(const std::string& prop,
fileSet->AddFileEntry(
BT<std::string>(value, this->impl->Makefile->GetBacktrace()));
} else if (prop == "HEADER_SETS") {
- for (auto const& name : cmExpandedList(value)) {
- if (!this->GetFileSet(name)) {
- this->impl->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("Header set \"", name, "\" has not yet been created."));
- return;
- }
- }
- this->impl->HeaderSetsEntries.emplace_back(
- value, this->impl->Makefile->GetBacktrace());
+ this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR,
+ "HEADER_SETS property is read-only\n");
+ return;
} else if (prop == "INTERFACE_HEADER_SETS") {
- for (auto const& name : cmExpandedList(value)) {
- if (!this->GetFileSet(name)) {
- this->impl->Makefile->IssueMessage(
- MessageType::FATAL_ERROR,
- cmStrCat("Header set \"", name, "\" has not yet been created."));
- return;
- }
- }
- this->impl->InterfaceHeaderSetsEntries.emplace_back(
- value, this->impl->Makefile->GetBacktrace());
+ this->impl->Makefile->IssueMessage(
+ MessageType::FATAL_ERROR,
+ "INTERFACE_HEADER_SETS property is read-only\n");
+ return;
} else {
this->impl->Properties.AppendProperty(prop, value, asString);
}
@@ -2125,13 +2089,26 @@ cmValue cmTarget::GetProperty(const std::string& prop) const
return cmValue(output);
}
if (prop == propHEADER_SETS) {
+ std::vector<std::string> set_names;
+ for (auto const& file_set : this->impl->FileSets) {
+ if (cmFileSetVisibilityIsForSelf(file_set.second.GetVisibility())) {
+ set_names.push_back(file_set.second.GetName());
+ }
+ }
static std::string output;
- output = cmJoin(this->impl->HeaderSetsEntries, ";"_s);
+ output = cmJoin(set_names, ";"_s);
return cmValue(output);
}
if (prop == propINTERFACE_HEADER_SETS) {
+ std::vector<std::string> set_names;
+ for (auto const& file_set : this->impl->FileSets) {
+ if (cmFileSetVisibilityIsForInterface(
+ file_set.second.GetVisibility())) {
+ set_names.push_back(file_set.second.GetName());
+ }
+ }
static std::string output;
- output = cmJoin(this->impl->InterfaceHeaderSetsEntries, ";"_s);
+ output = cmJoin(set_names, ";"_s);
return cmValue(output);
}
}
@@ -2429,10 +2406,20 @@ cmFileSet* cmTarget::GetFileSet(const std::string& name)
}
std::pair<cmFileSet*, bool> cmTarget::GetOrCreateFileSet(
- const std::string& name, const std::string& type)
+ const std::string& name, const std::string& type, cmFileSetVisibility vis)
{
- auto result =
- this->impl->FileSets.emplace(std::make_pair(name, cmFileSet(name, type)));
+ auto result = this->impl->FileSets.emplace(
+ std::make_pair(name, cmFileSet(name, type, vis)));
+ if (result.second) {
+ if (cmFileSetVisibilityIsForSelf(vis)) {
+ this->impl->HeaderSetsEntries.emplace_back(
+ name, this->impl->Makefile->GetBacktrace());
+ }
+ if (cmFileSetVisibilityIsForInterface(vis)) {
+ this->impl->InterfaceHeaderSetsEntries.emplace_back(
+ name, this->impl->Makefile->GetBacktrace());
+ }
+ }
return std::make_pair(&result.first->second, result.second);
}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 0cdd2fc..97fdbeb 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -12,6 +12,7 @@
#include <vector>
#include "cmAlgorithms.h"
+#include "cmFileSet.h"
#include "cmPolicies.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
@@ -19,7 +20,6 @@
#include "cmValue.h"
class cmCustomCommand;
-class cmFileSet;
class cmGlobalGenerator;
class cmInstallTargetGenerator;
class cmListFileBacktrace;
@@ -287,7 +287,8 @@ public:
const cmFileSet* GetFileSet(const std::string& name) const;
cmFileSet* GetFileSet(const std::string& name);
std::pair<cmFileSet*, bool> GetOrCreateFileSet(const std::string& name,
- const std::string& type);
+ const std::string& type,
+ cmFileSetVisibility vis);
std::vector<std::string> GetAllInterfaceFileSets() const;
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
index 9173a34..b1367e1 100644
--- a/Source/cmTargetSourcesCommand.cxx
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -2,7 +2,6 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmTargetSourcesCommand.h"
-#include <algorithm>
#include <sstream>
#include <utility>
@@ -239,7 +238,11 @@ bool TargetSourcesImpl::HandleOneFileSet(
(args.Type.empty() && args.FileSet[0] >= 'A' && args.FileSet[0] <= 'Z');
std::string type = isDefault ? args.FileSet : args.Type;
- auto fileSet = this->Target->GetOrCreateFileSet(args.FileSet, type);
+ cmFileSetVisibility visibility =
+ cmFileSetVisibilityFromName(scope, this->Makefile);
+
+ auto fileSet =
+ this->Target->GetOrCreateFileSet(args.FileSet, type, visibility);
if (fileSet.second) {
if (!isDefault) {
if (!cmFileSet::IsValidName(args.FileSet)) {
@@ -261,15 +264,6 @@ bool TargetSourcesImpl::HandleOneFileSet(
if (args.BaseDirs.empty()) {
args.BaseDirs.emplace_back(this->Makefile->GetCurrentSourceDirectory());
}
-
- if (scope == "PRIVATE"_s || scope == "PUBLIC"_s) {
- this->Target->AppendProperty(cmTarget::GetFileSetsPropertyName(type),
- args.FileSet);
- }
- if (scope == "INTERFACE"_s || scope == "PUBLIC"_s) {
- this->Target->AppendProperty(
- cmTarget::GetInterfaceFileSetsPropertyName(type), args.FileSet);
- }
} else {
type = fileSet.first->GetType();
if (!args.Type.empty() && args.Type != type) {
@@ -279,37 +273,11 @@ bool TargetSourcesImpl::HandleOneFileSet(
return false;
}
- std::string existingScope = "PRIVATE";
-
- auto const fileSetsProperty = cmTarget::GetFileSetsPropertyName(type);
- auto const interfaceFileSetsProperty =
- cmTarget::GetInterfaceFileSetsPropertyName(type);
- std::vector<std::string> fileSets;
- std::vector<std::string> interfaceFileSets;
- cmExpandList(this->Target->GetSafeProperty(fileSetsProperty), fileSets);
- cmExpandList(this->Target->GetSafeProperty(interfaceFileSetsProperty),
- interfaceFileSets);
-
- if (std::find(interfaceFileSets.begin(), interfaceFileSets.end(),
- args.FileSet) != interfaceFileSets.end()) {
- existingScope = "INTERFACE";
- }
- if (std::find(fileSets.begin(), fileSets.end(), args.FileSet) !=
- fileSets.end()) {
- if (existingScope == "INTERFACE"_s) {
- existingScope = "PUBLIC";
- }
- } else if (existingScope != "INTERFACE"_s) {
- this->SetError(cmStrCat("File set \"", args.FileSet, "\" is not in ",
- fileSetsProperty, " or ",
- interfaceFileSetsProperty));
- return false;
- }
-
- if (scope != existingScope) {
+ if (visibility != fileSet.first->GetVisibility()) {
this->SetError(
cmStrCat("Scope ", scope, " for file set \"", args.FileSet,
- "\" does not match original scope ", existingScope));
+ "\" does not match original scope ",
+ cmFileSetVisibilityToName(fileSet.first->GetVisibility())));
return false;
}
}
@@ -330,11 +298,11 @@ bool TargetSourcesImpl::HandleOneFileSet(
for (auto const& dir : cmExpandedList(baseDirectories)) {
auto interfaceDirectoriesGenex =
cmStrCat("$<BUILD_INTERFACE:", dir, ">");
- if (scope == "PRIVATE"_s || scope == "PUBLIC"_s) {
+ if (cmFileSetVisibilityIsForSelf(visibility)) {
this->Target->AppendProperty("INCLUDE_DIRECTORIES",
interfaceDirectoriesGenex);
}
- if (scope == "INTERFACE"_s || scope == "PUBLIC"_s) {
+ if (cmFileSetVisibilityIsForInterface(visibility)) {
this->Target->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
interfaceDirectoriesGenex);
}
diff --git a/Tests/RunCMake/target_sources/FileSetImport.cmake b/Tests/RunCMake/target_sources/FileSetImport.cmake
index 9c7358a..7e790c7 100644
--- a/Tests/RunCMake/target_sources/FileSetImport.cmake
+++ b/Tests/RunCMake/target_sources/FileSetImport.cmake
@@ -17,7 +17,7 @@ include("${export_build_dir}/export.cmake")
include("${export_build_dir}/install/lib/cmake/export.cmake")
assert_prop_eq(export::lib1 HEADER_SETS "")
-assert_prop_eq(export::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;e;f;g;dir3")
+assert_prop_eq(export::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;dir3;e;f;g")
assert_prop_eq(export::lib1 HEADER_SET "${CMAKE_CURRENT_SOURCE_DIR}/error.c")
assert_prop_eq(export::lib1 HEADER_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
assert_prop_eq(export::lib1 HEADER_SET_b "${CMAKE_CURRENT_SOURCE_DIR}/h2.h")
@@ -35,7 +35,7 @@ assert_prop_eq(export::lib1 HEADER_DIRS_g "${CMAKE_CURRENT_SOURCE_DIR}/dir1;${CM
assert_prop_eq(export::lib1 INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR};$<1:${CMAKE_CURRENT_SOURCE_DIR}/dir>;${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/$<IF:$<CONFIG:Debug>,debug,release>;${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/dir1;${CMAKE_CURRENT_SOURCE_DIR}/dir2;${CMAKE_CURRENT_SOURCE_DIR}/dir3;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:$<1:${CMAKE_CURRENT_SOURCE_DIR}/dir>>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/$<IF:$<CONFIG:Debug>,debug,release>>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir1>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir2>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir3>")
assert_prop_eq(install::lib1 HEADER_SETS "")
-assert_prop_eq(install::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;e;f;g;dir3")
+assert_prop_eq(install::lib1 INTERFACE_HEADER_SETS "HEADERS;b;c;d;dir3;e;f;g")
assert_prop_eq(install::lib1 HEADER_SET "${export_build_dir}/install/include/error.c")
assert_prop_eq(install::lib1 HEADER_DIRS "${export_build_dir}/install/include")
assert_prop_eq(install::lib1 HEADER_SET_b "${export_build_dir}/install/include/h2.h")
diff --git a/Tests/RunCMake/target_sources/FileSetNoExistInterface-result.txt b/Tests/RunCMake/target_sources/FileSetNoExistInterface-result.txt
deleted file mode 100644
index d00491f..0000000
--- a/Tests/RunCMake/target_sources/FileSetNoExistInterface-result.txt
+++ /dev/null
@@ -1 +0,0 @@
-1
diff --git a/Tests/RunCMake/target_sources/FileSetNoExistInterface-stderr.txt b/Tests/RunCMake/target_sources/FileSetNoExistInterface-stderr.txt
deleted file mode 100644
index 3972c89..0000000
--- a/Tests/RunCMake/target_sources/FileSetNoExistInterface-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-^CMake Error at FileSetNoExistInterface\.cmake:[0-9]+ \(set_property\):
- Header set "a" has not yet been created\.
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/FileSetNoExistPrivate-stderr.txt b/Tests/RunCMake/target_sources/FileSetNoExistPrivate-stderr.txt
deleted file mode 100644
index 336bafe..0000000
--- a/Tests/RunCMake/target_sources/FileSetNoExistPrivate-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-^CMake Error at FileSetNoExistPrivate\.cmake:[0-9]+ \(set_property\):
- Header set "a" has not yet been created\.
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/FileSetNoExistPrivate.cmake b/Tests/RunCMake/target_sources/FileSetNoExistPrivate.cmake
deleted file mode 100644
index f501912..0000000
--- a/Tests/RunCMake/target_sources/FileSetNoExistPrivate.cmake
+++ /dev/null
@@ -1,7 +0,0 @@
-enable_language(C)
-
-add_library(lib1 STATIC empty.c)
-set_property(TARGET lib1 PROPERTY HEADER_SETS "a")
-
-# Error happens at configure-time, so this doesn't help.
-target_sources(lib1 PRIVATE FILE_SET a TYPE HEADERS)
diff --git a/Tests/RunCMake/target_sources/FileSetNoScope-stderr.txt b/Tests/RunCMake/target_sources/FileSetNoScope-stderr.txt
deleted file mode 100644
index 835ffe7..0000000
--- a/Tests/RunCMake/target_sources/FileSetNoScope-stderr.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-^CMake Error at FileSetNoScope\.cmake:[0-9]+ \(target_sources\):
- target_sources File set "a" is not in HEADER_SETS or INTERFACE_HEADER_SETS
-Call Stack \(most recent call first\):
- CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/FileSetNoScope.cmake b/Tests/RunCMake/target_sources/FileSetNoScope.cmake
deleted file mode 100644
index 79ff341..0000000
--- a/Tests/RunCMake/target_sources/FileSetNoScope.cmake
+++ /dev/null
@@ -1,6 +0,0 @@
-enable_language(C)
-
-add_library(lib1 STATIC empty.c)
-target_sources(lib1 PRIVATE FILE_SET a TYPE HEADERS BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} FILES h1.h)
-set_property(TARGET lib1 PROPERTY HEADER_SETS)
-target_sources(lib1 PRIVATE FILE_SET a TYPE HEADERS FILES h2.h)
diff --git a/Tests/RunCMake/target_sources/FileSetProperties.cmake b/Tests/RunCMake/target_sources/FileSetProperties.cmake
index a671ab3..74487fe 100644
--- a/Tests/RunCMake/target_sources/FileSetProperties.cmake
+++ b/Tests/RunCMake/target_sources/FileSetProperties.cmake
@@ -57,14 +57,14 @@ assert_prop_eq(lib1 INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURC
assert_prop_eq(lib1 INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
target_sources(lib1 PUBLIC FILE_SET HEADERS BASE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}" FILES h1.h)
-assert_prop_eq(lib1 INTERFACE_HEADER_SETS "a;c;d;HEADERS")
+assert_prop_eq(lib1 INTERFACE_HEADER_SETS "HEADERS;a;c;d")
assert_prop_eq(lib1 HEADER_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
assert_prop_eq(lib1 HEADER_SET "${CMAKE_CURRENT_SOURCE_DIR}/h1.h")
assert_prop_eq(lib1 INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
assert_prop_eq(lib1 INTERFACE_INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
target_sources(lib1 PUBLIC FILE_SET HEADERS FILES h2.h)
-assert_prop_eq(lib1 INTERFACE_HEADER_SETS "a;c;d;HEADERS")
+assert_prop_eq(lib1 INTERFACE_HEADER_SETS "HEADERS;a;c;d")
assert_prop_eq(lib1 HEADER_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
assert_prop_eq(lib1 HEADER_SET "${CMAKE_CURRENT_SOURCE_DIR}/h1.h;${CMAKE_CURRENT_SOURCE_DIR}/h2.h")
assert_prop_eq(lib1 INCLUDE_DIRECTORIES "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/.>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/dir>;$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>")
diff --git a/Tests/RunCMake/target_sources/FileSetNoScope-result.txt b/Tests/RunCMake/target_sources/FileSetReadOnlyInterface-result.txt
index d00491f..d00491f 100644
--- a/Tests/RunCMake/target_sources/FileSetNoScope-result.txt
+++ b/Tests/RunCMake/target_sources/FileSetReadOnlyInterface-result.txt
diff --git a/Tests/RunCMake/target_sources/FileSetReadOnlyInterface-stderr.txt b/Tests/RunCMake/target_sources/FileSetReadOnlyInterface-stderr.txt
new file mode 100644
index 0000000..2307d13
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetReadOnlyInterface-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at FileSetReadOnlyInterface\.cmake:[0-9]+ \(set_property\):
+ INTERFACE_HEADER_SETS property is read-only
+
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/FileSetNoExistInterface.cmake b/Tests/RunCMake/target_sources/FileSetReadOnlyInterface.cmake
index 266bc61..468ef91 100644
--- a/Tests/RunCMake/target_sources/FileSetNoExistInterface.cmake
+++ b/Tests/RunCMake/target_sources/FileSetReadOnlyInterface.cmake
@@ -2,6 +2,3 @@ enable_language(C)
add_library(lib1 STATIC empty.c)
set_property(TARGET lib1 PROPERTY INTERFACE_HEADER_SETS "a")
-
-# Error happens at configure-time, so this doesn't help.
-target_sources(lib1 INTERFACE FILE_SET a TYPE HEADERS)
diff --git a/Tests/RunCMake/target_sources/FileSetNoExistPrivate-result.txt b/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate-result.txt
index d00491f..d00491f 100644
--- a/Tests/RunCMake/target_sources/FileSetNoExistPrivate-result.txt
+++ b/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate-result.txt
diff --git a/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate-stderr.txt b/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate-stderr.txt
new file mode 100644
index 0000000..5f955da
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate-stderr.txt
@@ -0,0 +1,5 @@
+^CMake Error at FileSetReadOnlyPrivate\.cmake:[0-9]+ \(set_property\):
+ HEADER_SETS property is read-only
+
+Call Stack \(most recent call first\):
+ CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate.cmake b/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate.cmake
new file mode 100644
index 0000000..eda92c1
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetReadOnlyPrivate.cmake
@@ -0,0 +1,4 @@
+enable_language(C)
+
+add_library(lib1 STATIC empty.c)
+set_property(TARGET lib1 PROPERTY HEADER_SETS "a")
diff --git a/Tests/RunCMake/target_sources/RunCMakeTest.cmake b/Tests/RunCMake/target_sources/RunCMakeTest.cmake
index 743879e..8429c96 100644
--- a/Tests/RunCMake/target_sources/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_sources/RunCMakeTest.cmake
@@ -33,9 +33,8 @@ run_cmake(FileSetWrongBaseDirsRelative)
run_cmake(FileSetOverlappingBaseDirs)
run_cmake(FileSetInstallMissingSetsPrivate)
run_cmake(FileSetInstallMissingSetsInterface)
-run_cmake(FileSetNoScope)
-run_cmake(FileSetNoExistPrivate)
-run_cmake(FileSetNoExistInterface)
+run_cmake(FileSetReadOnlyPrivate)
+run_cmake(FileSetReadOnlyInterface)
run_cmake(FileSetNoExistInstall)
run_cmake(FileSetDirectories)
run_cmake(FileSetCustomTarget)