<!--
- Copyright (c) 2001, 2002, 2003 Steven Knight
+ __COPYRIGHT__
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
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>
+ 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 of build.
+ 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 &BuildDir; function.
+ 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 Build Directory as Part of an &SConscript; Call</title>
+ <title>Specifying a Variant Directory Tree as Part of an &SConscript; Call</title>
<para>
- The most straightforward way to establish a build directory
+ The most straightforward way to establish a variant directory tree
uses the fact that the usual way to
- set up a build hierarcy is to have an
+ set up a build hierarchy is to have an
&SConscript; file in the source subdirectory.
- If you then pass a &build_dir; argument to the
+ If you then pass a &variant_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">
+ SConscript('src/SConscript', variant_dir='build')
+ </file>
+ <file name="src/SConscript">
env = Environment()
env.Program('hello.c')
</file>
- <file name="hello.c">
+ <file name="src/hello.c">
int main() { printf("Hello, world!\n"); }
</file>
</scons_example>
+ <para>
+
+ &SCons; will then build all of the files in
+ the &build; subdirectory:
+
+ </para>
+
<scons_output example="ex1">
- <command>ls -1 src</command>
- <command>scons</command>
- <command>ls -1 build</command>
+ <scons_output_command>ls src</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>ls build</scons_output_command>
</scons_output>
<para>
</section>
<section>
- <title>Why &SCons; Duplicates Source Files in a Build Directory</title>
+ <title>Why &SCons; Duplicates Source Files in a Variant Directory Tree</title>
<para>
- &SCons; duplicates source files in build directories
+ &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</emphasis>,
+ <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.
- 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
+ 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>
<sconstruct>
- env = Environmnet()
+ #include "file.h"
</sconstruct>
<para>
- XXX
+ 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>
- <literallayout>
- % <userinput>scons</userinput>
- cc -c build/hello.c -o build/hello.o
- cc -o build/hello build/hello.o
- </literallayout>
+ <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 Build Directory</title>
+ <title>Telling &SCons; to Not Duplicate Source Files in the Variant Directory Tree</title>
<para>
- In most cases, however,
- having &SCons; place its target files in a build subdirectory
+ 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 works just fine.
+ 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>
<sconstruct>
- SConscript('src/SConscript', build_dir='build', duplicate=0)
+ SConscript('src/SConscript', variant_dir='build', duplicate=0)
</sconstruct>
<para>
When this flag is specified,
- &SCons; uses the build directory
+ &SCons; uses the variant directory
like most people expect--that is,
- the output files are placed in the build directory
+ the output files are placed in the variant directory
while the source files stay in the source directory:
</para>
- <literallayout>
- % <userinput>ls -1 src</userinput>
+ <screen>
+ % <userinput>ls src</userinput>
SConscript
hello.c
- % <userinput>scons</userinput>
+ % <userinput>scons -Q</userinput>
cc -c src/hello.c -o build/hello.o
cc -o build/hello build/hello.o
- % <userinput>ls -1 build</userinput>
+ % <userinput>ls build</userinput>
hello
hello.o
- </literallayout>
+ </screen>
</section>
<section>
- <title>The &BuildDir; Function</title>
+ <title>The &VariantDir; Function</title>
<para>
- Use the &BuildDir; function to establish that target
+ Use the &VariantDir; function to establish that target
files should be built in a separate directory
from the source files:
<scons_example name="ex_builddir">
<file name="SConstruct" printme="1">
- BuildDir('build', 'src')
+ VariantDir('build', 'src')
env = Environment()
env.Program('build/hello.c')
</file>
<para>
- XXX
-
- </para>
-
- <para>
-
- When using the &BuildDir; function directly,
+ When using the &VariantDir; function directly,
&SCons; still duplicates the source files
- in the build directory by default:
+ in the variant directory by default:
</para>
<scons_output example="ex_builddir">
- <command>ls src</command>
- <command>scons</command>
- <command>ls -1 build</command>
+ <scons_output_command>ls src</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>ls build</scons_output_command>
</scons_output>
<para>
<scons_example name="ex_duplicate_0">
<file name="SConstruct" printme="1">
- BuildDir('build', 'src', duplicate=0)
+ VariantDir('build', 'src', duplicate=0)
env = Environment()
env.Program('build/hello.c')
</file>
</para>
<scons_output example="ex_duplicate_0">
- <command>ls src</command>
- <command>scons</command>
- <command>ls -1 build</command>
+ <scons_output_command>ls src</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>ls build</scons_output_command>
</scons_output>
</section>
<section>
- <title>Using &BuildDir; With an &SConscript; File</title>
+ <title>Using &VariantDir; With an &SConscript; File</title>
<para>
- Even when using the &BuildDir; function,
+ Even when using the &VariantDir; function,
it's much more natural to use it with
a subsidiary &SConscript; file.
For example, if the
</para>
<scons_example name="example_builddir_sconscript">
- <file name="SConstruct" printme="1">
+ <file name="SConstruct">
+ VariantDir('build', 'src')
+ SConscript('build/SConscript')
+ </file>
+ <file name="src/SConscript" printme="1">
env = Environment()
env.Program('hello.c')
</file>
- <file name="SConscript">
- BuildDir('build', 'src')
- SConscript('build/SConscript')
+ <file name="src/hello.c">
+ int main() { printf("Hello, world!\n"); }
+ </file>
</scons_example>
<para>
- Then our &SConscript; file could look like:
+ Then our &SConstruct; file could look like:
</para>
- <scons_example_file example="example_builddir_sconscript" name="SConscript">
+ <scons_example_file example="example_builddir_sconscript" name="SConstruct">
</scons_example_file>
<para>
</para>
<scons_output example="example_builddir_sconscript">
- <command>ls -1 src</command>
- <command>scons</command>
- <command>ls -1 build</command>
+ <scons_output_command>ls src</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>ls build</scons_output_command>
</scons_output>
<para>
</section>
<section>
- <title>Why You'd Want to Call &BuildDir; Instead of &SConscript;</title>
+ <title>Using &Glob; with &VariantDir;</title>
<para>
-
- XXX
+
+ 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>
+
+ <scons_example name="example_glob_builddir_sconscript">
+ <file name="SConstruct">
+ VariantDir('build', 'src')
+ SConscript('build/SConscript')
+ </file>
+ <file name="src/SConscript" printme="1">
+ env = Environment()
+ env.Program('hello', Glob('*.c'))
+ </file>
+ <file name="src/f1.c">
+ #include "f2.h"
+ int main() { printf(f2()); }
+ </file>
+ <file name="src/f2.c">
+ const char * f2() { return("Hello, world!\n"); }
+ </file>
+ <file name="src/f2.h">
+ const char * f2();
+ </file>
+ </scons_example>
+
+ <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>
+
+ <scons_output example="example_glob_builddir_sconscript">
+ <scons_output_command>ls src</scons_output_command>
+ <scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>ls build</scons_output_command>
+ </scons_output>
+
+ <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>
+
+ -->