scons/scons-user.html

30070 lines
500 KiB
HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<HTML
><HEAD
><TITLE
>SCons User Guide 0.96.91</TITLE
><META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.7"></HEAD
><BODY
CLASS="BOOK"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="BOOK"
><A
NAME="AEN1"
></A
><DIV
CLASS="TITLEPAGE"
><H1
CLASS="TITLE"
><A
NAME="AEN2"
>SCons User Guide 0.96.91</A
></H1
><H3
CLASS="AUTHOR"
><A
NAME="AEN4"
></A
>Steven Knight</H3
><P
CLASS="COPYRIGHT"
>Copyright &copy; 2004 Steven Knight</P
><DIV
CLASS="LEGALNOTICE"
><P
></P
><A
NAME="AEN12"
></A
><A
NAME="AEN13"
></A
><BLOCKQUOTE
CLASS="BLOCKQUOTE"
><P
>&#13; SCons User's Guide Copyright (c) 2004 Steven Knight
</P
></BLOCKQUOTE
><P
></P
></DIV
><SPAN
CLASS="RELEASEINFO"
>version 0.96.91<BR></SPAN
><HR></DIV
><DIV
CLASS="TOC"
><DL
><DT
><B
>Table of Contents</B
></DT
><DT
><A
HREF="#CHAP-PREFACE"
>Preface</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN29"
><TT
CLASS="APPLICATION"
>SCons</TT
> Principles</A
></DT
><DT
><A
HREF="#AEN54"
>A Caveat About This Guide's Completeness</A
></DT
><DT
><A
HREF="#AEN62"
>Acknowledgements</A
></DT
><DT
><A
HREF="#AEN83"
>Contact</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-BUILD-INSTALL"
>Building and Installing <TT
CLASS="APPLICATION"
>SCons</TT
></A
></DT
><DD
><DL
><DT
><A
HREF="#AEN102"
>Installing Python</A
></DT
><DT
><A
HREF="#AEN124"
>Installing <TT
CLASS="APPLICATION"
>SCons</TT
> From Pre-Built Packages</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN129"
>Installing <TT
CLASS="APPLICATION"
>SCons</TT
> on Red Hat (and Other RPM-based) Linux Systems</A
></DT
><DT
><A
HREF="#AEN149"
>Installing <TT
CLASS="APPLICATION"
>SCons</TT
> on Debian Linux Systems</A
></DT
><DT
><A
HREF="#AEN157"
>Installing <TT
CLASS="APPLICATION"
>SCons</TT
> on Windows Systems</A
></DT
></DL
></DD
><DT
><A
HREF="#AEN166"
>Building and Installing <TT
CLASS="APPLICATION"
>SCons</TT
> on Any System</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN194"
>Building and Installing Multiple Versions of <TT
CLASS="APPLICATION"
>SCons</TT
> Side-by-Side</A
></DT
><DT
><A
HREF="#AEN218"
>Installing <TT
CLASS="APPLICATION"
>SCons</TT
> in Other Locations</A
></DT
><DT
><A
HREF="#AEN236"
>Building and Installing <TT
CLASS="APPLICATION"
>SCons</TT
> Without Administrative Privileges</A
></DT
></DL
></DD
></DL
></DD
><DT
><A
HREF="#CHAP-SIMPLE"
>Simple Builds</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN256"
>Building Simple C / C++ Programs</A
></DT
><DT
><A
HREF="#AEN288"
>Building Object Files</A
></DT
><DT
><A
HREF="#AEN307"
>Simple Java Builds</A
></DT
><DT
><A
HREF="#AEN328"
>Cleaning Up After a Build</A
></DT
><DT
><A
HREF="#AEN348"
>The <TT
CLASS="FILENAME"
>SConstruct</TT
> File</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN358"
><TT
CLASS="FILENAME"
>SConstruct</TT
> Files Are Python Scripts</A
></DT
><DT
><A
HREF="#AEN370"
><TT
CLASS="APPLICATION"
>SCons</TT
> Functions Are Order-Independent</A
></DT
></DL
></DD
><DT
><A
HREF="#AEN420"
>Making the <TT
CLASS="APPLICATION"
>SCons</TT
> Output Less Verbose</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-LESS-SIMPLE"
>Less Simple Things to Do With Builds</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN443"
>Specifying the Name of the Target (Output) File</A
></DT
><DT
><A
HREF="#AEN467"
>Compiling Multiple Source Files</A
></DT
><DT
><A
HREF="#AEN489"
>Specifying Single Files Vs. Lists of Files</A
></DT
><DT
><A
HREF="#AEN507"
>Making Lists of Files Easier to Read</A
></DT
><DT
><A
HREF="#AEN533"
>Keyword Arguments</A
></DT
><DT
><A
HREF="#AEN544"
>Compiling Multiple Programs</A
></DT
><DT
><A
HREF="#AEN558"
>Sharing Source Files Between Multiple Programs</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-LIBRARIES"
>Building and Linking with Libraries</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN578"
>Building Libraries</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN597"
>Building Static Libraries Explicitly: the <TT
CLASS="FUNCTION"
>StaticLibrary</TT
> Builder</A
></DT
><DT
><A
HREF="#AEN611"
>Building Shared (DLL) Libraries: the <TT
CLASS="FUNCTION"
>SharedLibrary</TT
> Builder</A
></DT
></DL
></DD
><DT
><A
HREF="#AEN628"
>Linking with Libraries</A
></DT
><DT
><A
HREF="#AEN655"
>Finding Libraries: the <VAR
CLASS="ENVAR"
>$LIBPATH</VAR
> Construction Variable</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-NODES"
>Node Objects</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN686"
>Builder Methods Return Lists of Target Nodes</A
></DT
><DT
><A
HREF="#AEN717"
>Explicitly Creating File and Directory Nodes</A
></DT
><DT
><A
HREF="#AEN737"
>Printing <CODE
CLASS="CLASSNAME"
>Node</CODE
> File Names</A
></DT
><DT
><A
HREF="#AEN749"
>Using a <CODE
CLASS="CLASSNAME"
>Node</CODE
>'s File Name as a String</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-DEPENDS"
>Dependencies</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN785"
>Deciding When a Source File Has Changed: the <TT
CLASS="FUNCTION"
>SourceSignatures</TT
> Function</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN792"
>MD5 Source File Signatures</A
></DT
><DT
><A
HREF="#AEN816"
>Source File Time Stamps</A
></DT
></DL
></DD
><DT
><A
HREF="#AEN830"
>Deciding When a Target File Has Changed: the <TT
CLASS="FUNCTION"
>TargetSignatures</TT
> Function</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN836"
>Build Signatures</A
></DT
><DT
><A
HREF="#AEN856"
>File Contents</A
></DT
></DL
></DD
><DT
><A
HREF="#AEN874"
>Implicit Dependencies: The <VAR
CLASS="ENVAR"
>$CPPPATH</VAR
> Construction Variable</A
></DT
><DT
><A
HREF="#AEN931"
>Caching Implicit Dependencies</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN950"
>The <TT
CLASS="LITERAL"
>--implicit-deps-changed</TT
> Option</A
></DT
><DT
><A
HREF="#AEN962"
>The <TT
CLASS="LITERAL"
>--implicit-deps-unchanged</TT
> Option</A
></DT
></DL
></DD
><DT
><A
HREF="#AEN975"
>Ignoring Dependencies: the <TT
CLASS="FUNCTION"
>Ignore</TT
> Method</A
></DT
><DT
><A
HREF="#AEN995"
>Explicit Dependencies: the <TT
CLASS="FUNCTION"
>Depends</TT
> Method</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-ENVIRONMENTS"
>Construction Environments</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN1035"
>Multiple <TT
CLASS="LITERAL"
>Construction Environments</TT
></A
></DT
><DT
><A
HREF="#AEN1075"
>Copying <TT
CLASS="LITERAL"
>Construction Environments</TT
></A
></DT
><DT
><A
HREF="#AEN1095"
>Fetching Values From a <TT
CLASS="LITERAL"
>Construction Environment</TT
></A
></DT
><DT
><A
HREF="#AEN1118"
>Expanding Values From a <TT
CLASS="LITERAL"
>Construction Environment</TT
></A
></DT
><DT
><A
HREF="#AEN1148"
>Modifying a <TT
CLASS="LITERAL"
>Construction Environment</TT
></A
></DT
><DD
><DL
><DT
><A
HREF="#AEN1153"
>Replacing Values in a <TT
CLASS="LITERAL"
>Construction Environment</TT
></A
></DT
><DT
><A
HREF="#AEN1185"
>Appending to the End of Values in a <TT
CLASS="LITERAL"
>Construction Environment</TT
></A
></DT
><DT
><A
HREF="#AEN1203"
>Appending to the Beginning of Values in a <TT
CLASS="LITERAL"
>Construction Environment</TT
></A
></DT
></DL
></DD
></DL
></DD
><DT
><A
HREF="#CHAP-ENV"
>Controlling the External Environment Used to Execute Build Commands</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN1252"
>Propagating <VAR
CLASS="VARNAME"
>PATH</VAR
> From the External Environment</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-COMMAND-LINE"
>Controlling a Build From the Command Line</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN1276"
>Not Having to Specify Command-Line Options Each Time: the <VAR
CLASS="VARNAME"
>SCONSFLAGS</VAR
> Environment Variable</A
></DT
><DT
><A
HREF="#AEN1301"
>Getting at Command-Line Targets</A
></DT
><DT
><A
HREF="#AEN1317"
>Controlling the Default Targets</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN1367"
>Getting at the List of Default Targets</A
></DT
></DL
></DD
><DT
><A
HREF="#AEN1398"
>Getting at the List of Build Targets, Regardless of Origin</A
></DT
><DT
><A
HREF="#AEN1423"
>Command-Line <VAR
CLASS="VARNAME"
>variable</VAR
>=<VAR
CLASS="VARNAME"
>value</VAR
> Build Options</A
></DT
><DT
><A
HREF="#AEN1457"
>Controlling Command-Line Build Options</A
></DT
><DT
><A
HREF="#AEN1483"
>Providing Help for Command-Line Build Options</A
></DT
><DT
><A
HREF="#AEN1498"
>Reading Build Options From a File</A
></DT
><DT
><A
HREF="#AEN1520"
>Canned Build Options</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN1524"
>True/False Values: the <TT
CLASS="FUNCTION"
>BoolOption</TT
> Build Option</A
></DT
><DT
><A
HREF="#AEN1573"
>Single Value From a List: the <TT
CLASS="FUNCTION"
>EnumOption</TT
> Build Option</A
></DT
><DT
><A
HREF="#AEN1638"
>Multiple Values From a List: the <TT
CLASS="FUNCTION"
>ListOption</TT
> Build Option</A
></DT
><DT
><A
HREF="#AEN1660"
>Path Names: the <TT
CLASS="FUNCTION"
>PathOption</TT
> Build Option</A
></DT
><DT
><A
HREF="#AEN1689"
>Enabled/Disabled Path Names: the <TT
CLASS="FUNCTION"
>PackageOption</TT
> Build Option</A
></DT
></DL
></DD
><DT
><A
HREF="#AEN1706"
>Adding Multiple Command-Line Build Options at Once</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-HELP"
>Providing Build Help: the <TT
CLASS="FUNCTION"
>Help</TT
> Function</A
></DT
><DT
><A
HREF="#CHAP-INSTALL"
>Installing Files in Other Directories: the <TT
CLASS="FUNCTION"
>Install</TT
> Builder</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN1775"
>Installing Multiple Files in a Directory</A
></DT
><DT
><A
HREF="#AEN1785"
>Installing a File Under a Different Name</A
></DT
><DT
><A
HREF="#AEN1796"
>Installing Multiple Files Under Different Names</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-FACTORIES"
>Platform-Independent File System Manipulation</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN1812"
>Copying Files or Directories: The <TT
CLASS="FUNCTION"
>Copy</TT
> Factory</A
></DT
><DT
><A
HREF="#AEN1842"
>Deleting Files or Directories: The <TT
CLASS="FUNCTION"
>Delete</TT
> Factory</A
></DT
><DT
><A
HREF="#AEN1865"
>Moving (Renaming) Files or Directories: The <TT
CLASS="FUNCTION"
>Move</TT
> Factory</A
></DT
><DT
><A
HREF="#AEN1874"
>Updating the Modification Time of a File: The <TT
CLASS="FUNCTION"
>Touch</TT
> Factory</A
></DT
><DT
><A
HREF="#AEN1883"
>Creating a Directory: The <TT
CLASS="FUNCTION"
>Mkdir</TT
> Factory</A
></DT
><DT
><A
HREF="#AEN1892"
>Changing File or Directory Permissions: The <TT
CLASS="FUNCTION"
>Chmod</TT
> Factory</A
></DT
><DT
><A
HREF="#AEN1901"
>Executing an action immediately: the <TT
CLASS="FUNCTION"
>Execute</TT
> Function</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-PRECIOUS"
>Preventing Removal of Targets: the <TT
CLASS="FUNCTION"
>Precious</TT
> Function</A
></DT
><DT
><A
HREF="#CHAP-HIERARCHICAL"
>Hierarchical Builds</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN1945"
><TT
CLASS="FILENAME"
>SConscript</TT
> Files</A
></DT
><DT
><A
HREF="#AEN1973"
>Path Names Are Relative to the <TT
CLASS="FILENAME"
>SConscript</TT
> Directory</A
></DT
><DT
><A
HREF="#AEN1999"
>Top-Level Path Names in Subsidiary <TT
CLASS="FILENAME"
>SConscript</TT
> Files</A
></DT
><DT
><A
HREF="#AEN2020"
>Absolute Path Names</A
></DT
><DT
><A
HREF="#AEN2030"
>Sharing Environments (and Other Variables) Between <TT
CLASS="FILENAME"
>SConscript</TT
> Files</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN2042"
>Exporting Variables</A
></DT
><DT
><A
HREF="#AEN2070"
>Importing Variables</A
></DT
><DT
><A
HREF="#AEN2093"
>Returning Values From an <TT
CLASS="FILENAME"
>SConscript</TT
> File</A
></DT
></DL
></DD
></DL
></DD
><DT
><A
HREF="#CHAP-SEPARATE"
>Separating Source and Build Directories</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN2122"
>Specifying a Build Directory as Part of an <TT
CLASS="FILENAME"
>SConscript</TT
> Call</A
></DT
><DT
><A
HREF="#AEN2152"
>Why <TT
CLASS="APPLICATION"
>SCons</TT
> Duplicates Source Files in a Build Directory</A
></DT
><DT
><A
HREF="#AEN2169"
>Telling <TT
CLASS="APPLICATION"
>SCons</TT
> to Not Duplicate Source Files in the Build Directory</A
></DT
><DT
><A
HREF="#AEN2185"
>The <TT
CLASS="FUNCTION"
>BuildDir</TT
> Function</A
></DT
><DT
><A
HREF="#AEN2214"
>Using <TT
CLASS="FUNCTION"
>BuildDir</TT
> With an <TT
CLASS="FILENAME"
>SConscript</TT
> File</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-VARIANTS"
>Variant Builds</A
></DT
><DT
><A
HREF="#CHAP-BUILDERS-WRITING"
>Writing Your Own Builders</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN2257"
>Writing Builders That Execute External Commands</A
></DT
><DT
><A
HREF="#AEN2266"
>Attaching a Builder to a <TT
CLASS="LITERAL"
>Construction Environment</TT
></A
></DT
><DT
><A
HREF="#AEN2322"
>Letting <TT
CLASS="APPLICATION"
>SCons</TT
> Handle The File Suffixes</A
></DT
><DT
><A
HREF="#AEN2343"
>Builders That Execute Python Functions</A
></DT
><DT
><A
HREF="#AEN2379"
>Builders That Create Actions Using a <TT
CLASS="LITERAL"
>Generator</TT
></A
></DT
><DT
><A
HREF="#AEN2422"
>Builders That Modify the Target or Source Lists Using an <TT
CLASS="LITERAL"
>Emitter</TT
></A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-BUILDERS-COMMANDS"
>Not Writing a Builder: the <TT
CLASS="FUNCTION"
>Command</TT
> Builder</A
></DT
><DT
><A
HREF="#CHAP-SCANNERS"
>Writing Scanners</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN2464"
>A Simple Scanner Example</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-REPOSITORIES"
>Building From Code Repositories</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN2515"
>The <TT
CLASS="FUNCTION"
>Repository</TT
> Method</A
></DT
><DT
><A
HREF="#AEN2527"
>Finding source files in repositories</A
></DT
><DT
><A
HREF="#AEN2559"
>Finding the <TT
CLASS="FILENAME"
>SConstruct</TT
> file in repositories</A
></DT
><DT
><A
HREF="#AEN2577"
>Finding derived files in repositories</A
></DT
><DT
><A
HREF="#AEN2604"
>Guaranteeing local copies of files</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-SCONF"
>Multi-Platform Configuration (<TT
CLASS="APPLICATION"
>Autoconf</TT
> Functionality)</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN2638"
><TT
CLASS="LITERAL"
>Configure Contexts</TT
></A
></DT
><DT
><A
HREF="#AEN2654"
>Checking for the Existence of Header Files</A
></DT
><DT
><A
HREF="#AEN2663"
>Checking for the Availability of a Function</A
></DT
><DT
><A
HREF="#AEN2668"
>Checking for the Availability of a Library</A
></DT
><DT
><A
HREF="#AEN2683"
>Checking for the Availability of a <TT
CLASS="LITERAL"
>typedef</TT
></A
></DT
><DT
><A
HREF="#AEN2694"
>Adding Your Own Custom Checks</A
></DT
><DT
><A
HREF="#AEN2723"
>Not Configuring When Cleaning Targets</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-CACHING"
>Caching Built Files</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN2739"
>Specifying the Shared Cache Directory</A
></DT
><DT
><A
HREF="#AEN2753"
>Keeping Build Output Consistent</A
></DT
><DT
><A
HREF="#AEN2766"
>Not Retrieving Files From a Shared Cache</A
></DT
><DT
><A
HREF="#AEN2778"
>Populating a Shared Cache With Already-Built Files</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-ALIAS"
>Alias Targets</A
></DT
><DT
><A
HREF="#CHAP-JAVA"
>Java Builds</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN2827"
>Building Java Class Files: the <TT
CLASS="FUNCTION"
>Java</TT
> Builder</A
></DT
><DT
><A
HREF="#AEN2851"
>How <TT
CLASS="APPLICATION"
>SCons</TT
> Handles Java Dependencies</A
></DT
><DT
><A
HREF="#AEN2878"
>Building Java Archive (<TT
CLASS="FILENAME"
>.jar</TT
>) Files: the <TT
CLASS="FUNCTION"
>Jar</TT
> Builder</A
></DT
><DT
><A
HREF="#AEN2909"
>Building C Header and Stub Files: the <TT
CLASS="FUNCTION"
>JavaH</TT
> Builder</A
></DT
><DT
><A
HREF="#AEN2963"
>Building RMI Stub and Skeleton Class Files: the <TT
CLASS="FUNCTION"
>RMIC</TT
> Builder</A
></DT
></DL
></DD
><DT
><A
HREF="#CHAP-TROUBLESHOOTING"
>Troubleshooting</A
></DT
><DD
><DL
><DT
><A
HREF="#AEN2991"
>Why is That Target Being Rebuilt? the <TT
CLASS="LITERAL"
>--debug=explain</TT
> Option</A
></DT
><DT
><A
HREF="#AEN3037"
>What's in That Construction Environment? the <TT
CLASS="FUNCTION"
>Dump</TT
> Method</A
></DT
></DL
></DD
><DT
><A
HREF="#APP-VARIABLES"
>Construction Variables</A
></DT
><DT
><A
HREF="#APP-BUILDERS"
>Builders</A
></DT
><DT
><A
HREF="#APP-TOOLS"
>Tools</A
></DT
><DT
><A
HREF="#APP-TASKS"
>Handling Common Tasks</A
></DT
></DL
></DIV
><DIV
CLASS="PREFACE"
><HR><H1
><A
NAME="CHAP-PREFACE"
></A
>Preface</H1
><P
>&#13; Thank you for taking the time to read about <TT
CLASS="APPLICATION"
>SCons</TT
>.
<TT
CLASS="APPLICATION"
>SCons</TT
> is a next-generation
software construction tool,
or make tool--that is, a software utility
for building software (or other files)
and keeping built software up-to-date
whenever the underlying input files change.
</P
><P
>&#13; The most distinctive thing about <TT
CLASS="APPLICATION"
>SCons</TT
>
is that its configuration files are
actually <I
CLASS="EMPHASIS"
>scripts</I
>,
written in the <TT
CLASS="APPLICATION"
>Python</TT
> programming language.
This is in contrast to most alternative build tools,
which typically invent a new language to
configure the build.
<TT
CLASS="APPLICATION"
>SCons</TT
> still has a learning curve, of course,
because you have to know what functions to call
to set up your build properly,
but the underlying syntax used should be familiar
to anyone who has ever looked at a Python script.
</P
><P
>&#13; Paradoxically,
using Python as the configuration file format
makes <TT
CLASS="APPLICATION"
>SCons</TT
>
<I
CLASS="EMPHASIS"
>easier</I
>
for non-programmers to learn
than the cryptic languages of other build tools,
which are usually invented by programmers for other programmers.
This is in no small part due to the
consistency and readability that are built in to Python.
It just so happens that making a real, live
scripting language the basis for the
configuration files
makes it a snap for more accomplished programmers
to do more complicated things with builds,
as necessary.
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN29"
><TT
CLASS="APPLICATION"
>SCons</TT
> Principles</A
></H2
><P
>&#13; There are a few overriding principles
we try to live up to in designing and implementing <TT
CLASS="APPLICATION"
>SCons</TT
>:
</P
><P
></P
><DIV
CLASS="VARIABLELIST"
><DL
><DT
>Correctness</DT
><DD
><P
>&#13; First and foremost,
by default, <TT
CLASS="APPLICATION"
>SCons</TT
> guarantees a correct build
even if it means sacrificing performance a little.
We strive to guarantee the build is correct
regardless of how the software being built is structured,
how it may have been written,
or how unusual the tools are that build it.
</P
></DD
><DT
>Performance</DT
><DD
><P
>&#13; Given that the build is correct,
we try to make <TT
CLASS="APPLICATION"
>SCons</TT
> build software
as quickly as possible.
In particular, wherever we may have needed to slow
down the default <TT
CLASS="APPLICATION"
>SCons</TT
> behavior to guarantee a correct build,
we also try to make it easy to speed up <TT
CLASS="APPLICATION"
>SCons</TT
>
through optimization options that let you trade off
guaranteed correctness in all end cases for
a speedier build in the usual cases.
</P
></DD
><DT
>Convenience</DT
><DD
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> tries to do as much for you out of the box as reasonable,
including detecting the right tools on your system
and using them correctly to build the software.
</P
></DD
></DL
></DIV
><P
>&#13; In a nutshell, we try hard to make <TT
CLASS="APPLICATION"
>SCons</TT
> just
"do the right thing" and build software correctly,
with a minimum of hassles.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN54"
>A Caveat About This Guide's Completeness</A
></H2
><P
>&#13; One word of warning as you read through this Guide:
Like too much Open Source software out there,
the <TT
CLASS="APPLICATION"
>SCons</TT
> documentation isn't always
kept up-to-date with the available features.
In other words,
there's a lot that <TT
CLASS="APPLICATION"
>SCons</TT
> can do that
isn't yet covered in this User's Guide.
(Come to think of it,
that also describes a lot of proprietary software, doesn't it?)
</P
><P
>&#13; Although this User's Guide isn't as complete as we'd like it to be,
our development process does emphasize
making sure that the <TT
CLASS="APPLICATION"
>SCons</TT
> man page is kept up-to-date
with new features.
So if you're trying to figure out how to do something
that <TT
CLASS="APPLICATION"
>SCons</TT
> supports
but can't find enough (or any) information here,
it would be worth your while to look
at the man page to see if the information is covered there.
And if you do,
maybe you'd even consider contributing
a section to the User's Guide
so the next person looking for
that information won't have to
go through the same thing...?
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN62"
>Acknowledgements</A
></H2
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> would not exist without a lot of help
from a lot of people,
many of whom may not even be aware
that they helped or served as inspiration.
So in no particular order,
and at the risk of leaving out someone:
</P
><P
>&#13; First and foremost,
<TT
CLASS="APPLICATION"
>SCons</TT
> owes a tremendous debt to Bob Sidebotham,
the original author of the classic Perl-based <TT
CLASS="APPLICATION"
>Cons</TT
> tool
which Bob first released to the world back around 1996.
Bob's work on Cons classic provided the underlying architecture
and model of specifying a build configuration
using a real scripting language.
My real-world experience working on Cons
informed many of the design decisions in SCons,
including the improved parallel build support,
making Builder objects easily definable by users,
and separating the build engine from the wrapping interface.
</P
><P
>&#13; Greg Wilson was instrumental in getting
<TT
CLASS="APPLICATION"
>SCons</TT
> started as a real project
when he initiated the Software Carpentry design
competition in February 2000.
Without that nudge,
marrying the advantages of the Cons classic
architecture with the readability of Python
might have just stayed no more than a nice idea.
</P
><P
>&#13; The entire <TT
CLASS="APPLICATION"
>SCons</TT
> team have been
absolutely wonderful to work with,
and <TT
CLASS="APPLICATION"
>SCons</TT
> would be nowhere near as useful a
tool without the energy, enthusiasm
and time people have contributed over the past few years.
The "core team"
of Chad Austin, Anthony Roach, Charles Crain,
Steve Leblanc, Gary Oberbrunner, Greg Spencer and Christoph Wiedemann
have been great about reviewing my (and other) changes
and catching problems before they get in the code base.
Of particular technical note:
Anthony's outstanding and innovative work on the tasking engine
has given <TT
CLASS="APPLICATION"
>SCons</TT
> a vastly superior parallel build model;
Charles has been the master of the crucial Node infrastructure;
Christoph's work on the Configure infrastructure
has added crucial Autoconf-like functionality;
and Greg has provided excellent support
for Microsoft Visual Studio.
</P
><P
>&#13; Special thanks to David Snopek for contributing
his underlying "Autoscons" code that formed
the basis of Christoph's work with the Configure functionality.
David was extremely generous in making
this code available to <TT
CLASS="APPLICATION"
>SCons</TT
>,
given that he initially released it under the GPL
and <TT
CLASS="APPLICATION"
>SCons</TT
> is released under a less-restrictive MIT-style license.
</P
><P
>&#13; Thanks to Peter Miller
for his splendid change management system, <TT
CLASS="APPLICATION"
>Aegis</TT
>,
which has provided the <TT
CLASS="APPLICATION"
>SCons</TT
> project
with a robust development methodology from day one,
and which showed me how you could
integrate incremental regression tests into
a practical development cycle
(years before eXtreme Programming arrived on the scene).
</P
><P
>&#13; And last, thanks to Guido van Rossum
for his elegant scripting language,
which is the basis not only for the <TT
CLASS="APPLICATION"
>SCons</TT
> implementation,
but for the interface itself.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN83"
>Contact</A
></H2
><P
>&#13; The best way to contact people involved with SCons,
including the author,
is through the SCons mailing lists.
</P
><P
>&#13; If you want to ask general questions about how to use <TT
CLASS="APPLICATION"
>SCons</TT
>
send email to <TT
CLASS="LITERAL"
>users@scons.tigris.org</TT
>.
</P
><P
>&#13; If you want to contact the <TT
CLASS="APPLICATION"
>SCons</TT
> development community directly,
send email to <TT
CLASS="LITERAL"
>dev@scons.tigris.org</TT
>.
</P
><P
>&#13; If you want to receive announcements about <TT
CLASS="APPLICATION"
>SCons</TT
>,
join the low-volume <TT
CLASS="LITERAL"
>announce@scons.tigris.org</TT
> mailing list.
</P
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-BUILD-INSTALL"
></A
>Building and Installing <TT
CLASS="APPLICATION"
>SCons</TT
></H1
><P
>&#13; This chapter will take you through the basic steps
of installing <TT
CLASS="APPLICATION"
>SCons</TT
> on your system,
and building <TT
CLASS="APPLICATION"
>SCons</TT
> if you don't have a
pre-built package available
(or simply prefer the flexibility of building it yourself).
Before that, however, this chapter will also describe the basic steps
involved in installing Python on your system,
in case that is necessary.
Fortunately, both <TT
CLASS="APPLICATION"
>SCons</TT
> and Python
are very easy to install on almost any system,
and Python already comes installed on many systems.
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN102"
>Installing Python</A
></H2
><P
>&#13; Because <TT
CLASS="APPLICATION"
>SCons</TT
> is written in Python,
you must obviously have Python installed on your system
to use <TT
CLASS="APPLICATION"
>SCons</TT
>
Before you try to install Python,
you should check to see if Python is already
available on your system by typing
<KBD
CLASS="USERINPUT"
>python</KBD
>
at your system's command-line prompt.
You should see something like the following
on a UNIX or Linux system that has Python installed:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> $ <KBD
CLASS="USERINPUT"
>python</KBD
>
Python 2.2.2 (#1, Feb 24 2003, 19:13:11)
[GCC 3.2.2 20030222 (Red Hat Linux 3.2.2-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
&#62;&#62;&#62; <KBD
CLASS="USERINPUT"
>^D</KBD
>
</PRE
></TD
></TR
></TABLE
><P
>&#13; And on a Windows system with Python installed:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>python</KBD
>
Python 2.2.2 (#34, Apr 9 2002, 19:34:33) [MSC 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
&#62;&#62;&#62; <KBD
CLASS="USERINPUT"
>^Z</KBD
>
</PRE
></TD
></TR
></TABLE
><P
>&#13; The <TT
CLASS="PROMPT"
>&#62;&#62;&#62;</TT
> is the input prompt
for the Python interpreter.
The <KBD
CLASS="USERINPUT"
>^D</KBD
> and <KBD
CLASS="USERINPUT"
>^Z</KBD
>
represent the CTRL-D and CTRL-Z characters
that you will need to type to get out of the interpreter
before proceeding to installing <TT
CLASS="APPLICATION"
>SCons</TT
>.
</P
><P
>&#13; If Python is not installed on your system,
you will see an error message
stating something like "command not found"
(on UNIX or Linux)
or "'python' is not recognized
as an internal or external command, operable progam or batch file"
(on Windows).
In that case, you need to install Python
before you can install <TT
CLASS="APPLICATION"
>SCons</TT
>.
</P
><P
>&#13; The standard location for information
about downloading and installing Python is
<A
HREF="http://www.python.org/download/"
TARGET="_top"
>http://www.python.org/download/</A
>.
See that page for information about
how to download and install Python on your system.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN124"
>Installing <TT
CLASS="APPLICATION"
>SCons</TT
> From Pre-Built Packages</A
></H2
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> comes pre-packaged for installation on a number of systems,
including Linux and Windows systems.
You do not need to read this entire section,
you should only need to read the section
appropriate to the type of system you're running on.
</P
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN129"
>Installing <TT
CLASS="APPLICATION"
>SCons</TT
> on Red Hat (and Other RPM-based) Linux Systems</A
></H3
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> comes in RPM (Red Hat Package Manager) format,
pre-built and ready to install on Red Hat Linux,
Fedora Core,
or any other Linux distribution that uses RPM.
Your distribution may
already have an <TT
CLASS="APPLICATION"
>SCons</TT
> RPM built specifically for it;
many do, including SuSe, Mandrake and Fedora.
You can check for the availability of an <TT
CLASS="APPLICATION"
>SCons</TT
> RPM
on your distribution's download servers,
or by consulting an RPM search site like
<A
HREF="http://www.rpmfind.net/"
TARGET="_top"
>http://www.rpmfind.net/</A
> or
<A
HREF="http://rpm.pbone.net/"
TARGET="_top"
>http://rpm.pbone.net/</A
>.
</P
><P
>&#13; If your Linux distribution does not already have
a specific <TT
CLASS="APPLICATION"
>SCons</TT
> RPM file,
you can download and install from the
generic RPM provided by the <TT
CLASS="APPLICATION"
>SCons</TT
> project.
This will install the
SCons script(s) in <TT
CLASS="FILENAME"
>/usr/bin</TT
>,
and the SCons library modules in
<TT
CLASS="FILENAME"
>/usr/lib/scons</TT
>.
</P
><P
>&#13; To install from the command line, simply download the
appropriate <TT
CLASS="FILENAME"
>.rpm</TT
> file,
and then run:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> # <KBD
CLASS="USERINPUT"
>rpm -Uvh scons-0.96-1.noarch.rpm</KBD
>
</PRE
></TD
></TR
></TABLE
><P
>&#13; Or, you can use a graphical RPM package manager
like <TT
CLASS="APPLICATION"
>gnorpm</TT
>.
See your package manager application's documention
for specific instructions about
how to use it to install a downloaded RPM.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN149"
>Installing <TT
CLASS="APPLICATION"
>SCons</TT
> on Debian Linux Systems</A
></H3
><P
>&#13; Debian Linux systems use a different package management
format that also makes it very easy to install <TT
CLASS="APPLICATION"
>SCons</TT
>.
</P
><P
>&#13; If your system is connected to the Internet,
you can install the latest official Debian package
by running:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> # <KBD
CLASS="USERINPUT"
>apt-get install scons</KBD
>
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN157"
>Installing <TT
CLASS="APPLICATION"
>SCons</TT
> on Windows Systems</A
></H3
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> provides a Windows installer
that makes installation extremely easy.
Download the <TT
CLASS="FILENAME"
>scons-0.95.win32.exe</TT
>
file from the <TT
CLASS="APPLICATION"
>SCons</TT
> download page at
<A
HREF="http://www.scons.org/download.html"
TARGET="_top"
>http://www.scons.org/download.html</A
>.
Then all you need to do is execute the file
(usually by clicking on its icon in Windows Explorer).
These will take you through a small
sequence of windows that will install
<TT
CLASS="APPLICATION"
>SCons</TT
> on your system.
</P
></DIV
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN166"
>Building and Installing <TT
CLASS="APPLICATION"
>SCons</TT
> on Any System</A
></H2
><P
>&#13; If a pre-built <TT
CLASS="APPLICATION"
>SCons</TT
> package is not available for your system,
then you can still easily build and install <TT
CLASS="APPLICATION"
>SCons</TT
> using the native
Python <TT
CLASS="FILENAME"
>distutils</TT
> package.
</P
><P
>&#13; The first step is to download either the
<TT
CLASS="FILENAME"
>scons-0.96.91.tar.gz</TT
>
or <TT
CLASS="FILENAME"
>scons-0.96.91.zip</TT
>,
which are available from the SCons download page at
<A
HREF="http://www.scons.org/download.html"
TARGET="_top"
>http://www.scons.org/download.html</A
>.
</P
><P
>&#13; Unpack the archive you downloaded,
using a utility like <TT
CLASS="APPLICATION"
>tar</TT
>
on Linux or UNIX,
or <TT
CLASS="APPLICATION"
>WinZip</TT
> on Windows.
This will create a directory called
<TT
CLASS="FILENAME"
>scons-0.96.91</TT
>,
usually in your local directory.
Then change your working directory to that directory
and install <TT
CLASS="APPLICATION"
>SCons</TT
> by executing the following commands:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> # <KBD
CLASS="USERINPUT"
>cd scons-0.96.91</KBD
>
# <KBD
CLASS="USERINPUT"
>python setup.py install</KBD
>
</PRE
></TD
></TR
></TABLE
><P
>&#13; This will build <TT
CLASS="APPLICATION"
>SCons</TT
>,
install the <TT
CLASS="APPLICATION"
>scons</TT
> script
in the default system scripts directory
(<TT
CLASS="FILENAME"
>/usr/local/bin</TT
> or
<TT
CLASS="FILENAME"
>C:\Python2.2\Scripts</TT
>),
and will install the <TT
CLASS="APPLICATION"
>SCons</TT
> build engine
in an appropriate stand-alone library directory
(<TT
CLASS="FILENAME"
>/usr/local/lib/scons</TT
> or
<TT
CLASS="FILENAME"
>C:\Python2.2\scons</TT
>).
Because these are system directories,
you may need root (on Linux or UNIX) or Administrator (on Windows)
privileges to install <TT
CLASS="APPLICATION"
>SCons</TT
> like this.
</P
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN194"
>Building and Installing Multiple Versions of <TT
CLASS="APPLICATION"
>SCons</TT
> Side-by-Side</A
></H3
><P
>&#13; The <TT
CLASS="APPLICATION"
>SCons</TT
> <TT
CLASS="FILENAME"
>setup.py</TT
> script
has some extensions that support
easy installation of multiple versions of <TT
CLASS="APPLICATION"
>SCons</TT
>
in side-by-side locations.
This makes it easier to download and
experiment with different versions of <TT
CLASS="APPLICATION"
>SCons</TT
>
before moving your official build process to a new version,
for example.
</P
><P
>&#13; To install <TT
CLASS="APPLICATION"
>SCons</TT
> in a version-specific location,
add the <VAR
CLASS="OPTION"
>--version-lib</VAR
> option
when you call <TT
CLASS="FILENAME"
>setup.py</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> # <KBD
CLASS="USERINPUT"
>python setup.py install --version-lib</KBD
>
</PRE
></TD
></TR
></TABLE
><P
>&#13; This will install the <TT
CLASS="APPLICATION"
>SCons</TT
> build engine
in the
<TT
CLASS="FILENAME"
>/usr/lib/scons-0.96.91</TT
>
or
<TT
CLASS="FILENAME"
>C:\Python2.2\scons-0.96.91</TT
>
directory, for example.
</P
><P
>&#13; If you use the <VAR
CLASS="OPTION"
>--version-lib</VAR
> option
the first time you install <TT
CLASS="APPLICATION"
>SCons</TT
>,
you do not need to specify it each time you install
a new version.
The <TT
CLASS="APPLICATION"
>SCons</TT
> <TT
CLASS="FILENAME"
>setup.py</TT
> script
will detect the version-specific directory name(s)
and assume you want to install all versions
in version-specific directories.
You can override that assumption in the future
by explicitly specifying the <VAR
CLASS="OPTION"
>--standalone-lib</VAR
> option.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN218"
>Installing <TT
CLASS="APPLICATION"
>SCons</TT
> in Other Locations</A
></H3
><P
>&#13; You can install <TT
CLASS="APPLICATION"
>SCons</TT
> in locations other than
the default by specifying the <VAR
CLASS="OPTION"
>--prefix=</VAR
> option:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> # <KBD
CLASS="USERINPUT"
>python setup.py install --prefix=/opt/scons</KBD
>
</PRE
></TD
></TR
></TABLE
><P
>&#13; This would
install the <TT
CLASS="APPLICATION"
>scons</TT
> script in
<TT
CLASS="FILENAME"
>/opt/scons/bin</TT
>
and the build engine in
<TT
CLASS="FILENAME"
>/opt/scons/lib/scons</TT
>,
</P
><P
>&#13; Note that you can specify both the <VAR
CLASS="OPTION"
>--prefix=</VAR
>
and the <VAR
CLASS="OPTION"
>--version-lib</VAR
> options
at the same type,
in which case <TT
CLASS="FILENAME"
>setup.py</TT
>
will install the build engine
in a version-specific directory
relative to the specified prefix.
Adding <VAR
CLASS="OPTION"
>--version-lib</VAR
> to the
above example would install the build engine in
<TT
CLASS="FILENAME"
>/opt/scons/lib/scons-0.96.91</TT
>.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN236"
>Building and Installing <TT
CLASS="APPLICATION"
>SCons</TT
> Without Administrative Privileges</A
></H3
><P
>&#13; If you don't have the right privileges to install <TT
CLASS="APPLICATION"
>SCons</TT
>
in a system location,
simply use the <TT
CLASS="LITERAL"
>--prefix=</TT
> option
to install it in a location of your choosing.
For example,
to install <TT
CLASS="APPLICATION"
>SCons</TT
> in appropriate locations
relative to the user's <TT
CLASS="LITERAL"
>$HOME</TT
> directory,
the <TT
CLASS="APPLICATION"
>scons</TT
> script in
<TT
CLASS="FILENAME"
>$HOME/bin</TT
>
and the build engine in
<TT
CLASS="FILENAME"
>$HOME/lib/scons</TT
>,
simply type:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> $ <KBD
CLASS="USERINPUT"
>python setup.py install --prefix=$HOME</KBD
>
</PRE
></TD
></TR
></TABLE
><P
>&#13; You may, of course, specify any other location you prefer,
and may use the <VAR
CLASS="OPTION"
>--version-lib</VAR
> option
if you would like to install version-specific directories
relative to the specified prefix.
</P
></DIV
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-SIMPLE"
></A
>Simple Builds</H1
><P
>&#13; In this chapter,
you will see several examples of
very simple build configurations using <TT
CLASS="APPLICATION"
>SCons</TT
>,
which will demonstrate how easy
it is to use <TT
CLASS="APPLICATION"
>SCons</TT
> to
build programs from several different programming languages
on different types of systems.
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN256"
>Building Simple C / C++ Programs</A
></H2
><P
>&#13; Here's the famous "Hello, World!" program in C:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> int
main()
{
printf("Hello, world!\n");
}
</PRE
></TD
></TR
></TABLE
><P
>&#13; And here's how to build it using <TT
CLASS="APPLICATION"
>SCons</TT
>.
Enter the following into a file named <TT
CLASS="FILENAME"
>SConstruct</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('hello.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; This minimal configuration file gives
<TT
CLASS="APPLICATION"
>SCons</TT
> two pieces of information:
what you want to build
(an executable program),
and the input file from
which you want it built
(the <TT
CLASS="FILENAME"
>hello.c</TT
> file).
<A
HREF="#B-PROGRAM"
><TT
CLASS="FUNCTION"
>Program</TT
></A
> is a <I
CLASS="FIRSTTERM"
>builder_method</I
>,
a Python call that tells <TT
CLASS="APPLICATION"
>SCons</TT
> that you want to build an
executable program.
</P
><P
>&#13; That's it. Now run the <TT
CLASS="APPLICATION"
>scons</TT
> command to build the program.
On a POSIX-compliant system like Linux or UNIX,
you'll see something like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cc -c -o hello.o hello.c
cc -o hello hello.o
scons: done building targets.
</PRE
></TD
></TR
></TABLE
><P
>&#13; On a Windows system with the Microsoft Visual C++ compiler,
you'll see something like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cl /nologo /c hello.c /Fohello.obj
link /nologo /OUT:hello.exe hello.obj
scons: done building targets.
</PRE
></TD
></TR
></TABLE
><P
>&#13; First, notice that you only need
to specify the name of the source file,
and that <TT
CLASS="APPLICATION"
>SCons</TT
> correctly deduces the names of
the object and executable files to be built
from the base of the source file name.
</P
><P
>&#13; Second, notice that the same input <TT
CLASS="FILENAME"
>SConstruct</TT
> file,
without any changes,
generates the correct output file names on both systems:
<TT
CLASS="FILENAME"
>hello.o</TT
> and <TT
CLASS="FILENAME"
>hello</TT
>
on POSIX systems,
<TT
CLASS="FILENAME"
>hello.obj</TT
> and <TT
CLASS="FILENAME"
>hello.exe</TT
>
on Windows systems.
This is a simple example of how <TT
CLASS="APPLICATION"
>SCons</TT
>
makes it extremely easy to
write portable software builds.
</P
><P
>&#13; (Note that we won't provide duplicate side-by-side
POSIX and Windows output for all of the examples in this guide;
just keep in mind that, unless otherwise specified,
any of the examples should work equally well on both types of systems.)
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN288"
>Building Object Files</A
></H2
><P
>&#13; The <A
HREF="#B-PROGRAM"
><TT
CLASS="FUNCTION"
>Program</TT
></A
> builder method is only one of
many builder methods that <TT
CLASS="APPLICATION"
>SCons</TT
> provides
to build different types of files.
Another is the <A
HREF="#B-OBJECT"
><TT
CLASS="FUNCTION"
>Object</TT
></A
> builder method,
which tells <TT
CLASS="APPLICATION"
>SCons</TT
> to build an object file
from the specified source file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Object('hello.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Now when you run the <TT
CLASS="APPLICATION"
>scons</TT
> command to build the program,
it will build just the <TT
CLASS="FILENAME"
>hello.o</TT
> object file on a POSIX system:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cc -c -o hello.o hello.c
scons: done building targets.
</PRE
></TD
></TR
></TABLE
><P
>&#13; And just the <TT
CLASS="FILENAME"
>hello.obj</TT
> object file
on a Windows system (with the Microsoft Visual C++ compiler):
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cl /nologo /c hello.c /Fohello.obj
scons: done building targets.
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN307"
>Simple Java Builds</A
></H2
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> also makes building with Java extremely easy.
Unlike the <A
HREF="#B-PROGRAM"
><TT
CLASS="FUNCTION"
>Program</TT
></A
> and <A
HREF="#B-OBJECT"
><TT
CLASS="FUNCTION"
>Object</TT
></A
> builder methods,
however, the <A
HREF="#B-JAVA"
><TT
CLASS="FUNCTION"
>Java</TT
></A
> builder method
requires that you specify
the name of a destination directory in which
you want the class files placed,
followed by the source directory
in which the <TT
CLASS="FILENAME"
>.java</TT
> files live:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Java('classes', 'src')
</PRE
></TD
></TR
></TABLE
><P
>&#13; If the <TT
CLASS="FILENAME"
>src</TT
> directory
contains a single <TT
CLASS="FILENAME"
>hello.java</TT
> file,
then the output from running the <TT
CLASS="APPLICATION"
>scons</TT
> command
would look something like this
(on a POSIX system):
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
javac -d classes -sourcepath src src/hello.java
scons: done building targets.
</PRE
></TD
></TR
></TABLE
><P
>&#13; We'll cover Java builds in more detail,
including building Java archive (<TT
CLASS="FILENAME"
>.jar</TT
>)
and other types of file,
in <A
HREF="#CHAP-JAVA"
>the chapter called <I
>Java Builds</I
></A
>.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN328"
>Cleaning Up After a Build</A
></H2
><P
>&#13; When using <TT
CLASS="APPLICATION"
>SCons</TT
>, it is unnecessary to add special
commands or target names to clean up after a build.
Instead, you simply use the
<TT
CLASS="LITERAL"
>-c</TT
> or <TT
CLASS="LITERAL"
>--clean</TT
>
option when you invoke <TT
CLASS="APPLICATION"
>SCons</TT
>,
and <TT
CLASS="APPLICATION"
>SCons</TT
> removes the appropriate built files.
So if we build our example above
and then invoke <TT
CLASS="LITERAL"
>scons -c</TT
>
afterwards, the output on POSIX looks like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cc -c -o hello.o hello.c
cc -o hello hello.o
scons: done building targets.
% <KBD
CLASS="USERINPUT"
>scons -c</KBD
>
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed hello.o
Removed hello
scons: done cleaning targets.
</PRE
></TD
></TR
></TABLE
><P
>&#13; And the output on Windows looks like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cl /nologo /c hello.c /Fohello.obj
link /nologo /OUT:hello.exe hello.obj
scons: done building targets.
C:\&#62;<KBD
CLASS="USERINPUT"
>scons -c</KBD
>
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Cleaning targets ...
Removed hello.obj
Removed hello.exe
scons: done cleaning targets.
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice that <TT
CLASS="APPLICATION"
>SCons</TT
> changes its output to tell you that it
is <TT
CLASS="LITERAL"
>Cleaning targets ...</TT
> and
<TT
CLASS="LITERAL"
>done cleaning targets.</TT
>
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN348"
>The <TT
CLASS="FILENAME"
>SConstruct</TT
> File</A
></H2
><P
>&#13; If you're used to build systems like <TT
CLASS="APPLICATION"
>Make</TT
>
you've already figured out that the <TT
CLASS="FILENAME"
>SConstruct</TT
> file
is the <TT
CLASS="APPLICATION"
>SCons</TT
> equivalent of a <TT
CLASS="FILENAME"
>Makefile</TT
>.
That is, the <TT
CLASS="FILENAME"
>SConstruct</TT
> file is the input file
that <TT
CLASS="APPLICATION"
>SCons</TT
> reads to control the build.
</P
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN358"
><TT
CLASS="FILENAME"
>SConstruct</TT
> Files Are Python Scripts</A
></H3
><P
>&#13; There is, however, an important difference between
an <TT
CLASS="FILENAME"
>SConstruct</TT
> file and a <TT
CLASS="FILENAME"
>Makefile</TT
>:
the <TT
CLASS="FILENAME"
>SConstruct</TT
> file is actually a Python script.
If you're not already familiar with Python, don't worry.
This User's Guide will introduce you step-by-step
to the relatively small amount of Python you'll
need to know to be able to use <TT
CLASS="APPLICATION"
>SCons</TT
> effectively.
And Python is very easy to learn.
</P
><P
>&#13; One aspect of using Python as the
scripting language is that you can put comments
in your <TT
CLASS="FILENAME"
>SConstruct</TT
> file using Python's commenting convention;
that is, everything between a '#' and the end of the line
will be ignored:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> # Arrange to build the "hello" program.
Program('hello.c') # "hello.c" is the source file.
</PRE
></TD
></TR
></TABLE
><P
>&#13; You'll see throughout the remainder of this Guide
that being able to use the power of a
real scripting language
can greatly simplify the solutions
to complex requirements of real-world builds.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN370"
><TT
CLASS="APPLICATION"
>SCons</TT
> Functions Are Order-Independent</A
></H3
><P
>&#13; One important way in which the <TT
CLASS="FILENAME"
>SConstruct</TT
>
file is not exactly like a normal Python script,
and is more like a <TT
CLASS="FILENAME"
>Makefile</TT
>,
is that the order in which
the <TT
CLASS="APPLICATION"
>SCons</TT
> functions are called in
the <TT
CLASS="FILENAME"
>SConstruct</TT
> file
does <I
CLASS="EMPHASIS"
>not</I
>
affect the order in which <TT
CLASS="APPLICATION"
>SCons</TT
>
actually builds the programs and object files
you want it to build.<A
NAME="AEN380"
HREF="#FTN.AEN380"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
>
In other words, when you call the <A
HREF="#B-PROGRAM"
><TT
CLASS="FUNCTION"
>Program</TT
></A
> builder
(or any other builder method),
you're not telling <TT
CLASS="APPLICATION"
>SCons</TT
> to build
the program at the instant the builder method is called.
Instead, you're telling <TT
CLASS="APPLICATION"
>SCons</TT
> to build the program
that you want, for example,
a program built from a file named <TT
CLASS="FILENAME"
>hello.c</TT
>,
and it's up to <TT
CLASS="APPLICATION"
>SCons</TT
> to build that program
(and any other files) whenever it's necessary.
(We'll learn more about how
<TT
CLASS="APPLICATION"
>SCons</TT
> decides when building or rebuilding a file
is necessary in <A
HREF="#CHAP-DEPENDS"
>the chapter called <I
>Dependencies</I
></A
>, below.)
</P
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> reflects this distinction between
<I
CLASS="EMPHASIS"
>calling a builder method like</I
> <TT
CLASS="FUNCTION"
>Program</TT
>&#62;
and <I
CLASS="EMPHASIS"
>actually building the program</I
>
by printing the status messages that indicate
when it's "just reading" the <TT
CLASS="FILENAME"
>SConstruct</TT
> file,
and when it's actually building the target files.
This is to make it clear when <TT
CLASS="APPLICATION"
>SCons</TT
> is
executing the Python statements that make up the <TT
CLASS="FILENAME"
>SConstruct</TT
> file,
and when <TT
CLASS="APPLICATION"
>SCons</TT
> is actually executing the
commands or other actions to
build the necessary files.
</P
><P
>&#13; Let's clarify this with an example.
Python has a <TT
CLASS="LITERAL"
>print</TT
> statement that
prints a string of characters to the screen.
If we put <TT
CLASS="LITERAL"
>print</TT
> statements around
our calls to the <TT
CLASS="FUNCTION"
>Program</TT
> builder method:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> print "Calling Program('hello.c')"
Program('hello.c')
print "Calling Program('goodbye.c')"
Program('goodbye.c')
print "Finished calling Program()"
</PRE
></TD
></TR
></TABLE
><P
>&#13; Then when we execute <TT
CLASS="APPLICATION"
>SCons</TT
>,
we see the output from the <TT
CLASS="LITERAL"
>print</TT
>
statements in between the messages about
reading the <TT
CLASS="FILENAME"
>SConscript</TT
> files,
indicating that that is when the
Python statements are being executed:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
Calling Program('hello.c')
Calling Program('goodbye.c')
Finished calling Program()
scons: done reading SConscript files.
scons: Building targets ...
cc -c -o goodbye.o goodbye.c
cc -o goodbye goodbye.o
cc -c -o hello.o hello.c
cc -o hello hello.o
scons: done building targets.
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice also that <TT
CLASS="APPLICATION"
>SCons</TT
> built the <TT
CLASS="APPLICATION"
>goodbye</TT
> program first,
even though the "reading <TT
CLASS="FILENAME"
>SConscript</TT
>" output
shows that we called <TT
CLASS="LITERAL"
>Program('hello.c')</TT
>
first in the <TT
CLASS="FILENAME"
>SConstruct</TT
> file.
</P
></DIV
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN420"
>Making the <TT
CLASS="APPLICATION"
>SCons</TT
> Output Less Verbose</A
></H2
><P
>&#13; You've already seen how <TT
CLASS="APPLICATION"
>SCons</TT
> prints
some messages about what it's doing,
surrounding the actual commands used to build the software:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
cl /nologo /c hello.c /Fohello.obj
link /nologo /OUT:hello.exe hello.obj
scons: done building targets.
</PRE
></TD
></TR
></TABLE
><P
>&#13; These messages emphasize the
order in which <TT
CLASS="APPLICATION"
>SCons</TT
> does its work:
all of the configuration files
(generically referred to as <TT
CLASS="FILENAME"
>SConscript</TT
> files)
are read and executed first,
and only then are the target files built.
Among other benefits, these messages help to distinguish between
errors that occur while the configuration files are read,
and errors that occur while targets are being built.
</P
><P
>&#13; One drawback, of course, is that these messages clutter the output.
Fortunately, they're easily disabled by using
the <TT
CLASS="LITERAL"
>-Q</TT
> option when invoking <TT
CLASS="APPLICATION"
>SCons</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cl /nologo /c hello.c /Fohello.obj
link /nologo /OUT:hello.exe hello.obj
</PRE
></TD
></TR
></TABLE
><P
>&#13; Because we want this User's Guide to focus
on what <TT
CLASS="APPLICATION"
>SCons</TT
> is actually doing,
we're going use the <TT
CLASS="LITERAL"
>-Q</TT
> option
to remove these messages from the
output of all the remaining examples in this Guide.
</P
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-LESS-SIMPLE"
></A
>Less Simple Things to Do With Builds</H1
><P
>&#13; In this chapter,
you will see several examples of
very simple build configurations using <TT
CLASS="APPLICATION"
>SCons</TT
>,
which will demonstrate how easy
it is to use <TT
CLASS="APPLICATION"
>SCons</TT
> to
build programs from several different programming languages
on different types of systems.
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN443"
>Specifying the Name of the Target (Output) File</A
></H2
><P
>&#13; You've seen that when you call the <A
HREF="#B-PROGRAM"
><TT
CLASS="FUNCTION"
>Program</TT
></A
> builder method,
it builds the resulting program with the same
base name as the source file.
That is, the following call to build an
executable program from the <TT
CLASS="FILENAME"
>hello.c</TT
> source file
will build an executable program named <TT
CLASS="APPLICATION"
>hello</TT
> on POSIX systems,
and an executable program named <TT
CLASS="FILENAME"
>hello.exe</TT
> on Windows systems:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('hello.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; If you want to build a program with
a different name than the base of the source file name,
you simply put the target file name
to the left of the source file name:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('new_hello', 'hello.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; (<TT
CLASS="APPLICATION"
>SCons</TT
> requires the target file name first,
followed by the source file name,
so that the order mimics that of an
assignment statement in most programming languages,
including Python:
<TT
CLASS="LITERAL"
>"program = source files"</TT
>.)
</P
><P
>&#13; Now <TT
CLASS="APPLICATION"
>SCons</TT
> will build an executable program
named <TT
CLASS="APPLICATION"
>new_hello</TT
> when run on a POSIX system:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o hello.o hello.c
cc -o new_hello hello.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; And <TT
CLASS="APPLICATION"
>SCons</TT
> will build an executable program
named <TT
CLASS="APPLICATION"
>new_hello.exe</TT
> when run on a Windows system:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cl /nologo /c hello.c /Fohello.obj
link /nologo /OUT:new_hello.exe hello.obj
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN467"
>Compiling Multiple Source Files</A
></H2
><P
>&#13; You've just seen how to configure <TT
CLASS="APPLICATION"
>SCons</TT
>
to compile a program from a single source file.
It's more common, of course,
that you'll need to build a program from
many input source files, not just one.
To do this, you need to put the
source files in a Python list
(enclosed in square brackets),
like so:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program(['main.c', 'file1.c', 'file2.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; A build of the above example would look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o file1.o file1.c
cc -c -o file2.o file2.c
cc -c -o main.o main.c
cc -o main main.o file1.o file2.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice that <TT
CLASS="APPLICATION"
>SCons</TT
>
deduces the output program name
from the first source file specified
in the list--that is,
because the first source file was <TT
CLASS="FILENAME"
>prog.c</TT
>,
<TT
CLASS="APPLICATION"
>SCons</TT
> will name the resulting program <TT
CLASS="FILENAME"
>prog</TT
>
(or <TT
CLASS="FILENAME"
>prog.exe</TT
> on a Windows system).
If you want to specify a different program name,
then (as we've seen in the previous section)
you slide the list of source files
over to the right
to make room for the output program file name.
(<TT
CLASS="APPLICATION"
>SCons</TT
> puts the output file name to the left
of the source file names
so that the order mimics that of an
assignment statement: "program = source files".)
This makes our example:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('program', ['main.c', 'file1.c', 'file2.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; On Linux, a build of this example would look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o file1.o file1.c
cc -c -o file2.o file2.c
cc -c -o main.o main.c
cc -o program main.o file1.o file2.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; Or on Windows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cl /nologo /c file1.c /Fofile1.obj
cl /nologo /c file2.c /Fofile2.obj
cl /nologo /c main.c /Fomain.obj
link /nologo /OUT:program.exe main.obj file1.obj file2.obj
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN489"
>Specifying Single Files Vs. Lists of Files</A
></H2
><P
>&#13; We've now shown you two ways to specify
the source for a program,
one with a list of files:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('hello', ['file1.c', 'file2.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; And one with a single file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('hello', 'hello.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; You could actually put a single file name in a list, too,
which you might prefer just for the sake of consistency:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('hello', ['hello.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> functions will accept a single file name in either form.
In fact, internally, <TT
CLASS="APPLICATION"
>SCons</TT
> treats all input as lists of files,
but allows you to omit the square brackets
to cut down a little on the typing
when there's only a single file name.
</P
><DIV
CLASS="IMPORTANT"
><P
></P
><TABLE
CLASS="IMPORTANT"
WIDTH="100%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="./stylesheet-images/important.gif"
HSPACE="5"
ALT="Important"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
>&#13; Although <TT
CLASS="APPLICATION"
>SCons</TT
> functions
are forgiving about whether or not you
use a string vs. a list for a single file name,
Python itself is more strict about
treating lists and strings differently.
So where <TT
CLASS="APPLICATION"
>SCons</TT
> allows either
a string or list:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> # The following two calls both work correctly:
Program('program1', 'program1.c')
Program('program2', ['program2.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; Trying to do "Python things" that mix strings and
lists will cause errors or lead to incorrect results:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> common_sources = ['file1.c', 'file2.c']
# THE FOLLOWING IS INCORRECT AND GENERATES A PYTHON ERROR
# BECAUSE IT TRIES TO ADD A STRING TO A LIST:
Program('program1', common_sources + 'program1.c')
# The following works correctly, because it's adding two
# lists together to make another list.
Program('program2', common_sources + ['program2.c'])
</PRE
></TD
></TR
></TABLE
></TD
></TR
></TABLE
></DIV
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN507"
>Making Lists of Files Easier to Read</A
></H2
><P
>&#13; One drawback to the use of a Python list
for source files is that
each file name must be enclosed in quotes
(either single quotes or double quotes).
This can get cumbersome and difficult to read
when the list of file names is long.
Fortunately, <TT
CLASS="APPLICATION"
>SCons</TT
> and Python provide a number of ways
to make sure that
the <TT
CLASS="FILENAME"
>SConstruct</TT
> file stays easy to read.
</P
><P
>&#13; To make long lists of file names
easier to deal with, <TT
CLASS="APPLICATION"
>SCons</TT
> provides a
<TT
CLASS="FUNCTION"
>Split</TT
> function
that takes a quoted list of file names,
with the names separated by spaces or other white-space characters,
and turns it into a list of separate file names.
Using the <TT
CLASS="FUNCTION"
>Split</TT
> function turns the
previous example into:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('program', Split('main.c file1.c file2.c'))
</PRE
></TD
></TR
></TABLE
><P
>&#13; (If you're already familiar with Python,
you'll have realized that this is similar to the
<TT
CLASS="FUNCTION"
>split()</TT
> method
in the Python standard <TT
CLASS="FUNCTION"
>string</TT
> module.
Unlike the <TT
CLASS="FUNCTION"
>string.split()</TT
> method,
however, the <TT
CLASS="FUNCTION"
>Split</TT
> function
does not require a string as input
and will wrap up a single non-string object in a list,
or return its argument untouched if it's already a list.
This comes in handy as a way to make sure
arbitrary values can be passed to <TT
CLASS="APPLICATION"
>SCons</TT
> functions
without having to check the type of the variable by hand.)
</P
><P
>&#13; Putting the call to the <TT
CLASS="FUNCTION"
>Split</TT
> function
inside the <TT
CLASS="FUNCTION"
>Program</TT
> call
can also be a little unwieldy.
A more readable alternative is to
assign the output from the <TT
CLASS="FUNCTION"
>Split</TT
> call
to a variable name,
and then use the variable when calling the
<TT
CLASS="FUNCTION"
>Program</TT
> function:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> list = Split('main.c file1.c file2.c')
Program('program', list)
</PRE
></TD
></TR
></TABLE
><P
>&#13; Lastly, the <TT
CLASS="FUNCTION"
>Split</TT
> function
doesn't care how much white space separates
the file names in the quoted string.
This allows you to create lists of file
names that span multiple lines,
which often makes for easier editing:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> list = Split("""main.c
file1.c
file2.c""")
Program('program', list)
</PRE
></TD
></TR
></TABLE
><P
>&#13; (Note in this example that we used
the Python "triple-quote" syntax,
which allows a string to contain
multiple lines.
The three quotes can be either
single or double quotes.)
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN533"
>Keyword Arguments</A
></H2
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> also allows you to identify
the output file and input source files
using Python keyword arguments.
The output file is known as the
<I
CLASS="EMPHASIS"
>target</I
>,
and the source file(s) are known (logically enough) as the
<I
CLASS="EMPHASIS"
>source</I
>.
The Python syntax for this is:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> list = Split('main.c file1.c file2.c')
Program(target = 'program', source = list)
</PRE
></TD
></TR
></TABLE
><P
>&#13; Because the keywords explicitly identify
what each argument is,
you can actually reverse the order if you prefer:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> list = Split('main.c file1.c file2.c')
Program(source = list, target = 'program')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Whether or not you choose to use keyword arguments
to identify the target and source files,
and the order in which you specify them
when using keywords,
are purely personal choices;
<TT
CLASS="APPLICATION"
>SCons</TT
> functions the same regardless.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN544"
>Compiling Multiple Programs</A
></H2
><P
>&#13; In order to compile multiple programs
within the same <TT
CLASS="FILENAME"
>SConstruct</TT
> file,
simply call the <TT
CLASS="FUNCTION"
>Program</TT
> method
multiple times,
once for each program you need to build:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('foo.c')
Program('bar', ['bar1.c', 'bar2.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> would then build the programs as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o bar1.o bar1.c
cc -c -o bar2.o bar2.c
cc -o bar bar1.o bar2.o
cc -c -o foo.o foo.c
cc -o foo foo.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice that <TT
CLASS="APPLICATION"
>SCons</TT
> does not necessarily build the
programs in the same order in which you specify
them in the <TT
CLASS="FILENAME"
>SConstruct</TT
> file.
<TT
CLASS="APPLICATION"
>SCons</TT
> does, however, recognize that
the individual object files must be built
before the resulting program can be built.
We'll discuss this in greater detail in
the "Dependencies" section, below.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN558"
>Sharing Source Files Between Multiple Programs</A
></H2
><P
>&#13; It's common to re-use code by sharing source files
between multiple programs.
One way to do this is to create a library
from the common source files,
which can then be linked into resulting programs.
(Creating libraries is discussed in
<A
HREF="#CHAP-LIBRARIES"
>the chapter called <I
>Building and Linking with Libraries</I
></A
>, below.)
</P
><P
>&#13; A more straightforward, but perhaps less convenient,
way to share source files between multiple programs
is simply to include the common files
in the lists of source files for each program:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program(Split('foo.c common1.c common2.c'))
Program('bar', Split('bar1.c bar2.c common1.c common2.c'))
</PRE
></TD
></TR
></TABLE
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> recognizes that the object files for
the <TT
CLASS="FILENAME"
>common1.c</TT
> and <TT
CLASS="FILENAME"
>common2.c</TT
> source files
each only need to be built once,
even though the resulting object files are
each linked in to both of the resulting executable programs:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o bar1.o bar1.c
cc -c -o bar2.o bar2.c
cc -c -o common1.o common1.c
cc -c -o common2.o common2.c
cc -o bar bar1.o bar2.o common1.o common2.o
cc -c -o foo.o foo.c
cc -o foo foo.o common1.o common2.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; If two or more programs
share a lot of common source files,
repeating the common files in the list for each program
can be a maintenance problem when you need to change the
list of common files.
You can simplify this by creating a separate Python list
to hold the common file names,
and concatenating it with other lists
using the Python <TT
CLASS="LITERAL"
>+</TT
> operator:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> common = ['common1.c', 'common2.c']
foo_files = ['foo.c'] + common
bar_files = ['bar1.c', 'bar2.c'] + common
Program('foo', foo_files)
Program('bar', bar_files)
</PRE
></TD
></TR
></TABLE
><P
>&#13; This is functionally equivalent to the previous example.
</P
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-LIBRARIES"
></A
>Building and Linking with Libraries</H1
><P
>&#13; It's often useful to organize large software projects
by collecting parts of the software into one or more libraries.
<TT
CLASS="APPLICATION"
>SCons</TT
> makes it easy to create libraries
and to use them in the programs.
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN578"
>Building Libraries</A
></H2
><P
>&#13; You build your own libraries by specifying <A
HREF="#B-LIBRARY"
><TT
CLASS="FUNCTION"
>Library</TT
></A
>
instead of <A
HREF="#B-PROGRAM"
><TT
CLASS="FUNCTION"
>Program</TT
></A
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Library('foo', ['f1.c', 'f2.c', 'f3.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> uses the appropriate library prefix and suffix for your system.
So on POSIX or Linux systems,
the above example would build as follows
(although <TT
CLASS="APPLICATION"
>ranlib</TT
> may not be called on all systems):
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o f1.o f1.c
cc -c -o f2.o f2.c
cc -c -o f3.o f3.c
ar r libfoo.a f1.o f2.o f3.o
ranlib libfoo.a
</PRE
></TD
></TR
></TABLE
><P
>&#13; On a Windows system,
a build of the above example would look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cl /nologo /c f1.c /Fof1.obj
cl /nologo /c f2.c /Fof2.obj
cl /nologo /c f3.c /Fof3.obj
lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj
</PRE
></TD
></TR
></TABLE
><P
>&#13; The rules for the target name of the library
are similar to those for programs:
if you don't explicitly specify a target library name,
<TT
CLASS="APPLICATION"
>SCons</TT
> will deduce one from the
name of the first source file specified,
and <TT
CLASS="APPLICATION"
>SCons</TT
> will add an appropriate
file prefix and suffix if you leave them off.
</P
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN597"
>Building Static Libraries Explicitly: the <TT
CLASS="FUNCTION"
>StaticLibrary</TT
> Builder</A
></H3
><P
>&#13; The <A
HREF="#B-LIBRARY"
><TT
CLASS="FUNCTION"
>Library</TT
></A
> function builds a traditional static library.
If you want to be explicit about the type of library being built,
you can use the synonym <A
HREF="#B-STATICLIBRARY"
><TT
CLASS="FUNCTION"
>StaticLibrary</TT
></A
> function
instead of <TT
CLASS="FUNCTION"
>Library</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> StaticLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; There is no functional difference between the
<A
HREF="#B-STATICLIBRARY"
><TT
CLASS="FUNCTION"
>StaticLibrary</TT
></A
> and <TT
CLASS="FUNCTION"
>Library</TT
> functions.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN611"
>Building Shared (DLL) Libraries: the <TT
CLASS="FUNCTION"
>SharedLibrary</TT
> Builder</A
></H3
><P
>&#13; If you want to build a shared library (on POSIX systems)
or a DLL file (on Windows systems),
you use the <A
HREF="#B-SHAREDLIBRARY"
><TT
CLASS="FUNCTION"
>SharedLibrary</TT
></A
> function:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> SharedLibrary('foo', ['f1.c', 'f2.c', 'f3.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; The output on POSIX:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o f1.os f1.c
cc -c -o f2.os f2.c
cc -c -o f3.os f3.c
cc -shared -o libfoo.so f1.os f2.os f3.os
</PRE
></TD
></TR
></TABLE
><P
>&#13; And the output on Windows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cl /nologo /c f1.c /Fof1.obj
cl /nologo /c f2.c /Fof2.obj
cl /nologo /c f3.c /Fof3.obj
link /nologo /dll /out:foo.dll /implib:foo.lib f1.obj f2.obj f3.obj
RegServerFunc(target, source, env)
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice again that <TT
CLASS="APPLICATION"
>SCons</TT
> takes care of
building the output file correctly,
adding the <TT
CLASS="LITERAL"
>-shared</TT
> option
for a POSIX compilation,
and the <TT
CLASS="LITERAL"
>/dll</TT
> option on Windows.
</P
></DIV
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN628"
>Linking with Libraries</A
></H2
><P
>&#13; Usually, you build a library
because you want to link it with one or more programs.
You link libraries with a program by specifying
the libraries in the <A
HREF="#CV-LIBS"
><VAR
CLASS="ENVAR"
>$LIBS</VAR
></A
> construction variable,
and by specifying the directory in which
the library will be found in the
<A
HREF="#CV-LIBPATH"
><VAR
CLASS="ENVAR"
>$LIBPATH</VAR
></A
> construction variable:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Library('foo', ['f1.c', 'f2.c', 'f3.c'])
Program('prog.c', LIBS=['foo', 'bar'], LIBPATH='.')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice, of course, that you don't need to specify a library
prefix (like <TT
CLASS="LITERAL"
>lib</TT
>)
or suffix (like <TT
CLASS="LITERAL"
>.a</TT
> or <TT
CLASS="LITERAL"
>.lib</TT
>).
<TT
CLASS="APPLICATION"
>SCons</TT
> uses the correct prefix or suffix for the current system.
</P
><P
>&#13; On a POSIX or Linux system,
a build of the above example would look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o f1.o f1.c
cc -c -o f2.o f2.c
cc -c -o f3.o f3.c
ar r libfoo.a f1.o f2.o f3.o
ranlib libfoo.a
cc -c -o prog.o prog.c
cc -o prog prog.o -L. -lfoo -lbar
</PRE
></TD
></TR
></TABLE
><P
>&#13; On a Windows system,
a build of the above example would look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cl /nologo /c f1.c /Fof1.obj
cl /nologo /c f2.c /Fof2.obj
cl /nologo /c f3.c /Fof3.obj
lib /nologo /OUT:foo.lib f1.obj f2.obj f3.obj
cl /nologo /c prog.c /Foprog.obj
link /nologo /OUT:prog.exe /LIBPATH:. foo.lib bar.lib prog.obj
</PRE
></TD
></TR
></TABLE
><P
>&#13; As usual, notice that <TT
CLASS="APPLICATION"
>SCons</TT
> has taken care
of constructing the correct command lines
to link with the specified library on each system.
</P
><P
>&#13; Note also that,
if you only have a single library to link with,
you can specify the library name in single string,
instead of a Python list,
so that:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('prog.c', LIBS='foo', LIBPATH='.')
</PRE
></TD
></TR
></TABLE
><P
>&#13; is equivalent to:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('prog.c', LIBS=['foo'], LIBPATH='.')
</PRE
></TD
></TR
></TABLE
><P
>&#13; This is similar to the way that <TT
CLASS="APPLICATION"
>SCons</TT
>
handles either a string or a list to
specify a single source file.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN655"
>Finding Libraries: the <VAR
CLASS="ENVAR"
>$LIBPATH</VAR
> Construction Variable</A
></H2
><P
>&#13; By default, the linker will only look in
certain system-defined directories for libraries.
<TT
CLASS="APPLICATION"
>SCons</TT
> knows how to look for libraries
in directories that you specify with the
<A
HREF="#CV-LIBPATH"
><VAR
CLASS="ENVAR"
>$LIBPATH</VAR
></A
> construction variable.
<VAR
CLASS="ENVAR"
>$LIBPATH</VAR
> consists of a list of
directory names, like so:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('prog.c', LIBS = 'm',
LIBPATH = ['/usr/lib', '/usr/local/lib'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; Using a Python list is preferred because it's portable
across systems. Alternatively, you could put all of
the directory names in a single string, separated by the
system-specific path separator character:
a colon on POSIX systems:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> LIBPATH = '/usr/lib:/usr/local/lib'
</PRE
></TD
></TR
></TABLE
><P
>&#13; or a semi-colon on Windows systems:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> LIBPATH = 'C:\\lib;D:\\lib'
</PRE
></TD
></TR
></TABLE
><P
>&#13; (Note that Python requires that the backslash
separators in a Windows path name
be escaped within strings.)
</P
><P
>&#13; When the linker is executed,
<TT
CLASS="APPLICATION"
>SCons</TT
> will create appropriate flags
so that the linker will look for
libraries in the same directories as <TT
CLASS="APPLICATION"
>SCons</TT
>.
So on a POSIX or Linux system,
a build of the above example would look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o prog.o prog.c
cc -o prog prog.o -L/usr/lib -L/usr/local/lib -lm
</PRE
></TD
></TR
></TABLE
><P
>&#13; On a Windows system,
a build of the above example would look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cl /nologo /c prog.c /Foprog.obj
link /nologo /OUT:prog.exe /LIBPATH:\usr\lib /LIBPATH:\usr\local\lib m.lib prog.obj
</PRE
></TD
></TR
></TABLE
><P
>&#13; Note again that <TT
CLASS="APPLICATION"
>SCons</TT
> has taken care of
the system-specific details of creating
the right command-line options.
</P
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-NODES"
></A
>Node Objects</H1
><P
>&#13; Internally, <TT
CLASS="APPLICATION"
>SCons</TT
> represents all of the files
and directories it knows about as <TT
CLASS="LITERAL"
>Nodes</TT
>.
These internal objects
(not object <I
CLASS="EMPHASIS"
>files</I
>)
can be used in a variety of ways
to make your <TT
CLASS="FILENAME"
>SConscript</TT
>
files portable and easy to read.
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN686"
>Builder Methods Return Lists of Target Nodes</A
></H2
><P
>&#13; All builder methods return a list of
<CODE
CLASS="CLASSNAME"
>Node</CODE
> objects that identify the
target file or files that will be built.
These returned <TT
CLASS="LITERAL"
>Nodes</TT
> can be passed
as source files to other builder methods,
</P
><P
>&#13; 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 <A
HREF="#B-OBJECT"
><TT
CLASS="FUNCTION"
>Object</TT
></A
>
builder once for each object file,
specifying the desired options:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Object('hello.c', CCFLAGS='-DHELLO')
Object('goodbye.c', CCFLAGS='-DGOODBYE')
</PRE
></TD
></TR
></TABLE
><P
>&#13; One way to combine these object files
into the resulting program
would be to call the <A
HREF="#B-PROGRAM"
><TT
CLASS="FUNCTION"
>Program</TT
></A
>
builder with the names of the object files
listed as sources:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Object('hello.c', CCFLAGS='-DHELLO')
Object('goodbye.c', CCFLAGS='-DGOODBYE')
Program(['hello.o', 'goodbye.o'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; The problem with listing the names as strings
is that our <TT
CLASS="FILENAME"
>SConstruct</TT
> file is no longer portable
across operating systems.
It won't, for example, work on Windows
because the object files there would be
named <TT
CLASS="FILENAME"
>hello.obj</TT
> and <TT
CLASS="FILENAME"
>goodbye.obj</TT
>,
not <TT
CLASS="FILENAME"
>hello.o</TT
> and <TT
CLASS="FILENAME"
>goodbye.o</TT
>.
</P
><P
>&#13; A better solution is to assign the lists of targets
returned by the calls to the <TT
CLASS="FUNCTION"
>Object</TT
> builder to variables,
which we can then concatenate in our
call to the <TT
CLASS="FUNCTION"
>Program</TT
> builder:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> hello_list = Object('hello.c', CCFLAGS='-DHELLO')
goodbye_list = Object('goodbye.c', CCFLAGS='-DGOODBYE')
Program(hello_list + goodbye_list)
</PRE
></TD
></TR
></TABLE
><P
>&#13; This makes our <TT
CLASS="FILENAME"
>SConstruct</TT
> file portable again,
the build output on Linux looking like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -DGOODBYE -c -o goodbye.o goodbye.c
cc -DHELLO -c -o hello.o hello.c
cc -o hello hello.o goodbye.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; And on Windows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cl -DGOODBYE /c goodbye.c /Fogoodbye.obj
cl -DHELLO /c hello.c /Fohello.obj
link /nologo /OUT:hello.exe hello.obj goodbye.obj
</PRE
></TD
></TR
></TABLE
><P
>&#13; We'll see examples of using the list of nodes
returned by builder methods throughout
the rest of this guide.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN717"
>Explicitly Creating File and Directory Nodes</A
></H2
><P
>&#13; It's worth mentioning here that
<TT
CLASS="APPLICATION"
>SCons</TT
> maintains a clear distinction
between Nodes that represent files
and Nodes that represent directories.
<TT
CLASS="APPLICATION"
>SCons</TT
> supports <TT
CLASS="FUNCTION"
>File</TT
> and <TT
CLASS="FUNCTION"
>Dir</TT
>
functions that, repectively,
return a file or directory Node:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> hello_c = File('hello.c')
Program(hello_c)
classes = Dir('classes')
Java(classes, 'src')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Normally, you don't need to call
<TT
CLASS="FUNCTION"
>File</TT
> or <TT
CLASS="FUNCTION"
>Dir</TT
> 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 <TT
CLASS="FUNCTION"
>File</TT
> and <TT
CLASS="FUNCTION"
>Dir</TT
> functions can come in handy
in situations where you need to explicitly
instruct <TT
CLASS="APPLICATION"
>SCons</TT
> about the type of Node being
passed to a builder or other function,
or unambiguously refer to a specific
file in a directory tree.
</P
><P
>&#13; 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,
<TT
CLASS="APPLICATION"
>SCons</TT
> also supports an <TT
CLASS="FUNCTION"
>Entry</TT
> function,
which returns a Node
that can represent either a file or a directory.
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> xyzzy = Entry('xyzzy')
</PRE
></TD
></TR
></TABLE
><P
>&#13; The returned <TT
CLASS="LITERAL"
>xyzzy</TT
> 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.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN737"
>Printing <CODE
CLASS="CLASSNAME"
>Node</CODE
> File Names</A
></H2
><P
>&#13; 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 <TT
CLASS="FILENAME"
>SConstruct</TT
> file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> hello_c = File('hello.c')
Program(hello_c)
classes = Dir('classes')
Java(classes, 'src')
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]
</PRE
></TD
></TR
></TABLE
><P
>&#13; Would print the following file names on a POSIX system:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
The object file is: hello.o
The program file is: hello
cc -c -o hello.o hello.c
cc -o hello hello.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; And the following file names on a Windows system:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
The object file is: hello.obj
The program file is: hello.exe
cl /nologo /c hello.c /Fohello.obj
link /nologo /OUT:hello.exe hello.obj
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN749"
>Using a <CODE
CLASS="CLASSNAME"
>Node</CODE
>'s File Name as a String</A
></H2
><P
>&#13; Printing a <CODE
CLASS="CLASSNAME"
>Node</CODE
>'s name
as described in the previous section
works because the string representation of a <CODE
CLASS="CLASSNAME"
>Node</CODE
>
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
<TT
CLASS="FUNCTION"
>str</TT
> function.
For example, if you want to use the Python
<TT
CLASS="FUNCTION"
>os.path.exists</TT
>
to figure out whether a file
exists while the <TT
CLASS="FILENAME"
>SConstruct</TT
> file
is being read and executed,
you can fetch the string as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> 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!"
</PRE
></TD
></TR
></TABLE
><P
>&#13; Which executes as follows on a POSIX system:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
The object file is: hello.o
The program file is: hello
cc -c -o hello.o hello.c
cc -o hello hello.o
</PRE
></TD
></TR
></TABLE
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-DEPENDS"
></A
>Dependencies</H1
><P
>&#13; So far we've seen how <TT
CLASS="APPLICATION"
>SCons</TT
> handles one-time builds.
But the real point of a build tool like <TT
CLASS="APPLICATION"
>SCons</TT
>
is to rebuild only the necessary things
when source files change--or, put another way,
<TT
CLASS="APPLICATION"
>SCons</TT
> should <I
CLASS="EMPHASIS"
>not</I
>
waste time rebuilding things that have already been built.
You can see this at work simply be re-invoking <TT
CLASS="APPLICATION"
>SCons</TT
>
after building our simple <TT
CLASS="APPLICATION"
>hello</TT
> example:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
scons: `.' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; The second time it is executed,
<TT
CLASS="APPLICATION"
>SCons</TT
> realizes that the <TT
CLASS="APPLICATION"
>hello</TT
> program
is up-to-date with respect to the current <TT
CLASS="FILENAME"
>hello.c</TT
> source file,
and avoids rebuilding it.
You can see this more clearly by naming
the <TT
CLASS="APPLICATION"
>hello</TT
> program explicitly on the command line:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
scons: `hello' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; Note that <TT
CLASS="APPLICATION"
>SCons</TT
> reports <TT
CLASS="LITERAL"
>"...is up to date"</TT
>
only for target files named explicitly on the command line,
to avoid cluttering the output.
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN785"
>Deciding When a Source File Has Changed: the <TT
CLASS="FUNCTION"
>SourceSignatures</TT
> Function</A
></H2
><P
>&#13; The other side of avoiding unnecessary rebuilds
is the fundamental build tool behavior
of <I
CLASS="EMPHASIS"
>rebuilding</I
>
things when a source file changes,
so that the built software is up to date.
<TT
CLASS="APPLICATION"
>SCons</TT
> keeps track of this through a
<TT
CLASS="LITERAL"
>signature</TT
> for each source file,
and allows you to configure
whether you want to use the source
file contents or the modification time (timestamp)
as the signature.
</P
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN792"
>MD5 Source File Signatures</A
></H3
><P
>&#13; By default,
<TT
CLASS="APPLICATION"
>SCons</TT
> keeps track of whether a source file has changed
based on the file's contents,
not the modification time.
This means that you may be surprised by the
default <TT
CLASS="APPLICATION"
>SCons</TT
> behavior if you are used to the
<TT
CLASS="APPLICATION"
>Make</TT
> convention of forcing
a rebuild by updating the file's modification time
(using the <TT
CLASS="APPLICATION"
>touch</TT
> command, for example):
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>touch hello.c</KBD
>
% <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
scons: `hello' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; Even though the file's modification time has changed,
<TT
CLASS="APPLICATION"
>SCons</TT
> realizes that the contents of the
<TT
CLASS="FILENAME"
>hello.c</TT
> file have <I
CLASS="EMPHASIS"
>not</I
> changed,
and therefore that the <TT
CLASS="APPLICATION"
>hello</TT
> program
need not be rebuilt.
This avoids unnecessary rebuilds when,
for example, someone rewrites the
contents of a file without making a change.
But if the contents of the file really do change,
then <TT
CLASS="APPLICATION"
>SCons</TT
> detects the change
and rebuilds the program as required:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>edit hello.c</KBD
>
[CHANGE THE CONTENTS OF hello.c]
% <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; Note that you can, if you wish,
specify this default behavior
(MD5 signatures) explicitly
using the <TT
CLASS="FUNCTION"
>SourceSignatures</TT
> function as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('hello.c')
SourceSignatures('MD5')
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN816"
>Source File Time Stamps</A
></H3
><P
>&#13; If you prefer, you can
configure <TT
CLASS="APPLICATION"
>SCons</TT
> to use the modification time
of source files,
not the file contents,
when deciding if something needs to be rebuilt.
To do this, call the <TT
CLASS="FUNCTION"
>SourceSignatures</TT
>
function as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('hello.c')
SourceSignatures('timestamp')
</PRE
></TD
></TR
></TABLE
><P
>&#13; This makes <TT
CLASS="APPLICATION"
>SCons</TT
> act like <TT
CLASS="APPLICATION"
>Make</TT
>
when a file's modification time is updated
(using the <TT
CLASS="APPLICATION"
>touch</TT
> command, for example):
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>touch hello.c</KBD
>
% <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
</PRE
></TD
></TR
></TABLE
></DIV
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN830"
>Deciding When a Target File Has Changed: the <TT
CLASS="FUNCTION"
>TargetSignatures</TT
> Function</A
></H2
><P
>&#13; As you've just seen,
<TT
CLASS="APPLICATION"
>SCons</TT
> uses signatures to decide whether a
target file is up to date or must be rebuilt.
When a target file depends on another target file,
<TT
CLASS="APPLICATION"
>SCons</TT
> allows you to configure separately
how the signatures of "intermediate" target files
are used when deciding if a dependent target file
must be rebuilt.
</P
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN836"
>Build Signatures</A
></H3
><P
>&#13; Modifying a source file
will cause not only its direct target file to be rebuilt,
but also the target file(s)
that depend on that direct target file.
In our example,
changing the contents of the <TT
CLASS="FILENAME"
>hello.c</TT
> file causes
the <TT
CLASS="FILENAME"
>hello.o</TT
> file to be rebuilt,
which in turn causes the
<TT
CLASS="APPLICATION"
>hello</TT
> program to be rebuilt:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>edit hello.c</KBD
>
[CHANGE THE CONTENTS OF hello.c]
% <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; What's not obvious, though,
is that <TT
CLASS="APPLICATION"
>SCons</TT
> internally handles the signature of
the target file(s)
(<TT
CLASS="FILENAME"
>hello.o</TT
> in the above example)
differently from the signature of the source file
(<TT
CLASS="FILENAME"
>hello.c</TT
>).
By default,
<TT
CLASS="APPLICATION"
>SCons</TT
> tracks whether a target file must be rebuilt
by using a <TT
CLASS="LITERAL"
>build signature</TT
>
that consists of the combined
signatures of all the files
that go into making the target file.
This is efficient because
the accumulated signatures
actually give <TT
CLASS="APPLICATION"
>SCons</TT
> all of the
information it needs
to decide if the target file is out of date.
</P
><P
>&#13; If you wish, you can
specify this default behavior
(build signatures) explicitly
using the <TT
CLASS="FUNCTION"
>TargetSignatures</TT
> function:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('hello.c')
TargetSignatures('build')
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN856"
>File Contents</A
></H3
><P
>&#13; Sometimes a source file can be changed
in such a way that the contents of the
rebuilt target file(s)
will be exactly the same as the last time
the file was built.
If so, then any other target files
that depend on such a built-but-not-changed target
file actually need not be rebuilt.
You can make <TT
CLASS="APPLICATION"
>SCons</TT
>
realize that it does not need to rebuild
a dependent target file in this situation
using the <TT
CLASS="FUNCTION"
>TargetSignatures</TT
> function as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('hello.c')
TargetSignatures('content')
</PRE
></TD
></TR
></TABLE
><P
>&#13; So if, for example,
a user were to only change a comment in a C file,
then the rebuilt <TT
CLASS="FILENAME"
>hello.o</TT
> file
would be exactly the same as the one previously built
(assuming the compiler doesn't put any build-specific
information in the object file).
<TT
CLASS="APPLICATION"
>SCons</TT
> would then realize that it would not
need to rebuild the <TT
CLASS="APPLICATION"
>hello</TT
> program as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>edit hello.c</KBD
>
[CHANGE A COMMENT IN hello.c]
% <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -c -o hello.o hello.c
scons: `hello' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; In essence, <TT
CLASS="APPLICATION"
>SCons</TT
> has
"short-circuited" any dependent builds
when it realizes that a target file
has been rebuilt to exactly the same file as the last build.
So configured,
<TT
CLASS="APPLICATION"
>SCons</TT
> does take some extra processing time
to scan the contents of the target (<TT
CLASS="FILENAME"
>hello.o</TT
>) file,
but this may save time
if the rebuild that was avoided
would have been very time-consuming and expensive.
</P
></DIV
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN874"
>Implicit Dependencies: The <VAR
CLASS="ENVAR"
>$CPPPATH</VAR
> Construction Variable</A
></H2
><P
>&#13; Now suppose that our "Hello, World!" program
actually has a <TT
CLASS="LITERAL"
>#include</TT
> line
to include the <TT
CLASS="FILENAME"
>hello.h</TT
> file in the compilation:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> #include &#60;hello.h&#62;
int
main()
{
printf("Hello, %s!\n", string);
}
</PRE
></TD
></TR
></TABLE
><P
>&#13; And, for completeness, the <TT
CLASS="FILENAME"
>hello.h</TT
> file looks like this:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> #define string "world"
</PRE
></TD
></TR
></TABLE
><P
>&#13; In this case, we want <TT
CLASS="APPLICATION"
>SCons</TT
> to recognize that,
if the contents of the <TT
CLASS="FILENAME"
>hello.h</TT
> file change,
the <TT
CLASS="APPLICATION"
>hello</TT
> program must be recompiled.
To do this, we need to modify the
<TT
CLASS="FILENAME"
>SConstruct</TT
> file like so:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('hello.c', CPPPATH = '.')
</PRE
></TD
></TR
></TABLE
><P
>&#13; The <VAR
CLASS="ENVAR"
>$CPPPATH</VAR
> value
tells <TT
CLASS="APPLICATION"
>SCons</TT
> to look in the current directory
(<TT
CLASS="LITERAL"
>'.'</TT
>)
for any files included by C source files
(<TT
CLASS="FILENAME"
>.c</TT
> or <TT
CLASS="FILENAME"
>.h</TT
> files).
With this assignment in the <TT
CLASS="FILENAME"
>SConstruct</TT
> file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -I. -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
scons: `hello' is up to date.
% <KBD
CLASS="USERINPUT"
>edit hello.h</KBD
>
[CHANGE THE CONTENTS OF hello.h]
% <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -I. -c -o hello.o hello.c
cc -o hello hello.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; First, notice that <TT
CLASS="APPLICATION"
>SCons</TT
>
added the <TT
CLASS="LITERAL"
>-I.</TT
> argument
from the <VAR
CLASS="ENVAR"
>$CPPPATH</VAR
> variable
so that the compilation would find the
<TT
CLASS="FILENAME"
>hello.h</TT
> file in the local directory.
</P
><P
>&#13; Second, realize that <TT
CLASS="APPLICATION"
>SCons</TT
> knows that the <TT
CLASS="APPLICATION"
>hello</TT
>
program must be rebuilt
because it scans the contents of
the <TT
CLASS="FILENAME"
>hello.c</TT
> file
for the <TT
CLASS="LITERAL"
>#include</TT
> lines that indicate
another file is being included in the compilation.
<TT
CLASS="APPLICATION"
>SCons</TT
> records these as
<I
CLASS="EMPHASIS"
>implicit dependencies</I
>
of the target file,
Consequently,
when the <TT
CLASS="FILENAME"
>hello.h</TT
> file changes,
<TT
CLASS="APPLICATION"
>SCons</TT
> realizes that the <TT
CLASS="FILENAME"
>hello.c</TT
> file includes it,
and rebuilds the resulting <TT
CLASS="APPLICATION"
>hello</TT
> program
that depends on both the <TT
CLASS="FILENAME"
>hello.c</TT
> and <TT
CLASS="FILENAME"
>hello.h</TT
> files.
</P
><P
>&#13; Like the <VAR
CLASS="ENVAR"
>$LIBPATH</VAR
> variable,
the <VAR
CLASS="ENVAR"
>$CPPPATH</VAR
> variable
may be a list of directories,
or a string separated by
the system-specific path separate character
(':' on POSIX/Linux, ';' on Windows).
Either way, <TT
CLASS="APPLICATION"
>SCons</TT
> creates the
right command-line options
so that the following example:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Program('hello.c', CPPPATH = ['include', '/home/project/inc'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; Will look like this on POSIX or Linux:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -Iinclude -I/home/project/inc -c -o hello.o hello.c
cc -o hello hello.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; And like this on Windows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons -Q hello.exe</KBD
>
cl /nologo /Iinclude /I\home\project\inc /c hello.c /Fohello.obj
link /nologo /OUT:hello.exe hello.obj
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN931"
>Caching Implicit Dependencies</A
></H2
><P
>&#13; Scanning each file for <TT
CLASS="LITERAL"
>#include</TT
> lines
does take some extra processing time.
When you're doing a full build of a large system,
the scanning time is usually a very small percentage
of the overall time spent on the build.
You're most likely to notice the scanning time,
however, when you <I
CLASS="EMPHASIS"
>rebuild</I
>
all or part of a large system:
<TT
CLASS="APPLICATION"
>SCons</TT
> will likely take some extra time to "think about"
what must be built before it issues the
first build command
(or decides that everything is up to date
and nothing must be rebuilt).
</P
><P
>&#13; In practice, having <TT
CLASS="APPLICATION"
>SCons</TT
> scan files saves time
relative to the amount of potential time
lost to tracking down subtle problems
introduced by incorrect dependencies.
Nevertheless, the "waiting time"
while <TT
CLASS="APPLICATION"
>SCons</TT
> scans files can annoy
individual developers waiting for their builds to finish.
Consequently, <TT
CLASS="APPLICATION"
>SCons</TT
> lets you cache
the implicit dependencies
that its scanners find,
for use by later builds.
You can do this by specifying the
<TT
CLASS="LITERAL"
>--implicit-cache</TT
> option on the command line:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q --implicit-cache hello</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
scons: `hello' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; If you don't want to specify <TT
CLASS="LITERAL"
>--implicit-cache</TT
>
on the command line each time,
you can make it the default behavior for your build
by setting the <TT
CLASS="LITERAL"
>implicit_cache</TT
> option
in an <TT
CLASS="FILENAME"
>SConscript</TT
> file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> SetOption('implicit_cache', 1)
</PRE
></TD
></TR
></TABLE
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN950"
>The <TT
CLASS="LITERAL"
>--implicit-deps-changed</TT
> Option</A
></H3
><P
>&#13; When using cached implicit dependencies,
sometimes you want to "start fresh"
and have <TT
CLASS="APPLICATION"
>SCons</TT
> re-scan the files
for which it previously cached the dependencies.
For example,
if you have recently installed a new version of
external code that you use for compilation,
the external header files will have changed
and the previously-cached implicit dependencies
will be out of date.
You can update them by
running <TT
CLASS="APPLICATION"
>SCons</TT
> with the <TT
CLASS="LITERAL"
>--implicit-deps-changed</TT
> option:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q --implicit-deps-changed hello</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
scons: `hello' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; In this case, <TT
CLASS="APPLICATION"
>SCons</TT
> will re-scan all of the implicit dependencies
and cache updated copies of the information.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN962"
>The <TT
CLASS="LITERAL"
>--implicit-deps-unchanged</TT
> Option</A
></H3
><P
>&#13; By default when caching dependencies,
<TT
CLASS="APPLICATION"
>SCons</TT
> notices when a file has been modified
and re-scans the file for any updated
implicit dependency information.
Sometimes, however, you may want
to force <TT
CLASS="APPLICATION"
>SCons</TT
> to use the cached implicit dependencies,
even if the source files changed.
This can speed up a build for example,
when you have changed your source files
but know that you haven't changed
any <TT
CLASS="LITERAL"
>#include</TT
> lines.
In this case,
you can use the <TT
CLASS="LITERAL"
>--implicit-deps-unchanged</TT
> option:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q --implicit-deps-unchanged hello</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
scons: `hello' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; In this case,
<TT
CLASS="APPLICATION"
>SCons</TT
> will assume that the cached implicit
dependencies are correct and
will not bother to re-scan changed files.
For typical builds after small,
incremental changes to source files,
the savings may not be very big,
but sometimes every bit of
improved performance counts.
</P
></DIV
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN975"
>Ignoring Dependencies: the <TT
CLASS="FUNCTION"
>Ignore</TT
> Method</A
></H2
><P
>&#13; Sometimes it makes sense
to not rebuild a program,
even if a dependency file changes.
In this case,
you would tell <TT
CLASS="APPLICATION"
>SCons</TT
> specifically
to ignore a dependency as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> hello = Program('hello.c')
Ignore(hello, 'hello.h')
</PRE
></TD
></TR
></TABLE
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
scons: `hello' is up to date.
% <KBD
CLASS="USERINPUT"
>edit hello.h</KBD
>
[CHANGE THE CONTENTS OF hello.h]
% <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
scons: `hello' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; Now, the above example is a little contrived,
because it's hard to imagine a real-world situation
where you wouldn't to rebuild <TT
CLASS="APPLICATION"
>hello</TT
>
if the <TT
CLASS="FILENAME"
>hello.h</TT
> file changed.
A more realistic example
might be if the <TT
CLASS="APPLICATION"
>hello</TT
>
program is being built in a
directory that is shared between multiple systems
that have different copies of the
<TT
CLASS="FILENAME"
>stdio.h</TT
> include file.
In that case,
<TT
CLASS="APPLICATION"
>SCons</TT
> would notice the differences between
the different systems' copies of <TT
CLASS="FILENAME"
>stdio.h</TT
>
and would rebuild <TT
CLASS="APPLICATION"
>hello</TT
>
each time you change systems.
You could avoid these rebuilds as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> hello = Program('hello.c')
Ignore(hello, '/usr/include/stdio.h')
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN995"
>Explicit Dependencies: the <TT
CLASS="FUNCTION"
>Depends</TT
> Method</A
></H2
><P
>&#13; On the other hand,
sometimes a file depends on another file
that is not detected by an <TT
CLASS="APPLICATION"
>SCons</TT
> scanner.
For this situation,
<TT
CLASS="APPLICATION"
>SCons</TT
> allows you to specific explicitly that one file
depends on another file,
and must be rebuilt whenever that file changes.
This is specified using the <TT
CLASS="FUNCTION"
>Depends</TT
> method:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> hello = Program('hello.c')
Depends(hello, 'other_file')
</PRE
></TD
></TR
></TABLE
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -c hello.c -o hello.o
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
scons: `hello' is up to date.
% <KBD
CLASS="USERINPUT"
>edit other_file</KBD
>
[CHANGE THE CONTENTS OF other_file]
% <KBD
CLASS="USERINPUT"
>scons -Q hello</KBD
>
cc -c hello.c -o hello.o
cc -o hello hello.o
</PRE
></TD
></TR
></TABLE
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-ENVIRONMENTS"
></A
>Construction Environments</H1
><P
>&#13; It is rare that all of the software in a large,
complicated system needs to be built the same way.
For example, different source files may need different options
enabled on the command line,
or different executable programs need to be linked
with different libraries.
<TT
CLASS="APPLICATION"
>SCons</TT
> accomodates these different build
requirements by allowing you to create and
configure multiple <TT
CLASS="LITERAL"
>construction environments</TT
>
that control how the software is built.
Technically, a <TT
CLASS="LITERAL"
>construction environment</TT
> is an object
that has a number of associated
<TT
CLASS="LITERAL"
>construction variables</TT
>, each with a name and a value.
(A construction environment also has an attached
set of <CODE
CLASS="CLASSNAME"
>Builder</CODE
> methods,
about which we'll learn more later.)
</P
><P
>&#13; A <TT
CLASS="LITERAL"
>construction environment</TT
> is created by the <TT
CLASS="FUNCTION"
>Environment</TT
> method:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
</PRE
></TD
></TR
></TABLE
><P
>&#13; By default, <TT
CLASS="APPLICATION"
>SCons</TT
> intializes every
new construction environment
with a set of <TT
CLASS="LITERAL"
>construction variables</TT
>
based on the tools that it finds on your system,
plus the default set of builder methods
necessary for using those tools.
The construction variables
are initialized with values describing
the C compiler,
the Fortran compiler,
the linker,
etc.,
as well as the command lines to invoke them.
</P
><P
>&#13; When you initialize a construction environment
you can set the values of the
environment's <TT
CLASS="LITERAL"
>construction variables</TT
>
to control how a program is built.
For example:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment(CC = 'gcc',
CCFLAGS = '-O2')
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
><P
>
The construction environment in this example
is still initialized with the same default
construction variable values,
except that the user has explicitly specified use of the
GNU C compiler <TT
CLASS="APPLICATION"
>gcc</TT
>,
and further specifies that the <TT
CLASS="LITERAL"
>-O2</TT
>
(optimization level two)
flag should be used when compiling the object file.
In other words, the explicit initializations of
<A
HREF="#CV-CC"
><VAR
CLASS="ENVAR"
>$CC</VAR
></A
> and <A
HREF="#CV-CCFLAGS"
><VAR
CLASS="ENVAR"
>$CCFLAGS</VAR
></A
>
override the default values in the newly-created
construction environment.
So a run from this example would look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
gcc -O2 -c -o foo.o foo.c
gcc -o foo foo.o
</PRE
></TD
></TR
></TABLE
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1035"
>Multiple <TT
CLASS="LITERAL"
>Construction Environments</TT
></A
></H2
><P
>&#13; The real advantage of construction environments
is that you can create as many different construction
environments as you need,
each tailored to a different way to build
some piece of software or other file.
If, for example, we need to build
one program with the <TT
CLASS="LITERAL"
>-O2</TT
> flag
and another with the <TT
CLASS="LITERAL"
>-g</TT
> (debug) flag,
we would do this like so:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opt = Environment(CCFLAGS = '-O2')
dbg = Environment(CCFLAGS = '-g')
opt.Program('foo', 'foo.c')
dbg.Program('bar', 'bar.c')
</PRE
></TD
></TR
></TABLE
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -g -c -o bar.o bar.c
cc -o bar bar.o
cc -O2 -c -o foo.o foo.c
cc -o foo foo.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; We can even use multiple construction environments to build
multiple versions of a single program.
If you do this by simply trying to use the
<A
HREF="#B-PROGRAM"
><TT
CLASS="FUNCTION"
>Program</TT
></A
> builder with both environments, though,
like this:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opt = Environment(CCFLAGS = '-O2')
dbg = Environment(CCFLAGS = '-g')
opt.Program('foo', 'foo.c')
dbg.Program('foo', 'foo.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Then <TT
CLASS="APPLICATION"
>SCons</TT
> generates the following error:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
scons: *** Two environments with different actions were specified for the same target: foo.o
File "SConstruct", line 6, in ?
</PRE
></TD
></TR
></TABLE
><P
>&#13; This is because the two <TT
CLASS="FUNCTION"
>Program</TT
> calls have
each implicitly told <TT
CLASS="APPLICATION"
>SCons</TT
> to generate an object file named
<TT
CLASS="FILENAME"
>foo.o</TT
>,
one with a <A
HREF="#CV-CCFLAGS"
><VAR
CLASS="ENVAR"
>$CCFLAGS</VAR
></A
> value of
<TT
CLASS="LITERAL"
>-O2</TT
>
and one with a <A
HREF="#CV-CCFLAGS"
><VAR
CLASS="ENVAR"
>$CCFLAGS</VAR
></A
> value of
<TT
CLASS="LITERAL"
>-g</TT
>.
<TT
CLASS="APPLICATION"
>SCons</TT
> can't just decide that one of them
should take precedence over the other,
so it generates the error.
To avoid this problem,
we must explicitly specify
that each environment compile
<TT
CLASS="FILENAME"
>foo.c</TT
>
to a separately-named object file
using the <A
HREF="#B-OBJECT"
><TT
CLASS="FUNCTION"
>Object</TT
></A
> builder, like so:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opt = Environment(CCFLAGS = '-O2')
dbg = Environment(CCFLAGS = '-g')
o = opt.Object('foo-opt', 'foo.c')
opt.Program(o)
d = dbg.Object('foo-dbg', 'foo.c')
dbg.Program(d)
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice that each call to the <TT
CLASS="FUNCTION"
>Object</TT
> builder
returns a value,
an internal <TT
CLASS="APPLICATION"
>SCons</TT
> object that
represents the object file that will be built.
We then use that object
as input to the <TT
CLASS="FUNCTION"
>Program</TT
> builder.
This avoids having to specify explicitly
the object file name in multiple places,
and makes for a compact, readable
<TT
CLASS="FILENAME"
>SConstruct</TT
> file.
Our <TT
CLASS="APPLICATION"
>SCons</TT
> output then looks like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -g -c -o foo-dbg.o foo.c
cc -o foo-dbg foo-dbg.o
cc -O2 -c -o foo-opt.o foo.c
cc -o foo-opt foo-opt.o
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1075"
>Copying <TT
CLASS="LITERAL"
>Construction Environments</TT
></A
></H2
><P
>&#13; Sometimes you want more than one construction environment
to share the same values for one or more variables.
Rather than always having to repeat all of the common
variables when you create each construction environment,
you can use the <TT
CLASS="FUNCTION"
>Copy</TT
> method
to create a copy of a construction environment.
</P
><P
>&#13; Like the <TT
CLASS="FUNCTION"
>Environment</TT
> call that creates a construction environment,
the <TT
CLASS="FUNCTION"
>Copy</TT
> method takes <TT
CLASS="LITERAL"
>construction variable</TT
> assignments,
which will override the values in the copied construction environment.
For example, suppose we want to use <TT
CLASS="APPLICATION"
>gcc</TT
>
to create three versions of a program,
one optimized, one debug, and one with neither.
We could do this by creating a "base" construction environment
that sets <A
HREF="#CV-CC"
><VAR
CLASS="ENVAR"
>$CC</VAR
></A
> to <TT
CLASS="APPLICATION"
>gcc</TT
>,
and then creating two copies,
one which sets <A
HREF="#CV-CCFLAGS"
><VAR
CLASS="ENVAR"
>$CCFLAGS</VAR
></A
> for optimization
and the other which sets <VAR
CLASS="ENVAR"
>$CCFLAGS</VAR
> for debugging:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment(CC = 'gcc')
opt = env.Copy(CCFLAGS = '-O2')
dbg = env.Copy(CCFLAGS = '-g')
env.Program('foo', 'foo.c')
o = opt.Object('foo-opt', 'foo.c')
opt.Program(o)
d = dbg.Object('foo-dbg', 'foo.c')
dbg.Program(d)
</PRE
></TD
></TR
></TABLE
><P
>&#13; Then our output would look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
gcc -c -o foo.o foo.c
gcc -o foo foo.o
gcc -g -c -o foo-dbg.o foo.c
gcc -o foo-dbg foo-dbg.o
gcc -O2 -c -o foo-opt.o foo.c
gcc -o foo-opt foo-opt.o
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1095"
>Fetching Values From a <TT
CLASS="LITERAL"
>Construction Environment</TT
></A
></H2
><P
>&#13; You can fetch individual construction variables
using the normal syntax
for accessing individual named items in a Python dictionary:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
print "CC is:", env['CC']
</PRE
></TD
></TR
></TABLE
><P
>&#13; This example <TT
CLASS="FILENAME"
>SConstruct</TT
> file doesn't build anything,
but because it's actually a Python script,
it will print the value of <A
HREF="#CV-CC"
><VAR
CLASS="ENVAR"
>$CC</VAR
></A
> for us:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
CC is: cc
scons: `.' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; A construction environment, however,
is actually an object with associated methods, etc.
If you want to have direct access to only the
dictionary of construction variables,
you can fetch this using the <TT
CLASS="LITERAL"
>Dictionary</TT
> method:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment(FOO = 'foo', BAR = 'bar')
dict = env.Dictionary()
for key in ['OBJSUFFIX', 'LIBSUFFIX', 'PROGSUFFIX']:
print "key = %s, value = %s" % (key, dict[key])
</PRE
></TD
></TR
></TABLE
><P
>&#13; This <TT
CLASS="FILENAME"
>SConstruct</TT
> file
will print the specified dictionary items for us on POSIX
systems as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
key = OBJSUFFIX, value = .o
key = LIBSUFFIX, value = .a
key = PROGSUFFIX, value =
scons: `.' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; And on Win32:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
key = OBJSUFFIX, value = .obj
key = LIBSUFFIX, value = .lib
key = PROGSUFFIX, value = .exe
scons: `.' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; If you want to loop through and print the values of
all of the construction variables in a construction environment,
the Python code to do that in sorted order might look something like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
dict = env.Dictionary()
keys = dict.keys()
keys.sort()
for key in keys:
print "construction variable = '%s', value = '%s'" % (key, dict[key])
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1118"
>Expanding Values From a <TT
CLASS="LITERAL"
>Construction Environment</TT
></A
></H2
><P
>&#13; Another way to get information from
a construction environment.
is to use the <TT
CLASS="FUNCTION"
>subst</TT
> method
on a string containing $-expansions
of construction variable names.
As a simple example,
the example from the previous
section that used
<TT
CLASS="LITERAL"
>env['CC']</TT
>
to fetch the value of <A
HREF="#CV-CC"
><VAR
CLASS="ENVAR"
>$CC</VAR
></A
>
could also be written as:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
print "CC is:", env.subst('$CC')
</PRE
></TD
></TR
></TABLE
><P
>&#13; The real advantage of using
<TT
CLASS="FUNCTION"
>subst</TT
> to expand strings is
that construction variables
in the result get
re-expanded until
there are no expansions left in the string.
So a simple fetch of a value like
<A
HREF="#CV-CCCOM"
><VAR
CLASS="ENVAR"
>$CCCOM</VAR
></A
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment(CCFLAGS = '-DFOO')
print "CCCOM is:", env['CCCOM']
</PRE
></TD
></TR
></TABLE
><P
>&#13; Will print the unexpanded value of <VAR
CLASS="ENVAR"
>$CCCOM</VAR
>,
showing us the construction
variables that still need to be expanded:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
CCCOM is: $CC $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES
scons: `.' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; Calling the <TT
CLASS="FUNCTION"
>subst</TT
> method on <VAR
CLASS="VARNAME"
>$CCOM</VAR
>,
however:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment(CCFLAGS = '-DFOO')
print "CCCOM is:", env.subst('$CCCOM')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Will recursively expand all of
the $-prefixed construction variables,
showing us the final output:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
CCCOM is: gcc -DFOO -c -o
scons: `.' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; (Note that because we're not expanding this
in the context of building something
there are no target or source files
for <A
HREF="#CV-TARGET"
><VAR
CLASS="ENVAR"
>$TARGET</VAR
></A
> and <A
HREF="#CV-SOURCES"
><VAR
CLASS="ENVAR"
>$SOURCES</VAR
></A
> to expand.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1148"
>Modifying a <TT
CLASS="LITERAL"
>Construction Environment</TT
></A
></H2
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> provides various methods that
support modifying existing values in a construction environment.
</P
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN1153"
>Replacing Values in a <TT
CLASS="LITERAL"
>Construction Environment</TT
></A
></H3
><P
>&#13; You can replace existing construction variable values
using the <TT
CLASS="FUNCTION"
>Replace</TT
> method:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment(CCFLAGS = '-DDEFINE1')
env.Replace(CCFLAGS = '-DDEFINE2')
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; The replacing value
(<TT
CLASS="LITERAL"
>-DDEFINE2</TT
> in the above example)
completely replaces the value in the
construction environment:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -DDEFINE2 -c -o foo.o foo.c
cc -o foo foo.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; You can safely call <TT
CLASS="FUNCTION"
>Replace</TT
>
for construction variables that
don't exist in the construction environment:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
env.Replace(NEW_VARIABLE = 'xyzzy')
print "NEW_VARIABLE =", env['NEW_VARIABLE']
</PRE
></TD
></TR
></TABLE
><P
>&#13; In this case,
the construction variable simply
gets added to the construction environment:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
NEW_VARIABLE = xyzzy
scons: `.' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; Because the variables
aren't expanded until the construction environment
is actually used to build the targets,
and because <TT
CLASS="APPLICATION"
>SCons</TT
> function and method calls
are order-independent,
the last replacement "wins"
and is used to build all targets,
regardless of the order in which
the calls to Replace() are
interspersed with calls to
builder methods:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment(CCFLAGS = '-DDEFINE1')
print "CCFLAGS =", env['CCFLAGS']
env.Program('foo.c')
env.Replace(CCFLAGS = '-DDEFINE2')
print "CCFLAGS =", env['CCFLAGS']
env.Program('bar.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; The timing of when the replacement
actually occurs relative
to when the targets get built
becomes apparent
if we run <TT
CLASS="APPLICATION"
>scons</TT
> without the <TT
CLASS="LITERAL"
>-Q</TT
>
option:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
CCFLAGS = -DDEFINE1
CCFLAGS = -DDEFINE2
scons: done reading SConscript files.
scons: Building targets ...
cc -DDEFINE2 -c -o bar.o bar.c
cc -o bar bar.o
cc -DDEFINE2 -c -o foo.o foo.c
cc -o foo foo.o
scons: done building targets.
</PRE
></TD
></TR
></TABLE
><P
>&#13; Because the replacement occurs while
the <TT
CLASS="FILENAME"
>SConscript</TT
> files are being read,
the <A
HREF="#CV-CCFLAGS"
><VAR
CLASS="ENVAR"
>$CCFLAGS</VAR
></A
>
variable has already been set to
<TT
CLASS="LITERAL"
>-DDEFINE2</TT
>
by the time the <TT
CLASS="FILENAME"
>foo.o</TT
> target is built,
even though the call to the <TT
CLASS="FUNCTION"
>Replace</TT
>
method does not occur until later in
the <TT
CLASS="FILENAME"
>SConscript</TT
> file.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN1185"
>Appending to the End of Values in a <TT
CLASS="LITERAL"
>Construction Environment</TT
></A
></H3
><P
>&#13; You can append a value to
an existing construction variable
using the <TT
CLASS="FUNCTION"
>Append</TT
> method:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment(CCFLAGS = '-DMY_VALUE')
env.Append(CCFLAGS = ' -DLAST')
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> then supplies both the <TT
CLASS="LITERAL"
>-DMY_VALUE</TT
> and
<TT
CLASS="LITERAL"
>-DLAST</TT
> flags when compiling the object file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -DMY_VALUE -DLAST -c -o foo.o foo.c
cc -o foo foo.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; If the construction variable doesn't already exist,
the <TT
CLASS="FUNCTION"
>Append</TT
> method will create it:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
env.Append(NEW_VARIABLE = 'added')
print "NEW_VARIABLE =", env['NEW_VARIABLE']
</PRE
></TD
></TR
></TABLE
><P
>&#13; Which yields:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
NEW_VARIABLE = added
scons: `.' is up to date.
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN1203"
>Appending to the Beginning of Values in a <TT
CLASS="LITERAL"
>Construction Environment</TT
></A
></H3
><P
>&#13; You can append a value to the beginning
an existing construction variable
using the <TT
CLASS="FUNCTION"
>Prepend</TT
> method:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment(CCFLAGS = '-DMY_VALUE')
env.Prepend(CCFLAGS = '-DFIRST ')
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> then supplies both the <TT
CLASS="LITERAL"
>-DFIRST</TT
> and
<TT
CLASS="LITERAL"
>-DMY_VALUE</TT
> flags when compiling the object file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -DFIRST -DMY_VALUE -c -o foo.o foo.c
cc -o foo foo.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; If the construction variable doesn't already exist,
the <TT
CLASS="FUNCTION"
>Prepend</TT
> method will create it:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
env.Prepend(NEW_VARIABLE = 'added')
print "NEW_VARIABLE =", env['NEW_VARIABLE']
</PRE
></TD
></TR
></TABLE
><P
>&#13; Which yields:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
NEW_VARIABLE = added
scons: `.' is up to date.
</PRE
></TD
></TR
></TABLE
></DIV
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-ENV"
></A
>Controlling the External Environment Used to Execute Build Commands</H1
><P
>&#13; When <TT
CLASS="APPLICATION"
>SCons</TT
> builds a target file,
it does not execute the commands with
the same external environment
that you used to execute <TT
CLASS="APPLICATION"
>SCons</TT
>.
Instead, it uses the dictionary
stored in the <A
HREF="#CV-ENV"
><VAR
CLASS="ENVAR"
>$ENV</VAR
></A
> construction variable
as the external environment
for executing commands.
</P
><P
>&#13; The most important ramification of this behavior
is that the <VAR
CLASS="VARNAME"
>PATH</VAR
> environment variable,
which controls where the operating system
will look for commands and utilities,
is not the same as in the external environment
from which you called <TT
CLASS="APPLICATION"
>SCons</TT
>.
This means that <TT
CLASS="APPLICATION"
>SCons</TT
> will not, by default,
necessarily find all of the tools
that you can execute from the command line.
</P
><P
>&#13; The default value of the <VAR
CLASS="VARNAME"
>PATH</VAR
> environment variable
on a POSIX system
is <TT
CLASS="LITERAL"
>/usr/local/bin:/bin:/usr/bin</TT
>.
The default value of the <VAR
CLASS="VARNAME"
>PATH</VAR
> environment variable
on a Win32 system comes from the Windows registry
value for the command interpreter.
If you want to execute any commands--compilers, linkers, etc.--that
are not in these default locations,
you need to set the <VAR
CLASS="VARNAME"
>PATH</VAR
> value
in the <VAR
CLASS="ENVAR"
>$ENV</VAR
> dictionary
in your construction environment.
</P
><P
>&#13; The simplest way to do this is to initialize explicitly
the value when you create the construction environment;
this is one way to do that:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> path = ['/usr/local/bin', '/bin', '/usr/bin']
env = Environment(ENV = {'PATH' : path})
</PRE
></TD
></TR
></TABLE
><P
>&#13; Assign a dictionary to the <VAR
CLASS="ENVAR"
>$ENV</VAR
>
construction variable in this way
completely resets the external environment
so that the only variable that will be
set when external commands are executed
will be the <VAR
CLASS="VARNAME"
>PATH</VAR
> value.
If you want to use the rest of
the values in <VAR
CLASS="ENVAR"
>$ENV</VAR
> and only
set the value of <VAR
CLASS="VARNAME"
>PATH</VAR
>,
the most straightforward way is probably:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env['ENV']['PATH'] = ['/usr/local/bin', '/bin', '/usr/bin']
</PRE
></TD
></TR
></TABLE
><P
>&#13; Note that <TT
CLASS="APPLICATION"
>SCons</TT
> does allow you to define
the directories in the <VAR
CLASS="VARNAME"
>PATH</VAR
> in a string,
separated by the pathname-separator character
for your system (':' on POSIX systems, ';' on Windows):
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin'
</PRE
></TD
></TR
></TABLE
><P
>&#13; But doing so makes your <TT
CLASS="FILENAME"
>SConscript</TT
> file less portable,
(although in this case that may not be a huge concern
since the directories you list are likley system-specific, anyway).
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1252"
>Propagating <VAR
CLASS="VARNAME"
>PATH</VAR
> From the External Environment</A
></H2
><P
>&#13; You may want to propagate the external <VAR
CLASS="VARNAME"
>PATH</VAR
>
to the execution environment for commands.
You do this by initializing the <VAR
CLASS="VARNAME"
>PATH</VAR
>
variable with the <VAR
CLASS="VARNAME"
>PATH</VAR
> value from
the <TT
CLASS="LITERAL"
>os.environ</TT
>
dictionary,
which is Python's way of letting you
get at the external environment:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> import os
env = Environment(ENV = {'PATH' : os.environ['PATH']})
</PRE
></TD
></TR
></TABLE
><P
>&#13; Alternatively, you may find it easier
to just propagate the entire external
environment to the execution environment
for commands.
This is simpler to code than explicity
selecting the <VAR
CLASS="VARNAME"
>PATH</VAR
> value:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> import os
env = Environment(ENV = os.environ)
</PRE
></TD
></TR
></TABLE
><P
>&#13; Either of these will guarantee that
<TT
CLASS="APPLICATION"
>SCons</TT
> will be able to execute
any command that you can execute from the command line.
The drawback is that the build can behave
differently if it's run by people with
different <VAR
CLASS="VARNAME"
>PATH</VAR
> values in their environment--for example,
both the <TT
CLASS="LITERAL"
>/bin</TT
> and
<TT
CLASS="LITERAL"
>/usr/local/bin</TT
> directories
have different <TT
CLASS="APPLICATION"
>cc</TT
> commands,
then which one will be used to compile programs
will depend on which directory is listed
first in the user's <VAR
CLASS="VARNAME"
>PATH</VAR
> variable.
</P
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-COMMAND-LINE"
></A
>Controlling a Build From the Command Line</H1
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> provides a number of ways that
allow the writer of the <TT
CLASS="FILENAME"
>SConscript</TT
> files
to give users a great deal of control over how to run the builds.
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1276"
>Not Having to Specify Command-Line Options Each Time: the <VAR
CLASS="VARNAME"
>SCONSFLAGS</VAR
> Environment Variable</A
></H2
><P
>&#13; Users may find themselves supplying
the same command-line options every time
they run <TT
CLASS="APPLICATION"
>SCons</TT
>.
For example, a user might find that it saves time
to specify a value of <TT
CLASS="LITERAL"
>-j 2</TT
>
to run the builds in parallel.
To avoid having to type <TT
CLASS="LITERAL"
>-j 2</TT
> by hand
every time,
you can set the external environment variable
<VAR
CLASS="VARNAME"
>SCONSFLAGS</VAR
> to a string containing
command-line options that you want <TT
CLASS="APPLICATION"
>SCons</TT
> to use.
</P
><P
>&#13; If, for example,
and you're using a POSIX shell that's
compatible with the Bourne shell,
and you always want <TT
CLASS="APPLICATION"
>SCons</TT
> to use the
<TT
CLASS="LITERAL"
>-Q</TT
> option,
you can set the <VAR
CLASS="VARNAME"
>SCONSFLAGS</VAR
>
environment as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
... [build output] ...
scons: done building targets.
% <KBD
CLASS="USERINPUT"
>export SCONSFLAGS="-Q"</KBD
>
% <KBD
CLASS="USERINPUT"
>scons</KBD
>
... [build output] ...
</PRE
></TD
></TR
></TABLE
><P
>&#13; Users of <TT
CLASS="APPLICATION"
>csh</TT
>-style shells on POSIX systems
can set the <VAR
CLASS="VARNAME"
>SCONSFLAGS</VAR
> environment as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> $ <KBD
CLASS="USERINPUT"
>setenv SCONSFLAGS "-Q"</KBD
>
</PRE
></TD
></TR
></TABLE
><P
>&#13; Windows users may typically want to set this
<VAR
CLASS="VARNAME"
>SCONSFLAGS</VAR
> in the appropriate tab of the
<TT
CLASS="LITERAL"
>System Properties</TT
> window.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1301"
>Getting at Command-Line Targets</A
></H2
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> supports a <VAR
CLASS="VARNAME"
>COMMAND_LINE_TARGETS</VAR
> variable
that lets you get at the list of targets that the
user specified on the command line.
You can use the targets to manipulate the
build in any way you wish.
As a simple example,
suppose that you want to print a reminder
to the user whenever a specific program is built.
You can do this by checking for the
target in the <VAR
CLASS="VARNAME"
>COMMAND_LINE_TARGETS</VAR
> list:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> if 'bar' in COMMAND_LINE_TARGETS:
print "Don't forget to copy `bar' to the archive!"
Default(Program('foo.c'))
Program('bar.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Then, running <TT
CLASS="APPLICATION"
>SCons</TT
> with the default target
works as it always does,
but explicity specifying the <TT
CLASS="APPLICATION"
>bar</TT
> target
on the command line generates the warning message:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o foo.o foo.c
cc -o foo foo.o
% <KBD
CLASS="USERINPUT"
>scons -Q bar</KBD
>
Don't forget to copy `bar' to the archive!
cc -c -o bar.o bar.c
cc -o bar bar.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; Another practical use for the <VAR
CLASS="VARNAME"
>COMMAND_LINE_TARGETS</VAR
> variable
might be to speed up a build
by only reading certain subsidiary <TT
CLASS="FILENAME"
>SConscript</TT
>
files if a specific target is requested.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1317"
>Controlling the Default Targets</A
></H2
><P
>&#13; One of the most basic things you can control
is which targets <TT
CLASS="APPLICATION"
>SCons</TT
> will build by default--that is,
when there are no targets specified on the command line.
As mentioned previously,
<TT
CLASS="APPLICATION"
>SCons</TT
> will normally build every target
in or below the current directory
by default--that is, when you don't
explicitly specify one or more targets
on the command line.
Sometimes, however, you may want
to specify explicitly that only
certain programs, or programs in certain directories,
should be built by default.
You do this with the <TT
CLASS="FUNCTION"
>Default</TT
> function:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
hello = env.Program('hello.c')
env.Program('goodbye.c')
Default(hello)
</PRE
></TD
></TR
></TABLE
><P
>&#13; This <TT
CLASS="FILENAME"
>SConstruct</TT
> file knows how to build two programs,
<TT
CLASS="APPLICATION"
>hello</TT
> and <TT
CLASS="APPLICATION"
>goodbye</TT
>,
but only builds the
<TT
CLASS="APPLICATION"
>hello</TT
> program by default:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
scons: `hello' is up to date.
% <KBD
CLASS="USERINPUT"
>scons -Q goodbye</KBD
>
cc -c -o goodbye.o goodbye.c
cc -o goodbye goodbye.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; Note that, even when you use the <TT
CLASS="FUNCTION"
>Default</TT
>
function in your <TT
CLASS="FILENAME"
>SConstruct</TT
> file,
you can still explicitly specify the current directory
(<TT
CLASS="LITERAL"
>.</TT
>) on the command line
to tell <TT
CLASS="APPLICATION"
>SCons</TT
> to build
everything in (or below) the current directory:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q .</KBD
>
cc -c -o goodbye.o goodbye.c
cc -o goodbye goodbye.o
cc -c -o hello.o hello.c
cc -o hello hello.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; You can also call the <TT
CLASS="FUNCTION"
>Default</TT
>
function more than once,
in which case each call
adds to the list of targets to be built by default:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
prog1 = env.Program('prog1.c')
Default(prog1)
prog2 = env.Program('prog2.c')
prog3 = env.Program('prog3.c')
Default(prog3)
</PRE
></TD
></TR
></TABLE
><P
>&#13; Or you can specify more than one target
in a single call to the <TT
CLASS="FUNCTION"
>Default</TT
> function:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
prog1 = env.Program('prog1.c')
prog2 = env.Program('prog2.c')
prog3 = env.Program('prog3.c')
Default(prog1, prog3)
</PRE
></TD
></TR
></TABLE
><P
>&#13; Either of these last two examples
will build only the
<TT
CLASS="APPLICATION"
>prog1</TT
>
and
<TT
CLASS="APPLICATION"
>prog3</TT
>
programs by default:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o prog1.o prog1.c
cc -o prog1 prog1.o
cc -c -o prog3.o prog3.c
cc -o prog3 prog3.o
% <KBD
CLASS="USERINPUT"
>scons -Q .</KBD
>
cc -c -o prog2.o prog2.c
cc -o prog2 prog2.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; You can list a directory as
an argument to <TT
CLASS="FUNCTION"
>Default</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
env.Program(['prog1/main.c', 'prog1/foo.c'])
env.Program(['prog2/main.c', 'prog2/bar.c'])
Default('prog1')
</PRE
></TD
></TR
></TABLE
><P
>&#13; In which case only the target(s) in that
directory will be built by default:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o prog1/foo.o prog1/foo.c
cc -c -o prog1/main.o prog1/main.c
cc -o prog1/main prog1/main.o prog1/foo.o
% <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
scons: `prog1' is up to date.
% <KBD
CLASS="USERINPUT"
>scons -Q .</KBD
>
cc -c -o prog2/bar.o prog2/bar.c
cc -c -o prog2/main.o prog2/main.c
cc -o prog2/main prog2/main.o prog2/bar.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; Lastly, if for some reason you don't want
any targets built by default,
you can use the Python <TT
CLASS="LITERAL"
>None</TT
>
variable:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
prog1 = env.Program('prog1.c')
prog2 = env.Program('prog2.c')
Default(None)
</PRE
></TD
></TR
></TABLE
><P
>&#13; Which would produce build output like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
scons: *** No targets specified and no Default() targets found. Stop.
% <KBD
CLASS="USERINPUT"
>scons -Q .</KBD
>
cc -c -o prog1.o prog1.c
cc -o prog1 prog1.o
cc -c -o prog2.o prog2.c
cc -o prog2 prog2.o
</PRE
></TD
></TR
></TABLE
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN1367"
>Getting at the List of Default Targets</A
></H3
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> supports a <VAR
CLASS="VARNAME"
>DEFAULT_TARGETS</VAR
> variable
that lets you get at the current list of default targets.
The <VAR
CLASS="VARNAME"
>DEFAULT_TARGETS</VAR
> variable has
two important differences from the <VAR
CLASS="VARNAME"
>COMMAND_LINE_TARGETS</VAR
> variable.
First, the <VAR
CLASS="VARNAME"
>DEFAULT_TARGETS</VAR
> variable is a list of
internal <TT
CLASS="APPLICATION"
>SCons</TT
> nodes,
so you need to convert the list elements to strings
if you want to print them or look for a specific target name.
Fortunately, you can do this easily
by using the Python <TT
CLASS="FUNCTION"
>map</TT
> function
to run the list through <TT
CLASS="FUNCTION"
>str</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> prog1 = Program('prog1.c')
Default(prog1)
print "DEFAULT_TARGETS is", map(str, DEFAULT_TARGETS)
</PRE
></TD
></TR
></TABLE
><P
>&#13; (Keep in mind that all of the manipulation of the
<VAR
CLASS="VARNAME"
>DEFAULT_TARGETS</VAR
> list takes place during the
first phase when <TT
CLASS="APPLICATION"
>SCons</TT
> is reading up the <TT
CLASS="FILENAME"
>SConscript</TT
> files,
which is obvious if
we leave off the <TT
CLASS="LITERAL"
>-Q</TT
> flag when we run <TT
CLASS="APPLICATION"
>SCons</TT
>:)
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
DEFAULT_TARGETS is ['prog1']
scons: done reading SConscript files.
scons: Building targets ...
cc -c -o prog1.o prog1.c
cc -o prog1 prog1.o
scons: done building targets.
</PRE
></TD
></TR
></TABLE
><P
>&#13; Second,
the contents of the <VAR
CLASS="VARNAME"
>DEFAULT_TARGETS</VAR
> list change
in response to calls to the <TT
CLASS="FUNCTION"
>Default</TT
>: function,
as you can see from the following <TT
CLASS="FILENAME"
>SConstruct</TT
> file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> prog1 = Program('prog1.c')
Default(prog1)
print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS)
prog2 = Program('prog2.c')
Default(prog2)
print "DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS)
</PRE
></TD
></TR
></TABLE
><P
>&#13; Which yields the output:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
DEFAULT_TARGETS is now ['prog1']
DEFAULT_TARGETS is now ['prog1', 'prog2']
scons: done reading SConscript files.
scons: Building targets ...
cc -c -o prog1.o prog1.c
cc -o prog1 prog1.o
cc -c -o prog2.o prog2.c
cc -o prog2 prog2.o
scons: done building targets.
</PRE
></TD
></TR
></TABLE
><P
>&#13; In practice, this simply means that you
need to pay attention to the order in
which you call the <TT
CLASS="FUNCTION"
>Default</TT
> function
and refer to the <VAR
CLASS="VARNAME"
>DEFAULT_TARGETS</VAR
> list,
to make sure that you don't examine the
list before you've added the default targets
you expect to find in it.
</P
></DIV
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1398"
>Getting at the List of Build Targets, Regardless of Origin</A
></H2
><P
>&#13; We've already been introduced to the
<VAR
CLASS="VARNAME"
>COMMAND_LINE_TARGETS</VAR
> variable,
which contains a list of targets specified on the command line,
and the <VAR
CLASS="VARNAME"
>DEFAULT_TARGETS</VAR
> variable,
which contains a list of targets specified
via calls to the <TT
CLASS="FUNCTION"
>Default</TT
> method or function.
Sometimes, however,
you want a list of whatever targets
<TT
CLASS="APPLICATION"
>SCons</TT
> will try to build,
regardless of whether the targets came from the
command line or a <TT
CLASS="FUNCTION"
>Default</TT
> call.
You could code this up by hand, as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> if COMMAND_LINE_TARGETS:
targets = COMMAND_LINE_TARGETS
else:
targets = DEFAULT_TARGETS
</PRE
></TD
></TR
></TABLE
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
>, however, provides a convenient
<VAR
CLASS="VARNAME"
>BUILD_TARGETS</VAR
> variable
that eliminates the need for this by-hand manipulation.
Essentially, the <VAR
CLASS="VARNAME"
>BUILD_TARGETS</VAR
> variable
contains a list of the command-line targets,
if any were specified,
and if no command-line targets were specified,
it contains a list of the targets specified
via the <TT
CLASS="FUNCTION"
>Default</TT
> method or function.
</P
><P
>&#13; Because <VAR
CLASS="VARNAME"
>BUILD_TARGETS</VAR
> may contain a list of <TT
CLASS="APPLICATION"
>SCons</TT
> nodes,
you must convert the list elements to strings
if you want to print them or look for a specific target name,
just like the <VAR
CLASS="VARNAME"
>DEFAULT_TARGETS</VAR
> list:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> prog1 = Program('prog1.c')
Program('prog2.c')
Default(prog1)
print "BUILD_TARGETS is", map(str, BUILD_TARGETS)
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice how the value of <VAR
CLASS="VARNAME"
>BUILD_TARGETS</VAR
>
changes depending on whether a target is
specified on the command line:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
BUILD_TARGETS is ['prog1']
cc -c -o prog1.o prog1.c
cc -o prog1 prog1.o
% <KBD
CLASS="USERINPUT"
>scons -Q prog2</KBD
>
BUILD_TARGETS is ['prog2']
cc -c -o prog2.o prog2.c
cc -o prog2 prog2.o
% <KBD
CLASS="USERINPUT"
>scons -Q -c .</KBD
>
BUILD_TARGETS is ['.']
Removed prog1.o
Removed prog1
Removed prog2.o
Removed prog2
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1423"
>Command-Line <VAR
CLASS="VARNAME"
>variable</VAR
>=<VAR
CLASS="VARNAME"
>value</VAR
> Build Options</A
></H2
><P
>&#13; You may want to control various aspects
of your build by allowing the user
to specify <VAR
CLASS="VARNAME"
>variable</VAR
>=<VAR
CLASS="VARNAME"
>value</VAR
>
values on the command line.
For example, suppose you
want users to be able to
build a debug version of a program
by running <TT
CLASS="APPLICATION"
>SCons</TT
> as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q debug=1</KBD
>
</PRE
></TD
></TR
></TABLE
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> provides an <VAR
CLASS="VARNAME"
>ARGUMENTS</VAR
> dictionary
that stores all of the
<VAR
CLASS="VARNAME"
>variable</VAR
>=<VAR
CLASS="VARNAME"
>value</VAR
>
assignments from the command line.
This allows you to modify
aspects of your build in response
to specifications on the command line.
(Note that unless you want to require
that users <I
CLASS="EMPHASIS"
>always</I
>
specify an option,
you probably want to use
the Python
<TT
CLASS="LITERAL"
>ARGUMENTS.get()</TT
> function,
which allows you to specify a default value
to be used if there is no specification
on the command line.)
</P
><P
>&#13; The following code sets the <A
HREF="#CV-CCFLAGS"
><VAR
CLASS="ENVAR"
>$CCFLAGS</VAR
></A
> construction
variable in response to the <VAR
CLASS="VARNAME"
>debug</VAR
>
flag being set in the <VAR
CLASS="VARNAME"
>ARGUMENTS</VAR
> dictionary:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
debug = ARGUMENTS.get('debug', 0)
if int(debug):
env.Append(CCFLAGS = '-g')
env.Program('prog.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; This results in the <VAR
CLASS="VARNAME"
>-g</VAR
>
compiler option being used when
<TT
CLASS="LITERAL"
>debug=1</TT
>
is used on the command line:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q debug=0</KBD
>
cc -c -o prog.o prog.c
cc -o prog prog.o
% <KBD
CLASS="USERINPUT"
>scons -Q debug=0</KBD
>
scons: `.' is up to date.
% <KBD
CLASS="USERINPUT"
>scons -Q debug=1</KBD
>
cc -g -c -o prog.o prog.c
cc -o prog prog.o
% <KBD
CLASS="USERINPUT"
>scons -Q debug=1</KBD
>
scons: `.' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice that <TT
CLASS="APPLICATION"
>SCons</TT
> keeps track of
the last values used to build the object files,
and as a result correctly rebuilds
the object and executable files
only when the value of the <TT
CLASS="LITERAL"
>debug</TT
>
argument has changed.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1457"
>Controlling Command-Line Build Options</A
></H2
><P
>&#13; Being able to use a command-line build option like
<TT
CLASS="LITERAL"
>debug=1</TT
> is handy,
but it can be a chore to write specific Python code
to recognize each such option
and apply the values to a construction variable.
To help with this,
<TT
CLASS="APPLICATION"
>SCons</TT
> supports a class to
define such build options easily,
and a mechanism to apply the
build options to a construction environment.
This allows you to control how the build options affect
construction environments.
</P
><P
>&#13; For example, suppose that you want users to set
a <VAR
CLASS="VARNAME"
>RELEASE</VAR
> construction variable on the
command line whenever the time comes to build
a program for release,
and that the value of this variable
should be added to the command line
with the appropriate <TT
CLASS="LITERAL"
>-D</TT
> option
(or other command line option)
to pass the value to the C compiler.
Here's how you might do that by setting
the appropriate value in a dictionary for the
<A
HREF="#CV-CPPDEFINES"
><VAR
CLASS="ENVAR"
>$CPPDEFINES</VAR
></A
> construction variable:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options()
opts.Add('RELEASE', 'Set to 1 to build for release', 0)
env = Environment(options = opts,
CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'})
env.Program(['foo.c', 'bar.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; This <TT
CLASS="FILENAME"
>SConstruct</TT
> file first creates an
<TT
CLASS="FUNCTION"
>Options</TT
> object
(the <TT
CLASS="LITERAL"
>opts = Options()</TT
> call),
and then uses the object's <TT
CLASS="FUNCTION"
>Add</TT
>
method to indicate that the <VAR
CLASS="VARNAME"
>RELEASE</VAR
>
option can be set on the command line,
and that it's default value will be <TT
CLASS="LITERAL"
>0</TT
>
(the third argument to the <TT
CLASS="FUNCTION"
>Add</TT
> method).
The second argument is a line of help text;
we'll learn how to use it in the next section.
</P
><P
>&#13; We then pass the created <TT
CLASS="FUNCTION"
>Options</TT
>
object as an <VAR
CLASS="VARNAME"
>options</VAR
> keyword argument
to the <TT
CLASS="FUNCTION"
>Environment</TT
> call
used to create the construction environment.
This then allows a user to set the
<VAR
CLASS="VARNAME"
>RELEASE</VAR
> build option on the command line
and have the variable show up in
the command line used to build each object from
a C source file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q RELEASE=1</KBD
>
cc -DRELEASE_BUILD=1 -c -o bar.o bar.c
cc -DRELEASE_BUILD=1 -c -o foo.o foo.c
cc -o foo foo.o bar.o
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1483"
>Providing Help for Command-Line Build Options</A
></H2
><P
>&#13; To make command-line build options most useful,
you ideally want to provide
some help text that will describe
the available options
when the user runs <TT
CLASS="LITERAL"
>scons -h</TT
>.
You could write this text by hand,
but <TT
CLASS="APPLICATION"
>SCons</TT
> provides an easier way.
<TT
CLASS="FUNCTION"
>Options</TT
> objects support a
<TT
CLASS="FUNCTION"
>GenerateHelpText</TT
> method
that will, as its name indicates,
generate text that describes
the various options that
have been added to it.
You then pass the output from this method to
the <TT
CLASS="FUNCTION"
>Help</TT
> function:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options('custom.py')
opts.Add('RELEASE', 'Set to 1 to build for release', 0)
env = Environment(options = opts)
Help(opts.GenerateHelpText(env))
</PRE
></TD
></TR
></TABLE
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> will now display some useful text
when the <TT
CLASS="LITERAL"
>-h</TT
> option is used:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q -h</KBD
>
RELEASE: Set to 1 to build for release
default: 0
actual: 0
Use scons -H for help about command-line options.
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice that the help output shows the default value,
and the current actual value of the build option.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1498"
>Reading Build Options From a File</A
></H2
><P
>&#13; Being able to use a command-line build option like
<TT
CLASS="LITERAL"
>debug=1</TT
> is handy,
but it can be a chore to write specific Python code
to recognize each such option
and apply the values to a construction variable.
To help with this,
<TT
CLASS="APPLICATION"
>SCons</TT
> supports a class to
define such build options easily
and to read build option values from a file.
This allows you to control how the build options affect
construction environments.
The way you do this is by specifying
a file name when you call <TT
CLASS="FUNCTION"
>Options</TT
>,
like <TT
CLASS="FILENAME"
>custom.py</TT
> in the following example:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options('custom.py')
opts.Add('RELEASE', 'Set to 1 to build for release', 0)
env = Environment(options = opts,
CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'})
env.Program(['foo.c', 'bar.c'])
Help(opts.GenerateHelpText(env))
</PRE
></TD
></TR
></TABLE
><P
>&#13; This then allows us to control the <VAR
CLASS="VARNAME"
>RELEASE</VAR
>
variable by setting it in the <TT
CLASS="FILENAME"
>custom.py</TT
> file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> RELEASE = 1
</PRE
></TD
></TR
></TABLE
><P
>&#13; Note that this file is actually executed
like a Python script.
Now when we run <TT
CLASS="APPLICATION"
>SCons</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -DRELEASE_BUILD=1 -c -o bar.o bar.c
cc -DRELEASE_BUILD=1 -c -o foo.o foo.c
cc -o foo foo.o bar.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; And if we change the contents of <TT
CLASS="FILENAME"
>custom.py</TT
> to:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> RELEASE = 0
</PRE
></TD
></TR
></TABLE
><P
>&#13; The object files are rebuilt appropriately
with the new option:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -DRELEASE_BUILD=0 -c -o bar.o bar.c
cc -DRELEASE_BUILD=0 -c -o foo.o foo.c
cc -o foo foo.o bar.o
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1520"
>Canned Build Options</A
></H2
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> provides a number of functions
that provide ready-made behaviors
for various types of command-line build options.
</P
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN1524"
>True/False Values: the <TT
CLASS="FUNCTION"
>BoolOption</TT
> Build Option</A
></H3
><P
>&#13; It's often handy to be able to specify an
option that controls a simple Boolean variable
with a <TT
CLASS="LITERAL"
>true</TT
> or <TT
CLASS="LITERAL"
>false</TT
> value.
It would be even more handy to accomodate
users who have different preferences for how to represent
<TT
CLASS="LITERAL"
>true</TT
> or <TT
CLASS="LITERAL"
>false</TT
> values.
The <TT
CLASS="FUNCTION"
>BoolOption</TT
> function
makes it easy to accomodate a variety of
common values that represent
<TT
CLASS="LITERAL"
>true</TT
> or <TT
CLASS="LITERAL"
>false</TT
>.
</P
><P
>&#13; The <TT
CLASS="FUNCTION"
>BoolOption</TT
> function takes three arguments:
the name of the build option,
the default value of the build option,
and the help string for the option.
It then returns appropriate information for
passing to the <TT
CLASS="FUNCTION"
>Add</TT
> method of an <TT
CLASS="FUNCTION"
>Options</TT
> object, like so:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options('custom.py')
opts.Add(BoolOption('RELEASE', 'Set to build for release', 0))
env = Environment(options = opts,
CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'})
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; With this build option,
the <VAR
CLASS="VARNAME"
>RELEASE</VAR
> variable can now be enabled by
setting it to the value <TT
CLASS="LITERAL"
>yes</TT
>
or <TT
CLASS="LITERAL"
>t</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q RELEASE=yes foo.o</KBD
>
cc -DRELEASE_BUILD=1 -c -o foo.o foo.c
</PRE
></TD
></TR
></TABLE
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q RELEASE=t foo.o</KBD
>
cc -DRELEASE_BUILD=1 -c -o foo.o foo.c
</PRE
></TD
></TR
></TABLE
><P
>&#13; Other values that equate to <TT
CLASS="LITERAL"
>true</TT
> include
<TT
CLASS="LITERAL"
>y</TT
>,
<TT
CLASS="LITERAL"
>1</TT
>,
<TT
CLASS="LITERAL"
>on</TT
>
and
<TT
CLASS="LITERAL"
>all</TT
>.
</P
><P
>&#13; Conversely, <VAR
CLASS="VARNAME"
>RELEASE</VAR
> may now be given a <TT
CLASS="LITERAL"
>false</TT
>
value by setting it to
<TT
CLASS="LITERAL"
>no</TT
>
or
<TT
CLASS="LITERAL"
>f</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q RELEASE=no foo.o</KBD
>
cc -DRELEASE_BUILD=0 -c -o foo.o foo.c
</PRE
></TD
></TR
></TABLE
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q RELEASE=f foo.o</KBD
>
cc -DRELEASE_BUILD=0 -c -o foo.o foo.c
</PRE
></TD
></TR
></TABLE
><P
>&#13; Other values that equate to <TT
CLASS="LITERAL"
>true</TT
> include
<TT
CLASS="LITERAL"
>n</TT
>,
<TT
CLASS="LITERAL"
>0</TT
>,
<TT
CLASS="LITERAL"
>off</TT
>
and
<TT
CLASS="LITERAL"
>none</TT
>.
</P
><P
>&#13; Lastly, if a user tries to specify
any other value,
<TT
CLASS="APPLICATION"
>SCons</TT
> supplies an appropriate error message:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q RELEASE=bad_value foo.o</KBD
>
scons: *** Error converting option: RELEASE
Invalid value for boolean option: bad_value
File "SConstruct", line 4, in ?
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN1573"
>Single Value From a List: the <TT
CLASS="FUNCTION"
>EnumOption</TT
> Build Option</A
></H3
><P
>&#13; Suppose that we want a user to be able to
set a <VAR
CLASS="VARNAME"
>COLOR</VAR
> option
that selects a background color to be
displayed by an application,
but that we want to restrict the
choices to a specific set of allowed colors.
This can be set up quite easily
using the <TT
CLASS="FUNCTION"
>EnumOption</TT
>,
which takes a list of <VAR
CLASS="VARNAME"
>allowed_values</VAR
> in addition to the variable name,
default value,
and help text arguments:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options('custom.py')
opts.Add(EnumOption('COLOR', 'Set background color', 'red',
allowed_values=('red', 'green', 'blue')))
env = Environment(options = opts,
CPPDEFINES={'COLOR' : '"${COLOR}"'})
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; The user can now explicity set the <VAR
CLASS="VARNAME"
>COLOR</VAR
> build option
to any of the specified allowed values:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q COLOR=red foo.o</KBD
>
cc -DCOLOR="red" -c -o foo.o foo.c
% <KBD
CLASS="USERINPUT"
>scons -Q COLOR=blue foo.o</KBD
>
cc -DCOLOR="blue" -c -o foo.o foo.c
% <KBD
CLASS="USERINPUT"
>scons -Q COLOR=green foo.o</KBD
>
cc -DCOLOR="green" -c -o foo.o foo.c
</PRE
></TD
></TR
></TABLE
><P
>&#13; But, almost more importantly,
an attempt to set <VAR
CLASS="VARNAME"
>COLOR</VAR
>
to a value that's not in the list
generates an error message:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q COLOR=magenta foo.o</KBD
>
scons: *** Invalid value for option COLOR: magenta
File "SConstruct", line 5, in ?
</PRE
></TD
></TR
></TABLE
><P
>&#13; The <TT
CLASS="FUNCTION"
>EnumOption</TT
> function also supports a way
to map alternate names to allowed values.
Suppose, for example,
that we want to allow the user
to use the word <TT
CLASS="LITERAL"
>navy</TT
> as a synonym for
<TT
CLASS="LITERAL"
>blue</TT
>.
We do this by adding a <VAR
CLASS="VARNAME"
>map</VAR
> dictionary
that will map its key values
to the desired legal value:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options('custom.py')
opts.Add(EnumOption('COLOR', 'Set background color', 'red',
allowed_values=('red', 'green', 'blue'),
map={'navy':'blue'}))
env = Environment(options = opts,
CPPDEFINES={'COLOR' : '"${COLOR}"'})
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; As desired, the user can then use
<TT
CLASS="LITERAL"
>navy</TT
> on the command line,
and <TT
CLASS="APPLICATION"
>SCons</TT
> will translate it into <TT
CLASS="LITERAL"
>blue</TT
>
when it comes time to use the <VAR
CLASS="VARNAME"
>COLOR</VAR
>
option to build a target:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q COLOR=navy foo.o</KBD
>
cc -DCOLOR="blue" -c -o foo.o foo.c
</PRE
></TD
></TR
></TABLE
><P
>&#13; By default, when using the <TT
CLASS="FUNCTION"
>EnumOption</TT
> function,
arguments that differ
from the legal values
only in case
are treated as illegal values:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q COLOR=Red foo.o</KBD
>
scons: *** Invalid value for option COLOR: Red
File "SConstruct", line 5, in ?
% <KBD
CLASS="USERINPUT"
>scons -Q COLOR=BLUE foo.o</KBD
>
scons: *** Invalid value for option COLOR: BLUE
File "SConstruct", line 5, in ?
% <KBD
CLASS="USERINPUT"
>scons -Q COLOR=nAvY foo.o</KBD
>
scons: *** Invalid value for option COLOR: nAvY
File "SConstruct", line 5, in ?
</PRE
></TD
></TR
></TABLE
><P
>&#13; The <TT
CLASS="FUNCTION"
>EnumOption</TT
> function can take an additional
<VAR
CLASS="VARNAME"
>ignorecase</VAR
> keyword argument that,
when set to <TT
CLASS="LITERAL"
>1</TT
>,
tells <TT
CLASS="APPLICATION"
>SCons</TT
> to allow case differences
when the values are specified:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options('custom.py')
opts.Add(EnumOption('COLOR', 'Set background color', 'red',
allowed_values=('red', 'green', 'blue'),
map={'navy':'blue'},
ignorecase=1))
env = Environment(options = opts,
CPPDEFINES={'COLOR' : '"${COLOR}"'})
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Which yields the output:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q COLOR=Red foo.o</KBD
>
cc -DCOLOR="Red" -c -o foo.o foo.c
% <KBD
CLASS="USERINPUT"
>scons -Q COLOR=BLUE foo.o</KBD
>
cc -DCOLOR="BLUE" -c -o foo.o foo.c
% <KBD
CLASS="USERINPUT"
>scons -Q COLOR=nAvY foo.o</KBD
>
cc -DCOLOR="blue" -c -o foo.o foo.c
% <KBD
CLASS="USERINPUT"
>scons -Q COLOR=green foo.o</KBD
>
cc -DCOLOR="green" -c -o foo.o foo.c
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice that an <VAR
CLASS="VARNAME"
>ignorecase</VAR
> value of <TT
CLASS="LITERAL"
>1</TT
>
preserves the case-spelling that the user supplied.
If you want <TT
CLASS="APPLICATION"
>SCons</TT
> to translate the names
into lower-case,
regardless of the case used by the user,
specify an <VAR
CLASS="VARNAME"
>ignorecase</VAR
> value of <TT
CLASS="LITERAL"
>2</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options('custom.py')
opts.Add(EnumOption('COLOR', 'Set background color', 'red',
allowed_values=('red', 'green', 'blue'),
map={'navy':'blue'},
ignorecase=2))
env = Environment(options = opts,
CPPDEFINES={'COLOR' : '"${COLOR}"'})
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Now <TT
CLASS="APPLICATION"
>SCons</TT
> will use values of
<TT
CLASS="LITERAL"
>red</TT
>,
<TT
CLASS="LITERAL"
>green</TT
> or
<TT
CLASS="LITERAL"
>blue</TT
>
regardless of how the user spells
those values on the command line:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q COLOR=Red foo.o</KBD
>
cc -DCOLOR="red" -c -o foo.o foo.c
% <KBD
CLASS="USERINPUT"
>scons -Q COLOR=nAvY foo.o</KBD
>
cc -DCOLOR="blue" -c -o foo.o foo.c
% <KBD
CLASS="USERINPUT"
>scons -Q COLOR=GREEN foo.o</KBD
>
cc -DCOLOR="green" -c -o foo.o foo.c
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN1638"
>Multiple Values From a List: the <TT
CLASS="FUNCTION"
>ListOption</TT
> Build Option</A
></H3
><P
>&#13; Another way in which you might want to allow users
to control build option is to
specify a list of one or more legal values.
<TT
CLASS="APPLICATION"
>SCons</TT
> supports this through the <TT
CLASS="FUNCTION"
>ListOption</TT
> function.
If, for example, we want a user to be able to set a
<VAR
CLASS="VARNAME"
>COLORS</VAR
> option to one or more of the legal list of values:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options('custom.py')
opts.Add(ListOption('COLORS', 'List of colors', 0,
['red', 'green', 'blue']))
env = Environment(options = opts,
CPPDEFINES={'COLORS' : '"${COLORS}"'})
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; A user can now specify a comma-separated list
of legal values,
which will get translated into a space-separated
list for passing to the any build commands:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q COLORS=red,blue foo.o</KBD
>
cc -DCOLORS="red blue" -c -o foo.o foo.c
% <KBD
CLASS="USERINPUT"
>scons -Q COLORS=blue,green,red foo.o</KBD
>
cc -DCOLORS="blue green red" -c -o foo.o foo.c
</PRE
></TD
></TR
></TABLE
><P
>&#13; In addition, the <TT
CLASS="FUNCTION"
>ListOption</TT
> function
allows the user to specify explicit keywords of
<TT
CLASS="LITERAL"
>all</TT
> or <TT
CLASS="LITERAL"
>none</TT
>
to select all of the legal values,
or none of them, respectively:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q COLORS=all foo.o</KBD
>
cc -DCOLORS="red green blue" -c -o foo.o foo.c
% <KBD
CLASS="USERINPUT"
>scons -Q COLORS=none foo.o</KBD
>
cc -DCOLORS="" -c -o foo.o foo.c
</PRE
></TD
></TR
></TABLE
><P
>&#13; And, of course, an illegal value
still generates an error message:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q COLORS=magenta foo.o</KBD
>
scons: *** Error converting option: COLORS
Invalid value(s) for option: magenta
File "SConstruct", line 5, in ?
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN1660"
>Path Names: the <TT
CLASS="FUNCTION"
>PathOption</TT
> Build Option</A
></H3
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> supports a <TT
CLASS="FUNCTION"
>PathOption</TT
> function
to make it easy to create a build option
to control an expected path name.
If, for example, you need to
define a variable in the preprocessor
that control the location of a
configuration file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options('custom.py')
opts.Add(PathOption('CONFIG',
'Path to configuration file',
'/etc/my_config'))
env = Environment(options = opts,
CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'})
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; This then allows the user to
override the <VAR
CLASS="VARNAME"
>CONFIG</VAR
> build option
on the command line as necessary:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q foo.o</KBD
>
cc -DCONFIG_FILE="/etc/my_config" -c -o foo.o foo.c
% <KBD
CLASS="USERINPUT"
>scons -Q CONFIG=/usr/local/etc/other_config foo.o</KBD
>
scons: `foo.o' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; By default, <TT
CLASS="FUNCTION"
>PathOption</TT
> checks to make sure
that the specified path exists and generates an error if it
doesn't:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q CONFIG=/does/not/exist foo.o</KBD
>
scons: *** Path for option CONFIG does not exist: /does/not/exist
File "SConstruct", line 6, in ?
</PRE
></TD
></TR
></TABLE
><P
>&#13; <TT
CLASS="FUNCTION"
>PathOption</TT
> provides a number of methods
that you can use to change this behavior.
If you want to ensure that any specified paths are,
in fact, files and not directories,
use the <TT
CLASS="FUNCTION"
>PathOption.PathIsFile</TT
> method:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options('custom.py')
opts.Add(PathOption('CONFIG',
'Path to configuration file',
'/etc/my_config',
PathOption.PathIsFile))
env = Environment(options = opts,
CPPDEFINES={'CONFIG_FILE' : '"$CONFIG"'})
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Conversely, to ensure that any specified paths are
directories and not files,
use the <TT
CLASS="FUNCTION"
>PathOption.PathIsDir</TT
> method:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options('custom.py')
opts.Add(PathOption('DBDIR',
'Path to database directory',
'/var/my_dbdir',
PathOption.PathIsDir))
env = Environment(options = opts,
CPPDEFINES={'DBDIR' : '"$DBDIR"'})
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; If you want to make sure that any specified paths
are directories,
and you would like the directory created
if it doesn't already exist,
use the <TT
CLASS="FUNCTION"
>PathOption.PathIsDirCreate</TT
> method:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options('custom.py')
opts.Add(PathOption('DBDIR',
'Path to database directory',
'/var/my_dbdir',
PathOption.PathIsDirCreate))
env = Environment(options = opts,
CPPDEFINES={'DBDIR' : '"$DBDIR"'})
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Lastly, if you don't care whether the path exists,
is a file, or a directory,
use the <TT
CLASS="FUNCTION"
>PathOption.PathAccept</TT
> method
to accept any path that the user supplies:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options('custom.py')
opts.Add(PathOption('OUTPUT',
'Path to output file or directory',
None,
PathOption.PathAccept))
env = Environment(options = opts,
CPPDEFINES={'OUTPUT' : '"$OUTPUT"'})
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN1689"
>Enabled/Disabled Path Names: the <TT
CLASS="FUNCTION"
>PackageOption</TT
> Build Option</A
></H3
><P
>&#13; Sometimes you want to give users
even more control over a path name variable,
allowing them to explicitly enable or
disable the path name
by using <TT
CLASS="LITERAL"
>yes</TT
> or <TT
CLASS="LITERAL"
>no</TT
> keywords,
in addition to allow them
to supply an explicit path name.
<TT
CLASS="APPLICATION"
>SCons</TT
> supports the <TT
CLASS="FUNCTION"
>PackageOption</TT
>
function to support this:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options('custom.py')
opts.Add(PackageOption('PACKAGE',
'Location package',
'/opt/location'))
env = Environment(options = opts,
CPPDEFINES={'PACKAGE' : '"$PACKAGE"'})
env.Program('foo.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; When the <TT
CLASS="FILENAME"
>SConscript</TT
> file uses the <TT
CLASS="FUNCTION"
>PackageOption</TT
> funciton,
user can now still use the default
or supply an overriding path name,
but can now explicitly set the
specified variable to a value
that indicates the package should be enabled
(in which case the default should be used)
or disabled:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q foo.o</KBD
>
cc -DPACKAGE="/opt/location" -c -o foo.o foo.c
% <KBD
CLASS="USERINPUT"
>scons -Q PACKAGE=/usr/local/location foo.o</KBD
>
cc -DPACKAGE="/usr/local/location" -c -o foo.o foo.c
% <KBD
CLASS="USERINPUT"
>scons -Q PACKAGE=yes foo.o</KBD
>
cc -DPACKAGE="1" -c -o foo.o foo.c
% <KBD
CLASS="USERINPUT"
>scons -Q PACKAGE=no foo.o</KBD
>
cc -DPACKAGE="0" -c -o foo.o foo.c
</PRE
></TD
></TR
></TABLE
></DIV
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1706"
>Adding Multiple Command-Line Build Options at Once</A
></H2
><P
>&#13; Lastly, <TT
CLASS="APPLICATION"
>SCons</TT
> provides a way to add
multiple build options to an <TT
CLASS="FUNCTION"
>Options</TT
> object at once.
Instead of having to call the <TT
CLASS="FUNCTION"
>Add</TT
> method
multiple times,
you can call the <TT
CLASS="FUNCTION"
>AddOptions</TT
>
method with a list of build options
to be added to the object.
Each build option is specified
as either a tuple of arguments,
just like you'd pass to the <TT
CLASS="FUNCTION"
>Add</TT
> method itself,
or as a call to one of the canned
functions for pre-packaged command-line build options.
in any order:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> opts = Options()
opts.AddOptions(
('RELEASE', 'Set to 1 to build for release', 0),
('CONFIG', 'Configuration file', '/etc/my_config'),
BoolOption('warnings', 'compilation with -Wall and similiar', 1),
EnumOption('debug', 'debug output and symbols', 'no',
allowed_values=('yes', 'no', 'full'),
map={}, ignorecase=0), # case sensitive
ListOption('shared',
'libraries to build as shared libraries',
'all',
names = list_of_libs),
PackageOption('x11',
'use X11 installed here (yes = search some places)',
'yes'),
PathOption('qtdir', 'where the root of Qt is installed', qtdir),
)
</PRE
></TD
></TR
></TABLE
><P
> </P
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-HELP"
></A
>Providing Build Help: the <TT
CLASS="FUNCTION"
>Help</TT
> Function</H1
><P
>&#13; It's often very useful to be able to give
users some help that describes the
specific targets, build options, etc.,
that can be used for your build.
<TT
CLASS="APPLICATION"
>SCons</TT
> provides the <TT
CLASS="FUNCTION"
>Help</TT
> function
to allow you to specify this help text:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Help("""
Type: 'scons program' to build the production program,
'scons debug' to build the debug version.
""")
</PRE
></TD
></TR
></TABLE
><P
>&#13; (Note the above use of the Python triple-quote syntax,
which comes in very handy for
specifying multi-line strings like help text.)
</P
><P
>&#13; When the <TT
CLASS="FILENAME"
>SConstruct</TT
> or <TT
CLASS="FILENAME"
>SConscript</TT
> files
contain such a call to the <TT
CLASS="FUNCTION"
>Help</TT
> function,
the specified help text will be displayed in response to
the <TT
CLASS="APPLICATION"
>SCons</TT
> <TT
CLASS="LITERAL"
>-h</TT
> option:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -h</KBD
>
scons: Reading SConscript files ...
scons: done reading SConscript files.
Type: 'scons program' to build the production program,
'scons debug' to build the debug version.
Use scons -H for help about command-line options.
</PRE
></TD
></TR
></TABLE
><P
>&#13; The <TT
CLASS="FILENAME"
>SConscript</TT
> files may contain
multiple calls to the <TT
CLASS="FUNCTION"
>Help</TT
> function,
in which case the specified text(s)
will be concatenated when displayed.
This allows you to split up the
help text across multiple <TT
CLASS="FILENAME"
>SConscript</TT
> files.
In this situation, the order in
which the <TT
CLASS="FILENAME"
>SConscript</TT
> files are called
will determine the order in which the <TT
CLASS="FUNCTION"
>Help</TT
> functions are called,
which will determine the order in which
the various bits of text will get concatenated.
</P
><P
>&#13; Another use would be to make the help text conditional
on some variable.
For example, suppose you only want to display
a line about building a Windows-only
version of a program when actually
run on Windows.
The following <TT
CLASS="FILENAME"
>SConstruct</TT
> file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
Help("\nType: 'scons program' to build the production program.\n")
if env['PLATFORM'] == 'win32':
Help("\nType: 'scons windebug' to build the Windows debug version.\n")
</PRE
></TD
></TR
></TABLE
><P
>&#13; Will display the completely help text on Windows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons -h</KBD
>
scons: Reading SConscript files ...
scons: done reading SConscript files.
Type: 'scons program' to build the production program.
Type: 'scons windebug' to build the Windows debug version.
Use scons -H for help about command-line options.
</PRE
></TD
></TR
></TABLE
><P
>&#13; But only show the relevant option on a Linux or UNIX system:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -h</KBD
>
scons: Reading SConscript files ...
scons: done reading SConscript files.
Type: 'scons program' to build the production program.
Use scons -H for help about command-line options.
</PRE
></TD
></TR
></TABLE
><P
>&#13; If there is no <TT
CLASS="FUNCTION"
>Help</TT
> text in the <TT
CLASS="FILENAME"
>SConstruct</TT
> or
<TT
CLASS="FILENAME"
>SConscript</TT
> files,
<TT
CLASS="APPLICATION"
>SCons</TT
> will revert to displaying its
standard list that describes the <TT
CLASS="APPLICATION"
>SCons</TT
> command-line
options.
This list is also always displayed whenever
the <TT
CLASS="LITERAL"
>-H</TT
> option is used.
</P
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-INSTALL"
></A
>Installing Files in Other Directories: the <TT
CLASS="FUNCTION"
>Install</TT
> Builder</H1
><P
>&#13; Once a program is built,
it is often appropriate to install it in another
directory for public use.
You use the <TT
CLASS="FUNCTION"
>Install</TT
> method
to arrange for a program, or any other file,
to be copied into a destination directory:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
hello = env.Program('hello.c')
env.Install('/usr/bin', hello)
</PRE
></TD
></TR
></TABLE
><P
>&#13; Note, however, that installing a file is
still considered a type of file "build."
This is important when you remember that
the default behavior of <TT
CLASS="APPLICATION"
>SCons</TT
> is
to build files in or below the current directory.
If, as in the example above,
you are installing files in a directory
outside of the top-level <TT
CLASS="FILENAME"
>SConstruct</TT
> file's directory tree,
you must specify that directory
(or a higher directory, such as <TT
CLASS="LITERAL"
>/</TT
>)
for it to install anything there:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q /usr/bin</KBD
>
Install file: "hello" as "/usr/bin/hello"
</PRE
></TD
></TR
></TABLE
><P
>&#13; It can, however, be cumbersome to remember
(and type) the specific destination directory
in which the program (or any other file)
should be installed.
This is an area where the <TT
CLASS="FUNCTION"
>Alias</TT
>
function comes in handy,
allowing you, for example,
to create a pseudo-target named <TT
CLASS="LITERAL"
>install</TT
>
that can expand to the specified destination directory:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
hello = env.Program('hello.c')
env.Install('/usr/bin', hello)
env.Alias('install', '/usr/bin')
</PRE
></TD
></TR
></TABLE
><P
>&#13; This then yields the more natural
ability to install the program
in its destination as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q install</KBD
>
Install file: "hello" as "/usr/bin/hello"
</PRE
></TD
></TR
></TABLE
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1775"
>Installing Multiple Files in a Directory</A
></H2
><P
>&#13; You can install multiple files into a directory
simply by calling the <TT
CLASS="FUNCTION"
>Install</TT
> function multiple times:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
hello = env.Program('hello.c')
goodbye = env.Program('goodbye.c')
env.Install('/usr/bin', hello)
env.Install('/usr/bin', goodbye)
env.Alias('install', '/usr/bin')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Or, more succinctly, listing the multiple input
files in a list
(just like you can do with any other builder):
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
hello = env.Program('hello.c')
goodbye = env.Program('goodbye.c')
env.Install('/usr/bin', [hello, goodbye])
env.Alias('install', '/usr/bin')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Either of these two examples yields:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q install</KBD
>
cc -c -o goodbye.o goodbye.c
cc -o goodbye goodbye.o
Install file: "goodbye" as "/usr/bin/goodbye"
cc -c -o hello.o hello.c
cc -o hello hello.o
Install file: "hello" as "/usr/bin/hello"
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1785"
>Installing a File Under a Different Name</A
></H2
><P
>&#13; The <TT
CLASS="FUNCTION"
>Install</TT
> method preserves the name
of the file when it is copied into the
destination directory.
If you need to change the name of the file
when you copy it, use the <TT
CLASS="FUNCTION"
>InstallAs</TT
> function:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
hello = env.Program('hello.c')
env.InstallAs('/usr/bin/hello-new', hello)
env.Alias('install', '/usr/bin')
</PRE
></TD
></TR
></TABLE
><P
>&#13; This installs the <TT
CLASS="LITERAL"
>hello</TT
>
program with the name <TT
CLASS="LITERAL"
>hello-new</TT
>
as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q install</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
Install file: "hello" as "/usr/bin/hello-new"
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1796"
>Installing Multiple Files Under Different Names</A
></H2
><P
>&#13; Lastly, if you have multiple files that all
need to be installed with different file names,
you can either call the <TT
CLASS="FUNCTION"
>InstallAs</TT
> function
multiple times, or as a shorthand,
you can supply same-length lists
for the both the target and source arguments:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
hello = env.Program('hello.c')
goodbye = env.Program('goodbye.c')
env.InstallAs(['/usr/bin/hello-new',
'/usr/bin/goodbye-new'],
[hello, goodbye])
env.Alias('install', '/usr/bin')
</PRE
></TD
></TR
></TABLE
><P
>&#13; In this case, the <TT
CLASS="FUNCTION"
>InstallAs</TT
> function
loops through both lists simultaneously,
and copies each source file into its corresponding
target file name:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q install</KBD
>
cc -c -o goodbye.o goodbye.c
cc -o goodbye goodbye.o
Install file: "goodbye" as "/usr/bin/goodbye-new"
cc -c -o hello.o hello.c
cc -o hello hello.o
Install file: "hello" as "/usr/bin/hello-new"
</PRE
></TD
></TR
></TABLE
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-FACTORIES"
></A
>Platform-Independent File System Manipulation</H1
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> provides a number of platform-independent functions,
called <TT
CLASS="LITERAL"
>factories</TT
>,
that perform common file system manipulations
like copying, moving or deleting files and directories,
or making directories.
These functions are <TT
CLASS="LITERAL"
>factories</TT
>
because they don't perform the action
at the time they're called,
they each return an <CODE
CLASS="CLASSNAME"
>Action</CODE
> object
that can be executed at the appropriate time.
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1812"
>Copying Files or Directories: The <TT
CLASS="FUNCTION"
>Copy</TT
> Factory</A
></H2
><P
>&#13; Suppose you want to arrange to make a copy of a file,
and the <TT
CLASS="FUNCTION"
>Install</TT
> builder isn't appropriate
because it may make a hard link on POSIX systems.
One way would be to use the <TT
CLASS="FUNCTION"
>Copy</TT
> action factory
in conjunction with the <TT
CLASS="FUNCTION"
>Command</TT
> builder:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Command("file.out", "file.in", Copy("$TARGET", "$SOURCE"))
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice that the action returned by the <TT
CLASS="FUNCTION"
>Copy</TT
> factory
will expand the <VAR
CLASS="ENVAR"
>$TARGET</VAR
> and <VAR
CLASS="ENVAR"
>$SOURCE</VAR
> strings
at the time <TT
CLASS="FILENAME"
>file.out</TT
> 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:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
Copy("file.out", "file.in")
</PRE
></TD
></TR
></TABLE
><P
>&#13; You can, of course, name a file explicitly
instead of using <VAR
CLASS="ENVAR"
>$TARGET</VAR
> or <VAR
CLASS="ENVAR"
>$SOURCE</VAR
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Command("file.out", [], Copy("$TARGET", "file.in"))
</PRE
></TD
></TR
></TABLE
><P
>&#13; Which executes as:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
Copy("file.out", "file.in")
</PRE
></TD
></TR
></TABLE
><P
>&#13; The usefulness of the <TT
CLASS="FUNCTION"
>Copy</TT
> factory
becomes more apparent when
you use it in a list of actions
passed to the <TT
CLASS="FUNCTION"
>Command</TT
> 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 <TT
CLASS="FUNCTION"
>Copy</TT
> factory makes extremely easy:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Command("file.out", "file.in",
[
Copy("tempfile", "$SOURCE"),
"modify tempfile",
Copy("$TARGET", "tempfile"),
])
</PRE
></TD
></TR
></TABLE
><P
>&#13; The output then looks like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
Copy("tempfile", "file.in")
modify tempfile
Copy("file.out", "tempfile")
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1842"
>Deleting Files or Directories: The <TT
CLASS="FUNCTION"
>Delete</TT
> Factory</A
></H2
><P
>&#13; If you need to delete a file,
then the <TT
CLASS="FUNCTION"
>Delete</TT
> factory
can be used in much the same way as
the <TT
CLASS="FUNCTION"
>Copy</TT
> 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 <TT
CLASS="FUNCTION"
>Delete</TT
> to the beginning
of the command list:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Command("file.out", "file.in",
[
Delete("tempfile"),
Copy("tempfile", "$SOURCE"),
"modify tempfile",
Copy("$TARGET", "tempfile"),
])
</PRE
></TD
></TR
></TABLE
><P
>&#13; When then executes as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
Delete("tempfile")
Copy("tempfile", "file.in")
modify tempfile
Copy("file.out", "tempfile")
</PRE
></TD
></TR
></TABLE
><P
>&#13; Of course, like all of these <CODE
CLASS="CLASSNAME"
>Action</CODE
> factories,
the <TT
CLASS="FUNCTION"
>Delete</TT
> factory also expands
<VAR
CLASS="ENVAR"
>$TARGET</VAR
> and <VAR
CLASS="ENVAR"
>$SOURCE</VAR
> variables appropriately.
For example:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Command("file.out", "file.in",
[
Delete("$TARGET"),
Copy("$TARGET", "$SOURCE")
])
</PRE
></TD
></TR
></TABLE
><P
>&#13; Executes as:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
Delete("file.out")
Copy("file.out", "file.in")
</PRE
></TD
></TR
></TABLE
><P
>&#13; (Note, however, that you typically don't need to
call the <TT
CLASS="FUNCTION"
>Delete</TT
> factory explicitly in this way;
by default, <TT
CLASS="APPLICATION"
>SCons</TT
> deletes its target(s)
for you before executing any action.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1865"
>Moving (Renaming) Files or Directories: The <TT
CLASS="FUNCTION"
>Move</TT
> Factory</A
></H2
><P
>&#13; The <TT
CLASS="FUNCTION"
>Move</TT
> factory
allows you to rename a file or directory.
For example, if we don't want to copy the temporary file,
we could:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Command("file.out", "file.in",
[
Copy("tempfile", "$SOURCE"),
"modify tempfile",
Move("$TARGET", "tempfile"),
])
</PRE
></TD
></TR
></TABLE
><P
>&#13; Which would execute as:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
Copy("tempfile", "file.in")
modify tempfile
Move("file.out", "tempfile")
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1874"
>Updating the Modification Time of a File: The <TT
CLASS="FUNCTION"
>Touch</TT
> Factory</A
></H2
><P
>&#13; If you just need to update the
recorded modification time for a file,
use the <TT
CLASS="FUNCTION"
>Touch</TT
> factory:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Command("file.out", "file.in",
[
Copy("tempfile", "$SOURCE"),
"modify tempfile",
Move("$TARGET", "tempfile"),
])
</PRE
></TD
></TR
></TABLE
><P
>&#13; Which executes as:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
Copy("tempfile", "file.in")
modify tempfile
Move("file.out", "tempfile")
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1883"
>Creating a Directory: The <TT
CLASS="FUNCTION"
>Mkdir</TT
> Factory</A
></H2
><P
>&#13; If you need to create a directory,
use the <TT
CLASS="FUNCTION"
>Mkdir</TT
> 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:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Command("file.out", "file.in",
[
Delete("tempdir"),
Mkdir("tempdir"),
Copy("tempdir/${SOURCE.file}", "$SOURCE"),
"process tempdir",
Move("$TARGET", "tempdir/output_file"),
Delete("tempdir"),
])
</PRE
></TD
></TR
></TABLE
><P
>&#13; Which executes as:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
Delete("tempdir")
Mkdir("tempdir")
Copy("tempdir/file.in", "file.in")
process tempdir
Move("file.out", "tempdir/output_file")
scons: *** [file.out] No such file or directory
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1892"
>Changing File or Directory Permissions: The <TT
CLASS="FUNCTION"
>Chmod</TT
> Factory</A
></H2
><P
>&#13; To change permissions on a file or directory,
use the <TT
CLASS="FUNCTION"
>Chmod</TT
> factory.
The permission argument uses POSIX-style
permission bits and should typically
be expressed as an octal,
not decimal, number:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Command("file.out", "file.in",
[
Copy("$TARGET", "$SOURCE"),
Chmod("$TARGET", 0755),
])
</PRE
></TD
></TR
></TABLE
><P
>&#13; Which executes:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
Copy("file.out", "file.in")
Chmod("file.out", 0755)
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1901"
>Executing an action immediately: the <TT
CLASS="FUNCTION"
>Execute</TT
> Function</A
></H2
><P
>&#13; We've been showing you how to use <CODE
CLASS="CLASSNAME"
>Action</CODE
> factories
in the <TT
CLASS="FUNCTION"
>Command</TT
> function.
You can also execute an <CODE
CLASS="CLASSNAME"
>Action</CODE
> returned by a factory
(or actually, any <CODE
CLASS="CLASSNAME"
>Action</CODE
>)
at the time the <TT
CLASS="FILENAME"
>SConscript</TT
> file is read
by wrapping it up in the <TT
CLASS="FUNCTION"
>Execute</TT
> function.
For example, if we need to make sure that
a directory exists before we build any targets,
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Execute(Mkdir('/tmp/my_temp_directory'))
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice that this will
create the directory while
the <TT
CLASS="FILENAME"
>SConscript</TT
> file is being read:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
Mkdir("/tmp/my_temp_directory")
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.
</PRE
></TD
></TR
></TABLE
><P
>&#13; If you're familiar with Python,
you may wonder why you would want to use this
instead of just calling the native Python
<TT
CLASS="FUNCTION"
>os.mkdir()</TT
> function.
The advantage here is that the <TT
CLASS="FUNCTION"
>Mkdir</TT
>
action will behave appropriately if the user
specifies the <TT
CLASS="APPLICATION"
>SCons</TT
> <VAR
CLASS="OPTION"
>-n</VAR
> or
<VAR
CLASS="OPTION"
>-q</VAR
> options--that is,
it will print the action but not actually
make the directory when <VAR
CLASS="OPTION"
>-n</VAR
> is specified,
or make the directory but not print the action
when <VAR
CLASS="OPTION"
>-q</VAR
> is specified.
</P
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-PRECIOUS"
></A
>Preventing Removal of Targets: the <TT
CLASS="FUNCTION"
>Precious</TT
> Function</H1
><P
>&#13; By default, <TT
CLASS="APPLICATION"
>SCons</TT
> removes targets before building them.
Sometimes, however, this is not what you want.
For example, you may want to update a library incrementally,
not by having it deleted and then rebuilt from all
of the constituent object files.
In such cases, you can use the
<TT
CLASS="FUNCTION"
>Precious</TT
> method to prevent
<TT
CLASS="APPLICATION"
>SCons</TT
> from removing the target before it is built:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
lib = env.Library('foo', ['f1.c', 'f2.c', 'f3.c'])
env.Precious(lib)
</PRE
></TD
></TR
></TABLE
><P
>&#13; Although the output doesn't look any different,
<TT
CLASS="APPLICATION"
>SCons</TT
> does not, in fact,
delete the target library before rebuilding it:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o f1.o f1.c
cc -c -o f2.o f2.c
cc -c -o f3.o f3.c
ar r libfoo.a f1.o f2.o f3.o
ranlib libfoo.a
</PRE
></TD
></TR
></TABLE
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> will, however, still delete files marked as <TT
CLASS="FUNCTION"
>Precious</TT
>
when the <TT
CLASS="LITERAL"
>-c</TT
> option is used.
</P
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-HIERARCHICAL"
></A
>Hierarchical Builds</H1
><P
>&#13; The source code for large software projects
rarely stays in a single directory,
but is nearly always divided into a
hierarchy of directories.
Organizing a large software build using <TT
CLASS="APPLICATION"
>SCons</TT
>
involves creating a hierarchy of build scripts
using the <TT
CLASS="FILENAME"
>SConscript</TT
> function.
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1945"
><TT
CLASS="FILENAME"
>SConscript</TT
> Files</A
></H2
><P
>&#13; As we've already seen,
the build script at the top of the tree is called <TT
CLASS="FILENAME"
>SConstruct</TT
>.
The top-level <TT
CLASS="FILENAME"
>SConstruct</TT
> file can
use the <TT
CLASS="FILENAME"
>SConscript</TT
> function to
include other subsidiary scripts in the build.
These subsidiary scripts can, in turn,
use the <TT
CLASS="FILENAME"
>SConscript</TT
> function
to include still other scripts in the build.
By convention, these subsidiary scripts are usually
named <TT
CLASS="FILENAME"
>SConscript</TT
>.
For example, a top-level <TT
CLASS="FILENAME"
>SConstruct</TT
> file might
arrange for four subsidiary scripts to be included
in the build as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> SConscript(['drivers/display/SConscript',
'drivers/mouse/SConscript',
'parser/SConscript',
'utilities/SConscript'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; In this case, the <TT
CLASS="FILENAME"
>SConstruct</TT
> file
lists all of the <TT
CLASS="FILENAME"
>SConscript</TT
> files in the build explicitly.
(Note, however, that not every directory in the tree
necessarily has an <TT
CLASS="FILENAME"
>SConscript</TT
> file.)
Alternatively, the <TT
CLASS="LITERAL"
>drivers</TT
>
subdirectory might contain an intermediate
<TT
CLASS="FILENAME"
>SConscript</TT
> file,
in which case the <TT
CLASS="FILENAME"
>SConscript</TT
> call in
the top-level <TT
CLASS="FILENAME"
>SConstruct</TT
> file
would look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> SConscript(['drivers/SConscript',
'parser/SConscript',
'utilities/SConscript'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; And the subsidiary <TT
CLASS="FILENAME"
>SConscript</TT
> file in the
<TT
CLASS="LITERAL"
>drivers</TT
> subdirectory
would look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> SConscript(['display/SConscript',
'mouse/SConscript'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; Whether you list all of the <TT
CLASS="FILENAME"
>SConscript</TT
> files in the
top-level <TT
CLASS="FILENAME"
>SConstruct</TT
> file,
or place a subsidiary <TT
CLASS="FILENAME"
>SConscript</TT
> file in
intervening directories,
or use some mix of the two schemes,
is up to you and the needs of your software.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1973"
>Path Names Are Relative to the <TT
CLASS="FILENAME"
>SConscript</TT
> Directory</A
></H2
><P
>&#13; Subsidiary <TT
CLASS="FILENAME"
>SConscript</TT
> files make it easy to create a build
hierarchy because all of the file and directory names
in a subsidiary <TT
CLASS="FILENAME"
>SConscript</TT
> files are interpreted
relative to the directory in which the <TT
CLASS="FILENAME"
>SConscript</TT
> file lives.
Typically, this allows the <TT
CLASS="FILENAME"
>SConscript</TT
> file containing the
instructions to build a target file
to live in the same directory as the source files
from which the target will be built,
making it easy to update how the software is built
whenever files are added or deleted
(or other changes are made).
</P
><P
>&#13; For example, suppose we want to build two programs
<TT
CLASS="FILENAME"
>prog1</TT
> and <TT
CLASS="FILENAME"
>prog2</TT
> in two separate directories
with the same names as the programs.
One typical way to do this would be
with a top-level <TT
CLASS="FILENAME"
>SConstruct</TT
> file like this:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> SConscript(['prog1/SConscript',
'prog2/SConscript'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; And subsidiary <TT
CLASS="FILENAME"
>SConscript</TT
> files that look like this:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
env.Program('prog1', ['main.c', 'foo1.c', 'foo2.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; And this:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
env.Program('prog2', ['main.c', 'bar1.c', 'bar2.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; Then, when we run <TT
CLASS="APPLICATION"
>SCons</TT
> in the top-level directory,
our build looks like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o prog1/foo1.o prog1/foo1.c
cc -c -o prog1/foo2.o prog1/foo2.c
cc -c -o prog1/main.o prog1/main.c
cc -o prog1/prog1 prog1/main.o prog1/foo1.o prog1/foo2.o
cc -c -o prog2/bar1.o prog2/bar1.c
cc -c -o prog2/bar2.o prog2/bar2.c
cc -c -o prog2/main.o prog2/main.c
cc -o prog2/prog2 prog2/main.o prog2/bar1.o prog2/bar2.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice the following:
First, you can have files with the same names
in multiple directories, like main.c in the above example.
Second, unlike standard recursive use of <TT
CLASS="APPLICATION"
>Make</TT
>,
<TT
CLASS="APPLICATION"
>SCons</TT
> stays in the top-level directory
(where the <TT
CLASS="FILENAME"
>SConstruct</TT
> file lives)
and issues commands that use the path names
from the top-level directory to the
target and source files within the hierarchy.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN1999"
>Top-Level Path Names in Subsidiary <TT
CLASS="FILENAME"
>SConscript</TT
> Files</A
></H2
><P
>&#13; If you need to use a file from another directory,
it's sometimes more convenient to specify
the path to a file in another directory
from the top-level <TT
CLASS="FILENAME"
>SConstruct</TT
> directory,
even when you're using that file in
a subsidiary <TT
CLASS="FILENAME"
>SConscript</TT
> file in a subdirectory.
You can tell <TT
CLASS="APPLICATION"
>SCons</TT
> to interpret a path name
as relative to the top-level <TT
CLASS="FILENAME"
>SConstruct</TT
> directory,
not the local directory of the <TT
CLASS="FILENAME"
>SConscript</TT
> file,
by appending a <TT
CLASS="LITERAL"
>#</TT
> (hash mark)
to the beginning of the path name:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
env.Program('prog', ['main.c', '#lib/foo1.c', 'foo2.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; In this example,
the <TT
CLASS="LITERAL"
>lib</TT
> directory is
directly underneath the top-level <TT
CLASS="FILENAME"
>SConstruct</TT
> directory.
If the above <TT
CLASS="FILENAME"
>SConscript</TT
> file is in a subdirectory
named <TT
CLASS="LITERAL"
>src/prog</TT
>,
the output would look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o lib/foo1.o lib/foo1.c
cc -c -o src/prog/foo2.o src/prog/foo2.c
cc -c -o src/prog/main.o src/prog/main.c
cc -o src/prog/prog src/prog/main.o lib/foo1.o src/prog/foo2.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; (Notice that the <TT
CLASS="LITERAL"
>lib/foo1.o</TT
> object file
is built in the same directory as its source file.
See <A
HREF="#CHAP-SEPARATE"
>the chapter called <I
>Separating Source and Build Directories</I
></A
>, below,
for information about
how to build the object file in a different subdirectory.)
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2020"
>Absolute Path Names</A
></H2
><P
>&#13; Of course, you can always specify
an absolute path name for a file--for example:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
env.Program('prog', ['main.c', '/usr/joe/lib/foo1.c', 'foo2.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; Which, when executed, would yield:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o src/prog/foo2.o src/prog/foo2.c
cc -c -o src/prog/main.o src/prog/main.c
cc -c -o /usr/joe/lib/foo1.o /usr/joe/lib/foo1.c
cc -o src/prog/prog src/prog/main.o /usr/joe/lib/foo1.o src/prog/foo2.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; (As was the case with top-relative path names,
notice that the <TT
CLASS="LITERAL"
>/usr/joe/lib/foo1.o</TT
> object file
is built in the same directory as its source file.
See <A
HREF="#CHAP-SEPARATE"
>the chapter called <I
>Separating Source and Build Directories</I
></A
>, below,
for information about
how to build the object file in a different subdirectory.)
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2030"
>Sharing Environments (and Other Variables) Between <TT
CLASS="FILENAME"
>SConscript</TT
> Files</A
></H2
><P
>&#13; In the previous example,
each of the subsidiary <TT
CLASS="FILENAME"
>SConscript</TT
> files
created its own construction environment
by calling <TT
CLASS="FUNCTION"
>Environment</TT
> separately.
This obviously works fine,
but if each program must be built
with the same construction variables,
it's cumbersome and error-prone to initialize
separate construction environments
in the same way over and over in each subsidiary
<TT
CLASS="FILENAME"
>SConscript</TT
> file.
</P
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> supports the ability to <I
CLASS="EMPHASIS"
>export</I
> variables
from a parent <TT
CLASS="FILENAME"
>SConscript</TT
> file
to its subsidiary <TT
CLASS="FILENAME"
>SConscript</TT
> files,
which allows you to share common initialized
values throughout your build hierarchy.
</P
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN2042"
>Exporting Variables</A
></H3
><P
>&#13; There are two ways to export a variable,
such as a construction environment,
from an <TT
CLASS="FILENAME"
>SConscript</TT
> file,
so that it may be used by other <TT
CLASS="FILENAME"
>SConscript</TT
> files.
First, you can call the <TT
CLASS="FUNCTION"
>Export</TT
>
function with a list of variables,
or a string white-space separated variable names.
Each call to <TT
CLASS="FUNCTION"
>Export</TT
> adds one
or more variables to a global list
of variables that are available for import
by other <TT
CLASS="FILENAME"
>SConscript</TT
> files.
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
Export('env')
</PRE
></TD
></TR
></TABLE
><P
>&#13; You may export more than one variable name at a time:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
debug = ARGUMENTS['debug']
Export('env', 'debug')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Because white space is not legal in Python variable names,
the <TT
CLASS="FUNCTION"
>Export</TT
> function will even automatically split
a string into separate names for you:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Export('env debug')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Second, you can specify a list of
variables to export as a second argument
to the <TT
CLASS="FILENAME"
>SConscript</TT
> function call:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> SConscript('src/SConscript', 'env')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Or as the <VAR
CLASS="VARNAME"
>exports</VAR
> keyword argument:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> SConscript('src/SConscript', exports='env')
</PRE
></TD
></TR
></TABLE
><P
>&#13; These calls export the specified variables
to only the listed <TT
CLASS="FILENAME"
>SConscript</TT
> files.
You may, however, specify more than one
<TT
CLASS="FILENAME"
>SConscript</TT
> file in a list:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> SConscript(['src1/SConscript',
'src2/SConscript'], exports='env')
</PRE
></TD
></TR
></TABLE
><P
>&#13; This is functionally equivalent to
calling the <TT
CLASS="FILENAME"
>SConscript</TT
> function
multiple times with the same <VAR
CLASS="VARNAME"
>exports</VAR
> argument,
one per <TT
CLASS="FILENAME"
>SConscript</TT
> file.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN2070"
>Importing Variables</A
></H3
><P
>&#13; Once a variable has been exported from a calling
<TT
CLASS="FILENAME"
>SConscript</TT
> file,
it may be used in other <TT
CLASS="FILENAME"
>SConscript</TT
> files
by calling the <TT
CLASS="FUNCTION"
>Import</TT
> function:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Import('env')
env.Program('prog', ['prog.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; The <TT
CLASS="FUNCTION"
>Import</TT
> call makes the <TT
CLASS="LITERAL"
>env</TT
> construction
environment available to the <TT
CLASS="FILENAME"
>SConscript</TT
> file,
after which the variable can be used to build
programs, libraries, etc.
</P
><P
>&#13; Like the <TT
CLASS="FUNCTION"
>Export</TT
> function,
the <TT
CLASS="FUNCTION"
>Import</TT
> function can be used
with multiple variable names:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Import('env', 'debug')
env = env.Copy(DEBUG = debug)
env.Program('prog', ['prog.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; And the <TT
CLASS="FUNCTION"
>Import</TT
> function will similarly
split a string along white-space
into separate variable names:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Import('env debug')
env = env.Copy(DEBUG = debug)
env.Program('prog', ['prog.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; Lastly, as a special case,
you may import all of the variables that
have been exported by supplying an asterisk
to the <TT
CLASS="FUNCTION"
>Import</TT
> function:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Import('*')
env = env.Copy(DEBUG = debug)
env.Program('prog', ['prog.c'])
</PRE
></TD
></TR
></TABLE
><P
>&#13; If you're dealing with a lot of <TT
CLASS="FILENAME"
>SConscript</TT
> files,
this can be a lot simpler than keeping
arbitrary lists of imported variables in each file.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H3
CLASS="SECTION"
><A
NAME="AEN2093"
>Returning Values From an <TT
CLASS="FILENAME"
>SConscript</TT
> File</A
></H3
><P
>&#13; Sometimes, you would like to be able to
use information from a subsidiary
<TT
CLASS="FILENAME"
>SConscript</TT
> file in some way.
For example,
suppose that you want to create one
library from source files
scattered throughout a number
of subsidiary <TT
CLASS="FILENAME"
>SConscript</TT
> files.
You can do this by using the <TT
CLASS="FUNCTION"
>Return</TT
>
function to return values
from the subsidiary <TT
CLASS="FILENAME"
>SConscript</TT
> files
to the calling file.
</P
><P
>&#13; If, for example, we have two subdirectories
<TT
CLASS="APPLICATION"
>foo</TT
> and <TT
CLASS="APPLICATION"
>bar</TT
>
that should each contribute a source
file to a Library,
what we'd like to be able to do is
collect the object files
from the subsidiary <TT
CLASS="FILENAME"
>SConscript</TT
> calls
like this:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
Export('env')
objs = []
for subdir in ['foo', 'bar']:
o = SConscript('%s/SConscript' % subdir)
objs.append(o)
env.Library('prog', objs)
</PRE
></TD
></TR
></TABLE
><P
>&#13; We can do this by using the <TT
CLASS="FUNCTION"
>Return</TT
>
function in the
<TT
CLASS="LITERAL"
>foo/SConscript</TT
> file like this:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Import('env')
obj = env.Object('foo.c')
Return('obj')
</PRE
></TD
></TR
></TABLE
><P
>&#13; (The corresponding
<TT
CLASS="LITERAL"
>bar/SConscript</TT
>
file should be pretty obvious.)
Then when we run <TT
CLASS="APPLICATION"
>SCons</TT
>,
the object files from the subsidiary subdirectories
are all correctly archived in the desired library:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o bar/bar.o bar/bar.c
cc -c -o foo/foo.o foo/foo.c
ar r libprog.a foo/foo.o bar/bar.o
ranlib libprog.a
</PRE
></TD
></TR
></TABLE
></DIV
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-SEPARATE"
></A
>Separating Source and Build Directories</H1
><P
>&#13; It's often useful to keep any built files completely
separate from the source files.
This is usually done by creating one or more separate
<I
CLASS="EMPHASIS"
>build directories</I
>
that are used to hold the built objects files, libraries,
and executable programs, etc.
for a specific flavor of build.
<TT
CLASS="APPLICATION"
>SCons</TT
> provides two ways to do this,
one through the <TT
CLASS="FILENAME"
>SConscript</TT
> function that we've already seen,
and the second through a more flexible <TT
CLASS="FUNCTION"
>BuildDir</TT
> function.
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2122"
>Specifying a Build Directory as Part of an <TT
CLASS="FILENAME"
>SConscript</TT
> Call</A
></H2
><P
>&#13; The most straightforward way to establish a build directory
uses the fact that the usual way to
set up a build hierarchy is to have an
<TT
CLASS="FILENAME"
>SConscript</TT
> file in the source subdirectory.
If you then pass a <VAR
CLASS="VARNAME"
>build_dir</VAR
> argument to the
<TT
CLASS="FILENAME"
>SConscript</TT
> function call:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> SConscript('src/SConscript', build_dir='build')
</PRE
></TD
></TR
></TABLE
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> will then build all of the files in
the <TT
CLASS="FILENAME"
>build</TT
> subdirectory:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>ls src</KBD
>
SConscript hello.c
% <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o build/hello.o build/hello.c
cc -o build/hello build/hello.o
% <KBD
CLASS="USERINPUT"
>ls build</KBD
>
SConscript hello hello.c hello.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; But wait a minute--what's going on here?
<TT
CLASS="APPLICATION"
>SCons</TT
> created the object file
<TT
CLASS="FILENAME"
>build/hello.o</TT
>
in the <TT
CLASS="FILENAME"
>build</TT
> subdirectory,
as expected.
But even though our <TT
CLASS="FILENAME"
>hello.c</TT
> file lives in the <TT
CLASS="FILENAME"
>src</TT
> subdirectory,
<TT
CLASS="APPLICATION"
>SCons</TT
> has actually compiled a
<TT
CLASS="FILENAME"
>build/hello.c</TT
> file
to create the object file.
</P
><P
>&#13; What's happened is that <TT
CLASS="APPLICATION"
>SCons</TT
> has <I
CLASS="EMPHASIS"
>duplicated</I
>
the <TT
CLASS="FILENAME"
>hello.c</TT
> file from the <TT
CLASS="FILENAME"
>src</TT
> subdirectory
to the <TT
CLASS="FILENAME"
>build</TT
> subdirectory,
and built the program from there.
The next section explains why <TT
CLASS="APPLICATION"
>SCons</TT
> does this.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2152"
>Why <TT
CLASS="APPLICATION"
>SCons</TT
> Duplicates Source Files in a Build Directory</A
></H2
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> duplicates source files in build directories
because it's the most straightforward way to guarantee a correct build
<I
CLASS="EMPHASIS"
>regardless of include-file directory paths,
relative references between files,
or tool support for putting files in different locations</I
>,
and the <TT
CLASS="APPLICATION"
>SCons</TT
> philosophy is to, by default,
guarantee a correct build in all cases.
</P
><P
>&#13; The most direct reason to duplicate source files
in build directories
is simply that some tools (mostly older vesions)
are written to only build their output files
in the same directory as the source files.
In this case, the choices are either
to build the output file in the source directory
and move it to the build directory,
or to duplicate the source files in the build directory.
</P
><P
>&#13; Additionally,
relative references between files
can cause problems if we don't
just duplicate the hierarchy of source files
in the build directory.
You can see this at work in
use of the C preprocessor <TT
CLASS="LITERAL"
>#include</TT
>
mechanism with double quotes, not angle brackets:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> #include "file.h"
</PRE
></TD
></TR
></TABLE
><P
>&#13; The <I
CLASS="EMPHASIS"
>de facto</I
> standard behavior
for most C compilers in this case
is to first look in the same directory
as the source file that contains the <TT
CLASS="LITERAL"
>#include</TT
> line,
then to look in the directories in the preprocessor search path.
Add to this that the <TT
CLASS="APPLICATION"
>SCons</TT
> implementation of
support for code repositories
(described below)
means not all of the files
will be found in the same directory hierarchy,
and the simplest way to make sure
that the right include file is found
is to duplicate the source files into the build directory,
which provides a correct build
regardless of the original location(s) of the source files.
</P
><P
>&#13; Although source-file duplication guarantees a correct build
even in these end-cases,
it <I
CLASS="EMPHASIS"
>can</I
> usually be safely disabled.
The next section describes
how you can disable the duplication of source files
in the build directory.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2169"
>Telling <TT
CLASS="APPLICATION"
>SCons</TT
> to Not Duplicate Source Files in the Build Directory</A
></H2
><P
>&#13; In most cases and with most tool sets,
<TT
CLASS="APPLICATION"
>SCons</TT
> can place its target files in a build subdirectory
<I
CLASS="EMPHASIS"
>without</I
>
duplicating the source files
and everything will work just fine.
You can disable the default <TT
CLASS="APPLICATION"
>SCons</TT
> behavior
by specifying <TT
CLASS="LITERAL"
>duplicate=0</TT
>
when you call the <TT
CLASS="FILENAME"
>SConscript</TT
> function:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> SConscript('src/SConscript', build_dir='build', duplicate=0)
</PRE
></TD
></TR
></TABLE
><P
>&#13; When this flag is specified,
<TT
CLASS="APPLICATION"
>SCons</TT
> uses the build directory
like most people expect--that is,
the output files are placed in the build directory
while the source files stay in the source directory:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>ls src</KBD
>
SConscript
hello.c
% <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c src/hello.c -o build/hello.o
cc -o build/hello build/hello.o
% <KBD
CLASS="USERINPUT"
>ls build</KBD
>
hello
hello.o
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2185"
>The <TT
CLASS="FUNCTION"
>BuildDir</TT
> Function</A
></H2
><P
>&#13; Use the <TT
CLASS="FUNCTION"
>BuildDir</TT
> function to establish that target
files should be built in a separate directory
from the source files:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> BuildDir('build', 'src')
env = Environment()
env.Program('build/hello.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Note that when you're not using
an <TT
CLASS="FILENAME"
>SConscript</TT
> file in the <TT
CLASS="FILENAME"
>src</TT
> subdirectory,
you must actually specify that
the program must be built from
the <TT
CLASS="FILENAME"
>build/hello.c</TT
>
file that <TT
CLASS="APPLICATION"
>SCons</TT
> will duplicate in the
<TT
CLASS="FILENAME"
>build</TT
> subdirectory.
</P
><P
>&#13; When using the <TT
CLASS="FUNCTION"
>BuildDir</TT
> function directly,
<TT
CLASS="APPLICATION"
>SCons</TT
> still duplicates the source files
in the build directory by default:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>ls src</KBD
>
hello.c
% <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o build/hello.o build/hello.c
cc -o build/hello build/hello.o
% <KBD
CLASS="USERINPUT"
>ls build</KBD
>
hello hello.c hello.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; You can specify the same <TT
CLASS="LITERAL"
>duplicate=0</TT
> argument
that you can specify for an <TT
CLASS="FILENAME"
>SConscript</TT
> call:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> BuildDir('build', 'src', duplicate=0)
env = Environment()
env.Program('build/hello.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; In which case <TT
CLASS="APPLICATION"
>SCons</TT
>
will disable duplication of the source files:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>ls src</KBD
>
hello.c
% <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o build/hello.o src/hello.c
cc -o build/hello build/hello.o
% <KBD
CLASS="USERINPUT"
>ls build</KBD
>
hello hello.o
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2214"
>Using <TT
CLASS="FUNCTION"
>BuildDir</TT
> With an <TT
CLASS="FILENAME"
>SConscript</TT
> File</A
></H2
><P
>&#13; Even when using the <TT
CLASS="FUNCTION"
>BuildDir</TT
> function,
it's much more natural to use it with
a subsidiary <TT
CLASS="FILENAME"
>SConscript</TT
> file.
For example, if the
<TT
CLASS="FILENAME"
>src/SConscript</TT
>
looks like this:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
env.Program('hello.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Then our <TT
CLASS="FILENAME"
>SConstruct</TT
> file could look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> BuildDir('build', 'src')
SConscript('build/SConscript')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Yielding the following output:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>ls src</KBD
>
SConscript hello.c
% <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o build/hello.o build/hello.c
cc -o build/hello build/hello.o
% <KBD
CLASS="USERINPUT"
>ls build</KBD
>
SConscript hello hello.c hello.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice that this is completely equivalent
to the use of <TT
CLASS="FILENAME"
>SConscript</TT
> that we
learned about in the previous section.
</P
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-VARIANTS"
></A
>Variant Builds</H1
><P
>&#13; The <VAR
CLASS="VARNAME"
>build_dir</VAR
> keyword argument of
the <TT
CLASS="FILENAME"
>SConscript</TT
> function provides everything
we need to show how easy it is to create
variant builds using <TT
CLASS="APPLICATION"
>SCons</TT
>.
Suppose, for example, that we want to
build a program for both Windows and Linux platforms,
but that we want to build it in a shared directory
with separate side-by-side build directories
for the Windows and Linux versions of the program.
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> platform = ARGUMENTS.get('OS', Platform())
include = "#export/$PLATFORM/include"
lib = "#export/$PLATFORM/lib"
bin = "#export/$PLATFORM/bin"
env = Environment(PLATFORM = platform,
BINDIR = bin,
INCDIR = include,
LIBDIR = lib,
CPPPATH = [include],
LIBPATH = [lib],
LIBS = 'world')
Export('env')
env.SConscript('src/SConscript', build_dir='build/$PLATFORM')
</PRE
></TD
></TR
></TABLE
><P
>&#13; This SConstruct file,
when run on a Linux system, yields:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q OS=linux</KBD
>
Install file: "build/linux/world/world.h" as "export/linux/include/world.h"
cc -Iexport/linux/include -c -o build/linux/hello/hello.o build/linux/hello/hello.c
cc -Iexport/linux/include -c -o build/linux/world/world.o build/linux/world/world.c
ar r build/linux/world/libworld.a build/linux/world/world.o
ranlib build/linux/world/libworld.a
Install file: "build/linux/world/libworld.a" as "export/linux/lib/libworld.a"
cc -o build/linux/hello/hello build/linux/hello/hello.o -Lexport/linux/lib -lworld
Install file: "build/linux/hello/hello" as "export/linux/bin/hello"
</PRE
></TD
></TR
></TABLE
><P
>&#13; The same SConstruct file on Windows would build:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons -Q OS=windows</KBD
>
Install file: "build/windows/world/world.h" as "export/windows/include/world.h"
cl /nologo /Iexport\windows\include /c build\windows\hello\hello.c /Fobuild\windows\hello\hello.obj
cl /nologo /Iexport\windows\include /c build\windows\world\world.c /Fobuild\windows\world\world.obj
lib /nologo /OUT:build\windows\world\world.lib build\windows\world\world.obj
Install file: "build/windows/world/world.lib" as "export/windows/lib/world.lib"
link /nologo /OUT:build\windows\hello\hello.exe /LIBPATH:export\windows\lib world.lib build\windows\hello\hello.obj
Install file: "build/windows/hello/hello.exe" as "export/windows/bin/hello.exe"
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-BUILDERS-WRITING"
></A
>Writing Your Own Builders</H1
><P
>&#13; Although <TT
CLASS="APPLICATION"
>SCons</TT
> provides many useful methods
for building common software products:
programs, libraries, documents.
you frequently want to be
able to build some other type of file
not supported directly by <TT
CLASS="APPLICATION"
>SCons</TT
>
Fortunately, <TT
CLASS="APPLICATION"
>SCons</TT
> makes it very easy
to define your own <CODE
CLASS="CLASSNAME"
>Builder</CODE
> objects
for any custom file types you want to build.
(In fact, the <TT
CLASS="APPLICATION"
>SCons</TT
> interfaces for creating
<CODE
CLASS="CLASSNAME"
>Builder</CODE
> objects are flexible enough and easy enough to use
that all of the the <TT
CLASS="APPLICATION"
>SCons</TT
> built-in <CODE
CLASS="CLASSNAME"
>Builder</CODE
> objects
are created the mechanisms described in this section.)
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2257"
>Writing Builders That Execute External Commands</A
></H2
><P
>&#13; The simplest <CODE
CLASS="CLASSNAME"
>Builder</CODE
> to create is
one that executes an external command.
For example, if we want to build
an output file by running the contents
of the input file through a command named
<TT
CLASS="LITERAL"
>foobuild</TT
>,
creating that <CODE
CLASS="CLASSNAME"
>Builder</CODE
> might look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> bld = Builder(action = 'foobuild &#60; $SOURCE &#62; $TARGET')
</PRE
></TD
></TR
></TABLE
><P
>&#13; All the above line does is create a free-standing
<CODE
CLASS="CLASSNAME"
>Builder</CODE
> object.
The next section will show us how to actually use it.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2266"
>Attaching a Builder to a <TT
CLASS="LITERAL"
>Construction Environment</TT
></A
></H2
><P
>&#13; A <CODE
CLASS="CLASSNAME"
>Builder</CODE
> object isn't useful
until it's attached to a <TT
CLASS="LITERAL"
>construction environment</TT
>
so that we can call it to arrange
for files to be built.
This is done through the <A
HREF="#CV-BUILDERS"
><VAR
CLASS="ENVAR"
>$BUILDERS</VAR
></A
>
<TT
CLASS="LITERAL"
>construction variable</TT
> in an environment.
The <VAR
CLASS="ENVAR"
>$BUILDERS</VAR
> variable is a Python dictionary
that maps the names by which you want to call
various <CODE
CLASS="CLASSNAME"
>Builder</CODE
> objects to the objects themselves.
For example, if we want to call the
<CODE
CLASS="CLASSNAME"
>Builder</CODE
> we just defined by the name
<TT
CLASS="FUNCTION"
>Foo</TT
>,
our <TT
CLASS="FILENAME"
>SConstruct</TT
> file might look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> bld = Builder(action = 'foobuild &#60; $SOURCE &#62; $TARGET')
env = Environment(BUILDERS = {'Foo' : bld})
</PRE
></TD
></TR
></TABLE
><P
>&#13; With the <CODE
CLASS="CLASSNAME"
>Builder</CODE
> so attached to our <TT
CLASS="LITERAL"
>construction environment</TT
>
we can now actually call it like so:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env.Foo('file.foo', 'file.input')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Then when we run <TT
CLASS="APPLICATION"
>SCons</TT
> it looks like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
foobuild &#60; file.input &#62; file.foo
</PRE
></TD
></TR
></TABLE
><P
>&#13; Note, however, that the default <VAR
CLASS="ENVAR"
>$BUILDERS</VAR
>
variable in a <TT
CLASS="LITERAL"
>construction environment</TT
>
comes with a default set of <CODE
CLASS="CLASSNAME"
>Builder</CODE
> objects
already defined:
<A
HREF="#B-PROGRAM"
><TT
CLASS="FUNCTION"
>Program</TT
></A
>, <A
HREF="#B-LIBRARY"
><TT
CLASS="FUNCTION"
>Library</TT
></A
>, etc.
And when we explicitly set the <VAR
CLASS="ENVAR"
>$BUILDERS</VAR
> variable
when we create the <TT
CLASS="LITERAL"
>construction environment</TT
>,
the default <CODE
CLASS="CLASSNAME"
>Builder</CODE
>s are no longer part of
the environment:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> bld = Builder(action = 'foobuild &#60; $SOURCE &#62; $TARGET')
env = Environment(BUILDERS = {'Foo' : bld})
env.Foo('file.foo', 'file.input')
env.Program('hello.c')
</PRE
></TD
></TR
></TABLE
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
AttributeError: 'SConsEnvironment' object has no attribute 'Program':
File "SConstruct", line 4:
env.Program('hello.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; To be able use both our own defined <CODE
CLASS="CLASSNAME"
>Builder</CODE
> objects
and the default <CODE
CLASS="CLASSNAME"
>Builder</CODE
> objects in the same <TT
CLASS="LITERAL"
>construction environment</TT
>,
you can either add to the <VAR
CLASS="ENVAR"
>$BUILDERS</VAR
> variable
using the <TT
CLASS="FUNCTION"
>Append</TT
> function:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
bld = Builder(action = 'foobuild &#60; $SOURCE &#62; $TARGET')
env.Append(BUILDERS = {'Foo' : bld})
env.Foo('file.foo', 'file.input')
env.Program('hello.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Or you can explicitly set the appropriately-named
key in the <VAR
CLASS="ENVAR"
>$BUILDERS</VAR
> dictionary:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
bld = Builder(action = 'foobuild &#60; $SOURCE &#62; $TARGET')
env['BUILDERS']['Foo'] = bld
env.Foo('file.foo', 'file.input')
env.Program('hello.c')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Either way, the same <TT
CLASS="LITERAL"
>construction environment</TT
>
can then use both the newly-defined
<TT
CLASS="FUNCTION"
>Foo</TT
> <CODE
CLASS="CLASSNAME"
>Builder</CODE
>
and the default <A
HREF="#B-PROGRAM"
><TT
CLASS="FUNCTION"
>Program</TT
></A
> <CODE
CLASS="CLASSNAME"
>Builder</CODE
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
foobuild &#60; file.input &#62; file.foo
cc -c -o hello.o hello.c
cc -o hello hello.o
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2322"
>Letting <TT
CLASS="APPLICATION"
>SCons</TT
> Handle The File Suffixes</A
></H2
><P
>&#13; By supplying additional information
when you create a <CODE
CLASS="CLASSNAME"
>Builder</CODE
>,
you can let <TT
CLASS="APPLICATION"
>SCons</TT
> add appropriate file
suffixes to the target and/or the source file.
For example, rather than having to specify
explicitly that you want the <TT
CLASS="LITERAL"
>Foo</TT
>
<CODE
CLASS="CLASSNAME"
>Builder</CODE
> to build the <TT
CLASS="LITERAL"
>file.foo</TT
>
target file from the <TT
CLASS="LITERAL"
>file.input</TT
> source file,
you can give the <TT
CLASS="LITERAL"
>.foo</TT
>
and <TT
CLASS="LITERAL"
>.input</TT
> suffixes to the <CODE
CLASS="CLASSNAME"
>Builder</CODE
>,
making for more compact and readable calls to
the <TT
CLASS="LITERAL"
>Foo</TT
> <CODE
CLASS="CLASSNAME"
>Builder</CODE
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> bld = Builder(action = 'foobuild &#60; $SOURCE &#62; $TARGET',
suffix = '.foo',
src_suffix = '.input')
env = Environment(BUILDERS = {'Foo' : bld})
env.Foo('file1')
env.Foo('file2')
</PRE
></TD
></TR
></TABLE
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
foobuild &#60; file1.input &#62; file1.foo
foobuild &#60; file2.input &#62; file2.foo
</PRE
></TD
></TR
></TABLE
><P
>&#13; You can also supply a <TT
CLASS="LITERAL"
>prefix</TT
> keyword argument
if it's appropriate to have <TT
CLASS="APPLICATION"
>SCons</TT
> append a prefix
to the beginning of target file names.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2343"
>Builders That Execute Python Functions</A
></H2
><P
>&#13; In <TT
CLASS="APPLICATION"
>SCons</TT
>, you don't have to call an external command
to build a file.
You can, instead, define a Python function
that a <CODE
CLASS="CLASSNAME"
>Builder</CODE
> object can invoke
to build your target file (or files).
Such a <TT
CLASS="LITERAL"
>builder function</TT
> definition looks like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> def build_function(target, source, env):
# Code to build "target" from "source"
return None
</PRE
></TD
></TR
></TABLE
><P
>&#13; The arguments of a <TT
CLASS="LITERAL"
>builder function</TT
> are:
</P
><P
></P
><DIV
CLASS="VARIABLELIST"
><DL
><DT
>target</DT
><DD
><P
>&#13; A list of Node objects representing
the target or targets to be
built by this builder function.
The file names of these target(s)
may be extracted using the Python <TT
CLASS="FUNCTION"
>str</TT
> function.
</P
></DD
><DT
>source</DT
><DD
><P
>&#13; A list of Node objects representing
the sources to be
used by this builder function to build the targets.
The file names of these source(s)
may be extracted using the Python <TT
CLASS="FUNCTION"
>str</TT
> function.
</P
></DD
><DT
>env</DT
><DD
><P
>&#13; The <TT
CLASS="LITERAL"
>construction environment</TT
> used for building the target(s).
The builder function may use any of the
environment's construction variables
in any way to affect how it builds the targets.
</P
></DD
></DL
></DIV
><P
>&#13; The builder function must
return a <TT
CLASS="LITERAL"
>0</TT
> or <TT
CLASS="LITERAL"
>None</TT
> value
if the target(s) are built successfully.
The builder function
may raise an exception
or return any non-zero value
to indicate that the build is unsuccessful,
</P
><P
>&#13; Once you've defined the Python function
that will build your target file,
defining a <CODE
CLASS="CLASSNAME"
>Builder</CODE
> object for it is as
simple as specifying the name of the function,
instead of an external command,
as the <CODE
CLASS="CLASSNAME"
>Builder</CODE
>'s
<TT
CLASS="LITERAL"
>action</TT
>
argument:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> def build_function(target, source, env):
# Code to build "target" from "source"
return None
bld = Builder(action = build_function,
suffix = '.foo',
src_suffix = '.input')
env = Environment(BUILDERS = {'Foo' : bld})
env.Foo('file')
</PRE
></TD
></TR
></TABLE
><P
>&#13; And notice that the output changes slightly,
reflecting the fact that a Python function,
not an external command,
is now called to build the target file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
build_function(["file.foo"], ["file.input"])
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2379"
>Builders That Create Actions Using a <TT
CLASS="LITERAL"
>Generator</TT
></A
></H2
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> Builder objects can create an action "on the fly"
by using a function called a <TT
CLASS="LITERAL"
>generator</TT
>.
This provides a great deal of flexibility to
construct just the right list of commands
to build your target.
A <TT
CLASS="LITERAL"
>generator</TT
> looks like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> def generate_actions(source, target, env, for_signature):
return 'foobuild &#60; %s &#62; %s' % (target[0], source[0])
</PRE
></TD
></TR
></TABLE
><P
>&#13; The arguments of a <TT
CLASS="LITERAL"
>generator</TT
> are:
</P
><P
></P
><DIV
CLASS="VARIABLELIST"
><DL
><DT
>source</DT
><DD
><P
>&#13; A list of Node objects representing
the sources to be built
by the command or other action
generated by this function.
The file names of these source(s)
may be extracted using the Python <TT
CLASS="FUNCTION"
>str</TT
> function.
</P
></DD
><DT
>target</DT
><DD
><P
>&#13; A list of Node objects representing
the target or targets to be built
by the command or other action
generated by this function.
The file names of these target(s)
may be extracted using the Python <TT
CLASS="FUNCTION"
>str</TT
> function.
</P
></DD
><DT
>env</DT
><DD
><P
>&#13; The <TT
CLASS="LITERAL"
>construction environment</TT
> used for building the target(s).
The generator may use any of the
environment's construction variables
in any way to determine what command
or other action to return.
</P
></DD
><DT
>for_signature</DT
><DD
><P
>&#13; A flag that specifies whether the
generator is being called to contribute to a build signature,
as opposed to actually executing the command.
</P
></DD
></DL
></DIV
><P
>&#13; The <TT
CLASS="LITERAL"
>generator</TT
> must return a
command string or other action that will be used to
build the specified target(s) from the specified source(s).
</P
><P
>&#13; Once you've defined a <TT
CLASS="LITERAL"
>generator</TT
>,
you create a <CODE
CLASS="CLASSNAME"
>Builder</CODE
> to use it
by specifying the generator keyword argument
instead of <TT
CLASS="LITERAL"
>action</TT
>.
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> def generate_actions(source, target, env, for_signature):
return 'foobuild &#60; %s &#62; %s' % (source[0], target[0])
bld = Builder(generator = generate_actions,
suffix = '.foo',
src_suffix = '.input')
env = Environment(BUILDERS = {'Foo' : bld})
env.Foo('file')
</PRE
></TD
></TR
></TABLE
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
foobuild &#60; file.input &#62; file.foo
</PRE
></TD
></TR
></TABLE
><P
>&#13; Note that it's illegal to specify both an
<TT
CLASS="LITERAL"
>action</TT
>
and a
<TT
CLASS="LITERAL"
>generator</TT
>
for a <CODE
CLASS="CLASSNAME"
>Builder</CODE
>.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2422"
>Builders That Modify the Target or Source Lists Using an <TT
CLASS="LITERAL"
>Emitter</TT
></A
></H2
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> supports the ability for a Builder to modify the
lists of target(s) from the specified source(s).
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> def modify_targets(target, source, env):
target.append('new_target')
source.append('new_source')
return target, source
bld = Builder(action = 'foobuild $TARGETS - $SOURCES',
suffix = '.foo',
src_suffix = '.input',
emitter = modify_targets)
env = Environment(BUILDERS = {'Foo' : bld})
env.Foo('file')
</PRE
></TD
></TR
></TABLE
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
foobuild file.foo new_target - file.input new_source
</PRE
></TD
></TR
></TABLE
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> bld = Builder(action = 'XXX',
suffix = '.foo',
src_suffix = '.input',
emitter = 'MY_EMITTER')
def modify1(target, source, env):
return target, source
def modify2(target, source, env):
return target, source
env1 = Environment(BUILDERS = {'Foo' : bld},
MY_EMITTER = modify1)
env2 = Environment(BUILDERS = {'Foo' : bld},
MY_EMITTER = modify2)
env1.Foo('file1')
env2.Foo('file2')
</PRE
></TD
></TR
></TABLE
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-BUILDERS-COMMANDS"
></A
>Not Writing a Builder: the <TT
CLASS="FUNCTION"
>Command</TT
> Builder</H1
><P
>&#13; Creating a <CODE
CLASS="CLASSNAME"
>Builder</CODE
> and attaching it to a <TT
CLASS="LITERAL"
>construction environment</TT
>
allows for a lot of flexibility when you
want to re-use actions
to build multiple files of the same type.
This can, however, be cumbersome
if you only need to execute one specific command
to build a single file (or group of files).
For these situations, <TT
CLASS="APPLICATION"
>SCons</TT
> supports a
<TT
CLASS="FUNCTION"
>Command</TT
> <CODE
CLASS="CLASSNAME"
>Builder</CODE
> that arranges
for a specific action to be executed
to build a specific file or files.
This looks a lot like the other builders
(like <A
HREF="#B-PROGRAM"
><TT
CLASS="FUNCTION"
>Program</TT
></A
>, <A
HREF="#B-OBJECT"
><TT
CLASS="FUNCTION"
>Object</TT
></A
>, etc.),
but takes as an additional argument
the command to be executed to build the file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
env.Command('foo.out', 'foo.in', "sed 's/x/y/' &#60; $SOURCE &#62; $TARGET")
</PRE
></TD
></TR
></TABLE
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
sed 's/x/y/' &#60; foo.in &#62; foo.out
</PRE
></TD
></TR
></TABLE
><P
>&#13; This is often more convenient than
creating a <CODE
CLASS="CLASSNAME"
>Builder</CODE
> object
and adding it to the <A
HREF="#CV-BUILDERS"
><VAR
CLASS="ENVAR"
>$BUILDERS</VAR
></A
> variable
of a <TT
CLASS="LITERAL"
>construction environment</TT
>
</P
><P
>&#13; Note that the action you
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
def build(target, source, env):
# Whatever it takes to build
return None
env.Command('foo.out', 'foo.in', build)
</PRE
></TD
></TR
></TABLE
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
build(["foo.out"], ["foo.in"])
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-SCANNERS"
></A
>Writing Scanners</H1
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> has built-in scanners that know how to look in
C, Fortran and IDL source files for information about
other files that targets built from those files depend on--for example,
in the case of files that use the C preprocessor,
the <TT
CLASS="FILENAME"
>.h</TT
> files that are specified
using <TT
CLASS="LITERAL"
>#include</TT
> lines in the source.
You can use the same mechanisms that <TT
CLASS="APPLICATION"
>SCons</TT
> uses to create
its built-in scanners to write scanners of your own for file types
that <TT
CLASS="APPLICATION"
>SCons</TT
> does not know how to scan "out of the box."
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2464"
>A Simple Scanner Example</A
></H2
><P
>&#13; Suppose, for example, that we want to create a simple scanner
for <TT
CLASS="FILENAME"
>.foo</TT
> files.
A <TT
CLASS="FILENAME"
>.foo</TT
> file contains some text that
will be processed,
and can include other files on lines that begin
with <TT
CLASS="LITERAL"
>include</TT
>
followed by a file name:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> include filename.foo
</PRE
></TD
></TR
></TABLE
><P
>&#13; Scanning a file will be handled by a Python function
that you must supply.
Here is a function that will use the Python
<TT
CLASS="FILENAME"
>re</TT
> module
to scan for the <TT
CLASS="LITERAL"
>include</TT
> lines in our example:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> import re
include_re = re.compile(r'^include\s+(\S+)$', re.M)
def kfile_scan(node, env, path, arg):
contents = node.get_contents()
return include_re.findall(contents)
</PRE
></TD
></TR
></TABLE
><P
>&#13; The scanner function must
accept the four specified arguments
and return a list of implicit dependencies.
Presumably, these would be dependencies found
from examining the contents of the file,
although the function can perform any
manipulation at all to generate the list of
dependencies.
</P
><P
></P
><DIV
CLASS="VARIABLELIST"
><DL
><DT
>node</DT
><DD
><P
>&#13; An <TT
CLASS="APPLICATION"
>SCons</TT
> node object representing the file being scanned.
The path name to the file can be
used by converting the node to a string
using the <TT
CLASS="LITERAL"
>str()</TT
> function,
or an internal <TT
CLASS="APPLICATION"
>SCons</TT
> <TT
CLASS="LITERAL"
>get_contents()</TT
>
object method can be used to fetch the contents.
</P
></DD
><DT
>env</DT
><DD
><P
>&#13; The construction environment in effect for this scan.
The scanner function may choose to use construction
variables from this environment to affect its behavior.
</P
></DD
><DT
>path</DT
><DD
><P
>&#13; A list of directories that form the search path for included files
for this scanner.
This is how <TT
CLASS="APPLICATION"
>SCons</TT
> handles the <A
HREF="#CV-CPPPATH"
><VAR
CLASS="ENVAR"
>$CPPPATH</VAR
></A
> and <A
HREF="#CV-LIBPATH"
><VAR
CLASS="ENVAR"
>$LIBPATH</VAR
></A
>
variables.
</P
></DD
><DT
>arg</DT
><DD
><P
>&#13; An optional argument that you can choose to
have passed to this scanner function by
various scanner instances.
</P
></DD
></DL
></DIV
><P
>&#13; A Scanner object is created using the <CODE
CLASS="CLASSNAME"
>Scanner</CODE
> function,
which typically takes an <TT
CLASS="LITERAL"
>skeys</TT
> argument
to associate the type of file suffix with this scanner.
The Scanner object must then be associated with the
<A
HREF="#CV-SCANNERS"
><VAR
CLASS="ENVAR"
>$SCANNERS</VAR
></A
> construction variable of a construction environment,
typically by using the <TT
CLASS="FUNCTION"
>Append</TT
> method:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> kscan = Scanner(function = kfile_scan,
skeys = ['.k'])
env.Append(SCANNERS = kscan)
</PRE
></TD
></TR
></TABLE
><P
>&#13; When we put it all together, it looks like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> import re
include_re = re.compile(r'^include\s+(\S+)$', re.M)
def kfile_scan(node, env, path):
contents = node.get_contents()
includes = include_re.findall(contents)
return includes
kscan = Scanner(function = kfile_scan,
skeys = ['.k'])
env = Environment(ENV = {'PATH' : '/usr/local/bin'})
env.Append(SCANNERS = kscan)
env.Command('foo', 'foo.k', 'kprocess &#60; $SOURCES &#62; $TARGET')
</PRE
></TD
></TR
></TABLE
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-REPOSITORIES"
></A
>Building From Code Repositories</H1
><P
>&#13; Often, a software project will have
one or more central repositories,
directory trees that contain
source code, or derived files, or both.
You can eliminate additional unnecessary
rebuilds of files by having <TT
CLASS="APPLICATION"
>SCons</TT
>
use files from one or more code repositories
to build files in your local build tree.
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2515"
>The <TT
CLASS="FUNCTION"
>Repository</TT
> Method</A
></H2
><P
>&#13; It's often useful to allow multiple programmers working
on a project to build software from
source files and/or derived files that
are stored in a centrally-accessible repository,
a directory copy of the source code tree.
(Note that this is not the sort of repository
maintained by a source code management system
like BitKeeper, CVS, or Subversion.
For information about using <TT
CLASS="APPLICATION"
>SCons</TT
>
with these systems, see the section,
"Fetching Files From Source Code Management Systems,"
below.)
You use the <TT
CLASS="FUNCTION"
>Repository</TT
> method
to tell <TT
CLASS="APPLICATION"
>SCons</TT
> to search one or more
central code repositories (in order)
for any source files and derived files
that are not present in the local build tree:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
env.Program('hello.c')
Repository('/usr/repository1', '/usr/repository2')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Multiple calls to the <TT
CLASS="FUNCTION"
>Repository</TT
> method
will simply add repositories to the global list
that <TT
CLASS="APPLICATION"
>SCons</TT
> maintains,
with the exception that <TT
CLASS="APPLICATION"
>SCons</TT
> will automatically eliminate
the current directory and any non-existent
directories from the list.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2527"
>Finding source files in repositories</A
></H2
><P
>&#13; The above example
specifies that <TT
CLASS="APPLICATION"
>SCons</TT
>
will first search for files under
the <TT
CLASS="FILENAME"
>/usr/repository1</TT
> tree
and next under the <TT
CLASS="FILENAME"
>/usr/repository2</TT
> tree.
<TT
CLASS="APPLICATION"
>SCons</TT
> expects that any files it searches
for will be found in the same position
relative to the top-level directory.
In the above example, if the <TT
CLASS="FILENAME"
>hello.c</TT
> file is not
found in the local build tree,
<TT
CLASS="APPLICATION"
>SCons</TT
> will search first for
a <TT
CLASS="FILENAME"
>/usr/repository1/hello.c</TT
> file
and then for a <TT
CLASS="FILENAME"
>/usr/repository1/hello.c</TT
> file
to use in its place.
</P
><P
>&#13; So given the <TT
CLASS="FILENAME"
>SConstruct</TT
> file above,
if the <TT
CLASS="FILENAME"
>hello.c</TT
> file exists in the local
build directory,
<TT
CLASS="APPLICATION"
>SCons</TT
> will rebuild the <TT
CLASS="APPLICATION"
>hello</TT
> program
as normal:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; If, however, there is no local <TT
CLASS="FILENAME"
>hello.c</TT
> file,
but one exists in <TT
CLASS="FILENAME"
>/usr/repository1</TT
>,
<TT
CLASS="APPLICATION"
>SCons</TT
> will recompile the <TT
CLASS="APPLICATION"
>hello</TT
> program
from the source file it finds in the repository:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
gcc -c /usr/repository1/hello.c -o hello.o
gcc -o hello hello.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; And similarly, if there is no local <TT
CLASS="FILENAME"
>hello.c</TT
> file
and no <TT
CLASS="FILENAME"
>/usr/repository1/hello.c</TT
>,
but one exists in <TT
CLASS="FILENAME"
>/usr/repository2</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; </P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2559"
>Finding the <TT
CLASS="FILENAME"
>SConstruct</TT
> file in repositories</A
></H2
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> will also search in repositories
for the <TT
CLASS="FILENAME"
>SConstruct</TT
> file and any specified <TT
CLASS="FILENAME"
>SConscript</TT
> files.
This poses a problem, though: how can <TT
CLASS="APPLICATION"
>SCons</TT
> search a
repository tree for an <TT
CLASS="FILENAME"
>SConstruct</TT
> file
if the <TT
CLASS="FILENAME"
>SConstruct</TT
> file itself contains the information
about the pathname of the repository?
To solve this problem, <TT
CLASS="APPLICATION"
>SCons</TT
> allows you
to specify repository directories
on the command line using the <TT
CLASS="LITERAL"
>-Y</TT
> option:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q -Y /usr/repository1 -Y /usr/repository2</KBD
>
</PRE
></TD
></TR
></TABLE
><P
>&#13; When looking for source or derived files,
<TT
CLASS="APPLICATION"
>SCons</TT
> will first search the repositories
specified on the command line,
and then search the repositories
specified in the <TT
CLASS="FILENAME"
>SConstruct</TT
> or <TT
CLASS="FILENAME"
>SConscript</TT
> files.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2577"
>Finding derived files in repositories</A
></H2
><P
>&#13; If a repository contains not only source files,
but also derived files (such as object files,
libraries, or executables), <TT
CLASS="APPLICATION"
>SCons</TT
> will perform
its normal MD5 signature calculation to
decide if a derived file in a repository is up-to-date,
or the derived file must be rebuilt in the local build directory.
For the <TT
CLASS="APPLICATION"
>SCons</TT
> signature calculation to work correctly,
a repository tree must contain the <TT
CLASS="FILENAME"
>.sconsign</TT
> files
that <TT
CLASS="APPLICATION"
>SCons</TT
> uses to keep track of signature information.
</P
><P
>&#13; Usually, this would be done by a build integrator
who would run <TT
CLASS="APPLICATION"
>SCons</TT
> in the repository
to create all of its derived files and <TT
CLASS="FILENAME"
>.sconsign</TT
> files,
or who would <TT
CLASS="APPLICATION"
>SCons</TT
> in a separate build directory
and copying the resulting tree to the desired repository:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>cd /usr/repository1</KBD
>
% <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o file1.o file1.c
cc -c -o file2.o file2.c
cc -c -o hello.o hello.c
cc -o hello hello.o file1.o file2.o
</PRE
></TD
></TR
></TABLE
><P
>
(Note that this is safe even if the <TT
CLASS="FILENAME"
>SConstruct</TT
> file
lists <TT
CLASS="FILENAME"
>/usr/repository1</TT
> as a repository,
because <TT
CLASS="APPLICATION"
>SCons</TT
> will remove the current build directory
from its repository list for that invocation.)
</P
><P
>&#13; Now, with the repository populated,
we only need to create the one local source file
we're interested in working with at the moment,
and use the <TT
CLASS="LITERAL"
>-Y</TT
> option to
tell <TT
CLASS="APPLICATION"
>SCons</TT
> to fetch any other files it needs
from the repository:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>cd $HOME/build</KBD
>
% <KBD
CLASS="USERINPUT"
>edit hello.c</KBD
>
% <KBD
CLASS="USERINPUT"
>scons -Q -Y /usr/repository1</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o /usr/repository1/file1.o /usr/repository1/file2.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice that <TT
CLASS="APPLICATION"
>SCons</TT
> realizes that it does not need to
rebuild local copies file1.o and file2.o files,
but instead uses the already-compiled files
from the repository.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2604"
>Guaranteeing local copies of files</A
></H2
><P
>&#13; If the repository tree contains the complete results of a build,
and we try to build from the repository
without any files in our local tree,
something moderately surprising happens:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>mkdir $HOME/build2</KBD
>
% <KBD
CLASS="USERINPUT"
>cd $HOME/build2</KBD
>
% <KBD
CLASS="USERINPUT"
>scons -Q -Y /usr/all/repository hello</KBD
>
scons: `hello' is up-to-date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; Why does <TT
CLASS="APPLICATION"
>SCons</TT
> say that the <TT
CLASS="APPLICATION"
>hello</TT
> program
is up-to-date when there is no <TT
CLASS="APPLICATION"
>hello</TT
> program
in the local build directory?
Because the repository (not the local directory)
contains the up-to-date <TT
CLASS="APPLICATION"
>hello</TT
> program,
and <TT
CLASS="APPLICATION"
>SCons</TT
> correctly determines that nothing
needs to be done to rebuild that
up-to-date copy of the file.
</P
><P
>&#13; There are, however, many times when you want to ensure that a
local copy of a file always exists.
A packaging or testing script, for example,
may assume that certain generated files exist locally.
To tell <TT
CLASS="APPLICATION"
>SCons</TT
> to make a copy of any up-to-date repository
file in the local build directory,
use the <TT
CLASS="FUNCTION"
>Local</TT
> function:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
hello = env.Program('hello.c')
Local(hello)
</PRE
></TD
></TR
></TABLE
><P
>&#13; If we then run the same command,
<TT
CLASS="APPLICATION"
>SCons</TT
> will make a local copy of the program
from the repository copy,
and tell you that it is doing so:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Y /usr/all/repository hello</KBD
>
Local copy of hello from /usr/all/repository/hello
scons: `hello' is up-to-date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; (Notice that, because the act of making the local copy
is not considered a "build" of the <TT
CLASS="APPLICATION"
>hello</TT
> file,
<TT
CLASS="APPLICATION"
>SCons</TT
> still reports that it is up-to-date.)
</P
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-SCONF"
></A
>Multi-Platform Configuration (<TT
CLASS="APPLICATION"
>Autoconf</TT
> Functionality)</H1
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> has integrated support for multi-platform build configuration
similar to that offered by GNU <TT
CLASS="APPLICATION"
>Autoconf</TT
>,
such as
figuring out what libraries or header files
are available on the local system.
This section describes how to use
this <TT
CLASS="APPLICATION"
>SCons</TT
> feature.
</P
><DIV
CLASS="NOTE"
><P
></P
><TABLE
CLASS="NOTE"
WIDTH="100%"
BORDER="0"
><TR
><TD
WIDTH="25"
ALIGN="CENTER"
VALIGN="TOP"
><IMG
SRC="./stylesheet-images/note.gif"
HSPACE="5"
ALT="Note"></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
><P
> This chapter is still under development,
so not everything is explained as well as it should be.
See the <TT
CLASS="APPLICATION"
>SCons</TT
> man page for additional information.
</P
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2638"
><TT
CLASS="LITERAL"
>Configure Contexts</TT
></A
></H2
><P
>&#13; The basic framework for multi-platform build configuration
in <TT
CLASS="APPLICATION"
>SCons</TT
> is to attach a <TT
CLASS="LITERAL"
>configure context</TT
> to a
construction environment by calling the <TT
CLASS="FUNCTION"
>Configure</TT
> function,
perform a number of checks for
libraries, functions, header files, etc.,
and to then call the configure context's <TT
CLASS="FUNCTION"
>Finish</TT
> method
to finish off the configuration:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
conf = Configure(env)
# Checks for libraries, header files, etc. go here!
env = conf.Finish()
</PRE
></TD
></TR
></TABLE
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> provides a number of basic checks,
as well as a mechanism for adding your own custom checks.
</P
><P
>&#13; Note that <TT
CLASS="APPLICATION"
>SCons</TT
> uses its own dependency
mechanism to determine when a check
needs to be run--that is,
<TT
CLASS="APPLICATION"
>SCons</TT
> does not run the checks
every time it is invoked,
but caches the values returned by previous checks
and uses the cached values unless something has changed.
This saves a tremendous amount
of developer time while working on
cross-platform build issues.
</P
><P
>&#13; The next sections describe
the basic checks that <TT
CLASS="APPLICATION"
>SCons</TT
> supports,
as well as how to add your own custom checks.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2654"
>Checking for the Existence of Header Files</A
></H2
><P
>&#13; Testing the existence of a header file
requires knowing what language the header file is.
A configure context has a <TT
CLASS="FUNCTION"
>CheckCHeader</TT
> method
that checks for the existence of a C header file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
conf = Configure(env)
if not conf.CheckCHeader('math.h'):
print 'Math.h must be installed!'
Exit(1)
if conf.CheckCHeader('foo.h'):
conf.env.Append('-DHAS_FOO_H')
env = conf.Finish()
</PRE
></TD
></TR
></TABLE
><P
>&#13; Note that you can choose to terminate
the build if a given header file doesn't exist,
or you can modify the contstruction environment
based on the existence of a header file.
</P
><P
>&#13; If you need to check for the existence
a C++ header file,
use the <TT
CLASS="FUNCTION"
>CheckCXXHeader</TT
> method:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
conf = Configure(env)
if not conf.CheckCXXHeader('vector.h'):
print 'vector.h must be installed!'
Exit(1)
env = conf.Finish()
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2663"
>Checking for the Availability of a Function</A
></H2
><P
>&#13; Check for the availability of a specific function
using the <TT
CLASS="FUNCTION"
>CheckFunc</TT
> method:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
conf = Configure(env)
if not conf.CheckFunc('strcpy'):
print 'Did not find strcpy(), using local version'
conf.env.Append('-Dstrcpy=my_local_strcpy')
env = conf.Finish()
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2668"
>Checking for the Availability of a Library</A
></H2
><P
>&#13; Check for the availability of a library
using the <TT
CLASS="FUNCTION"
>CheckLib</TT
> method.
You only specify the basename of the library,
you don't need to add a <TT
CLASS="LITERAL"
>lib</TT
>
prefix or a <TT
CLASS="LITERAL"
>.a</TT
> or <TT
CLASS="LITERAL"
>.lib</TT
> suffix:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
conf = Configure(env)
if not conf.CheckLib('m'):
print 'Did not find libm.a or m.lib, exiting!'
Exit(1)
env = conf.Finish()
</PRE
></TD
></TR
></TABLE
><P
>&#13; Because the ability to use a library successfully
often depends on having access to a header file
that describes the library's interface,
you can check for a library
<I
CLASS="EMPHASIS"
>and</I
> a header file
at the same time by using the
<TT
CLASS="FUNCTION"
>CheckLibWithHeader</TT
> method:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
conf = Configure(env)
if not conf.CheckLibWithHeader('m', 'math.h'):
print 'Did not find libm.a or m.lib, exiting!'
Exit(1)
env = conf.Finish()
</PRE
></TD
></TR
></TABLE
><P
>&#13; This is essentially shorthand for
separate calls to the <TT
CLASS="FUNCTION"
>CheckHeader</TT
> and <TT
CLASS="FUNCTION"
>CheckLib</TT
>
functions.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2683"
>Checking for the Availability of a <TT
CLASS="LITERAL"
>typedef</TT
></A
></H2
><P
>&#13; Check for the availability of a <TT
CLASS="LITERAL"
>typedef</TT
>
by using the <TT
CLASS="FUNCTION"
>CheckType</TT
> method:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
conf = Configure(env)
if not conf.CheckType('off_t'):
print 'Did not find off_t typedef, assuming int'
conf.env.Append(CCFLAGS = '-Doff_t=int')
env = conf.Finish()
</PRE
></TD
></TR
></TABLE
><P
>&#13; You can also add a string that will be
placed at the beginning of the test file
that will be used to check for the <TT
CLASS="LITERAL"
>typedef</TT
>.
This provide a way to specify
files that must be included to find the <TT
CLASS="LITERAL"
>typedef</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
conf = Configure(env)
if not conf.CheckType('off_t', '#include &#60;sys/types.h&#62;\n'):
print 'Did not find off_t typedef, assuming int'
conf.env.Append(CCFLAGS = '-Doff_t=int')
env = conf.Finish()
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2694"
>Adding Your Own Custom Checks</A
></H2
><P
>&#13; A custom check is a Python function
that checks for a certain condition to exist
on the running system,
usually using methods that <TT
CLASS="APPLICATION"
>SCons</TT
>
supplies to take care of the details
of checking whether a compilation succeeds,
a link succeeds,
a program is runnable,
etc.
A simple custom check for the existence of
a specific library might look as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> mylib_test_source_file = """
#include &#60;mylib.h&#62;
int main(int argc, char **argv)
{
MyLibrary mylib(argc, argv);
return 0;
}
"""
def CheckMyLibrary(context):
context.Message('Checking for MyLibrary...')
result = context.TryLink(mylib_test_source_file, '.c')
context.Result(result)
return result
</PRE
></TD
></TR
></TABLE
><P
>&#13; The <TT
CLASS="FUNCTION"
>Message</TT
> and <TT
CLASS="FUNCTION"
>Result</TT
> methods
should typically begin and end a custom check to
let the user know what's going on:
the <TT
CLASS="FUNCTION"
>Message</TT
> call prints the
specified message (with no trailing newline)
and the <TT
CLASS="FUNCTION"
>Result</TT
> call prints
<TT
CLASS="LITERAL"
>ok</TT
> if the check succeeds and
<TT
CLASS="LITERAL"
>failed</TT
> if it doesn't.
The <TT
CLASS="FUNCTION"
>TryLink</TT
> method
actually tests for whether the
specified program text
will successfully link.
</P
><P
>&#13; (Note that a custom check can modify
its check based on any arguments you
choose to pass it,
or by using or modifying the configure context environment
in the <TT
CLASS="LITERAL"
>context.env</TT
> attribute.)
</P
><P
>&#13; This custom check function is
then attached to the <TT
CLASS="LITERAL"
>configure context</TT
>
by passing a dictionary
to the <TT
CLASS="FUNCTION"
>Configure</TT
> call
that maps a name of the check
to the underlying function:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary})
</PRE
></TD
></TR
></TABLE
><P
>&#13; You'll typically want to make
the check and the function name the same,
as we've done here,
to avoid potential confusion.
</P
><P
>&#13; We can then put these pieces together
and actually call the <TT
CLASS="LITERAL"
>CheckMyLibrary</TT
> check
as follows:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> mylib_test_source_file = """
#include &#60;mylib.h&#62;
int main(int argc, char **argv)
{
MyLibrary mylib(argc, argv);
return 0;
}
"""
def CheckMyLibrary(context):
context.Message('Checking for MyLibrary... ')
result = context.TryLink(mylib_test_source_file, '.c')
context.Result(result)
return result
env = Environment()
conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary})
if not conf.CheckMyLibrary():
print 'MyLibrary is not installed!'
Exit(1)
env = conf.Finish()
# We would then add actual calls like Program() to build
# something using the "env" construction environment.
</PRE
></TD
></TR
></TABLE
><P
>&#13; If MyLibrary is not installed on the system,
the output will look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript file ...
Checking for MyLibrary... failed
MyLibrary is not installed!
</PRE
></TD
></TR
></TABLE
><P
>&#13; If MyLibrary is installed,
the output will look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript file ...
Checking for MyLibrary... failed
scons: done reading SConscript
scons: Building targets ...
.
.
.
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2723"
>Not Configuring When Cleaning Targets</A
></H2
><P
>&#13; Using multi-platform configuration
as described in the previous sections
will run the configuration commands
even when invoking
<KBD
CLASS="USERINPUT"
>scons -c</KBD
>
to clean targets:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q -c</KBD
>
Checking for MyLibrary... ok
Removed foo.o
Removed foo
</PRE
></TD
></TR
></TABLE
><P
>&#13; Although running the platform checks
when removing targets doesn't hurt anything,
it's usually unnecessary.
You can avoid this by using the
<TT
CLASS="FUNCTION"
>GetOption</TT
>(); method to
check whether the <VAR
CLASS="OPTION"
>-c</VAR
> (clean)
option has been invoked on the command line:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
if not env.GetOption('clean'):
conf = Configure(env, custom_tests = {'CheckMyLibrary' : CheckMyLibrary})
if not conf.CheckMyLibrary():
print 'MyLibrary is not installed!'
Exit(1)
env = conf.Finish()
</PRE
></TD
></TR
></TABLE
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q -c</KBD
>
Removed foo.o
Removed foo
</PRE
></TD
></TR
></TABLE
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-CACHING"
></A
>Caching Built Files</H1
><P
>&#13; On multi-developer software projects,
you can sometimes speed up every developer's builds a lot by
allowing them to share the derived files that they build.
<TT
CLASS="APPLICATION"
>SCons</TT
> makes this easy, as well as reliable.
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2739"
>Specifying the Shared Cache Directory</A
></H2
><P
>&#13; To enable sharing of derived files,
use the <TT
CLASS="FUNCTION"
>CacheDir</TT
> function
in any <TT
CLASS="FILENAME"
>SConscript</TT
> file:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> CacheDir('/usr/local/build_cache')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Note that the directory you specify must already exist
and be readable and writable by all developers
who will be sharing derived files.
It should also be in some central location
that all builds will be able to access.
In environments where developers are using separate systems
(like individual workstations) for builds,
this directory would typically be
on a shared or NFS-mounted file system.
</P
><P
>&#13; Here's what happens:
When a build has a <TT
CLASS="FUNCTION"
>CacheDir</TT
> specified,
every time a file is built,
it is stored in the shared cache directory
along with its MD5 build signature.
On subsequent builds,
before an action is invoked to build a file,
<TT
CLASS="APPLICATION"
>SCons</TT
> will check the shared cache directory
to see if a file with the exact same build
signature already exists.
If so, the derived file will not be built locally,
but will be copied into the local build directory
from the shared cache directory,
like so:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q -c</KBD
>
Removed hello.o
Removed hello
% <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
Retrieved `hello.o' from cache
Retrieved `hello' from cache
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2753"
>Keeping Build Output Consistent</A
></H2
><P
>&#13; One potential drawback to using a shared cache
is that your build output can be inconsistent
from invocation to invocation,
because any given file may be rebuilt one time
and retrieved from the shared cache the next time.
This can make analyzing build output more difficult,
especially for automated scripts that
expect consistent output each time.
</P
><P
>&#13; If, however, you use the <TT
CLASS="LITERAL"
>--cache-show</TT
> option,
<TT
CLASS="APPLICATION"
>SCons</TT
> will print the command line that it
<I
CLASS="EMPHASIS"
>would</I
> have executed
to build the file,
even when it is retrieving the file from the shared cache.
This makes the build output consistent
every time the build is run:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q -c</KBD
>
Removed hello.o
Removed hello
% <KBD
CLASS="USERINPUT"
>scons -Q --cache-show</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; The trade-off, of course, is that you no longer
know whether or not <TT
CLASS="APPLICATION"
>SCons</TT
>
has retrieved a derived file from cache
or has rebuilt it locally.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2766"
>Not Retrieving Files From a Shared Cache</A
></H2
><P
>&#13; Retrieving an already-built file
from the shared cache
is usually a significant time-savings
over rebuilding the file,
but how much of a savings
(or even whether it saves time at all)
can depend a great deal on your
system or network configuration.
For example, retrieving cached files
from a busy server over a busy network
might end up being slower than
rebuilding the files locally.
</P
><P
>&#13; In these cases, you can specify
the <TT
CLASS="LITERAL"
>--cache-disable</TT
>
command-line option to tell <TT
CLASS="APPLICATION"
>SCons</TT
>
to not retrieve already-built files from the
shared cache directory:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q -c</KBD
>
Removed hello.o
Removed hello
% <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
Retrieved `hello.o' from cache
Retrieved `hello' from cache
% <KBD
CLASS="USERINPUT"
>scons -Q -c</KBD
>
Removed hello.o
Removed hello
% <KBD
CLASS="USERINPUT"
>scons -Q --cache-disable</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2778"
>Populating a Shared Cache With Already-Built Files</A
></H2
><P
>&#13; Sometimes, you may have one or more derived files
already built in your local build tree
that you wish to make available to other people doing builds.
For example, you may find it more effective to perform
integration builds with the cache disabled
(per the previous section)
and only populate the shared cache directory
with the built files after the integration build
has completed successfully.
This way, the cache will only get filled up
with derived files that are part of a complete, successful build
not with files that might be later overwritten
while you debug integration problems.
</P
><P
>&#13; In this case, you can use the
the <TT
CLASS="LITERAL"
>--cache-force</TT
> option
to tell <TT
CLASS="APPLICATION"
>SCons</TT
> to put all derived files in the cache,
even if the files had already been built
by a previous invocation:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q --cache-disable</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q -c</KBD
>
Removed hello.o
Removed hello
% <KBD
CLASS="USERINPUT"
>scons -Q --cache-disable</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
% <KBD
CLASS="USERINPUT"
>scons -Q --cache-force</KBD
>
scons: `.' is up to date.
% <KBD
CLASS="USERINPUT"
>scons -Q -c</KBD
>
Removed hello.o
Removed hello
% <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
Retrieved `hello.o' from cache
Retrieved `hello' from cache
</PRE
></TD
></TR
></TABLE
><P
>&#13; Notice how the above sample run
demonstrates that the <TT
CLASS="LITERAL"
>--cache-disable</TT
>
option avoids putting the built
<TT
CLASS="FILENAME"
>hello.o</TT
>
and
<TT
CLASS="FILENAME"
>hello</TT
> files in the cache,
but after using the <TT
CLASS="LITERAL"
>--cache-force</TT
> option,
the files have been put in the cache
for the next invocation to retrieve.
</P
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-ALIAS"
></A
>Alias Targets</H1
><P
>&#13; We've already seen how you can use the <TT
CLASS="FUNCTION"
>Alias</TT
>
function to create a target named <TT
CLASS="LITERAL"
>install</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
hello = env.Program('hello.c')
env.Install('/usr/bin', hello)
env.Alias('install', '/usr/bin')
</PRE
></TD
></TR
></TABLE
><P
>&#13; You can then use this alias on the command line
to tell <TT
CLASS="APPLICATION"
>SCons</TT
> more naturally that you want to install files:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q install</KBD
>
cc -c -o hello.o hello.c
cc -o hello hello.o
Install file: "hello" as "/usr/bin/hello"
</PRE
></TD
></TR
></TABLE
><P
>&#13; Like other <CODE
CLASS="CLASSNAME"
>Builder</CODE
> methods, though,
the <TT
CLASS="FUNCTION"
>Alias</TT
> method returns an object
representing the alias being built.
You can then use this object as input to anothother <CODE
CLASS="CLASSNAME"
>Builder</CODE
>.
This is especially useful if you use such an object
as input to another call to the <TT
CLASS="FUNCTION"
>Alias</TT
> <CODE
CLASS="CLASSNAME"
>Builder</CODE
>,
allowing you to create a hierarchy
of nested aliases:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env = Environment()
p = env.Program('foo.c')
l = env.Library('bar.c')
env.Install('/usr/bin', p)
env.Install('/usr/lib', l)
ib = env.Alias('install-bin', '/usr/bin')
il = env.Alias('install-lib', '/usr/lib')
env.Alias('install', [ib, il])
</PRE
></TD
></TR
></TABLE
><P
>&#13; This example defines separate <TT
CLASS="LITERAL"
>install</TT
>,
<TT
CLASS="LITERAL"
>install-bin</TT
>,
and <TT
CLASS="LITERAL"
>install-lib</TT
> aliases,
allowing you finer control over what gets installed:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q install-bin</KBD
>
cc -c -o foo.o foo.c
cc -o foo foo.o
Install file: "foo" as "/usr/bin/foo"
% <KBD
CLASS="USERINPUT"
>scons -Q install-lib</KBD
>
cc -c -o bar.o bar.c
ar r libbar.a bar.o
ranlib libbar.a
Install file: "libbar.a" as "/usr/lib/libbar.a"
% <KBD
CLASS="USERINPUT"
>scons -Q -c /</KBD
>
Removed foo.o
Removed foo
Removed /usr/bin/foo
Removed bar.o
Removed libbar.a
Removed /usr/lib/libbar.a
% <KBD
CLASS="USERINPUT"
>scons -Q install</KBD
>
cc -c -o foo.o foo.c
cc -o foo foo.o
Install file: "foo" as "/usr/bin/foo"
cc -c -o bar.o bar.c
ar r libbar.a bar.o
ranlib libbar.a
Install file: "libbar.a" as "/usr/lib/libbar.a"
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-JAVA"
></A
>Java Builds</H1
><P
>&#13; So far, we've been using examples of
building C and C++ programs
to demonstrate the features of <TT
CLASS="APPLICATION"
>SCons</TT
>.
<TT
CLASS="APPLICATION"
>SCons</TT
> also supports building Java programs,
but Java builds are handled slightly differently,
which reflects the ways in which
the Java compiler and tools
build programs differently than
other languages' tool chains.
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2827"
>Building Java Class Files: the <TT
CLASS="FUNCTION"
>Java</TT
> Builder</A
></H2
><P
>&#13; The basic activity when programming in Java,
of course, is to take one or more <TT
CLASS="FILENAME"
>.java</TT
> files
containing Java source code
and to call the Java compiler
to turn them into one or more
<TT
CLASS="FILENAME"
>.class</TT
> files.
In <TT
CLASS="APPLICATION"
>SCons</TT
>, you do this
by giving the <A
HREF="#B-JAVA"
><TT
CLASS="FUNCTION"
>Java</TT
></A
> Builder
a target directory in which
to put the <TT
CLASS="FILENAME"
>.class</TT
> files,
and a source directory that contains
the <TT
CLASS="FILENAME"
>.java</TT
> files:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Java('classes', 'src')
</PRE
></TD
></TR
></TABLE
><P
>&#13; If the <TT
CLASS="FILENAME"
>src</TT
> directory contains
three <TT
CLASS="FILENAME"
>.java</TT
> source files,
then running <TT
CLASS="APPLICATION"
>SCons</TT
> might look like this:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java
</PRE
></TD
></TR
></TABLE
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> will actually search the <TT
CLASS="FILENAME"
>src</TT
>
directory tree for all of the <TT
CLASS="FILENAME"
>.java</TT
> files.
The Java compiler will then create the
necessary class files in the <TT
CLASS="FILENAME"
>classes</TT
> subdirectory,
based on the class names found in the <TT
CLASS="FILENAME"
>.java</TT
> files.
</P
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2851"
>How <TT
CLASS="APPLICATION"
>SCons</TT
> Handles Java Dependencies</A
></H2
><P
>&#13; In addition to searching the source directory for
<TT
CLASS="FILENAME"
>.java</TT
> files,
<TT
CLASS="APPLICATION"
>SCons</TT
> actually runs the <TT
CLASS="FILENAME"
>.java</TT
> files
through a stripped-down Java parser that figures out
what classes are defined.
In other words, <TT
CLASS="APPLICATION"
>SCons</TT
> knows,
without you having to tell it,
what <TT
CLASS="FILENAME"
>.class</TT
> files
will be produced by the <TT
CLASS="APPLICATION"
>javac</TT
> call.
So our one-liner example from the preceding section:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Java('classes', 'src')
</PRE
></TD
></TR
></TABLE
><P
>&#13; Will not only tell you reliably
that the <TT
CLASS="FILENAME"
>.class</TT
> files
in the <TT
CLASS="FILENAME"
>classes</TT
> subdirectory
are up-to-date:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java
% <KBD
CLASS="USERINPUT"
>scons -Q classes</KBD
>
scons: `classes' is up to date.
</PRE
></TD
></TR
></TABLE
><P
>&#13; But it will also remove all of the generated
<TT
CLASS="FILENAME"
>.class</TT
> files,
even for inner classes,
without you having to specify them manually.
For example, if our
<TT
CLASS="FILENAME"
>Example1.java</TT
>
and
<TT
CLASS="FILENAME"
>Example3.java</TT
>
files both define additional classes,
and the class defined in <TT
CLASS="FILENAME"
>Example2.java</TT
>
has an inner class,
running <KBD
CLASS="USERINPUT"
>scons -c</KBD
>
will clean up all of those <TT
CLASS="FILENAME"
>.class</TT
> files
as well:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java
% <KBD
CLASS="USERINPUT"
>scons -Q -c classes</KBD
>
Removed classes/Example1.class
Removed classes/AdditionalClass1.class
Removed classes/Example2$Inner2.class
Removed classes/Example2.class
Removed classes/Example3.class
Removed classes/AdditionalClass3.class
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2878"
>Building Java Archive (<TT
CLASS="FILENAME"
>.jar</TT
>) Files: the <TT
CLASS="FUNCTION"
>Jar</TT
> Builder</A
></H2
><P
>&#13; After building the class files,
it's common to collect them into
a Java archive (<TT
CLASS="FILENAME"
>.jar</TT
>) file,
which you do by calling the <A
HREF="#B-JAR"
><TT
CLASS="FUNCTION"
>Jar</TT
></A
> Builder method.
If you want to just collect all of the
class files within a subdirectory,
you can just specify that subdirectory
as the <TT
CLASS="FUNCTION"
>Jar</TT
> source:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Java(target = 'classes', source = 'src')
Jar(target = 'test.jar', source = 'classes')
</PRE
></TD
></TR
></TABLE
><P
>&#13; <TT
CLASS="APPLICATION"
>SCons</TT
> will then pass that directory
to the <TT
CLASS="APPLICATION"
>jar</TT
> command,
which will collect all of the underlying
<TT
CLASS="FILENAME"
>.class</TT
> files:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java
jar cf test.jar classes
</PRE
></TD
></TR
></TABLE
><P
>&#13; If you want to keep all of the
<TT
CLASS="FILENAME"
>.class</TT
> files
for multiple programs in one location,
and only archive some of them in
each <TT
CLASS="FILENAME"
>.jar</TT
> file,
you can pass the <TT
CLASS="FUNCTION"
>Jar</TT
> builder a
list of files as its source.
It's extremely simple to create multiple
<TT
CLASS="FILENAME"
>.jar</TT
> files this way,
using the lists of target class files created
by calls to the <A
HREF="#B-JAVA"
><TT
CLASS="FUNCTION"
>Java</TT
></A
> builder
as sources to the various <TT
CLASS="FUNCTION"
>Jar</TT
> calls:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> prog1_class_files = Java(target = 'classes', source = 'prog1')
prog2_class_files = Java(target = 'classes', source = 'prog2')
Jar(target = 'prog1.jar', source = prog1_class_files)
Jar(target = 'prog2.jar', source = prog2_class_files)
</PRE
></TD
></TR
></TABLE
><P
>&#13; This will then create
<TT
CLASS="FILENAME"
>prog1.jar</TT
>
and <TT
CLASS="FILENAME"
>prog2.jar</TT
>
next to the subdirectories
that contain their <TT
CLASS="FILENAME"
>.java</TT
> files:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
javac -d classes -sourcepath prog1 prog1/Example1.java prog1/Example2.java
javac -d classes -sourcepath prog2 prog2/Example3.java prog2/Example4.java
jar cf prog1.jar classes/Example1.class classes/Example2.class
jar cf prog2.jar classes/Example3.class classes/Example4.class
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2909"
>Building C Header and Stub Files: the <TT
CLASS="FUNCTION"
>JavaH</TT
> Builder</A
></H2
><P
>&#13; You can generate C header and source files
for implementing native methods,
by using the <A
HREF="#B-JAVAH"
><TT
CLASS="FUNCTION"
>JavaH</TT
></A
> Builder.
There are several ways of using the <TT
CLASS="FUNCTION"
>JavaH</TT
> Builder.
One typical invocation might look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> classes = Java(target = 'classes', source = 'src/pkg/sub')
JavaH(target = 'native', source = classes)
</PRE
></TD
></TR
></TABLE
><P
>&#13; The source is a list of class files generated by the
call to the <A
HREF="#B-JAVA"
><TT
CLASS="FUNCTION"
>Java</TT
></A
> Builder,
and the target is the output directory in
which we want the C header files placed.
The target
gets converted into the <VAR
CLASS="OPTION"
>-d</VAR
>
when <TT
CLASS="APPLICATION"
>SCons</TT
> runs <TT
CLASS="APPLICATION"
>javah</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java
javah -d native -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3
</PRE
></TD
></TR
></TABLE
><P
>&#13; In this case,
the call to <TT
CLASS="APPLICATION"
>javah</TT
>
will generate the header files
<TT
CLASS="FILENAME"
>native/pkg_sub_Example1.h</TT
>,
<TT
CLASS="FILENAME"
>native/pkg_sub_Example2.h</TT
>
and
<TT
CLASS="FILENAME"
>native/pkg_sub_Example3.h</TT
>.
Notice that <TT
CLASS="APPLICATION"
>SCons</TT
> remembered that the class
files were generated with a target directory of
<TT
CLASS="FILENAME"
>classes</TT
>,
and that it then specified that target directory
as the <VAR
CLASS="OPTION"
>-classpath</VAR
> option
to the call to <TT
CLASS="APPLICATION"
>javah</TT
>.
</P
><P
>&#13; Although it's more convenient to use
the list of class files returned by
the <TT
CLASS="FUNCTION"
>Java</TT
> Builder
as the source of a call to the <TT
CLASS="FUNCTION"
>JavaH</TT
> Builder,
you <I
CLASS="EMPHASIS"
>can</I
>
specify the list of class files
by hand, if you prefer.
If you do,
you need to set the
<A
HREF="#CV-JAVACLASSDIR"
><VAR
CLASS="ENVAR"
>$JAVACLASSDIR</VAR
></A
> construction variable
when calling <TT
CLASS="FUNCTION"
>JavaH</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> Java(target = 'classes', source = 'src/pkg/sub')
class_file_list = ['classes/pkg/sub/Example1.class',
'classes/pkg/sub/Example2.class',
'classes/pkg/sub/Example3.class']
JavaH(target = 'native', source = class_file_list, JAVACLASSDIR = 'classes')
</PRE
></TD
></TR
></TABLE
><P
>&#13; The <VAR
CLASS="ENVAR"
>$JAVACLASSDIR</VAR
> value then
gets converted into the <VAR
CLASS="OPTION"
>-classpath</VAR
>
when <TT
CLASS="APPLICATION"
>SCons</TT
> runs <TT
CLASS="APPLICATION"
>javah</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java
javah -d native -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3
</PRE
></TD
></TR
></TABLE
><P
>&#13; Lastly, if you don't want a separate header file
generated for each source file,
you can specify an explicit File Node
as the target of the <TT
CLASS="FUNCTION"
>JavaH</TT
> Builder:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> classes = Java(target = 'classes', source = 'src/pkg/sub')
JavaH(target = File('native.h'), source = classes)
</PRE
></TD
></TR
></TABLE
><P
>&#13; Because <TT
CLASS="APPLICATION"
>SCons</TT
> assumes by default
that the target of the <TT
CLASS="FUNCTION"
>JavaH</TT
> builder is a directory,
you need to use the <TT
CLASS="FUNCTION"
>File</TT
> function
to make sure that <TT
CLASS="APPLICATION"
>SCons</TT
> doesn't
create a directory named <TT
CLASS="FILENAME"
>native.h</TT
>.
When a file is used, though,
<TT
CLASS="APPLICATION"
>SCons</TT
> correctly converts the file name
into the <TT
CLASS="APPLICATION"
>javah</TT
> <VAR
CLASS="OPTION"
>-o</VAR
> option:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java src/pkg/sub/Example3.java
javah -o native.h -classpath classes pkg.sub.Example1 pkg.sub.Example2 pkg.sub.Example3
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2963"
>Building RMI Stub and Skeleton Class Files: the <TT
CLASS="FUNCTION"
>RMIC</TT
> Builder</A
></H2
><P
>&#13; You can generate Remote Method Invocation stubs
by using the <A
HREF="#B-RMIC"
><TT
CLASS="FUNCTION"
>RMIC</TT
></A
> Builder.
The source is a list of directories,
typically returned by a call to the <A
HREF="#B-JAVA"
><TT
CLASS="FUNCTION"
>Java</TT
></A
> Builder,
and the target is an output directory
where the <TT
CLASS="FILENAME"
>_Stub.class</TT
>
and <TT
CLASS="FILENAME"
>_Skel.class</TT
> files will
be placed:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> classes = Java(target = 'classes', source = 'src/pkg/sub')
RMIC(target = 'outdir', source = classes)
</PRE
></TD
></TR
></TABLE
><P
>&#13; As it did with the <A
HREF="#B-JAVAH"
><TT
CLASS="FUNCTION"
>JavaH</TT
></A
> Builder,
<TT
CLASS="APPLICATION"
>SCons</TT
> remembers the class directory
and passes it as the <VAR
CLASS="OPTION"
>-classpath</VAR
> option
to <TT
CLASS="APPLICATION"
>rmic</TT
>:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
javac -d classes -sourcepath src/pkg/sub src/pkg/sub/Example1.java src/pkg/sub/Example2.java
rmic -d outdir -classpath classes pkg.sub.Example1 pkg.sub.Example2
</PRE
></TD
></TR
></TABLE
><P
>&#13; This example would generate the files
<TT
CLASS="FILENAME"
>outdir/pkg/sub/Example1_Skel.class</TT
>,
<TT
CLASS="FILENAME"
>outdir/pkg/sub/Example1_Stub.class</TT
>,
<TT
CLASS="FILENAME"
>outdir/pkg/sub/Example2_Skel.class</TT
> and
<TT
CLASS="FILENAME"
>outdir/pkg/sub/Example2_Stub.class</TT
>.
</P
></DIV
></DIV
><DIV
CLASS="CHAPTER"
><HR><H1
><A
NAME="CHAP-TROUBLESHOOTING"
></A
>Troubleshooting</H1
><P
>&#13; The experience of configuring any
software build tool to build a large code base
usually, at some point,
involves trying to figure out why
the tool is behaving a certain way,
and how to get it to behave the way you want.
<TT
CLASS="APPLICATION"
>SCons</TT
> is no different.
</P
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN2991"
>Why is That Target Being Rebuilt? the <TT
CLASS="LITERAL"
>--debug=explain</TT
> Option</A
></H2
><P
>&#13; Let's take a simple example of
a misconfigured build
that causes a target to be rebuilt
every time <TT
CLASS="APPLICATION"
>SCons</TT
> is run:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> # Intentionally misspell the output file name in the
# command used to create the file:
Command('file.out', 'file.in', 'cp $SOURCE file.oout')
</PRE
></TD
></TR
></TABLE
><P
>&#13; (Note to Windows users: The POSIX <TT
CLASS="APPLICATION"
>cp</TT
> command
copies the first file named on the command line
to the second file.
In our example, it copies the <TT
CLASS="FILENAME"
>file.in</TT
> file
to the <TT
CLASS="FILENAME"
>file.out</TT
> file.)
</P
><P
>&#13; Now if we run <TT
CLASS="APPLICATION"
>SCons</TT
> multiple on this example,
we see that it re-runs the <TT
CLASS="APPLICATION"
>cp</TT
>
command every time:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cp file.in file.oout
% <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cp file.in file.oout
% <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cp file.in file.oout
</PRE
></TD
></TR
></TABLE
><P
>&#13; In this example,
the underlying cause is obvious:
we've intentionally misspelled the output file name
in the <TT
CLASS="APPLICATION"
>cp</TT
> command,
so the command doesn't actually
build the <TT
CLASS="FILENAME"
>file.out</TT
> file that we've told <TT
CLASS="APPLICATION"
>SCons</TT
> to expect.
But if the problem weren't obvious,
it would be helpful
to specify the <TT
CLASS="LITERAL"
>--debug=explain</TT
> option
on the command line
to have <TT
CLASS="APPLICATION"
>SCons</TT
> tell us very specifically
why it's decided to rebuild the target:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q --debug=explain</KBD
>
scons: building `file.out' because it doesn't exist
cp file.in file.oout
</PRE
></TD
></TR
></TABLE
><P
>&#13; If this had been a more complicated example
involving a lot of build output,
having <TT
CLASS="APPLICATION"
>SCons</TT
> tell us that
it's trying to rebuild the target file
because it doesn't exist
would be an important clue
that something was wrong with
the command that we invoked to build it.
</P
><P
>&#13; The <TT
CLASS="LITERAL"
>--debug=explain</TT
> option also comes in handy
to help figure out what input file changed.
Given a simple configuration that builds
a program from three source files,
changing one of the source files
and rebuilding with the <TT
CLASS="LITERAL"
>--debug=explain</TT
>
option shows very specifically
why <TT
CLASS="APPLICATION"
>SCons</TT
> rebuilds the files that it does:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -c -o file1.o file1.c
cc -c -o file2.o file2.c
cc -c -o file3.o file3.c
cc -o prog file1.o file2.o file3.o
% <KBD
CLASS="USERINPUT"
>edit file2.c</KBD
>
[CHANGE THE CONTENTS OF file2.c]
% <KBD
CLASS="USERINPUT"
>scons -Q --debug=explain</KBD
>
scons: rebuilding `file2.o' because `file2.c' changed
cc -c -o file2.o file2.c
scons: rebuilding `prog' because `file2.o' changed
cc -o prog file1.o file2.o file3.o
</PRE
></TD
></TR
></TABLE
><P
>&#13; This becomes even more helpful
in identifying when a file is rebuilt
due to a change in an implicit dependency,
such as an incuded <TT
CLASS="FILENAME"
>.h</TT
> file.
If the <TT
CLASS="FILENAME"
>file1.c</TT
>
and <TT
CLASS="FILENAME"
>file3.c</TT
> files
in our example
both included a <TT
CLASS="FILENAME"
>hello.h</TT
> file,
then changing that included file
and re-running <TT
CLASS="APPLICATION"
>SCons</TT
> with the <TT
CLASS="LITERAL"
>--debug=explain</TT
> option
will pinpoint that it's the change to the included file
that starts the chain of rebuilds:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons -Q</KBD
>
cc -I. -c -o file1.o file1.c
cc -I. -c -o file2.o file2.c
cc -I. -c -o file3.o file3.c
cc -o prog file1.o file2.o file3.o
% <KBD
CLASS="USERINPUT"
>edit hello.h</KBD
>
[CHANGE THE CONTENTS OF hello.h]
% <KBD
CLASS="USERINPUT"
>scons -Q --debug=explain</KBD
>
scons: rebuilding `file1.o' because `hello.h' changed
cc -I. -c -o file1.o file1.c
scons: rebuilding `file3.o' because `hello.h' changed
cc -I. -c -o file3.o file3.c
scons: rebuilding `prog' because:
`file1.o' changed
`file3.o' changed
cc -o prog file1.o file2.o file3.o
</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="SECTION"
><HR><H2
CLASS="SECTION"
><A
NAME="AEN3037"
>What's in That Construction Environment? the <TT
CLASS="FUNCTION"
>Dump</TT
> Method</A
></H2
><P
>&#13; When you create a construction environment,
<TT
CLASS="APPLICATION"
>SCons</TT
> populates it
with construction variables that are set up
for various compilers, linkers and utilities
that it finds on your system.
Although this is usually helpful and what you want,
it might be frustrating if <TT
CLASS="APPLICATION"
>SCons</TT
>
doesn't set certain variables that you
expect to be sit.
In situations like this,
it's sometimes helpful to use the
construction environment <TT
CLASS="FUNCTION"
>Dump</TT
> method
to print all or some of
the construction variables.
Note that the <TT
CLASS="FUNCTION"
>Dump</TT
> method
<I
CLASS="EMPHASIS"
>returns</I
>
the representation of the variables
in the environment
for you to print (or otherwise manipulate):
</P
><P
>&#13; On a POSIX system with gcc installed,
this might generate:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
{ 'BUILDERS': {},
'CPPSUFFIXES': [ '.c',
'.C',
'.cxx',
'.cpp',
'.c++',
'.cc',
'.h',
'.H',
'.hxx',
'.hpp',
'.hh',
'.F',
'.fpp',
'.FPP',
'.S',
'.spp',
'.SPP'],
'DSUFFIXES': ['.d'],
'Dir': &#60;SCons.Defaults.Variable_Method_Caller instance at 0x829dcb4&#62;,
'ENV': {'PATH': '/usr/local/bin:/bin:/usr/bin'},
'ESCAPE': &#60;function escape at 0x837d2a4&#62;,
'File': &#60;SCons.Defaults.Variable_Method_Caller instance at 0x829e0fc&#62;,
'IDLSUFFIXES': ['.idl', '.IDL'],
'INSTALL': &#60;function copyFunc at 0x829db9c&#62;,
'LIBPREFIX': 'lib',
'LIBPREFIXES': '$LIBPREFIX',
'LIBSUFFIX': '.a',
'LIBSUFFIXES': ['$LIBSUFFIX', '$SHLIBSUFFIX'],
'OBJPREFIX': '',
'OBJSUFFIX': '.o',
'PDFPREFIX': '',
'PDFSUFFIX': '.pdf',
'PLATFORM': 'posix',
'PROGPREFIX': '',
'PROGSUFFIX': '',
'PSPAWN': &#60;function piped_env_spawn at 0x837d384&#62;,
'PSPREFIX': '',
'PSSUFFIX': '.ps',
'RDirs': &#60;SCons.Defaults.Variable_Method_Caller instance at 0x829e46c&#62;,
'SCANNERS': [],
'SHELL': 'sh',
'SHLIBPREFIX': '$LIBPREFIX',
'SHLIBSUFFIX': '.so',
'SHOBJPREFIX': '$OBJPREFIX',
'SHOBJSUFFIX': '$OBJSUFFIX',
'SPAWN': &#60;function spawnvpe_spawn at 0x8377fdc&#62;,
'TEMPFILE': &#60;class SCons.Defaults.NullCmdGenerator at 0x829ddec&#62;,
'TOOLS': [],
'_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}',
'_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET)} $)',
'_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET)} $)',
'_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}',
'__RPATH': '$_RPATH',
'_concat': &#60;function _concat at 0x829dc0c&#62;,
'_defines': &#60;function _defines at 0x829dc7c&#62;,
'_stripixes': &#60;function _stripixes at 0x829dc44&#62;}
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.
</PRE
></TD
></TR
></TABLE
><P
>&#13; On a Windows system with Visual C++
the output might look like:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
{ 'BUILDERS': {'Object': &#60;SCons.Memoize.MultiStepBuilder object at 0x83493e4&#62;, 'SharedObject': &#60;SCons.Memoize.MultiStepBuilder object at 0x8349fec&#62;, 'StaticObject': &#60;SCons.Memoize.MultiStepBuilder object at 0x83493e4&#62;, 'PCH': &#60;SCons.Memoize.BuilderBase object at 0x83418cc&#62;, 'RES': &#60;SCons.Memoize.BuilderBase object at 0x8367cec&#62;},
'CC': 'cl',
'CCCOM': &#60;SCons.Memoize.FunctionAction object at 0x8340454&#62;,
'CCCOMFLAGS': '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo$TARGET $CCPCHFLAGS $CCPDBFLAGS',
'CCFLAGS': ['/nologo'],
'CCPCHFLAGS': ['${(PCH and "/Yu%s /Fp%s"%(PCHSTOP or "",File(PCH))) or ""}'],
'CCPDBFLAGS': ['${(PDB and "/Z7") or ""}'],
'CFILESUFFIX': '.c',
'CPPDEFPREFIX': '/D',
'CPPDEFSUFFIX': '',
'CPPSUFFIXES': [ '.c',
'.C',
'.cxx',
'.cpp',
'.c++',
'.cc',
'.h',
'.H',
'.hxx',
'.hpp',
'.hh',
'.F',
'.fpp',
'.FPP',
'.S',
'.spp',
'.SPP'],
'CXX': '$CC',
'CXXCOM': '$CXX $CXXFLAGS $CCCOMFLAGS',
'CXXFILESUFFIX': '.cc',
'CXXFLAGS': ['$CCFLAGS', '$(', '/TP', '$)'],
'DSUFFIXES': ['.d'],
'Dir': &#60;SCons.Defaults.Variable_Method_Caller instance at 0x829dcb4&#62;,
'ENV': { 'INCLUDE': 'C:\\Program Files\\Microsoft Visual Studio/VC98\\include',
'LIB': 'C:\\Program Files\\Microsoft Visual Studio/VC98\\lib',
'PATH': 'C:\\Program Files\\Microsoft Visual Studio\\Common\\tools\\WIN95;C:\\Program Files\\Microsoft Visual Studio\\Common\\MSDev98\\bin;C:\\Program Files\\Microsoft Visual Studio\\Common\\tools;C:\\Program Files\\Microsoft Visual Studio/VC98\\bin',
'PATHEXT': '.COM;.EXE;.BAT;.CMD'},
'ESCAPE': &#60;function &#60;lambda&#62; at 0x82339ec&#62;,
'File': &#60;SCons.Defaults.Variable_Method_Caller instance at 0x829e0fc&#62;,
'IDLSUFFIXES': ['.idl', '.IDL'],
'INCPREFIX': '/I',
'INCSUFFIX': '',
'INSTALL': &#60;function copyFunc at 0x829db9c&#62;,
'LIBPREFIX': '',
'LIBPREFIXES': ['$LIBPREFIX'],
'LIBSUFFIX': '.lib',
'LIBSUFFIXES': ['$LIBSUFFIX'],
'MAXLINELENGTH': 2048,
'MSVS': {'VERSION': '6.0', 'VERSIONS': ['6.0']},
'MSVS_VERSION': '6.0',
'OBJPREFIX': '',
'OBJSUFFIX': '.obj',
'PCHCOM': '$CXX $CXXFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Fo${TARGETS[1]} /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS',
'PCHPDBFLAGS': ['${(PDB and "/Yd") or ""}'],
'PDFPREFIX': '',
'PDFSUFFIX': '.pdf',
'PLATFORM': 'win32',
'PROGPREFIX': '',
'PROGSUFFIX': '.exe',
'PSPAWN': &#60;function piped_spawn at 0x8372bc4&#62;,
'PSPREFIX': '',
'PSSUFFIX': '.ps',
'RC': 'rc',
'RCCOM': '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES',
'RCFLAGS': [],
'RDirs': &#60;SCons.Defaults.Variable_Method_Caller instance at 0x829e46c&#62;,
'SCANNERS': [],
'SHCC': '$CC',
'SHCCCOM': &#60;SCons.Memoize.FunctionAction object at 0x83494bc&#62;,
'SHCCFLAGS': ['$CCFLAGS'],
'SHCXX': '$CXX',
'SHCXXCOM': '$SHCXX $SHCXXFLAGS $CCCOMFLAGS',
'SHCXXFLAGS': ['$CXXFLAGS'],
'SHELL': None,
'SHLIBPREFIX': '',
'SHLIBSUFFIX': '.dll',
'SHOBJPREFIX': '$OBJPREFIX',
'SHOBJSUFFIX': '$OBJSUFFIX',
'SPAWN': &#60;function spawn at 0x8374c34&#62;,
'STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME': 1,
'TEMPFILE': &#60;class SCons.Platform.win32.TempFileMunge at 0x835edc4&#62;,
'TOOLS': ['msvc'],
'_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}',
'_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET)} $)',
'_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET)} $)',
'_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}',
'_concat': &#60;function _concat at 0x829dc0c&#62;,
'_defines': &#60;function _defines at 0x829dc7c&#62;,
'_stripixes': &#60;function _stripixes at 0x829dc44&#62;}
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.
</PRE
></TD
></TR
></TABLE
><P
>&#13; The construction environments in these examples have
actually been restricted to just gcc and Visual C++,
respectively.
In a real-life situation,
the construction environments will
likely contain a great many more variables.
</P
><P
>&#13; To make it easier to see just what you're
interested in,
the <TT
CLASS="FUNCTION"
>Dump</TT
> method allows you to
specify a specific constrcution variable
that you want to disply.
For example,
it's not unusual to want to verify
the external environment used to execute build commands,
to make sure that the PATH and other
environment variables are set up the way they should be.
You can do this as follows:
</P
><P
>&#13; Which might display the following when executed on a POSIX system:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> % <KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
{'PATH': '/usr/local/bin:/bin:/usr/bin'}
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.
</PRE
></TD
></TR
></TABLE
><P
>&#13; And the following when executed on a Windows system:
</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="SCREEN"
> C:\&#62;<KBD
CLASS="USERINPUT"
>scons</KBD
>
scons: Reading SConscript files ...
{ 'INCLUDE': 'C:\\Program Files\\Microsoft Visual Studio/VC98\\include',
'LIB': 'C:\\Program Files\\Microsoft Visual Studio/VC98\\lib',
'PATH': 'C:\\Program Files\\Microsoft Visual Studio\\Common\\tools\\WIN95;C:\\Program Files\\Microsoft Visual Studio\\Common\\MSDev98\\bin;C:\\Program Files\\Microsoft Visual Studio\\Common\\tools;C:\\Program Files\\Microsoft Visual Studio/VC98\\bin',
'PATHEXT': '.COM;.EXE;.BAT;.CMD'}
scons: done reading SConscript files.
scons: Building targets ...
scons: `.' is up to date.
scons: done building targets.
</PRE
></TD
></TR
></TABLE
></DIV
></DIV
><DIV
CLASS="APPENDIX"
><HR><H1
><A
NAME="APP-VARIABLES"
></A
>Construction Variables</H1
><P
>&#13;This appendix contains descriptions of all of the
construction variables that are <I
CLASS="EMPHASIS"
>potentially</I
>
available "out of the box" in this version of SCons.
Whether or not setting a construction variable
in a construction environment
will actually have an effect depends on
whether any of the Tools and/or Builders
that use the variable have been
included in the construction environment.&#13;</P
><P
>&#13;In this appendix, we have
appended the initial <VAR
CLASS="ENVAR"
>$</VAR
>
(dollar sign) to the beginning of each
variable name when it appears in the text,
but left off the dollar sign
in the left-hand column
where the name appears for each entry.&#13;</P
><P
></P
><DIV
CLASS="VARIABLELIST"
><DL
><DT
><A
NAME="CV-AR"
></A
><VAR
CLASS="ENVAR"
>AR</VAR
></DT
><DD
><P
>The static library archiver.</P
></DD
><DT
><A
NAME="CV-ARCOM"
></A
><VAR
CLASS="ENVAR"
>ARCOM</VAR
></DT
><DD
><P
>The command line used to generate a static library from object files.</P
></DD
><DT
><A
NAME="CV-ARCOMSTR"
></A
><VAR
CLASS="ENVAR"
>ARCOMSTR</VAR
></DT
><DD
><P
>The string displayed when an object file
is generated from an assembly-language source file.
If this is not set, then <VAR
CLASS="ENVAR"
>$ARCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(ARCOMSTR = "Archiving $TARGET")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-ARFLAGS"
></A
><VAR
CLASS="ENVAR"
>ARFLAGS</VAR
></DT
><DD
><P
>General options passed to the static library archiver.</P
></DD
><DT
><A
NAME="CV-AS"
></A
><VAR
CLASS="ENVAR"
>AS</VAR
></DT
><DD
><P
>The assembler.</P
></DD
><DT
><A
NAME="CV-ASCOM"
></A
><VAR
CLASS="ENVAR"
>ASCOM</VAR
></DT
><DD
><P
>The command line used to generate an object file
from an assembly-language source file.</P
></DD
><DT
><A
NAME="CV-ASCOMSTR"
></A
><VAR
CLASS="ENVAR"
>ASCOMSTR</VAR
></DT
><DD
><P
>The string displayed when an object file
is generated from an assembly-language source file.
If this is not set, then <VAR
CLASS="ENVAR"
>$ASCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(ASCOMSTR = "Assembling $TARGET")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-ASFLAGS"
></A
><VAR
CLASS="ENVAR"
>ASFLAGS</VAR
></DT
><DD
><P
>General options passed to the assembler.</P
></DD
><DT
><A
NAME="CV-ASPPCOM"
></A
><VAR
CLASS="ENVAR"
>ASPPCOM</VAR
></DT
><DD
><P
>The command line used to assemble an assembly-language
source file into an object file
after first running the file through the C preprocessor.
Any options specified in the <VAR
CLASS="ENVAR"
>$ASFLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$CPPFLAGS</VAR
> construction variables
are included on this command line.</P
></DD
><DT
><A
NAME="CV-ASPPCOMSTR"
></A
><VAR
CLASS="ENVAR"
>ASPPCOMSTR</VAR
></DT
><DD
><P
>The string displayed when an object file
is generated from an assembly-language source file
after first running the file through the C preprocessor.
If this is not set, then <VAR
CLASS="ENVAR"
>$ASPPCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(ASPPCOMSTR = "Assembling $TARGET")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-ASPPFLAGS"
></A
><VAR
CLASS="ENVAR"
>ASPPFLAGS</VAR
></DT
><DD
><P
>General options when an assembling an assembly-language
source file into an object file
after first running the file through the C preprocessor.
The default is to use the value of <VAR
CLASS="ENVAR"
>$ASFLAGS</VAR
>.</P
></DD
><DT
><A
NAME="CV-BIBTEX"
></A
><VAR
CLASS="ENVAR"
>BIBTEX</VAR
></DT
><DD
><P
>The bibliography generator for the TeX formatter and typesetter and the
LaTeX structured formatter and typesetter.</P
></DD
><DT
><A
NAME="CV-BIBTEXCOM"
></A
><VAR
CLASS="ENVAR"
>BIBTEXCOM</VAR
></DT
><DD
><P
>The command line used to call the bibliography generator for the
TeX formatter and typesetter and the LaTeX structured formatter and
typesetter.</P
></DD
><DT
><A
NAME="CV-BIBTEXCOMSTR"
></A
><VAR
CLASS="ENVAR"
>BIBTEXCOMSTR</VAR
></DT
><DD
><P
>The string displayed when generating a bibliography
for TeX or LaTeX.
If this is not set, then <VAR
CLASS="ENVAR"
>$BIBTEXCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(BIBTEXCOMSTR = "Generating bibliography $TARGET")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-BIBTEXFLAGS"
></A
><VAR
CLASS="ENVAR"
>BIBTEXFLAGS</VAR
></DT
><DD
><P
>General options passed to the bibliography generator for the TeX formatter
and typesetter and the LaTeX structured formatter and typesetter.</P
></DD
><DT
><A
NAME="CV-BITKEEPER"
></A
><VAR
CLASS="ENVAR"
>BITKEEPER</VAR
></DT
><DD
><P
>The BitKeeper executable.</P
></DD
><DT
><A
NAME="CV-BITKEEPERCOM"
></A
><VAR
CLASS="ENVAR"
>BITKEEPERCOM</VAR
></DT
><DD
><P
>The command line for
fetching source files using BitKEeper.</P
></DD
><DT
><A
NAME="CV-BITKEEPERCOMSTR"
></A
><VAR
CLASS="ENVAR"
>BITKEEPERCOMSTR</VAR
></DT
><DD
><P
>The string displayed when fetching
a source file using BitKeeper.
If this is not set, then <VAR
CLASS="ENVAR"
>$BITKEEPERCOM</VAR
>
(the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-BITKEEPERGET"
></A
><VAR
CLASS="ENVAR"
>BITKEEPERGET</VAR
></DT
><DD
><P
>The command (<VAR
CLASS="ENVAR"
>$BITKEEPER</VAR
>) and subcommand
for fetching source files using BitKeeper.</P
></DD
><DT
><A
NAME="CV-BITKEEPERGETFLAGS"
></A
><VAR
CLASS="ENVAR"
>BITKEEPERGETFLAGS</VAR
></DT
><DD
><P
>Options that are passed to the BitKeeper
<B
CLASS="COMMAND"
>get</B
>
subcommand.</P
></DD
><DT
><A
NAME="CV-BUILDERS"
></A
><VAR
CLASS="ENVAR"
>BUILDERS</VAR
></DT
><DD
><P
>A dictionary mapping the names of the builders
available through this environment
to underlying Builder objects.
Builders named
Alias, CFile, CXXFile, DVI, Library, Object, PDF, PostScript, and Program
are available by default.
If you initialize this variable when an
Environment is created:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(BUILDERS = {'NewBuilder' : foo})</PRE
></TD
></TR
></TABLE
><P
>the default Builders will no longer be available.
To use a new Builder object in addition to the default Builders,
add your new Builder object like this:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment()
env.Append(BUILDERS = {'NewBuilder' : foo})</PRE
></TD
></TR
></TABLE
><P
>or this:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment()
env['BUILDERS]['NewBuilder'] = foo</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-CC"
></A
><VAR
CLASS="ENVAR"
>CC</VAR
></DT
><DD
><P
>The C compiler.</P
></DD
><DT
><A
NAME="CV-CCCOM"
></A
><VAR
CLASS="ENVAR"
>CCCOM</VAR
></DT
><DD
><P
>The command line used to compile a C source file to a (static) object file.
Any options specified in the <VAR
CLASS="ENVAR"
>$CCFLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$CPPFLAGS</VAR
> construction variables
are included on this command line.</P
></DD
><DT
><A
NAME="CV-CCCOMSTR"
></A
><VAR
CLASS="ENVAR"
>CCCOMSTR</VAR
></DT
><DD
><P
>The string displayed when a C source file
is compiled to a (static) object file.
If this is not set, then <VAR
CLASS="ENVAR"
>$CCCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(CCCOMSTR = "Compiling static object $TARGET")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-CCFLAGS"
></A
><VAR
CLASS="ENVAR"
>CCFLAGS</VAR
></DT
><DD
><P
>General options that are passed to the C compiler.</P
></DD
><DT
><A
NAME="CV-CCVERSION"
></A
><VAR
CLASS="ENVAR"
>CCVERSION</VAR
></DT
><DD
><P
>The version number of the C compiler.
This may or may not be set,
depending on the specific C compiler being used.</P
></DD
><DT
><A
NAME="CV-CFILESUFFIX"
></A
><VAR
CLASS="ENVAR"
>CFILESUFFIX</VAR
></DT
><DD
><P
>The suffix for C source files.
This is used by the internal CFile builder
when generating C files from Lex (.l) or YACC (.y) input files.
The default suffix, of course, is
<TT
CLASS="FILENAME"
>.c</TT
>
(lower case).
On case-insensitive systems (like Win32),
SCons also treats
<TT
CLASS="FILENAME"
>.C</TT
>
(upper case) files
as C files.</P
></DD
><DT
><A
NAME="CV-_CONCAT"
></A
><VAR
CLASS="ENVAR"
>_concat</VAR
></DT
><DD
><P
>A function used to produce variables like <VAR
CLASS="ENVAR"
>$_CPPINCFLAGS</VAR
>. It takes
four or five
arguments: a prefix to concatenate onto each element, a list of
elements, a suffix to concatenate onto each element, an environment
for variable interpolation, and an optional function that will be
called to transform the list before concatenation.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env['_CPPINCFLAGS'] = '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs)} $)',</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-_CPPDEFFLAGS"
></A
><VAR
CLASS="ENVAR"
>_CPPDEFFLAGS</VAR
></DT
><DD
><P
>An automatically-generated construction variable
containing the C preprocessor command-line options
to define values.
The value of <VAR
CLASS="ENVAR"
>$_CPPDEFFLAGS</VAR
> is created
by appending <VAR
CLASS="ENVAR"
>$CPPDEFPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$CPPDEFSUFFIX</VAR
>
to the beginning and end
of each directory in <VAR
CLASS="ENVAR"
>$CPPDEFINES</VAR
>.</P
></DD
><DT
><A
NAME="CV-CPPDEFINES"
></A
><VAR
CLASS="ENVAR"
>CPPDEFINES</VAR
></DT
><DD
><P
>A platform independent specification of C preprocessor definitions.
The definitions will be added to command lines
through the automatically-generated
<VAR
CLASS="ENVAR"
>$_CPPDEFFLAGS</VAR
> construction variable (see below),
which is constructed according to
the type of value of <VAR
CLASS="ENVAR"
>$CPPDEFINES</VAR
>:</P
><P
>If <VAR
CLASS="ENVAR"
>$CPPDEFINES</VAR
> is a string,
the values of the
<VAR
CLASS="ENVAR"
>$CPPDEFPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$CPPDEFSUFFIX</VAR
>
construction variables
will be added to the beginning and end.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
># Will add -Dxyz to POSIX compiler command lines,
# and /Dxyz to Microsoft Visual C++ command lines.
env = Environment(CPPDEFINES='xyz')</PRE
></TD
></TR
></TABLE
><P
>If <VAR
CLASS="ENVAR"
>$CPPDEFINES</VAR
> is a list,
the values of the
<VAR
CLASS="ENVAR"
>$CPPDEFPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$CPPDEFSUFFIX</VAR
>
construction variables
will be appended to the beginning and end
of each element in the list.
If any element is a list or tuple,
then the first item is the name being
defined and the second item is its value:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
># Will add -DB=2 -DA to POSIX compiler command lines,
# and /DB=2 /DA to Microsoft Visual C++ command lines.
env = Environment(CPPDEFINES=[('B', 2), 'A'])</PRE
></TD
></TR
></TABLE
><P
>If <VAR
CLASS="ENVAR"
>$CPPDEFINES</VAR
> is a dictionary,
the values of the
<VAR
CLASS="ENVAR"
>$CPPDEFPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$CPPDEFSUFFIX</VAR
>
construction variables
will be appended to the beginning and end
of each item from the dictionary.
The key of each dictionary item
is a name being defined
to the dictionary item's corresponding value;
if the value is
<TT
CLASS="LITERAL"
>None</TT
>,
then the name is defined without an explicit value.
Note that the resulting flags are sorted by keyword
to ensure that the order of the options on the
command line is consistent each time
<TT
CLASS="APPLICATION"
>scons</TT
> is run.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
># Will add -DA -DB=2 to POSIX compiler command lines,
# and /DA /DB=2 to Microsoft Visual C++ command lines.
env = Environment(CPPDEFINES={'B':2, 'A':None})</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-CPPDEFPREFIX"
></A
><VAR
CLASS="ENVAR"
>CPPDEFPREFIX</VAR
></DT
><DD
><P
>The prefix used to specify preprocessor definitions
on the C compiler command line.
This will be appended to the beginning of each definition
in the <VAR
CLASS="ENVAR"
>$CPPDEFINES</VAR
> construction variable
when the <VAR
CLASS="ENVAR"
>$_CPPDEFFLAGS</VAR
> variable is automatically generated.</P
></DD
><DT
><A
NAME="CV-CPPDEFSUFFIX"
></A
><VAR
CLASS="ENVAR"
>CPPDEFSUFFIX</VAR
></DT
><DD
><P
>The suffix used to specify preprocessor definitions
on the C compiler command line.
This will be appended to the end of each definition
in the <VAR
CLASS="ENVAR"
>$CPPDEFINES</VAR
> construction variable
when the <VAR
CLASS="ENVAR"
>$_CPPDEFFLAGS</VAR
> variable is automatically generated.</P
></DD
><DT
><A
NAME="CV-CPPFLAGS"
></A
><VAR
CLASS="ENVAR"
>CPPFLAGS</VAR
></DT
><DD
><P
>User-specified C preprocessor options.
These will be included in any command that uses the C preprocessor,
including not just compilation of C and C++ source files
via the <VAR
CLASS="ENVAR"
>$CCCOM</VAR
>, <VAR
CLASS="ENVAR"
>$SHCCCOM</VAR
>, <VAR
CLASS="ENVAR"
>$CXXCOM</VAR
> and <VAR
CLASS="ENVAR"
>$SHCXXCOM</VAR
> command lines,
but also the <VAR
CLASS="ENVAR"
>$FORTRANPPCOM</VAR
>, <VAR
CLASS="ENVAR"
>$SHFORTRANPPCOM</VAR
>,
<VAR
CLASS="ENVAR"
>$F77PPCOM</VAR
> and <VAR
CLASS="ENVAR"
>$SHF77PPCOM</VAR
> command lines
used to compile a Fortran source file,
and the <VAR
CLASS="ENVAR"
>$ASPPCOM</VAR
> command line
used to assemble an assembly language source file,
after first running each file through the C preprocessor.
Note that this variable does
<I
CLASS="EMPHASIS"
>not</I
>
contain
<VAR
CLASS="OPTION"
>-I</VAR
>
(or similar) include search path options
that scons generates automatically from <VAR
CLASS="ENVAR"
>$CPPPATH</VAR
>.
See <A
HREF="#CV-_CPPINCFLAGS"
><VAR
CLASS="ENVAR"
>$_CPPINCFLAGS</VAR
></A
>, below,
for the variable that expands to those options.</P
></DD
><DT
><A
NAME="CV-_CPPINCFLAGS"
></A
><VAR
CLASS="ENVAR"
>_CPPINCFLAGS</VAR
></DT
><DD
><P
>An automatically-generated construction variable
containing the C preprocessor command-line options
for specifying directories to be searched for include files.
The value of <VAR
CLASS="ENVAR"
>$_CPPINCFLAGS</VAR
> is created
by appending <VAR
CLASS="ENVAR"
>$INCPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$INCSUFFIX</VAR
>
to the beginning and end
of each directory in <VAR
CLASS="ENVAR"
>$CPPPATH</VAR
>.</P
></DD
><DT
><A
NAME="CV-CPPPATH"
></A
><VAR
CLASS="ENVAR"
>CPPPATH</VAR
></DT
><DD
><P
>The list of directories that the C preprocessor will search for include
directories. The C/C++ implicit dependency scanner will search these
directories for include files. Don't explicitly put include directory
arguments in CCFLAGS or CXXFLAGS because the result will be non-portable
and the directories will not be searched by the dependency scanner. Note:
directory names in CPPPATH will be looked-up relative to the SConscript
directory when they are used in a command. To force
<TT
CLASS="APPLICATION"
>scons</TT
>
to look-up a directory relative to the root of the source tree use #:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(CPPPATH='#/include')</PRE
></TD
></TR
></TABLE
><P
>The directory look-up can also be forced using the
<TT
CLASS="FUNCTION"
>Dir</TT
>()
function:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>include = Dir('include')
env = Environment(CPPPATH=include)</PRE
></TD
></TR
></TABLE
><P
>The directory list will be added to command lines
through the automatically-generated
<VAR
CLASS="ENVAR"
>$_CPPINCFLAGS</VAR
>
construction variable,
which is constructed by
appending the values of the
<VAR
CLASS="ENVAR"
>$INCPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$INCSUFFIX</VAR
>
construction variables
to the beginning and end
of each directory in <VAR
CLASS="ENVAR"
>$CPPPATH</VAR
>.
Any command lines you define that need
the CPPPATH directory list should
include <VAR
CLASS="ENVAR"
>$_CPPINCFLAGS</VAR
>:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(CCCOM="my_compiler $_CPPINCFLAGS -c -o $TARGET $SOURCE")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-CPPSUFFIXES"
></A
><VAR
CLASS="ENVAR"
>CPPSUFFIXES</VAR
></DT
><DD
><P
>The list of suffixes of files that will be scanned
for C preprocessor implicit dependencies
(#include lines).
The default list is:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>[".c", ".C", ".cxx", ".cpp", ".c++", ".cc",
".h", ".H", ".hxx", ".hpp", ".hh",
".F", ".fpp", ".FPP",
".S", ".spp", ".SPP"]</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-CVS"
></A
><VAR
CLASS="ENVAR"
>CVS</VAR
></DT
><DD
><P
>The CVS executable.</P
></DD
><DT
><A
NAME="CV-CVSCOFLAGS"
></A
><VAR
CLASS="ENVAR"
>CVSCOFLAGS</VAR
></DT
><DD
><P
>Options that are passed to the CVS checkout subcommand.</P
></DD
><DT
><A
NAME="CV-CVSCOM"
></A
><VAR
CLASS="ENVAR"
>CVSCOM</VAR
></DT
><DD
><P
>The command line used to
fetch source files from a CVS repository.</P
></DD
><DT
><A
NAME="CV-CVSCOMSTR"
></A
><VAR
CLASS="ENVAR"
>CVSCOMSTR</VAR
></DT
><DD
><P
>The string displayed when fetching
a source file from a CVS repository.
If this is not set, then <VAR
CLASS="ENVAR"
>$CVSCOM</VAR
>
(the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-CVSFLAGS"
></A
><VAR
CLASS="ENVAR"
>CVSFLAGS</VAR
></DT
><DD
><P
>General options that are passed to CVS.
By default, this is set to
<TT
CLASS="LITERAL"
>-d $CVSREPOSITORY</TT
>
to specify from where the files must be fetched.</P
></DD
><DT
><A
NAME="CV-CVSREPOSITORY"
></A
><VAR
CLASS="ENVAR"
>CVSREPOSITORY</VAR
></DT
><DD
><P
>The path to the CVS repository.
This is referenced in the default
<VAR
CLASS="ENVAR"
>$CVSFLAGS</VAR
> value.</P
></DD
><DT
><A
NAME="CV-CXX"
></A
><VAR
CLASS="ENVAR"
>CXX</VAR
></DT
><DD
><P
>The C++ compiler.</P
></DD
><DT
><A
NAME="CV-CXXCOM"
></A
><VAR
CLASS="ENVAR"
>CXXCOM</VAR
></DT
><DD
><P
>The command line used to compile a C++ source file to an object file.
Any options specified in the <VAR
CLASS="ENVAR"
>$CXXFLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$CPPFLAGS</VAR
> construction variables
are included on this command line.</P
></DD
><DT
><A
NAME="CV-CXXCOMSTR"
></A
><VAR
CLASS="ENVAR"
>CXXCOMSTR</VAR
></DT
><DD
><P
>The string displayed when a C++ source file
is compiled to a (static) object file.
If this is not set, then <VAR
CLASS="ENVAR"
>$CXXCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(CXXCOMSTR = "Compiling static object $TARGET")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-CXXFILESUFFIX"
></A
><VAR
CLASS="ENVAR"
>CXXFILESUFFIX</VAR
></DT
><DD
><P
>The suffix for C++ source files.
This is used by the internal CXXFile builder
when generating C++ files from Lex (.ll) or YACC (.yy) input files.
The default suffix is
<TT
CLASS="FILENAME"
>.cc</TT
>.
SCons also treats files with the suffixes
<TT
CLASS="FILENAME"
>.cpp</TT
>,
<TT
CLASS="FILENAME"
>.cxx</TT
>,
<TT
CLASS="FILENAME"
>.c++</TT
>,
and
<TT
CLASS="FILENAME"
>.C++</TT
>
as C++ files.
On case-sensitive systems (Linux, UNIX, and other POSIX-alikes),
SCons also treats
<TT
CLASS="FILENAME"
>.C</TT
>
(upper case) files
as C++ files.</P
></DD
><DT
><A
NAME="CV-CXXFLAGS"
></A
><VAR
CLASS="ENVAR"
>CXXFLAGS</VAR
></DT
><DD
><P
>General options that are passed to the C++ compiler.
By default, this includes the value of <VAR
CLASS="ENVAR"
>$CCFLAGS</VAR
>,
so that setting <VAR
CLASS="ENVAR"
>$CCFLAGS</VAR
> affects both C and C++ compilation.
If you want to add C++-specific flags,
you must set or override the value of <VAR
CLASS="ENVAR"
>$CXXFLAGS</VAR
>.</P
></DD
><DT
><A
NAME="CV-CXXVERSION"
></A
><VAR
CLASS="ENVAR"
>CXXVERSION</VAR
></DT
><DD
><P
>The version number of the C++ compiler.
This may or may not be set,
depending on the specific C++ compiler being used.</P
></DD
><DT
><A
NAME="CV-DIR"
></A
><VAR
CLASS="ENVAR"
>Dir</VAR
></DT
><DD
><P
>A function that converts a file name into a Dir instance relative to the
target being built. </P
></DD
><DT
><A
NAME="CV-DIRS"
></A
><VAR
CLASS="ENVAR"
>Dirs</VAR
></DT
><DD
><P
>A function that converts a list of strings
into a list of Dir instances relative to the target being built.</P
></DD
><DT
><A
NAME="CV-DSUFFIXES"
></A
><VAR
CLASS="ENVAR"
>DSUFFIXES</VAR
></DT
><DD
><P
>The list of suffixes of files that will be scanned
for imported D package files.
The default list is:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>['.d']</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-DVIPDF"
></A
><VAR
CLASS="ENVAR"
>DVIPDF</VAR
></DT
><DD
><P
>The TeX DVI file to PDF file converter.</P
></DD
><DT
><A
NAME="CV-DVIPDFCOM"
></A
><VAR
CLASS="ENVAR"
>DVIPDFCOM</VAR
></DT
><DD
><P
>The command line used to convert TeX DVI files into a PDF file.</P
></DD
><DT
><A
NAME="CV-DVIPDFCOMSTR"
></A
><VAR
CLASS="ENVAR"
>DVIPDFCOMSTR</VAR
></DT
><DD
><P
>The string displayed when a TeX DVI file
is converted into a PDF file.
If this is not set, then <VAR
CLASS="ENVAR"
>$DVIPDFCOM</VAR
> (the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-DVIPDFFLAGS"
></A
><VAR
CLASS="ENVAR"
>DVIPDFFLAGS</VAR
></DT
><DD
><P
>General options passed to the TeX DVI file to PDF file converter.</P
></DD
><DT
><A
NAME="CV-DVIPS"
></A
><VAR
CLASS="ENVAR"
>DVIPS</VAR
></DT
><DD
><P
>The TeX DVI file to PostScript converter.</P
></DD
><DT
><A
NAME="CV-DVIPSFLAGS"
></A
><VAR
CLASS="ENVAR"
>DVIPSFLAGS</VAR
></DT
><DD
><P
>General options passed to the TeX DVI file to PostScript converter.</P
></DD
><DT
><A
NAME="CV-ENV"
></A
><VAR
CLASS="ENVAR"
>ENV</VAR
></DT
><DD
><P
>A dictionary of environment variables
to use when invoking commands. When
<VAR
CLASS="ENVAR"
>$ENV</VAR
> is used in a command all list
values will be joined using the path separator and any other non-string
values will simply be coerced to a string.
Note that, by default,
<TT
CLASS="APPLICATION"
>scons</TT
>
does
<I
CLASS="EMPHASIS"
>not</I
>
propagate the environment in force when you
execute
<TT
CLASS="APPLICATION"
>scons</TT
>
to the commands used to build target files.
This is so that builds will be guaranteed
repeatable regardless of the environment
variables set at the time
<TT
CLASS="APPLICATION"
>scons</TT
>
is invoked.</P
><P
>If you want to propagate your
environment variables
to the commands executed
to build target files,
you must do so explicitly:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>import os
env = Environment(ENV = os.environ)</PRE
></TD
></TR
></TABLE
><P
>Note that you can choose only to propagate
certain environment variables.
A common example is
the system
<VAR
CLASS="ENVAR"
>PATH</VAR
>
environment variable,
so that
<TT
CLASS="APPLICATION"
>scons</TT
>
uses the same utilities
as the invoking shell (or other process):</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>import os
env = Environment(ENV = {'PATH' : os.environ['PATH']})</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-ESCAPE"
></A
><VAR
CLASS="ENVAR"
>ESCAPE</VAR
></DT
><DD
><P
>A function that will be called to escape shell special characters in
command lines. The function should take one argument: the command line
string to escape; and should return the escaped command line.</P
></DD
><DT
><A
NAME="CV-F77"
></A
><VAR
CLASS="ENVAR"
>F77</VAR
></DT
><DD
><P
>The Fortran 77 compiler.
You should normally set the <VAR
CLASS="ENVAR"
>$FORTRAN</VAR
> variable,
which specifies the default Fortran compiler
for all Fortran versions.
You only need to set <VAR
CLASS="ENVAR"
>$F77</VAR
> if you need to use a specific compiler
or compiler version for Fortran 77 files.</P
></DD
><DT
><A
NAME="CV-F77COM"
></A
><VAR
CLASS="ENVAR"
>F77COM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran 77 source file to an object file.
You only need to set <VAR
CLASS="ENVAR"
>$F77COM</VAR
> if you need to use a specific
command line for Fortran 77 files.
You should normally set the <VAR
CLASS="ENVAR"
>$FORTRANCOM</VAR
> variable,
which specifies the default command line
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-F77COMSTR"
></A
><VAR
CLASS="ENVAR"
>F77COMSTR</VAR
></DT
><DD
><P
>The string displayed when a Fortran 77 source file
is compiled to an object file.
If this is not set, then <VAR
CLASS="ENVAR"
>$F77COM</VAR
> or <VAR
CLASS="ENVAR"
>$FORTRANCOM</VAR
>
(the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-F77FLAGS"
></A
><VAR
CLASS="ENVAR"
>F77FLAGS</VAR
></DT
><DD
><P
>General user-specified options that are passed to the Fortran 77 compiler.
Note that this variable does
<I
CLASS="EMPHASIS"
>not</I
>
contain
<VAR
CLASS="OPTION"
>-I</VAR
>
(or similar) include search path options
that scons generates automatically from <VAR
CLASS="ENVAR"
>$F77PATH</VAR
>.
See
<VAR
CLASS="ENVAR"
>$_F77INCFLAGS</VAR
>
below,
for the variable that expands to those options.
You only need to set <VAR
CLASS="ENVAR"
>$F77FLAGS</VAR
> if you need to define specific
user options for Fortran 77 files.
You should normally set the <VAR
CLASS="ENVAR"
>$FORTRANFLAGS</VAR
> variable,
which specifies the user-specified options
passed to the default Fortran compiler
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-_F77INCFLAGS"
></A
><VAR
CLASS="ENVAR"
>_F77INCFLAGS</VAR
></DT
><DD
><P
>An automatically-generated construction variable
containing the Fortran 77 compiler command-line options
for specifying directories to be searched for include files.
The value of <VAR
CLASS="ENVAR"
>$_F77INCFLAGS</VAR
> is created
by appending <VAR
CLASS="ENVAR"
>$INCPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$INCSUFFIX</VAR
>
to the beginning and end
of each directory in <VAR
CLASS="ENVAR"
>$F77PATH</VAR
>.</P
></DD
><DT
><A
NAME="CV-F77PATH"
></A
><VAR
CLASS="ENVAR"
>F77PATH</VAR
></DT
><DD
><P
>The list of directories that the Fortran 77 compiler will search for include
directories. The implicit dependency scanner will search these
directories for include files. Don't explicitly put include directory
arguments in <VAR
CLASS="ENVAR"
>$F77FLAGS</VAR
> because the result will be non-portable
and the directories will not be searched by the dependency scanner. Note:
directory names in <VAR
CLASS="ENVAR"
>$F77PATH</VAR
> will be looked-up relative to the SConscript
directory when they are used in a command. To force
<TT
CLASS="APPLICATION"
>scons</TT
>
to look-up a directory relative to the root of the source tree use #:
You only need to set <VAR
CLASS="ENVAR"
>$F77PATH</VAR
> if you need to define a specific
include path for Fortran 77 files.
You should normally set the <VAR
CLASS="ENVAR"
>$FORTRANPATH</VAR
> variable,
which specifies the include path
for the default Fortran compiler
for all Fortran versions.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(F77PATH='#/include')</PRE
></TD
></TR
></TABLE
><P
>The directory look-up can also be forced using the
<TT
CLASS="FUNCTION"
>Dir</TT
>()
function:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>include = Dir('include')
env = Environment(F77PATH=include)</PRE
></TD
></TR
></TABLE
><P
>The directory list will be added to command lines
through the automatically-generated
<VAR
CLASS="ENVAR"
>$_F77INCFLAGS</VAR
>
construction variable,
which is constructed by
appending the values of the
<VAR
CLASS="ENVAR"
>$INCPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$INCSUFFIX</VAR
>
construction variables
to the beginning and end
of each directory in <VAR
CLASS="ENVAR"
>$F77PATH</VAR
>.
Any command lines you define that need
the F77PATH directory list should
include <VAR
CLASS="ENVAR"
>$_F77INCFLAGS</VAR
>:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(F77COM="my_compiler $_F77INCFLAGS -c -o $TARGET $SOURCE")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-F77PPCOM"
></A
><VAR
CLASS="ENVAR"
>F77PPCOM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran 77 source file to an object file
after first running the file through the C preprocessor.
Any options specified in the <VAR
CLASS="ENVAR"
>$F77FLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$CPPFLAGS</VAR
> construction variables
are included on this command line.
You only need to set <VAR
CLASS="ENVAR"
>$F77PPCOM</VAR
> if you need to use a specific
C-preprocessor command line for Fortran 77 files.
You should normally set the <VAR
CLASS="ENVAR"
>$FORTRANPPCOM</VAR
> variable,
which specifies the default C-preprocessor command line
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-F90"
></A
><VAR
CLASS="ENVAR"
>F90</VAR
></DT
><DD
><P
>The Fortran 90 compiler.
You should normally set the <VAR
CLASS="ENVAR"
>$FORTRAN</VAR
> variable,
which specifies the default Fortran compiler
for all Fortran versions.
You only need to set <VAR
CLASS="ENVAR"
>$F90</VAR
> if you need to use a specific compiler
or compiler version for Fortran 90 files.</P
></DD
><DT
><A
NAME="CV-F90COM"
></A
><VAR
CLASS="ENVAR"
>F90COM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran 90 source file to an object file.
You only need to set <VAR
CLASS="ENVAR"
>$F90COM</VAR
> if you need to use a specific
command line for Fortran 90 files.
You should normally set the <VAR
CLASS="ENVAR"
>$FORTRANCOM</VAR
> variable,
which specifies the default command line
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-F90COMSTR"
></A
><VAR
CLASS="ENVAR"
>F90COMSTR</VAR
></DT
><DD
><P
>The string displayed when a Fortran 90 source file
is compiled to an object file.
If this is not set, then <VAR
CLASS="ENVAR"
>$F90COM</VAR
> or <VAR
CLASS="ENVAR"
>$FORTRANCOM</VAR
>
(the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-F90FLAGS"
></A
><VAR
CLASS="ENVAR"
>F90FLAGS</VAR
></DT
><DD
><P
>General user-specified options that are passed to the Fortran 90 compiler.
Note that this variable does
<I
CLASS="EMPHASIS"
>not</I
>
contain
<VAR
CLASS="OPTION"
>-I</VAR
>
(or similar) include search path options
that scons generates automatically from <VAR
CLASS="ENVAR"
>$F90PATH</VAR
>.
See
<VAR
CLASS="ENVAR"
>$_F90INCFLAGS</VAR
>
below,
for the variable that expands to those options.
You only need to set <VAR
CLASS="ENVAR"
>$F90FLAGS</VAR
> if you need to define specific
user options for Fortran 90 files.
You should normally set the <VAR
CLASS="ENVAR"
>$FORTRANFLAGS</VAR
> variable,
which specifies the user-specified options
passed to the default Fortran compiler
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-_F90INCFLAGS"
></A
><VAR
CLASS="ENVAR"
>_F90INCFLAGS</VAR
></DT
><DD
><P
>An automatically-generated construction variable
containing the Fortran 90 compiler command-line options
for specifying directories to be searched for include files.
The value of <VAR
CLASS="ENVAR"
>$_F90INCFLAGS</VAR
> is created
by appending <VAR
CLASS="ENVAR"
>$INCPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$INCSUFFIX</VAR
>
to the beginning and end
of each directory in <VAR
CLASS="ENVAR"
>$F90PATH</VAR
>.</P
></DD
><DT
><A
NAME="CV-F90PATH"
></A
><VAR
CLASS="ENVAR"
>F90PATH</VAR
></DT
><DD
><P
>The list of directories that the Fortran 90 compiler will search for include
directories. The implicit dependency scanner will search these
directories for include files. Don't explicitly put include directory
arguments in <VAR
CLASS="ENVAR"
>$F90FLAGS</VAR
> because the result will be non-portable
and the directories will not be searched by the dependency scanner. Note:
directory names in <VAR
CLASS="ENVAR"
>$F90PATH</VAR
> will be looked-up relative to the SConscript
directory when they are used in a command. To force
<TT
CLASS="APPLICATION"
>scons</TT
>
to look-up a directory relative to the root of the source tree use #:
You only need to set <VAR
CLASS="ENVAR"
>$F90PATH</VAR
> if you need to define a specific
include path for Fortran 90 files.
You should normally set the <VAR
CLASS="ENVAR"
>$FORTRANPATH</VAR
> variable,
which specifies the include path
for the default Fortran compiler
for all Fortran versions.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(F90PATH='#/include')</PRE
></TD
></TR
></TABLE
><P
>The directory look-up can also be forced using the
<TT
CLASS="FUNCTION"
>Dir</TT
>()
function:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>include = Dir('include')
env = Environment(F90PATH=include)</PRE
></TD
></TR
></TABLE
><P
>The directory list will be added to command lines
through the automatically-generated
<VAR
CLASS="ENVAR"
>$_F90INCFLAGS</VAR
>
construction variable,
which is constructed by
appending the values of the
<VAR
CLASS="ENVAR"
>$INCPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$INCSUFFIX</VAR
>
construction variables
to the beginning and end
of each directory in <VAR
CLASS="ENVAR"
>$F90PATH</VAR
>.
Any command lines you define that need
the F90PATH directory list should
include <VAR
CLASS="ENVAR"
>$_F90INCFLAGS</VAR
>:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(F90COM="my_compiler $_F90INCFLAGS -c -o $TARGET $SOURCE")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-F90PPCOM"
></A
><VAR
CLASS="ENVAR"
>F90PPCOM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran 90 source file to an object file
after first running the file through the C preprocessor.
Any options specified in the <VAR
CLASS="ENVAR"
>$F90FLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$CPPFLAGS</VAR
> construction variables
are included on this command line.
You only need to set <VAR
CLASS="ENVAR"
>$F90PPCOM</VAR
> if you need to use a specific
C-preprocessor command line for Fortran 90 files.
You should normally set the <VAR
CLASS="ENVAR"
>$FORTRANPPCOM</VAR
> variable,
which specifies the default C-preprocessor command line
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-F95"
></A
><VAR
CLASS="ENVAR"
>F95</VAR
></DT
><DD
><P
>The Fortran 95 compiler.
You should normally set the <VAR
CLASS="ENVAR"
>$FORTRAN</VAR
> variable,
which specifies the default Fortran compiler
for all Fortran versions.
You only need to set <VAR
CLASS="ENVAR"
>$F95</VAR
> if you need to use a specific compiler
or compiler version for Fortran 95 files.</P
></DD
><DT
><A
NAME="CV-F95COM"
></A
><VAR
CLASS="ENVAR"
>F95COM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran 95 source file to an object file.
You only need to set <VAR
CLASS="ENVAR"
>$F95COM</VAR
> if you need to use a specific
command line for Fortran 95 files.
You should normally set the <VAR
CLASS="ENVAR"
>$FORTRANCOM</VAR
> variable,
which specifies the default command line
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-F95COMSTR"
></A
><VAR
CLASS="ENVAR"
>F95COMSTR</VAR
></DT
><DD
><P
>The string displayed when a Fortran 95 source file
is compiled to an object file.
If this is not set, then <VAR
CLASS="ENVAR"
>$F95COM</VAR
> or <VAR
CLASS="ENVAR"
>$FORTRANCOM</VAR
>
(the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-F95FLAGS"
></A
><VAR
CLASS="ENVAR"
>F95FLAGS</VAR
></DT
><DD
><P
>General user-specified options that are passed to the Fortran 95 compiler.
Note that this variable does
<I
CLASS="EMPHASIS"
>not</I
>
contain
<VAR
CLASS="OPTION"
>-I</VAR
>
(or similar) include search path options
that scons generates automatically from <VAR
CLASS="ENVAR"
>$F95PATH</VAR
>.
See
<VAR
CLASS="ENVAR"
>$_F95INCFLAGS</VAR
>
below,
for the variable that expands to those options.
You only need to set <VAR
CLASS="ENVAR"
>$F95FLAGS</VAR
> if you need to define specific
user options for Fortran 95 files.
You should normally set the <VAR
CLASS="ENVAR"
>$FORTRANFLAGS</VAR
> variable,
which specifies the user-specified options
passed to the default Fortran compiler
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-_F95INCFLAGS"
></A
><VAR
CLASS="ENVAR"
>_F95INCFLAGS</VAR
></DT
><DD
><P
>An automatically-generated construction variable
containing the Fortran 95 compiler command-line options
for specifying directories to be searched for include files.
The value of <VAR
CLASS="ENVAR"
>$_F95INCFLAGS</VAR
> is created
by appending <VAR
CLASS="ENVAR"
>$INCPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$INCSUFFIX</VAR
>
to the beginning and end
of each directory in <VAR
CLASS="ENVAR"
>$F95PATH</VAR
>.</P
></DD
><DT
><A
NAME="CV-F95PATH"
></A
><VAR
CLASS="ENVAR"
>F95PATH</VAR
></DT
><DD
><P
>The list of directories that the Fortran 95 compiler will search for include
directories. The implicit dependency scanner will search these
directories for include files. Don't explicitly put include directory
arguments in <VAR
CLASS="ENVAR"
>$F95FLAGS</VAR
> because the result will be non-portable
and the directories will not be searched by the dependency scanner. Note:
directory names in <VAR
CLASS="ENVAR"
>$F95PATH</VAR
> will be looked-up relative to the SConscript
directory when they are used in a command. To force
<TT
CLASS="APPLICATION"
>scons</TT
>
to look-up a directory relative to the root of the source tree use #:
You only need to set <VAR
CLASS="ENVAR"
>$F95PATH</VAR
> if you need to define a specific
include path for Fortran 95 files.
You should normally set the <VAR
CLASS="ENVAR"
>$FORTRANPATH</VAR
> variable,
which specifies the include path
for the default Fortran compiler
for all Fortran versions.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(F95PATH='#/include')</PRE
></TD
></TR
></TABLE
><P
>The directory look-up can also be forced using the
<TT
CLASS="FUNCTION"
>Dir</TT
>()
function:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>include = Dir('include')
env = Environment(F95PATH=include)</PRE
></TD
></TR
></TABLE
><P
>The directory list will be added to command lines
through the automatically-generated
<VAR
CLASS="ENVAR"
>$_F95INCFLAGS</VAR
>
construction variable,
which is constructed by
appending the values of the
<VAR
CLASS="ENVAR"
>$INCPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$INCSUFFIX</VAR
>
construction variables
to the beginning and end
of each directory in <VAR
CLASS="ENVAR"
>$F95PATH</VAR
>.
Any command lines you define that need
the F95PATH directory list should
include <VAR
CLASS="ENVAR"
>$_F95INCFLAGS</VAR
>:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(F95COM="my_compiler $_F95INCFLAGS -c -o $TARGET $SOURCE")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-F95PPCOM"
></A
><VAR
CLASS="ENVAR"
>F95PPCOM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran 95 source file to an object file
after first running the file through the C preprocessor.
Any options specified in the <VAR
CLASS="ENVAR"
>$F95FLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$CPPFLAGS</VAR
> construction variables
are included on this command line.
You only need to set <VAR
CLASS="ENVAR"
>$F95PPCOM</VAR
> if you need to use a specific
C-preprocessor command line for Fortran 95 files.
You should normally set the <VAR
CLASS="ENVAR"
>$FORTRANPPCOM</VAR
> variable,
which specifies the default C-preprocessor command line
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-FILE"
></A
><VAR
CLASS="ENVAR"
>File</VAR
></DT
><DD
><P
>A function that converts a file name into a File instance relative to the
target being built. </P
></DD
><DT
><A
NAME="CV-FORTRAN"
></A
><VAR
CLASS="ENVAR"
>FORTRAN</VAR
></DT
><DD
><P
>The default Fortran compiler
for all versions of Fortran.</P
></DD
><DT
><A
NAME="CV-FORTRANCOM"
></A
><VAR
CLASS="ENVAR"
>FORTRANCOM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran source file to an object file.
By default, any options specified
in the <VAR
CLASS="ENVAR"
>$FORTRANFLAGS</VAR
>, <VAR
CLASS="ENVAR"
>$CPPFLAGS</VAR
>, <VAR
CLASS="ENVAR"
>$_CPPDEFFLAGS</VAR
>,
<VAR
CLASS="ENVAR"
>$_FORTRANMODFLAG</VAR
>, and <VAR
CLASS="ENVAR"
>$_FORTRANINCFLAGS</VAR
> construction variables
are included on this command line.</P
></DD
><DT
><A
NAME="CV-FORTRANCOMSTR"
></A
><VAR
CLASS="ENVAR"
>FORTRANCOMSTR</VAR
></DT
><DD
><P
>The string displayed when a Fortran source file
is compiled to an object file.
If this is not set, then <VAR
CLASS="ENVAR"
>$FORTRANCOM</VAR
>
(the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-FORTRANFLAGS"
></A
><VAR
CLASS="ENVAR"
>FORTRANFLAGS</VAR
></DT
><DD
><P
>General user-specified options that are passed to the Fortran compiler.
Note that this variable does
<I
CLASS="EMPHASIS"
>not</I
>
contain
<VAR
CLASS="OPTION"
>-I</VAR
>
(or similar) include or module search path options
that scons generates automatically from <VAR
CLASS="ENVAR"
>$FORTRANPATH</VAR
>.
See
<VAR
CLASS="ENVAR"
>$_FORTRANINCFLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$_FORTRANMODFLAG</VAR
>,
below,
for the variables that expand those options.</P
></DD
><DT
><A
NAME="CV-_FORTRANINCFLAGS"
></A
><VAR
CLASS="ENVAR"
>_FORTRANINCFLAGS</VAR
></DT
><DD
><P
>An automatically-generated construction variable
containing the Fortran compiler command-line options
for specifying directories to be searched for include
files and module files.
The value of <VAR
CLASS="ENVAR"
>$_FORTRANINCFLAGS</VAR
> is created
by prepending/appending <VAR
CLASS="ENVAR"
>$INCPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$INCSUFFIX</VAR
>
to the beginning and end
of each directory in <VAR
CLASS="ENVAR"
>$FORTRANPATH</VAR
>.</P
></DD
><DT
><A
NAME="CV-FORTRANMODDIR"
></A
><VAR
CLASS="ENVAR"
>FORTRANMODDIR</VAR
></DT
><DD
><P
>Directory location where the Fortran compiler should place
any module files it generates. This variable is empty, by default. Some
Fortran compilers will internally append this directory in the search path
for module files, as well.</P
></DD
><DT
><A
NAME="CV-FORTRANMODDIRPREFIX"
></A
><VAR
CLASS="ENVAR"
>FORTRANMODDIRPREFIX</VAR
></DT
><DD
><P
>The prefix used to specify a module directory on the Fortran compiler command
line.
This will be appended to the beginning of the directory
in the <VAR
CLASS="ENVAR"
>$FORTRANMODDIR</VAR
> construction variables
when the <VAR
CLASS="ENVAR"
>$_FORTRANMODFLAG</VAR
> variables is automatically generated.</P
></DD
><DT
><A
NAME="CV-FORTRANMODDIRSUFFIX"
></A
><VAR
CLASS="ENVAR"
>FORTRANMODDIRSUFFIX</VAR
></DT
><DD
><P
>The suffix used to specify a module directory on the Fortran compiler command
line.
This will be appended to the beginning of the directory
in the <VAR
CLASS="ENVAR"
>$FORTRANMODDIR</VAR
> construction variables
when the <VAR
CLASS="ENVAR"
>$_FORTRANMODFLAG</VAR
> variables is automatically generated.</P
></DD
><DT
><A
NAME="CV-_FORTRANMODFLAG"
></A
><VAR
CLASS="ENVAR"
>_FORTRANMODFLAG</VAR
></DT
><DD
><P
>An automatically-generated construction variable
containing the Fortran compiler command-line option
for specifying the directory location where the Fortran
compiler should place any module files that happen to get
generated during compilation.
The value of <VAR
CLASS="ENVAR"
>$_FORTRANMODFLAG</VAR
> is created
by prepending/appending <VAR
CLASS="ENVAR"
>$FORTRANMODDIRPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$FORTRANMODDIRSUFFIX</VAR
>
to the beginning and end of the directory in <VAR
CLASS="ENVAR"
>$FORTRANMODDIR</VAR
>.</P
></DD
><DT
><A
NAME="CV-FORTRANMODPREFIX"
></A
><VAR
CLASS="ENVAR"
>FORTRANMODPREFIX</VAR
></DT
><DD
><P
>The module file prefix used by the Fortran compiler. SCons assumes that
the Fortran compiler follows the quasi-standard naming convention for
module files of
<TT
CLASS="FILENAME"
>module_name.mod</TT
>.
As a result, this variable is left empty, by default. For situations in
which the compiler does not necessarily follow the normal convention,
the user may use this variable. Its value will be appended to every
module file name as scons attempts to resolve dependencies.</P
></DD
><DT
><A
NAME="CV-FORTRANMODSUFFIX"
></A
><VAR
CLASS="ENVAR"
>FORTRANMODSUFFIX</VAR
></DT
><DD
><P
>The module file suffix used by the Fortran compiler. SCons assumes that
the Fortran compiler follows the quasi-standard naming convention for
module files of
<TT
CLASS="FILENAME"
>module_name.mod</TT
>.
As a result, this variable is set to ".mod", by default. For situations
in which the compiler does not necessarily follow the normal convention,
the user may use this variable. Its value will be appended to every
module file name as scons attempts to resolve dependencies.</P
></DD
><DT
><A
NAME="CV-FORTRANPATH"
></A
><VAR
CLASS="ENVAR"
>FORTRANPATH</VAR
></DT
><DD
><P
>The list of directories that the Fortran compiler will search for
include files and (for some compilers) module files. The Fortran implicit
dependency scanner will search these directories for include files (but
not module files since they are autogenerated and, as such, may not
actually exist at the time the scan takes place). Don't explicitly put
include directory arguments in FORTRANFLAGS because the result will be
non-portable and the directories will not be searched by the dependency
scanner. Note: directory names in FORTRANPATH will be looked-up relative
to the SConscript directory when they are used in a command. To force
<TT
CLASS="APPLICATION"
>scons</TT
>
to look-up a directory relative to the root of the source tree use #:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(FORTRANPATH='#/include')</PRE
></TD
></TR
></TABLE
><P
>The directory look-up can also be forced using the
<TT
CLASS="FUNCTION"
>Dir</TT
>()
function:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>include = Dir('include')
env = Environment(FORTRANPATH=include)</PRE
></TD
></TR
></TABLE
><P
>The directory list will be added to command lines
through the automatically-generated
<VAR
CLASS="ENVAR"
>$_FORTRANINCFLAGS</VAR
>
construction variable,
which is constructed by
appending the values of the
<VAR
CLASS="ENVAR"
>$INCPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$INCSUFFIX</VAR
>
construction variables
to the beginning and end
of each directory in <VAR
CLASS="ENVAR"
>$FORTRANPATH</VAR
>.
Any command lines you define that need
the FORTRANPATH directory list should
include <VAR
CLASS="ENVAR"
>$_FORTRANINCFLAGS</VAR
>:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(FORTRANCOM="my_compiler $_FORTRANINCFLAGS -c -o $TARGET $SOURCE")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-FORTRANPPCOM"
></A
><VAR
CLASS="ENVAR"
>FORTRANPPCOM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran source file to an object file
after first running the file through the C preprocessor.
By default, any options specified in the <VAR
CLASS="ENVAR"
>$FORTRANFLAGS</VAR
>, <VAR
CLASS="ENVAR"
>$CPPFLAGS</VAR
>,
_CPPDEFFLAGS, <VAR
CLASS="ENVAR"
>$_FORTRANMODFLAG</VAR
>, and <VAR
CLASS="ENVAR"
>$_FORTRANINCFLAGS</VAR
>
construction variables are included on this command line.</P
></DD
><DT
><A
NAME="CV-FORTRANSUFFIXES"
></A
><VAR
CLASS="ENVAR"
>FORTRANSUFFIXES</VAR
></DT
><DD
><P
>The list of suffixes of files that will be scanned
for Fortran implicit dependencies
(INCLUDE lines and USE statements).
The default list is:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>[".f", ".F", ".for", ".FOR", ".ftn", ".FTN", ".fpp", ".FPP",
".f77", ".F77", ".f90", ".F90", ".f95", ".F95"]</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-FRAMEWORKPATH"
></A
><VAR
CLASS="ENVAR"
>FRAMEWORKPATH</VAR
></DT
><DD
><P
>On Mac OS X with gcc,
a list containing the paths to search for frameworks.
Used by the compiler to find framework-style includes like
#include &#60;Fmwk/Header.h&#62;.
Used by the linker to find user-specified frameworks when linking (see
<VAR
CLASS="ENVAR"
>$FRAMEWORKS</VAR
>).
For example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env.AppendUnique(FRAMEWORKPATH='#myframeworkdir')</PRE
></TD
></TR
></TABLE
><P
>will add</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> ... -Fmyframeworkdir</PRE
></TD
></TR
></TABLE
><P
>to the compiler and linker command lines.</P
></DD
><DT
><A
NAME="CV-_FRAMEWORKPATH"
></A
><VAR
CLASS="ENVAR"
>_FRAMEWORKPATH</VAR
></DT
><DD
><P
>On Mac OS X with gcc, an automatically-generated construction variable
containing the linker command-line options corresponding to
<VAR
CLASS="ENVAR"
>$FRAMEWORKPATH</VAR
>.</P
></DD
><DT
><A
NAME="CV-FRAMEWORKPATHPREFIX"
></A
><VAR
CLASS="ENVAR"
>FRAMEWORKPATHPREFIX</VAR
></DT
><DD
><P
>On Mac OS X with gcc, the prefix to be used for the FRAMEWORKPATH entries.
(see <VAR
CLASS="ENVAR"
>$FRAMEWORKPATH</VAR
>).
The default value is
<VAR
CLASS="OPTION"
>-F</VAR
>.</P
></DD
><DT
><A
NAME="CV-FRAMEWORKPREFIX"
></A
><VAR
CLASS="ENVAR"
>FRAMEWORKPREFIX</VAR
></DT
><DD
><P
>On Mac OS X with gcc,
the prefix to be used for linking in frameworks
(see <VAR
CLASS="ENVAR"
>$FRAMEWORKS</VAR
>).
The default value is
<VAR
CLASS="OPTION"
>-framework</VAR
>.</P
></DD
><DT
><A
NAME="CV-FRAMEWORKS"
></A
><VAR
CLASS="ENVAR"
>FRAMEWORKS</VAR
></DT
><DD
><P
>On Mac OS X with gcc, a list of the framework names to be linked into a
program or shared library or bundle.
The default value is the empty list.
For example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> env.AppendUnique(FRAMEWORKS=Split('System Cocoa SystemConfiguration'))</PRE
></TD
></TR
></TABLE
><P
></P
></DD
><DT
><A
NAME="CV-_FRAMEWORKS"
></A
><VAR
CLASS="ENVAR"
>_FRAMEWORKS</VAR
></DT
><DD
><P
>On Mac OS X with gcc,
an automatically-generated construction variable
containing the linker command-line options
for linking with FRAMEWORKS.</P
></DD
><DT
><A
NAME="CV-FRAMEWORKSFLAGS"
></A
><VAR
CLASS="ENVAR"
>FRAMEWORKSFLAGS</VAR
></DT
><DD
><P
>On Mac OS X with gcc,
general user-supplied frameworks options to be added at
the end of a command
line building a loadable module.
(This has been largely superceded by
the <VAR
CLASS="ENVAR"
>$FRAMEWORKPATH</VAR
>, <VAR
CLASS="ENVAR"
>$FRAMEWORKPATHPREFIX</VAR
>,
<VAR
CLASS="ENVAR"
>$FRAMEWORKPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$FRAMEWORKS</VAR
> variables
described above.)</P
></DD
><DT
><A
NAME="CV-GS"
></A
><VAR
CLASS="ENVAR"
>GS</VAR
></DT
><DD
><P
>The Ghostscript program used to convert PostScript to PDF files.</P
></DD
><DT
><A
NAME="CV-GSCOM"
></A
><VAR
CLASS="ENVAR"
>GSCOM</VAR
></DT
><DD
><P
>The Ghostscript command line used to convert PostScript to PDF files.</P
></DD
><DT
><A
NAME="CV-GSCOMSTR"
></A
><VAR
CLASS="ENVAR"
>GSCOMSTR</VAR
></DT
><DD
><P
>The string displayed when
Ghostscript is used to convert
a PostScript file to a PDF file.
If this is not set, then <VAR
CLASS="ENVAR"
>$GSCOM</VAR
> (the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-GSFLAGS"
></A
><VAR
CLASS="ENVAR"
>GSFLAGS</VAR
></DT
><DD
><P
>General options passed to the Ghostscript program
when converting PostScript to PDF files.</P
></DD
><DT
><A
NAME="CV-IDLSUFFIXES"
></A
><VAR
CLASS="ENVAR"
>IDLSUFFIXES</VAR
></DT
><DD
><P
>The list of suffixes of files that will be scanned
for IDL implicit dependencies
(#include or import lines).
The default list is:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>[".idl", ".IDL"]</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-INCPREFIX"
></A
><VAR
CLASS="ENVAR"
>INCPREFIX</VAR
></DT
><DD
><P
>The prefix used to specify an include directory on the C compiler command
line.
This will be appended to the beginning of each directory
in the <VAR
CLASS="ENVAR"
>$CPPPATH</VAR
> and <VAR
CLASS="ENVAR"
>$FORTRANPATH</VAR
> construction variables
when the <VAR
CLASS="ENVAR"
>$_CPPINCFLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$_FORTRANINCFLAGS</VAR
>
variables are automatically generated.</P
></DD
><DT
><A
NAME="CV-INCSUFFIX"
></A
><VAR
CLASS="ENVAR"
>INCSUFFIX</VAR
></DT
><DD
><P
>The suffix used to specify an include directory on the C compiler command
line.
This will be appended to the end of each directory
in the <VAR
CLASS="ENVAR"
>$CPPPATH</VAR
> and <VAR
CLASS="ENVAR"
>$FORTRANPATH</VAR
> construction variables
when the <VAR
CLASS="ENVAR"
>$_CPPINCFLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$_FORTRANINCFLAGS</VAR
>
variables are automatically generated.</P
></DD
><DT
><A
NAME="CV-INSTALL"
></A
><VAR
CLASS="ENVAR"
>INSTALL</VAR
></DT
><DD
><P
>A function to be called to install a file into a
destination file name.
The default function copies the file into the destination
(and sets the destination file's mode and permission bits
to match the source file's).
The function takes the following arguments:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>def install(dest, source, env):</PRE
></TD
></TR
></TABLE
><P
><VAR
CLASS="VARNAME"
>dest</VAR
>
is the path name of the destination file.
<VAR
CLASS="VARNAME"
>source</VAR
>
is the path name of the source file.
<VAR
CLASS="VARNAME"
>env</VAR
>
is the construction environment
(a dictionary of construction values)
in force for this file installation.</P
></DD
><DT
><A
NAME="CV-INTEL_C_COMPILER_VERSION"
></A
><VAR
CLASS="ENVAR"
>INTEL_C_COMPILER_VERSION</VAR
></DT
><DD
><P
>Set by the "intelc" Tool
to the major version number of the Intel C compiler
selected for use.</P
></DD
><DT
><A
NAME="CV-JAR"
></A
><VAR
CLASS="ENVAR"
>JAR</VAR
></DT
><DD
><P
>The Java archive tool.</P
></DD
><DT
><A
NAME="CV-JARCHDIR"
></A
><VAR
CLASS="ENVAR"
>JARCHDIR</VAR
></DT
><DD
><P
>The directory to which the Java archive tool should change
(using the
<VAR
CLASS="OPTION"
>-C</VAR
>
option).</P
></DD
><DT
><A
NAME="CV-JARCOM"
></A
><VAR
CLASS="ENVAR"
>JARCOM</VAR
></DT
><DD
><P
>The command line used to call the Java archive tool.</P
></DD
><DT
><A
NAME="CV-JARCOMSTR"
></A
><VAR
CLASS="ENVAR"
>JARCOMSTR</VAR
></DT
><DD
><P
>The string displayed when the Java archive tool
is called
If this is not set, then <VAR
CLASS="ENVAR"
>$JARCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(JARCOMSTR = "JARchiving $SOURCES into $TARGET")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-JARFLAGS"
></A
><VAR
CLASS="ENVAR"
>JARFLAGS</VAR
></DT
><DD
><P
>General options passed to the Java archive tool.
By default this is set to
<VAR
CLASS="OPTION"
>cf</VAR
>
to create the necessary
<B
CLASS="COMMAND"
>jar</B
>
file.</P
></DD
><DT
><A
NAME="CV-JARSUFFIX"
></A
><VAR
CLASS="ENVAR"
>JARSUFFIX</VAR
></DT
><DD
><P
>The suffix for Java archives:
<TT
CLASS="FILENAME"
>.jar</TT
>
by default.</P
></DD
><DT
><A
NAME="CV-JAVAC"
></A
><VAR
CLASS="ENVAR"
>JAVAC</VAR
></DT
><DD
><P
>The Java compiler.</P
></DD
><DT
><A
NAME="CV-JAVACCOM"
></A
><VAR
CLASS="ENVAR"
>JAVACCOM</VAR
></DT
><DD
><P
>The command line used to compile a directory tree containing
Java source files to
corresponding Java class files.
Any options specified in the <VAR
CLASS="ENVAR"
>$JAVACFLAGS</VAR
> construction variable
are included on this command line.</P
></DD
><DT
><A
NAME="CV-JAVACCOMSTR"
></A
><VAR
CLASS="ENVAR"
>JAVACCOMSTR</VAR
></DT
><DD
><P
>The string displayed when compiling
a directory tree of Java source files to
corresponding Java class files.
If this is not set, then <VAR
CLASS="ENVAR"
>$JAVACCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-JAVACFLAGS"
></A
><VAR
CLASS="ENVAR"
>JAVACFLAGS</VAR
></DT
><DD
><P
>General options that are passed to the Java compiler.</P
></DD
><DT
><A
NAME="CV-JAVACLASSDIR"
></A
><VAR
CLASS="ENVAR"
>JAVACLASSDIR</VAR
></DT
><DD
><P
>The directory in which Java class files may be found.
This is stripped from the beginning of any Java .class
file names supplied to the
<TT
CLASS="LITERAL"
>JavaH</TT
>
builder.</P
></DD
><DT
><A
NAME="CV-JAVACLASSSUFFIX"
></A
><VAR
CLASS="ENVAR"
>JAVACLASSSUFFIX</VAR
></DT
><DD
><P
>The suffix for Java class files;
<TT
CLASS="FILENAME"
>.class</TT
>
by default.</P
></DD
><DT
><A
NAME="CV-JAVAH"
></A
><VAR
CLASS="ENVAR"
>JAVAH</VAR
></DT
><DD
><P
>The Java generator for C header and stub files.</P
></DD
><DT
><A
NAME="CV-JAVAHCOM"
></A
><VAR
CLASS="ENVAR"
>JAVAHCOM</VAR
></DT
><DD
><P
>The command line used to generate C header and stub files
from Java classes.
Any options specified in the <VAR
CLASS="ENVAR"
>$JAVAHFLAGS</VAR
> construction variable
are included on this command line.</P
></DD
><DT
><A
NAME="CV-JAVAHCOMSTR"
></A
><VAR
CLASS="ENVAR"
>JAVAHCOMSTR</VAR
></DT
><DD
><P
>The string displayed when C header and stub files
are generated from Java classes.
If this is not set, then <VAR
CLASS="ENVAR"
>$JAVAHCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(JAVAHCOMSTR = "Generating header/stub file(s) $TARGETS from $SOURCES")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-JAVAHFLAGS"
></A
><VAR
CLASS="ENVAR"
>JAVAHFLAGS</VAR
></DT
><DD
><P
>General options passed to the C header and stub file generator
for Java classes.</P
></DD
><DT
><A
NAME="CV-JAVASUFFIX"
></A
><VAR
CLASS="ENVAR"
>JAVASUFFIX</VAR
></DT
><DD
><P
>The suffix for Java files;
<TT
CLASS="FILENAME"
>.java</TT
>
by default.</P
></DD
><DT
><A
NAME="CV-LATEX"
></A
><VAR
CLASS="ENVAR"
>LATEX</VAR
></DT
><DD
><P
>The LaTeX structured formatter and typesetter.</P
></DD
><DT
><A
NAME="CV-LATEXCOM"
></A
><VAR
CLASS="ENVAR"
>LATEXCOM</VAR
></DT
><DD
><P
>The command line used to call the LaTeX structured formatter and typesetter.</P
></DD
><DT
><A
NAME="CV-LATEXCOMSTR"
></A
><VAR
CLASS="ENVAR"
>LATEXCOMSTR</VAR
></DT
><DD
><P
>The string displayed when calling
the LaTeX structured formatter and typesetter.
If this is not set, then <VAR
CLASS="ENVAR"
>$LATEXCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(LATEXCOMSTR = "Building $TARGET from LaTeX input $SOURCES")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-LATEXFLAGS"
></A
><VAR
CLASS="ENVAR"
>LATEXFLAGS</VAR
></DT
><DD
><P
>General options passed to the LaTeX structured formatter and typesetter.</P
></DD
><DT
><A
NAME="CV-LDMODULE"
></A
><VAR
CLASS="ENVAR"
>LDMODULE</VAR
></DT
><DD
><P
>The linker for building loadable modules.
By default, this is the same as <VAR
CLASS="ENVAR"
>$SHLINK</VAR
>.</P
></DD
><DT
><A
NAME="CV-LDMODULECOM"
></A
><VAR
CLASS="ENVAR"
>LDMODULECOM</VAR
></DT
><DD
><P
>The command line for building loadable modules.
On Mac OS X, this uses the <VAR
CLASS="ENVAR"
>$LDMODULE</VAR
>,
<VAR
CLASS="ENVAR"
>$LDMODULEFLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$FRAMEWORKSFLAGS</VAR
> variables.
On other systems, this is the same as <VAR
CLASS="ENVAR"
>$SHLINK</VAR
>.</P
></DD
><DT
><A
NAME="CV-LDMODULECOMSTR"
></A
><VAR
CLASS="ENVAR"
>LDMODULECOMSTR</VAR
></DT
><DD
><P
>The string displayed when building loadable modules.
If this is not set, then <VAR
CLASS="ENVAR"
>$LDMODULECOM</VAR
> (the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-LDMODULEFLAGS"
></A
><VAR
CLASS="ENVAR"
>LDMODULEFLAGS</VAR
></DT
><DD
><P
>General user options passed to the linker for building loadable modules.</P
></DD
><DT
><A
NAME="CV-LDMODULEPREFIX"
></A
><VAR
CLASS="ENVAR"
>LDMODULEPREFIX</VAR
></DT
><DD
><P
>The prefix used for loadable module file names.
On Mac OS X, this is null;
on other systems, this is
the same as <VAR
CLASS="ENVAR"
>$SHLIBPREFIX</VAR
>.</P
></DD
><DT
><A
NAME="CV-LDMODULESUFFIX"
></A
><VAR
CLASS="ENVAR"
>LDMODULESUFFIX</VAR
></DT
><DD
><P
>The suffix used for loadable module file names.
On Mac OS X, this is null;
on other systems, this is
the same as $SHLIBSUFFIX.</P
></DD
><DT
><A
NAME="CV-LEX"
></A
><VAR
CLASS="ENVAR"
>LEX</VAR
></DT
><DD
><P
>The lexical analyzer generator.</P
></DD
><DT
><A
NAME="CV-LEXCOM"
></A
><VAR
CLASS="ENVAR"
>LEXCOM</VAR
></DT
><DD
><P
>The command line used to call the lexical analyzer generator
to generate a source file.</P
></DD
><DT
><A
NAME="CV-LEXCOMSTR"
></A
><VAR
CLASS="ENVAR"
>LEXCOMSTR</VAR
></DT
><DD
><P
>The string displayed when generating a source file
using the lexical analyzer generator.
If this is not set, then <VAR
CLASS="ENVAR"
>$LEXCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(LEXCOMSTR = "Lex'ing $TARGET from $SOURCES")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-LEXFLAGS"
></A
><VAR
CLASS="ENVAR"
>LEXFLAGS</VAR
></DT
><DD
><P
>General options passed to the lexical analyzer generator.</P
></DD
><DT
><A
NAME="CV-_LIBDIRFLAGS"
></A
><VAR
CLASS="ENVAR"
>_LIBDIRFLAGS</VAR
></DT
><DD
><P
>An automatically-generated construction variable
containing the linker command-line options
for specifying directories to be searched for library.
The value of <VAR
CLASS="ENVAR"
>$_LIBDIRFLAGS</VAR
> is created
by appending <VAR
CLASS="ENVAR"
>$LIBDIRPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$LIBDIRSUFFIX</VAR
>
to the beginning and end
of each directory in <VAR
CLASS="ENVAR"
>$LIBPATH</VAR
>.</P
></DD
><DT
><A
NAME="CV-LIBDIRPREFIX"
></A
><VAR
CLASS="ENVAR"
>LIBDIRPREFIX</VAR
></DT
><DD
><P
>The prefix used to specify a library directory on the linker command line.
This will be appended to the beginning of each directory
in the <VAR
CLASS="ENVAR"
>$LIBPATH</VAR
> construction variable
when the <VAR
CLASS="ENVAR"
>$_LIBDIRFLAGS</VAR
> variable is automatically generated.</P
></DD
><DT
><A
NAME="CV-LIBDIRSUFFIX"
></A
><VAR
CLASS="ENVAR"
>LIBDIRSUFFIX</VAR
></DT
><DD
><P
>The suffix used to specify a library directory on the linker command line.
This will be appended to the end of each directory
in the <VAR
CLASS="ENVAR"
>$LIBPATH</VAR
> construction variable
when the <VAR
CLASS="ENVAR"
>$_LIBDIRFLAGS</VAR
> variable is automatically generated.</P
></DD
><DT
><A
NAME="CV-_LIBFLAGS"
></A
><VAR
CLASS="ENVAR"
>_LIBFLAGS</VAR
></DT
><DD
><P
>An automatically-generated construction variable
containing the linker command-line options
for specifying libraries to be linked with the resulting target.
The value of <VAR
CLASS="ENVAR"
>$_LIBFLAGS</VAR
> is created
by appending <VAR
CLASS="ENVAR"
>$LIBLINKPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$LIBLINKSUFFIX</VAR
>
to the beginning and end
of each filename in <VAR
CLASS="ENVAR"
>$LIBS</VAR
>.</P
></DD
><DT
><A
NAME="CV-LIBLINKPREFIX"
></A
><VAR
CLASS="ENVAR"
>LIBLINKPREFIX</VAR
></DT
><DD
><P
>The prefix used to specify a library to link on the linker command line.
This will be appended to the beginning of each library
in the <VAR
CLASS="ENVAR"
>$LIBS</VAR
> construction variable
when the <VAR
CLASS="ENVAR"
>$_LIBFLAGS</VAR
> variable is automatically generated.</P
></DD
><DT
><A
NAME="CV-LIBLINKSUFFIX"
></A
><VAR
CLASS="ENVAR"
>LIBLINKSUFFIX</VAR
></DT
><DD
><P
>The suffix used to specify a library to link on the linker command line.
This will be appended to the end of each library
in the <VAR
CLASS="ENVAR"
>$LIBS</VAR
> construction variable
when the <VAR
CLASS="ENVAR"
>$_LIBFLAGS</VAR
> variable is automatically generated.</P
></DD
><DT
><A
NAME="CV-LIBPATH"
></A
><VAR
CLASS="ENVAR"
>LIBPATH</VAR
></DT
><DD
><P
>The list of directories that will be searched for libraries.
The implicit dependency scanner will search these
directories for include files. Don't explicitly put include directory
arguments in <VAR
CLASS="ENVAR"
>$LINKFLAGS</VAR
> or <VAR
CLASS="ENVAR"
>$SHLINKFLAGS</VAR
>
because the result will be non-portable
and the directories will not be searched by the dependency scanner. Note:
directory names in LIBPATH will be looked-up relative to the SConscript
directory when they are used in a command. To force
<TT
CLASS="APPLICATION"
>scons</TT
>
to look-up a directory relative to the root of the source tree use #:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(LIBPATH='#/libs')</PRE
></TD
></TR
></TABLE
><P
>The directory look-up can also be forced using the
<TT
CLASS="FUNCTION"
>Dir</TT
>()
function:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>libs = Dir('libs')
env = Environment(LIBPATH=libs)</PRE
></TD
></TR
></TABLE
><P
>The directory list will be added to command lines
through the automatically-generated
<VAR
CLASS="ENVAR"
>$_LIBDIRFLAGS</VAR
>
construction variable,
which is constructed by
appending the values of the
<VAR
CLASS="ENVAR"
>$LIBDIRPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$LIBDIRSUFFIX</VAR
>
construction variables
to the beginning and end
of each directory in <VAR
CLASS="ENVAR"
>$LIBPATH</VAR
>.
Any command lines you define that need
the LIBPATH directory list should
include <VAR
CLASS="ENVAR"
>$_LIBDIRFLAGS</VAR
>:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(LINKCOM="my_linker $_LIBDIRFLAGS $_LIBFLAGS -o $TARGET $SOURCE")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-LIBPREFIX"
></A
><VAR
CLASS="ENVAR"
>LIBPREFIX</VAR
></DT
><DD
><P
>The prefix used for (static) library file names.
A default value is set for each platform
(posix, win32, os2, etc.),
but the value is overridden by individual tools
(ar, mslib, sgiar, sunar, tlib, etc.)
to reflect the names of the libraries they create.</P
></DD
><DT
><A
NAME="CV-LIBPREFIXES"
></A
><VAR
CLASS="ENVAR"
>LIBPREFIXES</VAR
></DT
><DD
><P
>An array of legal prefixes for library file names.</P
></DD
><DT
><A
NAME="CV-LIBS"
></A
><VAR
CLASS="ENVAR"
>LIBS</VAR
></DT
><DD
><P
>A list of one or more libraries
that will be linked with
any executable programs
created by this environment.</P
><P
>The library list will be added to command lines
through the automatically-generated
<VAR
CLASS="ENVAR"
>$_LIBFLAGS</VAR
>
construction variable,
which is constructed by
appending the values of the
<VAR
CLASS="ENVAR"
>$LIBLINKPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$LIBLINKSUFFIX</VAR
>
construction variables
to the beginning and end
of each filename in <VAR
CLASS="ENVAR"
>$LIBS</VAR
>.
Any command lines you define that need
the LIBS library list should
include <VAR
CLASS="ENVAR"
>$_LIBFLAGS</VAR
>:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(LINKCOM="my_linker $_LIBDIRFLAGS $_LIBFLAGS -o $TARGET $SOURCE")</PRE
></TD
></TR
></TABLE
><P
>If you add a
File
object to the
<VAR
CLASS="ENVAR"
>$LIBS</VAR
>
list, the name of that file will be added to
<VAR
CLASS="ENVAR"
>$_LIBFLAGS</VAR
>,
and thus the link line, as is, without
<VAR
CLASS="ENVAR"
>$LIBLINKPREFIX</VAR
>
or
<VAR
CLASS="ENVAR"
>$LIBLINKSUFFIX</VAR
>.
For example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.Append(LIBS=File('/tmp/mylib.so'))</PRE
></TD
></TR
></TABLE
><P
>In all cases, scons will add dependencies from the executable program to
all the libraries in this list.</P
></DD
><DT
><A
NAME="CV-LIBSUFFIX"
></A
><VAR
CLASS="ENVAR"
>LIBSUFFIX</VAR
></DT
><DD
><P
>The suffix used for (static) library file names.
A default value is set for each platform
(posix, win32, os2, etc.),
but the value is overridden by individual tools
(ar, mslib, sgiar, sunar, tlib, etc.)
to reflect the names of the libraries they create.</P
></DD
><DT
><A
NAME="CV-LIBSUFFIXES"
></A
><VAR
CLASS="ENVAR"
>LIBSUFFIXES</VAR
></DT
><DD
><P
>An array of legal suffixes for library file names.</P
></DD
><DT
><A
NAME="CV-LINK"
></A
><VAR
CLASS="ENVAR"
>LINK</VAR
></DT
><DD
><P
>The linker.</P
></DD
><DT
><A
NAME="CV-LINKCOM"
></A
><VAR
CLASS="ENVAR"
>LINKCOM</VAR
></DT
><DD
><P
>The command line used to link object files into an executable.</P
></DD
><DT
><A
NAME="CV-LINKCOMSTR"
></A
><VAR
CLASS="ENVAR"
>LINKCOMSTR</VAR
></DT
><DD
><P
>The string displayed when object files
are linked into an executable.
If this is not set, then <VAR
CLASS="ENVAR"
>$LINKCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(LINKCOMSTR = "Linking $TARGET")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-LINKFLAGS"
></A
><VAR
CLASS="ENVAR"
>LINKFLAGS</VAR
></DT
><DD
><P
>General user options passed to the linker.
Note that this variable should
<I
CLASS="EMPHASIS"
>not</I
>
contain
<VAR
CLASS="OPTION"
>-l</VAR
>
(or similar) options for linking with the libraries listed in <VAR
CLASS="ENVAR"
>$LIBS</VAR
>,
nor
<VAR
CLASS="OPTION"
>-L</VAR
>
(or similar) library search path options
that scons generates automatically from <VAR
CLASS="ENVAR"
>$LIBPATH</VAR
>.
See
<VAR
CLASS="ENVAR"
>$_LIBFLAGS</VAR
>
above,
for the variable that expands to library-link options,
and
<VAR
CLASS="ENVAR"
>$_LIBDIRFLAGS</VAR
>
above,
for the variable that expands to library search path options.</P
></DD
><DT
><A
NAME="CV-M4"
></A
><VAR
CLASS="ENVAR"
>M4</VAR
></DT
><DD
><P
>The M4 macro preprocessor.</P
></DD
><DT
><A
NAME="CV-M4COM"
></A
><VAR
CLASS="ENVAR"
>M4COM</VAR
></DT
><DD
><P
>The command line used to pass files through the M4 macro preprocessor.</P
></DD
><DT
><A
NAME="CV-M4COMSTR"
></A
><VAR
CLASS="ENVAR"
>M4COMSTR</VAR
></DT
><DD
><P
>The string displayed when
a file is passed through the M4 macro preprocessor.
If this is not set, then <VAR
CLASS="ENVAR"
>$M4COM</VAR
> (the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-M4FLAGS"
></A
><VAR
CLASS="ENVAR"
>M4FLAGS</VAR
></DT
><DD
><P
>General options passed to the M4 macro preprocessor.</P
></DD
><DT
><A
NAME="CV-MAXLINELENGTH"
></A
><VAR
CLASS="ENVAR"
>MAXLINELENGTH</VAR
></DT
><DD
><P
>The maximum number of characters allowed on an external command line.
On Win32 systems,
link lines longer than this many characters
are linked via a temporary file name.</P
></DD
><DT
><A
NAME="CV-MSVS"
></A
><VAR
CLASS="ENVAR"
>MSVS</VAR
></DT
><DD
><P
>When the Microsoft Visual Studio tools are initialized, they set up
this dictionary with the following keys:</P
><P
><VAR
CLASS="ENVAR"
>VERSION</VAR
>
the version of MSVS being used (can be set via
MSVS_VERSION)</P
><P
><VAR
CLASS="ENVAR"
>VERSIONS</VAR
>
the available versions of MSVS installed</P
><P
><VAR
CLASS="ENVAR"
>VCINSTALLDIR</VAR
>
installed directory of Visual C++</P
><P
><VAR
CLASS="ENVAR"
>VSINSTALLDIR</VAR
>
installed directory of Visual Studio</P
><P
><VAR
CLASS="ENVAR"
>FRAMEWORKDIR</VAR
>
installed directory of the .NET framework</P
><P
><VAR
CLASS="ENVAR"
>FRAMEWORKVERSIONS</VAR
>
list of installed versions of the .NET framework, sorted latest to oldest.</P
><P
><VAR
CLASS="ENVAR"
>FRAMEWORKVERSION</VAR
>
latest installed version of the .NET framework</P
><P
><VAR
CLASS="ENVAR"
>FRAMEWORKSDKDIR</VAR
>
installed location of the .NET SDK.</P
><P
><VAR
CLASS="ENVAR"
>PLATFORMSDKDIR</VAR
>
installed location of the Platform SDK.</P
><P
><VAR
CLASS="ENVAR"
>PLATFORMSDK_MODULES</VAR
>
dictionary of installed Platform SDK modules,
where the dictionary keys are keywords for the various modules, and
the values are 2-tuples where the first is the release date, and the
second is the version number.</P
><P
>If a value isn't set, it wasn't available in the registry.</P
></DD
><DT
><A
NAME="CV-MSVS_IGNORE_IDE_PATHS"
></A
><VAR
CLASS="ENVAR"
>MSVS_IGNORE_IDE_PATHS</VAR
></DT
><DD
><P
>Tells the MS Visual Studio tools to use minimal INCLUDE, LIB, and PATH settings,
instead of the settings from the IDE.</P
><P
>For Visual Studio, SCons will (by default) automatically determine
where MSVS is installed, and use the LIB, INCLUDE, and PATH variables
set by the IDE. You can override this behavior by setting these
variables after Environment initialization, or by setting
<VAR
CLASS="ENVAR"
>MSVS_IGNORE_IDE_PATHS = 1</VAR
>
in the Environment initialization.
Specifying this will not leave these unset, but will set them to a
minimal set of paths needed to run the tools successfully.</P
><P
>For VS6, the mininimal set is:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> INCLUDE:'VSDir\VC98\ATL\include;VSDir\VC98\MFC\include;VSDir\VC98\include'
LIB:'VSDir\VC98\MFC\lib;VSDir\VC98\lib'
PATH:'VSDir\Common\MSDev98\bin;VSDir\VC98\bin'</PRE
></TD
></TR
></TABLE
><P
>For VS7, it is:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> INCLUDE:'VSDir\Vc7\atlmfc\include;VSDir\Vc7\include'
LIB:'VSDir\Vc7\atlmfc\lib;VSDir\Vc7\lib'
PATH:'VSDir\Common7\Tools\bin;VSDir\Common7\Tools;VSDir\Vc7\bin'</PRE
></TD
></TR
></TABLE
><P
>Where 'VSDir' is the installed location of Visual Studio.</P
></DD
><DT
><A
NAME="CV-MSVS_USE_MFC_DIRS"
></A
><VAR
CLASS="ENVAR"
>MSVS_USE_MFC_DIRS</VAR
></DT
><DD
><P
>Tells the MS Visual Studio tool(s) to use
the MFC directories in its default paths
for compiling and linking.
Under MSVS version 6,
setting
<VAR
CLASS="ENVAR"
>MSVS_USE_MFC_DIRS</VAR
>
to a non-zero value
adds the
<TT
CLASS="FILENAME"
>ATL\include</TT
>
and
<TT
CLASS="FILENAME"
>MFC\include</TT
>
directories to
the default
<VAR
CLASS="ENVAR"
>INCLUDE</VAR
>
external environment variable,
and adds the
<VAR
CLASS="ENVAR"
>MFC\lib</VAR
>
directory to
the default
<VAR
CLASS="ENVAR"
>LIB</VAR
>
external environment variable.
Under MSVS version 7,
setting
<VAR
CLASS="ENVAR"
>MSVS_USE_MFC_DIRS</VAR
>
to a non-zero value
adds the
<VAR
CLASS="ENVAR"
>atlmfc\include</VAR
>
directory to the default
<VAR
CLASS="ENVAR"
>INCLUDE</VAR
>
external environment variable,
and adds the
<VAR
CLASS="ENVAR"
>atlmfc\lib</VAR
>
directory to the default
<VAR
CLASS="ENVAR"
>LIB</VAR
>
external environment variable.
The current default value is
<TT
CLASS="LITERAL"
>1</TT
>
which means these directories
are added to the paths by default.
This default value is likely to change
in a future release,
so users who want the ATL and MFC
values included in their paths
are encouraged to enable the
<VAR
CLASS="ENVAR"
>MSVS_USE_MFC_DIRS</VAR
>
value explicitly
to avoid future incompatibility.
This variable has no effect if the
<VAR
CLASS="ENVAR"
>INCLUDE</VAR
>
or
<VAR
CLASS="ENVAR"
>LIB</VAR
>
environment variables are set explictly.</P
></DD
><DT
><A
NAME="CV-MSVS_VERSION"
></A
><VAR
CLASS="ENVAR"
>MSVS_VERSION</VAR
></DT
><DD
><P
>Sets the preferred version of MSVS to use.</P
><P
>SCons will (by default) select the latest version of MSVS
installed on your machine. So, if you have version 6 and version 7
(MSVS .NET) installed, it will prefer version 7. You can override this by
specifying the
<VAR
CLASS="ENVAR"
>MSVS_VERSION</VAR
>
variable in the Environment initialization, setting it to the
appropriate version ('6.0' or '7.0', for example).
If the given version isn't installed, tool initialization will fail.</P
></DD
><DT
><A
NAME="CV-MSVSPROJECTCOM"
></A
><VAR
CLASS="ENVAR"
>MSVSPROJECTCOM</VAR
></DT
><DD
><P
>The action used to generate Microsoft Visual Studio
project and solution files.</P
></DD
><DT
><A
NAME="CV-MSVSPROJECTSUFFIX"
></A
><VAR
CLASS="ENVAR"
>MSVSPROJECTSUFFIX</VAR
></DT
><DD
><P
>The suffix used for Microsoft Visual Studio project (DSP) files.
The default value is
<TT
CLASS="FILENAME"
>.vcproj</TT
>
when using Visual Studio version 7.x (.NET),
and
<TT
CLASS="FILENAME"
>.dsp</TT
>
when using earlier versions of Visual Studio.</P
></DD
><DT
><A
NAME="CV-MSVSSOLUTIONSUFFIX"
></A
><VAR
CLASS="ENVAR"
>MSVSSOLUTIONSUFFIX</VAR
></DT
><DD
><P
>The suffix used for Microsoft Visual Studio solution (DSW) files.
The default value is
<TT
CLASS="FILENAME"
>.sln</TT
>
when using Visual Studio version 7.x (.NET),
and
<TT
CLASS="FILENAME"
>.dsw</TT
>
when using earlier versions of Visual Studio.</P
></DD
><DT
><A
NAME="CV-MWCW_VERSION"
></A
><VAR
CLASS="ENVAR"
>MWCW_VERSION</VAR
></DT
><DD
><P
>The version number of the MetroWerks CodeWarrior C compiler
to be used.</P
></DD
><DT
><A
NAME="CV-MWCW_VERSIONS"
></A
><VAR
CLASS="ENVAR"
>MWCW_VERSIONS</VAR
></DT
><DD
><P
>A list of installed versions of the MetroWerks CodeWarrior C compiler
on this system.</P
></DD
><DT
><A
NAME="CV-NO_IMPORT_LIB"
></A
><VAR
CLASS="ENVAR"
>no_import_lib</VAR
></DT
><DD
><P
>When set to non-zero,
suppresses creation of a corresponding Win32 static import lib by the
<TT
CLASS="LITERAL"
>SharedLibrary</TT
>
builder when used with
MinGW, Microsoft Visual Studio or Metrowerks.
This also suppresses creation
of an export (.exp) file
when using Microsoft Visual Studio.</P
></DD
><DT
><A
NAME="CV-OBJPREFIX"
></A
><VAR
CLASS="ENVAR"
>OBJPREFIX</VAR
></DT
><DD
><P
>The prefix used for (static) object file names.</P
></DD
><DT
><A
NAME="CV-OBJSUFFIX"
></A
><VAR
CLASS="ENVAR"
>OBJSUFFIX</VAR
></DT
><DD
><P
>The suffix used for (static) object file names.</P
></DD
><DT
><A
NAME="CV-P4"
></A
><VAR
CLASS="ENVAR"
>P4</VAR
></DT
><DD
><P
>The Perforce executable.</P
></DD
><DT
><A
NAME="CV-P4COM"
></A
><VAR
CLASS="ENVAR"
>P4COM</VAR
></DT
><DD
><P
>The command line used to
fetch source files from Perforce.</P
></DD
><DT
><A
NAME="CV-P4COMSTR"
></A
><VAR
CLASS="ENVAR"
>P4COMSTR</VAR
></DT
><DD
><P
>The string displayed when
fetching a source file from Perforce.
If this is not set, then <VAR
CLASS="ENVAR"
>$P4COM</VAR
> (the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-P4FLAGS"
></A
><VAR
CLASS="ENVAR"
>P4FLAGS</VAR
></DT
><DD
><P
>General options that are passed to Perforce.</P
></DD
><DT
><A
NAME="CV-PCH"
></A
><VAR
CLASS="ENVAR"
>PCH</VAR
></DT
><DD
><P
>The Microsoft Visual C++ precompiled header that will be used when compiling
object files. This variable is ignored by tools other than Microsoft Visual C++.
When this variable is
defined SCons will add options to the compiler command line to
cause it to use the precompiled header, and will also set up the
dependencies for the PCH file. Example: </P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env['PCH'] = 'StdAfx.pch'</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-PCHCOM"
></A
><VAR
CLASS="ENVAR"
>PCHCOM</VAR
></DT
><DD
><P
>The command line used by the
<TT
CLASS="FUNCTION"
>PCH</TT
>
builder to generated a precompiled header.</P
></DD
><DT
><A
NAME="CV-PCHCOMSTR"
></A
><VAR
CLASS="ENVAR"
>PCHCOMSTR</VAR
></DT
><DD
><P
>The string displayed when generating a precompiled header.
If this is not set, then <VAR
CLASS="ENVAR"
>$PCHCOM</VAR
> (the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-PCHSTOP"
></A
><VAR
CLASS="ENVAR"
>PCHSTOP</VAR
></DT
><DD
><P
>This variable specifies how much of a source file is precompiled. This
variable is ignored by tools other than Microsoft Visual C++, or when
the PCH variable is not being used. When this variable is define it
must be a string that is the name of the header that
is included at the end of the precompiled portion of the source files, or
the empty string if the "#pragma hrdstop" construct is being used:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env['PCHSTOP'] = 'StdAfx.h'</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-PDB"
></A
><VAR
CLASS="ENVAR"
>PDB</VAR
></DT
><DD
><P
>The Microsoft Visual C++ PDB file that will store debugging information for
object files, shared libraries, and programs. This variable is ignored by
tools other than Microsoft Visual C++.
When this variable is
defined SCons will add options to the compiler and linker command line to
cause them to generate external debugging information, and will also set up the
dependencies for the PDB file. Example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env['PDB'] = 'hello.pdb'</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-PDFCOM"
></A
><VAR
CLASS="ENVAR"
>PDFCOM</VAR
></DT
><DD
><P
>A deprecated synonym for <VAR
CLASS="ENVAR"
>$DVIPDFCOM</VAR
>.</P
></DD
><DT
><A
NAME="CV-PDFPREFIX"
></A
><VAR
CLASS="ENVAR"
>PDFPREFIX</VAR
></DT
><DD
><P
>The prefix used for PDF file names.</P
></DD
><DT
><A
NAME="CV-PDFSUFFIX"
></A
><VAR
CLASS="ENVAR"
>PDFSUFFIX</VAR
></DT
><DD
><P
>The suffix used for PDF file names.</P
></DD
><DT
><A
NAME="CV-PLATFORM"
></A
><VAR
CLASS="ENVAR"
>PLATFORM</VAR
></DT
><DD
><P
>The name of the platform used to create the Environment. If no platform is
specified when the Environment is created,
<TT
CLASS="APPLICATION"
>scons</TT
>
autodetects the platform.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(tools = [])
if env['PLATFORM'] == 'cygwin':
Tool('mingw')(env)
else:
Tool('msvc')(env)</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-PRINT_CMD_LINE_FUNC"
></A
><VAR
CLASS="ENVAR"
>PRINT_CMD_LINE_FUNC</VAR
></DT
><DD
><P
>A Python function used to print the command lines as they are executed
(assuming command printing is not disabled by the
<VAR
CLASS="OPTION"
>-q</VAR
>
or
<VAR
CLASS="OPTION"
>-s</VAR
>
options or their equivalents).
The function should take four arguments:
<VAR
CLASS="VARNAME"
>s</VAR
>,
the command being executed (a string),
<VAR
CLASS="VARNAME"
>target</VAR
>,
the target being built (file node, list, or string name(s)),
<VAR
CLASS="VARNAME"
>source</VAR
>,
the source(s) used (file node, list, or string name(s)), and
<VAR
CLASS="VARNAME"
>env</VAR
>,
the environment being used.</P
><P
>The function must do the printing itself. The default implementation,
used if this variable is not set or is None, is:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>def print_cmd_line(s, target, source, env):
sys.stdout.write(s + "\n")</PRE
></TD
></TR
></TABLE
><P
>Here's an example of a more interesting function:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>def print_cmd_line(s, target, source, env):
sys.stdout.write("Building %s -&#62; %s...\n" %
(' and '.join([str(x) for x in source]),
' and '.join([str(x) for x in target])))
env=Environment(PRINT_CMD_LINE_FUNC=print_cmd_line)
env.Program('foo', 'foo.c')</PRE
></TD
></TR
></TABLE
><P
>This just prints "Building <VAR
CLASS="VARNAME"
>targetname</VAR
> from <VAR
CLASS="VARNAME"
>sourcename</VAR
>..." instead
of the actual commands.
Such a function could also log the actual commands to a log file,
for example.</P
></DD
><DT
><A
NAME="CV-PROGPREFIX"
></A
><VAR
CLASS="ENVAR"
>PROGPREFIX</VAR
></DT
><DD
><P
>The prefix used for executable file names.</P
></DD
><DT
><A
NAME="CV-PROGSUFFIX"
></A
><VAR
CLASS="ENVAR"
>PROGSUFFIX</VAR
></DT
><DD
><P
>The suffix used for executable file names.</P
></DD
><DT
><A
NAME="CV-PSCOM"
></A
><VAR
CLASS="ENVAR"
>PSCOM</VAR
></DT
><DD
><P
>The command line used to convert TeX DVI files into a PostScript file.</P
></DD
><DT
><A
NAME="CV-PSCOMSTR"
></A
><VAR
CLASS="ENVAR"
>PSCOMSTR</VAR
></DT
><DD
><P
>The string displayed when a TeX DVI file
is converted into a PostScript file.
If this is not set, then <VAR
CLASS="ENVAR"
>$PSCOM</VAR
> (the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-PSPREFIX"
></A
><VAR
CLASS="ENVAR"
>PSPREFIX</VAR
></DT
><DD
><P
>The prefix used for PostScript file names.</P
></DD
><DT
><A
NAME="CV-PSSUFFIX"
></A
><VAR
CLASS="ENVAR"
>PSSUFFIX</VAR
></DT
><DD
><P
>The prefix used for PostScript file names.</P
></DD
><DT
><A
NAME="CV-QT_AUTOSCAN"
></A
><VAR
CLASS="ENVAR"
>QT_AUTOSCAN</VAR
></DT
><DD
><P
>Turn off scanning for mocable files. Use the Moc Builder to explicitely
specify files to run moc on.</P
></DD
><DT
><A
NAME="CV-QT_BINPATH"
></A
><VAR
CLASS="ENVAR"
>QT_BINPATH</VAR
></DT
><DD
><P
>The path where the qt binaries are installed.
The default value is '<VAR
CLASS="ENVAR"
>$QTDIR</VAR
>/bin'.</P
></DD
><DT
><A
NAME="CV-QT_CPPPATH"
></A
><VAR
CLASS="ENVAR"
>QT_CPPPATH</VAR
></DT
><DD
><P
>The path where the qt header files are installed.
The default value is '<VAR
CLASS="ENVAR"
>$QTDIR</VAR
>/include'.
Note: If you set this variable to None, the tool won't change the <VAR
CLASS="ENVAR"
>$CPPPATH</VAR
>
construction variable.</P
></DD
><DT
><A
NAME="CV-QT_DEBUG"
></A
><VAR
CLASS="ENVAR"
>QT_DEBUG</VAR
></DT
><DD
><P
>Prints lots of debugging information while scanning for moc files.</P
></DD
><DT
><A
NAME="CV-QT_LIB"
></A
><VAR
CLASS="ENVAR"
>QT_LIB</VAR
></DT
><DD
><P
>Default value is 'qt'. You may want to set this to 'qt-mt'. Note: If you set
this variable to None, the tool won't change the <VAR
CLASS="ENVAR"
>$LIBS</VAR
> variable.</P
></DD
><DT
><A
NAME="CV-QT_LIBPATH"
></A
><VAR
CLASS="ENVAR"
>QT_LIBPATH</VAR
></DT
><DD
><P
>The path where the qt libraries are installed.
The default value is '<VAR
CLASS="ENVAR"
>$QTDIR</VAR
>/lib'.
Note: If you set this variable to None, the tool won't change the <VAR
CLASS="ENVAR"
>$LIBPATH</VAR
>
construction variable.</P
></DD
><DT
><A
NAME="CV-QT_MOC"
></A
><VAR
CLASS="ENVAR"
>QT_MOC</VAR
></DT
><DD
><P
>Default value is '<VAR
CLASS="ENVAR"
>$QT_BINPATH</VAR
>/bin/moc'.</P
></DD
><DT
><A
NAME="CV-QT_MOCCXXPREFIX"
></A
><VAR
CLASS="ENVAR"
>QT_MOCCXXPREFIX</VAR
></DT
><DD
><P
>Default value is ''. Prefix for moc output files, when source is a cxx file.</P
></DD
><DT
><A
NAME="CV-QT_MOCCXXSUFFIX"
></A
><VAR
CLASS="ENVAR"
>QT_MOCCXXSUFFIX</VAR
></DT
><DD
><P
>Default value is '.moc'. Suffix for moc output files, when source is a cxx
file.</P
></DD
><DT
><A
NAME="CV-QT_MOCFROMCPPFLAGS"
></A
><VAR
CLASS="ENVAR"
>QT_MOCFROMCPPFLAGS</VAR
></DT
><DD
><P
>Default value is '-i'. These flags are passed to moc, when moccing a
cpp file.</P
></DD
><DT
><A
NAME="CV-QT_MOCFROMCXXCOM"
></A
><VAR
CLASS="ENVAR"
>QT_MOCFROMCXXCOM</VAR
></DT
><DD
><P
>Command to generate a moc file from a cpp file.</P
></DD
><DT
><A
NAME="CV-QT_MOCFROMCXXCOMSTR"
></A
><VAR
CLASS="ENVAR"
>QT_MOCFROMCXXCOMSTR</VAR
></DT
><DD
><P
>The string displayed when generating a moc file from a cpp file.
If this is not set, then <VAR
CLASS="ENVAR"
>$QT_MOCFROMCXXCOM</VAR
> (the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-QT_MOCFROMHCOM"
></A
><VAR
CLASS="ENVAR"
>QT_MOCFROMHCOM</VAR
></DT
><DD
><P
>Command to generate a moc file from a header.</P
></DD
><DT
><A
NAME="CV-QT_MOCFROMHCOMSTR"
></A
><VAR
CLASS="ENVAR"
>QT_MOCFROMHCOMSTR</VAR
></DT
><DD
><P
>The string displayed when generating a moc file from a cpp file.
If this is not set, then <VAR
CLASS="ENVAR"
>$QT_MOCFROMHCOM</VAR
> (the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-QT_MOCFROMHFLAGS"
></A
><VAR
CLASS="ENVAR"
>QT_MOCFROMHFLAGS</VAR
></DT
><DD
><P
>Default value is ''. These flags are passed to moc, when moccing a header
file.</P
></DD
><DT
><A
NAME="CV-QT_MOCHPREFIX"
></A
><VAR
CLASS="ENVAR"
>QT_MOCHPREFIX</VAR
></DT
><DD
><P
>Default value is 'moc_'. Prefix for moc output files, when source is a header.</P
></DD
><DT
><A
NAME="CV-QT_MOCHSUFFIX"
></A
><VAR
CLASS="ENVAR"
>QT_MOCHSUFFIX</VAR
></DT
><DD
><P
>Default value is '<VAR
CLASS="ENVAR"
>$CXXFILESUFFIX</VAR
>'. Suffix for moc output files, when source is
a header.</P
></DD
><DT
><A
NAME="CV-QT_UIC"
></A
><VAR
CLASS="ENVAR"
>QT_UIC</VAR
></DT
><DD
><P
>Default value is '<VAR
CLASS="ENVAR"
>$QT_BINPATH</VAR
>/uic'.</P
></DD
><DT
><A
NAME="CV-QT_UICCOM"
></A
><VAR
CLASS="ENVAR"
>QT_UICCOM</VAR
></DT
><DD
><P
>Command to generate header files from .ui files.</P
></DD
><DT
><A
NAME="CV-QT_UICCOMSTR"
></A
><VAR
CLASS="ENVAR"
>QT_UICCOMSTR</VAR
></DT
><DD
><P
>The string displayed when generating header files from .ui files.
If this is not set, then <VAR
CLASS="ENVAR"
>$QT_UICCOM</VAR
> (the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-QT_UICDECLFLAGS"
></A
><VAR
CLASS="ENVAR"
>QT_UICDECLFLAGS</VAR
></DT
><DD
><P
>Default value is ''. These flags are passed to uic, when creating a a h
file from a .ui file.</P
></DD
><DT
><A
NAME="CV-QT_UICDECLPREFIX"
></A
><VAR
CLASS="ENVAR"
>QT_UICDECLPREFIX</VAR
></DT
><DD
><P
>Default value is ''. Prefix for uic generated header files.</P
></DD
><DT
><A
NAME="CV-QT_UICDECLSUFFIX"
></A
><VAR
CLASS="ENVAR"
>QT_UICDECLSUFFIX</VAR
></DT
><DD
><P
>Default value is '.h'. Suffix for uic generated header files.</P
></DD
><DT
><A
NAME="CV-QT_UICIMPLFLAGS"
></A
><VAR
CLASS="ENVAR"
>QT_UICIMPLFLAGS</VAR
></DT
><DD
><P
>Default value is ''. These flags are passed to uic, when creating a cxx
file from a .ui file.</P
></DD
><DT
><A
NAME="CV-QT_UICIMPLPREFIX"
></A
><VAR
CLASS="ENVAR"
>QT_UICIMPLPREFIX</VAR
></DT
><DD
><P
>Default value is 'uic_'. Prefix for uic generated implementation files.</P
></DD
><DT
><A
NAME="CV-QT_UICIMPLSUFFIX"
></A
><VAR
CLASS="ENVAR"
>QT_UICIMPLSUFFIX</VAR
></DT
><DD
><P
>Default value is '<VAR
CLASS="ENVAR"
>$CXXFILESUFFIX</VAR
>'. Suffix for uic generated implementation
files.</P
></DD
><DT
><A
NAME="CV-QT_UISUFFIX"
></A
><VAR
CLASS="ENVAR"
>QT_UISUFFIX</VAR
></DT
><DD
><P
>Default value is '.ui'. Suffix of designer input files.</P
></DD
><DT
><A
NAME="CV-QTDIR"
></A
><VAR
CLASS="ENVAR"
>QTDIR</VAR
></DT
><DD
><P
>The qt tool tries to take this from os.environ.
It also initializes all QT_*
construction variables listed below.
(Note that all paths are constructed
with python's os.path.join() method,
but are listed here with the '/' separator
for easier reading.)
In addition, the construction environment
variables <VAR
CLASS="ENVAR"
>$CPPPATH</VAR
>, <VAR
CLASS="ENVAR"
>$LIBPATH</VAR
> and <VAR
CLASS="ENVAR"
>$LIBS</VAR
> may be modified
and the variables
PROGEMITTER, SHLIBEMITTER and LIBEMITTER
are modified. Because the build-performance is affected when using this tool,
you have to explicitly specify it at Environment creation:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>Environment(tools=['default','qt'])</PRE
></TD
></TR
></TABLE
><P
>The qt tool supports the following operations:</P
><P
>.B Automatic moc file generation from header files.
You do not have to specify moc files explicitly, the tool does it for you.
However, there are a few preconditions to do so: Your header file must have
the same filebase as your implementation file and must stay in the same
directory. It must have one of the suffixes .h, .hpp, .H, .hxx, .hh. You
can turn off automatic moc file generation by setting QT_AUTOSCAN to 0.
See also the corresponding builder method
.B Moc()</P
><P
>.B Automatic moc file generation from cxx files.
As stated in the qt documentation, include the moc file at the end of
the cxx file. Note that you have to include the file, which is generated
by the transformation ${QT_MOCCXXPREFIX}basename${QT_MOCCXXSUFFIX}, by default
basename.moc. A warning is generated after building the moc file, if you
do not include the correct file. If you are using BuildDir, you may
need to specify duplicate=1. You can turn off automatic moc file generation
by setting QT_AUTOSCAN to 0. See also the corresponding builder method
.B Moc()</P
><P
>.B Automatic handling of .ui files.
The implementation files generated from .ui files are handled much the same
as yacc or lex files. Each .ui file given as a source of Program, Library or
SharedLibrary will generate three files, the declaration file, the
implementation file and a moc file. Because there are also generated headers,
you may need to specify duplicate=1 in calls to BuildDir. See also the corresponding builder method
.B Uic()</P
></DD
><DT
><A
NAME="CV-RANLIB"
></A
><VAR
CLASS="ENVAR"
>RANLIB</VAR
></DT
><DD
><P
>The archive indexer.</P
></DD
><DT
><A
NAME="CV-RANLIBFLAGS"
></A
><VAR
CLASS="ENVAR"
>RANLIBFLAGS</VAR
></DT
><DD
><P
>General options passed to the archive indexer.</P
></DD
><DT
><A
NAME="CV-RC"
></A
><VAR
CLASS="ENVAR"
>RC</VAR
></DT
><DD
><P
>The resource compiler used by the RES builder.</P
></DD
><DT
><A
NAME="CV-RCCOM"
></A
><VAR
CLASS="ENVAR"
>RCCOM</VAR
></DT
><DD
><P
>The command line used by the RES builder.</P
></DD
><DT
><A
NAME="CV-RCCOMSTR"
></A
><VAR
CLASS="ENVAR"
>RCCOMSTR</VAR
></DT
><DD
><P
>The string displayed when invoking the resource compiler.
If this is not set, then <VAR
CLASS="ENVAR"
>$RCCOM</VAR
> (the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-RCFLAGS"
></A
><VAR
CLASS="ENVAR"
>RCFLAGS</VAR
></DT
><DD
><P
>The flags passed to the resource compiler by the RES builder.</P
></DD
><DT
><A
NAME="CV-RCS"
></A
><VAR
CLASS="ENVAR"
>RCS</VAR
></DT
><DD
><P
>The RCS executable.
Note that this variable is not actually used
for the command to fetch source files from RCS;
see the
<VAR
CLASS="ENVAR"
>$RCS_CO</VAR
>
construction variable, below.</P
></DD
><DT
><A
NAME="CV-RCS_CO"
></A
><VAR
CLASS="ENVAR"
>RCS_CO</VAR
></DT
><DD
><P
>The RCS "checkout" executable,
used to fetch source files from RCS.</P
></DD
><DT
><A
NAME="CV-RCS_COCOM"
></A
><VAR
CLASS="ENVAR"
>RCS_COCOM</VAR
></DT
><DD
><P
>The command line used to
fetch (checkout) source files from RCS.</P
></DD
><DT
><A
NAME="CV-RCS_COCOMSTR"
></A
><VAR
CLASS="ENVAR"
>RCS_COCOMSTR</VAR
></DT
><DD
><P
>The string displayed when fetching
a source file from RCS.
If this is not set, then <VAR
CLASS="ENVAR"
>$RCS_COCOM</VAR
>
(the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-RCS_COFLAGS"
></A
><VAR
CLASS="ENVAR"
>RCS_COFLAGS</VAR
></DT
><DD
><P
>Options that are passed to the <VAR
CLASS="ENVAR"
>$RCS_CO</VAR
> command.</P
></DD
><DT
><A
NAME="CV-RDIRS"
></A
><VAR
CLASS="ENVAR"
>RDirs</VAR
></DT
><DD
><P
>A function that converts a file name into a list of Dir instances by
searching the repositories. </P
></DD
><DT
><A
NAME="CV-REGSVR"
></A
><VAR
CLASS="ENVAR"
>REGSVR</VAR
></DT
><DD
><P
>The program used on WIN32 systems
to register a newly-built DLL library
whenever the <TT
CLASS="FUNCTION"
>SharedLibrary</TT
> builder
is passed a keyword argument of <TT
CLASS="LITERAL"
>register=1</TT
>.</P
></DD
><DT
><A
NAME="CV-REGSVRCOM"
></A
><VAR
CLASS="ENVAR"
>REGSVRCOM</VAR
></DT
><DD
><P
>The command line used on WIN32 systems
to register a newly-built DLL library
whenever the <TT
CLASS="FUNCTION"
>SharedLibrary</TT
> builder
is passed a keyword argument of <TT
CLASS="LITERAL"
>register=1</TT
>.</P
></DD
><DT
><A
NAME="CV-REGSVRCOMSTR"
></A
><VAR
CLASS="ENVAR"
>REGSVRCOMSTR</VAR
></DT
><DD
><P
>The string displayed when registering a newly-built DLL file.
If this is not set, then <VAR
CLASS="ENVAR"
>$REGSVRCOM</VAR
> (the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-REGSVRFLAGS"
></A
><VAR
CLASS="ENVAR"
>REGSVRFLAGS</VAR
></DT
><DD
><P
>Flags passed to the DLL registration program
on WIN32 systems when a newly-built DLL library is registered.
By default,
this includes the <VAR
CLASS="OPTION"
>/s</VAR
>
that prevents dialog boxes from popping up
and requiring user attention.</P
></DD
><DT
><A
NAME="CV-RMIC"
></A
><VAR
CLASS="ENVAR"
>RMIC</VAR
></DT
><DD
><P
>The Java RMI stub compiler.</P
></DD
><DT
><A
NAME="CV-RMICCOM"
></A
><VAR
CLASS="ENVAR"
>RMICCOM</VAR
></DT
><DD
><P
>The command line used to compile stub
and skeleton class files
from Java classes that contain RMI implementations.
Any options specified in the <VAR
CLASS="ENVAR"
>$RMICFLAGS</VAR
> construction variable
are included on this command line.</P
></DD
><DT
><A
NAME="CV-RMICCOMSTR"
></A
><VAR
CLASS="ENVAR"
>RMICCOMSTR</VAR
></DT
><DD
><P
>The string displayed when compiling
stub and skeleton class files
from Java classes that contain RMI implementations.
If this is not set, then <VAR
CLASS="ENVAR"
>$RMICCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(RMICCOMSTR = "Generating stub/skeleton class files $TARGETS from $SOURCES")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-RMICFLAGS"
></A
><VAR
CLASS="ENVAR"
>RMICFLAGS</VAR
></DT
><DD
><P
>General options passed to the Java RMI stub compiler.</P
></DD
><DT
><A
NAME="CV-_RPATH"
></A
><VAR
CLASS="ENVAR"
>_RPATH</VAR
></DT
><DD
><P
>An automatically-generated construction variable
containing the rpath flags to be used when linking
a program with shared libraries.
The value of <VAR
CLASS="ENVAR"
>$_RPATH</VAR
> is created
by appending <VAR
CLASS="ENVAR"
>$RPATHPREFIX</VAR
> and <VAR
CLASS="ENVAR"
>$RPATHSUFFIX</VAR
>
to the beginning and end
of each directory in <VAR
CLASS="ENVAR"
>$RPATH</VAR
>.</P
></DD
><DT
><A
NAME="CV-RPATH"
></A
><VAR
CLASS="ENVAR"
>RPATH</VAR
></DT
><DD
><P
>A list of paths to search for shared libraries when running programs.
Currently only used in the GNU (gnulink),
IRIX (sgilink) and Sun (sunlink) linkers.
Ignored on platforms and toolchains that don't support it.
Note that the paths added to RPATH
are not transformed by
<TT
CLASS="APPLICATION"
>scons</TT
>
in any way: if you want an absolute
path, you must make it absolute yourself.</P
></DD
><DT
><A
NAME="CV-RPATHPREFIX"
></A
><VAR
CLASS="ENVAR"
>RPATHPREFIX</VAR
></DT
><DD
><P
>The prefix used to specify a directory to be searched for
shared libraries when running programs.
This will be appended to the beginning of each directory
in the <VAR
CLASS="ENVAR"
>$RPATH</VAR
> construction variable
when the <VAR
CLASS="ENVAR"
>$_RPATH</VAR
> variable is automatically generated.</P
></DD
><DT
><A
NAME="CV-RPATHSUFFIX"
></A
><VAR
CLASS="ENVAR"
>RPATHSUFFIX</VAR
></DT
><DD
><P
>The suffix used to specify a directory to be searched for
shared libraries when running programs.
This will be appended to the end of each directory
in the <VAR
CLASS="ENVAR"
>$RPATH</VAR
> construction variable
when the <VAR
CLASS="ENVAR"
>$_RPATH</VAR
> variable is automatically generated.</P
></DD
><DT
><A
NAME="CV-RPCGEN"
></A
><VAR
CLASS="ENVAR"
>RPCGEN</VAR
></DT
><DD
><P
>The RPC protocol compiler.</P
></DD
><DT
><A
NAME="CV-RPCGENCLIENTFLAGS"
></A
><VAR
CLASS="ENVAR"
>RPCGENCLIENTFLAGS</VAR
></DT
><DD
><P
>Options passed to the RPC protocol compiler
when generating client side stubs.
These are in addition to any flags specified in the
<VAR
CLASS="ENVAR"
>$RPCGENFLAGS</VAR
>
construction variable.</P
></DD
><DT
><A
NAME="CV-RPCGENFLAGS"
></A
><VAR
CLASS="ENVAR"
>RPCGENFLAGS</VAR
></DT
><DD
><P
>General options passed to the RPC protocol compiler.</P
></DD
><DT
><A
NAME="CV-RPCGENHEADERFLAGS"
></A
><VAR
CLASS="ENVAR"
>RPCGENHEADERFLAGS</VAR
></DT
><DD
><P
>Options passed to the RPC protocol compiler
when generating a header file.
These are in addition to any flags specified in the
<VAR
CLASS="ENVAR"
>$RPCGENFLAGS</VAR
>
construction variable.</P
></DD
><DT
><A
NAME="CV-RPCGENSERVICEFLAGS"
></A
><VAR
CLASS="ENVAR"
>RPCGENSERVICEFLAGS</VAR
></DT
><DD
><P
>Options passed to the RPC protocol compiler
when generating server side stubs.
These are in addition to any flags specified in the
<VAR
CLASS="ENVAR"
>$RPCGENFLAGS</VAR
>
construction variable.</P
></DD
><DT
><A
NAME="CV-RPCGENXDRFLAGS"
></A
><VAR
CLASS="ENVAR"
>RPCGENXDRFLAGS</VAR
></DT
><DD
><P
>Options passed to the RPC protocol compiler
when generating XDR routines.
These are in addition to any flags specified in the
<VAR
CLASS="ENVAR"
>$RPCGENFLAGS</VAR
>
construction variable.</P
></DD
><DT
><A
NAME="CV-SCANNERS"
></A
><VAR
CLASS="ENVAR"
>SCANNERS</VAR
></DT
><DD
><P
>A list of the available implicit dependency scanners.
New file scanners may be added by
appending to this list,
although the more flexible approach
is to associate scanners
with a specific Builder.
See the sections "Builder Objects"
and "Scanner Objects,"
below, for more information.</P
></DD
><DT
><A
NAME="CV-SCCS"
></A
><VAR
CLASS="ENVAR"
>SCCS</VAR
></DT
><DD
><P
>The SCCS executable.</P
></DD
><DT
><A
NAME="CV-SCCSCOM"
></A
><VAR
CLASS="ENVAR"
>SCCSCOM</VAR
></DT
><DD
><P
>The command line used to
fetch source files from SCCS.</P
></DD
><DT
><A
NAME="CV-SCCSCOMSTR"
></A
><VAR
CLASS="ENVAR"
>SCCSCOMSTR</VAR
></DT
><DD
><P
>The string displayed when fetching
a source file from a CVS repository.
If this is not set, then <VAR
CLASS="ENVAR"
>$SCCSCOM</VAR
>
(the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-SCCSFLAGS"
></A
><VAR
CLASS="ENVAR"
>SCCSFLAGS</VAR
></DT
><DD
><P
>General options that are passed to SCCS.</P
></DD
><DT
><A
NAME="CV-SCCSGETFLAGS"
></A
><VAR
CLASS="ENVAR"
>SCCSGETFLAGS</VAR
></DT
><DD
><P
>Options that are passed specifically to the SCCS "get" subcommand.
This can be set, for example, to
<VAR
CLASS="OPTION"
>-e</VAR
>
to check out editable files from SCCS.</P
></DD
><DT
><A
NAME="CV-SHCC"
></A
><VAR
CLASS="ENVAR"
>SHCC</VAR
></DT
><DD
><P
>The C compiler used for generating shared-library objects.</P
></DD
><DT
><A
NAME="CV-SHCCCOM"
></A
><VAR
CLASS="ENVAR"
>SHCCCOM</VAR
></DT
><DD
><P
>The command line used to compile a C source file
to a shared-library object file.
Any options specified in the <VAR
CLASS="ENVAR"
>$SHCCFLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$CPPFLAGS</VAR
> construction variables
are included on this command line.</P
></DD
><DT
><A
NAME="CV-SHCCCOMSTR"
></A
><VAR
CLASS="ENVAR"
>SHCCCOMSTR</VAR
></DT
><DD
><P
>The string displayed when a C source file
is compiled to a shared object file.
If this is not set, then <VAR
CLASS="ENVAR"
>$SHCCCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(SHCCCOMSTR = "Compiling shared object $TARGET")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-SHCCFLAGS"
></A
><VAR
CLASS="ENVAR"
>SHCCFLAGS</VAR
></DT
><DD
><P
>Options that are passed to the C compiler
to generate shared-library objects.</P
></DD
><DT
><A
NAME="CV-SHCXX"
></A
><VAR
CLASS="ENVAR"
>SHCXX</VAR
></DT
><DD
><P
>The C++ compiler used for generating shared-library objects.</P
></DD
><DT
><A
NAME="CV-SHCXXCOM"
></A
><VAR
CLASS="ENVAR"
>SHCXXCOM</VAR
></DT
><DD
><P
>The command line used to compile a C++ source file
to a shared-library object file.
Any options specified in the <VAR
CLASS="ENVAR"
>$SHCXXFLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$CPPFLAGS</VAR
> construction variables
are included on this command line.</P
></DD
><DT
><A
NAME="CV-SHCXXCOMSTR"
></A
><VAR
CLASS="ENVAR"
>SHCXXCOMSTR</VAR
></DT
><DD
><P
>The string displayed when a C++ source file
is compiled to a shared object file.
If this is not set, then <VAR
CLASS="ENVAR"
>$SHCXXCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(SHCXXCOMSTR = "Compiling shared object $TARGET")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-SHCXXFLAGS"
></A
><VAR
CLASS="ENVAR"
>SHCXXFLAGS</VAR
></DT
><DD
><P
>Options that are passed to the C++ compiler
to generate shared-library objects.</P
></DD
><DT
><A
NAME="CV-SHELL"
></A
><VAR
CLASS="ENVAR"
>SHELL</VAR
></DT
><DD
><P
>A string naming the shell program that will be passed to the
<VAR
CLASS="ENVAR"
>$SPAWN</VAR
>
function.
See the
<VAR
CLASS="ENVAR"
>$SPAWN</VAR
>
construction variable for more information.</P
></DD
><DT
><A
NAME="CV-SHF77"
></A
><VAR
CLASS="ENVAR"
>SHF77</VAR
></DT
><DD
><P
>The Fortran 77 compiler used for generating shared-library objects.
You should normally set the <VAR
CLASS="ENVAR"
>$SHFORTRAN</VAR
> variable,
which specifies the default Fortran compiler
for all Fortran versions.
You only need to set <VAR
CLASS="ENVAR"
>$SHF77</VAR
> if you need to use a specific compiler
or compiler version for Fortran 77 files.</P
></DD
><DT
><A
NAME="CV-SHF77COM"
></A
><VAR
CLASS="ENVAR"
>SHF77COM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran 77 source file
to a shared-library object file.
You only need to set <VAR
CLASS="ENVAR"
>$SHF77COM</VAR
> if you need to use a specific
command line for Fortran 77 files.
You should normally set the <VAR
CLASS="ENVAR"
>$SHFORTRANCOM</VAR
> variable,
which specifies the default command line
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-SHF77COMSTR"
></A
><VAR
CLASS="ENVAR"
>SHF77COMSTR</VAR
></DT
><DD
><P
>The string displayed when a Fortran 77 source file
is compiled to a shared-library object file.
If this is not set, then <VAR
CLASS="ENVAR"
>$SHF77COM</VAR
> or <VAR
CLASS="ENVAR"
>$SHFORTRANCOM</VAR
>
(the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-SHF77FLAGS"
></A
><VAR
CLASS="ENVAR"
>SHF77FLAGS</VAR
></DT
><DD
><P
>Options that are passed to the Fortran 77 compiler
to generated shared-library objects.
You only need to set <VAR
CLASS="ENVAR"
>$SHF77FLAGS</VAR
> if you need to define specific
user options for Fortran 77 files.
You should normally set the <VAR
CLASS="ENVAR"
>$SHFORTRANFLAGS</VAR
> variable,
which specifies the user-specified options
passed to the default Fortran compiler
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-SHF77PPCOM"
></A
><VAR
CLASS="ENVAR"
>SHF77PPCOM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran 77 source file to a
shared-library object file
after first running the file through the C preprocessor.
Any options specified in the <VAR
CLASS="ENVAR"
>$SHF77FLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$CPPFLAGS</VAR
> construction variables
are included on this command line.
You only need to set <VAR
CLASS="ENVAR"
>$SHF77PPCOM</VAR
> if you need to use a specific
C-preprocessor command line for Fortran 77 files.
You should normally set the <VAR
CLASS="ENVAR"
>$SHFORTRANPPCOM</VAR
> variable,
which specifies the default C-preprocessor command line
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-SHF90"
></A
><VAR
CLASS="ENVAR"
>SHF90</VAR
></DT
><DD
><P
>The Fortran 90 compiler used for generating shared-library objects.
You should normally set the <VAR
CLASS="ENVAR"
>$SHFORTRAN</VAR
> variable,
which specifies the default Fortran compiler
for all Fortran versions.
You only need to set <VAR
CLASS="ENVAR"
>$SHF90</VAR
> if you need to use a specific compiler
or compiler version for Fortran 90 files.</P
></DD
><DT
><A
NAME="CV-SHF90COM"
></A
><VAR
CLASS="ENVAR"
>SHF90COM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran 90 source file
to a shared-library object file.
You only need to set <VAR
CLASS="ENVAR"
>$SHF90COM</VAR
> if you need to use a specific
command line for Fortran 90 files.
You should normally set the <VAR
CLASS="ENVAR"
>$SHFORTRANCOM</VAR
> variable,
which specifies the default command line
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-SHF90COMSTR"
></A
><VAR
CLASS="ENVAR"
>SHF90COMSTR</VAR
></DT
><DD
><P
>The string displayed when a Fortran 90 source file
is compiled to a shared-library object file.
If this is not set, then <VAR
CLASS="ENVAR"
>$SHF90COM</VAR
> or <VAR
CLASS="ENVAR"
>$SHFORTRANCOM</VAR
>
(the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-SHF90FLAGS"
></A
><VAR
CLASS="ENVAR"
>SHF90FLAGS</VAR
></DT
><DD
><P
>Options that are passed to the Fortran 90 compiler
to generated shared-library objects.
You only need to set <VAR
CLASS="ENVAR"
>$SHF90FLAGS</VAR
> if you need to define specific
user options for Fortran 90 files.
You should normally set the <VAR
CLASS="ENVAR"
>$SHFORTRANFLAGS</VAR
> variable,
which specifies the user-specified options
passed to the default Fortran compiler
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-SHF90PPCOM"
></A
><VAR
CLASS="ENVAR"
>SHF90PPCOM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran 90 source file to a
shared-library object file
after first running the file through the C preprocessor.
Any options specified in the <VAR
CLASS="ENVAR"
>$SHF90FLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$CPPFLAGS</VAR
> construction variables
are included on this command line.
You only need to set <VAR
CLASS="ENVAR"
>$SHF90PPCOM</VAR
> if you need to use a specific
C-preprocessor command line for Fortran 90 files.
You should normally set the <VAR
CLASS="ENVAR"
>$SHFORTRANPPCOM</VAR
> variable,
which specifies the default C-preprocessor command line
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-SHF95"
></A
><VAR
CLASS="ENVAR"
>SHF95</VAR
></DT
><DD
><P
>The Fortran 95 compiler used for generating shared-library objects.
You should normally set the <VAR
CLASS="ENVAR"
>$SHFORTRAN</VAR
> variable,
which specifies the default Fortran compiler
for all Fortran versions.
You only need to set <VAR
CLASS="ENVAR"
>$SHF95</VAR
> if you need to use a specific compiler
or compiler version for Fortran 95 files.</P
></DD
><DT
><A
NAME="CV-SHF95COM"
></A
><VAR
CLASS="ENVAR"
>SHF95COM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran 95 source file
to a shared-library object file.
You only need to set <VAR
CLASS="ENVAR"
>$SHF95COM</VAR
> if you need to use a specific
command line for Fortran 95 files.
You should normally set the <VAR
CLASS="ENVAR"
>$SHFORTRANCOM</VAR
> variable,
which specifies the default command line
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-SHF95COMSTR"
></A
><VAR
CLASS="ENVAR"
>SHF95COMSTR</VAR
></DT
><DD
><P
>The string displayed when a Fortran 95 source file
is compiled to a shared-library object file.
If this is not set, then <VAR
CLASS="ENVAR"
>$SHF95COM</VAR
> or <VAR
CLASS="ENVAR"
>$SHFORTRANCOM</VAR
>
(the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-SHF95FLAGS"
></A
><VAR
CLASS="ENVAR"
>SHF95FLAGS</VAR
></DT
><DD
><P
>Options that are passed to the Fortran 95 compiler
to generated shared-library objects.
You only need to set <VAR
CLASS="ENVAR"
>$SHF95FLAGS</VAR
> if you need to define specific
user options for Fortran 95 files.
You should normally set the <VAR
CLASS="ENVAR"
>$SHFORTRANFLAGS</VAR
> variable,
which specifies the user-specified options
passed to the default Fortran compiler
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-SHF95PPCOM"
></A
><VAR
CLASS="ENVAR"
>SHF95PPCOM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran 95 source file to a
shared-library object file
after first running the file through the C preprocessor.
Any options specified in the <VAR
CLASS="ENVAR"
>$SHF95FLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$CPPFLAGS</VAR
> construction variables
are included on this command line.
You only need to set <VAR
CLASS="ENVAR"
>$SHF95PPCOM</VAR
> if you need to use a specific
C-preprocessor command line for Fortran 95 files.
You should normally set the <VAR
CLASS="ENVAR"
>$SHFORTRANPPCOM</VAR
> variable,
which specifies the default C-preprocessor command line
for all Fortran versions.</P
></DD
><DT
><A
NAME="CV-SHFORTRAN"
></A
><VAR
CLASS="ENVAR"
>SHFORTRAN</VAR
></DT
><DD
><P
>The default Fortran compiler used for generating shared-library objects.</P
></DD
><DT
><A
NAME="CV-SHFORTRANCOM"
></A
><VAR
CLASS="ENVAR"
>SHFORTRANCOM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran source file
to a shared-library object file.</P
></DD
><DT
><A
NAME="CV-SHFORTRANCOMSTR"
></A
><VAR
CLASS="ENVAR"
>SHFORTRANCOMSTR</VAR
></DT
><DD
><P
>The string displayed when a Fortran source file
is compiled to a shared-library object file.
If this is not set, then <VAR
CLASS="ENVAR"
>$SHFORTRANCOM</VAR
>
(the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-SHFORTRANFLAGS"
></A
><VAR
CLASS="ENVAR"
>SHFORTRANFLAGS</VAR
></DT
><DD
><P
>Options that are passed to the Fortran compiler
to generate shared-library objects.</P
></DD
><DT
><A
NAME="CV-SHFORTRANPPCOM"
></A
><VAR
CLASS="ENVAR"
>SHFORTRANPPCOM</VAR
></DT
><DD
><P
>The command line used to compile a Fortran source file to a
shared-library object file
after first running the file through the C preprocessor.
Any options specified
in the <VAR
CLASS="ENVAR"
>$SHFORTRANFLAGS</VAR
> and <VAR
CLASS="ENVAR"
>$CPPFLAGS</VAR
> construction variables
are included on this command line.</P
></DD
><DT
><A
NAME="CV-SHLIBPREFIX"
></A
><VAR
CLASS="ENVAR"
>SHLIBPREFIX</VAR
></DT
><DD
><P
>The prefix used for shared library file names.</P
></DD
><DT
><A
NAME="CV-SHLIBSUFFIX"
></A
><VAR
CLASS="ENVAR"
>SHLIBSUFFIX</VAR
></DT
><DD
><P
>The suffix used for shared library file names.</P
></DD
><DT
><A
NAME="CV-SHLINK"
></A
><VAR
CLASS="ENVAR"
>SHLINK</VAR
></DT
><DD
><P
>The linker for programs that use shared libraries.</P
></DD
><DT
><A
NAME="CV-SHLINKCOM"
></A
><VAR
CLASS="ENVAR"
>SHLINKCOM</VAR
></DT
><DD
><P
>The command line used to link programs using shared libaries.</P
></DD
><DT
><A
NAME="CV-SHLINKCOMSTR"
></A
><VAR
CLASS="ENVAR"
>SHLINKCOMSTR</VAR
></DT
><DD
><P
>The string displayed when programs using shared libraries are linked.
If this is not set, then <VAR
CLASS="ENVAR"
>$SHLINKCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(SHLINKCOMSTR = "Linking shared $TARGET")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-SHLINKFLAGS"
></A
><VAR
CLASS="ENVAR"
>SHLINKFLAGS</VAR
></DT
><DD
><P
>General user options passed to the linker for programs using shared libraries.
Note that this variable should
<I
CLASS="EMPHASIS"
>not</I
>
contain
<VAR
CLASS="OPTION"
>-l</VAR
>
(or similar) options for linking with the libraries listed in <VAR
CLASS="ENVAR"
>$LIBS</VAR
>,
nor
<VAR
CLASS="OPTION"
>-L</VAR
>
(or similar) include search path options
that scons generates automatically from <VAR
CLASS="ENVAR"
>$LIBPATH</VAR
>.
See
<VAR
CLASS="ENVAR"
>$_LIBFLAGS</VAR
>
above,
for the variable that expands to library-link options,
and
<VAR
CLASS="ENVAR"
>$_LIBDIRFLAGS</VAR
>
above,
for the variable that expands to library search path options.</P
></DD
><DT
><A
NAME="CV-SHOBJPREFIX"
></A
><VAR
CLASS="ENVAR"
>SHOBJPREFIX</VAR
></DT
><DD
><P
>The prefix used for shared object file names.</P
></DD
><DT
><A
NAME="CV-SHOBJSUFFIX"
></A
><VAR
CLASS="ENVAR"
>SHOBJSUFFIX</VAR
></DT
><DD
><P
>The suffix used for shared object file names.</P
></DD
><DT
><A
NAME="CV-SOURCE"
></A
><VAR
CLASS="ENVAR"
>SOURCE</VAR
></DT
><DD
><P
>A reserved variable name
that may not be set or used in a construction environment.
(See "Variable Substitution," below.)</P
></DD
><DT
><A
NAME="CV-SOURCES"
></A
><VAR
CLASS="ENVAR"
>SOURCES</VAR
></DT
><DD
><P
>A reserved variable name
that may not be set or used in a construction environment.
(See "Variable Substitution," below.)</P
></DD
><DT
><A
NAME="CV-SPAWN"
></A
><VAR
CLASS="ENVAR"
>SPAWN</VAR
></DT
><DD
><P
>A command interpreter function that will be called to execute command line
strings. The function must expect the following arguments:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>def spawn(shell, escape, cmd, args, env):</PRE
></TD
></TR
></TABLE
><P
><VAR
CLASS="VARNAME"
>sh</VAR
>
is a string naming the shell program to use.
<VAR
CLASS="VARNAME"
>escape</VAR
>
is a function that can be called to escape shell special characters in
the command line.
<VAR
CLASS="VARNAME"
>cmd</VAR
>
is the path to the command to be executed.
<VAR
CLASS="VARNAME"
>args</VAR
>
is the arguments to the command.
<VAR
CLASS="VARNAME"
>env</VAR
>
is a dictionary of the environment variables
in which the command should be executed.</P
></DD
><DT
><A
NAME="CV-SWIG"
></A
><VAR
CLASS="ENVAR"
>SWIG</VAR
></DT
><DD
><P
>The scripting language wrapper and interface generator.</P
></DD
><DT
><A
NAME="CV-SWIGCFILESUFFIX"
></A
><VAR
CLASS="ENVAR"
>SWIGCFILESUFFIX</VAR
></DT
><DD
><P
>The suffix that will be used for intermediate C
source files generated by
the scripting language wrapper and interface generator.
The default value is
<TT
CLASS="FILENAME"
>_wrap</TT
><VAR
CLASS="ENVAR"
>$CFILESUFFIX</VAR
>.
By default, this value is used whenever the
<VAR
CLASS="OPTION"
>-c++</VAR
>
option is
<I
CLASS="EMPHASIS"
>not</I
>
specified as part of the
<VAR
CLASS="ENVAR"
>$SWIGFLAGS</VAR
>
construction variable.</P
></DD
><DT
><A
NAME="CV-SWIGCOM"
></A
><VAR
CLASS="ENVAR"
>SWIGCOM</VAR
></DT
><DD
><P
>The command line used to call
the scripting language wrapper and interface generator.</P
></DD
><DT
><A
NAME="CV-SWIGCOMSTR"
></A
><VAR
CLASS="ENVAR"
>SWIGCOMSTR</VAR
></DT
><DD
><P
>The string displayed when calling
the scripting language wrapper and interface generator.
If this is not set, then <VAR
CLASS="ENVAR"
>$SWIGCOM</VAR
> (the command line) is displayed.</P
></DD
><DT
><A
NAME="CV-SWIGCXXFILESUFFIX"
></A
><VAR
CLASS="ENVAR"
>SWIGCXXFILESUFFIX</VAR
></DT
><DD
><P
>The suffix that will be used for intermediate C++
source files generated by
the scripting language wrapper and interface generator.
The default value is
<TT
CLASS="FILENAME"
>_wrap</TT
><VAR
CLASS="ENVAR"
>$CFILESUFFIX</VAR
>.
By default, this value is used whenever the
<TT
CLASS="FILENAME"
>-c++</TT
>
option is specified as part of the
<VAR
CLASS="ENVAR"
>$SWIGFLAGS</VAR
>
construction variable.</P
></DD
><DT
><A
NAME="CV-SWIGFLAGS"
></A
><VAR
CLASS="ENVAR"
>SWIGFLAGS</VAR
></DT
><DD
><P
>General options passed to
the scripting language wrapper and interface generator.
This is where you should set
<VAR
CLASS="OPTION"
>-python</VAR
>,
<VAR
CLASS="OPTION"
>-perl5</VAR
>,
<VAR
CLASS="OPTION"
>-tcl</VAR
>,
or whatever other options you want to specify to SWIG.
If you set the
<VAR
CLASS="OPTION"
>-c++</VAR
>
option in this variable,
<TT
CLASS="APPLICATION"
>scons</TT
>
will, by default,
generate a C++ intermediate source file
with the extension that is specified as the
<VAR
CLASS="ENVAR"
>$CXXFILESUFFIX</VAR
>
variable.</P
></DD
><DT
><A
NAME="CV-TAR"
></A
><VAR
CLASS="ENVAR"
>TAR</VAR
></DT
><DD
><P
>The tar archiver.</P
></DD
><DT
><A
NAME="CV-TARCOM"
></A
><VAR
CLASS="ENVAR"
>TARCOM</VAR
></DT
><DD
><P
>The command line used to call the tar archiver.</P
></DD
><DT
><A
NAME="CV-TARCOMSTR"
></A
><VAR
CLASS="ENVAR"
>TARCOMSTR</VAR
></DT
><DD
><P
>The string displayed when archiving files
using the tar archiver.
If this is not set, then <VAR
CLASS="ENVAR"
>$TARCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(TARCOMSTR = "Archiving $TARGET")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-TARFLAGS"
></A
><VAR
CLASS="ENVAR"
>TARFLAGS</VAR
></DT
><DD
><P
>General options passed to the tar archiver.</P
></DD
><DT
><A
NAME="CV-TARGET"
></A
><VAR
CLASS="ENVAR"
>TARGET</VAR
></DT
><DD
><P
>A reserved variable name
that may not be set or used in a construction environment.
(See "Variable Substitution," below.)</P
></DD
><DT
><A
NAME="CV-TARGETS"
></A
><VAR
CLASS="ENVAR"
>TARGETS</VAR
></DT
><DD
><P
>A reserved variable name
that may not be set or used in a construction environment.
(See "Variable Substitution," below.)</P
></DD
><DT
><A
NAME="CV-TARSUFFIX"
></A
><VAR
CLASS="ENVAR"
>TARSUFFIX</VAR
></DT
><DD
><P
>The suffix used for tar file names.</P
></DD
><DT
><A
NAME="CV-TEMPFILEPREFIX"
></A
><VAR
CLASS="ENVAR"
>TEMPFILEPREFIX</VAR
></DT
><DD
><P
>The prefix for a temporary file used
to execute lines longer than $MAXLINELENGTH.
The default is '@'.
This may be set for toolchains that use other values,
such as '-@' for the diab compiler
or '-via' for ARM toolchain.</P
></DD
><DT
><A
NAME="CV-TEX"
></A
><VAR
CLASS="ENVAR"
>TEX</VAR
></DT
><DD
><P
>The TeX formatter and typesetter.</P
></DD
><DT
><A
NAME="CV-TEXCOM"
></A
><VAR
CLASS="ENVAR"
>TEXCOM</VAR
></DT
><DD
><P
>The command line used to call the TeX formatter and typesetter.</P
></DD
><DT
><A
NAME="CV-TEXCOMSTR"
></A
><VAR
CLASS="ENVAR"
>TEXCOMSTR</VAR
></DT
><DD
><P
>The string displayed when calling
the TeX formatter and typesetter.
If this is not set, then <VAR
CLASS="ENVAR"
>$TEXCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(TEXCOMSTR = "Building $TARGET from TeX input $SOURCES")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-TEXFLAGS"
></A
><VAR
CLASS="ENVAR"
>TEXFLAGS</VAR
></DT
><DD
><P
>General options passed to the TeX formatter and typesetter.</P
></DD
><DT
><A
NAME="CV-TOOLS"
></A
><VAR
CLASS="ENVAR"
>TOOLS</VAR
></DT
><DD
><P
>A list of the names of the Tool specifications
that are part of this construction environment.</P
></DD
><DT
><A
NAME="CV-WIN32_INSERT_DEF"
></A
><VAR
CLASS="ENVAR"
>WIN32_INSERT_DEF</VAR
></DT
><DD
><P
>When this is set to true,
a library build of a WIN32 shared library (.dll file)
will also build a corresponding .def file at the same time,
if a .def file is not already listed as a build target.
The default is 0 (do not build a .def file).</P
></DD
><DT
><A
NAME="CV-WIN32DEFPREFIX"
></A
><VAR
CLASS="ENVAR"
>WIN32DEFPREFIX</VAR
></DT
><DD
><P
>The prefix used for WIN32 .def file names.</P
></DD
><DT
><A
NAME="CV-WIN32DEFSUFFIX"
></A
><VAR
CLASS="ENVAR"
>WIN32DEFSUFFIX</VAR
></DT
><DD
><P
>The suffix used for WIN32 .def file names.</P
></DD
><DT
><A
NAME="CV-WIN32EXPPREFIX"
></A
><VAR
CLASS="ENVAR"
>WIN32EXPPREFIX</VAR
></DT
><DD
><P
>XXX The prefix used for WIN32 .def file names.</P
></DD
><DT
><A
NAME="CV-WIN32EXPSUFFIX"
></A
><VAR
CLASS="ENVAR"
>WIN32EXPSUFFIX</VAR
></DT
><DD
><P
>XXX The suffix used for WIN32 .def file names.</P
></DD
><DT
><A
NAME="CV-YACC"
></A
><VAR
CLASS="ENVAR"
>YACC</VAR
></DT
><DD
><P
>The parser generator.</P
></DD
><DT
><A
NAME="CV-YACCCOM"
></A
><VAR
CLASS="ENVAR"
>YACCCOM</VAR
></DT
><DD
><P
>The command line used to call the parser generator
to generate a source file.</P
></DD
><DT
><A
NAME="CV-YACCCOMSTR"
></A
><VAR
CLASS="ENVAR"
>YACCCOMSTR</VAR
></DT
><DD
><P
>The string displayed when generating a source file
using the parser generator.
If this is not set, then <VAR
CLASS="ENVAR"
>$YACCCOM</VAR
> (the command line) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(YACCCOMSTR = "Yacc'ing $TARGET from $SOURCES")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-YACCFLAGS"
></A
><VAR
CLASS="ENVAR"
>YACCFLAGS</VAR
></DT
><DD
><P
>General options passed to the parser generator.
If <VAR
CLASS="ENVAR"
>$YACCFLAGS</VAR
> contains a <VAR
CLASS="OPTION"
>-d</VAR
> option,
SCons assumes that the call will also create a .h file
(if the yacc source file ends in a .y suffix)
or a .hpp file
(if the yacc source file ends in a .yy suffix)</P
></DD
><DT
><A
NAME="CV-YACCHFILESUFFIX"
></A
><VAR
CLASS="ENVAR"
>YACCHFILESUFFIX</VAR
></DT
><DD
><P
>The suffix of the C
header file generated by the parser generator
when the
<VAR
CLASS="OPTION"
>-d</VAR
>
option is used.
Note that setting this variable does not cause
the parser generator to generate a header
file with the specified suffix,
it exists to allow you to specify
what suffix the parser generator will use of its own accord.
The default value is
<TT
CLASS="FILENAME"
>.h</TT
>.</P
></DD
><DT
><A
NAME="CV-YACCHXXFILESUFFIX"
></A
><VAR
CLASS="ENVAR"
>YACCHXXFILESUFFIX</VAR
></DT
><DD
><P
>The suffix of the C++
header file generated by the parser generator
when the
<VAR
CLASS="OPTION"
>-d</VAR
>
option is used.
Note that setting this variable does not cause
the parser generator to generate a header
file with the specified suffix,
it exists to allow you to specify
what suffix the parser generator will use of its own accord.
The default value is
<TT
CLASS="FILENAME"
>.hpp</TT
>.</P
></DD
><DT
><A
NAME="CV-ZIP"
></A
><VAR
CLASS="ENVAR"
>ZIP</VAR
></DT
><DD
><P
>The zip compression and file packaging utility.</P
></DD
><DT
><A
NAME="CV-ZIPCOM"
></A
><VAR
CLASS="ENVAR"
>ZIPCOM</VAR
></DT
><DD
><P
>The command line used to call the zip utility,
or the internal Python function used to create a
zip archive.</P
></DD
><DT
><A
NAME="CV-ZIPCOMPRESSION"
></A
><VAR
CLASS="ENVAR"
>ZIPCOMPRESSION</VAR
></DT
><DD
><P
>The
<VAR
CLASS="VARNAME"
>compression</VAR
>
flag
from the Python
<TT
CLASS="FILENAME"
>zipfile</TT
>
module used by the internal Python function
to control whether the zip archive
is compressed or not.
The default value is
<VAR
CLASS="VARNAME"
>zipfile.ZIP_DEFLATED</VAR
>,
which creates a compressed zip archive.
This value has no effect when using Python 1.5.2
or if the
<VAR
CLASS="VARNAME"
>zipfile</VAR
>
module is otherwise unavailable.</P
></DD
><DT
><A
NAME="CV-ZIPCOMSTR"
></A
><VAR
CLASS="ENVAR"
>ZIPCOMSTR</VAR
></DT
><DD
><P
>The string displayed when archiving files
using the zip utility.
If this is not set, then <VAR
CLASS="ENVAR"
>$ZIPCOM</VAR
>
(the command line or internal Python function) is displayed.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env = Environment(ZIPCOMSTR = "Zipping $TARGET")</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="CV-ZIPFLAGS"
></A
><VAR
CLASS="ENVAR"
>ZIPFLAGS</VAR
></DT
><DD
><P
>General options passed to the zip utility.</P
></DD
></DL
></DIV
></DIV
><DIV
CLASS="APPENDIX"
><HR><H1
><A
NAME="APP-BUILDERS"
></A
>Builders</H1
><P
>&#13;This appendix contains descriptions of all of the
Builders that are <I
CLASS="EMPHASIS"
>potentially</I
>
available "out of the box" in this version of SCons.&#13;</P
><P
></P
><DIV
CLASS="VARIABLELIST"
><DL
><DT
><A
NAME="B-CFILE"
></A
><TT
CLASS="FUNCTION"
>CFile()</TT
>, <TT
CLASS="FUNCTION"
>env.CFile()</TT
></DT
><DD
><P
>Builds a C source file given a lex (<TT
CLASS="FILENAME"
>.l</TT
>)
or yacc (<TT
CLASS="FILENAME"
>.y</TT
>) input file.
The suffix specified by the <VAR
CLASS="ENVAR"
>$CFILESUFFIX</VAR
> construction variable
(<TT
CLASS="FILENAME"
>.c</TT
> by default)
is automatically added to the target
if it is not already present. Example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
># builds foo.c
env.CFile(target = 'foo.c', source = 'foo.l')
# builds bar.c
env.CFile(target = 'bar', source = 'bar.y')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-CXXFILE"
></A
><TT
CLASS="FUNCTION"
>CXXFile()</TT
>, <TT
CLASS="FUNCTION"
>env.CXXFile()</TT
></DT
><DD
><P
>Builds a C++ source file given a lex (<TT
CLASS="FILENAME"
>.ll</TT
>)
or yacc (<TT
CLASS="FILENAME"
>.yy</TT
>)
input file.
The suffix specified by the <VAR
CLASS="ENVAR"
>$CXXFILESUFFIX</VAR
> construction variable
(<TT
CLASS="FILENAME"
>.cc</TT
> by default)
is automatically added to the target
if it is not already present. Example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
># builds foo.cc
env.CXXFile(target = 'foo.cc', source = 'foo.ll')
# builds bar.cc
env.CXXFile(target = 'bar', source = 'bar.yy')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-DVI"
></A
><TT
CLASS="FUNCTION"
>DVI()</TT
>, <TT
CLASS="FUNCTION"
>env.DVI()</TT
></DT
><DD
><P
>Builds a <TT
CLASS="FILENAME"
>.dvi</TT
> file
from a <TT
CLASS="FILENAME"
>.tex</TT
>,
<TT
CLASS="FILENAME"
>.ltx</TT
> or <TT
CLASS="FILENAME"
>.latex</TT
> input file.
If the source file suffix is <TT
CLASS="FILENAME"
>.tex</TT
>,
<TT
CLASS="APPLICATION"
>scons</TT
>
will examine the contents of the file;
if the string
<TT
CLASS="LITERAL"
>\documentclass</TT
>
or
<TT
CLASS="LITERAL"
>\documentstyle</TT
>
is found, the file is assumed to be a LaTeX file and
the target is built by invoking the <VAR
CLASS="ENVAR"
>$LATEXCOM</VAR
> command line;
otherwise, the <VAR
CLASS="ENVAR"
>$TEXCOM</VAR
> command line is used.
If the file is a LaTeX file,
the
<TT
CLASS="FUNCTION"
>DVI</TT
>
builder method will also examine the contents
of the
<TT
CLASS="FILENAME"
>.aux</TT
>
file
and invoke the <VAR
CLASS="ENVAR"
>$BIBTEX</VAR
> command line
if the string
<TT
CLASS="LITERAL"
>bibdata</TT
>
is found,
and will examine the contents
<TT
CLASS="FILENAME"
>.log</TT
>
file and re-run the <VAR
CLASS="ENVAR"
>$LATEXCOM</VAR
> command
if the log file says it is necessary.</P
><P
>The suffix <TT
CLASS="FILENAME"
>.dvi</TT
>
(hard-coded within TeX itself)
is automatically added to the target
if it is not already present.
Examples:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
># builds from aaa.tex
env.DVI(target = 'aaa.dvi', source = 'aaa.tex')
# builds bbb.dvi
env.DVI(target = 'bbb', source = 'bbb.ltx')
# builds from ccc.latex
env.DVI(target = 'ccc.dvi', source = 'ccc.latex')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-JAR"
></A
><TT
CLASS="FUNCTION"
>Jar()</TT
>, <TT
CLASS="FUNCTION"
>env.Jar()</TT
></DT
><DD
><P
>Builds a Java archive (<TT
CLASS="FILENAME"
>.jar</TT
>) file
from a source tree of <TT
CLASS="FILENAME"
>.class</TT
> files.
If the <VAR
CLASS="ENVAR"
>$JARCHDIR</VAR
> value is set, the
<TT
CLASS="APPLICATION"
>jar</TT
>
command will change to the specified directory using the
<VAR
CLASS="OPTION"
>-C</VAR
>
option.
If the contents any of the source files begin with the string
<TT
CLASS="LITERAL"
>Manifest-Version</TT
>,
the file is assumed to be a manifest
and is passed to the
<TT
CLASS="APPLICATION"
>jar</TT
>
command with the
<VAR
CLASS="OPTION"
>m</VAR
>
option set.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.Jar(target = 'foo.jar', source = 'classes')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-JAVA"
></A
><TT
CLASS="FUNCTION"
>Java()</TT
>, <TT
CLASS="FUNCTION"
>env.Java()</TT
></DT
><DD
><P
>Builds one or more Java class files
from one or more source trees of <TT
CLASS="FILENAME"
>.java</TT
> files.
The class files will be placed underneath
the specified target directory.
SCons will parse each source <TT
CLASS="FILENAME"
>.java</TT
> file
to find the classes
(including inner classes)
defined within that file,
and from that figure out the
target <TT
CLASS="FILENAME"
>.class</TT
> files that will be created.
SCons will also search each Java file
for the Java package name,
which it assumes can be found on a line
beginning with the string
<TT
CLASS="LITERAL"
>package</TT
>
in the first column;
the resulting <TT
CLASS="FILENAME"
>.class</TT
> files
will be placed in a directory reflecting
the specified package name.
For example,
the file
<TT
CLASS="FILENAME"
>Foo.java</TT
>
defining a single public
<CODE
CLASS="CLASSNAME"
>Foo</CODE
>
class and
containing a package name of
<CODE
CLASS="CLASSNAME"
>sub.dir</CODE
>
will generate a corresponding
<TT
CLASS="FILENAME"
>sub/dir/Foo.class</TT
>
class file.</P
><P
>Example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.Java(target = 'classes', source = 'src')
env.Java(target = 'classes', source = ['src1', 'src2'])</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-JAVAH"
></A
><TT
CLASS="FUNCTION"
>JavaH()</TT
>, <TT
CLASS="FUNCTION"
>env.JavaH()</TT
></DT
><DD
><P
>Builds C header and source files for
implementing Java native methods.
The target can be either a directory
in which the header files will be written,
or a header file name which
will contain all of the definitions.
The source can be either the names of <TT
CLASS="FILENAME"
>.class</TT
> files,
or the objects returned from the
<TT
CLASS="FUNCTION"
>Java</TT
>
builder method.</P
><P
>If the construction variable
<VAR
CLASS="ENVAR"
>$JAVACLASSDIR</VAR
>
is set, either in the environment
or in the call to the
<TT
CLASS="FUNCTION"
>JavaH</TT
>
builder method itself,
then the value of the variable
will be stripped from the
beginning of any <TT
CLASS="FILENAME"
>.class</TT
> file names.</P
><P
>Examples:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
># builds java_native.h
classes = env.Java(target = 'classdir', source = 'src')
env.JavaH(target = 'java_native.h', source = classes)
# builds include/package_foo.h and include/package_bar.h
env.JavaH(target = 'include',
source = ['package/foo.class', 'package/bar.class'])
# builds export/foo.h and export/bar.h
env.JavaH(target = 'export',
source = ['classes/foo.class', 'classes/bar.class'],
JAVACLASSDIR = 'classes')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-LIBRARY"
></A
><TT
CLASS="FUNCTION"
>Library()</TT
>, <TT
CLASS="FUNCTION"
>env.Library()</TT
></DT
><DD
><P
>A synonym for the
<TT
CLASS="FUNCTION"
>StaticLibrary</TT
>
builder method.</P
></DD
><DT
><A
NAME="B-M4"
></A
><TT
CLASS="FUNCTION"
>M4()</TT
>, <TT
CLASS="FUNCTION"
>env.M4()</TT
></DT
><DD
><P
>Builds an output file from an M4 input file.
This uses a default <VAR
CLASS="ENVAR"
>$M4FLAGS</VAR
> value of
<VAR
CLASS="OPTION"
>-E</VAR
>,
which considers all warnings to be fatal
and stops on the first warning
when using the GNU version of m4.
Example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.M4(target = 'foo.c', source = 'foo.c.m4')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-MOC"
></A
><TT
CLASS="FUNCTION"
>Moc()</TT
>, <TT
CLASS="FUNCTION"
>env.Moc()</TT
></DT
><DD
><P
>Builds an output file from a moc input file. Moc input files are either
header files or cxx files. This builder is only available after using the
tool 'qt'. See the <VAR
CLASS="ENVAR"
>$QTDIR</VAR
> variable for more information.
Example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.Moc('foo.h') # generates moc_foo.cc
env.Moc('foo.cpp') # generates foo.moc</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-MSVSPROJECT"
></A
><TT
CLASS="FUNCTION"
>MSVSProject()</TT
>, <TT
CLASS="FUNCTION"
>env.MSVSProject()</TT
></DT
><DD
><P
>Builds Microsoft Visual Studio project files.
This builds a Visual Studio project file, based on the version of
Visual Studio that is configured (either the latest installed version,
or the version set by
<VAR
CLASS="ENVAR"
>$MSVS_VERSION</VAR
>
in the Environment constructor).
For VS 6, it will generate
<TT
CLASS="FILENAME"
>.dsp</TT
>
and
<TT
CLASS="FILENAME"
>.dsw</TT
>
files, for VS 7, it will
generate
<TT
CLASS="FILENAME"
>.vcproj</TT
>
and
<TT
CLASS="FILENAME"
>.sln</TT
>
files.</P
><P
>It takes several lists of filenames to be placed into the project
file, currently these are limited to
<TT
CLASS="LITERAL"
>srcs</TT
>,
<TT
CLASS="LITERAL"
>incs</TT
>,
<TT
CLASS="LITERAL"
>localincs</TT
>,
<TT
CLASS="LITERAL"
>resources</TT
>,
and
<TT
CLASS="LITERAL"
>misc</TT
>.
These are pretty self explanatory, but it
should be noted that the <TT
CLASS="LITERAL"
>srcs</TT
> list
is NOT added to the <VAR
CLASS="ENVAR"
>$SOURCES</VAR
>
construction variable. This is because it represents a list of files
to be added to the project file, not the source used to build the
project file (in this case, the "source" is the <TT
CLASS="FILENAME"
>SConscript</TT
> file used
to call MSVSProject).</P
><P
>In addition to these values (which are all optional, although not
specifying any of them results in an empty project file), the
following values must be specified:</P
><P
>target: The name of the target
<TT
CLASS="FILENAME"
>.dsp</TT
>
or
<TT
CLASS="FILENAME"
>.vcproj</TT
>
file. The correct
suffix for the version of Visual Studio must be used, but the
<VAR
CLASS="ENVAR"
>$MSVSPROJECTSUFFIX</VAR
>
construction value
will be defined to the correct value (see example below).</P
><P
>variant: The name of this particular variant. These are typically
things like "Debug" or "Release", but really can be anything you want.
Multiple calls to MSVSProject with different variants are allowed: all
variants will be added to the project file with their appropriate
build targets and sources.</P
><P
>buildtarget: A list of SCons.Node.FS objects which is returned from
the command which builds the target. This is used to tell SCons what
to build when the 'build' button is pressed inside of the IDE.</P
><P
>Example usage:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>barsrcs = ['bar.cpp'],
barincs = ['bar.h'],
barlocalincs = ['StdAfx.h']
barresources = ['bar.rc','resource.h']
barmisc = ['bar_readme.txt']
dll = local.SharedLibrary(target = 'bar.dll',
source = barsrcs)
local.MSVSProject(target = 'Bar' + env['MSVSPROJECTSUFFIX'],
srcs = barsrcs,
incs = barincs,
localincs = barlocalincs,
resources = barresources,
misc = barmisc,
buildtarget = dll,
variant = 'Release')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-OBJECT"
></A
><TT
CLASS="FUNCTION"
>Object()</TT
>, <TT
CLASS="FUNCTION"
>env.Object()</TT
></DT
><DD
><P
>A synonym for the
<TT
CLASS="FUNCTION"
>StaticObject</TT
>
builder method.</P
></DD
><DT
><A
NAME="B-PCH"
></A
><TT
CLASS="FUNCTION"
>PCH()</TT
>, <TT
CLASS="FUNCTION"
>env.PCH()</TT
></DT
><DD
><P
>Builds a Microsoft Visual C++ precompiled header.
Calling this builder method
returns a list of two targets: the PCH as the first element, and the object
file as the second element. Normally the object file is ignored.
This builder method is only
provided when Microsoft Visual C++ is being used as the compiler.
The PCH builder method is generally used in
conjuction with the PCH construction variable to force object files to use
the precompiled header:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env['PCH'] = env.PCH('StdAfx.cpp')[0]</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-PDF"
></A
><TT
CLASS="FUNCTION"
>PDF()</TT
>, <TT
CLASS="FUNCTION"
>env.PDF()</TT
></DT
><DD
><P
>Builds a <TT
CLASS="FILENAME"
>.pdf</TT
> file
from a <TT
CLASS="FILENAME"
>.dvi</TT
> input file
(or, by extension, a <TT
CLASS="FILENAME"
>.tex</TT
>,
<TT
CLASS="FILENAME"
>.ltx</TT
>,
or
<TT
CLASS="FILENAME"
>.latex</TT
> input file).
The suffix specified by the <VAR
CLASS="ENVAR"
>$PDFSUFFIX</VAR
> construction variable
(<TT
CLASS="FILENAME"
>.pdf</TT
> by default)
is added automatically to the target
if it is not already present. Example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
># builds from aaa.tex
env.PDF(target = 'aaa.pdf', source = 'aaa.tex')
# builds bbb.pdf from bbb.dvi
env.PDF(target = 'bbb', source = 'bbb.dvi')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-POSTSCRIPT"
></A
><TT
CLASS="FUNCTION"
>PostScript()</TT
>, <TT
CLASS="FUNCTION"
>env.PostScript()</TT
></DT
><DD
><P
>Builds a <TT
CLASS="FILENAME"
>.ps</TT
> file
from a <TT
CLASS="FILENAME"
>.dvi</TT
> input file
(or, by extension, a <TT
CLASS="FILENAME"
>.tex</TT
>,
<TT
CLASS="FILENAME"
>.ltx</TT
>,
or
<TT
CLASS="FILENAME"
>.latex</TT
> input file).
The suffix specified by the <VAR
CLASS="ENVAR"
>$PSSUFFIX</VAR
> construction variable
(<TT
CLASS="FILENAME"
>.ps</TT
> by default)
is added automatically to the target
if it is not already present. Example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
># builds from aaa.tex
env.PostScript(target = 'aaa.ps', source = 'aaa.tex')
# builds bbb.ps from bbb.dvi
env.PostScript(target = 'bbb', source = 'bbb.dvi')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-PROGRAM"
></A
><TT
CLASS="FUNCTION"
>Program()</TT
>, <TT
CLASS="FUNCTION"
>env.Program()</TT
></DT
><DD
><P
>Builds an executable given one or more object files
or C, C++, D, or Fortran source files.
If any C, C++, D or Fortran source files are specified,
then they will be automatically
compiled to object files using the
<TT
CLASS="FUNCTION"
>Object</TT
>
builder method;
see that builder method's description for
a list of legal source file suffixes
and how they are interpreted.
The target executable file prefix
(specified by the <VAR
CLASS="ENVAR"
>$PROGPREFIX</VAR
> construction variable; nothing by default)
and suffix
(specified by the <VAR
CLASS="ENVAR"
>$PROGSUFFIX</VAR
> construction variable;
by default, <TT
CLASS="FILENAME"
>.exe</TT
> on Windows systems,
nothing on POSIX systems)
are automatically added to the target if not already present.
Example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.Program(target = 'foo', source = ['foo.o', 'bar.c', 'baz.f'])</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-RES"
></A
><TT
CLASS="FUNCTION"
>RES()</TT
>, <TT
CLASS="FUNCTION"
>env.RES()</TT
></DT
><DD
><P
>Builds a Microsoft Visual C++ resource file.
This builder method is only provided
when Microsoft Visual C++ or MinGW is being used as the compiler. The
<TT
CLASS="FILENAME"
>.res</TT
>
(or
<TT
CLASS="FILENAME"
>.o</TT
>
for MinGW) suffix is added to the target name if no other suffix is given.
The source
file is scanned for implicit dependencies as though it were a C file. Example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.RES('resource.rc')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-RMIC"
></A
><TT
CLASS="FUNCTION"
>RMIC()</TT
>, <TT
CLASS="FUNCTION"
>env.RMIC()</TT
></DT
><DD
><P
>Builds stub and skeleton class files
for remote objects
from Java <TT
CLASS="FILENAME"
>.class</TT
> files.
The target is a directory
relative to which the stub
and skeleton class files will be written.
The source can be the names of <TT
CLASS="FILENAME"
>.class</TT
> files,
or the objects return from the
<TT
CLASS="FUNCTION"
>Java</TT
>
builder method.</P
><P
>If the construction variable
<VAR
CLASS="ENVAR"
>$JAVACLASSDIR</VAR
>
is set, either in the environment
or in the call to the
<TT
CLASS="FUNCTION"
>RMIC</TT
>
builder method itself,
then the value of the variable
will be stripped from the
beginning of any <TT
CLASS="FILENAME"
>.class </TT
>
file names.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>classes = env.Java(target = 'classdir', source = 'src')
env.RMIC(target = 'outdir1', source = classes)
env.RMIC(target = 'outdir2',
source = ['package/foo.class', 'package/bar.class'])
env.RMIC(target = 'outdir3',
source = ['classes/foo.class', 'classes/bar.class'],
JAVACLASSDIR = 'classes')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-RPCGENCLIENT"
></A
><TT
CLASS="FUNCTION"
>RPCGenClient()</TT
>, <TT
CLASS="FUNCTION"
>env.RPCGenClient()</TT
></DT
><DD
><P
>Generates an RPC client stub (<TT
CLASS="FILENAME"
>_clnt.c</TT
>) file
from a specified RPC (<TT
CLASS="FILENAME"
>.x</TT
>) source file.
Because rpcgen only builds output files
in the local directory,
the command will be executed
in the source file's directory by default.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
># Builds src/rpcif_clnt.c
env.RPCGenClient('src/rpcif.x')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-RPCGENHEADER"
></A
><TT
CLASS="FUNCTION"
>RPCGenHeader()</TT
>, <TT
CLASS="FUNCTION"
>env.RPCGenHeader()</TT
></DT
><DD
><P
>Generates an RPC header (<TT
CLASS="FILENAME"
>.h</TT
>) file
from a specified RPC (<TT
CLASS="FILENAME"
>.x</TT
>) source file.
Because rpcgen only builds output files
in the local directory,
the command will be executed
in the source file's directory by default.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
># Builds src/rpcif.h
env.RPCGenHeader('src/rpcif.x')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-RPCGENSERVICE"
></A
><TT
CLASS="FUNCTION"
>RPCGenService()</TT
>, <TT
CLASS="FUNCTION"
>env.RPCGenService()</TT
></DT
><DD
><P
>Generates an RPC server-skeleton (<TT
CLASS="FILENAME"
>_svc.c</TT
>) file
from a specified RPC (<TT
CLASS="FILENAME"
>.x</TT
>) source file.
Because rpcgen only builds output files
in the local directory,
the command will be executed
in the source file's directory by default.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
># Builds src/rpcif_svc.c
env.RPCGenClient('src/rpcif.x')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-RPCGENXDR"
></A
><TT
CLASS="FUNCTION"
>RPCGenXDR()</TT
>, <TT
CLASS="FUNCTION"
>env.RPCGenXDR()</TT
></DT
><DD
><P
>Generates an RPC XDR routine (<TT
CLASS="FILENAME"
>_xdr.c</TT
>) file
from a specified RPC (<TT
CLASS="FILENAME"
>.x</TT
>) source file.
Because rpcgen only builds output files
in the local directory,
the command will be executed
in the source file's directory by default.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
># Builds src/rpcif_xdr.c
env.RPCGenClient('src/rpcif.x')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-SHAREDLIBRARY"
></A
><TT
CLASS="FUNCTION"
>SharedLibrary()</TT
>, <TT
CLASS="FUNCTION"
>env.SharedLibrary()</TT
></DT
><DD
><P
>Builds a shared library
(<TT
CLASS="FILENAME"
>.so</TT
> on a POSIX system,
<TT
CLASS="FILENAME"
>.dll</TT
> on WIN32)
given one or more object files
or C, C++, D or Fortran source files.
If any source files are given,
then they will be automatically
compiled to object files.
The static library prefix and suffix (if any)
are automatically added to the target.
The target library file prefix
(specified by the <VAR
CLASS="ENVAR"
>$SHLIBPREFIX</VAR
> construction variable;
by default, <TT
CLASS="FILENAME"
>lib</TT
> on POSIX systems,
nothing on Windows systems)
and suffix
(specified by the <VAR
CLASS="ENVAR"
>$SHLIBSUFFIX</VAR
> construction variable;
by default, <TT
CLASS="FILENAME"
>.dll</TT
> on Windows systems,
<TT
CLASS="FILENAME"
>.so</TT
> on POSIX systems)
are automatically added to the target if not already present.
Example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.SharedLibrary(target = 'bar', source = ['bar.c', 'foo.o'])</PRE
></TD
></TR
></TABLE
><P
>On WIN32 systems, the
<TT
CLASS="FUNCTION"
>SharedLibrary</TT
>
builder method will always build an import
(<TT
CLASS="FILENAME"
>.lib</TT
>) library
in addition to the shared (<TT
CLASS="FILENAME"
>.dll</TT
>) library,
adding a <TT
CLASS="FILENAME"
>.lib</TT
> library with the same basename
if there is not already a <TT
CLASS="FILENAME"
>.lib</TT
> file explicitly
listed in the targets.</P
><P
>Any object files listed in the
<TT
CLASS="LITERAL"
>source</TT
>
must have been built for a shared library
(that is, using the
<TT
CLASS="FUNCTION"
>SharedObject</TT
>
builder method).
<TT
CLASS="APPLICATION"
>scons</TT
>
will raise an error if there is any mismatch.</P
><P
>On WIN32 systems, specifying
<TT
CLASS="LITERAL"
>register=1</TT
>
will cause the <TT
CLASS="FILENAME"
>.dll</TT
> to be
registered after it is built using REGSVR32.
The command that is run
("regsvr32" by default) is determined by <VAR
CLASS="ENVAR"
>$REGSVR</VAR
> construction
variable, and the flags passed are determined by <VAR
CLASS="ENVAR"
>$REGSVRFLAGS</VAR
>. By
default, <VAR
CLASS="ENVAR"
>$REGSVRFLAGS</VAR
> includes the <VAR
CLASS="OPTION"
>/s</VAR
> option,
to prevent dialogs from popping
up and requiring user attention when it is run. If you change
<VAR
CLASS="ENVAR"
>$REGSVRFLAGS</VAR
>, be sure to include the <VAR
CLASS="OPTION"
>/s</VAR
> option.
For example,</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.SharedLibrary(target = 'bar',
source = ['bar.cxx', 'foo.obj'],
register=1)</PRE
></TD
></TR
></TABLE
><P
>will register <TT
CLASS="FILENAME"
>bar.dll</TT
> as a COM object
when it is done linking it.</P
></DD
><DT
><A
NAME="B-SHAREDOBJECT"
></A
><TT
CLASS="FUNCTION"
>SharedObject()</TT
>, <TT
CLASS="FUNCTION"
>env.SharedObject()</TT
></DT
><DD
><P
>Builds an object file for
inclusion in a shared library.
Source files must have one of the same set of extensions
specified above for the
<TT
CLASS="FUNCTION"
>StaticObject</TT
>
builder method.
On some platforms building a shared object requires additional
compiler option
(e.g. <VAR
CLASS="OPTION"
>-fPIC</VAR
> for gcc)
in addition to those needed to build a
normal (static) object, but on some platforms there is no difference between a
shared object and a normal (static) one. When there is a difference, SCons
will only allow shared objects to be linked into a shared library, and will
use a different suffix for shared objects. On platforms where there is no
difference, SCons will allow both normal (static)
and shared objects to be linked into a
shared library, and will use the same suffix for shared and normal
(static) objects.
The target object file prefix
(specified by the <VAR
CLASS="ENVAR"
>$SHOBJPREFIX</VAR
> construction variable;
by default, the same as <VAR
CLASS="ENVAR"
>$OBJPREFIX</VAR
>)
and suffix
(specified by the <VAR
CLASS="ENVAR"
>$SHOBJSUFFIX</VAR
> construction variable)
are automatically added to the target if not already present.
Examples:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.SharedObject(target = 'ddd', source = 'ddd.c')
env.SharedObject(target = 'eee.o', source = 'eee.cpp')
env.SharedObject(target = 'fff.obj', source = 'fff.for')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-STATICLIBRARY"
></A
><TT
CLASS="FUNCTION"
>StaticLibrary()</TT
>, <TT
CLASS="FUNCTION"
>env.StaticLibrary()</TT
></DT
><DD
><P
>Builds a static library given one or more object files
or C, C++, D or Fortran source files.
If any source files are given,
then they will be automatically
compiled to object files.
The static library prefix and suffix (if any)
are automatically added to the target.
The target library file prefix
(specified by the <VAR
CLASS="ENVAR"
>$LIBPREFIX</VAR
> construction variable;
by default, <TT
CLASS="FILENAME"
>lib</TT
> on POSIX systems,
nothing on Windows systems)
and suffix
(specified by the <VAR
CLASS="ENVAR"
>$LIBSUFFIX</VAR
> construction variable;
by default, <TT
CLASS="FILENAME"
>.lib</TT
> on Windows systems,
<TT
CLASS="FILENAME"
>.a</TT
> on POSIX systems)
are automatically added to the target if not already present.
Example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.StaticLibrary(target = 'bar', source = ['bar.c', 'foo.o'])</PRE
></TD
></TR
></TABLE
><P
>Any object files listed in the
<TT
CLASS="LITERAL"
>source</TT
>
must have been built for a static library
(that is, using the
<TT
CLASS="FUNCTION"
>StaticObject</TT
>
builder method).
<TT
CLASS="APPLICATION"
>scons</TT
>
will raise an error if there is any mismatch.</P
></DD
><DT
><A
NAME="B-STATICOBJECT"
></A
><TT
CLASS="FUNCTION"
>StaticObject()</TT
>, <TT
CLASS="FUNCTION"
>env.StaticObject()</TT
></DT
><DD
><P
>Builds a static object file
from one or more C, C++, D, or Fortran source files.
Source files must have one of the following extensions:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
> .asm assembly language file
.ASM assembly language file
.c C file
.C WIN32: C file
POSIX: C++ file
.cc C++ file
.cpp C++ file
.cxx C++ file
.cxx C++ file
.c++ C++ file
.C++ C++ file
.d D file
.f Fortran file
.F WIN32: Fortran file
POSIX: Fortran file + C pre-processor
.for Fortran file
.FOR Fortran file
.fpp Fortran file + C pre-processor
.FPP Fortran file + C pre-processor
.s assembly language file
.S WIN32: assembly language file
POSIX: assembly language file + C pre-processor
.spp assembly language file + C pre-processor
.SPP assembly language file + C pre-processor</PRE
></TD
></TR
></TABLE
><P
>The target object file prefix
(specified by the <VAR
CLASS="ENVAR"
>$OBJPREFIX</VAR
> construction variable; nothing by default)
and suffix
(specified by the <VAR
CLASS="ENVAR"
>$OBJSUFFIX</VAR
> construction variable;
<TT
CLASS="FILENAME"
>.obj</TT
> on Windows systems,
<TT
CLASS="FILENAME"
>.o</TT
> on POSIX systems)
are automatically added to the target if not already present.
Examples:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.StaticObject(target = 'aaa', source = 'aaa.c')
env.StaticObject(target = 'bbb.o', source = 'bbb.c++')
env.StaticObject(target = 'ccc.obj', source = 'ccc.f')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-TAR"
></A
><TT
CLASS="FUNCTION"
>Tar()</TT
>, <TT
CLASS="FUNCTION"
>env.Tar()</TT
></DT
><DD
><P
>Builds a tar archive of the specified files
and/or directories.
Unlike most builder methods,
the
<TT
CLASS="FUNCTION"
>Tar</TT
>
builder method may be called multiple times
for a given target;
each additional call
adds to the list of entries
that will be built into the archive.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.Tar('src.tar', 'src')
# Create the stuff.tar file.
env.Tar('stuff', ['subdir1', 'subdir2'])
# Also add "another" to the stuff.tar file.
env.Tar('stuff', 'another')
# Set TARFLAGS to create a gzip-filtered archive.
env = Environment(TARFLAGS = '-c -z')
env.Tar('foo.tar.gz', 'foo')
# Also set the suffix to .tgz.
env = Environment(TARFLAGS = '-c -z',
TARSUFFIX = '.tgz')
env.Tar('foo')</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-TYPELIBRARY"
></A
><TT
CLASS="FUNCTION"
>TypeLibrary()</TT
>, <TT
CLASS="FUNCTION"
>env.TypeLibrary()</TT
></DT
><DD
><P
>Builds a Windows type library (<TT
CLASS="FILENAME"
>.tlb</TT
>)
file from an input IDL file (<TT
CLASS="FILENAME"
>.idl</TT
>).
In addition, it will build the associated inteface stub and
proxy source files,
naming them according to the base name of the <TT
CLASS="FILENAME"
>.idl</TT
> file.
For example,</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.TypeLibrary(source="foo.idl")</PRE
></TD
></TR
></TABLE
><P
>Will create <TT
CLASS="FILENAME"
>foo.tlb</TT
>,
<TT
CLASS="FILENAME"
>foo.h</TT
>,
<TT
CLASS="FILENAME"
>foo_i.c</TT
>,
<TT
CLASS="FILENAME"
>foo_p.c</TT
>
and
<TT
CLASS="FILENAME"
>foo_data.c</TT
>
files.</P
></DD
><DT
><A
NAME="B-UIC"
></A
><TT
CLASS="FUNCTION"
>Uic()</TT
>, <TT
CLASS="FUNCTION"
>env.Uic()</TT
></DT
><DD
><P
>Builds a header file, an implementation file and a moc file from an ui file.
and returns the corresponding nodes in the above order.
This builder is only available after using the tool 'qt'. Note: you can
specify <TT
CLASS="FILENAME"
>.ui</TT
> files directly as source
files to the <TT
CLASS="FUNCTION"
>Program</TT
>,
<TT
CLASS="FUNCTION"
>Library</TT
> and <TT
CLASS="FUNCTION"
>SharedLibrary</TT
> builders
without using this builder. Using this builder lets you override the standard
naming conventions (be careful: prefixes are always prepended to names of
built files; if you don't want prefixes, you may set them to ``).
See the <VAR
CLASS="ENVAR"
>$QTDIR</VAR
> variable for more information.
Example:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.Uic('foo.ui') # -&#62; ['foo.h', 'uic_foo.cc', 'moc_foo.cc']
env.Uic(target = Split('include/foo.h gen/uicfoo.cc gen/mocfoo.cc'),
source = 'foo.ui') # -&#62; ['include/foo.h', 'gen/uicfoo.cc', 'gen/mocfoo.cc']</PRE
></TD
></TR
></TABLE
></DD
><DT
><A
NAME="B-ZIP"
></A
><TT
CLASS="FUNCTION"
>Zip()</TT
>, <TT
CLASS="FUNCTION"
>env.Zip()</TT
></DT
><DD
><P
>Builds a zip archive of the specified files
and/or directories.
Unlike most builder methods,
the
<TT
CLASS="FUNCTION"
>Zip</TT
>
builder method may be called multiple times
for a given target;
each additional call
adds to the list of entries
that will be built into the archive.</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="90%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>env.Zip('src.zip', 'src')
# Create the stuff.zip file.
env.Zip('stuff', ['subdir1', 'subdir2'])
# Also add "another" to the stuff.tar file.
env.Zip('stuff', 'another')</PRE
></TD
></TR
></TABLE
></DD
></DL
></DIV
></DIV
><DIV
CLASS="APPENDIX"
><HR><H1
><A
NAME="APP-TOOLS"
></A
>Tools</H1
><P
>&#13;This appendix contains descriptions of all of the
Tools that are
available "out of the box" in this version of SCons.&#13;</P
><P
></P
><DIV
CLASS="VARIABLELIST"
><DL
><DT
><A
NAME="T-386ASM"
></A
><TT
CLASS="LITERAL"
>386asm</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-AIXCXX"
></A
><TT
CLASS="LITERAL"
>aixc++</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-AIXCC"
></A
><TT
CLASS="LITERAL"
>aixcc</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-AIXF77"
></A
><TT
CLASS="LITERAL"
>aixf77</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-AIXLINK"
></A
><TT
CLASS="LITERAL"
>aixlink</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-AR"
></A
><TT
CLASS="LITERAL"
>ar</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-AS"
></A
><TT
CLASS="LITERAL"
>as</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-BCC32"
></A
><TT
CLASS="LITERAL"
>bcc32</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-BITKEEPER"
></A
><TT
CLASS="LITERAL"
>BitKeeper</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-CXX"
></A
><TT
CLASS="LITERAL"
>c++</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-CC"
></A
><TT
CLASS="LITERAL"
>cc</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-CVF"
></A
><TT
CLASS="LITERAL"
>cvf</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-CVS"
></A
><TT
CLASS="LITERAL"
>CVS</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-DEFAULT"
></A
><TT
CLASS="LITERAL"
>default</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-DMD"
></A
><TT
CLASS="LITERAL"
>dmd</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-DVIPDF"
></A
><TT
CLASS="LITERAL"
>dvipdf</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-DVIPS"
></A
><TT
CLASS="LITERAL"
>dvips</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-F77"
></A
><TT
CLASS="LITERAL"
>f77</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-F90"
></A
><TT
CLASS="LITERAL"
>f90</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-F95"
></A
><TT
CLASS="LITERAL"
>f95</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-FORTRAN"
></A
><TT
CLASS="LITERAL"
>fortran</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-GXX"
></A
><TT
CLASS="LITERAL"
>g++</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-G77"
></A
><TT
CLASS="LITERAL"
>g77</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-GAS"
></A
><TT
CLASS="LITERAL"
>gas</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-GCC"
></A
><TT
CLASS="LITERAL"
>gcc</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-GNULINK"
></A
><TT
CLASS="LITERAL"
>gnulink</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-GS"
></A
><TT
CLASS="LITERAL"
>gs</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-HPCXX"
></A
><TT
CLASS="LITERAL"
>hpc++</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-HPCC"
></A
><TT
CLASS="LITERAL"
>hpcc</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-HPLINK"
></A
><TT
CLASS="LITERAL"
>hplink</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-ICC"
></A
><TT
CLASS="LITERAL"
>icc</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-ICL"
></A
><TT
CLASS="LITERAL"
>icl</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-IFL"
></A
><TT
CLASS="LITERAL"
>ifl</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-IFORT"
></A
><TT
CLASS="LITERAL"
>ifort</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-ILINK"
></A
><TT
CLASS="LITERAL"
>ilink</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-ILINK32"
></A
><TT
CLASS="LITERAL"
>ilink32</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-INTELC"
></A
><TT
CLASS="LITERAL"
>intelc</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-JAR"
></A
><TT
CLASS="LITERAL"
>jar</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-JAVAC"
></A
><TT
CLASS="LITERAL"
>javac</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-JAVAH"
></A
><TT
CLASS="LITERAL"
>javah</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-LATEX"
></A
><TT
CLASS="LITERAL"
>latex</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-LEX"
></A
><TT
CLASS="LITERAL"
>lex</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-LINK"
></A
><TT
CLASS="LITERAL"
>link</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-LINKLOC"
></A
><TT
CLASS="LITERAL"
>linkloc</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-M4"
></A
><TT
CLASS="LITERAL"
>m4</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-MASM"
></A
><TT
CLASS="LITERAL"
>masm</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-MIDL"
></A
><TT
CLASS="LITERAL"
>midl</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-MINGW"
></A
><TT
CLASS="LITERAL"
>mingw</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-MSLIB"
></A
><TT
CLASS="LITERAL"
>mslib</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-MSLINK"
></A
><TT
CLASS="LITERAL"
>mslink</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-MSVC"
></A
><TT
CLASS="LITERAL"
>msvc</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-MSVS"
></A
><TT
CLASS="LITERAL"
>msvs</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-MWCC"
></A
><TT
CLASS="LITERAL"
>mwcc</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-MWLD"
></A
><TT
CLASS="LITERAL"
>mwld</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-NASM"
></A
><TT
CLASS="LITERAL"
>nasm</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-PDFLATEX"
></A
><TT
CLASS="LITERAL"
>pdflatex</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-PDFTEX"
></A
><TT
CLASS="LITERAL"
>pdftex</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-PERFORCE"
></A
><TT
CLASS="LITERAL"
>Perforce</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-QT"
></A
><TT
CLASS="LITERAL"
>qt</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-RCS"
></A
><TT
CLASS="LITERAL"
>RCS</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-RMIC"
></A
><TT
CLASS="LITERAL"
>rmic</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-RPCGEN"
></A
><TT
CLASS="LITERAL"
>rpcgen</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-SCCS"
></A
><TT
CLASS="LITERAL"
>SCCS</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-SGIAR"
></A
><TT
CLASS="LITERAL"
>sgiar</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-SGICXX"
></A
><TT
CLASS="LITERAL"
>sgic++</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-SGICC"
></A
><TT
CLASS="LITERAL"
>sgicc</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-SGILINK"
></A
><TT
CLASS="LITERAL"
>sgilink</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-SUBVERSION"
></A
><TT
CLASS="LITERAL"
>Subversion</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-SUNAR"
></A
><TT
CLASS="LITERAL"
>sunar</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-SUNCXX"
></A
><TT
CLASS="LITERAL"
>sunc++</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-SUNCC"
></A
><TT
CLASS="LITERAL"
>suncc</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-SUNLINK"
></A
><TT
CLASS="LITERAL"
>sunlink</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-SWIG"
></A
><TT
CLASS="LITERAL"
>swig</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-TAR"
></A
><TT
CLASS="LITERAL"
>tar</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-TEX"
></A
><TT
CLASS="LITERAL"
>tex</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-TLIB"
></A
><TT
CLASS="LITERAL"
>tlib</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-YACC"
></A
><TT
CLASS="LITERAL"
>yacc</TT
></DT
><DD
><P
>XXX</P
></DD
><DT
><A
NAME="T-ZIP"
></A
><TT
CLASS="LITERAL"
>zip</TT
></DT
><DD
><P
>XXX</P
></DD
></DL
></DIV
></DIV
><DIV
CLASS="APPENDIX"
><HR><H1
><A
NAME="APP-TASKS"
></A
>Handling Common Tasks</H1
><P
>There is a common set of simple tasks that many build configurations rely
on as they become more complex. Most build tools have special
purpose constructs for performing these tasks, but since <TT
CLASS="FILENAME"
>SConscript</TT
>
files are <TT
CLASS="APPLICATION"
>Python</TT
> scripts, you can use more flexible built-in <TT
CLASS="APPLICATION"
>Python</TT
>
services to perform these tasks. This appendix lists a number of these
tasks and how to implement them in <TT
CLASS="APPLICATION"
>Python</TT
>.</P
><DIV
CLASS="EXAMPLE"
><A
NAME="AEN6148"
></A
><P
><B
>Example 1. Wildcard globbing to create a list of filenames</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>import glob
files = glob.glob(wildcard)</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="EXAMPLE"
><A
NAME="AEN6151"
></A
><P
><B
>Example 2. Filename extension substitution</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>import os.path
filename = os.path.splitext(filename)[0]+extension</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="EXAMPLE"
><A
NAME="AEN6154"
></A
><P
><B
>Example 3. Appending a path prefix to a list of filenames</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>import os.path
filenames = [os.path.join(prefix, x) for x in filenames]</PRE
></TD
></TR
></TABLE
><P
>or in Python 1.5.2:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>import os.path
new_filenames = []
for x in filenames:
new_filenames.append(os.path.join(prefix, x))</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="EXAMPLE"
><A
NAME="AEN6159"
></A
><P
><B
>Example 4. Substituting a path prefix with another one</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>if filename.find(old_prefix) == 0:
filename = filename.replace(old_prefix, new_prefix)</PRE
></TD
></TR
></TABLE
><P
>or in Python 1.5.2:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>import string
if string.find(filename, old_prefix) == 0:
filename = string.replace(filename, old_prefix, new_prefix) </PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="EXAMPLE"
><A
NAME="AEN6164"
></A
><P
><B
>Example 5. Filtering a filename list to exclude/retain only a specific set
of extensions</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>import os.path
filenames = [x for x in filenames if os.path.splitext(x)[1] in extensions]</PRE
></TD
></TR
></TABLE
><P
>or in Python 1.5.2:</P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>import os.path
new_filenames = []
for x in filenames:
if os.path.splitext(x)[1] in extensions:
new_filenames.append(x)</PRE
></TD
></TR
></TABLE
></DIV
><DIV
CLASS="EXAMPLE"
><A
NAME="AEN6169"
></A
><P
><B
>Example 6. The "backtick function": run a shell command and capture the
output</B
></P
><TABLE
BORDER="0"
BGCOLOR="#E0E0E0"
WIDTH="100%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>import os
output = os.popen(command).read()</PRE
></TD
></TR
></TABLE
></DIV
></DIV
></DIV
><H3
CLASS="FOOTNOTES"
>Notes</H3
><TABLE
BORDER="0"
CLASS="FOOTNOTES"
WIDTH="100%"
><TR
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="5%"
><A
NAME="FTN.AEN380"
HREF="#AEN380"
><SPAN
CLASS="footnote"
>[1]</SPAN
></A
></TD
><TD
ALIGN="LEFT"
VALIGN="TOP"
WIDTH="95%"
><P
>In programming parlance,
the <TT
CLASS="FILENAME"
>SConstruct</TT
> file is
<I
CLASS="EMPHASIS"
>declarative</I
>,
meaning you tell <TT
CLASS="APPLICATION"
>SCons</TT
> what you want done
and let it figure out the order in which to do it,
rather than strictly <I
CLASS="EMPHASIS"
>imperative</I
>,
where you specify explicitly the order in
which to do things.
</P
></TD
></TR
></TABLE
></BODY
></HTML
>