Coverage Report

Created: 2026-03-12 06:35

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 "cmSourceFile.h"
19
#include "cmStateTypes.h"
20
#include "cmStringAlgorithms.h"
21
#include "cmTarget.h"
22
#include "cmTargetDepend.h"
23
24
cmFastbuildUtilityTargetGenerator::cmFastbuildUtilityTargetGenerator(
25
  cmGeneratorTarget* gt, std::string configParam)
26
0
  : cmFastbuildTargetGenerator(gt, std::move(configParam))
27
0
{
28
0
}
29
30
void cmFastbuildUtilityTargetGenerator::Generate()
31
0
{
32
0
  if (!this->GetGeneratorTarget()->IsInBuildSystem()) {
33
0
    return;
34
0
  }
35
0
  std::string targetName = GeneratorTarget->GetName();
36
37
0
  if (this->GeneratorTarget->GetType() == cmStateEnums::GLOBAL_TARGET) {
38
0
    targetName = GetGlobalGenerator()->GetTargetName(GeneratorTarget);
39
0
  }
40
41
0
  FastbuildAliasNode fastbuildTarget;
42
0
  auto const addUtilDepToTarget = [&fastbuildTarget](std::string depName) {
43
0
    FastbuildTargetDep dep{ depName };
44
0
    dep.Type = FastbuildTargetDepType::UTIL;
45
0
    fastbuildTarget.PreBuildDependencies.emplace(std::move(dep));
46
0
  };
47
48
0
  fastbuildTarget.Name = targetName;
49
0
  fastbuildTarget.BaseName = targetName;
50
51
0
  LogMessage("<-------------->");
52
0
  LogMessage("Generate Utility target: " + targetName);
53
0
  LogMessage("Config: " + Config);
54
0
  for (auto const& dep : TargetDirectDependencies) {
55
0
    LogMessage("Dep: " + dep->GetName());
56
0
  }
57
58
0
  std::vector<std::string> nonImportedUtils;
59
0
  for (BT<std::pair<std::string, bool>> const& util :
60
0
       this->GeneratorTarget->GetUtilities()) {
61
0
    if (util.Value.first == targetName) {
62
0
      continue;
63
0
    }
64
0
    auto const& utilTargetName =
65
0
      this->ConvertToFastbuildPath(util.Value.first);
66
0
    LogMessage("Util: " + utilTargetName);
67
0
    auto* const target = this->Makefile->FindTargetToUse(utilTargetName);
68
0
    if (target && target->IsImported()) {
69
0
      LogMessage("Skipping imported util target: " + utilTargetName);
70
0
      continue;
71
0
    }
72
    // Since interface target don't appear in the generated build files,
73
    // transitively propagate their deps (if any).
74
    // Tested in "ExternalProjectSubdir" test.
75
0
    if (target && target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
76
0
      for (auto const& dep : target->GetUtilities()) {
77
0
        auto const& depName = this->ConvertToFastbuildPath(dep.Value.first);
78
0
        LogMessage("Transitively propagating iface dep: " + depName +
79
0
                   ", is cross: " + std::to_string(dep.Value.second));
80
0
        nonImportedUtils.emplace_back(depName);
81
0
        addUtilDepToTarget(this->ConvertToFastbuildPath(depName));
82
0
      }
83
0
    } else {
84
0
      nonImportedUtils.emplace_back(utilTargetName);
85
0
      addUtilDepToTarget(utilTargetName);
86
0
    }
87
0
  }
88
0
  if (this->GetGlobalGenerator()->IsExcluded(this->GetGeneratorTarget())) {
89
0
    LogMessage(cmStrCat("Excluding ", targetName, " from ALL"));
90
0
    fastbuildTarget.ExcludeFromAll = true;
91
0
  }
92
0
  auto preBuild = GenerateCommands(FastbuildBuildStep::PRE_BUILD);
93
94
  // Tested in "RunCMake.CPack*" tests.
95
  // Utility target "package" has packaging steps as "POST_BUILD".
96
0
  for (auto& exec : GenerateCommands(FastbuildBuildStep::POST_BUILD).Nodes) {
97
0
    addUtilDepToTarget(exec.Name);
98
0
    for (std::string const& util : nonImportedUtils) {
99
0
      LogMessage("Adding: util " + util);
100
0
      exec.PreBuildDependencies.emplace(util);
101
0
    }
102
    // So POST_BUILD is executed AFTER PRE_BUILD (tested in "CustomCommand"
103
    // test).
104
0
    for (auto const& pre : preBuild.Nodes) {
105
0
      LogMessage("Adding: " + pre.Name);
106
0
      exec.PreBuildDependencies.emplace(pre.Name);
107
0
    }
108
0
    this->GetGlobalGenerator()->AddTarget(std::move(exec));
109
0
  }
110
111
0
  for (auto& exec : preBuild.Nodes) {
112
0
    LogMessage("Adding exec " + exec.Name);
113
0
    addUtilDepToTarget(exec.Name);
114
0
    this->GetGlobalGenerator()->AddTarget(std::move(exec));
115
0
  }
116
117
0
  for (auto& exec : GenerateCommands(FastbuildBuildStep::REST).Nodes) {
118
0
    addUtilDepToTarget(exec.Name);
119
0
    for (auto const& dep : TargetDirectDependencies) {
120
0
      LogMessage("Direct dep " + dep->GetName() +
121
0
                 "-all propagating to CC: " + exec.Name);
122
      // All custom commands from within the target must be executed AFTER all
123
      // the target's deps.
124
0
      exec.PreBuildDependencies.emplace(dep->GetName());
125
0
    }
126
0
    this->GetGlobalGenerator()->AddTarget(std::move(exec));
127
0
  }
128
  // The target has to be in the build system, but has no custom commands
129
  // associated with it.
130
0
  if (fastbuildTarget.PreBuildDependencies.empty()) {
131
0
    std::vector<cmSourceFile*> sources;
132
0
    this->GetGeneratorTarget()->GetSourceFiles(sources, this->Config);
133
0
    if (sources.empty()) {
134
0
      FastbuildTargetDep dep{ FASTBUILD_NOOP_FILE_NAME };
135
0
      dep.Type = FastbuildTargetDepType::ORDER_ONLY;
136
0
      fastbuildTarget.PreBuildDependencies.emplace(std::move(dep));
137
0
    } else {
138
0
      for (cmSourceFile const* source : sources) {
139
0
        FastbuildTargetDep dep{
140
0
          this->GetGlobalGenerator()->ConvertToFastbuildPath(
141
0
            source->GetFullPath())
142
0
        };
143
0
        dep.Type = FastbuildTargetDepType::ARTIFACT;
144
0
        fastbuildTarget.PreBuildDependencies.emplace(std::move(dep));
145
0
      }
146
0
    }
147
0
  }
148
149
0
  fastbuildTarget.Hidden = false;
150
0
  this->AdditionalCleanFiles();
151
152
0
  fastbuildTarget.BasePath = this->GetMakefile()->GetCurrentSourceDirectory();
153
0
  this->GetGlobalGenerator()->AddIDEProject(fastbuildTarget, Config);
154
155
0
  this->GetGlobalGenerator()->AddTarget(std::move(fastbuildTarget));
156
0
}