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

#include <algorithm>
#include <assert.h>
#include <iterator>
#include <map>
#include <memory> // IWYU pragma: keep
#include <set>
#include <sstream>

#include "cmAlgorithms.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalNinjaGenerator.h"
#include "cmLinkLineComputer.h"
#include "cmLinkLineDeviceComputer.h"
#include "cmLocalGenerator.h"
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
#include "cmNinjaTypes.h"
#include "cmOSXBundleGenerator.h"
#include "cmOutputConverter.h"
#include "cmRulePlaceholderExpander.h"
#include "cmSourceFile.h"
#include "cmState.h"
#include "cmStateDirectory.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmake.h"

class cmCustomCommand;

cmNinjaNormalTargetGenerator::cmNinjaNormalTargetGenerator(
  cmGeneratorTarget* target)
  : cmNinjaTargetGenerator(target)
  , TargetNameOut()
  , TargetNameSO()
  , TargetNameReal()
  , TargetNameImport()
  , TargetNamePDB()
  , TargetLinkLanguage("")
  , DeviceLinkObject()
{
  this->TargetLinkLanguage = target->GetLinkerLanguage(this->GetConfigName());
  if (target->GetType() == cmStateEnums::EXECUTABLE) {
    this->GetGeneratorTarget()->GetExecutableNames(
      this->TargetNameOut, this->TargetNameReal, this->TargetNameImport,
      this->TargetNamePDB, GetLocalGenerator()->GetConfigName());
  } else {
    this->GetGeneratorTarget()->GetLibraryNames(
      this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
      this->TargetNameImport, this->TargetNamePDB,
      GetLocalGenerator()->GetConfigName());
  }

  if (target->GetType() != cmStateEnums::OBJECT_LIBRARY) {
    // on Windows the output dir is already needed at compile time
    // ensure the directory exists (OutDir test)
    EnsureDirectoryExists(target->GetDirectory(this->GetConfigName()));
  }

  this->OSXBundleGenerator =
    new cmOSXBundleGenerator(target, this->GetConfigName());
  this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}

cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator()
{
  delete this->OSXBundleGenerator;
}

void cmNinjaNormalTargetGenerator::Generate()
{
  if (this->TargetLinkLanguage.empty()) {
    cmSystemTools::Error("CMake can not determine linker language for "
                         "target: ",
                         this->GetGeneratorTarget()->GetName().c_str());
    return;
  }

  // Write the rules for each language.
  this->WriteLanguagesRules();

  // Write the build statements
  this->WriteObjectBuildStatements();

  if (this->GetGeneratorTarget()->GetType() == cmStateEnums::OBJECT_LIBRARY) {
    this->WriteObjectLibStatement();
  } else {
    // If this target has cuda language link inputs, and we need to do
    // device linking
    this->WriteDeviceLinkStatement();
    this->WriteLinkStatement();
  }
}

void cmNinjaNormalTargetGenerator::WriteLanguagesRules()
{
#ifdef NINJA_GEN_VERBOSE_FILES
  cmGlobalNinjaGenerator::WriteDivider(this->GetRulesFileStream());
  this->GetRulesFileStream()
    << "# Rules for each languages for "
    << cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType())
    << " target " << this->GetTargetName() << "\n\n";
#endif

  // Write rules for languages compiled in this target.
  std::set<std::string> languages;
  std::vector<cmSourceFile const*> sourceFiles;
  this->GetGeneratorTarget()->GetObjectSources(
    sourceFiles, this->GetMakefile()->GetSafeDefinition("CMAKE_BUILD_TYPE"));
  for (cmSourceFile const* sf : sourceFiles) {
    std::string const lang = sf->GetLanguage();
    if (!lang.empty()) {
      languages.insert(lang);
    }
  }
  for (std::string const& language : languages) {
    this->WriteLanguageRules(language);
  }
}

const char* cmNinjaNormalTargetGenerator::GetVisibleTypeName() const
{
  switch (this->GetGeneratorTarget()->GetType()) {
    case cmStateEnums::STATIC_LIBRARY:
      return "static library";
    case cmStateEnums::SHARED_LIBRARY:
      return "shared library";
    case cmStateEnums::MODULE_LIBRARY:
      if (this->GetGeneratorTarget()->IsCFBundleOnApple()) {
        return "CFBundle shared module";
      } else {
        return "shared module";
      }
    case cmStateEnums::EXECUTABLE:
      return "executable";
    default:
      return nullptr;
  }
}

std::string cmNinjaNormalTargetGenerator::LanguageLinkerRule() const
{
  return this->TargetLinkLanguage + "_" +
    cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) +
    "_LINKER__" +
    cmGlobalNinjaGenerator::EncodeRuleName(
           this->GetGeneratorTarget()->GetName());
}

std::string cmNinjaNormalTargetGenerator::LanguageLinkerDeviceRule() const
{
  return this->TargetLinkLanguage + "_" +
    cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType()) +
    "_DEVICE_LINKER__" +
    cmGlobalNinjaGenerator::EncodeRuleName(
           this->GetGeneratorTarget()->GetName());
}

struct cmNinjaRemoveNoOpCommands
{
  bool operator()(std::string const& cmd)
  {
    return cmd.empty() || cmd[0] == ':';
  }
};

