cmUtilitySourceCommand.cxx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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 "cmUtilitySourceCommand.h"
  4. #include <string.h>
  5. #include "cmMakefile.h"
  6. #include "cmState.h"
  7. #include "cmStateTypes.h"
  8. #include "cmSystemTools.h"
  9. class cmExecutionStatus;
  10. // cmUtilitySourceCommand
  11. bool cmUtilitySourceCommand::InitialPass(std::vector<std::string> const& args,
  12. cmExecutionStatus&)
  13. {
  14. if (args.size() < 3) {
  15. this->SetError("called with incorrect number of arguments");
  16. return false;
  17. }
  18. std::vector<std::string>::const_iterator arg = args.begin();
  19. // The first argument is the cache entry name.
  20. std::string const& cacheEntry = *arg++;
  21. const char* cacheValue = this->Makefile->GetDefinition(cacheEntry);
  22. // If it exists already and appears up to date then we are done. If
  23. // the string contains "(IntDir)" but that is not the
  24. // CMAKE_CFG_INTDIR setting then the value is out of date.
  25. const char* intDir =
  26. this->Makefile->GetRequiredDefinition("CMAKE_CFG_INTDIR");
  27. bool haveCacheValue = false;
  28. if (this->Makefile->IsOn("CMAKE_CROSSCOMPILING")) {
  29. haveCacheValue = (cacheValue != nullptr);
  30. if (!haveCacheValue) {
  31. std::string msg = "UTILITY_SOURCE is used in cross compiling mode for ";
  32. msg += cacheEntry;
  33. msg += ". If your intention is to run this executable, you need to "
  34. "preload the cache with the full path to a version of that "
  35. "program, which runs on this build machine.";
  36. cmSystemTools::Message(msg.c_str(), "Warning");
  37. }
  38. } else {
  39. cmState* state = this->Makefile->GetState();
  40. haveCacheValue =
  41. (cacheValue && (strstr(cacheValue, "(IntDir)") == nullptr ||
  42. (intDir && strcmp(intDir, "$(IntDir)") == 0)) &&
  43. (state->GetCacheMajorVersion() != 0 &&
  44. state->GetCacheMinorVersion() != 0));
  45. }
  46. if (haveCacheValue) {
  47. return true;
  48. }
  49. // The second argument is the utility's executable name, which will be
  50. // needed later.
  51. std::string const& utilityName = *arg++;
  52. // The third argument specifies the relative directory of the source
  53. // of the utility.
  54. std::string const& relativeSource = *arg++;
  55. std::string utilitySource = this->Makefile->GetCurrentSourceDirectory();
  56. utilitySource = utilitySource + "/" + relativeSource;
  57. // If the directory doesn't exist, the source has not been included.
  58. if (!cmSystemTools::FileExists(utilitySource)) {
  59. return true;
  60. }
  61. // Make sure all the files exist in the source directory.
  62. while (arg != args.end()) {
  63. std::string file = utilitySource + "/" + *arg++;
  64. if (!cmSystemTools::FileExists(file)) {
  65. return true;
  66. }
  67. }
  68. // The source exists.
  69. std::string cmakeCFGout =
  70. this->Makefile->GetRequiredDefinition("CMAKE_CFG_INTDIR");
  71. std::string utilityDirectory = this->Makefile->GetCurrentBinaryDirectory();
  72. std::string exePath;
  73. if (this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH")) {
  74. exePath = this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
  75. }
  76. if (!exePath.empty()) {
  77. utilityDirectory = exePath;
  78. } else {
  79. utilityDirectory += "/" + relativeSource;
  80. }
  81. // Construct the cache entry for the executable's location.
  82. std::string utilityExecutable = utilityDirectory + "/" + cmakeCFGout + "/" +
  83. utilityName + this->Makefile->GetDefinition("CMAKE_EXECUTABLE_SUFFIX");
  84. // make sure we remove any /./ in the name
  85. cmSystemTools::ReplaceString(utilityExecutable, "/./", "/");
  86. // Enter the value into the cache.
  87. this->Makefile->AddCacheDefinition(cacheEntry, utilityExecutable.c_str(),
  88. "Path to an internal program.",
  89. cmStateEnums::FILEPATH);
  90. // add a value into the cache that maps from the
  91. // full path to the name of the project
  92. cmSystemTools::ConvertToUnixSlashes(utilityExecutable);
  93. this->Makefile->AddCacheDefinition(utilityExecutable, utilityName.c_str(),
  94. "Executable to project name.",
  95. cmStateEnums::INTERNAL);
  96. return true;
  97. }