/* 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 <algorithm>
#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 "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 "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmTargetTypes.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() == cm::TargetType::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->IssuePolicyWarning(cmPolicies::CMP0115, {}, 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 {
        auto const& fileSets =
          tgt->GetGeneratorFileSets()->GetAllFileSetsForSource(config, src);
        if (fileSets.empty()) {
          continue;
        }
        auto fileMustBeUnique = [&fileSets]() -> bool {
          return std::none_of(
            fileSets.begin(), fileSets.end(),
            [](cmGeneratorFileSet const* fileSet) {
              return cm::FileSetMetadata::GetAttributes(fileSet->GetType())
                .contains(cm::FileSetMetadata::FileSetAttributes::
                            FilesInMultipleFileSets);
            });
        };
        if (fileMustBeUnique()) {
          auto const* fileSet = *fileSets.begin();
          switch (tgt->GetPolicyStatusCMP0211()) {
            case cmPolicies::WARN:
              tgt->GetLocalGenerator()->IssuePolicyWarning(
                cmPolicies::CMP0211, {},
                cmStrCat("In 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() != cm::TargetType::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) {
    cmGeneratorFileSet const* fileSet = this->GetFileSetForSource(config, sf);
    if (fileSet && fileSet->GetType() == cm::FileSetMetadata::HEADERS) {
      sf->SetProperty("HEADER_FILE_ONLY", "TRUE");
#if !defined(CMAKE_BOOTSTRAP)
      cmMakefile* mf = this->Target->GetMakefile();
      std::string const& path = sf->GetFullPath();
      bool found = false;
      for (auto const& sg : mf->GetSourceGroups()) {
        if (sg->MatchChildrenFiles(path)) {
          found = true;
          break;
        }
      }
      if (!found) {
        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 = this->Target->CxxModuleNeedsInterfaceObjects()
        ? SourceKindObjectSource
        : SourceKindCxxModuleSource;
    } else if (this->Target->GetType() == cm::TargetType::UTILITY ||
               this->Target->GetType() == cm::TargetType::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() == cm::TargetType::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() == cm::TargetType::OBJECT_LIBRARY) {
        badObjLib.push_back(sf);
      }
    } else if (ext == "idl") {
      kind = SourceKindIDL;
      if (this->GetType() == cm::TargetType::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;
}
