/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file LICENSE.rst or https://cmake.org/licensing for details.  */
#pragma once

#include "cmConfigure.h" // IWYU pragma: keep

#include <cstddef>
#include <iosfwd>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>

#include "cmBuildOptions.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalCommonGenerator.h"
#include "cmGlobalGeneratorFactory.h"
#include "cmStateSnapshot.h"

class cmGeneratedFileStream;
class cmLocalGenerator;
class cmLocalUnixMakefileGenerator3;
class cmMakefileTargetGenerator;
class cmake;

/** \class cmGlobalUnixMakefileGenerator3
 * \brief Write a Unix makefiles.
 *
 * cmGlobalUnixMakefileGenerator3 manages UNIX build process for a tree


 The basic approach of this generator is to produce Makefiles that will all
 be run with the current working directory set to the Home Output
 directory. The one exception to this is the subdirectory Makefiles which are
 created as a convenience and just cd up to the Home Output directory and
 invoke the main Makefiles.

 The make process starts with Makefile. Makefile should only contain the
 targets the user is likely to invoke directly from a make command line. No
 internal targets should be in this file. Makefile2 contains the internal
 targets that are required to make the process work.

 Makefile2 in turn will recursively make targets in the correct order. Each
 target has its own directory \<target\>.dir and its own makefile build.make in
 that directory. Also in that directory is a couple makefiles per source file
 used by the target. Typically these are named source.obj.build.make and
 source.obj.build.depend.make. The source.obj.build.make contains the rules
 for building, cleaning, and computing dependencies for the given source
 file. The build.depend.make contains additional dependencies that were
 computed during dependency scanning. An additional file called
 source.obj.depend is used as a marker to indicate when dependencies must be
 rescanned.

 Rules for custom commands follow the same model as rules for source files.

 */

class cmGlobalUnixMakefileGenerator3 : public cmGlobalCommonGenerator
{
public:
  cmGlobalUnixMakefileGenerator3(cmake* cm);
  static std::unique_ptr<cmGlobalGeneratorFactory> NewFactory()
  {
    return std::unique_ptr<cmGlobalGeneratorFactory>(
      new cmGlobalGeneratorSimpleFactory<cmGlobalUnixMakefileGenerator3>());
  }

  ~cmGlobalUnixMakefileGenerator3() override;

  cmGlobalUnixMakefileGenerator3(cmGlobalUnixMakefileGenerator3 const&) =
    delete;
  cmGlobalUnixMakefileGenerator3& operator=(
    cmGlobalUnixMakefileGenerator3 const&) = delete;

  //! Get the name for the generator.
  std::string GetName() const override
  {
    return cmGlobalUnixMakefileGenerator3::GetActualName();
  }
  static std::string GetActualName() { return "Unix Makefiles"; }

  /**
   * Utilized by the generator factory to determine if this generator
   * supports toolsets.
   */
  static bool SupportsToolset() { return false; }

  /**
   * Utilized by the generator factory to determine if this generator
   * supports platforms.
   */
  static bool SupportsPlatform() { return false; }

  /**
   * Utilized to determine if this generator
   * supports DEPFILE option.
   */
  bool SupportsCustomCommandDepfile() const override { return true; }

  /**
   * Utilized to determine if this generator
   * supports linker dependency file.
   */
  bool SupportsLinkerDependencyFile() const override { return true; }

  /** Get the documentation entry for this generator.  */
  static cmDocumentationEntry GetDocumentation();

  std::unique_ptr<cmLocalGenerator> CreateLocalGenerator(
    cmMakefile* mf) override;

  /**
   * Try to determine system information such as shared library
   * extension, pthreads, byte order etc.
   */
  void EnableLanguage(std::vector<std::string> const& languages, cmMakefile*,
                      bool optional) override;

  void Configure() override;

  bool IsGNUMakeJobServerAware() const override { return true; }

  /**
   * Utilized to determine if the make tool matches target names
   * case-insensitively, so that generated target names may not differ
   * only in case.
   */
  virtual bool TargetNamesAreCaseInsensitive() const { return false; }

  /**
   * Generate the all required files for building this project/tree. This
   * basically creates a series of LocalGenerators for each directory and
   * requests that they Generate.
   */
  void Generate() override;

  void WriteMainCMakefileLanguageRules(
    cmGeneratedFileStream& cmakefileStream,
    std::vector<std::unique_ptr<cmLocalGenerator>>&);

  // write out the help rule listing the valid targets
  void WriteHelpRule(std::ostream& ruleFileStream,
                     cmLocalUnixMakefileGenerator3*);

