/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */
#include "cmInstallTargetGenerator.h"

#include <algorithm>
#include <cassert>
#include <cstddef>
#include <functional>
#include <map>
#include <set>
#include <sstream>
#include <utility>
#include <vector>

#include <cm/optional>

#include "cmComputeLinkInformation.h"
#include "cmDiagnosticContext.h"
#include "cmDiagnostics.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmInstallType.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmObjectLocation.h"
#include "cmPolicies.h"
#include "cmScriptGenerator.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmValue.h"
#include "cmake.h"

namespace {
std::string computeInstallObjectDir(cmGeneratorTarget* gt,
                                    std::string const& config)
{
  std::string objectDir = "objects";
  if (!config.empty()) {
    objectDir += "-";
    objectDir += config;
  }
  objectDir += "/";
  objectDir += gt->GetName();
  return objectDir;
}

void computeFilesToInstall(
  cmInstallTargetGenerator::Files& files,
  cmInstallTargetGenerator::NamelinkModeType namelinkMode,
  std::string const& fromDirConfig, std::string const& output,
  std::string const& library, std::string const& real,
  cm::optional<std::function<void(std::string const&)>> GNUToMS = cm::nullopt)
{
  bool haveNamelink = false;
  auto convert = [&GNUToMS](std::string const& file) {
    if (GNUToMS) {
      (*GNUToMS)(file);
    }
  };

  // Library link name.
  std::string fromName = cmStrCat(fromDirConfig, output);
  std::string toName = output;

  // Library interface name.
  std::string fromSOName;
  std::string toSOName;
  if (!library.empty() && library != output) {
    haveNamelink = true;
    fromSOName = cmStrCat(fromDirConfig, library);
    toSOName = library;
  }

  // Library implementation name.
  std::string fromRealName;
  std::string toRealName;
  if (real != output && real != library) {
    haveNamelink = true;
    fromRealName = cmStrCat(fromDirConfig, real);
    toRealName = real;
  }

  // Add the names based on the current namelink mode.
  if (haveNamelink) {
    files.NamelinkMode = namelinkMode;
    // With a namelink we need to check the mode.
    if (namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly) {
      // Install the namelink only.
      files.From.emplace_back(fromName);
      files.To.emplace_back(toName);
      convert(output);
    } else {
      // Install the real file if it has its own name.
      if (!fromRealName.empty()) {
        files.From.emplace_back(fromRealName);
        files.To.emplace_back(toRealName);
        convert(real);
      }

      // Install the soname link if it has its own name.
      if (!fromSOName.empty()) {
        files.From.emplace_back(fromSOName);
        files.To.emplace_back(toSOName);
        convert(library);
      }

      // Install the namelink if it is not to be skipped.
      if (namelinkMode != cmInstallTargetGenerator::NamelinkModeSkip) {
        files.From.emplace_back(fromName);
        files.To.emplace_back(toName);
        convert(output);
      }
    }
  } else {
    // Without a namelink there will be only one file.  Install it
    // if this is not a namelink-only rule.
    if (namelinkMode != cmInstallTargetGenerator::NamelinkModeOnly) {
      files.From.emplace_back(fromName);
      files.To.emplace_back(toName);
      convert(output);
    }
  }
}
}

cmInstallTargetGenerator::cmInstallTargetGenerator(
  std::string targetName, std::string const& dest, bool implib,
  std::string filePermissions, std::vector<std::string> const& configurations,
  std::string const& component, MessageLevel message, bool excludeFromAll,
  bool optional, cmDiagnosticContext context)
  : cmInstallGenerator(dest, configurations, component, message,
                       excludeFromAll, false, std::move(context))
  , TargetName(std::move(targetName))
  , FilePermissions(std::move(filePermissions))
  , ImportLibrary(implib)
  , Optional(optional)
{
  this->ActionsPerConfig = true;
  this->NamelinkMode = NamelinkModeNone;
  this->ImportlinkMode = NamelinkModeNone;
}

cmInstallTargetGenerator::~cmInstallTargetGenerator() = default;

