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 &SCons; provides a number of platform-independent functions,
29 called <literal>factories</literal>,
30 that perform common file system manipulations
31 like copying, moving or deleting files and directories,
32 or making directories.
33 These functions are <literal>factories</literal>
34 because they don't perform the action
35 at the time they're called,
36 they each return an &Action; object
37 that can be executed at the appropriate time.
42 <title>Copying Files or Directories: The &Copy; Factory</title>
46 Suppose you want to arrange to make a copy of a file,
47 and don't have a suitable pre-existing builder.
50 Unfortunately, in the early days of SCons design,
51 we used the name &Copy; for the function that
52 returns a copy of the environment,
53 otherwise that would be the logical choice for
54 a Builder that copies a file or directory tree
58 One way would be to use the &Copy; action factory
59 in conjunction with the &Command; builder:
63 <scons_example name="Copy1">
64 <file name="SConstruct" printme="1">
65 Command("file.out", "file.in", Copy("$TARGET", "$SOURCE"))
67 <file name="file.in">file.in</file>
72 Notice that the action returned by the &Copy; factory
73 will expand the &cv-link-TARGET; and &cv-link-SOURCE; strings
74 at the time &file_out; is built,
75 and that the order of the arguments
76 is the same as that of a builder itself--that is,
77 target first, followed by source:
81 <scons_output example="Copy1">
82 <scons_output_command>scons -Q</scons_output_command>
87 You can, of course, name a file explicitly
88 instead of using &cv-TARGET; or &cv-SOURCE;:
92 <scons_example name="Copy2">
93 <file name="SConstruct" printme="1">
94 Command("file.out", [], Copy("$TARGET", "file.in"))
96 <file name="file.in">file.in</file>
105 <scons_output example="Copy2">
106 <scons_output_command>scons -Q</scons_output_command>
111 The usefulness of the &Copy; factory
112 becomes more apparent when
113 you use it in a list of actions
114 passed to the &Command; builder.
115 For example, suppose you needed to run a
116 file through a utility that only modifies files in-place,
117 and can't "pipe" input to output.
118 One solution is to copy the source file
119 to a temporary file name,
121 and then copy the modified temporary file to the target,
122 which the &Copy; factory makes extremely easy:
126 <scons_example name="Copy3">
127 <file name="S" printme="1">
128 Command("file.out", "file.in",
130 Copy("tempfile", "$SOURCE"),
132 Copy("$TARGET", "tempfile"),
135 <file name="SConstruct">
136 env = DefaultEnvironment()
138 env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
141 <file name="file.in">file.in</file>
142 <file name="modify" chmod="0755">
149 The output then looks like:
153 <scons_output example="Copy3">
154 <scons_output_command>scons -Q</scons_output_command>
160 <title>Deleting Files or Directories: The &Delete; Factory</title>
164 If you need to delete a file,
165 then the &Delete; factory
166 can be used in much the same way as
168 For example, if we want to make sure that
170 in our last example doesn't exist before
172 we could add &Delete; to the beginning
177 <scons_example name="Delete1">
178 <file name="S" printme="1">
179 Command("file.out", "file.in",
182 Copy("tempfile", "$SOURCE"),
184 Copy("$TARGET", "tempfile"),
187 <file name="SConstruct">
188 env = DefaultEnvironment()
190 env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
193 <file name="file.in">file.in</file>
194 <file name="modify" chmod="0755">
201 Which then executes as follows:
205 <scons_output example="Delete1">
206 <scons_output_command>scons -Q</scons_output_command>
211 Of course, like all of these &Action; factories,
212 the &Delete factory also expands
213 &cv-link-TARGET; and &cv-link-SOURCE; variables appropriately.
218 <scons_example name="Delete2">
219 <file name="SConstruct" printme="1">
220 Command("file.out", "file.in",
223 Copy("$TARGET", "$SOURCE")
226 <file name="file.in">file.in</file>
235 <scons_output example="Delete2">
236 <scons_output_command>scons -Q</scons_output_command>
241 Note, however, that you typically don't need to
242 call the &Delete; factory explicitly in this way;
243 by default, &SCons; deletes its target(s)
244 for you before executing any action.
250 One word of caution about using the &Delete; factory:
251 it has the same variable expansions available
252 as any other factory, including the &cv-SOURCE; variable.
253 Specifying <literal>Delete("$SOURCE")</literal>
254 is not something you usually want to do!
261 <title>Moving (Renaming) Files or Directories: The &Move; Factory</title>
266 allows you to rename a file or directory.
267 For example, if we don't want to copy the temporary file,
272 <scons_example name="Move">
273 <file name="S" printme="1">
274 Command("file.out", "file.in",
276 Copy("tempfile", "$SOURCE"),
278 Move("$TARGET", "tempfile"),
281 <file name="SConstruct">
282 env = DefaultEnvironment()
284 env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
287 <file name="file.in">file.in</file>
288 <file name="modify" chmod="0755">
295 Which would execute as:
299 <scons_output example="Move">
300 <scons_output_command>scons -Q</scons_output_command>
306 <title>Updating the Modification Time of a File: The &Touch; Factory</title>
310 If you just need to update the
311 recorded modification time for a file,
312 use the &Touch; factory:
316 <scons_example name="Touch">
317 <file name="S" printme="1">
318 Command("file.out", "file.in",
320 Copy("$TARGET", "$SOURCE"),
324 <file name="SConstruct">
325 env = DefaultEnvironment()
327 env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
330 <file name="file.in">file.in</file>
339 <scons_output example="Touch">
340 <scons_output_command>scons -Q</scons_output_command>
346 <title>Creating a Directory: The &Mkdir; Factory</title>
350 If you need to create a directory,
351 use the &Mkdir; factory.
352 For example, if we need to process
353 a file in a temporary directory
354 in which the processing tool
355 will create other files that we don't care about,
360 <scons_example name="Mkdir">
361 <file name="S" printme="1">
362 Command("file.out", "file.in",
366 Copy("tempdir/${SOURCE.file}", "$SOURCE"),
368 Move("$TARGET", "tempdir/output_file"),
372 <file name="SConstruct">
373 env = DefaultEnvironment()
375 env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd()
378 <file name="file.in">file.in</file>
379 <file name="process" chmod="0755">
390 <scons_output example="Mkdir">
391 <scons_output_command>scons -Q</scons_output_command>
397 <title>Changing File or Directory Permissions: The &Chmod; Factory</title>
401 To change permissions on a file or directory,
402 use the &Chmod; factory.
403 The permission argument uses POSIX-style
404 permission bits and should typically
405 be expressed as an octal,
410 <scons_example name="Chmod">
411 <file name="SConstruct" printme="1">
412 Command("file.out", "file.in",
414 Copy("$TARGET", "$SOURCE"),
415 Chmod("$TARGET", 0755),
418 <file name="file.in">file.in</file>
427 <scons_output example="Chmod">
428 <scons_output_command>scons -Q</scons_output_command>
434 <title>Executing an action immediately: the &Execute; Function</title>
438 We've been showing you how to use &Action; factories
439 in the &Command; function.
440 You can also execute an &Action; returned by a factory
441 (or actually, any &Action;)
442 at the time the &SConscript; file is read
443 by using the &Execute; function.
444 For example, if we need to make sure that
445 a directory exists before we build any targets,
449 <scons_example name="Execute">
450 <file name="SConstruct" printme="1">
451 Execute(Mkdir('__ROOT__/tmp/my_temp_directory'))
457 Notice that this will
458 create the directory while
459 the &SConscript; file is being read:
463 <scons_output example="Execute">
464 <scons_output_command>scons</scons_output_command>
469 If you're familiar with Python,
470 you may wonder why you would want to use this
471 instead of just calling the native Python
472 <function>os.mkdir()</function> function.
473 The advantage here is that the &Mkdir;
474 action will behave appropriately if the user
475 specifies the &SCons; <option>-n</option> or
476 <option>-q</option> options--that is,
477 it will print the action but not actually
478 make the directory when <option>-n</option> is specified,
479 or make the directory but not print the action
480 when <option>-q</option> is specified.
486 The &Execute; function returns the exit status
487 or return value of the underlying action being executed.
488 It will also print an error message if the action
489 fails and returns a non-zero value.
490 &SCons; will <emphasis>not</emphasis>, however,
491 actually stop the build if the action fails.
492 If you want the build to stop
493 in response to a failure in an action called by &Execute;,
494 you must do so by explicitly
495 checking the return value
496 and calling the &Exit; function
497 (or a Python equivalent):
502 if Execute(Mkdir('__ROOT__/tmp/my_temp_directory')):
503 # A problem occurred while making the temp directory.