[cmake-commits] king committed cmInstallCommand.cxx 1.42 1.43
cmInstallCommand.h 1.28 1.29 cmInstallCommandArguments.cxx 1.3
1.4 cmInstallCommandArguments.h 1.4 1.5
cmInstallTargetGenerator.cxx 1.56 1.57
cmInstallTargetGenerator.h 1.22 1.23
cmake-commits at cmake.org
cmake-commits at cmake.org
Mon Feb 4 17:03:50 EST 2008
Update of /cvsroot/CMake/CMake/Source
In directory public:/mounts/ram/cvs-serv6172/Source
Modified Files:
cmInstallCommand.cxx cmInstallCommand.h
cmInstallCommandArguments.cxx cmInstallCommandArguments.h
cmInstallTargetGenerator.cxx cmInstallTargetGenerator.h
Log Message:
ENH: Allow separate installation of shared libs and their links.
- Add NAMELINK_ONLY and NAMELINK_SKIP to INSTALL command
- Options select a \"namelink\" mode
- cmInstallTargetGenerator selects files/link based on mode
- See bug #4419
Index: cmInstallTargetGenerator.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallTargetGenerator.h,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- cmInstallTargetGenerator.h 29 Jan 2008 20:07:33 -0000 1.22
+++ cmInstallTargetGenerator.h 4 Feb 2008 22:03:48 -0000 1.23
@@ -36,6 +36,16 @@
);
virtual ~cmInstallTargetGenerator();
+ /** Select the policy for installing shared library linkable name
+ symlinks. */
+ enum NamelinkModeType
+ {
+ NamelinkModeNone,
+ NamelinkModeOnly,
+ NamelinkModeSkip
+ };
+ void SetNamelinkMode(NamelinkModeType mode) { this->NamelinkMode = mode; }
+
std::string GetInstallFilename(const char* config) const;
static std::string GetInstallFilename(cmTarget*target, const char* config,
bool implib, bool useSOName);
@@ -72,6 +82,7 @@
bool ImportLibrary;
std::string FilePermissions;
bool Optional;
+ NamelinkModeType NamelinkMode;
};
#endif
Index: cmInstallCommandArguments.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallCommandArguments.cxx,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- cmInstallCommandArguments.cxx 28 Jan 2008 13:38:35 -0000 1.3
+++ cmInstallCommandArguments.cxx 4 Feb 2008 22:03:48 -0000 1.4
@@ -37,6 +37,8 @@
,Permissions (&Parser, "PERMISSIONS" , &ArgumentGroup)
,Configurations(&Parser, "CONFIGURATIONS", &ArgumentGroup)
,Optional (&Parser, "OPTIONAL" , &ArgumentGroup)
+,NamelinkOnly (&Parser, "NAMELINK_ONLY" , &ArgumentGroup)
+,NamelinkSkip (&Parser, "NAMELINK_SKIP" , &ArgumentGroup)
,GenericArguments(0)
{
this->Component.SetDefaultString("Unspecified");
@@ -107,6 +109,32 @@
return false;
}
+bool cmInstallCommandArguments::GetNamelinkOnly() const
+{
+ if (this->NamelinkOnly.IsEnabled())
+ {
+ return true;
+ }
+ if (this->GenericArguments!=0)
+ {
+ return this->GenericArguments->GetNamelinkOnly();
+ }
+ return false;
+}
+
+bool cmInstallCommandArguments::GetNamelinkSkip() const
+{
+ if (this->NamelinkSkip.IsEnabled())
+ {
+ return true;
+ }
+ if (this->GenericArguments!=0)
+ {
+ return this->GenericArguments->GetNamelinkSkip();
+ }
+ return false;
+}
+
const std::vector<std::string>&
cmInstallCommandArguments::GetConfigurations() const
{
Index: cmInstallCommand.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallCommand.cxx,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -d -r1.42 -r1.43
--- cmInstallCommand.cxx 28 Jan 2008 19:46:16 -0000 1.42
+++ cmInstallCommand.cxx 4 Feb 2008 22:03:48 -0000 1.43
@@ -283,6 +283,57 @@
return false;
}
+ // Enforce argument rules too complex to specify for the
+ // general-purpose parser.
+ if(archiveArgs.GetNamelinkOnly() ||
+ runtimeArgs.GetNamelinkOnly() ||
+ frameworkArgs.GetNamelinkOnly() ||
+ bundleArgs.GetNamelinkOnly() ||
+ privateHeaderArgs.GetNamelinkOnly() ||
+ publicHeaderArgs.GetNamelinkOnly() ||
+ resourceArgs.GetNamelinkOnly())
+ {
+ this->SetError(
+ "TARGETS given NAMELINK_ONLY option not in LIBRARY group. "
+ "The NAMELINK_ONLY option may be specified only following LIBRARY."
+ );
+ return false;
+ }
+ if(archiveArgs.GetNamelinkSkip() ||
+ runtimeArgs.GetNamelinkSkip() ||
+ frameworkArgs.GetNamelinkSkip() ||
+ bundleArgs.GetNamelinkSkip() ||
+ privateHeaderArgs.GetNamelinkSkip() ||
+ publicHeaderArgs.GetNamelinkSkip() ||
+ resourceArgs.GetNamelinkSkip())
+ {
+ this->SetError(
+ "TARGETS given NAMELINK_SKIP option not in LIBRARY group. "
+ "The NAMELINK_SKIP option may be specified only following LIBRARY."
+ );
+ return false;
+ }
+ if(libraryArgs.GetNamelinkOnly() && libraryArgs.GetNamelinkSkip())
+ {
+ this->SetError(
+ "TARGETS given NAMELINK_ONLY and NAMELINK_SKIP. "
+ "At most one of these two options may be specified."
+ );
+ return false;
+ }
+
+ // Select the mode for installing symlinks to versioned shared libraries.
+ cmInstallTargetGenerator::NamelinkModeType
+ namelinkMode = cmInstallTargetGenerator::NamelinkModeNone;
+ if(libraryArgs.GetNamelinkOnly())
+ {
+ namelinkMode = cmInstallTargetGenerator::NamelinkModeOnly;
+ }
+ else if(libraryArgs.GetNamelinkSkip())
+ {
+ namelinkMode = cmInstallTargetGenerator::NamelinkModeSkip;
+ }
+
// Check if there is something to do.
if(targetList.GetVector().empty())
{
@@ -352,6 +403,12 @@
// cygwin. Currently no other platform is a DLL platform.
if(dll_platform)
{
+ // When in namelink only mode skip all libraries on Windows.
+ if(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly)
+ {
+ continue;
+ }
+
// This is a DLL platform.
if(!archiveArgs.GetDestination().empty())
{
@@ -378,6 +435,12 @@
// INSTALL properties. Otherwise, use the LIBRARY properties.
if(target.IsFrameworkOnApple())
{
+ // When in namelink only mode skip frameworks.
+ if(namelinkMode == cmInstallTargetGenerator::NamelinkModeOnly)
+ {
+ continue;
+ }
+
// Use the FRAMEWORK properties.
if (!frameworkArgs.GetDestination().empty())
{
@@ -400,6 +463,7 @@
{
libraryGenerator = CreateInstallTargetGenerator(target,
libraryArgs, false);
+ libraryGenerator->SetNamelinkMode(namelinkMode);
}
else
{
@@ -438,6 +502,7 @@
{
libraryGenerator = CreateInstallTargetGenerator(target, libraryArgs,
false);
+ libraryGenerator->SetNamelinkMode(namelinkMode);
}
else
{
Index: cmInstallCommand.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallCommand.h,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- cmInstallCommand.h 28 Jan 2008 20:12:12 -0000 1.28
+++ cmInstallCommand.h 4 Feb 2008 22:03:48 -0000 1.29
@@ -105,7 +105,7 @@
" [PERMISSIONS permissions...]\n"
" [CONFIGURATIONS [Debug|Release|...]]\n"
" [COMPONENT <component>]\n"
- " [OPTIONAL]\n"
+ " [OPTIONAL] [NAMELINK_ONLY|NAMELINK_SKIP]\n"
" ] [...])\n"
"The TARGETS form specifies rules for installing targets from a "
"project. There are five kinds of target files that may be "
@@ -140,6 +140,25 @@
"See documentation of the PRIVATE_HEADER, PUBLIC_HEADER, and RESOURCE "
"target properties for details."
"\n"
+ "Either NAMELINK_ONLY or NAMELINK_SKIP may be specified as a LIBRARY "
+ "option. "
+ "On some platforms a versioned shared library has a symbolic link "
+ "such as\n"
+ " lib<name>.so -> lib<name>.so.1\n"
+ "where \"lib<name>.so.1\" is the soname of the library and "
+ "\"lib<name>.so\" is a \"namelink\" allowing linkers to find the "
+ "library when given \"-l<name>\". "
+ "The NAMELINK_ONLY option causes installation of only the namelink "
+ "when a library target is installed. "
+ "The NAMELINK_SKIP option causes installation of library files other "
+ "than the namelink when a library target is installed. "
+ "When neither option is given both portions are installed. "
+ "On platforms where versioned shared libraries do not have namelinks "
+ "or when a library is not versioned the NAMELINK_SKIP option installs "
+ "the library and the NAMELINK_ONLY option installs nothing. "
+ "See the VERSION and SOVERSION target properties for details on "
+ "creating versioned shared libraries."
+ "\n"
"One or more groups of properties may be specified in a single call "
"to the TARGETS form of this command. A target may be installed more "
"than once to different locations. Consider hypothetical "
Index: cmInstallCommandArguments.h
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallCommandArguments.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- cmInstallCommandArguments.h 28 Jan 2008 13:38:35 -0000 1.4
+++ cmInstallCommandArguments.h 4 Feb 2008 22:03:48 -0000 1.5
@@ -39,6 +39,8 @@
const std::string& GetPermissions() const;
const std::vector<std::string>& GetConfigurations() const;
bool GetOptional() const;
+ bool GetNamelinkOnly() const;
+ bool GetNamelinkSkip() const;
// once HandleDirectoryMode() is also switched to using
// cmInstallCommandArguments then these two functions can become non-static
@@ -54,6 +56,8 @@
cmCAStringVector Permissions;
cmCAStringVector Configurations;
cmCAEnabler Optional;
+ cmCAEnabler NamelinkOnly;
+ cmCAEnabler NamelinkSkip;
std::string DestinationString;
std::string PermissionsString;
Index: cmInstallTargetGenerator.cxx
===================================================================
RCS file: /cvsroot/CMake/CMake/Source/cmInstallTargetGenerator.cxx,v
retrieving revision 1.56
retrieving revision 1.57
diff -u -d -r1.56 -r1.57
--- cmInstallTargetGenerator.cxx 1 Feb 2008 18:08:12 -0000 1.56
+++ cmInstallTargetGenerator.cxx 4 Feb 2008 22:03:48 -0000 1.57
@@ -22,9 +22,6 @@
#include "cmMakefile.h"
#include "cmake.h"
-// TODO:
-// - Skip IF(EXISTS) checks if nothing is done with the installed file
-
//----------------------------------------------------------------------------
cmInstallTargetGenerator
::cmInstallTargetGenerator(cmTarget& t, const char* dest, bool implib,
@@ -34,6 +31,7 @@
cmInstallGenerator(dest, configurations, component), Target(&t),
ImportLibrary(implib), FilePermissions(file_permissions), Optional(optional)
{
+ this->NamelinkMode = NamelinkModeNone;
this->Target->SetHaveInstallRule(true);
}
@@ -149,12 +147,19 @@
toInstallPath += this->GetInstallFilename(this->Target, config,
this->ImportLibrary, false);
+ // Track whether post-install operations should be added to the
+ // script.
+ bool tweakInstalledFile = true;
+
// Compute the list of files to install for this target.
std::vector<std::string> files;
std::string literal_args;
cmTarget::TargetType type = this->Target->GetType();
if(type == cmTarget::EXECUTABLE)
{
+ // There is a bug in cmInstallCommand if this fails.
+ assert(this->NamelinkMode == NamelinkModeNone);
+
std::string targetName;
std::string targetNameReal;
std::string targetNameImport;
@@ -215,6 +220,9 @@
config);
if(this->ImportLibrary)
{
+ // There is a bug in cmInstallCommand if this fails.
+ assert(this->NamelinkMode == NamelinkModeNone);
+
std::string from1 = fromDirConfig;
from1 += targetNameImport;
files.push_back(from1);
@@ -224,6 +232,9 @@
}
else if(this->Target->IsFrameworkOnApple())
{
+ // There is a bug in cmInstallCommand if this fails.
+ assert(this->NamelinkMode == NamelinkModeNone);
+
// Compute the build tree location of the framework directory
std::string from1 = fromDirConfig;
// Remove trailing slashes... so that from1 ends with ".framework":
@@ -243,25 +254,82 @@
}
else
{
- std::string from1 = fromDirConfig;
- from1 += targetName;
- files.push_back(from1);
+ // Operations done at install time on the installed file should
+ // be done on the real file and not any of the symlinks.
+ toInstallPath = this->GetInstallDestination();
+ toInstallPath += "/";
+ toInstallPath += targetNameReal;
+
+ // Construct the list of file names to install for this library.
+ bool haveNamelink = false;
+ std::string fromName;
+ std::string fromSOName;
+ std::string fromRealName;
+ fromName = fromDirConfig;
+ fromName += targetName;
if(targetNameSO != targetName)
{
- std::string from2 = fromDirConfig;
- from2 += targetNameSO;
- files.push_back(from2);
+ haveNamelink = true;
+ fromSOName = fromDirConfig;
+ fromSOName += targetNameSO;
}
if(targetNameReal != targetName &&
targetNameReal != targetNameSO)
{
- std::string from3 = fromDirConfig;
- from3 += targetNameReal;
- files.push_back(from3);
+ haveNamelink = true;
+ fromRealName = fromDirConfig;
+ fromRealName += targetNameReal;
+ }
+
+ // Add the names based on the current namelink mode.
+ if(haveNamelink)
+ {
+ // With a namelink we need to check the mode.
+ if(this->NamelinkMode == NamelinkModeOnly)
+ {
+ // Install the namelink only.
+ files.push_back(fromName);
+ tweakInstalledFile = false;
+ }
+ else
+ {
+ // Install the real file if it has its own name.
+ if(!fromRealName.empty())
+ {
+ files.push_back(fromRealName);
+ }
+
+ // Install the soname link if it has its own name.
+ if(!fromSOName.empty())
+ {
+ files.push_back(fromSOName);
+ }
+
+ // Install the namelink if it is not to be skipped.
+ if(this->NamelinkMode != NamelinkModeSkip)
+ {
+ files.push_back(fromName);
+ }
+ }
+ }
+ else
+ {
+ // Without a namelink there will be only one file. Install it
+ // if this is not a namelink-only rule.
+ if(this->NamelinkMode != NamelinkModeOnly)
+ {
+ files.push_back(fromName);
+ }
}
}
}
+ // Skip this rule if no files are to be installed for the target.
+ if(files.empty())
+ {
+ return;
+ }
+
// Write code to install the target file.
const char* no_dir_permissions = 0;
const char* no_rename = 0;
@@ -273,19 +341,26 @@
no_rename, literal_args.c_str(),
indent);
+ // Construct the path of the file on disk after installation on
+ // which tweaks may be performed.
std::string toDestDirPath = "$ENV{DESTDIR}";
- if(toInstallPath[0] != '/')
+ if(toInstallPath[0] != '/' && toInstallPath[0] != '$')
{
toDestDirPath += "/";
}
toDestDirPath += toInstallPath;
- os << indent << "IF(EXISTS \"" << toDestDirPath << "\")\n";
- this->AddInstallNamePatchRule(os, indent.Next(), config, toDestDirPath);
- this->AddChrpathPatchRule(os, indent.Next(), config, toDestDirPath);
- this->AddRanlibRule(os, indent.Next(), type, toDestDirPath);
- this->AddStripRule(os, indent.Next(), type, toDestDirPath);
- os << indent << "ENDIF(EXISTS \"" << toDestDirPath << "\")\n";
+ // TODO:
+ // - Skip IF(EXISTS) checks if nothing is done with the installed file
+ if(tweakInstalledFile)
+ {
+ os << indent << "IF(EXISTS \"" << toDestDirPath << "\")\n";
+ this->AddInstallNamePatchRule(os, indent.Next(), config, toDestDirPath);
+ this->AddChrpathPatchRule(os, indent.Next(), config, toDestDirPath);
+ this->AddRanlibRule(os, indent.Next(), type, toDestDirPath);
+ this->AddStripRule(os, indent.Next(), type, toDestDirPath);
+ os << indent << "ENDIF(EXISTS \"" << toDestDirPath << "\")\n";
+ }
}
//----------------------------------------------------------------------------
More information about the Cmake-commits
mailing list