mirror of
https://git.savannah.gnu.org/git/gnulib.git
synced 2026-10-24 00:48:56 +03:00
237 lines
7.9 KiB
Plaintext
237 lines
7.9 KiB
Plaintext
@node Package version management
|
|
@section Package version management
|
|
|
|
@c Copyright (C) 2007--2026 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([@var{package}], [package])
|
|
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`
|
|
gl_INIT_PACKAGE_VERSION([$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])])
|
|
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_VERSION}
|
|
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
|