[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lmi] autotools versus makefiles
Re: [lmi] autotools versus makefiles
Mon, 23 Jan 2006 02:48:16 +0100
On Sat, 21 Jan 2006 16:48:12 +0000 Greg Chicares <address@hidden> wrote:
GC> This is lengthy, but by considering the details I think we can find a
GC> way to support both paradigms with less work and more consistency.
I'm afraid my reply is going to be rather lengthy as well even although I
tried to condense it. If the discussion diverges too much from the original
topic or just splits in too many subthreads, it might be worth to dedicate
a separate mailing list message to each of them but I leave this decision
GC> On 2006-1-13 22:41 UTC, Vadim Zeitlin wrote:
GC> > On Fri, 13 Jan 2006 11:15:46 +0000 Greg Chicares <address@hidden> wrote:
GC> > GC> I don't see a compelling case for adopting autotools. What am I
GC> > GC> missing?
GC> > I don't think you miss anything, you've summarized the main advantage of
GC> > autoconf in an excellent way.
GC> > But I do believe that if we plan to support more compilers, it can
GC> > become quite important.
GC> I'd very much like to support more compilers.
Let me make it clear that I'm perfectly aware that you can support
multiple compilers with manually written makefiles. However using autoconf
gives an advantage of providing standard (this is the word I'm using a lot
when speaking about autoconf -- but only because it is, after all, one of
its main advantages) procedures for dealing with the issues which arise
with them. I.e. you may/will still have to write different compiler flags
for different compilers but with autoconf this is centralized in a single
place and better organized and, although this could be subjective, easier
GC> How would autotools make this easier? I find a thread starting here
GC> that seems to suggest that it's difficult to use automake with a compiler
GC> other than gcc.
The reply in this thread makes it quite clear that the goal of autoconf is
to support all compiler but that, unfortunately, sometimes some GNUisms
slip in. And automake goes to great lengths to not require the use of GNU
make as otherwise many, many things would have been much simpler (although,
of course, automake does work excellently with gmake and it does require
VPATH support from the make program which some BSD makes don't have).
From my personal experience, I've never had any problems due to not using
gcc with autoconf itself. I did have many problems with configure scripts
which assumed gcc (obvious example is putting gcc-specific flags in CFLAGS)
but this can hardly be blamed on autoconf. Also, I didn't use autoconf with
neither bcc nor como so far but I did use it with just about all standard
Unix C/C++ compilers I know about (Sun CC, HP-UX aCC, SGI mipsPro, AIX xlC)
GC> OTOH, this message
GC> | You might just want to use automake, autoconf and libtool.
GC> | AFAIK, they are supporting VC++ syntax.
GC> suggests that gnu autotools supports msvc--as a special case, I would
GC> presume, due to its widespread use.
I don't believe there are any special exceptions for msvc due to this.
GC> Yet como is very different. Here's a real problem:
GC> From the EDG POV, then, gcc is anomalous. But autotools were written for gcc
GC> (and apparently extended to msvc), and from that POV, EDG is anomalous, and
GC> I don't see much hope that automake has a canned solution for it.
Actually if the problem is really due to linking the same object file in
different targets, then it has a well-known solution which is just to
compile the .c file twice if it's used for different targets. So this
really shouldn't be a problem.
Of course I can't guarantee that automake doesn't have any other problems
with como or other (especially Windows) compilers. But I think it's not
unreasonable to count on [at least portable to Unix] compiler vendors being
actively interested in making their products usable with autotools
toolchain as otherwise their appeal would be severely limited.
GC> > A few other things:
GC> > - tests for functions can be written manually,
GC> I believe that only these four C99 functions have proved to be problematic:
GC> expm1(), log1p(), snprintf(), strtold()
So far, yes. LMI is mostly isolated from platform differences because it
GC> but they're all used only in very isolated cases. We have macros like
GC> LMI_COMPILER_PROVIDES_EXPM1, LMI_COMPILER_PROVIDES_STRTOLD
GC> and 'config_*.hpp' files to define them. We need another such file for each
GC> new compiler. We can write it by hand, or autoconf can write it.
I'd rather say that we can write N different error-prone (because they
will involve testing the compiler version and you don't always know for
sure when was the particular function added/removed and then there are also
strange but occuring in practice cases of using old compiler with newer
runtime libraries) tests for every compiler or write 1 autoconf test.
GC> I think we should treat expm1() like this (untested):
GC> #if !defined LMI_COMPILER_PROVIDES_EXPM1
GC> inline double expm1(double x)
GC> global_untrustworthy_flag = true;
GC> return std::exp(x) - 1.0;
GC> #endif // !defined LMI_COMPILER_PROVIDES_STRTOLD
GC> int main()
GC> warn("Results may be invalid.");
GC> and the other three C99 functions similarly.
If it's safe to assume that expm1() is called in all calculations (isn't
it?) then it could be simpler to write it as
#if !defined(HAVE_EXPM1) || !defined(HAVE_LOG1P)
warn("Results may be incorrect.");
GC> > but configure may also do
GC> > other compile-time checks, e.g. verify whether the correct version of
GC> > wxWidgets is available (and built with correct options),
Before continuing with wx-config, let me emphasize once again that
autoconf can be used to test all build settings dynamically instead of
hardcoding them statically into makefile. It's reminiscent of using
hardcoded constants to run-time variables in the code. And the advantages
of autoconf are comparable: easier maintenance, more clarity in the
makefiles. And even the main disadvantage (performance loss due to not
hardcoding things any more but having to run configure/initialize
variables) is the same.
GC> IIRC, building wx with autotools creates 'wx-config', a script that makes
GC> it easy to retrieve the options wx was built with, so that we wouldn't
GC> need to write, e.g.,
GC> in the lmi makefiles (and manually keep them coordinated with the wx build
GC> options we're using, which may change over time).
GC> But this can be done in the makefiles, too, can't it?
It certainly can. What makefile can't do is to test whether wx-config
exists and is correct (e.g. doesn't correspond to Unicode build of wx which
is not suitable for lmi). Of course you'd still get an error sooner or
later but it risks to be much less clear.
GC> I have no 'wx-config', probably because I built wx with its makefiles.
GC> I wouldn't mind using 'wx-config', though, if I've understood it correctly.
GC> Is there a way to get 'wx-config' from wx's 'config.h' without autotools?
No, wx-config is not generated from config.h. Rather, both config.h and
wx-config are generared by autoconf when you use it to build wxWidgets.
GC> > whether we have
GC> > boost installed (or need to build it as part of lmi)
GC> People who actually use lmi won't have boost installed. Our niche is narrow.
GC> We have to accommodate people who know little about such tools. That's why
GC> we're writing 'setup.make' to create an appropriate environment from
I understand, but it's still inconvenient to not be able to use the boost
libraries if you already have them. Especially on a Linux system where
they're quite likely to be available in a package.
GC> > - autoconf makes integration with other tools usually easier because it is
GC> > a well-known standard; e.g. creating Debian (or cygwin, for that matter)
GC> > packages is much simpler if you have an autoconf-based build system
GC> OK. Are there any other tools, besides debian's package facility and
GC> that work more easily with autoconf?
The vague answer is that all GNU tools having anything to do with
development do. The trouble is that I don't use that many other tools
myself, in particular I'm not really familiar with Linux IDEs but I do
believe they have better support for autotools than for custom makefiles.
GC> > - we gain a few very nice features for free when using autotools:
GC> > . standard configure arguments such as --prefix or --enable-debug:
GC> > it's really convenient to be able to specify them in a usual way
GC> > instead of having to modify the makefiles or pass the flags on
GC> > command line
GC> Is this only the difference between
GC> configure --enable-debug --prefix='/foo/bar' && make
GC> make CXXFLAGS='-g' prefix='/foo/bar'
There are a few differences here:
1. "make --help" won't give you possible values for CXXFLAGS but configure
will give you --enable-debug
2. "-g" is not going to work for msvc (it needs "-Zi") and --enable-debug
could hide it
3. you have to specify make parameters every time and this is painful if
you recompile repeatedly -- with configure you normally just run it once
and then just do "make"
4. you can't check validity of make parameters which means that error
reporting suffers greatly
GC> > . possibility to build in another directory: this is much more tidy
GC> > building in the source directory
GC> The lmi makefiles do that already.
Sorry, I should have been more clear. What I meant was to build in _any_
other directory. E.g. a common situation is to have sources on an NFS
volume and then you really don't want to build on it so typically you'd
build in /tmp/foo using sources from ~/src/foo.
GC> > . make targets such as install, dist, ... are implemented automatically
GC> > (this is done by automake and not autoconf but it doesn't matter)
GC> We have an 'install' target, and it uses 'prefix' and 'exec_prefix'
GC> as prescribed here, AFAIK:
GC> We have a 'test' target; maybe I should name it 'check' to conform to
GC> typical GNU practice. We have 'clean', 'distclean', 'mostlyclean', and
GC> 'maintainer-clean' just to conform to GNU standards, even though they all
GC> happen to do the same thing for now.
Yes, but you still need to maintain these targets. Automake takes care of
GC> We don't have 'dist', but we do have 'archive' to serve the same purpose.
GC> It uses bzip2. I wouldn't mind adding a 'dist' target that would use gzip
GC> instead. That's easy to do, and would make the system seem more familiar
GC> to developers who understand such conventions. But it would exist just for
GC> appearance's sake. It isn't actually useful, because our goal is to keep
GC> cvs releasable at every moment, not just on infrequent occasions when a
GC> release is declared.
Sorry, I don't think this contradicts "dist" existence. It's just another
name for the same thing...
GC> > . without speaking of automatic dependency tracking
GC> For gcc and perhaps msvc. What about borland? What about como? Anyway, we
GC> already use the autodependency method Tom Tromey invented for automake.
While I don't think automake supports neither borland nor como
dependencies tracking, we can hope that it will continue to develop and
support more compilers.
GC> > (and hopefully in the future automatic precompiled headers support)
GC> For gcc only? What about the EDG method used by como?
Again, I don't think it supports it already (but I could be wrong) but we
can expect to only gain from any future developments. And in the meanwhile
nothing prevents us from doing the same thing as we [would] do without
GC> Instead of maintaining these two files in parallel, I think our time would
GC> be better spent on finding a way to make them conformable, so that only one
GC> would take any real work to maintain. For example:
GC> zero_test_objects := \
GC> $(common_test_objects) \
GC> zero_test.o \
GC> zero_test$(EXEEXT): $(zero_test_objects)
GC> .PHONY: %_test.am
GC> @$(ECHO) $*_SOURCES = '$($*_test_objects)'
GC> @$(ECHO) $*_CXXFLAGS = '$$(AM_CXXFLAGS)'
GC> @$(ECHO) $*_LDADD = libtest_commons.la
GC> $make zero_test.am
GC> zero_SOURCES = alert.o alert_cli.o fenv_lmi.o getopt.o license.o
GC> zero_CXXFLAGS = $(AM_CXXFLAGS)
GC> zero_LDADD = libtest_commons.la
Unfortunately I don't think it can be automated entirely like this. There
are some exceptions.
GC> Does automake really require that ugly_mixture_of_lower_and_UPPER_CASE?
Yes. The lower case is used for the targets while the upper case is for
various automake "keywords".
GC> And is
GC> test_zero_CXXFLAGS = $(AM_CXXFLAGS)
GC> really necessary? Can't automake define a set of default flags?
Actually I don't think it's necessary in this particular case. It's
necessary in some other tests (e.g. test_xrang just above) to avoid the
above mentioned problem with using the same .c file for multiple targets.
Setting the flags explicitely (even if their value is the same as the
default one) forces automake to compile the file xrange.cpp twice: once for
the library and second time for the test. It is, of course, inefficient,
but it's also much safer as you don't risk to have subtle problems if you
ever don't use the same compiler flags for the main library and the test.
GC> BTW, this line
GC> seems out of place.
GC> Also BTW, as we discussed the other day, $(common_test_objects) is a list
GC> of objects because that lets me work more efficiently; putting them into
GC> a 'libtest_commons.la' library makes my work harder. I believe some tests
GC> won't work with the library approach if we use msw dll[im|ex]port.
So far all of them at least build...
GC> > Finally, let's put it the other way: what are the advantages of not using
GC> > autotools? We already have a working (barring last minute breakage since
GC> > our last tests) autotools-based system. It works under Linux, Cygwin and
GC> > MSYS
GC> I believe we'd need to update MSYS with the autotools packages that you've
GC> confirmed to work. Without doing that, here's what I get:
GC> configure.ac:28: error: possibly undefined macro: AM_INIT_AUTOMAKE
GC> Or was I supposed to run 'autogen.sh' first?
Yes, absolutely. Please see README.auto, I've tried to explain it there,
please let me know if/how can I improve this.
GC> Setting up build system for lmi:
GC> - aclocal
GC> aclocal: configure.ac: 297: macro `AM_OPTIONS_WXCONFIG' not found in library
GC> aclocal: configure.ac: 311: macro `AM_PATH_WXCONFIG' not found in library
GC> Automatic build files setup failed!
This is explained in README.auto too: you need to either install wx or set
ACLOCAL_AMFLAGS to "-I $wxwin" so that aclocal could find wxwin.m4 file
(which is in $wxwin directory, i.e. wx root).
GC> > and normally should require much less maintenance than the original
GC> > makefiles in the future. So what prevents you from using it?
GC> If I use my own makefiles, then I don't need to learn autotools. Neither
GC> do my coworkers.
This is definitely true but I wonder if you really need to learn
autotools. Just as not everybody needs to know the details of the existing
makefiles (or at least I hope so, as you know it took me quite some time to
learn them myself) I think it's quite possible to use and modify configure
and Makefile.am without spending time on learning autotools. Of course, I
also believe that sooner or later you will become quite acquainted with
autotools just by immersion. But then I don't see it as a big problem ;-)
GC> And the lmi makefiles have capabilities that aren't supported by
Sorry, I don't see how is this possible -- autotools are a strict
extension of the makefiles. autoconf can generate any makefile trivially
(by renaming existing makefile to makefile.in and not doing anything in
configure) and automake allows you to add arbitrary fragments of makefiles
in Makefile.am which are copied verbatim to the makefiles it generates.
GC> So I have to imagine it's not easy to support another compiler,
GC> particularly an EDG compiler that uses a separate prelinker for templates.
It would be interesting to try EDG. I think it hould work, after all there
are plenty of projects claiming to support it and using autoconf (starting
GC> Beyond that, the makefiles do various other things. The 'regression_test'
GC> target is very important to us, for instance. The 'check_idempotence'
GC> target guards against a class of problems not contemplated by autotools.
GC> I don't think it's appropriate for us to spend time making autotools
GC> support these things.
We don't have to -- we can just use the existing makefiles with autoconf.
The time taken to make some targets (lately check_conformity) to work with
autoconf is not really due to autoconf but to checking that it really works
under all of mingw32 (where it does, of course), cygwin (where it usually
doesn't) and Linux.
GC> The autotools approach is not without its problems; here's one rant:
There are many, many rants against autoconf. This one is quite stupid IMO
but there are some real problems with autotools. At least half of them are
related to it forcing a GNUish project organization -- as this is the case
for lmi already, it shouldn't be a problem. The other half hopefully
shouldn't affect us as we have a rather simple configure.
GC> I don't mind continuing to support autotools as long as we can find a
GC> way to make maintenance simple. Consider:
GC> revision bytes
GC> Makefile.am 1.15 17062
GC> autogen.sh 1.4 2005
GC> configure.ac 1.17 22959
GC> 'autogen.sh': This is tiny and unlikely to require much maintenance.
GC> 'configure.ac': Half the nontrivial changes have served to accommodate the
GC> four C99 functions mentioned above or the __argc problem we removed. I can
GC> rewrite the C99 things as described above--saving half the maintenance if
GC> past experience predicts the future well.
The nontrivial parts of configure are those dealing with external
libraries detection. And note that for wx itself, 90% of the code comes
from wxwin.m4 which is part of wx and not lmi (aclocal merges configure.ac
and any m4 files it needs into configure).
GC> 'Makefile.am": I believe my proposal to rewrite 'objects.make' reduces this
GC> file to about one-twentieth of its current size, and makes maintenance more
GC> reliable and easier through automation.
GC> What do you think?
I think it's a bit strange to do it like this but it just might work. OTOH
I honestly still don't understand what's wrong with copying [fragments of]
the existing makefiles to Makefile.am and just continuing to use them as