SO versions for cmake and libtool

this updates the version-sync script to generate proper SO versions
which will be used by cmake and libtool to create version symlinks
on the system when a library is installed as well as setting the SO
version in the binary.

To see what this does, you have to configure tox with a prefix:

    ./configure --prefix=/tmp/tox-with-libtool
    mkdir cbuild && cd cbuild && cmake -DCMAKE_INSTALL_PREFIX=/tmp/tox-with-cmake ..

Then run `make && make install`.

in both instances you should see the following installed in `lib/`:

    libtoxcore.so -> libtoxcore.so.1.4.0
    libtoxcore.so.1 -> libtoxcore.so.1.4.0
    libtoxcore.so.1.4.0

inside the binary the soname should be the one with .1 and it should not
contain the full version:

    $ objdump -p libtoxcore.so.1.4.0 | grep SONAME
      SONAME               libtoxcore.so.1
This commit is contained in:
Carsten Brandt 2017-01-15 21:22:35 +01:00 committed by Sergey 'Jin' Bostandzhyan
parent 3f24f04876
commit 3520eee05d
3 changed files with 136 additions and 25 deletions

View File

@ -2,15 +2,47 @@ cmake_minimum_required(VERSION 2.8.6)
project(toxcore)
include(CTest)
set(CMAKE_MODULE_PATH ${toxcore_SOURCE_DIR}/cmake)
################################################################################
#
# :: Version management
#
################################################################################
# This version is for the entire project. All libraries (core, av, ...) move in
# versions in a synchronised way.
set(PROJECT_VERSION_MAJOR "0")
set(PROJECT_VERSION_MINOR "1")
set(PROJECT_VERSION_PATCH "4")
set(PROJECT_VERSION
"${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
# Update versions in various places
# This must be run before setting SOVERSION, because SOVERSION is read from
# a file generated by this script
find_program(SHELL NAMES sh dash bash zsh)
if(SHELL)
execute_process(
COMMAND ${SHELL} ${toxcore_SOURCE_DIR}/other/version-sync
${toxcore_SOURCE_DIR}
${PROJECT_VERSION_MAJOR}
${PROJECT_VERSION_MINOR}
${PROJECT_VERSION_PATCH})
endif()
# set .so library version / following libtool scheme
# https://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info
file(STRINGS ${toxcore_SOURCE_DIR}/so.version SOVERSION_CURRENT REGEX "^CURRENT=[0-9]+$")
string(SUBSTRING "${SOVERSION_CURRENT}" 8 -1 SOVERSION_CURRENT)
file(STRINGS ${toxcore_SOURCE_DIR}/so.version SOVERSION_REVISION REGEX "^REVISION=[0-9]+$")
string(SUBSTRING "${SOVERSION_REVISION}" 9 -1 SOVERSION_REVISION)
file(STRINGS ${toxcore_SOURCE_DIR}/so.version SOVERSION_AGE REGEX "^AGE=[0-9]+$")
string(SUBSTRING "${SOVERSION_AGE}" 4 -1 SOVERSION_AGE)
# account for some libtool magic, see other/version-sync script for details
math(EXPR SOVERSION_MAJOR ${SOVERSION_CURRENT}-${SOVERSION_AGE})
set(SOVERSION "${SOVERSION_MAJOR}.${SOVERSION_AGE}.${SOVERSION_REVISION}")
message("SOVERSION: ${SOVERSION}")
set(CMAKE_MODULE_PATH ${toxcore_SOURCE_DIR}/cmake)
################################################################################
#
@ -591,23 +623,6 @@ if(BUILD_TOXAV)
DESTINATION "include/tox")
endif()
################################################################################
#
# :: Update versions in various places
#
################################################################################
find_program(SHELL NAMES sh dash bash zsh)
if(SHELL)
execute_process(
COMMAND ${SHELL} ${toxcore_SOURCE_DIR}/other/version-sync
${toxcore_SOURCE_DIR}
${PROJECT_VERSION_MAJOR}
${PROJECT_VERSION_MINOR}
${PROJECT_VERSION_PATCH})
endif()
################################################################################
#
# :: Strict ABI

View File

@ -56,10 +56,8 @@ function(add_module lib)
add_library(${lib}_shared SHARED ${ARGN})
set_target_properties(${lib}_shared PROPERTIES
OUTPUT_NAME ${lib}
VERSION ${PROJECT_VERSION}
# While on 0.x, the x behaves like the major version. 0.2 will be
# incompatible with 0.1. Change this, when releasing 1.0!
SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}
VERSION ${SOVERSION}
SOVERSION ${SOVERSION_MAJOR}
)
install(TARGETS ${lib}_shared DESTINATION "lib")
endif()

