automake
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RFE: allow for computed version number


From: Bruno Haible
Subject: RFE: allow for computed version number
Date: Sun, 24 May 2009 03:15:47 +0200
User-agent: KMail/1.9.9

Hi all,

It has been mentioned in a discussion [1][2][3]
  "In the medium to long run, Autoconf should be changed to not depend
   at autoconf run time upon a volatile version string."
and
  "the goal is that the version string should _not_ appear in
   config.h, so there should be _no_ configure output that changes in content
   due to a version string change."

As a first step in this direction, I'd like to propose a change to
AM_INIT_AUTOMAKE that makes it possible to explore various approaches
to this problem.

Table of contents:
1) Why some people want computed version numbers
2) AC_INIT, AM_INIT_AUTOMAKE and the version number
3) Why AC_INIT(PACKAGE, VERSION) is bad
4) Temporary hack #1
5) Temporary hack #2
6) Proposal for AM_INIT_AUTOMAKE


Why some people want computed version numbers
=============================================

At the time autoconf was designed, network bandwidth was limited, so
package maintainers created new releases once in ca. 6 months on average.
Using autoconf to propagate the version number into every Makefile seemed
adequate, since the version number did not change often.

Nowadays, it is customary to make prereleases on a weekly or more frequent
basis. So the version number changes more often.

For users of a distributed VCS, such as 'git', a new release is effectively
published each time the developer does a "git commit; git push". Thus the
version number can easily change 20 times a day.

Now, if the propagation chain of the version number into the compiled programs
goes like this:

        configure.ac or version.sh or .git/*
             |
             | aclocal, autoconf
             V
        configure
             |
             | ./configure or ./config.status --recheck
             V
        config.status
             |
             | ./config.status
             V
        Makefile, config.h
             |
             | make
             V
        program.o
             |
             | make
             V
        program

a change in the version number will cause a modification to 'configure',
then a modification to 'config.status',
then a modification to 'config.h',
then a modification to all object files,
then a relinking of all programs.

In other words, the entire package is rebuilt. This is acceptable once in 6
months, but not 20 times a day. It just gets in the way of the developer.

So people want to store the version number in a file other than configure.ac,
so that they control the dependencies.

        configure.ac                                         version.sh or 
.git/*
             |                                                        |
             | aclocal, autoconf                                      |
             V                                                        |
        configure                                                     |
             |                                                        |
             | ./configure or ./config.status --recheck               |
             V                                                        |
        config.status                                                 |
             |                                                        |
             | ./config.status                                        |
             V                                                        |
        Makefile, config.h                                            |
             |                                                        |
             | make                                                   |
             V                                                        |
        program.o                                                 version.o
             |                                                        |
             | make                                                   |
             V                                                        V
        program                                                   program

In this scenario, when the version number changes, a single file version.c
is recompiled, all programs are relinked, and the documentation is rebuilt.

Developers who don't care about the output of "program --version" on their
own system may reduce this propagation even more: They will typically only
make the 'info' formatted documentation depend on the version file (since
these are the only generated files that contain a version number and which
are distributed by "make distrib").

So, through cutting these dependencies down, a rebuild triggered by a change
in the version number takes a couple of seconds, rather than 15 minutes or
more.

I say "computed version number" because in one case the version number is
fetched from a file located in $(srcdir), whereas in other cases it can
be computed by a program on the fly (git-version-gen or similar).


AC_INIT, AM_INIT_AUTOMAKE and the version number
================================================

How are version numbers handled by autoconf and automake currently?

Autoconf and automake have essentially separate facilities for this.

- Autoconf: AC_INIT expects either both the package name and version number
  as literal values, or none of them. The AC_SUBSTed and AC_DEFINEd
  variables are
    PACKAGE_NAME
    PACKAGE_TARNAME
    PACKAGE_VERSION
    PACKAGE_STRING
    PACKAGE_BUGREPORT.

- Automake: AM_INIT_AUTOMAKE expects either both the package name and version
  number, allowing computed values, or none of them. The AC_SUBSTed and 
AC_DEFINEd
  variables are
    PACKAGE
    VERSION

Automake created Makefiles rely only on PACKAGE and VERSION, not on the
variables created by AC_INIT. (Witness: In GNU gettext, the 5 variables from
AC_INIT are empty. It works fine with only PACKAGE and VERSION.)

There is a catch, though: When package and version number are not specified
as arguments to AM_INIT_AUTOMAKE, AM_INIT_AUTOMAKE insists that they have been
specified to AC_INIT.


Why AC_INIT(PACKAGE, VERSION) is bad
====================================

The idea of specifying package and version as arguments to AC_INIT is bad
for three reasons:

1) Autoconf implements the checking of platform specific features, and a
   propagation/substitution mechanism for values which are supposed to stay
   constant until "make distclean".

   Automake implements the common coding idioms, important for package
   maintainers.

2) The propagation/substitution mechanism through 'configure', 'config.status'
   etc. is not adequate for values that change before "make distclean". See
   above.

3) In the use case above, the version number is stored in a file in $(srcdir).
   If its contents is read when 'configure' is created, the version number
   is stored in 'configure' - which we don't want. If its contents is OTOH
   read when 'configure' is run, it cannot be determined before AC_INIT,
   because $(srcdir) itself is only determined during the execution of
   AC_INIT's expansion; so we have a chicken-and-egg problem.

The only real use of the package and version number from AC_INIT's arguments
is for "./configure --version" or "./config.status --version". But that's a
tiny gimmick feature, in the big picture. GNU gettext has empty values in
these places, and nobody ever complained about it.

Conclusion: It's automake's business to deal with package and version number.


Temporary hack #1
=================

In gettext 0.17 I used this mechanism for a computed version number:
- Use AC_INIT without arguments.
- Then compute the version number.
- Then use the two-argument form of AM_INIT_AUTOMAKE.

-----------------------------------------------------
  AC_INIT
  AC_CONFIG_SRCDIR(...)
  . $srcdir/../version.sh
  AM_INIT_AUTOMAKE([gettext], [$VERSION_NUMBER])
-----------------------------------------------------

The drawback of this approach is that it's not possible to pass
automake options to AM_INIT_AUTOMAKE. Ralf mentions in [4] that some
automake options can only be passed this way, not through the Makefile.am.


Temporary hack #2
=================

The current gettext uses this mechanism for a computed version number:
- Use AC_INIT without arguments.
- Then compute the version number.
- Then pass the version number to a macro gl_INIT_PACKAGE.
- Then use the 0/1-argument form of AM_INIT_AUTOMAKE.

-----------------------------------------------------
  AC_INIT
  AC_CONFIG_SRCDIR(...)
  . $srcdir/../version.sh
  gl_INIT_PACKAGE([gettext-tools], [$VERSION_NUMBER])
  AM_INIT_AUTOMAKE([OPTIONS])
-----------------------------------------------------

The gl_INIT_PACKAGE macro is defined in [5].

The drawback of this approach is that the gl_INIT_PACKAGE macro uses internals
of AM_INIT_AUTOMAKE and is therefore fragile.


Proposal for AM_INIT_AUTOMAKE
=============================

It would be good to be able to invoke AM_INIT_AUTOMAKE with options, and
be able to set the package and version names (with computed values)
separately.

I'm *not* asking for a specific way of handling the version in a separate
file; simply to allow any way of computing the version (e.g. fetching it
from a shell script, by calling git-version-gen, etc.) Rationale: There
is more than one type of distributed VCS. Also, we need time to experiment
with this version propagation in order to find out the best way of doing it.

In particular, the request is that AM_INIT_AUTOMAKE does not bail out with
a fatal error message if AC_PACKAGE_NAME, AC_PACKAGE_TARNAME,
AC_PACKAGE_VERSION are not defined.

Bruno


[1] http://lists.gnu.org/archive/html/bug-gnulib/2008-08/msg00282.html
[2] http://lists.gnu.org/archive/html/bug-gnulib/2008-08/msg00283.html
[3] http://lists.gnu.org/archive/html/bug-gnulib/2008-08/msg00284.html
[4] http://lists.gnu.org/archive/html/bug-automake/2009-05/msg00053.html
[5] 
http://cvs.savannah.gnu.org/viewvc/gettext/m4/init-package-version.m4?revision=1.1&root=gettext&view=text/plain




reply via email to

[Prev in Thread] Current Thread [Next in Thread]