Coverage Report

Created: 2026-02-09 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Source/cmTargetPrecompileHeadersCommand.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
#include "cmTargetPrecompileHeadersCommand.h"
4
5
#include <utility>
6
7
#include <cm/optional>
8
9
#include "cmGeneratorExpression.h"
10
#include "cmList.h"
11
#include "cmListFileCache.h"
12
#include "cmMakefile.h"
13
#include "cmMessageType.h"
14
#include "cmStringAlgorithms.h"
15
#include "cmSystemTools.h"
16
#include "cmTarget.h"
17
#include "cmTargetPropCommandBase.h"
18
19
namespace {
20
21
std::vector<std::string> ConvertToAbsoluteContent(
22
  std::vector<std::string> const& content, std::string const& baseDir)
23
0
{
24
0
  std::vector<std::string> absoluteContent;
25
0
  absoluteContent.reserve(content.size());
26
0
  for (std::string const& src : content) {
27
0
    std::string absoluteSrc;
28
    // Use '<foo.h>' and '"foo.h"' includes and absolute paths as-is.
29
    // Interpret relative paths with respect to the source directory.
30
    // If the path starts in a generator expression, assume it is absolute.
31
0
    if (cmHasPrefix(src, '<') || cmHasPrefix(src, '"') ||
32
0
        cmSystemTools::FileIsFullPath(src) ||
33
0
        cmGeneratorExpression::Find(src) == 0) {
34
0
      absoluteSrc = src;
35
0
    } else {
36
0
      absoluteSrc = cmStrCat(baseDir, '/', src);
37
0
    }
38
0
    absoluteContent.emplace_back(std::move(absoluteSrc));
39
0
  }
40
0
  return absoluteContent;
41
0
}
42
43
class TargetPrecompileHeadersImpl : public cmTargetPropCommandBase
44
{
45
public:
46
  using cmTargetPropCommandBase::cmTargetPropCommandBase;
47
48
private:
49
  bool HandleDirectContent(cmTarget* tgt,
50
                           std::vector<std::string> const& content,
51
                           bool /*prepend*/, bool /*system*/) override
52
0
  {
53
0
    std::string const& base = this->Makefile->GetCurrentSourceDirectory();
54
0
    tgt->AppendProperty("PRECOMPILE_HEADERS",
55
0
                        this->Join(ConvertToAbsoluteContent(content, base)),
56
0
                        this->Makefile->GetBacktrace());
57
0
    return true;
58
0
  }
59
60
  void HandleInterfaceContent(cmTarget* tgt,
61
                              std::vector<std::string> const& content,
62
                              bool prepend, bool system) override
63
0
  {
64
0
    std::string const& base = this->Makefile->GetCurrentSourceDirectory();
65
0
    this->cmTargetPropCommandBase::HandleInterfaceContent(
66
0
      tgt, ConvertToAbsoluteContent(content, base), prepend, system);
67
0
  }
68
69
  void HandleMissingTarget(std::string const& name) override
70
0
  {
71
0
    this->Makefile->IssueMessage(
72
0
      MessageType::FATAL_ERROR,
73
0
      cmStrCat("Cannot specify precompile headers for target \"", name,
74
0
               "\" which is not built by this project."));
75
0
  }
76
77
  std::string Join(std::vector<std::string> const& content) override
78
0
  {
79
0
    return cmList::to_string(content);
80
0
  }
81
};
82
83
} // namespace
84
85
bool cmTargetPrecompileHeadersCommand(std::vector<std::string> const& args,
86
                                      cmExecutionStatus& status)
87
0
{
88
0
  return TargetPrecompileHeadersImpl(status).HandleArguments(
89
0
    args, "PRECOMPILE_HEADERS",
90
0
    TargetPrecompileHeadersImpl::PROCESS_REUSE_FROM);
91
0
}