resolve cyclic dependency with zstd
[platform/upstream/cmake.git] / Source / cmTargetPrecompileHeadersCommand.cxx
1 /* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
2    file Copyright.txt or https://cmake.org/licensing for details.  */
3 #include "cmTargetPrecompileHeadersCommand.h"
4
5 #include <utility>
6
7 #include "cmGeneratorExpression.h"
8 #include "cmListFileCache.h"
9 #include "cmMakefile.h"
10 #include "cmMessageType.h"
11 #include "cmStringAlgorithms.h"
12 #include "cmSystemTools.h"
13 #include "cmTarget.h"
14 #include "cmTargetPropCommandBase.h"
15
16 namespace {
17
18 std::vector<std::string> ConvertToAbsoluteContent(
19   const std::vector<std::string>& content, std::string const& baseDir)
20 {
21   std::vector<std::string> absoluteContent;
22   absoluteContent.reserve(content.size());
23   for (std::string const& src : content) {
24     std::string absoluteSrc;
25     // Use '<foo.h>' and '"foo.h"' includes and absolute paths as-is.
26     // Interpret relative paths with respect to the source directory.
27     // If the path starts in a generator expression, assume it is absolute.
28     if (cmHasLiteralPrefix(src, "<") || cmHasLiteralPrefix(src, "\"") ||
29         cmSystemTools::FileIsFullPath(src) ||
30         cmGeneratorExpression::Find(src) == 0) {
31       absoluteSrc = src;
32     } else {
33       absoluteSrc = cmStrCat(baseDir, '/', src);
34     }
35     absoluteContent.emplace_back(std::move(absoluteSrc));
36   }
37   return absoluteContent;
38 }
39
40 class TargetPrecompileHeadersImpl : public cmTargetPropCommandBase
41 {
42 public:
43   using cmTargetPropCommandBase::cmTargetPropCommandBase;
44
45 private:
46   bool HandleDirectContent(cmTarget* tgt,
47                            const std::vector<std::string>& content,
48                            bool /*prepend*/, bool /*system*/) override
49   {
50     std::string const& base = this->Makefile->GetCurrentSourceDirectory();
51     tgt->AppendProperty("PRECOMPILE_HEADERS",
52                         this->Join(ConvertToAbsoluteContent(content, base)),
53                         this->Makefile->GetBacktrace());
54     return true;
55   }
56
57   void HandleInterfaceContent(cmTarget* tgt,
58                               const std::vector<std::string>& content,
59                               bool prepend, bool system) override
60   {
61     std::string const& base = this->Makefile->GetCurrentSourceDirectory();
62     this->cmTargetPropCommandBase::HandleInterfaceContent(
63       tgt, ConvertToAbsoluteContent(content, base), prepend, system);
64   }
65
66   void HandleMissingTarget(const std::string& name) override
67   {
68     this->Makefile->IssueMessage(
69       MessageType::FATAL_ERROR,
70       cmStrCat("Cannot specify precompile headers for target \"", name,
71                "\" which is not built by this project."));
72   }
73
74   std::string Join(const std::vector<std::string>& content) override
75   {
76     return cmJoin(content, ";");
77   }
78 };
79
80 } // namespace
81
82 bool cmTargetPrecompileHeadersCommand(std::vector<std::string> const& args,
83                                       cmExecutionStatus& status)
84 {
85   return TargetPrecompileHeadersImpl(status).HandleArguments(
86     args, "PRECOMPILE_HEADERS",
87     TargetPrecompileHeadersImpl::PROCESS_REUSE_FROM);
88 }