# UNDF: UNDF-2026-000000035 diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index abc1234..def5678 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1428,11 +1428,19 @@ cmSourceFile* cmTarget::AddSource(std::string const& src, bool before) { cmSourceFileLocation sfl(this->impl->Makefile, src, cmSourceFileLocationKind::Known); + // Fast path: check a parallel unordered_set of source-path strings. + // The full TargetPropertyEntryFinder scan is O(n) and is called from loops + // (e.g. Unity build file iteration), producing O(n^2) overall. + // An exact-string set lookup is O(1) amortized and covers the common case + // where src is a canonical resolved path. + if (!this->impl->SourcePathsSet.insert(src).second) { + // Already present — skip the expensive find_if and WriteDirect. + if (cmGeneratorExpression::Find(src) != std::string::npos) + return nullptr; + return this->impl->Makefile->GetOrCreateSource( + src, false, cmSourceFileLocationKind::Known); + } auto const& sources = this->impl->Sources.Entries; if (std::find_if(sources.begin(), sources.end(), TargetPropertyEntryFinder(sfl)) == sources.end()) { this->impl->Sources.WriteDirect( this->impl.get(), {}, cmValue(src), before ? UsageRequirementProperty::Action::Prepend : UsageRequirementProperty::Action::Append); }