cmInstallGetRuntimeDependenciesGenerator.cxx 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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 "cmInstallGetRuntimeDependenciesGenerator.h"
  4. #include <memory>
  5. #include <ostream>
  6. #include <set>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10. #include <cm/optional>
  11. #include <cm/string_view>
  12. #include <cmext/string_view>
  13. #include "cmGeneratorExpression.h"
  14. #include "cmInstallRuntimeDependencySet.h"
  15. #include "cmListFileCache.h"
  16. #include "cmLocalGenerator.h"
  17. #include "cmMakefile.h"
  18. #include "cmOutputConverter.h"
  19. #include "cmScriptGenerator.h"
  20. #include "cmStringAlgorithms.h"
  21. namespace {
  22. template <typename T, typename F>
  23. void WriteMultiArgument(std::ostream& os, const cm::string_view& keyword,
  24. const std::vector<T>& list,
  25. cmScriptGeneratorIndent indent, F transform)
  26. {
  27. bool first = true;
  28. for (auto const& item : list) {
  29. cm::optional<std::string> result = transform(item);
  30. if (result) {
  31. if (first) {
  32. os << indent << " " << keyword << "\n";
  33. first = false;
  34. }
  35. os << indent << " " << *result << "\n";
  36. }
  37. }
  38. }
  39. void WriteFilesArgument(
  40. std::ostream& os, const cm::string_view& keyword,
  41. const std::vector<std::unique_ptr<cmInstallRuntimeDependencySet::Item>>&
  42. items,
  43. const std::string& config, cmScriptGeneratorIndent indent)
  44. {
  45. WriteMultiArgument(
  46. os, keyword, items, indent,
  47. [config](const std::unique_ptr<cmInstallRuntimeDependencySet::Item>& i)
  48. -> std::string { return cmStrCat('"', i->GetItemPath(config), '"'); });
  49. }
  50. void WriteGenexEvaluatorArgument(std::ostream& os,
  51. const cm::string_view& keyword,
  52. const std::vector<std::string>& genexes,
  53. const std::string& config,
  54. cmLocalGenerator* lg,
  55. cmScriptGeneratorIndent indent)
  56. {
  57. WriteMultiArgument(
  58. os, keyword, genexes, indent,
  59. [config, lg](const std::string& genex) -> cm::optional<std::string> {
  60. std::string result = cmGeneratorExpression::Evaluate(genex, lg, config);
  61. if (result.empty()) {
  62. return cm::nullopt;
  63. }
  64. return cmOutputConverter::EscapeForCMake(result);
  65. });
  66. }
  67. }
  68. cmInstallGetRuntimeDependenciesGenerator::
  69. cmInstallGetRuntimeDependenciesGenerator(
  70. cmInstallRuntimeDependencySet* runtimeDependencySet,
  71. std::vector<std::string> directories,
  72. std::vector<std::string> preIncludeRegexes,
  73. std::vector<std::string> preExcludeRegexes,
  74. std::vector<std::string> postIncludeRegexes,
  75. std::vector<std::string> postExcludeRegexes,
  76. std::vector<std::string> postIncludeFiles,
  77. std::vector<std::string> postExcludeFiles, std::string libraryComponent,
  78. std::string frameworkComponent, bool noInstallRPath, const char* depsVar,
  79. const char* rpathPrefix, std::vector<std::string> const& configurations,
  80. MessageLevel message, bool exclude_from_all, cmListFileBacktrace backtrace)
  81. : cmInstallGenerator("", configurations, "", message, exclude_from_all,
  82. false, std::move(backtrace))
  83. , RuntimeDependencySet(runtimeDependencySet)
  84. , Directories(std::move(directories))
  85. , PreIncludeRegexes(std::move(preIncludeRegexes))
  86. , PreExcludeRegexes(std::move(preExcludeRegexes))
  87. , PostIncludeRegexes(std::move(postIncludeRegexes))
  88. , PostExcludeRegexes(std::move(postExcludeRegexes))
  89. , PostIncludeFiles(std::move(postIncludeFiles))
  90. , PostExcludeFiles(std::move(postExcludeFiles))
  91. , LibraryComponent(std::move(libraryComponent))
  92. , FrameworkComponent(std::move(frameworkComponent))
  93. , NoInstallRPath(noInstallRPath)
  94. , DepsVar(depsVar)
  95. , RPathPrefix(rpathPrefix)
  96. {
  97. this->ActionsPerConfig = true;
  98. }
  99. bool cmInstallGetRuntimeDependenciesGenerator::Compute(cmLocalGenerator* lg)
  100. {
  101. this->LocalGenerator = lg;
  102. return true;
  103. }
  104. void cmInstallGetRuntimeDependenciesGenerator::GenerateScript(std::ostream& os)
  105. {
  106. // Track indentation.
  107. Indent indent;
  108. // Begin this block of installation.
  109. os << indent << "if(";
  110. if (this->FrameworkComponent.empty() ||
  111. this->FrameworkComponent == this->LibraryComponent) {
  112. os << this->CreateComponentTest(this->LibraryComponent,
  113. this->ExcludeFromAll);
  114. } else {
  115. os << this->CreateComponentTest(this->LibraryComponent, true) << " OR "
  116. << this->CreateComponentTest(this->FrameworkComponent,
  117. this->ExcludeFromAll);
  118. }
  119. os << ")\n";
  120. // Generate the script possibly with per-configuration code.
  121. this->GenerateScriptConfigs(os, indent.Next());
  122. // End this block of installation.
  123. os << indent << "endif()\n\n";
  124. }
  125. void cmInstallGetRuntimeDependenciesGenerator::GenerateScriptForConfig(
  126. std::ostream& os, const std::string& config, Indent indent)
  127. {
  128. std::string installNameTool =
  129. this->LocalGenerator->GetMakefile()->GetSafeDefinition(
  130. "CMAKE_INSTALL_NAME_TOOL");
  131. os << indent << "file(GET_RUNTIME_DEPENDENCIES\n"
  132. << indent << " RESOLVED_DEPENDENCIES_VAR " << this->DepsVar << '\n';
  133. WriteFilesArgument(os, "EXECUTABLES"_s,
  134. this->RuntimeDependencySet->GetExecutables(), config,
  135. indent);
  136. WriteFilesArgument(os, "LIBRARIES"_s,
  137. this->RuntimeDependencySet->GetLibraries(), config,
  138. indent);
  139. WriteFilesArgument(os, "MODULES"_s, this->RuntimeDependencySet->GetModules(),
  140. config, indent);
  141. if (this->RuntimeDependencySet->GetBundleExecutable()) {
  142. os << indent << " BUNDLE_EXECUTABLE \""
  143. << this->RuntimeDependencySet->GetBundleExecutable()->GetItemPath(
  144. config)
  145. << "\"\n";
  146. }
  147. WriteGenexEvaluatorArgument(os, "DIRECTORIES"_s, this->Directories, config,
  148. this->LocalGenerator, indent);
  149. WriteGenexEvaluatorArgument(os, "PRE_INCLUDE_REGEXES"_s,
  150. this->PreIncludeRegexes, config,
  151. this->LocalGenerator, indent);
  152. WriteGenexEvaluatorArgument(os, "PRE_EXCLUDE_REGEXES"_s,
  153. this->PreExcludeRegexes, config,
  154. this->LocalGenerator, indent);
  155. WriteGenexEvaluatorArgument(os, "POST_INCLUDE_REGEXES"_s,
  156. this->PostIncludeRegexes, config,
  157. this->LocalGenerator, indent);
  158. WriteGenexEvaluatorArgument(os, "POST_EXCLUDE_REGEXES"_s,
  159. this->PostExcludeRegexes, config,
  160. this->LocalGenerator, indent);
  161. WriteGenexEvaluatorArgument(os, "POST_INCLUDE_FILES"_s,
  162. this->PostIncludeFiles, config,
  163. this->LocalGenerator, indent);
  164. WriteGenexEvaluatorArgument(os, "POST_EXCLUDE_FILES"_s,
  165. this->PostExcludeFiles, config,
  166. this->LocalGenerator, indent);
  167. std::set<std::string> postExcludeFiles;
  168. auto const addPostExclude =
  169. [config, &postExcludeFiles, this](
  170. const std::vector<std::unique_ptr<cmInstallRuntimeDependencySet::Item>>&
  171. tgts) {
  172. for (auto const& item : tgts) {
  173. item->AddPostExcludeFiles(config, postExcludeFiles,
  174. this->RuntimeDependencySet);
  175. }
  176. };
  177. addPostExclude(this->RuntimeDependencySet->GetExecutables());
  178. addPostExclude(this->RuntimeDependencySet->GetLibraries());
  179. addPostExclude(this->RuntimeDependencySet->GetModules());
  180. bool first = true;
  181. for (auto const& file : postExcludeFiles) {
  182. if (first) {
  183. os << indent << " POST_EXCLUDE_FILES_STRICT\n";
  184. first = false;
  185. }
  186. os << indent << " \"" << file << "\"\n";
  187. }
  188. if (!installNameTool.empty() && !this->NoInstallRPath) {
  189. os << indent << " RPATH_PREFIX " << this->RPathPrefix << '\n';
  190. }
  191. os << indent << " )\n";
  192. }