1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
3 #include "cmMakefileUtilityTargetGenerator.h"
12 #include "cmGeneratedFileStream.h"
13 #include "cmGeneratorTarget.h"
14 #include "cmGlobalUnixMakefileGenerator3.h"
15 #include "cmLocalUnixMakefileGenerator3.h"
16 #include "cmMakefile.h"
17 #include "cmOSXBundleGenerator.h"
18 #include "cmStringAlgorithms.h"
19 #include "cmSystemTools.h"
21 cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator(
22 cmGeneratorTarget
* target
)
23 : cmMakefileTargetGenerator(target
)
25 this->CustomCommandDriver
= OnUtility
;
26 this->OSXBundleGenerator
= cm::make_unique
<cmOSXBundleGenerator
>(target
);
27 this->OSXBundleGenerator
->SetMacContentFolders(&this->MacContentFolders
);
30 cmMakefileUtilityTargetGenerator::~cmMakefileUtilityTargetGenerator() =
33 void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
35 this->CreateRuleFile();
37 *this->BuildFileStream
<< "# Utility rule file for "
38 << this->GeneratorTarget
->GetName() << ".\n\n";
40 const char* root
= (this->Makefile
->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")
41 ? "$(CMAKE_BINARY_DIR)/"
44 // Include the dependencies for the target.
45 std::string dependFile
=
46 cmStrCat(this->TargetBuildDirectoryFull
, "/compiler_depend.make");
47 *this->BuildFileStream
48 << "# Include any custom commands dependencies for this target.\n"
49 << this->GlobalGenerator
->IncludeDirective
<< " " << root
50 << cmSystemTools::ConvertToOutputPath(
51 this->LocalGenerator
->MaybeRelativeToTopBinDir(dependFile
))
53 if (!cmSystemTools::FileExists(dependFile
)) {
54 // Write an empty dependency file.
55 cmGeneratedFileStream
depFileStream(
56 dependFile
, false, this->GlobalGenerator
->GetMakefileEncoding());
57 depFileStream
<< "# Empty custom commands generated dependencies file for "
58 << this->GeneratorTarget
->GetName() << ".\n"
59 << "# This may be replaced when dependencies are built.\n";
62 std::string dependTimestamp
=
63 cmStrCat(this->TargetBuildDirectoryFull
, "/compiler_depend.ts");
64 if (!cmSystemTools::FileExists(dependTimestamp
)) {
65 // Write a dependency timestamp file.
66 cmGeneratedFileStream
depFileStream(
67 dependTimestamp
, false, this->GlobalGenerator
->GetMakefileEncoding());
68 depFileStream
<< "# CMAKE generated file: DO NOT EDIT!\n"
69 << "# Timestamp file for custom commands dependencies "
71 << this->GeneratorTarget
->GetName() << ".\n";
74 if (!this->NoRuleMessages
) {
75 // Include the progress variables for the target.
76 *this->BuildFileStream
77 << "# Include the progress variables for this target.\n"
78 << this->GlobalGenerator
->IncludeDirective
<< " " << root
79 << cmSystemTools::ConvertToOutputPath(
80 this->LocalGenerator
->MaybeRelativeToTopBinDir(
81 this->ProgressFileNameFull
))
85 // write the custom commands for this target
86 this->WriteTargetBuildRules();
88 // Collect the commands and dependencies.
89 std::vector
<std::string
> commands
;
90 std::vector
<std::string
> depends
;
92 // Utility targets store their rules in pre- and post-build commands.
93 this->LocalGenerator
->AppendCustomDepends(
94 depends
, this->GeneratorTarget
->GetPreBuildCommands());
96 this->LocalGenerator
->AppendCustomDepends(
97 depends
, this->GeneratorTarget
->GetPostBuildCommands());
99 this->LocalGenerator
->AppendCustomCommands(
100 commands
, this->GeneratorTarget
->GetPreBuildCommands(),
101 this->GeneratorTarget
, this->LocalGenerator
->GetBinaryDirectory());
103 // Depend on all custom command outputs for sources
104 this->DriveCustomCommands(depends
);
106 this->LocalGenerator
->AppendCustomCommands(
107 commands
, this->GeneratorTarget
->GetPostBuildCommands(),
108 this->GeneratorTarget
, this->LocalGenerator
->GetBinaryDirectory());
110 // Add dependencies on targets that must be built first.
111 this->AppendTargetDepends(depends
);
113 // Add a dependency on the rule file itself.
114 this->LocalGenerator
->AppendRuleDepend(depends
,
115 this->BuildFileNameFull
.c_str());
117 // If the rule is empty add the special empty rule dependency needed
118 // by some make tools.
119 if (depends
.empty() && commands
.empty()) {
120 std::string hack
= this->GlobalGenerator
->GetEmptyRuleHackDepends();
122 depends
.push_back(std::move(hack
));
127 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, nullptr,
128 this->GeneratorTarget
->GetName(),
129 depends
, commands
, true);
131 // Write the main driver rule to build everything in this target.
132 this->WriteTargetDriverRule(this->GeneratorTarget
->GetName(), false);
134 // Write clean target
135 this->WriteTargetCleanRules();
137 // Write the dependency generation rule. This must be done last so
138 // that multiple output pair information is available.
139 this->WriteTargetDependRules();
142 this->CloseFileStreams();