Add support for shared-library versioning

This commit is contained in:
Christophe de Dinechin 2018-05-26 11:17:39 +02:00
parent aa87d0f94b
commit 0e8c83820b
5 changed files with 64 additions and 4 deletions

View File

@ -433,6 +433,18 @@ in your makefile as follows:
A file called `my-great-stuff.pc` will be generated and installed
along with your product.
# Shared library versioning
Shared libraries can be versioned. Version numbers are typically
in the form major.minor.patch. The version number for a shared library
is taken from `PRODUCTS_VERSION`, which defaults to `PACKAGE_VERSION`.
For example, if `foo.dll` has `PRODUCTS_VERSION` is 1.3.2, this is
interpreted as major version 1, minor version 3 and patchlevel 2.
Accordingly, the library name is set to `libfoo.so.1.3.2`, the
soname is set to `libfoo.so.1`, and symbolc links `libfoo.so`
and `libfoo.so.1` will both point to `libfoo.so.1.3.2`.
## Other stuff
There a few utility targets, in particular:

View File

@ -72,6 +72,29 @@ EXE_PFX=
LIB_PFX= lib
DLL_PFX= lib
#------------------------------------------------------------------------------
# Shared libraries versioning
#------------------------------------------------------------------------------
MIQ_SOBASE= $(@F:%.install_dll=%)
MIQ_SONAME= $(@F:%.install_dll=%)$(MIQ_V_MAJOR:%=.%)
MIQ_DLLNAME= $(@:%.install_dll=%)$(PRODUCTS_VERSION:%=.$(MIQ_V_VERSION))
# Conversion to libttool input
MIQ_LT_CURRENT= $(shell echo $$(($(MIQ_V_MAJOR) + $(MIQ_V_MINOR))))
MIQ_LT_REVISION=$(MIQ_V_PATCH)
MIQ_LT_AGE= $(MIQ_V_MINOR)
MIQ_LT_VERSION= $(MIQ_LT_CURRENT):$(MIQ_LT_REVISION):$(MIQ_LT_AGE)
MIQ_LT_VERS_OPT=$(PRODUCTS_VERSION:%=-version-info $(MIQ_LT_VERSION))
# Symbolic links for shared libraries
MIQ_SONAME_OPT= $(PRODUCTS_VERSION:%=-Wl,-soname -Wl,$(MIQ_SONAME))
MIQ_SYMLINKS_SO=ln -sf $(notdir $(MIQ_DLLNAME)) $(MIQ_SOBASE) && \
ln -sf $(notdir $(MIQ_DLLNAME)) $(MIQ_SONAME)
MIQ_SYMLINKS= $(PRODUCTS_VERSION:%=&& $(MIQ_SYMLINKS_SO))
#------------------------------------------------------------------------------
# Build rules
#------------------------------------------------------------------------------
@ -85,8 +108,12 @@ MIQ_LINK= $(LIBTOOL) --silent --mode=link
MAKE_CC= $(MIQ_COMPILE) $(CC) $(MIQ_CFLAGS) -c $< -o $@
MAKE_CXX= $(MIQ_COMPILE) $(CXX) $(MIQ_CXXFLAGS) -c $< -o $@
MAKE_AS= $(MIQ_COMPILE) $(CC) $(MIQ_CFLAGS) -c $< -o $@
MAKE_LIB= $(MIQ_LINK) $(LD) $(MIQ_LDFLAGS) $(MIQ_TOLINK) -rpath $(PREFIX_DLL) -o $@
MAKE_LIB= $(MIQ_LINK) $(LD) $(MIQ_LDFLAGS) $(MIQ_TOLINK) \
-rpath $(PREFIX_DLL) -o $@ \
$(MIQ_LT_VERS_OPT)
MAKE_DLL= $(MAKE_LIB)
INSTALL_DLL= $(LIBTOOL) --silent --mode=install \
$(INSTALL) $(MIQ_DLLNAME) $(PREFIX_DLL)
MAKE_EXE= $(MIQ_LINK) $(LD) $(MIQ_LDFLAGS) $(MIQ_TOLINK) -o $@
else
# Non-libtool case: manage manually
@ -95,7 +122,13 @@ MAKE_CC= $(CC) $(MIQ_CFLAGS) -c $< -o $@
MAKE_CXX= $(CXX) $(MIQ_CXXFLAGS) -c $< -o $@
MAKE_AS= $(CC) $(MIQ_CFLAGS) -c $< -o $@
MAKE_LIB= $(AR) $@ $(MIQ_TOLINK) && $(RANLIB) $@
MAKE_DLL= $(LD) -shared $(MIQ_LDFLAGS) $(MIQ_TOLINK) -o $@ -Wl,-rpath -Wl,$(PREFIX_DLL)
MAKE_DLL= $(LD) -shared $(MIQ_LDFLAGS) $(MIQ_TOLINK) \
-o $(MIQ_DLLNAME) \
-Wl,-rpath -Wl,$(PREFIX_DLL) \
$(MIQ_SONAME_OPT) \
&& (cd $(OUTPUT) $(MIQ_SYMLINKS))
INSTALL_DLL= $(INSTALL) $(MIQ_DLLNAME) $(PREFIX_DLL) \
&& (cd $(PREFIX_DLL) $(MIQ_SYMLINKS))
MAKE_EXE= $(LD) $(MIQ_LDFLAGS) $(MIQ_TOLINK) -o $@
endif

