cmProjectCommand.cxx 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*============================================================================
  2. CMake - Cross Platform Makefile Generator
  3. Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
  4. Distributed under the OSI-approved BSD License (the "License");
  5. see accompanying file Copyright.txt for details.
  6. This software is distributed WITHOUT ANY WARRANTY; without even the
  7. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  8. See the License for more information.
  9. ============================================================================*/
  10. #include "cmProjectCommand.h"
  11. // cmProjectCommand
  12. bool cmProjectCommand
  13. ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
  14. {
  15. if(args.size() < 1 )
  16. {
  17. this->SetError("PROJECT called with incorrect number of arguments");
  18. return false;
  19. }
  20. this->Makefile->SetProjectName(args[0]);
  21. std::string bindir = args[0];
  22. bindir += "_BINARY_DIR";
  23. std::string srcdir = args[0];
  24. srcdir += "_SOURCE_DIR";
  25. this->Makefile->AddCacheDefinition
  26. (bindir,
  27. this->Makefile->GetCurrentBinaryDirectory(),
  28. "Value Computed by CMake", cmState::STATIC);
  29. this->Makefile->AddCacheDefinition
  30. (srcdir,
  31. this->Makefile->GetCurrentSourceDirectory(),
  32. "Value Computed by CMake", cmState::STATIC);
  33. bindir = "PROJECT_BINARY_DIR";
  34. srcdir = "PROJECT_SOURCE_DIR";
  35. this->Makefile->AddDefinition(bindir,
  36. this->Makefile->GetCurrentBinaryDirectory());
  37. this->Makefile->AddDefinition(srcdir,
  38. this->Makefile->GetCurrentSourceDirectory());
  39. this->Makefile->AddDefinition("PROJECT_NAME", args[0].c_str());
  40. // Set the CMAKE_PROJECT_NAME variable to be the highest-level
  41. // project name in the tree. If there are two project commands
  42. // in the same CMakeLists.txt file, and it is the top level
  43. // CMakeLists.txt file, then go with the last one, so that
  44. // CMAKE_PROJECT_NAME will match PROJECT_NAME, and cmake --build
  45. // will work.
  46. if(!this->Makefile->GetDefinition("CMAKE_PROJECT_NAME")
  47. || (this->Makefile->IsRootMakefile()))
  48. {
  49. this->Makefile->AddDefinition("CMAKE_PROJECT_NAME", args[0].c_str());
  50. this->Makefile->AddCacheDefinition
  51. ("CMAKE_PROJECT_NAME",
  52. args[0].c_str(),
  53. "Value Computed by CMake", cmState::STATIC);
  54. }
  55. bool haveVersion = false;
  56. bool haveLanguages = false;
  57. std::string version;
  58. std::vector<std::string> languages;
  59. enum Doing { DoingLanguages, DoingVersion };
  60. Doing doing = DoingLanguages;
  61. for(size_t i = 1; i < args.size(); ++i)
  62. {
  63. if(args[i] == "LANGUAGES")
  64. {
  65. if(haveLanguages)
  66. {
  67. this->Makefile->IssueMessage
  68. (cmake::FATAL_ERROR, "LANGUAGES may be specified at most once.");
  69. cmSystemTools::SetFatalErrorOccured();
  70. return true;
  71. }
  72. haveLanguages = true;
  73. doing = DoingLanguages;
  74. }
  75. else if (args[i] == "VERSION")
  76. {
  77. if(haveVersion)
  78. {
  79. this->Makefile->IssueMessage
  80. (cmake::FATAL_ERROR, "VERSION may be specified at most once.");
  81. cmSystemTools::SetFatalErrorOccured();
  82. return true;
  83. }
  84. haveVersion = true;
  85. doing = DoingVersion;
  86. }
  87. else if(doing == DoingVersion)
  88. {
  89. doing = DoingLanguages;
  90. version = args[i];
  91. }
  92. else // doing == DoingLanguages
  93. {
  94. languages.push_back(args[i]);
  95. }
  96. }
  97. if (haveVersion && !haveLanguages && !languages.empty())
  98. {
  99. this->Makefile->IssueMessage
  100. (cmake::FATAL_ERROR,
  101. "project with VERSION must use LANGUAGES before language names.");
  102. cmSystemTools::SetFatalErrorOccured();
  103. return true;
  104. }
  105. if (haveLanguages && languages.empty())
  106. {
  107. languages.push_back("NONE");
  108. }
  109. cmPolicies::PolicyStatus cmp0048 =
  110. this->Makefile->GetPolicyStatus(cmPolicies::CMP0048);
  111. if (haveVersion)
  112. {
  113. // Set project VERSION variables to given values
  114. if (cmp0048 == cmPolicies::OLD ||
  115. cmp0048 == cmPolicies::WARN)
  116. {
  117. this->Makefile->IssueMessage
  118. (cmake::FATAL_ERROR,
  119. "VERSION not allowed unless CMP0048 is set to NEW");
  120. cmSystemTools::SetFatalErrorOccured();
  121. return true;
  122. }
  123. cmsys::RegularExpression
  124. vx("^([0-9]+(\\.[0-9]+(\\.[0-9]+(\\.[0-9]+)?)?)?)?$");
  125. if(!vx.find(version))
  126. {
  127. std::string e = "VERSION \"" + version + "\" format invalid.";
  128. this->Makefile->IssueMessage(cmake::FATAL_ERROR, e);
  129. cmSystemTools::SetFatalErrorOccured();
  130. return true;
  131. }
  132. std::string vs;
  133. const char* sep = "";
  134. char vb[4][64];
  135. unsigned int v[4] = {0,0,0,0};
  136. int vc = sscanf(version.c_str(), "%u.%u.%u.%u",
  137. &v[0], &v[1], &v[2], &v[3]);
  138. for(int i=0; i < 4; ++i)
  139. {
  140. if(i < vc)
  141. {
  142. sprintf(vb[i], "%u", v[i]);
  143. vs += sep;
  144. vs += vb[i];
  145. sep = ".";
  146. }
  147. else
  148. {
  149. vb[i][0] = 0;
  150. }
  151. }
  152. std::string vv;
  153. vv = args[0] + "_VERSION";
  154. this->Makefile->AddDefinition("PROJECT_VERSION", vs.c_str());
  155. this->Makefile->AddDefinition(vv, vs.c_str());
  156. vv = args[0] + "_VERSION_MAJOR";
  157. this->Makefile->AddDefinition("PROJECT_VERSION_MAJOR", vb[0]);
  158. this->Makefile->AddDefinition(vv, vb[0]);
  159. vv = args[0] + "_VERSION_MINOR";
  160. this->Makefile->AddDefinition("PROJECT_VERSION_MINOR", vb[1]);
  161. this->Makefile->AddDefinition(vv, vb[1]);
  162. vv = args[0] + "_VERSION_PATCH";
  163. this->Makefile->AddDefinition("PROJECT_VERSION_PATCH", vb[2]);
  164. this->Makefile->AddDefinition(vv, vb[2]);
  165. vv = args[0] + "_VERSION_TWEAK";
  166. this->Makefile->AddDefinition("PROJECT_VERSION_TWEAK", vb[3]);
  167. this->Makefile->AddDefinition(vv, vb[3]);
  168. }
  169. else if(cmp0048 != cmPolicies::OLD)
  170. {
  171. // Set project VERSION variables to empty
  172. std::vector<std::string> vv;
  173. vv.push_back("PROJECT_VERSION");
  174. vv.push_back("PROJECT_VERSION_MAJOR");
  175. vv.push_back("PROJECT_VERSION_MINOR");
  176. vv.push_back("PROJECT_VERSION_PATCH");
  177. vv.push_back("PROJECT_VERSION_TWEAK");
  178. vv.push_back(args[0] + "_VERSION");
  179. vv.push_back(args[0] + "_VERSION_MAJOR");
  180. vv.push_back(args[0] + "_VERSION_MINOR");
  181. vv.push_back(args[0] + "_VERSION_PATCH");
  182. vv.push_back(args[0] + "_VERSION_TWEAK");
  183. std::string vw;
  184. for(std::vector<std::string>::iterator i = vv.begin();
  185. i != vv.end(); ++i)
  186. {
  187. const char* v = this->Makefile->GetDefinition(*i);
  188. if(v && *v)
  189. {
  190. if(cmp0048 == cmPolicies::WARN)
  191. {
  192. vw += "\n ";
  193. vw += *i;
  194. }
  195. else
  196. {
  197. this->Makefile->AddDefinition(*i, "");
  198. }
  199. }
  200. }
  201. if(!vw.empty())
  202. {
  203. std::ostringstream w;
  204. w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0048)
  205. << "\nThe following variable(s) would be set to empty:" << vw;
  206. this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
  207. }
  208. }
  209. if (languages.empty())
  210. {
  211. // if no language is specified do c and c++
  212. languages.push_back("C");
  213. languages.push_back("CXX");
  214. }
  215. this->Makefile->EnableLanguage(languages, false);
  216. std::string extraInclude = "CMAKE_PROJECT_" + args[0] + "_INCLUDE";
  217. const char* include = this->Makefile->GetDefinition(extraInclude);
  218. if(include)
  219. {
  220. bool readit =
  221. this->Makefile->ReadDependentFile(include);
  222. if(!readit && !cmSystemTools::GetFatalErrorOccured())
  223. {
  224. std::string m =
  225. "could not find file:\n"
  226. " ";
  227. m += include;
  228. this->SetError(m);
  229. return false;
  230. }
  231. }
  232. return true;
  233. }