Boost logo

Boost-Build :

Subject: [Boost-build] [repost] Dependency on shared library from static library
From: Johan Nilsson (r.johan.nilsson_at_[hidden])
Date: 2009-02-06 02:56:27


[Reposting the last posting in an attempt to get fresh views on the issue.
Follow the original thread for missing details. / Johan]

"Alexander Sack" <pisymbol_at_[hidden]> wrote
news:3c0b01820902040708g570a31b0h89dfcf4ab948429a_at_mail.gmail.com...
> On Wed, Feb 4, 2009 at 9:35 AM, Johan Nilsson <r.johan.nilsson_at_[hidden]>
> wrote:
>>>> Well, obviously a static lib can't be linked (at least not with msvc).
>>>> Hence
>>>> the "... _reference_ the shared build of a" (which could be even more
>>>> specific by stating "contains references to the functions exported by
>>>> the
>>>> shared build of a", perhaps).
>
> At least with gcc toolchain that worked fine for me.
>
>>> Do you still have the issue though?
>>
>> Yes. Your suggested solution generates both shared and static versions of
>> "a", and passes both as linker inputs for msvc. See below for relevant
>> part
>> of output using "bjam -d+2"
>
> Yes that's true too for gcc. However the final binary is c is
> depedent on the shared library a which is what you want. The rule you
> gave makes liba shared when the main target is always built as per:
>
> http://www.boost.org/doc/tools/build/doc/html/bbv2/advanced/targets.html
>
> Other than the fact that bjam builds both versions of the library, I
> guess I fail to see the real issue (at least with gcc since I have not
> tried msvc). If you build with link=static you get a static binary
> and static libraries, if you build link=shared, you get a static libb,
> a shared liba, and c exe/binary that has symbols linked in from static
> archive and depends on shared library.

I've modified the sample a bit (see attached indirect_usage_of_a.zip). This
is basically your Jamroot, but the c++ code now outputs some tracing
statements and runs the executable using the unit-test rule, showing whether
shared or static library version of a() is called. This is the output I get
when executing bjam link=shared:

---
main: calling b_call_a:
in b_call_a()
in a() (static lib)
---
Result: static library version of a is used (but both static and shared
versions of a are built).
When modifying c.cpp to directly call a() (see attached
direct_usage_of_a.zip), I get the following output:
---
main: calling b_call_a:
in b_call_a()
in a() (shared lib)
main: calling a
in a() (shared lib)
---
Result: shared library version of a is used (but both static and shared
versions of a are built).
I see a couple of problems with how this works:
- When declaring target c you'll need to know that b uses a (and manually
add a to the sources for c as well), _even_ if c does not directly use
anything
defined in "a". IMHO this breaks encapsulation and somehow voids the
usage-requirements feature - which is one big reason for me to use
Boost.Build. Breaks the principle of least surprise, at least for me.
- It causes both static and shared versions of a to be built, even though
the static version isn't actually used. For such a small project with small
libraries that build fast it's not a big deal, but I'm having this
requirement in a real project where building the static library in question
from scratch takes some ~15-20 minutes. I only tried to illustrate my
problem using a small project.
- When I specify link=shared, I expect all direct and indirect library
dependencies to be built for shared linking if they support it. It doesn't
make sense that one dependency/target along the way propagates its own
"deficiency" (able to build as a static library only) to its own
dependencies. I do realize that mixing shared and static libraries can
potentially lead to problems, but in this case (static lib uses methods in
shared) I can't see the problem, at least not in my specific use case.
This is how I would expect it to work:
--- (modified) Jamroot ---
import testing ;
project foo ;
# can be built as static or shared library
lib a
  : a.cpp
  : <link>shared:<define>A_BUILD_DLL
  :
  : <link>shared:<define>A_USE_DLL
  ;
# can only be built as static library
lib b : b.cpp : <link>static <use>a : : <library>a ;
unit-test c : c.cpp : <library>b ;
---
Running bjam link=shared should _not_ produce static version of "a" (but
does) and output the following (but does not):
---
main: calling b_call_a:
in b_call_a()
in a() (shared lib)
---
By adding "<library>a" to the requirements of target "c", I get the desired
output (but breaks encapsulation). No matter what I do, a static lib version
of a is always produced as a "side effect".
Help, anyone?
/ Johan
--------------------------------------------------------------------------------
_______________________________________________
Unsubscribe & other changes: 
http://lists.boost.org/mailman/listinfo.cgi/boost-build





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