cmTargetSourcesCommand.cxx 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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",
  40. this->Join(ConvertToAbsoluteContent(tgt, content, false)).c_str());
  41. return true; // Successfully handled.
  42. }
  43. std::string Join(const std::vector<std::string>& content) override
  44. {
  45. return cmJoin(content, ";");
  46. }
  47. std::vector<std::string> ConvertToAbsoluteContent(
  48. cmTarget* tgt, const std::vector<std::string>& content,
  49. bool isInterfaceContent);
  50. };
  51. std::vector<std::string> TargetSourcesImpl::ConvertToAbsoluteContent(
  52. cmTarget* tgt, const std::vector<std::string>& content,
  53. bool isInterfaceContent)
  54. {
  55. // Skip conversion in case old behavior has been explicitly requested
  56. if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076) ==
  57. cmPolicies::OLD) {
  58. return content;
  59. }
  60. bool changedPath = false;
  61. std::vector<std::string> absoluteContent;
  62. absoluteContent.reserve(content.size());
  63. for (std::string const& src : content) {
  64. std::string absoluteSrc;
  65. if (cmSystemTools::FileIsFullPath(src) ||
  66. cmGeneratorExpression::Find(src) == 0 ||
  67. (!isInterfaceContent &&
  68. (this->Makefile->GetCurrentSourceDirectory() ==
  69. tgt->GetMakefile()->GetCurrentSourceDirectory()))) {
  70. absoluteSrc = src;
  71. } else {
  72. changedPath = true;
  73. absoluteSrc =
  74. cmStrCat(this->Makefile->GetCurrentSourceDirectory(), '/', src);
  75. }
  76. absoluteContent.push_back(absoluteSrc);
  77. }
  78. if (!changedPath) {
  79. return content;
  80. }
  81. bool issueMessage = true;
  82. bool useAbsoluteContent = false;
  83. std::ostringstream e;
  84. switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0076)) {
  85. case cmPolicies::WARN:
  86. e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0076) << "\n";
  87. break;
  88. case cmPolicies::OLD:
  89. issueMessage = false;
  90. break;
  91. case cmPolicies::REQUIRED_ALWAYS:
  92. case cmPolicies::REQUIRED_IF_USED:
  93. this->Makefile->IssueMessage(
  94. MessageType::FATAL_ERROR,
  95. cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0076));
  96. break;
  97. case cmPolicies::NEW: {
  98. issueMessage = false;
  99. useAbsoluteContent = true;
  100. break;
  101. }
  102. }
  103. if (issueMessage) {
  104. if (isInterfaceContent) {
  105. e << "An interface source of target \"" << tgt->GetName()
  106. << "\" has a relative path.";
  107. } else {
  108. e << "A private source from a directory other than that of target \""
  109. << tgt->GetName() << "\" has a relative path.";
  110. }
  111. this->Makefile->IssueMessage(MessageType::AUTHOR_WARNING, e.str());
  112. }
  113. return useAbsoluteContent ? absoluteContent : content;
  114. }
  115. } // namespace
  116. bool cmTargetSourcesCommand(std::vector<std::string> const& args,
  117. cmExecutionStatus& status)
  118. {
  119. return TargetSourcesImpl(status).HandleArguments(args, "SOURCES");
  120. }