The boo build process
Written Oct. 18, 2006 by David Piepgrass (blog | home)
boo is built using NAnt. The build process is controlled by
default.build in the root directory of the source distribution; the
name of the default target in default.build is "all".
Here is a dependency graph for "all":

This page describes the build-related targets. It does not cover all
the targets, only those targets that "all" depends on, or that are
related to the build process. (I have not analyzed other targets, such
as unit tests.) The targets are listed in bottom-up order, so "all" is at the bottom. After each target, the
dependencies are listed in brackets. For example,
abra: (cad, ab, [ra])
signifies that target "abra" depends on targets "cad", "ab" and "ra".
The square brackets signify that the dependency is redundant because
either "cad" or "ab" already depends on "ra".
Summary
Most of the build targets follow a simple pattern: a target called XYZ
causes all the source files (*.cs or *.boo) in folder src/XYZ, and all
its subfolders, to be compiled into build/XYZ.dll or build/XYZ.exe. The
following targets follow this pattern, except those marked with a star
(*). Targets marked with ** follow the pattern, but have
additional effect(s).
| Target |
Source files |
Output file(s) |
| * init |
- |
- |
| * compile-grammar |
src/Boo.Lang.Parser/*.g |
output in src/Boo.Lang.Parser/ |
| * resources |
src/Boo.Lang/Resources/strings.txt et al. |
build/strings.resources et al. |
| ** Boo.Lang |
src/Boo.Lang/**/*.cs |
build/Boo.Lang.dll |
| * generate-ast |
ast.model.boo, via scripts/astgen.boo |
src/Boo.Lang.Compiler/Ast/Impl/*.cs |
| Boo.Lang.Compiler |
src/Boo.Lang.Compiler/**/*.cs |
build/Boo.Lang.Compiler.dll |
| Boo.Lang.Parser |
src/Boo.Lang.Parser/**/*.cs |
build/Boo.Lang.Parser.dll |
| core |
- |
- |
| ** booc |
src/booc/*.cs |
build/booc.exe |
| ** Boo.NAnt.Tasks |
src/Boo.NAnt.Tasks/*.boo |
build/Boo.NAnt.Tasks.dll |
| booi |
src/booi/*.boo (i.e. booi.boo) |
build/booi.exe |
| Boo.Lang.Interpreter |
src/Boo.Lang.Interpreter/*.boo |
build/Boo.Lang.Interpreter.dll |
| booish |
src/booish/*.boo (i.e. booish.boo) |
build/booish.exe |
| ** Boo.Lang.Useful |
src/Boo.Lang.Useful/**/*.boo |
build/Boo.Lang.Useful.dll |
| boo |
src/boo/*.boo |
build/boo.exe |
| Boo.Lang.CodeDom |
src/Boo.Lang.CodeDom/**/*.boo |
build/Boo.Lang.CodeDom.dll |
| ** Boo.Microsoft.Build.Tasks |
src/Boo.Microsoft.Build.Tasks/**/*.boo |
build/Boo.Microsoft.Build.Tasks.dll |
| * all |
- |
- |
See the following subsections under "Targets" for more details on these
targets, including a summary of the purpose of each component.
Namespaces
By the way, here's a table of namespaces, showing which DLLs
contribute to each. An easy way to inspect .NET assemblies (DLLs and
EXEs) is to open them with Micro Visual Studio or one of the Visual
Studio Express Editions. The assemblies' interfaces will be shown in
the Object Browser.
| Namespace |
DLL(s) |
| Boo.Lang |
Boo.Lang.dll, Boo.Lang.Compiler.dll |
| Boo.Lang.Runtime |
Boo.Lang.dll |
| Boo.Lang.Compiler |
Boo.Lang.Compiler.dll |
| Boo.Lang.Compiler.{Ast, Ast.Impl, Ast.Visitors} |
| Boo.Lang.Compiler.{IO, Pipelines, Resources, Steps, TypeSystem, Util} |
| Boo.Lang.Parser |
Boo.Lang.Parser.dll |
| Boo.Lang.Parser.Util |
| antlr |
| antlr.{collections, collections.impl, debug} |
| Boo.Lang.Useful.{Attributes, BooTemplate, Collections, CommandLine, IO, IOImpl, Resources) |
Boo.Lang.Useful.dll
|
Boo.NAnt
|
Boo.NAnt.Tasks.dll |
| CompilerGenerated (note: most code written in boo will have compiler-generated stuff in this namespace) |
Boo.Lang.Interpreter.dll, Boo.Lang.Useful.dll, Boo.Microsoft.Build.Tasks.dll, Boo.NAnt.Tools.dll |
Targets
init:
Creates the build/ folder. That's it!
clean:
Deletes the build/ folder and its contents.
compile-grammar: (init)
Generates a series of C# files:
BooLexer.cs
BooParserBase.cs
BooTokenTypes.cs
BooTokenTypes.txt
BooExpressionLexer.cs
BooExpressionLexerTokenTypes.cs
BooExpressionLexerTokenTypes.txt
WSABooLexer.cs
WSABooParserBase.cs
WSABooTokenTypes.cs
WSABooTokenTypes.txt
WSABooExpressionLexer.cs
WSABooExpressionLexerTokenTypes.cs
WSABooExpressionLexerTokenTypes.txt
from *.g files in src/Boo.Lang.Parser:
boo.g
booel.g
wsaboo.g
wsabooel.g
This is done with ANTLR, a Java program at lib\antlr-2.7.5\antlr-2.7.5.jar.
Parser grammar files (*.g) are written by hand and compiled by ANTLR to generate a C# parser and lexer automatically.
For some reason, this target touches src/Boo.Lang.Parser/BooParserBase.cs.
The actual command used to compile the *.g files is obfuscated by the
NAnt syntax. From src\Boo.Lang.Parser, the following commands can be
used to compile the *.g files:
java -cp ../../lib/antlr-2.7.5/antlr-2.7.5.jar antlr.Tool -o . boo.g
java -cp ../../lib/antlr-2.7.5/antlr-2.7.5.jar antlr.Tool -o . booel.g
java -cp ../../lib/antlr-2.7.5/antlr-2.7.5.jar antlr.Tool -o . wsaboo.g
java -cp ../../lib/antlr-2.7.5/antlr-2.7.5.jar antlr.Tool -o . wsabooel.g
"WSA" stands for White Space Agnostic. The WSA parser is almost
identical to the normal one, but instead of using idention for control,
":" and "end" are used instead. To enable the WSA parser, pass the -wsa
option to booc.
resources: (init)
This target builds build/strings.resources from
src/Boo.Lang/Resources/strings.txt. The latter is simply a list of text
strings; a standard .NET tool (part of the .NET and mono SDKs) called
resgen is used to convert the text file into a binary resource file.
This target also calls a sub-target, "build-resource", to make resource
files from other text files in src/Boo.Lang/Resources (looks like boo
is available in Italian and Portugese.)
Boo.Lang: (resources)
Builds:
build/Boo.Lang.dll
from:
1. src/Boo.Lang/**/*.cs (*.cs in src/Boo.Lang.Compiler and subfolders)
2. the string resource files (e.g. build/strings.resources)
It appears that non-English resources are included only when using a Microsoft framework.
Boo.Lang contains "core" classes that can be used by boo code, such as
List and Hash, and built-in functions (in class Boo.Lang.Builtins)
including as array(), cat(), enumerate(), map(), join(), zip(),
shell(), ...
generate-ast: (init)
Builds:
100 files in src/Boo.Lang.Compiler/Ast/Impl
using:
1. scripts/astgen.boo
2. bin/booi
3. ast.model.boo
Invokes scripts/astgen.boo, which in turn parses ast.model.boo and
generates a set of C# classes in src/Boo.Lang.Compiler/Ast/Impl.
astgen.boo is invoked via bin/booi (that's why a binary version of boo
is included in the source distribution), but without arguments (the
filename ast.model.boo is hard-coded in astgen.boo).
All 100 files in src/Boo.Lang.Compiler/Ast/Impl are automatically
generated, and all the filenames end in "Impl.cs". An interesting thing
is that every file in src/Boo.Lang.Compiler/Ast/Impl contains a base
class for a corresponding file in src/Boo.Lang.Compiler/Ast. For
example, AttributeImpl.cs contains a class AttributeImpl (namespace:
Boo.Lang.Compiler.Ast.Impl). The corresponding file
src/Boo.Lang.Compiler/Ast/Attribute.cs defines a class Attribute
(namespace: Boo.Lang.Compiler.Ast) that is derived from AttributeImpl.
The 119 files in src/Boo.Lang.Compiler/Ast might be automatically
generated as well. TODO figure it out. The following 19 files in
src/Boo.Lang.Compiler/Ast do NOT have a corresponding file in
src/Boo.Lang.Compiler/Ast/Impl:
AstUtil.cs
BinaryOperatorType.cs
DepthFirstTransformer.cs
DepthFirstVisitor.cs
IAstVisitor.cs
IExplicitMember.cs
INodeWithArguments.cs
INodeWithAttributes.cs
INodeWithParameters.cs
LexicalInfo.cs
MethodImplementationFlags.cs
Node.cs
NodeCollection.cs
NodeType.cs
OmittedExpression.cs
ParameterModifiers.cs
StatementModifierType.cs
TypeMemberModifiers.cs
UnaryOperatorType.cs
TODO figure out the purpose of all this!
Note that this target needs bin/booi; that's why a binary version of boo is included in the source distribution.
Boo.Lang.Compiler: (Boo.Lang, generate-ast)
Builds:
build/Boo.Lang.Compiler.dll
from:
src/Boo.Lang.Compiler/**/*.cs (*.cs in src/Boo.Lang.Compiler and
its subfolders, including sources generated by generate-ast.)
using:
build/Boo.Lang.dll
Boo.Lang.Parser: (Boo.Lang.Compiler, compile-grammar)
Builds:
build/Boo.Lang.Parser.dll
from:
src/Boo.Lang.Parser/**/*.cs (*.cs in src/Boo.Lang.Parser and its
subfolders, including the sources generated by compile-grammar.)
using:
build/Boo.Lang.dll
build/Boo.Lang.Compiler.dll
core: (Boo.Lang.Parser, [Boo.Lang], [Boo.Lang.Compiler])
This target does nothing.
booc: (core)
Builds the boo compiler front-end:
build/booc.exe
from:
src/booc/*.cs
using:
build/Boo.Lang.dll
build/Boo.Lang.Compiler.dll
build/Boo.Lang.Parser.dll
Also:
- Copies src/booc/booc.rsp to build/
- If platform is not Win32, copies extras/booc.in to build/booc,
replacing @RUNTIME@ with mono and @prefix@ with ${install.prefix}.
- Copies extras/template.config.in to build/booc.exe.config,
replacing @SUPPORTEDVERSIONS@ with ${supported.runtimes}.
- Runs ngen (if available) on Boo.Lang.dll, build/Boo.Lang.Compiler.dll,
build/Boo.Lang.Parser.dll and booc.exe.
Note that booc itself is a very small program--it relies on the DLLs to do the actual work of compiling.
Boo.NAnt.Tasks: (booc)
Builds:
build/Boo.NAnt.Tasks.dll
from:
src/Boo.NAnt.Tasks/*.boo; specifically
src/Boo.NAnt.Tasks/UpdateAssemblyVersionTask.boo
src/Boo.NAnt.Tasks/InsertLicenseTask.boo
src/Boo.NAnt.Tasks/BoocTask.boo
src/Boo.NAnt.Tasks/BooTask.boo
src/Boo.NAnt.Tasks/AbstractBooTask.boo
using:
build/booc.exe
${nant.location}/NAnt.Core.dll
${nant.location}/NAnt.DotNetTasks.dll
Builds build/Boo.NAnt.Tasks.dll and loads that DLL into NAnt itself.
This DLL contains boo-related tasks, which make it easier to compile
boo code from within a NAnt build file. Without a boo task, boo has to
be invoked using the "exec" task, which, from what I've seen, is very
cumbersome to use.
The "booc" task invokes the boo compiler, booc.exe. The "boo" task runs
boo code that is stored directly in the NAnt build file; for example:
<boo>
print("Hello from boo task!")
print("Framework directory: ${Project.TargetFramework.FrameworkAssemblyDirectory}")
</boo>
booi: (Boo.NAnt.Tasks)
Builds the boo interpreter front-end:
build/booi.exe
from:
src/booi/*.boo (specifically booi.boo)
using:
build/Boo.Lang.Parser.dll
booi is even smaller than booc. Again, the boo DLLs do all the work.
This program may be a good demonstration of how you can run a boo
script from your own code (But don't quote me.) Note that booi does NOT
use Boo.Lang.Interpreter, probably because booi is not interactive.
Boo.Lang.Interpreter: (Boo.NAnt.Tasks)
Builds:
build/Boo.Lang.Interpreter.dll
from:
src/Boo.Lang.Interpreter/*.boo
booish: (Boo.Lang.Interpreter)
Builds an interactive interpreter front-end:
build/booish.exe
from:
src/booish/*.boo (specifically booish.boo)
using:
Boo.Lang.Interpreter.dll
Also:
- Copies extras/template.config.in to build/booc.exe.config,
replacing @SUPPORTEDVERSIONS@ with ${supported.runtimes}.
(note: target booc does exactly the same thing)
- If platform is not Win32, copies extras/booish.in to build/booish,
replacing @RUNTIME@ with mono and @prefix@ with ${install.prefix}.
booish is even smaller than booi. Boo.Lang.Interpreter.dll does all the
work.
Boo.Lang.Useful: (Boo.NAnt.Tasks)
This target is built in two stages.
The first stage builds:
src/Boo.Lang.Useful/IO/Impl/PreProcessorExpressionEvaluator.boo
src/Boo.Lang.Useful/IO/Impl/PreProcessorExpressionLexer.boo
src/Boo.Lang.Useful/IO/Impl/PreProcessorExpressionParser.boo
src/Boo.Lang.Useful/IO/Impl/PreProcessorExpressionParserTokenTypes.boo
from:
src/Boo.Lang.Useful/IO/PreProcessorExpressions.g
using:
lib/antlr-2.7.5/antlr-2.7.5.jar (a parser generator that requires Java)
The second stage builds:
build/Boo.Lang.Useful.dll
from:
src/Boo.Lang.Useful/**/*.boo
using:
Boo.Lang.Parser.dll
I was told Boo.Lang.Useful "wraps functionality of booi, booish, and
booc" and that it's "an external library of contributed (mostly) code."
It should be possible to process PreProcessorExpressions.g manually
from the root folder using this command:
java -cp lib/antlr-2.7.5/antlr-2.7.5.jar antlr.Tool -o
src/Boo.Lang.Useful/IO/Impl
src/Boo.Lang.Useful/IO/PreProcessorExpressions.g
If you know anything about ANTLR, you may be puzzled because ANTLR
2.7.5 supposedly does NOT support boo as a target language. I assume
Rodrigo has included the specially modified version of ANTLR that he
made some time ago.
boo: (Boo.Lang.Useful, Boo.Lang.Interpreter.dll)
Builds another interactive interpreter front-end:
build/boo.exe
from:
src/boo/*.boo
using:
build/Boo.Lang.Useful.dll
build/Boo.Lang.Interpreter.dll
When run with no arguments, boo acts like booish. "Geek Ninja" says "boo.exe wraps functionality of booi, booish, and booc."
Boo.Lang.CodeDom: (Boo.NAnt.Tasks)
Builds:
build/Boo.Lang.CodeDom.dll
from:
src/Boo.Lang.CodeDom/**/*.boo
using standard (but non-default) .NET libraries:
System.Data.dll
System.Xml.dll
Boo.Lang.CodeDom is not used by the compiler tools. "PC Bender" says it
is "Used by asp.net and other codedom apps, including webbness."
Boo.Microsoft.Build.Tasks: (Boo.NAnt.Tasks)
Runs the 'msbuild' target if the "target-framework" is "net-2.0". msbuild builds:
Boo.Microsoft.Build.Tasks.dll
from:
src/Boo.Microsoft.Build.Tasks/**/*.boo
using:
Microsoft.Build.Utilities.dll
Microsoft.Build.Tasks.dll
Microsoft.Build.Framework.dll
Copies:
src/Boo.Microsoft.Build.Tasks/Boo.Microsoft.Build.targets to build/
Microsoft's "new build platform for Microsoft and Visual Studio", msbuild, can use this DLL.
all: ([booc], booi, booish, boo-pkgconfig, Boo.Lang.CodeDom,
[Boo.Lang.Useful], boo, Boo.Microsoft.Build.Tasks)
This is the "main" target--the one used when you start NAnt with no
parameters.
rebuild: (clean)
- touches (in src/Boo.Lang.Parser) boo.g and booel.g to force
the C# parser files to be regenerated (in src/Boo.Lang.Parser). "touch"
means that the modification time of the file is set to now.
- touches (in root) ast.model.boo to force the C# AST files
to be regenerated