ENH: Created target property INSTALL_NAME_DIR initalized by CMAKE_INSTALL_NAME_DIR specifying the directory portion of the OSX install_name field in shared libraries. This is the OSX equivalent of RPATH.
This commit is contained in:
parent
7db7b981af
commit
586a9427d3
|
@ -4,8 +4,11 @@ SET(CMAKE_SHARED_MODULE_PREFIX "lib")
|
|||
SET(CMAKE_SHARED_MODULE_SUFFIX ".so")
|
||||
SET(CMAKE_MODULE_EXISTS 1)
|
||||
SET(CMAKE_DL_LIBS "")
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib")
|
||||
SET(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle")
|
||||
SET(CMAKE_C_LINK_FLAGS "-headerpad_max_install_names")
|
||||
SET(CMAKE_CXX_LINK_FLAGS "-headerpad_max_install_names")
|
||||
SET(CMAKE_PLATFORM_HAS_INSTALLNAME 1)
|
||||
SET(CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS "-dynamiclib -headerpad_max_install_names")
|
||||
SET(CMAKE_SHARED_MODULE_CREATE_C_FLAGS "-bundle -headerpad_max_install_names")
|
||||
SET(CMAKE_FIND_LIBRARY_SUFFIXES ".dylib" ".so" ".a")
|
||||
|
||||
IF("${CMAKE_BACKWARDS_COMPATIBILITY}" MATCHES "^1\\.[0-6]$")
|
||||
|
@ -14,32 +17,17 @@ IF("${CMAKE_BACKWARDS_COMPATIBILITY}" MATCHES "^1\\.[0-6]$")
|
|||
ENDIF("${CMAKE_BACKWARDS_COMPATIBILITY}" MATCHES "^1\\.[0-6]$")
|
||||
|
||||
IF(NOT XCODE)
|
||||
# Enable shared library versioning.
|
||||
# Enable shared library versioning. This flag is not actually referenced
|
||||
# but the fact that the setting exists will cause the generators to support
|
||||
# soname computation.
|
||||
SET(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-install_name")
|
||||
SET(CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG "-install_name")
|
||||
ENDIF(NOT XCODE)
|
||||
|
||||
# OSX does not really implement an rpath, but it does allow a path to
|
||||
# be specified in the soname field of a dylib.
|
||||
IF(CMAKE_SKIP_RPATH)
|
||||
# No rpath requested. Just use the soname directly.
|
||||
SET(CMAKE_C_CREATE_SHARED_LIBRARY
|
||||
"<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <LINK_FLAGS> -o <TARGET> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG> <TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
|
||||
SET(CMAKE_CXX_CREATE_SHARED_LIBRARY
|
||||
"<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <LINK_FLAGS> -o <TARGET> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG> <TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
|
||||
ELSE(CMAKE_SKIP_RPATH)
|
||||
# Support for rpath is requested. Approximate it by putting the
|
||||
# full path to the library in the soname field. Then when executables
|
||||
# link the library they will copy this full path as the name to use
|
||||
# to find the library. We can get the directory containing the library
|
||||
# by using the dirname of the <TARGET>. It may be a relative path
|
||||
# so we use a "cd ...;pwd" trick to convert it to a full path at
|
||||
# build time.
|
||||
SET(CMAKE_C_CREATE_SHARED_LIBRARY
|
||||
"<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <LINK_FLAGS> -o <TARGET> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG> \"`cd \\`dirname <TARGET>\\`\;pwd`/<TARGET_SONAME>\" <OBJECTS> <LINK_LIBRARIES>")
|
||||
SET(CMAKE_CXX_CREATE_SHARED_LIBRARY
|
||||
"<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <LINK_FLAGS> -o <TARGET> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG> \"`cd \\`dirname <TARGET>\\`\;pwd`/<TARGET_SONAME>\" <OBJECTS> <LINK_LIBRARIES>")
|
||||
ENDIF(CMAKE_SKIP_RPATH)
|
||||
SET(CMAKE_C_CREATE_SHARED_LIBRARY
|
||||
"<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <LINK_FLAGS> -o <TARGET> -install_name <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
|
||||
SET(CMAKE_CXX_CREATE_SHARED_LIBRARY
|
||||
"<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <LINK_FLAGS> -o <TARGET> -install_name <TARGET_INSTALLNAME_DIR><TARGET_SONAME> <OBJECTS> <LINK_LIBRARIES>")
|
||||
|
||||
SET(CMAKE_CXX_CREATE_SHARED_MODULE
|
||||
"<CMAKE_CXX_COMPILER> <CMAKE_SHARED_MODULE_CREATE_CXX_FLAGS> <LINK_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
|
||||
|
|
|
@ -1145,13 +1145,30 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
|
|||
outflag += "\\\"";
|
||||
extraLinkOptions += " ";
|
||||
extraLinkOptions += outflag;
|
||||
|
||||
// Add the flags to create an executable.
|
||||
std::string createFlags =
|
||||
this->LookupFlags("CMAKE_", lang, "_LINK_FLAGS", "");
|
||||
if(!createFlags.empty())
|
||||
{
|
||||
extraLinkOptions += " ";
|
||||
extraLinkOptions += createFlags;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fileType = "compiled.mach-o.dylib";
|
||||
productType = "com.apple.product-type.library.dynamic";
|
||||
|
||||
extraLinkOptions += " -bundle";
|
||||
// Add the flags to create a module.
|
||||
std::string createFlags =
|
||||
this->LookupFlags("CMAKE_SHARED_MODULE_CREATE_", lang, "_FLAGS",
|
||||
"-bundle");
|
||||
if(!createFlags.empty())
|
||||
{
|
||||
extraLinkOptions += " ";
|
||||
extraLinkOptions += createFlags;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1166,13 +1183,31 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
|
|||
this->CreateString("1"));
|
||||
buildSettings->AddAttribute("DYLIB_CURRENT_VERSION",
|
||||
this->CreateString("1"));
|
||||
extraLinkOptions += " -dynamiclib";
|
||||
|
||||
// Add the flags to create a shared library.
|
||||
std::string createFlags =
|
||||
this->LookupFlags("CMAKE_SHARED_LIBRARY_CREATE_", lang, "_FLAGS",
|
||||
"-dynamiclib");
|
||||
if(!createFlags.empty())
|
||||
{
|
||||
extraLinkOptions += " ";
|
||||
extraLinkOptions += createFlags;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case cmTarget::EXECUTABLE:
|
||||
{
|
||||
fileType = "compiled.mach-o.executable";
|
||||
|
||||
// Add the flags to create an executable.
|
||||
std::string createFlags =
|
||||
this->LookupFlags("CMAKE_", lang, "_LINK_FLAGS", "");
|
||||
if(!createFlags.empty())
|
||||
{
|
||||
extraLinkOptions += " ";
|
||||
extraLinkOptions += createFlags;
|
||||
}
|
||||
|
||||
// Handle bundles and normal executables separately.
|
||||
if(target.GetPropertyAsBool("MACOSX_BUNDLE"))
|
||||
{
|
||||
|
@ -1284,8 +1319,6 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
|
|||
this->CreateString(debugStr));
|
||||
buildSettings->AddAttribute("GCC_OPTIMIZATION_LEVEL",
|
||||
this->CreateString(optLevel));
|
||||
buildSettings->AddAttribute("INSTALL_PATH",
|
||||
this->CreateString(""));
|
||||
buildSettings->AddAttribute("OPTIMIZATION_CFLAGS",
|
||||
this->CreateString(oflagc.c_str()));
|
||||
if(lang && strcmp(lang, "CXX") == 0)
|
||||
|
@ -1307,9 +1340,45 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
|
|||
buildSettings->AddAttribute("OTHER_CFLAGS",
|
||||
this->CreateString(flags.c_str()));
|
||||
}
|
||||
|
||||
// Create the INSTALL_PATH attribute.
|
||||
std::string install_name_dir;
|
||||
if(target.GetType() == cmTarget::SHARED_LIBRARY)
|
||||
{
|
||||
// Select whether to generate an install_name directory for the
|
||||
// install tree or the build tree.
|
||||
if(target.GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"))
|
||||
{
|
||||
install_name_dir =
|
||||
target.GetInstallNameDirForInstallTree(configName);
|
||||
}
|
||||
else
|
||||
{
|
||||
install_name_dir =
|
||||
target.GetInstallNameDirForBuildTree(configName);
|
||||
}
|
||||
|
||||
if(install_name_dir.empty())
|
||||
{
|
||||
// Xcode will not pass the -install_name option at all if INSTALL_PATH
|
||||
// is not given or is empty. We must explicitly put the flag in the
|
||||
// link flags to create an install_name with just the library soname.
|
||||
extraLinkOptions += " -install_name ";
|
||||
extraLinkOptions += productName;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert to a path for the native build tool.
|
||||
cmSystemTools::ConvertToUnixSlashes(install_name_dir);
|
||||
install_name_dir =
|
||||
this->XCodeEscapePath(install_name_dir.c_str());
|
||||
}
|
||||
}
|
||||
buildSettings->AddAttribute("INSTALL_PATH",
|
||||
this->CreateString(install_name_dir.c_str()));
|
||||
|
||||
buildSettings->AddAttribute("OTHER_LDFLAGS",
|
||||
this->CreateString(extraLinkOptions.c_str()));
|
||||
|
||||
buildSettings->AddAttribute("OTHER_REZFLAGS",
|
||||
this->CreateString(""));
|
||||
buildSettings->AddAttribute("SECTORDER_FLAGS",
|
||||
|
@ -2317,3 +2386,26 @@ cmGlobalXCodeGenerator
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmGlobalXCodeGenerator::LookupFlags(const char* varNamePrefix,
|
||||
const char* varNameLang,
|
||||
const char* varNameSuffix,
|
||||
const char* default_flags)
|
||||
{
|
||||
if(varNameLang)
|
||||
{
|
||||
std::string varName = varNamePrefix;
|
||||
varName += varNameLang;
|
||||
varName += varNameSuffix;
|
||||
if(const char* varValue =
|
||||
m_CurrentMakefile->GetDefinition(varName.c_str()))
|
||||
{
|
||||
if(*varValue)
|
||||
{
|
||||
return varValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
return default_flags;
|
||||
}
|
||||
|
|
|
@ -142,6 +142,11 @@ private:
|
|||
cmTarget& cmtarget,
|
||||
const std::vector<cmCustomCommand>&);
|
||||
void CreateReRunCMakeFile(cmLocalGenerator* root);
|
||||
|
||||
std::string LookupFlags(const char* varNamePrefix,
|
||||
const char* varNameLang,
|
||||
const char* varNameSuffix,
|
||||
const char* default_flags);
|
||||
protected:
|
||||
|
||||
int m_XcodeVersion;
|
||||
|
|
|
@ -52,10 +52,11 @@ void cmInstallTargetGenerator::GenerateScript(std::ostream& os)
|
|||
}
|
||||
|
||||
// Write variable settings to do per-configuration references.
|
||||
this->PrepareInstallReference(os);
|
||||
this->PrepareScriptReference(os, this->Target, "BUILD", true, false);
|
||||
|
||||
// Create the per-configuration reference.
|
||||
std::string fromName = this->GetInstallReference();
|
||||
std::string fromName = this->GetScriptReference(this->Target, "BUILD",
|
||||
false);
|
||||
std::string fromFile = fromDir;
|
||||
fromFile += fromName;
|
||||
|
||||
|
@ -150,12 +151,22 @@ void cmInstallTargetGenerator::GenerateScript(std::ostream& os)
|
|||
// Write code to install the target file.
|
||||
this->AddInstallRule(os, this->Destination.c_str(), type, fromFile.c_str(),
|
||||
this->ImportLibrary, properties);
|
||||
|
||||
// Fix the install_name settings in installed binaries.
|
||||
if(type == cmTarget::SHARED_LIBRARY ||
|
||||
type == cmTarget::MODULE_LIBRARY ||
|
||||
type == cmTarget::EXECUTABLE)
|
||||
{
|
||||
this->AddInstallNamePatchRule(os);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmInstallTargetGenerator
|
||||
::PrepareInstallReference(std::ostream& os)
|
||||
::PrepareScriptReference(std::ostream& os, cmTarget* target,
|
||||
const char* place, bool useConfigDir,
|
||||
bool useSOName)
|
||||
{
|
||||
// If the target name may vary with the configuration type then
|
||||
// store all possible names ahead of time in variables.
|
||||
|
@ -164,42 +175,180 @@ cmInstallTargetGenerator
|
|||
this->ConfigurationTypes->begin();
|
||||
i != this->ConfigurationTypes->end(); ++i)
|
||||
{
|
||||
// Start with the configuration's subdirectory.
|
||||
// Initialize the name.
|
||||
fname = "";
|
||||
this->Target->GetMakefile()->GetLocalGenerator()->GetGlobalGenerator()->
|
||||
AppendDirectoryForConfig(i->c_str(), fname);
|
||||
|
||||
if(useConfigDir)
|
||||
{
|
||||
// Start with the configuration's subdirectory.
|
||||
target->GetMakefile()->GetLocalGenerator()->GetGlobalGenerator()->
|
||||
AppendDirectoryForConfig(i->c_str(), fname);
|
||||
}
|
||||
|
||||
// Compute the name of the library.
|
||||
std::string targetName;
|
||||
std::string targetNameSO;
|
||||
std::string targetNameReal;
|
||||
std::string targetNameImport;
|
||||
target->GetLibraryNames(targetName, targetNameSO, targetNameReal,
|
||||
targetNameImport, i->c_str());
|
||||
if(this->ImportLibrary)
|
||||
{
|
||||
// Use the import library name.
|
||||
fname += targetNameImport;
|
||||
}
|
||||
else if(useSOName)
|
||||
{
|
||||
// Use the soname.
|
||||
fname += targetNameSO;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the canonical name.
|
||||
fname += targetName;
|
||||
}
|
||||
|
||||
// Set a variable with the target name for this configuration.
|
||||
fname += this->Target->GetFullName(i->c_str(), this->ImportLibrary);
|
||||
os << "SET(" << this->Target->GetName()
|
||||
os << "SET(" << target->GetName() << "_" << place
|
||||
<< (this->ImportLibrary? "_IMPNAME_" : "_NAME_") << *i
|
||||
<< " \"" << fname << "\")\n";
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmInstallTargetGenerator::GetInstallReference()
|
||||
std::string cmInstallTargetGenerator::GetScriptReference(cmTarget* target,
|
||||
const char* place,
|
||||
bool useSOName)
|
||||
{
|
||||
if(this->ConfigurationTypes->empty())
|
||||
{
|
||||
// Reference the target by its one configuration name.
|
||||
return this->Target->GetFullName(this->ConfigurationName,
|
||||
this->ImportLibrary);
|
||||
std::string targetName;
|
||||
std::string targetNameSO;
|
||||
std::string targetNameReal;
|
||||
std::string targetNameImport;
|
||||
target->GetLibraryNames(targetName, targetNameSO, targetNameReal,
|
||||
targetNameImport, this->ConfigurationName);
|
||||
if(this->ImportLibrary)
|
||||
{
|
||||
// Use the import library name.
|
||||
return targetNameImport;
|
||||
}
|
||||
else if(useSOName)
|
||||
{
|
||||
// Use the soname.
|
||||
return targetNameSO;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the canonical name.
|
||||
return targetName;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reference the target using the per-configuration variable.
|
||||
std::string ref = "${";
|
||||
ref += this->Target->GetName();
|
||||
ref += target->GetName();
|
||||
if(this->ImportLibrary)
|
||||
{
|
||||
ref += "_";
|
||||
ref += place;
|
||||
ref += "_IMPNAME_";
|
||||
}
|
||||
else
|
||||
{
|
||||
ref += "_";
|
||||
ref += place;
|
||||
ref += "_NAME_";
|
||||
}
|
||||
ref += "${CMAKE_INSTALL_CONFIG_NAME}}";
|
||||
return ref;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmInstallTargetGenerator::AddInstallNamePatchRule(std::ostream& os)
|
||||
{
|
||||
// Build a map of build-tree install_name to install-tree install_name for
|
||||
// shared libraries linked to this target.
|
||||
std::map<cmStdString, cmStdString> install_name_remap;
|
||||
cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED;
|
||||
const char* config = this->ConfigurationName;
|
||||
if(config && cmSystemTools::UpperCase(config) == "DEBUG")
|
||||
{
|
||||
linkType = cmTarget::DEBUG;
|
||||
}
|
||||
// TODO: Merge with ComputeLinkInformation.
|
||||
const cmTarget::LinkLibraries& inLibs = this->Target->GetLinkLibraries();
|
||||
for(cmTarget::LinkLibraries::const_iterator j = inLibs.begin();
|
||||
j != inLibs.end(); ++j)
|
||||
{
|
||||
std::string lib = j->first;
|
||||
if((this->Target->GetType() == cmTarget::EXECUTABLE ||
|
||||
lib != this->Target->GetName()) &&
|
||||
(j->second == cmTarget::GENERAL || j->second == linkType))
|
||||
{
|
||||
if(cmTarget* tgt = this->Target->GetMakefile()->GetLocalGenerator()->GetGlobalGenerator()->FindTarget(0, lib.c_str()))
|
||||
{
|
||||
if(tgt->GetType() == cmTarget::SHARED_LIBRARY)
|
||||
{
|
||||
// If the build tree and install tree use different path components
|
||||
// of the install_name field then we need to create a mapping to be
|
||||
// applied after installation.
|
||||
std::string for_build = tgt->GetInstallNameDirForBuildTree(config);
|
||||
std::string for_install = tgt->GetInstallNameDirForInstallTree(config);
|
||||
if(for_build != for_install)
|
||||
{
|
||||
// Map from the build-tree install_name.
|
||||
this->PrepareScriptReference(os, tgt, "REMAP_FROM",
|
||||
!for_build.empty(), true);
|
||||
for_build += this->GetScriptReference(tgt, "REMAP_FROM", true);
|
||||
|
||||
// Map to the install-tree install_name.
|
||||
this->PrepareScriptReference(os, tgt, "REMAP_TO",
|
||||
false, true);
|
||||
for_install += this->GetScriptReference(tgt, "REMAP_TO", true);
|
||||
|
||||
// Store the mapping entry.
|
||||
install_name_remap[for_build] = for_install;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Edit the install_name of the target itself if necessary.
|
||||
this->PrepareScriptReference(os, this->Target, "REMAPPED", false, true);
|
||||
std::string new_id;
|
||||
if(this->Target->GetType() == cmTarget::SHARED_LIBRARY)
|
||||
{
|
||||
std::string for_build = this->Target->GetInstallNameDirForBuildTree(config);
|
||||
std::string for_install = this->Target->GetInstallNameDirForInstallTree(config);
|
||||
if(for_build != for_install)
|
||||
{
|
||||
// Prepare to refer to the install-tree install_name.
|
||||
new_id = for_install;
|
||||
new_id += this->GetScriptReference(this->Target, "REMAPPED", true);
|
||||
}
|
||||
}
|
||||
|
||||
// Write a rule to run install_name_tool to set the install-tree
|
||||
// install_name value and references.
|
||||
if(!new_id.empty() || !install_name_remap.empty())
|
||||
{
|
||||
os << "EXECUTE_PROCESS(COMMAND install_name_tool";
|
||||
if(!new_id.empty())
|
||||
{
|
||||
os << "\n -id \"" << new_id << "\"";
|
||||
}
|
||||
for(std::map<cmStdString, cmStdString>::const_iterator
|
||||
i = install_name_remap.begin();
|
||||
i != install_name_remap.end(); ++i)
|
||||
{
|
||||
os << "\n -change \"" << i->first << "\" \"" << i->second << "\"";
|
||||
}
|
||||
os << "\n \"" << this->Destination.c_str() << "/"
|
||||
<< this->GetScriptReference(this->Target, "REMAPPED", true) << "\")\n";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,8 +33,12 @@ public:
|
|||
|
||||
protected:
|
||||
virtual void GenerateScript(std::ostream& os);
|
||||
void PrepareInstallReference(std::ostream& os);
|
||||
std::string GetInstallReference();
|
||||
void PrepareScriptReference(std::ostream& os, cmTarget* target,
|
||||
const char* place, bool useConfigDir,
|
||||
bool useSOName);
|
||||
std::string GetScriptReference(cmTarget* target, const char* place,
|
||||
bool useSOName);
|
||||
void AddInstallNamePatchRule(std::ostream& os);
|
||||
cmTarget* Target;
|
||||
std::string Destination;
|
||||
bool ImportLibrary;
|
||||
|
|
|
@ -643,6 +643,13 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable,
|
|||
return "";
|
||||
}
|
||||
}
|
||||
if(replaceValues.TargetInstallNameDir)
|
||||
{
|
||||
if(variable == "TARGET_INSTALLNAME_DIR")
|
||||
{
|
||||
return replaceValues.TargetInstallNameDir;
|
||||
}
|
||||
}
|
||||
if(replaceValues.LinkLibraries)
|
||||
{
|
||||
if(variable == "LINK_LIBRARIES")
|
||||
|
|
|
@ -182,6 +182,7 @@ public:
|
|||
this->Flags= 0;
|
||||
this->ObjectsQuoted= 0;
|
||||
this->TargetSOName= 0;
|
||||
this->TargetInstallNameDir = 0;
|
||||
this->LinkFlags= 0;
|
||||
}
|
||||
const char* Language;
|
||||
|
@ -193,6 +194,7 @@ public:
|
|||
const char* Flags;
|
||||
const char* ObjectsQuoted;
|
||||
const char* TargetSOName;
|
||||
const char* TargetInstallNameDir;
|
||||
const char* LinkFlags;
|
||||
};
|
||||
|
||||
|
|
|
@ -392,7 +392,46 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
|
|||
vars.ObjectsQuoted = buildObjs.c_str();
|
||||
vars.TargetSOName= targetNameSO.c_str();
|
||||
vars.LinkFlags = linkFlags.c_str();
|
||||
|
||||
|
||||
// Compute the directory portion of the install_name setting.
|
||||
std::string install_name_dir;
|
||||
if(this->Target->GetType() == cmTarget::SHARED_LIBRARY)
|
||||
{
|
||||
// Select whether to generate an install_name directory for the
|
||||
// install tree or the build tree.
|
||||
const char* config = this->LocalGenerator->m_ConfigurationName.c_str();
|
||||
if(this->Target->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"))
|
||||
{
|
||||
install_name_dir =
|
||||
this->Target->GetInstallNameDirForInstallTree(config);
|
||||
}
|
||||
else
|
||||
{
|
||||
install_name_dir =
|
||||
this->Target->GetInstallNameDirForBuildTree(config);
|
||||
}
|
||||
|
||||
// Set the rule variable replacement value.
|
||||
if(install_name_dir.empty())
|
||||
{
|
||||
vars.TargetInstallNameDir = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert to a path for the native build tool.
|
||||
install_name_dir =
|
||||
this->LocalGenerator->Convert(install_name_dir.c_str(),
|
||||
cmLocalGenerator::FULL,
|
||||
cmLocalGenerator::SHELL, false);
|
||||
|
||||
// The Convert method seems to strip trailing slashes, which should
|
||||
// probably be fixed. Since the only platform supporting install_name
|
||||
// right now uses forward slashes just add one.
|
||||
install_name_dir += "/";
|
||||
vars.TargetInstallNameDir = install_name_dir.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
// Expand placeholders in the commands.
|
||||
this->LocalGenerator->m_TargetImplib = targetOutPathImport;
|
||||
for(std::vector<std::string>::iterator i = commands.begin();
|
||||
|
|
|
@ -95,10 +95,13 @@ public:
|
|||
"BUILD_WITH_INSTALL_RPATH is a boolean specifying whether to link "
|
||||
"the target in the build tree with the INSTALL_RPATH. This takes "
|
||||
"precedence over SKIP_BUILD_RPATH and avoids the need for relinking "
|
||||
"before installation. When the target is created the values of "
|
||||
"the variables CMAKE_INSTALL_RPATH, CMAKE_SKIP_BUILD_RPATH, and "
|
||||
"CMAKE_BUILD_WITH_INSTALL_RPATH are used to initialize these "
|
||||
"properties.\n"
|
||||
"before installation. INSTALL_NAME_DIR is a string specifying the "
|
||||
"directory portion of the \"install_name\" field of shared libraries "
|
||||
"on Mac OSX to use in the installed targets. "
|
||||
"When the target is created the values of "
|
||||
"the variables CMAKE_INSTALL_RPATH, CMAKE_SKIP_BUILD_RPATH, "
|
||||
"CMAKE_BUILD_WITH_INSTALL_RPATH, and CMAKE_INSTALL_NAME_DIR "
|
||||
"are used to initialize these properties.\n"
|
||||
"PROJECT_LABEL can be used to change the name of "
|
||||
"the target in an IDE like visual studio. VS_KEYWORD can be set "
|
||||
"to change the visual studio keyword, for example QT integration "
|
||||
|
|
|
@ -52,6 +52,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
|
|||
m_Makefile = mf;
|
||||
|
||||
// Setup default property values.
|
||||
this->SetPropertyDefault("INSTALL_NAME_DIR", "");
|
||||
this->SetPropertyDefault("INSTALL_RPATH", "");
|
||||
this->SetPropertyDefault("SKIP_BUILD_RPATH", "OFF");
|
||||
this->SetPropertyDefault("BUILD_WITH_INSTALL_RPATH", "OFF");
|
||||
|
@ -775,7 +776,7 @@ void cmTarget::SetProperty(const char* prop, const char* value)
|
|||
m_Properties[prop] = value;
|
||||
}
|
||||
|
||||
const char* cmTarget::GetDirectory()
|
||||
const char* cmTarget::GetDirectory(const char* config)
|
||||
{
|
||||
switch( this->GetType() )
|
||||
{
|
||||
|
@ -794,6 +795,13 @@ const char* cmTarget::GetDirectory()
|
|||
{
|
||||
m_Directory = m_Makefile->GetStartOutputDirectory();
|
||||
}
|
||||
if(config)
|
||||
{
|
||||
// Add the configuration's subdirectory.
|
||||
m_Directory += "/";
|
||||
m_Makefile->GetLocalGenerator()->GetGlobalGenerator()->
|
||||
AppendDirectoryForConfig(config, m_Directory);
|
||||
}
|
||||
return m_Directory.c_str();
|
||||
}
|
||||
|
||||
|
@ -1069,13 +1077,9 @@ void cmTarget::GetFullName(std::string& prefix, std::string& base,
|
|||
std::string cmTarget::GetFullPath(const char* config, bool implib)
|
||||
{
|
||||
// Start with the output directory for the target.
|
||||
std::string fpath = this->GetDirectory();
|
||||
std::string fpath = this->GetDirectory(config);
|
||||
fpath += "/";
|
||||
|
||||
// Add the configuration's subdirectory.
|
||||
m_Makefile->GetLocalGenerator()->GetGlobalGenerator()->
|
||||
AppendDirectoryForConfig(config, fpath);
|
||||
|
||||
// Add the full name of the target.
|
||||
fpath += this->GetFullName(config, implib);
|
||||
return fpath;
|
||||
|
@ -1440,3 +1444,47 @@ bool cmTarget::NeedRelinkBeforeInstall()
|
|||
// this target must be relinked.
|
||||
return this->HaveBuildTreeRPATH() || this->HaveInstallTreeRPATH();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmTarget::GetInstallNameDirForBuildTree(const char* config)
|
||||
{
|
||||
// If building directly for installation then the build tree install_name
|
||||
// is the same as the install tree.
|
||||
if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"))
|
||||
{
|
||||
return GetInstallNameDirForInstallTree(config);
|
||||
}
|
||||
|
||||
// Use the build tree directory for the target.
|
||||
if(m_Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME") &&
|
||||
!m_Makefile->IsOn("CMAKE_SKIP_RPATH") &&
|
||||
!this->GetPropertyAsBool("SKIP_BUILD_RPATH"))
|
||||
{
|
||||
std::string dir = this->GetDirectory(config);
|
||||
dir += "/";
|
||||
return dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cmTarget::GetInstallNameDirForInstallTree(const char*)
|
||||
{
|
||||
// Lookup the target property.
|
||||
const char* install_name_dir = this->GetProperty("INSTALL_NAME_DIR");
|
||||
if(m_Makefile->IsOn("CMAKE_PLATFORM_HAS_INSTALLNAME") &&
|
||||
!m_Makefile->IsOn("CMAKE_SKIP_RPATH") &&
|
||||
install_name_dir && *install_name_dir)
|
||||
{
|
||||
std::string dir = install_name_dir;
|
||||
dir += "/";
|
||||
return dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -157,7 +157,15 @@ public:
|
|||
const char *GetProperty(const char *prop);
|
||||
bool GetPropertyAsBool(const char *prop);
|
||||
|
||||
const char* GetDirectory();
|
||||
/** Get the directory in which this target will be built. If the
|
||||
configuration name is given then the generator will add its
|
||||
subdirectory for that configuration. Otherwise just the canonical
|
||||
output directory is given. */
|
||||
const char* GetDirectory(const char* config = 0);
|
||||
|
||||
/** Get the location of the target in the build tree for the given
|
||||
configuration. This location is suitable for use as the LOCATION
|
||||
target property. */
|
||||
const char* GetLocation(const char* config);
|
||||
|
||||
/**
|
||||
|
@ -222,6 +230,9 @@ public:
|
|||
bool HaveBuildTreeRPATH();
|
||||
bool HaveInstallTreeRPATH();
|
||||
|
||||
std::string GetInstallNameDirForBuildTree(const char* config);
|
||||
std::string GetInstallNameDirForInstallTree(const char* config);
|
||||
|
||||
private:
|
||||
/**
|
||||
* A list of direct dependencies. Use in conjunction with DependencyMap.
|
||||
|
|
|
@ -9,6 +9,9 @@ SET(LIBRARY_OUTPUT_PATH "${EXECUTABLE_OUTPUT_PATH}")
|
|||
# tree.
|
||||
SET(CMAKE_SKIP_BUILD_RPATH 1)
|
||||
|
||||
# Make sure the executable can run from the install tree.
|
||||
SET(CMAKE_INSTALL_NAME_DIR ${CMAKE_INSTALL_PREFIX}/lib)
|
||||
|
||||
# Skip the dependency that causes a build when installing. This
|
||||
# avoids infinite loops when the post-build rule below installs.
|
||||
SET(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY 1)
|
||||
|
|
|
@ -9,6 +9,9 @@ SET(LIBRARY_OUTPUT_PATH "${EXECUTABLE_OUTPUT_PATH}")
|
|||
# tree.
|
||||
SET(CMAKE_SKIP_BUILD_RPATH 1)
|
||||
|
||||
# Make sure the executable can run from the install tree.
|
||||
SET(CMAKE_INSTALL_NAME_DIR ${CMAKE_INSTALL_PREFIX}/lib)
|
||||
|
||||
# Skip the dependency that causes a build when installing. This
|
||||
# avoids infinite loops when the post-build rule below installs.
|
||||
SET(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY 1)
|
||||
|
|
Loading…
Reference in New Issue