30070 lines
500 KiB
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 © 2004 Steven Knight</P
|
|
><DIV
|
|
CLASS="LEGALNOTICE"
|
|
><P
|
|
></P
|
|
><A
|
|
NAME="AEN12"
|
|
></A
|
|
><A
|
|
NAME="AEN13"
|
|
></A
|
|
><BLOCKQUOTE
|
|
CLASS="BLOCKQUOTE"
|
|
><P
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> The best way to contact people involved with SCons,
|
|
including the author,
|
|
is through the SCons mailing lists.
|
|
|
|
</P
|
|
><P
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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.
|
|
>>> <KBD
|
|
CLASS="USERINPUT"
|
|
>^D</KBD
|
|
>
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> And on a Windows system with Python installed:
|
|
|
|
</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
> C:\><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.
|
|
>>> <KBD
|
|
CLASS="USERINPUT"
|
|
>^Z</KBD
|
|
>
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> The <TT
|
|
CLASS="PROMPT"
|
|
>>>></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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> Debian Linux systems use a different package management
|
|
format that also makes it very easy to install <TT
|
|
CLASS="APPLICATION"
|
|
>SCons</TT
|
|
>.
|
|
|
|
</P
|
|
><P
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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:\><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
|
|
> 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
|
|
> 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
|
|
> (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
|
|
> 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
|
|
> 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
|
|
> 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:\><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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> And the output on Windows looks like:
|
|
|
|
</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
> C:\><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:\><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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <TT
|
|
CLASS="APPLICATION"
|
|
>SCons</TT
|
|
> reflects this distinction between
|
|
<I
|
|
CLASS="EMPHASIS"
|
|
>calling a builder method like</I
|
|
> <TT
|
|
CLASS="FUNCTION"
|
|
>Program</TT
|
|
>>
|
|
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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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:\><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
|
|
> 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
|
|
> 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:\><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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> (<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
|
|
> 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
|
|
> 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:\><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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> Or on Windows:
|
|
|
|
</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
> C:\><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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> (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
|
|
> 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
|
|
> 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
|
|
> (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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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:\><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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> And the output on Windows:
|
|
|
|
</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
> C:\><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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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:\><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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> (Note that Python requires that the backslash
|
|
separators in a Windows path name
|
|
be escaped within strings.)
|
|
|
|
</P
|
|
><P
|
|
> 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
|
|
> 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:\><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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> And on Windows:
|
|
|
|
</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
> C:\><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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> And the following file names on a Windows system:
|
|
|
|
</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
> C:\><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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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 <hello.h>
|
|
int
|
|
main()
|
|
{
|
|
printf("Hello, %s!\n", string);
|
|
}
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> And like this on Windows:
|
|
|
|
</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
> C:\><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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> And on Win32:
|
|
|
|
</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
> C:\><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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> (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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> (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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> (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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> Will display the completely help text on Windows:
|
|
|
|
</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
> C:\><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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> (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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> (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
|
|
> 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
|
|
> 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
|
|
> (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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> (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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> The same SConstruct file on Windows would build:
|
|
|
|
</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
> C:\><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
|
|
> 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
|
|
> 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 < $SOURCE > $TARGET')
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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
|
|
> 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 < $SOURCE > $TARGET')
|
|
env = Environment(BUILDERS = {'Foo' : bld})
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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
|
|
> 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 < file.input > file.foo
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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 < $SOURCE > $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
|
|
> 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 < $SOURCE > $TARGET')
|
|
env.Append(BUILDERS = {'Foo' : bld})
|
|
env.Foo('file.foo', 'file.input')
|
|
env.Program('hello.c')
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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 < $SOURCE > $TARGET')
|
|
env['BUILDERS']['Foo'] = bld
|
|
env.Foo('file.foo', 'file.input')
|
|
env.Program('hello.c')
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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 < file.input > 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
|
|
> 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 < $SOURCE > $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 < file1.input > file1.foo
|
|
foobuild < file2.input > file2.foo
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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
|
|
> 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
|
|
> The arguments of a <TT
|
|
CLASS="LITERAL"
|
|
>builder function</TT
|
|
> are:
|
|
|
|
</P
|
|
><P
|
|
></P
|
|
><DIV
|
|
CLASS="VARIABLELIST"
|
|
><DL
|
|
><DT
|
|
>target</DT
|
|
><DD
|
|
><P
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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 < %s > %s' % (target[0], source[0])
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> The arguments of a <TT
|
|
CLASS="LITERAL"
|
|
>generator</TT
|
|
> are:
|
|
|
|
</P
|
|
><P
|
|
></P
|
|
><DIV
|
|
CLASS="VARIABLELIST"
|
|
><DL
|
|
><DT
|
|
>source</DT
|
|
><DD
|
|
><P
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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 < %s > %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 < file.input > file.foo
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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
|
|
> <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
|
|
> 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/' < $SOURCE > $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/' < foo.in > foo.out
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> An optional argument that you can choose to
|
|
have passed to this scanner function by
|
|
various scanner instances.
|
|
|
|
</P
|
|
></DD
|
|
></DL
|
|
></DIV
|
|
><P
|
|
> 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
|
|
> 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 < $SOURCES > $TARGET')
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
></DIV
|
|
></DIV
|
|
><DIV
|
|
CLASS="CHAPTER"
|
|
><HR><H1
|
|
><A
|
|
NAME="CHAP-REPOSITORIES"
|
|
></A
|
|
>Building From Code Repositories</H1
|
|
><P
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> </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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> (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
|
|
> <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
|
|
> 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
|
|
> <TT
|
|
CLASS="APPLICATION"
|
|
>SCons</TT
|
|
> provides a number of basic checks,
|
|
as well as a mechanism for adding your own custom checks.
|
|
|
|
</P
|
|
><P
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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 <sys/types.h>\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
|
|
> 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 <mylib.h>
|
|
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
|
|
> 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
|
|
> (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
|
|
> 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
|
|
> 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
|
|
> 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 <mylib.h>
|
|
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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> <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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> (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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> 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': <SCons.Defaults.Variable_Method_Caller instance at 0x829dcb4>,
|
|
'ENV': {'PATH': '/usr/local/bin:/bin:/usr/bin'},
|
|
'ESCAPE': <function escape at 0x837d2a4>,
|
|
'File': <SCons.Defaults.Variable_Method_Caller instance at 0x829e0fc>,
|
|
'IDLSUFFIXES': ['.idl', '.IDL'],
|
|
'INSTALL': <function copyFunc at 0x829db9c>,
|
|
'LIBPREFIX': 'lib',
|
|
'LIBPREFIXES': '$LIBPREFIX',
|
|
'LIBSUFFIX': '.a',
|
|
'LIBSUFFIXES': ['$LIBSUFFIX', '$SHLIBSUFFIX'],
|
|
'OBJPREFIX': '',
|
|
'OBJSUFFIX': '.o',
|
|
'PDFPREFIX': '',
|
|
'PDFSUFFIX': '.pdf',
|
|
'PLATFORM': 'posix',
|
|
'PROGPREFIX': '',
|
|
'PROGSUFFIX': '',
|
|
'PSPAWN': <function piped_env_spawn at 0x837d384>,
|
|
'PSPREFIX': '',
|
|
'PSSUFFIX': '.ps',
|
|
'RDirs': <SCons.Defaults.Variable_Method_Caller instance at 0x829e46c>,
|
|
'SCANNERS': [],
|
|
'SHELL': 'sh',
|
|
'SHLIBPREFIX': '$LIBPREFIX',
|
|
'SHLIBSUFFIX': '.so',
|
|
'SHOBJPREFIX': '$OBJPREFIX',
|
|
'SHOBJSUFFIX': '$OBJSUFFIX',
|
|
'SPAWN': <function spawnvpe_spawn at 0x8377fdc>,
|
|
'TEMPFILE': <class SCons.Defaults.NullCmdGenerator at 0x829ddec>,
|
|
'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': <function _concat at 0x829dc0c>,
|
|
'_defines': <function _defines at 0x829dc7c>,
|
|
'_stripixes': <function _stripixes at 0x829dc44>}
|
|
scons: done reading SConscript files.
|
|
scons: Building targets ...
|
|
scons: `.' is up to date.
|
|
scons: done building targets.
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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:\><KBD
|
|
CLASS="USERINPUT"
|
|
>scons</KBD
|
|
>
|
|
scons: Reading SConscript files ...
|
|
{ 'BUILDERS': {'Object': <SCons.Memoize.MultiStepBuilder object at 0x83493e4>, 'SharedObject': <SCons.Memoize.MultiStepBuilder object at 0x8349fec>, 'StaticObject': <SCons.Memoize.MultiStepBuilder object at 0x83493e4>, 'PCH': <SCons.Memoize.BuilderBase object at 0x83418cc>, 'RES': <SCons.Memoize.BuilderBase object at 0x8367cec>},
|
|
'CC': 'cl',
|
|
'CCCOM': <SCons.Memoize.FunctionAction object at 0x8340454>,
|
|
'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': <SCons.Defaults.Variable_Method_Caller instance at 0x829dcb4>,
|
|
'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': <function <lambda> at 0x82339ec>,
|
|
'File': <SCons.Defaults.Variable_Method_Caller instance at 0x829e0fc>,
|
|
'IDLSUFFIXES': ['.idl', '.IDL'],
|
|
'INCPREFIX': '/I',
|
|
'INCSUFFIX': '',
|
|
'INSTALL': <function copyFunc at 0x829db9c>,
|
|
'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': <function piped_spawn at 0x8372bc4>,
|
|
'PSPREFIX': '',
|
|
'PSSUFFIX': '.ps',
|
|
'RC': 'rc',
|
|
'RCCOM': '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES',
|
|
'RCFLAGS': [],
|
|
'RDirs': <SCons.Defaults.Variable_Method_Caller instance at 0x829e46c>,
|
|
'SCANNERS': [],
|
|
'SHCC': '$CC',
|
|
'SHCCCOM': <SCons.Memoize.FunctionAction object at 0x83494bc>,
|
|
'SHCCFLAGS': ['$CCFLAGS'],
|
|
'SHCXX': '$CXX',
|
|
'SHCXXCOM': '$SHCXX $SHCXXFLAGS $CCCOMFLAGS',
|
|
'SHCXXFLAGS': ['$CXXFLAGS'],
|
|
'SHELL': None,
|
|
'SHLIBPREFIX': '',
|
|
'SHLIBSUFFIX': '.dll',
|
|
'SHOBJPREFIX': '$OBJPREFIX',
|
|
'SHOBJSUFFIX': '$OBJSUFFIX',
|
|
'SPAWN': <function spawn at 0x8374c34>,
|
|
'STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME': 1,
|
|
'TEMPFILE': <class SCons.Platform.win32.TempFileMunge at 0x835edc4>,
|
|
'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': <function _concat at 0x829dc0c>,
|
|
'_defines': <function _defines at 0x829dc7c>,
|
|
'_stripixes': <function _stripixes at 0x829dc44>}
|
|
scons: done reading SConscript files.
|
|
scons: Building targets ...
|
|
scons: `.' is up to date.
|
|
scons: done building targets.
|
|
</PRE
|
|
></TD
|
|
></TR
|
|
></TABLE
|
|
><P
|
|
> 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
|
|
> 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
|
|
> 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
|
|
> And the following when executed on a Windows system:
|
|
|
|
</P
|
|
><TABLE
|
|
BORDER="0"
|
|
BGCOLOR="#E0E0E0"
|
|
WIDTH="100%"
|
|
><TR
|
|
><TD
|
|
><PRE
|
|
CLASS="SCREEN"
|
|
> C:\><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
|
|
> 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. </P
|
|
><P
|
|
> 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. </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 <Fmwk/Header.h>.
|
|
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 -> %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
|
|
> 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. </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') # -> ['foo.h', 'uic_foo.cc', 'moc_foo.cc']
|
|
env.Uic(target = Split('include/foo.h gen/uicfoo.cc gen/mocfoo.cc'),
|
|
source = 'foo.ui') # -> ['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
|
|
> This appendix contains descriptions of all of the
|
|
Tools that are
|
|
available "out of the box" in this version of SCons. </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
|
|
> |