sdk.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // Copyright (C) 2019 The Android Open Source Project
  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 sdk
  15. import (
  16. "fmt"
  17. "io"
  18. "github.com/google/blueprint"
  19. "github.com/google/blueprint/proptools"
  20. "android/soong/android"
  21. // This package doesn't depend on the apex package, but import it to make its mutators to be
  22. // registered before mutators in this package. See RegisterPostDepsMutators for more details.
  23. _ "android/soong/apex"
  24. )
  25. func init() {
  26. pctx.Import("android/soong/android")
  27. pctx.Import("android/soong/java/config")
  28. registerSdkBuildComponents(android.InitRegistrationContext)
  29. }
  30. func registerSdkBuildComponents(ctx android.RegistrationContext) {
  31. ctx.RegisterModuleType("sdk", SdkModuleFactory)
  32. ctx.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
  33. }
  34. type sdk struct {
  35. android.ModuleBase
  36. android.DefaultableModuleBase
  37. // The dynamically generated information about the registered SdkMemberType
  38. dynamicSdkMemberTypes *dynamicSdkMemberTypes
  39. // The dynamically created instance of the properties struct containing the sdk member type
  40. // list properties, e.g. java_libs.
  41. dynamicMemberTypeListProperties interface{}
  42. // The dynamically generated information about the registered SdkMemberTrait
  43. dynamicSdkMemberTraits *dynamicSdkMemberTraits
  44. // The dynamically created instance of the properties struct containing the sdk member trait
  45. // list properties.
  46. dynamicMemberTraitListProperties interface{}
  47. // Information about the OsType specific member variants depended upon by this variant.
  48. //
  49. // Set by OsType specific variants in the collectMembers() method and used by the
  50. // CommonOS variant when building the snapshot. That work is all done on separate
  51. // calls to the sdk.GenerateAndroidBuildActions method which is guaranteed to be
  52. // called for the OsType specific variants before the CommonOS variant (because
  53. // the latter depends on the former).
  54. memberVariantDeps []sdkMemberVariantDep
  55. // The multilib variants that are used by this sdk variant.
  56. multilibUsages multilibUsage
  57. properties sdkProperties
  58. snapshotFile android.OptionalPath
  59. infoFile android.OptionalPath
  60. // The builder, preserved for testing.
  61. builderForTests *snapshotBuilder
  62. }
  63. type sdkProperties struct {
  64. Snapshot bool `blueprint:"mutated"`
  65. // True if this is a module_exports (or module_exports_snapshot) module type.
  66. Module_exports bool `blueprint:"mutated"`
  67. // The additional visibility to add to the prebuilt modules to allow them to
  68. // reference each other.
  69. //
  70. // This can only be used to widen the visibility of the members:
  71. //
  72. // * Specifying //visibility:public here will make all members visible and
  73. // essentially ignore their own visibility.
  74. // * Specifying //visibility:private here is an error.
  75. // * Specifying any other rule here will add it to the members visibility and
  76. // be output to the member prebuilt in the snapshot. Duplicates will be
  77. // dropped. Adding a rule to members that have //visibility:private will
  78. // cause the //visibility:private to be discarded.
  79. Prebuilt_visibility []string
  80. }
  81. // sdk defines an SDK which is a logical group of modules (e.g. native libs, headers, java libs, etc.)
  82. // which Mainline modules like APEX can choose to build with.
  83. func SdkModuleFactory() android.Module {
  84. return newSdkModule(false)
  85. }
  86. func newSdkModule(moduleExports bool) *sdk {
  87. s := &sdk{}
  88. s.properties.Module_exports = moduleExports
  89. // Get the dynamic sdk member type data for the currently registered sdk member types.
  90. sdkMemberTypeKey, sdkMemberTypes := android.RegisteredSdkMemberTypes(moduleExports)
  91. s.dynamicSdkMemberTypes = getDynamicSdkMemberTypes(sdkMemberTypeKey, sdkMemberTypes)
  92. // Create an instance of the dynamically created struct that contains all the
  93. // properties for the member type specific list properties.
  94. s.dynamicMemberTypeListProperties = s.dynamicSdkMemberTypes.createMemberTypeListProperties()
  95. sdkMemberTraitsKey, sdkMemberTraits := android.RegisteredSdkMemberTraits()
  96. s.dynamicSdkMemberTraits = getDynamicSdkMemberTraits(sdkMemberTraitsKey, sdkMemberTraits)
  97. // Create an instance of the dynamically created struct that contains all the properties for the
  98. // member trait specific list properties.
  99. s.dynamicMemberTraitListProperties = s.dynamicSdkMemberTraits.createMemberTraitListProperties()
  100. // Create a wrapper around the dynamic trait specific properties so that they have to be
  101. // specified within a traits:{} section in the .bp file.
  102. traitsWrapper := struct {
  103. Traits interface{}
  104. }{s.dynamicMemberTraitListProperties}
  105. s.AddProperties(&s.properties, s.dynamicMemberTypeListProperties, &traitsWrapper)
  106. // Make sure that the prebuilt visibility property is verified for errors.
  107. android.AddVisibilityProperty(s, "prebuilt_visibility", &s.properties.Prebuilt_visibility)
  108. android.InitCommonOSAndroidMultiTargetsArchModule(s, android.HostAndDeviceSupported, android.MultilibCommon)
  109. android.InitDefaultableModule(s)
  110. android.AddLoadHook(s, func(ctx android.LoadHookContext) {
  111. type props struct {
  112. Compile_multilib *string
  113. }
  114. p := &props{Compile_multilib: proptools.StringPtr("both")}
  115. ctx.PrependProperties(p)
  116. })
  117. return s
  118. }
  119. // sdk_snapshot is a snapshot of an SDK. This is an auto-generated module.
  120. func SnapshotModuleFactory() android.Module {
  121. s := newSdkModule(false)
  122. s.properties.Snapshot = true
  123. return s
  124. }
  125. func (s *sdk) memberTypeListProperties() []*sdkMemberTypeListProperty {
  126. return s.dynamicSdkMemberTypes.memberTypeListProperties
  127. }
  128. func (s *sdk) memberTypeListProperty(memberType android.SdkMemberType) *sdkMemberTypeListProperty {
  129. return s.dynamicSdkMemberTypes.memberTypeToProperty[memberType]
  130. }
  131. // memberTraitListProperties returns the list of *sdkMemberTraitListProperty instances for this sdk.
  132. func (s *sdk) memberTraitListProperties() []*sdkMemberTraitListProperty {
  133. return s.dynamicSdkMemberTraits.memberTraitListProperties
  134. }
  135. func (s *sdk) snapshot() bool {
  136. return s.properties.Snapshot
  137. }
  138. func (s *sdk) GenerateAndroidBuildActions(ctx android.ModuleContext) {
  139. if s.snapshot() {
  140. // We don't need to create a snapshot out of sdk_snapshot.
  141. // That doesn't make sense. We need a snapshot to create sdk_snapshot.
  142. return
  143. }
  144. // This method is guaranteed to be called on OsType specific variants before it is called
  145. // on their corresponding CommonOS variant.
  146. if !s.IsCommonOSVariant() {
  147. // Update the OsType specific sdk variant with information about its members.
  148. s.collectMembers(ctx)
  149. } else {
  150. // Get the OsType specific variants on which the CommonOS depends.
  151. osSpecificVariants := android.GetOsSpecificVariantsOfCommonOSVariant(ctx)
  152. var sdkVariants []*sdk
  153. for _, m := range osSpecificVariants {
  154. if sdkVariant, ok := m.(*sdk); ok {
  155. sdkVariants = append(sdkVariants, sdkVariant)
  156. }
  157. }
  158. // Generate the snapshot from the member info.
  159. s.buildSnapshot(ctx, sdkVariants)
  160. }
  161. }
  162. func (s *sdk) AndroidMkEntries() []android.AndroidMkEntries {
  163. if !s.snapshotFile.Valid() != !s.infoFile.Valid() {
  164. panic("Snapshot (%q) and info file (%q) should both be set or neither should be set.")
  165. } else if !s.snapshotFile.Valid() {
  166. return []android.AndroidMkEntries{}
  167. }
  168. return []android.AndroidMkEntries{android.AndroidMkEntries{
  169. Class: "FAKE",
  170. OutputFile: s.snapshotFile,
  171. DistFiles: android.MakeDefaultDistFiles(s.snapshotFile.Path(), s.infoFile.Path()),
  172. Include: "$(BUILD_PHONY_PACKAGE)",
  173. ExtraFooters: []android.AndroidMkExtraFootersFunc{
  174. func(w io.Writer, name, prefix, moduleDir string) {
  175. // Allow the sdk to be built by simply passing its name on the command line.
  176. fmt.Fprintln(w, ".PHONY:", s.Name())
  177. fmt.Fprintln(w, s.Name()+":", s.snapshotFile.String())
  178. // Allow the sdk info to be built by simply passing its name on the command line.
  179. infoTarget := s.Name() + ".info"
  180. fmt.Fprintln(w, ".PHONY:", infoTarget)
  181. fmt.Fprintln(w, infoTarget+":", s.infoFile.String())
  182. },
  183. },
  184. }}
  185. }
  186. // gatherTraits gathers the traits from the dynamically generated trait specific properties.
  187. //
  188. // Returns a map from member name to the set of required traits.
  189. func (s *sdk) gatherTraits() map[string]android.SdkMemberTraitSet {
  190. traitListByMember := map[string][]android.SdkMemberTrait{}
  191. for _, memberListProperty := range s.memberTraitListProperties() {
  192. names := memberListProperty.getter(s.dynamicMemberTraitListProperties)
  193. for _, name := range names {
  194. traitListByMember[name] = append(traitListByMember[name], memberListProperty.memberTrait)
  195. }
  196. }
  197. traitSetByMember := map[string]android.SdkMemberTraitSet{}
  198. for name, list := range traitListByMember {
  199. traitSetByMember[name] = android.NewSdkMemberTraitSet(list)
  200. }
  201. return traitSetByMember
  202. }
  203. // newDependencyContext creates a new SdkDependencyContext for this sdk.
  204. func (s *sdk) newDependencyContext(mctx android.BottomUpMutatorContext) android.SdkDependencyContext {
  205. traits := s.gatherTraits()
  206. return &dependencyContext{
  207. BottomUpMutatorContext: mctx,
  208. requiredTraits: traits,
  209. }
  210. }
  211. type dependencyContext struct {
  212. android.BottomUpMutatorContext
  213. // Map from member name to the set of traits that the sdk requires the member provides.
  214. requiredTraits map[string]android.SdkMemberTraitSet
  215. }
  216. func (d *dependencyContext) RequiredTraits(name string) android.SdkMemberTraitSet {
  217. if s, ok := d.requiredTraits[name]; ok {
  218. return s
  219. } else {
  220. return android.EmptySdkMemberTraitSet()
  221. }
  222. }
  223. func (d *dependencyContext) RequiresTrait(name string, trait android.SdkMemberTrait) bool {
  224. return d.RequiredTraits(name).Contains(trait)
  225. }
  226. var _ android.SdkDependencyContext = (*dependencyContext)(nil)
  227. type dependencyTag struct {
  228. blueprint.BaseDependencyTag
  229. }
  230. // Mark this tag so dependencies that use it are excluded from APEX contents.
  231. func (t dependencyTag) ExcludeFromApexContents() {}
  232. var _ android.ExcludeFromApexContentsTag = dependencyTag{}
  233. func (s *sdk) DepsMutator(mctx android.BottomUpMutatorContext) {
  234. // Add dependencies from non CommonOS variants to the sdk member variants.
  235. if s.IsCommonOSVariant() {
  236. return
  237. }
  238. ctx := s.newDependencyContext(mctx)
  239. for _, memberListProperty := range s.memberTypeListProperties() {
  240. if memberListProperty.getter == nil {
  241. continue
  242. }
  243. names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
  244. if len(names) > 0 {
  245. memberType := memberListProperty.memberType
  246. // Verify that the member type supports the specified traits.
  247. supportedTraits := memberType.SupportedTraits()
  248. for _, name := range names {
  249. requiredTraits := ctx.RequiredTraits(name)
  250. unsupportedTraits := requiredTraits.Subtract(supportedTraits)
  251. if !unsupportedTraits.Empty() {
  252. ctx.ModuleErrorf("sdk member %q has traits %s that are unsupported by its member type %q",
  253. name, unsupportedTraits, memberType.SdkPropertyName())
  254. }
  255. }
  256. // Add dependencies using the appropriate tag.
  257. tag := memberListProperty.dependencyTag
  258. memberType.AddDependencies(ctx, tag, names)
  259. }
  260. }
  261. }