1 | <?xml version="1.0" encoding="UTF-8"?> |
---|
2 | <!DOCTYPE appendix PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" |
---|
3 | "http://www.boost.org/tools/boostbook/dtd/boostbook.dtd"> |
---|
4 | |
---|
5 | <appendix id="bbv2.arch"> |
---|
6 | <title>Boost.Build v2 architecture</title> |
---|
7 | |
---|
8 | <sidebar> |
---|
9 | <para>This document is work-in progress. Don't expect much from it |
---|
10 | yet.</para> |
---|
11 | </sidebar> |
---|
12 | |
---|
13 | <section id="bbv2.arch.overview"> |
---|
14 | <title>Overview</title> |
---|
15 | |
---|
16 | <para>The Boost.Build code is structured in four different components: |
---|
17 | "kernel", "util", "build" and "tools". The first two are relatively |
---|
18 | uninteresting, so we'll focus on the remaining pair. The "build" component |
---|
19 | provides classes necessary to declare targets, determine which properties |
---|
20 | should be used for their building, and for creating the dependency |
---|
21 | graph. The "tools" component provides user-visible functionality. It |
---|
22 | mostly allows to declare specific kind of main targets, and declare |
---|
23 | avaiable tools, which are then used when creating the dependency graph. |
---|
24 | </para> |
---|
25 | |
---|
26 | </section> |
---|
27 | |
---|
28 | <section id="bbv2.arch.build"> |
---|
29 | <title>The build layer</title> |
---|
30 | |
---|
31 | <para>The build layer has just four main parts -- metatargets (abstract targets), |
---|
32 | virtual targets, generators and properties. |
---|
33 | <itemizedlist> |
---|
34 | <listitem><para>Metatargets (see the "targets.jam" module) represent |
---|
35 | all the user-defined entities which can be built. The "meta" prefix |
---|
36 | signify that they don't really corrspond to files -- depending of |
---|
37 | build request, they can produce different set of |
---|
38 | files. Metatargets are created when Jamfiles are loaded. Each |
---|
39 | metagarget has a <code>generate</code> method which is given a |
---|
40 | property set and produces virtual targets for the passed properties. |
---|
41 | </para></listitem> |
---|
42 | <listitem><para>Virtual targets (see the "virtual-targets.jam" |
---|
43 | module) correspond to the atomic things which can be updated -- |
---|
44 | most typically files. |
---|
45 | </para></listitem> |
---|
46 | <listitem><para>Properties are just (name, value) pairs, specified |
---|
47 | by the user and describing how the targets should be |
---|
48 | built. Properties are stored using the <code>property-set</code> class. |
---|
49 | </para></listitem> |
---|
50 | <listitem><para>Generators are the objects which encapsulate tools |
---|
51 | -- they can take a list of source virtual targets and produce new |
---|
52 | virtual targets from them. |
---|
53 | </para></listitem> |
---|
54 | </itemizedlist> |
---|
55 | </para> |
---|
56 | |
---|
57 | <para>The build process includes those steps: |
---|
58 | <orderedlist> |
---|
59 | <listitem><para>Top-level code calls the <code>generate</code> |
---|
60 | method of a metatarget with some properties. </para></listitem> |
---|
61 | |
---|
62 | |
---|
63 | <listitem><para>The metatarget combines the requested properties |
---|
64 | with requirements and passes the result, together with the list |
---|
65 | of sources, to the <code>generators.construct</code> |
---|
66 | function</para></listitem> |
---|
67 | |
---|
68 | |
---|
69 | <listitem><para>A generator appropriate for the build properties is |
---|
70 | selected and its <code>run</code> method is |
---|
71 | called. The method returns a list of virtual targets |
---|
72 | </para></listitem> |
---|
73 | |
---|
74 | <listitem><para>The targets are returned to the top level code. They |
---|
75 | are converted into bjam targets (via |
---|
76 | <code>virtual-target.actualize</code>) and passed to bjam for building. |
---|
77 | </para></listitem> |
---|
78 | </orderedlist> |
---|
79 | </para> |
---|
80 | |
---|
81 | <section id="bbv2.arch.metatargets"> |
---|
82 | <title>Metatargets</title> |
---|
83 | |
---|
84 | <para>There are several classes derived from "abstract-target". The |
---|
85 | "main-target" class represents top-level main target, the "project-target" |
---|
86 | acts like container for all main targets, and "basic-target" class is a |
---|
87 | base class for all further target types. |
---|
88 | </para> |
---|
89 | |
---|
90 | <para>Since each main target can have several alternatives, all top-level |
---|
91 | target objects are just containers, referring to "real" main target |
---|
92 | classes. The type is that container is "main-target". For example, given: |
---|
93 | <programlisting> |
---|
94 | alias a ; |
---|
95 | lib a : a.cpp : <toolset>gcc ; |
---|
96 | </programlisting> |
---|
97 | we would have one-top level instance of "main-target-class", which will |
---|
98 | contain one instance of "alias-target-class" and one instance of |
---|
99 | "lib-target-class". The "generate" method of "main-target" decides |
---|
100 | which of the alternative should be used, and call "generate" on the |
---|
101 | corresponding instance. |
---|
102 | </para> |
---|
103 | |
---|
104 | <para>Each alternative is a instance of a class derived from |
---|
105 | "basic-target". The "basic-target.generate" does several things that are |
---|
106 | always should be done: |
---|
107 | <itemizedlist> |
---|
108 | <listitem> |
---|
109 | <para>Determines what properties should be used for building the |
---|
110 | target. This includes looking at requested properties, requirements, |
---|
111 | and usage requirements of all sources.</para> |
---|
112 | </listitem> |
---|
113 | <listitem> |
---|
114 | <para>Builds all sources</para> |
---|
115 | </listitem> |
---|
116 | <listitem> |
---|
117 | <para>Computes the usage requirements which should be passes back.</para> |
---|
118 | </listitem> |
---|
119 | </itemizedlist> |
---|
120 | For the real work of constructing virtual target, a new method |
---|
121 | "construct" is called. |
---|
122 | </para> |
---|
123 | |
---|
124 | <para>The "construct" method can be implemented in any way by classes |
---|
125 | derived from "basic-target", but one specific derived class plays the |
---|
126 | central role -- "typed-target". That class holds the desired type of file |
---|
127 | to be produces, and calls the generators modules to do the job. |
---|
128 | </para> |
---|
129 | |
---|
130 | <para>This means that a specific metatarget subclass may avoid using |
---|
131 | generators at all. However, this is deprecated and we're trying to |
---|
132 | eliminate all such subsclasses at the moment. |
---|
133 | </para> |
---|
134 | |
---|
135 | <para>Note that the <filename>build/targets.jam</filename> file contains |
---|
136 | an UML diagram which might help.</para> |
---|
137 | |
---|
138 | </section> |
---|
139 | |
---|
140 | <section id="bbv2.arch.virtual"> |
---|
141 | <title>Virtual targets</title> |
---|
142 | |
---|
143 | <para>Virtual targets correspond to the atomic things which can be |
---|
144 | updated. Each virtual target can be assigned an updating action -- |
---|
145 | instance of the <code>action</code> class. The action class, in |
---|
146 | turn, contains a list of source targets, properties, and a name of |
---|
147 | bjam action block which should be executed. |
---|
148 | </para> |
---|
149 | |
---|
150 | <para>We try hard to never create equal instances of the |
---|
151 | <code>virtual-target</code> class. Each code which creates virtual |
---|
152 | targets passes them though the <code>virtual-target.register</code> |
---|
153 | function, which detects if a target with the same name, sources, and |
---|
154 | properties was created. In that case, existing target is returned. |
---|
155 | </para> |
---|
156 | |
---|
157 | <para>When all virtual targets are produced, they are |
---|
158 | "actualized". This means that the real file names are computed, and |
---|
159 | the commands that should be run are generated. This is done by the |
---|
160 | <code>virtual-target.actualize</code> method and the |
---|
161 | <code>action.actualize</code> methods. The first is conceptually |
---|
162 | simple, while the second need additional explanation. The commands |
---|
163 | in bjam are generated in two-stage process. First, a rule with the |
---|
164 | appropriate name (for example |
---|
165 | "gcc.compile") is called and is given the names of targets. The rule |
---|
166 | sets some variables, like "OPTIONS". After that, the command string |
---|
167 | is taken, and variable are substitutes, so use of OPTIONS inside the |
---|
168 | command string become the real compile options. |
---|
169 | </para> |
---|
170 | |
---|
171 | <para>Boost.Build added a third stage to simplify things. It's now |
---|
172 | possible to automatically convert properties to appropriate assignments to |
---|
173 | variables. For example, <debug-symbols>on would add "-g" to the |
---|
174 | OPTIONS variable, without requiring to manually add this logic to |
---|
175 | gcc.compile. This functionality is part of the "toolset" module. |
---|
176 | </para> |
---|
177 | |
---|
178 | <para>Note that the <filename>build/virtual-targets.jam</filename> file |
---|
179 | contains an UML diagram which might help.</para> |
---|
180 | </section> |
---|
181 | |
---|
182 | <section id="bbv2.arch.properties"> |
---|
183 | <para>Above, we noted that metatargets are built with a set of |
---|
184 | properties. That set is represented with the |
---|
185 | <code>property-set</code> class. An important point is that handling |
---|
186 | of property sets can get very expensive. For that reason, we make |
---|
187 | sure that for each set of (name, value) pairs only one |
---|
188 | <code>property-set</code> instance is created. The |
---|
189 | <code>property-set</code> uses extensive caching for all operation, |
---|
190 | so most work is avoided. The <code>property-set.create</code> is the |
---|
191 | factory function which should be used to create instances of the |
---|
192 | <code>property-set</code> class. |
---|
193 | </para> |
---|
194 | </section> |
---|
195 | |
---|
196 | |
---|
197 | </section> |
---|
198 | |
---|
199 | <section id="bbv2.arch.tools"> |
---|
200 | <title>The tools layer</title> |
---|
201 | |
---|
202 | <para>Write me!</para> |
---|
203 | |
---|
204 | </section> |
---|
205 | |
---|
206 | <section id="bbv2.arch.targets"> |
---|
207 | <title>Targets</title> |
---|
208 | |
---|
209 | <para>NOTE: THIS SECTION IS NOT EXPECTED TO BE READ! |
---|
210 | There are two user-visible kinds of targets in Boost.Build. |
---|
211 | First are "abstract" — they correspond to things declared |
---|
212 | by user, for example, projects and executable files. The primary |
---|
213 | thing about abstract target is that it's possible to request them |
---|
214 | to be build with a particular values of some properties. Each |
---|
215 | combination of properties may possible yield different set of |
---|
216 | real file, so abstract target do not have a direct correspondence |
---|
217 | with files.</para> |
---|
218 | |
---|
219 | <para>File targets, on the contary, are associated with concrete |
---|
220 | files. Dependency graphs for abstract targets with specific |
---|
221 | properties are constructed from file targets. User has no was to |
---|
222 | create file targets, however it can specify rules that detect |
---|
223 | file type for sources, and also rules for transforming between |
---|
224 | file targets of different types. That information is used in |
---|
225 | constructing dependency graph, as desribed in the "next section". |
---|
226 | [ link? ] <emphasis role="bold">Note:</emphasis>File targets are not |
---|
227 | the same as targets in Jam sense; the latter are created from |
---|
228 | file targets at the latest possible moment. <emphasis role="bold">Note:</emphasis>"File |
---|
229 | target" is a proposed name for what we call virtual targets. It |
---|
230 | it more understandable by users, but has one problem: virtual |
---|
231 | targets can potentially be "phony", and not correspond to any |
---|
232 | file.</para> |
---|
233 | |
---|
234 | <section id="bbv2.arch.depends"> |
---|
235 | <title>Dependency scanning</title> |
---|
236 | |
---|
237 | <para>Dependency scanning is the process of finding implicit |
---|
238 | dependencies, like "#include" statements in C++. The requirements |
---|
239 | for right dependency scanning mechanism are:</para> |
---|
240 | |
---|
241 | <itemizedlist> |
---|
242 | <listitem> |
---|
243 | <simpara> |
---|
244 | Support for different scanning algorithms. C++ and XML have |
---|
245 | quite different syntax for includes and rules for looking up |
---|
246 | included files. |
---|
247 | </simpara> |
---|
248 | </listitem> |
---|
249 | |
---|
250 | <listitem> |
---|
251 | <simpara> |
---|
252 | Ability to scan the same file several times. For example, |
---|
253 | single C++ file can be compiled with different include |
---|
254 | paths. |
---|
255 | </simpara> |
---|
256 | </listitem> |
---|
257 | |
---|
258 | <listitem> |
---|
259 | <simpara> |
---|
260 | Proper detection of dependencies on generated files. |
---|
261 | </simpara> |
---|
262 | </listitem> |
---|
263 | |
---|
264 | <listitem> |
---|
265 | <simpara> |
---|
266 | Proper detection of dependencies from generated file. |
---|
267 | </simpara> |
---|
268 | </listitem> |
---|
269 | </itemizedlist> |
---|
270 | |
---|
271 | <section> |
---|
272 | <title>Support for different scanning algorithms</title> |
---|
273 | |
---|
274 | <para>Different scanning algorithm are encapsulated by objects |
---|
275 | called "scanners". Please see the documentation for "scanner" |
---|
276 | module for more details.</para> |
---|
277 | |
---|
278 | </section> |
---|
279 | |
---|
280 | <section> |
---|
281 | <title>Ability to scan the same file several times</title> |
---|
282 | |
---|
283 | <para>As said above, it's possible to compile a C++ file twice, with |
---|
284 | different include paths. Therefore, include dependencies for |
---|
285 | those compilations can be different. The problem is that bjam |
---|
286 | does not allow several scans of the same target.</para> |
---|
287 | |
---|
288 | <para>The solution in Boost.Build is straigtforward. When a virtual |
---|
289 | target is converted to bjam target (via |
---|
290 | <literal>virtual-target.actualize</literal> method), we specify the scanner |
---|
291 | object to be used. The actualize method will create different |
---|
292 | bjam targets for different scanners.</para> |
---|
293 | |
---|
294 | <para>All targets with specific scanner are made dependent on target |
---|
295 | without scanner, which target is always created. This is done in |
---|
296 | case the target is updated. The updating action will be |
---|
297 | associated with target without scanner, but if sources for that |
---|
298 | action are touched, all targets — with scanner and without |
---|
299 | should be considered outdated.</para> |
---|
300 | |
---|
301 | <para>For example, assume that "a.cpp" is compiled by two compilers |
---|
302 | with different include path. It's also copied into some install |
---|
303 | location. In turn, it's produced from "a.verbatim". The |
---|
304 | dependency graph will look like:</para> |
---|
305 | |
---|
306 | <programlisting> |
---|
307 | a.o (<toolset>gcc) <--(compile)-- a.cpp (scanner1) ----+ |
---|
308 | a.o (<toolset>msvc) <--(compile)-- a.cpp (scanner2) ----| |
---|
309 | a.cpp (installed copy) <--(copy) ----------------------- a.cpp (no scanner) |
---|
310 | ^ |
---|
311 | | |
---|
312 | a.verbose --------------------------------+ |
---|
313 | </programlisting> |
---|
314 | |
---|
315 | </section> |
---|
316 | <section> |
---|
317 | <title>Proper detection of dependencies on generated files.</title> |
---|
318 | |
---|
319 | <para>This requirement breaks down to the following ones.</para> |
---|
320 | |
---|
321 | <orderedlist> |
---|
322 | <listitem> |
---|
323 | <simpara> |
---|
324 | If when compiling "a.cpp" there's include of "a.h", the |
---|
325 | "dir" directory is in include path, and a target called "a.h" |
---|
326 | will be generated to "dir", then bjam should discover the |
---|
327 | include, and create "a.h" before compiling "a.cpp". |
---|
328 | </simpara> |
---|
329 | </listitem> |
---|
330 | |
---|
331 | <listitem> |
---|
332 | <simpara> |
---|
333 | Since almost always Boost.Build generates targets to a |
---|
334 | "bin" directory, it should be supported as well. I.e. in the |
---|
335 | scanario above, Jamfile in "dir" might create a main target, |
---|
336 | which generates "a.h". The file will be generated to "dir/bin" |
---|
337 | directory, but we still have to recornize the dependency. |
---|
338 | </simpara> |
---|
339 | </listitem> |
---|
340 | </orderedlist> |
---|
341 | |
---|
342 | <para>The first requirement means that when determining what "a.h" |
---|
343 | means, when found in "a.cpp", we have to iterate over all |
---|
344 | directories in include paths, checking for each one:</para> |
---|
345 | |
---|
346 | <orderedlist> |
---|
347 | <listitem> |
---|
348 | <simpara> |
---|
349 | If there's file "a.h" in that directory, or |
---|
350 | </simpara> |
---|
351 | </listitem> |
---|
352 | |
---|
353 | <listitem> |
---|
354 | <simpara> |
---|
355 | If there's a target called "a.h", which will be generated |
---|
356 | to that directory. |
---|
357 | </simpara> |
---|
358 | </listitem> |
---|
359 | </orderedlist> |
---|
360 | |
---|
361 | <para>Classic Jam has built-in facilities for point (1) above, but |
---|
362 | that's not enough. It's hard to implement the right semantic |
---|
363 | without builtin support. For example, we could try to check if |
---|
364 | there's targer called "a.h" somewhere in dependency graph, and |
---|
365 | add a dependency to it. The problem is that without search in |
---|
366 | include path, the semantic may be incorrect. For example, one can |
---|
367 | have an action which generated some "dummy" header, for system |
---|
368 | which don't have the native one. Naturally, we don't want to |
---|
369 | depend on that generated header on platforms where native one is |
---|
370 | included.</para> |
---|
371 | |
---|
372 | <para>There are two design choices for builtin support. Suppose we |
---|
373 | have files a.cpp and b.cpp, and each one includes header.h, |
---|
374 | generated by some action. Dependency graph created by classic jam |
---|
375 | would look like:</para> |
---|
376 | |
---|
377 | <programlisting> |
---|
378 | a.cpp -----> <scanner1>header.h [search path: d1, d2, d3] |
---|
379 | |
---|
380 | |
---|
381 | <d2>header.h --------> header.y |
---|
382 | [generated in d2] |
---|
383 | |
---|
384 | b.cpp -----> <scanner2>header.h [ search path: d1, d2, d4] |
---|
385 | </programlisting> |
---|
386 | |
---|
387 | <para> |
---|
388 | In this case, Jam thinks all header.h target are not |
---|
389 | realated. The right dependency graph might be: |
---|
390 | |
---|
391 | <programlisting> |
---|
392 | a.cpp ---- |
---|
393 | \ |
---|
394 | \ |
---|
395 | >----> <d2>header.h --------> header.y |
---|
396 | / [generated in d2] |
---|
397 | / |
---|
398 | b.cpp ---- |
---|
399 | </programlisting> |
---|
400 | |
---|
401 | or |
---|
402 | |
---|
403 | <programlisting> |
---|
404 | a.cpp -----> <scanner1>header.h [search path: d1, d2, d3] |
---|
405 | | |
---|
406 | (includes) |
---|
407 | V |
---|
408 | <d2>header.h --------> header.y |
---|
409 | [generated in d2] |
---|
410 | ^ |
---|
411 | (includes) |
---|
412 | | |
---|
413 | b.cpp -----> <scanner2>header.h [ search path: d1, d2, d4] |
---|
414 | </programlisting> |
---|
415 | </para> |
---|
416 | |
---|
417 | <para> |
---|
418 | The first alternative was used for some time. The problem |
---|
419 | however is: what include paths should be used when scanning |
---|
420 | header.h? The second alternative was suggested by Matt Armstrong. |
---|
421 | It has similiar effect: add targets which depend on |
---|
422 | <scanner1>header.h will also depend on <d2>header.h. |
---|
423 | But now we have two different target with two different scanners, |
---|
424 | and those targets can be scanned independently. The problem of |
---|
425 | first alternative is avoided, so the second alternative is |
---|
426 | implemented now. |
---|
427 | </para> |
---|
428 | |
---|
429 | <para>The second sub-requirements is that targets generated to "bin" |
---|
430 | directory are handled as well. Boost.Build implements |
---|
431 | semi-automatic approach. When compiling C++ files the process |
---|
432 | is:</para> |
---|
433 | |
---|
434 | <orderedlist> |
---|
435 | <listitem> |
---|
436 | <simpara> |
---|
437 | The main target to which compiled file belongs is found. |
---|
438 | </simpara> |
---|
439 | </listitem> |
---|
440 | |
---|
441 | <listitem> |
---|
442 | <simpara> |
---|
443 | All other main targets that the found one depends on are |
---|
444 | found. Those include main target which are used as sources, or |
---|
445 | present as values of "dependency" features. |
---|
446 | </simpara> |
---|
447 | </listitem> |
---|
448 | |
---|
449 | <listitem> |
---|
450 | <simpara> |
---|
451 | All directories where files belonging to those main target |
---|
452 | will be generated are added to the include path. |
---|
453 | </simpara> |
---|
454 | </listitem> |
---|
455 | </orderedlist> |
---|
456 | |
---|
457 | <para>After this is done, dependencies are found by the approach |
---|
458 | explained previously.</para> |
---|
459 | |
---|
460 | <para>Note that if a target uses generated headers from other main |
---|
461 | target, that main target should be explicitly specified as |
---|
462 | dependency property. It would be better to lift this requirement, |
---|
463 | but it seems not very problematic in practice.</para> |
---|
464 | |
---|
465 | <para>For target types other than C++, adding of include paths must |
---|
466 | be implemented anew.</para> |
---|
467 | |
---|
468 | </section> |
---|
469 | <section> |
---|
470 | <title>Proper detection of dependencies from generated files</title> |
---|
471 | |
---|
472 | <para>Suppose file "a.cpp" includes "a.h" and both are generated by |
---|
473 | some action. Note that classic jam has two stages. In first stage |
---|
474 | dependency graph graph is build and actions which should be run |
---|
475 | are determined. In second stage the actions are executed. |
---|
476 | Initially, neither file exists, so the include is not found. As |
---|
477 | the result, jam might attempt to compile a.cpp before creating |
---|
478 | a.h, and compilation will fail.</para> |
---|
479 | |
---|
480 | <para>The solution in Boost.Jam is to perform additional dependency |
---|
481 | scans after targets are updated. This break separation between |
---|
482 | build stages in jam — which some people consider a good |
---|
483 | thing — but I'm not aware of any better solution.</para> |
---|
484 | |
---|
485 | <para>In order to understand the rest of this section, you better |
---|
486 | read some details about jam dependency scanning, available |
---|
487 | <ulink url= |
---|
488 | "http://public.perforce.com:8080/@md=d&cd=//public/jam/src/&ra=s&c=kVu@//2614?ac=10"> |
---|
489 | at this link</ulink>.</para> |
---|
490 | |
---|
491 | <para>Whenever a target is updated, Boost.Jam rescans it for |
---|
492 | includes. Consider this graph, created before any actions are |
---|
493 | run.</para> |
---|
494 | |
---|
495 | <programlisting> |
---|
496 | A -------> C ----> C.pro |
---|
497 | / |
---|
498 | B --/ C-includes ---> D |
---|
499 | </programlisting> |
---|
500 | |
---|
501 | <para> |
---|
502 | Both A and B have dependency on C and C-includes (the latter |
---|
503 | dependency is not shown). Say during building we've tried to create |
---|
504 | A, then tried to create C and successfully created C. |
---|
505 | </para> |
---|
506 | |
---|
507 | <para>In that case, the set of includes in C might well have |
---|
508 | changed. We do not bother to detect precisely which includes were |
---|
509 | added or removed. Instead we create another internal node |
---|
510 | C-includes-2. Then we determine what actions should be run to |
---|
511 | update the target. In fact this mean that we perform logic of |
---|
512 | first stage while already executing stage.</para> |
---|
513 | |
---|
514 | <para>After actions for C-includes-2 are determined, we add |
---|
515 | C-includes-2 to the list of A's dependents, and stage 2 proceeds |
---|
516 | as usual. Unfortunately, we can't do the same with target B, |
---|
517 | since when it's not visited, C target does not know B depends on |
---|
518 | it. So, we add a flag to C which tells and it was rescanned. When |
---|
519 | visiting B target, the flag is notices and C-includes-2 will be |
---|
520 | added to the list of B's dependencies.</para> |
---|
521 | |
---|
522 | <para>Note also that internal nodes are sometimes updated too. |
---|
523 | Consider this dependency graph:</para> |
---|
524 | |
---|
525 | <programlisting> |
---|
526 | a.o ---> a.cpp |
---|
527 | a.cpp-includes --> a.h (scanned) |
---|
528 | a.h-includes ------> a.h (generated) |
---|
529 | | |
---|
530 | | |
---|
531 | a.pro <-------------------------------------------+ |
---|
532 | </programlisting> |
---|
533 | |
---|
534 | <para>Here, out handling of generated headers come into play. Say |
---|
535 | that a.h exists but is out of date with respect to "a.pro", then |
---|
536 | "a.h (generated)" and "a.h-includes" will be marking for |
---|
537 | updating, but "a.h (scanned)" won't be marked. We have to rescan |
---|
538 | "a.h" file after it's created, but since "a.h (generated)" has no |
---|
539 | scanner associated with it, it's only possible to rescan "a.h" |
---|
540 | after "a.h-includes" target was updated.</para> |
---|
541 | |
---|
542 | <para>Tbe above consideration lead to decision that we'll rescan a |
---|
543 | target whenever it's updated, no matter if this target is |
---|
544 | internal or not.</para> |
---|
545 | |
---|
546 | <warning> |
---|
547 | <para> |
---|
548 | The remainder of this document is not indended to be read at |
---|
549 | all. This will be rearranged in future. |
---|
550 | </para> |
---|
551 | </warning> |
---|
552 | |
---|
553 | <section> |
---|
554 | <title>File targets</title> |
---|
555 | |
---|
556 | <para> |
---|
557 | As described above, file targets corresponds |
---|
558 | to files that Boost.Build manages. User's may be concerned about |
---|
559 | file targets in three ways: when declaring file target types, |
---|
560 | when declaring transformations between types, and when |
---|
561 | determining where file target will be placed. File targets can |
---|
562 | also be connected with actions, that determine how the target is |
---|
563 | created. Both file targets and actions are implemented in the |
---|
564 | <literal>virtual-target</literal> module. |
---|
565 | </para> |
---|
566 | |
---|
567 | <section> |
---|
568 | <title>Types</title> |
---|
569 | |
---|
570 | <para>A file target can be given a file, which determines |
---|
571 | what transformations can be applied to the file. The |
---|
572 | <literal>type.register</literal> rule declares new types. File type can |
---|
573 | also be assigned a scanner, which is used to find implicit |
---|
574 | dependencies. See "dependency scanning" [ link? ] below.</para> |
---|
575 | </section> |
---|
576 | </section> |
---|
577 | |
---|
578 | <section> |
---|
579 | <title>Target paths</title> |
---|
580 | |
---|
581 | <para>To distinguish targets build with different properties, they |
---|
582 | are put in different directories. Rules for determining target |
---|
583 | paths are given below:</para> |
---|
584 | |
---|
585 | <orderedlist> |
---|
586 | <listitem> |
---|
587 | <simpara> |
---|
588 | All targets are placed under directory corresponding to the |
---|
589 | project where they are defined. |
---|
590 | </simpara> |
---|
591 | </listitem> |
---|
592 | |
---|
593 | <listitem> |
---|
594 | <simpara> |
---|
595 | Each non free, non incidental property cause an additional |
---|
596 | element to be added to the target path. That element has the |
---|
597 | form <literal><feature-name>-<feature-value></literal> for |
---|
598 | ordinary features and <literal><feature-value></literal> for |
---|
599 | implicit ones. [Note about composite features]. |
---|
600 | </simpara> |
---|
601 | </listitem> |
---|
602 | |
---|
603 | <listitem> |
---|
604 | <simpara> |
---|
605 | If the set of free, non incidental properties is different |
---|
606 | from the set of free, non incidental properties for the project |
---|
607 | in which the main target that uses the target is defined, a |
---|
608 | part of the form <literal>main_target-<name></literal> is added to |
---|
609 | the target path. <emphasis role="bold">Note:</emphasis>It would be nice to completely |
---|
610 | track free features also, but this appears to be complex and |
---|
611 | not extremely needed. |
---|
612 | </simpara> |
---|
613 | </listitem> |
---|
614 | </orderedlist> |
---|
615 | |
---|
616 | <para>For example, we might have these paths:</para> |
---|
617 | |
---|
618 | <programlisting> |
---|
619 | debug/optimization-off |
---|
620 | debug/main-target-a |
---|
621 | </programlisting> |
---|
622 | |
---|
623 | </section> |
---|
624 | </section> |
---|
625 | </section> |
---|
626 | </section> |
---|
627 | </appendix> |
---|
628 | |
---|
629 | <!-- |
---|
630 | Local Variables: |
---|
631 | mode: xml |
---|
632 | sgml-indent-data: t |
---|
633 | sgml-parent-document: ("userman.xml" "chapter") |
---|
634 | sgml-set-face: t |
---|
635 | End: |
---|
636 | --> |
---|