diff options
Diffstat (limited to 'doc/user/separate.xml')
-rw-r--r-- | doc/user/separate.xml | 520 |
1 files changed, 520 insertions, 0 deletions
diff --git a/doc/user/separate.xml b/doc/user/separate.xml new file mode 100644 index 0000000..fd5bdf0 --- /dev/null +++ b/doc/user/separate.xml @@ -0,0 +1,520 @@ +<!-- + + Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons Foundation + + 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. + In &SCons;, this is usually done by creating one or more separate + <emphasis>variant directory trees</emphasis> + that are used to hold the built objects files, libraries, + and executable programs, etc. + for a specific flavor, or variant, 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 &VariantDir; function. + + </para> + + <para> + + One historical note: the &VariantDir; function + used to be called &BuildDir;. + That name is still supported + but has been deprecated + because the &SCons; functionality + differs from the model of a "build directory" + implemented by other build systems like the GNU Autotools. + + </para> + + <section> + <title>Specifying a Variant Directory Tree as Part of an &SConscript; Call</title> + + <para> + + The most straightforward way to establish a variant directory tree + uses the fact that the usual way to + set up a build hierarchy is to have an + &SConscript; file in the source subdirectory. + If you then pass a &variant_dir; argument to the + &SConscript; function call: + + </para> + + <programlisting> + SConscript('src/SConscript', variant_dir='build') + </programlisting> + + <para> + + &SCons; will then build all of the files in + the &build; subdirectory: + + </para> + + <screen> + % <userinput>ls src</userinput> + SConscript hello.c + % <userinput>scons -Q</userinput> + cc -o build/hello.o -c build/hello.c + cc -o build/hello build/hello.o + % <userinput>ls build</userinput> + SConscript hello hello.c hello.o + </screen> + + <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 Variant Directory Tree</title> + + <para> + + &SCons; duplicates source files in variant directory trees + because it's the most straightforward way to guarantee a correct build + <emphasis>regardless of include-file directory paths, + relative references between files, + or tool support for putting files in different locations</emphasis>, + and the &SCons; philosophy is to, by default, + guarantee a correct build in all cases. + + </para> + + <para> + + The most direct reason to duplicate source files + in variant directories + is simply that some tools (mostly older versions) + are written to only build their output files + in the same directory as the source files. + In this case, the choices are either + to build the output file in the source directory + and move it to the variant directory, + or to duplicate the source files in the variant directory. + + </para> + + <para> + + Additionally, + relative references between files + can cause problems if we don't + just duplicate the hierarchy of source files + in the variant directory. + You can see this at work in + use of the C preprocessor <literal>#include</literal> + mechanism with double quotes, not angle brackets: + + </para> + + <programlisting> + #include "file.h" + </programlisting> + + <para> + + The <emphasis>de facto</emphasis> standard behavior + for most C compilers in this case + is to first look in the same directory + as the source file that contains the <literal>#include</literal> line, + then to look in the directories in the preprocessor search path. + Add to this that the &SCons; implementation of + support for code repositories + (described below) + means not all of the files + will be found in the same directory hierarchy, + and the simplest way to make sure + that the right include file is found + is to duplicate the source files into the variant directory, + which provides a correct build + regardless of the original location(s) of the source files. + + </para> + + <para> + + Although source-file duplication guarantees a correct build + even in these end-cases, + it <emphasis>can</emphasis> usually be safely disabled. + The next section describes + how you can disable the duplication of source files + in the variant directory. + + </para> + + </section> + + <section> + <title>Telling &SCons; to Not Duplicate Source Files in the Variant Directory Tree</title> + + <para> + + In most cases and with most tool sets, + &SCons; can place its target files in a build subdirectory + <emphasis>without</emphasis> + duplicating the source files + and everything will work just fine. + You can disable the default &SCons; behavior + by specifying <literal>duplicate=0</literal> + when you call the &SConscript; function: + + </para> + + <programlisting> + SConscript('src/SConscript', variant_dir='build', duplicate=0) + </programlisting> + + <para> + + When this flag is specified, + &SCons; uses the variant directory + like most people expect--that is, + the output files are placed in the variant directory + while the source files stay in the source directory: + + </para> + + <screen> + % <userinput>ls src</userinput> + SConscript + hello.c + % <userinput>scons -Q</userinput> + cc -c src/hello.c -o build/hello.o + cc -o build/hello build/hello.o + % <userinput>ls build</userinput> + hello + hello.o + </screen> + + </section> + + <section> + <title>The &VariantDir; Function</title> + + <para> + + Use the &VariantDir; function to establish that target + files should be built in a separate directory + from the source files: + + </para> + + <programlisting> + VariantDir('build', 'src') + env = Environment() + env.Program('build/hello.c') + </programlisting> + + <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> + + When using the &VariantDir; function directly, + &SCons; still duplicates the source files + in the variant directory by default: + + </para> + + <screen> + % <userinput>ls src</userinput> + hello.c + % <userinput>scons -Q</userinput> + cc -o build/hello.o -c build/hello.c + cc -o build/hello build/hello.o + % <userinput>ls build</userinput> + hello hello.c hello.o + </screen> + + <para> + + You can specify the same <literal>duplicate=0</literal> argument + that you can specify for an &SConscript; call: + + </para> + + <programlisting> + VariantDir('build', 'src', duplicate=0) + env = Environment() + env.Program('build/hello.c') + </programlisting> + + <para> + + In which case &SCons; + will disable duplication of the source files: + + </para> + + <screen> + % <userinput>ls src</userinput> + hello.c + % <userinput>scons -Q</userinput> + cc -o build/hello.o -c src/hello.c + cc -o build/hello build/hello.o + % <userinput>ls build</userinput> + hello hello.o + </screen> + + </section> + + <section> + <title>Using &VariantDir; With an &SConscript; File</title> + + <para> + + Even when using the &VariantDir; 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> + + <programlisting> + env = Environment() + env.Program('hello.c') + </programlisting> + + <para> + + Then our &SConstruct; file could look like: + + </para> + + + <programlisting> + VariantDir('build', 'src') + SConscript('build/SConscript') + </programlisting> + + <para> + + Yielding the following output: + + </para> + + <screen> + % <userinput>ls src</userinput> + SConscript hello.c + % <userinput>scons -Q</userinput> + cc -o build/hello.o -c build/hello.c + cc -o build/hello build/hello.o + % <userinput>ls build</userinput> + SConscript hello hello.c hello.o + </screen> + + <para> + + Notice that this is completely equivalent + to the use of &SConscript; that we + learned about in the previous section. + + </para> + + </section> + + <section> + <title>Using &Glob; with &VariantDir;</title> + + <para> + + The &Glob; file name pattern matching function + works just as usual when using &VariantDir;. + For example, if the + <filename>src/SConscript</filename> + looks like this: + + </para> + + <programlisting> + env = Environment() + env.Program('hello', Glob('*.c')) + </programlisting> + + <para> + + Then with the same &SConstruct; file as in the previous section, + and source files <filename>f1.c</filename> + and <filename>f2.c</filename> in src, + we would see the following output: + + </para> + + <screen> + % <userinput>ls src</userinput> + SConscript f1.c f2.c f2.h + % <userinput>scons -Q</userinput> + cc -o build/f1.o -c build/f1.c + cc -o build/f2.o -c build/f2.c + cc -o build/hello build/f1.o build/f2.o + % <userinput>ls build</userinput> + SConscript f1.c f1.o f2.c f2.h f2.o hello + </screen> + + <para> + + The &Glob; function returns Nodes in the + <filename>build/</filename> tree, as you'd expect. + + </para> + + </section> + + <!-- + + <section> + <title>Why You'd Want to Call &VariantDir; Instead of &SConscript;</title> + + <para> + + XXX why call VariantDir() instead of SConscript(variant_dir=) + + </para> + + </section> + + --> |