Internally, &SCons; represents all of the files
and directories it knows about as &Nodes;.
These internal objects
(not object files)
can be used in a variety of ways
to make your &SConscript;
files portable and easy to read.
Builder Methods Return Lists of Target Nodes
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 source files to other builder methods,
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:
Object('hello.c', CCFLAGS='-DHELLO')
Object('goodbye.c', CCFLAGS='-DGOODBYE')
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:
Object('hello.c', CCFLAGS='-DHELLO')
Object('goodbye.c', CCFLAGS='-DGOODBYE')
Program(['hello.o', 'goodbye.o'])
The problem with listing 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;.
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:
hello_list = Object('hello.c', CCFLAGS='-DHELLO')
goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE')
Program(hello_list + goodbye_list)
int main() { printf("Hello, world!\n"); }
int main() { printf("Goodbye, world!\n"); }
This makes our &SConstruct; file portable again,
the build output on Linux looking like:
scons -Q
And on Windows:
scons -Q
We'll see examples of using the list of nodes
returned by builder methods throughout
the rest of this guide.
Explicitly Creating File and Directory Nodes
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, repectively,
return a file or directory Node:
hello_c = File('hello.c')
Program(hello_c)
classes = Dir('classes')
Java(classes, 'src')
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.
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.
xyzzy = Entry('xyzzy')
The returned xyzzy 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.
Printing &Node; File Names
One of the most common things you can do
with a Node is use it to print the
file name that the node represents.
For example, the following &SConstruct; file:
object_list = Object('hello.c')
program_list = Program(object_list)
print "The object file is:", object_list[0]
print "The program file is:", program_list[0]
int main() { printf("Hello, world!\n"); }
Would print the following file names on a POSIX system:
scons -Q
And the following file names on a Windows system:
scons -Q
Using a &Node;'s File Name as a String
Printing a &Node;'s name
as described in the previous section
works because the string representation of a &Node;
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
os.path.exists
to figure out whether a file
exists while the &SConstruct; file
is being read and executed,
you can fetch the string as follows:
import os.path
program_list = Program('hello.c')
program_name = str(program_list[0])
if not os.path.exists(program_name):
print program_name, "does not exist!"
int main() { printf("Hello, world!\n"); }
Which executes as follows on a POSIX system:
scons -Q