blob: 2772ba36e7694e8f3e5b078a40f5bd7e845e1a40 [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{
38 Command: `${assembleVintfCmd} -i ${inputs} -o ${out}`,
39 CommandDeps: []string{"${assembleVintfCmd}"},
40 Description: "assemble_vintf -i ${inputs}",
41 }, "inputs")
42
Yifan Hongfca5d952020-04-10 16:42:50 -070043 xmllintXsd = pctx.AndroidStaticRule("xmllint-xsd", blueprint.RuleParams{
44 Command: `$XmlLintCmd --schema $xsd $in > /dev/null && touch -a $out`,
45 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
67}
68
69type vintfCompatibilityMatrixRule struct {
70 android.ModuleBase
71 properties vintfCompatibilityMatrixProperties
72
Yifan Hongfca5d952020-04-10 16:42:50 -070073 genFile android.WritablePath
74 additionalDependencies android.WritablePaths
Yifan Hong0cd10dd2018-10-12 13:08:52 -070075}
76
77func init() {
78 pctx.HostBinToolVariable("assembleVintfCmd", "assemble_vintf")
Yifan Hongfca5d952020-04-10 16:42:50 -070079 pctx.HostBinToolVariable("XmlLintCmd", "xmllint")
Yifan Hong0cd10dd2018-10-12 13:08:52 -070080 android.RegisterModuleType("vintf_compatibility_matrix", vintfCompatibilityMatrixFactory)
81}
82
83func vintfCompatibilityMatrixFactory() android.Module {
84 g := &vintfCompatibilityMatrixRule{}
85 g.AddProperties(&g.properties)
86 android.InitAndroidArchModule(g, android.DeviceSupported, android.MultilibCommon)
87 return g
88}
89
90var _ android.AndroidMkDataProvider = (*vintfCompatibilityMatrixRule)(nil)
91
92func (g *vintfCompatibilityMatrixRule) DepsMutator(ctx android.BottomUpMutatorContext) {
93 android.ExtractSourcesDeps(ctx, g.properties.Srcs)
94 ctx.AddDependency(ctx.Module(), kernelConfigTag, g.properties.Kernel_configs...)
Yifan Hongfca5d952020-04-10 16:42:50 -070095 ctx.AddDependency(ctx.Module(), schemaTag, schemaModuleName)
96}
97
98func (g *vintfCompatibilityMatrixRule) timestampFilePath(ctx android.ModuleContext, path android.Path) android.WritablePath {
99 return android.GenPathWithExt(ctx, "vintf-xmllint", path, "ts")
100}
101
102func (g *vintfCompatibilityMatrixRule) generateValidateBuildAction(ctx android.ModuleContext, path android.Path, schema android.Path) {
103 timestamp := g.timestampFilePath(ctx, path)
104 ctx.Build(pctx, android.BuildParams{
105 Rule: xmllintXsd,
106 Description: "xmllint-xsd",
107 Input: path,
108 Output: timestamp,
109 Implicit: schema,
110 Args: map[string]string{
111 "xsd": schema.String(),
112 },
113 })
114 g.additionalDependencies = append(g.additionalDependencies, timestamp)
115}
116
117func (g *vintfCompatibilityMatrixRule) getSchema(ctx android.ModuleContext) android.OptionalPath {
118 schemaModule := ctx.GetDirectDepWithTag(schemaModuleName, schemaTag)
119 sfp, ok := schemaModule.(android.SourceFileProducer)
120 if !ok {
121 ctx.ModuleErrorf("Implicit dependency %q has no srcs", ctx.OtherModuleName(schemaModule))
122 return android.OptionalPath{}
123 }
124
125 schemaSrcs := sfp.Srcs()
126 if len(schemaSrcs) != 1 {
127 ctx.PropertyErrorf(`srcs of implicit dependency %q has length %d != 1`, ctx.OtherModuleName(schemaModule), len(schemaSrcs))
128 return android.OptionalPath{}
129 }
130 return android.OptionalPathForPath(schemaSrcs[0])
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700131}
132
133func (g *vintfCompatibilityMatrixRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
134
135 outputFilename := proptools.String(g.properties.Stem)
136 if outputFilename == "" {
137 outputFilename = g.Name()
138 }
139
Yifan Hongfca5d952020-04-10 16:42:50 -0700140 schema := g.getSchema(ctx)
141 if !schema.Valid() {
142 return
143 }
144
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700145 inputPaths := android.PathsForModuleSrc(ctx, g.properties.Srcs)
Yifan Hongfca5d952020-04-10 16:42:50 -0700146 for _, srcPath := range inputPaths {
147 g.generateValidateBuildAction(ctx, srcPath, schema.Path())
148 }
149
150 // No need to validate matrices from kernel configs because they are generated by
151 // assemble_vintf.
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700152 ctx.VisitDirectDepsWithTag(kernelConfigTag, func(m android.Module) {
153 if k, ok := m.(*configs.KernelConfigRule); ok {
154 inputPaths = append(inputPaths, k.OutputPath())
155 } else {
156 ctx.PropertyErrorf("kernel_config",
157 "module %q is not a kernel_config", ctx.OtherModuleName(m))
158 }
159 })
160
161 g.genFile = android.PathForModuleGen(ctx, outputFilename)
162
163 ctx.Build(pctx, android.BuildParams{
164 Rule: assembleVintfRule,
165 Description: "Framework Compatibility Matrix",
166 Implicits: inputPaths,
167 Output: g.genFile,
168 Args: map[string]string{
169 "inputs": strings.Join(inputPaths.Strings(), ":"),
170 },
171 })
Yifan Hongfca5d952020-04-10 16:42:50 -0700172 g.generateValidateBuildAction(ctx, g.genFile, schema.Path())
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700173
174 ctx.InstallFile(android.PathForModuleInstall(ctx, "etc", relpath), outputFilename, g.genFile)
175}
176
177func (g *vintfCompatibilityMatrixRule) AndroidMk() android.AndroidMkData {
178 return android.AndroidMkData{
179 Class: "ETC",
180 OutputFile: android.OptionalPathForPath(g.genFile),
181 Extra: []android.AndroidMkExtraFunc{
182 func(w io.Writer, outputFile android.Path) {
183 fmt.Fprintln(w, "LOCAL_MODULE_RELATIVE_PATH :=", relpath)
184 if proptools.String(g.properties.Stem) != "" {
185 fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", proptools.String(g.properties.Stem))
186 }
Yifan Hongfca5d952020-04-10 16:42:50 -0700187 for _, path := range g.additionalDependencies {
188 fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES +=", path.String())
189 }
Yifan Hong0cd10dd2018-10-12 13:08:52 -0700190 },
191 },
192 }
193}