cmInstallGetRuntimeDependenciesGenerator.cxx 7.7 KB

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