Merge "Expose the NDK STLs to make."
diff --git a/cc/cc.go b/cc/cc.go
index 6e28522..04aa6a6 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -1036,6 +1036,27 @@
ctx.ModuleErrorf("links %q built against newer API version %q",
ctx.OtherModuleName(to), String(to.Properties.Sdk_version))
}
+
+ // Also check that the two STL choices are compatible.
+ fromStl := from.stl.Properties.SelectedStl
+ toStl := to.stl.Properties.SelectedStl
+ if fromStl == "" || toStl == "" {
+ // Libraries that don't use the STL are unrestricted.
+ return
+ }
+
+ if fromStl == "ndk_system" || toStl == "ndk_system" {
+ // We can be permissive with the system "STL" since it is only the C++
+ // ABI layer, but in the future we should make sure that everyone is
+ // using either libc++ or nothing.
+ return
+ }
+
+ if getNdkStlFamily(ctx, from) != getNdkStlFamily(ctx, to) {
+ ctx.ModuleErrorf("uses %q and depends on %q which uses incompatible %q",
+ from.stl.Properties.SelectedStl, ctx.OtherModuleName(to),
+ to.stl.Properties.SelectedStl)
+ }
}
// Convert dependencies to paths. Returns a PathDeps containing paths
diff --git a/cc/compiler.go b/cc/compiler.go
index 40dbea4..4eae898 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -522,7 +522,7 @@
if ctx.useSdk() {
// The NDK sysroot timestamp file depends on all the NDK sysroot files
// (headers and libraries).
- return android.Paths{getNdkSysrootTimestampFile(ctx)}
+ return android.Paths{getNdkBaseTimestampFile(ctx)}
}
return nil
}
diff --git a/cc/config/global.go b/cc/config/global.go
index 6f4b3e2..6de1300 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -120,17 +120,14 @@
ClangDefaultShortVersion = "5.0.1"
WarningAllowedProjects = []string{
- "external/skia/",
"device/",
"vendor/",
}
// Some Android.mk files still have warnings.
WarningAllowedOldProjects = []string{
- "frameworks/av/drm/mediacas/plugins/",
"hardware/libhardware/modules/",
"hardware/qcom/",
- "tools/adt/idea/android/ultimate/get_modification_time/jni/",
}
)
diff --git a/cc/library.go b/cc/library.go
index b664a5e..d53bcfc 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -733,7 +733,8 @@
library.baseInstaller.install(ctx, file)
}
- if Bool(library.Properties.Static_ndk_lib) && library.static() {
+ if Bool(library.Properties.Static_ndk_lib) && library.static() &&
+ !ctx.useVndk() && ctx.Device() {
installPath := getNdkSysrootBase(ctx).Join(
ctx, "usr/lib", ctx.toolchain().ClangTriple(), file.Base())
diff --git a/cc/lto.go b/cc/lto.go
index fdb7688..b1e7cfa 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -40,10 +40,15 @@
// Lto must violate capitialization style for acronyms so that it can be
// referred to in blueprint files as "lto"
Lto struct {
- Full *bool `android:"arch_variant"`
- Thin *bool `android:"arch_variant"`
+ Never *bool `android:"arch_variant"`
+ Full *bool `android:"arch_variant"`
+ Thin *bool `android:"arch_variant"`
} `android:"arch_variant"`
- LTODep bool `blueprint:"mutated"`
+
+ // Dep properties indicate that this module needs to be built with LTO
+ // since it is an object dependency of an LTO module.
+ FullDep bool `blueprint:"mutated"`
+ ThinDep bool `blueprint:"mutated"`
}
type lto struct {
@@ -84,7 +89,7 @@
// Can be called with a null receiver
func (lto *lto) LTO() bool {
- if lto == nil {
+ if lto == nil || lto.Disabled() {
return false
}
@@ -93,41 +98,91 @@
return full || thin
}
+// Is lto.never explicitly set to true?
+func (lto *lto) Disabled() bool {
+ return lto.Properties.Lto.Never != nil && *lto.Properties.Lto.Never
+}
+
// Propagate lto requirements down from binaries
func ltoDepsMutator(mctx android.TopDownMutatorContext) {
- if c, ok := mctx.Module().(*Module); ok && c.lto.LTO() {
- full := Bool(c.lto.Properties.Lto.Full)
- thin := Bool(c.lto.Properties.Lto.Thin)
+ if m, ok := mctx.Module().(*Module); ok && m.lto.LTO() {
+ full := Bool(m.lto.Properties.Lto.Full)
+ thin := Bool(m.lto.Properties.Lto.Thin)
if full && thin {
mctx.PropertyErrorf("LTO", "FullLTO and ThinLTO are mutually exclusive")
}
- mctx.VisitDepsDepthFirst(func(m android.Module) {
- tag := mctx.OtherModuleDependencyTag(m)
+ mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
+ tag := mctx.OtherModuleDependencyTag(dep)
switch tag {
case staticDepTag, staticExportDepTag, lateStaticDepTag, wholeStaticDepTag, objDepTag, reuseObjTag:
- if cc, ok := m.(*Module); ok && cc.lto != nil {
- cc.lto.Properties.LTODep = true
+ if dep, ok := dep.(*Module); ok && dep.lto != nil &&
+ !dep.lto.Disabled() {
+ if full && !Bool(dep.lto.Properties.Lto.Full) {
+ dep.lto.Properties.FullDep = true
+ }
+ if thin && !Bool(dep.lto.Properties.Lto.Thin) {
+ dep.lto.Properties.ThinDep = true
+ }
}
+
+ // Recursively walk static dependencies
+ return true
}
+
+ // Do not recurse down non-static dependencies
+ return false
})
}
}
// Create lto variants for modules that need them
func ltoMutator(mctx android.BottomUpMutatorContext) {
- if c, ok := mctx.Module().(*Module); ok && c.lto != nil {
- if c.lto.LTO() {
- mctx.SetDependencyVariation("lto")
- } else if c.lto.Properties.LTODep {
- modules := mctx.CreateVariations("", "lto")
- modules[0].(*Module).lto.Properties.Lto.Full = boolPtr(false)
- modules[0].(*Module).lto.Properties.Lto.Thin = boolPtr(false)
- modules[0].(*Module).lto.Properties.LTODep = false
- modules[1].(*Module).lto.Properties.LTODep = false
- modules[1].(*Module).Properties.PreventInstall = true
- modules[1].(*Module).Properties.HideFromMake = true
+ if m, ok := mctx.Module().(*Module); ok && m.lto != nil {
+ // Create variations for LTO types required as static
+ // dependencies
+ variationNames := []string{""}
+ if m.lto.Properties.FullDep && !Bool(m.lto.Properties.Lto.Full) {
+ variationNames = append(variationNames, "lto-full")
}
- c.lto.Properties.LTODep = false
+ if m.lto.Properties.ThinDep && !Bool(m.lto.Properties.Lto.Thin) {
+ variationNames = append(variationNames, "lto-thin")
+ }
+
+ // Use correct dependencies if LTO property is explicitly set
+ // (mutually exclusive)
+ if Bool(m.lto.Properties.Lto.Full) {
+ mctx.SetDependencyVariation("lto-full")
+ }
+ if Bool(m.lto.Properties.Lto.Thin) {
+ mctx.SetDependencyVariation("lto-thin")
+ }
+
+ if len(variationNames) > 1 {
+ modules := mctx.CreateVariations(variationNames...)
+ for i, name := range variationNames {
+ variation := modules[i].(*Module)
+ // Default module which will be
+ // installed. Variation set above according to
+ // explicit LTO properties
+ if name == "" {
+ continue
+ }
+
+ // LTO properties for dependencies
+ if name == "lto-full" {
+ variation.lto.Properties.Lto.Full = boolPtr(true)
+ variation.lto.Properties.Lto.Thin = boolPtr(false)
+ }
+ if name == "lto-thin" {
+ variation.lto.Properties.Lto.Full = boolPtr(false)
+ variation.lto.Properties.Lto.Thin = boolPtr(true)
+ }
+ variation.Properties.PreventInstall = true
+ variation.Properties.HideFromMake = true
+ variation.lto.Properties.FullDep = false
+ variation.lto.Properties.ThinDep = false
+ }
+ }
}
}
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index 4324458..c7ba588 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -74,7 +74,16 @@
return getNdkInstallBase(ctx).Join(ctx, "sysroot")
}
-func getNdkSysrootTimestampFile(ctx android.PathContext) android.WritablePath {
+// The base timestamp file depends on the NDK headers and stub shared libraries,
+// but not the static libraries. This distinction is needed because the static
+// libraries themselves might need to depend on the base sysroot.
+func getNdkBaseTimestampFile(ctx android.PathContext) android.WritablePath {
+ return android.PathForOutput(ctx, "ndk_base.timestamp")
+}
+
+// The full timestamp file depends on the base timestamp *and* the static
+// libraries.
+func getNdkFullTimestampFile(ctx android.PathContext) android.WritablePath {
return android.PathForOutput(ctx, "ndk.timestamp")
}
@@ -85,6 +94,7 @@
type ndkSingleton struct{}
func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ var staticLibInstallPaths android.Paths
var installPaths android.Paths
var licensePaths android.Paths
ctx.VisitAllModules(func(module android.Module) {
@@ -109,7 +119,8 @@
if library, ok := m.linker.(*libraryDecorator); ok {
if library.ndkSysrootPath != nil {
- installPaths = append(installPaths, library.ndkSysrootPath)
+ staticLibInstallPaths = append(
+ staticLibInstallPaths, library.ndkSysrootPath)
}
}
}
@@ -123,13 +134,21 @@
Inputs: licensePaths,
})
- depPaths := append(installPaths, combinedLicense)
+ baseDepPaths := append(installPaths, combinedLicense)
// There's a dummy "ndk" rule defined in ndk/Android.mk that depends on
// this. `m ndk` will build the sysroots.
ctx.Build(pctx, android.BuildParams{
Rule: android.Touch,
- Output: getNdkSysrootTimestampFile(ctx),
- Implicits: depPaths,
+ Output: getNdkBaseTimestampFile(ctx),
+ Implicits: baseDepPaths,
+ })
+
+ fullDepPaths := append(staticLibInstallPaths, getNdkBaseTimestampFile(ctx))
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Touch,
+ Output: getNdkFullTimestampFile(ctx),
+ Implicits: fullDepPaths,
})
}
diff --git a/cc/pgo.go b/cc/pgo.go
index 9fea154..fef962e 100644
--- a/cc/pgo.go
+++ b/cc/pgo.go
@@ -42,6 +42,9 @@
Profile_file *string `android:"arch_variant"`
Benchmarks []string
Enable_profile_use *bool `android:"arch_variant"`
+ // Additional compiler flags to use when building this module
+ // for profiling (either instrumentation or sampling).
+ Cflags []string `android:"arch_variant"`
} `android:"arch_variant"`
PgoPresent bool `blueprint:"mutated"`
@@ -65,6 +68,8 @@
}
func (props *PgoProperties) addProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
+ flags.CFlags = append(flags.CFlags, props.Pgo.Cflags...)
+
if props.isInstrumentation() {
flags.CFlags = append(flags.CFlags, profileInstrumentFlag)
// The profile runtime is added below in deps(). Add the below
diff --git a/cc/stl.go b/cc/stl.go
index 347db99..338db84 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -19,6 +19,25 @@
"fmt"
)
+func getNdkStlFamily(ctx android.ModuleContext, m *Module) string {
+ stl := m.stl.Properties.SelectedStl
+ switch stl {
+ case "ndk_libc++_shared", "ndk_libc++_static":
+ return "libc++"
+ case "ndk_libstlport_shared", "ndk_libstlport_static":
+ return "stlport"
+ case "ndk_libgnustl_static":
+ return "gnustl"
+ case "ndk_system":
+ return "system"
+ case "":
+ return "none"
+ default:
+ ctx.ModuleErrorf("stl: %q is not a valid STL", stl)
+ return ""
+ }
+}
+
type StlProperties struct {
// select the STL library to use. Possible values are "libc++", "libc++_static",
// "stlport", "stlport_static", "ndk", "libstdc++", or "none". Leave blank to select the
diff --git a/cc/tidy.go b/cc/tidy.go
index 6d7c957..67fd3db 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -77,6 +77,11 @@
flags.TidyFlags = append(flags.TidyFlags, headerFilter)
}
+ // If clang-tidy is not enabled globally, add the -quiet flag.
+ if !ctx.Config().ClangTidy() {
+ flags.TidyFlags = append(flags.TidyFlags, "-quiet")
+ }
+
// We might be using the static analyzer through clang tidy.
// https://bugs.llvm.org/show_bug.cgi?id=32914
flags.TidyFlags = append(flags.TidyFlags, "-extra-arg-before=-D__clang_analyzer__")
diff --git a/java/androidmk.go b/java/androidmk.go
index 40ebe5b..24fe43a 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -156,6 +156,12 @@
if app.dexJarFile != nil {
fmt.Fprintln(w, "LOCAL_SOONG_DEX_JAR :=", app.dexJarFile.String())
}
+ if app.implementationJarFile != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_CLASSES_JAR :=", app.implementationJarFile)
+ }
+ if app.headerJarFile != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_HEADER_JAR :=", app.headerJarFile.String())
+ }
if app.jacocoReportClassesFile != nil {
fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", app.jacocoReportClassesFile.String())
}
diff --git a/java/builder.go b/java/builder.go
index 48fba23..ff618d8 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -214,11 +214,15 @@
inputs := append(android.Paths(nil), srcFiles...)
inputs = append(inputs, srcJars...)
+ var deps android.Paths
+ deps = append(deps, flags.kotlincClasspath...)
+
ctx.Build(pctx, android.BuildParams{
Rule: kotlinc,
Description: "kotlinc",
Output: outputFile,
Inputs: inputs,
+ Implicits: deps,
Args: map[string]string{
"classpath": flags.kotlincClasspath.FormJavaClassPath("-classpath"),
"kotlincFlags": flags.kotlincFlags,
diff --git a/java/java.go b/java/java.go
index d9075b1..9b345fd 100644
--- a/java/java.go
+++ b/java/java.go
@@ -142,6 +142,11 @@
Exclude_filter []string
}
+ Proto struct {
+ // List of extra options that will be passed to the proto generator.
+ Output_params []string
+ }
+
Instrument bool `blueprint:"mutated"`
}
@@ -620,7 +625,7 @@
}
srcFiles := ctx.ExpandSources(j.properties.Srcs, j.properties.Exclude_srcs)
if hasSrcExt(srcFiles.Strings(), ".proto") {
- flags = protoFlags(ctx, &j.protoProperties, flags)
+ flags = protoFlags(ctx, &j.properties, &j.protoProperties, flags)
}
srcFiles = j.genSources(ctx, srcFiles, flags)
diff --git a/java/java_test.go b/java/java_test.go
index 78fbd41..84fe903 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -705,43 +705,61 @@
ctx := testJava(t, `
java_library {
name: "foo",
- srcs: ["a.java", "b.kt"],
+ srcs: ["a.java", "b.kt"],
}
java_library {
name: "bar",
- srcs: ["b.kt"],
+ srcs: ["b.kt"],
+ libs: ["foo"],
+ static_libs: ["baz"],
+ }
+
+ java_library {
+ name: "baz",
+ srcs: ["c.java"],
}
`)
- kotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
- javac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
- jar := ctx.ModuleForTests("foo", "android_common").Output("combined/foo.jar")
+ fooKotlinc := ctx.ModuleForTests("foo", "android_common").Rule("kotlinc")
+ fooJavac := ctx.ModuleForTests("foo", "android_common").Rule("javac")
+ fooJar := ctx.ModuleForTests("foo", "android_common").Output("combined/foo.jar")
- if len(kotlinc.Inputs) != 2 || kotlinc.Inputs[0].String() != "a.java" ||
- kotlinc.Inputs[1].String() != "b.kt" {
- t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, kotlinc.Inputs)
+ if len(fooKotlinc.Inputs) != 2 || fooKotlinc.Inputs[0].String() != "a.java" ||
+ fooKotlinc.Inputs[1].String() != "b.kt" {
+ t.Errorf(`foo kotlinc inputs %v != ["a.java", "b.kt"]`, fooKotlinc.Inputs)
}
- if len(javac.Inputs) != 1 || javac.Inputs[0].String() != "a.java" {
- t.Errorf(`foo inputs %v != ["a.java"]`, javac.Inputs)
+ if len(fooJavac.Inputs) != 1 || fooJavac.Inputs[0].String() != "a.java" {
+ t.Errorf(`foo inputs %v != ["a.java"]`, fooJavac.Inputs)
}
- if !strings.Contains(javac.Args["classpath"], kotlinc.Output.String()) {
+ if !strings.Contains(fooJavac.Args["classpath"], fooKotlinc.Output.String()) {
t.Errorf("foo classpath %v does not contain %q",
- javac.Args["classpath"], kotlinc.Output.String())
+ fooJavac.Args["classpath"], fooKotlinc.Output.String())
}
- if !inList(kotlinc.Output.String(), jar.Inputs.Strings()) {
+ if !inList(fooKotlinc.Output.String(), fooJar.Inputs.Strings()) {
t.Errorf("foo jar inputs %v does not contain %q",
- jar.Inputs.Strings(), kotlinc.Output.String())
+ fooJar.Inputs.Strings(), fooKotlinc.Output.String())
}
- kotlinc = ctx.ModuleForTests("bar", "android_common").Rule("kotlinc")
- jar = ctx.ModuleForTests("bar", "android_common").Output("combined/bar.jar")
+ fooHeaderJar := ctx.ModuleForTests("foo", "android_common").Output("turbine-combined/foo.jar")
+ bazHeaderJar := ctx.ModuleForTests("baz", "android_common").Output("turbine-combined/baz.jar")
+ barKotlinc := ctx.ModuleForTests("bar", "android_common").Rule("kotlinc")
- if len(kotlinc.Inputs) != 1 || kotlinc.Inputs[0].String() != "b.kt" {
- t.Errorf(`bar kotlinc inputs %v != ["b.kt"]`, kotlinc.Inputs)
+ if len(barKotlinc.Inputs) != 1 || barKotlinc.Inputs[0].String() != "b.kt" {
+ t.Errorf(`bar kotlinc inputs %v != ["b.kt"]`, barKotlinc.Inputs)
+ }
+
+ if !inList(fooHeaderJar.Output.String(), barKotlinc.Implicits.Strings()) {
+ t.Errorf(`expected %q in bar implicits %v`,
+ fooHeaderJar.Output.String(), barKotlinc.Implicits.Strings())
+ }
+
+ if !inList(bazHeaderJar.Output.String(), barKotlinc.Implicits.Strings()) {
+ t.Errorf(`expected %q in bar implicits %v`,
+ bazHeaderJar.Output.String(), barKotlinc.Implicits.Strings())
}
}
@@ -754,7 +772,7 @@
java_library {
name: "bar",
- srcs: ["b.java"],
+ srcs: ["b.java"],
static_libs: ["foo"],
}
diff --git a/java/proto.go b/java/proto.go
index 428413f..226fac0 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -77,7 +77,9 @@
}
}
-func protoFlags(ctx android.ModuleContext, p *android.ProtoProperties, flags javaBuilderFlags) javaBuilderFlags {
+func protoFlags(ctx android.ModuleContext, j *CompilerProperties, p *android.ProtoProperties,
+ flags javaBuilderFlags) javaBuilderFlags {
+
switch proptools.String(p.Proto.Type) {
case "micro":
flags.protoOutTypeFlag = "--javamicro_out"
@@ -93,6 +95,13 @@
proptools.String(p.Proto.Type))
}
+ if len(j.Proto.Output_params) > 0 {
+ if flags.protoOutParams != "" {
+ flags.protoOutParams += ","
+ }
+ flags.protoOutParams += strings.Join(j.Proto.Output_params, ",")
+ }
+
flags.protoFlags = android.ProtoFlags(ctx, p)
return flags