diff options
Diffstat (limited to 'Source')
41 files changed, 395 insertions, 197 deletions
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 1819564..1a5fd15 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 12) -set(CMake_VERSION_PATCH 20180912) +set(CMake_VERSION_PATCH 20180919) #set(CMake_VERSION_RC 1) diff --git a/Source/CTest/cmCTestHandlerCommand.cxx b/Source/CTest/cmCTestHandlerCommand.cxx index 8863dc8..667a8ba 100644 --- a/Source/CTest/cmCTestHandlerCommand.cxx +++ b/Source/CTest/cmCTestHandlerCommand.cxx @@ -151,9 +151,9 @@ bool cmCTestHandlerCommand::InitialPass(std::vector<std::string> const& args, cmSystemTools::CollapseFullPath(this->Values[ct_BUILD]).c_str(), this->Quiet); } else { - const char* bdir = + std::string const& bdir = this->Makefile->GetSafeDefinition("CTEST_BINARY_DIRECTORY"); - if (bdir) { + if (!bdir.empty()) { this->CTest->SetCTestConfiguration( "BuildDirectory", cmSystemTools::CollapseFullPath(bdir).c_str(), this->Quiet); diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 54b4be2..3e0c1ac 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -56,7 +56,6 @@ cmCTestMultiProcessHandler::cmCTestMultiProcessHandler() this->RunningCount = 0; this->ProcessorsAvailable = cmAffinity::GetProcessorsAvailable(); this->HaveAffinity = this->ProcessorsAvailable.size(); - this->StopTimePassed = false; this->HasCycles = false; this->SerialTestRunning = false; } @@ -130,17 +129,6 @@ void cmCTestMultiProcessHandler::RunTests() bool cmCTestMultiProcessHandler::StartTestProcess(int test) { - std::chrono::system_clock::time_point stop_time = this->CTest->GetStopTime(); - if (stop_time != std::chrono::system_clock::time_point() && - stop_time <= std::chrono::system_clock::now()) { - cmCTestLog(this->CTest, ERROR_MESSAGE, - "The stop time has been passed. " - "Stopping all tests." - << std::endl); - this->StopTimePassed = true; - return false; - } - if (this->HaveAffinity && this->Properties[test]->WantAffinity) { size_t needProcessors = this->GetProcessorsUsed(test); if (needProcessors > this->ProcessorsAvailable.size()) { @@ -199,6 +187,30 @@ bool cmCTestMultiProcessHandler::StartTestProcess(int test) return false; } +bool cmCTestMultiProcessHandler::CheckStopTimePassed() +{ + if (!this->StopTimePassed) { + std::chrono::system_clock::time_point stop_time = + this->CTest->GetStopTime(); + if (stop_time != std::chrono::system_clock::time_point() && + stop_time <= std::chrono::system_clock::now()) { + this->SetStopTimePassed(); + } + } + return this->StopTimePassed; +} + +void cmCTestMultiProcessHandler::SetStopTimePassed() +{ + if (!this->StopTimePassed) { + cmCTestLog(this->CTest, ERROR_MESSAGE, + "The stop time has been passed. " + "Stopping all tests." + << std::endl); + this->StopTimePassed = true; + } +} + void cmCTestMultiProcessHandler::LockResources(int index) { this->LockedResources.insert( @@ -279,6 +291,10 @@ void cmCTestMultiProcessHandler::StartNextTests() return; } + if (this->CheckStopTimePassed()) { + return; + } + size_t numToStart = 0; if (this->RunningCount < this->ParallelLevel) { @@ -358,10 +374,6 @@ void cmCTestMultiProcessHandler::StartNextTests() } if (testLoadOk && processors <= numToStart && this->StartTest(test)) { - if (this->StopTimePassed) { - return; - } - numToStart -= processors; } else if (numToStart == 0) { break; @@ -424,8 +436,11 @@ void cmCTestMultiProcessHandler::FinishTestProcess(cmCTestRunTest* runner, auto properties = runner->GetTestProperties(); bool testResult = runner->EndTest(this->Completed, this->Total, started); + if (runner->TimedOutForStopTime()) { + this->SetStopTimePassed(); + } if (started) { - if (runner->StartAgain()) { + if (!this->StopTimePassed && runner->StartAgain()) { this->Completed--; // remove the completed test because run again return; } diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index 07a5fe7..3927a8a 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -113,6 +113,9 @@ protected: inline size_t GetProcessorsUsed(int index); std::string GetName(int index); + bool CheckStopTimePassed(); + void SetStopTimePassed(); + void LockResources(int index); void UnlockResources(int index); // map from test number to set of depend tests @@ -125,7 +128,7 @@ protected: size_t RunningCount; std::set<size_t> ProcessorsAvailable; size_t HaveAffinity; - bool StopTimePassed; + bool StopTimePassed = false; // list of test properties (indices concurrent to the test map) PropertiesMap Properties; std::map<int, bool> TestRunningMap; diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index ef0a49d..23d4616 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -140,6 +140,9 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) bool passed = true; cmProcess::State res = started ? this->TestProcess->GetProcessStatus() : cmProcess::State::Error; + if (res != cmProcess::State::Expired) { + this->TimeoutIsForStopTime = false; + } int retVal = this->TestProcess->GetExitValue(); bool forceFail = false; bool skipped = false; @@ -537,6 +540,7 @@ bool cmCTestRunTest::StartTest(size_t total) auto timeout = this->TestProperties->Timeout; + this->TimeoutIsForStopTime = false; std::chrono::system_clock::time_point stop_time = this->CTest->GetStopTime(); if (stop_time != std::chrono::system_clock::time_point()) { std::chrono::duration<double> stop_timeout = @@ -547,6 +551,7 @@ bool cmCTestRunTest::StartTest(size_t total) } if (timeout == std::chrono::duration<double>::zero() || stop_timeout < timeout) { + this->TimeoutIsForStopTime = true; timeout = stop_timeout; } } diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index 3b1d674..7e80157 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -80,6 +80,8 @@ public: void FinalizeTest(); + bool TimedOutForStopTime() const { return this->TimeoutIsForStopTime; } + private: bool NeedsToRerun(); void DartProcessing(); @@ -92,6 +94,7 @@ private: void MemCheckPostProcess(); cmCTestTestHandler::cmCTestTestProperties* TestProperties; + bool TimeoutIsForStopTime = false; // Pointer back to the "parent"; the handler that invoked this test run cmCTestTestHandler* TestHandler; cmCTest* CTest; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 2107d32..a3e135f 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -1725,7 +1725,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs, } const char* stagePath = this->Makefile->GetDefinition("CMAKE_STAGING_PREFIX"); - const char* installPrefix = + std::string const& installPrefix = this->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); cmSystemTools::ConvertToUnixSlashes(rootPath); std::vector<std::string> const& rdirs = this->GetRuntimeSearchPath(); diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx index 4716e14..6f1afd7 100644 --- a/Source/cmDepends.cxx +++ b/Source/cmDepends.cxx @@ -36,7 +36,7 @@ bool cmDepends::Write(std::ostream& makeDepends, std::ostream& internalDepends) std::string srcLang = "CMAKE_DEPENDS_CHECK_"; srcLang += this->Language; cmMakefile* mf = this->LocalGenerator->GetMakefile(); - const char* srcStr = mf->GetSafeDefinition(srcLang); + std::string const& srcStr = mf->GetSafeDefinition(srcLang); std::vector<std::string> pairs; cmSystemTools::ExpandListArgument(srcStr, pairs); diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx index 3d32b84..d12ad7f 100644 --- a/Source/cmExportBuildAndroidMKGenerator.cxx +++ b/Source/cmExportBuildAndroidMKGenerator.cxx @@ -8,11 +8,8 @@ #include <utility> #include "cmAlgorithms.h" -#include "cmGeneratorExpression.h" -#include "cmGeneratorExpressionDAGChecker.h" #include "cmGeneratorTarget.h" #include "cmLinkItem.h" -#include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmPolicies.h" #include "cmStateTypes.h" @@ -104,27 +101,14 @@ void cmExportBuildAndroidMKGenerator::GenerateInterfaceProperties( os << "LOCAL_CPP_FEATURES += "; os << (property.second) << "\n"; } else if (property.first == "INTERFACE_LINK_LIBRARIES") { - // evaluate any generator expressions with the current - // build type of the makefile - cmGeneratorExpression ge; - cmGeneratorExpressionDAGChecker dagChecker( - target, "INTERFACE_LINK_LIBRARIES", nullptr, nullptr); - std::unique_ptr<cmCompiledGeneratorExpression> cge = - ge.Parse(property.second); - std::string evaluated = cge->Evaluate( - target->GetLocalGenerator(), config, false, target, &dagChecker); - // need to look at list in pi->second and see if static or shared - // FindTargetToLink - // target->GetLocalGenerator()->FindGeneratorTargetToUse() - // then add to LOCAL_CPPFLAGS - std::vector<std::string> libraries; - cmSystemTools::ExpandListArgument(evaluated, libraries); std::string staticLibs; std::string sharedLibs; std::string ldlibs; - for (std::string const& lib : libraries) { - cmGeneratorTarget* gt = - target->GetLocalGenerator()->FindGeneratorTargetToUse(lib); + cmLinkInterfaceLibraries const* linkIFace = + target->GetLinkInterfaceLibraries(config, target, false); + for (cmLinkItem const& item : linkIFace->Libraries) { + cmGeneratorTarget const* gt = item.Target; + std::string const& lib = item.AsStr(); if (gt) { if (gt->GetType() == cmStateEnums::SHARED_LIBRARY || diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 1c5040a..d6573b8 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -195,7 +195,7 @@ static bool checkInterfaceDirs(const std::string& prepro, cmGeneratorTarget* target, const std::string& prop) { - const char* installDir = + std::string const& installDir = target->Makefile->GetSafeDefinition("CMAKE_INSTALL_PREFIX"); std::string const& topSourceDir = target->GetLocalGenerator()->GetSourceDirectory(); @@ -567,14 +567,17 @@ bool cmExportFileGenerator::AddTargetNamespace( std::string& input, cmGeneratorTarget* target, std::vector<std::string>& missingTargets) { - cmLocalGenerator* lg = target->GetLocalGenerator(); + cmGeneratorTarget::TargetOrString resolved = + target->ResolveTargetReference(input); - cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(input); + cmGeneratorTarget* tgt = resolved.Target; if (!tgt) { + input = resolved.String; return false; } if (tgt->IsImported()) { + input = tgt->GetName(); return true; } if (this->ExportedTargets.find(tgt) != this->ExportedTargets.end()) { @@ -584,6 +587,8 @@ bool cmExportFileGenerator::AddTargetNamespace( this->HandleMissingTarget(namespacedTarget, missingTargets, target, tgt); if (!namespacedTarget.empty()) { input = namespacedTarget; + } else { + input = tgt->GetName(); } } return true; diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index fbf6560..07a60de 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -666,7 +666,7 @@ std::string cmExtraCodeBlocksGenerator::GetCBCompilerId(const cmMakefile* mf) pureFortran = true; } - std::string compilerId = mf->GetSafeDefinition(compilerIdVar); + std::string const& compilerId = mf->GetSafeDefinition(compilerIdVar); std::string compiler = "gcc"; // default to gcc if (compilerId == "MSVC") { if (mf->IsDefinitionSet("MSVC10")) { diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx index fe5c7bb..28106d1 100644 --- a/Source/cmExtraCodeLiteGenerator.cxx +++ b/Source/cmExtraCodeLiteGenerator.cxx @@ -599,7 +599,7 @@ std::string cmExtraCodeLiteGenerator::GetCodeLiteCompilerName( compilerIdVar = "CMAKE_C_COMPILER_ID"; } - std::string compilerId = mf->GetSafeDefinition(compilerIdVar); + std::string const& compilerId = mf->GetSafeDefinition(compilerIdVar); std::string compiler = "gnu g++"; // default to g++ // Since we need the compiler for parsing purposes only diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 1e51f09..f901215 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -580,10 +580,11 @@ struct CompilerIdNode : public cmGeneratorExpressionNode cmGeneratorExpressionDAGChecker* /*unused*/, const std::string& lang) const { - const char* compilerId = context->LG->GetMakefile()->GetSafeDefinition( - "CMAKE_" + lang + "_COMPILER_ID"); + std::string const& compilerId = + context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang + + "_COMPILER_ID"); if (parameters.empty()) { - return compilerId ? compilerId : ""; + return compilerId; } static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$"); if (!compilerIdValidator.find(*parameters.begin())) { @@ -591,15 +592,16 @@ struct CompilerIdNode : public cmGeneratorExpressionNode "Expression syntax not recognized."); return std::string(); } - if (!compilerId) { + if (compilerId.empty()) { return parameters.front().empty() ? "1" : "0"; } - if (strcmp(parameters.begin()->c_str(), compilerId) == 0) { + if (strcmp(parameters.begin()->c_str(), compilerId.c_str()) == 0) { return "1"; } - if (cmsysString_strcasecmp(parameters.begin()->c_str(), compilerId) == 0) { + if (cmsysString_strcasecmp(parameters.begin()->c_str(), + compilerId.c_str()) == 0) { switch (context->LG->GetPolicyStatus(cmPolicies::CMP0044)) { case cmPolicies::WARN: { std::ostringstream e; @@ -676,11 +678,11 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode cmGeneratorExpressionDAGChecker* /*unused*/, const std::string& lang) const { - const char* compilerVersion = + std::string const& compilerVersion = context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_VERSION"); if (parameters.empty()) { - return compilerVersion ? compilerVersion : ""; + return compilerVersion; } static cmsys::RegularExpression compilerIdValidator("^[0-9\\.]*$"); @@ -689,13 +691,13 @@ struct CompilerVersionNode : public cmGeneratorExpressionNode "Expression syntax not recognized."); return std::string(); } - if (!compilerVersion) { + if (compilerVersion.empty()) { return parameters.front().empty() ? "1" : "0"; } return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL, parameters.begin()->c_str(), - compilerVersion) + compilerVersion.c_str()) ? "1" : "0"; } @@ -757,17 +759,17 @@ struct PlatformIdNode : public cmGeneratorExpressionNode const GeneratorExpressionContent* /*content*/, cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override { - const char* platformId = + std::string const& platformId = context->LG->GetMakefile()->GetSafeDefinition("CMAKE_SYSTEM_NAME"); if (parameters.empty()) { - return platformId ? platformId : ""; + return platformId; } - if (!platformId) { + if (platformId.empty()) { return parameters.front().empty() ? "1" : "0"; } - if (strcmp(parameters.begin()->c_str(), platformId) == 0) { + if (*parameters.begin() == platformId) { return "1"; } return "0"; @@ -1054,7 +1056,9 @@ std::string getLinkedTargetsContent( // Don't follow such link interface entries so as not to create a // self-referencing loop. if (l.Target && l.Target != target) { - depString += sep + "$<TARGET_PROPERTY:" + l.Target->GetName() + "," + + std::string uniqueName = + target->GetGlobalGenerator()->IndexGeneratorTargetUniquely(l.Target); + depString += sep + "$<TARGET_PROPERTY:" + std::move(uniqueName) + "," + interfacePropertyName + ">"; sep = ";"; } diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index e8e7b90..a58d3cb 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -138,8 +138,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) this->SourceEntries, true); this->DLLPlatform = - strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"), - "") != 0; + !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty(); this->PolicyMap = t->PolicyMap; } @@ -819,8 +818,11 @@ static void AddInterfaceEntries( thisTarget->GetLinkImplementationLibraries(config)) { for (cmLinkImplItem const& lib : impl->Libraries) { if (lib.Target) { + std::string uniqueName = + thisTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely( + lib.Target); std::string genex = - "$<TARGET_PROPERTY:" + lib.AsStr() + "," + prop + ">"; + "$<TARGET_PROPERTY:" + std::move(uniqueName) + "," + prop + ">"; cmGeneratorExpression ge(lib.Backtrace); std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(genex); cge->SetEvaluateForBuildsystem(true); @@ -840,7 +842,10 @@ static void AddObjectEntries( for (cmLinkImplItem const& lib : impl->Libraries) { if (lib.Target && lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) { - std::string genex = "$<TARGET_OBJECTS:" + lib.AsStr() + ">"; + std::string uniqueName = + thisTarget->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); @@ -3490,11 +3495,11 @@ void cmGeneratorTarget::GetFullNameInternal( // if there is no prefix on the target use the cmake definition if (!targetPrefix && prefixVar) { - targetPrefix = this->Makefile->GetSafeDefinition(prefixVar); + targetPrefix = this->Makefile->GetSafeDefinition(prefixVar).c_str(); } // if there is no suffix on the target use the cmake definition if (!targetSuffix && suffixVar) { - targetSuffix = this->Makefile->GetSafeDefinition(suffixVar); + targetSuffix = this->Makefile->GetSafeDefinition(suffixVar).c_str(); } // frameworks have directory prefix but no suffix @@ -5639,24 +5644,65 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( } } +cmGeneratorTarget::TargetOrString cmGeneratorTarget::ResolveTargetReference( + std::string const& name) const +{ + cmLocalGenerator const* lg = this->LocalGenerator; + std::string const* lookupName = &name; + + // When target_link_libraries() is called with a LHS target that is + // not created in the calling directory it adds a directory id suffix + // that we can use to look up the calling directory. It is that scope + // in which the item name is meaningful. This case is relatively rare + // so we allocate a separate string only when the directory id is present. + std::string::size_type pos = name.find(CMAKE_DIRECTORY_ID_SEP); + std::string plainName; + if (pos != std::string::npos) { + // We will look up the plain name without the directory id suffix. + plainName = name.substr(0, pos); + + // We will look up in the scope of the directory id. + // If we do not recognize the id then leave the original + // syntax in place to produce an indicative error later. + cmDirectoryId const dirId = + name.substr(pos + sizeof(CMAKE_DIRECTORY_ID_SEP) - 1); + if (cmLocalGenerator const* otherLG = + this->GlobalGenerator->FindLocalGenerator(dirId)) { + lg = otherLG; + lookupName = &plainName; + } + } + + TargetOrString resolved; + + if (cmGeneratorTarget* tgt = lg->FindGeneratorTargetToUse(*lookupName)) { + resolved.Target = tgt; + } else if (lookupName == &plainName) { + resolved.String = std::move(plainName); + } else { + resolved.String = name; + } + + return resolved; +} + cmLinkItem cmGeneratorTarget::ResolveLinkItem(std::string const& name) const { - cmGeneratorTarget* tgt = - this->LocalGenerator->FindGeneratorTargetToUse(name); + TargetOrString resolved = this->ResolveTargetReference(name); + + if (!resolved.Target) { + return cmLinkItem(resolved.String); + } // Skip targets that will not really be linked. This is probably a // name conflict between an external library and an executable // within the project. - if (tgt && tgt->GetType() == cmStateEnums::EXECUTABLE && - !tgt->IsExecutableWithExports()) { - tgt = nullptr; - } - - if (tgt) { - return cmLinkItem(tgt); + if (resolved.Target->GetType() == cmStateEnums::EXECUTABLE && + !resolved.Target->IsExecutableWithExports()) { + return cmLinkItem(resolved.Target->GetName()); } - return cmLinkItem(name); + return cmLinkItem(resolved.Target); } std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index a847e21..9d8c9f5 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -357,6 +357,13 @@ public: cmOptionalLinkImplementation& impl, const cmGeneratorTarget* head) const; + struct TargetOrString + { + std::string String; + cmGeneratorTarget* Target = nullptr; + }; + TargetOrString ResolveTargetReference(std::string const& name) const; + cmLinkItem ResolveLinkItem(std::string const& name) const; // Compute the set of languages compiled by the target. This is diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx index bf464d9..0d4d653 100644 --- a/Source/cmGetDirectoryPropertyCommand.cxx +++ b/Source/cmGetDirectoryPropertyCommand.cxx @@ -65,7 +65,7 @@ bool cmGetDirectoryPropertyCommand::InitialPass( "providing the name of the variable to get."); return false; } - std::string output = dir->GetSafeDefinition(*i); + std::string const& output = dir->GetSafeDefinition(*i); this->Makefile->AddDefinition(variable, output.c_str()); return true; } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 99135c8..23df7f1 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -828,10 +828,8 @@ void cmGlobalGenerator::EnableLanguage( std::string sharedLibFlagsVar = "CMAKE_SHARED_LIBRARY_"; sharedLibFlagsVar += lang; sharedLibFlagsVar += "_FLAGS"; - const char* sharedLibFlags = mf->GetSafeDefinition(sharedLibFlagsVar); - if (sharedLibFlags) { - this->LanguageToOriginalSharedLibFlags[lang] = sharedLibFlags; - } + this->LanguageToOriginalSharedLibFlags[lang] = + mf->GetSafeDefinition(sharedLibFlagsVar); // Translate compiler ids for compatibility. this->CheckCompilerIdCompatibility(mf, lang); @@ -1092,7 +1090,7 @@ void cmGlobalGenerator::FillExtensionToLanguageMap(const std::string& l, { std::string extensionsVar = std::string("CMAKE_") + std::string(l) + std::string("_SOURCE_FILE_EXTENSIONS"); - std::string exts = mf->GetSafeDefinition(extensionsVar); + const std::string& exts = mf->GetSafeDefinition(extensionsVar); std::vector<std::string> extensionList; cmSystemTools::ExpandListArgument(exts, extensionList); for (std::string const& i : extensionList) { @@ -1112,7 +1110,7 @@ bool cmGlobalGenerator::GlobalSettingIsOn(std::string const& name) const return this->Makefiles[0]->IsOn(name); } -const char* cmGlobalGenerator::GetSafeGlobalSetting( +std::string cmGlobalGenerator::GetSafeGlobalSetting( std::string const& name) const { assert(!this->Makefiles.empty()); @@ -1139,11 +1137,14 @@ void cmGlobalGenerator::ClearEnabledLanguages() void cmGlobalGenerator::CreateLocalGenerators() { + this->LocalGeneratorSearchIndex.clear(); cmDeleteAll(this->LocalGenerators); this->LocalGenerators.clear(); this->LocalGenerators.reserve(this->Makefiles.size()); for (cmMakefile* m : this->Makefiles) { - this->LocalGenerators.push_back(this->CreateLocalGenerator(m)); + cmLocalGenerator* lg = this->CreateLocalGenerator(m); + this->LocalGenerators.push_back(lg); + this->IndexLocalGenerator(lg); } } @@ -1593,7 +1594,7 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo() for (std::string const& li : langs) { std::string const standardIncludesVar = "CMAKE_" + li + "_STANDARD_INCLUDE_DIRECTORIES"; - std::string const standardIncludesStr = + std::string const& standardIncludesStr = mf->GetSafeDefinition(standardIncludesVar); std::vector<std::string> standardIncludesVec; cmSystemTools::ExpandListArgument(standardIncludesStr, @@ -1661,6 +1662,7 @@ void cmGlobalGenerator::ClearGeneratorMembers() this->TargetSearchIndex.clear(); this->GeneratorTargetSearchIndex.clear(); this->MakefileSearchIndex.clear(); + this->LocalGeneratorSearchIndex.clear(); this->ProjectMap.clear(); this->RuleHashes.clear(); this->DirectoryContentMap.clear(); @@ -2130,15 +2132,13 @@ cmMakefile* cmGlobalGenerator::FindMakefile(const std::string& start_dir) const return nullptr; } -///! Find a local generator by its startdirectory cmLocalGenerator* cmGlobalGenerator::FindLocalGenerator( - const std::string& start_dir) const + cmDirectoryId const& id) const { - for (cmLocalGenerator* lg : this->LocalGenerators) { - std::string sd = lg->GetCurrentSourceDirectory(); - if (sd == start_dir) { - return lg; - } + LocalGeneratorMap::const_iterator i = + this->LocalGeneratorSearchIndex.find(id.String); + if (i != this->LocalGeneratorSearchIndex.end()) { + return i->second; } return nullptr; } @@ -2168,6 +2168,24 @@ void cmGlobalGenerator::IndexGeneratorTarget(cmGeneratorTarget* gt) } } +std::string cmGlobalGenerator::IndexGeneratorTargetUniquely( + cmGeneratorTarget const* gt) +{ + // Use the pointer value to uniquely identify the target instance. + // Use a "T" prefix to indicate that this identifier is for a target. + // We must satisfy cmGeneratorExpression::IsValidTargetName so use no + // other special characters. + char buf[64]; + sprintf(buf, "::T%p", + static_cast<void const*>(gt)); // cast avoids format warning + std::string id = gt->GetName() + buf; + // We internally index pointers to non-const generator targets + // but our callers only have pointers to const generator targets. + // They will give up non-const privileges when looking up anyway. + this->GeneratorTargetSearchIndex[id] = const_cast<cmGeneratorTarget*>(gt); + return id; +} + void cmGlobalGenerator::IndexMakefile(cmMakefile* mf) { // FIXME: add_subdirectory supports multiple build directories @@ -2179,6 +2197,12 @@ void cmGlobalGenerator::IndexMakefile(cmMakefile* mf) MakefileMap::value_type(mf->GetCurrentSourceDirectory(), mf)); } +void cmGlobalGenerator::IndexLocalGenerator(cmLocalGenerator* lg) +{ + cmDirectoryId id = lg->GetMakefile()->GetDirectoryId(); + this->LocalGeneratorSearchIndex[id.String] = lg; +} + cmTarget* cmGlobalGenerator::FindTargetImpl(std::string const& name) const { TargetMap::const_iterator i = this->TargetSearchIndex.find(name); diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index c06ac52..1ea2d24 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -26,6 +26,9 @@ # include "cmFileLockPool.h" #endif +#define CMAKE_DIRECTORY_ID_SEP "::@" + +class cmDirectoryId; class cmExportBuildFileGenerator; class cmExternalMakefileProjectGenerator; class cmGeneratorTarget; @@ -230,7 +233,7 @@ public: const char* GetGlobalSetting(std::string const& name) const; bool GlobalSettingIsOn(std::string const& name) const; - const char* GetSafeGlobalSetting(std::string const& name) const; + std::string GetSafeGlobalSetting(std::string const& name) const; /** Add a file to the manifest of generated targets for a configuration. */ void AddToManifest(std::string const& f); @@ -284,8 +287,7 @@ public: bool NameResolvesToFramework(const std::string& libname) const; cmMakefile* FindMakefile(const std::string& start_dir) const; - ///! Find a local generator by its startdirectory - cmLocalGenerator* FindLocalGenerator(const std::string& start_dir) const; + cmLocalGenerator* FindLocalGenerator(cmDirectoryId const& id) const; /** Append the subdirectory for the given configuration. If anything is appended the given prefix and suffix will be appended around it, which @@ -305,6 +307,10 @@ public: void IndexTarget(cmTarget* t); void IndexGeneratorTarget(cmGeneratorTarget* gt); + // Index the target using a name that is unique to that target + // even if other targets have the same name. + std::string IndexGeneratorTargetUniquely(cmGeneratorTarget const* gt); + static bool IsReservedTarget(std::string const& name); virtual const char* GetAllTargetName() const { return "ALL_BUILD"; } @@ -514,6 +520,7 @@ private: typedef std::unordered_map<std::string, cmGeneratorTarget*> GeneratorTargetMap; typedef std::unordered_map<std::string, cmMakefile*> MakefileMap; + typedef std::unordered_map<std::string, cmLocalGenerator*> LocalGeneratorMap; // Map efficiently from target name to cmTarget instance. // Do not use this structure for looping over all targets. // It contains both normal and globally visible imported targets. @@ -525,6 +532,11 @@ private: // It may not contain all of them (see note in IndexMakefile method). MakefileMap MakefileSearchIndex; + // Map efficiently from source directory path to cmLocalGenerator instance. + // Do not use this structure for looping over all directories. + // Its order is not deterministic. + LocalGeneratorMap LocalGeneratorSearchIndex; + cmMakefile* TryCompileOuterMakefile; // If you add a new map here, make sure it is copied // in EnableLanguagesFromGenerator @@ -583,6 +595,7 @@ private: std::string const& reason) const; void IndexMakefile(cmMakefile* mf); + void IndexLocalGenerator(cmLocalGenerator* lg); virtual const char* GetBuildIgnoreErrorsFlag() const { return nullptr; } diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 0c80910..4948c73 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -651,13 +651,13 @@ void cmGlobalNinjaGenerator::EnableLanguage( this->ResolveLanguageCompiler(l, mf, optional); } #ifdef _WIN32 - if (strcmp(mf->GetSafeDefinition("CMAKE_C_SIMULATE_ID"), "MSVC") != 0 && - strcmp(mf->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID"), "MSVC") != 0 && + if ((mf->GetSafeDefinition("CMAKE_C_SIMULATE_ID") != "MSVC") && + (mf->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID") != "MSVC") && (mf->IsOn("CMAKE_COMPILER_IS_MINGW") || - strcmp(mf->GetSafeDefinition("CMAKE_C_COMPILER_ID"), "GNU") == 0 || - strcmp(mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID"), "GNU") == 0 || - strcmp(mf->GetSafeDefinition("CMAKE_C_COMPILER_ID"), "Clang") == 0 || - strcmp(mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID"), "Clang") == 0)) { + (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "GNU") || + (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "GNU") || + (mf->GetSafeDefinition("CMAKE_C_COMPILER_ID") == "Clang") || + (mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID") == "Clang"))) { this->UsingGCCOnWindows = true; } #endif diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 6eb597c..63e6903 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -111,6 +111,8 @@ public: bool FindMakeProgram(cmMakefile* mf) override; + bool IsIPOSupported() const override { return true; } + static std::string GetInstalledNsightTegraVersion(); cmIDEFlagTable const* GetClFlagTable() const; diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index d7fe777..6e33cf7 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -5,7 +5,6 @@ #include "cmsys/Glob.hxx" #include <sstream> #include <stddef.h> -#include <string.h> #include <utility> #include "cmAlgorithms.h" @@ -350,8 +349,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // Check whether this is a DLL platform. bool dll_platform = - strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"), - "") != 0; + !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty(); for (std::string const& tgt : targetList.GetVector()) { diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 4f8f2e7..7030725 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -683,7 +683,7 @@ std::string cmLocalGenerator::GetIncludeFlags( std::string flagVar = "CMAKE_INCLUDE_FLAG_"; flagVar += lang; - const char* includeFlag = this->Makefile->GetSafeDefinition(flagVar); + std::string const& includeFlag = this->Makefile->GetSafeDefinition(flagVar); flagVar = "CMAKE_INCLUDE_FLAG_SEP_"; flagVar += lang; const char* sep = this->Makefile->GetDefinition(flagVar); @@ -1824,9 +1824,9 @@ bool cmLocalGenerator::GetShouldUseOldFlags(bool shared, std::string flagsVar = "CMAKE_SHARED_LIBRARY_"; flagsVar += lang; flagsVar += "_FLAGS"; - const char* flags = this->Makefile->GetSafeDefinition(flagsVar); + std::string const& flags = this->Makefile->GetSafeDefinition(flagsVar); - if (flags && flags != originalFlags) { + if (flags != originalFlags) { switch (this->GetPolicyStatus(cmPolicies::CMP0018)) { case cmPolicies::WARN: { std::ostringstream e; @@ -1859,7 +1859,7 @@ void cmLocalGenerator::AddPositionIndependentFlags(std::string& flags, std::string const& lang, int targetType) { - const char* picFlags = nullptr; + std::string picFlags; if (targetType == cmStateEnums::EXECUTABLE) { std::string flagsVar = "CMAKE_"; @@ -1867,13 +1867,13 @@ void cmLocalGenerator::AddPositionIndependentFlags(std::string& flags, flagsVar += "_COMPILE_OPTIONS_PIE"; picFlags = this->Makefile->GetSafeDefinition(flagsVar); } - if (!picFlags) { + if (picFlags.empty()) { std::string flagsVar = "CMAKE_"; flagsVar += lang; flagsVar += "_COMPILE_OPTIONS_PIC"; picFlags = this->Makefile->GetSafeDefinition(flagsVar); } - if (picFlags) { + if (!picFlags.empty()) { std::vector<std::string> options; cmSystemTools::ExpandListArgument(picFlags, options); for (std::string const& o : options) { diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index 690b827..272cc0e 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -1422,7 +1422,8 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies( this->WriteDisclaimer(internalRuleFileStream); // for each language we need to scan, scan it - const char* langStr = mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES"); + std::string const& langStr = + mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES"); std::vector<std::string> langs; cmSystemTools::ExpandListArgument(langStr, langs); for (std::string const& lang : langs) { diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index c05b085..c03afdd 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1082,7 +1082,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( // Use the NOINHERIT macro to avoid getting VS project default // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " - << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); + << this->Makefile->GetSafeDefinition(standardLibsVar); if (this->FortranProject) { this->Internal->OutputObjects(fout, target, configName, " "); } @@ -1167,7 +1167,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool( // Use the NOINHERIT macro to avoid getting VS project default // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " - << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); + << this->Makefile->GetSafeDefinition(standardLibsVar); if (this->FortranProject) { this->Internal->OutputObjects(fout, target, configName, " "); } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index dce7bd0..ec5ce92 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -11,6 +11,7 @@ #include <iterator> #include <memory> // IWYU pragma: keep #include <sstream> +#include <stdio.h> #include <stdlib.h> #include <utility> @@ -48,6 +49,11 @@ class cmMessenger; +cmDirectoryId::cmDirectoryId(std::string s) + : String(std::move(s)) +{ +} + // default is not to be building executables cmMakefile::cmMakefile(cmGlobalGenerator* globalGenerator, cmStateSnapshot const& snapshot) @@ -111,6 +117,17 @@ cmMakefile::~cmMakefile() cmDeleteAll(this->EvaluationFiles); } +cmDirectoryId cmMakefile::GetDirectoryId() const +{ + // Use the instance pointer value to uniquely identify this directory. + // If we ever need to expose this to CMake language code we should + // add a read-only property in cmMakefile::GetProperty. + char buf[32]; + sprintf(buf, "<%p>", + static_cast<void const*>(this)); // cast avoids format warning + return std::string(buf); +} + void cmMakefile::IssueMessage(cmake::MessageType t, std::string const& text) const { @@ -2384,7 +2401,7 @@ bool cmMakefile::IsDefinitionSet(const std::string& name) const return def != nullptr; } -const char* cmMakefile::GetDefinition(const std::string& name) const +const std::string* cmMakefile::GetDef(const std::string& name) const { const std::string* def = this->StateSnapshot.GetDefinition(name); if (!def) { @@ -2410,16 +2427,26 @@ const char* cmMakefile::GetDefinition(const std::string& name) const } } #endif - return (def ? def->c_str() : nullptr); + return def; } -const char* cmMakefile::GetSafeDefinition(const std::string& def) const +const char* cmMakefile::GetDefinition(const std::string& name) const { - const char* ret = this->GetDefinition(def); - if (!ret) { - return ""; + const std::string* def = GetDef(name); + if (!def) { + return nullptr; } - return ret; + return def->c_str(); +} + +const std::string& cmMakefile::GetSafeDefinition(const std::string& name) const +{ + static std::string const empty; + const std::string* def = GetDef(name); + if (!def) { + return empty; + } + return *def; } std::vector<std::string> cmMakefile::GetDefinitions() const diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 0ab4371..bb01c0b 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -47,6 +47,14 @@ class cmTest; class cmTestGenerator; class cmVariableWatch; +/** A type-safe wrapper for a string representing a directory id. */ +class cmDirectoryId +{ +public: + cmDirectoryId(std::string s); + std::string String; +}; + /** \class cmMakefile * \brief Process the input CMakeLists.txt file. * @@ -75,6 +83,8 @@ public: */ ~cmMakefile(); + cmDirectoryId GetDirectoryId() const; + bool ReadListFile(const char* filename); bool ReadDependentFile(const char* filename, bool noPolicyScope = true); @@ -422,7 +432,8 @@ public: * cache is then queried. */ const char* GetDefinition(const std::string&) const; - const char* GetSafeDefinition(const std::string&) const; + const std::string* GetDef(const std::string&) const; + const std::string& GetSafeDefinition(const std::string&) const; std::string GetRequiredDefinition(const std::string& name) const; bool IsDefinitionSet(const std::string&) const; /** diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index ebcc501..7ac8d1b 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -10,7 +10,6 @@ #include <map> #include <memory> // IWYU pragma: keep #include <sstream> -#include <string.h> #include "cmAlgorithms.h" #include "cmComputeLinkInformation.h" @@ -174,9 +173,8 @@ void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags, bool cmNinjaTargetGenerator::NeedDepTypeMSVC(const std::string& lang) const { - return strcmp(this->GetMakefile()->GetSafeDefinition("CMAKE_NINJA_DEPTYPE_" + - lang), - "msvc") == 0; + return (this->GetMakefile()->GetSafeDefinition("CMAKE_NINJA_DEPTYPE_" + + lang) == "msvc"); } // TODO: Refactor with diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index ba50fb8..5caea7d 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -135,7 +135,7 @@ static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy, cmPolicies::PolicyStatus* defaultSetting) { std::string defaultVar = "CMAKE_POLICY_DEFAULT_" + policy; - std::string defaultValue = mf->GetSafeDefinition(defaultVar); + std::string const& defaultValue = mf->GetSafeDefinition(defaultVar); if (defaultValue == "NEW") { *defaultSetting = cmPolicies::NEW; } else if (defaultValue == "OLD") { diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 91ed924..4ffe803 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -230,7 +230,11 @@ class cmMakefile; SELECT(POLICY, CMP0077, "option() honors normal variables.", 3, 13, 0, \ cmPolicies::WARN) \ SELECT(POLICY, CMP0078, "UseSWIG generates standard target names.", 3, 13, \ - 0, cmPolicies::WARN) + 0, cmPolicies::WARN) \ + SELECT( \ + POLICY, CMP0079, \ + "target_link_libraries allows use with targets in other directories.", 3, \ + 13, 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 8bd985a..8a202a2 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -1126,7 +1126,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo() } }; auto MfDef = [makefile](const char* key) { - return std::string(makefile->GetSafeDefinition(key)); + return makefile->GetSafeDefinition(key); }; // Write diff --git a/Source/cmQtAutoGeneratorMocUic.cxx b/Source/cmQtAutoGeneratorMocUic.cxx index c364700..2e6f90f 100644 --- a/Source/cmQtAutoGeneratorMocUic.cxx +++ b/Source/cmQtAutoGeneratorMocUic.cxx @@ -1204,7 +1204,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) valueConf = makefile->GetDefinition(keyConf); } if (valueConf == nullptr) { - valueConf = makefile->GetSafeDefinition(key); + return makefile->GetSafeDefinition(key); } return std::string(valueConf); }; @@ -1226,7 +1226,7 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) Base_.MultiConfig = InfoGetBool("AM_MULTI_CONFIG"); { unsigned long num = Base_.NumThreads; - if (cmSystemTools::StringToULong(InfoGet("AM_PARALLEL"), &num)) { + if (cmSystemTools::StringToULong(InfoGet("AM_PARALLEL").c_str(), &num)) { num = std::max<unsigned long>(num, 1); num = std::min<unsigned long>(num, ParallelMax); Base_.NumThreads = static_cast<unsigned int>(num); @@ -1264,7 +1264,8 @@ bool cmQtAutoGeneratorMocUic::Init(cmMakefile* makefile) // - Qt environment { unsigned long qtv = Base_.QtVersionMajor; - if (cmSystemTools::StringToULong(InfoGet("AM_QT_VERSION_MAJOR"), &qtv)) { + if (cmSystemTools::StringToULong(InfoGet("AM_QT_VERSION_MAJOR").c_str(), + &qtv)) { Base_.QtVersionMajor = static_cast<unsigned int>(qtv); } } diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx index 6caa0d8..65c6741 100644 --- a/Source/cmQtAutoGeneratorRcc.cxx +++ b/Source/cmQtAutoGeneratorRcc.cxx @@ -52,7 +52,7 @@ bool cmQtAutoGeneratorRcc::Init(cmMakefile* makefile) valueConf = makefile->GetDefinition(keyConf); } if (valueConf == nullptr) { - valueConf = makefile->GetSafeDefinition(key); + return makefile->GetSafeDefinition(key); } return std::string(valueConf); }; diff --git a/Source/cmState.cxx b/Source/cmState.cxx index c8b8653..c6667f6 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -659,6 +659,7 @@ cmStateSnapshot cmState::CreateBaseSnapshot() pos->IncludeDirectoryPosition = 0; pos->CompileDefinitionsPosition = 0; pos->CompileOptionsPosition = 0; + pos->LinkOptionsPosition = 0; pos->BuildSystemDirectory->DirectoryEnd = pos; pos->Policies = this->PolicyStack.Root(); pos->PolicyRoot = this->PolicyStack.Root(); @@ -810,6 +811,8 @@ cmStateSnapshot cmState::Pop(cmStateSnapshot const& originSnapshot) prevPos->BuildSystemDirectory->CompileDefinitions.size(); prevPos->CompileOptionsPosition = prevPos->BuildSystemDirectory->CompileOptions.size(); + prevPos->LinkOptionsPosition = + prevPos->BuildSystemDirectory->LinkOptions.size(); prevPos->BuildSystemDirectory->DirectoryEnd = prevPos; if (!pos->Keep && this->SnapshotData.IsLast(pos)) { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index cfcb31a..4e353c7 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -190,13 +190,11 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, // Check whether this is a DLL platform. this->DLLPlatform = - strcmp(this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX"), - "") != 0; + !this->Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty(); // Check whether we are targeting an Android platform. this->IsAndroid = - strcmp(this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME"), - "Android") == 0; + (this->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME") == "Android"); // Setup default property values. if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY && @@ -745,20 +743,27 @@ void cmTarget::GetTllSignatureTraces(std::ostream& s, TLLSignature sig) const void cmTarget::AddLinkLibrary(cmMakefile& mf, const std::string& lib, cmTargetLinkLibraryType llt) { - cmTarget* tgt = this->Makefile->FindTargetToUse(lib); + this->AddLinkLibrary(mf, lib, lib, llt); +} + +void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib, + std::string const& libRef, + cmTargetLinkLibraryType llt) +{ + cmTarget* tgt = mf.FindTargetToUse(lib); { const bool isNonImportedTarget = tgt && !tgt->IsImported(); const std::string libName = (isNonImportedTarget && llt != GENERAL_LibraryType) - ? targetNameGenex(lib) - : lib; + ? targetNameGenex(libRef) + : libRef; this->AppendProperty( "LINK_LIBRARIES", this->GetDebugGeneratorExpressions(libName, llt).c_str()); } - if (cmGeneratorExpression::Find(lib) != std::string::npos || + if (cmGeneratorExpression::Find(lib) != std::string::npos || lib != libRef || (tgt && (tgt->GetType() == cmStateEnums::INTERFACE_LIBRARY || tgt->GetType() == cmStateEnums::OBJECT_LIBRARY)) || diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 7a3ab65..1f380df 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -142,6 +142,9 @@ public: void AddLinkLibrary(cmMakefile& mf, const std::string& lib, cmTargetLinkLibraryType llt); + void AddLinkLibrary(cmMakefile& mf, std::string const& lib, + std::string const& libRef, cmTargetLinkLibraryType llt); + enum TLLSignature { KeywordTLLSignature, diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 1bbcf46..ad33f98 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -359,30 +359,53 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, } } + bool warnRemoteInterface = false; + bool rejectRemoteLinking = false; + bool encodeRemoteReference = false; + if (this->Makefile != this->Target->GetMakefile()) { + // The LHS target was created in another directory. + switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0079)) { + case cmPolicies::WARN: + warnRemoteInterface = true; + CM_FALLTHROUGH; + case cmPolicies::OLD: + rejectRemoteLinking = true; + break; + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::NEW: + encodeRemoteReference = true; + break; + } + } + + std::string libRef; + if (encodeRemoteReference && !cmSystemTools::FileIsFullPath(lib)) { + // This is a library name added by a caller that is not in the + // same directory as the target was created. Add a suffix to + // the name to tell ResolveLinkItem to look up the name in the + // caller's directory. + cmDirectoryId const dirId = this->Makefile->GetDirectoryId(); + libRef = lib + CMAKE_DIRECTORY_ID_SEP + dirId.String; + } else { + // This is an absolute path or a library name added by a caller + // in the same directory as the target was created. We can use + // the original name directly. + libRef = lib; + } + // Handle normal case where the command was called with another keyword than // INTERFACE / LINK_INTERFACE_LIBRARIES or none at all. (The "LINK_LIBRARIES" // property of the target on the LHS shall be populated.) if (this->CurrentProcessingState != ProcessingKeywordLinkInterface && this->CurrentProcessingState != ProcessingPlainLinkInterface) { - // Assure that the target on the LHS was created in the current directory. - cmTarget* t = - this->Makefile->FindLocalNonAliasTarget(this->Target->GetName()); - if (!t) { - const std::vector<cmTarget*>& importedTargets = - this->Makefile->GetOwnedImportedTargets(); - for (cmTarget* importedTarget : importedTargets) { - if (importedTarget->GetName() == this->Target->GetName()) { - t = importedTarget; - break; - } - } - } - if (!t) { + if (rejectRemoteLinking) { std::ostringstream e; e << "Attempt to add link library \"" << lib << "\" to target \"" << this->Target->GetName() - << "\" which is not built in this directory."; + << "\" which is not built in this directory.\n" + << "This is allowed only when policy CMP0079 is set to NEW."; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return false; } @@ -404,7 +427,20 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); } - this->Target->AddLinkLibrary(*this->Makefile, lib, llt); + this->Target->AddLinkLibrary(*this->Makefile, lib, libRef, llt); + } + + if (warnRemoteInterface) { + std::ostringstream w; + /* clang-format off */ + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0079) << "\n" + "Target\n " << this->Target->GetName() << "\nis not created in this " + "directory. For compatibility with older versions of CMake, link " + "library\n " << lib << "\nwill be looked up in the directory in " + "which the target was created rather than in this calling " + "directory."; + /* clang-format on */ + this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); } // Handle (additional) case where the command was called with PRIVATE / @@ -415,9 +451,9 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, this->CurrentProcessingState == ProcessingPlainPrivateInterface) { if (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY) { std::string configLib = - this->Target->GetDebugGeneratorExpressions(lib, llt); - if (cmGeneratorExpression::IsValidTargetName(lib) || - cmGeneratorExpression::Find(lib) != std::string::npos) { + this->Target->GetDebugGeneratorExpressions(libRef, llt); + if (cmGeneratorExpression::IsValidTargetName(libRef) || + cmGeneratorExpression::Find(libRef) != std::string::npos) { configLib = "$<LINK_ONLY:" + configLib + ">"; } this->Target->AppendProperty("INTERFACE_LINK_LIBRARIES", @@ -431,7 +467,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, // property of the target on the LHS shall be populated.) this->Target->AppendProperty( "INTERFACE_LINK_LIBRARIES", - this->Target->GetDebugGeneratorExpressions(lib, llt).c_str()); + this->Target->GetDebugGeneratorExpressions(libRef, llt).c_str()); // Stop processing if called without any keyword. if (this->CurrentProcessingState == ProcessingLinkLibraries) { @@ -464,12 +500,12 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, for (std::string const& dc : debugConfigs) { prop = "LINK_INTERFACE_LIBRARIES_"; prop += dc; - this->Target->AppendProperty(prop, lib.c_str()); + this->Target->AppendProperty(prop, libRef.c_str()); } } if (llt == OPTIMIZED_LibraryType || llt == GENERAL_LibraryType) { // Put in the non-DEBUG configuration interfaces. - this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib.c_str()); + this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", libRef.c_str()); // Make sure the DEBUG configuration interfaces exist so that the // general one will not be used as a fall-back. diff --git a/Source/cmTargetLinkOptionsCommand.cxx b/Source/cmTargetLinkOptionsCommand.cxx index f0f13fd..d6ed5ae 100644 --- a/Source/cmTargetLinkOptionsCommand.cxx +++ b/Source/cmTargetLinkOptionsCommand.cxx @@ -33,9 +33,9 @@ std::string cmTargetLinkOptionsCommand::Join( } bool cmTargetLinkOptionsCommand::HandleDirectContent( - cmTarget* tgt, const std::vector<std::string>& content, bool, bool) + cmTarget* tgt, const std::vector<std::string>& content, bool prepend, bool) { cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - tgt->InsertLinkOption(this->Join(content), lfbt); + tgt->InsertLinkOption(this->Join(content), lfbt, prepend); return true; // Successfully handled. } diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 53a2a59..c79b071 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1122,6 +1122,9 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues( this->GeneratorTarget->GetPropertyAsBool("VS_WINRT_EXTENSIONS")) { e1.Element("WindowsAppContainer", "true"); } + if (this->IPOEnabledConfigurations.count(config) > 0) { + e1.Element("WholeProgramOptimization", "true"); + } } void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged( @@ -2370,9 +2373,11 @@ void cmVisualStudio10TargetGenerator::OutputLinkIncremental( Options& linkOptions = *(this->LinkOptions[configName]); const std::string cond = this->CalcCondition(configName); - const char* incremental = linkOptions.GetFlag("LinkIncremental"); - e1.WritePlatformConfigTag("LinkIncremental", cond, - (incremental ? incremental : "true")); + if (this->IPOEnabledConfigurations.count(configName) == 0) { + const char* incremental = linkOptions.GetFlag("LinkIncremental"); + e1.WritePlatformConfigTag("LinkIncremental", cond, + (incremental ? incremental : "true")); + } linkOptions.RemoveFlag("LinkIncremental"); const char* manifest = linkOptions.GetFlag("GenerateManifest"); @@ -2484,8 +2489,10 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( clOptions.AddFlag("CompileAs", "CompileAsCpp"); } - // Check IPO related warning/error. - this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName); + // Put the IPO enabled configurations into a set. + if (this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName)) { + this->IPOEnabledConfigurations.insert(configName); + } // Get preprocessor definitions for this directory. std::string defineFlags = this->Makefile->GetDefineFlags(); @@ -2699,11 +2706,9 @@ bool cmVisualStudio10TargetGenerator::ComputeRcOptions( Options& rcOptions = *pOptions; std::string CONFIG = cmSystemTools::UpperCase(configName); - std::string rcConfigFlagsVar = std::string("CMAKE_RC_FLAGS_") + CONFIG; - std::string flags = - std::string(this->Makefile->GetSafeDefinition("CMAKE_RC_FLAGS")) + - std::string(" ") + - std::string(this->Makefile->GetSafeDefinition(rcConfigFlagsVar)); + std::string rcConfigFlagsVar = "CMAKE_RC_FLAGS_" + CONFIG; + std::string flags = this->Makefile->GetSafeDefinition("CMAKE_RC_FLAGS") + + " " + this->Makefile->GetSafeDefinition(rcConfigFlagsVar); rcOptions.Parse(flags); @@ -2757,10 +2762,8 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions( // Get compile flags for CUDA in this directory. std::string CONFIG = cmSystemTools::UpperCase(configName); std::string configFlagsVar = std::string("CMAKE_CUDA_FLAGS_") + CONFIG; - std::string flags = - std::string(this->Makefile->GetSafeDefinition("CMAKE_CUDA_FLAGS")) + - std::string(" ") + - std::string(this->Makefile->GetSafeDefinition(configFlagsVar)); + std::string flags = this->Makefile->GetSafeDefinition("CMAKE_CUDA_FLAGS") + + " " + this->Makefile->GetSafeDefinition(configFlagsVar); this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, "CUDA", configName); @@ -2971,9 +2974,8 @@ bool cmVisualStudio10TargetGenerator::ComputeMasmOptions( std::string CONFIG = cmSystemTools::UpperCase(configName); std::string configFlagsVar = std::string("CMAKE_ASM_MASM_FLAGS_") + CONFIG; std::string flags = - std::string(this->Makefile->GetSafeDefinition("CMAKE_ASM_MASM_FLAGS")) + - std::string(" ") + - std::string(this->Makefile->GetSafeDefinition(configFlagsVar)); + this->Makefile->GetSafeDefinition("CMAKE_ASM_MASM_FLAGS") + " " + + this->Makefile->GetSafeDefinition(configFlagsVar); masmOptions.Parse(flags); @@ -3024,14 +3026,11 @@ bool cmVisualStudio10TargetGenerator::ComputeNasmOptions( Options& nasmOptions = *pOptions; std::string CONFIG = cmSystemTools::UpperCase(configName); - std::string configFlagsVar = std::string("CMAKE_ASM_NASM_FLAGS_") + CONFIG; + std::string configFlagsVar = "CMAKE_ASM_NASM_FLAGS_" + CONFIG; std::string flags = - std::string(this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_FLAGS")) + - std::string(" -f") + - std::string( - this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_OBJECT_FORMAT")) + - std::string(" ") + - std::string(this->Makefile->GetSafeDefinition(configFlagsVar)); + this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_FLAGS") + " -f" + + this->Makefile->GetSafeDefinition("CMAKE_ASM_NASM_OBJECT_FORMAT") + " " + + this->Makefile->GetSafeDefinition(configFlagsVar); nasmOptions.Parse(flags); // Get includes for this target diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 15e47b4..829d2bf 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -204,6 +204,7 @@ private: bool NsightTegra; unsigned int NsightTegraVersion[4]; bool TargetCompileAsWinRT; + std::set<std::string> IPOEnabledConfigurations; cmGlobalVisualStudio10Generator* const GlobalGenerator; cmLocalVisualStudio10Generator* const LocalGenerator; std::set<std::string> CSharpCustomCommandNames; diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index 9fa0cb1..2a2e737 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -973,8 +973,8 @@ void kwsysProcess_Execute(kwsysProcess* cp) wchar_t* wstdin = kwsysEncoding_DupToWide(cp->PipeFileSTDIN); DWORD error; cp->PipeChildStd[0] = - CreateFileW(wstdin, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0); + CreateFileW(wstdin, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, + OPEN_EXISTING, 0, 0); error = GetLastError(); /* Check now in case free changes this. */ free(wstdin); if (cp->PipeChildStd[0] == INVALID_HANDLE_VALUE) { diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 476fe08..0a4ad7a 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -3640,11 +3640,11 @@ bool SystemTools::Split(const std::string& str, while (lpos < data.length()) { std::string::size_type rpos = data.find_first_of(separator, lpos); if (rpos == std::string::npos) { - // Line ends at end of string without a newline. + // String ends at end of string without a separator. lines.push_back(data.substr(lpos)); return false; } else { - // Line ends in a "\n", remove the character. + // String ends in a separator, remove the character. lines.push_back(data.substr(lpos, rpos - lpos)); } lpos = rpos + 1; @@ -3658,7 +3658,7 @@ bool SystemTools::Split(const std::string& str, std::string data(str); std::string::size_type lpos = 0; while (lpos < data.length()) { - std::string::size_type rpos = data.find_first_of("\n", lpos); + std::string::size_type rpos = data.find_first_of('\n', lpos); if (rpos == std::string::npos) { // Line ends at end of string without a newline. lines.push_back(data.substr(lpos)); |
