Merge "Make java_sdk_library implement Dependency"
diff --git a/README.md b/README.md
index 74d49bb..44a98f3 100644
--- a/README.md
+++ b/README.md
@@ -34,7 +34,7 @@
all Android.bp files.
For a list of valid module types and their properties see
-[$OUT_DIR/soong/.bootstrap/docs/soong_build.html](http://go/Android.bp).
+[$OUT_DIR/soong/docs/soong_build.html](http://go/Android.bp).
### Globs
diff --git a/android/onceper.go b/android/onceper.go
index 5fefb71..f06f428 100644
--- a/android/onceper.go
+++ b/android/onceper.go
@@ -20,8 +20,23 @@
)
type OncePer struct {
- values sync.Map
- valuesLock sync.Mutex
+ values sync.Map
+}
+
+type onceValueWaiter chan bool
+
+func (once *OncePer) maybeWaitFor(key OnceKey, value interface{}) interface{} {
+ if wait, isWaiter := value.(onceValueWaiter); isWaiter {
+ // The entry in the map is a placeholder waiter because something else is constructing the value
+ // wait until the waiter is signalled, then load the real value.
+ <-wait
+ value, _ = once.values.Load(key)
+ if _, isWaiter := value.(onceValueWaiter); isWaiter {
+ panic(fmt.Errorf("Once() waiter completed but key is still not valid"))
+ }
+ }
+
+ return value
}
// Once computes a value the first time it is called with a given key per OncePer, and returns the
@@ -29,21 +44,20 @@
func (once *OncePer) Once(key OnceKey, value func() interface{}) interface{} {
// Fast path: check if the key is already in the map
if v, ok := once.values.Load(key); ok {
- return v
+ return once.maybeWaitFor(key, v)
}
- // Slow path: lock so that we don't call the value function twice concurrently
- once.valuesLock.Lock()
- defer once.valuesLock.Unlock()
-
- // Check again with the lock held
- if v, ok := once.values.Load(key); ok {
- return v
+ // Slow path: create a OnceValueWrapper and attempt to insert it
+ waiter := make(onceValueWaiter)
+ if v, loaded := once.values.LoadOrStore(key, waiter); loaded {
+ // Got a value, something else inserted its own waiter or a constructed value
+ return once.maybeWaitFor(key, v)
}
- // Still not in the map, call the value function and store it
+ // The waiter is inserted, call the value constructor, store it, and signal the waiter
v := value()
once.values.Store(key, v)
+ close(waiter)
return v
}
diff --git a/android/onceper_test.go b/android/onceper_test.go
index d2ca9ad..f27799b 100644
--- a/android/onceper_test.go
+++ b/android/onceper_test.go
@@ -133,3 +133,14 @@
t.Errorf(`second call to Once with the NewCustomOnceKey from equal key should return "a": %q`, b)
}
}
+
+func TestOncePerReentrant(t *testing.T) {
+ once := OncePer{}
+ key1 := NewOnceKey("key")
+ key2 := NewOnceKey("key")
+
+ a := once.Once(key1, func() interface{} { return once.Once(key2, func() interface{} { return "a" }) })
+ if a != "a" {
+ t.Errorf(`reentrant Once should return "a": %q`, a)
+ }
+}
diff --git a/android/prebuilt_etc.go b/android/prebuilt_etc.go
index 33647d7..8af08c1 100644
--- a/android/prebuilt_etc.go
+++ b/android/prebuilt_etc.go
@@ -25,7 +25,7 @@
func init() {
RegisterModuleType("prebuilt_etc", PrebuiltEtcFactory)
- RegisterModuleType("prebuilt_etc_host", prebuiltEtcHostFactory)
+ RegisterModuleType("prebuilt_etc_host", PrebuiltEtcHostFactory)
PreDepsMutators(func(ctx RegisterMutatorsContext) {
ctx.BottomUp("prebuilt_etc", prebuiltEtcMutator).Parallel()
@@ -182,7 +182,7 @@
return module
}
-func prebuiltEtcHostFactory() Module {
+func PrebuiltEtcHostFactory() Module {
module := &PrebuiltEtc{}
InitPrebuiltEtcModule(module)
// This module is host-only
diff --git a/android/prebuilt_etc_test.go b/android/prebuilt_etc_test.go
index f31fc9e..d0961a7 100644
--- a/android/prebuilt_etc_test.go
+++ b/android/prebuilt_etc_test.go
@@ -28,7 +28,7 @@
defer tearDown(buildDir)
ctx := NewTestArchContext()
ctx.RegisterModuleType("prebuilt_etc", ModuleFactoryAdaptor(PrebuiltEtcFactory))
- ctx.RegisterModuleType("prebuilt_etc_host", ModuleFactoryAdaptor(prebuiltEtcHostFactory))
+ ctx.RegisterModuleType("prebuilt_etc_host", ModuleFactoryAdaptor(PrebuiltEtcHostFactory))
ctx.PreDepsMutators(func(ctx RegisterMutatorsContext) {
ctx.BottomUp("prebuilt_etc", prebuiltEtcMutator).Parallel()
})
diff --git a/androidmk/cmd/androidmk/android.go b/androidmk/cmd/androidmk/android.go
index abe7917..1ecda2d 100644
--- a/androidmk/cmd/androidmk/android.go
+++ b/androidmk/cmd/androidmk/android.go
@@ -189,6 +189,7 @@
"LOCAL_PRIVILEGED_MODULE": "privileged",
"LOCAL_AAPT_INCLUDE_ALL_RESOURCES": "aapt_include_all_resources",
"LOCAL_USE_EMBEDDED_NATIVE_LIBS": "use_embedded_native_libs",
+ "LOCAL_USE_EMBEDDED_DEX": "use_embedded_dex",
"LOCAL_DEX_PREOPT": "dex_preopt.enabled",
"LOCAL_DEX_PREOPT_APP_IMAGE": "dex_preopt.app_image",
diff --git a/apex/apex.go b/apex/apex.go
index 95cee0c..0337afb 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -252,6 +252,19 @@
Ignore_system_library_special_case *bool
Multilib apexMultilibProperties
+
+ Prefer_sanitize struct {
+ // Prefer native libraries with asan if available
+ Address *bool
+ // Prefer native libraries with hwasan if available
+ Hwaddress *bool
+ // Prefer native libraries with tsan if available
+ Thread *bool
+ // Prefer native libraries with integer_overflow if available
+ Integer_overflow *bool
+ // Prefer native libraries with cfi if available
+ Cfi *bool
+ }
}
type apexTargetBundleProperties struct {
@@ -527,6 +540,31 @@
}
func (a *apexBundle) IsSanitizerEnabled(ctx android.BaseModuleContext, sanitizerName string) bool {
+ // If this APEX is configured to prefer a sanitizer, use it
+ switch sanitizerName {
+ case "asan":
+ if proptools.Bool(a.properties.Prefer_sanitize.Address) {
+ return true
+ }
+ case "hwasan":
+ if proptools.Bool(a.properties.Prefer_sanitize.Hwaddress) {
+ return true
+ }
+ case "tsan":
+ if proptools.Bool(a.properties.Prefer_sanitize.Thread) {
+ return true
+ }
+ case "cfi":
+ if proptools.Bool(a.properties.Prefer_sanitize.Cfi) {
+ return true
+ }
+ case "integer_overflow":
+ if proptools.Bool(a.properties.Prefer_sanitize.Integer_overflow) {
+ return true
+ }
+ }
+
+ // Then follow the global setting
globalSanitizerNames := []string{}
if a.Host() {
globalSanitizerNames = ctx.Config().SanitizeHost()
diff --git a/cc/cc.go b/cc/cc.go
index c09a2f3..01577bc 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -348,6 +348,7 @@
linkerFlagsDepTag = dependencyTag{name: "linker flags file"}
dynamicLinkerDepTag = dependencyTag{name: "dynamic linker"}
reuseObjTag = dependencyTag{name: "reuse objects"}
+ staticVariantTag = dependencyTag{name: "static variant"}
ndkStubDepTag = dependencyTag{name: "ndk stub", library: true}
ndkLateStubDepTag = dependencyTag{name: "ndk late stub", library: true}
vndkExtDepTag = dependencyTag{name: "vndk extends", library: true}
@@ -1536,6 +1537,13 @@
}
}
+ if depTag == staticVariantTag {
+ if _, ok := ccDep.compiler.(libraryInterface); ok {
+ c.staticVariant = ccDep
+ return
+ }
+ }
+
// Extract explicitlyVersioned field from the depTag and reset it inside the struct.
// Otherwise, sharedDepTag and lateSharedDepTag with explicitlyVersioned set to true
// won't be matched to sharedDepTag and lateSharedDepTag.
diff --git a/cc/cc_test.go b/cc/cc_test.go
index dc23620..9d370c1 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -215,6 +215,7 @@
ctx.RegisterModuleType("cc_binary", android.ModuleFactoryAdaptor(BinaryFactory))
ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(LibraryFactory))
ctx.RegisterModuleType("cc_library_shared", android.ModuleFactoryAdaptor(LibrarySharedFactory))
+ ctx.RegisterModuleType("cc_library_static", android.ModuleFactoryAdaptor(LibraryStaticFactory))
ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(LibraryHeaderFactory))
ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(ToolchainLibraryFactory))
ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(LlndkLibraryFactory))
@@ -1966,3 +1967,43 @@
}
}
}
+
+func TestStaticDepsOrderWithStubs(t *testing.T) {
+ ctx := testCc(t, `
+ cc_binary {
+ name: "mybin",
+ srcs: ["foo.c"],
+ static_libs: ["libB"],
+ static_executable: true,
+ stl: "none",
+ }
+
+ cc_library {
+ name: "libB",
+ srcs: ["foo.c"],
+ shared_libs: ["libC"],
+ stl: "none",
+ }
+
+ cc_library {
+ name: "libC",
+ srcs: ["foo.c"],
+ stl: "none",
+ stubs: {
+ versions: ["1"],
+ },
+ }`)
+
+ mybin := ctx.ModuleForTests("mybin", "android_arm64_armv8-a_core").Module().(*Module)
+ actual := mybin.depsInLinkOrder
+ expected := getOutputPaths(ctx, "android_arm64_armv8-a_core_static", []string{"libB", "libC"})
+
+ if !reflect.DeepEqual(actual, expected) {
+ t.Errorf("staticDeps orderings were not propagated correctly"+
+ "\nactual: %v"+
+ "\nexpected: %v",
+ actual,
+ expected,
+ )
+ }
+}
diff --git a/cc/library.go b/cc/library.go
index b4b89d2..a6c7bc8 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1032,6 +1032,9 @@
sharedCompiler.baseCompiler.Properties.Srcs
sharedCompiler.baseCompiler.Properties.Srcs = nil
sharedCompiler.baseCompiler.Properties.Generated_sources = nil
+ } else {
+ // This dep is just to reference static variant from shared variant
+ mctx.AddInterVariantDependency(staticVariantTag, shared, static)
}
}
}
diff --git a/java/aar.go b/java/aar.go
index f6a3d3a..7495bda 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -76,6 +76,7 @@
extraAaptPackagesFile android.Path
isLibrary bool
uncompressedJNI bool
+ useEmbeddedDex bool
aaptProperties aaptProperties
}
@@ -182,7 +183,8 @@
manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
- manifestPath := manifestMerger(ctx, manifestSrcPath, sdkContext, staticLibManifests, a.isLibrary, a.uncompressedJNI)
+ manifestPath := manifestMerger(ctx, manifestSrcPath, sdkContext, staticLibManifests, a.isLibrary,
+ a.uncompressedJNI, a.useEmbeddedDex)
linkFlags, linkDeps, resDirs, overlayDirs, rroDirs := a.aapt2Flags(ctx, sdkContext, manifestPath)
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 6d4399d..e63fb80 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -44,7 +44,7 @@
"libs")
func manifestMerger(ctx android.ModuleContext, manifest android.Path, sdkContext sdkContext,
- staticLibManifests android.Paths, isLibrary bool, uncompressedJNI bool) android.Path {
+ staticLibManifests android.Paths, isLibrary bool, uncompressedJNI, useEmbeddedDex bool) android.Path {
var args []string
if isLibrary {
@@ -62,6 +62,10 @@
}
}
+ if useEmbeddedDex {
+ args = append(args, "--use-embedded-dex=true")
+ }
+
// Inject minSdkVersion into the manifest
fixedManifest := android.PathForModuleOut(ctx, "manifest_fixer", "AndroidManifest.xml")
ctx.Build(pctx, android.BuildParams{
diff --git a/java/app.go b/java/app.go
index 47f4f0d..9697582 100644
--- a/java/app.go
+++ b/java/app.go
@@ -73,6 +73,10 @@
// sdk_version or min_sdk_version is set to a version that doesn't support it (<23), defaults to false for other
// module types where the native libraries are generally preinstalled outside the APK.
Use_embedded_native_libs *bool
+
+ // Store dex files uncompressed in the APK and set the android:useEmbeddedDex="true" manifest attribute so that
+ // they are used from inside the APK at runtime.
+ Use_embedded_dex *bool
}
type AndroidApp struct {
@@ -141,6 +145,7 @@
func (a *AndroidApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.aapt.uncompressedJNI = a.shouldUncompressJNI(ctx)
+ a.aapt.useEmbeddedDex = Bool(a.appProperties.Use_embedded_dex)
a.generateAndroidBuildActions(ctx)
}
@@ -157,6 +162,10 @@
// Returns whether this module should have the dex file stored uncompressed in the APK.
func (a *AndroidApp) shouldUncompressDex(ctx android.ModuleContext) bool {
+ if Bool(a.appProperties.Use_embedded_dex) {
+ return true
+ }
+
if ctx.Config().UnbundledBuild() {
return false
}
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index 17decd0..b9713fe 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -74,7 +74,6 @@
}
var Configuration = map[string]PathConfig{
- "awk": Allowed,
"bash": Allowed,
"bc": Allowed,
"bzip2": Allowed,
@@ -127,6 +126,7 @@
"pkg-config": Forbidden,
// On Linux we'll use the toybox versions of these instead.
+ "awk": Toybox, // Strictly one-true-awk, but...
"basename": Toybox,
"cat": Toybox,
"chmod": Toybox,