void cmNinjaNormalTargetGenerator::WriteDeviceLinkRule(bool useResponseFile)
{
  cmStateEnums::TargetType targetType = this->GetGeneratorTarget()->GetType();
  std::string ruleName = this->LanguageLinkerDeviceRule();
  // Select whether to use a response file for objects.
  std::string rspfile;
  std::string rspcontent;

  if (!this->GetGlobalGenerator()->HasRule(ruleName)) {
    cmRulePlaceholderExpander::RuleVariables vars;
    vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
    vars.CMTargetType =
      cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType());

    vars.Language = "CUDA";

    std::string responseFlag;
    if (!useResponseFile) {
      vars.Objects = "$in";
      vars.LinkLibraries = "$LINK_PATH $LINK_LIBRARIES";
    } else {
      std::string cmakeVarLang = "CMAKE_";
      cmakeVarLang += this->TargetLinkLanguage;

      // build response file name
      std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG";
      const char* flag = GetMakefile()->GetDefinition(cmakeLinkVar);
      if (flag) {
        responseFlag = flag;
      } else {
        responseFlag = "@";
      }
      rspfile = "$RSP_FILE";
      responseFlag += rspfile;

      // build response file content
      if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
        rspcontent = "$in";
      } else {
        rspcontent = "$in_newline";
      }
      rspcontent += " $LINK_LIBRARIES";
      vars.Objects = responseFlag.c_str();
      vars.LinkLibraries = "";
    }

    vars.ObjectDir = "$OBJECT_DIR";

    vars.Target = "$TARGET_FILE";

    vars.SONameFlag = "$SONAME_FLAG";
    vars.TargetSOName = "$SONAME";
    vars.TargetPDB = "$TARGET_PDB";
    vars.TargetCompilePDB = "$TARGET_COMPILE_PDB";

    vars.Flags = "$FLAGS";
    vars.LinkFlags = "$LINK_FLAGS";
    vars.Manifests = "$MANIFESTS";

    std::string langFlags;
    if (targetType != cmStateEnums::EXECUTABLE) {
      langFlags += "$LANGUAGE_COMPILE_FLAGS $ARCH_FLAGS";
      vars.LanguageCompileFlags = langFlags.c_str();
    }

    std::string launcher;
    const char* val = this->GetLocalGenerator()->GetRuleLauncher(
      this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
    if (val && *val) {
      launcher = val;
      launcher += " ";
    }

    std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
      this->GetLocalGenerator()->CreateRulePlaceholderExpander());

    // Rule for linking library/executable.
    std::vector<std::string> linkCmds = this->ComputeDeviceLinkCmd();
    for (std::string& linkCmd : linkCmds) {
      linkCmd = launcher + linkCmd;
      rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
                                                   linkCmd, vars);
    }

    // If there is no ranlib the command will be ":".  Skip it.
    cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands());

    std::string linkCmd =
      this->GetLocalGenerator()->BuildCommandLine(linkCmds);

    // Write the linker rule with response file if needed.
    std::ostringstream comment;
    comment << "Rule for linking " << this->TargetLinkLanguage << " "
            << this->GetVisibleTypeName() << ".";
    std::ostringstream description;
    description << "Linking " << this->TargetLinkLanguage << " "
                << this->GetVisibleTypeName() << " $TARGET_FILE";
    this->GetGlobalGenerator()->AddRule(ruleName, linkCmd, description.str(),
                                        comment.str(),
                                        /*depfile*/ "",
                                        /*deptype*/ "", rspfile, rspcontent,
                                        /*restat*/ "$RESTAT",
                                        /*generator*/ false);
  }
}

void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile)
{
  cmStateEnums::TargetType targetType = this->GetGeneratorTarget()->GetType();
  std::string ruleName = this->LanguageLinkerRule();

  // Select whether to use a response file for objects.
  std::string rspfile;
  std::string rspcontent;

  if (!this->GetGlobalGenerator()->HasRule(ruleName)) {
    cmRulePlaceholderExpander::RuleVariables vars;
    vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
    vars.CMTargetType =
      cmState::GetTargetTypeName(this->GetGeneratorTarget()->GetType());

    vars.Language = this->TargetLinkLanguage.c_str();

    std::string responseFlag;
    if (!useResponseFile) {
      vars.Objects = "$in";
      vars.LinkLibraries = "$LINK_PATH $LINK_LIBRARIES";
    } else {
      std::string cmakeVarLang = "CMAKE_";
      cmakeVarLang += this->TargetLinkLanguage;

      // build response file name
      std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG";
      const char* flag = GetMakefile()->GetDefinition(cmakeLinkVar);
      if (flag) {
        responseFlag = flag;
      } else {
        responseFlag = "@";
      }
      rspfile = "$RSP_FILE";
      responseFlag += rspfile;

      // build response file content
      if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
        rspcontent = "$in";
      } else {
        rspcontent = "$in_newline";
      }
      rspcontent += " $LINK_PATH $LINK_LIBRARIES";
      vars.Objects = responseFlag.c_str();
      vars.LinkLibraries = "";
    }

    vars.ObjectDir = "$OBJECT_DIR";

    vars.Target = "$TARGET_FILE";

    vars.SONameFlag = "$SONAME_FLAG";
    vars.TargetSOName = "$SONAME";
    vars.TargetInstallNameDir = "$INSTALLNAME_DIR";
    vars.TargetPDB = "$TARGET_PDB";

    // Setup the target version.
    std::string targetVersionMajor;
    std::string targetVersionMinor;
    {
      std::ostringstream majorStream;
      std::ostringstream minorStream;
      int major;
      int minor;
      this->GetGeneratorTarget()->GetTargetVersion(major, minor);
      majorStream << major;
      minorStream << minor;
      targetVersionMajor = majorStream.str();
      targetVersionMinor = minorStream.str();
    }
    vars.TargetVersionMajor = targetVersionMajor.c_str();
    vars.TargetVersionMinor = targetVersionMinor.c_str();

    vars.Flags = "$FLAGS";
    vars.LinkFlags = "$LINK_FLAGS";
    vars.Manifests = "$MANIFESTS";

    std::string langFlags;
    if (targetType != cmStateEnums::EXECUTABLE) {
      langFlags += "$LANGUAGE_COMPILE_FLAGS $ARCH_FLAGS";
      vars.LanguageCompileFlags = langFlags.c_str();
    }

    std::string launcher;
    const char* val = this->GetLocalGenerator()->GetRuleLauncher(
      this->GetGeneratorTarget(), "RULE_LAUNCH_LINK");
    if (val && *val) {
      launcher = val;
      launcher += " ";
    }

    std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
      this->GetLocalGenerator()->CreateRulePlaceholderExpander());

    // Rule for linking library/executable.
    std::vector<std::string> linkCmds = this->ComputeLinkCmd();
    for (std::string& linkCmd : linkCmds) {
      linkCmd = launcher + linkCmd;
      rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(),
                                                   linkCmd, vars);
    }

    // If there is no ranlib the command will be ":".  Skip it.
    cmEraseIf(linkCmds, cmNinjaRemoveNoOpCommands());

    linkCmds.insert(linkCmds.begin(), "$PRE_LINK");
    linkCmds.push_back("$POST_BUILD");
    std::string linkCmd =
      this->GetLocalGenerator()->BuildCommandLine(linkCmds);

    // Write the linker rule with response file if needed.
    std::ostringstream comment;
    comment << "Rule for linking " << this->TargetLinkLanguage << " "
            << this->GetVisibleTypeName() << ".";
    std::ostringstream description;
    description << "Linking " << this->TargetLinkLanguage << " "
                << this->GetVisibleTypeName() << " $TARGET_FILE";
    this->GetGlobalGenerator()->AddRule(ruleName, linkCmd, description.str(),
                                        comment.str(),
                                        /*depfile*/ "",
                                        /*deptype*/ "", rspfile, rspcontent,
                                        /*restat*/ "$RESTAT",
                                        /*generator*/ false);
  }

  if (this->TargetNameOut != this->TargetNameReal &&
      !this->GetGeneratorTarget()->IsFrameworkOnApple()) {
    std::string cmakeCommand =
      this->GetLocalGenerator()->ConvertToOutputFormat(
        cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
    if (targetType == cmStateEnums::EXECUTABLE) {
      std::vector<std::string> commandLines;
      commandLines.push_back(cmakeCommand +
                             " -E cmake_symlink_executable $in $out");
      commandLines.push_back("$POST_BUILD");

      this->GetGlobalGenerator()->AddRule(
        "CMAKE_SYMLINK_EXECUTABLE",
        this->GetLocalGenerator()->BuildCommandLine(commandLines),
        "Creating executable symlink $out",
        "Rule for creating "
        "executable symlink.",
        /*depfile*/ "",
        /*deptype*/ "",
        /*rspfile*/ "",
        /*rspcontent*/ "",
        /*restat*/ "",
        /*generator*/ false);
    } else {
      std::vector<std::string> commandLines;
      commandLines.push_back(cmakeCommand +
                             " -E cmake_symlink_library $in $SONAME $out");
      commandLines.push_back("$POST_BUILD");

      this->GetGlobalGenerator()->AddRule(
        "CMAKE_SYMLINK_LIBRARY",
        this->GetLocalGenerator()->BuildCommandLine(commandLines),
        "Creating library symlink $out",
        "Rule for creating "
        "library symlink.",
        /*depfile*/ "",
        /*deptype*/ "",
        /*rspfile*/ "",
        /*rspcontent*/ "",
        /*restat*/ "",
        /*generator*/ false);
    }
  }
}

std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeDeviceLinkCmd()
{
  std::vector<std::string> linkCmds;

  // this target requires separable cuda compilation
  // now build the correct command depending on if the target is
  // an executable or a dynamic library.
  std::string linkCmd;
  switch (this->GetGeneratorTarget()->GetType()) {
    case cmStateEnums::STATIC_LIBRARY:
    case cmStateEnums::SHARED_LIBRARY:
    case cmStateEnums::MODULE_LIBRARY: {
      const std::string cudaLinkCmd(
        this->GetMakefile()->GetDefinition("CMAKE_CUDA_DEVICE_LINK_LIBRARY"));
      cmSystemTools::ExpandListArgument(cudaLinkCmd, linkCmds);
    } break;
    case cmStateEnums::EXECUTABLE: {
      const std::string cudaLinkCmd(this->GetMakefile()->GetDefinition(
        "CMAKE_CUDA_DEVICE_LINK_EXECUTABLE"));
      cmSystemTools::ExpandListArgument(cudaLinkCmd, linkCmds);
    } break;
    default:
      break;
  }
  return linkCmds;
}

std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
{
  std::vector<std::string> linkCmds;
  cmMakefile* mf = this->GetMakefile();
  {
    // If we have a rule variable prefer it. In the case of static libraries
    // this occurs when things like IPO is enabled, and we need to use the
    // CMAKE_<lang>_CREATE_STATIC_LIBRARY_IPO define instead.
    std::string linkCmdVar = this->GetGeneratorTarget()->GetCreateRuleVariable(
      this->TargetLinkLanguage, this->GetConfigName());
    const char* linkCmd = mf->GetDefinition(linkCmdVar);
    if (linkCmd) {
      std::string linkCmdStr = linkCmd;
      if (this->GetGeneratorTarget()->HasImplibGNUtoMS(this->ConfigName)) {
        std::string ruleVar = "CMAKE_";
        ruleVar += this->GeneratorTarget->GetLinkerLanguage(this->ConfigName);
        ruleVar += "_GNUtoMS_RULE";
        if (const char* rule = this->Makefile->GetDefinition(ruleVar)) {
          linkCmdStr += rule;
        }
      }
      cmSystemTools::ExpandListArgument(linkCmdStr, linkCmds);
      if (this->GetGeneratorTarget()->GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
        std::string cmakeCommand =
          this->GetLocalGenerator()->ConvertToOutputFormat(
            cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL);
        cmakeCommand += " -E __run_co_compile --lwyu=";
        cmGeneratorTarget& gt = *this->GetGeneratorTarget();
        const std::string cfgName = this->GetConfigName();
        std::string targetOutputReal = this->ConvertToNinjaPath(
          gt.GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact,
                         /*realname=*/true));
        cmakeCommand += targetOutputReal;
        cmakeCommand += " || true";
        linkCmds.push_back(std::move(cmakeCommand));
      }
      return linkCmds;
    }
  }
  switch (this->GetGeneratorTarget()->GetType()) {
    case cmStateEnums::STATIC_LIBRARY: {
      // We have archive link commands set. First, delete the existing archive.
      {
        std::string cmakeCommand =
          this->GetLocalGenerator()->ConvertToOutputFormat(
            cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
        linkCmds.push_back(cmakeCommand + " -E remove $TARGET_FILE");
      }
      // TODO: Use ARCHIVE_APPEND for archives over a certain size.
      {
        std::string linkCmdVar = "CMAKE_";
        linkCmdVar += this->TargetLinkLanguage;
        linkCmdVar += "_ARCHIVE_CREATE";

        linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
          linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());

        const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar);
        cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
      }
      {
        std::string linkCmdVar = "CMAKE_";
        linkCmdVar += this->TargetLinkLanguage;
        linkCmdVar += "_ARCHIVE_FINISH";

        linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
          linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());

        const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar);
        cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
      }
      return linkCmds;
    }
    case cmStateEnums::SHARED_LIBRARY:
    case cmStateEnums::MODULE_LIBRARY:
    case cmStateEnums::EXECUTABLE:
      break;
    default:
      assert(false && "Unexpected target type");
  }
  return std::vector<std::string>();
}

