[ci skip] update generated files
[scons.git] / doc / user / nodes.xml
bloba652e79c79172be206641f460f7eb5d67dc9b56d
1 <?xml version='1.0'?>
3 <!--
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.
9 -->
11 <!DOCTYPE sconsdoc [
12     <!ENTITY % scons SYSTEM "../scons.mod">
13     %scons;
15     <!ENTITY % builders-mod SYSTEM "../generated/builders.mod">
16     %builders-mod;
17     <!ENTITY % functions-mod SYSTEM "../generated/functions.mod">
18     %functions-mod;
19     <!ENTITY % tools-mod SYSTEM "../generated/tools.mod">
20     %tools-mod;
21     <!ENTITY % variables-mod SYSTEM "../generated/variables.mod">
22     %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>
31 <para>
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.
41   </para>
43   <section>
44   <title>Builder Methods Return Lists of Target Nodes</title>
46     <para>
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.
54     </para>
56     <para>
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:
64     </para>
66     <sconstruct>
67 Object('hello.c', CCFLAGS='-DHELLO')
68 Object('goodbye.c', CCFLAGS='-DGOODBYE')
69     </sconstruct>
71     <para>
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
77     listed as sources:
79     </para>
81     <sconstruct>
82 Object('hello.c', CCFLAGS='-DHELLO')
83 Object('goodbye.c', CCFLAGS='-DGOODBYE')
84 Program(['hello.o', 'goodbye.o'])
85     </sconstruct>
87     <para>
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;.
97     </para>
99     <para>
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:
106     </para>
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)
113       </file>
114       <file name="hello.c">
115 int main() { printf("Hello, world!\n"); }
116       </file>
117       <file name="goodbye.c">
118 int main() { printf("Goodbye, world!\n"); }
119       </file>
120     </scons_example>
122     <para>
124     This makes our &SConstruct; file portable again,
125     the build output on Linux looking like:
127     </para>
129     <scons_output example="nodes_ex1" os="posix" suffix="1">
130        <scons_output_command>scons -Q</scons_output_command>
131     </scons_output>
133     <para>
135     And on Windows:
137     </para>
139     <scons_output example="nodes_ex1" os="win32" suffix="2">
140        <scons_output_command>scons -Q</scons_output_command>
141     </scons_output>
143     <para>
145     We'll see examples of using the list of nodes
146     returned by builder methods throughout
147     the rest of this guide.
149     </para>
151   </section>
153   <section>
154   <title>Explicitly Creating File and Directory Nodes</title>
156     <para>
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:
166     </para>
168     <scons_example name="nodes_print">
169       <file name="SConstruct" printme="1">
170 hello_c = File('hello.c')
171 Program(hello_c)
173 classes = Dir('classes')
174 Java(classes, 'src')
175       </file>
176     </scons_example>
178     <para>
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.
192     <!--
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">.)
198     -->
200     </para>
202     <para>
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,
210     which returns a Node
211     that can represent either a file or a directory.
213     </para>
215     <sconstruct>
216 xyzzy = Entry('xyzzy')
217     </sconstruct>
219     <para>
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.
227     </para>
229   </section>
231   <section>
232   <title>Printing &Node; File Names</title>
234     <para>
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:
246     </para>
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])
254       </file>
255       <file name="hello.c">
256 int main() { printf("Hello, world!\n"); }
257       </file>
258     </scons_example>
260     <para>
262     Would print the following file names on a POSIX system:
264     </para>
266     <scons_output example="nodes_print" os="posix" suffix="1">
267       <scons_output_command>scons -Q</scons_output_command>
268     </scons_output>
270     <para>
272     And the following file names on a Windows system:
274     </para>
276     <scons_output example="nodes_print" os="win32" suffix="2">
277       <scons_output_command>scons -Q</scons_output_command>
278     </scons_output>
280     <para>
282     Note that in the above example,
283     the <literal>object_list[0]</literal>
284     extracts an actual Node <emphasis>object</emphasis>
285     from the list,
286     and the Python <function>print</function> function
287     converts the object to a string for printing.
289     </para>
291   </section>
293   <section>
294   <title>Using a &Node;'s File Name as a String</title>
296     <para>
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
305     &str; function.
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:
313     </para>
315     <scons_example name="nodes_exists">
316       <file name="SConstruct" printme="1">
317 import os.path
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)
322       </file>
323       <file name="hello.c">
324 int main() { printf("Hello, world!\n"); }
325       </file>
326     </scons_example>
328     <para>
330     Which executes as follows on a POSIX system:
332     </para>
334     <scons_output example="nodes_exists" os="posix" suffix="1">
335       <scons_output_command>scons -Q</scons_output_command>
336     </scons_output>
338   </section>
340   <section>
341   <title>&GetBuildPath;: Getting the Path From a &Node; or String</title>
343     <para>
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
353     to exist.
355     </para>
357     <scons_example name="nodes_GetBuildPath">
358       <file name="SConstruct" printme="1">
359 env=Environment(VAR="value")
360 n=File("foo.c")
361 print(env.GetBuildPath([n, "sub/dir/$VAR"]))
362       </file>
363     </scons_example>
365     <para>
367     Would print the following file names:
369     </para>
371     <scons_output example="nodes_GetBuildPath" os="posix" suffix="1">
372       <scons_output_command>scons -Q</scons_output_command>
373     </scons_output>
375     <para>
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.
381     </para>
383   </section>
385   <!--
387   <section>
388   <title>Fetching the Contents of a &Node;</title>
390     <para>
392     XXX Describe using read() and readlines()
393     when we add that as a public interface.
395     </para>
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:")
402 print(contents)
403       </file>
404       <file name="hello.c">
405 int main() { printf("Hello, world!\n"); }
406       </file>
407     </scons_example>
409     <para>
411     Which executes as follows on a POSIX system:
413     </para>
415     <scons_output example="nodes_read" os="posix" suffix="1">
416       <scons_output_command>scons -Q</scons_output_command>
417     </scons_output>
419   </section>
421   -->
423   <!--
425   <section>
426   <title>Python Value &Node;</title>
428     <para>
430     XXX Value()
432     </para>
434   </section>
436   -->
438 </chapter>