cf5931949c58510c7e7f07c7d675e5acc1196c2b
[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(['prog.c', 'file1.c', 'file2.c'])
130        </file>
131        <file name="prog.c">
132        int main() { printf("prog.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', ['prog.c', 'file1.c', 'file2.c'])
177        </file>
178        <file name="prog.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>Making a list of files with Glob()</title>
213
214     <para>
215
216     You can also use the Glob() function to find all files matching a
217     certain template, using standard the shell pattern matching
218     characters *, ?, and [abc] to match any of a, b, or c.  [!abc] is
219     also supported, to match any character <emphasis>except</emphasis>
220     a, b, or c.  This makes many multi-source-file builds quite easy:
221
222     </para>
223
224     <sconstruct>
225        Program('program', Glob('*.c'))
226     </sconstruct>
227
228     <para>
229
230     The SCons man page has more details on using Glob() with Variant
231     dirs and Repositories and returning strings rather than Nodes.
232
233     </para>
234
235   </section>
236
237   <section>
238   <title>Specifying Single Files Vs. Lists of Files</title>
239
240     <para>
241
242     We've now shown you two ways to specify
243     the source for a program,
244     one with a list of files:
245
246     </para>
247
248     <sconstruct>
249        Program('hello', ['file1.c', 'file2.c'])
250     </sconstruct>
251
252     <para>
253
254     And one with a single file:
255
256     </para>
257
258     <sconstruct>
259        Program('hello', 'hello.c')
260     </sconstruct>
261
262     <para>
263
264     You could actually put a single file name in a list, too,
265     which you might prefer just for the sake of consistency:
266
267     </para>
268
269     <sconstruct>
270        Program('hello', ['hello.c'])
271     </sconstruct>
272
273     <para>
274
275     &SCons; functions will accept a single file name in either form.
276     In fact, internally, &SCons; treats all input as lists of files,
277     but allows you to omit the square brackets
278     to cut down a little on the typing
279     when there's only a single file name.
280
281     </para>
282
283     <important>
284     
285     <para>
286
287     Although &SCons; functions
288     are forgiving about whether or not you
289     use a string vs. a list for a single file name,
290     Python itself is more strict about
291     treating lists and strings differently.
292     So where &SCons; allows either
293     a string or list:
294
295     </para>
296
297     <sconstruct>
298        # The following two calls both work correctly:
299        Program('program1', 'program1.c')
300        Program('program2', ['program2.c'])
301     </sconstruct>
302
303     <para>
304
305     Trying to do "Python things" that mix strings and
306     lists will cause errors or lead to incorrect results:
307
308     </para>
309
310     <sconstruct>
311        common_sources = ['file1.c', 'file2.c']
312
313        # THE FOLLOWING IS INCORRECT AND GENERATES A PYTHON ERROR
314        # BECAUSE IT TRIES TO ADD A STRING TO A LIST:
315        Program('program1', common_sources + 'program1.c')
316
317        # The following works correctly, because it's adding two
318        # lists together to make another list.
319        Program('program2', common_sources + ['program2.c'])
320     </sconstruct>
321
322     </important>
323
324   </section>
325
326   <section>
327   <title>Making Lists of Files Easier to Read</title>
328
329     <para>
330
331     One drawback to the use of a Python list
332     for source files is that 
333     each file name must be enclosed in quotes
334     (either single quotes or double quotes).
335     This can get cumbersome and difficult to read
336     when the list of file names is long.
337     Fortunately, &SCons; and Python provide a number of ways
338     to make sure that
339     the &SConstruct; file stays easy to read.
340
341     </para>
342
343     <para>
344
345     To make long lists of file names
346     easier to deal with, &SCons; provides a
347     &Split; function
348     that takes a quoted list of file names,
349     with the names separated by spaces or other white-space characters,
350     and turns it into a list of separate file names.
351     Using the &Split; function turns the
352     previous example into:
353
354     </para>
355
356     <programlisting>
357        Program('program', Split('main.c file1.c file2.c'))
358     </programlisting>
359
360     <para>
361
362     (If you're already familiar with Python,
363     you'll have realized that this is similar to the
364     <function>split()</function> method
365     in the Python standard <function>string</function> module.
366     Unlike the <function>string.split()</function> method,
367     however, the &Split; function
368     does not require a string as input
369     and will wrap up a single non-string object in a list,
370     or return its argument untouched if it's already a list.
371     This comes in handy as a way to make sure
372     arbitrary values can be passed to &SCons; functions
373     without having to check the type of the variable by hand.)
374
375     </para>
376
377     <para>
378
379     Putting the call to the &Split; function
380     inside the &b-Program; call
381     can also be a little unwieldy.
382     A more readable alternative is to
383     assign the output from the &Split; call
384     to a variable name,
385     and then use the variable when calling the
386     &b-Program; function:
387
388     </para>
389
390     <programlisting>
391        list = Split('main.c file1.c file2.c')
392        Program('program', list)
393     </programlisting>
394
395     <para>
396
397     Lastly, the &Split; function
398     doesn't care how much white space separates
399     the file names in the quoted string.
400     This allows you to create lists of file
401     names that span multiple lines,
402     which often makes for easier editing:
403
404     </para>
405
406     <programlisting>
407        list = Split("""main.c
408                        file1.c
409                        file2.c""")
410        Program('program', list)
411     </programlisting>
412
413     <para>
414
415     (Note in this example that we used
416     the Python "triple-quote" syntax,
417     which allows a string to contain
418     multiple lines.
419     The three quotes can be either
420     single or double quotes.)
421
422     </para>
423
424   </section>
425
426   <section>
427   <title>Keyword Arguments</title>
428
429     <para>
430
431     &SCons; also allows you to identify
432     the output file and input source files
433     using Python keyword arguments.
434     The output file is known as the
435     <emphasis>target</emphasis>,
436     and the source file(s) are known (logically enough) as the
437     <emphasis>source</emphasis>.
438     The Python syntax for this is:
439
440     </para>
441
442     <programlisting>
443        list = Split('main.c file1.c file2.c')
444        Program(target = 'program', source = list)
445     </programlisting>
446
447     <para>
448
449     Because the keywords explicitly identify
450     what each argument is,
451     you can actually reverse the order if you prefer:
452
453     </para>
454
455     <programlisting>
456        list = Split('main.c file1.c file2.c')
457        Program(source = list, target = 'program')
458     </programlisting>
459
460     <para>
461
462     Whether or not you choose to use keyword arguments
463     to identify the target and source files,
464     and the order in which you specify them
465     when using keywords,
466     are purely personal choices;
467     &SCons; functions the same regardless.
468
469     </para>
470
471   </section>
472
473   <section>
474   <title>Compiling Multiple Programs</title>
475
476     <para>
477
478     In order to compile multiple programs
479     within the same &SConstruct; file,
480     simply call the &Program; method
481     multiple times,
482     once for each program you need to build:
483
484     </para>
485
486     <scons_example name="ex4">
487        <file name="SConstruct" printme="1">
488        Program('foo.c')
489        Program('bar', ['bar1.c', 'bar2.c'])
490        </file>
491        <file name="foo.c">
492        int main() { printf("foo.c\n"); }
493        </file>
494        <file name="bar1.c">
495        int main() { printf("bar1.c\n"); }
496        </file>
497        <file name="bar2.c">
498        void bar2() { printf("bar2.c\n"); }
499        </file>
500     </scons_example>
501
502     <para>
503
504     &SCons; would then build the programs as follows:
505
506     </para>
507
508     <scons_output example="ex4">
509        <scons_output_command>scons -Q</scons_output_command>
510     </scons_output>
511
512     <para>
513
514     Notice that &SCons; does not necessarily build the
515     programs in the same order in which you specify
516     them in the &SConstruct; file.
517     &SCons; does, however, recognize that
518     the individual object files must be built
519     before the resulting program can be built.
520     We'll discuss this in greater detail in
521     the "Dependencies" section, below.
522
523     </para>
524
525   </section>
526
527   <section>
528   <title>Sharing Source Files Between Multiple Programs</title>
529
530     <para>
531
532     It's common to re-use code by sharing source files
533     between multiple programs.
534     One way to do this is to create a library
535     from the common source files,
536     which can then be linked into resulting programs.
537     (Creating libraries is discussed in
538     <xref linkend="chap-libraries"></xref>, below.)
539
540     </para>
541
542     <para>
543
544     A more straightforward, but perhaps less convenient,
545     way to share source files between multiple programs
546     is simply to include the common files
547     in the lists of source files for each program:
548
549     </para>
550
551     <scons_example name="ex5">
552        <file name="SConstruct" printme="1">
553        Program(Split('foo.c common1.c common2.c'))
554        Program('bar', Split('bar1.c bar2.c common1.c common2.c'))
555        </file>
556        <file name="foo.c">
557        int main() { printf("foo.c\n"); }
558        </file>
559        <file name="bar1.c">
560        int main() { printf("bar1.c\n"); }
561        </file>
562        <file name="bar2.c">
563        int bar2() { printf("bar2.c\n"); }
564        </file>
565        <file name="common1.c">
566        void common1() { printf("common1.c\n"); }
567        </file>
568        <file name="common2.c">
569        void common22() { printf("common2.c\n"); }
570        </file>
571     </scons_example>
572
573     <para>
574
575     &SCons; recognizes that the object files for
576     the &common1_c; and &common2_c; source files
577     each only need to be built once,
578     even though the resulting object files are
579     each linked in to both of the resulting executable programs:
580
581     </para>
582
583     <scons_output example="ex5">
584        <scons_output_command>scons -Q</scons_output_command>
585     </scons_output>
586
587     <para>
588
589     If two or more programs
590     share a lot of common source files,
591     repeating the common files in the list for each program
592     can be a maintenance problem when you need to change the
593     list of common files.
594     You can simplify this by creating a separate Python list
595     to hold the common file names,
596     and concatenating it with other lists
597     using the Python &plus; operator:
598
599     </para>
600
601     <programlisting>
602        common = ['common1.c', 'common2.c']
603        foo_files = ['foo.c'] + common
604        bar_files = ['bar1.c', 'bar2.c'] + common
605        Program('foo', foo_files)
606        Program('bar', bar_files)
607     </programlisting>
608
609     <para>
610
611     This is functionally equivalent to the previous example.
612
613     </para>
614
615   </section>