blueprint

package module
v0.11.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 24, 2021 License: Apache-2.0 Imports: 25 Imported by: 0

README

Blueprint Build System

Build Status

Blueprint is a meta-build system that reads in Blueprints files that describe modules that need to be built, and produces a Ninja manifest describing the commands that need to be run and their dependencies. Where most build systems use built-in rules or a domain-specific language to describe the logic for converting module descriptions to build rules, Blueprint delegates this to per-project build logic written in Go. For large, heterogenous projects this allows the inherent complexity of the build logic to be maintained in a high-level language, while still allowing simple changes to individual modules by modifying easy to understand Blueprints files.

Documentation

Overview

Blueprint is a meta-build system that reads in Blueprints files that describe modules that need to be built, and produces a Ninja (https://ninja-build.org/) manifest describing the commands that need to be run and their dependencies. Where most build systems use built-in rules or a domain-specific language to describe the logic how modules are converted to build rules, Blueprint delegates this to per-project build logic written in Go. For large, heterogenous projects this allows the inherent complexity of the build logic to be maintained in a high-level language, while still allowing simple changes to individual modules by modifying easy to understand Blueprints files.

Blueprint uses a bootstrapping process to allow the code for Blueprint, the code for the build logic, and the code for the project being compiled to all live in the project. Dependencies between the layers are fully tracked - a change to the logic code will cause the logic to be recompiled, regenerate the project build manifest, and run modified project rules. A change to Blueprint itself will cause Blueprint to rebuild, and then rebuild the logic, etc.

A Blueprints file is a list of modules in a pseudo-python data format, where the module type looks like a function call, and the properties of the module look like optional arguments. For example, a simple module might look like:

cc_library {
    name: "cmd",
    srcs: [
        "main.c",
    ],
    deps: [
        "libc",
    ],
}

subdirs = ["subdir1", "subdir2"]

The modules from the top level Blueprints file and recursively through any subdirectories listed by the "subdirs" variable are read by Blueprint, and their properties are stored into property structs by module type. Once all modules are read, Blueprint calls any registered Mutators, in registration order. Mutators can visit each module top-down or bottom-up, and modify them as necessary. Common modifications include setting properties on modules to propagate information down from dependers to dependees (for example, telling a module what kinds of parents depend on it), or splitting a module into multiple variants (for example, one per architecture being compiled). After all Mutators have run, each module is asked to generate build rules based on property values, and then singletons can generate any build rules from the output of all modules.

The per-project build logic defines a top level command, referred to in the documentation as the "primary builder". This command is responsible for registering the module types needed for the project, as well as any singletons or mutators, and then calling into Blueprint with the path of the root Blueprint file.

Index

Constants

View Source
const MockModuleListFile = "bplist"

Variables

View Source
var ErrBuildActionsNotReady = errors.New("build actions are not ready")

Functions

func AddLoadHook

func AddLoadHook(module Module, hook LoadHook)

func CheckBlueprintSyntax

func CheckBlueprintSyntax(moduleFactories map[string]ModuleFactory, filename string, contents string) []error

Check the syntax of a generated blueprint file.

This is intended to perform a quick sanity check for generated blueprint code to ensure that it is syntactically correct, where syntactically correct means: * No variable definitions. * Valid module types. * Valid property names. * Valid values for the property type.

It does not perform any semantic checking of properties, existence of referenced files, or dependencies.

At a low level it: * Parses the contents. * Invokes relevant factory to create Module instances. * Unpacks the properties into the Module. * Does not invoke load hooks or any mutators.

The filename is only used for reporting errors.

Types

type BaseDependencyTag

type BaseDependencyTag struct {
}

type BaseModuleContext

type BaseModuleContext interface {
	EarlyModuleContext

	// GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
	// none exists.  It panics if the dependency does not have the specified tag.
	GetDirectDepWithTag(name string, tag DependencyTag) Module

	// GetDirectDep returns the Module and DependencyTag for the  direct dependency with the specified
	// name, or nil if none exists.  If there are multiple dependencies on the same module it returns
	// the first DependencyTag.
	GetDirectDep(name string) (Module, DependencyTag)

	// VisitDirectDeps calls visit for each direct dependency.  If there are multiple direct dependencies on the same
	// module visit will be called multiple times on that module and OtherModuleDependencyTag will return a different
	// tag for each.
	//
	// The Module passed to the visit function should not be retained outside of the visit function, it may be
	// invalidated by future mutators.
	VisitDirectDeps(visit func(Module))

	// VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit.  If there are
	// multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
	// OtherModuleDependencyTag will return a different tag for each.
	//
	// The Module passed to the visit function should not be retained outside of the visit function, it may be
	// invalidated by future mutators.
	VisitDirectDepsIf(pred func(Module) bool, visit func(Module))

	// VisitDepsDepthFirst calls visit for each transitive dependency, traversing the dependency tree in depth first
	// order. visit will only be called once for any given module, even if there are multiple paths through the
	// dependency tree to the module or multiple direct dependencies with different tags.  OtherModuleDependencyTag will
	// return the tag for the first path found to the module.
	//
	// The Module passed to the visit function should not be retained outside of the visit function, it may be
	// invalidated by future mutators.
	VisitDepsDepthFirst(visit func(Module))

	// VisitDepsDepthFirst calls pred for each transitive dependency, and if pred returns true calls visit, traversing
	// the dependency tree in depth first order.  visit will only be called once for any given module, even if there are
	// multiple paths through the dependency tree to the module or multiple direct dependencies with different tags.
	// OtherModuleDependencyTag will return the tag for the first path found to the module.  The return value of pred
	// does not affect which branches of the tree are traversed.
	//
	// The Module passed to the visit function should not be retained outside of the visit function, it may be
	// invalidated by future mutators.
	VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))

	// WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order.  visit may
	// be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
	// child and parent with different tags.  OtherModuleDependencyTag will return the tag for the currently visited
	// (child, parent) pair.  If visit returns false WalkDeps will not continue recursing down to child.
	//
	// The Modules passed to the visit function should not be retained outside of the visit function, they may be
	// invalidated by future mutators.
	WalkDeps(visit func(Module, Module) bool)

	// OtherModuleName returns the name of another Module.  See BaseModuleContext.ModuleName for more information.
	// It is intended for use inside the visit functions of Visit* and WalkDeps.
	OtherModuleName(m Module) string

	// OtherModuleDir returns the directory of another Module.  See BaseModuleContext.ModuleDir for more information.
	// It is intended for use inside the visit functions of Visit* and WalkDeps.
	OtherModuleDir(m Module) string

	// OtherModuleSubDir returns the unique subdirectory name of another Module.  See ModuleContext.ModuleSubDir for
	// more information.
	// It is intended for use inside the visit functions of Visit* and WalkDeps.
	OtherModuleSubDir(m Module) string

	// OtherModuleType returns the type of another Module.  See BaseModuleContext.ModuleType for more information.
	// It is intended for use inside the visit functions of Visit* and WalkDeps.
	OtherModuleType(m Module) string

	// OtherModuleErrorf reports an error on another Module.  See BaseModuleContext.ModuleErrorf for more information.
	// It is intended for use inside the visit functions of Visit* and WalkDeps.
	OtherModuleErrorf(m Module, fmt string, args ...interface{})

	// OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
	// on the module.  When called inside a Visit* method with current module being visited, and there are multiple
	// dependencies on the module being visited, it returns the dependency tag used for the current dependency.
	OtherModuleDependencyTag(m Module) DependencyTag

	// OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
	// passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
	OtherModuleExists(name string) bool

	// OtherModuleDependencyVariantExists returns true if a module with the
	// specified name and variant exists. The variant must match the given
	// variations. It must also match all the non-local variations of the current
	// module. In other words, it checks for the module AddVariationDependencies
	// would add a dependency on with the same arguments.
	OtherModuleDependencyVariantExists(variations []Variation, name string) bool

	// OtherModuleReverseDependencyVariantExists returns true if a module with the
	// specified name exists with the same variations as the current module. In
	// other words, it checks for the module AddReverseDependency would add a
	// dependency on with the same argument.
	OtherModuleReverseDependencyVariantExists(name string) bool
}

