ソースを参照

BUG: Implement installing of shared library versioning and add test for the whole thing

Andy Cedilnik 21 年 前
コミット
f9b43b9212

+ 78 - 5
Source/cmFileCommand.cxx

@@ -249,8 +249,6 @@ bool cmFileCommand::HandleInstallCommand(
   std::string destination = "";
   std::string stype = "FILES";
   const char* build_type = m_Makefile->GetDefinition("BUILD_TYPE");
-  const char* debug_postfix 
-    = m_Makefile->GetDefinition("CMAKE_DEBUG_POSTFIX");
   const char* destdir = cmSystemTools::GetEnv("DESTDIR");
 
   std::string extra_dir = "";
@@ -271,7 +269,10 @@ bool cmFileCommand::HandleInstallCommand(
   std::vector<std::string>::size_type i = 0;
   i++; // Get rid of subcommand
 
+  std::map<cmStdString, const char*> properties;
+
   bool in_files = false;
+  bool in_properties = false;
   bool optional = false;
   for ( ; i != args.size(); ++i )
     {
@@ -281,6 +282,7 @@ bool cmFileCommand::HandleInstallCommand(
       i++;
       destination = args[i];
       in_files = false;
+      in_properties = false;
       }
     else if ( *cstr == "TYPE" && i < args.size()-1 )
       {
@@ -291,11 +293,23 @@ bool cmFileCommand::HandleInstallCommand(
         i++;
         optional = true;
         }
+      in_properties = false;
+      in_files = false;
+      }
+    else if ( *cstr == "PROPERTIES"  )
+      {
+      in_properties = true;
       in_files = false;
       }
     else if ( *cstr == "FILES" && !in_files)
       {
       in_files = true;
+      in_properties = false;
+      }
+    else if ( in_properties && i < args.size()-1 )
+      {
+      properties[args[i]] = args[i+1].c_str();
+      i++;
       }
     else if ( in_files )
       {
@@ -437,9 +451,65 @@ bool cmFileCommand::HandleInstallCommand(
     case cmTarget::MODULE_LIBRARY:
     case cmTarget::STATIC_LIBRARY:
     case cmTarget::SHARED_LIBRARY:
-      if ( debug )
         {
-        fname = fnamewe + debug_postfix + ext;
+        // Handle shared library versioning
+        const char* lib_version = 0;
+        const char* lib_soversion = 0;
+        if ( properties.find("VERSION") != properties.end() )
+          {
+          lib_version = properties["VERSION"];
+          }
+        if ( properties.find("SOVERSION") != properties.end() )
+          {
+          lib_soversion = properties["SOVERSION"];
+          }
+        if ( !lib_version && lib_soversion )
+          {
+          lib_version = lib_soversion;
+          }
+        if ( !lib_soversion && lib_version )
+          {
+          lib_soversion = lib_version;
+          }
+        if ( lib_version && lib_soversion )
+          {
+          std::string libname = destfile;
+          std::string soname = destfile;
+          std::string soname_nopath = fname;
+          soname += ".";
+          soname += lib_soversion;
+          soname_nopath += ".";
+          soname_nopath += lib_soversion;
+
+          fname += ".";
+          fname += lib_version;
+          destfile += ".";
+          destfile += lib_version;
+
+          cmSystemTools::RemoveFile(soname.c_str());
+          cmSystemTools::RemoveFile(libname.c_str());
+
+          if (!cmSystemTools::CreateSymlink(soname_nopath.c_str(), libname.c_str()) )
+            {
+            std::string errstring = "error when creating symlink from: " + libname + " to " + soname_nopath;
+            this->SetError(errstring.c_str());
+            return false;
+            }
+          if ( destfile != soname )
+            {
+            if ( !cmSystemTools::CreateSymlink(fname.c_str(), soname.c_str()) )
+              {
+              std::string errstring = "error when creating symlink from: " + soname + " to " + fname;
+              this->SetError(errstring.c_str());
+              return false;
+              }
+            }
+          }
+        cmOStringStream str;
+        str << cmSystemTools::GetFilenamePath(ctarget) 
+          << "/" << extra_dir << "/" 
+          << fname;
+        ctarget = str.str();
         }
     case cmTarget::EXECUTABLE:
       if ( extra_dir.size() > 0 )
@@ -455,6 +525,7 @@ bool cmFileCommand::HandleInstallCommand(
 
     if ( cmSystemTools::FileExists(ctarget.c_str()) )
       {
+      cmSystemTools::RemoveFile(destfile.c_str());
       if ( !cmSystemTools::CopyFileAlways(ctarget.c_str(), 
           destination.c_str()) )
         {
@@ -482,7 +553,9 @@ bool cmFileCommand::HandleInstallCommand(
 #endif
         ) )
           {
-          perror("problem doing chmod.");
+          cmOStringStream err;
+          err << "Program setting permissions on file: " << destfile.c_str();
+          perror(err.str().c_str());
           }
         }
       smanifest_files += ";" + destfile;

+ 28 - 3
Source/cmLocalGenerator.cxx

@@ -189,7 +189,27 @@ void cmLocalGenerator::GenerateInstallRules()
         else
           {
           files = fname.c_str();
-          this->AddInstallRule(fout, dest, type, files);
+          std::string properties;
+          const char* lib_version = l->second.GetProperty("VERSION");
+          const char* lib_soversion = l->second.GetProperty("SOVERSION");
+          if(!m_Makefile->GetDefinition("CMAKE_SHARED_LIBRARY_SONAME_C_FLAG"))
+            {
+            // Versioning is supported only for shared libraries and modules,
+            // and then only when the platform supports an soname flag.
+            lib_version = 0;
+            lib_soversion = 0;
+            }
+          if ( lib_version )
+            {
+            properties += " VERSION ";
+            properties += lib_version;
+            }
+          if ( lib_soversion )
+            {
+            properties += " SOVERSION ";
+            properties += lib_soversion;
+            }
+          this->AddInstallRule(fout, dest, type, files, false, properties.c_str());
           }
         }
         break;
@@ -283,7 +303,7 @@ void cmLocalGenerator::GenerateInstallRules()
 }
 
 void cmLocalGenerator::AddInstallRule(std::ostream& fout, const char* dest, 
-  int type, const char* files, bool optional)
+  int type, const char* files, bool optional /* = false */, const char* properties /* = 0 */)
 {
   std::string sfiles = files;
   std::string destination = dest;
@@ -303,7 +323,12 @@ void cmLocalGenerator::AddInstallRule(std::ostream& fout, const char* dest,
     << "MESSAGE(STATUS \"Installing " << destination.c_str() 
     << "/" << fname.c_str() << "\")\n" 
     << "FILE(INSTALL DESTINATION \"" << destination.c_str() 
-    << "\" TYPE " << stype.c_str() << (optional?" OPTIONAL":"") 
+    << "\" TYPE " << stype.c_str() << (optional?" OPTIONAL":"") ;
+  if ( properties && *properties )
+    {
+    fout << " PROPERTIES" << properties;
+    }
+  fout
     << " FILES \"" << sfiles.c_str() << "\")\n";
 }
 

+ 2 - 1
Source/cmLocalGenerator.h

@@ -90,9 +90,10 @@ public:
   ///! set/get the parent generator 
   cmLocalGenerator* GetParent(){return m_Parent;}
   void SetParent(cmLocalGenerator* g) { m_Parent = g;}
+
 protected:
   virtual void AddInstallRule(std::ostream& fout, const char* dest, int type, 
-    const char* files, bool optional = false);
+    const char* files, bool optional = false, const char* properties = 0);
   
   bool m_FromTheTop;
   cmMakefile *m_Makefile;

+ 13 - 4
Tests/SimpleInstall/CMakeLists.txt

@@ -30,6 +30,7 @@ IF(STAGE2)
   SET(LIBPATHS "${CMAKE_INSTALL_PREFIX}/lib")
   SET(t1NAMES test1 test1${CMAKE_DEBUG_POSTFIX})
   SET(t2NAMES test2 test2${CMAKE_DEBUG_POSTFIX})
+  SET(t4NAMES test4 test4${CMAKE_DEBUG_POSTFIX})
 
   IF(CYGWIN OR MINGW)
     SET(LIBPATHS ${LIBPATHS} "${CMAKE_INSTALL_PREFIX}/bin")
@@ -42,10 +43,14 @@ IF(STAGE2)
   FIND_LIBRARY(TEST2_LIBRARY 
     NAMES ${t2NAMES}
     PATHS ${LIBPATHS}
-    DOC "First library")
+    DOC "Second library")
+  FIND_LIBRARY(TEST4_LIBRARY 
+    NAMES ${t4NAMES}
+    PATHS ${LIBPATHS}
+    DOC "Fourth library")
 
   ADD_EXECUTABLE (SimpleInstallS2 inst.cxx foo.c foo.h)
-  TARGET_LINK_LIBRARIES(SimpleInstallS2 ${TEST1_LIBRARY} ${TEST2_LIBRARY})
+  TARGET_LINK_LIBRARIES(SimpleInstallS2 ${TEST1_LIBRARY} ${TEST2_LIBRARY} ${TEST4_LIBRARY})
   SET(install_target SimpleInstallS2)
 
   INSTALL_TARGETS(/bin SimpleInstallS2)
@@ -58,22 +63,26 @@ ELSE(STAGE2)
   ADD_LIBRARY(test1 STATIC lib1.cxx)
   ADD_LIBRARY(test2 SHARED lib2.cxx)
   ADD_LIBRARY(test3 MODULE lib3.cxx)
+  ADD_LIBRARY(test4 SHARED lib4.cxx)
 
   ADD_EXECUTABLE (SimpleInstall inst.cxx foo.c foo.h)
-  TARGET_LINK_LIBRARIES(SimpleInstall test1 test2)
+  TARGET_LINK_LIBRARIES(SimpleInstall test1 test2 test4)
   SET(install_target SimpleInstall)
 
   ADD_DEPENDENCIES(SimpleInstall test3)
   ADD_DEPENDENCIES(test2 test3)
+  ADD_DEPENDENCIES(test4 test3)
 
   INSTALL_TARGETS(/bin SimpleInstall)
-  INSTALL_TARGETS(/lib test1 test2 test3)
+  INSTALL_TARGETS(/lib test1 test2 test3 test4)
   INSTALL_TARGETS(/include lib1.h lib2.h lib3.h)
 
   SET_TARGET_PROPERTIES(SimpleInstall PROPERTIES PRE_INSTALL_SCRIPT 
     ${CMAKE_CURRENT_SOURCE_DIR}/PreInstall.cmake)
   SET_TARGET_PROPERTIES(SimpleInstall PROPERTIES POST_INSTALL_SCRIPT 
     ${CMAKE_CURRENT_SOURCE_DIR}/PostInstall.cmake)
+  #SET_TARGET_PROPERTIES(test4 PROPERTIES VERSION 1.2 SOVERSION 3)
+  SET_TARGET_PROPERTIES(test4 PROPERTIES VERSION 1.2)
 ENDIF(STAGE2)
 
 ADD_CUSTOM_COMMAND(

+ 6 - 0
Tests/SimpleInstall/inst.cxx

@@ -2,6 +2,7 @@
 
 #include "lib1.h"
 #include "lib2.h"
+#include "lib4.h"
 
 #include <stdio.h>
 
@@ -17,6 +18,11 @@ int main ()
     printf("Problem with lib2\n");
     return 1;
     }
+  if ( Lib4Func() != 4.0 )
+    {
+    printf("Problem with lib4\n");
+    return 1;
+    }
   printf("The value of Foo: %s\n", foo);
   return SomeFunctionInFoo()-5;
 }

+ 7 - 0
Tests/SimpleInstall/lib4.cxx

@@ -0,0 +1,7 @@
+#include "lib4.h"
+
+float Lib4Func()
+{
+  return 4.0;
+}
+

+ 12 - 0
Tests/SimpleInstall/lib4.h

@@ -0,0 +1,12 @@
+#ifdef _WIN32
+#  ifdef test4_EXPORTS
+#    define CM_TEST_LIB_EXPORT  __declspec( dllexport )
+#  else
+#    define CM_TEST_LIB_EXPORT  __declspec( dllimport )
+#  endif
+#else
+#  define CM_TEST_LIB_EXPORT 
+#endif
+
+CM_TEST_LIB_EXPORT float Lib4Func();
+

+ 13 - 4
Tests/SimpleInstallS2/CMakeLists.txt

@@ -30,6 +30,7 @@ IF(STAGE2)
   SET(LIBPATHS "${CMAKE_INSTALL_PREFIX}/lib")
   SET(t1NAMES test1 test1${CMAKE_DEBUG_POSTFIX})
   SET(t2NAMES test2 test2${CMAKE_DEBUG_POSTFIX})
+  SET(t4NAMES test4 test4${CMAKE_DEBUG_POSTFIX})
 
   IF(CYGWIN OR MINGW)
     SET(LIBPATHS ${LIBPATHS} "${CMAKE_INSTALL_PREFIX}/bin")
@@ -42,10 +43,14 @@ IF(STAGE2)
   FIND_LIBRARY(TEST2_LIBRARY 
     NAMES ${t2NAMES}
     PATHS ${LIBPATHS}
-    DOC "First library")
+    DOC "Second library")
+  FIND_LIBRARY(TEST4_LIBRARY 
+    NAMES ${t4NAMES}
+    PATHS ${LIBPATHS}
+    DOC "Fourth library")
 
   ADD_EXECUTABLE (SimpleInstallS2 inst.cxx foo.c foo.h)
