cmSetPropertyCommand.cxx 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmSetPropertyCommand.h"
  14. #include "cmSetTargetPropertiesCommand.h"
  15. #include "cmSetTestsPropertiesCommand.h"
  16. #include "cmSetSourceFilesPropertiesCommand.h"
  17. //----------------------------------------------------------------------------
  18. cmSetPropertyCommand::cmSetPropertyCommand()
  19. {
  20. this->AppendMode = false;
  21. }
  22. //----------------------------------------------------------------------------
  23. bool cmSetPropertyCommand
  24. ::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
  25. {
  26. if(args.size() < 2 )
  27. {
  28. this->SetError("called with incorrect number of arguments");
  29. return false;
  30. }
  31. // Get the scope on which to set the property.
  32. std::vector<std::string>::const_iterator arg = args.begin();
  33. cmProperty::ScopeType scope;
  34. if(*arg == "GLOBAL")
  35. {
  36. scope = cmProperty::GLOBAL;
  37. }
  38. else if(*arg == "DIRECTORY")
  39. {
  40. scope = cmProperty::DIRECTORY;
  41. }
  42. else if(*arg == "TARGET")
  43. {
  44. scope = cmProperty::TARGET;
  45. }
  46. else if(*arg == "SOURCE")
  47. {
  48. scope = cmProperty::SOURCE_FILE;
  49. }
  50. else if(*arg == "TEST")
  51. {
  52. scope = cmProperty::TEST;
  53. }
  54. else
  55. {
  56. cmOStringStream e;
  57. e << "given invalid scope " << *arg << ". "
  58. << "Valid scopes are GLOBAL, DIRECTORY, TARGET, SOURCE, TEST.";
  59. this->SetError(e.str().c_str());
  60. return false;
  61. }
  62. // Parse the rest of the arguments up to the values.
  63. enum Doing { DoingNone, DoingNames, DoingProperty, DoingValues };
  64. Doing doing = DoingNames;
  65. const char* sep = "";
  66. for(++arg; arg != args.end(); ++arg)
  67. {
  68. if(*arg == "PROPERTY")
  69. {
  70. doing = DoingProperty;
  71. }
  72. else if(*arg == "APPEND")
  73. {
  74. doing = DoingNone;
  75. this->AppendMode = true;
  76. }
  77. else if(doing == DoingNames)
  78. {
  79. this->Names.insert(*arg);
  80. }
  81. else if(doing == DoingProperty)
  82. {
  83. this->PropertyName = *arg;
  84. doing = DoingValues;
  85. }
  86. else if(doing == DoingValues)
  87. {
  88. this->PropertyValue += sep;
  89. sep = ";";
  90. this->PropertyValue += *arg;
  91. }
  92. else
  93. {
  94. cmOStringStream e;
  95. e << "given invalid argument \"" << *arg << "\".";
  96. this->SetError(e.str().c_str());
  97. return false;
  98. }
  99. }
  100. // Make sure a property name was found.
  101. if(this->PropertyName.empty())
  102. {
  103. this->SetError("not given a PROPERTY <name> argument.");
  104. return false;
  105. }
  106. // Dispatch property setting.
  107. switch(scope)
  108. {
  109. case cmProperty::GLOBAL: return this->HandleGlobalMode();
  110. case cmProperty::DIRECTORY: return this->HandleDirectoryMode();
  111. case cmProperty::TARGET: return this->HandleTargetMode();
  112. case cmProperty::SOURCE_FILE: return this->HandleSourceMode();
  113. case cmProperty::TEST: return this->HandleTestMode();
  114. case cmProperty::VARIABLE:
  115. case cmProperty::CACHED_VARIABLE:
  116. break; // should never happen
  117. }
  118. return true;
  119. }
  120. //----------------------------------------------------------------------------
  121. bool cmSetPropertyCommand::HandleGlobalMode()
  122. {
  123. if(!this->Names.empty())
  124. {
  125. this->SetError("given names for GLOBAL scope.");
  126. return false;
  127. }
  128. // Set or append the property.
  129. cmake* cm = this->Makefile->GetCMakeInstance();
  130. const char* name = this->PropertyName.c_str();
  131. if(this->AppendMode)
  132. {
  133. cm->AppendProperty(name, this->PropertyValue.c_str());
  134. }
  135. else
  136. {
  137. cm->SetProperty(name, this->PropertyValue.c_str());
  138. }
  139. return true;
  140. }
  141. //----------------------------------------------------------------------------
  142. bool cmSetPropertyCommand::HandleDirectoryMode()
  143. {
  144. if(this->Names.size() > 1)
  145. {
  146. this->SetError("allows at most one name for DIRECTORY scope.");
  147. return false;
  148. }
  149. // Default to the current directory.
  150. cmMakefile* mf = this->Makefile;
  151. // Lookup the directory if given.
  152. if(!this->Names.empty())
  153. {
  154. // Construct the directory name. Interpret relative paths with
  155. // respect to the current directory.
  156. std::string dir = *this->Names.begin();
  157. if(!cmSystemTools::FileIsFullPath(dir.c_str()))
  158. {
  159. dir = this->Makefile->GetCurrentDirectory();
  160. dir += "/";
  161. dir += *this->Names.begin();
  162. }
  163. // The local generators are associated with collapsed paths.
  164. dir = cmSystemTools::CollapseFullPath(dir.c_str());
  165. // Lookup the generator.
  166. if(cmLocalGenerator* lg =
  167. (this->Makefile->GetLocalGenerator()
  168. ->GetGlobalGenerator()->FindLocalGenerator(dir.c_str())))
  169. {
  170. // Use the makefile for the directory found.
  171. mf = lg->GetMakefile();
  172. }
  173. else
  174. {
  175. // Could not find the directory.
  176. this->SetError
  177. ("DIRECTORY scope provided but requested directory was not found. "
  178. "This could be because the directory argument was invalid or, "
  179. "it is valid but has not been processed yet.");
  180. return false;
  181. }
  182. }
  183. // Set or append the property.
  184. const char* name = this->PropertyName.c_str();
  185. if(this->AppendMode)
  186. {
  187. mf->AppendProperty(name, this->PropertyValue.c_str());
  188. }
  189. else
  190. {
  191. mf->SetProperty(name, this->PropertyValue.c_str());
  192. }
  193. return true;
  194. }
  195. //----------------------------------------------------------------------------
  196. bool cmSetPropertyCommand::HandleTargetMode()
  197. {
  198. for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
  199. ni != this->Names.end(); ++ni)
  200. {
  201. if(cmTarget* target = this->Makefile->FindTargetToUse(ni->c_str()))
  202. {
  203. // Handle the current target.
  204. if(!this->HandleTarget(target))
  205. {
  206. return false;
  207. }
  208. }
  209. else
  210. {
  211. cmOStringStream e;
  212. e << "could not find TARGET " << *ni
  213. << ". Perhaps it has not yet been created.";
  214. this->SetError(e.str().c_str());
  215. return false;
  216. }
  217. }
  218. return true;
  219. }
  220. //----------------------------------------------------------------------------
  221. bool cmSetPropertyCommand::HandleTarget(cmTarget* target)
  222. {
  223. // Set or append the property.
  224. const char* name = this->PropertyName.c_str();
  225. if(this->AppendMode)
  226. {
  227. target->AppendProperty(name, this->PropertyValue.c_str());
  228. }
  229. else
  230. {
  231. target->SetProperty(name, this->PropertyValue.c_str());
  232. }
  233. return true;
  234. }
  235. //----------------------------------------------------------------------------
  236. bool cmSetPropertyCommand::HandleSourceMode()
  237. {
  238. for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
  239. ni != this->Names.end(); ++ni)
  240. {
  241. // Get the source file.
  242. if(cmSourceFile* sf = this->Makefile->GetOrCreateSource(ni->c_str()))
  243. {
  244. if(!this->HandleSource(sf))
  245. {
  246. return false;
  247. }
  248. }
  249. else
  250. {
  251. cmOStringStream e;
  252. e << "given SOURCE name that could not be found or created: " << *ni;
  253. this->SetError(e.str().c_str());
  254. return false;
  255. }
  256. }
  257. return true;
  258. }
  259. //----------------------------------------------------------------------------
  260. bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf)
  261. {
  262. // Set or append the property.
  263. const char* name = this->PropertyName.c_str();
  264. if(this->AppendMode)
  265. {
  266. sf->AppendProperty(name, this->PropertyValue.c_str());
  267. }
  268. else
  269. {
  270. sf->SetProperty(name, this->PropertyValue.c_str());
  271. }
  272. return true;
  273. }
  274. //----------------------------------------------------------------------------
  275. bool cmSetPropertyCommand::HandleTestMode()
  276. {
  277. // Loop over all tests looking for matching names.
  278. std::vector<cmTest*> const& tests = *this->Makefile->GetTests();
  279. for(std::vector<cmTest*>::const_iterator ti = tests.begin();
  280. ti != tests.end(); ++ti)
  281. {
  282. cmTest* test = *ti;
  283. std::set<cmStdString>::iterator ni =
  284. this->Names.find(test->GetName());
  285. if(ni != this->Names.end())
  286. {
  287. if(this->HandleTest(test))
  288. {
  289. this->Names.erase(ni);
  290. }
  291. else
  292. {
  293. return false;
  294. }
  295. }
  296. }
  297. // Names that are still left were not found.
  298. if(!this->Names.empty())
  299. {
  300. cmOStringStream e;
  301. e << "given TEST names that do not exist:\n";
  302. for(std::set<cmStdString>::const_iterator ni = this->Names.begin();
  303. ni != this->Names.end(); ++ni)
  304. {
  305. e << " " << *ni << "\n";
  306. }
  307. this->SetError(e.str().c_str());
  308. return false;
  309. }
  310. return true;
  311. }
  312. //----------------------------------------------------------------------------
  313. bool cmSetPropertyCommand::HandleTest(cmTest* test)
  314. {
  315. // Set or append the property.
  316. const char* name = this->PropertyName.c_str();
  317. if(this->AppendMode)
  318. {
  319. test->AppendProperty(name, this->PropertyValue.c_str());
  320. }
  321. else
  322. {
  323. test->SetProperty(name, this->PropertyValue.c_str());
  324. }
  325. return true;
  326. }