/* 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 "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_POLICY, 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()->IssueDiagnostic(
                cmDiagnostics::CMD_POLICY,
                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;
}