void cmInstallTargetGenerator::GenerateScriptForConfig(
  std::ostream& os, std::string const& config, Indent indent)
{
  // Compute the list of files to install for this target.
  Files files = this->GetFiles(config);

  // Skip this rule if no files are to be installed for the target.
  if (files.From.empty()) {
    return;
  }

  // Compute the effective install destination.
  std::string dest = this->GetDestination(config);
  if (!files.ToDir.empty()) {
    dest = cmStrCat(dest, '/', files.ToDir);
  }

  // Tweak files located in the destination directory.
  std::string toDir = cmStrCat(ConvertToAbsoluteDestination(dest), '/');

  // Add pre-installation tweaks.
  if (!files.NoTweak) {
    AddTweak(os, indent, config, toDir, files.To,
             [this](std::ostream& o, Indent i, std::string const& c,
                    std::string const& f) {
               this->PreReplacementTweaks(o, i, c, f);
             });
  }

  // Write code to install the target file.
  char const* no_dir_permissions = nullptr;
  bool optional = this->Optional || this->ImportLibrary;
  std::string literalArgs;
  if (files.UseSourcePermissions) {
    literalArgs += " USE_SOURCE_PERMISSIONS";
  }
  if (files.Rename) {
    if (files.From.size() != files.To.size()) {
      this->Target->GetLocalGenerator()->IssueMessage(
        MessageType::INTERNAL_ERROR,
        "cmInstallTargetGenerator generated a rename request with mismatched "
        "names.");
      return;
    }
    std::vector<std::string> FileNames;
    FileNames.resize(1);
    for (size_t i = 0; i < files.From.size(); ++i) {
      if (files.FromDir.empty()) {
        FileNames[0] = files.From[i];
      } else {
        FileNames[0] = cmStrCat(files.FromDir, '/', files.From[i]);
      }
      this->AddInstallRule(os, dest, files.Type, FileNames, optional,
                           this->FilePermissions.c_str(), no_dir_permissions,
                           files.To[i].c_str(), literalArgs.c_str(), indent);
    }
  } else {
    char const* no_rename = nullptr;
    if (!files.FromDir.empty()) {
      literalArgs += " FILES_FROM_DIR \"" + files.FromDir + "\"";
    }
    this->AddInstallRule(os, dest, files.Type, files.From, optional,
                         this->FilePermissions.c_str(), no_dir_permissions,
                         no_rename, literalArgs.c_str(), indent);
  }

  // Add post-installation tweaks.
  if (!files.NoTweak) {
    AddTweak(os, indent, config, toDir, files.To,
             [this](std::ostream& o, Indent i, std::string const& c,
                    std::string const& f) {
               this->PostReplacementTweaks(o, i, c, f);
             });
  }
}

