mirror of
https://github.com/Relintai/scons_gd.git
synced 2025-03-12 18:38:59 +01:00
568 lines
14 KiB
XML
568 lines
14 KiB
XML
<?xml version='1.0'?>
|
|
<!DOCTYPE sconsdoc [
|
|
<!ENTITY % scons SYSTEM "../scons.mod">
|
|
%scons;
|
|
|
|
<!ENTITY % builders-mod SYSTEM "../generated/builders.mod">
|
|
%builders-mod;
|
|
<!ENTITY % functions-mod SYSTEM "../generated/functions.mod">
|
|
%functions-mod;
|
|
<!ENTITY % tools-mod SYSTEM "../generated/tools.mod">
|
|
%tools-mod;
|
|
<!ENTITY % variables-mod SYSTEM "../generated/variables.mod">
|
|
%variables-mod;
|
|
|
|
]>
|
|
|
|
<chapter id="chap-factories"
|
|
xmlns="http://www.scons.org/dbxsd/v1.0"
|
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">
|
|
<title>Platform-Independent File System Manipulation</title>
|
|
|
|
<!--
|
|
|
|
__COPYRIGHT__
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining
|
|
a copy of this software and associated documentation files (the
|
|
"Software"), to deal in the Software without restriction, including
|
|
without limitation the rights to use, copy, modify, merge, publish,
|
|
distribute, sublicense, and/or sell copies of the Software, and to
|
|
permit persons to whom the Software is furnished to do so, subject to
|
|
the following conditions:
|
|
|
|
The above copyright notice and this permission notice shall be included
|
|
in all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
|
|
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
-->
|
|
|
|
<para>
|
|
|
|
&SCons; provides a number of platform-independent functions,
|
|
called <literal>factories</literal>,
|
|
that perform common file system manipulations
|
|
like copying, moving or deleting files and directories,
|
|
or making directories.
|
|
These functions are <literal>factories</literal>
|
|
because they don't perform the action
|
|
at the time they're called,
|
|
they each return an &Action; object
|
|
that can be executed at the appropriate time.
|
|
|
|
</para>
|
|
|
|
<section>
|
|
<title>Copying Files or Directories: The &Copy; Factory</title>
|
|
|
|
<para>
|
|
|
|
Suppose you want to arrange to make a copy of a file,
|
|
and don't have a suitable pre-existing builder.
|
|
<footnote>
|
|
<para>
|
|
Unfortunately, in the early days of SCons design,
|
|
we used the name &Copy; for the function that
|
|
returns a copy of the environment,
|
|
otherwise that would be the logical choice for
|
|
a Builder that copies a file or directory tree
|
|
to a target location.
|
|
</para>
|
|
</footnote>
|
|
One way would be to use the &Copy; action factory
|
|
in conjunction with the &Command; builder:
|
|
|
|
</para>
|
|
|
|
<scons_example name="factories_Copy1">
|
|
<file name="SConstruct" printme="1">
|
|
Command("file.out", "file.in", Copy("$TARGET", "$SOURCE"))
|
|
</file>
|
|
<file name="file.in">file.in</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Notice that the action returned by the &Copy; factory
|
|
will expand the &cv-link-TARGET; and &cv-link-SOURCE; strings
|
|
at the time &file_out; is built,
|
|
and that the order of the arguments
|
|
is the same as that of a builder itself--that is,
|
|
target first, followed by source:
|
|
|
|
</para>
|
|
|
|
<scons_output example="factories_Copy1" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
You can, of course, name a file explicitly
|
|
instead of using &cv-TARGET; or &cv-SOURCE;:
|
|
|
|
</para>
|
|
|
|
<scons_example name="factories_Copy2">
|
|
<file name="SConstruct" printme="1">
|
|
Command("file.out", [], Copy("$TARGET", "file.in"))
|
|
</file>
|
|
<file name="file.in">file.in</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Which executes as:
|
|
|
|
</para>
|
|
|
|
<scons_output example="factories_Copy2" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
The usefulness of the &Copy; factory
|
|
becomes more apparent when
|
|
you use it in a list of actions
|
|
passed to the &Command; builder.
|
|
For example, suppose you needed to run a
|
|
file through a utility that only modifies files in-place,
|
|
and can't "pipe" input to output.
|
|
One solution is to copy the source file
|
|
to a temporary file name,
|
|
run the utility,
|
|
and then copy the modified temporary file to the target,
|
|
which the &Copy; factory makes extremely easy:
|
|
|
|
</para>
|
|
|
|
<scons_example name="factories_Copy3">
|
|
<file name="S" printme="1">
|
|
Command(
|
|
"file.out",
|
|
"file.in",
|
|
action=[
|
|
Copy("tempfile", "$SOURCE"),
|
|
"modify tempfile",
|
|
Copy("$TARGET", "tempfile"),
|
|
],
|
|
)
|
|
</file>
|
|
<!-- this is a non-displayed script that fiddles PATH to allow dummy "modify" command to work -->
|
|
<file name="SConstruct">
|
|
def_env = DefaultEnvironment()
|
|
def_env.AppendENVPath('PATH', Dir('.'))
|
|
SConscript('S')
|
|
</file>
|
|
<file name="file.in">file.in</file>
|
|
<file name="modify" chmod="0o755">
|
|
touch $*
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
The output then looks like:
|
|
|
|
</para>
|
|
|
|
<scons_output example="factories_Copy3" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
The &Copy; factory has a third optional argument which controls
|
|
how symlinks are copied.
|
|
</para>
|
|
|
|
<para>
|
|
</para>
|
|
|
|
<scons_example name="factories_SymlinkCopy">
|
|
<file name ="SymlinkCopy" printme="1">
|
|
# Symbolic link shallow copied as a new symbolic link:
|
|
Command("LinkIn", "LinkOut", Copy("$TARGET", "$SOURCE", symlinks=True))
|
|
|
|
# Symbolic link target copied as a file or directory:
|
|
Command("LinkIn", "FileOrDirectoryOut", Copy("$TARGET", "$SOURCE", symlinks=False))
|
|
</file>
|
|
</scons_example>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Deleting Files or Directories: The &Delete; Factory</title>
|
|
|
|
<para>
|
|
|
|
If you need to delete a file,
|
|
then the &Delete; factory
|
|
can be used in much the same way as
|
|
the &Copy; factory.
|
|
For example, if we want to make sure that
|
|
the temporary file
|
|
in our last example doesn't exist before
|
|
we copy to it,
|
|
we could add &Delete; to the beginning
|
|
of the command list:
|
|
|
|
</para>
|
|
|
|
<scons_example name="factories_Delete1">
|
|
<file name="S" printme="1">
|
|
Command(
|
|
"file.out",
|
|
"file.in",
|
|
action=[
|
|
Delete("tempfile"),
|
|
Copy("tempfile", "$SOURCE"),
|
|
"modify tempfile",
|
|
Copy("$TARGET", "tempfile"),
|
|
],
|
|
)
|
|
</file>
|
|
<!-- this is a non-displayed script that fiddles PATH to allow dummy "modify" command to work -->
|
|
<file name="SConstruct">
|
|
def_env = DefaultEnvironment()
|
|
def_env.AppendENVPath('PATH', Dir('.'))
|
|
SConscript('S')
|
|
</file>
|
|
<file name="file.in">file.in</file>
|
|
<file name="modify" chmod="0o755">
|
|
touch $*
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Which then executes as follows:
|
|
|
|
</para>
|
|
|
|
<scons_output example="factories_Delete1" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
Of course, like all of these &Action; factories,
|
|
the &Delete; factory also expands
|
|
&cv-link-TARGET; and &cv-link-SOURCE; variables appropriately.
|
|
For example:
|
|
|
|
</para>
|
|
|
|
<scons_example name="factories_Delete2">
|
|
<file name="SConstruct" printme="1">
|
|
Command(
|
|
"file.out",
|
|
"file.in",
|
|
action=[
|
|
Delete("$TARGET"),
|
|
Copy("$TARGET", "$SOURCE"),
|
|
],
|
|
)
|
|
</file>
|
|
<file name="file.in">file.in</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Executes as:
|
|
|
|
</para>
|
|
|
|
<scons_output example="factories_Delete2" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
Note, however, that you typically don't need to
|
|
call the &Delete; factory explicitly in this way;
|
|
by default, &SCons; deletes its target(s)
|
|
for you before executing any action.
|
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
One word of caution about using the &Delete; factory:
|
|
it has the same variable expansions available
|
|
as any other factory, including the &cv-SOURCE; variable.
|
|
Specifying <literal>Delete("$SOURCE")</literal>
|
|
is not something you usually want to do!
|
|
|
|
</para>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Moving (Renaming) Files or Directories: The &Move; Factory</title>
|
|
|
|
<para>
|
|
|
|
The &Move; factory
|
|
allows you to rename a file or directory.
|
|
For example, if we don't want to copy the temporary file,
|
|
we could use:
|
|
|
|
</para>
|
|
|
|
<scons_example name="factories_Move">
|
|
<file name="S" printme="1">
|
|
Command(
|
|
"file.out",
|
|
"file.in",
|
|
action=[
|
|
Copy("tempfile", "$SOURCE"),
|
|
"modify tempfile",
|
|
Move("$TARGET", "tempfile"),
|
|
],
|
|
)
|
|
</file>
|
|
<!-- this is a non-displayed script that fiddles PATH to allow dummy "modify" command to work -->
|
|
<file name="SConstruct">
|
|
def_env = DefaultEnvironment()
|
|
def_env.AppendENVPath('PATH', Dir('.'))
|
|
SConscript('S')
|
|
</file>
|
|
<file name="file.in">file.in</file>
|
|
<file name="modify" chmod="0o755">
|
|
touch $*
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Which would execute as:
|
|
|
|
</para>
|
|
|
|
<scons_output example="factories_Move" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Updating the Modification Time of a File: The &Touch; Factory</title>
|
|
|
|
<para>
|
|
|
|
If you just need to update the
|
|
recorded modification time for a file,
|
|
use the &Touch; factory:
|
|
|
|
</para>
|
|
|
|
<scons_example name="factories_Touch">
|
|
<file name="S" printme="1">
|
|
Command(
|
|
"file.out",
|
|
"file.in",
|
|
action=[
|
|
Copy("$TARGET", "$SOURCE"),
|
|
Touch("$TARGET"),
|
|
]
|
|
)
|
|
</file>
|
|
<file name="SConstruct">
|
|
SConscript('S')
|
|
</file>
|
|
<file name="file.in">file.in</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Which executes as:
|
|
|
|
</para>
|
|
|
|
<scons_output example="factories_Touch" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Creating a Directory: The &Mkdir; Factory</title>
|
|
|
|
<para>
|
|
|
|
If you need to create a directory,
|
|
use the &Mkdir; factory.
|
|
For example, if we need to process
|
|
a file in a temporary directory
|
|
in which the processing tool
|
|
will create other files that we don't care about,
|
|
you could use:
|
|
|
|
</para>
|
|
|
|
<scons_example name="factories_Mkdir">
|
|
<file name="S" printme="1">
|
|
Command(
|
|
"file.out",
|
|
"file.in",
|
|
action=[
|
|
Delete("tempdir"),
|
|
Mkdir("tempdir"),
|
|
Copy("tempdir/${SOURCE.file}", "$SOURCE"),
|
|
"process tempdir",
|
|
Move("$TARGET", "tempdir/output_file"),
|
|
Delete("tempdir"),
|
|
],
|
|
)
|
|
</file>
|
|
<!-- this is a non-displayed script that fiddles PATH to allow dummy "process" command to work -->
|
|
<file name="SConstruct">
|
|
def_env = DefaultEnvironment()
|
|
def_env.AppendENVPath('PATH', Dir('.'))
|
|
SConscript('S')
|
|
</file>
|
|
<file name="file.in">file.in</file>
|
|
<file name="process" chmod="0o755">
|
|
touch $*
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Which executes as:
|
|
|
|
</para>
|
|
|
|
<scons_output example="factories_Mkdir" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Changing File or Directory Permissions: The &Chmod; Factory</title>
|
|
|
|
<para>
|
|
|
|
To change permissions on a file or directory,
|
|
use the &Chmod; factory.
|
|
The permission argument uses POSIX-style
|
|
permission bits and should typically
|
|
be expressed as an octal,
|
|
not decimal, number:
|
|
|
|
</para>
|
|
|
|
<scons_example name="factories_Chmod">
|
|
<file name="SConstruct" printme="1">
|
|
Command(
|
|
"file.out",
|
|
"file.in",
|
|
action=[
|
|
Copy("$TARGET", "$SOURCE"),
|
|
Chmod("$TARGET", 0o755),
|
|
]
|
|
)
|
|
</file>
|
|
<file name="file.in">file.in</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Which executes:
|
|
|
|
</para>
|
|
|
|
<scons_output example="factories_Chmod" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Executing an action immediately: the &Execute; Function</title>
|
|
|
|
<para>
|
|
|
|
We've been showing you how to use &Action; factories
|
|
in the &Command; function.
|
|
You can also execute an &Action; returned by a factory
|
|
(or actually, any &Action;)
|
|
at the time the &SConscript; file is read
|
|
by using the &Execute; function.
|
|
For example, if we need to make sure that
|
|
a directory exists before we build any targets,
|
|
|
|
</para>
|
|
|
|
<scons_example name="factories_Execute">
|
|
<file name="SConstruct" printme="1">
|
|
Execute(Mkdir('__ROOT__/tmp/my_temp_directory'))
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Notice that this will
|
|
create the directory while
|
|
the &SConscript; file is being read:
|
|
|
|
</para>
|
|
|
|
<scons_output example="factories_Execute" suffix="1">
|
|
<scons_output_command>scons</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
If you're familiar with Python,
|
|
you may wonder why you would want to use this
|
|
instead of just calling the native Python
|
|
<function>os.mkdir()</function> function.
|
|
The advantage here is that the &Mkdir;
|
|
action will behave appropriately if the user
|
|
specifies the &SCons; <option>-n</option> or
|
|
<option>-q</option> options--that is,
|
|
it will print the action but not actually
|
|
make the directory when <option>-n</option> is specified,
|
|
or make the directory but not print the action
|
|
when <option>-q</option> is specified.
|
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
The &Execute; function returns the exit status
|
|
or return value of the underlying action being executed.
|
|
It will also print an error message if the action
|
|
fails and returns a non-zero value.
|
|
&SCons; will <emphasis>not</emphasis>, however,
|
|
actually stop the build if the action fails.
|
|
If you want the build to stop
|
|
in response to a failure in an action called by &Execute;,
|
|
you must do so by explicitly
|
|
checking the return value
|
|
and calling the &Exit; function
|
|
(or a Python equivalent):
|
|
|
|
</para>
|
|
|
|
<sconstruct>
|
|
if Execute(Mkdir('__ROOT__/tmp/my_temp_directory')):
|
|
# A problem occurred while making the temp directory.
|
|
Exit(1)
|
|
</sconstruct>
|
|
|
|
</section>
|
|
|
|
</chapter>
|