cmInstallGenerator.cxx 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  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 "cmInstallGenerator.h"
  4. #include <sstream>
  5. #include <utility>
  6. #include "cmMakefile.h"
  7. #include "cmStringAlgorithms.h"
  8. #include "cmSystemTools.h"
  9. cmInstallGenerator::cmInstallGenerator(
  10. std::string destination, std::vector<std::string> const& configurations,
  11. std::string component, MessageLevel message, bool exclude_from_all,
  12. bool all_components, cmListFileBacktrace backtrace)
  13. : cmScriptGenerator("CMAKE_INSTALL_CONFIG_NAME", configurations)
  14. , Destination(std::move(destination))
  15. , Component(std::move(component))
  16. , Message(message)
  17. , ExcludeFromAll(exclude_from_all)
  18. , AllComponents(all_components)
  19. , Backtrace(std::move(backtrace))
  20. {
  21. }
  22. cmInstallGenerator::~cmInstallGenerator() = default;
  23. bool cmInstallGenerator::HaveInstall()
  24. {
  25. return true;
  26. }
  27. void cmInstallGenerator::CheckCMP0082(bool& haveSubdirectoryInstall,
  28. bool& haveInstallAfterSubdirectory)
  29. {
  30. if (haveSubdirectoryInstall) {
  31. haveInstallAfterSubdirectory = true;
  32. }
  33. }
  34. void cmInstallGenerator::AddInstallRule(
  35. std::ostream& os, std::string const& dest, cmInstallType type,
  36. std::vector<std::string> const& files, bool optional /* = false */,
  37. const char* permissions_file /* = 0 */,
  38. const char* permissions_dir /* = 0 */, const char* rename /* = 0 */,
  39. const char* literal_args /* = 0 */, Indent indent,
  40. const char* files_var /* = 0 */)
  41. {
  42. // Use the FILE command to install the file.
  43. std::string stype;
  44. switch (type) {
  45. case cmInstallType_DIRECTORY:
  46. stype = "DIRECTORY";
  47. break;
  48. case cmInstallType_PROGRAMS:
  49. stype = "PROGRAM";
  50. break;
  51. case cmInstallType_EXECUTABLE:
  52. stype = "EXECUTABLE";
  53. break;
  54. case cmInstallType_STATIC_LIBRARY:
  55. stype = "STATIC_LIBRARY";
  56. break;
  57. case cmInstallType_SHARED_LIBRARY:
  58. stype = "SHARED_LIBRARY";
  59. break;
  60. case cmInstallType_MODULE_LIBRARY:
  61. stype = "MODULE";
  62. break;
  63. case cmInstallType_FILES:
  64. stype = "FILE";
  65. break;
  66. }
  67. if (cmSystemTools::FileIsFullPath(dest)) {
  68. if (!files.empty()) {
  69. os << indent << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n";
  70. os << indent << " \"";
  71. bool firstIteration = true;
  72. for (std::string const& file : files) {
  73. if (!firstIteration) {
  74. os << ";";
  75. }
  76. os << dest << "/";
  77. if (rename && *rename) {
  78. os << rename;
  79. } else {
  80. os << cmSystemTools::GetFilenameName(file);
  81. }
  82. firstIteration = false;
  83. }
  84. os << "\")\n";
  85. }
  86. if (files_var) {
  87. os << indent << "foreach(_f IN LISTS " << files_var << ")\n";
  88. os << indent.Next() << "get_filename_component(_fn \"${_f}\" NAME)\n";
  89. os << indent.Next() << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES \""
  90. << dest << "/${_fn}\")\n";
  91. os << indent << "endforeach()\n";
  92. }
  93. os << indent << "if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
  94. os << indent.Next() << "message(WARNING \"ABSOLUTE path INSTALL "
  95. << "DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n";
  96. os << indent << "endif()\n";
  97. os << indent << "if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
  98. os << indent.Next() << "message(FATAL_ERROR \"ABSOLUTE path INSTALL "
  99. << "DESTINATION forbidden (by caller): "
  100. << "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n";
  101. os << indent << "endif()\n";
  102. }
  103. std::string absDest = ConvertToAbsoluteDestination(dest);
  104. os << indent << "file(INSTALL DESTINATION \"" << absDest << "\" TYPE "
  105. << stype;
  106. if (optional) {
  107. os << " OPTIONAL";
  108. }
  109. switch (this->Message) {
  110. case MessageDefault:
  111. break;
  112. case MessageAlways:
  113. os << " MESSAGE_ALWAYS";
  114. break;
  115. case MessageLazy:
  116. os << " MESSAGE_LAZY";
  117. break;
  118. case MessageNever:
  119. os << " MESSAGE_NEVER";
  120. break;
  121. }
  122. if (permissions_file && *permissions_file) {
  123. os << " PERMISSIONS" << permissions_file;
  124. }
  125. if (permissions_dir && *permissions_dir) {
  126. os << " DIR_PERMISSIONS" << permissions_dir;
  127. }
  128. if (rename && *rename) {
  129. os << " RENAME \"" << rename << "\"";
  130. }
  131. os << " FILES";
  132. if (files.size() == 1) {
  133. os << " \"" << files[0] << "\"";
  134. } else {
  135. for (std::string const& f : files) {
  136. os << "\n" << indent << " \"" << f << "\"";
  137. }
  138. if (files_var) {
  139. os << " ${" << files_var << "}";
  140. }
  141. os << "\n" << indent << " ";
  142. if (!(literal_args && *literal_args)) {
  143. os << " ";
  144. }
  145. }
  146. if (literal_args && *literal_args) {
  147. os << literal_args;
  148. }
  149. os << ")\n";
  150. }
  151. std::string cmInstallGenerator::CreateComponentTest(
  152. const std::string& component, bool exclude_from_all)
  153. {
  154. std::string result = "CMAKE_INSTALL_COMPONENT STREQUAL \"";
  155. result += component;
  156. result += "\"";
  157. if (!exclude_from_all) {
  158. result += " OR NOT CMAKE_INSTALL_COMPONENT";
  159. }
  160. return result;
  161. }
  162. void cmInstallGenerator::GenerateScript(std::ostream& os)
  163. {
  164. // Track indentation.
  165. Indent indent;
  166. // Begin this block of installation.
  167. if (!this->AllComponents) {
  168. std::string component_test =
  169. this->CreateComponentTest(this->Component, this->ExcludeFromAll);
  170. os << indent << "if(" << component_test << ")\n";
  171. }
  172. // Generate the script possibly with per-configuration code.
  173. this->GenerateScriptConfigs(os,
  174. this->AllComponents ? indent : indent.Next());
  175. // End this block of installation.
  176. if (!this->AllComponents) {
  177. os << indent << "endif()\n\n";
  178. }
  179. }
  180. bool cmInstallGenerator::InstallsForConfig(const std::string& config)
  181. {
  182. return this->GeneratesForConfig(config);
  183. }
  184. std::string cmInstallGenerator::ConvertToAbsoluteDestination(
  185. std::string const& dest)
  186. {
  187. std::string result;
  188. if (!dest.empty() && !cmSystemTools::FileIsFullPath(dest)) {
  189. result = "${CMAKE_INSTALL_PREFIX}/";
  190. }
  191. result += dest;
  192. return result;
  193. }
  194. cmInstallGenerator::MessageLevel cmInstallGenerator::SelectMessageLevel(
  195. cmMakefile* mf, bool never)
  196. {
  197. if (never) {
  198. return MessageNever;
  199. }
  200. std::string m = mf->GetSafeDefinition("CMAKE_INSTALL_MESSAGE");
  201. if (m == "ALWAYS") {
  202. return MessageAlways;
  203. }
  204. if (m == "LAZY") {
  205. return MessageLazy;
  206. }
  207. if (m == "NEVER") {
  208. return MessageNever;
  209. }
  210. return MessageDefault;
  211. }
  212. std::string cmInstallGenerator::GetDestDirPath(std::string const& file)
  213. {
  214. // Construct the path of the file on disk after installation on
  215. // which tweaks may be performed.
  216. std::string toDestDirPath = "$ENV{DESTDIR}";
  217. if (file[0] != '/' && file[0] != '$') {
  218. toDestDirPath += "/";
  219. }
  220. toDestDirPath += file;
  221. return toDestDirPath;
  222. }
  223. void cmInstallGenerator::AddTweak(std::ostream& os, Indent indent,
  224. const std::string& config,
  225. std::string const& file,
  226. const TweakMethod& tweak)
  227. {
  228. std::ostringstream tw;
  229. tweak(tw, indent.Next(), config, file);
  230. std::string tws = tw.str();
  231. if (!tws.empty()) {
  232. os << indent << "if(EXISTS \"" << file << "\" AND\n"
  233. << indent << " NOT IS_SYMLINK \"" << file << "\")\n";
  234. os << tws;
  235. os << indent << "endif()\n";
  236. }
  237. }
  238. void cmInstallGenerator::AddTweak(std::ostream& os, Indent indent,
  239. const std::string& config,
  240. std::string const& dir,
  241. std::vector<std::string> const& files,
  242. const TweakMethod& tweak)
  243. {
  244. if (files.size() == 1) {
  245. // Tweak a single file.
  246. AddTweak(os, indent, config, GetDestDirPath(cmStrCat(dir, files[0])),
  247. tweak);
  248. } else {
  249. // Generate a foreach loop to tweak multiple files.
  250. std::ostringstream tw;
  251. AddTweak(tw, indent.Next(), config, "${file}", tweak);
  252. std::string tws = tw.str();
  253. if (!tws.empty()) {
  254. Indent indent2 = indent.Next().Next();
  255. os << indent << "foreach(file\n";
  256. for (std::string const& f : files) {
  257. os << indent2 << "\"" << GetDestDirPath(cmStrCat(dir, f)) << "\"\n";
  258. }
  259. os << indent2 << ")\n";
  260. os << tws;
  261. os << indent << "endforeach()\n";
  262. }
  263. }
  264. }