/* 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 "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->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() != 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;
}