type BaseMutatorContext

type BaseMutatorContext interface {
	BaseModuleContext

	// Rename all variants of a module.  The new name is not visible to calls to ModuleName,
	// AddDependency or OtherModuleName until after this mutator pass is complete.
	Rename(name string)

	// MutatorName returns the name that this mutator was registered with.
	MutatorName() string
}

type BlueprintError

type BlueprintError struct {
	Err error            // the error that occurred
	Pos scanner.Position // the relevant Blueprints file location
}

An Error describes a problem that was encountered that is related to a particular location in a Blueprints file.

func (*BlueprintError) Error

func (e *BlueprintError) Error() string

type BottomUpMutator

type BottomUpMutator func(mctx BottomUpMutatorContext)

type BottomUpMutatorContext

type BottomUpMutatorContext interface {
	BaseMutatorContext

	// AddDependency adds a dependency to the given module.
	// Does not affect the ordering of the current mutator pass, but will be ordered
	// correctly for all future mutator passes.
	AddDependency(module Module, tag DependencyTag, name ...string)

	// AddReverseDependency adds a dependency from the destination to the given module.
	// Does not affect the ordering of the current mutator pass, but will be ordered
	// correctly for all future mutator passes.  All reverse dependencies for a destination module are
	// collected until the end of the mutator pass, sorted by name, and then appended to the destination
	// module's dependency list.
	AddReverseDependency(module Module, tag DependencyTag, name string)

	// CreateVariations splits  a module into mulitple variants, one for each name in the variationNames
	// parameter.  It returns a list of new modules in the same order as the variationNames
	// list.
	//
	// If any of the dependencies of the module being operated on were already split
	// by calling CreateVariations with the same name, the dependency will automatically
	// be updated to point the matching variant.
	//
	// If a module is split, and then a module depending on the first module is not split
	// when the Mutator is later called on it, the dependency of the depending module will
	// automatically be updated to point to the first variant.
	CreateVariations(...string) []Module

	// CreateLocationVariations splits a module into mulitple variants, one for each name in the variantNames
	// parameter.  It returns a list of new modules in the same order as the variantNames
	// list.
	//
	// Local variations do not affect automatic dependency resolution - dependencies added
	// to the split module via deps or DynamicDependerModule must exactly match a variant
	// that contains all the non-local variations.
	CreateLocalVariations(...string) []Module

	// SetDependencyVariation sets all dangling dependencies on the current module to point to the variation
	// with given name. This function ignores the default variation set by SetDefaultDependencyVariation.
	SetDependencyVariation(string)

	// SetDefaultDependencyVariation sets the default variation when a dangling reference is detected
	// during the subsequent calls on Create*Variations* functions. To reset, set it to nil.
	SetDefaultDependencyVariation(*string)

	// AddVariationDependencies adds deps as dependencies of the current module, but uses the variations
	// argument to select which variant of the dependency to use.  A variant of the dependency must
	// exist that matches the all of the non-local variations of the current module, plus the variations
	// argument.
	AddVariationDependencies([]Variation, DependencyTag, ...string)

	// AddFarVariationDependencies adds deps as dependencies of the current module, but uses the
	// variations argument to select which variant of the dependency to use.  A variant of the
	// dependency must exist that matches the variations argument, but may also have other variations.
	// For any unspecified variation the first variant will be used.
	//
	// Unlike AddVariationDependencies, the variations of the current module are ignored - the
	// dependency only needs to match the supplied variations.
	AddFarVariationDependencies([]Variation, DependencyTag, ...string)

	// AddInterVariantDependency adds a dependency between two variants of the same module.  Variants are always
	// ordered in the same orderas they were listed in CreateVariations, and AddInterVariantDependency does not change
	// that ordering, but it associates a DependencyTag with the dependency and makes it visible to VisitDirectDeps,
	// WalkDeps, etc.
	AddInterVariantDependency(tag DependencyTag, from, to Module)

	// ReplaceDependencies replaces all dependencies on the identical variant of the module with the
	// specified name with the current variant of this module.  Replacements don't take effect until
	// after the mutator pass is finished.
	ReplaceDependencies(string)

	// ReplaceDependencies replaces all dependencies on the identical variant of the module with the
	// specified name with the current variant of this module as long as the supplied predicate returns
	// true.
	//
	// Replacements don't take effect until after the mutator pass is finished.
	ReplaceDependenciesIf(string, ReplaceDependencyPredicate)

	// AliasVariation takes a variationName that was passed to CreateVariations for this module,
	// and creates an alias from the current variant (before the mutator has run) to the new
	// variant.  The alias will be valid until the next time a mutator calls CreateVariations or
	// CreateLocalVariations on this module without also calling AliasVariation.  The alias can
	// be used to add dependencies on the newly created variant using the variant map from
	// before CreateVariations was run.
	AliasVariation(variationName string)

	// CreateAliasVariation takes a toVariationName that was passed to CreateVariations for this
	// module, and creates an alias from a new fromVariationName variant the toVariationName
	// variant.  The alias will be valid until the next time a mutator calls CreateVariations or
	// CreateLocalVariations on this module without also calling AliasVariation.  The alias can
	// be used to add dependencies on the toVariationName variant using the fromVariationName
	// variant.
	CreateAliasVariation(fromVariationName, toVariationName string)
}

type BuildParams

