cmSetPropertyCommand.cxx 24 KB

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