Fix XML in documentation, and in the bin/scons-doc.py script that generates
[scons.git] / doc / user / caching.xml
1 <!--
2
3   __COPYRIGHT__
4
5   Permission is hereby granted, free of charge, to any person obtaining
6   a copy of this software and associated documentation files (the
7   "Software"), to deal in the Software without restriction, including
8   without limitation the rights to use, copy, modify, merge, publish,
9   distribute, sublicense, and/or sell copies of the Software, and to
10   permit persons to whom the Software is furnished to do so, subject to
11   the following conditions:
12
13   The above copyright notice and this permission notice shall be included
14   in all copies or substantial portions of the Software.
15
16   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17   KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18   WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24 -->
25
26   <para>
27
28   On multi-developer software projects,
29   you can sometimes speed up every developer's builds a lot by
30   allowing them to share the derived files that they build.
31   &SCons; makes this easy, as well as reliable.
32
33   </para>
34
35   <section>
36   <title>Specifying the Shared Cache Directory</title>
37
38     <para>
39
40     To enable sharing of derived files,
41     use the &CacheDir; function
42     in any &SConscript; file:
43
44     </para>
45
46     <programlisting>
47        CacheDir('/usr/local/build_cache')
48     </programlisting>
49
50     <para>
51
52     Note that the directory you specify must already exist
53     and be readable and writable by all developers
54     who will be sharing derived files.
55     It should also be in some central location
56     that all builds will be able to access.
57     In environments where developers are using separate systems
58     (like individual workstations) for builds,
59     this directory would typically be
60     on a shared or NFS-mounted file system.
61
62     </para>
63
64     <para>
65
66     Here's what happens:
67     When a build has a &CacheDir; specified,
68     every time a file is built,
69     it is stored in the shared cache directory
70     along with its MD5 build signature.
71       <footnote>
72       <para>
73       Actually, the MD5 signature is used as the name of the file
74       in the shared cache directory in which the contents are stored.
75       </para>
76       </footnote>
77     On subsequent builds,
78     before an action is invoked to build a file,
79     &SCons; will check the shared cache directory
80     to see if a file with the exact same build
81     signature already exists.
82     If so, the derived file will not be built locally,
83     but will be copied into the local build directory
84     from the shared cache directory,
85     like so:
86
87     </para>
88
89     <screen>
90       % <userinput>scons -Q</userinput>
91       cc -o hello.o -c hello.c
92       cc -o hello hello.o
93       % <userinput>scons -Q -c</userinput>
94       Removed hello.o
95       Removed hello
96       % <userinput>scons -Q</userinput>
97       Retrieved `hello.o' from cache
98       Retrieved `hello' from cache
99     </screen>
100
101     <para>
102
103     Note that the &CacheDir; feature still calculates
104     MD5 build sigantures for the shared cache file names
105     even if you configure &SCons; to use timestamps
106     to decide if files are up to date.
107     (See the <xref linkend="chap-depends"></xref>
108     chapter for information about the &Decider; function.)
109     Consequently, using &CacheDir; may reduce or eliminate any
110     potential performance improvements
111     from using timestamps for up-to-date decisions.
112
113     </para>
114
115   </section>
116
117   <section>
118   <title>Keeping Build Output Consistent</title>
119
120     <para>
121
122     One potential drawback to using a shared cache
123     is that the output printed by &SCons;
124     can be inconsistent from invocation to invocation,
125     because any given file may be rebuilt one time
126     and retrieved from the shared cache the next time.
127     This can make analyzing build output more difficult,
128     especially for automated scripts that
129     expect consistent output each time.
130
131     </para>
132
133     <para>
134
135     If, however, you use the <literal>--cache-show</literal> option,
136     &SCons; will print the command line that it
137     <emphasis>would</emphasis> have executed
138     to build the file,
139     even when it is retrieving the file from the shared cache.
140     This makes the build output consistent
141     every time the build is run:
142
143     </para>
144
145     <screen>
146       % <userinput>scons -Q</userinput>
147       cc -o hello.o -c hello.c
148       cc -o hello hello.o
149       % <userinput>scons -Q -c</userinput>
150       Removed hello.o
151       Removed hello
152       % <userinput>scons -Q --cache-show</userinput>
153       cc -o hello.o -c hello.c
154       cc -o hello hello.o
155     </screen>
156
157     <para>
158
159     The trade-off, of course, is that you no longer
160     know whether or not &SCons;
161     has retrieved a derived file from cache
162     or has rebuilt it locally.
163
164     </para>
165
166   </section>
167
168   <section>
169   <title>Not Using the Shared Cache for Specific Files</title>
170
171     <para>
172
173     You may want to disable caching for certain
174     specific files in your configuration.
175     For example, if you only want to put
176     executable files in a central cache,
177     but not the intermediate object files,
178     you can use the &NoCache;
179     function to specify that the
180     object files should not be cached:
181
182     </para>
183
184     <programlisting>
185        env = Environment()
186        obj = env.Object('hello.c')
187        env.Program('hello.c')
188        CacheDir('cache')
189        NoCache('hello.o')
190     </programlisting>
191
192     <para>
193
194     Then when you run &scons; after cleaning
195     the built targets,
196     it will recompile the object file locally
197     (since it doesn't exist in the shared cache directory),
198     but still realize that the shared cache directory
199     contains an up-to-date executable program
200     that can be retrieved instead of re-linking:
201
202     </para>
203
204     <!--
205
206     <scons_output example="ex1">
207       <scons_output_command>scons -Q</scons_output_command>
208       <scons_output_command>scons -Q -c</scons_output_command>
209       <scons_output_command>scons -Q</scons_output_command>
210     </scons_output>
211
212     -->
213
214     <screen>
215       % <userinput>scons -Q</userinput>
216       cc -o hello.o -c hello.c
217       cc -o hello hello.o
218       % <userinput>scons -Q -c</userinput>
219       Removed hello.o
220       Removed hello
221       % <userinput>scons -Q</userinput>
222       cc -o hello.o -c hello.c
223       Retrieved `hello' from cache
224     </screen>
225
226   </section>
227
228   <section>
229   <title>Disabling the Shared Cache</title>
230
231     <para>
232
233     Retrieving an already-built file
234     from the shared cache
235     is usually a significant time-savings
236     over rebuilding the file,
237     but how much of a savings
238     (or even whether it saves time at all)
239     can depend a great deal on your
240     system or network configuration.
241     For example, retrieving cached files
242     from a busy server over a busy network
243     might end up being slower than
244     rebuilding the files locally.
245
246     </para>
247
248     <para>
249
250     In these cases, you can specify
251     the <literal>--cache-disable</literal>
252     command-line option to tell &SCons;
253     to not retrieve already-built files from the
254     shared cache directory:
255
256     </para>
257
258     <screen>
259       % <userinput>scons -Q</userinput>
260       cc -o hello.o -c hello.c
261       cc -o hello hello.o
262       % <userinput>scons -Q -c</userinput>
263       Removed hello.o
264       Removed hello
265       % <userinput>scons -Q</userinput>
266       Retrieved `hello.o' from cache
267       Retrieved `hello' from cache
268       % <userinput>scons -Q -c</userinput>
269       Removed hello.o
270       Removed hello
271       % <userinput>scons -Q --cache-disable</userinput>
272       cc -o hello.o -c hello.c
273       cc -o hello hello.o
274     </screen>
275
276   </section>
277
278   <section>
279   <title>Populating a Shared Cache With Already-Built Files</title>
280
281     <para>
282
283     Sometimes, you may have one or more derived files
284     already built in your local build tree
285     that you wish to make available to other people doing builds.
286     For example, you may find it more effective to perform
287     integration builds with the cache disabled
288     (per the previous section)
289     and only populate the shared cache directory
290     with the built files after the integration build
291     has completed successfully.
292     This way, the cache will only get filled up
293     with derived files that are part of a complete, successful build
294     not with files that might be later overwritten
295     while you debug integration problems.
296
297     </para>
298
299     <para>
300
301     In this case, you can use the
302     the <literal>--cache-force</literal> option
303     to tell &SCons; to put all derived files in the cache,
304     even if the files already exist in your local tree
305     from having been built by a previous invocation:
306
307     </para>
308
309     <screen>
310       % <userinput>scons -Q --cache-disable</userinput>
311       cc -o hello.o -c hello.c
312       cc -o hello hello.o
313       % <userinput>scons -Q -c</userinput>
314       Removed hello.o
315       Removed hello
316       % <userinput>scons -Q --cache-disable</userinput>
317       cc -o hello.o -c hello.c
318       cc -o hello hello.o
319       % <userinput>scons -Q --cache-force</userinput>
320       scons: `.' is up to date.
321       % <userinput>scons -Q</userinput>
322       scons: `.' is up to date.
323     </screen>
324
325     <para>
326
327     Notice how the above sample run
328     demonstrates that the <literal>--cache-disable</literal>
329     option avoids putting the built
330     <filename>hello.o</filename>
331     and
332     <filename>hello</filename> files in the cache,
333     but after using the <literal>--cache-force</literal> option,
334     the files have been put in the cache
335     for the next invocation to retrieve.
336
337     </para>
338
339   </section>
340
341   <section>
342   <title>Minimizing Cache Contention:  the <literal>--random</literal> Option</title>
343
344     <para>
345
346     If you allow multiple builds to update the
347     shared cache directory simultaneously,
348     two builds that occur at the same time
349     can sometimes start "racing"
350     with one another to build the same files
351     in the same order.
352     If, for example,
353     you are linking multiple files into an executable program:
354
355     </para>
356
357     <programlisting>
358        Program('prog',
359                ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c'])
360     </programlisting>
361
362     <para>
363
364     &SCons; will normally build the input object files
365     on which the program depends in their normal, sorted order:
366
367     </para>
368
369     <screen>
370       % <userinput>scons -Q</userinput>
371       cc -o f1.o -c f1.c
372       cc -o f2.o -c f2.c
373       cc -o f3.o -c f3.c
374       cc -o f4.o -c f4.c
375       cc -o f5.o -c f5.c
376       cc -o prog f1.o f2.o f3.o f4.o f5.o
377     </screen>
378
379     <para>
380
381     But if two such builds take place simultaneously,
382     they may each look in the cache at nearly the same
383     time and both decide that <filename>f1.o</filename>
384     must be rebuilt and pushed into the shared cache directory,
385     then both decide that <filename>f2.o</filename>
386     must be rebuilt (and pushed into the shared cache directory),
387     then both decide that <filename>f3.o</filename>
388     must be rebuilt...
389     This won't cause any actual build problems--both
390     builds will succeed,
391     generate correct output files,
392     and populate the cache--but
393     it does represent wasted effort.
394
395     </para>
396
397     <para>
398
399     To alleviate such contention for the cache,
400     you can use the <literal>--random</literal> command-line option
401     to tell &SCons; to build dependencies
402     in a random order:
403
404     </para>
405
406     <!--
407
408     The following <screen> output was generated by this:
409
410     <scons_output example="ex-random">
411       <scons_output_command>scons -Q - -random</scons_output_command>
412     </scons_output>
413
414     We captured it directly here to guarantee a "random" order,
415     guarding against the potential for - -random to happen
416     to return things in the original sorted order.
417
418     -->
419
420     <screen>
421       % <userinput>scons -Q --random</userinput>
422       cc -o f3.o -c f3.c
423       cc -o f1.o -c f1.c
424       cc -o f5.o -c f5.c
425       cc -o f2.o -c f2.c
426       cc -o f4.o -c f4.c
427       cc -o prog f1.o f2.o f3.o f4.o f5.o
428     </screen>
429
430     <para>
431
432     Multiple builds using the <literal>--random</literal> option
433     will usually build their dependencies in different,
434     random orders,
435     which minimizes the chances for a lot of
436     contention for same-named files
437     in the shared cache directory.
438     Multiple simultaneous builds might still race to try to build
439     the same target file on occasion,
440     but long sequences of inefficient contention
441     should be rare.
442
443     </para>
444
445     <para>
446
447     Note, of course,
448     the <literal>--random</literal> option
449     will cause the output that &SCons; prints
450     to be inconsistent from invocation to invocation,
451     which may be an issue when
452     trying to compare output from different build runs.
453
454     </para>
455
456     <para>
457
458     If you want to make sure dependencies will be built
459     in a random order without having to specify
460     the <literal>--random</literal> on very command line,
461     you can use the &SetOption; function to
462     set the <literal>random</literal> option
463     within any &SConscript; file:
464
465     </para>
466
467     <programlisting>
468        Program('prog',
469                ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c'])
470
471        SetOption('random', 1)
472        Program('prog',
473                ['f1.c', 'f2.c', 'f3.c', 'f4.c', 'f5.c'])
474     </programlisting>
475
476   </section>
477
478   <!--
479
480   <section>
481   <title>Troubleshooting Shared Caching:  the &cache-debug; Option</title>
482
483     <para>
484
485     XXX describe the - - cache-debug option
486     XXX maybe point to the troubleshooting appendix?
487
488     </para>
489
490   </section>
491
492   -->
493
494   <!--
495
496   <section>
497
498     <para>
499
500     XXX describe CacheDir management:  monitoring, deleting, etc.
501
502     </para>
503
504   </section>
505
506   -->