Accumulated documentation changes.
[scons.git] / doc / user / factories.sgml
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 the &Install; builder isn't appropriate
48     because it may make a hard link on POSIX systems.
49     One way would be to use the &Copy; action factory
50     in conjunction with the &Command; builder:
51
52     </para>
53
54     <programlisting>
55         Command("file.out", "file.in", Copy("$TARGET", "$SOURCE"))
56     </programlisting>
57
58     <para>
59
60     Notice that the action returned by the &Copy; factory
61     will expand the &cv-TARGET; and &cv-SOURCE; strings
62     at the time &file_out; is built,
63     and that the order of the arguments
64     is the same as that of a builder itself--that is,
65     target first, followed by source:
66
67     </para>
68
69     <screen>
70        % <userinput>scons -Q</userinput>
71        Copy("file.out", "file.in")
72     </screen>
73
74     <para>
75
76     You can, of course, name a file explicitly
77     instead of using &cv-TARGET; or &cv-SOURCE;:
78
79     </para>
80
81     <programlisting>
82       Command("file.out", [], Copy("$TARGET", "file.in"))
83     </programlisting>
84
85     <para>
86
87     Which executes as:
88
89     </para>
90
91     <screen>
92       % <userinput>scons -Q</userinput>
93       Copy("file.out", "file.in")
94     </screen>
95
96     <para>
97
98     The usefulness of the &Copy; factory
99     becomes more apparent when
100     you use it in a list of actions
101     passed to the &Command; builder.
102     For example, suppose you needed to run a
103     file through a utility that only modifies files in-place,
104     and can't "pipe" input to output.
105     One solution is to copy the source file
106     to a temporary file name,
107     run the utility,
108     and then copy the modified temporary file to the target,
109     which the &Copy; factory makes extremely easy:
110
111     </para>
112
113     <programlisting>
114       Command("file.out", "file.in",
115               [
116                 Copy("tempfile", "$SOURCE"),
117                 "modify tempfile",
118                 Copy("$TARGET", "tempfile"),
119               ])
120     </programlisting>
121
122     <para>
123
124     The output then looks like:
125
126     </para>
127
128     <screen>
129       % <userinput>scons -Q</userinput>
130       Copy("tempfile", "file.in")
131       modify tempfile
132       Copy("file.out", "tempfile")
133     </screen>
134
135   </section>
136
137   <section>
138   <title>Deleting Files or Directories:  The &Delete; Factory</title>
139
140     <para>
141
142     If you need to delete a file,
143     then the &Delete; factory
144     can be used in much the same way as
145     the &Copy; factory.
146     For example, if we want to make sure that
147     the temporary file
148     in our last example doesn't exist before
149     we copy to it,
150     we could add &Delete; to the beginning
151     of the command list:
152
153     </para>
154
155     <programlisting>
156       Command("file.out", "file.in",
157               [
158                 Delete("tempfile"),
159                 Copy("tempfile", "$SOURCE"),
160                 "modify tempfile",
161                 Copy("$TARGET", "tempfile"),
162               ])
163     </programlisting>
164
165     <para>
166
167     When then executes as follows:
168
169     </para>
170
171     <screen>
172       % <userinput>scons -Q</userinput>
173       Delete("tempfile")
174       Copy("tempfile", "file.in")
175       modify tempfile
176       Copy("file.out", "tempfile")
177     </screen>
178
179     <para>
180
181     Of course, like all of these &Action; factories,
182     the &Delete; factory also expands
183     &cv-TARGET; and &cv-SOURCE; variables appropriately.
184     For example:
185
186     </para>
187
188     <programlisting>
189       Command("file.out", "file.in",
190               [
191                 Delete("$TARGET"),
192                 Copy("$TARGET", "$SOURCE")
193               ])
194     </programlisting>
195
196     <para>
197
198     Executes as:
199
200     </para>
201
202     <screen>
203       % <userinput>scons -Q</userinput>
204       Delete("file.out")
205       Copy("file.out", "file.in")
206     </screen>
207
208     <para>
209
210     (Note, however, that you typically don't need to
211     call the &Delete; factory explicitly in this way;
212     by default, &SCons; deletes its target(s)
213     for you before executing any action.
214
215     </para>
216
217   </section>
218
219   <section>
220   <title>Moving (Renaming) Files or Directories:  The &Move; Factory</title>
221
222     <para>
223
224     The &Move; factory
225     allows you to rename a file or directory.
226     For example, if we don't want to copy the temporary file,
227     we could:
228
229     </para>
230
231     <programlisting>
232       Command("file.out", "file.in",
233               [
234                 Copy("tempfile", "$SOURCE"),
235                 "modify tempfile",
236                 Move("$TARGET", "tempfile"),
237               ])
238     </programlisting>
239
240     <para>
241
242     Which would execute as:
243
244     </para>
245
246     <screen>
247       % <userinput>scons -Q</userinput>
248       Copy("tempfile", "file.in")
249       modify tempfile
250       Move("file.out", "tempfile")
251     </screen>
252
253   </section>
254
255   <section>
256   <title>Updating the Modification Time of a File:  The &Touch; Factory</title>
257
258     <para>
259
260     If you just need to update the
261     recorded modification time for a file,
262     use the &Touch; factory:
263
264     </para>
265
266     <programlisting>
267       Command("file.out", "file.in",
268               [
269                 Copy("tempfile", "$SOURCE"),
270                 "modify tempfile",
271                 Move("$TARGET", "tempfile"),
272               ])
273     </programlisting>
274
275     <para>
276
277     Which executes as:
278
279     </para>
280
281     <screen>
282       % <userinput>scons -Q</userinput>
283       Copy("tempfile", "file.in")
284       modify tempfile
285       Move("file.out", "tempfile")
286     </screen>
287
288   </section>
289
290   <section>
291   <title>Creating a Directory:  The &Mkdir; Factory</title>
292
293     <para>
294
295     If you need to create a directory,
296     use the &Mkdir; factory.
297     For example, if we need to process
298     a file in a temporary directory
299     in which the processing tool
300     will create other files that we don't care about, 
301     you could:
302
303     </para>
304
305     <programlisting>
306       Command("file.out", "file.in",
307               [
308                 Delete("tempdir"),
309                 Mkdir("tempdir"),
310                 Copy("tempdir/${SOURCE.file}", "$SOURCE"),
311                 "process tempdir",
312                 Move("$TARGET", "tempdir/output_file"),
313                 Delete("tempdir"),
314               ])
315     </programlisting>
316
317     <para>
318
319     Which executes as:
320
321     </para>
322
323     <screen>
324       % <userinput>scons -Q</userinput>
325       Delete("tempdir")
326       Mkdir("tempdir")
327       Copy("tempdir/file.in", "file.in")
328       process tempdir
329       Move("file.out", "tempdir/output_file")
330       scons: *** [file.out] No such file or directory
331     </screen>
332
333   </section>
334
335   <section>
336   <title>Changing File or Directory Permissions:  The &Chmod; Factory</title>
337
338     <para>
339
340     To change permissions on a file or directory,
341     use the &Chmod; factory.
342     The permission argument uses POSIX-style
343     permission bits and should typically
344     be expressed as an octal,
345     not decimal, number:
346
347     </para>
348
349     <programlisting>
350       Command("file.out", "file.in",
351               [
352                 Copy("$TARGET", "$SOURCE"),
353                 Chmod("$TARGET", 0755),
354               ])
355     </programlisting>
356
357     <para>
358
359     Which executes:
360
361     </para>
362
363     <screen>
364       % <userinput>scons -Q</userinput>
365       Copy("file.out", "file.in")
366       Chmod("file.out", 0755)
367     </screen>
368
369   </section>
370
371   <section>
372   <title>Executing an action immediately:  the &Execute; Function</title>
373
374     <para>
375
376     We've been showing you how to use &Action; factories
377     in the &Command; function.
378     You can also execute an &Action; returned by a factory
379     (or actually, any &Action;)
380     at the time the &SConscript; file is read
381     by wrapping it up in the &Execute; function.
382     For example, if we need to make sure that
383     a directory exists before we build any targets,
384
385
386     </para>
387
388     <programlisting>
389       Execute(Mkdir('/tmp/my_temp_directory'))
390     </programlisting>
391
392     <para>
393
394     Notice that this will
395     create the directory while
396     the &SConscript; file is being read:
397
398     </para>
399
400     <screen>
401       % <userinput>scons</userinput>
402       scons: Reading SConscript files ...
403       Mkdir("/tmp/my_temp_directory")
404       scons: done reading SConscript files.
405       scons: Building targets ...
406       scons: `.' is up to date.
407       scons: done building targets.
408     </screen>
409
410     <para>
411
412     If you're familiar with Python,
413     you may wonder why you would want to use this
414     instead of just calling the native Python
415     <function>os.mkdir()</function> function.
416     The advantage here is that the &Mkdir;
417     action will behave appropriately if the user
418     specifies the &SCons; <option>-n</option> or
419     <option>-q</option> options--that is,
420     it will print the action but not actually
421     make the directory when <option>-n</option> is specified,
422     or make the directory but not print the action
423     when <option>-q</option> is specified.
424
425     </para>
426
427   </section>