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:
104 hello_list = Object('hello.c', CCFLAGS='-DHELLO')
105 goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE')
106 Program(hello_list + goodbye_list)
111 This makes our &SConstruct; file portable again,
112 the build output on Linux looking like:
117 % <userinput>scons -Q</userinput>
118 cc -o goodbye.o -c -DGOODBYE goodbye.c
119 cc -o hello.o -c -DHELLO hello.c
120 cc -o hello hello.o goodbye.o
130 C:\><userinput>scons -Q</userinput>
131 cl /Fogoodbye.obj /c goodbye.c -DGOODBYE
132 cl /Fohello.obj /c hello.c -DHELLO
133 link /nologo /OUT:hello.exe hello.obj goodbye.obj
138 We'll see examples of using the list of nodes
139 returned by builder methods throughout
140 the rest of this guide.
147 <title>Explicitly Creating File and Directory Nodes</title>
151 It's worth mentioning here that
152 &SCons; maintains a clear distinction
153 between Nodes that represent files
154 and Nodes that represent directories.
155 &SCons; supports &File; and &Dir;
156 functions that, respectively,
157 return a file or directory Node:
162 hello_c = File('hello.c')
165 classes = Dir('classes')
171 Normally, you don't need to call
172 &File; or &Dir; directly,
173 because calling a builder method automatically
174 treats strings as the names of files or directories,
175 and translates them into
176 the Node objects for you.
177 The &File; and &Dir; functions can come in handy
178 in situations where you need to explicitly
179 instruct &SCons; about the type of Node being
180 passed to a builder or other function,
181 or unambiguously refer to a specific
182 file in a directory tree.
184 (For an example of when you might
185 need to use &File; or &Dir; to
186 prevent ambiguous interpretation of a string
187 naming a file or directory, see
188 <xref linkend="chap-hierarchy">.)
195 There are also times when you may need to
196 refer to an entry in a file system
197 without knowing in advance
198 whether it's a file or a directory.
199 For those situations,
200 &SCons; also supports an &Entry; function,
202 that can represent either a file or a directory.
207 xyzzy = Entry('xyzzy')
212 The returned <literal>xyzzy</literal> Node
213 will be turned into a file or directory Node
214 the first time it is used by a builder method
215 or other function that
216 requires one vs. the other.
223 <title>Printing &Node; File Names</title>
227 One of the most common things you can do
228 with a Node is use it to print the
229 file name that the node represents.
230 Keep in mind, though, that because the object
231 returned by a builder call
232 is a <emphasis>list</emphasis> of Nodes,
233 you must use Python subscripts
234 to fetch individual Nodes from the list.
235 For example, the following &SConstruct; file:
240 hello_c = File('hello.c')
243 classes = Dir('classes')
246 object_list = Object('hello.c')
247 program_list = Program(object_list)
248 print "The object file is:", object_list[0]
249 print "The program file is:", program_list[0]
254 Would print the following file names on a POSIX system:
259 % <userinput>scons -Q</userinput>
260 The object file is: hello.o
261 The program file is: hello
262 cc -o hello.o -c hello.c
268 And the following file names on a Windows system:
273 C:\><userinput>scons -Q</userinput>
274 The object file is: hello.obj
275 The program file is: hello.exe
276 cl /Fohello.obj /c hello.c /nologo
277 link /nologo /OUT:hello.exe hello.obj
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 <literal>print</literal> statement
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 builtin 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:
317 program_list = Program('hello.c')
318 program_name = str(program_list[0])
319 if not os.path.exists(program_name):
320 print program_name, "does not exist!"
325 Which executes as follows on a POSIX system:
330 % <userinput>scons -Q</userinput>
331 hello does not exist!
332 cc -o hello.o -c hello.c
341 <title>Fetching the Contents of a &Node;</title>
345 XXX Describe using read() and readlines()
346 when we add that as a public interface.
350 <scons_example name="read">
351 <file name="SConstruct" printme="1">
352 hello_c = File('hello.c')
353 contents = hello_c.read()
354 print "contents are:"
357 <file name="hello.c">
358 int main() { printf("Hello, world!\n"); }
364 Which executes as follows on a POSIX system:
368 <scons_output example="read" os="posix">
369 <scons_output_command>scons -Q</scons_output_command>
379 <title>Python Value &Node;</title>