File: tools.html

package info (click to toggle)
boost-build 2.0-m11-2
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 4,624 kB
  • ctags: 2,387
  • sloc: ansic: 12,978; python: 5,209; xml: 4,782; cpp: 555; yacc: 456; sh: 237; makefile: 71
file content (235 lines) | stat: -rw-r--r-- 11,087 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Tools and generators</title>
<link rel="stylesheet" href="../../boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.69.1">
<link rel="start" href="../../index.html" title="PartI.Boost.Build v2 User Manual">
<link rel="up" href="../extender.html" title="Chapter5.Extender Manual">
<link rel="prev" href="targets.html" title="Target types">
<link rel="next" href="features.html" title="Features">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../boost.png"></td></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="targets.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../extender.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="features.html"><img src="../../images/next.png" alt="Next"></a>
</div>
<div class="section" lang="en">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="bbv2.extending.tools"></a>Tools and generators</h2></div></div></div>
<p>
        This section will describe how Boost.Build can be extended to support
        new tools.
      </p>
<p>For each additional tool, a Boost.Build object called generator
        must be created. That object has specific types of targets that it
        accepts and produces. Using that information, Boost.Build is able
        to automatically invoke the generator. For example, if you declare a
        generator that takes a target of the type <code class="literal">D</code> and
        produces a target of the type <code class="literal">OBJ</code>, when placing a
        file with extention <code class="literal">.d</code> in a list of sources will
        cause Boost.Build to invoke your generator, and then to link the
        resulting object file into an application. (Of course, this requires
        that you specify that the <code class="literal">.d</code> extension corresponds
        to the <code class="literal">D</code> type.)
      </p>
<p>Each generator should be an instance of a class derived from the
        <code class="computeroutput">generator</code> class. In the simplest case, you don't need to
        create a derived class, but simply create an instance of the
        <code class="computeroutput">generator</code> class. Let's review the example we've seen in the
        <a href="../extender.html#bbv2.extender.intro" title="Introduction">introduction</a>.
        
</p>
<pre class="programlisting">
import generators ;
generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
actions inline-file
{
    "./inline-file.py" $(&lt;) $(&gt;)
}
</pre>
<p>
      </p>
<p>We declare a standard generator, specifying its id, the source type
        and the target type. When invoked, the generator will create a target
        of type <code class="literal">CPP</code> with a source target of
        type <code class="literal">VERBATIM</code> as the only source. But what command
        will be used to actually generate the file? In bjam, actions are
        specified using named "actions" blocks and the name of the action
        block should be specified when creating targets. By convention,
        generators use the same name of the action block as their own id. So,
        in above example, the "inline-file" actions block will be used to
        convert the source into the target.
      </p>
<p>
        There are two primary kinds of generators: standard and composing,
        which are registered with the
        <code class="computeroutput">generators.register-standard</code> and the
        <code class="computeroutput">generators.register-composing</code> rules, respectively. For
        example:
</p>
<pre class="programlisting">
generators.register-standard verbatim.inline-file : VERBATIM : CPP ;
generators.register-composing mex.mex : CPP LIB : MEX ;
</pre>
<p>
        Standard generators take a <span class="emphasis"><em>single</em></span> source of type
        <code class="computeroutput">VERBATIM</code> and produces a result. The second generator
        takes any number of sources, which can have either the
        <code class="computeroutput">CPP</code> or the <code class="computeroutput">LIB</code> type. Composing generators
        are typically used for generating top-level target type. For example,
        the first generator invoked when building an <code class="computeroutput">exe</code> target
        is a composing generator corresponding to the proper linker.
      </p>
<p>You should also know about two specific functions for registering
        generators: <code class="computeroutput">generators.register-c-compiler</code> and
        <code class="computeroutput">generators.register-linker</code>. The first sets up header
        dependecy scanning for C files, and the seconds handles various
        complexities like searched libraries. For that reason, you should always
        use those functions when adding support for compilers and linkers.
      </p>
<p>(Need a note about UNIX)</p>
<h3>
<a name="id2577024"></a>Custom generator classes</h3>
<p>The standard generators allows you to specify source and target
        types, an action, and a set of flags. If you need anything more complex,
        
        you need to create a new generator class with your own logic. Then,
        you have to create an instance of that class and register it. Here's
        an example how you can create your own generator class:
