summaryrefslogtreecommitdiff
path: root/Source/cmMakefileUtilityTargetGenerator.cxx
blob: 7f854ee6e640defcb7ad7c20a8f562375ab45b5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmMakefileUtilityTargetGenerator.h"

#include <ostream>
#include <string>
#include <utility>
#include <vector>

#include <cm/memory>

#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmOSXBundleGenerator.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"

cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator(
  cmGeneratorTarget* target)
  : cmMakefileTargetGenerator(target)
{
  this->CustomCommandDriver = OnUtility;
  this->OSXBundleGenerator = cm::make_unique<cmOSXBundleGenerator>(target);
  this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
}

cmMakefileUtilityTargetGenerator::~cmMakefileUtilityTargetGenerator() =
  default;

void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
{
  this->CreateRuleFile();

  *this->BuildFileStream << "# Utility rule file for "
                         << this->GeneratorTarget->GetName() << ".\n\n";

  const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")
                        ? "$(CMAKE_BINARY_DIR)/"
                        : "");

  // Include the dependencies for the target.
  std::string dependFile =
    cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make");
  *this->BuildFileStream
    << "# Include any custom commands dependencies for this target.\n"
    << this->GlobalGenerator->IncludeDirective << " " << root
    << cmSystemTools::ConvertToOutputPath(
         this->LocalGenerator->MaybeRelativeToTopBinDir(dependFile))
    << "\n\n";
  if (!cmSystemTools::FileExists(dependFile)) {
    // Write an empty dependency file.
    cmGeneratedFileStream depFileStream(
      dependFile, false, this->GlobalGenerator->GetMakefileEncoding());
    depFileStream << "# Empty custom commands generated dependencies file for "
                  << this->GeneratorTarget->GetName() << ".\n"
                  << "# This may be replaced when dependencies are built.\n";
  }

  std::string dependTimestamp =
    cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts");
  if (!cmSystemTools::FileExists(dependTimestamp)) {
    // Write a dependency timestamp file.
    cmGeneratedFileStream depFileStream(
      dependTimestamp, false, this->GlobalGenerator->GetMakefileEncoding());
    depFileStream << "# CMAKE generated file: DO NOT EDIT!\n"
                  << "# Timestamp file for custom commands dependencies "
                     "management for "
                  << this->GeneratorTarget->GetName() << ".\n";
  }

  if (!this->NoRuleMessages) {
    // Include the progress variables for the target.
    *this->BuildFileStream
      << "# Include the progress variables for this target.\n"
      << this->GlobalGenerator->IncludeDirective << " " << root
      << cmSystemTools::ConvertToOutputPath(
           this->LocalGenerator->MaybeRelativeToTopBinDir(
             this->ProgressFileNameFull))
      << "\n\n";
  }

  // write the custom commands for this target
  this->WriteTargetBuildRules();

  // Collect the commands and dependencies.
  std::vector<std::string> commands;
  std::vector<std::string> depends;

  // Utility targets store their rules in pre- and post-build commands.
  this->LocalGenerator->AppendCustomDepends(
    depends, this->GeneratorTarget->GetPreBuildCommands());

  this->LocalGenerator->AppendCustomDepends(
    depends, this->GeneratorTarget->GetPostBuildCommands());

  this->LocalGenerator->AppendCustomCommands(
    commands, this->GeneratorTarget->GetPreBuildCommands(),
    this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());

  // Depend on all custom command outputs for sources
  this->DriveCustomCommands(depends);

  this->LocalGenerator->AppendCustomCommands(
    commands, this->GeneratorTarget->GetPostBuildCommands(),
    this->GeneratorTarget, this->LocalGenerator->GetBinaryDirectory());

  // Add dependencies on targets that must be built first.
  this->AppendTargetDepends(depends);

  // Add a dependency on the rule file itself.
  this->LocalGenerator->AppendRuleDepend(depends,
                                         this->BuildFileNameFull.c_str());

  // If the rule is empty add the special empty rule dependency needed
  // by some make tools.
  if (depends.empty() && commands.empty()) {
    std::string hack = this->GlobalGenerator->GetEmptyRuleHackDepends();
    if (!hack.empty()) {
      depends.push_back(std::move(hack));
    }
  }

  // Write the rule.
  this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, nullptr,
                                      this->GeneratorTarget->GetName(),
                                      depends, commands, true);

  // Write the main driver rule to build everything in this target.
  this->WriteTargetDriverRule(this->GeneratorTarget->GetName(), false);

  // Write clean target
  this->WriteTargetCleanRules();

  // Write the dependency generation rule.  This must be done last so
  // that multiple output pair information is available.
  this->WriteTargetDependRules();

  // close the streams
  this->CloseFileStreams();
}