summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2003-11-26 22:38:37 (GMT)
committerBrad King <brad.king@kitware.com>2003-11-26 22:38:37 (GMT)
commit9229e6bc8b27556f913657d300e3c54a78770fc3 (patch)
tree8386a2a71a446abaf11e332cbbe72f35b2d2c086
parent5bbc45d589ba0a5725c232c57de38d8e8ea97598 (diff)
downloadCMake-9229e6bc8b27556f913657d300e3c54a78770fc3.zip
CMake-9229e6bc8b27556f913657d300e3c54a78770fc3.tar.gz
CMake-9229e6bc8b27556f913657d300e3c54a78770fc3.tar.bz2
ENH: Adding implementation of shared library version support on UNIX. This addresses the feature request described in bug#32.
-rw-r--r--Source/cmLocalUnixMakefileGenerator.cxx303
-rw-r--r--Source/cmLocalUnixMakefileGenerator.h13
2 files changed, 240 insertions, 76 deletions
diff --git a/Source/cmLocalUnixMakefileGenerator.cxx b/Source/cmLocalUnixMakefileGenerator.cxx
index 82805df..d8e05ff 100644
--- a/Source/cmLocalUnixMakefileGenerator.cxx
+++ b/Source/cmLocalUnixMakefileGenerator.cxx
@@ -332,30 +332,24 @@ std::string cmLocalUnixMakefileGenerator::GetOutputExtension(const char* s)
}
}
-std::string cmLocalUnixMakefileGenerator::GetFullTargetName(const char* n,
+std::string cmLocalUnixMakefileGenerator::GetBaseTargetName(const char* n,
const cmTarget& t)
{
const char* targetPrefix = t.GetProperty("PREFIX");
- const char* targetSuffix = t.GetProperty("SUFFIX");
const char* prefixVar = 0;
- const char* suffixVar = 0;
switch(t.GetType())
{
case cmTarget::STATIC_LIBRARY:
prefixVar = "CMAKE_STATIC_LIBRARY_PREFIX";
- suffixVar = "CMAKE_STATIC_LIBRARY_SUFFIX";
break;
case cmTarget::SHARED_LIBRARY:
prefixVar = "CMAKE_SHARED_LIBRARY_PREFIX";
- suffixVar = "CMAKE_SHARED_LIBRARY_SUFFIX";
break;
case cmTarget::MODULE_LIBRARY:
prefixVar = "CMAKE_SHARED_MODULE_PREFIX";
- suffixVar = "CMAKE_SHARED_MODULE_SUFFIX";
break;
case cmTarget::EXECUTABLE:
case cmTarget::WIN32_EXECUTABLE:
- targetSuffix = cmSystemTools::GetExecutableExtension();
case cmTarget::UTILITY:
case cmTarget::INSTALL_FILES:
case cmTarget::INSTALL_PROGRAMS:
@@ -366,13 +360,41 @@ std::string cmLocalUnixMakefileGenerator::GetFullTargetName(const char* n,
{
targetPrefix = this->GetSafeDefinition(prefixVar);
}
+ std::string name = targetPrefix?targetPrefix:"";
+ name += n;
+ return name;
+}
+
+std::string cmLocalUnixMakefileGenerator::GetFullTargetName(const char* n,
+ const cmTarget& t)
+{
+ const char* targetSuffix = t.GetProperty("SUFFIX");
+ const char* suffixVar = 0;
+ switch(t.GetType())
+ {
+ case cmTarget::STATIC_LIBRARY:
+ suffixVar = "CMAKE_STATIC_LIBRARY_SUFFIX";
+ break;
+ case cmTarget::SHARED_LIBRARY:
+ suffixVar = "CMAKE_SHARED_LIBRARY_SUFFIX";
+ break;
+ case cmTarget::MODULE_LIBRARY:
+ suffixVar = "CMAKE_SHARED_MODULE_SUFFIX";
+ break;
+ case cmTarget::EXECUTABLE:
+ case cmTarget::WIN32_EXECUTABLE:
+ targetSuffix = cmSystemTools::GetExecutableExtension();
+ case cmTarget::UTILITY:
+ case cmTarget::INSTALL_FILES:
+ case cmTarget::INSTALL_PROGRAMS:
+ break;
+ }
// if there is no suffix on the target use the cmake definition
if(!targetSuffix && suffixVar)
{
targetSuffix = this->GetSafeDefinition(suffixVar);
}
- std::string name = targetPrefix?targetPrefix:"";
- name += n;
+ std::string name = this->GetBaseTargetName(n, t);
name += targetSuffix?targetSuffix:"";
return name;
}
@@ -539,6 +561,45 @@ void cmLocalUnixMakefileGenerator::OutputTargetRules(std::ostream& fout)
fout << "\n\n";
}
}
+
+ // This list contains extra files created for a target. It includes
+ // the extra names associated with a versioned shared library.
+ fout << "TARGET_EXTRAS = ";
+ for(cmTargets::const_iterator l = tgts.begin();
+ l != tgts.end(); l++)
+ {
+ if (l->second.IsInAll())
+ {
+ if(l->second.GetType() == cmTarget::SHARED_LIBRARY ||
+ l->second.GetType() == cmTarget::MODULE_LIBRARY)
+ {
+ std::string targetName;
+ std::string targetNameSO;
+ std::string targetNameReal;
+ std::string targetNameBase;
+ this->GetLibraryNames(l->first.c_str(), l->second,
+ targetName, targetNameSO,
+ targetNameReal, targetNameBase);
+ if(targetNameSO != targetName)
+ {
+ path = m_LibraryOutputPath;
+ path += targetNameSO;
+ fout << " \\\n"
+ << cmSystemTools::ConvertToOutputPath(path.c_str());
+ }
+ if(targetNameReal != targetName &&
+ targetNameReal != targetNameSO)
+ {
+ path = m_LibraryOutputPath;
+ path += targetNameReal;
+ fout << " \\\n"
+ << cmSystemTools::ConvertToOutputPath(path.c_str());
+ }
+ }
+ }
+ }
+
+ fout << "\n\n";
fout << "CLEAN_OBJECT_FILES = ";
for(cmTargets::const_iterator l = tgts.begin();
l != tgts.end(); l++)
@@ -873,7 +934,8 @@ static RuleVariables ruleReplaceVars[] =
{"<CMAKE_CXX_LINK_FLAGS>", "CMAKE_CXX_LINK_FLAGS"},
{"<CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS>", "CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS"},
- {"<CMAKE_SHARED_MODULE_CREATE_C_FLAGS>", "CMAKE_SHARED_MODULE_CREATE_C_FLAGS"},
+ {"<CMAKE_SHARED_MODULE_CREATE_C_FLAGS>", "CMAKE_SHARED_MODULE_CREATE_C_FLAGS"},
+ {"<CMAKE_SHARED_LIBRARY_SONAME_FLAG>", "CMAKE_SHARED_LIBRARY_SONAME_FLAG"},
{"<CMAKE_C_LINK_FLAGS>", "CMAKE_C_LINK_FLAGS"},
{"<CMAKE_AR>", "CMAKE_AR"},
@@ -894,6 +956,7 @@ cmLocalUnixMakefileGenerator::ExpandRuleVariables(std::string& s,
const char* flags,
const char* objectsquoted,
const char* targetBase,
+ const char* targetSOName,
const char* linkFlags)
{
std::string cxxcompiler = this->ConvertToOutputForExisting(
@@ -955,6 +1018,17 @@ cmLocalUnixMakefileGenerator::ExpandRuleVariables(std::string& s,
}
cmSystemTools::ReplaceString(s, "<TARGET_BASE>", targetBase);
}
+ if(targetSOName)
+ {
+ if(m_Makefile->GetDefinition("CMAKE_SHARED_LIBRARY_SONAME_FLAG"))
+ {
+ cmSystemTools::ReplaceString(s, "<TARGET_SONAME>", targetSOName);
+ }
+ else
+ {
+ cmSystemTools::ReplaceString(s, "<TARGET_SONAME>", "");
+ }
+ }
if(linkLibs)
{
cmSystemTools::ReplaceString(s, "<LINK_LIBRARIES>", linkLibs);
@@ -973,40 +1047,57 @@ cmLocalUnixMakefileGenerator::ExpandRuleVariables(std::string& s,
void cmLocalUnixMakefileGenerator::OutputLibraryRule(std::ostream& fout,
const char* name,
const cmTarget &t,
- const char* prefix,
- const char* suffix,
const char* createVariable,
const char* comment,
const char* linkFlags
)
{
- // create the library name
- std::string targetNameBase = prefix;
- targetNameBase += name;
-
- std::string targetName = prefix;
- targetName += name;
- targetName += suffix;
- // create the target full path name
+ std::string targetName;
+ std::string targetNameSO;
+ std::string targetNameReal;
+ std::string targetNameBase;
+ this->GetLibraryNames(name, t,
+ targetName, targetNameSO,
+ targetNameReal, targetNameBase);
+
+ // The full path versions of the names.
std::string targetFullPath = m_LibraryOutputPath + targetName;
- std::string targetBaseFullPath = m_LibraryOutputPath + targetNameBase;
- targetBaseFullPath =
- cmSystemTools::ConvertToOutputPath(targetBaseFullPath.c_str());
+ std::string targetFullPathSO = m_LibraryOutputPath + targetNameSO;
+ std::string targetFullPathReal = m_LibraryOutputPath + targetNameReal;
+ std::string targetFullPathBase = m_LibraryOutputPath + targetNameBase;
targetFullPath = cmSystemTools::ConvertToOutputPath(targetFullPath.c_str());
+ targetFullPathSO = cmSystemTools::ConvertToOutputPath(targetFullPathSO.c_str());
+ targetFullPathReal = cmSystemTools::ConvertToOutputPath(targetFullPathReal.c_str());
+ targetFullPathBase = cmSystemTools::ConvertToOutputPath(targetFullPathBase.c_str());
+
// get the objects that are used to link this library
std::string objs = "$(" + this->CreateMakeVariable(name, "_SRC_OBJS") + ") ";
std::string objsQuoted = "$(" + this->CreateMakeVariable(name, "_SRC_OBJS_QUOTED") + ") ";
// create a variable with the objects that this library depends on
- std::string depend = objs + " $("
- + this->CreateMakeVariable(name, "_DEPEND_LIBS") + ")";
- // collect up the build rules
- std::vector<std::string> rules;
- std::string command = "$(RM) " + targetFullPath;
- rules.push_back(command);
- rules.push_back(m_Makefile->GetDefinition(createVariable));
- // expand multi-command semi-colon separated lists
- // of commands into separate commands
+ std::string depend =
+ objs + " $(" + this->CreateMakeVariable(name, "_DEPEND_LIBS") + ")";
+
std::vector<std::string> commands;
+ std::string cmakecommand = this->ConvertToOutputForExisting(
+ m_Makefile->GetDefinition("CMAKE_COMMAND"));
+
+ // Remove any existing files for this library.
+ std::string remove = cmakecommand;
+ remove += " -E remove -f ";
+ remove += targetFullPathReal;
+ if(targetFullPathSO != targetFullPathReal)
+ {
+ remove += " ";
+ remove += targetFullPathSO;
+ }
+ if(targetFullPath != targetFullPathSO &&
+ targetFullPath != targetFullPathReal)
+ {
+ remove += " ";
+ remove += targetFullPath;
+ }
+ commands.push_back(remove);
+
// collect custom commands for this target and add them to the list
std::string customCommands = this->CreatePreBuildRules(t, name);
if(customCommands.size() > 0)
@@ -1019,13 +1110,34 @@ void cmLocalUnixMakefileGenerator::OutputLibraryRule(std::ostream& fout,
{
commands.push_back(customCommands);
}
+
+ // collect up the build rules
+ std::vector<std::string> rules;
+ rules.push_back(m_Makefile->GetDefinition(createVariable));
+ // expand multi-command semi-colon separated lists
+ // of commands into separate commands
cmSystemTools::ExpandList(rules, commands);
+
+ // Create necessary symlinks for library.
+ if(targetFullPath != targetFullPathReal)
+ {
+ std::string symlink = cmakecommand;
+ symlink += " -E cmake_symlink_library ";
+ symlink += targetFullPathReal;
+ symlink += " ";
+ symlink += targetFullPathSO;
+ symlink += " ";
+ symlink += targetFullPath;
+ commands.push_back(symlink);
+ }
+
// collect custom commands for this target and add them to the list
customCommands = this->CreatePostBuildRules(t, name);
if(customCommands.size() > 0)
{
commands.push_back(customCommands);
}
+
// collect up the link libraries
cmOStringStream linklibs;
this->OutputLinkLibraries(linklibs, name, t);
@@ -1034,10 +1146,11 @@ void cmLocalUnixMakefileGenerator::OutputLibraryRule(std::ostream& fout,
{
this->ExpandRuleVariables(*i,
objs.c_str(),
- targetFullPath.c_str(),
+ targetFullPathReal.c_str(),
linklibs.str().c_str(),
0, 0, 0, objsQuoted.c_str(),
- targetBaseFullPath.c_str(),
+ targetFullPathBase.c_str(),
+ targetNameSO.c_str(),
linkFlags);
}
this->OutputMakeRule(fout, comment,
@@ -1084,17 +1197,7 @@ void cmLocalUnixMakefileGenerator::OutputSharedLibraryRule(std::ostream& fout,
}
}
}
-
- const char* targetPrefix = t.GetProperty("PREFIX");
- if(!targetPrefix)
- {
- targetPrefix = this->GetSafeDefinition("CMAKE_SHARED_LIBRARY_PREFIX");
- }
- const char* targetSuffix = t.GetProperty("SUFFIX");
- if(!targetSuffix)
- {
- targetSuffix = this->GetSafeDefinition("CMAKE_SHARED_LIBRARY_SUFFIX");
- }
+
const char* targetLinkFlags = t.GetProperty("LINK_FLAGS");
if(targetLinkFlags)
{
@@ -1102,8 +1205,6 @@ void cmLocalUnixMakefileGenerator::OutputSharedLibraryRule(std::ostream& fout,
linkFlags += " ";
}
this->OutputLibraryRule(fout, name, t,
- targetPrefix,
- targetSuffix,
createRule,
"shared library",
linkFlags.c_str());
@@ -1133,16 +1234,6 @@ void cmLocalUnixMakefileGenerator::OutputModuleLibraryRule(std::ostream& fout,
linkFlags += this->GetSafeDefinition(build.c_str());
linkFlags += " ";
}
- const char* targetPrefix = t.GetProperty("PREFIX");
- if(!targetPrefix)
- {
- targetPrefix = this->GetSafeDefinition("CMAKE_SHARED_MODULE_PREFIX");
- }
- const char* targetSuffix = t.GetProperty("SUFFIX");
- if(!targetSuffix)
- {
- targetSuffix = this->GetSafeDefinition("CMAKE_SHARED_MODULE_SUFFIX");
- }
const char* targetLinkFlags = t.GetProperty("LINK_FLAGS");
if(targetLinkFlags)
{
@@ -1150,8 +1241,6 @@ void cmLocalUnixMakefileGenerator::OutputModuleLibraryRule(std::ostream& fout,
linkFlags += " ";
}
this->OutputLibraryRule(fout, name, t,
- targetPrefix,
- targetSuffix,
createRule,
"shared module",
linkFlags.c_str());
@@ -1171,16 +1260,6 @@ void cmLocalUnixMakefileGenerator::OutputStaticLibraryRule(std::ostream& fout,
{
createRule = "CMAKE_C_CREATE_STATIC_LIBRARY";
}
- const char* targetPrefix = t.GetProperty("PREFIX");
- if(!targetPrefix)
- {
- targetPrefix = this->GetSafeDefinition("CMAKE_STATIC_LIBRARY_PREFIX");
- }
- const char* targetSuffix = t.GetProperty("SUFFIX");
- if(!targetSuffix)
- {
- targetSuffix = this->GetSafeDefinition("CMAKE_STATIC_LIBRARY_SUFFIX");
- }
std::string linkFlags;
const char* targetLinkFlags = t.GetProperty("LINK_FLAGS");
if(targetLinkFlags)
@@ -1189,8 +1268,6 @@ void cmLocalUnixMakefileGenerator::OutputStaticLibraryRule(std::ostream& fout,
linkFlags += " ";
}
this->OutputLibraryRule(fout, name, t,
- targetPrefix,
- targetSuffix,
createRule,
"static library",
linkFlags.c_str());
@@ -1307,6 +1384,7 @@ void cmLocalUnixMakefileGenerator::OutputExecutableRule(std::ostream& fout,
flags.c_str(),
0,
0,
+ 0,
linkFlags.c_str());
}
this->OutputMakeRule(fout,
@@ -2226,6 +2304,9 @@ void cmLocalUnixMakefileGenerator::OutputInstallRules(std::ostream& fout)
{
return;
}
+ std::string cmakecommand = this->ConvertToOutputForExisting(
+ m_Makefile->GetDefinition("CMAKE_COMMAND"));
+
const char* root
= m_Makefile->GetDefinition("CMAKE_ROOT");
fout << "INSTALL = \"" << root << "/Templates/install-sh\" -c\n";
@@ -2266,11 +2347,31 @@ void cmLocalUnixMakefileGenerator::OutputInstallRules(std::ostream& fout)
case cmTarget::STATIC_LIBRARY:
case cmTarget::SHARED_LIBRARY:
case cmTarget::MODULE_LIBRARY:
+ {
+ std::string targetName;
+ std::string targetNameSO;
+ std::string targetNameReal;
+ std::string targetNameBase;
+ this->GetLibraryNames(l->first.c_str(), l->second,
+ targetName, targetNameSO,
+ targetNameReal, targetNameBase);
+ std::string installName = "$(DESTDIR)";
+ installName += prefix;
+ installName += l->second.GetInstallPath();
+ installName += "/";
+ std::string installNameSO = installName;
+ std::string installNameReal = installName;
+ installName += targetName;
+ installNameSO += targetNameSO;
+ installNameReal += targetNameReal;
fname = m_LibraryOutputPath;
- fname += this->GetFullTargetName(l->first.c_str(), l->second);
+ fname += targetNameReal;
fout << "\t$(INSTALL_DATA) " << cmSystemTools::ConvertToOutputPath(fname.c_str())
<< " \"$(DESTDIR)" << prefix << l->second.GetInstallPath() << "\"\n";
- break;
+ fout << "\t" << cmakecommand << " -E cmake_symlink_library \""
+ << installNameReal << "\" \"" << installNameSO << "\" \"" << installName
+ << "\"\n";
+ }; break;
case cmTarget::WIN32_EXECUTABLE:
case cmTarget::EXECUTABLE:
fname = m_ExecutableOutputPath;
@@ -2369,7 +2470,7 @@ void cmLocalUnixMakefileGenerator::OutputMakeRules(std::ostream& fout)
"clean",
"$(SUBDIR_CLEAN)",
"-@ $(RM) $(CLEAN_OBJECT_FILES) "
- " $(TARGETS) $(GENERATED_QT_FILES) $(GENERATED_FLTK_FILES)");
+ " $(TARGETS) $(TARGET_EXTRAS) $(GENERATED_QT_FILES) $(GENERATED_FLTK_FILES)");
// collect up all the sources
std::vector<std::string> allsources;
@@ -3000,3 +3101,57 @@ cmLocalUnixMakefileGenerator::CreateMakeVariable(const char* sin, const char* s2
return ret;
}
+
+void cmLocalUnixMakefileGenerator::GetLibraryNames(const char* n,
+ const cmTarget& t,
+ std::string& name,
+ std::string& soName,
+ std::string& realName,
+ std::string& baseName)
+{
+ // Check for library version properties.
+ const char* version = t.GetProperty("VERSION");
+ const char* soversion = t.GetProperty("SOVERSION");
+ if((t.GetType() != cmTarget::SHARED_LIBRARY &&
+ t.GetType() != cmTarget::MODULE_LIBRARY) ||
+ !m_Makefile->GetDefinition("CMAKE_SHARED_LIBRARY_SONAME_FLAG"))
+ {
+ // Versioning is supported only for shared libraries and modules,
+ // and then only when the platform supports an soname flag.
+ version = 0;
+ soversion = 0;
+ }
+ if(version && !soversion)
+ {
+ // The soversion must be set if the library version is set. Use
+ // the library version as the soversion.
+ soversion = version;
+ }
+
+ // The library name.
+ name = this->GetFullTargetName(n, t);
+
+ // The library's soname.
+ soName = name;
+ if(soversion)
+ {
+ soName += ".";
+ soName += soversion;
+ }
+
+ // The library's real name on disk.
+ realName = name;
+ if(version)
+ {
+ realName += ".";
+ realName += version;
+ }
+ else if(soversion)
+ {
+ realName += ".";
+ realName += soversion;
+ }
+
+ // The library name without extension.
+ baseName = this->GetBaseTargetName(n, t);
+}
diff --git a/Source/cmLocalUnixMakefileGenerator.h b/Source/cmLocalUnixMakefileGenerator.h
index 2bbb9d3..e6ca2cf 100644
--- a/Source/cmLocalUnixMakefileGenerator.h
+++ b/Source/cmLocalUnixMakefileGenerator.h
@@ -99,8 +99,6 @@ protected:
void OutputLibraryRule(std::ostream& fout,
const char* name,
const cmTarget &t,
- const char* prefix,
- const char* suffix,
const char* createRule,
const char* comment,
const char* linkFlags
@@ -114,6 +112,7 @@ protected:
const char* flags = 0,
const char* objectsquoted = 0,
const char* targetBase = 0,
+ const char* targetSOName = 0,
const char* linkFlags = 0);
virtual void OutputSharedLibraryRule(std::ostream&, const char* name,
const cmTarget &);
@@ -220,6 +219,16 @@ protected:
/** Get the full name of the target's file, without path. */
std::string GetFullTargetName(const char* n, const cmTarget& t);
+ /** Get the base name of the target's file, without path or extension. */
+ std::string GetBaseTargetName(const char* n, const cmTarget& t);
+
+ /** Get the names associated with a library target. */
+ void GetLibraryNames(const char* n, const cmTarget& t,
+ std::string& name,
+ std::string& soName,
+ std::string& realName,
+ std::string& baseName);
+
/** Output an echo command to the Makefile */
void OutputEcho(std::ostream& fout, const char *msg);