Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmFastbuildUtilityTargetGenerator.cxx
Line
Count
Source
1
/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2
   file LICENSE.rst or https://cmake.org/licensing for details.  */
3
4
#include "cmFastbuildUtilityTargetGenerator.h"
5
6
#include <set>
7
#include <string>
8
#include <utility>
9
#include <vector>
10
11
#include <cm/memory>
12
13
#include "cmFastbuildTargetGenerator.h"
14
#include "cmGeneratorTarget.h"
15
#include "cmGlobalFastbuildGenerator.h"
16
#include "cmListFileCache.h"
17
#include "cmMakefile.h"
18
#include "cmStateTypes.h"
19
#include "cmStringAlgorithms.h"
20
#include "cmTarget.h"
21
#include "cmTargetDepend.h"
22
23
cmFastbuildUtilityTargetGenerator::cmFastbuildUtilityTargetGenerator(
24
  cmGeneratorTarget* gt, std::string configParam)
25
0
  : cmFastbuildTargetGenerator(gt, std::move(configParam))
26
0
{
27
0
}
28
29
void cmFastbuildUtilityTargetGenerator::Generate()
30
0
{
31
0
  std::string targetName = GeneratorTarget->GetName();
32
33
0
  if (this->GeneratorTarget->GetType() == cmStateEnums::GLOBAL_TARGET) {
34
0
    targetName = GetGlobalGenerator()->GetTargetName(GeneratorTarget);
35
0
  }
36
37
0
  FastbuildAliasNode fastbuildTarget;
38
0
  auto const addUtilDepToTarget = [&fastbuildTarget](std::string depName) {
39
0
    FastbuildTargetDep dep{ depName };
40
0
    dep.Type = FastbuildTargetDepType::UTIL;
41
0
    fastbuildTarget.PreBuildDependencies.emplace(std::move(dep));
42
0
  };
43
44
0
  fastbuildTarget.Name = targetName;
45
0
  fastbuildTarget.BaseName = targetName;
46
47
0
  LogMessage("<-------------->");
48
0
  LogMessage("Generate Utility target: " + targetName);
49
0
  LogMessage("Config: " + Config);
50
0
  for (auto const& dep : TargetDirectDependencies) {
51
0
    LogMessage("Dep: " + dep->GetName());
52
0
  }
53
54
0
  std::vector<std::string> nonImportedUtils;
55
0
  for (BT<std::pair<std::string, bool>> const& util :
56
0
       this->GeneratorTarget->GetUtilities()) {
57
0
    if (util.Value.first == targetName) {
58
0
      continue;
59
0
    }
60
0
    auto const& utilTargetName =
61
0
      this->ConvertToFastbuildPath(util.Value.first);
62
0
    LogMessage("Util: " + utilTargetName);
63
0
    auto* const target = this->Makefile->FindTargetToUse(utilTargetName);
64
0
    if (target && target->IsImported()) {
65
0
      LogMessage("Skipping imported util target: " + utilTargetName);
66
0
      continue;
67
0
    }
68
    // Since interface target don't appear in the generated build files,
69
    // transitively propagate their deps (if any).
70
    // Tested in "ExternalProjectSubdir" test.
71
0
    if (target && target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
72
0
      for (auto const& dep : target->GetUtilities()) {
73
0
        auto const& depName = this->ConvertToFastbuildPath(dep.Value.first);
74
0
        LogMessage("Transitively propagating iface dep: " + depName +
75
0
                   ", is cross: " + std::to_string(dep.Value.second));
76
0
        nonImportedUtils.emplace_back(depName);
77
0
        addUtilDepToTarget(this->ConvertToFastbuildPath(depName));
78
0
      }
79
0
    } else {
80
0
      nonImportedUtils.emplace_back(utilTargetName);
81
0
      addUtilDepToTarget(utilTargetName);
82
0
    }
83
0
  }
84
0
  if (this->GetGlobalGenerator()->IsExcluded(this->GetGeneratorTarget())) {
85
0
    LogMessage(cmStrCat("Excluding ", targetName, " from ALL"));
86
0
    fastbuildTarget.ExcludeFromAll = true;
87
0
  }
88
0
  auto preBuild = GenerateCommands(FastbuildBuildStep::PRE_BUILD);
89
90
  // Tested in "RunCMake.CPack*" tests.
91
  // Utility target "package" has packaging steps as "POST_BUILD".
92
0
  for (auto& exec : GenerateCommands(FastbuildBuildStep::POST_BUILD).Nodes) {
93
0
    addUtilDepToTarget(exec.Name);
94
0
    for (std::string const& util : nonImportedUtils) {
95
0
      LogMessage("Adding: util " + util);
96
0
      exec.PreBuildDependencies.emplace(util);
97
0
    }
98
    // So POST_BUILD is executed AFTER PRE_BUILD (tested in "CustomCommand"
99
    // test).
100
0
    for (auto const& pre : preBuild.Nodes) {
101
0
      LogMessage("Adding: " + pre.Name);
102
0
      exec.PreBuildDependencies.emplace(pre.Name);
103
0
    }
104
0
    this->GetGlobalGenerator()->AddTarget(std::move(exec));
105
0
  }
106
107
0
  for (auto& exec : preBuild.Nodes) {
108
0
    LogMessage("Adding exec " + exec.Name);
109
0
    addUtilDepToTarget(exec.Name);
110
0
    this->GetGlobalGenerator()->AddTarget(std::move(exec));
111
0
  }
112
113
0
  for (auto& exec : GenerateCommands(FastbuildBuildStep::REST).Nodes) {
114
0
    addUtilDepToTarget(exec.Name);
115
0
    for (auto const& dep : TargetDirectDependencies) {
116
0
      LogMessage("Direct dep " + dep->GetName() +
117
0
                 "-all propagating to CC: " + exec.Name);
118
      // All custom commands from within the target must be executed AFTER all
119
      // the target's deps.
120
0
      exec.PreBuildDependencies.emplace(dep->GetName());
121
0
    }
122
0
    this->GetGlobalGenerator()->AddTarget(std::move(exec));
123
0
  }
124
0
  if (fastbuildTarget.PreBuildDependencies.empty()) {
125
0
    if (fastbuildTarget.ExcludeFromAll) {
126
0
      return;
127
0
    }
128
0
    FastbuildTargetDep dep{ FASTBUILD_NOOP_FILE_NAME };
129
0
    dep.Type = FastbuildTargetDepType::ORDER_ONLY;
130
0
    fastbuildTarget.PreBuildDependencies.emplace(std::move(dep));
131
0
  }
132
0
  fastbuildTarget.Hidden = false;
133
0
  this->AdditionalCleanFiles();
134
135
0
  fastbuildTarget.BasePath = this->GetMakefile()->GetCurrentSourceDirectory();
136
0
  this->GetGlobalGenerator()->AddIDEProject(fastbuildTarget, Config);
137
138
0
  this->GetGlobalGenerator()->AddTarget(std::move(fastbuildTarget));
139
0
}