type BuildParams struct {
	Comment         string            // The comment that will appear above the definition.
	Depfile         string            // The dependency file name.
	Deps            Deps              // The format of the dependency file.
	Description     string            // The description that Ninja will print for the build.
	Rule            Rule              // The rule to invoke.
	Outputs         []string          // The list of explicit output targets.
	ImplicitOutputs []string          // The list of implicit output targets.
	Inputs          []string          // The list of explicit input dependencies.
	Implicits       []string          // The list of implicit input dependencies.
	OrderOnly       []string          // The list of order-only dependencies.
	Args            map[string]string // The variable/value pairs to set.
	Optional        bool              // Skip outputting a default statement
}

A BuildParams object contains the set of parameters that make up a Ninja build statement. Each field except for Args corresponds with a part of the Ninja build statement. The Args field contains variable names and values that are set within the build statement's scope in the Ninja file.

type Context

type Context struct {
	context.Context
	// contains filtered or unexported fields
}

A Context contains all the state needed to parse a set of Blueprints files and generate a Ninja file. The process of generating a Ninja file proceeds through a series of four phases. Each phase corresponds with a some methods on the Context object

      Phase                            Methods
   ------------      -------------------------------------------
1. Registration         RegisterModuleType, RegisterSingletonType

2. Parse                    ParseBlueprintsFiles, Parse

3. Generate            ResolveDependencies, PrepareBuildActions

4. Write                           WriteBuildFile

The registration phase prepares the context to process Blueprints files containing various types of modules. The parse phase reads in one or more Blueprints files and validates their contents against the module types that have been registered. The generate phase then analyzes the parsed Blueprints contents to create an internal representation for the build actions that must be performed. This phase also performs validation of the module dependencies and property values defined in the parsed Blueprints files. Finally, the write phase generates the Ninja manifest text based on the generated build actions.

func NewContext

func NewContext() *Context

NewContext creates a new Context object. The created context initially has no module or singleton factories registered, so the RegisterModuleFactory and RegisterSingletonFactory methods must be called before it can do anything useful.

func (*Context) AllTargets

func (c *Context) AllTargets() (map[string]string, error)

AllTargets returns a map all the build target names to the rule used to build them. This is the same information that is output by running 'ninja -t targets all'. If this is called before PrepareBuildActions successfully completes then ErrbuildActionsNotReady is returned.

func (*Context) BlueprintFile

func (c *Context) BlueprintFile(logicModule Module) string

func (*Context) FinalModule

func (c *Context) FinalModule(module Module) Module

func (*Context) Globs

func (c *Context) Globs() []GlobPath

func (*Context) ListModulePaths

func (c *Context) ListModulePaths(baseDir string) (paths []string, err error)

func (*Context) MockFileSystem

func (c *Context) MockFileSystem(files map[string][]byte)

MockFileSystem causes the Context to replace all reads with accesses to the provided map of filenames to contents stored as a byte slice.

func (*Context) ModuleDir

func (c *Context) ModuleDir(logicModule Module) string

func (*Context) ModuleErrorf

func (c *Context) ModuleErrorf(logicModule Module, format string,
	args ...interface{}) error

func (*Context) ModuleName

func (c *Context) ModuleName(logicModule Module) string

func (*Context) ModulePath

func (c *Context) ModulePath(logicModule Module) string

func (*Context) ModuleSubDir

func (c *Context) ModuleSubDir(logicModule Module) string

func (*Context) ModuleType

func (c *Context) ModuleType(logicModule Module) string

func (*Context) ModuleTypeFactories

func (c *Context) ModuleTypeFactories() map[string]ModuleFactory

func (*Context) ModuleTypePropertyStructs

func (c *Context) ModuleTypePropertyStructs() map[string][]interface{}

ModuleTypePropertyStructs returns a mapping from module type name to a list of pointers to property structs returned by the factory for that module type.

func (*Context) NinjaBuildDir

func (c *Context) NinjaBuildDir() (string, error)

func (*Context) ParseBlueprintsFiles

func (c *Context) ParseBlueprintsFiles(rootFile string,
	config interface{}) (deps []string, errs []error)

ParseBlueprintsFiles parses a set of Blueprints files starting with the file at rootFile. When it encounters a Blueprints file with a set of subdirs listed it recursively parses any Blueprints files found in those subdirectories.

If no errors are encountered while parsing the files, the list of paths on which the future output will depend is returned. This list will include both Blueprints file paths as well as directory paths for cases where wildcard subdirs are found.

func (*Context) ParseFileList

func (c *Context) ParseFileList(rootDir string, filePaths []string,
	config interface{}) (deps []string, errs []error)

func (*Context) PrepareBuildActions

func (c *Context) PrepareBuildActions(config interface{}) (deps []string, errs []error)

PrepareBuildActions generates an internal representation of all the build actions that need to be performed. This process involves invoking the GenerateBuildActions method on each of the Module objects created during the parse phase and then on each of the registered Singleton objects.

If the ResolveDependencies method has not already been called it is called automatically by this method.

The config argument is made available to all of the Module and Singleton objects via the Config method on the ModuleContext and SingletonContext objects passed to GenerateBuildActions. It is also passed to the functions specified via PoolFunc, RuleFunc, and VariableFunc so that they can compute config-specific values.

The returned deps is a list of the ninja files dependencies that were added by the modules and singletons via the ModuleContext.AddNinjaFileDeps(), SingletonContext.AddNinjaFileDeps(), and PackageContext.AddNinjaFileDeps() methods.

func (*Context) PrimaryModule

func (c *Context) PrimaryModule(module Module) Module

func (*Context) RegisterBottomUpMutator

func (c *Context) RegisterBottomUpMutator(name string, mutator BottomUpMutator) MutatorHandle

RegisterBottomUpMutator registers a mutator that will be invoked to split Modules into variants. Each registered mutator is invoked in registration order (mixing TopDownMutators and BottomUpMutators) once per Module, will not be invoked on a module until the invocations on all of the modules dependencies have returned.

The mutator type names given here must be unique to all bottom up or early mutators in the Context.

Returns a MutatorHandle, on which Parallel can be called to set the mutator to visit modules in parallel while maintaining ordering.

func (*Context) RegisterEarlyMutator

func (c *Context) RegisterEarlyMutator(name string, mutator EarlyMutator)

RegisterEarlyMutator registers a mutator that will be invoked to split Modules into multiple variant Modules before any dependencies have been created. Each registered mutator is invoked in registration order once per Module (including each variant from previous early mutators). Module order is unpredictable.

In order for dependencies to be satisifed in a later pass, all dependencies of a module either must have an identical variant or must have no variations.

The mutator type names given here must be unique to all bottom up or early mutators in the Context.

Deprecated, use a BottomUpMutator instead. The only difference between EarlyMutator and BottomUpMutator is that EarlyMutator runs before the deprecated DynamicDependencies.

func (*Context) RegisterModuleType

