1// Copyright (C) 2017 The Android Open Source Project 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 15package hal2vts 16 17import ( 18 "path/filepath" 19 "sort" 20 "strings" 21 "sync" 22 23 "android/soong/android" 24 "android/soong/genrule" 25 26 "github.com/google/blueprint" 27) 28 29func init() { 30 android.RegisterModuleType("hal2vts", hal2vtsFactory) 31} 32 33var ( 34 pctx = android.NewPackageContext("android/soong/hal2vts") 35 36 hidlGen = pctx.HostBinToolVariable("hidlGen", "hidl-gen") 37 38 hidlGenCmd = "${hidlGen} -o ${genDir} -L vts " + 39 "-r android.hardware:hardware/interfaces " + 40 "-r android.hidl:system/libhidl/transport " + 41 "${pckg}@${ver}::${halFile}" 42 43 hal2vtsRule = pctx.StaticRule("hal2vtsRule", blueprint.RuleParams{ 44 Command: hidlGenCmd, 45 CommandDeps: []string{"${hidlGen}"}, 46 Description: "hidl-gen -l vts $in => $out", 47 }, "genDir", "pckg", "ver", "halFile") 48) 49 50type hal2vtsProperties struct { 51 Srcs []string 52 Out []string 53} 54 55type hal2vts struct { 56 android.ModuleBase 57 58 properties hal2vtsProperties 59 60 exportedHeaderDirs android.Paths 61 generatedHeaders android.Paths 62} 63 64var _ genrule.SourceFileGenerator = (*hal2vts)(nil) 65 66func (h *hal2vts) GenerateAndroidBuildActions(ctx android.ModuleContext) { 67 // Sort by name to match .hal to .vts file name. 68 sort.Strings(h.properties.Out) 69 srcFiles := ctx.ExpandSources(h.properties.Srcs, nil) 70 sort.SliceStable(srcFiles, func(i, j int) bool { 71 return strings.Compare(srcFiles[j].String(), srcFiles[i].String()) == 1 72 }) 73 74 if len(srcFiles) != len(h.properties.Out) { 75 ctx.ModuleErrorf("Number of inputs must be equal to number of outputs.") 76 } 77 78 genDir := android.PathForModuleGen(ctx, "").String() 79 80 vtsList := vtsList(ctx.AConfig()) 81 82 vtsListMutex.Lock() 83 defer vtsListMutex.Unlock() 84 85 for i, src := range srcFiles { 86 out := android.PathForModuleGen(ctx, h.properties.Out[i]) 87 if src.Ext() != ".hal" { 88 ctx.ModuleErrorf("Source file has to be a .hal file.") 89 } 90 91 relSrc, err := filepath.Rel("hardware/interfaces/", src.String()) 92 if err != nil { 93 ctx.ModuleErrorf("Source file has to be from hardware/interfaces") 94 } 95 halDir := filepath.Dir(relSrc) 96 halFile := strings.TrimSuffix(src.Base(), ".hal") 97 98 ver := filepath.Base(halDir) 99 // Need this to transform directory path to hal name. 100 // For example, audio/effect -> audio.effect 101 pckg := strings.Replace(filepath.Dir(halDir), "/", ".", -1) 102 pckg = "android.hardware." + pckg 103 104 ctx.ModuleBuild(pctx, android.ModuleBuildParams{ 105 Rule: hal2vtsRule, 106 Input: src, 107 Output: out, 108 Args: map[string]string{ 109 "genDir": genDir, 110 "pckg": pckg, 111 "ver": ver, 112 "halFile": halFile, 113 }, 114 }) 115 h.generatedHeaders = append(h.generatedHeaders, out) 116 *vtsList = append(*vtsList, out) 117 } 118 h.exportedHeaderDirs = append(h.exportedHeaderDirs, android.PathForModuleGen(ctx, "")) 119} 120 121func (h *hal2vts) DepsMutator(ctx android.BottomUpMutatorContext) { 122 android.ExtractSourcesDeps(ctx, h.properties.Srcs) 123} 124 125func (h *hal2vts) GeneratedHeaderDirs() android.Paths { 126 return h.exportedHeaderDirs 127} 128 129func (h *hal2vts) GeneratedSourceFiles() android.Paths { 130 return h.generatedHeaders 131} 132 133func hal2vtsFactory() (blueprint.Module, []interface{}) { 134 h := &hal2vts{} 135 return android.InitAndroidModule(h, &h.properties) 136} 137 138func vtsList(config android.Config) *android.Paths { 139 return config.Once("vtsList", func() interface{} { 140 return &android.Paths{} 141 }).(*android.Paths) 142} 143 144var vtsListMutex sync.Mutex 145 146func init() { 147 android.RegisterMakeVarsProvider(pctx, makeVarsProvider) 148} 149 150func makeVarsProvider(ctx android.MakeVarsContext) { 151 vtsList := vtsList(ctx.Config()).Strings() 152 sort.Strings(vtsList) 153 154 ctx.Strict("VTS_SPEC_FILE_LIST", strings.Join(vtsList, " ")) 155} 156