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

#include "cmConfigure.h"

#include <cstddef>
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>

#include <cm/string_view>
#include <cmext/algorithm>

#include "cmsys/RegularExpression.hxx"

#include "cmDiagnostics.h"
#include "cmEvaluatedTargetProperty.h"
#include "cmFileSetMetadata.h"
#include "cmGenExContext.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorFileSet.h"
#include "cmGeneratorFileSets.h"
#include "cmGlobalGenerator.h"
#include "cmLinkItem.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmPolicies.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmSourceGroup.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmValue.h"
#include "cmake.h"

namespace {
using UseTo = cmGeneratorTarget::UseTo;

void AddObjectEntries(cmGeneratorTarget const* headTarget,
                      cm::GenEx::Context const& context,
                      cmGeneratorExpressionDAGChecker* dagChecker,
                      cm::EvaluatedTargetPropertyEntries& entries)
{
  if (cmLinkImplementationLibraries const* impl =
        headTarget->GetLinkImplementationLibraries(context.Config,
                                                   UseTo::Link)) {
    entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition;
    for (cmLinkItem const& lib : impl->Libraries) {
      if (lib.Target &&
          lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
        std::string uniqueName =
          headTarget->GetGlobalGenerator()->IndexGeneratorTargetUniquely(
            lib.Target);
        std::string genex =
          cmStrCat("$<TARGET_OBJECTS:", std::move(uniqueName), '>');
        cmGeneratorExpression ge(*headTarget->Makefile->GetCMakeInstance(),
                                 lib.Backtrace);
        std::unique_ptr<cmCompiledGeneratorExpression> cge =
          ge.Parse(std::move(genex));
        cge->SetEvaluateForBuildsystem(true);

        cm::EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace);
        cmExpandList(cge->Evaluate(context, dagChecker, headTarget),
                     ee.Values);
        if (cge->GetHadContextSensitiveCondition()) {
          ee.ContextDependent = true;
        }
        entries.Entries.emplace_back(std::move(ee));
      }
    }
  }
}

void AddFileSetEntries(cmGeneratorTarget const* headTarget,
                       cmGeneratorFileSets const* fileSets,
                       cm::GenEx::Context const& context,
                       cmGeneratorExpressionDAGChecker* dagChecker,
                       cm::EvaluatedTargetPropertyEntries& entries)
{
  auto sources = fileSets->GetSources(context, headTarget, dagChecker);
  entries =
    EvaluateTargetPropertyEntries(headTarget, context, dagChecker, sources);
}