func (c *Context) RegisterModuleType(name string, factory ModuleFactory)

RegisterModuleType associates a module type name (which can appear in a Blueprints file) with a Module factory function. When the given module type name is encountered in a Blueprints file during parsing, the Module factory is invoked to instantiate a new Module object to handle the build action generation for the module. If a Mutator splits a module into multiple variants, the factory is invoked again to create a new Module for each variant.

The module type names given here must be unique for the context. The factory function should be a named function so that its package and name can be included in the generated Ninja file for debugging purposes.

The factory function returns two values. The first is the newly created Module object. The second is a slice of pointers to that Module object's properties structs. Each properties struct is examined when parsing a module definition of this type in a Blueprints file. Exported fields of the properties structs are automatically set to the property values specified in the Blueprints file. The properties struct field names determine the name of the Blueprints file properties that are used - the Blueprints property name matches that of the properties struct field name with the first letter converted to lower-case.

The fields of the properties struct must be either []string, a string, or bool. The Context will panic if a Module gets instantiated with a properties struct containing a field that is not one these supported types.

Any properties that appear in the Blueprints files that are not built-in module properties (such as "name" and "deps") and do not have a corresponding field in the returned module properties struct result in an error during the Context's parse phase.

As an example, the follow code:

type myModule struct {
    properties struct {
        Foo string
        Bar []string
    }
}

func NewMyModule() (blueprint.Module, []interface{}) {
    module := new(myModule)
    properties := &module.properties
    return module, []interface{}{properties}
}

func main() {
    ctx := blueprint.NewContext()
    ctx.RegisterModuleType("my_module", NewMyModule)
    // ...
}

would support parsing a module defined in a Blueprints file as follows:

my_module {
    name: "myName",
    foo:  "my foo string",
    bar:  ["my", "bar", "strings"],
}

The factory function may be called from multiple goroutines. Any accesses to global variables must be synchronized.

func (*Context) RegisterPreSingletonType

func (c *Context) RegisterPreSingletonType(name string, factory SingletonFactory)

RegisterPreSingletonType registers a presingleton type that will be invoked to generate build actions before any Blueprint files have been read. Each registered presingleton type is instantiated and invoked exactly once at the beginning of the parse phase. Each registered presingleton is invoked in registration order.

The presingleton type names given here must be unique for the context. The factory function should be a named function so that its package and name can be included in the generated Ninja file for debugging purposes.

func (*Context) RegisterSingletonType

func (c *Context) RegisterSingletonType(name string, factory SingletonFactory)

RegisterSingletonType registers a singleton type that will be invoked to generate build actions. Each registered singleton type is instantiated and and invoked exactly once as part of the generate phase. Each registered singleton is invoked in registration order.

The singleton type names given here must be unique for the context. The factory function should be a named function so that its package and name can be included in the generated Ninja file for debugging purposes.

func (*Context) RegisterTopDownMutator

func (c *Context) RegisterTopDownMutator(name string, mutator TopDownMutator) MutatorHandle

RegisterTopDownMutator registers a mutator that will be invoked to propagate dependency info top-down between Modules. Each registered mutator is invoked in registration order (mixing TopDownMutators and BottomUpMutators) once per Module, and the invocation on any module will have returned before it is in invoked on any of its dependencies.

The mutator type names given here must be unique to all top down mutators in the Context.

Returns a MutatorHandle, on which Parallel can be called to set the mutator to visit modules in parallel while maintaining ordering.

func (*Context) ResolveDependencies

func (c *Context) ResolveDependencies(config interface{}) (deps []string, errs []error)

ResolveDependencies checks that the dependencies specified by all of the modules defined in the parsed Blueprints files are valid. This means that the modules depended upon are defined and that no circular dependencies exist.

func (*Context) SetAllowMissingDependencies

func (c *Context) SetAllowMissingDependencies(allowMissingDependencies bool)

SetAllowMissingDependencies changes the behavior of Blueprint to ignore unresolved dependencies. If the module's GenerateBuildActions calls ModuleContext.GetMissingDependencies Blueprint will not emit any errors for missing dependencies.

func (*Context) SetFs

func (c *Context) SetFs(fs pathtools.FileSystem)

func (*Context) SetIgnoreUnknownModuleTypes

func (c *Context) SetIgnoreUnknownModuleTypes(ignoreUnknownModuleTypes bool)

SetIgnoreUnknownModuleTypes sets the behavior of the context in the case where it encounters an unknown module type while parsing Blueprints files. By default, the context will report unknown module types as an error. If this method is called with ignoreUnknownModuleTypes set to true then the context will silently ignore unknown module types.

This method should generally not be used. It exists to facilitate the bootstrapping process.

func (*Context) SetModuleListFile

func (c *Context) SetModuleListFile(listFile string)

func (*Context) SetNameInterface

func (c *Context) SetNameInterface(i NameInterface)

func (*Context) SetSrcDir

func (c *Context) SetSrcDir(path string)

func (*Context) SingletonName

func (c *Context) SingletonName(singleton Singleton) string

SingletonName returns the name that the given singleton was registered with.

func (*Context) Singletons

func (c *Context) Singletons() []Singleton

Singletons returns a list of all registered Singletons.

func (*Context) SrcDir

func (c *Context) SrcDir() string

func (*Context) VisitAllModuleVariants

func (c *Context) VisitAllModuleVariants(module Module,
	visit func(Module))

func (*Context) VisitAllModules

func (c *Context) VisitAllModules(visit func(Module))

func (*Context) VisitAllModulesIf

func (c *Context) VisitAllModulesIf(pred func(Module) bool,
	visit func(Module))

func (*Context) VisitDepsDepthFirst

func (c *Context) VisitDepsDepthFirst(module Module, visit func(Module))

func (*Context) VisitDepsDepthFirstIf

func (c *Context) VisitDepsDepthFirstIf(module Module, pred func(Module) bool, visit func(Module))

func (*Context) VisitDirectDeps

func (c *Context) VisitDirectDeps(module Module, visit func(Module))

func (*Context) VisitDirectDepsIf

func (c *Context) VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module))

func (*Context) WalkBlueprintsFiles

func (c *Context) WalkBlueprintsFiles(rootDir string, filePaths []string,
	visitor FileHandler) (deps []string, errs []error)

WalkBlueprintsFiles walks a set of Blueprints files starting with the given filepaths, calling the given file handler on each

When WalkBlueprintsFiles encounters a Blueprints file with a set of subdirs listed, it recursively parses any Blueprints files found in those subdirectories.

If any of the file paths is an ancestor directory of any other of file path, the ancestor will be parsed and visited first.

the file handler will be called from a goroutine, so it must be reentrant.

If no errors are encountered while parsing the files, the list of paths on which the future output will depend is returned. This list will include both Blueprints file paths as well as directory paths for cases where wildcard subdirs are found.

