Boost logo

Boost-Build :

From: David Abrahams (dave_at_[hidden])
Date: 2002-11-12 10:42:31


Vladimir Prus <ghost_at_[hidden]> writes:

> David Abrahams wrote:
>> Whatever's going on in this rule, it's _way_* too tricky. If it _were_
>> important to do something this tricky, it's at least way
>> under-commented:
>
> Well, I believe we've concluded long ago that writing comments is
> not my strong point.

I have great respect for you, but I think that's a bit of a
cop-out. It's a skill we all need to develop, and I think you could do
much better with a little extra attention. You are usually able to
explain yourself quite well in emails; if you would just write the
same kinds of things in your code it would be much more
understandable.

> Let me explain.
>
> General scheme for creating main target is:
>
> 1. You call some rule:
>
> exe hello : hello.cpp ;
>
> 2. It does some preprocessing of requirements and default build.
>
> 3. That rules creates an instance of some class derived from 'abstract-target'.
> In this case, it's 'typed-target'.
>
> 4. It obtains 'project-target' for the current project, and calls 'add-alternative'
> method on it.
>
> What's in step 2?
>
> - If there are any path properties, they should be adjusted.
> - You should refine parent's requirements with target's requirements.
> - If no default build is specified, then parent's default build is
> used instead.
>
> You see that steps 2 and 4 are not specific to target type, but look at
> 'main-target-alternative' implementation. Those steps take a lot of code,
> so it's desirable to not repeat them in all rules that declared targets.
> I agree that the current solution is tricky.
>
>
>> What the heck is "will be specially processed" supposed to indicate to
>> the reader?
>
> Refer to step 2 description above.

Thanks.

However, when I post a remark indicating confusion with the
code/comments, it isn't enough to post a reply which answers the
questions; you need to clarify the comments in the code.

>> Also, the way this rule is invoked is extremely tricky as well:
>>
>> rule main-target-rule ( name : sources * : requirements * : default-build *
>> : use-requirements * )
>> {
>> # First find required target type, which is equal to the name used
>> # to invoke us.
>> local bt = [ BACKTRACE 1 ] ;
>> local type = $(bt[4]) ;
>>
>> targets.main-target-alternative $(name) [ CALLER_MODULE ] typed-target : 3 : 5 : 4
>> : $(type:U) : $(sources) : $(requirements) : $(default-build) : $(use-requirements)
>> ;
>> }
>
> There are two aspects. First, it's as tricky as 'main-target-alternative' interface.
> I did make mistakes with it several times myself. I believe we can use a better way:
>
> - Introduce three rules:
> - 'adjust-main-target-requirements'
> - 'adjust-main-target-use-requirements'
> - 'adjust-main-target-default-build'
>
> - Call those rules as appropriate. This will make all this "3 : 5 : 4" unneeded.
> You'd write
>
> targets.main-target-alternative $(name)
> [ new typed-target : $(type:U) : $(sources)
> : [ adjust-main-target-requirements $(requirements) ]
> : [ adjust-main-target-use-requirements $(use-requirements) ]
> : [ adjust-main-target-default-build $(default-build) ]
> ] ;
>
> This is more writing but is much more clear.

I think it's a lot better, but I'm not sure why you need to say
"adjust" here. What do these adjust-xxx rules return?

>> Where does "type" come from? How do we get here? This kind of
>> reaching back into the call stack always needs some extra comments
>> to describe what's actually going on. Something should state
>> explicitly that types and main target rule names have a one-to-one
>> uppercase/lowercase relationship.
>
> It is possible to create main target rule for any given type. That
> rule will have the same name as type, only lower cases. In fact, all
> those rules will call type.main-target-rule, which uses the name
> it's called with to find what type is needed. I think that the
> comment says that we're finding the name used to call us, which is
> equal to type. Maybe, you could put it in better words?

Already done. You had written:

# First find requuired target type, which is equal to the name used to
# invoke us.
local bt = [ BACKTRACE 1 ] ;
local type = $(bt[4]) ;

targets.main-target-alternative $(name) [ CALLER_MODULE ] typed-target : 3 : 5 : 4
: $(type:U) : $(sources) : $(requirements) : $(default-build) : $(use-requirements)
;

This is confusing, since there are no types in the backtrace. I
changed it to

local rulname = $(bt[4]) ;

targets.main-target-alternative $(name) [ CALLER_MODULE ] typed-target : 3 : 5 : 4
: $(.main-target-type.$(rulename)) : $(sources) : $(requirements) : $(default-build) : $(use-requirements)
;

Which I think helps.

> BTW, I positively don't know why target types are uppercase! I belive
> that's because the type hierarchy graph used in design discussion had
> uppercase type names. Should we switch to lower-case type names?

There's no need to, IMO.

BTW, I have to spend the day working on Boost.Python. I'll try to get
back to Boost.Build tonight.

-- 
David Abrahams
dave_at_[hidden] * http://www.boost-consulting.com
Boost support, enhancements, training, and commercial distribution
 

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