This is the mail archive of the
guile@cygnus.com
mailing list for the Guile project.
Re: Tired of make. Anyone interested in a guile-based replacement?
> I abandoned the whole thing long ago as the spawn of the devil. :-)
> Seriously, though, that's how it made me feel. It was great at first,
> but any time I tried to do something non-standard, I was faced with
> random errors, incomplete documentation, bugs, and impenetrable source
> code.
I came to the same conclusion about autoconf and I must say that I don't
like libtool either. I have some more concrete complaints though and I
have some ideas on a replacement (but my objectives are a lot more limited
than this project seems to be intending).
Firstly the bad things:
* In autoconf, symbols with the same meaning get given various different
names depending on where they are used. For example, when they are shell
variables they will be called one thing and when they are #defines in
C code they will be called something else. This generates complexity where
there is no reason to do so.
* In autoconf, symbols have short and arbitrary names without any overall
structure. This means that you can't scan a block of code for any autoconf
symbols because you don't know what to scan for.
* Yeah documentation is patchy, this seems to be true for everything so
not much else can be expected. The thing is that without a well defined
guiding structure the user is highly dependent on the docco. With a
sensible structure around it all, the user will at least know where to
go looking.
* autoconf depends highly on the behaviour of the system shell to get
correct results out of its configure scripts. The shell is not actually
particularly consistent across systems nor should shell behaviour really
be so critical to the build process.
* libtool doesn't handle shared library dependencies properly on Linux.
The best, easiest and most functional way to make a shared library on
Linux is to use exactly the same command line that you would have done
to make the executable but put in a -shared option for gcc. In some cases
adding -fPIC will help but it is usually not required. If you do it this
way then when a library depends on another library, it is correctly chained
into the load.
Libtool goes and mucks around with ld and linker options and ends up
producing libraries that require the user of the library to know every
dependency that the library has -- there is no need for this.
* When an autoconf `configure' script goes wrong it is difficult to figure
out why and where. There are some reasons for this: [1] The script builds
test code on the fly and deletes it afterwards, [2] the script itself
cannot easily be read through top to bottom, so you don't know which
bit exactly was the bit that failed, [3] the log files are difficult to
relate to the script.
* When you tweak something in an autoconf script or when you attempt to
override on of its settings, you can get unexpected results. Partly
this is because sometimes the settings files themselves are checked by
make so that it tries to tweak your tweaks and partly because of the
caching scheme that stores test results in more than one place.
> I really didn't like the philosophy of the whole thing. It was all ad
> hoc names, like a bad AI program.
The autoconf documentation admits this and autoconf was never intended
to be some ultimate configuration tool. Regular rethinking and rewriting
of such tools is always healthy IMHO.
> I think having a real programming language would lead to a more open
> and comprehensible structure. Given that, then all of the carefully
> collected rules of autoconf and automake could be imported. Those
> rules work just fine, and they should certainly not be discarded
> completely, but I think they are too monolithic and need to be
> reorganized into a series of manageable transformations.
I agree with some of this but not all. You do want a generic
programming language for configuration descriptions but you do not
want to go and use the features of this language willy-nilly, you want
99% of cases to be handled in a consistent manner so that anyone can
walk in and know where they are.
Here are some idea from my configuration utility.
* The name of my utility is ``jexy''. I chose this name because if you
really use your imagination it stands for ``Jett Enougher Xonfiguration
Youtility''. It also so happens that the combination of letters ``JEXY''
almost never occurs it intelligable writings so it is easy to know that
you won't crowd someone else's namespace. In keeping with this wisdom,
ALL defined symbols are prefixed JEXY_ and you can grep for them very
reliably. It happens to also be pronounceable.
If you want to make a useful configuration tool, don't give it a cool
name, give it a dumb name that no one else will ever use. Give it a short
name that will make a nice prefix but not piss people off when they type it.
Don't use my jexy name or by the powers of heaven I'll hunt you down...
* It uses a perl script to translate a table of shell symbols into a table
of #defines for use in C. The shell symbols look something like:
JEXY_GCC_OPTION_NO_RTTI=-fno-rtti
JEXY_GCC_OPTION_NO_EXCEPTIONS=-fno-exceptions
JEXY_LINK_SHARED_SONAME_SUN=1
JEXY_LINK_SHARED_SONAME_WHOLE_ARCHIVE_FPIC=1
JEXY_LINK_SHARED_SONAME_WHOLE_ARCHIVE=1
JEXY_LIBRARY_MATH=-lm
JEXY_LIBRARY_MATH_SCALB=1
JEXY_LIBRARY_SEARCH_DYNAMIC_LINK=-ldl
JEXY_LIBRARY_SEARCH_X11=-lX11
JEXY_LIBRARY_SEARCH_LIBGUILE=-lguile
JEXY_INCLUDE_SEARCH_LIBGUILE=libguile.h
JEXY_INCLUDE_SEARCH_XLIB=X11/Xlib.h
Needless to say these are auto-generated but there are a few important
points about this table format. It can be equally well be included by
makefiles and by shell scripts so the file ``config.sh'' handles both
jobs and thus the symbol definitions are guaranteed consistent.
It is easy to translate into a C header like so:
/* generated by jexy/Makefile from config.sh */
#define JEXY_GCC_OPTION_NO_RTTI "-fno-rtti"
#define JEXY_GCC_OPTION_NO_RTTI_AB <-fno-rtti>
#define JEXY_GCC_OPTION_NO_EXCEPTIONS "-fno-exceptions"
#define JEXY_GCC_OPTION_NO_EXCEPTIONS_AB <-fno-exceptions>
#define JEXY_LINK_SHARED_SONAME_SUN 1
#define JEXY_LINK_SHARED_SONAME_WHOLE_ARCHIVE_FPIC 1
#define JEXY_LINK_SHARED_SONAME_WHOLE_ARCHIVE 1
#define JEXY_LIBRARY_MATH "-lm"
#define JEXY_LIBRARY_MATH_AB <-lm>
#define JEXY_LIBRARY_MATH_SCALB 1
#define JEXY_LIBRARY_SEARCH_DYNAMIC_LINK "-ldl"
#define JEXY_LIBRARY_SEARCH_DYNAMIC_LINK_AB <-ldl>
#define JEXY_LIBRARY_SEARCH_X11 "-lX11"
#define JEXY_LIBRARY_SEARCH_X11_AB <-lX11>
#define JEXY_LIBRARY_SEARCH_LIBGUILE "-lguile"
#define JEXY_LIBRARY_SEARCH_LIBGUILE_AB <-lguile>
#define JEXY_INCLUDE_SEARCH_LIBGUILE "libguile.h"
#define JEXY_INCLUDE_SEARCH_LIBGUILE_AB <libguile.h>
#define JEXY_INCLUDE_SEARCH_XLIB "X11/Xlib.h"
#define JEXY_INCLUDE_SEARCH_XLIB_AB <X11/Xlib.h>
Note that for some jobs C needs quoteed strings for other jobs
it needs angle brackets so I generate both. OK, some lines in this
file are useless -- so what, it is logically consistent and the
system is easy to implement and easy to understand. I presume that
numerics are never going to be used as strings or filenames. Most people
seeing numerics would be surprised if they turned into filenames so
it is a bad idea to ever use them in such a manner.
* I write the fundamental configuration in scheme and then run a scheme
program on this configuration file. The scheme program generates makefiles
which are used with gnumake to do the actual build. I can't be bothered
supporting anything more primitive than gnumake so I don't feel guilty
about using its special features (though I don't push this to the limit).
* One special feature that I use is ``make -k'' which (with some care) can
be used to attempt to build test code and report the success or failure
of the test. Note that this is not blown up by warnings, only by success
or failure as reported by the compiler. In many places autoconf runs the
compiler and checks if any messages at all were produced -- any message
at all is enough to fail the test! Also, ``make -k'' is doing the closest
thing to a real build. Rather than search the path for something that
looks like a C compiler, I attempt to compile a C program -- if that works
then I decide that I must have a C compiler.
* Each test-run has one or more test C programs which are numbered
automatically and generated along with the makefile. The user can see which
C programs are being compiled, which options are being used and which
symbols are being defined as a consequence. OK, a lot of crap scrolls up
and it doesn't look as sweet as when configure runs but it is much much
easier to figure out what is happening. Tests and results are not deleted
after they are run so the user can check them. All this is done in a
subdirectory.
* Test runs go in waves and partially construct the symbol table after
each wave. This allows late waves to make use of results from earlier
waves. You need this to handle (for example) the situation where libguile
may or may not be compiled to depend on libreadline and unless you get
it right, you won't be able to prove that libguile works so you can't
find libguile on the system. Thus you have to first search for libreadline
on the system, then search for libguile.
* I do follow the autoconf philosophy of testing for features not for brand
names. This is explained in various places and I hope that we are all
comfortable with those concepts at this stage.
* I have a special user-override file called ``userconf.sh''. From this
I generate userconf.h (as above) and I always let these symbols override
my generated symbols. Any symbol can be redefined in this manner if the
user has some reason to do so. This also makes a convenient place for
users to put definitions of some symbols that cannot be automatically
guessed (such as installation target directory) and it also can be used
to hold documentation of what the symbols are so that when the user is
in a hurry he/she can read right then and there what will be the expected
effect of changing a symbol.
OK, that's enough of my comments... I dont expect everyone to rush out and
use my configurator but do please take heed of some of my suggestions before
anyone goes out to build a new behemoth.
- Tel