blob: 9adde9e9b3c331c7c9d3395e595f07b8a5cd6489 [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
22 "github.com/google/blueprint/proptools"
23)
24
25func init() {
26 RegisterGenNoticeBuildComponents(InitRegistrationContext)
27}
28
29// Register the gen_notice module type.
30func RegisterGenNoticeBuildComponents(ctx RegistrationContext) {
LaMont Jones0c10e4d2023-05-16 00:58:37 +000031 ctx.RegisterParallelSingletonType("gen_notice_build_rules", GenNoticeBuildRulesFactory)
Bob Badoureef4c1c2022-05-16 12:20:04 -070032 ctx.RegisterModuleType("gen_notice", GenNoticeFactory)
33}
34
35type genNoticeBuildRules struct{}
36
37func (s *genNoticeBuildRules) GenerateBuildActions(ctx SingletonContext) {
38 ctx.VisitAllModules(func(m Module) {
39 gm, ok := m.(*genNoticeModule)
40 if !ok {
41 return
42 }
43 if len(gm.missing) > 0 {
44 missingReferencesRule(ctx, gm)
45 return
46 }
47 out := BuildNoticeTextOutputFromLicenseMetadata
48 if proptools.Bool(gm.properties.Xml) {
49 out = BuildNoticeXmlOutputFromLicenseMetadata
50 } else if proptools.Bool(gm.properties.Html) {
51 out = BuildNoticeHtmlOutputFromLicenseMetadata
52 }
53 defaultName := ""
54 if len(gm.properties.For) > 0 {
55 defaultName = gm.properties.For[0]
56 }
57
58 modules := make([]Module, 0)
59 for _, name := range gm.properties.For {
60 mods := ctx.ModuleVariantsFromName(gm, name)
61 for _, mod := range mods {
62 if mod == nil {
63 continue
64 }
Cole Fausta963b942024-04-11 17:43:00 -070065 if !mod.Enabled(ctx) { // don't depend on variants without build rules
Bob Badour3800b5a2022-11-14 14:17:55 -080066 continue
67 }
Bob Badoureef4c1c2022-05-16 12:20:04 -070068 modules = append(modules, mod)
69 }
70 }
71 if ctx.Failed() {
72 return
73 }
Bob Badourc6ec9fb2022-06-08 15:59:35 -070074 out(ctx, gm.output, ctx.ModuleName(gm),
75 proptools.StringDefault(gm.properties.ArtifactName, defaultName),
76 []string{
Colin Cross95f18bd2022-12-14 15:43:39 -080077 filepath.Join(ctx.Config().OutDir(), "target", "product", ctx.Config().DeviceName()) + "/",
Bob Badourc6ec9fb2022-06-08 15:59:35 -070078 ctx.Config().OutDir() + "/",
79 ctx.Config().SoongOutDir() + "/",
80 }, modules...)
Bob Badoureef4c1c2022-05-16 12:20:04 -070081 })
82}
83
84func GenNoticeBuildRulesFactory() Singleton {
85 return &genNoticeBuildRules{}
86}
87
88type genNoticeProperties struct {
89 // For specifies the modules for which to generate a notice file.
90 For []string
91 // ArtifactName specifies the internal name to use for the notice file.
92 // It appears in the "used by:" list for targets whose entire name is stripped by --strip_prefix.
93 ArtifactName *string
94 // Stem specifies the base name of the output file.
95 Stem *string `android:"arch_variant"`
96 // Html indicates an html-format file is needed. The default is text. Can be Html or Xml but not both.
97 Html *bool
98 // Xml indicates an xml-format file is needed. The default is text. Can be Html or Xml but not both.
99 Xml *bool
100 // Gzipped indicates the output file must be compressed with gzip. Will append .gz to suffix if not there.
101 Gzipped *bool
102 // Suffix specifies the file extension to use. Defaults to .html for html, .xml for xml, or no extension for text.
103 Suffix *string
104 // Visibility specifies where this license can be used
105 Visibility []string
106}
107
108type genNoticeModule struct {
109 ModuleBase
110 DefaultableModuleBase
111
112 properties genNoticeProperties
113
114 output OutputPath
115 missing []string
116}
117
118func (m *genNoticeModule) DepsMutator(ctx BottomUpMutatorContext) {
Bob Badour4660a982022-09-12 16:06:03 -0700119 if ctx.ContainsProperty("licenses") {
120 ctx.PropertyErrorf("licenses", "not supported on \"gen_notice\" modules")
121 }
Bob Badoureef4c1c2022-05-16 12:20:04 -0700122 if proptools.Bool(m.properties.Html) && proptools.Bool(m.properties.Xml) {
123 ctx.ModuleErrorf("can be html or xml but not both")
124 }
125 if !ctx.Config().AllowMissingDependencies() {
126 var missing []string
127 // Verify the modules for which to generate notices exist.
128 for _, otherMod := range m.properties.For {
129 if !ctx.OtherModuleExists(otherMod) {
130 missing = append(missing, otherMod)
131 }
132 }
133 if len(missing) == 1 {
134 ctx.PropertyErrorf("for", "no %q module exists", missing[0])
135 } else if len(missing) > 1 {
136 ctx.PropertyErrorf("for", "modules \"%s\" do not exist", strings.Join(missing, "\", \""))
137 }
138 }
139}
140
141func (m *genNoticeModule) getStem() string {
142 stem := m.base().BaseModuleName()
143 if m.properties.Stem != nil {
144 stem = proptools.String(m.properties.Stem)
145 }
146 return stem
147}
148
149func (m *genNoticeModule) getSuffix() string {
150 suffix := ""
151 if m.properties.Suffix == nil {
152 if proptools.Bool(m.properties.Html) {
153 suffix = ".html"
154 } else if proptools.Bool(m.properties.Xml) {
155 suffix = ".xml"
156 }
157 } else {
158 suffix = proptools.String(m.properties.Suffix)
159 }
160 if proptools.Bool(m.properties.Gzipped) && !strings.HasSuffix(suffix, ".gz") {
161 suffix += ".gz"
162 }
163 return suffix
164}
165
166func (m *genNoticeModule) GenerateAndroidBuildActions(ctx ModuleContext) {
167 if ctx.Config().AllowMissingDependencies() {
168 // Verify the modules for which to generate notices exist.
169 for _, otherMod := range m.properties.For {
170 if !ctx.OtherModuleExists(otherMod) {
171 m.missing = append(m.missing, otherMod)
172 }
173 }
174 m.missing = append(m.missing, ctx.GetMissingDependencies()...)
175 m.missing = FirstUniqueStrings(m.missing)
176 }
177 out := m.getStem() + m.getSuffix()
178 m.output = PathForModuleOut(ctx, out).OutputPath
mrziwang1b25df02024-06-06 15:20:42 -0700179 ctx.SetOutputFiles(Paths{m.output}, "")
Bob Badoureef4c1c2022-05-16 12:20:04 -0700180}
181
182func GenNoticeFactory() Module {
183 module := &genNoticeModule{}
184
185 base := module.base()
186 module.AddProperties(&base.nameProperties, &module.properties)
187
188 // The visibility property needs to be checked and parsed by the visibility module.
189 setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
190
Bob Badoure3838732022-09-08 12:01:57 -0700191 InitAndroidArchModule(module, DeviceSupported, MultilibCommon)
Bob Badoureef4c1c2022-05-16 12:20:04 -0700192 InitDefaultableModule(module)
193
194 return module
195}
196
Bob Badour4660a982022-09-12 16:06:03 -0700197var _ AndroidMkEntriesProvider = (*genNoticeModule)(nil)
198
199// Implements AndroidMkEntriesProvider
200func (m *genNoticeModule) AndroidMkEntries() []AndroidMkEntries {
201 return []AndroidMkEntries{AndroidMkEntries{
202 Class: "ETC",
203 OutputFile: OptionalPathForPath(m.output),
204 }}
205}
206
Bob Badoureef4c1c2022-05-16 12:20:04 -0700207// missingReferencesRule emits an ErrorRule for missing module references.
208func missingReferencesRule(ctx BuilderContext, m *genNoticeModule) {
209 if len(m.missing) < 1 {
210 panic(fmt.Errorf("missing references rule requested with no missing references"))
211 }
212
213 ctx.Build(pctx, BuildParams{
214 Rule: ErrorRule,
215 Output: m.output,
216 Description: "notice for " + proptools.StringDefault(m.properties.ArtifactName, "container"),
217 Args: map[string]string{
218 "error": m.Name() + " references missing module(s): " + strings.Join(m.missing, ", "),
219 },
220 })
221}