Build rule updates for aosp

Various build rule changes to match AOSP:
Add libunwind_llvm and libdl as dependencies for libc++ on device
Always add libcompiler_rt-extras as a dependency
Add libm, libc, and libdl as depnendencies for libc++ static binaries
Disable some clang warnings, and add some clang filtered cflags
Add -fstack-protector to host linux builds
Add jack_flags property to java modules (currently ignored)

Change-Id: Ic0da617bdeaf25f58cb8298dd9ea91b7d6509151
diff --git a/cc/cc.go b/cc/cc.go
index 5d6e124..3ab8a47 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -278,6 +278,8 @@
 	}
 
 	installPath string
+
+	savedDepNames CCDeps
 }
 
 func newCCBase(base *CCBase, module CCModuleType, hod common.HostOrDeviceSupported,
@@ -301,12 +303,7 @@
 		return
 	}
 
-	depNames := c.module.depNames(ctx, CCDeps{})
-	if ctx.Failed() {
-		return
-	}
-
-	deps := c.depsToPaths(ctx, depNames)
+	deps := c.depsToPaths(ctx, c.savedDepNames)
 	if ctx.Failed() {
 		return
 	}
@@ -366,21 +363,24 @@
 func (c *CCBase) AndroidDynamicDependencies(ctx common.AndroidDynamicDependerModuleContext) []string {
 	c.module.ModifyProperties(ctx)
 
-	depNames := CCDeps{}
-	depNames = c.module.depNames(ctx, depNames)
-	staticLibs := depNames.WholeStaticLibs
-	staticLibs = append(staticLibs, depNames.StaticLibs...)
-	staticLibs = append(staticLibs, depNames.LateStaticLibs...)
+	c.savedDepNames = c.module.depNames(ctx, CCDeps{})
+	c.savedDepNames.WholeStaticLibs = lastUniqueElements(c.savedDepNames.WholeStaticLibs)
+	c.savedDepNames.StaticLibs = lastUniqueElements(c.savedDepNames.StaticLibs)
+	c.savedDepNames.SharedLibs = lastUniqueElements(c.savedDepNames.SharedLibs)
+
+	staticLibs := c.savedDepNames.WholeStaticLibs
+	staticLibs = append(staticLibs, c.savedDepNames.StaticLibs...)
+	staticLibs = append(staticLibs, c.savedDepNames.LateStaticLibs...)
 	ctx.AddVariationDependencies([]blueprint.Variation{{"link", "static"}}, staticLibs...)
 
-	ctx.AddVariationDependencies([]blueprint.Variation{{"link", "shared"}}, depNames.SharedLibs...)
+	ctx.AddVariationDependencies([]blueprint.Variation{{"link", "shared"}}, c.savedDepNames.SharedLibs...)
 
-	ret := append([]string(nil), depNames.ObjFiles...)
-	if depNames.CrtBegin != "" {
-		ret = append(ret, depNames.CrtBegin)
+	ret := append([]string(nil), c.savedDepNames.ObjFiles...)
+	if c.savedDepNames.CrtBegin != "" {
+		ret = append(ret, c.savedDepNames.CrtBegin)
 	}
-	if depNames.CrtEnd != "" {
-		ret = append(ret, depNames.CrtEnd)
+	if c.savedDepNames.CrtEnd != "" {
+		ret = append(ret, c.savedDepNames.CrtEnd)
 	}
 
 	return ret
@@ -818,14 +818,26 @@
 	}
 
 	switch stl {
-	case "libc++":
-		depNames.SharedLibs = append(depNames.SharedLibs, stl)
 	case "libstdc++":
 		if ctx.Device() {
 			depNames.SharedLibs = append(depNames.SharedLibs, stl)
 		}
-	case "libc++_static":
-		depNames.StaticLibs = append(depNames.StaticLibs, stl)
+	case "libc++", "libc++_static":
+		if stl == "libc++" {
+			depNames.SharedLibs = append(depNames.SharedLibs, stl)
+		} else {
+			depNames.StaticLibs = append(depNames.StaticLibs, stl)
+		}
+		if ctx.Device() {
+			if ctx.Arch().ArchType == common.Arm {
+				depNames.StaticLibs = append(depNames.StaticLibs, "libunwind_llvm")
+			}
+			if c.staticBinary() {
+				depNames.StaticLibs = append(depNames.StaticLibs, "libdl")
+			} else {
+				depNames.SharedLibs = append(depNames.SharedLibs, "libdl")
+			}
+		}
 	case "stlport":
 		depNames.SharedLibs = append(depNames.SharedLibs, "libstdc++", "libstlport")
 	case "stlport_static":
@@ -845,10 +857,11 @@
 		panic(fmt.Errorf("Unknown stl in CCLinked.depNames: %q", stl))
 	}
 
+	if ctx.ModuleName() != "libcompiler_rt-extras" {
+		depNames.StaticLibs = append(depNames.StaticLibs, "libcompiler_rt-extras")
+	}
+
 	if ctx.Device() {
-		if ctx.ModuleName() != "libcompiler_rt-extras" {
-			depNames.StaticLibs = append(depNames.StaticLibs, "libcompiler_rt-extras")
-		}
 		// libgcc and libatomic have to be last on the command line
 		depNames.LateStaticLibs = append(depNames.LateStaticLibs, "libgcov", "libatomic", "libgcc")
 
@@ -1259,6 +1272,9 @@
 		}
 
 		if c.BinaryProperties.Static_executable {
+			if c.stl(ctx) == "libc++_static" {
+				depNames.StaticLibs = append(depNames.StaticLibs, "libm", "libc", "libdl")
+			}
 			// static libraries libcompiler_rt, libc and libc_nomalloc need to be linked with
 			// --start-group/--end-group along with libgcc.  If they are in deps.StaticLibs,
 			// move them to the beginning of deps.LateStaticLibs
@@ -1751,3 +1767,21 @@
 		}
 	}
 }
+
+// lastUniqueElements returns all unique elements of a slice, keeping the last copy of each
+// modifies the slice contents in place, and returns a subslice of the original slice
+func lastUniqueElements(list []string) []string {
+	totalSkip := 0
+	for i := len(list) - 1; i >= totalSkip; i-- {
+		skip := 0
+		for j := i - 1; j >= totalSkip; j-- {
+			if list[i] == list[j] {
+				skip++
+			} else {
+				list[j+skip] = list[j]
+			}
+		}
+		totalSkip += skip
+	}
+	return list[totalSkip:]
+}
diff --git a/cc/cc_test.go b/cc/cc_test.go
new file mode 100644
index 0000000..3bf0c65
--- /dev/null
+++ b/cc/cc_test.go
@@ -0,0 +1,56 @@
+package cc
+
+import (
+	"reflect"
+	"testing"
+)
+
+var lastUniqueElementsTestCases = []struct {
+	in  []string
+	out []string
+}{
+	{
+		in:  []string{"a"},
+		out: []string{"a"},
+	},
+	{
+		in:  []string{"a", "b"},
+		out: []string{"a", "b"},
+	},
+	{
+		in:  []string{"a", "a"},
+		out: []string{"a"},
+	},
+	{
+		in:  []string{"a", "b", "a"},
+		out: []string{"b", "a"},
+	},
+	{
+		in:  []string{"b", "a", "a"},
+		out: []string{"b", "a"},
+	},
+	{
+		in:  []string{"a", "a", "b"},
+		out: []string{"a", "b"},
+	},
+	{
+		in:  []string{"a", "b", "a", "b"},
+		out: []string{"a", "b"},
+	},
+	{
+		in:  []string{"liblog", "libdl", "libc++", "libdl", "libc", "libm"},
+		out: []string{"liblog", "libc++", "libdl", "libc", "libm"},
+	},
+}
+
+func TestLastUniqueElements(t *testing.T) {
+	for _, testCase := range lastUniqueElementsTestCases {
+		out := lastUniqueElements(testCase.in)
+		if !reflect.DeepEqual(out, testCase.out) {
+			t.Errorf("incorrect output:")
+			t.Errorf("     input: %#v", testCase.in)
+			t.Errorf("  expected: %#v", testCase.out)
+			t.Errorf("       got: %#v", out)
+		}
+	}
+}
diff --git a/cc/clang.go b/cc/clang.go
index f3ced68..347efbe 100644
--- a/cc/clang.go
+++ b/cc/clang.go
@@ -15,15 +15,18 @@
 	"-funswitch-loops",
 	"-Wmaybe-uninitialized",
 	"-Wno-error=maybe-uninitialized",
+	"-Wno-error=unused-but-set-parameter",
+	"-Wno-error=unused-but-set-variable",
 	"-Wno-free-nonheap-object",
 	"-Wno-literal-suffix",
 	"-Wno-maybe-uninitialized",
 	"-Wno-old-style-declaration",
 	"-Wno-psabi",
-	"-Wno-unused-but-set-variable",
 	"-Wno-unused-but-set-parameter",
+	"-Wno-unused-but-set-variable",
 	"-Wno-unused-local-typedefs",
 	"-Wunused-but-set-parameter",
+	"-Wunused-but-set-variable",
 
 	// arm + arm64 + mips + mips64
 	"-fgcse-after-reload",
@@ -65,6 +68,14 @@
 		// Help catch common 32/64-bit errors.
 		"-Werror=int-conversion",
 
+		// Disable overly aggressive warning for macros defined with a leading underscore
+		// This happens in AndroidConfig.h, which is included nearly everywhere.
+		"-Wno-reserved-id-macro",
+
+		// Disable overly aggressive warning for format strings.
+		// Bug: 20148343
+		"-Wno-format-pedantic",
+
 		// Workaround for ccache with clang.
 		// See http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html.
 		"-Wno-unused-command-line-argument",
diff --git a/cc/x86_linux_host.go b/cc/x86_linux_host.go
index 05e5720..b39c0b4 100644
--- a/cc/x86_linux_host.go
+++ b/cc/x86_linux_host.go
@@ -18,9 +18,10 @@
 		"-no-canonical-prefixes",
 		"-include ${SrcDir}/build/core/combo/include/arch/linux-x86/AndroidConfig.h",
 
-		// Disable new longjmp in glibc 2.11 and later. See bug 2967937. Same for 2.15?
+		// TODO: Set _FORTIFY_SOURCE=2. Bug 20558757.
 		"-U_FORTIFY_SOURCE",
 		"-D_FORTIFY_SOURCE=0",
+		"-fstack-protector",
 
 		// Workaround differences in inttypes.h between host and target.
 		//See bug 12708004.
diff --git a/java/java.go b/java/java.go
index d9aad3c..d22f47a 100644
--- a/java/java.go
+++ b/java/java.go
@@ -65,6 +65,9 @@
 		// javacflags: list of module-specific flags that will be used for javac compiles
 		Javacflags []string `android:"arch_variant"`
 
+		// jack_flags: list of module-specific flags that will be used for jack compiles
+		Jack_flags []string `android:"arch_variant"`
+
 		// dxflags: list of module-specific flags that will be used for dex compiles
 		Dxflags []string `android:"arch_variant"`