diff options
Diffstat (limited to 'Source/cmGeneratorTarget.cxx')
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 1124 |
1 files changed, 584 insertions, 540 deletions
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 036a07d..3048c5f 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -7,7 +7,7 @@ #include <assert.h> #include <errno.h> #include <iterator> -#include <memory> // IWYU pragma: keep +#include <memory> #include <queue> #include <sstream> #include <stdio.h> @@ -22,7 +22,9 @@ #include "cmCustomCommandGenerator.h" #include "cmCustomCommandLines.h" #include "cmGeneratorExpression.h" +#include "cmGeneratorExpressionContext.h" #include "cmGeneratorExpressionDAGChecker.h" +#include "cmGeneratorExpressionNode.h" #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" @@ -32,10 +34,12 @@ #include "cmSourceFile.h" #include "cmSourceFileLocation.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmTarget.h" #include "cmTargetLinkLibraryType.h" #include "cmTargetPropertyComputer.h" +#include "cm_string_view.hxx" #include "cmake.h" class cmMessenger; @@ -92,9 +96,6 @@ public: virtual bool GetHadContextSensitiveCondition() const { return false; } cmLinkImplItem const& LinkImplItem; - -private: - cmListFileBacktrace Backtrace; }; cmLinkImplItem cmGeneratorTarget::TargetPropertyEntry::NoLinkImplItem; @@ -209,6 +210,62 @@ void CreatePropertyGeneratorExpressions( } } +namespace { +// Represent a target property entry after evaluating generator expressions +// and splitting up lists. +struct EvaluatedTargetPropertyEntry +{ + EvaluatedTargetPropertyEntry(cmLinkImplItem const& item, + cmListFileBacktrace bt) + : LinkImplItem(item) + , Backtrace(std::move(bt)) + { + } + + // Move-only. + EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry&&) = default; + EvaluatedTargetPropertyEntry(EvaluatedTargetPropertyEntry const&) = delete; + EvaluatedTargetPropertyEntry& operator=(EvaluatedTargetPropertyEntry&&) = + delete; + EvaluatedTargetPropertyEntry& operator=( + EvaluatedTargetPropertyEntry const&) = delete; + + cmLinkImplItem const& LinkImplItem; + cmListFileBacktrace Backtrace; + std::vector<std::string> Values; + bool ContextDependent = false; +}; + +EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry( + cmGeneratorTarget const* thisTarget, std::string const& config, + std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker, + cmGeneratorTarget::TargetPropertyEntry* entry) +{ + EvaluatedTargetPropertyEntry ee(entry->LinkImplItem, entry->GetBacktrace()); + cmExpandList(entry->Evaluate(thisTarget->GetLocalGenerator(), config, false, + thisTarget, dagChecker, lang), + ee.Values); + if (entry->GetHadContextSensitiveCondition()) { + ee.ContextDependent = true; + } + return ee; +} + +std::vector<EvaluatedTargetPropertyEntry> EvaluateTargetPropertyEntries( + cmGeneratorTarget const* thisTarget, std::string const& config, + std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker, + std::vector<cmGeneratorTarget::TargetPropertyEntry*> const& in) +{ + std::vector<EvaluatedTargetPropertyEntry> out; + out.reserve(in.size()); + for (cmGeneratorTarget::TargetPropertyEntry* entry : in) { + out.emplace_back(EvaluateTargetPropertyEntry(thisTarget, config, lang, + dagChecker, entry)); + } + return out; +} +} + cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) : Target(t) , FortranModuleDirectoryCreated(false) @@ -259,9 +316,6 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) t->GetSourceBacktraces(), this->SourceEntries, true); - this->DLLPlatform = - !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty(); - this->PolicyMap = t->GetPolicyMap(); } @@ -468,12 +522,14 @@ std::string cmGeneratorTarget::GetFilePrefix( const std::string& config, cmStateEnums::ArtifactType artifact) const { if (this->IsImported()) { - const char* prefix = this->GetFilePrefixInternal(artifact); + const char* prefix = this->GetFilePrefixInternal(config, artifact); return prefix ? prefix : std::string(); } - std::string prefix, suffix, base; + std::string prefix; + std::string suffix; + std::string base; this->GetFullNameInternal(config, artifact, prefix, base, suffix); return prefix; } @@ -481,12 +537,14 @@ std::string cmGeneratorTarget::GetFileSuffix( const std::string& config, cmStateEnums::ArtifactType artifact) const { if (this->IsImported()) { - const char* suffix = this->GetFileSuffixInternal(artifact); + const char* suffix = this->GetFileSuffixInternal(config, artifact); return suffix ? suffix : std::string(); } - std::string prefix, suffix, base; + std::string prefix; + std::string suffix; + std::string base; this->GetFullNameInternal(config, artifact, prefix, base, suffix); return suffix; } @@ -495,8 +553,8 @@ std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const { const char* postfix = nullptr; if (!config.empty()) { - std::string configProp = cmSystemTools::UpperCase(config); - configProp += "_POSTFIX"; + std::string configProp = + cmStrCat(cmSystemTools::UpperCase(config), "_POSTFIX"); postfix = this->GetProperty(configProp); // Mac application bundles and frameworks have no postfix. if (!this->IsImported() && postfix && @@ -508,7 +566,8 @@ std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const } const char* cmGeneratorTarget::GetFilePrefixInternal( - cmStateEnums::ArtifactType artifact, const std::string& language) const + std::string const& config, cmStateEnums::ArtifactType artifact, + const std::string& language) const { // no prefix for non-main target types. if (this->GetType() != cmStateEnums::STATIC_LIBRARY && @@ -523,8 +582,7 @@ const char* cmGeneratorTarget::GetFilePrefixInternal( // Return an empty prefix for the import library if this platform // does not support import libraries. - if (isImportedLibraryArtifact && - !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) { + if (isImportedLibraryArtifact && !this->NeedImportLibraryName(config)) { return nullptr; } @@ -558,7 +616,8 @@ const char* cmGeneratorTarget::GetFilePrefixInternal( return targetPrefix; } const char* cmGeneratorTarget::GetFileSuffixInternal( - cmStateEnums::ArtifactType artifact, const std::string& language) const + std::string const& config, cmStateEnums::ArtifactType artifact, + const std::string& language) const { // no suffix for non-main target types. if (this->GetType() != cmStateEnums::STATIC_LIBRARY && @@ -573,8 +632,7 @@ const char* cmGeneratorTarget::GetFileSuffixInternal( // Return an empty suffix for the import library if this platform // does not support import libraries. - if (isImportedLibraryArtifact && - !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) { + if (isImportedLibraryArtifact && !this->NeedImportLibraryName(config)) { return nullptr; } @@ -657,20 +715,21 @@ std::vector<cmSourceFile*> const* cmGeneratorTarget::GetSourceDepends( return nullptr; } -static void handleSystemIncludesDep( - cmLocalGenerator* lg, cmGeneratorTarget const* depTgt, - const std::string& config, cmGeneratorTarget const* headTarget, - cmGeneratorExpressionDAGChecker* dagChecker, - std::vector<std::string>& result, bool excludeImported, - std::string const& language) +namespace { +void handleSystemIncludesDep(cmLocalGenerator* lg, + cmGeneratorTarget const* depTgt, + const std::string& config, + cmGeneratorTarget const* headTarget, + cmGeneratorExpressionDAGChecker* dagChecker, + std::vector<std::string>& result, + bool excludeImported, std::string const& language) { if (const char* dirs = depTgt->GetProperty("INTERFACE_SYSTEM_INCLUDE_DIRECTORIES")) { cmGeneratorExpression ge; - cmSystemTools::ExpandListArgument( - ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, depTgt, - dagChecker, language), - result); + cmExpandList(ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, + depTgt, dagChecker, language), + result); } if (!depTgt->IsImported() || excludeImported) { return; @@ -679,12 +738,12 @@ static void handleSystemIncludesDep( if (const char* dirs = depTgt->GetProperty("INTERFACE_INCLUDE_DIRECTORIES")) { cmGeneratorExpression ge; - cmSystemTools::ExpandListArgument( - ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, depTgt, - dagChecker, language), - result); + cmExpandList(ge.Parse(dirs)->Evaluate(lg, config, false, headTarget, + depTgt, dagChecker, language), + result); } } +} /* clang-format off */ #define IMPLEMENT_VISIT(KIND) \ @@ -735,9 +794,8 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature, const std::string& config) const { if (!config.empty()) { - std::string featureConfig = feature; - featureConfig += "_"; - featureConfig += cmSystemTools::UpperCase(config); + std::string featureConfig = + cmStrCat(feature, '_', cmSystemTools::UpperCase(config)); if (const char* value = this->GetProperty(featureConfig)) { return value; } @@ -771,7 +829,7 @@ bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang, std::string const& config) const { const char* feature = "INTERPROCEDURAL_OPTIMIZATION"; - const bool result = cmSystemTools::IsOn(this->GetFeature(feature, config)); + const bool result = cmIsOn(this->GetFeature(feature, config)); if (!result) { // 'INTERPROCEDURAL_OPTIMIZATION' is off, no need to check policies @@ -1057,10 +1115,9 @@ bool cmGeneratorTarget::IsSystemIncludeDirectory( std::vector<std::string> result; for (std::string const& it : this->Target->GetSystemIncludeDirectories()) { cmGeneratorExpression ge; - cmSystemTools::ExpandListArgument( - ge.Parse(it)->Evaluate(this->LocalGenerator, config, false, this, - &dagChecker, language), - result); + cmExpandList(ge.Parse(it)->Evaluate(this->LocalGenerator, config, false, + this, &dagChecker, language), + result); } std::vector<cmGeneratorTarget const*> const& deps = @@ -1087,77 +1144,204 @@ bool cmGeneratorTarget::GetPropertyAsBool(const std::string& prop) const return this->Target->GetPropertyAsBool(prop); } -static void AddInterfaceEntries( - cmGeneratorTarget const* thisTarget, std::string const& config, - std::string const& prop, - std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries) +bool cmGeneratorTarget::MaybeHaveInterfaceProperty( + std::string const& prop, cmGeneratorExpressionContext* context) const +{ + std::string const key = prop + '@' + context->Config; + auto i = this->MaybeInterfacePropertyExists.find(key); + if (i == this->MaybeInterfacePropertyExists.end()) { + // Insert an entry now in case there is a cycle. + i = this->MaybeInterfacePropertyExists.emplace(key, false).first; + bool& maybeInterfaceProp = i->second; + + // If this target itself has a non-empty property value, we are done. + const char* p = this->GetProperty(prop); + maybeInterfaceProp = p && *p; + + // Otherwise, recurse to interface dependencies. + if (!maybeInterfaceProp) { + cmGeneratorTarget const* headTarget = + context->HeadTarget ? context->HeadTarget : this; + if (cmLinkInterfaceLibraries const* iface = + this->GetLinkInterfaceLibraries(context->Config, headTarget, + true)) { + if (iface->HadHeadSensitiveCondition) { + // With a different head target we may get to a library with + // this interface property. + maybeInterfaceProp = true; + } else { + // The transitive interface libraries do not depend on the + // head target, so we can follow them. + for (cmLinkItem const& lib : iface->Libraries) { + if (lib.Target && + lib.Target->MaybeHaveInterfaceProperty(prop, context)) { + maybeInterfaceProp = true; + break; + } + } + } + } + } + } + return i->second; +} + +std::string cmGeneratorTarget::EvaluateInterfaceProperty( + std::string const& prop, cmGeneratorExpressionContext* context, + cmGeneratorExpressionDAGChecker* dagCheckerParent) const +{ + std::string result; + + // If the property does not appear transitively at all, we are done. + if (!this->MaybeHaveInterfaceProperty(prop, context)) { + return result; + } + + // Evaluate $<TARGET_PROPERTY:this,prop> as if it were compiled. This is + // a subset of TargetPropertyNode::Evaluate without stringify/parse steps + // but sufficient for transitive interface properties. + cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace, this, prop, + nullptr, dagCheckerParent); + switch (dagChecker.Check()) { + case cmGeneratorExpressionDAGChecker::SELF_REFERENCE: + dagChecker.ReportError( + context, "$<TARGET_PROPERTY:" + this->GetName() + "," + prop + ">"); + return result; + case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: + // No error. We just skip cyclic references. + return result; + case cmGeneratorExpressionDAGChecker::ALREADY_SEEN: + // No error. We have already seen this transitive property. + return result; + case cmGeneratorExpressionDAGChecker::DAG: + break; + } + + cmGeneratorTarget const* headTarget = + context->HeadTarget ? context->HeadTarget : this; + + if (const char* p = this->GetProperty(prop)) { + result = cmGeneratorExpressionNode::EvaluateDependentExpression( + p, context->LG, context, headTarget, this, &dagChecker); + } + + if (cmLinkInterfaceLibraries const* iface = + this->GetLinkInterfaceLibraries(context->Config, headTarget, true)) { + for (cmLinkItem const& lib : iface->Libraries) { + // Broken code can have a target in its own link interface. + // Don't follow such link interface entries so as not to create a + // self-referencing loop. + if (lib.Target && lib.Target != this) { + // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in the + // above property and hand-evaluate it as if it were compiled. + // Create a context as cmCompiledGeneratorExpression::Evaluate does. + cmGeneratorExpressionContext libContext( + context->LG, context->Config, context->Quiet, headTarget, this, + context->EvaluateForBuildsystem, context->Backtrace, + context->Language); + std::string libResult = cmGeneratorExpression::StripEmptyListElements( + lib.Target->EvaluateInterfaceProperty(prop, &libContext, + &dagChecker)); + if (!libResult.empty()) { + if (result.empty()) { + result = std::move(libResult); + } else { + result.reserve(result.size() + 1 + libResult.size()); + result += ";"; + result += libResult; + } + } + context->HadContextSensitiveCondition = + context->HadContextSensitiveCondition || + libContext.HadContextSensitiveCondition; + context->HadHeadSensitiveCondition = + context->HadHeadSensitiveCondition || + libContext.HadHeadSensitiveCondition; + } + } + } + + return result; +} + +namespace { +void AddInterfaceEntries(cmGeneratorTarget const* headTarget, + std::string const& config, std::string const& prop, + std::string const& lang, + cmGeneratorExpressionDAGChecker* dagChecker, + std::vector<EvaluatedTargetPropertyEntry>& entries) { if (cmLinkImplementationLibraries const* impl = - thisTarget->GetLinkImplementationLibraries(config)) { + headTarget->GetLinkImplementationLibraries(config)) { for (cmLinkImplItem const& lib : impl->Libraries) { if (lib.Target) { - std::string uniqueName = - thisTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely( - lib.Target); - std::string genex = - "$<TARGET_PROPERTY:" + std::move(uniqueName) + "," + prop + ">"; - cmGeneratorExpression ge(lib.Backtrace); - std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex); - cge->SetEvaluateForBuildsystem(true); - entries.push_back(new TargetPropertyEntryGenex(std::move(cge), lib)); + EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace); + // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our + // caller's property and hand-evaluate it as if it were compiled. + // Create a context as cmCompiledGeneratorExpression::Evaluate does. + cmGeneratorExpressionContext context( + headTarget->GetLocalGenerator(), config, false, headTarget, + headTarget, true, lib.Backtrace, lang); + cmExpandList( + lib.Target->EvaluateInterfaceProperty(prop, &context, dagChecker), + ee.Values); + ee.ContextDependent = context.HadContextSensitiveCondition; + entries.emplace_back(std::move(ee)); } } } } -static void AddObjectEntries( - cmGeneratorTarget const* thisTarget, std::string const& config, - std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries) +void AddObjectEntries(cmGeneratorTarget const* headTarget, + std::string const& config, + cmGeneratorExpressionDAGChecker* dagChecker, + std::vector<EvaluatedTargetPropertyEntry>& entries) { if (cmLinkImplementationLibraries const* impl = - thisTarget->GetLinkImplementationLibraries(config)) { + headTarget->GetLinkImplementationLibraries(config)) { for (cmLinkImplItem const& lib : impl->Libraries) { if (lib.Target && lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) { std::string uniqueName = - thisTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely( + headTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely( lib.Target); std::string genex = "$<TARGET_OBJECTS:" + std::move(uniqueName) + ">"; cmGeneratorExpression ge(lib.Backtrace); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex); cge->SetEvaluateForBuildsystem(true); - entries.push_back(new TargetPropertyEntryGenex(std::move(cge), lib)); + + EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace); + cmExpandList(cge->Evaluate(headTarget->GetLocalGenerator(), config, + false, headTarget, dagChecker), + ee.Values); + if (cge->GetHadContextSensitiveCondition()) { + ee.ContextDependent = true; + } + entries.emplace_back(std::move(ee)); } } } } -static bool processSources( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& srcs, - std::unordered_set<std::string>& uniqueSrcs, - cmGeneratorExpressionDAGChecker* dagChecker, std::string const& config, - bool debugSources) +bool processSources(cmGeneratorTarget const* tgt, + std::vector<EvaluatedTargetPropertyEntry>& entries, + std::vector<BT<std::string>>& srcs, + std::unordered_set<std::string>& uniqueSrcs, + bool debugSources) { cmMakefile* mf = tgt->Target->GetMakefile(); bool contextDependent = false; - for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) { - cmLinkImplItem const& item = entry->LinkImplItem; - std::string const& targetName = item.AsStr(); - std::vector<std::string> entrySources; - cmSystemTools::ExpandListArgument(entry->Evaluate(tgt->GetLocalGenerator(), - config, false, tgt, tgt, - dagChecker), - entrySources); - - if (entry->GetHadContextSensitiveCondition()) { + for (EvaluatedTargetPropertyEntry& entry : entries) { + if (entry.ContextDependent) { contextDependent = true; } - for (std::string& src : entrySources) { + cmLinkImplItem const& item = entry.LinkImplItem; + std::string const& targetName = item.AsStr(); + + for (std::string& src : entry.Values) { cmSourceFile* sf = mf->GetOrCreateSource(src); std::string e; std::string fullPath = sf->GetFullPath(&e); @@ -1186,9 +1370,9 @@ static bool processSources( src = fullPath; } std::string usedSources; - for (std::string const& src : entrySources) { + for (std::string const& src : entry.Values) { if (uniqueSrcs.insert(src).second) { - srcs.emplace_back(src, entry->GetBacktrace()); + srcs.emplace_back(src, entry.Backtrace); if (debugSources) { usedSources += " * " + src + "\n"; } @@ -1199,11 +1383,12 @@ static bool processSources( MessageType::LOG, std::string("Used sources for target ") + tgt->GetName() + ":\n" + usedSources, - entry->GetBacktrace()); + entry.Backtrace); } } return contextDependent; } +} std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( std::string const& config) const @@ -1220,8 +1405,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( cmStringRange sourceEntries = this->Target->GetSourceEntries(); for (std::string const& entry : sourceEntries) { - std::vector<std::string> items; - cmSystemTools::ExpandListArgument(entry, items); + std::vector<std::string> items = cmExpandedList(entry); for (std::string const& item : items) { if (cmHasLiteralPrefix(item, "$<TARGET_OBJECTS:") && item.back() == '>') { @@ -1237,12 +1421,11 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( const char* debugProp = this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } - bool debugSources = !this->DebugSourcesDone && - std::find(debugProperties.begin(), debugProperties.end(), "SOURCES") != - debugProperties.end(); + bool debugSources = + !this->DebugSourcesDone && cmContains(debugProperties, "SOURCES"); if (this->LocalGenerator->GetGlobalGenerator()->GetConfigureDoneCMP0026()) { this->DebugSourcesDone = true; @@ -1251,28 +1434,28 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( cmGeneratorExpressionDAGChecker dagChecker(this, "SOURCES", nullptr, nullptr); + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, std::string(), &dagChecker, + this->SourceEntries); + std::unordered_set<std::string> uniqueSrcs; bool contextDependentDirectSources = - processSources(this, this->SourceEntries, files, uniqueSrcs, &dagChecker, - config, debugSources); + processSources(this, entries, files, uniqueSrcs, debugSources); // Collect INTERFACE_SOURCES of all direct link-dependencies. - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceSourcesEntries; - AddInterfaceEntries(this, config, "INTERFACE_SOURCES", - linkInterfaceSourcesEntries); + std::vector<EvaluatedTargetPropertyEntry> linkInterfaceSourcesEntries; + AddInterfaceEntries(this, config, "INTERFACE_SOURCES", std::string(), + &dagChecker, linkInterfaceSourcesEntries); std::vector<std::string>::size_type numFilesBefore = files.size(); - bool contextDependentInterfaceSources = - processSources(this, linkInterfaceSourcesEntries, files, uniqueSrcs, - &dagChecker, config, debugSources); + bool contextDependentInterfaceSources = processSources( + this, linkInterfaceSourcesEntries, files, uniqueSrcs, debugSources); // Collect TARGET_OBJECTS of direct object link-dependencies. - std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkObjectsEntries; - AddObjectEntries(this, config, linkObjectsEntries); + std::vector<EvaluatedTargetPropertyEntry> linkObjectsEntries; + AddObjectEntries(this, config, &dagChecker, linkObjectsEntries); std::vector<std::string>::size_type numFilesBefore2 = files.size(); bool contextDependentObjects = - processSources(this, linkObjectsEntries, files, uniqueSrcs, &dagChecker, - config, debugSources); + processSources(this, linkObjectsEntries, files, uniqueSrcs, debugSources); if (!contextDependentDirectSources && !(contextDependentInterfaceSources && numFilesBefore < files.size()) && @@ -1280,8 +1463,6 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( this->LinkImplementationLanguageIsContextDependent = false; } - cmDeleteAll(linkInterfaceSourcesEntries); - cmDeleteAll(linkObjectsEntries); return files; } @@ -1521,8 +1702,7 @@ std::string cmGeneratorTarget::GetCompilePDBName( // Check for a per-configuration output directory target property. std::string configUpper = cmSystemTools::UpperCase(config); - std::string configProp = "COMPILE_PDB_NAME_"; - configProp += configUpper; + std::string configProp = cmStrCat("COMPILE_PDB_NAME_", configUpper); const char* config_name = this->GetProperty(configProp); if (config_name && *config_name) { return prefix + config_name + ".pdb"; @@ -1594,9 +1774,8 @@ bool cmGeneratorTarget::NeedRelinkBeforeInstall( // Check for rpath support on this platform. std::string ll = this->GetLinkerLanguage(config); if (!ll.empty()) { - std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; - flagVar += ll; - flagVar += "_FLAG"; + std::string flagVar = + cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG"); if (!this->Makefile->IsSet(flagVar)) { // There is no rpath support on this platform so nothing needs // relinking. @@ -1612,7 +1791,7 @@ bool cmGeneratorTarget::NeedRelinkBeforeInstall( // will likely change between the build tree and install tree and // this target must be relinked. bool have_rpath = - this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH(); + this->HaveBuildTreeRPATH(config) || this->HaveInstallTreeRPATH(config); bool is_ninja = this->LocalGenerator->GetGlobalGenerator()->GetName() == "Ninja"; @@ -1674,9 +1853,8 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const // binaries. std::string ll = this->GetLinkerLanguage(config); if (!ll.empty()) { - std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_"; - sepVar += ll; - sepVar += "_FLAG_SEP"; + std::string sepVar = + cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG_SEP"); const char* sep = this->Makefile->GetDefinition(sepVar); if (sep && *sep) { // TODO: Add ELF check to ABI detection and get rid of @@ -1793,7 +1971,7 @@ bool cmGeneratorTarget::MacOSXUseInstallNameDir() const const char* build_with_install_name = this->GetProperty("BUILD_WITH_INSTALL_NAME_DIR"); if (build_with_install_name) { - return cmSystemTools::IsOn(build_with_install_name); + return cmIsOn(build_with_install_name); } cmPolicies::PolicyStatus cmp0068 = this->GetPolicyStatusCMP0068(); @@ -1858,23 +2036,23 @@ std::string cmGeneratorTarget::GetSOName(const std::string& config) const return this->GetLibraryNames(config).SharedObject; } -static bool shouldAddFullLevel(cmGeneratorTarget::BundleDirectoryLevel level) +namespace { +bool shouldAddFullLevel(cmGeneratorTarget::BundleDirectoryLevel level) { return level == cmGeneratorTarget::FullLevel; } -static bool shouldAddContentLevel( - cmGeneratorTarget::BundleDirectoryLevel level) +bool shouldAddContentLevel(cmGeneratorTarget::BundleDirectoryLevel level) { return level == cmGeneratorTarget::ContentLevel || shouldAddFullLevel(level); } +} std::string cmGeneratorTarget::GetAppBundleDirectory( const std::string& config, BundleDirectoryLevel level) const { - std::string fpath = - this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact); - fpath += "."; + std::string fpath = cmStrCat( + this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact), '.'); const char* ext = this->GetProperty("BUNDLE_EXTENSION"); if (!ext) { ext = "app"; @@ -1899,9 +2077,8 @@ bool cmGeneratorTarget::IsBundleOnApple() const std::string cmGeneratorTarget::GetCFBundleDirectory( const std::string& config, BundleDirectoryLevel level) const { - std::string fpath; - fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact); - fpath += "."; + std::string fpath = cmStrCat( + this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.'); const char* ext = this->GetProperty("BUNDLE_EXTENSION"); if (!ext) { if (this->IsXCTestOnApple()) { @@ -1924,9 +2101,8 @@ std::string cmGeneratorTarget::GetCFBundleDirectory( std::string cmGeneratorTarget::GetFrameworkDirectory( const std::string& config, BundleDirectoryLevel level) const { - std::string fpath; - fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact); - fpath += "."; + std::string fpath = cmStrCat( + this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.'); const char* ext = this->GetProperty("BUNDLE_EXTENSION"); if (!ext) { ext = "framework"; @@ -1983,8 +2159,7 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) { if (install_name_dir && *install_name_dir) { - dir = install_name_dir; - dir += "/"; + dir = cmStrCat(install_name_dir, '/'); } } if (!install_name_dir) { @@ -2025,8 +2200,7 @@ const std::string* cmGeneratorTarget::GetExportMacro() const if (const char* custom_export_name = this->GetProperty("DEFINE_SYMBOL")) { this->ExportMacro = custom_export_name; } else { - std::string in = this->GetName(); - in += "_EXPORTS"; + std::string in = cmStrCat(this->GetName(), "_EXPORTS"); this->ExportMacro = cmSystemTools::MakeCidentifier(in); } return &this->ExportMacro; @@ -2247,8 +2421,7 @@ std::string cmGeneratorTarget::GetMacContentDirectory( const std::string& config, cmStateEnums::ArtifactType artifact) const { // Start with the output directory for the target. - std::string fpath = this->GetDirectory(config, artifact); - fpath += "/"; + std::string fpath = cmStrCat(this->GetDirectory(config, artifact), '/'); BundleDirectoryLevel level = ContentLevel; if (this->IsFrameworkOnApple()) { // additional files with a framework go into the version specific @@ -2284,10 +2457,9 @@ cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo( } if (this->GetType() > cmStateEnums::OBJECT_LIBRARY) { - std::string msg = "cmTarget::GetCompileInfo called for "; - msg += this->GetName(); - msg += " which has type "; - msg += cmState::GetTargetTypeName(this->GetType()); + std::string msg = cmStrCat("cmTarget::GetCompileInfo called for ", + this->GetName(), " which has type ", + cmState::GetTargetTypeName(this->GetType())); this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); return nullptr; } @@ -2341,7 +2513,7 @@ void cmGeneratorTarget::ComputeModuleDefinitionInfo( info.WindowsExportAllSymbols = this->Makefile->IsOn("CMAKE_SUPPORT_WINDOWS_EXPORT_ALL_SYMBOLS") && this->GetPropertyAsBool("WINDOWS_EXPORT_ALL_SYMBOLS"); -#if defined(_WIN32) && defined(CMAKE_BUILD_WITH_CMAKE) +#if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP) info.DefFileGenerated = info.WindowsExportAllSymbols || info.Sources.size() > 1; #else @@ -2357,7 +2529,7 @@ void cmGeneratorTarget::ComputeModuleDefinitionInfo( bool cmGeneratorTarget::IsDLLPlatform() const { - return this->DLLPlatform; + return this->Target->IsDLLPlatform(); } void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result, @@ -2372,10 +2544,9 @@ void cmGeneratorTarget::GetAutoUicOptions(std::vector<std::string>& result, cmGeneratorExpressionDAGChecker dagChecker(this, "AUTOUIC_OPTIONS", nullptr, nullptr); - cmSystemTools::ExpandListArgument( - ge.Parse(prop)->Evaluate(this->LocalGenerator, config, false, this, - &dagChecker), - result); + cmExpandList(ge.Parse(prop)->Evaluate(this->LocalGenerator, config, false, + this, &dagChecker), + result); } void processILibs(const std::string& config, @@ -2468,7 +2639,7 @@ cmTargetTraceDependencies::cmTargetTraceDependencies(cmGeneratorTarget* target) for (cmSourceFile* sf : sources) { const std::set<cmGeneratorTarget const*> tgts = this->GlobalGenerator->GetFilenameTargetDepends(sf); - if (tgts.find(this->GeneratorTarget) != tgts.end()) { + if (cmContains(tgts, this->GeneratorTarget)) { std::ostringstream e; e << "Evaluation output file\n \"" << sf->GetFullPath() << "\"\ndepends on the sources of a target it is used in. This " @@ -2502,8 +2673,7 @@ void cmTargetTraceDependencies::Trace() // Queue dependencies added explicitly by the user. if (const char* additionalDeps = sf->GetProperty("OBJECT_DEPENDS")) { - std::vector<std::string> objDeps; - cmSystemTools::ExpandListArgument(additionalDeps, objDeps); + std::vector<std::string> objDeps = cmExpandedList(additionalDeps); for (std::string& objDep : objDeps) { if (cmSystemTools::FileIsFullPath(objDep)) { objDep = cmSystemTools::CollapseFullPath(objDep); @@ -2716,15 +2886,15 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config, { const char* archs = nullptr; if (!config.empty()) { - std::string defVarName = "OSX_ARCHITECTURES_"; - defVarName += cmSystemTools::UpperCase(config); + std::string defVarName = + cmStrCat("OSX_ARCHITECTURES_", cmSystemTools::UpperCase(config)); archs = this->GetProperty(defVarName); } if (!archs) { archs = this->GetProperty("OSX_ARCHITECTURES"); } if (archs) { - cmSystemTools::ExpandListArgument(std::string(archs), archVec); + cmExpandList(std::string(archs), archVec); } } @@ -2757,33 +2927,35 @@ std::string cmGeneratorTarget::GetCreateRuleVariable( case cmStateEnums::MODULE_LIBRARY: return "CMAKE_" + lang + "_CREATE_SHARED_MODULE"; case cmStateEnums::EXECUTABLE: + if (this->IsExecutableWithExports()) { + std::string linkExeWithExports = + "CMAKE_" + lang + "_LINK_EXECUTABLE_WITH_EXPORTS"; + if (this->Makefile->IsDefinitionSet(linkExeWithExports)) { + return linkExeWithExports; + } + } return "CMAKE_" + lang + "_LINK_EXECUTABLE"; default: break; } return ""; } -static void processIncludeDirectories( + +namespace { +void processIncludeDirectories( cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, + std::vector<EvaluatedTargetPropertyEntry>& entries, std::vector<BT<std::string>>& includes, - std::unordered_set<std::string>& uniqueIncludes, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - bool debugIncludes, const std::string& language) + std::unordered_set<std::string>& uniqueIncludes, bool debugIncludes) { - for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) { - cmLinkImplItem const& item = entry->LinkImplItem; + for (EvaluatedTargetPropertyEntry& entry : entries) { + cmLinkImplItem const& item = entry.LinkImplItem; std::string const& targetName = item.AsStr(); bool const fromImported = item.Target && item.Target->IsImported(); bool const checkCMP0027 = item.FromGenex; - std::vector<std::string> entryIncludes; - cmSystemTools::ExpandListArgument(entry->Evaluate(tgt->GetLocalGenerator(), - config, false, tgt, - dagChecker, language), - entryIncludes); std::string usedIncludes; - for (std::string& entryInclude : entryIncludes) { + for (std::string& entryInclude : entry.Values) { if (fromImported && !cmSystemTools::FileExists(entryInclude)) { std::ostringstream e; MessageType messageType = MessageType::FATAL_ERROR; @@ -2852,15 +3024,14 @@ static void processIncludeDirectories( } } - if (!cmSystemTools::IsOff(entryInclude)) { + if (!cmIsOff(entryInclude)) { cmSystemTools::ConvertToUnixSlashes(entryInclude); } - std::string inc = entryInclude; - if (uniqueIncludes.insert(inc).second) { - includes.emplace_back(inc, entry->GetBacktrace()); + if (uniqueIncludes.insert(entryInclude).second) { + includes.emplace_back(entryInclude, entry.Backtrace); if (debugIncludes) { - usedIncludes += " * " + inc + "\n"; + usedIncludes += " * " + entryInclude + "\n"; } } } @@ -2869,10 +3040,11 @@ static void processIncludeDirectories( MessageType::LOG, std::string("Used includes for target ") + tgt->GetName() + ":\n" + usedIncludes, - entry->GetBacktrace()); + entry.Backtrace); } } } +} std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( const std::string& config, const std::string& lang) const @@ -2887,25 +3059,22 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( const char* debugProp = this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } bool debugIncludes = !this->DebugIncludesDone && - std::find(debugProperties.begin(), debugProperties.end(), - "INCLUDE_DIRECTORIES") != debugProperties.end(); + cmContains(debugProperties, "INCLUDE_DIRECTORIES"); if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { this->DebugIncludesDone = true; } - processIncludeDirectories(this, this->IncludeDirectoriesEntries, includes, - uniqueIncludes, &dagChecker, config, debugIncludes, - lang); + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, lang, &dagChecker, + this->IncludeDirectoriesEntries); - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceIncludeDirectoriesEntries; - AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", - linkInterfaceIncludeDirectoriesEntries); + AddInterfaceEntries(this, config, "INTERFACE_INCLUDE_DIRECTORIES", lang, + &dagChecker, entries); if (this->Makefile->IsOn("APPLE")) { cmLinkImplementationLibraries const* impl = @@ -2921,16 +3090,14 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( libDir = frameworkCheck.match(1); - linkInterfaceIncludeDirectoriesEntries.push_back( - CreateTargetPropertyEntry(libDir)); + EvaluatedTargetPropertyEntry ee(lib, cmListFileBacktrace()); + ee.Values.emplace_back(std::move(libDir)); + entries.emplace_back(std::move(ee)); } } - processIncludeDirectories(this, linkInterfaceIncludeDirectoriesEntries, - includes, uniqueIncludes, &dagChecker, config, - debugIncludes, lang); - - cmDeleteAll(linkInterfaceIncludeDirectoriesEntries); + processIncludeDirectories(this, entries, includes, uniqueIncludes, + debugIncludes); return includes; } @@ -2941,33 +3108,26 @@ enum class OptionsParse Shell }; -static void processOptionsInternal( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& options, - std::unordered_set<std::string>& uniqueOptions, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - bool debugOptions, const char* logName, std::string const& language, - OptionsParse parse) -{ - for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) { - std::vector<std::string> entryOptions; - cmSystemTools::ExpandListArgument(entry->Evaluate(tgt->GetLocalGenerator(), - config, false, tgt, - dagChecker, language), - entryOptions); +namespace { +void processOptions(cmGeneratorTarget const* tgt, + std::vector<EvaluatedTargetPropertyEntry> const& entries, + std::vector<BT<std::string>>& options, + std::unordered_set<std::string>& uniqueOptions, + bool debugOptions, const char* logName, OptionsParse parse) +{ + for (EvaluatedTargetPropertyEntry const& entry : entries) { std::string usedOptions; - for (std::string const& opt : entryOptions) { + for (std::string const& opt : entry.Values) { if (uniqueOptions.insert(opt).second) { if (parse == OptionsParse::Shell && cmHasLiteralPrefix(opt, "SHELL:")) { std::vector<std::string> tmp; cmSystemTools::ParseUnixCommandLine(opt.c_str() + 6, tmp); for (std::string& o : tmp) { - options.emplace_back(std::move(o), entry->GetBacktrace()); + options.emplace_back(std::move(o), entry.Backtrace); } } else { - options.emplace_back(opt, entry->GetBacktrace()); + options.emplace_back(opt, entry.Backtrace); } if (debugOptions) { usedOptions += " * " + opt + "\n"; @@ -2979,22 +3139,10 @@ static void processOptionsInternal( MessageType::LOG, std::string("Used ") + logName + std::string(" for target ") + tgt->GetName() + ":\n" + usedOptions, - entry->GetBacktrace()); + entry.Backtrace); } } } - -static void processCompileOptions( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& options, - std::unordered_set<std::string>& uniqueOptions, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - bool debugOptions, std::string const& language) -{ - processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, - config, debugOptions, "compile options", language, - OptionsParse::Shell); } void cmGeneratorTarget::GetCompileOptions(std::vector<std::string>& result, @@ -3021,48 +3169,29 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileOptions( const char* debugProp = this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } bool debugOptions = !this->DebugCompileOptionsDone && - std::find(debugProperties.begin(), debugProperties.end(), - "COMPILE_OPTIONS") != debugProperties.end(); + cmContains(debugProperties, "COMPILE_OPTIONS"); if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { this->DebugCompileOptionsDone = true; } - processCompileOptions(this, this->CompileOptionsEntries, result, - uniqueOptions, &dagChecker, config, debugOptions, - language); - - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceCompileOptionsEntries; + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, language, &dagChecker, + this->CompileOptionsEntries); - AddInterfaceEntries(this, config, "INTERFACE_COMPILE_OPTIONS", - linkInterfaceCompileOptionsEntries); + AddInterfaceEntries(this, config, "INTERFACE_COMPILE_OPTIONS", language, + &dagChecker, entries); - processCompileOptions(this, linkInterfaceCompileOptionsEntries, result, - uniqueOptions, &dagChecker, config, debugOptions, - language); + processOptions(this, entries, result, uniqueOptions, debugOptions, + "compile options", OptionsParse::Shell); - cmDeleteAll(linkInterfaceCompileOptionsEntries); return result; } -static void processCompileFeatures( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& options, - std::unordered_set<std::string>& uniqueOptions, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - bool debugOptions) -{ - processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, - config, debugOptions, "compile features", - std::string(), OptionsParse::None); -} - void cmGeneratorTarget::GetCompileFeatures(std::vector<std::string>& result, const std::string& config) const { @@ -3086,45 +3215,29 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileFeatures( const char* debugProp = this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } bool debugFeatures = !this->DebugCompileFeaturesDone && - std::find(debugProperties.begin(), debugProperties.end(), - "COMPILE_FEATURES") != debugProperties.end(); + cmContains(debugProperties, "COMPILE_FEATURES"); if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { this->DebugCompileFeaturesDone = true; } - processCompileFeatures(this, this->CompileFeaturesEntries, result, - uniqueFeatures, &dagChecker, config, debugFeatures); + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, std::string(), &dagChecker, + this->CompileFeaturesEntries); - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceCompileFeaturesEntries; AddInterfaceEntries(this, config, "INTERFACE_COMPILE_FEATURES", - linkInterfaceCompileFeaturesEntries); + std::string(), &dagChecker, entries); - processCompileFeatures(this, linkInterfaceCompileFeaturesEntries, result, - uniqueFeatures, &dagChecker, config, debugFeatures); + processOptions(this, entries, result, uniqueFeatures, debugFeatures, + "compile features", OptionsParse::None); - cmDeleteAll(linkInterfaceCompileFeaturesEntries); return result; } -static void processCompileDefinitions( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& options, - std::unordered_set<std::string>& uniqueOptions, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - bool debugOptions, std::string const& language) -{ - processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, - config, debugOptions, "compile definitions", language, - OptionsParse::None); -} - void cmGeneratorTarget::GetCompileDefinitions( std::vector<std::string>& result, const std::string& config, const std::string& language) const @@ -3150,25 +3263,23 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( const char* debugProp = this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } bool debugDefines = !this->DebugCompileDefinitionsDone && - std::find(debugProperties.begin(), debugProperties.end(), - "COMPILE_DEFINITIONS") != debugProperties.end(); + cmContains(debugProperties, "COMPILE_DEFINITIONS"); if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { this->DebugCompileDefinitionsDone = true; } - processCompileDefinitions(this, this->CompileDefinitionsEntries, list, - uniqueOptions, &dagChecker, config, debugDefines, - language); + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, language, &dagChecker, + this->CompileDefinitionsEntries); + + AddInterfaceEntries(this, config, "INTERFACE_COMPILE_DEFINITIONS", language, + &dagChecker, entries); - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceCompileDefinitionsEntries; - AddInterfaceEntries(this, config, "INTERFACE_COMPILE_DEFINITIONS", - linkInterfaceCompileDefinitionsEntries); if (!config.empty()) { std::string configPropName = "COMPILE_DEFINITIONS_" + cmSystemTools::UpperCase(config); @@ -3176,15 +3287,16 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( if (configProp) { switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0043)) { case cmPolicies::WARN: { - std::ostringstream e; - e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0043); - this->LocalGenerator->IssueMessage(MessageType::AUTHOR_WARNING, - e.str()); + this->LocalGenerator->IssueMessage( + MessageType::AUTHOR_WARNING, + cmPolicies::GetPolicyWarning(cmPolicies::CMP0043)); CM_FALLTHROUGH; } case cmPolicies::OLD: { - linkInterfaceCompileDefinitionsEntries.push_back( + std::unique_ptr<TargetPropertyEntry> entry( CreateTargetPropertyEntry(configProp)); + entries.emplace_back(EvaluateTargetPropertyEntry( + this, config, language, &dagChecker, entry.get())); } break; case cmPolicies::NEW: case cmPolicies::REQUIRED_ALWAYS: @@ -3194,29 +3306,12 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( } } - processCompileDefinitions(this, linkInterfaceCompileDefinitionsEntries, list, - uniqueOptions, &dagChecker, config, debugDefines, - language); + processOptions(this, entries, list, uniqueOptions, debugDefines, + "compile definitions", OptionsParse::None); - cmDeleteAll(linkInterfaceCompileDefinitionsEntries); return list; } -namespace { -void processLinkOptions( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& options, - std::unordered_set<std::string>& uniqueOptions, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - bool debugOptions, std::string const& language) -{ - processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, - config, debugOptions, "link options", language, - OptionsParse::Shell); -} -} - void cmGeneratorTarget::GetLinkOptions(std::vector<std::string>& result, const std::string& config, const std::string& language) const @@ -3241,38 +3336,31 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( const char* debugProp = this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } - bool debugOptions = !this->DebugLinkOptionsDone && - std::find(debugProperties.begin(), debugProperties.end(), - "LINK_OPTIONS") != debugProperties.end(); + bool debugOptions = + !this->DebugLinkOptionsDone && cmContains(debugProperties, "LINK_OPTIONS"); if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { this->DebugLinkOptionsDone = true; } - processLinkOptions(this, this->LinkOptionsEntries, result, uniqueOptions, - &dagChecker, config, debugOptions, language); - - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceLinkOptionsEntries; - - AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", - linkInterfaceLinkOptionsEntries); + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, language, &dagChecker, + this->LinkOptionsEntries); - processLinkOptions(this, linkInterfaceLinkOptionsEntries, result, - uniqueOptions, &dagChecker, config, debugOptions, - language); + AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", language, + &dagChecker, entries); - cmDeleteAll(linkInterfaceLinkOptionsEntries); + processOptions(this, entries, result, uniqueOptions, debugOptions, + "link options", OptionsParse::Shell); // Last step: replace "LINKER:" prefixed elements by // actual linker wrapper const std::string wrapper(this->Makefile->GetSafeDefinition( "CMAKE_" + language + "_LINKER_WRAPPER_FLAG")); - std::vector<std::string> wrapperFlag; - cmSystemTools::ExpandListArgument(wrapper, wrapperFlag); + std::vector<std::string> wrapperFlag = cmExpandedList(wrapper); const std::string wrapperSep(this->Makefile->GetSafeDefinition( "CMAKE_" + language + "_LINKER_WRAPPER_FLAG_SEP")); bool concatFlagAndArgs = true; @@ -3300,8 +3388,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( cmSystemTools::ParseUnixCommandLine( value.c_str() + LINKER_SHELL.length(), linkerOptions); } else { - linkerOptions = - cmSystemTools::tokenize(value.substr(LINKER.length()), ","); + linkerOptions = cmTokenize(value.substr(LINKER.length()), ","); } if (linkerOptions.empty() || @@ -3371,21 +3458,6 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( return result; } -namespace { -void processStaticLibraryLinkOptions( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& options, - std::unordered_set<std::string>& uniqueOptions, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - std::string const& language) -{ - processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, - config, false, "static library link options", - language, OptionsParse::Shell); -} -} - void cmGeneratorTarget::GetStaticLibraryLinkOptions( std::vector<std::string>& result, const std::string& config, const std::string& language) const @@ -3402,47 +3474,40 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions( std::string const& config, std::string const& language) const { std::vector<BT<std::string>> result; - std::vector<cmGeneratorTarget::TargetPropertyEntry*> entries; std::unordered_set<std::string> uniqueOptions; cmGeneratorExpressionDAGChecker dagChecker(this, "STATIC_LIBRARY_OPTIONS", nullptr, nullptr); + std::vector<EvaluatedTargetPropertyEntry> entries; if (const char* linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) { - std::vector<std::string> options; - cmSystemTools::ExpandListArgument(linkOptions, options); + std::vector<std::string> options = cmExpandedList(linkOptions); for (const auto& option : options) { - entries.push_back(CreateTargetPropertyEntry(option)); + std::unique_ptr<TargetPropertyEntry> entry( + CreateTargetPropertyEntry(option)); + entries.emplace_back(EvaluateTargetPropertyEntry( + this, config, language, &dagChecker, entry.get())); } } - processStaticLibraryLinkOptions(this, entries, result, uniqueOptions, - &dagChecker, config, language); + processOptions(this, entries, result, uniqueOptions, false, + "static library link options", OptionsParse::Shell); - cmDeleteAll(entries); return result; } namespace { -void processLinkDirectories( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& directories, - std::unordered_set<std::string>& uniqueDirectories, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - bool debugDirectories, std::string const& language) -{ - for (cmGeneratorTarget::TargetPropertyEntry* entry : entries) { - cmLinkImplItem const& item = entry->LinkImplItem; +void processLinkDirectories(cmGeneratorTarget const* tgt, + std::vector<EvaluatedTargetPropertyEntry>& entries, + std::vector<BT<std::string>>& directories, + std::unordered_set<std::string>& uniqueDirectories, + bool debugDirectories) +{ + for (EvaluatedTargetPropertyEntry& entry : entries) { + cmLinkImplItem const& item = entry.LinkImplItem; std::string const& targetName = item.AsStr(); - std::vector<std::string> entryDirectories; - cmSystemTools::ExpandListArgument(entry->Evaluate(tgt->GetLocalGenerator(), - config, false, tgt, - dagChecker, language), - entryDirectories); - std::string usedDirectories; - for (std::string& entryDirectory : entryDirectories) { + for (std::string& entryDirectory : entry.Values) { if (!cmSystemTools::FileIsFullPath(entryDirectory)) { std::ostringstream e; bool noMessage = false; @@ -3495,7 +3560,7 @@ void processLinkDirectories( MessageType::LOG, std::string("Used link directories for target ") + tgt->GetName() + ":\n" + usedDirectories, - entry->GetBacktrace()); + entry.Backtrace); } } } @@ -3526,50 +3591,29 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories( const char* debugProp = this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } bool debugDirectories = !this->DebugLinkDirectoriesDone && - std::find(debugProperties.begin(), debugProperties.end(), - "LINK_DIRECTORIES") != debugProperties.end(); + cmContains(debugProperties, "LINK_DIRECTORIES"); if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { this->DebugLinkDirectoriesDone = true; } - processLinkDirectories(this, this->LinkDirectoriesEntries, result, - uniqueDirectories, &dagChecker, config, - debugDirectories, language); - - std::vector<cmGeneratorTarget::TargetPropertyEntry*> - linkInterfaceLinkDirectoriesEntries; + std::vector<EvaluatedTargetPropertyEntry> entries = + EvaluateTargetPropertyEntries(this, config, language, &dagChecker, + this->LinkDirectoriesEntries); - AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES", - linkInterfaceLinkDirectoriesEntries); + AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES", language, + &dagChecker, entries); - processLinkDirectories(this, linkInterfaceLinkDirectoriesEntries, result, - uniqueDirectories, &dagChecker, config, - debugDirectories, language); + processLinkDirectories(this, entries, result, uniqueDirectories, + debugDirectories); - cmDeleteAll(linkInterfaceLinkDirectoriesEntries); return result; } -namespace { -void processLinkDepends( - cmGeneratorTarget const* tgt, - const std::vector<cmGeneratorTarget::TargetPropertyEntry*>& entries, - std::vector<BT<std::string>>& options, - std::unordered_set<std::string>& uniqueOptions, - cmGeneratorExpressionDAGChecker* dagChecker, const std::string& config, - std::string const& language) -{ - processOptionsInternal(tgt, entries, options, uniqueOptions, dagChecker, - config, false, "link depends", language, - OptionsParse::None); -} -} - void cmGeneratorTarget::GetLinkDepends(std::vector<std::string>& result, const std::string& config, const std::string& language) const @@ -3585,24 +3629,26 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends( std::string const& config, std::string const& language) const { std::vector<BT<std::string>> result; - std::vector<cmGeneratorTarget::TargetPropertyEntry*> linkDependsEntries; std::unordered_set<std::string> uniqueOptions; cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr, nullptr); + std::vector<EvaluatedTargetPropertyEntry> entries; if (const char* linkDepends = this->GetProperty("LINK_DEPENDS")) { - std::vector<std::string> depends; - cmSystemTools::ExpandListArgument(linkDepends, depends); + std::vector<std::string> depends = cmExpandedList(linkDepends); for (const auto& depend : depends) { - linkDependsEntries.push_back(CreateTargetPropertyEntry(depend)); + std::unique_ptr<TargetPropertyEntry> entry( + CreateTargetPropertyEntry(depend)); + entries.emplace_back(EvaluateTargetPropertyEntry( + this, config, language, &dagChecker, entry.get())); } } - AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", - linkDependsEntries); - processLinkDepends(this, linkDependsEntries, result, uniqueOptions, - &dagChecker, config, language); + AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", language, + &dagChecker, entries); + + processOptions(this, entries, result, uniqueOptions, false, "link depends", + OptionsParse::None); - cmDeleteAll(linkDependsEntries); return result; } @@ -3632,33 +3678,25 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const // Add each name. std::string f; if (!targetNames.Output.empty()) { - f = dir; - f += "/"; - f += targetNames.Output; + f = cmStrCat(dir, '/', targetNames.Output); gg->AddToManifest(f); } if (!targetNames.SharedObject.empty()) { - f = dir; - f += "/"; - f += targetNames.SharedObject; + f = cmStrCat(dir, '/', targetNames.SharedObject); gg->AddToManifest(f); } if (!targetNames.Real.empty()) { - f = dir; - f += "/"; - f += targetNames.Real; + f = cmStrCat(dir, '/', targetNames.Real); gg->AddToManifest(f); } if (!targetNames.PDB.empty()) { - f = dir; - f += "/"; - f += targetNames.PDB; + f = cmStrCat(dir, '/', targetNames.PDB); gg->AddToManifest(f); } if (!targetNames.ImportLibrary.empty()) { - f = this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact); - f += "/"; - f += targetNames.ImportLibrary; + f = + cmStrCat(this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact), + '/', targetNames.ImportLibrary); gg->AddToManifest(f); } } @@ -3698,11 +3736,10 @@ std::string cmGeneratorTarget::NormalGetFullPath( const std::string& config, cmStateEnums::ArtifactType artifact, bool realname) const { - std::string fpath = this->GetDirectory(config, artifact); - fpath += "/"; + std::string fpath = cmStrCat(this->GetDirectory(config, artifact), '/'); if (this->IsAppBundleOnApple()) { - fpath = this->BuildBundleDirectory(fpath, config, FullLevel); - fpath += "/"; + fpath = + cmStrCat(this->BuildBundleDirectory(fpath, config, FullLevel), '/'); } // Add the full name of the target. @@ -3729,8 +3766,8 @@ std::string cmGeneratorTarget::NormalGetRealName( // TODO: Split cmTarget into a class hierarchy to get compile-time // enforcement of the limited imported target API. if (this->IsImported()) { - std::string msg = "NormalGetRealName called on imported target: "; - msg += this->GetName(); + std::string msg = cmStrCat("NormalGetRealName called on imported target: ", + this->GetName()); this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); } @@ -3751,8 +3788,8 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames( // TODO: Split cmTarget into a class hierarchy to get compile-time // enforcement of the limited imported target API. if (this->IsImported()) { - std::string msg = "GetLibraryNames called on imported target: "; - msg += this->GetName(); + std::string msg = + cmStrCat("GetLibraryNames called on imported target: ", this->GetName()); this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); } @@ -3828,8 +3865,8 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames( // TODO: Split cmTarget into a class hierarchy to get compile-time // enforcement of the limited imported target API. if (this->IsImported()) { - std::string msg = "GetExecutableNames called on imported target: "; - msg += this->GetName(); + std::string msg = cmStrCat( + "GetExecutableNames called on imported target: ", this->GetName()); this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); } @@ -3924,8 +3961,7 @@ void cmGeneratorTarget::GetFullNameInternal( // Return an empty name for the import library if this platform // does not support import libraries. - if (isImportedLibraryArtifact && - !this->Makefile->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) { + if (isImportedLibraryArtifact && !this->NeedImportLibraryName(config)) { outPrefix.clear(); outBase.clear(); outSuffix.clear(); @@ -3934,8 +3970,8 @@ void cmGeneratorTarget::GetFullNameInternal( // retrieve prefix and suffix std::string ll = this->GetLinkerLanguage(config); - const char* targetPrefix = this->GetFilePrefixInternal(artifact, ll); - const char* targetSuffix = this->GetFileSuffixInternal(artifact, ll); + const char* targetPrefix = this->GetFilePrefixInternal(config, artifact, ll); + const char* targetSuffix = this->GetFileSuffixInternal(config, artifact, ll); // The implib option is only allowed for shared libraries, module // libraries, and executables. @@ -3951,15 +3987,14 @@ void cmGeneratorTarget::GetFullNameInternal( // frameworks have directory prefix but no suffix std::string fw_prefix; if (this->IsFrameworkOnApple()) { - fw_prefix = this->GetFrameworkDirectory(config, ContentLevel); - fw_prefix += "/"; + fw_prefix = + cmStrCat(this->GetFrameworkDirectory(config, ContentLevel), '/'); targetPrefix = fw_prefix.c_str(); targetSuffix = nullptr; } if (this->IsCFBundleOnApple()) { - fw_prefix = this->GetCFBundleDirectory(config, FullLevel); - fw_prefix += "/"; + fw_prefix = cmStrCat(this->GetCFBundleDirectory(config, FullLevel), '/'); targetPrefix = fw_prefix.c_str(); targetSuffix = nullptr; } @@ -4121,7 +4156,7 @@ cmGeneratorTarget::GetTargetSourceFileFlags(const cmSourceFile* sf) const if (stripResources) { flags.MacFolder = ""; } - } else if (cmSystemTools::StringStartsWith(location, "Resources/")) { + } else if (cmHasLiteralPrefix(location, "Resources/")) { flags.Type = cmGeneratorTarget::SourceFileTypeDeepResource; if (stripResources) { flags.MacFolder += strlen("Resources/"); @@ -4143,8 +4178,7 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const // Process public headers to mark the source files. if (const char* files = this->GetProperty("PUBLIC_HEADER")) { - std::vector<std::string> relFiles; - cmSystemTools::ExpandListArgument(files, relFiles); + std::vector<std::string> relFiles = cmExpandedList(files); for (std::string const& relFile : relFiles) { if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) { SourceFileFlags& flags = this->SourceFlagsMap[sf]; @@ -4157,8 +4191,7 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const // Process private headers after public headers so that they take // precedence if a file is listed in both. if (const char* files = this->GetProperty("PRIVATE_HEADER")) { - std::vector<std::string> relFiles; - cmSystemTools::ExpandListArgument(files, relFiles); + std::vector<std::string> relFiles = cmExpandedList(files); for (std::string const& relFile : relFiles) { if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) { SourceFileFlags& flags = this->SourceFlagsMap[sf]; @@ -4170,8 +4203,7 @@ void cmGeneratorTarget::ConstructSourceFileFlags() const // Mark sources listed as resources. if (const char* files = this->GetProperty("RESOURCE")) { - std::vector<std::string> relFiles; - cmSystemTools::ExpandListArgument(files, relFiles); + std::vector<std::string> relFiles = cmExpandedList(files); for (std::string const& relFile : relFiles) { if (cmSourceFile* sf = this->Makefile->GetSource(relFile)) { SourceFileFlags& flags = this->SourceFlagsMap[sf]; @@ -4200,7 +4232,7 @@ cmGeneratorTarget::GetCompatibleInterfaces(std::string const& config) const #define CM_READ_COMPATIBLE_INTERFACE(X, x) \ if (const char* prop = li->GetProperty("COMPATIBLE_INTERFACE_" #X)) { \ std::vector<std::string> props; \ - cmSystemTools::ExpandListArgument(prop, props); \ + cmExpandList(prop, props); \ compat.Props##x.insert(props.begin(), props.end()); \ } CM_READ_COMPATIBLE_INTERFACE(BOOL, Bool) @@ -4313,10 +4345,9 @@ void checkPropertyConsistency(cmGeneratorTarget const* depender, return; } - std::vector<std::string> props; - cmSystemTools::ExpandListArgument(prop, props); - std::string pdir = cmSystemTools::GetCMakeRoot(); - pdir += "/Help/prop_tgt/"; + std::vector<std::string> props = cmExpandedList(prop); + std::string pdir = + cmStrCat(cmSystemTools::GetCMakeRoot(), "/Help/prop_tgt/"); for (std::string const& p : props) { std::string pname = cmSystemTools::HelpFileName(p); @@ -4343,8 +4374,9 @@ void checkPropertyConsistency(cmGeneratorTarget const* depender, } } -static std::string intersect(const std::set<std::string>& s1, - const std::set<std::string>& s2) +namespace { +std::string intersect(const std::set<std::string>& s1, + const std::set<std::string>& s2) { std::set<std::string> intersect; std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), @@ -4355,9 +4387,9 @@ static std::string intersect(const std::set<std::string>& s1, return ""; } -static std::string intersect(const std::set<std::string>& s1, - const std::set<std::string>& s2, - const std::set<std::string>& s3) +std::string intersect(const std::set<std::string>& s1, + const std::set<std::string>& s2, + const std::set<std::string>& s3) { std::string result; result = intersect(s1, s2); @@ -4371,10 +4403,10 @@ static std::string intersect(const std::set<std::string>& s1, return intersect(s2, s3); } -static std::string intersect(const std::set<std::string>& s1, - const std::set<std::string>& s2, - const std::set<std::string>& s3, - const std::set<std::string>& s4) +std::string intersect(const std::set<std::string>& s1, + const std::set<std::string>& s2, + const std::set<std::string>& s3, + const std::set<std::string>& s4) { std::string result; result = intersect(s1, s2); @@ -4391,6 +4423,7 @@ static std::string intersect(const std::set<std::string>& s1, } return intersect(s2, s3, s4); } +} void cmGeneratorTarget::CheckPropertyCompatibility( cmComputeLinkInformation* info, const std::string& config) const @@ -4460,8 +4493,8 @@ void cmGeneratorTarget::CheckPropertyCompatibility( } std::sort(props.begin(), props.end()); - std::string propsString = cmJoin(cmMakeRange(props).retreat(1), ", "); - propsString += " and the " + props.back(); + std::string propsString = cmStrCat( + cmJoin(cmMakeRange(props).retreat(1), ", "), " and the ", props.back()); std::ostringstream e; e << "Property \"" << prop << "\" appears in both the " << propsString @@ -4542,7 +4575,7 @@ bool getTypedProperty<bool>(cmGeneratorTarget const* tgt, } const char* value = tgt->GetProperty(prop); - return cmSystemTools::IsOn(genexInterpreter->Evaluate(value, prop)); + return cmIsOn(genexInterpreter->Evaluate(value, prop)); } template <> @@ -4660,7 +4693,7 @@ std::pair<bool, const char*> consistentProperty(const char* lhs, switch (t) { case BoolType: { - bool same = cmSystemTools::IsOn(lhs) == cmSystemTools::IsOn(rhs); + bool same = cmIsOn(lhs) == cmIsOn(rhs); return std::make_pair(same, same ? lhs : nullptr); } case StringType: @@ -4691,7 +4724,7 @@ std::pair<bool, std::string> consistentProperty(const std::string& lhs, switch (t) { case BoolType: { - bool same = cmSystemTools::IsOn(lhs) == cmSystemTools::IsOn(rhs); + bool same = cmIsOn(lhs) == cmIsOn(rhs); return std::make_pair(same, same ? lhs : null_ptr); } case StringType: @@ -4718,9 +4751,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, PropertyType propContent = getTypedProperty<PropertyType>(tgt, p); std::vector<std::string> headPropKeys = tgt->GetPropertyKeys(); - const bool explicitlySet = - std::find(headPropKeys.begin(), headPropKeys.end(), p) != - headPropKeys.end(); + const bool explicitlySet = cmContains(headPropKeys, p); const bool impliedByUse = tgt->IsNullImpliedByLinkLibraries(p); assert((impliedByUse ^ explicitlySet) || (!impliedByUse && !explicitlySet)); @@ -4733,8 +4764,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, } bool propInitialized = explicitlySet; - std::string report = " * Target \""; - report += tgt->GetName(); + std::string report = cmStrCat(" * Target \"", tgt->GetName()); if (explicitlySet) { report += "\" has property content \""; report += valueAsString<PropertyType>(propContent); @@ -4760,8 +4790,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt, std::vector<std::string> propKeys = theTarget->GetPropertyKeys(); - const bool ifaceIsSet = std::find(propKeys.begin(), propKeys.end(), - interfaceProperty) != propKeys.end(); + const bool ifaceIsSet = cmContains(propKeys, interfaceProperty); PropertyType ifacePropContent = getTypedProperty<PropertyType>( theTarget, interfaceProperty, genexInterpreter.get()); @@ -4991,9 +5020,8 @@ std::string cmGeneratorTarget::CreateFortranModuleDirectory( mod_dir = target_mod_dir; } else { // Interpret relative to the current output directory. - mod_dir = this->LocalGenerator->GetCurrentBinaryDirectory(); - mod_dir += "/"; - mod_dir += target_mod_dir; + mod_dir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), + '/', target_mod_dir); } // Make sure the module output directory exists. @@ -5032,13 +5060,7 @@ void cmGeneratorTarget::ComputeVersionedName(std::string& vName, std::vector<std::string> cmGeneratorTarget::GetPropertyKeys() const { - cmPropertyMap const& propsObject = this->Target->GetProperties(); - std::vector<std::string> props; - props.reserve(propsObject.size()); - for (auto const& it : propsObject) { - props.push_back(it.first); - } - return props; + return this->Target->GetProperties().GetKeys(); } void cmGeneratorTarget::ReportPropertyOrigin( @@ -5049,12 +5071,11 @@ void cmGeneratorTarget::ReportPropertyOrigin( const char* debugProp = this->Target->GetMakefile()->GetDefinition( "CMAKE_DEBUG_TARGET_PROPERTIES"); if (debugProp) { - cmSystemTools::ExpandListArgument(debugProp, debugProperties); + cmExpandList(debugProp, debugProperties); } - bool debugOrigin = !this->DebugCompatiblePropertiesDone[p] && - std::find(debugProperties.begin(), debugProperties.end(), p) != - debugProperties.end(); + bool debugOrigin = + !this->DebugCompatiblePropertiesDone[p] && cmContains(debugProperties, p); if (this->GlobalGenerator->GetConfigureDoneCMP0026()) { this->DebugCompatiblePropertiesDone[p] = true; @@ -5063,12 +5084,9 @@ void cmGeneratorTarget::ReportPropertyOrigin( return; } - std::string areport = compatibilityType; - areport += std::string(" of property \"") + p + "\" for target \""; - areport += std::string(this->GetName()); - areport += "\" (result: \""; - areport += result; - areport += "\"):\n" + report; + std::string areport = + cmStrCat(compatibilityType, " of property \"", p, "\" for target \"", + this->GetName(), "\" (result: \"", result, "\"):\n", report); this->LocalGenerator->GetCMakeInstance()->IssueMessage(MessageType::LOG, areport); @@ -5101,10 +5119,9 @@ void cmGeneratorTarget::ExpandLinkItems( } std::vector<std::string> libs; std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value); - cmSystemTools::ExpandListArgument(cge->Evaluate(this->LocalGenerator, config, - false, headTarget, this, - &dagChecker), - libs); + cmExpandList(cge->Evaluate(this->LocalGenerator, config, false, headTarget, + this, &dagChecker), + libs); this->LookupLinkItems(libs, cge->GetBacktrace(), items); hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); } @@ -5152,7 +5169,7 @@ void cmGeneratorTarget::ComputeLinkInterface( const std::string& config, cmOptionalLinkInterface& iface, cmGeneratorTarget const* headTarget) const { - if (iface.ExplicitLibraries) { + if (iface.Explicit) { if (this->GetType() == cmStateEnums::SHARED_LIBRARY || this->GetType() == cmStateEnums::STATIC_LIBRARY || this->GetType() == cmStateEnums::INTERFACE_LIBRARY) { @@ -5209,8 +5226,7 @@ void cmGeneratorTarget::ComputeLinkInterface( // How many repetitions are needed if this library has cyclic // dependencies? - std::string propName = "LINK_INTERFACE_MULTIPLICITY"; - propName += suffix; + std::string propName = cmStrCat("LINK_INTERFACE_MULTIPLICITY", suffix); if (const char* config_reps = this->GetProperty(propName)) { sscanf(config_reps, "%u", &iface.Multiplicity); } else if (const char* reps = @@ -5296,10 +5312,9 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo( // Only libraries and executables have well-defined output files. if (!this->HaveWellDefinedOutputFiles()) { - std::string msg = "cmGeneratorTarget::GetOutputInfo called for "; - msg += this->GetName(); - msg += " which has type "; - msg += cmState::GetTargetTypeName(this->GetType()); + std::string msg = cmStrCat("cmGeneratorTarget::GetOutputInfo called for ", + this->GetName(), " which has type ", + cmState::GetTargetTypeName(this->GetType())); this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg); return nullptr; } @@ -5485,13 +5500,41 @@ bool cmGeneratorTarget::ComputePDBOutputDir(const std::string& kind, return true; } -bool cmGeneratorTarget::HaveInstallTreeRPATH() const +bool cmGeneratorTarget::HaveInstallTreeRPATH(const std::string& config) const { - const char* install_rpath = this->GetProperty("INSTALL_RPATH"); - return (install_rpath && *install_rpath) && + std::string install_rpath; + this->GetInstallRPATH(config, install_rpath); + return !install_rpath.empty() && !this->Makefile->IsOn("CMAKE_SKIP_INSTALL_RPATH"); } +bool cmGeneratorTarget::GetBuildRPATH(const std::string& config, + std::string& rpath) const +{ + return this->GetRPATH(config, "BUILD_RPATH", rpath); +} + +bool cmGeneratorTarget::GetInstallRPATH(const std::string& config, + std::string& rpath) const +{ + return this->GetRPATH(config, "INSTALL_RPATH", rpath); +} + +bool cmGeneratorTarget::GetRPATH(const std::string& config, + const std::string& prop, + std::string& rpath) const +{ + const char* value = this->GetProperty(prop); + if (!value) { + return false; + } + + cmGeneratorExpression ge; + rpath = ge.Parse(value)->Evaluate(this->LocalGenerator, config); + + return true; +} + void cmGeneratorTarget::ComputeLinkInterfaceLibraries( const std::string& config, cmOptionalLinkInterface& iface, cmGeneratorTarget const* headTarget, bool usage_requirements_only) const @@ -5508,8 +5551,9 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( // libraries and executables that export symbols. const char* explicitLibraries = nullptr; std::string linkIfaceProp; - if (this->GetPolicyStatusCMP0022() != cmPolicies::OLD && - this->GetPolicyStatusCMP0022() != cmPolicies::WARN) { + bool const cmp0022NEW = (this->GetPolicyStatusCMP0022() != cmPolicies::OLD && + this->GetPolicyStatusCMP0022() != cmPolicies::WARN); + if (cmp0022NEW) { // CMP0022 NEW behavior is to use INTERFACE_LINK_LIBRARIES. linkIfaceProp = "INTERFACE_LINK_LIBRARIES"; explicitLibraries = this->GetProperty(linkIfaceProp); @@ -5519,8 +5563,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( // shared lib or executable. // Lookup the per-configuration property. - linkIfaceProp = "LINK_INTERFACE_LIBRARIES"; - linkIfaceProp += suffix; + linkIfaceProp = cmStrCat("LINK_INTERFACE_LIBRARIES", suffix); explicitLibraries = this->GetProperty(linkIfaceProp); // If not set, try the generic property. @@ -5564,15 +5607,14 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( return; } iface.Exists = true; - iface.ExplicitLibraries = explicitLibraries; + iface.Explicit = cmp0022NEW || explicitLibraries != nullptr; if (explicitLibraries) { // The interface libraries have been explicitly set. this->ExpandLinkItems(linkIfaceProp, explicitLibraries, config, headTarget, usage_requirements_only, iface.Libraries, iface.HadHeadSensitiveCondition); - } else if (this->GetPolicyStatusCMP0022() == cmPolicies::WARN || - this->GetPolicyStatusCMP0022() == cmPolicies::OLD) + } else if (!cmp0022NEW) // If CMP0022 is NEW then the plain tll signature sets the // INTERFACE_LINK_LIBRARIES, so if we get here then the project // cleared the property explicitly and we should not fall back @@ -5653,12 +5695,11 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( if (!iface.AllDone) { iface.AllDone = true; iface.Multiplicity = info->Multiplicity; - cmSystemTools::ExpandListArgument(info->Languages, iface.Languages); + cmExpandList(info->Languages, iface.Languages); this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config, headTarget, usage_requirements_only, iface.Libraries, iface.HadHeadSensitiveCondition); - std::vector<std::string> deps; - cmSystemTools::ExpandListArgument(info->SharedDeps, deps); + std::vector<std::string> deps = cmExpandedList(info->SharedDeps); this->LookupLinkItems(deps, cmListFileBacktrace(), iface.SharedDeps); } @@ -5727,8 +5768,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) { if (!propertyLibs) { - linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES"; - linkProp += suffix; + linkProp = cmStrCat("IMPORTED_LINK_INTERFACE_LIBRARIES", suffix); propertyLibs = this->GetProperty(linkProp); } @@ -5756,8 +5796,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, if (loc) { info.Location = loc; } else { - std::string impProp = "IMPORTED_LOCATION"; - impProp += suffix; + std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix); if (const char* config_location = this->GetProperty(impProp)) { info.Location = config_location; } else if (const char* location = this->GetProperty("IMPORTED_LOCATION")) { @@ -5767,8 +5806,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get the soname. if (this->GetType() == cmStateEnums::SHARED_LIBRARY) { - std::string soProp = "IMPORTED_SONAME"; - soProp += suffix; + std::string soProp = cmStrCat("IMPORTED_SONAME", suffix); if (const char* config_soname = this->GetProperty(soProp)) { info.SOName = config_soname; } else if (const char* soname = this->GetProperty("IMPORTED_SONAME")) { @@ -5778,13 +5816,12 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get the "no-soname" mark. if (this->GetType() == cmStateEnums::SHARED_LIBRARY) { - std::string soProp = "IMPORTED_NO_SONAME"; - soProp += suffix; + std::string soProp = cmStrCat("IMPORTED_NO_SONAME", suffix); if (const char* config_no_soname = this->GetProperty(soProp)) { - info.NoSOName = cmSystemTools::IsOn(config_no_soname); + info.NoSOName = cmIsOn(config_no_soname); } else if (const char* no_soname = this->GetProperty("IMPORTED_NO_SONAME")) { - info.NoSOName = cmSystemTools::IsOn(no_soname); + info.NoSOName = cmIsOn(no_soname); } } @@ -5793,8 +5830,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, info.ImportLibrary = imp; } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY || this->IsExecutableWithExports()) { - std::string impProp = "IMPORTED_IMPLIB"; - impProp += suffix; + std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix); if (const char* config_implib = this->GetProperty(impProp)) { info.ImportLibrary = config_implib; } else if (const char* implib = this->GetProperty("IMPORTED_IMPLIB")) { @@ -5804,8 +5840,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get the link dependencies. { - std::string linkProp = "IMPORTED_LINK_DEPENDENT_LIBRARIES"; - linkProp += suffix; + std::string linkProp = + cmStrCat("IMPORTED_LINK_DEPENDENT_LIBRARIES", suffix); if (const char* config_libs = this->GetProperty(linkProp)) { info.SharedDeps = config_libs; } else if (const char* libs = @@ -5816,8 +5852,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get the link languages. if (this->LinkLanguagePropagatesToDependents()) { - std::string linkProp = "IMPORTED_LINK_INTERFACE_LANGUAGES"; - linkProp += suffix; + std::string linkProp = + cmStrCat("IMPORTED_LINK_INTERFACE_LANGUAGES", suffix); if (const char* config_libs = this->GetProperty(linkProp)) { info.Languages = config_libs; } else if (const char* libs = @@ -5838,8 +5874,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config, // Get the cyclic repetition count. if (this->GetType() == cmStateEnums::STATIC_LIBRARY) { - std::string linkProp = "IMPORTED_LINK_INTERFACE_MULTIPLICITY"; - linkProp += suffix; + std::string linkProp = + cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix); if (const char* config_reps = this->GetProperty(linkProp)) { sscanf(config_reps, "%u", &info.Multiplicity); } else if (const char* reps = @@ -5946,8 +5982,7 @@ void cmGeneratorTarget::GetObjectLibrariesCMP0026( // behavior of CMP0024 and CMP0026 only. cmStringRange rng = this->Target->GetSourceEntries(); for (std::string const& entry : rng) { - std::vector<std::string> files; - cmSystemTools::ExpandListArgument(entry, files); + std::vector<std::string> files = cmExpandedList(entry); for (std::string const& li : files) { if (cmHasLiteralPrefix(li, "$<TARGET_OBJECTS:") && li.back() == '>') { std::string objLibName = li.substr(17, li.size() - 18); @@ -6091,7 +6126,8 @@ bool cmGeneratorTarget::HaveBuildTreeRPATH(const std::string& config) const if (this->GetPropertyAsBool("SKIP_BUILD_RPATH")) { return false; } - if (this->GetProperty("BUILD_RPATH")) { + std::string build_rpath; + if (this->GetBuildRPATH(config, build_rpath)) { return true; } if (cmLinkImplementationLibraries const* impl = @@ -6138,8 +6174,7 @@ cmGeneratorTarget::GetLinkImplementationLibrariesInternal( bool cmGeneratorTarget::IsNullImpliedByLinkLibraries( const std::string& p) const { - return this->LinkImplicitNullProperties.find(p) != - this->LinkImplicitNullProperties.end(); + return cmContains(this->LinkImplicitNullProperties, p); } void cmGeneratorTarget::ComputeLinkImplementationLibraries( @@ -6160,7 +6195,7 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( std::unique_ptr<cmCompiledGeneratorExpression> const cge = ge.Parse(*le); std::string const& evaluated = cge->Evaluate(this->LocalGenerator, config, false, head, &dagChecker); - cmSystemTools::ExpandListArgument(evaluated, llibs); + cmExpandList(evaluated, llibs); if (cge->GetHadHeadSensitiveCondition()) { impl.HadHeadSensitiveCondition = true; } @@ -6317,8 +6352,8 @@ bool cmGeneratorTarget::GetImplibGNUtoMS(std::string const& config, { if (this->HasImplibGNUtoMS(config) && gnuName.size() > 6 && gnuName.substr(gnuName.size() - 6) == ".dll.a") { - out = gnuName.substr(0, gnuName.size() - 6); - out += newExt ? newExt : ".lib"; + out = cmStrCat(cm::string_view(gnuName).substr(0, gnuName.size() - 6), + newExt ? newExt : ".lib"); return true; } return false; @@ -6337,15 +6372,24 @@ bool cmGeneratorTarget::HasImportLibrary(std::string const& config) const this->IsExecutableWithExports()) && // Assemblies which have only managed code do not have // import libraries. - this->GetManagedType(config) != ManagedType::Managed); + this->GetManagedType(config) != ManagedType::Managed) || + (this->Target->IsAIX() && this->IsExecutableWithExports()); +} + +bool cmGeneratorTarget::NeedImportLibraryName(std::string const& config) const +{ + return this->HasImportLibrary(config) || + // On DLL platforms we always generate the import library name + // just in case the sources have export markup. + (this->IsDLLPlatform() && + (this->GetType() == cmStateEnums::EXECUTABLE || + this->GetType() == cmStateEnums::MODULE_LIBRARY)); } std::string cmGeneratorTarget::GetSupportDirectory() const { - std::string dir = this->LocalGenerator->GetCurrentBinaryDirectory(); - dir += "/CMakeFiles"; - dir += "/"; - dir += this->GetName(); + std::string dir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), + "/CMakeFiles/", this->GetName()); #if defined(__VMS) dir += "_dir"; #else |