]> sigrok.org Git - libsigrok.git/commitdiff
make: move version suffix gathering from configure to compile time
authorGerhard Sittig <redacted>
Sat, 18 Mar 2023 16:18:15 +0000 (17:18 +0100)
committerGerhard Sittig <redacted>
Sun, 9 Apr 2023 22:41:39 +0000 (00:41 +0200)
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.

.gitignore
Makefile.am
configure.ac
include/libsigrok/version.h.in
m4/sigrok.m4
src/version.c

index aef631cb3d195ede4041d93c8dad3d53e42df1a6..235d51c2c95773d6ec2bd1046df274cbb4653b58 100644 (file)
@@ -30,6 +30,7 @@
 /config.*
 /doxy/
 /include/libsigrok/version.h
+/include/libsigrok/git-version.h
 /libsigrok-*.tar.*
 /libsigrok.pc
 /libtool
index dea187344335dce455dc128359c0c01c65b093af..57c77b3860d16df45aeebfb8e9aca7b70e7bc13e 100644 (file)
@@ -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-<hash>[-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
index ea386c0d3270b7d2946a471fb60a528ecf56fe98..5d0488602bbdd792bf37a31b2aaf089720fdd224 100644 (file)
@@ -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
index 1c977bd854766e5a828092024309baa2a775d84b..385097e81e58b7837972817560c94674d04d1987 100644 (file)
 #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 <libsigrok/git-version.h>
+#else
+#  undef SR_PACKAGE_VERSION_STRING_SUFFIX
+#  define SR_PACKAGE_VERSION_STRING_SUFFIX ""
+#endif
+
 /**
  * @file
  *
 #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).
index 2ca2444dfddf813abe3d26b94ed3d4d64c5d412f..5dc296090623b85c6ab1bbed484f8c448f582d53 100644 (file)
@@ -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)
index 402c7ca6093f36c9def1b1617cab190127e55819..912aedad30d91f5318251f9cf2cb14f8f472fea4 100644 (file)
@@ -18,6 +18,9 @@
  */
 
 #include <config.h>
+
+/* Request inclusion of the git version suffix in version.h. */
+#define WANT_LIBSIGROK_GIT_VERSION_H
 #include <libsigrok/libsigrok.h>
 
 /**