diff options
author | Steven Knight <knight@baldmt.com> | 2003-08-16 04:19:30 (GMT) |
---|---|---|
committer | Steven Knight <knight@baldmt.com> | 2003-08-16 04:19:30 (GMT) |
commit | 9d21228a092cc048be6e60053d0ed739eec5b629 (patch) | |
tree | d2447f2650bf7782e58826ad0c16364496722d1c /doc/user/separate.in | |
parent | 601839d06d9563854ce22a615d6670a7651cd858 (diff) | |
download | SCons-9d21228a092cc048be6e60053d0ed739eec5b629.zip SCons-9d21228a092cc048be6e60053d0ed739eec5b629.tar.gz SCons-9d21228a092cc048be6e60053d0ed739eec5b629.tar.bz2 |
Branch for User's Guide changes.
Diffstat (limited to 'doc/user/separate.in')
-rw-r--r-- | doc/user/separate.in | 429 |
1 files changed, 429 insertions, 0 deletions
diff --git a/doc/user/separate.in b/doc/user/separate.in new file mode 100644 index 0000000..c1b3c32 --- /dev/null +++ b/doc/user/separate.in @@ -0,0 +1,429 @@ +<!-- + + 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 + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY + KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE + WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--> + +<!-- + +=head1 Separating source and build trees + +It's often desirable to keep any derived files from the build completely +separate from the source files. This makes it much easier to keep track of +just what is a source file, and also makes it simpler to handle B<variant> +builds, especially if you want the variant builds to co-exist. + +=head2 Separating build and source directories using the Link command + +Cons provides a simple mechanism that handles all of these requirements. The +C<Link> command is invoked as in this example: + + Link 'build' => 'src'; + +The specified directories are ``linked'' to the specified source +directory. Let's suppose that you setup a source directory, F<src>, with the +sub-directories F<world> and F<hello> below it, as in the previous +example. You could then substitute for the original build lines the +following: + + Build qw( + build/world/Conscript + build/hello/Conscript + ); + +Notice that you treat the F<Conscript> file as if it existed in the build +directory. Now if you type the same command as before, you will get the +following results: + + % cons export + Install build/world/world.h as export/include/world.h + cc -Iexport/include -c build/hello/hello.c -o build/hello/hello.o + cc -Iexport/include -c build/world/world.c -o build/world/world.o + ar r build/world/libworld.a build/world/world.o + ar: creating build/world/libworld.a + ranlib build/world/libworld.a + Install build/world/libworld.a as export/lib/libworld.a + cc -o build/hello/hello build/hello/hello.o -Lexport/lib -lworld + Install build/hello/hello as export/bin/hello + +Again, Cons has taken care of the details for you. In particular, you will +notice that all the builds are done using source files and object files from +the build directory. For example, F<build/world/world.o> is compiled from +F<build/world/world.c>, and F<export/include/world.h> is installed from +F<build/world/world.h>. This is accomplished on most systems by the simple +expedient of ``hard'' linking the required files from each source directory +into the appropriate build directory. + +The links are maintained correctly by Cons, no matter what you do to the +source directory. If you modify a source file, your editor may do this ``in +place'' or it may rename it first and create a new file. In the latter case, +any hard link will be lost. Cons will detect this condition the next time +the source file is needed, and will relink it appropriately. + +You'll also notice, by the way, that B<no> changes were required to the +underlying F<Conscript> files. And we can go further, as we shall see in the +next section. + +=head2 Explicit references to the source directory + +When using the C<Link> command on some operating systems or with some +tool chains, it's sometimes useful to have a command actually use +the path name to the source directory, not the build directory. For +example, on systems that must copy, not "hard link," the F<src/> and +F<build/> copies of C<Linked> files, using the F<src/> path of a file +name might make an editor aware that a syntax error must be fixed in the +source directory, not the build directory. + +You can tell Cons that you want to use the "source path" for a file by +preceding the file name with a ``!'' (exclamation point). For example, +if we add a ``!'' to the beginning of a source file: + + Program $env "foo", "!foo.c"; # Notice initial ! on foo.c + +Cons will compile the target as follows: + + cc -c src/foo.c -o build/foo.o + cc -o build/foo build/foo.o + +Notice that Cons has compiled the program from the the F<src/foo.c> +source file. Without the initial ``!'', Cons would have compiled the +program using the F<build/foo.c> path name. + +--> + + <para> + + 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 + <emphasis>build directories</emphasis> + 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. + + </para> + + <section> + <title>Specifying a Build Directory as Part of an &SConscript; Call</title> + + <para> + + 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: + + </para> + + <sconstruct> + SConscript('src/SConscript', build_dir='build') + </sconstruct> + + <para> + + &SCons; will then build all of the files in + the &build; subdirectory: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Program('hello.c') + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <scons_output example="ex1"> + <command>ls -1 src</command> + <command>scons</command> + <command>ls -1 build</command> + </scons_output> + + <para> + + But wait a minute--what's going on here? + &SCons; created the object file + <filename>build/hello.o</filename> + in the &build; subdirectory, + as expected. + But even though our &hello_c; file lives in the &src; subdirectory, + &SCons; has actually compiled a + <filename>build/hello.c</filename> file + to create the object file. + + </para> + + <para> + + What's happened is that &SCons; has <emphasis>duplicated</emphasis> + 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. + + </para> + + </section> + + <section> + <title>Why &SCons; Duplicates Source Files in a Build Directory</title> + + <para> + + &SCons; duplicates source files in build directories + because it's the most straightforward way to guarantee a correct build + <emphasis>regardless of include-file directory paths</emphasis>, + 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: + + </para> + + <para> + + XXX + + </para> + + <sconstruct> + env = Environmnet() + </sconstruct> + + <para> + + XXX + + </para> + + <literallayout> + % <userinput>scons</userinput> + cc -c build/hello.c -o build/hello.o + cc -o build/hello build/hello.o + </literallayout> + + </section> + + <section> + <title>Telling &SCons; to Not Duplicate Source Files in the Build Directory</title> + + <para> + + In most cases, however, + having &SCons; place its target files in a build subdirectory + <emphasis>without</emphasis> + duplicating the source files works just fine. + You can disable the default &SCons; behavior + by specifying <literal>duplicate=0</literal> + when you call the &SConscript; function: + + </para> + + <sconstruct> + SConscript('src/SConscript', build_dir='build', duplicate=0) + </sconstruct> + + <para> + + 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: + + </para> + + <literallayout> + % <userinput>ls -1 src</userinput> + SConscript + hello.c + % <userinput>scons</userinput> + cc -c src/hello.c -o build/hello.o + cc -o build/hello build/hello.o + % <userinput>ls -1 build</userinput> + hello + hello.o + </literallayout> + + </section> + + <section> + <title>The &BuildDir; Function</title> + + <para> + + Use the &BuildDir; function to establish that target + files should be built in a separate directory + from the source files: + + </para> + + <scons_example name="ex_builddir"> + <file name="SConstruct" printme="1"> + BuildDir('build', 'src') + env = Environment() + env.Program('build/hello.c') + </file> + <file name="src/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + 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 <filename>build/hello.c</filename> + file that &SCons; will duplicate in the + &build; subdirectory. + + </para> + + <para> + + XXX + + </para> + + <para> + + When using the &BuildDir; function directly, + &SCons; still duplicates the source files + in the build directory by default: + + </para> + + <scons_output example="ex_builddir"> + <command>ls src</command> + <command>scons</command> + <command>ls -1 build</command> + </scons_output> + + <para> + + You can specify the same <literal>duplicate=0</literal> argument + that you can specify for an &SConscript; call: + + </para> + + <scons_example name="ex_duplicate_0"> + <file name="SConstruct" printme="1"> + BuildDir('build', 'src', duplicate=0) + env = Environment() + env.Program('build/hello.c') + </file> + <file name="src/hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + In which case &SCons; + will disable duplication of the source files: + + </para> + + <scons_output example="ex_duplicate_0"> + <command>ls src</command> + <command>scons</command> + <command>ls -1 build</command> + </scons_output> + + </section> + + <section> + <title>Using &BuildDir; With an &SConscript; File</title> + + <para> + + Even when using the &BuildDir; function, + it's much more natural to use it with + a subsidiary &SConscript; file. + For example, if the + <filename>src/SConscript</filename> + looks like this: + + </para> + + <scons_example name="example_builddir_sconscript"> + <file name="SConstruct" printme="1"> + env = Environment() + env.Program('hello.c') + </file> + <file name="SConscript"> + BuildDir('build', 'src') + SConscript('build/SConscript') + </scons_example> + + <para> + + Then our &SConscript; file could look like: + + </para> + + <scons_example_file example="example_builddir_sconscript" name="SConscript"> + </scons_example_file> + + <para> + + Yielding the following output: + + </para> + + <scons_output example="example_builddir_sconscript"> + <command>ls -1 src</command> + <command>scons</command> + <command>ls -1 build</command> + </scons_output> + + <para> + + Notice that this is completely equivalent + to the use of &SConscript; that we + learned about in the previous section. + + </para> + + </section> + + <section> + <title>Why You'd Want to Call &BuildDir; Instead of &SConscript;</title> + + <para> + + XXX + + </para> + + </section> |