github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/java/builder.go (about)

     1  // Copyright 2015 Google Inc. All rights reserved.
     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  
    15  package java
    16  
    17  // This file generates the final rules for compiling all Java.  All properties related to
    18  // compiling should have been translated into javaBuilderFlags or another argument to the Transform*
    19  // functions.
    20  
    21  import (
    22  	"path/filepath"
    23  	"strconv"
    24  	"strings"
    25  
    26  	"github.com/google/blueprint"
    27  
    28  	"android/soong/android"
    29  	"android/soong/java/config"
    30  )
    31  
    32  var (
    33  	pctx = android.NewPackageContext("android/soong/java")
    34  
    35  	// Compiling java is not conducive to proper dependency tracking.  The path-matches-class-name
    36  	// requirement leads to unpredictable generated source file names, and a single .java file
    37  	// will get compiled into multiple .class files if it contains inner classes.  To work around
    38  	// this, all java rules write into separate directories and then are combined into a .jar file
    39  	// (if the rule produces .class files) or a .srcjar file (if the rule produces .java files).
    40  	// .srcjar files are unzipped into a temporary directory when compiled with javac.
    41  	javac = pctx.AndroidGomaStaticRule("javac",
    42  		blueprint.RuleParams{
    43  			Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
    44  				`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
    45  				`${config.SoongJavacWrapper} ${config.JavacWrapper}${config.JavacCmd} ${config.JavacHeapFlags} ${config.CommonJdkFlags} ` +
    46  				`$javacFlags $bootClasspath $classpath ` +
    47  				`-source $javaVersion -target $javaVersion ` +
    48  				`-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list && ` +
    49  				`${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
    50  			CommandDeps: []string{
    51  				"${config.JavacCmd}",
    52  				"${config.SoongZipCmd}",
    53  				"${config.ZipSyncCmd}",
    54  			},
    55  			CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
    56  			Rspfile:          "$out.rsp",
    57  			RspfileContent:   "$in",
    58  		},
    59  		"javacFlags", "bootClasspath", "classpath", "srcJars", "srcJarDir",
    60  		"outDir", "annoDir", "javaVersion")
    61  
    62  	kotlinc = pctx.AndroidGomaStaticRule("kotlinc",
    63  		blueprint.RuleParams{
    64  			Command: `rm -rf "$outDir" "$srcJarDir" && mkdir -p "$outDir" "$srcJarDir" && ` +
    65  				`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
    66  				`${config.GenKotlinBuildFileCmd} $classpath $outDir $out.rsp $srcJarDir/list > $outDir/kotlinc-build.xml &&` +
    67  				`${config.KotlincCmd} $kotlincFlags ` +
    68  				`-jvm-target $kotlinJvmTarget -Xbuild-file=$outDir/kotlinc-build.xml && ` +
    69  				`${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
    70  			CommandDeps: []string{
    71  				"${config.KotlincCmd}",
    72  				"${config.KotlinCompilerJar}",
    73  				"${config.GenKotlinBuildFileCmd}",
    74  				"${config.SoongZipCmd}",
    75  				"${config.ZipSyncCmd}",
    76  			},
    77  			Rspfile:        "$out.rsp",
    78  			RspfileContent: `$in`,
    79  		},
    80  		"kotlincFlags", "classpath", "srcJars", "srcJarDir", "outDir", "kotlinJvmTarget")
    81  
    82  	errorprone = pctx.AndroidStaticRule("errorprone",
    83  		blueprint.RuleParams{
    84  			Command: `rm -rf "$outDir" "$annoDir" "$srcJarDir" && mkdir -p "$outDir" "$annoDir" "$srcJarDir" && ` +
    85  				`${config.ZipSyncCmd} -d $srcJarDir -l $srcJarDir/list -f "*.java" $srcJars && ` +
    86  				`${config.SoongJavacWrapper} ${config.ErrorProneCmd} ` +
    87  				`$javacFlags $bootClasspath $classpath ` +
    88  				`-source $javaVersion -target $javaVersion ` +
    89  				`-d $outDir -s $annoDir @$out.rsp @$srcJarDir/list && ` +
    90  				`${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
    91  			CommandDeps: []string{
    92  				"${config.JavaCmd}",
    93  				"${config.ErrorProneJavacJar}",
    94  				"${config.ErrorProneJar}",
    95  				"${config.SoongZipCmd}",
    96  				"${config.ZipSyncCmd}",
    97  			},
    98  			CommandOrderOnly: []string{"${config.SoongJavacWrapper}"},
    99  			Rspfile:          "$out.rsp",
   100  			RspfileContent:   "$in",
   101  		},
   102  		"javacFlags", "bootClasspath", "classpath", "srcJars", "srcJarDir",
   103  		"outDir", "annoDir", "javaVersion")
   104  
   105  	turbine = pctx.AndroidStaticRule("turbine",
   106  		blueprint.RuleParams{
   107  			Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
   108  				`${config.JavaCmd} -jar ${config.TurbineJar} --output $out.tmp ` +
   109  				`--temp_dir "$outDir" --sources @$out.rsp  --source_jars $srcJars ` +
   110  				`--javacopts ${config.CommonJdkFlags} ` +
   111  				`$javacFlags -source $javaVersion -target $javaVersion $bootClasspath $classpath && ` +
   112  				`${config.Ziptime} $out.tmp && ` +
   113  				`(if cmp -s $out.tmp $out ; then rm $out.tmp ; else mv $out.tmp $out ; fi )`,
   114  			CommandDeps: []string{
   115  				"${config.TurbineJar}",
   116  				"${config.JavaCmd}",
   117  				"${config.Ziptime}",
   118  			},
   119  			Rspfile:        "$out.rsp",
   120  			RspfileContent: "$in",
   121  			Restat:         true,
   122  		},
   123  		"javacFlags", "bootClasspath", "classpath", "srcJars", "outDir", "javaVersion")
   124  
   125  	jar = pctx.AndroidStaticRule("jar",
   126  		blueprint.RuleParams{
   127  			Command:        `${config.SoongZipCmd} -jar -o $out @$out.rsp`,
   128  			CommandDeps:    []string{"${config.SoongZipCmd}"},
   129  			Rspfile:        "$out.rsp",
   130  			RspfileContent: "$jarArgs",
   131  		},
   132  		"jarArgs")
   133  
   134  	combineJar = pctx.AndroidStaticRule("combineJar",
   135  		blueprint.RuleParams{
   136  			Command:     `${config.MergeZipsCmd} --ignore-duplicates -j $jarArgs $out $in`,
   137  			CommandDeps: []string{"${config.MergeZipsCmd}"},
   138  		},
   139  		"jarArgs")
   140  
   141  	jarjar = pctx.AndroidStaticRule("jarjar",
   142  		blueprint.RuleParams{
   143  			Command:     "${config.JavaCmd} -jar ${config.JarjarCmd} process $rulesFile $in $out",
   144  			CommandDeps: []string{"${config.JavaCmd}", "${config.JarjarCmd}", "$rulesFile"},
   145  		},
   146  		"rulesFile")
   147  )
   148  
   149  func init() {
   150  	pctx.Import("android/soong/java/config")
   151  }
   152  
   153  type javaBuilderFlags struct {
   154  	javacFlags    string
   155  	bootClasspath classpath
   156  	classpath     classpath
   157  	systemModules classpath
   158  	aidlFlags     string
   159  	javaVersion   string
   160  
   161  	errorProneExtraJavacFlags string
   162  
   163  	kotlincFlags     string
   164  	kotlincClasspath classpath
   165  
   166  	protoFlags       []string
   167  	protoOutTypeFlag string // The flag itself: --java_out
   168  	protoOutParams   string // Parameters to that flag: --java_out=$protoOutParams:$outDir
   169  	protoRoot        bool
   170  }
   171  
   172  func TransformKotlinToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
   173  	srcFiles, srcJars android.Paths,
   174  	flags javaBuilderFlags) {
   175  
   176  	inputs := append(android.Paths(nil), srcFiles...)
   177  
   178  	var deps android.Paths
   179  	deps = append(deps, flags.kotlincClasspath...)
   180  	deps = append(deps, srcJars...)
   181  
   182  	ctx.Build(pctx, android.BuildParams{
   183  		Rule:        kotlinc,
   184  		Description: "kotlinc",
   185  		Output:      outputFile,
   186  		Inputs:      inputs,
   187  		Implicits:   deps,
   188  		Args: map[string]string{
   189  			"classpath":    flags.kotlincClasspath.FormJavaClassPath("-classpath"),
   190  			"kotlincFlags": flags.kotlincFlags,
   191  			"srcJars":      strings.Join(srcJars.Strings(), " "),
   192  			"outDir":       android.PathForModuleOut(ctx, "kotlinc", "classes").String(),
   193  			"srcJarDir":    android.PathForModuleOut(ctx, "kotlinc", "srcJars").String(),
   194  			// http://b/69160377 kotlinc only supports -jvm-target 1.6 and 1.8
   195  			"kotlinJvmTarget": "1.8",
   196  		},
   197  	})
   198  }
   199  
   200  func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath, shardIdx int,
   201  	srcFiles, srcJars android.Paths, flags javaBuilderFlags, deps android.Paths) {
   202  
   203  	// Compile java sources into .class files
   204  	desc := "javac"
   205  	if shardIdx >= 0 {
   206  		desc += strconv.Itoa(shardIdx)
   207  	}
   208  
   209  	transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, flags, deps, "javac", desc, javac)
   210  }
   211  
   212  func RunErrorProne(ctx android.ModuleContext, outputFile android.WritablePath,
   213  	srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
   214  
   215  	if config.ErrorProneJar == "" {
   216  		ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
   217  	}
   218  
   219  	if len(flags.errorProneExtraJavacFlags) > 0 {
   220  		if len(flags.javacFlags) > 0 {
   221  			flags.javacFlags = flags.errorProneExtraJavacFlags + " " + flags.javacFlags
   222  		} else {
   223  			flags.javacFlags = flags.errorProneExtraJavacFlags
   224  		}
   225  	}
   226  
   227  	transformJavaToClasses(ctx, outputFile, -1, srcFiles, srcJars, flags, nil,
   228  		"errorprone", "errorprone", errorprone)
   229  }
   230  
   231  func TransformJavaToHeaderClasses(ctx android.ModuleContext, outputFile android.WritablePath,
   232  	srcFiles, srcJars android.Paths, flags javaBuilderFlags) {
   233  
   234  	var deps android.Paths
   235  	deps = append(deps, srcJars...)
   236  	deps = append(deps, flags.bootClasspath...)
   237  	deps = append(deps, flags.classpath...)
   238  
   239  	var bootClasspath string
   240  	if len(flags.bootClasspath) == 0 && ctx.Device() {
   241  		// explicitly specify -bootclasspath "" if the bootclasspath is empty to
   242  		// ensure java does not fall back to the default bootclasspath.
   243  		bootClasspath = `--bootclasspath ""`
   244  	} else {
   245  		bootClasspath = flags.bootClasspath.FormJavaClassPath("--bootclasspath")
   246  	}
   247  
   248  	ctx.Build(pctx, android.BuildParams{
   249  		Rule:        turbine,
   250  		Description: "turbine",
   251  		Output:      outputFile,
   252  		Inputs:      srcFiles,
   253  		Implicits:   deps,
   254  		Args: map[string]string{
   255  			"javacFlags":    flags.javacFlags,
   256  			"bootClasspath": bootClasspath,
   257  			"srcJars":       strings.Join(srcJars.Strings(), " "),
   258  			"classpath":     flags.classpath.FormJavaClassPath("--classpath"),
   259  			"outDir":        android.PathForModuleOut(ctx, "turbine", "classes").String(),
   260  			"javaVersion":   flags.javaVersion,
   261  		},
   262  	})
   263  }
   264  
   265  // transformJavaToClasses takes source files and converts them to a jar containing .class files.
   266  // srcFiles is a list of paths to sources, srcJars is a list of paths to jar files that contain
   267  // sources.  flags contains various command line flags to be passed to the compiler.
   268  //
   269  // This method may be used for different compilers, including javac and Error Prone.  The rule
   270  // argument specifies which command line to use and desc sets the description of the rule that will
   271  // be printed at build time.  The stem argument provides the file name of the output jar, and
   272  // suffix will be appended to various intermediate files and directories to avoid collisions when
   273  // this function is called twice in the same module directory.
   274  func transformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
   275  	shardIdx int, srcFiles, srcJars android.Paths,
   276  	flags javaBuilderFlags, deps android.Paths,
   277  	intermediatesDir, desc string, rule blueprint.Rule) {
   278  
   279  	deps = append(deps, srcJars...)
   280  
   281  	var bootClasspath string
   282  	if flags.javaVersion == "1.9" {
   283  		deps = append(deps, flags.systemModules...)
   284  		bootClasspath = flags.systemModules.FormJavaSystemModulesPath("--system=", ctx.Device())
   285  	} else {
   286  		deps = append(deps, flags.bootClasspath...)
   287  		if len(flags.bootClasspath) == 0 && ctx.Device() {
   288  			// explicitly specify -bootclasspath "" if the bootclasspath is empty to
   289  			// ensure java does not fall back to the default bootclasspath.
   290  			bootClasspath = `-bootclasspath ""`
   291  		} else {
   292  			bootClasspath = flags.bootClasspath.FormJavaClassPath("-bootclasspath")
   293  		}
   294  	}
   295  
   296  	deps = append(deps, flags.classpath...)
   297  
   298  	srcJarDir := "srcjars"
   299  	outDir := "classes"
   300  	annoDir := "anno"
   301  	if shardIdx >= 0 {
   302  		shardDir := "shard" + strconv.Itoa(shardIdx)
   303  		srcJarDir = filepath.Join(shardDir, srcJarDir)
   304  		outDir = filepath.Join(shardDir, outDir)
   305  		annoDir = filepath.Join(shardDir, annoDir)
   306  	}
   307  	ctx.Build(pctx, android.BuildParams{
   308  		Rule:        rule,
   309  		Description: desc,
   310  		Output:      outputFile,
   311  		Inputs:      srcFiles,
   312  		Implicits:   deps,
   313  		Args: map[string]string{
   314  			"javacFlags":    flags.javacFlags,
   315  			"bootClasspath": bootClasspath,
   316  			"classpath":     flags.classpath.FormJavaClassPath("-classpath"),
   317  			"srcJars":       strings.Join(srcJars.Strings(), " "),
   318  			"srcJarDir":     android.PathForModuleOut(ctx, intermediatesDir, srcJarDir).String(),
   319  			"outDir":        android.PathForModuleOut(ctx, intermediatesDir, outDir).String(),
   320  			"annoDir":       android.PathForModuleOut(ctx, intermediatesDir, annoDir).String(),
   321  			"javaVersion":   flags.javaVersion,
   322  		},
   323  	})
   324  }
   325  
   326  func TransformResourcesToJar(ctx android.ModuleContext, outputFile android.WritablePath,
   327  	jarArgs []string, deps android.Paths) {
   328  
   329  	ctx.Build(pctx, android.BuildParams{
   330  		Rule:        jar,
   331  		Description: "jar",
   332  		Output:      outputFile,
   333  		Implicits:   deps,
   334  		Args: map[string]string{
   335  			"jarArgs": strings.Join(jarArgs, " "),
   336  		},
   337  	})
   338  }
   339  
   340  func TransformJarsToJar(ctx android.ModuleContext, outputFile android.WritablePath, desc string,
   341  	jars android.Paths, manifest android.OptionalPath, stripDirs bool, dirsToStrip []string) {
   342  
   343  	var deps android.Paths
   344  
   345  	var jarArgs []string
   346  	if manifest.Valid() {
   347  		jarArgs = append(jarArgs, "-m ", manifest.String())
   348  		deps = append(deps, manifest.Path())
   349  	}
   350  
   351  	if dirsToStrip != nil {
   352  		for _, dir := range dirsToStrip {
   353  			jarArgs = append(jarArgs, "-stripDir ", dir)
   354  		}
   355  	}
   356  
   357  	// Remove any module-info.class files that may have come from prebuilt jars, they cause problems
   358  	// for downstream tools like desugar.
   359  	jarArgs = append(jarArgs, "-stripFile module-info.class")
   360  
   361  	if stripDirs {
   362  		jarArgs = append(jarArgs, "-D")
   363  	}
   364  
   365  	ctx.Build(pctx, android.BuildParams{
   366  		Rule:        combineJar,
   367  		Description: desc,
   368  		Output:      outputFile,
   369  		Inputs:      jars,
   370  		Implicits:   deps,
   371  		Args: map[string]string{
   372  			"jarArgs": strings.Join(jarArgs, " "),
   373  		},
   374  	})
   375  }
   376  
   377  func TransformJarJar(ctx android.ModuleContext, outputFile android.WritablePath,
   378  	classesJar android.Path, rulesFile android.Path) {
   379  	ctx.Build(pctx, android.BuildParams{
   380  		Rule:        jarjar,
   381  		Description: "jarjar",
   382  		Output:      outputFile,
   383  		Input:       classesJar,
   384  		Implicit:    rulesFile,
   385  		Args: map[string]string{
   386  			"rulesFile": rulesFile.String(),
   387  		},
   388  	})
   389  }
   390  
   391  type classpath []android.Path
   392  
   393  func (x *classpath) FormJavaClassPath(optName string) string {
   394  	if len(*x) > 0 {
   395  		return optName + " " + strings.Join(x.Strings(), ":")
   396  	} else {
   397  		return ""
   398  	}
   399  }
   400  
   401  // Returns a --system argument in the form javac expects with -source 1.9.  If forceEmpty is true,
   402  // returns --system=none if the list is empty to ensure javac does not fall back to the default
   403  // system modules.
   404  func (x *classpath) FormJavaSystemModulesPath(optName string, forceEmpty bool) string {
   405  	if len(*x) > 1 {
   406  		panic("more than one system module")
   407  	} else if len(*x) == 1 {
   408  		return optName + strings.TrimSuffix((*x)[0].String(), "lib/modules")
   409  	} else if forceEmpty {
   410  		return optName + "none"
   411  	} else {
   412  		return ""
   413  	}
   414  }
   415  
   416  func (x *classpath) FormDesugarClasspath(optName string) []string {
   417  	if x == nil || *x == nil {
   418  		return nil
   419  	}
   420  	flags := make([]string, len(*x))
   421  	for i, v := range *x {
   422  		flags[i] = optName + " " + v.String()
   423  	}
   424  
   425  	return flags
   426  }
   427  
   428  // Convert a classpath to an android.Paths
   429  func (x *classpath) Paths() android.Paths {
   430  	return append(android.Paths(nil), (*x)...)
   431  }
   432  
   433  func (x *classpath) Strings() []string {
   434  	if x == nil {
   435  		return nil
   436  	}
   437  	ret := make([]string, len(*x))
   438  	for i, path := range *x {
   439  		ret[i] = path.String()
   440  	}
   441  	return ret
   442  }