f6ea89d34029fdf7172ff3d81120db0681ba122c
[scons.git] / doc / user / factories.xml
1 <!--
2
3   __COPYRIGHT__
4
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:
12
13   The above copyright notice and this permission notice shall be included
14   in all copies or substantial portions of the Software.
15
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.
23
24 -->
25
26   <para>
27
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.
38
39   </para>
40
41   <section>
42   <title>Copying Files or Directories:  The &Copy; Factory</title>
43
44     <para>
45
46     Suppose you want to arrange to make a copy of a file,
47     and don't have a suitable pre-existing builder.
48     <footnote>
49     <para>
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
55     to a target location.
56     </para>
57     </footnote>
58     One way would be to use the &Copy; action factory
59     in conjunction with the &Command; builder:
60
61     </para>
62
63     <programlisting>
64         Command("file.out", "file.in", Copy("$TARGET", "$SOURCE"))
65     </programlisting>
66
67     <para>
68
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:
75
76     </para>
77
78     <screen>
79        % <userinput>scons -Q</userinput>
80        Copy("file.out", "file.in")
81     </screen>
82
83     <para>
84
85     You can, of course, name a file explicitly
86     instead of using &cv-TARGET; or &cv-SOURCE;:
87
88     </para>
89
90     <programlisting>
91       Command("file.out", [], Copy("$TARGET", "file.in"))
92     </programlisting>
93
94     <para>
95
96     Which executes as:
97
98     </para>
99
100     <screen>
101       % <userinput>scons -Q</userinput>
102       Copy("file.out", "file.in")
103     </screen>
104
105     <para>
106
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,
116     run the utility,
117     and then copy the modified temporary file to the target,
118     which the &Copy; factory makes extremely easy:
119
120     </para>
121
122     <programlisting>
123       Command("file.out", "file.in",
124               [
125                 Copy("tempfile", "$SOURCE"),
126                 "modify tempfile",
127                 Copy("$TARGET", "tempfile"),
128               ])
129     </programlisting>
130
131     <para>
132
133     The output then looks like:
134
135     </para>
136
137     <screen>
138       % <userinput>scons -Q</userinput>
139       Copy("tempfile", "file.in")
140       modify tempfile
141       Copy("file.out", "tempfile")
142     </screen>
143
144   </section>
145
146   <section>
147   <title>Deleting Files or Directories:  The &Delete; Factory</title>
148
149     <para>
150
151     If you need to delete a file,
152     then the &Delete; factory
153     can be used in much the same way as
154     the &Copy; factory.
155     For example, if we want to make sure that
156     the temporary file
157     in our last example doesn't exist before
158     we copy to it,
159     we could add &Delete; to the beginning
160     of the command list:
161
162     </para>
163
164     <programlisting>
165       Command("file.out", "file.in",
166               [
167                 Delete("tempfile"),
168                 Copy("tempfile", "$SOURCE"),
169                 "modify tempfile",
170                 Copy("$TARGET", "tempfile"),
171               ])
172     </programlisting>
173
174     <para>
175
176     Which then executes as follows:
177
178     </para>
179
180     <screen>
181       % <userinput>scons -Q</userinput>
182       Delete("tempfile")
183       Copy("tempfile", "file.in")
184       modify tempfile
185       Copy("file.out", "tempfile")
186     </screen>
187
188     <para>
189
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.
193     For example:
194
195     </para>
196
197     <programlisting>
198       Command("file.out", "file.in",
199               [
200                 Delete("$TARGET"),
201                 Copy("$TARGET", "$SOURCE")
202               ])
203     </programlisting>
204
205     <para>
206
207     Executes as:
208
209     </para>
210
211     <screen>
212       % <userinput>scons -Q</userinput>
213       Delete("file.out")
214       Copy("file.out", "file.in")
215     </screen>
216
217     <para>
218
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.
223
224     </para>
225
226     <para>
227
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!
233
234     </para>
235
236   </section>
237
238   <section>
239   <title>Moving (Renaming) Files or Directories:  The &Move; Factory</title>
240
241     <para>
242
243     The &Move; factory
244     allows you to rename a file or directory.
245     For example, if we don't want to copy the temporary file,
246     we could use:
247
248     </para>
249
250     <programlisting>
251       Command("file.out", "file.in",
252               [
253                 Copy("tempfile", "$SOURCE"),
254                 "modify tempfile",
255                 Move("$TARGET", "tempfile"),
256               ])
257     </programlisting>
258
259     <para>
260
261     Which would execute as:
262
263     </para>
264
265     <screen>
266       % <userinput>scons -Q</userinput>
267       Copy("tempfile", "file.in")
268       modify tempfile
269       Move("file.out", "tempfile")
270     </screen>
271
272   </section>
273
274   <section>
275   <title>Updating the Modification Time of a File:  The &Touch; Factory</title>
276
277     <para>
278
279     If you just need to update the
280     recorded modification time for a file,
281     use the &Touch; factory:
282
283     </para>
284
285     <programlisting>
286       Command("file.out", "file.in",
287               [
288                 Copy("$TARGET", "$SOURCE"),
289                 Touch("$TARGET"),
290               ])
291     </programlisting>
292
293     <para>
294
295     Which executes as:
296
297     </para>
298
299     <screen>
300       % <userinput>scons -Q</userinput>
301       Copy("file.out", "file.in")
302       Touch("file.out")
303     </screen>
304
305   </section>
306
307   <section>
308   <title>Creating a Directory:  The &Mkdir; Factory</title>
309
310     <para>
311
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, 
318     you could use:
319
320     </para>
321
322     <programlisting>
323       Command("file.out", "file.in",
324               [
325                 Delete("tempdir"),
326                 Mkdir("tempdir"),
327                 Copy("tempdir/${SOURCE.file}", "$SOURCE"),
328                 "process tempdir",
329                 Move("$TARGET", "tempdir/output_file"),
330                 Delete("tempdir"),
331               ])
332     </programlisting>
333
334     <para>
335
336     Which executes as:
337
338     </para>
339
340     <screen>
341       % <userinput>scons -Q</userinput>
342       Delete("tempdir")
343       Mkdir("tempdir")
344       Copy("tempdir/file.in", "file.in")
345       process tempdir
346       Move("file.out", "tempdir/output_file")
347       scons: *** [file.out] tempdir/output_file: No such file or directory
348     </screen>
349
350   </section>
351
352   <section>
353   <title>Changing File or Directory Permissions:  The &Chmod; Factory</title>
354
355     <para>
356
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,
362     not decimal, number:
363
364     </para>
365
366     <programlisting>
367       Command("file.out", "file.in",
368               [
369                 Copy("$TARGET", "$SOURCE"),
370                 Chmod("$TARGET", 0755),
371               ])
372     </programlisting>
373
374     <para>
375
376     Which executes:
377
378     </para>
379
380     <screen>
381       % <userinput>scons -Q</userinput>
382       Copy("file.out", "file.in")
383       Chmod("file.out", 0755)
384     </screen>
385
386   </section>
387
388   <section>
389   <title>Executing an action immediately:  the &Execute; Function</title>
390
391     <para>
392
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,
401
402     </para>
403
404     <programlisting>
405       Execute(Mkdir('/tmp/my_temp_directory'))
406     </programlisting>
407
408     <para>
409
410     Notice that this will
411     create the directory while
412     the &SConscript; file is being read:
413
414     </para>
415
416     <screen>
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.
424     </screen>
425
426     <para>
427
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.
440
441     </para>
442
443     <para>
444
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):
457
458     </para>
459
460     <programlisting>
461     if Execute(Mkdir('/tmp/my_temp_directory')):
462         # A problem occurred while making the temp directory.
463         Exit(1)
464     </programlisting>
465
466   </section>