/* 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 <cstddef>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <string>
#include <type_traits>
#include <unordered_set>
#include <utility>
#include <vector>

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

#include "cmsys/RegularExpression.hxx"

#include "cmAlgorithms.h"
#include "cmEvaluatedTargetProperty.h"
#include "cmFileSet.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGlobalGenerator.h"
#include "cmLinkItem.h"
#include "cmList.h"
#include "cmListFileCache.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmSourceFile.h"
#include "cmSourceFileLocation.h"
#include "cmSourceGroup.h"
#include "cmStateTypes.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmValue.h"
#include "cmake.h"

namespace {
using UseTo = cmGeneratorTarget::UseTo;

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

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

void addFileSetEntry(cmGeneratorTarget const* headTarget,
                     std::string const& config,
                     cmGeneratorExpressionDAGChecker* dagChecker,
                     cmFileSet const* fileSet,
                     EvaluatedTargetPropertyEntries& entries)
{
  auto dirCges = fileSet->CompileDirectoryEntries();
  auto dirs = fileSet->EvaluateDirectoryEntries(
    dirCges, headTarget->GetLocalGenerator(), config, headTarget, dagChecker);
  bool contextSensitiveDirs = false;
  for (auto const& dirCge : dirCges) {
    if (dirCge->GetHadContextSensitiveCondition()) {
      contextSensitiveDirs = true;
      break;
    }
  }
  cmake* cm = headTarget->GetLocalGenerator()->GetCMakeInstance();
  for (auto& entryCge : fileSet->CompileFileEntries()) {
    auto tpe = cmGeneratorTarget::TargetPropertyEntry::CreateFileSet(
      dirs, contextSensitiveDirs, std::move(entryCge), fileSet);
    entries.Entries.emplace_back(
      EvaluateTargetPropertyEntry(headTarget, config, "", dagChecker, *tpe));
    EvaluatedTargetPropertyEntry const& entry = entries.Entries.back();
    for (auto const& file : entry.Values) {
      auto* sf = headTarget->Makefile->GetOrCreateSource(file);
      if (fileSet->GetType() == "HEADERS"_s) {
        sf->SetProperty("HEADER_FILE_ONLY", "TRUE");
      }

#ifndef CMAKE_BOOTSTRAP
      std::string e;
      std::string w;
      auto path = sf->ResolveFullPath(&e, &w);
      if (!w.empty()) {
        cm->IssueMessage(MessageType::AUTHOR_WARNING, w, entry.Backtrace);
      }
      if (path.empty()) {
        if (!e.empty()) {
          cm->IssueMessage(MessageType::FATAL_ERROR, e, entry.Backtrace);
        }
        return;
      }
      bool found = false;
      for (auto const& sg : headTarget->Makefile->GetSourceGroups()) {
        if (sg.MatchChildrenFiles(path)) {
          found = true;
          break;
        }
      }
      if (!found) {
        if (fileSet->GetType() == "HEADERS"_s) {
          headTarget->Makefile->GetOrCreateSourceGroup("Header Files")
            ->AddGroupFile(path);
        }
      }
#endif
    }
  }
}

void AddFileSetEntries(cmGeneratorTarget const* headTarget,
                       std::string const& config,
                       cmGeneratorExpressionDAGChecker* dagChecker,
                       EvaluatedTargetPropertyEntries& entries)
{
  for (auto const& entry : headTarget->Target->GetHeaderSetsEntries()) {
    for (auto const& name : cmList{ entry.Value }) {
      auto const* headerSet = headTarget->Target->GetFileSet(name);
      addFileSetEntry(headTarget, config, dagChecker, headerSet, entries);
    }
  }
  for (auto const& entry : headTarget->Target->GetCxxModuleSetsEntries()) {
    for (auto const& name : cmList{ entry.Value }) {
      auto const* cxxModuleSet = headTarget->Target->GetFileSet(name);
      addFileSetEntry(headTarget, config, dagChecker, cxxModuleSet, entries);
    }
  }
}

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

  bool contextDependent = entries.HadContextSensitiveCondition;

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

    cmLinkImplItem const& item = entry.LinkImplItem;
    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);
      cmake* cm = tgt->GetLocalGenerator()->GetCMakeInstance();
      if (!w.empty()) {
        cm->IssueMessage(MessageType::AUTHOR_WARNING, w, entry.Backtrace);
      }
      if (fullPath.empty()) {
        if (!e.empty()) {
          cm->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;
    }
    std::string usedSources;
    for (std::string const& src : entry.Values) {
      if (uniqueSrcs.insert(src).second) {
        srcs.emplace_back(src, entry.Backtrace);
        if (debugSources) {
          usedSources += " * " + src + "\n";
        }
      }
    }
    if (!usedSources.empty()) {
      tgt->GetLocalGenerator()->GetCMakeInstance()->IssueMessage(
        MessageType::LOG,
        std::string("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;

  cmGeneratorExpressionDAGChecker dagChecker{
    this, "SOURCES", nullptr, nullptr, this->LocalGenerator, config,
  };

  EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries(
    this, config, std::string(), &dagChecker, this->SourceEntries);

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

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

  // Collect TARGET_OBJECTS of direct object link-dependencies.
  bool contextDependentObjects = false;
  if (this->GetType() != cmStateEnums::OBJECT_LIBRARY) {
    EvaluatedTargetPropertyEntries linkObjectsEntries;
    AddObjectEntries(this, config, &dagChecker, linkObjectsEntries);
    contextDependentObjects = processSources(this, 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.
  EvaluatedTargetPropertyEntries fileSetEntries;
  AddFileSetEntries(this, config, &dagChecker, fileSetEntries);
  bool contextDependentFileSets =
    processSources(this, fileSetEntries, files, uniqueSrcs, debugSources);

  // Determine if sources are context-dependent or not.
  if (!contextDependentDirectSources && !contextDependentInterfaceSources &&
      !contextDependentObjects && !contextDependentFileSets) {
    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;

  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());
    cmFileSet const* fs = this->GetFileSetForSource(config, sf);
    if (sf->GetCustomCommand()) {
      kind = SourceKindCustomCommand;
    } else if (!this->Target->IsNormal() && !this->Target->IsImported() &&
               fs && (fs->GetType() == "CXX_MODULES"_s)) {
      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()) {
      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;
}

std::set<std::string> cmGeneratorTarget::GetAllConfigCompileLanguages() 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);
    }
  }
  return languages;
}
