blob: 008aac5e2664a0a5f3104d5bb64acda1021398ab [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) {
Bob Badour4660a982022-09-12 16:06:03 -0700114 if ctx.ContainsProperty("licenses") {
115 ctx.PropertyErrorf("licenses", "not supported on \"gen_notice\" modules")
116 }
Bob Badoureef4c1c2022-05-16 12:20:04 -0700117 if proptools.Bool(m.properties.Html) && proptools.Bool(m.properties.Xml) {
118 ctx.ModuleErrorf("can be html or xml but not both")
119 }
120 if !ctx.Config().AllowMissingDependencies() {
121 var missing []string
122 // Verify the modules for which to generate notices exist.
123 for _, otherMod := range m.properties.For {
124 if !ctx.OtherModuleExists(otherMod) {
125 missing = append(missing, otherMod)
126 }
127 }
128 if len(missing) == 1 {
129 ctx.PropertyErrorf("for", "no %q module exists", missing[0])
130 } else if len(missing) > 1 {
131 ctx.PropertyErrorf("for", "modules \"%s\" do not exist", strings.Join(missing, "\", \""))
132 }
133 }
134}
135
136func (m *genNoticeModule) getStem() string {
137 stem := m.base().BaseModuleName()
138 if m.properties.Stem != nil {
139 stem = proptools.String(m.properties.Stem)
140 }
141 return stem
142}
143
144func (m *genNoticeModule) getSuffix() string {
145 suffix := ""
146 if m.properties.Suffix == nil {
147 if proptools.Bool(m.properties.Html) {
148 suffix = ".html"
149 } else if proptools.Bool(m.properties.Xml) {
150 suffix = ".xml"
151 }
152 } else {
153 suffix = proptools.String(m.properties.Suffix)
154 }
155 if proptools.Bool(m.properties.Gzipped) && !strings.HasSuffix(suffix, ".gz") {
156 suffix += ".gz"
157 }
158 return suffix
159}
160
161func (m *genNoticeModule) GenerateAndroidBuildActions(ctx ModuleContext) {
162 if ctx.Config().AllowMissingDependencies() {
163 // Verify the modules for which to generate notices exist.
164 for _, otherMod := range m.properties.For {
165 if !ctx.OtherModuleExists(otherMod) {
166 m.missing = append(m.missing, otherMod)
167 }
168 }
169 m.missing = append(m.missing, ctx.GetMissingDependencies()...)
170 m.missing = FirstUniqueStrings(m.missing)
171 }
172 out := m.getStem() + m.getSuffix()
173 m.output = PathForModuleOut(ctx, out).OutputPath
174}
175
176func GenNoticeFactory() Module {
177 module := &genNoticeModule{}
178
179 base := module.base()
180 module.AddProperties(&base.nameProperties, &module.properties)
181
182 // The visibility property needs to be checked and parsed by the visibility module.
183 setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
184
Bob Badoure3838732022-09-08 12:01:57 -0700185 InitAndroidArchModule(module, DeviceSupported, MultilibCommon)
Bob Badoureef4c1c2022-05-16 12:20:04 -0700186 InitDefaultableModule(module)
187
188 return module
189}
190
191var _ OutputFileProducer = (*genNoticeModule)(nil)
192
193// Implements OutputFileProducer
194func (m *genNoticeModule) OutputFiles(tag string) (Paths, error) {
195 if tag == "" {
196 return Paths{m.output}, nil
197 }
198 return nil, fmt.Errorf("unrecognized tag %q", tag)
199}
200
Bob Badour4660a982022-09-12 16:06:03 -0700201var _ AndroidMkEntriesProvider = (*genNoticeModule)(nil)
202
203// Implements AndroidMkEntriesProvider
204func (m *genNoticeModule) AndroidMkEntries() []AndroidMkEntries {
205 return []AndroidMkEntries{AndroidMkEntries{
206 Class: "ETC",
207 OutputFile: OptionalPathForPath(m.output),
208 }}
209}
210
Bob Badoureef4c1c2022-05-16 12:20:04 -0700211// missingReferencesRule emits an ErrorRule for missing module references.
212func missingReferencesRule(ctx BuilderContext, m *genNoticeModule) {
213 if len(m.missing) < 1 {
214 panic(fmt.Errorf("missing references rule requested with no missing references"))
215 }
216
217 ctx.Build(pctx, BuildParams{
218 Rule: ErrorRule,
219 Output: m.output,
220 Description: "notice for " + proptools.StringDefault(m.properties.ArtifactName, "container"),
221 Args: map[string]string{
222 "error": m.Name() + " references missing module(s): " + strings.Join(m.missing, ", "),
223 },
224 })
225}