sdk.go 13 KB

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