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:
64 Command("file.out", "file.in", Copy("$TARGET", "$SOURCE"))
69 Notice that the action returned by the &Copy; factory
70 will expand the &cv-link-TARGET; and &cv-link-SOURCE; strings
71 at the time &file_out; is built,
72 and that the order of the arguments
73 is the same as that of a builder itself--that is,
74 target first, followed by source:
79 % <userinput>scons -Q</userinput>
80 Copy("file.out", "file.in")
85 You can, of course, name a file explicitly
86 instead of using &cv-TARGET; or &cv-SOURCE;:
91 Command("file.out", [], Copy("$TARGET", "file.in"))
101 % <userinput>scons -Q</userinput>
102 Copy("file.out", "file.in")
107 The usefulness of the &Copy; factory
108 becomes more apparent when
109 you use it in a list of actions
110 passed to the &Command; builder.
111 For example, suppose you needed to run a
112 file through a utility that only modifies files in-place,
113 and can't "pipe" input to output.
114 One solution is to copy the source file
115 to a temporary file name,
117 and then copy the modified temporary file to the target,
118 which the &Copy; factory makes extremely easy:
123 Command("file.out", "file.in",
125 Copy("tempfile", "$SOURCE"),
127 Copy("$TARGET", "tempfile"),
133 The output then looks like:
138 % <userinput>scons -Q</userinput>
139 Copy("tempfile", "file.in")
141 Copy("file.out", "tempfile")
147 <title>Deleting Files or Directories: The &Delete; Factory</title>
151 If you need to delete a file,
152 then the &Delete; factory
153 can be used in much the same way as
155 For example, if we want to make sure that
157 in our last example doesn't exist before
159 we could add &Delete; to the beginning
165 Command("file.out", "file.in",
168 Copy("tempfile", "$SOURCE"),
170 Copy("$TARGET", "tempfile"),
176 Which then executes as follows:
181 % <userinput>scons -Q</userinput>
183 Copy("tempfile", "file.in")
185 Copy("file.out", "tempfile")
190 Of course, like all of these &Action; factories,
191 the &Delete; factory also expands
192 &cv-link-TARGET; and &cv-link-SOURCE; variables appropriately.
198 Command("file.out", "file.in",
201 Copy("$TARGET", "$SOURCE")
212 % <userinput>scons -Q</userinput>
214 Copy("file.out", "file.in")
219 Note, however, that you typically don't need to
220 call the &Delete; factory explicitly in this way;
221 by default, &SCons; deletes its target(s)
222 for you before executing any action.
228 One word of caution about using the &Delete; factory:
229 it has the same variable expansions available
230 as any other factory, including the &cv-SOURCE; variable.
231 Specifying <literal>Delete("$SOURCE")</literal>
232 is not something you usually want to do!
239 <title>Moving (Renaming) Files or Directories: The &Move; Factory</title>
244 allows you to rename a file or directory.
245 For example, if we don't want to copy the temporary file,
251 Command("file.out", "file.in",
253 Copy("tempfile", "$SOURCE"),
255 Move("$TARGET", "tempfile"),
261 Which would execute as:
266 % <userinput>scons -Q</userinput>
267 Copy("tempfile", "file.in")
269 Move("file.out", "tempfile")
275 <title>Updating the Modification Time of a File: The &Touch; Factory</title>
279 If you just need to update the
280 recorded modification time for a file,
281 use the &Touch; factory:
286 Command("file.out", "file.in",
288 Copy("$TARGET", "$SOURCE"),
300 % <userinput>scons -Q</userinput>
301 Copy("file.out", "file.in")
308 <title>Creating a Directory: The &Mkdir; Factory</title>
312 If you need to create a directory,
313 use the &Mkdir; factory.
314 For example, if we need to process
315 a file in a temporary directory
316 in which the processing tool
317 will create other files that we don't care about,
323 Command("file.out", "file.in",
327 Copy("tempdir/${SOURCE.file}", "$SOURCE"),
329 Move("$TARGET", "tempdir/output_file"),
341 % <userinput>scons -Q</userinput>
344 Copy("tempdir/file.in", "file.in")
346 Move("file.out", "tempdir/output_file")
347 scons: *** [file.out] tempdir/output_file: No such file or directory
353 <title>Changing File or Directory Permissions: The &Chmod; Factory</title>
357 To change permissions on a file or directory,
358 use the &Chmod; factory.
359 The permission argument uses POSIX-style
360 permission bits and should typically
361 be expressed as an octal,
367 Command("file.out", "file.in",
369 Copy("$TARGET", "$SOURCE"),
370 Chmod("$TARGET", 0755),
381 % <userinput>scons -Q</userinput>
382 Copy("file.out", "file.in")
383 Chmod("file.out", 0755)
389 <title>Executing an action immediately: the &Execute; Function</title>
393 We've been showing you how to use &Action; factories
394 in the &Command; function.
395 You can also execute an &Action; returned by a factory
396 (or actually, any &Action;)
397 at the time the &SConscript; file is read
398 by using the &Execute; function.
399 For example, if we need to make sure that
400 a directory exists before we build any targets,
405 Execute(Mkdir('/tmp/my_temp_directory'))
410 Notice that this will
411 create the directory while
412 the &SConscript; file is being read:
417 % <userinput>scons</userinput>
418 scons: Reading SConscript files ...
419 Mkdir("/tmp/my_temp_directory")
420 scons: done reading SConscript files.
421 scons: Building targets ...
422 scons: `.' is up to date.
423 scons: done building targets.
428 If you're familiar with Python,
429 you may wonder why you would want to use this
430 instead of just calling the native Python
431 <function>os.mkdir()</function> function.
432 The advantage here is that the &Mkdir;
433 action will behave appropriately if the user
434 specifies the &SCons; <option>-n</option> or
435 <option>-q</option> options--that is,
436 it will print the action but not actually
437 make the directory when <option>-n</option> is specified,
438 or make the directory but not print the action
439 when <option>-q</option> is specified.
445 The &Execute; function returns the exit status
446 or return value of the underlying action being executed.
447 It will also print an error message if the action
448 fails and returns a non-zero value.
449 &SCons; will <emphasis>not</emphasis>, however,
450 actually stop the build if the action fails.
451 If you want the build to stop
452 in response to a failure in an action called by &Execute;,
453 you must do so by explicitly
454 checking the return value
455 and calling the &Exit; function
456 (or a Python equivalent):
461 if Execute(Mkdir('/tmp/my_temp_directory')):
462 # A problem occurred while making the temp directory.