cmInstallTargetGenerator::Files cmInstallTargetGenerator::GetFiles(
  std::string const& config) const
{
  Files files;

  cmStateEnums::TargetType targetType = this->Target->GetType();
  switch (targetType) {
    case cmStateEnums::EXECUTABLE:
      files.Type = cmInstallType_EXECUTABLE;
      break;
    case cmStateEnums::STATIC_LIBRARY:
      files.Type = cmInstallType_STATIC_LIBRARY;
      break;
    case cmStateEnums::SHARED_LIBRARY:
      files.Type = cmInstallType_SHARED_LIBRARY;
      break;
    case cmStateEnums::MODULE_LIBRARY:
      files.Type = cmInstallType_MODULE_LIBRARY;
      break;
    case cmStateEnums::INTERFACE_LIBRARY:
      // Not reachable. We never create a cmInstallTargetGenerator for
      // an INTERFACE_LIBRARY.
      assert(false &&
             "INTERFACE_LIBRARY targets have no installable outputs.");
      break;

    case cmStateEnums::OBJECT_LIBRARY: {
      // Compute all the object files inside this target
      std::vector<std::pair<cmObjectLocation, cmObjectLocation>> objects;
      auto storeObjectLocations = [&objects](cmObjectLocation const& build,
                                             cmObjectLocation const& install) {
        objects.emplace_back(build, install);
      };
      this->Target->GetTargetObjectLocations(config, storeObjectLocations);

      files.Type = cmInstallType_FILES;
      files.NoTweak = true;
      files.Rename = true;
      files.FromDir = this->Target->GetObjectDirectory(config);
      if (!this->Target->GetPropertyAsBool(
            "INSTALL_OBJECT_ONLY_USE_DESTINATION")) {
        files.ToDir = computeInstallObjectDir(this->Target, config);
      }
      for (auto const& obj : objects) {
        files.From.emplace_back(obj.first.GetPath());
        files.To.emplace_back(obj.second.GetPath());
      }
      return files;
    }

    case cmStateEnums::UTILITY:
    case cmStateEnums::GLOBAL_TARGET:
    case cmStateEnums::UNKNOWN_LIBRARY:
      this->Target->GetLocalGenerator()->IssueMessage(
        MessageType::INTERNAL_ERROR,
        "cmInstallTargetGenerator created with non-installable target.");
      return files;
  }

  // Compute the build tree directory from which to copy the target.
  std::string fromDirConfig;
  if (this->Target->NeedRelinkBeforeInstall(config)) {
    fromDirConfig =
      cmStrCat(this->Target->GetLocalGenerator()->GetCurrentBinaryDirectory(),
               "/CMakeFiles/CMakeRelink.dir/");
  } else {
    cmStateEnums::ArtifactType artifact = this->ImportLibrary
      ? cmStateEnums::ImportLibraryArtifact
      : cmStateEnums::RuntimeBinaryArtifact;
    fromDirConfig =
      cmStrCat(this->Target->GetDirectory(config, artifact), '/');
  }

  if (targetType == cmStateEnums::EXECUTABLE) {
    // There is a bug in cmInstallCommand if this fails.
    assert(this->NamelinkMode == NamelinkModeNone);

    cmGeneratorTarget::Names targetNames =
      this->Target->GetExecutableNames(config);
    if (this->ImportLibrary) {
      std::string from1 = fromDirConfig + targetNames.ImportLibrary;
      std::string to1 = targetNames.ImportLibrary;
      files.From.emplace_back(std::move(from1));
      files.To.emplace_back(std::move(to1));
      std::string targetNameImportLib;
      if (this->Target->GetImplibGNUtoMS(config, targetNames.ImportLibrary,
                                         targetNameImportLib)) {
        files.From.emplace_back(fromDirConfig + targetNameImportLib);
        files.To.emplace_back(targetNameImportLib);
      }

      // An import library looks like a static library.
      files.Type = cmInstallType_STATIC_LIBRARY;
    } else {
      std::string from1 = fromDirConfig + targetNames.Output;
      std::string to1 = targetNames.Output;

      // Handle OSX Bundles.
      if (this->Target->IsAppBundleOnApple()) {
        cmMakefile const* mf = this->Target->Target->GetMakefile();

        // Get App Bundle Extension
        std::string ext;
        if (cmValue p = this->Target->GetProperty("BUNDLE_EXTENSION")) {
          ext = *p;
        } else {
          ext = "app";
        }

        // Install the whole app bundle directory.
        files.Type = cmInstallType_DIRECTORY;
        files.UseSourcePermissions = true;
        from1 += ".";
        from1 += ext;

        // Tweaks apply to the binary inside the bundle.
        to1 += ".";
        to1 += ext;
        to1 += "/";
        if (!mf->PlatformIsAppleEmbedded()) {
          to1 += "Contents/MacOS/";
        }
        to1 += targetNames.Output;
      } else {
        // Tweaks apply to the real file, so list it first.
        if (targetNames.Real != targetNames.Output) {
          std::string from2 = fromDirConfig + targetNames.Real;
          std::string to2 = targetNames.Real;
          files.From.emplace_back(std::move(from2));
          files.To.emplace_back(std::move(to2));
        }
      }

      files.From.emplace_back(std::move(from1));
      files.To.emplace_back(std::move(to1));
    }
  } else {
    cmGeneratorTarget::Names targetNames =
      this->Target->GetLibraryNames(config);
    if (this->ImportLibrary) {
      // There is a bug in cmInstallCommand if this fails.
      assert(this->Target->Makefile->PlatformSupportsAppleTextStubs() ||
             this->ImportlinkMode == NamelinkModeNone);

      auto GNUToMS = [this, &config, &files,
                      &fromDirConfig](std::string const& lib) {
        std::string importLib;
        if (this->Target->GetImplibGNUtoMS(config, lib, importLib)) {
          files.From.emplace_back(fromDirConfig + importLib);
          files.To.emplace_back(importLib);
        }
      };

      computeFilesToInstall(
        files, this->ImportlinkMode, fromDirConfig, targetNames.ImportOutput,
        targetNames.ImportLibrary, targetNames.ImportReal, GNUToMS);

      // An import library looks like a static library.
      files.Type = cmInstallType_STATIC_LIBRARY;
    } else if (this->Target->IsFrameworkOnApple()) {
      // FIXME: In principle we should be able to
      //   assert(this->NamelinkMode == NamelinkModeNone);
      // but since the current install() command implementation checks
      // the FRAMEWORK property immediately instead of delaying until
      // generate time, it is possible for project code to set the
      // property after calling install().  In such a case, the install()
      // command will use the LIBRARY code path and create two install
      // generators, one for the namelink component (NamelinkModeOnly)
      // and one for the primary artifact component (NamelinkModeSkip).
      // Historically this was not diagnosed and resulted in silent
      // installation of a framework to the LIBRARY destination.
      // Retain that behavior and warn about the case.
      switch (this->NamelinkMode) {
        case NamelinkModeNone:
          // Normal case.
          break;
        case NamelinkModeOnly:
          // Assume the NamelinkModeSkip instance will warn and install.
          return files;
        case NamelinkModeSkip: {
          cmake const* const cm =
            this->Target->GetGlobalGenerator()->GetCMakeInstance();
          cm->IssueDiagnostic(
            cmDiagnostics::CMD_AUTHOR,
            cmStrCat("Target '", this->Target->GetName(),
                     "' was changed to a FRAMEWORK sometime after install().  "
                     "This may result in the wrong install DESTINATION.  "
                     "Set the FRAMEWORK property earlier."),
            this->GetBacktrace());
        } break;
      }

      // Install the whole framework directory.
      files.Type = cmInstallType_DIRECTORY;
      files.UseSourcePermissions = true;

      std::string from1 = fromDirConfig + targetNames.Output;
      from1 = cmSystemTools::GetFilenamePath(from1);

      // Tweaks apply to the binary inside the bundle.
      std::string to1 = targetNames.Real;

      files.From.emplace_back(std::move(from1));
      files.To.emplace_back(std::move(to1));
    } else if (this->Target->IsCFBundleOnApple()) {
      // Install the whole app bundle directory.
      files.Type = cmInstallType_DIRECTORY;
      files.UseSourcePermissions = true;

      std::string targetNameBase =
        targetNames.Output.substr(0, targetNames.Output.find('/'));

      std::string from1 = fromDirConfig + targetNameBase;
      std::string to1 = targetNames.Output;

      files.From.emplace_back(std::move(from1));
      files.To.emplace_back(std::move(to1));
    } else if (this->Target->IsArchivedAIXSharedLibrary()) {
      // Install only the archive on AIX.
      computeFilesToInstall(files, this->NamelinkMode, fromDirConfig,
                            targetNames.Output, {}, targetNames.Real);
    } else {
      computeFilesToInstall(files, this->NamelinkMode, fromDirConfig,
                            targetNames.Output, targetNames.SharedObject,
                            targetNames.Real);
    }
  }

  // If this fails the above code is buggy.
  assert(files.From.size() == files.To.size());

  return files;
}

