From: stevenknight Date: Tue, 25 Mar 2003 05:13:22 +0000 (+0000) Subject: Branch for in-progress User's Guide changes. X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=c911a738519433c0d97ca8bdf44a3ad026fa050d;p=scons.git Branch for in-progress User's Guide changes. git-svn-id: http://scons.tigris.org/svn/scons/trunk@621 fdb21ef1-2011-0410-befe-b5e4ea1792b1 --- diff --git a/doc/SConscript b/doc/SConscript index feb8a753..d5fe171b 100644 --- a/doc/SConscript +++ b/doc/SConscript @@ -3,7 +3,7 @@ # # -# __COPYRIGHT__ +# Copyright (c) 2001, 2002, 2003 Steven Knight # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -141,6 +141,13 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. 'text' : 0, 'graphics' : [ 'arch', 'builder', 'job-task', 'node', 'scanner', 'sig' ], }, + 'reference' : { + 'htmlindex' : 'book1.html', + 'html' : 1, + 'ps' : 1, + 'pdf' : 1, + 'text' : 0, + }, 'user' : { 'htmlindex' : 'book1.html', 'html' : 1, diff --git a/doc/reference/.aeignore b/doc/reference/.aeignore new file mode 100644 index 00000000..877ac534 --- /dev/null +++ b/doc/reference/.aeignore @@ -0,0 +1,4 @@ +*,D +.*.swp +.consign +.sconsign diff --git a/doc/user/more.sgml b/doc/reference/Alias.sgml similarity index 84% rename from doc/user/more.sgml rename to doc/reference/Alias.sgml index 7defa414..b87967dd 100644 --- a/doc/user/more.sgml +++ b/doc/reference/Alias.sgml @@ -30,29 +30,7 @@
- The &Module; Method - - - - X - - - -
- -
- The &RuleSet; Method - - - - X - - - -
- -
- The &DefaultRules; Method + The &Alias; Method diff --git a/doc/reference/CFile.sgml b/doc/reference/CFile.sgml new file mode 100644 index 00000000..f76c3908 --- /dev/null +++ b/doc/reference/CFile.sgml @@ -0,0 +1,41 @@ + + + + + X + + + +
+ The &CFile; Method + + + + X + + + +
diff --git a/doc/reference/CXXFile.sgml b/doc/reference/CXXFile.sgml new file mode 100644 index 00000000..c1c038ee --- /dev/null +++ b/doc/reference/CXXFile.sgml @@ -0,0 +1,41 @@ + + + + + X + + + +
+ The &CXXFile; Method + + + + X + + + +
diff --git a/doc/reference/Command.sgml b/doc/reference/Command.sgml new file mode 100644 index 00000000..abb3a581 --- /dev/null +++ b/doc/reference/Command.sgml @@ -0,0 +1,73 @@ + + + + + + + X + + + +
+ The &Command; Method + + + + X + + + +
diff --git a/doc/reference/Install.sgml b/doc/reference/Install.sgml new file mode 100644 index 00000000..2d06e3b1 --- /dev/null +++ b/doc/reference/Install.sgml @@ -0,0 +1,41 @@ + + + + + X + + + +
+ The &Install; Method + + + + X + + + +
diff --git a/doc/reference/InstallAs.sgml b/doc/reference/InstallAs.sgml new file mode 100644 index 00000000..ed8cb78f --- /dev/null +++ b/doc/reference/InstallAs.sgml @@ -0,0 +1,41 @@ + + + + + X + + + +
+ The &InstallAs; Method + + + + X + + + +
diff --git a/doc/user/library.sgml b/doc/reference/Library.sgml similarity index 60% rename from doc/user/library.sgml rename to doc/reference/Library.sgml index 0c9292ca..19a3e963 100644 --- a/doc/user/library.sgml +++ b/doc/reference/Library.sgml @@ -63,11 +63,82 @@ be generated (the rest will disappear!). --> - +
+ Linking With a Library + + + env = Environment(CC = 'gcc', + LIBS = 'world') + env.Program('hello.c') + + + + % scons + gcc -c hello.c -o hello.o + gcc -c world.c -o world.o + gcc -o hello hello.o -lworld + + +
+ +
+ Creating a Library + + + env = Environment(CC = 'gcc', + LIBS = 'world') + env.Program('hello.c') + env.Library('world.c') + + + + % scons + gcc -c hello.c -o hello.o + gcc -c world.c -o world.o + ar r libworld.a world.o + ar: creating libworld.a + ranlib libworld.a + gcc -o hello hello.o libworld.a + + +
+ +
The &Library; Builder diff --git a/doc/user/object.sgml b/doc/reference/Object.sgml similarity index 100% rename from doc/user/object.sgml rename to doc/reference/Object.sgml diff --git a/doc/reference/PCH.sgml b/doc/reference/PCH.sgml new file mode 100644 index 00000000..b2a4d758 --- /dev/null +++ b/doc/reference/PCH.sgml @@ -0,0 +1,41 @@ + + + + + X + + + +
+ The &PCH; Method + + + + X + + + +
diff --git a/doc/reference/PDF.sgml b/doc/reference/PDF.sgml new file mode 100644 index 00000000..b3a25dc6 --- /dev/null +++ b/doc/reference/PDF.sgml @@ -0,0 +1,41 @@ + + + + + X + + + +
+ The &PDF; Method + + + + X + + + +
diff --git a/doc/reference/PostScript.sgml b/doc/reference/PostScript.sgml new file mode 100644 index 00000000..f5a6579c --- /dev/null +++ b/doc/reference/PostScript.sgml @@ -0,0 +1,41 @@ + + + + + X + + + +
+ The &PostScript; Method + + + + X + + + +
diff --git a/doc/user/program.sgml b/doc/reference/Program.sgml similarity index 100% rename from doc/user/program.sgml rename to doc/reference/Program.sgml diff --git a/doc/reference/RES.sgml b/doc/reference/RES.sgml new file mode 100644 index 00000000..15c0aeaa --- /dev/null +++ b/doc/reference/RES.sgml @@ -0,0 +1,41 @@ + + + + + X + + + +
+ The &RES; Method + + + + X + + + +
diff --git a/doc/reference/SharedLibrary.sgml b/doc/reference/SharedLibrary.sgml new file mode 100644 index 00000000..603dab1d --- /dev/null +++ b/doc/reference/SharedLibrary.sgml @@ -0,0 +1,41 @@ + + + + + X + + + +
+ The &SharedLibrary; Method + + + + X + + + +
diff --git a/doc/reference/SharedObject.sgml b/doc/reference/SharedObject.sgml new file mode 100644 index 00000000..08607693 --- /dev/null +++ b/doc/reference/SharedObject.sgml @@ -0,0 +1,41 @@ + + + + + X + + + +
+ The &SharedObject; Method + + + + X + + + +
diff --git a/doc/reference/StaticLibrary.sgml b/doc/reference/StaticLibrary.sgml new file mode 100644 index 00000000..ea7ae5b4 --- /dev/null +++ b/doc/reference/StaticLibrary.sgml @@ -0,0 +1,41 @@ + + + + + X + + + +
+ The &StaticLibrary; Method + + + + X + + + +
diff --git a/doc/reference/StaticObject.sgml b/doc/reference/StaticObject.sgml new file mode 100644 index 00000000..ff8dae89 --- /dev/null +++ b/doc/reference/StaticObject.sgml @@ -0,0 +1,41 @@ + + + + + X + + + +
+ The &StaticObject; Method + + + + X + + + +
diff --git a/doc/reference/copyright.sgml b/doc/reference/copyright.sgml new file mode 100644 index 00000000..7f6059ce --- /dev/null +++ b/doc/reference/copyright.sgml @@ -0,0 +1,32 @@ + + +
+ + + SCons User's Guide Copyright (c) 2003 Steven Knight + + +
diff --git a/doc/user/reference.sgml b/doc/reference/errors.sgml similarity index 87% rename from doc/user/reference.sgml rename to doc/reference/errors.sgml index ef8e5a94..448777f1 100644 --- a/doc/user/reference.sgml +++ b/doc/reference/errors.sgml @@ -29,28 +29,6 @@ -
- Command-Line Options - - - - X - - - -
- -
- Default Builders - - - - X - - - -
-
X diff --git a/doc/reference/main.sgml b/doc/reference/main.sgml new file mode 100644 index 00000000..87b4a848 --- /dev/null +++ b/doc/reference/main.sgml @@ -0,0 +1,204 @@ + + + + %version; + + + %scons; + + + + + + + + + + + + + + + + + + + + + + + + + + +]> + + + + SCons Reference Manual &buildversion; + + + Steven + Knight + + + Revision &buildrevision; (&builddate;) + + 2003 + + + 2003 + Steven Knight + + + + ©right; + + + version &buildversion; + + + + + Preface + &preface; + + + + Builder Reference + +
+ The Alias Builder + &Alias_file; +
+ +
+ The CFile Builder + &CFile_file; +
+ +
+ The Command Builder + &Command_file; +
+ +
+ The CXXFile Builder + &CXXFile_file; +
+ +
+ The Install Builder + &Install_file; +
+ +
+ The InstallAs Builder + &InstallAs_file; +
+ +
+ The Library Builder + &Library_file; +
+ +
+ The Object Builder + &Object_file; +
+ +
+ The PCH Builder + &PCH_file; +
+ +
+ The PDF Builder + &PDF_file; +
+ +
+ The PDF Builder + &PostScript_file; +
+ +
+ The Program Builder + &Program_file; +
+ +
+ The RES Builder + &RES_file; +
+ +
+ The SharedLibrary Builder + &SharedLibrary_file; +
+ +
+ The SharedObject Builder + &SharedObject_file; +
+ +
+ The StaticLibrary Builder + &StaticLibrary_file; +
+ +
+ The StaticObject Builder + &StaticObject_file; +
+ +
+ + + &ConsVar; Reference + +
+ AR + + + + X + + + +
+ +
+ + + Errors Generated by &SCons; + &errors; + + +
diff --git a/doc/reference/preface.sgml b/doc/reference/preface.sgml new file mode 100644 index 00000000..82ea44a1 --- /dev/null +++ b/doc/reference/preface.sgml @@ -0,0 +1,85 @@ + + + + + X + + + +
+ Why &SCons;? + + + + X + + + +
+ +
+ History + + + + X + + + +
+ +
+ Conventions + + + + X + + + +
+ +
+ Acknowledgements + + + + X + + + +
+ +
+ Contact + + + + X + + + +
diff --git a/doc/scons.mod b/doc/scons.mod index 9f1832c4..1c2653ef 100644 --- a/doc/scons.mod +++ b/doc/scons.mod @@ -16,6 +16,7 @@ Autoconf"> Cons"> +gcc"> Make"> Make++"> SCons"> @@ -79,8 +80,9 @@ Alias"> Aliases"> +Append"> Build"> -Cache"> +CacheDir"> Clean"> Clone"> Command"> @@ -106,6 +108,9 @@ Split"> Task"> + +Cache"> + +CC"> CCFLAGS"> LIBPATH"> PYTHONPATH"> @@ -140,12 +146,23 @@ --> -Object"> +BuildDir"> +CFile"> +CXXFile"> Library"> -SharedLibrary"> +Object"> +PCH"> +PDF"> +PostScript"> Program"> +RES"> +SharedLibrary"> +SharedObject"> +StaticLibrary"> +StaticObject"> + + Make"> -BuildDir"> diff --git a/doc/user/alias.sgml b/doc/user/alias.sgml index 33c236ac..3f48ee09 100644 --- a/doc/user/alias.sgml +++ b/doc/user/alias.sgml @@ -23,23 +23,72 @@ --> - + We've already seen how you can use the &Alias; + function to create a target named install: + + + + + env = Environment() + hello = env.Program('hello.c') + env.Install('/usr/bin', hello) + env.Alias('install', '/usr/bin') + + + + + You can then use this alias on the command line + to tell &SCons; more naturally that you want to install files: + + + + + % scons install + Install file: "hello" as "/usr/bin/hello" + - + - X + Like other &Builder; methods, though, + the &Alias; method returns an object + representing the alias being built. + You can then use this object as input to anothother &Builder;. + This is especially useful if you use such an object + as input to another call to the &Alias; &Builder;, + allowing you to create a hierarchy + of nested aliases: - + -
- Alias Targets + + env = Environment() + p = env.Program('hello.c') + l = env.Library('hello.c') + env.Install('/usr/bin', p) + env.Install('/usr/lib', l) + ib = env.Alias('install-bin', '/usr/bin') + il = env.Alias('install-lib', '/usr/lib') + env.Alias('install', [ib, il]) + - + - X + This example defines separate install, + install-bin, + and install-lib aliases, + allowing you finer control over what gets installed: - + -
+ + % scons install-bin + Install file: "hello" as "/usr/bin/hello" + % scons install-lib + Install file: "libhello.a" as "/usr/lib/libhello.a" + % scons -c / + % scons install + Install file: "hello" as "/usr/bin/hello" + Install file: "libhello.a" as "/usr/lib/libhello.a" + diff --git a/doc/user/builders.sgml b/doc/user/builders.sgml index ac5f1937..c1b42694 100644 --- a/doc/user/builders.sgml +++ b/doc/user/builders.sgml @@ -95,30 +95,375 @@ This functionality could be invoked as in the following example: --> - + + + &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. + + + +
- X +
+ Builders That Execute Python Functions - + -
- Builders That Execute External Commands + 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). - + - X + + def build_function(target, source, env): + # XXX + return None + - + -
+ XXX explain the function + XXX define the arguments -
- Builders That Execute Python Functions + - + - X + 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 5403c43e..ed72c1e0 100644 --- a/doc/user/caching.sgml +++ b/doc/user/caching.sgml @@ -23,30 +23,242 @@ --> - + + + To enable sharing of derived files, + use the &CacheDir; function + in any &SConscript; file: + + + + + CacheDir('/usr/local/build_cache') + + + + + Note that the directory you specify must already exist + and be readable and writable by all developers + who will be sharing derived files. + It should also be in some central location + that all builds will be able to access. + In environments where developers are using separate systems + (like individual workstations) for builds, + this directory would typically be + on a shared or NFS-mounted file system. + + + + + + Here's what happens: + When a build has a &CacheDir; specified, + every time a file is built, + it is stored in the shared cache directory + along with its MD5 build signature. + On subsequent builds, + before an action is invoked to build a file, + &SCons; will check the shared cache directory + to see if a file with the exact same build + signature already exists. + If so, the derived file will not be built locally, + but will be copied into the local build directory + from the shared cache directory, + like so: + + + + + % scons + cc -c hello.c -o hello.o + cc -o hello hello.o + % scons -c + % scons + Retrieved `hello.o' from cache + Retrieved `hello' from cache + % + + +
+ +
+ Keeping Build Output Consistent + + + + One potential drawback to using a shared cache + is that your build output can be inconsistent + from invocation to invocation, + because any given file may be rebuilt one time + and retrieved from the shared cache the next time. + This can make analyzing build output more difficult, + especially for automated scripts that + expect consistent output each time. + + + + + + If, however, you use the --cache-show option, + &SCons; will print the command line that it + would have executed + to build the file, + even when it is retrieving the file from the shared cache. + This makes the build output consistent + every time the build is run: + + + + + % scons + cc -c hello.c -o hello.o + cc -o hello hello.o + % scons -c + Removed hello.o + Removed hello + % scons --cache-show + cc -c hello.c -o hello.o + cc -o hello hello.o + % + + + + + The trade-off, of course, is that you no longer + know whether or not &SCons; + has retrieved a derived file from cache + or has rebuilt it locally. + + + +
+ +
+ Not Retrieving Files From a Shared Cache + + + + Retrieving an already-built file + from the shared cache + is usually a significant time-savings + over rebuilding the file, + but how much of a savings + (or even whether it saves time at all) + can depend a great deal on your + system or network configuration. + For example, retrieving cached files + from a busy server over a busy network + might end up being slower than + rebuilding the files locally. + + + + + + In these cases, you can specify + the --cache-disable + command-line option to tell &SCons; + to not retrieve already-built files from the + shared cache directory: + + + + + % scons + 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 + % scons -c + Removed hello.o + Removed hello + % scons --cache-disable + cc -c hello.c -o hello.o + cc -o hello hello.o + % + + +
+ +
+ Populating a Shared Cache With Already-Built Files + + + + Sometimes, you may have one or more derived files + already built in your local build tree + that you wish to make available to other people doing builds. + For example, you may find it more effective to perform + integration builds with the cache disabled + (per the previous section) + and only populate the shared cache directory + with the built files after the integration build + has completed successfully. + This way, the cache will only get filled up + with derived files that are part of a complete, successful build + not with files that might be later overwritten + while you debug integration problems. + + - + - X + In this case, you can use the + the --cache-force option + to tell &SCons; to put all derived files in the cache, + even if the files had already been built + by a previous invocation: - + -
- The &Cache; Method + + % scons --cache-disable + cc -c hello.c -o hello.o + cc -o hello hello.o + % scons -c + Removed hello.o + Removed hello + % scons --cache-disable + cc -c hello.c -o hello.o + cc -o hello hello.o + % scons --cache-force + % scons -c + Removed hello.o + Removed hello + % scons + Retrieved `hello.o' from cache + Retrieved `hello' from cache + % + - + - X + Notice how the above sample run + demonstrates that the --cache-disable + option avoids putting the built + hello.o + and + hello files in the cache, + but after using the --cache-force option, + the files have been put in the cache + for the next invocation to retrieve. - + -
+
diff --git a/doc/user/command.sgml b/doc/user/command.sgml index abb3a581..945c6565 100644 --- a/doc/user/command.sgml +++ b/doc/user/command.sgml @@ -27,12 +27,6 @@ =head2 The C method -The C method is a catchall method which can be used to arrange for -any build action to be executed to update the target. For this command, a -target file and list of inputs is provided. In addition, a build action -is specified as the last argument. The build action is typically a -command line or lines, but may also contain Perl code to be executed; -see the section above on build actions for details. The C method is called as follows: @@ -55,19 +49,60 @@ F and F. --> - - - X - - - -
- The &Command; Method - - - - X - - - -
+ + + 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/default.sgml b/doc/user/default.sgml index eb2bdc1a..981ac426 100644 --- a/doc/user/default.sgml +++ b/doc/user/default.sgml @@ -69,9 +69,9 @@ default list. explicitly specify one or more targets on the command line. Sometimes, however, you may want - to explicitly specify that only - certain programs should be built by default, - which you do using the &Default; function: + to specify explicitly that only + certain programs should be built by default. + You do this with the &Default; function: @@ -84,7 +84,7 @@ default list. - This &SConstruct; file builds two programs, + This &SConstruct; file knows how to build two programs, &hello; and &goodbye;, but only builds the &hello program by default: @@ -162,7 +162,7 @@ default list. prog1 and prog3 - programs: + programs by default: diff --git a/doc/user/depends.sgml b/doc/user/depends.sgml index e8491e4e..8669c722 100644 --- a/doc/user/depends.sgml +++ b/doc/user/depends.sgml @@ -46,369 +46,369 @@ operating system on which the build is performed (as reported by C - - - So far we've seen how &SCons; handles one-time builds. - But the real point of a build tool like &SCons; - is to rebuild the necessary things when source files change. - The other side of rebuilding all the necessary things - is that &SCons; should not - unnecessarily rebuild things that have already - been built. - You can see this at work simply be re-invoking &SCons; - after building our simple &hello; example: - - - - - % scons - cc -c hello.c -o hello.o - cc -o hello hello.o - % scons - % - - - - - &SCons; has remembered that the &hello; program - is up-to-date with respect to the current &hello_c; source file, - and avoids rebuilding it. - You can see this more clearly by naming - the &hello; program explicitly on the command line: - - - - - % scons hello - cc -c hello.c -o hello.o - cc -o hello hello.o - % scons hello - scons: `hello' is up to date. - % - - - - - Note that &SCons; only reports "...is up to date" - for target files named explicitly on the command line, - to avoid cluttering the output. - - - -
- MD5 Signatures - - - - &SCons; keeps track of whether a file has changed - based on the file's contents, - not the modification time. - This means that you may be surprised by the - behavior of &SCons; if you are used to the - &Make; convention of forcing - a rebuild by updating the file's - modification time like so: - - - - - % scons hello - cc -c hello.c -o hello.o - cc -o hello hello.o - % touch hello.c - % scons hello - scons: `hello' is up to date. - % - - - - - This saves time by avoiding unnecessary rebuilds when, - for example, someone rewrites the - contents of a file without making a change. - But if the contents of the file change, - then &SCons; detects the change - and rebuilds the program as required: - - - - - % scons hello - cc -c hello.c -o hello.o - cc -o hello hello.o - % edit hello.c - [CHANGE THE CONTENTS OF hello.c] - % scons hello - cc -c hello.c -o hello.o - cc -o hello hello.o - % - - - - - X - - - -
+ + + So far we've seen how &SCons; handles one-time builds. + But the real point of a build tool like &SCons; + is to rebuild the necessary things, + and only the necessary thing, when source files change. + Put another way, + &SCons; should not + waste time rebuilding things that have already been built. + You can see this at work simply be re-invoking &SCons; + after building our simple &hello; example: + + + + + % scons + cc -c hello.c -o hello.o + cc -o hello hello.o + % scons + % + + + + + The second time it is executed, + &SCons; realizes that the &hello; program + is up-to-date with respect to the current &hello_c; source file, + and avoids rebuilding it. + You can see this more clearly by naming + the &hello; program explicitly on the command line: + + + + + % scons hello + cc -c hello.c -o hello.o + cc -o hello hello.o + % scons hello + scons: `hello' is up to date. + % + + + + + Note that &SCons; only reports "...is up to date" + for target files named explicitly on the command line, + to avoid cluttering the output. + + + +
+ MD5 Signatures + + + + &SCons; keeps track of whether a file has changed + based on the file's contents, + not the modification time. + This means that you may be surprised by the + behavior of &SCons; if you are used to the + &Make; convention of forcing + a rebuild by updating the file's + modification time like so: + + + + + % scons hello + cc -c hello.c -o hello.o + cc -o hello hello.o + % touch hello.c + % scons hello + scons: `hello' is up to date. + % + + + + + This saves time by avoiding unnecessary rebuilds when, + for example, someone rewrites the + contents of a file without making a change. + But if the contents of the file change, + then &SCons; detects the change + and rebuilds the program as required: + + + + + % scons hello + cc -c hello.c -o hello.o + cc -o hello hello.o + % edit hello.c + [CHANGE THE CONTENTS OF hello.c] + % scons hello + cc -c hello.c -o hello.o + cc -o hello hello.o + % + + + + + X + + + +
+ + - -
- Implicit Dependencies + --> - +
+ Implicit Dependencies + + + + Now suppose that our "Hello, World!" program + actually has a #include line + to include &hello_h; file in the compilation: + + + + + #include "hello.h" + int + main() + { + printf("Hello, %s!\n", string); + } + + + + + And, for completeness, the &hello_h; file looks like this: + + + + + #define string "world" + + + + + In this case, we want &SCons; to recognize that, + if the contents of the &hello_h; file change, + the &hello; program must be recompiled. + To do this, we need to modify the + &SConstruct; file like so: + + + + + env = Environment(CPPPATH = '.') XXX IS CPPPATH NECESSARY? + hello = env.Program('hello.c') + + + + + The &CPPPATH; assignment in the &Environment; call + tells &SCons; to look in the current directory + ('.') + for any files included by C source files + (.c or .h files). + With this assignment in the &SConstruct file: + + + + + % scons hello + cc -c hello.c -o hello.o + cc -o hello hello.o + % scons hello + scons: `hello' is up to date. + % edit hello.h + [CHANGE THE CONTENTS OF hello.h] + % scons hello + cc -c hello.c -o hello.o + cc -o hello hello.o + % + + + + + &SCons; knows that the &hello; + program must be rebuilt + because it scans the contents of + the &hello_c; file + for the #include lines that indicate + another file is being included in the compilation. + &SCons; records these as + implicit dependencies + of the target file, + Consequently, + when the &hello_h; file changes, + &SCons; realizes that the &hello_c; file includes it, + and rebuilds the resulting &hello; program + that depends on both the &hello_c; and &hello_h; files. + + + + + + X + + - Now suppose that our "Hello, World!" program - actually looks like this: + + +
+ +
+ The &Ignore; Method + + + + Sometimes it makes sense + to not rebuild a program, + even if a dependency file changes. + In this case, + you would tell &SCons; specifically + to ignore a dependency as follows: + + + + + env = Environment() + hello = env.Program('hello.c') + env.Ignore(hello, 'hello.h') + - + - - #include "hello.h" - int - main() - { - printf("Hello, %s!\n", string); - } - + + % scons hello + cc -c hello.c -o hello.o + cc -o hello hello.o + % scons hello + scons: `hello' is up to date. + % edit hello.h + [CHANGE THE CONTENTS OF hello.h] + % scons hello + scons: `hello' is up to date. + - + - That is, the first line - includes a &hello_h; - that looks like this: + Now, the above example is a little contrived, + because it's hard to imagine a real-world situation + where you wouldn't to rebuild &hello; + if the &hello_h; file changed. + A more realistic example + might be if the &hello; + program is being built in a + directory that is shared between multiple systems + that have different copies of the + &stdio_h; include file. + In that case, + &SCons; would notice the differences between + the different systems' copies of &stdio_h; + and would rebuild &hello; + each time you change systems. + You could avoid these rebuilds as follows: - + - - #define string "world" - + + env = Environment() + hello = env.Program('hello.c') + env.Ignore(hello, '/usr/include/stdio.h') + - +
- In this case, we want &SCons; to recognize that, - if the contents of the &hello_h; file change, - the &hello; program must be recompiled. - To do this, we need to modify the - &SConstruct; file like so: +
+ The &Depends; Method - + - - env = Environment(CPPPATH = '.') XXX IS CPPPATH NECESSARY? - hello = env.Program('hello.c') - + On the other hand, + sometimes a file depends on another + file that the scanner(s) in &SCons; will not detect. + For this situation, + &SCons; allows you to specific that one file explicitly + depends on another file, + and must be rebuilt whenever that file changes, + using the &Depends; method: - + - The &CPPPATH; assignment in the &Environment; call - tells &SCons; to look in the current directory - ('.') - for any files included by C source files - (.c or .h files). - With this assignment in the &SConstruct file: + + env = Environment() + hello = env.Program('hello.c') + env.Depends(hello, 'other_file') + - + - - % scons hello - cc -c hello.c -o hello.o - cc -o hello hello.o - % scons hello - scons: `hello' is up to date. - % edit hello.h - [CHANGE THE CONTENTS OF hello.h] - % scons hello - cc -c hello.c -o hello.o - cc -o hello hello.o - % - + + % scons hello + cc -c hello.c -o hello.o + cc -o hello hello.o + % scons hello + scons: `hello' is up to date. + % edit other_file + [CHANGE THE CONTENTS OF other_file] + % scons hello + cc -c hello.c -o hello.o + cc -o hello hello.o + - +
- &SCons; knows that the &hello; - program must be rebuilt - because it scans the contents of - the &hello_c; file - for the #include lines that indicate - another file is being included in the compilation. - &SCons; records these as - implicit dependencies - of the target file, - Consequently, - when the &hello_h; file changes, - &SCons; realizes that the &hello_c; file includes it, - and rebuilds the resulting &hello; program - that depends on both the &hello_c; and &hello_h; files. + -
+
+ The &Salt; Method - + - X + X - + - - -
- -
- The &Ignore; Method - - - - Sometimes it makes sense - to not rebuild a program, - even if a dependency file changes. - In this case, - you would tell &SCons; specifically - to ignore a dependency as follows: - - - - - env = Environment() - hello = env.Program('hello.c') - env.Ignore(hello, 'hello.h') - - - - - - % scons hello - cc -c hello.c -o hello.o - cc -o hello hello.o - % scons hello - scons: `hello' is up to date. - % edit hello.h - [CHANGE THE CONTENTS OF hello.h] - % scons hello - scons: `hello' is up to date. - - - - - Now, the above example is a little contrived, - because it's hard to imagine a real-world situation - where you wouldn't to rebuild &hello; - if the &hello_h; file changed. - A more realistic example - might be if the &hello; - program is being built in a - directory that is shared between multiple systems - that have different copies of the - &stdio_h; include file. - In that case, - &SCons; would notice the differences between - the different systems' copies of &stdio_h; - and would rebuild &hello; - each time you change systems. - You could avoid these rebuilds as follows: - - - - - env = Environment() - hello = env.Program('hello.c') - env.Ignore(hello, '/usr/include/stdio.h') - - -
- -
- The &Depends; Method - - - - On the other hand, - sometimes a file depends on another - file that the scanner(s) in &SCons; will not detect. - For this situation, - &SCons; allows you to specific that one file explicitly - depends on another file, - and must be rebuilt whenever that file changes, - using the &Depends; method: - - - - - env = Environment() - hello = env.Program('hello.c') - env.Depends(hello, 'other_file') - - - - - - % scons hello - cc -c hello.c -o hello.o - cc -o hello hello.o - % scons hello - scons: `hello' is up to date. - % edit other_file - [CHANGE THE CONTENTS OF other_file] - % scons hello - cc -c hello.c -o hello.o - cc -o hello hello.o - - -
- - - -
- The &Salt; Method - - - - X - - - -
+
- --> + --> -
- Time Stamps +
+ Time Stamps - + - X + X - + -
+
-
- The &SourceSignature; Method +
+ The &SourceSignature; Method - + - X + X - + -
+
diff --git a/doc/user/environments.sgml b/doc/user/environments.sgml index b06ade11..8117cf04 100644 --- a/doc/user/environments.sgml +++ b/doc/user/environments.sgml @@ -25,47 +25,6 @@ + + + It is rare that all of the software in a large, + complicated system needs to be built the same way. + Different source files need different options + enabled on the command line; + different executable programs need to be linked + with different libraries (shared or static); + XXX + &SCons; accomodates these different build + requirements by allowing you to create and + configure multiple &consenvs; + that control how the software is built. + Technically, a &consenv; is an object + that has a number of associated + &consvars;, each with a name and a value. + (A &consenv; also has an attached + set of &Builder; methods, + about which we'll learn more later.) -=head2 Overriding construction variables + -There are several ways of extending Cons, which vary in degree of -difficulty. The simplest method is to define your own construction -environment, based on the default environment, but modified to reflect your -particular needs. This will often suffice for C-based applications. You can -use the C constructor, and the C and C methods to create -hybrid environments. These changes can be entirely transparent to the -underlying F files. + ---> + A &consenv; is created by the &Environment; + method which you have already seen. + What you haven't seen, though, + is that when you initialize a &consenv;, + you can set the values of the + environment's &consvars; + to control how a program is built. + For example: + + + + + env = Environment(CC = 'gcc', + CCFLAGS = '-O2') + + env.Program('foo.c') + + + This example, rather than using the default, + explicitly specifies use of the + GNU C compiler &gcc;, + and further specifies that the -O2 + (optimization level two) + flag should be used when compiling the object file. + So a run from this example would look like: - X + - + We can even use multiple &consenvs; to build + multiple versions of a single program. + If you do this by simply trying to use the + &Program; builder with both environments, though, + like this: - + - - optimize = Environment(CCFLAGS = '-O2') - debug = Environment(CCFLAGS = '-g') + + opt = Environment(CCFLAGS = '-O2') + dbg = Environment(CCFLAGS = '-g') - o = optimize.Object('foo-opt', 'foo.c') - optimize.Program(o) + opt.Program('foo', 'foo.c') - d = debug.Object('foo-debug', 'foo.c') - debug.Program(d) - + dbg.Program('foo', 'foo.c') + - - % scons . - cc -c -g foo.c -o foo-debug.o - cc -o foo-debug foo-debug.o - cc -c -O2 foo.c -o foo-opt.o - cc -o foo-opt foo-opt.o - + + + Then &SCons; generates the following error: + + + + + % scons + scons: *** Two different environments were specified for the same target: foo.o + File "SConstruct", line 6, in ? + + + + + This is because the two &Program; calls have + each implicitly told &SCons; to generate an object file named + foo.o, + one with a &CCFLAGS; value of + -O2 + and one with a &CCFLAGS; value of + -g. + To work around this, + we must explicitly specify + that each environment compile + foo.c + to a separately-named object file + using the &Object; call, like so: + + + + + opt = Environment(CCFLAGS = '-O2') + dbg = Environment(CCFLAGS = '-g') + + o = opt.Object('foo-opt', 'foo.c') + opt.Program(o) + + d = dbg.Object('foo-dbg', 'foo.c') + dbg.Program(d) + + + + + Notice that each call to the &Object; builder + returns a value, + an internal &SCons; object that + represents the file that will be built. + We then use that object + as input to the &Program; builder. + This avoids having to specify explicitly + the object file name in multiple places, + and makes for a compact, readable + &SConstruct file. + Our &SCons; output then looks like: + + + + + % scons + cc -c -g foo.c -o foo-dbg.o + cc -o foo-dbg foo-dbg.o + cc -c -O2 foo.c -o foo-opt.o + cc -o foo-opt foo-opt.o + + +
- The &Environment; Constructor + Copying &ConsEnvs; - X + Sometimes you want to more than one &consenv; + to use 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 + to create a copy of a &consenv;. + Like the &Environment; call that creates a &consenv;, + the &Copy; method takes &consvar; assignments, + which will override the values in the copied &consenv;. + For example, suppose we want to use &gcc; + to create three versions of a program, + one optimized, one debug, and one with neither. + We could do this by creating a "base" &consenv; + that sets &CC; to &gcc;, + and then creating two copies, + one which sets &CCFLAGS; for optimization + and the other with sets &CCFLAGS; for debugging: + + + + + env = Environment(CC = 'gcc') + opt = env.Copy(CCFLAGS = '-O2') + dbg = env.Copy(CCFLAGS = '-g') + + e = opt.Object('foo', 'foo.c') + + o = opt.Object('foo-opt', 'foo.c') + opt.Program(o) + + d = dbg.Object('foo-dbg', 'foo.c') + dbg.Program(d) + + + + + Then our output would look like: + + % scons + gcc -c foo.c -o foo.o + gcc -o foo foo.o + gcc -c -g foo.c -o foo-dbg.o + gcc -o foo-dbg foo-dbg.o + gcc -c -O2 foo.c -o foo-opt.o + gcc -o foo-opt foo-opt.o + +
- The &Copy; Method + Fetching Values From a &ConsEnv; @@ -522,4 +647,74 @@ is linked, and, of course, C will be used to compile both modules: + + env = Environment() + + + + % scons + + +
+ +
+ Modifying a &ConsEnv; + +
+ Replacing Values in a &ConsEnv; + + + + X + + + + + env = Environment() + + + + % scons + + +
+ +
+ Appending to the End of Values in a &ConsEnv; + + + + X + + + + + env = Environment() + + + + % scons + + +
+ +
+ Appending to the Beginning of Values in a &ConsEnv; + + + + X + + + + + env = Environment() + + + + % scons + + +
+
diff --git a/doc/user/help.sgml b/doc/user/help.sgml index 5e2ced38..233809e7 100644 --- a/doc/user/help.sgml +++ b/doc/user/help.sgml @@ -69,7 +69,7 @@ If there is no &Help; text in the &SConstruct; or &SConscript; files, &SCons; will revert to displaying its - standard list and description of available command-line + standard list that describes the &SCons; command-line options. This list is also always displayed whenever the -H option is used. diff --git a/doc/user/hierarchy.sgml b/doc/user/hierarchy.sgml index aa56c8d4..617eb592 100644 --- a/doc/user/hierarchy.sgml +++ b/doc/user/hierarchy.sgml @@ -36,44 +36,6 @@ C commands. =head2 The Build command -The C command takes a list of F file names, and arranges -for them to be included in the build. For example: - - Build qw( - drivers/display/Conscript - drivers/mouse/Conscript - parser/Conscript - utilities/Conscript - ); - -This is a simple two-level hierarchy of build scripts: all the subsidiary -F files are mentioned in the top-level F file. Notice -that not all directories in the tree necessarily have build scripts -associated with them. - -This could also be written as a multi-level script. For example, the -F file might contain this command: - - Build qw( - parser/Conscript - drivers/Conscript - utilities/Conscript - ); - -and the F file in the F directory might contain this: - - Build qw( - display/Conscript - mouse/Conscript - ); - -Experience has shown that the former model is a little easier to understand, -since the whole construction tree is laid out in front of you, at the -top-level. Hybrid schemes are also possible. A separately maintained -component that needs to be incorporated into a build tree, for example, -might hook into the build tree in one place, but define its own construction -hierarchy. - By default, Cons does not change its working directory to the directory containing a subsidiary F file it is including. This behavior can be enabled for a build by specifying, in the top-level F @@ -220,30 +182,169 @@ make no difference to the build. --> - + + + The source code for large software projects + rarely stays in a single directory, + but is nearly always divided into a + hierarchy of directories. + Organizing a large software build using &SCons; + involves creating a hierarchy of build scripts + using the &SConscript; function. + + + +
+ &SConscript; Files + + + + As we've already seen, + the build script at the top of the tree is called &SConstruct;. + The top-level &SConstruct; file can + use the &SConscript; function to + include other subsidiary scripts in the build. + These subsidiary scripts can, in turn, + use the &SConscript; function + to include still other scripts in the build. + By convention, these subsidiary scripts are usually + named &SConscript;. + For example, a top-level &SConstruct; file might + arrange for four subsidiary scripts to be included + in the build as follows: + + + + + SConscript(['drivers/display/SConscript', + 'drivers/mouse/SConscript', + 'parser/SConscript', + 'utilities/SConscript']) + + + + + In this case, the &SConstruct; file + lists all of the &SConscript; files in the build explicitly. + (Note, however, that not every directory in the tree + necessarily has an &SConscript; file.) + Alternatively, the drivers + subdirectory might contain an intermediate + &SConscript; file, + in which case the &SConscript; call in + the top-level &SConstruct; file + would look like: + + + + + SConscript(['drivers/SConscript', + 'parser/SConscript', + 'utilities/SConscript']) + + + + + And the subsidiary &SConscript; file in the + drivers subdirectory + would look like: + + + + + SConscript(['display/SConscript', + 'mouse/SConscript']) + + + + + Whether you list all of the &SConscript; files in the + top-level &SConstruct; file, + or place a subsidiary &SConscript; file in + intervening directories, + or use some mix of the two schemes, + is up to you and the needs of your software. + + + +
+ +
+ Path Names Are Relative to the &SConscript; Directory + + + + X + + + + + SConscript(['display/SConscript', + 'mouse/SConscript']) + + +
+ +
+ Sharing Environments (and Other Variables) Between &SConscript; Files + + + + X + + + + + SConscript(['display/SConscript', + 'mouse/SConscript']) + + +
+ Exporting Variables + + + + X + + + + + SConscript(['display/SConscript', + 'mouse/SConscript']) + + +
+ +
+ Importing Variables - X + - + X -
- &SConscript; Files + - + + SConscript(['display/SConscript', + 'mouse/SConscript']) + - X +
- +
+ Returning Values -
+ -
- X + X - + - X + + SConscript(['display/SConscript', + 'mouse/SConscript']) + - +
-
+
diff --git a/doc/user/install.sgml b/doc/user/install.sgml index 530fa7ad..2cebbd45 100644 --- a/doc/user/install.sgml +++ b/doc/user/install.sgml @@ -23,75 +23,211 @@ --> - + + env = Environment() + hello = env.Program('hello.c') + env.InstallAs('/usr/bin/hello-new', hello) + env.Alias('install', '/usr/bin') + - + - X + This installs the hello + program with the name hello-new + as follows: - + -
- The &Install; Builder + + % scons install + cc -c hello.c -o hello.o + cc -o hello hello.o + Install file: "hello" as "/usr/bin/hello-new" + - +
- X +
+ Installing Multiple Files Under Different Names - + -
+ Lastly, if you have multiple files that all + need to be installed with different file names, + you can either call the &InstallAs; function + multiple times, or as a shorthand, + you can supply same-length lists + for the both the target and source arguments: -
- The &InstallAs; Method + - + + env = Environment() + hello = env.Program('hello.c') + goodbye = env.Program('goodbye.c') + env.InstallAs(['/usr/bin/hello-new', + '/usr/bin/goodbye-new', + [hello, goodbye]) + + + - X + In this case, the &InstallAs; function + loops through both lists simultaneously, + and copies each source file into its corresponding + target file name: - + + + + % scons install + cc -c goodbye.c -o goodbye.o + cc -o goodbye goodbye.o + cc -c hello.c -o hello.o + cc -o hello hello.o + Install file: "goodbye" as "/usr/bin/goodbye-new" + Install file: "hello" as "/usr/bin/hello-new" + -
+
diff --git a/doc/user/main.sgml b/doc/user/main.sgml index b285696d..68bc59c7 100644 --- a/doc/user/main.sgml +++ b/doc/user/main.sgml @@ -47,19 +47,15 @@ - - - - - + @@ -111,8 +107,6 @@ &depends; - - Default Targets &default; @@ -128,31 +122,6 @@ &install; - - The Program Builder - &program; - - - - The Library Builder - &library; - - - - More Things to Do With Builds - &more; - - - - The Command Builder - &command; - - - - The Object Builder - &object; - - Preventing Removal of Targets &precious; @@ -178,6 +147,11 @@ &builders; + + Avoiding Having to Write Builders + &command; + + SCons Actions &actions; @@ -193,35 +167,45 @@ &repositories; + + Fetching Files From Source Code Management Systems + &sourcecode; + + Caching Built Files &caching; - - How to Run &SCons; - &run; - - Alias Targets &alias; + + How to Run &SCons; + &run; + + Troubleshooting &troubleshoot; - - Quick Reference - &reference; - - - - Errors Generated by &SCons; - &errors; - + Complex &SCons; Example diff --git a/doc/user/precious.sgml b/doc/user/precious.sgml index 9cd2a431..26ad3451 100644 --- a/doc/user/precious.sgml +++ b/doc/user/precious.sgml @@ -25,17 +25,6 @@ - + + + Often, a software project will have + one or more central repositories, + directory trees that contain + source code, or derived files, or both. + You can eliminate additional unnecessary + rebuilds of files by having &SCons; + use files from one or more code repositories + to build files in your local build tree. + + + +
+ The &Repository; Method + + + + + + It's often useful to allow multiple programmers working + on a project to build software from + source files and/or derived files that + are stored in a centrally-accessible repository, + a directory copy of the source code tree. + (Note that this is not the sort of repository + maintained by a source code management system + like BitKeeper, CVS, or Subversion. + For information about using &SCons; + with these systems, see the section, + "Fetching Files From Source Code Management Systems," + below.) + You use the &Repository; method + to tell &SCons; to search one or more + central code repositories (in order) + for any source files and derived files + that are not present in the local build tree: - Often, a software project will have - one or more central repositories, - directory trees that contain - source code, or derived files, or both. - You can eliminate additional unnecessary - rebuilds of files by having &SCons; - use files from one or more code repositories - to build files in your local build tree. + + + + env = Environment() + env.Program('hello.c') + Repository('/usr/repository1', '/usr/repository2') + + + + + Multiple calls to the &Repository; method + will simply add repositories to the global list + that &SCons; maintains, + with the exception that &SCons; will automatically eliminate + the current directory and any non-existent + directories from the list. - + + +
+ +
+ Finding source files in repositories + + + + The above example + specifies that &SCons; + will first search for files under + the /usr/repository1 tree + and next under the /usr/repository2 tree. + &SCons; expects that any files it searches + for will be found in the same position + relative to the top-level directory XXX + In the above example, if the &hello_c; file is not + found in the local build tree, + &SCons; will search first for + a /usr/repository1/hello.c file + and then for a /usr/repository1/hello.c file + to use in its place. + + + + -
- The &Repository; Method + So given the &SConstruct; file above, + if the &hello_c; file exists in the local + build directory, + &SCons; will rebuild the &hello; program + as normal: + + - - - - - The &Repository; method - tells &SCons; to search one or more - central code repositories (in order) - for any source files and derived files - that are not present in the local build tree: - - - - - env = Environment() - env.Program('hello.c') - Repository('/usr/repository1', '/usr/repository2') - - - - - (Note that multiple calls to the &Repository; method - will simply add repositories to the global list - that &SCons; maintains, - with the exception that &SCons; will automatically eliminate - the current directory and any non-existent - directories from the list.) - - - -
- -
- Finding source files in repositories - - - - The above example - specifies that &SCons; - will first search for files under - the /usr/repository1 tree - and next under the /usr/repository2 tree. - &SCons; expects that any files it searches - for will be found in the same position - relative to the top-level directory XXX - In the above example, if the &hello_c; file is not - found in the local build tree, - &SCons; will search first for - a /usr/repository1/hello.c file - and then for a /usr/repository1/hello.c file - to use in its place. - - - - - - So given the &SConstruct; file above, - if the &hello_c; file exists in the local - build directory, - &SCons; will rebuild the &hello; program - as normal: - - - - - % scons - gcc -c hello.c -o hello.o - gcc -o hello hello.o - - - - - If, however, there is no local &hello_c; file, - but one exists in /usr/repository1, - &SCons; will recompile the &hello; program - from the source file it finds in the repository: - - - - - % scons - gcc -c /usr/repository1/hello.c -o hello.o - gcc -o hello hello.o - - - - - And similarly, if there is no local &hello_c; file - and no /usr/repository1/hello.c, - but one exists in /usr/repository2: - - - - - % scons - gcc -c /usr/repository2/hello.c -o hello.o - gcc -o hello hello.o - - - + + % scons + gcc -c hello.c -o hello.o + gcc -o hello hello.o + + + - + If, however, there is no local &hello_c; file, + but one exists in /usr/repository1, + &SCons; will recompile the &hello; program + from the source file it finds in the repository: + + + + + % scons + gcc -c /usr/repository1/hello.c -o hello.o + gcc -o hello hello.o + + + + + And similarly, if there is no local &hello_c; file + and no /usr/repository1/hello.c, + but one exists in /usr/repository2: + + + + + % scons + gcc -c /usr/repository2/hello.c -o hello.o + gcc -o hello hello.o + + + + + -
+
-
- Finding the &SConstruct; file in repositories +
+ Finding the &SConstruct; file in repositories - + - &SCons; will also search in repositories - for the &SConstruct; file and any specified &SConscript; files. - This poses a problem, though: how can &SCons; search a - repository tree for an &SConstruct; file - if the &SConstruct; file itself contains the information - about the pathname of the repository? - To solve this problem, &SCons; allows you - to specify repository directories - on the command line using the -Y: + &SCons; will also search in repositories + for the &SConstruct; file and any specified &SConscript; files. + This poses a problem, though: how can &SCons; search a + repository tree for an &SConstruct; file + if the &SConstruct; file itself contains the information + about the pathname of the repository? + To solve this problem, &SCons; allows you + to specify repository directories + on the command line using the -Y: - + - - % scons -Y /usr/repository1 -Y /usr/repository2 - + + % scons -Y /usr/repository1 -Y /usr/repository2 + - + - When looking for source or derived files, - &SCons; will first search the repositories - specified on the command line, - and then search the repositories - specified in the &SConstruct; or &SConscript; files. + When looking for source or derived files, + &SCons; will first search the repositories + specified on the command line, + and then search the repositories + specified in the &SConstruct; or &SConscript; files. - + -
+
-
- Finding derived files in repositories +
+ Finding derived files in repositories - + - If a repository contains not only source files, - but also derived files (such as object files, - libraries, or executables), &SCons; will perform - its normal MD5 signature calculation to - decide if a derived file in a repository is up-to-date, - or the derived file must be rebuilt in the local build directory. - For the &SCons; signature calculation to work correctly, - a repository tree must contain the &sconsign; files - that &SCons; uses to keep track of signature information. + If a repository contains not only source files, + but also derived files (such as object files, + libraries, or executables), &SCons; will perform + its normal MD5 signature calculation to + decide if a derived file in a repository is up-to-date, + or the derived file must be rebuilt in the local build directory. + For the &SCons; signature calculation to work correctly, + a repository tree must contain the &sconsign; files + that &SCons; uses to keep track of signature information. - + - + - Usually, this would be done by a build integrator - who would run &SCons; in the repository - to create all of its derived files and &sconsign; files, - or who would &SCons; in a separate build directory - and copying the resulting tree to the desired repository: + Usually, this would be done by a build integrator + who would run &SCons; in the repository + to create all of its derived files and &sconsign; files, + or who would &SCons; in a separate build directory + and copying the resulting tree to the desired repository: - + - - % cd /usr/repository1 - % scons - gcc -c hello.c -o hello.o - gcc -o hello hello.o - + + % cd /usr/repository1 + % scons + gcc -c hello.c -o hello.o + gcc -o hello hello.o + - - - (Note that this is safe even if the &SConstruct; file - lists /usr/repository1 as a repository, - because &SCons; will remove the current build directory - from its repository list for that invocation.) + + + (Note that this is safe even if the &SConstruct; file + lists /usr/repository1 as a repository, + because &SCons; will remove the current build directory + from its repository list for that invocation.) - + - + - Now, with the repository populated, - we only need to create the one local source file - we're interested in working with at the moment, - and use the -Y option to - tell &SCons; to fetch any other files it needs - from the repository: + Now, with the repository populated, + we only need to create the one local source file + we're interested in working with at the moment, + and use the -Y option to + tell &SCons; to fetch any other files it needs + from the repository: - + - - % cd $HOME/build - % edit hello.c - % scons -Y /usr/repository1 - gcc -c hello.c -o hello.o - gcc -o hello hello.o - XXXXXXX - + + % cd $HOME/build + % edit hello.c + % scons -Y /usr/repository1 + gcc -c hello.c -o hello.o + gcc -o hello hello.o + XXXXXXX + - + - Notice that &SCons; realizes that it does not need to - rebuild a local XXX.o file, - but instead uses the already-compiled XXX.o file - from the repository. + Notice that &SCons; realizes that it does not need to + rebuild a local XXX.o file, + but instead uses the already-compiled XXX.o file + from the repository. - + -
+
-
- Guaranteeing local copies of files +
+ Guaranteeing local copies of files - + - If the repository tree contains the complete results of a build, - and we try to build from the repository - without any files in our local tree, - something moderately surprising happens: + If the repository tree contains the complete results of a build, + and we try to build from the repository + without any files in our local tree, + something moderately surprising happens: - + - - % mkdir $HOME/build2 - % cd $HOME/build2 - % scons -Y /usr/all/repository hello - scons: `hello' is up-to-date. - + + % mkdir $HOME/build2 + % cd $HOME/build2 + % scons -Y /usr/all/repository hello + scons: `hello' is up-to-date. + - + - Why does &SCons; say that the &hello; program - is up-to-date when there is no &hello; program - in the local build directory? - Because the repository (not the local directory) - contains the up-to-date &hello; program, - and &SCons; correctly determines that nothing - needs to be done to rebuild that - up-to-date copy of the file. + Why does &SCons; say that the &hello; program + is up-to-date when there is no &hello; program + in the local build directory? + Because the repository (not the local directory) + contains the up-to-date &hello; program, + and &SCons; correctly determines that nothing + needs to be done to rebuild that + up-to-date copy of the file. - - - + + + - There are, however, many times when you want to ensure that a - local copy of a file always exists. - A packaging or testing script, for example, - may assume that certain generated files exist locally. - To tell &SCons; to make a copy of any up-to-date repository - file in the local build directory, - use the &Local; function: + There are, however, many times when you want to ensure that a + local copy of a file always exists. + A packaging or testing script, for example, + may assume that certain generated files exist locally. + To tell &SCons; to make a copy of any up-to-date repository + file in the local build directory, + use the &Local; function: - + - - env = Environment() - hello = env.Program('hello.c') - Local(hello) - + + env = Environment() + hello = env.Program('hello.c') + Local(hello) + - + - If we then run the same command, - &SCons; will make a local copy of the program - from the repository copy, - and tell you that it is doing so: + If we then run the same command, + &SCons; will make a local copy of the program + from the repository copy, + and tell you that it is doing so: - + - - % cons -R /usr/all/repository hello - Local copy of hello from /usr/all/repository/hello - scons: `hello' is up-to-date. - XXXXXX DO WE REALLY REPORT up-to-date, TOO? - + + % scons -Y /usr/all/repository hello + Local copy of hello from /usr/all/repository/hello + scons: `hello' is up-to-date. + XXXXXX DO WE REALLY REPORT up-to-date, TOO? + - + - (Notice that, because the act of making the local copy - is not considered a "build" of the &hello; file, - &SCons; still reports that it is up-to-date.) - XXXXXX DO WE REALLY REPORT up-to-date, TOO? + (Notice that, because the act of making the local copy + is not considered a "build" of the &hello; file, + &SCons; still reports that it is up-to-date.) + XXXXXX DO WE REALLY REPORT up-to-date, TOO? - + -
+
diff --git a/doc/user/separate.sgml b/doc/user/separate.sgml index e1c0e49b..9050eb7f 100644 --- a/doc/user/separate.sgml +++ b/doc/user/separate.sgml @@ -112,12 +112,178 @@ program using the F path name. - X + 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.
- X + The &BuildDir; Function + + + + X + + + + + BuildDir('build', 'src') + env = Environment() + env.Program('build/hello.c') + + + + + 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 + + +
+ +
+ Avoiding Duplicate Source Files in the Build Directory + + + + X + + + + + BuildDir('build', 'src', duplicate=0) + env = Environment() + env.Program('build/hello.c') + + + + + X + + + + + % 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 + + + + + X + + + +
+ +
+ Why &SCons; Duplicates Source Files by Default + + + + X + + + + + env = Environmnet() + + + + + X + + + + + % scons + cc -c build/hello.c -o build/hello.o + cc -o build/hello build/hello.o + + +
+ +
+ Using &BuildDir; With an &SConscript; File + + + + X + + + + + env = Environment() + env.Program('hello.c') + + + + + X + + + + + BuildDir('build', 'src') + SConscript('build/SConscript') + + + + + X + + + + + % 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 + + +
+ +
+ Specifying a Build Directory as Part of an &SConscript; Call + + + + X + + + + + SConscript('src/SConscript', build_dir='build') + @@ -125,4 +291,45 @@ program using the F path name. + + % 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 + + + + + X + + + + + SConscript('src/SConscript', build_dir='build', duplicate=0) + + + + + X + + + + + % 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 + +
diff --git a/doc/user/simple.sgml b/doc/user/simple.sgml index 8cafe2d8..a86fd344 100644 --- a/doc/user/simple.sgml +++ b/doc/user/simple.sgml @@ -147,10 +147,10 @@ requirements of a build. 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 extremely easy to learn, + Python is very easy to learn, and this User's Guide will introduce you step-by-step to the relatively small amount of Python you'll - neede to know to be able to use &SCons; effectively. + need to know to be able to use &SCons; effectively.
@@ -254,7 +254,7 @@ requirements of a build. - One minor drawback to the use of a Python list + 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). diff --git a/doc/user/sourcecode.sgml b/doc/user/sourcecode.sgml new file mode 100644 index 00000000..4ee49d44 --- /dev/null +++ b/doc/user/sourcecode.sgml @@ -0,0 +1,144 @@ + + + + + + + X + + + +
+ Fetching Source Code From BitKeeper + + + + X + + + + + env = Environment() + env.SourceCode('.', env.BitKeeper('XXX') + env.Program('hello.c') + + + + % scons + XXX + + +
+ +
+ Fetching Source Code From CVS + + + + X + + + + + env = Environment() + env.SourceCode('.', env.CVS('XXX') + env.Program('hello.c') + + + + % scons + XXX + + +
+ +
+ Fetching Source Code From RCS + + + + X + + + + + env = Environment() + env.SourceCode('.', env.RCS() + env.Program('hello.c') + + + + % scons + XXX + + +
+ +
+ Fetching Source Code From SCCS + + + + X + + + + + env = Environment() + env.SourceCode('.', env.SCCS() + env.Program('hello.c') + + + + % scons + XXX + + +
+ +
+ Fetching Source Code From Subversion + + + + X + + + + + env = Environment() + env.SourceCode('.', env.Subversion('XXX') + env.Program('hello.c') + + + + % scons + XXX + + +
diff --git a/doc/user/variants.sgml b/doc/user/variants.sgml index fdd209ee..6ad93609 100644 --- a/doc/user/variants.sgml +++ b/doc/user/variants.sgml @@ -122,4 +122,25 @@ is pretty smart about rebuilding things when you change options.
+ + 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 + +