| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying |
| file Copyright.txt or https://cmake.org/licensing for details. */ |
| #include "cmInstallGetRuntimeDependenciesGenerator.h" |
| |
| #include <memory> |
| #include <ostream> |
| #include <set> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include <cm/optional> |
| #include <cm/string_view> |
| #include <cmext/string_view> |
| |
| #include "cmGeneratorExpression.h" |
| #include "cmInstallRuntimeDependencySet.h" |
| #include "cmListFileCache.h" |
| #include "cmLocalGenerator.h" |
| #include "cmMakefile.h" |
| #include "cmOutputConverter.h" |
| #include "cmScriptGenerator.h" |
| #include "cmStringAlgorithms.h" |
| |
| namespace { |
| template <typename T, typename F> |
| void WriteMultiArgument(std::ostream& os, cm::string_view const& keyword, |
| std::vector<T> const& list, |
| cmScriptGeneratorIndent indent, F transform) |
| { |
| bool first = true; |
| for (auto const& item : list) { |
| cm::optional<std::string> result = transform(item); |
| if (result) { |
| if (first) { |
| os << indent << " " << keyword << "\n"; |
| first = false; |
| } |
| os << indent << " " << *result << "\n"; |
| } |
| } |
| } |
| |
| void WriteFilesArgument( |
| std::ostream& os, cm::string_view const& keyword, |
| std::vector<std::unique_ptr<cmInstallRuntimeDependencySet::Item>> const& |
| items, |
| std::string const& config, cmScriptGeneratorIndent indent) |
| { |
| WriteMultiArgument( |
| os, keyword, items, indent, |
| [config](std::unique_ptr<cmInstallRuntimeDependencySet::Item> const& i) |
| -> std::string { return cmStrCat('"', i->GetItemPath(config), '"'); }); |
| } |
| |
| void WriteGenexEvaluatorArgument(std::ostream& os, |
| cm::string_view const& keyword, |
| std::vector<std::string> const& genexes, |
| std::string const& config, |
| cmLocalGenerator* lg, |
| cmScriptGeneratorIndent indent) |
| { |
| WriteMultiArgument( |
| os, keyword, genexes, indent, |
| [config, lg](std::string const& genex) -> cm::optional<std::string> { |
| std::string result = cmGeneratorExpression::Evaluate(genex, lg, config); |
| if (result.empty()) { |
| return cm::nullopt; |
| } |
| return cmOutputConverter::EscapeForCMake(result); |
| }); |
| } |
| } |
| |
| cmInstallGetRuntimeDependenciesGenerator:: |
| cmInstallGetRuntimeDependenciesGenerator( |
| cmInstallRuntimeDependencySet* runtimeDependencySet, |
| std::vector<std::string> directories, |
| std::vector<std::string> preIncludeRegexes, |
| std::vector<std::string> preExcludeRegexes, |
| std::vector<std::string> postIncludeRegexes, |
| std::vector<std::string> postExcludeRegexes, |
| std::vector<std::string> postIncludeFiles, |
| std::vector<std::string> postExcludeFiles, std::string libraryComponent, |
| std::string frameworkComponent, bool noInstallRPath, char const* depsVar, |
| char const* rpathPrefix, std::vector<std::string> const& configurations, |
| MessageLevel message, bool exclude_from_all, cmListFileBacktrace backtrace) |
| : cmInstallGenerator("", configurations, "", message, exclude_from_all, |
| false, std::move(backtrace)) |
| , RuntimeDependencySet(runtimeDependencySet) |
| , Directories(std::move(directories)) |
| , PreIncludeRegexes(std::move(preIncludeRegexes)) |
| , PreExcludeRegexes(std::move(preExcludeRegexes)) |
| , PostIncludeRegexes(std::move(postIncludeRegexes)) |
| , PostExcludeRegexes(std::move(postExcludeRegexes)) |
| , PostIncludeFiles(std::move(postIncludeFiles)) |
| , PostExcludeFiles(std::move(postExcludeFiles)) |
| , LibraryComponent(std::move(libraryComponent)) |
| , FrameworkComponent(std::move(frameworkComponent)) |
| , NoInstallRPath(noInstallRPath) |
| , DepsVar(depsVar) |
| , RPathPrefix(rpathPrefix) |
| { |
| this->ActionsPerConfig = true; |
| } |
| |
| bool cmInstallGetRuntimeDependenciesGenerator::Compute(cmLocalGenerator* lg) |
| { |
| this->LocalGenerator = lg; |
| return true; |
| } |
| |
| void cmInstallGetRuntimeDependenciesGenerator::GenerateScript(std::ostream& os) |
| { |
| // Track indentation. |
| Indent indent; |
| |
| // Begin this block of installation. |
| os << indent << "if("; |
| if (this->FrameworkComponent.empty() || |
| this->FrameworkComponent == this->LibraryComponent) { |
| os << this->CreateComponentTest(this->LibraryComponent, |
| this->ExcludeFromAll); |
| } else { |
| os << this->CreateComponentTest(this->LibraryComponent, true) << " OR " |
| << this->CreateComponentTest(this->FrameworkComponent, |
| this->ExcludeFromAll); |
| } |
| os << ")\n"; |
| |
| // Generate the script possibly with per-configuration code. |
| this->GenerateScriptConfigs(os, indent.Next()); |
| |
| // End this block of installation. |
| os << indent << "endif()\n\n"; |
| } |
| |
| void cmInstallGetRuntimeDependenciesGenerator::GenerateScriptForConfig( |
| std::ostream& os, std::string const& config, Indent indent) |
| { |
| std::string installNameTool = |
| this->LocalGenerator->GetMakefile()->GetSafeDefinition( |
| "CMAKE_INSTALL_NAME_TOOL"); |
| |
| os << indent << "file(GET_RUNTIME_DEPENDENCIES\n" |
| << indent << " RESOLVED_DEPENDENCIES_VAR " << this->DepsVar << '\n'; |
| WriteFilesArgument(os, "EXECUTABLES"_s, |
| this->RuntimeDependencySet->GetExecutables(), config, |
| indent); |
| WriteFilesArgument(os, "LIBRARIES"_s, |
| this->RuntimeDependencySet->GetLibraries(), config, |
| indent); |
| WriteFilesArgument(os, "MODULES"_s, this->RuntimeDependencySet->GetModules(), |
| config, indent); |
| if (this->RuntimeDependencySet->GetBundleExecutable()) { |
| os << indent << " BUNDLE_EXECUTABLE \"" |
| << this->RuntimeDependencySet->GetBundleExecutable()->GetItemPath( |
| config) |
| << "\"\n"; |
| } |
| WriteGenexEvaluatorArgument(os, "DIRECTORIES"_s, this->Directories, config, |
| this->LocalGenerator, indent); |
| WriteGenexEvaluatorArgument(os, "PRE_INCLUDE_REGEXES"_s, |
| this->PreIncludeRegexes, config, |
| this->LocalGenerator, indent); |
| WriteGenexEvaluatorArgument(os, "PRE_EXCLUDE_REGEXES"_s, |
| this->PreExcludeRegexes, config, |
| this->LocalGenerator, indent); |
| WriteGenexEvaluatorArgument(os, "POST_INCLUDE_REGEXES"_s, |
| this->PostIncludeRegexes, config, |
| this->LocalGenerator, indent); |
| WriteGenexEvaluatorArgument(os, "POST_EXCLUDE_REGEXES"_s, |
| this->PostExcludeRegexes, config, |
| this->LocalGenerator, indent); |
| WriteGenexEvaluatorArgument(os, "POST_INCLUDE_FILES"_s, |
| this->PostIncludeFiles, config, |
| this->LocalGenerator, indent); |
| WriteGenexEvaluatorArgument(os, "POST_EXCLUDE_FILES"_s, |
| this->PostExcludeFiles, config, |
| this->LocalGenerator, indent); |
| |
| std::set<std::string> postExcludeFiles; |
| auto const addPostExclude = |
| [config, &postExcludeFiles, this]( |
| std::vector<std::unique_ptr<cmInstallRuntimeDependencySet::Item>> const& |
| tgts) { |
| for (auto const& item : tgts) { |
| item->AddPostExcludeFiles(config, postExcludeFiles, |
| this->RuntimeDependencySet); |
| } |
| }; |
| addPostExclude(this->RuntimeDependencySet->GetExecutables()); |
| addPostExclude(this->RuntimeDependencySet->GetLibraries()); |
| addPostExclude(this->RuntimeDependencySet->GetModules()); |
| bool first = true; |
| for (auto const& file : postExcludeFiles) { |
| if (first) { |
| os << indent << " POST_EXCLUDE_FILES_STRICT\n"; |
| first = false; |
| } |
| os << indent << " \"" << file << "\"\n"; |
| } |
| |
| if (!installNameTool.empty() && !this->NoInstallRPath) { |
| os << indent << " RPATH_PREFIX " << this->RPathPrefix << '\n'; |
| } |
| os << indent << " )\n"; |
| } |