-  TARGET_LINK_LIBRARIES(SimpleInstallS2 ${TEST1_LIBRARY} ${TEST2_LIBRARY})
+  TARGET_LINK_LIBRARIES(SimpleInstallS2 ${TEST1_LIBRARY} ${TEST2_LIBRARY} ${TEST4_LIBRARY})
   SET(install_target SimpleInstallS2)
 
   INSTALL_TARGETS(/bin SimpleInstallS2)
@@ -58,22 +63,26 @@ ELSE(STAGE2)
   ADD_LIBRARY(test1 STATIC lib1.cxx)
   ADD_LIBRARY(test2 SHARED lib2.cxx)
   ADD_LIBRARY(test3 MODULE lib3.cxx)
+  ADD_LIBRARY(test4 SHARED lib4.cxx)
 
   ADD_EXECUTABLE (SimpleInstall inst.cxx foo.c foo.h)
-  TARGET_LINK_LIBRARIES(SimpleInstall test1 test2)
+  TARGET_LINK_LIBRARIES(SimpleInstall test1 test2 test4)
   SET(install_target SimpleInstall)
 
   ADD_DEPENDENCIES(SimpleInstall test3)
   ADD_DEPENDENCIES(test2 test3)
+  ADD_DEPENDENCIES(test4 test3)
 
   INSTALL_TARGETS(/bin SimpleInstall)