visitor will be called asynchronously, and will only be called once visitor for each ancestor directory has completed.

WalkBlueprintsFiles will not return until all calls to visitor have returned.

func (*Context) WriteBuildFile

func (c *Context) WriteBuildFile(w io.Writer) error

WriteBuildFile writes the Ninja manifeset text for the generated build actions to w. If this is called before PrepareBuildActions successfully completes then ErrBuildActionsNotReady is returned.

type DependencyTag

type DependencyTag interface {
	// contains filtered or unexported methods
}

DependencyTag is an interface to an arbitrary object that embeds BaseDependencyTag. It can be used to transfer information on a dependency between the mutator that called AddDependency and the GenerateBuildActions method. Variants created by CreateVariations have a copy of the interface (pointing to the same concrete object) from their original module.

type Deps

type Deps int

A Deps value indicates the dependency file format that Ninja should expect to be output by a compiler.

const (
	DepsNone Deps = iota
	DepsGCC
	DepsMSVC
)

func (Deps) String

func (d Deps) String() string

type DynamicDependerModule

type DynamicDependerModule interface {
	Module

	// DynamicDependencies is called by the Context that created the
	// DynamicDependerModule during its generate phase.  This call should return
	// the list of module names that the DynamicDependerModule depends on
	// dynamically.  Module names that already appear in the "deps" property may
	// but do not need to be included in the returned list.
	DynamicDependencies(DynamicDependerModuleContext) []string
}

A DynamicDependerModule is a Module that may add dependencies that do not appear in its "deps" property. Any Module that implements this interface will have its DynamicDependencies method called by the Context that created it during generate phase.

Deprecated, use a BottomUpMutator instead

type DynamicDependerModuleContext

type DynamicDependerModuleContext BottomUpMutatorContext

type EarlyModuleContext

type EarlyModuleContext interface {
	// Module returns the current module as a Module.  It should rarely be necessary, as the module already has a
	// reference to itself.
	Module() Module

	// ModuleName returns the name of the module.  This is generally the value that was returned by Module.Name() when
	// the module was created, but may have been modified by calls to BaseMutatorContext.Rename.
	ModuleName() string

	// ModuleDir returns the path to the directory that contains the defintion of the module.
	ModuleDir() string

	// ModuleType returns the name of the module type that was used to create the module, as specified in
	// RegisterModuleType.
	ModuleType() string

	// BlueprintFile returns the name of the blueprint file that contains the definition of this
	// module.
	BlueprintsFile() string

	// Config returns the config object that was passed to Context.PrepareBuildActions.
	Config() interface{}

	// ContainsProperty returns true if the specified property name was set in the module definition.
	ContainsProperty(name string) bool

	// Errorf reports an error at the specified position of the module definition file.
	Errorf(pos scanner.Position, fmt string, args ...interface{})

	// ModuleErrorf reports an error at the line number of the module type in the module definition.
	ModuleErrorf(fmt string, args ...interface{})

	// PropertyErrorf reports an error at the line number of a property in the module definition.
	PropertyErrorf(property, fmt string, args ...interface{})

	// Failed returns true if any errors have been reported.  In most cases the module can continue with generating
	// build rules after an error, allowing it to report additional errors in a single run, but in cases where the error
	// has prevented the module from creating necessary data it can return early when Failed returns true.
	Failed() bool

	// GlobWithDeps returns a list of files and directories that match the
	// specified pattern but do not match any of the patterns in excludes.
	// Any directories will have a '/' suffix.  It also adds efficient
	// dependencies to rerun the primary builder whenever a file matching
	// the pattern as added or removed, without rerunning if a file that
	// does not match the pattern is added to a searched directory.
	GlobWithDeps(pattern string, excludes []string) ([]string, error)

	// Fs returns a pathtools.Filesystem that can be used to interact with files.  Using the Filesystem interface allows
	// the module to be used in build system tests that run against a mock filesystem.
	Fs() pathtools.FileSystem

	// AddNinjaFileDeps adds dependencies on the specified files to the rule that creates the ninja manifest.  The
	// primary builder will be rerun whenever the specified files are modified.
	AddNinjaFileDeps(deps ...string)

	// Namespace returns the Namespace object provided by the NameInterface set by Context.SetNameInterface, or the
	// default SimpleNameInterface if Context.SetNameInterface was not called.
	Namespace() Namespace

	// ModuleFactories returns a map of all of the global ModuleFactories by name.
	ModuleFactories() map[string]ModuleFactory
	// contains filtered or unexported methods
}

type EarlyMutator

type EarlyMutator func(mctx EarlyMutatorContext)

type EarlyMutatorContext

type EarlyMutatorContext interface {
	BaseMutatorContext

	// CreateVariations splits  a module into mulitple variants, one for each name in the variationNames
	// parameter.  It returns a list of new modules in the same order as the variationNames
	// list.
	//
	// If any of the dependencies of the module being operated on were already split
	// by calling CreateVariations with the same name, the dependency will automatically
	// be updated to point the matching variant.
	//
	// If a module is split, and then a module depending on the first module is not split
	// when the Mutator is later called on it, the dependency of the depending module will
	// automatically be updated to point to the first variant.
	CreateVariations(...string) []Module

	// CreateLocationVariations splits a module into mulitple variants, one for each name in the variantNames
	// parameter.  It returns a list of new modules in the same order as the variantNames
	// list.
	//
	// Local variations do not affect automatic dependency resolution - dependencies added
	// to the split module via deps or DynamicDependerModule must exactly match a variant
	// that contains all the non-local variations.
	CreateLocalVariations(...string) []Module
}

type FileHandler

type FileHandler func(*parser.File)

type GlobPath

type GlobPath struct {
	Pattern  string
	Excludes []string
	Files    []string
	Deps     []string
	Name     string
}

type LoadHook

type LoadHook func(ctx LoadHookContext)

type LoadHookContext

type LoadHookContext interface {
	EarlyModuleContext

	// CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
	// the specified property structs to it as if the properties were set in a blueprint file.
	CreateModule(ModuleFactory, ...interface{}) Module

	// RegisterScopedModuleType creates a new module type that is scoped to the current Blueprints
	// file.
	RegisterScopedModuleType(name string, factory ModuleFactory)
}

type Module

type Module interface {
	// Name returns a string used to uniquely identify each module.  The return
	// value must be unique across all modules.  It is only called once, during
	// initial blueprint parsing.  To change the name later a mutator must call
	// MutatorContext.Rename
	//
	// In most cases, Name should return the contents of a "name:" property from
	// the blueprint file.  An embeddable SimpleName object can be used for this
	// case.
	Name() string

	// GenerateBuildActions is called by the Context that created the Module
	// during its generate phase.  This call should generate all Ninja build
	// actions (rules, pools, and build statements) needed to build the module.
	GenerateBuildActions(ModuleContext)
}

