cmInstallCommand.cxx 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170
  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 "cmInstallCommand.h"
  14. #include "cmInstallDirectoryGenerator.h"
  15. #include "cmInstallFilesGenerator.h"
  16. #include "cmInstallScriptGenerator.h"
  17. #include "cmInstallTargetGenerator.h"
  18. #include <cmsys/Glob.hxx>
  19. // cmInstallCommand
  20. bool cmInstallCommand::InitialPass(std::vector<std::string> const& args)
  21. {
  22. // Allow calling with no arguments so that arguments may be built up
  23. // using a variable that may be left empty.
  24. if(args.empty())
  25. {
  26. return true;
  27. }
  28. // Enable the install target.
  29. this->Makefile->GetLocalGenerator()
  30. ->GetGlobalGenerator()->EnableInstallTarget();
  31. // Switch among the command modes.
  32. if(args[0] == "SCRIPT")
  33. {
  34. return this->HandleScriptMode(args);
  35. }
  36. else if(args[0] == "CODE")
  37. {
  38. return this->HandleScriptMode(args);
  39. }
  40. else if(args[0] == "TARGETS")
  41. {
  42. return this->HandleTargetsMode(args);
  43. }
  44. else if(args[0] == "FILES")
  45. {
  46. return this->HandleFilesMode(args);
  47. }
  48. else if(args[0] == "PROGRAMS")
  49. {
  50. return this->HandleFilesMode(args);
  51. }
  52. else if(args[0] == "DIRECTORY")
  53. {
  54. return this->HandleDirectoryMode(args);
  55. }
  56. // Unknown mode.
  57. cmStdString e = "called with unknown mode ";
  58. e += args[0];
  59. this->SetError(e.c_str());
  60. return false;
  61. }
  62. //----------------------------------------------------------------------------
  63. bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
  64. {
  65. bool doing_script = false;
  66. bool doing_code = false;
  67. for(size_t i=0; i < args.size(); ++i)
  68. {
  69. if(args[i] == "SCRIPT")
  70. {
  71. doing_script = true;
  72. doing_code = false;
  73. }
  74. else if(args[i] == "CODE")
  75. {
  76. doing_script = false;
  77. doing_code = true;
  78. }
  79. else if(doing_script)
  80. {
  81. doing_script = false;
  82. std::string script = args[i];
  83. if(!cmSystemTools::FileIsFullPath(script.c_str()))
  84. {
  85. script = this->Makefile->GetCurrentDirectory();
  86. script += "/";
  87. script += args[i];
  88. }
  89. if(cmSystemTools::FileIsDirectory(script.c_str()))
  90. {
  91. this->SetError("given a directory as value of SCRIPT argument.");
  92. return false;
  93. }
  94. this->Makefile->AddInstallGenerator(
  95. new cmInstallScriptGenerator(script.c_str()));
  96. }
  97. else if(doing_code)
  98. {
  99. doing_code = false;
  100. std::string code = args[i];
  101. this->Makefile->AddInstallGenerator(
  102. new cmInstallScriptGenerator(code.c_str(), true));
  103. }
  104. }
  105. if(doing_script)
  106. {
  107. this->SetError("given no value for SCRIPT argument.");
  108. return false;
  109. }
  110. if(doing_code)
  111. {
  112. this->SetError("given no value for CODE argument.");
  113. return false;
  114. }
  115. return true;
  116. }
  117. //----------------------------------------------------------------------------
  118. bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
  119. {
  120. // This is the TARGETS mode.
  121. bool doing_targets = true;
  122. bool doing_destination = false;
  123. bool doing_permissions = false;
  124. bool doing_component = false;
  125. bool doing_configurations = false;
  126. bool archive_settings = true;
  127. bool library_settings = true;
  128. bool runtime_settings = true;
  129. std::vector<cmTarget*> targets;
  130. const char* archive_destination = 0;
  131. const char* library_destination = 0;
  132. const char* runtime_destination = 0;
  133. std::string archive_permissions;
  134. std::string library_permissions;
  135. std::string runtime_permissions;
  136. std::string archive_component;
  137. std::string library_component;
  138. std::string runtime_component;
  139. std::vector<std::string> archive_configurations;
  140. std::vector<std::string> library_configurations;
  141. std::vector<std::string> runtime_configurations;
  142. bool archive_optional = false;
  143. bool library_optional = false;
  144. bool runtime_optional = false;
  145. for(unsigned int i=1; i < args.size(); ++i)
  146. {
  147. if(args[i] == "DESTINATION")
  148. {
  149. // Switch to setting the destination property.
  150. doing_targets = false;
  151. doing_destination = true;
  152. doing_permissions = false;
  153. doing_component = false;
  154. doing_configurations = false;
  155. }
  156. else if(args[i] == "PERMISSIONS")
  157. {
  158. // Switch to setting the permissions property.
  159. doing_targets = false;
  160. doing_destination = false;
  161. doing_permissions = true;
  162. doing_component = false;
  163. doing_configurations = false;
  164. }
  165. else if(args[i] == "COMPONENT")
  166. {
  167. // Switch to setting the component property.
  168. doing_targets = false;
  169. doing_destination = false;
  170. doing_permissions = false;
  171. doing_component = true;
  172. doing_configurations = false;
  173. }
  174. else if(args[i] == "CONFIGURATIONS")
  175. {
  176. // Switch to setting the configurations property.
  177. doing_targets = false;
  178. doing_destination = false;
  179. doing_permissions = false;
  180. doing_component = false;
  181. doing_configurations = true;
  182. }
  183. else if(args[i] == "ARCHIVE")
  184. {
  185. // Switch to setting only archive properties.
  186. doing_targets = false;
  187. doing_destination = false;
  188. doing_permissions = false;
  189. doing_component = false;
  190. doing_configurations = false;
  191. archive_settings = true;
  192. library_settings = false;
  193. runtime_settings = false;
  194. }
  195. else if(args[i] == "LIBRARY")
  196. {
  197. // Switch to setting only library properties.
  198. doing_targets = false;
  199. doing_destination = false;
  200. doing_permissions = false;
  201. doing_component = false;
  202. doing_configurations = false;
  203. archive_settings = false;
  204. library_settings = true;
  205. runtime_settings = false;
  206. }
  207. else if(args[i] == "RUNTIME")
  208. {
  209. // Switch to setting only runtime properties.
  210. doing_targets = false;
  211. doing_destination = false;
  212. doing_permissions = false;
  213. doing_component = false;
  214. doing_configurations = false;
  215. archive_settings = false;
  216. library_settings = false;
  217. runtime_settings = true;
  218. }
  219. else if(args[i] == "OPTIONAL")
  220. {
  221. // Set the optional property.
  222. doing_targets = false;
  223. doing_destination = false;
  224. doing_permissions = false;
  225. doing_component = false;
  226. doing_configurations = false;
  227. if(archive_settings)
  228. {
  229. archive_optional = true;
  230. }
  231. if(library_settings)
  232. {
  233. library_optional = true;
  234. }
  235. if(runtime_settings)
  236. {
  237. runtime_optional = true;
  238. }
  239. }
  240. else if(doing_targets)
  241. {
  242. // Lookup this target in the current directory.
  243. if(cmTarget* target = this->Makefile->FindTarget(args[i].c_str(), false))
  244. {
  245. // Found the target. Check its type.
  246. if(target->GetType() != cmTarget::EXECUTABLE &&
  247. target->GetType() != cmTarget::STATIC_LIBRARY &&
  248. target->GetType() != cmTarget::SHARED_LIBRARY &&
  249. target->GetType() != cmTarget::MODULE_LIBRARY)
  250. {
  251. cmOStringStream e;
  252. e << "TARGETS given target \"" << args[i]
  253. << "\" which is not an executable, library, or module.";
  254. this->SetError(e.str().c_str());
  255. return false;
  256. }
  257. // Store the target in the list to be installed.
  258. targets.push_back(target);
  259. }
  260. else
  261. {
  262. // Did not find the target.
  263. cmOStringStream e;
  264. e << "TARGETS given target \"" << args[i]
  265. << "\" which does not exist in this directory.";
  266. this->SetError(e.str().c_str());
  267. return false;
  268. }
  269. }
  270. else if(doing_destination)
  271. {
  272. // Set the destination in the active set(s) of properties.
  273. if(archive_settings)
  274. {
  275. archive_destination = args[i].c_str();
  276. }
  277. if(library_settings)
  278. {
  279. library_destination = args[i].c_str();
  280. }
  281. if(runtime_settings)
  282. {
  283. runtime_destination = args[i].c_str();
  284. }
  285. doing_destination = false;
  286. }
  287. else if(doing_component)
  288. {
  289. // Set the component in the active set(s) of properties.
  290. if(archive_settings)
  291. {
  292. archive_component = args[i];
  293. }
  294. if(library_settings)
  295. {
  296. library_component = args[i];
  297. }
  298. if(runtime_settings)
  299. {
  300. runtime_component = args[i];
  301. }
  302. doing_component = false;
  303. }
  304. else if(doing_permissions)
  305. {
  306. // Set the permissions in the active set(s) of properties.
  307. if(archive_settings)
  308. {
  309. // Check the requested permission.
  310. if(!this->CheckPermissions(args[i], archive_permissions))
  311. {
  312. cmOStringStream e;
  313. e << args[0] << " given invalid permission \""
  314. << args[i] << "\".";
  315. this->SetError(e.str().c_str());
  316. return false;
  317. }
  318. }
  319. if(library_settings)
  320. {
  321. // Check the requested permission.
  322. if(!this->CheckPermissions(args[i], library_permissions))
  323. {
  324. cmOStringStream e;
  325. e << args[0] << " given invalid permission \""
  326. << args[i] << "\".";
  327. this->SetError(e.str().c_str());
  328. return false;
  329. }
  330. }
  331. if(runtime_settings)
  332. {
  333. // Check the requested permission.
  334. if(!this->CheckPermissions(args[i], runtime_permissions))
  335. {
  336. cmOStringStream e;
  337. e << args[0] << " given invalid permission \""
  338. << args[i] << "\".";
  339. this->SetError(e.str().c_str());
  340. return false;
  341. }
  342. }
  343. }
  344. else if(doing_configurations)
  345. {
  346. // Add the configuration in the active set(s) of properties.
  347. if(archive_settings)
  348. {
  349. archive_configurations.push_back(args[i]);
  350. }
  351. if(library_settings)
  352. {
  353. library_configurations.push_back(args[i]);
  354. }
  355. if(runtime_settings)
  356. {
  357. runtime_configurations.push_back(args[i]);
  358. }
  359. }
  360. else
  361. {
  362. // Unknown argument.
  363. cmOStringStream e;
  364. e << "TARGETS given unknown argument \"" << args[i] << "\".";
  365. this->SetError(e.str().c_str());
  366. return false;
  367. }
  368. }
  369. // Check if there is something to do.
  370. if(targets.empty())
  371. {
  372. return true;
  373. }
  374. if(!archive_destination && !library_destination && !runtime_destination)
  375. {
  376. this->SetError("TARGETS given no DESTINATION!");
  377. return false;
  378. }
  379. // Check whether this is a DLL platform.
  380. bool dll_platform = (this->Makefile->IsOn("WIN32") ||
  381. this->Makefile->IsOn("CYGWIN") ||
  382. this->Makefile->IsOn("MINGW"));
  383. // Compute destination paths.
  384. std::string archive_dest;
  385. std::string library_dest;
  386. std::string runtime_dest;
  387. this->ComputeDestination(archive_destination, archive_dest);
  388. this->ComputeDestination(library_destination, library_dest);
  389. this->ComputeDestination(runtime_destination, runtime_dest);
  390. // Generate install script code to install the given targets.
  391. for(std::vector<cmTarget*>::iterator ti = targets.begin();
  392. ti != targets.end(); ++ti)
  393. {
  394. // Handle each target type.
  395. cmTarget& target = *(*ti);
  396. switch(target.GetType())
  397. {
  398. case cmTarget::SHARED_LIBRARY:
  399. {
  400. // Shared libraries are handled differently on DLL and non-DLL
  401. // platforms. All windows platforms are DLL platforms
  402. // including cygwin. Currently no other platform is a DLL
  403. // platform.
  404. if(dll_platform)
  405. {
  406. // This is a DLL platform.
  407. if(archive_destination)
  408. {
  409. // The import library uses the ARCHIVE properties.
  410. this->Makefile->AddInstallGenerator(
  411. new cmInstallTargetGenerator(target, archive_dest.c_str(), true,
  412. archive_permissions.c_str(),
  413. archive_configurations,
  414. archive_component.c_str(),
  415. archive_optional));
  416. }
  417. if(runtime_destination)
  418. {
  419. // The DLL uses the RUNTIME properties.
  420. this->Makefile->AddInstallGenerator(
  421. new cmInstallTargetGenerator(target, runtime_dest.c_str(),
  422. false,
  423. runtime_permissions.c_str(),
  424. runtime_configurations,
  425. runtime_component.c_str(),
  426. runtime_optional));
  427. }
  428. }
  429. else
  430. {
  431. // This is a non-DLL platform.
  432. if(library_destination)
  433. {
  434. // The shared library uses the LIBRARY properties.
  435. this->Makefile->AddInstallGenerator(
  436. new cmInstallTargetGenerator(target, library_dest.c_str(),
  437. false,
  438. library_permissions.c_str(),
  439. library_configurations,
  440. library_component.c_str(),
  441. library_optional));
  442. }
  443. else
  444. {
  445. cmOStringStream e;
  446. e << "TARGETS given no LIBRARY DESTINATION for shared library "
  447. "target \"" << target.GetName() << "\".";
  448. this->SetError(e.str().c_str());
  449. return false;
  450. }
  451. }
  452. }
  453. break;
  454. case cmTarget::STATIC_LIBRARY:
  455. {
  456. // Static libraries use ARCHIVE properties.
  457. if(archive_destination)
  458. {
  459. this->Makefile->AddInstallGenerator(
  460. new cmInstallTargetGenerator(target, archive_dest.c_str(), false,
  461. archive_permissions.c_str(),
  462. archive_configurations,
  463. archive_component.c_str(),
  464. archive_optional));
  465. }
  466. else
  467. {
  468. cmOStringStream e;
  469. e << "TARGETS given no ARCHIVE DESTINATION for static library "
  470. "target \"" << target.GetName() << "\".";
  471. this->SetError(e.str().c_str());
  472. return false;
  473. }
  474. }
  475. break;
  476. case cmTarget::MODULE_LIBRARY:
  477. {
  478. // Modules use LIBRARY properties.
  479. if(library_destination)
  480. {
  481. this->Makefile->AddInstallGenerator(
  482. new cmInstallTargetGenerator(target, library_dest.c_str(), false,
  483. library_permissions.c_str(),
  484. library_configurations,
  485. library_component.c_str(),
  486. library_optional));
  487. }
  488. else
  489. {
  490. cmOStringStream e;
  491. e << "TARGETS given no LIBRARY DESTINATION for module target \""
  492. << target.GetName() << "\".";
  493. this->SetError(e.str().c_str());
  494. return false;
  495. }
  496. }
  497. break;
  498. case cmTarget::EXECUTABLE:
  499. {
  500. // Executables use the RUNTIME properties.
  501. if(runtime_destination)
  502. {
  503. this->Makefile->AddInstallGenerator(
  504. new cmInstallTargetGenerator(target, runtime_dest.c_str(), false,
  505. runtime_permissions.c_str(),
  506. runtime_configurations,
  507. runtime_component.c_str(),
  508. runtime_optional));
  509. }
  510. else
  511. {
  512. cmOStringStream e;
  513. e << "TARGETS given no RUNTIME DESTINATION for executable target \""
  514. << target.GetName() << "\".";
  515. this->SetError(e.str().c_str());
  516. return false;
  517. }
  518. // On DLL platforms an executable may also have an import
  519. // library. Install it to the archive destination if it
  520. // exists.
  521. if(dll_platform && archive_destination)
  522. {
  523. // The import library uses the ARCHIVE properties.
  524. this->Makefile->AddInstallGenerator(
  525. new cmInstallTargetGenerator(target, archive_dest.c_str(), true,
  526. archive_permissions.c_str(),
  527. archive_configurations,
  528. archive_component.c_str(),
  529. true));
  530. }
  531. }
  532. break;
  533. default:
  534. // This should never happen due to the above type check.
  535. // Ignore the case.
  536. break;
  537. }
  538. }
  539. // Tell the global generator about any installation component names
  540. // specified.
  541. this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
  542. ->AddInstallComponent(archive_component.c_str());
  543. this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
  544. ->AddInstallComponent(library_component.c_str());
  545. this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
  546. ->AddInstallComponent(runtime_component.c_str());
  547. return true;
  548. }
  549. //----------------------------------------------------------------------------
  550. bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
  551. {
  552. // This is the FILES mode.
  553. bool programs = (args[0] == "PROGRAMS");
  554. bool doing_files = true;
  555. bool doing_destination = false;
  556. bool doing_permissions = false;
  557. bool doing_configurations = false;
  558. bool doing_component = false;
  559. bool doing_rename = false;
  560. std::vector<std::string> files;
  561. const char* destination = 0;
  562. std::string rename;
  563. std::string permissions;
  564. std::vector<std::string> configurations;
  565. std::string component;
  566. bool optional = false;
  567. for(unsigned int i=1; i < args.size(); ++i)
  568. {
  569. if(args[i] == "DESTINATION")
  570. {
  571. // Switch to setting the destination property.
  572. doing_files = false;
  573. doing_destination = true;
  574. doing_permissions = false;
  575. doing_configurations = false;
  576. doing_component = false;
  577. doing_rename = false;
  578. }
  579. else if(args[i] == "PERMISSIONS")
  580. {
  581. // Switch to setting the permissions property.
  582. doing_files = false;
  583. doing_destination = false;
  584. doing_permissions = true;
  585. doing_configurations = false;
  586. doing_component = false;
  587. doing_rename = false;
  588. }
  589. else if(args[i] == "CONFIGURATIONS")
  590. {
  591. // Switch to setting the configurations property.
  592. doing_files = false;
  593. doing_destination = false;
  594. doing_permissions = false;
  595. doing_configurations = true;
  596. doing_component = false;
  597. doing_rename = false;
  598. }
  599. else if(args[i] == "COMPONENT")
  600. {
  601. // Switch to setting the component property.
  602. doing_files = false;
  603. doing_destination = false;
  604. doing_permissions = false;
  605. doing_configurations = false;
  606. doing_component = true;
  607. doing_rename = false;
  608. }
  609. else if(args[i] == "RENAME")
  610. {
  611. // Switch to setting the rename property.
  612. doing_files = false;
  613. doing_destination = false;
  614. doing_permissions = false;
  615. doing_configurations = false;
  616. doing_component = false;
  617. doing_rename = true;
  618. }
  619. else if(args[i] == "OPTIONAL")
  620. {
  621. // Set the optional property.
  622. doing_files = false;
  623. doing_destination = false;
  624. doing_permissions = false;
  625. doing_configurations = false;
  626. doing_component = false;
  627. doing_rename = false;
  628. optional = true;
  629. }
  630. else if(doing_files)
  631. {
  632. // Convert this file to a full path.
  633. std::string file = args[i];
  634. if(!cmSystemTools::FileIsFullPath(file.c_str()))
  635. {
  636. file = this->Makefile->GetCurrentDirectory();
  637. file += "/";
  638. file += args[i];
  639. }
  640. // Make sure the file is not a directory.
  641. if(cmSystemTools::FileIsDirectory(file.c_str()))
  642. {
  643. cmOStringStream e;
  644. e << args[0] << " given directory \"" << args[i] << "\" to install.";
  645. this->SetError(e.str().c_str());
  646. return false;
  647. }
  648. // Store the file for installation.
  649. files.push_back(file);
  650. }
  651. else if(doing_configurations)
  652. {
  653. configurations.push_back(args[i]);
  654. }
  655. else if(doing_destination)
  656. {
  657. destination = args[i].c_str();
  658. doing_destination = false;
  659. }
  660. else if(doing_component)
  661. {
  662. component = args[i];
  663. doing_component = false;
  664. }
  665. else if(doing_permissions)
  666. {
  667. // Check the requested permission.
  668. if(!this->CheckPermissions(args[i], permissions))
  669. {
  670. cmOStringStream e;
  671. e << args[0] << " given invalid permission \""
  672. << args[i] << "\".";
  673. this->SetError(e.str().c_str());
  674. return false;
  675. }
  676. }
  677. else if(doing_rename)
  678. {
  679. rename = args[i];
  680. doing_rename = false;
  681. }
  682. else
  683. {
  684. // Unknown argument.
  685. cmOStringStream e;
  686. e << args[0] << " given unknown argument \"" << args[i] << "\".";
  687. this->SetError(e.str().c_str());
  688. return false;
  689. }
  690. }
  691. // Check if there is something to do.
  692. if(files.empty())
  693. {
  694. return true;
  695. }
  696. if(!destination)
  697. {
  698. // A destination is required.
  699. cmOStringStream e;
  700. e << args[0] << " given no DESTINATION!";
  701. this->SetError(e.str().c_str());
  702. return false;
  703. }
  704. if(!rename.empty() && files.size() > 1)
  705. {
  706. // The rename option works only with one file.
  707. cmOStringStream e;
  708. e << args[0] << " given RENAME option with more than one file.";
  709. this->SetError(e.str().c_str());
  710. return false;
  711. }
  712. // Compute destination path.
  713. std::string dest;
  714. this->ComputeDestination(destination, dest);
  715. // Create the files install generator.
  716. this->Makefile->AddInstallGenerator(
  717. new cmInstallFilesGenerator(files, dest.c_str(), programs,
  718. permissions.c_str(), configurations,
  719. component.c_str(), rename.c_str(),
  720. optional));
  721. // Tell the global generator about any installation component names
  722. // specified.
  723. this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
  724. ->AddInstallComponent(component.c_str());
  725. return true;
  726. }
  727. //----------------------------------------------------------------------------
  728. bool
  729. cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args)
  730. {
  731. bool doing_dirs = true;
  732. bool doing_destination = false;
  733. bool doing_pattern = false;
  734. bool doing_regex = false;
  735. bool doing_permissions_file = false;
  736. bool doing_permissions_dir = false;
  737. bool doing_permissions_match = false;
  738. bool doing_configurations = false;
  739. bool doing_component = false;
  740. bool in_match_mode = false;
  741. std::vector<std::string> dirs;
  742. const char* destination = 0;
  743. std::string permissions_file;
  744. std::string permissions_dir;
  745. std::vector<std::string> configurations;
  746. std::string component;
  747. std::string literal_args;
  748. for(unsigned int i=1; i < args.size(); ++i)
  749. {
  750. if(args[i] == "DESTINATION")
  751. {
  752. if(in_match_mode)
  753. {
  754. cmOStringStream e;
  755. e << args[0] << " does not allow \""
  756. << args[i] << "\" after PATTERN or REGEX.";
  757. this->SetError(e.str().c_str());
  758. return false;
  759. }
  760. // Switch to setting the destination property.
  761. doing_dirs = false;
  762. doing_destination = true;
  763. doing_pattern = false;
  764. doing_regex = false;
  765. doing_permissions_file = false;
  766. doing_permissions_dir = false;
  767. doing_configurations = false;
  768. doing_component = false;
  769. }
  770. else if(args[i] == "PATTERN")
  771. {
  772. // Switch to a new pattern match rule.
  773. doing_dirs = false;
  774. doing_destination = false;
  775. doing_pattern = true;
  776. doing_regex = false;
  777. doing_permissions_file = false;
  778. doing_permissions_dir = false;
  779. doing_permissions_match = false;
  780. doing_configurations = false;
  781. doing_component = false;
  782. in_match_mode = true;
  783. }
  784. else if(args[i] == "REGEX")
  785. {
  786. // Switch to a new regex match rule.
  787. doing_dirs = false;
  788. doing_destination = false;
  789. doing_pattern = false;
  790. doing_regex = true;
  791. doing_permissions_file = false;
  792. doing_permissions_dir = false;
  793. doing_permissions_match = false;
  794. doing_configurations = false;
  795. doing_component = false;
  796. in_match_mode = true;
  797. }
  798. else if(args[i] == "EXCLUDE")
  799. {
  800. // Add this property to the current match rule.
  801. if(!in_match_mode || doing_pattern || doing_regex)
  802. {
  803. cmOStringStream e;
  804. e << args[0] << " does not allow \""
  805. << args[i] << "\" before a PATTERN or REGEX is given.";
  806. this->SetError(e.str().c_str());
  807. return false;
  808. }
  809. literal_args += " EXCLUDE";
  810. doing_permissions_match = false;
  811. }
  812. else if(args[i] == "PERMISSIONS")
  813. {
  814. if(!in_match_mode)
  815. {
  816. cmOStringStream e;
  817. e << args[0] << " does not allow \""
  818. << args[i] << "\" before a PATTERN or REGEX is given.";
  819. this->SetError(e.str().c_str());
  820. return false;
  821. }
  822. // Switch to setting the current match permissions property.
  823. literal_args += " PERMISSIONS";
  824. doing_permissions_match = true;
  825. }
  826. else if(args[i] == "FILE_PERMISSIONS")
  827. {
  828. if(in_match_mode)
  829. {
  830. cmOStringStream e;
  831. e << args[0] << " does not allow \""
  832. << args[i] << "\" after PATTERN or REGEX.";
  833. this->SetError(e.str().c_str());
  834. return false;
  835. }
  836. // Switch to setting the file permissions property.
  837. doing_dirs = false;
  838. doing_destination = false;
  839. doing_pattern = false;
  840. doing_regex = false;
  841. doing_permissions_file = true;
  842. doing_permissions_dir = false;
  843. doing_configurations = false;
  844. doing_component = false;
  845. }
  846. else if(args[i] == "DIRECTORY_PERMISSIONS")
  847. {
  848. if(in_match_mode)
  849. {
  850. cmOStringStream e;
  851. e << args[0] << " does not allow \""
  852. << args[i] << "\" after PATTERN or REGEX.";
  853. this->SetError(e.str().c_str());
  854. return false;
  855. }
  856. // Switch to setting the directory permissions property.
  857. doing_dirs = false;
  858. doing_destination = false;
  859. doing_pattern = false;
  860. doing_regex = false;
  861. doing_permissions_file = false;
  862. doing_permissions_dir = true;
  863. doing_configurations = false;
  864. doing_component = false;
  865. }
  866. else if(args[i] == "USE_SOURCE_PERMISSIONS")
  867. {
  868. if(in_match_mode)
  869. {
  870. cmOStringStream e;
  871. e << args[0] << " does not allow \""
  872. << args[i] << "\" after PATTERN or REGEX.";
  873. this->SetError(e.str().c_str());
  874. return false;
  875. }
  876. // Add this option literally.
  877. doing_dirs = false;
  878. doing_destination = false;
  879. doing_pattern = false;
  880. doing_regex = false;
  881. doing_permissions_file = false;
  882. doing_permissions_dir = false;
  883. doing_configurations = false;
  884. doing_component = false;
  885. literal_args += " USE_SOURCE_PERMISSIONS";
  886. }
  887. else if(args[i] == "CONFIGURATIONS")
  888. {
  889. if(in_match_mode)
  890. {
  891. cmOStringStream e;
  892. e << args[0] << " does not allow \""
  893. << args[i] << "\" after PATTERN or REGEX.";
  894. this->SetError(e.str().c_str());
  895. return false;
  896. }
  897. // Switch to setting the configurations property.
  898. doing_dirs = false;
  899. doing_destination = false;
  900. doing_pattern = false;
  901. doing_regex = false;
  902. doing_permissions_file = false;
  903. doing_permissions_dir = false;
  904. doing_configurations = true;
  905. doing_component = false;
  906. }
  907. else if(args[i] == "COMPONENT")
  908. {
  909. if(in_match_mode)
  910. {
  911. cmOStringStream e;
  912. e << args[0] << " does not allow \""
  913. << args[i] << "\" after PATTERN or REGEX.";
  914. this->SetError(e.str().c_str());
  915. return false;
  916. }
  917. // Switch to setting the component property.
  918. doing_dirs = false;
  919. doing_destination = false;
  920. doing_pattern = false;
  921. doing_regex = false;
  922. doing_permissions_file = false;
  923. doing_permissions_dir = false;
  924. doing_configurations = false;
  925. doing_component = true;
  926. }
  927. else if(doing_dirs)
  928. {
  929. // Convert this directory to a full path.
  930. std::string dir = args[i];
  931. if(!cmSystemTools::FileIsFullPath(dir.c_str()))
  932. {
  933. dir = this->Makefile->GetCurrentDirectory();
  934. dir += "/";
  935. dir += args[i];
  936. }
  937. // Make sure the name is a directory.
  938. if(!cmSystemTools::FileIsDirectory(dir.c_str()))
  939. {
  940. cmOStringStream e;
  941. e << args[0] << " given non-directory \""
  942. << args[i] << "\" to install.";
  943. this->SetError(e.str().c_str());
  944. return false;
  945. }
  946. // Store the directory for installation.
  947. dirs.push_back(dir);
  948. }
  949. else if(doing_configurations)
  950. {
  951. configurations.push_back(args[i]);
  952. }
  953. else if(doing_destination)
  954. {
  955. destination = args[i].c_str();
  956. doing_destination = false;
  957. }
  958. else if(doing_pattern)
  959. {
  960. // Convert the pattern to a regular expression. Require a
  961. // leading slash and trailing end-of-string in the matched
  962. // string to make sure the pattern matches only whole file
  963. // names.
  964. literal_args += " REGEX \"/";
  965. std::string regex = cmsys::Glob::PatternToRegex(args[i], false);
  966. cmSystemTools::ReplaceString(regex, "\\", "\\\\");
  967. literal_args += regex;
  968. literal_args += "$\"";
  969. doing_pattern = false;
  970. }
  971. else if(doing_regex)
  972. {
  973. literal_args += " REGEX \"";
  974. // Match rules are case-insensitive on some platforms.
  975. #if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__)
  976. std::string regex = cmSystemTools::LowerCase(args[i]);
  977. #else
  978. std::string regex = args[i];
  979. #endif
  980. cmSystemTools::ReplaceString(regex, "\\", "\\\\");
  981. literal_args += regex;
  982. literal_args += "\"";
  983. doing_regex = false;
  984. }
  985. else if(doing_component)
  986. {
  987. component = args[i];
  988. doing_component = false;
  989. }
  990. else if(doing_permissions_file)
  991. {
  992. // Check the requested permission.
  993. if(!this->CheckPermissions(args[i], permissions_file))
  994. {
  995. cmOStringStream e;
  996. e << args[0] << " given invalid file permission \""
  997. << args[i] << "\".";
  998. this->SetError(e.str().c_str());
  999. return false;
  1000. }
  1001. }
  1002. else if(doing_permissions_dir)
  1003. {
  1004. // Check the requested permission.
  1005. if(!this->CheckPermissions(args[i], permissions_dir))
  1006. {
  1007. cmOStringStream e;
  1008. e << args[0] << " given invalid directory permission \""
  1009. << args[i] << "\".";
  1010. this->SetError(e.str().c_str());
  1011. return false;
  1012. }
  1013. }
  1014. else if(doing_permissions_match)
  1015. {
  1016. // Check the requested permission.
  1017. if(!this->CheckPermissions(args[i], literal_args))
  1018. {
  1019. cmOStringStream e;
  1020. e << args[0] << " given invalid permission \""
  1021. << args[i] << "\".";
  1022. this->SetError(e.str().c_str());
  1023. return false;
  1024. }
  1025. }
  1026. else
  1027. {
  1028. // Unknown argument.
  1029. cmOStringStream e;
  1030. e << args[0] << " given unknown argument \"" << args[i] << "\".";
  1031. this->SetError(e.str().c_str());
  1032. return false;
  1033. }
  1034. }
  1035. // Support installing an empty directory.
  1036. if(dirs.empty() && destination)
  1037. {
  1038. dirs.push_back("");
  1039. }
  1040. // Check if there is something to do.
  1041. if(dirs.empty())
  1042. {
  1043. return true;
  1044. }
  1045. if(!destination)
  1046. {
  1047. // A destination is required.
  1048. cmOStringStream e;
  1049. e << args[0] << " given no DESTINATION!";
  1050. this->SetError(e.str().c_str());
  1051. return false;
  1052. }
  1053. // Compute destination path.
  1054. std::string dest;
  1055. this->ComputeDestination(destination, dest);
  1056. // Create the directory install generator.
  1057. this->Makefile->AddInstallGenerator(
  1058. new cmInstallDirectoryGenerator(dirs, dest.c_str(),
  1059. permissions_file.c_str(),
  1060. permissions_dir.c_str(),
  1061. configurations,
  1062. component.c_str(),
  1063. literal_args.c_str()));
  1064. // Tell the global generator about any installation component names
  1065. // specified.
  1066. this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
  1067. ->AddInstallComponent(component.c_str());
  1068. return true;
  1069. }
  1070. //----------------------------------------------------------------------------
  1071. void cmInstallCommand::ComputeDestination(const char* destination,
  1072. std::string& dest)
  1073. {
  1074. if(destination)
  1075. {
  1076. if(cmSystemTools::FileIsFullPath(destination))
  1077. {
  1078. // Full paths are absolute.
  1079. dest = destination;
  1080. }
  1081. else
  1082. {
  1083. // Relative paths are treated with respect to the installation prefix.
  1084. dest = "${CMAKE_INSTALL_PREFIX}/";
  1085. dest += destination;
  1086. }
  1087. // Format the path nicely. Note this also removes trailing
  1088. // slashes.
  1089. cmSystemTools::ConvertToUnixSlashes(dest);
  1090. }
  1091. else
  1092. {
  1093. dest = "";
  1094. }
  1095. }
  1096. //----------------------------------------------------------------------------
  1097. bool cmInstallCommand::CheckPermissions(std::string const& arg,
  1098. std::string& permissions)
  1099. {
  1100. // Table of valid permissions.
  1101. const char* table[] =
  1102. {
  1103. "OWNER_READ", "OWNER_WRITE", "OWNER_EXECUTE",
  1104. "GROUP_READ", "GROUP_WRITE", "GROUP_EXECUTE",
  1105. "WORLD_READ", "WORLD_WRITE", "WORLD_EXECUTE",
  1106. "SETUID", "SETGID", 0
  1107. };
  1108. // Check the permission against the table.
  1109. for(const char** valid = table; *valid; ++valid)
  1110. {
  1111. if(arg == *valid)
  1112. {
  1113. // This is a valid permission.
  1114. permissions += " ";
  1115. permissions += arg;
  1116. return true;
  1117. }
  1118. }
  1119. // This is not a valid permission.
  1120. return false;
  1121. }