From f9b43b9212b1ae2ba4dd9c4f609f8d5093421398 Mon Sep 17 00:00:00 2001 From: Andy Cedilnik Date: Mon, 28 Jun 2004 14:40:17 -0400 Subject: [PATCH] BUG: Implement installing of shared library versioning and add test for the whole thing --- Source/cmFileCommand.cxx | 83 ++++++++++++++++++++++++++-- Source/cmLocalGenerator.cxx | 31 ++++++++++- Source/cmLocalGenerator.h | 3 +- Tests/SimpleInstall/CMakeLists.txt | 17 ++++-- Tests/SimpleInstall/inst.cxx | 6 ++ Tests/SimpleInstall/lib4.cxx | 7 +++ Tests/SimpleInstall/lib4.h | 12 ++++ Tests/SimpleInstallS2/CMakeLists.txt | 17 ++++-- Tests/SimpleInstallS2/inst.cxx | 6 ++ Tests/SimpleInstallS2/lib4.cxx | 7 +++ Tests/SimpleInstallS2/lib4.h | 12 ++++ 11 files changed, 184 insertions(+), 17 deletions(-) create mode 100644 Tests/SimpleInstall/lib4.cxx create mode 100644 Tests/SimpleInstall/lib4.h create mode 100644 Tests/SimpleInstallS2/lib4.cxx create mode 100644 Tests/SimpleInstallS2/lib4.h diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 4f578c2b5..1b49ff758 100644 --- a/Source/cmFileCommand.cxx +++ b/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::size_type i = 0; i++; // Get rid of subcommand + std::map 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; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 61cb39d2e..f337ff184 100644 --- a/Source/cmLocalGenerator.cxx +++ b/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"; } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 412d3acf9..792d8e13c 100644 --- a/Source/cmLocalGenerator.h +++ b/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; diff --git a/Tests/SimpleInstall/CMakeLists.txt b/Tests/SimpleInstall/CMakeLists.txt index 1d15e56bc..fc36dd16f 100644 --- a/Tests/SimpleInstall/CMakeLists.txt +++ b/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( diff --git a/Tests/SimpleInstall/inst.cxx b/Tests/SimpleInstall/inst.cxx index a933e2bfd..241a296b4 100644 --- a/Tests/SimpleInstall/inst.cxx +++ b/Tests/SimpleInstall/inst.cxx @@ -2,6 +2,7 @@ #include "lib1.h" #include "lib2.h" +#include "lib4.h" #include @@ -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; } diff --git a/Tests/SimpleInstall/lib4.cxx b/Tests/SimpleInstall/lib4.cxx new file mode 100644 index 000000000..fbfa23aa4 --- /dev/null +++ b/Tests/SimpleInstall/lib4.cxx @@ -0,0 +1,7 @@ +#include "lib4.h" + +float Lib4Func() +{ + return 4.0; +} + diff --git a/Tests/SimpleInstall/lib4.h b/Tests/SimpleInstall/lib4.h new file mode 100644 index 000000000..4b94ea207 --- /dev/null +++ b/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(); + diff --git a/Tests/SimpleInstallS2/CMakeLists.txt b/Tests/SimpleInstallS2/CMakeLists.txt index 1d15e56bc..fc36dd16f 100644 --- a/Tests/SimpleInstallS2/CMakeLists.txt +++ b/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( diff --git a/Tests/SimpleInstallS2/inst.cxx b/Tests/SimpleInstallS2/inst.cxx index a933e2bfd..241a296b4 100644 --- a/Tests/SimpleInstallS2/inst.cxx +++ b/Tests/SimpleInstallS2/inst.cxx @@ -2,6 +2,7 @@ #include "lib1.h" #include "lib2.h" +#include "lib4.h" #include @@ -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; } diff --git a/Tests/SimpleInstallS2/lib4.cxx b/Tests/SimpleInstallS2/lib4.cxx new file mode 100644 index 000000000..fbfa23aa4 --- /dev/null +++ b/Tests/SimpleInstallS2/lib4.cxx @@ -0,0 +1,7 @@ +#include "lib4.h" + +float Lib4Func() +{ + return 4.0; +} + diff --git a/Tests/SimpleInstallS2/lib4.h b/Tests/SimpleInstallS2/lib4.h new file mode 100644 index 000000000..4b94ea207 --- /dev/null +++ b/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(); +