Jaewoong Jung | 5b425e2 | 2019-06-17 17:40:56 -0700 | [diff] [blame] | 1 | // 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 | |
| 15 | package android |
| 16 | |
| 17 | import ( |
| 18 | "path/filepath" |
| 19 | |
| 20 | "github.com/google/blueprint" |
| 21 | ) |
| 22 | |
| 23 | func init() { |
| 24 | pctx.SourcePathVariable("merge_notices", "build/soong/scripts/mergenotice.py") |
Bob Badour | 3911e6a | 2020-02-10 17:08:47 -0800 | [diff] [blame] | 25 | pctx.SourcePathVariable("generate_notice", "build/soong/scripts/generate-notice-files.py") |
Jaewoong Jung | 5b425e2 | 2019-06-17 17:40:56 -0700 | [diff] [blame] | 26 | |
| 27 | pctx.HostBinToolVariable("minigzip", "minigzip") |
| 28 | } |
| 29 | |
Jaewoong Jung | 9877279 | 2019-07-01 17:15:13 -0700 | [diff] [blame] | 30 | type NoticeOutputs struct { |
| 31 | Merged OptionalPath |
| 32 | TxtOutput OptionalPath |
| 33 | HtmlOutput OptionalPath |
| 34 | HtmlGzOutput OptionalPath |
| 35 | } |
| 36 | |
Jaewoong Jung | 5b425e2 | 2019-06-17 17:40:56 -0700 | [diff] [blame] | 37 | var ( |
| 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 Jung | 825c814 | 2019-07-15 10:57:26 -0700 | [diff] [blame] | 45 | Command: `rm -rf $$(dirname $txtOut) $$(dirname $htmlOut) $$(dirname $out) && ` + |
| 46 | `mkdir -p $$(dirname $txtOut) $$(dirname $htmlOut) $$(dirname $out) && ` + |
Jaewoong Jung | 9877279 | 2019-07-01 17:15:13 -0700 | [diff] [blame] | 47 | `${generate_notice} --text-output $txtOut --html-output $htmlOut -t "$title" -s $inputDir && ` + |
| 48 | `${minigzip} -c $htmlOut > $out`, |
Jaewoong Jung | 5b425e2 | 2019-06-17 17:40:56 -0700 | [diff] [blame] | 49 | CommandDeps: []string{"${generate_notice}", "${minigzip}"}, |
| 50 | Description: "produce notice file $out", |
Jaewoong Jung | 9877279 | 2019-07-01 17:15:13 -0700 | [diff] [blame] | 51 | }, "txtOut", "htmlOut", "title", "inputDir") |
Jaewoong Jung | 5b425e2 | 2019-06-17 17:40:56 -0700 | [diff] [blame] | 52 | ) |
| 53 | |
| 54 | func 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 Cross | 70dda7e | 2019-10-01 22:05:35 -0700 | [diff] [blame] | 63 | func BuildNoticeOutput(ctx ModuleContext, installPath InstallPath, installFilename string, |
Jaewoong Jung | 9877279 | 2019-07-01 17:15:13 -0700 | [diff] [blame] | 64 | noticePaths []Path) NoticeOutputs { |
Jaewoong Jung | 5b425e2 | 2019-06-17 17:40:56 -0700 | [diff] [blame] | 65 | // 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 Jung | 9877279 | 2019-07-01 17:15:13 -0700 | [diff] [blame] | 78 | txtOuptut := PathForModuleOut(ctx, "NOTICE_txt", "NOTICE.txt") |
| 79 | htmlOutput := PathForModuleOut(ctx, "NOTICE_html", "NOTICE.html") |
| 80 | htmlGzOutput := PathForModuleOut(ctx, "NOTICE", "NOTICE.html.gz") |
Jaewoong Jung | 5b425e2 | 2019-06-17 17:40:56 -0700 | [diff] [blame] | 81 | title := "Notices for " + ctx.ModuleName() |
| 82 | ctx.Build(pctx, BuildParams{ |
Jaewoong Jung | 9877279 | 2019-07-01 17:15:13 -0700 | [diff] [blame] | 83 | Rule: generateNoticeRule, |
| 84 | Description: "generate notice output", |
| 85 | Input: mergedNotice, |
| 86 | Output: htmlGzOutput, |
| 87 | ImplicitOutputs: WritablePaths{txtOuptut, htmlOutput}, |
Jaewoong Jung | 5b425e2 | 2019-06-17 17:40:56 -0700 | [diff] [blame] | 88 | Args: map[string]string{ |
Jaewoong Jung | 9877279 | 2019-07-01 17:15:13 -0700 | [diff] [blame] | 89 | "txtOut": txtOuptut.String(), |
| 90 | "htmlOut": htmlOutput.String(), |
Jaewoong Jung | 5b425e2 | 2019-06-17 17:40:56 -0700 | [diff] [blame] | 91 | "title": title, |
| 92 | "inputDir": PathForModuleOut(ctx, "NOTICE_FILES/src").String(), |
| 93 | }, |
| 94 | }) |
| 95 | |
Jaewoong Jung | 9877279 | 2019-07-01 17:15:13 -0700 | [diff] [blame] | 96 | return NoticeOutputs{ |
| 97 | Merged: OptionalPathForPath(mergedNotice), |
| 98 | TxtOutput: OptionalPathForPath(txtOuptut), |
| 99 | HtmlOutput: OptionalPathForPath(htmlOutput), |
| 100 | HtmlGzOutput: OptionalPathForPath(htmlGzOutput), |
| 101 | } |
Jaewoong Jung | 5b425e2 | 2019-06-17 17:40:56 -0700 | [diff] [blame] | 102 | } |
Dan Willemsen | 9fe1410 | 2021-07-13 21:52:04 -0700 | [diff] [blame^] | 103 | |
| 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). |
| 106 | func 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 | } |