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

#include <cassert>
#include <memory>
#include <sstream>
#include <unordered_set>
#include <utility>

#include <cm/optional>
#include <cm/string_view>

#include "cmExecutionStatus.h"
#include "cmGeneratorExpression.h"
#include "cmGlobalGenerator.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmState.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetLinkLibraryType.h"
#include "cmValue.h"
#include "cmake.h"

namespace {

enum ProcessingState
{
  ProcessingLinkLibraries,
  ProcessingPlainLinkInterface,
  ProcessingKeywordLinkInterface,
  ProcessingPlainPublicInterface,
  ProcessingKeywordPublicInterface,
  ProcessingPlainPrivateInterface,
  ProcessingKeywordPrivateInterface
};

const char* LinkLibraryTypeNames[3] = { "general", "debug", "optimized" };

struct TLL
{
  cmMakefile& Makefile;
  cmTarget* Target;
  bool WarnRemoteInterface = false;
  bool RejectRemoteLinking = false;
  bool EncodeRemoteReference = false;
  std::string DirectoryId;
  std::unordered_set<std::string> Props;

  TLL(cmMakefile& mf, cmTarget* target);
  ~TLL();

  bool HandleLibrary(ProcessingState currentProcessingState,
                     const std::string& lib, cmTargetLinkLibraryType llt);
  void AppendProperty(std::string const& prop, std::string const& value);
  void AffectsProperty(std::string const& prop);
};

} // namespace

static void LinkLibraryTypeSpecifierWarning(cmMakefile& mf, int left,
                                            int right);

