/* 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 "cmDiagnostics.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmInstallType.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 file_permissions, std::vector<std::string> const& configurations,
  std::string const& component, MessageLevel message, bool exclude_from_all,
  bool optional, cmListFileBacktrace backtrace)
  : cmInstallGenerator(dest, configurations, component, message,
                       exclude_from_all, false, std::move(backtrace))
  , TargetName(std::move(targetName))
  , FilePermissions(std::move(file_permissions))
  , 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 literal_args;
  if (files.UseSourcePermissions) {
    literal_args += " 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(), literal_args.c_str(), indent);
    }
  } else {
    char const* no_rename = nullptr;
    if (!files.FromDir.empty()) {
      literal_args += " FILES_FROM_DIR \"" + files.FromDir + "\"";
    }
    this->AddInstallRule(os, dest, files.Type, files.From, optional,
                         this->FilePermissions.c_str(), no_dir_permissions,
                         no_rename, literal_args.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);
  cmInstallGenerator::CheckAbsoluteDestination(dest, lg, this->Backtrace);
  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_AUTHOR, w.str(),
                        this->GetBacktrace());
  }
}
