blob: ae831185fc11c1b4d3e756eaf4fca9dd74179065 [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"
Colin Cross95f18bd2022-12-14 15:43:39 -080019 "path/filepath"
Bob Badoureef4c1c2022-05-16 12:20:04 -070020 "strings"
21
Yu Liu71f1ea32025-02-26 23:39:20 +000022 "github.com/google/blueprint"
Bob Badoureef4c1c2022-05-16 12:20:04 -070023 "github.com/google/blueprint/proptools"
24)
25
26func init() {
27 RegisterGenNoticeBuildComponents(InitRegistrationContext)
28}
29
30// Register the gen_notice module type.
31func RegisterGenNoticeBuildComponents(ctx RegistrationContext) {
LaMont Jones0c10e4d2023-05-16 00:58:37 +000032 ctx.RegisterParallelSingletonType("gen_notice_build_rules", GenNoticeBuildRulesFactory)
Bob Badoureef4c1c2022-05-16 12:20:04 -070033 ctx.RegisterModuleType("gen_notice", GenNoticeFactory)
34}
35
36type genNoticeBuildRules struct{}
37
38func (s *genNoticeBuildRules) GenerateBuildActions(ctx SingletonContext) {
Yu Liu71f1ea32025-02-26 23:39:20 +000039 ctx.VisitAllModuleProxies(func(m ModuleProxy) {
40 gm, ok := OtherModuleProvider(ctx, m, GenNoticeInfoProvider)
Bob Badoureef4c1c2022-05-16 12:20:04 -070041 if !ok {
42 return
43 }
Yu Liu71f1ea32025-02-26 23:39:20 +000044 if len(gm.Missing) > 0 {
45 missingReferencesRule(ctx, m, &gm)
Bob Badoureef4c1c2022-05-16 12:20:04 -070046 return
47 }
48 out := BuildNoticeTextOutputFromLicenseMetadata
Yu Liu71f1ea32025-02-26 23:39:20 +000049 if gm.Xml {
Bob Badoureef4c1c2022-05-16 12:20:04 -070050 out = BuildNoticeXmlOutputFromLicenseMetadata
Yu Liu71f1ea32025-02-26 23:39:20 +000051 } else if gm.Html {
Bob Badoureef4c1c2022-05-16 12:20:04 -070052 out = BuildNoticeHtmlOutputFromLicenseMetadata
53 }
54 defaultName := ""
Yu Liu71f1ea32025-02-26 23:39:20 +000055 if len(gm.For) > 0 {
56 defaultName = gm.For[0]
Bob Badoureef4c1c2022-05-16 12:20:04 -070057 }
58
Yu Liu71f1ea32025-02-26 23:39:20 +000059 modules := make([]ModuleProxy, 0)
60 for _, name := range gm.For {
61 mods := ctx.ModuleVariantsFromName(m, name)
Bob Badoureef4c1c2022-05-16 12:20:04 -070062 for _, mod := range mods {
Yu Liuef9e63e2025-03-04 19:01:28 +000063 if !OtherModuleProviderOrDefault(ctx, mod, CommonModuleInfoProvider).Enabled { // don't depend on variants without build rules
Bob Badour3800b5a2022-11-14 14:17:55 -080064 continue
65 }
Bob Badoureef4c1c2022-05-16 12:20:04 -070066 modules = append(modules, mod)
67 }
68 }
69 if ctx.Failed() {
70 return
71 }
Yu Liu71f1ea32025-02-26 23:39:20 +000072 out(ctx, gm.Output, ctx.ModuleName(m),
73 proptools.StringDefault(gm.ArtifactName, defaultName),
Bob Badourc6ec9fb2022-06-08 15:59:35 -070074 []string{
Colin Cross95f18bd2022-12-14 15:43:39 -080075 filepath.Join(ctx.Config().OutDir(), "target", "product", ctx.Config().DeviceName()) + "/",
Bob Badourc6ec9fb2022-06-08 15:59:35 -070076 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
Yu Liu71f1ea32025-02-26 23:39:20 +0000116type GenNoticeInfo struct {
117 // For specifies the modules for which to generate a notice file.
118 For []string
119 // ArtifactName specifies the internal name to use for the notice file.
120 // It appears in the "used by:" list for targets whose entire name is stripped by --strip_prefix.
121 ArtifactName *string
122 // Html indicates an html-format file is needed. The default is text. Can be Html or Xml but not both.
123 Html bool
124 // Xml indicates an xml-format file is needed. The default is text. Can be Html or Xml but not both.
125 Xml bool
126 Output OutputPath
127 Missing []string
128}
129
130var GenNoticeInfoProvider = blueprint.NewProvider[GenNoticeInfo]()
131
Bob Badoureef4c1c2022-05-16 12:20:04 -0700132func (m *genNoticeModule) DepsMutator(ctx BottomUpMutatorContext) {
Bob Badour4660a982022-09-12 16:06:03 -0700133 if ctx.ContainsProperty("licenses") {
134 ctx.PropertyErrorf("licenses", "not supported on \"gen_notice\" modules")
135 }
Bob Badoureef4c1c2022-05-16 12:20:04 -0700136 if proptools.Bool(m.properties.Html) && proptools.Bool(m.properties.Xml) {
137 ctx.ModuleErrorf("can be html or xml but not both")
138 }
139 if !ctx.Config().AllowMissingDependencies() {
140 var missing []string
141 // Verify the modules for which to generate notices exist.
142 for _, otherMod := range m.properties.For {
143 if !ctx.OtherModuleExists(otherMod) {
144 missing = append(missing, otherMod)
145 }
146 }
147 if len(missing) == 1 {
148 ctx.PropertyErrorf("for", "no %q module exists", missing[0])
149 } else if len(missing) > 1 {
150 ctx.PropertyErrorf("for", "modules \"%s\" do not exist", strings.Join(missing, "\", \""))
151 }
152 }
153}
154
155func (m *genNoticeModule) getStem() string {
156 stem := m.base().BaseModuleName()
157 if m.properties.Stem != nil {
158 stem = proptools.String(m.properties.Stem)
159 }
160 return stem
161}
162
163func (m *genNoticeModule) getSuffix() string {
164 suffix := ""
165 if m.properties.Suffix == nil {
166 if proptools.Bool(m.properties.Html) {
167 suffix = ".html"
168 } else if proptools.Bool(m.properties.Xml) {
169 suffix = ".xml"
170 }
171 } else {
172 suffix = proptools.String(m.properties.Suffix)
173 }
174 if proptools.Bool(m.properties.Gzipped) && !strings.HasSuffix(suffix, ".gz") {
175 suffix += ".gz"
176 }
177 return suffix
178}
179
180func (m *genNoticeModule) GenerateAndroidBuildActions(ctx ModuleContext) {
181 if ctx.Config().AllowMissingDependencies() {
182 // Verify the modules for which to generate notices exist.
183 for _, otherMod := range m.properties.For {
184 if !ctx.OtherModuleExists(otherMod) {
185 m.missing = append(m.missing, otherMod)
186 }
187 }
188 m.missing = append(m.missing, ctx.GetMissingDependencies()...)
189 m.missing = FirstUniqueStrings(m.missing)
190 }
191 out := m.getStem() + m.getSuffix()
192 m.output = PathForModuleOut(ctx, out).OutputPath
Yu Liu71f1ea32025-02-26 23:39:20 +0000193
194 SetProvider(ctx, GenNoticeInfoProvider, GenNoticeInfo{
195 For: m.properties.For,
196 ArtifactName: m.properties.ArtifactName,
197 Xml: proptools.Bool(m.properties.Xml),
198 Html: proptools.Bool(m.properties.Html),
199 Output: m.output,
200 Missing: m.missing,
201 })
mrziwang1b25df02024-06-06 15:20:42 -0700202 ctx.SetOutputFiles(Paths{m.output}, "")
Bob Badoureef4c1c2022-05-16 12:20:04 -0700203}
204
205func GenNoticeFactory() Module {
206 module := &genNoticeModule{}
207
208 base := module.base()
209 module.AddProperties(&base.nameProperties, &module.properties)
210
211 // The visibility property needs to be checked and parsed by the visibility module.
212 setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
213
Bob Badoure3838732022-09-08 12:01:57 -0700214 InitAndroidArchModule(module, DeviceSupported, MultilibCommon)
Bob Badoureef4c1c2022-05-16 12:20:04 -0700215 InitDefaultableModule(module)
216
217 return module
218}
219
Bob Badour4660a982022-09-12 16:06:03 -0700220var _ AndroidMkEntriesProvider = (*genNoticeModule)(nil)
221
222// Implements AndroidMkEntriesProvider
223func (m *genNoticeModule) AndroidMkEntries() []AndroidMkEntries {
224 return []AndroidMkEntries{AndroidMkEntries{
225 Class: "ETC",
226 OutputFile: OptionalPathForPath(m.output),
227 }}
228}
229
Bob Badoureef4c1c2022-05-16 12:20:04 -0700230// missingReferencesRule emits an ErrorRule for missing module references.
Yu Liu71f1ea32025-02-26 23:39:20 +0000231func missingReferencesRule(ctx BuilderContext, m ModuleProxy, genInfo *GenNoticeInfo) {
232 if len(genInfo.Missing) < 1 {
Bob Badoureef4c1c2022-05-16 12:20:04 -0700233 panic(fmt.Errorf("missing references rule requested with no missing references"))
234 }
235
236 ctx.Build(pctx, BuildParams{
237 Rule: ErrorRule,
Yu Liu71f1ea32025-02-26 23:39:20 +0000238 Output: genInfo.Output,
239 Description: "notice for " + proptools.StringDefault(genInfo.ArtifactName, "container"),
Bob Badoureef4c1c2022-05-16 12:20:04 -0700240 Args: map[string]string{
Yu Liu71f1ea32025-02-26 23:39:20 +0000241 "error": m.Name() + " references missing module(s): " + strings.Join(genInfo.Missing, ", "),
Bob Badoureef4c1c2022-05-16 12:20:04 -0700242 },
243 })
244}