Subject: Re: [boost] Announcement: Faber, a new build system based on bjam
From: Hans Dembinski (hans.dembinski_at_[hidden])
Date: 2017-11-29 12:59:26
> On 22. Nov 2017, at 14:43, Stefan Seefeld via Boost <boost_at_[hidden]> wrote:
>>> On 22. Nov 2017, at 09:00, Richard Hodges via Boost <boost_at_[hidden] <mailto:boost_at_[hidden]>> wrote:
>>> Stephan wrote:
>>>> In case it isn't obvious: I very much welcome collaboration, so if you
>>>> want to contribute (be it more tools or even entirely new
>>>> functionality), I'd be happy to talk.
>>> Nothing would please me more than to be able to dump the horrific syntax of
>>> cmake. I have often thought that python would be the obvious language for a
>>> replacement. There was of course a similar tool called SCONS once, which is
>>> python also. It seems to have fallen by the wayside.
> Not at all. SCons is well alive (and I have contributed to it in the
> past, even mentored a GSoC student for it).
> There are fundamental differences, though, and (as you mention it) I
> think its interface is quite unpythonic, unfortunately, despite the
> superficial fact that it uses Python for its SConscripts.
I was referring to the fact that big OS projects moved away from SCons to CMake, notably KDE. This article nicely explains some issues with SCons.
I think that using an established scripting language to write build scripts is a great idea. I like that about Faber and about Scons, and I think it is bad that CMake established yet another scripting language, effectively.
The annoying thing about SConscripts is that it looks like Python, but the behaviour is different, since the order of statements is not maintained. It looks like Python, but it behaves like a Makefile, where only the dependencies of the statements matter and not the order in the code. This is inconsistent.
>> I am not a big fan of CMake and I do like Python very much, but the success of CMake shows me once again that people have surprising needs they are usually not concerned about how powerful the tool is for the technical expert. Mostly it is about making simple things simple and saving time for the average guy.
> Yes. But despite its popularity, I disagree with CMake's approach on a
> very fundamental level (it being a build system generator, rather than a
> build system), as it makes things oh so much more complex. Everything
> works well until it doesn't, at which point all hell breaks loose.
> That's very typical for macro-based languages (think latex, m4). And it
> had to reinvent its own language, in a rather ad-hoc manner (i.e.
> started with a simple declarative syntax, but then had to expand on that
> to cover other use-cases. "Now you have two problems." comes to mind (if
> I may paraphrase).
I agree with you on all points, like most people would. Like I said, I am not in love with CMake either.
>> Here is my list why I believe CMake is so popular (ordered by perceived priority):
>> 1) it is a high-level language for describing build trees, it allows me to ignore much of the technical low-level stuff, like how to call the compiler with the right options
>> 2) the commands have nice long names which makes CMake build scripts almost self-documenting
>> 3) it ships with a maintained collection of scripts to configure and include external libraries
>> 4) there is a company behind it which continuously adapts cmake to its user base and advertises its use
>> 5) the documentation is ok
>> 6) it is comparably fast (Scons was rejected because it is slow, AFAIK), especially when you use the Ninja backend
>> 7) it has a ncurses-based configuration interface
>> 8) it produces pretty output
>> Since cmake has already an impressive following, this adds the most important item on the top of the list:
>> 0) people already know the tool and don't have to learn it
>> Boost.Build does not offer points 0-4 and 7
> I'd contest that. Boost.Build does hide most details about tool
> internals (how to invoke the compiler, say), until you need to plug in
> your own tools.
Ok, you are right.
>> # define some actions
>> compile = action('c++.compile', 'c++ -c -o $(<) $(>)')
>> link = action('c++.link', 'c++ -o $(<) $(>)')
>> # bind artefacts to sources using the above recipes
>> obj = rule(compile, 'hello.o', 'hello.cpp')
>> bin = rule(link, 'hello', obj)
>> test = rule(action('run_test', './$(>)'), 'test', bin, attrs=notfile|always)
>> default = bin
>> This looks rather mathematical and abstract. I appreciate math, but many people don't. The syntax is very terse, which I think is not good. For build scripts, I think that Cmake has a point with its long and descriptive names. I touch a build script only very rarely. If I touch it very rarely, I want it to be very easy to read, because I forgot all the little details of how it works after a few months. I learned CMake basically by looking at build scripts from other people, not by studying a documentation from ground up. This is incredibly useful, nobody likes to study manuals.
> Thanks for your feedback. I may rethink how I document Faber. As a
> developer, I typically much prefer a bottom-up approach, starting with
> the lowest details, then adding layer upon layer of abstraction. So what
> you are looking for is likely persent in a higher layer. Have a look at
> one of the other examples:
Yes, I think providing high-level examples first is better to draw people in.
> from faber.artefacts.binary import binary
> greet = module('greet')
> hello = binary('hello', ['hello.cpp', greet.greet])
> rule(action('test', '$(>)'), 'test', hello, attrs=notfile|always)
> default = hello
> https://github.com/stefanseefeld/faber/blob/develop/examples/modular/fabscript <https://github.com/stefanseefeld/faber/blob/develop/examples/modular/fabscript>),
> which uses higher-level artefacts (`binary`, `library`) and doesn't
> require the user to define his own actions to build.
This example remains cryptic.
from faber.artefacts...: artefacts? The term "artefact" is very general and non-descriptive. The first definition provided by Google is essentially "human-made thing".
Then, I have to type many redundant things here. Note, the many occurrences of greet in these two lines
greet = module('greet')
hello = binary('hello', ['hello.cpp', greet.greet])
It seems like hello is a binary which depends on 'hello.cpp' and the module greet. Why the latter?
The rule to make a test is very cryptic. The action takes several positional arguments, and I can only guess what each positional argument does. I am also critical about this in bjam. By using a syntax that uses a lot of positional arguments, you need to read the documentation to figure out what is going on. If you are lucky, the author provided comments for each positional argument, but then one might as well use keywords which are self-documenting. This is what CMake does well, IMHO.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk