diff options
Diffstat (limited to 'doc')
77 files changed, 7290 insertions, 1449 deletions
diff --git a/doc/man/scons.1 b/doc/man/scons.1 index 64756e9..f9138a7 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -945,10 +945,11 @@ env = Environment(tools = ['msvc', 'lex']) Non-built-in tools may be specified using the toolpath argument: .ES -env = Environment(tools = ['foo'], toolpath = ['tools']) +env = Environment(tools = ['default', 'foo'], toolpath = ['tools']) .EE -This looks for a tool specification in tools/foo.py. foo.py should +This looks for a tool specification in tools/foo.py (as well as +using the ordinary default tools for the platform). foo.py should have two functions: generate(env) and exists(env). generate() modifies the passed in environment and exists() should return a true value if the tool is available. Tools in the toolpath are used before @@ -2618,12 +2619,23 @@ cc_dict = env.Dictionary('CC', 'CCFLAGS', 'CCCOM') .RI Dir( name ", [" directory ]) .TP .RI env.Dir( name ", [" directory ]) -This returns an object that represents a given directory +This returns a Directory Node, +an object that represents the specified directory .IR name . .I name can be a relative or absolute path. .I directory is an optional directory that will be used as the parent directory. +If no +.I directory +is specified, the current script's directory is used as the parent. + +Directory Nodes can be used anywhere you +would supply a string as a directory name +to a Builder method or function. +Directory Nodes have attributes and methods +that are useful in many situations; +see "File and Directory Nodes," below. '\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .TP @@ -2753,13 +2765,22 @@ function, below. .RI File( name ", [" directory ]) .TP .RI env.File( name ", [" directory ]) -This returns an object that represents a given file +This returns a +File Node, +an object that represents the specified file .IR name . .I name can be a relative or absolute path. .I directory is an optional directory that will be used as the parent directory. +File Nodes can be used anywhere you +would supply a string as a file name +to a Builder method or function. +File Nodes have attributes and methods +that are useful in many situations; +see "File and Directory Nodes," below. + '\""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .TP .RI FindFile( file ", " dirs ) @@ -3390,6 +3411,9 @@ that would normally be built in the subdirectory in which resides should actually be built in .IR build_dir . +.I build_dir +is interpreted relative to the directory +of the calling SConscript file. The optional .I src_dir @@ -3398,6 +3422,9 @@ source files from which the target files should be built can be found in .IR src_dir . +.I src_dir +is interpreted relative to the directory +of the calling SConscript file. By default, .B scons @@ -5377,15 +5404,15 @@ setting .B MSVS_USE_MFC_DIRS to a non-zero value adds the -.BR ATL\\include +.B "ATL\\\\include" and -.BR MFC\\include +.B "MFC\\\\include" directories to the default .B INCLUDE external environment variable, and adds the -.B MFC\\lib +.B "MFC\\\\lib" directory to the default .B LIB @@ -5395,12 +5422,12 @@ setting .B MSVS_USE_MFC_DIRS to a non-zero value adds the -.BR atlmfc\\include +.B "atlmfc\\\\include" directory to the default .B INCLUDE external environment variable, and adds the -.BR atlmfc\\lib +.B "atlmfc\\\\lib" directory to the default .B LIB external environment variable. @@ -6329,7 +6356,7 @@ Returns 1 on success and 0 on failure. .TP .RI Configure.CheckFunc( self ", " function_name ", [" language ]) Checks if the specified -C or C+++ function is available. +C or C++ function is available. .I function_name is the name of the function to check for. The optional @@ -6869,7 +6896,7 @@ arbitrary string that is being enabled). The option will also support the values .BR no , -.BR flase , +.BR false , .BR off or .BR disable @@ -6914,6 +6941,66 @@ opts.AddOptions( ) .EE +.SS File and Directory Nodes + +The +.IR File () +and +.IR Dir () +functions return +.I File +and +.I Dir +Nodes, respectively. +python objects, respectively. +Those objects have several user-visible attributes +and methods that are often useful: + +.IP path +The build path +of the given +file or directory. +This path is relative to the top-level directory +(where the +.B SConstruct +file is found). +The build path is the same as the source path if +.I build_dir +is not being used. + +.IP abspath +The absolute build path of the given file or directory. + +.IP srcnode() +The +.IR srcnode () +method +returns another +.I File +or +.I Dir +object representing the +.I source +path of the given +.I File +or +.IR Dir . +The + +.ES +# Get the current build dir's path, relative to top. +Dir('.').path +# Current dir's absolute path +Dir('.').abspath +# Next line is always '.', because it is the top dir's path relative to itself. +Dir('#.').path +File('foo.c').srcnode().path # source path of the given source file. + +# Builders also return File objects: +foo = env.Program('foo.c') +print "foo will be built in %s"%foo.path +.EE + .SH EXTENDING SCONS .SS Builder Objects .B scons @@ -6935,7 +7022,7 @@ that sets the appropriate construction variables (CC, LINK, etc.). Builder objects are created -using the +using the .B Builder function. The @@ -8366,7 +8453,7 @@ libB/SConscript: Main/SConscript: Import('env') - e = env.Copy(LIBS = ['a', ','b']) + e = env.Copy(LIBS = ['a', 'b']) e.Program('foo', Split('m1.c m2.c m3.c')) .EE diff --git a/doc/scons.mod b/doc/scons.mod index c4d0e8e..3b15c64 100644 --- a/doc/scons.mod +++ b/doc/scons.mod @@ -1,5 +1,7 @@ <!-- + __COPYRIGHT__ + An SCons-specific DTD module, for use with SCons DocBook documentation, that contains names, phrases, acronyms, etc. used throughout the SCons documentation. @@ -20,13 +22,18 @@ <!ENTITY Automake "<application>Automake</application>"> <!ENTITY cc "<application>cc</application>"> <!ENTITY Cons "<application>Cons</application>"> +<!ENTITY cp "<application>cp</application>"> <!ENTITY csh "<application>csh</application>"> <!ENTITY gcc "<application>gcc</application>"> <!ENTITY Jam "<application>Jam</application>"> +<!ENTITY jar "<application>jar</application>"> +<!ENTITY javac "<application>javac</application>"> +<!ENTITY javah "<application>javah</application>"> <!ENTITY Make "<application>Make</application>"> <!ENTITY Makepp "<application>Make++</application>"> <!ENTITY Python "<application>Python</application>"> <!ENTITY ranlib "<application>ranlib</application>"> +<!ENTITY rmic "<application>rmic</application>"> <!ENTITY SCons "<application>SCons</application>"> <!ENTITY scons "<application>scons</application>"> <!ENTITY ScCons "<application>ScCons</application>"> @@ -72,6 +79,7 @@ --> +<!ENTITY debug-explain "<literal>--debug=explain</literal>"> <!ENTITY implicit-cache "<literal>--implicit-cache</literal>"> <!ENTITY implicit-deps-changed "<literal>--implicit-deps-changed</literal>"> <!ENTITY implicit-deps-unchanged "<literal>--implicit-deps-unchanged</literal>"> @@ -125,13 +133,18 @@ <!ENTITY Clean "<function>Clean</function>"> <!ENTITY Clone "<function>Clone</function>"> <!ENTITY Command "<function>Command</function>"> +<!ENTITY Configure "<function>Configure</function>"> <!ENTITY Copy "<function>Copy</function>"> <!ENTITY Default "<function>Default</function>"> <!ENTITY DefaultRules "<function>DefaultRules</function>"> <!ENTITY Depends "<function>Depends</function>"> +<!ENTITY Dir "<function>Dir</function>"> +<!ENTITY Entry "<function>Entry</function>"> <!ENTITY EnumOption "<function>EnumOption</function>"> <!ENTITY Environment "<function>Environment</function>"> <!ENTITY Export "<function>Export</function>"> +<!ENTITY File "<function>File</function>"> +<!ENTITY Finish "<function>Finish</function>"> <!ENTITY GenerateHelpText "<function>GenerateHelpText</function>"> <!ENTITY Help "<function>Help</function>"> <!ENTITY Ignore "<function>Ignore</function>"> @@ -161,6 +174,25 @@ <!ENTITY TargetSignatures "<function>TargetSignatures</function>"> <!ENTITY Task "<function>Task</function>"> +<!-- Environment methods --> +<!ENTITY subst "<function>subst</function>"> + +<!-- Configure context functions --> +<!ENTITY Message "<function>Message</function>"> +<!ENTITY Result "<function>Result</function>"> +<!ENTITY CheckCHeader "<function>CheckCHeader</function>"> +<!ENTITY CheckCXXHeader "<function>CheckCXXHeader</function>"> +<!ENTITY CheckFunc "<function>CheckFunc</function>"> +<!ENTITY CheckHeader "<function>CheckHeader</function>"> +<!ENTITY CheckLibrary "<function>CheckLibrary</function>"> +<!ENTITY CheckType "<function>CheckType</function>"> +<!ENTITY TryAction "<function>TryAction</function>"> +<!ENTITY TryBuild "<function>TryBuild</function>"> +<!ENTITY TryCompile "<function>TryCompile</function>"> +<!ENTITY TryLink "<function>TryLink</function>"> +<!ENTITY TryRun "<function>TryRun</function>"> + +<!-- Python functions --> <!ENTITY str "<function>str</function>"> <!ENTITY zipfile "<function>zipfile</function>"> @@ -192,11 +224,13 @@ <!ENTITY BUILDERS "<varname>BUILDERS</varname>"> <!ENTITY CC "<varname>CC</varname>"> <!ENTITY CCFLAGS "<varname>CCFLAGS</varname>"> +<!ENTITY CCCOM "<varname>CCCOM</varname>"> <!ENTITY COLOR "<varname>COLOR</varname>"> <!ENTITY COLORS "<varname>COLORS</varname>"> <!ENTITY CONFIG "<varname>CONFIG</varname>"> <!ENTITY CPPDEFINES "<varname>CPPDEFINES</varname>"> <!ENTITY ENV "<varname>ENV</varname>"> +<!ENTITY JAVACLASSDIR "<varname>JAVACLASSDIR</varname>"> <!ENTITY LIBDIRPREFIX "<varname>LIBDIRPREFIX</varname>"> <!ENTITY LIBDIRSUFFIX "<varname>LIBDIRSUFFIX</varname>"> <!ENTITY LIBLINKPREFIX "<varname>LIBLINKPREFIX</varname>"> @@ -296,6 +330,10 @@ --> <!ENTITY buildfunc "<literal>builder function</literal>"> +<!ENTITY builder_method "<literal>builder method</literal>"> + +<!ENTITY Configure_Contexts "<literal>Configure Contexts</literal>"> +<!ENTITY configure_context "<literal>configure context</literal>"> <!ENTITY ConsEnv "<literal>Construction Environment</literal>"> <!ENTITY ConsEnvs "<literal>Construction Environments</literal>"> @@ -320,12 +358,16 @@ <!ENTITY Generator "<literal>Generator</literal>"> <!ENTITY generator "<literal>generator</literal>"> +<!ENTITY Nodes "<literal>Nodes</literal>"> + <!ENTITY signature "<literal>signature</literal>"> <!ENTITY buildsignature "<literal>build signature</literal>"> <!ENTITY true "<literal>true</literal>"> <!ENTITY false "<literal>false</literal>"> +<!ENTITY typedef "<literal>typedef</literal>"> + <!-- File and program names used in examples. @@ -333,22 +375,31 @@ --> <!ENTITY bar "<application>bar</application>"> -<!ENTITY common1_c "<application>common1.c</application>"> -<!ENTITY common2_c "<application>common2.c</application>"> +<!ENTITY common1_c "<filename>common1.c</filename>"> +<!ENTITY common2_c "<filename>common2.c</filename>"> <!ENTITY custom_py "<filename>custom.py</filename>"> <!ENTITY goodbye "<application>goodbye</application>"> -<!ENTITY file_dll "<application>file.dll</application>"> -<!ENTITY file_lib "<application>file.lib</application>"> -<!ENTITY file_o "<application>file.o</application>"> -<!ENTITY file_obj "<application>file.obj</application>"> +<!ENTITY goodbye_o "<filename>goodbye.o</filename>"> +<!ENTITY goodbye_obj "<filename>goodbye.obj</filename>"> +<!ENTITY file_dll "<filename>file.dll</filename>"> +<!ENTITY file_in "<filename>file.in</filename>"> +<!ENTITY file_lib "<filename>file.lib</filename>"> +<!ENTITY file_o "<filename>file.o</filename>"> +<!ENTITY file_obj "<filename>file.obj</filename>"> +<!ENTITY file_out "<filename>file.out</filename>"> <!ENTITY foo "<application>foo</application>"> +<!ENTITY foo_o "<filename>foo.o</filename>"> +<!ENTITY foo_obj "<filename>foo.obj</filename>"> <!ENTITY hello "<application>hello</application>"> <!ENTITY hello_c "<filename>hello.c</filename>"> <!ENTITY hello_exe "<filename>hello.exe</filename>"> <!ENTITY hello_h "<filename>hello.h</filename>"> <!ENTITY hello_o "<filename>hello.o</filename>"> +<!ENTITY hello_obj "<filename>hello.obj</filename>"> <!ENTITY libfile_a "<filename>libfile_a</filename>"> <!ENTITY libfile_so "<filename>libfile_so</filename>"> +<!ENTITY new_hello "<application>new_hello</application>"> +<!ENTITY new_hello_exe "<application>new_hello.exe</application>"> <!ENTITY prog "<filename>prog</filename>"> <!ENTITY prog1 "<filename>prog1</filename>"> <!ENTITY prog2 "<filename>prog2</filename>"> @@ -371,6 +422,6 @@ --> -<!ENTITY scons-announce "<literal>scons-announce@lists.sourceforge.net</literal>"> -<!ENTITY scons-devel "<literal>scons-devel@lists.sourceforge.net</literal>"> -<!ENTITY scons-users "<literal>scons-users@lists.sourceforge.net</literal>"> +<!ENTITY scons-announce "<literal>announce@scons.tigris.org</literal>"> +<!ENTITY scons-devel "<literal>dev@scons.tigris.org</literal>"> +<!ENTITY scons-users "<literal>users@scons.tigris.org</literal>"> diff --git a/doc/user/ENV.in b/doc/user/ENV.in index 3fc3a29..b1edd81 100644 --- a/doc/user/ENV.in +++ b/doc/user/ENV.in @@ -1,7 +1,7 @@ <!-- - 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 @@ -80,6 +80,46 @@ env = Environment(ENV = {'PATH' : path}) </sconstruct> + <para> + + Assign a dictionary to the &ENV; + construction variable in this way + completely resets the external environment + so that the only variable that will be + set when external commands are executed + will be the &PATH; value. + If you want to use the rest of + the values in &ENV; and only + set the value of &PATH;, + the most straightforward way is probably: + + </para> + + <sconstruct> + env['ENV']['PATH'] = ['/usr/local/bin', '/bin', '/usr/bin'] + </sconstruct> + + <para> + + Note that &SCons; does allow you to define + the directories in the &PATH; in a string, + separated by the pathname-separator character + for your system (':' on POSIX systems, ';' on Windows): + + </para> + + <sconstruct> + env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin' + </sconstruct> + + <para> + + But doing so makes your &SConscript; file less portable, + (although in this case that may not be a huge concern + since the directories you list are likley system-specific, anyway). + + </para> + <!-- <scons_example name="ex1"> diff --git a/doc/user/ENV.sgml b/doc/user/ENV.sgml index d3078f1..c2d7296 100644 --- a/doc/user/ENV.sgml +++ b/doc/user/ENV.sgml @@ -1,7 +1,7 @@ <!-- - 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 @@ -80,6 +80,46 @@ env = Environment(ENV = {'PATH' : path}) </programlisting> + <para> + + Assign a dictionary to the &ENV; + construction variable in this way + completely resets the external environment + so that the only variable that will be + set when external commands are executed + will be the &PATH; value. + If you want to use the rest of + the values in &ENV; and only + set the value of &PATH;, + the most straightforward way is probably: + + </para> + + <programlisting> + env['ENV']['PATH'] = ['/usr/local/bin', '/bin', '/usr/bin'] + </programlisting> + + <para> + + Note that &SCons; does allow you to define + the directories in the &PATH; in a string, + separated by the pathname-separator character + for your system (':' on POSIX systems, ';' on Windows): + + </para> + + <programlisting> + env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin' + </programlisting> + + <para> + + But doing so makes your &SConscript; file less portable, + (although in this case that may not be a huge concern + since the directories you list are likley system-specific, anyway). + + </para> + <!-- <scons_example name="ex1"> diff --git a/doc/user/MANIFEST b/doc/user/MANIFEST index 9e3f7bf..58ac2fc 100644 --- a/doc/user/MANIFEST +++ b/doc/user/MANIFEST @@ -4,6 +4,7 @@ ant.sgml builders-built-in.sgml builders-commands.sgml builders-writing.sgml +build-install.sgml caching.sgml command-line.sgml cons.pl @@ -17,14 +18,18 @@ example.sgml help.sgml hierarchy.sgml install.sgml +java.sgml libraries.sgml +less-simple.sgml main.sgml make.sgml +nodes.sgml precious.sgml preface.sgml repositories.sgml run.sgml scanners.sgml +sconf.sgml separate.sgml simple.sgml sourcecode.sgml diff --git a/doc/user/actions.in b/doc/user/actions.in index c35ccdd..928b7ea 100644 --- a/doc/user/actions.in +++ b/doc/user/actions.in @@ -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 diff --git a/doc/user/actions.sgml b/doc/user/actions.sgml index c35ccdd..928b7ea 100644 --- a/doc/user/actions.sgml +++ b/doc/user/actions.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 diff --git a/doc/user/alias.in b/doc/user/alias.in index 6cc68b0..d2344a2 100644 --- a/doc/user/alias.in +++ b/doc/user/alias.in @@ -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 diff --git a/doc/user/alias.sgml b/doc/user/alias.sgml index a4b65da..4471605 100644 --- a/doc/user/alias.sgml +++ b/doc/user/alias.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 @@ -44,12 +44,12 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q install</userinput> cc -c -o hello.o hello.c cc -o hello hello.o Install file: "hello" as "/usr/bin/hello" - </literallayout> + </screen> <para> @@ -84,7 +84,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q install-bin</userinput> cc -c -o foo.o foo.c cc -o foo foo.o @@ -109,4 +109,4 @@ ar r libbar.a bar.o ranlib libbar.a Install file: "libbar.a" as "/usr/lib/libbar.a" - </literallayout> + </screen> diff --git a/doc/user/ant.in b/doc/user/ant.in index 4eb5007..0df1027 100644 --- a/doc/user/ant.in +++ b/doc/user/ant.in @@ -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 diff --git a/doc/user/ant.sgml b/doc/user/ant.sgml index 4eb5007..0df1027 100644 --- a/doc/user/ant.sgml +++ b/doc/user/ant.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 diff --git a/doc/user/build-install.in b/doc/user/build-install.in new file mode 100644 index 0000000..164aabe --- /dev/null +++ b/doc/user/build-install.in @@ -0,0 +1,605 @@ +<!-- + + __COPYRIGHT__ + + 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> + + This chapter will take you through the basic steps + of installing &SCons; on your system, + and building &SCons; if you don't have a + pre-built package available + (or simply prefer the flexibility of building it yourself). + Before that, however, this chapter will also describe the basic steps + involved in installing Python on your system, + in case that is necessary. + Fortunately, both &SCons; and Python + are very easy to install on almost any system, + and Python already comes installed on many systems. + + </para> + + <!-- + + <para> + + Lastly, this chapter also contains a section that + provides a brief overview of the Python programming language, + which is the language used to implement &SCons;, + and which forms the basis of the &SCons; configuration files. + Becoming familiar with some Python concepts will make it easier + to understand many of the examples in this User's Guide. + Nevertheless, it <emphasis>is</emphasis> possible + to configure simple &SCons; builds without knowing Python, + so you can skip this section if you + want to dive in and pick up things + by example- -or, of course, if you are + already familiar with Python. + + </para> + + --> + + <section> + <title>Installing Python</title> + + <para> + + Because &SCons; is written in Python, + you must obviously have Python installed on your system + to use &SCons; + Before you try to install Python, + you should check to see if Python is already + available on your system by typing + <userinput>python</userinput> + at your system's command-line prompt. + You should see something like the following + on a UNIX or Linux system that has Python installed: + + </para> + + <screen> + $ <userinput>python</userinput> + Python 2.2.2 (#1, Feb 24 2003, 19:13:11) + [GCC 3.2.2 20030222 (Red Hat Linux 3.2.2-4)] on linux2 + Type "help", "copyright", "credits" or "license" for more information. + >>> <userinput>^D</userinput> + </screen> + + <para> + + And on a Windows system with Python installed: + + </para> + + <screen> + C:\><userinput>python</userinput> + Python 2.2.2 (#34, Apr 9 2002, 19:34:33) [MSC 32 bit (Intel)] on win32 + Type "help", "copyright", "credits" or "license" for more information. + >>> <userinput>^Z</userinput> + </screen> + + <para> + + The <prompt>>>></prompt> is the input prompt + for the Python interpreter. + The <userinput>^D</userinput> and <userinput>^Z</userinput> + represent the CTRL-D and CTRL-Z characters + that you will need to type to get out of the interpreter + before proceeding to installing &SCons;. + + </para> + + <para> + + If Python is not installed on your system, + you will see an error message + stating something like "command not found" + (on UNIX or Linux) + or "'python' is not recognized + as an internal or external command, operable progam or batch file" + (on Windows). + In that case, you need to install Python + before you can install &SCons;. + + </para> + + <para> + + The standard location for information + about downloading and installing Python is + <ulink url="http://www.python.org/download/">http://www.python.org/download/</ulink>. + See that page for information about + how to download and install Python on your system. + + </para> + + </section> + + <section> + <title>Installing &SCons; From Pre-Built Packages</title> + + <para> + + &SCons; comes pre-packaged for installation on a number of systems, + including Linux and Windows systems. + You do not need to read this entire section, + you should only need to read the section + appropriate to the type of system you're running on. + + </para> + + <section> + <title>Installing &SCons; on Red Hat (and Other RPM-based) Linux Systems</title> + + <para> + + &SCons; comes in RPM (Red Hat Package Manager) format, + pre-built and ready to install on Red Hat Linux, + or any other Linux distribution that uses RPM. + Your distribution may + already have an &SCons; RPM built specifically for it; + many do, including SuSe, Mandrake and Fedora. + You can check for the availability of an &SCons; RPM + on your distribution's download servers, + or by consulting an RPM search site like + <ulink url="http://www.rpmfind.net/">http://www.rpmfind.net/</ulink> or + <ulink url="http://rpm.pbone.net/">http://rpm.pbone.net/</ulink>. + + </para> + + <para> + + If your Linux distribution does not already have + a specific &SCons; RPM file, + you can download and install from the + generic RPM provided by the &SCons; project. + This will install the + SCons script(s) in <filename>/usr/bin</filename>, + and the SCons library modules in + <filename>/usr/lib/scons</filename>. + + </para> + + <para> + + To install from the command line, simply download the + appropriate <filename>.rpm</filename> file, + and then run: + + </para> + + <screen> + # <userinput>rpm -Uvh scons-0.96-1.noarch.rpm</userinput> + </screen> + + <para> + + Or, you can use a graphical RPM package manager + like <application>gnorpm</application>. + See your package manager application's documention + for specific instructions about + how to use it to install a downloaded RPM. + + </para> + + </section> + + <section> + <title>Installing &SCons; on Debian Linux Systems</title> + + <para> + + Debian Linux systems use a different package management + format that also makes it very easy to install &SCons;. + + </para> + + <para> + + If your system is connected to the Internet, + you can install the latest official Debian package + by running: + + </para> + + <screen> + # <userinput>apt-get install scons</userinput> + </screen> + + <!-- + + <para> + + Alternatively, + you can download the Debian package built + by the &SCons; project + and install it manually by running: + + </para> + + <screen> + # <userinput>db-XXX scons-*.deb</userinput> + </screen> + + --> + + </section> + + <section> + <title>Installing &SCons; on Windows Systems</title> + + <para> + + &SCons; provides a Windows installer + that makes installation extremely easy. + Download the <filename>scons-0.95.win32.exe</filename> + file from the &SCons; download page at + <ulink url="http://www.scons.org/download.html">http://www.scons.org/download.html</ulink>. + Then all you need to is execute the file + (usually by clicking on its icon in Windows Explorer). + These will take you through a small + sequence of windows that will install + &SCons; on your system. + + <!-- + Things are a little more complicated + if you are using the Cygwin version of Python. + This is because Cygwin + tries to make a Windows system look more + POSIX-like (or UNIX-like or Linux-like, if you prefer) + by having the Cygwin utilities, + including Cygwin Python, + interpret file name arguments on the command line + using the forward-slash (<filename>/</filename>) + as the directory separator, + instead of the normal Windows behavior of the + backslash (<filename>\</filename>) as the directory separator. + --> + + </para> + + <!-- + + <section> + <title>Installing &SCons; on Windows Systems Without Cygwin Python</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Installing &SCons; on Windows Systems With Cygwin Python</title> + + <para> + + XXX + + </para> + + </section> + + --> + + </section> + + </section> + + <section> + <title>Building and Installing &SCons; on Any System</title> + + <para> + + If a pre-built &SCons; package is not available for your system, + then you can still easily build and install &SCons; using the native + Python <filename>distutils</filename> package. + + </para> + + <para> + + The first step is to download either the + <filename>scons-__VERSION__.tar.gz</filename> + or <filename>scons-__VERSION__.zip</filename>, + which are available from the SCons download page at + <ulink url="http://www.scons.org/download.html">http://www.scons.org/download.html</ulink>. + + </para> + + <para> + + Unpack the archive you downloaded, + using a utility like <application>tar</application> + on Linux or UNIX, + or <application>WinZip</application> on Windows. + This will create a directory called + <filename>scons-__VERSION__</filename>, + usually in your local directory. + Then change your working directory to that directory + and install &SCons; by executing the following commands: + + </para> + + <screen> + # <userinput>cd scons-__VERSION__</userinput> + # <userinput>python setup.py install</userinput> + </screen> + + <para> + + This will build &SCons;, + install the <application>scons</application> script + in the default system scripts directory + (<filename>/usr/local/bin</filename> or + <filename>C:\Python2.2\Scripts</filename>), + and will install the &SCons; build engine + in an appropriate stand-alone library directory + (<filename>/usr/local/lib/scons</filename> or + <filename>C:\Python2.2\scons</filename>). + Because these are system directories, + you may need root (on Linux or UNIX) or Administrator (on Windows) + privileges to install &SCons; like this. + + </para> + + <section> + <title>Building and Installing &SCons; Without Administrative Privileges</title> + + <para> + + If you don't have the right privileges to install &SCons; + in a system location, + you can install it in a location of your choosing + by specifying the <literal>--prefix=</literal> option: + + </para> + + <screen> + # <userinput>python setup.py install --prefix=$HOME</userinput> + </screen> + + <para> + + This would install &SCons; in appropriate locations + relative to the user's <literal>$HOME</literal> directory, + the <application>scons</application> script in + <filename>$HOME/bin</filename> + and the build engine in + <filename>$HOME/lib/scons</filename>. + You may, of course, specify any other location you prefer. + + </para> + + </section> + + <!-- + + <section> + <title>Building and Installing &SCons; in the Standard Python Library Directories</title> + + <para> + + XXX + + </para> + + </section> + + --> + + <section> + <title>Building and Installing Multiple Versions of &SCons; Side-by-Side</title> + + <para> + + The &SCons; <filename>setup.py</filename> script + has some extensions that support + easy installation of multiple versions of &SCons; + in side-by-side locations. + This makes it easier to download and + experiment with different versions of &SCons; + before moving your official build process to a new version, + for example. + + </para> + + <para> + + To install &SCons; in a version-specific location, + add the <option>--version-lib</option> option + when you call <filename>setup.py</filename>: + + </para> + + <screen> + # <userinput>python setup.py install --version-lib</userinput> + </screen> + + <para> + + This will install the &SCons; build engine + in the + <filename>/usr/lib/scons-__VERSION__</filename> + or + <filename>C:\Python2.2\scons-__VERSION__</filename> + directory, for example. + You can also specify <option>--prefix=</option>, + in which case <filename>setup.py</filename> + will install the build engine + in a version-specific directory + relative to the specified prefix. + + </para> + + <para> + + If you use the <option>--version-lib</option> option + the first time you install &SCons;, + you do not need to specify it each time you install + a new version. + The &SCons; <filename>setup.py</filename> script + will detect the version-specific directory name(s) + and assume you want to install all versions + in version-specific directories. + You can override that assumption in the future + by explicitly specifying the <option>--standalone-lib</option> option. + + </para> + + </section> + + </section> + + <!-- + + <section> + <title>Python Basics</title> + + <para> + + This section will provide a brief overview of + the Python programming language. + Skip this section if you are already familiar with Python + (or you're really intent on diving into &SCons; + and just picking up things as you go). + + </para> + + <para> + + Python has a lot of good + documentation freely available on-line + to help you get started. + The standard tutorial is available at XXX. + + + </para> + + <para> + + Python is very easy to pick up. + + </para> + + <para> + + Python variables must be assigned to before they can be referenced. + + </para> + + <para> + + Assignment is like most programming languages: + + x = 1 + 2 + z = 3 * x + + </para> + + <para> + + Function calls look like most language function calls: + + a = f(g) + + </para> + + <para> + + Define functions like so: + + def func(arg1, arg2): + return arg1 * arg 2 + + The number of parameters + + </para> + + <para> + + Strings can be enclosed in single quotes or double quotes, + backslashes are used to escape characters, + triple-quote syntax lets you include quotes and newlines, + raw strings begin with 'r'. + + </para> + + <para> + + Lists are enclosed in square brackets, + list items are separated by commas. + List references use square brackets and integer index values, + slice notation lets you select, delete or replace a range. + + </para> + + <para> + + Dictionaries (hashes) are enclosed in curly brackets, + : separates keys from values, + , separates items. + Dictionary values are referenced using square brackets. + + </para> + + <para> + + Access class attributes (including methods) using a '.'. + + </para> + + <para> + + if: statements look like + + elif: statements look like + + else: statements look like + + </para> + + <para> + + for: statements look like + + while: statements look like + + break statements look like + + continue statements look like + + </para> + + <para> + + pass + + </para> + + </section> + + --> diff --git a/doc/user/build-install.sgml b/doc/user/build-install.sgml new file mode 100644 index 0000000..164aabe --- /dev/null +++ b/doc/user/build-install.sgml @@ -0,0 +1,605 @@ +<!-- + + __COPYRIGHT__ + + 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> + + This chapter will take you through the basic steps + of installing &SCons; on your system, + and building &SCons; if you don't have a + pre-built package available + (or simply prefer the flexibility of building it yourself). + Before that, however, this chapter will also describe the basic steps + involved in installing Python on your system, + in case that is necessary. + Fortunately, both &SCons; and Python + are very easy to install on almost any system, + and Python already comes installed on many systems. + + </para> + + <!-- + + <para> + + Lastly, this chapter also contains a section that + provides a brief overview of the Python programming language, + which is the language used to implement &SCons;, + and which forms the basis of the &SCons; configuration files. + Becoming familiar with some Python concepts will make it easier + to understand many of the examples in this User's Guide. + Nevertheless, it <emphasis>is</emphasis> possible + to configure simple &SCons; builds without knowing Python, + so you can skip this section if you + want to dive in and pick up things + by example- -or, of course, if you are + already familiar with Python. + + </para> + + --> + + <section> + <title>Installing Python</title> + + <para> + + Because &SCons; is written in Python, + you must obviously have Python installed on your system + to use &SCons; + Before you try to install Python, + you should check to see if Python is already + available on your system by typing + <userinput>python</userinput> + at your system's command-line prompt. + You should see something like the following + on a UNIX or Linux system that has Python installed: + + </para> + + <screen> + $ <userinput>python</userinput> + Python 2.2.2 (#1, Feb 24 2003, 19:13:11) + [GCC 3.2.2 20030222 (Red Hat Linux 3.2.2-4)] on linux2 + Type "help", "copyright", "credits" or "license" for more information. + >>> <userinput>^D</userinput> + </screen> + + <para> + + And on a Windows system with Python installed: + + </para> + + <screen> + C:\><userinput>python</userinput> + Python 2.2.2 (#34, Apr 9 2002, 19:34:33) [MSC 32 bit (Intel)] on win32 + Type "help", "copyright", "credits" or "license" for more information. + >>> <userinput>^Z</userinput> + </screen> + + <para> + + The <prompt>>>></prompt> is the input prompt + for the Python interpreter. + The <userinput>^D</userinput> and <userinput>^Z</userinput> + represent the CTRL-D and CTRL-Z characters + that you will need to type to get out of the interpreter + before proceeding to installing &SCons;. + + </para> + + <para> + + If Python is not installed on your system, + you will see an error message + stating something like "command not found" + (on UNIX or Linux) + or "'python' is not recognized + as an internal or external command, operable progam or batch file" + (on Windows). + In that case, you need to install Python + before you can install &SCons;. + + </para> + + <para> + + The standard location for information + about downloading and installing Python is + <ulink url="http://www.python.org/download/">http://www.python.org/download/</ulink>. + See that page for information about + how to download and install Python on your system. + + </para> + + </section> + + <section> + <title>Installing &SCons; From Pre-Built Packages</title> + + <para> + + &SCons; comes pre-packaged for installation on a number of systems, + including Linux and Windows systems. + You do not need to read this entire section, + you should only need to read the section + appropriate to the type of system you're running on. + + </para> + + <section> + <title>Installing &SCons; on Red Hat (and Other RPM-based) Linux Systems</title> + + <para> + + &SCons; comes in RPM (Red Hat Package Manager) format, + pre-built and ready to install on Red Hat Linux, + or any other Linux distribution that uses RPM. + Your distribution may + already have an &SCons; RPM built specifically for it; + many do, including SuSe, Mandrake and Fedora. + You can check for the availability of an &SCons; RPM + on your distribution's download servers, + or by consulting an RPM search site like + <ulink url="http://www.rpmfind.net/">http://www.rpmfind.net/</ulink> or + <ulink url="http://rpm.pbone.net/">http://rpm.pbone.net/</ulink>. + + </para> + + <para> + + If your Linux distribution does not already have + a specific &SCons; RPM file, + you can download and install from the + generic RPM provided by the &SCons; project. + This will install the + SCons script(s) in <filename>/usr/bin</filename>, + and the SCons library modules in + <filename>/usr/lib/scons</filename>. + + </para> + + <para> + + To install from the command line, simply download the + appropriate <filename>.rpm</filename> file, + and then run: + + </para> + + <screen> + # <userinput>rpm -Uvh scons-0.96-1.noarch.rpm</userinput> + </screen> + + <para> + + Or, you can use a graphical RPM package manager + like <application>gnorpm</application>. + See your package manager application's documention + for specific instructions about + how to use it to install a downloaded RPM. + + </para> + + </section> + + <section> + <title>Installing &SCons; on Debian Linux Systems</title> + + <para> + + Debian Linux systems use a different package management + format that also makes it very easy to install &SCons;. + + </para> + + <para> + + If your system is connected to the Internet, + you can install the latest official Debian package + by running: + + </para> + + <screen> + # <userinput>apt-get install scons</userinput> + </screen> + + <!-- + + <para> + + Alternatively, + you can download the Debian package built + by the &SCons; project + and install it manually by running: + + </para> + + <screen> + # <userinput>db-XXX scons-*.deb</userinput> + </screen> + + --> + + </section> + + <section> + <title>Installing &SCons; on Windows Systems</title> + + <para> + + &SCons; provides a Windows installer + that makes installation extremely easy. + Download the <filename>scons-0.95.win32.exe</filename> + file from the &SCons; download page at + <ulink url="http://www.scons.org/download.html">http://www.scons.org/download.html</ulink>. + Then all you need to is execute the file + (usually by clicking on its icon in Windows Explorer). + These will take you through a small + sequence of windows that will install + &SCons; on your system. + + <!-- + Things are a little more complicated + if you are using the Cygwin version of Python. + This is because Cygwin + tries to make a Windows system look more + POSIX-like (or UNIX-like or Linux-like, if you prefer) + by having the Cygwin utilities, + including Cygwin Python, + interpret file name arguments on the command line + using the forward-slash (<filename>/</filename>) + as the directory separator, + instead of the normal Windows behavior of the + backslash (<filename>\</filename>) as the directory separator. + --> + + </para> + + <!-- + + <section> + <title>Installing &SCons; on Windows Systems Without Cygwin Python</title> + + <para> + + XXX + + </para> + + </section> + + <section> + <title>Installing &SCons; on Windows Systems With Cygwin Python</title> + + <para> + + XXX + + </para> + + </section> + + --> + + </section> + + </section> + + <section> + <title>Building and Installing &SCons; on Any System</title> + + <para> + + If a pre-built &SCons; package is not available for your system, + then you can still easily build and install &SCons; using the native + Python <filename>distutils</filename> package. + + </para> + + <para> + + The first step is to download either the + <filename>scons-__VERSION__.tar.gz</filename> + or <filename>scons-__VERSION__.zip</filename>, + which are available from the SCons download page at + <ulink url="http://www.scons.org/download.html">http://www.scons.org/download.html</ulink>. + + </para> + + <para> + + Unpack the archive you downloaded, + using a utility like <application>tar</application> + on Linux or UNIX, + or <application>WinZip</application> on Windows. + This will create a directory called + <filename>scons-__VERSION__</filename>, + usually in your local directory. + Then change your working directory to that directory + and install &SCons; by executing the following commands: + + </para> + + <screen> + # <userinput>cd scons-__VERSION__</userinput> + # <userinput>python setup.py install</userinput> + </screen> + + <para> + + This will build &SCons;, + install the <application>scons</application> script + in the default system scripts directory + (<filename>/usr/local/bin</filename> or + <filename>C:\Python2.2\Scripts</filename>), + and will install the &SCons; build engine + in an appropriate stand-alone library directory + (<filename>/usr/local/lib/scons</filename> or + <filename>C:\Python2.2\scons</filename>). + Because these are system directories, + you may need root (on Linux or UNIX) or Administrator (on Windows) + privileges to install &SCons; like this. + + </para> + + <section> + <title>Building and Installing &SCons; Without Administrative Privileges</title> + + <para> + + If you don't have the right privileges to install &SCons; + in a system location, + you can install it in a location of your choosing + by specifying the <literal>--prefix=</literal> option: + + </para> + + <screen> + # <userinput>python setup.py install --prefix=$HOME</userinput> + </screen> + + <para> + + This would install &SCons; in appropriate locations + relative to the user's <literal>$HOME</literal> directory, + the <application>scons</application> script in + <filename>$HOME/bin</filename> + and the build engine in + <filename>$HOME/lib/scons</filename>. + You may, of course, specify any other location you prefer. + + </para> + + </section> + + <!-- + + <section> + <title>Building and Installing &SCons; in the Standard Python Library Directories</title> + + <para> + + XXX + + </para> + + </section> + + --> + + <section> + <title>Building and Installing Multiple Versions of &SCons; Side-by-Side</title> + + <para> + + The &SCons; <filename>setup.py</filename> script + has some extensions that support + easy installation of multiple versions of &SCons; + in side-by-side locations. + This makes it easier to download and + experiment with different versions of &SCons; + before moving your official build process to a new version, + for example. + + </para> + + <para> + + To install &SCons; in a version-specific location, + add the <option>--version-lib</option> option + when you call <filename>setup.py</filename>: + + </para> + + <screen> + # <userinput>python setup.py install --version-lib</userinput> + </screen> + + <para> + + This will install the &SCons; build engine + in the + <filename>/usr/lib/scons-__VERSION__</filename> + or + <filename>C:\Python2.2\scons-__VERSION__</filename> + directory, for example. + You can also specify <option>--prefix=</option>, + in which case <filename>setup.py</filename> + will install the build engine + in a version-specific directory + relative to the specified prefix. + + </para> + + <para> + + If you use the <option>--version-lib</option> option + the first time you install &SCons;, + you do not need to specify it each time you install + a new version. + The &SCons; <filename>setup.py</filename> script + will detect the version-specific directory name(s) + and assume you want to install all versions + in version-specific directories. + You can override that assumption in the future + by explicitly specifying the <option>--standalone-lib</option> option. + + </para> + + </section> + + </section> + + <!-- + + <section> + <title>Python Basics</title> + + <para> + + This section will provide a brief overview of + the Python programming language. + Skip this section if you are already familiar with Python + (or you're really intent on diving into &SCons; + and just picking up things as you go). + + </para> + + <para> + + Python has a lot of good + documentation freely available on-line + to help you get started. + The standard tutorial is available at XXX. + + + </para> + + <para> + + Python is very easy to pick up. + + </para> + + <para> + + Python variables must be assigned to before they can be referenced. + + </para> + + <para> + + Assignment is like most programming languages: + + x = 1 + 2 + z = 3 * x + + </para> + + <para> + + Function calls look like most language function calls: + + a = f(g) + + </para> + + <para> + + Define functions like so: + + def func(arg1, arg2): + return arg1 * arg 2 + + The number of parameters + + </para> + + <para> + + Strings can be enclosed in single quotes or double quotes, + backslashes are used to escape characters, + triple-quote syntax lets you include quotes and newlines, + raw strings begin with 'r'. + + </para> + + <para> + + Lists are enclosed in square brackets, + list items are separated by commas. + List references use square brackets and integer index values, + slice notation lets you select, delete or replace a range. + + </para> + + <para> + + Dictionaries (hashes) are enclosed in curly brackets, + : separates keys from values, + , separates items. + Dictionary values are referenced using square brackets. + + </para> + + <para> + + Access class attributes (including methods) using a '.'. + + </para> + + <para> + + if: statements look like + + elif: statements look like + + else: statements look like + + </para> + + <para> + + for: statements look like + + while: statements look like + + break statements look like + + continue statements look like + + </para> + + <para> + + pass + + </para> + + </section> + + --> diff --git a/doc/user/builders-built-in.in b/doc/user/builders-built-in.in index 1d00a10..1c7ed9f 100644 --- a/doc/user/builders-built-in.in +++ b/doc/user/builders-built-in.in @@ -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 @@ -284,9 +284,9 @@ </para> - <literallayout> + <programlisting> StaticObject('file.c') - </literallayout> + </programlisting> <para> @@ -363,9 +363,9 @@ </para> - <literallayout> + <programlisting> SharedObject('file.c') - </literallayout> + </programlisting> <para> @@ -461,9 +461,9 @@ </para> - <literallayout> + <programlisting> StaticLibrary(['file.c', 'another.c']) - </literallayout> + </programlisting> <para> @@ -535,9 +535,9 @@ </para> - <literallayout> + <programlisting> SharedLibrary(['file.c', 'another.c']) - </literallayout> + </programlisting> <para> @@ -612,9 +612,9 @@ XXX </programlisting> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> @@ -631,9 +631,9 @@ XXX </programlisting> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> @@ -662,9 +662,9 @@ XXX </programlisting> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> @@ -692,9 +692,9 @@ XXX </programlisting> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> @@ -846,10 +846,10 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q .</userinput> zip /home/my/project/zip.out file1 file2 - </literallayout> + </screen> </section> @@ -895,9 +895,9 @@ </para> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> @@ -916,9 +916,9 @@ env.Jar(target = '', source = 'classes') </programlisting> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> @@ -935,9 +935,9 @@ XXX </programlisting> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> @@ -954,9 +954,9 @@ XXX </programlisting> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> diff --git a/doc/user/builders-built-in.sgml b/doc/user/builders-built-in.sgml index 3afbf19..767e1d2 100644 --- a/doc/user/builders-built-in.sgml +++ b/doc/user/builders-built-in.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 @@ -142,12 +142,12 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o goodbye.o goodbye.c cc -c -o hello.o hello.c cc -o hello hello.o goodbye.o -L/usr/dir1 -Ldir2 -lfoo1 -lfoo2 - </literallayout> + </screen> <para> @@ -155,12 +155,12 @@ </para> - <literallayout> + <screen> C:\><userinput>scons -Q</userinput> cl /nologo /c goodbye.c /Fogoodbye.obj cl /nologo /c hello.c /Fohello.obj link /nologo /OUT:hello.exe /LIBPATH:\usr\dir1 /LIBPATH:dir2 foo1.lib foo2.lib hello.obj goodbye.obj - </literallayout> + </screen> <para> @@ -282,9 +282,9 @@ </para> - <literallayout> + <programlisting> StaticObject('file.c') - </literallayout> + </programlisting> <para> @@ -361,9 +361,9 @@ </para> - <literallayout> + <programlisting> SharedObject('file.c') - </literallayout> + </programlisting> <para> @@ -459,9 +459,9 @@ </para> - <literallayout> + <programlisting> StaticLibrary(['file.c', 'another.c']) - </literallayout> + </programlisting> <para> @@ -533,9 +533,9 @@ </para> - <literallayout> + <programlisting> SharedLibrary(['file.c', 'another.c']) - </literallayout> + </programlisting> <para> @@ -610,9 +610,9 @@ XXX </programlisting> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> @@ -629,9 +629,9 @@ XXX </programlisting> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> @@ -660,9 +660,9 @@ XXX </programlisting> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> @@ -690,9 +690,9 @@ XXX </programlisting> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> @@ -725,11 +725,11 @@ env.Tar('out2', 'directory') </programlisting> - <literallayout> + <screen> % <userinput>scons -Q .</userinput> tar -c -f out1.tar file1 file2 tar -c -f out2.tar directory - </literallayout> + </screen> <para> @@ -751,10 +751,10 @@ env.Tar('out.tar.gz', 'directory') </programlisting> - <literallayout> + <screen> % <userinput>scons -Q .</userinput> tar -c -z -f out.tar.gz directory - </literallayout> + </screen> <para> @@ -772,10 +772,10 @@ env.Tar('out', 'directory') </programlisting> - <literallayout> + <screen> % <userinput>scons -Q .</userinput> tar -c -z -f out.tgz directory - </literallayout> + </screen> </section> @@ -807,10 +807,10 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q .</userinput> - zip("out.zip", ["file1", "file2"]) - </literallayout> + zip(["out.zip"], ["file1", "file2"]) + </screen> <para> @@ -820,10 +820,10 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q .</userinput> zip /home/my/project/zip.out file1 file2 - </literallayout> + </screen> </section> @@ -869,9 +869,9 @@ </para> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> @@ -890,9 +890,9 @@ env.Jar(target = '', source = 'classes') </programlisting> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> @@ -909,9 +909,9 @@ XXX </programlisting> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> @@ -928,9 +928,9 @@ XXX </programlisting> - <literallayout> + <screen> XXX - </literallayout> + </screen> </section> diff --git a/doc/user/builders-commands.in b/doc/user/builders-commands.in index 2c72bbd..f22fbd0 100644 --- a/doc/user/builders-commands.in +++ b/doc/user/builders-commands.in @@ -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 diff --git a/doc/user/builders-commands.sgml b/doc/user/builders-commands.sgml index 49ba08d..bef6ded 100644 --- a/doc/user/builders-commands.sgml +++ b/doc/user/builders-commands.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 @@ -74,10 +74,10 @@ env.Command('foo.out', 'foo.in', "sed 's/x/y/' < $SOURCE > $TARGET") </programlisting> - <literallayout> + <screen> % <userinput>scons -Q</userinput> sed 's/x/y/' < foo.in > foo.out - </literallayout> + </screen> <para> @@ -102,7 +102,7 @@ env.Command('foo.out', 'foo.in', build) </programlisting> - <literallayout> + <screen> % <userinput>scons -Q</userinput> - build("foo.out", "foo.in") - </literallayout> + build(["foo.out"], ["foo.in"]) + </screen> diff --git a/doc/user/builders-writing.in b/doc/user/builders-writing.in index d68b872..afd862b 100644 --- a/doc/user/builders-writing.in +++ b/doc/user/builders-writing.in @@ -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 diff --git a/doc/user/builders-writing.sgml b/doc/user/builders-writing.sgml index 4dddb55..9b211e2 100644 --- a/doc/user/builders-writing.sgml +++ b/doc/user/builders-writing.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 @@ -187,10 +187,10 @@ This functionality could be invoked as in the following example: </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> foobuild < file.input > file.foo - </literallayout> + </screen> <para> @@ -213,10 +213,12 @@ This functionality could be invoked as in the following example: env.Program('hello.c') </programlisting> - <literallayout> + <screen> % <userinput>scons -Q</userinput> AttributeError: SConsEnvironment instance has no attribute 'Program': - </literallayout> + File "SConstruct", line 4: + env.Program('hello.c') + </screen> <para> @@ -261,12 +263,12 @@ This functionality could be invoked as in the following example: </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> foobuild < file.input > file.foo cc -c -o hello.o hello.c cc -o hello hello.o - </literallayout> + </screen> </section> @@ -301,11 +303,11 @@ This functionality could be invoked as in the following example: env.Foo('file2') </programlisting> - <literallayout> + <screen> % <userinput>scons -Q</userinput> foobuild < file1.input > file1.foo foobuild < file2.input > file2.foo - </literallayout> + </screen> <para> @@ -439,10 +441,10 @@ This functionality could be invoked as in the following example: </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> - build_function("file.foo", "file.input") - </literallayout> + build_function(["file.foo"], ["file.input"]) + </screen> </section> @@ -574,10 +576,10 @@ This functionality could be invoked as in the following example: env.Foo('file') </programlisting> - <literallayout> + <screen> % <userinput>scons -Q</userinput> foobuild < file.input > file.foo - </literallayout> + </screen> <para> @@ -616,10 +618,10 @@ This functionality could be invoked as in the following example: env.Foo('file') </programlisting> - <literallayout> + <screen> % <userinput>scons -Q</userinput> foobuild file.foo new_target - file.input new_source - </literallayout> + </screen> <programlisting> bld = Builder(action = 'XXX', diff --git a/doc/user/caching.in b/doc/user/caching.in index 3c87761..552f3c1 100644 --- a/doc/user/caching.in +++ b/doc/user/caching.in @@ -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 diff --git a/doc/user/caching.sgml b/doc/user/caching.sgml index 223592e..eac6911 100644 --- a/doc/user/caching.sgml +++ b/doc/user/caching.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 @@ -80,7 +80,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o hello.o hello.c cc -o hello hello.o @@ -90,7 +90,7 @@ % <userinput>scons -Q</userinput> Retrieved `hello.o' from cache Retrieved `hello' from cache - </literallayout> + </screen> </section> @@ -122,7 +122,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o hello.o hello.c cc -o hello hello.o @@ -132,7 +132,7 @@ % <userinput>scons -Q --cache-show</userinput> cc -c -o hello.o hello.c cc -o hello hello.o - </literallayout> + </screen> <para> @@ -175,7 +175,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o hello.o hello.c cc -o hello hello.o @@ -191,7 +191,7 @@ % <userinput>scons -Q --cache-disable</userinput> cc -c -o hello.o hello.c cc -o hello hello.o - </literallayout> + </screen> </section> @@ -226,7 +226,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q --cache-disable</userinput> cc -c -o hello.o hello.c cc -o hello hello.o @@ -244,7 +244,7 @@ % <userinput>scons -Q</userinput> Retrieved `hello.o' from cache Retrieved `hello' from cache - </literallayout> + </screen> <para> diff --git a/doc/user/command-line.in b/doc/user/command-line.in index 70c7ca7..9d69b21 100644 --- a/doc/user/command-line.in +++ b/doc/user/command-line.in @@ -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 @@ -90,9 +90,9 @@ </para> - <literallayout> - $ setenv SCONSFLAGS "-Q" - </literallayout> + <screen> + $ <userinput>setenv SCONSFLAGS "-Q"</userinput> + </screen> <para> @@ -560,9 +560,9 @@ </para> - <literallayout> - % scons -Q debug=1 - </literallayout> + <screen> + % <userinput>scons -Q debug=1</userinput> + </screen> <para> @@ -920,7 +920,7 @@ <scons_example name="BoolOption"> <file name="SConstruct" printme="1"> opts = Options('custom.py') - opts.Add(BoolOption('RELEASE', 0, 'Set to build for release')) + opts.Add(BoolOption('RELEASE', 'Set to build for release', 0)) env = Environment(options = opts, CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) env.Program('foo.c') @@ -1024,7 +1024,7 @@ <scons_example name="EnumOption"> <file name="SConstruct" printme="1"> opts = Options('custom.py') - opts.Add(EnumOption('COLOR', 'red', 'Set background color', + opts.Add(EnumOption('COLOR', 'Set background color', 'red', allowed_values=('red', 'green', 'blue'))) env = Environment(options = opts, CPPDEFINES={'COLOR' : '"${COLOR}"'}) @@ -1078,7 +1078,7 @@ <scons_example name="EnumOption_map"> <file name="SConstruct" printme="1"> opts = Options('custom.py') - opts.Add(EnumOption('COLOR', 'red', 'Set background color', + opts.Add(EnumOption('COLOR', 'Set background color', 'red', allowed_values=('red', 'green', 'blue'), map={'navy':'blue'})) env = Environment(options = opts, @@ -1133,7 +1133,7 @@ <scons_example name="EnumOption_ic1"> <file name="SConstruct" printme="1"> opts = Options('custom.py') - opts.Add(EnumOption('COLOR', 'red', 'Set background color', + opts.Add(EnumOption('COLOR', 'Set background color', 'red', allowed_values=('red', 'green', 'blue'), map={'navy':'blue'}, ignorecase=1)) @@ -1173,7 +1173,7 @@ <scons_example name="EnumOption_ic2"> <file name="SConstruct" printme="1"> opts = Options('custom.py') - opts.Add(EnumOption('COLOR', 'red', 'Set background color', + opts.Add(EnumOption('COLOR', 'Set background color', 'red', allowed_values=('red', 'green', 'blue'), map={'navy':'blue'}, ignorecase=2)) @@ -1222,7 +1222,7 @@ <scons_example name="ListOption"> <file name="SConstruct" printme="1"> opts = Options('custom.py') - opts.Add(ListOption('COLORS', 0, 'List of colors', + opts.Add(ListOption('COLORS', 'List of colors', 0, ['red', 'green', 'blue'])) env = Environment(options = opts, CPPDEFINES={'COLORS' : '"${COLORS}"'}) @@ -1293,7 +1293,9 @@ <scons_example name="PathOption"> <file name="SConstruct" printme="1"> opts = Options('custom.py') - opts.Add(PathOption('CONFIG', '__ROOT__/etc/my_config', 'Path to configuration file')) + opts.Add(PathOption('CONFIG', + 'Path to configuration file', + '__ROOT__/etc/my_config')) env = Environment(options = opts, CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'}) env.Program('foo.c') @@ -1344,7 +1346,9 @@ <scons_example name="PackageOption"> <file name="SConstruct" printme="1"> opts = Options('custom.py') - opts.Add(PackageOption('PACKAGE', '__ROOT__/opt/location', 'Location package')) + opts.Add(PackageOption('PACKAGE', + 'Location package', + '__ROOT__/opt/location')) env = Environment(options = opts, CPPDEFINES={'PACKAGE' : '"$PACKAGE"'}) env.Program('foo.c') diff --git a/doc/user/command-line.sgml b/doc/user/command-line.sgml index 78c94e1..c488f7f 100644 --- a/doc/user/command-line.sgml +++ b/doc/user/command-line.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 @@ -64,7 +64,7 @@ - <literallayout> + <screen> % <userinput>scons</userinput> scons: Reading SConscript files ... scons: done reading SConscript files. @@ -74,7 +74,7 @@ % <userinput>export SCONSFLAGS="-Q"</userinput> % <userinput>scons</userinput> ... [build output] ... - </literallayout> + </screen> <para> @@ -83,9 +83,9 @@ </para> - <literallayout> - $ setenv SCONSFLAGS "-Q" - </literallayout> + <screen> + $ <userinput>setenv SCONSFLAGS "-Q"</userinput> + </screen> <para> @@ -131,7 +131,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o foo.o foo.c cc -o foo foo.o @@ -139,7 +139,7 @@ Don't forget to copy `bar' to the archive! cc -c -o bar.o bar.c cc -o bar bar.o - </literallayout> + </screen> <para> @@ -190,7 +190,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o hello.o hello.c cc -o hello hello.o @@ -199,7 +199,7 @@ % <userinput>scons -Q goodbye</userinput> cc -c -o goodbye.o goodbye.c cc -o goodbye goodbye.o - </literallayout> + </screen> <para> @@ -212,13 +212,13 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q .</userinput> cc -c -o goodbye.o goodbye.c cc -o goodbye goodbye.o cc -c -o hello.o hello.c cc -o hello hello.o - </literallayout> + </screen> <para> @@ -264,7 +264,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o prog1.o prog1.c cc -o prog1 prog1.o @@ -273,7 +273,7 @@ % <userinput>scons -Q .</userinput> cc -c -o prog2.o prog2.c cc -o prog2 prog2.o - </literallayout> + </screen> <para> @@ -296,7 +296,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o prog1/foo.o prog1/foo.c cc -c -o prog1/main.o prog1/main.c @@ -307,7 +307,7 @@ cc -c -o prog2/bar.o prog2/bar.c cc -c -o prog2/main.o prog2/main.c cc -o prog2/main prog2/main.o prog2/bar.o - </literallayout> + </screen> <para> @@ -331,7 +331,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> scons: *** No targets specified and no Default() targets found. Stop. % <userinput>scons -Q .</userinput> @@ -339,7 +339,7 @@ cc -o prog1 prog1.o cc -c -o prog2.o prog2.c cc -o prog2 prog2.o - </literallayout> + </screen> <section> <title>Getting at the List of Default Targets</title> @@ -376,7 +376,7 @@ </para> - <literallayout> + <screen> % <userinput>scons</userinput> scons: Reading SConscript files ... DEFAULT_TARGETS is ['prog1'] @@ -385,7 +385,7 @@ cc -c -o prog1.o prog1.c cc -o prog1 prog1.o scons: done building targets. - </literallayout> + </screen> <para> @@ -411,7 +411,7 @@ </para> - <literallayout> + <screen> % <userinput>scons</userinput> scons: Reading SConscript files ... DEFAULT_TARGETS is now ['prog1'] @@ -423,7 +423,7 @@ cc -c -o prog2.o prog2.c cc -o prog2 prog2.o scons: done building targets. - </literallayout> + </screen> <para> @@ -506,7 +506,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> BUILD_TARGETS is ['prog1'] cc -c -o prog1.o prog1.c @@ -521,7 +521,7 @@ Removed prog1 Removed prog2.o Removed prog2 - </literallayout> + </screen> </section> @@ -541,9 +541,9 @@ </para> - <literallayout> - % scons -Q debug=1 - </literallayout> + <screen> + % <userinput>scons -Q debug=1</userinput> + </screen> <para> @@ -591,7 +591,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q debug=0</userinput> cc -c -o prog.o prog.c cc -o prog prog.o @@ -602,7 +602,7 @@ cc -o prog prog.o % <userinput>scons -Q debug=1</userinput> scons: `.' is up to date. - </literallayout> + </screen> <para> @@ -691,12 +691,12 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q RELEASE=1</userinput> cc -DRELEASE_BUILD=1 -c -o bar.o bar.c cc -DRELEASE_BUILD=1 -c -o foo.o foo.c cc -o foo foo.o bar.o - </literallayout> + </screen> </section> @@ -737,7 +737,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q -h</userinput> RELEASE: Set to 1 to build for release @@ -745,7 +745,7 @@ actual: 0 Use scons -H for help about command-line options. - </literallayout> + </screen> <para> @@ -806,12 +806,12 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -DRELEASE_BUILD=1 -c -o bar.o bar.c cc -DRELEASE_BUILD=1 -c -o foo.o foo.c cc -o foo foo.o bar.o - </literallayout> + </screen> <para> @@ -830,12 +830,12 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -DRELEASE_BUILD=0 -c -o bar.o bar.c cc -DRELEASE_BUILD=0 -c -o foo.o foo.c cc -o foo foo.o bar.o - </literallayout> + </screen> </section> @@ -881,7 +881,7 @@ <programlisting> opts = Options('custom.py') - opts.Add(BoolOption('RELEASE', 0, 'Set to build for release')) + opts.Add(BoolOption('RELEASE', 'Set to build for release', 0)) env = Environment(options = opts, CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) env.Program('foo.c') @@ -896,15 +896,15 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q RELEASE=yes foo.o</userinput> cc -DRELEASE_BUILD=1 -c -o foo.o foo.c - </literallayout> + </screen> - <literallayout> + <screen> % <userinput>scons -Q RELEASE=t foo.o</userinput> cc -DRELEASE_BUILD=1 -c -o foo.o foo.c - </literallayout> + </screen> <para> @@ -927,15 +927,15 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q RELEASE=no foo.o</userinput> cc -DRELEASE_BUILD=0 -c -o foo.o foo.c - </literallayout> + </screen> - <literallayout> + <screen> % <userinput>scons -Q RELEASE=f foo.o</userinput> cc -DRELEASE_BUILD=0 -c -o foo.o foo.c - </literallayout> + </screen> <para> @@ -956,13 +956,13 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q RELEASE=bad_value foo.o</userinput> scons: *** Error converting option: RELEASE Invalid value for boolean option: bad_value File "SConstruct", line 4, in ? - </literallayout> + </screen> </section> @@ -988,7 +988,7 @@ <programlisting> opts = Options('custom.py') - opts.Add(EnumOption('COLOR', 'red', 'Set background color', + opts.Add(EnumOption('COLOR', 'Set background color', 'red', allowed_values=('red', 'green', 'blue'))) env = Environment(options = opts, CPPDEFINES={'COLOR' : '"${COLOR}"'}) @@ -1002,14 +1002,14 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q COLOR=red foo.o</userinput> cc -DCOLOR="red" -c -o foo.o foo.c % <userinput>scons -Q COLOR=blue foo.o</userinput> cc -DCOLOR="blue" -c -o foo.o foo.c % <userinput>scons -Q COLOR=green foo.o</userinput> cc -DCOLOR="green" -c -o foo.o foo.c - </literallayout> + </screen> <para> @@ -1020,12 +1020,12 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q COLOR=magenta foo.o</userinput> scons: *** Invalid value for option COLOR: magenta File "SConstruct", line 5, in ? - </literallayout> + </screen> <para> @@ -1043,7 +1043,7 @@ <programlisting> opts = Options('custom.py') - opts.Add(EnumOption('COLOR', 'red', 'Set background color', + opts.Add(EnumOption('COLOR', 'Set background color', 'red', allowed_values=('red', 'green', 'blue'), map={'navy':'blue'})) env = Environment(options = opts, @@ -1061,10 +1061,10 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q COLOR=navy foo.o</userinput> cc -DCOLOR="blue" -c -o foo.o foo.c - </literallayout> + </screen> <para> @@ -1076,7 +1076,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q COLOR=Red foo.o</userinput> scons: *** Invalid value for option COLOR: Red @@ -1089,7 +1089,7 @@ scons: *** Invalid value for option COLOR: nAvY File "SConstruct", line 5, in ? - </literallayout> + </screen> <para> @@ -1103,7 +1103,7 @@ <programlisting> opts = Options('custom.py') - opts.Add(EnumOption('COLOR', 'red', 'Set background color', + opts.Add(EnumOption('COLOR', 'Set background color', 'red', allowed_values=('red', 'green', 'blue'), map={'navy':'blue'}, ignorecase=1)) @@ -1118,7 +1118,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q COLOR=Red foo.o</userinput> cc -DCOLOR="Red" -c -o foo.o foo.c % <userinput>scons -Q COLOR=BLUE foo.o</userinput> @@ -1127,7 +1127,7 @@ cc -DCOLOR="blue" -c -o foo.o foo.c % <userinput>scons -Q COLOR=green foo.o</userinput> cc -DCOLOR="green" -c -o foo.o foo.c - </literallayout> + </screen> <para> @@ -1142,7 +1142,7 @@ <programlisting> opts = Options('custom.py') - opts.Add(EnumOption('COLOR', 'red', 'Set background color', + opts.Add(EnumOption('COLOR', 'Set background color', 'red', allowed_values=('red', 'green', 'blue'), map={'navy':'blue'}, ignorecase=2)) @@ -1162,14 +1162,14 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q COLOR=Red foo.o</userinput> cc -DCOLOR="red" -c -o foo.o foo.c % <userinput>scons -Q COLOR=nAvY foo.o</userinput> cc -DCOLOR="blue" -c -o foo.o foo.c % <userinput>scons -Q COLOR=GREEN foo.o</userinput> cc -DCOLOR="green" -c -o foo.o foo.c - </literallayout> + </screen> </section> @@ -1189,7 +1189,7 @@ <programlisting> opts = Options('custom.py') - opts.Add(ListOption('COLORS', 0, 'List of colors', + opts.Add(ListOption('COLORS', 'List of colors', 0, ['red', 'green', 'blue'])) env = Environment(options = opts, CPPDEFINES={'COLORS' : '"${COLORS}"'}) @@ -1205,12 +1205,12 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q COLORS=red,blue foo.o</userinput> - TypeError: sequence item 0: expected string, int found: + cc -DCOLORS="red blue" -c -o foo.o foo.c % <userinput>scons -Q COLORS=blue,green,red foo.o</userinput> - TypeError: sequence item 0: expected string, int found: - </literallayout> + cc -DCOLORS="blue green red" -c -o foo.o foo.c + </screen> <para> @@ -1222,12 +1222,12 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q COLORS=all foo.o</userinput> - TypeError: sequence item 0: expected string, int found: + cc -DCOLORS="red green blue" -c -o foo.o foo.c % <userinput>scons -Q COLORS=none foo.o</userinput> - TypeError: sequence item 0: expected string, int found: - </literallayout> + cc -DCOLORS="" -c -o foo.o foo.c + </screen> <para> @@ -1236,10 +1236,13 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q COLORS=magenta foo.o</userinput> - TypeError: sequence item 0: expected string, int found: - </literallayout> + + scons: *** Error converting option: COLORS + Invalid value(s) for option: magenta + File "SConstruct", line 5, in ? + </screen> </section> @@ -1260,7 +1263,9 @@ <programlisting> opts = Options('custom.py') - opts.Add(PathOption('CONFIG', '/etc/my_config', 'Path to configuration file')) + opts.Add(PathOption('CONFIG', + 'Path to configuration file', + '/etc/my_config')) env = Environment(options = opts, CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'}) env.Program('foo.c') @@ -1274,14 +1279,12 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q foo.o</userinput> - - scons: *** Path does not exist for option CONFIG: Path to configuration file - File "SConstruct", line 4, in ? + cc -DCONFIG_FILE="/etc/my_config" -c -o foo.o foo.c % <userinput>scons -Q CONFIG=/usr/local/etc/other_config foo.o</userinput> - cc -DCONFIG_FILE="/usr/local/etc/other_config" -c -o foo.o foo.c - </literallayout> + scons: `foo.o' is up to date. + </screen> </section> @@ -1304,7 +1307,9 @@ <programlisting> opts = Options('custom.py') - opts.Add(PackageOption('PACKAGE', '/opt/location', 'Location package')) + opts.Add(PackageOption('PACKAGE', + 'Location package', + '/opt/location')) env = Environment(options = opts, CPPDEFINES={'PACKAGE' : '"$PACKAGE"'}) env.Program('foo.c') @@ -1323,18 +1328,16 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q foo.o</userinput> - - scons: *** Path does not exist for option PACKAGE: Location package - File "SConstruct", line 4, in ? + cc -DPACKAGE="/opt/location" -c -o foo.o foo.c % <userinput>scons -Q PACKAGE=/usr/local/location foo.o</userinput> cc -DPACKAGE="/usr/local/location" -c -o foo.o foo.c % <userinput>scons -Q PACKAGE=yes foo.o</userinput> cc -DPACKAGE="1" -c -o foo.o foo.c % <userinput>scons -Q PACKAGE=no foo.o</userinput> cc -DPACKAGE="0" -c -o foo.o foo.c - </literallayout> + </screen> </section> diff --git a/doc/user/cons.in b/doc/user/cons.in index be02a51..6967b42 100644 --- a/doc/user/cons.in +++ b/doc/user/cons.in @@ -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 diff --git a/doc/user/cons.sgml b/doc/user/cons.sgml index be02a51..6967b42 100644 --- a/doc/user/cons.sgml +++ b/doc/user/cons.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 diff --git a/doc/user/copyright.in b/doc/user/copyright.in index 7f6059c..119f749 100644 --- a/doc/user/copyright.in +++ b/doc/user/copyright.in @@ -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 @@ -26,7 +26,7 @@ <blockquote> <para> - SCons User's Guide Copyright (c) 2003 Steven Knight + SCons User's Guide Copyright (c) 2004 Steven Knight </para> </blockquote> diff --git a/doc/user/copyright.sgml b/doc/user/copyright.sgml index 7f6059c..119f749 100644 --- a/doc/user/copyright.sgml +++ b/doc/user/copyright.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 @@ -26,7 +26,7 @@ <blockquote> <para> - SCons User's Guide Copyright (c) 2003 Steven Knight + SCons User's Guide Copyright (c) 2004 Steven Knight </para> </blockquote> diff --git a/doc/user/depends.in b/doc/user/depends.in index 43ec7f3..ab422b6 100644 --- a/doc/user/depends.in +++ b/doc/user/depends.in @@ -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 @@ -96,7 +96,7 @@ operating system on which the build is performed (as reported by C<uname </para> <section> - <title>Source File Signatures</title> + <title>Deciding When a Source File Has Changed: the &SourceSignatures; Function</title> <para> @@ -219,7 +219,7 @@ operating system on which the build is performed (as reported by C<uname </section> <section> - <title>Target File Signatures</title> + <title>Deciding When a Target File Has Changed: the &TargetSignatures; Function</title> <para> @@ -227,7 +227,7 @@ operating system on which the build is performed (as reported by C<uname &SCons; uses signatures to decide whether a target file is up to date or must be rebuilt. When a target file depends on another target file, - &SCons; allows you to separately configure + &SCons; allows you to configure separately how the signatures of "intermediate" target files are used when deciding if a dependent target file must be rebuilt. @@ -668,7 +668,7 @@ operating system on which the build is performed (as reported by C<uname </section> <section> - <title>The &Ignore; Method</title> + <title>Ignoring Dependencies: the &Ignore; Method</title> <para> @@ -707,7 +707,7 @@ operating system on which the build is performed (as reported by C<uname </scons_output> --> - <literallayout> + <screen> % <userinput>scons -Q hello</userinput> cc -c -o hello.o hello.c cc -o hello hello.o @@ -717,7 +717,7 @@ operating system on which the build is performed (as reported by C<uname [CHANGE THE CONTENTS OF hello.h] % <userinput>scons -Q hello</userinput> scons: `hello' is up to date. - </literallayout> + </screen> <para> @@ -748,7 +748,7 @@ operating system on which the build is performed (as reported by C<uname </section> <section> - <title>The &Depends; Method</title> + <title>Explicit Dependencies: the &Depends; Method</title> <para> @@ -770,7 +770,7 @@ operating system on which the build is performed (as reported by C<uname <!-- XXX mention that you can use arrays for target and source? --> - <literallayout> + <screen> % <userinput>scons -Q hello</userinput> cc -c hello.c -o hello.o cc -o hello hello.o @@ -781,7 +781,7 @@ operating system on which the build is performed (as reported by C<uname % <userinput>scons -Q hello</userinput> cc -c hello.c -o hello.o cc -o hello hello.o - </literallayout> + </screen> </section> diff --git a/doc/user/depends.sgml b/doc/user/depends.sgml index 09fb62d..b372885 100644 --- a/doc/user/depends.sgml +++ b/doc/user/depends.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 @@ -59,13 +59,13 @@ operating system on which the build is performed (as reported by C<uname - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o hello.o hello.c cc -o hello hello.o % <userinput>scons -Q</userinput> scons: `.' is up to date. - </literallayout> + </screen> <para> @@ -78,13 +78,13 @@ operating system on which the build is performed (as reported by C<uname </para> - <literallayout> + <screen> % <userinput>scons -Q hello</userinput> cc -c -o hello.o hello.c cc -o hello hello.o % <userinput>scons -Q hello</userinput> scons: `hello' is up to date. - </literallayout> + </screen> <para> @@ -95,7 +95,7 @@ operating system on which the build is performed (as reported by C<uname </para> <section> - <title>Source File Signatures</title> + <title>Deciding When a Source File Has Changed: the &SourceSignatures; Function</title> <para> @@ -130,14 +130,14 @@ operating system on which the build is performed (as reported by C<uname </para> - <literallayout> + <screen> % <userinput>scons -Q hello</userinput> cc -c -o hello.o hello.c cc -o hello hello.o % <userinput>touch hello.c</userinput> % <userinput>scons -Q hello</userinput> scons: `hello' is up to date. - </literallayout> + </screen> <para> @@ -155,7 +155,7 @@ operating system on which the build is performed (as reported by C<uname </para> - <literallayout> + <screen> % <userinput>scons -Q hello</userinput> cc -c -o hello.o hello.c cc -o hello hello.o @@ -164,7 +164,7 @@ operating system on which the build is performed (as reported by C<uname % <userinput>scons -Q hello</userinput> cc -c -o hello.o hello.c cc -o hello hello.o - </literallayout> + </screen> <para> @@ -210,7 +210,7 @@ operating system on which the build is performed (as reported by C<uname </para> - <literallayout> + <screen> % <userinput>scons -Q hello</userinput> cc -c -o hello.o hello.c cc -o hello hello.o @@ -218,14 +218,14 @@ operating system on which the build is performed (as reported by C<uname % <userinput>scons -Q hello</userinput> cc -c -o hello.o hello.c cc -o hello hello.o - </literallayout> + </screen> </section> </section> <section> - <title>Target File Signatures</title> + <title>Deciding When a Target File Has Changed: the &TargetSignatures; Function</title> <para> @@ -233,7 +233,7 @@ operating system on which the build is performed (as reported by C<uname &SCons; uses signatures to decide whether a target file is up to date or must be rebuilt. When a target file depends on another target file, - &SCons; allows you to separately configure + &SCons; allows you to configure separately how the signatures of "intermediate" target files are used when deciding if a dependent target file must be rebuilt. @@ -257,7 +257,7 @@ operating system on which the build is performed (as reported by C<uname </para> - <literallayout> + <screen> % <userinput>scons -Q hello</userinput> cc -c -o hello.o hello.c cc -o hello hello.o @@ -266,7 +266,7 @@ operating system on which the build is performed (as reported by C<uname % <userinput>scons -Q hello</userinput> cc -c -o hello.o hello.c cc -o hello hello.o - </literallayout> + </screen> <para> @@ -344,7 +344,7 @@ operating system on which the build is performed (as reported by C<uname </para> - <literallayout> + <screen> % <userinput>scons -Q hello</userinput> cc -c -o hello.o hello.c cc -o hello hello.o @@ -353,7 +353,7 @@ operating system on which the build is performed (as reported by C<uname % <userinput>scons -Q hello</userinput> cc -c -o hello.o hello.c scons: `hello' is up to date. - </literallayout> + </screen> <para> @@ -431,7 +431,7 @@ operating system on which the build is performed (as reported by C<uname </para> - <literallayout> + <screen> % <userinput>scons -Q hello</userinput> cc -I. -c -o hello.o hello.c cc -o hello hello.o @@ -442,7 +442,7 @@ operating system on which the build is performed (as reported by C<uname % <userinput>scons -Q hello</userinput> cc -I. -c -o hello.o hello.c cc -o hello hello.o - </literallayout> + </screen> <para> @@ -497,11 +497,11 @@ operating system on which the build is performed (as reported by C<uname </para> - <literallayout> + <screen> % <userinput>scons -Q hello</userinput> cc -Iinclude -I/home/project/inc -c -o hello.o hello.c cc -o hello hello.o - </literallayout> + </screen> <para> @@ -509,11 +509,11 @@ operating system on which the build is performed (as reported by C<uname </para> - <literallayout> + <screen> C:\><userinput>scons -Q hello.exe</userinput> cl /nologo /Iinclude /I\home\project\inc /c hello.c /Fohello.obj link /nologo /OUT:hello.exe hello.obj - </literallayout> + </screen> </section> @@ -565,13 +565,13 @@ operating system on which the build is performed (as reported by C<uname </para> - <literallayout> + <screen> % <userinput>scons -Q --implicit-cache hello</userinput> cc -c -o hello.o hello.c cc -o hello hello.o % <userinput>scons -Q hello</userinput> scons: `hello' is up to date. - </literallayout> + </screen> <para> @@ -624,13 +624,13 @@ operating system on which the build is performed (as reported by C<uname </para> - <literallayout> + <screen> % <userinput>scons -Q --implicit-deps-changed hello</userinput> cc -c -o hello.o hello.c cc -o hello hello.o % <userinput>scons -Q hello</userinput> scons: `hello' is up to date. - </literallayout> + </screen> <para> @@ -662,13 +662,13 @@ operating system on which the build is performed (as reported by C<uname </para> - <literallayout> + <screen> % <userinput>scons -Q --implicit-deps-unchanged hello</userinput> cc -c -o hello.o hello.c cc -o hello hello.o % <userinput>scons -Q hello</userinput> scons: `hello' is up to date. - </literallayout> + </screen> <para> @@ -689,7 +689,7 @@ operating system on which the build is performed (as reported by C<uname </section> <section> - <title>The &Ignore; Method</title> + <title>Ignoring Dependencies: the &Ignore; Method</title> <para> @@ -719,7 +719,7 @@ operating system on which the build is performed (as reported by C<uname </scons_output> --> - <literallayout> + <screen> % <userinput>scons -Q hello</userinput> cc -c -o hello.o hello.c cc -o hello hello.o @@ -729,7 +729,7 @@ operating system on which the build is performed (as reported by C<uname [CHANGE THE CONTENTS OF hello.h] % <userinput>scons -Q hello</userinput> scons: `hello' is up to date. - </literallayout> + </screen> <para> @@ -760,7 +760,7 @@ operating system on which the build is performed (as reported by C<uname </section> <section> - <title>The &Depends; Method</title> + <title>Explicit Dependencies: the &Depends; Method</title> <para> @@ -782,7 +782,7 @@ operating system on which the build is performed (as reported by C<uname <!-- XXX mention that you can use arrays for target and source? --> - <literallayout> + <screen> % <userinput>scons -Q hello</userinput> cc -c hello.c -o hello.o cc -o hello hello.o @@ -793,7 +793,7 @@ operating system on which the build is performed (as reported by C<uname % <userinput>scons -Q hello</userinput> cc -c hello.c -o hello.o cc -o hello hello.o - </literallayout> + </screen> </section> diff --git a/doc/user/environments.in b/doc/user/environments.in index 7e68b5e..47a3c44 100644 --- a/doc/user/environments.in +++ b/doc/user/environments.in @@ -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 @@ -410,7 +410,34 @@ environment undisturbed. <para> - A &consenv; is created by the &Environment; method. + A &consenv; is created by the &Environment; method: + + </para> + + <sconstruct> + env = Environment() + </sconstruct> + + <para> + + By default, &SCons; intializes every + new construction environment + with a set of &consvars; + based on the tools that it finds on your system, + plus the default set of builder methods + necessary for using those tools. + The construction variables + are initialized with values describing + the C compiler, + the Fortran compiler, + the linker, + etc., + as well as the command lines to invoke them. + + </para> + + <para> + When you initialize a construction environment you can set the values of the environment's &consvars; @@ -433,12 +460,17 @@ environment undisturbed. <para> - This example, rather than using the default, - explicitly specifies use of the + The construction environment in this example + is still initialized with the same default + construction variable values, + except that the user has explicitly specified use of the GNU C compiler &gcc;, and further specifies that the <literal>-O2</literal> (optimization level two) flag should be used when compiling the object file. + In other words, the explicit initializations of &CC; and &CCFLAGS; + override the default values in the newly-created + construction environment. So a run from this example would look like: </para> @@ -540,9 +572,6 @@ environment undisturbed. </para> - <programlisting> - </programlisting> - <scons_example name="ex4"> <file name="SConstruct" printme="1"> opt = Environment(CCFLAGS = '-O2') @@ -675,8 +704,7 @@ environment undisturbed. <para> A construction environment, however, - is actually a Python object with - associated methods, etc. + is actually an object with associated methods, etc. If you want to have direct access to only the dictionary of construction variables, you can fetch this using the &Dictionary; method: @@ -714,6 +742,116 @@ environment undisturbed. <command>scons -Q</command> </scons_output> + <para> + + If you want to loop through and print the values of + all of the construction variables in a construction environment, + the Python code to do that in sorted order might look something like: + + </para> + + <sconstruct> + env = Environment() + dict = env.Dictionary() + keys = dict.keys() + keys.sort() + for key in keys: + print "construction variable = '%s', value = '%s'" % (key, dict[key]) + </sconstruct> + + </section> + + <section> + <title>Expanding Values From a &ConsEnv;</title> + + <para> + + Another way to get information from + a construction environment. + is to use the &subst; method + on a string containing $-expansions + of construction variable names. + As a simple example, + the example from the previous + section that used + <literal>env['CC']</literal> + to fetch the value of &CC; + could also be written as: + + </para> + + <sconstruct> + env = Environment() + print "CC is:", env.subst('$CC') + </sconstruct> + + <para> + + The real advantage of using + &subst; to expand strings is + that construction variables + in the result get + re-expanded until + there are no expansions left in the string. + So a simple fetch of a value like + <varname>$CCCOM</varname>: + + </para> + + <sconstruct> + env = Environment(CCFLAGS = '-DFOO') + print "CCCOM is:", env['CCCOM'] + </sconstruct> + + <para> + + Will print the unexpanded value of &CCCOM;, + showing us the construction + variables that still need to be expanded: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + CCCOM is: $CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES + scons: `.' is up to date. + </screen> + + <para> + + Calling the &subst; method on <varname>$CCOM</varname>, + however: + + </para> + + <sconstruct> + env = Environment(CCFLAGS = '-DFOO') + print "CCCOM is:", env.subst('$CCCOM') + </sconstruct> + + <para> + + Will recursively expand all of + the $-prefixed construction variables, + showing us the final output: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + CCCOM is: gcc -DFOO -c -o + scons: `.' is up to date. + </screen> + + <para> + + (Note that because we're not expanding this + in the context of building something + there are no target or source files + for <varname>$TARGET</varname> and <varname>$SOURCES</varname> to expand. + + </para> + </section> <section> @@ -736,11 +874,82 @@ environment undisturbed. </para> - <scons_example name="ex7"> + <scons_example name="Replace1"> + <file name="SConstruct" printme="1"> + env = Environment(CCFLAGS = '-DDEFINE1') + env.Replace(CCFLAGS = '-DDEFINE2') + env.Program('foo.c') + </file> + <file name="foo.c"> + int main() { } + </file> + </scons_example> + + <para> + + The replacing value + (<literal>-DDEFINE2</literal> in the above example) + completely replaces the value in the + construction environment: + + </para> + + <scons_output example="Replace1"> + <command>scons -Q</command> + </scons_output> + + <para> + + You can safely call &Replace; + for construction variables that + don't exist in the construction environment: + + </para> + + <scons_example name="Replace-nonexistent"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Replace(NEW_VARIABLE = 'xyzzy') + print "NEW_VARIABLE =", env['NEW_VARIABLE'] + </file> + </scons_example> + + <para> + + In this case, + the construction variable simply + gets added to the construction environment: + + </para> + + <scons_output example="Replace-nonexistent"> + <command>scons -Q</command> + </scons_output> + + <para> + + Because the variables + aren't expanded until the construction environment + is actually used to build the targets, + and because &SCons; function and method calls + are order-independent, + the last replacement "wins" + and is used to build all targets, + regardless of the order in which + the calls to Replace() are + interspersed with calls to + builder methods: + + </para> + + <scons_example name="Replace2"> <file name="SConstruct" printme="1"> env = Environment(CCFLAGS = '-DDEFINE1') + print "CCFLAGS =", env['CCFLAGS'] env.Program('foo.c') + env.Replace(CCFLAGS = '-DDEFINE2') + print "CCFLAGS =", env['CCFLAGS'] env.Program('bar.c') </file> <file name="foo.c"> @@ -753,14 +962,33 @@ environment undisturbed. <para> - The replaced value completely overwrites + The timing of when the replacement + actually occurs relative + to when the targets get built + becomes apparent + if we run &scons; without the <literal>-Q</literal> + option: </para> - <scons_output example="ex7"> - <command>scons -Q</command> + <scons_output example="Replace2"> + <command>scons</command> </scons_output> + <para> + + Because the replacement occurs while + the &SConscript; files are being read, + the <literal>$CCFLAGS</literal> + variable has already been set to + <literal>-DDEFINE2</literal> + by the time the &foo_o; target is built, + even though the call to the &Replace; + method does not occur until later in + the &SConscript; file. + + </para> + </section> <section> @@ -785,10 +1013,42 @@ environment undisturbed. </file> </scons_example> + <para> + + &SCons; then supplies both the <literal>-DMY_VALUE</literal> and + <literal>-DLAST</literal> flags when compiling the object file: + + </para> + <scons_output example="ex8"> <command>scons -Q</command> </scons_output> + <para> + + If the construction variable doesn't already exist, + the &Append; method will create it: + + </para> + + <scons_example name="Append-nonexistent"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Append(NEW_VARIABLE = 'added') + print "NEW_VARIABLE =", env['NEW_VARIABLE'] + </file> + </scons_example> + + <para> + + Which yields: + + </para> + + <scons_output example="Append-nonexistent"> + <command>scons -Q</command> + </scons_output> + </section> <section> @@ -813,10 +1073,42 @@ environment undisturbed. </file> </scons_example> + <para> + + &SCons; then supplies both the <literal>-DFIRST</literal> and + <literal>-DMY_VALUE</literal> flags when compiling the object file: + + </para> + <scons_output example="ex9"> <command>scons -Q</command> </scons_output> + <para> + + If the construction variable doesn't already exist, + the &Prepend; method will create it: + + </para> + + <scons_example name="Prepend-nonexistent"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Prepend(NEW_VARIABLE = 'added') + print "NEW_VARIABLE =", env['NEW_VARIABLE'] + </file> + </scons_example> + + <para> + + Which yields: + + </para> + + <scons_output example="Prepend-nonexistent"> + <command>scons -Q</command> + </scons_output> + </section> </section> diff --git a/doc/user/environments.sgml b/doc/user/environments.sgml index eb9bf5b..1ff2fb3 100644 --- a/doc/user/environments.sgml +++ b/doc/user/environments.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 @@ -410,7 +410,34 @@ environment undisturbed. <para> - A &consenv; is created by the &Environment; method. + A &consenv; is created by the &Environment; method: + + </para> + + <programlisting> + env = Environment() + </programlisting> + + <para> + + By default, &SCons; intializes every + new construction environment + with a set of &consvars; + based on the tools that it finds on your system, + plus the default set of builder methods + necessary for using those tools. + The construction variables + are initialized with values describing + the C compiler, + the Fortran compiler, + the linker, + etc., + as well as the command lines to invoke them. + + </para> + + <para> + When you initialize a construction environment you can set the values of the environment's &consvars; @@ -428,21 +455,26 @@ environment undisturbed. <para> - This example, rather than using the default, - explicitly specifies use of the + The construction environment in this example + is still initialized with the same default + construction variable values, + except that the user has explicitly specified use of the GNU C compiler &gcc;, and further specifies that the <literal>-O2</literal> (optimization level two) flag should be used when compiling the object file. + In other words, the explicit initializations of &CC; and &CCFLAGS; + override the default values in the newly-created + construction environment. So a run from this example would look like: </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> gcc -O2 -c -o foo.o foo.c gcc -o foo foo.o - </literallayout> + </screen> <section> <title>Multiple &ConsEnvs;</title> @@ -470,13 +502,13 @@ environment undisturbed. dbg.Program('bar', 'bar.c') </programlisting> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -g -c -o bar.o bar.c cc -o bar bar.o cc -O2 -c -o foo.o foo.c cc -o foo foo.o - </literallayout> + </screen> <para> @@ -503,12 +535,12 @@ environment undisturbed. </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> scons: *** Two environments with different actions were specified for the same target: foo.o File "SConstruct", line 6, in ? - </literallayout> + </screen> <para> @@ -532,9 +564,6 @@ environment undisturbed. </para> <programlisting> - </programlisting> - - <programlisting> opt = Environment(CCFLAGS = '-O2') dbg = Environment(CCFLAGS = '-g') @@ -561,13 +590,13 @@ environment undisturbed. </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -g -c -o foo-dbg.o foo.c cc -o foo-dbg foo-dbg.o cc -O2 -c -o foo-opt.o foo.c cc -o foo-opt foo-opt.o - </literallayout> + </screen> </section> @@ -621,7 +650,7 @@ environment undisturbed. </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> gcc -c -o foo.o foo.c gcc -o foo foo.o @@ -629,7 +658,7 @@ environment undisturbed. gcc -o foo-dbg foo-dbg.o gcc -O2 -c -o foo-opt.o foo.c gcc -o foo-opt foo-opt.o - </literallayout> + </screen> </section> @@ -657,17 +686,16 @@ environment undisturbed. </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> CC is: cc scons: `.' is up to date. - </literallayout> + </screen> <para> A construction environment, however, - is actually a Python object with - associated methods, etc. + is actually an object with associated methods, etc. If you want to have direct access to only the dictionary of construction variables, you can fetch this using the &Dictionary; method: @@ -689,13 +717,13 @@ environment undisturbed. </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> key = OBJSUFFIX, value = .o key = LIBSUFFIX, value = .a key = PROGSUFFIX, value = scons: `.' is up to date. - </literallayout> + </screen> <para> @@ -703,13 +731,123 @@ environment undisturbed. </para> - <literallayout> + <screen> C:\><userinput>scons -Q</userinput> key = OBJSUFFIX, value = .obj key = LIBSUFFIX, value = .lib key = PROGSUFFIX, value = .exe scons: `.' is up to date. - </literallayout> + </screen> + + <para> + + If you want to loop through and print the values of + all of the construction variables in a construction environment, + the Python code to do that in sorted order might look something like: + + </para> + + <programlisting> + env = Environment() + dict = env.Dictionary() + keys = dict.keys() + keys.sort() + for key in keys: + print "construction variable = '%s', value = '%s'" % (key, dict[key]) + </programlisting> + + </section> + + <section> + <title>Expanding Values From a &ConsEnv;</title> + + <para> + + Another way to get information from + a construction environment. + is to use the &subst; method + on a string containing $-expansions + of construction variable names. + As a simple example, + the example from the previous + section that used + <literal>env['CC']</literal> + to fetch the value of &CC; + could also be written as: + + </para> + + <programlisting> + env = Environment() + print "CC is:", env.subst('$CC') + </programlisting> + + <para> + + The real advantage of using + &subst; to expand strings is + that construction variables + in the result get + re-expanded until + there are no expansions left in the string. + So a simple fetch of a value like + <varname>$CCCOM</varname>: + + </para> + + <programlisting> + env = Environment(CCFLAGS = '-DFOO') + print "CCCOM is:", env['CCCOM'] + </programlisting> + + <para> + + Will print the unexpanded value of &CCCOM;, + showing us the construction + variables that still need to be expanded: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + CCCOM is: $CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES + scons: `.' is up to date. + </screen> + + <para> + + Calling the &subst; method on <varname>$CCOM</varname>, + however: + + </para> + + <programlisting> + env = Environment(CCFLAGS = '-DFOO') + print "CCCOM is:", env.subst('$CCCOM') + </programlisting> + + <para> + + Will recursively expand all of + the $-prefixed construction variables, + showing us the final output: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + CCCOM is: gcc -DFOO -c -o + scons: `.' is up to date. + </screen> + + <para> + + (Note that because we're not expanding this + in the context of building something + there are no target or source files + for <varname>$TARGET</varname> and <varname>$SOURCES</varname> to expand. + + </para> </section> @@ -735,24 +873,117 @@ environment undisturbed. <programlisting> env = Environment(CCFLAGS = '-DDEFINE1') + env.Replace(CCFLAGS = '-DDEFINE2') + env.Program('foo.c') + </programlisting> + + <para> + + The replacing value + (<literal>-DDEFINE2</literal> in the above example) + completely replaces the value in the + construction environment: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -DDEFINE2 -c -o foo.o foo.c + cc -o foo foo.o + </screen> + + <para> + + You can safely call &Replace; + for construction variables that + don't exist in the construction environment: + + </para> + + <programlisting> + env = Environment() + env.Replace(NEW_VARIABLE = 'xyzzy') + print "NEW_VARIABLE =", env['NEW_VARIABLE'] + </programlisting> + + <para> + + In this case, + the construction variable simply + gets added to the construction environment: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + NEW_VARIABLE = xyzzy + scons: `.' is up to date. + </screen> + + <para> + + Because the variables + aren't expanded until the construction environment + is actually used to build the targets, + and because &SCons; function and method calls + are order-independent, + the last replacement "wins" + and is used to build all targets, + regardless of the order in which + the calls to Replace() are + interspersed with calls to + builder methods: + + </para> + + <programlisting> + env = Environment(CCFLAGS = '-DDEFINE1') + print "CCFLAGS =", env['CCFLAGS'] env.Program('foo.c') + env.Replace(CCFLAGS = '-DDEFINE2') + print "CCFLAGS =", env['CCFLAGS'] env.Program('bar.c') </programlisting> <para> - The replaced value completely overwrites + The timing of when the replacement + actually occurs relative + to when the targets get built + becomes apparent + if we run &scons; without the <literal>-Q</literal> + option: </para> - <literallayout> - % <userinput>scons -Q</userinput> + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript files ... + CCFLAGS = -DDEFINE1 + CCFLAGS = -DDEFINE2 + scons: done reading SConscript files. + scons: Building targets ... cc -DDEFINE2 -c -o bar.o bar.c cc -o bar bar.o - cc -DDEFINE1 -c -o foo.o foo.c + cc -DDEFINE2 -c -o foo.o foo.c cc -o foo foo.o - </literallayout> + scons: done building targets. + </screen> + + <para> + + Because the replacement occurs while + the &SConscript; files are being read, + the <literal>$CCFLAGS</literal> + variable has already been set to + <literal>-DDEFINE2</literal> + by the time the &foo_o; target is built, + even though the call to the &Replace; + method does not occur until later in + the &SConscript; file. + + </para> </section> @@ -773,11 +1004,43 @@ environment undisturbed. env.Program('foo.c') </programlisting> - <literallayout> + <para> + + &SCons; then supplies both the <literal>-DMY_VALUE</literal> and + <literal>-DLAST</literal> flags when compiling the object file: + + </para> + + <screen> % <userinput>scons -Q</userinput> cc -DMY_VALUE -DLAST -c -o foo.o foo.c cc -o foo foo.o - </literallayout> + </screen> + + <para> + + If the construction variable doesn't already exist, + the &Append; method will create it: + + </para> + + <programlisting> + env = Environment() + env.Append(NEW_VARIABLE = 'added') + print "NEW_VARIABLE =", env['NEW_VARIABLE'] + </programlisting> + + <para> + + Which yields: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + NEW_VARIABLE = added + scons: `.' is up to date. + </screen> </section> @@ -798,11 +1061,43 @@ environment undisturbed. env.Program('foo.c') </programlisting> - <literallayout> + <para> + + &SCons; then supplies both the <literal>-DFIRST</literal> and + <literal>-DMY_VALUE</literal> flags when compiling the object file: + + </para> + + <screen> % <userinput>scons -Q</userinput> cc -DFIRST -DMY_VALUE -c -o foo.o foo.c cc -o foo foo.o - </literallayout> + </screen> + + <para> + + If the construction variable doesn't already exist, + the &Prepend; method will create it: + + </para> + + <programlisting> + env = Environment() + env.Prepend(NEW_VARIABLE = 'added') + print "NEW_VARIABLE =", env['NEW_VARIABLE'] + </programlisting> + + <para> + + Which yields: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + NEW_VARIABLE = added + scons: `.' is up to date. + </screen> </section> diff --git a/doc/user/errors.in b/doc/user/errors.in index f83ab63..0891bf8 100644 --- a/doc/user/errors.in +++ b/doc/user/errors.in @@ -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 diff --git a/doc/user/errors.sgml b/doc/user/errors.sgml index f83ab63..0891bf8 100644 --- a/doc/user/errors.sgml +++ b/doc/user/errors.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 diff --git a/doc/user/example.in b/doc/user/example.in index f83ab63..0891bf8 100644 --- a/doc/user/example.in +++ b/doc/user/example.in @@ -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 diff --git a/doc/user/example.sgml b/doc/user/example.sgml index f83ab63..0891bf8 100644 --- a/doc/user/example.sgml +++ b/doc/user/example.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 diff --git a/doc/user/help.in b/doc/user/help.in index 087f3bf..d4b2caa 100644 --- a/doc/user/help.in +++ b/doc/user/help.in @@ -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 diff --git a/doc/user/help.sgml b/doc/user/help.sgml index 72e09aa..9db5bf0 100644 --- a/doc/user/help.sgml +++ b/doc/user/help.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 @@ -58,7 +58,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -h</userinput> scons: Reading SConscript files ... scons: done reading SConscript files. @@ -67,7 +67,7 @@ 'scons debug' to build the debug version. Use scons -H for help about command-line options. - </literallayout> + </screen> <para> diff --git a/doc/user/hierarchy.in b/doc/user/hierarchy.in index cc059ed..0c4563d 100644 --- a/doc/user/hierarchy.in +++ b/doc/user/hierarchy.in @@ -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 @@ -418,7 +418,7 @@ make no difference to the build. (Notice that the <literal>lib/foo1.o</literal> object file is built in the same directory as its source file. - See section XXX, below, + See <xref linkend="chap-separate">, below, for information about how to build the object file in a different subdirectory.) @@ -470,7 +470,7 @@ make no difference to the build. (As was the case with top-relative path names, notice that the <literal>/usr/joe/lib/foo1.o</literal> object file is built in the same directory as its source file. - See section XXX, below, + See <xref linkend="chap-separate">, below, for information about how to build the object file in a different subdirectory.) diff --git a/doc/user/hierarchy.sgml b/doc/user/hierarchy.sgml index 5db49a8..8281175 100644 --- a/doc/user/hierarchy.sgml +++ b/doc/user/hierarchy.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 @@ -315,7 +315,7 @@ make no difference to the build. </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o prog1/foo1.o prog1/foo1.c cc -c -o prog1/foo2.o prog1/foo2.c @@ -325,7 +325,7 @@ make no difference to the build. cc -c -o prog2/bar2.o prog2/bar2.c cc -c -o prog2/main.o prog2/main.c cc -o prog2/prog2 prog2/main.o prog2/bar1.o prog2/bar2.o - </literallayout> + </screen> <para> @@ -380,19 +380,19 @@ make no difference to the build. </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o lib/foo1.o lib/foo1.c cc -c -o src/prog/foo2.o src/prog/foo2.c cc -c -o src/prog/main.o src/prog/main.c cc -o src/prog/prog src/prog/main.o lib/foo1.o src/prog/foo2.o - </literallayout> + </screen> <para> (Notice that the <literal>lib/foo1.o</literal> object file is built in the same directory as its source file. - See section XXX, below, + See <xref linkend="chap-separate">, below, for information about how to build the object file in a different subdirectory.) @@ -421,20 +421,20 @@ make no difference to the build. </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o src/prog/foo2.o src/prog/foo2.c cc -c -o src/prog/main.o src/prog/main.c cc -c -o /usr/joe/lib/foo1.o /usr/joe/lib/foo1.c cc -o src/prog/prog src/prog/main.o /usr/joe/lib/foo1.o src/prog/foo2.o - </literallayout> + </screen> <para> (As was the case with top-relative path names, notice that the <literal>/usr/joe/lib/foo1.o</literal> object file is built in the same directory as its source file. - See section XXX, below, + See <xref linkend="chap-separate">, below, for information about how to build the object file in a different subdirectory.) @@ -714,13 +714,13 @@ make no difference to the build. </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o bar/bar.o bar/bar.c cc -c -o foo/foo.o foo/foo.c ar r libprog.a foo/foo.o bar/bar.o ranlib libprog.a - </literallayout> + </screen> </section> diff --git a/doc/user/install.in b/doc/user/install.in index 370ca9f..dfbb822 100644 --- a/doc/user/install.in +++ b/doc/user/install.in @@ -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 diff --git a/doc/user/install.sgml b/doc/user/install.sgml index b7555b7..430b336 100644 --- a/doc/user/install.sgml +++ b/doc/user/install.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 @@ -56,13 +56,13 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o hello.o hello.c cc -o hello hello.o % <userinput>scons -Q /usr/bin</userinput> Install file: "hello" as "/usr/bin/hello" - </literallayout> + </screen> <para> @@ -93,13 +93,13 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o hello.o hello.c cc -o hello hello.o % <userinput>scons -Q install</userinput> Install file: "hello" as "/usr/bin/hello" - </literallayout> + </screen> <section> <title>Installing Multiple Files in a Directory</title> @@ -142,7 +142,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q install</userinput> cc -c -o goodbye.o goodbye.c cc -o goodbye goodbye.o @@ -150,7 +150,7 @@ cc -c -o hello.o hello.c cc -o hello hello.o Install file: "hello" as "/usr/bin/hello" - </literallayout> + </screen> </section> @@ -182,12 +182,12 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q install</userinput> cc -c -o hello.o hello.c cc -o hello hello.o Install file: "hello" as "/usr/bin/hello-new" - </literallayout> + </screen> </section> @@ -224,7 +224,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q install</userinput> cc -c -o goodbye.o goodbye.c cc -o goodbye goodbye.o @@ -232,6 +232,6 @@ cc -c -o hello.o hello.c cc -o hello hello.o Install file: "hello" as "/usr/bin/hello-new" - </literallayout> + </screen> </section> diff --git a/doc/user/java.in b/doc/user/java.in new file mode 100644 index 0000000..6b22de8 --- /dev/null +++ b/doc/user/java.in @@ -0,0 +1,540 @@ +<!-- + + __COPYRIGHT__ + + 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> + + So far, we've been using examples of + building C and C++ programs + to demonstrate the features of &SCons;. + &SCons; also supports building Java programs, + but Java builds are handled slightly differently, + which reflects the ways in which + the Java compiler and tools + build programs differently than + other languages' tool chains. + + </para> + + <section> + <title>Building Java Class Files: the &Java; Builder</title> + + <para> + + The basic activity when programming in Java, + of course, is to take one or more <filename>.java</filename> files + containing Java source code + and to call the Java compiler + to turn them into one or more + <filename>.class</filename> files. + In &SCons;, you do this + by giving the &Java; Builder + a target directory in which + to put the <filename>.class</filename> files, + and a source directory that contains + the <filename>.java</filename> files: + + </para> + + <scons_example name="java"> + <file name="SConstruct" printme="1"> + Java('classes', 'src') + </file> + <file name="src/Example1.java"> + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="src/Example2.java"> + public class Example2 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="src/Example3.java"> + public class Example3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + </scons_example> + + <para> + + If the <filename>src</filename> directory contains + three <filename>.java</filename> source files, + then running &SCons; might look like this: + + </para> + + <scons_output example="java"> + <command>scons -Q</command> + </scons_output> + + <para> + + &SCons; will actually search the <filename>src</filename> + directory tree for all of the <filename>.java</filename> files. + The Java compiler will then create the + necessary class files in the <filename>classes</filename> subdirectory, + based on the class names found in the <filename>.java</filename> files. + + </para> + + </section> + + <section> + <title>How &SCons; Handles Java Dependencies</title> + + <scons_output example="java"> + <command>scons -Q</command> + <command>scons -Q classes</command> + </scons_output> + + </section> + + <section> + <title>Building Java Archive (<filename>.jar</filename>) Files: the &Jar; Builder</title> + + <para> + + After building the class files, + it's common to collect them into + a Java archive (<filename>.jar</filename>) file, + which you do by calling the &Jar; Builder method. + If you want to just collect all of the + class files within a subdirectory, + you can just specify that subdirectory + as the &Jar; source: + + </para> + + <scons_example name="jar1"> + <file name="SConstruct" printme="1"> + Java(target = 'classes', source = 'src') + Jar(target = 'test.jar', source = 'classes') + </file> + <file name="src/Example1.java"> + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="src/Example2.java"> + public class Example2 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="src/Example3.java"> + public class Example3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + </scons_example> + + <para> + + &SCons; will then pass that directory + to the &jar; command, + which will collect all of the underlying + <filename>.class</filename> files: + + </para> + + <scons_output example="jar1"> + <command>scons -Q</command> + </scons_output> + + <para> + + If you want to keep all of the + <filename>.class</filename> files + for multiple programs in one location, + and only archive some of them in + each <filename>.jar</filename> file, + you can pass the &Jar; builder a + list of files as its source. + It's extremely simple to create multiple + <filename>.jar</filename> files this way, + using the lists of target class files created + by calls to the &Java; builder + as sources to the various &Jar; calls: + + </para> + + <scons_example name="jar2"> + <file name="SConstruct" printme="1"> + prog1_class_files = Java(target = 'classes', source = 'prog1') + prog2_class_files = Java(target = 'classes', source = 'prog2') + Jar(target = 'prog1.jar', source = prog1_class_files) + Jar(target = 'prog2.jar', source = prog2_class_files) + </file> + <file name="prog1/Example1.java"> + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="prog1/Example2.java"> + public class Example2 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="prog2/Example3.java"> + public class Example3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + <file name="prog2/Example4.java"> + public class Example4 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + </scons_example> + + <para> + + This will then create + <filename>prog1.jar</filename> + and <filename>prog2.jar</filename> + next to the subdirectories + that contain their <filename>.java</filename> files: + + </para> + + <scons_output example="jar2"> + <command>scons -Q</command> + </scons_output> + + </section> + + <section> + <title>Building C Header and Stub Files: the &JavaH; Builder</title> + + <para> + + You can generate C header and source files + for implementing native methods, + by using the &JavaH; Builder. + There are several ways of using the &JavaH Builder. + One typical invocation might look like: + + </para> + + <scons_example name="javah"> + <file name="SConstruct" printme="1"> + classes = Java(target = 'classes', source = 'src/pkg/sub') + JavaH(target = 'native', source = classes) + </file> + <file name="src/pkg/sub/Example1.java"> + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example2.java"> + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example3.java"> + package pkg.sub; + public class Example3 + { + public static void main(String[] args) + { + } + } + </file> + </scons_example> + + <para> + + The source is a list of class files generated by the + call to the &Java; Builder, + and the target is the output directory in + which we want the C header files placed. + The target + gets converted into the <option>-d</option> + when &SCons; runs &javah;: + + </para> + + <scons_output example="javah"> + <command>scons -Q</command> + </scons_output> + + <para> + + In this case, + the call to &javah; + will generate the header files + <filename>native/pkg_sub_Example1.h</filename>, + <filename>native/pkg_sub_Example2.h</filename> + and + <filename>native/pkg_sub_Example3.h</filename>. + Notice that &SCons; remembered that the class + files were generated with a target directory of + <filename>classes</filename>, + and that it then specified that target directory + as the <option>-classpath</option> option + to the call to &javah;. + + </para> + + <para> + + Although it's more convenient to use + the list of class files returned by + the &Java; Builder + as the source of a call to the &JavaH; Builder, + you <emphasis>can</emphasis> + specify the list of class files + by hand, if you prefer. + If you do, + you need to set the + &JAVACLASSDIR; construction variable + when calling &JavaH;: + + </para> + + <scons_example name="JAVACLASSDIR"> + <file name="SConstruct" printme="1"> + Java(target = 'classes', source = 'src/pkg/sub') + class_file_list = ['classes/pkg/sub/Example1.class', + 'classes/pkg/sub/Example2.class', + 'classes/pkg/sub/Example3.class'] + JavaH(target = 'native', source = class_file_list, JAVACLASSDIR = 'classes') + </file> + <file name="src/pkg/sub/Example1.java"> + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example2.java"> + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example3.java"> + package pkg.sub; + public class Example3 + { + public static void main(String[] args) + { + } + } + </file> + </scons_example> + + <para> + + The &JAVACLASSDIR; value then + gets converted into the <option>-classpath</option> + when &SCons; runs &javah;: + + </para> + + <scons_output example="JAVACLASSDIR"> + <command>scons -Q</command> + </scons_output> + + <para> + + Lastly, if you don't want a separate header file + generated for each source file, + you can specify an explicit File Node + as the target of the &JavaH; Builder: + + </para> + + <scons_example name="javah_file"> + <file name="SConstruct" printme="1"> + classes = Java(target = 'classes', source = 'src/pkg/sub') + JavaH(target = File('native.h'), source = classes) + </file> + <file name="src/pkg/sub/Example1.java"> + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example2.java"> + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example3.java"> + package pkg.sub; + public class Example3 + { + public static void main(String[] args) + { + } + } + </file> + </scons_example> + + <para> + + Because &SCons; assumes by default + that the target of the &JavaH; builder is a directory, + you need to use the &File; function + to make sure that &SCons; doesn't + create a directory named <filename>native.h</filename>. + When a file is used, though, + &SCons; correctly converts the file name + into the &javah; <option>-o</option> option: + + </para> + + <scons_output example="javah_file"> + <command>scons -Q</command> + </scons_output> + + </section> + + <section> + <title>Building RMI Stub and Skeleton Class Files: the &RMIC; Builder</title> + + <para> + + You can generate Remote Method Invocation stubs + by using the &RMIC; Builder. + The source is a list of directories, + typically returned by a call to the &Java; Builder, + and the target is an output directory + where the <filename>_Stub.class</filename> + and <filename>_Skel.class</filename> files will + be placed: + + </para> + + <scons_example name="RMIC"> + <file name="SConstruct" printme="1"> + classes = Java(target = 'classes', source = 'src/pkg/sub') + RMIC(target = 'outdir', source = classes) + </file> + <file name="src/pkg/sub/Example1.java"> + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + </file> + <file name="src/pkg/sub/Example2.java"> + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + </file> + </scons_example> + + <para> + + As it did with the &JavaH; Builder, + &SCons; remembers the class directory + and passes it as the <option>-classpath</option> option + to &rmic: + + </para> + + <scons_output example="RMIC"> + <command>scons -Q</command> + </scons_output> + + <para> + + This example would generate the files + <filename>outdir/pkg/sub/Example1_Skel.class</filename>, + <filename>outdir/pkg/sub/Example1_Stub.class</filename>, + <filename>outdir/pkg/sub/Example2_Skel.class</filename> and + <filename>outdir/pkg/sub/Example2_Stub.class</filename>. + + </para> + + </section> diff --git a/doc/user/java.sgml b/doc/user/java.sgml new file mode 100644 index 0000000..98135b0 --- /dev/null +++ b/doc/user/java.sgml @@ -0,0 +1,354 @@ +<!-- + + __COPYRIGHT__ + + 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> + + So far, we've been using examples of + building C and C++ programs + to demonstrate the features of &SCons;. + &SCons; also supports building Java programs, + but Java builds are handled slightly differently, + which reflects the ways in which + the Java compiler and tools + build programs differently than + other languages' tool chains. + + </para> + + <section> + <title>Building Java Class Files: the &Java; Builder</title> + + <para> + + The basic activity when programming in Java, + of course, is to take one or more <filename>.java</filename> files + containing Java source code + and to call the Java compiler + to turn them into one or more + <filename>.class</filename> files. + In &SCons;, you do this + by giving the &Java; Builder + a target directory in which + to put the <filename>.class</filename> files, + and a source directory that contains + the <filename>.java</filename> files: + + </para> + + <programlisting> + Java('classes', 'src') + </programlisting> + + <para> + + If the <filename>src</filename> directory contains + three <filename>.java</filename> source files, + then running &SCons; might look like this: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java + </screen> + + <para> + + &SCons; will actually search the <filename>src</filename> + directory tree for all of the <filename>.java</filename> files. + The Java compiler will then create the + necessary class files in the <filename>classes</filename> subdirectory, + based on the class names found in the <filename>.java</filename> files. + + </para> + + </section> + + <section> + <title>How &SCons; Handles Java Dependencies</title> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java + % <userinput>scons -Q classes</userinput> + scons: `classes' is up to date. + </screen> + + </section> + + <section> + <title>Building Java Archive (<filename>.jar</filename>) Files: the &Jar; Builder</title> + + <para> + + After building the class files, + it's common to collect them into + a Java archive (<filename>.jar</filename>) file, + which you do by calling the &Jar; Builder method. + If you want to just collect all of the + class files within a subdirectory, + you can just specify that subdirectory + as the &Jar; source: + + </para> + + <programlisting> + Java(target = 'classes', source = 'src') + Jar(target = 'test.jar', source = 'classes') + </programlisting> + + <para> + + &SCons; will then pass that directory + to the &jar; command, + which will collect all of the underlying + <filename>.class</filename> files: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java + jar cf test.jar classes + </screen> + + <para> + + If you want to keep all of the + <filename>.class</filename> files + for multiple programs in one location, + and only archive some of them in + each <filename>.jar</filename> file, + you can pass the &Jar; builder a + list of files as its source. + It's extremely simple to create multiple + <filename>.jar</filename> files this way, + using the lists of target class files created + by calls to the &Java; builder + as sources to the various &Jar; calls: + + </para> + + <programlisting> + prog1_class_files = Java(target = 'classes', source = 'prog1') + prog2_class_files = Java(target = 'classes', source = 'prog2') + Jar(target = 'prog1.jar', source = prog1_class_files) + Jar(target = 'prog2.jar', source = prog2_class_files) + </programlisting> + + <para> + + This will then create + <filename>prog1.jar</filename> + and <filename>prog2.jar</filename> + next to the subdirectories + that contain their <filename>.java</filename> files: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath prog1 prog1/Example1.java prog1/Example2.java + javac -d classes -sourcepath prog2 prog2/Example3.java prog2/Example4.java + jar cf prog1.jar classes/Example1.class classes/Example2.class + jar cf prog2.jar classes/Example3.class classes/Example4.class + </screen> + + </section> + + <section> + <title>Building C Header and Stub Files: the &JavaH; Builder</title> + + <para> + + You can generate C header and source files + for implementing native methods, + by using the &JavaH; Builder. + There are several ways of using the &JavaH; Builder. + One typical invocation might look like: + + </para> + + <programlisting> + classes = Java(target = 'classes', source = 'src/pkg/sub') + JavaH(target = 'native', source = classes) + </programlisting> + + <para> + + The source is a list of class files generated by the + call to the &Java; Builder, + and the target is the output directory in + which we want the C header files placed. + The target + gets converted into the <option>-d</option> + when &SCons; runs &javah;: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java + javah -d native -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3 + </screen> + + <para> + + In this case, + the call to &javah; + will generate the header files + <filename>native/pkg_sub_Example1.h</filename>, + <filename>native/pkg_sub_Example2.h</filename> + and + <filename>native/pkg_sub_Example3.h</filename>. + Notice that &SCons; remembered that the class + files were generated with a target directory of + <filename>classes</filename>, + and that it then specified that target directory + as the <option>-classpath</option> option + to the call to &javah;. + + </para> + + <para> + + Although it's more convenient to use + the list of class files returned by + the &Java; Builder + as the source of a call to the &JavaH; Builder, + you <emphasis>can</emphasis> + specify the list of class files + by hand, if you prefer. + If you do, + you need to set the + &JAVACLASSDIR; construction variable + when calling &JavaH;: + + </para> + + <programlisting> + Java(target = 'classes', source = 'src/pkg/sub') + class_file_list = ['classes/pkg/sub/Example1.class', + 'classes/pkg/sub/Example2.class', + 'classes/pkg/sub/Example3.class'] + JavaH(target = 'native', source = class_file_list, JAVACLASSDIR = 'classes') + </programlisting> + + <para> + + The &JAVACLASSDIR; value then + gets converted into the <option>-classpath</option> + when &SCons; runs &javah;: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java + javah -d native -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3 + </screen> + + <para> + + Lastly, if you don't want a separate header file + generated for each source file, + you can specify an explicit File Node + as the target of the &JavaH; Builder: + + </para> + + <programlisting> + classes = Java(target = 'classes', source = 'src/pkg/sub') + JavaH(target = File('native.h'), source = classes) + </programlisting> + + <para> + + Because &SCons; assumes by default + that the target of the &JavaH; builder is a directory, + you need to use the &File; function + to make sure that &SCons; doesn't + create a directory named <filename>native.h</filename>. + When a file is used, though, + &SCons; correctly converts the file name + into the &javah; <option>-o</option> option: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java + javah -o native.h -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3 + </screen> + + </section> + + <section> + <title>Building RMI Stub and Skeleton Class Files: the &RMIC; Builder</title> + + <para> + + You can generate Remote Method Invocation stubs + by using the &RMIC; Builder. + The source is a list of directories, + typically returned by a call to the &Java; Builder, + and the target is an output directory + where the <filename>_Stub.class</filename> + and <filename>_Skel.class</filename> files will + be placed: + + </para> + + <programlisting> + classes = Java(target = 'classes', source = 'src/pkg/sub') + RMIC(target = 'outdir', source = classes) + </programlisting> + + <para> + + As it did with the &JavaH; Builder, + &SCons; remembers the class directory + and passes it as the <option>-classpath</option> option + to &rmic;: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java + rmic -d outdir -classpath classes pkg.sub.Example1 pkg.sub.Example2 + </screen> + + <para> + + This example would generate the files + <filename>outdir/pkg/sub/Example1_Skel.class</filename>, + <filename>outdir/pkg/sub/Example1_Stub.class</filename>, + <filename>outdir/pkg/sub/Example2_Skel.class</filename> and + <filename>outdir/pkg/sub/Example2_Stub.class</filename>. + + </para> + + </section> diff --git a/doc/user/less-simple.in b/doc/user/less-simple.in new file mode 100644 index 0000000..c0dafb1 --- /dev/null +++ b/doc/user/less-simple.in @@ -0,0 +1,589 @@ +<!-- + + __COPYRIGHT__ + + 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 &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"> + <command>scons -Q</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"> + <command>scons -Q</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(['main.c', 'file1.c', 'file2.c']) + </file> + <file name="main.c"> + int main() { printf("main.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"> + <command>scons -Q</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', ['main.c', 'file1.c', 'file2.c']) + </file> + <file name="main.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"> + <command>scons -Q</command> + </scons_output> + + <para> + + Or on Windows: + + </para> + + <scons_output example="ex3" os="win32"> + <command>scons -Q</command> + </scons_output> + + </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']) + </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 <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> + + <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> + list = Split("""main.c + file1.c + file2.c""") + Program('program', list) + </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> + list = Split('main.c file1.c file2.c') + Program(target = 'program', source = list) + </programlisting> + + <para> + + Because the keywords explicitly identify + what each argument is, + you can actually reverse the order if you prefer: + + </para> + + <programlisting> + list = Split('main.c file1.c file2.c') + Program(source = list, 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 <function>Program</function> 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"> + <command>scons -Q</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">, 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 only need to be built once, + even though the resulting object files are + each linked in to both of the resulting executable programs: + + </para> + + <scons_output example="ex5"> + <command>scons -Q</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 + 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> diff --git a/doc/user/less-simple.sgml b/doc/user/less-simple.sgml new file mode 100644 index 0000000..d3a6edc --- /dev/null +++ b/doc/user/less-simple.sgml @@ -0,0 +1,562 @@ +<!-- + + __COPYRIGHT__ + + 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 &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 -c -o hello.o 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> + cl /nologo /c hello.c /Fohello.obj + 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(['main.c', 'file1.c', 'file2.c']) + </programlisting> + + <para> + + A build of the above example would look like: + + </para> + + <screen> + % <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 main main.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', ['main.c', 'file1.c', 'file2.c']) + </programlisting> + + <para> + + On Linux, a build of this example would look like: + + </para> + + <screen> + % <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 + </screen> + + <para> + + Or on Windows: + + </para> + + <screen> + 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 + </screen> + + </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']) + </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 <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> + + <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> + list = Split("""main.c + file1.c + file2.c""") + Program('program', list) + </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> + list = Split('main.c file1.c file2.c') + Program(target = 'program', source = list) + </programlisting> + + <para> + + Because the keywords explicitly identify + what each argument is, + you can actually reverse the order if you prefer: + + </para> + + <programlisting> + list = Split('main.c file1.c file2.c') + Program(source = list, 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 <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> + + <para> + + &SCons; would then build the programs as follows: + + </para> + + <screen> + % <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 + </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">, 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 only need to be built 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 -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 + </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> diff --git a/doc/user/libraries.in b/doc/user/libraries.in index 7a88d6f..542cd13 100644 --- a/doc/user/libraries.in +++ b/doc/user/libraries.in @@ -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 @@ -94,7 +94,7 @@ </para> <section> - <title>Building Static Libraries Explicitly</title> + <title>Building Static Libraries Explicitly: the &StaticLibrary; Builder</title> <para> @@ -121,7 +121,7 @@ </section> <section> - <title>Building Shared (DLL) Libraries</title> + <title>Building Shared (DLL) Libraries: the &SharedLibrary; Builder</title> <para> @@ -198,7 +198,7 @@ <scons_example name="ex2"> <file name="SConstruct" printme="1"> Library('foo', ['f1.c', 'f2.c', 'f3.c']) - Program('prog.c', LIBS='foo', LIBPATH='.') + Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.') </file> <file name="f1.c"> int main() { printf("Hello, world!\n"); } @@ -253,6 +253,38 @@ </para> + <para> + + Note also that, + if you only have a single library to link with, + you can specify the library name in single string, + instead of a Python list, + so that: + + </para> + + <sconstruct> + Program('prog.c', LIBS='foo', LIBPATH='.') + </sconstruct> + + <para> + + is equivalent to: + + </para> + + <sconstruct> + Program('prog.c', LIBS=['foo'], LIBPATH='.') + </sconstruct> + + <para> + + This is similar to the way that &SCons; + handles either a string or a list to + specify a single source file. + + </para> + </section> <section> @@ -301,11 +333,19 @@ </para> <sconstruct> - LIBPATH = 'C:\lib;D:\lib' + LIBPATH = 'C:\\lib;D:\\lib' </sconstruct> <para> + (Note that Python requires that the backslash + separators in a Windows path name + be escaped within strings.) + + </para> + + <para> + When the linker is executed, &SCons; will create appropriate flags so that the linker will look for diff --git a/doc/user/libraries.sgml b/doc/user/libraries.sgml index a47446a..8e25c9a 100644 --- a/doc/user/libraries.sgml +++ b/doc/user/libraries.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 @@ -55,14 +55,14 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o f1.o f1.c cc -c -o f2.o f2.c cc -c -o f3.o f3.c ar r libfoo.a f1.o f2.o f3.o ranlib libfoo.a - </literallayout> + </screen> <para> @@ -71,13 +71,13 @@ </para> - <literallayout> + <screen> C:\><userinput>scons -Q</userinput> cl /nologo /c f1.c /Fof1.obj cl /nologo /c f2.c /Fof2.obj cl /nologo /c f3.c /Fof3.obj lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj - </literallayout> + </screen> <para> @@ -92,7 +92,7 @@ </para> <section> - <title>Building Static Libraries Explicitly</title> + <title>Building Static Libraries Explicitly: the &StaticLibrary; Builder</title> <para> @@ -117,7 +117,7 @@ </section> <section> - <title>Building Shared (DLL) Libraries</title> + <title>Building Shared (DLL) Libraries: the &SharedLibrary; Builder</title> <para> @@ -137,13 +137,13 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o f1.os f1.c cc -c -o f2.os f2.c cc -c -o f3.os f3.c cc -shared -o libfoo.so f1.os f2.os f3.os - </literallayout> + </screen> <para> @@ -151,13 +151,13 @@ </para> - <literallayout> + <screen> C:\><userinput>scons -Q</userinput> cl /nologo /c f1.c /Fof1.obj cl /nologo /c f2.c /Fof2.obj cl /nologo /c f3.c /Fof3.obj link /nologo /dll /out:foo.dll /implib:foo.lib f1.obj f2.obj f3.obj - </literallayout> + </screen> <para> @@ -190,7 +190,7 @@ <programlisting> Library('foo', ['f1.c', 'f2.c', 'f3.c']) - Program('prog.c', LIBS='foo', LIBPATH='.') + Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.') </programlisting> <para> @@ -209,7 +209,7 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o f1.o f1.c cc -c -o f2.o f2.c @@ -217,8 +217,8 @@ ar r libfoo.a f1.o f2.o f3.o ranlib libfoo.a cc -c -o prog.o prog.c - cc -o prog prog.o -L. -lfoo - </literallayout> + cc -o prog prog.o -L. -lfoo -lbar + </screen> <para> @@ -227,15 +227,15 @@ </para> - <literallayout> + <screen> C:\><userinput>scons -Q</userinput> cl /nologo /c f1.c /Fof1.obj cl /nologo /c f2.c /Fof2.obj cl /nologo /c f3.c /Fof3.obj lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj cl /nologo /c prog.c /Foprog.obj - link /nologo /OUT:prog.exe /LIBPATH:. foo.lib prog.obj - </literallayout> + link /nologo /OUT:prog.exe /LIBPATH:. foo.lib bar.lib prog.obj + </screen> <para> @@ -245,6 +245,38 @@ </para> + <para> + + Note also that, + if you only have a single library to link with, + you can specify the library name in single string, + instead of a Python list, + so that: + + </para> + + <programlisting> + Program('prog.c', LIBS='foo', LIBPATH='.') + </programlisting> + + <para> + + is equivalent to: + + </para> + + <programlisting> + Program('prog.c', LIBS=['foo'], LIBPATH='.') + </programlisting> + + <para> + + This is similar to the way that &SCons; + handles either a string or a list to + specify a single source file. + + </para> + </section> <section> @@ -288,11 +320,19 @@ </para> <programlisting> - LIBPATH = 'C:\lib;D:\lib' + LIBPATH = 'C:\\lib;D:\\lib' </programlisting> <para> + (Note that Python requires that the backslash + separators in a Windows path name + be escaped within strings.) + + </para> + + <para> + When the linker is executed, &SCons; will create appropriate flags so that the linker will look for @@ -302,11 +342,11 @@ </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o prog.o prog.c cc -o prog prog.o -L/usr/lib -L/usr/local/lib -lm - </literallayout> + </screen> <para> @@ -315,11 +355,11 @@ </para> - <literallayout> + <screen> C:\><userinput>scons -Q</userinput> cl /nologo /c prog.c /Foprog.obj link /nologo /OUT:prog.exe /LIBPATH:\usr\lib /LIBPATH:\usr\local\lib m.lib prog.obj - </literallayout> + </screen> <para> diff --git a/doc/user/main.in b/doc/user/main.in index 0fcf95c..3e0e047 100644 --- a/doc/user/main.in +++ b/doc/user/main.in @@ -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 @@ -35,6 +35,7 @@ <!ENTITY actions SYSTEM "actions.sgml"> <!ENTITY alias SYSTEM "alias.sgml"> <!ENTITY ant SYSTEM "ant.sgml"> + <!ENTITY build-install SYSTEM "build-install.sgml"> <!ENTITY builders-built-in SYSTEM "builders-built-in.sgml"> <!ENTITY builders-commands SYSTEM "builders-commands.sgml"> <!ENTITY builders-writing SYSTEM "builders-writing.sgml"> @@ -49,14 +50,18 @@ <!ENTITY example SYSTEM "example.sgml"> <!ENTITY help SYSTEM "help.sgml"> <!ENTITY hierarchy SYSTEM "hierarchy.sgml"> + <!ENTITY java SYSTEM "java.sgml"> <!ENTITY install SYSTEM "install.sgml"> + <!ENTITY less-simple SYSTEM "less-simple.sgml"> <!ENTITY libraries SYSTEM "libraries.sgml"> <!ENTITY make SYSTEM "make.sgml"> + <!ENTITY nodes SYSTEM "nodes.sgml"> <!ENTITY precious SYSTEM "precious.sgml"> <!ENTITY preface SYSTEM "preface.sgml"> <!ENTITY repositories SYSTEM "repositories.sgml"> <!ENTITY run SYSTEM "run.sgml"> <!ENTITY scanners SYSTEM "scanners.sgml"> + <!ENTITY sconf SYSTEM "sconf.sgml"> <!ENTITY separate SYSTEM "separate.sgml"> <!ENTITY simple SYSTEM "simple.sgml"> <!ENTITY sourcecode SYSTEM "sourcecode.sgml"> @@ -77,10 +82,10 @@ <edition>Revision &buildrevision; (&builddate;)</edition> - <pubdate>2003</pubdate> + <pubdate>2004</pubdate> <copyright> - <year>2003</year> + <year>2004</year> <holder>Steven Knight</holder> </copyright> @@ -92,9 +97,14 @@ </bookinfo> - <chapter id="chap-preface"> + <preface id="chap-preface"> <title>Preface</title> &preface; + </preface> + + <chapter id="chap-build-install"> + <title>Building and Installing &SCons;</title> + &build-install; </chapter> <chapter id="chap-simple"> @@ -102,11 +112,21 @@ &simple; </chapter> + <chapter id="chap-less-simple"> + <title>Less Simple Things to Do With Builds</title> + &less-simple; + </chapter> + <chapter id="chap-libraries"> <title>Building and Linking with Libraries</title> &libraries; </chapter> + <chapter id="chap-nodes"> + <title>Node Objects</title> + &nodes; + </chapter> + <chapter id="chap-depends"> <title>Dependencies</title> &depends; @@ -118,7 +138,7 @@ </chapter> <chapter id="chap-ENV"> - <title>Controlling the Environment Used to Execute Build Commands</title> + <title>Controlling the External Environment Used to Execute Build Commands</title> &ENV_file; </chapter> @@ -128,17 +148,17 @@ </chapter> <chapter id="chap-help"> - <title>Providing Build Help</title> + <title>Providing Build Help: the &Help; Function</title> &help; </chapter> <chapter id="chap-install"> - <title>Installing Files in Other Directories</title> + <title>Installing Files in Other Directories: the &Install; Builder</title> &install; </chapter> <chapter id="chap-precious"> - <title>Preventing Removal of Targets</title> + <title>Preventing Removal of Targets: the &Precious; Function</title> &precious; </chapter> @@ -172,14 +192,14 @@ </chapter> <chapter id="chap-builders-commands"> - <title>Not Writing a Builder: The &Command; Builder</title> + <title>Not Writing a Builder: the &Command; Builder</title> &builders-commands; </chapter> <!-- <chapter id="chap-actions"> - <title>SCons Actions</title> + <title>&SCons; Actions</title> &actions; </chapter> @@ -195,6 +215,11 @@ &repositories; </chapter> + <chapter id="chap-sconf"> + <title>Multi-Platform Configuration (&Autoconf; Functionality)</title> + &sconf; + </chapter> + <!-- <chapter id="chap-sourcecode"> @@ -214,6 +239,11 @@ &alias; </chapter> + <chapter id="chap-java"> + <title>Java Builds</title> + &java; + </chapter> + <!-- <chapter id="chap-run"> @@ -221,13 +251,13 @@ &run; </chapter> + --> + <chapter id="chap-troubleshooting"> <title>Troubleshooting</title> &troubleshoot; </chapter> - --> - <!-- AddPostAction() AddPreAction() diff --git a/doc/user/main.sgml b/doc/user/main.sgml index 0fcf95c..3e0e047 100644 --- a/doc/user/main.sgml +++ b/doc/user/main.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 @@ -35,6 +35,7 @@ <!ENTITY actions SYSTEM "actions.sgml"> <!ENTITY alias SYSTEM "alias.sgml"> <!ENTITY ant SYSTEM "ant.sgml"> + <!ENTITY build-install SYSTEM "build-install.sgml"> <!ENTITY builders-built-in SYSTEM "builders-built-in.sgml"> <!ENTITY builders-commands SYSTEM "builders-commands.sgml"> <!ENTITY builders-writing SYSTEM "builders-writing.sgml"> @@ -49,14 +50,18 @@ <!ENTITY example SYSTEM "example.sgml"> <!ENTITY help SYSTEM "help.sgml"> <!ENTITY hierarchy SYSTEM "hierarchy.sgml"> + <!ENTITY java SYSTEM "java.sgml"> <!ENTITY install SYSTEM "install.sgml"> + <!ENTITY less-simple SYSTEM "less-simple.sgml"> <!ENTITY libraries SYSTEM "libraries.sgml"> <!ENTITY make SYSTEM "make.sgml"> + <!ENTITY nodes SYSTEM "nodes.sgml"> <!ENTITY precious SYSTEM "precious.sgml"> <!ENTITY preface SYSTEM "preface.sgml"> <!ENTITY repositories SYSTEM "repositories.sgml"> <!ENTITY run SYSTEM "run.sgml"> <!ENTITY scanners SYSTEM "scanners.sgml"> + <!ENTITY sconf SYSTEM "sconf.sgml"> <!ENTITY separate SYSTEM "separate.sgml"> <!ENTITY simple SYSTEM "simple.sgml"> <!ENTITY sourcecode SYSTEM "sourcecode.sgml"> @@ -77,10 +82,10 @@ <edition>Revision &buildrevision; (&builddate;)</edition> - <pubdate>2003</pubdate> + <pubdate>2004</pubdate> <copyright> - <year>2003</year> + <year>2004</year> <holder>Steven Knight</holder> </copyright> @@ -92,9 +97,14 @@ </bookinfo> - <chapter id="chap-preface"> + <preface id="chap-preface"> <title>Preface</title> &preface; + </preface> + + <chapter id="chap-build-install"> + <title>Building and Installing &SCons;</title> + &build-install; </chapter> <chapter id="chap-simple"> @@ -102,11 +112,21 @@ &simple; </chapter> + <chapter id="chap-less-simple"> + <title>Less Simple Things to Do With Builds</title> + &less-simple; + </chapter> + <chapter id="chap-libraries"> <title>Building and Linking with Libraries</title> &libraries; </chapter> + <chapter id="chap-nodes"> + <title>Node Objects</title> + &nodes; + </chapter> + <chapter id="chap-depends"> <title>Dependencies</title> &depends; @@ -118,7 +138,7 @@ </chapter> <chapter id="chap-ENV"> - <title>Controlling the Environment Used to Execute Build Commands</title> + <title>Controlling the External Environment Used to Execute Build Commands</title> &ENV_file; </chapter> @@ -128,17 +148,17 @@ </chapter> <chapter id="chap-help"> - <title>Providing Build Help</title> + <title>Providing Build Help: the &Help; Function</title> &help; </chapter> <chapter id="chap-install"> - <title>Installing Files in Other Directories</title> + <title>Installing Files in Other Directories: the &Install; Builder</title> &install; </chapter> <chapter id="chap-precious"> - <title>Preventing Removal of Targets</title> + <title>Preventing Removal of Targets: the &Precious; Function</title> &precious; </chapter> @@ -172,14 +192,14 @@ </chapter> <chapter id="chap-builders-commands"> - <title>Not Writing a Builder: The &Command; Builder</title> + <title>Not Writing a Builder: the &Command; Builder</title> &builders-commands; </chapter> <!-- <chapter id="chap-actions"> - <title>SCons Actions</title> + <title>&SCons; Actions</title> &actions; </chapter> @@ -195,6 +215,11 @@ &repositories; </chapter> + <chapter id="chap-sconf"> + <title>Multi-Platform Configuration (&Autoconf; Functionality)</title> + &sconf; + </chapter> + <!-- <chapter id="chap-sourcecode"> @@ -214,6 +239,11 @@ &alias; </chapter> + <chapter id="chap-java"> + <title>Java Builds</title> + &java; + </chapter> + <!-- <chapter id="chap-run"> @@ -221,13 +251,13 @@ &run; </chapter> + --> + <chapter id="chap-troubleshooting"> <title>Troubleshooting</title> &troubleshoot; </chapter> - --> - <!-- AddPostAction() AddPreAction() diff --git a/doc/user/make.in b/doc/user/make.in index fe697a0..72b2df1 100644 --- a/doc/user/make.in +++ b/doc/user/make.in @@ -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 diff --git a/doc/user/make.sgml b/doc/user/make.sgml index fe697a0..72b2df1 100644 --- a/doc/user/make.sgml +++ b/doc/user/make.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 diff --git a/doc/user/nodes.in b/doc/user/nodes.in new file mode 100644 index 0000000..fd9846a --- /dev/null +++ b/doc/user/nodes.in @@ -0,0 +1,355 @@ +<!-- + + __COPYRIGHT__ + + 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> + + Internally, &SCons; represents all of the files + and directories it knows about as &Nodes;. + These internal objects + (not object <emphasis>files</emphasis>) + can be used in a variety of ways + to make your &SConscript; + files portable and easy to read. + + </para> + + <section> + <title>Builder Methods Return Lists of Target Nodes</title> + + <para> + + All builder methods return a list of + &Node; objects that identify the + target file or files that will be built. + These returned &Nodes; can be passed + as source files to other builder methods, + + </para> + + <para> + + For example, suppose that we want to build + the two object files that make up a program with different options. + This would mean calling the &Object; + builder once for each object file, + specifying the desired options: + + </para> + + <sconstruct> + Object('hello.c', CCFLAGS='-DHELLO') + Object('goodbye.c', CCFLAGS='-DGOODBYE') + </sconstruct> + + <para> + + One way to combine these object files + into the resulting program + would be to call the &Program; + builder with the names of the object files + listed as sources: + + </para> + + <sconstruct> + Object('hello.c', CCFLAGS='-DHELLO') + Object('goodbye.c', CCFLAGS='-DGOODBYE') + Program(['hello.o', 'goodbye.o']) + </sconstruct> + + <para> + + The problem with listing the names as strings + is that our &SConstruct; file is no longer portable + across operating systems. + It won't, for example, work on Windows + because the object files there would be + named &hello_obj; and &goodbye_obj;, + not &hello_o; and &goodbye_o;. + + </para> + + <para> + + A better solution is to assign the lists of targets + returned by the calls to the &Object; builder to variables, + which we can then concatenate in our + call to the &Program; builder: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + hello_list = Object('hello.c', CCFLAGS='-DHELLO') + goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE') + Program(hello_list + goodbye_list) + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="goodbye.c"> + int main() { printf("Goodbye, world!\n"); } + </file> + </scons_example> + + <para> + + This makes our &SConstruct; file portable again, + the build output on Linux looking like: + + </para> + + <scons_output example="ex1" os="posix"> + <command>scons -Q</command> + </scons_output> + + <para> + + And on Windows: + + </para> + + <scons_output example="ex1" os="win32"> + <command>scons -Q</command> + </scons_output> + + <para> + + We'll see examples of using the list of nodes + returned by builder methods throughout + the rest of this guide. + + </para> + + </section> + + <section> + <title>Explicitly Creating File and Directory Nodes</title> + + <para> + + It's worth mentioning here that + &SCons; maintains a clear distinction + between Nodes that represent files + and Nodes that represent directories. + &SCons; supports &File; and &Dir; + functions that, repectively, + return a file or directory Node: + + </para> + + <scons_example name="print"> + <file name="SConstruct" printme="1"> + hello_c = File('hello.c') + Program(hello_c) + + classes = Dir('classes') + Java(classes, 'src') + </file> + </scons_example> + + <para> + + Normally, you don't need to call + &File; or &Dir; directly, + because calling a builder method automatically + treats strings as the names of files or directories, + and translates them into + the Node objects for you. + The &File; and &Dir; functions can come in handy + in situations where you need to explicitly + instruct &SCons; about the type of Node being + passed to a builder or other function, + or unambiguously refer to a specific + file in a directory tree. + <!-- + (For an example of when you might + need to use &File; or &Dir; to + prevent ambiguous interpretation of a string + naming a file or directory, see + <xref linkend="chap-hierarchy">.) + --> + + </para> + + <para> + + There are also times when you may need to + refer to an entry in a file system + without knowing in advance + whether it's a file or a directory. + For those situations, + &SCons; also supports an &Entry; function, + which returns a Node + that can represent either a file or a directory. + + </para> + + <sconstruct> + xyzzy = Entry('xyzzy') + </sconstruct> + + <para> + + The returned <literal>xyzzy</literal> Node + will be turned into a file or directory Node + the first time it is used by a builder method + or other function that + requires one vs. the other. + + </para> + + </section> + + <section> + <title>Printing &Node; File Names</title> + + <para> + + One of the most common things you can do + with a Node is use it to print the + file name that the node represents. + For example, the following &SConstruct; file: + + </para> + + <scons_example name="print"> + <file name="SConstruct" printme="1"> + object_list = Object('hello.c') + program_list = Program(object_list) + print "The object file is:", object_list[0] + print "The program file is:", program_list[0] + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Would print the following file names on a POSIX system: + + </para> + + <scons_output example="print" os="posix"> + <command>scons -Q</command> + </scons_output> + + <para> + + And the following file names on a Windows system: + + </para> + + <scons_output example="print" os="win32"> + <command>scons -Q</command> + </scons_output> + + </section> + + <section> + <title>Using a &Node;'s File Name as a String</title> + + <para> + + Printing a &Node;'s name + as described in the previous section + works because the string representation of a &Node; + is the name of the file. + If you want to do something other than + print the name of the file, + you can fetch it by using the builtin Python + &str; function. + For example, if you want to use the Python + <function>os.path.exists</function> + to figure out whether a file + exists while the &SConstruct; file + is being read and executed, + you can fetch the string as follows: + + </para> + + <scons_example name="exists"> + <file name="SConstruct" printme="1"> + import os.path + program_list = Program('hello.c') + program_name = str(program_list[0]) + if not os.path.exists(program_name) + print program_name, "does not exist!" + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Which executes as follows on a POSIX system: + + </para> + + <scons_output example="print" os="posix"> + <command>scons -Q</command> + </scons_output> + + </section> + + <!-- + + <section> + <title>Fetching the Contents of a &Node;</title> + + <para> + + XXX Describe using read() and readlines() + when we add that as a public interface. + + </para> + + <scons_example name="exists"> + <file name="SConstruct" printme="1"> + hello_c = File('hello.c') + contents = hello_c.read() + print "contents are:" + print contents + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Which executes as follows on a POSIX system: + + </para> + + <scons_output example="print" os="posix"> + <command>scons -Q</command> + </scons_output> + + </section> + + --> diff --git a/doc/user/nodes.sgml b/doc/user/nodes.sgml new file mode 100644 index 0000000..8e24f14 --- /dev/null +++ b/doc/user/nodes.sgml @@ -0,0 +1,359 @@ +<!-- + + __COPYRIGHT__ + + 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> + + Internally, &SCons; represents all of the files + and directories it knows about as &Nodes;. + These internal objects + (not object <emphasis>files</emphasis>) + can be used in a variety of ways + to make your &SConscript; + files portable and easy to read. + + </para> + + <section> + <title>Builder Methods Return Lists of Target Nodes</title> + + <para> + + All builder methods return a list of + &Node; objects that identify the + target file or files that will be built. + These returned &Nodes; can be passed + as source files to other builder methods, + + </para> + + <para> + + For example, suppose that we want to build + the two object files that make up a program with different options. + This would mean calling the &Object; + builder once for each object file, + specifying the desired options: + + </para> + + <programlisting> + Object('hello.c', CCFLAGS='-DHELLO') + Object('goodbye.c', CCFLAGS='-DGOODBYE') + </programlisting> + + <para> + + One way to combine these object files + into the resulting program + would be to call the &Program; + builder with the names of the object files + listed as sources: + + </para> + + <programlisting> + Object('hello.c', CCFLAGS='-DHELLO') + Object('goodbye.c', CCFLAGS='-DGOODBYE') + Program(['hello.o', 'goodbye.o']) + </programlisting> + + <para> + + The problem with listing the names as strings + is that our &SConstruct; file is no longer portable + across operating systems. + It won't, for example, work on Windows + because the object files there would be + named &hello_obj; and &goodbye_obj;, + not &hello_o; and &goodbye_o;. + + </para> + + <para> + + A better solution is to assign the lists of targets + returned by the calls to the &Object; builder to variables, + which we can then concatenate in our + call to the &Program; builder: + + </para> + + <programlisting> + hello_list = Object('hello.c', CCFLAGS='-DHELLO') + goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE') + Program(hello_list + goodbye_list) + </programlisting> + + <para> + + This makes our &SConstruct; file portable again, + the build output on Linux looking like: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cc -DGOODBYE -c -o goodbye.o goodbye.c + cc -DHELLO -c -o hello.o hello.c + cc -o hello hello.o goodbye.o + </screen> + + <para> + + And on Windows: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + cl -DGOODBYE /c goodbye.c /Fogoodbye.obj + cl -DHELLO /c hello.c /Fohello.obj + link /nologo /OUT:hello.exe hello.obj goodbye.obj + </screen> + + <para> + + We'll see examples of using the list of nodes + returned by builder methods throughout + the rest of this guide. + + </para> + + </section> + + <section> + <title>Explicitly Creating File and Directory Nodes</title> + + <para> + + It's worth mentioning here that + &SCons; maintains a clear distinction + between Nodes that represent files + and Nodes that represent directories. + &SCons; supports &File; and &Dir; + functions that, repectively, + return a file or directory Node: + + </para> + + <programlisting> + hello_c = File('hello.c') + Program(hello_c) + + classes = Dir('classes') + Java(classes, 'src') + </programlisting> + + <para> + + Normally, you don't need to call + &File; or &Dir; directly, + because calling a builder method automatically + treats strings as the names of files or directories, + and translates them into + the Node objects for you. + The &File; and &Dir; functions can come in handy + in situations where you need to explicitly + instruct &SCons; about the type of Node being + passed to a builder or other function, + or unambiguously refer to a specific + file in a directory tree. + <!-- + (For an example of when you might + need to use &File; or &Dir; to + prevent ambiguous interpretation of a string + naming a file or directory, see + <xref linkend="chap-hierarchy">.) + --> + + </para> + + <para> + + There are also times when you may need to + refer to an entry in a file system + without knowing in advance + whether it's a file or a directory. + For those situations, + &SCons; also supports an &Entry; function, + which returns a Node + that can represent either a file or a directory. + + </para> + + <programlisting> + xyzzy = Entry('xyzzy') + </programlisting> + + <para> + + The returned <literal>xyzzy</literal> Node + will be turned into a file or directory Node + the first time it is used by a builder method + or other function that + requires one vs. the other. + + </para> + + </section> + + <section> + <title>Printing &Node; File Names</title> + + <para> + + One of the most common things you can do + with a Node is use it to print the + file name that the node represents. + For example, the following &SConstruct; file: + + </para> + + <programlisting> + hello_c = File('hello.c') + Program(hello_c) + + classes = Dir('classes') + Java(classes, 'src') + + object_list = Object('hello.c') + program_list = Program(object_list) + print "The object file is:", object_list[0] + print "The program file is:", program_list[0] + </programlisting> + + <para> + + Would print the following file names on a POSIX system: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + The object file is: hello.o + The program file is: hello + cc -c -o hello.o hello.c + cc -o hello hello.o + </screen> + + <para> + + And the following file names on a Windows system: + + </para> + + <screen> + C:\><userinput>scons -Q</userinput> + The object file is: hello.obj + The program file is: hello.exe + cl /nologo /c hello.c /Fohello.obj + link /nologo /OUT:hello.exe hello.obj + </screen> + + </section> + + <section> + <title>Using a &Node;'s File Name as a String</title> + + <para> + + Printing a &Node;'s name + as described in the previous section + works because the string representation of a &Node; + is the name of the file. + If you want to do something other than + print the name of the file, + you can fetch it by using the builtin Python + &str; function. + For example, if you want to use the Python + <function>os.path.exists</function> + to figure out whether a file + exists while the &SConstruct; file + is being read and executed, + you can fetch the string as follows: + + </para> + + <programlisting> + import os.path + program_list = Program('hello.c') + program_name = str(program_list[0]) + if not os.path.exists(program_name) + print program_name, "does not exist!" + </programlisting> + + <para> + + Which executes as follows on a POSIX system: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + The object file is: hello.o + The program file is: hello + cc -c -o hello.o hello.c + cc -o hello hello.o + </screen> + + </section> + + <!-- + + <section> + <title>Fetching the Contents of a &Node;</title> + + <para> + + XXX Describe using read() and readlines() + when we add that as a public interface. + + </para> + + <scons_example name="exists"> + <file name="SConstruct" printme="1"> + hello_c = File('hello.c') + contents = hello_c.read() + print "contents are:" + print contents + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Which executes as follows on a POSIX system: + + </para> + + <scons_output example="print" os="posix"> + <command>scons -Q</command> + </scons_output> + + </section> + + --> diff --git a/doc/user/precious.in b/doc/user/precious.in index 95a2c56..fb32f2b 100644 --- a/doc/user/precious.in +++ b/doc/user/precious.in @@ -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 diff --git a/doc/user/precious.sgml b/doc/user/precious.sgml index 4453d4b..6e80c85 100644 --- a/doc/user/precious.sgml +++ b/doc/user/precious.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 @@ -67,14 +67,14 @@ which the C<AfterBuild> method is called. </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o f1.o f1.c cc -c -o f2.o f2.c cc -c -o f3.o f3.c ar r libfoo.a f1.o f2.o f3.o ranlib libfoo.a - </literallayout> + </screen> <para> diff --git a/doc/user/preface.in b/doc/user/preface.in index 5e46f0a..190dad1 100644 --- a/doc/user/preface.in +++ b/doc/user/preface.in @@ -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 @@ -222,6 +222,44 @@ --> <section> + <title>A Caveat About This Guide's Completeness</title> + + <para> + + One word of warning as you read through this Guide: + Like too much Open Source software out there, + the &SCons; documentation lags the available features. + In other words, + there's a lot that &SCons; can do that + isn't yet covered in this User's Guide. + (Come to think of it, + that also describes a lot of proprietary software, doesn't it?) + + </para> + + <para> + + Although this User's Guide isn't as complete as we'd like it to be, + our development process does emphasize + making sure that the &SCons; man page is kept up-to-date + with new features. + So if you're trying to figure out how to do something + that &SCons; supports + but can't find enough (or any) information here, + it would be worth your while to look + at the man page to see if the information is covered there. + And if you do, + maybe you'd even consider contributing + a section to the User's Guide + so the next person looking for + that information won't have to + go through the same thing...? + + </para> + + </section> + + <section> <title>Acknowledgements</title> <para> @@ -274,7 +312,7 @@ and time people have contributed over the past few years. The "core team" of Chad Austin, Anthony Roach, Charles Crain, - Steve Leblanc, Gary Oerbrunner, Greg Spencer and Christoph Wiedemann + Steve Leblanc, Gary Oberbrunner, Greg Spencer and Christoph Wiedemann have been great about reviewing my (and other) changes and catching problems before they get in the code base. Of particular technical note: diff --git a/doc/user/preface.sgml b/doc/user/preface.sgml index 390d6a8..dfececd 100644 --- a/doc/user/preface.sgml +++ b/doc/user/preface.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 @@ -222,6 +222,44 @@ --> <section> + <title>A Caveat About This Guide's Completeness</title> + + <para> + + One word of warning as you read through this Guide: + Like too much Open Source software out there, + the &SCons; documentation lags the available features. + In other words, + there's a lot that &SCons; can do that + isn't yet covered in this User's Guide. + (Come to think of it, + that also describes a lot of proprietary software, doesn't it?) + + </para> + + <para> + + Although this User's Guide isn't as complete as we'd like it to be, + our development process does emphasize + making sure that the &SCons; man page is kept up-to-date + with new features. + So if you're trying to figure out how to do something + that &SCons; supports + but can't find enough (or any) information here, + it would be worth your while to look + at the man page to see if the information is covered there. + And if you do, + maybe you'd even consider contributing + a section to the User's Guide + so the next person looking for + that information won't have to + go through the same thing...? + + </para> + + </section> + + <section> <title>Acknowledgements</title> <para> @@ -274,7 +312,7 @@ and time people have contributed over the past few years. The "core team" of Chad Austin, Anthony Roach, Charles Crain, - Steve Leblanc, Gary Oerbrunner, Greg Spencer and Christoph Wiedemann + Steve Leblanc, Gary Oberbrunner, Greg Spencer and Christoph Wiedemann have been great about reviewing my (and other) changes and catching problems before they get in the code base. Of particular technical note: diff --git a/doc/user/repositories.in b/doc/user/repositories.in index 480ea3f..79d9a75 100644 --- a/doc/user/repositories.in +++ b/doc/user/repositories.in @@ -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 @@ -315,9 +315,9 @@ subdirectories under the repository tree. </para> - <literallayout> + <screen> % <userinput>scons -Q -Y /usr/repository1 -Y /usr/repository2</userinput> - </literallayout> + </screen> <para> @@ -407,13 +407,13 @@ subdirectories under the repository tree. <command>scons -Q -Y __ROOT__/usr/repository1</command> </scons_output> --> - <literallayout> + <screen> % <userinput>cd $HOME/build</userinput> % <userinput>edit hello.c</userinput> % <userinput>scons -Q -Y /usr/repository1</userinput> cc -c -o hello.o hello.c cc -o hello hello.o /usr/repository1/file1.o /usr/repository1/file2.o - </literallayout> + </screen> <para> @@ -438,12 +438,12 @@ subdirectories under the repository tree. </para> - <literallayout> + <screen> % <userinput>mkdir $HOME/build2</userinput> % <userinput>cd $HOME/build2</userinput> % <userinput>scons -Q -Y /usr/all/repository hello</userinput> scons: `hello' is up-to-date. - </literallayout> + </screen> <para> @@ -490,11 +490,11 @@ subdirectories under the repository tree. </para> - <literallayout> - % scons -Y /usr/all/repository hello + <screen> + % <userinput>scons -Y /usr/all/repository hello</userinput> Local copy of hello from /usr/all/repository/hello scons: `hello' is up-to-date. - </literallayout> + </screen> <para> diff --git a/doc/user/repositories.sgml b/doc/user/repositories.sgml index fdb8b5b..e728bc4 100644 --- a/doc/user/repositories.sgml +++ b/doc/user/repositories.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 @@ -234,11 +234,11 @@ subdirectories under the repository tree. </para> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o hello.o hello.c cc -o hello hello.o - </literallayout> + </screen> <para> @@ -251,13 +251,13 @@ subdirectories under the repository tree. - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o hello.o hello.c cc -o hello hello.o gcc -c /usr/repository1/hello.c -o hello.o gcc -o hello hello.o - </literallayout> + </screen> <para> @@ -269,11 +269,11 @@ subdirectories under the repository tree. - <literallayout> + <screen> % <userinput>scons -Q</userinput> cc -c -o hello.o hello.c cc -o hello hello.o - </literallayout> + </screen> <para> @@ -298,9 +298,9 @@ subdirectories under the repository tree. </para> - <literallayout> + <screen> % <userinput>scons -Q -Y /usr/repository1 -Y /usr/repository2</userinput> - </literallayout> + </screen> <para> @@ -343,14 +343,14 @@ subdirectories under the repository tree. - <literallayout> + <screen> % <userinput>cd /usr/repository1</userinput> % <userinput>scons -Q</userinput> cc -c -o file1.o file1.c cc -c -o file2.o file2.c cc -c -o hello.o hello.c cc -o hello hello.o file1.o file2.o - </literallayout> + </screen> <para> @@ -379,13 +379,13 @@ subdirectories under the repository tree. <command>scons -Q -Y __ROOT__/usr/repository1</command> </scons_output> --> - <literallayout> + <screen> % <userinput>cd $HOME/build</userinput> % <userinput>edit hello.c</userinput> % <userinput>scons -Q -Y /usr/repository1</userinput> cc -c -o hello.o hello.c cc -o hello hello.o /usr/repository1/file1.o /usr/repository1/file2.o - </literallayout> + </screen> <para> @@ -410,12 +410,12 @@ subdirectories under the repository tree. </para> - <literallayout> + <screen> % <userinput>mkdir $HOME/build2</userinput> % <userinput>cd $HOME/build2</userinput> % <userinput>scons -Q -Y /usr/all/repository hello</userinput> scons: `hello' is up-to-date. - </literallayout> + </screen> <para> @@ -457,11 +457,11 @@ subdirectories under the repository tree. </para> - <literallayout> - % scons -Y /usr/all/repository hello + <screen> + % <userinput>scons -Y /usr/all/repository hello</userinput> Local copy of hello from /usr/all/repository/hello scons: `hello' is up-to-date. - </literallayout> + </screen> <para> diff --git a/doc/user/run.in b/doc/user/run.in index 0d3e7f0..56b8fa2 100644 --- a/doc/user/run.in +++ b/doc/user/run.in @@ -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 diff --git a/doc/user/run.sgml b/doc/user/run.sgml index 0d3e7f0..56b8fa2 100644 --- a/doc/user/run.sgml +++ b/doc/user/run.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 diff --git a/doc/user/scanners.in b/doc/user/scanners.in index 254b433..946c058 100644 --- a/doc/user/scanners.in +++ b/doc/user/scanners.in @@ -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 diff --git a/doc/user/scanners.sgml b/doc/user/scanners.sgml index ee82b43..4632369 100644 --- a/doc/user/scanners.sgml +++ b/doc/user/scanners.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 diff --git a/doc/user/sconf.in b/doc/user/sconf.in new file mode 100644 index 0000000..309e862 --- /dev/null +++ b/doc/user/sconf.in @@ -0,0 +1,386 @@ +<!-- + + __COPYRIGHT__ + + 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> + + &SCons; has integrated support for multi-platform build configuration + similar to that offered by GNU &Autoconf;, + such as + figuring out what libraries or header files + are available on the local system. + This section describes how to use + this &SCons feature. + + </para> + + <note> + <para> + This chapter is still under development, + so not everything is explained as well as it should be. + See the &SCons; man page for additional information. + </para> + </note> + + <section> + <title>&Configure_Contexts;</title> + + <para> + + The basic framework for multi-platform build configuration + in &SCons; is to attach a &configure_context; to a + construction environment by calling the &Configure; function, + perform a number of checks for + libraries, functions, header files, etc., + and to then call the configure context's &Finish; method + to finish off the configuration: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env) + # Checks for libraries, header files, etc. go here! + env = conf.Finish() + </sconstruct> + + <para> + + The next sections describe + the basic checks that &SCons; supports, + as well as how to add your own custom checks. + + </para> + + </section> + + <section> + <title>Checking for the Existence of Header Files</title> + + <para> + + Testing the existence of a header file + requires knowing what language the header file is. + A configure context has a &CheckCHeader; method + that checks for the existence of a C header file: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env) + if not conf.CheckCHeader('math.h'): + print 'Math.h must be installed!' + Exit(1) + if conf.CheckCHeader('foo.h'): + conf.env.Append('-DHAS_FOO_H') + env = conf.Finish() + </sconstruct> + + <para> + + Note that you can choose to terminate + the build if a given header file doesn't exist, + or you can modify the contstruction environment + based on the existence of a header file. + + </para> + + <para> + + If you need to check for the existence + a C++ header file, + use the &CheckCXXHeader; method: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env) + if not conf.CheckCXXHeader('vector.h'): + print 'vector.h must be installed!' + Exit(1) + env = conf.Finish() + </sconstruct> + + </section> + + <section> + <title>Checking for the Availability of a Function</title> + + <para> + + Check for the availability of a specific function + using the &CheckFunc; method: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env) + if not conf.CheckFunc('strcpy'): + print 'Did not find strcpy(), using local version' + conf.env.Append('-Dstrcpy=my_local_strcpy') + env = conf.Finish() + </sconstruct> + + </section> + + <section> + <title>Checking for the Availability of a Library</title> + + <para> + + Check for the availability of a library + using the &CheckLibrary; method. + You only specify the basename of the library, + you don't need to add a <literal>lib</literal> + prefix or a <literal>.a</literal> or <literal>.lib</literal> suffix: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env) + if not conf.CheckLib('m'): + print 'Did not find libm.a or m.lib, exiting!' + Exit(1) + env = conf.Finish() + </sconstruct> + + <para> + + If the library requires the inclusion of + a header file to compile successfully, + add that as a second argument: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env) + if not conf.CheckLibWithHeader('m', 'math.h'): + print 'Did not find libm.a or m.lib, exiting!' + Exit(1) + env = conf.Finish() + </sconstruct> + + </section> + + <section> + <title>Checking for the Availability of a &typedef;</title> + + <para> + + Check for the availability of a &typedef; + by using the &CheckType; method: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env) + if not conf.CheckType('off_t'): + print 'Did not find off_t typedef, assuming int' + conf.env.Append(CCFLAGS = '-Doff_t=int') + env = conf.Finish() + </sconstruct> + + <para> + + You can also add a string that will be + placed at the beginning of the test file + that will be used to check for the &typedef;. + This provide a way to specify + files that must be included to find the &typedef;: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + if not conf.CheckType('off_t', '#include &lt;sys/types.h&gt;\n'): + print 'Did not find off_t typedef, assuming int' + conf.env.Append(CCFLAGS = '-Doff_t=int') + env = conf.Finish() + </programlisting> + + </section> + + <section> + <title>Adding Your Own Custom Checks</title> + + <para> + + A custom check is a Python function + that checks for a certain condition to exist + on the running system, + usually using methods that &SCons; + supplies to take care of the details + of checking whether a compilation succeeds, + a link succeeds, + a program is runnable, + etc. + A simple custom check for the existence of + a specific library might look as follows: + + </para> + + <programlisting> + mylib_test_source_file = """ + #include &lt;mylib.h&gt; + int main(int argc, char **argv) + { + MyLibrary mylib(argc, argv); + return 0; + } + """ + + def CheckMyLibrary(context): + context.Message('Checking for MyLibrary...') + result = context.TryLink(mylib_test_source_file, '.c') + context.Result(result) + return result + </programlisting> + + <para> + + The &Message; and &Result; methods + should typically begin and end a custom check to + let the user know what's going on: + the &Message; call prints the + specified message (with no trailing newline) + and the &Result; call prints + <literal>ok</literal> if the check succeeds and + <literal>failed</literal> if it doesn't. + The &TryLink; method + actually tests for whether the + specified program text + will successfully link. + + </para> + + <para> + + (Note that a custom check can modify + its check based on any arguments you + choose to pass it, + or by using or modifying the configure context environment + in the <literal>context.env</literal> attribute.) + + </para> + + <para> + + This custom check function is + then attached to the &configure_context; + by passing a dictionary + to the &Configure; call + that maps a name of the check + to the underlying function: + + </para> + + <sconstruct> + env = Environment() + conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) + </sconstruct> + + <para> + + You'll typically want to make + the check and the function name the same, + as we've done here, + to avoid potential confusion. + + </para> + + <para> + + We can then put these pieces together + and actually call the <literal>CheckMyLibrary</literal> check + as follows: + + </para> + + <programlisting> + mylib_test_source_file = """ + #include &lt;mylib.h&gt; + int main(int argc, char **argv) + { + MyLibrary mylib(argc, argv); + return 0; + } + """ + + def CheckMyLibrary(context): + context.Message('Checking for MyLibrary... ') + result = context.TryLink(mylib_test_source_file, '.c') + context.Result(result) + return result + + env = Environment() + conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) + if not conf.CheckMyLibrary(): + print 'MyLibrary is not installed!' + Exit(1) + env = conf.Finish() + + # We would then add actual calls like Program() to build + # something using the "env" construction environment. + </programlisting> + + <para> + + If MyLibrary is not installed on the system, + the output will look like: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript file ... + Checking for MyLibrary... failed + MyLibrary is not installed! + </screen> + + <para> + + If MyLibrary is installed, + the output will look like: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript file ... + Checking for MyLibrary... failed + scons: done reading SConscript + scons: Building targets ... + . + . + . + </screen> + + </section> diff --git a/doc/user/sconf.sgml b/doc/user/sconf.sgml new file mode 100644 index 0000000..715ba67 --- /dev/null +++ b/doc/user/sconf.sgml @@ -0,0 +1,386 @@ +<!-- + + __COPYRIGHT__ + + 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> + + &SCons; has integrated support for multi-platform build configuration + similar to that offered by GNU &Autoconf;, + such as + figuring out what libraries or header files + are available on the local system. + This section describes how to use + this &SCons; feature. + + </para> + + <note> + <para> + This chapter is still under development, + so not everything is explained as well as it should be. + See the &SCons; man page for additional information. + </para> + </note> + + <section> + <title>&Configure_Contexts;</title> + + <para> + + The basic framework for multi-platform build configuration + in &SCons; is to attach a &configure_context; to a + construction environment by calling the &Configure; function, + perform a number of checks for + libraries, functions, header files, etc., + and to then call the configure context's &Finish; method + to finish off the configuration: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + # Checks for libraries, header files, etc. go here! + env = conf.Finish() + </programlisting> + + <para> + + The next sections describe + the basic checks that &SCons; supports, + as well as how to add your own custom checks. + + </para> + + </section> + + <section> + <title>Checking for the Existence of Header Files</title> + + <para> + + Testing the existence of a header file + requires knowing what language the header file is. + A configure context has a &CheckCHeader; method + that checks for the existence of a C header file: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + if not conf.CheckCHeader('math.h'): + print 'Math.h must be installed!' + Exit(1) + if conf.CheckCHeader('foo.h'): + conf.env.Append('-DHAS_FOO_H') + env = conf.Finish() + </programlisting> + + <para> + + Note that you can choose to terminate + the build if a given header file doesn't exist, + or you can modify the contstruction environment + based on the existence of a header file. + + </para> + + <para> + + If you need to check for the existence + a C++ header file, + use the &CheckCXXHeader; method: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + if not conf.CheckCXXHeader('vector.h'): + print 'vector.h must be installed!' + Exit(1) + env = conf.Finish() + </programlisting> + + </section> + + <section> + <title>Checking for the Availability of a Function</title> + + <para> + + Check for the availability of a specific function + using the &CheckFunc; method: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + if not conf.CheckFunc('strcpy'): + print 'Did not find strcpy(), using local version' + conf.env.Append('-Dstrcpy=my_local_strcpy') + env = conf.Finish() + </programlisting> + + </section> + + <section> + <title>Checking for the Availability of a Library</title> + + <para> + + Check for the availability of a library + using the &CheckLibrary; method. + You only specify the basename of the library, + you don't need to add a <literal>lib</literal> + prefix or a <literal>.a</literal> or <literal>.lib</literal> suffix: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + if not conf.CheckLib('m'): + print 'Did not find libm.a or m.lib, exiting!' + Exit(1) + env = conf.Finish() + </programlisting> + + <para> + + If the library requires the inclusion of + a header file to compile successfully, + add that as a second argument: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + if not conf.CheckLibWithHeader('m', 'math.h'): + print 'Did not find libm.a or m.lib, exiting!' + Exit(1) + env = conf.Finish() + </programlisting> + + </section> + + <section> + <title>Checking for the Availability of a &typedef;</title> + + <para> + + Check for the availability of a &typedef; + by using the &CheckType; method: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + if not conf.CheckType('off_t'): + print 'Did not find off_t typedef, assuming int' + conf.env.Append(CCFLAGS = '-Doff_t=int') + env = conf.Finish() + </programlisting> + + <para> + + You can also add a string that will be + placed at the beginning of the test file + that will be used to check for the &typedef;. + This provide a way to specify + files that must be included to find the &typedef;: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env) + if not conf.CheckType('off_t', '#include <sys/types.h>\n'): + print 'Did not find off_t typedef, assuming int' + conf.env.Append(CCFLAGS = '-Doff_t=int') + env = conf.Finish() + </programlisting> + + </section> + + <section> + <title>Adding Your Own Custom Checks</title> + + <para> + + A custom check is a Python function + that checks for a certain condition to exist + on the running system, + usually using methods that &SCons; + supplies to take care of the details + of checking whether a compilation succeeds, + a link succeeds, + a program is runnable, + etc. + A simple custom check for the existence of + a specific library might look as follows: + + </para> + + <programlisting> + mylib_test_source_file = """ + #include <mylib.h> + int main(int argc, char **argv) + { + MyLibrary mylib(argc, argv); + return 0; + } + """ + + def CheckMyLibrary(context): + context.Message('Checking for MyLibrary...') + result = context.TryLink(mylib_test_source_file, '.c') + context.Result(result) + return result + </programlisting> + + <para> + + The &Message; and &Result; methods + should typically begin and end a custom check to + let the user know what's going on: + the &Message; call prints the + specified message (with no trailing newline) + and the &Result; call prints + <literal>ok</literal> if the check succeeds and + <literal>failed</literal> if it doesn't. + The &TryLink; method + actually tests for whether the + specified program text + will successfully link. + + </para> + + <para> + + (Note that a custom check can modify + its check based on any arguments you + choose to pass it, + or by using or modifying the configure context environment + in the <literal>context.env</literal> attribute.) + + </para> + + <para> + + This custom check function is + then attached to the &configure_context; + by passing a dictionary + to the &Configure; call + that maps a name of the check + to the underlying function: + + </para> + + <programlisting> + env = Environment() + conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) + </programlisting> + + <para> + + You'll typically want to make + the check and the function name the same, + as we've done here, + to avoid potential confusion. + + </para> + + <para> + + We can then put these pieces together + and actually call the <literal>CheckMyLibrary</literal> check + as follows: + + </para> + + <programlisting> + mylib_test_source_file = """ + #include <mylib.h> + int main(int argc, char **argv) + { + MyLibrary mylib(argc, argv); + return 0; + } + """ + + def CheckMyLibrary(context): + context.Message('Checking for MyLibrary... ') + result = context.TryLink(mylib_test_source_file, '.c') + context.Result(result) + return result + + env = Environment() + conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) + if not conf.CheckMyLibrary(): + print 'MyLibrary is not installed!' + Exit(1) + env = conf.Finish() + + # We would then add actual calls like Program() to build + # something using the "env" construction environment. + </programlisting> + + <para> + + If MyLibrary is not installed on the system, + the output will look like: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript file ... + Checking for MyLibrary... failed + MyLibrary is not installed! + </screen> + + <para> + + If MyLibrary is installed, + the output will look like: + + </para> + + <screen> + % <userinput>scons</userinput> + scons: Reading SConscript file ... + Checking for MyLibrary... failed + scons: done reading SConscript + scons: Building targets ... + . + . + . + </screen> + + </section> diff --git a/doc/user/separate.in b/doc/user/separate.in index 1b24edf..d613f42 100644 --- a/doc/user/separate.in +++ b/doc/user/separate.in @@ -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 @@ -300,7 +300,7 @@ program using the F<build/foo.c> path name. </para> - <literallayout> + <screen> % <userinput>ls src</userinput> SConscript hello.c @@ -310,7 +310,7 @@ program using the F<build/foo.c> path name. % <userinput>ls build</userinput> hello hello.o - </literallayout> + </screen> </section> diff --git a/doc/user/separate.sgml b/doc/user/separate.sgml index b00be1a..1c04f8a 100644 --- a/doc/user/separate.sgml +++ b/doc/user/separate.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 @@ -150,7 +150,7 @@ program using the F<build/foo.c> path name. </para> - <literallayout> + <screen> % <userinput>ls src</userinput> SConscript hello.c % <userinput>scons -Q</userinput> @@ -158,7 +158,7 @@ program using the F<build/foo.c> path name. cc -o build/hello build/hello.o % <userinput>ls build</userinput> SConscript hello hello.c hello.o - </literallayout> + </screen> <para> @@ -295,7 +295,7 @@ program using the F<build/foo.c> path name. </para> - <literallayout> + <screen> % <userinput>ls src</userinput> SConscript hello.c @@ -305,7 +305,7 @@ program using the F<build/foo.c> path name. % <userinput>ls build</userinput> hello hello.o - </literallayout> + </screen> </section> @@ -346,7 +346,7 @@ program using the F<build/foo.c> path name. </para> - <literallayout> + <screen> % <userinput>ls src</userinput> hello.c % <userinput>scons -Q</userinput> @@ -354,7 +354,7 @@ program using the F<build/foo.c> path name. cc -o build/hello build/hello.o % <userinput>ls build</userinput> hello hello.c hello.o - </literallayout> + </screen> <para> @@ -376,7 +376,7 @@ program using the F<build/foo.c> path name. </para> - <literallayout> + <screen> % <userinput>ls src</userinput> hello.c % <userinput>scons -Q</userinput> @@ -384,7 +384,7 @@ program using the F<build/foo.c> path name. cc -o build/hello build/hello.o % <userinput>ls build</userinput> hello hello.o - </literallayout> + </screen> </section> @@ -425,7 +425,7 @@ program using the F<build/foo.c> path name. </para> - <literallayout> + <screen> % <userinput>ls src</userinput> SConscript hello.c % <userinput>scons -Q</userinput> @@ -433,7 +433,7 @@ program using the F<build/foo.c> path name. cc -o build/hello build/hello.o % <userinput>ls build</userinput> SConscript hello hello.c hello.o - </literallayout> + </screen> <para> diff --git a/doc/user/simple.in b/doc/user/simple.in index 3d9d7dc..4ac6d33 100644 --- a/doc/user/simple.in +++ b/doc/user/simple.in @@ -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,110 +25,42 @@ <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> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - Program('hello.c') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <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> - - <scons_output example="ex1" os="posix"> - <command>scons</command> - </scons_output> - - <para> - - On a Windows system with the Microsoft Visual C++ compiler, - you'll see something like: - - </para> - - <scons_output example="ex1" os="win32"> - <command>scons</command> - </scons_output> - - <para> - - 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> - - 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> + <section> + <title>Building Simple C / C++ Programs</title> - <para> + <para> - (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.) + Here's the famous "Hello, World!" program in C: - </para> + </para> - <section> - <title>Cleaning Up After a Build</title> + <programlisting> + int + main() + { + printf("Hello, world!\n"); + } + </programlisting> <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: + And here's how to build it using &SCons;. + Enter the following into a file named &SConstruct;: </para> - <scons_example name="clean"> - <file name="SConstruct"> + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> Program('hello.c') </file> <file name="hello.c"> @@ -136,93 +68,37 @@ </file> </scons_example> - <scons_output example="clean" os="posix"> - <command>scons</command> - <command>scons -c</command> - </scons_output> - <para> - And the output on Windows looks like: + 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. </para> - <scons_output example="clean" os="win32"> - <command>scons</command> - <command>scons -c</command> - </scons_output> - <para> - Notice that &SCons; changes its output to tell you that it - is <literal>Cleaning targets ...</literal> and - <literal>done cleaning targets.</literal> + 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> - </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. - - </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. - - </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>Making the Output Less Verbose</title> + <scons_output example="ex1" os="posix"> + <command>scons</command> + </scons_output> <para> - You've already seen how &SCons; prints - some messages about what it's doing, - surrounding the actual commands used to build the software: + On a Windows system with the Microsoft Visual C++ compiler, + you'll see something like: </para> @@ -232,417 +108,409 @@ <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. + 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> <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;: + 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> - <scons_output example="ex1" os="win32"> - <command>scons -Q</command> - </scons_output> - <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. + (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>Compiling Multiple Source Files</title> + <title>Building Object 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: + 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> - <scons_example name="ex2"> + <scons_example name="Object"> <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"); } + Object('hello.c') </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"> - <command>scons -Q</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 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', ['main.c', 'file1.c', 'file2.c']) - </file> - <file name="main.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 name="hello.c"> + int main() { printf("Hello, world!\n"); } </file> </scons_example> <para> - On Linux, a build of this example would look like: + 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> - <scons_output example="ex3" os="posix"> - <command>scons -Q</command> + <scons_output example="Object" os="posix"> + <command>scons</command> </scons_output> <para> - Or on Windows: + And just the &hello_obj; object file + on a Windows system (with the Microsoft Visual C++ compiler): </para> - <scons_output example="ex3" os="win32"> - <command>scons -Q</command> + <scons_output example="Object" os="win32"> + <command>scons</command> </scons_output> </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> + <title>Simple Java Builds</title> + + <para> + + &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> + + <scons_example name="java"> + <file name="SConstruct" printme="1"> + Java('classes', 'src') + </file> + <file name="src/hello.java"> + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + </file> + </scons_example> <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: + 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> - <programlisting> - list = Split('main.c file1.c file2.c') - Program('program', list) - </programlisting> + <scons_output example="java" os="posix"> + <command>scons</command> + </scons_output> <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: + 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> - <programlisting> - list = Split('main.c - file1.c - file2.c') - Program('program', list) - </programlisting> - </section> <section> - <title>Keyword Arguments</title> + <title>Cleaning Up After a Build</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: + 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(target = 'program', source = list) - </programlisting> + <scons_example name="clean"> + <file name="SConstruct"> + Program('hello.c') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <scons_output example="clean" os="posix"> + <command>scons</command> + <command>scons -c</command> + </scons_output> <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> + <scons_output example="clean" os="win32"> + <command>scons</command> + <command>scons -c</command> + </scons_output> <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> - - <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> + <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> - <scons_output example="ex4"> - <command>scons -Q</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> + <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> + + <scons_example name="declarative"> + <file name="SConstruct" printme="1"> + print "Calling Program('hello.c')" + Program('hello.c') + print "Calling Program('goodbye.c')" + Program('goodbye.c') + print "Finished calling Program()" + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="goodbye.c"> + int main() { printf("Goodbye, world!\n"); } + </file> + </scons_example> + + <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> + + <scons_output example="declarative" os="posix"> + <command>scons</command> + </scons_output> + + <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> + <title>Making the &SCons; Output Less Verbose</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.) + You've already seen how &SCons; prints + some messages about what it's doing, + surrounding the actual commands used to build the software: </para> + <scons_output example="ex1" os="win32"> + <command>scons</command> + </scons_output> + <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: + 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> - <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 only need to be built once, - even though the resulting object files are - each linked in to both of the resulting executable programs: + 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> - <scons_output example="ex5"> + <scons_output example="ex1" os="win32"> <command>scons -Q</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 + 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. + 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> 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> diff --git a/doc/user/sourcecode.in b/doc/user/sourcecode.in index 30b6ecb..c40c512 100644 --- a/doc/user/sourcecode.in +++ b/doc/user/sourcecode.in @@ -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 diff --git a/doc/user/sourcecode.sgml b/doc/user/sourcecode.sgml index 74b7347..daa9ad7 100644 --- a/doc/user/sourcecode.sgml +++ b/doc/user/sourcecode.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 @@ -48,13 +48,13 @@ env.Program('hello.c') </programlisting> - <literallayout> + <screen> % <userinput>scons -Q</userinput> bk get - bk get hello.c cc -c -o hello.o hello.c cc -o hello hello.o - </literallayout> + </screen> </section> @@ -73,13 +73,13 @@ env.Program('hello.c') </programlisting> - <literallayout> + <screen> % <userinput>scons -Q</userinput> cvs -d /usr/local/CVS co - cvs -d /usr/local/CVS co hello.c cc -c -o hello.o hello.c cc -o hello hello.o - </literallayout> + </screen> </section> @@ -98,13 +98,13 @@ env.Program('hello.c') </programlisting> - <literallayout> + <screen> % <userinput>scons -Q</userinput> co - co hello.c cc -c -o hello.o hello.c cc -o hello hello.o - </literallayout> + </screen> </section> @@ -123,13 +123,13 @@ env.Program('hello.c') </programlisting> - <literallayout> + <screen> % <userinput>scons -Q</userinput> sccs get - sccs get hello.c cc -c -o hello.o hello.c cc -o hello hello.o - </literallayout> + </screen> </section> diff --git a/doc/user/tasks.in b/doc/user/tasks.in index 29299ab..7be3562 100644 --- a/doc/user/tasks.in +++ b/doc/user/tasks.in @@ -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 diff --git a/doc/user/tasks.sgml b/doc/user/tasks.sgml index 29299ab..7be3562 100644 --- a/doc/user/tasks.sgml +++ b/doc/user/tasks.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 diff --git a/doc/user/troubleshoot.in b/doc/user/troubleshoot.in index f83ab63..e5c008d 100644 --- a/doc/user/troubleshoot.in +++ b/doc/user/troubleshoot.in @@ -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 @@ -23,19 +23,174 @@ --> - <para> + <para> - XXX + The experience of configuring any + software build tool to build a large code base + usually, at some point, + involves trying to figure out why + the tool is behaving a certain way, + and how to get it to behave the way you want. + &SCons; is no different. - </para> + </para> - <section> - <title>XXX</title> + <section> + <title>Why is That Target Being Rebuilt? the &debug-explain; Option</title> - <para> + <para> - XXX + Let's take a simple example of + a misconfigured build + that causes a target to be rebuilt + every time &SCons; is run: - </para> + </para> - </section> + <scons_example name="explain1"> + <file name="SConstruct" printme="1"> + # Intentionally misspell the output file name in the + # command used to create the file: + Command('file.out', 'file.in', 'cp $SOURCE file.oout') + </file> + <file name="file.in"> + file.in + </file> + </scons_example> + + <para> + + (Note to Windows users: The POSIX &cp; command + copies the first file named on the command line + to the second file. + In our example, it copies the &file_in; file + to the &file_out; file.) + + </para> + + <para> + + Now if we run &SCons; multiple on this example, + we see that it re-runs the &cp; + command every time: + + </para> + + <scons_output example="explain1" os="posix"> + <command>scons -Q</command> + <command>scons -Q</command> + <command>scons -Q</command> + </scons_output> + + <para> + + In this example, + the underlying cause is obvious: + we've intentionally misspelled the output file name + in the &cp; command, + so the command doesn't actually + build the &file_out; file that we've told &SCons; to expect. + But if the problem weren't obvious, + it would be helpful + to specify the &debug-explain; option + on the command line + to have &SCons; tell us very specifically + why it's decided to rebuild the target: + + </para> + + <scons_output example="explain1" os="posix"> + <command>scons -Q --debug=explain</command> + </scons_output> + + <para> + + If this had been a more complicated example + involving a lot of build output, + having &SCons; tell us that + it's trying to rebuild the target file + because it doesn't exist + would be an important clue + that something was wrong with + the command that we invoked to build it. + + </para> + + <para> + + The &debug-explain; option also comes in handy + to help figure out what input file changed. + Given a simple configuration that builds + a program from three source files, + changing one of the source files + and rebuilding with the &debug-explain; + option shows very specifically + why &SCons; rebuilds the files that it does: + + </para> + + <scons_example name="explain2"> + <file name="SConstruct"> + Program('prog', ['file1.c', 'file2.c', 'file3.c']) + </file> + <file name="file1.c"> + file1.c + </file> + <file name="file2.c"> + file2.c + </file> + <file name="file3.c"> + file3.c + </file> + </scons_example> + + <scons_output example="explain2" os="posix"> + <command>scons -Q</command> + <command output=" [CHANGE THE CONTENTS OF file2.c]">edit file2.c</command> + <command>scons -Q --debug=explain</command> + </scons_output> + + <para> + + This becomes even more helpful + in identifying when a file is rebuilt + due to a change in an implicit dependency, + such as an incuded <filename>.h</filename> file. + If the <filename>file1.c</filename> + and <filename>file3.c</filename> files + in our example + both included a &hello_h; file, + then changing that included file + and re-running &SCons; with the &debug-explain; option + will pinpoint that it's the change to the included file + that starts the chain of rebuilds: + + </para> + + <scons_example name="explain3"> + <file name="SConstruct"> + Program('prog', ['file1.c', 'file2.c', 'file3.c'], CPPPATH='.') + </file> + <file name="file1.c"> + #include <hello.h> + file1.c + </file> + <file name="file2.c"> + file2.c + </file> + <file name="file3.c"> + #include <hello.h> + file3.c + </file> + <file name="hello.h"> + #define string "world" + </file> + </scons_example> + + <scons_output example="explain3" os="posix"> + <command>scons -Q</command> + <command output=" [CHANGE THE CONTENTS OF hello.h]">edit hello.h</command> + <command>scons -Q --debug=explain</command> + </scons_output> + + </section> diff --git a/doc/user/troubleshoot.sgml b/doc/user/troubleshoot.sgml index f83ab63..aee2aee 100644 --- a/doc/user/troubleshoot.sgml +++ b/doc/user/troubleshoot.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 @@ -23,19 +23,165 @@ --> - <para> + <para> - XXX + The experience of configuring any + software build tool to build a large code base + usually, at some point, + involves trying to figure out why + the tool is behaving a certain way, + and how to get it to behave the way you want. + &SCons; is no different. - </para> + </para> - <section> - <title>XXX</title> + <section> + <title>Why is That Target Being Rebuilt? the &debug-explain; Option</title> - <para> + <para> - XXX + Let's take a simple example of + a misconfigured build + that causes a target to be rebuilt + every time &SCons; is run: - </para> + </para> - </section> + <programlisting> + # Intentionally misspell the output file name in the + # command used to create the file: + Command('file.out', 'file.in', 'cp $SOURCE file.oout') + </programlisting> + + <para> + + (Note to Windows users: The POSIX &cp; command + copies the first file named on the command line + to the second file. + In our example, it copies the &file_in; file + to the &file_out; file.) + + </para> + + <para> + + Now if we run &SCons; multiple on this example, + we see that it re-runs the &cp; + command every time: + + </para> + + <screen> + % <userinput>scons -Q</userinput> + cp file.in file.oout + % <userinput>scons -Q</userinput> + cp file.in file.oout + % <userinput>scons -Q</userinput> + cp file.in file.oout + </screen> + + <para> + + In this example, + the underlying cause is obvious: + we've intentionally misspelled the output file name + in the &cp; command, + so the command doesn't actually + build the &file_out; file that we've told &SCons; to expect. + But if the problem weren't obvious, + it would be helpful + to specify the &debug-explain; option + on the command line + to have &SCons; tell us very specifically + why it's decided to rebuild the target: + + </para> + + <screen> + % <userinput>scons -Q --debug=explain</userinput> + scons: building `file.out' because it doesn't exist + cp file.in file.oout + </screen> + + <para> + + If this had been a more complicated example + involving a lot of build output, + having &SCons; tell us that + it's trying to rebuild the target file + because it doesn't exist + would be an important clue + that something was wrong with + the command that we invoked to build it. + + </para> + + <para> + + The &debug-explain; option also comes in handy + to help figure out what input file changed. + Given a simple configuration that builds + a program from three source files, + changing one of the source files + and rebuilding with the &debug-explain; + option shows very specifically + why &SCons; rebuilds the files that it does: + + </para> + + + + <screen> + % <userinput>scons -Q</userinput> + cc -c -o file1.o file1.c + cc -c -o file2.o file2.c + cc -c -o file3.o file3.c + cc -o prog file1.o file2.o file3.o + % <userinput>edit file2.c</userinput> + [CHANGE THE CONTENTS OF file2.c] + % <userinput>scons -Q --debug=explain</userinput> + scons: rebuilding `file2.o' because `file2.c' changed + cc -c -o file2.o file2.c + scons: rebuilding `prog' because `file2.o' changed + cc -o prog file1.o file2.o file3.o + </screen> + + <para> + + This becomes even more helpful + in identifying when a file is rebuilt + due to a change in an implicit dependency, + such as an incuded <filename>.h</filename> file. + If the <filename>file1.c</filename> + and <filename>file3.c</filename> files + in our example + both included a &hello_h; file, + then changing that included file + and re-running &SCons; with the &debug-explain; option + will pinpoint that it's the change to the included file + that starts the chain of rebuilds: + + </para> + + + + <screen> + % <userinput>scons -Q</userinput> + cc -I. -c -o file1.o file1.c + cc -I. -c -o file2.o file2.c + cc -I. -c -o file3.o file3.c + cc -o prog file1.o file2.o file3.o + % <userinput>edit hello.h</userinput> + [CHANGE THE CONTENTS OF hello.h] + % <userinput>scons -Q --debug=explain</userinput> + scons: rebuilding `file1.o' because `hello.h' changed + cc -I. -c -o file1.o file1.c + scons: rebuilding `file3.o' because `hello.h' changed + cc -I. -c -o file3.o file3.c + scons: rebuilding `prog' because: + `file1.o' changed + `file3.o' changed + cc -o prog file1.o file2.o file3.o + </screen> + + </section> diff --git a/doc/user/variants.in b/doc/user/variants.in index ceab8f6..82d938b 100644 --- a/doc/user/variants.in +++ b/doc/user/variants.in @@ -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 diff --git a/doc/user/variants.sgml b/doc/user/variants.sgml index 4ddb40b..0ef7d1f 100644 --- a/doc/user/variants.sgml +++ b/doc/user/variants.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 @@ -92,7 +92,7 @@ is pretty smart about rebuilding things when you change options. </para> - <literallayout> + <screen> % <userinput>scons -Q OS=linux</userinput> Install file: "build/linux/world/world.h" as "export/linux/include/world.h" cc -Iexport/linux/include -c -o build/linux/hello/hello.o build/linux/hello/hello.c @@ -102,7 +102,7 @@ is pretty smart about rebuilding things when you change options. Install file: "build/linux/world/libworld.a" as "export/linux/lib/libworld.a" cc -o build/linux/hello/hello build/linux/hello/hello.o -Lexport/linux/lib -lworld Install file: "build/linux/hello/hello" as "export/linux/bin/hello" - </literallayout> + </screen> <para> @@ -110,7 +110,7 @@ is pretty smart about rebuilding things when you change options. </para> - <literallayout> + <screen> C:\><userinput>scons -Q OS=windows</userinput> Install file: "build/windows/world/world.h" as "export/windows/include/world.h" cl /nologo /Iexport\windows\include /c build\windows\hello\hello.c /Fobuild\windows\hello\hello.obj @@ -119,7 +119,7 @@ is pretty smart about rebuilding things when you change options. Install file: "build/windows/world/world.lib" as "export/windows/lib/world.lib" link /nologo /OUT:build\windows\hello\hello.exe /LIBPATH:export\windows\lib world.lib build\windows\hello\hello.obj Install file: "build/windows/hello/hello.exe" as "export/windows/bin/hello.exe" - </literallayout> + </screen> <!-- |