Boost logo

Boost-Build :

Subject: Re: [Boost-build] feature, properties, variants, and all the rest
From: Steven Watanabe (watanabesj_at_[hidden])
Date: 2017-08-04 04:41:43


AMDG

On 08/03/2017 09:26 PM, Stefan Seefeld via Boost-build wrote:
> On 03.08.2017 20:37, Steven Watanabe via Boost-build wrote:
>>
>> On 08/03/2017 03:57 PM, Stefan Seefeld via Boost-build wrote:
>>> Consider again my earlier example, where the target "C" depends on some
>>> config checks "A" and "B", during the update of which some properties
>>> will be set that are used to build C.
>>> I think the spelling was
>>>
>>> exe C : C.cpp : [ check-target-builds B : <use>B ] ;
>>>
>>> So, let's assume that one of the usage requirements of "B" affects the
>>> choice of the toolset, or some other essential property that influences
>>> the qualified filename .../C.exe.
>> That's not allowed. Only free features can be
>> used in usage-requirements. The appending
>> behavior of free features is necessary. If
>> usage requirements can override properties, then
>> it's essentially impossible to maintain consistency.
>
> Can you give an example of a scenario giving rise to inconsistency,
> would this be allowed ?
>

  There's no clear priority for usage-requirements
from two different dependencies. As a result,
if two dependencies have contradictory usage
requirements, it can only be a hard error, as
neither one can override the other. Propagated
features are even more problematic because they
are supposed to be passed on to dependencies.
Therefore propagated usage requirements would
have to spread out to the entire dependency graph,
which is completely impractical.

> <snip>
> Can you elaborate ? (I believe I understand the distinction between
> "main targets", "virtual targets", and "jam targets". However, from an
> operational POV, I wonder what happens: If I invoke `b2 C`, "C" is
> recognized as a target, so needs to correspond to something the
> scheduler knows, right ? Similarly, if I want `b2 C` to actually build
> some .../C.exe, I need to make that .../C.exe a prerequisite of C, no ?
> (If not, can you please outline to logic leading to the making of
> .../C.exe from the invocation of `b2 C` ?)

  It's pretty simple. The list of main targets is
lowered to a list of virtual-targets. These virtual-targets
are then lowered to Jam targets which are passed to
the engine.

> In Faber, I was able to do the multi-stage thing, i.e. have a first
> "config" phase (done in-sync while the "fabscripts" - the equivalent of
> Jamfiles - were read in), which resulted in a fully constructed
> dependency graph. Then, the actual build would simply execute that
> dependency graph (or parts of it expressed by the goals from the
> command-line).
>
> But I came to the conclusion that this results in a messy encoding of
> dependencies (and an equally in-elegant process), so I'm now rewriting
> the necessary logic to make the dependency graph dynamic, i.e. add to it
> while it is being executed.

  I think I understand where you're coming from now.
Boost.Build makes no attempt to model configure
checks explicitly in the dependency graph, which
seems to be what you're trying to achieve. In b2,
configure checks just take advantage of the ability
to inject arbitrary code into the target generation
phase. The main advantages and disadvantages of
this approach are:
+ It's easy to retrofit into an existing system
+ The dependency graph has a fairly simple representation.
  I honestly have no idea how to represent configure
  checks, as they behave quite differently from normal
  dependencies.
- Running configure checks in parallel is difficult to impossible
- The implicit dependency on the configure check means
  that the actual dependency graph is incomplete, which
  gets in the way if you want to process it in some way
  other than just updating.

> As it is my understanding that b2 does at
> least most of it, too, I want to understand how it does it, and what
> requirement and restrictions it puts on the input.
>

  The main restriction on modifying the dependency graph
at the low level is that no out-edges can be added to
a target after it has been updated. This is easy to
guarantee as long as you have declarative target definitions.

> Again, many thanks for all your help. I hope this will be useful not
> just for my own understanding, but for others, too.
>

In Christ,
Steven Watanabe


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