void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement()
{
  cmGeneratorTarget& genTarget = *this->GetGeneratorTarget();

  // determine if we need to do any device linking for this target
  const std::string cuda_lang("CUDA");
  cmGeneratorTarget::LinkClosure const* closure =
    genTarget.GetLinkClosure(this->GetConfigName());

  const bool hasCUDA =
    (std::find(closure->Languages.begin(), closure->Languages.end(),
               cuda_lang) != closure->Languages.end());

  bool shouldHaveDeviceLinking = false;
  switch (genTarget.GetType()) {
    case cmStateEnums::SHARED_LIBRARY:
    case cmStateEnums::MODULE_LIBRARY:
    case cmStateEnums::EXECUTABLE:
      shouldHaveDeviceLinking = true;
      break;
    case cmStateEnums::STATIC_LIBRARY:
      shouldHaveDeviceLinking =
        genTarget.GetPropertyAsBool("CUDA_RESOLVE_DEVICE_SYMBOLS");
      break;
    default:
      break;
  }

  if (!(shouldHaveDeviceLinking && hasCUDA)) {
    return;
  }

  // Now we can do device linking

  // First and very important step is to make sure while inside this
  // step our link language is set to CUDA
  std::string cudaLinkLanguage = "CUDA";
  std::string const objExt =
    this->Makefile->GetSafeDefinition("CMAKE_CUDA_OUTPUT_EXTENSION");

  std::string const cfgName = this->GetConfigName();
  std::string const targetOutputReal = ConvertToNinjaPath(
    genTarget.ObjectDirectory + "cmake_device_link" + objExt);

  std::string const targetOutputImplib = ConvertToNinjaPath(
    genTarget.GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact));

  this->DeviceLinkObject = targetOutputReal;

  // Write comments.
  cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
  const cmStateEnums::TargetType targetType = genTarget.GetType();
  this->GetBuildFileStream() << "# Device Link build statements for "
                             << cmState::GetTargetTypeName(targetType)
                             << " target " << this->GetTargetName() << "\n\n";

  // Compute the comment.
  std::ostringstream comment;
  comment << "Link the " << this->GetVisibleTypeName() << " "
          << targetOutputReal;

  cmNinjaDeps emptyDeps;
  cmNinjaVars vars;

  // Compute outputs.
  cmNinjaDeps outputs;
  outputs.push_back(targetOutputReal);
  // Compute specific libraries to link with.
  cmNinjaDeps explicitDeps = this->GetObjects();
  cmNinjaDeps implicitDeps = this->ComputeLinkDeps();

  std::string frameworkPath;
  std::string linkPath;

  std::string createRule = genTarget.GetCreateRuleVariable(
    this->TargetLinkLanguage, this->GetConfigName());
  const bool useWatcomQuote =
    this->GetMakefile()->IsOn(createRule + "_USE_WATCOM_QUOTE");
  cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator();

  vars["TARGET_FILE"] =
    localGen.ConvertToOutputFormat(targetOutputReal, cmOutputConverter::SHELL);

  std::unique_ptr<cmLinkLineComputer> linkLineComputer(
    new cmNinjaLinkLineDeviceComputer(
      this->GetLocalGenerator(),
      this->GetLocalGenerator()->GetStateSnapshot().GetDirectory(),
      this->GetGlobalGenerator()));
  linkLineComputer->SetUseWatcomQuote(useWatcomQuote);

  localGen.GetTargetFlags(
    linkLineComputer.get(), this->GetConfigName(), vars["LINK_LIBRARIES"],
    vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, &genTarget);

  this->addPoolNinjaVariable("JOB_POOL_LINK", &genTarget, vars);

  vars["LINK_FLAGS"] =
    cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]);

  vars["MANIFESTS"] = this->GetManifests();

  vars["LINK_PATH"] = frameworkPath + linkPath;

  // Compute architecture specific link flags.  Yes, these go into a different
  // variable for executables, probably due to a mistake made when duplicating
  // code between the Makefile executable and library generators.
  if (targetType == cmStateEnums::EXECUTABLE) {
    std::string t = vars["FLAGS"];
    localGen.AddArchitectureFlags(t, &genTarget, cudaLinkLanguage, cfgName);
    vars["FLAGS"] = t;
  } else {
    std::string t = vars["ARCH_FLAGS"];
    localGen.AddArchitectureFlags(t, &genTarget, cudaLinkLanguage, cfgName);
    vars["ARCH_FLAGS"] = t;
    t.clear();
    localGen.AddLanguageFlagsForLinking(t, &genTarget, cudaLinkLanguage,
                                        cfgName);
    vars["LANGUAGE_COMPILE_FLAGS"] = t;
  }
  if (this->GetGeneratorTarget()->HasSOName(cfgName)) {
    vars["SONAME_FLAG"] =
      this->GetMakefile()->GetSONameFlag(this->TargetLinkLanguage);
    vars["SONAME"] = this->TargetNameSO;
    if (targetType == cmStateEnums::SHARED_LIBRARY) {
      std::string install_dir =
        this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(cfgName);
      if (!install_dir.empty()) {
        vars["INSTALLNAME_DIR"] = localGen.ConvertToOutputFormat(
          install_dir, cmOutputConverter::SHELL);
      }
    }
  }

  if (!this->TargetNameImport.empty()) {
    const std::string impLibPath = localGen.ConvertToOutputFormat(
      targetOutputImplib, cmOutputConverter::SHELL);
    vars["TARGET_IMPLIB"] = impLibPath;
    EnsureParentDirectoryExists(impLibPath);
  }

  const std::string objPath = GetGeneratorTarget()->GetSupportDirectory();
  vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
    this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL);
  EnsureDirectoryExists(objPath);

  this->SetMsvcTargetPdbVariable(vars);

  if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
    // ar.exe can't handle backslashes in rsp files (implicitly used by gcc)
    std::string& linkLibraries = vars["LINK_LIBRARIES"];
    std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/');
    std::string& link_path = vars["LINK_PATH"];
    std::replace(link_path.begin(), link_path.end(), '\\', '/');
  }

  cmGlobalNinjaGenerator& globalGen = *this->GetGlobalGenerator();

  // Device linking currently doesn't support response files so
  // do not check if the user has explicitly forced a response file.
  int const commandLineLengthLimit =
    static_cast<int>(cmSystemTools::CalculateCommandLineLengthLimit()) -
    globalGen.GetRuleCmdLength(this->LanguageLinkerDeviceRule());

  const std::string rspfile = this->ConvertToNinjaPath(
    std::string(cmake::GetCMakeFilesDirectoryPostSlash()) +
    genTarget.GetName() + ".rsp");

  // Gather order-only dependencies.
  cmNinjaDeps orderOnlyDeps;
  this->GetLocalGenerator()->AppendTargetDepends(this->GetGeneratorTarget(),
                                                 orderOnlyDeps);

  // Write the build statement for this target.
  bool usedResponseFile = false;
  globalGen.WriteBuild(this->GetBuildFileStream(), comment.str(),
                       this->LanguageLinkerDeviceRule(), outputs,
                       /*implicitOuts=*/cmNinjaDeps(), explicitDeps,
                       implicitDeps, orderOnlyDeps, vars, rspfile,
                       commandLineLengthLimit, &usedResponseFile);
  this->WriteDeviceLinkRule(false);
}

