mirror of
https://github.com/Kitware/CMake.git
synced 2025-06-09 07:20:19 +08:00

Most calls to `MaybeConvertToRelativePath` use one of our common work directories (e.g. top of the build tree) as the local path. Add helpers for each of the common cases to simplify and clarify call sites.
144 lines
5.2 KiB
C++
144 lines
5.2 KiB
C++
/* 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();
|
|
}
|