Home | History | Annotate | Download | only in java
      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