On Apr 25, 2009, at 8:33 AM, Ralf Wildenhues wrote:

I hardly know scons.  What's cool about it that autotools don't have?



This is worthy of its own thread, so I re-subjected the mail.

I worked up a prototype usage of scons in OMPI a few years ago. It was actually fully functional -- it built (and installed? I don't remember, but I assume so) a usable OMPI. The work is still available here:

    https://svn.open-mpi.org/trac/ompi/browser/tmp-public/scons

The OMPI source tree was quite different back then; that work would need to be significantly updated for it to be relevant to today's OMPI SVN trunk.

Here's what I remember liking (and not liking) about scons. Take this with a big grain of salt -- this was a few years ago; both my memory may be bad and things may (likely) have changed in scons since then (I have not kept up with scons since). Note that *all* of this is IMHO.

Likes:

+++ Treating the whole tree as a single entity: with a traditional "make" setup, you have a standalone Makefile in each directory in your tree, and upper-level Makefiles effectively "cd subdir; $(MAKE)". scons treats your entire source tree as one entity (even though you can have multiple scons data files scattered throughout the tree -- you don't have to have everything in a single, top-level file). Specifically: scons will analyze the entire tree at once, decide what to build, and build it. There's no notion of recursive traversal.

Sidenote: of course, you can implement such a system with Make as well, but, IMHO, make is not well setup to handle that (especially for very large source trees). Automake does it a bit better, but it would still be cumbersome to have (effectively) one Makefile.am for the entire OMPI tree (meaning: no recursive traversal, even if we had a single top-level Makefile.am + lots of Makefile.include's scattered around the tree).

+++ I was writing [python] code to build OMPI. This was incredibly natural; significantly easier than writing rules with embeded bourne shell scripts (sometimes with extremely awkward quoting). Some of my friends / colleagues disagreed with me -- they worried that you would then need to QA the build system (because it's developer-written code). But I contend that we have to do that today already (look how much m4 code is in contrib/*m4 and elsewhere in the OMPI tree!).

+++ I had subroutines -- subroutines! -- for common (to OMPI) build actions. This was *fantastic* -- I could customize the build process by writing real code, and having the full power of python behind it. For example, building a component was something trivial like this:

Import('ompi_build_component')
ompi_build_component(sources = Split("""
ptl_tcp.c
ptl_tcp_component.c
ptl_tcp_peer.c
ptl_tcp_proc.c
ptl_tcp_recvfrag.c
ptl_tcp_sendfrag.c
ptl_tcp_sendreq.c"""))

The ompi_build_component() python subroutine (that I obviously wrote) that did the Right Thing to build the OMPI components, regardless of whether we were slurping components up into libmpi (etc.) or building as standalone DSOs.

Having the ability to effectively extend scons and have my own subroutines for project-specific functionality was simply fantabulous. This is probably one of the two biggest things that I liked about scons -- I had subroutines (and the power of a real/full scripting language) that I could invoke anywhere in the project's source tree.

--> From the above example, I don't see/remember offhand how the TCP PTL's .h files got slurped into the distribution tarball; it's possible that I stopped doing the scons work before I got to the part of making the tarball. Or perhaps scons did source code analysis and just figured it out...? I honestly don't remember.

+++ No need for a fixed, pre-determined directory layout. A decision that we made way back in the beginning of Open MPI was that we wanted to make it [relatively] easy for developers to add new frameworks and components -- essentially, make a new directory, put in a few specific files, and then re-run autogen.sh. Specifically: normal developers shouldn't have to edit the configure/build system to add new frameworks and components. I still stand by this decision; it would have been a Big Mess if we had to educate all of our developers in the intricacies of the autotools about how to add new frameworks/ components (in short: the vast majority of developers don't know squat about configure/build systems, so we wanted to make the bar as low as possible to add new frameworks/components without needing to touch the configure/build system at all since it's a relatively common OMPI developer action).

This decision ended up generating *significantly complicated* autogen.sh and various m4 scripts in OMPI's pre-configure/configure/ build system. Early in 2009, Brian Barrett and I sat down with another OMPI developer and tried to explain OMPI's configure/build system. Needless to say, it was a many-hour conversation, and the other developer was reeling when we were all done. :-)

With scons, I had subroutines to -- at build time -- discover OMPI's frameworks and components, and then build them. Specifically: with scons, it was trivial to have a pre-determined directory layout (just like the autotools). But it was also fairly straightforward to have a dynamic directory layout: I wrote real python logic to go look at a directory, decide if it was a valid framework/component, and if so, go build it.

This was the 2nd of the "two biggest things" that I liked about scons. It's likely that OMPI is fairly unique in its "we want to discover frameworks / components at run time" requirement, but I would imagine that other plugin-based projects might use such functionality if it were easy to do (it is *not* easy to do with the current autotools!).

Disclaimer: like I mentioned above, when I did this, the OMPI tree was significantly different than it is today. I'm don't remember how I handled the configuration vs. building of conditional components (e.g., only build the openib component if you have OpenFabrics devel support installed on your system). I.e.: just "discovering" a component at build time is not enough -- it also has to have been configured properly first. I don't remember the details of what I did there.

+++ As mentioned above, you could split the build specification in multiple files throughout the tree (similar to how we have Makefile.am's throughout the tree). A nice feature is that each separate scons file (named SConscript) was in its own python namespace. This gave a nice, well-defined mechanism for sharing data without fear of accidentally tromping on variables in another file elsewhere in the tree.

+++ There were pre-defined constructs (subroutines, IIRC?) that were Automake-like in that you would just say "build a library, here's the sources" -- and the right Magic happened behind the scenes. Such a feature is pretty much a given for a build system, of course -- but it did make the learning curve for "write code to build your code" much less steep.

+++ Scons would build a distribution tarball that would include enough scons bootstrapping such that the end-user did not need to have scons pre-installed just to build Open MPI. This was(is) a huge requirement -- it was a deal-breaker if a build system didn't support this (I believe that, at least at the time, only the autotools and scons did this).

+++ Support for Windows native Microsoft build system stuff. I didn't get to investigate this at all, but supposedly scons would generate project files that could be slurped into MS Developer Studio (or whatever it's called). That would have been nice.

Dislikes:

--- Scons also tried to replace Autoconf by allowing you to embed tests in the build process (e.g., built-in subroutines the equivalent of AC_CHECK_HEADER, etc.). This has the side effect of running the tests *every* time you build. Even if the answers are cached and the test is therefore really fast, that just seems weird to me. Configuration is different than building. Indeed, look at the length of OMPI's configure script -- there's no way I'd want to run that every time I do a build (even if the answers are cached). As a developer, I build OMPI many, many more times than I configure it. In the OMPI scons solution that I coded up, I still used Autoconf/ configure; it output a file with all the results of its tests that was then slurped up into scons for building.

--- Scons support of various compilers was not nearly as complete / comprehensive as Libtool's.

--- I had to learn Python (at least, learn enough to get by). Python seemed like a neat language and it wasn't *that* hard to learn, but I started from zero and had to do a bunch of learning before I could really use scons. There were definitely times where I had to go spend an hour and figure something out in Python before I could continue what I wanted to do in scons. This is probably true of most tools if you're not already familiar with the back-end language, so it may not be a fair "dislike", but I mention it anyway. Did I mention that this is all IMHO? :-)

Hope this helps!

--
Jeff Squyres
Cisco Systems

Reply via email to