bool cmTargetLinkLibrariesCommand(std::vector<std::string> const& args,
                                  cmExecutionStatus& status)
{
  // Must have at least one argument.
  if (args.empty()) {
    status.SetError("called with incorrect number of arguments");
    return false;
  }

  cmMakefile& mf = status.GetMakefile();

  // Alias targets cannot be on the LHS of this command.
  if (mf.IsAlias(args[0])) {
    status.SetError("can not be used on an ALIAS target.");
    return false;
  }

  // Lookup the target for which libraries are specified.
  cmTarget* target =
    mf.GetCMakeInstance()->GetGlobalGenerator()->FindTarget(args[0]);
  if (!target) {
    for (const auto& importedTarget : mf.GetOwnedImportedTargets()) {
      if (importedTarget->GetName() == args[0]) {
        target = importedTarget.get();
        break;
      }
    }
  }
  if (!target) {
    MessageType t = MessageType::FATAL_ERROR; // fail by default
    std::ostringstream e;
    e << "Cannot specify link libraries for target \"" << args[0] << "\" "
      << "which is not built by this project.";
    // The bad target is the only argument. Check how policy CMP0016 is set,
    // and accept, warn or fail respectively:
    if (args.size() < 2) {
      switch (mf.GetPolicyStatus(cmPolicies::CMP0016)) {
        case cmPolicies::WARN:
          t = MessageType::AUTHOR_WARNING;
          // Print the warning.
          e << "\n"
            << "CMake does not support this but it used to work accidentally "
            << "and is being allowed for compatibility."
            << "\n"
            << cmPolicies::GetPolicyWarning(cmPolicies::CMP0016);
          break;
        case cmPolicies::OLD: // OLD behavior does not warn.
          t = MessageType::MESSAGE;
          break;
        case cmPolicies::REQUIRED_IF_USED:
        case cmPolicies::REQUIRED_ALWAYS:
          e << "\n" << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0016);
          break;
        case cmPolicies::NEW: // NEW behavior prints the error.
          break;
      }
    }
    // Now actually print the message.
    switch (t) {
      case MessageType::AUTHOR_WARNING:
        mf.IssueMessage(MessageType::AUTHOR_WARNING, e.str());
        break;
      case MessageType::FATAL_ERROR:
        mf.IssueMessage(MessageType::FATAL_ERROR, e.str());
        cmSystemTools::SetFatalErrorOccurred();
        break;
      default:
        break;
    }
    return true;
  }

  // Having a UTILITY library on the LHS is a bug.
  if (target->GetType() == cmStateEnums::UTILITY) {
    std::ostringstream e;
    const char* modal = nullptr;
    MessageType messageType = MessageType::AUTHOR_WARNING;
    switch (mf.GetPolicyStatus(cmPolicies::CMP0039)) {
      case cmPolicies::WARN:
        e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0039) << "\n";
        modal = "should";
        CM_FALLTHROUGH;
      case cmPolicies::OLD:
        break;
      case cmPolicies::REQUIRED_ALWAYS:
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::NEW:
        modal = "must";
        messageType = MessageType::FATAL_ERROR;
        break;
    }
    if (modal) {
      e << "Utility target \"" << target->GetName() << "\" " << modal
        << " not be used as the target of a target_link_libraries call.";
      mf.IssueMessage(messageType, e.str());
      if (messageType == MessageType::FATAL_ERROR) {
        return false;
      }
    }
  }

  // But we might not have any libs after variable expansion.
  if (args.size() < 2) {
    return true;
  }

  TLL tll(mf, target);

  // Keep track of link configuration specifiers.
  cmTargetLinkLibraryType llt = GENERAL_LibraryType;
  bool haveLLT = false;

  // Start with primary linking and switch to link interface
  // specification if the keyword is encountered as the first argument.
  ProcessingState currentProcessingState = ProcessingLinkLibraries;

  // Accumulate consectuive non-keyword arguments into one entry in
  // order to handle unquoted generator expressions containing ';'.
  std::size_t genexNesting = 0;
  cm::optional<std::string> currentEntry;
  auto processCurrentEntry = [&]() -> bool {
    // FIXME: Warn about partial genex if genexNesting > 0?
    genexNesting = 0;
    if (currentEntry) {
      assert(!haveLLT);
      if (!tll.HandleLibrary(currentProcessingState, *currentEntry,
                             GENERAL_LibraryType)) {
        return false;
      }
      currentEntry = cm::nullopt;
    }
    return true;
  };
  auto extendCurrentEntry = [&currentEntry](std::string const& arg) {
    if (currentEntry) {
      currentEntry = cmStrCat(*currentEntry, ';', arg);
    } else {
      currentEntry = arg;
    }
  };

  // Keep this list in sync with the keyword dispatch below.
  static std::unordered_set<std::string> const keywords{
    "LINK_INTERFACE_LIBRARIES",
    "INTERFACE",
    "LINK_PUBLIC",
    "PUBLIC",
    "LINK_PRIVATE",
    "PRIVATE",
    "debug",
    "optimized",
    "general",
  };

  // Add libraries, note that there is an optional prefix
  // of debug and optimized that can be used.
  for (unsigned int i = 1; i < args.size(); ++i) {
    if (keywords.count(args[i])) {
      // A keyword argument terminates any accumulated partial genex.
      if (!processCurrentEntry()) {
        return false;
      }

      // Process this keyword argument.
      if (args[i] == "LINK_INTERFACE_LIBRARIES") {
        currentProcessingState = ProcessingPlainLinkInterface;
        if (i != 1) {
          mf.IssueMessage(
            MessageType::FATAL_ERROR,
            "The LINK_INTERFACE_LIBRARIES option must appear as the "
            "second argument, just after the target name.");
          return true;
        }
      } else if (args[i] == "INTERFACE") {
        if (i != 1 &&
            currentProcessingState != ProcessingKeywordPrivateInterface &&
            currentProcessingState != ProcessingKeywordPublicInterface &&
            currentProcessingState != ProcessingKeywordLinkInterface) {
          mf.IssueMessage(MessageType::FATAL_ERROR,
                          "The INTERFACE, PUBLIC or PRIVATE option must "
                          "appear as the second argument, just after the "
                          "target name.");
          return true;
        }
        currentProcessingState = ProcessingKeywordLinkInterface;
      } else if (args[i] == "LINK_PUBLIC") {
        if (i != 1 &&
            currentProcessingState != ProcessingPlainPrivateInterface &&
            currentProcessingState != ProcessingPlainPublicInterface) {
          mf.IssueMessage(
            MessageType::FATAL_ERROR,
            "The LINK_PUBLIC or LINK_PRIVATE option must appear as the "
            "second argument, just after the target name.");
          return true;
        }
        currentProcessingState = ProcessingPlainPublicInterface;
      } else if (args[i] == "PUBLIC") {
        if (i != 1 &&
            currentProcessingState != ProcessingKeywordPrivateInterface &&
            currentProcessingState != ProcessingKeywordPublicInterface &&
            currentProcessingState != ProcessingKeywordLinkInterface) {
          mf.IssueMessage(MessageType::FATAL_ERROR,
                          "The INTERFACE, PUBLIC or PRIVATE option must "
                          "appear as the second argument, just after the "
                          "target name.");
          return true;
        }
        currentProcessingState = ProcessingKeywordPublicInterface;
      } else if (args[i] == "LINK_PRIVATE") {
        if (i != 1 &&
            currentProcessingState != ProcessingPlainPublicInterface &&
            currentProcessingState != ProcessingPlainPrivateInterface) {
          mf.IssueMessage(
            MessageType::FATAL_ERROR,
            "The LINK_PUBLIC or LINK_PRIVATE option must appear as the "
            "second argument, just after the target name.");
          return true;
        }
        currentProcessingState = ProcessingPlainPrivateInterface;
      } else if (args[i] == "PRIVATE") {
        if (i != 1 &&
            currentProcessingState != ProcessingKeywordPrivateInterface &&
            currentProcessingState != ProcessingKeywordPublicInterface &&
            currentProcessingState != ProcessingKeywordLinkInterface) {
          mf.IssueMessage(MessageType::FATAL_ERROR,
                          "The INTERFACE, PUBLIC or PRIVATE option must "
                          "appear as the second argument, just after the "
                          "target name.");
          return true;
        }
        currentProcessingState = ProcessingKeywordPrivateInterface;
      } else if (args[i] == "debug") {
        if (haveLLT) {
          LinkLibraryTypeSpecifierWarning(mf, llt, DEBUG_LibraryType);
        }
        llt = DEBUG_LibraryType;
        haveLLT = true;
      } else if (args[i] == "optimized") {
        if (haveLLT) {
          LinkLibraryTypeSpecifierWarning(mf, llt, OPTIMIZED_LibraryType);
        }
        llt = OPTIMIZED_LibraryType;
        haveLLT = true;
      } else if (args[i] == "general") {
        if (haveLLT) {
          LinkLibraryTypeSpecifierWarning(mf, llt, GENERAL_LibraryType);
        }
        llt = GENERAL_LibraryType;
        haveLLT = true;
      }
    } else if (haveLLT) {
      // The link type was specified by the previous argument.
      haveLLT = false;
      assert(!currentEntry);
      if (!tll.HandleLibrary(currentProcessingState, args[i], llt)) {
        return false;
      }
      llt = GENERAL_LibraryType;
    } else {
      // Track the genex nesting level.
      {
        cm::string_view arg = args[i];
        for (std::string::size_type pos = 0; pos < arg.size(); ++pos) {
          cm::string_view cur = arg.substr(pos);
          if (cmHasLiteralPrefix(cur, "$<")) {
            ++genexNesting;
            ++pos;
          } else if (genexNesting > 0 && cmHasLiteralPrefix(cur, ">")) {
            --genexNesting;
          }
        }
      }

      // Accumulate this argument in the current entry.
      extendCurrentEntry(args[i]);

      // Process this entry if it does not end inside a genex.
      if (genexNesting == 0) {
        if (!processCurrentEntry()) {
          return false;
        }
      }
    }
  }

  // Process the last accumulated partial genex, if any.
  if (!processCurrentEntry()) {
    return false;
  }

  // Make sure the last argument was not a library type specifier.
  if (haveLLT) {
    mf.IssueMessage(MessageType::FATAL_ERROR,
                    cmStrCat("The \"", LinkLibraryTypeNames[llt],
                             "\" argument must be followed by a library."));
    cmSystemTools::SetFatalErrorOccurred();
  }

  const cmPolicies::PolicyStatus policy22Status =
    target->GetPolicyStatusCMP0022();

  // If any of the LINK_ options were given, make sure the
  // LINK_INTERFACE_LIBRARIES target property exists.
  // Use of any of the new keywords implies awareness of
  // this property. And if no libraries are named, it should
  // result in an empty link interface.
  if ((policy22Status == cmPolicies::OLD ||
       policy22Status == cmPolicies::WARN) &&
      currentProcessingState != ProcessingLinkLibraries &&
      !target->GetProperty("LINK_INTERFACE_LIBRARIES")) {
    target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
  }

  target->CheckProperty("LINK_LIBRARIES", &mf);
  target->CheckProperty("INTERFACE_LINK_LIBRARIES", &mf);

  return true;
}

