| /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying | |
| file LICENSE.rst 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 "cmDiagnosticContext.h" | |
| #include "cmGeneratorExpression.h" | |
| #include "cmInstallRuntimeDependencySet.h" | |
| #include "cmListFileCache.h" | |
| #include "cmLocalGenerator.h" | |
| #include "cmMakefile.h" | |
| #include "cmOutputConverter.h" | |
| #include "cmPolicies.h" | |
| #include "cmScriptGenerator.h" | |
| #include "cmStringAlgorithms.h" | |
| class cmGeneratorTarget; | |
| namespace { | |
| template <typename T, typename F> | |
| void WriteMultiArgument(std::ostream& os, cm::string_view 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 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 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 excludeFromAll, cmListFileBacktrace backtrace, | |
| cmPolicies::PolicyStatus policyStatusCMP0207) | |
| : cmInstallGenerator("", configurations, "", message, excludeFromAll, false, | |
| cmDiagnosticContext{ 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)) | |
| , PolicyStatusCMP0207(policyStatusCMP0207) | |
| , NoInstallRPath(noInstallRPath) | |
| , DepsVar(depsVar) | |
| , RPathPrefix(rpathPrefix) | |
| { | |
| this->ActionsPerConfig = true; | |
| } | |
| bool cmInstallGetRuntimeDependenciesGenerator::Compute(cmLocalGenerator* lg) | |
| { | |
| this->LocalGenerator = lg; | |
| return true; | |
| } | |
| void cmInstallGetRuntimeDependenciesGenerator::GetInstallBuildDependencies( | |
| std::string const&, std::vector<BuildDependency>& dependencies) const | |
| { | |
| std::vector<cmGeneratorTarget const*> targets; | |
| this->RuntimeDependencySet->GetInstallBuildDependencies(targets); | |
| for (cmGeneratorTarget const* target : targets) { | |
| dependencies.push_back({ target, BuildDependencyType::Normal }); | |
| } | |
| } | |
| void cmInstallGetRuntimeDependenciesGenerator:: | |
| GetInstallBuildDependencyComponents( | |
| std::vector<std::string>& components) const | |
| { | |
| if (!this->LibraryComponent.empty()) { | |
| components.push_back(this->LibraryComponent); | |
| } | |
| if (!this->FrameworkComponent.empty() && | |
| this->FrameworkComponent != this->LibraryComponent) { | |
| components.push_back(this->FrameworkComponent); | |
| } | |
| } | |
| 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"); | |
| Indent inputIndent = indent; | |
| if (this->PolicyStatusCMP0207 != cmPolicies::WARN) { | |
| indent = indent.Next(); | |
| os << inputIndent << "block(SCOPE_FOR POLICIES)\n" | |
| << indent << "cmake_policy(SET CMP0207 " | |
| << (this->PolicyStatusCMP0207 == cmPolicies::NEW ? "NEW" : "OLD") | |
| << ")\n"; | |
| } | |
| 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"; | |
| if (this->PolicyStatusCMP0207 != cmPolicies::WARN) { | |
| os << inputIndent << "endblock()\n"; | |
| } | |
| } |