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 14 package java 15 16 import ( 17 "fmt" 18 "io" 19 "strings" 20 21 "github.com/google/blueprint" 22 23 "android/soong/android" 24 ) 25 26 // OpenJDK 9 introduces the concept of "system modules", which replace the bootclasspath. This 27 // file will produce the rules necessary to convert each unique set of bootclasspath jars into 28 // system modules in a runtime image using the jmod and jlink tools. 29 30 func init() { 31 android.RegisterModuleType("java_system_modules", SystemModulesFactory) 32 33 pctx.SourcePathVariable("moduleInfoJavaPath", "build/soong/scripts/jars-to-module-info-java.sh") 34 } 35 36 var ( 37 jarsTosystemModules = pctx.AndroidStaticRule("jarsTosystemModules", blueprint.RuleParams{ 38 Command: `rm -rf ${outDir} ${workDir} && mkdir -p ${workDir}/jmod && ` + 39 `${moduleInfoJavaPath} ${moduleName} $in > ${workDir}/module-info.java && ` + 40 `${config.JavacCmd} --system=none --patch-module=java.base=${classpath} ${workDir}/module-info.java && ` + 41 `${config.SoongZipCmd} -jar -o ${workDir}/classes.jar -C ${workDir} -f ${workDir}/module-info.class && ` + 42 `${config.MergeZipsCmd} -j ${workDir}/module.jar ${workDir}/classes.jar $in && ` + 43 `${config.JmodCmd} create --module-version 9 --target-platform android ` + 44 ` --class-path ${workDir}/module.jar ${workDir}/jmod/${moduleName}.jmod && ` + 45 `${config.JlinkCmd} --module-path ${workDir}/jmod --add-modules ${moduleName} --output ${outDir} && ` + 46 `cp ${config.JrtFsJar} ${outDir}/lib/`, 47 CommandDeps: []string{ 48 "${moduleInfoJavaPath}", 49 "${config.JavacCmd}", 50 "${config.SoongZipCmd}", 51 "${config.MergeZipsCmd}", 52 "${config.JmodCmd}", 53 "${config.JlinkCmd}", 54 "${config.JrtFsJar}", 55 }, 56 }, 57 "moduleName", "classpath", "outDir", "workDir") 58 ) 59 60 func TransformJarsToSystemModules(ctx android.ModuleContext, moduleName string, jars android.Paths) android.WritablePath { 61 outDir := android.PathForModuleOut(ctx, "system") 62 workDir := android.PathForModuleOut(ctx, "modules") 63 outputFile := android.PathForModuleOut(ctx, "system/lib/modules") 64 outputs := android.WritablePaths{ 65 outputFile, 66 android.PathForModuleOut(ctx, "system/lib/jrt-fs.jar"), 67 android.PathForModuleOut(ctx, "system/release"), 68 } 69 70 ctx.Build(pctx, android.BuildParams{ 71 Rule: jarsTosystemModules, 72 Description: "system modules", 73 Outputs: outputs, 74 Inputs: jars, 75 Args: map[string]string{ 76 "moduleName": moduleName, 77 "classpath": strings.Join(jars.Strings(), ":"), 78 "workDir": workDir.String(), 79 "outDir": outDir.String(), 80 }, 81 }) 82 83 return outputFile 84 } 85 86 func SystemModulesFactory() android.Module { 87 module := &SystemModules{} 88 module.AddProperties(&module.properties) 89 android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) 90 return module 91 } 92 93 type SystemModules struct { 94 android.ModuleBase 95 96 properties SystemModulesProperties 97 98 outputFile android.Path 99 } 100 101 type SystemModulesProperties struct { 102 // List of java library modules that should be included in the system modules 103 Libs []string 104 105 // List of prebuilt jars that should be included in the system modules 106 Jars []string 107 108 // Sdk version that should be included in the system modules 109 Sdk_version *string 110 } 111 112 func (system *SystemModules) GenerateAndroidBuildActions(ctx android.ModuleContext) { 113 var jars android.Paths 114 115 ctx.VisitDirectDepsWithTag(libTag, func(module android.Module) { 116 dep, _ := module.(Dependency) 117 jars = append(jars, dep.HeaderJars()...) 118 }) 119 120 jars = append(jars, android.PathsForModuleSrc(ctx, system.properties.Jars)...) 121 122 if ctx.Config().TargetOpenJDK9() { 123 system.outputFile = TransformJarsToSystemModules(ctx, "java.base", jars) 124 } 125 } 126 127 func (system *SystemModules) DepsMutator(ctx android.BottomUpMutatorContext) { 128 ctx.AddDependency(ctx.Module(), libTag, system.properties.Libs...) 129 } 130 131 func (system *SystemModules) AndroidMk() android.AndroidMkData { 132 return android.AndroidMkData{ 133 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { 134 if system.outputFile != nil { 135 makevar := "SOONG_SYSTEM_MODULES_" + name 136 fmt.Fprintln(w) 137 fmt.Fprintln(w, makevar, ":=", system.outputFile.String()) 138 fmt.Fprintln(w, ".KATI_READONLY", ":=", makevar) 139 fmt.Fprintln(w, name+":", "$("+makevar+")") 140 fmt.Fprintln(w) 141 makevar = "SOONG_SYSTEM_MODULES_LIBS_" + name 142 fmt.Fprintln(w, makevar, ":=", strings.Join(system.properties.Libs, " ")) 143 fmt.Fprintln(w, ".KATI_READONLY :=", makevar) 144 } 145 }, 146 } 147 } 148