/* 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 #include #include #include #include #include "cmFastbuildTargetGenerator.h" #include "cmGeneratorTarget.h" #include "cmGlobalFastbuildGenerator.h" #include "cmListFileCache.h" #include "cmMakefile.h" #include "cmSourceFile.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" #include "cmTargetDepend.h" #include "cmTargetTypes.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() == cm::TargetType::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 nonImportedUtils; for (BT> 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() == cm::TargetType::INTERFACE_LIBRARY) { for (auto const& dep : target->GetUtilities()) { auto const& depName = this->ConvertToFastbuildPath(dep.Value.first); LogMessage(cmStrCat("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(cmStrCat("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 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() != cm::TargetType::GLOBAL_TARGET) { this->GetGlobalGenerator()->AddIDEProject(fastbuildTarget, Config); } this->GetGlobalGenerator()->AddTarget(std::move(fastbuildTarget)); }