blob: e2b839f69d235c3661c8b120b8f997246ce6c1d3 [file] [log] [blame]
Bob Badoureef4c1c2022-05-16 12:20:04 -07001// Copyright 2020 Google Inc. All rights reserved.
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 android
16
17import (
18 "fmt"
19 "strings"
20
21 "github.com/google/blueprint/proptools"
22)
23
24func init() {
25 RegisterGenNoticeBuildComponents(InitRegistrationContext)
26}
27
28// Register the gen_notice module type.
29func RegisterGenNoticeBuildComponents(ctx RegistrationContext) {
30 ctx.RegisterSingletonType("gen_notice_build_rules", GenNoticeBuildRulesFactory)
31 ctx.RegisterModuleType("gen_notice", GenNoticeFactory)
32}
33
34type genNoticeBuildRules struct{}
35
36func (s *genNoticeBuildRules) GenerateBuildActions(ctx SingletonContext) {
37 ctx.VisitAllModules(func(m Module) {
38 gm, ok := m.(*genNoticeModule)
39 if !ok {
40 return
41 }
42 if len(gm.missing) > 0 {
43 missingReferencesRule(ctx, gm)
44 return
45 }
46 out := BuildNoticeTextOutputFromLicenseMetadata
47 if proptools.Bool(gm.properties.Xml) {
48 out = BuildNoticeXmlOutputFromLicenseMetadata
49 } else if proptools.Bool(gm.properties.Html) {
50 out = BuildNoticeHtmlOutputFromLicenseMetadata
51 }
52 defaultName := ""
53 if len(gm.properties.For) > 0 {
54 defaultName = gm.properties.For[0]
55 }
56
57 modules := make([]Module, 0)
58 for _, name := range gm.properties.For {
59 mods := ctx.ModuleVariantsFromName(gm, name)
60 for _, mod := range mods {
61 if mod == nil {
62 continue
63 }
64 modules = append(modules, mod)
65 }
66 }
67 if ctx.Failed() {
68 return
69 }
Bob Badourc6ec9fb2022-06-08 15:59:35 -070070 out(ctx, gm.output, ctx.ModuleName(gm),
71 proptools.StringDefault(gm.properties.ArtifactName, defaultName),
72 []string{
73 ctx.Config().OutDir() + "/",
74 ctx.Config().SoongOutDir() + "/",
75 }, modules...)
Bob Badoureef4c1c2022-05-16 12:20:04 -070076 })
77}
78
79func GenNoticeBuildRulesFactory() Singleton {
80 return &genNoticeBuildRules{}
81}
82
83type genNoticeProperties struct {
84 // For specifies the modules for which to generate a notice file.
85 For []string
86 // ArtifactName specifies the internal name to use for the notice file.
87 // It appears in the "used by:" list for targets whose entire name is stripped by --strip_prefix.
88 ArtifactName *string
89 // Stem specifies the base name of the output file.
90 Stem *string `android:"arch_variant"`
91 // Html indicates an html-format file is needed. The default is text. Can be Html or Xml but not both.
92 Html *bool
93 // Xml indicates an xml-format file is needed. The default is text. Can be Html or Xml but not both.
94 Xml *bool
95 // Gzipped indicates the output file must be compressed with gzip. Will append .gz to suffix if not there.
96 Gzipped *bool
97 // Suffix specifies the file extension to use. Defaults to .html for html, .xml for xml, or no extension for text.
98 Suffix *string
99 // Visibility specifies where this license can be used
100 Visibility []string
101}
102
103type genNoticeModule struct {
104 ModuleBase
105 DefaultableModuleBase
106
107 properties genNoticeProperties
108
109 output OutputPath
110 missing []string
111}
112
113func (m *genNoticeModule) DepsMutator(ctx BottomUpMutatorContext) {
114 if proptools.Bool(m.properties.Html) && proptools.Bool(m.properties.Xml) {
115 ctx.ModuleErrorf("can be html or xml but not both")
116 }
117 if !ctx.Config().AllowMissingDependencies() {
118 var missing []string
119 // Verify the modules for which to generate notices exist.
120 for _, otherMod := range m.properties.For {
121 if !ctx.OtherModuleExists(otherMod) {
122 missing = append(missing, otherMod)
123 }
124 }
125 if len(missing) == 1 {
126 ctx.PropertyErrorf("for", "no %q module exists", missing[0])
127 } else if len(missing) > 1 {
128 ctx.PropertyErrorf("for", "modules \"%s\" do not exist", strings.Join(missing, "\", \""))
129 }
130 }
131}
132
133func (m *genNoticeModule) getStem() string {
134 stem := m.base().BaseModuleName()
135 if m.properties.Stem != nil {
136 stem = proptools.String(m.properties.Stem)
137 }
138 return stem
139}
140
141func (m *genNoticeModule) getSuffix() string {
142 suffix := ""
143 if m.properties.Suffix == nil {
144 if proptools.Bool(m.properties.Html) {
145 suffix = ".html"
146 } else if proptools.Bool(m.properties.Xml) {
147 suffix = ".xml"
148 }
149 } else {
150 suffix = proptools.String(m.properties.Suffix)
151 }
152 if proptools.Bool(m.properties.Gzipped) && !strings.HasSuffix(suffix, ".gz") {
153 suffix += ".gz"
154 }
155 return suffix
156}
157
158func (m *genNoticeModule) GenerateAndroidBuildActions(ctx ModuleContext) {
159 if ctx.Config().AllowMissingDependencies() {
160 // Verify the modules for which to generate notices exist.
161 for _, otherMod := range m.properties.For {
162 if !ctx.OtherModuleExists(otherMod) {
163 m.missing = append(m.missing, otherMod)
164 }
165 }
166 m.missing = append(m.missing, ctx.GetMissingDependencies()...)
167 m.missing = FirstUniqueStrings(m.missing)
168 }
169 out := m.getStem() + m.getSuffix()
170 m.output = PathForModuleOut(ctx, out).OutputPath
171}
172
173func GenNoticeFactory() Module {
174 module := &genNoticeModule{}
175
176 base := module.base()
177 module.AddProperties(&base.nameProperties, &module.properties)
178
179 // The visibility property needs to be checked and parsed by the visibility module.
180 setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
181
182 initAndroidModuleBase(module)
183 InitDefaultableModule(module)
184
185 return module
186}
187
188var _ OutputFileProducer = (*genNoticeModule)(nil)
189
190// Implements OutputFileProducer
191func (m *genNoticeModule) OutputFiles(tag string) (Paths, error) {
192 if tag == "" {
193 return Paths{m.output}, nil
194 }
195 return nil, fmt.Errorf("unrecognized tag %q", tag)
196}
197
198// missingReferencesRule emits an ErrorRule for missing module references.
199func missingReferencesRule(ctx BuilderContext, m *genNoticeModule) {
200 if len(m.missing) < 1 {
201 panic(fmt.Errorf("missing references rule requested with no missing references"))
202 }
203
204 ctx.Build(pctx, BuildParams{
205 Rule: ErrorRule,
206 Output: m.output,
207 Description: "notice for " + proptools.StringDefault(m.properties.ArtifactName, "container"),
208 Args: map[string]string{
209 "error": m.Name() + " references missing module(s): " + strings.Join(m.missing, ", "),
210 },
211 })
212}