I saw a book called “Die GNU Autotools” and I thought “My feelings exactly”. Turns out the book was in German 1 . You can talk for a long time about the imperfection of this toolkit, about the superiority of CMake / QMake / substitute_your_a favorite assembly system, but projects that use autotools surround us everywhere, and you should at least know what this beast is and what it is eaten with, so that when you try to do it, then send the patch to the developers, do not edit the auto-generated files, which I did not so long ago.
It should also be understood that it is autoconf that is not an assembly system at all, it is a configuration system before assembly. For some reason, autoconf is considered by many to be a kind of monster, "checking 15 long-non-existent versions of the Fortran compiler, and then supporting the keys with these compilers," which is not quite true, because it does exactly what they say. Another thing is that many people just copy-paste his config from project to project, in the end the result is horrendous.
')
In this article (I plan to master the cycle), I would like to tell you about autoconf, why you need it and how to use it.
NB I have prepared an archive with source codes for the article, you can
download it .
It is best to explain why autoconf is used on a simple example of a spherical program in a POSIX environment.
So, suppose you have a program consisting of a single executable file that reads a line from the config and writes to the log. This is a good spherical example, since many programs, in addition to their payload, do just that:
#include <stdlib.h> #include <stdio.h> void main (int argc, char**argv[]) { FILE* config = fopen ("/etc/hellolog.conf", "r"); FILE* log = fopen ("/var/log/hellolog.log", "a"); char*line; getline (&line, NULL, config); fprintf (log, "Line from config %s", line); fclose(config); fclose(log); free(line); }
And a simple makefile to build it:
If in the process of reading there will be some questions on Makefiles, it is strongly recommended to read the
dock on make .
In principle, take it and use it, but in an amicable way, the program should also be installed in the system. You can guess that you need to copy the executable file to / bin, but it is better to still install and uninstall goals at the same time:
install: install hellolog $(DESTDIR)/usr/bin/hellolog uninstall: rm $(DESTDIR)/usr/bin/hellolog
install - * nix-ovaya utility that in addition to copying the file performs manipulations with access rights to it.
DESTDIR is needed here so that it is possible to install not immediately into the system, but into a temporary directory so that the package building system can deduct and package them from there. We remember that
using make install directly is very bad , right?
One important problem remains - all our ways are hard-coded. If someone needs to install the program in the home directory, in / opt / or simply use the
distribution kit, who wanted to sneeze on the FHS , there will be problems.
In principle, we can take the paths to the necessary directories as make arguments as we do with DESTDIR (make overrides the values specified in the Makefile, so we can do the defaults. To begin, modify the source code:
... #define CONFIG_PATH CONFDIR"/hellolog.conf" #define LOG_PATH LOCALSTATEDIR"/helloconf.log" void main (int argc, char**argv[]) { printf ("Config %s Log %s\n", CONFIG_PATH, LOG_PATH); FILE* config = fopen (CONFIG_PATH, "r"); FILE* log = fopen (LOG_PATH, "a"); ...
Now we add the definitions of the necessary paths in the Makefile, passing them to CFLAGS along the way, so that it would be more convenient to reuse when compiling several files, as well as modify the install and uninstall targets:
Already much better. We can make make prefix = / opt / hellolog && make install prefix = / opt / hellolog and isolate the files of our program in this directory. The problem now is that there may be more assembly goals, and it’s not quite convenient to write a bunch of parameters each time. In an amicable way, everything has to be put into a configuration script that will receive configuration parameters, and then simply use make.
In bearded times, such scripts were written manually, at the same time for the purpose of code portability (we only use POSIX here, a lot of libraries are used in these programs, and some of them are interchangeable in some part) it included dependencies checks and platform-dependent changes to the Makefile logic . At some point, the amount of the script code, which advanced Chinese technology reuse code called "copy-paste" was transferred from the project to the project, began to exceed imaginable limits. As a result, one resourceful person decided to put frequently used pieces into macros on M4 (M + 4 letters of the word Macro, a macro language developed by Kernigan and Ritchie), which resulted in autoconf. Later on, it became widespread, and then automake and libtool tools were created on its infrastructure. However, the essence of autoconf remains the same (set of macros) and it can successfully be used separately.
Let's see what we can do with our toy program. In principle, the set of changes is extremely small and concerns only the Makefile. We replace the predefined path values with placeholders, and rename the Makefile itself to Makefile.in:
prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sysconfdir = @sysconfdir@ sharedstatedir = @sharedstatedir@
Also add the minimally useful configure.conf file:
AC_INIT([hellolog], [1.0]) AC_CONFIG_FILES([Makefile]) AC_OUTPUT
Run autoreconf and get the configure file in the current directory, which has the usual command line format for everyone. We do ./configure --prefix = / opt && make && ./hellolog and see that all paths are spelled correctly. Now let's see what happened “under the hood”.
The only file that autoconf accepts is configure.ac, which is a regular Bourne-shell script that uses macros, respectively AC_INIT and AC_OUTPUT are a required skeleton, AC_CONFIG_FILES also specifies a list of files that need to be replaced. Here you can also make a bunch of different actions like checking for dependencies. I recommend using pkg-config for this, there is a separate set of macros for it. Next, a configure script is generated that doesn’t need anything other than a Bourne-compatible shell and awk (sed was used before).
./configure in turn, after checks, generates a config.status script containing the required substitution parameters and starts it. And that one in turn generates files with the values of these substitutions. So if you only changed the Makefile, then you only need to run config.status.
So the toolchain looks like this: autoreconf + configure.ac -> configure -> config.status -> summary files.
In principle, nothing prevents you from using autoconf along with your favorite build environment. I, for example, use MSBuild for my programs, sharpened for Mono, the Makefile wrapper for this is trivial.
LinksGNU Make ManualM4 manualManual on Autoconf (in English)
Notes1. die (read as "di") is a definite article of the plural in German.