Accumulated documentation changes.
[scons.git] / doc / user / less-simple.in
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   In this chapter,
29   you will see several examples of
30   very simple build configurations using &SCons;,
31   which will demonstrate how easy
32   it is to use &SCons; to
33   build programs from several different programming languages
34   on different types of systems.
35
36   </para>
37
38   <section>
39   <title>Specifying the Name of the Target (Output) File</title>
40
41     <para>
42
43     You've seen that when you call the &b-link-Program; builder method,
44     it builds the resulting program with the same
45     base name as the source file.
46     That is, the following call to build an
47     executable program from the &hello_c; source file
48     will build an executable program named &hello; on POSIX systems,
49     and an executable program named &hello_exe; on Windows systems:
50
51     </para>
52
53     <programlisting>
54        Program('hello.c')
55     </programlisting>
56
57     <para>
58
59     If you want to build a program with
60     a different name than the base of the source file name,
61     you simply put the target file name
62     to the left of the source file name:
63
64     </para>
65
66     <scons_example name="target">
67        <file name="SConstruct" printme="1">
68        Program('new_hello', 'hello.c')
69        </file>
70        <file name="hello.c">
71        int main() { printf("Hello, world!\n"); }
72        </file>
73     </scons_example>
74
75     <para>
76
77     (&SCons; requires the target file name first,
78     followed by the source file name,
79     so that the order mimics that of an
80     assignment statement in most programming languages,
81     including Python:
82     <literal>"program = source files"</literal>.)
83
84     </para>
85
86     <para>
87
88     Now &SCons; will build an executable program
89     named &new_hello; when run on a POSIX system:
90
91     </para>
92
93     <scons_output example="target" os="posix">
94        <scons_output_command>scons -Q</scons_output_command>
95     </scons_output>
96
97     <para>
98
99     And &SCons; will build an executable program
100     named &new_hello_exe; when run on a Windows system:
101
102     </para>
103
104     <scons_output example="target" os="win32">
105        <scons_output_command>scons -Q</scons_output_command>
106     </scons_output>
107
108   </section>
109
110   <section>
111   <title>Compiling Multiple Source Files</title>
112
113     <para>
114
115     You've just seen how to configure &SCons;
116     to compile a program from a single source file.
117     It's more common, of course,
118     that you'll need to build a program from
119     many input source files, not just one.
120     To do this, you need to put the
121     source files in a Python list
122     (enclosed in square brackets),
123     like so:
124
125     </para>
126
127     <scons_example name="ex2">
128        <file name="SConstruct" printme="1">
129        Program(['main.c', 'file1.c', 'file2.c'])
130        </file>
131        <file name="main.c">
132        int main() { printf("main.c\n"); }
133        </file>
134        <file name="file1.c">
135        void file1() { printf("file1.c\n"); }
136        </file>
137        <file name="file2.c">
138        void file2() { printf("file2.c\n"); }
139        </file>
140     </scons_example>
141
142     <para>
143
144     A build of the above example would look like:
145
146     </para>
147
148     <scons_output example="ex2">
149        <scons_output_command>scons -Q</scons_output_command>
150     </scons_output>
151
152     <para>
153
154     Notice that &SCons;
155     deduces the output program name
156     from the first source file specified
157     in the list--that is,
158     because the first source file was &prog_c;,
159     &SCons; will name the resulting program &prog;
160     (or &prog_exe; on a Windows system).
161     If you want to specify a different program name,
162     then (as we've seen in the previous section)
163     you slide the list of source files
164     over to the right
165     to make room for the output program file name.
166     (&SCons; puts the output file name to the left
167     of the source file names
168     so that the order mimics that of an
169     assignment statement:  "program = source files".)
170     This makes our example:
171
172     </para>
173
174     <scons_example name="ex3">
175        <file name="SConstruct" printme="1">
176        Program('program', ['main.c', 'file1.c', 'file2.c'])
177        </file>
178        <file name="main.c">
179        int main() { printf("prog.c\n"); }
180        </file>
181        <file name="file1.c">
182        void file1() { printf("file1.c\n"); }
183        </file>
184        <file name="file2.c">
185        void file2() { printf("file2.c\n"); }
186        </file>
187     </scons_example>
188
189     <para>
190
191     On Linux, a build of this example would look like:
192
193     </para>
194
195     <scons_output example="ex3" os="posix">
196        <scons_output_command>scons -Q</scons_output_command>
197     </scons_output>
198
199     <para>
200
201     Or on Windows:
202
203     </para>
204
205     <scons_output example="ex3" os="win32">
206        <scons_output_command>scons -Q</scons_output_command>
207     </scons_output>
208
209   </section>
210
211   <section>
212   <title>Specifying Single Files Vs. Lists of Files</title>
213
214     <para>
215
216     We've now shown you two ways to specify
217     the source for a program,
218     one with a list of files:
219
220     </para>
221
222     <sconstruct>
223        Program('hello', ['file1.c', 'file2.c'])
224     </sconstruct>
225
226     <para>
227
228     And one with a single file:
229
230     </para>
231
232     <sconstruct>
233        Program('hello', 'hello.c')
234     </sconstruct>
235
236     <para>
237
238     You could actually put a single file name in a list, too,
239     which you might prefer just for the sake of consistency:
240
241     </para>
242
243     <sconstruct>
244        Program('hello', ['hello.c'])
245     </sconstruct>
246
247     <para>
248
249     &SCons; functions will accept a single file name in either form.
250     In fact, internally, &SCons; treats all input as lists of files,
251     but allows you to omit the square brackets
252     to cut down a little on the typing
253     when there's only a single file name.
254
255     </para>
256
257     <important>
258     
259     <para>
260
261     Although &SCons; functions
262     are forgiving about whether or not you
263     use a string vs. a list for a single file name,
264     Python itself is more strict about
265     treating lists and strings differently.
266     So where &SCons; allows either
267     a string or list:
268
269     </para>
270
271     <sconstruct>
272        # The following two calls both work correctly:
273        Program('program1', 'program1.c')
274        Program('program2', ['program2.c'])
275     </sconstruct>
276
277     <para>
278
279     Trying to do "Python things" that mix strings and
280     lists will cause errors or lead to incorrect results:
281
282     </para>
283
284     <sconstruct>
285        common_sources = ['file1.c', 'file2.c']
286
287        # THE FOLLOWING IS INCORRECT AND GENERATES A PYTHON ERROR
288        # BECAUSE IT TRIES TO ADD A STRING TO A LIST:
289        Program('program1', common_sources + 'program1.c')
290
291        # The following works correctly, because it's adding two
292        # lists together to make another list.
293        Program('program2', common_sources + ['program2.c'])
294     </sconstruct>
295
296     </important>
297
298   </section>
299
300   <section>
301   <title>Making Lists of Files Easier to Read</title>
302
303     <para>
304
305     One drawback to the use of a Python list
306     for source files is that 
307     each file name must be enclosed in quotes
308     (either single quotes or double quotes).
309     This can get cumbersome and difficult to read
310     when the list of file names is long.
311     Fortunately, &SCons; and Python provide a number of ways
312     to make sure that
313     the &SConstruct; file stays easy to read.
314
315     </para>
316
317     <para>
318
319     To make long lists of file names
320     easier to deal with, &SCons; provides a
321     &Split; function
322     that takes a quoted list of file names,
323     with the names separated by spaces or other white-space characters,
324     and turns it into a list of separate file names.
325     Using the &Split; function turns the
326     previous example into:
327
328     </para>
329
330     <programlisting>
331        Program('program', Split('main.c file1.c file2.c'))
332     </programlisting>
333
334     <para>
335
336     (If you're already familiar with Python,
337     you'll have realized that this is similar to the
338     <function>split()</function> method
339     in the Python standard <function>string</function> module.
340     Unlike the <function>string.split()</function> method,
341     however, the &Split; function
342     does not require a string as input
343     and will wrap up a single non-string object in a list,
344     or return its argument untouched if it's already a list.
345     This comes in handy as a way to make sure
346     arbitrary values can be passed to &SCons; functions
347     without having to check the type of the variable by hand.)
348
349     </para>
350
351     <para>
352
353     Putting the call to the &Split; function
354     inside the &b-Program; call
355     can also be a little unwieldy.
356     A more readable alternative is to
357     assign the output from the &Split; call
358     to a variable name,
359     and then use the variable when calling the
360     &b-Program; function:
361
362     </para>
363
364     <programlisting>
365        list = Split('main.c file1.c file2.c')
366        Program('program', list)
367     </programlisting>
368
369     <para>
370
371     Lastly, the &Split; function
372     doesn't care how much white space separates
373     the file names in the quoted string.
374     This allows you to create lists of file
375     names that span multiple lines,
376     which often makes for easier editing:
377
378     </para>
379
380     <programlisting>
381        list = Split("""main.c
382                        file1.c
383                        file2.c""")
384        Program('program', list)
385     </programlisting>
386
387     <para>
388
389     (Note in this example that we used
390     the Python "triple-quote" syntax,
391     which allows a string to contain
392     multiple lines.
393     The three quotes can be either
394     single or double quotes.)
395
396     </para>
397
398   </section>
399
400   <section>
401   <title>Keyword Arguments</title>
402
403     <para>
404
405     &SCons; also allows you to identify
406     the output file and input source files
407     using Python keyword arguments.
408     The output file is known as the
409     <emphasis>target</emphasis>,
410     and the source file(s) are known (logically enough) as the
411     <emphasis>source</emphasis>.
412     The Python syntax for this is:
413
414     </para>
415
416     <programlisting>
417        list = Split('main.c file1.c file2.c')
418        Program(target = 'program', source = list)
419     </programlisting>
420
421     <para>
422
423     Because the keywords explicitly identify
424     what each argument is,
425     you can actually reverse the order if you prefer:
426
427     </para>
428
429     <programlisting>
430        list = Split('main.c file1.c file2.c')
431        Program(source = list, target = 'program')
432     </programlisting>
433
434     <para>
435
436     Whether or not you choose to use keyword arguments
437     to identify the target and source files,
438     and the order in which you specify them
439     when using keywords,
440     are purely personal choices;
441     &SCons; functions the same regardless.
442
443     </para>
444
445   </section>
446
447   <section>
448   <title>Compiling Multiple Programs</title>
449
450     <para>
451
452     In order to compile multiple programs
453     within the same &SConstruct; file,
454     simply call the &Program; method
455     multiple times,
456     once for each program you need to build:
457
458     </para>
459
460     <scons_example name="ex4">
461        <file name="SConstruct" printme="1">
462        Program('foo.c')
463        Program('bar', ['bar1.c', 'bar2.c'])
464        </file>
465        <file name="foo.c">
466        int main() { printf("foo.c\n"); }
467        </file>
468        <file name="bar1.c">
469        int main() { printf("bar1.c\n"); }
470        </file>
471        <file name="bar2.c">
472        void bar2() { printf("bar2.c\n"); }
473        </file>
474     </scons_example>
475
476     <para>
477
478     &SCons; would then build the programs as follows:
479
480     </para>
481
482     <scons_output example="ex4">
483        <scons_output_command>scons -Q</scons_output_command>
484     </scons_output>
485
486     <para>
487
488     Notice that &SCons; does not necessarily build the
489     programs in the same order in which you specify
490     them in the &SConstruct; file.
491     &SCons; does, however, recognize that
492     the individual object files must be built
493     before the resulting program can be built.
494     We'll discuss this in greater detail in
495     the "Dependencies" section, below.
496
497     </para>
498
499   </section>
500
501   <section>
502   <title>Sharing Source Files Between Multiple Programs</title>
503
504     <para>
505
506     It's common to re-use code by sharing source files
507     between multiple programs.
508     One way to do this is to create a library
509     from the common source files,
510     which can then be linked into resulting programs.
511     (Creating libraries is discussed in
512     <xref linkend="chap-libraries">, below.)
513
514     </para>
515
516     <para>
517
518     A more straightforward, but perhaps less convenient,
519     way to share source files between multiple programs
520     is simply to include the common files
521     in the lists of source files for each program:
522
523     </para>
524
525     <scons_example name="ex5">
526        <file name="SConstruct" printme="1">
527        Program(Split('foo.c common1.c common2.c'))
528        Program('bar', Split('bar1.c bar2.c common1.c common2.c'))
529        </file>
530        <file name="foo.c">
531        int main() { printf("foo.c\n"); }
532        </file>
533        <file name="bar1.c">
534        int main() { printf("bar1.c\n"); }
535        </file>
536        <file name="bar2.c">
537        int bar2() { printf("bar2.c\n"); }
538        </file>
539        <file name="common1.c">
540        void common1() { printf("common1.c\n"); }
541        </file>
542        <file name="common2.c">
543        void common22() { printf("common2.c\n"); }
544        </file>
545     </scons_example>
546
547     <para>
548
549     &SCons; recognizes that the object files for
550     the &common1_c; and &common2_c; source files
551     each only need to be built once,
552     even though the resulting object files are
553     each linked in to both of the resulting executable programs:
554
555     </para>
556
557     <scons_output example="ex5">
558        <scons_output_command>scons -Q</scons_output_command>
559     </scons_output>
560
561     <para>
562
563     If two or more programs
564     share a lot of common source files,
565     repeating the common files in the list for each program
566     can be a maintenance problem when you need to change the
567     list of common files.
568     You can simplify this by creating a separate Python list
569     to hold the common file names,
570     and concatenating it with other lists
571     using the Python &plus; operator:
572
573     </para>
574
575     <programlisting>
576        common = ['common1.c', 'common2.c']
577        foo_files = ['foo.c'] + common
578        bar_files = ['bar1.c', 'bar2.c'] + common
579        Program('foo', foo_files)
580        Program('bar', bar_files)
581     </programlisting>
582
583     <para>
584
585     This is functionally equivalent to the previous example.
586
587     </para>
588
589   </section>