From 9b334397f55b70689ff1d8f7d6767a34834e85b6 Mon Sep 17 00:00:00 2001
From: Sebastian Holtermann <sebholt@xwmw.org>
Date: Thu, 22 Aug 2019 16:34:40 +0200
Subject: Source sweep: Use cmStrCat for string concatenation

This patch is generated by a python script that uses regular expressions to
search for string concatenation patterns of the kind

```
std::string str = <ARG0>;
str += <ARG1>;
str += <ARG2>;
...
```

and replaces them with a single `cmStrCat` call

```
std::string str = cmStrCat(<ARG0>, <ARG1>, <ARG2>, ...);
```

If any `<ARGX>` is itself a concatenated string of the kind

```
a + b + c + ...;
```

then `<ARGX>` is split into multiple arguments for the `cmStrCat` call.

If there's a sequence of literals in the `<ARGX>`, then all literals in the
sequence are concatenated and merged into a single literal argument for
the `cmStrCat` call.

Single character strings are converted to single char arguments for
the `cmStrCat` call.

`std::to_string(...)` wrappings are removed from `cmStrCat` arguments,
because it supports numeric types as well as string types.

`arg.substr(x)` arguments to `cmStrCat` are replaced with
`cm::string_view(arg).substr(x)`
---
 Source/CPack/IFW/cmCPackIFWGenerator.cxx       |   7 +-
 Source/CPack/IFW/cmCPackIFWInstaller.cxx       |   4 +-
 Source/CPack/WiX/cmCPackWIXGenerator.cxx       |   8 +-
 Source/CPack/cmCPackArchiveGenerator.cxx       |   4 +-
 Source/CPack/cmCPackBundleGenerator.cxx        |  10 +-
 Source/CPack/cmCPackComponentGroup.cxx         |   5 +-
 Source/CPack/cmCPackCygwinBinaryGenerator.cxx  |  10 +-
 Source/CPack/cmCPackCygwinSourceGenerator.cxx  |  32 ++--
 Source/CPack/cmCPackDebGenerator.cxx           |  28 ++-
 Source/CPack/cmCPackDragNDropGenerator.cxx     |  16 +-
 Source/CPack/cmCPackGenerator.cxx              |  41 ++---
 Source/CPack/cmCPackNSISGenerator.cxx          |  68 ++++----
 Source/CPack/cmCPackOSXX11Generator.cxx        |  42 ++---
 Source/CPack/cmCPackPKGGenerator.cxx           |  46 ++---
 Source/CPack/cmCPackPackageMakerGenerator.cxx  |  48 +++--
 Source/CPack/cmCPackProductBuildGenerator.cxx  |  23 +--
 Source/CPack/cmCPackRPMGenerator.cxx           |   6 +-
 Source/CPack/cpack.cxx                         |   4 +-
 Source/CTest/cmCTestBuildAndTestHandler.cxx    |   6 +-
 Source/CTest/cmCTestBuildCommand.cxx           |   6 +-
 Source/CTest/cmCTestBuildHandler.cxx           |  31 ++--
 Source/CTest/cmCTestCVS.cxx                    |   5 +-
 Source/CTest/cmCTestConfigureCommand.cxx       |   5 +-
 Source/CTest/cmCTestCoverageHandler.cxx        |  37 ++--
 Source/CTest/cmCTestCurl.cxx                   |   5 +-
 Source/CTest/cmCTestGIT.cxx                    |   4 +-
 Source/CTest/cmCTestLaunch.cxx                 |  31 +---
 Source/CTest/cmCTestRunTest.cxx                |  31 ++--
 Source/CTest/cmCTestSVN.cxx                    |   6 +-
 Source/CTest/cmCTestScriptHandler.cxx          |  33 ++--
 Source/CTest/cmCTestTestHandler.cxx            |  53 ++----
 Source/CTest/cmCTestUpdateHandler.cxx          |  19 +-
 Source/CTest/cmParseCacheCoverage.cxx          |   5 +-
 Source/CTest/cmParseGTMCoverage.cxx            |   4 +-
 Source/CTest/cmParseJacocoCoverage.cxx         |   4 +-
 Source/CTest/cmParseMumpsCoverage.cxx          |   4 +-
 Source/CTest/cmParsePHPCoverage.cxx            |   5 +-
 Source/CTest/cmProcess.cxx                     |   4 +-
 Source/CursesDialog/cmCursesMainForm.cxx       |   4 +-
 Source/QtDialog/FirstConfigure.cxx             |   8 +-
 Source/cmAddCustomCommandCommand.cxx           |   4 +-
 Source/cmAddCustomTargetCommand.cxx            |   4 +-
 Source/cmAddSubDirectoryCommand.cxx            |  14 +-
 Source/cmArchiveWrite.cxx                      |  86 +++++----
 Source/cmAuxSourceDirectoryCommand.cxx         |   8 +-
 Source/cmCPluginAPI.cxx                        |   8 +-
 Source/cmCTest.cxx                             |  29 ++--
 Source/cmCacheManager.cxx                      |  42 ++---
 Source/cmCommandArgumentParserHelper.cxx       |   4 +-
 Source/cmCommonTargetGenerator.cxx             |  20 +--
 Source/cmComputeLinkDepends.cxx                |   6 +-
 Source/cmComputeLinkInformation.cxx            |  93 ++++------
 Source/cmConfigureFileCommand.cxx              |   5 +-
 Source/cmCoreTryCompile.cxx                    |  10 +-
 Source/cmCreateTestSourceList.cxx              |  13 +-
 Source/cmCurl.cxx                              |   5 +-
 Source/cmCustomCommandGenerator.cxx            |   4 +-
 Source/cmDepends.cxx                           |   9 +-
 Source/cmDependsC.cxx                          |  23 +--
 Source/cmDependsFortran.cxx                    |  43 ++---
 Source/cmExecProgramCommand.cxx                |  11 +-
 Source/cmExportBuildAndroidMKGenerator.cxx     |   3 +-
 Source/cmExportBuildFileGenerator.cxx          |   9 +-
 Source/cmExportCommand.cxx                     |   7 +-
 Source/cmExportFileGenerator.cxx               |  17 +-
 Source/cmExportInstallAndroidMKGenerator.cxx   |   4 +-
 Source/cmExportInstallFileGenerator.cxx        |  18 +-
 Source/cmExportLibraryDependenciesCommand.cxx  |   7 +-
 Source/cmExprParserHelper.cxx                  |  12 +-
 Source/cmExternalMakefileProjectGenerator.cxx  |   5 +-
 Source/cmExtraCodeBlocksGenerator.cxx          |  33 ++--
 Source/cmExtraCodeLiteGenerator.cxx            |  14 +-
 Source/cmExtraEclipseCDT4Generator.cxx         |  39 ++---
 Source/cmExtraKateGenerator.cxx                |  22 +--
 Source/cmExtraSublimeTextGenerator.cxx         |  10 +-
 Source/cmFLTKWrapUICommand.cxx                 |  11 +-
 Source/cmFileAPI.cxx                           |   4 +-
 Source/cmFileCommand.cxx                       |  91 +++++-----
 Source/cmFileCopier.cxx                        |  21 +--
 Source/cmFileInstaller.cxx                     |  14 +-
 Source/cmFindBase.cxx                          |  12 +-
 Source/cmFindCommon.cxx                        |   7 +-
 Source/cmFindLibraryCommand.cxx                |  17 +-
 Source/cmFindPackageCommand.cxx                | 122 +++++--------
 Source/cmFindPathCommand.cxx                   |  16 +-
 Source/cmFindProgramCommand.cxx                |   3 +-
 Source/cmFortranParserImpl.cxx                 |  10 +-
 Source/cmFunctionCommand.cxx                   |   6 +-
 Source/cmGeneratorExpressionNode.cxx           |  14 +-
 Source/cmGeneratorTarget.cxx                   | 180 ++++++++-----------
 Source/cmGetDirectoryPropertyCommand.cxx       |   5 +-
 Source/cmGetPropertyCommand.cxx                |   6 +-
 Source/cmGhsMultiTargetGenerator.cxx           |  56 +++---
 Source/cmGlobVerificationManager.cxx           |   4 +-
 Source/cmGlobalGenerator.cxx                   | 163 +++++++----------
 Source/cmGlobalGhsMultiGenerator.cxx           |  65 +++----
 Source/cmGlobalMSYSMakefileGenerator.cxx       |   6 +-
 Source/cmGlobalNinjaGenerator.cxx              |  53 +++---
 Source/cmGlobalUnixMakefileGenerator3.cxx      | 115 +++++-------
 Source/cmGlobalVisualStudio10Generator.cxx     |  29 ++--
 Source/cmGlobalVisualStudio71Generator.cxx     |   6 +-
 Source/cmGlobalVisualStudio7Generator.cxx      |  31 ++--
 Source/cmGlobalVisualStudio8Generator.cxx      |  27 ++-
 Source/cmGlobalVisualStudioGenerator.cxx       |  15 +-
 Source/cmGlobalXCodeGenerator.cxx              | 197 ++++++++-------------
 Source/cmGraphVizWriter.cxx                    |  19 +-
 Source/cmIfCommand.cxx                         |   9 +-
 Source/cmIncludeCommand.cxx                    |  14 +-
 Source/cmIncludeDirectoryCommand.cxx           |   5 +-
 Source/cmInstallCommand.cxx                    |  21 +--
 Source/cmInstallExportAndroidMKGenerator.cxx   |  13 +-
 Source/cmInstallExportGenerator.cxx            |  18 +-
 Source/cmInstallFilesCommand.cxx               |   9 +-
 Source/cmInstallProgramsCommand.cxx            |   9 +-
 Source/cmInstallTargetGenerator.cxx            |  17 +-
 Source/cmLinkDirectoriesCommand.cxx            |   5 +-
 Source/cmListCommand.cxx                       |  14 +-
 Source/cmLoadCommandCommand.cxx                |  21 +--
 Source/cmLocalCommonGenerator.cxx              |  12 +-
 Source/cmLocalGenerator.cxx                    |  27 ++-
 Source/cmLocalGhsMultiGenerator.cxx            |  25 ++-
 Source/cmLocalNinjaGenerator.cxx               |   6 +-
 Source/cmLocalUnixMakefileGenerator3.cxx       | 178 +++++++++----------
 Source/cmLocalVisualStudio10Generator.cxx      |   3 +-
 Source/cmLocalVisualStudio7Generator.cxx       | 130 +++++---------
 Source/cmLocalXCodeGenerator.cxx               |   5 +-
 Source/cmMacroCommand.cxx                      |   4 +-
 Source/cmMakefile.cxx                          |  53 +++---
 Source/cmMakefileExecutableTargetGenerator.cxx |  61 +++----
 Source/cmMakefileLibraryTargetGenerator.cxx    |  73 ++++----
 Source/cmMakefileTargetGenerator.cxx           | 231 +++++++++++--------------
 Source/cmNinjaNormalTargetGenerator.cxx        |  92 ++++------
 Source/cmNinjaTargetGenerator.cxx              | 118 +++++--------
 Source/cmNinjaUtilityTargetGenerator.cxx       |   7 +-
 Source/cmOSXBundleGenerator.cxx                |  74 ++++----
 Source/cmOptionCommand.cxx                     |   4 +-
 Source/cmOrderDirectories.cxx                  |   8 +-
 Source/cmOutputRequiredFilesCommand.cxx        |   6 +-
 Source/cmProjectCommand.cxx                    |  13 +-
 Source/cmQTWrapCPPCommand.cxx                  |   7 +-
 Source/cmQTWrapUICommand.cxx                   |  19 +-
 Source/cmQtAutoGen.cxx                         |  20 +--
 Source/cmQtAutoGenGlobalInitializer.cxx        |  20 +--
 Source/cmQtAutoGenInitializer.cxx              |  67 +++----
 Source/cmQtAutoGenerator.cxx                   |   3 +-
 Source/cmQtAutoMocUic.cxx                      | 125 ++++++-------
 Source/cmQtAutoRcc.cxx                         |  78 +++------
 Source/cmScriptGenerator.cxx                   |  11 +-
 Source/cmSetPropertyCommand.cxx                |   5 +-
 Source/cmSetTargetPropertiesCommand.cxx        |   5 +-
 Source/cmSetTestsPropertiesCommand.cxx         |   4 +-
 Source/cmSourceFile.cxx                        |  10 +-
 Source/cmSourceFileLocation.cxx                |   3 +-
 Source/cmSourceGroup.cxx                       |   5 +-
 Source/cmSourceGroupCommand.cxx                |   9 +-
 Source/cmStringCommand.cxx                     |  11 +-
 Source/cmSubdirCommand.cxx                     |   5 +-
 Source/cmSystemTools.cxx                       |  87 ++++------
 Source/cmTarget.cxx                            |  52 ++----
 Source/cmTargetLinkLibrariesCommand.cxx        |  10 +-
 Source/cmTargetSourcesCommand.cxx              |   5 +-
 Source/cmTimestamp.cxx                         |   4 +-
 Source/cmTryRunCommand.cxx                     |  56 +++---
 Source/cmUseMangledMesaCommand.cxx             |  20 +--
 Source/cmUtilitySourceCommand.cxx              |  11 +-
 Source/cmVSSetupHelper.cxx                     |   4 +-
 Source/cmVariableRequiresCommand.cxx           |  12 +-
 Source/cmVisualStudio10TargetGenerator.cxx     |  86 ++++-----
 Source/cmVisualStudioGeneratorOptions.cxx      |   6 +-
 Source/cmWorkerPool.cxx                        |  21 +--
 Source/cmWriteFileCommand.cxx                  |   7 +-
 Source/cmXCodeScheme.cxx                       |   9 +-
 Source/cmake.cxx                               | 128 ++++++--------
 Source/cmakemain.cxx                           |   6 +-
 Source/cmcmd.cxx                               |  15 +-
 175 files changed, 1960 insertions(+), 2949 deletions(-)

diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
index f0fb37a..234da2f 100644
--- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx
+++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx
@@ -35,8 +35,7 @@ int cmCPackIFWGenerator::PackageFiles()
   this->Installer.GeneratePackageFiles();
 
   std::string ifwTLD = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  std::string ifwTmpFile = ifwTLD;
-  ifwTmpFile += "/IFWOutput.log";
+  std::string ifwTmpFile = cmStrCat(ifwTLD, "/IFWOutput.log");
 
   // Run repogen
   if (!this->Installer.RemoteRepositories.empty()) {
@@ -117,8 +116,8 @@ int cmCPackIFWGenerator::PackageFiles()
 
   // Run binary creator
   {
-    std::string ifwCmd = this->BinCreator;
-    ifwCmd += " -c " + this->toplevel + "/config/config.xml";
+    std::string ifwCmd =
+      cmStrCat(this->BinCreator, " -c ", this->toplevel, "/config/config.xml");
 
     if (!this->Installer.Resources.empty()) {
       ifwCmd += " -r ";
diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
index 5313dd0..b4bfea7 100644
--- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx
+++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx
@@ -193,8 +193,8 @@ void cmCPackIFWInstaller::ConfigureFromOptions()
     this->TargetDir = optIFW_TARGET_DIRECTORY;
   } else if (const char* optPACKAGE_INSTALL_DIRECTORY =
                this->GetOption("CPACK_PACKAGE_INSTALL_DIRECTORY")) {
-    this->TargetDir = "@ApplicationsDir@/";
-    this->TargetDir += optPACKAGE_INSTALL_DIRECTORY;
+    this->TargetDir =
+      cmStrCat("@ApplicationsDir@/", optPACKAGE_INSTALL_DIRECTORY);
   } else {
     this->TargetDir = "@RootDir@/usr/local";
   }
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index 5b01ae6..e960fab 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -11,6 +11,7 @@
 #include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmUuid.h"
+#include "cm_string_view.hxx"
 #include <algorithm>
 
 #include "cmWIXDirectoriesSourceWriter.h"
@@ -519,9 +520,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
     for (auto const& i : this->Components) {
       cmCPackComponent const& component = i.second;
 
-      std::string componentPath = toplevel;
-      componentPath += "/";
-      componentPath += component.Name;
+      std::string componentPath = cmStrCat(toplevel, '/', component.Name);
 
       std::string const componentFeatureId = "CM_C_" + component.Name;
 
@@ -1087,8 +1086,7 @@ std::string cmCPackWIXGenerator::CreateHashedId(
   cmCryptoHash sha1(cmCryptoHash::AlgoSHA1);
   std::string const hash = sha1.HashString(path);
 
-  std::string identifier;
-  identifier += hash.substr(0, 7) + "_";
+  std::string identifier = cmStrCat(cm::string_view(hash).substr(0, 7), '_');
 
   const size_t maxFileNameLength = 52;
   if (normalizedFilename.length() > maxFileNameLength) {
diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx
index 98fb29d..6c9c6b9 100644
--- a/Source/CPack/cmCPackArchiveGenerator.cxx
+++ b/Source/CPack/cmCPackArchiveGenerator.cxx
@@ -6,6 +6,7 @@
 #include "cmCPackGenerator.h"
 #include "cmCPackLog.h"
 #include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmWorkingDirectory.h"
 
@@ -71,8 +72,7 @@ int cmCPackArchiveGenerator::addOneComponentToArchive(
   }
   std::string filePrefix;
   if (this->IsOn("CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY")) {
-    filePrefix = this->GetOption("CPACK_PACKAGE_FILE_NAME");
-    filePrefix += "/";
+    filePrefix = cmStrCat(this->GetOption("CPACK_PACKAGE_FILE_NAME"), '/');
   }
   const char* installPrefix =
     this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
diff --git a/Source/CPack/cmCPackBundleGenerator.cxx b/Source/CPack/cmCPackBundleGenerator.cxx
index 213ce92..f58cc0a 100644
--- a/Source/CPack/cmCPackBundleGenerator.cxx
+++ b/Source/CPack/cmCPackBundleGenerator.cxx
@@ -41,9 +41,8 @@ int cmCPackBundleGenerator::InitializeInternal()
 
 const char* cmCPackBundleGenerator::GetPackagingInstallPrefix()
 {
-  this->InstallPrefix = "/";
-  this->InstallPrefix += this->GetOption("CPACK_BUNDLE_NAME");
-  this->InstallPrefix += ".app/Contents/Resources";
+  this->InstallPrefix = cmStrCat('/', this->GetOption("CPACK_BUNDLE_NAME"),
+                                 ".app/Contents/Resources");
 
   return this->InstallPrefix.c_str();
 }
@@ -191,9 +190,8 @@ int cmCPackBundleGenerator::SignBundle(const std::string& src_dir)
   if (!cpack_apple_cert_app.empty()) {
     std::string output;
     std::string bundle_path;
-    bundle_path = src_dir + "/";
-    bundle_path += this->GetOption("CPACK_BUNDLE_NAME");
-    bundle_path += ".app";
+    bundle_path =
+      cmStrCat(src_dir, '/', this->GetOption("CPACK_BUNDLE_NAME"), ".app");
 
     // A list of additional files to sign, ie. frameworks and plugins.
     const std::string sign_parameter =
diff --git a/Source/CPack/cmCPackComponentGroup.cxx b/Source/CPack/cmCPackComponentGroup.cxx
index f888a5f..9e05d86 100644
--- a/Source/CPack/cmCPackComponentGroup.cxx
+++ b/Source/CPack/cmCPackComponentGroup.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmCPackComponentGroup.h"
 
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <string>
@@ -14,9 +15,7 @@ unsigned long cmCPackComponent::GetInstalledSize(
   }
 
   for (std::string const& file : this->Files) {
-    std::string path = installDir;
-    path += '/';
-    path += file;
+    std::string path = cmStrCat(installDir, '/', file);
     this->TotalSize += cmSystemTools::FileLength(path);
   }
 
diff --git a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
index 49a9f15..553a677 100644
--- a/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinBinaryGenerator.cxx
@@ -28,13 +28,11 @@ int cmCPackCygwinBinaryGenerator::InitializeInternal()
 
 int cmCPackCygwinBinaryGenerator::PackageFiles()
 {
-  std::string packageName = this->GetOption("CPACK_PACKAGE_NAME");
-  packageName += "-";
-  packageName += this->GetOption("CPACK_PACKAGE_VERSION");
+  std::string packageName =
+    cmStrCat(this->GetOption("CPACK_PACKAGE_NAME"), '-',
+             this->GetOption("CPACK_PACKAGE_VERSION"));
   packageName = cmsys::SystemTools::LowerCase(packageName);
-  std::string manifest = "/usr/share/doc/";
-  manifest += packageName;
-  manifest += "/MANIFEST";
+  std::string manifest = cmStrCat("/usr/share/doc/", packageName, "/MANIFEST");
   std::string manifestFile = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
   // Create a MANIFEST file that contains all of the files in
   // the tar file
diff --git a/Source/CPack/cmCPackCygwinSourceGenerator.cxx b/Source/CPack/cmCPackCygwinSourceGenerator.cxx
index 889f29a..8cae9b4 100644
--- a/Source/CPack/cmCPackCygwinSourceGenerator.cxx
+++ b/Source/CPack/cmCPackCygwinSourceGenerator.cxx
@@ -37,8 +37,7 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
 {
   // Create a tar file of the sources
   std::string packageDirFileName =
-    this->GetOption("CPACK_TEMPORARY_DIRECTORY");
-  packageDirFileName += ".tar.bz2";
+    cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), ".tar.bz2");
   packageFileNames[0] = packageDirFileName;
   std::string output;
   // skip one parent up to the cmCPackTarBZip2Generator
@@ -94,8 +93,8 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
                     << this->GetOption("CPACK_TOPLEVEL_DIRECTORY") << "]\n");
     return 0;
   }
-  std::string outerTarFile = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
-  outerTarFile += "-";
+  std::string outerTarFile =
+    cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '-');
   const char* patch = this->GetOption("CPACK_CYGWIN_PATCH_NUMBER");
   if (!patch) {
     cmCPackLogger(cmCPackLog::LOG_WARNING,
@@ -106,19 +105,18 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
   outerTarFile += patch;
   outerTarFile += "-src.tar.bz2";
   std::string tmpDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  std::string buildScript = tmpDir;
-  buildScript += "/";
-  buildScript += cmSystemTools::GetFilenameName(
-    this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT"));
-  std::string patchFile = tmpDir;
-  patchFile += "/";
-  patchFile +=
-    cmSystemTools::GetFilenameName(this->GetOption("CPACK_CYGWIN_PATCH_FILE"));
+  std::string buildScript =
+    cmStrCat(tmpDir, '/',
+             cmSystemTools::GetFilenameName(
+               this->GetOption("CPACK_CYGWIN_BUILD_SCRIPT")));
+  std::string patchFile =
+    cmStrCat(tmpDir, '/',
+             cmSystemTools::GetFilenameName(
+               this->GetOption("CPACK_CYGWIN_PATCH_FILE")));
 
   std::string file = cmSystemTools::GetFilenameName(compressOutFile);
-  std::string sourceTar = cmSystemTools::GetFilenamePath(compressOutFile);
-  sourceTar += "/";
-  sourceTar += file;
+  std::string sourceTar =
+    cmStrCat(cmSystemTools::GetFilenamePath(compressOutFile), '/', file);
   /* reset list of file to be packaged */
   files.clear();
   // a source release in cygwin should have the build script used
@@ -140,8 +138,8 @@ int cmCPackCygwinSourceGenerator::PackageFiles()
 
 const char* cmCPackCygwinSourceGenerator::GetPackagingInstallPrefix()
 {
-  this->InstallPrefix = "/";
-  this->InstallPrefix += this->GetOption("CPACK_PACKAGE_FILE_NAME");
+  this->InstallPrefix =
+    cmStrCat('/', this->GetOption("CPACK_PACKAGE_FILE_NAME"));
   return this->InstallPrefix.c_str();
 }
 
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index 7c2f21a..db336b0 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -149,8 +149,7 @@ void DebGenerator::generateControlFile() const
 
   unsigned long totalSize = 0;
   {
-    std::string dirName = TemporaryDir;
-    dirName += '/';
+    std::string dirName = cmStrCat(TemporaryDir, '/');
     for (std::string const& file : PackageFiles) {
       totalSize += cmSystemTools::FileLength(file);
     }
@@ -248,8 +247,7 @@ std::string DebGenerator::generateMD5File() const
 
   cmGeneratedFileStream out(md5filename);
 
-  std::string topLevelWithTrailingSlash = TemporaryDir;
-  topLevelWithTrailingSlash += '/';
+  std::string topLevelWithTrailingSlash = cmStrCat(TemporaryDir, '/');
   for (std::string const& file : PackageFiles) {
     // hash only regular files
     if (cmSystemTools::FileIsDirectory(file) ||
@@ -469,8 +467,7 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
   // Tell CPackDeb.cmake the name of the component GROUP.
   this->SetOption("CPACK_DEB_PACKAGE_COMPONENT", packageName.c_str());
   // Tell CPackDeb.cmake the path where the component is.
-  std::string component_path = "/";
-  component_path += packageName;
+  std::string component_path = cmStrCat('/', packageName);
   this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH",
                   component_path.c_str());
   if (!this->ReadListFile("Internal/CPack/CPackDeb.cmake")) {
@@ -500,9 +497,8 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
     retval = 0;
   }
   // add the generated package to package file names list
-  packageFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  packageFileName += "/";
-  packageFileName += this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME");
+  packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
+                             this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"));
   packageFileNames.push_back(std::move(packageFileName));
 
   if (this->IsOn("GEN_CPACK_DEBIAN_DEBUGINFO_PACKAGE")) {
@@ -524,9 +520,9 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel,
       retval = 0;
     }
     // add the generated package to package file names list
-    packageFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-    packageFileName += "/";
-    packageFileName += this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME");
+    packageFileName =
+      cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
+               this->GetOption("GEN_CPACK_DBGSYM_OUTPUT_FILE_NAME"));
     packageFileNames.push_back(std::move(packageFileName));
   }
 
@@ -614,8 +610,7 @@ int cmCPackDebGenerator::PackageComponentsAllInOne(
 
   if (!compInstDirName.empty()) {
     // Tell CPackDeb.cmake the path where the component is.
-    std::string component_path = "/";
-    component_path += compInstDirName;
+    std::string component_path = cmStrCat('/', compInstDirName);
     this->SetOption("CPACK_DEB_PACKAGE_COMPONENT_PART_PATH",
                     component_path.c_str());
   }
@@ -644,9 +639,8 @@ int cmCPackDebGenerator::PackageComponentsAllInOne(
     retval = 0;
   }
   // add the generated package to package file names list
-  packageFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  packageFileName += "/";
-  packageFileName += this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME");
+  packageFileName = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
+                             this->GetOption("GEN_CPACK_OUTPUT_FILE_NAME"));
   packageFileNames.push_back(std::move(packageFileName));
   return retval;
 }
diff --git a/Source/CPack/cmCPackDragNDropGenerator.cxx b/Source/CPack/cmCPackDragNDropGenerator.cxx
index 85faa61..2aa0612 100644
--- a/Source/CPack/cmCPackDragNDropGenerator.cxx
+++ b/Source/CPack/cmCPackDragNDropGenerator.cxx
@@ -196,9 +196,7 @@ int cmCPackDragNDropGenerator::PackageFiles()
     full_package_name += std::string(GetOutputExtension());
     packageFileNames.push_back(full_package_name);
 
-    std::string src_dir = toplevel;
-    src_dir += "/";
-    src_dir += package_file;
+    std::string src_dir = cmStrCat(toplevel, '/', package_file);
 
     if (0 == this->CreateDMG(src_dir, full_package_name)) {
       return 0;
@@ -409,8 +407,8 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
   }
 
   // Create a temporary read-write disk image ...
-  std::string temp_image = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  temp_image += "/temp.dmg";
+  std::string temp_image =
+    cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/temp.dmg");
 
   std::string create_error;
   std::ostringstream temp_image_command;
@@ -522,8 +520,8 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
   if (!cpack_license_file.empty() || !slaDirectory.empty()) {
     // Use old hardcoded style if sla_dir is not set
     bool oldStyle = slaDirectory.empty();
-    std::string sla_r = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-    sla_r += "/sla.r";
+    std::string sla_r =
+      cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/sla.r");
 
     std::vector<std::string> languages;
     if (!oldStyle) {
@@ -649,8 +647,8 @@ int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
     if (temp_image_format != "UDZO") {
       temp_image_format = "UDZO";
       // convert to UDZO to enable unflatten/flatten
-      std::string temp_udzo = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-      temp_udzo += "/temp-udzo.dmg";
+      std::string temp_udzo = cmStrCat(
+        this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/temp-udzo.dmg");
 
       std::ostringstream udco_image_command;
       udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx
index f3de53c..0e9f1b6 100644
--- a/Source/CPack/cmCPackGenerator.cxx
+++ b/Source/CPack/cmCPackGenerator.cxx
@@ -73,8 +73,8 @@ int cmCPackGenerator::PrepareNames()
     }
   }
 
-  std::string tempDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY");
-  tempDirectory += "/_CPack_Packages/";
+  std::string tempDirectory =
+    cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/_CPack_Packages/");
   const char* toplevelTag = this->GetOption("CPACK_TOPLEVEL_TAG");
   if (toplevelTag) {
     tempDirectory += toplevelTag;
@@ -197,8 +197,7 @@ int cmCPackGenerator::InstallProject()
   }
 
   if (setDestDir) {
-    std::string destDir = "DESTDIR=";
-    destDir += tempInstallDirectory;
+    std::string destDir = cmStrCat("DESTDIR=", tempInstallDirectory);
     cmSystemTools::PutEnv(destDir);
   } else {
     // Make sure there is no destdir
@@ -271,8 +270,8 @@ int cmCPackGenerator::InstallProjectViaInstallCommands(
   (void)setDestDir;
   const char* installCommands = this->GetOption("CPACK_INSTALL_COMMANDS");
   if (installCommands && *installCommands) {
-    std::string tempInstallDirectoryEnv = "CMAKE_INSTALL_PREFIX=";
-    tempInstallDirectoryEnv += tempInstallDirectory;
+    std::string tempInstallDirectoryEnv =
+      cmStrCat("CMAKE_INSTALL_PREFIX=", tempInstallDirectory);
     cmSystemTools::PutEnv(tempInstallDirectoryEnv);
     std::vector<std::string> installCommandsVector;
     cmExpandList(installCommands, installCommandsVector);
@@ -284,8 +283,8 @@ int cmCPackGenerator::InstallProjectViaInstallCommands(
         ic, &output, &output, &retVal, nullptr, this->GeneratorVerbose,
         cmDuration::zero());
       if (!resB || retVal) {
-        std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-        tmpFile += "/InstallOutput.log";
+        std::string tmpFile = cmStrCat(
+          this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/InstallOutput.log");
         cmGeneratedFileStream ofs(tmpFile);
         ofs << "# Run command: " << ic << std::endl
             << "# Output:" << std::endl
@@ -343,8 +342,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
       std::string top = *it;
       it++;
       std::string subdir = *it;
-      std::string findExpr = top;
-      findExpr += "/*";
+      std::string findExpr = cmStrCat(top, "/*");
       cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                     "- Install directory: " << top << std::endl);
       gl.RecurseOn();
@@ -372,8 +370,8 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
         if (skip) {
           continue;
         }
-        std::string filePath = tempDir;
-        filePath += "/" + subdir + "/" + cmSystemTools::RelativePath(top, gf);
+        std::string filePath = cmStrCat(tempDir, '/', subdir, '/',
+                                        cmSystemTools::RelativePath(top, gf));
         cmCPackLogger(cmCPackLog::LOG_DEBUG,
                       "Copy file: " << inFile << " -> " << filePath
                                     << std::endl);
@@ -398,8 +396,7 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories(
       /* rebuild symlinks in the installed tree */
       if (!symlinkedFiles.empty()) {
         std::string curDir = cmSystemTools::GetCurrentWorkingDirectory();
-        std::string goToDir = tempDir;
-        goToDir += "/" + subdir;
+        std::string goToDir = cmStrCat(tempDir, '/', subdir);
         cmCPackLogger(cmCPackLog::LOG_DEBUG,
                       "Change dir to: " << goToDir << std::endl);
         cmWorkingDirectory workdir(goToDir);
@@ -662,8 +659,8 @@ int cmCPackGenerator::RunPreinstallTarget(
       buildCommand, &output, &output, &retVal, installDirectory.c_str(),
       this->GeneratorVerbose, cmDuration::zero());
     if (!resB || retVal) {
-      std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-      tmpFile += "/PreinstallOutput.log";
+      std::string tmpFile = cmStrCat(
+        this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/PreinstallOutput.log");
       cmGeneratedFileStream ofs(tmpFile);
       ofs << "# Run command: " << buildCommand << std::endl
           << "# Directory: " << installDirectory << std::endl
@@ -911,10 +908,8 @@ int cmCPackGenerator::InstallCMakeProject(
         GetComponentInstallDirNameSuffix(component);
       if (nullptr != this->GetOption(absoluteDestFileComponent)) {
         std::string absoluteDestFilesListComponent =
-          this->GetOption(absoluteDestFileComponent);
-        absoluteDestFilesListComponent += ";";
-        absoluteDestFilesListComponent +=
-          mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES");
+          cmStrCat(this->GetOption(absoluteDestFileComponent), ';',
+                   mf.GetDefinition("CPACK_ABSOLUTE_DESTINATION_FILES"));
         this->SetOption(absoluteDestFileComponent,
                         absoluteDestFilesListComponent.c_str());
       } else {
@@ -1006,8 +1001,7 @@ int cmCPackGenerator::DoPackage()
 
   cmCPackLogger(cmCPackLog::LOG_DEBUG, "Find files" << std::endl);
   cmsys::Glob gl;
-  std::string findExpr = tempDirectory;
-  findExpr += "/*";
+  std::string findExpr = cmStrCat(tempDirectory, "/*");
   gl.RecurseOn();
   gl.SetRecurseListDirs(true);
   gl.SetRecurseThroughSymlinks(false);
@@ -1203,8 +1197,7 @@ const char* cmCPackGenerator::GetInstallPath()
   if (cmsys::SystemTools::GetEnv("ProgramFiles", prgfiles)) {
     this->InstallPath = prgfiles;
   } else if (cmsys::SystemTools::GetEnv("SystemDrive", sysDrive)) {
-    this->InstallPath = sysDrive;
-    this->InstallPath += "/Program Files";
+    this->InstallPath = cmStrCat(sysDrive, "/Program Files");
   } else {
     this->InstallPath = "c:/Program Files";
   }
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index 7ca343a..41ffa0e 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -56,8 +56,7 @@ int cmCPackNSISGenerator::PackageFiles()
   }
 
   std::string nsisFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  std::string tmpFile = nsisFileName;
-  tmpFile += "/NSISOutput.log";
+  std::string tmpFile = cmStrCat(nsisFileName, "/NSISOutput.log");
   std::string nsisInstallOptions = nsisFileName + "/NSIS.InstallOptions.ini";
   nsisFileName += "/project.nsi";
   std::ostringstream str;
@@ -142,39 +141,34 @@ int cmCPackNSISGenerator::PackageFiles()
                             installerIconCode.c_str());
   }
   if (this->IsSet("CPACK_PACKAGE_ICON")) {
-    std::string installerIconCode = "!define MUI_HEADERIMAGE_BITMAP \"";
-    installerIconCode += this->GetOption("CPACK_PACKAGE_ICON");
-    installerIconCode += "\"\n";
+    std::string installerIconCode =
+      cmStrCat("!define MUI_HEADERIMAGE_BITMAP \"",
+               this->GetOption("CPACK_PACKAGE_ICON"), "\"\n");
     this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_ICON_CODE",
                             installerIconCode.c_str());
   }
 
   if (this->IsSet("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP")) {
-    std::string installerBitmapCode =
-      "!define MUI_WELCOMEFINISHPAGE_BITMAP \"";
-    installerBitmapCode +=
-      this->GetOption("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP");
-    installerBitmapCode += "\"\n";
+    std::string installerBitmapCode = cmStrCat(
+      "!define MUI_WELCOMEFINISHPAGE_BITMAP \"",
+      this->GetOption("CPACK_NSIS_MUI_WELCOMEFINISHPAGE_BITMAP"), "\"\n");
     this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_WELCOMEFINISH_CODE",
                             installerBitmapCode.c_str());
   }
 
   if (this->IsSet("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP")) {
-    std::string installerBitmapCode =
-      "!define MUI_UNWELCOMEFINISHPAGE_BITMAP \"";
-    installerBitmapCode +=
-      this->GetOption("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP");
-    installerBitmapCode += "\"\n";
+    std::string installerBitmapCode = cmStrCat(
+      "!define MUI_UNWELCOMEFINISHPAGE_BITMAP \"",
+      this->GetOption("CPACK_NSIS_MUI_UNWELCOMEFINISHPAGE_BITMAP"), "\"\n");
     this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_UNWELCOMEFINISH_CODE",
                             installerBitmapCode.c_str());
   }
 
   if (this->IsSet("CPACK_NSIS_MUI_FINISHPAGE_RUN")) {
-    std::string installerRunCode = "!define MUI_FINISHPAGE_RUN \"$INSTDIR\\";
-    installerRunCode += this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY");
-    installerRunCode += "\\";
-    installerRunCode += this->GetOption("CPACK_NSIS_MUI_FINISHPAGE_RUN");
-    installerRunCode += "\"\n";
+    std::string installerRunCode =
+      cmStrCat("!define MUI_FINISHPAGE_RUN \"$INSTDIR\\",
+               this->GetOption("CPACK_NSIS_EXECUTABLES_DIRECTORY"), '\\',
+               this->GetOption("CPACK_NSIS_MUI_FINISHPAGE_RUN"), "\"\n");
     this->SetOptionIfNotSet("CPACK_NSIS_INSTALLER_MUI_FINISHPAGE_RUN_CODE",
                             installerRunCode.c_str());
   }
@@ -297,9 +291,9 @@ int cmCPackNSISGenerator::PackageFiles()
 
   this->ConfigureFile(nsisInInstallOptions, nsisInstallOptions);
   this->ConfigureFile(nsisInFileName, nsisFileName);
-  std::string nsisCmd = "\"";
-  nsisCmd += this->GetOption("CPACK_INSTALLER_PROGRAM");
-  nsisCmd += "\" \"" + nsisFileName + "\"";
+  std::string nsisCmd =
+    cmStrCat('"', this->GetOption("CPACK_INSTALLER_PROGRAM"), "\" \"",
+             nsisFileName, '"');
   cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << nsisCmd << std::endl);
   std::string output;
   int retVal = 1;
@@ -415,8 +409,7 @@ int cmCPackNSISGenerator::InitializeInternal()
   if (!resS || retVal ||
       (!versionRex.find(output) && !versionRexCVS.find(output))) {
     const char* topDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-    std::string tmpFile = topDir ? topDir : ".";
-    tmpFile += "/NSISOutput.log";
+    std::string tmpFile = cmStrCat(topDir ? topDir : ".", "/NSISOutput.log");
     cmGeneratedFileStream ofs(tmpFile);
     ofs << "# Run command: " << nsisCmd << std::endl
         << "# Output:" << std::endl
@@ -573,8 +566,7 @@ void cmCPackNSISGenerator::CreateMenuLinks(std::ostream& str,
     }
     // see if CPACK_CREATE_DESKTOP_LINK_ExeName is on
     // if so add a desktop link
-    std::string desktop = "CPACK_CREATE_DESKTOP_LINK_";
-    desktop += linkName;
+    std::string desktop = cmStrCat("CPACK_CREATE_DESKTOP_LINK_", linkName);
     if (this->IsSet(desktop)) {
       str << "  StrCmp \"$INSTALL_DESKTOP\" \"1\" 0 +2\n";
       str << "    CreateShortCut \"$DESKTOP\\" << linkName
@@ -656,8 +648,8 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
   if (component->IsDownloaded) {
     if (component->ArchiveFile.empty()) {
       // Compute the name of the archive.
-      std::string packagesDir = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
-      packagesDir += ".dummy";
+      std::string packagesDir =
+        cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), ".dummy");
       std::ostringstream out;
       out << cmSystemTools::GetFilenameWithoutLastExtension(packagesDir) << "-"
           << component->Name << ".zip";
@@ -671,8 +663,8 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
     if (userUploadDirectory && *userUploadDirectory) {
       uploadDirectory = userUploadDirectory;
     } else {
-      uploadDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY");
-      uploadDirectory += "/CPackUploads";
+      uploadDirectory =
+        cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/CPackUploads");
     }
     if (!cmSystemTools::FileExists(uploadDirectory)) {
       if (!cmSystemTools::MakeDirectory(uploadDirectory)) {
@@ -709,15 +701,13 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
     }
 
     // The directory where this component's files reside
-    std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
-    dirName += '/';
-    dirName += component->Name;
-    dirName += '/';
+    std::string dirName = cmStrCat(
+      this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '/', component->Name, '/');
 
     // Build the list of files to go into this archive, and determine the
     // size of the installed component.
-    std::string zipListFileName = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
-    zipListFileName += "/winZip.filelist";
+    std::string zipListFileName = cmStrCat(
+      this->GetOption("CPACK_TEMPORARY_DIRECTORY"), "/winZip.filelist");
     bool needQuotesInFile = cmIsOn(this->GetOption("CPACK_ZIP_NEED_QUOTES"));
     unsigned long totalSize = 0;
     { // the scope is needed for cmGeneratedFileStream
@@ -747,8 +737,8 @@ std::string cmCPackNSISGenerator::CreateComponentDescription(
       cmd, &output, &output, &retVal, dirName.c_str(),
       cmSystemTools::OUTPUT_NONE, cmDuration::zero());
     if (!res || retVal) {
-      std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-      tmpFile += "/CompressZip.log";
+      std::string tmpFile = cmStrCat(
+        this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/CompressZip.log");
       cmGeneratedFileStream ofs(tmpFile);
       ofs << "# Run command: " << cmd << std::endl
           << "# Output:" << std::endl
diff --git a/Source/CPack/cmCPackOSXX11Generator.cxx b/Source/CPack/cmCPackOSXX11Generator.cxx
index 7cc48f4..ffa8a42 100644
--- a/Source/CPack/cmCPackOSXX11Generator.cxx
+++ b/Source/CPack/cmCPackOSXX11Generator.cxx
@@ -55,16 +55,14 @@ int cmCPackOSXX11Generator::PackageFiles()
     diskImageDirectory + "/.background";
 
   // App bundle directories
-  std::string packageDirFileName = toplevel;
-  packageDirFileName += "/";
-  packageDirFileName += this->GetOption("CPACK_PACKAGE_FILE_NAME");
-  packageDirFileName += ".app";
+  std::string packageDirFileName = cmStrCat(
+    toplevel, '/', this->GetOption("CPACK_PACKAGE_FILE_NAME"), ".app");
   std::string contentsDirectory = packageDirFileName + "/Contents";
   std::string resourcesDirectory = contentsDirectory + "/Resources";
   std::string appDirectory = contentsDirectory + "/MacOS";
   std::string scriptDirectory = resourcesDirectory + "/Scripts";
-  std::string resourceFileName = this->GetOption("CPACK_PACKAGE_FILE_NAME");
-  resourceFileName += ".rsrc";
+  std::string resourceFileName =
+    cmStrCat(this->GetOption("CPACK_PACKAGE_FILE_NAME"), ".rsrc");
 
   const char* dir = resourcesDirectory.c_str();
   const char* appdir = appDirectory.c_str();
@@ -113,13 +111,10 @@ int cmCPackOSXX11Generator::PackageFiles()
   }
 
   // Two of the files need to have execute permission, so ensure they do:
-  std::string runTimeScript = dir;
-  runTimeScript += "/";
-  runTimeScript += "RuntimeScript";
+  std::string runTimeScript = cmStrCat(dir, "/RuntimeScript");
 
-  std::string appScriptName = appdir;
-  appScriptName += "/";
-  appScriptName += this->GetOption("CPACK_PACKAGE_FILE_NAME");
+  std::string appScriptName =
+    cmStrCat(appdir, '/', this->GetOption("CPACK_PACKAGE_FILE_NAME"));
 
   mode_t mode;
   if (cmsys::SystemTools::GetPermissions(runTimeScript.c_str(), mode)) {
@@ -139,8 +134,8 @@ int cmCPackOSXX11Generator::PackageFiles()
   }
 
   std::string output;
-  std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  tmpFile += "/hdiutilOutput.log";
+  std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+                                 "/hdiutilOutput.log");
   std::ostringstream dmgCmd;
   dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE")
          << "\" create -ov -fs HFS+ -format UDZO -srcfolder \""
@@ -228,9 +223,8 @@ bool cmCPackOSXX11Generator::CopyCreateResourceFile(const std::string& name)
     return false;
     }
 
-  std::string destFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  destFileName += "/Resources/";
-  destFileName += name + ext;
+  std::string destFileName = cmStrCat(
+this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/Resources/", name, ext );
 
 
   cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Configure file: "
@@ -245,9 +239,7 @@ bool cmCPackOSXX11Generator::CopyResourcePlistFile(
   const std::string& name, const std::string& dir,
   const char* outputFileName /* = 0 */, bool copyOnly /* = false */)
 {
-  std::string inFName = "Internal/CPack/CPack.";
-  inFName += name;
-  inFName += ".in";
+  std::string inFName = cmStrCat("Internal/CPack/CPack.", name, ".in");
   std::string inFileName = this->FindTemplate(inFName.c_str());
   if (inFileName.empty()) {
     cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -259,9 +251,7 @@ bool cmCPackOSXX11Generator::CopyResourcePlistFile(
     outputFileName = name.c_str();
   }
 
-  std::string destFileName = dir;
-  destFileName += "/";
-  destFileName += outputFileName;
+  std::string destFileName = cmStrCat(dir, '/', outputFileName);
 
   cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                 "Configure file: " << inFileName << " to " << destFileName
@@ -272,8 +262,8 @@ bool cmCPackOSXX11Generator::CopyResourcePlistFile(
 
 const char* cmCPackOSXX11Generator::GetPackagingInstallPrefix()
 {
-  this->InstallPrefix = "/";
-  this->InstallPrefix += this->GetOption("CPACK_PACKAGE_FILE_NAME");
-  this->InstallPrefix += ".app/Contents/Resources";
+  this->InstallPrefix =
+    cmStrCat('/', this->GetOption("CPACK_PACKAGE_FILE_NAME"),
+             ".app/Contents/Resources");
   return this->InstallPrefix.c_str();
 }
diff --git a/Source/CPack/cmCPackPKGGenerator.cxx b/Source/CPack/cmCPackPKGGenerator.cxx
index d361921..3e1a51b 100644
--- a/Source/CPack/cmCPackPKGGenerator.cxx
+++ b/Source/CPack/cmCPackPKGGenerator.cxx
@@ -7,6 +7,7 @@
 #include "cmCPackComponentGroup.h"
 #include "cmCPackGenerator.h"
 #include "cmCPackLog.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmXMLWriter.h"
 
@@ -34,8 +35,8 @@ std::string cmCPackPKGGenerator::GetPackageName(
   const cmCPackComponent& component)
 {
   if (component.ArchiveFile.empty()) {
-    std::string packagesDir = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
-    packagesDir += ".dummy";
+    std::string packagesDir =
+      cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), ".dummy");
     std::ostringstream out;
     out << cmSystemTools::GetFilenameWithoutLastExtension(packagesDir) << "-"
         << component.Name << ".pkg";
@@ -56,8 +57,8 @@ void cmCPackPKGGenerator::WriteDistributionFile(const char* metapackageFile)
     return;
   }
 
-  std::string distributionFile = metapackageFile;
-  distributionFile += "/Contents/distribution.dist";
+  std::string distributionFile =
+    cmStrCat(metapackageFile, "/Contents/distribution.dist");
 
   // Create the choice outline, which provides a tree-based view of
   // the components in their groups.
@@ -144,12 +145,9 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponentGroup& group,
 void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component,
                                        cmXMLWriter& xout)
 {
-  std::string packageId = "com.";
-  packageId += this->GetOption("CPACK_PACKAGE_VENDOR");
-  packageId += '.';
-  packageId += this->GetOption("CPACK_PACKAGE_NAME");
-  packageId += '.';
-  packageId += component.Name;
+  std::string packageId =
+    cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"), '.',
+             this->GetOption("CPACK_PACKAGE_NAME"), '.', component.Name);
 
   xout.StartElement("choice");
   xout.Attribute("id", component.Name + "Choice");
@@ -192,14 +190,13 @@ void cmCPackPKGGenerator::CreateChoice(const cmCPackComponent& component,
 
   // Create a description of the package associated with this
   // component.
-  std::string relativePackageLocation = "Contents/Packages/";
-  relativePackageLocation += this->GetPackageName(component);
+  std::string relativePackageLocation =
+    cmStrCat("Contents/Packages/", this->GetPackageName(component));
 
   // Determine the installed size of the package.
-  std::string dirName = this->GetOption("CPACK_TEMPORARY_DIRECTORY");
-  dirName += '/';
-  dirName += component.Name;
-  dirName += this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX");
+  std::string dirName =
+    cmStrCat(this->GetOption("CPACK_TEMPORARY_DIRECTORY"), '/', component.Name,
+             this->GetOption("CPACK_PACKAGING_INSTALL_PREFIX"));
   unsigned long installedSize = component.GetInstalledSizeInKbytes(dirName);
 
   xout.StartElement("pkg-ref");
@@ -282,9 +279,7 @@ bool cmCPackPKGGenerator::CopyCreateResourceFile(const std::string& name,
     return false;
   }
 
-  std::string destFileName = dirName;
-  destFileName += '/';
-  destFileName += name + ext;
+  std::string destFileName = cmStrCat(dirName, '/', name, ext);
 
   // Set this so that distribution.dist gets the right name (without
   // the path).
@@ -305,9 +300,7 @@ bool cmCPackPKGGenerator::CopyResourcePlistFile(const std::string& name,
     outName = name.c_str();
   }
 
-  std::string inFName = "Internal/CPack/CPack.";
-  inFName += name;
-  inFName += ".in";
+  std::string inFName = cmStrCat("Internal/CPack/CPack.", name, ".in");
   std::string inFileName = this->FindTemplate(inFName.c_str());
   if (inFileName.empty()) {
     cmCPackLogger(cmCPackLog::LOG_ERROR,
@@ -315,9 +308,8 @@ bool cmCPackPKGGenerator::CopyResourcePlistFile(const std::string& name,
     return false;
   }
 
-  std::string destFileName = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  destFileName += "/";
-  destFileName += outName;
+  std::string destFileName =
+    cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/', outName);
 
   cmCPackLogger(cmCPackLog::LOG_VERBOSE,
                 "Configure file: " << inFileName << " to " << destFileName
@@ -330,9 +322,7 @@ int cmCPackPKGGenerator::CopyInstallScript(const std::string& resdir,
                                            const std::string& script,
                                            const std::string& name)
 {
-  std::string dst = resdir;
-  dst += "/";
-  dst += name;
+  std::string dst = cmStrCat(resdir, '/', name);
   cmSystemTools::CopyFileAlways(script, dst);
   cmSystemTools::SetPermissions(dst.c_str(), 0777);
   cmCPackLogger(cmCPackLog::LOG_VERBOSE,
diff --git a/Source/CPack/cmCPackPackageMakerGenerator.cxx b/Source/CPack/cmCPackPackageMakerGenerator.cxx
index 3d93c48..5dc36ab 100644
--- a/Source/CPack/cmCPackPackageMakerGenerator.cxx
+++ b/Source/CPack/cmCPackPackageMakerGenerator.cxx
@@ -15,6 +15,7 @@
 #include "cmCPackLog.h"
 #include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmXMLWriter.h"
 
@@ -47,8 +48,8 @@ int cmCPackPackageMakerGenerator::PackageFiles()
     this->GetOption("CPACK_TEMPORARY_DIRECTORY");
   if (this->Components.empty()) {
     packageDirFileName += ".pkg";
-    resDir = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-    resDir += "/Resources";
+    resDir =
+      cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), "/Resources");
   } else {
     packageDirFileName += ".mpkg";
     if (!cmsys::SystemTools::MakeDirectory(packageDirFileName.c_str())) {
@@ -58,8 +59,7 @@ int cmCPackPackageMakerGenerator::PackageFiles()
       return 0;
     }
 
-    resDir = packageDirFileName;
-    resDir += "/Contents";
+    resDir = cmStrCat(packageDirFileName, "/Contents");
     if (!cmsys::SystemTools::MakeDirectory(resDir.c_str())) {
       cmCPackLogger(cmCPackLog::LOG_ERROR,
                     "unable to create package subdirectory " << resDir
@@ -155,8 +155,8 @@ int cmCPackPackageMakerGenerator::PackageFiles()
 
   if (!this->Components.empty()) {
     // Create the directory where component packages will be built.
-    std::string basePackageDir = packageDirFileName;
-    basePackageDir += "/Contents/Packages";
+    std::string basePackageDir =
+      cmStrCat(packageDirFileName, "/Contents/Packages");
     if (!cmsys::SystemTools::MakeDirectory(basePackageDir.c_str())) {
       cmCPackLogger(cmCPackLog::LOG_ERROR,
                     "Problem creating component packages directory: "
@@ -172,8 +172,8 @@ int cmCPackPackageMakerGenerator::PackageFiles()
     if (userUploadDirectory && *userUploadDirectory) {
       uploadDirectory = userUploadDirectory;
     } else {
-      uploadDirectory = this->GetOption("CPACK_PACKAGE_DIRECTORY");
-      uploadDirectory += "/CPackUploads";
+      uploadDirectory =
+        cmStrCat(this->GetOption("CPACK_PACKAGE_DIRECTORY"), "/CPackUploads");
     }
 
     // Create packages for each component
@@ -232,9 +232,7 @@ int cmCPackPackageMakerGenerator::PackageFiles()
       packageFile += '/';
       packageFile += GetPackageName(compIt->second);
 
-      std::string packageDir = toplevel;
-      packageDir += '/';
-      packageDir += compIt->first;
+      std::string packageDir = cmStrCat(toplevel, '/', compIt->first);
       if (!this->GenerateComponentPackage(
             packageFile.c_str(), packageDir.c_str(), compIt->second)) {
         return 0;
@@ -283,8 +281,8 @@ int cmCPackPackageMakerGenerator::PackageFiles()
     WriteDistributionFile(packageDirFileName.c_str());
   }
 
-  std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  tmpFile += "/hdiutilOutput.log";
+  std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+                                 "/hdiutilOutput.log");
   std::ostringstream dmgCmd;
   dmgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM_DISK_IMAGE")
          << "\" create -ov -fs HFS+ -format UDZO -srcfolder \""
@@ -461,8 +459,8 @@ int cmCPackPackageMakerGenerator::InitializeInternal()
 bool cmCPackPackageMakerGenerator::RunPackageMaker(const char* command,
                                                    const char* packageFile)
 {
-  std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  tmpFile += "/PackageMakerOutput.log";
+  std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+                                 "/PackageMakerOutput.log");
 
   cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl);
   std::string output;
@@ -517,8 +515,9 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage(
       this->PackageMakerVersion < 3.0) {
     // Create Description.plist and Info.plist files for normal Mac OS
     // X packages, which work on Mac OS X 10.3 and newer.
-    std::string descriptionFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-    descriptionFile += '/' + component.Name + "-Description.plist";
+    std::string descriptionFile =
+      cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"), '/',
+               component.Name, "-Description.plist");
     cmsys::ofstream out(descriptionFile.c_str());
     cmXMLWriter xout(out);
     xout.StartDocument();
@@ -539,12 +538,10 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage(
     out.close();
 
     // Create the Info.plist file for this component
-    std::string moduleVersionSuffix = ".";
-    moduleVersionSuffix += component.Name;
+    std::string moduleVersionSuffix = cmStrCat('.', component.Name);
     this->SetOption("CPACK_MODULE_VERSION_SUFFIX",
                     moduleVersionSuffix.c_str());
-    std::string infoFileName = component.Name;
-    infoFileName += "-Info.plist";
+    std::string infoFileName = cmStrCat(component.Name, "-Info.plist");
     if (!this->CopyResourcePlistFile("Info.plist", infoFileName.c_str())) {
       return false;
     }
@@ -561,12 +558,9 @@ bool cmCPackPackageMakerGenerator::GenerateComponentPackage(
     // like normal packages, and can be downloaded by the installer
     // on-the-fly in Mac OS X 10.5 or newer. Thus, we need to create
     // flat packages when the packages will be downloaded on the fly.
-    std::string pkgId = "com.";
-    pkgId += this->GetOption("CPACK_PACKAGE_VENDOR");
-    pkgId += '.';
-    pkgId += this->GetOption("CPACK_PACKAGE_NAME");
-    pkgId += '.';
-    pkgId += component.Name;
+    std::string pkgId =
+      cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"), '.',
+               this->GetOption("CPACK_PACKAGE_NAME"), '.', component.Name);
 
     pkgCmd << "\"" << this->GetOption("CPACK_INSTALLER_PROGRAM")
            << "\" --root \"" << packageDir << "\""
diff --git a/Source/CPack/cmCPackProductBuildGenerator.cxx b/Source/CPack/cmCPackProductBuildGenerator.cxx
index 94b5b5f..800af28 100644
--- a/Source/CPack/cmCPackProductBuildGenerator.cxx
+++ b/Source/CPack/cmCPackProductBuildGenerator.cxx
@@ -10,6 +10,7 @@
 #include "cmCPackLog.h"
 #include "cmDuration.h"
 #include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 cmCPackProductBuildGenerator::cmCPackProductBuildGenerator()
@@ -28,8 +29,8 @@ int cmCPackProductBuildGenerator::PackageFiles()
     this->GetOption("CPACK_TEMPORARY_DIRECTORY");
 
   // Create the directory where component packages will be built.
-  std::string basePackageDir = packageDirFileName;
-  basePackageDir += "/Contents/Packages";
+  std::string basePackageDir =
+    cmStrCat(packageDirFileName, "/Contents/Packages");
   if (!cmsys::SystemTools::MakeDirectory(basePackageDir.c_str())) {
     cmCPackLogger(cmCPackLog::LOG_ERROR,
                   "Problem creating component packages directory: "
@@ -41,9 +42,7 @@ int cmCPackProductBuildGenerator::PackageFiles()
     std::map<std::string, cmCPackComponent>::iterator compIt;
     for (compIt = this->Components.begin(); compIt != this->Components.end();
          ++compIt) {
-      std::string packageDir = toplevel;
-      packageDir += '/';
-      packageDir += compIt->first;
+      std::string packageDir = cmStrCat(toplevel, '/', compIt->first);
       if (!this->GenerateComponentPackage(basePackageDir,
                                           GetPackageName(compIt->second),
                                           packageDir, &compIt->second)) {
@@ -138,8 +137,8 @@ int cmCPackProductBuildGenerator::InitializeInternal()
 
 bool cmCPackProductBuildGenerator::RunProductBuild(const std::string& command)
 {
-  std::string tmpFile = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
-  tmpFile += "/ProductBuildOutput.log";
+  std::string tmpFile = cmStrCat(this->GetOption("CPACK_TOPLEVEL_DIRECTORY"),
+                                 "/ProductBuildOutput.log");
 
   cmCPackLogger(cmCPackLog::LOG_VERBOSE, "Execute: " << command << std::endl);
   std::string output;
@@ -166,9 +165,7 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage(
   const std::string& packageFileDir, const std::string& packageFileName,
   const std::string& packageDir, const cmCPackComponent* component)
 {
-  std::string packageFile = packageFileDir;
-  packageFile += '/';
-  packageFile += packageFileName;
+  std::string packageFile = cmStrCat(packageFileDir, '/', packageFileName);
 
   cmCPackLogger(cmCPackLog::LOG_OUTPUT,
                 "-   Building component package: " << packageFile
@@ -206,10 +203,8 @@ bool cmCPackProductBuildGenerator::GenerateComponentPackage(
   // The command that will be used to run ProductBuild
   std::ostringstream pkgCmd;
 
-  std::string pkgId = "com.";
-  pkgId += this->GetOption("CPACK_PACKAGE_VENDOR");
-  pkgId += '.';
-  pkgId += this->GetOption("CPACK_PACKAGE_NAME");
+  std::string pkgId = cmStrCat("com.", this->GetOption("CPACK_PACKAGE_VENDOR"),
+                               '.', this->GetOption("CPACK_PACKAGE_NAME"));
   if (component) {
     pkgId += '.';
     pkgId += component->Name;
diff --git a/Source/CPack/cmCPackRPMGenerator.cxx b/Source/CPack/cmCPackRPMGenerator.cxx
index 9ffebf5..0f621cc 100644
--- a/Source/CPack/cmCPackRPMGenerator.cxx
+++ b/Source/CPack/cmCPackRPMGenerator.cxx
@@ -82,8 +82,7 @@ int cmCPackRPMGenerator::PackageOnePack(std::string const& initialToplevel,
   // Tell CPackRPM.cmake the name of the component NAME.
   this->SetOption("CPACK_RPM_PACKAGE_COMPONENT", packageName.c_str());
   // Tell CPackRPM.cmake the path where the component is.
-  std::string component_path = "/";
-  component_path += packageName;
+  std::string component_path = cmStrCat('/', packageName);
   this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH",
                   component_path.c_str());
   if (!this->ReadListFile("Internal/CPack/CPackRPM.cmake")) {
@@ -376,8 +375,7 @@ int cmCPackRPMGenerator::PackageComponentsAllInOne(
 
   if (!compInstDirName.empty()) {
     // Tell CPackRPM.cmake the path where the component is.
-    std::string component_path = "/";
-    component_path += compInstDirName;
+    std::string component_path = cmStrCat('/', compInstDirName);
     this->SetOption("CPACK_RPM_PACKAGE_COMPONENT_PART_PATH",
                     component_path.c_str());
   }
diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx
index 5abf0ab..a98fabc 100644
--- a/Source/CPack/cpack.cxx
+++ b/Source/CPack/cpack.cxx
@@ -230,8 +230,8 @@ int main(int argc, char const* const* argv)
 
   bool cpackConfigFileSpecified = true;
   if (cpackConfigFile.empty()) {
-    cpackConfigFile = cmSystemTools::GetCurrentWorkingDirectory();
-    cpackConfigFile += "/CPackConfig.cmake";
+    cpackConfigFile = cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(),
+                               "/CPackConfig.cmake");
     cpackConfigFileSpecified = false;
   }
 
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx
index 3aea1f4..e7fb4c7 100644
--- a/Source/CTest/cmCTestBuildAndTestHandler.cxx
+++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx
@@ -7,6 +7,7 @@
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmState.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmWorkingDirectory.h"
 #include "cmake.h"
@@ -289,9 +290,8 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring)
   std::vector<std::string> extraPaths;
   // if this->ExecutableDirectory is set try that as well
   if (!this->ExecutableDirectory.empty()) {
-    std::string tempPath = this->ExecutableDirectory;
-    tempPath += "/";
-    tempPath += this->TestCommand;
+    std::string tempPath =
+      cmStrCat(this->ExecutableDirectory, '/', this->TestCommand);
     extraPaths.push_back(tempPath);
   }
   std::vector<std::string> failed;
diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx
index e71eafe..6e76f08 100644
--- a/Source/CTest/cmCTestBuildCommand.cxx
+++ b/Source/CTest/cmCTestBuildCommand.cxx
@@ -7,6 +7,7 @@
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 
@@ -90,9 +91,8 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler()
           this->Makefile->GetCMakeInstance()->CreateGlobalGenerator(
             cmakeGeneratorName);
         if (!this->GlobalGenerator) {
-          std::string e = "could not create generator named \"";
-          e += cmakeGeneratorName;
-          e += "\"";
+          std::string e = cmStrCat("could not create generator named \"",
+                                   cmakeGeneratorName, '"');
           this->Makefile->IssueMessage(MessageType::FATAL_ERROR, e);
           cmSystemTools::SetFatalErrorOccured();
           return nullptr;
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index 2365a66..8d1f76b 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -565,8 +565,7 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml)
   std::string srcdir = this->CTest->GetCTestConfiguration("SourceDirectory");
   // make sure the source dir is in the correct case on windows
   // via a call to collapse full path.
-  srcdir = cmSystemTools::CollapseFullPath(srcdir);
-  srcdir += "/";
+  srcdir = cmStrCat(cmSystemTools::CollapseFullPath(srcdir), '/');
   for (it = ew.begin();
        it != ew.end() && (numErrorsAllowed || numWarningsAllowed); it++) {
     cmCTestBuildErrorWarning* cm = &(*it);
@@ -697,10 +696,8 @@ cmCTestBuildHandler::LaunchHelper::LaunchHelper(cmCTestBuildHandler* handler)
   } else {
     // Compute a directory in which to store launcher fragments.
     std::string& launchDir = this->Handler->CTestLaunchDir;
-    launchDir = this->CTest->GetBinaryDir();
-    launchDir += "/Testing/";
-    launchDir += tag;
-    launchDir += "/Build";
+    launchDir =
+      cmStrCat(this->CTest->GetBinaryDir(), "/Testing/", tag, "/Build");
 
     // Clean out any existing launcher fragments.
     cmSystemTools::RemoveADirectory(launchDir);
@@ -709,8 +706,7 @@ cmCTestBuildHandler::LaunchHelper::LaunchHelper(cmCTestBuildHandler* handler)
       // Enable launcher fragments.
       cmSystemTools::MakeDirectory(launchDir);
       this->WriteLauncherConfig();
-      std::string launchEnv = "CTEST_LAUNCH_LOGS=";
-      launchEnv += launchDir;
+      std::string launchEnv = cmStrCat("CTEST_LAUNCH_LOGS=", launchDir);
       cmSystemTools::PutEnv(launchEnv);
     }
   }
@@ -736,8 +732,8 @@ void cmCTestBuildHandler::LaunchHelper::WriteLauncherConfig()
                             this->Handler->ReallyCustomWarningExceptions);
 
   // Give some testing configuration information to the launcher.
-  std::string fname = this->Handler->CTestLaunchDir;
-  fname += "/CTestLaunchConfig.cmake";
+  std::string fname =
+    cmStrCat(this->Handler->CTestLaunchDir, "/CTestLaunchConfig.cmake");
   cmGeneratedFileStream fout(fname);
   std::string srcdir = this->CTest->GetCTestConfiguration("SourceDirectory");
   fout << "set(CTEST_SOURCE_DIRECTORY \"" << srcdir << "\")\n";
@@ -749,10 +745,8 @@ void cmCTestBuildHandler::LaunchHelper::WriteScrapeMatchers(
   if (matchers.empty()) {
     return;
   }
-  std::string fname = this->Handler->CTestLaunchDir;
-  fname += "/Custom";
-  fname += purpose;
-  fname += ".txt";
+  std::string fname =
+    cmStrCat(this->Handler->CTestLaunchDir, "/Custom", purpose, ".txt");
   cmGeneratedFileStream fout(fname);
   for (std::string const& m : matchers) {
     fout << m << "\n";
@@ -891,9 +885,8 @@ int cmCTestBuildHandler::RunMakeCommand(const std::string& command,
         // dashboard.
         cmCTestBuildErrorWarning errorwarning;
         errorwarning.LogLine = 1;
-        errorwarning.Text =
-          "*** WARNING non-zero return value in ctest from: ";
-        errorwarning.Text += argv[0];
+        errorwarning.Text = cmStrCat(
+          "*** WARNING non-zero return value in ctest from: ", argv[0]);
         errorwarning.PreContext.clear();
         errorwarning.PostContext.clear();
         errorwarning.Error = false;
@@ -915,8 +908,8 @@ int cmCTestBuildHandler::RunMakeCommand(const std::string& command,
     // If there was an error running command, report that on the dashboard.
     cmCTestBuildErrorWarning errorwarning;
     errorwarning.LogLine = 1;
-    errorwarning.Text = "*** ERROR executing: ";
-    errorwarning.Text += cmsysProcess_GetErrorString(cp);
+    errorwarning.Text =
+      cmStrCat("*** ERROR executing: ", cmsysProcess_GetErrorString(cp));
     errorwarning.PreContext.clear();
     errorwarning.PostContext.clear();
     errorwarning.Error = true;
diff --git a/Source/CTest/cmCTestCVS.cxx b/Source/CTest/cmCTestCVS.cxx
index 9c03839..560c169 100644
--- a/Source/CTest/cmCTestCVS.cxx
+++ b/Source/CTest/cmCTestCVS.cxx
@@ -4,8 +4,10 @@
 
 #include "cmCTest.h"
 #include "cmProcessTools.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmXMLWriter.h"
+#include "cm_string_view.hxx"
 
 #include "cmsys/FStream.hxx"
 #include "cmsys/RegularExpression.hxx"
@@ -204,8 +206,7 @@ std::string cmCTestCVS::ComputeBranchFlag(std::string const& dir)
   if (tagStream && cmSystemTools::GetLineFromStream(tagStream, tagLine) &&
       tagLine.size() > 1 && tagLine[0] == 'T') {
     // Use the branch specified in the tag file.
-    std::string flag = "-r";
-    flag += tagLine.substr(1);
+    std::string flag = cmStrCat("-r", cm::string_view(tagLine).substr(1));
     return flag;
   }
   // Use the default branch.
diff --git a/Source/CTest/cmCTestConfigureCommand.cxx b/Source/CTest/cmCTestConfigureCommand.cxx
index eb7ecb5..320c184 100644
--- a/Source/CTest/cmCTestConfigureCommand.cxx
+++ b/Source/CTest/cmCTestConfigureCommand.cxx
@@ -76,9 +76,8 @@ cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
         delete gg;
       }
 
-      std::string cmakeConfigureCommand = "\"";
-      cmakeConfigureCommand += cmSystemTools::GetCMakeCommand();
-      cmakeConfigureCommand += "\"";
+      std::string cmakeConfigureCommand =
+        cmStrCat('"', cmSystemTools::GetCMakeCommand(), '"');
 
       for (std::string const& option : options) {
         cmakeConfigureCommand += " \"";
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 2a68544..772fa47 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -130,10 +130,9 @@ void cmCTestCoverageHandler::Initialize()
 
 void cmCTestCoverageHandler::CleanCoverageLogFiles(std::ostream& log)
 {
-  std::string logGlob = this->CTest->GetCTestConfiguration("BuildDirectory");
-  logGlob += "/Testing/";
-  logGlob += this->CTest->GetCurrentTag();
-  logGlob += "/CoverageLog*";
+  std::string logGlob =
+    cmStrCat(this->CTest->GetCTestConfiguration("BuildDirectory"), "/Testing/",
+             this->CTest->GetCurrentTag(), "/CoverageLog*");
   cmsys::Glob gl;
   gl.FindFiles(logGlob);
   std::vector<std::string> const& files = gl.GetFiles();
@@ -1456,8 +1455,7 @@ int cmCTestCoverageHandler::HandleLCovCoverage(
       std::vector<std::string> lcovFiles;
       dir = this->CTest->GetBinaryDir();
       std::string daGlob;
-      daGlob = dir;
-      daGlob += "/*.LCOV";
+      daGlob = cmStrCat(dir, "/*.LCOV");
       cmCTestOptionalLog(
         this->CTest, HANDLER_VERBOSE_OUTPUT,
         "   looking for LCOV files in: " << daGlob << std::endl, this->Quiet);
@@ -1598,12 +1596,10 @@ void cmCTestCoverageHandler::FindGCovFiles(std::vector<std::string>& files)
     cmCTestOptionalLog(
       this->CTest, HANDLER_VERBOSE_OUTPUT,
       "   globbing for coverage in: " << lm.first << std::endl, this->Quiet);
-    std::string daGlob = lm.first;
-    daGlob += "/*.da";
+    std::string daGlob = cmStrCat(lm.first, "/*.da");
     gl.FindFiles(daGlob);
     cmAppend(files, gl.GetFiles());
-    daGlob = lm.first;
-    daGlob += "/*.gcda";
+    daGlob = cmStrCat(lm.first, "/*.gcda");
     gl.FindFiles(daGlob);
     cmAppend(files, gl.GetFiles());
   }
@@ -1632,8 +1628,7 @@ bool cmCTestCoverageHandler::FindLCovFiles(std::vector<std::string>& files)
 
   // DPI file should appear in build directory
   std::string daGlob;
-  daGlob = buildDir;
-  daGlob += "/*.dpi";
+  daGlob = cmStrCat(buildDir, "/*.dpi");
   cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                      "   looking for dpi files in: " << daGlob << std::endl,
                      this->Quiet);
@@ -1946,10 +1941,9 @@ int cmCTestCoverageHandler::RunBullseyeCommand(
   cmCTestRunProcess runCoverageSrc;
   runCoverageSrc.SetCommand(program.c_str());
   runCoverageSrc.AddArgument(arg);
-  std::string stdoutFile = cont->BinaryDir + "/Testing/Temporary/";
-  stdoutFile += this->GetCTestInstance()->GetCurrentTag();
-  stdoutFile += "-";
-  stdoutFile += cmd;
+  std::string stdoutFile =
+    cmStrCat(cont->BinaryDir, "/Testing/Temporary/",
+             this->GetCTestInstance()->GetCurrentTag(), '-', cmd);
   std::string stderrFile = stdoutFile;
   stdoutFile += ".stdout";
   stderrFile += ".stderr";
@@ -2038,9 +2032,7 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary(
       coveredFileNames.insert(file);
       if (!cmSystemTools::FileIsFullPath(sourceFile)) {
         // file will be relative to the binary dir
-        file = cont->BinaryDir;
-        file += "/";
-        file += sourceFile;
+        file = cmStrCat(cont->BinaryDir, '/', sourceFile);
       }
       file = cmSystemTools::CollapseFullPath(file);
       bool shouldIDoCoverage =
@@ -2222,8 +2214,8 @@ int cmCTestCoverageHandler::GetLabelId(std::string const& label)
 
 void cmCTestCoverageHandler::LoadLabels()
 {
-  std::string fileList = this->CTest->GetBinaryDir();
-  fileList += "/CMakeFiles/TargetDirectories.txt";
+  std::string fileList =
+    cmStrCat(this->CTest->GetBinaryDir(), "/CMakeFiles/TargetDirectories.txt");
   cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
                      " target directory list [" << fileList << "]\n",
                      this->Quiet);
@@ -2237,8 +2229,7 @@ void cmCTestCoverageHandler::LoadLabels()
 void cmCTestCoverageHandler::LoadLabels(const char* dir)
 {
   LabelSet& dirLabels = this->TargetDirs[dir];
-  std::string fname = dir;
-  fname += "/Labels.txt";
+  std::string fname = cmStrCat(dir, "/Labels.txt");
   cmsys::ifstream fin(fname.c_str());
   if (!fin) {
     return;
diff --git a/Source/CTest/cmCTestCurl.cxx b/Source/CTest/cmCTestCurl.cxx
index cc63e45..40f5918 100644
--- a/Source/CTest/cmCTestCurl.cxx
+++ b/Source/CTest/cmCTestCurl.cxx
@@ -5,6 +5,7 @@
 #include "cmAlgorithms.h"
 #include "cmCTest.h"
 #include "cmCurl.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <ostream>
@@ -127,9 +128,7 @@ bool cmCTestCurl::UploadFile(std::string const& local_file,
     return false;
   }
   // set the url
-  std::string upload_url = url;
-  upload_url += "?";
-  upload_url += fields;
+  std::string upload_url = cmStrCat(url, '?', fields);
   ::curl_easy_setopt(this->Curl, CURLOPT_URL, upload_url.c_str());
   // now specify which file to upload
   ::curl_easy_setopt(this->Curl, CURLOPT_INFILE, ftpfile);
diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx
index b832018..c13cc80 100644
--- a/Source/CTest/cmCTestGIT.cxx
+++ b/Source/CTest/cmCTestGIT.cxx
@@ -111,8 +111,8 @@ std::string cmCTestGIT::FindGitDir()
   else if (git_dir[0] == '/') {
     // Cygwin Git reports a full path that Cygwin understands, but we
     // are a Windows application.  Run "cygpath" to get Windows path.
-    std::string cygpath_exe = cmSystemTools::GetFilenamePath(git);
-    cygpath_exe += "/cygpath.exe";
+    std::string cygpath_exe =
+      cmStrCat(cmSystemTools::GetFilenamePath(git), "/cygpath.exe");
     if (cmSystemTools::FileExists(cygpath_exe)) {
       char const* cygpath[] = { cygpath_exe.c_str(), "-w", git_dir.c_str(),
                                 0 };
diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx
index 4708a71..ac52581 100644
--- a/Source/CTest/cmCTestLaunch.cxx
+++ b/Source/CTest/cmCTestLaunch.cxx
@@ -176,14 +176,8 @@ void cmCTestLaunch::ComputeFileNames()
   this->LogHash = md5.FinalizeHex();
 
   // We store stdout and stderr in temporary log files.
-  this->LogOut = this->LogDir;
-  this->LogOut += "launch-";
-  this->LogOut += this->LogHash;
-  this->LogOut += "-out.txt";
-  this->LogErr = this->LogDir;
-  this->LogErr += "launch-";
-  this->LogErr += this->LogHash;
-  this->LogErr += "-err.txt";
+  this->LogOut = cmStrCat(this->LogDir, "launch-", this->LogHash, "-out.txt");
+  this->LogErr = cmStrCat(this->LogDir, "launch-", this->LogHash, "-err.txt");
 }
 
 void cmCTestLaunch::RunChild()
@@ -282,10 +276,8 @@ void cmCTestLaunch::LoadLabels()
   }
 
   // Labels are listed in per-target files.
-  std::string fname = this->OptionBuildDir;
-  fname += "/CMakeFiles/";
-  fname += this->OptionTargetName;
-  fname += ".dir/Labels.txt";
+  std::string fname = cmStrCat(this->OptionBuildDir, "/CMakeFiles/",
+                               this->OptionTargetName, ".dir/Labels.txt");
 
   // We are interested in per-target labels for this source file.
   std::string source = this->OptionSource;
@@ -339,10 +331,9 @@ bool cmCTestLaunch::IsError() const
 void cmCTestLaunch::WriteXML()
 {
   // Name the xml file.
-  std::string logXML = this->LogDir;
-  logXML += this->IsError() ? "error-" : "warning-";
-  logXML += this->LogHash;
-  logXML += ".xml";
+  std::string logXML =
+    cmStrCat(this->LogDir, this->IsError() ? "error-" : "warning-",
+             this->LogHash, ".xml");
 
   // Use cmGeneratedFileStream to atomically create the report file.
   cmGeneratedFileStream fxml(logXML);
@@ -545,10 +536,7 @@ void cmCTestLaunch::LoadScrapeRules()
 void cmCTestLaunch::LoadScrapeRules(
   const char* purpose, std::vector<cmsys::RegularExpression>& regexps)
 {
-  std::string fname = this->LogDir;
-  fname += "Custom";
-  fname += purpose;
-  fname += ".txt";
+  std::string fname = cmStrCat(this->LogDir, "Custom", purpose, ".txt");
   cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary);
   std::string line;
   cmsys::RegularExpression rex;
@@ -616,8 +604,7 @@ void cmCTestLaunch::LoadConfig()
   cm.GetCurrentSnapshot().SetDefaultDefinitions();
   cmGlobalGenerator gg(&cm);
   cmMakefile mf(&gg, cm.GetCurrentSnapshot());
-  std::string fname = this->LogDir;
-  fname += "CTestLaunchConfig.cmake";
+  std::string fname = cmStrCat(this->LogDir, "CTestLaunchConfig.cmake");
   if (cmSystemTools::FileExists(fname) && mf.ReadListFile(fname)) {
     this->SourceDir = mf.GetSafeDefinition("CTEST_SOURCE_DIRECTORY");
     cmSystemTools::ConvertToUnixSlashes(this->SourceDir);
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index fb91322..89b585e 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -6,6 +6,7 @@
 #include "cmCTestMemCheckHandler.h"
 #include "cmCTestMultiProcessHandler.h"
 #include "cmProcess.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmWorkingDirectory.h"
 
@@ -86,16 +87,13 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
     for (auto& pass : this->TestProperties->RequiredRegularExpressions) {
       if (pass.first.find(this->ProcessOutput)) {
         found = true;
-        reason = "Required regular expression found.";
-        reason += " Regex=[";
-        reason += pass.second;
-        reason += "]";
+        reason = cmStrCat("Required regular expression found. Regex=[",
+                          pass.second, ']');
         break;
       }
     }
     if (!found) {
-      reason = "Required regular expression not found.";
-      reason += " Regex=[";
+      reason = "Required regular expression not found. Regex=[";
       for (auto& pass : this->TestProperties->RequiredRegularExpressions) {
         reason += pass.second;
         reason += "\n";
@@ -108,10 +106,8 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
       this->FailedDependencies.empty()) {
     for (auto& fail : this->TestProperties->ErrorRegularExpressions) {
       if (fail.first.find(this->ProcessOutput)) {
-        reason = "Error regular expression found in output.";
-        reason += " Regex=[";
-        reason += fail.second;
-        reason += "]";
+        reason = cmStrCat("Error regular expression found in output. Regex=[",
+                          fail.second, ']');
         forceFail = true;
         break;
       }
@@ -121,10 +117,8 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started)
       this->FailedDependencies.empty()) {
     for (auto& skip : this->TestProperties->SkipRegularExpressions) {
       if (skip.first.find(this->ProcessOutput)) {
-        reason = "Skip regular expression found in output.";
-        reason += " Regex=[";
-        reason += skip.second;
-        reason += "]";
+        reason = cmStrCat("Skip regular expression found in output. Regex=[",
+                          skip.second, ']');
         forceSkip = true;
         break;
       }
@@ -504,12 +498,11 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total)
     this->TestProcess = cm::make_unique<cmProcess>(*this);
     std::string msg;
     if (this->CTest->GetConfigType().empty()) {
-      msg = "Test not available without configuration.";
-      msg += "  (Missing \"-C <config>\"?)";
+      msg = "Test not available without configuration.  (Missing \"-C "
+            "<config>\"?)";
     } else {
-      msg = "Test not available in configuration \"";
-      msg += this->CTest->GetConfigType();
-      msg += "\".";
+      msg = cmStrCat("Test not available in configuration \"",
+                     this->CTest->GetConfigType(), "\".");
     }
     *this->TestHandler->LogFile << msg << std::endl;
     cmCTestLog(this->CTest, ERROR_MESSAGE, msg << std::endl);
diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx
index c834686..dc1472b 100644
--- a/Source/CTest/cmCTestSVN.cxx
+++ b/Source/CTest/cmCTestSVN.cxx
@@ -6,6 +6,7 @@
 #include "cmCTest.h"
 #include "cmCTestVC.h"
 #include "cmProcessTools.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmXMLParser.h"
 #include "cmXMLWriter.h"
@@ -143,9 +144,8 @@ bool cmCTestSVN::NoteNewRevision()
     // the repository root.
     if (!svninfo.Root.empty() &&
         cmCTestSVNPathStarts(svninfo.URL, svninfo.Root)) {
-      svninfo.Base =
-        cmCTest::DecodeURL(svninfo.URL.substr(svninfo.Root.size()));
-      svninfo.Base += "/";
+      svninfo.Base = cmStrCat(
+        cmCTest::DecodeURL(svninfo.URL.substr(svninfo.Root.size())), '/');
     }
     this->Log << "Repository '" << svninfo.LocalPath
               << "' Base = " << svninfo.Base << "\n";
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index 1c40a58..52d4596 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -451,12 +451,13 @@ int cmCTestScriptHandler::ExtractVariables()
   // make sure the required info is here
   if (this->SourceDir.empty() || this->BinaryDir.empty() ||
       this->CTestCmd.empty()) {
-    std::string msg = "CTEST_SOURCE_DIRECTORY = ";
-    msg += (!this->SourceDir.empty()) ? this->SourceDir.c_str() : "(Null)";
-    msg += "\nCTEST_BINARY_DIRECTORY = ";
-    msg += (!this->BinaryDir.empty()) ? this->BinaryDir.c_str() : "(Null)";
-    msg += "\nCTEST_COMMAND = ";
-    msg += (!this->CTestCmd.empty()) ? this->CTestCmd.c_str() : "(Null)";
+    std::string msg =
+      cmStrCat("CTEST_SOURCE_DIRECTORY = ",
+               (!this->SourceDir.empty()) ? this->SourceDir.c_str() : "(Null)",
+               "\nCTEST_BINARY_DIRECTORY = ",
+               (!this->BinaryDir.empty()) ? this->BinaryDir.c_str() : "(Null)",
+               "\nCTEST_COMMAND = ",
+               (!this->CTestCmd.empty()) ? this->CTestCmd.c_str() : "(Null)");
     cmSystemTools::Error(
       "Some required settings in the configuration file were missing:\n" +
       msg);
@@ -610,10 +611,8 @@ int cmCTestScriptHandler::BackupDirectories()
   int retVal;
 
   // compute the backup names
-  this->BackupSourceDir = this->SourceDir;
-  this->BackupSourceDir += "_CMakeBackup";
-  this->BackupBinaryDir = this->BinaryDir;
-  this->BackupBinaryDir += "_CMakeBackup";
+  this->BackupSourceDir = cmStrCat(this->SourceDir, "_CMakeBackup");
+  this->BackupBinaryDir = cmStrCat(this->BinaryDir, "_CMakeBackup");
 
   // backup the binary and src directories if requested
   if (this->Backup) {
@@ -653,9 +652,7 @@ int cmCTestScriptHandler::PerformExtraUpdates()
     std::vector<std::string> cvsArgs;
     cmExpandList(eu, cvsArgs);
     if (cvsArgs.size() == 2) {
-      std::string fullCommand = command;
-      fullCommand += " update ";
-      fullCommand += cvsArgs[1];
+      std::string fullCommand = cmStrCat(command, " update ", cvsArgs[1]);
       output.clear();
       retVal = 0;
       cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT,
@@ -756,9 +753,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
   int cmakeFailed = 0;
   std::string cmakeFailedOuput;
   if (!this->CMakeCmd.empty()) {
-    command = this->CMakeCmd;
-    command += " \"";
-    command += this->SourceDir;
+    command = cmStrCat(this->CMakeCmd, " \"", this->SourceDir);
     output.clear();
     command += "\"";
     retVal = 0;
@@ -839,8 +834,7 @@ int cmCTestScriptHandler::RunConfigurationDashboard()
 bool cmCTestScriptHandler::WriteInitialCache(const char* directory,
                                              const char* text)
 {
-  std::string cacheFile = directory;
-  cacheFile += "/CMakeCache.txt";
+  std::string cacheFile = cmStrCat(directory, "/CMakeCache.txt");
   cmGeneratedFileStream fout(cacheFile);
   if (!fout) {
     return false;
@@ -905,8 +899,7 @@ bool cmCTestScriptHandler::EmptyBinaryDirectory(const char* sname)
   }
 
   // try to avoid deleting directories that we shouldn't
-  std::string check = sname;
-  check += "/CMakeCache.txt";
+  std::string check = cmStrCat(sname, "/CMakeCache.txt");
 
   if (!cmSystemTools::FileExists(check)) {
     return false;
diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx
index 7ae0d26..4cb19f8 100644
--- a/Source/CTest/cmCTestTestHandler.cxx
+++ b/Source/CTest/cmCTestTestHandler.cxx
@@ -77,9 +77,7 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args,
     if (cmSystemTools::FileIsFullPath(arg)) {
       fname = arg;
     } else {
-      fname = cwd;
-      fname += "/";
-      fname += arg;
+      fname = cmStrCat(cwd, '/', arg);
     }
 
     if (!cmSystemTools::FileIsDirectory(fname)) {
@@ -110,8 +108,7 @@ bool cmCTestSubdirCommand::InitialPass(std::vector<std::string> const& args,
       readit = this->Makefile->ReadDependentFile(fname);
     }
     if (!readit) {
-      std::string m = "Could not find include file: ";
-      m += fname;
+      std::string m = cmStrCat("Could not find include file: ", fname);
       this->SetError(m);
       return false;
     }
@@ -150,9 +147,8 @@ bool cmCTestAddSubdirectoryCommand::InitialPass(
     return false;
   }
 
-  std::string fname = cmSystemTools::GetCurrentWorkingDirectory();
-  fname += "/";
-  fname += args[0];
+  std::string fname =
+    cmStrCat(cmSystemTools::GetCurrentWorkingDirectory(), '/', args[0]);
 
   if (!cmSystemTools::FileExists(fname)) {
     // No subdirectory? So what...
@@ -176,8 +172,7 @@ bool cmCTestAddSubdirectoryCommand::InitialPass(
     readit = this->Makefile->ReadDependentFile(fname);
   }
   if (!readit) {
-    std::string m = "Could not find include file: ";
-    m += fname;
+    std::string m = cmStrCat("Could not find include file: ", fname);
     this->SetError(m);
     return false;
   }
@@ -1552,50 +1547,32 @@ void cmCTestTestHandler::AddConfigurations(
   attemptedConfigs.emplace_back();
 
   if (!ctest->GetConfigType().empty()) {
-    tempPath = filepath;
-    tempPath += ctest->GetConfigType();
-    tempPath += "/";
-    tempPath += filename;
+    tempPath = cmStrCat(filepath, ctest->GetConfigType(), '/', filename);
     attempted.push_back(tempPath);
     attemptedConfigs.push_back(ctest->GetConfigType());
     // If the file is an OSX bundle then the configtype
     // will be at the start of the path
-    tempPath = ctest->GetConfigType();
-    tempPath += "/";
-    tempPath += filepath;
-    tempPath += filename;
+    tempPath = cmStrCat(ctest->GetConfigType(), '/', filepath, filename);
     attempted.push_back(tempPath);
     attemptedConfigs.push_back(ctest->GetConfigType());
   } else {
     // no config specified - try some options...
-    tempPath = filepath;
-    tempPath += "Release/";
-    tempPath += filename;
+    tempPath = cmStrCat(filepath, "Release/", filename);
     attempted.push_back(tempPath);
     attemptedConfigs.emplace_back("Release");
-    tempPath = filepath;
-    tempPath += "Debug/";
-    tempPath += filename;
+    tempPath = cmStrCat(filepath, "Debug/", filename);
     attempted.push_back(tempPath);
     attemptedConfigs.emplace_back("Debug");
-    tempPath = filepath;
-    tempPath += "MinSizeRel/";
-    tempPath += filename;
+    tempPath = cmStrCat(filepath, "MinSizeRel/", filename);
     attempted.push_back(tempPath);
     attemptedConfigs.emplace_back("MinSizeRel");
-    tempPath = filepath;
-    tempPath += "RelWithDebInfo/";
-    tempPath += filename;
+    tempPath = cmStrCat(filepath, "RelWithDebInfo/", filename);
     attempted.push_back(tempPath);
     attemptedConfigs.emplace_back("RelWithDebInfo");
-    tempPath = filepath;
-    tempPath += "Deployment/";
-    tempPath += filename;
+    tempPath = cmStrCat(filepath, "Deployment/", filename);
     attempted.push_back(tempPath);
     attemptedConfigs.emplace_back("Deployment");
-    tempPath = filepath;
-    tempPath += "Development/";
-    tempPath += filename;
+    tempPath = cmStrCat(filepath, "Development/", filename);
     attempted.push_back(tempPath);
     attemptedConfigs.emplace_back("Deployment");
   }
@@ -1649,8 +1626,8 @@ std::string cmCTestTestHandler::FindExecutable(
     // then try with the exe extension
     else {
       failed.push_back(attempted[ai]);
-      tempPath = attempted[ai];
-      tempPath += cmSystemTools::GetExecutableExtension();
+      tempPath =
+        cmStrCat(attempted[ai], cmSystemTools::GetExecutableExtension());
       if (cmSystemTools::FileExists(tempPath) &&
           !cmSystemTools::FileIsDirectory(tempPath)) {
         fullPath = cmSystemTools::CollapseFullPath(tempPath);
diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx
index d80b5a5..a6a3542 100644
--- a/Source/CTest/cmCTestUpdateHandler.cxx
+++ b/Source/CTest/cmCTestUpdateHandler.cxx
@@ -12,6 +12,7 @@
 #include "cmCTestSVN.h"
 #include "cmCTestVC.h"
 #include "cmGeneratedFileStream.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmVersion.h"
 #include "cmXMLWriter.h"
@@ -266,33 +267,27 @@ int cmCTestUpdateHandler::DetectVCS(const char* dir)
   if (cmSystemTools::FileExists(sourceDirectory)) {
     return cmCTestUpdateHandler::e_SVN;
   }
-  sourceDirectory = dir;
-  sourceDirectory += "/CVS";
+  sourceDirectory = cmStrCat(dir, "/CVS");
   if (cmSystemTools::FileExists(sourceDirectory)) {
     return cmCTestUpdateHandler::e_CVS;
   }
-  sourceDirectory = dir;
-  sourceDirectory += "/.bzr";
+  sourceDirectory = cmStrCat(dir, "/.bzr");
   if (cmSystemTools::FileExists(sourceDirectory)) {
     return cmCTestUpdateHandler::e_BZR;
   }
-  sourceDirectory = dir;
-  sourceDirectory += "/.git";
+  sourceDirectory = cmStrCat(dir, "/.git");
   if (cmSystemTools::FileExists(sourceDirectory)) {
     return cmCTestUpdateHandler::e_GIT;
   }
-  sourceDirectory = dir;
-  sourceDirectory += "/.hg";
+  sourceDirectory = cmStrCat(dir, "/.hg");
   if (cmSystemTools::FileExists(sourceDirectory)) {
     return cmCTestUpdateHandler::e_HG;
   }
-  sourceDirectory = dir;
-  sourceDirectory += "/.p4";
+  sourceDirectory = cmStrCat(dir, "/.p4");
   if (cmSystemTools::FileExists(sourceDirectory)) {
     return cmCTestUpdateHandler::e_P4;
   }
-  sourceDirectory = dir;
-  sourceDirectory += "/.p4config";
+  sourceDirectory = cmStrCat(dir, "/.p4config");
   if (cmSystemTools::FileExists(sourceDirectory)) {
     return cmCTestUpdateHandler::e_P4;
   }
diff --git a/Source/CTest/cmParseCacheCoverage.cxx b/Source/CTest/cmParseCacheCoverage.cxx
index ca1fe70..cd2bb1a 100644
--- a/Source/CTest/cmParseCacheCoverage.cxx
+++ b/Source/CTest/cmParseCacheCoverage.cxx
@@ -2,6 +2,7 @@
 
 #include "cmCTest.h"
 #include "cmCTestCoverageHandler.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include "cmsys/Directory.hxx"
@@ -30,9 +31,7 @@ bool cmParseCacheCoverage::LoadCoverageData(const char* d)
   for (i = 0; i < numf; i++) {
     std::string file = dir.GetFile(i);
     if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
-      std::string path = d;
-      path += "/";
-      path += file;
+      std::string path = cmStrCat(d, '/', file);
       if (cmSystemTools::GetFilenameLastExtension(path) == ".cmcov") {
         if (!this->ReadCMCovFile(path.c_str())) {
           return false;
diff --git a/Source/CTest/cmParseGTMCoverage.cxx b/Source/CTest/cmParseGTMCoverage.cxx
index 881bf2d..621ca79 100644
--- a/Source/CTest/cmParseGTMCoverage.cxx
+++ b/Source/CTest/cmParseGTMCoverage.cxx
@@ -31,9 +31,7 @@ bool cmParseGTMCoverage::LoadCoverageData(const char* d)
   for (i = 0; i < numf; i++) {
     std::string file = dir.GetFile(i);
     if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
-      std::string path = d;
-      path += "/";
-      path += file;
+      std::string path = cmStrCat(d, '/', file);
       if (cmSystemTools::GetFilenameLastExtension(path) == ".mcov") {
         if (!this->ReadMCovFile(path.c_str())) {
           return false;
diff --git a/Source/CTest/cmParseJacocoCoverage.cxx b/Source/CTest/cmParseJacocoCoverage.cxx
index 5f1e712..374acad 100644
--- a/Source/CTest/cmParseJacocoCoverage.cxx
+++ b/Source/CTest/cmParseJacocoCoverage.cxx
@@ -104,9 +104,7 @@ protected:
                                 std::string const& baseDir)
   {
     // Search for the file in the baseDir and its subdirectories.
-    std::string packageGlob = baseDir;
-    packageGlob += "/";
-    packageGlob += fileName;
+    std::string packageGlob = cmStrCat(baseDir, '/', fileName);
     cmsys::Glob gl;
     gl.RecurseOn();
     gl.RecurseThroughSymlinksOn();
diff --git a/Source/CTest/cmParseMumpsCoverage.cxx b/Source/CTest/cmParseMumpsCoverage.cxx
index 4a81ee4..afd7dc3 100644
--- a/Source/CTest/cmParseMumpsCoverage.cxx
+++ b/Source/CTest/cmParseMumpsCoverage.cxx
@@ -2,6 +2,7 @@
 
 #include "cmCTest.h"
 #include "cmCTestCoverageHandler.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include "cmsys/FStream.hxx"
@@ -107,8 +108,7 @@ bool cmParseMumpsCoverage::LoadPackages(const char* d)
 {
   cmsys::Glob glob;
   glob.RecurseOn();
-  std::string pat = d;
-  pat += "/*.m";
+  std::string pat = cmStrCat(d, "/*.m");
   glob.FindFiles(pat);
   for (std::string& file : glob.GetFiles()) {
     std::string name = cmSystemTools::GetFilenameName(file);
diff --git a/Source/CTest/cmParsePHPCoverage.cxx b/Source/CTest/cmParsePHPCoverage.cxx
index a6e65c9..870e222 100644
--- a/Source/CTest/cmParsePHPCoverage.cxx
+++ b/Source/CTest/cmParsePHPCoverage.cxx
@@ -2,6 +2,7 @@
 
 #include "cmCTest.h"
 #include "cmCTestCoverageHandler.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include "cmsys/Directory.hxx"
@@ -210,9 +211,7 @@ bool cmParsePHPCoverage::ReadPHPCoverageDirectory(const char* d)
   for (i = 0; i < numf; i++) {
     std::string file = dir.GetFile(i);
     if (file != "." && file != ".." && !cmSystemTools::FileIsDirectory(file)) {
-      std::string path = d;
-      path += "/";
-      path += file;
+      std::string path = cmStrCat(d, '/', file);
       if (!this->ReadPHPData(path.c_str())) {
         return false;
       }
diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx
index 7a3b82e..61d2ed3 100644
--- a/Source/CTest/cmProcess.cxx
+++ b/Source/CTest/cmProcess.cxx
@@ -7,6 +7,7 @@
 #include "cmCTestRunTest.h"
 #include "cmCTestTestHandler.h"
 #include "cmGetPipes.h"
+#include "cmStringAlgorithms.h"
 #include "cmsys/Process.h"
 
 #include <iostream>
@@ -694,8 +695,7 @@ std::string cmProcess::GetExitExceptionString()
 #    endif
 #  endif
     default:
-      exception_str = "Signal ";
-      exception_str += std::to_string(this->Signal);
+      exception_str = cmStrCat("Signal ", this->Signal);
   }
 #endif
   return exception_str;
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index 9115a3b..1b25716 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -48,8 +48,8 @@ cmCursesMainForm::cmCursesMainForm(std::vector<std::string> args,
     cmSystemTools::GetCMakeCursesCommand());
 
   // create the arguments for the cmake object
-  std::string whereCMake = cmSystemTools::GetProgramPath(this->Args[0]);
-  whereCMake += "/cmake";
+  std::string whereCMake =
+    cmStrCat(cmSystemTools::GetProgramPath(this->Args[0]), "/cmake");
   this->Args[0] = whereCMake;
   this->CMakeInstance->SetArgs(this->Args);
   this->SearchString = "";
diff --git a/Source/QtDialog/FirstConfigure.cxx b/Source/QtDialog/FirstConfigure.cxx
index 364a378..d9a8aff 100644
--- a/Source/QtDialog/FirstConfigure.cxx
+++ b/Source/QtDialog/FirstConfigure.cxx
@@ -2,6 +2,7 @@
 #include "FirstConfigure.h"
 
 #include "Compilers.h"
+#include "cmStringAlgorithms.h"
 
 #include <QComboBox>
 #include <QRadioButton>
@@ -183,10 +184,9 @@ void StartCompilerSetup::onGeneratorChanged(QString const& name)
   if (GeneratorsSupportingPlatform.contains(name)) {
 
     // Change the label title to include the default platform
-    std::string label = "Optional platform for generator";
-    label += "(if empty, generator uses: ";
-    label += this->GeneratorDefaultPlatform[name].toStdString();
-    label += ")";
+    std::string label =
+      cmStrCat("Optional platform for generator(if empty, generator uses: ",
+               this->GeneratorDefaultPlatform[name].toStdString(), ')');
     this->PlatformLabel->setText(tr(label.c_str()));
 
     // Regenerate the list of supported platform
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index 11d28c2..d2330e1 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -14,6 +14,7 @@
 #include "cmMessageType.h"
 #include "cmPolicies.h"
 #include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 
@@ -202,8 +203,7 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
             // and later references "${CMAKE_CURRENT_SOURCE_DIR}/out.txt".
             // This is fairly obscure so we can wait for someone to
             // complain.
-            filename = mf.GetCurrentBinaryDirectory();
-            filename += "/";
+            filename = cmStrCat(mf.GetCurrentBinaryDirectory(), '/');
           }
           filename += copy;
           cmSystemTools::ConvertToUnixSlashes(filename);
diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx
index c14b745..caea510 100644
--- a/Source/cmAddCustomTargetCommand.cxx
+++ b/Source/cmAddCustomTargetCommand.cxx
@@ -12,6 +12,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 
@@ -122,8 +123,7 @@ bool cmAddCustomTargetCommand(std::vector<std::string> const& args,
         case doing_byproducts: {
           std::string filename;
           if (!cmSystemTools::FileIsFullPath(copy)) {
-            filename = mf.GetCurrentBinaryDirectory();
-            filename += "/";
+            filename = cmStrCat(mf.GetCurrentBinaryDirectory(), '/');
           }
           filename += copy;
           cmSystemTools::ConvertToUnixSlashes(filename);
diff --git a/Source/cmAddSubDirectoryCommand.cxx b/Source/cmAddSubDirectoryCommand.cxx
index 50c682f..17bdc4a 100644
--- a/Source/cmAddSubDirectoryCommand.cxx
+++ b/Source/cmAddSubDirectoryCommand.cxx
@@ -8,6 +8,7 @@
 #include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 #include "cmRange.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 bool cmAddSubDirectoryCommand(std::vector<std::string> const& args,
@@ -45,14 +46,11 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args,
   if (cmSystemTools::FileIsFullPath(srcArg)) {
     srcPath = srcArg;
   } else {
-    srcPath = mf.GetCurrentSourceDirectory();
-    srcPath += "/";
-    srcPath += srcArg;
+    srcPath = cmStrCat(mf.GetCurrentSourceDirectory(), '/', srcArg);
   }
   if (!cmSystemTools::FileIsDirectory(srcPath)) {
-    std::string error = "given source \"";
-    error += srcArg;
-    error += "\" which is not an existing directory.";
+    std::string error = cmStrCat("given source \"", srcArg,
+                                 "\" which is not an existing directory.");
     status.SetError(error);
     return false;
   }
@@ -95,9 +93,7 @@ bool cmAddSubDirectoryCommand(std::vector<std::string> const& args,
     if (cmSystemTools::FileIsFullPath(binArg)) {
       binPath = binArg;
     } else {
-      binPath = mf.GetCurrentBinaryDirectory();
-      binPath += "/";
-      binPath += binArg;
+      binPath = cmStrCat(mf.GetCurrentBinaryDirectory(), '/', binArg);
     }
   }
   binPath = cmSystemTools::CollapseFullPath(binPath);
diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx
index 359d57a..a063fd9 100644
--- a/Source/cmArchiveWrite.cxx
+++ b/Source/cmArchiveWrite.cxx
@@ -3,12 +3,14 @@
 #include "cmArchiveWrite.h"
 
 #include "cmLocale.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cm_get_date.h"
 #include "cm_libarchive.h"
 #include "cmsys/Directory.hxx"
 #include "cmsys/Encoding.hxx"
 #include "cmsys/FStream.hxx"
+
 #include <iostream>
 #include <sstream>
 #include <string.h>
@@ -85,22 +87,22 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
   switch (c) {
     case CompressNone:
       if (archive_write_add_filter_none(this->Archive) != ARCHIVE_OK) {
-        this->Error = "archive_write_add_filter_none: ";
-        this->Error += cm_archive_error_string(this->Archive);
+        this->Error = cmStrCat("archive_write_add_filter_none: ",
+                               cm_archive_error_string(this->Archive));
         return;
       }
       break;
     case CompressCompress:
       if (archive_write_add_filter_compress(this->Archive) != ARCHIVE_OK) {
-        this->Error = "archive_write_add_filter_compress: ";
-        this->Error += cm_archive_error_string(this->Archive);
+        this->Error = cmStrCat("archive_write_add_filter_compress: ",
+                               cm_archive_error_string(this->Archive));
         return;
       }
       break;
     case CompressGZip: {
       if (archive_write_add_filter_gzip(this->Archive) != ARCHIVE_OK) {
-        this->Error = "archive_write_add_filter_gzip: ";
-        this->Error += cm_archive_error_string(this->Archive);
+        this->Error = cmStrCat("archive_write_add_filter_gzip: ",
+                               cm_archive_error_string(this->Archive));
         return;
       }
       std::string source_date_epoch;
@@ -110,60 +112,60 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
         // The next best thing is to omit the timestamp entirely.
         if (archive_write_set_filter_option(this->Archive, "gzip", "timestamp",
                                             nullptr) != ARCHIVE_OK) {
-          this->Error = "archive_write_set_filter_option: ";
-          this->Error += cm_archive_error_string(this->Archive);
+          this->Error = cmStrCat("archive_write_set_filter_option: ",
+                                 cm_archive_error_string(this->Archive));
           return;
         }
       }
     } break;
     case CompressBZip2:
       if (archive_write_add_filter_bzip2(this->Archive) != ARCHIVE_OK) {
-        this->Error = "archive_write_add_filter_bzip2: ";
-        this->Error += cm_archive_error_string(this->Archive);
+        this->Error = cmStrCat("archive_write_add_filter_bzip2: ",
+                               cm_archive_error_string(this->Archive));
         return;
       }
       break;
     case CompressLZMA:
       if (archive_write_add_filter_lzma(this->Archive) != ARCHIVE_OK) {
-        this->Error = "archive_write_add_filter_lzma: ";
-        this->Error += cm_archive_error_string(this->Archive);
+        this->Error = cmStrCat("archive_write_add_filter_lzma: ",
+                               cm_archive_error_string(this->Archive));
         return;
       }
       break;
     case CompressXZ:
       if (archive_write_add_filter_xz(this->Archive) != ARCHIVE_OK) {
-        this->Error = "archive_write_add_filter_xz: ";
-        this->Error += cm_archive_error_string(this->Archive);
+        this->Error = cmStrCat("archive_write_add_filter_xz: ",
+                               cm_archive_error_string(this->Archive));
         return;
       }
       break;
     case CompressZstd:
       if (archive_write_add_filter_zstd(this->Archive) != ARCHIVE_OK) {
-        this->Error = "archive_write_add_filter_zstd: ";
-        this->Error += cm_archive_error_string(this->Archive);
+        this->Error = cmStrCat("archive_write_add_filter_zstd: ",
+                               cm_archive_error_string(this->Archive));
         return;
       }
       break;
   }
 #if !defined(_WIN32) || defined(__CYGWIN__)
   if (archive_read_disk_set_standard_lookup(this->Disk) != ARCHIVE_OK) {
-    this->Error = "archive_read_disk_set_standard_lookup: ";
-    this->Error += cm_archive_error_string(this->Archive);
+    this->Error = cmStrCat("archive_read_disk_set_standard_lookup: ",
+                           cm_archive_error_string(this->Archive));
     return;
   }
 #endif
 
   if (archive_write_set_format_by_name(this->Archive, format.c_str()) !=
       ARCHIVE_OK) {
-    this->Error = "archive_write_set_format_by_name: ";
-    this->Error += cm_archive_error_string(this->Archive);
+    this->Error = cmStrCat("archive_write_set_format_by_name: ",
+                           cm_archive_error_string(this->Archive));
     return;
   }
 
   // do not pad the last block!!
   if (archive_write_set_bytes_in_last_block(this->Archive, 1)) {
-    this->Error = "archive_write_set_bytes_in_last_block: ";
-    this->Error += cm_archive_error_string(this->Archive);
+    this->Error = cmStrCat("archive_write_set_bytes_in_last_block: ",
+                           cm_archive_error_string(this->Archive));
     return;
   }
 
@@ -171,8 +173,8 @@ cmArchiveWrite::cmArchiveWrite(std::ostream& os, Compress c,
         this->Archive, this, nullptr,
         reinterpret_cast<archive_write_callback*>(&Callback::Write),
         nullptr) != ARCHIVE_OK) {
-    this->Error = "archive_write_open: ";
-    this->Error += cm_archive_error_string(this->Archive);
+    this->Error =
+      cmStrCat("archive_write_open: ", cm_archive_error_string(this->Archive));
     return;
   }
 }
@@ -205,8 +207,7 @@ bool cmArchiveWrite::AddPath(const char* path, size_t skip, const char* prefix,
   }
   cmsys::Directory d;
   if (d.Load(path)) {
-    std::string next = path;
-    next += "/";
+    std::string next = cmStrCat(path, '/');
     std::string::size_type end = next.size();
     unsigned long n = d.GetNumberOfFiles();
     for (unsigned long i = 0; i < n; ++i) {
@@ -237,8 +238,7 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
   static_cast<void>(localeRAII);
 
   // Meta-data.
-  std::string dest = prefix ? prefix : "";
-  dest += out;
+  std::string dest = cmStrCat(prefix ? prefix : "", out);
   if (this->Verbose) {
     std::cout << dest << "\n";
   }
@@ -247,10 +247,8 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
   cm_archive_entry_copy_pathname(e, dest);
   if (archive_read_disk_entry_from_file(this->Disk, e, -1, nullptr) !=
       ARCHIVE_OK) {
-    this->Error = "Unable to read from file '";
-    this->Error += file;
-    this->Error += "': ";
-    this->Error += cm_archive_error_string(this->Disk);
+    this->Error = cmStrCat("Unable to read from file '", file,
+                           "': ", cm_archive_error_string(this->Disk));
     return false;
   }
   if (!this->MTime.empty()) {
@@ -258,9 +256,7 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
     time(&now);
     time_t t = cm_get_date(now, this->MTime.c_str());
     if (t == -1) {
-      this->Error = "unable to parse mtime '";
-      this->Error += this->MTime;
-      this->Error += "'";
+      this->Error = cmStrCat("unable to parse mtime '", this->MTime, '\'');
       return false;
     }
     archive_entry_set_mtime(e, t, 0);
@@ -310,8 +306,8 @@ bool cmArchiveWrite::AddFile(const char* file, size_t skip, const char* prefix)
   }
 
   if (archive_write_header(this->Archive, e) != ARCHIVE_OK) {
-    this->Error = "archive_write_header: ";
-    this->Error += cm_archive_error_string(this->Archive);
+    this->Error = cmStrCat("archive_write_header: ",
+                           cm_archive_error_string(this->Archive));
     return false;
   }
 
@@ -329,10 +325,8 @@ bool cmArchiveWrite::AddData(const char* file, size_t size)
 {
   cmsys::ifstream fin(file, std::ios::in | std::ios::binary);
   if (!fin) {
-    this->Error = "Error opening \"";
-    this->Error += file;
-    this->Error += "\": ";
-    this->Error += cmSystemTools::GetLastSystemError();
+    this->Error = cmStrCat("Error opening \"", file,
+                           "\": ", cmSystemTools::GetLastSystemError());
     return false;
   }
 
@@ -350,17 +344,15 @@ bool cmArchiveWrite::AddData(const char* file, size_t size)
       break;
     }
     if (archive_write_data(this->Archive, buffer, nnext) != nnext_s) {
-      this->Error = "archive_write_data: ";
-      this->Error += cm_archive_error_string(this->Archive);
+      this->Error = cmStrCat("archive_write_data: ",
+                             cm_archive_error_string(this->Archive));
       return false;
     }
     nleft -= nnext;
   }
   if (nleft > 0) {
-    this->Error = "Error reading \"";
-    this->Error += file;
-    this->Error += "\": ";
-    this->Error += cmSystemTools::GetLastSystemError();
+    this->Error = cmStrCat("Error reading \"", file,
+                           "\": ", cmSystemTools::GetLastSystemError());
     return false;
   }
   return true;
diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx
index 83199b4..7bf19d0 100644
--- a/Source/cmAuxSourceDirectoryCommand.cxx
+++ b/Source/cmAuxSourceDirectoryCommand.cxx
@@ -27,9 +27,7 @@ bool cmAuxSourceDirectoryCommand(std::vector<std::string> const& args,
   std::string const& templateDirectory = args[0];
   std::string tdir;
   if (!cmSystemTools::FileIsFullPath(templateDirectory)) {
-    tdir = mf.GetCurrentSourceDirectory();
-    tdir += "/";
-    tdir += templateDirectory;
+    tdir = cmStrCat(mf.GetCurrentSourceDirectory(), '/', templateDirectory);
   } else {
     tdir = templateDirectory;
   }
@@ -56,9 +54,7 @@ bool cmAuxSourceDirectoryCommand(std::vector<std::string> const& args,
         // Process only source files
         auto cm = mf.GetCMakeInstance();
         if (!base.empty() && cm->IsSourceExtension(ext)) {
-          std::string fullname = templateDirectory;
-          fullname += "/";
-          fullname += file;
+          std::string fullname = cmStrCat(templateDirectory, '/', file);
           // add the file as a class file so
           // depends can be done
           cmSourceFile* sf = mf.GetOrCreateSource(fullname);
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index d06ec20..f0c1845 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -690,9 +690,7 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir,
 
   // Next, try the various source extensions
   for (std::string const& ext : sourceExts) {
-    hname = pathname;
-    hname += ".";
-    hname += ext;
+    hname = cmStrCat(pathname, '.', ext);
     if (cmSystemTools::FileExists(hname)) {
       sf->SourceExtension = ext;
       sf->FullPath = hname;
@@ -702,9 +700,7 @@ void CCONV cmSourceFileSetName(void* arg, const char* name, const char* dir,
 
   // Finally, try the various header extensions
   for (std::string const& ext : headerExts) {
-    hname = pathname;
-    hname += ".";
-    hname += ext;
+    hname = cmStrCat(pathname, '.', ext);
     if (cmSystemTools::FileExists(hname)) {
       sf->SourceExtension = ext;
       sf->FullPath = hname;
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index e7a16b5..866d262 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -641,12 +641,10 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command)
   cmMakefile* mf = command->GetMakefile();
   std::string fname;
 
-  std::string src_dir_fname = src_dir;
-  src_dir_fname += "/CTestConfig.cmake";
+  std::string src_dir_fname = cmStrCat(src_dir, "/CTestConfig.cmake");
   cmSystemTools::ConvertToUnixSlashes(src_dir_fname);
 
-  std::string bld_dir_fname = bld_dir;
-  bld_dir_fname += "/CTestConfig.cmake";
+  std::string bld_dir_fname = cmStrCat(bld_dir, "/CTestConfig.cmake");
   cmSystemTools::ConvertToUnixSlashes(bld_dir_fname);
 
   if (cmSystemTools::FileExists(bld_dir_fname)) {
@@ -662,8 +660,7 @@ bool cmCTest::InitializeFromCommand(cmCTestStartCommand* command)
                        command->ShouldBeQuiet());
     bool readit = mf->ReadDependentFile(fname);
     if (!readit) {
-      std::string m = "Could not find include file: ";
-      m += fname;
+      std::string m = cmStrCat("Could not find include file: ", fname);
       command->SetError(m);
       return false;
     }
@@ -856,8 +853,7 @@ bool cmCTest::AddIfExists(Part part, const char* file)
   if (this->CTestFileExists(file)) {
     this->AddSubmitFile(part, file);
   } else {
-    std::string name = file;
-    name += ".gz";
+    std::string name = cmStrCat(file, ".gz");
     if (this->CTestFileExists(name)) {
       this->AddSubmitFile(part, file);
     } else {
@@ -1320,15 +1316,15 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output,
       OutputTestErrors(tempOutput);
     }
     *retVal = cmsysProcess_GetExitException(cp);
-    std::string outerr = "\n*** Exception executing: ";
-    outerr += cmsysProcess_GetExceptionString(cp);
+    std::string outerr = cmStrCat("\n*** Exception executing: ",
+                                  cmsysProcess_GetExceptionString(cp));
     if (output) {
       *output += outerr;
     }
     cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, outerr << std::endl);
   } else if (result == cmsysProcess_State_Error) {
-    std::string outerr = "\n*** ERROR executing: ";
-    outerr += cmsysProcess_GetErrorString(cp);
+    std::string outerr =
+      cmStrCat("\n*** ERROR executing: ", cmsysProcess_GetErrorString(cp));
     if (output) {
       *output += outerr;
     }
@@ -2499,8 +2495,7 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf)
              "* Read custom CTest configuration directory: " << dir
                                                              << std::endl);
 
-  std::string fname = dir;
-  fname += "/CTestCustom.cmake";
+  std::string fname = cmStrCat(dir, "/CTestCustom.cmake");
   cmCTestLog(this, DEBUG, "* Check for file: " << fname << std::endl);
   if (cmSystemTools::FileExists(fname)) {
     cmCTestLog(this, DEBUG,
@@ -2520,8 +2515,7 @@ int cmCTest::ReadCustomConfigurationFileTree(const char* dir, cmMakefile* mf)
     }
   }
 
-  std::string rexpr = dir;
-  rexpr += "/CTestCustom.ctest";
+  std::string rexpr = cmStrCat(dir, "/CTestCustom.ctest");
   cmCTestLog(this, DEBUG, "* Check for file: " << rexpr << std::endl);
   if (!found && cmSystemTools::FileExists(rexpr)) {
     cmsys::Glob gl;
@@ -2673,8 +2667,7 @@ std::string cmCTest::GetSubmitURL()
     std::string site = this->GetCTestConfiguration("DropSite");
     std::string location = this->GetCTestConfiguration("DropLocation");
 
-    url = method.empty() ? "http" : method;
-    url += "://";
+    url = cmStrCat(method.empty() ? "http" : method, "://");
     if (!user.empty()) {
       url += user;
       if (!password.empty()) {
diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx
index 6b61f1b..67ff94b 100644
--- a/Source/cmCacheManager.cxx
+++ b/Source/cmCacheManager.cxx
@@ -26,8 +26,7 @@ cmCacheManager::cmCacheManager()
 
 void cmCacheManager::CleanCMakeFiles(const std::string& path)
 {
-  std::string glob = path;
-  glob += "/CMakeFiles/*.cmake";
+  std::string glob = cmStrCat(path, "/CMakeFiles/*.cmake");
   cmsys::Glob globIt;
   globIt.FindFiles(glob);
   std::vector<std::string> files = globIt.GetFiles();
@@ -38,8 +37,7 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
                                std::set<std::string>& excludes,
                                std::set<std::string>& includes)
 {
-  std::string cacheFile = path;
-  cacheFile += "/CMakeCache.txt";
+  std::string cacheFile = cmStrCat(path, "/CMakeCache.txt");
   // clear the old cache, if we are reading in internal values
   if (internal) {
     this->Cache.clear();
@@ -104,12 +102,10 @@ bool cmCacheManager::LoadCache(const std::string& path, bool internal,
           // not visible in the gui
           if (!internal) {
             e.Type = cmStateEnums::INTERNAL;
-            helpString = "DO NOT EDIT, ";
-            helpString += entryKey;
-            helpString += " loaded from external file.  "
-                          "To change this value edit this file: ";
-            helpString += path;
-            helpString += "/CMakeCache.txt";
+            helpString = cmStrCat("DO NOT EDIT, ", entryKey,
+                                  " loaded from external file.  "
+                                  "To change this value edit this file: ",
+                                  path, "/CMakeCache.txt");
             e.SetProperty("HELPSTRING", helpString.c_str());
           }
           if (!this->ReadPropertyEntry(entryKey, e)) {
@@ -214,14 +210,11 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i,
 {
   for (const char** p = cmCacheManager::PersistentProperties; *p; ++p) {
     if (const char* value = i.GetProperty(*p)) {
-      std::string helpstring = *p;
-      helpstring += " property for variable: ";
-      helpstring += i.GetName();
+      std::string helpstring =
+        cmStrCat(*p, " property for variable: ", i.GetName());
       cmCacheManager::OutputHelpString(os, helpstring);
 
-      std::string key = i.GetName();
-      key += "-";
-      key += *p;
+      std::string key = cmStrCat(i.GetName(), '-', *p);
       cmCacheManager::OutputKey(os, key);
       os << ":INTERNAL=";
       cmCacheManager::OutputValue(os, value);
@@ -234,8 +227,7 @@ void cmCacheManager::WritePropertyEntries(std::ostream& os, CacheIterator i,
 
 bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger)
 {
-  std::string cacheFile = path;
-  cacheFile += "/CMakeCache.txt";
+  std::string cacheFile = cmStrCat(path, "/CMakeCache.txt");
   cmGeneratedFileStream fout(cacheFile);
   fout.SetCopyIfDifferent(true);
   if (!fout) {
@@ -356,8 +348,7 @@ bool cmCacheManager::SaveCache(const std::string& path, cmMessenger* messenger)
   }
   fout << "\n";
   fout.Close();
-  std::string checkCacheFile = path;
-  checkCacheFile += "/CMakeFiles";
+  std::string checkCacheFile = cmStrCat(path, "/CMakeFiles");
   cmSystemTools::MakeDirectory(checkCacheFile);
   checkCacheFile += "/cmake.check_cache";
   cmsys::ofstream checkCache(checkCacheFile.c_str());
@@ -473,15 +464,14 @@ void cmCacheManager::OutputNewlineTruncationWarning(std::ostream& fout,
 {
   if (value.find('\n') != std::string::npos) {
     if (messenger) {
-      std::string message = "Value of ";
-      message += key;
-      message += " contained a newline; truncating";
+      std::string message =
+        cmStrCat("Value of ", key, " contained a newline; truncating");
       messenger->IssueMessage(MessageType::WARNING, message);
     }
 
-    std::string comment = "WARNING: Value of ";
-    comment += key;
-    comment += " contained a newline and was truncated. Original value:";
+    std::string comment =
+      cmStrCat("WARNING: Value of ", key,
+               " contained a newline and was truncated. Original value:");
 
     OutputWarningComment(fout, comment, true);
     OutputWarningComment(fout, value, false);
diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx
index 5583520..073a0cd 100644
--- a/Source/cmCommandArgumentParserHelper.cxx
+++ b/Source/cmCommandArgumentParserHelper.cxx
@@ -124,9 +124,7 @@ const char* cmCommandArgumentParserHelper::ExpandVariableForAt(const char* var)
   // - this->ReplaceAtSyntax is false
   // - this->ReplaceAtSyntax is true, but this->RemoveEmpty is false,
   //   and the variable was not defined
-  std::string ref = "@";
-  ref += var;
-  ref += "@";
+  std::string ref = cmStrCat('@', var, '@');
   return this->AddString(ref);
 }
 
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx
index 61880c2..49db505 100644
--- a/Source/cmCommonTargetGenerator.cxx
+++ b/Source/cmCommonTargetGenerator.cxx
@@ -59,10 +59,11 @@ void cmCommonTargetGenerator::AddModuleDefinitionFlag(
 
   // Append the flag and value.  Use ConvertToLinkReference to help
   // vs6's "cl -link" pass it to the linker.
-  std::string flag = defFileFlag;
-  flag += this->LocalCommonGenerator->ConvertToOutputFormat(
-    linkLineComputer->ConvertToLinkReference(mdi->DefFile),
-    cmOutputConverter::SHELL);
+  std::string flag =
+    cmStrCat(defFileFlag,
+             this->LocalCommonGenerator->ConvertToOutputFormat(
+               linkLineComputer->ConvertToLinkReference(mdi->DefFile),
+               cmOutputConverter::SHELL));
   this->LocalCommonGenerator->AppendFlags(flags, flag);
 }
 
@@ -155,9 +156,8 @@ std::vector<std::string> cmCommonTargetGenerator::GetLinkedTargetDirectories()
           && linkee->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
           emitted.insert(linkee).second) {
         cmLocalGenerator* lg = linkee->GetLocalGenerator();
-        std::string di = lg->GetCurrentBinaryDirectory();
-        di += "/";
-        di += lg->GetTargetDirectory(linkee);
+        std::string di = cmStrCat(lg->GetCurrentBinaryDirectory(), '/',
+                                  lg->GetTargetDirectory(linkee));
         dirs.push_back(std::move(di));
       }
     }
@@ -210,11 +210,7 @@ void cmCommonTargetGenerator::AppendOSXVerFlag(std::string& flags,
                                                const char* name, bool so)
 {
   // Lookup the flag to specify the version.
-  std::string fvar = "CMAKE_";
-  fvar += lang;
-  fvar += "_OSX_";
-  fvar += name;
-  fvar += "_VERSION_FLAG";
+  std::string fvar = cmStrCat("CMAKE_", lang, "_OSX_", name, "_VERSION_FLAG");
   const char* flag = this->Makefile->GetDefinition(fvar);
 
   // Skip if no such flag.
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index a187f99..c4b0c05 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -319,8 +319,7 @@ int cmComputeLinkDepends::AddLinkEntry(cmLinkItem const& item)
     this->BFSQueue.push(qe);
   } else {
     // Look for an old-style <item>_LIB_DEPENDS variable.
-    std::string var = entry.Item;
-    var += "_LIB_DEPENDS";
+    std::string var = cmStrCat(entry.Item, "_LIB_DEPENDS");
     if (const char* val = this->Makefile->GetDefinition(var)) {
       // The item dependencies are known.  Follow them.
       BFSEntry qe = { index, val };
@@ -461,8 +460,7 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index,
       // the export_library_dependencies command from CMake 2.4 and
       // lower.
       if (!haveLLT) {
-        std::string var = d;
-        var += "_LINK_TYPE";
+        std::string var = cmStrCat(d, "_LINK_TYPE");
         if (const char* val = this->Makefile->GetDefinition(var)) {
           if (strcmp(val, "debug") == 0) {
             llt = DEBUG_LibraryType;
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index c87fc80..0ff0c3a 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -279,9 +279,8 @@ cmComputeLinkInformation::cmComputeLinkInformation(
   this->LoaderFlag = nullptr;
   if (!this->Target->IsDLLPlatform() &&
       this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) {
-    std::string loader_flag_var = "CMAKE_SHARED_MODULE_LOADER_";
-    loader_flag_var += this->LinkLanguage;
-    loader_flag_var += "_FLAG";
+    std::string loader_flag_var =
+      cmStrCat("CMAKE_SHARED_MODULE_LOADER_", this->LinkLanguage, "_FLAG");
     this->LoaderFlag = this->Makefile->GetDefinition(loader_flag_var);
   }
 
@@ -304,11 +303,8 @@ cmComputeLinkInformation::cmComputeLinkInformation(
     const char* tType = ((this->Target->GetType() == cmStateEnums::EXECUTABLE)
                            ? "EXECUTABLE"
                            : "SHARED_LIBRARY");
-    std::string rtVar = "CMAKE_";
-    rtVar += tType;
-    rtVar += "_RUNTIME_";
-    rtVar += this->LinkLanguage;
-    rtVar += "_FLAG";
+    std::string rtVar =
+      cmStrCat("CMAKE_", tType, "_RUNTIME_", this->LinkLanguage, "_FLAG");
     std::string rtSepVar = rtVar + "_SEP";
     this->RuntimeFlag = this->Makefile->GetSafeDefinition(rtVar);
     this->RuntimeSep = this->Makefile->GetSafeDefinition(rtSepVar);
@@ -318,19 +314,15 @@ cmComputeLinkInformation::cmComputeLinkInformation(
     this->RuntimeUseChrpath = this->Target->IsChrpathUsed(config);
 
     // Get options needed to help find dependent libraries.
-    std::string rlVar = "CMAKE_";
-    rlVar += tType;
-    rlVar += "_RPATH_LINK_";
-    rlVar += this->LinkLanguage;
-    rlVar += "_FLAG";
+    std::string rlVar =
+      cmStrCat("CMAKE_", tType, "_RPATH_LINK_", this->LinkLanguage, "_FLAG");
     this->RPathLinkFlag = this->Makefile->GetSafeDefinition(rlVar);
   }
 
   // Check if we need to include the runtime search path at link time.
   {
-    std::string var = "CMAKE_SHARED_LIBRARY_LINK_";
-    var += this->LinkLanguage;
-    var += "_WITH_RUNTIME_PATH";
+    std::string var = cmStrCat("CMAKE_SHARED_LIBRARY_LINK_",
+                               this->LinkLanguage, "_WITH_RUNTIME_PATH");
     this->LinkWithRuntimePath = this->Makefile->IsOn(var);
   }
 
@@ -547,9 +539,7 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang)
 {
   // Add libraries for this language that are not implied by the
   // linker language.
-  std::string libVar = "CMAKE_";
-  libVar += lang;
-  libVar += "_IMPLICIT_LINK_LIBRARIES";
+  std::string libVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_LIBRARIES");
   if (const char* libs = this->Makefile->GetDefinition(libVar)) {
     std::vector<std::string> libsVec;
     cmExpandList(libs, libsVec);
@@ -562,9 +552,7 @@ void cmComputeLinkInformation::AddImplicitLinkInfo(std::string const& lang)
 
   // Add linker search paths for this language that are not
   // implied by the linker language.
-  std::string dirVar = "CMAKE_";
-  dirVar += lang;
-  dirVar += "_IMPLICIT_LINK_DIRECTORIES";
+  std::string dirVar = cmStrCat("CMAKE_", lang, "_IMPLICIT_LINK_DIRECTORIES");
   if (const char* dirs = this->Makefile->GetDefinition(dirVar)) {
     std::vector<std::string> dirsVec;
     cmExpandList(dirs, dirsVec);
@@ -760,19 +748,15 @@ void cmComputeLinkInformation::ComputeLinkTypeInfo()
       break;
   }
   if (target_type_str) {
-    std::string static_link_type_flag_var = "CMAKE_";
-    static_link_type_flag_var += target_type_str;
-    static_link_type_flag_var += "_LINK_STATIC_";
-    static_link_type_flag_var += this->LinkLanguage;
-    static_link_type_flag_var += "_FLAGS";
+    std::string static_link_type_flag_var =
+      cmStrCat("CMAKE_", target_type_str, "_LINK_STATIC_", this->LinkLanguage,
+               "_FLAGS");
     static_link_type_flag =
       this->Makefile->GetDefinition(static_link_type_flag_var);
 
-    std::string shared_link_type_flag_var = "CMAKE_";
-    shared_link_type_flag_var += target_type_str;
-    shared_link_type_flag_var += "_LINK_DYNAMIC_";
-    shared_link_type_flag_var += this->LinkLanguage;
-    shared_link_type_flag_var += "_FLAGS";
+    std::string shared_link_type_flag_var =
+      cmStrCat("CMAKE_", target_type_str, "_LINK_DYNAMIC_", this->LinkLanguage,
+               "_FLAGS");
     shared_link_type_flag =
       this->Makefile->GetDefinition(shared_link_type_flag_var);
   }
@@ -848,8 +832,7 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
   reg += "([^/:]*)";
 
   // Create a regex to match any library name.
-  std::string reg_any = reg;
-  reg_any += libext;
+  std::string reg_any = cmStrCat(reg, libext);
 #ifdef CM_COMPUTE_LINK_INFO_DEBUG
   fprintf(stderr, "any regex [%s]\n", reg_any.c_str());
 #endif
@@ -857,9 +840,8 @@ void cmComputeLinkInformation::ComputeItemParserInfo()
 
   // Create a regex to match static library names.
   if (!this->StaticLinkExtensions.empty()) {
-    std::string reg_static = reg;
-    reg_static +=
-      this->CreateExtensionRegex(this->StaticLinkExtensions, LinkStatic);
+    std::string reg_static = cmStrCat(
+      reg, this->CreateExtensionRegex(this->StaticLinkExtensions, LinkStatic));
 #ifdef CM_COMPUTE_LINK_INFO_DEBUG
     fprintf(stderr, "static regex [%s]\n", reg_static.c_str());
 #endif
@@ -1215,9 +1197,7 @@ void cmComputeLinkInformation::AddUserItem(std::string const& item,
   }
 
   // Create an option to ask the linker to search for the library.
-  std::string out = this->LibLinkFlag;
-  out += lib;
-  out += this->LibLinkSuffix;
+  std::string out = cmStrCat(this->LibLinkFlag, lib, this->LibLinkSuffix);
   this->Items.emplace_back(out, false);
 
   // Here we could try to find the library the linker will find and
@@ -1239,12 +1219,7 @@ void cmComputeLinkInformation::AddFrameworkItem(std::string const& item)
 
   std::string fw_path = this->SplitFramework.match(1);
   std::string fw = this->SplitFramework.match(2);
-  std::string full_fw = fw_path;
-  full_fw += "/";
-  full_fw += fw;
-  full_fw += ".framework";
-  full_fw += "/";
-  full_fw += fw;
+  std::string full_fw = cmStrCat(fw_path, '/', fw, ".framework/", fw);
 
   // Add the directory portion to the framework search path.
   this->AddFrameworkPath(fw_path);
@@ -1293,9 +1268,8 @@ void cmComputeLinkInformation::ComputeFrameworkInfo()
   }
 
   // Get language-specific implicit directories.
-  std::string implicitDirVar = "CMAKE_";
-  implicitDirVar += this->LinkLanguage;
-  implicitDirVar += "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES";
+  std::string implicitDirVar = cmStrCat(
+    "CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES");
   if (const char* implicitDirs =
         this->Makefile->GetDefinition(implicitDirVar)) {
     cmExpandList(implicitDirs, implicitDirVec);
@@ -1368,8 +1342,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item,
   switch (this->Target->GetPolicyStatusCMP0008()) {
     case cmPolicies::WARN: {
       // Print the warning at most once for this item.
-      std::string wid = "CMP0008-WARNING-GIVEN-";
-      wid += item;
+      std::string wid = cmStrCat("CMP0008-WARNING-GIVEN-", item);
       if (!this->CMakeInstance->GetState()->GetGlobalPropertyAsBool(wid)) {
         this->CMakeInstance->GetState()->SetGlobalProperty(wid, "1");
         std::ostringstream w;
@@ -1530,9 +1503,8 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo()
   }
 
   // Get language-specific implicit directories.
-  std::string implicitDirVar = "CMAKE_";
-  implicitDirVar += this->LinkLanguage;
-  implicitDirVar += "_IMPLICIT_LINK_DIRECTORIES";
+  std::string implicitDirVar =
+    cmStrCat("CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_DIRECTORIES");
   if (const char* implicitDirs =
         this->Makefile->GetDefinition(implicitDirVar)) {
     cmExpandList(implicitDirs, implicitDirVec);
@@ -1543,9 +1515,8 @@ void cmComputeLinkInformation::LoadImplicitLinkInfo()
 
   // Get language-specific implicit libraries.
   std::vector<std::string> implicitLibVec;
-  std::string implicitLibVar = "CMAKE_";
-  implicitLibVar += this->LinkLanguage;
-  implicitLibVar += "_IMPLICIT_LINK_LIBRARIES";
+  std::string implicitLibVar =
+    cmStrCat("CMAKE_", this->LinkLanguage, "_IMPLICIT_LINK_LIBRARIES");
   if (const char* implicitLibs =
         this->Makefile->GetDefinition(implicitLibVar)) {
     cmExpandList(implicitLibs, implicitLibVec);
@@ -1749,9 +1720,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
           d = d.substr(rootPath.size());
         } else if (stagePath && *stagePath && d.find(stagePath) == 0) {
           std::string suffix = d.substr(strlen(stagePath));
-          d = installPrefix;
-          d += "/";
-          d += suffix;
+          d = cmStrCat(installPrefix, '/', suffix);
           cmSystemTools::ConvertToUnixSlashes(d);
         } else if (use_relative_build_rpath) {
           // If expansion of the $ORIGIN token is supported and permitted per
@@ -1782,9 +1751,7 @@ void cmComputeLinkInformation::GetRPath(std::vector<std::string>& runtimeDirs,
             d = d.substr(rootPath.size());
           } else if (stagePath && *stagePath && d.find(stagePath) == 0) {
             std::string suffix = d.substr(strlen(stagePath));
-            d = installPrefix;
-            d += "/";
-            d += suffix;
+            d = cmStrCat(installPrefix, '/', suffix);
             cmSystemTools::ConvertToUnixSlashes(d);
           }
           if (emitted.insert(d).second) {
diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx
index 701214e..7e37f32 100644
--- a/Source/cmConfigureFileCommand.cxx
+++ b/Source/cmConfigureFileCommand.cxx
@@ -8,6 +8,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmNewLineStyle.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 // cmConfigureFileCommand
@@ -88,8 +89,8 @@ bool cmConfigureFileCommand(std::vector<std::string> const& args,
     }
   }
   if (!unknown_args.empty()) {
-    std::string msg = "configure_file called with unknown argument(s):\n";
-    msg += unknown_args;
+    std::string msg = cmStrCat(
+      "configure_file called with unknown argument(s):\n", unknown_args);
     status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, msg);
   }
 
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index e5e1ecf..f696b95 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -1045,16 +1045,14 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
     this->Makefile->GetDefinition("CMAKE_TRY_COMPILE_CONFIGURATION");
   // if a config was specified try that first
   if (config && config[0]) {
-    std::string tmp = "/";
-    tmp += config;
+    std::string tmp = cmStrCat('/', config);
     searchDirs.push_back(std::move(tmp));
   }
   searchDirs.emplace_back("/Debug");
 #if defined(__APPLE__)
   std::string app = "/" + targetName + ".app";
   if (config && config[0]) {
-    std::string tmp = "/";
-    tmp += config + app;
+    std::string tmp = cmStrCat('/', config, app);
     searchDirs.push_back(std::move(tmp));
   }
   std::string tmp = "/Debug" + app;
@@ -1064,9 +1062,7 @@ void cmCoreTryCompile::FindOutputFile(const std::string& targetName,
   searchDirs.emplace_back("/Development");
 
   for (std::string const& sdir : searchDirs) {
-    std::string command = this->BinaryDirectory;
-    command += sdir;
-    command += tmpOutputFile;
+    std::string command = cmStrCat(this->BinaryDirectory, sdir, tmpOutputFile);
     if (cmSystemTools::FileExists(command)) {
       this->OutputFile = cmSystemTools::CollapseFullPath(command);
       return;
diff --git a/Source/cmCreateTestSourceList.cxx b/Source/cmCreateTestSourceList.cxx
index 427db72..4a1825f 100644
--- a/Source/cmCreateTestSourceList.cxx
+++ b/Source/cmCreateTestSourceList.cxx
@@ -6,6 +6,7 @@
 
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -31,17 +32,14 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args,
         this->SetError("incorrect arguments to EXTRA_INCLUDE");
         return false;
       }
-      extraInclude = "#include \"";
-      extraInclude += *i;
-      extraInclude += "\"\n";
+      extraInclude = cmStrCat("#include \"", *i, "\"\n");
     } else if (*i == "FUNCTION") {
       ++i;
       if (i == args.end()) {
         this->SetError("incorrect arguments to FUNCTION");
         return false;
       }
-      function = *i;
-      function += "(&ac, &av);\n";
+      function = cmStrCat(*i, "(&ac, &av);\n");
     } else {
       tests.push_back(*i);
     }
@@ -60,9 +58,8 @@ bool cmCreateTestSourceList::InitialPass(std::vector<std::string> const& args,
       "You must specify a file extension for the test driver file.");
     return false;
   }
-  std::string driver = this->Makefile->GetCurrentBinaryDirectory();
-  driver += "/";
-  driver += *i;
+  std::string driver =
+    cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', *i);
   ++i;
 
   std::string configFile = cmSystemTools::GetCMakeRoot();
diff --git a/Source/cmCurl.cxx b/Source/cmCurl.cxx
index 0004f66..233790e 100644
--- a/Source/cmCurl.cxx
+++ b/Source/cmCurl.cxx
@@ -7,6 +7,7 @@
 #  define CMAKE_FIND_CAFILE
 #  include "cmSystemTools.h"
 #endif
+#include "cmStringAlgorithms.h"
 
 // curl versions before 7.21.5 did not provide this error code
 #if defined(LIBCURL_VERSION_NUM) && LIBCURL_VERSION_NUM < 0x071505
@@ -72,8 +73,8 @@ std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level,
     } else if (netrc_level == "IGNORED") {
       curl_netrc_level = CURL_NETRC_IGNORED;
     } else {
-      e = "NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: ";
-      e += netrc_level;
+      e = cmStrCat("NETRC accepts OPTIONAL, IGNORED or REQUIRED but got: ",
+                   netrc_level);
       return e;
     }
   }
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 20f0ef2..82cc037 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -169,9 +169,7 @@ std::string escapeForShellOldStyle(const std::string& str)
   std::string temp = str;
   if (temp.find(" ") != std::string::npos &&
       temp.find("\"") == std::string::npos) {
-    result = "\"";
-    result += str;
-    result += "\"";
+    result = cmStrCat('"', str, '"');
     return result;
   }
   return str;
diff --git a/Source/cmDepends.cxx b/Source/cmDepends.cxx
index 6623d94..06a442b 100644
--- a/Source/cmDepends.cxx
+++ b/Source/cmDepends.cxx
@@ -236,18 +236,15 @@ void cmDepends::SetIncludePathFromLanguage(const std::string& lang)
 {
   // Look for the new per "TARGET_" variant first:
   const char* includePath = nullptr;
-  std::string includePathVar = "CMAKE_";
-  includePathVar += lang;
-  includePathVar += "_TARGET_INCLUDE_PATH";
+  std::string includePathVar =
+    cmStrCat("CMAKE_", lang, "_TARGET_INCLUDE_PATH");
   cmMakefile* mf = this->LocalGenerator->GetMakefile();
   includePath = mf->GetDefinition(includePathVar);
   if (includePath) {
     cmExpandList(includePath, this->IncludePath);
   } else {
     // Fallback to the old directory level variable if no per-target var:
-    includePathVar = "CMAKE_";
-    includePathVar += lang;
-    includePathVar += "_INCLUDE_PATH";
+    includePathVar = cmStrCat("CMAKE_", lang, "_INCLUDE_PATH");
     includePath = mf->GetDefinition(includePathVar);
     if (includePath) {
       cmExpandList(includePath, this->IncludePath);
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index 6eefe82..0f9f166 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -36,15 +36,12 @@ cmDependsC::cmDependsC(cmLocalGenerator* lg, const std::string& targetDir,
   std::string scanRegex = "^.*$";
   std::string complainRegex = "^$";
   {
-    std::string scanRegexVar = "CMAKE_";
-    scanRegexVar += lang;
-    scanRegexVar += "_INCLUDE_REGEX_SCAN";
+    std::string scanRegexVar = cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_SCAN");
     if (const char* sr = mf->GetDefinition(scanRegexVar)) {
       scanRegex = sr;
     }
-    std::string complainRegexVar = "CMAKE_";
-    complainRegexVar += lang;
-    complainRegexVar += "_INCLUDE_REGEX_COMPLAIN";
+    std::string complainRegexVar =
+      cmStrCat("CMAKE_", lang, "_INCLUDE_REGEX_COMPLAIN");
     if (const char* cr = mf->GetDefinition(complainRegexVar)) {
       complainRegex = cr;
     }
@@ -54,17 +51,15 @@ cmDependsC::cmDependsC(cmLocalGenerator* lg, const std::string& targetDir,
   this->IncludeRegexScan.compile(scanRegex);
   this->IncludeRegexComplain.compile(complainRegex);
   this->IncludeRegexLineString = INCLUDE_REGEX_LINE_MARKER INCLUDE_REGEX_LINE;
-  this->IncludeRegexScanString = INCLUDE_REGEX_SCAN_MARKER;
-  this->IncludeRegexScanString += scanRegex;
-  this->IncludeRegexComplainString = INCLUDE_REGEX_COMPLAIN_MARKER;
-  this->IncludeRegexComplainString += complainRegex;
+  this->IncludeRegexScanString =
+    cmStrCat(INCLUDE_REGEX_SCAN_MARKER, scanRegex);
+  this->IncludeRegexComplainString =
+    cmStrCat(INCLUDE_REGEX_COMPLAIN_MARKER, complainRegex);
 
   this->SetupTransforms();
 
-  this->CacheFileName = this->TargetDirectory;
-  this->CacheFileName += "/";
-  this->CacheFileName += lang;
-  this->CacheFileName += ".includecache";
+  this->CacheFileName =
+    cmStrCat(this->TargetDirectory, '/', lang, ".includecache");
 
   this->ReadCacheFile();
 }
diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx
index 63d1c4d..6c77db9 100644
--- a/Source/cmDependsFortran.cxx
+++ b/Source/cmDependsFortran.cxx
@@ -180,8 +180,7 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
   }
 
   // Store the list of modules provided by this target.
-  std::string fiName = this->TargetDirectory;
-  fiName += "/fortran.internal";
+  std::string fiName = cmStrCat(this->TargetDirectory, "/fortran.internal");
   cmGeneratedFileStream fiStream(fiName);
   fiStream << "# The fortran modules provided by this target.\n";
   fiStream << "provides\n";
@@ -192,23 +191,18 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends,
 
   // Create a script to clean the modules.
   if (!provides.empty()) {
-    std::string fcName = this->TargetDirectory;
-    fcName += "/cmake_clean_Fortran.cmake";
+    std::string fcName =
+      cmStrCat(this->TargetDirectory, "/cmake_clean_Fortran.cmake");
     cmGeneratedFileStream fcStream(fcName);
     fcStream << "# Remove fortran modules provided by this target.\n";
     fcStream << "FILE(REMOVE";
     std::string currentBinDir =
       this->LocalGenerator->GetCurrentBinaryDirectory();
     for (std::string const& i : provides) {
-      std::string mod_upper = mod_dir;
-      mod_upper += "/";
-      std::string mod_lower = mod_dir;
-      mod_lower += "/";
+      std::string mod_upper = cmStrCat(mod_dir, '/');
+      std::string mod_lower = cmStrCat(mod_dir, '/');
       cmFortranModuleAppendUpperLower(i, mod_upper, mod_lower);
-      std::string stamp = stamp_dir;
-      stamp += "/";
-      stamp += i;
-      stamp += ".stamp";
+      std::string stamp = cmStrCat(stamp_dir, '/', i, ".stamp");
       fcStream << "\n";
       fcStream << "  \""
                << this->MaybeConvertToRelativePath(currentBinDir, mod_lower)
@@ -315,10 +309,7 @@ void cmDependsFortran::ConsiderModule(const std::string& name,
   if (required != this->Internal->TargetRequires.end() &&
       required->second.empty()) {
     // The module is provided by a CMake target.  It will have a stamp file.
-    std::string stampFile = stampDir;
-    stampFile += "/";
-    stampFile += name;
-    stampFile += ".stamp";
+    std::string stampFile = cmStrCat(stampDir, '/', name, ".stamp");
     required->second = stampFile;
   }
 }
@@ -392,16 +383,11 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
       // Always use lower case for the mod stamp file name.  The
       // cmake_copy_f90_mod will call back to this class, which will
       // try various cases for the real mod file name.
-      std::string modFile = mod_dir;
-      modFile += "/";
-      modFile += i;
+      std::string modFile = cmStrCat(mod_dir, '/', i);
       modFile = this->LocalGenerator->ConvertToOutputFormat(
         this->MaybeConvertToRelativePath(binDir, modFile),
         cmOutputConverter::SHELL);
-      std::string stampFile = stamp_dir;
-      stampFile += "/";
-      stampFile += i;
-      stampFile += ".stamp";
+      std::string stampFile = cmStrCat(stamp_dir, '/', i, ".stamp");
       stampFile = this->MaybeConvertToRelativePath(binDir, stampFile);
       std::string const stampFileForShell =
         this->LocalGenerator->ConvertToOutputFormat(stampFile,
@@ -435,8 +421,7 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj,
 
     // Make sure the module timestamp rule is evaluated by the time
     // the target finishes building.
-    std::string driver = this->TargetDirectory;
-    driver += "/build";
+    std::string driver = cmStrCat(this->TargetDirectory, "/build");
     driver = cmSystemTools::ConvertToOutputPath(
       this->MaybeConvertToRelativePath(binDir, driver));
     makeDepends << driver << ": " << obj_m << ".provides.build\n";
@@ -456,18 +441,14 @@ bool cmDependsFortran::FindModule(std::string const& name, std::string& module)
   std::string fullName;
   for (std::string const& ip : this->IncludePath) {
     // Try the lower-case name.
-    fullName = ip;
-    fullName += "/";
-    fullName += mod_lower;
+    fullName = cmStrCat(ip, '/', mod_lower);
     if (cmSystemTools::FileExists(fullName, true)) {
       module = fullName;
       return true;
     }
 
     // Try the upper-case name.
-    fullName = ip;
-    fullName += "/";
-    fullName += mod_upper;
+    fullName = cmStrCat(ip, '/', mod_upper);
     if (cmSystemTools::FileExists(fullName, true)) {
       module = fullName;
       return true;
diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx
index 75716c0..7f41640 100644
--- a/Source/cmExecProgramCommand.cxx
+++ b/Source/cmExecProgramCommand.cxx
@@ -8,6 +8,7 @@
 #include "cmExecutionStatus.h"
 #include "cmMakefile.h"
 #include "cmProcessOutput.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 typedef cmProcessOutput::Encoding Encoding;
@@ -74,9 +75,8 @@ bool cmExecProgramCommand(std::vector<std::string> const& args,
 
   std::string command;
   if (!arguments.empty()) {
-    command = cmSystemTools::ConvertToRunCommandPath(args[0]);
-    command += " ";
-    command += arguments;
+    command = cmStrCat(cmSystemTools::ConvertToRunCommandPath(args[0]), ' ',
+                       arguments);
   } else {
     command = args[0];
   }
@@ -192,10 +192,7 @@ bool RunCommand(std::string command, std::string& output, int& retVal,
 #else
   std::string commandInDir;
   if (dir) {
-    commandInDir = "cd \"";
-    commandInDir += dir;
-    commandInDir += "\" && ";
-    commandInDir += command;
+    commandInDir = cmStrCat("cd \"", dir, "\" && ", command);
   } else {
     commandInDir = command;
   }
diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx
index 9b1e15e..f8ce592 100644
--- a/Source/cmExportBuildAndroidMKGenerator.cxx
+++ b/Source/cmExportBuildAndroidMKGenerator.cxx
@@ -41,8 +41,7 @@ void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode(
   std::ostream& os, cmGeneratorTarget const* target,
   cmStateEnums::TargetType /*targetType*/)
 {
-  std::string targetName = this->Namespace;
-  targetName += target->GetExportName();
+  std::string targetName = cmStrCat(this->Namespace, target->GetExportName());
   os << "include $(CLEAR_VARS)\n";
   os << "LOCAL_MODULE := ";
   os << targetName << "\n";
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index dee50ac..8a1a305 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -202,8 +202,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
   cmMakefile* mf = target->Makefile;
 
   if (target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
-    std::string prop = "IMPORTED_OBJECTS";
-    prop += suffix;
+    std::string prop = cmStrCat("IMPORTED_OBJECTS", suffix);
 
     // Compute all the object files inside this target and setup
     // IMPORTED_OBJECTS as a list of object files
@@ -221,8 +220,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
   } else {
     // Add the main target file.
     {
-      std::string prop = "IMPORTED_LOCATION";
-      prop += suffix;
+      std::string prop = cmStrCat("IMPORTED_LOCATION", suffix);
       std::string value;
       if (target->IsAppBundleOnApple()) {
         value =
@@ -236,8 +234,7 @@ void cmExportBuildFileGenerator::SetImportLocationProperty(
 
     // Add the import library for windows DLLs.
     if (target->HasImportLibrary(config)) {
-      std::string prop = "IMPORTED_IMPLIB";
-      prop += suffix;
+      std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix);
       std::string value =
         target->GetFullPath(config, cmStateEnums::ImportLibraryArtifact);
       if (mf->GetDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX")) {
diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx
index 598eafe..4046f91 100644
--- a/Source/cmExportCommand.cxx
+++ b/Source/cmExportCommand.cxx
@@ -299,8 +299,7 @@ void cmExportCommand::StorePackageRegistryWin(std::string const& package,
                                               const char* content,
                                               const char* hash)
 {
-  std::string key = "Software\\Kitware\\CMake\\Packages\\";
-  key += package;
+  std::string key = cmStrCat("Software\\Kitware\\CMake\\Packages\\", package);
   HKEY hKey;
   LONG err =
     RegCreateKeyExW(HKEY_CURRENT_USER, cmsys::Encoding::ToWide(key).c_str(), 0,
@@ -334,9 +333,7 @@ void cmExportCommand::StorePackageRegistryDir(std::string const& package,
       B_OK) {
     return;
   }
-  std::string fname = dir;
-  fname += "/cmake/packages/";
-  fname += package;
+  std::string fname = cmStrCat(dir, "/cmake/packages/", package);
 #  else
   std::string fname;
   if (!cmSystemTools::GetEnv("HOME", fname)) {
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 35d8668..96733f2 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -584,8 +584,8 @@ void cmExportFileGenerator::GenerateInterfaceProperties(
   const ImportPropertyMap& properties)
 {
   if (!properties.empty()) {
-    std::string targetName = this->Namespace;
-    targetName += target->GetExportName();
+    std::string targetName =
+      cmStrCat(this->Namespace, target->GetExportName());
     os << "set_target_properties(" << targetName << " PROPERTIES\n";
     for (auto const& property : properties) {
       os << "  " << property.first << " "
@@ -841,8 +841,8 @@ void cmExportFileGenerator::SetImportDetailProperties(
                                 "IMPORTED_LINK_DEPENDENT_LIBRARIES",
                                 iface->SharedDeps, properties, dummy);
     if (iface->Multiplicity > 0) {
-      std::string prop = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
-      prop += suffix;
+      std::string prop =
+        cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix);
       std::ostringstream m;
       m << iface->Multiplicity;
       properties[prop] = m.str();
@@ -852,8 +852,7 @@ void cmExportFileGenerator::SetImportDetailProperties(
   // Add information if this target is a managed target
   if (target->GetManagedType(config) !=
       cmGeneratorTarget::ManagedType::Native) {
-    std::string prop = "IMPORTED_COMMON_LANGUAGE_RUNTIME";
-    prop += suffix;
+    std::string prop = cmStrCat("IMPORTED_COMMON_LANGUAGE_RUNTIME", suffix);
     std::string propval;
     if (auto* p = target->GetProperty("COMMON_LANGUAGE_RUNTIME")) {
       propval = p;
@@ -904,8 +903,7 @@ void cmExportFileGenerator::SetImportLinkProperty(
   }
 
   // Store the property.
-  std::string prop = propName;
-  prop += suffix;
+  std::string prop = cmStrCat(propName, suffix);
   properties[prop] = link_entries;
 }
 
@@ -1182,8 +1180,7 @@ void cmExportFileGenerator::GenerateImportedFileChecksCode(
   const std::set<std::string>& importedLocations)
 {
   // Construct the imported target name.
-  std::string targetName = this->Namespace;
-  targetName += target->GetExportName();
+  std::string targetName = cmStrCat(this->Namespace, target->GetExportName());
 
   os << "list(APPEND _IMPORT_CHECK_TARGETS " << targetName
      << " )\n"
diff --git a/Source/cmExportInstallAndroidMKGenerator.cxx b/Source/cmExportInstallAndroidMKGenerator.cxx
index 9bc8089..1b536c9 100644
--- a/Source/cmExportInstallAndroidMKGenerator.cxx
+++ b/Source/cmExportInstallAndroidMKGenerator.cxx
@@ -11,6 +11,7 @@
 #include "cmInstallExportGenerator.h"
 #include "cmInstallTargetGenerator.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTargetExport.h"
@@ -58,8 +59,7 @@ void cmExportInstallAndroidMKGenerator::GenerateImportTargetCode(
   std::ostream& os, cmGeneratorTarget const* target,
   cmStateEnums::TargetType /*targetType*/)
 {
-  std::string targetName = this->Namespace;
-  targetName += target->GetExportName();
+  std::string targetName = cmStrCat(this->Namespace, target->GetExportName());
   os << "include $(CLEAR_VARS)\n";
   os << "LOCAL_MODULE := ";
   os << targetName << "\n";
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index 7056577..e7f301e 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -30,9 +30,7 @@ cmExportInstallFileGenerator::cmExportInstallFileGenerator(
 
 std::string cmExportInstallFileGenerator::GetConfigImportFileGlob()
 {
-  std::string glob = this->FileBase;
-  glob += "-*";
-  glob += this->FileExt;
+  std::string glob = cmStrCat(this->FileBase, "-*", this->FileExt);
   return glob;
 }
 
@@ -277,10 +275,7 @@ bool cmExportInstallFileGenerator::GenerateImportFileConfig(
   }
 
   // Construct the name of the file to generate.
-  std::string fileName = this->FileDir;
-  fileName += "/";
-  fileName += this->FileBase;
-  fileName += "-";
+  std::string fileName = cmStrCat(this->FileDir, '/', this->FileBase, '-');
   if (!config.empty()) {
     fileName += cmSystemTools::LowerCase(config);
   } else {
@@ -392,8 +387,7 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
 
   if (itgen->IsImportLibrary()) {
     // Construct the property name.
-    std::string prop = "IMPORTED_IMPLIB";
-    prop += suffix;
+    std::string prop = cmStrCat("IMPORTED_IMPLIB", suffix);
 
     // Append the installed file name.
     value += cmInstallTargetGenerator::GetInstallFilename(
@@ -404,8 +398,7 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
     importedLocations.insert(prop);
   } else if (itgen->GetTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) {
     // Construct the property name.
-    std::string prop = "IMPORTED_OBJECTS";
-    prop += suffix;
+    std::string prop = cmStrCat("IMPORTED_OBJECTS", suffix);
 
     // Compute all the object files inside this target and setup
     // IMPORTED_OBJECTS as a list of object files
@@ -420,8 +413,7 @@ void cmExportInstallFileGenerator::SetImportLocationProperty(
     importedLocations.insert(prop);
   } else {
     // Construct the property name.
-    std::string prop = "IMPORTED_LOCATION";
-    prop += suffix;
+    std::string prop = cmStrCat("IMPORTED_LOCATION", suffix);
 
     // Append the installed file name.
     if (target->IsAppBundleOnApple()) {
diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx
index 8f2fff5..81237db 100644
--- a/Source/cmExportLibraryDependenciesCommand.cxx
+++ b/Source/cmExportLibraryDependenciesCommand.cxx
@@ -12,6 +12,7 @@
 #include "cmGlobalGenerator.h"
 #include "cmMakefile.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTargetLinkLibraryType.h"
@@ -61,8 +62,7 @@ static void FinalAction(cmMakefile& makefile, std::string const& filename,
       }
 
       // Construct the dependency variable name.
-      std::string targetEntry = target.GetName();
-      targetEntry += "_LIB_DEPENDS";
+      std::string targetEntry = cmStrCat(target.GetName(), "_LIB_DEPENDS");
 
       // Construct the dependency variable value with the direct link
       // dependencies.
@@ -71,8 +71,7 @@ static void FinalAction(cmMakefile& makefile, std::string const& filename,
       cmTarget::LinkLibraryVectorType const& libs =
         target.GetOriginalLinkLibraries();
       for (cmTarget::LibraryID const& li : libs) {
-        std::string ltVar = li.first;
-        ltVar += "_LINK_TYPE";
+        std::string ltVar = cmStrCat(li.first, "_LINK_TYPE");
         std::string ltValue;
         switch (li.second) {
           case GENERAL_LibraryType:
diff --git a/Source/cmExprParserHelper.cxx b/Source/cmExprParserHelper.cxx
index 80c78a3..c01e959 100644
--- a/Source/cmExprParserHelper.cxx
+++ b/Source/cmExprParserHelper.cxx
@@ -3,6 +3,7 @@
 #include "cmExprParserHelper.h"
 
 #include "cmExprLexer.h"
+#include "cmStringAlgorithms.h"
 
 #include <iostream>
 #include <sstream>
@@ -41,16 +42,13 @@ int cmExprParserHelper::ParseString(const char* str, int verb)
   try {
     int res = cmExpr_yyparse(yyscanner);
     if (res != 0) {
-      std::string e = "cannot parse the expression: \"" + InputBuffer + "\": ";
-      e += ErrorString;
-      e += ".";
+      std::string e = cmStrCat("cannot parse the expression: \"", InputBuffer,
+                               "\": ", ErrorString, '.');
       this->SetError(std::move(e));
     }
   } catch (std::runtime_error const& fail) {
-    std::string e =
-      "cannot evaluate the expression: \"" + InputBuffer + "\": ";
-    e += fail.what();
-    e += ".";
+    std::string e = cmStrCat("cannot evaluate the expression: \"", InputBuffer,
+                             "\": ", fail.what(), '.');
     this->SetError(std::move(e));
   } catch (std::out_of_range const&) {
     std::string e = "cannot evaluate the expression: \"" + InputBuffer +
diff --git a/Source/cmExternalMakefileProjectGenerator.cxx b/Source/cmExternalMakefileProjectGenerator.cxx
index ac54811..83a0ba6 100644
--- a/Source/cmExternalMakefileProjectGenerator.cxx
+++ b/Source/cmExternalMakefileProjectGenerator.cxx
@@ -2,6 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmExternalMakefileProjectGenerator.h"
 
+#include "cmStringAlgorithms.h"
+
 #include <utility>
 
 class cmMakefile;
@@ -18,8 +20,7 @@ std::string cmExternalMakefileProjectGenerator::CreateFullGeneratorName(
   std::string fullName;
   if (!globalGenerator.empty()) {
     if (!extraGenerator.empty()) {
-      fullName = extraGenerator;
-      fullName += " - ";
+      fullName = cmStrCat(extraGenerator, " - ");
     }
     fullName += globalGenerator;
   }
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index 79ecf45..d8a1a49 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -74,10 +74,9 @@ void cmExtraCodeBlocksGenerator::CreateProjectFile(
   std::string outputDir = lgs[0]->GetCurrentBinaryDirectory();
   std::string projectName = lgs[0]->GetProjectName();
 
-  std::string filename = outputDir + "/";
-  filename += projectName + ".cbp";
-  std::string sessionFilename = outputDir + "/";
-  sessionFilename += projectName + ".layout";
+  std::string filename = cmStrCat(outputDir, '/', projectName, ".cbp");
+  std::string sessionFilename =
+    cmStrCat(outputDir, '/', projectName, ".layout");
 
   this->CreateNewProjectFile(lgs, filename);
 }
@@ -319,8 +318,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
           cmGeneratorTarget* gt = target;
           this->AppendTarget(xml, targetName, gt, make, lg, compiler,
                              makeArgs);
-          std::string fastTarget = targetName;
-          fastTarget += "/fast";
+          std::string fastTarget = cmStrCat(targetName, "/fast");
           this->AppendTarget(xml, fastTarget, gt, make, lg, compiler,
                              makeArgs);
         } break;
@@ -413,15 +411,13 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile(
   // A very similar version of that code exists also in the CodeLite
   // project generator.
   for (std::string const& fileName : cFiles) {
-    std::string headerBasename = cmSystemTools::GetFilenamePath(fileName);
-    headerBasename += "/";
-    headerBasename += cmSystemTools::GetFilenameWithoutExtension(fileName);
+    std::string headerBasename =
+      cmStrCat(cmSystemTools::GetFilenamePath(fileName), '/',
+               cmSystemTools::GetFilenameWithoutExtension(fileName));
 
     // check if there's a matching header around
     for (std::string const& ext : headerExts) {
-      std::string hname = headerBasename;
-      hname += ".";
-      hname += ext;
+      std::string hname = cmStrCat(headerBasename, '.', ext);
       // if it's already in the set, don't check if it exists on disk
       if (allFiles.find(hname) != allFiles.end()) {
         break;
@@ -466,12 +462,9 @@ std::string cmExtraCodeBlocksGenerator::CreateDummyTargetFile(
   // this file doesn't seem to be used by C::B in custom makefile mode,
   // but we generate a unique file for each OBJECT library so in case
   // C::B uses it in some way, the targets don't interfere with each other.
-  std::string filename = lg->GetCurrentBinaryDirectory();
-  filename += "/";
-  filename += lg->GetTargetDirectory(target);
-  filename += "/";
-  filename += target->GetName();
-  filename += ".objlib";
+  std::string filename = cmStrCat(lg->GetCurrentBinaryDirectory(), '/',
+                                  lg->GetTargetDirectory(target), '/',
+                                  target->GetName(), ".objlib");
   cmGeneratedFileStream fout(filename);
   if (fout) {
     /* clang-format off */
@@ -491,8 +484,8 @@ void cmExtraCodeBlocksGenerator::AppendTarget(
   const std::string& compiler, const std::string& makeFlags)
 {
   cmMakefile const* makefile = lg->GetMakefile();
-  std::string makefileName = lg->GetCurrentBinaryDirectory();
-  makefileName += "/Makefile";
+  std::string makefileName =
+    cmStrCat(lg->GetCurrentBinaryDirectory(), "/Makefile");
 
   xml.StartElement("Target");
   xml.Attribute("title", targetName);
diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx
index 70e9a36..7f71a2c 100644
--- a/Source/cmExtraCodeLiteGenerator.cxx
+++ b/Source/cmExtraCodeLiteGenerator.cxx
@@ -68,8 +68,8 @@ void cmExtraCodeLiteGenerator::Generate()
       workspaceOutputDir = lg->GetCurrentBinaryDirectory();
       workspaceProjectName = lg->GetProjectName();
       workspaceSourcePath = lg->GetSourceDirectory();
-      workspaceFileName = workspaceOutputDir + "/";
-      workspaceFileName += workspaceProjectName + ".workspace";
+      workspaceFileName =
+        cmStrCat(workspaceOutputDir, '/', workspaceProjectName, ".workspace");
       this->WorkspacePath = lg->GetCurrentBinaryDirectory();
       break;
     }
@@ -299,15 +299,13 @@ void cmExtraCodeLiteGenerator::FindMatchingHeaderfiles(
   // A very similar version of that code exists also in the CodeBlocks
   // project generator.
   for (auto const& sit : cFiles) {
-    std::string headerBasename = cmSystemTools::GetFilenamePath(sit.first);
-    headerBasename += "/";
-    headerBasename += cmSystemTools::GetFilenameWithoutExtension(sit.first);
+    std::string headerBasename =
+      cmStrCat(cmSystemTools::GetFilenamePath(sit.first), '/',
+               cmSystemTools::GetFilenameWithoutExtension(sit.first));
 
     // check if there's a matching header around
     for (std::string const& ext : headerExts) {
-      std::string hname = headerBasename;
-      hname += ".";
-      hname += ext;
+      std::string hname = cmStrCat(headerBasename, '.', ext);
       // if it's already in the set, don't check if it exists on disk
       std::set<std::string>::const_iterator headerIt = otherFiles.find(hname);
       if (headerIt != otherFiles.end()) {
diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx
index 9ac355c..5ff638d 100644
--- a/Source/cmExtraEclipseCDT4Generator.cxx
+++ b/Source/cmExtraEclipseCDT4Generator.cxx
@@ -240,8 +240,7 @@ void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out,
   std::string envVarValue;
   const bool envVarSet = cmSystemTools::GetEnv(envVar, envVarValue);
 
-  std::string cacheEntryName = "CMAKE_ECLIPSE_ENVVAR_";
-  cacheEntryName += envVar;
+  std::string cacheEntryName = cmStrCat("CMAKE_ECLIPSE_ENVVAR_", envVar);
   const std::string* cacheValue =
     lg->GetState()->GetInitializedCacheValue(cacheEntryName);
 
@@ -464,9 +463,7 @@ void cmExtraEclipseCDT4Generator::WriteGroups(
   cmXMLWriter& xml)
 {
   for (cmSourceGroup const& sg : sourceGroups) {
-    std::string linkName3 = linkName;
-    linkName3 += "/";
-    linkName3 += sg.GetFullName();
+    std::string linkName3 = cmStrCat(linkName, '/', sg.GetFullName());
 
     std::replace(linkName3.begin(), linkName3.end(), '\\', '/');
 
@@ -481,9 +478,8 @@ void cmExtraEclipseCDT4Generator::WriteGroups(
       std::string const& fullPath = file->GetFullPath();
 
       if (!cmSystemTools::FileIsDirectory(fullPath)) {
-        std::string linkName4 = linkName3;
-        linkName4 += "/";
-        linkName4 += cmSystemTools::GetFilenameName(fullPath);
+        std::string linkName4 =
+          cmStrCat(linkName3, '/', cmSystemTools::GetFilenameName(fullPath));
         cmExtraEclipseCDT4Generator::AppendLinkedResource(
           xml, linkName4,
           cmExtraEclipseCDT4Generator::GetEclipsePath(fullPath), LinkToFile);
@@ -503,8 +499,7 @@ void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml)
     const std::vector<cmGeneratorTarget*>& targets = lg->GetGeneratorTargets();
 
     for (cmGeneratorTarget* target : targets) {
-      std::string linkName2 = linkName;
-      linkName2 += "/";
+      std::string linkName2 = cmStrCat(linkName, '/');
       switch (target->GetType()) {
         case cmStateEnums::EXECUTABLE:
         case cmStateEnums::STATIC_LIBRARY:
@@ -566,8 +561,7 @@ void cmExtraEclipseCDT4Generator::CreateLinksToSubprojects(
     // .project itself
     if ((baseDir != linkSourceDirectory) &&
         !cmSystemTools::IsSubDirectory(baseDir, linkSourceDirectory)) {
-      std::string linkName = "[Subprojects]/";
-      linkName += it.first;
+      std::string linkName = cmStrCat("[Subprojects]/", it.first);
       cmExtraEclipseCDT4Generator::AppendLinkedResource(
         xml, linkName,
         cmExtraEclipseCDT4Generator::GetEclipsePath(linkSourceDirectory),
@@ -970,28 +964,21 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
                                                            : "[lib] ");
           cmExtraEclipseCDT4Generator::AppendTarget(xml, targetName, make,
                                                     makeArgs, subdir, prefix);
-          std::string fastTarget = targetName;
-          fastTarget += "/fast";
+          std::string fastTarget = cmStrCat(targetName, "/fast");
           cmExtraEclipseCDT4Generator::AppendTarget(xml, fastTarget, make,
                                                     makeArgs, subdir, prefix);
 
           // Add Build and Clean targets in the virtual folder of targets:
           if (this->SupportsVirtualFolders) {
-            std::string virtDir = "[Targets]/";
-            virtDir += prefix;
-            virtDir += targetName;
-            std::string buildArgs = "-C \"";
-            buildArgs += lgen->GetBinaryDirectory();
-            buildArgs += "\" ";
-            buildArgs += makeArgs;
+            std::string virtDir = cmStrCat("[Targets]/", prefix, targetName);
+            std::string buildArgs =
+              cmStrCat("-C \"", lgen->GetBinaryDirectory(), "\" ", makeArgs);
             cmExtraEclipseCDT4Generator::AppendTarget(
               xml, "Build", make, buildArgs, virtDir, "", targetName.c_str());
 
-            std::string cleanArgs = "-E chdir \"";
-            cleanArgs += lgen->GetCurrentBinaryDirectory();
-            cleanArgs += "\" \"";
-            cleanArgs += cmSystemTools::GetCMakeCommand();
-            cleanArgs += "\" -P \"";
+            std::string cleanArgs =
+              cmStrCat("-E chdir \"", lgen->GetCurrentBinaryDirectory(),
+                       "\" \"", cmSystemTools::GetCMakeCommand(), "\" -P \"");
             cmGeneratorTarget* gt = target;
             cleanArgs += lgen->GetTargetDirectory(gt);
             cleanArgs += "/cmake_clean.cmake\"";
diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx
index 877f109..2bfbb0d 100644
--- a/Source/cmExtraKateGenerator.cxx
+++ b/Source/cmExtraKateGenerator.cxx
@@ -9,6 +9,7 @@
 #include "cmMakefile.h"
 #include "cmSourceFile.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <ostream>
@@ -53,8 +54,7 @@ void cmExtraKateGenerator::Generate()
 void cmExtraKateGenerator::CreateKateProjectFile(
   const cmLocalGenerator* lg) const
 {
-  std::string filename = lg->GetBinaryDirectory();
-  filename += "/.kateproject";
+  std::string filename = cmStrCat(lg->GetBinaryDirectory(), "/.kateproject");
   cmGeneratedFileStream fout(filename);
   if (!fout) {
     return;
@@ -164,8 +164,7 @@ void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator* lg,
         case cmStateEnums::OBJECT_LIBRARY: {
           this->AppendTarget(fout, targetName, make, makeArgs, currentDir,
                              homeOutputDir);
-          std::string fastTarget = targetName;
-          fastTarget += "/fast";
+          std::string fastTarget = cmStrCat(targetName, "/fast");
           this->AppendTarget(fout, fastTarget, make, makeArgs, currentDir,
                              homeOutputDir);
 
@@ -208,10 +207,8 @@ void cmExtraKateGenerator::AppendTarget(cmGeneratedFileStream& fout,
 void cmExtraKateGenerator::CreateDummyKateProjectFile(
   const cmLocalGenerator* lg) const
 {
-  std::string filename = lg->GetBinaryDirectory();
-  filename += "/";
-  filename += this->ProjectName;
-  filename += ".kateproject";
+  std::string filename =
+    cmStrCat(lg->GetBinaryDirectory(), '/', this->ProjectName, ".kateproject");
   cmGeneratedFileStream fout(filename);
   if (!fout) {
     return;
@@ -224,20 +221,17 @@ void cmExtraKateGenerator::CreateDummyKateProjectFile(
 std::string cmExtraKateGenerator::GenerateFilesString(
   const cmLocalGenerator* lg) const
 {
-  std::string s = lg->GetSourceDirectory();
-  s += "/.git";
+  std::string s = cmStrCat(lg->GetSourceDirectory(), "/.git");
   if (cmSystemTools::FileExists(s)) {
     return "\"git\": 1 ";
   }
 
-  s = lg->GetSourceDirectory();
-  s += "/.svn";
+  s = cmStrCat(lg->GetSourceDirectory(), "/.svn");
   if (cmSystemTools::FileExists(s)) {
     return "\"svn\": 1 ";
   }
 
-  s = lg->GetSourceDirectory();
-  s += "/";
+  s = cmStrCat(lg->GetSourceDirectory(), '/');
 
   std::set<std::string> files;
   std::string tmp;
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index 6c17279..36d9afd 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -219,8 +219,7 @@ void cmExtraSublimeTextGenerator::AppendAllTargets(
           this->AppendTarget(fout, targetName, lg, target, make.c_str(),
                              makefile, compiler.c_str(), sourceFileFlags,
                              false);
-          std::string fastTarget = targetName;
-          fastTarget += "/fast";
+          std::string fastTarget = cmStrCat(targetName, "/fast");
           this->AppendTarget(fout, fastTarget, lg, target, make.c_str(),
                              makefile, compiler.c_str(), sourceFileFlags,
                              false);
@@ -311,8 +310,7 @@ void cmExtraSublimeTextGenerator::AppendTarget(
 std::string cmExtraSublimeTextGenerator::BuildMakeCommand(
   const std::string& make, const char* makefile, const std::string& target)
 {
-  std::string command = "\"";
-  command += make + "\"";
+  std::string command = cmStrCat('"', make, '"');
   std::string generator = this->GlobalGenerator->GetName();
   if (generator == "NMake Makefiles") {
     std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
@@ -393,8 +391,8 @@ std::string cmExtraSublimeTextGenerator::ComputeDefines(
       defines, genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS));
   }
 
-  std::string defPropName = "COMPILE_DEFINITIONS_";
-  defPropName += cmSystemTools::UpperCase(config);
+  std::string defPropName =
+    cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config));
   if (const char* config_compile_defs = source->GetProperty(defPropName)) {
     lg->AppendDefines(
       defines,
diff --git a/Source/cmFLTKWrapUICommand.cxx b/Source/cmFLTKWrapUICommand.cxx
index ccd6be9..2150051 100644
--- a/Source/cmFLTKWrapUICommand.cxx
+++ b/Source/cmFLTKWrapUICommand.cxx
@@ -21,12 +21,11 @@ static void FinalAction(cmMakefile& makefile, std::string const& name)
   // they didn;t then print a warning and add then anyhow
   cmTarget* target = makefile.FindLocalNonAliasTarget(name);
   if (!target) {
-    std::string msg =
-      "FLTK_WRAP_UI was called with a target that was never created: ";
-    msg += name;
-    msg += ".  The problem was found while processing the source directory: ";
-    msg += makefile.GetCurrentSourceDirectory();
-    msg += ".  This FLTK_WRAP_UI call will be ignored.";
+    std::string msg = cmStrCat(
+      "FLTK_WRAP_UI was called with a target that was never created: ", name,
+      ".  The problem was found while processing the source directory: ",
+      makefile.GetCurrentSourceDirectory(),
+      ".  This FLTK_WRAP_UI call will be ignored.");
     cmSystemTools::Message(msg, "Warning");
   }
 }
diff --git a/Source/cmFileAPI.cxx b/Source/cmFileAPI.cxx
index aee42d7..5d9181a 100644
--- a/Source/cmFileAPI.cxx
+++ b/Source/cmFileAPI.cxx
@@ -407,9 +407,7 @@ const char* cmFileAPI::ObjectKindName(ObjectKind kind)
 
 std::string cmFileAPI::ObjectName(Object const& o)
 {
-  std::string name = ObjectKindName(o.Kind);
-  name += "-v";
-  name += std::to_string(o.Version);
+  std::string name = cmStrCat(ObjectKindName(o.Kind), "-v", o.Version);
   return name;
 }
 
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 9867f16..5589537 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -97,8 +97,8 @@ bool HandleWriteImpl(std::vector<std::string> const& args, bool append,
 
   std::string fileName = *i;
   if (!cmsys::SystemTools::FileIsFullPath(*i)) {
-    fileName = status.GetMakefile().GetCurrentSourceDirectory();
-    fileName += "/" + *i;
+    fileName =
+      cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', *i);
   }
 
   i++;
@@ -134,20 +134,18 @@ bool HandleWriteImpl(std::vector<std::string> const& args, bool append,
   cmsys::ofstream file(fileName.c_str(),
                        append ? std::ios::app : std::ios::out);
   if (!file) {
-    std::string error = "failed to open for writing (";
-    error += cmSystemTools::GetLastSystemError();
-    error += "):\n  ";
-    error += fileName;
+    std::string error =
+      cmStrCat("failed to open for writing (",
+               cmSystemTools::GetLastSystemError(), "):\n  ", fileName);
     status.SetError(error);
     return false;
   }
   std::string message = cmJoin(cmMakeRange(i, args.end()), std::string());
   file << message;
   if (!file) {
-    std::string error = "write failed (";
-    error += cmSystemTools::GetLastSystemError();
-    error += "):\n  ";
-    error += fileName;
+    std::string error =
+      cmStrCat("write failed (", cmSystemTools::GetLastSystemError(), "):\n  ",
+               fileName);
     status.SetError(error);
     return false;
   }
@@ -198,8 +196,8 @@ bool HandleReadCommand(std::vector<std::string> const& args,
 
   std::string fileName = fileNameArg;
   if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
-    fileName = status.GetMakefile().GetCurrentSourceDirectory();
-    fileName += "/" + fileNameArg;
+    fileName = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/',
+                        fileNameArg);
   }
 
 // Open the specified file.
@@ -212,10 +210,9 @@ bool HandleReadCommand(std::vector<std::string> const& args,
 #endif
 
   if (!file) {
-    std::string error = "failed to open for reading (";
-    error += cmSystemTools::GetLastSystemError();
-    error += "):\n  ";
-    error += fileName;
+    std::string error =
+      cmStrCat("failed to open for reading (",
+               cmSystemTools::GetLastSystemError(), "):\n  ", fileName);
     status.SetError(error);
     return false;
   }
@@ -315,8 +312,8 @@ bool HandleStringsCommand(std::vector<std::string> const& args,
   // Get the file to read.
   std::string fileName = args[1];
   if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
-    fileName = status.GetMakefile().GetCurrentSourceDirectory();
-    fileName += "/" + args[1];
+    fileName =
+      cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[1]);
   }
 
   // Get the variable in which to store the results.
@@ -468,8 +465,8 @@ bool HandleStringsCommand(std::vector<std::string> const& args,
   if (hex_conversion_enabled) {
     // TODO: should work without temp file, but just on a memory buffer
     std::string binaryFileName =
-      status.GetMakefile().GetCurrentBinaryDirectory();
-    binaryFileName += "/CMakeFiles/FileCommandStringsBinaryFile";
+      cmStrCat(status.GetMakefile().GetCurrentBinaryDirectory(),
+               "/CMakeFiles/FileCommandStringsBinaryFile");
     if (cmHexFileConverter::TryConvert(fileName, binaryFileName)) {
       fileName = binaryFileName;
     }
@@ -872,8 +869,8 @@ bool HandleMakeDirectoryCommand(std::vector<std::string> const& args,
   {
     const std::string* cdir = &arg;
     if (!cmsys::SystemTools::FileIsFullPath(arg)) {
-      expr = status.GetMakefile().GetCurrentSourceDirectory();
-      expr += "/" + arg;
+      expr =
+        cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', arg);
       cdir = &expr;
     }
     if (!status.GetMakefile().CanIWriteThisFile(*cdir)) {
@@ -903,8 +900,8 @@ bool HandleTouchImpl(std::vector<std::string> const& args, bool create,
   {
     std::string tfile = arg;
     if (!cmsys::SystemTools::FileIsFullPath(tfile)) {
-      tfile = status.GetMakefile().GetCurrentSourceDirectory();
-      tfile += "/" + arg;
+      tfile =
+        cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', arg);
     }
     if (!status.GetMakefile().CanIWriteThisFile(tfile)) {
       std::string e =
@@ -1074,11 +1071,8 @@ bool HandleRPathChangeCommand(std::vector<std::string> const& args,
   }
   if (success) {
     if (changed) {
-      std::string message = "Set runtime path of \"";
-      message += file;
-      message += "\" to \"";
-      message += newRPath;
-      message += "\"";
+      std::string message =
+        cmStrCat("Set runtime path of \"", file, "\" to \"", newRPath, '"');
       status.GetMakefile().DisplayStatus(message, -1);
     }
     ft.Store(file);
@@ -1136,9 +1130,8 @@ bool HandleRPathRemoveCommand(std::vector<std::string> const& args,
   }
   if (success) {
     if (removed) {
-      std::string message = "Removed runtime path from \"";
-      message += file;
-      message += "\"";
+      std::string message =
+        cmStrCat("Removed runtime path from \"", file, '"');
       status.GetMakefile().DisplayStatus(message, -1);
     }
     ft.Store(file);
@@ -1307,13 +1300,13 @@ bool HandleRename(std::vector<std::string> const& args,
   // Compute full path for old and new names.
   std::string oldname = args[1];
   if (!cmsys::SystemTools::FileIsFullPath(oldname)) {
-    oldname = status.GetMakefile().GetCurrentSourceDirectory();
-    oldname += "/" + args[1];
+    oldname =
+      cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[1]);
   }
   std::string newname = args[2];
   if (!cmsys::SystemTools::FileIsFullPath(newname)) {
-    newname = status.GetMakefile().GetCurrentSourceDirectory();
-    newname += "/" + args[2];
+    newname =
+      cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', args[2]);
   }
 
   if (!cmSystemTools::RenameFile(oldname, newname)) {
@@ -1349,8 +1342,8 @@ bool HandleRemoveImpl(std::vector<std::string> const& args, bool recurse,
       continue;
     }
     if (!cmsys::SystemTools::FileIsFullPath(fileName)) {
-      fileName = status.GetMakefile().GetCurrentSourceDirectory();
-      fileName += "/" + arg;
+      fileName =
+        cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', arg);
     }
 
     if (cmSystemTools::FileIsDirectory(fileName) &&
@@ -1704,8 +1697,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
       std::string::size_type pos = i->find("=");
       if (pos == std::string::npos) {
         std::string err =
-          "DOWNLOAD EXPECTED_HASH expects ALGO=value but got: ";
-        err += *i;
+          cmStrCat("DOWNLOAD EXPECTED_HASH expects ALGO=value but got: ", *i);
         status.SetError(err);
         return false;
       }
@@ -1713,8 +1705,8 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
       expectedHash = cmSystemTools::LowerCase(i->substr(pos + 1));
       hash = std::unique_ptr<cmCryptoHash>(cmCryptoHash::New(algo));
       if (!hash) {
-        std::string err = "DOWNLOAD EXPECTED_HASH given unknown ALGO: ";
-        err += algo;
+        std::string err =
+          cmStrCat("DOWNLOAD EXPECTED_HASH given unknown ALGO: ", algo);
         status.SetError(err);
         return false;
       }
@@ -1735,8 +1727,7 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
       curl_headers.push_back(*i);
     } else {
       // Do not return error for compatibility reason.
-      std::string err = "Unexpected argument: ";
-      err += *i;
+      std::string err = cmStrCat("Unexpected argument: ", *i);
       status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, err);
     }
     ++i;
@@ -1749,9 +1740,8 @@ bool HandleDownloadCommand(std::vector<std::string> const& args,
     std::string msg;
     std::string actualHash = hash->HashFile(file);
     if (actualHash == expectedHash) {
-      msg = "returning early; file already exists with expected ";
-      msg += hashMatchMSG;
-      msg += "\"";
+      msg = cmStrCat("returning early; file already exists with expected ",
+                     hashMatchMSG, '"');
       if (!statusVar.empty()) {
         std::ostringstream result;
         result << 0 << ";\"" << msg;
@@ -2050,8 +2040,7 @@ bool HandleUploadCommand(std::vector<std::string> const& args,
       curl_headers.push_back(*i);
     } else {
       // Do not return error for compatibility reason.
-      std::string err = "Unexpected argument: ";
-      err += *i;
+      std::string err = cmStrCat("Unexpected argument: ", *i);
       status.GetMakefile().IssueMessage(MessageType::AUTHOR_WARNING, err);
     }
 
@@ -2062,8 +2051,8 @@ bool HandleUploadCommand(std::vector<std::string> const& args,
   //
   FILE* fin = cmsys::SystemTools::Fopen(filename, "rb");
   if (!fin) {
-    std::string errStr = "UPLOAD cannot open file '";
-    errStr += filename + "' for reading.";
+    std::string errStr =
+      cmStrCat("UPLOAD cannot open file '", filename, "' for reading.");
     status.SetError(errStr);
     return false;
   }
diff --git a/Source/cmFileCopier.cxx b/Source/cmFileCopier.cxx
index 2e54b88..3156c95 100644
--- a/Source/cmFileCopier.cxx
+++ b/Source/cmFileCopier.cxx
@@ -314,8 +314,8 @@ bool cmFileCopier::CheckValue(std::string const& arg)
       if (arg.empty() || cmSystemTools::FileIsFullPath(arg)) {
         this->Destination = arg;
       } else {
-        this->Destination = this->Makefile->GetCurrentBinaryDirectory();
-        this->Destination += "/" + arg;
+        this->Destination =
+          cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/', arg);
       }
       this->Doing = DoingNone;
       break;
@@ -323,8 +323,8 @@ bool cmFileCopier::CheckValue(std::string const& arg)
       if (cmSystemTools::FileIsFullPath(arg)) {
         this->FilesFromDir = arg;
       } else {
-        this->FilesFromDir = this->Makefile->GetCurrentSourceDirectory();
-        this->FilesFromDir += "/" + arg;
+        this->FilesFromDir =
+          cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', arg);
       }
       cmSystemTools::ConvertToUnixSlashes(this->FilesFromDir);
       this->Doing = DoingNone;
@@ -334,9 +334,8 @@ bool cmFileCopier::CheckValue(std::string const& arg)
       // leading slash and trailing end-of-string in the matched
       // string to make sure the pattern matches only whole file
       // names.
-      std::string regex = "/";
-      regex += cmsys::Glob::PatternToRegex(arg, false);
-      regex += "$";
+      std::string regex =
+        cmStrCat('/', cmsys::Glob::PatternToRegex(arg, false), '$');
       this->MatchRules.emplace_back(regex);
       this->CurrentMatchRule = &*(this->MatchRules.end() - 1);
       if (this->CurrentMatchRule->Regex.is_valid()) {
@@ -699,12 +698,8 @@ bool cmFileCopier::InstallDirectory(const std::string& source,
   for (unsigned long fileNum = 0; fileNum < numFiles; ++fileNum) {
     if (!(strcmp(dir.GetFile(fileNum), ".") == 0 ||
           strcmp(dir.GetFile(fileNum), "..") == 0)) {
-      std::string fromPath = source;
-      fromPath += "/";
-      fromPath += dir.GetFile(fileNum);
-      std::string toPath = destination;
-      toPath += "/";
-      toPath += dir.GetFile(fileNum);
+      std::string fromPath = cmStrCat(source, '/', dir.GetFile(fileNum));
+      std::string toPath = cmStrCat(destination, '/', dir.GetFile(fileNum));
       if (!this->Install(fromPath, toPath)) {
         return false;
       }
diff --git a/Source/cmFileInstaller.cxx b/Source/cmFileInstaller.cxx
index 6a95b92..a773738 100644
--- a/Source/cmFileInstaller.cxx
+++ b/Source/cmFileInstaller.cxx
@@ -59,8 +59,8 @@ void cmFileInstaller::ReportCopy(const std::string& toFile, Type type,
                                  bool copy)
 {
   if (!this->MessageNever && (copy || !this->MessageLazy)) {
-    std::string message = (copy ? "Installing: " : "Up-to-date: ");
-    message += toFile;
+    std::string message =
+      cmStrCat((copy ? "Installing: " : "Up-to-date: "), toFile);
     this->Makefile->DisplayStatus(message, -1);
   }
   if (type != TypeDir) {
@@ -311,11 +311,11 @@ bool cmFileInstaller::HandleInstallDestination()
       if (ch2 == '/') {
         // looks like a network path.
         std::string message =
-          "called with network path DESTINATION. This "
-          "does not make sense when using DESTDIR. Specify local "
-          "absolute path or remove DESTDIR environment variable."
-          "\nDESTINATION=\n";
-        message += destination;
+          cmStrCat("called with network path DESTINATION. This "
+                   "does not make sense when using DESTDIR. Specify local "
+                   "absolute path or remove DESTDIR environment variable."
+                   "\nDESTINATION=\n",
+                   destination);
         this->Status.SetError(message);
         return false;
       }
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index 9bacfc4..191d7bb 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -189,9 +189,7 @@ void cmFindBase::FillCMakeEnvironmentPath()
   cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeEnvironment];
 
   // Add CMAKE_*_PATH environment variables
-  std::string var = "CMAKE_";
-  var += this->CMakePathName;
-  var += "_PATH";
+  std::string var = cmStrCat("CMAKE_", this->CMakePathName, "_PATH");
   paths.AddEnvPrefixPath("CMAKE_PREFIX_PATH");
   paths.AddEnvPath(var);
 
@@ -223,9 +221,7 @@ void cmFindBase::FillCMakeVariablePath()
   // Add CMake variables of the same name as the previous environment
   // variables CMAKE_*_PATH to be used most of the time with -D
   // command line options
-  std::string var = "CMAKE_";
-  var += this->CMakePathName;
-  var += "_PATH";
+  std::string var = cmStrCat("CMAKE_", this->CMakePathName, "_PATH");
   paths.AddCMakePrefixPath("CMAKE_PREFIX_PATH");
   paths.AddCMakePath(var);
 
@@ -257,9 +253,7 @@ void cmFindBase::FillCMakeSystemVariablePath()
 {
   cmSearchPath& paths = this->LabeledPaths[PathLabel::CMakeSystem];
 
-  std::string var = "CMAKE_SYSTEM_";
-  var += this->CMakePathName;
-  var += "_PATH";
+  std::string var = cmStrCat("CMAKE_SYSTEM_", this->CMakePathName, "_PATH");
   paths.AddCMakePrefixPath("CMAKE_SYSTEM_PREFIX_PATH");
   paths.AddCMakePath(var);
 
diff --git a/Source/cmFindCommon.cxx b/Source/cmFindCommon.cxx
index c5209c4..9425f99 100644
--- a/Source/cmFindCommon.cxx
+++ b/Source/cmFindCommon.cxx
@@ -92,8 +92,8 @@ void cmFindCommon::InitializeSearchPathGroups()
 void cmFindCommon::SelectDefaultRootPathMode()
 {
   // Check the policy variable for this find command type.
-  std::string findRootPathVar = "CMAKE_FIND_ROOT_PATH_MODE_";
-  findRootPathVar += this->CMakePathName;
+  std::string findRootPathVar =
+    cmStrCat("CMAKE_FIND_ROOT_PATH_MODE_", this->CMakePathName);
   std::string rootPathMode =
     this->Makefile->GetSafeDefinition(findRootPathVar);
   if (rootPathMode == "NEVER") {
@@ -229,8 +229,7 @@ void cmFindCommon::RerootPaths(std::vector<std::string>& paths)
         rootedDir = up;
       } else if (!up.empty() && up[0] != '~') {
         // Start with the new root.
-        rootedDir = r;
-        rootedDir += "/";
+        rootedDir = cmStrCat(r, '/');
 
         // Append the original path with its old root removed.
         rootedDir += cmSystemTools::SplitPathRootComponent(up);
diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx
index dc160b5..924a14e 100644
--- a/Source/cmFindLibraryCommand.cxx
+++ b/Source/cmFindLibraryCommand.cxx
@@ -312,8 +312,7 @@ void cmFindLibraryHelper::AddName(std::string const& name)
   entry.Raw = name;
 
   // Build a regular expression to match library names.
-  std::string regex = "^";
-  regex += this->PrefixRegexStr;
+  std::string regex = cmStrCat('^', this->PrefixRegexStr);
   this->RegexFromLiteral(regex, name);
   regex += this->SuffixRegexStr;
   if (this->OpenBSD) {
@@ -349,8 +348,7 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
   // one cannot tell just from the library name whether it is a static
   // library or an import library).
   if (name.TryRaw) {
-    this->TestPath = path;
-    this->TestPath += name.Raw;
+    this->TestPath = cmStrCat(path, name.Raw);
     if (cmSystemTools::FileExists(this->TestPath, true)) {
       this->BestPath = cmSystemTools::CollapseFullPath(this->TestPath);
       cmSystemTools::ConvertToUnixSlashes(this->BestPath);
@@ -375,8 +373,7 @@ bool cmFindLibraryHelper::CheckDirectoryForName(std::string const& path,
     std::string const& testName = origName;
 #endif
     if (name.Regex.find(testName)) {
-      this->TestPath = path;
-      this->TestPath += origName;
+      this->TestPath = cmStrCat(path, origName);
       if (!cmSystemTools::FileIsDirectory(this->TestPath)) {
         // This is a matching file.  Check if it is better than the
         // best name found so far.  Earlier prefixes are preferred,
@@ -466,9 +463,7 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryNamesPerDir()
   // Search for all names in each search path.
   for (std::string const& d : this->SearchPaths) {
     for (std::string const& n : this->Names) {
-      fwPath = d;
-      fwPath += n;
-      fwPath += ".framework";
+      fwPath = cmStrCat(d, n, ".framework");
       if (cmSystemTools::FileIsDirectory(fwPath)) {
         return cmSystemTools::CollapseFullPath(fwPath);
       }
@@ -485,9 +480,7 @@ std::string cmFindLibraryCommand::FindFrameworkLibraryDirsPerName()
   // Search for each name in all search paths.
   for (std::string const& n : this->Names) {
     for (std::string const& d : this->SearchPaths) {
-      fwPath = d;
-      fwPath += n;
-      fwPath += ".framework";
+      fwPath = cmStrCat(d, n, ".framework");
       if (cmSystemTools::FileIsDirectory(fwPath)) {
         return cmSystemTools::CollapseFullPath(fwPath);
       }
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index ae93eff..9132760 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -408,19 +408,16 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
   if (this->Version.empty() || components.empty()) {
     // Check whether we are recursing inside "Find<name>.cmake" within
     // another find_package(<name>) call.
-    std::string mod = this->Name;
-    mod += "_FIND_MODULE";
+    std::string mod = cmStrCat(this->Name, "_FIND_MODULE");
     if (this->Makefile->IsOn(mod)) {
       if (this->Version.empty()) {
         // Get version information from the outer call if necessary.
         // Requested version string.
-        std::string ver = this->Name;
-        ver += "_FIND_VERSION";
+        std::string ver = cmStrCat(this->Name, "_FIND_VERSION");
         this->Version = this->Makefile->GetSafeDefinition(ver);
 
         // Whether an exact version is required.
-        std::string exact = this->Name;
-        exact += "_FIND_VERSION_EXACT";
+        std::string exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT");
         this->VersionExact = this->Makefile->IsOn(exact);
       }
       if (components.empty()) {
@@ -458,8 +455,8 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args,
     }
   }
 
-  std::string disableFindPackageVar = "CMAKE_DISABLE_FIND_PACKAGE_";
-  disableFindPackageVar += this->Name;
+  std::string disableFindPackageVar =
+    cmStrCat("CMAKE_DISABLE_FIND_PACKAGE_", this->Name);
   if (this->Makefile->IsOn(disableFindPackageVar)) {
     if (this->Required) {
       std::ostringstream e;
@@ -589,8 +586,7 @@ bool cmFindPackageCommand::FindPackageUsingModuleMode()
 
 bool cmFindPackageCommand::FindPackageUsingConfigMode()
 {
-  this->Variable = this->Name;
-  this->Variable += "_DIR";
+  this->Variable = cmStrCat(this->Name, "_DIR");
 
   // Add the default name.
   if (this->Names.empty()) {
@@ -600,12 +596,10 @@ bool cmFindPackageCommand::FindPackageUsingConfigMode()
   // Add the default configs.
   if (this->Configs.empty()) {
     for (std::string const& n : this->Names) {
-      std::string config = n;
-      config += "Config.cmake";
+      std::string config = cmStrCat(n, "Config.cmake");
       this->Configs.push_back(config);
 
-      config = cmSystemTools::LowerCase(n);
-      config += "-config.cmake";
+      config = cmStrCat(cmSystemTools::LowerCase(n), "-config.cmake");
       this->Configs.push_back(std::move(config));
     }
   }
@@ -634,24 +628,21 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components)
   if (this->Quiet) {
     // Tell the module that is about to be read that it should find
     // quietly.
-    std::string quietly = this->Name;
-    quietly += "_FIND_QUIETLY";
+    std::string quietly = cmStrCat(this->Name, "_FIND_QUIETLY");
     this->AddFindDefinition(quietly, "1");
   }
 
   if (this->Required) {
     // Tell the module that is about to be read that it should report
     // a fatal error if the package is not found.
-    std::string req = this->Name;
-    req += "_FIND_REQUIRED";
+    std::string req = cmStrCat(this->Name, "_FIND_REQUIRED");
     this->AddFindDefinition(req, "1");
   }
 
   if (!this->Version.empty()) {
     // Tell the module that is about to be read what version of the
     // package has been requested.
-    std::string ver = this->Name;
-    ver += "_FIND_VERSION";
+    std::string ver = cmStrCat(this->Name, "_FIND_VERSION");
     this->AddFindDefinition(ver, this->Version.c_str());
     char buf[64];
     sprintf(buf, "%u", this->VersionMajor);
@@ -666,8 +657,7 @@ void cmFindPackageCommand::SetModuleVariables(const std::string& components)
     this->AddFindDefinition(ver + "_COUNT", buf);
 
     // Tell the module whether an exact version has been requested.
-    std::string exact = this->Name;
-    exact += "_FIND_VERSION_EXACT";
+    std::string exact = cmStrCat(this->Name, "_FIND_VERSION_EXACT");
     this->AddFindDefinition(exact, this->VersionExact ? "1" : "0");
   }
 }
@@ -700,9 +690,7 @@ void cmFindPackageCommand::RestoreFindDefinitions()
 
 bool cmFindPackageCommand::FindModule(bool& found)
 {
-  std::string module = "Find";
-  module += this->Name;
-  module += ".cmake";
+  std::string module = cmStrCat("Find", this->Name, ".cmake");
   bool system = false;
   std::string mfile = this->Makefile->GetModulesFile(module, system);
   if (!mfile.empty()) {
@@ -731,8 +719,7 @@ bool cmFindPackageCommand::FindModule(bool& found)
     // Load the module we found, and set "<name>_FIND_MODULE" to true
     // while inside it.
     found = true;
-    std::string var = this->Name;
-    var += "_FIND_MODULE";
+    std::string var = cmStrCat(this->Name, "_FIND_MODULE");
     this->Makefile->AddDefinition(var, "1");
     bool result = this->ReadListFile(mfile, DoPolicyScope);
     this->Makefile->RemoveDefinition(var);
@@ -785,10 +772,8 @@ bool cmFindPackageCommand::HandlePackageMode(
     }
   }
 
-  std::string foundVar = this->Name;
-  foundVar += "_FOUND";
-  std::string notFoundMessageVar = this->Name;
-  notFoundMessageVar += "_NOT_FOUND_MESSAGE";
+  std::string foundVar = cmStrCat(this->Name, "_FOUND");
+  std::string notFoundMessageVar = cmStrCat(this->Name, "_NOT_FOUND_MESSAGE");
   std::string notFoundMessage;
 
   // If the directory for the config file was found, try to read the file.
@@ -878,9 +863,8 @@ bool cmFindPackageCommand::HandlePackageMode(
       } else {
         std::string requestedVersionString;
         if (!this->Version.empty()) {
-          requestedVersionString = " (requested version ";
-          requestedVersionString += this->Version;
-          requestedVersionString += ")";
+          requestedVersionString =
+            cmStrCat(" (requested version ", this->Version, ')');
         }
 
         if (this->UseConfigFiles) {
@@ -962,18 +946,17 @@ bool cmFindPackageCommand::HandlePackageMode(
   this->Makefile->AddDefinition(foundVar, found ? "1" : "0");
 
   // Set a variable naming the configuration file that was found.
-  std::string fileVar = this->Name;
-  fileVar += "_CONFIG";
+  std::string fileVar = cmStrCat(this->Name, "_CONFIG");
   if (found) {
     this->Makefile->AddDefinition(fileVar, this->FileFound);
   } else {
     this->Makefile->RemoveDefinition(fileVar);
   }
 
-  std::string consideredConfigsVar = this->Name;
-  consideredConfigsVar += "_CONSIDERED_CONFIGS";
-  std::string consideredVersionsVar = this->Name;
-  consideredVersionsVar += "_CONSIDERED_VERSIONS";
+  std::string consideredConfigsVar =
+    cmStrCat(this->Name, "_CONSIDERED_CONFIGS");
+  std::string consideredVersionsVar =
+    cmStrCat(this->Name, "_CONSIDERED_VERSIONS");
 
   std::string consideredConfigFiles;
   std::string consideredVersions;
@@ -1035,9 +1018,8 @@ bool cmFindPackageCommand::FindConfig()
     init = this->Variable + "-NOTFOUND";
   }
   std::string help =
-    "The directory containing a CMake configuration file for ";
-  help += this->Name;
-  help += ".";
+    cmStrCat("The directory containing a CMake configuration file for ",
+             this->Name, '.');
   // We force the value since we do not get here if it was already set.
   this->Makefile->AddCacheDefinition(this->Variable, init.c_str(),
                                      help.c_str(), cmStateEnums::PATH, true);
@@ -1084,9 +1066,7 @@ bool cmFindPackageCommand::ReadListFile(const std::string& f,
   if (this->Makefile->ReadDependentFile(f, noPolicyScope)) {
     return true;
   }
-  std::string e = "Error reading CMake code from \"";
-  e += f;
-  e += "\".";
+  std::string e = cmStrCat("Error reading CMake code from \"", f, "\".");
   this->SetError(e);
   return false;
 }
@@ -1138,12 +1118,11 @@ void cmFindPackageCommand::AppendToFoundProperty(bool found)
 void cmFindPackageCommand::AppendSuccessInformation()
 {
   {
-    std::string transitivePropName = "_CMAKE_";
-    transitivePropName += this->Name + "_TRANSITIVE_DEPENDENCY";
+    std::string transitivePropName =
+      cmStrCat("_CMAKE_", this->Name, "_TRANSITIVE_DEPENDENCY");
     this->Makefile->GetState()->SetGlobalProperty(transitivePropName, "False");
   }
-  std::string found = this->Name;
-  found += "_FOUND";
+  std::string found = cmStrCat(this->Name, "_FOUND");
   std::string upperFound = cmSystemTools::UpperCase(found);
 
   const char* upperResult = this->Makefile->GetDefinition(upperFound);
@@ -1154,28 +1133,23 @@ void cmFindPackageCommand::AppendSuccessInformation()
 
   // Record whether the find was quiet or not, so this can be used
   // e.g. in FeatureSummary.cmake
-  std::string quietInfoPropName = "_CMAKE_";
-  quietInfoPropName += this->Name;
-  quietInfoPropName += "_QUIET";
+  std::string quietInfoPropName = cmStrCat("_CMAKE_", this->Name, "_QUIET");
   this->Makefile->GetState()->SetGlobalProperty(
     quietInfoPropName, this->Quiet ? "TRUE" : "FALSE");
 
   // set a global property to record the required version of this package
-  std::string versionInfoPropName = "_CMAKE_";
-  versionInfoPropName += this->Name;
-  versionInfoPropName += "_REQUIRED_VERSION";
+  std::string versionInfoPropName =
+    cmStrCat("_CMAKE_", this->Name, "_REQUIRED_VERSION");
   std::string versionInfo;
   if (!this->Version.empty()) {
-    versionInfo = this->VersionExact ? "==" : ">=";
-    versionInfo += " ";
-    versionInfo += this->Version;
+    versionInfo =
+      cmStrCat(this->VersionExact ? "==" : ">=", ' ', this->Version);
   }
   this->Makefile->GetState()->SetGlobalProperty(versionInfoPropName,
                                                 versionInfo.c_str());
   if (this->Required) {
-    std::string requiredInfoPropName = "_CMAKE_";
-    requiredInfoPropName += this->Name;
-    requiredInfoPropName += "_TYPE";
+    std::string requiredInfoPropName =
+      cmStrCat("_CMAKE_", this->Name, "_TYPE");
     this->Makefile->GetState()->SetGlobalProperty(requiredInfoPropName,
                                                   "REQUIRED");
   }
@@ -1285,9 +1259,7 @@ void cmFindPackageCommand::FillPrefixesUserRegistry()
   char dir[B_PATH_NAME_LENGTH];
   if (find_directory(B_USER_SETTINGS_DIRECTORY, -1, false, dir, sizeof(dir)) ==
       B_OK) {
-    std::string fname = dir;
-    fname += "/cmake/packages/";
-    fname += Name;
+    std::string fname = cmStrCat(dir, "/cmake/packages/", Name);
     this->LoadPackageRegistryDir(fname,
                                  this->LabeledPaths[PathLabel::UserRegistry]);
   }
@@ -1428,9 +1400,7 @@ void cmFindPackageCommand::LoadPackageRegistryDir(std::string const& dir,
 
   std::string fname;
   for (unsigned long i = 0; i < files.GetNumberOfFiles(); ++i) {
-    fname = dir;
-    fname += "/";
-    fname += files.GetFile(i);
+    fname = cmStrCat(dir, '/', files.GetFile(i));
 
     if (!cmSystemTools::FileIsDirectory(fname)) {
       // Hold this file hostage until it behaves.
@@ -1545,9 +1515,7 @@ bool cmFindPackageCommand::FindConfigFile(std::string const& dir,
   }
 
   for (std::string const& c : this->Configs) {
-    file = dir;
-    file += "/";
-    file += c;
+    file = cmStrCat(dir, '/', c);
     if (this->DebugMode) {
       fprintf(stderr, "Checking file [%s]\n", file.c_str());
     }
@@ -1573,16 +1541,14 @@ bool cmFindPackageCommand::CheckVersion(std::string const& config_file)
   std::string version_file_base = config_file.substr(0, pos);
 
   // Look for foo-config-version.cmake
-  std::string version_file = version_file_base;
-  version_file += "-version.cmake";
+  std::string version_file = cmStrCat(version_file_base, "-version.cmake");
   if (!haveResult && cmSystemTools::FileExists(version_file, true)) {
     result = this->CheckVersionFile(version_file, version);
     haveResult = true;
   }
 
   // Look for fooConfigVersion.cmake
-  version_file = version_file_base;
-  version_file += "Version.cmake";
+  version_file = cmStrCat(version_file_base, "Version.cmake");
   if (!haveResult && cmSystemTools::FileExists(version_file, true)) {
     result = this->CheckVersionFile(version_file, version);
     haveResult = true;
@@ -1690,8 +1656,7 @@ bool cmFindPackageCommand::CheckVersionFile(std::string const& version_file,
 void cmFindPackageCommand::StoreVersionFound()
 {
   // Store the whole version string.
-  std::string ver = this->Name;
-  ver += "_VERSION";
+  std::string ver = cmStrCat(this->Name, "_VERSION");
   if (this->VersionFound.empty()) {
     this->Makefile->RemoveDefinition(ver);
   } else {
@@ -2039,8 +2004,7 @@ private:
   bool Search(std::string const& parent, cmFileList& lister) override
   {
     // Glob the set of matching files.
-    std::string expr = parent;
-    expr += this->Pattern;
+    std::string expr = cmStrCat(parent, this->Pattern);
     cmsys::Glob g;
     if (!g.FindFiles(expr)) {
       return false;
diff --git a/Source/cmFindPathCommand.cxx b/Source/cmFindPathCommand.cxx
index 38ff2ed..41f5e51 100644
--- a/Source/cmFindPathCommand.cxx
+++ b/Source/cmFindPathCommand.cxx
@@ -6,6 +6,7 @@
 
 #include "cmMakefile.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -88,12 +89,8 @@ std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file,
       frameWorkName.clear();
     }
     if (!frameWorkName.empty()) {
-      std::string fpath = dir;
-      fpath += frameWorkName;
-      fpath += ".framework";
-      std::string intPath = fpath;
-      intPath += "/Headers/";
-      intPath += fileName;
+      std::string fpath = cmStrCat(dir, frameWorkName, ".framework");
+      std::string intPath = cmStrCat(fpath, "/Headers/", fileName);
       if (cmSystemTools::FileExists(intPath)) {
         if (this->IncludeFileInPath) {
           return intPath;
@@ -104,9 +101,7 @@ std::string cmFindPathCommand::FindHeaderInFramework(std::string const& file,
   }
   // if it is not found yet or not a framework header, then do a glob search
   // for all frameworks in the directory: dir/*.framework/Headers/<file>
-  std::string glob = dir;
-  glob += "*.framework/Headers/";
-  glob += file;
+  std::string glob = cmStrCat(dir, "*.framework/Headers/", file);
   cmsys::Glob globIt;
   globIt.FindFiles(glob);
   std::vector<std::string> files = globIt.GetFiles();
@@ -126,8 +121,7 @@ std::string cmFindPathCommand::FindNormalHeader()
   std::string tryPath;
   for (std::string const& n : this->Names) {
     for (std::string const& sp : this->SearchPaths) {
-      tryPath = sp;
-      tryPath += n;
+      tryPath = cmStrCat(sp, n);
       if (cmSystemTools::FileExists(tryPath)) {
         if (this->IncludeFileInPath) {
           return tryPath;
diff --git a/Source/cmFindProgramCommand.cxx b/Source/cmFindProgramCommand.cxx
index 8fcf1ac..a2db65c 100644
--- a/Source/cmFindProgramCommand.cxx
+++ b/Source/cmFindProgramCommand.cxx
@@ -75,8 +75,7 @@ struct cmFindProgramHelper
       if (!ext.empty() && cmHasSuffix(name, ext)) {
         continue;
       }
-      this->TestNameExt = name;
-      this->TestNameExt += ext;
+      this->TestNameExt = cmStrCat(name, ext);
       this->TestPath =
         cmSystemTools::CollapseFullPath(this->TestNameExt, path);
 
diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx
index e8b1da8..ad377de 100644
--- a/Source/cmFortranParserImpl.cxx
+++ b/Source/cmFortranParserImpl.cxx
@@ -1,6 +1,8 @@
 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmFortranParser.h"
+
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <assert.h>
@@ -22,9 +24,7 @@ bool cmFortranParser_s::FindIncludeFile(const char* dir,
   }
   // Check for the file in the directory containing the including
   // file.
-  std::string fullName = dir;
-  fullName += "/";
-  fullName += includeName;
+  std::string fullName = cmStrCat(dir, '/', includeName);
   if (cmSystemTools::FileExists(fullName, true)) {
     fileName = fullName;
     return true;
@@ -32,9 +32,7 @@ bool cmFortranParser_s::FindIncludeFile(const char* dir,
 
   // Search the include path for the file.
   for (std::string const& i : this->IncludePath) {
-    fullName = i;
-    fullName += "/";
-    fullName += includeName;
+    fullName = cmStrCat(i, '/', includeName);
     if (cmSystemTools::FileExists(fullName, true)) {
       fileName = fullName;
       return true;
diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx
index f130e8d..e8f03d7 100644
--- a/Source/cmFunctionCommand.cxx
+++ b/Source/cmFunctionCommand.cxx
@@ -51,9 +51,9 @@ bool cmFunctionHelperCommand::operator()(
   // make sure the number of arguments passed is at least the number
   // required by the signature
   if (expandedArgs.size() < this->Args.size() - 1) {
-    std::string errorMsg =
-      "Function invoked with incorrect arguments for function named: ";
-    errorMsg += this->Args[0];
+    std::string errorMsg = cmStrCat(
+      "Function invoked with incorrect arguments for function named: ",
+      this->Args[0]);
     inStatus.SetError(errorMsg);
     return false;
   }
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index f181132..9a4e13e 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -909,8 +909,8 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
         // for this (possibly mapped) config.
         // Check if there is a proper config mapping for the tested config.
         std::vector<std::string> mappedConfigs;
-        std::string mapProp = "MAP_IMPORTED_CONFIG_";
-        mapProp += cmSystemTools::UpperCase(context->Config);
+        std::string mapProp = cmStrCat(
+          "MAP_IMPORTED_CONFIG_", cmSystemTools::UpperCase(context->Config));
         if (const char* mapValue =
               context->CurrentTarget->GetProperty(mapProp)) {
           cmExpandList(cmSystemTools::UpperCase(mapValue), mappedConfigs);
@@ -1695,9 +1695,8 @@ struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag>
                     "SHARED libraries.");
       return std::string();
     }
-    std::string result = target->GetDirectory(context->Config);
-    result += "/";
-    result += target->GetSOName(context->Config);
+    std::string result = cmStrCat(target->GetDirectory(context->Config), '/',
+                                  target->GetSOName(context->Config));
     return result;
   }
 };
@@ -1736,9 +1735,8 @@ struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag>
       return std::string();
     }
 
-    std::string result = target->GetPDBDirectory(context->Config);
-    result += "/";
-    result += target->GetPDBName(context->Config);
+    std::string result = cmStrCat(target->GetPDBDirectory(context->Config),
+                                  '/', target->GetPDBName(context->Config));
     return result;
   }
 };
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index e62b692..2e9a11a 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -39,6 +39,7 @@
 #include "cmTarget.h"
 #include "cmTargetLinkLibraryType.h"
 #include "cmTargetPropertyComputer.h"
+#include "cm_string_view.hxx"
 #include "cmake.h"
 
 class cmMessenger;
@@ -552,8 +553,8 @@ std::string cmGeneratorTarget::GetFilePostfix(const std::string& config) const
 {
   const char* postfix = nullptr;
   if (!config.empty()) {
-    std::string configProp = cmSystemTools::UpperCase(config);
-    configProp += "_POSTFIX";
+    std::string configProp =
+      cmStrCat(cmSystemTools::UpperCase(config), "_POSTFIX");
     postfix = this->GetProperty(configProp);
     // Mac application bundles and frameworks have no postfix.
     if (!this->IsImported() && postfix &&
@@ -793,9 +794,8 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature,
                                           const std::string& config) const
 {
   if (!config.empty()) {
-    std::string featureConfig = feature;
-    featureConfig += "_";
-    featureConfig += cmSystemTools::UpperCase(config);
+    std::string featureConfig =
+      cmStrCat(feature, '_', cmSystemTools::UpperCase(config));
     if (const char* value = this->GetProperty(featureConfig)) {
       return value;
     }
@@ -1703,8 +1703,7 @@ std::string cmGeneratorTarget::GetCompilePDBName(
 
   // Check for a per-configuration output directory target property.
   std::string configUpper = cmSystemTools::UpperCase(config);
-  std::string configProp = "COMPILE_PDB_NAME_";
-  configProp += configUpper;
+  std::string configProp = cmStrCat("COMPILE_PDB_NAME_", configUpper);
   const char* config_name = this->GetProperty(configProp);
   if (config_name && *config_name) {
     return prefix + config_name + ".pdb";
@@ -1776,9 +1775,8 @@ bool cmGeneratorTarget::NeedRelinkBeforeInstall(
   // Check for rpath support on this platform.
   std::string ll = this->GetLinkerLanguage(config);
   if (!ll.empty()) {
-    std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
-    flagVar += ll;
-    flagVar += "_FLAG";
+    std::string flagVar =
+      cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG");
     if (!this->Makefile->IsSet(flagVar)) {
       // There is no rpath support on this platform so nothing needs
       // relinking.
@@ -1856,9 +1854,8 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const
   // binaries.
   std::string ll = this->GetLinkerLanguage(config);
   if (!ll.empty()) {
-    std::string sepVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
-    sepVar += ll;
-    sepVar += "_FLAG_SEP";
+    std::string sepVar =
+      cmStrCat("CMAKE_SHARED_LIBRARY_RUNTIME_", ll, "_FLAG_SEP");
     const char* sep = this->Makefile->GetDefinition(sepVar);
     if (sep && *sep) {
       // TODO: Add ELF check to ABI detection and get rid of
@@ -2055,9 +2052,8 @@ bool shouldAddContentLevel(cmGeneratorTarget::BundleDirectoryLevel level)
 std::string cmGeneratorTarget::GetAppBundleDirectory(
   const std::string& config, BundleDirectoryLevel level) const
 {
-  std::string fpath =
-    this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact);
-  fpath += ".";
+  std::string fpath = cmStrCat(
+    this->GetFullName(config, cmStateEnums::RuntimeBinaryArtifact), '.');
   const char* ext = this->GetProperty("BUNDLE_EXTENSION");
   if (!ext) {
     ext = "app";
@@ -2082,9 +2078,8 @@ bool cmGeneratorTarget::IsBundleOnApple() const
 std::string cmGeneratorTarget::GetCFBundleDirectory(
   const std::string& config, BundleDirectoryLevel level) const
 {
-  std::string fpath;
-  fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact);
-  fpath += ".";
+  std::string fpath = cmStrCat(
+    this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.');
   const char* ext = this->GetProperty("BUNDLE_EXTENSION");
   if (!ext) {
     if (this->IsXCTestOnApple()) {
@@ -2107,9 +2102,8 @@ std::string cmGeneratorTarget::GetCFBundleDirectory(
 std::string cmGeneratorTarget::GetFrameworkDirectory(
   const std::string& config, BundleDirectoryLevel level) const
 {
-  std::string fpath;
-  fpath += this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact);
-  fpath += ".";
+  std::string fpath = cmStrCat(
+    this->GetOutputName(config, cmStateEnums::RuntimeBinaryArtifact), '.');
   const char* ext = this->GetProperty("BUNDLE_EXTENSION");
   if (!ext) {
     ext = "framework";
@@ -2166,8 +2160,7 @@ std::string cmGeneratorTarget::GetInstallNameDirForInstallTree() const
 
     if (this->CanGenerateInstallNameDir(INSTALL_NAME_FOR_INSTALL)) {
       if (install_name_dir && *install_name_dir) {
-        dir = install_name_dir;
-        dir += "/";
+        dir = cmStrCat(install_name_dir, '/');
       }
     }
     if (!install_name_dir) {
@@ -2208,8 +2201,7 @@ const std::string* cmGeneratorTarget::GetExportMacro() const
     if (const char* custom_export_name = this->GetProperty("DEFINE_SYMBOL")) {
       this->ExportMacro = custom_export_name;
     } else {
-      std::string in = this->GetName();
-      in += "_EXPORTS";
+      std::string in = cmStrCat(this->GetName(), "_EXPORTS");
       this->ExportMacro = cmSystemTools::MakeCidentifier(in);
     }
     return &this->ExportMacro;
@@ -2430,8 +2422,7 @@ std::string cmGeneratorTarget::GetMacContentDirectory(
   const std::string& config, cmStateEnums::ArtifactType artifact) const
 {
   // Start with the output directory for the target.
-  std::string fpath = this->GetDirectory(config, artifact);
-  fpath += "/";
+  std::string fpath = cmStrCat(this->GetDirectory(config, artifact), '/');
   BundleDirectoryLevel level = ContentLevel;
   if (this->IsFrameworkOnApple()) {
     // additional files with a framework go into the version specific
@@ -2467,10 +2458,9 @@ cmGeneratorTarget::CompileInfo const* cmGeneratorTarget::GetCompileInfo(
   }
 
   if (this->GetType() > cmStateEnums::OBJECT_LIBRARY) {
-    std::string msg = "cmTarget::GetCompileInfo called for ";
-    msg += this->GetName();
-    msg += " which has type ";
-    msg += cmState::GetTargetTypeName(this->GetType());
+    std::string msg = cmStrCat("cmTarget::GetCompileInfo called for ",
+                               this->GetName(), " which has type ",
+                               cmState::GetTargetTypeName(this->GetType()));
     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
     return nullptr;
   }
@@ -2898,8 +2888,8 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config,
 {
   const char* archs = nullptr;
   if (!config.empty()) {
-    std::string defVarName = "OSX_ARCHITECTURES_";
-    defVarName += cmSystemTools::UpperCase(config);
+    std::string defVarName =
+      cmStrCat("OSX_ARCHITECTURES_", cmSystemTools::UpperCase(config));
     archs = this->GetProperty(defVarName);
   }
   if (!archs) {
@@ -3694,33 +3684,25 @@ void cmGeneratorTarget::ComputeTargetManifest(const std::string& config) const
   // Add each name.
   std::string f;
   if (!targetNames.Output.empty()) {
-    f = dir;
-    f += "/";
-    f += targetNames.Output;
+    f = cmStrCat(dir, '/', targetNames.Output);
     gg->AddToManifest(f);
   }
   if (!targetNames.SharedObject.empty()) {
-    f = dir;
-    f += "/";
-    f += targetNames.SharedObject;
+    f = cmStrCat(dir, '/', targetNames.SharedObject);
     gg->AddToManifest(f);
   }
   if (!targetNames.Real.empty()) {
-    f = dir;
-    f += "/";
-    f += targetNames.Real;
+    f = cmStrCat(dir, '/', targetNames.Real);
     gg->AddToManifest(f);
   }
   if (!targetNames.PDB.empty()) {
-    f = dir;
-    f += "/";
-    f += targetNames.PDB;
+    f = cmStrCat(dir, '/', targetNames.PDB);
     gg->AddToManifest(f);
   }
   if (!targetNames.ImportLibrary.empty()) {
-    f = this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact);
-    f += "/";
-    f += targetNames.ImportLibrary;
+    f =
+      cmStrCat(this->GetDirectory(config, cmStateEnums::ImportLibraryArtifact),
+               '/', targetNames.ImportLibrary);
     gg->AddToManifest(f);
   }
 }
@@ -3760,11 +3742,10 @@ std::string cmGeneratorTarget::NormalGetFullPath(
   const std::string& config, cmStateEnums::ArtifactType artifact,
   bool realname) const
 {
-  std::string fpath = this->GetDirectory(config, artifact);
-  fpath += "/";
+  std::string fpath = cmStrCat(this->GetDirectory(config, artifact), '/');
   if (this->IsAppBundleOnApple()) {
-    fpath = this->BuildBundleDirectory(fpath, config, FullLevel);
-    fpath += "/";
+    fpath =
+      cmStrCat(this->BuildBundleDirectory(fpath, config, FullLevel), '/');
   }
 
   // Add the full name of the target.
@@ -3791,8 +3772,8 @@ std::string cmGeneratorTarget::NormalGetRealName(
   // TODO: Split cmTarget into a class hierarchy to get compile-time
   // enforcement of the limited imported target API.
   if (this->IsImported()) {
-    std::string msg = "NormalGetRealName called on imported target: ";
-    msg += this->GetName();
+    std::string msg = cmStrCat("NormalGetRealName called on imported target: ",
+                               this->GetName());
     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
   }
 
@@ -3813,8 +3794,8 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetLibraryNames(
   // TODO: Split cmTarget into a class hierarchy to get compile-time
   // enforcement of the limited imported target API.
   if (this->IsImported()) {
-    std::string msg = "GetLibraryNames called on imported target: ";
-    msg += this->GetName();
+    std::string msg =
+      cmStrCat("GetLibraryNames called on imported target: ", this->GetName());
     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
   }
 
@@ -3890,8 +3871,8 @@ cmGeneratorTarget::Names cmGeneratorTarget::GetExecutableNames(
   // TODO: Split cmTarget into a class hierarchy to get compile-time
   // enforcement of the limited imported target API.
   if (this->IsImported()) {
-    std::string msg = "GetExecutableNames called on imported target: ";
-    msg += this->GetName();
+    std::string msg = cmStrCat(
+      "GetExecutableNames called on imported target: ", this->GetName());
     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
   }
 
@@ -4012,15 +3993,14 @@ void cmGeneratorTarget::GetFullNameInternal(
   // frameworks have directory prefix but no suffix
   std::string fw_prefix;
   if (this->IsFrameworkOnApple()) {
-    fw_prefix = this->GetFrameworkDirectory(config, ContentLevel);
-    fw_prefix += "/";
+    fw_prefix =
+      cmStrCat(this->GetFrameworkDirectory(config, ContentLevel), '/');
     targetPrefix = fw_prefix.c_str();
     targetSuffix = nullptr;
   }
 
   if (this->IsCFBundleOnApple()) {
-    fw_prefix = this->GetCFBundleDirectory(config, FullLevel);
-    fw_prefix += "/";
+    fw_prefix = cmStrCat(this->GetCFBundleDirectory(config, FullLevel), '/');
     targetPrefix = fw_prefix.c_str();
     targetSuffix = nullptr;
   }
@@ -4376,8 +4356,8 @@ void checkPropertyConsistency(cmGeneratorTarget const* depender,
 
   std::vector<std::string> props;
   cmExpandList(prop, props);
-  std::string pdir = cmSystemTools::GetCMakeRoot();
-  pdir += "/Help/prop_tgt/";
+  std::string pdir =
+    cmStrCat(cmSystemTools::GetCMakeRoot(), "/Help/prop_tgt/");
 
   for (std::string const& p : props) {
     std::string pname = cmSystemTools::HelpFileName(p);
@@ -4523,8 +4503,8 @@ void cmGeneratorTarget::CheckPropertyCompatibility(
     }
     std::sort(props.begin(), props.end());
 
-    std::string propsString = cmJoin(cmMakeRange(props).retreat(1), ", ");
-    propsString += " and the " + props.back();
+    std::string propsString = cmStrCat(
+      cmJoin(cmMakeRange(props).retreat(1), ", "), " and the ", props.back());
 
     std::ostringstream e;
     e << "Property \"" << prop << "\" appears in both the " << propsString
@@ -4794,8 +4774,7 @@ PropertyType checkInterfacePropertyCompatibility(cmGeneratorTarget const* tgt,
   }
   bool propInitialized = explicitlySet;
 
-  std::string report = " * Target \"";
-  report += tgt->GetName();
+  std::string report = cmStrCat(" * Target \"", tgt->GetName());
   if (explicitlySet) {
     report += "\" has property content \"";
     report += valueAsString<PropertyType>(propContent);
@@ -5051,9 +5030,8 @@ std::string cmGeneratorTarget::CreateFortranModuleDirectory(
       mod_dir = target_mod_dir;
     } else {
       // Interpret relative to the current output directory.
-      mod_dir = this->LocalGenerator->GetCurrentBinaryDirectory();
-      mod_dir += "/";
-      mod_dir += target_mod_dir;
+      mod_dir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(),
+                         '/', target_mod_dir);
     }
 
     // Make sure the module output directory exists.
@@ -5116,12 +5094,9 @@ void cmGeneratorTarget::ReportPropertyOrigin(
     return;
   }
 
-  std::string areport = compatibilityType;
-  areport += std::string(" of property \"") + p + "\" for target \"";
-  areport += std::string(this->GetName());
-  areport += "\" (result: \"";
-  areport += result;
-  areport += "\"):\n" + report;
+  std::string areport =
+    cmStrCat(compatibilityType, " of property \"", p, "\" for target \"",
+             this->GetName(), "\" (result: \"", result, "\"):\n", report);
 
   this->LocalGenerator->GetCMakeInstance()->IssueMessage(MessageType::LOG,
                                                          areport);
@@ -5261,8 +5236,7 @@ void cmGeneratorTarget::ComputeLinkInterface(
 
     // How many repetitions are needed if this library has cyclic
     // dependencies?
-    std::string propName = "LINK_INTERFACE_MULTIPLICITY";
-    propName += suffix;
+    std::string propName = cmStrCat("LINK_INTERFACE_MULTIPLICITY", suffix);
     if (const char* config_reps = this->GetProperty(propName)) {
       sscanf(config_reps, "%u", &iface.Multiplicity);
     } else if (const char* reps =
@@ -5348,10 +5322,9 @@ cmGeneratorTarget::OutputInfo const* cmGeneratorTarget::GetOutputInfo(
 
   // Only libraries and executables have well-defined output files.
   if (!this->HaveWellDefinedOutputFiles()) {
-    std::string msg = "cmGeneratorTarget::GetOutputInfo called for ";
-    msg += this->GetName();
-    msg += " which has type ";
-    msg += cmState::GetTargetTypeName(this->GetType());
+    std::string msg = cmStrCat("cmGeneratorTarget::GetOutputInfo called for ",
+                               this->GetName(), " which has type ",
+                               cmState::GetTargetTypeName(this->GetType()));
     this->LocalGenerator->IssueMessage(MessageType::INTERNAL_ERROR, msg);
     return nullptr;
   }
@@ -5600,8 +5573,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries(
     // shared lib or executable.
 
     // Lookup the per-configuration property.
-    linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
-    linkIfaceProp += suffix;
+    linkIfaceProp = cmStrCat("LINK_INTERFACE_LIBRARIES", suffix);
     explicitLibraries = this->GetProperty(linkIfaceProp);
 
     // If not set, try the generic property.
@@ -5807,8 +5779,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
 
     if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
       if (!propertyLibs) {
-        linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
-        linkProp += suffix;
+        linkProp = cmStrCat("IMPORTED_LINK_INTERFACE_LIBRARIES", suffix);
         propertyLibs = this->GetProperty(linkProp);
       }
 
@@ -5836,8 +5807,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
   if (loc) {
     info.Location = loc;
   } else {
-    std::string impProp = "IMPORTED_LOCATION";
-    impProp += suffix;
+    std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix);
     if (const char* config_location = this->GetProperty(impProp)) {
       info.Location = config_location;
     } else if (const char* location = this->GetProperty("IMPORTED_LOCATION")) {
@@ -5847,8 +5817,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
 
   // Get the soname.
   if (this->GetType() == cmStateEnums::SHARED_LIBRARY) {
-    std::string soProp = "IMPORTED_SONAME";
-    soProp += suffix;
+    std::string soProp = cmStrCat("IMPORTED_SONAME", suffix);
     if (const char* config_soname = this->GetProperty(soProp)) {
       info.SOName = config_soname;
     } else if (const char* soname = this->GetProperty("IMPORTED_SONAME")) {
@@ -5858,8 +5827,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
 
   // Get the "no-soname" mark.
   if (this->GetType() == cmStateEnums::SHARED_LIBRARY) {
-    std::string soProp = "IMPORTED_NO_SONAME";
-    soProp += suffix;
+    std::string soProp = cmStrCat("IMPORTED_NO_SONAME", suffix);
     if (const char* config_no_soname = this->GetProperty(soProp)) {
       info.NoSOName = cmIsOn(config_no_soname);
     } else if (const char* no_soname =
@@ -5873,8 +5841,7 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
     info.ImportLibrary = imp;
   } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
              this->IsExecutableWithExports()) {
-    std::string impProp = "IMPORTED_IMPLIB";
-    impProp += suffix;
+    std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
     if (const char* config_implib = this->GetProperty(impProp)) {
       info.ImportLibrary = config_implib;
     } else if (const char* implib = this->GetProperty("IMPORTED_IMPLIB")) {
@@ -5884,8 +5851,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
 
   // Get the link dependencies.
   {
-    std::string linkProp = "IMPORTED_LINK_DEPENDENT_LIBRARIES";
-    linkProp += suffix;
+    std::string linkProp =
+      cmStrCat("IMPORTED_LINK_DEPENDENT_LIBRARIES", suffix);
     if (const char* config_libs = this->GetProperty(linkProp)) {
       info.SharedDeps = config_libs;
     } else if (const char* libs =
@@ -5896,8 +5863,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
 
   // Get the link languages.
   if (this->LinkLanguagePropagatesToDependents()) {
-    std::string linkProp = "IMPORTED_LINK_INTERFACE_LANGUAGES";
-    linkProp += suffix;
+    std::string linkProp =
+      cmStrCat("IMPORTED_LINK_INTERFACE_LANGUAGES", suffix);
     if (const char* config_libs = this->GetProperty(linkProp)) {
       info.Languages = config_libs;
     } else if (const char* libs =
@@ -5918,8 +5885,8 @@ void cmGeneratorTarget::ComputeImportInfo(std::string const& desired_config,
 
   // Get the cyclic repetition count.
   if (this->GetType() == cmStateEnums::STATIC_LIBRARY) {
-    std::string linkProp = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
-    linkProp += suffix;
+    std::string linkProp =
+      cmStrCat("IMPORTED_LINK_INTERFACE_MULTIPLICITY", suffix);
     if (const char* config_reps = this->GetProperty(linkProp)) {
       sscanf(config_reps, "%u", &info.Multiplicity);
     } else if (const char* reps =
@@ -6397,8 +6364,8 @@ bool cmGeneratorTarget::GetImplibGNUtoMS(std::string const& config,
 {
   if (this->HasImplibGNUtoMS(config) && gnuName.size() > 6 &&
       gnuName.substr(gnuName.size() - 6) == ".dll.a") {
-    out = gnuName.substr(0, gnuName.size() - 6);
-    out += newExt ? newExt : ".lib";
+    out = cmStrCat(cm::string_view(gnuName).substr(0, gnuName.size() - 6),
+                   newExt ? newExt : ".lib");
     return true;
   }
   return false;
@@ -6433,9 +6400,8 @@ bool cmGeneratorTarget::NeedImportLibraryName(std::string const& config) const
 
 std::string cmGeneratorTarget::GetSupportDirectory() const
 {
-  std::string dir = this->LocalGenerator->GetCurrentBinaryDirectory();
-  dir += "/CMakeFiles/";
-  dir += this->GetName();
+  std::string dir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(),
+                             "/CMakeFiles/", this->GetName());
 #if defined(__VMS)
   dir += "_dir";
 #else
diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx
index fa3d39c..d078a7a 100644
--- a/Source/cmGetDirectoryPropertyCommand.cxx
+++ b/Source/cmGetDirectoryPropertyCommand.cxx
@@ -7,6 +7,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmPolicies.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 namespace {
@@ -39,9 +40,7 @@ bool cmGetDirectoryPropertyCommand(std::vector<std::string> const& args,
     std::string sd = *i;
     // make sure the start dir is a full path
     if (!cmSystemTools::FileIsFullPath(sd)) {
-      sd = status.GetMakefile().GetCurrentSourceDirectory();
-      sd += "/";
-      sd += *i;
+      sd = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', *i);
     }
 
     // The local generators are associated with collapsed paths.
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index 2f720f0..e8e87e7 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -15,6 +15,7 @@
 #include "cmPropertyDefinition.h"
 #include "cmSourceFile.h"
 #include "cmState.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmTargetPropertyComputer.h"
@@ -261,9 +262,8 @@ bool HandleDirectoryMode(cmExecutionStatus& status, const std::string& name,
     // respect to the current directory.
     std::string dir = name;
     if (!cmSystemTools::FileIsFullPath(dir)) {
-      dir = status.GetMakefile().GetCurrentSourceDirectory();
-      dir += "/";
-      dir += name;
+      dir =
+        cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/', name);
     }
 
     // The local generators are associated with collapsed paths.
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index fc9ae01..26fc226 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -75,8 +75,8 @@ void cmGhsMultiTargetGenerator::Generate()
       break;
     }
     case cmStateEnums::SHARED_LIBRARY: {
-      std::string msg = "add_library(<name> SHARED ...) not supported: ";
-      msg += this->Name;
+      std::string msg =
+        cmStrCat("add_library(<name> SHARED ...) not supported: ", this->Name);
       cmSystemTools::Message(msg);
       return;
     }
@@ -87,8 +87,8 @@ void cmGhsMultiTargetGenerator::Generate()
       break;
     }
     case cmStateEnums::MODULE_LIBRARY: {
-      std::string msg = "add_library(<name> MODULE ...) not supported: ";
-      msg += this->Name;
+      std::string msg =
+        cmStrCat("add_library(<name> MODULE ...) not supported: ", this->Name);
       cmSystemTools::Message(msg);
       return;
     }
@@ -123,10 +123,9 @@ void cmGhsMultiTargetGenerator::Generate()
 void cmGhsMultiTargetGenerator::GenerateTarget()
 {
   // Open the target file in copy-if-different mode.
-  std::string fproj = this->LocalGenerator->GetCurrentBinaryDirectory();
-  fproj += "/";
-  fproj += this->Name;
-  fproj += cmGlobalGhsMultiGenerator::FILE_EXTENSION;
+  std::string fproj =
+    cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+             this->Name, cmGlobalGhsMultiGenerator::FILE_EXTENSION);
   cmGeneratedFileStream fout(fproj);
   fout.SetCopyIfDifferent(true);
 
@@ -347,12 +346,11 @@ void cmGhsMultiTargetGenerator::WriteBuildEventsHelper(
   for (cmCustomCommand const& cc : ccv) {
     cmCustomCommandGenerator ccg(cc, this->ConfigName, this->LocalGenerator);
     // Open the filestream for this custom command
-    std::string fname = this->LocalGenerator->GetCurrentBinaryDirectory();
-    fname +=
-      "/" + this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
-    fname += "/" + this->Name + "_" + name;
-    fname += std::to_string(cmdcount++);
-    fname += this->CmdWindowsShell ? ".bat" : ".sh";
+    std::string fname =
+      cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+               this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
+               '/', this->Name, '_', name, cmdcount++,
+               this->CmdWindowsShell ? ".bat" : ".sh");
     cmGeneratedFileStream f(fname);
     f.SetCopyIfDifferent(true);
     this->WriteCustomCommandsHelper(f, ccg);
@@ -395,8 +393,7 @@ void cmGhsMultiTargetGenerator::WriteCustomCommandsHelper(
   // Echo the custom command's comment text.
   const char* comment = ccg.GetComment();
   if (comment && *comment) {
-    std::string echocmd = "echo ";
-    echocmd += comment;
+    std::string echocmd = cmStrCat("echo ", comment);
     cmdLines.push_back(std::move(echocmd));
   }
 
@@ -569,14 +566,11 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
       // Open the filestream in copy-if-different mode.
       std::string gname = sg;
       cmsys::SystemTools::ReplaceString(gname, "\\", "_");
-      std::string lpath =
-        this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
-      lpath += "/";
-      lpath += gname;
-      lpath += cmGlobalGhsMultiGenerator::FILE_EXTENSION;
-      std::string fpath = this->LocalGenerator->GetCurrentBinaryDirectory();
-      fpath += "/";
-      fpath += lpath;
+      std::string lpath = cmStrCat(
+        this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), '/',
+        gname, cmGlobalGhsMultiGenerator::FILE_EXTENSION);
+      std::string fpath = cmStrCat(
+        this->LocalGenerator->GetCurrentBinaryDirectory(), '/', lpath);
       cmGeneratedFileStream* f = new cmGeneratedFileStream(fpath);
       f->SetCopyIfDifferent(true);
       gfiles.push_back(f);
@@ -668,14 +662,12 @@ void cmGhsMultiTargetGenerator::WriteSources(std::ostream& fout_proj)
                                        this->LocalGenerator);
 
           // Open the filestream for this custom command
-          std::string fname =
-            this->LocalGenerator->GetCurrentBinaryDirectory();
-          fname += "/" +
-            this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
-          fname += "/" + this->Name + "_cc";
-          fname += std::to_string(cmdcount++) + "_";
-          fname += (sf->GetLocation()).GetName();
-          fname += this->CmdWindowsShell ? ".bat" : ".sh";
+          std::string fname = cmStrCat(
+            this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+            this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
+            '/', this->Name, "_cc", cmdcount++, '_',
+            (sf->GetLocation()).GetName(),
+            this->CmdWindowsShell ? ".bat" : ".sh");
           cmGeneratedFileStream f(fname);
           f.SetCopyIfDifferent(true);
           this->WriteCustomCommandsHelper(f, ccg);
diff --git a/Source/cmGlobVerificationManager.cxx b/Source/cmGlobVerificationManager.cxx
index 9fb4170..72451b2 100644
--- a/Source/cmGlobVerificationManager.cxx
+++ b/Source/cmGlobVerificationManager.cxx
@@ -7,6 +7,7 @@
 
 #include "cmGeneratedFileStream.h"
 #include "cmListFileCache.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmVersion.h"
 
@@ -16,8 +17,7 @@ bool cmGlobVerificationManager::SaveVerificationScript(const std::string& path)
     return true;
   }
 
-  std::string scriptFile = path;
-  scriptFile += "/CMakeFiles";
+  std::string scriptFile = cmStrCat(path, "/CMakeFiles");
   std::string stampFile = scriptFile;
   cmSystemTools::MakeDirectory(scriptFile);
   scriptFile += "/VerifyGlobs.cmake";
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index c815fdb..e145ad4 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -205,9 +205,7 @@ void cmGlobalGenerator::ResolveLanguageCompiler(const std::string& lang,
                                                 cmMakefile* mf,
                                                 bool optional) const
 {
-  std::string langComp = "CMAKE_";
-  langComp += lang;
-  langComp += "_COMPILER";
+  std::string langComp = cmStrCat("CMAKE_", lang, "_COMPILER");
 
   if (!mf->GetDefinition(langComp)) {
     if (!optional) {
@@ -408,9 +406,7 @@ bool cmGlobalGenerator::FindMakeProgram(cmMakefile* mf)
     std::string saveFile = file;
     cmSystemTools::GetShortPath(makeProgram, makeProgram);
     cmSystemTools::SplitProgramPath(makeProgram, dir, file);
-    makeProgram = dir;
-    makeProgram += "/";
-    makeProgram += saveFile;
+    makeProgram = cmStrCat(dir, '/', saveFile);
     mf->AddCacheDefinition("CMAKE_MAKE_PROGRAM", makeProgram.c_str(),
                            "make program", cmStateEnums::FILEPATH);
   }
@@ -512,8 +508,8 @@ void cmGlobalGenerator::EnableLanguage(
   bool fatalError = false;
 
   mf->AddDefinitionBool("RUN_CONFIGURE", true);
-  std::string rootBin = this->CMakeInstance->GetHomeOutputDirectory();
-  rootBin += "/CMakeFiles";
+  std::string rootBin =
+    cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(), "/CMakeFiles");
 
   // If the configuration files path has been set,
   // then we are in a try compile and need to copy the enable language
@@ -592,8 +588,7 @@ void cmGlobalGenerator::EnableLanguage(
     mf->ReadListFile(systemFile);
     // load the CMakeSystem.cmake from the binary directory
     // this file is configured by the CMakeDetermineSystem.cmake file
-    fpath = rootBin;
-    fpath += "/CMakeSystem.cmake";
+    fpath = cmStrCat(rootBin, "/CMakeSystem.cmake");
     mf->ReadListFile(fpath);
   }
 
@@ -659,14 +654,9 @@ void cmGlobalGenerator::EnableLanguage(
       this->SetLanguageEnabled("NONE", mf);
       continue;
     }
-    std::string loadedLang = "CMAKE_";
-    loadedLang += lang;
-    loadedLang += "_COMPILER_LOADED";
+    std::string loadedLang = cmStrCat("CMAKE_", lang, "_COMPILER_LOADED");
     if (!mf->GetDefinition(loadedLang)) {
-      fpath = rootBin;
-      fpath += "/CMake";
-      fpath += lang;
-      fpath += "Compiler.cmake";
+      fpath = cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
 
       // If the existing build tree was already configured with this
       // version of CMake then try to load the configured file first
@@ -693,9 +683,8 @@ void cmGlobalGenerator::EnableLanguage(
       }
       // if the CMake(LANG)Compiler.cmake file was not found then
       // load CMakeDetermine(LANG)Compiler.cmake
-      std::string determineCompiler = "CMakeDetermine";
-      determineCompiler += lang;
-      determineCompiler += "Compiler.cmake";
+      std::string determineCompiler =
+        cmStrCat("CMakeDetermine", lang, "Compiler.cmake");
       std::string determineFile = mf->GetModulesFile(determineCompiler);
       if (!mf->ReadListFile(determineFile)) {
         cmSystemTools::Error("Could not find cmake module file: " +
@@ -711,27 +700,19 @@ void cmGlobalGenerator::EnableLanguage(
         // put ${CMake_(LANG)_COMPILER_ENV_VAR}=${CMAKE_(LANG)_COMPILER
         // into the environment, in case user scripts want to run
         // configure, or sub cmakes
-        std::string compilerName = "CMAKE_";
-        compilerName += lang;
-        compilerName += "_COMPILER";
-        std::string compilerEnv = "CMAKE_";
-        compilerEnv += lang;
-        compilerEnv += "_COMPILER_ENV_VAR";
+        std::string compilerName = cmStrCat("CMAKE_", lang, "_COMPILER");
+        std::string compilerEnv =
+          cmStrCat("CMAKE_", lang, "_COMPILER_ENV_VAR");
         const std::string& envVar = mf->GetRequiredDefinition(compilerEnv);
         const std::string& envVarValue =
           mf->GetRequiredDefinition(compilerName);
-        std::string env = envVar;
-        env += "=";
-        env += envVarValue;
+        std::string env = cmStrCat(envVar, '=', envVarValue);
         cmSystemTools::PutEnv(env);
       }
 
       // if determineLanguage was called then load the file it
       // configures CMake(LANG)Compiler.cmake
-      fpath = rootBin;
-      fpath += "/CMake";
-      fpath += lang;
-      fpath += "Compiler.cmake";
+      fpath = cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
       if (!mf->ReadListFile(fpath)) {
         cmSystemTools::Error("Could not find cmake module file: " + fpath);
       }
@@ -762,12 +743,8 @@ void cmGlobalGenerator::EnableLanguage(
     }
 
     // Check that the compiler was found.
-    std::string compilerName = "CMAKE_";
-    compilerName += lang;
-    compilerName += "_COMPILER";
-    std::string compilerEnv = "CMAKE_";
-    compilerEnv += lang;
-    compilerEnv += "_COMPILER_ENV_VAR";
+    std::string compilerName = cmStrCat("CMAKE_", lang, "_COMPILER");
+    std::string compilerEnv = cmStrCat("CMAKE_", lang, "_COMPILER_ENV_VAR");
     std::ostringstream noCompiler;
     const char* compilerFile = mf->GetDefinition(compilerName);
     if (!compilerFile || !*compilerFile || cmIsNOTFOUND(compilerFile)) {
@@ -801,10 +778,8 @@ void cmGlobalGenerator::EnableLanguage(
       if (!optional) {
         // The compiler was not found and it is not optional.  Remove
         // CMake(LANG)Compiler.cmake so we try again next time CMake runs.
-        std::string compilerLangFile = rootBin;
-        compilerLangFile += "/CMake";
-        compilerLangFile += lang;
-        compilerLangFile += "Compiler.cmake";
+        std::string compilerLangFile =
+          cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
         cmSystemTools::RemoveFile(compilerLangFile);
         if (!this->CMakeInstance->GetIsInTryCompile()) {
           this->PrintCompilerAdvice(noCompiler, lang,
@@ -815,13 +790,10 @@ void cmGlobalGenerator::EnableLanguage(
       }
     }
 
-    std::string langLoadedVar = "CMAKE_";
-    langLoadedVar += lang;
-    langLoadedVar += "_INFORMATION_LOADED";
+    std::string langLoadedVar =
+      cmStrCat("CMAKE_", lang, "_INFORMATION_LOADED");
     if (!mf->GetDefinition(langLoadedVar)) {
-      fpath = "CMake";
-      fpath += lang;
-      fpath += "Information.cmake";
+      fpath = cmStrCat("CMake", lang, "Information.cmake");
       std::string informationFile = mf->GetModulesFile(fpath);
       if (informationFile.empty()) {
         cmSystemTools::Error("Could not find cmake module file: " + fpath);
@@ -842,33 +814,27 @@ void cmGlobalGenerator::EnableLanguage(
     // If the language is untested then test it now with a try compile.
     if (needTestLanguage[lang]) {
       if (!this->CMakeInstance->GetIsInTryCompile()) {
-        std::string testLang = "CMakeTest";
-        testLang += lang;
-        testLang += "Compiler.cmake";
+        std::string testLang = cmStrCat("CMakeTest", lang, "Compiler.cmake");
         std::string ifpath = mf->GetModulesFile(testLang);
         if (!mf->ReadListFile(ifpath)) {
           cmSystemTools::Error("Could not find cmake module file: " +
                                testLang);
         }
-        std::string compilerWorks = "CMAKE_";
-        compilerWorks += lang;
-        compilerWorks += "_COMPILER_WORKS";
+        std::string compilerWorks =
+          cmStrCat("CMAKE_", lang, "_COMPILER_WORKS");
         // if the compiler did not work, then remove the
         // CMake(LANG)Compiler.cmake file so that it will get tested the
         // next time cmake is run
         if (!mf->IsOn(compilerWorks)) {
-          std::string compilerLangFile = rootBin;
-          compilerLangFile += "/CMake";
-          compilerLangFile += lang;
-          compilerLangFile += "Compiler.cmake";
+          std::string compilerLangFile =
+            cmStrCat(rootBin, "/CMake", lang, "Compiler.cmake");
           cmSystemTools::RemoveFile(compilerLangFile);
         }
       } // end if in try compile
     }   // end need test language
     // Store the shared library flags so that we can satisfy CMP0018
-    std::string sharedLibFlagsVar = "CMAKE_SHARED_LIBRARY_";
-    sharedLibFlagsVar += lang;
-    sharedLibFlagsVar += "_FLAGS";
+    std::string sharedLibFlagsVar =
+      cmStrCat("CMAKE_SHARED_LIBRARY_", lang, "_FLAGS");
     this->LanguageToOriginalSharedLibFlags[lang] =
       mf->GetSafeDefinition(sharedLibFlagsVar);
 
@@ -879,10 +845,9 @@ void cmGlobalGenerator::EnableLanguage(
   // Now load files that can override any settings on the platform or for
   // the project First load the project compatibility file if it is in
   // cmake
-  std::string projectCompatibility = cmSystemTools::GetCMakeRoot();
-  projectCompatibility += "/Modules/";
-  projectCompatibility += mf->GetSafeDefinition("PROJECT_NAME");
-  projectCompatibility += "Compatibility.cmake";
+  std::string projectCompatibility =
+    cmStrCat(cmSystemTools::GetCMakeRoot(), "/Modules/",
+             mf->GetSafeDefinition("PROJECT_NAME"), "Compatibility.cmake");
   if (cmSystemTools::FileExists(projectCompatibility)) {
     mf->ReadListFile(projectCompatibility);
   }
@@ -1118,8 +1083,8 @@ void cmGlobalGenerator::SetLanguageEnabledMaps(const std::string& l,
   }
 
   if (preference < 0) {
-    std::string msg = linkerPrefVar;
-    msg += " is negative, adjusting it to 0";
+    std::string msg =
+      cmStrCat(linkerPrefVar, " is negative, adjusting it to 0");
     cmSystemTools::Message(msg, "Warning");
     preference = 0;
   }
@@ -1274,9 +1239,8 @@ void cmGlobalGenerator::Configure()
       msg << "Configuring incomplete, errors occurred!";
       const char* logs[] = { "CMakeOutput.log", "CMakeError.log", nullptr };
       for (const char** log = logs; *log; ++log) {
-        std::string f = this->CMakeInstance->GetHomeOutputDirectory();
-        f += "/CMakeFiles/";
-        f += *log;
+        std::string f = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
+                                 "/CMakeFiles/", *log);
         if (cmSystemTools::FileExists(f)) {
           msg << "\nSee also \"" << f << "\".";
         }
@@ -1602,8 +1566,8 @@ void cmGlobalGenerator::FinalizeTargetCompileInfo()
         mf->GetConfigurations(configs);
 
         for (std::string const& c : configs) {
-          std::string defPropName = "COMPILE_DEFINITIONS_";
-          defPropName += cmSystemTools::UpperCase(c);
+          std::string defPropName =
+            cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(c));
           t->AppendProperty(defPropName, mf->GetProperty(defPropName));
         }
       }
@@ -1710,11 +1674,10 @@ void cmGlobalGenerator::CheckTargetProperties()
           if (state->GetCacheEntryPropertyAsBool(varName, "ADVANCED")) {
             varName += " (ADVANCED)";
           }
-          std::string text = notFoundMap[varName];
-          text += "\n    linked by target \"";
-          text += target.second.GetName();
-          text += "\" in directory ";
-          text += this->Makefiles[i]->GetCurrentSourceDirectory();
+          std::string text =
+            cmStrCat(notFoundMap[varName], "\n    linked by target \"",
+                     target.second.GetName(), "\" in directory ",
+                     this->Makefiles[i]->GetCurrentSourceDirectory());
           notFoundMap[varName] = text;
         }
       }
@@ -1736,9 +1699,10 @@ void cmGlobalGenerator::CheckTargetProperties()
           if (state->GetCacheEntryPropertyAsBool(varName, "ADVANCED")) {
             varName += " (ADVANCED)";
           }
-          std::string text = notFoundMap[varName];
-          text += "\n   used as include directory in directory ";
-          text += this->Makefiles[i]->GetCurrentSourceDirectory();
+          std::string text =
+            cmStrCat(notFoundMap[varName],
+                     "\n   used as include directory in directory ",
+                     this->Makefiles[i]->GetCurrentSourceDirectory());
           notFoundMap[varName] = text;
         }
       }
@@ -1837,8 +1801,8 @@ int cmGlobalGenerator::Build(
   output += "\n";
   if (workdir.Failed()) {
     cmSystemTools::SetRunCommandHideConsole(hideconsole);
-    std::string err = "Failed to change directory: ";
-    err += std::strerror(workdir.GetLastResult());
+    std::string err = cmStrCat("Failed to change directory: ",
+                               std::strerror(workdir.GetLastResult()));
     cmSystemTools::Error(err);
     output += err;
     output += "\n";
@@ -1943,8 +1907,8 @@ std::string cmGlobalGenerator::GenerateCMakeBuildCommand(
   const std::string& native, bool ignoreErrors)
 {
   std::string makeCommand = cmSystemTools::GetCMakeCommand();
-  makeCommand = cmSystemTools::ConvertToOutputPath(makeCommand);
-  makeCommand += " --build .";
+  makeCommand =
+    cmStrCat(cmSystemTools::ConvertToOutputPath(makeCommand), " --build .");
   if (!config.empty()) {
     makeCommand += " --config \"";
     makeCommand += config;
@@ -2047,8 +2011,8 @@ void cmGlobalGenerator::SetConfiguredFilesPath(cmGlobalGenerator* gen)
   if (!gen->ConfiguredFilesPath.empty()) {
     this->ConfiguredFilesPath = gen->ConfiguredFilesPath;
   } else {
-    this->ConfiguredFilesPath = gen->CMakeInstance->GetHomeOutputDirectory();
-    this->ConfiguredFilesPath += "/CMakeFiles";
+    this->ConfiguredFilesPath =
+      cmStrCat(gen->CMakeInstance->GetHomeOutputDirectory(), "/CMakeFiles");
   }
 }
 
@@ -2318,8 +2282,8 @@ void cmGlobalGenerator::AddGlobalTarget_Package(
   std::vector<GlobalTargetInfo>& targets)
 {
   cmMakefile* mf = this->Makefiles[0];
-  std::string configFile = mf->GetCurrentBinaryDirectory();
-  configFile += "/CPackConfig.cmake";
+  std::string configFile =
+    cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackConfig.cmake");
   if (!cmSystemTools::FileExists(configFile)) {
     return;
   }
@@ -2367,8 +2331,8 @@ void cmGlobalGenerator::AddGlobalTarget_PackageSource(
   }
 
   cmMakefile* mf = this->Makefiles[0];
-  std::string configFile = mf->GetCurrentBinaryDirectory();
-  configFile += "/CPackSourceConfig.cmake";
+  std::string configFile =
+    cmStrCat(mf->GetCurrentBinaryDirectory(), "/CPackSourceConfig.cmake");
   if (!cmSystemTools::FileExists(configFile)) {
     return;
   }
@@ -2647,8 +2611,7 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti,
 std::string cmGlobalGenerator::GenerateRuleFile(
   std::string const& output) const
 {
-  std::string ruleFile = output;
-  ruleFile += ".rule";
+  std::string ruleFile = cmStrCat(output, ".rule");
   const char* dir = this->GetCMakeCFGIntDir();
   if (dir && dir[0] == '$') {
     cmSystemTools::ReplaceString(ruleFile, dir, "/CMakeFiles");
@@ -2846,8 +2809,7 @@ void cmGlobalGenerator::CheckRuleHashes()
 {
 #if !defined(CMAKE_BOOTSTRAP)
   std::string home = this->GetCMakeInstance()->GetHomeOutputDirectory();
-  std::string pfile = home;
-  pfile += "/CMakeFiles/CMakeRuleHashes.txt";
+  std::string pfile = cmStrCat(home, "/CMakeFiles/CMakeRuleHashes.txt");
   this->CheckRuleHashes(pfile, home);
   this->WriteRuleHashes(pfile);
 #endif
@@ -2923,8 +2885,8 @@ void cmGlobalGenerator::WriteRuleHashes(std::string const& pfile)
 void cmGlobalGenerator::WriteSummary()
 {
   // Record all target directories in a central location.
-  std::string fname = this->CMakeInstance->GetHomeOutputDirectory();
-  fname += "/CMakeFiles/TargetDirectories.txt";
+  std::string fname = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
+                               "/CMakeFiles/TargetDirectories.txt");
   cmGeneratedFileStream fout(fname);
 
   for (cmLocalGenerator* lg : this->LocalGenerators) {
@@ -2942,8 +2904,7 @@ void cmGlobalGenerator::WriteSummary(cmGeneratorTarget* target)
 {
   // Place the labels file in a per-target support directory.
   std::string dir = target->GetSupportDirectory();
-  std::string file = dir;
-  file += "/Labels.txt";
+  std::string file = cmStrCat(dir, "/Labels.txt");
   std::string json_file = dir + "/Labels.json";
 
 #ifndef CMAKE_BOOTSTRAP
@@ -3111,8 +3072,8 @@ bool cmGlobalGenerator::GenerateCPackPropertiesFile()
   std::vector<std::string> configs;
   std::string config = mf->GetConfigurations(configs, false);
 
-  std::string path = this->CMakeInstance->GetHomeOutputDirectory();
-  path += "/CPackProperties.cmake";
+  std::string path = cmStrCat(this->CMakeInstance->GetHomeOutputDirectory(),
+                              "/CPackProperties.cmake");
 
   if (!cmSystemTools::FileExists(path) && installedFiles.empty()) {
     return true;
diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx
index 3397e95..25d678f 100644
--- a/Source/cmGlobalGhsMultiGenerator.cxx
+++ b/Source/cmGlobalGhsMultiGenerator.cxx
@@ -57,11 +57,9 @@ void cmGlobalGhsMultiGenerator::ComputeTargetObjectDirectory(
   cmGeneratorTarget* gt) const
 {
   // Compute full path to object file directory for this target.
-  std::string dir;
-  dir += gt->LocalGenerator->GetCurrentBinaryDirectory();
-  dir += "/";
-  dir += gt->LocalGenerator->GetTargetDirectory(gt);
-  dir += "/";
+  std::string dir =
+    cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+             gt->LocalGenerator->GetTargetDirectory(gt), '/');
   gt->ObjectDirectory = dir;
 }
 
@@ -78,10 +76,9 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
   }
   if (ts.empty()) {
     std::string message;
-    message =
-      "Green Hills MULTI: -T <toolset> not specified; defaulting to \"";
-    message += tsp;
-    message += "\"";
+    message = cmStrCat(
+      "Green Hills MULTI: -T <toolset> not specified; defaulting to \"", tsp,
+      '"');
     cmSystemTools::Message(message);
 
     /* store the full toolset for later use
@@ -99,12 +96,11 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorToolset(std::string const& ts,
 
   /* check if the toolset changed from last generate */
   if (prevTool != nullptr && (gbuild != prevTool)) {
-    std::string message = "toolset build tool: ";
-    message += gbuild;
-    message += "\nDoes not match the previously used build tool: ";
-    message += prevTool;
-    message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
-               "directory or choose a different binary directory.";
+    std::string message =
+      cmStrCat("toolset build tool: ", gbuild,
+               "\nDoes not match the previously used build tool: ", prevTool,
+               "\nEither remove the CMakeCache.txt file and CMakeFiles "
+               "directory or choose a different binary directory.");
     cmSystemTools::Error(message);
     return false;
   }
@@ -143,19 +139,17 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p,
   if (cmIsOff(osdir) && platform.find("integrity") != std::string::npos) {
     if (!this->CMakeInstance->GetIsInTryCompile()) {
       /* required OS location is not found */
-      std::string m =
-        "Green Hills MULTI: GHS_OS_DIR not specified; No OS found in \"";
-      m += mf->GetSafeDefinition("GHS_OS_ROOT");
-      m += "\"";
+      std::string m = cmStrCat(
+        "Green Hills MULTI: GHS_OS_DIR not specified; No OS found in \"",
+        mf->GetSafeDefinition("GHS_OS_ROOT"), '"');
       cmSystemTools::Message(m);
     }
     osdir = "GHS_OS_DIR-NOT-SPECIFIED";
   } else if (!this->CMakeInstance->GetIsInTryCompile() &&
              cmIsOff(this->OsDir) && !cmIsOff(osdir)) {
     /* OS location was updated by auto-selection */
-    std::string m = "Green Hills MULTI: GHS_OS_DIR not specified; found \"";
-    m += osdir;
-    m += "\"";
+    std::string m = cmStrCat(
+      "Green Hills MULTI: GHS_OS_DIR not specified; found \"", osdir, '"');
     cmSystemTools::Message(m);
   }
   this->OsDir = osdir;
@@ -169,10 +163,9 @@ bool cmGlobalGhsMultiGenerator::SetGeneratorPlatform(std::string const& p,
     mf->AddCacheDefinition("GHS_BSP_NAME", bspName.c_str(),
                            "Name of GHS target platform.",
                            cmStateEnums::STRING, true);
-    std::string m =
-      "Green Hills MULTI: GHS_BSP_NAME not specified; defaulting to \"";
-    m += bspName;
-    m += "\"";
+    std::string m = cmStrCat(
+      "Green Hills MULTI: GHS_BSP_NAME not specified; defaulting to \"",
+      bspName, '"');
     cmSystemTools::Message(m);
   }
 
@@ -403,8 +396,8 @@ void cmGlobalGhsMultiGenerator::WriteProjectLine(
 
 void cmGlobalGhsMultiGenerator::WriteTargets(cmLocalGenerator* root)
 {
-  std::string rootBinaryDir = root->GetCurrentBinaryDirectory();
-  rootBinaryDir += "/CMakeFiles";
+  std::string rootBinaryDir =
+    cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeFiles");
 
   // All known targets
   for (cmGeneratorTarget const* target : this->ProjectTargets) {
@@ -479,8 +472,8 @@ void cmGlobalGhsMultiGenerator::WriteAllTarget(
     cmSystemTools::Error(message);
   } else {
     // determine the targets for ALL target
-    std::string rootBinaryDir = root->GetCurrentBinaryDirectory();
-    rootBinaryDir += "/CMakeFiles";
+    std::string rootBinaryDir =
+      cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeFiles");
     for (cmGeneratorTarget const* target : build) {
       if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY ||
           target->GetType() == cmStateEnums::MODULE_LIBRARY ||
@@ -538,11 +531,8 @@ void cmGlobalGhsMultiGenerator::OutputTopLevelProject(
    * with target projects.  This avoid the issue where the project has
    * the same name as the executable target.
    */
-  fname = root->GetCurrentBinaryDirectory();
-  fname += "/";
-  fname += root->GetProjectName();
-  fname += ".top";
-  fname += FILE_EXTENSION;
+  fname = cmStrCat(root->GetCurrentBinaryDirectory(), '/',
+                   root->GetProjectName(), ".top", FILE_EXTENSION);
 
   cmGeneratedFileStream top(fname);
   top.SetCopyIfDifferent(true);
@@ -643,10 +633,7 @@ void cmGlobalGhsMultiGenerator::WriteHighLevelDirectives(
       this->GetCMakeInstance()->GetCacheDefinition("CMAKE_GENERATOR_PLATFORM");
     const char* p =
       this->GetCMakeInstance()->GetCacheDefinition("GHS_TARGET_PLATFORM");
-    tgt = (a ? a : "");
-    tgt += "_";
-    tgt += (p ? p : "");
-    tgt += ".tgt";
+    tgt = cmStrCat((a ? a : ""), '_', (p ? p : ""), ".tgt");
   }
 
   fout << "primaryTarget=" << tgt << std::endl;
diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx
index 483d4ab..ae9d5a7 100644
--- a/Source/cmGlobalMSYSMakefileGenerator.cxx
+++ b/Source/cmGlobalMSYSMakefileGenerator.cxx
@@ -24,8 +24,7 @@ cmGlobalMSYSMakefileGenerator::cmGlobalMSYSMakefileGenerator(cmake* cm)
 std::string cmGlobalMSYSMakefileGenerator::FindMinGW(
   std::string const& makeloc)
 {
-  std::string fstab = makeloc;
-  fstab += "/../etc/fstab";
+  std::string fstab = cmStrCat(makeloc, "/../etc/fstab");
   cmsys::ifstream fin(fstab.c_str());
   std::string path;
   std::string mount;
@@ -34,8 +33,7 @@ std::string cmGlobalMSYSMakefileGenerator::FindMinGW(
     fin >> path;
     fin >> mount;
     if (mount == "/mingw") {
-      mingwBin = path;
-      mingwBin += "/bin";
+      mingwBin = cmStrCat(path, "/bin");
     }
   }
   return mingwBin;
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index a457911..062eccb 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -704,11 +704,9 @@ void cmGlobalNinjaGenerator::ComputeTargetObjectDirectory(
   cmGeneratorTarget* gt) const
 {
   // Compute full path to object file directory for this target.
-  std::string dir;
-  dir += gt->LocalGenerator->GetCurrentBinaryDirectory();
-  dir += "/";
-  dir += gt->LocalGenerator->GetTargetDirectory(gt);
-  dir += "/";
+  std::string dir =
+    cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+             gt->LocalGenerator->GetTargetDirectory(gt), '/');
   gt->ObjectDirectory = dir;
 }
 
@@ -718,9 +716,8 @@ bool cmGlobalNinjaGenerator::OpenBuildFileStream()
 {
   // Compute Ninja's build file path.
   std::string buildFilePath =
-    this->GetCMakeInstance()->GetHomeOutputDirectory();
-  buildFilePath += "/";
-  buildFilePath += cmGlobalNinjaGenerator::NINJA_BUILD_FILE;
+    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/',
+             cmGlobalNinjaGenerator::NINJA_BUILD_FILE);
 
   // Get a stream where to generate things.
   if (!this->BuildFileStream) {
@@ -757,9 +754,8 @@ bool cmGlobalNinjaGenerator::OpenRulesFileStream()
 {
   // Compute Ninja's build file path.
   std::string rulesFilePath =
-    this->GetCMakeInstance()->GetHomeOutputDirectory();
-  rulesFilePath += "/";
-  rulesFilePath += cmGlobalNinjaGenerator::NINJA_RULES_FILE;
+    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), '/',
+             cmGlobalNinjaGenerator::NINJA_RULES_FILE);
 
   // Get a stream where to generate things.
   if (!this->RulesFileStream) {
@@ -1314,13 +1310,13 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
 
   {
     cmNinjaRule rule("RERUN_CMAKE");
-    rule.Command = CMakeCmd();
-    rule.Command += " -S";
-    rule.Command += lg->ConvertToOutputFormat(lg->GetSourceDirectory(),
-                                              cmOutputConverter::SHELL);
-    rule.Command += " -B";
-    rule.Command += lg->ConvertToOutputFormat(lg->GetBinaryDirectory(),
-                                              cmOutputConverter::SHELL);
+    rule.Command =
+      cmStrCat(CMakeCmd(), " -S",
+               lg->ConvertToOutputFormat(lg->GetSourceDirectory(),
+                                         cmOutputConverter::SHELL),
+               " -B",
+               lg->ConvertToOutputFormat(lg->GetBinaryDirectory(),
+                                         cmOutputConverter::SHELL));
     rule.Description = "Re-running CMake...";
     rule.Comment = "Rule for re-running cmake.";
     rule.Generator = true;
@@ -1348,10 +1344,10 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os)
   if (this->SupportsManifestRestat() && cm->DoWriteGlobVerifyTarget()) {
     {
       cmNinjaRule rule("VERIFY_GLOBS");
-      rule.Command = CMakeCmd();
-      rule.Command += " -P ";
-      rule.Command += lg->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
-                                                cmOutputConverter::SHELL);
+      rule.Command =
+        cmStrCat(CMakeCmd(), " -P ",
+                 lg->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
+                                           cmOutputConverter::SHELL));
       rule.Description = "Re-checking globbed directories...";
       rule.Comment = "Rule for re-checking globbed directories.";
       rule.Generator = true;
@@ -1457,9 +1453,8 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
 {
   cmLocalGenerator* lgr = this->LocalGenerators.at(0);
   std::string cleanScriptRel = "CMakeFiles/clean_additional.cmake";
-  std::string cleanScriptAbs = lgr->GetBinaryDirectory();
-  cleanScriptAbs += '/';
-  cleanScriptAbs += cleanScriptRel;
+  std::string cleanScriptAbs =
+    cmStrCat(lgr->GetBinaryDirectory(), '/', cleanScriptRel);
 
   // Check if there are additional files to clean
   if (this->AdditionalCleanFiles.empty()) {
@@ -1489,10 +1484,10 @@ bool cmGlobalNinjaGenerator::WriteTargetCleanAdditional(std::ostream& os)
   // Write rule
   {
     cmNinjaRule rule("CLEAN_ADDITIONAL");
-    rule.Command = CMakeCmd();
-    rule.Command += " -P ";
-    rule.Command += lgr->ConvertToOutputFormat(
-      this->NinjaOutputPath(cleanScriptRel), cmOutputConverter::SHELL);
+    rule.Command = cmStrCat(
+      CMakeCmd(), " -P ",
+      lgr->ConvertToOutputFormat(this->NinjaOutputPath(cleanScriptRel),
+                                 cmOutputConverter::SHELL));
     rule.Description = "Cleaning additional files...";
     rule.Comment = "Rule for cleaning additional files.";
     WriteRule(*this->RulesFileStream, rule);
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index d311c1e..22c304e 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -108,11 +108,9 @@ void cmGlobalUnixMakefileGenerator3::ComputeTargetObjectDirectory(
   cmGeneratorTarget* gt) const
 {
   // Compute full path to object file directory for this target.
-  std::string dir;
-  dir += gt->LocalGenerator->GetCurrentBinaryDirectory();
-  dir += "/";
-  dir += gt->LocalGenerator->GetTargetDirectory(gt);
-  dir += "/";
+  std::string dir =
+    cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+             gt->LocalGenerator->GetTargetDirectory(gt), '/');
   gt->ObjectDirectory = dir;
 }
 
@@ -147,8 +145,8 @@ void cmGlobalUnixMakefileGenerator3::Generate()
     pmi.second.WriteProgressVariables(total, current);
   }
   for (cmLocalGenerator* lg : this->LocalGenerators) {
-    std::string markFileName = lg->GetCurrentBinaryDirectory();
-    markFileName += "/CMakeFiles/progress.marks";
+    std::string markFileName =
+      cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles/progress.marks");
     cmGeneratedFileStream markFile(markFileName);
     markFile << this->CountProgressMarksInAll(lg) << "\n";
   }
@@ -196,8 +194,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
   // because the check-build-system step compares the makefile time to
   // see if the build system must be regenerated.
   std::string makefileName =
-    this->GetCMakeInstance()->GetHomeOutputDirectory();
-  makefileName += "/CMakeFiles/Makefile2";
+    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
+             "/CMakeFiles/Makefile2");
   cmGeneratedFileStream makefileStream(makefileName, false,
                                        this->GetMakefileEncoding());
   if (!makefileStream) {
@@ -255,16 +253,15 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
   // because the check-build-system step compares the makefile time to
   // see if the build system must be regenerated.
   std::string cmakefileName =
-    this->GetCMakeInstance()->GetHomeOutputDirectory();
-  cmakefileName += "/CMakeFiles/Makefile.cmake";
+    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
+             "/CMakeFiles/Makefile.cmake");
   cmGeneratedFileStream cmakefileStream(cmakefileName);
   if (!cmakefileStream) {
     return;
   }
 
   std::string makefileName =
-    this->GetCMakeInstance()->GetHomeOutputDirectory();
-  makefileName += "/Makefile";
+    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(), "/Makefile");
 
   // get a local generator for some useful methods
   cmLocalUnixMakefileGenerator3* lg =
@@ -316,8 +313,9 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
   cmakefileStream << "  )\n\n";
 
   // Build the path to the cache check file.
-  std::string check = this->GetCMakeInstance()->GetHomeOutputDirectory();
-  check += "/CMakeFiles/cmake.check_cache";
+  std::string check =
+    cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
+             "/CMakeFiles/cmake.check_cache");
 
   // Set the corresponding makefile in the cmake file.
   cmakefileStream << "# The corresponding makefile is:\n"
@@ -347,8 +345,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
     std::string tmpStr;
     for (cmLocalGenerator* localGen : this->LocalGenerators) {
       lg = static_cast<cmLocalUnixMakefileGenerator3*>(localGen);
-      tmpStr = lg->GetCurrentBinaryDirectory();
-      tmpStr += "/CMakeFiles/CMakeDirectoryInformation.cmake";
+      tmpStr = cmStrCat(lg->GetCurrentBinaryDirectory(),
+                        "/CMakeFiles/CMakeDirectoryInformation.cmake");
       cmakefileStream << "  \""
                       << lg->MaybeConvertToRelativePath(binDir, tmpStr)
                       << "\"\n";
@@ -380,8 +378,8 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefileLanguageRules(
           (tgt->GetType() == cmStateEnums::OBJECT_LIBRARY) ||
           (tgt->GetType() == cmStateEnums::UTILITY)) {
         cmGeneratorTarget* gt = tgt;
-        std::string tname = lg->GetRelativeTargetDirectory(gt);
-        tname += "/DependInfo.cmake";
+        std::string tname =
+          cmStrCat(lg->GetRelativeTargetDirectory(gt), "/DependInfo.cmake");
         cmSystemTools::ConvertToUnixSlashes(tname);
         cmakefileStream << "  \"" << tname << "\"\n";
       }
@@ -396,9 +394,8 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
   std::vector<std::string> const& commands)
 {
   // Get the relative path to the subdirectory from the top.
-  std::string makeTarget = lg->GetCurrentBinaryDirectory();
-  makeTarget += '/';
-  makeTarget += pass;
+  std::string makeTarget =
+    cmStrCat(lg->GetCurrentBinaryDirectory(), '/', pass);
 
   // The directory-level rule should depend on the target-level rules
   // for all targets in the directory.
@@ -415,9 +412,8 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
       if ((!check_all || !gtarget->GetPropertyAsBool("EXCLUDE_FROM_ALL")) &&
           (!check_relink ||
            gtarget->NeedRelinkBeforeInstall(lg->GetConfigName()))) {
-        std::string tname = lg->GetRelativeTargetDirectory(gtarget);
-        tname += "/";
-        tname += pass;
+        std::string tname =
+          cmStrCat(lg->GetRelativeTargetDirectory(gtarget), '/', pass);
         depends.push_back(std::move(tname));
       }
     }
@@ -426,9 +422,8 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
   // The directory-level rule should depend on the directory-level
   // rules of the subdirectories.
   for (cmStateSnapshot const& c : lg->GetStateSnapshot().GetChildren()) {
-    std::string subdir = c.GetDirectory().GetCurrentBinary();
-    subdir += '/';
-    subdir += pass;
+    std::string subdir =
+      cmStrCat(c.GetDirectory().GetCurrentBinary(), '/', pass);
     depends.push_back(std::move(subdir));
   }
 
@@ -441,13 +436,9 @@ void cmGlobalUnixMakefileGenerator3::WriteDirectoryRule2(
   // Write the rule.
   std::string doc;
   if (lg->IsRootMakefile()) {
-    doc = "The main recursive \"";
-    doc += pass;
-    doc += "\" target.";
+    doc = cmStrCat("The main recursive \"", pass, "\" target.");
   } else {
-    doc = "Recursive \"";
-    doc += pass;
-    doc += "\" directory target.";
+    doc = cmStrCat("Recursive \"", pass, "\" directory target.");
   }
   lg->WriteMakeRule(ruleFileStream, doc.c_str(), makeTarget, depends, commands,
                     true);
@@ -578,8 +569,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
 
         // Write the rule.
         commands.clear();
-        std::string tmp = "CMakeFiles/";
-        tmp += "Makefile2";
+        std::string tmp = "CMakeFiles/Makefile2";
         commands.push_back(lg->GetRecursiveMakeCall(tmp, name));
         depends.clear();
         if (regenerate) {
@@ -591,14 +581,11 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
         // Add a fast rule to build the target
         std::string localName = lg->GetRelativeTargetDirectory(gtarget);
         std::string makefileName;
-        makefileName = localName;
-        makefileName += "/build.make";
+        makefileName = cmStrCat(localName, "/build.make");
         depends.clear();
         commands.clear();
-        std::string makeTargetName = localName;
-        makeTargetName += "/build";
-        localName = name;
-        localName += "/fast";
+        std::string makeTargetName = cmStrCat(localName, "/build");
+        localName = cmStrCat(name, "/fast");
         commands.push_back(
           lg->GetRecursiveMakeCall(makefileName, makeTargetName));
         lg->WriteMakeRule(ruleFileStream, "fast build rule for target.",
@@ -607,10 +594,9 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules(
         // Add a local name for the rule to relink the target before
         // installation.
         if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) {
-          makeTargetName = lg->GetRelativeTargetDirectory(gtarget);
-          makeTargetName += "/preinstall";
-          localName = name;
-          localName += "/preinstall";
+          makeTargetName =
+            cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/preinstall");
+          localName = cmStrCat(name, "/preinstall");
           depends.clear();
           commands.clear();
           commands.push_back(
@@ -654,20 +640,17 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
       std::string makefileName;
       // Add a rule to build the target by name.
       localName = lg->GetRelativeTargetDirectory(gtarget);
-      makefileName = localName;
-      makefileName += "/build.make";
+      makefileName = cmStrCat(localName, "/build.make");
 
       lg->WriteDivider(ruleFileStream);
       ruleFileStream << "# Target rules for target " << localName << "\n\n";
 
       commands.clear();
-      makeTargetName = localName;
-      makeTargetName += "/depend";
+      makeTargetName = cmStrCat(localName, "/depend");
       commands.push_back(
         lg->GetRecursiveMakeCall(makefileName, makeTargetName));
 
-      makeTargetName = localName;
-      makeTargetName += "/build";
+      makeTargetName = cmStrCat(localName, "/build");
       commands.push_back(
         lg->GetRecursiveMakeCall(makefileName, makeTargetName));
 
@@ -676,8 +659,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
       depends.clear();
 
       cmLocalUnixMakefileGenerator3::EchoProgress progress;
-      progress.Dir = lg->GetBinaryDirectory();
-      progress.Dir += "/CMakeFiles";
+      progress.Dir = cmStrCat(lg->GetBinaryDirectory(), "/CMakeFiles");
       {
         std::ostringstream progressArg;
         const char* sep = "";
@@ -720,8 +702,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
         progCmd << " " << this->CountProgressMarksInTarget(gtarget, emitted);
         commands.push_back(progCmd.str());
       }
-      std::string tmp = "CMakeFiles/";
-      tmp += "Makefile2";
+      std::string tmp = "CMakeFiles/Makefile2";
       commands.push_back(lg->GetRecursiveMakeCall(tmp, localName));
       {
         std::ostringstream progCmd;
@@ -736,8 +717,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
       if (regenerate) {
         depends.emplace_back("cmake_check_build_system");
       }
-      localName = lg->GetRelativeTargetDirectory(gtarget);
-      localName += "/rule";
+      localName = cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/rule");
       lg->WriteMakeRule(ruleFileStream,
                         "Build rule for subdir invocation for target.",
                         localName, depends, commands, true);
@@ -751,8 +731,8 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
 
       // Add rules to prepare the target for installation.
       if (gtarget->NeedRelinkBeforeInstall(lg->GetConfigName())) {
-        localName = lg->GetRelativeTargetDirectory(gtarget);
-        localName += "/preinstall";
+        localName =
+          cmStrCat(lg->GetRelativeTargetDirectory(gtarget), "/preinstall");
         depends.clear();
         commands.clear();
         commands.push_back(lg->GetRecursiveMakeCall(makefileName, localName));
@@ -771,8 +751,7 @@ void cmGlobalUnixMakefileGenerator3::WriteConvenienceRules2(
 
       // add the clean rule
       localName = lg->GetRelativeTargetDirectory(gtarget);
-      makeTargetName = localName;
-      makeTargetName += "/clean";
+      makeTargetName = cmStrCat(localName, "/clean");
       depends.clear();
       commands.clear();
       commands.push_back(
@@ -891,9 +870,9 @@ void cmGlobalUnixMakefileGenerator3::AppendGlobalTargetDepends(
     }
     cmLocalUnixMakefileGenerator3* lg3 =
       static_cast<cmLocalUnixMakefileGenerator3*>(dep->GetLocalGenerator());
-    std::string tgtName =
-      lg3->GetRelativeTargetDirectory(const_cast<cmGeneratorTarget*>(dep));
-    tgtName += "/all";
+    std::string tgtName = cmStrCat(
+      lg3->GetRelativeTargetDirectory(const_cast<cmGeneratorTarget*>(dep)),
+      "/all");
     depends.push_back(tgtName);
   }
 }
@@ -936,8 +915,7 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule(
             (type == cmStateEnums::UTILITY)) {
           std::string const& name = target->GetName();
           if (emittedTargets.insert(name).second) {
-            path = "... ";
-            path += name;
+            path = cmStrCat("... ", name);
             lg->AppendEcho(commands, path);
           }
         }
@@ -945,8 +923,7 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule(
     }
   }
   for (std::string const& o : lg->GetLocalHelp()) {
-    path = "... ";
-    path += o;
+    path = cmStrCat("... ", o);
     lg->AppendEcho(commands, path);
   }
   lg->WriteMakeRule(ruleFileStream, "Help Target", "help", no_depends,
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 02d25fb..48b17c0 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -678,9 +678,9 @@ std::string cmGlobalVisualStudio10Generator::FindMSBuildCommand()
   std::string mskey;
 
   // Search in standard location.
-  mskey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\";
-  mskey += this->GetToolsVersion();
-  mskey += ";MSBuildToolsPath";
+  mskey = cmStrCat(
+    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\",
+    this->GetToolsVersion(), ";MSBuildToolsPath");
   if (cmSystemTools::ReadRegistryValue(mskey.c_str(), msbuild,
                                        cmSystemTools::KeyWOW64_32)) {
     cmSystemTools::ConvertToUnixSlashes(msbuild);
@@ -720,8 +720,8 @@ bool cmGlobalVisualStudio10Generator::FindVCTargetsPath(cmMakefile* mf)
     // In a try-compile we are given the outer CMakeFiles directory.
     wd = this->ConfiguredFilesPath;
   } else {
-    wd = this->GetCMakeInstance()->GetHomeOutputDirectory();
-    wd += "/CMakeFiles";
+    wd = cmStrCat(this->GetCMakeInstance()->GetHomeOutputDirectory(),
+                  "/CMakeFiles");
   }
   wd += "/";
   wd += cmVersion::GetCMakeVersion();
@@ -905,8 +905,7 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand(
   {
     std::string slnFile;
     if (!projectDir.empty()) {
-      slnFile = projectDir;
-      slnFile += "/";
+      slnFile = cmStrCat(projectDir, '/');
     }
     slnFile += projectName;
     slnFile += ".sln";
@@ -953,8 +952,7 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand(
       makeCommand.Add(std::string(projectName) + ".sln");
       makeCommand.Add("/t:Clean");
     } else {
-      std::string targetProject(tname);
-      targetProject += ".vcxproj";
+      std::string targetProject = cmStrCat(tname, ".vcxproj");
       if (targetProject.find('/') == std::string::npos) {
         // it might be in a subdir
         if (cmSlnProjectEntry const* proj = slnData.GetProjectByName(tname)) {
@@ -1037,13 +1035,12 @@ std::string cmGlobalVisualStudio10Generator::GenerateRuleFile(
 {
   // The VS 10 generator needs to create the .rule files on disk.
   // Hide them away under the CMakeFiles directory.
-  std::string ruleDir = this->GetCMakeInstance()->GetHomeOutputDirectory();
-  ruleDir += "/CMakeFiles/";
-  ruleDir += cmSystemTools::ComputeStringMD5(
-    cmSystemTools::GetFilenamePath(output).c_str());
-  std::string ruleFile = ruleDir + "/";
-  ruleFile += cmSystemTools::GetFilenameName(output);
-  ruleFile += ".rule";
+  std::string ruleDir = cmStrCat(
+    this->GetCMakeInstance()->GetHomeOutputDirectory(), "/CMakeFiles/",
+    cmSystemTools::ComputeStringMD5(
+      cmSystemTools::GetFilenamePath(output).c_str()));
+  std::string ruleFile =
+    cmStrCat(ruleDir, '/', cmSystemTools::GetFilenameName(output), ".rule");
   return ruleFile;
 }
 
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index e0d86ca..e8e9ece 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -145,10 +145,8 @@ void cmGlobalVisualStudio71Generator::WriteProjectDepends(
   for (std::string const& name : depends) {
     std::string guid = this->GetGUID(name);
     if (guid.empty()) {
-      std::string m = "Target: ";
-      m += target->GetName();
-      m += " depends on unknown target: ";
-      m += name;
+      std::string m = cmStrCat("Target: ", target->GetName(),
+                               " depends on unknown target: ", name);
       cmSystemTools::Error(m);
     }
     fout << "\t\t{" << guid << "} = {" << guid << "}\n";
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index 7136746..258e300 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -66,8 +66,9 @@ const std::string& cmGlobalVisualStudio7Generator::GetIntelProjectVersion()
     // Compute the version of the Intel plugin to the VS IDE.
     // If the key does not exist then use a default guess.
     std::string intelVersion;
-    std::string vskey = this->GetRegistryBase();
-    vskey += "\\Packages\\" CM_INTEL_PLUGIN_GUID ";ProductVersion";
+    std::string vskey =
+      cmStrCat(this->GetRegistryBase(),
+               "\\Packages\\" CM_INTEL_PLUGIN_GUID ";ProductVersion");
     cmSystemTools::ReadRegistryValue(vskey, intelVersion,
                                      cmSystemTools::KeyWOW64_32);
     unsigned int intelVersionNumber = ~0u;
@@ -153,8 +154,9 @@ std::string cmGlobalVisualStudio7Generator::FindDevEnvCommand()
   }
 
   // Search where VS15Preview places it.
-  vskey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7;";
-  vskey += this->GetIDEVersion();
+  vskey = cmStrCat(
+    "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\SxS\\VS7;",
+    this->GetIDEVersion());
   if (cmSystemTools::ReadRegistryValue(vskey.c_str(), vscmd,
                                        cmSystemTools::KeyWOW64_32)) {
     cmSystemTools::ConvertToUnixSlashes(vscmd);
@@ -294,10 +296,8 @@ void cmGlobalVisualStudio7Generator::OutputSLNFile(
     return;
   }
   this->CurrentProject = root->GetProjectName();
-  std::string fname = root->GetCurrentBinaryDirectory();
-  fname += "/";
-  fname += root->GetProjectName();
-  fname += ".sln";
+  std::string fname = cmStrCat(root->GetCurrentBinaryDirectory(), '/',
+                               root->GetProjectName(), ".sln");
   cmGeneratedFileStream fout(fname.c_str());
   fout.SetCopyIfDifferent(true);
   if (!fout) {
@@ -554,12 +554,10 @@ std::string cmGlobalVisualStudio7Generator::WriteUtilityDepend(
 {
   std::vector<std::string> configs;
   target->Target->GetMakefile()->GetConfigurations(configs);
-  std::string pname = target->GetName();
-  pname += "_UTILITY";
-  std::string fname = target->GetLocalGenerator()->GetCurrentBinaryDirectory();
-  fname += "/";
-  fname += pname;
-  fname += ".vcproj";
+  std::string pname = cmStrCat(target->GetName(), "_UTILITY");
+  std::string fname =
+    cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/',
+             pname, ".vcproj");
   cmGeneratedFileStream fout(fname.c_str());
   fout.SetCopyIfDifferent(true);
   std::string guid = this->GetGUID(pname.c_str());
@@ -616,9 +614,8 @@ std::string cmGlobalVisualStudio7Generator::GetGUID(std::string const& name)
     return std::string(storedGUID);
   }
   // Compute a GUID that is deterministic but unique to the build tree.
-  std::string input = this->CMakeInstance->GetState()->GetBinaryDirectory();
-  input += "|";
-  input += name;
+  std::string input =
+    cmStrCat(this->CMakeInstance->GetState()->GetBinaryDirectory(), '|', name);
 
   cmUuid uuidGenerator;
 
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index 20deafe..b0c065f 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -26,9 +26,9 @@ std::string cmGlobalVisualStudio8Generator::FindDevEnvCommand()
 {
   // First look for VCExpress.
   std::string vsxcmd;
-  std::string vsxkey = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\";
-  vsxkey += this->GetIDEVersion();
-  vsxkey += ";InstallDir";
+  std::string vsxkey =
+    cmStrCat("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\",
+             this->GetIDEVersion(), ";InstallDir");
   if (cmSystemTools::ReadRegistryValue(vsxkey.c_str(), vsxcmd,
                                        cmSystemTools::KeyWOW64_32)) {
     cmSystemTools::ConvertToUnixSlashes(vsxcmd);
@@ -116,20 +116,17 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
 
   // Create a list of all stamp files for this project.
   std::vector<std::string> stamps;
-  std::string stampList = "CMakeFiles/";
-  stampList += cmGlobalVisualStudio8Generator::GetGenerateStampList();
+  std::string stampList = cmStrCat(
+    "CMakeFiles/", cmGlobalVisualStudio8Generator::GetGenerateStampList());
   {
     std::string stampListFile =
-      generators[0]->GetMakefile()->GetCurrentBinaryDirectory();
-    stampListFile += "/";
-    stampListFile += stampList;
+      cmStrCat(generators[0]->GetMakefile()->GetCurrentBinaryDirectory(), '/',
+               stampList);
     std::string stampFile;
     cmGeneratedFileStream fout(stampListFile.c_str());
     for (cmLocalGenerator const* gi : generators) {
-      stampFile = gi->GetMakefile()->GetCurrentBinaryDirectory();
-      stampFile += "/";
-      stampFile += "CMakeFiles/";
-      stampFile += "generate.stamp";
+      stampFile = cmStrCat(gi->GetMakefile()->GetCurrentBinaryDirectory(),
+                           "/CMakeFiles/generate.stamp");
       fout << stampFile << "\n";
       stamps.push_back(stampFile);
     }
@@ -176,11 +173,9 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
     // Create a rule to re-run CMake.
     cmCustomCommandLine commandLine;
     commandLine.push_back(cmSystemTools::GetCMakeCommand());
-    std::string argS = "-S";
-    argS += lg->GetSourceDirectory();
+    std::string argS = cmStrCat("-S", lg->GetSourceDirectory());
     commandLine.push_back(argS);
-    std::string argB = "-B";
-    argB += lg->GetBinaryDirectory();
+    std::string argB = cmStrCat("-B", lg->GetBinaryDirectory());
     commandLine.push_back(argB);
     commandLine.push_back("--check-stamp-list");
     commandLine.push_back(stampList.c_str());
diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx
index 18cf922..bb6ad16 100644
--- a/Source/cmGlobalVisualStudioGenerator.cxx
+++ b/Source/cmGlobalVisualStudioGenerator.cxx
@@ -227,8 +227,8 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets()
 void cmGlobalVisualStudioGenerator::ComputeTargetObjectDirectory(
   cmGeneratorTarget* gt) const
 {
-  std::string dir = gt->LocalGenerator->GetCurrentBinaryDirectory();
-  dir += "/";
+  std::string dir =
+    cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(), '/');
   std::string tgtDir = gt->LocalGenerator->GetTargetDirectory(gt);
   if (!tgtDir.empty()) {
     dir += tgtDir;
@@ -261,8 +261,8 @@ void cmGlobalVisualStudioGenerator::ConfigureCMakeVisualStudioMacros()
   std::string dir = this->GetUserMacrosDirectory();
 
   if (!dir.empty()) {
-    std::string src = cmSystemTools::GetCMakeRoot();
-    src += "/Templates/" CMAKE_VSMACROS_FILENAME;
+    std::string src = cmStrCat(cmSystemTools::GetCMakeRoot(),
+                               "/Templates/" CMAKE_VSMACROS_FILENAME);
 
     std::string dst = dir + "/CMakeMacros/" CMAKE_VSMACROS_FILENAME;
 
@@ -309,10 +309,9 @@ void cmGlobalVisualStudioGenerator::CallVisualStudioMacro(
       if (vsSolutionFile) {
         topLevelSlnName = vsSolutionFile;
       } else {
-        topLevelSlnName = mf->GetCurrentBinaryDirectory();
-        topLevelSlnName += "/";
-        topLevelSlnName += this->LocalGenerators[0]->GetProjectName();
-        topLevelSlnName += ".sln";
+        topLevelSlnName =
+          cmStrCat(mf->GetCurrentBinaryDirectory(), '/',
+                   this->LocalGenerators[0]->GetProjectName(), ".sln");
       }
 
       if (m == MacroReload) {
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 8e0d0b5..a8f27d6 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -349,9 +349,7 @@ cmGlobalXCodeGenerator::GenerateBuildCommand(
 
   if (!projectName.empty()) {
     makeCommand.Add("-project");
-    std::string projectArg = projectName;
-    projectArg += ".xcode";
-    projectArg += "proj";
+    std::string projectArg = cmStrCat(projectName, ".xcodeproj");
     makeCommand.Add(projectArg);
   }
   if (cmContains(targetNames, "clean")) {
@@ -475,8 +473,8 @@ void cmGlobalXCodeGenerator::SetGenerationRoot(cmLocalGenerator* root)
     this->CurrentLocalGenerator->GetCurrentBinaryDirectory(),
     this->ProjectOutputDirectoryComponents);
 
-  this->CurrentXCodeHackMakefile = root->GetCurrentBinaryDirectory();
-  this->CurrentXCodeHackMakefile += "/CMakeScripts";
+  this->CurrentXCodeHackMakefile =
+    cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeScripts");
   cmSystemTools::MakeDirectory(this->CurrentXCodeHackMakefile);
   this->CurrentXCodeHackMakefile += "/XCODE_DEPEND_HELPER.make";
 }
@@ -486,8 +484,7 @@ std::string cmGlobalXCodeGenerator::PostBuildMakeTarget(
 {
   std::string target = tName;
   std::replace(target.begin(), target.end(), ' ', '_');
-  std::string out = "PostBuild." + target;
-  out += "." + configName;
+  std::string out = cmStrCat("PostBuild.", target, '.', configName);
   return out;
 }
 
@@ -595,8 +592,8 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile(
     lfiles.emplace_back(cm->GetGlobVerifyStamp());
   }
 
-  this->CurrentReRunCMakeMakefile = root->GetCurrentBinaryDirectory();
-  this->CurrentReRunCMakeMakefile += "/CMakeScripts";
+  this->CurrentReRunCMakeMakefile =
+    cmStrCat(root->GetCurrentBinaryDirectory(), "/CMakeScripts");
   cmSystemTools::MakeDirectory(this->CurrentReRunCMakeMakefile);
   this->CurrentReRunCMakeMakefile += "/ReRunCMake.make";
   cmGeneratedFileStream makefileStream(this->CurrentReRunCMakeMakefile);
@@ -614,10 +611,8 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile(
   }
   makefileStream << "\n";
 
-  std::string checkCache = root->GetBinaryDirectory();
-  checkCache += "/";
-  checkCache += "CMakeFiles/";
-  checkCache += "cmake.check_cache";
+  std::string checkCache =
+    cmStrCat(root->GetBinaryDirectory(), "/CMakeFiles/cmake.check_cache");
 
   if (cm->DoWriteGlobVerifyTarget()) {
     makefileStream << ".NOTPARALLEL:\n\n";
@@ -899,8 +894,8 @@ void cmGlobalXCodeGenerator::AddXCodeProjBuildRule(
   cmGeneratorTarget* target, std::vector<cmSourceFile*>& sources) const
 {
   std::string listfile =
-    target->GetLocalGenerator()->GetCurrentSourceDirectory();
-  listfile += "/CMakeLists.txt";
+    cmStrCat(target->GetLocalGenerator()->GetCurrentSourceDirectory(),
+             "/CMakeLists.txt");
   cmSourceFile* srcCMakeLists = target->Makefile->GetOrCreateSource(listfile);
   if (!cmContains(sources, srcCMakeLists)) {
     sources.push_back(srcCMakeLists);
@@ -1396,12 +1391,9 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt)
   // linker language.  This should convince Xcode to choose the proper
   // language.
   cmMakefile* mf = gtgt->Target->GetMakefile();
-  std::string fname = gtgt->GetLocalGenerator()->GetCurrentBinaryDirectory();
-  fname += "/CMakeFiles/";
-  fname += gtgt->GetName();
-  fname += "-CMakeForceLinker";
-  fname += ".";
-  fname += cmSystemTools::LowerCase(llang);
+  std::string fname = cmStrCat(
+    gtgt->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/CMakeFiles/",
+    gtgt->GetName(), "-CMakeForceLinker.", cmSystemTools::LowerCase(llang));
   {
     cmGeneratedFileStream fout(fname);
     fout << "\n";
@@ -1456,15 +1448,11 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
     cmd[0].push_back(cmSystemTools::GetCMakeCommand());
     cmd[0].push_back("-E");
     cmd[0].push_back("cmake_symlink_library");
-    std::string str_file = "$<TARGET_FILE:";
-    str_file += gtgt->GetName();
-    str_file += ">";
-    std::string str_so_file = "$<TARGET_SONAME_FILE:";
-    str_so_file += gtgt->GetName();
-    str_so_file += ">";
-    std::string str_link_file = "$<TARGET_LINKER_FILE:";
-    str_link_file += gtgt->GetName();
-    str_link_file += ">";
+    std::string str_file = cmStrCat("$<TARGET_FILE:", gtgt->GetName(), '>');
+    std::string str_so_file =
+      cmStrCat("$<TARGET_SONAME_FILE:", gtgt->GetName(), '>');
+    std::string str_link_file =
+      cmStrCat("$<TARGET_LINKER_FILE:", gtgt->GetName(), '>');
     cmd[0].push_back(str_file);
     cmd[0].push_back(str_so_file);
     cmd[0].push_back(str_link_file);
@@ -1631,15 +1619,11 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase(
   cmXCodeObject* buildphase, cmGeneratorTarget* target,
   std::vector<cmCustomCommand> const& commands, const char* name)
 {
-  std::string dir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory();
-  dir += "/CMakeScripts";
+  std::string dir = cmStrCat(
+    this->CurrentLocalGenerator->GetCurrentBinaryDirectory(), "/CMakeScripts");
   cmSystemTools::MakeDirectory(dir);
-  std::string makefile = dir;
-  makefile += "/";
-  makefile += target->GetName();
-  makefile += "_";
-  makefile += name;
-  makefile += ".make";
+  std::string makefile =
+    cmStrCat(dir, '/', target->GetName(), '_', name, ".make");
 
   for (const auto& currentConfig : this->CurrentConfigurationTypes) {
     this->CreateCustomRulesMakefile(makefile.c_str(), target, commands,
@@ -1648,12 +1632,10 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase(
 
   std::string cdir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory();
   cdir = this->ConvertToRelativeForMake(cdir);
-  std::string makecmd = "make -C ";
-  makecmd += cdir;
-  makecmd += " -f ";
-  makecmd += this->ConvertToRelativeForMake((makefile + "$CONFIGURATION"));
-  makecmd += " OBJDIR=$(basename \"$OBJECT_FILE_DIR_normal\")";
-  makecmd += " all";
+  std::string makecmd =
+    cmStrCat("make -C ", cdir, " -f ",
+             this->ConvertToRelativeForMake((makefile + "$CONFIGURATION")),
+             " OBJDIR=$(basename \"$OBJECT_FILE_DIR_normal\") all");
   buildphase->AddAttribute("shellScript", this->CreateString(makecmd));
   buildphase->AddAttribute("showEnvVarsInLog", this->CreateString("0"));
 }
@@ -1662,8 +1644,7 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
   const char* makefileBasename, cmGeneratorTarget* target,
   std::vector<cmCustomCommand> const& commands, const std::string& configName)
 {
-  std::string makefileName = makefileBasename;
-  makefileName += configName;
+  std::string makefileName = cmStrCat(makefileBasename, configName);
   cmGeneratedFileStream makefileStream(makefileName);
   if (!makefileStream) {
     return;
@@ -1726,9 +1707,10 @@ void cmGlobalXCodeGenerator::CreateCustomRulesMakefile(
       makefileStream << "\n";
 
       if (const char* comment = ccg.GetComment()) {
-        std::string echo_cmd = "echo ";
-        echo_cmd += (this->CurrentLocalGenerator->EscapeForShell(
-          comment, ccg.GetCC().GetEscapeAllowMakeVars()));
+        std::string echo_cmd =
+          cmStrCat("echo ",
+                   (this->CurrentLocalGenerator->EscapeForShell(
+                     comment, ccg.GetCC().GetEscapeAllowMakeVars())));
         makefileStream << "\t" << echo_cmd << "\n";
       }
 
@@ -1876,8 +1858,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
                                                targetLinkFlags);
     }
     if (!configName.empty()) {
-      std::string linkFlagsVar = "LINK_FLAGS_";
-      linkFlagsVar += cmSystemTools::UpperCase(configName);
+      std::string linkFlagsVar =
+        cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(configName));
       if (const char* linkFlags = gtgt->GetProperty(linkFlagsVar)) {
         this->CurrentLocalGenerator->AppendFlags(extraLinkOptions, linkFlags);
       }
@@ -2129,8 +2111,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
 
   for (auto& include : includes) {
     if (this->NameResolvesToFramework(include)) {
-      std::string frameworkDir = include;
-      frameworkDir += "/../";
+      std::string frameworkDir = cmStrCat(include, "/../");
       frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir);
       if (emitted.insert(frameworkDir).second) {
         std::string incpath = this->XCodeEscapePath(frameworkDir);
@@ -2483,11 +2464,9 @@ std::string cmGlobalXCodeGenerator::AddConfigurations(cmXCodeObject* target,
   cmXCodeObject* buildConfigurations =
     this->CreateObject(cmXCodeObject::OBJECT_LIST);
   configlist->AddAttribute("buildConfigurations", buildConfigurations);
-  std::string comment = "Build configuration list for ";
-  comment += cmXCodeObject::PBXTypeNames[target->GetIsA()];
-  comment += " \"";
-  comment += gtgt->GetName();
-  comment += "\"";
+  std::string comment = cmStrCat("Build configuration list for ",
+                                 cmXCodeObject::PBXTypeNames[target->GetIsA()],
+                                 " \"", gtgt->GetName(), '"');
   configlist->SetComment(comment);
   target->AddAttribute("buildConfigurationList",
                        this->CreateObjectReference(configlist));
@@ -2615,9 +2594,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeTarget(
   }
   std::string fullName;
   if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY) {
-    fullName = "lib";
-    fullName += gtgt->GetName();
-    fullName += ".a";
+    fullName = cmStrCat("lib", gtgt->GetName(), ".a");
   } else {
     fullName = gtgt->GetFullName(defConfig);
   }
@@ -2654,8 +2631,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(
 std::string cmGlobalXCodeGenerator::GetOrCreateId(const std::string& name,
                                                   const std::string& id)
 {
-  std::string guidStoreName = name;
-  guidStoreName += "_GUID_CMAKE";
+  std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE");
   const char* storedGUID =
     this->CMakeInstance->GetCacheDefinition(guidStoreName);
 
@@ -2710,9 +2686,7 @@ void cmGlobalXCodeGenerator::AppendOrAddBuildSetting(cmXCodeObject* settings,
     if (!attr) {
       settings->AddAttribute(attribute, this->CreateString(value));
     } else {
-      std::string oldValue = attr->GetString();
-      oldValue += " ";
-      oldValue += value;
+      std::string oldValue = cmStrCat(attr->GetString(), ' ', value);
       attr->SetString(oldValue);
     }
   }
@@ -2877,8 +2851,8 @@ bool cmGlobalXCodeGenerator::CreateGroups(
       // Add CMakeLists.txt file for user convenience.
       {
         std::string listfile =
-          gtgt->GetLocalGenerator()->GetCurrentSourceDirectory();
-        listfile += "/CMakeLists.txt";
+          cmStrCat(gtgt->GetLocalGenerator()->GetCurrentSourceDirectory(),
+                   "/CMakeLists.txt");
         cmSourceFile* sf = gtgt->Makefile->GetOrCreateSource(listfile);
         addSourceToGroup(sf->GetFullPath());
       }
@@ -2920,12 +2894,10 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup(
   std::string target;
   const std::string targetFolder = gtgt->GetEffectiveFolderName();
   if (!targetFolder.empty()) {
-    target = targetFolder;
-    target += "/";
+    target = cmStrCat(targetFolder, '/');
   }
   target += gtgt->GetName();
-  s = target + "/";
-  s += sg->GetFullName();
+  s = cmStrCat(target, '/', sg->GetFullName());
   std::map<std::string, cmXCodeObject*>::iterator it =
     this->GroupNameMap.find(s);
   if (it != this->GroupNameMap.end()) {
@@ -2969,8 +2941,7 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup(
 
   // It's a recursive folder structure, let's find the real parent group
   if (sg->GetFullName() != sg->GetName()) {
-    std::string curr_folder = target;
-    curr_folder += "/";
+    std::string curr_folder = cmStrCat(target, '/');
     for (auto const& folder : cmTokenize(sg->GetFullName(), "\\")) {
       curr_folder += folder;
       std::map<std::string, cmXCodeObject*>::iterator i_folder =
@@ -3035,8 +3006,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
   this->RootObject = this->CreateObject(cmXCodeObject::PBXProject);
   this->RootObject->SetComment("Project object");
 
-  std::string project_id = "PROJECT_";
-  project_id += root->GetProjectName();
+  std::string project_id = cmStrCat("PROJECT_", root->GetProjectName());
   this->RootObject->SetId(
     this->GetOrCreateId(project_id, this->RootObject->GetId()));
 
@@ -3087,10 +3057,8 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
   }
   configlist->AddAttribute("buildConfigurations", buildConfigurations);
 
-  std::string comment = "Build configuration list for PBXProject";
-  comment += " \"";
-  comment += this->CurrentProject;
-  comment += "\"";
+  std::string comment = cmStrCat("Build configuration list for PBXProject \"",
+                                 this->CurrentProject, '"');
   configlist->SetComment(comment);
   configlist->AddAttribute("defaultConfigurationIsVisible",
                            this->CreateString("0"));
@@ -3139,8 +3107,7 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects(
                                 this->CreateString(swiftVersion));
   }
 
-  std::string symroot = root->GetCurrentBinaryDirectory();
-  symroot += "/build";
+  std::string symroot = cmStrCat(root->GetCurrentBinaryDirectory(), "/build");
   buildSettings->AddAttribute("SYMROOT", this->CreateString(symroot));
 
   for (auto& config : configs) {
@@ -3197,15 +3164,9 @@ std::string cmGlobalXCodeGenerator::GetObjectsDirectory(
   const std::string& projName, const std::string& configName,
   const cmGeneratorTarget* t, const std::string& variant) const
 {
-  std::string dir = t->GetLocalGenerator()->GetCurrentBinaryDirectory();
-  dir += "/";
-  dir += projName;
-  dir += ".build/";
-  dir += configName;
-  dir += "/";
-  dir += t->GetName();
-  dir += ".build/";
-  dir += variant;
+  std::string dir = cmStrCat(
+    t->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/', projName,
+    ".build/", configName, '/', t->GetName(), ".build/", variant);
   return dir;
 }
 
@@ -3330,12 +3291,10 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
         for (auto objLib : objlibs) {
 
           const std::string objLibName = objLib->GetName();
-          std::string d =
+          std::string d = cmStrCat(
             this->GetObjectsDirectory(this->CurrentProject, configName, objLib,
-                                      OBJECT_LIBRARY_ARTIFACT_DIR);
-          d += "lib";
-          d += objLibName;
-          d += ".a";
+                                      OBJECT_LIBRARY_ARTIFACT_DIR),
+            "lib", objLibName, ".a");
 
           std::string dependency = this->ConvertToRelativeForMake(d);
           makefileStream << "\\\n\t" << dependency;
@@ -3352,10 +3311,8 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget(
           std::string universal = this->GetObjectsDirectory(
             this->CurrentProject, configName, gt, "$(OBJDIR)/");
           for (const auto& architecture : this->Architectures) {
-            std::string universalFile = universal;
-            universalFile += architecture;
-            universalFile += "/";
-            universalFile += gt->GetFullName(configName);
+            std::string universalFile = cmStrCat(universal, architecture, '/',
+                                                 gt->GetFullName(configName));
             makefileStream << "\t/bin/rm -f "
                            << this->ConvertToRelativeForMake(universalFile)
                            << "\n";
@@ -3383,10 +3340,8 @@ void cmGlobalXCodeGenerator::OutputXCodeProject(
   if (!this->CreateXCodeObjects(root, generators)) {
     return;
   }
-  std::string xcodeDir = root->GetCurrentBinaryDirectory();
-  xcodeDir += "/";
-  xcodeDir += root->GetProjectName();
-  xcodeDir += ".xcodeproj";
+  std::string xcodeDir = cmStrCat(root->GetCurrentBinaryDirectory(), '/',
+                                  root->GetProjectName(), ".xcodeproj");
   cmSystemTools::MakeDirectory(xcodeDir);
   std::string xcodeProjFile = xcodeDir + "/project.pbxproj";
   cmGeneratedFileStream fout(xcodeProjFile);
@@ -3460,12 +3415,12 @@ bool cmGlobalXCodeGenerator::OutputXCodeSharedSchemes(
 void cmGlobalXCodeGenerator::OutputXCodeWorkspaceSettings(
   const std::string& xcProjDir, bool hasGeneratedSchemes)
 {
-  std::string xcodeSharedDataDir = xcProjDir;
-  xcodeSharedDataDir += "/project.xcworkspace/xcshareddata";
+  std::string xcodeSharedDataDir =
+    cmStrCat(xcProjDir, "/project.xcworkspace/xcshareddata");
   cmSystemTools::MakeDirectory(xcodeSharedDataDir);
 
-  std::string workspaceSettingsFile = xcodeSharedDataDir;
-  workspaceSettingsFile += "/WorkspaceSettings.xcsettings";
+  std::string workspaceSettingsFile =
+    cmStrCat(xcodeSharedDataDir, "/WorkspaceSettings.xcsettings");
 
   cmGeneratedFileStream fout(workspaceSettingsFile);
   fout.SetCopyIfDifferent(true);
@@ -3571,9 +3526,7 @@ std::string cmGlobalXCodeGenerator::RelativeToBinary(const std::string& p)
 std::string cmGlobalXCodeGenerator::XCodeEscapePath(const std::string& p)
 {
   if (p.find(' ') != std::string::npos) {
-    std::string t = "\"";
-    t += p;
-    t += "\"";
+    std::string t = cmStrCat('"', p, '"');
     return t;
   }
   return p;
@@ -3595,9 +3548,7 @@ std::string cmGlobalXCodeGenerator::LookupFlags(
   const std::string& varNameSuffix, const std::string& default_flags)
 {
   if (!varNameLang.empty()) {
-    std::string varName = varNamePrefix;
-    varName += varNameLang;
-    varName += varNameSuffix;
+    std::string varName = cmStrCat(varNamePrefix, varNameLang, varNameSuffix);
     if (const char* varValue = this->CurrentMakefile->GetDefinition(varName)) {
       if (*varValue) {
         return varValue;
@@ -3632,8 +3583,7 @@ void cmGlobalXCodeGenerator::AppendDefines(
   std::string def;
   for (auto const& define : defines) {
     // Start with -D if requested.
-    def = dflag ? "-D" : "";
-    def += define;
+    def = cmStrCat(dflag ? "-D" : "", define);
 
     // Append the flag with needed escapes.
     std::string tmp;
@@ -3694,10 +3644,9 @@ void cmGlobalXCodeGenerator::AppendFlag(std::string& flags,
 std::string cmGlobalXCodeGenerator::ComputeInfoPListLocation(
   cmGeneratorTarget* target)
 {
-  std::string plist = target->GetLocalGenerator()->GetCurrentBinaryDirectory();
-  plist += "/CMakeFiles/";
-  plist += target->GetName();
-  plist += ".dir/Info.plist";
+  std::string plist =
+    cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(),
+             "/CMakeFiles/", target->GetName(), ".dir/Info.plist");
   return plist;
 }
 
@@ -3744,10 +3693,10 @@ void cmGlobalXCodeGenerator::ComputeTargetObjectDirectory(
   cmGeneratorTarget* gt) const
 {
   std::string configName = this->GetCMakeCFGIntDir();
-  std::string dir = this->GetObjectsDirectory(
-    "$(PROJECT_NAME)", configName, gt, "$(OBJECT_FILE_DIR_normal:base)/");
-  dir += this->ObjectDirArch;
-  dir += "/";
+  std::string dir =
+    cmStrCat(this->GetObjectsDirectory("$(PROJECT_NAME)", configName, gt,
+                                       "$(OBJECT_FILE_DIR_normal:base)/"),
+             this->ObjectDirArch, '/');
   gt->ObjectDirectory = dir;
 }
 
diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx
index cae8136..c5b5522 100644
--- a/Source/cmGraphVizWriter.cxx
+++ b/Source/cmGraphVizWriter.cxx
@@ -267,10 +267,8 @@ void cmGraphVizWriter::WriteTargetDependersFiles(const std::string& fileName)
       continue;
     }
 
-    std::string currentFilename = fileName;
-    currentFilename += ".";
-    currentFilename += ptr.first;
-    currentFilename += ".dependers";
+    std::string currentFilename =
+      cmStrCat(fileName, '.', ptr.first, ".dependers");
 
     cmGeneratedFileStream str(currentFilename);
     if (!str) {
@@ -312,9 +310,7 @@ void cmGraphVizWriter::WritePerTargetFiles(const std::string& fileName)
     std::set<std::string> insertedConnections;
     std::set<std::string> insertedNodes;
 
-    std::string currentFilename = fileName;
-    currentFilename += ".";
-    currentFilename += ptr.first;
+    std::string currentFilename = cmStrCat(fileName, '.', ptr.first);
     cmGeneratedFileStream str(currentFilename);
     if (!str) {
       return;
@@ -402,9 +398,7 @@ void cmGraphVizWriter::WriteConnections(
       continue;
     }
 
-    std::string connectionName = myNodeName;
-    connectionName += "-";
-    connectionName += libNameIt->second;
+    std::string connectionName = cmStrCat(myNodeName, '-', libNameIt->second);
     if (insertedConnections.find(connectionName) ==
         insertedConnections.end()) {
       insertedConnections.insert(connectionName);
@@ -464,9 +458,8 @@ void cmGraphVizWriter::WriteDependerConnections(
           this->TargetNamesNodes.find(tptr.first);
 
         if (dependerNodeNameIt != this->TargetNamesNodes.end()) {
-          std::string connectionName = dependerNodeNameIt->second;
-          connectionName += "-";
-          connectionName += myNodeName;
+          std::string connectionName =
+            cmStrCat(dependerNodeNameIt->second, '-', myNodeName);
 
           if (insertedConnections.find(connectionName) ==
               insertedConnections.end()) {
diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx
index 7b49ae7..f719041 100644
--- a/Source/cmIfCommand.cxx
+++ b/Source/cmIfCommand.cxx
@@ -14,6 +14,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmOutputConverter.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 
@@ -127,8 +128,8 @@ bool cmIfFunctionBlocker::Replay(std::vector<cmListFileFunction> functions,
           conditionEvaluator.IsTrue(expandedArguments, errorString, messType);
 
         if (!errorString.empty()) {
-          std::string err = cmIfCommandError(expandedArguments);
-          err += errorString;
+          std::string err =
+            cmStrCat(cmIfCommandError(expandedArguments), errorString);
           cmListFileBacktrace bt = mf.GetBacktrace(func);
           mf.GetCMakeInstance()->IssueMessage(messType, err, bt);
           if (messType == MessageType::FATAL_ERROR) {
@@ -184,8 +185,8 @@ bool cmIfCommand(std::vector<cmListFileArgument> const& args,
     conditionEvaluator.IsTrue(expandedArguments, errorString, status);
 
   if (!errorString.empty()) {
-    std::string err = "if " + cmIfCommandError(expandedArguments);
-    err += errorString;
+    std::string err =
+      cmStrCat("if ", cmIfCommandError(expandedArguments), errorString);
     if (status == MessageType::FATAL_ERROR) {
       makefile.IssueMessage(MessageType::FATAL_ERROR, err);
       cmSystemTools::SetFatalErrorOccured();
diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx
index 723b633..14264f4 100644
--- a/Source/cmIncludeCommand.cxx
+++ b/Source/cmIncludeCommand.cxx
@@ -9,6 +9,7 @@
 #include "cmMakefile.h"
 #include "cmMessageType.h"
 #include "cmPolicies.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 // cmIncludeCommand
@@ -49,8 +50,8 @@ bool cmIncludeCommand(std::vector<std::string> const& args,
     } else if (i > 1) // compat.: in previous cmake versions the second
                       // parameter was ignored if it wasn't "OPTIONAL"
     {
-      std::string errorText = "called with invalid argument: ";
-      errorText += args[i];
+      std::string errorText =
+        cmStrCat("called with invalid argument: ", args[i]);
       status.SetError(errorText);
       return false;
     }
@@ -65,8 +66,7 @@ bool cmIncludeCommand(std::vector<std::string> const& args,
 
   if (!cmSystemTools::FileIsFullPath(fname)) {
     // Not a path. Maybe module.
-    std::string module = fname;
-    module += ".cmake";
+    std::string module = cmStrCat(fname, ".cmake");
     std::string mfile = status.GetMakefile().GetModulesFile(module);
     if (!mfile.empty()) {
       fname = mfile;
@@ -130,9 +130,9 @@ bool cmIncludeCommand(std::vector<std::string> const& args,
   }
 
   if (!optional && !readit && !cmSystemTools::GetFatalErrorOccured()) {
-    std::string m = "could not find load file:\n"
-                    "  ";
-    m += fname;
+    std::string m = cmStrCat("could not find load file:\n"
+                             "  ",
+                             fname);
     status.SetError(m);
     return false;
   }
diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx
index eb10aa8..876bd95 100644
--- a/Source/cmIncludeDirectoryCommand.cxx
+++ b/Source/cmIncludeDirectoryCommand.cxx
@@ -122,9 +122,8 @@ void cmIncludeDirectoryCommand::NormalizeInclude(std::string& inc)
 
     if (!cmSystemTools::FileIsFullPath(inc)) {
       if (!cmGeneratorExpression::StartsWithGeneratorExpression(inc)) {
-        std::string tmp = this->Makefile->GetCurrentSourceDirectory();
-        tmp += "/";
-        tmp += inc;
+        std::string tmp =
+          cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', inc);
         inc = tmp;
       }
     }
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 51689a2..8b428a9 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -137,8 +137,7 @@ bool cmInstallCommand::InitialPass(std::vector<std::string> const& args,
   }
 
   // Unknown mode.
-  std::string e = "called with unknown mode ";
-  e += args[0];
+  std::string e = cmStrCat("called with unknown mode ", args[0]);
   this->SetError(e);
   return false;
 }
@@ -188,9 +187,8 @@ bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
       doing_script = false;
       std::string script = arg;
       if (!cmSystemTools::FileIsFullPath(script)) {
-        script = this->Makefile->GetCurrentSourceDirectory();
-        script += "/";
-        script += arg;
+        script =
+          cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', arg);
       }
       if (cmSystemTools::FileIsDirectory(script)) {
         this->SetError("given a directory as value of SCRIPT argument.");
@@ -1123,9 +1121,8 @@ bool cmInstallCommand::HandleDirectoryMode(
       std::string dir = args[i];
       std::string::size_type gpos = cmGeneratorExpression::Find(dir);
       if (gpos != 0 && !cmSystemTools::FileIsFullPath(dir)) {
-        dir = this->Makefile->GetCurrentSourceDirectory();
-        dir += "/";
-        dir += args[i];
+        dir =
+          cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', args[i]);
       }
 
       // Make sure the name is a directory.
@@ -1424,8 +1421,7 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
 
   // Construct the file name.
   if (fname.empty()) {
-    fname = exp;
-    fname += ".cmake";
+    fname = cmStrCat(exp, ".cmake");
 
     if (fname.find_first_of(":/\\") != std::string::npos) {
       std::ostringstream e;
@@ -1482,9 +1478,8 @@ bool cmInstallCommand::MakeFilesFullPath(
     std::string file = relFile;
     std::string::size_type gpos = cmGeneratorExpression::Find(file);
     if (gpos != 0 && !cmSystemTools::FileIsFullPath(file)) {
-      file = this->Makefile->GetCurrentSourceDirectory();
-      file += "/";
-      file += relFile;
+      file =
+        cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', relFile);
     }
 
     // Make sure the file is not a directory.
diff --git a/Source/cmInstallExportAndroidMKGenerator.cxx b/Source/cmInstallExportAndroidMKGenerator.cxx
index 55d3685..e8de029 100644
--- a/Source/cmInstallExportAndroidMKGenerator.cxx
+++ b/Source/cmInstallExportAndroidMKGenerator.cxx
@@ -53,9 +53,7 @@ void cmInstallExportAndroidMKGenerator::GenerateScript(std::ostream& os)
   cmSystemTools::MakeDirectory(this->TempDir.c_str());
 
   // Construct a temporary location for the file.
-  this->MainImportFile = this->TempDir;
-  this->MainImportFile += "/";
-  this->MainImportFile += this->FileName;
+  this->MainImportFile = cmStrCat(this->TempDir, '/', this->FileName);
 
   // Generate the import file for this export set.
   this->EFGen->SetExportFile(this->MainImportFile.c_str());
@@ -103,11 +101,10 @@ void cmInstallExportAndroidMKGenerator::GenerateScriptActions(
   std::ostream& os, Indent const& indent)
 {
   // Remove old per-configuration export files if the main changes.
-  std::string installedDir = "$ENV{DESTDIR}";
-  installedDir += this->ConvertToAbsoluteDestination(this->Destination);
-  installedDir += "/";
-  std::string installedFile = installedDir;
-  installedFile += this->FileName;
+  std::string installedDir =
+    cmStrCat("$ENV{DESTDIR}",
+             this->ConvertToAbsoluteDestination(this->Destination), '/');
+  std::string installedFile = cmStrCat(installedDir, this->FileName);
   os << indent << "if(EXISTS \"" << installedFile << "\")\n";
   Indent indentN = indent.Next();
   Indent indentNN = indentN.Next();
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index 9919ce8..0b3617b 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -14,6 +14,7 @@
 #include "cmExportSet.h"
 #include "cmInstallType.h"
 #include "cmLocalGenerator.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 cmInstallExportGenerator::cmInstallExportGenerator(
@@ -56,8 +57,8 @@ void cmInstallExportGenerator::ComputeTempDir()
 {
   // Choose a temporary directory in which to generate the import
   // files to be installed.
-  this->TempDir = this->LocalGenerator->GetCurrentBinaryDirectory();
-  this->TempDir += "/CMakeFiles/Export";
+  this->TempDir = cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(),
+                           "/CMakeFiles/Export");
   if (this->Destination.empty()) {
     return;
   }
@@ -135,9 +136,7 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
   cmSystemTools::MakeDirectory(this->TempDir);
 
   // Construct a temporary location for the file.
-  this->MainImportFile = this->TempDir;
-  this->MainImportFile += "/";
-  this->MainImportFile += this->FileName;
+  this->MainImportFile = cmStrCat(this->TempDir, '/', this->FileName);
 
   // Generate the import file for this export set.
   this->EFGen->SetExportFile(this->MainImportFile.c_str());
@@ -185,11 +184,10 @@ void cmInstallExportGenerator::GenerateScriptActions(std::ostream& os,
                                                      Indent indent)
 {
   // Remove old per-configuration export files if the main changes.
-  std::string installedDir = "$ENV{DESTDIR}";
-  installedDir += this->ConvertToAbsoluteDestination(this->Destination);
-  installedDir += "/";
-  std::string installedFile = installedDir;
-  installedFile += this->FileName;
+  std::string installedDir =
+    cmStrCat("$ENV{DESTDIR}",
+             this->ConvertToAbsoluteDestination(this->Destination), '/');
+  std::string installedFile = cmStrCat(installedDir, this->FileName);
   os << indent << "if(EXISTS \"" << installedFile << "\")\n";
   Indent indentN = indent.Next();
   Indent indentNN = indentN.Next();
diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx
index 4522669..11687a8 100644
--- a/Source/cmInstallFilesCommand.cxx
+++ b/Source/cmInstallFilesCommand.cxx
@@ -8,6 +8,7 @@
 #include "cmInstallGenerator.h"
 #include "cmMakefile.h"
 #include "cmRange.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -135,12 +136,8 @@ static std::string FindInstallSource(cmMakefile& makefile, const char* name)
   }
 
   // This is a relative path.
-  std::string tb = makefile.GetCurrentBinaryDirectory();
-  tb += "/";
-  tb += name;
-  std::string ts = makefile.GetCurrentSourceDirectory();
-  ts += "/";
-  ts += name;
+  std::string tb = cmStrCat(makefile.GetCurrentBinaryDirectory(), '/', name);
+  std::string ts = cmStrCat(makefile.GetCurrentSourceDirectory(), '/', name);
 
   if (cmSystemTools::FileExists(tb)) {
     // The file exists in the binary tree.  Use it.
diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx
index 6ec02e7..3eca0e0 100644
--- a/Source/cmInstallProgramsCommand.cxx
+++ b/Source/cmInstallProgramsCommand.cxx
@@ -7,6 +7,7 @@
 #include "cmInstallFilesGenerator.h"
 #include "cmInstallGenerator.h"
 #include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -110,12 +111,8 @@ static std::string FindInstallSource(cmMakefile& makefile, const char* name)
   }
 
   // This is a relative path.
-  std::string tb = makefile.GetCurrentBinaryDirectory();
-  tb += "/";
-  tb += name;
-  std::string ts = makefile.GetCurrentSourceDirectory();
-  ts += "/";
-  ts += name;
+  std::string tb = cmStrCat(makefile.GetCurrentBinaryDirectory(), '/', name);
+  std::string ts = cmStrCat(makefile.GetCurrentSourceDirectory(), '/', name);
 
   if (cmSystemTools::FileExists(tb)) {
     // The file exists in the binary tree.  Use it.
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 7bc9fdf..7bbef35 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -87,19 +87,18 @@ void cmInstallTargetGenerator::GenerateScriptForConfig(
   std::string fromDirConfig;
   if (this->Target->NeedRelinkBeforeInstall(config)) {
     fromDirConfig =
-      this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory();
-    fromDirConfig += "/CMakeFiles/CMakeRelink.dir/";
+      cmStrCat(this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory(),
+               "/CMakeFiles/CMakeRelink.dir/");
   } else {
     cmStateEnums::ArtifactType artifact = this->ImportLibrary
       ? cmStateEnums::ImportLibraryArtifact
       : cmStateEnums::RuntimeBinaryArtifact;
-    fromDirConfig = this->Target->GetDirectory(config, artifact);
-    fromDirConfig += "/";
+    fromDirConfig =
+      cmStrCat(this->Target->GetDirectory(config, artifact), '/');
   }
 
-  std::string toDir =
-    this->ConvertToAbsoluteDestination(this->GetDestination(config));
-  toDir += "/";
+  std::string toDir = cmStrCat(
+    this->ConvertToAbsoluteDestination(this->GetDestination(config)), '/');
 
   // Compute the list of files to install for this target.
   std::vector<std::string> filesFrom;
@@ -593,8 +592,8 @@ void cmInstallTargetGenerator::AddInstallNamePatchRule(
     // on the installed file.
     if (for_build != for_install) {
       // Prepare to refer to the install-tree install_name.
-      new_id = for_install;
-      new_id += this->GetInstallFilename(this->Target, config, NameSO);
+      new_id = cmStrCat(
+        for_install, this->GetInstallFilename(this->Target, config, NameSO));
     }
   }
 
diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx
index a278925..57b69c8 100644
--- a/Source/cmLinkDirectoriesCommand.cxx
+++ b/Source/cmLinkDirectoriesCommand.cxx
@@ -75,9 +75,8 @@ void cmLinkDirectoriesCommand::AddLinkDir(
         break;
     }
     if (convertToAbsolute) {
-      std::string tmp = this->Makefile->GetCurrentSourceDirectory();
-      tmp += "/";
-      tmp += unixPath;
+      std::string tmp =
+        cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', unixPath);
       unixPath = tmp;
     }
   }
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index 3c41f4a..fe77b33 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -179,10 +179,9 @@ bool GetList(std::vector<std::string>& list, const std::string& var,
       // empty values
       list.clear();
       cmExpandList(listString, list);
-      std::string warn = cmPolicies::GetPolicyWarning(cmPolicies::CMP0007);
-      warn += " List has value = [";
-      warn += listString;
-      warn += "].";
+      std::string warn =
+        cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0007),
+                 " List has value = [", listString, "].");
       makefile.IssueMessage(MessageType::AUTHOR_WARNING, warn);
       return true;
     }
@@ -1549,10 +1548,9 @@ bool FilterRegex(std::vector<std::string> const& args, bool includeMatches,
   const std::string& pattern = args[4];
   cmsys::RegularExpression regex(pattern);
   if (!regex.is_valid()) {
-    std::string error = "sub-command FILTER, mode REGEX ";
-    error += "failed to compile regex \"";
-    error += pattern;
-    error += "\".";
+    std::string error =
+      cmStrCat("sub-command FILTER, mode REGEX failed to compile regex \"",
+               pattern, "\".");
     status.SetError(error);
     return false;
   }
diff --git a/Source/cmLoadCommandCommand.cxx b/Source/cmLoadCommandCommand.cxx
index 5ae660a..180e65b 100644
--- a/Source/cmLoadCommandCommand.cxx
+++ b/Source/cmLoadCommandCommand.cxx
@@ -17,6 +17,7 @@
 #include "cmDynamicLoader.h"
 #include "cmMakefile.h"
 #include "cmState.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -183,16 +184,14 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args,
 
   // Construct a variable to report what file was loaded, if any.
   // Start by removing the definition in case of failure.
-  std::string reportVar = "CMAKE_LOADED_COMMAND_";
-  reportVar += args[0];
+  std::string reportVar = cmStrCat("CMAKE_LOADED_COMMAND_", args[0]);
   this->Makefile->RemoveDefinition(reportVar);
 
   // the file must exist
-  std::string moduleName =
-    this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_PREFIX");
-  moduleName += "cm" + args[0];
-  moduleName +=
-    this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_SUFFIX");
+  std::string moduleName = cmStrCat(
+    this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_PREFIX"), "cm",
+    args[0],
+    this->Makefile->GetRequiredDefinition("CMAKE_SHARED_MODULE_SUFFIX"));
 
   // search for the file
   std::vector<std::string> path;
@@ -218,8 +217,8 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args,
   cmsys::DynamicLoader::LibraryHandle lib =
     cmDynamicLoader::OpenLibrary(fullPath.c_str());
   if (!lib) {
-    std::string err = "Attempt to load the library ";
-    err += fullPath + " failed.";
+    std::string err =
+      cmStrCat("Attempt to load the library ", fullPath, " failed.");
     const char* error = cmsys::DynamicLoader::LastError();
     if (error) {
       err += " Additional error info is:\n";
@@ -237,9 +236,7 @@ bool cmLoadCommandCommand::InitialPass(std::vector<std::string> const& args,
   CM_INIT_FUNCTION initFunction = reinterpret_cast<CM_INIT_FUNCTION>(
     cmsys::DynamicLoader::GetSymbolAddress(lib, initFuncName));
   if (!initFunction) {
-    initFuncName = "_";
-    initFuncName += args[0];
-    initFuncName += "Init";
+    initFuncName = cmStrCat('_', args[0], "Init");
     initFunction = reinterpret_cast<CM_INIT_FUNCTION>(
       cmsys::DynamicLoader::GetSymbolAddress(lib, initFuncName));
   }
diff --git a/Source/cmLocalCommonGenerator.cxx b/Source/cmLocalCommonGenerator.cxx
index 75ad2a6..7c36bdc 100644
--- a/Source/cmLocalCommonGenerator.cxx
+++ b/Source/cmLocalCommonGenerator.cxx
@@ -8,6 +8,7 @@
 #include "cmGeneratorTarget.h"
 #include "cmMakefile.h"
 #include "cmOutputConverter.h"
+#include "cmStringAlgorithms.h"
 
 class cmGlobalGenerator;
 
@@ -51,9 +52,9 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags(
       this->Makefile->GetSafeDefinition("CMAKE_Fortran_MODDIR_DEFAULT");
   }
   if (!mod_dir.empty()) {
-    std::string modflag =
-      this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
-    modflag += mod_dir;
+    std::string modflag = cmStrCat(
+      this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG"),
+      mod_dir);
     this->AppendFlags(flags, modflag);
   }
 
@@ -65,8 +66,9 @@ std::string cmLocalCommonGenerator::GetTargetFortranFlags(
     std::vector<std::string> includes;
     this->GetIncludeDirectories(includes, target, "C", config);
     for (std::string const& id : includes) {
-      std::string flg = modpath_flag;
-      flg += this->ConvertToOutputFormat(id, cmOutputConverter::SHELL);
+      std::string flg =
+        cmStrCat(modpath_flag,
+                 this->ConvertToOutputFormat(id, cmOutputConverter::SHELL));
       this->AppendFlags(flags, flg);
     }
   }
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index d3a5535..1827a42 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -26,6 +26,7 @@
 #include "cmTarget.h"
 #include "cmTestGenerator.h"
 #include "cmVersion.h"
+#include "cm_string_view.hxx"
 #include "cmake.h"
 #include "cmsys/RegularExpression.hxx"
 
@@ -283,9 +284,9 @@ void cmLocalGenerator::GenerateTestFiles()
   const std::string& config =
     this->Makefile->GetConfigurations(configurationTypes, false);
 
-  std::string file = this->StateSnapshot.GetDirectory().GetCurrentBinary();
-  file += "/";
-  file += "CTestTestfile.cmake";
+  std::string file =
+    cmStrCat(this->StateSnapshot.GetDirectory().GetCurrentBinary(),
+             "/CTestTestfile.cmake");
 
   cmGeneratedFileStream fout(file);
   fout.SetCopyIfDifferent(true);
@@ -1160,12 +1161,10 @@ void cmLocalGenerator::GetTargetFlags(
       CM_FALLTHROUGH;
     case cmStateEnums::SHARED_LIBRARY: {
       if (linkLanguage != "Swift") {
-        linkFlags = this->Makefile->GetSafeDefinition(libraryLinkVariable);
-        linkFlags += " ";
+        linkFlags = cmStrCat(
+          this->Makefile->GetSafeDefinition(libraryLinkVariable), ' ');
         if (!buildType.empty()) {
-          std::string build = libraryLinkVariable;
-          build += "_";
-          build += buildType;
+          std::string build = cmStrCat(libraryLinkVariable, '_', buildType);
           linkFlags += this->Makefile->GetSafeDefinition(build);
           linkFlags += " ";
         }
@@ -1347,8 +1346,7 @@ static std::string GetFrameworkFlags(const std::string& lang,
   // will already have added a -F for the framework
   for (std::string const& include : includes) {
     if (lg->GetGlobalGenerator()->NameResolvesToFramework(include)) {
-      std::string frameworkDir = include;
-      frameworkDir += "/../";
+      std::string frameworkDir = cmStrCat(include, "/../");
       frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir);
       emitted.insert(frameworkDir);
     }
@@ -1724,9 +1722,8 @@ bool cmLocalGenerator::GetRealDependency(const std::string& inName,
 
   // Treat the name as relative to the source directory in which it
   // was given.
-  dep = this->StateSnapshot.GetDirectory().GetCurrentSource();
-  dep += "/";
-  dep += inName;
+  dep = cmStrCat(this->StateSnapshot.GetDirectory().GetCurrentSource(), '/',
+                 inName);
   return true;
 }
 
@@ -2519,8 +2516,8 @@ static bool cmLocalGeneratorShortenObjectName(std::string& objName,
     objName.find('/', objName.size() - max_len + 32);
   if (pos != std::string::npos) {
     cmCryptoHash md5(cmCryptoHash::AlgoMD5);
-    std::string md5name = md5.HashString(objName.substr(0, pos));
-    md5name += objName.substr(pos);
+    std::string md5name = cmStrCat(md5.HashString(objName.substr(0, pos)),
+                                   cm::string_view(objName).substr(pos));
     objName = md5name;
 
     // The object name is now short enough.
diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx
index bf25f98..b00dda1 100644
--- a/Source/cmLocalGhsMultiGenerator.cxx
+++ b/Source/cmLocalGhsMultiGenerator.cxx
@@ -7,6 +7,7 @@
 #include "cmGlobalGenerator.h"
 #include "cmSourceFile.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <algorithm>
@@ -23,9 +24,7 @@ cmLocalGhsMultiGenerator::~cmLocalGhsMultiGenerator() = default;
 std::string cmLocalGhsMultiGenerator::GetTargetDirectory(
   cmGeneratorTarget const* target) const
 {
-  std::string dir;
-  dir += target->GetName();
-  dir += ".dir";
+  std::string dir = cmStrCat(target->GetName(), ".dir");
   return dir;
 }
 
@@ -63,11 +62,8 @@ void cmLocalGhsMultiGenerator::ComputeObjectFilenames(
   std::map<cmSourceFile const*, std::string>& mapping,
   cmGeneratorTarget const* gt)
 {
-  std::string dir_max;
-  dir_max += this->GetCurrentBinaryDirectory();
-  dir_max += "/";
-  dir_max += this->GetTargetDirectory(gt);
-  dir_max += "/";
+  std::string dir_max = cmStrCat(this->GetCurrentBinaryDirectory(), '/',
+                                 this->GetTargetDirectory(gt), '/');
 
   // Count the number of object files with each name.  Note that
   // filesystem may not be case sensitive.
@@ -75,9 +71,10 @@ void cmLocalGhsMultiGenerator::ComputeObjectFilenames(
 
   for (auto const& si : mapping) {
     cmSourceFile const* sf = si.first;
-    std::string objectNameLower = cmSystemTools::LowerCase(
-      cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()));
-    objectNameLower += this->GlobalGenerator->GetLanguageOutputExtension(*sf);
+    std::string objectNameLower = cmStrCat(
+      cmSystemTools::LowerCase(
+        cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath())),
+      this->GlobalGenerator->GetLanguageOutputExtension(*sf));
     counts[objectNameLower] += 1;
   }
 
@@ -85,9 +82,9 @@ void cmLocalGhsMultiGenerator::ComputeObjectFilenames(
   // object name computation.
   for (auto& si : mapping) {
     cmSourceFile const* sf = si.first;
-    std::string objectName =
-      cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
-    objectName += this->GlobalGenerator->GetLanguageOutputExtension(*sf);
+    std::string objectName = cmStrCat(
+      cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()),
+      this->GlobalGenerator->GetLanguageOutputExtension(*sf));
 
     if (counts[cmSystemTools::LowerCase(objectName)] > 1) {
       const_cast<cmGeneratorTarget*>(gt)->AddExplicitObjectName(sf);
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 220553b..1be219c 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -103,8 +103,7 @@ void cmLocalNinjaGenerator::Generate()
 std::string cmLocalNinjaGenerator::GetTargetDirectory(
   cmGeneratorTarget const* target) const
 {
-  std::string dir = "CMakeFiles/";
-  dir += target->GetName();
+  std::string dir = cmStrCat("CMakeFiles/", target->GetName());
 #if defined(__VMS)
   dir += "_dir";
 #else
@@ -301,8 +300,7 @@ std::string cmLocalNinjaGenerator::WriteCommandScript(
   if (target) {
     scriptPath = target->GetSupportDirectory();
   } else {
-    scriptPath = this->GetCurrentBinaryDirectory();
-    scriptPath += "/CMakeFiles";
+    scriptPath = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles");
   }
   cmSystemTools::MakeDirectory(scriptPath);
   scriptPath += '/';
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index b4ed033..c301b1a 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -164,11 +164,8 @@ void cmLocalUnixMakefileGenerator3::GetLocalObjectFiles(
     gt->GetObjectSources(
       objectSources, this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
     // Compute full path to object file directory for this target.
-    std::string dir;
-    dir += gt->LocalGenerator->GetCurrentBinaryDirectory();
-    dir += "/";
-    dir += this->GetTargetDirectory(gt);
-    dir += "/";
+    std::string dir = cmStrCat(gt->LocalGenerator->GetCurrentBinaryDirectory(),
+                               '/', this->GetTargetDirectory(gt), '/');
     // Compute the name of each object file.
     for (cmSourceFile const* sf : objectSources) {
       bool hasSourceExtension = true;
@@ -365,14 +362,12 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets(
       emitted.insert(target->GetName());
 
       // for subdirs add a rule to build this specific target by name.
-      localName = this->GetRelativeTargetDirectory(target);
-      localName += "/rule";
+      localName = cmStrCat(this->GetRelativeTargetDirectory(target), "/rule");
       commands.clear();
       depends.clear();
 
       // Build the target for this pass.
-      std::string makefile2 = "CMakeFiles/";
-      makefile2 += "Makefile2";
+      std::string makefile2 = "CMakeFiles/Makefile2";
       commands.push_back(this->GetRecursiveMakeCall(makefile2, localName));
       this->CreateCDCommand(commands, this->GetBinaryDirectory(),
                             this->GetCurrentBinaryDirectory());
@@ -388,13 +383,12 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets(
       }
 
       // Add a fast rule to build the target
-      std::string makefileName = this->GetRelativeTargetDirectory(target);
-      makefileName += "/build.make";
+      std::string makefileName =
+        cmStrCat(this->GetRelativeTargetDirectory(target), "/build.make");
       // make sure the makefile name is suitable for a makefile
-      std::string makeTargetName = this->GetRelativeTargetDirectory(target);
-      makeTargetName += "/build";
-      localName = target->GetName();
-      localName += "/fast";
+      std::string makeTargetName =
+        cmStrCat(this->GetRelativeTargetDirectory(target), "/build");
+      localName = cmStrCat(target->GetName(), "/fast");
       depends.clear();
       commands.clear();
       commands.push_back(
@@ -407,10 +401,9 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets(
       // Add a local name for the rule to relink the target before
       // installation.
       if (target->NeedRelinkBeforeInstall(this->ConfigName)) {
-        makeTargetName = this->GetRelativeTargetDirectory(target);
-        makeTargetName += "/preinstall";
-        localName = target->GetName();
-        localName += "/preinstall";
+        makeTargetName =
+          cmStrCat(this->GetRelativeTargetDirectory(target), "/preinstall");
+        localName = cmStrCat(target->GetName(), "/preinstall");
         depends.clear();
         commands.clear();
         commands.push_back(
@@ -427,8 +420,9 @@ void cmLocalUnixMakefileGenerator3::WriteLocalMakefileTargets(
 
 void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
 {
-  std::string infoFileName = this->GetCurrentBinaryDirectory();
-  infoFileName += "/CMakeFiles/CMakeDirectoryInformation.cmake";
+  std::string infoFileName =
+    cmStrCat(this->GetCurrentBinaryDirectory(),
+             "/CMakeFiles/CMakeDirectoryInformation.cmake");
 
   // Open the output file.
   cmGeneratedFileStream infoFileStream(infoFileName);
@@ -484,9 +478,8 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
 std::string cmLocalUnixMakefileGenerator3::ConvertToFullPath(
   const std::string& localPath)
 {
-  std::string dir = this->GetCurrentBinaryDirectory();
-  dir += "/";
-  dir += localPath;
+  std::string dir =
+    cmStrCat(this->GetCurrentBinaryDirectory(), '/', localPath);
   return dir;
 }
 
@@ -767,19 +760,18 @@ void cmLocalUnixMakefileGenerator3::WriteSpecialTargetsBottom(
     std::vector<std::string> commands;
     cmake* cm = this->GlobalGenerator->GetCMakeInstance();
     if (cm->DoWriteGlobVerifyTarget()) {
-      std::string rescanRule = "$(CMAKE_COMMAND) -P ";
-      rescanRule += this->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
-                                                cmOutputConverter::SHELL);
+      std::string rescanRule =
+        cmStrCat("$(CMAKE_COMMAND) -P ",
+                 this->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
+                                             cmOutputConverter::SHELL));
       commands.push_back(rescanRule);
     }
-    std::string cmakefileName = "CMakeFiles/";
-    cmakefileName += "Makefile.cmake";
-    std::string runRule =
-      "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
-    runRule += " --check-build-system ";
-    runRule +=
-      this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL);
-    runRule += " 0";
+    std::string cmakefileName = "CMakeFiles/Makefile.cmake";
+    std::string runRule = cmStrCat(
+      "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) "
+      "--check-build-system ",
+      this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL),
+      " 0");
 
     std::vector<std::string> no_depends;
     commands.push_back(std::move(runRule));
@@ -820,8 +812,8 @@ void cmLocalUnixMakefileGenerator3::WriteConvenienceRule(
 std::string cmLocalUnixMakefileGenerator3::GetRelativeTargetDirectory(
   cmGeneratorTarget* target)
 {
-  std::string dir = this->HomeRelativeOutputPath;
-  dir += this->GetTargetDirectory(target);
+  std::string dir =
+    cmStrCat(this->HomeRelativeOutputPath, this->GetTargetDirectory(target));
   return dir;
 }
 
@@ -1044,10 +1036,8 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand(
   cmGeneratorTarget* target, const char* filename)
 {
   std::string currentBinDir = this->GetCurrentBinaryDirectory();
-  std::string cleanfile = currentBinDir;
-  cleanfile += "/";
-  cleanfile += this->GetTargetDirectory(target);
-  cleanfile += "/cmake_clean";
+  std::string cleanfile = cmStrCat(
+    currentBinDir, '/', this->GetTargetDirectory(target), "/cmake_clean");
   if (filename) {
     cleanfile += "_";
     cleanfile += filename;
@@ -1067,11 +1057,12 @@ void cmLocalUnixMakefileGenerator3::AppendCleanCommand(
     fout << ")\n";
   }
   {
-    std::string remove = "$(CMAKE_COMMAND) -P ";
-    remove += this->ConvertToOutputFormat(
-      this->MaybeConvertToRelativePath(this->GetCurrentBinaryDirectory(),
-                                       cleanfile),
-      cmOutputConverter::SHELL);
+    std::string remove =
+      cmStrCat("$(CMAKE_COMMAND) -P ",
+               this->ConvertToOutputFormat(
+                 this->MaybeConvertToRelativePath(
+                   this->GetCurrentBinaryDirectory(), cleanfile),
+                 cmOutputConverter::SHELL));
     commands.push_back(std::move(remove));
   }
 
@@ -1114,8 +1105,8 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand(
     this->GetGlobalGenerator()->GetLocalGenerators().at(0);
   std::string const& binaryDir = rootLG->GetCurrentBinaryDirectory();
   std::string const& currentBinaryDir = this->GetCurrentBinaryDirectory();
-  std::string cleanfile = currentBinaryDir;
-  cleanfile += "/CMakeFiles/cmake_directory_clean.cmake";
+  std::string cleanfile =
+    cmStrCat(currentBinaryDir, "/CMakeFiles/cmake_directory_clean.cmake");
   // Write clean script
   {
     std::string cleanfilePath = cmSystemTools::CollapseFullPath(cleanfile);
@@ -1134,10 +1125,11 @@ void cmLocalUnixMakefileGenerator3::AppendDirectoryCleanCommand(
   }
   // Create command
   {
-    std::string remove = "$(CMAKE_COMMAND) -P ";
-    remove += this->ConvertToOutputFormat(
-      rootLG->MaybeConvertToRelativePath(binaryDir, cleanfile),
-      cmOutputConverter::SHELL);
+    std::string remove =
+      cmStrCat("$(CMAKE_COMMAND) -P ",
+               this->ConvertToOutputFormat(
+                 rootLG->MaybeConvertToRelativePath(binaryDir, cleanfile),
+                 cmOutputConverter::SHELL));
     commands.push_back(std::move(remove));
   }
 }
@@ -1183,12 +1175,12 @@ void cmLocalUnixMakefileGenerator3::AppendEcho(
         std::string cmd;
         if (color_name.empty() && !progress) {
           // Use the native echo command.
-          cmd = "@echo ";
-          cmd += this->EscapeForShell(line, false, true);
+          cmd = cmStrCat("@echo ", this->EscapeForShell(line, false, true));
         } else {
           // Use cmake to echo the text in color.
-          cmd = "@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) ";
-          cmd += color_name;
+          cmd = cmStrCat(
+            "@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) ",
+            color_name);
           if (progress) {
             cmd += "--progress-dir=";
             cmd += this->ConvertToOutputFormat(
@@ -1224,8 +1216,7 @@ void cmLocalUnixMakefileGenerator3::AppendEcho(
 std::string cmLocalUnixMakefileGenerator3::CreateMakeVariable(
   std::string const& s, std::string const& s2)
 {
-  std::string unmodified = s;
-  unmodified += s2;
+  std::string unmodified = cmStrCat(s, s2);
   // if there is no restriction on the length of make variables
   // and there are no "." characters in the string, then return the
   // unmodified combination.
@@ -1343,8 +1334,9 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
   // may have changed. In this case discard all old dependencies.
   bool needRescanDirInfo = false;
   {
-    std::string dirInfoFile = this->GetCurrentBinaryDirectory();
-    dirInfoFile += "/CMakeFiles/CMakeDirectoryInformation.cmake";
+    std::string dirInfoFile =
+      cmStrCat(this->GetCurrentBinaryDirectory(),
+               "/CMakeFiles/CMakeDirectoryInformation.cmake");
     int result;
     if (!ftc->Compare(internalDependFile, dirInfoFile, &result) ||
         result < 0) {
@@ -1386,8 +1378,8 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
     // The dependencies must be regenerated.
     std::string targetName = cmSystemTools::GetFilenameName(targetDir);
     targetName = targetName.substr(0, targetName.length() - 4);
-    std::string message = "Scanning dependencies of target ";
-    message += targetName;
+    std::string message =
+      cmStrCat("Scanning dependencies of target ", targetName);
     cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundMagenta |
                                        cmsysTerminal_Color_ForegroundBold,
                                      message.c_str(), true, color);
@@ -1408,8 +1400,9 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(
   cmMakefile* mf = this->Makefile;
   bool haveDirectoryInfo = false;
   {
-    std::string dirInfoFile = this->GetCurrentBinaryDirectory();
-    dirInfoFile += "/CMakeFiles/CMakeDirectoryInformation.cmake";
+    std::string dirInfoFile =
+      cmStrCat(this->GetCurrentBinaryDirectory(),
+               "/CMakeFiles/CMakeDirectoryInformation.cmake");
     if (mf->ReadListFile(dirInfoFile) &&
         !cmSystemTools::GetErrorOccuredFlag()) {
       haveDirectoryInfo = true;
@@ -1621,8 +1614,8 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
   std::vector<std::string> commands;
 
   // Write the all rule.
-  std::string recursiveTarget = this->GetCurrentBinaryDirectory();
-  recursiveTarget += "/all";
+  std::string recursiveTarget =
+    cmStrCat(this->GetCurrentBinaryDirectory(), "/all");
 
   bool regenerate =
     !this->GlobalGenerator->GlobalSettingIsOn("CMAKE_SUPPRESS_REGENERATION");
@@ -1630,8 +1623,8 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
     depends.emplace_back("cmake_check_build_system");
   }
 
-  std::string progressDir = this->GetBinaryDirectory();
-  progressDir += "/CMakeFiles";
+  std::string progressDir =
+    cmStrCat(this->GetBinaryDirectory(), "/CMakeFiles");
   {
     std::ostringstream progCmd;
     progCmd << "$(CMAKE_COMMAND) -E cmake_progress_start ";
@@ -1662,8 +1655,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
                       commands, true);
 
   // Write the clean rule.
-  recursiveTarget = this->GetCurrentBinaryDirectory();
-  recursiveTarget += "/clean";
+  recursiveTarget = cmStrCat(this->GetCurrentBinaryDirectory(), "/clean");
   commands.clear();
   depends.clear();
   commands.push_back(this->GetRecursiveMakeCall(mf2Dir, recursiveTarget));
@@ -1678,8 +1670,7 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
                       depends, commands, true);
 
   // Write the preinstall rule.
-  recursiveTarget = this->GetCurrentBinaryDirectory();
-  recursiveTarget += "/preinstall";
+  recursiveTarget = cmStrCat(this->GetCurrentBinaryDirectory(), "/preinstall");
   commands.clear();
   depends.clear();
   const char* noall =
@@ -1706,20 +1697,19 @@ void cmLocalUnixMakefileGenerator3::WriteLocalAllRules(
     commands.clear();
     cmake* cm = this->GlobalGenerator->GetCMakeInstance();
     if (cm->DoWriteGlobVerifyTarget()) {
-      std::string rescanRule = "$(CMAKE_COMMAND) -P ";
-      rescanRule += this->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
-                                                cmOutputConverter::SHELL);
+      std::string rescanRule =
+        cmStrCat("$(CMAKE_COMMAND) -P ",
+                 this->ConvertToOutputFormat(cm->GetGlobVerifyScript(),
+                                             cmOutputConverter::SHELL));
       commands.push_back(rescanRule);
     }
-    std::string cmakefileName = "CMakeFiles/";
-    cmakefileName += "Makefile.cmake";
+    std::string cmakefileName = "CMakeFiles/Makefile.cmake";
     {
-      std::string runRule =
-        "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)";
-      runRule += " --check-build-system ";
-      runRule +=
-        this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL);
-      runRule += " 1";
+      std::string runRule = cmStrCat(
+        "$(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) "
+        "--check-build-system ",
+        this->ConvertToOutputFormat(cmakefileName, cmOutputConverter::SHELL),
+        " 1");
       commands.push_back(std::move(runRule));
     }
     this->CreateCDCommand(commands, this->GetBinaryDirectory(),
@@ -1840,9 +1830,8 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
     cmakefileStream << "  )\n";
 
     // Tell the dependency scanner what compiler is used.
-    std::string cidVar = "CMAKE_";
-    cidVar += implicitLang.first;
-    cidVar += "_COMPILER_ID";
+    std::string cidVar =
+      cmStrCat("CMAKE_", implicitLang.first, "_COMPILER_ID");
     const char* cid = this->Makefile->GetDefinition(cidVar);
     if (cid && *cid) {
       cmakefileStream << "set(CMAKE_" << implicitLang.first
@@ -1933,10 +1922,9 @@ std::string cmLocalUnixMakefileGenerator3::GetRecursiveMakeCall(
   const std::string& makefile, const std::string& tgt)
 {
   // Call make on the given file.
-  std::string cmd;
-  cmd += "$(MAKE) -f ";
-  cmd += this->ConvertToOutputFormat(makefile, cmOutputConverter::SHELL);
-  cmd += " ";
+  std::string cmd = cmStrCat(
+    "$(MAKE) -f ",
+    this->ConvertToOutputFormat(makefile, cmOutputConverter::SHELL), ' ');
 
   cmGlobalUnixMakefileGenerator3* gg =
     static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator);
@@ -2067,8 +2055,7 @@ std::string cmLocalUnixMakefileGenerator3::ConvertToQuotedOutputPath(
 std::string cmLocalUnixMakefileGenerator3::GetTargetDirectory(
   cmGeneratorTarget const* target) const
 {
-  std::string dir = "CMakeFiles/";
-  dir += target->GetName();
+  std::string dir = cmStrCat("CMakeFiles/", target->GetName());
 #if defined(__VMS)
   dir += "_dir";
 #else
@@ -2111,13 +2098,12 @@ void cmLocalUnixMakefileGenerator3::CreateCDCommand(
     // On Windows we must perform each step separately and then change
     // back because the shell keeps the working directory between
     // commands.
-    std::string cmd = cd_cmd;
-    cmd += this->ConvertToOutputForExisting(tgtDir);
+    std::string cmd =
+      cmStrCat(cd_cmd, this->ConvertToOutputForExisting(tgtDir));
     commands.insert(commands.begin(), cmd);
 
     // Change back to the starting directory.
-    cmd = cd_cmd;
-    cmd += this->ConvertToOutputForExisting(relDir);
+    cmd = cmStrCat(cd_cmd, this->ConvertToOutputForExisting(relDir));
     commands.push_back(std::move(cmd));
   } else {
     // On UNIX we must construct a single shell command to change
diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx
index d45c335..6d7b359 100644
--- a/Source/cmLocalVisualStudio10Generator.cxx
+++ b/Source/cmLocalVisualStudio10Generator.cxx
@@ -121,8 +121,7 @@ void cmLocalVisualStudio10Generator::ReadAndStoreExternalGUID(
     return;
   }
 
-  std::string guidStoreName = name;
-  guidStoreName += "_GUID_CMAKE";
+  std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE");
   // save the GUID in the cache
   this->GlobalGenerator->GetCMakeInstance()->AddCacheEntry(
     guidStoreName.c_str(), parser.GUID.c_str(), "Stored GUID",
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 6e35e0c..bbee705 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -97,10 +97,8 @@ void cmLocalVisualStudio7Generator::FixGlobalTargets()
       cmCustomCommandLines force_commands;
       force_commands.push_back(force_command);
       std::string no_main_dependency;
-      std::string force = this->GetCurrentBinaryDirectory();
-      force += "/CMakeFiles/";
-      force += l->GetName();
-      force += "_force";
+      std::string force = cmStrCat(this->GetCurrentBinaryDirectory(),
+                                   "/CMakeFiles/", l->GetName(), "_force");
       if (cmSourceFile* file = this->Makefile->AddCustomCommandToOutput(
             force.c_str(), no_depends, no_main_dependency, force_commands, " ",
             0, true)) {
@@ -143,8 +141,8 @@ void cmLocalVisualStudio7Generator::WriteStampFiles()
 {
   // Touch a timestamp file used to determine when the project file is
   // out of date.
-  std::string stampName = this->GetCurrentBinaryDirectory();
-  stampName += "/CMakeFiles";
+  std::string stampName =
+    cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles");
   cmSystemTools::MakeDirectory(stampName.c_str());
   stampName += "/generate.stamp";
   cmsys::ofstream stamp(stampName.c_str());
@@ -156,8 +154,7 @@ void cmLocalVisualStudio7Generator::WriteStampFiles()
   // dependencies.  If any file listed in it is newer than itself then
   // CMake must rerun.  Otherwise the project files are up to date and
   // the stamp file can just be touched.
-  std::string depName = stampName;
-  depName += ".depend";
+  std::string depName = cmStrCat(stampName, ".depend");
   cmsys::ofstream depFile(depName.c_str());
   depFile << "# CMake generation dependency list for this directory.\n";
 
@@ -197,9 +194,7 @@ void cmLocalVisualStudio7Generator::CreateSingleVCProj(
   target->Target->SetProperty("GENERATOR_FILE_NAME", lname.c_str());
   // create the dsp.cmake file
   std::string fname;
-  fname = this->GetCurrentBinaryDirectory();
-  fname += "/";
-  fname += lname;
+  fname = cmStrCat(this->GetCurrentBinaryDirectory(), '/', lname);
   if (this->FortranProject) {
     fname += ".vfproj";
   } else {
@@ -226,9 +221,8 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
     return nullptr;
   }
 
-  std::string makefileIn = this->GetCurrentSourceDirectory();
-  makefileIn += "/";
-  makefileIn += "CMakeLists.txt";
+  std::string makefileIn =
+    cmStrCat(this->GetCurrentSourceDirectory(), "/CMakeLists.txt");
   makefileIn = cmSystemTools::CollapseFullPath(makefileIn);
   if (cmSourceFile* file = this->Makefile->GetSource(makefileIn)) {
     if (file->GetCustomCommand()) {
@@ -251,20 +245,15 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule()
     std::unique(listFiles.begin(), listFiles.end());
   listFiles.erase(new_end, listFiles.end());
 
-  std::string stampName = this->GetCurrentBinaryDirectory();
-  stampName += "/";
-  stampName += "CMakeFiles/";
-  stampName += "generate.stamp";
+  std::string stampName =
+    cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/generate.stamp");
   cmCustomCommandLine commandLine;
   commandLine.push_back(cmSystemTools::GetCMakeCommand());
-  std::string comment = "Building Custom Rule ";
-  comment += makefileIn;
+  std::string comment = cmStrCat("Building Custom Rule ", makefileIn);
   std::string args;
-  args = "-S";
-  args += this->GetSourceDirectory();
+  args = cmStrCat("-S", this->GetSourceDirectory());
   commandLine.push_back(args);
-  args = "-B";
-  args += this->GetBinaryDirectory();
+  args = cmStrCat("-B", this->GetBinaryDirectory());
   commandLine.push_back(args);
   commandLine.push_back("--check-stamp-file");
   commandLine.push_back(stampName);
@@ -719,9 +708,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
     this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
 
   // Add a definition for the configuration name.
-  std::string configDefine = "CMAKE_INTDIR=\"";
-  configDefine += configName;
-  configDefine += "\"";
+  std::string configDefine = cmStrCat("CMAKE_INTDIR=\"", configName, '"');
   targetOptions.AddDefine(configDefine);
 
   // Add the export symbol definition for shared library objects.
@@ -731,9 +718,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
 
   // The intermediate directory name consists of a directory for the
   // target and a subdirectory for the configuration name.
-  std::string intermediateDir = this->GetTargetDirectory(target);
-  intermediateDir += "/";
-  intermediateDir += configName;
+  std::string intermediateDir =
+    cmStrCat(this->GetTargetDirectory(target), '/', configName);
 
   if (target->GetType() < cmStateEnums::UTILITY) {
     std::string const& outDir =
@@ -954,8 +940,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
     extraLinkOptions += targetLinkFlags;
   }
   std::string configTypeUpper = cmSystemTools::UpperCase(configName);
-  std::string linkFlagsConfig = "LINK_FLAGS_";
-  linkFlagsConfig += configTypeUpper;
+  std::string linkFlagsConfig = cmStrCat("LINK_FLAGS_", configTypeUpper);
   targetLinkFlags = target->GetProperty(linkFlagsConfig.c_str());
   if (targetLinkFlags) {
     extraLinkOptions += " ";
@@ -987,12 +972,9 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
     case cmStateEnums::UNKNOWN_LIBRARY:
       break;
     case cmStateEnums::OBJECT_LIBRARY: {
-      std::string libpath = this->GetTargetDirectory(target);
-      libpath += "/";
-      libpath += configName;
-      libpath += "/";
-      libpath += target->GetName();
-      libpath += ".lib";
+      std::string libpath =
+        cmStrCat(this->GetTargetDirectory(target), '/', configName, '/',
+                 target->GetName(), ".lib");
       const char* tool =
         this->FortranProject ? "VFLibrarianTool" : "VCLibrarianTool";
       fout << "\t\t\t<Tool\n"
@@ -1003,9 +985,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
     }
     case cmStateEnums::STATIC_LIBRARY: {
       std::string targetNameFull = target->GetFullName(configName);
-      std::string libpath = target->GetDirectory(configName);
-      libpath += "/";
-      libpath += targetNameFull;
+      std::string libpath =
+        cmStrCat(target->GetDirectory(configName), '/', targetNameFull);
       const char* tool = "VCLibrarianTool";
       if (this->FortranProject) {
         tool = "VFLibrarianTool";
@@ -1047,9 +1028,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
 
       // Compute the variable name to lookup standard libraries for this
       // language.
-      std::string standardLibsVar = "CMAKE_";
-      standardLibsVar += linkLanguage;
-      standardLibsVar += "_STANDARD_LIBRARIES";
+      std::string standardLibsVar =
+        cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LIBRARIES");
       const char* tool = "VCLinkerTool";
       if (this->FortranProject) {
         tool = "VFLinkerTool";
@@ -1069,9 +1049,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
       fout << " ";
       this->Internal->OutputLibraries(fout, cli.GetItems());
       fout << "\"\n";
-      temp = target->GetDirectory(configName);
-      temp += "/";
-      temp += targetNames.Output;
+      temp =
+        cmStrCat(target->GetDirectory(configName), '/', targetNames.Output);
       fout << "\t\t\t\tOutputFile=\""
            << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
       this->WriteTargetVersionAttribute(fout, target);
@@ -1079,9 +1058,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
       fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
       this->OutputLibraryDirectories(fout, cli.GetDirectories());
       fout << "\"\n";
-      temp = target->GetPDBDirectory(configName);
-      temp += "/";
-      temp += targetNames.PDB;
+      temp =
+        cmStrCat(target->GetPDBDirectory(configName), '/', targetNames.PDB);
       fout << "\t\t\t\tProgramDatabaseFile=\""
            << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
       if (targetOptions.IsDebug()) {
@@ -1094,17 +1072,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
           fout << "\t\t\t\tSubSystem=\"8\"\n";
         }
       }
-      std::string stackVar = "CMAKE_";
-      stackVar += linkLanguage;
-      stackVar += "_STACK_SIZE";
+      std::string stackVar = cmStrCat("CMAKE_", linkLanguage, "_STACK_SIZE");
       const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str());
       if (stackVal) {
         fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\"\n";
       }
-      temp =
-        target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact);
-      temp += "/";
-      temp += targetNames.ImportLibrary;
+      temp = cmStrCat(
+        target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact),
+        '/', targetNames.ImportLibrary);
       fout << "\t\t\t\tImportLibrary=\""
            << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"";
       if (this->FortranProject) {
@@ -1128,9 +1103,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
 
       // Compute the variable name to lookup standard libraries for this
       // language.
-      std::string standardLibsVar = "CMAKE_";
-      standardLibsVar += linkLanguage;
-      standardLibsVar += "_STANDARD_LIBRARIES";
+      std::string standardLibsVar =
+        cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LIBRARIES");
       const char* tool = "VCLinkerTool";
       if (this->FortranProject) {
         tool = "VFLinkerTool";
@@ -1150,9 +1124,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
       fout << " ";
       this->Internal->OutputLibraries(fout, cli.GetItems());
       fout << "\"\n";
-      temp = target->GetDirectory(configName);
-      temp += "/";
-      temp += targetNames.Output;
+      temp =
+        cmStrCat(target->GetDirectory(configName), '/', targetNames.Output);
       fout << "\t\t\t\tOutputFile=\""
            << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"\n";
       this->WriteTargetVersionAttribute(fout, target);
@@ -1188,17 +1161,14 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
         fout << "\t\t\t\tSubSystem=\"" << (isWin32Executable ? "2" : "1")
              << "\"\n";
       }
-      std::string stackVar = "CMAKE_";
-      stackVar += linkLanguage;
-      stackVar += "_STACK_SIZE";
+      std::string stackVar = cmStrCat("CMAKE_", linkLanguage, "_STACK_SIZE");
       const char* stackVal = this->Makefile->GetDefinition(stackVar.c_str());
       if (stackVal) {
         fout << "\t\t\t\tStackReserveSize=\"" << stackVal << "\"";
       }
-      temp =
-        target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact);
-      temp += "/";
-      temp += targetNames.ImportLibrary;
+      temp = cmStrCat(
+        target->GetDirectory(configName, cmStateEnums::ImportLibraryArtifact),
+        '/', targetNames.ImportLibrary);
       fout << "\t\t\t\tImportLibrary=\""
            << this->ConvertToXMLOutputPathSingle(temp.c_str()) << "\"/>\n";
       break;
@@ -1507,8 +1477,7 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo(
       fc.CompileDefs = genexInterpreter.Evaluate(cdefs, COMPILE_DEFINITIONS);
       needfc = true;
     }
-    std::string defPropName = "COMPILE_DEFINITIONS_";
-    defPropName += configUpper;
+    std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper);
     if (const char* ccdefs = sf.GetProperty(defPropName)) {
       fc.CompileDefsConfig =
         genexInterpreter.Evaluate(ccdefs, COMPILE_DEFINITIONS);
@@ -1583,13 +1552,9 @@ std::string cmLocalVisualStudio7Generator::ComputeLongestObjectDirectory(
   // Compute the maximum length full path to the intermediate
   // files directory for any configuration.  This is used to construct
   // object file names that do not produce paths that are too long.
-  std::string dir_max;
-  dir_max += this->GetCurrentBinaryDirectory();
-  dir_max += "/";
-  dir_max += this->GetTargetDirectory(target);
-  dir_max += "/";
-  dir_max += config_max;
-  dir_max += "/";
+  std::string dir_max =
+    cmStrCat(this->GetCurrentBinaryDirectory(), '/',
+             this->GetTargetDirectory(target), '/', config_max, '/');
   return dir_max;
 }
 
@@ -2139,8 +2104,7 @@ void cmLocalVisualStudio7Generator::ReadAndStoreExternalGUID(
   if (parser.GUID.empty()) {
     return;
   }
-  std::string guidStoreName = name;
-  guidStoreName += "_GUID_CMAKE";
+  std::string guidStoreName = cmStrCat(name, "_GUID_CMAKE");
   // save the GUID in the cache
   this->GlobalGenerator->GetCMakeInstance()->AddCacheEntry(
     guidStoreName.c_str(), parser.GUID.c_str(), "Stored GUID",
@@ -2150,9 +2114,7 @@ void cmLocalVisualStudio7Generator::ReadAndStoreExternalGUID(
 std::string cmLocalVisualStudio7Generator::GetTargetDirectory(
   cmGeneratorTarget const* target) const
 {
-  std::string dir;
-  dir += target->GetName();
-  dir += ".dir";
+  std::string dir = cmStrCat(target->GetName(), ".dir");
   return dir;
 }
 
diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx
index 9c36627..5a06d4a 100644
--- a/Source/cmLocalXCodeGenerator.cxx
+++ b/Source/cmLocalXCodeGenerator.cxx
@@ -65,9 +65,8 @@ void cmLocalXCodeGenerator::ComputeObjectFilenames(
   std::map<std::string, int> counts;
   for (auto& si : mapping) {
     cmSourceFile const* sf = si.first;
-    std::string objectName =
-      cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath());
-    objectName += ".o";
+    std::string objectName = cmStrCat(
+      cmSystemTools::GetFilenameWithoutLastExtension(sf->GetFullPath()), ".o");
 
     std::string objectNameLower = cmSystemTools::LowerCase(objectName);
     counts[objectNameLower] += 1;
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index bc3c3ac..92ea9aa 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -54,8 +54,8 @@ bool cmMacroHelperCommand::operator()(
   // required by the signature
   if (expandedArgs.size() < this->Args.size() - 1) {
     std::string errorMsg =
-      "Macro invoked with incorrect arguments for macro named: ";
-    errorMsg += this->Args[0];
+      cmStrCat("Macro invoked with incorrect arguments for macro named: ",
+               this->Args[0]);
     inStatus.SetError(errorMsg);
     return false;
   }
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 0af32eb..78351c1 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -429,9 +429,8 @@ bool cmMakefile::ExecuteCommand(const cmListFileFunction& lff,
     }
   } else {
     if (!cmSystemTools::GetFatalErrorOccured()) {
-      std::string error = "Unknown CMake command \"";
-      error += lff.Name.Original;
-      error += "\".";
+      std::string error =
+        cmStrCat("Unknown CMake command \"", lff.Name.Original, "\".");
       this->IssueMessage(MessageType::FATAL_ERROR, error);
       result = false;
       cmSystemTools::SetFatalErrorOccured();
@@ -1188,9 +1187,8 @@ cmTarget* cmMakefile::AddUtilityCommand(
 
   // Store the custom command in the target.
   if (!commandLines.empty() || !depends.empty()) {
-    std::string force = this->GetCurrentBinaryDirectory();
-    force += "/CMakeFiles/";
-    force += utilityName;
+    std::string force =
+      cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles/", utilityName);
     std::vector<std::string> forced;
     forced.push_back(force);
     std::string no_main_dependency;
@@ -1396,8 +1394,8 @@ void cmMakefile::InitializeFromParent(cmMakefile* parent)
     std::vector<std::string> configs;
     this->GetConfigurations(configs);
     for (std::string const& config : configs) {
-      std::string defPropName = "COMPILE_DEFINITIONS_";
-      defPropName += cmSystemTools::UpperCase(config);
+      std::string defPropName =
+        cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config));
       const char* prop = parent->GetProperty(defPropName);
       this->SetProperty(defPropName, prop);
     }
@@ -1490,8 +1488,8 @@ public:
     , ReportError(true)
   {
     std::string currentStart =
-      this->Makefile->StateSnapshot.GetDirectory().GetCurrentSource();
-    currentStart += "/CMakeLists.txt";
+      cmStrCat(this->Makefile->StateSnapshot.GetDirectory().GetCurrentSource(),
+               "/CMakeLists.txt");
     this->Makefile->StateSnapshot.SetListFile(currentStart);
     this->Makefile->StateSnapshot =
       this->Makefile->StateSnapshot.GetState()->CreatePolicyScopeSnapshot(
@@ -1534,9 +1532,8 @@ private:
 
 void cmMakefile::Configure()
 {
-  std::string currentStart =
-    this->StateSnapshot.GetDirectory().GetCurrentSource();
-  currentStart += "/CMakeLists.txt";
+  std::string currentStart = cmStrCat(
+    this->StateSnapshot.GetDirectory().GetCurrentSource(), "/CMakeLists.txt");
 
   // Add the bottom of all backtraces within this directory.
   // We will never pop this scope because it should be available
@@ -1546,8 +1543,8 @@ void cmMakefile::Configure()
   BuildsystemFileScope scope(this);
 
   // make sure the CMakeFiles dir is there
-  std::string filesDir = this->StateSnapshot.GetDirectory().GetCurrentBinary();
-  filesDir += "/CMakeFiles";
+  std::string filesDir = cmStrCat(
+    this->StateSnapshot.GetDirectory().GetCurrentBinary(), "/CMakeFiles");
   cmSystemTools::MakeDirectory(filesDir);
 
   assert(cmSystemTools::FileExists(currentStart, true));
@@ -1658,8 +1655,7 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf)
   mf->InitializeFromParent(this);
   std::string currentStart = mf->GetCurrentSourceDirectory();
   if (this->GetCMakeInstance()->GetDebugOutput()) {
-    std::string msg = "   Entering             ";
-    msg += currentStart;
+    std::string msg = cmStrCat("   Entering             ", currentStart);
     cmSystemTools::Message(msg);
   }
 
@@ -1701,8 +1697,8 @@ void cmMakefile::ConfigureSubDirectory(cmMakefile* mf)
   mf->Configure();
 
   if (this->GetCMakeInstance()->GetDebugOutput()) {
-    std::string msg = "   Returning to         ";
-    msg += this->GetCurrentSourceDirectory();
+    std::string msg =
+      cmStrCat("   Returning to         ", this->GetCurrentSourceDirectory());
     cmSystemTools::Message(msg);
   }
 }
@@ -1909,8 +1905,7 @@ void cmMakefile::LogUnused(const char* reason, const std::string& name) const
     if (!this->ExecutionStatusStack.empty()) {
       path = this->GetExecutionContext().FilePath;
     } else {
-      path = this->GetCurrentSourceDirectory();
-      path += "/CMakeLists.txt";
+      path = cmStrCat(this->GetCurrentSourceDirectory(), "/CMakeLists.txt");
     }
 
     if (this->CheckSystemVars || this->IsProjectFile(path.c_str())) {
@@ -2602,8 +2597,8 @@ const std::string& cmMakefile::ExpandVariablesInString(
   }
   // ...otherwise, see if there's a difference that needs to be warned about.
   else if (compareResults && (newResult != source || newError != mtype)) {
-    std::string msg = cmPolicies::GetPolicyWarning(cmPolicies::CMP0053);
-    msg += "\n";
+    std::string msg =
+      cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0053), '\n');
 
     std::string msg_input = original;
     cmSystemTools::ReplaceString(msg_input, "\n", "\n  ");
@@ -3579,9 +3574,8 @@ std::string cmMakefile::GetModulesFile(const std::string& filename,
   }
 
   // Always search in the standard modules location.
-  moduleInCMakeRoot = cmSystemTools::GetCMakeRoot();
-  moduleInCMakeRoot += "/Modules/";
-  moduleInCMakeRoot += filename;
+  moduleInCMakeRoot =
+    cmStrCat(cmSystemTools::GetCMakeRoot(), "/Modules/", filename);
   cmSystemTools::ConvertToUnixSlashes(moduleInCMakeRoot);
   if (!cmSystemTools::FileExists(moduleInCMakeRoot)) {
     moduleInCMakeRoot.clear();
@@ -3747,8 +3741,7 @@ int cmMakefile::ConfigureFile(const std::string& infile,
     } else {
       newLineCharacters = "\n";
     }
-    std::string tempOutputFile = soutfile;
-    tempOutputFile += ".tmp";
+    std::string tempOutputFile = cmStrCat(soutfile, ".tmp");
     cmsys::ofstream fout(tempOutputFile.c_str(), omode);
     if (!fout) {
       cmSystemTools::Error("Could not open file for write in copy operation " +
@@ -3895,9 +3888,7 @@ void cmMakefile::AddCMakeDependFilesFromUser()
     if (cmSystemTools::FileIsFullPath(dep)) {
       this->AddCMakeDependFile(dep);
     } else {
-      std::string f = this->GetCurrentSourceDirectory();
-      f += "/";
-      f += dep;
+      std::string f = cmStrCat(this->GetCurrentSourceDirectory(), '/', dep);
       this->AddCMakeDependFile(f);
     }
   }
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 097ce45..7bc05b1 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -111,14 +111,13 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
     cmLocalUnixMakefileGenerator3::EchoProgress progress;
     this->MakeEchoProgress(progress);
     // Add the link message.
-    std::string buildEcho = "Linking ";
-    buildEcho += linkLanguage;
-    buildEcho += " device code ";
-    buildEcho += this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(),
-        this->DeviceLinkObject),
-      cmOutputConverter::SHELL);
+    std::string buildEcho =
+      cmStrCat("Linking ", linkLanguage, " device code ",
+               this->LocalGenerator->ConvertToOutputFormat(
+                 this->LocalGenerator->MaybeConvertToRelativePath(
+                   this->LocalGenerator->GetCurrentBinaryDirectory(),
+                   this->DeviceLinkObject),
+                 cmOutputConverter::SHELL));
     this->LocalGenerator->AppendEcho(
       commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
   }
@@ -130,9 +129,8 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
   // Add flags to create an executable.
   // Add symbol export flags if necessary.
   if (this->GeneratorTarget->IsExecutableWithExports()) {
-    std::string export_flag_var = "CMAKE_EXE_EXPORTS_";
-    export_flag_var += linkLanguage;
-    export_flag_var += "_FLAG";
+    std::string export_flag_var =
+      cmStrCat("CMAKE_EXE_EXPORTS_", linkLanguage, "_FLAG");
     this->LocalGenerator->AppendFlags(
       linkFlags, this->Makefile->GetDefinition(export_flag_var));
   }
@@ -234,8 +232,7 @@ void cmMakefileExecutableTargetGenerator::WriteDeviceExecutableRule(
     const char* val = this->LocalGenerator->GetRuleLauncher(
       this->GeneratorTarget, "RULE_LAUNCH_LINK");
     if (val && *val) {
-      launcher = val;
-      launcher += " ";
+      launcher = cmStrCat(val, ' ');
     }
 
     std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
@@ -300,8 +297,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
   outpath += '/';
   std::string outpathImp;
   if (relink) {
-    outpath = this->Makefile->GetCurrentBinaryDirectory();
-    outpath += "/CMakeFiles/CMakeRelink.dir";
+    outpath = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(),
+                       "/CMakeFiles/CMakeRelink.dir");
     cmSystemTools::MakeDirectory(outpath);
     outpath += '/';
     if (!targetNames.ImportLibrary.empty()) {
@@ -371,10 +368,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     cmLocalUnixMakefileGenerator3::EchoProgress progress;
     this->MakeEchoProgress(progress);
     // Add the link message.
-    std::string buildEcho = "Linking ";
-    buildEcho += linkLanguage;
-    buildEcho += " executable ";
-    buildEcho += targetOutPath;
+    std::string buildEcho =
+      cmStrCat("Linking ", linkLanguage, " executable ", targetOutPath);
     this->LocalGenerator->AppendEcho(
       commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
   }
@@ -397,9 +392,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
 
   // Add symbol export flags if necessary.
   if (this->GeneratorTarget->IsExecutableWithExports()) {
-    std::string export_flag_var = "CMAKE_EXE_EXPORTS_";
-    export_flag_var += linkLanguage;
-    export_flag_var += "_FLAG";
+    std::string export_flag_var =
+      cmStrCat("CMAKE_EXE_EXPORTS_", linkLanguage, "_FLAG");
     this->LocalGenerator->AppendFlags(
       linkFlags, this->Makefile->GetDefinition(export_flag_var));
   }
@@ -491,9 +485,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
   if (this->GeneratorTarget->IsExecutableWithExports()) {
     // If a separate rule for creating an import library is specified
     // add it now.
-    std::string implibRuleVar = "CMAKE_";
-    implibRuleVar += linkLanguage;
-    implibRuleVar += "_CREATE_IMPORT_LIBRARY";
+    std::string implibRuleVar =
+      cmStrCat("CMAKE_", linkLanguage, "_CREATE_IMPORT_LIBRARY");
     if (const char* rule = this->Makefile->GetDefinition(implibRuleVar)) {
       cmExpandList(rule, real_link_commands);
     }
@@ -590,10 +583,10 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     vars.Manifests = manifests.c_str();
 
     if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
-      std::string cmakeCommand = this->LocalGenerator->ConvertToOutputFormat(
-        cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
-      cmakeCommand += " -E __run_co_compile --lwyu=";
-      cmakeCommand += targetOutPathReal;
+      std::string cmakeCommand =
+        cmStrCat(this->LocalGenerator->ConvertToOutputFormat(
+                   cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
+                 " -E __run_co_compile --lwyu=", targetOutPathReal);
       real_link_commands.push_back(std::move(cmakeCommand));
     }
 
@@ -602,8 +595,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
     const char* val = this->LocalGenerator->GetRuleLauncher(
       this->GeneratorTarget, "RULE_LAUNCH_LINK");
     if (val && *val) {
-      launcher = val;
-      launcher += " ";
+      launcher = cmStrCat(val, ' ');
     }
 
     std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
@@ -639,10 +631,9 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
 
   // Add a rule to create necessary symlinks for the library.
   if (targetOutPath != targetOutPathReal) {
-    std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_executable ";
-    symlink += targetOutPathReal;
-    symlink += " ";
-    symlink += targetOutPath;
+    std::string symlink =
+      cmStrCat("$(CMAKE_COMMAND) -E cmake_symlink_executable ",
+               targetOutPathReal, ' ', targetOutPath);
     commands1.push_back(std::move(symlink));
     this->LocalGenerator->CreateCDCommand(
       commands1, this->Makefile->GetCurrentBinaryDirectory(),
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 45c74cb..252279f 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -163,9 +163,8 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
 
   std::string linkLanguage =
     this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
-  std::string linkRuleVar = "CMAKE_";
-  linkRuleVar += linkLanguage;
-  linkRuleVar += "_CREATE_SHARED_LIBRARY";
+  std::string linkRuleVar =
+    cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_LIBRARY");
 
   std::string extraFlags;
   this->GetTargetLinkFlags(extraFlags, linkLanguage);
@@ -198,9 +197,8 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
 
   std::string linkLanguage =
     this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
-  std::string linkRuleVar = "CMAKE_";
-  linkRuleVar += linkLanguage;
-  linkRuleVar += "_CREATE_SHARED_MODULE";
+  std::string linkRuleVar =
+    cmStrCat("CMAKE_", linkLanguage, "_CREATE_SHARED_MODULE");
 
   std::string extraFlags;
   this->GetTargetLinkFlags(extraFlags, linkLanguage);
@@ -221,9 +219,8 @@ void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink)
 {
   std::string linkLanguage =
     this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
-  std::string linkRuleVar = "CMAKE_";
-  linkRuleVar += linkLanguage;
-  linkRuleVar += "_CREATE_MACOSX_FRAMEWORK";
+  std::string linkRuleVar =
+    cmStrCat("CMAKE_", linkLanguage, "_CREATE_MACOSX_FRAMEWORK");
 
   std::string extraFlags;
   this->GetTargetLinkFlags(extraFlags, linkLanguage);
@@ -264,12 +261,13 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
     cmLocalUnixMakefileGenerator3::EchoProgress progress;
     this->MakeEchoProgress(progress);
     // Add the link message.
-    std::string buildEcho = "Linking " + linkLanguage + " device code ";
-    buildEcho += this->LocalGenerator->ConvertToOutputFormat(
-      this->LocalGenerator->MaybeConvertToRelativePath(
-        this->LocalGenerator->GetCurrentBinaryDirectory(),
-        this->DeviceLinkObject),
-      cmOutputConverter::SHELL);
+    std::string buildEcho =
+      cmStrCat("Linking ", linkLanguage, " device code ",
+               this->LocalGenerator->ConvertToOutputFormat(
+                 this->LocalGenerator->MaybeConvertToRelativePath(
+                   this->LocalGenerator->GetCurrentBinaryDirectory(),
+                   this->DeviceLinkObject),
+                 cmOutputConverter::SHELL));
     this->LocalGenerator->AppendEcho(
       commands, buildEcho, cmLocalUnixMakefileGenerator3::EchoLink, &progress);
   }
@@ -360,8 +358,7 @@ void cmMakefileLibraryTargetGenerator::WriteDeviceLibraryRules(
     const char* val = this->LocalGenerator->GetRuleLauncher(
       this->GeneratorTarget, "RULE_LAUNCH_LINK");
     if (val && *val) {
-      launcher = val;
-      launcher += " ";
+      launcher = cmStrCat(val, ' ');
     }
 
     std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
@@ -472,8 +469,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
                                              outpath);
     outpath += '/';
   } else if (relink) {
-    outpath = this->Makefile->GetCurrentBinaryDirectory();
-    outpath += "/CMakeFiles/CMakeRelink.dir";
+    outpath = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(),
+                       "/CMakeFiles/CMakeRelink.dir");
     cmSystemTools::MakeDirectory(outpath);
     outpath += '/';
     if (!this->TargetNames.ImportLibrary.empty()) {
@@ -536,8 +533,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     cmLocalUnixMakefileGenerator3::EchoProgress progress;
     this->MakeEchoProgress(progress);
     // Add the link message.
-    std::string buildEcho = "Linking ";
-    buildEcho += linkLanguage;
+    std::string buildEcho = cmStrCat("Linking ", linkLanguage);
     switch (this->GeneratorTarget->GetType()) {
       case cmStateEnums::STATIC_LIBRARY:
         buildEcho += " static library ";
@@ -641,9 +637,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
   std::string::size_type archiveCommandLimit = std::string::npos;
   if (this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY) {
     haveStaticLibraryRule = this->Makefile->IsDefinitionSet(linkRuleVar);
-    std::string arCreateVar = "CMAKE_";
-    arCreateVar += linkLanguage;
-    arCreateVar += "_ARCHIVE_CREATE";
+    std::string arCreateVar =
+      cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_CREATE");
 
     arCreateVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
       arCreateVar, linkLanguage, this->ConfigName);
@@ -651,9 +646,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     if (const char* rule = this->Makefile->GetDefinition(arCreateVar)) {
       cmExpandList(rule, archiveCreateCommands);
     }
-    std::string arAppendVar = "CMAKE_";
-    arAppendVar += linkLanguage;
-    arAppendVar += "_ARCHIVE_APPEND";
+    std::string arAppendVar =
+      cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_APPEND");
 
     arAppendVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
       arAppendVar, linkLanguage, this->ConfigName);
@@ -661,9 +655,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     if (const char* rule = this->Makefile->GetDefinition(arAppendVar)) {
       cmExpandList(rule, archiveAppendCommands);
     }
-    std::string arFinishVar = "CMAKE_";
-    arFinishVar += linkLanguage;
-    arFinishVar += "_ARCHIVE_FINISH";
+    std::string arFinishVar =
+      cmStrCat("CMAKE_", linkLanguage, "_ARCHIVE_FINISH");
 
     arFinishVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
       arFinishVar, linkLanguage, this->ConfigName);
@@ -821,8 +814,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
     const char* val = this->LocalGenerator->GetRuleLauncher(
       this->GeneratorTarget, "RULE_LAUNCH_LINK");
     if (val && *val) {
-      launcher = val;
-      launcher += " ";
+      launcher = cmStrCat(val, ' ');
     }
 
     std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
@@ -882,10 +874,10 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
       cmExpandList(linkRule, real_link_commands);
       if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE") &&
           (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY)) {
-        std::string cmakeCommand = this->LocalGenerator->ConvertToOutputFormat(
-          cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
-        cmakeCommand += " -E __run_co_compile --lwyu=";
-        cmakeCommand += targetOutPathReal;
+        std::string cmakeCommand = cmStrCat(
+          this->LocalGenerator->ConvertToOutputFormat(
+            cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
+          " -E __run_co_compile --lwyu=", targetOutPathReal);
         real_link_commands.push_back(std::move(cmakeCommand));
       }
 
@@ -921,12 +913,9 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
   // Frameworks are handled by cmOSXBundleGenerator.
   if (targetOutPath != targetOutPathReal &&
       !this->GeneratorTarget->IsFrameworkOnApple()) {
-    std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library ";
-    symlink += targetOutPathReal;
-    symlink += " ";
-    symlink += targetOutPathSO;
-    symlink += " ";
-    symlink += targetOutPath;
+    std::string symlink =
+      cmStrCat("$(CMAKE_COMMAND) -E cmake_symlink_library ", targetOutPathReal,
+               ' ', targetOutPathSO, ' ', targetOutPath);
     commands1.push_back(std::move(symlink));
     this->LocalGenerator->CreateCDCommand(
       commands1, this->Makefile->GetCurrentBinaryDirectory(),
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index f35df32..5477e48 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -90,8 +90,8 @@ void cmMakefileTargetGenerator::GetTargetLinkFlags(
   this->LocalGenerator->AppendFlags(
     flags, this->GeneratorTarget->GetProperty("LINK_FLAGS"));
 
-  std::string linkFlagsConfig = "LINK_FLAGS_";
-  linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
+  std::string linkFlagsConfig =
+    cmStrCat("LINK_FLAGS_", cmSystemTools::UpperCase(this->ConfigName));
   this->LocalGenerator->AppendFlags(
     flags, this->GeneratorTarget->GetProperty(linkFlagsConfig));
 
@@ -114,14 +114,13 @@ void cmMakefileTargetGenerator::CreateRuleFile()
   cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull);
 
   // Construct the rule file name.
-  this->BuildFileName = this->TargetBuildDirectory;
-  this->BuildFileName += "/build.make";
-  this->BuildFileNameFull = this->TargetBuildDirectoryFull;
-  this->BuildFileNameFull += "/build.make";
+  this->BuildFileName = cmStrCat(this->TargetBuildDirectory, "/build.make");
+  this->BuildFileNameFull =
+    cmStrCat(this->TargetBuildDirectoryFull, "/build.make");
 
   // Construct the rule file name.
-  this->ProgressFileNameFull = this->TargetBuildDirectoryFull;
-  this->ProgressFileNameFull += "/progress.make";
+  this->ProgressFileNameFull =
+    cmStrCat(this->TargetBuildDirectoryFull, "/progress.make");
 
   // reset the progress count
   this->NumberOfProgressActions = 0;
@@ -260,8 +259,8 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
                         : "");
 
   // Include the dependencies for the target.
-  std::string dependFileNameFull = this->TargetBuildDirectoryFull;
-  dependFileNameFull += "/depend.make";
+  std::string dependFileNameFull =
+    cmStrCat(this->TargetBuildDirectoryFull, "/depend.make");
   *this->BuildFileStream
     << "# Include any dependencies generated for this target.\n"
     << this->GlobalGenerator->IncludeDirective << " " << root
@@ -295,8 +294,8 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
 
   // Open the flags file.  This should be copy-if-different because the
   // rules may depend on this file itself.
-  this->FlagFileNameFull = this->TargetBuildDirectoryFull;
-  this->FlagFileNameFull += "/flags.make";
+  this->FlagFileNameFull =
+    cmStrCat(this->TargetBuildDirectoryFull, "/flags.make");
   this->FlagFileStream =
     new cmGeneratedFileStream(this->FlagFileNameFull, false,
                               this->GlobalGenerator->GetMakefileEncoding());
@@ -325,9 +324,7 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
   // put the compiler in the rules.make file so that if it changes
   // things rebuild
   for (std::string const& language : languages) {
-    std::string compiler = "CMAKE_";
-    compiler += language;
-    compiler += "_COMPILER";
+    std::string compiler = cmStrCat("CMAKE_", language, "_COMPILER");
     *this->FlagFileStream << "# compile " << language << " with "
                           << this->Makefile->GetSafeDefinition(compiler)
                           << "\n";
@@ -362,9 +359,8 @@ void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()(
   std::string const& input = source.GetFullPath();
 
   // Get the output file location.
-  std::string output = macdir;
-  output += "/";
-  output += cmSystemTools::GetFilenameName(input);
+  std::string output =
+    cmStrCat(macdir, '/', cmSystemTools::GetFilenameName(input));
   this->Generator->CleanFiles.insert(
     this->Generator->LocalGenerator->MaybeConvertToRelativePath(
       this->Generator->LocalGenerator->GetCurrentBinaryDirectory(), output));
@@ -375,16 +371,16 @@ void cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()(
   std::vector<std::string> depends;
   std::vector<std::string> commands;
   depends.push_back(input);
-  std::string copyEcho = "Copying OS X content ";
-  copyEcho += output;
+  std::string copyEcho = cmStrCat("Copying OS X content ", output);
   this->Generator->LocalGenerator->AppendEcho(
     commands, copyEcho, cmLocalUnixMakefileGenerator3::EchoBuild);
-  std::string copyCommand = "$(CMAKE_COMMAND) -E copy ";
-  copyCommand += this->Generator->LocalGenerator->ConvertToOutputFormat(
-    input, cmOutputConverter::SHELL);
-  copyCommand += " ";
-  copyCommand += this->Generator->LocalGenerator->ConvertToOutputFormat(
-    output, cmOutputConverter::SHELL);
+  std::string copyCommand =
+    cmStrCat("$(CMAKE_COMMAND) -E copy ",
+             this->Generator->LocalGenerator->ConvertToOutputFormat(
+               input, cmOutputConverter::SHELL),
+             ' ',
+             this->Generator->LocalGenerator->ConvertToOutputFormat(
+               output, cmOutputConverter::SHELL));
   commands.push_back(std::move(copyCommand));
   this->Generator->LocalGenerator->WriteMakeRule(
     *this->Generator->BuildFileStream, nullptr, output, depends, commands,
@@ -407,9 +403,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
   std::string const& objectName =
     this->GeneratorTarget->GetObjectName(&source);
   std::string obj =
-    this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
-  obj += "/";
-  obj += objectName;
+    cmStrCat(this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
+             '/', objectName);
 
   // Avoid generating duplicate rules.
   if (this->ObjectFiles.find(obj) == this->ObjectFiles.end()) {
@@ -445,9 +440,8 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles(
   this->WriteObjectBuildFile(obj, lang, source, depends);
 
   // The object file should be checked for dependency integrity.
-  std::string objFullPath = this->LocalGenerator->GetCurrentBinaryDirectory();
-  objFullPath += "/";
-  objFullPath += obj;
+  std::string objFullPath =
+    cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/', obj);
   objFullPath = cmSystemTools::CollapseFullPath(objFullPath);
   std::string srcFullPath =
     cmSystemTools::CollapseFullPath(source.GetFullPath());
@@ -467,17 +461,15 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
   // generate the depend scanning rule
   this->WriteObjectDependRules(source, depends);
 
-  std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
-  relativeObj += obj;
+  std::string relativeObj =
+    cmStrCat(this->LocalGenerator->GetHomeRelativeOutputPath(), obj);
   // Write the build rule.
 
   // Build the set of compiler flags.
   std::string flags;
 
   // Add language-specific flags.
-  std::string langFlags = "$(";
-  langFlags += lang;
-  langFlags += "_FLAGS)";
+  std::string langFlags = cmStrCat("$(", lang, "_FLAGS)");
   this->LocalGenerator->AppendFlags(flags, langFlags);
 
   std::string config = this->LocalGenerator->GetConfigName();
@@ -539,8 +531,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
                           << "_DEFINES = " << evaluatedDefs << "\n"
                           << "\n";
   }
-  std::string defPropName = "COMPILE_DEFINITIONS_";
-  defPropName += configUpper;
+  std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper);
   if (const char* config_compile_defs = source.GetProperty(defPropName)) {
     const std::string& evaluatedDefs =
       genexInterpreter.Evaluate(config_compile_defs, COMPILE_DEFINITIONS);
@@ -564,10 +555,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
   if (!this->NoRuleMessages) {
     cmLocalUnixMakefileGenerator3::EchoProgress progress;
     this->MakeEchoProgress(progress);
-    std::string buildEcho = "Building ";
-    buildEcho += lang;
-    buildEcho += " object ";
-    buildEcho += relativeObj;
+    std::string buildEcho =
+      cmStrCat("Building ", lang, " object ", relativeObj);
     this->LocalGenerator->AppendEcho(commands, buildEcho,
                                      cmLocalUnixMakefileGenerator3::EchoBuild,
                                      &progress);
@@ -587,9 +576,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
       targetFullPathReal = this->GeneratorTarget->GetFullPath(
         this->ConfigName, cmStateEnums::RuntimeBinaryArtifact, true);
       targetFullPathPDB =
-        this->GeneratorTarget->GetPDBDirectory(this->ConfigName);
-      targetFullPathPDB += "/";
-      targetFullPathPDB += this->GeneratorTarget->GetPDBName(this->ConfigName);
+        cmStrCat(this->GeneratorTarget->GetPDBDirectory(this->ConfigName), '/',
+                 this->GeneratorTarget->GetPDBName(this->ConfigName));
     }
 
     targetOutPathReal = this->LocalGenerator->ConvertToOutputFormat(
@@ -638,9 +626,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
   vars.ObjectFileDir = objectFileDir.c_str();
   vars.Flags = flags.c_str();
 
-  std::string definesString = "$(";
-  definesString += lang;
-  definesString += "_DEFINES)";
+  std::string definesString = cmStrCat("$(", lang, "_DEFINES)");
 
   this->LocalGenerator->JoinDefines(defines, definesString, lang);
 
@@ -798,8 +784,7 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
       const char* val = this->LocalGenerator->GetRuleLauncher(
         this->GeneratorTarget, "RULE_LAUNCH_COMPILE");
       if (val && *val) {
-        launcher = val;
-        launcher += " ";
+        launcher = cmStrCat(val, ' ');
       }
     }
 
@@ -846,16 +831,13 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
       std::string relativeObjI = relativeObjBase + ".i";
       std::string objI = objBase + ".i";
 
-      std::string preprocessEcho = "Preprocessing ";
-      preprocessEcho += lang;
-      preprocessEcho += " source to ";
-      preprocessEcho += objI;
+      std::string preprocessEcho =
+        cmStrCat("Preprocessing ", lang, " source to ", objI);
       this->LocalGenerator->AppendEcho(
         commands, preprocessEcho, cmLocalUnixMakefileGenerator3::EchoBuild);
 
-      std::string preprocessRuleVar = "CMAKE_";
-      preprocessRuleVar += lang;
-      preprocessRuleVar += "_CREATE_PREPROCESSED_SOURCE";
+      std::string preprocessRuleVar =
+        cmStrCat("CMAKE_", lang, "_CREATE_PREPROCESSED_SOURCE");
       if (const char* preprocessRule =
             this->Makefile->GetDefinition(preprocessRuleVar)) {
         std::vector<std::string> preprocessCommands;
@@ -878,8 +860,9 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
           this->LocalGenerator->GetBinaryDirectory());
         cmAppend(commands, preprocessCommands);
       } else {
-        std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
-        cmd += preprocessRuleVar;
+        std::string cmd =
+          cmStrCat("$(CMAKE_COMMAND) -E cmake_unimplemented_variable ",
+                   preprocessRuleVar);
         commands.push_back(std::move(cmd));
       }
 
@@ -893,16 +876,13 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
       std::string relativeObjS = relativeObjBase + ".s";
       std::string objS = objBase + ".s";
 
-      std::string assemblyEcho = "Compiling ";
-      assemblyEcho += lang;
-      assemblyEcho += " source to assembly ";
-      assemblyEcho += objS;
+      std::string assemblyEcho =
+        cmStrCat("Compiling ", lang, " source to assembly ", objS);
       this->LocalGenerator->AppendEcho(
         commands, assemblyEcho, cmLocalUnixMakefileGenerator3::EchoBuild);
 
-      std::string assemblyRuleVar = "CMAKE_";
-      assemblyRuleVar += lang;
-      assemblyRuleVar += "_CREATE_ASSEMBLY_SOURCE";
+      std::string assemblyRuleVar =
+        cmStrCat("CMAKE_", lang, "_CREATE_ASSEMBLY_SOURCE");
       if (const char* assemblyRule =
             this->Makefile->GetDefinition(assemblyRuleVar)) {
         std::vector<std::string> assemblyCommands;
@@ -924,8 +904,9 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile(
           this->LocalGenerator->GetBinaryDirectory());
         cmAppend(commands, assemblyCommands);
       } else {
-        std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
-        cmd += assemblyRuleVar;
+        std::string cmd =
+          cmStrCat("$(CMAKE_COMMAND) -E cmake_unimplemented_variable ",
+                   assemblyRuleVar);
         commands.push_back(std::move(cmd));
       }
 
@@ -942,9 +923,9 @@ void cmMakefileTargetGenerator::WriteTargetCleanRules()
   std::vector<std::string> commands;
 
   // Construct the clean target name.
-  std::string cleanTarget =
-    this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget);
-  cleanTarget += "/clean";
+  std::string cleanTarget = cmStrCat(
+    this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget),
+    "/clean");
 
   // Construct the clean command.
   this->LocalGenerator->AppendCleanCommand(commands, this->CleanFiles,
@@ -1028,8 +1009,7 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
   // must write the targets depend info file
   std::string dir =
     this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
-  this->InfoFileNameFull = dir;
-  this->InfoFileNameFull += "/DependInfo.cmake";
+  this->InfoFileNameFull = cmStrCat(dir, "/DependInfo.cmake");
   this->InfoFileNameFull =
     this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull);
   this->InfoFileStream = new cmGeneratedFileStream(this->InfoFileNameFull);
@@ -1088,9 +1068,9 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
   std::vector<std::string> commands;
 
   // Construct the name of the dependency generation target.
-  std::string depTarget =
-    this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget);
-  depTarget += "/depend";
+  std::string depTarget = cmStrCat(
+    this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget),
+    "/depend");
 
   // Add a command to call CMake to scan dependencies.  CMake will
   // touch the corresponding depends file after scanning dependencies.
@@ -1235,8 +1215,8 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile(
 void cmMakefileTargetGenerator::MakeEchoProgress(
   cmLocalUnixMakefileGenerator3::EchoProgress& progress) const
 {
-  progress.Dir = this->LocalGenerator->GetBinaryDirectory();
-  progress.Dir += "/CMakeFiles";
+  progress.Dir =
+    cmStrCat(this->LocalGenerator->GetBinaryDirectory(), "/CMakeFiles");
   std::ostringstream progressArg;
   progressArg << "$(CMAKE_PROGRESS_" << this->NumberOfProgressActions << ")";
   progress.Arg = progressArg.str();
@@ -1370,8 +1350,8 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule(
   // Compute the name of the driver target.
   std::string dir =
     this->LocalGenerator->GetRelativeTargetDirectory(this->GeneratorTarget);
-  std::string buildTargetRuleName = dir;
-  buildTargetRuleName += relink ? "/preinstall" : "/build";
+  std::string buildTargetRuleName =
+    cmStrCat(dir, relink ? "/preinstall" : "/build");
   buildTargetRuleName = this->LocalGenerator->MaybeConvertToRelativePath(
     this->LocalGenerator->GetBinaryDirectory(), buildTargetRuleName);
 
@@ -1426,8 +1406,7 @@ void cmMakefileTargetGenerator::AppendObjectDepends(
   std::string const& relPath =
     this->LocalGenerator->GetHomeRelativeOutputPath();
   for (std::string const& obj : this->Objects) {
-    std::string objTarget = relPath;
-    objTarget += obj;
+    std::string objTarget = cmStrCat(relPath, obj);
     depends.push_back(std::move(objTarget));
   }
 
@@ -1473,9 +1452,9 @@ std::string cmMakefileTargetGenerator::GetLinkRule(
 {
   std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
   if (this->GeneratorTarget->HasImplibGNUtoMS(this->ConfigName)) {
-    std::string ruleVar = "CMAKE_";
-    ruleVar += this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
-    ruleVar += "_GNUtoMS_RULE";
+    std::string ruleVar = cmStrCat(
+      "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName),
+      "_GNUtoMS_RULE");
     if (const char* rule = this->Makefile->GetDefinition(ruleVar)) {
       linkRule += rule;
     }
@@ -1496,9 +1475,8 @@ void cmMakefileTargetGenerator::CreateLinkScript(
   std::vector<std::string>& makefile_depends)
 {
   // Create the link script file.
-  std::string linkScriptName = this->TargetBuildDirectoryFull;
-  linkScriptName += "/";
-  linkScriptName += name;
+  std::string linkScriptName =
+    cmStrCat(this->TargetBuildDirectoryFull, '/', name);
   cmGeneratedFileStream linkScriptStream(linkScriptName);
   linkScriptStream.SetCopyIfDifferent(true);
   for (std::string const& link_command : link_commands) {
@@ -1510,12 +1488,13 @@ void cmMakefileTargetGenerator::CreateLinkScript(
   }
 
   // Create the makefile command to invoke the link script.
-  std::string link_command = "$(CMAKE_COMMAND) -E cmake_link_script ";
-  link_command += this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), linkScriptName),
-    cmOutputConverter::SHELL);
-  link_command += " --verbose=$(VERBOSE)";
+  std::string link_command = cmStrCat(
+    "$(CMAKE_COMMAND) -E cmake_link_script ",
+    this->LocalGenerator->ConvertToOutputFormat(
+      this->LocalGenerator->MaybeConvertToRelativePath(
+        this->LocalGenerator->GetCurrentBinaryDirectory(), linkScriptName),
+      cmOutputConverter::SHELL),
+    " --verbose=$(VERBOSE)");
   makefile_commands.push_back(std::move(link_command));
   makefile_depends.push_back(std::move(linkScriptName));
 }
@@ -1580,9 +1559,8 @@ std::string cmMakefileTargetGenerator::CreateResponseFile(
   std::vector<std::string>& makefile_depends)
 {
   // Create the response file.
-  std::string responseFileNameFull = this->TargetBuildDirectoryFull;
-  responseFileNameFull += "/";
-  responseFileNameFull += name;
+  std::string responseFileNameFull =
+    cmStrCat(this->TargetBuildDirectoryFull, '/', name);
   cmGeneratedFileStream responseStream(responseFileNameFull);
   responseStream.SetCopyIfDifferent(true);
   responseStream << options << "\n";
@@ -1592,9 +1570,8 @@ std::string cmMakefileTargetGenerator::CreateResponseFile(
   makefile_depends.push_back(std::move(responseFileNameFull));
 
   // Construct the name to be used on the command line.
-  std::string responseFileName = this->TargetBuildDirectory;
-  responseFileName += "/";
-  responseFileName += name;
+  std::string responseFileName =
+    cmStrCat(this->TargetBuildDirectory, '/', name);
   return responseFileName;
 }
 
@@ -1626,10 +1603,9 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
   if (useResponseFile &&
       linkLibs.find_first_not_of(' ') != std::string::npos) {
     // Lookup the response file reference flag.
-    std::string responseFlagVar = "CMAKE_";
-    responseFlagVar +=
-      this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
-    responseFlagVar += "_RESPONSE_FILE_LINK_FLAG";
+    std::string responseFlagVar = cmStrCat(
+      "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName),
+      "_RESPONSE_FILE_LINK_FLAG");
     const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar);
     if (!responseFlag) {
       responseFlag = "@";
@@ -1640,9 +1616,9 @@ void cmMakefileTargetGenerator::CreateLinkLibs(
       this->CreateResponseFile("linklibs.rsp", linkLibs, makefile_depends);
 
     // Reference the response file.
-    linkLibs = responseFlag;
-    linkLibs += this->LocalGenerator->ConvertToOutputFormat(
-      link_rsp, cmOutputConverter::SHELL);
+    linkLibs = cmStrCat(responseFlag,
+                        this->LocalGenerator->ConvertToOutputFormat(
+                          link_rsp, cmOutputConverter::SHELL));
   }
 }
 
@@ -1664,10 +1640,9 @@ void cmMakefileTargetGenerator::CreateObjectLists(
     this->WriteObjectsStrings(object_strings, responseFileLimit);
 
     // Lookup the response file reference flag.
-    std::string responseFlagVar = "CMAKE_";
-    responseFlagVar +=
-      this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
-    responseFlagVar += "_RESPONSE_FILE_LINK_FLAG";
+    std::string responseFlagVar = cmStrCat(
+      "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName),
+      "_RESPONSE_FILE_LINK_FLAG");
     const char* responseFlag = this->Makefile->GetDefinition(responseFlagVar);
     if (!responseFlag) {
       responseFlag = "@";
@@ -1700,20 +1675,16 @@ void cmMakefileTargetGenerator::CreateObjectLists(
       buildObjs = objStrings[0];
     }
   } else {
-    buildObjs = "$(";
-    buildObjs += variableName;
-    buildObjs += ") $(";
-    buildObjs += variableNameExternal;
-    buildObjs += ")";
+    buildObjs =
+      cmStrCat("$(", variableName, ") $(", variableNameExternal, ')');
   }
 }
 
 void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
                                                 const std::string& lang)
 {
-  std::string responseVar = "CMAKE_";
-  responseVar += lang;
-  responseVar += "_USE_RESPONSE_FILE_FOR_INCLUDES";
+  std::string responseVar =
+    cmStrCat("CMAKE_", lang, "_USE_RESPONSE_FILE_FOR_INCLUDES");
   bool useResponseFile = this->Makefile->IsOn(responseVar);
 
   std::vector<std::string> includes;
@@ -1736,9 +1707,7 @@ void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
     if (responseFlag.empty()) {
       responseFlag = "@";
     }
-    std::string name = "includes_";
-    name += lang;
-    name += ".rsp";
+    std::string name = cmStrCat("includes_", lang, ".rsp");
     std::string arg = std::move(responseFlag) +
       this->CreateResponseFile(name.c_str(), includeFlags,
                                this->FlagFileDepends[lang]);
@@ -1757,14 +1726,14 @@ void cmMakefileTargetGenerator::GenDefFile(
     return;
   }
   std::string cmd = cmSystemTools::GetCMakeCommand();
-  cmd =
-    this->LocalGenerator->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL);
-  cmd += " -E __create_def ";
-  cmd += this->LocalGenerator->ConvertToOutputFormat(
-    this->LocalGenerator->MaybeConvertToRelativePath(
-      this->LocalGenerator->GetCurrentBinaryDirectory(), mdi->DefFile),
-    cmOutputConverter::SHELL);
-  cmd += " ";
+  cmd = cmStrCat(
+    this->LocalGenerator->ConvertToOutputFormat(cmd, cmOutputConverter::SHELL),
+    " -E __create_def ",
+    this->LocalGenerator->ConvertToOutputFormat(
+      this->LocalGenerator->MaybeConvertToRelativePath(
+        this->LocalGenerator->GetCurrentBinaryDirectory(), mdi->DefFile),
+      cmOutputConverter::SHELL),
+    ' ');
   std::string objlist_file = mdi->DefFile + ".objs";
   cmd += this->LocalGenerator->ConvertToOutputFormat(
     this->LocalGenerator->MaybeConvertToRelativePath(
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 15c6580..2841245 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -218,8 +218,7 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile)
     const char* val = this->GetLocalGenerator()->GetRuleLauncher(
       this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
     if (val && *val) {
-      launcher = val;
-      launcher += " ";
+      launcher = cmStrCat(val, ' ');
     }
 
     std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
@@ -239,16 +238,10 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile)
     rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds);
 
     // Write the linker rule with response file if needed.
-    rule.Comment = "Rule for linking ";
-    rule.Comment += this->TargetLinkLanguage;
-    rule.Comment += " ";
-    rule.Comment += this->GetVisibleTypeName();
-    rule.Comment += ".";
-    rule.Description = "Linking ";
-    rule.Description += this->TargetLinkLanguage;
-    rule.Description += " ";
-    rule.Description += this->GetVisibleTypeName();
-    rule.Description += " $TARGET_FILE";
+    rule.Comment = cmStrCat("Rule for linking ", this->TargetLinkLanguage, ' ',
+                            this->GetVisibleTypeName(), '.');
+    rule.Description = cmStrCat("Linking ", this->TargetLinkLanguage, ' ',
+                                this->GetVisibleTypeName(), " $TARGET_FILE");
     rule.Restat = "$RESTAT";
 
     this->GetGlobalGenerator()->AddRule(rule);
@@ -282,8 +275,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
 
     std::string responseFlag;
 
-    std::string cmakeVarLang = "CMAKE_";
-    cmakeVarLang += this->TargetLinkLanguage;
+    std::string cmakeVarLang = cmStrCat("CMAKE_", this->TargetLinkLanguage);
 
     // build response file name
     std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG";
@@ -357,8 +349,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
     const char* val = this->GetLocalGenerator()->GetRuleLauncher(
       this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
     if (val && *val) {
-      launcher = val;
-      launcher += " ";
+      launcher = cmStrCat(val, ' ');
     }
 
     std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
@@ -380,16 +371,10 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
     rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds);
 
     // Write the linker rule with response file if needed.
-    rule.Comment = "Rule for linking ";
-    rule.Comment += this->TargetLinkLanguage;
-    rule.Comment += " ";
-    rule.Comment += this->GetVisibleTypeName();
-    rule.Comment += ".";
-    rule.Description = "Linking ";
-    rule.Description += this->TargetLinkLanguage;
-    rule.Description += " ";
-    rule.Description += this->GetVisibleTypeName();
-    rule.Description += " $TARGET_FILE";
+    rule.Comment = cmStrCat("Rule for linking ", this->TargetLinkLanguage, ' ',
+                            this->GetVisibleTypeName(), '.');
+    rule.Description = cmStrCat("Linking ", this->TargetLinkLanguage, ' ',
+                                this->GetVisibleTypeName(), " $TARGET_FILE");
     rule.Restat = "$RESTAT";
     this->GetGlobalGenerator()->AddRule(rule);
   }
@@ -467,19 +452,19 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
     if (linkCmd) {
       std::string linkCmdStr = linkCmd;
       if (this->GetGeneratorTarget()->HasImplibGNUtoMS(this->ConfigName)) {
-        std::string ruleVar = "CMAKE_";
-        ruleVar += this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
-        ruleVar += "_GNUtoMS_RULE";
+        std::string ruleVar = cmStrCat(
+          "CMAKE_", this->GeneratorTarget->GetLinkerLanguage(this->ConfigName),
+          "_GNUtoMS_RULE");
         if (const char* rule = this->Makefile->GetDefinition(ruleVar)) {
           linkCmdStr += rule;
         }
       }
       cmExpandList(linkCmdStr, linkCmds);
       if (this->GetGeneratorTarget()->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
-        std::string cmakeCommand =
+        std::string cmakeCommand = cmStrCat(
           this->GetLocalGenerator()->ConvertToOutputFormat(
-            cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
-        cmakeCommand += " -E __run_co_compile --lwyu=";
+            cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL),
+          " -E __run_co_compile --lwyu=");
         cmGeneratorTarget& gt = *this->GetGeneratorTarget();
         const std::string cfgName = this->GetConfigName();
         std::string targetOutputReal = this->ConvertToNinjaPath(
@@ -502,9 +487,8 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
       }
       // TODO: Use ARCHIVE_APPEND for archives over a certain size.
       {
-        std::string linkCmdVar = "CMAKE_";
-        linkCmdVar += this->TargetLinkLanguage;
-        linkCmdVar += "_ARCHIVE_CREATE";
+        std::string linkCmdVar =
+          cmStrCat("CMAKE_", this->TargetLinkLanguage, "_ARCHIVE_CREATE");
 
         linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
           linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());
@@ -513,9 +497,8 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
         cmExpandList(linkCmd, linkCmds);
       }
       {
-        std::string linkCmdVar = "CMAKE_";
-        linkCmdVar += this->TargetLinkLanguage;
-        linkCmdVar += "_ARCHIVE_FINISH";
+        std::string linkCmdVar =
+          cmStrCat("CMAKE_", this->TargetLinkLanguage, "_ARCHIVE_FINISH");
 
         linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
           linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());
@@ -590,10 +573,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
 
   // Compute the comment.
   cmNinjaBuild build(this->LanguageLinkerDeviceRule());
-  build.Comment = "Link the ";
-  build.Comment += this->GetVisibleTypeName();
-  build.Comment += " ";
-  build.Comment += targetOutputReal;
+  build.Comment =
+    cmStrCat("Link the ", this->GetVisibleTypeName(), ' ', targetOutputReal);
 
   cmNinjaVars& vars = build.Variables;
 
@@ -728,13 +709,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
                                               outpath);
 
     // Calculate the output path
-    targetOutput = outpath;
-    targetOutput += "/";
-    targetOutput += this->TargetNames.Output;
+    targetOutput = cmStrCat(outpath, '/', this->TargetNames.Output);
     targetOutput = this->ConvertToNinjaPath(targetOutput);
-    targetOutputReal = outpath;
-    targetOutputReal += "/";
-    targetOutputReal += this->TargetNames.Real;
+    targetOutputReal = cmStrCat(outpath, '/', this->TargetNames.Real);
     targetOutputReal = this->ConvertToNinjaPath(targetOutputReal);
   } else if (gt->IsFrameworkOnApple()) {
     // Create the library framework.
@@ -757,10 +734,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
   cmNinjaVars& vars = linkBuild.Variables;
 
   // Compute the comment.
-  linkBuild.Comment = "Link the ";
-  linkBuild.Comment += this->GetVisibleTypeName();
-  linkBuild.Comment += " ";
-  linkBuild.Comment += targetOutputReal;
+  linkBuild.Comment =
+    cmStrCat("Link the ", this->GetVisibleTypeName(), ' ', targetOutputReal);
 
   // Compute outputs.
   linkBuild.Outputs.push_back(targetOutputReal);
@@ -990,11 +965,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
     std::string cmakeCommand =
       this->GetLocalGenerator()->ConvertToOutputFormat(
         cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
-    std::string cmd = cmakeCommand;
-    cmd += " -E __create_def ";
-    cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
-      mdi->DefFile, cmOutputConverter::SHELL);
-    cmd += " ";
+    std::string cmd =
+      cmStrCat(cmakeCommand, " -E __create_def ",
+               this->GetLocalGenerator()->ConvertToOutputFormat(
+                 mdi->DefFile, cmOutputConverter::SHELL),
+               ' ');
     std::string obj_list_file = mdi->DefFile + ".objs";
     cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
       obj_list_file, cmOutputConverter::SHELL);
@@ -1039,8 +1014,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
     symlinkVars["POST_BUILD"] = postBuildCmdLine;
   }
 
-  std::string cmakeVarLang = "CMAKE_";
-  cmakeVarLang += this->TargetLinkLanguage;
+  std::string cmakeVarLang = cmStrCat("CMAKE_", this->TargetLinkLanguage);
 
   // build response file name
   std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG";
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 64b2bf6..7b91bd4 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -219,8 +219,8 @@ std::string cmNinjaTargetGenerator::ComputeDefines(cmSourceFile const* source,
       defines, genexInterpreter.Evaluate(compile_defs, COMPILE_DEFINITIONS));
   }
 
-  std::string defPropName = "COMPILE_DEFINITIONS_";
-  defPropName += cmSystemTools::UpperCase(config);
+  std::string defPropName =
+    cmStrCat("COMPILE_DEFINITIONS_", cmSystemTools::UpperCase(config));
   if (const char* config_compile_defs = source->GetProperty(defPropName)) {
     this->LocalGenerator->AppendDefines(
       defines,
@@ -374,10 +374,10 @@ std::string cmNinjaTargetGenerator::GetDyndepFilePath(
 std::string cmNinjaTargetGenerator::GetTargetDependInfoPath(
   std::string const& lang) const
 {
-  std::string path = this->Makefile->GetCurrentBinaryDirectory();
-  path += "/";
-  path += this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
-  path += "/" + lang + "DependInfo.json";
+  std::string path =
+    cmStrCat(this->Makefile->GetCurrentBinaryDirectory(), '/',
+             this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget),
+             '/', lang, "DependInfo.json");
   return path;
 }
 
@@ -416,9 +416,9 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const
         this->GeneratorTarget->GetType() == cmStateEnums::STATIC_LIBRARY ||
         this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
         this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
-      pdbPath = this->GeneratorTarget->GetPDBDirectory(this->GetConfigName());
-      pdbPath += "/";
-      pdbPath += this->GeneratorTarget->GetPDBName(this->GetConfigName());
+      pdbPath = cmStrCat(
+        this->GeneratorTarget->GetPDBDirectory(this->GetConfigName()), '/',
+        this->GeneratorTarget->GetPDBName(this->GetConfigName()));
     }
 
     vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
@@ -488,8 +488,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
   const char* val = this->GetLocalGenerator()->GetRuleLauncher(
     this->GetGeneratorTarget(), "RULE_LAUNCH_COMPILE");
   if (val && *val) {
-    launcher = val;
-    launcher += " ";
+    launcher = cmStrCat(val, ' ');
   }
 
   std::string const cmakeCmd =
@@ -529,12 +528,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
     // If using a response file, move defines, includes, and flags into it.
     if (!responseFlag.empty()) {
       rule.RspFile = "$RSP_FILE";
-      rule.RspContent = " ";
-      rule.RspContent += ppVars.Defines;
-      rule.RspContent += " ";
-      rule.RspContent += ppVars.Includes;
-      rule.RspContent += " ";
-      rule.RspContent += ppFlags;
+      rule.RspContent =
+        cmStrCat(' ', ppVars.Defines, ' ', ppVars.Includes, ' ', ppFlags);
       ppFlags = responseFlag + rule.RspFile;
       ppVars.Defines = "";
       ppVars.Includes = "";
@@ -546,8 +541,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
     std::vector<std::string> ppCmds;
     {
       // Lookup the explicit preprocessing rule.
-      std::string ppVar = "CMAKE_" + lang;
-      ppVar += "_PREPROCESS_SOURCE";
+      std::string ppVar = cmStrCat("CMAKE_", lang, "_PREPROCESS_SOURCE");
       cmExpandList(this->GetMakefile()->GetRequiredDefinition(ppVar), ppCmds);
     }
 
@@ -559,12 +553,9 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
 
     // Run CMake dependency scanner on preprocessed output.
     {
-      std::string ccmd = cmakeCmd;
-      ccmd += " -E cmake_ninja_depends --tdi=";
-      ccmd += tdi;
-      ccmd += " --lang=";
-      ccmd += lang;
-      ccmd += " --pp=$out --dep=$DEP_FILE";
+      std::string ccmd =
+        cmStrCat(cmakeCmd, " -E cmake_ninja_depends --tdi=", tdi,
+                 " --lang=", lang, " --pp=$out --dep=$DEP_FILE");
       if (needDyndep) {
         ccmd += " --obj=$OBJ_FILE --ddi=$DYNDEP_INTERMEDIATE_FILE";
       }
@@ -573,12 +564,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
     rule.Command = this->GetLocalGenerator()->BuildCommandLine(ppCmds);
 
     // Write the rule for preprocessing file of the given language.
-    rule.Comment = "Rule for preprocessing ";
-    rule.Comment += lang;
-    rule.Comment += " files.";
-    rule.Description = "Building ";
-    rule.Description += lang;
-    rule.Description += " preprocessed $out";
+    rule.Comment = cmStrCat("Rule for preprocessing ", lang, " files.");
+    rule.Description = cmStrCat("Building ", lang, " preprocessed $out");
     this->GetGlobalGenerator()->AddRule(rule);
   }
 
@@ -595,24 +582,16 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
     {
       std::vector<std::string> ddCmds;
       {
-        std::string ccmd = cmakeCmd;
-        ccmd += " -E cmake_ninja_dyndep --tdi=";
-        ccmd += tdi;
-        ccmd += " --lang=";
-        ccmd += lang;
-        ccmd += " --dd=$out ";
-        ccmd += "@";
-        ccmd += rule.RspFile;
+        std::string ccmd =
+          cmStrCat(cmakeCmd, " -E cmake_ninja_dyndep --tdi=", tdi,
+                   " --lang=", lang, " --dd=$out @", rule.RspFile);
         ddCmds.emplace_back(std::move(ccmd));
       }
       rule.Command = this->GetLocalGenerator()->BuildCommandLine(ddCmds);
     }
-    rule.Comment = "Rule to generate ninja dyndep files for ";
-    rule.Comment += lang;
-    rule.Comment += ".";
-    rule.Description = "Generating ";
-    rule.Description += lang;
-    rule.Description += " dyndep file $out";
+    rule.Comment =
+      cmStrCat("Rule to generate ninja dyndep files for ", lang, '.');
+    rule.Description = cmStrCat("Generating ", lang, " dyndep file $out");
     this->GetGlobalGenerator()->AddRule(rule);
   }
 
@@ -620,12 +599,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
   // If using a response file, move defines, includes, and flags into it.
   if (!responseFlag.empty()) {
     rule.RspFile = "$RSP_FILE";
-    rule.RspContent = " ";
-    rule.RspContent += vars.Defines;
-    rule.RspContent += " ";
-    rule.RspContent += vars.Includes;
-    rule.RspContent += " ";
-    rule.RspContent += flags;
+    rule.RspContent =
+      cmStrCat(' ', vars.Defines, ' ', vars.Includes, ' ', flags);
     flags = responseFlag + rule.RspFile;
     vars.Defines = "";
     vars.Includes = "";
@@ -648,11 +623,10 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
       const std::string cl = mf->GetDefinition("CMAKE_C_COMPILER")
         ? mf->GetSafeDefinition("CMAKE_C_COMPILER")
         : mf->GetSafeDefinition("CMAKE_CXX_COMPILER");
-      cldeps = "\"";
-      cldeps += cmSystemTools::GetCMClDepsCommand();
-      cldeps += "\" " + lang + " " + vars.Source + " $DEP_FILE $out \"";
-      cldeps += mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX");
-      cldeps += "\" \"" + cl + "\" ";
+      cldeps = cmStrCat('"', cmSystemTools::GetCMClDepsCommand(), "\" ", lang,
+                        ' ', vars.Source, " $DEP_FILE $out \"",
+                        mf->GetSafeDefinition("CMAKE_CL_SHOWINCLUDES_PREFIX"),
+                        "\" \"", cl, "\" ");
     }
   } else {
     rule.DepType = "gcc";
@@ -715,8 +689,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
     const char* cppcheck = this->GeneratorTarget->GetProperty(cppcheck_prop);
     if ((iwyu && *iwyu) || (tidy && *tidy) || (cpplint && *cpplint) ||
         (cppcheck && *cppcheck)) {
-      std::string run_iwyu = cmakeCmd;
-      run_iwyu += " -E __run_co_compile";
+      std::string run_iwyu = cmStrCat(cmakeCmd, " -E __run_co_compile");
       if (!compilerLauncher.empty()) {
         // In __run_co_compile case the launcher command is supplied
         // via --launcher=<maybe-list> and consumed
@@ -777,12 +750,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang)
   rule.Command = this->GetLocalGenerator()->BuildCommandLine(compileCmds);
 
   // Write the rule for compiling file of the given language.
-  rule.Comment = "Rule for compiling ";
-  rule.Comment += lang;
-  rule.Comment += " files.";
-  rule.Description = "Building ";
-  rule.Description += lang;
-  rule.Description += " object $out";
+  rule.Comment = cmStrCat("Rule for compiling ", lang, " files.");
+  rule.Description = cmStrCat("Building ", lang, " object $out");
   this->GetGlobalGenerator()->AddRule(rule);
 }
 
@@ -864,11 +833,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements()
     if (orderOnlyDeps.empty()) {
       // Any path that always exists will work here.  It would be nice to
       // use just "." but that is not supported by Ninja < 1.7.
-      std::string tgtDir;
-      tgtDir += this->LocalGenerator->GetCurrentBinaryDirectory();
-      tgtDir += "/";
-      tgtDir +=
-        this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
+      std::string tgtDir = cmStrCat(
+        this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+        this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget));
       orderOnlyDeps.push_back(this->ConvertToNinjaPath(tgtDir));
     }
 
@@ -945,8 +912,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
   std::string const objectFileDir =
     cmSystemTools::GetFilenamePath(objectFileName);
 
-  std::string cmakeVarLang = "CMAKE_";
-  cmakeVarLang += language;
+  std::string cmakeVarLang = cmStrCat("CMAKE_", language);
 
   // build response file name
   std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_FLAG";
@@ -967,9 +933,8 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
   if (!this->NeedDepTypeMSVC(language)) {
     bool replaceExt(false);
     if (!language.empty()) {
-      std::string repVar = "CMAKE_";
-      repVar += language;
-      repVar += "_DEPFILE_EXTENSION_REPLACE";
+      std::string repVar =
+        cmStrCat("CMAKE_", language, "_DEPFILE_EXTENSION_REPLACE");
       replaceExt = this->Makefile->IsOn(repVar);
     }
     if (!replaceExt) {
@@ -1383,9 +1348,8 @@ void cmNinjaTargetGenerator::MacOSXContentGeneratorType::operator()(
   input = this->Generator->GetGlobalGenerator()->ConvertToNinjaPath(input);
 
   // Get the output file location.
-  std::string output = macdir;
-  output += "/";
-  output += cmSystemTools::GetFilenameName(input);
+  std::string output =
+    cmStrCat(macdir, '/', cmSystemTools::GetFilenameName(input));
   output = this->Generator->GetGlobalGenerator()->ConvertToNinjaPath(output);
 
   // Write a build statement to copy the content into the bundle.
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index 4f0f92b..83a9beb 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -13,6 +13,7 @@
 #include "cmOutputConverter.h"
 #include "cmSourceFile.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <algorithm>
@@ -36,9 +37,9 @@ void cmNinjaUtilityTargetGenerator::Generate()
   cmLocalNinjaGenerator* lg = this->GetLocalGenerator();
   cmGeneratorTarget* genTarget = this->GetGeneratorTarget();
 
-  std::string utilCommandName = lg->GetCurrentBinaryDirectory();
-  utilCommandName += "/CMakeFiles/";
-  utilCommandName += this->GetTargetName() + ".util";
+  std::string utilCommandName =
+    cmStrCat(lg->GetCurrentBinaryDirectory(), "/CMakeFiles/",
+             this->GetTargetName(), ".util");
   utilCommandName = this->ConvertToNinjaPath(utilCommandName);
 
   cmNinjaBuild phonyBuild("phony");
diff --git a/Source/cmOSXBundleGenerator.cxx b/Source/cmOSXBundleGenerator.cxx
index 47a8df4..6175c1e 100644
--- a/Source/cmOSXBundleGenerator.cxx
+++ b/Source/cmOSXBundleGenerator.cxx
@@ -6,6 +6,7 @@
 #include "cmLocalGenerator.h"
 #include "cmMakefile.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 
@@ -40,20 +41,20 @@ void cmOSXBundleGenerator::CreateAppBundle(const std::string& targetName,
   }
 
   // Compute bundle directory names.
-  std::string out = outpath;
-  out += "/";
-  out += this->GT->GetAppBundleDirectory(this->ConfigName,
-                                         cmGeneratorTarget::FullLevel);
+  std::string out =
+    cmStrCat(outpath, '/',
+             this->GT->GetAppBundleDirectory(this->ConfigName,
+                                             cmGeneratorTarget::FullLevel));
   cmSystemTools::MakeDirectory(out);
   this->Makefile->AddCMakeOutputFile(out);
 
   // Configure the Info.plist file.  Note that it needs the executable name
   // to be set.
-  std::string plist = outpath;
-  plist += "/";
-  plist += this->GT->GetAppBundleDirectory(this->ConfigName,
-                                           cmGeneratorTarget::ContentLevel);
-  plist += "/Info.plist";
+  std::string plist =
+    cmStrCat(outpath, '/',
+             this->GT->GetAppBundleDirectory(this->ConfigName,
+                                             cmGeneratorTarget::ContentLevel),
+             "/Info.plist");
   this->LocalGenerator->GenerateAppleInfoPList(this->GT, targetName, plist);
   this->Makefile->AddCMakeOutputFile(plist);
   outpath = out;
@@ -69,10 +70,11 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
   assert(this->MacContentFolders);
 
   // Compute the location of the top-level foo.framework directory.
-  std::string contentdir = outpath + "/" +
-    this->GT->GetFrameworkDirectory(this->ConfigName,
-                                    cmGeneratorTarget::ContentLevel);
-  contentdir += "/";
+  std::string contentdir =
+    cmStrCat(outpath, '/',
+             this->GT->GetFrameworkDirectory(this->ConfigName,
+                                             cmGeneratorTarget::ContentLevel),
+             '/');
 
   std::string newoutpath = outpath + "/" +
     this->GT->GetFrameworkDirectory(this->ConfigName,
@@ -102,8 +104,7 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
   std::string newName;
 
   // Make foo.framework/Versions
-  std::string versions = contentdir;
-  versions += "Versions";
+  std::string versions = cmStrCat(contentdir, "Versions");
   cmSystemTools::MakeDirectory(versions);
 
   // Make foo.framework/Versions/version
@@ -111,17 +112,14 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
 
   // Current -> version
   oldName = frameworkVersion;
-  newName = versions;
-  newName += "/Current";
+  newName = cmStrCat(versions, "/Current");
   cmSystemTools::RemoveFile(newName);
   cmSystemTools::CreateSymlink(oldName, newName);
   this->Makefile->AddCMakeOutputFile(newName);
 
   // foo -> Versions/Current/foo
-  oldName = "Versions/Current/";
-  oldName += name;
-  newName = contentdir;
-  newName += name;
+  oldName = cmStrCat("Versions/Current/", name);
+  newName = cmStrCat(contentdir, name);
   cmSystemTools::RemoveFile(newName);
   cmSystemTools::CreateSymlink(oldName, newName);
   this->Makefile->AddCMakeOutputFile(newName);
@@ -130,8 +128,7 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
   if (this->MacContentFolders->find("Resources") !=
       this->MacContentFolders->end()) {
     oldName = "Versions/Current/Resources";
-    newName = contentdir;
-    newName += "Resources";
+    newName = cmStrCat(contentdir, "Resources");
     cmSystemTools::RemoveFile(newName);
     cmSystemTools::CreateSymlink(oldName, newName);
     this->Makefile->AddCMakeOutputFile(newName);
@@ -141,8 +138,7 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
   if (this->MacContentFolders->find("Headers") !=
       this->MacContentFolders->end()) {
     oldName = "Versions/Current/Headers";
-    newName = contentdir;
-    newName += "Headers";
+    newName = cmStrCat(contentdir, "Headers");
     cmSystemTools::RemoveFile(newName);
     cmSystemTools::CreateSymlink(oldName, newName);
     this->Makefile->AddCMakeOutputFile(newName);
@@ -152,8 +148,7 @@ void cmOSXBundleGenerator::CreateFramework(const std::string& targetName,
   if (this->MacContentFolders->find("PrivateHeaders") !=
       this->MacContentFolders->end()) {
     oldName = "Versions/Current/PrivateHeaders";
-    newName = contentdir;
-    newName += "PrivateHeaders";
+    newName = cmStrCat(contentdir, "PrivateHeaders");
     cmSystemTools::RemoveFile(newName);
     cmSystemTools::CreateSymlink(oldName, newName);
     this->Makefile->AddCMakeOutputFile(newName);
@@ -168,19 +163,20 @@ void cmOSXBundleGenerator::CreateCFBundle(const std::string& targetName,
   }
 
   // Compute bundle directory names.
-  std::string out = root;
-  out += "/";
-  out += this->GT->GetCFBundleDirectory(this->ConfigName,
-                                        cmGeneratorTarget::FullLevel);
+  std::string out =
+    cmStrCat(root, '/',
+             this->GT->GetCFBundleDirectory(this->ConfigName,
+                                            cmGeneratorTarget::FullLevel));
   cmSystemTools::MakeDirectory(out);
   this->Makefile->AddCMakeOutputFile(out);
 
   // Configure the Info.plist file.  Note that it needs the executable name
   // to be set.
-  std::string plist = root + "/" +
-    this->GT->GetCFBundleDirectory(this->ConfigName,
-                                   cmGeneratorTarget::ContentLevel);
-  plist += "/Info.plist";
+  std::string plist =
+    cmStrCat(root, '/',
+             this->GT->GetCFBundleDirectory(this->ConfigName,
+                                            cmGeneratorTarget::ContentLevel),
+             "/Info.plist");
   std::string name = cmSystemTools::GetFilenameName(targetName);
   this->LocalGenerator->GenerateAppleInfoPList(this->GT, name, plist);
   this->Makefile->AddCMakeOutputFile(plist);
@@ -208,10 +204,10 @@ std::string cmOSXBundleGenerator::InitMacOSXContentDirectory(
 {
   // Construct the full path to the content subdirectory.
 
-  std::string macdir = this->GT->GetMacContentDirectory(
-    this->ConfigName, cmStateEnums::RuntimeBinaryArtifact);
-  macdir += "/";
-  macdir += pkgloc;
+  std::string macdir =
+    cmStrCat(this->GT->GetMacContentDirectory(
+               this->ConfigName, cmStateEnums::RuntimeBinaryArtifact),
+             '/', pkgloc);
   cmSystemTools::MakeDirectory(macdir);
 
   // Record use of this content location.  Only the first level
diff --git a/Source/cmOptionCommand.cxx b/Source/cmOptionCommand.cxx
index 21841c8..a0a0989 100644
--- a/Source/cmOptionCommand.cxx
+++ b/Source/cmOptionCommand.cxx
@@ -19,8 +19,8 @@ bool cmOptionCommand(std::vector<std::string> const& args,
 {
   const bool argError = (args.size() < 2) || (args.size() > 3);
   if (argError) {
-    std::string m = "called with incorrect number of arguments: ";
-    m += cmJoin(args, " ");
+    std::string m = cmStrCat("called with incorrect number of arguments: ",
+                             cmJoin(args, " "));
     status.SetError(m);
     return false;
   }
diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx
index 2d055ff..21a17e8 100644
--- a/Source/cmOrderDirectories.cxx
+++ b/Source/cmOrderDirectories.cxx
@@ -6,6 +6,7 @@
 #include "cmGeneratorTarget.h"
 #include "cmGlobalGenerator.h"
 #include "cmMessageType.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmake.h"
 
@@ -117,9 +118,7 @@ bool cmOrderDirectoriesConstraint::FileMayConflict(std::string const& dir,
                                                    std::string const& name)
 {
   // Check if the file exists on disk.
-  std::string file = dir;
-  file += "/";
-  file += name;
+  std::string file = cmStrCat(dir, '/', name);
   if (cmSystemTools::FileExists(file, true)) {
     // The file conflicts only if it is not the same as the original
     // file due to a symlink or hardlink.
@@ -229,8 +228,7 @@ bool cmOrderDirectoriesConstraintLibrary::FindConflict(std::string const& dir)
     std::string ext = this->OD->RemoveLibraryExtension.match(2);
     for (std::string const& LinkExtension : this->OD->LinkExtensions) {
       if (LinkExtension != ext) {
-        std::string fname = lib;
-        fname += LinkExtension;
+        std::string fname = cmStrCat(lib, LinkExtension);
         if (this->FileMayConflict(dir, fname)) {
           return true;
         }
diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx
index de47ce0..38e86e3 100644
--- a/Source/cmOutputRequiredFilesCommand.cxx
+++ b/Source/cmOutputRequiredFilesCommand.cxx
@@ -193,10 +193,8 @@ protected:
         // see if the include matches the regular expression
         if (!this->IncludeFileRegularExpression.find(includeFile)) {
           if (this->Verbose) {
-            std::string message = "Skipping ";
-            message += includeFile;
-            message += " for file ";
-            message += info->FullPath;
+            std::string message =
+              cmStrCat("Skipping ", includeFile, " for file ", info->FullPath);
             cmSystemTools::Error(message);
           }
           continue;
diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx
index 96d9843..f8c5ada 100644
--- a/Source/cmProjectCommand.cxx
+++ b/Source/cmProjectCommand.cxx
@@ -102,11 +102,10 @@ bool cmProjectCommand::InitialPass(std::vector<std::string> const& args,
       }
       doing = DoingLanguages;
       if (!languages.empty()) {
-        std::string msg =
+        std::string msg = cmStrCat(
           "the following parameters must be specified after LANGUAGES "
-          "keyword: ";
-        msg += cmJoin(languages, ", ");
-        msg += '.';
+          "keyword: ",
+          cmJoin(languages, ", "), '.');
         this->Makefile->IssueMessage(MessageType::WARNING, msg);
       }
     } else if (args[i] == "VERSION") {
@@ -368,9 +367,9 @@ bool cmProjectCommand::IncludeByVariable(const std::string& variable)
     return true;
   }
 
-  std::string m = "could not find file:\n"
-                  "  ";
-  m += include;
+  std::string m = cmStrCat("could not find file:\n"
+                           "  ",
+                           include);
   this->SetError(m);
   return false;
 }
diff --git a/Source/cmQTWrapCPPCommand.cxx b/Source/cmQTWrapCPPCommand.cxx
index f5852a9..ba82813 100644
--- a/Source/cmQTWrapCPPCommand.cxx
+++ b/Source/cmQTWrapCPPCommand.cxx
@@ -6,6 +6,7 @@
 #include "cmMakefile.h"
 #include "cmRange.h"
 #include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <utility>
@@ -37,10 +38,8 @@ bool cmQTWrapCPPCommand::InitialPass(std::vector<std::string> const& args,
       // Compute the name of the file to generate.
       std::string srcName =
         cmSystemTools::GetFilenameWithoutLastExtension(arg);
-      std::string newName = this->Makefile->GetCurrentBinaryDirectory();
-      newName += "/moc_";
-      newName += srcName;
-      newName += ".cxx";
+      std::string newName = cmStrCat(
+        this->Makefile->GetCurrentBinaryDirectory(), "/moc_", srcName, ".cxx");
       cmSourceFile* sf = this->Makefile->GetOrCreateSource(newName, true);
       if (curr) {
         sf->SetProperty("ABSTRACT", curr->GetProperty("ABSTRACT"));
diff --git a/Source/cmQTWrapUICommand.cxx b/Source/cmQTWrapUICommand.cxx
index 361d7b3..8bc914f 100644
--- a/Source/cmQTWrapUICommand.cxx
+++ b/Source/cmQTWrapUICommand.cxx
@@ -6,6 +6,7 @@
 #include "cmMakefile.h"
 #include "cmRange.h"
 #include "cmSourceFile.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <utility>
@@ -41,18 +42,12 @@ bool cmQTWrapUICommand::InitialPass(std::vector<std::string> const& args,
       // Compute the name of the files to generate.
       std::string srcName =
         cmSystemTools::GetFilenameWithoutLastExtension(arg);
-      std::string hName = this->Makefile->GetCurrentBinaryDirectory();
-      hName += "/";
-      hName += srcName;
-      hName += ".h";
-      std::string cxxName = this->Makefile->GetCurrentBinaryDirectory();
-      cxxName += "/";
-      cxxName += srcName;
-      cxxName += ".cxx";
-      std::string mocName = this->Makefile->GetCurrentBinaryDirectory();
-      mocName += "/moc_";
-      mocName += srcName;
-      mocName += ".cxx";
+      std::string hName = cmStrCat(this->Makefile->GetCurrentBinaryDirectory(),
+                                   '/', srcName, ".h");
+      std::string cxxName = cmStrCat(
+        this->Makefile->GetCurrentBinaryDirectory(), '/', srcName, ".cxx");
+      std::string mocName = cmStrCat(
+        this->Makefile->GetCurrentBinaryDirectory(), "/moc_", srcName, ".cxx");
 
       // Compute the name of the ui file from which to generate others.
       std::string uiName;
diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx
index fe04fba..9d29e5c 100644
--- a/Source/cmQtAutoGen.cxx
+++ b/Source/cmQtAutoGen.cxx
@@ -292,9 +292,8 @@ static bool RccListParseOutput(std::string const& rccStdOut,
 
         std::string::size_type pos = eline.find(searchString);
         if (pos == std::string::npos) {
-          error = "rcc lists unparsable output:\n";
-          error += cmQtAutoGen::Quoted(eline);
-          error += "\n";
+          error = cmStrCat("rcc lists unparsable output:\n",
+                           cmQtAutoGen::Quoted(eline), '\n');
           return false;
         }
         pos += searchString.length();
@@ -323,9 +322,8 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile,
   error.clear();
 
   if (!cmSystemTools::FileExists(qrcFile, true)) {
-    error = "The resource file ";
-    error += Quoted(qrcFile);
-    error += " does not exist.";
+    error =
+      cmStrCat("The resource file ", Quoted(qrcFile), " does not exist.");
     return false;
   }
 
@@ -361,9 +359,8 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile,
         cmSystemTools::OUTPUT_NONE, cmDuration::zero(), cmProcessOutput::Auto);
     }
     if (!result || retVal) {
-      error = "The rcc list process failed for ";
-      error += Quoted(qrcFile);
-      error += "\n";
+      error =
+        cmStrCat("The rcc list process failed for ", Quoted(qrcFile), '\n');
       if (!rccStdOut.empty()) {
         error += rccStdOut;
         error += "\n";
@@ -389,9 +386,8 @@ bool cmQtAutoGen::RccLister::list(std::string const& qrcFile,
           osst << ifs.rdbuf();
           qrcContents = osst.str();
         } else {
-          error = "The resource file ";
-          error += Quoted(qrcFile);
-          error += " is not readable\n";
+          error = cmStrCat("The resource file ", Quoted(qrcFile),
+                           " is not readable\n");
           return false;
         }
       }
diff --git a/Source/cmQtAutoGenGlobalInitializer.cxx b/Source/cmQtAutoGenGlobalInitializer.cxx
index 21de8c6..abc69d0 100644
--- a/Source/cmQtAutoGenGlobalInitializer.cxx
+++ b/Source/cmQtAutoGenGlobalInitializer.cxx
@@ -211,11 +211,8 @@ cmQtAutoGenGlobalInitializer::GetCompilerFeatures(
 
   // Check if the executable exists
   if (!cmSystemTools::FileExists(executable, true)) {
-    error = "The \"";
-    error += generator;
-    error += "\" executable ";
-    error += cmQtAutoGen::Quoted(executable);
-    error += " does not exist.";
+    error = cmStrCat("The \"", generator, "\" executable ",
+                     cmQtAutoGen::Quoted(executable), " does not exist.");
     return cmQtAutoGen::CompilerFeaturesHandle();
   }
 
@@ -231,15 +228,10 @@ cmQtAutoGenGlobalInitializer::GetCompilerFeatures(
       command, &stdOut, &stdErr, &retVal, nullptr, cmSystemTools::OUTPUT_NONE,
       cmDuration::zero(), cmProcessOutput::Auto);
     if (!runResult) {
-      error = "Test run of \"";
-      error += generator;
-      error += "\" executable ";
-      error += cmQtAutoGen::Quoted(executable) + " failed.\n";
-      error += cmQtAutoGen::QuotedCommand(command);
-      error += "\n";
-      error += stdOut;
-      error += "\n";
-      error += stdErr;
+      error = cmStrCat("Test run of \"", generator, "\" executable ",
+                       cmQtAutoGen::Quoted(executable), " failed.\n",
+                       cmQtAutoGen::QuotedCommand(command), '\n', stdOut, '\n',
+                       stdErr);
       return cmQtAutoGen::CompilerFeaturesHandle();
     }
   }
diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx
index d21fc61..6718466 100644
--- a/Source/cmQtAutoGenInitializer.cxx
+++ b/Source/cmQtAutoGenInitializer.cxx
@@ -293,19 +293,15 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
       std::string(), makefile->GetCurrentBinaryDirectory());
 
     // Info directory
-    this->Dir.Info = cbd;
-    this->Dir.Info += "/CMakeFiles/";
-    this->Dir.Info += this->Target->GetName();
-    this->Dir.Info += "_autogen.dir";
+    this->Dir.Info =
+      cmStrCat(cbd, "/CMakeFiles/", this->Target->GetName(), "_autogen.dir");
     cmSystemTools::ConvertToUnixSlashes(this->Dir.Info);
 
     // Build directory
     this->Dir.Build = this->Target->GetSafeProperty("AUTOGEN_BUILD_DIR");
     if (this->Dir.Build.empty()) {
-      this->Dir.Build = cbd;
-      this->Dir.Build += '/';
-      this->Dir.Build += this->Target->GetName();
-      this->Dir.Build += "_autogen";
+      this->Dir.Build =
+        cmStrCat(cbd, '/', this->Target->GetName(), "_autogen");
     }
     cmSystemTools::ConvertToUnixSlashes(this->Dir.Build);
     // Cleanup build directory
@@ -316,8 +312,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
     cmSystemTools::ConvertToUnixSlashes(this->Dir.Work);
 
     // Include directory
-    this->Dir.Include = this->Dir.Build;
-    this->Dir.Include += "/include";
+    this->Dir.Include = cmStrCat(this->Dir.Build, "/include");
     if (this->MultiConfig) {
       this->Dir.Include += "_$<CONFIG>";
     }
@@ -325,9 +320,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
     if (this->MultiConfig) {
       for (std::string const& cfg : this->ConfigsList) {
         std::string& dir = this->Dir.ConfigInclude[cfg];
-        dir = this->Dir.Build;
-        dir += "/include_";
-        dir += cfg;
+        dir = cmStrCat(this->Dir.Build, "/include_", cfg);
       }
     }
   }
@@ -345,8 +338,7 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
     }
 
     // Autogen target name
-    this->AutogenTarget.Name = this->Target->GetName();
-    this->AutogenTarget.Name += "_autogen";
+    this->AutogenTarget.Name = cmStrCat(this->Target->GetName(), "_autogen");
 
     // Autogen target parallel processing
     this->AutogenTarget.Parallel =
@@ -359,11 +351,11 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
 
     // Autogen target info and settings files
     {
-      this->AutogenTarget.InfoFile = this->Dir.Info;
-      this->AutogenTarget.InfoFile += "/AutogenInfo.cmake";
+      this->AutogenTarget.InfoFile =
+        cmStrCat(this->Dir.Info, "/AutogenInfo.cmake");
 
-      this->AutogenTarget.SettingsFile = this->Dir.Info;
-      this->AutogenTarget.SettingsFile += "/AutogenOldSettings.txt";
+      this->AutogenTarget.SettingsFile =
+        cmStrCat(this->Dir.Info, "/AutogenOldSettings.txt");
 
       if (this->MultiConfig) {
         for (std::string const& cfg : this->ConfigsList) {
@@ -376,8 +368,8 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
         this->AddCleanFile(this->AutogenTarget.SettingsFile);
       }
 
-      this->AutogenTarget.ParseCacheFile = this->Dir.Info;
-      this->AutogenTarget.ParseCacheFile += "/ParseCache.txt";
+      this->AutogenTarget.ParseCacheFile =
+        cmStrCat(this->Dir.Info, "/ParseCache.txt");
       this->AddCleanFile(this->AutogenTarget.ParseCacheFile);
     }
 
@@ -406,11 +398,11 @@ bool cmQtAutoGenInitializer::InitCustomTargets()
     // CMAKE_AUTOMOC_RELAXED_MODE deprecation warning
     if (this->Moc.Enabled) {
       if (cmIsOn(makefile->GetDefinition("CMAKE_AUTOMOC_RELAXED_MODE"))) {
-        std::string msg = "AUTOMOC: CMAKE_AUTOMOC_RELAXED_MODE is "
-                          "deprecated an will be removed in the future.  ";
-        msg += "Consider disabling it and converting the target ";
-        msg += this->Target->GetName();
-        msg += " to regular mode.";
+        std::string msg =
+          cmStrCat("AUTOMOC: CMAKE_AUTOMOC_RELAXED_MODE is "
+                   "deprecated an will be removed in the future.  Consider "
+                   "disabling it and converting the target ",
+                   this->Target->GetName(), " to regular mode.");
         makefile->IssueMessage(MessageType::AUTHOR_WARNING, msg);
       }
     }
@@ -450,8 +442,8 @@ bool cmQtAutoGenInitializer::InitMoc()
   cmLocalGenerator* localGen = this->Target->GetLocalGenerator();
 
   // Mocs compilation file
-  this->Moc.MocsCompilation = this->Dir.Build;
-  this->Moc.MocsCompilation += "/mocs_compilation.cpp";
+  this->Moc.MocsCompilation =
+    cmStrCat(this->Dir.Build, "/mocs_compilation.cpp");
 
   // Moc predefs command
   if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") &&
@@ -886,14 +878,11 @@ bool cmQtAutoGenInitializer::InitScanFiles()
             base += qrc.PathChecksum;
           }
 
-          qrc.LockFile = base;
-          qrc.LockFile += ".lock";
+          qrc.LockFile = cmStrCat(base, ".lock");
 
-          qrc.InfoFile = base;
-          qrc.InfoFile += "Info.cmake";
+          qrc.InfoFile = cmStrCat(base, "Info.cmake");
 
-          qrc.SettingsFile = base;
-          qrc.SettingsFile += "Settings.txt";
+          qrc.SettingsFile = cmStrCat(base, "Settings.txt");
 
           if (this->MultiConfig) {
             for (std::string const& cfg : this->ConfigsList) {
@@ -971,10 +960,8 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
       }
       tools += "UIC";
     }
-    autogenComment = "Automatic ";
-    autogenComment += tools;
-    autogenComment += " for target ";
-    autogenComment += this->Target->GetName();
+    autogenComment =
+      cmStrCat("Automatic ", tools, " for target ", this->Target->GetName());
   }
 
   // Compose command lines
@@ -1145,9 +1132,7 @@ bool cmQtAutoGenInitializer::InitRccTargets()
       // Create custom rcc target
       std::string ccName;
       {
-        ccName = this->Target->GetName();
-        ccName += "_arcc_";
-        ccName += qrc.QrcName;
+        ccName = cmStrCat(this->Target->GetName(), "_arcc_", qrc.QrcName);
         if (!qrc.Unique) {
           ccName += "_";
           ccName += qrc.PathChecksum;
diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx
index 0e8fa9a..90361a9 100644
--- a/Source/cmQtAutoGenerator.cxx
+++ b/Source/cmQtAutoGenerator.cxx
@@ -298,8 +298,7 @@ bool cmQtAutoGenerator::Run(std::string const& infoFile,
 std::string cmQtAutoGenerator::SettingsFind(std::string const& content,
                                             const char* key)
 {
-  std::string prefix(key);
-  prefix += ':';
+  std::string prefix = cmStrCat(key, ':');
   std::string::size_type pos = content.find(prefix);
   if (pos != std::string::npos) {
     pos += prefix.size();
diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx
index 7148fc1..a82dd3a 100644
--- a/Source/cmQtAutoMocUic.cxx
+++ b/Source/cmQtAutoMocUic.cxx
@@ -344,9 +344,8 @@ bool cmQtAutoMocUic::JobMocPredefsT::Update(std::string* reason) const
   // Test if the file exists
   if (!MocEval().PredefsTime.Load(MocConst().PredefsFileAbs)) {
     if (reason != nullptr) {
-      *reason = "Generating ";
-      *reason += Quoted(MocConst().PredefsFileRel);
-      *reason += ", because it doesn't exist.";
+      *reason = cmStrCat("Generating ", Quoted(MocConst().PredefsFileRel),
+                         ", because it doesn't exist.");
     }
     return true;
   }
@@ -354,9 +353,8 @@ bool cmQtAutoMocUic::JobMocPredefsT::Update(std::string* reason) const
   // Test if the settings changed
   if (MocConst().SettingsChanged) {
     if (reason != nullptr) {
-      *reason = "Generating ";
-      *reason += Quoted(MocConst().PredefsFileRel);
-      *reason += ", because the moc settings changed.";
+      *reason = cmStrCat("Generating ", Quoted(MocConst().PredefsFileRel),
+                         ", because the moc settings changed.");
     }
     return true;
   }
@@ -368,11 +366,8 @@ bool cmQtAutoMocUic::JobMocPredefsT::Update(std::string* reason) const
     if (execTime.Load(exec)) {
       if (MocEval().PredefsTime.Older(execTime)) {
         if (reason != nullptr) {
-          *reason = "Generating ";
-          *reason += Quoted(MocConst().PredefsFileRel);
-          *reason += " because it is older than ";
-          *reason += Quoted(exec);
-          *reason += ".";
+          *reason = cmStrCat("Generating ", Quoted(MocConst().PredefsFileRel),
+                             " because it is older than ", Quoted(exec), '.');
         }
         return true;
       }
@@ -676,11 +671,11 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource(
     SourceFileHandleT header = MocFindIncludedHeader(sourceDir, headerBase);
     if (!header) {
       {
-        std::string msg = "The file includes the moc file ";
-        msg += Quoted(incKey.Key);
-        msg += ",\nbut the header could not be found "
-               "in the following locations\n";
-        msg += MocMessageTestHeaders(headerBase);
+        std::string msg =
+          cmStrCat("The file includes the moc file ", Quoted(incKey.Key),
+                   ",\nbut the header could not be found "
+                   "in the following locations\n",
+                   MocMessageTestHeaders(headerBase));
         LogFileError(GenT::MOC, sourceFile.FileName, msg);
       }
       return false;
@@ -740,12 +735,12 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource(
       std::string const headerBase = incKey.Dir + incKey.Base;
       SourceFileHandleT header = MocFindIncludedHeader(sourceDir, headerBase);
       if (!header) {
-        std::string msg = "The file includes the moc file ";
-        msg += Quoted(incKey.Key);
-        msg += ",\nwhich seems to be the moc file from a different source "
-               "file.\nCMAKE_AUTOMOC_RELAXED_MODE: Also a matching header"
-               "could not be found in the following locations\n";
-        msg += MocMessageTestHeaders(headerBase);
+        std::string msg =
+          cmStrCat("The file includes the moc file ", Quoted(incKey.Key),
+                   ",\nwhich seems to be the moc file from a different source "
+                   "file.\nCMAKE_AUTOMOC_RELAXED_MODE: Also a matching header"
+                   "could not be found in the following locations\n",
+                   MocMessageTestHeaders(headerBase));
         LogFileError(GenT::MOC, sourceFile.FileName, msg);
         return false;
       }
@@ -785,12 +780,11 @@ bool cmQtAutoMocUic::JobEvaluateT::MocEvalSource(
       bool const ownMoc = (incKey.Base == sourceBase);
       if (!ownMoc) {
         // Don't allow <BASE>.moc include other than own in regular mode
-        std::string msg = "The file includes the moc file ";
-        msg += Quoted(incKey.Key);
-        msg += ",\nwhich seems to be the moc file from a different "
-               "source file.\nThis is not supported.  Include ";
-        msg += Quoted(sourceBase + ".moc");
-        msg += " to run moc on this source file.";
+        std::string msg = cmStrCat(
+          "The file includes the moc file ", Quoted(incKey.Key),
+          ",\nwhich seems to be the moc file from a different "
+          "source file.\nThis is not supported.  Include ",
+          Quoted(sourceBase + ".moc"), " to run moc on this source file.");
         LogFileError(GenT::MOC, sourceFile.FileName, msg);
         return false;
       }
@@ -1172,10 +1166,9 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
   cmFileTime outputFileTime;
   if (!outputFileTime.Load(outputFile)) {
     if (reason != nullptr) {
-      *reason = "Generating ";
-      *reason += Quoted(outputFile);
-      *reason += ", because it doesn't exist, from ";
-      *reason += Quoted(sourceFile);
+      *reason =
+        cmStrCat("Generating ", Quoted(outputFile),
+                 ", because it doesn't exist, from ", Quoted(sourceFile));
     }
     return true;
   }
@@ -1183,10 +1176,9 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
   // Test if any setting changed
   if (MocConst().SettingsChanged) {
     if (reason != nullptr) {
-      *reason = "Generating ";
-      *reason += Quoted(outputFile);
-      *reason += ", because the uic settings changed, from ";
-      *reason += Quoted(sourceFile);
+      *reason = cmStrCat("Generating ", Quoted(outputFile),
+                         ", because the uic settings changed, from ",
+                         Quoted(sourceFile));
     }
     return true;
   }
@@ -1194,10 +1186,9 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
   // Test if the source file is newer
   if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
     if (reason != nullptr) {
-      *reason = "Generating ";
-      *reason += Quoted(outputFile);
-      *reason += ", because it's older than its source file, from ";
-      *reason += Quoted(sourceFile);
+      *reason = cmStrCat("Generating ", Quoted(outputFile),
+                         ", because it's older than its source file, from ",
+                         Quoted(sourceFile));
     }
     return true;
   }
@@ -1206,12 +1197,9 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
   if (!MocConst().PredefsFileAbs.empty()) {
     if (outputFileTime.Older(MocEval().PredefsTime)) {
       if (reason != nullptr) {
-        *reason = "Generating ";
-        *reason += Quoted(outputFile);
-        *reason += ", because it's older than ";
-        *reason += Quoted(MocConst().PredefsFileAbs);
-        *reason += ", from ";
-        *reason += Quoted(sourceFile);
+        *reason = cmStrCat(
+          "Generating ", Quoted(outputFile), ", because it's older than ",
+          Quoted(MocConst().PredefsFileAbs), ", from ", Quoted(sourceFile));
       }
       return true;
     }
@@ -1220,10 +1208,9 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
   // Test if the moc executable is newer
   if (outputFileTime.Older(MocConst().ExecutableTime)) {
     if (reason != nullptr) {
-      *reason = "Generating ";
-      *reason += Quoted(outputFile);
-      *reason += ", because it's older than the moc executable, from ";
-      *reason += Quoted(sourceFile);
+      *reason = cmStrCat("Generating ", Quoted(outputFile),
+                         ", because it's older than the moc executable, from ",
+                         Quoted(sourceFile));
     }
     return true;
   }
@@ -1243,12 +1230,10 @@ bool cmQtAutoMocUic::JobGenerateT::MocUpdate(MappingT const& mapping,
       // Test if dependency file is older
       if (outputFileTime.Older(depMatch.second)) {
         if (reason != nullptr) {
-          *reason = "Generating ";
-          *reason += Quoted(outputFile);
-          *reason += ", because it's older than its dependency file ";
-          *reason += Quoted(depMatch.first);
-          *reason += ", from ";
-          *reason += Quoted(sourceFile);
+          *reason =
+            cmStrCat("Generating ", Quoted(outputFile),
+                     ", because it's older than its dependency file ",
+                     Quoted(depMatch.first), ", from ", Quoted(sourceFile));
         }
         return true;
       }
@@ -1313,10 +1298,9 @@ bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping,
   cmFileTime outputFileTime;
   if (!outputFileTime.Load(outputFile)) {
     if (reason != nullptr) {
-      *reason = "Generating ";
-      *reason += Quoted(outputFile);
-      *reason += ", because it doesn't exist, from ";
-      *reason += Quoted(sourceFile);
+      *reason =
+        cmStrCat("Generating ", Quoted(outputFile),
+                 ", because it doesn't exist, from ", Quoted(sourceFile));
     }
     return true;
   }
@@ -1324,10 +1308,9 @@ bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping,
   // Test if the uic settings changed
   if (UicConst().SettingsChanged) {
     if (reason != nullptr) {
-      *reason = "Generating ";
-      *reason += Quoted(outputFile);
-      *reason += ", because the uic settings changed, from ";
-      *reason += Quoted(sourceFile);
+      *reason = cmStrCat("Generating ", Quoted(outputFile),
+                         ", because the uic settings changed, from ",
+                         Quoted(sourceFile));
     }
     return true;
   }
@@ -1335,10 +1318,9 @@ bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping,
   // Test if the source file is newer
   if (outputFileTime.Older(mapping.SourceFile->FileTime)) {
     if (reason != nullptr) {
-      *reason = "Generating ";
-      *reason += Quoted(outputFile);
-      *reason += " because it's older than the source file ";
-      *reason += Quoted(sourceFile);
+      *reason = cmStrCat("Generating ", Quoted(outputFile),
+                         " because it's older than the source file ",
+                         Quoted(sourceFile));
     }
     return true;
   }
@@ -1346,10 +1328,9 @@ bool cmQtAutoMocUic::JobGenerateT::UicUpdate(MappingT const& mapping,
   // Test if the uic executable is newer
   if (outputFileTime.Older(UicConst().ExecutableTime)) {
     if (reason != nullptr) {
-      *reason = "Generating ";
-      *reason += Quoted(outputFile);
-      *reason += ", because it's older than the uic executable, from ";
-      *reason += Quoted(sourceFile);
+      *reason = cmStrCat("Generating ", Quoted(outputFile),
+                         ", because it's older than the uic executable, from ",
+                         Quoted(sourceFile));
     }
     return true;
   }
diff --git a/Source/cmQtAutoRcc.cxx b/Source/cmQtAutoRcc.cxx
index ea3cad9..f15634c 100644
--- a/Source/cmQtAutoRcc.cxx
+++ b/Source/cmQtAutoRcc.cxx
@@ -122,17 +122,12 @@ bool cmQtAutoRcc::Init(cmMakefile* makefile)
   // Init derived information
   // ------------------------
 
-  RccFilePublic_ = AutogenBuildDir_;
-  RccFilePublic_ += '/';
-  RccFilePublic_ += RccPathChecksum_;
-  RccFilePublic_ += '/';
-  RccFilePublic_ += RccFileName_;
+  RccFilePublic_ =
+    cmStrCat(AutogenBuildDir_, '/', RccPathChecksum_, '/', RccFileName_);
 
   // Compute rcc output file name
   if (IsMultiConfig()) {
-    RccFileOutput_ = IncludeDir_;
-    RccFileOutput_ += '/';
-    RccFileOutput_ += MultiConfigOutput();
+    RccFileOutput_ = cmStrCat(IncludeDir_, '/', MultiConfigOutput());
   } else {
     RccFileOutput_ = RccFilePublic_;
   }
@@ -188,21 +183,10 @@ bool cmQtAutoRcc::SettingsFileRead()
     cmCryptoHash crypt(cmCryptoHash::AlgoSHA256);
     std::string const sep(" ~~~ ");
     {
-      std::string str;
-      str += RccExecutable_;
-      str += sep;
-      str += cmJoin(RccListOptions_, ";");
-      str += sep;
-      str += QrcFile_;
-      str += sep;
-      str += RccPathChecksum_;
-      str += sep;
-      str += RccFileName_;
-      str += sep;
-      str += cmJoin(Options_, ";");
-      str += sep;
-      str += cmJoin(Inputs_, ";");
-      str += sep;
+      std::string str =
+        cmStrCat(RccExecutable_, sep, cmJoin(RccListOptions_, ";"), sep,
+                 QrcFile_, sep, RccPathChecksum_, sep, RccFileName_, sep,
+                 cmJoin(Options_, ";"), sep, cmJoin(Inputs_, ";"), sep);
       SettingsString_ = crypt.HashString(str);
     }
   }
@@ -290,9 +274,8 @@ bool cmQtAutoRcc::TestQrcRccFiles(bool& generate)
   // Test if the rcc input file exists
   if (!QrcFileTime_.Load(QrcFile_)) {
     std::string error;
-    error = "The resources file ";
-    error += Quoted(QrcFile_);
-    error += " does not exist";
+    error =
+      cmStrCat("The resources file ", Quoted(QrcFile_), " does not exist");
     Log().ErrorFile(GenT::RCC, QrcFile_, error);
     return false;
   }
@@ -300,10 +283,8 @@ bool cmQtAutoRcc::TestQrcRccFiles(bool& generate)
   // Test if the rcc output file exists
   if (!RccFileTime_.Load(RccFileOutput_)) {
     if (Log().Verbose()) {
-      Reason = "Generating ";
-      Reason += Quoted(RccFileOutput_);
-      Reason += ", because it doesn't exist, from ";
-      Reason += Quoted(QrcFile_);
+      Reason = cmStrCat("Generating ", Quoted(RccFileOutput_),
+                        ", because it doesn't exist, from ", Quoted(QrcFile_));
     }
     generate = true;
     return true;
@@ -312,10 +293,9 @@ bool cmQtAutoRcc::TestQrcRccFiles(bool& generate)
   // Test if the settings changed
   if (SettingsChanged_) {
     if (Log().Verbose()) {
-      Reason = "Generating ";
-      Reason += Quoted(RccFileOutput_);
-      Reason += ", because the rcc settings changed, from ";
-      Reason += Quoted(QrcFile_);
+      Reason = cmStrCat("Generating ", Quoted(RccFileOutput_),
+                        ", because the rcc settings changed, from ",
+                        Quoted(QrcFile_));
     }
     generate = true;
     return true;
@@ -324,12 +304,9 @@ bool cmQtAutoRcc::TestQrcRccFiles(bool& generate)
   // Test if the rcc output file is older than the .qrc file
   if (RccFileTime_.Older(QrcFileTime_)) {
     if (Log().Verbose()) {
-      Reason = "Generating ";
-      Reason += Quoted(RccFileOutput_);
-      Reason += ", because it is older than ";
-      Reason += Quoted(QrcFile_);
-      Reason += ", from ";
-      Reason += Quoted(QrcFile_);
+      Reason = cmStrCat("Generating ", Quoted(RccFileOutput_),
+                        ", because it is older than ", Quoted(QrcFile_),
+                        ", from ", Quoted(QrcFile_));
     }
     generate = true;
     return true;
@@ -338,10 +315,9 @@ bool cmQtAutoRcc::TestQrcRccFiles(bool& generate)
   // Test if the rcc output file is older than the rcc executable
   if (RccFileTime_.Older(RccExecutableTime_)) {
     if (Log().Verbose()) {
-      Reason = "Generating ";
-      Reason += Quoted(RccFileOutput_);
-      Reason += ", because it is older than the rcc executable, from ";
-      Reason += Quoted(QrcFile_);
+      Reason = cmStrCat("Generating ", Quoted(RccFileOutput_),
+                        ", because it is older than the rcc executable, from ",
+                        Quoted(QrcFile_));
     }
     generate = true;
     return true;
@@ -368,21 +344,17 @@ bool cmQtAutoRcc::TestResources(bool& generate)
     cmFileTime fileTime;
     if (!fileTime.Load(resFile)) {
       std::string error;
-      error = "Could not find the resource file\n  ";
-      error += Quoted(resFile);
-      error += '\n';
+      error = cmStrCat("Could not find the resource file\n  ", Quoted(resFile),
+                       '\n');
       Log().ErrorFile(GenT::RCC, QrcFile_, error);
       return false;
     }
     // Check if the resource file is newer than the rcc output file
     if (RccFileTime_.Older(fileTime)) {
       if (Log().Verbose()) {
-        Reason = "Generating ";
-        Reason += Quoted(RccFileOutput_);
-        Reason += ", because it is older than ";
-        Reason += Quoted(resFile);
-        Reason += ", from ";
-        Reason += Quoted(QrcFile_);
+        Reason = cmStrCat("Generating ", Quoted(RccFileOutput_),
+                          ", because it is older than ", Quoted(resFile),
+                          ", from ", Quoted(QrcFile_));
       }
       generate = true;
       break;
diff --git a/Source/cmScriptGenerator.cxx b/Source/cmScriptGenerator.cxx
index 9182b41..1438f07 100644
--- a/Source/cmScriptGenerator.cxx
+++ b/Source/cmScriptGenerator.cxx
@@ -2,6 +2,7 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmScriptGenerator.h"
 
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 #include <utility>
@@ -51,9 +52,8 @@ static void cmScriptGeneratorEncodeConfig(const std::string& config,
 
 std::string cmScriptGenerator::CreateConfigTest(const std::string& config)
 {
-  std::string result = "\"${";
-  result += this->RuntimeConfigVariable;
-  result += "}\" MATCHES \"^(";
+  std::string result =
+    cmStrCat("\"${", this->RuntimeConfigVariable, "}\" MATCHES \"^(");
   if (!config.empty()) {
     cmScriptGeneratorEncodeConfig(config, result);
   }
@@ -64,9 +64,8 @@ std::string cmScriptGenerator::CreateConfigTest(const std::string& config)
 std::string cmScriptGenerator::CreateConfigTest(
   std::vector<std::string> const& configs)
 {
-  std::string result = "\"${";
-  result += this->RuntimeConfigVariable;
-  result += "}\" MATCHES \"^(";
+  std::string result =
+    cmStrCat("\"${", this->RuntimeConfigVariable, "}\" MATCHES \"^(");
   const char* sep = "";
   for (std::string const& config : configs) {
     result += sep;
diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx
index 72291dc..7e3a340 100644
--- a/Source/cmSetPropertyCommand.cxx
+++ b/Source/cmSetPropertyCommand.cxx
@@ -242,9 +242,8 @@ bool HandleDirectoryMode(cmExecutionStatus& status,
     // respect to the current directory.
     std::string dir = *names.begin();
     if (!cmSystemTools::FileIsFullPath(dir)) {
-      dir = status.GetMakefile().GetCurrentSourceDirectory();
-      dir += "/";
-      dir += *names.begin();
+      dir = cmStrCat(status.GetMakefile().GetCurrentSourceDirectory(), '/',
+                     *names.begin());
     }
 
     // The local generators are associated with collapsed paths.
diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx
index 1dc7e69..b4360e4 100644
--- a/Source/cmSetTargetPropertiesCommand.cxx
+++ b/Source/cmSetTargetPropertiesCommand.cxx
@@ -6,6 +6,7 @@
 
 #include "cmAlgorithms.h"
 #include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
 #include "cmTarget.h"
 
 class cmExecutionStatus;
@@ -52,8 +53,8 @@ bool cmSetTargetPropertiesCommand::InitialPass(
     bool ret = cmSetTargetPropertiesCommand::SetOneTarget(
       args[i], propertyPairs, this->Makefile);
     if (!ret) {
-      std::string message = "Can not find target to add properties to: ";
-      message += args[i];
+      std::string message =
+        cmStrCat("Can not find target to add properties to: ", args[i]);
       this->SetError(message);
       return false;
     }
diff --git a/Source/cmSetTestsPropertiesCommand.cxx b/Source/cmSetTestsPropertiesCommand.cxx
index cc9587c..ed909c6 100644
--- a/Source/cmSetTestsPropertiesCommand.cxx
+++ b/Source/cmSetTestsPropertiesCommand.cxx
@@ -6,6 +6,7 @@
 
 #include "cmAlgorithms.h"
 #include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
 #include "cmTest.h"
 
 class cmExecutionStatus;
@@ -70,8 +71,7 @@ bool cmSetTestsPropertiesCommand::SetOneTest(
       }
     }
   } else {
-    errors = "Can not find test to add properties to: ";
-    errors += tname;
+    errors = cmStrCat("Can not find test to add properties to: ", tname);
     return false;
   }
 
diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx
index 3f52e64..a6d2807 100644
--- a/Source/cmSourceFile.cxx
+++ b/Source/cmSourceFile.cxx
@@ -151,9 +151,7 @@ bool cmSourceFile::FindFullPath(std::string* error)
     for (auto exts : extsLists) {
       for (std::string const& ext : *exts) {
         if (!ext.empty()) {
-          std::string extPath = fullPath;
-          extPath += '.';
-          extPath += ext;
+          std::string extPath = cmStrCat(fullPath, '.', ext);
           if (cmSystemTools::FileExists(extPath)) {
             this->FullPath = extPath;
             return true;
@@ -178,10 +176,8 @@ bool cmSourceFile::FindFullPath(std::string* error)
   }
 
   // Compose error
-  std::string err;
-  err += "Cannot find source file:\n  ";
-  err += lPath;
-  err += "\nTried extensions";
+  std::string err =
+    cmStrCat("Cannot find source file:\n  ", lPath, "\nTried extensions");
   for (auto exts : extsLists) {
     for (std::string const& ext : *exts) {
       err += " .";
diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx
index 6e2e820..0e8d09d 100644
--- a/Source/cmSourceFileLocation.cxx
+++ b/Source/cmSourceFileLocation.cxx
@@ -110,8 +110,7 @@ void cmSourceFileLocation::UpdateExtension(const std::string& name)
       // Check the source tree only because a file in the build tree should
       // be specified by full path at least once.  We do not want this
       // detection to depend on whether the project has already been built.
-      tryPath = this->Makefile->GetCurrentSourceDirectory();
-      tryPath += "/";
+      tryPath = cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/');
     }
     if (!this->Directory.empty()) {
       tryPath += this->Directory;
diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx
index 7e1e836..418a40f 100644
--- a/Source/cmSourceGroup.cxx
+++ b/Source/cmSourceGroup.cxx
@@ -2,6 +2,8 @@
    file Copyright.txt or https://cmake.org/licensing for details.  */
 #include "cmSourceGroup.h"
 
+#include "cmStringAlgorithms.h"
+
 #include <utility>
 
 class cmSourceGroupInternals
@@ -17,8 +19,7 @@ cmSourceGroup::cmSourceGroup(std::string name, const char* regex,
   this->Internal = new cmSourceGroupInternals;
   this->SetGroupRegex(regex);
   if (parentName) {
-    this->FullName = parentName;
-    this->FullName += "\\";
+    this->FullName = cmStrCat(parentName, '\\');
   }
   this->FullName += this->Name;
 }
diff --git a/Source/cmSourceGroupCommand.cxx b/Source/cmSourceGroupCommand.cxx
index 146e06d..399f1da 100644
--- a/Source/cmSourceGroupCommand.cxx
+++ b/Source/cmSourceGroupCommand.cxx
@@ -30,9 +30,7 @@ std::string getFullFilePath(const std::string& currentPath,
   std::string fullPath = path;
 
   if (!cmSystemTools::FileIsFullPath(path)) {
-    fullPath = currentPath;
-    fullPath += "/";
-    fullPath += path;
+    fullPath = cmStrCat(currentPath, '/', path);
   }
 
   return cmSystemTools::CollapseFullPath(fullPath);
@@ -236,9 +234,8 @@ bool cmSourceGroupCommand::InitialPass(std::vector<std::string> const& args,
     for (auto const& filesArg : filesArguments) {
       std::string src = filesArg;
       if (!cmSystemTools::FileIsFullPath(src)) {
-        src = this->Makefile->GetCurrentSourceDirectory();
-        src += "/";
-        src += filesArg;
+        src =
+          cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', filesArg);
       }
       src = cmSystemTools::CollapseFullPath(src);
       sg->AddGroupFile(src);
diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx
index 0f1adb3..849a566 100644
--- a/Source/cmStringCommand.cxx
+++ b/Source/cmStringCommand.cxx
@@ -229,9 +229,8 @@ bool HandleAsciiCommand(std::vector<std::string> const& args,
     if (ch > 0 && ch < 256) {
       output += static_cast<char>(ch);
     } else {
-      std::string error = "Character with code ";
-      error += args[cc];
-      error += " does not exist.";
+      std::string error =
+        cmStrCat("Character with code ", args[cc], " does not exist.");
       status.SetError(error);
       return false;
     }
@@ -514,9 +513,9 @@ bool HandleCompareCommand(std::vector<std::string> const& args,
       (mode == "LESS_EQUAL") || (mode == "GREATER") ||
       (mode == "GREATER_EQUAL")) {
     if (args.size() < 5) {
-      std::string e = "sub-command COMPARE, mode ";
-      e += mode;
-      e += " needs at least 5 arguments total to command.";
+      std::string e =
+        cmStrCat("sub-command COMPARE, mode ", mode,
+                 " needs at least 5 arguments total to command.");
       status.SetError(e);
       return false;
     }
diff --git a/Source/cmSubdirCommand.cxx b/Source/cmSubdirCommand.cxx
index 9d36228..07f8efe 100644
--- a/Source/cmSubdirCommand.cxx
+++ b/Source/cmSubdirCommand.cxx
@@ -3,6 +3,7 @@
 #include "cmSubdirCommand.h"
 
 #include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -44,8 +45,8 @@ bool cmSubdirCommand::InitialPass(std::vector<std::string> const& args,
         cmSystemTools::GetFilenameName(i);
       this->Makefile->AddSubDirectory(i, binPath, excludeFromAll, false);
     } else {
-      std::string error = "Incorrect SUBDIRS command. Directory: ";
-      error += i + " does not exist.";
+      std::string error = cmStrCat("Incorrect SUBDIRS command. Directory: ", i,
+                                   " does not exist.");
       this->SetError(error);
       res = false;
     }
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index caaa0a3..b7287d9 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -147,12 +147,10 @@ void cmSystemTools::ExpandRegistryValues(std::string& source, KeyWOW64 view)
     std::string key = regEntry.match(1);
     std::string val;
     if (ReadRegistryValue(key.c_str(), val, view)) {
-      std::string reg = "[";
-      reg += key + "]";
+      std::string reg = cmStrCat('[', key, ']');
       cmSystemTools::ReplaceString(source, reg.c_str(), val.c_str());
     } else {
-      std::string reg = "[";
-      reg += key + "]";
+      std::string reg = cmStrCat('[', key, ']');
       cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
     }
   }
@@ -165,8 +163,7 @@ void cmSystemTools::ExpandRegistryValues(std::string& source,
   while (regEntry.find(source)) {
     // the arguments are the second match
     std::string key = regEntry.match(1);
-    std::string reg = "[";
-    reg += key + "]";
+    std::string reg = cmStrCat('[', key, ']');
     cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
   }
 }
@@ -244,9 +241,8 @@ void cmSystemTools::Message(const std::string& m, const char* title)
 
 void cmSystemTools::ReportLastSystemError(const char* msg)
 {
-  std::string m = msg;
-  m += ": System Error: ";
-  m += Superclass::GetLastSystemError();
+  std::string m =
+    cmStrCat(msg, ": System Error: ", Superclass::GetLastSystemError());
   cmSystemTools::Error(m);
 }
 
@@ -346,10 +342,9 @@ std::vector<std::string> cmSystemTools::HandleResponseFile(
     if (cmHasLiteralPrefix(arg, "@")) {
       cmsys::ifstream responseFile(arg.substr(1).c_str(), std::ios::in);
       if (!responseFile) {
-        std::string error = "failed to open for reading (";
-        error += cmSystemTools::GetLastSystemError();
-        error += "):\n  ";
-        error += arg.substr(1);
+        std::string error = cmStrCat("failed to open for reading (",
+                                     cmSystemTools::GetLastSystemError(),
+                                     "):\n  ", cm::string_view(arg).substr(1));
         cmSystemTools::Error(error);
       } else {
         std::string line;
@@ -702,9 +697,7 @@ bool cmSystemTools::DoesFileExistWithExtensions(
   std::string hname;
 
   for (std::string const& headerExt : headerExts) {
-    hname = name;
-    hname += ".";
-    hname += headerExt;
+    hname = cmStrCat(name, '.', headerExt);
     if (cmSystemTools::FileExists(hname)) {
       return true;
     }
@@ -998,9 +991,7 @@ void cmSystemTools::GlobDirs(const std::string& path,
     for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i) {
       if ((std::string(d.GetFile(i)) != ".") &&
           (std::string(d.GetFile(i)) != "..")) {
-        std::string fname = startPath;
-        fname += "/";
-        fname += d.GetFile(i);
+        std::string fname = cmStrCat(startPath, '/', d.GetFile(i));
         if (cmSystemTools::FileIsDirectory(fname)) {
           fname += finishPath;
           cmSystemTools::GlobDirs(fname, files);
@@ -1183,8 +1174,7 @@ std::string cmSystemTools::ForceToRelativePath(std::string const& local_path,
 bool cmSystemTools::UnsetEnv(const char* value)
 {
 #  if !defined(HAVE_UNSETENV)
-  std::string var = value;
-  var += "=";
+  std::string var = cmStrCat(value, '=');
   return cmSystemTools::PutEnv(var.c_str());
 #  else
   unsetenv(value);
@@ -1270,10 +1260,8 @@ bool cmSystemTools::CreateTar(const std::string& outFileName,
   std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
   cmsys::ofstream fout(outFileName.c_str(), std::ios::out | std::ios::binary);
   if (!fout) {
-    std::string e = "Cannot open output file \"";
-    e += outFileName;
-    e += "\": ";
-    e += cmSystemTools::GetLastSystemError();
+    std::string e = cmStrCat("Cannot open output file \"", outFileName,
+                             "\": ", cmSystemTools::GetLastSystemError());
     cmSystemTools::Error(e);
     return false;
   }
@@ -1956,35 +1944,29 @@ void cmSystemTools::FindCMakeResources(const char* argv0)
   }
 #endif
   exe_dir = cmSystemTools::GetActualCaseForPath(exe_dir);
-  cmSystemToolsCMakeCommand = exe_dir;
-  cmSystemToolsCMakeCommand += "/cmake";
-  cmSystemToolsCMakeCommand += cmSystemTools::GetExecutableExtension();
+  cmSystemToolsCMakeCommand =
+    cmStrCat(exe_dir, "/cmake", cmSystemTools::GetExecutableExtension());
 #ifdef CMAKE_BOOTSTRAP
   // The bootstrap cmake does not provide the other tools,
   // so use the directory where they are about to be built.
   exe_dir = CMAKE_BOOTSTRAP_BINARY_DIR "/bin";
 #endif
-  cmSystemToolsCTestCommand = exe_dir;
-  cmSystemToolsCTestCommand += "/ctest";
-  cmSystemToolsCTestCommand += cmSystemTools::GetExecutableExtension();
-  cmSystemToolsCPackCommand = exe_dir;
-  cmSystemToolsCPackCommand += "/cpack";
-  cmSystemToolsCPackCommand += cmSystemTools::GetExecutableExtension();
-  cmSystemToolsCMakeGUICommand = exe_dir;
-  cmSystemToolsCMakeGUICommand += "/cmake-gui";
-  cmSystemToolsCMakeGUICommand += cmSystemTools::GetExecutableExtension();
+  cmSystemToolsCTestCommand =
+    cmStrCat(exe_dir, "/ctest", cmSystemTools::GetExecutableExtension());
+  cmSystemToolsCPackCommand =
+    cmStrCat(exe_dir, "/cpack", cmSystemTools::GetExecutableExtension());
+  cmSystemToolsCMakeGUICommand =
+    cmStrCat(exe_dir, "/cmake-gui", cmSystemTools::GetExecutableExtension());
   if (!cmSystemTools::FileExists(cmSystemToolsCMakeGUICommand)) {
     cmSystemToolsCMakeGUICommand.clear();
   }
-  cmSystemToolsCMakeCursesCommand = exe_dir;
-  cmSystemToolsCMakeCursesCommand += "/ccmake";
-  cmSystemToolsCMakeCursesCommand += cmSystemTools::GetExecutableExtension();
+  cmSystemToolsCMakeCursesCommand =
+    cmStrCat(exe_dir, "/ccmake", cmSystemTools::GetExecutableExtension());
   if (!cmSystemTools::FileExists(cmSystemToolsCMakeCursesCommand)) {
     cmSystemToolsCMakeCursesCommand.clear();
   }
-  cmSystemToolsCMClDepsCommand = exe_dir;
-  cmSystemToolsCMClDepsCommand += "/cmcldeps";
-  cmSystemToolsCMClDepsCommand += cmSystemTools::GetExecutableExtension();
+  cmSystemToolsCMClDepsCommand =
+    cmStrCat(exe_dir, "/cmcldeps", cmSystemTools::GetExecutableExtension());
   if (!cmSystemTools::FileExists(cmSystemToolsCMClDepsCommand)) {
     cmSystemToolsCMClDepsCommand.clear();
   }
@@ -2222,8 +2204,9 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
         return true;
       }
       if (emsg) {
-        *emsg = "No valid ELF RPATH or RUNPATH entry exists in the file; ";
-        *emsg += elf.GetErrorMessage();
+        *emsg =
+          cmStrCat("No valid ELF RPATH or RUNPATH entry exists in the file; ",
+                   elf.GetErrorMessage());
       }
       return false;
     }
@@ -2289,9 +2272,8 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
       // least one null terminator.
       if (rp[rp_count].Size < rp[rp_count].Value.length() + 1) {
         if (emsg) {
-          *emsg = "The replacement path is too long for the ";
-          *emsg += se_name[i];
-          *emsg += " entry.";
+          *emsg = cmStrCat("The replacement path is too long for the ",
+                           se_name[i], " entry.");
         }
         return false;
       }
@@ -2327,9 +2309,7 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
       // Seek to the RPATH position.
       if (!f.seekp(rp[i].Position)) {
         if (emsg) {
-          *emsg = "Error seeking to ";
-          *emsg += rp[i].Name;
-          *emsg += " position.";
+          *emsg = cmStrCat("Error seeking to ", rp[i].Name, " position.");
         }
         return false;
       }
@@ -2344,9 +2324,8 @@ bool cmSystemTools::ChangeRPath(std::string const& file,
       // Make sure it wrote correctly.
       if (!f) {
         if (emsg) {
-          *emsg = "Error writing the new ";
-          *emsg += rp[i].Name;
-          *emsg += " string to the file.";
+          *emsg = cmStrCat("Error writing the new ", rp[i].Name,
+                           " string to the file.");
         }
         return false;
       }
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 9b002ee..bc1b9de 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -392,8 +392,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
             strcmp(prop, "MAP_IMPORTED_CONFIG_") != 0) {
           continue;
         }
-        std::string property = prop;
-        property += configUpper;
+        std::string property = cmStrCat(prop, configUpper);
         initProp(property);
       }
 
@@ -404,8 +403,8 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type,
       // property directly.
       if (impl->TargetType != cmStateEnums::EXECUTABLE &&
           impl->TargetType != cmStateEnums::INTERFACE_LIBRARY) {
-        std::string property = cmSystemTools::UpperCase(configName);
-        property += "_POSTFIX";
+        std::string property =
+          cmStrCat(cmSystemTools::UpperCase(configName), "_POSTFIX");
         initProp(property);
       }
     }
@@ -778,8 +777,7 @@ cmSourceFile* cmTarget::AddSource(const std::string& src, bool before)
 
 void cmTarget::ClearDependencyInformation(cmMakefile& mf)
 {
-  std::string depname = this->GetName();
-  depname += "_LIB_DEPENDS";
+  std::string depname = cmStrCat(this->GetName(), "_LIB_DEPENDS");
   mf.RemoveCacheDefinition(depname);
 }
 
@@ -947,8 +945,7 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf, std::string const& lib,
       impl->TargetType <= cmStateEnums::MODULE_LIBRARY &&
       (this->GetPolicyStatusCMP0073() == cmPolicies::OLD ||
        this->GetPolicyStatusCMP0073() == cmPolicies::WARN)) {
-    std::string targetEntry = impl->Name;
-    targetEntry += "_LIB_DEPENDS";
+    std::string targetEntry = cmStrCat(impl->Name, "_LIB_DEPENDS");
     std::string dependencies;
     const char* old_val = mf.GetDefinition(targetEntry);
     if (old_val) {
@@ -1806,8 +1803,7 @@ std::string cmTarget::ImportedGetFullPath(
         if (loc) {
           result = loc;
         } else {
-          std::string impProp = "IMPORTED_LOCATION";
-          impProp += suffix;
+          std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix);
           if (const char* config_location = this->GetProperty(impProp)) {
             result = config_location;
           } else if (const char* location =
@@ -1822,8 +1818,7 @@ std::string cmTarget::ImportedGetFullPath(
           result = imp;
         } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
                    this->IsExecutableWithExports()) {
-          std::string impProp = "IMPORTED_IMPLIB";
-          impProp += suffix;
+          std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
           if (const char* config_implib = this->GetProperty(impProp)) {
             result = config_implib;
           } else if (const char* implib =
@@ -1836,8 +1831,7 @@ std::string cmTarget::ImportedGetFullPath(
   }
 
   if (result.empty()) {
-    result = this->GetName();
-    result += "-NOTFOUND";
+    result = cmStrCat(this->GetName(), "-NOTFOUND");
   }
   return result;
 }
@@ -1891,13 +1885,11 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
   }
 
   // Track the configuration-specific property suffix.
-  suffix = "_";
-  suffix += config_upper;
+  suffix = cmStrCat('_', config_upper);
 
   std::vector<std::string> mappedConfigs;
   {
-    std::string mapProp = "MAP_IMPORTED_CONFIG_";
-    mapProp += config_upper;
+    std::string mapProp = cmStrCat("MAP_IMPORTED_CONFIG_", config_upper);
     if (const char* mapValue = this->GetProperty(mapProp)) {
       cmExpandList(mapValue, mappedConfigs, true);
     }
@@ -1928,19 +1920,16 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
       }
     } else {
       std::string mcUpper = cmSystemTools::UpperCase(*mci);
-      std::string locProp = locPropBase + "_";
-      locProp += mcUpper;
+      std::string locProp = cmStrCat(locPropBase, '_', mcUpper);
       *loc = this->GetProperty(locProp);
       if (allowImp) {
-        std::string impProp = "IMPORTED_IMPLIB_";
-        impProp += mcUpper;
+        std::string impProp = cmStrCat("IMPORTED_IMPLIB_", mcUpper);
         *imp = this->GetProperty(impProp);
       }
 
       // If it was found, use it for all properties below.
       if (*loc || *imp) {
-        suffix = "_";
-        suffix += mcUpper;
+        suffix = cmStrCat('_', mcUpper);
       }
     }
   }
@@ -1957,12 +1946,10 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
   // If we have not yet found it then there are no mapped
   // configurations.  Look for an exact-match.
   if (!*loc && !*imp) {
-    std::string locProp = locPropBase;
-    locProp += suffix;
+    std::string locProp = cmStrCat(locPropBase, suffix);
     *loc = this->GetProperty(locProp);
     if (allowImp) {
-      std::string impProp = "IMPORTED_IMPLIB";
-      impProp += suffix;
+      std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
       *imp = this->GetProperty(impProp);
     }
   }
@@ -1991,14 +1978,11 @@ bool cmTarget::GetMappedConfig(std::string const& desired_config,
     for (std::vector<std::string>::const_iterator aci =
            availableConfigs.begin();
          !*loc && !*imp && aci != availableConfigs.end(); ++aci) {
-      suffix = "_";
-      suffix += cmSystemTools::UpperCase(*aci);
-      std::string locProp = locPropBase;
-      locProp += suffix;
+      suffix = cmStrCat('_', cmSystemTools::UpperCase(*aci));
+      std::string locProp = cmStrCat(locPropBase, suffix);
       *loc = this->GetProperty(locProp);
       if (allowImp) {
-        std::string impProp = "IMPORTED_IMPLIB";
-        impProp += suffix;
+        std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
         *imp = this->GetProperty(impProp);
       }
     }
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index 3883b52..4fbec90 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -12,6 +12,7 @@
 #include "cmPolicies.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 #include "cmake.h"
@@ -237,8 +238,7 @@ bool cmTargetLinkLibrariesCommand::InitialPass(
       // only there for backwards compatibility when mixing projects built
       // with old versions of CMake and new)
       llt = GENERAL_LibraryType;
-      std::string linkType = args[0];
-      linkType += "_LINK_TYPE";
+      std::string linkType = cmStrCat(args[0], "_LINK_TYPE");
       const char* linkTypeString = this->Makefile->GetDefinition(linkType);
       if (linkTypeString) {
         if (strcmp(linkTypeString, "debug") == 0) {
@@ -502,8 +502,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
     if (llt == DEBUG_LibraryType || llt == GENERAL_LibraryType) {
       // Put in the DEBUG configuration interfaces.
       for (std::string const& dc : debugConfigs) {
-        prop = "LINK_INTERFACE_LIBRARIES_";
-        prop += dc;
+        prop = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc);
         this->Target->AppendProperty(prop, libRef.c_str());
       }
     }
@@ -514,8 +513,7 @@ bool cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib,
       // Make sure the DEBUG configuration interfaces exist so that the
       // general one will not be used as a fall-back.
       for (std::string const& dc : debugConfigs) {
-        prop = "LINK_INTERFACE_LIBRARIES_";
-        prop += dc;
+        prop = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc);
         if (!this->Target->GetProperty(prop)) {
           this->Target->SetProperty(prop, "");
         }
diff --git a/Source/cmTargetSourcesCommand.cxx b/Source/cmTargetSourcesCommand.cxx
index eb5f37c..2251a65 100644
--- a/Source/cmTargetSourcesCommand.cxx
+++ b/Source/cmTargetSourcesCommand.cxx
@@ -75,9 +75,8 @@ std::vector<std::string> cmTargetSourcesCommand::ConvertToAbsoluteContent(
       absoluteSrc = src;
     } else {
       changedPath = true;
-      absoluteSrc = this->Makefile->GetCurrentSourceDirectory();
-      absoluteSrc += "/";
-      absoluteSrc += src;
+      absoluteSrc =
+        cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', src);
     }
     absoluteContent.push_back(absoluteSrc);
   }
diff --git a/Source/cmTimestamp.cxx b/Source/cmTimestamp.cxx
index 0915986..9e32226 100644
--- a/Source/cmTimestamp.cxx
+++ b/Source/cmTimestamp.cxx
@@ -6,6 +6,7 @@
 #include <sstream>
 #include <stdlib.h>
 
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 std::string cmTimestamp::CurrentTime(const std::string& formatString,
@@ -131,8 +132,7 @@ std::string cmTimestamp::AddTimestampComponent(char flag,
                                                struct tm& timeStruct,
                                                const time_t timeT) const
 {
-  std::string formatString = "%";
-  formatString += flag;
+  std::string formatString = cmStrCat('%', flag);
 
   switch (flag) {
     case 'a':
diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx
index 0847b9b..1c892c7 100644
--- a/Source/cmTryRunCommand.cxx
+++ b/Source/cmTryRunCommand.cxx
@@ -214,19 +214,17 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
   // copy the executable out of the CMakeFiles/ directory, so it is not
   // removed at the end of TRY_RUN and the user can run it manually
   // on the target platform.
-  std::string copyDest = this->Makefile->GetHomeOutputDirectory();
-  copyDest += "/CMakeFiles/";
-  copyDest += cmSystemTools::GetFilenameWithoutExtension(this->OutputFile);
-  copyDest += "-";
-  copyDest += this->RunResultVariable;
-  copyDest += cmSystemTools::GetFilenameExtension(this->OutputFile);
+  std::string copyDest =
+    cmStrCat(this->Makefile->GetHomeOutputDirectory(), "/CMakeFiles/",
+             cmSystemTools::GetFilenameWithoutExtension(this->OutputFile), '-',
+             this->RunResultVariable,
+             cmSystemTools::GetFilenameExtension(this->OutputFile));
   cmSystemTools::CopyFileAlways(this->OutputFile, copyDest);
 
-  std::string resultFileName = this->Makefile->GetHomeOutputDirectory();
-  resultFileName += "/TryRunResults.cmake";
+  std::string resultFileName =
+    cmStrCat(this->Makefile->GetHomeOutputDirectory(), "/TryRunResults.cmake");
 
-  std::string detailsString = "For details see ";
-  detailsString += resultFileName;
+  std::string detailsString = cmStrCat("For details see ", resultFileName);
 
   std::string internalRunOutputName =
     this->RunResultVariable + "__TRYRUN_OUTPUT";
@@ -235,10 +233,10 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
   if (!this->Makefile->GetDefinition(this->RunResultVariable)) {
     // if the variables doesn't exist, create it with a helpful error text
     // and mark it as advanced
-    std::string comment;
-    comment += "Run result of TRY_RUN(), indicates whether the executable "
-               "would have been able to run on its target platform.\n";
-    comment += detailsString;
+    std::string comment =
+      cmStrCat("Run result of TRY_RUN(), indicates whether the executable "
+               "would have been able to run on its target platform.\n",
+               detailsString);
     this->Makefile->AddCacheDefinition(this->RunResultVariable,
                                        "PLEASE_FILL_OUT-FAILED_TO_RUN",
                                        comment.c_str(), cmStateEnums::STRING);
@@ -258,11 +256,10 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
     if (!this->Makefile->GetDefinition(internalRunOutputName)) {
       // if the variables doesn't exist, create it with a helpful error text
       // and mark it as advanced
-      std::string comment;
-      comment +=
+      std::string comment = cmStrCat(
         "Output of TRY_RUN(), contains the text, which the executable "
-        "would have printed on stdout and stderr on its target platform.\n";
-      comment += detailsString;
+        "would have printed on stdout and stderr on its target platform.\n",
+        detailsString);
 
       this->Makefile->AddCacheDefinition(
         internalRunOutputName, "PLEASE_FILL_OUT-NOTFOUND", comment.c_str(),
@@ -294,15 +291,15 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
         /* clang-format on */
       }
 
-      std::string comment = "\n";
-      comment += this->RunResultVariable;
-      comment += "\n   indicates whether the executable would have been able "
+      std::string comment =
+        cmStrCat('\n', this->RunResultVariable,
+                 "\n   indicates whether the executable would have been able "
                  "to run on its\n"
-                 "   target platform. If so, set ";
-      comment += this->RunResultVariable;
-      comment += " to\n"
+                 "   target platform. If so, set ",
+                 this->RunResultVariable,
+                 " to\n"
                  "   the exit code (in many cases 0 for success), otherwise "
-                 "enter \"FAILED_TO_RUN\".\n";
+                 "enter \"FAILED_TO_RUN\".\n");
       if (out) {
         comment += internalRunOutputName;
         comment +=
@@ -343,10 +340,11 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs,
     }
     firstTryRun = false;
 
-    std::string errorMessage = "TRY_RUN() invoked in cross-compiling mode, "
-                               "please set the following cache variables "
-                               "appropriately:\n";
-    errorMessage += "   " + this->RunResultVariable + " (advanced)\n";
+    std::string errorMessage =
+      cmStrCat("TRY_RUN() invoked in cross-compiling mode, "
+               "please set the following cache variables "
+               "appropriately:\n   ",
+               this->RunResultVariable, " (advanced)\n");
     if (out) {
       errorMessage += "   " + internalRunOutputName + " (advanced)\n";
     }
diff --git a/Source/cmUseMangledMesaCommand.cxx b/Source/cmUseMangledMesaCommand.cxx
index 2b553b0..3d83760 100644
--- a/Source/cmUseMangledMesaCommand.cxx
+++ b/Source/cmUseMangledMesaCommand.cxx
@@ -5,6 +5,7 @@
 #include "cmsys/FStream.hxx"
 #include "cmsys/RegularExpression.hxx"
 
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -20,13 +21,9 @@ bool cmUseMangledMesaCommand::InitialPass(std::vector<std::string> const& args,
     return false;
   }
   const std::string& inputDir = args[0];
-  std::string glh = inputDir;
-  glh += "/";
-  glh += "gl.h";
+  std::string glh = cmStrCat(inputDir, "/gl.h");
   if (!cmSystemTools::FileExists(glh)) {
-    std::string e = "Bad path to Mesa, could not find: ";
-    e += glh;
-    e += " ";
+    std::string e = cmStrCat("Bad path to Mesa, could not find: ", glh, ' ');
     this->SetError(e);
     return false;
   }
@@ -39,9 +36,7 @@ bool cmUseMangledMesaCommand::InitialPass(std::vector<std::string> const& args,
   }
   cmSystemTools::MakeDirectory(destDir);
   for (std::string const& f : files) {
-    std::string path = inputDir;
-    path += "/";
-    path += f;
+    std::string path = cmStrCat(inputDir, '/', f);
     this->CopyAndFullPathMesaHeader(path, destDir);
   }
 
@@ -54,11 +49,8 @@ void cmUseMangledMesaCommand::CopyAndFullPathMesaHeader(
   std::string dir;
   std::string file;
   cmSystemTools::SplitProgramPath(source, dir, file);
-  std::string outFile = outdir;
-  outFile += "/";
-  outFile += file;
-  std::string tempOutputFile = outFile;
-  tempOutputFile += ".tmp";
+  std::string outFile = cmStrCat(outdir, '/', file);
+  std::string tempOutputFile = cmStrCat(outFile, ".tmp");
   cmsys::ofstream fout(tempOutputFile.c_str());
   if (!fout) {
     cmSystemTools::Error("Could not open file for write in copy operation: " +
diff --git a/Source/cmUtilitySourceCommand.cxx b/Source/cmUtilitySourceCommand.cxx
index b59a587..d255b67 100644
--- a/Source/cmUtilitySourceCommand.cxx
+++ b/Source/cmUtilitySourceCommand.cxx
@@ -7,6 +7,7 @@
 #include "cmMakefile.h"
 #include "cmState.h"
 #include "cmStateTypes.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -35,11 +36,11 @@ bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args,
   if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING")) {
     haveCacheValue = (cacheValue != nullptr);
     if (!haveCacheValue) {
-      std::string msg = "UTILITY_SOURCE is used in cross compiling mode for ";
-      msg += cacheEntry;
-      msg += ". If your intention is to run this executable, you need to "
-             "preload the cache with the full path to a version of that "
-             "program, which runs on this build machine.";
+      std::string msg = cmStrCat(
+        "UTILITY_SOURCE is used in cross compiling mode for ", cacheEntry,
+        ". If your intention is to run this executable, you need to "
+        "preload the cache with the full path to a version of that "
+        "program, which runs on this build machine.");
       cmSystemTools::Message(msg, "Warning");
     }
   } else {
diff --git a/Source/cmVSSetupHelper.cxx b/Source/cmVSSetupHelper.cxx
index 20f5e2f..707ceac 100644
--- a/Source/cmVSSetupHelper.cxx
+++ b/Source/cmVSSetupHelper.cxx
@@ -365,8 +365,8 @@ bool cmVSSetupAPIHelper::EnumerateAndChooseVSInstance()
         // We are not looking for a specific instance.
         // If we've been given a hint then use it.
         if (!envVSCommonToolsDir.empty()) {
-          std::string currentVSLocation = instanceInfo.GetInstallLocation();
-          currentVSLocation += "/Common7/Tools";
+          std::string currentVSLocation =
+            cmStrCat(instanceInfo.GetInstallLocation(), "/Common7/Tools");
           if (cmSystemTools::ComparePath(currentVSLocation,
                                          envVSCommonToolsDir)) {
             chosenInstanceInfo = instanceInfo;
diff --git a/Source/cmVariableRequiresCommand.cxx b/Source/cmVariableRequiresCommand.cxx
index 9878ff1..c44eeca 100644
--- a/Source/cmVariableRequiresCommand.cxx
+++ b/Source/cmVariableRequiresCommand.cxx
@@ -4,6 +4,7 @@
 
 #include "cmMakefile.h"
 #include "cmState.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 
 class cmExecutionStatus;
@@ -46,12 +47,11 @@ bool cmVariableRequiresCommand::InitialPass(
   }
 
   if (!requirementsMet) {
-    std::string message = "Variable assertion failed:\n";
-    message +=
-      testVariable + " Requires that the following unset variables are set:\n";
-    message += notSet;
-    message += "\nPlease set them, or set ";
-    message += testVariable + " to false, and re-configure.\n";
+    std::string message =
+      cmStrCat("Variable assertion failed:\n", testVariable,
+               " Requires that the following unset variables are set:\n",
+               notSet, "\nPlease set them, or set ", testVariable,
+               " to false, and re-configure.\n");
     if (hasAdvanced) {
       message +=
         "One or more of the required variables is advanced."
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 8d4908d..c5cf9a7 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -364,10 +364,9 @@ void cmVisualStudio10TargetGenerator::Generate()
       return;
     }
   }
-  std::string path = this->LocalGenerator->GetCurrentBinaryDirectory();
-  path += "/";
-  path += this->Name;
-  path += ProjectFileExtension;
+  std::string path =
+    cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
+             this->Name, ProjectFileExtension);
   cmGeneratedFileStream BuildFileStream(path);
   const std::string PathToProjectFile = path;
   BuildFileStream.SetCopyIfDifferent(true);
@@ -628,9 +627,8 @@ void cmVisualStudio10TargetGenerator::Generate()
         std::string propsTemplate =
           GetCMakeFilePath("Templates/MSBuild/nasm.props.in");
 
-        std::string propsLocal;
-        propsLocal += this->DefaultArtifactDir;
-        propsLocal += "\\nasm.props";
+        std::string propsLocal =
+          cmStrCat(this->DefaultArtifactDir, "\\nasm.props");
         ConvertToWindowsSlash(propsLocal);
         this->Makefile->ConfigureFile(propsTemplate, propsLocal, false, true,
                                       true);
@@ -1272,8 +1270,8 @@ void cmVisualStudio10TargetGenerator::WriteMSToolConfigurationValuesManaged(
     e1.Element("PlatformToolset", toolset);
   }
 
-  std::string postfixName = cmSystemTools::UpperCase(config);
-  postfixName += "_POSTFIX";
+  std::string postfixName =
+    cmStrCat(cmSystemTools::UpperCase(config), "_POSTFIX");
   std::string assemblyName = this->GeneratorTarget->GetOutputName(
     config, cmStateEnums::RuntimeBinaryArtifact);
   if (const char* postfix = this->GeneratorTarget->GetProperty(postfixName)) {
@@ -1378,9 +1376,8 @@ void cmVisualStudio10TargetGenerator::WriteCustomRule(
         // preventing dependent rebuilds.
         this->ForceOld(sourcePath);
       } else {
-        std::string error = "Could not create file: [";
-        error += sourcePath;
-        error += "]  ";
+        std::string error =
+          cmStrCat("Could not create file: [", sourcePath, "]  ");
         cmSystemTools::Error(error + cmSystemTools::GetLastSystemError());
       }
     }
@@ -1549,11 +1546,9 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
   this->AddMissingSourceGroups(groupsUsed, sourceGroups);
 
   // Write out group file
-  std::string path = this->LocalGenerator->GetCurrentBinaryDirectory();
-  path += "/";
-  path += this->Name;
-  path += computeProjectFileExtension(this->GeneratorTarget);
-  path += ".filters";
+  std::string path = cmStrCat(
+    this->LocalGenerator->GetCurrentBinaryDirectory(), '/', this->Name,
+    computeProjectFileExtension(this->GeneratorTarget), ".filters");
   cmGeneratedFileStream fout(path);
   fout.SetCopyIfDifferent(true);
   char magic[] = { char(0xEF), char(0xBB), char(0xBF) };
@@ -2234,8 +2229,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags(
   for (std::string const& config : this->Configurations) {
     std::string configUpper = cmSystemTools::UpperCase(config);
     std::string configDefines = defines;
-    std::string defPropName = "COMPILE_DEFINITIONS_";
-    defPropName += configUpper;
+    std::string defPropName = cmStrCat("COMPILE_DEFINITIONS_", configUpper);
     if (const char* ccdefs = sf.GetProperty(defPropName)) {
       if (!configDefines.empty()) {
         configDefines += ";";
@@ -2425,17 +2419,14 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
       e1.WritePlatformConfigTag(
         "IntDir", cond, "$(Platform)\\$(Configuration)\\$(ProjectName)\\");
     } else {
-      std::string intermediateDir =
-        this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget);
-      intermediateDir += "/";
-      intermediateDir += config;
-      intermediateDir += "/";
+      std::string intermediateDir = cmStrCat(
+        this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), '/',
+        config, '/');
       std::string outDir;
       std::string targetNameFull;
       if (ttype == cmStateEnums::OBJECT_LIBRARY) {
         outDir = intermediateDir;
-        targetNameFull = this->GeneratorTarget->GetName();
-        targetNameFull += ".lib";
+        targetNameFull = cmStrCat(this->GeneratorTarget->GetName(), ".lib");
       } else {
         outDir = this->GeneratorTarget->GetDirectory(config) + "/";
         targetNameFull = this->GeneratorTarget->GetFullName(config);
@@ -2715,9 +2706,7 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
   }
 
   // Add a definition for the configuration name.
-  std::string configDefine = "CMAKE_INTDIR=\"";
-  configDefine += configName;
-  configDefine += "\"";
+  std::string configDefine = cmStrCat("CMAKE_INTDIR=\"", configName, '"');
   clOptions.AddDefine(configDefine);
   if (const std::string* exportMacro =
         this->GeneratorTarget->GetExportMacro()) {
@@ -3012,9 +3001,7 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
   cudaOptions.AddDefines(targetDefines);
 
   // Add a definition for the configuration name.
-  std::string configDefine = "CMAKE_INTDIR=\"";
-  configDefine += configName;
-  configDefine += "\"";
+  std::string configDefine = cmStrCat("CMAKE_INTDIR=\"", configName, '"');
   cudaOptions.AddDefine(configDefine);
   if (const std::string* exportMacro =
         this->GeneratorTarget->GetExportMacro()) {
@@ -3429,9 +3416,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
     linkType = "EXE";
   }
   std::string flags;
-  std::string linkFlagVarBase = "CMAKE_";
-  linkFlagVarBase += linkType;
-  linkFlagVarBase += "_LINKER_FLAGS";
+  std::string linkFlagVarBase = cmStrCat("CMAKE_", linkType, "_LINKER_FLAGS");
   flags += " ";
   flags += this->Makefile->GetRequiredDefinition(linkFlagVarBase);
   std::string linkFlagVar = linkFlagVarBase + "_" + CONFIG;
@@ -3443,8 +3428,7 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
     flags += " ";
     flags += targetLinkFlags;
   }
-  std::string flagsProp = "LINK_FLAGS_";
-  flagsProp += CONFIG;
+  std::string flagsProp = cmStrCat("LINK_FLAGS_", CONFIG);
   if (const char* flagsConfig =
         this->GeneratorTarget->GetProperty(flagsProp)) {
     flags += " ";
@@ -3484,9 +3468,8 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
         break;
     }
   }
-  std::string standardLibsVar = "CMAKE_";
-  standardLibsVar += linkLanguage;
-  standardLibsVar += "_STANDARD_LIBRARIES";
+  std::string standardLibsVar =
+    cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LIBRARIES");
   std::string const& libs = this->Makefile->GetSafeDefinition(standardLibsVar);
   cmSystemTools::ParseWindowsCommandLine(libs.c_str(), libVec);
   linkOptions.AddFlag("AdditionalDependencies", libVec);
@@ -3550,13 +3533,12 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
 
     linkOptions.AddFlag("GenerateDebugInformation", "false");
 
-    std::string pdb = this->GeneratorTarget->GetPDBDirectory(config);
-    pdb += "/";
-    pdb += targetNames.PDB;
-    std::string imLib = this->GeneratorTarget->GetDirectory(
-      config, cmStateEnums::ImportLibraryArtifact);
-    imLib += "/";
-    imLib += targetNames.ImportLibrary;
+    std::string pdb = cmStrCat(this->GeneratorTarget->GetPDBDirectory(config),
+                               '/', targetNames.PDB);
+    std::string imLib =
+      cmStrCat(this->GeneratorTarget->GetDirectory(
+                 config, cmStateEnums::ImportLibraryArtifact),
+               '/', targetNames.ImportLibrary);
 
     linkOptions.AddFlag("ImportLibrary", imLib);
     linkOptions.AddFlag("ProgramDataBaseFile", pdb);
@@ -3938,10 +3920,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0)
     if (p) {
       path = p;
     } else {
-      path = lg->GetCurrentBinaryDirectory();
-      path += "/";
-      path += dt->GetName();
-      path += computeProjectFileExtension(dt);
+      path = cmStrCat(lg->GetCurrentBinaryDirectory(), '/', dt->GetName(),
+                      computeProjectFileExtension(dt));
     }
     ConvertToWindowsSlash(path);
     Elem e2(e1, "ProjectReference");
@@ -4748,8 +4728,8 @@ std::string cmVisualStudio10TargetGenerator::GetCMakeFilePath(
   const char* relativeFilePath) const
 {
   // Always search in the standard modules location.
-  std::string path = cmSystemTools::GetCMakeRoot() + "/";
-  path += relativeFilePath;
+  std::string path =
+    cmStrCat(cmSystemTools::GetCMakeRoot(), '/', relativeFilePath);
   ConvertToWindowsSlash(path);
 
   return path;
diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx
index 6c28996..3e423e9 100644
--- a/Source/cmVisualStudioGeneratorOptions.cxx
+++ b/Source/cmVisualStudioGeneratorOptions.cxx
@@ -325,9 +325,9 @@ void cmVisualStudioGeneratorOptions::ParseFinish()
     //  "rtSingleThreadedDLL", "10", /libs:dll
     //  "rtSingleThreadedDebug", "5", /dbglibs /libs:static
     //  "rtSingleThreadedDebugDLL", "11", /dbglibs /libs:dll
-    std::string rl = "rtMultiThreaded";
-    rl += this->FortranRuntimeDebug ? "Debug" : "";
-    rl += this->FortranRuntimeDLL ? "DLL" : "";
+    std::string rl =
+      cmStrCat("rtMultiThreaded", this->FortranRuntimeDebug ? "Debug" : "",
+               this->FortranRuntimeDLL ? "DLL" : "");
     this->FlagMap["RuntimeLibrary"] = rl;
   }
 
diff --git a/Source/cmWorkerPool.cxx b/Source/cmWorkerPool.cxx
index 974100b..baf326a 100644
--- a/Source/cmWorkerPool.cxx
+++ b/Source/cmWorkerPool.cxx
@@ -3,6 +3,7 @@
 #include "cmWorkerPool.h"
 
 #include "cmRange.h"
+#include "cmStringAlgorithms.h"
 #include "cmUVHandlePtr.h"
 #include "cmUVSignalHackRAII.h" // IWYU pragma: keep
 #include "cm_uv.h"
@@ -306,13 +307,11 @@ void cmUVReadOnlyProcess::UVExit(uv_process_t* handle, int64_t exitStatus,
     proc.Result()->TermSignal = termSignal;
     if (!proc.Result()->error()) {
       if (termSignal != 0) {
-        proc.Result()->ErrorMessage = "Process was terminated by signal ";
-        proc.Result()->ErrorMessage +=
-          std::to_string(proc.Result()->TermSignal);
+        proc.Result()->ErrorMessage = cmStrCat(
+          "Process was terminated by signal ", proc.Result()->TermSignal);
       } else if (exitStatus != 0) {
-        proc.Result()->ErrorMessage = "Process failed with return value ";
-        proc.Result()->ErrorMessage +=
-          std::to_string(proc.Result()->ExitStatus);
+        proc.Result()->ErrorMessage = cmStrCat(
+          "Process failed with return value ", proc.Result()->ExitStatus);
       }
     }
 
@@ -332,9 +331,8 @@ void cmUVReadOnlyProcess::UVPipeOutEnd(ssize_t error)
 {
   // Process pipe error
   if ((error != 0) && !Result()->error()) {
-    Result()->ErrorMessage =
-      "Reading from stdout pipe failed with libuv error code ";
-    Result()->ErrorMessage += std::to_string(error);
+    Result()->ErrorMessage = cmStrCat(
+      "Reading from stdout pipe failed with libuv error code ", error);
   }
   // Try finish
   UVTryFinish();
@@ -351,9 +349,8 @@ void cmUVReadOnlyProcess::UVPipeErrEnd(ssize_t error)
 {
   // Process pipe error
   if ((error != 0) && !Result()->error()) {
-    Result()->ErrorMessage =
-      "Reading from stderr pipe failed with libuv error code ";
-    Result()->ErrorMessage += std::to_string(error);
+    Result()->ErrorMessage = cmStrCat(
+      "Reading from stderr pipe failed with libuv error code ", error);
   }
   // Try finish
   UVTryFinish();
diff --git a/Source/cmWriteFileCommand.cxx b/Source/cmWriteFileCommand.cxx
index 63af65d..5009b16 100644
--- a/Source/cmWriteFileCommand.cxx
+++ b/Source/cmWriteFileCommand.cxx
@@ -6,6 +6,7 @@
 
 #include "cmExecutionStatus.h"
 #include "cmMakefile.h"
+#include "cmStringAlgorithms.h"
 #include "cmSystemTools.h"
 #include "cm_sys_stat.h"
 
@@ -64,9 +65,9 @@ bool cmWriteFileCommand(std::vector<std::string> const& args,
   cmsys::ofstream file(fileName.c_str(),
                        overwrite ? std::ios::out : std::ios::app);
   if (!file) {
-    std::string error = "Internal CMake error when trying to open file: ";
-    error += fileName;
-    error += " for writing.";
+    std::string error =
+      cmStrCat("Internal CMake error when trying to open file: ", fileName,
+               " for writing.");
     status.SetError(error);
     return false;
   }
diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx
index 112d1c1..0b3962e 100644
--- a/Source/cmXCodeScheme.cxx
+++ b/Source/cmXCodeScheme.cxx
@@ -27,14 +27,11 @@ void cmXCodeScheme::WriteXCodeSharedScheme(const std::string& xcProjDir,
 {
   // Create shared scheme sub-directory tree
   //
-  std::string xcodeSchemeDir = xcProjDir;
-  xcodeSchemeDir += "/xcshareddata/xcschemes";
+  std::string xcodeSchemeDir = cmStrCat(xcProjDir, "/xcshareddata/xcschemes");
   cmSystemTools::MakeDirectory(xcodeSchemeDir.c_str());
 
-  std::string xcodeSchemeFile = xcodeSchemeDir;
-  xcodeSchemeFile += "/";
-  xcodeSchemeFile += this->TargetName;
-  xcodeSchemeFile += ".xcscheme";
+  std::string xcodeSchemeFile =
+    cmStrCat(xcodeSchemeDir, '/', this->TargetName, ".xcscheme");
 
   cmGeneratedFileStream fout(xcodeSchemeFile);
   fout.SetCopyIfDifferent(true);
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 794119a..a5c8d46 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -605,10 +605,9 @@ void cmake::LoadEnvironmentPresets()
       if (hasEnvironmentGenerator) {
         key = varValue;
       } else if (!this->GetIsInTryCompile()) {
-        std::string message = "Warning: Environment variable ";
-        message += name;
-        message += " will be ignored, because CMAKE_GENERATOR ";
-        message += "is not set.";
+        std::string message =
+          cmStrCat("Warning: Environment variable ", name,
+                   " will be ignored, because CMAKE_GENERATOR is not set.");
         cmSystemTools::Message(message, "Warning");
       }
     }
@@ -901,10 +900,8 @@ void cmake::SetDirectoriesFromFile(const std::string& arg)
   if (cmSystemTools::FileIsDirectory(arg)) {
     std::string path = cmSystemTools::CollapseFullPath(arg);
     cmSystemTools::ConvertToUnixSlashes(path);
-    std::string cacheFile = path;
-    cacheFile += "/CMakeCache.txt";
-    std::string listFile = path;
-    listFile += "/CMakeLists.txt";
+    std::string cacheFile = cmStrCat(path, "/CMakeCache.txt");
+    std::string listFile = cmStrCat(path, "/CMakeLists.txt");
     if (cmSystemTools::FileExists(cacheFile)) {
       cachePath = path;
     }
@@ -1159,12 +1156,10 @@ std::string cmake::FindCacheFile(const std::string& binaryDir)
 {
   std::string cachePath = binaryDir;
   cmSystemTools::ConvertToUnixSlashes(cachePath);
-  std::string cacheFile = cachePath;
-  cacheFile += "/CMakeCache.txt";
+  std::string cacheFile = cmStrCat(cachePath, "/CMakeCache.txt");
   if (!cmSystemTools::FileExists(cacheFile)) {
     // search in parent directories for cache
-    std::string cmakeFiles = cachePath;
-    cmakeFiles += "/CMakeFiles";
+    std::string cmakeFiles = cmStrCat(cachePath, "/CMakeFiles");
     if (cmSystemTools::FileExists(cmakeFiles)) {
       std::string cachePathFound =
         cmSystemTools::FileExistsInParentDirectories("CMakeCache.txt",
@@ -1219,8 +1214,7 @@ void cmake::SetGlobalGenerator(cmGlobalGenerator* gg)
 int cmake::DoPreConfigureChecks()
 {
   // Make sure the Source directory contains a CMakeLists.txt file.
-  std::string srcList = this->GetHomeDirectory();
-  srcList += "/CMakeLists.txt";
+  std::string srcList = cmStrCat(this->GetHomeDirectory(), "/CMakeLists.txt");
   if (!cmSystemTools::FileExists(srcList)) {
     std::ostringstream err;
     if (cmSystemTools::FileIsDirectory(this->GetHomeDirectory())) {
@@ -1242,17 +1236,16 @@ int cmake::DoPreConfigureChecks()
   // do a sanity check on some values
   if (this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY")) {
     std::string cacheStart =
-      *this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY");
-    cacheStart += "/CMakeLists.txt";
-    std::string currentStart = this->GetHomeDirectory();
-    currentStart += "/CMakeLists.txt";
+      cmStrCat(*this->State->GetInitializedCacheValue("CMAKE_HOME_DIRECTORY"),
+               "/CMakeLists.txt");
+    std::string currentStart =
+      cmStrCat(this->GetHomeDirectory(), "/CMakeLists.txt");
     if (!cmSystemTools::SameFile(cacheStart, currentStart)) {
-      std::string message = "The source \"";
-      message += currentStart;
-      message += "\" does not match the source \"";
-      message += cacheStart;
-      message += "\" used to generate cache.  ";
-      message += "Re-run cmake with a different source directory.";
+      std::string message =
+        cmStrCat("The source \"", currentStart,
+                 "\" does not match the source \"", cacheStart,
+                 "\" used to generate cache.  Re-run cmake with a different "
+                 "source directory.");
       cmSystemTools::Error(message);
       return -2;
     }
@@ -1455,12 +1448,11 @@ int cmake::ActualConfigure()
     this->State->GetInitializedCacheValue("CMAKE_GENERATOR");
   if (genName) {
     if (!this->GlobalGenerator->MatchesGeneratorName(*genName)) {
-      std::string message = "Error: generator : ";
-      message += this->GlobalGenerator->GetName();
-      message += "\nDoes not match the generator used previously: ";
-      message += *genName;
-      message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
-                 "directory or choose a different binary directory.";
+      std::string message =
+        cmStrCat("Error: generator : ", this->GlobalGenerator->GetName(),
+                 "\nDoes not match the generator used previously: ", *genName,
+                 "\nEither remove the CMakeCache.txt file and CMakeFiles "
+                 "directory or choose a different binary directory.");
       cmSystemTools::Error(message);
       return -2;
     }
@@ -1478,12 +1470,11 @@ int cmake::ActualConfigure()
   if (const std::string* instance =
         this->State->GetInitializedCacheValue("CMAKE_GENERATOR_INSTANCE")) {
     if (this->GeneratorInstanceSet && this->GeneratorInstance != *instance) {
-      std::string message = "Error: generator instance: ";
-      message += this->GeneratorInstance;
-      message += "\nDoes not match the instance used previously: ";
-      message += *instance;
-      message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
-                 "directory or choose a different binary directory.";
+      std::string message =
+        cmStrCat("Error: generator instance: ", this->GeneratorInstance,
+                 "\nDoes not match the instance used previously: ", *instance,
+                 "\nEither remove the CMakeCache.txt file and CMakeFiles "
+                 "directory or choose a different binary directory.");
       cmSystemTools::Error(message);
       return -2;
     }
@@ -1497,12 +1488,11 @@ int cmake::ActualConfigure()
         this->State->GetInitializedCacheValue("CMAKE_GENERATOR_PLATFORM")) {
     if (this->GeneratorPlatformSet &&
         this->GeneratorPlatform != *platformName) {
-      std::string message = "Error: generator platform: ";
-      message += this->GeneratorPlatform;
-      message += "\nDoes not match the platform used previously: ";
-      message += *platformName;
-      message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
-                 "directory or choose a different binary directory.";
+      std::string message = cmStrCat(
+        "Error: generator platform: ", this->GeneratorPlatform,
+        "\nDoes not match the platform used previously: ", *platformName,
+        "\nEither remove the CMakeCache.txt file and CMakeFiles "
+        "directory or choose a different binary directory.");
       cmSystemTools::Error(message);
       return -2;
     }
@@ -1515,12 +1505,11 @@ int cmake::ActualConfigure()
   if (const std::string* tsName =
         this->State->GetInitializedCacheValue("CMAKE_GENERATOR_TOOLSET")) {
     if (this->GeneratorToolsetSet && this->GeneratorToolset != *tsName) {
-      std::string message = "Error: generator toolset: ";
-      message += this->GeneratorToolset;
-      message += "\nDoes not match the toolset used previously: ";
-      message += *tsName;
-      message += "\nEither remove the CMakeCache.txt file and CMakeFiles "
-                 "directory or choose a different binary directory.";
+      std::string message =
+        cmStrCat("Error: generator toolset: ", this->GeneratorToolset,
+                 "\nDoes not match the toolset used previously: ", *tsName,
+                 "\nEither remove the CMakeCache.txt file and CMakeFiles "
+                 "directory or choose a different binary directory.");
       cmSystemTools::Error(message);
       return -2;
     }
@@ -1778,8 +1767,8 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure)
                            "Build files cannot be regenerated correctly.");
     return ret;
   }
-  std::string message = "Build files have been written to: ";
-  message += this->GetHomeOutputDirectory();
+  std::string message = cmStrCat("Build files have been written to: ",
+                                 this->GetHomeOutputDirectory());
   this->UpdateProgress(message, -1);
   return ret;
 }
@@ -1938,8 +1927,8 @@ int cmake::LoadCache()
   // could we not read the cache
   if (!this->LoadCache(this->GetHomeOutputDirectory())) {
     // if it does exist, but isn't readable then warn the user
-    std::string cacheFile = this->GetHomeOutputDirectory();
-    cacheFile += "/CMakeCache.txt";
+    std::string cacheFile =
+      cmStrCat(this->GetHomeOutputDirectory(), "/CMakeCache.txt");
     if (cmSystemTools::FileExists(cacheFile)) {
       cmSystemTools::Error(
         "There is a CMakeCache.txt file for the current binary tree but "
@@ -2269,9 +2258,7 @@ int cmake::CheckBuildSystem()
 
 void cmake::TruncateOutputLog(const char* fname)
 {
-  std::string fullPath = this->GetHomeOutputDirectory();
-  fullPath += "/";
-  fullPath += fname;
+  std::string fullPath = cmStrCat(this->GetHomeOutputDirectory(), '/', fname);
   struct stat st;
   if (::stat(fullPath.c_str(), &st)) {
     return;
@@ -2298,10 +2285,10 @@ void cmake::GenerateGraphViz(const std::string& fileName) const
 #ifndef CMAKE_BOOTSTRAP
   cmGraphVizWriter gvWriter(this->GetGlobalGenerator());
 
-  std::string settingsFile = this->GetHomeOutputDirectory();
-  settingsFile += "/CMakeGraphVizOptions.cmake";
-  std::string fallbackSettingsFile = this->GetHomeDirectory();
-  fallbackSettingsFile += "/CMakeGraphVizOptions.cmake";
+  std::string settingsFile =
+    cmStrCat(this->GetHomeOutputDirectory(), "/CMakeGraphVizOptions.cmake");
+  std::string fallbackSettingsFile =
+    cmStrCat(this->GetHomeDirectory(), "/CMakeGraphVizOptions.cmake");
 
   gvWriter.ReadSettings(settingsFile, fallbackSettingsFile);
   gvWriter.WritePerTargetFiles(fileName);
@@ -2398,8 +2385,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
     // no option assume it is the output file
     else {
       if (!cmSystemTools::FileIsFullPath(arg)) {
-        resultFile = cwd;
-        resultFile += "/";
+        resultFile = cmStrCat(cwd, '/');
       }
       resultFile += arg;
       writeToStdout = false;
@@ -2408,12 +2394,10 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
 
   // we have to find the module directory, so we can copy the files
   this->AddCMakePaths();
-  std::string modulesPath = cmSystemTools::GetCMakeRoot();
-  modulesPath += "/Modules";
-  std::string inFile = modulesPath;
-  inFile += "/SystemInformation.cmake";
-  std::string outFile = destPath;
-  outFile += "/CMakeLists.txt";
+  std::string modulesPath =
+    cmStrCat(cmSystemTools::GetCMakeRoot(), "/Modules");
+  std::string inFile = cmStrCat(modulesPath, "/SystemInformation.cmake");
+  std::string outFile = cmStrCat(destPath, "/CMakeLists.txt");
 
   // Copy file
   if (!cmsys::SystemTools::CopyFileAlways(inFile, outFile)) {
@@ -2424,8 +2408,7 @@ int cmake::GetSystemInformation(std::vector<std::string>& args)
 
   // do we write to a file or to stdout?
   if (resultFile.empty()) {
-    resultFile = cwd;
-    resultFile += "/__cmake_systeminformation/results.txt";
+    resultFile = cmStrCat(cwd, "/__cmake_systeminformation/results.txt");
   }
 
   {
@@ -2481,8 +2464,7 @@ static bool cmakeCheckStampFile(const std::string& stampName)
   // conjunction with cmLocalVisualStudio7Generator to avoid
   // repeatedly re-running CMake when the user rebuilds the entire
   // solution.
-  std::string stampDepends = stampName;
-  stampDepends += ".depend";
+  std::string stampDepends = cmStrCat(stampName, ".depend");
 #if defined(_WIN32) || defined(__CYGWIN__)
   cmsys::ifstream fin(stampDepends.c_str(), std::ios::in | std::ios::binary);
 #else
@@ -2692,8 +2674,8 @@ int cmake::Build(int jobs, const std::string& dir,
                                "Build files cannot be regenerated correctly.");
         return ret;
       }
-      std::string message = "Build files have been written to: ";
-      message += this->GetHomeOutputDirectory();
+      std::string message = cmStrCat("Build files have been written to: ",
+                                     this->GetHomeOutputDirectory());
       this->UpdateProgress(message, -1);
 
       // Restore the previously set directories to their original value.
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index a210959..2b51a2a 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -138,11 +138,9 @@ void cmakemainProgressCallback(const std::string& m, float prog, cmake* cm)
   cmMakefile* mf = cmakemainGetMakefile(cm);
   std::string dir;
   if (mf && cmHasLiteralPrefix(m, "Configuring") && (prog < 0)) {
-    dir = " ";
-    dir += mf->GetCurrentSourceDirectory();
+    dir = cmStrCat(' ', mf->GetCurrentSourceDirectory());
   } else if (mf && cmHasLiteralPrefix(m, "Generating")) {
-    dir = " ";
-    dir += mf->GetCurrentBinaryDirectory();
+    dir = cmStrCat(' ', mf->GetCurrentBinaryDirectory());
   }
 
   if ((prog < 0) || (!dir.empty())) {
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 9f4bdda..0832e2f 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -837,8 +837,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
     // Command to start progress for a build
     if (args[1] == "cmake_progress_start" && args.size() == 4) {
       // basically remove the directory
-      std::string dirName = args[2];
-      dirName += "/Progress";
+      std::string dirName = cmStrCat(args[2], "/Progress");
       cmSystemTools::RemoveADirectory(dirName);
 
       // is the last argument a filename that exists?
@@ -855,8 +854,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args)
       if (count) {
         cmSystemTools::MakeDirectory(dirName);
         // write the count into the directory
-        std::string fName = dirName;
-        fName += "/count.txt";
+        std::string fName = cmStrCat(dirName, "/count.txt");
         FILE* progFile = cmsys::SystemTools::Fopen(fName, "w");
         if (progFile) {
           fprintf(progFile, "%i\n", count);
@@ -1346,14 +1344,12 @@ bool cmcmd::SymlinkInternal(std::string const& file, std::string const& link)
 
 static void cmcmdProgressReport(std::string const& dir, std::string const& num)
 {
-  std::string dirName = dir;
-  dirName += "/Progress";
+  std::string dirName = cmStrCat(dir, "/Progress");
   std::string fName;
   FILE* progFile;
 
   // read the count
-  fName = dirName;
-  fName += "/count.txt";
+  fName = cmStrCat(dirName, "/count.txt");
   progFile = cmsys::SystemTools::Fopen(fName, "r");
   int count = 0;
   if (!progFile) {
@@ -1368,8 +1364,7 @@ static void cmcmdProgressReport(std::string const& dir, std::string const& num)
   for (const char* c = last;; ++c) {
     if (*c == ',' || *c == '\0') {
       if (c != last) {
-        fName = dirName;
-        fName += "/";
+        fName = cmStrCat(dirName, '/');
         fName.append(last, c - last);
         progFile = cmsys::SystemTools::Fopen(fName, "w");
         if (progFile) {
-- 
cgit v0.12