diff options
Diffstat (limited to 'doc/user/repositories.in')
-rw-r--r-- | doc/user/repositories.in | 641 |
1 files changed, 0 insertions, 641 deletions
diff --git a/doc/user/repositories.in b/doc/user/repositories.in deleted file mode 100644 index 28d1233..0000000 --- a/doc/user/repositories.in +++ /dev/null @@ -1,641 +0,0 @@ -<!-- - - Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 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. - ---> - - <para> - - 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. - - </para> - - <section> - <title>The &Repository; Method</title> - - <!-- - - The repository directories specified may contain source files, derived files - (objects, libraries and executables), or both. If there is no local file - (source or derived) under the directory in which Cons is executed, then the - first copy of a same-named file found under a repository directory will be - used to build any local derived files. - - --> - - <para> - - 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: - - </para> - - <scons_example name="ex1"> - <file name="SConstruct" printme="1"> - env = Environment() - env.Program('hello.c') - Repository('__ROOT__/usr/repository1', '__ROOT__/usr/repository2') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - 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. - - </para> - - </section> - - <section> - <title>Finding source files in repositories</title> - - <para> - - The above example - specifies that &SCons; - will first search for files under - the <filename>/usr/repository1</filename> tree - and next under the <filename>/usr/repository2</filename> tree. - &SCons; expects that any files it searches - for will be found in the same position - relative to the top-level directory. - In the above example, if the &hello_c; file is not - found in the local build tree, - &SCons; will search first for - a <filename>/usr/repository1/hello.c</filename> file - and then for a <filename>/usr/repository2/hello.c</filename> file - to use in its place. - - </para> - - <para> - - 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: - - </para> - - <scons_output example="ex1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - If, however, there is no local &hello_c; file, - but one exists in <filename>/usr/repository1</filename>, - &SCons; will recompile the &hello; program - from the source file it finds in the repository: - - </para> - - <scons_example name="ex2"> - <file name="SConstruct"> - env = Environment() - env.Program('hello.c') - Repository('__ROOT__/usr/repository1', '__ROOT__/usr/repository2') - </file> - <file name="__ROOT__/usr/repository1/hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <scons_output example="ex2"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - And similarly, if there is no local &hello_c; file - and no <filename>/usr/repository1/hello.c</filename>, - but one exists in <filename>/usr/repository2</filename>: - - </para> - - <scons_example name="ex3"> - <file name="SConstruct"> - env = Environment() - env.Program('hello.c') - Repository('__ROOT__/usr/repository1', '__ROOT__/usr/repository2') - </file> - <file name="__ROOT__/usr/repository2/hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <scons_output example="ex3"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - </para> - - </section> - - <section> - <title>Finding <literal>#include</literal> files in repositories</title> - - <para> - - We've already seen that SCons will scan the contents of - a source file for <literal>#include</literal> file names - and realize that targets built from that source file - also depend on the <literal>#include</literal> file(s). - For each directory in the &cv-link-CPPPATH; list, - &SCons; will actually search the corresponding directories - in any repository trees and establish the - correct dependencies on any - <literal>#include</literal> files that it finds - in repository directory. - - </para> - - <para> - - Unless the C compiler also knows about these directories - in the repository trees, though, - it will be unable to find the <literal>#include</literal> files. - If, for example, the &hello_c; file in - our previous example includes the &hello_h; - in its current directory, - and the &hello_h; only exists in the repository: - - </para> - - <screen> - % <userinput>scons -Q</userinput> - cc -o hello.o -c hello.c - hello.c:1: hello.h: No such file or directory - </screen> - - <para> - - In order to inform the C compiler about the repositories, - &SCons; will add appropriate - <literal>-I</literal> flags to the compilation commands - for each directory in the &cv-CPPPATH; list. - So if we add the current directory to the - construction environment &cv-CPPPATH; like so: - - </para> - - <scons_example name="CPPPATH"> - <file name="SConstruct" printme="1"> - env = Environment(CPPPATH = ['.']) - env.Program('hello.c') - Repository('__ROOT__/usr/repository1') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - Then re-executing &SCons; yields: - - </para> - - <scons_output example="CPPPATH"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - The order of the <literal>-I</literal> options replicates, - for the C preprocessor, - the same repository-directory search path - that &SCons; uses for its own dependency analysis. - If there are multiple repositories and multiple &cv-CPPPATH; - directories, &SCons; will add the repository directories - to the beginning of each &cv-CPPPATH; directory, - rapidly multiplying the number of <literal>-I</literal> flags. - If, for example, the &cv-CPPPATH; contains three directories - (and shorter repository path names!): - - </para> - - <scons_example name="CPPPATH3"> - <file name="SConstruct" printme="1"> - env = Environment(CPPPATH = ['dir1', 'dir2', 'dir3']) - env.Program('hello.c') - Repository('__ROOT__/r1', '__ROOT__/r2') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - Then we'll end up with nine <literal>-I</literal> options - on the command line, - three (for each of the &cv-CPPPATH; directories) - times three (for the local directory plus the two repositories): - - </para> - - <scons_output example="CPPPATH3"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - -<!-- - -Cons classic did the following, does SCons? - -In order to shorten the command lines as much as possible, Cons will -remove C<-I> flags for any directories, locally or in the repositories, -which do not actually exist. (Note that the C<-I> flags are not included -in the MD5 signature calculation for the target file, so the target will -not be recompiled if the compilation command changes due to a directory -coming into existence.) - ---> - - <section> - <title>Limitations on <literal>#include</literal> files in repositories</title> - - <para> - - &SCons; relies on the C compiler's - <literal>-I</literal> options to control the order in which - the preprocessor will search the repository directories - for <literal>#include</literal> files. - This causes a problem, however, with how the C preprocessor - handles <literal>#include</literal> lines with - the file name included in double-quotes. - - </para> - - <para> - - As we've seen, - &SCons; will compile the &hello_c; file from - the repository if it doesn't exist in - the local directory. - If, however, the &hello_c; file in the repository contains - a <literal>#include</literal> line with the file name in - double quotes: - - </para> - - <programlisting> - #include "hello.h" - int - main(int argc, char *argv[]) - { - printf(HELLO_MESSAGE); - return (0); - } - </programlisting> - - <para> - - Then the C preprocessor will <emphasis>always</emphasis> - use a &hello_h; file from the repository directory first, - even if there is a &hello_h; file in the local directory, - despite the fact that the command line specifies - <literal>-I</literal> as the first option: - - </para> - - <scons_example name="quote1"> - <file name="SConstruct"> - env = Environment(CPPPATH = ['.']) - env.Program('hello.c') - Repository('__ROOT__/usr/repository1') - </file> - <file name="__ROOT__/usr/repository1/hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <scons_output example="quote1"> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - This behavior of the C preprocessor--always search - for a <literal>#include</literal> file in double-quotes - first in the same directory as the source file, - and only then search the <literal>-I</literal>--can - not, in general, be changed. - In other words, it's a limitation - that must be lived with if you want to use - code repositories in this way. - There are three ways you can possibly - work around this C preprocessor behavior: - - </para> - - <orderedlist> - - <listitem> - <para> - - Some modern versions of C compilers do have an option - to disable or control this behavior. - If so, add that option to &cv-link-CFLAGS; - (or &cv-link-CXXFLAGS; or both) in your construction environment(s). - Make sure the option is used for all construction - environments that use C preprocessing! - - </para> - </listitem> - - <listitem> - <para> - - Change all occurrences of <literal>#include "file.h"</literal> - to <literal>#include &lt;file.h&gt;</literal>. - Use of <literal>#include</literal> with angle brackets - does not have the same behavior--the <literal>-I</literal> - directories are searched first - for <literal>#include</literal> files--which - gives &SCons; direct control over the list of - directories the C preprocessor will search. - - </para> - </listitem> - - <listitem> - <para> - - Require that everyone working with compilation from - repositories check out and work on entire directories of files, - not individual files. - (If you use local wrapper scripts around - your source code control system's command, - you could add logic to enforce this restriction there. - - </para> - </listitem> - - </orderedlist> - - </section> - - </section> - - <section> - <title>Finding the &SConstruct; file in repositories</title> - - <para> - - &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 <literal>-Y</literal> option: - - </para> - - <screen> - % <userinput>scons -Q -Y /usr/repository1 -Y /usr/repository2</userinput> - </screen> - - <para> - - 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. - - </para> - - </section> - - <section> - <title>Finding derived files in repositories</title> - - <para> - - 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. - - </para> - - <para> - - 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 run &SCons; in a separate build directory - and copy the resulting tree to the desired repository: - - </para> - - <scons_example name="ex4"> - <file name="SConstruct"> - env = Environment() - env.Program(['hello.c', 'file1.c', 'file2.c']) - Repository('/usr/repository1', '/usr/repository2') - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - <file name="file1.c"> - int f1() { printf("file1\n"); } - </file> - <file name="file2.c"> - int f2() { printf("file2.c\n"); } - </file> - </scons_example> - - <scons_output example="ex4"> - <scons_output_command>cd /usr/repository1</scons_output_command> - <scons_output_command>scons -Q</scons_output_command> - </scons_output> - - <para> - - (Note that this is safe even if the &SConstruct; file - lists <filename>/usr/repository1</filename> as a repository, - because &SCons; will remove the current build directory - from its repository list for that invocation.) - - </para> - - <para> - - 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 <literal>-Y</literal> option to - tell &SCons; to fetch any other files it needs - from the repository: - - </para> - - <!-- - <scons_output example="ex4"> - <scons_output_command>cd $HOME/build</scons_output_command> - <scons_output_command>edit hello.c</scons_output_command> - <scons_output_command>scons -Q -Y __ROOT__/usr/repository1</scons_output_command> - </scons_output> - --> - <screen> - % <userinput>cd $HOME/build</userinput> - % <userinput>edit hello.c</userinput> - % <userinput>scons -Q -Y /usr/repository1</userinput> - cc -c -o hello.o hello.c - cc -o hello hello.o /usr/repository1/file1.o /usr/repository1/file2.o - </screen> - - <para> - - Notice that &SCons; realizes that it does not need to - rebuild local copies <filename>file1.o</filename> and <filename>file2.o</filename> files, - but instead uses the already-compiled files - from the repository. - - </para> - - </section> - - <section> - <title>Guaranteeing local copies of files</title> - - <para> - - 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: - - </para> - - <screen> - % <userinput>mkdir $HOME/build2</userinput> - % <userinput>cd $HOME/build2</userinput> - % <userinput>scons -Q -Y /usr/all/repository hello</userinput> - scons: `hello' is up-to-date. - </screen> - - <para> - - 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. - - </para> - - <para> - - 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: - - </para> - - <scons_example name="ex5"> - <file name="SConstruct" printme="1"> - env = Environment() - hello = env.Program('hello.c') - Local(hello) - </file> - <file name="hello.c"> - int main() { printf("Hello, world!\n"); } - </file> - </scons_example> - - <para> - - 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: - - </para> - - <screen> - % <userinput>scons -Y /usr/all/repository hello</userinput> - Local copy of hello from /usr/all/repository/hello - scons: `hello' is up-to-date. - </screen> - - <para> - - (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.) - - </para> - - </section> |