Merge topic 'discourage-cmake_install'

0f76839bc7 Help: Discourage direct use of cmake_install.cmake

Acked-by: Kitware Robot <kwrobot@kitware.com>
Merge-request: !4553
diff --git a/Auxiliary/CMakeLists.txt b/Auxiliary/CMakeLists.txt
index 53cf2c5..a833c79 100644
--- a/Auxiliary/CMakeLists.txt
+++ b/Auxiliary/CMakeLists.txt
@@ -1,4 +1,4 @@
-install(DIRECTORY vim/indent vim/syntax DESTINATION ${CMAKE_DATA_DIR}/editors/vim)
-install(FILES cmake-mode.el DESTINATION ${CMAKE_DATA_DIR}/editors/emacs)
+install(DIRECTORY vim/indent vim/syntax DESTINATION ${CMAKE_XDGDATA_DIR}/vim/vimfiles)
+install(FILES cmake-mode.el DESTINATION ${CMAKE_XDGDATA_DIR}/emacs/site-lisp)
 install(FILES cmake.m4 DESTINATION ${CMAKE_XDGDATA_DIR}/aclocal)
 add_subdirectory (bash-completion)
diff --git a/Auxiliary/bash-completion/CMakeLists.txt b/Auxiliary/bash-completion/CMakeLists.txt
index c0a8899..06d22c2 100644
--- a/Auxiliary/bash-completion/CMakeLists.txt
+++ b/Auxiliary/bash-completion/CMakeLists.txt
@@ -1,8 +1,16 @@
-# Always install completion file in local dir
-# in order to be sure to always be able to install
-# in a local user directory rooted in a single directory.
-# packager should either patch that out or
-# add symlinks to the files in appropriate places
-#  /etc/bash_completion.d/
-#  DATADIR/completions (may be /usr/share/<package>/completions
-install(FILES cmake cpack ctest DESTINATION ${CMAKE_DATA_DIR}/completions)
+# We need to integrate into the system install, or this will silently fail to
+# accomplish anything at all, and packagers won't even know it exists. Use the
+# `<sharedir>/bash-completion/completions/` hierarchy by default, rooted in
+# CMake's XDGDATA_DIR definition of the sharedir. This works with installation
+# to `/usr` or `/usr/local` (or any prefix which bash-completion is configured
+# with) as well as a simple installation by a local user into their home
+# directory *if* the prefix is `$HOME/.local` since `.local/share/` is part of
+# the bash-completion search path too.
+# For more complex installations, packagers can set CMAKE_BASH_COMP_DIR to
+# another system location.
+
+set(CMAKE_BASH_COMP_DIR_DEFAULT ${CMAKE_XDGDATA_DIR}/bash-completion/completions)
+if (NOT CMAKE_BASH_COMP_DIR)
+  set(CMAKE_BASH_COMP_DIR "${CMAKE_BASH_COMP_DIR_DEFAULT}")
+endif()
+install(FILES cmake cpack ctest DESTINATION ${CMAKE_BASH_COMP_DIR})
diff --git a/Help/cpack_gen/nsis.rst b/Help/cpack_gen/nsis.rst
index a310e9f..d1e495f 100644
--- a/Help/cpack_gen/nsis.rst
+++ b/Help/cpack_gen/nsis.rst
@@ -1,7 +1,9 @@
 CPack NSIS Generator
 --------------------
 
-CPack Nullsoft Scriptable Install System (NSIS) generator specific options
+CPack Nullsoft Scriptable Install System (NSIS) generator specific options.
+
+The NSIS generator requires NSIS 3.0 or newer.
 
 Variables specific to CPack NSIS generator
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/Help/release/3.17.rst b/Help/release/3.17.rst
index c2cfdf0..7c5b44d 100644
--- a/Help/release/3.17.rst
+++ b/Help/release/3.17.rst
@@ -282,6 +282,8 @@
   option and cannot be fixed without breaking compatibility, and so have
   been superseded.
 
+* The :cpack_gen:`CPack NSIS Generator` now requires NSIS 3.0 or later.
+
 Other Changes
 =============
 
@@ -319,3 +321,15 @@
 
 * The :generator:`Xcode` generator no longer hard-codes ``-Wmost``,
   ``-Wno-four-char-constants``, and ``-Wno-unknown-pragmas`` warning flags.
+
+Updates
+=======
+
+Changes made since CMake 3.17.0 include the following.
+
+3.17.1
+------
+
+* CMake 3.17.0 updated the :cpack_gen:`CPack NSIS Generator` with changes
+  that require NSIS 3.0 or later.  CMake 3.17.1 now enforces the use
+  of a sufficiently new version.
diff --git a/Modules/CMakeDetermineCCompiler.cmake b/Modules/CMakeDetermineCCompiler.cmake
index 037c33b..9d395e5 100644
--- a/Modules/CMakeDetermineCCompiler.cmake
+++ b/Modules/CMakeDetermineCCompiler.cmake
@@ -153,7 +153,7 @@
 # NAME_WE cannot be used since then this test will fail for names like
 # "arm-unknown-nto-qnx6.3.0-gcc.exe", where BASENAME would be
 # "arm-unknown-nto-qnx6" instead of the correct "arm-unknown-nto-qnx6.3.0-"
-if (CMAKE_CROSSCOMPILING  AND NOT _CMAKE_TOOLCHAIN_PREFIX)
+if (NOT _CMAKE_TOOLCHAIN_PREFIX)
 
   if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang|QCC")
     get_filename_component(COMPILER_BASENAME "${CMAKE_C_COMPILER}" NAME)
diff --git a/Modules/CMakeDetermineCXXCompiler.cmake b/Modules/CMakeDetermineCXXCompiler.cmake
index 7274eec..ebac435 100644
--- a/Modules/CMakeDetermineCXXCompiler.cmake
+++ b/Modules/CMakeDetermineCXXCompiler.cmake
@@ -150,7 +150,7 @@
 # "arm-unknown-nto-qnx6" instead of the correct "arm-unknown-nto-qnx6.3.0-"
 
 
-if (CMAKE_CROSSCOMPILING  AND NOT  _CMAKE_TOOLCHAIN_PREFIX)
+if (NOT _CMAKE_TOOLCHAIN_PREFIX)
 
   if("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|Clang|QCC")
     get_filename_component(COMPILER_BASENAME "${CMAKE_CXX_COMPILER}" NAME)
