summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2006-02-24 18:13:14 (GMT)
committerBrad King <brad.king@kitware.com>2006-02-24 18:13:14 (GMT)
commit586a9427d3dd8b4a99f7a3d545814f8b9bf42453 (patch)
tree82f286d8b7e97066af8c623bff58840ba42c5828
parent7db7b981afa37cb33c131c3ba1c559bb6d15b1a5 (diff)
downloadCMake-586a9427d3dd8b4a99f7a3d545814f8b9bf42453.zip
CMake-586a9427d3dd8b4a99f7a3d545814f8b9bf42453.tar.gz
CMake-586a9427d3dd8b4a99f7a3d545814f8b9bf42453.tar.bz2
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.
-rw-r--r--Modules/Platform/Darwin.cmake36
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx102
-rw-r--r--Source/cmGlobalXCodeGenerator.h5
-rw-r--r--Source/cmInstallTargetGenerator.cxx173
-rw-r--r--Source/cmInstallTargetGenerator.h8
-rw-r--r--Source/cmLocalGenerator.cxx7
-rw-r--r--Source/cmLocalGenerator.h2
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx41
-rw-r--r--Source/cmSetTargetPropertiesCommand.h11
-rw-r--r--Source/cmTarget.cxx60
-rw-r--r--Source/cmTarget.h13
-rw-r--r--Tests/SimpleInstall/CMakeLists.txt3
-rw-r--r--Tests/SimpleInstallS2/CMakeLists.txt3
13 files changed, 409 insertions, 55 deletions
diff --git a/Modules/Platform/Darwin.cmake b/Modules/Platform/Darwin.cmake
index f6e5946..46374cf 100644
--- a/Modules/Platform/Darwin.cmake
+++ b/Modules/Platform/Darwin.cmake
@@ -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>")
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 273c98c..d15e53b 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -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;
+}
diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h
index 7d49b34..0e6f65f 100644
--- a/Source/cmGlobalXCodeGenerator.h
+++ b/Source/cmGlobalXCodeGenerator.h
@@ -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;
diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx
index 243ba63..62f0504 100644
--- a/Source/cmInstallTargetGenerator.cxx
+++ b/Source/cmInstallTargetGenerator.cxx
@@ -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";
+ }
+}
diff --git a/Source/cmInstallTargetGenerator.h b/Source/cmInstallTargetGenerator.h
index 6e13ac8..ac7058a 100644
--- a/Source/cmInstallTargetGenerator.h
+++ b/Source/cmInstallTargetGenerator.h
@@ -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;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 1f6a596..ab2d31d 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -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")
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 7260513..d28917a 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -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;
};
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index d8bc80e..a5b6154 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -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();
diff --git a/Source/cmSetTargetPropertiesCommand.h b/Source/cmSetTargetPropertiesCommand.h
index e3afd76..2bb9a81 100644
--- a/Source/cmSetTargetPropertiesCommand.h
+++ b/Source/cmSetTargetPropertiesCommand.h
@@ -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 "
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index e15dcdd..68788fa 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -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 "";
+ }
+}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index eb455fa..bb4140b 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -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.
diff --git a/Tests/SimpleInstall/CMakeLists.txt b/Tests/SimpleInstall/CMakeLists.txt
index a12fdcd..c712978 100644
--- a/Tests/SimpleInstall/CMakeLists.txt
+++ b/Tests/SimpleInstall/CMakeLists.txt
@@ -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)
diff --git a/Tests/SimpleInstallS2/CMakeLists.txt b/Tests/SimpleInstallS2/CMakeLists.txt
index a12fdcd..c712978 100644
--- a/Tests/SimpleInstallS2/CMakeLists.txt
+++ b/Tests/SimpleInstallS2/CMakeLists.txt
@@ -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)