cmInstallCommand.cxx 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  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 "cmInstallFilesGenerator.h"
  15. #include "cmInstallScriptGenerator.h"
  16. #include "cmInstallTargetGenerator.h"
  17. // cmInstallCommand
  18. bool cmInstallCommand::InitialPass(std::vector<std::string> const& args)
  19. {
  20. // Allow calling with no arguments so that arguments may be built up
  21. // using a variable that may be left empty.
  22. if(args.empty())
  23. {
  24. return true;
  25. }
  26. // Switch among the command modes.
  27. if(args[0] == "SCRIPT")
  28. {
  29. return this->HandleScriptMode(args);
  30. }
  31. else if(args[0] == "CODE")
  32. {
  33. return this->HandleScriptMode(args);
  34. }
  35. else if(args[0] == "TARGETS")
  36. {
  37. return this->HandleTargetsMode(args);
  38. }
  39. else if(args[0] == "FILES")
  40. {
  41. return this->HandleFilesMode(args);
  42. }
  43. else if(args[0] == "PROGRAMS")
  44. {
  45. return this->HandleFilesMode(args);
  46. }
  47. // Unknown mode.
  48. cmStdString e = "called with unknown mode ";
  49. e += args[0];
  50. this->SetError(e.c_str());
  51. return false;
  52. }
  53. //----------------------------------------------------------------------------
  54. bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args)
  55. {
  56. bool doing_script = false;
  57. bool doing_code = false;
  58. for(size_t i=0; i < args.size(); ++i)
  59. {
  60. if(args[i] == "SCRIPT")
  61. {
  62. doing_script = true;
  63. doing_code = false;
  64. }
  65. else if(args[i] == "CODE")
  66. {
  67. doing_script = false;
  68. doing_code = true;
  69. }
  70. else if(doing_script)
  71. {
  72. doing_script = false;
  73. std::string script = args[i];
  74. if(!cmSystemTools::FileIsFullPath(script.c_str()))
  75. {
  76. script = this->Makefile->GetCurrentDirectory();
  77. script += "/";
  78. script += args[i];
  79. }
  80. if(cmSystemTools::FileIsDirectory(script.c_str()))
  81. {
  82. this->SetError("given a directory as value of SCRIPT argument.");
  83. return false;
  84. }
  85. this->Makefile->AddInstallGenerator(
  86. new cmInstallScriptGenerator(script.c_str()));
  87. }
  88. else if(doing_code)
  89. {
  90. doing_code = false;
  91. std::string code = args[i];
  92. this->Makefile->AddInstallGenerator(
  93. new cmInstallScriptGenerator(code.c_str(), true));
  94. }
  95. }
  96. if(doing_script)
  97. {
  98. this->SetError("given no value for SCRIPT argument.");
  99. return false;
  100. }
  101. if(doing_code)
  102. {
  103. this->SetError("given no value for CODE argument.");
  104. return false;
  105. }
  106. return true;
  107. }
  108. //----------------------------------------------------------------------------
  109. bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
  110. {
  111. // This is the TARGETS mode.
  112. bool doing_targets = true;
  113. bool doing_destination = false;
  114. bool doing_permissions = false;
  115. bool doing_component = false;
  116. bool doing_configurations = false;
  117. bool archive_settings = true;
  118. bool library_settings = true;
  119. bool runtime_settings = true;
  120. std::vector<cmTarget*> targets;
  121. const char* archive_destination = 0;
  122. const char* library_destination = 0;
  123. const char* runtime_destination = 0;
  124. std::string archive_permissions;
  125. std::string library_permissions;
  126. std::string runtime_permissions;
  127. std::string archive_component;
  128. std::string library_component;
  129. std::string runtime_component;
  130. std::vector<std::string> archive_configurations;
  131. std::vector<std::string> library_configurations;
  132. std::vector<std::string> runtime_configurations;
  133. for(unsigned int i=1; i < args.size(); ++i)
  134. {
  135. if(args[i] == "DESTINATION")
  136. {
  137. // Switch to setting the destination property.
  138. doing_targets = false;
  139. doing_destination = true;
  140. doing_permissions = false;
  141. doing_component = false;
  142. doing_configurations = false;
  143. }
  144. else if(args[i] == "PERMISSIONS")
  145. {
  146. // Switch to setting the permissions property.
  147. doing_targets = false;
  148. doing_destination = false;
  149. doing_permissions = true;
  150. doing_component = false;
  151. doing_configurations = false;
  152. }
  153. else if(args[i] == "COMPONENT")
  154. {
  155. // Switch to setting the component property.
  156. doing_targets = false;
  157. doing_destination = false;
  158. doing_permissions = false;
  159. doing_component = true;
  160. doing_configurations = false;
  161. }
  162. else if(args[i] == "CONFIGURATIONS")
  163. {
  164. // Switch to setting the configurations property.
  165. doing_targets = false;
  166. doing_destination = false;
  167. doing_permissions = false;
  168. doing_component = false;
  169. doing_configurations = true;
  170. }
  171. else if(args[i] == "ARCHIVE")
  172. {
  173. // Switch to setting only archive properties.
  174. doing_targets = false;
  175. doing_destination = false;
  176. doing_permissions = false;
  177. doing_component = false;
  178. doing_configurations = false;
  179. archive_settings = true;
  180. library_settings = false;
  181. runtime_settings = false;
  182. }
  183. else if(args[i] == "LIBRARY")
  184. {
  185. // Switch to setting only library properties.
  186. doing_targets = false;
  187. doing_destination = false;
  188. doing_permissions = false;
  189. doing_component = false;
  190. doing_configurations = false;
  191. archive_settings = false;
  192. library_settings = true;
  193. runtime_settings = false;
  194. }
  195. else if(args[i] == "RUNTIME")
  196. {
  197. // Switch to setting only runtime 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 = false;
  205. runtime_settings = true;
  206. }
  207. else if(doing_targets)
  208. {
  209. // Lookup this target in the current directory.
  210. if(cmTarget* target = this->Makefile->FindTarget(args[i].c_str()))
  211. {
  212. // Found the target. Check its type.
  213. if(target->GetType() != cmTarget::EXECUTABLE &&
  214. target->GetType() != cmTarget::STATIC_LIBRARY &&
  215. target->GetType() != cmTarget::SHARED_LIBRARY &&
  216. target->GetType() != cmTarget::MODULE_LIBRARY)
  217. {
  218. cmOStringStream e;
  219. e << "TARGETS given target \"" << args[i]
  220. << "\" which is not an executable, library, or module.";
  221. this->SetError(e.str().c_str());
  222. return false;
  223. }
  224. // Store the target in the list to be installed.
  225. targets.push_back(target);
  226. }
  227. else
  228. {
  229. // Did not find the target.
  230. cmOStringStream e;
  231. e << "TARGETS given target \"" << args[i]
  232. << "\" which does not exist in this directory.";
  233. this->SetError(e.str().c_str());
  234. return false;
  235. }
  236. }
  237. else if(doing_destination)
  238. {
  239. // Set the destination in the active set(s) of properties.
  240. if(archive_settings)
  241. {
  242. archive_destination = args[i].c_str();
  243. }
  244. if(library_settings)
  245. {
  246. library_destination = args[i].c_str();
  247. }
  248. if(runtime_settings)
  249. {
  250. runtime_destination = args[i].c_str();
  251. }
  252. doing_destination = false;
  253. }
  254. else if(doing_component)
  255. {
  256. // Set the component in the active set(s) of properties.
  257. if(archive_settings)
  258. {
  259. archive_component = args[i];
  260. }
  261. if(library_settings)
  262. {
  263. library_component = args[i];
  264. }
  265. if(runtime_settings)
  266. {
  267. runtime_component = args[i];
  268. }
  269. doing_component = false;
  270. }
  271. else if(doing_permissions)
  272. {
  273. // Set the permissions in the active set(s) of properties.
  274. if(archive_settings)
  275. {
  276. // Check the requested permission.
  277. if(!this->CheckPermissions(args[i], archive_permissions))
  278. {
  279. cmOStringStream e;
  280. e << args[0] << " given invalid permission \""
  281. << args[i] << "\".";
  282. this->SetError(e.str().c_str());
  283. return false;
  284. }
  285. }
  286. if(library_settings)
  287. {
  288. // Check the requested permission.
  289. if(!this->CheckPermissions(args[i], library_permissions))
  290. {
  291. cmOStringStream e;
  292. e << args[0] << " given invalid permission \""
  293. << args[i] << "\".";
  294. this->SetError(e.str().c_str());
  295. return false;
  296. }
  297. }
  298. if(runtime_settings)
  299. {
  300. // Check the requested permission.
  301. if(!this->CheckPermissions(args[i], runtime_permissions))
  302. {
  303. cmOStringStream e;
  304. e << args[0] << " given invalid permission \""
  305. << args[i] << "\".";
  306. this->SetError(e.str().c_str());
  307. return false;
  308. }
  309. }
  310. }
  311. else if(doing_configurations)
  312. {
  313. // Add the configuration in the active set(s) of properties.
  314. if(archive_settings)
  315. {
  316. archive_configurations.push_back(args[i]);
  317. }
  318. if(library_settings)
  319. {
  320. library_configurations.push_back(args[i]);
  321. }
  322. if(runtime_settings)
  323. {
  324. runtime_configurations.push_back(args[i]);
  325. }
  326. }
  327. else
  328. {
  329. // Unknown argument.
  330. cmOStringStream e;
  331. e << "TARGETS given unknown argument \"" << args[i] << "\".";
  332. this->SetError(e.str().c_str());
  333. return false;
  334. }
  335. }
  336. // Check if there is something to do.
  337. if(targets.empty())
  338. {
  339. return true;
  340. }
  341. if(!archive_destination && !library_destination && !runtime_destination)
  342. {
  343. this->SetError("TARGETS given no DESTINATION!");
  344. return false;
  345. }
  346. // Compute destination paths.
  347. std::string archive_dest;
  348. std::string library_dest;
  349. std::string runtime_dest;
  350. this->ComputeDestination(archive_destination, archive_dest);
  351. this->ComputeDestination(library_destination, library_dest);
  352. this->ComputeDestination(runtime_destination, runtime_dest);
  353. // Generate install script code to install the given targets.
  354. for(std::vector<cmTarget*>::iterator ti = targets.begin();
  355. ti != targets.end(); ++ti)
  356. {
  357. // Handle each target type.
  358. cmTarget& target = *(*ti);
  359. switch(target.GetType())
  360. {
  361. case cmTarget::SHARED_LIBRARY:
  362. {
  363. // Shared libraries are handled differently on DLL and non-DLL
  364. // platforms. All windows platforms are DLL platforms
  365. // including cygwin. Currently no other platform is a DLL
  366. // platform.
  367. #if defined(_WIN32) || defined(__CYGWIN__)
  368. // This is a DLL platform.
  369. if(archive_destination)
  370. {
  371. // The import library uses the ARCHIVE properties.
  372. this->Makefile->AddInstallGenerator(
  373. new cmInstallTargetGenerator(target, archive_dest.c_str(), true,
  374. archive_permissions.c_str(),
  375. archive_configurations,
  376. archive_component.c_str()));
  377. }
  378. if(runtime_destination)
  379. {
  380. // The DLL uses the RUNTIME properties.
  381. this->Makefile->AddInstallGenerator(
  382. new cmInstallTargetGenerator(target, runtime_dest.c_str(), false,
  383. runtime_permissions.c_str(),
  384. runtime_configurations,
  385. runtime_component.c_str()));
  386. }
  387. #else
  388. // This is a non-DLL platform.
  389. if(library_destination)
  390. {
  391. // The shared library uses the LIBRARY properties.
  392. this->Makefile->AddInstallGenerator(
  393. new cmInstallTargetGenerator(target, library_dest.c_str(), false,
  394. library_permissions.c_str(),
  395. library_configurations,
  396. library_component.c_str()));
  397. }
  398. else
  399. {
  400. cmOStringStream e;
  401. e << "TARGETS given no LIBRARY DESTINATION for shared library "
  402. "target \"" << target.GetName() << "\".";
  403. this->SetError(e.str().c_str());
  404. return false;
  405. }
  406. #endif
  407. }
  408. break;
  409. case cmTarget::STATIC_LIBRARY:
  410. {
  411. // Static libraries use ARCHIVE properties.
  412. if(archive_destination)
  413. {
  414. this->Makefile->AddInstallGenerator(
  415. new cmInstallTargetGenerator(target, archive_dest.c_str(), false,
  416. archive_permissions.c_str(),
  417. archive_configurations,
  418. archive_component.c_str()));
  419. }
  420. else
  421. {
  422. cmOStringStream e;
  423. e << "TARGETS given no ARCHIVE DESTINATION for static library "
  424. "target \"" << target.GetName() << "\".";
  425. this->SetError(e.str().c_str());
  426. return false;
  427. }
  428. }
  429. break;
  430. case cmTarget::MODULE_LIBRARY:
  431. {
  432. // Modules use LIBRARY properties.
  433. if(library_destination)
  434. {
  435. this->Makefile->AddInstallGenerator(
  436. new cmInstallTargetGenerator(target, library_dest.c_str(), false,
  437. library_permissions.c_str(),
  438. library_configurations,
  439. library_component.c_str()));
  440. }
  441. else
  442. {
  443. cmOStringStream e;
  444. e << "TARGETS given no LIBRARY DESTINATION for module target \""
  445. << target.GetName() << "\".";
  446. this->SetError(e.str().c_str());
  447. return false;
  448. }
  449. }
  450. break;
  451. case cmTarget::EXECUTABLE:
  452. {
  453. // Executables use the RUNTIME properties.
  454. if(runtime_destination)
  455. {
  456. this->Makefile->AddInstallGenerator(
  457. new cmInstallTargetGenerator(target, runtime_dest.c_str(), false,
  458. runtime_permissions.c_str(),
  459. runtime_configurations,
  460. runtime_component.c_str()));
  461. }
  462. else
  463. {
  464. cmOStringStream e;
  465. e << "TARGETS given no RUNTIME DESTINATION for executable target \""
  466. << target.GetName() << "\".";
  467. this->SetError(e.str().c_str());
  468. return false;
  469. }
  470. }
  471. break;
  472. default:
  473. // This should never happen due to the above type check.
  474. // Ignore the case.
  475. break;
  476. }
  477. }
  478. // Tell the global generator about any installation component names
  479. // specified.
  480. this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
  481. ->AddInstallComponent(archive_component.c_str());
  482. this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
  483. ->AddInstallComponent(library_component.c_str());
  484. this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
  485. ->AddInstallComponent(runtime_component.c_str());
  486. return true;
  487. }
  488. //----------------------------------------------------------------------------
  489. bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args)
  490. {
  491. // This is the FILES mode.
  492. bool programs = (args[0] == "PROGRAMS");
  493. bool doing_files = true;
  494. bool doing_destination = false;
  495. bool doing_permissions = false;
  496. bool doing_configurations = false;
  497. bool doing_component = false;
  498. bool doing_rename = false;
  499. std::vector<std::string> files;
  500. const char* destination = 0;
  501. std::string rename;
  502. std::string permissions;
  503. std::vector<std::string> configurations;
  504. std::string component;
  505. for(unsigned int i=1; i < args.size(); ++i)
  506. {
  507. if(args[i] == "DESTINATION")
  508. {
  509. // Switch to setting the destination property.
  510. doing_files = false;
  511. doing_destination = true;
  512. doing_permissions = false;
  513. doing_configurations = false;
  514. doing_component = false;
  515. doing_rename = false;
  516. }
  517. else if(args[i] == "PERMISSIONS")
  518. {
  519. // Switch to setting the permissions property.
  520. doing_files = false;
  521. doing_destination = false;
  522. doing_permissions = true;
  523. doing_configurations = false;
  524. doing_component = false;
  525. doing_rename = false;
  526. }
  527. else if(args[i] == "CONFIGURATIONS")
  528. {
  529. // Switch to setting the configurations property.
  530. doing_files = false;
  531. doing_destination = false;
  532. doing_permissions = false;
  533. doing_configurations = true;
  534. doing_component = false;
  535. doing_rename = false;
  536. }
  537. else if(args[i] == "COMPONENT")
  538. {
  539. // Switch to setting the component property.
  540. doing_files = false;
  541. doing_destination = false;
  542. doing_permissions = false;
  543. doing_configurations = false;
  544. doing_component = true;
  545. doing_rename = false;
  546. }
  547. else if(args[i] == "RENAME")
  548. {
  549. // Switch to setting the rename property.
  550. doing_files = false;
  551. doing_destination = false;
  552. doing_permissions = false;
  553. doing_configurations = false;
  554. doing_component = false;
  555. doing_rename = true;
  556. }
  557. else if(doing_files)
  558. {
  559. // Convert this file to a full path.
  560. std::string file = args[i];
  561. if(!cmSystemTools::FileIsFullPath(file.c_str()))
  562. {
  563. file = this->Makefile->GetCurrentDirectory();
  564. file += "/";
  565. file += args[i];
  566. }
  567. // Make sure the file is not a directory.
  568. if(cmSystemTools::FileIsDirectory(file.c_str()))
  569. {
  570. cmOStringStream e;
  571. e << args[0] << " given directory \"" << args[i] << "\" to install.";
  572. this->SetError(e.str().c_str());
  573. return false;
  574. }
  575. // Store the file for installation.
  576. files.push_back(file);
  577. }
  578. else if(doing_configurations)
  579. {
  580. configurations.push_back(args[i]);
  581. }
  582. else if(doing_destination)
  583. {
  584. destination = args[i].c_str();
  585. doing_destination = false;
  586. }
  587. else if(doing_component)
  588. {
  589. component = args[i];
  590. doing_component = false;
  591. }
  592. else if(doing_permissions)
  593. {
  594. // Check the requested permission.
  595. if(!this->CheckPermissions(args[i], permissions))
  596. {
  597. cmOStringStream e;
  598. e << args[0] << " given invalid permission \""
  599. << args[i] << "\".";
  600. this->SetError(e.str().c_str());
  601. return false;
  602. }
  603. }
  604. else if(doing_rename)
  605. {
  606. rename = args[i];
  607. doing_rename = false;
  608. }
  609. else
  610. {
  611. // Unknown argument.
  612. cmOStringStream e;
  613. e << args[0] << " given unknown argument \"" << args[i] << "\".";
  614. this->SetError(e.str().c_str());
  615. return false;
  616. }
  617. }
  618. // Check if there is something to do.
  619. if(files.empty())
  620. {
  621. return true;
  622. }
  623. if(!destination)
  624. {
  625. // A destination is required.
  626. cmOStringStream e;
  627. e << args[0] << " given no DESTINATION!";
  628. this->SetError(e.str().c_str());
  629. return false;
  630. }
  631. if(!rename.empty() && files.size() > 1)
  632. {
  633. // The rename option works only with one file.
  634. cmOStringStream e;
  635. e << args[0] << " given RENAME option with more than one file.";
  636. this->SetError(e.str().c_str());
  637. return false;
  638. }
  639. // Compute destination path.
  640. std::string dest;
  641. this->ComputeDestination(destination, dest);
  642. // Create the files install generator.
  643. this->Makefile->AddInstallGenerator(
  644. new cmInstallFilesGenerator(files, dest.c_str(), programs,
  645. permissions.c_str(), configurations,
  646. component.c_str(), rename.c_str()));
  647. // Tell the global generator about any installation component names
  648. // specified.
  649. this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
  650. ->AddInstallComponent(component.c_str());
  651. return true;
  652. }
  653. //----------------------------------------------------------------------------
  654. void cmInstallCommand::ComputeDestination(const char* destination,
  655. std::string& dest)
  656. {
  657. if(destination)
  658. {
  659. if(cmSystemTools::FileIsFullPath(destination))
  660. {
  661. // Full paths are absolute.
  662. dest = destination;
  663. }
  664. else
  665. {
  666. // Relative paths are treated with respect to the installation prefix.
  667. dest = "${CMAKE_INSTALL_PREFIX}/";
  668. dest += destination;
  669. }
  670. // Format the path nicely. Note this also removes trailing
  671. // slashes.
  672. cmSystemTools::ConvertToUnixSlashes(dest);
  673. }
  674. else
  675. {
  676. dest = "";
  677. }
  678. }
  679. //----------------------------------------------------------------------------
  680. bool cmInstallCommand::CheckPermissions(std::string const& arg,
  681. std::string& permissions)
  682. {
  683. // Table of valid permissions.
  684. const char* table[] =
  685. {
  686. "OWNER_READ", "OWNER_WRITE", "OWNER_EXECUTE",
  687. "GROUP_READ", "GROUP_WRITE", "GROUP_EXECUTE",
  688. "WORLD_READ", "WORLD_WRITE", "WORLD_EXECUTE",
  689. "SETUID", "SETGID", 0
  690. };
  691. // Check the permission against the table.
  692. for(const char** valid = table; *valid; ++valid)
  693. {
  694. if(arg == *valid)
  695. {
  696. // This is a valid permission.
  697. permissions += " ";
  698. permissions += arg;
  699. return true;
  700. }
  701. }
  702. // This is not a valid permission.
  703. return false;
  704. }