mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-14 02:08:27 +08:00
install(TARGETS): Add RUNTIME_DEPENDENCIES option
This commit is contained in:
@@ -345,6 +345,8 @@ set(SRCS
|
||||
cmGraphVizWriter.h
|
||||
cmInstallGenerator.h
|
||||
cmInstallGenerator.cxx
|
||||
cmInstallGetRuntimeDependenciesGenerator.h
|
||||
cmInstallGetRuntimeDependenciesGenerator.cxx
|
||||
cmInstallExportGenerator.cxx
|
||||
cmInstalledFile.h
|
||||
cmInstalledFile.cxx
|
||||
@@ -354,6 +356,8 @@ set(SRCS
|
||||
cmInstallImportedRuntimeArtifactsGenerator.cxx
|
||||
cmInstallRuntimeDependencySet.h
|
||||
cmInstallRuntimeDependencySet.cxx
|
||||
cmInstallRuntimeDependencySetGenerator.h
|
||||
cmInstallRuntimeDependencySetGenerator.cxx
|
||||
cmInstallScriptGenerator.h
|
||||
cmInstallScriptGenerator.cxx
|
||||
cmInstallSubdirectoryGenerator.h
|
||||
|
@@ -3044,11 +3044,10 @@ bool HandleCreateLinkCommand(std::vector<std::string> const& args,
|
||||
bool HandleGetRuntimeDependenciesCommand(std::vector<std::string> const& args,
|
||||
cmExecutionStatus& status)
|
||||
{
|
||||
static const std::set<std::string> supportedPlatforms = { "Windows", "Linux",
|
||||
"Darwin" };
|
||||
std::string platform =
|
||||
status.GetMakefile().GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
|
||||
if (!supportedPlatforms.count(platform)) {
|
||||
if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
|
||||
platform)) {
|
||||
status.SetError(
|
||||
cmStrCat("GET_RUNTIME_DEPENDENCIES is not supported on system \"",
|
||||
platform, "\""));
|
||||
|
@@ -2,8 +2,10 @@
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmInstallCommand.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
@@ -23,7 +25,10 @@
|
||||
#include "cmInstallExportGenerator.h"
|
||||
#include "cmInstallFilesGenerator.h"
|
||||
#include "cmInstallGenerator.h"
|
||||
#include "cmInstallGetRuntimeDependenciesGenerator.h"
|
||||
#include "cmInstallImportedRuntimeArtifactsGenerator.h"
|
||||
#include "cmInstallRuntimeDependencySet.h"
|
||||
#include "cmInstallRuntimeDependencySetGenerator.h"
|
||||
#include "cmInstallScriptGenerator.h"
|
||||
#include "cmInstallTargetGenerator.h"
|
||||
#include "cmListFileCache.h"
|
||||
@@ -31,6 +36,7 @@
|
||||
#include "cmMessageType.h"
|
||||
#include "cmPolicies.h"
|
||||
#include "cmProperty.h"
|
||||
#include "cmRuntimeDependencyArchive.h"
|
||||
#include "cmStateTypes.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmSubcommandTable.h"
|
||||
@@ -40,6 +46,29 @@
|
||||
|
||||
namespace {
|
||||
|
||||
struct RuntimeDependenciesArgs
|
||||
{
|
||||
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;
|
||||
};
|
||||
|
||||
auto const RuntimeDependenciesArgHelper =
|
||||
cmArgumentParser<RuntimeDependenciesArgs>{}
|
||||
.Bind("DIRECTORIES"_s, &RuntimeDependenciesArgs::Directories)
|
||||
.Bind("PRE_INCLUDE_REGEXES"_s, &RuntimeDependenciesArgs::PreIncludeRegexes)
|
||||
.Bind("PRE_EXCLUDE_REGEXES"_s, &RuntimeDependenciesArgs::PreExcludeRegexes)
|
||||
.Bind("POST_INCLUDE_REGEXES"_s,
|
||||
&RuntimeDependenciesArgs::PostIncludeRegexes)
|
||||
.Bind("POST_EXCLUDE_REGEXES"_s,
|
||||
&RuntimeDependenciesArgs::PostExcludeRegexes)
|
||||
.Bind("POST_INCLUDE_FILES"_s, &RuntimeDependenciesArgs::PostIncludeFiles)
|
||||
.Bind("POST_EXCLUDE_FILES"_s, &RuntimeDependenciesArgs::PostExcludeFiles);
|
||||
|
||||
class Helper
|
||||
{
|
||||
public:
|
||||
@@ -147,12 +176,106 @@ std::unique_ptr<cmInstallFilesGenerator> CreateInstallFilesGenerator(
|
||||
args.GetDestination());
|
||||
}
|
||||
|
||||
void AddInstallRuntimeDependenciesGenerator(
|
||||
Helper& helper, cmInstallRuntimeDependencySet* runtimeDependencySet,
|
||||
const cmInstallCommandArguments& runtimeArgs,
|
||||
const cmInstallCommandArguments& libraryArgs,
|
||||
const cmInstallCommandArguments& frameworkArgs,
|
||||
RuntimeDependenciesArgs runtimeDependenciesArgs, bool& installsRuntime,
|
||||
bool& installsLibrary, bool& installsFramework)
|
||||
{
|
||||
bool dllPlatform =
|
||||
!helper.Makefile->GetSafeDefinition("CMAKE_IMPORT_LIBRARY_SUFFIX").empty();
|
||||
bool apple =
|
||||
helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME") == "Darwin";
|
||||
auto const& runtimeDependenciesArgsRef =
|
||||
dllPlatform ? runtimeArgs : libraryArgs;
|
||||
std::vector<std::string> configurations =
|
||||
runtimeDependenciesArgsRef.GetConfigurations();
|
||||
if (apple) {
|
||||
std::copy(frameworkArgs.GetConfigurations().begin(),
|
||||
frameworkArgs.GetConfigurations().end(),
|
||||
std::back_inserter(configurations));
|
||||
}
|
||||
|
||||
// Create file(GET_RUNTIME_DEPENDENCIES) generator.
|
||||
auto getRuntimeDependenciesGenerator =
|
||||
cm::make_unique<cmInstallGetRuntimeDependenciesGenerator>(
|
||||
runtimeDependencySet, std::move(runtimeDependenciesArgs.Directories),
|
||||
std::move(runtimeDependenciesArgs.PreIncludeRegexes),
|
||||
std::move(runtimeDependenciesArgs.PreExcludeRegexes),
|
||||
std::move(runtimeDependenciesArgs.PostIncludeRegexes),
|
||||
std::move(runtimeDependenciesArgs.PostExcludeRegexes),
|
||||
std::move(runtimeDependenciesArgs.PostIncludeFiles),
|
||||
std::move(runtimeDependenciesArgs.PostExcludeFiles),
|
||||
runtimeDependenciesArgsRef.GetComponent(),
|
||||
apple ? frameworkArgs.GetComponent() : "", true, "_CMAKE_DEPS",
|
||||
"_CMAKE_RPATH", configurations,
|
||||
cmInstallGenerator::SelectMessageLevel(helper.Makefile),
|
||||
runtimeDependenciesArgsRef.GetExcludeFromAll() &&
|
||||
(apple ? frameworkArgs.GetExcludeFromAll() : true),
|
||||
helper.Makefile->GetBacktrace());
|
||||
helper.Makefile->AddInstallGenerator(
|
||||
std::move(getRuntimeDependenciesGenerator));
|
||||
|
||||
// Create the library dependencies generator.
|
||||
auto libraryRuntimeDependenciesGenerator =
|
||||
cm::make_unique<cmInstallRuntimeDependencySetGenerator>(
|
||||
cmInstallRuntimeDependencySetGenerator::DependencyType::Library,
|
||||
runtimeDependencySet, std::vector<std::string>{}, true, std::string{},
|
||||
true, "_CMAKE_DEPS", "_CMAKE_RPATH", "_CMAKE_TMP",
|
||||
dllPlatform ? helper.GetRuntimeDestination(&runtimeArgs)
|
||||
: helper.GetLibraryDestination(&libraryArgs),
|
||||
runtimeDependenciesArgsRef.GetConfigurations(),
|
||||
runtimeDependenciesArgsRef.GetComponent(),
|
||||
runtimeDependenciesArgsRef.GetPermissions(),
|
||||
cmInstallGenerator::SelectMessageLevel(helper.Makefile),
|
||||
runtimeDependenciesArgsRef.GetExcludeFromAll(),
|
||||
helper.Makefile->GetBacktrace());
|
||||
helper.Makefile->AddInstallGenerator(
|
||||
std::move(libraryRuntimeDependenciesGenerator));
|
||||
if (dllPlatform) {
|
||||
installsRuntime = true;
|
||||
} else {
|
||||
installsLibrary = true;
|
||||
}
|
||||
|
||||
if (apple) {
|
||||
// Create the framework dependencies generator.
|
||||
auto frameworkRuntimeDependenciesGenerator =
|
||||
cm::make_unique<cmInstallRuntimeDependencySetGenerator>(
|
||||
cmInstallRuntimeDependencySetGenerator::DependencyType::Framework,
|
||||
runtimeDependencySet, std::vector<std::string>{}, true, std::string{},
|
||||
true, "_CMAKE_DEPS", "_CMAKE_RPATH", "_CMAKE_TMP",
|
||||
frameworkArgs.GetDestination(), frameworkArgs.GetConfigurations(),
|
||||
frameworkArgs.GetComponent(), frameworkArgs.GetPermissions(),
|
||||
cmInstallGenerator::SelectMessageLevel(helper.Makefile),
|
||||
frameworkArgs.GetExcludeFromAll(), helper.Makefile->GetBacktrace());
|
||||
helper.Makefile->AddInstallGenerator(
|
||||
std::move(frameworkRuntimeDependenciesGenerator));
|
||||
installsFramework = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::set<std::string> const allowedTypes{
|
||||
"BIN", "SBIN", "LIB", "INCLUDE", "SYSCONF",
|
||||
"SHAREDSTATE", "LOCALSTATE", "RUNSTATE", "DATA", "INFO",
|
||||
"LOCALE", "MAN", "DOC",
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
bool AddBundleExecutable(Helper& helper,
|
||||
cmInstallRuntimeDependencySet* runtimeDependencySet,
|
||||
T&& bundleExecutable)
|
||||
{
|
||||
if (!runtimeDependencySet->AddBundleExecutable(bundleExecutable)) {
|
||||
helper.SetError(
|
||||
"A runtime dependency set may only have one bundle executable.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HandleScriptMode(std::vector<std::string> const& args,
|
||||
cmExecutionStatus& status)
|
||||
{
|
||||
@@ -289,13 +412,23 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
|
||||
// These generic args also contain the targets and the export stuff
|
||||
std::vector<std::string> targetList;
|
||||
std::string exports;
|
||||
std::vector<std::string> runtimeDependenciesArgVector;
|
||||
std::vector<std::string> unknownArgs;
|
||||
std::vector<std::string> parsedArgs;
|
||||
cmInstallCommandArguments genericArgs(helper.DefaultComponentName);
|
||||
genericArgs.Bind("TARGETS"_s, targetList);
|
||||
genericArgs.Bind("EXPORT"_s, exports);
|
||||
genericArgs.Parse(genericArgVector, &unknownArgs);
|
||||
genericArgs.Bind("RUNTIME_DEPENDENCIES"_s, runtimeDependenciesArgVector);
|
||||
genericArgs.Parse(genericArgVector, &unknownArgs, nullptr, &parsedArgs);
|
||||
bool success = genericArgs.Finalize();
|
||||
|
||||
bool withRuntimeDependencies =
|
||||
std::find(parsedArgs.begin(), parsedArgs.end(), "RUNTIME_DEPENDENCIES") !=
|
||||
parsedArgs.end();
|
||||
RuntimeDependenciesArgs runtimeDependenciesArgs =
|
||||
RuntimeDependenciesArgHelper.Parse(runtimeDependenciesArgVector,
|
||||
&unknownArgs);
|
||||
|
||||
cmInstallCommandArguments archiveArgs(helper.DefaultComponentName);
|
||||
cmInstallCommandArguments libraryArgs(helper.DefaultComponentName);
|
||||
cmInstallCommandArguments runtimeArgs(helper.DefaultComponentName);
|
||||
@@ -402,6 +535,32 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
|
||||
return false;
|
||||
}
|
||||
|
||||
cmInstallRuntimeDependencySet* runtimeDependencySet = nullptr;
|
||||
if (withRuntimeDependencies) {
|
||||
auto system = helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
|
||||
if (!cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
|
||||
system)) {
|
||||
status.SetError(
|
||||
cmStrCat("TARGETS RUNTIME_DEPENDENCIES is not supported on system \"",
|
||||
system, '"'));
|
||||
return false;
|
||||
}
|
||||
if (helper.Makefile->IsOn("CMAKE_CROSSCOMPILING")) {
|
||||
status.SetError("TARGETS RUNTIME_DEPENDENCIES is not supported "
|
||||
"when cross-compiling.");
|
||||
return false;
|
||||
}
|
||||
if (helper.Makefile->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME") ==
|
||||
"Darwin" &&
|
||||
frameworkArgs.GetDestination().empty()) {
|
||||
status.SetError(
|
||||
"TARGETS RUNTIME_DEPENDENCIES given no FRAMEWORK DESTINATION");
|
||||
return false;
|
||||
}
|
||||
runtimeDependencySet = helper.Makefile->GetGlobalGenerator()
|
||||
->CreateAnonymousRuntimeDependencySet();
|
||||
}
|
||||
|
||||
// Select the mode for installing symlinks to versioned shared libraries.
|
||||
cmInstallTargetGenerator::NamelinkModeType namelinkMode =
|
||||
cmInstallTargetGenerator::NamelinkModeNone;
|
||||
@@ -546,6 +705,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
|
||||
target, runtimeArgs, false, helper.Makefile->GetBacktrace(),
|
||||
helper.GetRuntimeDestination(nullptr));
|
||||
}
|
||||
if (runtimeDependencySet && runtimeGenerator) {
|
||||
runtimeDependencySet->AddLibrary(runtimeGenerator.get());
|
||||
}
|
||||
} else {
|
||||
// This is a non-DLL platform.
|
||||
// If it is marked with FRAMEWORK property use the FRAMEWORK set of
|
||||
@@ -591,6 +753,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
|
||||
namelinkOnly =
|
||||
(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
|
||||
}
|
||||
if (runtimeDependencySet && libraryGenerator) {
|
||||
runtimeDependencySet->AddLibrary(libraryGenerator.get());
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case cmStateEnums::STATIC_LIBRARY: {
|
||||
@@ -633,6 +798,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
|
||||
libraryGenerator->SetNamelinkMode(namelinkMode);
|
||||
namelinkOnly =
|
||||
(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly);
|
||||
if (runtimeDependencySet) {
|
||||
runtimeDependencySet->AddModule(libraryGenerator.get());
|
||||
}
|
||||
} else {
|
||||
status.SetError(
|
||||
cmStrCat("TARGETS given no LIBRARY DESTINATION for module "
|
||||
@@ -685,6 +853,12 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
|
||||
target.GetName(), "\"."));
|
||||
return false;
|
||||
}
|
||||
if (runtimeDependencySet) {
|
||||
if (!AddBundleExecutable(helper, runtimeDependencySet,
|
||||
bundleGenerator.get())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Executables use the RUNTIME properties.
|
||||
if (!runtimeArgs.GetDestination().empty()) {
|
||||
@@ -693,6 +867,9 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
|
||||
runtimeGenerator = CreateInstallTargetGenerator(
|
||||
target, runtimeArgs, false, helper.Makefile->GetBacktrace(),
|
||||
helper.GetRuntimeDestination(&runtimeArgs));
|
||||
if (runtimeDependencySet) {
|
||||
runtimeDependencySet->AddExecutable(runtimeGenerator.get());
|
||||
}
|
||||
}
|
||||
|
||||
// On DLL platforms an executable may also have an import
|
||||
@@ -821,6 +998,13 @@ bool HandleTargetsMode(std::vector<std::string> const& args,
|
||||
helper.Makefile->AddInstallGenerator(std::move(resourceGenerator));
|
||||
}
|
||||
|
||||
if (withRuntimeDependencies && !runtimeDependencySet->Empty()) {
|
||||
AddInstallRuntimeDependenciesGenerator(
|
||||
helper, runtimeDependencySet, runtimeArgs, libraryArgs, frameworkArgs,
|
||||
std::move(runtimeDependenciesArgs), installsRuntime, installsLibrary,
|
||||
installsFramework);
|
||||
}
|
||||
|
||||
// Tell the global generator about any installation component names
|
||||
// specified
|
||||
if (installsArchive) {
|
||||
|
@@ -43,7 +43,8 @@ void cmInstallGenerator::AddInstallRule(
|
||||
std::vector<std::string> const& files, bool optional /* = false */,
|
||||
const char* permissions_file /* = 0 */,
|
||||
const char* permissions_dir /* = 0 */, const char* rename /* = 0 */,
|
||||
const char* literal_args /* = 0 */, Indent indent)
|
||||
const char* literal_args /* = 0 */, Indent indent,
|
||||
const char* files_var /* = 0 */)
|
||||
{
|
||||
// Use the FILE command to install the file.
|
||||
std::string stype;
|
||||
@@ -70,37 +71,46 @@ void cmInstallGenerator::AddInstallRule(
|
||||
stype = "FILE";
|
||||
break;
|
||||
}
|
||||
os << indent;
|
||||
if (cmSystemTools::FileIsFullPath(dest)) {
|
||||
os << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n";
|
||||
os << indent << " \"";
|
||||
bool firstIteration = true;
|
||||
for (std::string const& file : files) {
|
||||
if (!firstIteration) {
|
||||
os << ";";
|
||||
if (!files.empty()) {
|
||||
os << indent << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES\n";
|
||||
os << indent << " \"";
|
||||
bool firstIteration = true;
|
||||
for (std::string const& file : files) {
|
||||
if (!firstIteration) {
|
||||
os << ";";
|
||||
}
|
||||
os << dest << "/";
|
||||
if (rename && *rename) {
|
||||
os << rename;
|
||||
} else {
|
||||
os << cmSystemTools::GetFilenameName(file);
|
||||
}
|
||||
firstIteration = false;
|
||||
}
|
||||
os << dest << "/";
|
||||
if (rename && *rename) {
|
||||
os << rename;
|
||||
} else {
|
||||
os << cmSystemTools::GetFilenameName(file);
|
||||
}
|
||||
firstIteration = false;
|
||||
os << "\")\n";
|
||||
}
|
||||
if (files_var) {
|
||||
os << indent << "foreach(_f IN LISTS " << files_var << ")\n";
|
||||
os << indent.Next() << "get_filename_component(_fn \"${_f}\" NAME)\n";
|
||||
os << indent.Next() << "list(APPEND CMAKE_ABSOLUTE_DESTINATION_FILES \""
|
||||
<< dest << "/${_fn}\")\n";
|
||||
os << indent << "endforeach()\n";
|
||||
}
|
||||
os << "\")\n";
|
||||
os << indent << "if(CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
|
||||
os << indent << indent << "message(WARNING \"ABSOLUTE path INSTALL "
|
||||
os << indent.Next() << "message(WARNING \"ABSOLUTE path INSTALL "
|
||||
<< "DESTINATION : ${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n";
|
||||
os << indent << "endif()\n";
|
||||
|
||||
os << indent << "if(CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION)\n";
|
||||
os << indent << indent << "message(FATAL_ERROR \"ABSOLUTE path INSTALL "
|
||||
os << indent.Next() << "message(FATAL_ERROR \"ABSOLUTE path INSTALL "
|
||||
<< "DESTINATION forbidden (by caller): "
|
||||
<< "${CMAKE_ABSOLUTE_DESTINATION_FILES}\")\n";
|
||||
os << indent << "endif()\n";
|
||||
}
|
||||
std::string absDest = ConvertToAbsoluteDestination(dest);
|
||||
os << "file(INSTALL DESTINATION \"" << absDest << "\" TYPE " << stype;
|
||||
os << indent << "file(INSTALL DESTINATION \"" << absDest << "\" TYPE "
|
||||
<< stype;
|
||||
if (optional) {
|
||||
os << " OPTIONAL";
|
||||
}
|
||||
@@ -133,6 +143,9 @@ void cmInstallGenerator::AddInstallRule(
|
||||
for (std::string const& f : files) {
|
||||
os << "\n" << indent << " \"" << f << "\"";
|
||||
}
|
||||
if (files_var) {
|
||||
os << " ${" << files_var << "}";
|
||||
}
|
||||
os << "\n" << indent << " ";
|
||||
if (!(literal_args && *literal_args)) {
|
||||
os << " ";
|
||||
|
@@ -50,7 +50,8 @@ public:
|
||||
std::vector<std::string> const& files, bool optional = false,
|
||||
const char* permissions_file = nullptr,
|
||||
const char* permissions_dir = nullptr, const char* rename = nullptr,
|
||||
const char* literal_args = nullptr, Indent indent = Indent());
|
||||
const char* literal_args = nullptr, Indent indent = Indent(),
|
||||
const char* files_var = nullptr);
|
||||
|
||||
/** Get the install destination as it should appear in the
|
||||
installation script. */
|
||||
|
206
Source/cmInstallGetRuntimeDependenciesGenerator.cxx
Normal file
206
Source/cmInstallGetRuntimeDependenciesGenerator.cxx
Normal file
@@ -0,0 +1,206 @@
|
||||
/* 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 "cmLocalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmOutputConverter.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
|
||||
namespace {
|
||||
template <typename T, typename F>
|
||||
void WriteMultiArgument(std::ostream& os, const cm::string_view& keyword,
|
||||
const std::vector<T>& 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, const cm::string_view& keyword,
|
||||
const std::vector<std::unique_ptr<cmInstallRuntimeDependencySet::Item>>&
|
||||
items,
|
||||
const std::string& config, cmScriptGeneratorIndent indent)
|
||||
{
|
||||
WriteMultiArgument(
|
||||
os, keyword, items, indent,
|
||||
[config](const std::unique_ptr<cmInstallRuntimeDependencySet::Item>& i)
|
||||
-> std::string { return cmStrCat('"', i->GetItemPath(config), '"'); });
|
||||
}
|
||||
|
||||
void WriteGenexEvaluatorArgument(std::ostream& os,
|
||||
const cm::string_view& keyword,
|
||||
const std::vector<std::string>& genexes,
|
||||
const std::string& config,
|
||||
cmLocalGenerator* lg,
|
||||
cmScriptGeneratorIndent indent)
|
||||
{
|
||||
WriteMultiArgument(
|
||||
os, keyword, genexes, indent,
|
||||
[config, lg](const std::string& 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, const char* depsVar,
|
||||
const char* 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, 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<std::string> postExcludeFiles;
|
||||
auto const addPostExclude =
|
||||
[config, &postExcludeFiles, this](
|
||||
const std::vector<std::unique_ptr<cmInstallRuntimeDependencySet::Item>>&
|
||||
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";
|
||||
}
|
56
Source/cmInstallGetRuntimeDependenciesGenerator.h
Normal file
56
Source/cmInstallGetRuntimeDependenciesGenerator.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#pragma once
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cmInstallGenerator.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmScriptGenerator.h"
|
||||
|
||||
class cmLocalGenerator;
|
||||
class cmInstallRuntimeDependencySet;
|
||||
|
||||
class cmInstallGetRuntimeDependenciesGenerator : public cmInstallGenerator
|
||||
{
|
||||
public:
|
||||
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, const char* depsVar,
|
||||
const char* rpathPrefix, std::vector<std::string> const& configurations,
|
||||
MessageLevel message, bool exclude_from_all,
|
||||
cmListFileBacktrace backtrace);
|
||||
|
||||
bool Compute(cmLocalGenerator* lg) override;
|
||||
|
||||
protected:
|
||||
void GenerateScript(std::ostream& os) override;
|
||||
|
||||
void GenerateScriptForConfig(std::ostream& os, const std::string& config,
|
||||
Indent indent) override;
|
||||
|
||||
private:
|
||||
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;
|
||||
const char* DepsVar;
|
||||
const char* RPathPrefix;
|
||||
cmLocalGenerator* LocalGenerator = nullptr;
|
||||
};
|
276
Source/cmInstallRuntimeDependencySetGenerator.cxx
Normal file
276
Source/cmInstallRuntimeDependencySetGenerator.cxx
Normal file
@@ -0,0 +1,276 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#include "cmInstallRuntimeDependencySetGenerator.h"
|
||||
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "cmGeneratorExpression.h"
|
||||
#include "cmInstallGenerator.h"
|
||||
#include "cmInstallType.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmLocalGenerator.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmOutputConverter.h"
|
||||
#include "cmScriptGenerator.h"
|
||||
#include "cmStringAlgorithms.h"
|
||||
#include "cmake.h"
|
||||
|
||||
cmInstallRuntimeDependencySetGenerator::cmInstallRuntimeDependencySetGenerator(
|
||||
DependencyType type, cmInstallRuntimeDependencySet* dependencySet,
|
||||
std::vector<std::string> installRPaths, bool noInstallRPath,
|
||||
std::string installNameDir, bool noInstallName, const char* depsVar,
|
||||
const char* rpathPrefix, const char* tmpVarPrefix, std::string destination,
|
||||
std::vector<std::string> const& configurations, std::string component,
|
||||
std::string permissions, MessageLevel message, bool exclude_from_all,
|
||||
cmListFileBacktrace backtrace)
|
||||
: cmInstallGenerator(std::move(destination), configurations,
|
||||
std::move(component), message, exclude_from_all, false,
|
||||
std::move(backtrace))
|
||||
, Type(type)
|
||||
, DependencySet(dependencySet)
|
||||
, InstallRPaths(std::move(installRPaths))
|
||||
, NoInstallRPath(noInstallRPath)
|
||||
, InstallNameDir(std::move(installNameDir))
|
||||
, NoInstallName(noInstallName)
|
||||
, Permissions(std::move(permissions))
|
||||
, DepsVar(depsVar)
|
||||
, RPathPrefix(rpathPrefix)
|
||||
, TmpVarPrefix(tmpVarPrefix)
|
||||
{
|
||||
this->ActionsPerConfig = true;
|
||||
}
|
||||
|
||||
bool cmInstallRuntimeDependencySetGenerator::Compute(cmLocalGenerator* lg)
|
||||
{
|
||||
this->LocalGenerator = lg;
|
||||
return true;
|
||||
}
|
||||
|
||||
void cmInstallRuntimeDependencySetGenerator::GenerateScriptForConfig(
|
||||
std::ostream& os, const std::string& config, Indent indent)
|
||||
{
|
||||
if (!this->LocalGenerator->GetMakefile()
|
||||
->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL")
|
||||
.empty() &&
|
||||
!this->NoInstallName) {
|
||||
std::string installNameDir = "@rpath/";
|
||||
if (!this->InstallNameDir.empty()) {
|
||||
installNameDir = this->InstallNameDir;
|
||||
cmGeneratorExpression::ReplaceInstallPrefix(installNameDir,
|
||||
"${CMAKE_INSTALL_PREFIX}");
|
||||
installNameDir = cmGeneratorExpression::Evaluate(
|
||||
installNameDir, this->LocalGenerator, config);
|
||||
if (installNameDir.empty()) {
|
||||
this->LocalGenerator->GetMakefile()->GetCMakeInstance()->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
"INSTALL_NAME_DIR argument must not evaluate to an "
|
||||
"empty string",
|
||||
this->Backtrace);
|
||||
return;
|
||||
}
|
||||
if (installNameDir.back() != '/') {
|
||||
installNameDir += '/';
|
||||
}
|
||||
}
|
||||
os << indent << "set(" << this->TmpVarPrefix << "_install_name_dir \""
|
||||
<< installNameDir << "\")\n";
|
||||
}
|
||||
|
||||
os << indent << "foreach(" << this->TmpVarPrefix << "_dep IN LISTS "
|
||||
<< this->DepsVar << ")\n";
|
||||
|
||||
if (!this->LocalGenerator->GetMakefile()
|
||||
->GetSafeDefinition("CMAKE_INSTALL_NAME_TOOL")
|
||||
.empty()) {
|
||||
std::vector<std::string> evaluatedRPaths;
|
||||
for (auto const& rpath : this->InstallRPaths) {
|
||||
std::string result =
|
||||
cmGeneratorExpression::Evaluate(rpath, this->LocalGenerator, config);
|
||||
if (!result.empty()) {
|
||||
evaluatedRPaths.push_back(std::move(result));
|
||||
}
|
||||
}
|
||||
|
||||
switch (this->Type) {
|
||||
case DependencyType::Library:
|
||||
this->GenerateAppleLibraryScript(os, config, evaluatedRPaths,
|
||||
indent.Next());
|
||||
break;
|
||||
case DependencyType::Framework:
|
||||
this->GenerateAppleFrameworkScript(os, config, evaluatedRPaths,
|
||||
indent.Next());
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
std::string depVar = cmStrCat(this->TmpVarPrefix, "_dep");
|
||||
|
||||
this->AddInstallRule(
|
||||
os, this->GetDestination(config), cmInstallType_SHARED_LIBRARY, {},
|
||||
false, this->Permissions.c_str(), nullptr, nullptr,
|
||||
" FOLLOW_SYMLINK_CHAIN", indent.Next(), depVar.c_str());
|
||||
|
||||
if (this->LocalGenerator->GetMakefile()->GetSafeDefinition(
|
||||
"CMAKE_SYSTEM_NAME") == "Linux" &&
|
||||
!this->NoInstallRPath) {
|
||||
std::string evaluatedRPath;
|
||||
for (auto const& rpath : this->InstallRPaths) {
|
||||
std::string result =
|
||||
cmGeneratorExpression::Evaluate(rpath, this->LocalGenerator, config);
|
||||
if (!result.empty()) {
|
||||
if (evaluatedRPath.empty()) {
|
||||
evaluatedRPath = std::move(result);
|
||||
} else {
|
||||
evaluatedRPath += ':';
|
||||
evaluatedRPath += result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
os << indent.Next() << "get_filename_component(" << this->TmpVarPrefix
|
||||
<< "_dep_name \"${" << this->TmpVarPrefix << "_dep}\" NAME)\n";
|
||||
if (evaluatedRPath.empty()) {
|
||||
os << indent.Next() << "file(RPATH_REMOVE FILE \""
|
||||
<< GetDestDirPath(
|
||||
ConvertToAbsoluteDestination(this->GetDestination(config)))
|
||||
<< "/${" << this->TmpVarPrefix << "_dep_name}\")\n";
|
||||
} else {
|
||||
os << indent.Next() << "file(RPATH_SET FILE \""
|
||||
<< GetDestDirPath(
|
||||
ConvertToAbsoluteDestination(this->GetDestination(config)))
|
||||
<< "/${" << this->TmpVarPrefix << "_dep_name}\" NEW_RPATH "
|
||||
<< cmOutputConverter::EscapeForCMake(evaluatedRPath) << ")\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
os << indent << "endforeach()\n";
|
||||
}
|
||||
|
||||
void cmInstallRuntimeDependencySetGenerator::GenerateAppleLibraryScript(
|
||||
std::ostream& os, const std::string& config,
|
||||
const std::vector<std::string>& evaluatedRPaths, Indent indent)
|
||||
{
|
||||
os << indent << "if(NOT " << this->TmpVarPrefix
|
||||
<< "_dep MATCHES \"\\\\.framework/\")\n";
|
||||
|
||||
auto depName = cmStrCat(this->TmpVarPrefix, "_dep");
|
||||
this->AddInstallRule(
|
||||
os, this->GetDestination(config), cmInstallType_SHARED_LIBRARY, {}, false,
|
||||
this->Permissions.c_str(), nullptr, nullptr, " FOLLOW_SYMLINK_CHAIN",
|
||||
indent.Next(), depName.c_str());
|
||||
|
||||
os << indent.Next() << "get_filename_component(" << this->TmpVarPrefix
|
||||
<< "_dep_name \"${" << this->TmpVarPrefix << "_dep}\" NAME)\n";
|
||||
auto depNameVar = cmStrCat("${", this->TmpVarPrefix, "_dep_name}");
|
||||
this->GenerateInstallNameFixup(os, config, evaluatedRPaths,
|
||||
cmStrCat("${", this->TmpVarPrefix, "_dep}"),
|
||||
depNameVar, indent.Next());
|
||||
|
||||
os << indent << "endif()\n";
|
||||
}
|
||||
|
||||
void cmInstallRuntimeDependencySetGenerator::GenerateAppleFrameworkScript(
|
||||
std::ostream& os, const std::string& config,
|
||||
const std::vector<std::string>& evaluatedRPaths, Indent indent)
|
||||
{
|
||||
os << indent << "if(" << this->TmpVarPrefix
|
||||
<< "_dep MATCHES \"^(.*/)?([^/]*\\\\.framework)/(.*)$\")\n"
|
||||
<< indent.Next() << "set(" << this->TmpVarPrefix
|
||||
<< "_dir \"${CMAKE_MATCH_1}\")\n"
|
||||
<< indent.Next() << "set(" << this->TmpVarPrefix
|
||||
<< "_name \"${CMAKE_MATCH_2}\")\n"
|
||||
<< indent.Next() << "set(" << this->TmpVarPrefix
|
||||
<< "_file \"${CMAKE_MATCH_3}\")\n"
|
||||
<< indent.Next() << "set(" << this->TmpVarPrefix << "_path \"${"
|
||||
<< this->TmpVarPrefix << "_dir}${" << this->TmpVarPrefix << "_name}\")\n";
|
||||
|
||||
auto depName = cmStrCat(this->TmpVarPrefix, "_path");
|
||||
this->AddInstallRule(
|
||||
os, this->GetDestination(config), cmInstallType_DIRECTORY, {}, false,
|
||||
this->Permissions.c_str(), nullptr, nullptr, " USE_SOURCE_PERMISSIONS",
|
||||
indent.Next(), depName.c_str());
|
||||
|
||||
auto depNameVar = cmStrCat("${", this->TmpVarPrefix, "_name}/${",
|
||||
this->TmpVarPrefix, "_file}");
|
||||
this->GenerateInstallNameFixup(os, config, evaluatedRPaths,
|
||||
cmStrCat("${", this->TmpVarPrefix, "_dep}"),
|
||||
depNameVar, indent.Next());
|
||||
|
||||
os << indent << "endif()\n";
|
||||
}
|
||||
|
||||
void cmInstallRuntimeDependencySetGenerator::GenerateInstallNameFixup(
|
||||
std::ostream& os, const std::string& config,
|
||||
const std::vector<std::string>& evaluatedRPaths, const std::string& filename,
|
||||
const std::string& depName, Indent indent)
|
||||
{
|
||||
if (!(this->NoInstallRPath && this->NoInstallName)) {
|
||||
auto indent2 = indent;
|
||||
if (evaluatedRPaths.empty() && this->NoInstallName) {
|
||||
indent2 = indent2.Next();
|
||||
os << indent << "if(" << this->RPathPrefix << "_" << filename << ")\n";
|
||||
}
|
||||
os << indent2 << "set(" << this->TmpVarPrefix << "_rpath_args)\n";
|
||||
if (!this->NoInstallRPath) {
|
||||
os << indent2 << "foreach(" << this->TmpVarPrefix << "_rpath IN LISTS "
|
||||
<< this->RPathPrefix << '_' << filename << ")\n"
|
||||
<< indent2.Next() << "list(APPEND " << this->TmpVarPrefix
|
||||
<< "_rpath_args -delete_rpath \"${" << this->TmpVarPrefix
|
||||
<< "_rpath}\")\n"
|
||||
<< indent2 << "endforeach()\n";
|
||||
}
|
||||
os << indent2 << "execute_process(COMMAND \""
|
||||
<< this->LocalGenerator->GetMakefile()->GetSafeDefinition(
|
||||
"CMAKE_INSTALL_NAME_TOOL")
|
||||
<< "\" ${" << this->TmpVarPrefix << "_rpath_args}\n";
|
||||
if (!this->NoInstallRPath) {
|
||||
for (auto const& rpath : evaluatedRPaths) {
|
||||
os << indent2 << " -add_rpath "
|
||||
<< cmOutputConverter::EscapeForCMake(rpath) << "\n";
|
||||
}
|
||||
}
|
||||
if (!this->NoInstallName) {
|
||||
os << indent2 << " -id \"${" << this->TmpVarPrefix
|
||||
<< "_install_name_dir}" << depName << "\"\n";
|
||||
}
|
||||
os << indent2 << " \""
|
||||
<< GetDestDirPath(
|
||||
ConvertToAbsoluteDestination(this->GetDestination(config)))
|
||||
<< "/" << depName << "\")\n";
|
||||
if (evaluatedRPaths.empty() && this->NoInstallName) {
|
||||
os << indent << "endif()\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmInstallRuntimeDependencySetGenerator::GenerateStripFixup(
|
||||
std::ostream& os, const std::string& config, const std::string& depName,
|
||||
Indent indent)
|
||||
{
|
||||
std::string strip =
|
||||
this->LocalGenerator->GetMakefile()->GetSafeDefinition("CMAKE_STRIP");
|
||||
if (!strip.empty()) {
|
||||
os << indent << "if(CMAKE_INSTALL_DO_STRIP)\n"
|
||||
<< indent.Next() << "execute_process(COMMAND \"" << strip << "\" ";
|
||||
if (this->LocalGenerator->GetMakefile()->GetSafeDefinition(
|
||||
"CMAKE_HOST_SYSTEM_NAME") == "Darwin") {
|
||||
os << "-x ";
|
||||
}
|
||||
os << "\""
|
||||
<< GetDestDirPath(
|
||||
ConvertToAbsoluteDestination(this->GetDestination(config)))
|
||||
<< "/" << depName << "\")\n"
|
||||
<< indent << "endif()\n";
|
||||
}
|
||||
}
|
||||
|
||||
std::string cmInstallRuntimeDependencySetGenerator::GetDestination(
|
||||
std::string const& config) const
|
||||
{
|
||||
return cmGeneratorExpression::Evaluate(this->Destination,
|
||||
this->LocalGenerator, config);
|
||||
}
|
74
Source/cmInstallRuntimeDependencySetGenerator.h
Normal file
74
Source/cmInstallRuntimeDependencySetGenerator.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
||||
file Copyright.txt or https://cmake.org/licensing for details. */
|
||||
#pragma once
|
||||
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "cmInstallGenerator.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmScriptGenerator.h"
|
||||
|
||||
class cmInstallRuntimeDependencySet;
|
||||
class cmLocalGenerator;
|
||||
|
||||
class cmInstallRuntimeDependencySetGenerator : public cmInstallGenerator
|
||||
{
|
||||
public:
|
||||
enum class DependencyType
|
||||
{
|
||||
Library,
|
||||
Framework,
|
||||
};
|
||||
|
||||
cmInstallRuntimeDependencySetGenerator(
|
||||
DependencyType type, cmInstallRuntimeDependencySet* dependencySet,
|
||||
std::vector<std::string> installRPaths, bool noInstallRPath,
|
||||
std::string installNameDir, bool noInstallName, const char* depsVar,
|
||||
const char* rpathPrefix, const char* tmpVarPrefix, std::string destination,
|
||||
std::vector<std::string> const& configurations, std::string component,
|
||||
std::string permissions, MessageLevel message, bool exclude_from_all,
|
||||
cmListFileBacktrace backtrace);
|
||||
|
||||
bool Compute(cmLocalGenerator* lg) override;
|
||||
|
||||
DependencyType GetDependencyType() const { return this->Type; }
|
||||
|
||||
cmInstallRuntimeDependencySet* GetRuntimeDependencySet() const
|
||||
{
|
||||
return this->DependencySet;
|
||||
}
|
||||
|
||||
std::string GetDestination(std::string const& config) const;
|
||||
|
||||
protected:
|
||||
void GenerateScriptForConfig(std::ostream& os, const std::string& config,
|
||||
Indent indent) override;
|
||||
|
||||
private:
|
||||
DependencyType Type;
|
||||
cmInstallRuntimeDependencySet* DependencySet;
|
||||
std::vector<std::string> InstallRPaths;
|
||||
bool NoInstallRPath;
|
||||
std::string InstallNameDir;
|
||||
bool NoInstallName;
|
||||
std::string Permissions;
|
||||
const char* DepsVar;
|
||||
const char* RPathPrefix;
|
||||
const char* TmpVarPrefix;
|
||||
cmLocalGenerator* LocalGenerator = nullptr;
|
||||
|
||||
void GenerateAppleLibraryScript(
|
||||
std::ostream& os, const std::string& config,
|
||||
const std::vector<std::string>& evaluatedRPaths, Indent indent);
|
||||
void GenerateAppleFrameworkScript(
|
||||
std::ostream& os, const std::string& config,
|
||||
const std::vector<std::string>& evaluatedRPaths, Indent indent);
|
||||
void GenerateInstallNameFixup(
|
||||
std::ostream& os, const std::string& config,
|
||||
const std::vector<std::string>& evaluatedRPaths,
|
||||
const std::string& filename, const std::string& depName, Indent indent);
|
||||
void GenerateStripFixup(std::ostream& os, const std::string& config,
|
||||
const std::string& depName, Indent indent);
|
||||
};
|
@@ -397,3 +397,11 @@ cmRuntimeDependencyArchive::GetRPaths() const
|
||||
{
|
||||
return this->RPaths;
|
||||
}
|
||||
|
||||
bool cmRuntimeDependencyArchive::PlatformSupportsRuntimeDependencies(
|
||||
const std::string& platform)
|
||||
{
|
||||
static const std::set<std::string> supportedPlatforms = { "Windows", "Linux",
|
||||
"Darwin" };
|
||||
return supportedPlatforms.count(platform);
|
||||
}
|
||||
|
@@ -53,6 +53,8 @@ public:
|
||||
const std::set<std::string>& GetUnresolvedPaths() const;
|
||||
const std::map<std::string, std::vector<std::string>>& GetRPaths() const;
|
||||
|
||||
static bool PlatformSupportsRuntimeDependencies(const std::string& platform);
|
||||
|
||||
private:
|
||||
cmExecutionStatus& Status;
|
||||
std::unique_ptr<cmBinUtilsLinker> Linker;
|
||||
|
@@ -44,7 +44,7 @@ function(check_installed expect)
|
||||
do not match what we expected:
|
||||
${expect}
|
||||
in directory:
|
||||
${CMAKE_INSTALL_PREFIX}" PARENT_SCOPE)
|
||||
${CMAKE_INSTALL_PREFIX}\n" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
@@ -174,6 +174,21 @@ run_install_test(FILES-PERMISSIONS)
|
||||
run_install_test(TARGETS-RPATH)
|
||||
run_install_test(InstallRequiredSystemLibraries)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
run_cmake(TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle)
|
||||
run_cmake(TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin|Windows)$")
|
||||
run_install_test(TARGETS-RUNTIME_DEPENDENCIES-nodep)
|
||||
run_install_test(TARGETS-RUNTIME_DEPENDENCIES-empty)
|
||||
set(RunCMake_TEST_OPTIONS "-DCMAKE_SYSTEM_NAME:STRING=${CMAKE_SYSTEM_NAME}")
|
||||
run_cmake(TARGETS-RUNTIME_DEPENDENCIES-cross)
|
||||
unset(RunCMake_TEST_OPTIONS)
|
||||
else()
|
||||
run_cmake(TARGETS-RUNTIME_DEPENDENCIES-unsupported)
|
||||
endif()
|
||||
|
||||
set(run_install_test_components 1)
|
||||
run_install_test(FILES-EXCLUDE_FROM_ALL)
|
||||
run_install_test(TARGETS-EXCLUDE_FROM_ALL)
|
||||
|
@@ -0,0 +1 @@
|
||||
1
|
@@ -0,0 +1,4 @@
|
||||
^CMake Error at TARGETS-RUNTIME_DEPENDENCIES-cross\.cmake:[0-9]+ \(install\):
|
||||
install TARGETS RUNTIME_DEPENDENCIES is not supported when cross-compiling\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:[0-9]+ \(include\)$
|
@@ -0,0 +1,4 @@
|
||||
enable_language(C)
|
||||
|
||||
add_executable(exe main.c)
|
||||
install(TARGETS exe RUNTIME_DEPENDENCIES)
|
@@ -0,0 +1 @@
|
||||
check_installed([[^static;static/(liblib\.a|lib\.lib)$]])
|
@@ -0,0 +1,9 @@
|
||||
enable_language(C)
|
||||
|
||||
add_library(lib STATIC obj1.c)
|
||||
|
||||
install(TARGETS lib RUNTIME_DEPENDENCIES
|
||||
LIBRARY DESTINATION lib
|
||||
ARCHIVE DESTINATION static
|
||||
FRAMEWORK DESTINATION fw
|
||||
)
|
@@ -0,0 +1 @@
|
||||
1
|
@@ -0,0 +1,4 @@
|
||||
^CMake Error at TARGETS-RUNTIME_DEPENDENCIES-macos-no-framework\.cmake:[0-9]+ \(install\):
|
||||
install TARGETS RUNTIME_DEPENDENCIES given no FRAMEWORK DESTINATION
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
@@ -0,0 +1,4 @@
|
||||
enable_language(C)
|
||||
|
||||
add_executable(exe main.c)
|
||||
install(TARGETS exe RUNTIME_DEPENDENCIES)
|
@@ -0,0 +1 @@
|
||||
1
|
@@ -0,0 +1,4 @@
|
||||
^CMake Error at TARGETS-RUNTIME_DEPENDENCIES-macos-two-bundle\.cmake:[0-9]+ \(install\):
|
||||
install A runtime dependency set may only have one bundle executable\.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:[0-9]+ \(include\)$
|
@@ -0,0 +1,10 @@
|
||||
enable_language(C)
|
||||
|
||||
add_executable(exe1 MACOSX_BUNDLE main.c)
|
||||
add_executable(exe2 MACOSX_BUNDLE main.c)
|
||||
|
||||
install(TARGETS exe1 exe2
|
||||
RUNTIME_DEPENDENCIES
|
||||
BUNDLE DESTINATION bundles
|
||||
FRAMEWORK DESTINATION fw
|
||||
)
|
@@ -0,0 +1 @@
|
||||
check_installed([[^bin;bin/exe(\.exe)?$]])
|
@@ -0,0 +1,9 @@
|
||||
enable_language(C)
|
||||
|
||||
add_executable(exe main.c)
|
||||
|
||||
install(TARGETS exe
|
||||
RUNTIME_DEPENDENCIES
|
||||
PRE_EXCLUDE_REGEXES ".*"
|
||||
FRAMEWORK DESTINATION fw
|
||||
)
|
@@ -0,0 +1 @@
|
||||
1
|
@@ -0,0 +1,5 @@
|
||||
^CMake Error at TARGETS-RUNTIME_DEPENDENCIES-unsupported\.cmake:[0-9]+ \(install\):
|
||||
install TARGETS RUNTIME_DEPENDENCIES is not supported on system "[^
|
||||
]*"
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:[0-9]+ \(include\)$
|
@@ -0,0 +1,4 @@
|
||||
enable_language(C)
|
||||
|
||||
add_executable(exe main.c)
|
||||
install(TARGETS exe RUNTIME_DEPENDENCIES)
|
@@ -387,8 +387,10 @@ CMAKE_CXX_SOURCES="\
|
||||
cmInstallFilesCommand \
|
||||
cmInstallFilesGenerator \
|
||||
cmInstallGenerator \
|
||||
cmInstallGetRuntimeDependenciesGenerator \
|
||||
cmInstallImportedRuntimeArtifactsGenerator \
|
||||
cmInstallRuntimeDependencySet \
|
||||
cmInstallRuntimeDependencySetGenerator \
|
||||
cmInstallScriptGenerator \
|
||||
cmInstallSubdirectoryGenerator \
|
||||
cmInstallTargetGenerator \
|
||||
|
Reference in New Issue
Block a user