cmAddSubDirectoryCommand.cxx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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 "cmAddSubDirectoryCommand.h"
  4. #include <cstring>
  5. #include <cm/string_view>
  6. #include "cmExecutionStatus.h"
  7. #include "cmMakefile.h"
  8. #include "cmRange.h"
  9. #include "cmStringAlgorithms.h"
  10. #include "cmSystemTools.h"
  11. bool cmAddSubDirectoryCommand(std::vector<std::string> const& args,
  12. cmExecutionStatus& status)
  13. {
  14. if (args.empty()) {
  15. status.SetError("called with incorrect number of arguments");
  16. return false;
  17. }
  18. cmMakefile& mf = status.GetMakefile();
  19. // store the binpath
  20. std::string const& srcArg = args.front();
  21. std::string binArg;
  22. bool excludeFromAll = false;
  23. bool system = false;
  24. // process the rest of the arguments looking for optional args
  25. for (std::string const& arg : cmMakeRange(args).advance(1)) {
  26. if (arg == "EXCLUDE_FROM_ALL") {
  27. excludeFromAll = true;
  28. continue;
  29. }
  30. if (arg == "SYSTEM") {
  31. system = true;
  32. continue;
  33. }
  34. if (binArg.empty()) {
  35. binArg = arg;
  36. } else {
  37. status.SetError("called with incorrect number of arguments");
  38. return false;
  39. }
  40. }
  41. // "SYSTEM" directory property should also affects targets in nested
  42. // subdirectories.
  43. if (mf.GetPropertyAsBool("SYSTEM")) {
  44. system = true;
  45. }
  46. // Compute the full path to the specified source directory.
  47. // Interpret a relative path with respect to the current source directory.
  48. std::string srcPath;
  49. if (cmSystemTools::FileIsFullPath(srcArg)) {
  50. srcPath = srcArg;
  51. } else {
  52. srcPath = cmStrCat(mf.GetCurrentSourceDirectory(), '/', srcArg);
  53. }
  54. if (!cmSystemTools::FileIsDirectory(srcPath)) {
  55. std::string error = cmStrCat("given source \"", srcArg,
  56. "\" which is not an existing directory.");
  57. status.SetError(error);
  58. return false;
  59. }
  60. srcPath =
  61. cmSystemTools::CollapseFullPath(srcPath, mf.GetHomeOutputDirectory());
  62. // Compute the full path to the binary directory.
  63. std::string binPath;
  64. if (binArg.empty()) {
  65. // No binary directory was specified. If the source directory is
  66. // not a subdirectory of the current directory then it is an
  67. // error.
  68. if (!cmSystemTools::IsSubDirectory(srcPath,
  69. mf.GetCurrentSourceDirectory())) {
  70. status.SetError(
  71. cmStrCat("not given a binary directory but the given source "
  72. "directory \"",
  73. srcPath, "\" is not a subdirectory of \"",
  74. mf.GetCurrentSourceDirectory(),
  75. "\". When specifying an "
  76. "out-of-tree source a binary directory must be explicitly "
  77. "specified."));
  78. return false;
  79. }
  80. // Remove the CurrentDirectory from the srcPath and replace it
  81. // with the CurrentOutputDirectory.
  82. std::string const& src = mf.GetCurrentSourceDirectory();
  83. std::string const& bin = mf.GetCurrentBinaryDirectory();
  84. size_t srcLen = src.length();
  85. size_t binLen = bin.length();
  86. if (srcLen > 0 && src.back() == '/') {
  87. --srcLen;
  88. }
  89. if (binLen > 0 && bin.back() == '/') {
  90. --binLen;
  91. }
  92. binPath = cmStrCat(cm::string_view(bin).substr(0, binLen),
  93. cm::string_view(srcPath).substr(srcLen));
  94. } else {
  95. // Use the binary directory specified.
  96. // Interpret a relative path with respect to the current binary directory.
  97. if (cmSystemTools::FileIsFullPath(binArg)) {
  98. binPath = binArg;
  99. } else {
  100. binPath = cmStrCat(mf.GetCurrentBinaryDirectory(), '/', binArg);
  101. }
  102. }
  103. binPath = cmSystemTools::CollapseFullPath(binPath);
  104. // Add the subdirectory using the computed full paths.
  105. mf.AddSubDirectory(srcPath, binPath, excludeFromAll, true, system);
  106. return true;
  107. }