Re: Project options and other format enhancements (and dropping "variants")



On Thu, 2017-09-14 at 20:59 +0100, Angelos Evripiotis wrote:
Hi!

Hi Angelos !

Thanks for your feedback...


This plan looks like it nicely addresses some concerns that I had, which you
listed:

    * Combinatorial explosion of variants needed to express multiple options,
      e.g. with{,out}_poll__with{,out}_sqlite__with{,out}_readline__with{,out}_gdbm
      etc.

    * Global selection of variant options from the CLI, e.g. 'enable all
      asserts everywhere', 'build everything without optimisation', etc.

I don't think it addresses these ones I also have:

(1) Building particular elements for debugging

i.e. while keeping the rest optimised. In the options world, I think this means
changing some options selectively from the command-line. Perhaps something like
this would be workable: 'bst build app1.bst --option mylib.bst:debug=true'.

Enabling or disabling options for a specific element only is tricky;
because it's also very important to be able to express option
conditionals in project.conf (because you want to make sweeping
statements which optionally apply to the whole project as well).

That said, the S-Expression parser is very extensible, so it would be
conceivable to write conditions which say, evaluate to true if a given
string is found in a list; like say:

  (?):
    condition: (contains debug_elements "mylib.bst")
    value:
      random-key: The value I would apply if mylib is on the debug list

(2) Allowing elements to specify what they need from their dependencies

This is so that we can easily tailor to the needs of each pipeline within a
project. This worked wonderfully with variants, I think the problem was that
each variant was mutually exclusive.

Might we be able to use options in 'depends' declarations in a similar way?
e.g.:

    app1.bst:
        ...
        depends:
            - filename: foo.bst
            options: flying-ponies
        ...

    app2.bst:
        ...
        depends:
            - filename: foo.bst
            options: dancing-badgers
        ...

Yes, this is really what I like so much about variants.

The problems I have with moving forward for a full blown variant
solution with competing orthogonal variants, are mostly that:

  o It's going to be very, very tricky to implement.

    We already have an imperfect algorithm for resolving variants when
    there can only be one variant per element. The solution which works
    exactly to spec takes several minutes to solve (so already we need
    work to get it right with a proper constraint solving algorithm or
    engine, which still wont work in linear time but should be usable).

  o While it may be easy enough to explain the rules of constraint
    resolution to the user, it will often be difficult for the user
    to easily predict what variant of what element will be chosen.


This second point, Jürg pointed out is already true when variants are
limited to one per element; because there are some complex cases where
a variant will be chosen implicitly, simply because it's the only
variant which agrees with an orthogonal element in the graph which does
have some explicit variant chosen.

The rules seem to be very clear and easy to reason about when there is
only one variant per element, but I can see this getting frustrating to
deal with for a user in a system where competing variants could exist.


Assuming that we can supply both flying ponies and dancing badgers then this
would be ok. If we can't then I imagine we can use the '!!' operator to
complain about this in 'foo.bst'.

Perhaps there could be namespacing to separate global options and element
options, to avoid collision and confusion. I haven't thought that through yet.

One use-case I'm considering for this is dealing with breaking changes across
versions of a library. If you imagine a project with 1000's of flatpak-like
things being generated from BuildStream, from separate pipelines, it could be
tricky to get all of them to be ok with a breaking change in the same commit.

Potentially we could use a 'version' option on an element to allow elements
that depend on the library to require the older or newer version. If two
versions are requested in a pipeline, we can generate an error thanks to the
'!!' operator.

Right so with the proposed approach, one could theoretically at least
make an assertion that the correct version of an API is chosen from an
element that depends on that API, that element need only have knowledge
of the name of the option which enables the API.

So one element may build differently depending on an option, and
another element might raise an assertion if the chosen option doesnt
work for that element, meaning we've at least expressed that a given
element was incompatible for a given option.

However, what we dont have is the element declaring the value of an
option on an element it depends on; depending on how the element itself
was configured; this all leads back down the variant path where an
agreement between elements must be reached.


What do you think?

I'm torn, of course I wish variants was going to work perfectly. On the
other hand I have to concede that the implicit nature of how things
resolved was already a little bit complex for the user to digest, and
increasing that complexity by making them orthogonal (both to implement
and to use) seems to be unwise.


I'm also curious if this could be punted. Looking at this right now, is
there a way forward where perhaps some automatic constraint resolution
could be an added feature to options at a later time, without breaking
things ?

Maybe there is a practical way forward without closing the door
entirely on the variants approach.


Cheers,
    -Tristan



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]