| /* 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 "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<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() == 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<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() != cm::TargetType::GLOBAL_TARGET) { | |
| this->GetGlobalGenerator()->AddIDEProject(fastbuildTarget, Config); | |
| } | |
| this->GetGlobalGenerator()->AddTarget(std::move(fastbuildTarget)); | |
| } |