Initial Blueprint commit.
Blueprint is a build system component that reads Blueprints files defining
modules to be built, and generates a Ninja build manifest that can be used to
perform all the build actions. It does not dictate or implement much build
policy itself, but rather provides a framework to ease the process of defining
build logic in Go.
The "blueprint" and "blueprint/parser" Go packages contain the functionality
for reading Blueprint files and invoking build logic functions defined in other
Go packages.
The "blueprint/bootstrap" Go package contains just enough build logic to build
a binary that includes Blueprint and any pure-Go (i.e. no cgo) build logic
defined in external Go packages. This can be used to create a minimal Ninja
file that's capable of bootstrapping a Blueprint-based build system from
source.
The "blueprint/bootstrap/minibp" Go package contains code for a minimal binary
that includes the build logic defined in the "blueprint/bootstrap" package.
This binary can then create the Ninja file for the bootstrapping process.
Change-Id: I8d8390042372a72d225785cda738525001b009f1
diff --git a/blueprint/module_ctx.go b/blueprint/module_ctx.go
new file mode 100644
index 0000000..f8fe564
--- /dev/null
+++ b/blueprint/module_ctx.go
@@ -0,0 +1,116 @@
+package blueprint
+
+import (
+ "fmt"
+ "path/filepath"
+)
+
+type Module interface {
+ GenerateBuildActions(ModuleContext)
+}
+
+type ModuleContext interface {
+ ModuleName() string
+ ModuleDir() string
+ Config() Config
+
+ ModuleErrorf(fmt string, args ...interface{})
+ PropertyErrorf(property, fmt string, args ...interface{})
+
+ Variable(name, value string)
+ Rule(name string, params RuleParams) Rule
+ Build(params BuildParams)
+
+ VisitDepsDepthFirst(visit func(Module))
+ VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
+}
+
+var _ ModuleContext = (*moduleContext)(nil)
+
+type moduleContext struct {
+ context *Context
+ config Config
+ module Module
+ scope *localScope
+ info *moduleInfo
+
+ errs []error
+
+ actionDefs localBuildActions
+}
+
+func (m *moduleContext) ModuleName() string {
+ return m.info.properties.Name
+}
+
+func (m *moduleContext) ModuleDir() string {
+ return filepath.Dir(m.info.relBlueprintFile)
+}
+
+func (m *moduleContext) Config() Config {
+ return m.config
+}
+
+func (m *moduleContext) ModuleErrorf(format string, args ...interface{}) {
+ m.errs = append(m.errs, &Error{
+ Err: fmt.Errorf(format, args...),
+ Pos: m.info.pos,
+ })
+}
+
+func (m *moduleContext) PropertyErrorf(property, format string,
+ args ...interface{}) {
+
+ pos, ok := m.info.propertyPos[property]
+ if !ok {
+ panic(fmt.Errorf("property %q was not set for this module", property))
+ }
+
+ m.errs = append(m.errs, &Error{
+ Err: fmt.Errorf(format, args...),
+ Pos: pos,
+ })
+}
+
+func (m *moduleContext) Variable(name, value string) {
+ v, err := m.scope.AddLocalVariable(name, value)
+ if err != nil {
+ panic(err)
+ }
+
+ m.actionDefs.variables = append(m.actionDefs.variables, v)
+}
+
+func (m *moduleContext) Rule(name string, params RuleParams) Rule {
+ // TODO: Verify that params.Pool is accessible in this module's scope.
+
+ r, err := m.scope.AddLocalRule(name, ¶ms)
+ if err != nil {
+ panic(err)
+ }
+
+ m.actionDefs.rules = append(m.actionDefs.rules, r)
+
+ return r
+}
+
+func (m *moduleContext) Build(params BuildParams) {
+ // TODO: Verify that params.Rule is accessible in this module's scope.
+
+ def, err := parseBuildParams(m.scope, ¶ms)
+ if err != nil {
+ panic(err)
+ }
+
+ m.actionDefs.buildDefs = append(m.actionDefs.buildDefs, def)
+}
+
+func (m *moduleContext) VisitDepsDepthFirst(visit func(Module)) {
+ m.context.visitDepsDepthFirst(m.module, visit)
+}
+
+func (m *moduleContext) VisitDepsDepthFirstIf(pred func(Module) bool,
+ visit func(Module)) {
+
+ m.context.visitDepsDepthFirstIf(m.module, pred, visit)
+}