[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