blob: d8cfaf2a1505d65ecbb3a10a7000b8ea0400dc58 [file] [log] [blame]
Jaewoong Jung5b425e22019-06-17 17:40:56 -07001// Copyright 2019 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 "path/filepath"
19
20 "github.com/google/blueprint"
21)
22
23func init() {
24 pctx.SourcePathVariable("merge_notices", "build/soong/scripts/mergenotice.py")
Bob Badour3911e6a2020-02-10 17:08:47 -080025 pctx.SourcePathVariable("generate_notice", "build/soong/scripts/generate-notice-files.py")
Jaewoong Jung5b425e22019-06-17 17:40:56 -070026
27 pctx.HostBinToolVariable("minigzip", "minigzip")
28}
29
Jaewoong Jung98772792019-07-01 17:15:13 -070030type NoticeOutputs struct {
31 Merged OptionalPath
32 TxtOutput OptionalPath
33 HtmlOutput OptionalPath
34 HtmlGzOutput OptionalPath
35}
36
Jaewoong Jung5b425e22019-06-17 17:40:56 -070037var (
38 mergeNoticesRule = pctx.AndroidStaticRule("mergeNoticesRule", blueprint.RuleParams{
39 Command: `${merge_notices} --output $out $in`,
40 CommandDeps: []string{"${merge_notices}"},
41 Description: "merge notice files into $out",
42 })
43
44 generateNoticeRule = pctx.AndroidStaticRule("generateNoticeRule", blueprint.RuleParams{
Jaewoong Jung825c8142019-07-15 10:57:26 -070045 Command: `rm -rf $$(dirname $txtOut) $$(dirname $htmlOut) $$(dirname $out) && ` +
46 `mkdir -p $$(dirname $txtOut) $$(dirname $htmlOut) $$(dirname $out) && ` +
Jaewoong Jung98772792019-07-01 17:15:13 -070047 `${generate_notice} --text-output $txtOut --html-output $htmlOut -t "$title" -s $inputDir && ` +
48 `${minigzip} -c $htmlOut > $out`,
Jaewoong Jung5b425e22019-06-17 17:40:56 -070049 CommandDeps: []string{"${generate_notice}", "${minigzip}"},
50 Description: "produce notice file $out",
Jaewoong Jung98772792019-07-01 17:15:13 -070051 }, "txtOut", "htmlOut", "title", "inputDir")
Jaewoong Jung5b425e22019-06-17 17:40:56 -070052)
53
54func MergeNotices(ctx ModuleContext, mergedNotice WritablePath, noticePaths []Path) {
55 ctx.Build(pctx, BuildParams{
56 Rule: mergeNoticesRule,
57 Description: "merge notices",
58 Inputs: noticePaths,
59 Output: mergedNotice,
60 })
61}
62
Colin Cross70dda7e2019-10-01 22:05:35 -070063func BuildNoticeOutput(ctx ModuleContext, installPath InstallPath, installFilename string,
Jaewoong Jung98772792019-07-01 17:15:13 -070064 noticePaths []Path) NoticeOutputs {
Jaewoong Jung5b425e22019-06-17 17:40:56 -070065 // Merge all NOTICE files into one.
66 // TODO(jungjw): We should just produce a well-formatted NOTICE.html file in a single pass.
67 //
68 // generate-notice-files.py, which processes the merged NOTICE file, has somewhat strict rules
69 // about input NOTICE file paths.
70 // 1. Their relative paths to the src root become their NOTICE index titles. We want to use
71 // on-device paths as titles, and so output the merged NOTICE file the corresponding location.
72 // 2. They must end with .txt extension. Otherwise, they're ignored.
73 noticeRelPath := InstallPathToOnDevicePath(ctx, installPath.Join(ctx, installFilename+".txt"))
74 mergedNotice := PathForModuleOut(ctx, filepath.Join("NOTICE_FILES/src", noticeRelPath))
75 MergeNotices(ctx, mergedNotice, noticePaths)
76
77 // Transform the merged NOTICE file into a gzipped HTML file.
Jaewoong Jung98772792019-07-01 17:15:13 -070078 txtOuptut := PathForModuleOut(ctx, "NOTICE_txt", "NOTICE.txt")
79 htmlOutput := PathForModuleOut(ctx, "NOTICE_html", "NOTICE.html")
80 htmlGzOutput := PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz")
Jaewoong Jung5b425e22019-06-17 17:40:56 -070081 title := "Notices for " + ctx.ModuleName()
82 ctx.Build(pctx, BuildParams{
Jaewoong Jung98772792019-07-01 17:15:13 -070083 Rule: generateNoticeRule,
84 Description: "generate notice output",
85 Input: mergedNotice,
86 Output: htmlGzOutput,
87 ImplicitOutputs: WritablePaths{txtOuptut, htmlOutput},
Jaewoong Jung5b425e22019-06-17 17:40:56 -070088 Args: map[string]string{
Jaewoong Jung98772792019-07-01 17:15:13 -070089 "txtOut": txtOuptut.String(),
90 "htmlOut": htmlOutput.String(),
Jaewoong Jung5b425e22019-06-17 17:40:56 -070091 "title": title,
92 "inputDir": PathForModuleOut(ctx, "NOTICE_FILES/src").String(),
93 },
94 })
95
Jaewoong Jung98772792019-07-01 17:15:13 -070096 return NoticeOutputs{
97 Merged: OptionalPathForPath(mergedNotice),
98 TxtOutput: OptionalPathForPath(txtOuptut),
99 HtmlOutput: OptionalPathForPath(htmlOutput),
100 HtmlGzOutput: OptionalPathForPath(htmlGzOutput),
101 }
Jaewoong Jung5b425e22019-06-17 17:40:56 -0700102}
Dan Willemsen9fe14102021-07-13 21:52:04 -0700103
104// BuildNotices merges the supplied NOTICE files into a single file that lists notices
105// for every key in noticeMap (which would normally be installed files).
106func BuildNotices(ctx ModuleContext, noticeMap map[string]Paths) NoticeOutputs {
107 // TODO(jungjw): We should just produce a well-formatted NOTICE.html file in a single pass.
108 //
109 // generate-notice-files.py, which processes the merged NOTICE file, has somewhat strict rules
110 // about input NOTICE file paths.
111 // 1. Their relative paths to the src root become their NOTICE index titles. We want to use
112 // on-device paths as titles, and so output the merged NOTICE file the corresponding location.
113 // 2. They must end with .txt extension. Otherwise, they're ignored.
114
115 mergeTool := PathForSource(ctx, "build/soong/scripts/mergenotice.py")
116 generateNoticeTool := PathForSource(ctx, "build/soong/scripts/generate-notice-files.py")
117
118 outputDir := PathForModuleOut(ctx, "notices")
119 builder := NewRuleBuilder(pctx, ctx).
120 Sbox(outputDir, PathForModuleOut(ctx, "notices.sbox.textproto"))
121 for _, installPath := range SortedStringKeys(noticeMap) {
122 noticePath := outputDir.Join(ctx, installPath+".txt")
123 // It would be nice if sbox created directories for temporaries, but until then
124 // this is simple enough.
125 builder.Command().
126 Text("(cd").OutputDir().Text("&&").
127 Text("mkdir -p").Text(filepath.Dir(installPath)).Text(")")
128 builder.Temporary(noticePath)
129 builder.Command().
130 Tool(mergeTool).
131 Flag("--output").Output(noticePath).
132 Inputs(noticeMap[installPath])
133 }
134
135 // Transform the merged NOTICE file into a gzipped HTML file.
136 txtOutput := outputDir.Join(ctx, "NOTICE.txt")
137 htmlOutput := outputDir.Join(ctx, "NOTICE.html")
138 htmlGzOutput := outputDir.Join(ctx, "NOTICE.html.gz")
139 title := "\"Notices for " + ctx.ModuleName() + "\""
140 builder.Command().Tool(generateNoticeTool).
141 FlagWithOutput("--text-output ", txtOutput).
142 FlagWithOutput("--html-output ", htmlOutput).
143 FlagWithArg("-t ", title).
144 Flag("-s").OutputDir()
145 builder.Command().BuiltTool("minigzip").
146 FlagWithInput("-c ", htmlOutput).
147 FlagWithOutput("> ", htmlGzOutput)
148 builder.Build("build_notices", "generate notice output")
149
150 return NoticeOutputs{
151 TxtOutput: OptionalPathForPath(txtOutput),
152 HtmlOutput: OptionalPathForPath(htmlOutput),
153 HtmlGzOutput: OptionalPathForPath(htmlGzOutput),
154 }
155}