[Cmake] Shared library versioning (Take II)

Gavin Baker gavinb at antonym . org
23 Jun 2003 18:27:29 +1000


--=-A4WRKrql1DUA+ek6nYoG
Content-Type: multipart/mixed; boundary="=-xITelKsrr9PxJvvA6rwE"


--=-xITelKsrr9PxJvvA6rwE
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

Here is Take II on adding versioning support for shared libraries in
CMake.  The patch is made against the latest release tarball 1.6.7.

I took into account the feedback from Brad [0] and rewrote the patch
accordingly.  It is still not complete (I have yet to add flags for all
the different platforms) but I would like some feedback on it before I
continue further.

[0] http://www . cmake . org/pipermail/cmake/2003-June/001797 . html

This time it uses a MACRO instead of a new command, and the macro
defines the PROPERTIES of the target.  These properties, when present,
cause extra flags to be added to the linking command.  I have modified
the CMakeDefaultMakeRuleVariables.cmake accordingly.

Here is a sample CMakeLists.txt :

  PROJECT(Xanadu)
  ADD_LIBRARY(foo SHARED foo.cxx)
  SET_LIBRARY_VERSION(foo 1.5.4 7)

The generated output is:

libfoo.so: $(foo_SRC_OBJS)  $(foo_DEPEND_LIBS)
	echo "Building shared library libfoo.so..."
	$(RM) libfoo.so
	c++ -fPIC  -rdynamic -Wl,-soname,libfoo.so.7 -shared -o libfoo.so.1.5.4
$(foo_SRC_OBJS) =20
	 ln -sf libfoo.so.1.5.4 libfoo.so.7
	 ln -sf libfoo.so.7 libfoo.so

I have tested it and it works fine.  If the versioning is not specified,
the flags and commands revert to normal.

But - the symlink commands get left behind.  Since they are not added
programmatically (but appear in the default rules file) they are
currently always there.  Any suggestions on how to clean this up?

I noticed that if I made the rules in the
CMakeDefaultMakeRuleVariables.cmake multi-line (ie. in several strings)
it only took the first one, while using a semicolon separator worked.=20
The multiline style is used further down in another rule, so I thought
this should have worked.

I added a CMAKE_SYMLINK command, which should probably have an
associated Find* command with it.  Is that the right approach?

BTW, I noticed the documentation file CMake.pdf is way out of date with
respect to CMake.rtf.

All feedback appreciated!

Thanks,

  :: Gavin

--=20
Gavin Baker // gavinb*antonym_org // Linux|Python|Esperanto|MIDI|Cheese

--=-xITelKsrr9PxJvvA6rwE
Content-Disposition: attachment; filename=cmake_sover.diff
Content-Type: text/x-patch; name=cmake_sover.diff; charset=ANSI_X3.4-1968
Content-Transfer-Encoding: quoted-printable

diff -ru cmake-1.6.7_orig/Modules/CMakeDefaultMakeRuleVariables.cmake cmake=
-1.6.7_sover/Modules/CMakeDefaultMakeRuleVariables.cmake
--- cmake-1.6.7_orig/Modules/CMakeDefaultMakeRuleVariables.cmake	2003-01-01=
 05:08:44.000000000 +1100
+++ cmake-1.6.7_sover/Modules/CMakeDefaultMakeRuleVariables.cmake	2003-06-2=
2 22:55:26.000000000 +1000
@@ -17,6 +17,8 @@
 # variables supplied by the generator at use time
 # <TARGET>
 # <TARGET_BASE> the target without the suffix
+# <TARGET_VERSION> (optional) full version number (eg. 2.5.3)
+# <TARGET_SOVERSION> (optional) shared object version number (eg. 4)
 # <OBJECTS>
 # <OBJECT>
 # <LINK_LIBRARIES>
@@ -39,11 +41,16 @@
 # <CMAKE_AR>=20
 # <CMAKE_RANLIB>