void cmInstallTargetGenerator::GetInstallObjectNames(
  std::string const& config, std::vector<std::string>& objects) const
{
  std::vector<cmObjectLocation> installedObjects;
  auto storeObjectLocations =
    [&installedObjects](cmObjectLocation const&,
                        cmObjectLocation const& install) {
      installedObjects.emplace_back(install);
    };
  this->Target->GetTargetObjectLocations(config, storeObjectLocations);
  objects.reserve(installedObjects.size());
  std::string rootDir;
  if (!this->Target->GetPropertyAsBool(
        "INSTALL_OBJECT_ONLY_USE_DESTINATION")) {
    rootDir = cmStrCat(computeInstallObjectDir(this->Target, config), '/');
  }
  for (cmObjectLocation const& o : installedObjects) {
    objects.emplace_back(cmStrCat(rootDir, o.GetPath()));
  }
}

std::string cmInstallTargetGenerator::GetDestination(
  std::string const& config) const
{
  cmLocalGenerator* lg = this->Target->GetLocalGenerator();
  std::string dest =
    cmGeneratorExpression::Evaluate(this->Destination, lg, config);
  this->CheckAbsoluteDestination(dest, lg);
  return dest;
}

std::string cmInstallTargetGenerator::GetInstallFilename(
  std::string const& config) const
{
  NameType nameType = this->ImportLibrary ? NameImplib : NameNormal;
  return cmInstallTargetGenerator::GetInstallFilename(this->Target, config,
                                                      nameType);
}

