From ad41c9cd1161bb3d19bc1db8a20a7b7e87665f3a Mon Sep 17 00:00:00 2001
From: Kyle Edwards <kyle.edwards@kitware.com>
Date: Mon, 28 Feb 2022 17:11:53 -0500
Subject: target_sources(): Prohibit FILE_SET on custom targets

Fixes: #23262
---
 Help/command/target_sources.rst                              | 3 ++-
 Source/cmTargetSourcesCommand.cxx                            | 6 ++++++
 Tests/RunCMake/target_sources/FileSetCustomTarget-result.txt | 1 +
 Tests/RunCMake/target_sources/FileSetCustomTarget-stderr.txt | 4 ++++
 Tests/RunCMake/target_sources/FileSetCustomTarget.cmake      | 2 ++
 Tests/RunCMake/target_sources/RunCMakeTest.cmake             | 1 +
 6 files changed, 16 insertions(+), 1 deletion(-)
 create mode 100644 Tests/RunCMake/target_sources/FileSetCustomTarget-result.txt
 create mode 100644 Tests/RunCMake/target_sources/FileSetCustomTarget-stderr.txt
 create mode 100644 Tests/RunCMake/target_sources/FileSetCustomTarget.cmake

diff --git a/Help/command/target_sources.rst b/Help/command/target_sources.rst
index f4833e7..e482117 100644
--- a/Help/command/target_sources.rst
+++ b/Help/command/target_sources.rst
@@ -75,7 +75,8 @@ Adds a file set to a target, or adds files to an existing file set. Targets
 have zero or more named file sets. Each file set has a name, a type, a scope of
 ``INTERFACE``, ``PUBLIC``, or ``PRIVATE``, one or more base directories, and
 files within those directories. The only acceptable type is ``HEADERS``. The
-optional default file sets are named after their type.
+optional default file sets are named after their type. The target may not be a
+custom target.
 
 Files in a ``PRIVATE`` or ``PUBLIC`` file set are marked as source files for
 the purposes of IDE integration. Additionally, files in ``HEADERS`` file sets
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
index 818e271..b425acb 100644
--- a/Source/cmTargetSourcesCommand.cxx
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -16,6 +16,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmPolicies.h"
+#include "cmStateTypes.h"
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
@@ -202,6 +203,11 @@ bool TargetSourcesImpl::HandleFileSetMode(
     return false;
   }
 
+  if (this->Target->GetType() == cmStateEnums::UTILITY) {
+    this->SetError("FILE_SETs may not be added to custom targets");
+    return false;
+  }
+
   bool const isDefault = args.Type == args.FileSet ||
     (args.Type.empty() && args.FileSet[0] >= 'A' && args.FileSet[0] <= 'Z');
   std::string type = isDefault ? args.FileSet : args.Type;
diff --git a/Tests/RunCMake/target_sources/FileSetCustomTarget-result.txt b/Tests/RunCMake/target_sources/FileSetCustomTarget-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetCustomTarget-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/target_sources/FileSetCustomTarget-stderr.txt b/Tests/RunCMake/target_sources/FileSetCustomTarget-stderr.txt
new file mode 100644
index 0000000..8ab3de7
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetCustomTarget-stderr.txt
@@ -0,0 +1,4 @@
+^CMake Error at FileSetCustomTarget\.cmake:[0-9]+ \(target_sources\):
+  target_sources FILE_SETs may not be added to custom targets
+Call Stack \(most recent call first\):
+  CMakeLists\.txt:[0-9]+ \(include\)$
diff --git a/Tests/RunCMake/target_sources/FileSetCustomTarget.cmake b/Tests/RunCMake/target_sources/FileSetCustomTarget.cmake
new file mode 100644
index 0000000..ce26400
--- /dev/null
+++ b/Tests/RunCMake/target_sources/FileSetCustomTarget.cmake
@@ -0,0 +1,2 @@
+add_custom_target(tgt)
+target_sources(tgt PRIVATE FILE_SET HEADERS FILES h1.h)
diff --git a/Tests/RunCMake/target_sources/RunCMakeTest.cmake b/Tests/RunCMake/target_sources/RunCMakeTest.cmake
index 171de60..da9944d 100644
--- a/Tests/RunCMake/target_sources/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_sources/RunCMakeTest.cmake
@@ -38,6 +38,7 @@ run_cmake(FileSetNoExistPrivate)
 run_cmake(FileSetNoExistInterface)
 run_cmake(FileSetNoExistInstall)
 run_cmake(FileSetDirectories)
+run_cmake(FileSetCustomTarget)
 
 set(RunCMake_TEST_OPTIONS -DCMAKE_POLICY_DEFAULT_CMP0115=NEW)
 run_cmake(FileSetFileNoExist)
-- 
cgit v0.12