A Module handles generating all of the Ninja build actions needed to build a single module based on properties defined in a Blueprints file. Module objects are initially created during the parse phase of a Context using one of the registered module types (and the associated ModuleFactory function). The Module's properties struct is automatically filled in with the property values specified in the Blueprints file (see Context.RegisterModuleType for more information on this).

A Module can be split into multiple Modules by a Mutator. All existing properties set on the module will be duplicated to the new Module, and then modified as necessary by the Mutator.

The Module implementation can access the build configuration as well as any modules on which on which it depends (as defined by the "deps" property specified in the Blueprints file, dynamically added by implementing the (deprecated) DynamicDependerModule interface, or dynamically added by a BottomUpMutator) using the ModuleContext passed to GenerateBuildActions. This ModuleContext is also used to create Ninja build actions and to report errors to the user.

In addition to implementing the GenerateBuildActions method, a Module should implement methods that provide dependant modules and singletons information they need to generate their build actions. These methods will only be called after GenerateBuildActions is called because the Context calls GenerateBuildActions in dependency-order (and singletons are invoked after all the Modules). The set of methods a Module supports will determine how dependant Modules interact with it.

For example, consider a Module that is responsible for generating a library that other modules can link against. The library Module might implement the following interface:

type LibraryProducer interface {
    LibraryFileName() string
}

func IsLibraryProducer(module blueprint.Module) {
    _, ok := module.(LibraryProducer)
    return ok
}

A binary-producing Module that depends on the library Module could then do:

func (m *myBinaryModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
    ...
    var libraryFiles []string
    ctx.VisitDepsDepthFirstIf(IsLibraryProducer,
        func(module blueprint.Module) {
            libProducer := module.(LibraryProducer)
            libraryFiles = append(libraryFiles, libProducer.LibraryFileName())
        })
    ...
}

to build the list of library file names that should be included in its link command.

GenerateBuildActions may be called from multiple threads. It is guaranteed to be called after it has finished being called on all dependencies and on all variants of that appear earlier in the ModuleContext.VisitAllModuleVariants list. Any accesses to global variables or to Module objects that are not dependencies or variants of the current Module must be synchronized by the implementation of GenerateBuildActions.

type ModuleContext

type ModuleContext interface {
	BaseModuleContext

	// ModuleSubDir returns a unique name for the current variant of a module that can be used as part of the path
	// to ensure that each variant of a module gets its own intermediates directory to write to.
	ModuleSubDir() string

	// Variable creates a new ninja variable scoped to the module.  It can be referenced by calls to Rule and Build
	// in the same module.
	Variable(pctx PackageContext, name, value string)

	// Rule creates a new ninja rule scoped to the module.  It can be referenced by calls to Build in the same module.
	Rule(pctx PackageContext, name string, params RuleParams, argNames ...string) Rule

	// Build creates a new ninja build statement.
	Build(pctx PackageContext, params BuildParams)

	// PrimaryModule returns the first variant of the current module.  Variants of a module are always visited in
	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
	// Module returned by PrimaryModule without data races.  This can be used to perform singleton actions that are
	// only done once for all variants of a module.
	PrimaryModule() Module

	// FinalModule returns the last variant of the current module.  Variants of a module are always visited in
	// order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
	// variants using VisitAllModuleVariants if the current module == FinalModule().  This can be used to perform
	// singleton actions that are only done once for all variants of a module.
	FinalModule() Module

	// VisitAllModuleVariants calls visit for each variant of the current module.  Variants of a module are always
	// visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
	// from all variants if the current module == FinalModule().  Otherwise, care must be taken to not access any
	// data modified by the current mutator.
	VisitAllModuleVariants(visit func(Module))

	// GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods,
	// but do not exist.  It can be used with Context.SetAllowMissingDependencies to allow the primary builder to
	// handle missing dependencies on its own instead of having Blueprint treat them as an error.
	GetMissingDependencies() []string
}

type ModuleError

type ModuleError struct {
	BlueprintError
	// contains filtered or unexported fields
}

A ModuleError describes a problem that was encountered that is related to a particular module in a Blueprints file

func (*ModuleError) Error

func (e *ModuleError) Error() string

type ModuleFactory

type ModuleFactory func() (m Module, propertyStructs []interface{})

A ModuleFactory function creates a new Module object. See the Context.RegisterModuleType method for details about how a registered ModuleFactory is used by a Context.

type ModuleGroup

type ModuleGroup struct {
	// contains filtered or unexported fields
}

A ModuleGroup just points to a moduleGroup to allow external packages to refer to a moduleGroup but not use it

func (*ModuleGroup) String

func (h *ModuleGroup) String() string

type MutatorHandle

type MutatorHandle interface {
	// Set the mutator to visit modules in parallel while maintaining ordering.  Calling any
	// method on the mutator context is thread-safe, but the mutator must handle synchronization
	// for any modifications to global state or any modules outside the one it was invoked on.
	Parallel() MutatorHandle
}

type NameInterface

type NameInterface interface {
	// Gets called when a new module is created
	NewModule(ctx NamespaceContext, group ModuleGroup, module Module) (namespace Namespace, err []error)

	// Finds the module with the given name
	ModuleFromName(moduleName string, namespace Namespace) (group ModuleGroup, found bool)

	// Returns an error indicating that the given module could not be found.
	// The error contains some diagnostic information about where the dependency can be found.
	MissingDependencyError(depender string, dependerNamespace Namespace, depName string) (err error)

	// Rename
	Rename(oldName string, newName string, namespace Namespace) []error

	// Returns all modules in a deterministic order.
	AllModules() []ModuleGroup

	// gets the namespace for a given path
	GetNamespace(ctx NamespaceContext) (namespace Namespace)

	// returns a deterministic, unique, arbitrary string for the given name in the given namespace
	UniqueName(ctx NamespaceContext, name string) (unique string)
}

A NameInterface tells how to locate modules by name. There should only be one name interface per Context, but potentially many namespaces

type Namespace

type Namespace interface {
	// contains filtered or unexported methods
}

The Namespace interface is just a marker interface for usage by the NameInterface, to allow a NameInterface to specify that a certain parameter should be a Namespace. In practice, a specific NameInterface will expect to only give and receive structs of the same concrete type, but because Go doesn't support generics, we use a marker interface for a little bit of clarity, and expect implementers to do typecasting instead.

type NamespaceContext

type NamespaceContext interface {
	ModulePath() string
}

A NamespaceContext stores the information given to a NameInterface to enable the NameInterface to choose the namespace for any given module

type NamespaceMarker

type NamespaceMarker struct {
}

type PackageContext

