Boost logo

Boost-Build :

Subject: Re: [Boost-build] RFC: Boost.Build Python Prototype
From: Vladimir Prus (vladimir.prus_at_[hidden])
Date: 2016-11-15 09:25:07


Stefan,

On 15-Nov-16 4:02 PM, Stefan Seefeld wrote:

>> - Yes, metatargets are complex parts of Boost.Build, but I think it's
>> an essential parts. The fact that you can generate a metatarget with
>> different properties gives quite some flexibility - in particular
>> Boost users that to build multiple variants of the libraries, and run
>> tests in different combination of properties. When you say that it's
>> easy to chain some invocations, I think you just gloss over the issue.
>
> Can you demonstrate (by virtue of a use-case) what I'm missing by not
> supporting multi-variant builds ? What is the difference (in
> functionality) between `b2 --toolchain=gcc,clang` and `b3 --tool=cc:gcc
> && b3 --tool=cc:clang` ?

The primary example is not that, it's this:

   unit-test test_static
        : test.cpp /boost/test//unit_test_framework : <link>static ;
   unit-test test_shared
         : test.cpp /boost/test//unit_test_framework : <link>shared ;
   unit-test test_generic : test_generic.cpp ;

This builds some parts of the project with two different values of
the 'link' property, while building the rest only once.

Also, "b3 --tool=gcc:gcc & b3 --tool=cc:clang" might work if the
decision what variants to build is done by user. In case of Boost,
the decision which variants to build is done inside top-level Jamroot,
using various properties include the toolset. I don't suppose it
would be good if users were required to use non-portable shell scripting
for that.

BTW, may I suggest we don't use "b3", since "b2" stands for
"Boost.Build", not "Boost.Build V2".

>> - You also seem to not have any notion of portable build properties -
>> instead each tool just accepts whatever it pleases. I can't see any
>> support for automatically generating build directories based on
>> properties. There does not seem to be any support for computing final
>> build properties based on requested ones.
>
> You are right, that is still missing. Indeed, my putting together the
> mechanism for communicating properties across targets felt quite ad-hoc,
> and I would like to consolidate that into something more formal. I'd
> appreciate your help with that ! :-)
> And for avoidance of doubt: I'm not at all against establishing build
> directory naming conventions based on properties. I just don' want to
> bake that into the tool itself, i.e. I'd rather make that something that
> can be "plugged in" per project.

It is fine to customize that, but I think build variants that work out
of box is also key part of Boost.Build appeal. Users should not have to
configure this manually.

>> - Looks like the action/target mechanism basically reimplements all
>> of Boost.Build generators
>
> Yes, that is indeed my goal. Is there anything fundamentally wrong with
> that approach ? (I'd rather avoid layering the Python front-end on top
> of a Jam layer, as that leads to overly complex (and thus rigid) code.

Boost.Build generators have nothing to do with Jam code, really. That's
the code in
https://github.com/boostorg/build/blob/develop/src/build/generators.py
that determines the best transformation from sources
to targets.

> It is the underlying idea that is important and useful to preserve. So
> again, can you demonstrate (ideally by virtue of a few use-cases) how my
> suggested approach isn't able to serve the requirements ? Or is this
> strictly about terminology, i.e. BBV2 calling it "generators" and me
> calling it "composite targets" ?

I suppose it's hard to compare 1200 lines of code, plus a bunch of
actual generators, with a fairly small prototype :-)

Generators are similar to your composite targets, except that they
come with a selection merchanism. Where you declare 'library' function
and must use it, Boost.Build declares a generator with target type of
SHARED_LIB and source type of OBJ and requirements of <toolset>gcc,
and then maybe another with requirements of <toolset>msvc.
Then, when generating a 'lib' metatarget, an appropriate generator
is selected and run, and can in turn use generators to convert its
sources to OBJ type.

In other words, you have this:

     from b3.targets.library import *
     hello = library('hello', ['hello.cc'])

and

     def map_src_to_obj(s):
             return rule(splitext(s)[0]+'.o', s, cxx.compile,
                         params=dict(link='static'))

Which hardcodes specific 'library' and 'cxx.compile'. In Boost.Build,
in both places we use a mechanism that uses a generator appropriate
for the target type and properties, which sounds better than
hardcoding enough - and has enough of tricky details to make reuse
worthwhile.

-- 
Vladimir Prus
https://vladimirprus.com

Boost-Build list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk