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 14package java 15 16import ( 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 30func init() { 31 android.RegisterModuleType("java_system_modules", SystemModulesFactory) 32 33 pctx.SourcePathVariable("moduleInfoJavaPath", "build/soong/scripts/jars-to-module-info-java.sh") 34} 35 36var ( 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 60func 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 86func SystemModulesFactory() android.Module { 87 module := &SystemModules{} 88 module.AddProperties(&module.properties) 89 android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon) 90 return module 91} 92 93type SystemModules struct { 94 android.ModuleBase 95 96 properties SystemModulesProperties 97 98 outputFile android.Path 99} 100 101type 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 112func (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 system.outputFile = TransformJarsToSystemModules(ctx, "java.base", jars) 123} 124 125func (system *SystemModules) DepsMutator(ctx android.BottomUpMutatorContext) { 126 ctx.AddVariationDependencies(nil, libTag, system.properties.Libs...) 127} 128 129func (system *SystemModules) AndroidMk() android.AndroidMkData { 130 return android.AndroidMkData{ 131 Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) { 132 makevar := "SOONG_SYSTEM_MODULES_" + name 133 fmt.Fprintln(w) 134 fmt.Fprintln(w, makevar, ":=", system.outputFile.String()) 135 fmt.Fprintln(w, ".KATI_READONLY", ":=", makevar) 136 fmt.Fprintln(w, name+":", "$("+makevar+")") 137 fmt.Fprintln(w, ".PHONY:", name) 138 fmt.Fprintln(w) 139 makevar = "SOONG_SYSTEM_MODULES_LIBS_" + name 140 fmt.Fprintln(w, makevar, ":=", strings.Join(system.properties.Libs, " ")) 141 fmt.Fprintln(w, ".KATI_READONLY :=", makevar) 142 }, 143 } 144} 145