![]() |
|
|||
Copyright (c) 2000 Steven Knight. This material may
be distributed only subject to the terms and conditions set forth in
the Software Carpentry Open Publication License, which is available at:
|
Most of the ideas in sccons originate with Cons, a Perl-based software construction utility that has been in use by a small but growing community since its development by Bob Sidebotham at Fore Systems in 1996. The author of this proposal is currently a principal maintainer of Cons.
Cons was originally designed to handle complicated software build problems (multiple directories, variant builds) while keeping the input files simple and maintainable. The general philosophy is that the build tool should ``do the right thing'' with minimal input from an unsophisticated user, while still providing a rich set of underlying functionality for more complicated software construction tasks needed by experts.
I've used the name sccons to distinguish this design from the already-available Perl implementation of Cons, and knowing that the actual name of the tool isn't important and should change to reflect some common naming with other Software Carpentry tools.
sccons reads one or more configuration files that specify target files to be built and rules for building those files. Common build rules are available by default and need not be explicitly specified in the configuration files.
The default configuration file read by sccons is named Construct. A -f
command-line option exists to read a different file name.
Additional configuration files read by sccons are specified explicitly via
the Include
method:
Include('other_file')
Inclusion is recursive; an included configuration file may in turn
Include
other configuration files.
By convention, subsidiary configuration files in subdirectories are named Conscript:
Include('src/Conscript')
When a subsidiary configuration file is read from a subdirectory, all of that configuration file's targets and build rules are interpreted relative to that directory (as if sccons had changed its working directory to that subdirectory). This allows for easy support of hierarchical builds of directory trees for large projects.
sccons configuration files are simply Python scripts that invoke methods to specify target files to be built, rules for building the target files, and dependencies.
The following minimal example builds the 'hello' program from the 'hello.c' source file:
Environment().Make('hello', 'hello.c')
(Details about the construction Environment
class are explained below.)
Users are not required to understand intermediate steps involved in generating a file--for example, the distinction between compiling source code into an object file, and then linking object files into an executable. The details of intermediate steps are handled by the invoked method. Users that need to, however, can specify intermediate steps explicitly:
env = Environment() env.Make('hello.o', 'hello.c') env.Make('hello', 'hello.o')
The env.Make
method understands the file suffixes specified and ``does the right thing''
to generate the target object and program files, respectively.
Multiple input files that go into creating a target file are passed in as an array:
env.Make('foo.a', ['aaa.c', 'bbb.c', 'ccc.c']) env.Make('bar', ['xxx.c', 'yyy.o', 'foo.a'])
Conversely, the generated target may be an array of multiple files that are created or updated simultaneously by the method:
env.Make(['grammar.o', 'y.tab.h'], 'grammar.y')
Because sccons configuration files are Python scripts, normal Python syntax can be used to generate or manipulate lists of targets or dependencies:
sources = ['aaa.c', 'bbb.c', 'ccc.c'] env.Make('bar', sources)
Python flow-control can be used to iterate through invocations of build rules:
objects = ['aaa.o', 'bbb.o', 'ccc.o'] for obj in objects: src = replace(obj, '.o', '.c') env.Make(obj, src)
or to handle more complicated conditional invocations:
# only build 'foo' on Linux systems if sys.platform == 'linux1': env.Make('foo', 'foo.c')
sccons needs a way to pass variables explicitly from a parent configuration
file to an Include
d Conscript file. This is necessary to allow an environment defined in one Construct or
Conscript file to be used in the subsidiary files as well.
I do not know enough about Python name spaces to be able to suggest an appropriate interface, but am confident that one can be invented.
sccons uses construction environments to control the build process. A
construction environment is an object with methods for determining
dependencies and generating target files, and a dictionary of values used
by the methods. Passing no arguments to the Environment
instantiation creates a construction environment with default values for
the current platform:
env = Environment()
The default construction environment values may be overridden when an environment is created:
env = Environment( CC = 'gcc', CCFLAGS = '-g', CPPPATH = ['.', 'src', '/usr/include'], LIBPATH = ['/usr/lib', '.'])
A method exists to return a copy of an existing environment, with any overridden values specified as keyword arguments to the method:
env = Environment() debug = env.Copy( CCFLAGS = '-g' )
A method exists to return just the dictionary of construction environment variables:
env = Environment() dict = env.Dictionary()
Different target files often require different build characteristics. sccons supports the use of multiple construction environments, each with different values:
env = Environment( CCFLAGS = '', ) debug = Environment( CCFLAGS = '-g', ) env.Make('hello', 'hello.c') debug.Make('hello-debug', 'hello.c')
Dictionaries of values from multiple environments may be passed to the
Environment
instantiation or the Copy
method, in which case the last-specified dictionary value wins:
env1 = Environment( CCFLAGS = '-O', LDFLAGS = '-d' ) env2 = Environment( CCFLAGS = '-g' ) new = Environment(env1.Dictionary(), env2.Dictionary())
The new
environment in the above example retains LDFLAGS =
'-d'
from the env1
environment, and CCFLAGS = '-g'
from the
env2
environment.
Construction environments may be imported from a central, shared repository using normal Python syntax:
from LocalEnvironments import optimized, debug
optimized.Make('foo', 'foo.c') debug.Make('foo-d', 'foo.c')
The expectation is that some local tool-master, integrator or administrator
will be responsible for assembling environments (creating the Builder
objects that specify the tools, options, etc.) and make these available for
sharing by all users.
The modules containing shared construction environments (LocalEnvironments in the above example) can be checked in and controlled with the rest of the source files. This allows a project to track the combinations of tools and command-line options that work on different platforms, at different times, and with different tool versions, by using already-familiar revision control tools.
The env.Make
method already introduced is a specific case of a
Builder
object. By default, sccons also supplies (and uses) some additional Builder
objects:
Object compile or assemble an object file Library archive files into a library SharedLibrary archive files into a shared library Program link objects and/or libraries into an executable
A construction environment can be explicitly initialized with associated
Builder
objects that will be bound to the environment object:
env = Environment(BUILDERS = ['Object', 'Program'])
Builder
objects bound to a construction environment can be used directly:
env.Object('hello.o', 'hello.c') env.Library('libfoo.a', ['aaa.c', 'bbb.c']) env.SharedLibrary('libbar.so', ['xxx.c', 'yyy.c']) env.Program('hello', ['hello.o', 'libfoo.a', 'libbar.so'])
Users can define additional Builder
objects for specific file types unknown to sccons:
WebPage = Builder(command = 'htmlgen %HTMLGENFLAGS %< > %>') OtherBuilder = Builder(command = '%OTHERTOOL < %< > %>', input_suffixes = ['.in', '.input'])
User-defined Builder
objects can be used like the default
Builder
objects to initialize construction environments.
A Builder
object must be initialized with the command line to be invoked to build the
target file. The command-line specification can interpolate variables from
the construction environment; see ``Variable substitution,'' below.
A Builder
object may optionally be initialized with a list of the expected suffixes
of input files for this object. This list is used in automatic dependency
analysis.
Typically, Builder
objects will be supplied by a tool-master or administrator through a shared
construction environment.
The env.Make
method ``does the right thing'' to build different file types because it
uses a construction-environment dictionary that maps file suffixes to the
appropriate Builder
object. This
BUILDERMAP
can be initialized at instantiation:
env = Environment( BUILDERMAP = { '.o' : Object, '.a' : Library, '.html' : WebPage, '' : Program, } )
With the BUILDERMAP
properly initialized, the env.Make
method can be used to build additional file types:
env.Make('index.html', 'index.input')
Builder
objects referenced in the BUILDERMAP
do not need to be listed separately in the BUILDERS
variable. The construction environment will bind the union of the Builder
objects listed in both variables.
A method exists to associate a target file with a specific command or list of commands for building the file:
env.Command('foo.out', 'foo.in', "foo.process %< > %>")
commands = [ "bar.process -o .tmpfile %<", "mv .tmpfile %>" ] env.Command('bar.out', 'bar.in', commands)
This is useful when it's too cumbersome to create a Builder
object just to build a single file in a special way.
Within a construction command, any variable from the construction
environment may be interpolated by prefixing the name of the construction
with %
:
XXBuilder = Builder( command = "%XX %XXFLAGS -c %< -o %>" )
env.Command('bar.out', 'bar.in', "sed '1d' < %< > %>" )
Variable substitution is recursive: the command line is expanded until no more substitutions can be made.
If a referenced variable is not defined in the construction environment, the null string is interpolated.
The following special variables can also be used:
The target file name. If multiple targets are specified in an array, expands to only the first target in the list.
All target file names. If multiple targets are specified in an array, expands to the entire list of targets.
Individual input file names, expanding to the first, second, third, etc. input file, respectively.
All input file names. Any input file names that are used anywhere else on
the current command line (via %1
, %2
, etc.) are removed from the expanded list.
Any of the above special variables may be followed immediately by one of the following suffixes to select just a portion of the expanded path name:
basename; the directory plus the file name less any file suffix
the directory
the file name
the file name suffix
the file name less any file suffix
By default, sccons assumes that a target file automatically has dependencies on the:
tool used to build the target file
contents of the input files
command line used to build the target file
If any of these changes, the target file will be rebuilt.
Additionally, sccons can scan the contents of files for implicit
dependencies. For example, sccons will scan the contents of a
.c file and determine that any object created from it is dependent on any .h
files specified via #include
. sccons, therefore, ``does the right thing'' without needing to have these
dependencies listed explicitly:
% cat Construct env = Environment() env.Program('hello', 'hello.c') % cat hello.c #include "hello_string.h" main() { printf("%s\n", STRING); } % cat > hello_string.h #define STRING "Hello, world!\n" % sccons . gcc -c hello.c -o hello.o gcc -o hello hello.c % ./hello Hello, world! % cat > hello_string.h #define STRING "Hello, world, hello!\n" % sccons . gcc -c hello.c -o hello.o gcc -o hello hello.c % ./hello Hello, world, hello! %
Undesirable automatically-generated or implicit dependencies may be ignored:
env.Program('bar', 'bar.c') Ignore('bar', '/usr/bin/gcc', 'version.h')
In the above example, the bar
program will not be rebuilt if the
/usr/bin/gcc compiler or the version.h file change.
Dependencies that are unknown to sccons may be specified explicitly in an sccons configuration file:
Dependency('output', ['input_1', 'input_2']) Dependency(['output_a', 'output_b'], 'input_2')
A dependency on an sccons configuration file itself may be specified explicitly to force a rebuild whenever the configuration file changes:
Dependency('archive.tar.gz', 'Construct')
Analagous to the previously-described Builder
objects, sccons supplies (and uses) Scanner
objects to search the contents of a file for implicit dependency files:
CScan scan .{c,C,cc,cxx,cpp} files for #include dependencies
A construction environment can be explicitly initialized with associated Scanner
objects:
env = Environment(SCANNERS = ['CScan', 'M4Scan'])
Scanner
objects bound to a construction environment can be associated directly with
specified files:
env.CScan('foo.c', 'bar.c') env.M4Scan('input.m4')
A user may define a Scanner
object to scan a type of file for implicit dependencies:
def scanner1(line): # search for dependencies return dependency_list
FirstScan = Scanner(scanner1)
The scanner function is passed each line of text in the file or files, and must return a list of dependencies that it finds based on analyzing the line.
Additional arguments may be specified when the Scanner
object is created. When the scanner is invoked, these additional arguments
will be expanded using environment-variable substitution and passed to the
scanner function. This can be used to pass in a search paths that the
scanner will use when trying to find dependency files:
def scanner2(line, path): # search for dependencies, using directories in 'path' return dependency_list
SecondScan = Scanner(scanner2, '%SCANNERPATH')
Typically, Scanner
objects will be supplied by a tool-master or administrator through a shared
construction environment.
Each construction environment has a SCANNERMAP
, a dictionary that associates different file suffixes with a scanner
object that can be used to generate a list of dependencies from the
contents of that file. This SCANNERMAP
can be initialized at instantiation:
env = Environment( SCANNERMAP = { '.c' : CScan, '.cc' : CScan, '.m4' : M4Scan, } )
Scanner
objects referenced in the SCANNERMAP
do not need to be listed separately in the SCANNERS
variable. The construction environment will bind the union of the Scanner
objects listed in both variables.
By default, sccons explicitly removes a target file before invoking the
command(s)
to build it.
Files that should not be removed before rebuilding can be specified via the Precious
method:
env.Library('libfoo.a', ['aaa.c', 'bbb.c', 'ccc.c']) Precious('libfoo.a')
The user may specify default targets that will be built if there are no targets supplied on the command line:
Default('install', 'src')
Multiple calls to the Default
method (typically one per Conscript
file) append their arguments to the list of default targets.
Files may be installed in a destination directory:
env.Install('/usr/bin', 'program1', 'program2')
Files may be renamed on installation:
env.InstallAs('/usr/bin/xyzzy', 'xyzzy.in') env.InstallAs(['/usr/bin/foo', '/usr/bin/bar'], ['foo.in', 'bar.in'])
sccons allows target files to be built completely separately from the source files by ``linking'' a build directory to an underlying source directory:
LinkDir('build', 'src')
Include('build/Conscript')
sccons will copy (or hard link) necessary files (including the Conscript file) into the build directory hierarchy. This allows the source directory to remain uncluttered by derived files.
The LinkDir
method may be used in conjunction with multiple construction environments
to support variant builds. The following
Construct and Conscript files would build separate debug and production versions of the same
program side-by-side:
% cat Construct LinkDir('build/debug', 'src') LinkDir('build/production', 'src') flags = '-g' Include('build/debug/Conscript') flags = '-O' Include('build/production/Conscript') % cat src/Conscript env = Environment( CCFLAGS = flags ) env.Program('hello', 'hello.c')
The following example would build the appropriate program for the current compilation platform, without having to clean any directories of object or executable files for other architectures:
% cat Construct build_platform = 'build/' + sys.platform LinkDir(build_platform, 'src') Include(build_platform + '/Conscript') % cat src/Conscript env = Environment env.Program('hello', 'hello.c')
sccons may use files from one or more shared code repositories in order to build local copies of changed target files. A repository would typically be a central directory tree, maintained by an integrator, with known good libraries and executables.
Repository('/home/source/1.1', '/home/source/1.0')
Specified repositories will be searched in-order for any file
(configuration file, input file, target file) that does not exist in the
local directory tree. When building a local target file, sccons will
rewrite path names in the build command to use the necessary repository
files. This includes modifying lists of -I
or -L
flags to specify an appropriate set of include paths for dependency
analysis.
sccons will modify the Python sys.path
variable to reflect the addition of repositories to the search path, so
that any imported modules or packages necessary for the build can be found
in a repository, as well.
If an up-to-date target file is found in a code repository, the file will not be rebuilt or copied locally. Files that must exist locally (for testing, e.g.) may be specified:
Local('program', 'libfoo.a')
in which case sccons will copy or link an up-to-date copy of the file from the appropriate repository.
sccons can maintain a cache directory of target files which may be shared among multiple builds. This reduces build times by allowing developers working on a project together to share common target files:
Cache('/var/tmp/build.cache/i386')
When a target file is generated, a copy is added to the cache. When generating a target file, if sccons determines that a file that has been built with the exact same dependencies already exists in the specified cache, sccons will copy the cached file rather than re-building the target.
Command-line options exist to modify the sccons caching behavior for a specific build, including disabling caching, building dependencies in random order, and displaying commands as if cached files were built.
The normal way to execute sccons is in a top-level directory containing a Construct file, specifying the target or targets to be built:
% sccons .
Specified target may be omitted, in which case the targets specified via Default are built:
% sccons
Specifying ``cleanup'' targets is not necessary. The sccons -r flag removes all files necessary to build the specified target:
# removes all target files % sccons -r .
# removes all target files under the specified subdirectories % sccons -r build export
A subset of a hierarchical tree may be built by:
1) remaining at the top-level directory (where the Construct file lives) and specifying the subdirectory as the target to be built:
% sccons src/subdir
2) changing directory and invoking sccons with the -t option, which traverses up the directory hierarchy until it finds the Construct file, and then builds targets relatively to the current subdirectory:
% cd src/subdir % sccons -t .
Various command-line options exist to provide more information about a
build and help debug problems. See the attached man page for details on the -d
, -p
, -pa
and -pw
options.
Variables can be passed in on the command line:
% sccons debuglevel=4 .
These can be used in the configuration files to modify the build as requested.
sccons will support a -j
option to build up to a specified number of target files simultaneously:
% sccons -j 4
sccons does not provide a native graphical interface--that is, it is ``only'' a software construction tool.
sccons can, however, be used as an underlying construction tool in an
integrated development environment with a graphical user interface. The IDE
can use the sccons -d
option to generate a list of dependencies to be displayed graphically.
Storing dependency lists between invocations provides a mechanism for
display changed dependencies as well.
Conversely, any changes made via a graphic interface can be easily written into Construct and Conscript files using conventions that are appropriate for the IDE. The IDE developers would be responsible for maintaining correspondence between their graphical interface and the underlying sccons idioms generated by their IDE.
Syntax errors in sccons configuration files will be caught by the Python parser. Target-building does not begin until after all configuration files are read, so a syntax error will not cause a build to fail half-way.
sccons detects build failures via the exit status from the tools used to build the target files. By default, a failed exit status (non-zero on UNIX systems) terminates the build with an appropriate error message. An appropriate class from the Python library will interpret build-tool failures via an OS-independent API.
If multiple tasks are executing in a parallel build, and one tool returns failure, sccons will not initiate any further build tasks, but allow the other build tasks to complete before terminating.
A -k
command-line option may be used to ignore errors and continue building
other targets. In no case will a target that depends on a failed build be
rebuilt.
A brief discussion of the important classes necessary to implement this design:
This class will be very straightforward, wrapping up the arguments supplied
on instantiation. Initialization of a Builder
object may require creation of a method that can later be bound to
Environment
objects.
This class will be equally straightforward, wrapping up the arguments
supplied on instantiation. Initialization of a Scanner
object may require creation of a method that can later be bound to
Environment
objects.
The Environment
class will consist mainly of the dictionary construction environment
variables and a handful of unbound methods (Copy
, Dictionary
, Command
, Scan
, Install
,
InstallAs
).
Additional methods will be bound at instantiation from the lists of Builder
and Scanner
objects supplied in the variables
BUILDERS
, BUILDERMAP
, SCANNERS
, and SCANNERMAP
.
The Entry
class is the key to Cons dependency management. It has two derived classes, Entry.Dir
and Entry.File
.
An Entry
object is a generic ``file system object'' that represents any file that
might (or does) exist as part of an sccons build. Any reference to a file
or directory results in the creation of an appropriate Entry.File
or Entry.Dir
object, respectively. References to entries that could be either (e.g.,
each target listed in the Default
method could be a file or a directory) are created as a generic Entry
and later turned into the appropriate derived class when a more specific
reference resolves the ambiguity.
One set of Entry
attributes maintains a normal file-system hierarchy, with pointers to the
parent directory, a dictionary of entries in the directory, etc.
Another parallel set of Entry
attributes maintain information about how to go about building the entry
(if it is a target file): pointers to the appropriate Builder
object, etc.
There will be additional attributes and unbound methods to handle build functionality, file system traversal, repository searching, etc. Specific attributes and methods will be part of the full design submission.
sccons will include a Job
class that will manage creation and monitoring of tasks that are spawned to
build a file.
There will likely be two derived classes, Job.Serial
and
Job.Parallel
that handle job creation for ``normal'' builds and parallel builds,
respectively. An alternative would be to use a single Job
class that treats a ``normal'' single-threaded build as a parallel builds
with only one simultaneous task (i.e., ``sccons -j 1''). Experimentation
with this approach, however, suggests that it is slower than a separate
derived class.
Additional experimentation suggests that having the Job
class ``pull'' tasks from the dependency analysis subsystem yields better
parallelization. If the dependency analysis subsystem pushes tasks to the Job
class, recursive descent of dependencies makes it difficult to keep N jobs
running simultaneously.
A Sig
class provides an interface for determing whether a target file is
up-to-date by calculating a signature value for the file. There are two
derived classes: Sig.MD5
and Sig.TimeStamp
.
The Sig.TimeStamp
derived class uses the modification time of a file as its signature. This
provides a file-update capability similar to make
, and can be used as a baseline for comparison with other signature
mechanisms. It could also be used on systems where other signature
calculations are impractical.
The Sig.MD5
derived class determines a file's signature by calculating the MD5 checksum
of the contents of the file. This provides a more robust file-update
capability than time stamps, since the MD5 signature changes only if the
file contents actually change.
Each derived class provides an interface for adding arbitrary string values
to a file's signature value. This is used to add the build command line to
a target file's signature, so that changes in build methods (e.g., using a
different CCFLAGS
value) will cause the target file to be rebuilt appropriately.
The SC-config tool will be used in the sccons installation process to generate an appropriate default construction environment so that building most software ``just works'' on the installed platform. The SC-config tool will find reasonable default compilers (C, C++, Fortran), linkers/loaders, library archive tools, etc. for specification in the default sccons construction environment.
sccons can be configured to use SC-test (or some other test tool) to
provide controlled, automated testing of software. The LinkDir
method could link a test subdirectory to a build subdirectory:
LinkDir('test', 'build') Include('test/Conscript')
Any test cases checked in with the source code will be linked into the test subdirectory and executed. If Conscript files and test cases are written with this in mind, then invoking:
% sccons test
Would run all the automated test cases that depend on any changed software.
No specific interaction with SC-track is anticipated.
Java dependencies are difficult for an external dependency-based
construction tool to accomodate. Determining Java class dependencies is
more complicated than the simple pattern-matching of C or C++
#include
files. From the point of view of an external build tool, the Java compiler
behaves ``unpredictably'' because it may create or update multiple output
class files and directories as a result of its internal class dependencies.
An obvious sccons implementation would be to have the Scanner
object parse output from Java -depend -verbose
to calculate dependencies, but this has the distinct disadvantage of
requiring two separate compiler invocations, thereby slowing down builds.
The use of appropriate Python classes (especially the sys
,
os
, and os.path
classes) for operating system interaction will make sccons portable to any
operating system that supports Python. It is possible that sccons will need
an operating system feature or capability not found in the Python library.
In this case, sccons should derive a class from an existing library class,
implement the needed OS-indepenedent extension, and try to have the new
feature added to the Python library.
In practice, calculating MD5 signatures of a file's contents is a more robust mechanism than time stamps for determining what needs building. However:
1) Developers used to the time stamp model of Make
can initially find MD5 signatures counter-intuitive. The assumption that:
% touch file.c
will cause a rebuild of file is strong...
2) Abstracting dependency calculation into a single MD5 signature loses a little information: It is no longer possible to tell (without laborious additional calculation) which input file dependency caused a rebuild of a given target file. A feature that could report, ``I'm rebuilding file X because it's out-of-date with respect to file Y,'' would be good, but an MD5-signature implementation of such a feature is non-obvious.
The ability to use multiple build systems through remote execution of tools
would be good. This should be implementable through the
Job
class. Construction environments would need modification to specify build
systems.
The ability to check run-time conditions as suggested on the sc-discuss mailing list (``build X only if: the machine is idle / the file system has Y megabytes free space'') would also be good.
Development would likely proceed as follows:
The following classes can be designed and tested independently from the rest of the system, and will be implemented first:
Entry
Job
Sig.TimeStamp
Sig.MD5
Unit tests of each Class' interface will be developed concurrently. These will form the basis of the regression test suite for sccons development.
Builder
and Scanner
objects for C-language programs will be designed and implemented.
The Environment class that ties these pieces together will be designed and implemented. Necessary __main__ methods will be implemented.
The result will be an sccons that works for building C programs within the current directory.
Full-functionality tests for building C programs will be written and added to the regression test base.
Functionality explicitly excluded at this stage:
Include Repository LinkDir Cache
Builder
and Scanner
objects for Fortran programs will be designed and implemented.
The Environment and sccons classes will be extended to support more than
one Builder
/Scanner
object.
Full-functionality tests for building Fortran programs will be written and added to the regression test base.
A Builder
object for libraries will be designed and implemented.
Full-functionality tests for building Libraries programs will be written and added to the regression test base.
The ability to read/execute subsidiary configuration files (Conscript files) will be designed and implemented. This will require solving the name space issue that I don't know how to solve in Python.
The ability to ``link'' a build directory to a source directory will be
added, involving extending the Entry
class. Regression tests from the previous stages will prevent problems with
refactoring this class.
The ability to search for files in a list of Repository
directories will be added, involving another extension to the Entry
class. Regression tests from the previous stages will prevent problems with
refactoring this class.
The ability to store and retrieve target files from a build cache will be added.
Testing of sccons' full functionality will use, as a reference, the
existing cons-test
suite of tests for the original Perl-based Cons utility. These
self-contained scripts test Cons functionality by creating specific test
cases in temporary directories and verifying that Cons behaves correctly:
builds the expected target files, generates the proper error messages, etc.
The cases covered by the sccons test suite should be a rough superset of
those covered by the cons-test
suite.
Tests of sccons functionality will be written using the SC-test design. The sccons team will work with the winning SC-test team to ensure that their design provides adequate testing functionality for sccons.
sccons offers a robust and feature-rich design for an SC-build tool. Based
on the proven design of the Cons utility, it offers increased
simplification of the user interface for unsophisticated users with the
addition of the ``do-the-right-thing'' env.Make
method, increased flexibility for sophisticated users with the addition of Builder
and Scanner
objects, and a mechanism to allow tool-masters (and users) to share working
construction environments.
[Home] | [FAQ] | [License] | [Rules] | [Resources] | [Archives] |