Boost logo

Boost-Build :

Subject: Re: [Boost-build] feature, properties, variants, and all the rest
From: Stefan Seefeld (stefan_at_[hidden])
Date: 2017-09-29 18:33:25


On 29.09.2017 14:20, Steven Watanabe via Boost-build wrote:
> AMDG
>
> On 09/29/2017 09:13 AM, Stefan Seefeld via Boost-build wrote:
>> On 25.09.2017 19:49, Steven Watanabe via Boost-build wrote:
>>> The interaction between SEARCH and LOCATE requires
>>> the boundname of targets with an explicit LOCATE to
>>> be set early.
>>> SEARCH on <x>file1 = /path1 /path2 ;
>>> LOCATE on <x/path1>file1 = /path1 ;
>>> The boundname of <x>file1 is /path1/file1
>>> and it gets a hard dependency on <x/path1>file1
>> This reminds me of a (slightly) tangential question: how are header
>> dependencies handled by bjam ? In particular:
>>
>> * it appears as if source code is scanned without any true
>> pre-processing. Doesn't this lead to false positives (such as
>> conditional include directives) ?
> Yes. It also causes false negatives (#include through a macro).

Right. Ouch !
>> * how are include directives mapped (bound) to actual files ? Do you
>> interact with the selected compiler to determine the absolute path ?
> They're found using the include path.
> (Headers in the compiler's default include
> path will not be found)

Again, ouch ! (Of course, in practice this is a minor issue, as those
headers rarely become artefacts of the current build itself, so can be
assumed stable.)
>> * it seems to me that letting the compiler itself do this work (the
>> typical "make depend" idiom, using commands akin to `gcc -M`) would
>> solve these issues. What are the reasons bjam doesn't use that strategy ?
>>
> - It's more efficient, since each header only needs to be read once.

That's true. But I would never trade efficiency for correctness.

> - It can scan headers that are generated during the build.

and so can a compiler-based approach.

>>> In addition, it's impossible to determine
>>> a target's fate without knowing its location,
>>> as you need an actual file to check the timestamp.
>>> To make this work, you'd need to merge make0 into
>>> make1 completely. This creates another problem,
>>> because the cycle detection in make0 requires a
>>> strict depth-first search.
>> I see "scc" related code in multiple locations, not just in make0().
>> Assuming that that's the code used to detect cycles, how does it work,
> scc = Strongly Connected Components.
> The part in make0 is an implementation of Tarjan's algorithm
> https://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm.

Right, I found that. Thanks.

>
> The other parts are for fixing up the result when
> the dependency graph changes due to header scanning.
>
> Basically we treat a cycle as if the entire cycle
> were a single node. This works as long as none of
> the targets have updating actions attached to them.
> A #include cycle exists in the 'internal nodes',
> which never have updating actions.

Ah. So if I don't handle includes with bjam, I can simply ignore all
that code ?

>> and why isn't it a local call in make0 that
>> simply raises an error if a cycle is detected ? In fact, why do cycles
>> merely generate warnings, rather than errors ?
> I don't know. I think it was originally that way,
> and I never changed it.

OK. What behaviour do you expect users would prefer ? Error or warning ?

And further, right now the cycle detection is run when a target update
is requested, so the search is constrained to the subgraph the target is
part of.
Wouldn't it be useful to include the entire graph in this validation step ?

Regards,
        Stefan

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

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