summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx24
-rw-r--r--Source/cmLocalGenerator.cxx50
-rw-r--r--Source/cmLocalGenerator.h2
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx18
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx20
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.h2
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx57
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.h7
-rw-r--r--Source/cmSetTargetPropertiesCommand.h15
-rw-r--r--Source/cmTarget.cxx101
-rw-r--r--Source/cmTarget.h16
-rw-r--r--Tests/SimpleInstall/CMakeLists.txt3
-rw-r--r--Tests/SimpleInstallS2/CMakeLists.txt3
13 files changed, 278 insertions, 40 deletions
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 1acea61..70c0ed4 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -152,6 +152,11 @@ void cmGlobalUnixMakefileGenerator3::WriteMainMakefile2()
"The main recursive all target", "all",
depends, no_commands, true);
+ // Write an empty preinstall:
+ lg->WriteMakeRule(makefileStream,
+ "The main recursive preinstall target", "preinstall",
+ depends, no_commands, true);
+
lg->WriteMakeVariables(makefileStream);
// Write out the "special" stuff
@@ -731,6 +736,25 @@ cmGlobalUnixMakefileGenerator3
lg->WriteMakeRule(ruleFileStream, "Convenience name for target.",
t->second.GetName(), depends, commands, true);
+ // Add rules to prepare the target for installation.
+ if(t->second.NeedRelinkBeforeInstall())
+ {
+ localName = lg->GetRelativeTargetDirectory(t->second);
+ localName += "/preinstall";
+ depends.clear();
+ commands.clear();
+ commands.push_back(lg->GetRecursiveMakeCall
+ (makefileName.c_str(), localName.c_str()));
+ this->AppendGlobalTargetDepends(depends,t->second);
+ lg->WriteMakeRule(ruleFileStream, "Pre-intsall relink rule for target.",
+ localName.c_str(), depends, commands, true);
+ depends.clear();
+ depends.push_back(localName);
+ commands.clear();
+ lg->WriteMakeRule(ruleFileStream, "Prepare target for install.",
+ "preinstall", depends, commands, true);
+ }
+
// add the clean rule
localName = lg->GetRelativeTargetDirectory(t->second);
makeTargetName = localName;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 4a95ca1..42738f9 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -353,6 +353,7 @@ void cmLocalGenerator::GenerateInstallRules()
// EXECUTABLE_OUTPUT_PATH not defined
exeOutPath = currdir + "/";
}
+ std::string relinkDir = currdir + "/CMakeFiles/CMakeRelink.dir/";
// Include user-specified install scripts.
std::vector<std::string> const& installScripts =
@@ -375,6 +376,7 @@ void cmLocalGenerator::GenerateInstallRules()
}
if (l->second.GetInstallPath() != "")
{
+ bool need_relink = l->second.NeedRelinkBeforeInstall();
destination = "${CMAKE_INSTALL_PREFIX}" + l->second.GetInstallPath();
cmSystemTools::ConvertToUnixSlashes(destination);
const char* dest = destination.c_str();
@@ -398,7 +400,7 @@ void cmLocalGenerator::GenerateInstallRules()
if ( ext == ".dll" )
{
// Install the .lib separately.
- std::string libname = libOutPath;
+ std::string libname = need_relink? relinkDir : libOutPath;
libname += this->GetInstallReference(l->second, config,
configurationTypes,
true);
@@ -438,7 +440,7 @@ void cmLocalGenerator::GenerateInstallRules()
case cmTarget::STATIC_LIBRARY:
case cmTarget::MODULE_LIBRARY:
{
- fname = libOutPath;
+ fname = need_relink? relinkDir : libOutPath;
fname += this->GetInstallReference(l->second, config,
configurationTypes);
files = fname.c_str();
@@ -460,7 +462,7 @@ void cmLocalGenerator::GenerateInstallRules()
}
std::string exeName =
this->GetInstallReference(l->second, config, configurationTypes);
- fname = exeOutPath;
+ fname = need_relink? relinkDir : exeOutPath;
fname += exeName;
if(l->second.GetPropertyAsBool("MACOSX_BUNDLE"))
{
@@ -1117,7 +1119,11 @@ const char* cmLocalGenerator::GetIncludeFlags(const char* lang)
}
flags += m_Makefile->GetDefineFlags();
m_LanguageToIncludeFlags[lang] = flags;
- return m_LanguageToIncludeFlags[lang].c_str();
+
+ // Use this temorary variable for the return value to work-around a
+ // bogus GCC 2.95 warning.
+ const char* ret = m_LanguageToIncludeFlags[lang].c_str();
+ return ret;
}
//----------------------------------------------------------------------------
@@ -1246,7 +1252,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
linkFlags += " ";
}
cmOStringStream linklibsStr;
- this->OutputLinkLibraries(linklibsStr, target);
+ this->OutputLinkLibraries(linklibsStr, target, false);
linkLibs = linklibsStr.str();
}
break;
@@ -1279,7 +1285,7 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
flags += m_Makefile->GetSafeDefinition(sharedFlagsVar.c_str());
flags += " ";
cmOStringStream linklibs;
- this->OutputLinkLibraries(linklibs, target);
+ this->OutputLinkLibraries(linklibs, target, false);
linkLibs = linklibs.str();
if(cmSystemTools::IsOn(m_Makefile->GetDefinition("BUILD_SHARED_LIBS")))
{
@@ -1319,7 +1325,8 @@ void cmLocalGenerator::GetTargetFlags(std::string& linkLibs,
* to the name of the library. This will not link a library against itself.
*/
void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
- cmTarget &tgt)
+ cmTarget& tgt,
+ bool relink)
{
// Try to emit each search path once
std::set<cmStdString> emitted;
@@ -1327,7 +1334,6 @@ void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
bool outputRuntime = true;
std::string runtimeFlag;
std::string runtimeSep;
- std::vector<std::string> runtimeDirs;
const char* config = m_Makefile->GetDefinition("CMAKE_BUILD_TYPE");
const char* linkLanguage = tgt.GetLinkerLanguage(this->GetGlobalGenerator());
@@ -1347,7 +1353,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
// concatenate all paths or no?
bool runtimeConcatenate = ( runtimeSep!="" );
- if(runtimeFlag == "" || m_Makefile->IsOn("CMAKE_SKIP_RPATH") )
+ if(runtimeFlag == "" || m_Makefile->IsOn("CMAKE_SKIP_RPATH"))
{
outputRuntime = false;
}
@@ -1375,6 +1381,28 @@ void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
std::vector<cmStdString> libDirs;
this->ComputeLinkInformation(tgt, config, libNames, libDirs);
+ // Select whether to generate an rpath for the install tree or the
+ // build tree.
+ bool linking_for_install =
+ relink || tgt.GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH");
+ bool use_install_rpath =
+ outputRuntime && tgt.HaveInstallTreeRPATH() && linking_for_install;
+ bool use_build_rpath =
+ outputRuntime && tgt.HaveBuildTreeRPATH() && !linking_for_install;
+
+ // Construct the RPATH.
+ std::vector<std::string> runtimeDirs;
+ if(use_install_rpath)
+ {
+ const char* install_rpath = tgt.GetProperty("INSTALL_RPATH");
+ cmSystemTools::ExpandListArgument(install_rpath, runtimeDirs);
+ for(unsigned int i=0; i < runtimeDirs.size(); ++i)
+ {
+ runtimeDirs[i] =
+ this->Convert(runtimeDirs[i].c_str(), FULL, SHELL, false);
+ }
+ }
+
// Append the library search path flags.
for(std::vector<cmStdString>::const_iterator libDir = libDirs.begin();
libDir != libDirs.end(); ++libDir)
@@ -1397,7 +1425,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
&& libDir->find("${") == std::string::npos)
{
linkLibs += libPathFlag;
- if(outputRuntime)
+ if(use_build_rpath)
{
runtimeDirs.push_back( fullLibPath );
}
@@ -1417,7 +1445,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::ostream& fout,
fout << linkLibs;
- if(outputRuntime && runtimeDirs.size()>0)
+ if(!runtimeDirs.empty())
{
// For the runtime search directories, do a "-Wl,-rpath,a:b:c" or
// a "-R a -R b -R c" type link line
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index f9dd468..9937cae 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -175,7 +175,7 @@ protected:
cmTarget&target);
///! put all the libraries for a target on into the given stream
- virtual void OutputLinkLibraries(std::ostream&, cmTarget&);
+ virtual void OutputLinkLibraries(std::ostream&, cmTarget&, bool relink);
/** Compute the string to use to refer to a target in an install
file. */
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index fe1e25b..d421b4b 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -1288,6 +1288,7 @@ void cmLocalUnixMakefileGenerator3
// Write special "install" target to run cmake_install.cmake script.
{
std::vector<std::string> depends;
+ depends.push_back("preinstall");
std::vector<std::string> commands;
std::string cmd;
if(m_Makefile->GetDefinition("CMake_BINARY_DIR"))
@@ -1304,6 +1305,12 @@ void cmLocalUnixMakefileGenerator3
}
cmd += " -P cmake_install.cmake";
commands.push_back(cmd);
+ this->WriteMakeRule(ruleFileStream,
+ "Special rule to run installation script.",
+ "install", depends, commands, true);
+
+ commands.clear();
+ depends.clear();
const char* noall =
m_Makefile->GetDefinition("CMAKE_SKIP_INSTALL_ALL_DEPENDENCY");
if(!noall || cmSystemTools::IsOff(noall))
@@ -1311,9 +1318,16 @@ void cmLocalUnixMakefileGenerator3
// Drive the build before installing.
depends.push_back("all");
}
+ else
+ {
+ // At least make sure the build system is up to date.
+ depends.push_back("cmake_check_build_system");
+ }
+ commands.push_back(this->GetRecursiveMakeCall
+ ("CMakeFiles/Makefile2", "preinstall"));
this->WriteMakeRule(ruleFileStream,
- "Special rule to run installation script.",
- "install", depends, commands, true);
+ "Prepare targets for installation.",
+ "preinstall", depends, commands, true);
}
// Write special "rebuild_cache" target to re-run cmake.
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 600cb2e..87d6feb 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -39,7 +39,12 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
this->WriteTargetDependRules();
// write the link rules
- this->WriteExecutableRule();
+ this->WriteExecutableRule(false);
+ if(this->Target->NeedRelinkBeforeInstall())
+ {
+ // Write rules to link an installable version of the target.
+ this->WriteExecutableRule(true);
+ }
// Write the requires target.
this->WriteTargetRequiresRules();
@@ -54,7 +59,7 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
//----------------------------------------------------------------------------
-void cmMakefileExecutableTargetGenerator::WriteExecutableRule()
+void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
{
std::vector<std::string> commands;
@@ -132,6 +137,13 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule()
false, false, false);
}
#endif
+ if(relink)
+ {
+ outpath = this->Makefile->GetStartOutputDirectory();
+ outpath += "/CMakeFiles/CMakeRelink.dir";
+ cmSystemTools::MakeDirectory(outpath.c_str());
+ outpath += "/";
+ }
std::string targetFullPath = outpath + targetName;
std::string targetFullPathReal = outpath + targetNameReal;
@@ -259,7 +271,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule()
// Collect up flags to link in needed libraries.
cmOStringStream linklibs;
- this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target);
+ this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target, relink);
// Construct object file lists that may be needed to expand the
// rule.
@@ -316,7 +328,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule()
dir += "/";
dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
std::string buildTargetRuleName = dir;
- buildTargetRuleName += "/build";
+ buildTargetRuleName += relink?"/preinstall":"/build";
buildTargetRuleName =
this->Convert(buildTargetRuleName.c_str(),
cmLocalGenerator::HOME_OUTPUT,
diff --git a/Source/cmMakefileExecutableTargetGenerator.h b/Source/cmMakefileExecutableTargetGenerator.h
index a02286c..f6ffad2 100644
--- a/Source/cmMakefileExecutableTargetGenerator.h
+++ b/Source/cmMakefileExecutableTargetGenerator.h
@@ -27,7 +27,7 @@ public:
virtual void WriteRuleFiles();
protected:
- virtual void WriteExecutableRule();
+ virtual void WriteExecutableRule(bool relink);
};
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index b4d5aa9..206b49d 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -46,10 +46,20 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
this->WriteStaticLibraryRules();
break;
case cmTarget::SHARED_LIBRARY:
- this->WriteSharedLibraryRules();
+ this->WriteSharedLibraryRules(false);
+ if(this->Target->NeedRelinkBeforeInstall())
+ {
+ // Write rules to link an installable version of the target.
+ this->WriteSharedLibraryRules(true);
+ }
break;
case cmTarget::MODULE_LIBRARY:
- this->WriteModuleLibraryRules();
+ this->WriteModuleLibraryRules(false);
+ if(this->Target->NeedRelinkBeforeInstall())
+ {
+ // Write rules to link an installable version of the target.
+ this->WriteModuleLibraryRules(true);
+ }
break;
default:
// If language is not known, this is an error.
@@ -82,11 +92,11 @@ void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
std::string extraFlags;
this->LocalGenerator->AppendFlags(extraFlags, this->Target->GetProperty("STATIC_LIBRARY_FLAGS"));
- this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str());
+ this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), false);
}
//----------------------------------------------------------------------------
-void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules()
+void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
{
const char* linkLanguage =
this->Target->GetLinkerLanguage(this->GlobalGenerator);
@@ -115,11 +125,11 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules()
}
}
}
- this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str());
+ this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
}
//----------------------------------------------------------------------------
-void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules()
+void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
{
const char* linkLanguage =
this->Target->GetLinkerLanguage(this->GlobalGenerator);
@@ -134,12 +144,12 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules()
this->LocalGenerator->AppendFlags(extraFlags, this->Target->GetProperty("LINK_FLAGS"));
this->LocalGenerator->AddConfigVariableFlags(extraFlags, "CMAKE_MODULE_LINKER_FLAGS");
// TODO: .def files should be supported here also.
- this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str());
+ this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
}
//----------------------------------------------------------------------------
void cmMakefileLibraryTargetGenerator::WriteLibraryRules
-(const char* linkRuleVar, const char* extraFlags)
+(const char* linkRuleVar, const char* extraFlags, bool relink)
{
// TODO: Merge the methods that call this method to avoid
// code duplication.
@@ -202,6 +212,13 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
outpath = this->Makefile->GetStartOutputDirectory();
outpath += "/";
}
+ if(relink)
+ {
+ outpath = this->Makefile->GetStartOutputDirectory();
+ outpath += "/CMakeFiles/CMakeRelink.dir";
+ cmSystemTools::MakeDirectory(outpath.c_str());
+ outpath += "/";
+ }
std::string targetFullPath = outpath + targetName;
std::string targetFullPathSO = outpath + targetNameSO;
std::string targetFullPathReal = outpath + targetNameReal;
@@ -285,9 +302,15 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
this->Makefile->GetHomeOutputDirectory());
commands.insert(commands.end(), commands1.begin(), commands1.end());
commands1.clear();
- // Add the pre-build and pre-link rules.
- this->LocalGenerator->AppendCustomCommands(commands, this->Target->GetPreBuildCommands());
- this->LocalGenerator->AppendCustomCommands(commands, this->Target->GetPreLinkCommands());
+
+ // Add the pre-build and pre-link rules building but not when relinking.
+ if(!relink)
+ {
+ this->LocalGenerator
+ ->AppendCustomCommands(commands, this->Target->GetPreBuildCommands());
+ this->LocalGenerator
+ ->AppendCustomCommands(commands, this->Target->GetPreLinkCommands());
+ }
// Construct the main link rule.
std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
@@ -314,12 +337,16 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
commands.insert(commands.end(), commands1.begin(), commands1.end());
}
- // Add the post-build rules.
- this->LocalGenerator->AppendCustomCommands(commands, this->Target->GetPostBuildCommands());
+ // Add the post-build rules when building but not when relinking.
+ if(!relink)
+ {
+ this->LocalGenerator->
+ AppendCustomCommands(commands, this->Target->GetPostBuildCommands());
+ }
// Collect up flags to link in needed libraries.
cmOStringStream linklibs;
- this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target);
+ this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target, relink);
// Construct object file lists that may be needed to expand the
// rule.
@@ -381,7 +408,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
dir += "/";
dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
std::string buildTargetRuleName = dir;
- buildTargetRuleName += "/build";
+ buildTargetRuleName += relink?"/preinstall":"/build";
buildTargetRuleName =
this->Convert(buildTargetRuleName.c_str(),
cmLocalGenerator::HOME_OUTPUT,cmLocalGenerator::MAKEFILE);
diff --git a/Source/cmMakefileLibraryTargetGenerator.h b/Source/cmMakefileLibraryTargetGenerator.h
index 7c7c43d..502e35b 100644
--- a/Source/cmMakefileLibraryTargetGenerator.h
+++ b/Source/cmMakefileLibraryTargetGenerator.h
@@ -29,9 +29,10 @@ public:
protected:
void WriteStaticLibraryRules();
- void WriteSharedLibraryRules();
- void WriteModuleLibraryRules();
- void WriteLibraryRules(const char *linkRule, const char *extraFlags);
+ void WriteSharedLibraryRules(bool relink);
+ void WriteModuleLibraryRules(bool relink);
+ void WriteLibraryRules(const char *linkRule, const char *extraFlags,
+ bool relink);
};
#endif
diff --git a/Source/cmSetTargetPropertiesCommand.h b/Source/cmSetTargetPropertiesCommand.h
index 5d5b23d..f4cb976 100644
--- a/Source/cmSetTargetPropertiesCommand.h
+++ b/Source/cmSetTargetPropertiesCommand.h
@@ -79,7 +79,20 @@ public:
"When building or installing appropriate symlinks are created if "
"the platform supports symlinks. "
"The OUTPUT_NAME can be used to set an output name that is "
- "used in place of the target name when creating executables. "
+ "used in place of the target name when creating executables.\n"
+ "There are a few properties used to specify RPATH rules. "
+ "INSTALL_RPATH is a semicolon-separated list specifying the rpath "
+ "to use in installed targets (for platforms that support it). "
+ "SKIP_BUILD_RPATH is a boolean specifying whether to skip automatic "
+ "generation of an rpath allowing the target to run from the "
+ "build tree. "
+ "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"
"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 58a40b3..c006bf2 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -44,6 +44,17 @@ void cmTarget::SetType(TargetType type, const char* name)
}
}
+//----------------------------------------------------------------------------
+void cmTarget::SetMakefile(cmMakefile* mf)
+{
+ // Set our makefile.
+ m_Makefile = mf;
+
+ // Setup default property values.
+ this->SetPropertyDefault("INSTALL_RPATH", "");
+ this->SetPropertyDefault("SKIP_BUILD_RPATH", "OFF");
+ this->SetPropertyDefault("BUILD_WITH_INSTALL_RPATH", "OFF");
+}
void cmTarget::TraceVSDependencies(std::string projFile,
cmMakefile *makefile)
@@ -1309,3 +1320,93 @@ void cmTarget::GetExecutableNamesInternal(std::string& name,
realName += version;
}
}
+
+//----------------------------------------------------------------------------
+void cmTarget::SetPropertyDefault(const char* property,
+ const char* default_value)
+{
+ // Compute the name of the variable holding the default value.
+ std::string var = "CMAKE_";
+ var += property;
+
+ if(const char* value = m_Makefile->GetDefinition(var.c_str()))
+ {
+ this->SetProperty(property, value);
+ }
+ else if(default_value)
+ {
+ this->SetProperty(property, default_value);
+ }
+}
+
+//----------------------------------------------------------------------------
+bool cmTarget::HaveBuildTreeRPATH()
+{
+ return (!this->GetPropertyAsBool("SKIP_BUILD_RPATH") &&
+ !m_LinkLibraries.empty());
+}
+
+//----------------------------------------------------------------------------
+bool cmTarget::HaveInstallTreeRPATH()
+{
+ const char* install_rpath = this->GetProperty("INSTALL_RPATH");
+ return install_rpath && *install_rpath;
+}
+
+//----------------------------------------------------------------------------
+bool cmTarget::NeedRelinkBeforeInstall()
+{
+ // Only executables and shared libraries can have an rpath and may
+ // need relinking.
+ if(m_TargetType != cmTarget::EXECUTABLE &&
+ m_TargetType != cmTarget::SHARED_LIBRARY &&
+ m_TargetType != cmTarget::MODULE_LIBRARY)
+ {
+ return false;
+ }
+
+ // If there is no install location this target will not be installed
+ // and therefore does not need relinking.
+ if(this->GetInstallPath().empty())
+ {
+ return false;
+ }
+
+ // If skipping all rpaths completely then no relinking is needed.
+ if(m_Makefile->IsOn("CMAKE_SKIP_RPATH"))
+ {
+ return false;
+ }
+
+ // If building with the install-tree rpath no relinking is needed.
+ if(this->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"))
+ {
+ return false;
+ }
+
+ // Check for rpath support on this platform.
+ if(const char* ll = this->GetLinkerLanguage(
+ m_Makefile->GetLocalGenerator()->GetGlobalGenerator()))
+ {
+ std::string flagVar = "CMAKE_SHARED_LIBRARY_RUNTIME_";
+ flagVar += ll;
+ flagVar += "_FLAG";
+ if(!m_Makefile->IsSet(flagVar.c_str()))
+ {
+ // There is no rpath support on this platform so nothing needs
+ // relinking.
+ return false;
+ }
+ }
+ else
+ {
+ // No linker language is known. This error will be reported by
+ // other code.
+ return false;
+ }
+
+ // If either a build or install tree rpath is set then the rpath
+ // will likely change between the build tree and install tree and
+ // this target must be relinked.
+ return this->HaveBuildTreeRPATH() || this->HaveInstallTreeRPATH();
+}
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 790ab39..0f6749c 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -63,7 +63,7 @@ public:
void SetInAll(bool f) { this->SetProperty("IN_ALL", (f) ?"TRUE" : "FALSE"); }
///! Set the cmMakefile that owns this target
- void SetMakefile(cmMakefile *mf) { m_Makefile = mf; };
+ void SetMakefile(cmMakefile *mf);
cmMakefile *GetMakefile() { return m_Makefile;};
/**
@@ -209,6 +209,15 @@ public:
executable target. */
void GetExecutableCleanNames(std::string& name, std::string& realName,
const char* config);
+
+ /**
+ * Compute whether this target must be relinked before installing.
+ */
+ bool NeedRelinkBeforeInstall();
+
+ bool HaveBuildTreeRPATH();
+ bool HaveInstallTreeRPATH();
+
private:
/**
* A list of direct dependencies. Use in conjunction with DependencyMap.
@@ -281,7 +290,10 @@ private:
// update the value of the LOCATION var
void UpdateLocation();
-
+
+ // Use a makefile variable to set a default for the given property.
+ // If the variable is not defined use the given default instead.
+ void SetPropertyDefault(const char* property, const char* default_value);
private:
std::string m_Name;
std::vector<cmCustomCommand> m_PreBuildCommands;
diff --git a/Tests/SimpleInstall/CMakeLists.txt b/Tests/SimpleInstall/CMakeLists.txt
index b238b87..4f64662 100644
--- a/Tests/SimpleInstall/CMakeLists.txt
+++ b/Tests/SimpleInstall/CMakeLists.txt
@@ -8,6 +8,9 @@ SET(LIBRARY_OUTPUT_PATH "${EXECUTABLE_OUTPUT_PATH}")
# avoids infinite loops when the post-build rule below installs.
SET(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY 1)
+# Make sure the test executable can run from the install tree.
+SET(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
+
SET(CMAKE_DEBUG_POSTFIX "_test_debug_postfix")
SET(EXTRA_INSTALL_FLAGS)
diff --git a/Tests/SimpleInstallS2/CMakeLists.txt b/Tests/SimpleInstallS2/CMakeLists.txt
index b238b87..4f64662 100644
--- a/Tests/SimpleInstallS2/CMakeLists.txt
+++ b/Tests/SimpleInstallS2/CMakeLists.txt
@@ -8,6 +8,9 @@ SET(LIBRARY_OUTPUT_PATH "${EXECUTABLE_OUTPUT_PATH}")
# avoids infinite loops when the post-build rule below installs.
SET(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY 1)
+# Make sure the test executable can run from the install tree.
+SET(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib)
+
SET(CMAKE_DEBUG_POSTFIX "_test_debug_postfix")
SET(EXTRA_INSTALL_FLAGS)