Home | History | Annotate | Download | only in genrule
      1 // Copyright 2015 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 genrule
     16 
     17 import (
     18 	"github.com/google/blueprint"
     19 
     20 	"android/soong"
     21 	"android/soong/common"
     22 )
     23 
     24 func init() {
     25 	soong.RegisterModuleType("gensrcs", GenSrcsFactory)
     26 	soong.RegisterModuleType("genrule", GenRuleFactory)
     27 
     28 	common.RegisterBottomUpMutator("genrule_deps", genruleDepsMutator)
     29 }
     30 
     31 var (
     32 	pctx = common.NewPackageContext("android/soong/genrule")
     33 )
     34 
     35 func init() {
     36 	pctx.SourcePathVariable("srcDir", "")
     37 	pctx.HostBinToolVariable("hostBin", "")
     38 }
     39 
     40 type SourceFileGenerator interface {
     41 	GeneratedSourceFiles() common.Paths
     42 }
     43 
     44 type HostToolProvider interface {
     45 	HostToolPath() common.OptionalPath
     46 }
     47 
     48 type generatorProperties struct {
     49 	// command to run on one or more input files.  Available variables for substitution:
     50 	// $in: one or more input files
     51 	// $out: a single output file
     52 	// $srcDir: the root directory of the source tree
     53 	// The host bin directory will be in the path
     54 	Cmd string
     55 
     56 	// name of the module (if any) that produces the host executable.   Leave empty for
     57 	// prebuilts or scripts that do not need a module to build them.
     58 	Tool string
     59 }
     60 
     61 type generator struct {
     62 	common.AndroidModuleBase
     63 
     64 	properties generatorProperties
     65 
     66 	tasks taskFunc
     67 
     68 	deps common.Paths
     69 	rule blueprint.Rule
     70 
     71 	outputFiles common.Paths
     72 }
     73 
     74 type taskFunc func(ctx common.AndroidModuleContext) []generateTask
     75 
     76 type generateTask struct {
     77 	in  common.Paths
     78 	out common.ModuleGenPath
     79 }
     80 
     81 func (g *generator) GeneratedSourceFiles() common.Paths {
     82 	return g.outputFiles
     83 }
     84 
     85 func genruleDepsMutator(ctx common.AndroidBottomUpMutatorContext) {
     86 	if g, ok := ctx.Module().(*generator); ok {
     87 		if g.properties.Tool != "" {
     88 			ctx.AddFarVariationDependencies([]blueprint.Variation{
     89 				{"host_or_device", common.Host.String()},
     90 				{"host_type", common.CurrentHostType().String()},
     91 			}, g.properties.Tool)
     92 		}
     93 	}
     94 }
     95 
     96 func (g *generator) GenerateAndroidBuildActions(ctx common.AndroidModuleContext) {
     97 	g.rule = ctx.Rule(pctx, "generator", blueprint.RuleParams{
     98 		Command: "PATH=$$PATH:$hostBin " + g.properties.Cmd,
     99 	})
    100 
    101 	ctx.VisitDirectDeps(func(module blueprint.Module) {
    102 		if t, ok := module.(HostToolProvider); ok {
    103 			p := t.HostToolPath()
    104 			if p.Valid() {
    105 				g.deps = append(g.deps, p.Path())
    106 			} else {
    107 				ctx.ModuleErrorf("host tool %q missing output file", ctx.OtherModuleName(module))
    108 			}
    109 		} else {
    110 			ctx.ModuleErrorf("unknown dependency %q", ctx.OtherModuleName(module))
    111 		}
    112 	})
    113 
    114 	for _, task := range g.tasks(ctx) {
    115 		g.generateSourceFile(ctx, task)
    116 	}
    117 }
    118 
    119 func (g *generator) generateSourceFile(ctx common.AndroidModuleContext, task generateTask) {
    120 	ctx.ModuleBuild(pctx, common.ModuleBuildParams{
    121 		Rule:      g.rule,
    122 		Output:    task.out,
    123 		Inputs:    task.in,
    124 		Implicits: g.deps,
    125 	})
    126 
    127 	g.outputFiles = append(g.outputFiles, task.out)
    128 }
    129 
    130 func generatorFactory(tasks taskFunc, props ...interface{}) (blueprint.Module, []interface{}) {
    131 	module := &generator{
    132 		tasks: tasks,
    133 	}
    134 
    135 	props = append(props, &module.properties)
    136 
    137 	return common.InitAndroidModule(module, props...)
    138 }
    139 
    140 func GenSrcsFactory() (blueprint.Module, []interface{}) {
    141 	properties := &genSrcsProperties{}
    142 
    143 	tasks := func(ctx common.AndroidModuleContext) []generateTask {
    144 		srcFiles := ctx.ExpandSources(properties.Srcs, nil)
    145 		tasks := make([]generateTask, 0, len(srcFiles))
    146 		for _, in := range srcFiles {
    147 			tasks = append(tasks, generateTask{
    148 				in:  common.Paths{in},
    149 				out: common.GenPathWithExt(ctx, in, properties.Output_extension),
    150 			})
    151 		}
    152 		return tasks
    153 	}
    154 
    155 	return generatorFactory(tasks, properties)
    156 }
    157 
    158 type genSrcsProperties struct {
    159 	// list of input files
    160 	Srcs []string
    161 
    162 	// extension that will be substituted for each output file
    163 	Output_extension string
    164 }
    165 
    166 func GenRuleFactory() (blueprint.Module, []interface{}) {
    167 	properties := &genRuleProperties{}
    168 
    169 	tasks := func(ctx common.AndroidModuleContext) []generateTask {
    170 		return []generateTask{
    171 			{
    172 				in:  ctx.ExpandSources(properties.Srcs, nil),
    173 				out: properties.Out,
    174 			},
    175 		}
    176 	}
    177 
    178 	return generatorFactory(tasks, properties)
    179 }
    180 
    181 type genRuleProperties struct {
    182 	// list of input files
    183 	Srcs []string
    184 
    185 	// name of the output file that will be generated
    186 	Out common.ModuleGenPath
    187 }
    188