static void LinkLibraryTypeSpecifierWarning(cmMakefile& mf, int left,
                                            int right)
{
  mf.IssueMessage(
    MessageType::AUTHOR_WARNING,
    cmStrCat(
      "Link library type specifier \"", LinkLibraryTypeNames[left],
      "\" is followed by specifier \"", LinkLibraryTypeNames[right],
      "\" instead of a library name.  The first specifier will be ignored."));
}

namespace {

TLL::TLL(cmMakefile& mf, cmTarget* target)
  : Makefile(mf)
  , Target(target)
{
  if (&this->Makefile != this->Target->GetMakefile()) {
    // The LHS target was created in another directory.
    switch (this->Makefile.GetPolicyStatus(cmPolicies::CMP0079)) {
      case cmPolicies::WARN:
        this->WarnRemoteInterface = true;
        CM_FALLTHROUGH;
      case cmPolicies::OLD:
        this->RejectRemoteLinking = true;
        break;
      case cmPolicies::REQUIRED_ALWAYS:
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::NEW:
        this->EncodeRemoteReference = true;
        break;
    }
  }
  if (this->EncodeRemoteReference) {
    cmDirectoryId const dirId = this->Makefile.GetDirectoryId();
    this->DirectoryId = cmStrCat(CMAKE_DIRECTORY_ID_SEP, dirId.String);
  }
}

bool TLL::HandleLibrary(ProcessingState currentProcessingState,
                        const std::string& lib, cmTargetLinkLibraryType llt)
{
  if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY &&
      currentProcessingState != ProcessingKeywordLinkInterface) {
    this->Makefile.IssueMessage(
      MessageType::FATAL_ERROR,
      "INTERFACE library can only be used with the INTERFACE keyword of "
      "target_link_libraries");
    return false;
  }
  if (this->Target->IsImported() &&
      currentProcessingState != ProcessingKeywordLinkInterface) {
    this->Makefile.IssueMessage(
      MessageType::FATAL_ERROR,
      "IMPORTED library can only be used with the INTERFACE keyword of "
      "target_link_libraries");
    return false;
  }

