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