cmGetPropertyCommand.cxx 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  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 "cmGetPropertyCommand.h"
  4. #include "cmGlobalGenerator.h"
  5. #include "cmPropertyDefinition.h"
  6. #include "cmSourceFile.h"
  7. #include "cmStateTypes.h"
  8. #include "cmTargetPropertyComputer.h"
  9. #include "cmTest.h"
  10. #include "cmake.h"
  11. cmGetPropertyCommand::cmGetPropertyCommand()
  12. {
  13. this->InfoType = OutValue;
  14. }
  15. bool cmGetPropertyCommand::InitialPass(std::vector<std::string> const& args,
  16. cmExecutionStatus&)
  17. {
  18. if (args.size() < 3) {
  19. this->SetError("called with incorrect number of arguments");
  20. return false;
  21. }
  22. // The cmake variable in which to store the result.
  23. this->Variable = args[0];
  24. // Get the scope from which to get the property.
  25. cmProperty::ScopeType scope;
  26. if (args[1] == "GLOBAL") {
  27. scope = cmProperty::GLOBAL;
  28. } else if (args[1] == "DIRECTORY") {
  29. scope = cmProperty::DIRECTORY;
  30. } else if (args[1] == "TARGET") {
  31. scope = cmProperty::TARGET;
  32. } else if (args[1] == "SOURCE") {
  33. scope = cmProperty::SOURCE_FILE;
  34. } else if (args[1] == "TEST") {
  35. scope = cmProperty::TEST;
  36. } else if (args[1] == "VARIABLE") {
  37. scope = cmProperty::VARIABLE;
  38. } else if (args[1] == "CACHE") {
  39. scope = cmProperty::CACHE;
  40. } else if (args[1] == "INSTALL") {
  41. scope = cmProperty::INSTALL;
  42. } else {
  43. std::ostringstream e;
  44. e << "given invalid scope " << args[1] << ". "
  45. << "Valid scopes are "
  46. << "GLOBAL, DIRECTORY, TARGET, SOURCE, TEST, VARIABLE, CACHE, INSTALL.";
  47. this->SetError(e.str());
  48. return false;
  49. }
  50. // Parse remaining arguments.
  51. enum Doing
  52. {
  53. DoingNone,
  54. DoingName,
  55. DoingProperty,
  56. DoingType
  57. };
  58. Doing doing = DoingName;
  59. for (unsigned int i = 2; i < args.size(); ++i) {
  60. if (args[i] == "PROPERTY") {
  61. doing = DoingProperty;
  62. } else if (args[i] == "BRIEF_DOCS") {
  63. doing = DoingNone;
  64. this->InfoType = OutBriefDoc;
  65. } else if (args[i] == "FULL_DOCS") {
  66. doing = DoingNone;
  67. this->InfoType = OutFullDoc;
  68. } else if (args[i] == "SET") {
  69. doing = DoingNone;
  70. this->InfoType = OutSet;
  71. } else if (args[i] == "DEFINED") {
  72. doing = DoingNone;
  73. this->InfoType = OutDefined;
  74. } else if (doing == DoingName) {
  75. doing = DoingNone;
  76. this->Name = args[i];
  77. } else if (doing == DoingProperty) {
  78. doing = DoingNone;
  79. this->PropertyName = args[i];
  80. } else {
  81. std::ostringstream e;
  82. e << "given invalid argument \"" << args[i] << "\".";
  83. this->SetError(e.str());
  84. return false;
  85. }
  86. }
  87. // Make sure a property name was found.
  88. if (this->PropertyName.empty()) {
  89. this->SetError("not given a PROPERTY <name> argument.");
  90. return false;
  91. }
  92. // Compute requested output.
  93. if (this->InfoType == OutBriefDoc) {
  94. // Lookup brief documentation.
  95. std::string output;
  96. if (cmPropertyDefinition const* def =
  97. this->Makefile->GetState()->GetPropertyDefinition(this->PropertyName,
  98. scope)) {
  99. output = def->GetShortDescription();
  100. } else {
  101. output = "NOTFOUND";
  102. }
  103. this->Makefile->AddDefinition(this->Variable, output.c_str());
  104. } else if (this->InfoType == OutFullDoc) {
  105. // Lookup full documentation.
  106. std::string output;
  107. if (cmPropertyDefinition const* def =
  108. this->Makefile->GetState()->GetPropertyDefinition(this->PropertyName,
  109. scope)) {
  110. output = def->GetFullDescription();
  111. } else {
  112. output = "NOTFOUND";
  113. }
  114. this->Makefile->AddDefinition(this->Variable, output.c_str());
  115. } else if (this->InfoType == OutDefined) {
  116. // Lookup if the property is defined
  117. if (this->Makefile->GetState()->GetPropertyDefinition(this->PropertyName,
  118. scope)) {
  119. this->Makefile->AddDefinition(this->Variable, "1");
  120. } else {
  121. this->Makefile->AddDefinition(this->Variable, "0");
  122. }
  123. } else {
  124. // Dispatch property getting.
  125. switch (scope) {
  126. case cmProperty::GLOBAL:
  127. return this->HandleGlobalMode();
  128. case cmProperty::DIRECTORY:
  129. return this->HandleDirectoryMode();
  130. case cmProperty::TARGET:
  131. return this->HandleTargetMode();
  132. case cmProperty::SOURCE_FILE:
  133. return this->HandleSourceMode();
  134. case cmProperty::TEST:
  135. return this->HandleTestMode();
  136. case cmProperty::VARIABLE:
  137. return this->HandleVariableMode();
  138. case cmProperty::CACHE:
  139. return this->HandleCacheMode();
  140. case cmProperty::INSTALL:
  141. return this->HandleInstallMode();
  142. case cmProperty::CACHED_VARIABLE:
  143. break; // should never happen
  144. }
  145. }
  146. return true;
  147. }
  148. bool cmGetPropertyCommand::StoreResult(const char* value)
  149. {
  150. if (this->InfoType == OutSet) {
  151. this->Makefile->AddDefinition(this->Variable, value ? "1" : "0");
  152. } else // if(this->InfoType == OutValue)
  153. {
  154. if (value) {
  155. this->Makefile->AddDefinition(this->Variable, value);
  156. } else {
  157. this->Makefile->RemoveDefinition(this->Variable);
  158. }
  159. }
  160. return true;
  161. }
  162. bool cmGetPropertyCommand::HandleGlobalMode()
  163. {
  164. if (!this->Name.empty()) {
  165. this->SetError("given name for GLOBAL scope.");
  166. return false;
  167. }
  168. // Get the property.
  169. cmake* cm = this->Makefile->GetCMakeInstance();
  170. return this->StoreResult(
  171. cm->GetState()->GetGlobalProperty(this->PropertyName));
  172. }
  173. bool cmGetPropertyCommand::HandleDirectoryMode()
  174. {
  175. // Default to the current directory.
  176. cmMakefile* mf = this->Makefile;
  177. // Lookup the directory if given.
  178. if (!this->Name.empty()) {
  179. // Construct the directory name. Interpret relative paths with
  180. // respect to the current directory.
  181. std::string dir = this->Name;
  182. if (!cmSystemTools::FileIsFullPath(dir.c_str())) {
  183. dir = this->Makefile->GetCurrentSourceDirectory();
  184. dir += "/";
  185. dir += this->Name;
  186. }
  187. // The local generators are associated with collapsed paths.
  188. dir = cmSystemTools::CollapseFullPath(dir);
  189. // Lookup the generator.
  190. mf = this->Makefile->GetGlobalGenerator()->FindMakefile(dir);
  191. if (!mf) {
  192. // Could not find the directory.
  193. this->SetError(
  194. "DIRECTORY scope provided but requested directory was not found. "
  195. "This could be because the directory argument was invalid or, "
  196. "it is valid but has not been processed yet.");
  197. return false;
  198. }
  199. }
  200. if (this->PropertyName == "DEFINITIONS") {
  201. switch (mf->GetPolicyStatus(cmPolicies::CMP0059)) {
  202. case cmPolicies::WARN:
  203. mf->IssueMessage(cmake::AUTHOR_WARNING,
  204. cmPolicies::GetPolicyWarning(cmPolicies::CMP0059));
  205. case cmPolicies::OLD:
  206. return this->StoreResult(mf->GetDefineFlagsCMP0059());
  207. case cmPolicies::NEW:
  208. case cmPolicies::REQUIRED_ALWAYS:
  209. case cmPolicies::REQUIRED_IF_USED:
  210. break;
  211. }
  212. }
  213. // Get the property.
  214. return this->StoreResult(mf->GetProperty(this->PropertyName));
  215. }
  216. bool cmGetPropertyCommand::HandleTargetMode()
  217. {
  218. if (this->Name.empty()) {
  219. this->SetError("not given name for TARGET scope.");
  220. return false;
  221. }
  222. if (cmTarget* target = this->Makefile->FindTargetToUse(this->Name)) {
  223. if (this->PropertyName == "ALIASED_TARGET") {
  224. if (this->Makefile->IsAlias(this->Name)) {
  225. return this->StoreResult(target->GetName().c_str());
  226. }
  227. return this->StoreResult(CM_NULLPTR);
  228. }
  229. const char* prop_cstr = 0;
  230. cmListFileBacktrace bt = this->Makefile->GetBacktrace();
  231. cmMessenger* messenger = this->Makefile->GetMessenger();
  232. if (cmTargetPropertyComputer::PassesWhitelist(
  233. target->GetType(), this->PropertyName, messenger, bt)) {
  234. prop_cstr =
  235. target->GetComputedProperty(this->PropertyName, messenger, bt);
  236. if (!prop_cstr) {
  237. prop_cstr = target->GetProperty(this->PropertyName);
  238. }
  239. }
  240. return this->StoreResult(prop_cstr);
  241. }
  242. std::ostringstream e;
  243. e << "could not find TARGET " << this->Name
  244. << ". Perhaps it has not yet been created.";
  245. this->SetError(e.str());
  246. return false;
  247. }
  248. bool cmGetPropertyCommand::HandleSourceMode()
  249. {
  250. if (this->Name.empty()) {
  251. this->SetError("not given name for SOURCE scope.");
  252. return false;
  253. }
  254. // Get the source file.
  255. if (cmSourceFile* sf = this->Makefile->GetOrCreateSource(this->Name)) {
  256. return this->StoreResult(sf->GetPropertyForUser(this->PropertyName));
  257. }
  258. std::ostringstream e;
  259. e << "given SOURCE name that could not be found or created: " << this->Name;
  260. this->SetError(e.str());
  261. return false;
  262. }
  263. bool cmGetPropertyCommand::HandleTestMode()
  264. {
  265. if (this->Name.empty()) {
  266. this->SetError("not given name for TEST scope.");
  267. return false;
  268. }
  269. // Loop over all tests looking for matching names.
  270. if (cmTest* test = this->Makefile->GetTest(this->Name)) {
  271. return this->StoreResult(test->GetProperty(this->PropertyName));
  272. }
  273. // If not found it is an error.
  274. std::ostringstream e;
  275. e << "given TEST name that does not exist: " << this->Name;
  276. this->SetError(e.str());
  277. return false;
  278. }
  279. bool cmGetPropertyCommand::HandleVariableMode()
  280. {
  281. if (!this->Name.empty()) {
  282. this->SetError("given name for VARIABLE scope.");
  283. return false;
  284. }
  285. return this->StoreResult(this->Makefile->GetDefinition(this->PropertyName));
  286. }
  287. bool cmGetPropertyCommand::HandleCacheMode()
  288. {
  289. if (this->Name.empty()) {
  290. this->SetError("not given name for CACHE scope.");
  291. return false;
  292. }
  293. const char* value = CM_NULLPTR;
  294. if (this->Makefile->GetState()->GetCacheEntryValue(this->Name)) {
  295. value = this->Makefile->GetState()->GetCacheEntryProperty(
  296. this->Name, this->PropertyName);
  297. }
  298. this->StoreResult(value);
  299. return true;
  300. }
  301. bool cmGetPropertyCommand::HandleInstallMode()
  302. {
  303. if (this->Name.empty()) {
  304. this->SetError("not given name for INSTALL scope.");
  305. return false;
  306. }
  307. // Get the installed file.
  308. cmake* cm = this->Makefile->GetCMakeInstance();
  309. if (cmInstalledFile* file =
  310. cm->GetOrCreateInstalledFile(this->Makefile, this->Name)) {
  311. std::string value;
  312. bool isSet = file->GetProperty(this->PropertyName, value);
  313. return this->StoreResult(isSet ? value.c_str() : CM_NULLPTR);
  314. }
  315. std::ostringstream e;
  316. e << "given INSTALL name that could not be found or created: " << this->Name;
  317. this->SetError(e.str());
  318. return false;
  319. }