Boost logo

Boost :

Subject: Re: [boost] Announcement: Faber, a new build system based on bjam
From: Stefan Seefeld (stefan_at_[hidden])
Date: 2017-11-30 13:38:15


Hi Hans,

let me get right through to the points not yet discussed elsewhere.

On 30.11.2017 05:51, Hans Dembinski wrote:
>>> 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?
>>
>> "hello" is a binary built from a "hello.cpp" source file and a
>> "greet" library provided from another ("greet") module (thus using
>> Pythonic syntax, we refer to the latter as "greet.greet").
>> If the library would have been built by the same module, the above
>> would simply be
>>
>> greet = library('greet', 'greet.cpp')
>> hello = binary('hello', ['hello.cpp', greet])
>>
>> as is in fact done in this example:
>> https://github.com/stefanseefeld/faber/blob/develop/examples/implicit_rules/fabscript
>
> I think source code is allowed to be verbose, but it should not be
> redundant, especially if said redundancy could lead to mistakes. I
> suppose you run the fabscript through a special interpreter, not just
> the standard Python interpreter.
(no special interpreter involved here, it's all standard Python)

> If so, then you can use this shorthand syntax instead:
>
> greet = library('greet.cpp')
>
> That way, one cannot make a mistake like this
>
> greet = library('great', 'greet.cpp')

Ah, well, now that's a fundamental limitation of Python. In the line

greet = library('greet.cpp')

you get a variable ("greet") that holds a reference to a "library"
object. Take note that that object has no notion of it being referred to
by the name "greet", and thus it doesn't know what name it needs to
assign to the compiled and linked library, unless I provide that
explicitly. Thus

hello = binary(['hello.cpp', greet])

likewise wouldn't know how to name the binary file, and the 'greet'
library object still having no name, the compiler couldn't refer to it
either.

I was actually thinking of ways to merge the two (the name of the
variable, and the intrinsic names of the library and binary artefacts)
to avoid that perceived redundancy, but got in all kinds of additional
complexities trying that. The main point being that I really want to
take advantage of this being written in a well established language, and
using its idioms.
SCons is a very good (or bad, actually) example of what happens if you
technically use an established language without paying tribute to its
idioms and established practices. I don't want to repeat that error.

>
> To make the syntax very consistent (the Zen of Python says: "There
> should be one - preferably only one - obvious way to do it."), you
> could define all build items like library and binary in this way:
>
> def binary(*inputs, attribute1=default1, attribute2=default2, …): ...
>
> All positional arguments would always be inputs of any kind, like a
> source file or a library. If you always use positional arguments
> consistently like this, then my complaint about ambiguity is gone,
> because there is a clear rule which is easy to remember.

Perhaps you should think this through for a while longer (the way I have
thought about it for months :-) ). I believe you will come to a very
similar conclusion as I have.

>
> Attributes would be passed consistently via keywords. They have
> reasonable defaults that Faber picks for me. Like, if I want another
> file extension for a library than the default for the platform. For
> libraries, I could specify whether to build a static or shared one. Or
> if I really don't want to name the library "greet", I could pass the
> keyword name="great".
>
> This declaration enforces the use of keywords for attributes,
> positional arguments are not allowed for attributes, which is a good
> for clarity.
That's actually a good point: I can change the definition of these
functions (`rule`, artefact constructors, etc.) to explicitly forbid
positional arguments for anything but the required arguments. I agree
that would prevent certain errors. Thanks for the tip !

>
>>> 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.
>>
>> rules take at least two (positional) arguments (an action and a name
>> for the target artefact). All other arguments have default values,
>> and thus *may* be given as keyword arguments or as positional
>> arguments, depending on your preference. (But given that a "source"
>> argument is still very common, I just chose to not spell it out as
>> "source=hello" for compactness.) As a fabscript author you are of
>> course free to name all your rule arguments, if that helps
>> readability. I not inventing anything here, but rather take the most
>> natural approach possible following Python language rules and idioms.
>>
>>> 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.
>>
>> Again, Python allows you to name all arguments. This is up to the
>> caller, not the API designer. As far as the API is concerned, rules
>> have two mandatory arguments, so it wouldn't make sense to make them
>> keyword arguments.
>
> I hope I explained better above what I had in mind. I agree, of
> course, that writing things like source="bla" all the time is annoying
> and superfluous.
>
>> But if you prefer some help in drafting your fabscript logic, there
>> are good tools to help interactively editing Python code, including
>> code completion etc.
>> That's the beauty of using Python: we can tap into a fabulous
>> ecosystem of tools and modules, including ipython, jupyter, spyder,
>> etc., etc.
>
> Agreed, that's why I am also in favour of using an established
> scripting language to describe a build tree. I am sorry that I am so
> critical, but we have some common ground. All this is meant in a
> constructive way.

OK, great to hear. I'm taking it in a constructive way.

Stefan

-- 
      ...ich hab' noch einen Koffer in Berlin...
    

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk