From 08855d03c2bbef0e9b0765f732245fff171d4d9f Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Thu, 25 Jun 2026 18:04:55 +0200 Subject: [PATCH] Add target properties to discover target's file set information Currently, target properties related to file sets are specific to file set type (for example "SOURCE_SETS"). This raises some concerns: 1. For each new file set type, 6 new properties are created which need a lot off documentation update 2. there is no "generic" way to discover file sets information The new target properties (FILE_SET_TYPES, FILE_SETS_, and INTERFACE_FILE_SETS_), in conjunction with the file sets properties, enable a complete generic file sets information discovery. --- Help/manual/cmake-properties.7.rst | 3 ++ Help/prop_tgt/CXX_MODULE_SETS.rst | 17 +++++++--- Help/prop_tgt/FILE_SETS_TYPE.rst | 25 ++++++++++++++ Help/prop_tgt/FILE_SET_TYPES.rst | 16 +++++++++ Help/prop_tgt/HEADER_SETS.rst | 17 +++++++--- Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst | 14 ++++++-- Help/prop_tgt/INTERFACE_FILE_SETS_TYPE.rst | 25 ++++++++++++++ Help/prop_tgt/INTERFACE_HEADER_SETS.rst | 14 ++++++-- Help/prop_tgt/INTERFACE_SOURCE_SETS.rst | 14 ++++++-- Help/prop_tgt/SOURCE_SETS.rst | 17 +++++++--- .../dev/target-FILE_SET-properties.rst | 6 ++++ Source/cmTarget.cxx | 33 +++++++++++++++++++ .../target_sources/FileSetProperties.cmake | 18 ++++++++++ 13 files changed, 198 insertions(+), 21 deletions(-) create mode 100644 Help/prop_tgt/FILE_SETS_TYPE.rst create mode 100644 Help/prop_tgt/FILE_SET_TYPES.rst create mode 100644 Help/prop_tgt/INTERFACE_FILE_SETS_TYPE.rst create mode 100644 Help/release/dev/target-FILE_SET-properties.rst diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 5b4e11c972..97d0073b0e 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -227,6 +227,8 @@ Properties on Targets /prop_tgt/EXPORT_PROPERTIES /prop_tgt/FASTBUILD_CACHING /prop_tgt/FASTBUILD_DISTRIBUTION + /prop_tgt/FILE_SET_TYPES + /prop_tgt/FILE_SETS_TYPE /prop_tgt/FOLDER /prop_tgt/Fortran_BUILDING_INTRINSIC_MODULES /prop_tgt/Fortran_FORMAT @@ -295,6 +297,7 @@ Properties on Targets /prop_tgt/INTERFACE_COMPILE_FEATURES /prop_tgt/INTERFACE_COMPILE_OPTIONS /prop_tgt/INTERFACE_CXX_MODULE_SETS + /prop_tgt/INTERFACE_FILE_SETS_TYPE /prop_tgt/INTERFACE_HEADER_SETS /prop_tgt/INTERFACE_HEADER_SETS_TO_VERIFY /prop_tgt/INTERFACE_INCLUDE_DIRECTORIES diff --git a/Help/prop_tgt/CXX_MODULE_SETS.rst b/Help/prop_tgt/CXX_MODULE_SETS.rst index 2165027186..b71c60c11e 100644 --- a/Help/prop_tgt/CXX_MODULE_SETS.rst +++ b/Help/prop_tgt/CXX_MODULE_SETS.rst @@ -7,8 +7,17 @@ Read-only list of the target's ``PRIVATE`` and ``PUBLIC`` C++ module sets (i.e. all file sets with the type ``CXX_MODULES``). Files listed in these file sets are treated as source files for the purpose of IDE integration. -C++ module sets may be defined using the :command:`target_sources` command -``FILE_SET`` option with type ``CXX_MODULES``. +See Also +^^^^^^^^ -See also :prop_tgt:`CXX_MODULE_SET_`, :prop_tgt:`CXX_MODULE_SET` and -:prop_tgt:`INTERFACE_CXX_MODULE_SETS`. +Related properties: + +* :prop_tgt:`FILE_SETS_` +* :prop_tgt:`INTERFACE_FILE_SETS_` +* :prop_tgt:`INTERFACE_CXX_MODULE_SETS` +* :prop_tgt:`CXX_MODULE_SET_` +* :prop_tgt:`CXX_MODULE_SET` + +Related commands: + +* :command:`target_sources` to define file sets of type ``CXX_MODULES`` diff --git a/Help/prop_tgt/FILE_SETS_TYPE.rst b/Help/prop_tgt/FILE_SETS_TYPE.rst new file mode 100644 index 0000000000..bcc4d02cda --- /dev/null +++ b/Help/prop_tgt/FILE_SETS_TYPE.rst @@ -0,0 +1,25 @@ +FILE_SETS_ +---------------- + +.. versionadded:: 4.5 + +Read-only list of the target's ``PRIVATE`` and ``PUBLIC`` file sets of type +````. + +See Also +^^^^^^^^ + +Related properties: + +* :prop_tgt:`INTERFACE_FILE_SETS_` to list the target's ``INTERFACE`` file sets +* :prop_tgt:`FILE_SET_TYPES` to list the target's file set types +* :prop_tgt:`HEADER_SETS` to list the target's ``PRIVATE`` file sets of type + ``HEADER`` +* :prop_tgt:`SOURCE_SETS` to list the target's ``PRIVATE`` file sets of type + ``SOURCE`` +* :prop_tgt:`CXX_MODULE_SETS` to list the target's ``PRIVATE`` file sets of + type ``CXX_MODULES`` + +Related commands: + +* :command:`target_sources` to define file sets diff --git a/Help/prop_tgt/FILE_SET_TYPES.rst b/Help/prop_tgt/FILE_SET_TYPES.rst new file mode 100644 index 0000000000..fd74fa5922 --- /dev/null +++ b/Help/prop_tgt/FILE_SET_TYPES.rst @@ -0,0 +1,16 @@ +FILE_SET_TYPES +-------------- + +.. versionadded:: 4.5 + +Read-only list of the target's file set types. + +See Also +^^^^^^^^ + +Related properties: + +* :prop_tgt:`FILE_SETS_` to list ``PRIVATE`` and ``PUBLIC`` file sets of + type ````. +* :prop_tgt:`INTERFACE_FILE_SETS_` to list ``INTERFACE`` and ``PUBLIC`` + file sets of type ````. diff --git a/Help/prop_tgt/HEADER_SETS.rst b/Help/prop_tgt/HEADER_SETS.rst index ceb1df5062..e712cb4dce 100644 --- a/Help/prop_tgt/HEADER_SETS.rst +++ b/Help/prop_tgt/HEADER_SETS.rst @@ -8,8 +8,17 @@ 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``. -Header sets may be defined using the :command:`target_sources` command -``FILE_SET`` option with type ``HEADERS``. +See Also +^^^^^^^^ -See also :prop_tgt:`HEADER_SET_`, :prop_tgt:`HEADER_SET` and -:prop_tgt:`INTERFACE_HEADER_SETS`. +Related properties: + +* :prop_tgt:`FILE_SETS_` +* :prop_tgt:`INTERFACE_FILE_SETS_` +* :prop_tgt:`INTERFACE_HEADER_SETS` +* :prop_tgt:`HEADER_SET_` +* :prop_tgt:`HEADER_SET` + +Related commands: + +* :command:`target_sources` to define file sets of type ``HEADERS`` diff --git a/Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst b/Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst index fd6e34bb04..7bd2b12129 100644 --- a/Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst +++ b/Help/prop_tgt/INTERFACE_CXX_MODULE_SETS.rst @@ -8,7 +8,15 @@ with the type ``CXX_MODULES``). Files listed in these C++ module sets can be installed with :command:`install(TARGETS)` and exported with :command:`install(EXPORT)` and :command:`export`. -C++ module sets may be defined using the :command:`target_sources` command -``FILE_SET`` option with type ``CXX_MODULES``. +See Also +^^^^^^^^ -See also :prop_tgt:`CXX_MODULE_SETS`. +Related properties: + +* :prop_tgt:`INTERFACE_FILE_SETS_` +* :prop_tgt:`FILE_SETS_` +* :prop_tgt:`CXX_MODULE_SETS` + +Related commands: + +* :command:`target_sources` to define file sets of type ``CXX_MODULES`` diff --git a/Help/prop_tgt/INTERFACE_FILE_SETS_TYPE.rst b/Help/prop_tgt/INTERFACE_FILE_SETS_TYPE.rst new file mode 100644 index 0000000000..03b1ee1d07 --- /dev/null +++ b/Help/prop_tgt/INTERFACE_FILE_SETS_TYPE.rst @@ -0,0 +1,25 @@ +INTERFACE_FILE_SETS_ +-------------------------- + +.. versionadded:: 4.5 + +Read-only list of the target's ``INTERFACE`` and ``PUBLIC`` file sets of type +````. + +See Also +^^^^^^^^ + +Related properties: + +* :prop_tgt:`FILE_SETS_` to list the target's ``PRIVATE`` file sets +* :prop_tgt:`FILE_SET_TYPES` to list the target's file set types +* :prop_tgt:`INTERFACE_HEADER_SETS` to list the target's ``INTERFACE`` file + sets of type ``HEADER`` +* :prop_tgt:`INTERFACE_SOURCE_SETS` to list the target's ``INTERFACE`` file + sets of type ``SOURCE`` +* :prop_tgt:`INTERFACE_CXX_MODULE_SETS` to list the target's ``INTERFACE`` file + sets of type ``CXX_MODULES`` + +Related commands: + +* :command:`target_sources` to define file sets diff --git a/Help/prop_tgt/INTERFACE_HEADER_SETS.rst b/Help/prop_tgt/INTERFACE_HEADER_SETS.rst index 2d3bdacfcf..bca51c0976 100644 --- a/Help/prop_tgt/INTERFACE_HEADER_SETS.rst +++ b/Help/prop_tgt/INTERFACE_HEADER_SETS.rst @@ -8,7 +8,15 @@ 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`. -Header sets may be defined using the :command:`target_sources` command -``FILE_SET`` option with type ``HEADERS``. +See Also +^^^^^^^^ -See also :prop_tgt:`HEADER_SETS`. +Related properties: + +* :prop_tgt:`INTERFACE_FILE_SETS_` +* :prop_tgt:`FILE_SETS_` +* :prop_tgt:`HEADER_SETS` + +Related commands: + +* :command:`target_sources` to define file sets of type ``HEADERS`` diff --git a/Help/prop_tgt/INTERFACE_SOURCE_SETS.rst b/Help/prop_tgt/INTERFACE_SOURCE_SETS.rst index 4aba9288ee..113797def9 100644 --- a/Help/prop_tgt/INTERFACE_SOURCE_SETS.rst +++ b/Help/prop_tgt/INTERFACE_SOURCE_SETS.rst @@ -8,7 +8,15 @@ all file sets with the type ``SOURCES``). Files listed in these source sets can be installed with :command:`install(TARGETS)` and exported with :command:`install(EXPORT)` and :command:`export`. -Source sets may be defined using the :command:`target_sources` command -``FILE_SET`` option with type ``SOURCES``. +See Also +^^^^^^^^ -See also :prop_tgt:`SOURCE_SETS`. +Related properties: + +* :prop_tgt:`INTERFACE_FILE_SETS_` +* :prop_tgt:`FILE_SETS_` +* :prop_tgt:`SOURCE_SETS` + +Related commands: + +* :command:`target_sources` to define file sets of type ``SOURCES`` diff --git a/Help/prop_tgt/SOURCE_SETS.rst b/Help/prop_tgt/SOURCE_SETS.rst index b6fad22c38..fdcd43e1f1 100644 --- a/Help/prop_tgt/SOURCE_SETS.rst +++ b/Help/prop_tgt/SOURCE_SETS.rst @@ -7,8 +7,17 @@ Read-only list of the target's ``PRIVATE`` and ``PUBLIC`` source sets (i.e. all file sets with the type ``SOURCES``). Files listed in these file sets are treated as source files. -Source sets may be defined using the :command:`target_sources` command -``FILE_SET`` option with type ``SOURCES``. +See Also +^^^^^^^^ -See also :prop_tgt:`SOURCE_SET_`, :prop_tgt:`SOURCE_SET` and -:prop_tgt:`INTERFACE_SOURCE_SETS`. +Related properties: + +* :prop_tgt:`FILE_SETS_` +* :prop_tgt:`INTERFACE_FILE_SETS_` +* :prop_tgt:`INTERFACE_SOURCE_SETS` +* :prop_tgt:`SOURCE_SET_` +* :prop_tgt:`SOURCE_SET` + +Related commands: + +* :command:`target_sources` to define file sets of type ``SOURCES`` diff --git a/Help/release/dev/target-FILE_SET-properties.rst b/Help/release/dev/target-FILE_SET-properties.rst new file mode 100644 index 0000000000..a1fe641506 --- /dev/null +++ b/Help/release/dev/target-FILE_SET-properties.rst @@ -0,0 +1,6 @@ +target-FILE_SET-properties +-------------------------- + +* The :prop_tgt:`FILE_SET_TYPES`, :prop_tgt:`FILE_SETS_`, and + :prop_tgt:`INTERFACE_FILE_SETS_` target properties were added to get + information about file sets attached to the target. diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index c8d4dfe5d1..61d97a5b14 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -41,6 +41,7 @@ #include "cmState.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTargetPropertyComputer.h" #include "cmValue.h" @@ -2114,6 +2115,7 @@ bool IsSettableProperty(cmMakefile* context, cmTarget* target, using ROC = ReadOnlyCondition; static std::unordered_map const readOnlyProps{ { "EXPORT_NAME", { ROC::Imported } }, + { "FILE_SET_TYPES", { ROC::All } }, { "HEADER_SETS", { ROC::All } }, { "IMPORTED_GLOBAL", { ROC::NonImported } }, { "INTERFACE_HEADER_SETS", { ROC::All } }, @@ -2181,6 +2183,11 @@ void cmTarget::SetProperty(std::string const& prop, cmValue value) } } + if (cmHasPrefix(prop, "FILE_SETS_"_s) || + cmHasPrefix(prop, "INTERFACE_FILE_SETS_"_s)) { + // these properties are always read-only + return; + } for (auto& fileSetType : this->impl->FileSetTypes) { if (fileSetType.second.WriteProperties(this, this->impl.get(), prop, value, FileSetType::Action::Set)) { @@ -2773,6 +2780,32 @@ cmValue cmTarget::GetProperty(std::string const& prop) const } // Check fileset properties. + if (prop == "FILE_SET_TYPES"_s) { + static std::string fsTypes; + cmList types; + for (auto const& fileSetType : this->impl->FileSetTypes) { + if (!fileSetType.second.SelfEntries.Entries.empty() || + !fileSetType.second.InterfaceEntries.Entries.empty()) { + types.push_back(fileSetType.first); + } + } + std::sort(types.begin(), types.end()); + fsTypes = types.to_string(); + return cmValue{ fsTypes }; + } + if (cmHasPrefix(prop, "FILE_SETS_"_s)) { + static std::string fileSets; + std::string type = prop.substr(10); + fileSets = cmList::to_string(this->GetFileSetsEntries(type)); + return cmValue{ fileSets }; + } + if (cmHasPrefix(prop, "INTERFACE_FILE_SETS_"_s)) { + static std::string fileSets; + std::string type = prop.substr(20); + fileSets = cmList::to_string(this->GetInterfaceFileSetsEntries(type)); + return cmValue{ fileSets }; + } + { for (auto const& fileSetType : this->impl->FileSetTypes) { auto value = diff --git a/Tests/RunCMake/target_sources/FileSetProperties.cmake b/Tests/RunCMake/target_sources/FileSetProperties.cmake index 8753eb6667..654e91d341 100644 --- a/Tests/RunCMake/target_sources/FileSetProperties.cmake +++ b/Tests/RunCMake/target_sources/FileSetProperties.cmake @@ -21,10 +21,14 @@ assert_prop_eq(lib1 HEADER_SETS "") assert_prop_eq(lib1 INTERFACE_HEADER_SETS "") assert_prop_undef(lib1 INCLUDE_DIRECTORIES) assert_prop_undef(lib1 INTERFACE_INCLUDE_DIRECTORIES) +assert_prop_eq(lib1 FILE_SET_TYPES "") target_sources(lib1 PUBLIC FILE_SET a TYPE HEADERS BASE_DIRS "." FILES h1.h h2.h) assert_prop_eq(lib1 HEADER_SETS "a") assert_prop_eq(lib1 INTERFACE_HEADER_SETS "a") +assert_prop_eq(lib1 FILE_SET_TYPES "HEADERS") +assert_prop_eq(lib1 FILE_SETS_HEADERS "a") +assert_prop_eq(lib1 INTERFACE_FILE_SETS_HEADERS "a") assert_prop_eq(lib1 HEADER_DIRS_a "${CMAKE_CURRENT_SOURCE_DIR}/.") assert_prop_eq(lib1 HEADER_SET_a "${CMAKE_CURRENT_SOURCE_DIR}/h1.h;${CMAKE_CURRENT_SOURCE_DIR}/h2.h") assert_prop_eq(lib1 INCLUDE_DIRECTORIES "$") @@ -41,6 +45,9 @@ assert_prop_eq(lib1 INTERFACE_INCLUDE_DIRECTORIES "$;$") @@ -49,6 +56,8 @@ assert_prop_eq(lib1 INTERFACE_INCLUDE_DIRECTORIES "$;$;$") assert_prop_eq(lib1 INTERFACE_INCLUDE_DIRECTORIES "$;$;$;$") + +target_sources(lib1 PUBLIC FILE_SET src1 TYPE SOURCES FILES lib1.c) +assert_prop_eq(lib1 FILE_SET_TYPES "HEADERS;SOURCES") +assert_prop_eq(lib1 FILE_SETS_HEADERS "a;b;HEADERS") +assert_prop_eq(lib1 INTERFACE_FILE_SETS_HEADERS "a;c;d;HEADERS") +assert_prop_eq(lib1 FILE_SETS_SOURCES "src1") +assert_prop_eq(lib1 INTERFACE_FILE_SETS_SOURCES "src1")