type PackageContext interface {
	Import(pkgPath string)
	ImportAs(as, pkgPath string)

	StaticVariable(name, value string) Variable
	VariableFunc(name string, f func(config interface{}) (string, error)) Variable
	VariableConfigMethod(name string, method interface{}) Variable

	StaticPool(name string, params PoolParams) Pool
	PoolFunc(name string, f func(interface{}) (PoolParams, error)) Pool

	StaticRule(name string, params RuleParams, argNames ...string) Rule
	RuleFunc(name string, f func(interface{}) (RuleParams, error), argNames ...string) Rule

	AddNinjaFileDeps(deps ...string)
	// contains filtered or unexported methods
}

A PackageContext provides a way to create package-scoped Ninja pools, rules, and variables. A Go package should create a single unexported package-scoped PackageContext variable that it uses to create all package- scoped Ninja object definitions. This PackageContext object should then be passed to all calls to define module- or singleton-specific Ninja definitions. For example:

package blah

import (
    "blueprint"
)

var (
    pctx = NewPackageContext("path/to/blah")

    myPrivateVar = pctx.StaticVariable("myPrivateVar", "abcdef")
    MyExportedVar = pctx.StaticVariable("MyExportedVar", "$myPrivateVar 123456!")

    SomeRule = pctx.StaticRule(...)
)

// ...

func (m *MyModule) GenerateBuildActions(ctx blueprint.Module) {
    ctx.Build(pctx, blueprint.BuildParams{
        Rule:    SomeRule,
        Outputs: []string{"$myPrivateVar"},
    })
}

func NewPackageContext

func NewPackageContext(pkgPath string) PackageContext

NewPackageContext creates a PackageContext object for a given package. The pkgPath argument should always be set to the full path used to import the package. This function may only be called from a Go package's init() function or as part of a package-scoped variable initialization.

type Pool

type Pool interface {
	String() string
	// contains filtered or unexported methods
}

A Pool represents a Ninja pool that will be written to the output .ninja file.

var Console Pool = NewBuiltinPool("console")

func NewBuiltinPool

func NewBuiltinPool(name string) Pool

NewBuiltinPool returns a Pool object that refers to a pool name created outside of Blueprint

type PoolParams

type PoolParams struct {
	Comment string // The comment that will appear above the definition.
	Depth   int    // The Ninja pool depth.
}

A PoolParams object contains the set of parameters that make up a Ninja pool definition.

type PropertyError

type PropertyError struct {
	ModuleError
	// contains filtered or unexported fields
}

A PropertyError describes a problem that was encountered that is related to a particular property in a Blueprints file

func (*PropertyError) Error

func (e *PropertyError) Error() string

type ReplaceDependencyPredicate

type ReplaceDependencyPredicate func(from Module, tag DependencyTag, to Module) bool

type Rule

type Rule interface {
	String() string
	// contains filtered or unexported methods
}

A Rule represents a Ninja build rule that will be written to the output .ninja file.

var Phony Rule = NewBuiltinRule("phony")

func NewBuiltinRule

func NewBuiltinRule(name string) Rule

NewBuiltinRule returns a Rule object that refers to a rule that was created outside of Blueprint

type RuleParams

type RuleParams struct {
	// These fields correspond to a Ninja variable of the same name.
	Command        string // The command that Ninja will run for the rule.
	Depfile        string // The dependency file name.
	Deps           Deps   // The format of the dependency file.
	Description    string // The description that Ninja will print for the rule.
	Generator      bool   // Whether the rule generates the Ninja manifest file.
	Pool           Pool   // The Ninja pool to which the rule belongs.
	Restat         bool   // Whether Ninja should re-stat the rule's outputs.
	Rspfile        string // The response file.
	RspfileContent string // The response file content.

	// These fields are used internally in Blueprint
	CommandDeps      []string // Command-specific implicit dependencies to prepend to builds
	CommandOrderOnly []string // Command-specific order-only dependencies to prepend to builds
	Comment          string   // The comment that will appear above the definition.
}

A RuleParams object contains the set of parameters that make up a Ninja rule definition.

type SimpleName

type SimpleName struct {
	Properties struct {
		Name string
	}
}

SimpleName is an embeddable object to implement the ModuleContext.Name method using a property called "name". Modules that embed it must also add SimpleName.Properties to their property structure list.

func (*SimpleName) Name

func (s *SimpleName) Name() string

type SimpleNameInterface

type SimpleNameInterface struct {
	// contains filtered or unexported fields
}

a SimpleNameInterface just stores all modules in a map based on name

func NewSimpleNameInterface

func NewSimpleNameInterface() *SimpleNameInterface

func (*SimpleNameInterface) AllModules

func (s *SimpleNameInterface) AllModules() []ModuleGroup

func (*SimpleNameInterface) GetNamespace

func (s *SimpleNameInterface) GetNamespace(ctx NamespaceContext) Namespace

func (*SimpleNameInterface) MissingDependencyError

func (s *SimpleNameInterface) MissingDependencyError(depender string, dependerNamespace Namespace, dependency string) (err error)

func (*SimpleNameInterface) ModuleFromName

func (s *SimpleNameInterface) ModuleFromName(moduleName string, namespace Namespace) (group ModuleGroup, found bool)

func (*SimpleNameInterface) NewModule

func (s *SimpleNameInterface) NewModule(ctx NamespaceContext, group ModuleGroup, module Module) (namespace Namespace, err []error)

func (*SimpleNameInterface) Rename

func (s *SimpleNameInterface) Rename(oldName string, newName string, namespace Namespace) (errs []error)

func (*SimpleNameInterface) UniqueName

func (s *SimpleNameInterface) UniqueName(ctx NamespaceContext, name string) (unique string)

type Singleton

type Singleton interface {
	GenerateBuildActions(SingletonContext)
}

type SingletonContext