bool processSources(cmGeneratorTarget const* tgt, std::string const& config,
                    cm::EvaluatedTargetPropertyEntries& entries,
                    std::vector<BT<std::string>>& srcs,
                    std::unordered_set<std::string>& uniqueSrcs,
                    bool debugSources,
                    std::function<void(cmSourceFile*)> postProcess = {})
{
  cmMakefile* mf = tgt->Target->GetMakefile();

  bool contextDependent = entries.HadContextSensitiveCondition;

  for (cm::EvaluatedTargetPropertyEntry& entry : entries.Entries) {
    if (entry.ContextDependent) {
      contextDependent = true;
    }

    cmLinkItem const& item = entry.LinkItem;
    std::string const& targetName = item.AsStr();

    for (std::string& src : entry.Values) {
      cmSourceFile* sf = mf->GetOrCreateSource(src);
      std::string e;
      std::string w;
      std::string fullPath = sf->ResolveFullPath(&e, &w);
      cmLocalGenerator const* const lg = tgt->GetLocalGenerator();
      if (!w.empty()) {
        lg->IssueDiagnostic(cmDiagnostics::CMD_AUTHOR, w, entry.Backtrace);
      }
      if (fullPath.empty()) {
        if (!e.empty()) {
          lg->IssueMessage(MessageType::FATAL_ERROR, e, entry.Backtrace);
        }
        return contextDependent;
      }

      if (!targetName.empty() && !cmSystemTools::FileIsFullPath(src)) {
        std::ostringstream err;
        if (!targetName.empty()) {
          err << "Target \"" << targetName
              << "\" contains relative path in its INTERFACE_SOURCES:\n  \""
              << src << "\"";
        } else {
          err << "Found relative path while evaluating sources of \""
              << tgt->GetName() << "\":\n  \"" << src << "\"\n";
        }
        tgt->GetLocalGenerator()->IssueMessage(MessageType::FATAL_ERROR,
                                               err.str());
        return contextDependent;
      }
      src = fullPath;

      if (postProcess) {
        postProcess(sf);
      }
    }
    std::string usedSources;
    for (std::string const& src : entry.Values) {
      if (uniqueSrcs.insert(src).second) {
        srcs.emplace_back(src, entry.Backtrace);
        if (debugSources) {
          usedSources += cmStrCat(" * ", src, '\n');
        }
      } else {
        if (auto const* fileSet =
              tgt->GetGeneratorFileSets()->GetFileSetForSource(config, src)) {
          switch (tgt->GetPolicyStatusCMP0211()) {
            case cmPolicies::WARN:
              tgt->GetLocalGenerator()->IssueDiagnostic(
                cmDiagnostics::CMD_AUTHOR,
                cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0211),
                         "\nIn target \"", tgt->GetName(), "\" the file\n  ",
                         src, "\nalready belongs to file set \"",
                         fileSet->GetName(), "\"."));
              CM_FALLTHROUGH;
            case cmPolicies::OLD:
              break;
            default:
              tgt->GetLocalGenerator()->IssueMessage(
                MessageType::FATAL_ERROR,
                cmStrCat("In target \"", tgt->GetName(), "\" the file\n  ",
                         src, "\nalready belongs to file set \"",
                         fileSet->GetName(), "\"."));
          }
        }
      }
    }
    if (!usedSources.empty()) {
      tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
        MessageType::LOG,
        cmStrCat("Used sources for target ", tgt->GetName(), ":\n",
                 usedSources),
        entry.Backtrace);
    }
  }
  return contextDependent;
}
}

