Boost logo

Boost-Build :

From: Ali Azarbayejani (ali_at_[hidden])
Date: 2003-03-25 11:29:22


David Abrahams wrote:
>
> Ali Azarbayejani <ali_at_[hidden]> writes:
>
> I understand that you're decomposing orthogonal concepts here. I like
> that in principle, and it may be the right move for our
> implementation, but I also feel fairly well convinced that most users
> _should_ never have to know about these distinctions.

Ok, I think I agree with that sentiment. The orthogonal low-level
functionality is there when needed, but most users employ a simpler
expression.

> Hmm, the way <library> in requirements expands to something which
> includes a usage-requirement worries me a little now. Currently
> there's no provision for this sort of cross-category composite feature
> expansion. I begin to wonder if we shouldn't have a different way to
> deal with usage requirements that puts them all in the requirements
> section:
>
> <use>b <usage:link-to>b # **
>
> or something.

I just received Vladimir's response...apparently I misunderstood
this...<library> in Req does NOT imply <link-to> (i.e. <library> in
Usage-Req).

> > # If, e.g., b's headers are in a's public interface, you might do
> > # the following to expose b's usage requirements. (Again, from a
> > # purist SW architecture point of view, I always recommend against
> > # this sort of sneaky thing...but it comes up and this is how to do
> > # it.)
> > lib a : a.cpp : <library>b : : <uses>b ;
>
> If a and b have any templates or inline functions, it may not matter
> whether b's headers are in a's public interface. <use>b might still
> be imposed on whoever is using a.
>
> Should there be some way for a to say that any usage requirements it
> inherits get propagated on to its dependents?

Doesn't <library> (or <link-to>) in Usage Requirements *already*
propagate (while <include> or <define> do not? or do they?) ?

I don't know what's right...and I'm happy to help specify...but I'm
trying to understand what the current specification and/or
implementatation is doing.

> > # If you wanted to have a statically-linked DLL, you would have to
> > # do something like this. This would somehow have to interact with
> > # the <link> feature. Note the difference.
> > lib a : a.cpp : <uses>b <link-to>b ;
>
> Which is the statically linked DLL (whatever that is!) in this case?
> a or b?

Library "a" is the DLL, "b" is a static library linked into "a". The
MSVC linker allows you to create a DLL (a dynamic or "shared" library)
by statically linking to other libraries (e.g. "b"). In this case, it
would be natural to say

lib a : a.cpp b ;

which is confusing if you use the same expression to specify a shared
lib "a" that depends on a shared lib "b".

But using the <link-to> feature that I defined, you can make the
distinction.

lib a : a.cpp : <link-to>b ;
lib c : c.cpp : : : <link-to>b ;

The first says "I link to b", the second says "my client links to b".

If "a" is built <link>shared, it will statically link to "b" (I don't
think this is possible with GCC) and no user of "a" will know or care
about "b". However, if "c" is built <link>shared, the <link-to>b will
propagate to all direct and indirect users of "c" so that "b" appears
on the final link line.

(It's not clear to me whether either MSVC or GCC/AR can build a
static library that contains other static libraries, so if "a" is
built <link>static, I'm not sure what would happen.)

Btw, I'm not necessarily advocating this approach, but just using it
to illustrate some of the things I don't understand about the current
implementation.

> > # These would be unusual, but illustrate what <library> in
> > # usage-requirements means.
> > lib a : a.cpp : : : <uses>b <link-to>b ; # client to lib a uses and links b
> > lib a : a.cpp : : : <library>b ; # same as above
> >
> > # N.B. the second line would basically would pass on the <library>
> > # property to the client of "a", which would then expand it to
> > # Requirement <uses>b and ((for a "lib") Usage-Requirement <link-to>b
> > # or (for a "exe") Requirement <link-to> b). Thus, functionally,
> > # <library> only gets expanded when it is a Requirement.
>
> Sneaky. This makes me think that (**) above was really on the right
> track.

Are we questioning the distinction between Requirements and
Usage-Requirements or just the syntax for expressing them?

This proposed syntax might make your redundant <include> issue even
uglier:

lib a : a.cpp : <include>./include <usage:include>./include ;

You may be thinking

lib a : a.cpp : <include>./include ;

applies both to me and to my users, but then how do you restrict to
one or the other? <build:include> and <usage:include> perhaps?

> > # Executables
> >
> > exe e : e.cpp : <link-to>b ; # e merely links to b
>
> Explicitly and stubbornly ignoring b's usage requirements?
> OK, but it's inadvisable, right?

Yes, inadvisable, but permissible and perfectly well-defined.

> > exe e : e.cpp : <uses>b <link-to>b ; # e directly uses b and links to b
> > exe e : e.cpp b ; # same as above (uses and links)
> > exe e : e.cpp : <library>b ; # same as above (uses and links)
>
> I like these, especially the middle one.

That, IMO, would be the "normal" way.

> As I said, I have some concerns about <library> and the cross-category
> expansion. In any case, the orthogonal <use> and <link-to> features
> make sense to me.
>
> >> One other concern I have is the common need to repeat properties in
> >> the requirements and usage-requirements sections, particularly some
> >> defines and most includes. It would be nice to eliminate that
> >> redundancy.
> >
> > The above proposal addresses some of that...at least you don't need to
> > specify both <uses> and <link-to> most of the time.
>
> That really doesn't help with either of the cases I mentioned, I
> think.
>
> I'm thinking of:
>
> lib x : x.cpp
> : <include>./include <define>XSPOOF
> : : <include>./include <define>XSPOOF ;

But, you know, there is a difference between "I use" and "my client
uses". When the include paths or macros are all contained in the
private implementation, you really do want them just in Requirements,
and when they apply only to the client, you really do want them just
in Usage Requirements, so I wouldn't want to get rid of the
distinction, even at the cost of having to specify twice.

So I'm happy that they are separate. My solution to the above is.

Req += <include>./include ;
Req += <define>XSPOOF ;

lib x : x.cpp : $(Req) : : $(Req) ;

--Ali

 


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