diff --git a/Modules/CMakeDetermineFortranCompiler.cmake b/Modules/CMakeDetermineFortranCompiler.cmake
index e850541..6731abe 100644
--- a/Modules/CMakeDetermineFortranCompiler.cmake
+++ b/Modules/CMakeDetermineFortranCompiler.cmake
@@ -249,7 +249,7 @@
 # NAME_WE cannot be used since then this test will fail for names like
 # "arm-unknown-nto-qnx6.3.0-gcc.exe", where BASENAME would be
 # "arm-unknown-nto-qnx6" instead of the correct "arm-unknown-nto-qnx6.3.0-"
-if (CMAKE_CROSSCOMPILING  AND NOT _CMAKE_TOOLCHAIN_PREFIX)
+if (NOT _CMAKE_TOOLCHAIN_PREFIX)
 
   if(CMAKE_Fortran_COMPILER_ID MATCHES "GNU")
     get_filename_component(COMPILER_BASENAME "${CMAKE_Fortran_COMPILER}" NAME)
diff --git a/Modules/CMakeDetermineOBJCXXCompiler.cmake b/Modules/CMakeDetermineOBJCXXCompiler.cmake
index 60fcbb3..2cf5119 100644
--- a/Modules/CMakeDetermineOBJCXXCompiler.cmake
+++ b/Modules/CMakeDetermineOBJCXXCompiler.cmake
@@ -145,7 +145,7 @@
 # "arm-unknown-nto-qnx6" instead of the correct "arm-unknown-nto-qnx6.3.0-"
 
 
-if (CMAKE_CROSSCOMPILING  AND NOT  _CMAKE_TOOLCHAIN_PREFIX)
+if (NOT _CMAKE_TOOLCHAIN_PREFIX)
 
   if("${CMAKE_OBJCXX_COMPILER_ID}" MATCHES "GNU|Clang|QCC")
     get_filename_component(COMPILER_BASENAME "${CMAKE_OBJCXX_COMPILER}" NAME)
diff --git a/Modules/Compiler/XL-CXX.cmake b/Modules/Compiler/XL-CXX.cmake
index 3037851..41e3e11 100644
--- a/Modules/Compiler/XL-CXX.cmake
+++ b/Modules/Compiler/XL-CXX.cmake
@@ -17,8 +17,14 @@
   set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-qlanglvl=extended0x")
   set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-qlanglvl=extended0x")
   set(CMAKE_CXX98_STANDARD__HAS_FULL_SUPPORT ON)
+
+  # XL does not really have full C++11 or C++14 support, but since we do not
+  # have a granular XL-CXX-FeatureTests table for it just pretend it does.
+  # This way projects that specify granular features will at least get a
+  # compiler mode for the corresponding standard.
   set(CMAKE_CXX11_STANDARD__HAS_FULL_SUPPORT ON)
-  if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.1.0)
+
+  if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 16.1.0 AND CMAKE_SYSTEM_NAME STREQUAL "Linux")
     set(CMAKE_CXX14_STANDARD_COMPILE_OPTION "-qlanglvl=extended1y")
     set(CMAKE_CXX14_EXTENSION_COMPILE_OPTION "-qlanglvl=extended1y")
     set(CMAKE_CXX14_STANDARD__HAS_FULL_SUPPORT ON)
diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake
index 68be3f9..5467b77 100644
--- a/Modules/FindPython/Support.cmake
+++ b/Modules/FindPython/Support.cmake
@@ -1046,7 +1046,7 @@
           if (_${_PYTHON_PREFIX}_EXECUTABLE)
             break()
           endif()