std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths(
  std::string const& config) const
{
  std::vector<BT<std::string>> files;

  cmList debugProperties{ this->Makefile->GetDefinition(
    "CMAKE_DEBUG_TARGET_PROPERTIES") };
  bool debugSources =
    !this->DebugSourcesDone && cm::contains(debugProperties, "SOURCES");

  this->DebugSourcesDone = true;

  cm::GenEx::Context context(this->LocalGenerator, config,
                             /*language=*/std::string());

  cmGeneratorExpressionDAGChecker dagChecker{
    this, "SOURCES", nullptr, nullptr, context,
  };

  cm::EvaluatedTargetPropertyEntries entries =
    cm::EvaluateTargetPropertyEntries(this, context, &dagChecker,
                                      this->SourceEntries);

  std::unordered_set<std::string> uniqueSrcs;
  bool contextDependentDirectSources =
    processSources(this, config, entries, files, uniqueSrcs, debugSources);

  // Collect INTERFACE_SOURCES of all direct link-dependencies.
  cm::EvaluatedTargetPropertyEntries linkInterfaceSourcesEntries;
  cm::AddInterfaceEntries(this, "INTERFACE_SOURCES", context, &dagChecker,
                          linkInterfaceSourcesEntries,
                          cm::IncludeRuntimeInterface::No, UseTo::Compile);
  bool contextDependentInterfaceSources =
    processSources(this, config, linkInterfaceSourcesEntries, files,
                   uniqueSrcs, debugSources);

  // Collect TARGET_OBJECTS of direct object link-dependencies.
  bool contextDependentObjects = false;
  if (this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
    cm::EvaluatedTargetPropertyEntries linkObjectsEntries;
    AddObjectEntries(this, context, &dagChecker, linkObjectsEntries);
    contextDependentObjects = processSources(this, config, linkObjectsEntries,
                                             files, uniqueSrcs, debugSources);
    // Note that for imported targets or multi-config generators supporting
    // cross-config builds the paths to the object files must be per-config,
    // so contextDependentObjects will be true here even if object libraries
    // are specified without per-config generator expressions.
  }

  // Collect this target's file sets.
  cmGeneratorExpressionDAGChecker fsDagChecker{
    this, "SOURCES", nullptr, nullptr, context,
  };

  cm::EvaluatedTargetPropertyEntries fileSetEntries;
  AddFileSetEntries(this, this->FileSets.get(), context, &fsDagChecker,
                    fileSetEntries);
  auto processFileSetEntry = [this, &config](cmSourceFile* sf) {
    auto const* fileSet = this->GetFileSetForSource(config, sf);
    if (fileSet->GetType() == cm::FileSetMetadata::HEADERS) {
      sf->SetProperty("HEADER_FILE_ONLY", "TRUE");
    }
#if !defined(CMAKE_BOOTSTRAP)
    cmMakefile* mf = this->Target->GetMakefile();
    auto const& path = sf->GetFullPath();
    bool found = false;
    for (auto const& sg : mf->GetSourceGroups()) {
      if (sg->MatchChildrenFiles(path)) {
        found = true;
        break;
      }
    }
    if (!found) {
      if (fileSet->GetType() == cm::FileSetMetadata::HEADERS) {
        mf->GetOrCreateSourceGroup("Header Files")->AddGroupFile(path);
      }
    }
#endif
  };
  bool contextDependentFileSets =
    processSources(this, config, fileSetEntries, files, uniqueSrcs,
                   debugSources, processFileSetEntry);

  // Collect file sets INTERFACE_SOURCES of all direct link-dependencies.
  cm::EvaluatedTargetPropertyEntries linkInterfaceFileSetsEntries;
  cm::AddInterfaceFileSetsEntries(this, cm::FileSetMetadata::SOURCES,
                                  "INTERFACE_SOURCES", context, &fsDagChecker,
                                  linkInterfaceFileSetsEntries);
  bool contextDependentInterfaceFileSets =
    processSources(this, config, linkInterfaceFileSetsEntries, files,
                   uniqueSrcs, debugSources);

  // Determine if sources are context-dependent or not.
  if (!contextDependentDirectSources && !contextDependentInterfaceSources &&
      !contextDependentObjects && !contextDependentFileSets &&
      !contextDependentInterfaceFileSets) {
    this->SourcesAreContextDependent = Tribool::False;
  } else {
    this->SourcesAreContextDependent = Tribool::True;
  }

  return files;
}

void cmGeneratorTarget::GetSourceFiles(std::vector<cmSourceFile*>& files,
                                       std::string const& config) const
{
  std::vector<BT<cmSourceFile*>> tmp = this->GetSourceFiles(config);
  files.reserve(tmp.size());
  for (BT<cmSourceFile*>& v : tmp) {
    files.push_back(v.Value);
  }
}

std::vector<BT<cmSourceFile*>> cmGeneratorTarget::GetSourceFiles(
  std::string const& config) const
{
  std::vector<BT<cmSourceFile*>> files;
  KindedSources const& kinded = this->GetKindedSources(config);
  files.reserve(kinded.Sources.size());
  for (SourceAndKind const& si : kinded.Sources) {
    files.push_back(si.Source);
  }
  return files;
}

void cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
  std::vector<cmSourceFile*>& files, std::string const& config) const
{
  std::vector<BT<cmSourceFile*>> tmp =
    this->GetSourceFilesWithoutObjectLibraries(config);
  files.reserve(tmp.size());
  for (BT<cmSourceFile*>& v : tmp) {
    files.push_back(v.Value);
  }
}

std::vector<BT<cmSourceFile*>>
cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries(
  std::string const& config) const
{
  std::vector<BT<cmSourceFile*>> files;
  KindedSources const& kinded = this->GetKindedSources(config);
  files.reserve(kinded.Sources.size());
  for (SourceAndKind const& si : kinded.Sources) {
    if (si.Source.Value->GetObjectLibrary().empty()) {
      files.push_back(si.Source);
    }
  }
  return files;
}

cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources(
  std::string const& config) const
{
  // If we already processed one configuration and found no dependency
  // on configuration then always use the one result.
  if (this->SourcesAreContextDependent == Tribool::False) {
    return this->KindedSourcesMap.begin()->second;
  }

  // Lookup any existing link implementation for this configuration.
  std::string const key = cmSystemTools::UpperCase(config);
  auto it = this->KindedSourcesMap.find(key);
  if (it != this->KindedSourcesMap.end()) {
    if (!it->second.Initialized) {
      std::ostringstream e;
      e << "The SOURCES of \"" << this->GetName()
        << "\" use a generator expression that depends on the "
           "SOURCES themselves.";
      this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
        MessageType::FATAL_ERROR, e.str(), this->GetBacktrace());
      static KindedSources empty;
      return empty;
    }
    return it->second;
  }

  // Add an entry to the map for this configuration.
  KindedSources& files = this->KindedSourcesMap[key];
  this->ComputeKindedSources(files, config);
  files.Initialized = true;
  return files;
}

void cmGeneratorTarget::ComputeKindedSources(KindedSources& files,
                                             std::string const& config) const
{
  // Get the source file paths by string.
  std::vector<BT<std::string>> srcs = this->GetSourceFilePaths(config);

  cmsys::RegularExpression header_regex(CM_HEADER_REGEX);
  std::vector<cmSourceFile*> badObjLib;

  cmValue const rustMainCrateRootProp =
    this->GetProperty("Rust_MAIN_CRATE_ROOT");
  cmSourceFile const* rustMainCrateRootSf = rustMainCrateRootProp
    ? this->Makefile->GetOrCreateSource(rustMainCrateRootProp)
    : nullptr;

  std::set<cmSourceFile*> emitted;
  for (BT<std::string> const& s : srcs) {
    // Create each source at most once.
    cmSourceFile* sf = this->Makefile->GetOrCreateSource(s.Value);
    if (!emitted.insert(sf).second) {
      continue;
    }

    // Compute the kind (classification) of this source file.
    SourceKind kind;
    std::string ext = cmSystemTools::LowerCase(sf->GetExtension());
    cmGeneratorFileSet const* fs = this->GetFileSetForSource(config, sf);
    if (sf->GetCustomCommand()) {
      kind = SourceKindCustomCommand;
    } else if (!this->Target->IsNormal() && !this->Target->IsImported() &&
               fs && (fs->GetType() == cm::FileSetMetadata::CXX_MODULES)) {
      kind = SourceKindCxxModuleSource;
    } else if (this->Target->GetType() == cmStateEnums::UTILITY ||
               this->Target->GetType() == cmStateEnums::INTERFACE_LIBRARY
               // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
               // NOLINTNEXTLINE(bugprone-branch-clone)
    ) {
      kind = SourceKindExtra;
    } else if (this->IsSourceFilePartOfUnityBatch(sf->ResolveFullPath())) {
      kind = SourceKindUnityBatched;
      // XXX(clang-tidy): https://bugs.llvm.org/show_bug.cgi?id=44165
      // NOLINTNEXTLINE(bugprone-branch-clone)
    } else if (sf->GetPropertyAsBool("HEADER_FILE_ONLY")) {
      kind = SourceKindHeader;
    } else if (sf->GetPropertyAsBool("EXTERNAL_OBJECT")) {
      kind = SourceKindExternalObject;
    } else if (!sf->GetOrDetermineLanguage().empty()) {
      if (sf->GetOrDetermineLanguage() == "Rust") {
        // NOLINTNEXTLINE(bugprone-branch-clone)
        if (this->Target->GetType() == cmStateEnums::OBJECT_LIBRARY) {
          // There is no main crate root for object libraries.
          kind = SourceKindObjectSource;
        } else if (!rustMainCrateRootSf) {
          // We do not have a main crate root source file, we use the first
          // Rust source file for it.
          rustMainCrateRootSf = sf;
          kind = SourceKindRustMainCrateRoot;
        } else if (rustMainCrateRootSf == sf) {
          // Current source file is the main crate root defined in the target
          // Rust_MAIN_CRATE_ROOT property.
          kind = SourceKindRustMainCrateRoot;
        } else {
          // Any other Rust source file is treated as a normal object, but will
          // be built into a .rlib. Maybe in the future this could be changed?
          kind = SourceKindObjectSource;
        }
      } else {
        kind = SourceKindObjectSource;
      }
    } else if (ext == "def") {
      kind = SourceKindModuleDefinition;
      if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
        badObjLib.push_back(sf);
      }
    } else if (ext == "idl") {
      kind = SourceKindIDL;
      if (this->GetType() == cmStateEnums::OBJECT_LIBRARY) {
        badObjLib.push_back(sf);
      }
    } else if (ext == "resx") {
      kind = SourceKindResx;
    } else if (ext == "appxmanifest") {
      kind = SourceKindAppManifest;
    } else if (ext == "manifest") {
      if (sf->GetPropertyAsBool("VS_DEPLOYMENT_CONTENT")) {
        kind = SourceKindExtra;
      } else {
        kind = SourceKindManifest;
      }
    } else if (ext == "pfx") {
      kind = SourceKindCertificate;
    } else if (ext == "xaml") {
      kind = SourceKindXaml;
    } else if (header_regex.find(sf->ResolveFullPath())) {
      kind = SourceKindHeader;
    } else {
      kind = SourceKindExtra;
    }

    // Save this classified source file in the result vector.
    files.Sources.push_back({ BT<cmSourceFile*>(sf, s.Backtrace), kind });
  }

  if (!badObjLib.empty()) {
    std::ostringstream e;
    e << "OBJECT library \"" << this->GetName() << "\" contains:\n";
    for (cmSourceFile* i : badObjLib) {
      e << "  " << i->GetLocation().GetName() << "\n";
    }
    e << "but may contain only sources that compile, header files, and "
         "other files that would not affect linking of a normal library.";
    this->GlobalGenerator->GetCMakeInstance()->IssueMessage(
      MessageType::FATAL_ERROR, e.str(), this->GetBacktrace());
  }
}

