From: David Abrahams (dave_at_[hidden])
Date: 2003-03-24 08:50:11
Vladimir Prus <ghost_at_[hidden]> writes:
>> lib a : a.cpp : : : <uses>b ; # if a target depends on a, it can also
>> # find b's headers (this is imo usually
>> bad sw
>> # design, because the user should explicitly
>> # depend on b if it wants to use its headers,
>> # or its other usage-req's for that matter)
> Yep, this is how it behaves now. A target which uses 'a' will get usage
> requirements of 'b' as well --- there's accumulation of usage requirements, in
> some sense.
> I understand your concerns, but have no idea how to address them.
I'm not sure it's a problem, either. Consider that many libraries
involve templates and inline definitions which only appear in headers.
> We need to propagate some properties this way. E.g. if 'b' has
> <library>zlib in usage-requirements, than any exe linking to 'a'
> should get that property.
> Another example: 'b' uses Boost, and includes some Boost headers in public
> interface. 'a' uses 'b' and includes 'b's headers in public interface. Some
> exe uses 'a'. Now, that exe must have Boost in include path, because it
> indirectly uses Boost headers.
> I think this is mostly the question of carefully writing usage requirements.
Yes. You don't want to expose your implementation headers (if any)
via usage requirements, just your interface headers.
>> exe e : e.cpp : <library>a ; # link to a. isn't this the same as:
>> # "exe e : e.cpp a ;" ?
> True. That's precisely the same if <library> is written explicitly. (It can
> come implicitly from usage requirements of some source).
>> exe e : e.cpp : : : <library>a ; # ?? makes no sense at all, no ??
> That's not yet clear. For example, some target can have
> <uses>e in requirements and get <library>a. I cannot back up this
> statement with real use cases, though.
I can imagine an executable which is a kind of tool used to build
other targets of a special kind which all need to link to a particular
library. Real use cases? Forget it ;-)
>> exe e : e.cpp : : : <uses>a ; # ?? conceivably has a use, but
>> probably not ?
> The same comment as above applies.
Yeah, I think the reasoning is similar.
>> Conceptually, dependencies on libs should be quite simple
>> <A> If lib "a" depends on lib "b", "a" simply needs to be able to
>> find the public headers of "b".
I guess in the absence of a consistent ability to link libraries with
one another, that's right.
>> <B> If exe "e" depends on a lib, "e" needs both to find the public
>> headers of the lib and to link to the lib and all its
>> dependencies, recursively.
>> It seems as though this could be expressed more simply like this:
>> lib b : b.cpp : : : <include>./include/b ;
>> lib a : a.cpp b : : : <include>./include/a ;
>> exe e : e.cpp a ;
> As written, this would mean that 'b' should be linked into 'a' --- which
> is something we don't support (and not sure we should).
Yeah, it's not consistently achievable across platforms. I think Ali
is suggesting that the lib rule give special meaning to libs that
appear in the list of sources for libs, though. IOW, it would
translate the 2nd line into
lib a : a.cpp : : : <include>./include/a <library>b ;
I'm not sure I like that idea, but it's not completely unreasonable.
>> or, alternatively, like this (I don't quite understand the
>> difference between specifying a library as a "source" versus as a
>> lib b : b.cpp : : : <include>./include/b ;
>> lib a : a.cpp : <library>b : : <include>./include/a ;
>> exe e : e.cpp : <library>a ;
> That's precisely the same as above.
>> In either case, why can't "a" acquire the usage-requirements of "b"
>> (find its headers) by virtue of "b" being a source (or,
>> alternatively, by virtue of "b" being a <library> requirement).
>> Similarly, why can't "e" acquire "a"s usage-requirements and link to
>> "a" and "b" simply by virtue of "a" being a source (or <library>
>> requirement) of "e"?
> It will! Usage requirements are propagated from sources, and "dependency"
> features. Both <dependency> and <library> are "dependency" features.
> The difference from
> library a : a.cpp : <library>b ;
> library a : a.cpp : <uses>b ;
> is very simple. The former grabs usage requirements and is supposed to link
> to 'b'. The latter only grabs usage requirements.
Maybe I'm coming around to Ali's point: if whether you want
<library>somelib or <uses>somelib is determined entirely by the kind
of target being declared (lib or exe), we should collapse the
distinction in the feature names, and just give it different semantics
depending on context.
>> Surely <uses> (a.k.a. <dependency>) has other uses and should still
>> be a feature in its own right, but it seems to me that expressing
>> library interdependencies should be more straightforward than is
>> currently the case. Please explain if I am misunderstanding
> The problem with putting dependecy library in sources is that it
> creates illusion that library is being linked in, while it is not
> --- and we don't want that, in general. I think that's the primary
I'm not sure if keeping conceptual purity is worth the cost in this
>> Maybe I am misunderstanding the intent of the <library> feature.
>> It seems currently to be a low-level synonym for "<link-to>"
>> rather than a higher-level statement of a lib dependency ?
> Yes, it's 'link-to' statement. I'm not sure what "lib dependency"
> is, though. A library might require that another one be linked in
> (via <library> in usage requirements). Or library might require
> headers of another one (via <uses> in requirements). We currently
> plan to use the latter information for determining link order. Is
> this approach not good for some reason?
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
-- Dave Abrahams Boost Consulting www.boost-consulting.com
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