[ci skip] update generated files
[scons.git] / doc / user / less-simple.xml
blob19dab6f13cc5bc7cb07f542405853693a402d73c
1 <?xml version='1.0'?>
3 <!--
4 SPDX-FileCopyrightText: Copyright The SCons Foundation (https://scons.org)
5 SPDX-License-Identifier: MIT
6 SPDX-FileType: DOCUMENTATION
8 This file is processed by the bin/SConsDoc.py module.
9 -->
11 <!DOCTYPE sconsdoc [
12     <!ENTITY % scons SYSTEM "../scons.mod">
13     %scons;
15     <!ENTITY % builders-mod SYSTEM "../generated/builders.mod">
16     %builders-mod;
17     <!ENTITY % functions-mod SYSTEM "../generated/functions.mod">
18     %functions-mod;
19     <!ENTITY % tools-mod SYSTEM "../generated/tools.mod">
20     %tools-mod;
21     <!ENTITY % variables-mod SYSTEM "../generated/variables.mod">
22     %variables-mod;
25 <chapter id="chap-less-simple"
26          xmlns="http://www.scons.org/dbxsd/v1.0"
27          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
28          xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">
30 <title>Less Simple Things to Do With Builds</title>
32   <para>
34   Of course, most builds are more complicated than in the previous chapter.
35   In this chapter,
36   you will learn about builds that incorporate multiple source files,
37   and then about building multiple targets that share some source files.
39   </para>
41   <section id="sect-target-name">
42   <title>Specifying the Name of the Target (Output) File</title>
44     <para>
46     You've seen that when you call the &b-link-Program; builder method,
47     it builds the resulting program with the same
48     base name as the source file.
49     That is, the following call to build an
50     executable program from the &hello_c; source file
51     will build an executable program named &hello; on POSIX systems,
52     and an executable program named &hello_exe; on Windows systems:
54     </para>
56     <sconstruct>
57 Program('hello.c')
58     </sconstruct>
60     <para>
62     If you want to build a program with
63     a different base name than the base of the source file name
64     (or even the same name),
65     you simply put the target file name
66     to the left of the source file name:
68     </para>
70     <scons_example name="lesssimple_target">
71        <file name="SConstruct" printme="1">
72 Program('new_hello', 'hello.c')
73        </file>
74        <file name="hello.c">
75 int main() { printf("Hello, world!\n"); }
76        </file>
77     </scons_example>
79     <para>
81     &SCons; requires the target file name first,
82     followed by the source file name,
83     so that the order mimics that of an
84     assignment statement in most programming languages,
85     including &Python;:
86     <literal>"target = source files"</literal>. For an
87     alternative way to supply this information, see
88     <xref linkend="sect-keyword-args"></xref>.
90     </para>
92     <para>
94     Now &SCons; will build an executable program
95     named &new_hello; when run on a POSIX system:
97     </para>
99     <scons_output example="lesssimple_target" os="posix" suffix="1">
100        <scons_output_command>scons -Q</scons_output_command>
101     </scons_output>
103     <para>
105     And &SCons; will build an executable program
106     named &new_hello_exe; when run on a Windows system:
108     </para>
110     <scons_output example="lesssimple_target" os="win32" suffix="2">
111        <scons_output_command>scons -Q</scons_output_command>
112     </scons_output>
114   </section>
116   <section id="sect-multi-source">
117   <title>Compiling Multiple Source Files</title>
119     <para>
121     You've just seen how to configure &SCons;
122     to compile a program from a single source file.
123     It's more common, of course,
124     that you'll need to build a program from
125     many input source files, not just one.
126     To do this, you need to put the
127     source files in a &Python; list
128     (enclosed in square brackets),
129     like so:
131     </para>
133     <scons_example name="lesssimple_ex2">
134        <file name="SConstruct" printme="1">
135 Program(['prog.c', 'file1.c', 'file2.c'])
136        </file>
137        <file name="prog.c">
138 int main() { printf("prog.c\n"); }
139        </file>
140        <file name="file1.c">
141 void file1() { printf("file1.c\n"); }
142        </file>
143        <file name="file2.c">
144 void file2() { printf("file2.c\n"); }
145        </file>
146     </scons_example>
148     <para>
150     A build of the above example would look like:
152     </para>
154     <scons_output example="lesssimple_ex2" suffix="1">
155        <scons_output_command>scons -Q</scons_output_command>
156     </scons_output>
158     <para>
160     Notice that &SCons;
161     deduces the output program name
162     from the first source file specified
163     in the list--that is,
164     because the first source file was &prog_c;,
165     &SCons; will name the resulting program &prog;
166     (or &prog_exe; on a Windows system).
167     If you want to specify a different program name,
168     then (as described in the previous section)
169     you slide the list of source files
170     over to the right
171     to make room for the output program file name.
172     Here is the updated example:
174     </para>
176     <scons_example name="lesssimple_ex3">
177        <file name="SConstruct" printme="1">
178 Program('program', ['prog.c', 'file1.c', 'file2.c'])
179        </file>
180        <file name="prog.c">
181 int main() { printf("prog.c\n"); }
182        </file>
183        <file name="file1.c">
184 void file1() { printf("file1.c\n"); }
185        </file>
186        <file name="file2.c">
187 void file2() { printf("file2.c\n"); }
188        </file>
189     </scons_example>
191     <para>
193     On Linux, a build of this example would look like:
195     </para>
197     <scons_output example="lesssimple_ex3" os="posix" suffix="1">
198        <scons_output_command>scons -Q</scons_output_command>
199     </scons_output>
201     <para>
203     Or on Windows:
205     </para>
207     <scons_output example="lesssimple_ex3" os="win32" suffix="2">
208        <scons_output_command>scons -Q</scons_output_command>
209     </scons_output>
211   </section>
213   <section id="sect-glob-source">
214   <title>Making a list of files with &Glob;</title>
216     <para>
218     You can also use the &f-link-Glob; function to find all files matching a
219     certain template, using the standard shell pattern matching
220     characters <literal>*</literal> (to match everything),
221     <literal>?</literal> (to match a single character)
222     and <literal>[abc]</literal> to match any of
223     <literal>a</literal>, <literal>b</literal> or <literal>c</literal>.
224     <literal>[!abc]</literal> is also supported,
225     to match any character <emphasis>except</emphasis>
226     <literal>a</literal>, <literal>b</literal> or <literal>c</literal>.
227     This makes many multi-source-file builds quite easy:
229     </para>
231     <sconstruct>
232 Program('program', Glob('*.c'))
233     </sconstruct>
235     <para>
237     &f-Glob; has powerful capabilities - it matches even if the
238     file does not currently exist,
239     but &SCons; can determine that it would
240     exist after a build.
241     You will meet it again reading about
242     variant directories
243     (see <xref linkend="chap-separate"/>)
244     and repositories
245     (see <xref linkend="chap-repositories"/>).
247     </para>
249   </section>
251   <section id="sect-single-list">
252   <title>Specifying Single Files Vs. Lists of Files</title>
254     <para>
256     You've now seen two ways to specify
257     the source for a program,
258     one with a list of files:
260     </para>
262     <sconstruct>
263 Program('hello', ['file1.c', 'file2.c'])
264     </sconstruct>
266     <para>
268     And one with a single file:
270     </para>
272     <sconstruct>
273 Program('hello', 'hello.c')
274     </sconstruct>
276     <para>
278     You can actually put a single file name in a list, too,
279     which you might prefer just for the sake of consistency:
281     </para>
283     <sconstruct>
284 Program('hello', ['hello.c'])
285     </sconstruct>
287     <para>
289     &SCons; functions will accept a single file name in either form.
290     In fact, internally, &SCons; treats all input as lists of files,
291     but allows you to omit the square brackets
292     to cut down a little on the typing
293     when there's only a single file name.
295     </para>
297     <important>
299     <para>
301     Although &SCons; functions
302     are forgiving about whether or not you
303     use a string vs. a list for a single file name,
304     &Python; itself is stricter about
305     treating lists and strings differently.
306     So where &SCons; allows either
307     a string or list:
309     </para>
311     <sconstruct>
312 # The following two calls both work correctly:
313 Program('program1', 'program1.c')
314 Program('program2', ['program2.c'])
315     </sconstruct>
317     <para>
319     Trying to do "&Python; things" that mix strings and
320     lists will cause errors or lead to incorrect results:
322     </para>
324     <sconstruct>
325 common_sources = ['file1.c', 'file2.c']
327 # THE FOLLOWING IS INCORRECT AND GENERATES A PYTHON ERROR
328 # BECAUSE IT TRIES TO ADD A STRING TO A LIST:
329 Program('program1', common_sources + 'program1.c')
331 # The following works correctly, because it's adding two
332 # lists together to make another list.
333 Program('program2', common_sources + ['program2.c'])
334     </sconstruct>
336     </important>
338   </section>
340   <section id="sect-source-split">
341   <title>Making Lists of Files Easier to Read</title>
343     <para>
345     One drawback to the use of a &Python; list
346     for source files is that
347     each file name must be enclosed in quotes
348     (either single quotes or double quotes).
349     This can get cumbersome and difficult to read
350     when the list of file names is long.
351     Fortunately, &SCons; and &Python; provide a number of ways
352     to make sure that
353     the &SConstruct; file stays easy to read.
355     </para>
357     <para>
359     To make long lists of file names
360     easier to deal with, &SCons; provides a
361     &f-link-Split; function
362     that takes a quoted list of file names,
363     with the names separated by spaces or other white-space characters,
364     and turns it into a list of separate file names.
365     Using the &Split; function turns the
366     previous example into:
368     </para>
370     <sconstruct>
371 Program('program', Split('main.c file1.c file2.c'))
372     </sconstruct>
374     <para>
376     (If you're already familiar with &Python;,
377     you'll have realized that this is similar to the
378     <function>split()</function> method
379     of &Python; string objects.
380     Unlike the <function>split()</function> method,
381     however, the &Split; function
382     does not require a string as input
383     and will wrap up a single non-string object in a list,
384     or return its argument untouched if it's already a list.
385     This comes in handy as a way to make sure
386     arbitrary values can be passed to &SCons; functions
387     without having to check the type of the variable by hand.)
389     </para>
391     <para>
393     Putting the call to the &Split; function
394     inside the &b-Program; call
395     can also be a little unwieldy.
396     A more readable alternative is to
397     assign the output from the &Split; call
398     to a variable name,
399     and then use the variable when calling the
400     &b-Program; function:
402     </para>
404     <sconstruct>
405 src_files = Split('main.c file1.c file2.c')
406 Program('program', src_files)
407     </sconstruct>
409     <para>
411     Lastly, the &Split; function
412     doesn't care how much white space separates
413     the file names in the quoted string.
414     This allows you to create lists of file
415     names that span multiple lines,
416     which often makes for easier editing:
418     </para>
420     <sconstruct>
421 src_files = Split("""
422     main.c
423     file1.c
424     file2.c
425 """)
426 Program('program', src_files)
427     </sconstruct>
429     <para>
431     (Note this example uses
432     the &Python; "triple-quote" syntax,
433     which allows a string to span multiple lines.
434     The three quotes can be either
435     single or double quotes as long as they match.)
437     </para>
439   </section>
441   <section id="sect-keyword-args">
442   <title>Keyword Arguments</title>
444     <para>
446     &SCons; also allows you to identify
447     the output file and input source files
448     using &Python; <firstterm>keyword arguments</firstterm>
449     <parameter>target</parameter> and
450     <parameter>source</parameter>.
451     A keyword argument is an argument preceded by an identifier,
452     of the form <literal>name=value</literal>, in a function call.
453     The usage looks like this example:
455     </para>
457     <sconstruct>
458 src_files = Split('main.c file1.c file2.c')
459 Program(target='program', source=src_files)
460     </sconstruct>
462     <para>
464     Because the keywords explicitly identify
465     what each argument is, the order does
466     not matter and you can reverse it if you prefer:
468     </para>
470     <sconstruct>
471 src_files = Split('main.c file1.c file2.c')
472 Program(source=src_files, target='program')
473     </sconstruct>
475     <para>
477     Whether or not you choose to use keyword arguments
478     to identify the target and source files,
479     and the order in which you specify them
480     when using keywords,
481     are purely personal choices;
482     &SCons; functions the same regardless.
484     </para>
486   </section>
488   <section id="sect-multi-targets">
489   <title>Compiling Multiple Programs</title>
491     <para>
493     In order to compile multiple programs
494     within the same &SConstruct; file,
495     simply call the &Program; method
496     multiple times,
497     once for each program you need to build:
499     </para>
501     <scons_example name="lesssimple_ex4">
502        <file name="SConstruct" printme="1">
503 Program('foo.c')
504 Program('bar', ['bar1.c', 'bar2.c'])
505        </file>
506        <file name="foo.c">
507 int main() { printf("foo.c\n"); }
508        </file>
509        <file name="bar1.c">
510 int main() { printf("bar1.c\n"); }
511        </file>
512        <file name="bar2.c">
513 void bar2() { printf("bar2.c\n"); }
514        </file>
515     </scons_example>
517     <para>
519     &SCons; would then build the programs as follows:
521     </para>
523     <scons_output example="lesssimple_ex4" suffix="1">
524        <scons_output_command>scons -Q</scons_output_command>
525     </scons_output>
527     <para>
529     Notice that &SCons; does not necessarily build the
530     programs in the same order in which you specify
531     them in the &SConstruct; file.
532     &SCons; does, however, recognize that
533     the individual object files must be built
534     before the resulting program can be built.
535     (This will be covered in greater detail in
536     <xref linkend="chap-depends"/>, below.)
538     </para>
540   </section>
542   <section id="sect-sharing-sources">
543   <title>Sharing Source Files Between Multiple Programs</title>
545     <para>
547     It's common to re-use code by sharing source files
548     between multiple programs.
549     One way to do this is to create a library
550     from the common source files,
551     which can then be linked into resulting programs.
552     (Creating libraries is discussed in
553     <xref linkend="chap-libraries"></xref>, below.)
555     </para>
557     <para>
559     A more straightforward, but perhaps less convenient,
560     way to share source files between multiple programs
561     is simply to include the common files
562     in the lists of source files for each program:
564     </para>
566     <scons_example name="lesssimple_ex5">
567        <file name="SConstruct" printme="1">
568 Program(Split('foo.c common1.c common2.c'))
569 Program('bar', Split('bar1.c bar2.c common1.c common2.c'))
570        </file>
571        <file name="foo.c">
572 int main() { printf("foo.c\n"); }
573        </file>
574        <file name="bar1.c">
575 int main() { printf("bar1.c\n"); }
576        </file>
577        <file name="bar2.c">
578 int bar2() { printf("bar2.c\n"); }
579        </file>
580        <file name="common1.c">
581 void common1() { printf("common1.c\n"); }
582        </file>
583        <file name="common2.c">
584 void common22() { printf("common2.c\n"); }
585        </file>
586     </scons_example>
588     <para>
590     &SCons; recognizes that the object files for
591     the &common1_c; and &common2_c; source files
592     each need to be built only once,
593     even though the resulting object files are
594     each linked in to both of the resulting executable programs:
596     </para>
598     <scons_output example="lesssimple_ex5" suffix="1">
599        <scons_output_command>scons -Q</scons_output_command>
600     </scons_output>
602     <para>
604     If two or more programs
605     share a lot of common source files,
606     repeating the common files in the list for each program
607     can be a maintenance problem when you need to change the
608     list of common files.
609     You can simplify this by creating a separate &Python; list
610     to hold the common file names,
611     and concatenating it with other lists
612     using the &Python; &plus; operator:
614     </para>
616     <sconstruct>
617 common = ['common1.c', 'common2.c']
618 foo_files = ['foo.c'] + common
619 bar_files = ['bar1.c', 'bar2.c'] + common
620 Program('foo', foo_files)
621 Program('bar', bar_files)
622     </sconstruct>
624     <para>
626     This is functionally equivalent to the previous example.
628     </para>
630   </section>
632 </chapter>