std::vector<cmGeneratorTarget::AllConfigSource> const&
cmGeneratorTarget::GetAllConfigSources() const
{
  if (this->AllConfigSources.empty()) {
    this->ComputeAllConfigSources();
  }
  return this->AllConfigSources;
}

void cmGeneratorTarget::ComputeAllConfigSources() const
{
  std::vector<std::string> configs =
    this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);

  std::map<cmSourceFile const*, size_t> index;

  for (size_t ci = 0; ci < configs.size(); ++ci) {
    KindedSources const& sources = this->GetKindedSources(configs[ci]);
    for (SourceAndKind const& src : sources.Sources) {
      auto mi = index.find(src.Source.Value);
      if (mi == index.end()) {
        AllConfigSource acs;
        acs.Source = src.Source.Value;
        acs.Kind = src.Kind;
        this->AllConfigSources.push_back(std::move(acs));
        std::map<cmSourceFile const*, size_t>::value_type entry(
          src.Source.Value, this->AllConfigSources.size() - 1);
        mi = index.insert(entry).first;
      }
      this->AllConfigSources[mi->second].Configs.push_back(ci);
    }
  }
}

std::vector<cmGeneratorTarget::AllConfigSource>
cmGeneratorTarget::GetAllConfigSources(SourceKind kind) const
{
  std::vector<AllConfigSource> result;
  for (AllConfigSource const& source : this->GetAllConfigSources()) {
    if (source.Kind == kind) {
      result.push_back(source);
    }
  }
  return result;
}

void cmGeneratorTarget::ComputeAllConfigCompileLanguages() const
{
  std::set<std::string> languages;
  std::vector<AllConfigSource> const& sources = this->GetAllConfigSources();
  for (AllConfigSource const& si : sources) {
    std::string const& lang = si.Source->GetOrDetermineLanguage();
    if (!lang.empty()) {
      languages.emplace(lang);
    }
  }
  this->AllConfigCompileLanguages = languages;
}

std::set<std::string> cmGeneratorTarget::GetAllConfigCompileLanguages() const
{
  if (this->AllConfigCompileLanguages.empty()) {
    this->ComputeAllConfigCompileLanguages();
  }
  return this->AllConfigCompileLanguages;
}
