You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
276 lines
10 KiB
276 lines
10 KiB
/* 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()->IsOn("APPLE")) {
|
|
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);
|
|
}
|