From: Gerhard Sittig Date: Sat, 18 Mar 2023 16:18:15 +0000 (+0100) Subject: make: move version suffix gathering from configure to compile time X-Git-Url: http://sigrok.org/gitweb/?p=libsigrok.git;a=commitdiff_plain;h=5bce22ac654fa45cdab49152bb3633ea77b4b7fc make: move version suffix gathering from configure to compile time Check at configure time whether version control is available. Determine at configure time which branch is being worked on, and re-configure when the branch changes. Append "-git" to the package version when the source tree is not tagged at configure time. Get revision numbers and the dirty flag at compile time. Check whether the source code revision exactly matches a tag at compile time. Derive the version suffix from these details. Generate a git-version.h header file which only the version.c source file references. This embeds detailled version information into the library, where it is available at runtime for the library and for applications. And severely speeds up development iterations by avoiding full rebuilds of the whole library when a git commit happened. The dirty flag may either require a manual reconfiguration, or 'make version-clean', if that workspace state is not automatically picked up. Which is considered acceptable for now, because builds for distribution should always start with the configure phase anyway. This uncertainty could only get avoided at the cost of always creating the git-version.h header file in every build invocation. Which would be easy to achieve, but remains for a future commit. The approach was outlined by Martin Ling in 2018-09, see bug #1283. This implementation additionally handles out-of-source builds, uses positive logic for the header inclusion, and handles distribution builds from tarballs or other non-versioned sources (assumes an empty suffix then). Could also handle other sources of version details, or alternative VCS implementations, thus passes more variables than strictly necessary from configuration to compilation. --- diff --git a/.gitignore b/.gitignore index aef631cb..235d51c2 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ /config.* /doxy/ /include/libsigrok/version.h +/include/libsigrok/git-version.h /libsigrok-*.tar.* /libsigrok.pc /libtool diff --git a/Makefile.am b/Makefile.am index dea18734..57c77b38 100644 --- a/Makefile.am +++ b/Makefile.am @@ -25,6 +25,8 @@ GNUMAKEFLAGS = --no-print-directory # distutils/setuptools cause trouble on distcheck. Disable for now. DISTCHECK_CONFIGURE_FLAGS = --disable-python +CLEAN_EXTRA = + FIRMWARE_DIR = $(datadir)/sigrok-firmware local_includes = -Iinclude -I$(srcdir)/include -I$(srcdir)/src -I. @RPC_CFLAGS@ @@ -725,6 +727,35 @@ nodist_library_include_HEADERS = \ include/libsigrok/version.h noinst_HEADERS = src/libsigrok-internal.h +$(builddir)/src/version.lo: $(builddir)/include/libsigrok/git-version.h + +# Create the git-version.h file even for non-versioned source trees, +# to reduce complexity in the library code. Re-create the header file +# when branches change, when revisions change, or upon re-configuration. +# Use the verbatim tagged version number when applicable, or append the +# "-git-[-dirty]" suffix for non-tagged source trees. +if VCS_IS_GIT + +$(builddir)/include/libsigrok/git-version.h: Makefile $(VERSION_GITVERSION_DEPS) + $(AM_V_GEN) \ + HASH=`git -C "$(srcdir)" describe --match "@VERSION_TAG_MATCH@" --always --dirty` && \ + HASH=`echo "$${HASH}" | sed 's/@VERSION_TAG_MATCH@-//'` && \ + SUFFIX=`git -C "$(srcdir)" describe --match "@VERSION_TAG_MATCH@" --exact-match > /dev/null 2> /dev/null || echo "-$${HASH}"` && \ + echo "#undef SR_PACKAGE_VERSION_STRING_SUFFIX" > $@ && \ + echo "#define SR_PACKAGE_VERSION_STRING_SUFFIX \"$${SUFFIX}\"" >> $@ + +else + +$(builddir)/include/libsigrok/git-version.h: + $(AM_V_GEN)echo '#define SR_PACKAGE_VERSION_STRING_SUFFIX ""' > $@ + +endif + +version-clean: + rm -f $(builddir)/include/libsigrok/git-version.h + +CLEAN_EXTRA += version-clean + pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libsigrok.pc @@ -802,7 +833,6 @@ tests_main_LDADD = libsigrok.la $(SR_EXTRA_LIBS) $(TESTS_LIBS) BUILD_EXTRA = INSTALL_EXTRA = UNINSTALL_EXTRA = -CLEAN_EXTRA = libsigrok-uninstall: -rmdir $(DESTDIR)$(includedir)/libsigrok diff --git a/configure.ac b/configure.ac index ea386c0d..5d048860 100644 --- a/configure.ac +++ b/configure.ac @@ -695,6 +695,7 @@ cat >&AS_MESSAGE_FD <<_EOF libsigrok configuration summary: - Package version................. $SR_PACKAGE_VERSION + - Version string suffix .......... $SR_PACKAGE_VERSION_STRING_SUFFIX - Library ABI version............. $SR_LIB_VERSION - Prefix.......................... $prefix - Building on..................... $build diff --git a/include/libsigrok/version.h.in b/include/libsigrok/version.h.in index 1c977bd8..385097e8 100644 --- a/include/libsigrok/version.h.in +++ b/include/libsigrok/version.h.in @@ -20,6 +20,21 @@ #ifndef LIBSIGROK_VERSION_H #define LIBSIGROK_VERSION_H +/* + * Only libsigrok library builds, and only parts of the library build, + * need to reference the git-version.h header file. Which contains the + * version suffix, which is relevant to local development, but is not + * applicable to release builds. Application builds need not bother with + * internal library version details, and always can get this information + * in text form for display purposes from the library at runtime. + */ +#if defined WANT_LIBSIGROK_GIT_VERSION_H +# include +#else +# undef SR_PACKAGE_VERSION_STRING_SUFFIX +# define SR_PACKAGE_VERSION_STRING_SUFFIX "" +#endif + /** * @file * @@ -46,7 +61,10 @@ #undef SR_PACKAGE_VERSION_MICRO /** The libsigrok package version ("major.minor.micro") as string. */ -#undef SR_PACKAGE_VERSION_STRING +#define SR_PACKAGE_VERSION_STRING_PREFIX + +/** The libsigrok package version with git commit suffix. */ +#define SR_PACKAGE_VERSION_STRING (SR_PACKAGE_VERSION_STRING_PREFIX SR_PACKAGE_VERSION_STRING_SUFFIX) /* * Library/libtool version macros (can be used for conditional compilation). diff --git a/m4/sigrok.m4 b/m4/sigrok.m4 index 2ca2444d..5dc29609 100644 --- a/m4/sigrok.m4 +++ b/m4/sigrok.m4 @@ -52,34 +52,48 @@ m4_define([_SR_PKG_VERSION_SET], [dnl m4_assert([$# >= 6])[]dnl $1=$4 +dnl Check if we can get version control details. Re-configure when +dnl branches change (when HEAD starts pointing somewhere else). +dnl Track individual revisions at compile time, and only as a local +dnl dependency of just a part of the library build. In other words: +dnl Don't re-configure and re-build everything just because a commit +dnl happened). Checks for tagged sources also happen at compile time. sr_git_deps= -# Check if we can get revision information from git. sr_head=`git -C "$srcdir" rev-parse --verify --short HEAD 2>&AS_MESSAGE_LOG_FD` - -AS_IF([test "$?" = 0 && test "x$sr_head" != x], [dnl - test ! -f "$srcdir/.git/HEAD" \ - || sr_git_deps="$sr_git_deps \$(top_srcdir)/.git/HEAD" - +AS_IF([test "$?" = 0 && test -n "$sr_head"], [dnl + test ! -f "$srcdir/.git/HEAD" || \ + sr_git_deps="$sr_git_deps ${ac_abs_confdir}/.git/HEAD" sr_head_name=`git -C "$srcdir" rev-parse --symbolic-full-name HEAD 2>&AS_MESSAGE_LOG_FD` - AS_IF([test "$?" = 0 && test -f "$srcdir/.git/$sr_head_name"], - [sr_git_deps="$sr_git_deps \$(top_srcdir)/.git/$sr_head_name"]) - - # Append the revision hash unless we are exactly on a tagged release. - git -C "$srcdir" describe --match "$3$4" \ - --exact-match >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD \ - || $1="[$]$1-git-$sr_head" + AS_IF([test "$?" = 0 && test -f "$srcdir/.git/$sr_head_name"], [dnl + sr_head_file="${ac_abs_confdir}/.git/$sr_head_name" + AC_SUBST(VERSION_HEAD_FILE, [$sr_head_file]) + ]) + sr_hash=`git -C "$srcdir" describe --match "$3$4" --always --dirty` + sr_hash=`echo "$sr_hash" | sed 's/$3$4-//'` && \ + $1_STRING_SUFFIX=`git -C "$srcdir" describe --match "$3$4" --exact-match > /dev/null 2> /dev/null || echo "-$sr_hash"` + AS_IF([test -n "$1_STRING_SUFFIX"], [$1="[$]$1-git"]) ]) -# Use $(wildcard) so that things do not break if for whatever -# reason these files do not exist anymore at make time. +AM_CONDITIONAL([VCS_IS_GIT], [test -n "$sr_git_deps"]) +# Use $(wildcard) so that things do not break if for whatever reason +# these files do not exist anymore at make time. AS_IF([test -n "$sr_git_deps"], - [SR_APPEND([CONFIG_STATUS_DEPENDENCIES], ["\$(wildcard$sr_git_deps)"])]) + [SR_APPEND([CONFIG_STATUS_DEPENDENCIES], ["\$(wildcard $sr_git_deps)"])]) AC_SUBST([CONFIG_STATUS_DEPENDENCIES])[]dnl +AS_IF([test -n "$sr_git_deps$sr_head_file"], + [SR_APPEND([VERSION_GITVERSION_DEPS], ["\$(wildcard $sr_git_deps $sr_head_file)"])]) +AC_SUBST(VERSION_GITVERSION_DEPS)[]dnl +AC_SUBST(VERSION_SOURCE_DIR, [${ac_abs_confdir}]) +AC_SUBST(VERSION_TAG_PREFIX, [$3])[]dnl +AC_SUBST(VERSION_TAG_NUMBER, [$4])[]dnl +AC_SUBST(VERSION_TAG_MATCH, [$3$4])[]dnl +dnl End of git version control details gathering. +dnl AC_SUBST([$1])[]dnl dnl AC_DEFINE([$1_MAJOR], [$5], [Major version number of $2.])[]dnl AC_DEFINE([$1_MINOR], [$6], [Minor version number of $2.])[]dnl m4_ifval([$7], [AC_DEFINE([$1_MICRO], [$7], [Micro version number of $2.])])[]dnl -AC_DEFINE_UNQUOTED([$1_STRING], ["[$]$1"], [Version of $2.])[]dnl +AC_DEFINE_UNQUOTED([$1_STRING_PREFIX], ["[$]$1"], [Version of $2.])[]dnl ]) ## SR_PKG_VERSION_SET(var-prefix, version-triple) diff --git a/src/version.c b/src/version.c index 402c7ca6..912aedad 100644 --- a/src/version.c +++ b/src/version.c @@ -18,6 +18,9 @@ */ #include + +/* Request inclusion of the git version suffix in version.h. */ +#define WANT_LIBSIGROK_GIT_VERSION_H #include /**