cmSetSourceFilesPropertiesCommand.cxx 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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 "cmSetSourceFilesPropertiesCommand.h"
  4. #include <algorithm>
  5. #include <iterator>
  6. #include <cm/string_view>
  7. #include <cmext/algorithm>
  8. #include <cmext/string_view>
  9. #include "cmExecutionStatus.h"
  10. #include "cmMakefile.h"
  11. #include "cmSetPropertyCommand.h"
  12. #include "cmSourceFile.h"
  13. #include "cmStringAlgorithms.h"
  14. static bool RunCommandForScope(
  15. cmMakefile* mf, std::vector<std::string>::const_iterator file_begin,
  16. std::vector<std::string>::const_iterator file_end,
  17. std::vector<std::string>::const_iterator prop_begin,
  18. std::vector<std::string>::const_iterator prop_end, std::string& errors);
  19. bool cmSetSourceFilesPropertiesCommand(std::vector<std::string> const& args,
  20. cmExecutionStatus& status)
  21. {
  22. if (args.size() < 2) {
  23. status.SetError("called with incorrect number of arguments");
  24. return false;
  25. }
  26. // break the arguments into source file names and properties
  27. // old style allows for specifier before PROPERTIES keyword
  28. static cm::string_view const prop_names[] = {
  29. "ABSTRACT", "GENERATED", "WRAP_EXCLUDE", "COMPILE_FLAGS",
  30. "OBJECT_DEPENDS", "PROPERTIES", "DIRECTORY", "TARGET_DIRECTORY"
  31. };
  32. auto isAPropertyKeyword =
  33. [](std::vector<std::string>::const_iterator arg_it) {
  34. return std::any_of(
  35. std::begin(prop_names), std::end(prop_names),
  36. [&arg_it](cm::string_view prop_name) { return *arg_it == prop_name; });
  37. };
  38. auto options_begin = std::find_first_of(
  39. args.begin(), args.end(), std::begin(prop_names), std::end(prop_names));
  40. auto options_it = options_begin;
  41. // Handle directory options.
  42. std::vector<std::string> source_file_directories;
  43. std::vector<std::string> source_file_target_directories;
  44. bool source_file_directory_option_enabled = false;
  45. bool source_file_target_option_enabled = false;
  46. std::vector<cmMakefile*> source_file_directory_makefiles;
  47. enum Doing
  48. {
  49. DoingNone,
  50. DoingSourceDirectory,
  51. DoingSourceTargetDirectory
  52. };
  53. Doing doing = DoingNone;
  54. for (; options_it != args.end(); ++options_it) {
  55. if (*options_it == "DIRECTORY") {
  56. doing = DoingSourceDirectory;
  57. source_file_directory_option_enabled = true;
  58. } else if (*options_it == "TARGET_DIRECTORY") {
  59. doing = DoingSourceTargetDirectory;
  60. source_file_target_option_enabled = true;
  61. } else if (isAPropertyKeyword(options_it)) {
  62. break;
  63. } else if (doing == DoingSourceDirectory) {
  64. source_file_directories.push_back(*options_it);
  65. } else if (doing == DoingSourceTargetDirectory) {
  66. source_file_target_directories.push_back(*options_it);
  67. } else {
  68. status.SetError(
  69. cmStrCat("given invalid argument \"", *options_it, "\"."));
  70. }
  71. }
  72. auto const props_begin = options_it;
  73. bool file_scopes_handled =
  74. SetPropertyCommand::HandleAndValidateSourceFileDirectoryScopes(
  75. status, source_file_directory_option_enabled,
  76. source_file_target_option_enabled, source_file_directories,
  77. source_file_target_directories, source_file_directory_makefiles);
  78. if (!file_scopes_handled) {
  79. return false;
  80. }
  81. std::vector<std::string> files;
  82. bool source_file_paths_should_be_absolute =
  83. source_file_directory_option_enabled || source_file_target_option_enabled;
  84. SetPropertyCommand::MakeSourceFilePathsAbsoluteIfNeeded(
  85. status, files, args.begin(), options_begin,
  86. source_file_paths_should_be_absolute);
  87. // Now call the worker function for each directory scope represented by a
  88. // cmMakefile instance.
  89. std::string errors;
  90. for (auto* const mf : source_file_directory_makefiles) {
  91. bool ret = RunCommandForScope(mf, files.begin(), files.end(), props_begin,
  92. args.end(), errors);
  93. if (!ret) {
  94. status.SetError(errors);
  95. return ret;
  96. }
  97. }
  98. return true;
  99. }
  100. static bool RunCommandForScope(
  101. cmMakefile* mf, std::vector<std::string>::const_iterator file_begin,
  102. std::vector<std::string>::const_iterator file_end,
  103. std::vector<std::string>::const_iterator prop_begin,
  104. std::vector<std::string>::const_iterator prop_end, std::string& errors)
  105. {
  106. std::vector<std::string> propertyPairs;
  107. // build the property pairs
  108. for (auto j = prop_begin; j != prop_end; ++j) {
  109. // consume old style options
  110. if (*j == "ABSTRACT" || *j == "GENERATED" || *j == "WRAP_EXCLUDE") {
  111. propertyPairs.emplace_back(*j);
  112. propertyPairs.emplace_back("1");
  113. } else if (*j == "COMPILE_FLAGS") {
  114. propertyPairs.emplace_back("COMPILE_FLAGS");
  115. ++j;
  116. if (j == prop_end) {
  117. errors = "called with incorrect number of arguments "
  118. "COMPILE_FLAGS with no flags";
  119. return false;
  120. }
  121. propertyPairs.push_back(*j);
  122. } else if (*j == "OBJECT_DEPENDS") {
  123. propertyPairs.emplace_back("OBJECT_DEPENDS");
  124. ++j;
  125. if (j == prop_end) {
  126. errors = "called with incorrect number of arguments "
  127. "OBJECT_DEPENDS with no dependencies";
  128. return false;
  129. }
  130. propertyPairs.push_back(*j);
  131. } else if (*j == "PROPERTIES") {
  132. // PROPERTIES is followed by new style prop value pairs
  133. cmStringRange newStyleProps{ j + 1, prop_end };
  134. if (newStyleProps.size() % 2 != 0) {
  135. errors = "called with incorrect number of arguments.";
  136. return false;
  137. }
  138. // set newStyleProps as is.
  139. cm::append(propertyPairs, newStyleProps);
  140. // break out of the loop.
  141. break;
  142. } else {
  143. errors = "called with illegal arguments, maybe missing a "
  144. "PROPERTIES specifier?";
  145. return false;
  146. }
  147. }
  148. // loop over all the files
  149. for (std::string const& sfname : cmStringRange{ file_begin, file_end }) {
  150. // get the source file
  151. if (cmSourceFile* sf = mf->GetOrCreateSource(sfname)) {
  152. // loop through the props and set them
  153. for (auto k = propertyPairs.begin(); k != propertyPairs.end(); k += 2) {
  154. // Special handling for GENERATED property?
  155. if (*k == "GENERATED"_s) {
  156. SetPropertyCommand::HandleAndValidateSourceFilePropertyGENERATED(
  157. sf, *(k + 1));
  158. } else {
  159. sf->SetProperty(*k, *(k + 1));
  160. }
  161. }
  162. }
  163. }
  164. return true;
  165. }