FILE_SET: manage unity build exclusions based on file set type

This complements commit 5f7a7aa263 (FILE_SET: add SKIP_UNITY_BUILD_INCLUSION property support, 2026-05-11)
This commit is contained in:
Marc Chevrier
2026-05-20 18:42:37 +02:00
parent 4f5d22f085
commit 7d892786d8
7 changed files with 37 additions and 13 deletions

View File

@@ -13,7 +13,8 @@ This property helps with "ODR (One definition rule)" problems where combining
a particular source file with others might lead to build errors or other
unintended side effects.
Note that sources which are scanned for C++ modules (see
Note that :ref:`file sets <File Sets>` of type ``HEADERS`` and ``CXX_MODULES``
as well as the sources which are scanned for C++ modules (see
:manual:`cmake-cxxmodules(7)`) are not eligible for unity build inclusion and
will automatically be excluded.

View File

@@ -82,7 +82,8 @@ bool IsExcludedFromUnity(cmGeneratorTarget const* target,
cmSourceFile const& srcFile)
{
if (fileSet &&
(fileSet->GetType() == cm::FileSetMetadata::HEADERS ||
(!cm::FileSetMetadata::GetAttributes(fileSet->GetType())
.contains(cm::FileSetMetadata::FileSetAttributes::UnityBuild) ||
fileSet->GetProperty("SKIP_UNITY_BUILD_INCLUSION").IsOn() ||
fileSet->GetProperty(fileSet->BelongsTo(target)
? "COMPILE_OPTIONS"

View File

@@ -92,7 +92,8 @@ std::map<cm::string_view, FileSetDescriptor> const FileSetDescriptors{
cm::FileSetMetadata::FileSetLookup::Dependencies,
{ DependencyMode ::IndependentFiles, DependencyMode ::Includables },
DependencyMode ::Includables,
{ cm::FileSetMetadata::FileSetAttributes::FrameworkCompatible } } },
{ cm::FileSetMetadata::FileSetAttributes::FrameworkCompatible,
cm::FileSetMetadata::FileSetAttributes::UnityBuild } } },
{ cm::FileSetMetadata::CXX_MODULES,
{ cm::FileSetMetadata::CXX_MODULES,
cm::FileSetMetadata::FileSetLookup::Target,

View File

@@ -56,11 +56,12 @@ using DependencySet = std::set<DependencyMode>;
enum class FileSetAttributes : std::uint16_t
{
FrameworkCompatible, // Can be part of an Apple framework
FilesInMultipleFileSets // Files of this file set type can be part of other
// file sets
FrameworkCompatible, // Can be part of an Apple framework
FilesInMultipleFileSets, // Files of this file set type can be part of other
// file sets
UnityBuild // Can be part of a unity build
};
using AttributeSet = cm::enum_set<FileSetAttributes, 2>;
using AttributeSet = cm::enum_set<FileSetAttributes, 3>;
struct FileSetDescriptor
{

View File

@@ -3291,6 +3291,13 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
std::vector<cmSourceFile*> sources;
target->GetSourceFiles(sources, configs[ci]);
for (cmSourceFile* sf : sources) {
cmGeneratorFileSet const* fileSet =
target->GetFileSetForSource(configs[ci], sf);
if (fileSet &&
!cm::FileSetMetadata::GetAttributes(fileSet->GetType())
.contains(cm::FileSetMetadata::FileSetAttributes::UnityBuild)) {
continue;
}
// Files which need C++ scanning cannot participate in unity builds as
// there is a single place in TUs that may perform module-dependency bits
// and a unity source cannot `#include` them in-order and represent a
@@ -3341,8 +3348,7 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
cmGeneratorFileSet const* fileSet =
target->GetFileSetForSource(configs[idx], sf);
if (fileSet &&
(fileSet->GetType() == cm::FileSetMetadata::HEADERS ||
fileSet->GetProperty("SKIP_UNITY_BUILD_INCLUSION").IsOn() ||
(fileSet->GetProperty("SKIP_UNITY_BUILD_INCLUSION").IsOn() ||
fileSet->GetProperty(fileSet->BelongsTo(target)
? "COMPILE_OPTIONS"
: "INTERFACE_COMPILE_OPTIONS") ||

View File

@@ -1638,7 +1638,9 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
(gt->GetPropertyAsBool("UNITY_BUILD") &&
sf.GetProperty("UNITY_SOURCE_FILE") &&
!((fileSet &&
fileSet->GetProperty("SKIP_UNITY_BUILD_INCLUSION").IsOn()) ||
(!cm::FileSetMetadata::GetAttributes(fileSet->GetType())
.contains(cm::FileSetMetadata::FileSetAttributes::UnityBuild) ||
fileSet->GetProperty("SKIP_UNITY_BUILD_INCLUSION").IsOn())) ||
sf.GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION")));
if (fc.ExcludedFromBuild) {
needfc = true;

View File

@@ -2694,7 +2694,11 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
if (useNativeUnityBuild) {
e2.Attribute(
"IncludeInUnityFile",
((fs && fs->GetProperty("SKIP_UNITY_BUILD_INCLUSION").IsOn()) ||
((fs &&
(!cm::FileSetMetadata::GetAttributes(fs->GetType())
.contains(
cm::FileSetMetadata::FileSetAttributes::UnityBuild) ||
fs->GetProperty("SKIP_UNITY_BUILD_INCLUSION").IsOn())) ||
si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION"))
? "false"
: "true");
@@ -2706,7 +2710,11 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
} else {
// Visual Studio versions prior to 2017 15.8 do not know about unity
// builds, thus we exclude the files already part of unity sources.
if (!((fs && fs->GetProperty("SKIP_UNITY_BUILD_INCLUSION").IsOn()) ||
if (!((fs &&
(!cm::FileSetMetadata::GetAttributes(fs->GetType())
.contains(
cm::FileSetMetadata::FileSetAttributes::UnityBuild) ||
fs->GetProperty("SKIP_UNITY_BUILD_INCLUSION").IsOn())) ||
si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION"))) {
exclude_configs = all_configs;
}
@@ -2714,7 +2722,11 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0)
}
if (haveUnityBuild && strcmp(tool, "CudaCompile") == 0 &&
si.Source->GetProperty("UNITY_SOURCE_FILE")) {
if (!((fs && fs->GetProperty("SKIP_UNITY_BUILD_INCLUSION").IsOn()) ||
if (!((fs &&
(!cm::FileSetMetadata::GetAttributes(fs->GetType())
.contains(
cm::FileSetMetadata::FileSetAttributes::UnityBuild) ||
fs->GetProperty("SKIP_UNITY_BUILD_INCLUSION").IsOn())) ||
si.Source->GetPropertyAsBool("SKIP_UNITY_BUILD_INCLUSION"))) {
exclude_configs = all_configs;
}