std::string cmInstallTargetGenerator::GetInstallFilename(
  cmGeneratorTarget const* target, std::string const& config,
  NameType nameType)
{
  std::string fname;
  // Compute the name of the library.
  if (target->GetType() == cmStateEnums::EXECUTABLE) {
    cmGeneratorTarget::Names targetNames = target->GetExecutableNames(config);
    if (nameType == NameImplib) {
      // Use the import library name.
      if (!target->GetImplibGNUtoMS(config, targetNames.ImportLibrary, fname,
                                    "${CMAKE_IMPORT_LIBRARY_SUFFIX}")) {
        fname = targetNames.ImportLibrary;
      }
    } else if (nameType == NameImplibReal) {
      // Use the import library name.
      if (!target->GetImplibGNUtoMS(config, targetNames.ImportReal, fname,
                                    "${CMAKE_IMPORT_LIBRARY_SUFFIX}")) {
        fname = targetNames.ImportReal;
      }
    } else if (nameType == NameReal) {
      // Use the canonical name.
      fname = targetNames.Real;
    } else {
      // Use the canonical name.
      fname = targetNames.Output;
    }
  } else {
    cmGeneratorTarget::Names targetNames = target->GetLibraryNames(config);
    if (nameType == NameImplib || nameType == NameImplibReal) {
      auto const& importName = nameType == NameImplib
        ? targetNames.ImportLibrary
        : targetNames.ImportReal;
      // Use the import library name.
      if (!target->GetImplibGNUtoMS(config, importName, fname,
                                    "${CMAKE_IMPORT_LIBRARY_SUFFIX}")) {
        fname = importName;
      }
    } else if (nameType == NameSO) {
      // Use the soname.
      fname = targetNames.SharedObject;
    } else if (nameType == NameReal) {
      // Use the real name.
      fname = targetNames.Real;
    } else {
      // Use the canonical name.
      fname = targetNames.Output;
    }
  }

  return fname;
}

bool cmInstallTargetGenerator::Compute(cmLocalGenerator* lg)
{
  // Lookup this target in the current directory.
  this->Target = lg->FindLocalNonAliasGeneratorTarget(this->TargetName);
  if (!this->Target) {
    // If no local target has been found, find it in the global scope.
    this->Target =
      lg->GetGlobalGenerator()->FindGeneratorTarget(this->TargetName);
  }

  return true;
}

void cmInstallTargetGenerator::PreReplacementTweaks(std::ostream& os,
                                                    Indent indent,
                                                    std::string const& config,
                                                    std::string const& file)
{
  this->AddRPathCheckRule(os, indent, config, file);
}

void cmInstallTargetGenerator::PostReplacementTweaks(std::ostream& os,
                                                     Indent indent,
                                                     std::string const& config,
                                                     std::string const& file)
{
  this->AddInstallNamePatchRule(os, indent, config, file);
  this->AddChrpathPatchRule(os, indent, config, file);
  this->AddUniversalInstallRule(os, indent, file);
  this->AddRanlibRule(os, indent, file);
  this->AddStripRule(os, indent, file);
}

void cmInstallTargetGenerator::AddInstallNamePatchRule(
  std::ostream& os, Indent indent, std::string const& config,
  std::string const& toDestDirPath)
{
  if (this->ImportLibrary || this->NamelinkMode == NamelinkModeOnly ||
      !(this->Target->GetType() == cmStateEnums::SHARED_LIBRARY ||
        this->Target->GetType() == cmStateEnums::MODULE_LIBRARY ||
        this->Target->GetType() == cmStateEnums::EXECUTABLE)) {
    return;
  }

  // Fix the install_name settings in installed binaries.
  std::string installNameTool =
    this->Target->Target->GetMakefile()->GetSafeDefinition(
      "CMAKE_INSTALL_NAME_TOOL");

  if (installNameTool.empty()) {
    return;
  }

  // Build a map of build-tree install_name to install-tree install_name for
  // shared libraries linked to this target.
  std::map<std::string, std::string> install_name_remap;
  if (cmComputeLinkInformation* cli =
        this->Target->GetLinkInformation(config)) {
    std::set<cmGeneratorTarget const*> const& sharedLibs =
      cli->GetSharedLibrariesLinked();
    for (cmGeneratorTarget const* tgt : sharedLibs) {
      // The install_name of an imported target does not change.
      if (tgt->IsImported()) {
        continue;
      }

      // If the build tree and install tree use different path
      // components of the install_name field then we need to create a
      // mapping to be applied after installation.
      std::string for_build = tgt->GetInstallNameDirForBuildTree(config);
      std::string for_install = tgt->GetInstallNameDirForInstallTree(
        config, "${CMAKE_INSTALL_PREFIX}");
      if (for_build != for_install) {
        // The directory portions differ.  Append the filename to
        // create the mapping.
        std::string fname = this->GetInstallFilename(tgt, config, NameSO);

        // Map from the build-tree install_name.
        for_build += fname;

        // Map to the install-tree install_name.
        for_install += fname;

        // Store the mapping entry.
        install_name_remap[for_build] = for_install;
      }
    }
  }

  // Edit the install_name of the target itself if necessary.
  std::string new_id;
  if (this->Target->GetType() == cmStateEnums::SHARED_LIBRARY) {
    std::string for_build =
      this->Target->GetInstallNameDirForBuildTree(config);
    std::string for_install = this->Target->GetInstallNameDirForInstallTree(
      config, "${CMAKE_INSTALL_PREFIX}");

    if (this->Target->IsFrameworkOnApple() && for_install.empty()) {
      // Frameworks seem to have an id corresponding to their own full
      // path.
      // ...
      // for_install = fullDestPath_without_DESTDIR_or_name;
    }

    // If the install name will change on installation set the new id
    // on the installed file.
    if (for_build != for_install) {
      // Prepare to refer to the install-tree install_name.
      new_id = cmStrCat(
        for_install, this->GetInstallFilename(this->Target, config, NameSO));
    }
  }

  // Write a rule to run install_name_tool to set the install-tree
  // install_name value and references.
  if (!new_id.empty() || !install_name_remap.empty()) {
    os << indent << "execute_process(COMMAND \"" << installNameTool;
    os << "\"";
    if (!new_id.empty()) {
      os << "\n" << indent << "  -id \"" << new_id << "\"";
    }
    for (auto const& i : install_name_remap) {
      os << "\n"
         << indent << "  -change \"" << i.first << "\" \"" << i.second << "\"";
    }
    os << "\n" << indent << "  \"" << toDestDirPath << "\")\n";
  }
}

