Merge "Let LoadHooks call CreateModule"
diff --git a/README.md b/README.md
index bc019ae..3d24e75 100644
--- a/README.md
+++ b/README.md
@@ -61,6 +61,7 @@
first assignment, and properties statically by the module type. The supported
types are:
* Bool (`true` or `false`)
+* Integers (`int`)
* Strings (`"string"`)
* Lists of strings (`["string1", "string2"]`)
* Maps (`{key1: "value1", key2: ["value2"]}`)
@@ -71,8 +72,9 @@
### Operators
Strings, lists of strings, and maps can be appended using the `+` operator.
-Appending a map produces the union of keys in both maps, appending the values
-of any keys that are present in both maps.
+Integers can be summed up using the `+` operator. Appending a map produces the
+union of keys in both maps, appending the values of any keys that are present
+in both maps.
### Defaults modules
diff --git a/cc/config/global.go b/cc/config/global.go
index 7362f2e..de4fa11 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -36,6 +36,7 @@
// Make paths in deps files relative
"-no-canonical-prefixes",
+ "-fno-canonical-system-headers",
"-DNDEBUG",
"-UDEBUG",
@@ -54,7 +55,6 @@
deviceGlobalCflags = []string{
"-fdiagnostics-color",
- "-fno-canonical-system-headers",
"-ffunction-sections",
"-funwind-tables",
"-fstack-protector-strong",
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 9e1f02f..5d7f617 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -34,9 +34,8 @@
cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
"-fsanitize-blacklist=external/compiler-rt/lib/cfi/cfi_blacklist.txt"}
- // FIXME: revert the __cfi_check flag when clang is updated to r280031.
cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi",
- "-Wl,-plugin-opt,O1 -Wl,-export-dynamic-symbol=__cfi_check"}
+ "-Wl,-plugin-opt,O1"}
cfiArflags = []string{"--plugin ${config.ClangBin}/../lib64/LLVMgold.so"}
cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map"
cfiExportsMap android.Path
@@ -364,9 +363,6 @@
// __cfi_check needs to be built as Thumb (see the code in linker_cfi.cpp). LLVM is not set up
// to do this on a function basis, so force Thumb on the entire module.
flags.RequiredInstructionSet = "thumb"
- // Workaround for b/33678192. CFI jumptables need Thumb2 codegen. Revert when
- // Clang is updated past r290384.
- flags.LdFlags = append(flags.LdFlags, "-march=armv7-a")
}
sanitizers = append(sanitizers, "cfi")
diff --git a/cmd/multiproduct_kati/Android.bp b/cmd/multiproduct_kati/Android.bp
index b264c35..04a5802 100644
--- a/cmd/multiproduct_kati/Android.bp
+++ b/cmd/multiproduct_kati/Android.bp
@@ -18,6 +18,7 @@
"soong-ui-build",
"soong-ui-logger",
"soong-ui-tracer",
+ "soong-zip",
],
srcs: [
"main.go",
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index 1c853d6..e4a05fc 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -30,6 +30,7 @@
"android/soong/ui/build"
"android/soong/ui/logger"
"android/soong/ui/tracer"
+ "android/soong/zip"
)
// We default to number of cpus / 4, which seems to be the sweet spot for my
@@ -45,7 +46,7 @@
var numJobs = flag.Int("j", detectNumJobs(), "number of parallel kati jobs")
-var keep = flag.Bool("keep", false, "keep successful output files")
+var keepArtifacts = flag.Bool("keep", false, "keep archives of artifacts")
var outDir = flag.String("out", "", "path to store output directories (defaults to tmpdir under $OUT when empty)")
var alternateResultDir = flag.Bool("dist", false, "write select results to $DIST_DIR (or <out>/dist when empty)")
@@ -200,24 +201,19 @@
if err := os.MkdirAll(*outDir, 0777); err != nil {
log.Fatalf("Failed to create tempdir: %v", err)
}
-
- if !*keep {
- defer func() {
- if status.Finished() == 0 {
- os.RemoveAll(*outDir)
- }
- }()
- }
}
config.Environment().Set("OUT_DIR", *outDir)
log.Println("Output directory:", *outDir)
+ logsDir := filepath.Join(config.OutDir(), "logs")
+ os.MkdirAll(logsDir, 0777)
+
build.SetupOutDir(buildCtx, config)
if *alternateResultDir {
- logsDir := filepath.Join(config.DistDir(), "logs")
- os.MkdirAll(logsDir, 0777)
- log.SetOutput(filepath.Join(logsDir, "soong.log"))
- trace.SetOutput(filepath.Join(logsDir, "build.trace"))
+ distLogsDir := filepath.Join(config.DistDir(), "logs")
+ os.MkdirAll(distLogsDir, 0777)
+ log.SetOutput(filepath.Join(distLogsDir, "soong.log"))
+ trace.SetOutput(filepath.Join(distLogsDir, "build.trace"))
} else {
log.SetOutput(filepath.Join(config.OutDir(), "soong.log"))
trace.SetOutput(filepath.Join(config.OutDir(), "build.trace"))
@@ -269,17 +265,14 @@
})
productOutDir := filepath.Join(config.OutDir(), product)
- productLogDir := productOutDir
- if *alternateResultDir {
- productLogDir = filepath.Join(config.DistDir(), product)
- if err := os.MkdirAll(productLogDir, 0777); err != nil {
- log.Fatalf("Error creating log directory: %v", err)
- }
- }
+ productLogDir := filepath.Join(logsDir, product)
if err := os.MkdirAll(productOutDir, 0777); err != nil {
log.Fatalf("Error creating out directory: %v", err)
}
+ if err := os.MkdirAll(productLogDir, 0777); err != nil {
+ log.Fatalf("Error creating log directory: %v", err)
+ }
stdLog = filepath.Join(productLogDir, "std.log")
f, err := os.Create(stdLog)
@@ -324,6 +317,26 @@
status.Fail(product.config.TargetProduct(), err, product.logFile)
})
+ defer func() {
+ if *keepArtifacts {
+ args := zip.ZipArgs{
+ FileArgs: []zip.FileArg{
+ {
+ GlobDir: product.config.OutDir(),
+ SourcePrefixToStrip: product.config.OutDir(),
+ },
+ },
+ OutputFilePath: filepath.Join(config.OutDir(), product.config.TargetProduct()+".zip"),
+ NumParallelJobs: runtime.NumCPU(),
+ CompressionLevel: 5,
+ }
+ if err := zip.Run(args); err != nil {
+ log.Fatalf("Error zipping artifacts: %v", err)
+ }
+ }
+ os.RemoveAll(product.config.OutDir())
+ }()
+
buildWhat := 0
if !*onlyConfig {
buildWhat |= build.BuildSoong
@@ -332,9 +345,6 @@
}
}
build.Build(product.ctx, product.config, buildWhat)
- if !*keep {
- os.RemoveAll(product.config.OutDir())
- }
status.Finish(product.config.TargetProduct())
}()
}
@@ -342,6 +352,20 @@
}
wg2.Wait()
+ if *alternateResultDir {
+ args := zip.ZipArgs{
+ FileArgs: []zip.FileArg{
+ {GlobDir: logsDir, SourcePrefixToStrip: logsDir},
+ },
+ OutputFilePath: filepath.Join(config.DistDir(), "logs.zip"),
+ NumParallelJobs: runtime.NumCPU(),
+ CompressionLevel: 5,
+ }
+ if err := zip.Run(args); err != nil {
+ log.Fatalf("Error zipping logs: %v", err)
+ }
+ }
+
if count := status.Finished(); count > 0 {
log.Fatalln(count, "products failed")
}
diff --git a/cmd/pom2mk/pom2mk.go b/cmd/pom2mk/pom2mk.go
index e6144a5..ac29a2a 100644
--- a/cmd/pom2mk/pom2mk.go
+++ b/cmd/pom2mk/pom2mk.go
@@ -18,7 +18,6 @@
"encoding/xml"
"flag"
"fmt"
- "io"
"io/ioutil"
"os"
"path/filepath"
@@ -84,6 +83,8 @@
var extraDeps = make(ExtraDeps)
+var useVersion string
+
type Dependency struct {
XMLName xml.Name `xml:"dependency"`
@@ -98,6 +99,7 @@
type Pom struct {
XMLName xml.Name `xml:"http://maven.apache.org/POM/4.0.0 project"`
+ PomFile string `xml:"-"`
ArtifactFile string `xml:"-"`
GroupId string `xml:"groupId"`
@@ -105,7 +107,7 @@
Version string `xml:"version"`
Packaging string `xml:"packaging"`
- Dependencies []Dependency `xml:"dependencies>dependency"`
+ Dependencies []*Dependency `xml:"dependencies>dependency"`
}
func (p Pom) MkName() string {
@@ -125,6 +127,17 @@
return ret
}
+func (p *Pom) FixDepTypes(modules map[string]*Pom) {
+ for _, d := range p.Dependencies {
+ if d.Type != "" {
+ continue
+ }
+ if depPom, ok := modules[d.ArtifactId]; ok {
+ d.Type = depPom.Packaging
+ }
+ }
+}
+
var mkTemplate = template.Must(template.New("mk").Parse(`
include $(CLEAR_VARS)
LOCAL_MODULE := {{.MkName}}
@@ -140,25 +153,30 @@
include $(BUILD_PREBUILT)
`))
-func convert(filename string, out io.Writer) error {
+func parse(filename string) (*Pom, error) {
data, err := ioutil.ReadFile(filename)
if err != nil {
- return err
+ return nil, err
}
var pom Pom
err = xml.Unmarshal(data, &pom)
if err != nil {
- return err
+ return nil, err
+ }
+
+ if useVersion != "" && pom.Version != useVersion {
+ return nil, nil
}
if pom.Packaging == "" {
pom.Packaging = "jar"
}
+ pom.PomFile = filename
pom.ArtifactFile = strings.TrimSuffix(filename, ".pom") + "." + pom.Packaging
- return mkTemplate.Execute(out, pom)
+ return &pom, nil
}
func main() {
@@ -178,6 +196,9 @@
Some Android.mk modules have transitive dependencies that must be specified when they are
depended upon (like android-support-v7-mediarouter requires android-support-v7-appcompat).
This may be specified multiple times to declare these dependencies.
+ -use-version <version>
+ If the maven directory contains multiple versions of artifacts and their pom files,
+ -use-version can be used to only write makefiles for a specific version of those artifacts.
<dir>
The directory to search for *.pom files under.
@@ -187,6 +208,7 @@
flag.Var(&extraDeps, "extra-deps", "Extra dependencies needed when depending on a module")
flag.Var(&rewriteNames, "rewrite", "Regex(es) to rewrite artifact names")
+ flag.StringVar(&useVersion, "use-version", "", "Only read artifacts of a specific version")
flag.Parse()
if flag.NArg() != 1 {
@@ -240,14 +262,39 @@
sort.Strings(filenames)
+ poms := []*Pom{}
+ modules := make(map[string]*Pom)
+ for _, filename := range filenames {
+ pom, err := parse(filename)
+ if err != nil {
+ fmt.Fprintln(os.Stderr, "Error converting", filename, err)
+ os.Exit(1)
+ }
+
+ if pom != nil {
+ poms = append(poms, pom)
+
+ if old, ok := modules[pom.ArtifactId]; ok {
+ fmt.Fprintln(os.Stderr, "Module", pom.ArtifactId, "defined twice:", old.PomFile, pom.PomFile)
+ os.Exit(1)
+ }
+
+ modules[pom.ArtifactId] = pom
+ }
+ }
+
+ for _, pom := range poms {
+ pom.FixDepTypes(modules)
+ }
+
fmt.Println("# Automatically generated with:")
fmt.Println("# pom2mk", strings.Join(proptools.ShellEscape(os.Args[1:]), " "))
fmt.Println("LOCAL_PATH := $(call my-dir)")
- for _, filename := range filenames {
- err := convert(filename, os.Stdout)
+ for _, pom := range poms {
+ err := mkTemplate.Execute(os.Stdout, pom)
if err != nil {
- fmt.Fprintln(os.Stderr, "Error converting", filename, err)
+ fmt.Fprintln(os.Stderr, "Error writing", pom.PomFile, pom.MkName(), err)
os.Exit(1)
}
}
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index e3e68c9..4b008eb 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -15,6 +15,7 @@
package main
import (
+ "flag"
"fmt"
"io/ioutil"
"os"
@@ -24,7 +25,50 @@
"strings"
)
+var (
+ sandboxesRoot string
+ rawCommand string
+ outputRoot string
+ keepOutDir bool
+ depfileOut string
+)
+
+func init() {
+ flag.StringVar(&sandboxesRoot, "sandbox-path", "",
+ "root of temp directory to put the sandbox into")
+ flag.StringVar(&rawCommand, "c", "",
+ "command to run")
+ flag.StringVar(&outputRoot, "output-root", "",
+ "root of directory to copy outputs into")
+ flag.BoolVar(&keepOutDir, "keep-out-dir", false,
+ "whether to keep the sandbox directory when done")
+
+ flag.StringVar(&depfileOut, "depfile-out", "",
+ "file path of the depfile to generate. This value will replace '__SBOX_DEPFILE__' in the command and will be treated as an output but won't be added to __SBOX_OUT_FILES__")
+}
+
+func usageViolation(violation string) {
+ if violation != "" {
+ fmt.Fprintf(os.Stderr, "Usage error: %s.\n\n", violation)
+ }
+
+ fmt.Fprintf(os.Stderr,
+ "Usage: sbox -c <commandToRun> --sandbox-path <sandboxPath> --output-root <outputRoot> [--depfile-out depFile] <outputFile> [<outputFile>...]\n"+
+ "\n"+
+ "Runs <commandToRun> and moves each <outputFile> out of <sandboxPath>\n"+
+ "and into <outputRoot>\n")
+
+ flag.PrintDefaults()
+
+ os.Exit(1)
+}
+
func main() {
+ flag.Usage = func() {
+ usageViolation("")
+ }
+ flag.Parse()
+
error := run()
if error != nil {
fmt.Fprintln(os.Stderr, error)
@@ -32,55 +76,9 @@
}
}
-var usage = "Usage: sbox -c <commandToRun> --sandbox-path <sandboxPath> --output-root <outputRoot> [--depfile-out depFile] <outputFile> [<outputFile>...]\n" +
- "\n" +
- "Runs <commandToRun> and moves each <outputFile> out of <sandboxPath>\n" +
- "If any file in <outputFiles> is specified by absolute path, then <outputRoot> must be specified as well,\n" +
- "to enable sbox to compute the relative path within the sandbox of the specified output files"
-
-func usageError(violation string) error {
- return fmt.Errorf("Usage error: %s.\n\n%s", violation, usage)
-}
-
func run() error {
- // the contents of the __SBOX_OUT_FILES__ variable
- var outputsVarEntries []string
- // all outputs
- var allOutputs []string
-
- args := os.Args[1:]
-
- var rawCommand string
- var sandboxesRoot string
- removeTempDir := true
- var outputRoot string
- var depfile string
-
- for i := 0; i < len(args); i++ {
- arg := args[i]
- if arg == "--sandbox-path" {
- sandboxesRoot = args[i+1]
- i++
- } else if arg == "-c" {
- rawCommand = args[i+1]
- i++
- } else if arg == "--output-root" {
- outputRoot = args[i+1]
- i++
- } else if arg == "--keep-out-dir" {
- removeTempDir = false
- } else if arg == "--depfile-out" {
- depfile = args[i+1]
- i++
- } else {
- outputsVarEntries = append(outputsVarEntries, arg)
- }
- }
if rawCommand == "" {
- return usageError("-c <commandToRun> is required and must be non-empty")
- }
- if len(outputsVarEntries) == 0 {
- return usageError("at least one output file must be given")
+ usageViolation("-c <commandToRun> is required and must be non-empty")
}
if sandboxesRoot == "" {
// In practice, the value of sandboxesRoot will mostly likely be at a fixed location relative to OUT_DIR,
@@ -88,12 +86,21 @@
// the value of sandboxesRoot will most likely be at a fixed location relative to the sbox executable
// However, Soong also needs to be able to separately remove the sandbox directory on startup (if it has anything left in it)
// and by passing it as a parameter we don't need to duplicate its value
- return usageError("--sandbox-path <sandboxPath> is required and must be non-empty")
+ usageViolation("--sandbox-path <sandboxPath> is required and must be non-empty")
}
if len(outputRoot) == 0 {
- return usageError("--output-root <outputRoot> is required and must be non-empty")
+ usageViolation("--output-root <outputRoot> is required and must be non-empty")
}
+ // the contents of the __SBOX_OUT_FILES__ variable
+ outputsVarEntries := flag.Args()
+ if len(outputsVarEntries) == 0 {
+ usageViolation("at least one output file must be given")
+ }
+
+ // all outputs
+ var allOutputs []string
+
os.MkdirAll(sandboxesRoot, 0777)
tempDir, err := ioutil.TempDir(sandboxesRoot, "sbox")
@@ -110,8 +117,8 @@
allOutputs = append([]string(nil), outputsVarEntries...)
- if depfile != "" {
- sandboxedDepfile, err := filepath.Rel(outputRoot, depfile)
+ if depfileOut != "" {
+ sandboxedDepfile, err := filepath.Rel(outputRoot, depfileOut)
if err != nil {
return err
}
@@ -132,7 +139,7 @@
// then at the beginning of the next build, Soong will retry the cleanup
defer func() {
// in some cases we decline to remove the temp dir, to facilitate debugging
- if removeTempDir {
+ if !keepOutDir {
os.RemoveAll(tempDir)
}
}()
@@ -190,7 +197,7 @@
if len(outputErrors) > 0 {
// Keep the temporary output directory around in case a user wants to inspect it for debugging purposes.
// Soong will delete it later anyway.
- removeTempDir = false
+ keepOutDir = true
return fmt.Errorf("mismatch between declared and actual outputs in sbox command (%s):\n%v", commandDescription, outputErrors)
}
// the created files match the declared files; now move them
diff --git a/java/builder.go b/java/builder.go
index 8b6eb9f..45e59a4 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -19,6 +19,8 @@
// functions.
import (
+ "path/filepath"
+ "strconv"
"strings"
"github.com/google/blueprint"
@@ -211,12 +213,16 @@
})
}
-func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
- srcFiles, srcJars android.Paths,
- flags javaBuilderFlags, deps android.Paths) {
+func TransformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath, shardIdx int,
+ srcFiles, srcJars android.Paths, flags javaBuilderFlags, deps android.Paths) {
- transformJavaToClasses(ctx, outputFile, srcFiles, srcJars, flags, deps,
- "javac", "javac", javac)
+ // Compile java sources into .class files
+ desc := "javac"
+ if shardIdx >= 0 {
+ desc += strconv.Itoa(shardIdx)
+ }
+
+ transformJavaToClasses(ctx, outputFile, shardIdx, srcFiles, srcJars, flags, deps, "javac", desc, javac)
}
func RunErrorProne(ctx android.ModuleContext, outputFile android.WritablePath,
@@ -226,7 +232,7 @@
ctx.ModuleErrorf("cannot build with Error Prone, missing external/error_prone?")
}
- transformJavaToClasses(ctx, outputFile, srcFiles, srcJars, flags, nil,
+ transformJavaToClasses(ctx, outputFile, -1, srcFiles, srcJars, flags, nil,
"errorprone", "errorprone", errorprone)
}
@@ -275,7 +281,7 @@
// suffix will be appended to various intermediate files and directories to avoid collisions when
// this function is called twice in the same module directory.
func transformJavaToClasses(ctx android.ModuleContext, outputFile android.WritablePath,
- srcFiles, srcJars android.Paths,
+ shardIdx int, srcFiles, srcJars android.Paths,
flags javaBuilderFlags, deps android.Paths,
intermediatesDir, desc string, rule blueprint.Rule) {
@@ -298,6 +304,15 @@
deps = append(deps, flags.classpath...)
+ srcJarDir := "srcjars"
+ outDir := "classes"
+ annoDir := "anno"
+ if shardIdx >= 0 {
+ shardDir := "shard" + strconv.Itoa(shardIdx)
+ srcJarDir = filepath.Join(shardDir, srcJarDir)
+ outDir = filepath.Join(shardDir, outDir)
+ annoDir = filepath.Join(shardDir, annoDir)
+ }
ctx.Build(pctx, android.BuildParams{
Rule: rule,
Description: desc,
@@ -309,9 +324,9 @@
"bootClasspath": bootClasspath,
"classpath": flags.classpath.FormJavaClassPath("-classpath"),
"srcJars": strings.Join(srcJars.Strings(), " "),
- "srcJarDir": android.PathForModuleOut(ctx, intermediatesDir, "srcjars").String(),
- "outDir": android.PathForModuleOut(ctx, intermediatesDir, "classes").String(),
- "annoDir": android.PathForModuleOut(ctx, intermediatesDir, "anno").String(),
+ "srcJarDir": android.PathForModuleOut(ctx, intermediatesDir, srcJarDir).String(),
+ "outDir": android.PathForModuleOut(ctx, intermediatesDir, outDir).String(),
+ "annoDir": android.PathForModuleOut(ctx, intermediatesDir, annoDir).String(),
"javaVersion": flags.javaVersion,
},
})
diff --git a/java/java.go b/java/java.go
index f9a4c04..bb6e556 100644
--- a/java/java.go
+++ b/java/java.go
@@ -117,6 +117,9 @@
// List of classes to pass to javac to use as annotation processors
Annotation_processor_classes []string
+ // The number of Java source entries each Javac instance can process
+ Javac_shard_size *int64
+
Openjdk9 struct {
// List of source files that should only be used when passing -source 1.9
Srcs []string
@@ -355,6 +358,18 @@
return false
}
+func shardPaths(paths android.Paths, shardSize int) []android.Paths {
+ ret := make([]android.Paths, 0, (len(paths)+shardSize-1)/shardSize)
+ for len(paths) > shardSize {
+ ret = append(ret, paths[0:shardSize])
+ paths = paths[shardSize:]
+ }
+ if len(paths) > 0 {
+ ret = append(ret, paths)
+ }
+ return ret
+}
+
func (j *Module) hasSrcExt(ext string) bool {
return hasSrcExt(j.properties.Srcs, ext)
}
@@ -571,7 +586,17 @@
}
}
+ enable_sharding := false
if ctx.Device() && !ctx.AConfig().IsEnvFalse("TURBINE_ENABLED") {
+ if j.properties.Javac_shard_size != nil && *(j.properties.Javac_shard_size) > 0 {
+ enable_sharding = true
+ if len(j.properties.Annotation_processors) != 0 ||
+ len(j.properties.Annotation_processor_classes) != 0 {
+ ctx.PropertyErrorf("javac_shard_size",
+ "%q cannot be set when annotation processors are enabled.",
+ j.properties.Javac_shard_size)
+ }
+ }
// If sdk jar is java module, then directly return classesJar as header.jar
if j.Name() != "android_stubs_current" && j.Name() != "android_system_stubs_current" &&
j.Name() != "android_test_stubs_current" {
@@ -590,18 +615,35 @@
// TODO(ccross): Once we always compile with javac9 we may be able to conditionally
// enable error-prone without affecting the output class files.
errorprone := android.PathForModuleOut(ctx, "errorprone", jarName)
- RunErrorProne(ctx, errorprone, javaSrcFiles, srcJars, flags)
+ RunErrorProne(ctx, errorprone, uniqueSrcFiles, srcJars, flags)
extraJarDeps = append(extraJarDeps, errorprone)
}
- // Compile java sources into .class files
- classes := android.PathForModuleOut(ctx, "javac", jarName)
- TransformJavaToClasses(ctx, classes, javaSrcFiles, srcJars, flags, extraJarDeps)
+ if enable_sharding {
+ flags.classpath.AddPaths([]android.Path{j.headerJarFile})
+ shardSize := int(*(j.properties.Javac_shard_size))
+ var shardSrcs []android.Paths
+ if len(uniqueSrcFiles) > 0 {
+ shardSrcs = shardPaths(uniqueSrcFiles, shardSize)
+ for idx, shardSrc := range shardSrcs {
+ classes := android.PathForModuleOut(ctx, "javac", jarName+strconv.Itoa(idx))
+ TransformJavaToClasses(ctx, classes, idx, shardSrc, nil, flags, extraJarDeps)
+ jars = append(jars, classes)
+ }
+ }
+ if len(srcJars) > 0 {
+ classes := android.PathForModuleOut(ctx, "javac", jarName+strconv.Itoa(len(shardSrcs)))
+ TransformJavaToClasses(ctx, classes, len(shardSrcs), nil, srcJars, flags, extraJarDeps)
+ jars = append(jars, classes)
+ }
+ } else {
+ classes := android.PathForModuleOut(ctx, "javac", jarName)
+ TransformJavaToClasses(ctx, classes, -1, uniqueSrcFiles, srcJars, flags, extraJarDeps)
+ jars = append(jars, classes)
+ }
if ctx.Failed() {
return
}
-
- jars = append(jars, classes)
}
dirArgs, dirDeps := ResourceDirsToJarArgs(ctx, j.properties.Java_resource_dirs, j.properties.Exclude_java_resource_dirs)
diff --git a/java/java_test.go b/java/java_test.go
index b819447..82eff1e 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -22,6 +22,7 @@
"os"
"path/filepath"
"reflect"
+ "strconv"
"strings"
"testing"
)
@@ -669,6 +670,71 @@
}
}
+func TestTurbine(t *testing.T) {
+ ctx := testJava(t, `
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ static_libs: ["foo"],
+ }
+
+ java_library {
+ name: "baz",
+ srcs: ["c.java"],
+ libs: ["bar"],
+ sdk_version: "14",
+ }
+ `)
+
+ fooTurbine := ctx.ModuleForTests("foo", "android_common").Rule("turbine")
+ barTurbine := ctx.ModuleForTests("bar", "android_common").Rule("turbine")
+ barJavac := ctx.ModuleForTests("bar", "android_common").Rule("javac")
+ barTurbineCombined := ctx.ModuleForTests("bar", "android_common").Description("for turbine")
+ bazJavac := ctx.ModuleForTests("baz", "android_common").Rule("javac")
+
+ if len(fooTurbine.Inputs) != 1 || fooTurbine.Inputs[0].String() != "a.java" {
+ t.Errorf(`foo inputs %v != ["a.java"]`, fooTurbine.Inputs)
+ }
+
+ fooHeaderJar := filepath.Join(buildDir, ".intermediates", "foo", "android_common", "turbine-combined", "foo.jar")
+ if !strings.Contains(barTurbine.Args["classpath"], fooHeaderJar) {
+ t.Errorf("bar turbine classpath %v does not contain %q", barTurbine.Args["classpath"], fooHeaderJar)
+ }
+ if !strings.Contains(barJavac.Args["classpath"], fooHeaderJar) {
+ t.Errorf("bar javac classpath %v does not contain %q", barJavac.Args["classpath"], fooHeaderJar)
+ }
+ if len(barTurbineCombined.Inputs) != 2 || barTurbineCombined.Inputs[1].String() != fooHeaderJar {
+ t.Errorf("bar turbine combineJar inputs %v does not contain %q", barTurbineCombined.Inputs, fooHeaderJar)
+ }
+ if !strings.Contains(bazJavac.Args["classpath"], "prebuilts/sdk/14/android.jar") {
+ t.Errorf("baz javac classpath %v does not contain %q", bazJavac.Args["classpath"],
+ "prebuilts/sdk/14/android.jar")
+ }
+}
+
+func TestSharding(t *testing.T) {
+ ctx := testJava(t, `
+ java_library {
+ name: "bar",
+ srcs: ["a.java","b.java","c.java"],
+ javac_shard_size: 1
+ }
+ `)
+
+ barHeaderJar := filepath.Join(buildDir, ".intermediates", "bar", "android_common", "turbine-combined", "bar.jar")
+ for i := 0; i < 3; i++ {
+ barJavac := ctx.ModuleForTests("bar", "android_common").Description("javac" + strconv.Itoa(i))
+ if !strings.Contains(barJavac.Args["classpath"], barHeaderJar) {
+ t.Errorf("bar javac classpath %v does not contain %q", barJavac.Args["classpath"], barHeaderJar)
+ }
+ }
+}
+
func fail(t *testing.T, errs []error) {
if len(errs) > 0 {
for _, err := range errs {
diff --git a/scripts/copygcclib.sh b/scripts/copygcclib.sh
index 93c52cc..4bd6f9b 100755
--- a/scripts/copygcclib.sh
+++ b/scripts/copygcclib.sh
@@ -2,6 +2,6 @@
OUT=$1
shift
-LIBPATH=$($@)
+LIBPATH=$($@ | sed -e "s|^$PWD/||")
cp -f $LIBPATH $OUT
echo "$OUT: $LIBPATH" > ${OUT}.d