diff options
Diffstat (limited to 'doc/user/simple.sgml')
-rw-r--r-- | doc/user/simple.sgml | 826 |
1 files changed, 361 insertions, 465 deletions
diff --git a/doc/user/simple.sgml b/doc/user/simple.sgml index 4309837..b925d04 100644 --- a/doc/user/simple.sgml +++ b/doc/user/simple.sgml @@ -1,6 +1,6 @@ <!-- - Copyright (c) 2001, 2002, 2003 Steven Knight + __COPYRIGHT__ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -25,118 +25,68 @@ <para> - Here's the famous "Hello, World!" program in C: + 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> - <programlisting> - int - main() - { - printf("Hello, world!\n"); - } - </programlisting> - - <para> - - And here's how to build it using &SCons;. - Enter the following into a file named &SConstruct;: - - </para> - - <programlisting> - Program('hello.c') - </programlisting> - - <para> - - That's it. Now run the &scons; command to build the program. - On a POSIX-compliant system like Linux or UNIX, - you'll see something like: - - </para> - - <literallayout> - % <userinput>scons</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - cc -c -o hello.o hello.c - cc -o hello hello.o - scons: done building targets. - </literallayout> - - <para> - - On a Windows system with the Microsoft Visual C++ compiler, - you'll see something like: - - </para> + <section> + <title>Building Simple C / C++ Programs</title> - <literallayout> - C:\><userinput>scons</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Building targets ... - cl /nologo /c hello.c /Fohello.obj - link /nologo /OUT:hello.exe hello.obj - scons: done building targets. - </literallayout> + <para> - <para> + Here's the famous "Hello, World!" program in C: - First, notice that you only need - to specify the name of the source file, - and that &SCons; deduces the names of - the object and executable files - correctly from the base of the source file name. + </para> - </para> + <programlisting> + int + main() + { + printf("Hello, world!\n"); + } + </programlisting> - <para> + <para> - Second, notice that the same input &SConstruct; file, - without any changes, - generates the correct output file names on both systems: - <filename>hello.o</filename> and <filename>hello</filename> - on POSIX systems, - <filename>hello.obj</filename> and <filename>hello.exe</filename> - on Windows systems. - This is a simple example of how &SCons; - makes it extremely easy to - write portable software builds. + And here's how to build it using &SCons;. + Enter the following into a file named &SConstruct;: - </para> + </para> - <para> + <programlisting> + Program('hello.c') + </programlisting> - (Note that we won't provide duplicate side-by-side - POSIX and Windows output for all of the examples in this guide; - just keep in mind that, unless otherwise specified, - any of the examples should work equally well on both types of systems.) + <para> - </para> + This minimal configuration file gives + &SCons; two pieces of information: + what you want to build + (an executable program), + and the input file from + which you want it built + (the <filename>hello.c</filename> file). + &Program; is a &builder_method;, + a Python call that tells &SCons; that you want to build an + executable program. - <section> - <title>Cleaning Up After a Build</title> + </para> <para> - When using &SCons;, it is unnecessary to add special - commands or target names to clean up after a build. - Instead, you simply use the - <literal>-c</literal> or <literal>--clean</literal> - option when you invoke &SCons;, - and &SCons; removes the appropriate built files. - So if we build our example above - and then invoke <literal>scons -c</literal> - afterwards, the output on POSIX looks like: + That's it. Now run the &scons; command to build the program. + On a POSIX-compliant system like Linux or UNIX, + you'll see something like: </para> - - - <literallayout> + <screen> % <userinput>scons</userinput> scons: Reading SConscript files ... scons: done reading SConscript files. @@ -144,22 +94,16 @@ cc -c -o hello.o hello.c cc -o hello hello.o scons: done building targets. - % <userinput>scons -c</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Cleaning targets ... - Removed hello.o - Removed hello - scons: done cleaning targets. - </literallayout> + </screen> <para> - And the output on Windows looks like: + On a Windows system with the Microsoft Visual C++ compiler, + you'll see something like: </para> - <literallayout> + <screen> C:\><userinput>scons</userinput> scons: Reading SConscript files ... scons: done reading SConscript files. @@ -167,488 +111,440 @@ cl /nologo /c hello.c /Fohello.obj link /nologo /OUT:hello.exe hello.obj scons: done building targets. - C:\><userinput>scons -c</userinput> - scons: Reading SConscript files ... - scons: done reading SConscript files. - scons: Cleaning targets ... - Removed hello.obj - Removed hello.exe - scons: done cleaning targets. - </literallayout> + </screen> <para> - Notice that &SCons; changes its output to tell you that it - is <literal>Cleaning targets ...</literal> and - <literal>done cleaning targets.</literal> + First, notice that you only need + to specify the name of the source file, + and that &SCons; correctly deduces the names of + the object and executable files to be built + from the base of the source file name. </para> - </section> - - <section> - <title>The &SConstruct; File</title> - <para> - If you're used to build systems like &Make; - you've already figured out that the &SConstruct; file - is the &SCons; equivalent of a &Makefile;. - That is, the &SConstruct; file is the input file - that &SCons; reads to control the build. + Second, notice that the same input &SConstruct; file, + without any changes, + generates the correct output file names on both systems: + <filename>hello.o</filename> and <filename>hello</filename> + on POSIX systems, + <filename>hello.obj</filename> and <filename>hello.exe</filename> + on Windows systems. + This is a simple example of how &SCons; + makes it extremely easy to + write portable software builds. </para> <para> - There is, however, an important difference between - an &SConstruct; file and a &Makefile;: - the &SConstruct; file is actually a Python script. - If you're not already familiar with Python, don't worry. - This User's Guide will introduce you step-by-step - to the relatively small amount of Python you'll - need to know to be able to use &SCons; effectively. - And Python is very easy to learn. + (Note that we won't provide duplicate side-by-side + POSIX and Windows output for all of the examples in this guide; + just keep in mind that, unless otherwise specified, + any of the examples should work equally well on both types of systems.) </para> + </section> + + <section> + <title>Building Object Files</title> + <para> - One aspect of using Python as the - scripting language is that you can put comments - in your &SConstruct; file using Python's commenting convention; - that is, everything between a '#' and the end of the line - will be ignored: + The &Program; builder method is only one of + many builder methods that &SCons; provides + to build different types of files. + Another is the &Object; builder method, + which tells &SCons; to build an object file + from the specified source file: </para> <programlisting> - # Arrange to build the "hello" program. - Program('hello.c') # "hello.c" is the source file. + Object('hello.c') </programlisting> <para> - You'll see throughout the remainder of this Guide - that being able to use the power of a - real scripting language - can greatly simplify the solutions - to complex requirements of real-world builds. + Now when you run the &scons; command to build the program, + it will build just the &hello_o; object file on a POSIX system: </para> - </section> - - <section> - <title>Making the Output Less Verbose</title> + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + scons: Building targets ... + cc -c -o hello.o hello.c + scons: done building targets. + </screen> <para> - You've already seen how &SCons; prints - some messages about what it's doing, - surrounding the actual commands used to build the software: + And just the &hello_obj; object file + on a Windows system (with the Microsoft Visual C++ compiler): </para> - <literallayout> + <screen> C:\><userinput>scons</userinput> scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... cl /nologo /c hello.c /Fohello.obj - link /nologo /OUT:hello.exe hello.obj scons: done building targets. - </literallayout> - - <para> - - These messages emphasize the - order in which &SCons; does its work: - the configuration files - (generically referred to as &SConscript; files) - are read and executed first, - and only then are the target files built. - Among other benefits, these messages help to distinguish between - errors that occur while the configuration files are read, - and errors that occur while targets are being built. - - </para> - - <para> - - The drawback, of course, is that these messages clutter the output. - Fortunately, they're easily disabled by using - the &Q; option when invoking &SCons;: - - </para> - - <literallayout> - C:\><userinput>scons -Q</userinput> - cl /nologo /c hello.c /Fohello.obj - link /nologo /OUT:hello.exe hello.obj - </literallayout> - - <para> - - Because we want this User's Guide to focus - on what &SCons; is actually doing, - we're going use the &Q; option - to remove these messages from the - output of all the remaining examples in this Guide. - - </para> + </screen> </section> <section> - <title>Compiling Multiple Source Files</title> + <title>Simple Java Builds</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: + &SCons; also makes building with Java extremely easy. + Unlike the &Program; and &Object; builder methods, + however, the &Java; builder method + requires that you specify + the name of a destination directory in which + you want the class files placed, + followed by the source directory + in which the <filename>.java</filename> files live: </para> <programlisting> - Program(['prog.c', 'file1.c', 'file2.c']) + Java('classes', 'src') </programlisting> <para> - A build of the above example would look like: + If the <filename>src</filename> directory + contains a single <filename>hello.java</filename> file, + then the output from running the &scons; command + would look something like this + (on a POSIX system): </para> - <literallayout> - % <userinput>scons -Q</userinput> - cc -c -o file1.o file1.c - cc -c -o file2.o file2.c - cc -c -o prog.o prog.c - cc -o prog prog.o file1.o file2.o - </literallayout> - - <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 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', ['main.c', 'file1.c', 'file2.c']) - </programlisting> - - <para> - - On Linux, a build of this example would look like: - - </para> - - <literallayout> - % <userinput>scons -Q</userinput> - cc -c -o file1.o file1.c - cc -c -o file2.o file2.c - cc -c -o main.o main.c - cc -o program main.o file1.o file2.o - </literallayout> + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + scons: Building targets ... + javac -d classes -sourcepath src src/hello.java + scons: done building targets. + </screen> <para> - Or on Windows: + We'll cover Java builds in more detail, + including building Java archive (<filename>.jar</filename>) + and other types of file, + in <xref linkend="chap-java">. </para> - <literallayout> - C:\><userinput>scons -Q</userinput> - cl /nologo /c file1.c /Fofile1.obj - cl /nologo /c file2.c /Fofile2.obj - cl /nologo /c main.c /Fomain.obj - link /nologo /OUT:program.exe main.obj file1.obj file2.obj - </literallayout> - </section> <section> - <title>Keeping &SConstruct; Files Easy 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 <function>Program</function> 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 - <function>Program</function> function: - - </para> - - <programlisting> - list = Split('main.c file1.c file2.c') - Program('program', list) - </programlisting> + <title>Cleaning Up After a Build</title> <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: + When using &SCons;, it is unnecessary to add special + commands or target names to clean up after a build. + Instead, you simply use the + <literal>-c</literal> or <literal>--clean</literal> + option when you invoke &SCons;, + and &SCons; removes the appropriate built files. + So if we build our example above + and then invoke <literal>scons -c</literal> + afterwards, the output on POSIX looks like: </para> - <programlisting> - list = Split('main.c - file1.c - file2.c') - Program('program', list) - </programlisting> - - </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> - list = Split('main.c file1.c file2.c') - Program(target = 'program', source = list) - </programlisting> + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + scons: Building targets ... + cc -c -o hello.o hello.c + cc -o hello hello.o + scons: done building targets. + % <userinput>scons -c</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + scons: Cleaning targets ... + Removed hello.o + Removed hello + scons: done cleaning targets. + </screen> <para> - Because the keywords explicitly identify - what each argument is, - you can actually reverse the order if you prefer: + And the output on Windows looks like: </para> - <programlisting> - list = Split('main.c file1.c file2.c') - Program(source = list, target = 'program') - </programlisting> + <screen> + C:\><userinput>scons</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + scons: Building targets ... + cl /nologo /c hello.c /Fohello.obj + link /nologo /OUT:hello.exe hello.obj + scons: done building targets. + C:\><userinput>scons -c</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + scons: Cleaning targets ... + Removed hello.obj + Removed hello.exe + scons: done cleaning targets. + </screen> <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. + Notice that &SCons; changes its output to tell you that it + is <literal>Cleaning targets ...</literal> and + <literal>done cleaning targets.</literal> </para> </section> <section> - <title>Compiling Multiple Programs</title> - - <para> - - In order to compile multiple programs - within the same &SConstruct; file, - simply call the <function>Program</function> method - multiple times, - once for each program you need to build: - - </para> - - <programlisting> - Program('foo.c') - Program('bar', ['bar1.c', 'bar2.c']) - </programlisting> + <title>The &SConstruct; File</title> <para> - &SCons; would then build the programs as follows: + If you're used to build systems like &Make; + you've already figured out that the &SConstruct; file + is the &SCons; equivalent of a &Makefile;. + That is, the &SConstruct; file is the input file + that &SCons; reads to control the build. </para> - <literallayout> - % <userinput>scons -Q</userinput> - cc -c -o bar1.o bar1.c - cc -c -o bar2.o bar2.c - cc -o bar bar1.o bar2.o - cc -c -o foo.o foo.c - cc -o foo foo.o - </literallayout> - - <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> + <title>&SConstruct; Files Are Python Scripts</title> + + <para> + + There is, however, an important difference between + an &SConstruct; file and a &Makefile;: + the &SConstruct; file is actually a Python script. + If you're not already familiar with Python, don't worry. + This User's Guide will introduce you step-by-step + to the relatively small amount of Python you'll + need to know to be able to use &SCons; effectively. + And Python is very easy to learn. + + </para> + + <para> + + One aspect of using Python as the + scripting language is that you can put comments + in your &SConstruct; file using Python's commenting convention; + that is, everything between a '#' and the end of the line + will be ignored: + + </para> + + <programlisting> + # Arrange to build the "hello" program. + Program('hello.c') # "hello.c" is the source file. + </programlisting> + + <para> + + You'll see throughout the remainder of this Guide + that being able to use the power of a + real scripting language + can greatly simplify the solutions + to complex requirements of real-world builds. + + </para> + + </section> + + <section> + <title>&SCons; Functions Are Order-Independent</title> + + <para> + + One important way in which the &SConstruct; + file is not exactly like a normal Python script, + and is more like a &Makefile;, + is that the order in which + the &SCons; functions are called in + the &SConstruct; file + does <emphasis>not</emphasis> + affect the order in which &SCons; + actually builds the programs and object files + you want it to build.<footnote> + <para>In programming parlance, + the &SConstruct; file is + <emphasis>declarative</emphasis>, + meaning you tell &SCons; what you want done + and let it figure out the order in which to do it, + rather than strictly <emphasis>imperative</emphasis>, + where you specify explicitly the order in + which to do things. + </para> + </footnote> + In other words, when you call the &Program; builder + (or any other builder method), + you're not telling &SCons; to build + the program at the instant the builder method is called. + Instead, you're telling &SCons; to build the program + that you want, for example, + a program built from a file named &hello_c;, + and it's up to &SCons; to build that program + (and any other files) whenever it's necessary. + (We'll learn more about how + &SCons; decides when building or rebuilding a file + is necessary in <xref linkend="chap-depends">, below.) + + </para> + + <para> + + &SCons; reflects this distinction between + <emphasis>calling a builder method like</emphasis> &Program;> + and <emphasis>actually building the program</emphasis> + by printing the status messages that indicate + when it's "just reading" the &SConstruct; file, + and when it's actually building the target files. + This is to make it clear when &SCons; is + executing the Python statements that make up the &SConstruct; file, + and when &SCons; is actually executing the + commands or other actions to + build the necessary files. + + </para> + + <para> + + Let's clarify this with an example. + Python has a <literal>print</literal> statement that + prints a string of characters to the screen. + If we put <literal>print</literal> statements around + our calls to the &Program; builder method: + + </para> + + <programlisting> + print "Calling Program('hello.c')" + Program('hello.c') + print "Calling Program('goodbye.c')" + Program('goodbye.c') + print "Finished calling Program()" + </programlisting> + + <para> + + Then when we execute &SCons;, + we see the output from the <literal>print</literal> + statements in between the messages about + reading the &SConscript; files, + indicating that that is when the + Python statements are being executed: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + Calling Program('hello.c') + Calling Program('goodbye.c') + Finished calling Program() + scons: done reading SConscript files. + scons: Building targets ... + cc -c -o goodbye.o goodbye.c + cc -o goodbye goodbye.o + cc -c -o hello.o hello.c + cc -o hello hello.o + scons: done building targets. + </screen> + + <para> + + Notice also that &SCons; built the &goodbye; program first, + even though the "reading &SConscript;" output + shows that we called <literal>Program('hello.c')</literal> + first in the &SConstruct; file. + + </para> + + </section> </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 - section XXX, below.) - - </para> + <title>Making the &SCons; Output Less Verbose</title> <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: + You've already seen how &SCons; prints + some messages about what it's doing, + surrounding the actual commands used to build the software: </para> - <programlisting> - Program(Split('foo.c common1.c common2.c')) - Program('bar', Split('bar1.c bar2.c common1.c common2.c')) - </programlisting> + <screen> + C:\><userinput>scons</userinput> + scons: Reading SConscript files ... + scons: done reading SConscript files. + scons: Building targets ... + cl /nologo /c hello.c /Fohello.obj + link /nologo /OUT:hello.exe hello.obj + scons: done building targets. + </screen> <para> - &SCons; recognizes that the object files for - the &common1_c; and &common2_c; source files - each only need to be built once, - even though the resulting object files are - each linked in to both of the resulting executable programs: + These messages emphasize the + order in which &SCons; does its work: + all of the configuration files + (generically referred to as &SConscript; files) + are read and executed first, + and only then are the target files built. + Among other benefits, these messages help to distinguish between + errors that occur while the configuration files are read, + and errors that occur while targets are being built. </para> - <literallayout> - % <userinput>scons -Q</userinput> - cc -c -o bar1.o bar1.c - cc -c -o bar2.o bar2.c - cc -c -o common1.o common1.c - cc -c -o common2.o common2.c - cc -o bar bar1.o bar2.o common1.o common2.o - cc -c -o foo.o foo.c - cc -o foo foo.o common1.o common2.o - </literallayout> - <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: + One drawback, of course, is that these messages clutter the output. + Fortunately, they're easily disabled by using + the &Q; option when invoking &SCons;: </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> + <screen> + C:\><userinput>scons -Q</userinput> + cl /nologo /c hello.c /Fohello.obj + link /nologo /OUT:hello.exe hello.obj + </screen> <para> - This is functionally equivalent to the previous example. + Because we want this User's Guide to focus + on what &SCons; is actually doing, + we're going use the &Q; option + to remove these messages from the + output of all the remaining examples in this Guide. </para> |