void cmInstallTargetGenerator::AddRPathCheckRule(
  std::ostream& os, Indent indent, std::string const& config,
  std::string const& toDestDirPath)
{
  // Skip the chrpath if the target does not need it.
  if (this->ImportLibrary || this->NamelinkMode == NamelinkModeOnly ||
      !this->Target->IsChrpathUsed(config)) {
    return;
  }
  // Skip if on Apple
  if (this->Target->Target->GetMakefile()->IsOn(
        "CMAKE_PLATFORM_HAS_INSTALLNAME")) {
    return;
  }

  // Get the link information for this target.
  // It can provide the RPATH.
  cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config);
  if (!cli) {
    return;
  }

  // Write a rule to remove the installed file if its rpath is not the
  // new rpath.  This is needed for existing build/install trees when
  // the installed rpath changes but the file is not rebuilt.
  os << indent << "file(RPATH_CHECK\n"
     << indent << "     FILE \"" << toDestDirPath << "\"\n";

  // CMP0095: ``RPATH`` entries are properly escaped in the intermediary
  // CMake install script.
  switch (this->Target->GetPolicyStatusCMP0095()) {
    case cmPolicies::WARN:
      // No author warning needed here, we warn later in
      // cmInstallTargetGenerator::AddChrpathPatchRule().
      CM_FALLTHROUGH;
    case cmPolicies::OLD: {
      // Get the install RPATH from the link information.
      std::string newRpath = cli->GetChrpathString();
      os << indent << "     RPATH \"" << newRpath << "\")\n";
      break;
    }
    default: {
      // Get the install RPATH from the link information and
      // escape any CMake syntax in the install RPATH.
      os << indent << "     RPATH "
         << cmScriptGenerator::Quote(cli->GetChrpathString()) << ")\n";
      break;
    }
  }
}

