Newsgroups: comp.os.linux.development.apps Date: Thu, 31 Aug 2000
I just got into Linux development recently, and this the first time I've encountered the use of such tools as autoconf, automake, autogen.sh, configure, etc., that I'm seeing accompanying all the source code that I've started downloading.
Although these tools definitely appear to be doing a lot for me, I really don't comprehend all of what they are doing, what the intermediate files are, etc.
In particular, I'm looking at a current source code distribution (for Glade), and I'm trying to answer for myself the simple question "where is the right place to insert a -Dxxx compile definition so that it is used in my next compilation, given that there are several Makefiles present (in several directories), and they were all generated auto-magically?"
Does anybody know of a nice explanation of what the flow is of all these programs, how they work, etc.? And most importantly, where *IS* the right place to add a -D compile option?
> place to add a -D compile option?
Not sure exactly how to add a -D options, but the place to add it would be to the file Makefile.am.
I use the script included below to reconfigure a project when I change Makefile.am of configure.in. The last command "automake -a" converts Makefile.am into Makefile.in which is used by the configure script to generate the Makefile.
Erik
#!/bin/sh rm -f config.cache if [ -d m4 ]; then echo "Looking in m4 directory for macros." aclocal -I m4 else echo "Looking in current directory for macros." aclocal -I . fi autoconf autoheader automake -a exit
Erik de Castro Lopo
> place to add a -D compile option?
If you're "adding" it for yourself, what I usually do is pass it to configure, ala (in sh-flavored shells):
CFLAGS="-Dmyoption" ./configure
That propogates it through all the automagic files, as well as during the configure tests themselves. It also makes it easier to build binary packages, if you do that sort of thing.
If you're "adding" it as part of the actuall distributed version, then you should make a check if it's needed in configure.in and have it replaced in the output.
Matt Gauthier
> CFLAGS="-Dmyoption" ./configure
You should always use
./configure CFLAGS="-Dmyoption"
as otherwise, CFLAGS won't be set by config.status, so config.status —recheck (as run by automake-generated makefiles when —enable-maintainer-mode is on) will not pick it up.
If you want to add the same things for many packages in a programmatic fashion, you should use a site-config file; see the autoconf manual for information.
Nix
our group is relying heavily on these tools for our code development, and usually for newcomers it's a bit hard to grasp what the "top-level" thing in there is. Also, we have libtool in the mix as well — takes the pain out of creating shared libs on multiple platforms.
Let's start at the bottom - what you want to get in the end is a platform-specific Makefile, you run "make" and it's coming up with an app or whatver you build. Obviously, maintaining individual Makefiles for different platforms is extremely hard to do, although you'll see software packages where it is done this way. In that case, you may see a Makefile.Linux, Makefile.SGI, Makefile.Sun, Makefile.IBM, Makefile.whatever, and you are supposed to make a symlink to the one you think is right. Problem is, no two machines are exactly the same, my current extreme case is SGI where you have 32bit vs 64bit architectures, 64bit w/ 32bit compatibility-mode libs, native vs gcc compiler, and then some variations, all requiring different compiler flags and, on occasion, different commands. But also on linux you may have to distinguish gcc from egcs, and so on, and before you know it, it has all become quite unmanageable.
Throw in "autoconf" and its product, the configure script. The latter takes a Makefile template which is called "Makefile.in", and generates your platform-specific Makefile from it. The configure script is a plain shell script which runs on any machine which has sh. This script goes and probes the system you're running it on - does this header file exist, do we have this tool, does it take this or that compiler flag, does the system libs support this function, does it take these or those parameters, what is the command to run the linker, and so on, and so on. The configure script is automatically generated by autoconf, which takes its hints from a file called "configure.in". There are predefined macros for every type of checks you can imagine and then some; look at the manual, it's really comprehensive. And should you come across something that isn't quite covered, you can ask the produced configure script to actually try to compile a code snippet and take a decision based on whether that works or not. The decisions taken by configure result, most of the time anyway, in -D def's passed to the compiler, which you can use to select one piece of code or another.
These configure.in scripts are generally *relatively* simple or at least straightforward. Here's an extremely simple one which does nothing but figure out the commands to run the cc and c++ compilers:
> AC_INIT(alltt.h)
> AC_PROG_CC > AC_PROG_CXX
> AC_OUTPUT(Makefile)
The Makefile.in template, on the other hand, can become quite complex. You can write (and I have in the past written) Makefile.in's by hand, but I stopped doing that a long time ago. automake is a tool that takes a (again relatively simple) "meta template" Makefile.am, and creates the Makefile template Makefile.in from it.
It is important to understand the autoconf and automake tools are *not* required to be present on the end user's machine - the developer uses them to create the Makefile.in template and the configure script (and some more helper scripts), which are distributed along with the sources and which are sufficient to produce the Makefile and then the application.
As the developer, you run automake and autoconf each time you change something in the Makefile.am or configure.in files. autogen.sh is now the script that runs those tools in one go.
As to your question, the -D option, that depends if that option is platform-specific or not. If it is, include an instruction in configure.in to test what the value should be set to based on what you find. If, for some reason, you *always* want this option to be present, unconditionally, put it in the Makefile.am. On a case-by-case basis, you can set the value yourself by
> ./configure CFLAGS="-Dxxx=yyy"
That will do it, and that may be ok for you as the developer, but this is not how I'd recommend distributing a package to the outside world or your colleague next door. Let's say (crude example) the option selects whether you want graphics capabilities in your package or not (wouldn't be done with just a -D, but as an example). Add something in the configure.in to give configure a "dashdash" option in the spirit of the standard options:
> ./configure --help > Usage: configure [options] [host] > Options: [defaults in brackets after descriptions] > Configuration: > --cache-file=FILE cache test results in FILE > --help print this message > --no-create do not create output files > --quiet, --silent do not print `checking...' messages > --version print the version of autoconf that created configure <stuff deleted> > Features and packages: > --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) > --enable-FEATURE[=ARG] include FEATURE [ARG=yes] > --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] > --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
so add a
> --with-graphics
option which in turn sets the -D option.
It's already a long mail, but in addition to making the whole build/make system painless, there are two more great features in there that I learned to appreciate. The one is the generation of a bunch of automatically included make targets. As an example, you can say "make clean" and you get everything that "make" generated cleaned out.
The other feature is the concept of "pristine sources". How often have you clobbered your source directories with leftover temp files, such as .o or something else. Here you get the source distribution tree, and you are free to cd there and run ./configure. However, you can do better. Go to an empty directory which you create, let's call it "build", and execute the configure from there:
> /path_where_the_source_is/configure
Now all newly created files not originally included in the distribution get put into that directory and maybe subdirs underneath, but the source distribution remains completely unchanged. I develop for several different platforms, Linux, Sun, and several flavors of SGI, and I have the same source tree but different build (and installation) areas for the platforms. If I make a change, I can immediately test the effect on all platforms and see if it works.
Ok. Executive summary:
"Makefile" is generated by "configure" from a template "Makefile.in".
"configure" is generated by "autoconf" from "configure.in".
"Makefile.in" is generated by automake from "Makefile.am".
Martin Purschke