cmSetPropertyCommand.cxx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  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 "cmSetPropertyCommand.h"
  11. #include "cmSetTargetPropertiesCommand.h"
  12. #include "cmSetTestsPropertiesCommand.h"
  13. #include "cmSetSourceFilesPropertiesCommand.h"
  14. #include "cmCacheManager.h"
  15. //----------------------------------------------------------------------------
  16. cmSetPropertyCommand::cmSetPropertyCommand()
  17. {
  18. this->AppendMode = false;
  19. this->AppendAsString = false;
  20. this->Remove = true;
  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 if(*arg == "CACHE")
  55. {
  56. scope = cmProperty::CACHE;
  57. }
  58. else if(*arg == "INSTALL")
  59. {
  60. scope = cmProperty::INSTALL;
  61. }
  62. else
  63. {
  64. std::ostringstream e;
  65. e << "given invalid scope " << *arg << ". "
  66. << "Valid scopes are GLOBAL, DIRECTORY, "
  67. "TARGET, SOURCE, TEST, CACHE, INSTALL.";
  68. this->SetError(e.str());
  69. return false;
  70. }
  71. // Parse the rest of the arguments up to the values.
  72. enum Doing { DoingNone, DoingNames, DoingProperty, DoingValues };
  73. Doing doing = DoingNames;
  74. const char* sep = "";
  75. for(++arg; arg != args.end(); ++arg)
  76. {
  77. if(*arg == "PROPERTY")
  78. {
  79. doing = DoingProperty;
  80. }
  81. else if(*arg == "APPEND")
  82. {
  83. doing = DoingNone;
  84. this->AppendMode = true;
  85. this->Remove = false;
  86. this->AppendAsString = false;
  87. }
  88. else if(*arg == "APPEND_STRING")
  89. {
  90. doing = DoingNone;
  91. this->AppendMode = true;
  92. this->Remove = false;
  93. this->AppendAsString = true;
  94. }
  95. else if(doing == DoingNames)
  96. {
  97. this->Names.insert(*arg);
  98. }
  99. else if(doing == DoingProperty)
  100. {
  101. this->PropertyName = *arg;
  102. doing = DoingValues;
  103. }
  104. else if(doing == DoingValues)
  105. {
  106. this->PropertyValue += sep;
  107. sep = ";";
  108. this->PropertyValue += *arg;
  109. this->Remove = false;
  110. }
  111. else
  112. {
  113. std::ostringstream e;
  114. e << "given invalid argument \"" << *arg << "\".";
  115. this->SetError(e.str());
  116. return false;
  117. }
  118. }
  119. // Make sure a property name was found.
  120. if(this->PropertyName.empty())
  121. {
  122. this->SetError("not given a PROPERTY <name> argument.");
  123. return false;
  124. }
  125. // Dispatch property setting.
  126. switch(scope)
  127. {
  128. case cmProperty::GLOBAL: return this->HandleGlobalMode();
  129. case cmProperty::DIRECTORY: return this->HandleDirectoryMode();
  130. case cmProperty::TARGET: return this->HandleTargetMode();
  131. case cmProperty::SOURCE_FILE: return this->HandleSourceMode();
  132. case cmProperty::TEST: return this->HandleTestMode();
  133. case cmProperty::CACHE: return this->HandleCacheMode();
  134. case cmProperty::INSTALL: return this->HandleInstallMode();
  135. case cmProperty::VARIABLE:
  136. case cmProperty::CACHED_VARIABLE:
  137. break; // should never happen
  138. }
  139. return true;
  140. }
  141. //----------------------------------------------------------------------------
  142. bool cmSetPropertyCommand::HandleGlobalMode()
  143. {
  144. if(!this->Names.empty())
  145. {
  146. this->SetError("given names for GLOBAL scope.");
  147. return false;
  148. }
  149. // Set or append the property.
  150. cmake* cm = this->Makefile->GetCMakeInstance();
  151. const char* name = this->PropertyName.c_str();
  152. const char *value = this->PropertyValue.c_str();
  153. if (this->Remove)
  154. {
  155. value = 0;
  156. }
  157. if(this->AppendMode)
  158. {
  159. cm->AppendProperty(name, value ? value : "", this->AppendAsString);
  160. }
  161. else
  162. {
  163. cm->SetProperty(name, value);
  164. }
  165. return true;
  166. }
  167. //----------------------------------------------------------------------------
  168. bool cmSetPropertyCommand::HandleDirectoryMode()
  169. {
  170. if(this->Names.size() > 1)
  171. {
  172. this->SetError("allows at most one name for DIRECTORY scope.");
  173. return false;
  174. }
  175. // Default to the current directory.
  176. cmMakefile* mf = this->Makefile;
  177. // Lookup the directory if given.
  178. if(!this->Names.empty())
  179. {
  180. // Construct the directory name. Interpret relative paths with
  181. // respect to the current directory.
  182. std::string dir = *this->Names.begin();
  183. if(!cmSystemTools::FileIsFullPath(dir.c_str()))
  184. {
  185. dir = this->Makefile->GetCurrentDirectory();
  186. dir += "/";
  187. dir += *this->Names.begin();
  188. }
  189. // The local generators are associated with collapsed paths.
  190. dir = cmSystemTools::CollapseFullPath(dir);
  191. // Lookup the generator.
  192. if(cmLocalGenerator* lg =
  193. (this->Makefile->GetLocalGenerator()
  194. ->GetGlobalGenerator()->FindLocalGenerator(dir)))
  195. {
  196. // Use the makefile for the directory found.
  197. mf = lg->GetMakefile();
  198. }
  199. else
  200. {
  201. // Could not find the directory.
  202. this->SetError
  203. ("DIRECTORY scope provided but requested directory was not found. "
  204. "This could be because the directory argument was invalid or, "
  205. "it is valid but has not been processed yet.");
  206. return false;
  207. }
  208. }
  209. // Set or append the property.
  210. const char* name = this->PropertyName.c_str();
  211. const char *value = this->PropertyValue.c_str();
  212. if (this->Remove)
  213. {
  214. value = 0;
  215. }
  216. if(this->AppendMode)
  217. {
  218. mf->AppendProperty(name, value ? value : "", this->AppendAsString);
  219. }
  220. else
  221. {
  222. mf->SetProperty(name, value);
  223. }
  224. return true;
  225. }
  226. //----------------------------------------------------------------------------
  227. bool cmSetPropertyCommand::HandleTargetMode()
  228. {
  229. for(std::set<std::string>::const_iterator ni = this->Names.begin();
  230. ni != this->Names.end(); ++ni)
  231. {
  232. if (this->Makefile->IsAlias(*ni))
  233. {
  234. this->SetError("can not be used on an ALIAS target.");
  235. return false;
  236. }
  237. if(cmTarget* target = this->Makefile->FindTargetToUse(*ni))
  238. {
  239. // Handle the current target.
  240. if(!this->HandleTarget(target))
  241. {
  242. return false;
  243. }
  244. }
  245. else
  246. {
  247. std::ostringstream e;
  248. e << "could not find TARGET " << *ni
  249. << ". Perhaps it has not yet been created.";
  250. this->SetError(e.str());
  251. return false;
  252. }
  253. }
  254. return true;
  255. }
  256. //----------------------------------------------------------------------------
  257. bool cmSetPropertyCommand::HandleTarget(cmTarget* target)
  258. {
  259. // Set or append the property.
  260. const char* name = this->PropertyName.c_str();
  261. const char *value = this->PropertyValue.c_str();
  262. if (this->Remove)
  263. {
  264. value = 0;
  265. }
  266. if(this->AppendMode)
  267. {
  268. target->AppendProperty(name, value, this->AppendAsString);
  269. }
  270. else
  271. {
  272. target->SetProperty(name, value);
  273. }
  274. // Check the resulting value.
  275. target->CheckProperty(name, this->Makefile);
  276. return true;
  277. }
  278. //----------------------------------------------------------------------------
  279. bool cmSetPropertyCommand::HandleSourceMode()
  280. {
  281. for(std::set<std::string>::const_iterator ni = this->Names.begin();
  282. ni != this->Names.end(); ++ni)
  283. {
  284. // Get the source file.
  285. if(cmSourceFile* sf = this->Makefile->GetOrCreateSource(*ni))
  286. {
  287. if(!this->HandleSource(sf))
  288. {
  289. return false;
  290. }
  291. }
  292. else
  293. {
  294. std::ostringstream e;
  295. e << "given SOURCE name that could not be found or created: " << *ni;
  296. this->SetError(e.str());
  297. return false;
  298. }
  299. }
  300. return true;
  301. }
  302. //----------------------------------------------------------------------------
  303. bool cmSetPropertyCommand::HandleSource(cmSourceFile* sf)
  304. {
  305. // Set or append the property.
  306. const char* name = this->PropertyName.c_str();
  307. const char *value = this->PropertyValue.c_str();
  308. if (this->Remove)
  309. {
  310. value = 0;
  311. }
  312. if(this->AppendMode)
  313. {
  314. sf->AppendProperty(name, value, this->AppendAsString);
  315. }
  316. else
  317. {
  318. sf->SetProperty(name, value);
  319. }
  320. return true;
  321. }
  322. //----------------------------------------------------------------------------
  323. bool cmSetPropertyCommand::HandleTestMode()
  324. {
  325. // Look for tests with all names given.
  326. std::set<std::string>::iterator next;
  327. for(std::set<std::string>::iterator ni = this->Names.begin();
  328. ni != this->Names.end(); ni = next)
  329. {
  330. next = ni;
  331. ++next;
  332. if(cmTest* test = this->Makefile->GetTest(*ni))
  333. {
  334. if(this->HandleTest(test))
  335. {
  336. this->Names.erase(ni);
  337. }
  338. else
  339. {
  340. return false;
  341. }
  342. }
  343. }
  344. // Names that are still left were not found.
  345. if(!this->Names.empty())
  346. {
  347. std::ostringstream e;
  348. e << "given TEST names that do not exist:\n";
  349. for(std::set<std::string>::const_iterator ni = this->Names.begin();
  350. ni != this->Names.end(); ++ni)
  351. {
  352. e << " " << *ni << "\n";
  353. }
  354. this->SetError(e.str());
  355. return false;
  356. }
  357. return true;
  358. }
  359. //----------------------------------------------------------------------------
  360. bool cmSetPropertyCommand::HandleTest(cmTest* test)
  361. {
  362. // Set or append the property.
  363. const char* name = this->PropertyName.c_str();
  364. const char *value = this->PropertyValue.c_str();
  365. if (this->Remove)
  366. {
  367. value = 0;
  368. }
  369. if(this->AppendMode)
  370. {
  371. test->AppendProperty(name, value, this->AppendAsString);
  372. }
  373. else
  374. {
  375. test->SetProperty(name, value);
  376. }
  377. return true;
  378. }
  379. //----------------------------------------------------------------------------
  380. bool cmSetPropertyCommand::HandleCacheMode()
  381. {
  382. if(this->PropertyName == "ADVANCED")
  383. {
  384. if(!this->Remove &&
  385. !cmSystemTools::IsOn(this->PropertyValue.c_str()) &&
  386. !cmSystemTools::IsOff(this->PropertyValue.c_str()))
  387. {
  388. std::ostringstream e;
  389. e << "given non-boolean value \"" << this->PropertyValue
  390. << "\" for CACHE property \"ADVANCED\". ";
  391. this->SetError(e.str());
  392. return false;
  393. }
  394. }
  395. else if(this->PropertyName == "TYPE")
  396. {
  397. if(!cmCacheManager::IsType(this->PropertyValue.c_str()))
  398. {
  399. std::ostringstream e;
  400. e << "given invalid CACHE entry TYPE \"" << this->PropertyValue << "\"";
  401. this->SetError(e.str());
  402. return false;
  403. }
  404. }
  405. else if(this->PropertyName != "HELPSTRING" &&
  406. this->PropertyName != "STRINGS" &&
  407. this->PropertyName != "VALUE")
  408. {
  409. std::ostringstream e;
  410. e << "given invalid CACHE property " << this->PropertyName << ". "
  411. << "Settable CACHE properties are: "
  412. << "ADVANCED, HELPSTRING, STRINGS, TYPE, and VALUE.";
  413. this->SetError(e.str());
  414. return false;
  415. }
  416. for(std::set<std::string>::const_iterator ni = this->Names.begin();
  417. ni != this->Names.end(); ++ni)
  418. {
  419. // Get the source file.
  420. cmMakefile* mf = this->GetMakefile();
  421. cmake* cm = mf->GetCMakeInstance();
  422. const char* existingValue
  423. = cm->GetCacheManager()->GetCacheEntryValue(*ni);
  424. if(existingValue)
  425. {
  426. if(!this->HandleCacheEntry(*ni))
  427. {
  428. return false;
  429. }
  430. }
  431. else
  432. {
  433. std::ostringstream e;
  434. e << "could not find CACHE variable " << *ni
  435. << ". Perhaps it has not yet been created.";
  436. this->SetError(e.str());
  437. return false;
  438. }
  439. }
  440. return true;
  441. }
  442. //----------------------------------------------------------------------------
  443. bool cmSetPropertyCommand::HandleCacheEntry(std::string const& cacheKey)
  444. {
  445. // Set or append the property.
  446. const char* name = this->PropertyName.c_str();
  447. const char* value = this->PropertyValue.c_str();
  448. cmCacheManager* manager = this->Makefile->GetCacheManager();
  449. if (this->Remove)
  450. {
  451. manager->RemoveCacheEntryProperty(cacheKey, name);
  452. return true;
  453. }
  454. if(this->AppendMode)
  455. {
  456. manager->AppendCacheEntryProperty(cacheKey, name, value,
  457. this->AppendAsString);
  458. }
  459. else
  460. {
  461. manager->SetCacheEntryProperty(cacheKey, name, value);
  462. }
  463. return true;
  464. }
  465. //----------------------------------------------------------------------------
  466. bool cmSetPropertyCommand::HandleInstallMode()
  467. {
  468. cmake* cm = this->Makefile->GetCMakeInstance();
  469. for(std::set<std::string>::const_iterator i = this->Names.begin();
  470. i != this->Names.end(); ++i)
  471. {
  472. if(cmInstalledFile* file = cm->GetOrCreateInstalledFile(
  473. this->Makefile, *i))
  474. {
  475. if(!this->HandleInstall(file))
  476. {
  477. return false;
  478. }
  479. }
  480. else
  481. {
  482. std::ostringstream e;
  483. e << "given INSTALL name that could not be found or created: " << *i;
  484. this->SetError(e.str());
  485. return false;
  486. }
  487. }
  488. return true;
  489. }
  490. //----------------------------------------------------------------------------
  491. bool cmSetPropertyCommand::HandleInstall(cmInstalledFile* file)
  492. {
  493. // Set or append the property.
  494. std::string const& name = this->PropertyName;
  495. cmMakefile* mf = this->Makefile;
  496. const char *value = this->PropertyValue.c_str();
  497. if (this->Remove)
  498. {
  499. file->RemoveProperty(name);
  500. }
  501. else if(this->AppendMode)
  502. {
  503. file->AppendProperty(mf, name, value, this->AppendAsString);
  504. }
  505. else
  506. {
  507. file->SetProperty(mf, name, value);
  508. }
  509. return true;
  510. }