=20
+# Other tools
+# <CMAKE_SYMLINK>
+
+# Search for this?
+SET(CMAKE_SYMLINK "ln -sf")
=20
 # create a shared C++ library
 IF(NOT CMAKE_CXX_CREATE_SHARED_LIBRARY)
   SET(CMAKE_CXX_CREATE_SHARED_LIBRARY
-      "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LINK_FLAGS> =
<CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARI=
ES>")
+      "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LINK_FLAGS> =
<CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> -o <TARGET><TARGET_VERSION_SUFFIX> =
<OBJECTS> <LINK_LIBRARIES>; <CMAKE_SYMLINK> <TARGET><TARGET_VERSION_SUFFIX>=
 <TARGET><TARGET_SOVERSION_SUFFIX>; <CMAKE_SYMLINK> <TARGET><TARGET_SOVERSI=
ON_SUFFIX> <TARGET>")
 ENDIF(NOT CMAKE_CXX_CREATE_SHARED_LIBRARY)
=20
 # create a c++ shared module copy the shared library rule by default
@@ -54,7 +61,7 @@
 # create a C shared library
 IF(NOT CMAKE_C_CREATE_SHARED_LIBRARY)
   SET(CMAKE_C_CREATE_SHARED_LIBRARY
-      "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LINK_FLAGS> <CMA=
KE_SHARED_LIBRARY_CREATE_C_FLAGS> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
+      "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LINK_FLAGS> <CMA=
KE_SHARED_LIBRARY_CREATE_C_FLAGS> -o <TARGET><TARGET_VERSION><TARGET_VERSIO=
N_SUFFIX> <OBJECTS> <LINK_LIBRARIES>; <CMAKE_SYMLINK> <TARGET><TARGET_VERSI=
ON_SUFFIX> <TARGET><TARGET_SOVERSION_SUFFIX>; <CMAKE_SYMLINK> <TARGET><TARG=
ET_SOVERSION_SUFFIX> <TARGET>")
 ENDIF(NOT CMAKE_C_CREATE_SHARED_LIBRARY)
=20
 # create a C shared module just copy the shared library rule
@@ -99,3 +106,10 @@
   SET(CMAKE_CXX_LINK_EXECUTABLE
     "<CMAKE_CXX_COMPILER> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <FLAGS> <OBJ=
ECTS>  -o <TARGET> <LINK_LIBRARIES>")
 ENDIF(NOT CMAKE_CXX_LINK_EXECUTABLE)
+
+# Versioning supoprt for shared libraries
+MACRO(SET_LIBRARY_VERSION lib ver sover)
+        SET_TARGET_PROPERTIES(${lib} PROPERTIES
+                                     LIBRARY_VERSION    ${ver}
+                                     LIBRARY_SOVERSION  ${sover})
+ENDMACRO(SET_LIBRARY_VERSION)
diff -ru cmake-1.6.7_orig/Modules/Platform/Linux.cmake cmake-1.6.7_sover/Mo=
dules/Platform/Linux.cmake
--- cmake-1.6.7_orig/Modules/Platform/Linux.cmake	2002-11-09 10:06:53.00000=
0000 +1100
+++ cmake-1.6.7_sover/Modules/Platform/Linux.cmake	2003-06-18 22:14:08.0000=
00000 +1000
@@ -7,3 +7,4 @@
 SET(CMAKE_SHARED_LIBRARY_LINK_FLAGS "-rdynamic") =20
 SET(CMAKE_SHARED_LIBRARY_RUNTIME_FLAG "-Wl,-rpath,")
 SET(CMAKE_SHARED_LIBRARY_RUNTIME_FLAG_SEP ":")
+SET(CMAKE_SHARED_LIBRARY_SONAME_FLAGS "-rdynamic -Wl,-soname,")
diff -ru cmake-1.6.7_orig/Source/cmLocalUnixMakefileGenerator.cxx cmake-1.6=
.7_sover/Source/cmLocalUnixMakefileGenerator.cxx
--- cmake-1.6.7_orig/Source/cmLocalUnixMakefileGenerator.cxx	2003-05-17 05:=
20:48.000000000 +1000
+++ cmake-1.6.7_sover/Source/cmLocalUnixMakefileGenerator.cxx	2003-06-22 22=
:58:50.000000000 +1000
@@ -727,6 +727,7 @@
=20
   {"<CMAKE_AR>", "CMAKE_AR"},
   {"<CMAKE_RANLIB>", "CMAKE_RANLIB"},
+  {"<CMAKE_SYMLINK>", "CMAKE_SYMLINK"},
   {0, 0}
 };
=20
@@ -743,7 +744,9 @@
                                                   const char* flags,
                                                   const char* objectsquote=
d,
                                                   const char* targetBase,
-                                                  const char* linkFlags)
+                                                  const char* linkFlags,
+                                                  const char* versionSuffi=
x,
+                                                  const char* soversionSuf=
fix)
 {=20
   std::string cxxcompiler =3D this->ConvertToOutputForExisting(
     this->GetSafeDefinition("CMAKE_CXX_COMPILER"));
@@ -759,7 +762,6 @@
     {
     cmSystemTools::ReplaceString(s, "<FLAGS>", flags);
     }
-   =20
   if(source)
     {
     cmSystemTools::ReplaceString(s, "<SOURCE>", source);
@@ -800,7 +802,23 @@
     {
     cmSystemTools::ReplaceString(s, "<LINK_LIBRARIES>", linkLibs);
     }
- =20
+  if(versionSuffix)
+    {
+    cmSystemTools::ReplaceString(s, "<TARGET_VERSION_SUFFIX>", versionSuff=
ix);
+    }
+  else
+    {
+    cmSystemTools::ReplaceString(s, "<TARGET_VERSION_SUFFIX>", "");
+    }
+  if(soversionSuffix)
+    {
+    cmSystemTools::ReplaceString(s, "<TARGET_SOVERSION_SUFFIX>", soversion=
Suffix);
+    }
+  else
+    {
+    cmSystemTools::ReplaceString(s, "<TARGET_SOVERSION_SUFFIX>", "");
+    }
+
   RuleVariables* rv =3D ruleReplaceVars;
   while(rv->replace)
     {
@@ -818,7 +836,9 @@
                                                      const char* suffix,
                                                      const char* createVar=
iable,
                                                      const char* comment,
-                                                     const char* linkFlags
+                                                     const char* linkFlags=
,
+                                                     const char* versionSu=
ffix,
+                                                     const char* soversion=
Suffix
                                                      )
 {
   // create the library name
@@ -867,7 +887,9 @@
                               linklibs.str().c_str(),
                               0, 0, 0, objsQuoted.c_str(),
                               targetBaseFullPath.c_str(),
-                              linkFlags);
+                              linkFlags,
+                              versionSuffix,
+                              soversionSuffix);
     }
   this->OutputMakeRule(fout, comment,
                        targetFullPath.c_str(),
@@ -928,12 +950,32 @@
     linkFlags +=3D targetLinkFlags;
     linkFlags +=3D " ";
     }
