unicode string library
git clone git://
Log | Files | Refs | README | LICENSE

commit ed7ebdc7f7fa748f89372e034d6d983835db5d42
parent b583c3ab6855d491154f7be6d3bdb5c44380290c
Author: Laslo Hunhold <>
Date:   Wed,  5 Oct 2022 22:14:17 +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.


Signed-off-by: Laslo Hunhold <>

MMakefile | 14+++++++++----- | 9++++++++-
2 files changed, 17 insertions(+), 6 deletions(-)

diff --git 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 +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 "$(DESTDIR)$(LIBPREFIX)" + cp -f "$(DESTDIR)$(LIBPREFIX)/$(VERSION)" + i=0; while [ "$$i" -le $(VERSION_MINOR) ]; do ln -sf "$(VERSION)" "$(DESTDIR)$(LIBPREFIX)/$(VERSION_MAJOR).$$i"; i=$$((i+1)); done + ln -sf "$(VERSION)" "$(DESTDIR)$(LIBPREFIX)/$(VERSION_MAJOR)" + ln -sf "$(VERSION)" "$(DESTDIR)$(LIBPREFIX)/" 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)/$(VERSION)" + i=0; while [ "$$i" -le $(VERSION_MINOR) ]; do rm -f "$(DESTDIR)$(LIBPREFIX)/$(VERSION_MAJOR).$$i"; i=$$((i+1)); done + rm -f "$(DESTDIR)$(LIBPREFIX)/$(VERSION_MAJOR)" rm -f "$(DESTDIR)$(LIBPREFIX)/" rm -f "$(DESTDIR)$(INCPREFIX)/grapheme.h" $(LDCONFIG) diff --git a/ b/ @@ -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, +SOFLAGS = -shared -nostdlib -Wl,$(VERSION_MAJOR).$(VERSION_MINOR) # tools CC = cc