void cmNinjaNormalTargetGenerator::WriteLinkStatement()
{
  cmGeneratorTarget& gt = *this->GetGeneratorTarget();
  const std::string cfgName = this->GetConfigName();
  std::string targetOutput = ConvertToNinjaPath(gt.GetFullPath(cfgName));
  std::string targetOutputReal = ConvertToNinjaPath(
    gt.GetFullPath(cfgName, cmStateEnums::RuntimeBinaryArtifact,
                   /*realname=*/true));
  std::string targetOutputImplib = ConvertToNinjaPath(
    gt.GetFullPath(cfgName, cmStateEnums::ImportLibraryArtifact));

  if (gt.IsAppBundleOnApple()) {
    // Create the app bundle
    std::string outpath = gt.GetDirectory(cfgName);
    this->OSXBundleGenerator->CreateAppBundle(this->TargetNameOut, outpath);

    // Calculate the output path
    targetOutput = outpath;
    targetOutput += "/";
    targetOutput += this->TargetNameOut;
    targetOutput = this->ConvertToNinjaPath(targetOutput);
    targetOutputReal = outpath;
    targetOutputReal += "/";
    targetOutputReal += this->TargetNameReal;
    targetOutputReal = this->ConvertToNinjaPath(targetOutputReal);
  } else if (gt.IsFrameworkOnApple()) {
    // Create the library framework.
    this->OSXBundleGenerator->CreateFramework(this->TargetNameOut,
                                              gt.GetDirectory(cfgName));
  } else if (gt.IsCFBundleOnApple()) {
    // Create the core foundation bundle.
    this->OSXBundleGenerator->CreateCFBundle(this->TargetNameOut,
                                             gt.GetDirectory(cfgName));
  }

  // Write comments.
  cmGlobalNinjaGenerator::WriteDivider(this->GetBuildFileStream());
  const cmStateEnums::TargetType targetType = gt.GetType();
  this->GetBuildFileStream()
    << "# Link build statements for " << cmState::GetTargetTypeName(targetType)
    << " target " << this->GetTargetName() << "\n\n";

  cmNinjaDeps emptyDeps;
  cmNinjaVars vars;

  // Compute the comment.
  std::ostringstream comment;
  comment << "Link the " << this->GetVisibleTypeName() << " "
          << targetOutputReal;

  // Compute outputs.
  cmNinjaDeps outputs;
  outputs.push_back(targetOutputReal);

  // Compute specific libraries to link with.
  cmNinjaDeps explicitDeps = this->GetObjects();
  cmNinjaDeps implicitDeps = this->ComputeLinkDeps();

  if (!this->DeviceLinkObject.empty()) {
    explicitDeps.push_back(this->DeviceLinkObject);
  }

  cmMakefile* mf = this->GetMakefile();

  std::string frameworkPath;
  std::string linkPath;
  cmGeneratorTarget& genTarget = *this->GetGeneratorTarget();

  std::string createRule = genTarget.GetCreateRuleVariable(
    this->TargetLinkLanguage, this->GetConfigName());
  bool useWatcomQuote = mf->IsOn(createRule + "_USE_WATCOM_QUOTE");
  cmLocalNinjaGenerator& localGen = *this->GetLocalGenerator();

  vars["TARGET_FILE"] =
    localGen.ConvertToOutputFormat(targetOutputReal, cmOutputConverter::SHELL);

  std::unique_ptr<cmLinkLineComputer> linkLineComputer(
    this->GetGlobalGenerator()->CreateLinkLineComputer(
      this->GetLocalGenerator(),
      this->GetLocalGenerator()->GetStateSnapshot().GetDirectory()));
  linkLineComputer->SetUseWatcomQuote(useWatcomQuote);

  localGen.GetTargetFlags(
    linkLineComputer.get(), this->GetConfigName(), vars["LINK_LIBRARIES"],
    vars["FLAGS"], vars["LINK_FLAGS"], frameworkPath, linkPath, &genTarget);

  // Add OS X version flags, if any.
  if (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY ||
      this->GeneratorTarget->GetType() == cmStateEnums::MODULE_LIBRARY) {
    this->AppendOSXVerFlag(vars["LINK_FLAGS"], this->TargetLinkLanguage,
                           "COMPATIBILITY", true);
    this->AppendOSXVerFlag(vars["LINK_FLAGS"], this->TargetLinkLanguage,
                           "CURRENT", false);
  }

  this->addPoolNinjaVariable("JOB_POOL_LINK", &gt, vars);

  this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"]);
  vars["LINK_FLAGS"] =
    cmGlobalNinjaGenerator::EncodeLiteral(vars["LINK_FLAGS"]);

  vars["MANIFESTS"] = this->GetManifests();

  vars["LINK_PATH"] = frameworkPath + linkPath;
  std::string lwyuFlags;
  if (genTarget.GetPropertyAsBool("LINK_WHAT_YOU_USE")) {
    lwyuFlags = " -Wl,--no-as-needed";
  }

  // Compute architecture specific link flags.  Yes, these go into a different
  // variable for executables, probably due to a mistake made when duplicating
  // code between the Makefile executable and library generators.
  if (targetType == cmStateEnums::EXECUTABLE) {
    std::string t = vars["FLAGS"];
    localGen.AddArchitectureFlags(t, &genTarget, TargetLinkLanguage, cfgName);
    t += lwyuFlags;
    vars["FLAGS"] = t;
  } else {
    std::string t = vars["ARCH_FLAGS"];
    localGen.AddArchitectureFlags(t, &genTarget, TargetLinkLanguage, cfgName);
    vars["ARCH_FLAGS"] = t;
    t.clear();
    t += lwyuFlags;
    localGen.AddLanguageFlagsForLinking(t, &genTarget, TargetLinkLanguage,
                                        cfgName);
    vars["LANGUAGE_COMPILE_FLAGS"] = t;
  }
  if (this->GetGeneratorTarget()->HasSOName(cfgName)) {
    vars["SONAME_FLAG"] = mf->GetSONameFlag(this->TargetLinkLanguage);
    vars["SONAME"] = this->TargetNameSO;
    if (targetType == cmStateEnums::SHARED_LIBRARY) {
      std::string install_dir =
        this->GetGeneratorTarget()->GetInstallNameDirForBuildTree(cfgName);
      if (!install_dir.empty()) {
        vars["INSTALLNAME_DIR"] = localGen.ConvertToOutputFormat(
          install_dir, cmOutputConverter::SHELL);
      }
    }
  }

  cmNinjaDeps byproducts;

  if (!this->TargetNameImport.empty()) {
    const std::string impLibPath = localGen.ConvertToOutputFormat(
      targetOutputImplib, cmOutputConverter::SHELL);
    vars["TARGET_IMPLIB"] = impLibPath;
    EnsureParentDirectoryExists(impLibPath);
    if (genTarget.HasImportLibrary(cfgName)) {
      byproducts.push_back(targetOutputImplib);
    }
  }

  if (!this->SetMsvcTargetPdbVariable(vars)) {
    // It is common to place debug symbols at a specific place,
    // so we need a plain target name in the rule available.
    std::string prefix;
    std::string base;
    std::string suffix;
    this->GetGeneratorTarget()->GetFullNameComponents(prefix, base, suffix);
    std::string dbg_suffix = ".dbg";
    // TODO: Where to document?
    if (mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX")) {
      dbg_suffix = mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX");
    }
    vars["TARGET_PDB"] = base + suffix + dbg_suffix;
  }

  const std::string objPath = GetGeneratorTarget()->GetSupportDirectory();
  vars["OBJECT_DIR"] = this->GetLocalGenerator()->ConvertToOutputFormat(
    this->ConvertToNinjaPath(objPath), cmOutputConverter::SHELL);
  EnsureDirectoryExists(objPath);

  if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
    // ar.exe can't handle backslashes in rsp files (implicitly used by gcc)
    std::string& linkLibraries = vars["LINK_LIBRARIES"];
    std::replace(linkLibraries.begin(), linkLibraries.end(), '\\', '/');
    std::string& link_path = vars["LINK_PATH"];
    std::replace(link_path.begin(), link_path.end(), '\\', '/');
  }

  const std::vector<cmCustomCommand>* cmdLists[3] = {
    &gt.GetPreBuildCommands(), &gt.GetPreLinkCommands(),
    &gt.GetPostBuildCommands()
  };

  std::vector<std::string> preLinkCmdLines, postBuildCmdLines;
  std::vector<std::string>* cmdLineLists[3] = { &preLinkCmdLines,
                                                &preLinkCmdLines,
                                                &postBuildCmdLines };

  for (unsigned i = 0; i != 3; ++i) {
    for (cmCustomCommand const& cc : *cmdLists[i]) {
      cmCustomCommandGenerator ccg(cc, cfgName, this->GetLocalGenerator());
      localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]);
      std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
      std::transform(ccByproducts.begin(), ccByproducts.end(),
                     std::back_inserter(byproducts), MapToNinjaPath());
    }
  }

  // maybe create .def file from list of objects
  cmGeneratorTarget::ModuleDefinitionInfo const* mdi =
    gt.GetModuleDefinitionInfo(this->GetConfigName());
  if (mdi && mdi->DefFileGenerated) {
    std::string cmakeCommand =
      this->GetLocalGenerator()->ConvertToOutputFormat(
        cmSystemTools::GetCMakeCommand(), cmOutputConverter::SHELL);
    std::string cmd = cmakeCommand;
    cmd += " -E __create_def ";
    cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
      mdi->DefFile, cmOutputConverter::SHELL);
    cmd += " ";
    std::string obj_list_file = mdi->DefFile + ".objs";
    cmd += this->GetLocalGenerator()->ConvertToOutputFormat(
      obj_list_file, cmOutputConverter::SHELL);
    preLinkCmdLines.push_back(std::move(cmd));

    // create a list of obj files for the -E __create_def to read
    cmGeneratedFileStream fout(obj_list_file.c_str());

    if (mdi->WindowsExportAllSymbols) {
      cmNinjaDeps objs = this->GetObjects();
      for (std::string const& obj : objs) {
        if (cmHasLiteralSuffix(obj, ".obj")) {
          fout << obj << "\n";
        }
      }
    }

    for (cmSourceFile const* src : mdi->Sources) {
      fout << src->GetFullPath() << "\n";
    }
  }
  // If we have any PRE_LINK commands, we need to go back to CMAKE_BINARY_DIR
  // for
  // the link commands.
  if (!preLinkCmdLines.empty()) {
    const std::string homeOutDir = localGen.ConvertToOutputFormat(
      localGen.GetBinaryDirectory(), cmOutputConverter::SHELL);
    preLinkCmdLines.push_back("cd " + homeOutDir);
  }

  vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines, "pre-link",
                                               this->GeneratorTarget);
  std::string postBuildCmdLine = localGen.BuildCommandLine(
    postBuildCmdLines, "post-build", this->GeneratorTarget);

  cmNinjaVars symlinkVars;
  bool const symlinkNeeded =
    (targetOutput != targetOutputReal && !gt.IsFrameworkOnApple());
  if (!symlinkNeeded) {
    vars["POST_BUILD"] = postBuildCmdLine;
  } else {
    vars["POST_BUILD"] = cmGlobalNinjaGenerator::SHELL_NOOP;
    symlinkVars["POST_BUILD"] = postBuildCmdLine;
  }
  cmGlobalNinjaGenerator& globalGen = *this->GetGlobalGenerator();

  bool const lang_supports_response =
    !(this->TargetLinkLanguage == "RC" || this->TargetLinkLanguage == "CUDA");
  int commandLineLengthLimit = -1;
  if (!lang_supports_response || !this->ForceResponseFile()) {
    commandLineLengthLimit =
      static_cast<int>(cmSystemTools::CalculateCommandLineLengthLimit()) -
      globalGen.GetRuleCmdLength(this->LanguageLinkerRule());
  }

  const std::string rspfile = this->ConvertToNinjaPath(
    std::string(cmake::GetCMakeFilesDirectoryPostSlash()) + gt.GetName() +
    ".rsp");

  // Gather order-only dependencies.
  cmNinjaDeps orderOnlyDeps;
  this->GetLocalGenerator()->AppendTargetDepends(this->GetGeneratorTarget(),
                                                 orderOnlyDeps);

  // Ninja should restat after linking if and only if there are byproducts.
  vars["RESTAT"] = byproducts.empty() ? "" : "1";

  for (std::string const& o : byproducts) {
    this->GetGlobalGenerator()->SeenCustomCommandOutput(o);
    outputs.push_back(o);
  }

  // Write the build statement for this target.
  bool usedResponseFile = false;
  globalGen.WriteBuild(this->GetBuildFileStream(), comment.str(),
                       this->LanguageLinkerRule(), outputs,
                       /*implicitOuts=*/cmNinjaDeps(), explicitDeps,
                       implicitDeps, orderOnlyDeps, vars, rspfile,
                       commandLineLengthLimit, &usedResponseFile);
  this->WriteLinkRule(usedResponseFile);

  if (symlinkNeeded) {
    if (targetType == cmStateEnums::EXECUTABLE) {
      globalGen.WriteBuild(
        this->GetBuildFileStream(),
        "Create executable symlink " + targetOutput,
        "CMAKE_SYMLINK_EXECUTABLE", cmNinjaDeps(1, targetOutput),
        /*implicitOuts=*/cmNinjaDeps(), cmNinjaDeps(1, targetOutputReal),
        emptyDeps, emptyDeps, symlinkVars);
    } else {
      cmNinjaDeps symlinks;
      std::string const soName =
        this->ConvertToNinjaPath(this->GetTargetFilePath(this->TargetNameSO));
      // If one link has to be created.
      if (targetOutputReal == soName || targetOutput == soName) {
        symlinkVars["SONAME"] = soName;
      } else {
        symlinkVars["SONAME"].clear();
        symlinks.push_back(soName);
      }
      symlinks.push_back(targetOutput);
      globalGen.WriteBuild(
        this->GetBuildFileStream(), "Create library symlink " + targetOutput,
        "CMAKE_SYMLINK_LIBRARY", symlinks,
        /*implicitOuts=*/cmNinjaDeps(), cmNinjaDeps(1, targetOutputReal),
        emptyDeps, emptyDeps, symlinkVars);
    }
  }

  // Add aliases for the file name and the target name.
  globalGen.AddTargetAlias(this->TargetNameOut, &gt);
  globalGen.AddTargetAlias(this->GetTargetName(), &gt);
}

void cmNinjaNormalTargetGenerator::WriteObjectLibStatement()
{
  // Write a phony output that depends on all object files.
  cmNinjaDeps outputs;
  this->GetLocalGenerator()->AppendTargetOutputs(this->GetGeneratorTarget(),
                                                 outputs);
  cmNinjaDeps depends = this->GetObjects();
  this->GetGlobalGenerator()->WritePhonyBuild(
    this->GetBuildFileStream(), "Object library " + this->GetTargetName(),
    outputs, depends);

  // Add aliases for the target name.
  this->GetGlobalGenerator()->AddTargetAlias(this->GetTargetName(),
                                             this->GetGeneratorTarget());
}
