diff options
Diffstat (limited to 'doc/user/nodes.in')
-rw-r--r-- | doc/user/nodes.in | 386 |
1 files changed, 386 insertions, 0 deletions
diff --git a/doc/user/nodes.in b/doc/user/nodes.in new file mode 100644 index 0000000..c914ce5 --- /dev/null +++ b/doc/user/nodes.in @@ -0,0 +1,386 @@ +<!-- + + 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. + +--> + + <para> + + Internally, &SCons; represents all of the files + and directories it knows about as &Nodes;. + These internal objects + (not object <emphasis>files</emphasis>) + can be used in a variety of ways + to make your &SConscript; + files portable and easy to read. + + </para> + + <section> + <title>Builder Methods Return Lists of Target Nodes</title> + + <para> + + All builder methods return a list of + &Node; objects that identify the + target file or files that will be built. + These returned &Nodes; can be passed + as arguments to other builder methods. + + </para> + + <para> + + For example, suppose that we want to build + the two object files that make up a program with different options. + This would mean calling the &b-link-Object; + builder once for each object file, + specifying the desired options: + + </para> + + <sconstruct> + Object('hello.c', CCFLAGS='-DHELLO') + Object('goodbye.c', CCFLAGS='-DGOODBYE') + </sconstruct> + + <para> + + One way to combine these object files + into the resulting program + would be to call the &b-link-Program; + builder with the names of the object files + listed as sources: + + </para> + + <sconstruct> + Object('hello.c', CCFLAGS='-DHELLO') + Object('goodbye.c', CCFLAGS='-DGOODBYE') + Program(['hello.o', 'goodbye.o']) + </sconstruct> + + <para> + + The problem with specifying the names as strings + is that our &SConstruct; file is no longer portable + across operating systems. + It won't, for example, work on Windows + because the object files there would be + named &hello_obj; and &goodbye_obj;, + not &hello_o; and &goodbye_o;. + + </para> + + <para> + + A better solution is to assign the lists of targets + returned by the calls to the &b-Object; builder to variables, + which we can then concatenate in our + call to the &b-Program; builder: + + </para> + + <scons_example name="ex1"> + <file name="SConstruct" printme="1"> + hello_list = Object('hello.c', CCFLAGS='-DHELLO') + goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE') + Program(hello_list + goodbye_list) + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + <file name="goodbye.c"> + int main() { printf("Goodbye, world!\n"); } + </file> + </scons_example> + + <para> + + This makes our &SConstruct; file portable again, + the build output on Linux looking like: + + </para> + + <scons_output example="ex1" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + And on Windows: + + </para> + + <scons_output example="ex1" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + We'll see examples of using the list of nodes + returned by builder methods throughout + the rest of this guide. + + </para> + + </section> + + <section> + <title>Explicitly Creating File and Directory Nodes</title> + + <para> + + It's worth mentioning here that + &SCons; maintains a clear distinction + between Nodes that represent files + and Nodes that represent directories. + &SCons; supports &File; and &Dir; + functions that, respectively, + return a file or directory Node: + + </para> + + <scons_example name="print"> + <file name="SConstruct" printme="1"> + hello_c = File('hello.c') + Program(hello_c) + + classes = Dir('classes') + Java(classes, 'src') + </file> + </scons_example> + + <para> + + Normally, you don't need to call + &File; or &Dir; directly, + because calling a builder method automatically + treats strings as the names of files or directories, + and translates them into + the Node objects for you. + The &File; and &Dir; functions can come in handy + in situations where you need to explicitly + instruct &SCons; about the type of Node being + passed to a builder or other function, + or unambiguously refer to a specific + file in a directory tree. + <!-- + (For an example of when you might + need to use &File; or &Dir; to + prevent ambiguous interpretation of a string + naming a file or directory, see + <xref linkend="chap-hierarchy">.) + --> + + </para> + + <para> + + There are also times when you may need to + refer to an entry in a file system + without knowing in advance + whether it's a file or a directory. + For those situations, + &SCons; also supports an &Entry; function, + which returns a Node + that can represent either a file or a directory. + + </para> + + <sconstruct> + xyzzy = Entry('xyzzy') + </sconstruct> + + <para> + + The returned <literal>xyzzy</literal> Node + will be turned into a file or directory Node + the first time it is used by a builder method + or other function that + requires one vs. the other. + + </para> + + </section> + + <section> + <title>Printing &Node; File Names</title> + + <para> + + One of the most common things you can do + with a Node is use it to print the + file name that the node represents. + Keep in mind, though, that because the object + returned by a builder call + is a <emphasis>list</emphasis> of Nodes, + you must use Python subscripts + to fetch individual Nodes from the list. + For example, the following &SConstruct; file: + + </para> + + <scons_example name="print"> + <file name="SConstruct" printme="1"> + object_list = Object('hello.c') + program_list = Program(object_list) + print "The object file is:", object_list[0] + print "The program file is:", program_list[0] + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Would print the following file names on a POSIX system: + + </para> + + <scons_output example="print" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + And the following file names on a Windows system: + + </para> + + <scons_output example="print" os="win32"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + Note that in the above example, + the <literal>object_list[0]</literal> + extracts an actual Node <emphasis>object</emphasis> + from the list, + and the Python <literal>print</literal> statement + converts the object to a string for printing. + + </para> + + </section> + + <section> + <title>Using a &Node;'s File Name as a String</title> + + <para> + + Printing a &Node;'s name + as described in the previous section + works because the string representation of a &Node; object + is the name of the file. + If you want to do something other than + print the name of the file, + you can fetch it by using the builtin Python + &str; function. + For example, if you want to use the Python + <function>os.path.exists</function> + to figure out whether a file + exists while the &SConstruct; file + is being read and executed, + you can fetch the string as follows: + + </para> + + <scons_example name="exists"> + <file name="SConstruct" printme="1"> + import os.path + program_list = Program('hello.c') + program_name = str(program_list[0]) + if not os.path.exists(program_name): + print program_name, "does not exist!" + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Which executes as follows on a POSIX system: + + </para> + + <scons_output example="exists" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <!-- + + <section> + <title>Fetching the Contents of a &Node;</title> + + <para> + + XXX Describe using read() and readlines() + when we add that as a public interface. + + </para> + + <scons_example name="read"> + <file name="SConstruct" printme="1"> + hello_c = File('hello.c') + contents = hello_c.read() + print "contents are:" + print contents + </file> + <file name="hello.c"> + int main() { printf("Hello, world!\n"); } + </file> + </scons_example> + + <para> + + Which executes as follows on a POSIX system: + + </para> + + <scons_output example="read" os="posix"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + --> + + <!-- + + <section> + <title>Python Value &Node;</title> + + <para> + + XXX Value() + + </para> + + </section> + + --> |