diff options
Diffstat (limited to 'Source')
40 files changed, 494 insertions, 286 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index a6babe5..b1f4ca5 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -404,6 +404,7 @@ set(SRCS cmStateSnapshot.cxx cmStateSnapshot.h cmStateTypes.h + cmStringAlgorithms.cxx cmStringAlgorithms.h cmSystemTools.cxx cmSystemTools.h diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 63a4207..3bbbd28 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 15) -set(CMake_VERSION_PATCH 20190730) +set(CMake_VERSION_PATCH 20190805) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index 512ac7a..3fd124b 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -21,6 +21,7 @@ #include "cmMakefile.h" #include "cmState.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" #include "cmVersion.h" #include "cmWorkingDirectory.h" #include "cmXMLSafe.h" @@ -772,7 +773,7 @@ int cmCPackGenerator::InstallCMakeProject( // Make sure that DESTDIR + CPACK_INSTALL_PREFIX directory // exists: // - if (cmSystemTools::StringStartsWith(dir.c_str(), "/")) { + if (cmHasLiteralPrefix(dir, "/")) { dir = tempInstallDirectory + dir; } else { dir = tempInstallDirectory + "/" + dir; diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index f6028c4..54fe612 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -13,6 +13,7 @@ #include "cmParseGTMCoverage.h" #include "cmParseJacocoCoverage.h" #include "cmParsePHPCoverage.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmWorkingDirectory.h" #include "cmXMLWriter.h" @@ -1181,7 +1182,7 @@ int cmCTestCoverageHandler::HandleGCovCoverage( // gcov 4.7 can have output lines saying "No executable lines" and // "Removing 'filename.gcov'"... Don't log those as "errors." if (line != "No executable lines" && - !cmSystemTools::StringStartsWith(line.c_str(), "Removing ")) { + !cmHasLiteralPrefix(line, "Removing ")) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Unknown gcov output line: [" << line << "]" << std::endl); diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx index 237ca82..bbf490e 100644 --- a/Source/CTest/cmCTestLaunch.cxx +++ b/Source/CTest/cmCTestLaunch.cxx @@ -16,6 +16,7 @@ #include "cmProcessOutput.h" #include "cmState.h" #include "cmStateSnapshot.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" #include "cmake.h" @@ -594,7 +595,7 @@ bool cmCTestLaunch::Match(std::string const& line, bool cmCTestLaunch::MatchesFilterPrefix(std::string const& line) const { return !this->OptionFilterPrefix.empty() && - cmSystemTools::StringStartsWith(line, this->OptionFilterPrefix.c_str()); + cmHasPrefix(line, this->OptionFilterPrefix); } int cmCTestLaunch::Main(int argc, const char* const argv[]) diff --git a/Source/CTest/cmParseBlanketJSCoverage.cxx b/Source/CTest/cmParseBlanketJSCoverage.cxx index 63d6a15..b74decb 100644 --- a/Source/CTest/cmParseBlanketJSCoverage.cxx +++ b/Source/CTest/cmParseBlanketJSCoverage.cxx @@ -110,7 +110,8 @@ cmParseBlanketJSCoverage::cmParseBlanketJSCoverage( { } -bool cmParseBlanketJSCoverage::LoadCoverageData(std::vector<std::string> files) +bool cmParseBlanketJSCoverage::LoadCoverageData( + std::vector<std::string> const& files) { cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Found " << files.size() << " Files" << std::endl, diff --git a/Source/CTest/cmParseBlanketJSCoverage.h b/Source/CTest/cmParseBlanketJSCoverage.h index 696121f..cd1b225 100644 --- a/Source/CTest/cmParseBlanketJSCoverage.h +++ b/Source/CTest/cmParseBlanketJSCoverage.h @@ -29,7 +29,7 @@ class cmParseBlanketJSCoverage public: cmParseBlanketJSCoverage(cmCTestCoverageHandlerContainer& cont, cmCTest* ctest); - bool LoadCoverageData(std::vector<std::string> files); + bool LoadCoverageData(std::vector<std::string> const& files); // Read the JSON output bool ReadJSONFile(std::string const& file); diff --git a/Source/CTest/cmParseJacocoCoverage.cxx b/Source/CTest/cmParseJacocoCoverage.cxx index b78142a..5f1e712 100644 --- a/Source/CTest/cmParseJacocoCoverage.cxx +++ b/Source/CTest/cmParseJacocoCoverage.cxx @@ -2,6 +2,7 @@ #include "cmCTest.h" #include "cmCTestCoverageHandler.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmXMLParser.h" @@ -118,7 +119,7 @@ protected: // Check if any of the locations found match our package. for (std::string const& f : files) { std::string dir = cmsys::SystemTools::GetParentDirectory(f); - if (cmsys::SystemTools::StringEndsWith(dir, this->PackageName.c_str())) { + if (cmHasSuffix(dir, this->PackageName)) { cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Found package directory for " << fileName << ": " << dir << std::endl, diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 610e9f9..026250d 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -1965,7 +1965,7 @@ bool cmCTest::HandleCommandLineArguments(size_t& i, if (this->CheckArgument(arg, "-N", "--show-only")) { this->Impl->ShowOnly = true; } - if (cmSystemTools::StringStartsWith(arg.c_str(), "--show-only=")) { + if (cmHasLiteralPrefix(arg, "--show-only=")) { this->Impl->ShowOnly = true; // Check if a specific format is requested. Defaults to human readable @@ -2227,7 +2227,7 @@ int cmCTest::Run(std::vector<std::string>& args, std::string* output) // attempts are simply ignored since previous ctest versions ignore // this too. (As well as many other unknown command line args.) // - if (arg != "-D" && cmSystemTools::StringStartsWith(arg.c_str(), "-D")) { + if (arg != "-D" && cmHasLiteralPrefix(arg, "-D")) { std::string input = arg.substr(2); this->AddVariableDefinition(input); } diff --git a/Source/cmCallVisualStudioMacro.cxx b/Source/cmCallVisualStudioMacro.cxx index f7a2244..9e152ff 100644 --- a/Source/cmCallVisualStudioMacro.cxx +++ b/Source/cmCallVisualStudioMacro.cxx @@ -4,6 +4,7 @@ #include <sstream> +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #if defined(_MSC_VER) @@ -328,8 +329,7 @@ HRESULT FindVisualStudioInstances(const std::string& slnFile, if (SUCCEEDED(hr)) { std::map<std::string, IUnknownPtr>::iterator it; for (it = mrot.begin(); it != mrot.end(); ++it) { - if (cmSystemTools::StringStartsWith(it->first.c_str(), - "!VisualStudio.DTE.")) { + if (cmHasLiteralPrefix(it->first, "!VisualStudio.DTE.")) { IDispatchPtr disp(it->second); if (disp != (IDispatch*)0) { std::string slnName; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 78cddf0..5f46631 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -990,11 +990,6 @@ void cmComputeLinkInformation::AddTargetItem(std::string const& item, return; } - // If this platform wants a flag before the full path, add it. - if (!this->LibLinkFileFlag.empty()) { - this->Items.emplace_back(this->LibLinkFileFlag, false); - } - // For compatibility with CMake 2.4 include the item's directory in // the linker search path. if (this->OldLinkDirMode && !target->IsFrameworkOnApple() && @@ -1057,11 +1052,6 @@ void cmComputeLinkInformation::AddFullItem(std::string const& item) this->OldLinkDirItems.push_back(item); } - // If this platform wants a flag before the full path, add it. - if (!this->LibLinkFileFlag.empty()) { - this->Items.emplace_back(this->LibLinkFileFlag, false); - } - // Now add the full path to the library. this->Items.emplace_back(item, true); } diff --git a/Source/cmComputeLinkInformation.h b/Source/cmComputeLinkInformation.h index 3be2c7f..784d3fa 100644 --- a/Source/cmComputeLinkInformation.h +++ b/Source/cmComputeLinkInformation.h @@ -56,6 +56,11 @@ public: std::string GetChrpathString() const; std::set<cmGeneratorTarget const*> const& GetSharedLibrariesLinked() const; + std::string const& GetLibLinkFileFlag() const + { + return this->LibLinkFileFlag; + } + std::string const& GetRPathLinkFlag() const { return this->RPathLinkFlag; } std::string GetRPathLinkString() const; diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 8fd2947..87f9b4c 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -1209,8 +1209,8 @@ bool cmExportFileGenerator::PopulateExportProperties( targetProperties.GetPropertyValue("EXPORT_PROPERTIES")) { for (auto& prop : cmSystemTools::ExpandedListArgument(exportProperties)) { /* Black list reserved properties */ - if (cmSystemTools::StringStartsWith(prop, "IMPORTED_") || - cmSystemTools::StringStartsWith(prop, "INTERFACE_")) { + if (cmHasLiteralPrefix(prop, "IMPORTED_") || + cmHasLiteralPrefix(prop, "INTERFACE_")) { std::ostringstream e; e << "Target \"" << gte->Target->GetName() << "\" contains property \"" << prop << "\" in EXPORT_PROPERTIES but IMPORTED_* and INTERFACE_* " diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx index aa84396..2594287 100644 --- a/Source/cmFileAPI.cxx +++ b/Source/cmFileAPI.cxx @@ -684,7 +684,6 @@ void cmFileAPI::BuildClientRequestCodeModel( Json::Value cmFileAPI::BuildCodeModel(Object const& object) { - using namespace std::placeholders; Json::Value codemodel = cmFileAPICodemodelDump(*this, object.Version); codemodel["kind"] = this->ObjectKindName(object.Kind); @@ -719,7 +718,6 @@ void cmFileAPI::BuildClientRequestCache( Json::Value cmFileAPI::BuildCache(Object const& object) { - using namespace std::placeholders; Json::Value cache = cmFileAPICacheDump(*this, object.Version); cache["kind"] = this->ObjectKindName(object.Kind); @@ -754,7 +752,6 @@ void cmFileAPI::BuildClientRequestCMakeFiles( Json::Value cmFileAPI::BuildCMakeFiles(Object const& object) { - using namespace std::placeholders; Json::Value cmakeFiles = cmFileAPICMakeFilesDump(*this, object.Version); cmakeFiles["kind"] = this->ObjectKindName(object.Kind); diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 7b916cd..172897c 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -30,6 +30,9 @@ #include <algorithm> #include <cassert> +#include <cstddef> +#include <functional> +#include <limits> #include <map> #include <memory> #include <set> @@ -135,6 +138,40 @@ std::string TargetId(cmGeneratorTarget const* gt, std::string const& topBuild) return gt->GetName() + CMAKE_DIRECTORY_ID_SEP + hash; } +class JBTIndex +{ +public: + JBTIndex() = default; + explicit operator bool() const { return Index != None; } + Json::ArrayIndex Index = None; + static Json::ArrayIndex const None = static_cast<Json::ArrayIndex>(-1); +}; + +template <typename T> +class JBT +{ +public: + JBT(T v = T(), JBTIndex bt = JBTIndex()) + : Value(std::move(v)) + , Backtrace(bt) + { + } + T Value; + JBTIndex Backtrace; + friend bool operator==(JBT<T> const& l, JBT<T> const& r) + { + return l.Value == r.Value && l.Backtrace.Index == r.Backtrace.Index; + } + static bool ValueEq(JBT<T> const& l, JBT<T> const& r) + { + return l.Value == r.Value; + } + static bool ValueLess(JBT<T> const& l, JBT<T> const& r) + { + return l.Value < r.Value; + } +}; + class BacktraceData { std::string TopSource; @@ -169,7 +206,7 @@ class BacktraceData public: BacktraceData(std::string topSource); - bool Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index); + JBTIndex Add(cmListFileBacktrace const& bt); Json::Value Dump(); }; @@ -178,16 +215,17 @@ BacktraceData::BacktraceData(std::string topSource) { } -bool BacktraceData::Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index) +JBTIndex BacktraceData::Add(cmListFileBacktrace const& bt) { + JBTIndex index; if (bt.Empty()) { - return false; + return index; } cmListFileContext const* top = &bt.Top(); auto found = this->NodeMap.find(top); if (found != this->NodeMap.end()) { - index = found->second; - return true; + index.Index = found->second; + return index; } Json::Value entry = Json::objectValue; entry["file"] = this->AddFile(top->FilePath); @@ -197,13 +235,12 @@ bool BacktraceData::Add(cmListFileBacktrace const& bt, Json::ArrayIndex& index) if (!top->Name.empty()) { entry["command"] = this->AddCommand(top->Name); } - Json::ArrayIndex parent; - if (this->Add(bt.Pop(), parent)) { - entry["parent"] = parent; + if (JBTIndex parent = this->Add(bt.Pop())) { + entry["parent"] = parent.Index; } - index = this->NodeMap[top] = this->Nodes.size(); + index.Index = this->NodeMap[top] = this->Nodes.size(); this->Nodes.append(std::move(entry)); // NOLINT(*) - return true; + return index; } Json::Value BacktraceData::Dump() @@ -222,32 +259,65 @@ struct CompileData { struct IncludeEntry { - BT<std::string> Path; + JBT<std::string> Path; bool IsSystem = false; - IncludeEntry(BT<std::string> path, bool isSystem) + IncludeEntry(JBT<std::string> path, bool isSystem) : Path(std::move(path)) , IsSystem(isSystem) { } + friend bool operator==(IncludeEntry const& l, IncludeEntry const& r) + { + return l.Path == r.Path && l.IsSystem == r.IsSystem; + } }; - void SetDefines(std::set<BT<std::string>> const& defines); - std::string Language; std::string Sysroot; - std::vector<BT<std::string>> Flags; - std::vector<BT<std::string>> Defines; + std::vector<JBT<std::string>> Flags; + std::vector<JBT<std::string>> Defines; std::vector<IncludeEntry> Includes; + + friend bool operator==(CompileData const& l, CompileData const& r) + { + return (l.Language == r.Language && l.Sysroot == r.Sysroot && + l.Flags == r.Flags && l.Defines == r.Defines && + l.Includes == r.Includes); + } }; +} + +namespace std { -void CompileData::SetDefines(std::set<BT<std::string>> const& defines) +template <> +struct hash<CompileData> { - this->Defines.reserve(defines.size()); - for (BT<std::string> const& d : defines) { - this->Defines.push_back(d); + std::size_t operator()(CompileData const& in) const + { + using std::hash; + size_t result = + hash<std::string>()(in.Language) ^ hash<std::string>()(in.Sysroot); + for (auto const& i : in.Includes) { + result = result ^ + (hash<std::string>()(i.Path.Value) ^ + hash<Json::ArrayIndex>()(i.Path.Backtrace.Index) ^ + (i.IsSystem ? std::numeric_limits<size_t>::max() : 0)); + } + for (auto const& i : in.Flags) { + result = result ^ hash<std::string>()(i.Value) ^ + hash<Json::ArrayIndex>()(i.Backtrace.Index); + } + for (auto const& i : in.Defines) { + result = result ^ hash<std::string>()(i.Value) ^ + hash<Json::ArrayIndex>()(i.Backtrace.Index); + } + return result; } -} +}; +} // namespace std + +namespace { class Target { cmGeneratorTarget* GT; @@ -272,24 +342,32 @@ class Target struct CompileGroup { - std::map<Json::Value, Json::ArrayIndex>::iterator Entry; + std::unordered_map<CompileData, Json::ArrayIndex>::iterator Entry; Json::Value SourceIndexes = Json::arrayValue; }; - std::map<Json::Value, Json::ArrayIndex> CompileGroupMap; + std::unordered_map<CompileData, Json::ArrayIndex> CompileGroupMap; std::vector<CompileGroup> CompileGroups; + template <typename T> + JBT<T> ToJBT(BT<T> const& bt) + { + return JBT<T>(bt.Value, this->Backtraces.Add(bt.Backtrace)); + } + void ProcessLanguages(); void ProcessLanguage(std::string const& lang); Json::ArrayIndex AddSourceGroup(cmSourceGroup* sg, Json::ArrayIndex si); CompileData BuildCompileData(cmSourceFile* sf); + CompileData MergeCompileData(CompileData const& fd); Json::ArrayIndex AddSourceCompileGroup(cmSourceFile* sf, Json::ArrayIndex si); void AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt); + void AddBacktrace(Json::Value& object, JBTIndex bt); Json::Value DumpPaths(); - Json::Value DumpCompileData(CompileData cd); + Json::Value DumpCompileData(CompileData const& cd); Json::Value DumpInclude(CompileData::IncludeEntry const& inc); - Json::Value DumpDefine(BT<std::string> const& def); + Json::Value DumpDefine(JBT<std::string> const& def); Json::Value DumpSources(); Json::Value DumpSource(cmGeneratorTarget::SourceAndKind const& sk, Json::ArrayIndex si); @@ -306,8 +384,8 @@ class Target Json::Value DumpLink(); Json::Value DumpArchive(); Json::Value DumpLinkCommandFragments(); - Json::Value DumpCommandFragments(std::vector<BT<std::string>> const& frags); - Json::Value DumpCommandFragment(BT<std::string> const& frag, + Json::Value DumpCommandFragments(std::vector<JBT<std::string>> const& frags); + Json::Value DumpCommandFragment(JBT<std::string> const& frag, std::string const& role = std::string()); Json::Value DumpDependencies(); Json::Value DumpDependency(cmTargetDepend const& td); @@ -722,16 +800,20 @@ void Target::ProcessLanguage(std::string const& lang) // which may need to be factored out. std::string flags; lg->GetTargetCompileFlags(this->GT, this->Config, lang, flags); - cd.Flags.emplace_back(std::move(flags), cmListFileBacktrace()); + cd.Flags.emplace_back(std::move(flags), JBTIndex()); } std::set<BT<std::string>> defines = lg->GetTargetDefines(this->GT, this->Config, lang); - cd.SetDefines(defines); + cd.Defines.reserve(defines.size()); + for (BT<std::string> const& d : defines) { + cd.Defines.emplace_back(this->ToJBT(d)); + } std::vector<BT<std::string>> includePathList = lg->GetIncludeDirectories(this->GT, lang, this->Config); for (BT<std::string> const& i : includePathList) { cd.Includes.emplace_back( - i, this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang)); + this->ToJBT(i), + this->GT->IsSystemIncludeDirectory(i.Value, this->Config, lang)); } } @@ -758,26 +840,22 @@ CompileData Target::BuildCompileData(cmSourceFile* sf) if (fd.Language.empty()) { return fd; } - CompileData const& cd = this->CompileDataMap.at(fd.Language); - - fd.Sysroot = cd.Sysroot; cmLocalGenerator* lg = this->GT->GetLocalGenerator(); cmGeneratorExpressionInterpreter genexInterpreter(lg, this->Config, this->GT, fd.Language); - fd.Flags = cd.Flags; const std::string COMPILE_FLAGS("COMPILE_FLAGS"); if (const char* cflags = sf->GetProperty(COMPILE_FLAGS)) { std::string flags = genexInterpreter.Evaluate(cflags, COMPILE_FLAGS); - fd.Flags.emplace_back(std::move(flags), cmListFileBacktrace()); + fd.Flags.emplace_back(std::move(flags), JBTIndex()); } const std::string COMPILE_OPTIONS("COMPILE_OPTIONS"); if (const char* coptions = sf->GetProperty(COMPILE_OPTIONS)) { std::string flags; lg->AppendCompileOptions( flags, genexInterpreter.Evaluate(coptions, COMPILE_OPTIONS)); - fd.Flags.emplace_back(std::move(flags), cmListFileBacktrace()); + fd.Flags.emplace_back(std::move(flags), JBTIndex()); } // Add include directories from source file properties. @@ -796,8 +874,6 @@ CompileData Target::BuildCompileData(cmSourceFile* sf) } } } - fd.Includes.insert(fd.Includes.end(), cd.Includes.begin(), - cd.Includes.end()); const std::string COMPILE_DEFINITIONS("COMPILE_DEFINITIONS"); std::set<std::string> fileDefines; @@ -814,27 +890,62 @@ CompileData Target::BuildCompileData(cmSourceFile* sf) genexInterpreter.Evaluate(config_defs, COMPILE_DEFINITIONS)); } - std::set<BT<std::string>> defines; - defines.insert(fileDefines.begin(), fileDefines.end()); - defines.insert(cd.Defines.begin(), cd.Defines.end()); - - fd.SetDefines(defines); + fd.Defines.reserve(fileDefines.size()); + for (std::string const& d : fileDefines) { + fd.Defines.emplace_back(d, JBTIndex()); + } return fd; } +CompileData Target::MergeCompileData(CompileData const& fd) +{ + CompileData cd; + cd.Language = fd.Language; + if (cd.Language.empty()) { + return cd; + } + CompileData const& td = this->CompileDataMap.at(cd.Language); + + // All compile groups share the sysroot of the target. + cd.Sysroot = td.Sysroot; + + // Use target-wide flags followed by source-specific flags. + cd.Flags.reserve(td.Flags.size() + fd.Flags.size()); + cd.Flags.insert(cd.Flags.end(), td.Flags.begin(), td.Flags.end()); + cd.Flags.insert(cd.Flags.end(), fd.Flags.begin(), fd.Flags.end()); + + // Use source-specific includes followed by target-wide includes. + cd.Includes.reserve(fd.Includes.size() + td.Includes.size()); + cd.Includes.insert(cd.Includes.end(), fd.Includes.begin(), + fd.Includes.end()); + cd.Includes.insert(cd.Includes.end(), td.Includes.begin(), + td.Includes.end()); + + // Use target-wide defines followed by source-specific defines. + cd.Defines.reserve(td.Defines.size() + fd.Defines.size()); + cd.Defines.insert(cd.Defines.end(), td.Defines.begin(), td.Defines.end()); + cd.Defines.insert(cd.Defines.end(), fd.Defines.begin(), fd.Defines.end()); + + // De-duplicate defines. + std::stable_sort(cd.Defines.begin(), cd.Defines.end(), + JBT<std::string>::ValueLess); + auto end = std::unique(cd.Defines.begin(), cd.Defines.end(), + JBT<std::string>::ValueEq); + cd.Defines.erase(end, cd.Defines.end()); + + return cd; +} + Json::ArrayIndex Target::AddSourceCompileGroup(cmSourceFile* sf, Json::ArrayIndex si) { - Json::Value compileDataJson = - this->DumpCompileData(this->BuildCompileData(sf)); - std::map<Json::Value, Json::ArrayIndex>::iterator i = - this->CompileGroupMap.find(compileDataJson); + CompileData compileData = this->BuildCompileData(sf); + auto i = this->CompileGroupMap.find(compileData); if (i == this->CompileGroupMap.end()) { Json::ArrayIndex cgIndex = static_cast<Json::ArrayIndex>(this->CompileGroups.size()); - i = - this->CompileGroupMap.emplace(std::move(compileDataJson), cgIndex).first; + i = this->CompileGroupMap.emplace(std::move(compileData), cgIndex).first; CompileGroup g; g.Entry = i; this->CompileGroups.push_back(std::move(g)); @@ -845,9 +956,15 @@ Json::ArrayIndex Target::AddSourceCompileGroup(cmSourceFile* sf, void Target::AddBacktrace(Json::Value& object, cmListFileBacktrace const& bt) { - Json::ArrayIndex backtrace; - if (this->Backtraces.Add(bt, backtrace)) { - object["backtrace"] = backtrace; + if (JBTIndex backtrace = this->Backtraces.Add(bt)) { + object["backtrace"] = backtrace.Index; + } +} + +void Target::AddBacktrace(Json::Value& object, JBTIndex bt) +{ + if (bt) { + object["backtrace"] = bt.Index; } } @@ -915,7 +1032,7 @@ Json::Value Target::DumpSource(cmGeneratorTarget::SourceAndKind const& sk, return source; } -Json::Value Target::DumpCompileData(CompileData cd) +Json::Value Target::DumpCompileData(CompileData const& cd) { Json::Value result = Json::objectValue; @@ -937,7 +1054,7 @@ Json::Value Target::DumpCompileData(CompileData cd) } if (!cd.Defines.empty()) { Json::Value defines = Json::arrayValue; - for (BT<std::string> const& d : cd.Defines) { + for (JBT<std::string> const& d : cd.Defines) { defines.append(this->DumpDefine(d)); } result["defines"] = std::move(defines); @@ -957,7 +1074,7 @@ Json::Value Target::DumpInclude(CompileData::IncludeEntry const& inc) return include; } -Json::Value Target::DumpDefine(BT<std::string> const& def) +Json::Value Target::DumpDefine(JBT<std::string> const& def) { Json::Value define = Json::objectValue; define["define"] = def.Value; @@ -993,7 +1110,8 @@ Json::Value Target::DumpCompileGroups() Json::Value Target::DumpCompileGroup(CompileGroup& cg) { - Json::Value group = cg.Entry->first; + Json::Value group = + this->DumpCompileData(this->MergeCompileData(cg.Entry->first)); group["sourceIndexes"] = std::move(cg.SourceIndexes); return group; } @@ -1026,12 +1144,9 @@ Json::Value Target::DumpInstallPrefix() Json::Value Target::DumpInstallDestinations() { Json::Value destinations = Json::arrayValue; - auto installGens = this->GT->Makefile->GetInstallGenerators(); - for (auto iGen : installGens) { - auto itGen = dynamic_cast<cmInstallTargetGenerator*>(iGen); - if (itGen != nullptr && itGen->GetTarget() == this->GT) { - destinations.append(this->DumpInstallDestination(itGen)); - } + auto installGens = this->GT->Target->GetInstallGenerators(); + for (auto itGen : installGens) { + destinations.append(this->DumpInstallDestination(itGen)); } return destinations; } @@ -1190,16 +1305,16 @@ Json::Value Target::DumpLinkCommandFragments() } Json::Value Target::DumpCommandFragments( - std::vector<BT<std::string>> const& frags) + std::vector<JBT<std::string>> const& frags) { Json::Value commandFragments = Json::arrayValue; - for (BT<std::string> const& f : frags) { + for (JBT<std::string> const& f : frags) { commandFragments.append(this->DumpCommandFragment(f)); } return commandFragments; } -Json::Value Target::DumpCommandFragment(BT<std::string> const& frag, +Json::Value Target::DumpCommandFragment(JBT<std::string> const& frag, std::string const& role) { Json::Value fragment = Json::objectValue; diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx index 782f746..8fcf1ac 100644 --- a/Source/cmFindProgramCommand.cxx +++ b/Source/cmFindProgramCommand.cxx @@ -4,6 +4,7 @@ #include "cmMakefile.h" #include "cmStateTypes.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -71,7 +72,7 @@ struct cmFindProgramHelper bool CheckDirectoryForName(std::string const& path, std::string const& name) { for (std::string const& ext : this->Extensions) { - if (!ext.empty() && cmSystemTools::StringEndsWith(name, ext.c_str())) { + if (!ext.empty() && cmHasSuffix(name, ext)) { continue; } this->TestNameExt = name; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 38f34ac..d9e5e71 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -4192,7 +4192,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/"); @@ -5219,7 +5219,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) { @@ -5603,8 +5603,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); @@ -5659,15 +5660,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 diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 7b8ffc5..88da5eb 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -337,15 +337,16 @@ bool cmGlobalGenerator::CheckTargetsForType() const bool failed = false; for (cmLocalGenerator* generator : this->LocalGenerators) { for (cmGeneratorTarget* target : generator->GetGeneratorTargets()) { - std::vector<std::string> configs; - target->Makefile->GetConfigurations(configs); - if (configs.empty()) { - configs.emplace_back(); - } + if (target->GetType() == cmStateEnums::EXECUTABLE && + target->GetPropertyAsBool("WIN32_EXECUTABLE")) { + std::vector<std::string> configs; + target->Makefile->GetConfigurations(configs); + if (configs.empty()) { + configs.emplace_back(); + } - for (std::string const& config : configs) { - if (target->GetLinkerLanguage(config) == "Swift") { - if (target->GetPropertyAsBool("WIN32_EXECUTABLE")) { + for (std::string const& config : configs) { + if (target->GetLinkerLanguage(config) == "Swift") { this->GetCMakeInstance()->IssueMessage( MessageType::FATAL_ERROR, "WIN32_EXECUTABLE property is not supported on Swift " diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index bad715d..0b68966 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -415,14 +415,6 @@ void cmGlobalNinjaGenerator::WriteDefault(std::ostream& os, cmGlobalNinjaGenerator::cmGlobalNinjaGenerator(cmake* cm) : cmGlobalCommonGenerator(cm) - , UsingGCCOnWindows(false) - , ComputingUnknownDependencies(false) - , PolicyCMP0058(cmPolicies::WARN) - , NinjaSupportsConsolePool(false) - , NinjaSupportsImplicitOuts(false) - , NinjaSupportsManifestRestat(false) - , NinjaSupportsMultilineDepfile(false) - , NinjaSupportsDyndeps(0) { #ifdef _WIN32 cm->GetState()->SetWindowsShell(true); @@ -556,14 +548,22 @@ void cmGlobalNinjaGenerator::CheckNinjaFeatures() this->NinjaSupportsMultilineDepfile = !cmSystemTools::VersionCompare( cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), RequiredNinjaVersionForMultilineDepfile().c_str()); - { + this->NinjaSupportsDyndeps = !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), + RequiredNinjaVersionForDyndeps().c_str()); + if (!this->NinjaSupportsDyndeps) { + // The ninja version number is not new enough to have upstream support. // Our ninja branch adds ".dyndep-#" to its version number, // where '#' is a feature-specific version number. Extract it. static std::string const k_DYNDEP_ = ".dyndep-"; std::string::size_type pos = this->NinjaVersion.find(k_DYNDEP_); if (pos != std::string::npos) { const char* fv = &this->NinjaVersion[pos + k_DYNDEP_.size()]; - cmSystemTools::StringToULong(fv, &this->NinjaSupportsDyndeps); + unsigned long dyndep = 0; + cmSystemTools::StringToULong(fv, &dyndep); + if (dyndep == 1) { + this->NinjaSupportsDyndeps = true; + } } } } @@ -580,37 +580,25 @@ bool cmGlobalNinjaGenerator::CheckLanguages( bool cmGlobalNinjaGenerator::CheckFortran(cmMakefile* mf) const { - if (this->NinjaSupportsDyndeps == 1) { + if (this->NinjaSupportsDyndeps) { return true; } std::ostringstream e; - if (this->NinjaSupportsDyndeps == 0) { - /* clang-format off */ - e << - "The Ninja generator does not support Fortran using Ninja version\n" - " " + this->NinjaVersion + "\n" - "due to lack of required features. " - "Kitware has implemented the required features but as of this version " - "of CMake they have not been integrated to upstream ninja. " - "Pending integration, Kitware maintains a branch at:\n" - " https://github.com/Kitware/ninja/tree/features-for-fortran#readme\n" - "with the required features. " - "One may build ninja from that branch to get support for Fortran." - ; - /* clang-format on */ - } else { - /* clang-format off */ - e << - "The Ninja generator in this version of CMake does not support Fortran " - "using Ninja version\n" - " " + this->NinjaVersion + "\n" - "because its 'dyndep' feature version is " << - this->NinjaSupportsDyndeps << ". " - "This version of CMake is aware only of 'dyndep' feature version 1." - ; - /* clang-format on */ - } + /* clang-format off */ + e << + "The Ninja generator does not support Fortran using Ninja version\n" + " " + this->NinjaVersion + "\n" + "due to lack of required features. " + "Kitware has implemented the required features and they have been " + "merged to upstream ninja for inclusion in Ninja 1.10 and higher. " + "As of this version of CMake, Ninja 1.10 has not been released. " + "Meanwhile, Kitware maintains a branch of Ninja at:\n" + " https://github.com/Kitware/ninja/tree/features-for-fortran#readme\n" + "with the required features. " + "One may build ninja from that branch to get support for Fortran." + ; + /* clang-format on */ mf->IssueMessage(MessageType::FATAL_ERROR, e.str()); cmSystemTools::SetFatalErrorOccured(); return false; diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index 99afc1d..db64031 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -322,6 +322,7 @@ public: { return "1.9"; } + static std::string RequiredNinjaVersionForDyndeps() { return "1.10"; } bool SupportsConsolePool() const; bool SupportsImplicitOuts() const; bool SupportsManifestRestat() const; @@ -402,7 +403,7 @@ private: /// The set of dependencies to add to the "all" target. cmNinjaDeps AllDependencies; - bool UsingGCCOnWindows; + bool UsingGCCOnWindows = false; /// The set of custom commands we have seen. std::set<cmCustomCommand const*> CustomCommands; @@ -412,8 +413,8 @@ private: /// Whether we are collecting known build outputs and needed /// dependencies to determine unknown dependencies. - bool ComputingUnknownDependencies; - cmPolicies::PolicyStatus PolicyCMP0058; + bool ComputingUnknownDependencies = false; + cmPolicies::PolicyStatus PolicyCMP0058 = cmPolicies::WARN; /// The combined explicit dependencies of custom build commands std::set<std::string> CombinedCustomCommandExplicitDependencies; @@ -435,11 +436,11 @@ private: std::string NinjaCommand; std::string NinjaVersion; - bool NinjaSupportsConsolePool; - bool NinjaSupportsImplicitOuts; - bool NinjaSupportsManifestRestat; - bool NinjaSupportsMultilineDepfile; - unsigned long NinjaSupportsDyndeps; + bool NinjaSupportsConsolePool = false; + bool NinjaSupportsImplicitOuts = false; + bool NinjaSupportsManifestRestat = false; + bool NinjaSupportsMultilineDepfile = false; + bool NinjaSupportsDyndeps = false; private: void InitOutputPathPrefix(); diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 8401efb..bead0e3 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -8,7 +8,9 @@ #include "cmMakefile.h" #include "cmMessageType.h" #include "cmState.h" +#include "cmStringAlgorithms.h" #include "cmUuid.h" +#include "cm_string_view.hxx" #include "cmake.h" #include "cmsys/Encoding.hxx" @@ -432,16 +434,15 @@ void cmGlobalVisualStudio7Generator::WriteTargetDepends( void cmGlobalVisualStudio7Generator::WriteFolders(std::ostream& fout) { - const char* prefix = "CMAKE_FOLDER_GUID_"; - const std::string::size_type skip_prefix = strlen(prefix); + cm::string_view const prefix = "CMAKE_FOLDER_GUID_"; std::string guidProjectTypeFolder = "2150E333-8FDC-42A3-9474-1A3956D46DE8"; for (auto const& iter : VisualStudioFolders) { std::string fullName = iter.first; std::string guid = this->GetGUID(fullName); std::replace(fullName.begin(), fullName.end(), '/', '\\'); - if (cmSystemTools::StringStartsWith(fullName.c_str(), prefix)) { - fullName = fullName.substr(skip_prefix); + if (cmHasPrefix(fullName, prefix)) { + fullName = fullName.substr(prefix.size()); } std::string nameOnly = cmSystemTools::GetFilenameName(fullName); diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index aca7268..5349a9d 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -43,11 +43,13 @@ static cmInstallTargetGenerator* CreateInstallTargetGenerator( target.SetHaveInstallRule(true); const char* component = namelink ? args.GetNamelinkComponent().c_str() : args.GetComponent().c_str(); - return new cmInstallTargetGenerator( + auto g = new cmInstallTargetGenerator( target.GetName(), destination.c_str(), impLib, args.GetPermissions().c_str(), args.GetConfigurations(), component, message, args.GetExcludeFromAll(), args.GetOptional() || forceOpt, backtrace); + target.AddInstallGenerator(g); + return g; } static cmInstallTargetGenerator* CreateInstallTargetGenerator( diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h index 6450c62..d71ff49 100644 --- a/Source/cmLinkItem.h +++ b/Source/cmLinkItem.h @@ -87,7 +87,7 @@ struct cmOptionalLinkInterface : public cmLinkInterface bool LibrariesDone = false; bool AllDone = false; bool Exists = false; - const char* ExplicitLibraries = nullptr; + bool Explicit = false; }; struct cmHeadToLinkInterfaceMap diff --git a/Source/cmLinkLineComputer.cxx b/Source/cmLinkLineComputer.cxx index 8746b35..4430f97 100644 --- a/Source/cmLinkLineComputer.cxx +++ b/Source/cmLinkLineComputer.cxx @@ -63,6 +63,7 @@ std::string cmLinkLineComputer::ComputeLinkLibs(cmComputeLinkInformation& cli) continue; } if (item.IsPath) { + linkLibs += cli.GetLibLinkFileFlag(); linkLibs += this->ConvertToOutputFormat(this->ConvertToLinkReference(item.Value)); } else { diff --git a/Source/cmNewLineStyle.cxx b/Source/cmNewLineStyle.cxx index 3f6523e..1ff741e 100644 --- a/Source/cmNewLineStyle.cxx +++ b/Source/cmNewLineStyle.cxx @@ -41,7 +41,7 @@ bool cmNewLineStyle::ReadFromArguments(const std::vector<std::string>& args, return true; } -const std::string cmNewLineStyle::GetCharacters() const +std::string cmNewLineStyle::GetCharacters() const { switch (NewLineStyle) { case Invalid: diff --git a/Source/cmNewLineStyle.h b/Source/cmNewLineStyle.h index f1a7bc6..ab9002e 100644 --- a/Source/cmNewLineStyle.h +++ b/Source/cmNewLineStyle.h @@ -30,7 +30,7 @@ public: bool ReadFromArguments(const std::vector<std::string>& args, std::string& errorString); - const std::string GetCharacters() const; + std::string GetCharacters() const; private: Style NewLineStyle = Invalid; diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index 2aefe8f..0801c24 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -1894,7 +1894,7 @@ bool cmQtAutoMocUic::Init(cmMakefile* makefile) std::list<std::string>::iterator it = includes.begin(); while (it != includes.end()) { std::string const& path = *it; - if (cmSystemTools::StringStartsWith(path, ppath->c_str())) { + if (cmHasPrefix(path, *ppath)) { MocConst_.IncludePaths.push_back(path); it = includes.erase(it); } else { diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index c5de742..8fcb710 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -378,8 +378,7 @@ void cmServerProtocol1::HandleCMakeFileChanges(const std::string& path, SendSignal(kFILE_CHANGE_SIGNAL, obj); } -const cmServerResponse cmServerProtocol1::Process( - const cmServerRequest& request) +cmServerResponse cmServerProtocol1::Process(const cmServerRequest& request) { assert(this->m_State >= STATE_ACTIVE); diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h index 2f55a20..5da4344 100644 --- a/Source/cmServerProtocol.h +++ b/Source/cmServerProtocol.h @@ -80,7 +80,7 @@ public: virtual std::pair<int, int> ProtocolVersion() const = 0; virtual bool IsExperimental() const = 0; - virtual const cmServerResponse Process(const cmServerRequest& request) = 0; + virtual cmServerResponse Process(const cmServerRequest& request) = 0; bool Activate(cmServer* server, const cmServerRequest& request, std::string* errorMessage); @@ -106,7 +106,7 @@ class cmServerProtocol1 : public cmServerProtocol public: std::pair<int, int> ProtocolVersion() const override; bool IsExperimental() const override; - const cmServerResponse Process(const cmServerRequest& request) override; + cmServerResponse Process(const cmServerRequest& request) override; private: bool DoActivate(const cmServerRequest& request, diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx index 5cdacaa..ffdd0ce 100644 --- a/Source/cmSourceGroupCommand.cxx +++ b/Source/cmSourceGroupCommand.cxx @@ -9,6 +9,7 @@ #include "cmMakefile.h" #include "cmSourceGroup.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" namespace { @@ -54,7 +55,7 @@ bool rootIsPrefix(const std::string& root, const std::vector<std::string>& files, std::string& error) { for (std::string const& file : files) { - if (!cmSystemTools::StringStartsWith(file, root.c_str())) { + if (!cmHasPrefix(file, root)) { error = "ROOT: " + root + " is not a prefix of file: " + file; return false; } @@ -63,15 +64,6 @@ bool rootIsPrefix(const std::string& root, return true; } -std::string prepareFilePathForTree(const std::string& path, - const std::string& currentSourceDir) -{ - if (!cmSystemTools::FileIsFullPath(path)) { - return cmSystemTools::CollapseFullPath(currentSourceDir + "/" + path); - } - return cmSystemTools::CollapseFullPath(path); -} - std::vector<std::string> prepareFilesPathsForTree( const std::vector<std::string>& filesPaths, const std::string& currentSourceDir) @@ -80,9 +72,11 @@ std::vector<std::string> prepareFilesPathsForTree( prepared.reserve(filesPaths.size()); for (auto const& filePath : filesPaths) { + std::string fullPath = + cmSystemTools::CollapseFullPath(filePath, currentSourceDir); // If provided file path is actually not a file, silently ignore it. - if (cmSystemTools::FileExists(filePath, /*isFile=*/true)) { - prepared.push_back(prepareFilePathForTree(filePath, currentSourceDir)); + if (cmSystemTools::FileExists(fullPath, /*isFile=*/true)) { + prepared.emplace_back(std::move(fullPath)); } } diff --git a/Source/cmStringAlgorithms.cxx b/Source/cmStringAlgorithms.cxx new file mode 100644 index 0000000..5deb9b0 --- /dev/null +++ b/Source/cmStringAlgorithms.cxx @@ -0,0 +1,73 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmStringAlgorithms.h" + +#include <algorithm> +#include <cstdio> + +namespace { +template <std::size_t N, typename T> +inline void MakeDigits(cm::string_view& view, char (&digits)[N], + const char* pattern, T value) +{ + int res = std::snprintf(digits, N, pattern, value); + if (res > 0 && res < static_cast<int>(N)) { + view = cm::string_view(digits, static_cast<std::size_t>(res)); + } +} +} // unnamed namespace + +cmAlphaNum::cmAlphaNum(int val) +{ + MakeDigits(View_, Digits_, "%i", val); +} + +cmAlphaNum::cmAlphaNum(unsigned int val) +{ + MakeDigits(View_, Digits_, "%u", val); +} + +cmAlphaNum::cmAlphaNum(long int val) +{ + MakeDigits(View_, Digits_, "%li", val); +} + +cmAlphaNum::cmAlphaNum(unsigned long int val) +{ + MakeDigits(View_, Digits_, "%lu", val); +} + +cmAlphaNum::cmAlphaNum(long long int val) +{ + MakeDigits(View_, Digits_, "%lli", val); +} + +cmAlphaNum::cmAlphaNum(unsigned long long int val) +{ + MakeDigits(View_, Digits_, "%llu", val); +} + +cmAlphaNum::cmAlphaNum(float val) +{ + MakeDigits(View_, Digits_, "%g", static_cast<double>(val)); +} + +cmAlphaNum::cmAlphaNum(double val) +{ + MakeDigits(View_, Digits_, "%g", val); +} + +std::string cmCatViews(std::initializer_list<cm::string_view> views) +{ + std::size_t total_size = 0; + for (cm::string_view const& view : views) { + total_size += view.size(); + } + + std::string result(total_size, '\0'); + std::string::iterator sit = result.begin(); + for (cm::string_view const& view : views) { + sit = std::copy_n(view.data(), view.size(), sit); + } + return result; +} diff --git a/Source/cmStringAlgorithms.h b/Source/cmStringAlgorithms.h index 149e0ad..cdb494f 100644 --- a/Source/cmStringAlgorithms.h +++ b/Source/cmStringAlgorithms.h @@ -7,120 +7,158 @@ #include "cmRange.h" #include "cm_string_view.hxx" -#include <algorithm> -#include <iterator> +#include <initializer_list> #include <sstream> #include <string.h> #include <string> #include <utility> #include <vector> +/** String range type. */ typedef cmRange<std::vector<std::string>::const_iterator> cmStringRange; +/** Callable string comparison struct. */ struct cmStrCmp { - cmStrCmp(const char* test) - : m_test(test) - { - } - cmStrCmp(std::string test) - : m_test(std::move(test)) + cmStrCmp(std::string str) + : Test_(std::move(str)) { } - bool operator()(const std::string& input) const { return m_test == input; } - - bool operator()(const char* input) const - { - return strcmp(input, m_test.c_str()) == 0; - } + bool operator()(cm::string_view sv) const { return Test_ == sv; } private: - const std::string m_test; + std::string const Test_; }; +/** Joins elements of a range with separator into a single string. */ template <typename Range> -std::string cmJoin(Range const& r, const char* delimiter) +std::string cmJoin(Range const& rng, cm::string_view separator) { - if (r.empty()) { + if (rng.empty()) { return std::string(); } - std::ostringstream os; - typedef typename Range::value_type ValueType; - typedef typename Range::const_iterator InputIt; - const InputIt first = r.begin(); - InputIt last = r.end(); - --last; - std::copy(first, last, std::ostream_iterator<ValueType>(os, delimiter)); - - os << *last; + std::ostringstream os; + auto it = rng.begin(); + auto const end = rng.end(); + os << *it; + while (++it != end) { + os << separator << *it; + } return os.str(); } -template <typename Range> -std::string cmJoin(Range const& r, std::string const& delimiter) +/** Concatenate string pieces into a single string. */ +std::string cmCatViews(std::initializer_list<cm::string_view> views); + +/** Utility class for cmStrCat. */ +class cmAlphaNum +{ +public: + cmAlphaNum(cm::string_view view) + : View_(view) + { + } + cmAlphaNum(std::string const& str) + : View_(str) + { + } + cmAlphaNum(const char* str) + : View_(str) + { + } + cmAlphaNum(char ch) + : View_(Digits_, 1) + { + Digits_[0] = ch; + } + cmAlphaNum(int val); + cmAlphaNum(unsigned int val); + cmAlphaNum(long int val); + cmAlphaNum(unsigned long int val); + cmAlphaNum(long long int val); + cmAlphaNum(unsigned long long int val); + cmAlphaNum(float val); + cmAlphaNum(double val); + + cm::string_view View() const { return View_; } + +private: + cm::string_view View_; + char Digits_[32]; +}; + +/** Concatenate string pieces and numbers into a single string. */ +template <typename... AV> +inline std::string cmStrCat(cmAlphaNum const& a, cmAlphaNum const& b, + AV const&... args) { - return cmJoin(r, delimiter.c_str()); + return cmCatViews( + { a.View(), b.View(), static_cast<cmAlphaNum const&>(args).View()... }); } +/** Joins wrapped elements of a range with separator into a single string. */ template <typename Range> -std::string cmWrap(std::string const& prefix, Range const& r, - std::string const& suffix, std::string const& sep) +std::string cmWrap(cm::string_view prefix, Range const& rng, + cm::string_view suffix, cm::string_view sep) { - if (r.empty()) { + if (rng.empty()) { return std::string(); } - return prefix + cmJoin(r, suffix + sep + prefix) + suffix; + return cmCatViews( + { prefix, cmJoin(rng, cmCatViews({ suffix, sep, prefix })), suffix }); } +/** Joins wrapped elements of a range with separator into a single string. */ template <typename Range> -std::string cmWrap(char prefix, Range const& r, char suffix, - std::string const& sep) +std::string cmWrap(char prefix, Range const& rng, char suffix, + cm::string_view sep) { - return cmWrap(std::string(1, prefix), r, std::string(1, suffix), sep); + return cmWrap(cm::string_view(&prefix, 1), rng, cm::string_view(&suffix, 1), + sep); } -/** Returns true if string @a str starts with the character @a prefix. **/ +/** Returns true if string @a str starts with the character @a prefix. */ inline bool cmHasPrefix(cm::string_view str, char prefix) { return !str.empty() && (str.front() == prefix); } -/** Returns true if string @a str starts with string @a prefix. **/ +/** Returns true if string @a str starts with string @a prefix. */ inline bool cmHasPrefix(cm::string_view str, cm::string_view prefix) { return str.compare(0, prefix.size(), prefix) == 0; } -/** Returns true if string @a str starts with string @a prefix. **/ +/** Returns true if string @a str starts with string @a prefix. */ template <size_t N> inline bool cmHasLiteralPrefix(cm::string_view str, const char (&prefix)[N]) { return cmHasPrefix(str, cm::string_view(prefix, N - 1)); } -/** Returns true if string @a str ends with the character @a suffix. **/ +/** Returns true if string @a str ends with the character @a suffix. */ inline bool cmHasSuffix(cm::string_view str, char suffix) { return !str.empty() && (str.back() == suffix); } -/** Returns true if string @a str ends with string @a suffix. **/ +/** Returns true if string @a str ends with string @a suffix. */ inline bool cmHasSuffix(cm::string_view str, cm::string_view suffix) { return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; } -/** Returns true if string @a str ends with string @a suffix. **/ +/** Returns true if string @a str ends with string @a suffix. */ template <size_t N> inline bool cmHasLiteralSuffix(cm::string_view str, const char (&suffix)[N]) { return cmHasSuffix(str, cm::string_view(suffix, N - 1)); } -/** Removes an existing suffix character of from the string @a str. **/ +/** Removes an existing suffix character of from the string @a str. */ inline void cmStripSuffixIfExists(std::string& str, char suffix) { if (cmHasSuffix(str, suffix)) { @@ -128,7 +166,7 @@ inline void cmStripSuffixIfExists(std::string& str, char suffix) } } -/** Removes an existing suffix string of from the string @a str. **/ +/** Removes an existing suffix string of from the string @a str. */ inline void cmStripSuffixIfExists(std::string& str, cm::string_view suffix) { if (cmHasSuffix(str, suffix)) { diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index beccfce..7ca2391 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -180,6 +180,7 @@ public: std::vector<cmCustomCommand> PreBuildCommands; std::vector<cmCustomCommand> PreLinkCommands; std::vector<cmCustomCommand> PostBuildCommands; + std::vector<cmInstallTargetGenerator*> InstallGenerators; std::set<std::string> SystemIncludeDirectories; cmTarget::LinkLibraryVectorType OriginalLinkLibraries; std::vector<std::string> IncludeDirectoriesEntries; @@ -873,6 +874,17 @@ void cmTarget::SetHaveInstallRule(bool hir) impl->HaveInstallRule = hir; } +void cmTarget::AddInstallGenerator(cmInstallTargetGenerator* g) +{ + impl->InstallGenerators.emplace_back(g); +} + +std::vector<cmInstallTargetGenerator*> const& cmTarget::GetInstallGenerators() + const +{ + return impl->InstallGenerators; +} + bool cmTarget::GetIsGeneratorProvided() const { return impl->IsGeneratorProvided; diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 4e5141b..2b75879 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -21,6 +21,7 @@ class cmCustomCommand; class cmGlobalGenerator; +class cmInstallTargetGenerator; class cmMakefile; class cmMessenger; class cmPropertyMap; @@ -147,6 +148,9 @@ public: bool GetHaveInstallRule() const; void SetHaveInstallRule(bool hir); + void AddInstallGenerator(cmInstallTargetGenerator* g); + std::vector<cmInstallTargetGenerator*> const& GetInstallGenerators() const; + /** * Get/Set whether this target was auto-created by a generator. */ diff --git a/Source/cmTargetDepend.h b/Source/cmTargetDepend.h index 5ea0085..4ca78fa 100644 --- a/Source/cmTargetDepend.h +++ b/Source/cmTargetDepend.h @@ -31,7 +31,7 @@ public: operator cmGeneratorTarget const*() const { return this->Target; } cmGeneratorTarget const* operator->() const { return this->Target; } cmGeneratorTarget const& operator*() const { return *this->Target; } - friend bool operator<(cmTargetDepend l, cmTargetDepend r) + friend bool operator<(cmTargetDepend const& l, cmTargetDepend const& r) { return l.Target < r.Target; } diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 4a151b3..ed6e4d9 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1235,8 +1235,11 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValues( if (this->IPOEnabledConfigurations.count(config) > 0) { e1.Element("WholeProgramOptimization", "true"); } - if (this->SpectreMitigationConfigurations.count(config) > 0) { - e1.Element("SpectreMitigation", "Spectre"); + { + auto s = this->SpectreMitigation.find(config); + if (s != this->SpectreMitigation.end()) { + e1.Element("SpectreMitigation", s->second); + } } } @@ -2766,8 +2769,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( } } - if (clOptions.HasFlag("SpectreMitigation")) { - this->SpectreMitigationConfigurations.insert(configName); + if (const char* s = clOptions.GetFlag("SpectreMitigation")) { + this->SpectreMitigation[configName] = s; clOptions.RemoveFlag("SpectreMitigation"); } diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 860b809..6607e77 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -215,7 +215,7 @@ private: unsigned int NsightTegraVersion[4]; bool TargetCompileAsWinRT; std::set<std::string> IPOEnabledConfigurations; - std::set<std::string> SpectreMitigationConfigurations; + std::map<std::string, std::string> SpectreMitigation; cmGlobalVisualStudio10Generator* const GlobalGenerator; cmLocalVisualStudio10Generator* const LocalGenerator; std::set<std::string> CSharpCustomCommandNames; diff --git a/Source/cmVisualStudioSlnParser.cxx b/Source/cmVisualStudioSlnParser.cxx index 9353276..3e7e142 100644 --- a/Source/cmVisualStudioSlnParser.cxx +++ b/Source/cmVisualStudioSlnParser.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmVisualStudioSlnParser.h" +#include "cmStringAlgorithms.h" #include "cmSystemTools.h" #include "cmVisualStudioSlnData.h" #include "cmsys/FStream.hxx" @@ -192,8 +193,8 @@ bool cmVisualStudioSlnParser::State::Process( assert(!line.IsComment()); switch (this->Stack.top()) { case FileStateStart: - if (!cmSystemTools::StringStartsWith( - line.GetTag().c_str(), "Microsoft Visual Studio Solution File")) { + if (!cmHasLiteralPrefix(line.GetTag(), + "Microsoft Visual Studio Solution File")) { result.SetError(ResultErrorInputStructure, this->GetCurrentLine()); return false; } diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 3b4a6c0..a81b7e4 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -28,6 +28,7 @@ #include "cmUtils.hxx" #include "cmVersionConfig.h" #include "cmWorkingDirectory.h" +#include "cm_string_view.hxx" #include "cm_sys_stat.h" #if defined(CMAKE_BUILD_WITH_CMAKE) @@ -132,22 +133,15 @@ static void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/, } cmake::cmake(Role role, cmState::Mode mode) + : FileTimeCache(cm::make_unique<cmFileTimeCache>()) +#ifdef CMAKE_BUILD_WITH_CMAKE + , VariableWatch(cm::make_unique<cmVariableWatch>()) +#endif + , State(cm::make_unique<cmState>()) + , Messenger(cm::make_unique<cmMessenger>()) { - this->Trace = false; - this->TraceExpand = false; - this->WarnUninitialized = false; - this->WarnUnused = false; - this->WarnUnusedCli = true; - this->CheckSystemVars = false; - this->DebugOutput = false; - this->DebugTryCompile = false; - this->ClearBuildSystem = false; - this->FileTimeCache = cm::make_unique<cmFileTimeCache>(); - - this->State = cm::make_unique<cmState>(); this->State->SetMode(mode); this->CurrentSnapshot = this->State->CreateBaseSnapshot(); - this->Messenger = cm::make_unique<cmMessenger>(); #ifdef __APPLE__ struct rlimit rlp; @@ -159,16 +153,6 @@ cmake::cmake(Role role, cmState::Mode mode) } #endif - this->GlobalGenerator = nullptr; - this->GeneratorInstanceSet = false; - this->GeneratorPlatformSet = false; - this->GeneratorToolsetSet = false; - this->CurrentWorkingMode = NORMAL_MODE; - -#ifdef CMAKE_BUILD_WITH_CMAKE - this->VariableWatch = cm::make_unique<cmVariableWatch>(); -#endif - this->AddDefaultGenerators(); this->AddDefaultExtraGenerators(); if (role == RoleScript || role == RoleProject) { @@ -188,32 +172,25 @@ cmake::cmake(Role role, cmState::Mode mode) // Set up a list of source and header extensions. // These are used to find files when the extension is not given. { - auto fillExts = [](FileExtensions& exts, - std::initializer_list<const char*> extList) { + auto setupExts = [](FileExtensions& exts, + std::initializer_list<cm::string_view> extList) { // Fill ordered vector exts.ordered.reserve(extList.size()); - for (const char* ext : extList) { + for (cm::string_view ext : extList) { exts.ordered.emplace_back(ext); }; // Fill unordered set exts.unordered.insert(exts.ordered.begin(), exts.ordered.end()); }; - // Source extensions // The "c" extension MUST precede the "C" extension. - fillExts(this->SourceFileExtensions, - { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "m", "M", "mm" }); - - // Header extensions - fillExts(this->HeaderFileExtensions, - { "h", "hh", "h++", "hm", "hpp", "hxx", "in", "txx" }); - - // Cuda extensions - fillExts(this->CudaFileExtensions, { "cu" }); - - // Fortran extensions - fillExts(this->FortranFileExtensions, - { "f", "F", "for", "f77", "f90", "f95", "f03" }); + setupExts(this->SourceFileExtensions, + { "c", "C", "c++", "cc", "cpp", "cxx", "cu", "m", "M", "mm" }); + setupExts(this->HeaderFileExtensions, + { "h", "hh", "h++", "hm", "hpp", "hxx", "in", "txx" }); + setupExts(this->CudaFileExtensions, { "cu" }); + setupExts(this->FortranFileExtensions, + { "f", "F", "for", "f77", "f90", "f95", "f03" }); } } @@ -620,7 +597,7 @@ void cmake::LoadEnvironmentPresets() this->EnvironmentGenerator = envGenVar; } - auto readGeneratorVar = [&](std::string name, std::string& key) { + auto readGeneratorVar = [&](std::string const& name, std::string& key) { std::string varValue; if (cmSystemTools::GetEnv(name, varValue)) { if (hasEnvironmentGenerator) { @@ -2031,8 +2008,7 @@ void cmake::AppendGlobalGeneratorsDocumentation( for (cmGlobalGeneratorFactory* g : this->Generators) { cmDocumentationEntry e; g->GetDocumentation(e); - if (!foundDefaultOne && - cmSystemTools::StringStartsWith(e.Name, defaultName.c_str())) { + if (!foundDefaultOne && cmHasPrefix(e.Name, defaultName)) { e.CustomNamePrefix = '*'; foundDefaultOne = true; } diff --git a/Source/cmake.h b/Source/cmake.h index 6aa00e1..92494ae 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -509,14 +509,14 @@ protected: void AddDefaultGenerators(); void AddDefaultExtraGenerators(); - cmGlobalGenerator* GlobalGenerator; + cmGlobalGenerator* GlobalGenerator = nullptr; std::map<std::string, DiagLevel> DiagLevels; std::string GeneratorInstance; std::string GeneratorPlatform; std::string GeneratorToolset; - bool GeneratorInstanceSet; - bool GeneratorPlatformSet; - bool GeneratorToolsetSet; + bool GeneratorInstanceSet = false; + bool GeneratorPlatformSet = false; + bool GeneratorToolsetSet = false; //! read in a cmake list file to initialize the cache void ReadListFile(const std::vector<std::string>& args, @@ -543,14 +543,14 @@ protected: private: ProgressCallbackType ProgressCallback; - WorkingMode CurrentWorkingMode; - bool DebugOutput; - bool Trace; - bool TraceExpand; - bool WarnUninitialized; - bool WarnUnused; - bool WarnUnusedCli; - bool CheckSystemVars; + WorkingMode CurrentWorkingMode = NORMAL_MODE; + bool DebugOutput = false; + bool Trace = false; + bool TraceExpand = false; + bool WarnUninitialized = false; + bool WarnUnused = false; + bool WarnUnusedCli = true; + bool CheckSystemVars = false; std::map<std::string, bool> UsedCliVariables; std::string CMakeEditCommand; std::string CXXEnvironment; @@ -564,8 +564,8 @@ private: FileExtensions HeaderFileExtensions; FileExtensions CudaFileExtensions; FileExtensions FortranFileExtensions; - bool ClearBuildSystem; - bool DebugTryCompile; + bool ClearBuildSystem = false; + bool DebugTryCompile = false; std::unique_ptr<cmFileTimeCache> FileTimeCache; std::string GraphVizFile; InstalledFilesMap InstalledFiles; |