summaryrefslogtreecommitdiff
path: root/doc/user/less-simple.in
diff options
context:
space:
mode:
authorLuca Falavigna <dktrkranz@debian.org>2010-01-02 20:56:27 +0100
committerLuca Falavigna <dktrkranz@debian.org>2010-01-02 20:56:27 +0100
commit72c578fd4b0b4a5a43e18594339ac4ff26c376dc (patch)
treecadaf3abe37a1066ceae933bc8fe7b75c85f56d2 /doc/user/less-simple.in
parent548ed1064f327bccc6e538806740d41ea2d928a1 (diff)
Imported Upstream version 1.2.0.d20091224upstream/1.2.0.d20091224
Diffstat (limited to 'doc/user/less-simple.in')
-rw-r--r--doc/user/less-simple.in623
1 files changed, 623 insertions, 0 deletions
diff --git a/doc/user/less-simple.in b/doc/user/less-simple.in
new file mode 100644
index 0000000..e19ba13
--- /dev/null
+++ b/doc/user/less-simple.in
@@ -0,0 +1,623 @@
+<!--
+
+ Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be included
+ in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+ KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+-->
+
+ <para>
+
+ In this chapter,
+ you will see several examples of
+ very simple build configurations using &SCons;,
+ which will demonstrate how easy
+ it is to use &SCons; to
+ build programs from several different programming languages
+ on different types of systems.
+
+ </para>
+
+ <section>
+ <title>Specifying the Name of the Target (Output) File</title>
+
+ <para>
+
+ You've seen that when you call the &b-link-Program; builder method,
+ it builds the resulting program with the same
+ base name as the source file.
+ That is, the following call to build an
+ executable program from the &hello_c; source file
+ will build an executable program named &hello; on POSIX systems,
+ and an executable program named &hello_exe; on Windows systems:
+
+ </para>
+
+ <programlisting>
+ Program('hello.c')
+ </programlisting>
+
+ <para>
+
+ If you want to build a program with
+ a different name than the base of the source file name,
+ you simply put the target file name
+ to the left of the source file name:
+
+ </para>
+
+ <scons_example name="target">
+ <file name="SConstruct" printme="1">
+ Program('new_hello', 'hello.c')
+ </file>
+ <file name="hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ (&SCons; requires the target file name first,
+ followed by the source file name,
+ so that the order mimics that of an
+ assignment statement in most programming languages,
+ including Python:
+ <literal>"program = source files"</literal>.)
+
+ </para>
+
+ <para>
+
+ Now &SCons; will build an executable program
+ named &new_hello; when run on a POSIX system:
+
+ </para>
+
+ <scons_output example="target" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ And &SCons; will build an executable program
+ named &new_hello_exe; when run on a Windows system:
+
+ </para>
+
+ <scons_output example="target" os="win32">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Compiling Multiple Source Files</title>
+
+ <para>
+
+ You've just seen how to configure &SCons;
+ to compile a program from a single source file.
+ It's more common, of course,
+ that you'll need to build a program from
+ many input source files, not just one.
+ To do this, you need to put the
+ source files in a Python list
+ (enclosed in square brackets),
+ like so:
+
+ </para>
+
+ <scons_example name="ex2">
+ <file name="SConstruct" printme="1">
+ Program(['prog.c', 'file1.c', 'file2.c'])
+ </file>
+ <file name="prog.c">
+ int main() { printf("prog.c\n"); }
+ </file>
+ <file name="file1.c">
+ void file1() { printf("file1.c\n"); }
+ </file>
+ <file name="file2.c">
+ void file2() { printf("file2.c\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ A build of the above example would look like:
+
+ </para>
+
+ <scons_output example="ex2">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Notice that &SCons;
+ deduces the output program name
+ from the first source file specified
+ in the list--that is,
+ because the first source file was &prog_c;,
+ &SCons; will name the resulting program &prog;
+ (or &prog_exe; on a Windows system).
+ If you want to specify a different program name,
+ then (as we've seen in the previous section)
+ you slide the list of source files
+ over to the right
+ to make room for the output program file name.
+ (&SCons; puts the output file name to the left
+ of the source file names
+ so that the order mimics that of an
+ assignment statement: "program = source files".)
+ This makes our example:
+
+ </para>
+
+ <scons_example name="ex3">
+ <file name="SConstruct" printme="1">
+ Program('program', ['prog.c', 'file1.c', 'file2.c'])
+ </file>
+ <file name="prog.c">
+ int main() { printf("prog.c\n"); }
+ </file>
+ <file name="file1.c">
+ void file1() { printf("file1.c\n"); }
+ </file>
+ <file name="file2.c">
+ void file2() { printf("file2.c\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ On Linux, a build of this example would look like:
+
+ </para>
+
+ <scons_output example="ex3" os="posix">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Or on Windows:
+
+ </para>
+
+ <scons_output example="ex3" os="win32">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ </section>
+
+ <section>
+ <title>Making a list of files with &Glob;</title>
+
+ <para>
+
+ You can also use the &Glob; function to find all files matching a
+ certain template, using the standard shell pattern matching
+ characters <literal>*</literal>, <literal>?</literal>
+ and <literal>[abc]</literal> to match any of
+ <literal>a</literal>, <literal>b</literal> or <literal>c</literal>.
+ <literal>[!abc]</literal> is also supported,
+ to match any character <emphasis>except</emphasis>
+ <literal>a</literal>, <literal>b</literal> or <literal>c</literal>.
+ This makes many multi-source-file builds quite easy:
+
+ </para>
+
+ <sconstruct>
+ Program('program', Glob('*.c'))
+ </sconstruct>
+
+ <para>
+
+ The SCons man page has more details on using &Glob;
+ with variant directories
+ (see <xref linkend="chap-variants"></xref>, below)
+ and repositories
+ (see <xref linkend="chap-repositories"></xref>, below),
+ and returning strings rather than Nodes.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Specifying Single Files Vs. Lists of Files</title>
+
+ <para>
+
+ We've now shown you two ways to specify
+ the source for a program,
+ one with a list of files:
+
+ </para>
+
+ <sconstruct>
+ Program('hello', ['file1.c', 'file2.c'])
+ </sconstruct>
+
+ <para>
+
+ And one with a single file:
+
+ </para>
+
+ <sconstruct>
+ Program('hello', 'hello.c')
+ </sconstruct>
+
+ <para>
+
+ You could actually put a single file name in a list, too,
+ which you might prefer just for the sake of consistency:
+
+ </para>
+
+ <sconstruct>
+ Program('hello', ['hello.c'])
+ </sconstruct>
+
+ <para>
+
+ &SCons; functions will accept a single file name in either form.
+ In fact, internally, &SCons; treats all input as lists of files,
+ but allows you to omit the square brackets
+ to cut down a little on the typing
+ when there's only a single file name.
+
+ </para>
+
+ <important>
+
+ <para>
+
+ Although &SCons; functions
+ are forgiving about whether or not you
+ use a string vs. a list for a single file name,
+ Python itself is more strict about
+ treating lists and strings differently.
+ So where &SCons; allows either
+ a string or list:
+
+ </para>
+
+ <sconstruct>
+ # The following two calls both work correctly:
+ Program('program1', 'program1.c')
+ Program('program2', ['program2.c'])
+ </sconstruct>
+
+ <para>
+
+ Trying to do "Python things" that mix strings and
+ lists will cause errors or lead to incorrect results:
+
+ </para>
+
+ <sconstruct>
+ common_sources = ['file1.c', 'file2.c']
+
+ # THE FOLLOWING IS INCORRECT AND GENERATES A PYTHON ERROR
+ # BECAUSE IT TRIES TO ADD A STRING TO A LIST:
+ Program('program1', common_sources + 'program1.c')
+
+ # The following works correctly, because it's adding two
+ # lists together to make another list.
+ Program('program2', common_sources + ['program2.c'])
+ </sconstruct>
+
+ </important>
+
+ </section>
+
+ <section>
+ <title>Making Lists of Files Easier to Read</title>
+
+ <para>
+
+ One drawback to the use of a Python list
+ for source files is that
+ each file name must be enclosed in quotes
+ (either single quotes or double quotes).
+ This can get cumbersome and difficult to read
+ when the list of file names is long.
+ Fortunately, &SCons; and Python provide a number of ways
+ to make sure that
+ the &SConstruct; file stays easy to read.
+
+ </para>
+
+ <para>
+
+ To make long lists of file names
+ easier to deal with, &SCons; provides a
+ &Split; function
+ that takes a quoted list of file names,
+ with the names separated by spaces or other white-space characters,
+ and turns it into a list of separate file names.
+ Using the &Split; function turns the
+ previous example into:
+
+ </para>
+
+ <programlisting>
+ Program('program', Split('main.c file1.c file2.c'))
+ </programlisting>
+
+ <para>
+
+ (If you're already familiar with Python,
+ you'll have realized that this is similar to the
+ <function>split()</function> method
+ in the Python standard <function>string</function> module.
+ Unlike the <function>string.split()</function> method,
+ however, the &Split; function
+ does not require a string as input
+ and will wrap up a single non-string object in a list,
+ or return its argument untouched if it's already a list.
+ This comes in handy as a way to make sure
+ arbitrary values can be passed to &SCons; functions
+ without having to check the type of the variable by hand.)
+
+ </para>
+
+ <para>
+
+ Putting the call to the &Split; function
+ inside the &b-Program; call
+ can also be a little unwieldy.
+ A more readable alternative is to
+ assign the output from the &Split; call
+ to a variable name,
+ and then use the variable when calling the
+ &b-Program; function:
+
+ </para>
+
+ <programlisting>
+ src_files = Split('main.c file1.c file2.c')
+ Program('program', src_files)
+ </programlisting>
+
+ <para>
+
+ Lastly, the &Split; function
+ doesn't care how much white space separates
+ the file names in the quoted string.
+ This allows you to create lists of file
+ names that span multiple lines,
+ which often makes for easier editing:
+
+ </para>
+
+ <programlisting>
+ src_files = Split("""main.c
+ file1.c
+ file2.c""")
+ Program('program', src_files)
+ </programlisting>
+
+ <para>
+
+ (Note in this example that we used
+ the Python "triple-quote" syntax,
+ which allows a string to contain
+ multiple lines.
+ The three quotes can be either
+ single or double quotes.)
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Keyword Arguments</title>
+
+ <para>
+
+ &SCons; also allows you to identify
+ the output file and input source files
+ using Python keyword arguments.
+ The output file is known as the
+ <emphasis>target</emphasis>,
+ and the source file(s) are known (logically enough) as the
+ <emphasis>source</emphasis>.
+ The Python syntax for this is:
+
+ </para>
+
+ <programlisting>
+ src_files = Split('main.c file1.c file2.c')
+ Program(target = 'program', source = src_files)
+ </programlisting>
+
+ <para>
+
+ Because the keywords explicitly identify
+ what each argument is,
+ you can actually reverse the order if you prefer:
+
+ </para>
+
+ <programlisting>
+ src_files = Split('main.c file1.c file2.c')
+ Program(source = src_files, target = 'program')
+ </programlisting>
+
+ <para>
+
+ Whether or not you choose to use keyword arguments
+ to identify the target and source files,
+ and the order in which you specify them
+ when using keywords,
+ are purely personal choices;
+ &SCons; functions the same regardless.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Compiling Multiple Programs</title>
+
+ <para>
+
+ In order to compile multiple programs
+ within the same &SConstruct; file,
+ simply call the &Program; method
+ multiple times,
+ once for each program you need to build:
+
+ </para>
+
+ <scons_example name="ex4">
+ <file name="SConstruct" printme="1">
+ Program('foo.c')
+ Program('bar', ['bar1.c', 'bar2.c'])
+ </file>
+ <file name="foo.c">
+ int main() { printf("foo.c\n"); }
+ </file>
+ <file name="bar1.c">
+ int main() { printf("bar1.c\n"); }
+ </file>
+ <file name="bar2.c">
+ void bar2() { printf("bar2.c\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ &SCons; would then build the programs as follows:
+
+ </para>
+
+ <scons_output example="ex4">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ Notice that &SCons; does not necessarily build the
+ programs in the same order in which you specify
+ them in the &SConstruct; file.
+ &SCons; does, however, recognize that
+ the individual object files must be built
+ before the resulting program can be built.
+ We'll discuss this in greater detail in
+ the "Dependencies" section, below.
+
+ </para>
+
+ </section>
+
+ <section>
+ <title>Sharing Source Files Between Multiple Programs</title>
+
+ <para>
+
+ It's common to re-use code by sharing source files
+ between multiple programs.
+ One way to do this is to create a library
+ from the common source files,
+ which can then be linked into resulting programs.
+ (Creating libraries is discussed in
+ <xref linkend="chap-libraries"></xref>, below.)
+
+ </para>
+
+ <para>
+
+ A more straightforward, but perhaps less convenient,
+ way to share source files between multiple programs
+ is simply to include the common files
+ in the lists of source files for each program:
+
+ </para>
+
+ <scons_example name="ex5">
+ <file name="SConstruct" printme="1">
+ Program(Split('foo.c common1.c common2.c'))
+ Program('bar', Split('bar1.c bar2.c common1.c common2.c'))
+ </file>
+ <file name="foo.c">
+ int main() { printf("foo.c\n"); }
+ </file>
+ <file name="bar1.c">
+ int main() { printf("bar1.c\n"); }
+ </file>
+ <file name="bar2.c">
+ int bar2() { printf("bar2.c\n"); }
+ </file>
+ <file name="common1.c">
+ void common1() { printf("common1.c\n"); }
+ </file>
+ <file name="common2.c">
+ void common22() { printf("common2.c\n"); }
+ </file>
+ </scons_example>
+
+ <para>
+
+ &SCons; recognizes that the object files for
+ the &common1_c; and &common2_c; source files
+ each need to be built only once,
+ even though the resulting object files are
+ each linked in to both of the resulting executable programs:
+
+ </para>
+
+ <scons_output example="ex5">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ If two or more programs
+ share a lot of common source files,
+ repeating the common files in the list for each program
+ can be a maintenance problem when you need to change the
+ list of common files.
+ You can simplify this by creating a separate Python list
+ to hold the common file names,
+ and concatenating it with other lists
+ using the Python &plus; operator:
+
+ </para>
+
+ <programlisting>
+ common = ['common1.c', 'common2.c']
+ foo_files = ['foo.c'] + common
+ bar_files = ['bar1.c', 'bar2.c'] + common
+ Program('foo', foo_files)
+ Program('bar', bar_files)
+ </programlisting>
+
+ <para>
+
+ This is functionally equivalent to the previous example.
+
+ </para>
+
+ </section>