Merge "Support MacOS SDK version 10.12"
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
new file mode 100644
index 0000000..928ca03
--- /dev/null
+++ b/PREUPLOAD.cfg
@@ -0,0 +1,2 @@
+[Builtin Hooks]
+gofmt = true
diff --git a/android/arch.go b/android/arch.go
index 61564d8..6c99684 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -799,13 +799,15 @@
 	return targets, nil
 }
 
-func decodeMegaDevice() ([]Target, error) {
-	archSettings := []struct {
-		arch        string
-		archVariant string
-		cpuVariant  string
-		abi         []string
-	}{
+type archConfig struct {
+	arch        string
+	archVariant string
+	cpuVariant  string
+	abi         []string
+}
+
+func getMegaDeviceConfig() []archConfig {
+	return []archConfig{
 		// armv5 is only used for unbundled apps
 		//{"arm", "armv5te", "", []string{"armeabi"}},
 		{"arm", "armv7-a", "generic", []string{"armeabi-v7a"}},
@@ -846,10 +848,23 @@
 		{"x86_64", "sandybridge", "", []string{"x86_64"}},
 		{"x86_64", "silvermont", "", []string{"x86_64"}},
 	}
+}
 
+func getNdkAbisConfig() []archConfig {
+	return []archConfig{
+		{"arm", "armv5te", "", []string{"armeabi"}},
+		{"arm64", "armv8-a", "", []string{"arm64-v8a"}},
+		{"mips", "mips32-fp", "", []string{"mips"}},
+		{"mips64", "mips64r6", "", []string{"mips64"}},
+		{"x86", "", "", []string{"x86"}},
+		{"x86_64", "", "", []string{"x86_64"}},
+	}
+}
+
+func decodeArchSettings(archConfigs []archConfig) ([]Target, error) {
 	var ret []Target
 
-	for _, config := range archSettings {
+	for _, config := range archConfigs {
 		arch, err := decodeArch(config.arch, &config.archVariant,
 			&config.cpuVariant, &config.abi)
 		if err != nil {
diff --git a/android/config.go b/android/config.go
index 483ec91..4d7e8df 100644
--- a/android/config.go
+++ b/android/config.go
@@ -37,6 +37,7 @@
 // config file. These will be included in the config struct.
 type FileConfigurableOptions struct {
 	Mega_device *bool `json:",omitempty"`
+	Ndk_abis    *bool `json:",omitempty"`
 }
 
 func (f *FileConfigurableOptions) SetDefaultConfig() {
@@ -211,8 +212,15 @@
 		return Config{}, err
 	}
 
+	var archConfig []archConfig
 	if Bool(config.Mega_device) {
-		deviceTargets, err := decodeMegaDevice()
+		archConfig = getMegaDeviceConfig()
+	} else if Bool(config.Ndk_abis) {
+		archConfig = getNdkAbisConfig()
+	}
+
+	if archConfig != nil {
+		deviceTargets, err := decodeArchSettings(archConfig)
 		if err != nil {
 			return Config{}, err
 		}
diff --git a/android/defs.go b/android/defs.go
index 6e28de7..d7e2a9f 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -74,6 +74,12 @@
 		},
 		"error")
 
+	Cat = pctx.AndroidStaticRule("Cat",
+		blueprint.RuleParams{
+			Command:     "cat $in > $out",
+			Description: "concatenate licenses $out",
+		})
+
 	// Used only when USE_GOMA=true is set, to restrict non-goma jobs to the local parallelism value
 	localPool = blueprint.NewBuiltinPool("local_pool")
 )
diff --git a/android/module.go b/android/module.go
index 572b162..230d95c 100644
--- a/android/module.go
+++ b/android/module.go
@@ -170,6 +170,7 @@
 const (
 	_ HostOrDeviceSupported = iota
 	HostSupported
+	HostSupportedNoCross
 	DeviceSupported
 	HostAndDeviceSupported
 	HostAndDeviceDefault
@@ -326,8 +327,9 @@
 func (a *ModuleBase) OsClassSupported() []OsClass {
 	switch a.commonProperties.HostOrDeviceSupported {
 	case HostSupported:
-		// TODO(ccross): explicitly mark host cross support
 		return []OsClass{Host, HostCross}
+	case HostSupportedNoCross:
+		return []OsClass{Host}
 	case DeviceSupported:
 		return []OsClass{Device}
 	case HostAndDeviceSupported:
diff --git a/build.ninja.in b/build.ninja.in
index ec1bc0d..e22f146 100644
--- a/build.ninja.in
+++ b/build.ninja.in
@@ -154,7 +154,7 @@
 # Variant:
 # Type:    bootstrap_go_package
 # Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
-# Defined: build/blueprint/Blueprints:83:1
+# Defined: build/blueprint/Blueprints:85:1
 
 build $
         ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap/pkg/github.com/google/blueprint/bootstrap.a $
@@ -182,7 +182,7 @@
 # Variant:
 # Type:    bootstrap_go_package
 # Factory: github.com/google/blueprint/bootstrap.newGoPackageModuleFactory.func1
-# Defined: build/blueprint/Blueprints:102:1
+# Defined: build/blueprint/Blueprints:104:1
 
 build $
         ${g.bootstrap.buildDir}/.bootstrap/blueprint-bootstrap-bpdoc/pkg/github.com/google/blueprint/bootstrap/bpdoc.a $
@@ -354,10 +354,12 @@
         ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/test/github.com/google/blueprint/proptools.a $
         : g.bootstrap.compile $
         ${g.bootstrap.srcDir}/build/blueprint/proptools/clone.go $
+        ${g.bootstrap.srcDir}/build/blueprint/proptools/escape.go $
         ${g.bootstrap.srcDir}/build/blueprint/proptools/extend.go $
         ${g.bootstrap.srcDir}/build/blueprint/proptools/proptools.go $
         ${g.bootstrap.srcDir}/build/blueprint/proptools/typeequal.go $
         ${g.bootstrap.srcDir}/build/blueprint/proptools/clone_test.go $
+        ${g.bootstrap.srcDir}/build/blueprint/proptools/escape_test.go $
         ${g.bootstrap.srcDir}/build/blueprint/proptools/extend_test.go $
         ${g.bootstrap.srcDir}/build/blueprint/proptools/typeequal_test.go | $
         ${g.bootstrap.compileCmd}
@@ -368,6 +370,7 @@
 build ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/test/test.go: $
         g.bootstrap.gotestmain $
         ${g.bootstrap.srcDir}/build/blueprint/proptools/clone_test.go $
+        ${g.bootstrap.srcDir}/build/blueprint/proptools/escape_test.go $
         ${g.bootstrap.srcDir}/build/blueprint/proptools/extend_test.go $
         ${g.bootstrap.srcDir}/build/blueprint/proptools/typeequal_test.go | $
         ${g.bootstrap.goTestMainCmd}
@@ -403,6 +406,7 @@
         ${g.bootstrap.buildDir}/.bootstrap/blueprint-proptools/pkg/github.com/google/blueprint/proptools.a $
         : g.bootstrap.compile $
         ${g.bootstrap.srcDir}/build/blueprint/proptools/clone.go $
+        ${g.bootstrap.srcDir}/build/blueprint/proptools/escape.go $
         ${g.bootstrap.srcDir}/build/blueprint/proptools/extend.go $
         ${g.bootstrap.srcDir}/build/blueprint/proptools/proptools.go $
         ${g.bootstrap.srcDir}/build/blueprint/proptools/typeequal.go | $
@@ -417,7 +421,7 @@
 # Variant:
 # Type:    bootstrap_core_go_binary
 # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
-# Defined: build/blueprint/Blueprints:135:1
+# Defined: build/blueprint/Blueprints:137:1
 
 build ${g.bootstrap.buildDir}/.bootstrap/gotestmain/obj/gotestmain.a: $
         g.bootstrap.compile $
@@ -441,7 +445,7 @@
 # Variant:
 # Type:    bootstrap_core_go_binary
 # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
-# Defined: build/blueprint/Blueprints:140:1
+# Defined: build/blueprint/Blueprints:142:1
 
 build ${g.bootstrap.buildDir}/.bootstrap/gotestrunner/obj/gotestrunner.a: $
         g.bootstrap.compile $
@@ -465,7 +469,7 @@
 # Variant:
 # Type:    bootstrap_core_go_binary
 # Factory: github.com/google/blueprint/bootstrap.newGoBinaryModuleFactory.func1
-# Defined: build/blueprint/Blueprints:114:1
+# Defined: build/blueprint/Blueprints:116:1
 
 build ${g.bootstrap.buildDir}/.bootstrap/minibp/obj/minibp.a: $
         g.bootstrap.compile $
diff --git a/cc/compiler.go b/cc/compiler.go
index 198b792..a0068ad 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -84,6 +84,9 @@
 	// pass -frtti instead of -fno-rtti
 	Rtti *bool
 
+	// if set to false, use -std=c++* instead of -std=gnu++*
+	Gnu_extensions *bool
+
 	Debug, Release struct {
 		// list of module-specific flags that will be used for C and C++ compiles in debug or
 		// release builds
@@ -278,13 +281,27 @@
 	}
 
 	if !ctx.sdk() {
-		if ctx.Host() && !flags.Clang {
+		cStd := config.CStdVersion
+		cppStd := config.CppStdVersion
+
+		if !flags.Clang {
+			// GCC uses an invalid C++14 ABI (emits calls to
+			// __cxa_throw_bad_array_length, which is not a valid C++ RT ABI).
+			// http://b/25022512
+			cppStd = config.GccCppStdVersion
+		} else if ctx.Host() && !flags.Clang {
 			// The host GCC doesn't support C++14 (and is deprecated, so likely
 			// never will). Build these modules with C++11.
-			flags.CppFlags = append(flags.CppFlags, "-std=gnu++11")
-		} else {
-			flags.CppFlags = append(flags.CppFlags, "-std=gnu++14")
+			cppStd = config.GccCppStdVersion
 		}
+
+		if compiler.Properties.Gnu_extensions != nil && *compiler.Properties.Gnu_extensions == false {
+			cStd = gnuToCReplacer.Replace(cStd)
+			cppStd = gnuToCReplacer.Replace(cppStd)
+		}
+
+		flags.ConlyFlags = append([]string{"-std=" + cStd}, flags.ConlyFlags...)
+		flags.CppFlags = append([]string{"-std=" + cppStd}, flags.CppFlags...)
 	}
 
 	// We can enforce some rules more strictly in the code we own. strict
@@ -306,6 +323,8 @@
 	return flags
 }
 
+var gnuToCReplacer = strings.NewReplacer("gnu", "c")
+
 func ndkPathDeps(ctx ModuleContext) android.Paths {
 	if ctx.sdk() {
 		// The NDK sysroot timestamp file depends on all the NDK sysroot files
diff --git a/cc/config/global.go b/cc/config/global.go
index 9b77662..348c586 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -37,9 +37,7 @@
 		"-UDEBUG",
 	}
 
-	commonGlobalConlyflags = []string{
-		"-std=gnu99",
-	}
+	commonGlobalConlyflags = []string{}
 
 	deviceGlobalCflags = []string{
 		"-fdiagnostics-color",
@@ -66,6 +64,10 @@
 	IllegalFlags = []string{
 		"-w",
 	}
+
+	CStdVersion      = "gnu99"
+	CppStdVersion    = "gnu++14"
+	GccCppStdVersion = "gnu++11"
 )
 
 var pctx = android.NewPackageContext("android/soong/cc/config")
diff --git a/cc/library.go b/cc/library.go
index feeb03c..a61e6a1 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -229,9 +229,13 @@
 			f = append(f,
 				"-dynamiclib",
 				"-single_module",
-				"-read_only_relocs suppress",
 				"-install_name @rpath/"+libName+flags.Toolchain.ShlibSuffix(),
 			)
+			if ctx.Arch().ArchType == android.X86 {
+				f = append(f,
+					"-read_only_relocs suppress",
+				)
+			}
 		} else {
 			f = append(f,
 				sharedFlag,
diff --git a/cc/linker.go b/cc/linker.go
index 399074d..0923338 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -150,7 +150,12 @@
 	toolchain := ctx.toolchain()
 
 	if !ctx.noDefaultCompilerFlags() {
-		if ctx.Device() && !Bool(linker.Properties.Allow_undefined_symbols) {
+		if Bool(linker.Properties.Allow_undefined_symbols) {
+			if ctx.Darwin() {
+				// darwin defaults to treating undefined symbols as errors
+				flags.LdFlags = append(flags.LdFlags, "-Wl,-undefined,dynamic_lookup")
+			}
+		} else if !ctx.Darwin() {
 			flags.LdFlags = append(flags.LdFlags, "-Wl,--no-undefined")
 		}
 
diff --git a/cc/makevars.go b/cc/makevars.go
index 098ec02..770e1d0 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -48,6 +48,10 @@
 	ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS", asanLdflags)
 	ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_STATIC_LIBRARIES", asanLibs)
 
+	ctx.Strict("DEFAULT_C_STD_VERSION", config.CStdVersion)
+	ctx.Strict("DEFAULT_CPP_STD_VERSION", config.CppStdVersion)
+	ctx.Strict("DEFAULT_GCC_CPP_STD_VERSION", config.GccCppStdVersion)
+
 	includeFlags, err := ctx.Eval("${config.CommonGlobalIncludes} ${config.CommonGlobalSystemIncludes}")
 	if err != nil {
 		panic(err)
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index ece83bb..9cc3417 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -46,6 +46,9 @@
 
 	// List of headers to install. Glob compatible. Common case is "include/**/*.h".
 	Srcs []string
+
+	// Path to the NOTICE file associated with the headers.
+	License string
 }
 
 type headerModule struct {
@@ -54,12 +57,19 @@
 	properties headerProperies
 
 	installPaths []string
+	licensePath  android.ModuleSrcPath
 }
 
 func (m *headerModule) DepsMutator(ctx android.BottomUpMutatorContext) {
 }
 
 func (m *headerModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+	if m.properties.License == "" {
+		ctx.PropertyErrorf("license", "field is required")
+	}
+
+	m.licensePath = android.PathForModuleSrc(ctx, m.properties.License)
+
 	srcFiles := ctx.ExpandSources(m.properties.Srcs, nil)
 	for _, header := range srcFiles {
 		// Output path is the sysroot base + "usr/include" + to directory + directory component
@@ -100,6 +110,10 @@
 
 func ndkHeadersFactory() (blueprint.Module, []interface{}) {
 	module := &headerModule{}
-	return android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst,
-		&module.properties)
+	// Host module rather than device module because device module install steps
+	// do not get run when embedded in make. We're not any of the existing
+	// module types that can be exposed via the Android.mk exporter, so just use
+	// a host module.
+	return android.InitAndroidArchModule(module, android.HostSupportedNoCross,
+		android.MultilibFirst, &module.properties)
 }
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index cbdaa26..e82f12b 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -66,12 +66,12 @@
 	pctx.Import("android/soong/common")
 }
 
-func getNdkInstallBase(ctx android.ModuleContext) android.OutputPath {
+func getNdkInstallBase(ctx android.PathContext) android.OutputPath {
 	return android.PathForOutput(ctx, "ndk")
 }
 
 // Returns the main install directory for the NDK sysroot. Usable with --sysroot.
-func getNdkSysrootBase(ctx android.ModuleContext) android.OutputPath {
+func getNdkSysrootBase(ctx android.PathContext) android.OutputPath {
 	return getNdkInstallBase(ctx).Join(ctx, "sysroot")
 }
 
@@ -87,9 +87,11 @@
 
 func (n *ndkSingleton) GenerateBuildActions(ctx blueprint.SingletonContext) {
 	installPaths := []string{}
+	licensePaths := []string{}
 	ctx.VisitAllModules(func(module blueprint.Module) {
 		if m, ok := module.(*headerModule); ok {
 			installPaths = append(installPaths, m.installPaths...)
+			licensePaths = append(licensePaths, m.licensePath.String())
 		}
 	})
 
@@ -101,12 +103,22 @@
 		}
 	})
 
+	combinedLicense := getNdkInstallBase(ctx).Join(ctx, "NOTICE")
+	ctx.Build(pctx, blueprint.BuildParams{
+		Rule:     android.Cat,
+		Outputs:  []string{combinedLicense.String()},
+		Inputs:   licensePaths,
+		Optional: true,
+	})
+
+	depPaths := append(installPaths, combinedLicense.String())
+
 	// There's a dummy "ndk" rule defined in ndk/Android.mk that depends on
 	// this. `m ndk` will build the sysroots.
 	ctx.Build(pctx, blueprint.BuildParams{
 		Rule:      android.Touch,
 		Outputs:   []string{getNdkSysrootTimestampFile(ctx).String()},
-		Implicits: installPaths,
+		Implicits: depPaths,
 		Optional:  true,
 	})
 }
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 2676373..d9e28cc 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -25,9 +25,9 @@
 )
 
 const (
-	asanCflags = "-fno-omit-frame-pointer"
+	asanCflags  = "-fno-omit-frame-pointer"
 	asanLdflags = "-Wl,-u,__asan_preinit"
-	asanLibs = "libasan"
+	asanLibs    = "libasan"
 )
 
 type sanitizerType int
@@ -255,6 +255,9 @@
 			// libraries needed with -fsanitize=address. http://b/18650275 (WAI)
 			flags.LdFlags = append(flags.LdFlags, "-lm", "-lpthread")
 			flags.LdFlags = append(flags.LdFlags, "-Wl,--no-as-needed")
+			// Host ASAN only links symbols in the final executable, so
+			// there will always be undefined symbols in intermediate libraries.
+			_, flags.LdFlags = removeFromList("-Wl,--no-undefined", flags.LdFlags)
 		} else {
 			flags.CFlags = append(flags.CFlags, "-mllvm", "-asan-globals=0")
 			flags.DynamicLinker = "/system/bin/linker_asan"
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
new file mode 100755
index 0000000..cc418d4
--- /dev/null
+++ b/scripts/build-ndk-prebuilts.sh
@@ -0,0 +1,25 @@
+#!/bin/bash -ex
+
+if [ -z "${OUT_DIR}" ]; then
+    echo Must set OUT_DIR
+    exit 1
+fi
+
+TOP=$(pwd)
+
+SOONG_OUT=${OUT_DIR}/soong
+SOONG_NDK_OUT=${OUT_DIR}/soong/ndk
+rm -rf ${SOONG_OUT}
+mkdir -p ${SOONG_OUT}
+cat > ${SOONG_OUT}/soong.config << EOF
+{
+    "Ndk_abis": true
+}
+EOF
+BUILDDIR=${SOONG_OUT} ./bootstrap.bash
+${SOONG_OUT}/soong ${SOONG_OUT}/ndk.timestamp
+
+if [ -n "${DIST_DIR}" ]; then
+    mkdir -p ${DIST_DIR} || true
+    tar cjf ${DIST_DIR}/ndk_platform.tar.bz2 -C ${SOONG_OUT} ndk
+fi