Skip to content

Commit

Permalink
Merge pull request #2554 from jimklimov/issue-1949
Browse files Browse the repository at this point in the history
Provide a single script for Git-based version with `configure` and `nut_version.h` contexts
  • Loading branch information
jimklimov authored Jul 27, 2024
2 parents 273572b + 88fdc82 commit 4503f23
Show file tree
Hide file tree
Showing 14 changed files with 459 additions and 22 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
/_install_pkgprotodir/
Makefile
Makefile.in

## Parent directory only
/aclocal.m4
/ar-lib
Expand Down Expand Up @@ -43,6 +44,9 @@ Makefile.in
/README
/TODO
/UPGRADING
/VERSION_DEFAULT
/VERSION_FORCED
/VERSION_FORCED_SEMVER
/install-sh
/libtool
/ltmain.sh
Expand Down
9 changes: 9 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,15 @@ maintainer-asciidocs:
check-NIT check-NIT-devel:
+cd $(builddir)/tests/NIT && $(MAKE) $(AM_MAKEFLAGS) $@

VERSION_DEFAULT: dummy-stamp
@abs_top_srcdir='$(abs_top_srcdir)' ; \
abs_top_builddir='$(abs_top_builddir)' ; \
export abs_top_srcdir ; export abs_top_builddir ; \
NUT_VERSION_QUERY=UPDATE_FILE '$(abs_top_srcdir)/tools/gitlog2version.sh'

CLEANFILES += VERSION_DEFAULT.tmp
EXTRA_DIST += VERSION_DEFAULT