void cmInstallTargetGenerator::AddChrpathPatchRule(
  std::ostream& os, Indent indent, std::string const& config,
  std::string const& toDestDirPath)
{
  // Skip the chrpath if the target does not need it.
  if (this->ImportLibrary || this->NamelinkMode == NamelinkModeOnly ||
      !this->Target->IsChrpathUsed(config)) {
    return;
  }

  // Get the link information for this target.
  // It can provide the RPATH.
  cmComputeLinkInformation* cli = this->Target->GetLinkInformation(config);
  if (!cli) {
    return;
  }

  cmMakefile* mf = this->Target->Target->GetMakefile();

  if (mf->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME")) {
    // If using install_name_tool, set up the rules to modify the rpaths.
    std::string installNameTool =
      mf->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL");

    std::vector<std::string> oldRuntimeDirs;
    std::vector<std::string> newRuntimeDirs;
    cli->GetRPath(oldRuntimeDirs, false);
    cli->GetRPath(newRuntimeDirs, true);

    std::string darwin_major_version_s =
      mf->GetSafeDefinition("DARWIN_MAJOR_VERSION");

    std::istringstream ss(darwin_major_version_s);
    int darwin_major_version;
    ss >> darwin_major_version;
    if (!ss.fail() && darwin_major_version <= 9 &&
        (!oldRuntimeDirs.empty() || !newRuntimeDirs.empty())) {
      std::ostringstream msg;
      msg
        << "WARNING: Target \"" << this->Target->GetName()
        << "\" has runtime paths which cannot be changed during install.  "
        << "To change runtime paths, OS X version 10.6 or newer is required.  "
        << "Therefore, runtime paths will not be changed when installing.  "
        << "CMAKE_BUILD_WITH_INSTALL_RPATH may be used to work around"
           " this limitation.";
      mf->IssueMessage(MessageType::WARNING, msg.str());
    } else {
      // To be consistent with older versions, runpath changes must be ordered,
      // deleted first, then added, *and* the same path must only appear once.
      std::map<std::string, std::string> runpath_change;
      std::vector<std::string> ordered;
      for (std::string const& dir : oldRuntimeDirs) {
        // Normalize path and add to map of changes to make
        auto iter_inserted = runpath_change.insert(
          { mf->GetGlobalGenerator()->ExpandCFGIntDir(dir, config),
            "delete" });
        if (iter_inserted.second) {
          // Add path to ordered list of changes
          ordered.push_back(iter_inserted.first->first);
        }
      }

      for (std::string const& dir : newRuntimeDirs) {
        // Normalize path and add to map of changes to make
        auto iter_inserted = runpath_change.insert(
          { mf->GetGlobalGenerator()->ExpandCFGIntDir(dir, config), "add" });
        if (iter_inserted.second) {
          // Add path to ordered list of changes
          ordered.push_back(iter_inserted.first->first);
        } else if (iter_inserted.first->second != "add") {
          // Rpath was requested to be deleted and then later re-added. Drop it
          // from the list by marking as an empty value.
          iter_inserted.first->second.clear();
        }
      }

      // Remove rpaths that are unchanged (value was set to empty)
      ordered.erase(
        std::remove_if(ordered.begin(), ordered.end(),
                       [&runpath_change](std::string const& runpath) {
                         return runpath_change.find(runpath)->second.empty();
                       }),
        ordered.end());

      if (!ordered.empty()) {
        os << indent << "execute_process(COMMAND " << installNameTool << "\n";
        for (std::string const& runpath : ordered) {
          // Either 'add_rpath' or 'delete_rpath' since we've removed empty
          // entries
          os << indent << "  -" << runpath_change.find(runpath)->second
             << "_rpath \"" << runpath << "\"\n";
        }
        os << indent << "  \"" << toDestDirPath << "\")\n";
      }
    }
  } else {
    // Construct the original rpath string to be replaced.
    std::string oldRpath = cli->GetRPathString(false);

    // Get the install RPATH from the link information.
    std::string newRpath = cli->GetChrpathString();

    // Skip the rule if the paths are identical
    if (oldRpath == newRpath) {
      return;
    }

    // Write a rule to run chrpath to set the install-tree RPATH
    os << indent << "file(RPATH_CHANGE\n"
       << indent << "     FILE \"" << toDestDirPath << "\"\n"
       << indent << "     OLD_RPATH " << cmScriptGenerator::Quote(oldRpath)
       << "\n";

    // CMP0095: ``RPATH`` entries are properly escaped in the intermediary
    // CMake install script.
    switch (this->Target->GetPolicyStatusCMP0095()) {
      case cmPolicies::WARN:
        this->IssueCMP0095Warning(newRpath);
        CM_FALLTHROUGH;
      case cmPolicies::OLD:
        os << indent << "     NEW_RPATH \"" << newRpath << "\"";
        break;
      default:
        os << indent << "     NEW_RPATH "
           << cmScriptGenerator::Quote(newRpath);
        break;
    }

    if (this->Target->GetPropertyAsBool("INSTALL_REMOVE_ENVIRONMENT_RPATH")) {
      os << "\n" << indent << "     INSTALL_REMOVE_ENVIRONMENT_RPATH)\n";
    } else {
      os << ")\n";
    }
  }
}

