# init-package-version.m4 # serial 3 dnl Copyright (C) 1992-2024 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]) ]) ])