cmSetPropertyCommand.cxx 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  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 "cmSetPropertyCommand.h"
  4. #include <set>
  5. #include <sstream>
  6. #include "cmExecutionStatus.h"
  7. #include "cmGlobalGenerator.h"
  8. #include "cmInstalledFile.h"
  9. #include "cmMakefile.h"
  10. #include "cmProperty.h"
  11. #include "cmRange.h"
  12. #include "cmSourceFile.h"
  13. #include "cmState.h"
  14. #include "cmStringAlgorithms.h"
  15. #include "cmSystemTools.h"
  16. #include "cmTarget.h"
  17. #include "cmTest.h"
  18. #include "cmake.h"
  19. namespace {
  20. bool HandleGlobalMode(cmExecutionStatus& status,
  21. const std::set<std::string>& names,
  22. const std::string& propertyName,
  23. const std::string& propertyValue, bool appendAsString,
  24. bool appendMode, bool remove);
  25. bool HandleDirectoryMode(cmExecutionStatus& status,
  26. const std::set<std::string>& names,
  27. const std::string& propertyName,
  28. const std::string& propertyValue, bool appendAsString,
  29. bool appendMode, bool remove);
  30. bool HandleTargetMode(cmExecutionStatus& status,
  31. const std::set<std::string>& names,
  32. const std::string& propertyName,
  33. const std::string& propertyValue, bool appendAsString,
  34. bool appendMode, bool remove);
  35. bool HandleTarget(cmTarget* target, cmMakefile& makefile,
  36. const std::string& propertyName,
  37. const std::string& propertyValue, bool appendAsString,
  38. bool appendMode, bool remove);
  39. bool HandleSourceMode(cmExecutionStatus& status,
  40. const std::set<std::string>& names,
  41. const std::string& propertyName,
  42. const std::string& propertyValue, bool appendAsString,
  43. bool appendMode, bool remove,
  44. const std::vector<cmMakefile*>& directory_makefiles,
  45. bool source_file_paths_should_be_absolute);
  46. bool HandleSource(cmSourceFile* sf, const std::string& propertyName,
  47. const std::string& propertyValue, bool appendAsString,
  48. bool appendMode, bool remove);
  49. bool HandleTestMode(cmExecutionStatus& status, std::set<std::string>& names,
  50. const std::string& propertyName,
  51. const std::string& propertyValue, bool appendAsString,
  52. bool appendMode, bool remove);
  53. bool HandleTest(cmTest* test, const std::string& propertyName,
  54. const std::string& propertyValue, bool appendAsString,
  55. bool appendMode, bool remove);
  56. bool HandleCacheMode(cmExecutionStatus& status,
  57. const std::set<std::string>& names,
  58. const std::string& propertyName,
  59. const std::string& propertyValue, bool appendAsString,
  60. bool appendMode, bool remove);
  61. bool HandleCacheEntry(std::string const& cacheKey, const cmMakefile& makefile,
  62. const std::string& propertyName,
  63. const std::string& propertyValue, bool appendAsString,
  64. bool appendMode, bool remove);
  65. bool HandleInstallMode(cmExecutionStatus& status,
  66. const std::set<std::string>& names,
  67. const std::string& propertyName,
  68. const std::string& propertyValue, bool appendAsString,
  69. bool appendMode, bool remove);
  70. bool HandleInstall(cmInstalledFile* file, cmMakefile& makefile,
  71. const std::string& propertyName,
  72. const std::string& propertyValue, bool appendAsString,
  73. bool appendMode, bool remove);
  74. }
  75. namespace SetPropertyCommand {
  76. bool HandleSourceFileDirectoryScopes(
  77. cmExecutionStatus& status, std::vector<std::string>& source_file_directories,
  78. std::vector<std::string>& source_file_target_directories,
  79. std::vector<cmMakefile*>& directory_makefiles)
  80. {
  81. cmMakefile* current_dir_mf = &status.GetMakefile();
  82. if (!source_file_directories.empty()) {
  83. for (const std::string& dir_path : source_file_directories) {
  84. const std::string absolute_dir_path = cmSystemTools::CollapseFullPath(
  85. dir_path, current_dir_mf->GetCurrentSourceDirectory());
  86. cmMakefile* dir_mf =
  87. status.GetMakefile().GetGlobalGenerator()->FindMakefile(
  88. absolute_dir_path);
  89. if (!dir_mf) {
  90. status.SetError(cmStrCat("given non-existent DIRECTORY ", dir_path));
  91. return false;
  92. }
  93. directory_makefiles.push_back(dir_mf);
  94. }
  95. }
  96. if (!source_file_target_directories.empty()) {
  97. for (const std::string& target_name : source_file_target_directories) {
  98. cmTarget* target = current_dir_mf->FindTargetToUse(target_name);
  99. if (!target) {
  100. status.SetError(cmStrCat(
  101. "given non-existent target for TARGET_DIRECTORY ", target_name));
  102. return false;
  103. }
  104. cmProp target_source_dir = target->GetProperty("SOURCE_DIR");
  105. cmMakefile* target_dir_mf =
  106. status.GetMakefile().GetGlobalGenerator()->FindMakefile(
  107. *target_source_dir);
  108. directory_makefiles.push_back(target_dir_mf);
  109. }
  110. }
  111. if (source_file_directories.empty() &&
  112. source_file_target_directories.empty()) {
  113. directory_makefiles.push_back(current_dir_mf);
  114. }
  115. return true;
  116. }
  117. bool HandleSourceFileDirectoryScopeValidation(
  118. cmExecutionStatus& status, bool source_file_directory_option_enabled,
  119. bool source_file_target_option_enabled,
  120. std::vector<std::string>& source_file_directories,
  121. std::vector<std::string>& source_file_target_directories)
  122. {
  123. // Validate source file directory scopes.
  124. if (source_file_directory_option_enabled &&
  125. source_file_directories.empty()) {
  126. std::string errors = "called with incorrect number of arguments "
  127. "no value provided to the DIRECTORY option";
  128. status.SetError(errors);
  129. return false;
  130. }
  131. if (source_file_target_option_enabled &&
  132. source_file_target_directories.empty()) {
  133. std::string errors = "called with incorrect number of arguments "
  134. "no value provided to the TARGET_DIRECTORY option";
  135. status.SetError(errors);
  136. return false;
  137. }
  138. return true;
  139. }
  140. bool HandleAndValidateSourceFileDirectortoryScopes(
  141. cmExecutionStatus& status, bool source_file_directory_option_enabled,
  142. bool source_file_target_option_enabled,
  143. std::vector<std::string>& source_file_directories,
  144. std::vector<std::string>& source_file_target_directories,
  145. std::vector<cmMakefile*>& source_file_directory_makefiles)
  146. {
  147. bool scope_options_valid =
  148. SetPropertyCommand::HandleSourceFileDirectoryScopeValidation(
  149. status, source_file_directory_option_enabled,
  150. source_file_target_option_enabled, source_file_directories,
  151. source_file_target_directories);
  152. if (!scope_options_valid) {
  153. return false;
  154. }
  155. scope_options_valid = SetPropertyCommand::HandleSourceFileDirectoryScopes(
  156. status, source_file_directories, source_file_target_directories,
  157. source_file_directory_makefiles);
  158. return scope_options_valid;
  159. }
  160. std::string MakeSourceFilePathAbsoluteIfNeeded(
  161. cmExecutionStatus& status, const std::string& source_file_path,
  162. const bool needed)
  163. {
  164. if (!needed) {
  165. return source_file_path;
  166. }
  167. const std::string absolute_file_path = cmSystemTools::CollapseFullPath(
  168. source_file_path, status.GetMakefile().GetCurrentSourceDirectory());
  169. return absolute_file_path;
  170. }
  171. void MakeSourceFilePathsAbsoluteIfNeeded(
  172. cmExecutionStatus& status,
  173. std::vector<std::string>& source_files_absolute_paths,
  174. std::vector<std::string>::const_iterator files_it_begin,
  175. std::vector<std::string>::const_iterator files_it_end, const bool needed)
  176. {
  177. // Make the file paths absolute, so that relative source file paths are
  178. // picked up relative to the command calling site, regardless of the
  179. // directory scope.
  180. std::vector<std::string>::difference_type num_files =
  181. files_it_end - files_it_begin;
  182. source_files_absolute_paths.reserve(num_files);
  183. if (!needed) {
  184. source_files_absolute_paths.assign(files_it_begin, files_it_end);
  185. return;
  186. }
  187. for (; files_it_begin != files_it_end; ++files_it_begin) {
  188. const std::string absolute_file_path =
  189. MakeSourceFilePathAbsoluteIfNeeded(status, *files_it_begin, true);
  190. source_files_absolute_paths.push_back(absolute_file_path);
  191. }
  192. }
  193. }
  194. bool cmSetPropertyCommand(std::vector<std::string> const& args,
  195. cmExecutionStatus& status)
  196. {
  197. if (args.size() < 2) {
  198. status.SetError("called with incorrect number of arguments");
  199. return false;
  200. }
  201. // Get the scope on which to set the property.
  202. std::string const& scopeName = args.front();
  203. cmProperty::ScopeType scope;
  204. if (scopeName == "GLOBAL") {
  205. scope = cmProperty::GLOBAL;
  206. } else if (scopeName == "DIRECTORY") {
  207. scope = cmProperty::DIRECTORY;
  208. } else if (scopeName == "TARGET") {
  209. scope = cmProperty::TARGET;
  210. } else if (scopeName == "SOURCE") {
  211. scope = cmProperty::SOURCE_FILE;
  212. } else if (scopeName == "TEST") {
  213. scope = cmProperty::TEST;
  214. } else if (scopeName == "CACHE") {
  215. scope = cmProperty::CACHE;
  216. } else if (scopeName == "INSTALL") {
  217. scope = cmProperty::INSTALL;
  218. } else {
  219. status.SetError(cmStrCat("given invalid scope ", scopeName,
  220. ". "
  221. "Valid scopes are GLOBAL, DIRECTORY, "
  222. "TARGET, SOURCE, TEST, CACHE, INSTALL."));
  223. return false;
  224. }
  225. bool appendAsString = false;
  226. bool appendMode = false;
  227. bool remove = true;
  228. std::set<std::string> names;
  229. std::string propertyName;
  230. std::string propertyValue;
  231. std::vector<std::string> source_file_directories;
  232. std::vector<std::string> source_file_target_directories;
  233. bool source_file_directory_option_enabled = false;
  234. bool source_file_target_option_enabled = false;
  235. // Parse the rest of the arguments up to the values.
  236. enum Doing
  237. {
  238. DoingNone,
  239. DoingNames,
  240. DoingProperty,
  241. DoingValues,
  242. DoingSourceDirectory,
  243. DoingSourceTargetDirectory
  244. };
  245. Doing doing = DoingNames;
  246. const char* sep = "";
  247. for (std::string const& arg : cmMakeRange(args).advance(1)) {
  248. if (arg == "PROPERTY") {
  249. doing = DoingProperty;
  250. } else if (arg == "APPEND") {
  251. doing = DoingNone;
  252. appendMode = true;
  253. remove = false;
  254. appendAsString = false;
  255. } else if (arg == "APPEND_STRING") {
  256. doing = DoingNone;
  257. appendMode = true;
  258. remove = false;
  259. appendAsString = true;
  260. } else if (doing != DoingProperty && doing != DoingValues &&
  261. scope == cmProperty::SOURCE_FILE && arg == "DIRECTORY") {
  262. doing = DoingSourceDirectory;
  263. source_file_directory_option_enabled = true;
  264. } else if (doing != DoingProperty && doing != DoingValues &&
  265. scope == cmProperty::SOURCE_FILE && arg == "TARGET_DIRECTORY") {
  266. doing = DoingSourceTargetDirectory;
  267. source_file_target_option_enabled = true;
  268. } else if (doing == DoingNames) {
  269. names.insert(arg);
  270. } else if (doing == DoingSourceDirectory) {
  271. source_file_directories.push_back(arg);
  272. } else if (doing == DoingSourceTargetDirectory) {
  273. source_file_target_directories.push_back(arg);
  274. } else if (doing == DoingProperty) {
  275. propertyName = arg;
  276. doing = DoingValues;
  277. } else if (doing == DoingValues) {
  278. propertyValue += sep;
  279. sep = ";";
  280. propertyValue += arg;
  281. remove = false;
  282. } else {
  283. status.SetError(cmStrCat("given invalid argument \"", arg, "\"."));
  284. return false;
  285. }
  286. }
  287. // Make sure a property name was found.
  288. if (propertyName.empty()) {
  289. status.SetError("not given a PROPERTY <name> argument.");
  290. return false;
  291. }
  292. std::vector<cmMakefile*> source_file_directory_makefiles;
  293. bool file_scopes_handled =
  294. SetPropertyCommand::HandleAndValidateSourceFileDirectortoryScopes(
  295. status, source_file_directory_option_enabled,
  296. source_file_target_option_enabled, source_file_directories,
  297. source_file_target_directories, source_file_directory_makefiles);
  298. if (!file_scopes_handled) {
  299. return false;
  300. }
  301. bool source_file_paths_should_be_absolute =
  302. source_file_directory_option_enabled || source_file_target_option_enabled;
  303. // Dispatch property setting.
  304. switch (scope) {
  305. case cmProperty::GLOBAL:
  306. return HandleGlobalMode(status, names, propertyName, propertyValue,
  307. appendAsString, appendMode, remove);
  308. case cmProperty::DIRECTORY:
  309. return HandleDirectoryMode(status, names, propertyName, propertyValue,
  310. appendAsString, appendMode, remove);
  311. case cmProperty::TARGET:
  312. return HandleTargetMode(status, names, propertyName, propertyValue,
  313. appendAsString, appendMode, remove);
  314. case cmProperty::SOURCE_FILE:
  315. return HandleSourceMode(status, names, propertyName, propertyValue,
  316. appendAsString, appendMode, remove,
  317. source_file_directory_makefiles,
  318. source_file_paths_should_be_absolute);
  319. case cmProperty::TEST:
  320. return HandleTestMode(status, names, propertyName, propertyValue,
  321. appendAsString, appendMode, remove);
  322. case cmProperty::CACHE:
  323. return HandleCacheMode(status, names, propertyName, propertyValue,
  324. appendAsString, appendMode, remove);
  325. case cmProperty::INSTALL:
  326. return HandleInstallMode(status, names, propertyName, propertyValue,
  327. appendAsString, appendMode, remove);
  328. case cmProperty::VARIABLE:
  329. case cmProperty::CACHED_VARIABLE:
  330. break; // should never happen
  331. }
  332. return true;
  333. }
  334. namespace {
  335. bool HandleGlobalMode(cmExecutionStatus& status,
  336. const std::set<std::string>& names,
  337. const std::string& propertyName,
  338. const std::string& propertyValue, bool appendAsString,
  339. bool appendMode, bool remove)
  340. {
  341. if (!names.empty()) {
  342. status.SetError("given names for GLOBAL scope.");
  343. return false;
  344. }
  345. // Set or append the property.
  346. cmake* cm = status.GetMakefile().GetCMakeInstance();
  347. if (appendMode) {
  348. cm->AppendProperty(propertyName, propertyValue, appendAsString);
  349. } else {
  350. if (remove) {
  351. cm->SetProperty(propertyName, nullptr);
  352. } else {
  353. cm->SetProperty(propertyName, propertyValue.c_str());
  354. }
  355. }
  356. return true;
  357. }
  358. bool HandleDirectoryMode(cmExecutionStatus& status,
  359. const std::set<std::string>& names,
  360. const std::string& propertyName,
  361. const std::string& propertyValue, bool appendAsString,
  362. bool appendMode, bool remove)
  363. {
  364. if (names.size() > 1) {
  365. status.SetError("allows at most one name for DIRECTORY scope.");
  366. return false;
  367. }
  368. // Default to the current directory.
  369. cmMakefile* mf = &status.GetMakefile();
  370. // Lookup the directory if given.
  371. if (!names.empty()) {
  372. // Construct the directory name. Interpret relative paths with
  373. // respect to the current directory.
  374. std::string dir = cmSystemTools::CollapseFullPath(
  375. *names.begin(), status.GetMakefile().GetCurrentSourceDirectory());
  376. mf = status.GetMakefile().GetGlobalGenerator()->FindMakefile(dir);
  377. if (!mf) {
  378. // Could not find the directory.
  379. status.SetError(
  380. "DIRECTORY scope provided but requested directory was not found. "
  381. "This could be because the directory argument was invalid or, "
  382. "it is valid but has not been processed yet.");
  383. return false;
  384. }
  385. }
  386. // Set or append the property.
  387. if (appendMode) {
  388. mf->AppendProperty(propertyName, propertyValue, appendAsString);
  389. } else {
  390. if (remove) {
  391. mf->SetProperty(propertyName, nullptr);
  392. } else {
  393. mf->SetProperty(propertyName, propertyValue.c_str());
  394. }
  395. }
  396. return true;
  397. }
  398. bool HandleTargetMode(cmExecutionStatus& status,
  399. const std::set<std::string>& names,
  400. const std::string& propertyName,
  401. const std::string& propertyValue, bool appendAsString,
  402. bool appendMode, bool remove)
  403. {
  404. for (std::string const& name : names) {
  405. if (status.GetMakefile().IsAlias(name)) {
  406. status.SetError("can not be used on an ALIAS target.");
  407. return false;
  408. }
  409. if (cmTarget* target = status.GetMakefile().FindTargetToUse(name)) {
  410. // Handle the current target.
  411. if (!HandleTarget(target, status.GetMakefile(), propertyName,
  412. propertyValue, appendAsString, appendMode, remove)) {
  413. return false;
  414. }
  415. } else {
  416. status.SetError(cmStrCat("could not find TARGET ", name,
  417. ". Perhaps it has not yet been created."));
  418. return false;
  419. }
  420. }
  421. return true;
  422. }
  423. bool HandleTarget(cmTarget* target, cmMakefile& makefile,
  424. const std::string& propertyName,
  425. const std::string& propertyValue, bool appendAsString,
  426. bool appendMode, bool remove)
  427. {
  428. // Set or append the property.
  429. if (appendMode) {
  430. target->AppendProperty(propertyName, propertyValue, appendAsString);
  431. } else {
  432. if (remove) {
  433. target->SetProperty(propertyName, nullptr);
  434. } else {
  435. target->SetProperty(propertyName, propertyValue);
  436. }
  437. }
  438. // Check the resulting value.
  439. target->CheckProperty(propertyName, &makefile);
  440. return true;
  441. }
  442. bool HandleSourceMode(cmExecutionStatus& status,
  443. const std::set<std::string>& names,
  444. const std::string& propertyName,
  445. const std::string& propertyValue, bool appendAsString,
  446. bool appendMode, bool remove,
  447. const std::vector<cmMakefile*>& directory_makefiles,
  448. const bool source_file_paths_should_be_absolute)
  449. {
  450. std::vector<std::string> files_absolute;
  451. std::vector<std::string> unique_files(names.begin(), names.end());
  452. SetPropertyCommand::MakeSourceFilePathsAbsoluteIfNeeded(
  453. status, files_absolute, unique_files.begin(), unique_files.end(),
  454. source_file_paths_should_be_absolute);
  455. for (const auto mf : directory_makefiles) {
  456. for (std::string const& name : files_absolute) {
  457. // Get the source file.
  458. if (cmSourceFile* sf = mf->GetOrCreateSource(name)) {
  459. if (!HandleSource(sf, propertyName, propertyValue, appendAsString,
  460. appendMode, remove)) {
  461. return false;
  462. }
  463. } else {
  464. status.SetError(cmStrCat(
  465. "given SOURCE name that could not be found or created: ", name));
  466. return false;
  467. }
  468. }
  469. }
  470. return true;
  471. }
  472. bool HandleSource(cmSourceFile* sf, const std::string& propertyName,
  473. const std::string& propertyValue, bool appendAsString,
  474. bool appendMode, bool remove)
  475. {
  476. // Set or append the property.
  477. if (appendMode) {
  478. sf->AppendProperty(propertyName, propertyValue, appendAsString);
  479. } else {
  480. if (remove) {
  481. sf->SetProperty(propertyName, nullptr);
  482. } else {
  483. sf->SetProperty(propertyName, propertyValue.c_str());
  484. }
  485. }
  486. return true;
  487. }
  488. bool HandleTestMode(cmExecutionStatus& status, std::set<std::string>& names,
  489. const std::string& propertyName,
  490. const std::string& propertyValue, bool appendAsString,
  491. bool appendMode, bool remove)
  492. {
  493. // Look for tests with all names given.
  494. std::set<std::string>::iterator next;
  495. for (auto ni = names.begin(); ni != names.end(); ni = next) {
  496. next = ni;
  497. ++next;
  498. if (cmTest* test = status.GetMakefile().GetTest(*ni)) {
  499. if (HandleTest(test, propertyName, propertyValue, appendAsString,
  500. appendMode, remove)) {
  501. names.erase(ni);
  502. } else {
  503. return false;
  504. }
  505. }
  506. }
  507. // Names that are still left were not found.
  508. if (!names.empty()) {
  509. std::ostringstream e;
  510. e << "given TEST names that do not exist:\n";
  511. for (std::string const& name : names) {
  512. e << " " << name << "\n";
  513. }
  514. status.SetError(e.str());
  515. return false;
  516. }
  517. return true;
  518. }
  519. bool HandleTest(cmTest* test, const std::string& propertyName,
  520. const std::string& propertyValue, bool appendAsString,
  521. bool appendMode, bool remove)
  522. {
  523. // Set or append the property.
  524. if (appendMode) {
  525. test->AppendProperty(propertyName, propertyValue, appendAsString);
  526. } else {
  527. if (remove) {
  528. test->SetProperty(propertyName, nullptr);
  529. } else {
  530. test->SetProperty(propertyName, propertyValue.c_str());
  531. }
  532. }
  533. return true;
  534. }
  535. bool HandleCacheMode(cmExecutionStatus& status,
  536. const std::set<std::string>& names,
  537. const std::string& propertyName,
  538. const std::string& propertyValue, bool appendAsString,
  539. bool appendMode, bool remove)
  540. {
  541. if (propertyName == "ADVANCED") {
  542. if (!remove && !cmIsOn(propertyValue) && !cmIsOff(propertyValue)) {
  543. status.SetError(cmStrCat("given non-boolean value \"", propertyValue,
  544. R"(" for CACHE property "ADVANCED". )"));
  545. return false;
  546. }
  547. } else if (propertyName == "TYPE") {
  548. if (!cmState::IsCacheEntryType(propertyValue)) {
  549. status.SetError(
  550. cmStrCat("given invalid CACHE entry TYPE \"", propertyValue, "\""));
  551. return false;
  552. }
  553. } else if (propertyName != "HELPSTRING" && propertyName != "STRINGS" &&
  554. propertyName != "VALUE") {
  555. status.SetError(
  556. cmStrCat("given invalid CACHE property ", propertyName,
  557. ". "
  558. "Settable CACHE properties are: "
  559. "ADVANCED, HELPSTRING, STRINGS, TYPE, and VALUE."));
  560. return false;
  561. }
  562. for (std::string const& name : names) {
  563. // Get the source file.
  564. cmake* cm = status.GetMakefile().GetCMakeInstance();
  565. cmProp existingValue = cm->GetState()->GetCacheEntryValue(name);
  566. if (existingValue) {
  567. if (!HandleCacheEntry(name, status.GetMakefile(), propertyName,
  568. propertyValue, appendAsString, appendMode,
  569. remove)) {
  570. return false;
  571. }
  572. } else {
  573. status.SetError(cmStrCat("could not find CACHE variable ", name,
  574. ". Perhaps it has not yet been created."));
  575. return false;
  576. }
  577. }
  578. return true;
  579. }
  580. bool HandleCacheEntry(std::string const& cacheKey, const cmMakefile& makefile,
  581. const std::string& propertyName,
  582. const std::string& propertyValue, bool appendAsString,
  583. bool appendMode, bool remove)
  584. {
  585. // Set or append the property.
  586. cmState* state = makefile.GetState();
  587. if (remove) {
  588. state->RemoveCacheEntryProperty(cacheKey, propertyName);
  589. }
  590. if (appendMode) {
  591. state->AppendCacheEntryProperty(cacheKey, propertyName, propertyValue,
  592. appendAsString);
  593. } else {
  594. state->SetCacheEntryProperty(cacheKey, propertyName, propertyValue);
  595. }
  596. return true;
  597. }
  598. bool HandleInstallMode(cmExecutionStatus& status,
  599. const std::set<std::string>& names,
  600. const std::string& propertyName,
  601. const std::string& propertyValue, bool appendAsString,
  602. bool appendMode, bool remove)
  603. {
  604. cmake* cm = status.GetMakefile().GetCMakeInstance();
  605. for (std::string const& name : names) {
  606. if (cmInstalledFile* file =
  607. cm->GetOrCreateInstalledFile(&status.GetMakefile(), name)) {
  608. if (!HandleInstall(file, status.GetMakefile(), propertyName,
  609. propertyValue, appendAsString, appendMode, remove)) {
  610. return false;
  611. }
  612. } else {
  613. status.SetError(cmStrCat(
  614. "given INSTALL name that could not be found or created: ", name));
  615. return false;
  616. }
  617. }
  618. return true;
  619. }
  620. bool HandleInstall(cmInstalledFile* file, cmMakefile& makefile,
  621. const std::string& propertyName,
  622. const std::string& propertyValue, bool appendAsString,
  623. bool appendMode, bool remove)
  624. {
  625. // Set or append the property.
  626. if (remove) {
  627. file->RemoveProperty(propertyName);
  628. } else if (appendMode) {
  629. file->AppendProperty(&makefile, propertyName, propertyValue,
  630. appendAsString);
  631. } else {
  632. file->SetProperty(&makefile, propertyName, propertyValue);
  633. }
  634. return true;
  635. }
  636. }