blob: 28fddbcee516fbdfe4d269e9a452b82d1eabf11c [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 }
Bob Badour3800b5a2022-11-14 14:17:55 -080064 if !mod.Enabled() { // don't depend on variants without build rules
65 continue
66 }
Bob Badoureef4c1c2022-05-16 12:20:04 -070067 modules = append(modules, mod)
68 }
69 }
70 if ctx.Failed() {
71 return
72 }
Bob Badourc6ec9fb2022-06-08 15:59:35 -070073 out(ctx, gm.output, ctx.ModuleName(gm),
74 proptools.StringDefault(gm.properties.ArtifactName, defaultName),
75 []string{
76 ctx.Config().OutDir() + "/",
77 ctx.Config().SoongOutDir() + "/",
78 }, modules...)
Bob Badoureef4c1c2022-05-16 12:20:04 -070079 })
80}
81
82func GenNoticeBuildRulesFactory() Singleton {
83 return &genNoticeBuildRules{}
84}
85
86type genNoticeProperties struct {
87 // For specifies the modules for which to generate a notice file.
88 For []string
89 // ArtifactName specifies the internal name to use for the notice file.
90 // It appears in the "used by:" list for targets whose entire name is stripped by --strip_prefix.
91 ArtifactName *string
92 // Stem specifies the base name of the output file.
93 Stem *string `android:"arch_variant"`
94 // Html indicates an html-format file is needed. The default is text. Can be Html or Xml but not both.
95 Html *bool
96 // Xml indicates an xml-format file is needed. The default is text. Can be Html or Xml but not both.
97 Xml *bool
98 // Gzipped indicates the output file must be compressed with gzip. Will append .gz to suffix if not there.
99 Gzipped *bool
100 // Suffix specifies the file extension to use. Defaults to .html for html, .xml for xml, or no extension for text.
101 Suffix *string
102 // Visibility specifies where this license can be used
103 Visibility []string
104}
105
106type genNoticeModule struct {
107 ModuleBase
108 DefaultableModuleBase
109
110 properties genNoticeProperties
111
112 output OutputPath
113 missing []string
114}
115
116func (m *genNoticeModule) DepsMutator(ctx BottomUpMutatorContext) {
Bob Badour4660a982022-09-12 16:06:03 -0700117 if ctx.ContainsProperty("licenses") {
118 ctx.PropertyErrorf("licenses", "not supported on \"gen_notice\" modules")
119 }
Bob Badoureef4c1c2022-05-16 12:20:04 -0700120 if proptools.Bool(m.properties.Html) && proptools.Bool(m.properties.Xml) {
121 ctx.ModuleErrorf("can be html or xml but not both")
122 }
123 if !ctx.Config().AllowMissingDependencies() {
124 var missing []string
125 // Verify the modules for which to generate notices exist.
126 for _, otherMod := range m.properties.For {
127 if !ctx.OtherModuleExists(otherMod) {
128 missing = append(missing, otherMod)
129 }
130 }
131 if len(missing) == 1 {
132 ctx.PropertyErrorf("for", "no %q module exists", missing[0])
133 } else if len(missing) > 1 {
134 ctx.PropertyErrorf("for", "modules \"%s\" do not exist", strings.Join(missing, "\", \""))
135 }
136 }
137}
138
139func (m *genNoticeModule) getStem() string {
140 stem := m.base().BaseModuleName()
141 if m.properties.Stem != nil {
142 stem = proptools.String(m.properties.Stem)
143 }
144 return stem
145}
146
147func (m *genNoticeModule) getSuffix() string {
148 suffix := ""
149 if m.properties.Suffix == nil {
150 if proptools.Bool(m.properties.Html) {
151 suffix = ".html"
152 } else if proptools.Bool(m.properties.Xml) {
153 suffix = ".xml"
154 }
155 } else {
156 suffix = proptools.String(m.properties.Suffix)
157 }
158 if proptools.Bool(m.properties.Gzipped) && !strings.HasSuffix(suffix, ".gz") {
159 suffix += ".gz"
160 }
161 return suffix
162}
163
164func (m *genNoticeModule) GenerateAndroidBuildActions(ctx ModuleContext) {
165 if ctx.Config().AllowMissingDependencies() {
166 // Verify the modules for which to generate notices exist.
167 for _, otherMod := range m.properties.For {
168 if !ctx.OtherModuleExists(otherMod) {
169 m.missing = append(m.missing, otherMod)
170 }
171 }
172 m.missing = append(m.missing, ctx.GetMissingDependencies()...)
173 m.missing = FirstUniqueStrings(m.missing)
174 }
175 out := m.getStem() + m.getSuffix()
176 m.output = PathForModuleOut(ctx, out).OutputPath
177}
178
179func GenNoticeFactory() Module {
180 module := &genNoticeModule{}
181
182 base := module.base()
183 module.AddProperties(&base.nameProperties, &module.properties)
184
185 // The visibility property needs to be checked and parsed by the visibility module.
186 setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
187
Bob Badoure3838732022-09-08 12:01:57 -0700188 InitAndroidArchModule(module, DeviceSupported, MultilibCommon)
Bob Badoureef4c1c2022-05-16 12:20:04 -0700189 InitDefaultableModule(module)
190
191 return module
192}
193
194var _ OutputFileProducer = (*genNoticeModule)(nil)
195
196// Implements OutputFileProducer
197func (m *genNoticeModule) OutputFiles(tag string) (Paths, error) {
198 if tag == "" {
199 return Paths{m.output}, nil
200 }
201 return nil, fmt.Errorf("unrecognized tag %q", tag)
202}
203
Bob Badour4660a982022-09-12 16:06:03 -0700204var _ AndroidMkEntriesProvider = (*genNoticeModule)(nil)
205
206// Implements AndroidMkEntriesProvider
207func (m *genNoticeModule) AndroidMkEntries() []AndroidMkEntries {
208 return []AndroidMkEntries{AndroidMkEntries{
209 Class: "ETC",
210 OutputFile: OptionalPathForPath(m.output),
211 }}
212}
213
Bob Badoureef4c1c2022-05-16 12:20:04 -0700214// missingReferencesRule emits an ErrorRule for missing module references.
215func missingReferencesRule(ctx BuilderContext, m *genNoticeModule) {
216 if len(m.missing) < 1 {
217 panic(fmt.Errorf("missing references rule requested with no missing references"))
218 }
219
220 ctx.Build(pctx, BuildParams{
221 Rule: ErrorRule,
222 Output: m.output,
223 Description: "notice for " + proptools.StringDefault(m.properties.ArtifactName, "container"),
224 Args: map[string]string{
225 "error": m.Name() + " references missing module(s): " + strings.Join(m.missing, ", "),
226 },
227 })
228}