gen_notice.go 6.8 KB

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