Merge "Disble CFI for ARM32 processes."
diff --git a/android/config.go b/android/config.go
index 76635b3..eaacef7 100644
--- a/android/config.go
+++ b/android/config.go
@@ -471,11 +471,3 @@
 func (c *deviceConfig) BtConfigIncludeDir() string {
 	return String(c.config.ProductVariables.BtConfigIncludeDir)
 }
-
-func (c *deviceConfig) BtHcilpIncluded() string {
-	return String(c.config.ProductVariables.BtHcilpIncluded)
-}
-
-func (c *deviceConfig) BtHciUseMct() bool {
-	return Bool(c.config.ProductVariables.BtHciUseMct)
-}
diff --git a/android/variable.go b/android/variable.go
index bb84be2..24c58df 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -141,8 +141,6 @@
 	ArtUseReadBarrier *bool `json:",omitempty"`
 
 	BtConfigIncludeDir *string `json:",omitempty"`
-	BtHcilpIncluded    *string `json:",omitempty"`
-	BtHciUseMct        *bool   `json:",omitempty"`
 }
 
 func boolPtr(v bool) *bool {
diff --git a/cc/config/global.go b/cc/config/global.go
index e254a1c..1ce1cce 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -145,6 +145,14 @@
 	})
 	pctx.StaticVariable("ClangAsanLibDir", "${ClangPath}/lib64/clang/${ClangShortVersion}/lib/linux")
 
