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 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file LICENSE.rst or https://cmake.org/licensing for details. */
#include "cmFastbuildUtilityTargetGenerator.h"
#include <set>
#include <string>
#include <utility>
#include <vector>
#include <cm/memory>
#include "cmFastbuildTargetGenerator.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalFastbuildGenerator.h"
#include "cmListFileCache.h"
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmTarget.h"
#include "cmTargetDepend.h"
cmFastbuildUtilityTargetGenerator::cmFastbuildUtilityTargetGenerator(
cmGeneratorTarget* gt, std::string configParam)
: cmFastbuildTargetGenerator(gt, std::move(configParam))
{
}
void cmFastbuildUtilityTargetGenerator::Generate()
{
if (!this->GetGeneratorTarget()->IsInBuildSystem()) {
return;
}
std::string targetName = GeneratorTarget->GetName();
if (this->GeneratorTarget->GetType() == cmStateEnums::GLOBAL_TARGET) {
targetName = GetGlobalGenerator()->GetTargetName(GeneratorTarget);
}
FastbuildAliasNode fastbuildTarget;
auto const addUtilDepToTarget = [&fastbuildTarget](std::string depName) {
FastbuildTargetDep dep{ depName };
dep.Type = FastbuildTargetDepType::UTIL;
fastbuildTarget.PreBuildDependencies.emplace(std::move(dep));
};
fastbuildTarget.Name = targetName;
fastbuildTarget.BaseName = targetName;
LogMessage("<-------------->");
LogMessage("Generate Utility target: " + targetName);
LogMessage("Config: " + Config);
for (auto const& dep : TargetDirectDependencies) {
LogMessage("Dep: " + dep->GetName());
}
std::vector<std::string> nonImportedUtils;
for (BT<std::pair<std::string, bool>> const& util :
this->GeneratorTarget->GetUtilities()) {
if (util.Value.first == targetName) {
continue;
}
auto const& utilTargetName =
this->ConvertToFastbuildPath(util.Value.first);
LogMessage("Util: " + utilTargetName);
auto* const target = this->Makefile->FindTargetToUse(utilTargetName);
if (target && target->IsImported()) {
LogMessage("Skipping imported util target: " + utilTargetName);
continue;
}
// Since interface target don't appear in the generated build files,
// transitively propagate their deps (if any).
// Tested in "ExternalProjectSubdir" test.
if (target && target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
for (auto const& dep : target->GetUtilities()) {
auto const& depName = this->ConvertToFastbuildPath(dep.Value.first);
LogMessage("Transitively propagating iface dep: " + depName +
", is cross: " + std::to_string(dep.Value.second));
nonImportedUtils.emplace_back(depName);
addUtilDepToTarget(this->ConvertToFastbuildPath(depName));
}
} else {
nonImportedUtils.emplace_back(utilTargetName);
addUtilDepToTarget(utilTargetName);
}
}
if (this->GetGlobalGenerator()->IsExcluded(this->GetGeneratorTarget())) {
LogMessage(cmStrCat("Excluding ", targetName, " from ALL"));
fastbuildTarget.ExcludeFromAll = true;
}
auto preBuild = GenerateCommands(FastbuildBuildStep::PRE_BUILD);
// Tested in "RunCMake.CPack*" tests.
// Utility target "package" has packaging steps as "POST_BUILD".
for (auto& exec : GenerateCommands(FastbuildBuildStep::POST_BUILD).Nodes) {
addUtilDepToTarget(exec.Name);
for (std::string const& util : nonImportedUtils) {
LogMessage("Adding: util " + util);
exec.PreBuildDependencies.emplace(util);
}
// So POST_BUILD is executed AFTER PRE_BUILD (tested in "CustomCommand"
// test).
for (auto const& pre : preBuild.Nodes) {
LogMessage("Adding: " + pre.Name);
exec.PreBuildDependencies.emplace(pre.Name);
}
this->GetGlobalGenerator()->AddTarget(std::move(exec));
}
for (auto& exec : preBuild.Nodes) {
LogMessage("Adding exec " + exec.Name);
addUtilDepToTarget(exec.Name);
this->GetGlobalGenerator()->AddTarget(std::move(exec));
}
for (auto& exec : GenerateCommands(FastbuildBuildStep::REST).Nodes) {
addUtilDepToTarget(exec.Name);
for (auto const& dep : TargetDirectDependencies) {
LogMessage("Direct dep " + dep->GetName() +
"-all propagating to CC: " + exec.Name);
// All custom commands from within the target must be executed AFTER all
// the target's deps.
exec.PreBuildDependencies.emplace(dep->GetName());
}
this->GetGlobalGenerator()->AddTarget(std::move(exec));
}
// The target has to be in the build system, but has no custom commands
// associated with it.
if (fastbuildTarget.PreBuildDependencies.empty()) {
std::vector<cmSourceFile*> sources;
this->GetGeneratorTarget()->GetSourceFiles(sources, this->Config);
if (sources.empty()) {
FastbuildTargetDep dep{ FASTBUILD_NOOP_FILE_NAME };
dep.Type = FastbuildTargetDepType::ORDER_ONLY;
fastbuildTarget.PreBuildDependencies.emplace(std::move(dep));
} else {
for (cmSourceFile const* source : sources) {
FastbuildTargetDep dep{
this->GetGlobalGenerator()->ConvertToFastbuildPath(
source->GetFullPath())
};
dep.Type = FastbuildTargetDepType::ARTIFACT;
fastbuildTarget.PreBuildDependencies.emplace(std::move(dep));
}
}
}
fastbuildTarget.Hidden = false;
this->AdditionalCleanFiles();
fastbuildTarget.BasePath = this->GetMakefile()->GetCurrentSourceDirectory();
if (this->GetGeneratorTarget()->GetType() != cmStateEnums::GLOBAL_TARGET) {
this->GetGlobalGenerator()->AddIDEProject(fastbuildTarget, Config);
}
this->GetGlobalGenerator()->AddTarget(std::move(fastbuildTarget));
}
|