5 Permission is hereby granted, free of charge, to any person obtaining
6 a copy of this software and associated documentation files (the
7 "Software"), to deal in the Software without restriction, including
8 without limitation the rights to use, copy, modify, merge, publish,
9 distribute, sublicense, and/or sell copies of the Software, and to
10 permit persons to whom the Software is furnished to do so, subject to
11 the following conditions:
13 The above copyright notice and this permission notice shall be included
14 in all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
17 KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
18 WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 Internally, &SCons; represents all of the files
29 and directories it knows about as &Nodes;.
30 These internal objects
31 (not object <emphasis>files</emphasis>)
32 can be used in a variety of ways
33 to make your &SConscript;
34 files portable and easy to read.
39 <title>Builder Methods Return Lists of Target Nodes</title>
43 All builder methods return a list of
44 &Node; objects that identify the
45 target file or files that will be built.
46 These returned &Nodes; can be passed
47 as arguments to other builder methods.
53 For example, suppose that we want to build
54 the two object files that make up a program with different options.
55 This would mean calling the &b-link-Object;
56 builder once for each object file,
57 specifying the desired options:
62 Object('hello.c', CCFLAGS='-DHELLO')
63 Object('goodbye.c', CCFLAGS='-DGOODBYE')
68 One way to combine these object files
69 into the resulting program
70 would be to call the &b-link-Program;
71 builder with the names of the object files
77 Object('hello.c', CCFLAGS='-DHELLO')
78 Object('goodbye.c', CCFLAGS='-DGOODBYE')
79 Program(['hello.o', 'goodbye.o'])
84 The problem with specifying the names as strings
85 is that our &SConstruct; file is no longer portable
86 across operating systems.
87 It won't, for example, work on Windows
88 because the object files there would be
89 named &hello_obj; and &goodbye_obj;,
90 not &hello_o; and &goodbye_o;.
96 A better solution is to assign the lists of targets
97 returned by the calls to the &b-Object; builder to variables,
98 which we can then concatenate in our
99 call to the &b-Program; builder:
103 <scons_example name="ex1">
104 <file name="SConstruct" printme="1">
105 hello_list = Object('hello.c', CCFLAGS='-DHELLO')
106 goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE')
107 Program(hello_list + goodbye_list)
109 <file name="hello.c">
110 int main() { printf("Hello, world!\n"); }
112 <file name="goodbye.c">
113 int main() { printf("Goodbye, world!\n"); }
119 This makes our &SConstruct; file portable again,
120 the build output on Linux looking like:
124 <scons_output example="ex1" os="posix">
125 <scons_output_command>scons -Q</scons_output_command>
134 <scons_output example="ex1" os="win32">
135 <scons_output_command>scons -Q</scons_output_command>
140 We'll see examples of using the list of nodes
141 returned by builder methods throughout
142 the rest of this guide.
149 <title>Explicitly Creating File and Directory Nodes</title>
153 It's worth mentioning here that
154 &SCons; maintains a clear distinction
155 between Nodes that represent files
156 and Nodes that represent directories.
157 &SCons; supports &File; and &Dir;
158 functions that, respectively,
159 return a file or directory Node:
163 <scons_example name="print">
164 <file name="SConstruct" printme="1">
165 hello_c = File('hello.c')
168 classes = Dir('classes')
175 Normally, you don't need to call
176 &File; or &Dir; directly,
177 because calling a builder method automatically
178 treats strings as the names of files or directories,
179 and translates them into
180 the Node objects for you.
181 The &File; and &Dir; functions can come in handy
182 in situations where you need to explicitly
183 instruct &SCons; about the type of Node being
184 passed to a builder or other function,
185 or unambiguously refer to a specific
186 file in a directory tree.
188 (For an example of when you might
189 need to use &File; or &Dir; to
190 prevent ambiguous interpretation of a string
191 naming a file or directory, see
192 <xref linkend="chap-hierarchy">.)
199 There are also times when you may need to
200 refer to an entry in a file system
201 without knowing in advance
202 whether it's a file or a directory.
203 For those situations,
204 &SCons; also supports an &Entry; function,
206 that can represent either a file or a directory.
211 xyzzy = Entry('xyzzy')
216 The returned <literal>xyzzy</literal> Node
217 will be turned into a file or directory Node
218 the first time it is used by a builder method
219 or other function that
220 requires one vs. the other.
227 <title>Printing &Node; File Names</title>
231 One of the most common things you can do
232 with a Node is use it to print the
233 file name that the node represents.
234 Keep in mind, though, that because the object
235 returned by a builder call
236 is a <emphasis>list</emphasis> of Nodes,
237 you must use Python subscripts
238 to fetch individual Nodes from the list.
239 For example, the following &SConstruct; file:
243 <scons_example name="print">
244 <file name="SConstruct" printme="1">
245 object_list = Object('hello.c')
246 program_list = Program(object_list)
247 print "The object file is:", object_list[0]
248 print "The program file is:", program_list[0]
250 <file name="hello.c">
251 int main() { printf("Hello, world!\n"); }
257 Would print the following file names on a POSIX system:
261 <scons_output example="print" os="posix">
262 <scons_output_command>scons -Q</scons_output_command>
267 And the following file names on a Windows system:
271 <scons_output example="print" os="win32">
272 <scons_output_command>scons -Q</scons_output_command>
277 Note that in the above example,
278 the <literal>object_list[0]</literal>
279 extracts an actual Node <emphasis>object</emphasis>
281 and the Python <literal>print</literal> statement
282 converts the object to a string for printing.
289 <title>Using a &Node;'s File Name as a String</title>
293 Printing a &Node;'s name
294 as described in the previous section
295 works because the string representation of a &Node; object
296 is the name of the file.
297 If you want to do something other than
298 print the name of the file,
299 you can fetch it by using the builtin Python
301 For example, if you want to use the Python
302 <function>os.path.exists</function>
303 to figure out whether a file
304 exists while the &SConstruct; file
305 is being read and executed,
306 you can fetch the string as follows:
310 <scons_example name="exists">
311 <file name="SConstruct" printme="1">
313 program_list = Program('hello.c')
314 program_name = str(program_list[0])
315 if not os.path.exists(program_name):
316 print program_name, "does not exist!"
318 <file name="hello.c">
319 int main() { printf("Hello, world!\n"); }
325 Which executes as follows on a POSIX system:
329 <scons_output example="exists" os="posix">
330 <scons_output_command>scons -Q</scons_output_command>
338 <title>Fetching the Contents of a &Node;</title>
342 XXX Describe using read() and readlines()
343 when we add that as a public interface.
347 <scons_example name="read">
348 <file name="SConstruct" printme="1">
349 hello_c = File('hello.c')
350 contents = hello_c.read()
351 print "contents are:"
354 <file name="hello.c">
355 int main() { printf("Hello, world!\n"); }
361 Which executes as follows on a POSIX system:
365 <scons_output example="read" os="posix">
366 <scons_output_command>scons -Q</scons_output_command>
376 <title>Python Value &Node;</title>