Relax module naming restrictions
Forcing module names to be valid ninja names is an unnecessary restraint on the project build logic. Allow any string as a module name, and sanitize and uniquify the module name for use in module-scoped variables. Also move the module scope to be per-module instead of per-group so that modules can use the same local variable name for each variant. Change-Id: If44cca20712305e2c0b6d6b39daa5eace335c148
This commit is contained in:
parent
50fb09375a
commit
6134a5c66a
3 changed files with 48 additions and 22 deletions
45
context.go
45
context.go
|
@ -26,6 +26,7 @@ import (
|
|||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/scanner"
|
||||
"text/template"
|
||||
|
@ -67,6 +68,7 @@ type Context struct {
|
|||
moduleGroupsSorted []*moduleGroup
|
||||
singletonInfo map[string]*singletonInfo
|
||||
mutatorInfo []*mutatorInfo
|
||||
moduleNinjaNames map[string]*moduleGroup
|
||||
|
||||
dependenciesReady bool // set to true on a successful ResolveDependencies
|
||||
buildActionsReady bool // set to true on a successful PrepareBuildActions
|
||||
|
@ -106,6 +108,7 @@ type localBuildActions struct {
|
|||
type moduleGroup struct {
|
||||
// set during Parse
|
||||
typeName string
|
||||
ninjaName string
|
||||
relBlueprintsFile string
|
||||
pos scanner.Position
|
||||
propertyPos map[string]scanner.Position
|
||||
|
@ -182,10 +185,11 @@ func (e *Error) Error() string {
|
|||
// useful.
|
||||
func NewContext() *Context {
|
||||
return &Context{
|
||||
moduleFactories: make(map[string]ModuleFactory),
|
||||
moduleGroups: make(map[string]*moduleGroup),
|
||||
moduleInfo: make(map[Module]*moduleInfo),
|
||||
singletonInfo: make(map[string]*singletonInfo),
|
||||
moduleFactories: make(map[string]ModuleFactory),
|
||||
moduleGroups: make(map[string]*moduleGroup),
|
||||
moduleInfo: make(map[Module]*moduleInfo),
|
||||
singletonInfo: make(map[string]*singletonInfo),
|
||||
moduleNinjaNames: make(map[string]*moduleGroup),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -790,23 +794,23 @@ func (c *Context) processModuleDef(moduleDef *parser.Module,
|
|||
return nil, errs
|
||||
}
|
||||
|
||||
ninjaName := toNinjaName(group.properties.Name)
|
||||
|
||||
// The sanitizing in toNinjaName can result in collisions, uniquify the name if it
|
||||
// already exists
|
||||
for i := 0; c.moduleNinjaNames[ninjaName] != nil; i++ {
|
||||
ninjaName = toNinjaName(group.properties.Name) + strconv.Itoa(i)
|
||||
}
|
||||
|
||||
c.moduleNinjaNames[ninjaName] = group
|
||||
group.ninjaName = ninjaName
|
||||
|
||||
group.pos = moduleDef.Type.Pos
|
||||
group.propertyPos = make(map[string]scanner.Position)
|
||||
for name, propertyDef := range propertyMap {
|
||||
group.propertyPos[name] = propertyDef.Pos
|
||||
}
|
||||
|
||||
name := group.properties.Name
|
||||
err := validateNinjaName(name)
|
||||
if err != nil {
|
||||
return nil, []error{
|
||||
&Error{
|
||||
Err: fmt.Errorf("invalid module name %q: %s", err),
|
||||
Pos: group.propertyPos["name"],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
module := &moduleInfo{
|
||||
group: group,
|
||||
logicModule: logicModule,
|
||||
|
@ -1317,12 +1321,13 @@ func (c *Context) generateModuleBuildActions(config interface{},
|
|||
}()
|
||||
|
||||
c.parallelVisitAllBottomUp(func(group *moduleGroup) bool {
|
||||
// The parent scope of the moduleContext's local scope gets overridden to be that of the
|
||||
// calling Go package on a per-call basis. Since the initial parent scope doesn't matter we
|
||||
// just set it to nil.
|
||||
scope := newLocalScope(nil, moduleNamespacePrefix(group.properties.Name))
|
||||
|
||||
for _, module := range group.modules {
|
||||
// The parent scope of the moduleContext's local scope gets overridden to be that of the
|
||||
// calling Go package on a per-call basis. Since the initial parent scope doesn't matter we
|
||||
// just set it to nil.
|
||||
prefix := moduleNamespacePrefix(group.ninjaName + "_" + module.subName())
|
||||
scope := newLocalScope(nil, prefix)
|
||||
|
||||
mctx := &moduleContext{
|
||||
baseModuleContext: baseModuleContext{
|
||||
context: c,
|
||||
|
|
4
doc.go
4
doc.go
|
@ -13,7 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
// Blueprint is a meta-build system that reads in Blueprints files that describe
|
||||
// modules that need to be built, and produces a Ninja
|
||||
// modules that need to be built, and produces a Ninja
|
||||
// (http://martine.github.io/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 langauge to describe the logic how modules are
|
||||
|
@ -25,7 +25,7 @@
|
|||
//
|
||||
// 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
|
||||
// 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
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
package blueprint
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
@ -288,6 +289,26 @@ func validateNinjaName(name string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func toNinjaName(name string) string {
|
||||
ret := bytes.Buffer{}
|
||||
ret.Grow(len(name))
|
||||
for _, r := range name {
|
||||
valid := (r >= 'a' && r <= 'z') ||
|
||||
(r >= 'A' && r <= 'Z') ||
|
||||
(r >= '0' && r <= '9') ||
|
||||
(r == '_') ||
|
||||
(r == '-') ||
|
||||
(r == '.')
|
||||
if valid {
|
||||
ret.WriteRune(r)
|
||||
} else {
|
||||
ret.WriteRune('_')
|
||||
}
|
||||
}
|
||||
|
||||
return ret.String()
|
||||
}
|
||||
|
||||
var builtinRuleArgs = []string{"out", "in"}
|
||||
|
||||
func validateArgName(argName string) error {
|
||||
|
|
Loading…
Reference in a new issue