-          if (NOT _${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY")
+          if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY")
             break()
           endif()
         endif()
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index b37e1ee..b2b6e54 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,7 +1,7 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 17)
-set(CMake_VERSION_PATCH 20200331)
+set(CMake_VERSION_PATCH 20200402)
 #set(CMake_VERSION_RC 0)
 set(CMake_VERSION_IS_DIRTY 0)
 
diff --git a/Source/CPack/cmCPackNSISGenerator.cxx b/Source/CPack/cmCPackNSISGenerator.cxx
index 6b30407..9afdc62 100644
--- a/Source/CPack/cmCPackNSISGenerator.cxx
+++ b/Source/CPack/cmCPackNSISGenerator.cxx
@@ -453,12 +453,12 @@
   }
   if (versionRex.find(output)) {
     double nsisVersion = atof(versionRex.match(1).c_str());
-    double minNSISVersion = 2.09;
+    double minNSISVersion = 3.0;
     cmCPackLogger(cmCPackLog::LOG_DEBUG,
                   "NSIS Version: " << nsisVersion << std::endl);
     if (nsisVersion < minNSISVersion) {
       cmCPackLogger(cmCPackLog::LOG_ERROR,
-                    "CPack requires NSIS Version 2.09 or greater.  "
+                    "CPack requires NSIS Version 3.0 or greater.  "
                     "NSIS found on the system was: "
                       << nsisVersion << std::endl);
       return 0;
diff --git a/Source/Checks/cm_cxx_features.cmake b/Source/Checks/cm_cxx_features.cmake
index c16286c..3b00dfb 100644
--- a/Source/Checks/cm_cxx_features.cmake
+++ b/Source/Checks/cm_cxx_features.cmake
@@ -32,8 +32,6 @@
     string(REGEX REPLACE "[^\n]* xcodebuild\\[[0-9]*:[0-9]*\\] warning: [^\n]*" "" check_output "${check_output}")
     # Filter out ld warnings.
     string(REGEX REPLACE "[^\n]*ld: warning: [^\n]*" "" check_output "${check_output}")
-    # Filter out CUDA installation warnings.
-    string(REGEX REPLACE "[^\n]*clang: warning: Unknown CUDA version[^\n]*" "" check_output "${check_output}")
     # If using the feature causes warnings, treat it as broken/unavailable.
     if(check_output MATCHES "(^|[ :])[Ww][Aa][Rr][Nn][Ii][Nn][Gg]")
       set(CMake_HAVE_CXX_${FEATURE} OFF CACHE INTERNAL "TRY_COMPILE" FORCE)
diff --git a/Source/cmExportLibraryDependenciesCommand.cxx b/Source/cmExportLibraryDependenciesCommand.cxx
index 6011ba4..be63278 100644
--- a/Source/cmExportLibraryDependenciesCommand.cxx
+++ b/Source/cmExportLibraryDependenciesCommand.cxx
@@ -23,6 +23,8 @@
 
 class cmListFileBacktrace;
 
+using cmProp = const std::string*;
+
 static void FinalAction(cmMakefile& makefile, std::string const& filename,
                         bool append)
 {
@@ -95,8 +97,8 @@
           // Handle simple output name changes.  This command is
           // deprecated so we do not support full target name
           // translation (which requires per-configuration info).
-          if (const char* outname = libtgt->GetProperty("OUTPUT_NAME")) {
-            lib = outname;
+          if (cmProp outname = libtgt->GetProperty("OUTPUT_NAME")) {
+            lib = *outname;
           }
         }
         valueOld += lib;
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
index c0db90f..dfc354d 100644
--- a/Source/cmGeneratorExpressionNode.cxx
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -907,8 +907,8 @@
     }
 
     if (context->CurrentTarget && context->CurrentTarget->IsImported()) {
-      const char* loc = nullptr;
-      const char* imp = nullptr;
+      cmProp loc = nullptr;
+      cmProp imp = nullptr;
       std::string suffix;
       if (context->CurrentTarget->Target->GetMappedConfig(context->Config, loc,
                                                           imp, suffix)) {
@@ -1565,11 +1565,11 @@
     std::vector<std::string> objects;
 
     if (gt->IsImported()) {
-      const char* loc = nullptr;
-      const char* imp = nullptr;
+      cmProp loc = nullptr;
+      cmProp imp = nullptr;
       std::string suffix;
       if (gt->Target->GetMappedConfig(context->Config, loc, imp, suffix)) {
-        cmExpandList(loc, objects);
+        cmExpandList(*loc, objects);
       }
       context->HadContextSensitiveCondition = true;
     } else {
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index e722034..e81b619 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -383,7 +383,8 @@
   if (cmSystemTools::GetFatalErrorOccured()) {
     return nullptr;
   }
-  return this->Target->GetProperty(prop);
+  cmProp retval = this->Target->GetProperty(prop);
+  return retval ? retval->c_str() : nullptr;
 }
 
 const char* cmGeneratorTarget::GetSafeProperty(const std::string& prop) const
@@ -6349,8 +6350,8 @@
   // Initialize members.
   info.NoSOName = false;
 
-  const char* loc = nullptr;
-  const char* imp = nullptr;
+  cmProp loc = nullptr;
+  cmProp imp = nullptr;
   std::string suffix;
   if (!this->Target->GetMappedConfig(desired_config, loc, imp, suffix)) {
     return;
@@ -6379,7 +6380,7 @@
   }
   if (this->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
     if (loc) {
-      info.LibName = loc;
+      info.LibName = *loc;
     }
     return;
   }
@@ -6389,7 +6390,7 @@
 
   // Get the location.
   if (loc) {
-    info.Location = loc;
+    info.Location = *loc;
   } else {
     std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix);
     if (const char* config_location = this->GetProperty(impProp)) {
@@ -6422,7 +6423,7 @@
 
   // Get the import library.
   if (imp) {
-    info.ImportLibrary = imp;
+    info.ImportLibrary = *imp;
   } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
              this->IsExecutableWithExports()) {
     std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx
index 1d8f0a9..c704803 100644
--- a/Source/cmGetPropertyCommand.cxx
+++ b/Source/cmGetPropertyCommand.cxx
@@ -310,7 +310,7 @@
       }
       return StoreResult(infoType, status.GetMakefile(), variable, nullptr);
     }
-    const char* prop_cstr = nullptr;
+    cmProp prop_cstr = nullptr;
     cmListFileBacktrace bt = status.GetMakefile().GetBacktrace();
     cmMessenger* messenger = status.GetMakefile().GetMessenger();
     if (cmTargetPropertyComputer::PassesWhitelist(
@@ -320,7 +320,8 @@
         prop_cstr = target->GetProperty(propertyName);
       }
     }
-    return StoreResult(infoType, status.GetMakefile(), variable, prop_cstr);
+    return StoreResult(infoType, status.GetMakefile(), variable,
+                       prop_cstr ? prop_cstr->c_str() : nullptr);
   }
   status.SetError(cmStrCat("could not find TARGET ", name,
                            ".  Perhaps it has not yet been created."));
diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx
index 7f5df9c..6b850d1 100644
--- a/Source/cmGetTargetPropertyCommand.cxx
+++ b/Source/cmGetTargetPropertyCommand.cxx
@@ -34,7 +34,7 @@
         prop_exists = true;
       }
     } else if (!args[2].empty()) {
-      const char* prop_cstr = nullptr;
+      cmProp prop_cstr = nullptr;
       cmListFileBacktrace bt = mf.GetBacktrace();
       cmMessenger* messenger = mf.GetMessenger();
       if (cmTargetPropertyComputer::PassesWhitelist(tgt->GetType(), args[2],
@@ -45,7 +45,7 @@
         }
       }
       if (prop_cstr) {
-        prop = prop_cstr;
+        prop = *prop_cstr;
         prop_exists = true;
       }
     }
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 6d08369..152e294 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1790,14 +1790,13 @@
         }
       }
       std::vector<std::string> incs;
