diff options
Diffstat (limited to 'Source/cmTargetPrecompileHeadersCommand.cxx')
-rw-r--r-- | Source/cmTargetPrecompileHeadersCommand.cxx | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/Source/cmTargetPrecompileHeadersCommand.cxx b/Source/cmTargetPrecompileHeadersCommand.cxx new file mode 100644 index 0000000..4dd158d --- /dev/null +++ b/Source/cmTargetPrecompileHeadersCommand.cxx @@ -0,0 +1,88 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmTargetPrecompileHeadersCommand.h" + +#include <utility> + +#include "cmGeneratorExpression.h" +#include "cmListFileCache.h" +#include "cmMakefile.h" +#include "cmMessageType.h" +#include "cmStringAlgorithms.h" +#include "cmSystemTools.h" +#include "cmTarget.h" +#include "cmTargetPropCommandBase.h" + +namespace { + +std::vector<std::string> ConvertToAbsoluteContent( + const std::vector<std::string>& content, std::string const& baseDir) +{ + std::vector<std::string> absoluteContent; + absoluteContent.reserve(content.size()); + for (std::string const& src : content) { + std::string absoluteSrc; + // Use '<foo.h>' and '"foo.h"' includes and absolute paths as-is. + // Interpret relative paths with respect to the source directory. + // If the path starts in a generator expression, assume it is absolute. + if (cmHasLiteralPrefix(src, "<") || cmHasLiteralPrefix(src, "\"") || + cmSystemTools::FileIsFullPath(src) || + cmGeneratorExpression::Find(src) == 0) { + absoluteSrc = src; + } else { + absoluteSrc = cmStrCat(baseDir, '/', src); + } + absoluteContent.emplace_back(std::move(absoluteSrc)); + } + return absoluteContent; +} + +class TargetPrecompileHeadersImpl : public cmTargetPropCommandBase +{ +public: + using cmTargetPropCommandBase::cmTargetPropCommandBase; + +private: + bool HandleDirectContent(cmTarget* tgt, + const std::vector<std::string>& content, + bool /*prepend*/, bool /*system*/) override + { + std::string const& base = this->Makefile->GetCurrentSourceDirectory(); + tgt->AppendProperty("PRECOMPILE_HEADERS", + this->Join(ConvertToAbsoluteContent(content, base)), + this->Makefile->GetBacktrace()); + return true; + } + + void HandleInterfaceContent(cmTarget* tgt, + const std::vector<std::string>& content, + bool prepend, bool system) override + { + std::string const& base = this->Makefile->GetCurrentSourceDirectory(); + this->cmTargetPropCommandBase::HandleInterfaceContent( + tgt, ConvertToAbsoluteContent(content, base), prepend, system); + } + + void HandleMissingTarget(const std::string& name) override + { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Cannot specify precompile headers for target \"", name, + "\" which is not built by this project.")); + } + + std::string Join(const std::vector<std::string>& content) override + { + return cmJoin(content, ";"); + } +}; + +} // namespace + +bool cmTargetPrecompileHeadersCommand(std::vector<std::string> const& args, + cmExecutionStatus& status) +{ + return TargetPrecompileHeadersImpl(status).HandleArguments( + args, "PRECOMPILE_HEADERS", + TargetPrecompileHeadersImpl::PROCESS_REUSE_FROM); +} |