+  const char* targetVersion =3D t.GetProperty("LIBRARY_VERSION");
+  const char* targetSoversion =3D t.GetProperty("LIBRARY_SOVERSION");
+  std::string versionSuffix;
+  std::string soversionSuffix;
+  if(targetVersion && targetSoversion)
+    {
+    versionSuffix +=3D ".";
+    versionSuffix +=3D targetVersion;
+
+    soversionSuffix +=3D ".";
+    soversionSuffix +=3D targetSoversion;
+
+    linkFlags +=3D this->GetSafeDefinition("CMAKE_SHARED_LIBRARY_SONAME_FL=
AGS");
+    linkFlags +=3D targetPrefix;
+    linkFlags +=3D name;
+    linkFlags +=3D targetSuffix;
+    linkFlags +=3D soversionSuffix;
+    }
   this->OutputLibraryRule(fout, name, t,
                           targetPrefix,
                           targetSuffix,
                           createRule,
                           "shared library",
-                          linkFlags.c_str());
+                          linkFlags.c_str(),
+                          versionSuffix.c_str(),
+                          soversionSuffix.c_str());
 }
=20
 void cmLocalUnixMakefileGenerator::OutputModuleLibraryRule(std::ostream& f=
out,=20
diff -ru cmake-1.6.7_orig/Source/cmLocalUnixMakefileGenerator.h cmake-1.6.7=
_sover/Source/cmLocalUnixMakefileGenerator.h
--- cmake-1.6.7_orig/Source/cmLocalUnixMakefileGenerator.h	2003-01-19 03:34=
:25.000000000 +1100
+++ cmake-1.6.7_sover/Source/cmLocalUnixMakefileGenerator.h	2003-06-22 17:2=
6:30.000000000 +1000
@@ -93,7 +93,9 @@
                          const char* suffix,
                          const char* createRule,
                          const char* comment,
-                         const char* linkFlags
+                         const char* linkFlags,
+                         const char* versionSuffix =3D 0,
+                         const char* soversionSuffix =3D 0
     );
   void ExpandRuleVariables(std::string& string,
                            const char* objects=3D0,
@@ -104,7 +106,9 @@
                            const char* flags =3D 0,
                            const char* objectsquoted =3D 0,
                            const char* targetBase =3D 0,
-                           const char* linkFlags =3D 0);
+                           const char* linkFlags =3D 0,
+                           const char* versionSuffix =3D 0,
+                           const char* soversionSuffix =3D 0);
   virtual void OutputSharedLibraryRule(std::ostream&, const char* name,
                                        const cmTarget &);
   virtual void OutputModuleLibraryRule(std::ostream&, const char* name,=20

--=-xITelKsrr9PxJvvA6rwE--

--=-A4WRKrql1DUA+ek6nYoG
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.2 (GNU/Linux)

iD8DBQA+9rnwgMaYJRCPYLsRAg7ZAJ9M6kyALXhMVVpOa7FuvKLuoEmILwCfRKPH
/EAui/aaJ+OOl4/eulvVyL0=
=3vYb
-----END PGP SIGNATURE-----

--=-A4WRKrql1DUA+ek6nYoG--