Fix XML in documentation, and in the bin/scons-doc.py script that generates
[scons.git] / doc / python10 / design.xml
1 <para>
2
3   The &SCons; architecture consists of three layers:
4
5 </para>
6
7 <mediaobject>
8   <imageobject>
9     <imagedata fileref="arch" format="eps" align="center"/>
10   </imageobject>
11   <imageobject>
12     <imagedata fileref="arch.jpg" format="jpg" align="center"/>
13   </imageobject>
14   <!--  PDF files?
15   <imageobject>
16     <imagedata fileref="arch.pdf" align="center"/>
17   </imageobject>
18   -->
19 </mediaobject>
20
21 <itemizedlist>
22
23   <listitem>
24     <para>
25
26       The &SCons; <emphasis>Build Engine</emphasis>, a package of Python
27       modules that handle dependency management and updating out-of-date
28       objects.
29
30     </para>
31   </listitem>
32
33   <listitem>
34     <para>
35
36       The &SCons; <emphasis>API</emphasis> (applications programming
37       interface) between the Build Engine
38       and the user interface.
39
40     </para>
41   </listitem>
42
43   <listitem>
44     <para>
45
46       The &scons; <emphasis>script</emphasis> itself (note lower case
47       <emphasis>sc</emphasis>), which is the pre-provided interface to
48       the Build Engine.
49
50     </para>
51   </listitem>
52
53 </itemizedlist>
54
55 <para>
56
57   Notice that this architecture separates the internal workings of
58   &SCons; (the Build Engine) from the
59   external user interface.  The benefit is that the &SCons; Build Engine
60   can be imported into any other software package written in Python
61   to support a variety of user interfaces&mdash;or, to look at it
62   in reverse, other software interfaces can use the &SCons; Build
63   Engine to manage dependencies between their objects.
64
65 </para>
66
67 <para>
68
69   Because the
70   &SCons; package itself is modular, only those parts of the package
71   relevant to the embedding interface need be imported; for example,
72   a utility that wants to use only file timestamps for checking
73   whether a file is up-to-date
74   need not import the MD5 signature module.
75
76 </para>
77
78 <section>
79   <title>The &SCons; Build Engine</title>
80
81   <para>
82
83     The Build Engine is a package of Python modules that
84     form the heart of &SCons;.
85
86     The Build Engine can be broadly divided into five
87     architectural subsystems, each responsible
88     for a crucial part of &SCons; functionality:
89
90   </para>
91
92   <itemizedlist>
93
94     <listitem>
95       <para>
96
97         A <emphasis>node</emphasis> subsystem, responsible for managing
98         the files (or other objects) to be built, and the dependency
99         relationships between them.
100
101       </para>
102     </listitem>
103
104     <listitem>
105       <para>
106
107         A <emphasis>scanner</emphasis> subsystem, responsible for
108         scanning various file types for implicit dependencies.
109
110       </para>
111     </listitem>
112
113     <listitem>
114       <para>
115
116         A <emphasis>signature</emphasis> subsystem, responsible for
117         deciding whether a given file (or other object) requires
118         rebuilding.
119
120       </para>
121     </listitem>
122
123     <listitem>
124       <para>
125
126         A <emphasis>builder</emphasis> subsystem, responsible for
127         actually executing the necessary command or function to
128         build a file (or other object).
129
130       </para>
131     </listitem>
132
133     <listitem>
134       <para>
135
136         A <emphasis>job/task</emphasis> subsystem, responsible for
137         handling parallelization of builds.
138
139       </para>
140     </listitem>
141
142   </itemizedlist>
143
144   <para>
145
146     The rest of this section will provide a high-level overview of the
147     class structure of each of these Build Engine subsystems.
148
149   </para>
150
151   <section>
152     <title>Node Subsystem</title>
153
154     <para>
155
156       The node subsystem of the Build Engine is
157       responsible for managing the knowledge in &SCons; of
158       the relationships among the external objects
159       (files) it is responsible for updating.
160       The most important of these relationships is
161       the dependency relationship between various &Node; objects,
162       which &SCons; uses to determine the order
163       in which builds should be performed.
164
165     </para>
166
167     <mediaobject>
168       <imageobject>
169         <imagedata fileref="node" format="eps" align="center"/>
170       </imageobject>
171       <imageobject>
172         <imagedata fileref="node.jpg" format="jpg" align="center"/>
173       </imageobject>
174       <!--  PDF files?
175       <imageobject>
176         <imagedata fileref="node.pdf" align="center"/>
177       </imageobject>
178       -->
179     </mediaobject>
180
181     <para>
182
183       The &scons; script (or other
184       user interface)
185       tells the Build Engine
186       about dependencies
187       through its &consenv; API.
188       The Build Engine also discovers
189       dependencies automatically through the use of &Scanner; objects.
190
191     </para>
192
193     <para>
194
195       Subclasses of the &Node; class maintain additional
196       relationships that reflect the real-world
197       existence of these objects.
198       For example, the &Node_FS; subclass
199       is responsible for managing a
200       representation of the directory hierarchy
201       of a file system.
202
203     </para>
204
205     <para>
206
207       A &Walker; class is used by other subsystems
208       to walk the dependency tree maintained by the &Node; class.
209       The &Walker; class maintains a stack of &Node; objects
210       visited during its depth-first traversal of the
211       dependency tree,
212       and uses an intermediate node &Wrapper; class
213       to maintain state information about a
214       &Node; object's dependencies.
215
216     </para>
217
218   </section>
219
220   <section>
221     <title>Scanner Subsystem</title>
222
223     <para>
224
225       The scanner subsystem is responsible for maintaining
226       objects that can scan the contents of a &Node;'s
227       for implicit dependencies.
228
229     </para>
230
231     <mediaobject>
232       <imageobject>
233         <imagedata fileref="scanner" format="eps" align="center"/>
234       </imageobject>
235       <imageobject>
236         <imagedata fileref="scanner.jpg" format="jpg" align="center"/>
237       </imageobject>
238       <!--  PDF files?
239       <imageobject>
240         <imagedata fileref="scanner.pdf" align="center"/>
241       </imageobject>
242       -->
243     </mediaobject>
244
245     <para>
246
247       In practice, a given &Scanner; subclass object
248       functions as a prototype,
249       returning clones of itself
250       depending on the &consenv;
251       values governing how the &Node;
252       should be scanned.
253
254     </para>
255
256   </section>
257
258   <section>
259     <title>Signature Subsystem</title>
260
261     <para>
262
263       The signature subsystem is responsible for computing
264       signature information for &Node; objects.
265       The signature subsystem in &SCons;
266       supports multiple ways to
267       determine whether a &Node; is up-to-date
268       by using an abstract &Sig; class
269       as a strategy wrapper:
270
271     </para>
272
273     <mediaobject>
274       <imageobject>
275         <imagedata fileref="sig" format="eps" align="center"/>
276       </imageobject>
277       <imageobject>
278         <imagedata fileref="sig.jpg" format="jpg" align="center"/>
279       </imageobject>
280       <!--  PDF files?
281       <imageobject>
282         <imagedata fileref="sig.pdf" align="center"/>
283       </imageobject>
284       -->
285     </mediaobject>
286
287     <para>
288
289       By default, &SCons; tracks dependencies by computing and
290       maintaining MD5 signatures for the contents of each source file
291       (or other object). The signature of a <emphasis>derived</emphasis>
292       file consists of the aggregate of the signatures of all the source
293       files <emphasis>plus</emphasis> the command-line string used to
294       build the file. These signatures are stored in a &sconsign; file
295       in each directory.
296
297     </para>
298
299     <para>
300
301       If the contents of any of the source files changes, the change to its
302       MD5 signature is propogated to the signature of the derived file(s). The
303       simple fact that the new signature does not match the stored signature
304       indicates that the derived file is not up to date and must be rebuilt.
305
306     </para>
307
308     <para>
309
310       A separate &TimeStamp; subclass of the &Sig; class supports
311       the use of traditional file timestamps for
312       deciding whether files are up-to-date.
313
314     </para>
315
316   </section>
317
318   <section>
319     <title>Builder Subsystem</title>
320
321     <para>
322
323       The &SCons; Build Engine records how out-of-date files
324       (or other objects) should be rebuilt in &Builder; objects,
325       maintained by the builder subsystem:
326
327     </para>
328
329     <mediaobject>
330       <imageobject>
331         <imagedata fileref="builder" format="eps" align="center"/>
332       </imageobject>
333       <imageobject>
334         <imagedata fileref="builder.jpg" format="jpg" align="center"/>
335       </imageobject>
336       <!--  PDF files?
337       <imageobject>
338         <imagedata fileref="builder.pdf" align="center"/>
339       </imageobject>
340       -->
341     </mediaobject>
342
343     <para>
344       
345       The actual underlying class name is &BuilderBase;,
346       and there are subclasses that can encapsulate
347       multiple &Builder; objects for special purposes.
348       One subclass
349       (&CompositeBuilder;)
350       selects an appropriate encapsulated &Builder;
351       based on the file suffix of the target object.
352       The other
353       (&MultiStepBuilder;).
354       can chain together multiple
355       &Builder; objects,
356       for example,
357       to build an executable program from a source file
358       through an implicit intermediate object file.
359
360     </para>
361
362     <para>
363
364       A &BuilderBase; object has an associated
365       &ActionBase; object
366       responsible for actually executing
367       the appropriate steps
368       to update the target file.
369       There are three subclasses,
370       one for externally executable commands
371       (&CommandAction;),
372       one for Python functions
373       (&FunctionAction;),
374       and one for lists of
375       multiple &Action; objects
376       (&ListAction;).
377
378     </para>
379
380   </section>
381
382   <section>
383     <title>Job/Task Subsystem</title>
384
385     <para>
386
387       &SCons; supports parallel builds with a thread-based tasking
388       model, managed by the job/task subsystem.
389
390     </para>
391
392     <mediaobject>
393       <imageobject>
394         <imagedata fileref="job-task" format="eps" align="center"/>
395       </imageobject>
396       <imageobject>
397         <imagedata fileref="job-task.jpg" format="jpg" align="center"/>
398       </imageobject>
399       <!--  PDF files?
400       <imageobject>
401         <imagedata fileref="job-task.pdf" align="center"/>
402       </imageobject>
403       -->
404     </mediaobject>
405
406     <para>
407       
408       Instead of performing an outer-loop recursive descent
409       of the dependency tree and then forking a task when it finds a
410       file that needs updating, &SCons; starts as many threads as are
411       requested, each thread managed by the &Jobs; class.
412       As a performance optimization,
413       the &Jobs; class maintains an internal
414       distinction between
415       &Serial; and &Parallel;
416       build jobs,
417       so that serial builds
418       don't pay any performance penalty
419       by using a multi-threaded implementation
420       written for &Parallel; builds.
421
422     </para>
423
424     <para>
425       
426       Each &Jobs; object, running in its own thread,
427       then requests a &Task; from a central &Taskmaster;,
428       which is responsible
429       for handing out available &Task; objects for (re-)building
430       out-of-date nodes. A condition variable
431       makes sure that the &Jobs; objects
432       query the &Taskmaster; one at a time.
433
434     </para>
435
436     <para>
437
438       The &Taskmaster; uses the node subsystem's
439       &Walker; class to walk the dependency tree,
440       and the &Sig; class to use the
441       appropriate method
442       of deciding if a &Node; is up-to-date.
443
444     </para>
445
446     <para>
447
448       This scheme has many advantages over the standard &Make;
449       implementation of <option>-j</option>.
450       Effective use of <option>-j</option> is difficult
451       with the usual recursive use of Make,
452       because the number of jobs started by <option>-j</option> multiply
453       at each level of the source tree.
454       This makes the actual number of jobs
455       executed at any moment very dependent on the size and layout of
456       the tree. &SCons;, in contrast, starts only as many jobs as are
457       requested, and keeps them constantly busy (excepting jobs that
458       block waiting for their dependency files to finish building).
459
460     </para>
461
462   </section>
463
464 </section>
465
466 <section>
467   <title>The &SCons; API</title>
468
469   <para>
470
471     This section provides an overview of the &SCons; interface. The
472     complete interface specification is both more detailed and flexible
473     than this overview.
474
475   </para>
476
477   <section>
478     <title>&ConsVars;</title>
479
480     <para>
481
482       In &SCons;, a &consenv; is an object through which an external
483       interface (such as the &scons; script) communicates dependency
484       information to the &SCons; Build Engine.
485
486     </para>
487
488     <para>
489
490       A construction environment is implemented as a dictionary
491       containing:
492
493     </para>
494
495     <itemizedlist>
496
497       <listitem>
498         <para>
499
500           construction variables, string values that are substituted
501           into command lines or used by builder functions;
502
503         </para>
504       </listitem>
505
506       <listitem>
507         <para>
508
509           one or more &Builder; objects that can be invoked to update a
510           file or other object;
511
512         </para>
513       </listitem>
514
515       <listitem>
516         <para>
517
518           one or more &Scanner; objects that can be used to
519           scan a file automatically for dependencies (such as
520           files specified on <literal>#include</literal> lines).
521
522         </para>
523       </listitem>
524
525     </itemizedlist>
526
527     <para>
528
529       &Consenvs; are instantiated as follows:
530
531     </para>
532
533     <programlisting>
534       env = Environment()
535       env_debug = Environment(CCFLAGS = '-g')
536     </programlisting>
537
538   </section>
539
540   <section>
541     <title>&Builder; Objects</title>
542
543     <para>
544
545       An &SCons; &Builder; object encapsulates information about how to
546       build a specific type of file: an executable program, an object
547       file, a library, etc. A &Builder; object is associated with a
548       file through an associated &consenv; method and later invoked to
549       actually build the file. The &Builder; object will typically use
550       construction variables (such as &CCFLAGS;, &LIBPATH;) to influence
551       the specific build execution.
552
553     </para>
554
555     <para>
556
557       &Builder; objects are instantiated as follows:
558
559     </para>
560
561     <programlisting>
562       bld = Builder(name = 'Program', action = "$CC -o $TARGET $SOURCES")
563     </programlisting>
564
565     <para>
566
567       In the above example, the <literal>action</literal> is a
568       command-line string in which the Build Engine will
569       interpolate the values of construction
570       variables before execution. The actual
571       <literal>action</literal> specified, though,
572       may be a function:
573
574     </para>
575
576     <programlisting>
577       def update(dest):
578           # [code to update the object]
579           return 0
580
581       bld = Builder(name = 'Program', function = update)
582     </programlisting>
583
584     <para>
585
586       Or a callable Python object (or class):
587
588     </para>
589
590     <programlisting>
591       class class_a:
592           def __call__(self, kw):
593               # build the desired object
594           return 0
595
596       builder = SCons.Builder.Builder(action = class_a())
597     </programlisting>
598
599     <para>
600
601       A &Builder; object may have the <literal>prefix</literal> and
602       <literal>suffix</literal> of its target file type specified
603       as keyword arguments at instantiation.  Additionally, the
604       suffix of the <emphasis>source files</emphasis> used by this
605       &Builder; to build its target files may be specified using the
606       <literal>src_suffix</literal> keyword argument:
607
608     </para>
609
610     <programlisting>
611       bld_lib = Builder(name = 'Library', action = "$AR r $TARGET $SOURCES",
612                         prefix = 'lib', suffix = '.a', src_suffix = '.o')
613     </programlisting>
614
615     <para>
616
617       The specified <literal>prefix</literal> and
618       <literal>suffix</literal> will be appended to the name of any
619       target file built by this &Builder; object, if they are not
620       already part of the file name.  The <literal>src_suffix</literal>
621       is used by the &SCons; Build Engine to chain together
622       multiple &Builder; objects to create,
623       for example, a library from the original source
624       files without having to specify the
625       intermediate <literal>.o</literal> files.
626
627     </para>
628
629     <para>
630
631       &Builder; objects are associated with a &consenv; through a
632       &consvar; named &BUILDERS;, a list of the &Builder; objects that
633       will be available for execution through the &consenv;:
634
635     </para>
636
637     <programlisting>
638       env = Environment(BUILDERS = [ Object, Library, WebPage, Program ])
639     </programlisting>
640
641   </section>
642
643   <section>
644     <title>&Scanner; Objects</title>
645
646     <para>
647
648       &Scanner; objects perform automatic checking for dependencies
649       by scanning the contents of files. The canonical
650       example is scanning a C source file or header file for
651       files specified on <literal>#include</literal> lines.
652
653     </para>
654
655     <para>
656
657       A &Scanner; object is instantiated as follows:
658
659     </para>
660
661     <programlisting>
662       def c_scan(contents):
663            # scan contents of file
664            return # list of files found
665
666       c_scanner = Scanner(name = 'CScan', function = c_scan,
667                           argument = None,
668                           skeys = ['.c', '.C', '.h', '.H')
669     </programlisting>
670
671     <para>
672
673       The <literal>skeys</literal> argument specifies a list of file
674       suffixes for file types that this &Scanner; knows how to scan.
675
676     </para>
677
678     <para>
679
680       &Scanner; objects are associated with a &consenv; through a
681       &consvar; named &SCANNERS;, a list of the &Scanner; objects that
682       will be available through the &consenv;:
683
684     </para>
685
686     <programlisting>
687       env = Environment(SCANNERS = [ CScan, M4Scan ])
688     </programlisting>
689
690     <para>
691
692       For utilities that will build files with a variety of file
693       suffixes, or which require unusual scanning rules, a &Scanner;
694       object may be associated explicitly with a &Builder; object as
695       follows:
696
697     </para>
698
699     <programlisting>
700       def tool_scan(contents):
701           # scan contents of file
702           return # list of files found
703
704       tool_scanner = Scanner(name = 'TScan', function = tool_scan)
705
706       bld = Builder(name = 'Tool', scanner = tool_scanner)
707     </programlisting>
708
709   </section>
710
711   <section>
712     <title>&BuildDir;</title>
713
714     <para>
715
716       &SCons; supports a flexible mechanism for building target
717       files in a separate build directory from the source files.
718       The &BuildDir; syntax is straightforward:
719
720     </para>
721
722     <programlisting>
723       BuildDir(source = 'src', build = 'bld')
724     </programlisting>
725
726     <para>
727
728       By
729       default, source files are linked or copied into the build
730       directory, because exactly replicating the source directory
731       is sometimes necessary for certain combinations of use of
732       <literal>#include "..."</literal> and <option>-I</option> search
733       paths.
734
735       An option exists to specify that only output files should be placed in
736       the build directory:
737
738     </para>
739
740     <programlisting>
741       BuildDir(source = 'src', build = 'bld', no_sources = 1)
742     </programlisting>
743
744   </section>
745
746   <section>
747     <title>&Repository;</title>
748
749     <para>
750
751       &SCons; supports the ability to search a list of code repositories
752       for source files and derived files. This works much like
753       &Make;'s <varname>VPATH</varname> feature, as implemented in
754       recent versions of GNU &Make;.
755       (The POSIX standard for &Make; specifies slightly
756       different behavior for <varname>VPATH</varname>.)
757       The syntax is:
758
759     </para>
760
761     <programlisting>
762       Repository('/home/source/1.1', '/home/source/1.0')
763     </programlisting>
764
765     <para>
766
767       A command-line <option>-Y</option> option exists to allow
768       repositories to be specified on the command line, or in the
769       &SCONSFLAGS; environment variable (not construction variable!).
770       This avoids a chicken-and-egg situation and allows the top-level
771       &SConstruct; file to be found in a repository as well.
772
773     </para>
774
775   </section>
776
777   <section>
778     <title>&Cache;</title>
779
780     <para>
781
782       &SCons; supports a way for developers to share derived files. Again, the
783       syntax is straightforward:
784
785     </para>
786
787     <programlisting>
788       Cache('/var/build.cache/i386')
789     </programlisting>
790
791     <para>
792
793       Copies of any derived files built will be placed in the specified
794       directory with their MD5 signature. If another build results in an
795       out-of-date derived file with the same signature, the derived file
796       will be copied from the cache instead of being rebuilt.
797
798     </para>
799
800   </section>
801
802 </section>
803
804 <section>
805   <title>The &scons; Script</title>
806
807   <para>
808
809     The &scons; script provides an interface
810     that looks roughly equivalent to the
811     classic &Make; utility&mdash;that is, execution from the command
812     line, and dependency information read from configuration files.
813
814   </para>
815
816   <para>
817
818     The most noticeable difference between &scons; and &Make;, or most
819     other build tools, is that the configuration files are actually
820     Python scripts, generically called "SConscripts" (although the
821     top-level "Makefile" is named &SConstruct;). Users do not have to
822     learn a new language syntax, but instead configure dependency
823     information by making direct calls to the Python API of the
824     &SCons; Build Engine. Here is an example &SConstruct; file which
825     builds a program in side-by-side normal and debug versions:
826
827   </para>
828
829   <programlisting>
830     env = Environment()
831     debug = env.Copy(CCFLAGS = '-g')
832
833     source_files = ['f1.c', 'f2.c', 'f3.c']
834
835     env.Program(target = 'foo', sources = source_files)
836     debug.Program(target = 'foo-debug', sources = source_files)
837   </programlisting>
838
839   <para>
840
841     Notice the fact that this file is a Python script, which allows us
842     to define and re-use an array that lists the source files.
843
844   </para>
845
846   <para>
847
848     Because quoting individul strings in long
849     lists of files can get tedious and error-prone, the &SCons;
850     methods support a short-cut of listing multiple files in a single
851     string, separated by white space.
852     This would change
853     the assignment in the above example to a more easily-readable:
854
855   </para>
856
857   <programlisting>
858     source_files = 'f1.c f2.c f3.c'
859   </programlisting>
860
861   <para>
862
863     The mechanism to establish hierarchical builds is to "include" any
864     subsidiary configuration files in the build by listing them explicitly
865     in a call to the &SConscript; function:
866
867   </para>
868
869   <programlisting>
870     SConscript('src/SConscript', 'lib/SConscript')
871   </programlisting>
872
873   <para>
874
875     By convention, configuration files in subdirectories are named
876     &SConscript;.
877
878   </para>
879
880   <para>
881
882     The &scons; script has intentionally been made to look, from
883     the outside, as much like &Make; as is practical. To this
884     end, the &scons; script supports all of the same command-line
885     options supported by GNU &Make;: <option>-f</option> FILE,
886     <option>-j</option>, <option>-k</option>, <option>-s</option>,
887     etc. For compatibility, &scons; ignores those GNU &Make; options
888     that don't make sense for the &SCons; architecture, such as
889     <option>-b</option>, <option>-m</option>, <option>-S</option>,
890     and <option>-t</option>.  The
891     intention is that, given an equivalent &SConstruct; file for a
892     &Makefile;, a user could use &SCons; as a drop-in replacement for
893     &Make;. Additional command-line options are, where possible, taken
894     from the Perl &Cons; utility on which the &SCons; design is based.
895
896   </para>
897
898 </section>