type SingletonContext interface {
	// Config returns the config object that was passed to Context.PrepareBuildActions.
	Config() interface{}

	// Name returns the name of the current singleton passed to Context.RegisterSingletonType
	Name() string

	// ModuleName returns the name of the given Module.  See BaseModuleContext.ModuleName for more information.
	ModuleName(module Module) string

	// ModuleDir returns the directory of the given Module.  See BaseModuleContext.ModuleDir for more information.
	ModuleDir(module Module) string

	// ModuleSubDir returns the unique subdirectory name of the given Module.  See ModuleContext.ModuleSubDir for
	// more information.
	ModuleSubDir(module Module) string

	// ModuleType returns the type of the given Module.  See BaseModuleContext.ModuleType for more information.
	ModuleType(module Module) string

	// BlueprintFile returns the path of the Blueprint file that defined the given module.
	BlueprintFile(module Module) string

	// ModuleErrorf reports an error at the line number of the module type in the module definition.
	ModuleErrorf(module Module, format string, args ...interface{})

	// Errorf reports an error at the specified position of the module definition file.
	Errorf(format string, args ...interface{})

	// Failed returns true if any errors have been reported.  In most cases the singleton can continue with generating
	// build rules after an error, allowing it to report additional errors in a single run, but in cases where the error
	// has prevented the singleton from creating necessary data it can return early when Failed returns true.
	Failed() bool

	// Variable creates a new ninja variable scoped to the singleton.  It can be referenced by calls to Rule and Build
	// in the same singleton.
	Variable(pctx PackageContext, name, value string)

	// Rule creates a new ninja rule scoped to the singleton.  It can be referenced by calls to Build in the same
	// singleton.
	Rule(pctx PackageContext, name string, params RuleParams, argNames ...string) Rule

	// Build creates a new ninja build statement.
	Build(pctx PackageContext, params BuildParams)

	// RequireNinjaVersion sets the generated ninja manifest to require at least the specified version of ninja.
	RequireNinjaVersion(major, minor, micro int)

	// SetNinjaBuildDir sets the value of the top-level "builddir" Ninja variable
	// that controls where Ninja stores its build log files.  This value can be
	// set at most one time for a single build, later calls are ignored.
	SetNinjaBuildDir(pctx PackageContext, value string)

	// AddSubninja adds a ninja file to include with subninja. This should likely
	// only ever be used inside bootstrap to handle glob rules.
	AddSubninja(file string)

	// Eval takes a string with embedded ninja variables, and returns a string
	// with all of the variables recursively expanded. Any variables references
	// are expanded in the scope of the PackageContext.
	Eval(pctx PackageContext, ninjaStr string) (string, error)

	// VisitAllModules calls visit for each defined variant of each module in an unspecified order.
	VisitAllModules(visit func(Module))

	// VisitAllModules calls pred for each defined variant of each module in an unspecified order, and if pred returns
	// true calls visit.
	VisitAllModulesIf(pred func(Module) bool, visit func(Module))

	// VisitDirectDeps calls visit for each direct dependency of the Module.  If there are
	// multiple direct dependencies on the same module visit will be called multiple times on
	// that module and OtherModuleDependencyTag will return a different tag for each.
	//
	// The Module passed to the visit function should not be retained outside of the visit
	// function, it may be invalidated by future mutators.
	VisitDirectDeps(module Module, visit func(Module))

	// VisitDirectDepsIf calls pred for each direct dependency of the Module, and if pred
	// returns true calls visit.  If there are multiple direct dependencies on the same module
	// pred and visit will be called multiple times on that module and OtherModuleDependencyTag
	// will return a different tag for each.
	//
	// The Module passed to the visit function should not be retained outside of the visit
	// function, it may be invalidated by future mutators.
	VisitDirectDepsIf(module Module, pred func(Module) bool, visit func(Module))

	// VisitDepsDepthFirst calls visit for each transitive dependency, traversing the dependency tree in depth first
	// order. visit will only be called once for any given module, even if there are multiple paths through the
	// dependency tree to the module or multiple direct dependencies with different tags.
	VisitDepsDepthFirst(module Module, visit func(Module))

	// VisitDepsDepthFirst calls pred for each transitive dependency, and if pred returns true calls visit, traversing
	// the dependency tree in depth first order.  visit will only be called once for any given module, even if there are
	// multiple paths through the dependency tree to the module or multiple direct dependencies with different tags.
	VisitDepsDepthFirstIf(module Module, pred func(Module) bool,
		visit func(Module))

	// VisitAllModuleVariants calls visit for each variant of the given module.
	VisitAllModuleVariants(module Module, visit func(Module))

	// PrimaryModule returns the first variant of the given module.  This can be used to perform
	//	// singleton actions that are only done once for all variants of a module.
	PrimaryModule(module Module) Module

	// FinalModule returns the last variant of the given module.  This can be used to perform
	// singleton actions that are only done once for all variants of a module.
	FinalModule(module Module) Module

	// AddNinjaFileDeps adds dependencies on the specified files to the rule that creates the ninja manifest.  The
	// primary builder will be rerun whenever the specified files are modified.
	AddNinjaFileDeps(deps ...string)

	// GlobWithDeps returns a list of files and directories that match the
	// specified pattern but do not match any of the patterns in excludes.
	// Any directories will have a '/' suffix. It also adds efficient
	// dependencies to rerun the primary builder whenever a file matching
	// the pattern as added or removed, without rerunning if a file that
	// does not match the pattern is added to a searched directory.
	GlobWithDeps(pattern string, excludes []string) ([]string, error)

	// Fs returns a pathtools.Filesystem that can be used to interact with files.  Using the Filesystem interface allows
	// the singleton to be used in build system tests that run against a mock filesystem.
	Fs() pathtools.FileSystem
}

type SingletonFactory

type SingletonFactory func() Singleton

A SingletonFactory function creates a new Singleton object. See the Context.RegisterSingletonType method for details about how a registered SingletonFactory is used by a Context.

type TopDownMutator

type TopDownMutator func(mctx TopDownMutatorContext)

A Mutator function is called for each Module, and can use MutatorContext.CreateVariations to split a Module into multiple Modules, modifying properties on the new modules to differentiate them. It is called after parsing all Blueprint files, but before generating any build rules, and is always called on dependencies before being called on the depending module.

The Mutator function should only modify members of properties structs, and not members of the module struct itself, to ensure the modified values are copied if a second Mutator chooses to split the module a second time.

type TopDownMutatorContext

type TopDownMutatorContext interface {
	BaseMutatorContext

	// CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
	// the specified property structs to it as if the properties were set in a blueprint file.
	CreateModule(ModuleFactory, ...interface{}) Module
}

type Variable

type Variable interface {
	String() string
	// contains filtered or unexported methods
}

A Variable represents a global Ninja variable definition that will be written to the output .ninja file. A variable may contain references to other global Ninja variables, but circular variable references are not allowed.

type Variation

type Variation struct {
	// Mutator is the axis on which this variation applies, i.e. "arch" or "link"
	Mutator string
	// Variation is the name of the variation on the axis, i.e. "arm" or "arm64" for arch, or
	// "shared" or "static" for link.
	Variation string
}

A Variation is a way that a variant of a module differs from other variants of the same module. For example, two variants of the same module might have Variation{"arch","arm"} and Variation{"arch","arm64"}

Directories

Path Synopsis
The Blueprint bootstrapping mechanism is intended to enable building a source tree with minimal prebuilts.
The Blueprint bootstrapping mechanism is intended to enable building a source tree with minimal prebuilts.
bpglob
bpglob is the command line tool that checks if the list of files matching a glob has changed, and only updates the output file list if it has changed.
bpglob is the command line tool that checks if the list of files matching a glob has changed, and only updates the output file list if it has changed.
Microfactory is a tool to incrementally compile a go program.
Microfactory is a tool to incrementally compile a go program.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL