6.3.5 Serial Numbers

Because third-party macros defined in *.m4 files are naturally shared between multiple projects, people like to version them. This makes it easier to tell which of two M4 files is newer. Since at least 1996, the convention is to use a ‘#serial’ line for this.

Such a serial number should be a single line of the form

# serial version

where version is a version number containing only digits and dots. Usually people use a single integer, and they increment it each time they change the macro (hence the name of “serial”). Such a line should appear in the M4 file before any macro definition.

The ‘#’ must be the first character on the line, and it is OK to have extra words after the version, as in

#serial version garbage

Normally these serial numbers are completely ignored by aclocal and autoconf, like any genuine comment. However when using aclocal’s --install feature, these serial numbers will modify the way aclocal selects the macros to install in the package: if two files with the same basename exist in your search path, and if at least one of them uses a ‘#serial’ line, aclocal will ignore the file that has the older ‘#serial’ line (or the file that has none).

A serial number applies to a whole M4 file, not to any macro it contains. A file can contain multiple macros, but only one serial number.

Serial Number Example

Here is a use case that illustrates the use of --install and its interaction with serial numbers. Let’s assume we maintain a package called MyPackage, the configure.ac of which requires a third-party macro AX_THIRD_PARTY defined in /usr/share/aclocal/thirdparty.m4 as follows:

# serial 1
AC_DEFUN([AX_THIRD_PARTY], [...])

MyPackage uses an m4/ directory to store local macros as explained in Handling Local Macros, and has

AC_CONFIG_MACRO_DIRS([m4])

in its configure.ac.

Initially the m4/ directory is empty. The first time we run aclocal --install, it will notice that

Because /usr/share/aclocal/thirdparty.m4 is a system-wide macro and aclocal was given the --install option, it will copy this file in m4/thirdparty.m4, and output an aclocal.m4 that contains ‘m4_include([m4/thirdparty.m4])’.

The next time ‘aclocal --install’ is run, something different happens. aclocal notices that

Because both files have the same serial number, aclocal uses the first it found in its search path order (see Macro Search Path). aclocal therefore ignores /usr/share/aclocal/thirdparty.m4 and outputs an aclocal.m4 that contains ‘m4_include([m4/thirdparty.m4])’.

Local directories specified with -I are always searched before system-wide directories, so a local file will always be preferred to the system-wide file in case of equal serial numbers.

Now suppose the system-wide third-party macro is changed. This can happen if the package installing this macro is updated. Let’s suppose the new macro has serial number 2. The next time ‘aclocal --install’ is run the situation is the following:

When aclocal sees a greater serial number, it immediately forgets anything it knows from files that have the same basename and a smaller serial number. So after it has found /usr/share/aclocal/thirdparty.m4 with serial 2, aclocal will proceed as if it had never seen m4/thirdparty.m4. This brings us back to a situation similar to that at the beginning of our example, where no local file defined the macro. aclocal will install the new version of the macro in m4/thirdparty.m4, in this case overriding the old version. MyPackage just had its macro updated as a side effect of running aclocal.

If you are leery of letting aclocal update your local macro, you can run ‘aclocal --diff’ to review the changes ‘aclocal --install’ would perform on these macros.

Finally, note that the --force option of aclocal has no effect on the files installed by --install. For instance, if you have modified your local macros, do not expect --install --force to replace the local macros by their system-wide versions. If you want to do so, simply erase the local macros you want to revert, and run ‘aclocal --install’.