From 15da9cb4667872d0da09e5c0bb684d92197c5e34 Mon Sep 17 00:00:00 2001 From: Steven Knight Date: Wed, 21 May 2003 13:01:13 +0000 Subject: Branch for User's Guide updates. --- SConstruct | 5 +- doc/scons.mod | 56 +++- doc/user/actions.sgml | 6 +- doc/user/ant.sgml | 41 +++ doc/user/builders-built-in.sgml | 628 ++++++++++++++++++++++++++++++++++++++ doc/user/builders-commands.sgml | 108 +++++++ doc/user/builders-writing.sgml | 658 ++++++++++++++++++++++++++++++++++++++++ doc/user/builders.sgml | 469 ---------------------------- doc/user/caching.sgml | 2 + doc/user/command.sgml | 108 ------- doc/user/cons.sgml | 6 +- doc/user/default.sgml | 2 +- doc/user/depends.sgml | 393 +++++++++++++++++++----- doc/user/environments.sgml | 16 +- doc/user/errors.sgml | 6 +- doc/user/example.sgml | 6 +- doc/user/hierarchy.sgml | 10 +- doc/user/install.sgml | 4 +- doc/user/libraries.sgml | 250 +++++++++++++++ doc/user/main.sgml | 34 ++- doc/user/make.sgml | 6 +- doc/user/preface.sgml | 185 +++++++++-- doc/user/repositories.sgml | 2 +- doc/user/run.sgml | 100 ++---- doc/user/scanners.sgml | 6 +- doc/user/separate.sgml | 410 +++++++++++++++---------- doc/user/simple.sgml | 133 ++++++-- doc/user/sourcecode.sgml | 10 +- doc/user/troubleshoot.sgml | 6 +- doc/user/variants.sgml | 123 +++++--- 30 files changed, 2771 insertions(+), 1018 deletions(-) create mode 100644 doc/user/ant.sgml create mode 100644 doc/user/builders-built-in.sgml create mode 100644 doc/user/builders-commands.sgml create mode 100644 doc/user/builders-writing.sgml delete mode 100644 doc/user/builders.sgml delete mode 100644 doc/user/command.sgml create mode 100644 doc/user/libraries.sgml diff --git a/SConstruct b/SConstruct index 87eafb0..b1af691 100644 --- a/SConstruct +++ b/SConstruct @@ -865,7 +865,10 @@ if change: for f in pf + cf: u[f] = 1 for f in df: - del u[f] + try: + del u[f] + except KeyError: + pass sfiles = filter(lambda x: x[-9:] != '.aeignore' and x[-9:] != '.sconsign', u.keys()) diff --git a/doc/scons.mod b/doc/scons.mod index 32283c3..f9deaa1 100644 --- a/doc/scons.mod +++ b/doc/scons.mod @@ -14,14 +14,20 @@ --> +Aegis"> Autoconf"> Cons"> gcc"> +Jam"> Make"> Make++"> +ranlib"> SCons"> scons"> ScCons"> +tar"> +touch"> +zip"> +build"> Makefile"> Makefiles"> SConscript"> @@ -68,6 +75,7 @@ Sconstruct"> sconstruct"> .sconsign"> +src"> @@ -106,10 +114,17 @@ Repository"> RuleSet"> Salt"> +SetBuildSignatureType"> +SetContentSignatureType"> SourceSignature"> +SourceSignatures"> Split"> +TargetSignatures"> Task"> +str"> +zipfile"> + Cache"> @@ -125,6 +140,8 @@ BUILDERS"> SCANNERMAP"> SCANNERS"> +TARFLAGS"> +TARSUFFIX"> @@ -137,6 +154,7 @@ CC"> CCFLAGS"> LIBPATH"> +LIBS"> PYTHONPATH"> SCONSFLAGS"> @@ -144,6 +162,18 @@ + +build_dir"> +source"> +target"> + + + + @@ -151,6 +181,10 @@ BuildDir"> CFile"> CXXFile"> +DVI"> +Jar"> +Java"> +JavaH"> Library"> Object"> PCH"> @@ -158,10 +192,13 @@ PostScript"> Program"> RES"> +RMIC"> SharedLibrary"> SharedObject"> StaticLibrary"> StaticObject"> +Tar"> +Zip"> Make"> @@ -175,6 +212,8 @@ --> +builder function"> + Construction Environment"> Construction Environments"> Construction environment"> @@ -193,14 +232,29 @@ Dictionary"> +Emitter"> +emitter"> +Generator"> +generator"> + +signature"> +build signature"> + +common1.c"> +common2.c"> goodbye"> hello"> hello.c"> +hello.exe"> hello.h"> +hello.o"> +prog"> +prog.c"> +prog.exe"> stdio.h"> diff --git a/doc/user/actions.sgml b/doc/user/actions.sgml index 447b331..c35ccdd 100644 --- a/doc/user/actions.sgml +++ b/doc/user/actions.sgml @@ -224,16 +224,16 @@ solutions to the above limitations. - X + XXX
- X + XXX - X + XXX diff --git a/doc/user/ant.sgml b/doc/user/ant.sgml new file mode 100644 index 0000000..f83ab63 --- /dev/null +++ b/doc/user/ant.sgml @@ -0,0 +1,41 @@ + + + + + XXX + + + +
+ XXX + + + + XXX + + + +
diff --git a/doc/user/builders-built-in.sgml b/doc/user/builders-built-in.sgml new file mode 100644 index 0000000..bb29cc4 --- /dev/null +++ b/doc/user/builders-built-in.sgml @@ -0,0 +1,628 @@ + + + + + &SCons; provides the ability to build a lot of different + types of files right "out of the box." + So far, we've been using &SCons;' ability to build + programs, objects and libraries to + illustrate much of the underlying functionality of &SCons; + This section will describe all of the different + types of files that you can build with &SCons;, + and the built-in &Builder; objects used to build them. + + + +
+ Programs: the &Program; Builder + + + + As we've seen, the &Program; Builder + is used to build an executable program. + The &source; argument is one or more + source-code files or object files, + and the ⌖ argument is the + name of the executable program name to be created. + For example: + + + + + env = Environment() + env.Program('prog', 'file1.o') + + + + + Will create the &prog; + executable on a POSIX system, + the &prog_exe; executable on a Windows system. + + + + + + The target file's prefix and suffix may be omitted, + and the values from the + $PROGPREFIX + and + $PROGSUFFIX + construction variables + will be appended appropriately. + For example: + + + + + env = Environment(PROGPREFIX='my', PROGSUFFIX='.xxx') + env.Program('prog', ['file1.o', 'file2.o']) + + + + + Will create a program named + myprog.xxx + regardless of the system on which it is run. + + + + + + If you omit the ⌖, + the base of the first input + file name specified + because the base of the target + program created. + For example: + + + + + env = Environment() + env.Program(['hello.c', 'goodbye.c']) + + + + + Will create the &hello; + executable on a POSIX system, + the &hello_exe; executable on a Windows system. + + + +
+ +
+ Object-File Builders + + + + &SCons; provides separate Builder objects + to create both static and shared object files. + + + +
+ The &StaticObject; Builder + + + + XXX + + + + + XXX + + + + XXX + + +
+ +
+ The &SharedObject; Builder + + + + XXX + + + + + XXX + + + + XXX + + +
+ +
+ The &Object; Builder + + + + XXX + + + + + XXX + + + + + Creates a static object file. + + + +
+ +
+ +
+ Library Builders + + + + &SCons; provides separate Builder objects + to create both static and shared libraries. + + + +
+ The &StaticLibrary; Builder + + + + XXX + + + + + XXX + + + + XXX + + +
+ +
+ The &SharedLibrary; Builder + + + + XXX + + + +
+ +
+ The &Library; Builder + + + + XXX + + + + + XXX + + + + XXX + + + + + Creates a static library file. + + + +
+ +
+ +
+ Pre-Compiled Headers: the &PCH; Builder + + + + XXX + + + +
+ +
+ Microsoft Visual C++ Resource Files: the &RES; Builder + + + + XXX + + + +
+ +
+ Source Files + + + + By default + &SCons; supports two Builder objects + that know how to build source files + from other input files. + + + +
+ The &CFile; Builder + + + + XXX + + + + + XXX + + + + XXX + + +
+ +
+ The &CXXFile; Builder + + + + XXX + + + + + XXX + + + + XXX + + +
+ +
+ +
+ Documents + + + + &SCons; provides a number of Builder objects + for creating different types of documents. + + + +
+ The &DVI; Builder + + + + XXX + + + + + XXX + + + + XXX + + +
+ +
+ The &PDF; Builder + + + + XXX + + + +
+ +
+ The &PostScript; Builder + + + + XXX + + + + + XXX + + + + XXX + + +
+ +
+ +
+ Archives + + + + &SCons; provides Builder objects + for creating two different types of archive files. + + + +
+ The &Tar; Builder + + + + The &Tar; Builder object uses the &tar; + utility to create archives of files + and/or directory trees: + + + + + env = Environment() + env.Tar('out1.tar', ['file1', 'file2']) + env.Tar('out2', 'directory') + + + + % scons . + tar -c -f out1.tar file1 file2 + tar -c -f out2.tar directory + + + + + One common requirement when creating a &tar; archive + is to create a compressed archive using the + option. + This is easily handled by specifying + the value of the &TARFLAGS; variable + when you create the construction environment. + Note, however, that the used to + to instruct &tar; to create the archive + is part of the default value of &TARFLAGS;, + so you need to set it both options: + + + + + env = Environment(TARFLAGS = '-c -z') + env.Tar('out.tar.gz', 'directory') + + + + % scons . + tar -c -z -f out.tar.gz directory + + + + + you may also wish to set the value of the + &TARSUFFIX; construction variable + to your desired suffix for compress &tar; archives, + so that &SCons; can append it to the target file name + without your having to specify it explicitly: + + + + + env = Environment(TARFLAGS = '-c -z', + TARSUFFIX = '.tgz') + env.Tar('out', 'directory') + + + + % scons . + tar -c -z -f out.tgz directory + + +
+ +
+ The &Zip; Builder + + + + The &Zip; Builder object creates archives of files + and/or directory trees in the ZIP file format. + Python versions 1.6 or later + contain an internal &zipfile; module + that &SCons; will use. + In this case, given the following + &SConstruct; file: + + + + + env = Environment() + env.Zip('out', ['file1', 'file2']) + + + + + Your output will reflect the fact + that an internal Python function + is being used to create the output ZIP archive: + + + + + % scons . + zip("out.zip", ["file1", "file2"]) + + + + + If you're using Python version 1.5.2 to run &SCons;, + then &SCons; will try to use an external + &zip; program as follows: + + + + + % scons . + zip /home/my/project/zip.out file1 file2 + + +
+ +
+ +
+ Java + + + + &SCons; provides Builder objects + for creating various types of Java output files. + + + +
+ Building Class Files: the &Java; Builder + + + + The &Java; builder takes one or more input + .java files + and turns them into one or more + .class files + Unlike most builders, however, + the &Java; builder takes + target and source directories, + not files, as input. + + + + + env = Environment() + env.Java(target = 'classes', source = 'src') + + + + + The &Java; builder will then + search the specified source directory + tree for all .java files, + and pass any out-of-date + + + + + XXX + + +
+ +
+ The &Jar; Builder + + + + The &Jar; builder object XXX + + + + + env = Environment() + env.Java(target = 'classes', source = 'src') + env.Jar(target = '', source = 'classes') + + + + XXX + + +
+ +
+ Building C header and stub files: the &JavaH; Builder + + + + XXX + + + + + XXX + + + + XXX + + +
+ +
+ Building RMI stub and skeleton class files: the &RMIC; Builder + + + + XXX + + + + + XXX + + + + XXX + + +
+ +
diff --git a/doc/user/builders-commands.sgml b/doc/user/builders-commands.sgml new file mode 100644 index 0000000..e21f6d0 --- /dev/null +++ b/doc/user/builders-commands.sgml @@ -0,0 +1,108 @@ + + + + + + + Creating a &Builder; and attaching it to a &consenv; + allows for a lot of flexibility when you + want to re-use actions + to build multiple files of the same type. + This can, however, be cumbersome + if you only need to execute one specific command + to build a single file (or group of files). + For these situations, &SCons; supports a + &Command; &Builder; that arranges + for a specific action to be executed + to build a specific file or files. + This looks a lot like the other builders + (like &Program;, &Object;, etc.), + but takes as an additional argument + the command to be executed to build the file: + + + + + env = Environment() + env.Command('foo.out', 'foo.in', "sed 's/x/y/' < $TARGET > $SOURCE") + + + + % scons . + sed 's/x/y' < foo.in > foo.out + + + + + This is often more convenient than + creating a &Builder; object + and adding it to the &BUILDERS; variable + of a &consenv; + + + + + + Note that the action you + + + + + env = Environment() + def build(target, source, env) + XXX + return None + env.Command('foo.out', 'foo.in', build) + + + + % scons . + build("foo.out", "foo.in") + diff --git a/doc/user/builders-writing.sgml b/doc/user/builders-writing.sgml new file mode 100644 index 0000000..27a48b9 --- /dev/null +++ b/doc/user/builders-writing.sgml @@ -0,0 +1,658 @@ + + + + + + + Although &SCons; provides many useful methods + for building common software products: + programs, libraries, documents. + you frequently want to be + able to build some other type of file + not supported directly by &SCons; + Fortunately, &SCons; makes it very easy + to define your own &Builder; objects + for any custom file types you want to build. + (In fact, the &SCons; interfaces for creating + &Builder; objects are flexible enough and easy enough to use + that all of the the &SCons; built-in &Builder; objects + are created the mechanisms described in this section.) + + + +
+ Writing Builders That Execute External Commands + + + + The simplest &Builder; to create is + one that executes an external command. + For example, if we want to build + an output file by running the contents + of the input file through a command named + foobuild, + creating that &Builder; might look like: + + + + + bld = Builder(action = 'foobuild < $TARGET > $SOURCE') + + + + + All the above line does is create a free-standing + &Builder; object. + The next section will show us how to actually use it. + + + +
+ +
+ Attaching a Builder to a &ConsEnv; + + + + A &Builder; object isn't useful + until it's attached to a &consenv; + so that we can call it to arrange + for files to be built. + This is done through the &BUILDERS; + &consvar; in an environment. + The &BUILDERS; variable is a Python dictionary + that maps the names by which you want to call + various &Builder; objects to the objects themselves. + For example, if we want to call the + &Builder; we just defined by the name + Foo, + our &SConstruct; file might look like: + + + + + bld = Builder(action = 'foobuild < $TARGET > $SOURCE') + env = Environment(BUILDERS = {'Foo' : bld}) + + + + + With the &Builder; so attached to our &consenv; + we can now actually call it like so: + + + + + env.Foo('file.foo', 'file.input') + + + + + Then when we run &SCons; it looks like: + + + + + % scons + foobuild < file.input > file.foo + + + + + Note, however, that the default &BUILDERS; + variable in a &consenv; + comes with a default set of &Builder; objects + already defined: + &Program;, &Library;, etc. + And when we explicitly set the &BUILDERS; variable + when we create the &consenv;, + the default &Builder;s are no longer part of + the environment: + + + + + bld = Builder(action = 'foobuild < $TARGET > $SOURCE') + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file.foo', 'file.input') + env.Program('hello.c') + + + + % scons + scons: Reading SConscript files ... + other errors + Traceback (most recent call last): + File "/usr/lib/scons/SCons/Script/__init__.py", line 901, in main + _main() + File "/usr/lib/scons/SCons/Script/__init__.py", line 762, in _main + SCons.Script.SConscript.SConscript(script) + File "/usr/lib/scons/SCons/Script/SConscript.py", line 207, in SConscript + exec _file_ in stack[-1].globals + File "SConstruct", line 4, in ? + env.Program('hello.c') + scons: Environment instance has no attribute 'Program' + + + + + To be able use both our own defined &Builder; objects + and the default &Builder; objects in the same &consenv;, + you can either add to the &BUILDERS; variable + using the &Append; function: + + + + + env = Environment() + bld = Builder(action = 'foobuild < $TARGET > $SOURCE') + env.Append(BUILDERS = {'Foo' : bld}) + env.Foo('file.foo', 'file.input') + env.Program('hello.c') + + + + + Or you can explicitly set the appropriately-named + key in the &BUILDERS; dictionary: + + + + + env = Environment() + bld = Builder(action = 'foobuild < $TARGET > $SOURCE') + env['BUILDERS']['Foo'] = bld + env.Foo('file.foo', 'file.input') + env.Program('hello.c') + + + + + Either way, the same &consenv; + can then use both the newly-defined + Foo &Builder; + and the default &Program; &Builder;: + + + + + % scons + foobuild < file.input > file.foo + cc -c hello.c -o hello.o + cc -o hello hello.o + + +
+ +
+ Letting &SCons; Handle The File Suffixes + + + + By supplying additional information + when you create a &Builder;, + you can let &SCons; add appropriate file + suffixes to the target and/or the source file. + For example, rather than having to specify + explicitly that you want the Foo + &Builder; to build the file.foo + target file from the file.input source file, + you can give the .foo + and .input suffixes to the &Builder;, + making for more compact and readable calls to + the Foo &Builder;: + + + + + bld = Builder(action = 'foobuild < $TARGET > $SOURCE', + suffix = '.foo', + src_suffix = '.input') + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file1') + env.Foo('file2') + + + + % scons + foobuild < file1.input > file1.foo + foobuild < file2.input > file2.foo + + + + + You can also supply a prefix keyword argument + if it's appropriate to have &SCons; append a prefix + to the beginning of target file names. + + + +
+ +
+ Builders That Execute Python Functions + + + + In &SCons;, you don't have to call an external command + to build a file. + You can, instead, define a Python function + that a &Builder; object can invoke + to build your target file (or files). + Such a &buildfunc; definition looks like: + + + + + def build_function(target, source, env): + # XXX + return None + + + + + The arguments of a &buildfunc; are: + + + + + + + target + + + + + A list of Node objects representing + the target or targets to be + built by this builder function. + The file names of these target(s) + may be extracted using the Python &str; funcion. + + + + + + + source + + + + + A list of Node objects representing + the sources to be + used by this builder function to build the targets. + The file names of these source(s) + may be extracted using the Python &str; funcion. + + + + + + + env + + + + + The &consenv; used for building the target(s). + The builder function may use any of the + environment's construction variables + in any way to affect how it builds the targets. + + + + + + + + + + The builder function must + return a 0 or None value + if the target(s) are built successfully. + The builder function + may raise an exception + or return any non-zero value + to indicate that the build is unsuccessful, + + + + + + Once you've defined the Python function + that will build your target file, + defining a &Builder; object for it is as + simple as specifying the name of the function, + instead of an external command, + as the &Builder;'s + action + argument: + + + + + def build_function(target, source, env): + # XXX + return None + bld = Builder(action = build_function, + suffix = '.foo', + src_suffix = '.input') + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file') + + + + + And notice that the output changes slightly, + reflecting the fact that a Python function, + not an external command, + is now called to build the target file: + + + + + % scons + build_function("file.foo", "file.input") + + +
+ +
+ Builders That Create Actions Using a &Generator; + + + + &SCons; Builder objects can create an action "on the fly" + by using a function called a &generator;. + This provides a great deal of flexibility XXX + A &generator; looks like: + + + + + def generate_actions(source, target, env, for_signature): + return XXX + + + + + The arguments of a &generator; are: + + + + + + + source + + + + + A list of Node objects representing + the sources to be built + by the command or other action + generated by this function. + The file names of these source(s) + may be extracted using the Python &str; funcion. + + + + + + + + target + + + + + A list of Node objects representing + the target or targets to be built + by the command or other action + generated by this function. + The file names of these target(s) + may be extracted using the Python &str; funcion. + + + + + + + + env + + + + + The &consenv; used for building the target(s). + The generator may use any of the + environment's construction variables + in any way to determine what command + or other action to return. + + + + + + + + for_signature + + + + + A flag that specifies whether the + generator is being called to contribute to a build signature, + as opposed to actually executing the command. + + XXX + + + + + + + + + + + The &generator; must return a + command string or other action that will be used to + build the specified target(s) from the specified source(s). + + + + + + Once you've defined a &generator;, + you create a &Builder; to use it + by specifying the generator keyword argument + instead of action. + + + + + bld = Builder(generator = generate_actions, + suffix = '.foo', + src_suffix = '.input') + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file') + + + + % scons + XXX + + + + + Note that it's illegal to specify both an + action + and a + generator + for a &Builder;. + + + +
+ +
+ Builders That Modify the Target or Source Lists Using an &Emitter; + + + + &SCons; supports the ability for a Builder to modify the + lists of target(s) from the specified source(s). + + + + + def modify_targets(XXX): + return XXX + bld = Builder(action = 'XXX', + suffix = '.foo', + src_suffix = '.input', + emitter = modify_targets) + env = Environment(BUILDERS = {'Foo' : bld}) + env.Foo('file') + + + + % scons + XXX + + + + bld = Builder(action = 'XXX', + suffix = '.foo', + src_suffix = '.input', + emitter = 'MY_EMITTER') + def modify1(XXX): + return XXX + def modify2(XXX): + return XXX + env1 = Environment(BUILDERS = {'Foo' : bld}, + MY_EMITTER = modify1) + env2 = Environment(BUILDERS = {'Foo' : bld}, + MY_EMITTER = modify2) + env1.Foo('file1') + env2.Foo('file2') + + +
+ +
+ Builders That Use Other Builders + + + + XXX + + + + + env = Environment() + env.SourceCode('.', env.BitKeeper('XXX') + env.Program('hello.c') + + + + % scons + XXX + + +
diff --git a/doc/user/builders.sgml b/doc/user/builders.sgml deleted file mode 100644 index c1b4269..0000000 --- a/doc/user/builders.sgml +++ /dev/null @@ -1,469 +0,0 @@ - - - - - - - &SCons; provides many useful methods - for building common software products: - programs, libraries, documents. - Frequently, however, you want to be - able to build some other type of file - not supported directly by &SCons; - Fortunately, &SCons; makes it very easy - to define your own &Builder; objects - for any custom file types you want to build. - - - -
- Builders That Execute External Commands - - - - The simplest &Builder; to create is - one that executes an external command. - For example, if we want to build - an output file by running the contents - of the input file through a command named - foobuild, - creating that &Builder; might look like: - - - - - bld = Builder(action = 'foobuild < $TARGET > $SOURCE') - - -
- -
- Attaching a Builder to a &ConsEnv; - - - - A &Builder; object by itself, though, - isn't useful until it's attached to a &consenv; - so that we can call it to arrange - for files to be built. - This is done through the &BUILDERS; - &consvar; in an environment. - The &BUILDERS; variable is a Python dictionary - that maps the names by which you want to call various &Builder; - to the &Builder; objects themselves. - For example, if we want to call the - &Builder; we defined by the name - Foo, - our &SConstruct; file might look like: - - - - - bld = Builder(action = 'foobuild < $TARGET > $SOURCE') - env = Environment(BUILDERS = {'Foo' : bld}) - env.Foo('file.foo', 'file.input') - - - - - Then when we run &SCons; it looks like: - - - - - % scons - foobuild < file.input > file.foo - - - - - Note, however, that the default &BUILDERS; - variable in a &consenv; - comes with a default set of &Builder; objects - already defined: - &Program;, &Library;, etc. - And when we explicitly set the &BUILDERS; variable - when we create the &consenv;, - the default &Builder;s are no longer part of - the environment: - - - - - bld = Builder(action = 'foobuild < $TARGET > $SOURCE') - env = Environment(BUILDERS = {'Foo' : bld}) - env.Foo('file.foo', 'file.input') - env.Program('hello.c') - - - - % scons - scons: Reading SConscript files ... - other errors - Traceback (most recent call last): - File "/usr/lib/scons/SCons/Script/__init__.py", line 901, in main - _main() - File "/usr/lib/scons/SCons/Script/__init__.py", line 762, in _main - SCons.Script.SConscript.SConscript(script) - File "/usr/lib/scons/SCons/Script/SConscript.py", line 207, in SConscript - exec _file_ in stack[-1].globals - File "SConstruct", line 4, in ? - env.Program('hello.c') - scons: Environment instance has no attribute 'Program' - - - - - To be able use both our own defined &Builder; objects - and the default &Builder; objects in the same &consenv;, - you can either add to the &BUILDERS; variable - using the &Append; function: - - - - - env = Environment() - bld = Builder(action = 'foobuild < $TARGET > $SOURCE') - env.Append(BUILDERS = {'Foo' : bld}) - env.Foo('file.foo', 'file.input') - env.Program('hello.c') - - - - - Or you can explicitly set the appropriately-named - key in the &BUILDERS; dictionary: - - - - - env = Environment() - bld = Builder(action = 'foobuild < $TARGET > $SOURCE') - env['BUILDERS']['Foo'] = bld - env.Foo('file.foo', 'file.input') - env.Program('hello.c') - - - - - Either way, the same &consenv; - can then use both the newly-defined - Foo &Builder; - and the default &Program; &Builder;: - - - - - % scons - foobuild < file.input > file.foo - cc -c hello.c -o hello.o - cc -o hello hello.o - - -
- -
- Letting &SCons; Handle The File Suffixes - - - - By supplying additional information - when you create a &Builder;, - you can let &SCons; add appropriate file - suffixes to the target and/or the source file. - For example, rather than having to specify - explicitly that you want the Foo - &Builder; to build the file.foo - target file from the file.input source file, - you can give the .foo - and .input suffixes to the &Builder;, - making for more compact and readable calls to - the Foo &Builder;: - - - - - bld = Builder(action = 'foobuild < $TARGET > $SOURCE', - suffix = '.foo', - src_suffix = '.input') - env = Environment(BUILDERS = {'Foo' : bld}) - env.Foo('file1') - env.Foo('file2') - - - - % scons - foobuild < file1.input > file1.foo - foobuild < file2.input > file2.foo - - - - - You can also supply a prefix keyword argument - if it's appropriate to have &SCons; append a prefix - to the beginning of target file names. - - - -
- -
- Builders That Execute Python Functions - - - - In &SCons;, you don't have to call an external command - to build a file. - You can, instead, define a Python function - that a &Builder; object can invoke - to build your target file (or files). - - - - - def build_function(target, source, env): - # XXX - return None - - - - - XXX explain the function - XXX define the arguments - - - - - - Once you've defined the Python function - that will build your target file, - defining a &Builder; object for it is as - simple as specifying the name of the function, - instead of an external command, - as the &Builder;'s - action - argument: - - - - - def build_function(target, source, env): - # XXX - return None - bld = Builder(action = build_function, - suffix = '.foo', - src_suffix = '.input') - env = Environment(BUILDERS = {'Foo' : bld}) - env.Foo('file') - - - - - And notice that the output changes slightly, - reflecting the fact that a Python function, - not an external command, - is now called to build the target file: - - - - - % scons - build_function("file.foo", "file.input") - - -
- -
- Builders That Generate Actions - - - - X - - - - - def generate_actions(XXX): - return XXX - bld = Builder(generator = generate_actions, - suffix = '.foo', - src_suffix = '.input') - env = Environment(BUILDERS = {'Foo' : bld}) - env.Foo('file') - - - - % scons - XXX - - - - - Note that it's illegal to specify both an - action - and a - generator - for a &Builder;. - - - -
- -
- Builders That Modify the Target List - - - - X - - - - - def modify_targets(XXX): - return XXX - bld = Builder(action = 'XXX', - suffix = '.foo', - src_suffix = '.input', - emitter = modify_targets) - env = Environment(BUILDERS = {'Foo' : bld}) - env.Foo('file') - - - - % scons - XXX - - - - bld = Builder(action = 'XXX', - suffix = '.foo', - src_suffix = '.input', - emitter = 'MY_EMITTER') - def modify1(XXX): - return XXX - def modify2(XXX): - return XXX - env1 = Environment(BUILDERS = {'Foo' : bld}, - MY_EMITTER = modify1) - env2 = Environment(BUILDERS = {'Foo' : bld}, - MY_EMITTER = modify2) - env1.Foo('file1') - env2.Foo('file2') - - -
- -
- Builders That Use Other Builders - - - - X - - - - - env = Environment() - env.SourceCode('.', env.BitKeeper('XXX') - env.Program('hello.c') - - - - % scons - XXX - - -
diff --git a/doc/user/caching.sgml b/doc/user/caching.sgml index ed72c1e..3d9158e 100644 --- a/doc/user/caching.sgml +++ b/doc/user/caching.sgml @@ -85,6 +85,8 @@ cc -c hello.c -o hello.o cc -o hello hello.o % scons -c + Removed hello.o + Removed hello % scons Retrieved `hello.o' from cache Retrieved `hello' from cache diff --git a/doc/user/command.sgml b/doc/user/command.sgml deleted file mode 100644 index 945c656..0000000 --- a/doc/user/command.sgml +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - Creating a &Builder; and attaching it to a &consenv; - allows for a lot of flexibility when you - want to re-use the same actions - to build multiple files of the same type. - This can, however, be cumbersome - if you only need to execute one specific command - to build a single file (or single group of files). - For these situations, &SCons; supports a - &Command; &Builder; that arranges - for a specific action to be executed - to build a specific file or files. - This looks a lot like the other builders - (like &Program;, &Object;, etc.), - but takes as an additional argument - the command to be executed to build the file: - - - - - env = Environment() - env.Command('foo.out', 'foo.in', "sed 's/x/y/' < $TARGET > $SOURCE") - - - - % scons . - sed 's/x/y' < foo.in > foo.out - - - - - This is often more convenient than - creating a &Builder; object - and adding it to the &BUILDERS; variable - of a &consenv; - - - - - - Note that the action you - - - - - env = Environment() - def build(target, source, env) - XXX - return None - env.Command('foo.out', 'foo.in', build) - - - - % scons . - build("foo.out", "foo.in") - diff --git a/doc/user/cons.sgml b/doc/user/cons.sgml index 448777f..f83ab63 100644 --- a/doc/user/cons.sgml +++ b/doc/user/cons.sgml @@ -25,16 +25,16 @@ - X + XXX
- X + XXX - X + XXX diff --git a/doc/user/default.sgml b/doc/user/default.sgml index 981ac42..f44719f 100644 --- a/doc/user/default.sgml +++ b/doc/user/default.sgml @@ -87,7 +87,7 @@ default list. This &SConstruct; file knows how to build two programs, &hello; and &goodbye;, but only builds the - &hello program by default: + &hello; program by default: diff --git a/doc/user/depends.sgml b/doc/user/depends.sgml index bc46618..fbbb54a 100644 --- a/doc/user/depends.sgml +++ b/doc/user/depends.sgml @@ -25,8 +25,6 @@ - -
- Time Stamps - - - - X - - - -
- -
- The &SourceSignature; Method - - - - X - - - -
diff --git a/doc/user/environments.sgml b/doc/user/environments.sgml index 77d9c6b..d3c3b0c 100644 --- a/doc/user/environments.sgml +++ b/doc/user/environments.sgml @@ -452,18 +452,20 @@ environment undisturbed. - So far, we've always created a &consenv; named + So far, + all of our examples have + created a single &consenv; named env. env, however, is simply a Python variable name, - and you can use any other variable name that we like. + and you can use any other variable name that you like. For example: my_env = Environment(CC = 'gcc', - CCFLAGS = '-O2') + CCFLAGS = '-O2') my_env.Program('foo.c') @@ -535,7 +537,7 @@ environment undisturbed. -O2 and one with a &CCFLAGS; value of -g. - To work around this, + To avoid this problem, we must explicitly specify that each environment compile foo.c @@ -566,7 +568,7 @@ environment undisturbed. This avoids having to specify explicitly the object file name in multiple places, and makes for a compact, readable - &SConstruct file. + &SConstruct; file. Our &SCons; output then looks like: @@ -586,8 +588,8 @@ environment undisturbed. - Sometimes you want to more than one &consenv; - to use the same values for one or more variables. + Sometimes you want more than one &consenv; + to share the same values for one or more variables. Rather than always having to repeat all of the common variables when you create each &consenv;, you can use the &Copy; method diff --git a/doc/user/errors.sgml b/doc/user/errors.sgml index 448777f..f83ab63 100644 --- a/doc/user/errors.sgml +++ b/doc/user/errors.sgml @@ -25,16 +25,16 @@ - X + XXX
- X + XXX - X + XXX diff --git a/doc/user/example.sgml b/doc/user/example.sgml index 448777f..f83ab63 100644 --- a/doc/user/example.sgml +++ b/doc/user/example.sgml @@ -25,16 +25,16 @@ - X + XXX
- X + XXX - X + XXX diff --git a/doc/user/hierarchy.sgml b/doc/user/hierarchy.sgml index 617eb59..e39da8f 100644 --- a/doc/user/hierarchy.sgml +++ b/doc/user/hierarchy.sgml @@ -274,7 +274,7 @@ make no difference to the build. - X + XXX @@ -290,7 +290,7 @@ make no difference to the build. - X + XXX @@ -304,7 +304,7 @@ make no difference to the build. - X + XXX @@ -320,7 +320,7 @@ make no difference to the build. - X + XXX @@ -336,7 +336,7 @@ make no difference to the build. - X + XXX diff --git a/doc/user/install.sgml b/doc/user/install.sgml index 2cebbd4..7f522e5 100644 --- a/doc/user/install.sgml +++ b/doc/user/install.sgml @@ -72,7 +72,7 @@ should be installed. This is an area where the &Alias; function comes in handy, - allowing you, if you wish, + allowing you, for example, to create a pseudo-target named install that can expand to the specified destination directory: @@ -104,7 +104,7 @@ You can install multiple files into a directory - simploy by calling the &Install; function multiple times: + simply by calling the &Install; function multiple times: diff --git a/doc/user/libraries.sgml b/doc/user/libraries.sgml new file mode 100644 index 0000000..ea41f5d --- /dev/null +++ b/doc/user/libraries.sgml @@ -0,0 +1,250 @@ + + + + + One of the more useful ways in which you can use multiple + construction environments is to link programs + with different sets of libraries. + + + +
+ Building Libraries + + + + You build your own libraries by specifying &Library; + instead of &Program;: + + + + + env = Environment() + env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) + + + + + &SCons; uses the appropriate library prefix and suffix for your system. + So on POSIX or Linux systems, + the above example would build as follows + (although &ranlib may not be called on all systems): + + + + + % scons + cc -c f1.c -o f1.o + cc -c f2.c -o f2.o + cc -c f3.c -o f3.o + ar r libfoo.a f1.o f2.o f3.o + ranlib libfoo.a + + + + + On a Windows system, + a build of the above example would look like: + + + + + C:\>scons + cl /Fof1.obj f1.c + cl /Fof2.obj f2.c + cl /Fof3.obj f3.c + lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj + + + + + The rules for the target name of the library + are similar to those for programs: + if you don't explicitly specify a target library name, + &SCons; will deduce one from the + name of the first source file specified, + and &SCons; will add an appropriate + file prefix and suffix if you leave them off. + + + +
+ +
+ Linking with Libraries + + + + Usually, the goal of building a library + is to link it with one or more programs. + You link libraries with a program by specifying + the libraries in the &LIBS; construction variable, + and by specifying the directory in which + the library will be found in the + &LIBPATH; construction variable: + + + + + env = Environment(LIBS = 'foo', LIBPATH = '.') + env.Library('foo', ['f1.c', 'f2.c', 'f3.c']) + env.Program('prog.c') + + + + + Notice, of course, that you don't need to specify a library + prefix (like lib) + or suffix (like .a or .lib). + &SCons; uses the correct prefix or suffix for the current system. + + + + + + On a POSIX or Linux system, + a build of the above example would look like: + + + + + % scons + cc -c f1.c -o f1.o + cc -c f2.c -o f2.o + cc -c f3.c -o f3.o + ar r libfoo.a f1.o f2.o f3.o + ranlib libfoo.a + cc -c prog.c -o prog.o + cc -o prog -L. -lfoo prog.o + + + + + On a Windows system, + a build of the above example would look like: + + + + + C:\>scons + cl /Fof1.obj f1.c + cl /Fof2.obj f2.c + cl /Fof3.obj f3.c + lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj + cl /Foprog.obj prog.c + link /OUT:prog.exe /LIBPATH:. foo.lib prog.obj + + + + + As usual, notice that &SCons; has taken care + of constructing the correct command lines + to link with the specified library on each system. + + + +
+ +
+ Finding Libraries: the &LIBPATH; Construction Variable + + + + By default, the linker will only look in + certain system-defined directories for libraries. + &SCons; knows how to look for libraries + in directories that you specify with the + &LIBPATH; construction variable. + &LIBPATH; consists of a list of + directory names, like so: + + + + + env = Environment(LIBS = 'm', + LIBPATH = ['/usr/lib', '/usr/local/lib']) + env.Program('prog.c') + + + + + Using a Python list is preferred because it's portable + across systems. Alternatively, you could put all of + the directory names in a single string, separated by the + system-specific path separator character: + a colon on POSIX systems: + + + + + LIBPATH = '/usr/lib:/usr/local/lib' + + + + + or a semi-colon on Windows systems: + + + + + LIBPATH = 'C:\lib;D:\lib' + + + + + On a POSIX or Linux system, + a build of the above example would look like: + + + + + % scons + cc -c prog.c -o prog.o + cc -o prog -L/usr/lib -L/usr/local/lib -lm prog.o + + + + + On a Windows system, + a build of the above example would look like: + + + + + C:\>scons + cl /Foprog.obj prog.c + link /nologo /OUT:program.exe /LIBPATH:\usr\lib;\usr\local\lib m.lib prog.obj + + + + + Note again that &SCons; has taken care of + the system-specific details of creating + the right command-line options. + + + +
diff --git a/doc/user/main.sgml b/doc/user/main.sgml index 9ea4dd5..12b0480 100644 --- a/doc/user/main.sgml +++ b/doc/user/main.sgml @@ -34,9 +34,11 @@ - + + + + - @@ -47,6 +49,7 @@ + @@ -102,6 +105,11 @@ &environments; + + Building and Linking with Libraries + &libraries; + + Dependencies &depends; @@ -142,14 +150,19 @@ &variants; - - Writing Builders - &builders; + + Built-In Builders + &builders-built-in; + + + + Writing Your Own Builders + &builders-writing; - - Not Writing a Builder (for One-Time Builds) - &command; + + Not Writing a Builder: The &Command; Builder + &builders-commands; @@ -222,4 +235,9 @@ &cons; + + Converting From Ant + &ant; + + diff --git a/doc/user/make.sgml b/doc/user/make.sgml index 5666ea6..c7ecc63 100644 --- a/doc/user/make.sgml +++ b/doc/user/make.sgml @@ -94,16 +94,16 @@ the makefiles. - X + XXX
- X + XXX - X + XXX diff --git a/doc/user/preface.sgml b/doc/user/preface.sgml index 82ea44a..bba7f49 100644 --- a/doc/user/preface.sgml +++ b/doc/user/preface.sgml @@ -23,63 +23,182 @@ --> - + - X + XXX - + -
- Why &SCons;? +
+ Why &SCons;? - + - X + XXX - + -
+
-
- History +
+ &SCons; Principles - + - X + By default, &SCons; guarantees a correct build + regardless of what end case you may have. - + -
+ -
- Conventions + &SCons; makes it easy to speed up the build through + optimization options that trade off + guaranteed correctness for speed. - + - X + - + &SCons; tries to do as much for you out of the box as reasonable. -
+
-
- Acknowledgements +
- +
+ History - X + - + &SCons; originated with a design + that was submitted to the Software Carpentry + design competition in 2000. -
+
-
- Contact + - + &SCons; is the direct descendant + of a Perl utility called &Cons;. + &Cons; in turn based some of its ideas on &Jam;, + a build tool from Perforce Systems. - X + - +
-
+
+ Conventions + + + + XXX + + + +
+ +
+ Acknowledgements + + + + &SCons; would not exist without a lot of help + from a lot of people, + many of whom may not even be aware + that they helped or served as inspiration. + So in no particular order, + and at the risk of leaving out someone: + + + + + + First and foremost, + &SCons; owes a tremendous debt to Bob Sidebotham, + the original author of the classic Perl-based &Cons; tool + which Bob first released to the world back around 1996. + Bob's work on Cons classic provided the underlying architecture + and model of specifying a build configuration + using a real scripting language. + My real-world experience working on Cons + informed many of the design decisions in SCons, + including the improved parallel build support, + making Builder objects easily definable by users, + and separating the build engine from the wrapping interface. + + + + + + Greg Wilson was instrumental in getting + &SCons; started as a real project + when he initiated the Software Carpentry design + competition in February 2000. + Without that nudge, + marrying the advantages of the Cons classic + architecture with the readability of Python + might have just stayed no more than a nice idea. + + + + + + The entire &SCons; team have been + absolutely wonderful to work with, + and &SCons; would be nowhere near as useful a + tool without the energy, enthusiasm + and time people have contributed over the past few years. + The "core team" + of Chad Austin, Anthony Roach, Charles Crain, and Steve Leblanc + have been great about reviewing my (and other) changes + and catching problems before they get in the code base. + Technically, + Anthony's outstanding and innovative work on the tasking engine + has given &SCons; a vastly superior parallel build model, + and Charles has been the master of the crucial Node infrastructure. + &SCons; has received contributions + from many other people, of course: + Matt Balvin (extending long command-line support on Win32), + Michael Cook (avoiding losing signal bits from executed commands), + Derrick 'dman' Hudson (), + Alex Jacques (work on the Win32 scons.bat file), + Stephen Kennedy (performance enhancements), + Lachlan O'Dea (SharedObject() support for masm + and normalized paths for the WhereIs() function), + Jeff Petkau (fixes for CacheDir and other areas), + Zed Shaw (Append() and Replace() environment methods), + Terrel Shumway (build and test fixes, as well as the SCons Wiki), + sam th (dynamic checks for utilities) + and Moshe Zadke (Debian packaging). + + + + + + Thanks to Peter Miller + for his splendid change management system, &Aegis;, + which has provided the &SCons; project + with a robust development methodology from day one, + and which showed me how you could + integrate incremental regression tests into + a practical development cycle + (years before eXtreme Programming arrived on the scene). + + + +
+ +
+ Contact + + + + The best way to contact people involved with SCons, + including the author, + is through the SCons mailing lists. + + + +
diff --git a/doc/user/repositories.sgml b/doc/user/repositories.sgml index 616e903..07af115 100644 --- a/doc/user/repositories.sgml +++ b/doc/user/repositories.sgml @@ -288,7 +288,7 @@ subdirectories under the repository tree. about the pathname of the repository? To solve this problem, &SCons; allows you to specify repository directories - on the command line using the -Y: + on the command line using the -Y option: diff --git a/doc/user/run.sgml b/doc/user/run.sgml index 30b61ca..83ca3d2 100644 --- a/doc/user/run.sgml +++ b/doc/user/run.sgml @@ -266,48 +266,6 @@ rebuilt, if necessary, and then installed there. Note that C might build files that C doesn't build, and vice-versa. -=head2 No ``special'' targets - -With Cons, make-style ``special'' targets are not required. The simplest -analog with Cons is to use special F directories, instead. Let's -suppose, for example, that you have a whole series of unit tests that are -associated with your code. The tests live in the source directory near the -code. Normally, however, you don't want to build these tests. One solution -is to provide all the build instructions for creating the tests, and then to -install the tests into a separate part of the tree. If we install the tests -in a top-level directory called F, then: - - % cons tests - -will build all the tests. - - % cons export - -will build the production version of the system (but not the tests), and: - - % cons build - -should probably be avoided (since it will compile tests unnecessarily). - -If you want to build just a single test, then you could explicitly name the -test (in either the F directory or the F directory). You could -also aggregate the tests into a convenient hierarchy within the tests -directory. This hierarchy need not necessarily match the source hierarchy, -in much the same manner that the include hierarchy probably doesn't match -the source hierarchy (the include hierarchy is unlikely to be more than two -levels deep, for C programs). - -If you want to build absolutely everything in the tree (subject to whatever -options you select), you can use: - - % cons . - -This is not particularly efficient, since it will redundantly walk all the -trees, including the source tree. The source tree, of course, may have -buildable objects in it-,-nothing stops you from doing this, even if you -normally build in a separate build tree. - - =head1 Build Pruning In conjunction with target selection, B can be used to reduce @@ -351,52 +309,56 @@ do an unconstrained build before committing the integration). --> - + + + XXX + + - X +
+ Selective Builds - + -
- Selective Builds + XXX - + - X +
-
+ -
- Overriding Construction Variables +
+ Overriding Construction Variables - + - X + XXX - + -
+
-
- The &SCONSFLAGS; Environment Variable +
+ The &SCONSFLAGS; Environment Variable - + - X + XXX - + -
+
diff --git a/doc/user/scanners.sgml b/doc/user/scanners.sgml index 8d13b0c..76b2a1a 100644 --- a/doc/user/scanners.sgml +++ b/doc/user/scanners.sgml @@ -123,16 +123,16 @@ over the file scanning rather than being called for each input line: - X + XXX
- X + XXX - X + XXX diff --git a/doc/user/separate.sgml b/doc/user/separate.sgml index 21fcabc..ac3c0f3 100644 --- a/doc/user/separate.sgml +++ b/doc/user/separate.sgml @@ -110,228 +110,322 @@ program using the F path name. --> - + - It's often useful to keep any built files completely - separate from the source files. - This is usually done by creating one or more separate - build directories - that are used to hold the built objects files, libraries, - and executable programs, etc. - for a specific flavor of build. - &SCons; provides two ways of doing this, - one with a little more flexibility. + It's often useful to keep any built files completely + separate from the source files. + This is usually done by creating one or more separate + build directories + that are used to hold the built objects files, libraries, + and executable programs, etc. + for a specific flavor of build. + &SCons; provides two ways to do this, + one through the &SConscript; function that we've already seen, + and the second through a more flexible &BuildDir; function. - + -
- The &BuildDir; Function +
+ Specifying a Build Directory as Part of an &SConscript; Call - + - Use the &BuildDir; function to establish that target - files should be built in a separate directory - from the source files: + The most straightforward way to establish a build directory + uses the fact that the usual way to + set up a build hierarcy is to have an + &SConscript; file in the source subdirectory. + If you then pass a &build_dir; argument to the + &SConscript; function call: - + - - BuildDir('build', 'src') - env = Environment() - env.Program('build/hello.c') - + + SConscript('src/SConscript', build_dir='build') + - + - Note that XXX + &SCons; will then build all of the files in + the &build; subdirectory: - + - - % ls src - hello.c - % scons - cc -c build/hello.c -o build/hello.o - cc -o build/hello build/hello.o - % ls -1 build - hello - hello.c - hello.o - + + % ls -1 src + SConscript + hello.c + % scons + cc -c build/hello.c -o build/hello.o + cc -o build/hello build/hello.o + % ls -1 build + hello + hello.c + hello.o + -
+ -
- Avoiding Duplicate Source Files in the Build Directory + But wait a minute--what's going on here? + &SCons; created the object file + build/hello.o + in the &build; subdirectory, + as expected. + But even though our &hello_c; file lives in the &src; subdirectory, + &SCons; has actually compiled a + build/hello.c file + to create the object file. - + - X + - + What's happened is that &SCons; has duplicated + the &hello_c; file from the &src; subdirectory + to the &build; subdirectory, + and built the program from there. + The next section explains why &SCons; does this. - - BuildDir('build', 'src', duplicate=0) - env = Environment() - env.Program('build/hello.c') - + - +
- X +
+ Why &SCons; Duplicates Source Files in a Build Directory - + - - % ls -1 src - hello.c - % scons - cc -c src/hello.c -o build/hello.o - cc -o build/hello build/hello.o - % ls -1 build - hello - hello.o - + &SCons; duplicates source files in build directories + because it's the most straightforward way to guarantee a correct build + regardless of include-file directory paths, + and the &SCons; philosophy is to, by default, + guarantee a correct build in all cases. + Here is an example of an end case where duplicating + source files in a build directory + is necessary for a correct build: - + - X + - + XXX -
+
-
- Why &SCons; Duplicates Source Files by Default + + env = Environmnet() + - + - X + XXX - + - - env = Environmnet() - + + % scons + cc -c build/hello.c -o build/hello.o + cc -o build/hello build/hello.o + - +
- X +
+ Telling &SCons; to Not Duplicate Source Files in the Build Directory - + - - % scons - cc -c build/hello.c -o build/hello.o - cc -o build/hello build/hello.o - + In most cases, however, + having &SCons; place its target files in a build subdirectory + without + duplicating the source files works just fine. + You can disable the default &SCons; behavior + by specifying duplicate=0 + when you call the &SConscript; function: -
+ -
- Using &BuildDir; With an &SConscript; File + + SConscript('src/SConscript', build_dir='build', duplicate=0) + - + - X + When this flag is specified, + &SCons; uses the build directory + like most people expect--that is, + the output files are placed in the build directory + while the source files stay in the source directory: - + - - env = Environment() - env.Program('hello.c') - + + % ls -1 src + SConscript + hello.c + % scons + cc -c src/hello.c -o build/hello.o + cc -o build/hello build/hello.o + % ls -1 build + hello + hello.o + - +
- X +
+ The &BuildDir; Function - + - - BuildDir('build', 'src') - SConscript('build/SConscript') - + Use the &BuildDir; function to establish that target + files should be built in a separate directory + from the source files: - + - X + + BuildDir('build', 'src') + env = Environment() + env.Program('build/hello.c') + - + - - % ls -1 src - SConscript - hello.c - % scons - cc -c build/hello.c -o build/hello.o - cc -o build/hello build/hello.o - % ls -1 build - hello - hello.c - hello.o - + Note that when you're not using + an &SConscript; file in the &src; subdirectory, + you must actually specify that + the program must be built from + the build/hello.c + file that &SCons; will duplicate in the + &build; subdirectory. -
+ -
- Specifying a Build Directory as Part of an &SConscript; Call + - + XXX - X + - + - - SConscript('src/SConscript', build_dir='build') - + When using the &BuildDir; function directly, + &SCons; still duplicates the source files + in the build directory by default: - + - X + + % ls src + hello.c + % scons + cc -c build/hello.c -o build/hello.o + cc -o build/hello build/hello.o + % ls -1 build + hello + hello.c + hello.o + - + - - % ls -1 src - SConscript - hello.c - % scons - cc -c build/hello.c -o build/hello.o - cc -o build/hello build/hello.o - % ls -1 build - hello - hello.c - hello.o - + You can specify the same duplicate=0 argument + that you can specify for an &SConscript; call: - + - X + + BuildDir('build', 'src', duplicate=0) + env = Environment() + env.Program('build/hello.c') + - + - - SConscript('src/SConscript', build_dir='build', duplicate=0) - + In which case &SCons; + will disable duplication of the source files: - + - X + + % ls src + hello.c + % scons + cc -c src/hello.c -o build/hello.o + cc -o build/hello build/hello.o + % ls -1 build + hello + hello.o + - +
- - % ls -1 src - SConscript - hello.c - % scons - cc -c src/hello.c -o build/hello.o - cc -o build/hello build/hello.o - % ls -1 build - hello - hello.o - +
+ Using &BuildDir; With an &SConscript; File -
+ + + Even when using the &BuildDir; function, + it's much more natural to use it with + a subsidiary &SConscript; file. + For example, if the + src/SConscript + looks like this: + + + + + env = Environment() + env.Program('hello.c') + + + + + Then our &SConscript; file could look like: + + + + + BuildDir('build', 'src') + SConscript('build/SConscript') + + + + + Yielding the following output: + + + + + % ls -1 src + SConscript + hello.c + % scons + cc -c build/hello.c -o build/hello.o + cc -o build/hello build/hello.o + % ls -1 build + hello + hello.c + hello.o + + + + + Notice that this is completely equivalent + to the use of &SConscript; that we + learned about in the previous section. + + + +
+ +
+ Why You'd Want to Call &BuildDir; Instead of &SConscript; + + + + XXX + + + +
diff --git a/doc/user/simple.sgml b/doc/user/simple.sgml index 2acd669..8f76f2a 100644 --- a/doc/user/simple.sgml +++ b/doc/user/simple.sgml @@ -43,7 +43,7 @@ requirements of a build. - Here's how to build the famous "Hello, World!" example using &SCons;. + Here's the famous "Hello, World!" program in C: @@ -57,7 +57,8 @@ requirements of a build. - Enter the following into a file name &SConstruct;: + And here's how to build it using &SCons;. + Enter the following into a file named &SConstruct;: @@ -144,7 +145,7 @@ requirements of a build. What may not be obvious, though, is that there's an important difference between - an &SConstruct; file and a &Makefile: + an &SConstruct; file and a &Makefile;: the &SConstruct; file is actually a Python script. If you're not already familiar with Python, don't worry; Python is very easy to learn, @@ -193,29 +194,58 @@ requirements of a build. To do this, you need to put the source files in a Python list (enclosed in square brackets), - and slide that list over to to the right - to make room for the output program file name. - For example: + like so: env = Environment() - env.Program('program', ['main.c', 'file1.c', 'file2.']) + env.Program(['prog.c', 'file1.c', 'file2.']) + A build of the above example would look like: + + + + + % scons + cc -c file1.c -o file1.o + cc -c file2.c -o file2.o + cc -c prog.c -o prog.o + cc -o prog prog.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 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: + + env = Environment() + env.Program('program', ['main.c', 'file1.c', 'file2.']) + + - A build of the above example would look: + On Linux, a build of this example would look like: @@ -227,11 +257,7 @@ requirements of a build. cc -o program main.o file1.o file2.o - -
@@ -260,8 +284,8 @@ requirements of a build. (either single quotes or double quotes). This can get cumbersome and difficult to read when the list of file names is long. - Fortunately, there are a number of things - we can do to make sure that + Fortunately, &SCons; and Python provide a number of ways + to make sure that the &SConstruct; file stays easy to read. @@ -363,7 +387,7 @@ requirements of a build. In order to compile multiple programs within the same &SConstruct; file, - simply call env.Program + simply call the env.Program method multiple times, once for each program you need to build: @@ -390,6 +414,19 @@ requirements of a build. 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. + + +
@@ -397,17 +434,40 @@ requirements of a build. - XXX + It's common to re-use code by sharing source files + between multiple programs. + One way to do this is to create a library + from the common source files, + which can then be linked into resulting programs. + (Creating libraries is discussed in + section XXX, below.) + + + + + + A more straightforward, but perhaps less convenient, + way to share source files between multiple programs + is to simply include the common source files + when listing the source files for each program: - common = ['common1.c', 'common2.c'] env = Environment() - env.Program(['foo.c'] + common) - env.Program('bar', ['bar1.c', 'bar2.c'] + common) + env.Program(Split('foo.c common1.c common2.c')) + env.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 files are listed multiple times: + + + % scons cc -c bar1.c -o bar1.o @@ -419,4 +479,33 @@ requirements of a build. 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 + a maintenance problem if 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 + env = Environment() + env.Program('foo', foo_files) + env.Program('bar', bar_files) + + + + + This is functionally equivalent to the previous example. + + +
diff --git a/doc/user/sourcecode.sgml b/doc/user/sourcecode.sgml index 4ee49d4..6bbccee 100644 --- a/doc/user/sourcecode.sgml +++ b/doc/user/sourcecode.sgml @@ -44,7 +44,7 @@ env = Environment() - env.SourceCode('.', env.BitKeeper('XXX') + env.SourceCode('.', env.BitKeeper('XXX')) env.Program('hello.c') @@ -66,7 +66,7 @@ env = Environment() - env.SourceCode('.', env.CVS('XXX') + env.SourceCode('.', env.CVS('XXX')) env.Program('hello.c') @@ -88,7 +88,7 @@ env = Environment() - env.SourceCode('.', env.RCS() + env.SourceCode('.', env.RCS()) env.Program('hello.c') @@ -110,7 +110,7 @@ env = Environment() - env.SourceCode('.', env.SCCS() + env.SourceCode('.', env.SCCS()) env.Program('hello.c') @@ -132,7 +132,7 @@ env = Environment() - env.SourceCode('.', env.Subversion('XXX') + env.SourceCode('.', env.Subversion('XXX')) env.Program('hello.c') diff --git a/doc/user/troubleshoot.sgml b/doc/user/troubleshoot.sgml index 448777f..f83ab63 100644 --- a/doc/user/troubleshoot.sgml +++ b/doc/user/troubleshoot.sgml @@ -25,16 +25,16 @@ - X + XXX
- X + XXX - X + XXX diff --git a/doc/user/variants.sgml b/doc/user/variants.sgml index 6ad9360..09dd16d 100644 --- a/doc/user/variants.sgml +++ b/doc/user/variants.sgml @@ -107,40 +107,89 @@ is pretty smart about rebuilding things when you change options. --> - - - X - - - -
- X - - - - X - - - - - env = Environment(OS = ARGUMENT['os']) - SConscript('src/SConscript', build_dir='build/$OS') - - - - - X - - - - - env = Environment(OS = ) - for os in ['newell', 'post']: - SConscript('src/SConscript', build_dir='build/' + os) - - - - % scons - - -
+ + + The &BuildDir; function now gives us everything + we need to show how easy it is to create + variant builds using &SCons;. + Suppose, for example, that we want to + build a program for both Windows and Linux platforms, + but that we want to build it in a shared directory + with separate side-by-side build directories + for the Windows and Linux versions of the program. + + + + + platform = ARGUMENT.get('OS', Platform()) + + include = "#export/$PLATFORM/include" + lib = "#export/$PLATFORM/lib" + bin = "#export/$PLATFORM/bin" + + env = Environment(PLATFORM = platform, + CPPPATH = [include], + LIB = lib, + LIBS = '-lworld') + + Export('env') + + SConscript('src/SConscript', build_dir='build/$PLATFORM') + + # + #BuildDir("#build/$PLATFORM", 'src') + #SConscript("build/$PLATFORM/hello/SConscript") + #SConscript("build/$PLATFORM/world/SConscript") + + + + + This SConstruct file, + when run on a Linux system, yields: + + + + + $ scons OS=linux + Install build/linux/world/world.h as export/linux/include/world.h + cc -Iexport/linux/include -c build/linux/hello/hello.c -o build/linux/hello/hello.o + cc -Iexport/linux/include -c build/linux/world/world.c -o build/linux/world/world.o + ar r build/linux/world/libworld.a build/linux/world/world.o + ar: creating build/linux/world/libworld.a + ranlib build/linux/world/libworld.a + Install build/linux/world/libworld.a as export/linux/lib/libworld.a + cc -o build/linux/hello/hello build/linux/hello/hello.o -Lexport/linux/lib -lworld + Install build/linux/hello/hello as export/linux/bin/hello + + + + + The same SConstruct file on Windows would build: + + + + + + C:\test\>scons OS=linux + Install build\linux\world\world.h as export\linux\include\world.h + cl /Iexport\linux\include /Fobuild\linux\hello\hello.obj build\linux\hello\hello.c + cl /Iexport\linux\include /Fobuild\linux\world\world.obj build\linux\world\world.c + XXX + ar r build\linux\world\world.lib build\linux\world\world.obj + Install build\linux\world\world.lib as export\linux\lib\libworld.a + link /Fobuild\linux\hello\hello.exe build\linux\hello\hello.obj -Lexport\linux\lib world.lib + Install build\linux\hello\hello.exe as export\linux\bin\hello.exe + + + + env = Environment(OS = ) + for os in ['newell', 'post']: + SConscript('src/SConscript', build_dir='build/' + os) + + + + % scons + -- cgit v0.12