</p>
<pre class="programlisting">
class custom-generator : generator
{
    rule __init__ ( * : * )
    {
        generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
    }

}

generators.register 
  [ new custom-generator verbatim.inline-file : VERBATIM : CPP ] ;
</pre>
<p>
        This generator will work exactly like the
        <code class="computeroutput">verbatim.inline-file</code> generator we've defined above, but
        it's possible to customize the behaviour by overriding methods of the
        <code class="computeroutput">generator</code> class.
      </p>
<p>There are two methods of interest. The <code class="computeroutput">run</code> method is
        responsible for the overall process - it takes a number of source targets,
        converts them to the right types, and creates the result. The
        <code class="computeroutput">generated-targets</code> method is called when all sources are
        converted to the right types to actually create the result.
      </p>
<p>The <code class="computeroutput">generated-target</code> 
      method can be overridden
      when you want to add additional properties to the generated
      targets or use additional sources. For a real-life example,
      suppose you have a program analysis tool that should be given a
      name of executable and the list of all sources. Naturally, you
      don't want to list all source files manually. Here's how the
      <code class="computeroutput">generated-targets</code> method can find the list of
      sources automatically:
</p>
<pre class="programlisting">
class itrace-generator : generator {
....
    rule generated-targets ( sources + : property-set : project name ? )
    {
        local leaves ;
        local temp = [ virtual-target.traverse $(sources[1]) : : include-sources ] ;
        for local t in $(temp)
        {
            if ! [ $(t).action ]
            {
                leaves += $(t) ;
            }
        }
        return [ generator.generated-targets $(sources) $(leafs)
          : $(property-set) : $(project) $(name) ] ;
    }
}
generators.register [ new itrace-generator nm.itrace : EXE : ITRACE ] ;
</pre>
<p>
        The <code class="computeroutput">generated-targets</code> method will be called with a single
        source target of type <code class="literal">EXE</code>. The call to 
        <code class="computeroutput">virtual-target.traverse</code> will return all targets the
        executable depends on, and we further find files that are not
        produced from anything. 
        The found targets are added to the sources.
      </p>
<p>The <code class="computeroutput">run</code> method can be overriden to completely
        customize the way the generator works. In particular, the conversion of
        sources to the desired types can be completely customized. Here's
        another real example. Tests for the Boost Python library usually
        consist of two parts: a Python program and a C++ file. The C++ file is
        compiled to Python extension that is loaded by the Python
        program. But in the likely case that both files have the same name,
        the created Python extension must be renamed. Otherwise, the Python
        program will import itself, not the extension. Here's how it can be
        done:
</p>
<pre class="programlisting">
rule run ( project name ? : property-set : sources * : multiple ? )
{       
    local python ;
    for local s in $(sources)
    {
        if [ $(s).type ] = PY
        {
            python = $(s) ;
        }
    }
    
    local libs ;
    for local s in $(sources)
    {
        if [ type.is-derived [ $(s).type ] LIB ]
        {
            libs += $(s) ;
        }
    }
    
    local new-sources ;
    for local s in $(sources)
    {
        if [ type.is-derived [ $(s).type ] CPP ] 
        {
            local name = [ $(s).name ] ;    # get the target's basename
            if $(name) = [ $(python).name ] 
            {
                name = $(name)_ext ;        # rename the target
            }                                
            new-sources += [ generators.construct $(project) $(name) :
              PYTHON_EXTENSION : $(property-set) : $(s) $(libs) ] ;
        }
    }
        
    result = [ construct-result $(python) $(new-sources) : $(project) $(name) 
                 : $(property-set) ] ;        
}    
</pre>
<p>        
        

        First, we separate all source into python files, libraries and C++
        sources. For each C++ source we create a separate Python extension by
        calling <code class="computeroutput">generators.construct</code> and passing the C++ source
        and the libraries. At this point, we also change the extension's name,
        if necessary.        
      </p>
</div>
<table width="100%"><tr>
<td align="left"></td>
<td align="right"><small></small></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="targets.html"><img src="../../images/prev.png" alt="Prev"></a><a accesskey="u" href="../extender.html"><img src="../../images/up.png" alt="Up"></a><a accesskey="h" href="../../index.html"><img src="../../images/home.png" alt="Home"></a><a accesskey="n" href="features.html"><img src="../../images/next.png" alt="Next"></a>
</div>
</body>
</html>