Boost logo

Boost-Build :

From: Vladimir Prus (ghost_at_[hidden])
Date: 2006-02-28 03:25:34


On Monday 27 February 2006 00:14, Daniel Einspanjer wrote:
> "Vladimir Prus" <ghost_at_[hidden]> wrote in message
> news:200602261936.16703.ghost_at_cs.msu.su...
>
> > no, I'm afraid no idea yet. Any chance you can provide a testcase which
> > reproduces the problem? Then I might be able to get to the root of the
> > problem much faster then if we exchange the necessary information over
> > email.
> >
> > BTW, it's always preferrable to include testcases together with bug
> > reports/queries, as they tend to be more accurate than extracts from
> > code.
>
> Sorry to make things more difficult for you. I thought it would be better
> to just include a snippet of code at first because I was afraid I might
> just have some glaring syntax error that would be obvious.
>
> Attached is a testcase that demonstrates the ambiguity error. Just run
> bjam on the extracted directory.

Thank you, this reproduces.

Here's what's going on. First of all, to clarify your intent, I suggest you
make all generators that now produce CPP type produce CUSTOMERINFO type.
Likewise, instead of

    cpp csconfig-customer.cpp

you better write

    customerinfo csconfig-customer.cpp

as you're really producing customer info file, not some random CPP. With those
change you get this pair of generators:

      csconfig.transform: CSCONFIG -> CUSTOMERINFO
      customerinfo.transform: CUSTOMERINFO -> CUSTOMERINFO

For a simplified use case:

    cpp csconfig-customer.cpp
       : # sources
          csconfig-base.ini
      ;

you really get two possible transformation chains:

   CSCONFIG -> CUSTOMERINFO
   CSCONFIG -> CUSTOMERINFO -> CUSTOMERINFO

In theory, the CUSTOMERINFO -> CUSTOMERINFO step can be applied N times more,
but Boost.Build does not allow repating application of the same generator for
obvious reasons.

The most likely situation is that you want the CUSTOMERINFO -> CUSTOMERINFO
generator to be only invoked when you explicitly ask for this.

1. If the generator should be invoked only when some property, say <customer>
is in build properties, use this:

  generators.override csconfig.transform : customerinfo.transform ;
  
  generators.register [ new customerinfo-generator customerinfo.transform :
       CUSTOMERINFO : CUSTOMERINFO : <customer> ] ;

This way, the customerinfo.transform generator won't be used unless there's
<customer> in the properties. Or you can use:

  generators.register [ new customerinfo-generator customerinfo.transform :
       CUSTOMERINFO : CUSTOMERINFO : <allow>customerinfo.transform ] ;

and add <allow>customerinfo.transform to requirements if you want this
generator to run. The <allow> property is the standard one. You can use a
helper rule to automatically add this property when declaring targets:

   rule customerinfo-transformed ( name : sources * : requirements * .. )
   {
        customerinfo $(name)
           : $(sources)
           : $(requirements) <allow>customerinfo.transform
           .........
   }

2. You can change customerinfo.transform signature:

   type.register CUSTOMERINFO_TRANSFORMED : : CUSTOMERINFO ;
   generators.register [ new customerinfo-generator customerinfo.transform :
       CUSTOMERINFO : CUSTOMERINFO : <allow>customerinfo.transform ] ;

and again use 'customerinfo-transformed' rule when you need to transform
customer info.

In both cases, you won't need the 'cast' rule to indicate you need to
transform, as you try to do in the first target in Jamroot you've sent.

I'd prefer method 2 above, as it's the most straight-forward.

And as a closing remark, the explanation why you get the error with the
current code, where target type of generators is CPP. Here's the second
transformation chains that Boost.Build finds:

    1. customerinfo.transform has CPP as target type so it's asked
       to create CPP from CSCONFIG
    2. Source type of customerinfo.transform is CUSTOMERINFO. There are
       no generators for this type.
    3. Boost.Build tries generators for base types of CUSTOMERINFO, in this
       case -- CPP.
    4. It finds the csconfig.transform (CSCONFIG->CPP) generator.

If Boost.Build did not do (3), this chain would not be found, and you'd have
no ambiguity. However, this will prevent a handy feature -- you can create a
new target type derived from an existing one and change it's extension, but
all the generators will be inherited. Say, if you do:

  type.register MY_PLUGIN : plg : SHARED_LIB ;

you've be able to build .plg files on all platforms using standard dll linking
actions.

So, I'd suggest using one of two methods I've suggested, as they'll solve the
problem and make the code more explicit.

HTH,
Volodya


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