Home | History | Annotate | Download | only in blueprint
      1 // Copyright 2014 Google Inc. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 package blueprint
     16 
     17 import (
     18 	"fmt"
     19 	"github.com/google/blueprint/pathtools"
     20 )
     21 
     22 type Singleton interface {
     23 	GenerateBuildActions(SingletonContext)
     24 }
     25 
     26 type SingletonContext interface {
     27 	Config() interface{}
     28 
     29 	ModuleName(module Module) string
     30 	ModuleDir(module Module) string
     31 	ModuleSubDir(module Module) string
     32 	ModuleType(module Module) string
     33 	BlueprintFile(module Module) string
     34 
     35 	ModuleErrorf(module Module, format string, args ...interface{})
     36 	Errorf(format string, args ...interface{})
     37 	Failed() bool
     38 
     39 	Variable(pctx PackageContext, name, value string)
     40 	Rule(pctx PackageContext, name string, params RuleParams, argNames ...string) Rule
     41 	Build(pctx PackageContext, params BuildParams)
     42 	RequireNinjaVersion(major, minor, micro int)
     43 
     44 	// SetNinjaBuildDir sets the value of the top-level "builddir" Ninja variable
     45 	// that controls where Ninja stores its build log files.  This value can be
     46 	// set at most one time for a single build, later calls are ignored.
     47 	SetNinjaBuildDir(pctx PackageContext, value string)
     48 
     49 	// Eval takes a string with embedded ninja variables, and returns a string
     50 	// with all of the variables recursively expanded. Any variables references
     51 	// are expanded in the scope of the PackageContext.
     52 	Eval(pctx PackageContext, ninjaStr string) (string, error)
     53 
     54 	VisitAllModules(visit func(Module))
     55 	VisitAllModulesIf(pred func(Module) bool, visit func(Module))
     56 	VisitDepsDepthFirst(module Module, visit func(Module))
     57 	VisitDepsDepthFirstIf(module Module, pred func(Module) bool,
     58 		visit func(Module))
     59 
     60 	VisitAllModuleVariants(module Module, visit func(Module))
     61 
     62 	PrimaryModule(module Module) Module
     63 	FinalModule(module Module) Module
     64 
     65 	AddNinjaFileDeps(deps ...string)
     66 
     67 	// GlobWithDeps returns a list of files that match the specified pattern but do not match any
     68 	// of the patterns in excludes.  It also adds efficient dependencies to rerun the primary
     69 	// builder whenever a file matching the pattern as added or removed, without rerunning if a
     70 	// file that does not match the pattern is added to a searched directory.
     71 	GlobWithDeps(pattern string, excludes []string) ([]string, error)
     72 
     73 	Fs() pathtools.FileSystem
     74 }
     75 
     76 var _ SingletonContext = (*singletonContext)(nil)
     77 
     78 type singletonContext struct {
     79 	context *Context
     80 	config  interface{}
     81 	scope   *localScope
     82 	globals *liveTracker
     83 
     84 	ninjaFileDeps []string
     85 	errs          []error
     86 
     87 	actionDefs localBuildActions
     88 }
     89 
     90 func (s *singletonContext) Config() interface{} {
     91 	return s.config
     92 }
     93 
     94 func (s *singletonContext) ModuleName(logicModule Module) string {
     95 	return s.context.ModuleName(logicModule)
     96 }
     97 
     98 func (s *singletonContext) ModuleDir(logicModule Module) string {
     99 	return s.context.ModuleDir(logicModule)
    100 }
    101 
    102 func (s *singletonContext) ModuleSubDir(logicModule Module) string {
    103 	return s.context.ModuleSubDir(logicModule)
    104 }
    105 
    106 func (s *singletonContext) ModuleType(logicModule Module) string {
    107 	return s.context.ModuleType(logicModule)
    108 }
    109 
    110 func (s *singletonContext) BlueprintFile(logicModule Module) string {
    111 	return s.context.BlueprintFile(logicModule)
    112 }
    113 
    114 func (s *singletonContext) error(err error) {
    115 	if err != nil {
    116 		s.errs = append(s.errs, err)
    117 	}
    118 }
    119 
    120 func (s *singletonContext) ModuleErrorf(logicModule Module, format string,
    121 	args ...interface{}) {
    122 
    123 	s.error(s.context.ModuleErrorf(logicModule, format, args...))
    124 }
    125 
    126 func (s *singletonContext) Errorf(format string, args ...interface{}) {
    127 	// TODO: Make this not result in the error being printed as "internal error"
    128 	s.error(fmt.Errorf(format, args...))
    129 }
    130 
    131 func (s *singletonContext) Failed() bool {
    132 	return len(s.errs) > 0
    133 }
    134 
    135 func (s *singletonContext) Variable(pctx PackageContext, name, value string) {
    136 	s.scope.ReparentTo(pctx)
    137 
    138 	v, err := s.scope.AddLocalVariable(name, value)
    139 	if err != nil {
    140 		panic(err)
    141 	}
    142 
    143 	s.actionDefs.variables = append(s.actionDefs.variables, v)
    144 }
    145 
    146 func (s *singletonContext) Rule(pctx PackageContext, name string,
    147 	params RuleParams, argNames ...string) Rule {
    148 
    149 	s.scope.ReparentTo(pctx)
    150 
    151 	r, err := s.scope.AddLocalRule(name, &params, argNames...)
    152 	if err != nil {
    153 		panic(err)
    154 	}
    155 
    156 	s.actionDefs.rules = append(s.actionDefs.rules, r)
    157 
    158 	return r
    159 }
    160 
    161 func (s *singletonContext) Build(pctx PackageContext, params BuildParams) {
    162 	s.scope.ReparentTo(pctx)
    163 
    164 	def, err := parseBuildParams(s.scope, &params)
    165 	if err != nil {
    166 		panic(err)
    167 	}
    168 
    169 	s.actionDefs.buildDefs = append(s.actionDefs.buildDefs, def)
    170 }
    171 
    172 func (s *singletonContext) Eval(pctx PackageContext, str string) (string, error) {
    173 	s.scope.ReparentTo(pctx)
    174 
    175 	ninjaStr, err := parseNinjaString(s.scope, str)
    176 	if err != nil {
    177 		return "", err
    178 	}
    179 
    180 	err = s.globals.addNinjaStringDeps(ninjaStr)
    181 	if err != nil {
    182 		return "", err
    183 	}
    184 
    185 	return ninjaStr.Eval(s.globals.variables)
    186 }
    187 
    188 func (s *singletonContext) RequireNinjaVersion(major, minor, micro int) {
    189 	s.context.requireNinjaVersion(major, minor, micro)
    190 }
    191 
    192 func (s *singletonContext) SetNinjaBuildDir(pctx PackageContext, value string) {
    193 	s.scope.ReparentTo(pctx)
    194 
    195 	ninjaValue, err := parseNinjaString(s.scope, value)
    196 	if err != nil {
    197 		panic(err)
    198 	}
    199 
    200 	s.context.setNinjaBuildDir(ninjaValue)
    201 }
    202 
    203 func (s *singletonContext) VisitAllModules(visit func(Module)) {
    204 	s.context.VisitAllModules(visit)
    205 }
    206 
    207 func (s *singletonContext) VisitAllModulesIf(pred func(Module) bool,
    208 	visit func(Module)) {
    209 
    210 	s.context.VisitAllModulesIf(pred, visit)
    211 }
    212 
    213 func (s *singletonContext) VisitDepsDepthFirst(module Module,
    214 	visit func(Module)) {
    215 
    216 	s.context.VisitDepsDepthFirst(module, visit)
    217 }
    218 
    219 func (s *singletonContext) VisitDepsDepthFirstIf(module Module,
    220 	pred func(Module) bool, visit func(Module)) {
    221 
    222 	s.context.VisitDepsDepthFirstIf(module, pred, visit)
    223 }
    224 
    225 func (s *singletonContext) PrimaryModule(module Module) Module {
    226 	return s.context.PrimaryModule(module)
    227 }
    228 
    229 func (s *singletonContext) FinalModule(module Module) Module {
    230 	return s.context.FinalModule(module)
    231 }
    232 
    233 func (s *singletonContext) VisitAllModuleVariants(module Module, visit func(Module)) {
    234 	s.context.VisitAllModuleVariants(module, visit)
    235 }
    236 
    237 func (s *singletonContext) AddNinjaFileDeps(deps ...string) {
    238 	s.ninjaFileDeps = append(s.ninjaFileDeps, deps...)
    239 }
    240 
    241 func (s *singletonContext) GlobWithDeps(pattern string,
    242 	excludes []string) ([]string, error) {
    243 	return s.context.glob(pattern, excludes)
    244 }
    245 
    246 func (s *singletonContext) Fs() pathtools.FileSystem {
    247 	return s.context.fs
    248 }
    249