/* 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 "cmGeneratorExpression.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmInstallType.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmObjectLocation.h"
#include "cmOutputConverter.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: {
          std::string e = "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->Target->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
            MessageType::AUTHOR_WARNING, e, 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
{
  return cmGeneratorExpression::Evaluate(
    this->Destination, this->Target->GetLocalGenerator(), config);
}

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.
      std::string escapedNewRpath =
        cmOutputConverter::EscapeForCMake(cli->GetChrpathString());
      os << indent << "     RPATH " << escapedNewRpath << ")\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;
    }

    // Escape any CMake syntax in the RPATHs.
    std::string escapedOldRpath = cmOutputConverter::EscapeForCMake(oldRpath);
    std::string escapedNewRpath = cmOutputConverter::EscapeForCMake(newRpath);

    // 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 " << escapedOldRpath << "\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 " << escapedNewRpath;
        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) {
    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.";
    this->Target->GetGlobalGenerator()->GetCMakeInstance()->IssueMessage(
      MessageType::AUTHOR_WARNING, w.str(), this->GetBacktrace());
  }
}