View File

@ -17,7 +17,9 @@ update() {
if diff "$file" "$file.updated-version"; then
rm "$file.updated-version"
else
mv "$file.updated-version" "$file"
# use cat > and rm instead of move to keep file permissions
cat "$file.updated-version" > "$file"
rm "$file.updated-version"
fi
}
@ -26,3 +28,99 @@ update 'configure.ac' 's/AC_INIT(\[tox\], \[.*\])/AC_INIT([tox], ['$VER'])/'
update 'toxcore/tox.api.h' 's/\(const VERSION_MAJOR *= \).*;/\1'$MAJOR';/'
update 'toxcore/tox.api.h' 's/\(const VERSION_MINOR *= \).*;/\1'$MINOR';/'
update 'toxcore/tox.api.h' 's/\(const VERSION_PATCH *= \).*;/\1'$PATCH';/'
#
# calculating the SO version
#
# The SO version reflects changes in the ABI compatibility of the libary [1].
# The general convention on this is that the SO version is a monotonically
# increasing number. The major version reflects breaking changes and the minor
# number reflect non-breaking updates [2].
#
# The SO version for tox libraries consists of two parts: `A.B`.
# - incrementing A reflects an ABI breaking change.
# - incrementing B reflects a non-ABI-breaking update. B is set to 0 when A is incremented.
#
# As the tox versioning scheme directly reflects ABI compatibility, we can use it
# to construct the SO version.
#
# In the `0.y.z` release cycle, breaking changes are allowed in every increment of `y`,
# so we can build the SO version just by taking `y.z`.
# In the `x.y.z` release cycle with `x > 0` the SO version must be calculated by taking
# the major of the tox version and add a hardcoded number that is the last A of the 0.y.z
# release cycle.
#
# References:
#
# [1]: https://autotools.io/libtool/version.html
# [2]: http://www.ibm.com/developerworks/linux/library/l-shlibs/index.html#N1006E
#
# the last major version number from the 0.x release cycle
# this must be constant starting from the 1.0 release
LAST_SOMAJOR=1
if [ $MAJOR -eq 0 ]; then
SOMAJOR=$MINOR
SOMINOR=$PATCH
# update lastmajor above
update 'other/version-sync' 's/^\(LAST_SOMAJOR=\).*/\1'$SOMAJOR'/'
else
SOMAJOR=$(expr $MAJOR + $LAST_SOMAJOR)
SOMINOR=$MINOR
fi
#
# libtool has a quite cryptic implementation of the versioning system, which also
# changes between systems, see https://github.com/lxde/lxqt/issues/488#issuecomment-238084222
#
# .so library version, following the libtool scheme:
#
# current:revision:age
#
# current: increment if interfaces have been added, removed or changed
# revision: increment if source code has changed, set to zero if current is
# incremented
# age: increment if interfaces have been added, set to zero if
# interfaces have been removed or changed
#
# For a full reference see:
# https://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info
#
# Passing such a version string to libtool will generate the following version number
# on the libary binary file on GNU/Linux:
#
# (current - age).(age).(revision)
#
# We do not want to use a separate version numbering for the library because the package versioning is equally good:
#
# Semver non-breaking: 0.y.(z+1) or x.(y+1).0:
#
# This would mean to increment current and age, which leave the major of SOVERSION the same.
# Revision is incremented.
#
# Semver breaking: 0.(y+1).0 or (x+1).0.0:
#
# This would mean to increment current, set age and revision to zero.
#
# Thus to make libtool use our version, we have to pass (major + minor):patch:minor as current:revision:age to get:
#
# (current - age).(age).(revision)
# <=> (major + minor - minor).minor.patch
# <=> major.minor.patch
#
if [ $MAJOR -eq 0 ]; then
LIBTOOL_CURRENT=$(expr $SOMAJOR + $SOMINOR)
LIBTOOL_AGE=$SOMINOR
LIBTOOL_REVISION=0
else
LIBTOOL_CURRENT=$(expr $SOMAJOR + $SOMINOR)
LIBTOOL_AGE=$SOMINOR
LIBTOOL_REVISION=$PATCH
fi
update 'so.version' 's/^\(CURRENT=\).*/\1'$LIBTOOL_CURRENT'/'
update 'so.version' 's/^\(AGE=\).*/\1'$LIBTOOL_AGE'/'
update 'so.version' 's/^\(REVISION=\).*/\1'$LIBTOOL_REVISION'/'