Merge "Disable inlining and loop unrolling in LTO without PGO profile"
diff --git a/java/builder.go b/java/builder.go
index 72574f1..9e38065 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -61,19 +61,23 @@
 
 	kotlinc = pctx.AndroidGomaStaticRule("kotlinc",
 		blueprint.RuleParams{
-			// TODO(ccross): kotlinc doesn't support @ file for arguments, which will limit the
-			// maximum number of input files, especially on darwin.
-			Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
-				`${config.KotlincCmd} $classpath $kotlincFlags ` +
-				`-jvm-target $kotlinJvmTarget -d $outDir $in && ` +
+			Command: `rm -rf "$outDir" "$srcJarDir" && mkdir -p "$outDir" "$srcJarDir" && ` +
+				`${config.ExtractSrcJarsCmd} $srcJarDir $srcJarDir/list $srcJars && ` +
+				`${config.GenKotlinBuildFileCmd} $classpath $outDir $out.rsp $srcJarDir/list > $outDir/kotlinc-build.xml &&` +
+				`${config.KotlincCmd} $kotlincFlags ` +
+				`-jvm-target $kotlinJvmTarget -Xbuild-file=$outDir/kotlinc-build.xml && ` +
 				`${config.SoongZipCmd} -jar -o $out -C $outDir -D $outDir`,
 			CommandDeps: []string{
 				"${config.KotlincCmd}",
 				"${config.KotlinCompilerJar}",
+				"${config.GenKotlinBuildFileCmd}",
 				"${config.SoongZipCmd}",
+				"${config.ExtractSrcJarsCmd}",
 			},
+			Rspfile:        "$out.rsp",
+			RspfileContent: `$in`,
 		},
-		"kotlincFlags", "classpath", "outDir", "kotlinJvmTarget")
+		"kotlincFlags", "classpath", "srcJars", "srcJarDir", "outDir", "kotlinJvmTarget")
 
 	errorprone = pctx.AndroidStaticRule("errorprone",
 		blueprint.RuleParams{
@@ -171,13 +175,11 @@
 	srcFiles, srcJars android.Paths,
 	flags javaBuilderFlags) {
 
-	classDir := android.PathForModuleOut(ctx, "kotlinc", "classes")
-
 	inputs := append(android.Paths(nil), srcFiles...)
-	inputs = append(inputs, srcJars...)
 
 	var deps android.Paths
 	deps = append(deps, flags.kotlincClasspath...)
+	deps = append(deps, srcJars...)
 
 	ctx.Build(pctx, android.BuildParams{
 		Rule:        kotlinc,
@@ -188,7 +190,9 @@
 		Args: map[string]string{
 			"classpath":    flags.kotlincClasspath.FormJavaClassPath("-classpath"),
 			"kotlincFlags": flags.kotlincFlags,
-			"outDir":       classDir.String(),
+			"srcJars":      strings.Join(srcJars.Strings(), " "),
+			"outDir":       android.PathForModuleOut(ctx, "kotlinc", "classes").String(),
+			"srcJarDir":    android.PathForModuleOut(ctx, "kotlinc", "srcJars").String(),
 			// http://b/69160377 kotlinc only supports -jvm-target 1.6 and 1.8
 			"kotlinJvmTarget": "1.8",
 		},
diff --git a/java/config/config.go b/java/config/config.go
index 75176c9..b5e574e 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -83,6 +83,8 @@
 	pctx.SourcePathVariable("Ziptime", "prebuilts/build-tools/${hostPrebuiltTag}/bin/ziptime")
 
 	pctx.SourcePathVariable("ExtractSrcJarsCmd", "build/soong/scripts/extract-srcjars.sh")
+	pctx.SourcePathVariable("GenKotlinBuildFileCmd", "build/soong/scripts/gen-kotlin-build-file.sh")
+
 	pctx.SourcePathVariable("JarArgsCmd", "build/soong/scripts/jar-args.sh")
 	pctx.HostBinToolVariable("SoongZipCmd", "soong_zip")
 	pctx.HostBinToolVariable("MergeZipsCmd", "merge_zips")
diff --git a/java/java.go b/java/java.go
index 955b720..b587990 100644
--- a/java/java.go
+++ b/java/java.go
@@ -757,6 +757,16 @@
 
 	jarName := ctx.ModuleName() + ".jar"
 
+	javaSrcFiles := srcFiles.FilterByExt(".java")
+	var uniqueSrcFiles android.Paths
+	set := make(map[string]bool)
+	for _, v := range javaSrcFiles {
+		if _, found := set[v.String()]; !found {
+			set[v.String()] = true
+			uniqueSrcFiles = append(uniqueSrcFiles, v)
+		}
+	}
+
 	if srcFiles.HasExt(".kt") {
 		// If there are kotlin files, compile them first but pass all the kotlin and java files
 		// kotlinc will use the java files to resolve types referenced by the kotlin files, but
@@ -767,11 +777,15 @@
 			flags.kotlincFlags += " -no-jdk"
 		}
 
+		var kotlinSrcFiles android.Paths
+		kotlinSrcFiles = append(kotlinSrcFiles, uniqueSrcFiles...)
+		kotlinSrcFiles = append(kotlinSrcFiles, srcFiles.FilterByExt(".kt")...)
+
 		flags.kotlincClasspath = append(flags.kotlincClasspath, deps.kotlinStdlib...)
 		flags.kotlincClasspath = append(flags.kotlincClasspath, deps.classpath...)
 
 		kotlinJar := android.PathForModuleOut(ctx, "kotlin", jarName)
-		TransformKotlinToClasses(ctx, kotlinJar, srcFiles, srcJars, flags)
+		TransformKotlinToClasses(ctx, kotlinJar, kotlinSrcFiles, srcJars, flags)
 		if ctx.Failed() {
 			return
 		}
@@ -783,16 +797,6 @@
 		jars = append(jars, deps.kotlinStdlib...)
 	}
 
-	javaSrcFiles := srcFiles.FilterByExt(".java")
-	var uniqueSrcFiles android.Paths
-	set := make(map[string]bool)
-	for _, v := range javaSrcFiles {
-		if _, found := set[v.String()]; !found {
-			set[v.String()] = true
-			uniqueSrcFiles = append(uniqueSrcFiles, v)
-		}
-	}
-
 	// Store the list of .java files that was passed to javac
 	j.compiledJavaSrcs = uniqueSrcFiles
 	j.compiledSrcJars = srcJars
diff --git a/scripts/gen-kotlin-build-file.sh b/scripts/gen-kotlin-build-file.sh
new file mode 100755
index 0000000..f077a0c
--- /dev/null
+++ b/scripts/gen-kotlin-build-file.sh
@@ -0,0 +1,60 @@
+#!/bin/bash -e
+
+# Copyright 2018 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Generates kotlinc module xml file to standard output based on rsp files
+
+if [ -z "$1" ]; then
+  echo "usage: $0 <classpath> <outDir> <rspFiles>..." >&2
+  exit 1
+fi
+
+# Classpath variable has a tendency to be prefixed by "-classpath", remove it.
+if [[ $1 == "-classpath" ]]; then
+  shift
+fi;
+
+classpath=$1
+out_dir=$2
+shift 2
+
+# Path in the build file are relative to the build file, we need to make them absolute.
+prefix=`pwd`
+
+# Print preamble
+echo "<modules><module name=\"name\" type=\"java-production\" outputDir=\"${out_dir}\">"
+
+# Print classpath entries
+for file in $(echo $classpath | tr ":" "\n"); do
+  echo "  <classpath path=\"${prefix}/${file}\"/>"
+done
+
+# For each rsp file, print source entries
+while (( "$#" )); do
+  for file in $(cat $1); do
+    if [[ $file == *.java ]]; then
+      echo "  <javaSourceRoots path=\"${prefix}/${file}\"/>"
+    elif [[ $file == *.kt ]]; then
+      echo "  <sources path=\"${prefix}/${file}\"/>"
+    else
+      echo "Unknown source file type ${file}"
+      exit 1
+    fi
+  done
+
+  shift
+done
+
+echo "</module></modules>"
diff --git a/ui/build/config.go b/ui/build/config.go
index 363121f..27ed8e9 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -15,12 +15,14 @@
 package build
 
 import (
+	"io/ioutil"
 	"log"
 	"os"
 	"path/filepath"
 	"runtime"
 	"strconv"
 	"strings"
+	"time"
 
 	"android/soong/shared"
 )
@@ -181,6 +183,20 @@
 	ret.environ.Set("ANDROID_JAVA9_HOME", java9Home)
 	ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
 
+	outDir := ret.OutDir()
+	buildDateTimeFile := filepath.Join(outDir, "build_date.txt")
+	var content string
+	if buildDateTime, ok := ret.environ.Get("BUILD_DATETIME"); ok && buildDateTime != "" {
+		content = buildDateTime
+	} else {
+		content = strconv.FormatInt(time.Now().Unix(), 10)
+	}
+	err := ioutil.WriteFile(buildDateTimeFile, []byte(content), 0777)
+	if err != nil {
+		ctx.Fatalln("Failed to write BUILD_DATETIME to file:", err)
+	}
+	ret.environ.Set("BUILD_DATETIME_FILE", buildDateTimeFile)
+
 	return Config{ret}
 }