  cmTarget::TLLSignature sig =
    (currentProcessingState == ProcessingPlainPrivateInterface ||
     currentProcessingState == ProcessingPlainPublicInterface ||
     currentProcessingState == ProcessingKeywordPrivateInterface ||
     currentProcessingState == ProcessingKeywordPublicInterface ||
     currentProcessingState == ProcessingKeywordLinkInterface)
    ? cmTarget::KeywordTLLSignature
    : cmTarget::PlainTLLSignature;
  if (!this->Target->PushTLLCommandTrace(
        sig, this->Makefile.GetBacktrace().Top())) {
    std::ostringstream e;
    const char* modal = nullptr;
    MessageType messageType = MessageType::AUTHOR_WARNING;
    switch (this->Makefile.GetPolicyStatus(cmPolicies::CMP0023)) {
      case cmPolicies::WARN:
        e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0023) << "\n";
        modal = "should";
        CM_FALLTHROUGH;
      case cmPolicies::OLD:
        break;
      case cmPolicies::REQUIRED_ALWAYS:
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::NEW:
        modal = "must";
        messageType = MessageType::FATAL_ERROR;
        break;
    }

    if (modal) {
      // If the sig is a keyword form and there is a conflict, the existing
      // form must be the plain form.
      const char* existingSig =
        (sig == cmTarget::KeywordTLLSignature ? "plain" : "keyword");
      e << "The " << existingSig
        << " signature for target_link_libraries has "
           "already been used with the target \""
        << this->Target->GetName()
        << "\".  All uses of target_link_libraries with a target " << modal
        << " be either all-keyword or all-plain.\n";
      this->Target->GetTllSignatureTraces(e,
                                          sig == cmTarget::KeywordTLLSignature
                                            ? cmTarget::PlainTLLSignature
                                            : cmTarget::KeywordTLLSignature);
      this->Makefile.IssueMessage(messageType, e.str());
      if (messageType == MessageType::FATAL_ERROR) {
        return false;
      }
    }
  }

  // Handle normal case where the command was called with another keyword than
  // INTERFACE / LINK_INTERFACE_LIBRARIES or none at all. (The "LINK_LIBRARIES"
  // property of the target on the LHS shall be populated.)
  if (currentProcessingState != ProcessingKeywordLinkInterface &&
      currentProcessingState != ProcessingPlainLinkInterface) {

    if (this->RejectRemoteLinking) {
      this->Makefile.IssueMessage(
        MessageType::FATAL_ERROR,
        cmStrCat("Attempt to add link library \"", lib, "\" to target \"",
                 this->Target->GetName(),
                 "\" which is not built in this "
                 "directory.\nThis is allowed only when policy CMP0079 "
                 "is set to NEW."));
      return false;
    }

    cmTarget* tgt = this->Makefile.GetGlobalGenerator()->FindTarget(lib);

    if (tgt && (tgt->GetType() != cmStateEnums::STATIC_LIBRARY) &&
        (tgt->GetType() != cmStateEnums::SHARED_LIBRARY) &&
        (tgt->GetType() != cmStateEnums::UNKNOWN_LIBRARY) &&
        (tgt->GetType() != cmStateEnums::OBJECT_LIBRARY) &&
        (tgt->GetType() != cmStateEnums::INTERFACE_LIBRARY) &&
        !tgt->IsExecutableWithExports()) {
      this->Makefile.IssueMessage(
        MessageType::FATAL_ERROR,
        cmStrCat(
          "Target \"", lib, "\" of type ",
          cmState::GetTargetTypeName(tgt->GetType()),
          " may not be linked into another target. One may link only to "
          "INTERFACE, OBJECT, STATIC or SHARED libraries, or to ",
          "executables with the ENABLE_EXPORTS property set."));
    }

    this->AffectsProperty("LINK_LIBRARIES");
    this->Target->AddLinkLibrary(this->Makefile, lib, llt);
  }

  if (this->WarnRemoteInterface) {
    this->Makefile.IssueMessage(
      MessageType::AUTHOR_WARNING,
      cmStrCat(
        cmPolicies::GetPolicyWarning(cmPolicies::CMP0079), "\nTarget\n  ",
        this->Target->GetName(),
        "\nis not created in this "
        "directory.  For compatibility with older versions of CMake, link "
        "library\n  ",
        lib,
        "\nwill be looked up in the directory in which "
        "the target was created rather than in this calling directory."));
  }

  // Handle (additional) case where the command was called with PRIVATE /
  // LINK_PRIVATE and stop its processing. (The "INTERFACE_LINK_LIBRARIES"
  // property of the target on the LHS shall only be populated if it is a
  // STATIC library.)
  if (currentProcessingState == ProcessingKeywordPrivateInterface ||
      currentProcessingState == ProcessingPlainPrivateInterface) {
    if (this->Target->GetType() == cmStateEnums::STATIC_LIBRARY ||
        this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
      std::string configLib =
        this->Target->GetDebugGeneratorExpressions(lib, llt);
      if (cmGeneratorExpression::IsValidTargetName(lib) ||
          cmGeneratorExpression::Find(lib) != std::string::npos) {
        configLib = "$<LINK_ONLY:" + configLib + ">";
      }
      this->AppendProperty("INTERFACE_LINK_LIBRARIES", configLib);
    }
    return true;
  }

  // Handle general case where the command was called with another keyword than
  // PRIVATE / LINK_PRIVATE or none at all. (The "INTERFACE_LINK_LIBRARIES"
  // property of the target on the LHS shall be populated.)
  this->AppendProperty("INTERFACE_LINK_LIBRARIES",
                       this->Target->GetDebugGeneratorExpressions(lib, llt));

  // Stop processing if called without any keyword.
  if (currentProcessingState == ProcessingLinkLibraries) {
    return true;
  }
  // Stop processing if policy CMP0022 is set to NEW.
  const cmPolicies::PolicyStatus policy22Status =
    this->Target->GetPolicyStatusCMP0022();
  if (policy22Status != cmPolicies::OLD &&
      policy22Status != cmPolicies::WARN) {
    return true;
  }
  // Stop processing if called with an INTERFACE library on the LHS.
  if (this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
    return true;
  }

  // Handle (additional) backward-compatibility case where the command was
  // called with PUBLIC / INTERFACE / LINK_PUBLIC / LINK_INTERFACE_LIBRARIES.
  // (The policy CMP0022 is not set to NEW.)
  {
    // Get the list of configurations considered to be DEBUG.
    std::vector<std::string> debugConfigs =
      this->Makefile.GetCMakeInstance()->GetDebugConfigs();
    std::string prop;

    // Include this library in the link interface for the target.
    if (llt == DEBUG_LibraryType || llt == GENERAL_LibraryType) {
      // Put in the DEBUG configuration interfaces.
      for (std::string const& dc : debugConfigs) {
        prop = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc);
        this->AppendProperty(prop, lib);
      }
    }
    if (llt == OPTIMIZED_LibraryType || llt == GENERAL_LibraryType) {
      // Put in the non-DEBUG configuration interfaces.
      this->AppendProperty("LINK_INTERFACE_LIBRARIES", lib);

      // Make sure the DEBUG configuration interfaces exist so that the
      // general one will not be used as a fall-back.
      for (std::string const& dc : debugConfigs) {
        prop = cmStrCat("LINK_INTERFACE_LIBRARIES_", dc);
        if (!this->Target->GetProperty(prop)) {
          this->Target->SetProperty(prop, "");
        }
      }
    }
  }
  return true;
}

void TLL::AppendProperty(std::string const& prop, std::string const& value)
{
  this->AffectsProperty(prop);
  this->Target->AppendProperty(prop, value);
}

void TLL::AffectsProperty(std::string const& prop)
{
  if (!this->EncodeRemoteReference) {
    return;
  }
  // Add a wrapper to the expression to tell LookupLinkItem to look up
  // names in the caller's directory.
  if (this->Props.insert(prop).second) {
    this->Target->AppendProperty(prop, this->DirectoryId);
  }
}

TLL::~TLL()
{
  for (std::string const& prop : this->Props) {
    this->Target->AppendProperty(prop, CMAKE_DIRECTORY_ID_SEP);
  }
}

} // namespace
