cmTargetPrecompileHeadersCommand.cxx 3.0 KB

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