void cmInstallTargetGenerator::AddStripRule(std::ostream& os, Indent indent,
                                            std::string const& toDestDirPath)
{

  // don't strip static and import libraries, because it removes the only
  // symbol table they have so you can't link to them anymore
  if (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY ||
      this->ImportLibrary || this->NamelinkMode == NamelinkModeOnly) {
    return;
  }

  // Don't handle OSX Bundles.
  if (this->Target->IsApple() &&
      this->Target->GetPropertyAsBool("MACOSX_BUNDLE")) {
    return;
  }

  std::string const& strip =
    this->Target->Target->GetMakefile()->GetSafeDefinition("CMAKE_STRIP");
  if (strip.empty()) {
    return;
  }

  std::string stripArgs;
  if (this->Target->IsApple()) {
    if (this->Target->GetType() == cmStateEnums::SHARED_LIBRARY ||
        this->Target->GetType() == cmStateEnums::MODULE_LIBRARY) {
      // Strip tools need '-x' to strip Apple dylibs correctly.
      stripArgs = "-x ";
    } else if (this->Target->GetType() == cmStateEnums::EXECUTABLE &&
               this->Target->GetGlobalGenerator()->GetStripCommandStyle(
                 strip) == cmGlobalGenerator::StripCommandStyle::Apple) {
      // Apple's strip tool needs '-u -r' to strip executables correctly.
      stripArgs = "-u -r ";
    }
  }

  os << indent << "if(CMAKE_INSTALL_DO_STRIP)\n";
  os << indent << "  execute_process(COMMAND \"" << strip << "\" " << stripArgs
     << "\"" << toDestDirPath << "\")\n";
  os << indent << "endif()\n";
}

void cmInstallTargetGenerator::AddRanlibRule(std::ostream& os, Indent indent,
                                             std::string const& toDestDirPath)
{
  // Static libraries need ranlib on this platform.
  if (this->Target->GetType() != cmStateEnums::STATIC_LIBRARY) {
    return;
  }

  // Perform post-installation processing on the file depending
  // on its type.
  if (!this->Target->IsApple()) {
    return;
  }

  std::string const& ranlib =
    this->Target->Target->GetMakefile()->GetRequiredDefinition("CMAKE_RANLIB");
  if (ranlib.empty()) {
    return;
  }

  os << indent << "execute_process(COMMAND \"" << ranlib << "\" \""
     << toDestDirPath << "\")\n";
}

void cmInstallTargetGenerator::AddUniversalInstallRule(
  std::ostream& os, Indent indent, std::string const& toDestDirPath)
{
  cmMakefile const* mf = this->Target->Target->GetMakefile();

  if (!mf->PlatformIsAppleEmbedded() || !mf->IsOn("XCODE")) {
    return;
  }

  cmValue xcodeVersion = mf->GetDefinition("XCODE_VERSION");
  if (!xcodeVersion ||
      cmSystemTools::VersionCompareGreater("6", *xcodeVersion)) {
    return;
  }

  switch (this->Target->GetType()) {
    case cmStateEnums::EXECUTABLE:
    case cmStateEnums::STATIC_LIBRARY:
    case cmStateEnums::SHARED_LIBRARY:
    case cmStateEnums::MODULE_LIBRARY:
      break;

    default:
      return;
  }

  if (!this->Target->Target->GetPropertyAsBool("IOS_INSTALL_COMBINED")) {
    return;
  }

  os << indent << "include(CMakeIOSInstallCombined)\n";
  os << indent << "ios_install_combined("
     << "\"" << this->Target->Target->GetName() << "\" "
     << "\"" << toDestDirPath << "\")\n";
}

void cmInstallTargetGenerator::IssueCMP0095Warning(
  std::string const& unescapedRpath)
{
  // Reduce warning noise to cases where used RPATHs may actually be affected
  // by CMP0095. This filter is meant to skip warnings in cases when
  // non-curly-braces syntax (e.g. $ORIGIN) or no keyword is used which has
  // worked already before CMP0095. We intend to issue a warning in all cases
  // with curly-braces syntax, even if the workaround of double-escaping is in
  // place, since we deprecate the need for it with CMP0095.
  bool const potentially_affected(unescapedRpath.find("${") !=
                                  std::string::npos);

  if (potentially_affected) {
    cmake const* const cm =
      this->Target->GetGlobalGenerator()->GetCMakeInstance();
    std::ostringstream w;
    w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0095) << "\n";
    w << "RPATH entries for target '" << this->Target->GetName() << "' "
      << "will not be escaped in the intermediary "
      << "cmake_install.cmake script.";
    cm->IssueDiagnostic(cmDiagnostics::CMD_POLICY, w.str(),
                        this->GetBacktrace());
  }
}
