diff options
Diffstat (limited to 'Source/cmGeneratorTarget.cxx')
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 221 |
1 files changed, 197 insertions, 24 deletions
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 43bcdd4..db4be63 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -13,6 +13,7 @@ #include <iterator> #include <queue> #include <sstream> +#include <type_traits> #include <unordered_set> #include <utility> @@ -26,7 +27,9 @@ #include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" +#include "cmCryptoHash.h" #include "cmCustomCommandGenerator.h" +#include "cmCxxModuleUsageEffects.h" #include "cmEvaluatedTargetProperty.h" #include "cmExperimental.h" #include "cmFileSet.h" @@ -51,6 +54,7 @@ #include "cmStandardLevelResolver.h" #include "cmState.h" #include "cmStringAlgorithms.h" +#include "cmSyntheticTargetCache.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetLinkLibraryType.h" @@ -190,7 +194,7 @@ public: } static std::string filesStr; - filesStr = cmJoin(files, ";"); + filesStr = cmList::to_string(files); return filesStr; } @@ -322,8 +326,7 @@ cmValue cmGeneratorTarget::GetSourcesProperty() const values.push_back(se->GetInput()); } static std::string value; - value.clear(); - value = cmJoin(values, ";"); + value = cmList::to_string(values); return cmValue(value); } @@ -1071,6 +1074,12 @@ void cmGeneratorTarget::GetHeaderSources( IMPLEMENT_VISIT(SourceKindHeader); } +void cmGeneratorTarget::GetCxxModuleSources( + std::vector<cmSourceFile const*>& data, const std::string& config) const +{ + IMPLEMENT_VISIT(SourceKindCxxModuleSource); +} + void cmGeneratorTarget::GetExtraSources(std::vector<cmSourceFile const*>& data, const std::string& config) const { @@ -1224,6 +1233,11 @@ bool cmGeneratorTarget::IsNormal() const return this->Target->IsNormal(); } +bool cmGeneratorTarget::IsRuntimeBinary() const +{ + return this->Target->IsRuntimeBinary(); +} + bool cmGeneratorTarget::IsSynthetic() const { return this->Target->IsSynthetic(); @@ -1493,9 +1507,9 @@ std::string AddLangSpecificInterfaceIncludeDirectories( } std::string directories; - if (const auto* interface = target->GetLinkInterfaceLibraries( + if (const auto* link_interface = target->GetLinkInterfaceLibraries( config, root, LinkInterfaceFor::Usage)) { - for (const cmLinkItem& library : interface->Libraries) { + for (const cmLinkItem& library : link_interface->Libraries) { if (const cmGeneratorTarget* dependency = library.Target) { if (cm::contains(dependency->GetAllConfigCompileLanguages(), lang)) { auto* lg = dependency->GetLocalGenerator(); @@ -1948,8 +1962,12 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files, // Compute the kind (classification) of this source file. SourceKind kind; std::string ext = cmSystemTools::LowerCase(sf->GetExtension()); + cmFileSet const* fs = this->GetFileSetForSource(config, sf); if (sf->GetCustomCommand()) { kind = SourceKindCustomCommand; + } else if (!this->Target->IsNormal() && !this->Target->IsImported() && + fs && (fs->GetType() == "CXX_MODULES"_s)) { + kind = SourceKindCxxModuleSource; } else if (this->Target->GetType() == cmStateEnums::UTILITY || this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165 @@ -3828,7 +3846,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( if (lib.Target == nullptr) { libDir = cmSystemTools::CollapseFullPath( lib.AsStr(), this->Makefile->GetHomeOutputDirectory()); - } else if (lib.Target->Target->IsFrameworkOnApple()) { + } else if (lib.Target->Target->IsFrameworkOnApple() || + this->IsImportedFrameworkFolderOnApple(config)) { libDir = lib.Target->GetLocation(config); } else { continue; @@ -5857,7 +5876,7 @@ void cmGeneratorTarget::CheckPropertyCompatibility( static const std::string strNumMax = "COMPATIBLE_INTERFACE_NUMBER_MAX"; for (auto const& dep : deps) { - if (!dep.Target) { + if (!dep.Target || dep.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) { continue; } @@ -8214,6 +8233,96 @@ void ComputeLinkImplTransitive(cmGeneratorTarget const* self, } } +bool cmGeneratorTarget::DiscoverSyntheticTargets(cmSyntheticTargetCache& cache, + std::string const& config) +{ + cmOptionalLinkImplementation impl; + this->ComputeLinkImplementationLibraries(config, impl, this, + LinkInterfaceFor::Link); + + cmCxxModuleUsageEffects usage(this); + + auto& SyntheticDeps = this->Configs[config].SyntheticDeps; + + for (auto const& entry : impl.Libraries) { + auto const* gt = entry.Target; + if (!gt || !gt->IsImported()) { + continue; + } + + if (gt->HaveCxx20ModuleSources()) { + auto hasher = cmCryptoHash::New("SHA3_512"); + constexpr size_t HASH_TRUNCATION = 12; + auto dirhash = hasher->HashString( + gt->GetLocalGenerator()->GetCurrentBinaryDirectory()); + std::string safeName = gt->GetName(); + cmSystemTools::ReplaceString(safeName, ":", "_"); + auto targetIdent = + hasher->HashString(cmStrCat("@d_", dirhash, "@u_", usage.GetHash())); + std::string targetName = + cmStrCat(safeName, "@synth_", targetIdent.substr(0, HASH_TRUNCATION)); + + // Check the cache to see if this instance of the imported target has + // already been created. + auto cached = cache.CxxModuleTargets.find(targetName); + cmGeneratorTarget const* synthDep = nullptr; + if (cached == cache.CxxModuleTargets.end()) { + auto const* model = gt->Target; + auto* mf = gt->Makefile; + auto* lg = gt->GetLocalGenerator(); + auto* tgt = mf->AddSynthesizedTarget(cmStateEnums::INTERFACE_LIBRARY, + targetName); + + // Copy relevant information from the existing IMPORTED target. + + // Copy policies to the target. + tgt->CopyPolicyStatuses(model); + + // Copy file sets. + { + auto fsNames = model->GetAllFileSetNames(); + for (auto const& fsName : fsNames) { + auto const* fs = model->GetFileSet(fsName); + if (!fs) { + mf->IssueMessage(MessageType::INTERNAL_ERROR, + cmStrCat("Failed to find file set named '", + fsName, "' on target '", + tgt->GetName(), '\'')); + continue; + } + auto* newFs = tgt + ->GetOrCreateFileSet(fs->GetName(), fs->GetType(), + fs->GetVisibility()) + .first; + newFs->CopyEntries(fs); + } + } + + // Copy imported C++ module properties. + tgt->CopyImportedCxxModulesEntries(model); + + // Copy other properties which may affect the C++ module BMI + // generation. + tgt->CopyImportedCxxModulesProperties(model); + + // Apply usage requirements to the target. + usage.ApplyToTarget(tgt); + + // Create the generator target and attach it to the local generator. + auto gtp = cm::make_unique<cmGeneratorTarget>(tgt, lg); + synthDep = gtp.get(); + lg->AddGeneratorTarget(std::move(gtp)); + } else { + synthDep = cached->second; + } + + SyntheticDeps[gt].push_back(synthDep); + } + } + + return true; +} + void cmGeneratorTarget::ComputeLinkImplementationLibraries( const std::string& config, cmOptionalLinkImplementation& impl, cmGeneratorTarget const* head, LinkInterfaceFor implFor) const @@ -8221,6 +8330,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( cmLocalGenerator const* lg = this->LocalGenerator; cmMakefile const* mf = lg->GetMakefile(); cmBTStringRange entryRange = this->Target->GetLinkImplementationEntries(); + auto const& synthTargetsForConfig = this->Configs[config].SyntheticDeps; // Collect libraries directly linked in this configuration. for (auto const& entry : entryRange) { // Keep this logic in sync with ExpandLinkItems. @@ -8310,7 +8420,15 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( // The entry is meant for this configuration. cmLinkItem item = this->ResolveLinkItem(BT<std::string>(name, entry.Backtrace), lg); - if (!item.Target) { + if (item.Target) { + auto depsForTarget = synthTargetsForConfig.find(item.Target); + if (depsForTarget != synthTargetsForConfig.end()) { + for (auto const* depForTarget : depsForTarget->second) { + cmLinkItem synthItem(depForTarget, item.Cross, item.Backtrace); + impl.Libraries.emplace_back(std::move(synthItem), false); + } + } + } else { // Report explicitly linked object files separately. std::string const& maybeObj = item.AsStr(); if (cmSystemTools::FileIsFullPath(maybeObj)) { @@ -8572,6 +8690,16 @@ bool cmGeneratorTarget::IsFrameworkOnApple() const return this->Target->IsFrameworkOnApple(); } +bool cmGeneratorTarget::IsImportedFrameworkFolderOnApple( + const std::string& config) const +{ + return this->IsApple() && this->IsImported() && + (this->GetType() == cmStateEnums::STATIC_LIBRARY || + this->GetType() == cmStateEnums::SHARED_LIBRARY || + this->GetType() == cmStateEnums::UNKNOWN_LIBRARY) && + cmSystemTools::IsPathToFramework(this->GetLocation(config)); +} + bool cmGeneratorTarget::IsAppBundleOnApple() const { return this->Target->IsAppBundleOnApple(); @@ -8864,6 +8992,47 @@ std::string cmGeneratorTarget::GenerateHeaderSetVerificationFile( return filename; } +std::string cmGeneratorTarget::GetImportedXcFrameworkPath( + const std::string& config) const +{ + if (!(this->IsApple() && this->IsImported() && + (this->GetType() == cmStateEnums::SHARED_LIBRARY || + this->GetType() == cmStateEnums::STATIC_LIBRARY || + this->GetType() == cmStateEnums::UNKNOWN_LIBRARY))) { + return {}; + } + + std::string desiredConfig = config; + if (config.empty()) { + desiredConfig = "NOCONFIG"; + } + + std::string result; + + cmValue loc = nullptr; + cmValue imp = nullptr; + std::string suffix; + + if (this->Target->GetMappedConfig(desiredConfig, loc, imp, suffix)) { + if (loc) { + result = *loc; + } else { + std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix); + if (cmValue configLocation = this->GetProperty(impProp)) { + result = *configLocation; + } else if (cmValue location = this->GetProperty("IMPORTED_LOCATION")) { + result = *location; + } + } + + if (cmSystemTools::IsPathToXcFramework(result)) { + return result; + } + } + + return {}; +} + bool cmGeneratorTarget::HaveFortranSources(std::string const& config) const { auto sources = cmGeneratorTarget::GetSourceFiles(config); @@ -8873,24 +9042,28 @@ bool cmGeneratorTarget::HaveFortranSources(std::string const& config) const }); } -bool cmGeneratorTarget::HaveCxx20ModuleSources() const +bool cmGeneratorTarget::HaveCxx20ModuleSources(std::string* errorMessage) const { auto const& fs_names = this->Target->GetAllFileSetNames(); - return std::any_of(fs_names.begin(), fs_names.end(), - [this](std::string const& name) -> bool { - auto const* file_set = this->Target->GetFileSet(name); - if (!file_set) { - this->Makefile->IssueMessage( - MessageType::INTERNAL_ERROR, - cmStrCat("Target \"", this->Target->GetName(), - "\" is tracked to have file set \"", name, - "\", but it was not found.")); - return false; - } - - auto const& fs_type = file_set->GetType(); - return fs_type == "CXX_MODULES"_s; - }); + return std::any_of( + fs_names.begin(), fs_names.end(), + [this, errorMessage](std::string const& name) -> bool { + auto const* file_set = this->Target->GetFileSet(name); + if (!file_set) { + auto message = cmStrCat("Target \"", this->Target->GetName(), + "\" is tracked to have file set \"", name, + "\", but it was not found."); + if (errorMessage) { + *errorMessage = std::move(message); + } else { + this->Makefile->IssueMessage(MessageType::INTERNAL_ERROR, message); + } + return false; + } + + auto const& fs_type = file_set->GetType(); + return fs_type == "CXX_MODULES"_s; + }); } cmGeneratorTarget::Cxx20SupportLevel cmGeneratorTarget::HaveCxxModuleSupport( |