commit ed7ebdc7f7fa748f89372e034d6d983835db5d42
Author:     Laslo Hunhold <[email protected]>
AuthorDate: Wed Oct 5 22:14:17 2022 +0200
Commit:     Laslo Hunhold <[email protected]>
CommitDate: Wed Oct 5 22:44:52 2022 +0200

    Switch to semantic versioning and improve dynamic library handling
    
    After long consideration, I've made the decision to switch this project
    over to semantic versioning[0]. While it made sense for farbfeld in
    some way to use incremental versioning, for libraries it is almost
    canonical to make use of semantic versioning instead.
    
    Given there have been breaking API-changes since version 1 (which now
    corresponds to 1.0.0), the major version will naturally be bumped.
    Afterwards though, additions to the API will only trigger a minor bump,
    as is convention, while also making it possible to release
    patch-releases when there have been errors. Because, to be frank, if you
    only have full integers, you kind of get anxiety that a release is in
    fact correct, given you don't want to waste another whole integer-step
    on a simple bugfix.
    
    For farbfeld, which is very small and self-contained, it was okay, but
    libgrapheme has become complex enough to warrant this.
    
    Regarding dynamic library handling: I really read a lot about it and
    referred to some interesting articles like [1] to figure out what the
    best approach is to reflect versioning in the dynamic library.
    
    Doing this portably is quite difficult and the common approach to
    simply use the major version has some serious drawbacks, given a
    binary linked against the version 2.4 can falsely be linked against
    versions 2.3.x, 2.2.x, 2.1.x or 2.0.x at runtime, even though they
    lack functions added in 2.4 that might be used in the binary, something
    explicitly allowed in semantic versioning.
    
    A portable trick described in [1] is to set SONAME to contain
    MAJOR.MINOR and explicitly create symlinks from all "lower" MAJOR-MINOR-
    combinations with the same MAJOR-version to ensure forward-compatibility
    for all binaries linked against a certain MAJOR.MINOR-combination.
    
    This way, a library linked against libgrapheme-2.4 is properly linkable
    against libgrapheme-2.5 at runtime (given semantic versioning ensures
    forward compatibility), but at the same time, it will not allow linking
    against libgrapheme-2.2 (if that is installed), given it has no
    explicit symlink set from libgrapheme-2.2 at libgrapheme.2.5.
    
    [0]:https://semver.org/
    [1]:https://begriffs.com/posts/2021-07-04-shared-libraries.html
    
    Signed-off-by: Laslo Hunhold <[email protected]>

diff --git a/Makefile b/Makefile
index d325c1b..1f9edc7 100644
--- a/Makefile
+++ b/Makefile
@@ -2,12 +2,10 @@
 # libgrapheme - unicode string library
 .POSIX:
 
-VERSION = 1
-MAN_DATE = 2022-09-07
-UNICODE_VERSION = 15.0.0
-
 include config.mk
 
+VERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)
+
 BENCHMARK =\
        benchmark/case\
        benchmark/character\
@@ -277,7 +275,10 @@ install: all
        cp -f $(MAN3:=.3) "$(DESTDIR)$(MANPREFIX)/man3"
        cp -f $(MAN7:=.7) "$(DESTDIR)$(MANPREFIX)/man7"
        cp -f libgrapheme.a "$(DESTDIR)$(LIBPREFIX)"
-       cp -f libgrapheme.so "$(DESTDIR)$(LIBPREFIX)"
+       cp -f libgrapheme.so "$(DESTDIR)$(LIBPREFIX)/libgrapheme.so.$(VERSION)"
+       i=0; while [ "$$i" -le $(VERSION_MINOR) ]; do ln -sf 
"libgrapheme.so.$(VERSION)" 
"$(DESTDIR)$(LIBPREFIX)/libgrapheme.so.$(VERSION_MAJOR).$$i"; i=$$((i+1)); done
+       ln -sf "libgrapheme.so.$(VERSION)" 
"$(DESTDIR)$(LIBPREFIX)/libgrapheme.so.$(VERSION_MAJOR)"
+       ln -sf "libgrapheme.so.$(VERSION)" 
"$(DESTDIR)$(LIBPREFIX)/libgrapheme.so"
        cp -f grapheme.h "$(DESTDIR)$(INCPREFIX)"
        $(LDCONFIG)
 
@@ -285,6 +286,9 @@ uninstall:
        for m in $(MAN3:=.3); do rm -f "$(DESTDIR)$(MANPREFIX)/man3/`basename 
$$m`"; done
        for m in $(MAN7:=.7); do rm -f "$(DESTDIR)$(MANPREFIX)/man7/`basename 
$$m`"; done
        rm -f "$(DESTDIR)$(LIBPREFIX)/libgrapheme.a"
+       rm -f "$(DESTDIR)$(LIBPREFIX)/libgrapheme.so.$(VERSION)"
+       i=0; while [ "$$i" -le $(VERSION_MINOR) ]; do rm -f 
"$(DESTDIR)$(LIBPREFIX)/libgrapheme.so.$(VERSION_MAJOR).$$i"; i=$$((i+1)); done
+       rm -f "$(DESTDIR)$(LIBPREFIX)/libgrapheme.so.$(VERSION_MAJOR)"
        rm -f "$(DESTDIR)$(LIBPREFIX)/libgrapheme.so"
        rm -f "$(DESTDIR)$(INCPREFIX)/grapheme.h"
        $(LDCONFIG)
diff --git a/config.mk b/config.mk
index 14aedd3..f8bd40f 100644
--- a/config.mk
+++ b/config.mk
@@ -1,3 +1,10 @@
+# libgrapheme version
+VERSION_MAJOR = 1
+VERSION_MINOR = 0
+VERSION_PATCH = 0
+UNICODE_VERSION = 15.0.0
+MAN_DATE = 2022-09-07
+
 # Customize below to fit your system
 
 # paths
@@ -16,7 +23,7 @@ BUILD_CFLAGS   = $(CFLAGS)
 BUILD_LDFLAGS  = $(LDFLAGS)
 
 SHFLAGS  = -fPIC -ffreestanding
-SOFLAGS  = -shared -nostdlib -Wl,--soname=libgrapheme.so
+SOFLAGS  = -shared -nostdlib 
-Wl,--soname=libgrapheme.so.$(VERSION_MAJOR).$(VERSION_MINOR)
 
 # tools
 CC       = cc

Reply via email to