Home | History | Annotate | Download | only in soong
      1 package libchrome
      2 
      3 import (
      4 	"fmt"
      5 	"path"
      6 	"strings"
      7 
      8 	"android/soong/android"
      9 	"android/soong/genrule"
     10 
     11 	"github.com/google/blueprint"
     12 )
     13 
     14 func init() {
     15 	android.RegisterModuleType("generate_mojom_pickles", mojomPicklesFactory)
     16 	android.RegisterModuleType("generate_mojom_headers", mojomHeadersFactory)
     17 	android.RegisterModuleType("generate_mojom_srcs", mojomSrcsFactory)
     18 	android.RegisterModuleType("generate_mojom_srcjar", mojomSrcjarFactory)
     19 }
     20 
     21 var (
     22 	pctx = android.NewPackageContext("android/soong/external/libchrome")
     23 
     24 	mojomBindingsGenerator = pctx.HostBinToolVariable("mojomBindingsGenerator", "mojom_bindings_generator")
     25 	mergeZips              = pctx.HostBinToolVariable("mergeZips", "merge_zips")
     26 
     27 	generateMojomPicklesRule = pctx.StaticRule("generateMojomPicklesRule", blueprint.RuleParams{
     28 		Command: `${mojomBindingsGenerator}
     29 		--use_bundled_pylibs parse
     30 		-d ${package}
     31 		${flags}
     32 		-o ${outDir}
     33 		${in}`,
     34 		CommandDeps: []string{
     35 			"${mojomBindingsGenerator}",
     36 		},
     37 		Description: "Mojo pickles generation $in => $out",
     38 		Restat:      true,
     39 	}, "package", "flags", "outDir")
     40 
     41 	generateMojomSrcsRule = pctx.StaticRule("generateMojomSrcsRule", blueprint.RuleParams{
     42 		Command: `${mojomBindingsGenerator}
     43 		--use_bundled_pylibs generate
     44 		-o ${outDir}
     45 		-I=${package}:${package}
     46 		-d ${package}
     47 		${flags}
     48 		--bytecode_path=${templateDir}
     49 		--generators=${mojomGenerator}
     50 		--use_new_wrapper_types
     51 		${in}`,
     52 		CommandDeps: []string{
     53 			"${mojomBindingsGenerator}",
     54 		},
     55 		Description: "Mojo sources generation $in => $out",
     56 		Restat:      true,
     57 	}, "mojomGenerator", "package", "flags", "outDir", "templateDir")
     58 
     59 	mergeSrcjarsRule = pctx.StaticRule("mergeSrcjarsRule", blueprint.RuleParams{
     60 		Command: "${mergeZips} ${out} ${in}",
     61 		CommandDeps: []string{
     62 			"${mergeZips}",
     63 		},
     64 		Description: "Merge .srcjars $in => $out",
     65 	})
     66 )
     67 
     68 type mojomPicklesProperties struct {
     69 	// list of input files
     70 	Srcs []string
     71 }
     72 
     73 type mojomPickles struct {
     74 	android.ModuleBase
     75 
     76 	properties mojomPicklesProperties
     77 
     78 	generatedSrcs android.Paths
     79 	outDir        android.Path
     80 }
     81 
     82 var _ genrule.SourceFileGenerator = (*mojomPickles)(nil)
     83 
     84 func (m *mojomPickles) DepsMutator(ctx android.BottomUpMutatorContext) {
     85 	android.ExtractSourcesDeps(ctx, m.properties.Srcs)
     86 }
     87 
     88 func (m *mojomPickles) GenerateAndroidBuildActions(ctx android.ModuleContext) {
     89 	m.outDir = android.PathForModuleGen(ctx, "")
     90 
     91 	packagePath := android.PathForModuleSrc(ctx, "")
     92 
     93 	for _, in := range ctx.ExpandSources(m.properties.Srcs, nil) {
     94 		if !strings.HasSuffix(in.Rel(), ".mojom") {
     95 			ctx.PropertyErrorf("srcs", "Source is not a .mojom file: %s", in.Rel())
     96 			continue
     97 		}
     98 		relStem := strings.TrimSuffix(in.Rel(), ".mojom")
     99 
    100 		out := android.PathForModuleGen(ctx, relStem+".p")
    101 		m.generatedSrcs = append(m.generatedSrcs, out)
    102 
    103 		ctx.ModuleBuild(pctx, android.ModuleBuildParams{
    104 			Rule:   generateMojomPicklesRule,
    105 			Input:  in,
    106 			Output: out,
    107 			Args: map[string]string{
    108 				"package": packagePath.Rel(),
    109 				"outDir":  m.outDir.String(),
    110 				"flags":   fmt.Sprintf("-I=%s:%s", packagePath, packagePath),
    111 			},
    112 		})
    113 	}
    114 }
    115 
    116 func (m *mojomPickles) GeneratedHeaderDirs() android.Paths {
    117 	return nil
    118 }
    119 
    120 func (m *mojomPickles) GeneratedDeps() android.Paths {
    121 	return append(android.Paths{}, m.generatedSrcs...)
    122 }
    123 
    124 func (m *mojomPickles) GeneratedSourceFiles() android.Paths {
    125 	return append(android.Paths{}, m.generatedSrcs...)
    126 }
    127 
    128 func (m *mojomPickles) Srcs() android.Paths {
    129 	return append(android.Paths{}, m.generatedSrcs...)
    130 }
    131 
    132 func mojomPicklesFactory() android.Module {
    133 	m := &mojomPickles{}
    134 	m.AddProperties(&m.properties)
    135 	android.InitAndroidModule(m)
    136 	return m
    137 }
    138 
    139 // mojomGenerationProperties are the common properties across the header,
    140 // source and Java source modules.
    141 type mojomGenerationProperties struct {
    142 	// list of input files
    143 	Srcs []string
    144 
    145 	// name of the output .srcjar
    146 	Srcjar string
    147 
    148 	// name of the templates module
    149 	Templates string
    150 
    151 	// Additional flags to pass to the bindings generation script
    152 	Flags string
    153 
    154 	// list of pickles modules that will be imported
    155 	Pickles []string
    156 
    157 	// list of include paths
    158 	Includes []string
    159 
    160 	// list of typemaps modules that will be imported
    161 	Typemaps []string
    162 
    163 	// If true, set --use_once_callback flag to the generator.
    164 	// This works only on C++ generation.
    165 	Use_once_callback bool
    166 }
    167 
    168 // extractSources adds any necessary dependencies to satisfy filegroup or
    169 // generated sources modules listed in the properties using ":module" syntax,
    170 // if any.
    171 func (p *mojomGenerationProperties) extractSources(ctx android.BottomUpMutatorContext) {
    172 	android.ExtractSourcesDeps(ctx, p.Srcs)
    173 	android.ExtractSourcesDeps(ctx, p.Typemaps)
    174 	android.ExtractSourcesDeps(ctx, p.Pickles)
    175 	android.ExtractSourceDeps(ctx, &p.Templates)
    176 }
    177 
    178 // flags generates all needed flags for the build rule.
    179 func (p *mojomGenerationProperties) flags(ctx android.ModuleContext) string {
    180 	flags := []string{}
    181 
    182 	for _, typemap := range ctx.ExpandSources(p.Typemaps, nil) {
    183 		flags = append(flags, fmt.Sprintf("--typemap=%s", typemap.String()))
    184 	}
    185 	for _, include := range android.PathsForSource(ctx, p.Includes) {
    186 		flags = append(flags, fmt.Sprintf("-I=%s:%s", include, include))
    187 	}
    188 	for _, pickle := range p.Pickles {
    189 		m := android.SrcIsModule(pickle)
    190 		if m == "" {
    191 			ctx.PropertyErrorf("pickles", "not a module: %q", m)
    192 			continue
    193 		}
    194 		module := ctx.GetDirectDepWithTag(m, android.SourceDepTag).(*mojomPickles)
    195 		flags = append(flags, fmt.Sprintf("--gen_dir=%s", module.outDir.String()))
    196 	}
    197 	if p.Flags != "" {
    198 		flags = append(flags, p.Flags)
    199 	}
    200 	if p.Use_once_callback {
    201 		flags = append(flags, "--use_once_callback")
    202 	}
    203 
    204 	return strings.Join(flags, " ")
    205 }
    206 
    207 // implicitDeps collects all dependencies of the module.
    208 func (p *mojomGenerationProperties) implicitDeps(ctx android.ModuleContext) android.Paths {
    209 	deps := android.Paths{}
    210 	deps = append(deps, ctx.ExpandSources(p.Pickles, nil)...)
    211 	deps = append(deps, ctx.ExpandSources(p.Typemaps, nil)...)
    212 	deps = append(deps, ctx.ExpandSources([]string{p.Templates}, nil)...)
    213 	return deps
    214 }
    215 
    216 // templateDir returns the path where the template .zips are located.
    217 func (p *mojomGenerationProperties) templateDir(ctx android.ModuleContext) string {
    218 	srcFiles := ctx.ExpandSources([]string{p.Templates}, nil)
    219 	if len(srcFiles) == 0 {
    220 		ctx.PropertyErrorf("templates", "module %s does not produce any files", p.Templates)
    221 		return ""
    222 	}
    223 	return path.Dir(srcFiles[0].String())
    224 }
    225 
    226 // mojomSrcsRuleDescription has the necessary arguments to perform one
    227 // invocation of generateMojomSrcsRule.
    228 type mojomSrcsRuleDescription struct {
    229 	generatedExtensions []string
    230 	extraFlags          string
    231 }
    232 
    233 // generateBuildActions generates all the necessary build actions for the
    234 // current module.
    235 func (p *mojomGenerationProperties) generateBuildActions(
    236 	ctx android.ModuleContext,
    237 	mojomGenerator string,
    238 	descriptions []mojomSrcsRuleDescription,
    239 ) android.Paths {
    240 	packageName := android.PathForModuleSrc(ctx, "").Rel()
    241 	outDir := android.PathForModuleGen(ctx, "")
    242 	implicitDeps := p.implicitDeps(ctx)
    243 	templateDir := p.templateDir(ctx)
    244 	generatedSrcs := android.Paths{}
    245 
    246 	for _, in := range ctx.ExpandSources(p.Srcs, nil) {
    247 		if !strings.HasSuffix(in.Rel(), ".mojom") {
    248 			ctx.PropertyErrorf("srcs", "Source is not a .mojom file: %s", in.Rel())
    249 			continue
    250 		}
    251 		relStem := strings.TrimSuffix(in.Rel(), ".mojom")
    252 
    253 		for _, description := range descriptions {
    254 			outs := android.WritablePaths{}
    255 			for _, ext := range description.generatedExtensions {
    256 				out := android.PathForModuleGen(ctx, relStem+ext)
    257 				outs = append(outs, out)
    258 				generatedSrcs = append(generatedSrcs, out)
    259 			}
    260 			ctx.ModuleBuild(pctx, android.ModuleBuildParams{
    261 				Rule:      generateMojomSrcsRule,
    262 				Input:     in,
    263 				Implicits: implicitDeps,
    264 				Outputs:   outs,
    265 				Args: map[string]string{
    266 					"mojomGenerator": mojomGenerator,
    267 					"package":        packageName,
    268 					"flags":          fmt.Sprintf("%s %s", p.flags(ctx), description.extraFlags),
    269 					"outDir":         outDir.String(),
    270 					"templateDir":    templateDir,
    271 				},
    272 			})
    273 		}
    274 	}
    275 
    276 	return generatedSrcs
    277 }
    278 
    279 // mojomHeaders generates all the .h files for a .mojom source.
    280 type mojomHeaders struct {
    281 	android.ModuleBase
    282 
    283 	properties mojomGenerationProperties
    284 
    285 	exportedHeaderDirs android.Paths
    286 	generatedSrcs      android.Paths
    287 }
    288 
    289 var _ genrule.SourceFileGenerator = (*mojomHeaders)(nil)
    290 
    291 func (m *mojomHeaders) DepsMutator(ctx android.BottomUpMutatorContext) {
    292 	m.properties.extractSources(ctx)
    293 }
    294 
    295 func (m *mojomHeaders) GenerateAndroidBuildActions(ctx android.ModuleContext) {
    296 	m.generatedSrcs = m.properties.generateBuildActions(
    297 		ctx,
    298 		"c++",
    299 		[]mojomSrcsRuleDescription{
    300 			{
    301 				generatedExtensions: []string{".mojom.h"},
    302 				extraFlags:          "",
    303 			},
    304 			{
    305 				generatedExtensions: []string{".mojom-shared.h", ".mojom-shared-internal.h"},
    306 				extraFlags:          "--generate_non_variant_code",
    307 			},
    308 			{
    309 				generatedExtensions: []string{".mojom-shared-message-ids.h"},
    310 				extraFlags:          "--generate_message_ids --generate_non_variant_code",
    311 			},
    312 		},
    313 	)
    314 	m.exportedHeaderDirs = append(m.exportedHeaderDirs, android.PathForModuleGen(ctx, ""))
    315 }
    316 
    317 func (m *mojomHeaders) GeneratedHeaderDirs() android.Paths {
    318 	return m.exportedHeaderDirs
    319 }
    320 
    321 func (m *mojomHeaders) GeneratedDeps() android.Paths {
    322 	return append(android.Paths{}, m.generatedSrcs...)
    323 }
    324 
    325 func (m *mojomHeaders) GeneratedSourceFiles() android.Paths {
    326 	return append(android.Paths{}, m.generatedSrcs...)
    327 }
    328 
    329 func (m *mojomHeaders) Srcs() android.Paths {
    330 	return append(android.Paths{}, m.generatedSrcs...)
    331 }
    332 
    333 func mojomHeadersFactory() android.Module {
    334 	m := &mojomHeaders{}
    335 	m.AddProperties(&m.properties)
    336 	android.InitAndroidModule(m)
    337 	return m
    338 }
    339 
    340 // mojomHeaders generates all the .cc files for a .mojom source.
    341 type mojomSrcs struct {
    342 	android.ModuleBase
    343 
    344 	properties mojomGenerationProperties
    345 
    346 	generatedSrcs android.Paths
    347 }
    348 
    349 var _ genrule.SourceFileGenerator = (*mojomSrcs)(nil)
    350 
    351 func (m *mojomSrcs) DepsMutator(ctx android.BottomUpMutatorContext) {
    352 	m.properties.extractSources(ctx)
    353 }
    354 
    355 func (m *mojomSrcs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
    356 	m.generatedSrcs = m.properties.generateBuildActions(
    357 		ctx,
    358 		"c++",
    359 		[]mojomSrcsRuleDescription{
    360 			{
    361 				generatedExtensions: []string{".mojom.cc"},
    362 				extraFlags:          "",
    363 			},
    364 			{
    365 				generatedExtensions: []string{".mojom-shared.cc"},
    366 				extraFlags:          "--generate_non_variant_code",
    367 			},
    368 		},
    369 	)
    370 }
    371 
    372 func (m *mojomSrcs) GeneratedHeaderDirs() android.Paths {
    373 	return nil
    374 }
    375 
    376 func (m *mojomSrcs) GeneratedDeps() android.Paths {
    377 	return append(android.Paths{}, m.generatedSrcs...)
    378 }
    379 
    380 func (m *mojomSrcs) GeneratedSourceFiles() android.Paths {
    381 	return append(android.Paths{}, m.generatedSrcs...)
    382 }
    383 
    384 func (m *mojomSrcs) Srcs() android.Paths {
    385 	return append(android.Paths{}, m.generatedSrcs...)
    386 }
    387 
    388 func mojomSrcsFactory() android.Module {
    389 	m := &mojomSrcs{}
    390 	m.AddProperties(&m.properties)
    391 	android.InitAndroidModule(m)
    392 	return m
    393 }
    394 
    395 // mojomHeaders generates the .srcjar file for a set of .mojom source.
    396 type mojomSrcjar struct {
    397 	android.ModuleBase
    398 
    399 	properties mojomGenerationProperties
    400 
    401 	outDir        android.Path
    402 	generatedSrcs android.Paths
    403 }
    404 
    405 var _ genrule.SourceFileGenerator = (*mojomSrcjar)(nil)
    406 
    407 func (m *mojomSrcjar) DepsMutator(ctx android.BottomUpMutatorContext) {
    408 	m.properties.extractSources(ctx)
    409 }
    410 
    411 func (m *mojomSrcjar) GenerateAndroidBuildActions(ctx android.ModuleContext) {
    412 	srcjars := m.properties.generateBuildActions(
    413 		ctx,
    414 		"java",
    415 		[]mojomSrcsRuleDescription{
    416 			{
    417 				generatedExtensions: []string{".mojom.srcjar"},
    418 				extraFlags:          "",
    419 			},
    420 		},
    421 	)
    422 
    423 	out := android.PathForModuleGen(ctx, m.properties.Srcjar)
    424 	ctx.ModuleBuild(pctx, android.ModuleBuildParams{
    425 		Rule:   mergeSrcjarsRule,
    426 		Inputs: srcjars,
    427 		Output: out,
    428 	})
    429 	m.generatedSrcs = append(m.generatedSrcs, out)
    430 }
    431 
    432 func (m *mojomSrcjar) GeneratedHeaderDirs() android.Paths {
    433 	return nil
    434 }
    435 
    436 func (m *mojomSrcjar) GeneratedDeps() android.Paths {
    437 	return append(android.Paths{}, m.generatedSrcs...)
    438 }
    439 
    440 func (m *mojomSrcjar) GeneratedSourceFiles() android.Paths {
    441 	return append(android.Paths{}, m.generatedSrcs...)
    442 }
    443 
    444 func (m *mojomSrcjar) Srcs() android.Paths {
    445 	return append(android.Paths{}, m.generatedSrcs...)
    446 }
    447 
    448 func mojomSrcjarFactory() android.Module {
    449 	m := &mojomSrcjar{}
    450 	m.AddProperties(&m.properties)
    451 	android.InitAndroidModule(m)
    452 	return m
    453 }
    454