View File

@ -27,7 +27,12 @@ OS_NAME_BUILDENV_macosx-clang=macosx
include $(MIQ)config.gnu.mk
DLL_EXT= .dylib
MAKE_DLL= $(LD) -shared $(MIQ_LDFLAGS) $(MIQ_TOLINK) -o $@ -rpath $(PREFIX_DLL)
# For macOS, the convention is to put the version number before extension,
# e.g. where Linux would have libfoo.so.1.3.2, macOS has libfoo.1.3.2.dylib
MIQ_NOINSTALL= $(@:%.install_dll=%)
MIQ_DLLNAME= $(MIQ_NOINSTALL:%$(DLL_EXT)=%$(PRODUCTS_VERSION:%=.$(MIQ_V_VERSION))$(DLL_EXT))
MIQ_SONAME_OPT= $(PRODUCTS_VERSION:%=-Wl,-install_name -Wl,$(MIQ_SONAME))
# On MacOSX, we will use basic frameworks e.g. for string and filesystem functions
LDFLAGS_BUILDENV_macosx-clang= -framework CoreFoundation \

View File

@ -61,6 +61,9 @@ NOT_PARALLEL?= .NOTPARALLEL
# Git revision for the current code
GIT_REVISION:= $(shell git rev-parse --short HEAD 2> /dev/null || echo "unknown")
# Product version defaults to package version
PRODUCTS_VERSION?=$(PACKAGE_VERSION)
# Package installation directory
PACKAGE_DIR?=$(PACKAGE_NAME:%=%/)
PACKAGE_LIBS=$(MIQ_PRODLIB)

View File

@ -119,6 +119,13 @@ MIQ_RUNTEST= $(TEST_ENV) \
$(OUTPUT)$(EXE_PFX)$*_test$(EXE_EXT) \
$(TEST_ARGS_$*)
# Versioning for DLLs
MIQ_V_WORDS= $(subst ., ,$(PRODUCTS_VERSION))
MIQ_V_MAJOR= $(word 1,$(MIQ_V_WORDS) 0 0 0)
MIQ_V_MINOR= $(word 2,$(MIQ_V_WORDS) 0 0 0)
MIQ_V_PATCH= $(word 3,$(MIQ_V_WORDS) 0 0 0)
MIQ_V_VERSION= $(MIQ_V_MAJOR).$(MIQ_V_MINOR).$(MIQ_V_PATCH)
# Check a common mistake with PRODUCTS= not being set or set without extension
# Even on Linux / Unix, the PRODUCTS variable must end in .exe for executables,
# in .lib for static libraries, and in .dll for dynamic libraries.
@ -568,7 +575,7 @@ benchmark: $(BENCHMARKS:%=%.benchmark)
%.install_lib: $(PREFIX_LIB).mkdir-only .product
$(PRINT_INSTALL) $(INSTALL) $* $(PREFIX_LIB)
%.install_dll: $(PREFIX_DLL).mkdir-only .product
$(PRINT_INSTALL) $(INSTALL) $* $(PREFIX_DLL)
$(PRINT_INSTALL) $(INSTALL_DLL)
%.install_hdr: $(PREFIX_HDR).mkdir-only
$(PRINT_INSTALL) $(INSTALL) $* $(PREFIX_HDR)
%.install_shr: $(PREFIX_SHR).mkdir-only