-      const char* incDirProp =
-        target.second.GetProperty("INCLUDE_DIRECTORIES");
+      cmProp incDirProp = target.second.GetProperty("INCLUDE_DIRECTORIES");
       if (!incDirProp) {
         continue;
       }
 
       std::string incDirs = cmGeneratorExpression::Preprocess(
-        incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions);
+        *incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions);
 
       cmExpandList(incDirs, incs);
 
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index d669ed7..704db66 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -680,9 +680,9 @@
     }
 
     if (createInstallGeneratorsForTargetFileSets && !namelinkOnly) {
-      const char* files = target.GetProperty("PRIVATE_HEADER");
-      if ((files) && (*files)) {
-        std::vector<std::string> relFiles = cmExpandedList(files);
+      cmProp files = target.GetProperty("PRIVATE_HEADER");
+      if (files && !files->empty()) {
+        std::vector<std::string> relFiles = cmExpandedList(*files);
         std::vector<std::string> absFiles;
         if (!helper.MakeFilesFullPath("PRIVATE_HEADER", relFiles, absFiles)) {
           return false;
@@ -703,8 +703,8 @@
       }
 
       files = target.GetProperty("PUBLIC_HEADER");
-      if ((files) && (*files)) {
-        std::vector<std::string> relFiles = cmExpandedList(files);
+      if (files && !files->empty()) {
+        std::vector<std::string> relFiles = cmExpandedList(*files);
         std::vector<std::string> absFiles;
         if (!helper.MakeFilesFullPath("PUBLIC_HEADER", relFiles, absFiles)) {
           return false;
@@ -725,8 +725,8 @@
       }
 
       files = target.GetProperty("RESOURCE");
-      if ((files) && (*files)) {
-        std::vector<std::string> relFiles = cmExpandedList(files);
+      if (files && !files->empty()) {
+        std::vector<std::string> relFiles = cmExpandedList(*files);
         std::vector<std::string> absFiles;
         if (!helper.MakeFilesFullPath("RESOURCE", relFiles, absFiles)) {
           return false;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 812f922..af6b44e 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -2473,14 +2473,14 @@
         t.GetType() == cmStateEnums::GLOBAL_TARGET) {
       continue;
     }
-    includeDirs = t.GetProperty("INCLUDE_DIRECTORIES");
-    if (mightExpandVariablesCMP0019(includeDirs)) {
-      std::string dirs = includeDirs;
+    cmProp includeDirs2 = t.GetProperty("INCLUDE_DIRECTORIES");
+    if (includeDirs2 && mightExpandVariablesCMP0019(includeDirs2->c_str())) {
+      std::string dirs = *includeDirs2;
       this->ExpandVariablesInString(dirs, true, true);
-      if (pol == cmPolicies::WARN && dirs != includeDirs) {
+      if (pol == cmPolicies::WARN && dirs != *includeDirs2) {
         /* clang-format off */
         w << "Evaluated target " << t.GetName() << " INCLUDE_DIRECTORIES\n"
-          << "  " << includeDirs << "\n"
+          << "  " << *includeDirs2 << "\n"
           << "as\n"
           << "  " << dirs << "\n";
         /* clang-format on */
@@ -2492,7 +2492,7 @@
   if (const char* linkDirsProp = this->GetProperty("LINK_DIRECTORIES")) {
     if (mightExpandVariablesCMP0019(linkDirsProp)) {
       std::string d = linkDirsProp;
-      std::string orig = linkDirsProp;
+      const std::string orig = d;
       this->ExpandVariablesInString(d, true, true);
       if (pol == cmPolicies::WARN && d != orig) {
         /* clang-format off */
@@ -2518,7 +2518,7 @@
         libName = *l;
       }
       if (mightExpandVariablesCMP0019(libName.c_str())) {
-        std::string orig = libName;
+        const std::string orig = libName;
         this->ExpandVariablesInString(libName, true, true);
         if (pol == cmPolicies::WARN && libName != orig) {
           /* clang-format off */
@@ -3031,7 +3031,7 @@
           openstack.pop_back();
           result.append(last, in - last);
           std::string const& lookup = result.substr(var.loc);
-          const char* value = nullptr;
+          cmProp value = nullptr;
           std::string varresult;
           std::string svalue;
           switch (var.domain) {
@@ -3039,26 +3039,24 @@
               if (filename && lookup == lineVar) {
                 varresult = std::to_string(line);
               } else {
-                value = this->GetDefinition(lookup);
+                value = this->GetDef(lookup);
               }
               break;
             case ENVIRONMENT:
               if (cmSystemTools::GetEnv(lookup, svalue)) {
-                value = svalue.c_str();
+                value = &svalue;
               }
               break;
             case CACHE:
-              if (cmProp value2 = state->GetCacheEntryValue(lookup)) {
-                value = value2->c_str();
-              }
+              value = state->GetCacheEntryValue(lookup);
               break;
           }
           // Get the string we're meant to append to.
           if (value) {
             if (escapeQuotes) {
-              varresult = cmEscapeQuotes(value);
+              varresult = cmEscapeQuotes(*value);
             } else {
-              varresult = value;
+              varresult = *value;
             }
           } else if (!this->SuppressSideEffects) {
             this->MaybeWarnUninitialized(lookup, filename);
@@ -4800,8 +4798,8 @@
                                         const std::string& feature,
                                         std::string const& lang) const
 {
-  const char* defaultCStandard =
-    this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
+  cmProp defaultCStandard =
+    this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
   if (!defaultCStandard) {
     this->IssueMessage(
       MessageType::INTERNAL_ERROR,
@@ -4812,11 +4810,11 @@
     return true;
   }
   if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
-                   cmStrCmp(defaultCStandard)) == cm::cend(C_STANDARDS)) {
+                   cmStrCmp(*defaultCStandard)) == cm::cend(C_STANDARDS)) {
     const std::string e = cmStrCat("The CMAKE_", lang,
                                    "_STANDARD_DEFAULT variable contains an "
                                    "invalid value: \"",
-                                   defaultCStandard, "\".");
+                                   *defaultCStandard, "\".");
     this->IssueMessage(MessageType::INTERNAL_ERROR, e);
     return false;
   }
@@ -4827,24 +4825,23 @@
 
   this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11);
 
-  const char* existingCStandard =
-    target->GetProperty(cmStrCat(lang, "_STANDARD"));
+  cmProp existingCStandard = target->GetProperty(cmStrCat(lang, "_STANDARD"));
   if (!existingCStandard) {
     existingCStandard = defaultCStandard;
   }
 
   if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
-                   cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) {
+                   cmStrCmp(*existingCStandard)) == cm::cend(C_STANDARDS)) {
     const std::string e = cmStrCat(
       "The ", lang, "_STANDARD property on target \"", target->GetName(),
-      "\" contained an invalid value: \"", existingCStandard, "\".");
+      "\" contained an invalid value: \"", *existingCStandard, "\".");
     this->IssueMessage(MessageType::FATAL_ERROR, e);
     return false;
   }
 
   const char* const* existingCIt = existingCStandard
     ? std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
-                   cmStrCmp(existingCStandard))
+                   cmStrCmp(*existingCStandard))
     : cm::cend(C_STANDARDS);
 
   if (needC11 && existingCStandard &&
@@ -4895,8 +4892,8 @@
                                           const std::string& feature,
                                           std::string const& lang) const
 {
-  const char* defaultCxxStandard =
-    this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
+  cmProp defaultCxxStandard =
+    this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
   if (!defaultCxxStandard) {
     this->IssueMessage(
       MessageType::INTERNAL_ERROR,
@@ -4907,10 +4904,10 @@
     return true;
   }
   if (std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
-                   cmStrCmp(defaultCxxStandard)) == cm::cend(CXX_STANDARDS)) {
+                   cmStrCmp(*defaultCxxStandard)) == cm::cend(CXX_STANDARDS)) {
     const std::string e =
       cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an ",
-               "invalid value: \"", defaultCxxStandard, "\".");
+               "invalid value: \"", *defaultCxxStandard, "\".");
     this->IssueMessage(MessageType::INTERNAL_ERROR, e);
     return false;
   }
@@ -4923,7 +4920,7 @@
   this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14,
                                needCxx17, needCxx20);
 
-  const char* existingCxxStandard =
+  cmProp existingCxxStandard =
     target->GetProperty(cmStrCat(lang, "_STANDARD"));
   if (!existingCxxStandard) {
     existingCxxStandard = defaultCxxStandard;
@@ -4931,11 +4928,11 @@
 
   const char* const* existingCxxLevel =
     std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
-                 cmStrCmp(existingCxxStandard));
+                 cmStrCmp(*existingCxxStandard));
   if (existingCxxLevel == cm::cend(CXX_STANDARDS)) {
     const std::string e = cmStrCat(
       "The ", lang, "_STANDARD property on target \"", target->GetName(),
-      "\" contained an invalid value: \"", existingCxxStandard, "\".");
+      "\" contained an invalid value: \"", *existingCxxStandard, "\".");
     this->IssueMessage(MessageType::FATAL_ERROR, e);
     return false;
   }
@@ -5000,12 +4997,12 @@
   this->CheckNeededCxxLanguage(feature, lang, needCxx98, needCxx11, needCxx14,
                                needCxx17, needCxx20);
 
-  const char* existingCxxStandard =
+  cmProp existingCxxStandard =
     target->GetProperty(cmStrCat(lang, "_STANDARD"));
   if (existingCxxStandard == nullptr) {
-    const char* defaultCxxStandard =
-      this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
-    if (defaultCxxStandard && *defaultCxxStandard) {
+    cmProp defaultCxxStandard =
+      this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
+    if (defaultCxxStandard && !defaultCxxStandard->empty()) {
       existingCxxStandard = defaultCxxStandard;
     }
   }
@@ -5013,11 +5010,11 @@
   if (existingCxxStandard) {
     existingCxxLevel =
       std::find_if(cm::cbegin(CXX_STANDARDS), cm::cend(CXX_STANDARDS),
-                   cmStrCmp(existingCxxStandard));
+                   cmStrCmp(*existingCxxStandard));
     if (existingCxxLevel == cm::cend(CXX_STANDARDS)) {
       const std::string e = cmStrCat(
         "The ", lang, "_STANDARD property on target \"", target->GetName(),
-        "\" contained an invalid value: \"", existingCxxStandard, "\".");
+        "\" contained an invalid value: \"", *existingCxxStandard, "\".");
       if (error) {
         *error = e;
       } else {
@@ -5053,8 +5050,8 @@
                                            const std::string& feature,
                                            std::string const& lang) const
 {
-  const char* defaultCudaStandard =
-    this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
+  cmProp defaultCudaStandard =
+    this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
   if (!defaultCudaStandard) {
     this->IssueMessage(
       MessageType::INTERNAL_ERROR,
@@ -5065,11 +5062,11 @@
     return true;
   }
   if (std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS),
-                   cmStrCmp(defaultCudaStandard)) ==
+                   cmStrCmp(*defaultCudaStandard)) ==
       cm::cend(CUDA_STANDARDS)) {
     const std::string e =
       cmStrCat("The CMAKE_", lang, "_STANDARD_DEFAULT variable contains an ",
-               "invalid value: \"", defaultCudaStandard, "\".");
+               "invalid value: \"", *defaultCudaStandard, "\".");
     this->IssueMessage(MessageType::INTERNAL_ERROR, e);
     return false;
   }
@@ -5082,7 +5079,7 @@
   this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11,
                                 needCuda14, needCuda17, needCuda20);
 
