Boost logo

Boost-Build :

Subject: Re: [Boost-build] feature, properties, variants, and all the rest
From: Stefan Seefeld (stefan_at_[hidden])
Date: 2017-07-28 18:59:51


On 28.07.2017 14:15, Steven Watanabe via Boost-build wrote:
> AMDG
>
> On 07/28/2017 11:25 AM, Stefan Seefeld via Boost-build wrote:
>> Hi Steven,
>>
>> I'm coming back to a discussion from a long time ago...
>>
>> On 23.12.2016 16:39, Steven Watanabe wrote:
>>> Conditional properties are evaluated when
>>> processing target requirements. The actual
>>> algorithm evaluates all conditionals repeatedly,
>>> until it reaches a fixed point.
>>>
>>> Ex:
>>>
>>> rule c ( properties * )
>>> {
>>> if <variant>debug in $(properties)
>>> { return <define>DEBUG }
>>> }
>>>
>>> Requirements:
>>> <toolset>msvc:<link>shared <link>shared:<variant>debug <conditional>@c
>>>
>>> Initial properties:
>>> - <toolset>msvc
>>> Round 1:
>>> - <toolset>msvc <link>shared (Other conditionals are not satisfied)
>>> Round 2:
>>> - <toolset>msvc <link>shared <variant>debug
>>> Round 3:
>>> - <toolset>msvc <link>shared <variant>debug <define>DEBUG
>>> Round 4:
>>> - <toolset>msvc <link>shared <variant>debug <define>DEBUG
>>> (Identical to round 3, terminating the algorithm)
>> This describes a (domain-specific) constraint solver. Are there any
>> chances this could lead to undefined behaviour (for example if the order
>> in which the conditionals are evaluated influences the outcome) ?
> I suppose that it's theoretically possible,
> but I've never seen it happen nor have I heard
> any reports of it. In order for this to occur
> you'd need to have a cycle.
> The normal uses of conditionals are
> a) add a compiler flag for a specific compiler (normal conditional)
> b) add include/library paths if they are found (ac.check-library)
> c) disable a target for broken compilers (config.requires)
> d) add #defines to control dllexport/visibility (normal conditional)
> e) force a specific build variant for some compiler (normal conditional)
> which results in properties being resolved in this order:
> toolset -> link/runtime-link/variant -> cxxflags/linkflags
>
>> What
>> are the odds that it will result in an infinite loop ?
> It terminates with an error if it fails to
> converge after a number of iterations equal
> to the number of conditionals + 1.
>
>> Or does the
>> design necessarily lead to a stationary state ?
> It's guaranteed to converge in the absence of cycles.
> If you do something like this you'll have a problem:
> <toolset>gcc:<link>static <link>static:<toolset>msvc
> <toolset>msvc:<link>shared <link>shared:<toolset>gcc
>
>> What about invalid
>> (conflicting) constraints ?
>>
> That should be an error.

I'm actually thinking of cases where (assuming multiple passes) a single
conditional may yield different (mutually exclusive) results. Consider

1) if defined(A) define(B) else define(C)
2) if not defined(B) define(A)

for which the final state depends on whether you start the evaluation
loop with 1) or with 2). It seems impossible for b2 to flag this as
wrong, and it may even be right, as long as a specific order of
evaluation of the conditionals as guaranteed. But in the absence of that
order, it simply is undefined.

Of course, looking at a single conditional statement (as in your
original example), there always is an implied order. But in real-world
scenarios that may not be the case (if for example configure checks are
combined with multiple prerequisite targets that all contribute to the
final property-set for a given target.

How would b2 handle this ?

Thanks,
        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