  // write the top level target rules
  void WriteConvenienceRules(std::ostream& ruleFileStream,
                             std::set<std::string>& emitted);

  // Make tool supports dependency files generated by compiler
  bool SupportsCompilerDependencies() const
  {
    return this->ToolSupportsCompilerDependencies;
  }

  // Make tool supports long line dependencies
  bool SupportsLongLineDependencies() const
  {
    return this->ToolSupportsLongLineDependencies;
  }

  /** Get the command to use for a target that has no rule.  This is
      used for multiple output dependencies and for cmake_force.  */
  std::string GetEmptyRuleHackCommand() { return this->EmptyRuleHackCommand; }

  /** Get the fake dependency to use when a rule has no real commands
      or dependencies.  */
  std::string GetEmptyRuleHackDepends() { return this->EmptyRuleHackDepends; }

  /**
   * Convert a file path to a Makefile target or dependency with
   * escaping and quoting suitable for the generator's make tool.
   */
  std::string ConvertToMakefilePath(std::string const& path) const;

  // change the build command for speed
  std::vector<GeneratedMakeCommand> GenerateBuildCommand(
    std::string const& makeProgram, std::string const& projectName,
    std::string const& projectDir, std::vector<std::string> const& targetNames,
    std::string const& config, int jobs, bool verbose,
    cmBuildOptions buildOptions = cmBuildOptions(),
    std::vector<std::string> const& makeOptions = std::vector<std::string>(),
    BuildTryCompile isInTryCompile = BuildTryCompile::No) override;

  /** Record per-target progress information.  */
  void RecordTargetProgress(cmMakefileTargetGenerator* tg);

  void AddCXXCompileCommand(std::string const& sourceFile,
                            std::string const& workingDirectory,
                            std::string const& compileCommand,
                            std::string const& objPath);

  /** Does the make tool tolerate .NOTPARALLEL? */
  virtual bool AllowNotParallel() const { return true; }

  /** Does the make tool tolerate .DELETE_ON_ERROR? */
  virtual bool AllowDeleteOnError() const { return true; }

  /** Does the make tool interpret '\#' as '#'?  */
  virtual bool CanEscapeOctothorpe() const;

  bool IsIPOSupported() const override { return true; }

  bool IsInstallPrepComponentRepresentable(
    std::string const& component) const override;

  bool SupportsShortObjectNames() const override;
  void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const override;

  std::string IncludeDirective;
  std::string LineContinueDirective;
  bool DefineWindowsNULL;
  bool PassMakeflags;
  bool UnixCD;

protected:
  void WriteMainMakefile2();
  void WriteMainCMakefile();

  void WriteConvenienceRules2(std::ostream& ruleFileStream,
                              cmLocalUnixMakefileGenerator3& rootLG,
                              cmLocalUnixMakefileGenerator3& lg);

  void WriteDirectoryRule2(std::ostream& ruleFileStream,
                           cmLocalUnixMakefileGenerator3& rootLG,
                           DirectoryTarget const& dt, char const* pass,
                           bool check_all, bool check_relink,
                           std::vector<std::string> const& commands = {});
  void WriteDirectoryRules2(std::ostream& ruleFileStream,
                            cmLocalUnixMakefileGenerator3& rootLG,
                            DirectoryTarget const& dt);

  void AppendGlobalTargetDepends(std::vector<std::string>& depends,
                                 cmGeneratorTarget* target);

  void AppendCodegenTargetDepends(std::vector<std::string>& depends,
                                  cmGeneratorTarget* target);

  // Compute the "test_prep/<name>" build targets.  Each test's dependencies
  // are resolved to the build-system targets that produce them so that the
  // recursive Makefile graph can build them.
  void ComputeTestPrepTargets();

  // Write the internal "test_prep/<name>" and "test_prep/all" rules into
  // CMakeFiles/Makefile2.
  void WriteTestPrepRules(std::ostream& makefileStream,
                          cmLocalUnixMakefileGenerator3& rootLG);

  // Write the top-level "test_prep/<name>" convenience rules that forward
  // into CMakeFiles/Makefile2.
  void WriteTestPrepConvenienceRules(std::ostream& ruleFileStream);

  // Compute the "install_prep/<component>" build targets. Each installation
  // component's dependencies are resolved to the build-system targets that
  // produce them so that the recursive Makefile graph can build them.
  void ComputeInstallPrepTargets();

  // Write the internal "install_prep/<component>" and "install_prep/all" rules
  // into CMakeFiles/Makefile2.
  void WriteInstallPrepRules(std::ostream& makefileStream,
                             cmLocalUnixMakefileGenerator3& rootLG);

  // Write the top-level "install_prep/<component>" convenience rules that
  // forward into CMakeFiles/Makefile2.
  void WriteInstallPrepConvenienceRules(std::ostream& ruleFileStream);

  // Target name hooks for superclass.
  char const* GetAllTargetName() const override { return "all"; }
  char const* GetInstallTargetName() const override { return "install"; }
  char const* GetInstallLocalTargetName() const override
  {
    return "install/local";
  }
  char const* GetInstallStripTargetName() const override
  {
    return "install/strip";
  }
  char const* GetPreinstallTargetName() const override { return "preinstall"; }
  char const* GetTestTargetName() const override { return "test"; }
  char const* GetPackageTargetName() const override { return "package"; }
  char const* GetPackageSourceTargetName() const override
  {
    return "package_source";
  }
  char const* GetRebuildCacheTargetName() const override
  {
    return "rebuild_cache";
  }
  char const* GetCleanTargetName() const override { return "clean"; }

  bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const override { return true; }

  // Specify if the make tool is able to consume dependency files
  // generated by the compiler
  bool ToolSupportsCompilerDependencies = true;

  // some Make generator, such as Borland not support long line dependencies,
  // we add SupportsLongLineDependencies to predicate.
  bool ToolSupportsLongLineDependencies = true;

  // Some make programs (Borland) do not keep a rule if there are no
  // dependencies or commands.  This is a problem for creating rules
  // that might not do anything but might have other dependencies
  // added later.  If non-empty this variable holds a fake dependency
  // that can be added.
  std::string EmptyRuleHackDepends;

  // Some make programs (Watcom) do not like rules with no commands.
  // If non-empty this variable holds a bogus command that may be put
  // in the rule to satisfy the make program.
  std::string EmptyRuleHackCommand;

  // Store per-target progress counters.
  struct TargetProgress
  {
    unsigned long NumberOfActions = 0;
    std::string VariableFile;
    std::vector<unsigned long> Marks;
    void WriteProgressVariables(unsigned long total, unsigned long& current);
  };
  using ProgressMapType = std::map<cmGeneratorTarget const*, TargetProgress,
                                   cmGeneratorTarget::StrictTargetComparison>;
  ProgressMapType ProgressMap;

  size_t CountProgressMarksInTarget(
    cmGeneratorTarget const* target,
    std::set<cmGeneratorTarget const*>& emitted);
  size_t CountProgressMarksInAll(cmLocalGenerator const& lg);

  std::unique_ptr<cmGeneratedFileStream> CommandDatabase;

private:
  char const* GetBuildIgnoreErrorsFlag() const override { return "-i"; }

  // Probe the make tool (once, memoized) for whether it is GNU Make 4.0 or
  // newer and thus supports grouped output via --output-sync.
  bool MakeSupportsOutputSync(std::string const& makeProgram);

  enum class OutputSyncSupport
  {
    Unknown,
    Yes,
    No
  };
  OutputSyncSupport OutputSyncSupportState = OutputSyncSupport::Unknown;

  std::map<cmStateSnapshot, std::set<cmGeneratorTarget const*>,
           cmStateSnapshot::StrictWeakOrder>
    DirectoryTargetsMap;
  void InitializeProgressMarks() override;

  // A "test_prep/<name>" target and the "<target>.dir/all" recursive rules
  // that must be built to prepare the named test.
  struct TestPrepTarget
  {
    std::string Name;
    std::vector<std::string> Rules;
  };

  // Ordered map of "test_prep/" target name -> its rules.  Populated by
  // ComputeTestPrepTargets when test preparation targets are enabled.
  std::map<std::string, TestPrepTarget> TestPrepTargets;
  TestPrepTarget& GetTestPrepTarget(std::string const& name);
  void AddDirectoryTestPrepTargets(cmLocalGenerator* lg);
  bool TestPrepEnabled = false;

  // An "install_prep/<component>" target and the "<target>.dir/all"
  // recursive rules that must be built to prepare the named installation
  // component.
  struct InstallPrepTarget
  {
    std::string Name;
    std::vector<std::string> Rules;
  };

  // Ordered map of "install_prep/" target name -> its rules.  Populated by
  // ComputeInstallPrepTargets.
  std::map<std::string, InstallPrepTarget> InstallPrepComponentTargets;
  std::vector<std::string> InstallPrepAllTargets;

  struct InstallPrepOrderedTarget
  {
    std::string NormalRule;
    std::string PreinstallRule;
  };
  std::map<std::string, InstallPrepOrderedTarget> InstallPrepOrderedTargets;

  bool InstallPrepEnabled = false;
};