-  const char* existingCudaStandard =
+  cmProp existingCudaStandard =
     target->GetProperty(cmStrCat(lang, "_STANDARD"));
   if (!existingCudaStandard) {
     existingCudaStandard = defaultCudaStandard;
@@ -5090,11 +5087,11 @@
 
   const char* const* existingCudaLevel =
     std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS),
-                 cmStrCmp(existingCudaStandard));
+                 cmStrCmp(*existingCudaStandard));
   if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) {
     const std::string e = cmStrCat(
       "The ", lang, "_STANDARD property on target \"", target->GetName(),
-      "\" contained an invalid value: \"", existingCudaStandard, "\".");
+      "\" contained an invalid value: \"", *existingCudaStandard, "\".");
     this->IssueMessage(MessageType::FATAL_ERROR, e);
     return false;
   }
@@ -5159,12 +5156,12 @@
   this->CheckNeededCudaLanguage(feature, lang, needCuda03, needCuda11,
                                 needCuda14, needCuda17, needCuda20);
 
-  const char* existingCudaStandard =
+  cmProp existingCudaStandard =
     target->GetProperty(cmStrCat(lang, "_STANDARD"));
   if (existingCudaStandard == nullptr) {
-    const char* defaultCudaStandard =
-      this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
-    if (defaultCudaStandard && *defaultCudaStandard) {
+    cmProp defaultCudaStandard =
+      this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
+    if (defaultCudaStandard && !defaultCudaStandard->empty()) {
       existingCudaStandard = defaultCudaStandard;
     }
   }
@@ -5172,11 +5169,11 @@
   if (existingCudaStandard) {
     existingCudaLevel =
       std::find_if(cm::cbegin(CUDA_STANDARDS), cm::cend(CUDA_STANDARDS),
-                   cmStrCmp(existingCudaStandard));
+                   cmStrCmp(*existingCudaStandard));
     if (existingCudaLevel == cm::cend(CUDA_STANDARDS)) {
       const std::string e = cmStrCat(
         "The ", lang, "_STANDARD property on target \"", target->GetName(),
-        "\" contained an invalid value: \"", existingCudaStandard, "\".");
+        "\" contained an invalid value: \"", *existingCudaStandard, "\".");
       if (error) {
         *error = e;
       } else {
@@ -5240,21 +5237,20 @@
 
   this->CheckNeededCLanguage(feature, lang, needC90, needC99, needC11);
 
-  const char* existingCStandard =
-    target->GetProperty(cmStrCat(lang, "_STANDARD"));
+  cmProp existingCStandard = target->GetProperty(cmStrCat(lang, "_STANDARD"));
   if (existingCStandard == nullptr) {
-    const char* defaultCStandard =
-      this->GetDefinition(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
-    if (defaultCStandard && *defaultCStandard) {
+    cmProp defaultCStandard =
+      this->GetDef(cmStrCat("CMAKE_", lang, "_STANDARD_DEFAULT"));
+    if (defaultCStandard && !defaultCStandard->empty()) {
       existingCStandard = defaultCStandard;
     }
   }
   if (existingCStandard) {
     if (std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
-                     cmStrCmp(existingCStandard)) == cm::cend(C_STANDARDS)) {
+                     cmStrCmp(*existingCStandard)) == cm::cend(C_STANDARDS)) {
       const std::string e = cmStrCat(
         "The ", lang, "_STANDARD property on target \"", target->GetName(),
-        "\" contained an invalid value: \"", existingCStandard, "\".");
+        "\" contained an invalid value: \"", *existingCStandard, "\".");
       if (error) {
         *error = e;
       } else {
@@ -5266,7 +5262,7 @@
   }
   const char* const* existingCIt = existingCStandard
     ? std::find_if(cm::cbegin(C_STANDARDS), cm::cend(C_STANDARDS),
-                   cmStrCmp(existingCStandard))
+                   cmStrCmp(*existingCStandard))
     : cm::cend(C_STANDARDS);
 
   bool setC90 = needC90 && !existingCStandard;
diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx
index 147f97f..b18c205 100644
--- a/Source/cmOutputRequiredFilesCommand.cxx
+++ b/Source/cmOutputRequiredFilesCommand.cxx
@@ -20,6 +20,8 @@
 #include "cmSystemTools.h"
 #include "cmTarget.h"
 
+using cmProp = const std::string*;
+
 namespace {
 /** \class cmDependInformation
  * \brief Store dependency information for a single source file.
@@ -117,14 +119,13 @@
     std::set<std::string> uniqueIncludes;
     std::vector<std::string> orderedAndUniqueIncludes;
     for (auto const& target : this->Makefile->GetTargets()) {
-      const char* incDirProp =
-        target.second.GetProperty("INCLUDE_DIRECTORIES");
+      cmProp incDirProp = target.second.GetProperty("INCLUDE_DIRECTORIES");
       if (!incDirProp) {
         continue;
       }
 
       std::string incDirs = cmGeneratorExpression::Preprocess(
-        incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions);
+        *incDirProp, cmGeneratorExpression::StripAllGeneratorExpressions);
 
       std::vector<std::string> includes = cmExpandedList(incDirs);
 
diff --git a/Source/cmState.cxx b/Source/cmState.cxx
index 5a113dd..2dfdcf7 100644
--- a/Source/cmState.cxx
+++ b/Source/cmState.cxx
@@ -26,6 +26,8 @@
 #include "cmSystemTools.h"
 #include "cmake.h"
 
+using cmProp = const std::string*;
+
 cmState::cmState()
 {
   this->CacheManager = cm::make_unique<cmCacheManager>();
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 93c168a..063576c 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -1301,8 +1301,8 @@
     reusedTarget->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY",
                               cmStrCat(reusedFrom, ".dir/"));
 
-    this->SetProperty("COMPILE_PDB_NAME",
-                      reusedTarget->GetProperty("COMPILE_PDB_NAME"));
+    cmProp tmp = reusedTarget->GetProperty("COMPILE_PDB_NAME");
+    this->SetProperty("COMPILE_PDB_NAME", tmp ? tmp->c_str() : nullptr);
     this->AddUtility(reusedFrom, false, impl->Makefile);
   } else {
     impl->Properties.SetProperty(prop, value);
@@ -1506,7 +1506,7 @@
 }
 
 static void cmTargetCheckLINK_INTERFACE_LIBRARIES(const std::string& prop,
-                                                  const char* value,
+                                                  const std::string& value,
                                                   cmMakefile* context,
                                                   bool imported)
 {
@@ -1544,7 +1544,7 @@
   context->IssueMessage(MessageType::FATAL_ERROR, e.str());
 }
 
-static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value,
+static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const std::string& value,
                                                   cmMakefile* context)
 {
   // Look for link-type keywords in the value.
@@ -1589,18 +1589,18 @@
 {
   // Certain properties need checking.
   if (cmHasLiteralPrefix(prop, "LINK_INTERFACE_LIBRARIES")) {
-    if (const char* value = this->GetProperty(prop)) {
-      cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, false);
+    if (cmProp value = this->GetProperty(prop)) {
+      cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, *value, context, false);
     }
   }
   if (cmHasLiteralPrefix(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES")) {
-    if (const char* value = this->GetProperty(prop)) {
-      cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, true);
+    if (cmProp value = this->GetProperty(prop)) {
+      cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, *value, context, true);
     }
   }
   if (prop == "INTERFACE_LINK_LIBRARIES") {
-    if (const char* value = this->GetProperty(prop)) {
-      cmTargetCheckINTERFACE_LINK_LIBRARIES(value, context);
+    if (cmProp value = this->GetProperty(prop)) {
+      cmTargetCheckINTERFACE_LINK_LIBRARIES(*value, context);
     }
   }
   if (prop == "IMPORTED_GLOBAL") {
@@ -1610,16 +1610,14 @@
   }
 }
 
-const char* cmTarget::GetComputedProperty(
-  const std::string& prop, cmMessenger* messenger,
-  cmListFileBacktrace const& context) const
+cmProp cmTarget::GetComputedProperty(const std::string& prop,
+                                     cmMessenger* messenger,
+                                     cmListFileBacktrace const& context) const
 {
-  cmProp retVal =
-    cmTargetPropertyComputer::GetProperty(this, prop, messenger, context);
-  return retVal ? retVal->c_str() : nullptr;
+  return cmTargetPropertyComputer::GetProperty(this, prop, messenger, context);
 }
 
-const char* cmTarget::GetProperty(const std::string& prop) const
+cmProp cmTarget::GetProperty(const std::string& prop) const
 {
 #define MAKE_STATIC_PROP(PROP) static const std::string prop##PROP = #PROP
   MAKE_STATIC_PROP(LINK_LIBRARIES);
@@ -1638,6 +1636,8 @@
   MAKE_STATIC_PROP(BINARY_DIR);
   MAKE_STATIC_PROP(SOURCE_DIR);
   MAKE_STATIC_PROP(SOURCES);
+  MAKE_STATIC_PROP(FALSE);
+  MAKE_STATIC_PROP(TRUE);
 #undef MAKE_STATIC_PROP
   static std::unordered_set<std::string> const specialProps{
     propLINK_LIBRARIES,
@@ -1665,11 +1665,11 @@
 
       static std::string output;
       output = cmJoin(impl->LinkImplementationPropertyEntries, ";");
-      return output.c_str();
+      return &output;
     }
     // the type property returns what type the target is
     if (prop == propTYPE) {
-      return cmState::GetTargetTypeName(this->GetType()).c_str();
+      return &cmState::GetTargetTypeName(this->GetType());
     }
     if (prop == propINCLUDE_DIRECTORIES) {
       if (impl->IncludeDirectoriesEntries.empty()) {
@@ -1678,7 +1678,7 @@
 
       static std::string output;
       output = cmJoin(impl->IncludeDirectoriesEntries, ";");
-      return output.c_str();
+      return &output;
     }
     if (prop == propCOMPILE_FEATURES) {
       if (impl->CompileFeaturesEntries.empty()) {
@@ -1687,7 +1687,7 @@
 
       static std::string output;
       output = cmJoin(impl->CompileFeaturesEntries, ";");
-      return output.c_str();
+      return &output;
     }
     if (prop == propCOMPILE_OPTIONS) {
       if (impl->CompileOptionsEntries.empty()) {
@@ -1696,7 +1696,7 @@
 
       static std::string output;
       output = cmJoin(impl->CompileOptionsEntries, ";");
-      return output.c_str();
+      return &output;
     }
     if (prop == propCOMPILE_DEFINITIONS) {
       if (impl->CompileDefinitionsEntries.empty()) {
@@ -1705,7 +1705,7 @@
 
       static std::string output;
       output = cmJoin(impl->CompileDefinitionsEntries, ";");
-      return output.c_str();
+      return &output;
     }
     if (prop == propLINK_OPTIONS) {
       if (impl->LinkOptionsEntries.empty()) {
@@ -1714,7 +1714,7 @@
 
       static std::string output;
       output = cmJoin(impl->LinkOptionsEntries, ";");
-      return output.c_str();
+      return &output;
     }
     if (prop == propLINK_DIRECTORIES) {
       if (impl->LinkDirectoriesEntries.empty()) {
@@ -1724,7 +1724,7 @@
       static std::string output;
       output = cmJoin(impl->LinkDirectoriesEntries, ";");
 
-      return output.c_str();
+      return &output;
     }
     if (prop == propMANUALLY_ADDED_DEPENDENCIES) {
       if (impl->Utilities.empty()) {
@@ -1740,7 +1740,7 @@
           return item.Value.first;
         });
       output = cmJoin(utilities, ";");
-      return output.c_str();
+      return &output;
     }
     if (prop == propPRECOMPILE_HEADERS) {
       if (impl->PrecompileHeadersEntries.empty()) {
@@ -1749,28 +1749,26 @@
 
       static std::string output;
       output = cmJoin(impl->PrecompileHeadersEntries, ";");
-      return output.c_str();
+      return &output;
     }
     if (prop == propIMPORTED) {
-      return this->IsImported() ? "TRUE" : "FALSE";
+      return this->IsImported() ? &propTRUE : &propFALSE;
     }
     if (prop == propIMPORTED_GLOBAL) {
-      return this->IsImportedGloballyVisible() ? "TRUE" : "FALSE";
+      return this->IsImportedGloballyVisible() ? &propTRUE : &propFALSE;
     }
     if (prop == propNAME) {
-      return this->GetName().c_str();
+      return &this->GetName();
     }
     if (prop == propBINARY_DIR) {
-      return impl->Makefile->GetStateSnapshot()
-        .GetDirectory()
-        .GetCurrentBinary()
-        .c_str();
+      return &impl->Makefile->GetStateSnapshot()
+                .GetDirectory()
+                .GetCurrentBinary();
     }
     if (prop == propSOURCE_DIR) {
-      return impl->Makefile->GetStateSnapshot()
-        .GetDirectory()
-        .GetCurrentSource()
-        .c_str();
+      return &impl->Makefile->GetStateSnapshot()
+                .GetDirectory()
+                .GetCurrentSource();
     }
   }
 
@@ -1779,29 +1777,27 @@
     const bool chain =
       impl->Makefile->GetState()->IsPropertyChained(prop, cmProperty::TARGET);
     if (chain) {
-      retVal = impl->Makefile->GetStateSnapshot().GetDirectory().GetProperty(
+      return impl->Makefile->GetStateSnapshot().GetDirectory().GetProperty(
         prop, chain);
-      if (retVal) {
-        return retVal->c_str();
-      }
     }
     return nullptr;
   }
-  return retVal->c_str();
+  return retVal;
 }
 
 const char* cmTarget::GetSafeProperty(const std::string& prop) const
 {
-  const char* ret = this->GetProperty(prop);
+  cmProp ret = this->GetProperty(prop);
   if (!ret) {
     return "";
   }
-  return ret;
+  return ret->c_str();
 }
 
 bool cmTarget::GetPropertyAsBool(const std::string& prop) const
 {
-  return cmIsOn(this->GetProperty(prop));
+  cmProp p = this->GetProperty(prop);
+  return p && cmIsOn(*p);
 }
 
 cmPropertyMap const& cmTarget::GetProperties() const
@@ -1930,8 +1926,8 @@
 
   std::string result;
 
-  const char* loc = nullptr;
-  const char* imp = nullptr;
+  cmProp loc = nullptr;
+  cmProp imp = nullptr;
   std::string suffix;
 
   if (this->GetType() != cmStateEnums::INTERFACE_LIBRARY &&
@@ -1939,29 +1935,28 @@
     switch (artifact) {
       case cmStateEnums::RuntimeBinaryArtifact:
         if (loc) {
-          result = loc;
+          result = *loc;
         } else {
           std::string impProp = cmStrCat("IMPORTED_LOCATION", suffix);
-          if (const char* config_location = this->GetProperty(impProp)) {
-            result = config_location;
-          } else if (const char* location =
+          if (cmProp config_location = this->GetProperty(impProp)) {
+            result = *config_location;
+          } else if (cmProp location =
                        this->GetProperty("IMPORTED_LOCATION")) {
-            result = location;
+            result = *location;
           }
         }
         break;
 
       case cmStateEnums::ImportLibraryArtifact:
         if (imp) {
-          result = imp;
+          result = *imp;
         } else if (this->GetType() == cmStateEnums::SHARED_LIBRARY ||
                    this->IsExecutableWithExports()) {
           std::string impProp = cmStrCat("IMPORTED_IMPLIB", suffix);
-          if (const char* config_implib = this->GetProperty(impProp)) {
-            result = config_implib;
-          } else if (const char* implib =
-                       this->GetProperty("IMPORTED_IMPLIB")) {
-            result = implib;
+          if (cmProp config_implib = this->GetProperty(impProp)) {
+            result = *config_implib;
+          } else if (cmProp implib = this->GetProperty("IMPORTED_IMPLIB")) {
+            result = *implib;
           }
         }
         break;
@@ -2004,9 +1999,8 @@
   return true;
 }
 
-bool cmTarget::GetMappedConfig(std::string const& desired_config,
-                               const char*& loc, const char*& imp,
-                               std::string& suffix) const
+bool cmTarget::GetMappedConfig(std::string const& desired_config, cmProp& loc,
+                               cmProp& imp, std::string& suffix) const
 {
   std::string config_upper;
   if (!desired_config.empty()) {
@@ -2028,8 +2022,8 @@
   std::vector<std::string> mappedConfigs;
   {
     std::string mapProp = cmStrCat("MAP_IMPORTED_CONFIG_", config_upper);
-    if (const char* mapValue = this->GetProperty(mapProp)) {
-      cmExpandList(mapValue, mappedConfigs, true);
+    if (cmProp mapValue = this->GetProperty(mapProp)) {
+      cmExpandList(*mapValue, mappedConfigs, true);
     }
   }
 
@@ -2110,8 +2104,8 @@
   // any available configuration.
   if (!loc && !imp) {
     std::vector<std::string> availableConfigs;
-    if (const char* iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) {
-      cmExpandList(iconfigs, availableConfigs);
+    if (cmProp iconfigs = this->GetProperty("IMPORTED_CONFIGURATIONS")) {
+      cmExpandList(*iconfigs, availableConfigs);
     }
     for (auto aci = availableConfigs.begin();
          !loc && !imp && aci != availableConfigs.end(); ++aci) {
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 463b234..ddc3b9b 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -28,6 +28,8 @@
 class cmSourceFile;
 class cmTargetInternals;
 
+using cmProp = const std::string*;
+
 /** \class cmTarget
  * \brief Represent a library or executable target loaded from a makefile.
  *
@@ -170,14 +172,13 @@
   void AppendProperty(const std::string& prop, const std::string& value,
                       bool asString = false);
   //! Might return a nullptr if the property is not set or invalid
-  const char* GetProperty(const std::string& prop) const;
+  cmProp GetProperty(const std::string& prop) const;
   //! Always returns a valid pointer
   const char* GetSafeProperty(const std::string& prop) const;
   bool GetPropertyAsBool(const std::string& prop) const;
   void CheckProperty(const std::string& prop, cmMakefile* context) const;
-  const char* GetComputedProperty(const std::string& prop,
-                                  cmMessenger* messenger,
-                                  cmListFileBacktrace const& context) const;
+  cmProp GetComputedProperty(const std::string& prop, cmMessenger* messenger,
+                             cmListFileBacktrace const& context) const;
   //! Get all properties
   cmPropertyMap const& GetProperties() const;
 
@@ -191,8 +192,8 @@
   bool IsImportedGloballyVisible() const;
   bool IsPerConfig() const;
 
-  bool GetMappedConfig(std::string const& desired_config, const char*& loc,
-                       const char*& imp, std::string& suffix) const;
+  bool GetMappedConfig(std::string const& desired_config, cmProp& loc,
+                       cmProp& imp, std::string& suffix) const;
 
   //! Return whether this target is an executable with symbol exports enabled.
   bool IsExecutableWithExports() const;
diff --git a/Source/cmTargetPropCommandBase.cxx b/Source/cmTargetPropCommandBase.cxx
index 0de8d6d..6325837 100644
--- a/Source/cmTargetPropCommandBase.cxx
+++ b/Source/cmTargetPropCommandBase.cxx
@@ -9,6 +9,8 @@
 #include "cmTarget.h"
 #include "cmake.h"
 
+using cmProp = const std::string*;
+
 cmTargetPropCommandBase::cmTargetPropCommandBase(cmExecutionStatus& status)
   : Makefile(&status.GetMakefile())
   , Status(status)
@@ -157,9 +159,9 @@
 {
   if (prepend) {
     const std::string propName = std::string("INTERFACE_") + this->Property;
-    const char* propValue = tgt->GetProperty(propName);
-    const std::string totalContent = this->Join(content) +
-      (propValue ? std::string(";") + propValue : std::string());
+    cmProp propValue = tgt->GetProperty(propName);
+    const std::string totalContent =
+      this->Join(content) + (propValue ? (";" + *propValue) : std::string());
     tgt->SetProperty(propName, totalContent);
   } else {
     tgt->AppendProperty("INTERFACE_" + this->Property, this->Join(content));
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index abc8b6f..96543e5 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -877,11 +877,10 @@
 
 void cmVisualStudio10TargetGenerator::WriteImports(Elem& e0)
 {
-  const char* imports =
+  cmProp imports =
     this->GeneratorTarget->Target->GetProperty("VS_PROJECT_IMPORT");
   if (imports) {
-    std::vector<std::string> argsSplit =
-      cmExpandedList(std::string(imports), false);
+    std::vector<std::string> argsSplit = cmExpandedList(*imports, false);
     for (auto& path : argsSplit) {
       if (!cmsys::SystemTools::FileIsFullPath(path)) {
         path = this->Makefile->GetCurrentSourceDirectory() + "/" + path;
@@ -1959,11 +1958,12 @@
   }
 
   if (ParsedToolTargetSettings.find(tool) == ParsedToolTargetSettings.end()) {
-    const char* toolTargetProperty =
-      this->GeneratorTarget->Target->GetProperty("VS_SOURCE_SETTINGS_" +
-                                                 std::string(tool));
+    cmProp toolTargetProperty = this->GeneratorTarget->Target->GetProperty(
+      "VS_SOURCE_SETTINGS_" + std::string(tool));
     ConfigToSettings toolTargetSettings;
-    ParseSettingsProperty(toolTargetProperty, toolTargetSettings);
+    if (toolTargetProperty) {
+      ParseSettingsProperty(toolTargetProperty->c_str(), toolTargetSettings);
+    }
 
     ParsedToolTargetSettings[tool] = toolTargetSettings;
   }
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index 670e8dc..aa38aec 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -328,7 +328,14 @@
   }
 
   // While we're at it, check proper TestFileAccess functionality.
-  if (kwsys::SystemTools::TestFileAccess(testNewFile,
+  bool do_write_test = true;
+#if defined(__linux__)
+  // If we are running as root on linux ignore this check, as
+  // root can always write to files
+  do_write_test = (getuid() != 0);
+#endif
+  if (do_write_test &&
+      kwsys::SystemTools::TestFileAccess(testNewFile,
                                          kwsys::TEST_FILE_WRITE)) {
     std::cerr
       << "TestFileAccess incorrectly indicated that this is a writable file:"