-  INSTALL_TARGETS(/lib test1 test2 test3)
+  INSTALL_TARGETS(/lib test1 test2 test3 test4)
   INSTALL_TARGETS(/include lib1.h lib2.h lib3.h)
 
   SET_TARGET_PROPERTIES(SimpleInstall PROPERTIES PRE_INSTALL_SCRIPT 
     ${CMAKE_CURRENT_SOURCE_DIR}/PreInstall.cmake)
   SET_TARGET_PROPERTIES(SimpleInstall PROPERTIES POST_INSTALL_SCRIPT 
     ${CMAKE_CURRENT_SOURCE_DIR}/PostInstall.cmake)
+  #SET_TARGET_PROPERTIES(test4 PROPERTIES VERSION 1.2 SOVERSION 3)
+  SET_TARGET_PROPERTIES(test4 PROPERTIES VERSION 1.2)
 ENDIF(STAGE2)
 
 ADD_CUSTOM_COMMAND(

+ 6 - 0
Tests/SimpleInstallS2/inst.cxx

@@ -2,6 +2,7 @@
 
 #include "lib1.h"
 #include "lib2.h"
+#include "lib4.h"
 
 #include <stdio.h>
 
@@ -17,6 +18,11 @@ int main ()
     printf("Problem with lib2\n");
     return 1;
     }
+  if ( Lib4Func() != 4.0 )
+    {
+    printf("Problem with lib4\n");
+    return 1;
+    }
   printf("The value of Foo: %s\n", foo);
   return SomeFunctionInFoo()-5;
 }

+ 7 - 0
Tests/SimpleInstallS2/lib4.cxx

@@ -0,0 +1,7 @@
+#include "lib4.h"
+
+float Lib4Func()
+{
+  return 4.0;
+}
+

+ 12 - 0
Tests/SimpleInstallS2/lib4.h

@@ -0,0 +1,12 @@
+#ifdef _WIN32
+#  ifdef test4_EXPORTS
+#    define CM_TEST_LIB_EXPORT  __declspec( dllexport )
+#  else
+#    define CM_TEST_LIB_EXPORT  __declspec( dllimport )
+#  endif
+#else
+#  define CM_TEST_LIB_EXPORT 
+#endif
+
+CM_TEST_LIB_EXPORT float Lib4Func();
+