system_modules.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. // Copyright 2017 Google Inc. All rights reserved.
  2. // Licensed under the Apache License, Version 2.0 (the "License");
  3. // you may not use this file except in compliance with the License.
  4. // You may obtain a copy of the License at
  5. //
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. package java
  14. import (
  15. "fmt"
  16. "io"
  17. "strings"
  18. "github.com/google/blueprint"
  19. "android/soong/android"
  20. )
  21. // OpenJDK 9 introduces the concept of "system modules", which replace the bootclasspath. This
  22. // file will produce the rules necessary to convert each unique set of bootclasspath jars into
  23. // system modules in a runtime image using the jmod and jlink tools.
  24. func init() {
  25. RegisterSystemModulesBuildComponents(android.InitRegistrationContext)
  26. pctx.SourcePathVariable("moduleInfoJavaPath", "build/soong/scripts/jars-to-module-info-java.sh")
  27. // Register sdk member types.
  28. android.RegisterSdkMemberType(&systemModulesSdkMemberType{
  29. android.SdkMemberTypeBase{
  30. PropertyName: "java_system_modules",
  31. SupportsSdk: true,
  32. },
  33. })
  34. }
  35. func RegisterSystemModulesBuildComponents(ctx android.RegistrationContext) {
  36. ctx.RegisterModuleType("java_system_modules", SystemModulesFactory)
  37. ctx.RegisterModuleType("java_system_modules_import", systemModulesImportFactory)
  38. }
  39. var (
  40. jarsTosystemModules = pctx.AndroidStaticRule("jarsTosystemModules", blueprint.RuleParams{
  41. Command: `rm -rf ${outDir} ${workDir} && mkdir -p ${workDir}/jmod && ` +
  42. `${moduleInfoJavaPath} java.base $in > ${workDir}/module-info.java && ` +
  43. `${config.JavacCmd} --system=none --patch-module=java.base=${classpath} ${workDir}/module-info.java && ` +
  44. `${config.SoongZipCmd} -jar -o ${workDir}/classes.jar -C ${workDir} -f ${workDir}/module-info.class && ` +
  45. `${config.MergeZipsCmd} -j ${workDir}/module.jar ${workDir}/classes.jar $in && ` +
  46. // Note: The version of the java.base module created must match the version
  47. // of the jlink tool which consumes it.
  48. `${config.JmodCmd} create --module-version ${config.JlinkVersion} --target-platform android ` +
  49. ` --class-path ${workDir}/module.jar ${workDir}/jmod/java.base.jmod && ` +
  50. `${config.JlinkCmd} --module-path ${workDir}/jmod --add-modules java.base --output ${outDir} ` +
  51. // Note: The system-modules jlink plugin is disabled because (a) it is not
  52. // useful on Android, and (b) it causes errors with later versions of jlink
  53. // when the jdk.internal.module is absent from java.base (as it is here).
  54. ` --disable-plugin system-modules && ` +
  55. `cp ${config.JrtFsJar} ${outDir}/lib/`,
  56. CommandDeps: []string{
  57. "${moduleInfoJavaPath}",
  58. "${config.JavacCmd}",
  59. "${config.SoongZipCmd}",
  60. "${config.MergeZipsCmd}",
  61. "${config.JmodCmd}",
  62. "${config.JlinkCmd}",
  63. "${config.JrtFsJar}",
  64. },
  65. },
  66. "classpath", "outDir", "workDir")
  67. // Dependency tag that causes the added dependencies to be added as java_header_libs
  68. // to the sdk/module_exports/snapshot. Dependencies that are added automatically via this tag are
  69. // not automatically exported.
  70. systemModulesLibsTag = android.DependencyTagForSdkMemberType(javaHeaderLibsSdkMemberType, false)
  71. )
  72. func TransformJarsToSystemModules(ctx android.ModuleContext, jars android.Paths) (android.Path, android.Paths) {
  73. outDir := android.PathForModuleOut(ctx, "system")
  74. workDir := android.PathForModuleOut(ctx, "modules")
  75. outputFile := android.PathForModuleOut(ctx, "system/lib/modules")
  76. outputs := android.WritablePaths{
  77. outputFile,
  78. android.PathForModuleOut(ctx, "system/lib/jrt-fs.jar"),
  79. android.PathForModuleOut(ctx, "system/release"),
  80. }
  81. ctx.Build(pctx, android.BuildParams{
  82. Rule: jarsTosystemModules,
  83. Description: "system modules",
  84. Outputs: outputs,
  85. Inputs: jars,
  86. Args: map[string]string{
  87. "classpath": strings.Join(jars.Strings(), ":"),
  88. "workDir": workDir.String(),
  89. "outDir": outDir.String(),
  90. },
  91. })
  92. return outDir, outputs.Paths()
  93. }
  94. // java_system_modules creates a system module from a set of java libraries that can
  95. // be referenced from the system_modules property. It must contain at a minimum the
  96. // java.base module which must include classes from java.lang amongst other java packages.
  97. func SystemModulesFactory() android.Module {
  98. module := &SystemModules{}
  99. module.AddProperties(&module.properties)
  100. android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
  101. android.InitDefaultableModule(module)
  102. return module
  103. }
  104. type SystemModulesProvider interface {
  105. HeaderJars() android.Paths
  106. OutputDirAndDeps() (android.Path, android.Paths)
  107. }
  108. var _ SystemModulesProvider = (*SystemModules)(nil)
  109. var _ SystemModulesProvider = (*systemModulesImport)(nil)
  110. type SystemModules struct {
  111. android.ModuleBase
  112. android.DefaultableModuleBase
  113. properties SystemModulesProperties
  114. // The aggregated header jars from all jars specified in the libs property.
  115. // Used when system module is added as a dependency to bootclasspath.
  116. headerJars android.Paths
  117. outputDir android.Path
  118. outputDeps android.Paths
  119. }
  120. type SystemModulesProperties struct {
  121. // List of java library modules that should be included in the system modules
  122. Libs []string
  123. }
  124. func (system *SystemModules) HeaderJars() android.Paths {
  125. return system.headerJars
  126. }
  127. func (system *SystemModules) OutputDirAndDeps() (android.Path, android.Paths) {
  128. if system.outputDir == nil || len(system.outputDeps) == 0 {
  129. panic("Missing directory for system module dependency")
  130. }
  131. return system.outputDir, system.outputDeps
  132. }
  133. func (system *SystemModules) GenerateAndroidBuildActions(ctx android.ModuleContext) {
  134. var jars android.Paths
  135. ctx.VisitDirectDepsWithTag(systemModulesLibsTag, func(module android.Module) {
  136. dep, _ := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
  137. jars = append(jars, dep.HeaderJars...)
  138. })
  139. system.headerJars = jars
  140. system.outputDir, system.outputDeps = TransformJarsToSystemModules(ctx, jars)
  141. }
  142. // ComponentDepsMutator is called before prebuilt modules without a corresponding source module are
  143. // renamed so unless the supplied libs specifically includes the prebuilt_ prefix this is guaranteed
  144. // to only add dependencies on source modules.
  145. //
  146. // The systemModuleLibsTag will prevent the prebuilt mutators from replacing this dependency so it
  147. // will never be changed to depend on a prebuilt either.
  148. func (system *SystemModules) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
  149. ctx.AddVariationDependencies(nil, systemModulesLibsTag, system.properties.Libs...)
  150. }
  151. func (system *SystemModules) AndroidMk() android.AndroidMkData {
  152. return android.AndroidMkData{
  153. Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
  154. fmt.Fprintln(w)
  155. makevar := "SOONG_SYSTEM_MODULES_" + name
  156. fmt.Fprintln(w, makevar, ":=$=", system.outputDir.String())
  157. fmt.Fprintln(w)
  158. makevar = "SOONG_SYSTEM_MODULES_LIBS_" + name
  159. fmt.Fprintln(w, makevar, ":=$=", strings.Join(system.properties.Libs, " "))
  160. fmt.Fprintln(w)
  161. makevar = "SOONG_SYSTEM_MODULES_DEPS_" + name
  162. fmt.Fprintln(w, makevar, ":=$=", strings.Join(system.outputDeps.Strings(), " "))
  163. fmt.Fprintln(w)
  164. fmt.Fprintln(w, name+":", "$("+makevar+")")
  165. fmt.Fprintln(w, ".PHONY:", name)
  166. // TODO(b/151177513): Licenses: Doesn't go through base_rules. May have to generate meta_lic and meta_module here.
  167. },
  168. }
  169. }
  170. // A prebuilt version of java_system_modules. It does not import the
  171. // generated system module, it generates the system module from imported
  172. // java libraries in the same way that java_system_modules does. It just
  173. // acts as a prebuilt, i.e. can have the same base name as another module
  174. // type and the one to use is selected at runtime.
  175. func systemModulesImportFactory() android.Module {
  176. module := &systemModulesImport{}
  177. module.AddProperties(&module.properties)
  178. android.InitPrebuiltModule(module, &module.properties.Libs)
  179. android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
  180. android.InitDefaultableModule(module)
  181. return module
  182. }
  183. type systemModulesImport struct {
  184. SystemModules
  185. prebuilt android.Prebuilt
  186. }
  187. func (system *systemModulesImport) Name() string {
  188. return system.prebuilt.Name(system.ModuleBase.Name())
  189. }
  190. func (system *systemModulesImport) Prebuilt() *android.Prebuilt {
  191. return &system.prebuilt
  192. }
  193. // ComponentDepsMutator is called before prebuilt modules without a corresponding source module are
  194. // renamed so as this adds a prebuilt_ prefix this is guaranteed to only add dependencies on source
  195. // modules.
  196. func (system *systemModulesImport) ComponentDepsMutator(ctx android.BottomUpMutatorContext) {
  197. for _, lib := range system.properties.Libs {
  198. ctx.AddVariationDependencies(nil, systemModulesLibsTag, android.PrebuiltNameFromSource(lib))
  199. }
  200. }
  201. type systemModulesSdkMemberType struct {
  202. android.SdkMemberTypeBase
  203. }
  204. func (mt *systemModulesSdkMemberType) AddDependencies(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) {
  205. ctx.AddVariationDependencies(nil, dependencyTag, names...)
  206. }
  207. func (mt *systemModulesSdkMemberType) IsInstance(module android.Module) bool {
  208. if _, ok := module.(*SystemModules); ok {
  209. // A prebuilt system module cannot be added as a member of an sdk because the source and
  210. // snapshot instances would conflict.
  211. _, ok := module.(*systemModulesImport)
  212. return !ok
  213. }
  214. return false
  215. }
  216. func (mt *systemModulesSdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
  217. return ctx.SnapshotBuilder().AddPrebuiltModule(member, "java_system_modules_import")
  218. }
  219. type systemModulesInfoProperties struct {
  220. android.SdkMemberPropertiesBase
  221. Libs []string
  222. }
  223. func (mt *systemModulesSdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
  224. return &systemModulesInfoProperties{}
  225. }
  226. func (p *systemModulesInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
  227. systemModule := variant.(*SystemModules)
  228. p.Libs = systemModule.properties.Libs
  229. }
  230. func (p *systemModulesInfoProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
  231. if len(p.Libs) > 0 {
  232. // Add the references to the libraries that form the system module.
  233. propertySet.AddPropertyWithTag("libs", p.Libs, ctx.SnapshotBuilder().SdkMemberReferencePropertyTag(true))
  234. }
  235. }