// Copyright (C) 2017 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package hal2vts import ( "path/filepath" "sort" "strings" "sync" "android/soong/android" "android/soong/genrule" "github.com/google/blueprint" ) func init() { android.RegisterModuleType("hal2vts", hal2vtsFactory) } var ( pctx = android.NewPackageContext("android/soong/hal2vts") hidlGen = pctx.HostBinToolVariable("hidlGen", "hidl-gen") hidlGenCmd = "${hidlGen} -o ${genDir} -L vts ${args} " + "${pckg}@${ver}::${halFile}" hal2vtsRule = pctx.StaticRule("hal2vtsRule", blueprint.RuleParams{ Command: hidlGenCmd, CommandDeps: []string{"${hidlGen}"}, Description: "hidl-gen -l vts $in => $out", }, "genDir", "args", "pckg", "ver", "halFile") ) type hal2vtsProperties struct { Hidl_gen_args string Srcs []string Out []string } type hal2vts struct { android.ModuleBase properties hal2vtsProperties exportedHeaderDirs android.Paths generatedHeaders android.Paths } var _ genrule.SourceFileGenerator = (*hal2vts)(nil) func (h *hal2vts) GenerateAndroidBuildActions(ctx android.ModuleContext) { // Sort by name to match .hal to .vts file name. sort.Strings(h.properties.Out) srcFiles := ctx.ExpandSources(h.properties.Srcs, nil) sort.SliceStable(srcFiles, func(i, j int) bool { return strings.Compare(srcFiles[j].String(), srcFiles[i].String()) == 1 }) if len(srcFiles) != len(h.properties.Out) { ctx.ModuleErrorf("Number of inputs must be equal to number of outputs.") } args := h.properties.Hidl_gen_args genDir := android.PathForModuleGen(ctx, "").String() vtsList := vtsList(ctx.AConfig()) vtsListMutex.Lock() defer vtsListMutex.Unlock() for i, src := range srcFiles { out := android.PathForModuleGen(ctx, h.properties.Out[i]) if src.Ext() != ".hal" { ctx.ModuleErrorf("Source file has to be a .hal file.") } relOut, err := filepath.Rel(genDir, out.String()) if err != nil { ctx.ModuleErrorf("Cannot get relative output path.") } halDir := filepath.Dir(relOut) halFile := strings.TrimSuffix(src.Base(), ".hal") ver := filepath.Base(halDir) // Need this to transform directory path to hal name. // For example, audio/effect -> audio.effect pckg := strings.Replace(filepath.Dir(halDir), "/", ".", -1) ctx.ModuleBuild(pctx, android.ModuleBuildParams{ Rule: hal2vtsRule, Input: src, Output: out, Args: map[string]string{ "genDir": genDir, "args": args, "pckg": pckg, "ver": ver, "halFile": halFile, }, }) h.generatedHeaders = append(h.generatedHeaders, out) *vtsList = append(*vtsList, out) } h.exportedHeaderDirs = append(h.exportedHeaderDirs, android.PathForModuleGen(ctx, "")) } func (h *hal2vts) DepsMutator(ctx android.BottomUpMutatorContext) { android.ExtractSourcesDeps(ctx, h.properties.Srcs) } func (h *hal2vts) GeneratedHeaderDirs() android.Paths { return h.exportedHeaderDirs } func (h *hal2vts) GeneratedSourceFiles() android.Paths { return nil } func (h *hal2vts) GeneratedDeps() android.Paths { return h.generatedHeaders } func hal2vtsFactory() android.Module { h := &hal2vts{} h.AddProperties(&h.properties) android.InitAndroidModule(h) return h } func vtsList(config android.Config) *android.Paths { return config.Once("vtsList", func() interface{} { return &android.Paths{} }).(*android.Paths) } var vtsListMutex sync.Mutex func init() { android.RegisterMakeVarsProvider(pctx, makeVarsProvider) } func makeVarsProvider(ctx android.MakeVarsContext) { vtsList := vtsList(ctx.Config()).Strings() sort.Strings(vtsList) ctx.Strict("VTS_SPEC_FILE_LIST", strings.Join(vtsList, " ")) }