# This target adds syntax-checking for committed shell script files,
# to avoid surprises and delays in finding fatal typos after packaging
###
Expand Down
14 changes: 14 additions & 0 deletions NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,20 @@ https://github.com/networkupstools/nut/milestone/11
bug is ancient, it took recent development to hit it as a practical
regression. [issue #1904, issue #2484]
- development iterations of NUT should now identify with not only the semantic
version of a preceding release, but with git-derived information about the
amount of iterations that followed (if available): the three-number "semver"
would be seen on release snapshots, while other builds would expose the
added components: one with the amount of commits on the main development
trunk since the preceding release which are ancestors of the built code
base, and in case of feature development branches -- another component
with the amount of commits unique to this branch (which are not part of
the development trunk). This allows to produce more relevant (monotonously
growing) version identifiers for packages and similar artifacts, with more
meaningful upgrades via development snapshots, eventually. A copy of the
current version information would be embedded into "dist" archives as a
`VERSION_DEFAULT` file. [#1949]
- drivers, `upsd`, `upsmon`: reduce "scary noise" about failure to `fopen()`
the PID file (which most of the time means that no previous instance of
the daemon was running to potentially conflict with), especially useless
Expand Down
18 changes: 18 additions & 0 deletions UPGRADING.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,24 @@ Changes from 2.8.2 to 2.8.3

- PLANNED: Keep track of any further API clean-up?
- NUT development snapshots can now have more version components than the
standard semantic versioning triplet, optionally adding the amount of
commits on the development trunk since previous release, and the amount
of commits on a feature branch that are unique to it. Release artifacts
that have zeroes in both positions would have them stripped and still
have the standard "semver" exposed, but the development snapshots can
now be more reasonably upgraded with automated tooling. A copy of the
current version information would be embedded into "dist" archives as
a `VERSION_DEFAULT` file, so it can be used without git. Certain distros
can benefit from a `VERSION_FORCED` file or a `NUT_VERSION_FORCED`
environment variable exported from their build system, e.g. via
`echo NUT_VERSION_FORCED=1.1.1 > VERSION_FORCED`. Unfortunately, some
appliances tag all software the same with their firmware version;
if this is required, a (NUT_)VERSION_FORCED_SEMVER envvar or file can
help identify the actual NUT release version triplet used on the box.
Please use it, it immensely helps with community troubleshooting!
[issue #1949]
- `usbhid-ups` subdriver `PowerCOM HID` subdriver sent UPS `shutdown` and
`stayoff` commands in wrong byte order, at least for devices currently
in the field. Driver now sends the commands in a way that satisfies new
Expand Down
14 changes: 14 additions & 0 deletions autogen.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ else
DEBUG=false
fi

NUT_VERSION_QUERY=UPDATE_FILE "`dirname $0`"/tools/gitlog2version.sh

if [ -n "${PYTHON-}" ] ; then
# May be a name/path of binary, or one with args - check both
(command -v "$PYTHON") \
Expand Down Expand Up @@ -165,6 +167,18 @@ fi >&2
[ -f NEWS ] || { echo "Please see NEWS.adoc for actual contents" > NEWS; }
[ -f README ] || { echo "Please see README.adoc for actual contents" > README; }

# Try to serve a fresh one at least when we remake from scratch like this
# Note to not do it forcefully during `configure` or rebuild
rm -f include/nut_version.h || true

echo "----------------------------------------------------------------------"
echo "Please note that on some systems the routine below can complain that "
echo " > configure.ac: warning: AC_INIT: not a literal: m4_esyscmd_s(...)"
echo "but still does the right thing about PACKAGE_VERSION and PACKAGE_URL settings."
echo "Check if your distro provides an 'autoconf-archive' package anf if it helps."
echo "Please post an issue in NUT bug tracker with platform details if it does not."
echo "----------------------------------------------------------------------"

echo "Calling autoreconf..."
AUTOTOOL_RES=0
if $DEBUG ; then
Expand Down
2 changes: 1 addition & 1 deletion ci_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ check_gitignore() {
# reported by `git status -- '*'` and not hidden.
[ -n "${FILE_GLOB-}" ] || FILE_GLOB="'*'"
# Always filter these names away:
FILE_GLOB_EXCLUDE="':!.ci*.log*'"
FILE_GLOB_EXCLUDE="':!.ci*.log*' ':!VERSION_DEFAULT' ':!VERSION_FORCED*'"
[ -n "${GIT_ARGS-}" ] || GIT_ARGS='' # e.g. GIT_ARGS="--ignored"
# Display contents of the diff?
# (Helps copy-paste from CI logs to source to amend quickly)
Expand Down
47 changes: 39 additions & 8 deletions common/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ static int upsnotify_report_verbosity = -1;

/* the reason we define UPS_VERSION as a static string, rather than a
macro, is to make dependency tracking easier (only common.o depends
on nut_version_macro.h), and also to prevent all sources from
on nut_version.h), and also to prevent all sources from
having to be recompiled each time the version changes (they only
need to be re-linked). */
#include "nut_version.h"
Expand Down Expand Up @@ -2103,7 +2103,9 @@ void nut_report_config_flags(void)
* Depending on amount of configuration tunables involved by a particular
* build of NUT, the string can be quite long (over 1KB).
*/
#if 0
const char *acinit_ver = NULL;
#endif
/* Pass these as variables to avoid warning about never reaching one
* of compiled codepaths: */
const char *compiler_ver = CC_VERSION;
Expand All @@ -2113,6 +2115,7 @@ void nut_report_config_flags(void)
if (nut_debug_level < 1)
return;

#if 0
/* Only report git revision if NUT_VERSION_MACRO in nut_version.h aka
* UPS_VERSION here is remarkably different from PACKAGE_VERSION from
* configure.ac AC_INIT() -- which may be e.g. "2.8.0.1" although some
Expand All @@ -2130,7 +2133,14 @@ void nut_report_config_flags(void)
* especially embedders, tend to place their product IDs here),
* or if PACKAGE_VERSION *is NOT* a substring of it: */
acinit_ver = PACKAGE_VERSION;
/*
// Triplet that was printed below:
(acinit_ver ? " (release/snapshot of " : ""),
(acinit_ver ? acinit_ver : ""),
(acinit_ver ? ")" : ""),
*/
}
#endif

/* NOTE: If changing wording here, keep in sync with configure.ac logic
* looking for CONFIG_FLAGS_DEPLOYED via "configured with flags:" string!
Expand All @@ -2147,14 +2157,28 @@ void nut_report_config_flags(void)
now.tv_sec -= 1;
}

#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic push
#endif
#ifdef HAVE_PRAGMA_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic ignored "-Wunreachable-code"
#endif
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunreachable-code"
#endif
/* NOTE: Some compilers deduce that macro-based decisions about
* NUT_VERSION_IS_RELEASE make one of codepaths unreachable in
* a particular build. So we pragmatically handwave this away.
*/
if (xbit_test(upslog_flags, UPSLOG_STDERR)) {
fprintf(stderr, "%4.0f.%06ld\t[D1] Network UPS Tools version %s%s%s%s%s%s%s %s%s\n",
difftime(now.tv_sec, upslog_start.tv_sec),
(long)(now.tv_usec - upslog_start.tv_usec),
UPS_VERSION,
(acinit_ver ? " (release/snapshot of " : ""),
(acinit_ver ? acinit_ver : ""),
(acinit_ver ? ")" : ""),
NUT_VERSION_IS_RELEASE ? " release" : " (development iteration after ",
NUT_VERSION_IS_RELEASE ? "" : NUT_VERSION_SEMVER_MACRO,
NUT_VERSION_IS_RELEASE ? "" : ")",
(compiler_ver && *compiler_ver != '\0' ? " built with " : ""),
(compiler_ver && *compiler_ver != '\0' ? compiler_ver : ""),
(compiler_ver && *compiler_ver != '\0' ? " and" : ""),
Expand All @@ -2168,18 +2192,25 @@ void nut_report_config_flags(void)

/* NOTE: May be ignored or truncated by receiver if that syslog server
* (and/or OS sender) does not accept messages of such length */
if (xbit_test(upslog_flags, UPSLOG_SYSLOG))
if (xbit_test(upslog_flags, UPSLOG_SYSLOG)) {
syslog(LOG_DEBUG, "Network UPS Tools version %s%s%s%s%s%s%s %s%s",
UPS_VERSION,
(acinit_ver ? " (release/snapshot of " : ""),
(acinit_ver ? acinit_ver : ""),
(acinit_ver ? ")" : ""),
NUT_VERSION_IS_RELEASE ? " release" : " (development iteration after ",
NUT_VERSION_IS_RELEASE ? "" : NUT_VERSION_SEMVER_MACRO,
NUT_VERSION_IS_RELEASE ? "" : ")",
(compiler_ver && *compiler_ver != '\0' ? " built with " : ""),
(compiler_ver && *compiler_ver != '\0' ? compiler_ver : ""),
(compiler_ver && *compiler_ver != '\0' ? " and" : ""),
(config_flags && *config_flags != '\0' ? "configured with flags: " : "configured all by default guesswork"),
(config_flags && *config_flags != '\0' ? config_flags : "")
);
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif
#ifdef HAVE_PRAGMAS_FOR_GCC_DIAGNOSTIC_IGNORED_UNREACHABLE_CODE
#pragma GCC diagnostic pop
#endif
}

static void vupslog(int priority, const char *fmt, va_list va, int use_strerror)
Expand Down
58 changes: 50 additions & 8 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,31 @@ dnl +------------------------------------------------------------------+
dnl | Network UPS Tools: configure.ac |
dnl +------------------------------------------------------------------+

dnl # Support for older autoconf without m4_esyscmd_s
m4_ifndef([m4_chomp_all], [m4_define([m4_chomp_all], [m4_format([[%.*s]], m4_bregexp(m4_translit([[$1]], [/], [/ ]), [/*$]), [$1])])])
m4_ifndef([m4_esyscmd_s], [m4_define([m4_esyscmd_s], [m4_chomp_all(m4_esyscmd([$1]))])])

dnl NUT version number is defined here, with a Git suffixed macro like
dnl NUT_VERSION_MACRO "2.7.4-2838-gdfc3ac08"
dnl in include/nut_version.h (generated by make)
AC_INIT([nut],[2.8.2.1],[https://github.com/networkupstools/nut/issues],[nut],[https://networkupstools.org/])
dnl defined separately in include/nut_version.h (generated by make)
dnl ...or not defined, for quicker rebuilds, depending on settings.
dnl Old hard-coded approach (mangled a bit):
dnl AC INIT([nut],[2.8.2.1],[https://github.com/networkupstools/nut/issues])
dnl Note: srcdir is only set after AC INIT has completed, but $0 points
dnl to the generated configure script which is part of dist tarball and
dnl should be at source root too.
dnl Note: this gets evaluated (script called) a lot of times during autoconf
dnl but ends up as static strings in the generated configure script. It may
dnl be beneficial to have a `version.m4` generated by `autogen.sh` and/or
dnl shipped in a tarball, allowing for a singular include into configure.ac
dnl See https://github.com/networkupstools/nut/issues/1949 for details.
dnl Oddly, autoconf-2.69 on CentOS 7 both complains that AC INIT argument
dnl is not a literal, and does contain expected values in the generated
dnl script and include/config.h. A "pure" m4 solution would be quieter.
AC_INIT([nut],
m4_esyscmd_s([NUT_VERSION_QUERY=VER50 "`dirname "$0"`/tools/gitlog2version.sh" 2>/dev/null]),
[https://github.com/networkupstools/nut/issues],[nut],
m4_esyscmd_s([NUT_VERSION_QUERY=URL "`dirname "$0"`/tools/gitlog2version.sh" 2>/dev/null]))
dnl See docs/maintainer-guide.txt about releases - updating the version
dnl above is a small part of the consistent ritual!

Expand All @@ -15,12 +36,25 @@ dnl the PDF documentation revision history via docs/docinfo.xml.in).
dnl If the NUT codebase in this workspace is being developed and rebuilt
dnl without reconfiguration, detailed version in the binaries will differ
dnl (that one comes from the NUT_VERSION_MACRO from nut_version.h file).
(command -v git >/dev/null 2>/dev/null) \
&& NUT_SOURCE_GITREV="`(git describe --tags --match 'v@<:@0-9@:>@*.@<:@0-9@:>@*.@<:@0-9@:>@' --exclude '*-signed' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' 2>/dev/null || git describe --tags --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' --exclude '*Windows*' --exclude '*IPM*' 2>/dev/null ) | sed -e 's/^v\(@<:@0-9@:>@\)/\1/' -e 's,^.*/,,'`" \
|| NUT_SOURCE_GITREV=""
dnl # Example: NUT_SOURCE_GITREV='2.8.2.695.1-696-g0e00f0777'
NUT_SOURCE_GITREV="`NUT_VERSION_QUERY=DESC50 "${srcdir}/tools/gitlog2version.sh" 2>/dev/null`"

dnl A true/false (literally) response that can be used for prettier messages
dnl emitted by NUT code.
NUT_SOURCE_GITREV_IS_RELEASE="`NUT_VERSION_QUERY=IS_RELEASE "${srcdir}/tools/gitlog2version.sh" 2>/dev/null`"
AS_IF([$NUT_SOURCE_GITREV_IS_RELEASE], [NUT_SOURCE_GITREV_DEVREL="release"], [NUT_SOURCE_GITREV_DEVREL="development iteration"])

dnl Semantic version of most-recent NUT release this code is derived from.
dnl It may equal the NUT_SOURCE_GITREV and NUT_SOURCE_GITREV_NUMERIC, but
dnl this situation is only expected if NUT_SOURCE_GITREV_IS_RELEASE==true.
NUT_SOURCE_GITREV_SEMVER="`NUT_VERSION_QUERY=SEMVER "${srcdir}/tools/gitlog2version.sh" 2>/dev/null`"

dnl Gitrev-based build identifier which can be used for e.g. PyPI uploads:
NUT_SOURCE_GITREV_NUMERIC="`echo "${NUT_SOURCE_GITREV}" | sed -e 's/^v//' -e 's/-g.*$//' -e 's/-/./g'`"
dnl # Example: NUT_SOURCE_GITREV_NUMERIC='2.8.2.695.1.696'
dnl # NUT_SOURCE_GITREV_NUMERIC="`echo "${NUT_SOURCE_GITREV}" | sed -e 's/^v//' -e 's/-g.*$//' -e 's/-/./g'`"
dnl # Without the commit-count since tag (dash-separated part):
dnl # Example: NUT_SOURCE_GITREV_NUMERIC='2.8.2.695.1'
NUT_SOURCE_GITREV_NUMERIC="`echo "${NUT_SOURCE_GITREV}" | sed -e 's/^v//' -e 's/-g.*$//' -e 's/-@<:@0-9@:>@*$//'`"

dnl Note: except for experiments, do not pass this into config.h - use
dnl the NUT_VERSION_MACRO from nut_version.h instead. Developers may
Expand Down Expand Up @@ -81,7 +115,10 @@ AC_CONFIG_SRCDIR(server/upsd.c)
AC_CONFIG_MACRO_DIR([m4])
AS_IF([test x"${NUT_SOURCE_GITREV}" = x],
[echo "Network UPS Tools version ${PACKAGE_VERSION}"],
[echo "Network UPS Tools version ${PACKAGE_VERSION} (${NUT_SOURCE_GITREV})"])
[AS_IF([test x"${NUT_SOURCE_GITREV}" = x"${PACKAGE_VERSION}"],
[echo "Network UPS Tools version ${PACKAGE_VERSION} ${NUT_SOURCE_GITREV_DEVREL}"],
[echo "Network UPS Tools version ${PACKAGE_VERSION} (${NUT_SOURCE_GITREV}) ${NUT_SOURCE_GITREV_DEVREL}"])
])
AC_CANONICAL_TARGET
NUT_CHECK_OS
NUT_STASH_WARNINGS
Expand Down Expand Up @@ -676,7 +713,10 @@ NUT_ARG_ENABLE([keep_nut_report_feature],

AS_IF([test x"${NUT_SOURCE_GITREV}" = x],
[NUT_REPORT([configured version], [${PACKAGE_VERSION}])],
[NUT_REPORT([configured version], [${PACKAGE_VERSION} (${NUT_SOURCE_GITREV})])])
[AS_IF([test x"${NUT_SOURCE_GITREV}" = x"${PACKAGE_VERSION}"],
[NUT_REPORT([configured version], [${PACKAGE_VERSION} ${NUT_SOURCE_GITREV_DEVREL}])],
[NUT_REPORT([configured version], [${PACKAGE_VERSION} (${NUT_SOURCE_GITREV}) ${NUT_SOURCE_GITREV_DEVREL}])])
])

dnl Note: the compiler/pragma/attr methods below are custom for NUT codebase:
NUT_COMPILER_FAMILY
Expand Down Expand Up @@ -4684,6 +4724,8 @@ AC_SUBST(TREE_VERSION)
AC_SUBST(NUT_NETVERSION)
AC_SUBST(FORCE_NUT_VERSION)
AC_SUBST(NUT_SOURCE_GITREV)
AC_SUBST(NUT_SOURCE_GITREV_IS_RELEASE)
AC_SUBST(NUT_SOURCE_GITREV_SEMVER)
AC_SUBST(NUT_SOURCE_GITREV_NUMERIC)
AC_SUBST(LIBSSL_CFLAGS)
AC_SUBST(LIBSSL_LIBS)
Expand Down
14 changes: 14 additions & 0 deletions docs/config-prereqs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,20 @@ actual package source versions on both Debian 8 "Jessie" and
Debian 11 "Buster").
======

[NOTE]
.FUN NOTE
======
For development on the road (or a native ARM build) you can use the
link:https://termux.dev/en/[Termux] project on Android. It provides
a sufficiently Debian-like operating environment for all intents and
purposes, but you may have to use their `pkg` wrapper instead of `apt`
tooling directly.

You would need at least a couple of gigabytes available on the internal
phone storage though, especially if using `ccache` or setting up cross
builds.
======

Debian-like package installations commonly start with an update of
metadata about recently published package revisions:

Expand Down
3 changes: 2 additions & 1 deletion docs/nut.dict
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
personal_ws-1.1 en 3198 utf-8
personal_ws-1.1 en 3199 utf-8
AAC
AAS
ABI
Expand Down Expand Up @@ -2724,6 +2724,7 @@ securityLevel
securityName
sed
selftest
semver
sendback
sendline
sendmail
Expand Down
15 changes: 13 additions & 2 deletions include/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ MAINTAINERCLEANFILES = Makefile.in .dirstamp
# (for builds not made from the tagged commit in a Git workspace)

nut_version.h: @FORCE_NUT_VERSION@
@GITREV="`git describe --tags --match 'v[0-9]*.[0-9]*.[0-9]' --exclude '*-signed' --exclude '*rc*' --exclude '*alpha*' --exclude '*beta*' 2>/dev/null | sed -e 's/^v\([0-9]\)/\1/' -e 's,^.*/,,'`" || GITREV=""; \
@GITREV="`$(top_srcdir)/tools/gitlog2version.sh`" || GITREV=""; \
GITREV_IS_RELEASE="`NUT_VERSION_QUERY=IS_RELEASE $(top_srcdir)/tools/gitlog2version.sh 2>/dev/null`" || GITREV_IS_RELEASE="false"; \
GITREV_SEMVER="`NUT_VERSION_QUERY=SEMVER $(top_srcdir)/tools/gitlog2version.sh 2>/dev/null`" || GITREV_SEMVER=""; \
{ echo '/* Autogenerated file. Do not change. */' ; \
echo '/* This file was generated by "make". */' ; \
if [ -z "$$GITREV" ]; then \
Expand All @@ -45,9 +47,18 @@ nut_version.h: @FORCE_NUT_VERSION@
echo ' * building the newest tagged commit itself - then just the tag).'; \
echo ' */' ; \
fi ; \
if [ -z "$$GITREV_SEMVER" ]; then \
GITREV_SEMVER="@NUT_SOURCE_GITREV_SEMVER@"; \
fi ; \
echo "#define NUT_VERSION_MACRO \"$$NUT_VERSION\"" ; \
echo "#define NUT_VERSION_SEMVER_MACRO \"$$GITREV_SEMVER\"" ; \
if $$GITREV_IS_RELEASE ; then \
echo "#define NUT_VERSION_IS_RELEASE 1" ; \
else \
echo "#define NUT_VERSION_IS_RELEASE 0" ; \
fi ; \
} > "$@.tmp" ; \
echo "NUT_VERSION: \"$$NUT_VERSION\""
echo "NUT_VERSION: \"$$NUT_VERSION\" NUT_VERSION_IS_RELEASE:$$GITREV_IS_RELEASE NUT_VERSION_SEMVER: \"$$GITREV_SEMVER\""
-test -f "$@" || cp "$@.tmp" "$@"
-cmp -s "$@.tmp" "$@" || cp "$@.tmp" "$@"
-rm -f "$@.tmp"
Expand Down
2 changes: 1 addition & 1 deletion tools/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ SUBDIRS = . nut-scanner nutconf
PYTHON = @PYTHON@

EXTRA_DIST = nut-usbinfo.pl nut-recorder.sh nut-ddl-dump.sh nut-dumpdiff.sh \
gitlog2changelog.py.in nut-snmpinfo.py.in driver-list-format.sh
gitlog2changelog.py.in gitlog2version.sh nut-snmpinfo.py.in driver-list-format.sh

# These files are generated for nut-scanner builds (and cleaned as any others),
# and can change as respective SNMP/USB subdriver sources are iterated by a
Expand Down
Loading

0 comments on commit 4503f23

Please sign in to comment.