xref: /aosp_15_r20/build/soong/android/gen_notice.go (revision 333d2b3687b3a337dbcca9d65000bca186795e39)
1*333d2b36SAndroid Build Coastguard Worker// Copyright 2020 Google Inc. All rights reserved.
2*333d2b36SAndroid Build Coastguard Worker//
3*333d2b36SAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License");
4*333d2b36SAndroid Build Coastguard Worker// you may not use this file except in compliance with the License.
5*333d2b36SAndroid Build Coastguard Worker// You may obtain a copy of the License at
6*333d2b36SAndroid Build Coastguard Worker//
7*333d2b36SAndroid Build Coastguard Worker//     http://www.apache.org/licenses/LICENSE-2.0
8*333d2b36SAndroid Build Coastguard Worker//
9*333d2b36SAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software
10*333d2b36SAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS,
11*333d2b36SAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*333d2b36SAndroid Build Coastguard Worker// See the License for the specific language governing permissions and
13*333d2b36SAndroid Build Coastguard Worker// limitations under the License.
14*333d2b36SAndroid Build Coastguard Worker
15*333d2b36SAndroid Build Coastguard Workerpackage android
16*333d2b36SAndroid Build Coastguard Worker
17*333d2b36SAndroid Build Coastguard Workerimport (
18*333d2b36SAndroid Build Coastguard Worker	"fmt"
19*333d2b36SAndroid Build Coastguard Worker	"path/filepath"
20*333d2b36SAndroid Build Coastguard Worker	"strings"
21*333d2b36SAndroid Build Coastguard Worker
22*333d2b36SAndroid Build Coastguard Worker	"github.com/google/blueprint/proptools"
23*333d2b36SAndroid Build Coastguard Worker)
24*333d2b36SAndroid Build Coastguard Worker
25*333d2b36SAndroid Build Coastguard Workerfunc init() {
26*333d2b36SAndroid Build Coastguard Worker	RegisterGenNoticeBuildComponents(InitRegistrationContext)
27*333d2b36SAndroid Build Coastguard Worker}
28*333d2b36SAndroid Build Coastguard Worker
29*333d2b36SAndroid Build Coastguard Worker// Register the gen_notice module type.
30*333d2b36SAndroid Build Coastguard Workerfunc RegisterGenNoticeBuildComponents(ctx RegistrationContext) {
31*333d2b36SAndroid Build Coastguard Worker	ctx.RegisterParallelSingletonType("gen_notice_build_rules", GenNoticeBuildRulesFactory)
32*333d2b36SAndroid Build Coastguard Worker	ctx.RegisterModuleType("gen_notice", GenNoticeFactory)
33*333d2b36SAndroid Build Coastguard Worker}
34*333d2b36SAndroid Build Coastguard Worker
35*333d2b36SAndroid Build Coastguard Workertype genNoticeBuildRules struct{}
36*333d2b36SAndroid Build Coastguard Worker
37*333d2b36SAndroid Build Coastguard Workerfunc (s *genNoticeBuildRules) GenerateBuildActions(ctx SingletonContext) {
38*333d2b36SAndroid Build Coastguard Worker	ctx.VisitAllModules(func(m Module) {
39*333d2b36SAndroid Build Coastguard Worker		gm, ok := m.(*genNoticeModule)
40*333d2b36SAndroid Build Coastguard Worker		if !ok {
41*333d2b36SAndroid Build Coastguard Worker			return
42*333d2b36SAndroid Build Coastguard Worker		}
43*333d2b36SAndroid Build Coastguard Worker		if len(gm.missing) > 0 {
44*333d2b36SAndroid Build Coastguard Worker			missingReferencesRule(ctx, gm)
45*333d2b36SAndroid Build Coastguard Worker			return
46*333d2b36SAndroid Build Coastguard Worker		}
47*333d2b36SAndroid Build Coastguard Worker		out := BuildNoticeTextOutputFromLicenseMetadata
48*333d2b36SAndroid Build Coastguard Worker		if proptools.Bool(gm.properties.Xml) {
49*333d2b36SAndroid Build Coastguard Worker			out = BuildNoticeXmlOutputFromLicenseMetadata
50*333d2b36SAndroid Build Coastguard Worker		} else if proptools.Bool(gm.properties.Html) {
51*333d2b36SAndroid Build Coastguard Worker			out = BuildNoticeHtmlOutputFromLicenseMetadata
52*333d2b36SAndroid Build Coastguard Worker		}
53*333d2b36SAndroid Build Coastguard Worker		defaultName := ""
54*333d2b36SAndroid Build Coastguard Worker		if len(gm.properties.For) > 0 {
55*333d2b36SAndroid Build Coastguard Worker			defaultName = gm.properties.For[0]
56*333d2b36SAndroid Build Coastguard Worker		}
57*333d2b36SAndroid Build Coastguard Worker
58*333d2b36SAndroid Build Coastguard Worker		modules := make([]Module, 0)
59*333d2b36SAndroid Build Coastguard Worker		for _, name := range gm.properties.For {
60*333d2b36SAndroid Build Coastguard Worker			mods := ctx.ModuleVariantsFromName(gm, name)
61*333d2b36SAndroid Build Coastguard Worker			for _, mod := range mods {
62*333d2b36SAndroid Build Coastguard Worker				if mod == nil {
63*333d2b36SAndroid Build Coastguard Worker					continue
64*333d2b36SAndroid Build Coastguard Worker				}
65*333d2b36SAndroid Build Coastguard Worker				if !mod.Enabled(ctx) { // don't depend on variants without build rules
66*333d2b36SAndroid Build Coastguard Worker					continue
67*333d2b36SAndroid Build Coastguard Worker				}
68*333d2b36SAndroid Build Coastguard Worker				modules = append(modules, mod)
69*333d2b36SAndroid Build Coastguard Worker			}
70*333d2b36SAndroid Build Coastguard Worker		}
71*333d2b36SAndroid Build Coastguard Worker		if ctx.Failed() {
72*333d2b36SAndroid Build Coastguard Worker			return
73*333d2b36SAndroid Build Coastguard Worker		}
74*333d2b36SAndroid Build Coastguard Worker		out(ctx, gm.output, ctx.ModuleName(gm),
75*333d2b36SAndroid Build Coastguard Worker			proptools.StringDefault(gm.properties.ArtifactName, defaultName),
76*333d2b36SAndroid Build Coastguard Worker			[]string{
77*333d2b36SAndroid Build Coastguard Worker				filepath.Join(ctx.Config().OutDir(), "target", "product", ctx.Config().DeviceName()) + "/",
78*333d2b36SAndroid Build Coastguard Worker				ctx.Config().OutDir() + "/",
79*333d2b36SAndroid Build Coastguard Worker				ctx.Config().SoongOutDir() + "/",
80*333d2b36SAndroid Build Coastguard Worker			}, modules...)
81*333d2b36SAndroid Build Coastguard Worker	})
82*333d2b36SAndroid Build Coastguard Worker}
83*333d2b36SAndroid Build Coastguard Worker
84*333d2b36SAndroid Build Coastguard Workerfunc GenNoticeBuildRulesFactory() Singleton {
85*333d2b36SAndroid Build Coastguard Worker	return &genNoticeBuildRules{}
86*333d2b36SAndroid Build Coastguard Worker}
87*333d2b36SAndroid Build Coastguard Worker
88*333d2b36SAndroid Build Coastguard Workertype genNoticeProperties struct {
89*333d2b36SAndroid Build Coastguard Worker	// For specifies the modules for which to generate a notice file.
90*333d2b36SAndroid Build Coastguard Worker	For []string
91*333d2b36SAndroid Build Coastguard Worker	// ArtifactName specifies the internal name to use for the notice file.
92*333d2b36SAndroid Build Coastguard Worker	// It appears in the "used by:" list for targets whose entire name is stripped by --strip_prefix.
93*333d2b36SAndroid Build Coastguard Worker	ArtifactName *string
94*333d2b36SAndroid Build Coastguard Worker	// Stem specifies the base name of the output file.
95*333d2b36SAndroid Build Coastguard Worker	Stem *string `android:"arch_variant"`
96*333d2b36SAndroid Build Coastguard Worker	// Html indicates an html-format file is needed. The default is text. Can be Html or Xml but not both.
97*333d2b36SAndroid Build Coastguard Worker	Html *bool
98*333d2b36SAndroid Build Coastguard Worker	// Xml indicates an xml-format file is needed. The default is text. Can be Html or Xml but not both.
99*333d2b36SAndroid Build Coastguard Worker	Xml *bool
100*333d2b36SAndroid Build Coastguard Worker	// Gzipped indicates the output file must be compressed with gzip. Will append .gz to suffix if not there.
101*333d2b36SAndroid Build Coastguard Worker	Gzipped *bool
102*333d2b36SAndroid Build Coastguard Worker	// Suffix specifies the file extension to use. Defaults to .html for html, .xml for xml, or no extension for text.
103*333d2b36SAndroid Build Coastguard Worker	Suffix *string
104*333d2b36SAndroid Build Coastguard Worker	// Visibility specifies where this license can be used
105*333d2b36SAndroid Build Coastguard Worker	Visibility []string
106*333d2b36SAndroid Build Coastguard Worker}
107*333d2b36SAndroid Build Coastguard Worker
108*333d2b36SAndroid Build Coastguard Workertype genNoticeModule struct {
109*333d2b36SAndroid Build Coastguard Worker	ModuleBase
110*333d2b36SAndroid Build Coastguard Worker	DefaultableModuleBase
111*333d2b36SAndroid Build Coastguard Worker
112*333d2b36SAndroid Build Coastguard Worker	properties genNoticeProperties
113*333d2b36SAndroid Build Coastguard Worker
114*333d2b36SAndroid Build Coastguard Worker	output  OutputPath
115*333d2b36SAndroid Build Coastguard Worker	missing []string
116*333d2b36SAndroid Build Coastguard Worker}
117*333d2b36SAndroid Build Coastguard Worker
118*333d2b36SAndroid Build Coastguard Workerfunc (m *genNoticeModule) DepsMutator(ctx BottomUpMutatorContext) {
119*333d2b36SAndroid Build Coastguard Worker	if ctx.ContainsProperty("licenses") {
120*333d2b36SAndroid Build Coastguard Worker		ctx.PropertyErrorf("licenses", "not supported on \"gen_notice\" modules")
121*333d2b36SAndroid Build Coastguard Worker	}
122*333d2b36SAndroid Build Coastguard Worker	if proptools.Bool(m.properties.Html) && proptools.Bool(m.properties.Xml) {
123*333d2b36SAndroid Build Coastguard Worker		ctx.ModuleErrorf("can be html or xml but not both")
124*333d2b36SAndroid Build Coastguard Worker	}
125*333d2b36SAndroid Build Coastguard Worker	if !ctx.Config().AllowMissingDependencies() {
126*333d2b36SAndroid Build Coastguard Worker		var missing []string
127*333d2b36SAndroid Build Coastguard Worker		// Verify the modules for which to generate notices exist.
128*333d2b36SAndroid Build Coastguard Worker		for _, otherMod := range m.properties.For {
129*333d2b36SAndroid Build Coastguard Worker			if !ctx.OtherModuleExists(otherMod) {
130*333d2b36SAndroid Build Coastguard Worker				missing = append(missing, otherMod)
131*333d2b36SAndroid Build Coastguard Worker			}
132*333d2b36SAndroid Build Coastguard Worker		}
133*333d2b36SAndroid Build Coastguard Worker		if len(missing) == 1 {
134*333d2b36SAndroid Build Coastguard Worker			ctx.PropertyErrorf("for", "no %q module exists", missing[0])
135*333d2b36SAndroid Build Coastguard Worker		} else if len(missing) > 1 {
136*333d2b36SAndroid Build Coastguard Worker			ctx.PropertyErrorf("for", "modules \"%s\" do not exist", strings.Join(missing, "\", \""))
137*333d2b36SAndroid Build Coastguard Worker		}
138*333d2b36SAndroid Build Coastguard Worker	}
139*333d2b36SAndroid Build Coastguard Worker}
140*333d2b36SAndroid Build Coastguard Worker
141*333d2b36SAndroid Build Coastguard Workerfunc (m *genNoticeModule) getStem() string {
142*333d2b36SAndroid Build Coastguard Worker	stem := m.base().BaseModuleName()
143*333d2b36SAndroid Build Coastguard Worker	if m.properties.Stem != nil {
144*333d2b36SAndroid Build Coastguard Worker		stem = proptools.String(m.properties.Stem)
145*333d2b36SAndroid Build Coastguard Worker	}
146*333d2b36SAndroid Build Coastguard Worker	return stem
147*333d2b36SAndroid Build Coastguard Worker}
148*333d2b36SAndroid Build Coastguard Worker
149*333d2b36SAndroid Build Coastguard Workerfunc (m *genNoticeModule) getSuffix() string {
150*333d2b36SAndroid Build Coastguard Worker	suffix := ""
151*333d2b36SAndroid Build Coastguard Worker	if m.properties.Suffix == nil {
152*333d2b36SAndroid Build Coastguard Worker		if proptools.Bool(m.properties.Html) {
153*333d2b36SAndroid Build Coastguard Worker			suffix = ".html"
154*333d2b36SAndroid Build Coastguard Worker		} else if proptools.Bool(m.properties.Xml) {
155*333d2b36SAndroid Build Coastguard Worker			suffix = ".xml"
156*333d2b36SAndroid Build Coastguard Worker		}
157*333d2b36SAndroid Build Coastguard Worker	} else {
158*333d2b36SAndroid Build Coastguard Worker		suffix = proptools.String(m.properties.Suffix)
159*333d2b36SAndroid Build Coastguard Worker	}
160*333d2b36SAndroid Build Coastguard Worker	if proptools.Bool(m.properties.Gzipped) && !strings.HasSuffix(suffix, ".gz") {
161*333d2b36SAndroid Build Coastguard Worker		suffix += ".gz"
162*333d2b36SAndroid Build Coastguard Worker	}
163*333d2b36SAndroid Build Coastguard Worker	return suffix
164*333d2b36SAndroid Build Coastguard Worker}
165*333d2b36SAndroid Build Coastguard Worker
166*333d2b36SAndroid Build Coastguard Workerfunc (m *genNoticeModule) GenerateAndroidBuildActions(ctx ModuleContext) {
167*333d2b36SAndroid Build Coastguard Worker	if ctx.Config().AllowMissingDependencies() {
168*333d2b36SAndroid Build Coastguard Worker		// Verify the modules for which to generate notices exist.
169*333d2b36SAndroid Build Coastguard Worker		for _, otherMod := range m.properties.For {
170*333d2b36SAndroid Build Coastguard Worker			if !ctx.OtherModuleExists(otherMod) {
171*333d2b36SAndroid Build Coastguard Worker				m.missing = append(m.missing, otherMod)
172*333d2b36SAndroid Build Coastguard Worker			}
173*333d2b36SAndroid Build Coastguard Worker		}
174*333d2b36SAndroid Build Coastguard Worker		m.missing = append(m.missing, ctx.GetMissingDependencies()...)
175*333d2b36SAndroid Build Coastguard Worker		m.missing = FirstUniqueStrings(m.missing)
176*333d2b36SAndroid Build Coastguard Worker	}
177*333d2b36SAndroid Build Coastguard Worker	out := m.getStem() + m.getSuffix()
178*333d2b36SAndroid Build Coastguard Worker	m.output = PathForModuleOut(ctx, out).OutputPath
179*333d2b36SAndroid Build Coastguard Worker	ctx.SetOutputFiles(Paths{m.output}, "")
180*333d2b36SAndroid Build Coastguard Worker}
181*333d2b36SAndroid Build Coastguard Worker
182*333d2b36SAndroid Build Coastguard Workerfunc GenNoticeFactory() Module {
183*333d2b36SAndroid Build Coastguard Worker	module := &genNoticeModule{}
184*333d2b36SAndroid Build Coastguard Worker
185*333d2b36SAndroid Build Coastguard Worker	base := module.base()
186*333d2b36SAndroid Build Coastguard Worker	module.AddProperties(&base.nameProperties, &module.properties)
187*333d2b36SAndroid Build Coastguard Worker
188*333d2b36SAndroid Build Coastguard Worker	// The visibility property needs to be checked and parsed by the visibility module.
189*333d2b36SAndroid Build Coastguard Worker	setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
190*333d2b36SAndroid Build Coastguard Worker
191*333d2b36SAndroid Build Coastguard Worker	InitAndroidArchModule(module, DeviceSupported, MultilibCommon)
192*333d2b36SAndroid Build Coastguard Worker	InitDefaultableModule(module)
193*333d2b36SAndroid Build Coastguard Worker
194*333d2b36SAndroid Build Coastguard Worker	return module
195*333d2b36SAndroid Build Coastguard Worker}
196*333d2b36SAndroid Build Coastguard Worker
197*333d2b36SAndroid Build Coastguard Workervar _ AndroidMkEntriesProvider = (*genNoticeModule)(nil)
198*333d2b36SAndroid Build Coastguard Worker
199*333d2b36SAndroid Build Coastguard Worker// Implements AndroidMkEntriesProvider
200*333d2b36SAndroid Build Coastguard Workerfunc (m *genNoticeModule) AndroidMkEntries() []AndroidMkEntries {
201*333d2b36SAndroid Build Coastguard Worker	return []AndroidMkEntries{AndroidMkEntries{
202*333d2b36SAndroid Build Coastguard Worker		Class:      "ETC",
203*333d2b36SAndroid Build Coastguard Worker		OutputFile: OptionalPathForPath(m.output),
204*333d2b36SAndroid Build Coastguard Worker	}}
205*333d2b36SAndroid Build Coastguard Worker}
206*333d2b36SAndroid Build Coastguard Worker
207*333d2b36SAndroid Build Coastguard Worker// missingReferencesRule emits an ErrorRule for missing module references.
208*333d2b36SAndroid Build Coastguard Workerfunc missingReferencesRule(ctx BuilderContext, m *genNoticeModule) {
209*333d2b36SAndroid Build Coastguard Worker	if len(m.missing) < 1 {
210*333d2b36SAndroid Build Coastguard Worker		panic(fmt.Errorf("missing references rule requested with no missing references"))
211*333d2b36SAndroid Build Coastguard Worker	}
212*333d2b36SAndroid Build Coastguard Worker
213*333d2b36SAndroid Build Coastguard Worker	ctx.Build(pctx, BuildParams{
214*333d2b36SAndroid Build Coastguard Worker		Rule:        ErrorRule,
215*333d2b36SAndroid Build Coastguard Worker		Output:      m.output,
216*333d2b36SAndroid Build Coastguard Worker		Description: "notice for " + proptools.StringDefault(m.properties.ArtifactName, "container"),
217*333d2b36SAndroid Build Coastguard Worker		Args: map[string]string{
218*333d2b36SAndroid Build Coastguard Worker			"error": m.Name() + " references missing module(s): " + strings.Join(m.missing, ", "),
219*333d2b36SAndroid Build Coastguard Worker		},
220*333d2b36SAndroid Build Coastguard Worker	})
221*333d2b36SAndroid Build Coastguard Worker}
222