4 SPDX-FileCopyrightText: Copyright The SCons Foundation (https://scons.org)
5 SPDX-License-Identifier: MIT
6 SPDX-FileType: DOCUMENTATION
8 This file is processed by the bin/SConsDoc.py module.
12 <!ENTITY % scons SYSTEM "../scons.mod">
15 <!ENTITY % builders-mod SYSTEM "../generated/builders.mod">
17 <!ENTITY % functions-mod SYSTEM "../generated/functions.mod">
19 <!ENTITY % tools-mod SYSTEM "../generated/tools.mod">
21 <!ENTITY % variables-mod SYSTEM "../generated/variables.mod">
25 <chapter id="chap-nodes"
26 xmlns="http://www.scons.org/dbxsd/v1.0"
27 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
28 xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">
29 <title>Node Objects</title>
33 Internally, &SCons; represents all of the files
34 and directories it knows about as &Nodes;.
35 These internal objects
36 (not object <emphasis>files</emphasis>)
37 can be used in a variety of ways
38 to make your &SConscript;
39 files portable and easy to read.
44 <title>Builder Methods Return Lists of Target Nodes</title>
48 All builder methods return a list of
49 &Node; objects that identify the
50 target file or files that will be built.
51 These returned &Nodes; can be passed
52 as arguments to other builder methods.
58 For example, suppose that we want to build
59 the two object files that make up a program with different options.
60 This would mean calling the &b-link-Object;
61 builder once for each object file,
62 specifying the desired options:
67 Object('hello.c', CCFLAGS='-DHELLO')
68 Object('goodbye.c', CCFLAGS='-DGOODBYE')
73 One way to combine these object files
74 into the resulting program
75 would be to call the &b-link-Program;
76 builder with the names of the object files
82 Object('hello.c', CCFLAGS='-DHELLO')
83 Object('goodbye.c', CCFLAGS='-DGOODBYE')
84 Program(['hello.o', 'goodbye.o'])
89 The problem with specifying the names as strings
90 is that our &SConstruct; file is no longer portable
91 across operating systems.
92 It won't, for example, work on Windows
93 because the object files there would be
94 named &hello_obj; and &goodbye_obj;,
95 not &hello_o; and &goodbye_o;.
101 A better solution is to assign the lists of targets
102 returned by the calls to the &b-Object; builder to variables,
103 which we can then concatenate in our
104 call to the &b-Program; builder:
108 <scons_example name="nodes_ex1">
109 <file name="SConstruct" printme="1">
110 hello_list = Object('hello.c', CCFLAGS='-DHELLO')
111 goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE')
112 Program(hello_list + goodbye_list)
114 <file name="hello.c">
115 int main() { printf("Hello, world!\n"); }
117 <file name="goodbye.c">
118 int main() { printf("Goodbye, world!\n"); }
124 This makes our &SConstruct; file portable again,
125 the build output on Linux looking like:
129 <scons_output example="nodes_ex1" os="posix" suffix="1">
130 <scons_output_command>scons -Q</scons_output_command>
139 <scons_output example="nodes_ex1" os="win32" suffix="2">
140 <scons_output_command>scons -Q</scons_output_command>
145 We'll see examples of using the list of nodes
146 returned by builder methods throughout
147 the rest of this guide.
154 <title>Explicitly Creating File and Directory Nodes</title>
158 It's worth mentioning here that
159 &SCons; maintains a clear distinction
160 between Nodes that represent files
161 and Nodes that represent directories.
162 &SCons; supports &File; and &Dir;
163 functions that, respectively,
164 return a file or directory Node:
168 <scons_example name="nodes_print">
169 <file name="SConstruct" printme="1">
170 hello_c = File('hello.c')
173 classes = Dir('classes')
180 Normally, you don't need to call
181 &File; or &Dir; directly,
182 because calling a builder method automatically
183 treats strings as the names of files or directories,
184 and translates them into
185 the Node objects for you.
186 The &File; and &Dir; functions can come in handy
187 in situations where you need to explicitly
188 instruct &SCons; about the type of Node being
189 passed to a builder or other function,
190 or unambiguously refer to a specific
191 file in a directory tree.
193 (For an example of when you might
194 need to use &File; or &Dir; to
195 prevent ambiguous interpretation of a string
196 naming a file or directory, see
197 <xref linkend="chap-hierarchy">.)
204 There are also times when you may need to
205 refer to an entry in a file system
206 without knowing in advance
207 whether it's a file or a directory.
208 For those situations,
209 &SCons; also supports an &Entry; function,
211 that can represent either a file or a directory.
216 xyzzy = Entry('xyzzy')
221 The returned <literal>xyzzy</literal> Node
222 will be turned into a file or directory Node
223 the first time it is used by a builder method
224 or other function that
225 requires one vs. the other.
232 <title>Printing &Node; File Names</title>
236 One of the most common things you can do
237 with a Node is use it to print the
238 file name that the node represents.
239 Keep in mind, though, that because the object
240 returned by a builder call
241 is a <emphasis>list</emphasis> of Nodes,
242 you must use Python subscripts
243 to fetch individual Nodes from the list.
244 For example, the following &SConstruct; file:
248 <scons_example name="nodes_print">
249 <file name="SConstruct" printme="1">
250 object_list = Object('hello.c')
251 program_list = Program(object_list)
252 print("The object file is: %s"%object_list[0])
253 print("The program file is: %s"%program_list[0])
255 <file name="hello.c">
256 int main() { printf("Hello, world!\n"); }
262 Would print the following file names on a POSIX system:
266 <scons_output example="nodes_print" os="posix" suffix="1">
267 <scons_output_command>scons -Q</scons_output_command>
272 And the following file names on a Windows system:
276 <scons_output example="nodes_print" os="win32" suffix="2">
277 <scons_output_command>scons -Q</scons_output_command>
282 Note that in the above example,
283 the <literal>object_list[0]</literal>
284 extracts an actual Node <emphasis>object</emphasis>
286 and the Python <function>print</function> function
287 converts the object to a string for printing.
294 <title>Using a &Node;'s File Name as a String</title>
298 Printing a &Node;'s name
299 as described in the previous section
300 works because the string representation of a &Node; object
301 is the name of the file.
302 If you want to do something other than
303 print the name of the file,
304 you can fetch it by using the built-in Python
306 For example, if you want to use the Python
307 <function>os.path.exists</function>
308 to figure out whether a file
309 exists while the &SConstruct; file
310 is being read and executed,
311 you can fetch the string as follows:
315 <scons_example name="nodes_exists">
316 <file name="SConstruct" printme="1">
318 program_list = Program('hello.c')
319 program_name = str(program_list[0])
320 if not os.path.exists(program_name):
321 print("%s does not exist!"%program_name)
323 <file name="hello.c">
324 int main() { printf("Hello, world!\n"); }
330 Which executes as follows on a POSIX system:
334 <scons_output example="nodes_exists" os="posix" suffix="1">
335 <scons_output_command>scons -Q</scons_output_command>
341 <title>&GetBuildPath;: Getting the Path From a &Node; or String</title>
345 <function>env.GetBuildPath(file_or_list)</function>
346 returns the path of a &Node; or a string representing a
347 path. It can also take a list of &Node;s and/or strings, and
348 returns the list of paths. If passed a single &Node;, the result
349 is the same as calling <literal>str(node)</literal> (see above).
350 The string(s) can have embedded construction variables, which are
351 expanded as usual, using the calling environment's set of
352 variables. The paths can be files or directories, and do not have
357 <scons_example name="nodes_GetBuildPath">
358 <file name="SConstruct" printme="1">
359 env=Environment(VAR="value")
361 print(env.GetBuildPath([n, "sub/dir/$VAR"]))
367 Would print the following file names:
371 <scons_output example="nodes_GetBuildPath" os="posix" suffix="1">
372 <scons_output_command>scons -Q</scons_output_command>
377 There is also a function version of &GetBuildPath; which can
378 be called without an &Environment;; that uses the default SCons
379 &Environment; to do substitution on any string arguments.
388 <title>Fetching the Contents of a &Node;</title>
392 XXX Describe using read() and readlines()
393 when we add that as a public interface.
397 <scons_example name="nodes_read">
398 <file name="SConstruct" printme="1">
399 hello_c = File('hello.c')
400 contents = hello_c.read()
401 print("contents are:")
404 <file name="hello.c">
405 int main() { printf("Hello, world!\n"); }
411 Which executes as follows on a POSIX system:
415 <scons_output example="nodes_read" os="posix" suffix="1">
416 <scons_output_command>scons -Q</scons_output_command>
426 <title>Python Value &Node;</title>