diff options
Diffstat (limited to 'doc/user/less-simple.xml')
-rw-r--r-- | doc/user/less-simple.xml | 608 |
1 files changed, 608 insertions, 0 deletions
diff --git a/doc/user/less-simple.xml b/doc/user/less-simple.xml new file mode 100644 index 0000000..57c61e2 --- /dev/null +++ b/doc/user/less-simple.xml @@ -0,0 +1,608 @@ +<!-- + + 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> + + <programlisting> + Program('new_hello', 'hello.c') + </programlisting> + + <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> + + <screen> + % <userinput>scons -Q</userinput> + cc -o hello.o -c hello.c + cc -o new_hello hello.o + </screen> + + <para> + + And &SCons; will build an executable program + named &new_hello_exe; when run on a Windows system: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + cl /Fohello.obj /c hello.c /nologo + link /nologo /OUT:new_hello.exe hello.obj + </screen> + + </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> + + <programlisting> + Program(['prog.c', 'file1.c', 'file2.c']) + </programlisting> + + <para> + + A build of the above example would look like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o file1.o -c file1.c + cc -o file2.o -c file2.c + cc -o prog.o -c prog.c + cc -o prog prog.o file1.o file2.o + </screen> + + <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> + + <programlisting> + Program('program', ['prog.c', 'file1.c', 'file2.c']) + </programlisting> + + <para> + + On Linux, a build of this example would look like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o file1.o -c file1.c + cc -o file2.o -c file2.c + cc -o prog.o -c prog.c + cc -o program prog.o file1.o file2.o + </screen> + + <para> + + Or on Windows: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + + scons: warning: No installed VCs + File "<stdin>", line 67, in __call__ + + scons: warning: No version of Visual Studio compiler found - C/C++ compilers most likely not set correctly + File "<stdin>", line 67, in __call__ + cl /Fofile1.obj /c file1.c /nologo + cl /Fofile2.obj /c file2.c /nologo + cl /Foprog.obj /c prog.c /nologo + link /nologo /OUT:program.exe prog.obj file1.obj file2.obj + </screen> + + </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> + + <programlisting> + Program('program', Glob('*.c')) + </programlisting> + + <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> + + <programlisting> + Program('hello', ['file1.c', 'file2.c']) + </programlisting> + + <para> + + And one with a single file: + + </para> + + <programlisting> + Program('hello', 'hello.c') + </programlisting> + + <para> + + You could actually put a single file name in a list, too, + which you might prefer just for the sake of consistency: + + </para> + + <programlisting> + Program('hello', ['hello.c']) + </programlisting> + + <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> + + <programlisting> + # The following two calls both work correctly: + Program('program1', 'program1.c') + Program('program2', ['program2.c']) + </programlisting> + + <para> + + Trying to do "Python things" that mix strings and + lists will cause errors or lead to incorrect results: + + </para> + + <programlisting> + 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']) + </programlisting> + + </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> + + <programlisting> + Program('foo.c') + Program('bar', ['bar1.c', 'bar2.c']) + </programlisting> + + <para> + + &SCons; would then build the programs as follows: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -o bar1.o -c bar1.c + cc -o bar2.o -c bar2.c + cc -o bar bar1.o bar2.o + cc -o foo.o -c foo.c + cc -o foo foo.o + </screen> + + <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> + + <programlisting> + Program(Split('foo.c common1.c common2.c')) + Program('bar', Split('bar1.c bar2.c common1.c common2.c')) + </programlisting> + + <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> + + <screen> + % <userinput>scons -Q</userinput> + cc -o bar1.o -c bar1.c + cc -o bar2.o -c bar2.c + cc -o common1.o -c common1.c + cc -o common2.o -c common2.c + cc -o bar bar1.o bar2.o common1.o common2.o + cc -o foo.o -c foo.c + cc -o foo foo.o common1.o common2.o + </screen> + + <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 + 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> |