diff options
Diffstat (limited to 'doc/user/nodes.xml')
| -rw-r--r-- | doc/user/nodes.xml | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/doc/user/nodes.xml b/doc/user/nodes.xml new file mode 100644 index 0000000..ff6ee66 --- /dev/null +++ b/doc/user/nodes.xml @@ -0,0 +1,454 @@ +<?xml version='1.0'?> +<!DOCTYPE sconsdoc [ + <!ENTITY % scons SYSTEM "../scons.mod"> + %scons; + + <!ENTITY % builders-mod SYSTEM "../generated/builders.mod"> + %builders-mod; + <!ENTITY % functions-mod SYSTEM "../generated/functions.mod"> + %functions-mod; + <!ENTITY % tools-mod SYSTEM "../generated/tools.mod"> + %tools-mod; + <!ENTITY % variables-mod SYSTEM "../generated/variables.mod"> + %variables-mod; +]> + +<chapter id="chap-nodes" + xmlns="http://www.scons.org/dbxsd/v1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd"> +<title>Node Objects</title> + +<!-- + + Copyright (c) 2001 - 2014 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="nodes_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="nodes_ex1" os="posix" suffix="1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + And on Windows: + + </para> + + <scons_output example="nodes_ex1" os="win32" suffix="2"> + <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="nodes_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="nodes_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="nodes_print" os="posix" suffix="1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + And the following file names on a Windows system: + + </para> + + <scons_output example="nodes_print" os="win32" suffix="2"> + <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="nodes_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="nodes_exists" os="posix" suffix="1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + <section> + <title>&GetBuildPath;: Getting the Path From a &Node; or String</title> + + <para> + + <function>env.GetBuildPath(file_or_list)</function> + returns the path of a &Node; or a string representing a + path. It can also take a list of &Node;s and/or strings, and + returns the list of paths. If passed a single &Node;, the result + is the same as calling <literal>str(node)</literal> (see above). + The string(s) can have embedded construction variables, which are + expanded as usual, using the calling environment's set of + variables. The paths can be files or directories, and do not have + to exist. + + </para> + + <scons_example name="nodes_GetBuildPath"> + <file name="SConstruct" printme="1"> +env=Environment(VAR="value") +n=File("foo.c") +print env.GetBuildPath([n, "sub/dir/$VAR"]) + </file> + </scons_example> + + <para> + + Would print the following file names: + + </para> + + <scons_output example="nodes_GetBuildPath" os="posix" suffix="1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + <para> + + There is also a function version of &GetBuildPath; which can + be called without an &Environment;; that uses the default SCons + &Environment; to do substitution on any string arguments. + + </para> + + </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="nodes_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="nodes_read" os="posix" suffix="1"> + <scons_output_command>scons -Q</scons_output_command> + </scons_output> + + </section> + + --> + + <!-- + + <section> + <title>Python Value &Node;</title> + + <para> + + XXX Value() + + </para> + + </section> + + --> + +</chapter> |
