cmTargetSourcesCommand.cxx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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 "cmTargetSourcesCommand.h"
  4. #include <sstream>
  5. #include "cmGeneratorExpression.h"
  6. #include "cmMakefile.h"
  7. #include "cmMessageType.h"
  8. #include "cmPolicies.h"
  9. #include "cmStringAlgorithms.h"
  10. #include "cmSystemTools.h"
  11. #include "cmTarget.h"
  12. #include "cmTargetPropCommandBase.h"
  13. namespace {
  14. class TargetSourcesImpl : public cmTargetPropCommandBase
  15. {
  16. public:
  17. using cmTargetPropCommandBase::cmTargetPropCommandBase;
  18. protected:
  19. void HandleInterfaceContent(cmTarget* tgt,
  20. const std::vector<std::string>& content,
  21. bool prepend, bool system) override
  22. {
  23. cmTargetPropCommandBase::HandleInterfaceContent(
  24. tgt, ConvertToAbsoluteContent(tgt, content, true), prepend, system);
  25. }
  26. private:
  27. void HandleMissingTarget(const std::string& name) override
  28. {
  29. this->Makefile->IssueMessage(
  30. MessageType::FATAL_ERROR,
  31. cmStrCat("Cannot specify sources for target \"", name,
  32. "\" which is not built by this project."));
  33. }
  34. bool HandleDirectContent(cmTarget* tgt,
  35. const std::vector<std::string>& content,
  36. bool /*prepend*/, bool /*system*/) override
  37. {
  38. tgt->AppendProperty(
  39. "SOURCES", this->Join(ConvertToAbsoluteContent(tgt, content, false)));
  40. return true; // Successfully handled.
  41. }
  42. std::string Join(const std::vector<std::string>& content) override
  43. {
  44. return cmJoin(content, ";");
  45. }
  46. std::vector<std::string> ConvertToAbsoluteContent(
  47. cmTarget* tgt, const std::vector<std::string>& content,
  48. bool isInterfaceContent);
  49. };
  50. std::vector<std::string> TargetSourcesImpl::ConvertToAbsoluteContent(
  51. cmTarget* tgt, const std::vector<std::string>& content,
  52. bool isInterfaceContent)
  53. {
  54. // Skip conversion in case old behavior has been explicitly requested
  55. if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076) ==
  56. cmPolicies::OLD) {
  57. return content;
  58. }
  59. bool changedPath = false;
  60. std::vector<std::string> absoluteContent;
  61. absoluteContent.reserve(content.size());
  62. for (std::string const& src : content) {
  63. std::string absoluteSrc;
  64. if (cmSystemTools::FileIsFullPath(src) ||
  65. cmGeneratorExpression::Find(src) == 0 ||
  66. (!isInterfaceContent &&
  67. (this->Makefile->GetCurrentSourceDirectory() ==
  68. tgt->GetMakefile()->GetCurrentSourceDirectory()))) {
  69. absoluteSrc = src;
  70. } else {
  71. changedPath = true;
  72. absoluteSrc =
  73. cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', src);
  74. }
  75. absoluteContent.push_back(absoluteSrc);
  76. }
  77. if (!changedPath) {
  78. return content;
  79. }
  80. bool issueMessage = true;
  81. bool useAbsoluteContent = false;
  82. std::ostringstream e;
  83. switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076)) {
  84. case cmPolicies::WARN:
  85. e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0076) << "\n";
  86. break;
  87. case cmPolicies::OLD:
  88. issueMessage = false;
  89. break;
  90. case cmPolicies::REQUIRED_ALWAYS:
  91. case cmPolicies::REQUIRED_IF_USED:
  92. this->Makefile->IssueMessage(
  93. MessageType::FATAL_ERROR,
  94. cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0076));
  95. break;
  96. case cmPolicies::NEW: {
  97. issueMessage = false;
  98. useAbsoluteContent = true;
  99. break;
  100. }
  101. }
  102. if (issueMessage) {
  103. if (isInterfaceContent) {
  104. e << "An interface source of target \"" << tgt->GetName()
  105. << "\" has a relative path.";
  106. } else {
  107. e << "A private source from a directory other than that of target \""
  108. << tgt->GetName() << "\" has a relative path.";
  109. }
  110. this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
  111. }
  112. return useAbsoluteContent ? absoluteContent : content;
  113. }
  114. } // namespace
  115. bool cmTargetSourcesCommand(std::vector<std::string> const& args,
  116. cmExecutionStatus& status)
  117. {
  118. return TargetSourcesImpl(status).HandleArguments(args, "SOURCES");
  119. }