cmCTestConfigureCommand.cxx 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  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 "cmCTestConfigureCommand.h"
  4. #include <cstring>
  5. #include <sstream>
  6. #include <vector>
  7. #include "cm_static_string_view.hxx"
  8. #include "cmCTest.h"
  9. #include "cmCTestConfigureHandler.h"
  10. #include "cmGlobalGenerator.h"
  11. #include "cmMakefile.h"
  12. #include "cmStringAlgorithms.h"
  13. #include "cmSystemTools.h"
  14. #include "cmake.h"
  15. void cmCTestConfigureCommand::BindArguments()
  16. {
  17. this->cmCTestHandlerCommand::BindArguments();
  18. this->Bind("OPTIONS"_s, this->Options);
  19. }
  20. cmCTestGenericHandler* cmCTestConfigureCommand::InitializeHandler()
  21. {
  22. std::vector<std::string> options;
  23. if (!this->Options.empty()) {
  24. cmExpandList(this->Options, options);
  25. }
  26. if (this->CTest->GetCTestConfiguration("BuildDirectory").empty()) {
  27. this->SetError(
  28. "Build directory not specified. Either use BUILD "
  29. "argument to CTEST_CONFIGURE command or set CTEST_BINARY_DIRECTORY "
  30. "variable");
  31. return nullptr;
  32. }
  33. const char* ctestConfigureCommand =
  34. this->Makefile->GetDefinition("CTEST_CONFIGURE_COMMAND");
  35. if (ctestConfigureCommand && *ctestConfigureCommand) {
  36. this->CTest->SetCTestConfiguration("ConfigureCommand",
  37. ctestConfigureCommand, this->Quiet);
  38. } else {
  39. const char* cmakeGeneratorName =
  40. this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR");
  41. if (cmakeGeneratorName && *cmakeGeneratorName) {
  42. const std::string& source_dir =
  43. this->CTest->GetCTestConfiguration("SourceDirectory");
  44. if (source_dir.empty()) {
  45. this->SetError(
  46. "Source directory not specified. Either use SOURCE "
  47. "argument to CTEST_CONFIGURE command or set CTEST_SOURCE_DIRECTORY "
  48. "variable");
  49. return nullptr;
  50. }
  51. const std::string cmakelists_file = source_dir + "/CMakeLists.txt";
  52. if (!cmSystemTools::FileExists(cmakelists_file)) {
  53. std::ostringstream e;
  54. e << "CMakeLists.txt file does not exist [" << cmakelists_file << "]";
  55. this->SetError(e.str());
  56. return nullptr;
  57. }
  58. bool multiConfig = false;
  59. bool cmakeBuildTypeInOptions = false;
  60. auto gg = this->Makefile->GetCMakeInstance()->CreateGlobalGenerator(
  61. cmakeGeneratorName);
  62. if (gg) {
  63. multiConfig = gg->IsMultiConfig();
  64. gg.reset();
  65. }
  66. std::string cmakeConfigureCommand =
  67. cmStrCat('"', cmSystemTools::GetCMakeCommand(), '"');
  68. for (std::string const& option : options) {
  69. cmakeConfigureCommand += " \"";
  70. cmakeConfigureCommand += option;
  71. cmakeConfigureCommand += "\"";
  72. if ((nullptr != strstr(option.c_str(), "CMAKE_BUILD_TYPE=")) ||
  73. (nullptr != strstr(option.c_str(), "CMAKE_BUILD_TYPE:STRING="))) {
  74. cmakeBuildTypeInOptions = true;
  75. }
  76. }
  77. if (!multiConfig && !cmakeBuildTypeInOptions &&
  78. !this->CTest->GetConfigType().empty()) {
  79. cmakeConfigureCommand += " \"-DCMAKE_BUILD_TYPE:STRING=";
  80. cmakeConfigureCommand += this->CTest->GetConfigType();
  81. cmakeConfigureCommand += "\"";
  82. }
  83. if (this->Makefile->IsOn("CTEST_USE_LAUNCHERS")) {
  84. cmakeConfigureCommand += " \"-DCTEST_USE_LAUNCHERS:BOOL=TRUE\"";
  85. }
  86. cmakeConfigureCommand += " \"-G";
  87. cmakeConfigureCommand += cmakeGeneratorName;
  88. cmakeConfigureCommand += "\"";
  89. const char* cmakeGeneratorPlatform =
  90. this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR_PLATFORM");
  91. if (cmakeGeneratorPlatform && *cmakeGeneratorPlatform) {
  92. cmakeConfigureCommand += " \"-A";
  93. cmakeConfigureCommand += cmakeGeneratorPlatform;
  94. cmakeConfigureCommand += "\"";
  95. }
  96. const char* cmakeGeneratorToolset =
  97. this->Makefile->GetDefinition("CTEST_CMAKE_GENERATOR_TOOLSET");
  98. if (cmakeGeneratorToolset && *cmakeGeneratorToolset) {
  99. cmakeConfigureCommand += " \"-T";
  100. cmakeConfigureCommand += cmakeGeneratorToolset;
  101. cmakeConfigureCommand += "\"";
  102. }
  103. cmakeConfigureCommand += " \"";
  104. cmakeConfigureCommand += source_dir;
  105. cmakeConfigureCommand += "\"";
  106. this->CTest->SetCTestConfiguration(
  107. "ConfigureCommand", cmakeConfigureCommand.c_str(), this->Quiet);
  108. } else {
  109. this->SetError(
  110. "Configure command is not specified. If this is a "
  111. "\"built with CMake\" project, set CTEST_CMAKE_GENERATOR. If not, "
  112. "set CTEST_CONFIGURE_COMMAND.");
  113. return nullptr;
  114. }
  115. }
  116. if (const char* labelsForSubprojects =
  117. this->Makefile->GetDefinition("CTEST_LABELS_FOR_SUBPROJECTS")) {
  118. this->CTest->SetCTestConfiguration("LabelsForSubprojects",
  119. labelsForSubprojects, this->Quiet);
  120. }
  121. cmCTestConfigureHandler* handler = this->CTest->GetConfigureHandler();
  122. handler->Initialize();
  123. handler->SetQuiet(this->Quiet);
  124. return handler;
  125. }