From 74e2a97dc2ed0412ffb1a9c6dc810c1a1c4a4e67 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Mon, 16 Aug 2004 13:43:09 +0000 Subject: Branch for documentation changes. --- doc/man/scons.1 | 113 +++++- doc/scons.mod | 69 +++- doc/user/ENV.in | 42 +- doc/user/ENV.sgml | 42 +- doc/user/MANIFEST | 5 + doc/user/actions.in | 2 +- doc/user/actions.sgml | 2 +- doc/user/alias.in | 2 +- doc/user/alias.sgml | 10 +- doc/user/ant.in | 2 +- doc/user/ant.sgml | 2 +- doc/user/build-install.in | 605 +++++++++++++++++++++++++++++ doc/user/build-install.sgml | 605 +++++++++++++++++++++++++++++ doc/user/builders-built-in.in | 54 +-- doc/user/builders-built-in.sgml | 80 ++-- doc/user/builders-commands.in | 2 +- doc/user/builders-commands.sgml | 12 +- doc/user/builders-writing.in | 2 +- doc/user/builders-writing.sgml | 34 +- doc/user/caching.in | 2 +- doc/user/caching.sgml | 18 +- doc/user/command-line.in | 34 +- doc/user/command-line.sgml | 181 ++++----- doc/user/cons.in | 2 +- doc/user/cons.sgml | 2 +- doc/user/copyright.in | 4 +- doc/user/copyright.sgml | 4 +- doc/user/depends.in | 20 +- doc/user/depends.sgml | 72 ++-- doc/user/environments.in | 318 +++++++++++++++- doc/user/environments.sgml | 363 ++++++++++++++++-- doc/user/errors.in | 2 +- doc/user/errors.sgml | 2 +- doc/user/example.in | 2 +- doc/user/example.sgml | 2 +- doc/user/help.in | 2 +- doc/user/help.sgml | 6 +- doc/user/hierarchy.in | 6 +- doc/user/hierarchy.sgml | 22 +- doc/user/install.in | 2 +- doc/user/install.sgml | 22 +- doc/user/java.in | 540 ++++++++++++++++++++++++++ doc/user/java.sgml | 354 +++++++++++++++++ doc/user/less-simple.in | 589 ++++++++++++++++++++++++++++ doc/user/less-simple.sgml | 562 +++++++++++++++++++++++++++ doc/user/libraries.in | 50 ++- doc/user/libraries.sgml | 86 +++-- doc/user/main.in | 54 ++- doc/user/main.sgml | 54 ++- doc/user/make.in | 2 +- doc/user/make.sgml | 2 +- doc/user/nodes.in | 355 +++++++++++++++++ doc/user/nodes.sgml | 359 +++++++++++++++++ doc/user/precious.in | 2 +- doc/user/precious.sgml | 6 +- doc/user/preface.in | 42 +- doc/user/preface.sgml | 42 +- doc/user/repositories.in | 20 +- doc/user/repositories.sgml | 36 +- doc/user/run.in | 2 +- doc/user/run.sgml | 2 +- doc/user/scanners.in | 2 +- doc/user/scanners.sgml | 2 +- doc/user/sconf.in | 386 +++++++++++++++++++ doc/user/sconf.sgml | 386 +++++++++++++++++++ doc/user/separate.in | 6 +- doc/user/separate.sgml | 22 +- doc/user/simple.in | 800 ++++++++++++++++---------------------- doc/user/simple.sgml | 826 ++++++++++++++++++---------------------- doc/user/sourcecode.in | 2 +- doc/user/sourcecode.sgml | 18 +- doc/user/tasks.in | 2 +- doc/user/tasks.sgml | 2 +- doc/user/troubleshoot.in | 175 ++++++++- doc/user/troubleshoot.sgml | 166 +++++++- doc/user/variants.in | 2 +- doc/user/variants.sgml | 10 +- src/CHANGES.txt | 18 + src/test_copyrights.py | 18 +- 79 files changed, 7323 insertions(+), 1452 deletions(-) create mode 100644 doc/user/build-install.in create mode 100644 doc/user/build-install.sgml create mode 100644 doc/user/java.in create mode 100644 doc/user/java.sgml create mode 100644 doc/user/less-simple.in create mode 100644 doc/user/less-simple.sgml create mode 100644 doc/user/nodes.in create mode 100644 doc/user/nodes.sgml create mode 100644 doc/user/sconf.in create mode 100644 doc/user/sconf.sgml 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 @@ +--debug=explain"> --implicit-cache"> --implicit-deps-changed"> --implicit-deps-unchanged"> @@ -125,13 +133,18 @@ Clean"> Clone"> Command"> +Configure"> Copy"> Default"> DefaultRules"> Depends"> +Dir"> +Entry"> EnumOption"> Environment"> Export"> +File"> +Finish"> GenerateHelpText"> Help"> Ignore"> @@ -161,6 +174,25 @@ TargetSignatures"> Task"> + +subst"> + + +Message"> +Result"> +CheckCHeader"> +CheckCXXHeader"> +CheckFunc"> +CheckHeader"> +CheckLibrary"> +CheckType"> +TryAction"> +TryBuild"> +TryCompile"> +TryLink"> +TryRun"> + + str"> zipfile"> @@ -192,11 +224,13 @@ BUILDERS"> CC"> CCFLAGS"> +CCCOM"> COLOR"> COLORS"> CONFIG"> CPPDEFINES"> ENV"> +JAVACLASSDIR"> LIBDIRPREFIX"> LIBDIRSUFFIX"> LIBLINKPREFIX"> @@ -296,6 +330,10 @@ --> builder function"> +builder method"> + +Configure Contexts"> +configure context"> Construction Environment"> Construction Environments"> @@ -320,12 +358,16 @@ Generator"> generator"> +Nodes"> + signature"> build signature"> true"> false"> +typedef"> + bar"> -common1.c"> -common2.c"> +common1.c"> +common2.c"> custom.py"> goodbye"> -file.dll"> -file.lib"> -file.o"> -file.obj"> +goodbye.o"> +goodbye.obj"> +file.dll"> +file.in"> +file.lib"> +file.o"> +file.obj"> +file.out"> foo"> +foo.o"> +foo.obj"> hello"> hello.c"> hello.exe"> hello.h"> hello.o"> +hello.obj"> libfile_a"> libfile_so"> +new_hello"> +new_hello.exe"> prog"> prog1"> prog2"> @@ -371,6 +422,6 @@ --> -scons-announce@lists.sourceforge.net"> -scons-devel@lists.sourceforge.net"> -scons-users@lists.sourceforge.net"> +announce@scons.tigris.org"> +dev@scons.tigris.org"> +users@scons.tigris.org"> 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 @@ + + + + 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. + + + + + +
+ Installing Python + + + + 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 + python + at your system's command-line prompt. + You should see something like the following + on a UNIX or Linux system that has Python installed: + + + + + $ python + 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. + >>> ^D + + + + + And on a Windows system with Python installed: + + + + + C:\>python + 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. + >>> ^Z + + + + + The >>> is the input prompt + for the Python interpreter. + The ^D and ^Z + 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;. + + + + + + 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;. + + + + + + The standard location for information + about downloading and installing Python is + http://www.python.org/download/. + See that page for information about + how to download and install Python on your system. + + + +
+ +
+ Installing &SCons; From Pre-Built Packages + + + + &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. + + + +
+ Installing &SCons; on Red Hat (and Other RPM-based) Linux Systems + + + + &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 + http://www.rpmfind.net/ or + http://rpm.pbone.net/. + + + + + + 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 /usr/bin, + and the SCons library modules in + /usr/lib/scons. + + + + + + To install from the command line, simply download the + appropriate .rpm file, + and then run: + + + + + # rpm -Uvh scons-0.96-1.noarch.rpm + + + + + Or, you can use a graphical RPM package manager + like gnorpm. + See your package manager application's documention + for specific instructions about + how to use it to install a downloaded RPM. + + + +
+ +
+ Installing &SCons; on Debian Linux Systems + + + + Debian Linux systems use a different package management + format that also makes it very easy to install &SCons;. + + + + + + If your system is connected to the Internet, + you can install the latest official Debian package + by running: + + + + + # apt-get install scons + + + + +
+ +
+ Installing &SCons; on Windows Systems + + + + &SCons; provides a Windows installer + that makes installation extremely easy. + Download the scons-0.95.win32.exe + file from the &SCons; download page at + http://www.scons.org/download.html. + 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. + + + + + + + +
+ +
+ +
+ Building and Installing &SCons; on Any System + + + + 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 distutils package. + + + + + + The first step is to download either the + scons-__VERSION__.tar.gz + or scons-__VERSION__.zip, + which are available from the SCons download page at + http://www.scons.org/download.html. + + + + + + Unpack the archive you downloaded, + using a utility like tar + on Linux or UNIX, + or WinZip on Windows. + This will create a directory called + scons-__VERSION__, + usually in your local directory. + Then change your working directory to that directory + and install &SCons; by executing the following commands: + + + + + # cd scons-__VERSION__ + # python setup.py install + + + + + This will build &SCons;, + install the scons script + in the default system scripts directory + (/usr/local/bin or + C:\Python2.2\Scripts), + and will install the &SCons; build engine + in an appropriate stand-alone library directory + (/usr/local/lib/scons or + C:\Python2.2\scons). + Because these are system directories, + you may need root (on Linux or UNIX) or Administrator (on Windows) + privileges to install &SCons; like this. + + + +
+ Building and Installing &SCons; Without Administrative Privileges + + + + 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 --prefix= option: + + + + + # python setup.py install --prefix=$HOME + + + + + This would install &SCons; in appropriate locations + relative to the user's $HOME directory, + the scons script in + $HOME/bin + and the build engine in + $HOME/lib/scons. + You may, of course, specify any other location you prefer. + + + +
+ + + +
+ Building and Installing Multiple Versions of &SCons; Side-by-Side + + + + The &SCons; setup.py 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. + + + + + + To install &SCons; in a version-specific location, + add the option + when you call setup.py: + + + + + # python setup.py install --version-lib + + + + + This will install the &SCons; build engine + in the + /usr/lib/scons-__VERSION__ + or + C:\Python2.2\scons-__VERSION__ + directory, for example. + You can also specify , + in which case setup.py + will install the build engine + in a version-specific directory + relative to the specified prefix. + + + + + + If you use the option + the first time you install &SCons;, + you do not need to specify it each time you install + a new version. + The &SCons; setup.py 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. + + + +
+ +
+ + 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 @@ + + + + + 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. + + + + + +
+ Installing Python + + + + 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 + python + at your system's command-line prompt. + You should see something like the following + on a UNIX or Linux system that has Python installed: + + + + + $ python + 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. + >>> ^D + + + + + And on a Windows system with Python installed: + + + + + C:\>python + 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. + >>> ^Z + + + + + The >>> is the input prompt + for the Python interpreter. + The ^D and ^Z + 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;. + + + + + + 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;. + + + + + + The standard location for information + about downloading and installing Python is + http://www.python.org/download/. + See that page for information about + how to download and install Python on your system. + + + +
+ +
+ Installing &SCons; From Pre-Built Packages + + + + &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. + + + +
+ Installing &SCons; on Red Hat (and Other RPM-based) Linux Systems + + + + &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 + http://www.rpmfind.net/ or + http://rpm.pbone.net/. + + + + + + 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 /usr/bin, + and the SCons library modules in + /usr/lib/scons. + + + + + + To install from the command line, simply download the + appropriate .rpm file, + and then run: + + + + + # rpm -Uvh scons-0.96-1.noarch.rpm + + + + + Or, you can use a graphical RPM package manager + like gnorpm. + See your package manager application's documention + for specific instructions about + how to use it to install a downloaded RPM. + + + +
+ +
+ Installing &SCons; on Debian Linux Systems + + + + Debian Linux systems use a different package management + format that also makes it very easy to install &SCons;. + + + + + + If your system is connected to the Internet, + you can install the latest official Debian package + by running: + + + + + # apt-get install scons + + + + +
+ +
+ Installing &SCons; on Windows Systems + + + + &SCons; provides a Windows installer + that makes installation extremely easy. + Download the scons-0.95.win32.exe + file from the &SCons; download page at + http://www.scons.org/download.html. + 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. + + + + + + + +
+ +
+ +
+ Building and Installing &SCons; on Any System + + + + 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 distutils package. + + + + + + The first step is to download either the + scons-__VERSION__.tar.gz + or scons-__VERSION__.zip, + which are available from the SCons download page at + http://www.scons.org/download.html. + + + + + + Unpack the archive you downloaded, + using a utility like tar + on Linux or UNIX, + or WinZip on Windows. + This will create a directory called + scons-__VERSION__, + usually in your local directory. + Then change your working directory to that directory + and install &SCons; by executing the following commands: + + + + + # cd scons-__VERSION__ + # python setup.py install + + + + + This will build &SCons;, + install the scons script + in the default system scripts directory + (/usr/local/bin or + C:\Python2.2\Scripts), + and will install the &SCons; build engine + in an appropriate stand-alone library directory + (/usr/local/lib/scons or + C:\Python2.2\scons). + Because these are system directories, + you may need root (on Linux or UNIX) or Administrator (on Windows) + privileges to install &SCons; like this. + + + +
+ Building and Installing &SCons; Without Administrative Privileges + + + + 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 --prefix= option: + + + + + # python setup.py install --prefix=$HOME + + + + + This would install &SCons; in appropriate locations + relative to the user's $HOME directory, + the scons script in + $HOME/bin + and the build engine in + $HOME/lib/scons. + You may, of course, specify any other location you prefer. + + + +
+ + + +
+ Building and Installing Multiple Versions of &SCons; Side-by-Side + + + + The &SCons; setup.py 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. + + + + + + To install &SCons; in a version-specific location, + add the option + when you call setup.py: + + + + + # python setup.py install --version-lib + + + + + This will install the &SCons; build engine + in the + /usr/lib/scons-__VERSION__ + or + C:\Python2.2\scons-__VERSION__ + directory, for example. + You can also specify , + in which case setup.py + will install the build engine + in a version-specific directory + relative to the specified prefix. + + + + + + If you use the option + the first time you install &SCons;, + you do not need to specify it each time you install + a new version. + The &SCons; setup.py 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. + + + +
+ +
+ + 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 @@ - + % scons -Q hello 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 Cscons -Q hello scons: `hello' is up to date. - + @@ -748,7 +748,7 @@ operating system on which the build is performed (as reported by C
- The &Depends; Method + Explicit Dependencies: the &Depends; Method @@ -770,7 +770,7 @@ operating system on which the build is performed (as reported by C - + % scons -Q hello 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 Cscons -Q hello cc -c hello.c -o hello.o cc -o hello hello.o - +
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 @@ - + % scons -Q hello 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 Cscons -Q hello scons: `hello' is up to date. - + @@ -760,7 +760,7 @@ operating system on which the build is performed (as reported by C
- The &Depends; Method + Explicit Dependencies: the &Depends; Method @@ -782,7 +782,7 @@ operating system on which the build is performed (as reported by C - + % scons -Q hello 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 Cscons -Q hello cc -c hello.c -o hello.o cc -o hello hello.o - +
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 @@ + + + + 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. + + + +
+ Building Java Class Files: the &Java; Builder + + + + The basic activity when programming in Java, + of course, is to take one or more .java files + containing Java source code + and to call the Java compiler + to turn them into one or more + .class files. + In &SCons;, you do this + by giving the &Java; Builder + a target directory in which + to put the .class files, + and a source directory that contains + the .java files: + + + + + + Java('classes', 'src') + + + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + + + public class Example2 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + + + public class Example3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + + + + + + If the src directory contains + three .java source files, + then running &SCons; might look like this: + + + + + scons -Q + + + + + &SCons; will actually search the src + directory tree for all of the .java files. + The Java compiler will then create the + necessary class files in the classes subdirectory, + based on the class names found in the .java files. + + + +
+ +
+ How &SCons; Handles Java Dependencies + + + scons -Q + scons -Q classes + + +
+ +
+ Building Java Archive (<filename>.jar</filename>) Files: the &Jar; Builder + + + + After building the class files, + it's common to collect them into + a Java archive (.jar) 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: + + + + + + Java(target = 'classes', source = 'src') + Jar(target = 'test.jar', source = 'classes') + + + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + + + public class Example2 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + + + public class Example3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + + + + + + &SCons; will then pass that directory + to the &jar; command, + which will collect all of the underlying + .class files: + + + + + scons -Q + + + + + If you want to keep all of the + .class files + for multiple programs in one location, + and only archive some of them in + each .jar file, + you can pass the &Jar; builder a + list of files as its source. + It's extremely simple to create multiple + .jar files this way, + using the lists of target class files created + by calls to the &Java; builder + as sources to the various &Jar; calls: + + + + + + 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) + + + public class Example1 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + + + public class Example2 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + + + public class Example3 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + + + public class Example4 + { + public static void main(String[] args) + { + System.out.println("Hello Java world!\n"); + } + } + + + + + + This will then create + prog1.jar + and prog2.jar + next to the subdirectories + that contain their .java files: + + + + + scons -Q + + +
+ +
+ Building C Header and Stub Files: the &JavaH; Builder + + + + 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: + + + + + + classes = Java(target = 'classes', source = 'src/pkg/sub') + JavaH(target = 'native', source = classes) + + + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + + + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + + + package pkg.sub; + public class Example3 + { + public static void main(String[] args) + { + } + } + + + + + + 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 + when &SCons; runs &javah;: + + + + + scons -Q + + + + + In this case, + the call to &javah; + will generate the header files + native/pkg_sub_Example1.h, + native/pkg_sub_Example2.h + and + native/pkg_sub_Example3.h. + Notice that &SCons; remembered that the class + files were generated with a target directory of + classes, + and that it then specified that target directory + as the option + to the call to &javah;. + + + + + + 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 can + 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;: + + + + + + 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') + + + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + + + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + + + package pkg.sub; + public class Example3 + { + public static void main(String[] args) + { + } + } + + + + + + The &JAVACLASSDIR; value then + gets converted into the + when &SCons; runs &javah;: + + + + + scons -Q + + + + + 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: + + + + + + classes = Java(target = 'classes', source = 'src/pkg/sub') + JavaH(target = File('native.h'), source = classes) + + + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + + + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + + + package pkg.sub; + public class Example3 + { + public static void main(String[] args) + { + } + } + + + + + + 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 native.h. + When a file is used, though, + &SCons; correctly converts the file name + into the &javah; option: + + + + + scons -Q + + +
+ +
+ Building RMI Stub and Skeleton Class Files: the &RMIC; Builder + + + + 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 _Stub.class + and _Skel.class files will + be placed: + + + + + + classes = Java(target = 'classes', source = 'src/pkg/sub') + RMIC(target = 'outdir', source = classes) + + + package pkg.sub; + public class Example1 + { + public static void main(String[] args) + { + } + } + + + package pkg.sub; + public class Example2 + { + public static void main(String[] args) + { + } + } + + + + + + As it did with the &JavaH; Builder, + &SCons; remembers the class directory + and passes it as the option + to &rmic: + + + + + scons -Q + + + + + This example would generate the files + outdir/pkg/sub/Example1_Skel.class, + outdir/pkg/sub/Example1_Stub.class, + outdir/pkg/sub/Example2_Skel.class and + outdir/pkg/sub/Example2_Stub.class. + + + +
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 @@ + + + + + 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. + + + +
+ Building Java Class Files: the &Java; Builder + + + + The basic activity when programming in Java, + of course, is to take one or more .java files + containing Java source code + and to call the Java compiler + to turn them into one or more + .class files. + In &SCons;, you do this + by giving the &Java; Builder + a target directory in which + to put the .class files, + and a source directory that contains + the .java files: + + + + + Java('classes', 'src') + + + + + If the src directory contains + three .java source files, + then running &SCons; might look like this: + + + + + % scons -Q + javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java + + + + + &SCons; will actually search the src + directory tree for all of the .java files. + The Java compiler will then create the + necessary class files in the classes subdirectory, + based on the class names found in the .java files. + + + +
+ +
+ How &SCons; Handles Java Dependencies + + + % scons -Q + javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java + % scons -Q classes + scons: `classes' is up to date. + + +
+ +
+ Building Java Archive (<filename>.jar</filename>) Files: the &Jar; Builder + + + + After building the class files, + it's common to collect them into + a Java archive (.jar) 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: + + + + + Java(target = 'classes', source = 'src') + Jar(target = 'test.jar', source = 'classes') + + + + + &SCons; will then pass that directory + to the &jar; command, + which will collect all of the underlying + .class files: + + + + + % scons -Q + javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java + jar cf test.jar classes + + + + + If you want to keep all of the + .class files + for multiple programs in one location, + and only archive some of them in + each .jar file, + you can pass the &Jar; builder a + list of files as its source. + It's extremely simple to create multiple + .jar files this way, + using the lists of target class files created + by calls to the &Java; builder + as sources to the various &Jar; calls: + + + + + 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) + + + + + This will then create + prog1.jar + and prog2.jar + next to the subdirectories + that contain their .java files: + + + + + % scons -Q + 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 + + +
+ +
+ Building C Header and Stub Files: the &JavaH; Builder + + + + 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: + + + + + classes = Java(target = 'classes', source = 'src/pkg/sub') + JavaH(target = 'native', source = classes) + + + + + 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 + when &SCons; runs &javah;: + + + + + % scons -Q + 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 + + + + + In this case, + the call to &javah; + will generate the header files + native/pkg_sub_Example1.h, + native/pkg_sub_Example2.h + and + native/pkg_sub_Example3.h. + Notice that &SCons; remembered that the class + files were generated with a target directory of + classes, + and that it then specified that target directory + as the option + to the call to &javah;. + + + + + + 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 can + 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;: + + + + + 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') + + + + + The &JAVACLASSDIR; value then + gets converted into the + when &SCons; runs &javah;: + + + + + % scons -Q + 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 + + + + + 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: + + + + + classes = Java(target = 'classes', source = 'src/pkg/sub') + JavaH(target = File('native.h'), source = classes) + + + + + 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 native.h. + When a file is used, though, + &SCons; correctly converts the file name + into the &javah; option: + + + + + % scons -Q + 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 + + +
+ +
+ Building RMI Stub and Skeleton Class Files: the &RMIC; Builder + + + + 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 _Stub.class + and _Skel.class files will + be placed: + + + + + classes = Java(target = 'classes', source = 'src/pkg/sub') + RMIC(target = 'outdir', source = classes) + + + + + As it did with the &JavaH; Builder, + &SCons; remembers the class directory + and passes it as the option + to &rmic;: + + + + + % scons -Q + 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 + + + + + This example would generate the files + outdir/pkg/sub/Example1_Skel.class, + outdir/pkg/sub/Example1_Stub.class, + outdir/pkg/sub/Example2_Skel.class and + outdir/pkg/sub/Example2_Stub.class. + + + +
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 @@ + + + + + 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. + + + +
+ Specifying the Name of the Target (Output) File + + + + 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: + + + + + Program('hello.c') + + + + + 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: + + + + + + Program('new_hello', 'hello.c') + + + int main() { printf("Hello, world!\n"); } + + + + + + (&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: + "program = source files".) + + + + + + Now &SCons; will build an executable program + named &new_hello; when run on a POSIX system: + + + + + scons -Q + + + + + And &SCons; will build an executable program + named &new_hello_exe; when run on a Windows system: + + + + + scons -Q + + +
+ +
+ Compiling Multiple Source Files + + + + 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: + + + + + + Program(['main.c', 'file1.c', 'file2.c']) + + + int main() { printf("main.c\n"); } + + + void file1() { printf("file1.c\n"); } + + + void file2() { printf("file2.c\n"); } + + + + + + A build of the above example would look like: + + + + + scons -Q + + + + + 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: + + + + + + Program('program', ['main.c', 'file1.c', 'file2.c']) + + + int main() { printf("prog.c\n"); } + + + void file1() { printf("file1.c\n"); } + + + void file2() { printf("file2.c\n"); } + + + + + + On Linux, a build of this example would look like: + + + + + scons -Q + + + + + Or on Windows: + + + + + scons -Q + + +
+ +
+ Specifying Single Files Vs. Lists of Files + + + + We've now shown you two ways to specify + the source for a program, + one with a list of files: + + + + + Program('hello', ['file1.c', 'file2']) + + + + + And one with a single file: + + + + + Program('hello', 'hello.c') + + + + + You could actually put a single file name in a list, too, + which you might prefer just for the sake of consistency: + + + + + Program('hello', ['hello.c']) + + + + + &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. + + + + + + + + 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: + + + + + # The following two calls both work correctly: + Program('program1', 'program1.c') + Program('program2', ['program2.c']) + + + + + Trying to do "Python things" that mix strings and + lists will cause errors or lead to incorrect results: + + + + + 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']) + + + + +
+ +
+ Making Lists of Files Easier to Read + + + + 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. + + + + + + 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: + + + + + Program('program', Split('main.c file1.c file2.c')) + + + + + (If you're already familiar with Python, + you'll have realized that this is similar to the + split() method + in the Python standard string module. + Unlike the string.split() 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.) + + + + + + Putting the call to the &Split; function + inside the Program call + can also be a little unwieldy. + A more readable alternative is to + assign the output from the &Split; call + to a variable name, + and then use the variable when calling the + Program function: + + + + + list = Split('main.c file1.c file2.c') + Program('program', list) + + + + + 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: + + + + + list = Split("""main.c + file1.c + file2.c""") + Program('program', list) + + + + + (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.) + + + +
+ +
+ Keyword Arguments + + + + &SCons; also allows you to identify + the output file and input source files + using Python keyword arguments. + The output file is known as the + target, + and the source file(s) are known (logically enough) as the + source. + The Python syntax for this is: + + + + + list = Split('main.c file1.c file2.c') + Program(target = 'program', source = list) + + + + + Because the keywords explicitly identify + what each argument is, + you can actually reverse the order if you prefer: + + + + + list = Split('main.c file1.c file2.c') + Program(source = list, target = 'program') + + + + + 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. + + + +
+ +
+ Compiling Multiple Programs + + + + In order to compile multiple programs + within the same &SConstruct; file, + simply call the Program method + multiple times, + once for each program you need to build: + + + + + + Program('foo.c') + Program('bar', ['bar1.c', 'bar2.c']) + + + int main() { printf("foo.c\n"); } + + + int main() { printf("bar1.c\n"); } + + + void bar2() { printf("bar2.c\n"); } + + + + + + &SCons; would then build the programs as follows: + + + + + scons -Q + + + + + 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. + + + +
+ +
+ Sharing Source Files Between Multiple Programs + + + + 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 + , below.) + + + + + + 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: + + + + + + Program(Split('foo.c common1.c common2.c')) + Program('bar', Split('bar1.c bar2.c common1.c common2.c')) + + + int main() { printf("foo.c\n"); } + + + int main() { printf("bar1.c\n"); } + + + int bar2() { printf("bar2.c\n"); } + + + void common1() { printf("common1.c\n"); } + + + void common22() { printf("common2.c\n"); } + + + + + + &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: + + + + + scons -Q + + + + + 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: + + + + + 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) + + + + + This is functionally equivalent to the previous example. + + + +
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 @@ + + + + + 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. + + + +
+ Specifying the Name of the Target (Output) File + + + + 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: + + + + + Program('hello.c') + + + + + 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: + + + + + Program('new_hello', 'hello.c') + + + + + (&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: + "program = source files".) + + + + + + Now &SCons; will build an executable program + named &new_hello; when run on a POSIX system: + + + + + % scons -Q + cc -c -o hello.o hello.c + cc -o new_hello hello.o + + + + + And &SCons; will build an executable program + named &new_hello_exe; when run on a Windows system: + + + + + C:\>scons -Q + cl /nologo /c hello.c /Fohello.obj + link /nologo /OUT:new_hello.exe hello.obj + + +
+ +
+ Compiling Multiple Source Files + + + + 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: + + + + + Program(['main.c', 'file1.c', 'file2.c']) + + + + + A build of the above example would look like: + + + + + % scons -Q + 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 + + + + + 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: + + + + + Program('program', ['main.c', 'file1.c', 'file2.c']) + + + + + On Linux, a build of this example would look like: + + + + + % scons -Q + 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 + + + + + Or on Windows: + + + + + C:\>scons -Q + 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 + + +
+ +
+ Specifying Single Files Vs. Lists of Files + + + + We've now shown you two ways to specify + the source for a program, + one with a list of files: + + + + + Program('hello', ['file1.c', 'file2']) + + + + + And one with a single file: + + + + + Program('hello', 'hello.c') + + + + + You could actually put a single file name in a list, too, + which you might prefer just for the sake of consistency: + + + + + Program('hello', ['hello.c']) + + + + + &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. + + + + + + + + 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: + + + + + # The following two calls both work correctly: + Program('program1', 'program1.c') + Program('program2', ['program2.c']) + + + + + Trying to do "Python things" that mix strings and + lists will cause errors or lead to incorrect results: + + + + + 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']) + + + + +
+ +
+ Making Lists of Files Easier to Read + + + + 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. + + + + + + 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: + + + + + Program('program', Split('main.c file1.c file2.c')) + + + + + (If you're already familiar with Python, + you'll have realized that this is similar to the + split() method + in the Python standard string module. + Unlike the string.split() 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.) + + + + + + Putting the call to the &Split; function + inside the Program call + can also be a little unwieldy. + A more readable alternative is to + assign the output from the &Split; call + to a variable name, + and then use the variable when calling the + Program function: + + + + + list = Split('main.c file1.c file2.c') + Program('program', list) + + + + + 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: + + + + + list = Split("""main.c + file1.c + file2.c""") + Program('program', list) + + + + + (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.) + + + +
+ +
+ Keyword Arguments + + + + &SCons; also allows you to identify + the output file and input source files + using Python keyword arguments. + The output file is known as the + target, + and the source file(s) are known (logically enough) as the + source. + The Python syntax for this is: + + + + + list = Split('main.c file1.c file2.c') + Program(target = 'program', source = list) + + + + + Because the keywords explicitly identify + what each argument is, + you can actually reverse the order if you prefer: + + + + + list = Split('main.c file1.c file2.c') + Program(source = list, target = 'program') + + + + + 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. + + + +
+ +
+ Compiling Multiple Programs + + + + In order to compile multiple programs + within the same &SConstruct; file, + simply call the Program method + multiple times, + once for each program you need to build: + + + + + Program('foo.c') + Program('bar', ['bar1.c', 'bar2.c']) + + + + + &SCons; would then build the programs as follows: + + + + + % scons -Q + 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 + + + + + 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. + + + +
+ +
+ Sharing Source Files Between Multiple Programs + + + + 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 + , below.) + + + + + + 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: + + + + + Program(Split('foo.c common1.c common2.c')) + Program('bar', Split('bar1.c bar2.c common1.c common2.c')) + + + + + &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: + + + + + % scons -Q + 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 + + + + + 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: + + + + + 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) + + + + + This is functionally equivalent to the previous example. + + + +
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 @@ + Troubleshooting &troubleshoot; - --> - + Troubleshooting &troubleshoot; - --> - + + + + Internally, &SCons; represents all of the files + and directories it knows about as &Nodes;. + These internal objects + (not object files) + can be used in a variety of ways + to make your &SConscript; + files portable and easy to read. + + + +
+ Builder Methods Return Lists of Target Nodes + + + + 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, + + + + + + 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: + + + + + Object('hello.c', CCFLAGS='-DHELLO') + Object('goodbye.c', CCFLAGS='-DGOODBYE') + + + + + 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: + + + + + Object('hello.c', CCFLAGS='-DHELLO') + Object('goodbye.c', CCFLAGS='-DGOODBYE') + Program(['hello.o', 'goodbye.o']) + + + + + 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;. + + + + + + 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: + + + + + + hello_list = Object('hello.c', CCFLAGS='-DHELLO') + goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE') + Program(hello_list + goodbye_list) + + + int main() { printf("Hello, world!\n"); } + + + int main() { printf("Goodbye, world!\n"); } + + + + + + This makes our &SConstruct; file portable again, + the build output on Linux looking like: + + + + + scons -Q + + + + + And on Windows: + + + + + scons -Q + + + + + We'll see examples of using the list of nodes + returned by builder methods throughout + the rest of this guide. + + + +
+ +
+ Explicitly Creating File and Directory Nodes + + + + 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: + + + + + + hello_c = File('hello.c') + Program(hello_c) + + classes = Dir('classes') + Java(classes, 'src') + + + + + + 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. + + + + + + + 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. + + + + + xyzzy = Entry('xyzzy') + + + + + The returned xyzzy 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. + + + +
+ +
+ Printing &Node; File Names + + + + 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: + + + + + + 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] + + + int main() { printf("Hello, world!\n"); } + + + + + + Would print the following file names on a POSIX system: + + + + + scons -Q + + + + + And the following file names on a Windows system: + + + + + scons -Q + + +
+ +
+ Using a &Node;'s File Name as a String + + + + 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 + os.path.exists + to figure out whether a file + exists while the &SConstruct; file + is being read and executed, + you can fetch the string as follows: + + + + + + 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!" + + + int main() { printf("Hello, world!\n"); } + + + + + + Which executes as follows on a POSIX system: + + + + + scons -Q + + +
+ + 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 @@ + + + + + Internally, &SCons; represents all of the files + and directories it knows about as &Nodes;. + These internal objects + (not object files) + can be used in a variety of ways + to make your &SConscript; + files portable and easy to read. + + + +
+ Builder Methods Return Lists of Target Nodes + + + + 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, + + + + + + 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: + + + + + Object('hello.c', CCFLAGS='-DHELLO') + Object('goodbye.c', CCFLAGS='-DGOODBYE') + + + + + 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: + + + + + Object('hello.c', CCFLAGS='-DHELLO') + Object('goodbye.c', CCFLAGS='-DGOODBYE') + Program(['hello.o', 'goodbye.o']) + + + + + 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;. + + + + + + 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: + + + + + hello_list = Object('hello.c', CCFLAGS='-DHELLO') + goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE') + Program(hello_list + goodbye_list) + + + + + This makes our &SConstruct; file portable again, + the build output on Linux looking like: + + + + + % scons -Q + cc -DGOODBYE -c -o goodbye.o goodbye.c + cc -DHELLO -c -o hello.o hello.c + cc -o hello hello.o goodbye.o + + + + + And on Windows: + + + + + C:\>scons -Q + cl -DGOODBYE /c goodbye.c /Fogoodbye.obj + cl -DHELLO /c hello.c /Fohello.obj + link /nologo /OUT:hello.exe hello.obj goodbye.obj + + + + + We'll see examples of using the list of nodes + returned by builder methods throughout + the rest of this guide. + + + +
+ +
+ Explicitly Creating File and Directory Nodes + + + + 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: + + + + + hello_c = File('hello.c') + Program(hello_c) + + classes = Dir('classes') + Java(classes, 'src') + + + + + 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. + + + + + + + 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. + + + + + xyzzy = Entry('xyzzy') + + + + + The returned xyzzy 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. + + + +
+ +
+ Printing &Node; File Names + + + + 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: + + + + + 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] + + + + + Would print the following file names on a POSIX system: + + + + + % scons -Q + The object file is: hello.o + The program file is: hello + cc -c -o hello.o hello.c + cc -o hello hello.o + + + + + And the following file names on a Windows system: + + + + + C:\>scons -Q + 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 + + +
+ +
+ Using a &Node;'s File Name as a String + + + + 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 + os.path.exists + to figure out whether a file + exists while the &SConstruct; file + is being read and executed, + you can fetch the string as follows: + + + + + 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!" + + + + + Which executes as follows on a POSIX system: + + + + + % scons -Q + The object file is: hello.o + The program file is: hello + cc -c -o hello.o hello.c + cc -o hello hello.o + + +
+ + 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 @@
+ A Caveat About This Guide's Completeness + + + + 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?) + + + + + + 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...? + + + +
+ +
Acknowledgements @@ -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 @@
+ A Caveat About This Guide's Completeness + + + + 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?) + + + + + + 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...? + + + +
+ +
Acknowledgements @@ -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 @@ - + % cd $HOME/build % edit hello.c % scons -Q -Y /usr/repository1 cc -c -o hello.o hello.c cc -o hello hello.o /usr/repository1/file1.o /usr/repository1/file2.o - + @@ -438,12 +438,12 @@ subdirectories under the repository tree. - + % mkdir $HOME/build2 % cd $HOME/build2 % scons -Q -Y /usr/all/repository hello scons: `hello' is up-to-date. - + @@ -490,11 +490,11 @@ subdirectories under the repository tree. - - % scons -Y /usr/all/repository hello + + % scons -Y /usr/all/repository hello Local copy of hello from /usr/all/repository/hello scons: `hello' is up-to-date. - + 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 @@ - + % cd $HOME/build % edit hello.c % scons -Q -Y /usr/repository1 cc -c -o hello.o hello.c cc -o hello hello.o /usr/repository1/file1.o /usr/repository1/file2.o - + @@ -410,12 +410,12 @@ subdirectories under the repository tree. - + % mkdir $HOME/build2 % cd $HOME/build2 % scons -Q -Y /usr/all/repository hello scons: `hello' is up-to-date. - + @@ -457,11 +457,11 @@ subdirectories under the repository tree. - - % scons -Y /usr/all/repository hello + + % scons -Y /usr/all/repository hello Local copy of hello from /usr/all/repository/hello scons: `hello' is up-to-date. - + 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 @@ + + + + &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. + + + + + + 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. + + + +
+ &Configure_Contexts; + + + + 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: + + + + + env = Environment() + conf = Configure(env) + # Checks for libraries, header files, etc. go here! + env = conf.Finish() + + + + + The next sections describe + the basic checks that &SCons; supports, + as well as how to add your own custom checks. + + + +
+ +
+ Checking for the Existence of Header Files + + + + 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: + + + + + 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() + + + + + 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. + + + + + + If you need to check for the existence + a C++ header file, + use the &CheckCXXHeader; method: + + + + + env = Environment() + conf = Configure(env) + if not conf.CheckCXXHeader('vector.h'): + print 'vector.h must be installed!' + Exit(1) + env = conf.Finish() + + +
+ +
+ Checking for the Availability of a Function + + + + Check for the availability of a specific function + using the &CheckFunc; method: + + + + + 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() + + +
+ +
+ Checking for the Availability of a Library + + + + 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 lib + prefix or a .a or .lib suffix: + + + + + 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() + + + + + If the library requires the inclusion of + a header file to compile successfully, + add that as a second argument: + + + + + 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() + + +
+ +
+ Checking for the Availability of a &typedef; + + + + Check for the availability of a &typedef; + by using the &CheckType; method: + + + + + 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() + + + + + 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;: + + + + + 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() + + +
+ +
+ Adding Your Own Custom Checks + + + + 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: + + + + + 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 + + + + + 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 + ok if the check succeeds and + failed if it doesn't. + The &TryLink; method + actually tests for whether the + specified program text + will successfully link. + + + + + + (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 context.env attribute.) + + + + + + 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: + + + + + env = Environment() + conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) + + + + + You'll typically want to make + the check and the function name the same, + as we've done here, + to avoid potential confusion. + + + + + + We can then put these pieces together + and actually call the CheckMyLibrary check + as follows: + + + + + 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. + + + + + If MyLibrary is not installed on the system, + the output will look like: + + + + + % scons + scons: Reading SConscript file ... + Checking for MyLibrary... failed + MyLibrary is not installed! + + + + + If MyLibrary is installed, + the output will look like: + + + + + % scons + scons: Reading SConscript file ... + Checking for MyLibrary... failed + scons: done reading SConscript + scons: Building targets ... + . + . + . + + +
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 @@ + + + + + &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. + + + + + + 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. + + + +
+ &Configure_Contexts; + + + + 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: + + + + + env = Environment() + conf = Configure(env) + # Checks for libraries, header files, etc. go here! + env = conf.Finish() + + + + + The next sections describe + the basic checks that &SCons; supports, + as well as how to add your own custom checks. + + + +
+ +
+ Checking for the Existence of Header Files + + + + 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: + + + + + 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() + + + + + 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. + + + + + + If you need to check for the existence + a C++ header file, + use the &CheckCXXHeader; method: + + + + + env = Environment() + conf = Configure(env) + if not conf.CheckCXXHeader('vector.h'): + print 'vector.h must be installed!' + Exit(1) + env = conf.Finish() + + +
+ +
+ Checking for the Availability of a Function + + + + Check for the availability of a specific function + using the &CheckFunc; method: + + + + + 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() + + +
+ +
+ Checking for the Availability of a Library + + + + 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 lib + prefix or a .a or .lib suffix: + + + + + 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() + + + + + If the library requires the inclusion of + a header file to compile successfully, + add that as a second argument: + + + + + 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() + + +
+ +
+ Checking for the Availability of a &typedef; + + + + Check for the availability of a &typedef; + by using the &CheckType; method: + + + + + 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() + + + + + 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;: + + + + + 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() + + +
+ +
+ Adding Your Own Custom Checks + + + + 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: + + + + + 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 + + + + + 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 + ok if the check succeeds and + failed if it doesn't. + The &TryLink; method + actually tests for whether the + specified program text + will successfully link. + + + + + + (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 context.env attribute.) + + + + + + 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: + + + + + env = Environment() + conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary}) + + + + + You'll typically want to make + the check and the function name the same, + as we've done here, + to avoid potential confusion. + + + + + + We can then put these pieces together + and actually call the CheckMyLibrary check + as follows: + + + + + 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. + + + + + If MyLibrary is not installed on the system, + the output will look like: + + + + + % scons + scons: Reading SConscript file ... + Checking for MyLibrary... failed + MyLibrary is not installed! + + + + + If MyLibrary is installed, + the output will look like: + + + + + % scons + scons: Reading SConscript file ... + Checking for MyLibrary... failed + scons: done reading SConscript + scons: Building targets ... + . + . + . + + +
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 @@ - + - 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. - + -
- XXX +
+ Why is That Target Being Rebuilt? the &debug-explain; Option - + - XXX + Let's take a simple example of + a misconfigured build + that causes a target to be rebuilt + every time &SCons; is run: - + -
+ + + # Intentionally misspell the output file name in the + # command used to create the file: + Command('file.out', 'file.in', 'cp $SOURCE file.oout') + + + file.in + + + + + + (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.) + + + + + + Now if we run &SCons; multiple on this example, + we see that it re-runs the &cp; + command every time: + + + + + scons -Q + scons -Q + scons -Q + + + + + 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: + + + + + scons -Q --debug=explain + + + + + 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. + + + + + + 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: + + + + + + Program('prog', ['file1.c', 'file2.c', 'file3.c']) + + + file1.c + + + file2.c + + + file3.c + + + + + scons -Q + edit file2.c + scons -Q --debug=explain + + + + + This becomes even more helpful + in identifying when a file is rebuilt + due to a change in an implicit dependency, + such as an incuded .h file. + If the file1.c + and file3.c 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: + + + + + + Program('prog', ['file1.c', 'file2.c', 'file3.c'], CPPPATH='.') + + + #include <hello.h> + file1.c + + + file2.c + + + #include <hello.h> + file3.c + + + #define string "world" + + + + + scons -Q + edit hello.h + scons -Q --debug=explain + + +
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 @@ - + - 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. - + -
- XXX +
+ Why is That Target Being Rebuilt? the &debug-explain; Option - + - XXX + Let's take a simple example of + a misconfigured build + that causes a target to be rebuilt + every time &SCons; is run: - + -
+ + # Intentionally misspell the output file name in the + # command used to create the file: + Command('file.out', 'file.in', 'cp $SOURCE file.oout') + + + + + (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.) + + + + + + Now if we run &SCons; multiple on this example, + we see that it re-runs the &cp; + command every time: + + + + + % scons -Q + cp file.in file.oout + % scons -Q + cp file.in file.oout + % scons -Q + cp file.in file.oout + + + + + 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: + + + + + % scons -Q --debug=explain + scons: building `file.out' because it doesn't exist + cp file.in file.oout + + + + + 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. + + + + + + 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: + + + + + + + % scons -Q + 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 + % edit file2.c + [CHANGE THE CONTENTS OF file2.c] + % scons -Q --debug=explain + 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 + + + + + This becomes even more helpful + in identifying when a file is rebuilt + due to a change in an implicit dependency, + such as an incuded .h file. + If the file1.c + and file3.c 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: + + + + + + + % scons -Q + 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 + % edit hello.h + [CHANGE THE CONTENTS OF hello.h] + % scons -Q --debug=explain + 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 + + +
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 @@