|
Boost-Build : |
From: Vladimir Prus (ghost_at_[hidden])
Date: 2003-10-16 08:59:21
All,
I attach a proposal for a somewhat refined linking mechanism for V2. The
primary goal is to avoid requiring to use
lib a : a.cpp : <use>b : : <library>b ;
everytime one wants to use a library. It seems it's implementable without much
effort.
I'd appreciate all comments on this document.
TIA,
Volodya
--Boundary-00=_5Qqj/ypDYk8cvzz Content-Type: text/html;
charset="us-ascii";
name="linking.html"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="linking.html"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=koi8-r">
<TITLE></TITLE>
<META NAME="GENERATOR" CONTENT="OpenOffice.org 1.1 (Linux)">
<META NAME="AUTHOR" CONTENT="Vladimir Prus">
<META NAME="CREATED" CONTENT="20031015;15444000">
<META NAME="CHANGEDBY" CONTENT="Vladimir Prus">
<META NAME="CHANGED" CONTENT="20031016;16362400">
<STYLE>
<!--
@page { size: 21cm 29.7cm }
P.text-body-indent { margin-left: 0.5cm }
-->
</STYLE>
</HEAD>
<BODY LANG="en-US" DIR="LTR">
<H1>Improved library linking mechanism</H1>
<H2>Motivation</H2>
<P>When V2 first got the <library> feature, it was a good idea.
Together with usage requirements is allowed to link to a library
without bothering about transitive dependency on other libraries,
which must be linked as well. Unfortunately, the current model has a
couple of drawbacks:</P>
<UL>
<LI><P>it requires more typing than necessary</P>
<LI><P>it does not allow to directly link one library to another
one, for shared linking, and yet doing something sensible for static
linking.</P>
</UL>
<P>This document discusses what can be improved and proposes a
solution which can be implemented with little effort.</P>
<H2>Overview</H2>
<P>Assume executable “m” uses library “a”,
and that library uses another library, “b”. Naturally,
the code of “b” should be somehow available when “m”
is run. There are two different ways how we can achieve this:</P>
<UL>
<LI><P>Direct linking means that “a” library contains
reference to library “b”. On common toolsets, it's only
possible is “a” is a shared library. In this case, “b”
will be automatically found at runtime. The problem with this
solution is that it will just break for static build.</P>
<LI><P>Bubble-up linking meands that “a” does not
contain a reference to “b”. However, when the library is
build, Boost.Build is told about dependency on “b”, and
“b” will be automatically linked to “m”. The
problem with this solution, as described in docs, is that it's
pretty verbose. For our example, the declaration of “a”
might look like:</P>
</UL>
<P CLASS="text-body-indent">lib a : a.cpp : <use>b : :
<library>b ;</P>
<P STYLE="margin-bottom: 0cm">The duplication of “b” is
not nice.
</P>
<P STYLE="margin-bottom: 0cm"><BR>
</P>
<H2>Proposal</H2>
<P>It was proposed by Ali, IIRC, that putting library in sources of
other library does the right thing: use direct linking if the library
is build as shared, and use bubble-up if library is linked as static.
Later, Christopher Currie noted that for static linking, libraries in
sources of other libraries are passed through by the current code,
which opens an easy path for implementation.</P>
<P>Accordingly, it's proposed that dependency from one library to
another can be expressed in two ways:</P>
<UL>
<LI><P>Automatic: “lib a : a.cpp b ;”. When building
with <link>shared, direct linking is used. Otherwise, “b”
is returned together with targets created for “a” and
this will be effectively the same as bubble-up linking.</P>
<LI><P>Bubble-up: “lib a : a.cpp : <use>b : : <library>b
;”. For both static and shared linking, “b” is not
linked it but is returned as usage-requirement.</P>
</UL>
<P>Let's consider interactions between two libraries “a”
and “b”, where “a” depends on “b”
and “b” might depend on other libraries. Each cell of the
following table documents what target are created when building “b”
and how they are handled.</P>
<TABLE WIDTH=100% BORDER=1 BORDERCOLOR="#000000" CELLPADDING=4 CELLSPACING=3>
<COL WIDTH=64*>
<COL WIDTH=64*>
<COL WIDTH=64*>
<COL WIDTH=64*>
<THEAD>
<TR VALIGN=TOP>
<TH WIDTH=25%>
<P><BR>
</P>
</TH>
<TH WIDTH=25%>
<P>B: automatic/static</P>
</TH>
<TH WIDTH=25%>
<P>B: automatic/shared</P>
</TH>
<TH WIDTH=25%>
<P>B: bubble up</P>
</TH>
</TR>
</THEAD>
<TBODY>
<TR VALIGN=TOP>
<TH WIDTH=25%>
<P>B creates:</P>
</TH>
<TD WIDTH=25%>
<P>“b” target and target for “b”
dependendies.</P>
</TD>
<TD WIDTH=25%>
<P> A single target for “b”</P>
</TD>
<TD WIDTH=25%>
<P>A single target for “b” and <library> usage
requirements</P>
</TD>
</TR>
<TR VALIGN=TOP>
<TH WIDTH=25%>
<P>A: automatic/static</P>
</TH>
<TD WIDTH=25%>
<P>Targets are returned together with the target for “a”</P>
</TD>
<TD WIDTH=25%>
<P>Target is returned together with the target for “a”</P>
</TD>
<TD WIDTH=25%>
<P>Target for “b” and targets in usage requirements
are returned.</P>
</TD>
</TR>
<TR VALIGN=TOP>
<TH WIDTH=25%>
<P>A: automatic/shared</P>
</TH>
<TD WIDTH=25%>
<P>All targets are directly linked</P>
</TD>
<TD WIDTH=25%>
<P>The target is directly linked.</P>
</TD>
<TD WIDTH=25%>
<P>The targets are directly linked.</P>
</TD>
</TR>
<TR VALIGN=TOP>
<TH WIDTH=25%>
<P>A: bubble up</P>
</TH>
<TD WIDTH=25%>
<P>Targets are returned in usage requirements.</P>
</TD>
<TD WIDTH=25%>
<P>Targets are returned in usage requirements.</P>
</TD>
<TD WIDTH=25%>
<P>Targets are returned in usage requirements.</P>
</TD>
</TR>
</TBODY>
</TABLE>
<P><BR><BR>
</P>
<P>To implement the above scheme we need two mechanism. One which
cause “b” target to be returned without processing when A
is linked statically, and the second to achieve the same processing
for <library> properties returned as usage requirements by “b”.</P>
<P STYLE="margin-bottom: 0cm">The first mechanism is already in
place. If generator for static library sees another library as
source, that library is bypassed. The second mechanism requires that
<library> properties are treated as sources when building
library target. This can be archieved by tweaking the “construct”
method of the “lib-target-class” class.</P>
<P STYLE="margin-bottom: 0cm"><BR>
</P>
<H2>Implementation</H2>
<P>The presented proposal requires two changes to the existing code:</P>
<UL>
<LI><P>The “construct” method of the “lib-target-class”
should find all <library> properties an add it to the list of
sources. After that, it can call inherited “construct”</P>
<LI><P>For “searched” libraries, current code contains a
special code. It look at all the <library> properties, finds
which refer to searched libraries and adds special
<find-shared-library> and <find-static-library>
features, which are converted by toolset into -l switches to the
linker. When <library> is converted into source, this logic
should be adjusted and moved to the “generated-targets”
method of the “linking-generator” class.</P>
</UL>
<HR>
<P ALIGN=RIGHT>Last modified: <SDFIELD TYPE=DOCINFO SUBTYPE=CHANGE FORMAT=DATE SDNUM="1049;1033;MMM D, YYYY">Oct 16, 2003</SDFIELD></P>
</BODY>
</HTML> --Boundary-00=_5Qqj/ypDYk8cvzz--
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