+	// These are tied to the version of LLVM directly in external/llvm, so they might trail the host prebuilts
+	// being used for the rest of the build process.
+	pctx.SourcePathVariable("RSClangBase", "prebuilts/clang/host")
+	pctx.SourcePathVariable("RSClangVersion", "clang-3289846")
+	pctx.SourcePathVariable("RSReleaseVersion", "3.8")
+	pctx.StaticVariable("RSLLVMPrebuiltsPath", "${RSClangBase}/${HostPrebuiltTag}/${RSClangVersion}/bin")
+	pctx.StaticVariable("RSIncludePath", "${RSLLVMPrebuiltsPath}/../lib64/clang/${RSReleaseVersion}/include")
+
 	pctx.VariableFunc("CcWrapper", func(config interface{}) (string, error) {
 		if override := config.(android.Config).Getenv("CC_WRAPPER"); override != "" {
 			return override + " ", nil
diff --git a/cc/makevars.go b/cc/makevars.go
index 30d83e8..06b57c9 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -40,6 +40,13 @@
 	ctx.Strict("PATH_TO_CLANG_TIDY", "${config.ClangBin}/clang-tidy")
 	ctx.StrictSorted("CLANG_CONFIG_UNKNOWN_CFLAGS", strings.Join(config.ClangUnknownCflags, " "))
 
+	ctx.Strict("RS_LLVM_PREBUILTS_VERSION", "${config.RSClangVersion}")
+	ctx.Strict("RS_LLVM_PREBUILTS_BASE", "${config.RSClangBase}")
+	ctx.Strict("RS_LLVM_PREBUILTS_PATH", "${config.RSLLVMPrebuiltsPath}")
+	ctx.Strict("RS_CLANG", "${config.RSLLVMPrebuiltsPath}/clang")
+	ctx.Strict("RS_LLVM_AS", "${config.RSLLVMPrebuiltsPath}/llvm-as")
+	ctx.Strict("RS_LLVM_LINK", "${config.RSLLVMPrebuiltsPath}/llvm-link")
+
 	ctx.Strict("GLOBAL_CFLAGS_NO_OVERRIDE", "${config.NoOverrideGlobalCflags}")
 	ctx.Strict("GLOBAL_CLANG_CFLAGS_NO_OVERRIDE", "${config.ClangExtraNoOverrideCflags}")
 	ctx.Strict("GLOBAL_CPPFLAGS_NO_OVERRIDE", "")
diff --git a/cmd/javac_filter/Android.bp b/cmd/javac_filter/Android.bp
new file mode 100644
index 0000000..cbdabb9
--- /dev/null
+++ b/cmd/javac_filter/Android.bp
@@ -0,0 +1,23 @@
+// Copyright 2017 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.
+
+blueprint_go_binary {
+    name: "soong_javac_filter",
+    srcs: [
+        "javac_filter.go",
+    ],
+    testSrcs: [
+        "javac_filter_test.go",
+    ],
+}
diff --git a/cmd/javac_filter/javac_filter.go b/cmd/javac_filter/javac_filter.go
new file mode 100644
index 0000000..32fcd63
--- /dev/null
+++ b/cmd/javac_filter/javac_filter.go
@@ -0,0 +1,105 @@
+// Copyright 2017 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.
+
+// soong_javac_filter expects the output of javac on stdin, and produces
+// an ANSI colorized version of the output on stdout.
+//
+// It also hides the unhelpful and unhideable "warning there is a warning"
+// messages.
+package main
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"os"
+	"regexp"
+)
+
+// Regular expressions are based on
+// https://chromium.googlesource.com/chromium/src/+/master/build/android/gyp/javac.py
+// Colors are based on clang's output
+var (
+	filelinePrefix = `^[-.\w/\\]+.java:[0-9]+:`
+	warningRe      = regexp.MustCompile(filelinePrefix + ` (warning:) .*$`)
+	errorRe        = regexp.MustCompile(filelinePrefix + ` (.*?:) .*$`)
+	markerRe       = regexp.MustCompile(`\s*(\^)\s*$`)
+
+	escape  = "\x1b"
+	reset   = escape + "[0m"
+	bold    = escape + "[1m"
+	red     = escape + "[31m"
+	green   = escape + "[32m"
+	magenta = escape + "[35m"
+)
+
+func main() {
+	err := process(bufio.NewReader(os.Stdin), os.Stdout)
+	if err != nil {
+		fmt.Fprintln(os.Stderr, "reading standard input:", err)
+		os.Exit(-1)
+	}
+}
+
+func process(r io.Reader, w io.Writer) error {
+	scanner := bufio.NewScanner(r)
+	for scanner.Scan() {
+		processLine(w, scanner.Text())
+	}
+	return scanner.Err()
+}
+
+func processLine(w io.Writer, line string) {
+	for _, f := range filters {
+		if f.MatchString(line) {
+			return
+		}
+	}
+	for _, p := range colorPatterns {
+		var matched bool
+		if line, matched = applyColor(line, p.color, p.re); matched {
+			break
+		}
+	}
+	fmt.Fprintln(w, line)
+}
+
+// If line matches re, make it bold and apply color to the first submatch
+// Returns line, modified if it matched, and true if it matched.
+func applyColor(line, color string, re *regexp.Regexp) (string, bool) {
+	if m := re.FindStringSubmatchIndex(line); m != nil {
+		tagStart, tagEnd := m[2], m[3]
+		line = bold + line[:tagStart] +
+			color + line[tagStart:tagEnd] + reset + bold +
+			line[tagEnd:] + reset
+		return line, true
+	}
+	return line, false
+}
+
+var colorPatterns = []struct {
+	re    *regexp.Regexp
+	color string
+}{
+	{warningRe, magenta},
+	{errorRe, red},
+	{markerRe, green},
+}
+
+var filters = []*regexp.Regexp{
+	regexp.MustCompile(`Note: (Some input files|.*\.java) uses? or overrides? a deprecated API.`),
+	regexp.MustCompile(`Note: Recompile with -Xlint:deprecation for details.`),
+	regexp.MustCompile(`Note: (Some input files|.*\.java) uses? unchecked or unsafe operations.`),
+	regexp.MustCompile(`Note: Recompile with -Xlint:unchecked for details.`),
+}
diff --git a/cmd/javac_filter/javac_filter_test.go b/cmd/javac_filter/javac_filter_test.go
new file mode 100644
index 0000000..43381ce
--- /dev/null
+++ b/cmd/javac_filter/javac_filter_test.go
@@ -0,0 +1,74 @@
+// Copyright 2017 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.
+
+package main
+
+import (
+	"bytes"
+	"testing"
+)
+
+var testCases = []struct {
+	in, out string
+}{
+	{
+		in:  "File.java:40: error: cannot find symbol\n",
+		out: "\x1b[1mFile.java:40: \x1b[31merror:\x1b[0m\x1b[1m cannot find symbol\x1b[0m\n",
+	},
+	{
+		in:  "import static com.blah.SYMBOL;\n",
+		out: "import static com.blah.SYMBOL;\n",
+	},
+	{
+		in:  "          ^           \n",
+		out: "\x1b[1m          \x1b[32m^\x1b[0m\x1b[1m           \x1b[0m\n",
+	},
+	{
+		in:  "File.java:398: warning: [RectIntersectReturnValueIgnored] Return value of com.blah.function() must be checked\n",
+		out: "\x1b[1mFile.java:398: \x1b[35mwarning:\x1b[0m\x1b[1m [RectIntersectReturnValueIgnored] Return value of com.blah.function() must be checked\x1b[0m\n",
+	},
+	{
+		in:  "    (see http://go/errorprone/bugpattern/RectIntersectReturnValueIgnored.md)\n",
+		out: "    (see http://go/errorprone/bugpattern/RectIntersectReturnValueIgnored.md)\n",
+	},
+	{
+		in: `
+Note: Some input files use or override a deprecated API.
+Note: Recompile with -Xlint:deprecation for details.
+Note: Some input files use unchecked or unsafe operations.
+Note: Recompile with -Xlint:unchecked for details.
+Note: dir/file.java uses or overrides a deprecated API.
+Note: dir/file.java uses unchecked or unsafe operations.
+`,
+		out: "\n",
+	},
+	{
+		in:  "\n",
+		out: "\n",
+	},
+}
+
+func TestJavacColorize(t *testing.T) {
+	for _, test := range testCases {
+		buf := new(bytes.Buffer)
+		err := process(bytes.NewReader([]byte(test.in)), buf)
+		if err != nil {
+			t.Errorf("error: %q", err)
+		}
+		got := string(buf.Bytes())
+		if got != test.out {
+			t.Errorf("expected %q got %q", test.out, got)
+		}
+	}
+}
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index 2ff19ce..21d8383 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -102,7 +102,7 @@
 	log.Println("Output directory:", *outDir)
 
 	build.SetupOutDir(buildCtx, config)
-	log.SetOutput(filepath.Join(config.OutDir(), "build.log"))
+	log.SetOutput(filepath.Join(config.OutDir(), "soong.log"))
 	trace.SetOutput(filepath.Join(config.OutDir(), "build.trace"))
 
 	vars, err := build.DumpMakeVars(buildCtx, config, nil, nil, []string{"all_named_products"})
@@ -137,7 +137,7 @@
 			}
 
 			productLog := logger.New(&bytes.Buffer{})
-			productLog.SetOutput(filepath.Join(productOutDir, "build.log"))
+			productLog.SetOutput(filepath.Join(productOutDir, "soong.log"))
 
 			productCtx := build.Context{&build.ContextImpl{
 				Context:        ctx,
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index de941f4..06a601e 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -70,8 +70,15 @@
 
 	log.SetVerbose(config.IsVerbose())
 	build.SetupOutDir(buildCtx, config)
-	log.SetOutput(filepath.Join(config.OutDir(), "build.log"))
-	trace.SetOutput(filepath.Join(config.OutDir(), "build.trace"))
+
+	if config.Dist() {
+		os.MkdirAll(config.DistDir(), 0777)
+		log.SetOutput(filepath.Join(config.DistDir(), "logs", "soong.log"))
+		trace.SetOutput(filepath.Join(config.DistDir(), "logs", "build.trace"))
+	} else {
+		log.SetOutput(filepath.Join(config.OutDir(), "soong.log"))
+		trace.SetOutput(filepath.Join(config.OutDir(), "build.trace"))
+	}
 
 	if start, ok := os.LookupEnv("TRACE_BEGIN_SOONG"); ok {
 		if !strings.HasSuffix(start, "N") {
diff --git a/ui/build/config.go b/ui/build/config.go
index 35c5213..4853643 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -35,6 +35,7 @@
 	parallel  int
 	keepGoing int
 	verbose   bool
+	dist      bool
 
 	// From the product config
 	katiArgs   []string
@@ -90,6 +91,8 @@
 		} else if arg == "showcommands" {
 			ret.verbose = true
 			continue
+		} else if arg == "dist" {
+			ret.dist = true
 		}
 		if arg[0] == '-' {
 			var err error
@@ -183,6 +186,13 @@
 	return "out"
 }
 
+func (c *configImpl) DistDir() string {
+	if distDir, ok := c.environ.Get("DIST_DIR"); ok {
+		return distDir
+	}
+	return filepath.Join(c.OutDir(), "dist")
+}
+
 func (c *configImpl) NinjaArgs() []string {
 	return c.ninjaArgs
 }
@@ -198,6 +208,10 @@
 	panic("SetKatiSuffix has not been called")
 }
 
+func (c *configImpl) Dist() bool {
+	return c.dist
+}
+
 func (c *configImpl) IsVerbose() bool {
 	return c.verbose
 }