[Software Carpentry logo]
[ACL Logo]

[CodeSourcery Logo]
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:
http://www.software-carpentry.com/openpub-license.html


Proposal for sccons

Software Carpentry Construction System
Steven Knight <knight@baldmt.com>
March 2000

Background

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.


Overview

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 Files

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')

Variable scoping

sccons needs a way to pass variables explicitly from a parent configuration file to an Included 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.

Construction environments

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()

Multiple construction environments

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.

Shared construction environments

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.

Builder objects

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'])

User-defined builder objects

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.

Builder maps

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.

Special-purpose build rules

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.

Variable Substitution

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:

%0

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.

%1, %2, %3, %4, %5, %6, %7, %8, %9

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:

:b

basename; the directory plus the file name less any file suffix

:d

the directory

:f

the file name

:s

the file name suffix

:F

the file name less any file suffix

Automatically-generated dependencies

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.

Implicit dependencies

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!
        %

Ignoring dependencies

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.

Explicit dependencies

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')

Scanner objects

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')

User-defined scanner objects

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.

Scanner maps

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.

Targets

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')

Default targets

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.

File installation

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'])

Separate source and build trees

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.

Variant Builds

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')

Code Repositories

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.

Derived-File Caching

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.


Interface

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

Removing targets

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

Hierarchical build subsets

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 .

Debugging the build process

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.

Passing in variables

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.

Parallel builds

sccons will support a -j option to build up to a specified number of target files simultaneously:

        % sccons -j 4

Graphical interface

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

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.

Build failures

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.


Design Outline

A brief discussion of the important classes necessary to implement this design:

Builder class

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.

Scanner class

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.

Environment class

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.

Entry class

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.

Job class

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.

Signature classes

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.


Other Issues

Interaction with SC-config

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.

Interaction with SC-test

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.

Interaction with SC-track

No specific interaction with SC-track is anticipated.

Java dependencies

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.

Portability

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.

Limitations of MD5 signature calculation

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.

Remote execution

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.

Conditional builds

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 Plan Outline

Development would likely proceed as follows:

Stage 1: Underlying infrastructure classes

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.

Stage 2: Building simple C programs

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

Stage 3: Building simple Fortran programs

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.

Stage 4: Building libraries

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.

Stage 5: Include functionality

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.

Stage 6: LinkDir

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.

Stage 7: Repository functionality

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.

Stage 8: Cache functionality

The ability to store and retrieve target files from a build cache will be added.

Testing

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.


Summary

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]   

Powered by Zope

Zope management by SPVI

Last modified 2000/05/15 19:31:29.9982 US/Mountain