blob: 4f342b252e97037225458301df66ba1bf6bc77d7 [file] [log] [blame]
Yifan Hong0cd10dd2018-10-12 13:08:52 -07001// Copyright (C) 2018 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 vintf
16
17import (
18 "fmt"
19 "io"
20 "strings"
21
22 "github.com/google/blueprint"
23 "github.com/google/blueprint/proptools"
24
25 "android/soong/android"
26 "android/soong/kernel/configs"
27)
28
29type dependencyTag struct {
30 blueprint.BaseDependencyTag
31 name string
32}
33
34var (
35 pctx = android.NewPackageContext("android/vintf")
36
37 assembleVintfRule = pctx.AndroidStaticRule("assemble_vintf", blueprint.RuleParams{
Yifan Hong9fb9ff72023-07-10 17:42:05 -070038 Command: `${assembleVintfCmd} -i ${inputs} -o ${out} ${extraParams}`,
Yifan Hong0cd10dd2018-10-12 13:08:52 -070039 CommandDeps: []string{"${assembleVintfCmd}"},
40 Description: "assemble_vintf -i ${inputs}",
Yifan Hong9fb9ff72023-07-10 17:42:05 -070041 }, "inputs", "extraParams")
Yifan Hong0cd10dd2018-10-12 13:08:52 -070042
Yifan Hongfca5d952020-04-10 16:42:50 -070043 xmllintXsd = pctx.AndroidStaticRule("xmllint-xsd", blueprint.RuleParams{
Yifan Hong5a6c7b12021-02-24 17:58:17 -080044 Command: `$XmlLintCmd --quiet --schema $xsd $in > /dev/null && touch -a $out`,
Yifan Hongfca5d952020-04-10 16:42:50 -070045 CommandDeps: []string{"$XmlLintCmd"},
46 Restat: true,
47 }, "xsd")
48
49 kernelConfigTag = dependencyTag{name: "kernel-config"}
50 schemaTag = dependencyTag{name: "matrix-schema"}
51 schemaModuleName = "compatibility_matrix_schema"
Yifan Hong0cd10dd2018-10-12 13:08:52 -070052)
53
54const (
55 relpath = "vintf"
56)
57
58type vintfCompatibilityMatrixProperties struct {
59 // set the name of the output
60 Stem *string
61
62 // list of source compatibility matrix XML files
63 Srcs []string
64
65 // list of kernel_config modules to be combined to final output
66 Kernel_configs []string
Yifan Hong9fb9ff72023-07-10 17:42:05 -070067
68 // Default is "default" for compatibility matrices on /vendor
69 // and /odm, and "disallow" for compatibility matrices on /system,
70 // /product, and /system_ext.
71 // If value is "only", only android.* HALs are allowed. If value
72 // is "disallow", none of android.* HALs are allowed.
73 Core_hals *string
Yifan Hong0cd10dd2018-10-12 13:08:52 -070074}
75
76type vintfCompatibilityMatrixRule struct {
77 android.ModuleBase
78 properties vintfCompatibilityMatrixProperties
79
Yifan Hongfca5d952020-04-10 16:42:50 -070080 genFile android.WritablePath
81 additionalDependencies android.WritablePaths
Yifan Hong0cd10dd2018-10-12 13:08:52 -070082}
83
84func init() {
85 pctx.HostBinToolVariable("assembleVintfCmd", "assemble_vintf")
Yifan Hongfca5d952020-04-10 16:42:50 -070086 pctx.HostBinToolVariable("XmlLintCmd", "xmllint")
Yifan Hong0cd10dd2018-10-12 13:08:52 -070087 android.RegisterModuleType("vintf_compatibility_matrix", vintfCompatibilityMatrixFactory)
88}
89
90func vintfCompatibilityMatrixFactory() android.Module {
91 g := &vintfCompatibilityMatrixRule{}
92 g.AddProperties(&g.properties)
93 android.InitAndroidArchModule(g, android.DeviceSupported, android.MultilibCommon)
94 return g
95}
96
97var _ android.AndroidMkDataProvider = (*vintfCompatibilityMatrixRule)(nil)
98
99func (g *vintfCompatibilityMatrixRule) DepsMutator(ctx android.BottomUpMutatorContext) {
100 android.ExtractSourcesDeps(ctx, g.properties.Srcs)
101 ctx.AddDependency(ctx.Module(), kernelConfigTag, g.properties.Kernel_configs...)
Yifan Hongfca5d952020-04-10 16:42:50 -0700102 ctx.AddDependency(ctx.Module(), schemaTag, schemaModuleName)
103}
104
105func (g *vintfCompatibilityMatrixRule) timestampFilePath(ctx android.ModuleContext, path android.Path) android.WritablePath {
106 return android.GenPathWithExt(ctx, "vintf-xmllint", path, "ts")
107}
108
109func (g *vintfCompatibilityMatrixRule) generateValidateBuildAction(ctx android.ModuleContext, path android.Path, schema android.Path) {
110 timestamp := g.timestampFilePath(ctx, path)
111 ctx.Build(pctx, android.BuildParams{
112 Rule: xmllintXsd,
113 Description: "xmllint-xsd",
114 Input: path,
115 Output: timestamp,
116 Implicit: schema,
117 Args: map[string]string{
118 "xsd": schema.String(),
119 },
120 })
121 g.additionalDependencies = append(g.additionalDependencies, timestamp)
122}
123
124func (g *vintfCompatibilityMatrixRule) getSchema(ctx android.ModuleContext) android.OptionalPath {
125 schemaModule := ctx.GetDirectDepWithTag(schemaModuleName, schemaTag)
126 sfp, ok := schemaModule.(android.SourceFileProducer)
127 if !ok {
128 ctx.ModuleErrorf("Implicit dependency %q has no srcs", ctx.OtherModuleName(schemaModule))
129 return android.OptionalPath{}
130 }
131
132 schemaSrcs := sfp.Srcs()
133 if len(schemaSrcs) != 1 {
134 ctx.PropertyErrorf(`srcs of implicit dependency %q has length %d != 1`, ctx.OtherModuleName(schemaModule), len(schemaSrcs))
135 return android.OptionalPath{}
136 }
137 return android.OptionalPathForPath(schemaSrcs[0])
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700138}
139
140func (g *vintfCompatibilityMatrixRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
141
142 outputFilename := proptools.String(g.properties.Stem)
143 if outputFilename == "" {
144 outputFilename = g.Name()
145 }
146
Yifan Hongfca5d952020-04-10 16:42:50 -0700147 schema := g.getSchema(ctx)
148 if !schema.Valid() {
149 return
150 }
151
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700152 inputPaths := android.PathsForModuleSrc(ctx, g.properties.Srcs)
Yifan Hongfca5d952020-04-10 16:42:50 -0700153 for _, srcPath := range inputPaths {
154 g.generateValidateBuildAction(ctx, srcPath, schema.Path())
155 }
156
157 // No need to validate matrices from kernel configs because they are generated by
158 // assemble_vintf.
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700159 ctx.VisitDirectDepsWithTag(kernelConfigTag, func(m android.Module) {
160 if k, ok := m.(*configs.KernelConfigRule); ok {
161 inputPaths = append(inputPaths, k.OutputPath())
162 } else {
Steven Moreland3f40b2b2021-05-21 20:25:47 +0000163 ctx.PropertyErrorf("kernel_configs",
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700164 "module %q is not a kernel_config", ctx.OtherModuleName(m))
165 }
166 })
167
168 g.genFile = android.PathForModuleGen(ctx, outputFilename)
169
170 ctx.Build(pctx, android.BuildParams{
171 Rule: assembleVintfRule,
172 Description: "Framework Compatibility Matrix",
173 Implicits: inputPaths,
174 Output: g.genFile,
175 Args: map[string]string{
Yifan Hong9fb9ff72023-07-10 17:42:05 -0700176 "inputs": strings.Join(inputPaths.Strings(), ":"),
177 "extraParams": strings.Join(g.getExtraParams(), " "),
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700178 },
179 })
Yifan Hongfca5d952020-04-10 16:42:50 -0700180 g.generateValidateBuildAction(ctx, g.genFile, schema.Path())
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700181
182 ctx.InstallFile(android.PathForModuleInstall(ctx, "etc", relpath), outputFilename, g.genFile)
183}
184
185func (g *vintfCompatibilityMatrixRule) AndroidMk() android.AndroidMkData {
186 return android.AndroidMkData{
187 Class: "ETC",
188 OutputFile: android.OptionalPathForPath(g.genFile),
189 Extra: []android.AndroidMkExtraFunc{
190 func(w io.Writer, outputFile android.Path) {
191 fmt.Fprintln(w, "LOCAL_MODULE_RELATIVE_PATH :=", relpath)
192 if proptools.String(g.properties.Stem) != "" {
193 fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", proptools.String(g.properties.Stem))
194 }
Yifan Hongfca5d952020-04-10 16:42:50 -0700195 for _, path := range g.additionalDependencies {
196 fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES +=", path.String())
197 }
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700198 },
199 },
200 }
201}
Yifan Hong9fb9ff72023-07-10 17:42:05 -0700202
203// Return extra parameters to assemble_vintf.
204func (g *vintfCompatibilityMatrixRule) getExtraParams() []string {
205 var extraParams []string
206
207 coreHalsStrategy := proptools.StringDefault(
208 g.properties.Core_hals,
209 g.defaultCoreHalsStrategy(),
210 )
211 extraParams = append(extraParams, "--core-hals", proptools.ShellEscape(coreHalsStrategy))
212 return extraParams
213}
214
215func (g *vintfCompatibilityMatrixRule) defaultCoreHalsStrategy() string {
216 // TODO(b/290408770): default to "disallow" for FCMs
217
218 // For Device (vendor, odm) compatibility matrix, default is
219 // to not check anything.
220 return "default"
221}