/* 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 #include #include #include #include #include #include #include #include #include "cmGeneratorExpression.h" #include "cmInstallRuntimeDependencySet.h" #include "cmListFileCache.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmOutputConverter.h" #include "cmStringAlgorithms.h" namespace { template void WriteMultiArgument(std::ostream& os, const cm::string_view& keyword, const std::vector& list, cmScriptGeneratorIndent indent, F transform) { bool first = true; for (auto const& item : list) { cm::optional result = transform(item); if (result) { if (first) { os << indent << " " << keyword << "\n"; first = false; } os << indent << " " << *result << "\n"; } } } void WriteFilesArgument( std::ostream& os, const cm::string_view& keyword, const std::vector>& items, const std::string& config, cmScriptGeneratorIndent indent) { WriteMultiArgument( os, keyword, items, indent, [config](const std::unique_ptr& i) -> std::string { return cmStrCat('"', i->GetItemPath(config), '"'); }); } void WriteGenexEvaluatorArgument(std::ostream& os, const cm::string_view& keyword, const std::vector& genexes, const std::string& config, cmLocalGenerator* lg, cmScriptGeneratorIndent indent) { WriteMultiArgument( os, keyword, genexes, indent, [config, lg](const std::string& genex) -> cm::optional { std::string result = cmGeneratorExpression::Evaluate(genex, lg, config); if (result.empty()) { return cm::nullopt; } return cmOutputConverter::EscapeForCMake(result); }); } } cmInstallGetRuntimeDependenciesGenerator:: cmInstallGetRuntimeDependenciesGenerator( cmInstallRuntimeDependencySet* runtimeDependencySet, std::vector directories, std::vector preIncludeRegexes, std::vector preExcludeRegexes, std::vector postIncludeRegexes, std::vector postExcludeRegexes, std::vector postIncludeFiles, std::vector postExcludeFiles, std::string libraryComponent, std::string frameworkComponent, bool noInstallRPath, const char* depsVar, const char* rpathPrefix, std::vector 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, const std::string& 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 postExcludeFiles; auto const addPostExclude = [config, &postExcludeFiles, this]( const std::vector>& 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"; }