mirror of
https://github.com/Relintai/scons_gd.git
synced 2025-04-23 22:03:22 +02:00
457 lines
11 KiB
XML
457 lines
11 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-nodes"
|
|
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>Node Objects</title>
|
|
|
|
<!--
|
|
|
|
MIT License
|
|
|
|
Copyright The SCons Foundation
|
|
|
|
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>
|
|
|
|
Internally, &SCons; represents all of the files
|
|
and directories it knows about as &Nodes;.
|
|
These internal objects
|
|
(not object <emphasis>files</emphasis>)
|
|
can be used in a variety of ways
|
|
to make your &SConscript;
|
|
files portable and easy to read.
|
|
|
|
</para>
|
|
|
|
<section>
|
|
<title>Builder Methods Return Lists of Target Nodes</title>
|
|
|
|
<para>
|
|
|
|
All builder methods return a list of
|
|
&Node; objects that identify the
|
|
target file or files that will be built.
|
|
These returned &Nodes; can be passed
|
|
as arguments to other builder methods.
|
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
For example, suppose that we want to build
|
|
the two object files that make up a program with different options.
|
|
This would mean calling the &b-link-Object;
|
|
builder once for each object file,
|
|
specifying the desired options:
|
|
|
|
</para>
|
|
|
|
<sconstruct>
|
|
Object('hello.c', CCFLAGS='-DHELLO')
|
|
Object('goodbye.c', CCFLAGS='-DGOODBYE')
|
|
</sconstruct>
|
|
|
|
<para>
|
|
|
|
One way to combine these object files
|
|
into the resulting program
|
|
would be to call the &b-link-Program;
|
|
builder with the names of the object files
|
|
listed as sources:
|
|
|
|
</para>
|
|
|
|
<sconstruct>
|
|
Object('hello.c', CCFLAGS='-DHELLO')
|
|
Object('goodbye.c', CCFLAGS='-DGOODBYE')
|
|
Program(['hello.o', 'goodbye.o'])
|
|
</sconstruct>
|
|
|
|
<para>
|
|
|
|
The problem with specifying the names as strings
|
|
is that our &SConstruct; file is no longer portable
|
|
across operating systems.
|
|
It won't, for example, work on Windows
|
|
because the object files there would be
|
|
named &hello_obj; and &goodbye_obj;,
|
|
not &hello_o; and &goodbye_o;.
|
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
A better solution is to assign the lists of targets
|
|
returned by the calls to the &b-Object; builder to variables,
|
|
which we can then concatenate in our
|
|
call to the &b-Program; builder:
|
|
|
|
</para>
|
|
|
|
<scons_example name="nodes_ex1">
|
|
<file name="SConstruct" printme="1">
|
|
hello_list = Object('hello.c', CCFLAGS='-DHELLO')
|
|
goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE')
|
|
Program(hello_list + goodbye_list)
|
|
</file>
|
|
<file name="hello.c">
|
|
int main() { printf("Hello, world!\n"); }
|
|
</file>
|
|
<file name="goodbye.c">
|
|
int main() { printf("Goodbye, world!\n"); }
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
This makes our &SConstruct; file portable again,
|
|
the build output on Linux looking like:
|
|
|
|
</para>
|
|
|
|
<scons_output example="nodes_ex1" os="posix" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
And on Windows:
|
|
|
|
</para>
|
|
|
|
<scons_output example="nodes_ex1" os="win32" suffix="2">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
We'll see examples of using the list of nodes
|
|
returned by builder methods throughout
|
|
the rest of this guide.
|
|
|
|
</para>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Explicitly Creating File and Directory Nodes</title>
|
|
|
|
<para>
|
|
|
|
It's worth mentioning here that
|
|
&SCons; maintains a clear distinction
|
|
between Nodes that represent files
|
|
and Nodes that represent directories.
|
|
&SCons; supports &File; and &Dir;
|
|
functions that, respectively,
|
|
return a file or directory Node:
|
|
|
|
</para>
|
|
|
|
<scons_example name="nodes_print">
|
|
<file name="SConstruct" printme="1">
|
|
hello_c = File('hello.c')
|
|
Program(hello_c)
|
|
|
|
classes = Dir('classes')
|
|
Java(classes, 'src')
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Normally, you don't need to call
|
|
&File; or &Dir; directly,
|
|
because calling a builder method automatically
|
|
treats strings as the names of files or directories,
|
|
and translates them into
|
|
the Node objects for you.
|
|
The &File; and &Dir; functions can come in handy
|
|
in situations where you need to explicitly
|
|
instruct &SCons; about the type of Node being
|
|
passed to a builder or other function,
|
|
or unambiguously refer to a specific
|
|
file in a directory tree.
|
|
<!--
|
|
(For an example of when you might
|
|
need to use &File; or &Dir; to
|
|
prevent ambiguous interpretation of a string
|
|
naming a file or directory, see
|
|
<xref linkend="chap-hierarchy">.)
|
|
-->
|
|
|
|
</para>
|
|
|
|
<para>
|
|
|
|
There are also times when you may need to
|
|
refer to an entry in a file system
|
|
without knowing in advance
|
|
whether it's a file or a directory.
|
|
For those situations,
|
|
&SCons; also supports an &Entry; function,
|
|
which returns a Node
|
|
that can represent either a file or a directory.
|
|
|
|
</para>
|
|
|
|
<sconstruct>
|
|
xyzzy = Entry('xyzzy')
|
|
</sconstruct>
|
|
|
|
<para>
|
|
|
|
The returned <literal>xyzzy</literal> Node
|
|
will be turned into a file or directory Node
|
|
the first time it is used by a builder method
|
|
or other function that
|
|
requires one vs. the other.
|
|
|
|
</para>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Printing &Node; File Names</title>
|
|
|
|
<para>
|
|
|
|
One of the most common things you can do
|
|
with a Node is use it to print the
|
|
file name that the node represents.
|
|
Keep in mind, though, that because the object
|
|
returned by a builder call
|
|
is a <emphasis>list</emphasis> of Nodes,
|
|
you must use Python subscripts
|
|
to fetch individual Nodes from the list.
|
|
For example, the following &SConstruct; file:
|
|
|
|
</para>
|
|
|
|
<scons_example name="nodes_print">
|
|
<file name="SConstruct" printme="1">
|
|
object_list = Object('hello.c')
|
|
program_list = Program(object_list)
|
|
print("The object file is: %s"%object_list[0])
|
|
print("The program file is: %s"%program_list[0])
|
|
</file>
|
|
<file name="hello.c">
|
|
int main() { printf("Hello, world!\n"); }
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Would print the following file names on a POSIX system:
|
|
|
|
</para>
|
|
|
|
<scons_output example="nodes_print" os="posix" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
And the following file names on a Windows system:
|
|
|
|
</para>
|
|
|
|
<scons_output example="nodes_print" os="win32" suffix="2">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
Note that in the above example,
|
|
the <literal>object_list[0]</literal>
|
|
extracts an actual Node <emphasis>object</emphasis>
|
|
from the list,
|
|
and the Python <function>print</function> function
|
|
converts the object to a string for printing.
|
|
|
|
</para>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>Using a &Node;'s File Name as a String</title>
|
|
|
|
<para>
|
|
|
|
Printing a &Node;'s name
|
|
as described in the previous section
|
|
works because the string representation of a &Node; object
|
|
is the name of the file.
|
|
If you want to do something other than
|
|
print the name of the file,
|
|
you can fetch it by using the builtin Python
|
|
&str; function.
|
|
For example, if you want to use the Python
|
|
<function>os.path.exists</function>
|
|
to figure out whether a file
|
|
exists while the &SConstruct; file
|
|
is being read and executed,
|
|
you can fetch the string as follows:
|
|
|
|
</para>
|
|
|
|
<scons_example name="nodes_exists">
|
|
<file name="SConstruct" printme="1">
|
|
import os.path
|
|
program_list = Program('hello.c')
|
|
program_name = str(program_list[0])
|
|
if not os.path.exists(program_name):
|
|
print("%s does not exist!"%program_name)
|
|
</file>
|
|
<file name="hello.c">
|
|
int main() { printf("Hello, world!\n"); }
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Which executes as follows on a POSIX system:
|
|
|
|
</para>
|
|
|
|
<scons_output example="nodes_exists" os="posix" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
</section>
|
|
|
|
<section>
|
|
<title>&GetBuildPath;: Getting the Path From a &Node; or String</title>
|
|
|
|
<para>
|
|
|
|
<function>env.GetBuildPath(file_or_list)</function>
|
|
returns the path of a &Node; or a string representing a
|
|
path. It can also take a list of &Node;s and/or strings, and
|
|
returns the list of paths. If passed a single &Node;, the result
|
|
is the same as calling <literal>str(node)</literal> (see above).
|
|
The string(s) can have embedded construction variables, which are
|
|
expanded as usual, using the calling environment's set of
|
|
variables. The paths can be files or directories, and do not have
|
|
to exist.
|
|
|
|
</para>
|
|
|
|
<scons_example name="nodes_GetBuildPath">
|
|
<file name="SConstruct" printme="1">
|
|
env=Environment(VAR="value")
|
|
n=File("foo.c")
|
|
print(env.GetBuildPath([n, "sub/dir/$VAR"]))
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Would print the following file names:
|
|
|
|
</para>
|
|
|
|
<scons_output example="nodes_GetBuildPath" os="posix" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
<para>
|
|
|
|
There is also a function version of &GetBuildPath; which can
|
|
be called without an &Environment;; that uses the default SCons
|
|
&Environment; to do substitution on any string arguments.
|
|
|
|
</para>
|
|
|
|
</section>
|
|
|
|
<!--
|
|
|
|
<section>
|
|
<title>Fetching the Contents of a &Node;</title>
|
|
|
|
<para>
|
|
|
|
XXX Describe using read() and readlines()
|
|
when we add that as a public interface.
|
|
|
|
</para>
|
|
|
|
<scons_example name="nodes_read">
|
|
<file name="SConstruct" printme="1">
|
|
hello_c = File('hello.c')
|
|
contents = hello_c.read()
|
|
print("contents are:")
|
|
print(contents)
|
|
</file>
|
|
<file name="hello.c">
|
|
int main() { printf("Hello, world!\n"); }
|
|
</file>
|
|
</scons_example>
|
|
|
|
<para>
|
|
|
|
Which executes as follows on a POSIX system:
|
|
|
|
</para>
|
|
|
|
<scons_output example="nodes_read" os="posix" suffix="1">
|
|
<scons_output_command>scons -Q</scons_output_command>
|
|
</scons_output>
|
|
|
|
</section>
|
|
|
|
-->
|
|
|
|
<!--
|
|
|
|
<section>
|
|
<title>Python Value &Node;</title>
|
|
|
|
<para>
|
|
|
|
XXX Value()
|
|
|
|
</para>
|
|
|
|
</section>
|
|
|
|
-->
|
|
|
|
</chapter>
|