Simon Josefsson wrote: > > Maybe a doc/git-version-gen.texi is the answer here... and thinking > > through the concepts a bit more.
I replied: > Let me start doing that. > ... > Next, what are the problems? Spent the day thinking through the concepts and fixing all the problems. * The comment about .version in git-version-gen was misplaced. .version is unrelated to git-version-gen; in fact, it is possible to use git-version-gen without a .version. * The description of .tarball-version was wrong: "present only in a distribution tarball, and not in a checked-out repository." Wrong because when the maintainer wants to make a release with a specific version number, they do that by creating .tarball-version in their git checkout. * The recommendation to use git-version-gen via m4_esyscmd was wrong, because the goal of that snippet is described as "Use the following line in your configure.ac, so that $(VERSION) will automatically be up-to-date each time configure is run" and what the snippet actually does is to invoke git-version-gen when autoconf is run, not when configure is run. * The Makefile.am snippet with dist-hook was misleading, because one could think that it creates the file $(top_srcdir)/.tarball-version (which it doesn't — fortunately). * The Makefile.am snippet regarding .version was wrong on multiple accounts: 1) Since the purpose of this file is to be a stamp file, it needs to be updated when the value of $(VERSION) in config.status has changed. This was not done, and this was the cause for the several out-of-date version references in the past releases of coreutils and gettext. 2) Since the moment $(VERSION) can change is when config.status is regenerated, it would be overkill to check for this situation in a Makefile rule. The relevant moment for checking it is when config.status is being run. 2025-01-22 Bruno Haible <br...@clisp.org> doc: Document the workflows of the .tarball-version and .version files. * doc/package-version.texi: New file. * doc/gnulib.texi (Build Infrastructure Modules): Include it. * build-aux/git-version-gen: Fix comments: Fix description of .tarball-version. Recommend to invoke git-version-gen at configure time, not at autoconf time. Remove description of .version. Rename Makefile target 'tarball-version' to 'dist-tarball-version'. * top/GNUmakefile: Improve comments. 2025-01-22 Bruno Haible <br...@clisp.org> New module 'version-stamp'. * m4/version-stamp.m4: New file. * modules/version-stamp: New file. 2025-01-22 Bruno Haible <br...@clisp.org> New module 'package-version'. * m4/init-package-version.m4: New file, from GNU libunistring. * modules/package-version: New file. * modules/git-version-gen (Depends-on): Add it.
>From e518788ad085e02b046e42889039a1f671e4619a Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Wed, 22 Jan 2025 21:21:59 +0100 Subject: [PATCH 1/3] New module 'package-version'. * m4/init-package-version.m4: New file, from GNU libunistring. * modules/package-version: New file. * modules/git-version-gen (Depends-on): Add it. --- ChangeLog | 7 +++ m4/init-package-version.m4 | 124 +++++++++++++++++++++++++++++++++++++ modules/git-version-gen | 1 + modules/package-version | 19 ++++++ 4 files changed, 151 insertions(+) create mode 100644 m4/init-package-version.m4 create mode 100644 modules/package-version diff --git a/ChangeLog b/ChangeLog index 7c402b5a0b..87087d2d3b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2025-01-22 Bruno Haible <br...@clisp.org> + + New module 'package-version'. + * m4/init-package-version.m4: New file, from GNU libunistring. + * modules/package-version: New file. + * modules/git-version-gen (Depends-on): Add it. + 2025-01-19 Bruno Haible <br...@clisp.org> attribute: Add note about ongoing standardization of some attributes. diff --git a/m4/init-package-version.m4 b/m4/init-package-version.m4 new file mode 100644 index 0000000000..525dfe5bf5 --- /dev/null +++ b/m4/init-package-version.m4 @@ -0,0 +1,124 @@ +# init-package-version.m4 +# serial 3 +dnl Copyright (C) 1992-2025 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +# Make it possible to pass version numbers extracted from a file in +# $(srcdir) to autoconf. +# +# Autoconf insists on passing the package name and version number to +# every generated .h file and every Makefile. This was a reasonable +# design at times when a version number was changed only once a month. +# Nowadays, people often assign a new version number once a week, or +# even change it each time a 'git' commit is made. Regenerating all +# the files that depend on configure.ac (aclocal.m4, configure, +# config.status, config.h, all Makefiles) may take 15 minutes. These +# delays can severely hamper development. +# +# An alternative is to store the version number in a file in $(srcdir) +# that is separate from configure.ac. It can be a data file, a shell +# script, a .m4 file, or other. The essential point is that the maintainer +# is responsible for creating Makefile dependencies to this version file +# for every file that needs to be rebuilt when the version changes. This +# typically includes +# - distributable documentation files that carry the version number, +# but does not include +# - aclocal.m4, configure, config.status, config.h, all Makefiles, +# - executables. +# +# autoconf and automake make it hard to follow this approach: +# +# - If AC_INIT is used with arguments, there is a chicken-and-egg problem: +# The arguments need to be read from a file in $(srcdir). The location +# of $(srcdir) is only determined by AC_CONFIG_SRCDIR. AC_CONFIG_SRCDIR +# can only appear after AC_INIT (otherwise aclocal gives an error: +# "error: m4_defn: undefined macro: _m4_divert_diversion"). +# Furthermore, the arguments passed to AC_INIT must be literals; for +# example, the assignment to PACKAGE_VERSION looks like this: +# [PACKAGE_VERSION=']AC_PACKAGE_VERSION['] +# +# - If AC_INIT is used without arguments: +# Automake provides its own variables, PACKAGE and VERSION, and uses them +# instead of PACKAGE_NAME and PACKAGE_VERSION that come from Autoconf. +# - If AM_INIT_AUTOMAKE is used with two arguments, automake options +# like 'silent-rules' cannot be specified. +# - If AM_INIT_AUTOMAKE is used in its one-argument form or without +# arguments at all, it triggers an error +# "error: AC_INIT should be called with package and version arguments". +# - If AM_INIT_AUTOMAKE is used in its one-argument form or without +# arguments at all, and _AC_INIT_PACKAGE is used before it, with +# the package and version number from the file as arguments, we get +# a warning: "warning: AC_INIT: not a literal: $VERSION_NUMBER". +# The arguments passed to _AC_INIT_PACKAGE must be literals. +# +# With the macro defined in this file, the approach can be coded like this: +# +# AC_INIT +# AC_CONFIG_SRCDIR(WITNESS) +# . $srcdir/../version.sh +# gl_INIT_PACKAGE(PACKAGE, $VERSION_NUMBER) +# AM_INIT_AUTOMAKE([OPTIONS]) +# +# and after changing version.sh, the developer can directly configure and build: +# +# make distclean +# ./configure +# make +# +# Some other packages use another approach: +# +# AC_INIT(PACKAGE, +# m4_normalize(m4_esyscmd([. ./version.sh; echo $VERSION_NUMBER]))) +# AC_CONFIG_SRCDIR(WITNESS) +# AM_INIT_AUTOMAKE([OPTIONS]) +# +# but here, after changing version.sh, the developer must first regenerate the +# configure file: +# +# make distclean +# ./autogen.sh --skip-gnulib +# ./configure +# make +# + +# gl_INIT_PACKAGE(PACKAGE-NAME, VERSION) +# -------------------------------------- +# followed by an AM_INIT_AUTOMAKE invocation, +# is like calling AM_INIT_AUTOMAKE(PACKAGE-NAME, VERSION) +# except that it can use computed non-literal arguments. +AC_DEFUN([gl_INIT_PACKAGE], +[ + AC_BEFORE([$0], [AM_INIT_AUTOMAKE]) + dnl Redefine AM_INIT_AUTOMAKE. + m4_define([gl_AM_INIT_AUTOMAKE], + m4_bpatsubst(m4_dquote( + m4_bpatsubst(m4_dquote( + m4_bpatsubst(m4_dquote( + m4_defn([AM_INIT_AUTOMAKE])), + [AC_PACKAGE_NAME], [gl_INIT_DUMMY])), + [AC_PACKAGE_TARNAME], [gl_INIT_EMPTY])), + [AC_PACKAGE_VERSION], [gl_INIT_DUMMY]) + [AC_SUBST([PACKAGE], [$1]) + AC_SUBST([VERSION], [$2]) + ]) + m4_define([AM_INIT_AUTOMAKE], + m4_defn([gl_RPL_INIT_AUTOMAKE])) +]) +m4_define([gl_INIT_EMPTY], []) +dnl Automake 1.16.4 no longer accepts an empty value for gl_INIT_DUMMY. +dnl But a macro that later expands to empty works. +m4_define([gl_INIT_DUMMY], [gl_INIT_DUMMY2]) +m4_define([gl_INIT_DUMMY2], []) +AC_DEFUN([gl_RPL_INIT_AUTOMAKE], [ + m4_ifval([$2], + [m4_fatal([After gl_INIT_PACKAGE, the two-argument form of AM_INIT_AUTOMAKE cannot be used.])]) + gl_AM_INIT_AUTOMAKE([$1 no-define]) + m4_if(m4_index([ $1 ], [ no-define ]), [-1], + [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package]) + ]) +]) diff --git a/modules/git-version-gen b/modules/git-version-gen index a783ac570d..ee02ef4ee5 100644 --- a/modules/git-version-gen +++ b/modules/git-version-gen @@ -5,6 +5,7 @@ Files: build-aux/git-version-gen Depends-on: +package-version configure.ac: diff --git a/modules/package-version b/modules/package-version new file mode 100644 index 0000000000..fafa8b058a --- /dev/null +++ b/modules/package-version @@ -0,0 +1,19 @@ +Description: +Support for a computed version string. + +Files: +m4/init-package-version.m4 + +Depends-on: + +configure.ac: + +Makefile.am: + +Include: + +License: +GPLed build tool + +Maintainer: +Bruno Haible -- 2.43.0
>From 85599643e2fbf70f7f0bd58831993132ef335705 Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Wed, 22 Jan 2025 21:25:27 +0100 Subject: [PATCH 2/3] New module 'version-stamp'. * m4/version-stamp.m4: New file. * modules/version-stamp: New file. --- ChangeLog | 6 ++++++ m4/version-stamp.m4 | 35 +++++++++++++++++++++++++++++++++++ modules/version-stamp | 19 +++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 m4/version-stamp.m4 create mode 100644 modules/version-stamp diff --git a/ChangeLog b/ChangeLog index 87087d2d3b..ef6f39e3a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2025-01-22 Bruno Haible <br...@clisp.org> + + New module 'version-stamp'. + * m4/version-stamp.m4: New file. + * modules/version-stamp: New file. + 2025-01-22 Bruno Haible <br...@clisp.org> New module 'package-version'. diff --git a/m4/version-stamp.m4 b/m4/version-stamp.m4 new file mode 100644 index 0000000000..81e9f15d26 --- /dev/null +++ b/m4/version-stamp.m4 @@ -0,0 +1,35 @@ +# version-stamp.m4 +# serial 1 +dnl Copyright (C) 2025 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +# Manages a stamp file, that keeps track when $(VERSION) was last changed. +# +# gl_CONFIG_VERSION_STAMP +# needs to be invoked near the end of the package's top-level configure.ac, +# before AC_OUTPUT. +# It makes sure that during the build, +# - $(top_srcdir)/.version exists, and +# - when $(VERSION) is changed, $(top_srcdir)/.version gets modified. +# +# $(top_srcdir)/.version is a stamp file. Its contents wouldn't matter, +# except that for detecting the change, we store the value of $(VERSION) +# in it (but we could just as well store it in a different file). +AC_DEFUN([gl_CONFIG_VERSION_STAMP], +[ + AC_CONFIG_COMMANDS([version-timestamp], + [if test -f "$ac_top_srcdir/.version" \ + && test `cat "$ac_top_srcdir/.version"` = "$gl_version"; then + # The value of $(VERSION) is the same as last time. + : + else + # The value of $(VERSION) has changed. Update the stamp. + echo "$gl_version" > "$ac_top_srcdir/.version" + fi + ], + [gl_version="$VERSION"]) +]) diff --git a/modules/version-stamp b/modules/version-stamp new file mode 100644 index 0000000000..6257221f6f --- /dev/null +++ b/modules/version-stamp @@ -0,0 +1,19 @@ +Description: +Optimized rebuilding of artifacts that depend on $(VERSION). + +Files: +m4/version-stamp.m4 + +Depends-on: + +configure.ac: + +Makefile.am: + +Include: + +License: +GPLed build tool + +Maintainer: +Bruno Haible -- 2.43.0
>From 7e2fe1fb9abf29e80a26a43b2cee047985ef3c1c Mon Sep 17 00:00:00 2001 From: Bruno Haible <br...@clisp.org> Date: Wed, 22 Jan 2025 21:31:52 +0100 Subject: [PATCH 3/3] doc: Document the workflows of the .tarball-version and .version files. * doc/package-version.texi: New file. * doc/gnulib.texi (Build Infrastructure Modules): Include it. * build-aux/git-version-gen: Fix comments: Fix description of .tarball-version. Recommend to invoke git-version-gen at configure time, not at autoconf time. Remove description of .version. Rename Makefile target 'tarball-version' to 'dist-tarball-version'. * top/GNUmakefile: Improve comments. --- ChangeLog | 11 ++ build-aux/git-version-gen | 47 ++++---- doc/gnulib.texi | 3 + doc/package-version.texi | 238 ++++++++++++++++++++++++++++++++++++++ top/GNUmakefile | 3 + 5 files changed, 278 insertions(+), 24 deletions(-) create mode 100644 doc/package-version.texi diff --git a/ChangeLog b/ChangeLog index ef6f39e3a9..e5419275d4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2025-01-22 Bruno Haible <br...@clisp.org> + + doc: Document the workflows of the .tarball-version and .version files. + * doc/package-version.texi: New file. + * doc/gnulib.texi (Build Infrastructure Modules): Include it. + * build-aux/git-version-gen: Fix comments: Fix description of + .tarball-version. Recommend to invoke git-version-gen at configure time, + not at autoconf time. Remove description of .version. Rename Makefile + target 'tarball-version' to 'dist-tarball-version'. + * top/GNUmakefile: Improve comments. + 2025-01-22 Bruno Haible <br...@clisp.org> New module 'version-stamp'. diff --git a/build-aux/git-version-gen b/build-aux/git-version-gen index d936fab979..4535beb99b 100755 --- a/build-aux/git-version-gen +++ b/build-aux/git-version-gen @@ -1,6 +1,6 @@ #!/bin/sh # Print a version string. -scriptversion=2025-01-14.15; # UTC +scriptversion=2025-01-22.18; # UTC # Copyright (C) 2007-2025 Free Software Foundation, Inc. # @@ -34,15 +34,15 @@ scriptversion=2025-01-14.15; # UTC # In order to use intra-version strings in your project, you will need some # separate generated version string files: # -# .tarball-version - present only in a distribution tarball, and not in -# a checked-out repository. Created with contents that were learned at -# the last time autoconf was run, and used by git-version-gen. Must not -# be present in either $(srcdir) or $(builddir) for git-version-gen to -# give accurate answers during normal development with a checked out tree, -# but must be present in a tarball when there is no version control system. -# Therefore, it cannot be used in any dependencies. GNUmakefile has -# hooks to force a reconfigure at distribution time to get the value -# correct, without penalizing normal development with extra reconfigures. +# .tarball-version - contains the version number assigned by the maintainer. +# Present or missing in a checked-out repository, at the discretion of the +# maintainer/contributor. Present in a distribution tarball, because the +# tarball does not include the version control history. +# Used by git-version-gen as an override. +# Cannot be used in any dependencies (since it may be absent). +# GNUmakefile has hooks to force a reconfigure at "make dist" time to get +# the value correct, without penalizing normal development with extra +# reconfigures. # # .tarball-version-git - a file committed to git containing a single # line with the string $Format:%(describe)$ and that the file is @@ -62,27 +62,26 @@ scriptversion=2025-01-14.15; # UTC # .tarball-version is never generated in a VC'd directory, so needn't # be listed there. # -# Use the following line in your configure.ac, so that $(VERSION) will +# Use the following snippet in your configure.ac, so that $(VERSION) will # automatically be up-to-date each time configure is run (and note that # since configure.ac no longer includes a version string, Makefile rules # should not depend on configure.ac for version updates). # -# AC_INIT([GNU project], -# m4_esyscmd([build-aux/git-version-gen .tarball-version]), -# [bug-project@example]) +# AC_INIT +# AC_CONFIG_SRCDIR([@var{unique-file-in-source-dir}]) +# AC_CONFIG_AUX_DIR([build-aux]) +# VERSION_NUMBER=`cd $srcdir \ +# && build-aux/git-version-gen .tarball-version \ +# | sed -e 's/dirty$/modified/'` +# gl_INIT_PACKAGE([@var{package}], [$VERSION_NUMBER]) +# AM_INIT_AUTOMAKE([@var{options}]) # -# Then use the following lines in your Makefile.am, so that .version -# will be present for dependencies, and so that .version and +# Then use the following lines in your Makefile.am, so that # .tarball-version will exist in distribution tarballs. # -# EXTRA_DIST = $(top_srcdir)/.version -# BUILT_SOURCES = $(top_srcdir)/.version -# $(top_srcdir)/.version: -# echo '$(VERSION)' > $@-t -# mv $@-t $@ -# dist-hook: tarball-version -# .PHONY: tarball-version -# tarball-version: +# dist-hook: dist-tarball-version +# .PHONY: dist-tarball-version +# dist-tarball-version: # echo '$(VERSION)' > $(distdir)/.tarball-version # # To setup support for "git archive" tarballs, use the following: diff --git a/doc/gnulib.texi b/doc/gnulib.texi index 5eed50d4e0..6a7ba18f5f 100644 --- a/doc/gnulib.texi +++ b/doc/gnulib.texi @@ -8192,6 +8192,7 @@ * warnings:: * manywarnings:: * Running self-tests under valgrind:: +* Package version management:: * VCS To ChangeLog:: * gitlog-to-changelog:: @end menu @@ -8210,6 +8211,8 @@ @include valgrind-tests.texi +@include package-version.texi + @include vcs-to-changelog.texi @include gitlog-to-changelog.texi diff --git a/doc/package-version.texi b/doc/package-version.texi new file mode 100644 index 0000000000..fb050a8fcf --- /dev/null +++ b/doc/package-version.texi @@ -0,0 +1,238 @@ +@node Package version management +@section Package version management + +@c Copyright (C) 2007--2025 Free Software Foundation, Inc. + +@c Permission is granted to copy, distribute and/or modify this document +@c under the terms of the GNU Free Documentation License, Version 1.3 or +@c any later version published by the Free Software Foundation; with no +@c Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A +@c copy of the license is at <https://www.gnu.org/licenses/fdl-1.3.en.html>. + +The goals of a package maintainer, +when dealing with the version number of a package, are: + +@itemize +@item +Programs should identify themselves with that version number +when invoked as @command{@var{program} --version}. + +@item +Every package tarball should contain the version number, in up to four ways: +@itemize +@item +The tarball name should be @code{@var{package}-@var{version}.tar.gz}. +@item +The tarball should unpack into a directory +named @code{@var{package}-@var{version}}. +@item +Programs built from that tarball should identify themselves +when invoked as @command{@var{program} --version}. +@item +Documentation (especially in PDF format) and man pages +may contain the version number, as an important bit of meta information. +@end itemize + +@item +The package maintainer should be able to +easily set the version number before making a release, +and doing so should be quick. + +@item +When a contributor is +building from the git repository (as opposed to a tarball), +the version number should, by default, reflect the git commit, +in order to avoid confusion w.r.t. official releases. +@end itemize + +Here's how the GNU Build System and Gnulib achieve these goals. + +@menu +* Setting the package version:: +* Propagating the package version:: +* Using the package version:: +@end menu + +@node Setting the package version +@subsection Setting the package version + +@cindex @code{.tarball-version} +When the maintainer has decided about the version number +for the next build (and likely also the next tarball), +they implement that decision by storing this version number +in a file named @file{.tarball-version} at the top level of the package. +This is a simple one-line text file. + +The maintainer can, alternatively, decide to +let the git version be the version number. +To implement this choice, +they remove the file @file{.tarball-version} at the top level of the package. + +@mindex git-version-gen +The actual version number comes from an invocation of +the program @code{git-version-gen}, +part of the Gnulib module @code{git-version-gen}. +It looks at the file @file{.tarball-version}, if that exists, +and at the current checkout, otherwise. + +The file @file{.tarball-version} should not be put under version control. +Therefore you may want to list it +in the package's top-level @code{.gitignore} file. + +But you need a @code{Makefile.am} rule that will +make sure that @file{.tarball-version} will exist in distribution tarballs: + +@example +dist-hook: dist-tarball-version +.PHONY: dist-tarball-version +dist-tarball-version: + echo '$(VERSION)' > $(distdir)/.tarball-version +@end example + +Typically, the maintainer will set the version number in a clean directory +(i.e. after ``make distclean''). +@mindex gnumakefile +In order to adapt to alternative workflows, +the file @file{GNUmakefile}, part of the Gnulib module @code{gnumakefile}, +contains a rule that will print a warning or possibly call @code{autoreconf} +if it finds that the version has changed but has not yet been propagated. +Reminder: Not every package supports @code{autoreconf}. + +@node Propagating the package version +@subsection Propagating the package version + +At the end of a @file{configure} run, +@code{config.status} is run, +that creates various files with embedded pieces of information. +It thus propagates the values of various variables +to various files in the build tree +(most notably, @code{Makefile}s and @code{config.h}). + +One such propagated value is +the value of the Automake-defined variable @code{$(VERSION)}. +(There is also the Autoconf-defined variable @code{$(PACKAGE_VERSION)}, +but nothing except Automake ought to use it.) + +For @code{$(VERSION)} to have a sensible value, +a few lines are needed in @code{configure.ac}. + +The recommended code pattern is +@example +AC_INIT +AC_CONFIG_SRCDIR([@var{unique-file-in-source-dir}]) +AC_CONFIG_AUX_DIR([build-aux]) +VERSION_NUMBER=`cd $srcdir \ + && build-aux/git-version-gen .tarball-version \ + | sed -e 's/dirty$/modified/'` +gl_INIT_PACKAGE([@var{package}], [$VERSION_NUMBER]) +AM_INIT_AUTOMAKE([@var{options}]) +@end example +@noindent +With this code pattern, +the contents of the file @file{.tarball-version} and the git status +are considered when @code{configure} is run. + +Two older code patterns are deprecated, because they read +the contents of the file @file{.tarball-version} and the git status +when @code{autoconf} is run, not when @code{configure} is run. +These older code patterns thus require a longer turnaround cycle +when the maintainer has changed the version number. + +The first such old code pattern +is to set the version number directly in @code{configure.ac}: +@example +AC_INIT([@var{package}, @var{version}]) +AC_CONFIG_SRCDIR([@var{unique-file-in-source-dir}]) +AC_CONFIG_AUX_DIR([build-aux]) +AM_INIT_AUTOMAKE([@var{options}]) +@end example + +The second such old code pattern +is to invoke @code{git-version-gen} at @code{autoconf} time: +@example +AC_INIT([@var{package}], + m4_esyscmd([build-aux/git-version-gen .tarball-version \ + | sed -e 's/dirty$/modified/'])]) +AC_CONFIG_SRCDIR([@var{unique-file-in-source-dir}]) +AC_CONFIG_AUX_DIR([build-aux]) +AM_INIT_AUTOMAKE([@var{options}]) +@end example + +@mindex package-version +The macro @code{gl_INIT_PACKAGE} +is defined in the Gnulib module @code{package-version}. + +@node Using the package version +@subsection Using the package version during the build + +@subsubheading The unoptimized way + +Once propagated through @code{config.status}, +the value of @code{$(VERSION)} can appear anywhere in built files. +For built files that are +distributed (that is, not erased by ``make distclean''), +it is important to add a dependency in the @code{Makefile.am}, +so that the file gets rebuilt: +@example +@var{built-file}: $(top_builddir)/config.status +@end example + +For files that are erased by ``make distclean'', this is not really necessary, +because +@itemize +@item +In the main workflow, where the developer +changes the version only between ``make distclean'' and ``./configure'', +the built files have been remade. +@item +Most @code{.o} files depend on @code{config.h}, +which is rebuilt when @code{configure} runs. +@end itemize + +Thus, only in packages that don't use Gnulib would a dependency such as +@example +hello-hello.$(OBJEXT): $(top_builddir)/config.status +@end example +@noindent +be needed. + +@subsubheading The optimized way + +Notice that +@code{config.status} usually changes much more often than the version number. +Therefore, for built files which depend +@emph{only} on @code{$(VERSION)} and not on other variables, +the following optimized technique can be used. + +The technique consists of keeping a file named @code{$(top_srcdir)/.version}, +which is a timestamp file. +Its modification time represents the last time +the value of @code{$(VERSION)} was changed. +Its contents is an undocumented implementation detail. + +With such a file, the dependency in @code{Makefile.am} becomes: +@example +@var{built-file}: $(top_srcdir)/.version +@end example + +In order to prepare for using @code{$(top_srcdir)/.version}, +three modifications in the package are needed: +@itemize +@item +In the top-level @code{configure.ac} file, +add an invocation of the macro @code{gl_CONFIG_VERSION_STAMP}, +near the end (before @code{AC_OUTPUT}). +This macro is defined in file @file{m4/version-stamp.m4}, +part of the Gnulib module @code{version-stamp}. +@item +In the top-level @code{Makefile.am}, add: +@example +EXTRA_DIST += $(top_srcdir)/.version +BUILT_SOURCES += $(top_srcdir)/.version +@end example +@noindent +so that the file @code{.version} will be present in tarballs +and so that ``make maintainer-clean'' will erase it. +@item +Add @code{.version} to the package's top-level @code{.gitignore} file. +@end itemize diff --git a/top/GNUmakefile b/top/GNUmakefile index d85da0bed4..44419bfcb0 100644 --- a/top/GNUmakefile +++ b/top/GNUmakefile @@ -44,6 +44,9 @@ include $(srcdir)/maint.mk # Ensure that $(VERSION) is up to date for dist-related targets, but not # for others: rerunning autoreconf and recompiling everything isn't cheap. +# This is not part of the essential workflow with .tarball-version. Rather, +# it is meant to help the maintainer who has changed the current version +# but not done a "make distclean". _have-git-version-gen := \ $(shell test -f $(srcdir)/$(_build-aux)/git-version-gen && echo yes) ifeq ($(_have-git-version-gen)0,yes$(MAKELEVEL)) -- 2.43.0