Merge "Fix error handling"
diff --git a/android/bazel_test.go b/android/bazel_test.go
index 3164b23..7b38b6a 100644
--- a/android/bazel_test.go
+++ b/android/bazel_test.go
@@ -423,3 +423,21 @@
}
}
}
+
+func TestShouldKeepExistingBuildFileForDir(t *testing.T) {
+ allowlist := NewBp2BuildAllowlist()
+ // entry "a/b2/c2" is moot because of its parent "a/b2"
+ allowlist.SetKeepExistingBuildFile(map[string]bool{"a": false, "a/b1": false, "a/b2": true, "a/b1/c1": true, "a/b2/c2": false})
+ truths := []string{"a", "a/b1", "a/b2", "a/b1/c1", "a/b2/c", "a/b2/c2", "a/b2/c2/d"}
+ falsities := []string{"a1", "a/b", "a/b1/c"}
+ for _, dir := range truths {
+ if !allowlist.ShouldKeepExistingBuildFileForDir(dir) {
+ t.Errorf("%s expected TRUE but was FALSE", dir)
+ }
+ }
+ for _, dir := range falsities {
+ if allowlist.ShouldKeepExistingBuildFileForDir(dir) {
+ t.Errorf("%s expected FALSE but was TRUE", dir)
+ }
+ }
+}
diff --git a/android/licenses.go b/android/licenses.go
index c47b3e6..c6b3243 100644
--- a/android/licenses.go
+++ b/android/licenses.go
@@ -340,4 +340,5 @@
ctx.Strict("COMPLIANCENOTICE_SHIPPEDLIBS", ctx.Config().HostToolPath(ctx, "compliancenotice_shippedlibs").String())
ctx.Strict("COMPLIANCE_LISTSHARE", ctx.Config().HostToolPath(ctx, "compliance_listshare").String())
ctx.Strict("COMPLIANCE_CHECKSHARE", ctx.Config().HostToolPath(ctx, "compliance_checkshare").String())
+ ctx.Strict("COMPLIANCE_SBOM", ctx.Config().HostToolPath(ctx, "compliance_sbom").String())
}
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index 7d21b75..1519f60 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -642,9 +642,13 @@
// Extracts an interface from values containing the properties to apply based on config.
// If config does not match a value with a non-nil property set, the default value will be returned.
func (s *stringVariable) PropertiesToApply(config SoongConfig, values reflect.Value) (interface{}, error) {
+ configValue := config.String(s.variable)
+ if configValue != "" && !InList(configValue, s.values) {
+ return nil, fmt.Errorf("Soong config property %q must be one of %v, found %q", s.variable, s.values, configValue)
+ }
for j, v := range s.values {
f := values.Field(j)
- if config.String(s.variable) == v && !f.Elem().IsNil() {
+ if configValue == v && !f.Elem().IsNil() {
return f.Interface(), nil
}
}
@@ -861,3 +865,13 @@
}
var emptyInterfaceType = reflect.TypeOf(emptyInterfaceStruct{}).Field(0).Type
+
+// InList checks if the string belongs to the list
+func InList(s string, list []string) bool {
+ for _, s2 := range list {
+ if s2 == s {
+ return true
+ }
+ }
+ return false
+}
diff --git a/android/soongconfig/modules_test.go b/android/soongconfig/modules_test.go
index a7800e8..d5d87ef 100644
--- a/android/soongconfig/modules_test.go
+++ b/android/soongconfig/modules_test.go
@@ -303,6 +303,10 @@
Bool_var interface{}
}
+type stringSoongConfigVars struct {
+ String_var interface{}
+}
+
func Test_PropertiesToApply(t *testing.T) {
mt, _ := newModuleType(&ModuleTypeProperties{
Module_type: "foo",
@@ -365,6 +369,51 @@
}
}
+func Test_PropertiesToApply_String_Error(t *testing.T) {
+ mt, _ := newModuleType(&ModuleTypeProperties{
+ Module_type: "foo",
+ Config_namespace: "bar",
+ Variables: []string{"string_var"},
+ Properties: []string{"a", "b"},
+ })
+ mt.Variables = append(mt.Variables, &stringVariable{
+ baseVariable: baseVariable{
+ variable: "string_var",
+ },
+ values: []string{"a", "b", "c"},
+ })
+ stringVarPositive := &properties{
+ A: proptools.StringPtr("A"),
+ B: true,
+ }
+ conditionsDefault := &properties{
+ A: proptools.StringPtr("default"),
+ B: false,
+ }
+ actualProps := &struct {
+ Soong_config_variables stringSoongConfigVars
+ }{
+ Soong_config_variables: stringSoongConfigVars{
+ String_var: &boolVarProps{
+ A: stringVarPositive.A,
+ B: stringVarPositive.B,
+ Conditions_default: conditionsDefault,
+ },
+ },
+ }
+ props := reflect.ValueOf(actualProps)
+
+ _, err := PropertiesToApply(mt, props, Config(map[string]string{
+ "string_var": "x",
+ }))
+ expected := `Soong config property "string_var" must be one of [a b c], found "x"`
+ if err == nil {
+ t.Fatalf("Expected an error, got nil")
+ } else if err.Error() != expected {
+ t.Fatalf("Error message was not correct, expected %q, got %q", expected, err.Error())
+ }
+}
+
func Test_Bp2BuildSoongConfigDefinitions(t *testing.T) {
testCases := []struct {
desc string
diff --git a/apex/apex.go b/apex/apex.go
index b039d0d..a3872d3 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -225,7 +225,7 @@
// List of JNI libraries that are embedded inside this APEX.
Jni_libs []string
- // List of rust dyn libraries
+ // List of rust dyn libraries that are embedded inside this APEX.
Rust_dyn_libs []string
// List of native executables that are embedded inside this APEX.
@@ -236,6 +236,41 @@
// List of filesystem images that are embedded inside this APEX bundle.
Filesystems []string
+
+ // List of native libraries to exclude from this APEX.
+ Exclude_native_shared_libs []string
+
+ // List of JNI libraries to exclude from this APEX.
+ Exclude_jni_libs []string
+
+ // List of rust dyn libraries to exclude from this APEX.
+ Exclude_rust_dyn_libs []string
+
+ // List of native executables to exclude from this APEX.
+ Exclude_binaries []string
+
+ // List of native tests to exclude from this APEX.
+ Exclude_tests []string
+
+ // List of filesystem images to exclude from this APEX bundle.
+ Exclude_filesystems []string
+}
+
+// Merge combines another ApexNativeDependencies into this one
+func (a *ApexNativeDependencies) Merge(b ApexNativeDependencies) {
+ a.Native_shared_libs = append(a.Native_shared_libs, b.Native_shared_libs...)
+ a.Jni_libs = append(a.Jni_libs, b.Jni_libs...)
+ a.Rust_dyn_libs = append(a.Rust_dyn_libs, b.Rust_dyn_libs...)
+ a.Binaries = append(a.Binaries, b.Binaries...)
+ a.Tests = append(a.Tests, b.Tests...)
+ a.Filesystems = append(a.Filesystems, b.Filesystems...)
+
+ a.Exclude_native_shared_libs = append(a.Exclude_native_shared_libs, b.Exclude_native_shared_libs...)
+ a.Exclude_jni_libs = append(a.Exclude_jni_libs, b.Exclude_jni_libs...)
+ a.Exclude_rust_dyn_libs = append(a.Exclude_rust_dyn_libs, b.Exclude_rust_dyn_libs...)
+ a.Exclude_binaries = append(a.Exclude_binaries, b.Exclude_binaries...)
+ a.Exclude_tests = append(a.Exclude_tests, b.Exclude_tests...)
+ a.Exclude_filesystems = append(a.Exclude_filesystems, b.Exclude_filesystems...)
}
type apexMultilibProperties struct {
@@ -675,12 +710,18 @@
// Use *FarVariation* to be able to depend on modules having conflicting variations with
// this module. This is required since arch variant of an APEX bundle is 'common' but it is
// 'arm' or 'arm64' for native shared libs.
- ctx.AddFarVariationDependencies(binVariations, executableTag, nativeModules.Binaries...)
- ctx.AddFarVariationDependencies(binVariations, testTag, nativeModules.Tests...)
- ctx.AddFarVariationDependencies(libVariations, jniLibTag, nativeModules.Jni_libs...)
- ctx.AddFarVariationDependencies(libVariations, sharedLibTag, nativeModules.Native_shared_libs...)
- ctx.AddFarVariationDependencies(rustLibVariations, sharedLibTag, nativeModules.Rust_dyn_libs...)
- ctx.AddFarVariationDependencies(target.Variations(), fsTag, nativeModules.Filesystems...)
+ ctx.AddFarVariationDependencies(binVariations, executableTag,
+ android.RemoveListFromList(nativeModules.Binaries, nativeModules.Exclude_binaries)...)
+ ctx.AddFarVariationDependencies(binVariations, testTag,
+ android.RemoveListFromList(nativeModules.Tests, nativeModules.Exclude_tests)...)
+ ctx.AddFarVariationDependencies(libVariations, jniLibTag,
+ android.RemoveListFromList(nativeModules.Jni_libs, nativeModules.Exclude_jni_libs)...)
+ ctx.AddFarVariationDependencies(libVariations, sharedLibTag,
+ android.RemoveListFromList(nativeModules.Native_shared_libs, nativeModules.Exclude_native_shared_libs)...)
+ ctx.AddFarVariationDependencies(rustLibVariations, sharedLibTag,
+ android.RemoveListFromList(nativeModules.Rust_dyn_libs, nativeModules.Exclude_rust_dyn_libs)...)
+ ctx.AddFarVariationDependencies(target.Variations(), fsTag,
+ android.RemoveListFromList(nativeModules.Filesystems, nativeModules.Exclude_filesystems)...)
}
func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
@@ -748,12 +789,12 @@
continue
}
- var depsList []ApexNativeDependencies
+ var deps ApexNativeDependencies
// Add native modules targeting both ABIs. When multilib.* is omitted for
// native_shared_libs/jni_libs/tests, it implies multilib.both
- depsList = append(depsList, a.properties.Multilib.Both)
- depsList = append(depsList, ApexNativeDependencies{
+ deps.Merge(a.properties.Multilib.Both)
+ deps.Merge(ApexNativeDependencies{
Native_shared_libs: a.properties.Native_shared_libs,
Tests: a.properties.Tests,
Jni_libs: a.properties.Jni_libs,
@@ -764,8 +805,8 @@
// binaries, it implies multilib.first
isPrimaryAbi := i == 0
if isPrimaryAbi {
- depsList = append(depsList, a.properties.Multilib.First)
- depsList = append(depsList, ApexNativeDependencies{
+ deps.Merge(a.properties.Multilib.First)
+ deps.Merge(ApexNativeDependencies{
Native_shared_libs: nil,
Tests: nil,
Jni_libs: nil,
@@ -776,34 +817,32 @@
// Add native modules targeting either 32-bit or 64-bit ABI
switch target.Arch.ArchType.Multilib {
case "lib32":
- depsList = append(depsList, a.properties.Multilib.Lib32)
- depsList = append(depsList, a.properties.Multilib.Prefer32)
+ deps.Merge(a.properties.Multilib.Lib32)
+ deps.Merge(a.properties.Multilib.Prefer32)
case "lib64":
- depsList = append(depsList, a.properties.Multilib.Lib64)
+ deps.Merge(a.properties.Multilib.Lib64)
if !has32BitTarget {
- depsList = append(depsList, a.properties.Multilib.Prefer32)
+ deps.Merge(a.properties.Multilib.Prefer32)
}
}
// Add native modules targeting a specific arch variant
switch target.Arch.ArchType {
case android.Arm:
- depsList = append(depsList, a.archProperties.Arch.Arm.ApexNativeDependencies)
+ deps.Merge(a.archProperties.Arch.Arm.ApexNativeDependencies)
case android.Arm64:
- depsList = append(depsList, a.archProperties.Arch.Arm64.ApexNativeDependencies)
+ deps.Merge(a.archProperties.Arch.Arm64.ApexNativeDependencies)
case android.Riscv64:
- depsList = append(depsList, a.archProperties.Arch.Riscv64.ApexNativeDependencies)
+ deps.Merge(a.archProperties.Arch.Riscv64.ApexNativeDependencies)
case android.X86:
- depsList = append(depsList, a.archProperties.Arch.X86.ApexNativeDependencies)
+ deps.Merge(a.archProperties.Arch.X86.ApexNativeDependencies)
case android.X86_64:
- depsList = append(depsList, a.archProperties.Arch.X86_64.ApexNativeDependencies)
+ deps.Merge(a.archProperties.Arch.X86_64.ApexNativeDependencies)
default:
panic(fmt.Errorf("unsupported arch %v\n", ctx.Arch().ArchType))
}
- for _, d := range depsList {
- addDependenciesForNativeModules(ctx, d, target, imageVariation)
- }
+ addDependenciesForNativeModules(ctx, deps, target, imageVariation)
ctx.AddFarVariationDependencies([]blueprint.Variation{
{Mutator: "os", Variation: target.OsVariation()},
{Mutator: "arch", Variation: target.ArchVariation()},
@@ -2593,6 +2632,7 @@
module.AddProperties(
&apexBundleProperties{},
&apexTargetBundleProperties{},
+ &apexArchBundleProperties{},
&overridableProperties{},
)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 2e116c7..21a71ce 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4399,12 +4399,15 @@
name: "myapex",
key: "myapex.key",
updatable: false,
+ native_shared_libs: ["mylib.generic"],
arch: {
arm64: {
native_shared_libs: ["mylib.arm64"],
+ exclude_native_shared_libs: ["mylib.generic"],
},
x86_64: {
native_shared_libs: ["mylib.x64"],
+ exclude_native_shared_libs: ["mylib.generic"],
},
}
}
@@ -4416,6 +4419,18 @@
}
cc_library {
+ name: "mylib.generic",
+ srcs: ["mylib.cpp"],
+ system_shared_libs: [],
+ stl: "none",
+ // TODO: remove //apex_available:platform
+ apex_available: [
+ "//apex_available:platform",
+ "myapex",
+ ],
+ }
+
+ cc_library {
name: "mylib.arm64",
srcs: ["mylib.cpp"],
system_shared_libs: [],
@@ -4445,6 +4460,7 @@
// Ensure that apex variant is created for the direct dep
ensureListContains(t, ctx.ModuleVariantsForTests("mylib.arm64"), "android_arm64_armv8-a_shared_apex10000")
+ ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib.generic"), "android_arm64_armv8-a_shared_apex10000")
ensureListNotContains(t, ctx.ModuleVariantsForTests("mylib.x64"), "android_arm64_armv8-a_shared_apex10000")
// Ensure that both direct and indirect deps are copied into apex
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 70308c8..39446a1 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -532,6 +532,10 @@
src = String(p.Arch.Arm64.Src)
case android.Riscv64:
src = String(p.Arch.Riscv64.Src)
+ // HACK: fall back to arm64 prebuilts, the riscv64 ones don't exist yet.
+ if src == "" {
+ src = String(p.Arch.Arm64.Src)
+ }
case android.X86:
src = String(p.Arch.X86.Src)
case android.X86_64:
diff --git a/bp2build/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go
index c860844..e8551e5 100644
--- a/bp2build/java_binary_host_conversion_test.go
+++ b/bp2build/java_binary_host_conversion_test.go
@@ -33,7 +33,7 @@
}, tc)
}
-var fs = map[string]string{
+var testFs = map[string]string{
"test.mf": "Main-Class: com.android.test.MainClass",
"other/Android.bp": `cc_library_host_shared {
name: "jni-lib-1",
@@ -44,7 +44,7 @@
func TestJavaBinaryHost(t *testing.T) {
runJavaBinaryHostTestCase(t, Bp2buildTestCase{
Description: "java_binary_host with srcs, exclude_srcs, jni_libs, javacflags, and manifest.",
- Filesystem: fs,
+ Filesystem: testFs,
Blueprint: `java_binary_host {
name: "java-binary-host-1",
srcs: ["a.java", "b.java"],
@@ -77,7 +77,7 @@
func TestJavaBinaryHostRuntimeDeps(t *testing.T) {
runJavaBinaryHostTestCase(t, Bp2buildTestCase{
Description: "java_binary_host with srcs, exclude_srcs, jni_libs, javacflags, and manifest.",
- Filesystem: fs,
+ Filesystem: testFs,
Blueprint: `java_binary_host {
name: "java-binary-host-1",
static_libs: ["java-dep-1"],
@@ -107,7 +107,7 @@
func TestJavaBinaryHostLibs(t *testing.T) {
runJavaBinaryHostTestCase(t, Bp2buildTestCase{
Description: "java_binary_host with srcs, libs.",
- Filesystem: fs,
+ Filesystem: testFs,
Blueprint: `java_binary_host {
name: "java-binary-host-libs",
libs: ["java-lib-dep-1"],
diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go
index 45817e3..81ec7ee 100644
--- a/bp2build/symlink_forest.go
+++ b/bp2build/symlink_forest.go
@@ -15,7 +15,9 @@
package bp2build
import (
+ "errors"
"fmt"
+ "io/fs"
"io/ioutil"
"os"
"path/filepath"
@@ -49,6 +51,59 @@
okay atomic.Bool // Whether the forest was successfully constructed
}
+// A simple thread pool to limit concurrency on system calls.
+// Necessary because Go spawns a new OS-level thread for each blocking system
+// call. This means that if syscalls are too slow and there are too many of
+// them, the hard limit on OS-level threads can be exhausted.
+type syscallPool struct {
+ shutdownCh []chan<- struct{}
+ workCh chan syscall
+}
+
+type syscall struct {
+ work func()
+ done chan<- struct{}
+}
+
+func createSyscallPool(count int) *syscallPool {
+ result := &syscallPool{
+ shutdownCh: make([]chan<- struct{}, count),
+ workCh: make(chan syscall),
+ }
+
+ for i := 0; i < count; i++ {
+ shutdownCh := make(chan struct{})
+ result.shutdownCh[i] = shutdownCh
+ go result.worker(shutdownCh)
+ }
+
+ return result
+}
+
+func (p *syscallPool) do(work func()) {
+ doneCh := make(chan struct{})
+ p.workCh <- syscall{work, doneCh}
+ <-doneCh
+}
+
+func (p *syscallPool) shutdown() {
+ for _, ch := range p.shutdownCh {
+ ch <- struct{}{} // Blocks until the value is received
+ }
+}
+
+func (p *syscallPool) worker(shutdownCh <-chan struct{}) {
+ for {
+ select {
+ case <-shutdownCh:
+ return
+ case work := <-p.workCh:
+ work.work()
+ work.done <- struct{}{}
+ }
+ }
+}
+
// Ensures that the node for the given path exists in the tree and returns it.
func ensureNodeExists(root *instructionsNode, path string) *instructionsNode {
if path == "" {
@@ -317,6 +372,51 @@
}
}
+func removeParallelRecursive(pool *syscallPool, path string, fi os.FileInfo, wg *sync.WaitGroup) {
+ defer wg.Done()
+
+ if fi.IsDir() {
+ children := readdirToMap(path)
+ childrenWg := &sync.WaitGroup{}
+ childrenWg.Add(len(children))
+
+ for child, childFi := range children {
+ go removeParallelRecursive(pool, shared.JoinPath(path, child), childFi, childrenWg)
+ }
+
+ childrenWg.Wait()
+ }
+
+ pool.do(func() {
+ if err := os.Remove(path); err != nil {
+ fmt.Fprintf(os.Stderr, "Cannot unlink '%s': %s\n", path, err)
+ os.Exit(1)
+ }
+ })
+}
+
+func removeParallel(path string) {
+ fi, err := os.Lstat(path)
+ if err != nil {
+ if errors.Is(err, fs.ErrNotExist) {
+ return
+ }
+
+ fmt.Fprintf(os.Stderr, "Cannot lstat '%s': %s\n", path, err)
+ os.Exit(1)
+ }
+
+ wg := &sync.WaitGroup{}
+ wg.Add(1)
+
+ // Random guess as to the best number of syscalls to run in parallel
+ pool := createSyscallPool(100)
+ removeParallelRecursive(pool, path, fi, wg)
+ pool.shutdown()
+
+ wg.Wait()
+}
+
// Creates a symlink forest by merging the directory tree at "buildFiles" and
// "srcDir" while excluding paths listed in "exclude". Returns the set of paths
// under srcDir on which readdir() had to be called to produce the symlink
@@ -330,7 +430,7 @@
context.okay.Store(true)
- os.RemoveAll(shared.JoinPath(topdir, forest))
+ removeParallel(shared.JoinPath(topdir, forest))
instructions := instructionsFromExcludePathList(exclude)
go func() {
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index eb71aa1..052832d 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -244,4 +244,8 @@
return LibclangRuntimeLibrary(t, "fuzzer")
}
+func LibFuzzerRuntimeInterceptors(t Toolchain) string {
+ return LibclangRuntimeLibrary(t, "fuzzer_interceptors")
+}
+
var inList = android.InList
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 0fbe45c..64bb7dd 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -126,6 +126,14 @@
deps.HeaderLibs = append(deps.HeaderLibs, "libafl_headers")
} else {
deps.StaticLibs = append(deps.StaticLibs, config.LibFuzzerRuntimeLibrary(ctx.toolchain()))
+ // Fuzzers built with HWASAN should use the interceptors for better
+ // mutation based on signals in strcmp, memcpy, etc. This is only needed for
+ // fuzz targets, not generic HWASAN-ified binaries or libraries.
+ if module, ok := ctx.Module().(*Module); ok {
+ if module.IsSanitizerEnabled(Hwasan) {
+ deps.StaticLibs = append(deps.StaticLibs, config.LibFuzzerRuntimeInterceptors(ctx.toolchain()))
+ }
+ }
}
deps = fuzzBin.binaryDecorator.linkerDeps(ctx, deps)
@@ -137,9 +145,18 @@
// RunPaths on devices isn't instantiated by the base linker. `../lib` for
// installed fuzz targets (both host and device), and `./lib` for fuzz
// target packages.
- flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/lib`)
+ // When running on device, fuzz targets with vendor: true set will be in
+ // fuzzer_name/vendor/fuzzer_name (note the extra 'vendor' and thus need to
+ // link with libraries in ../../lib/. Non-vendor binaries only need to look
+ // one level up, in ../lib/.
+ if ctx.inVendor() {
+ flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../../lib`)
+ } else {
+ flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
+ }
+
return flags
}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 2cea5a5..0669f65 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -244,7 +244,7 @@
ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
// Create soong_injection repository
- soongInjectionFiles := bp2build.CreateSoongInjectionFiles(configuration, bp2build.CodegenMetrics{})
+ soongInjectionFiles := bp2build.CreateSoongInjectionFiles(configuration, bp2build.CreateCodegenMetrics())
absoluteSoongInjectionDir := shared.JoinPath(topDir, configuration.SoongOutDir(), bazel.SoongInjectionDirName)
for _, file := range soongInjectionFiles {
writeReadOnlyFile(absoluteSoongInjectionDir, file)
diff --git a/java/app_set.go b/java/app_set.go
index d99fadb..d8c2a8d 100644
--- a/java/app_set.go
+++ b/java/app_set.go
@@ -90,9 +90,10 @@
}
var TargetCpuAbi = map[string]string{
- "arm": "ARMEABI_V7A",
- "arm64": "ARM64_V8A",
- "riscv64": "RISCV64",
+ "arm": "ARMEABI_V7A",
+ "arm64": "ARM64_V8A",
+ // TODO: use "RISCV64" when that is supported in bundles
+ "riscv64": "ARM64_V8A",
"x86": "X86",
"x86_64": "X86_64",
}
diff --git a/java/base.go b/java/base.go
index 96f36e8..602e8d8 100644
--- a/java/base.go
+++ b/java/base.go
@@ -593,6 +593,8 @@
return android.Paths{j.outputFile}, nil
case ".jar":
return android.Paths{j.implementationAndResourcesJar}, nil
+ case ".hjar":
+ return android.Paths{j.headerJarFile}, nil
case ".proguard_map":
if j.dexer.proguardDictionary.Valid() {
return android.Paths{j.dexer.proguardDictionary.Path()}, nil
diff --git a/symbol_inject/macho.go b/symbol_inject/macho.go
index 9946d34..ca3d50e 100644
--- a/symbol_inject/macho.go
+++ b/symbol_inject/macho.go
@@ -16,9 +16,12 @@
import (
"debug/macho"
+ "encoding/binary"
"fmt"
"io"
+ "os"
"os/exec"
+ "path/filepath"
"sort"
"strings"
)
@@ -98,6 +101,80 @@
}
func CodeSignMachoFile(path string) error {
- cmd := exec.Command("/usr/bin/codesign", "--force", "-s", "-", path)
- return cmd.Run()
+ filename := filepath.Base(path)
+ cmd := exec.Command("/usr/bin/codesign", "--force", "-s", "-", "-i", filename, path)
+ if err := cmd.Run(); err != nil {
+ return err
+ }
+ return modifyCodeSignFlags(path)
+}
+
+const LC_CODE_SIGNATURE = 0x1d
+const CSSLOT_CODEDIRECTORY = 0
+
+// To make codesign not invalidated by stripping, modify codesign flags to 0x20002
+// (adhoc | linkerSigned).
+func modifyCodeSignFlags(path string) error {
+ f, err := os.OpenFile(path, os.O_RDWR, 0)
+ if err != nil {
+ return err
+ }
+ defer f.Close()
+
+ // Step 1: find code signature section.
+ machoFile, err := macho.NewFile(f)
+ if err != nil {
+ return err
+ }
+ var codeSignSectionOffset uint32 = 0
+ var codeSignSectionSize uint32 = 0
+ for _, l := range machoFile.Loads {
+ data := l.Raw()
+ cmd := machoFile.ByteOrder.Uint32(data)
+ if cmd == LC_CODE_SIGNATURE {
+ codeSignSectionOffset = machoFile.ByteOrder.Uint32(data[8:])
+ codeSignSectionSize = machoFile.ByteOrder.Uint32(data[12:])
+ }
+ }
+ if codeSignSectionOffset == 0 {
+ return fmt.Errorf("code signature section not found")
+ }
+
+ data := make([]byte, codeSignSectionSize)
+ _, err = f.ReadAt(data, int64(codeSignSectionOffset))
+ if err != nil {
+ return err
+ }
+
+ // Step 2: get flags offset.
+ blobCount := binary.BigEndian.Uint32(data[8:])
+ off := 12
+ var codeDirectoryOff uint32 = 0
+ for blobCount > 0 {
+ blobType := binary.BigEndian.Uint32(data[off:])
+ if blobType == CSSLOT_CODEDIRECTORY {
+ codeDirectoryOff = binary.BigEndian.Uint32(data[off+4:])
+ break
+ }
+ blobCount--
+ off += 8
+ }
+ if codeDirectoryOff == 0 {
+ return fmt.Errorf("no code directory in code signature section")
+ }
+ flagsOff := codeSignSectionOffset + codeDirectoryOff + 12
+
+ // Step 3: modify flags.
+ flagsData := make([]byte, 4)
+ _, err = f.ReadAt(flagsData, int64(flagsOff))
+ if err != nil {
+ return err
+ }
+ oldFlags := binary.BigEndian.Uint32(flagsData)
+ if oldFlags != 0x2 {
+ return fmt.Errorf("unexpected flags in code signature section: 0x%x", oldFlags)
+ }
+ binary.BigEndian.PutUint32(flagsData, 0x20002)
+ _, err = f.WriteAt(flagsData, int64(flagsOff))
+ return err
}
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index 2331eb1..ba5ba8b 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -547,7 +547,6 @@
function test_bp2build_generates_marker_file {
setup
- create_mock_bazel
run_soong bp2build
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
index ad21d7d..679ac55 100755
--- a/tests/bp2build_bazel_test.sh
+++ b/tests/bp2build_bazel_test.sh
@@ -50,7 +50,6 @@
function test_different_relative_outdir {
setup
- create_mock_bazel
mkdir -p a
touch a/g.txt
@@ -73,7 +72,6 @@
function test_different_absolute_outdir {
setup
- create_mock_bazel
mkdir -p a
touch a/g.txt
@@ -96,7 +94,6 @@
function test_bp2build_generates_all_buildfiles {
setup
- create_mock_bazel
mkdir -p foo/convertible_soong_module
cat > foo/convertible_soong_module/Android.bp <<'EOF'
@@ -167,7 +164,6 @@
function test_cc_correctness {
setup
- create_mock_bazel
mkdir -p a
cat > a/Android.bp <<EOF
diff --git a/tests/lib.sh b/tests/lib.sh
index 006186a..e40f0ad 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -82,10 +82,10 @@
}
function create_mock_soong {
+ create_mock_bazel
copy_directory build/blueprint
copy_directory build/soong
copy_directory build/make/tools/rbcrun
- copy_directory prebuilts/bazel/common/proto
symlink_directory prebuilts/sdk
symlink_directory prebuilts/go
diff --git a/tests/mixed_mode_test.sh b/tests/mixed_mode_test.sh
index 076ec4b..8949b42 100755
--- a/tests/mixed_mode_test.sh
+++ b/tests/mixed_mode_test.sh
@@ -12,7 +12,6 @@
function test_bazel_smoke {
setup
- create_mock_bazel
run_soong bp2build
@@ -21,7 +20,6 @@
function test_add_irrelevant_file {
setup
- create_mock_bazel
mkdir -p soong_tests/a/b
touch soong_tests/a/b/c.txt
@@ -33,7 +31,7 @@
}
EOF
- run_soong --bazel-mode nothing
+ run_soong --bazel-mode-staging nothing
if [[ ! -e out/soong/bp2build/soong_tests/a/b/BUILD.bazel ]]; then
fail "BUILD.bazel not created"
@@ -48,7 +46,7 @@
touch soong_tests/a/irrelevant.txt
- run_soong --bazel-mode nothing
+ run_soong --bazel-mode-staging nothing
local mtime_build2=$(stat -c "%y" out/soong/bp2build/soong_tests/a/b/BUILD.bazel)
local mtime_ninja2=$(stat -c "%y" out/soong/build.ninja)
diff --git a/ui/build/config.go b/ui/build/config.go
index 36119f0..de10112 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -236,6 +236,19 @@
return nil
}
+func defaultBazelProdMode(cfg *configImpl) bool {
+ // Envirnoment flag to disable Bazel for users which experience
+ // broken bazel-handled builds, or significant performance regressions.
+ if cfg.IsBazelMixedBuildForceDisabled() {
+ return false
+ }
+ // Darwin-host builds are currently untested with Bazel.
+ if runtime.GOOS == "darwin" {
+ return false
+ }
+ return true
+}
+
func NewConfig(ctx Context, args ...string) Config {
ret := &configImpl{
environ: OsEnvironment(),
@@ -774,6 +787,9 @@
c.arguments = append(c.arguments, arg)
}
}
+ if (!c.bazelProdMode) && (!c.bazelDevMode) && (!c.bazelStagingMode) {
+ c.bazelProdMode = defaultBazelProdMode(c)
+ }
}
func (c *configImpl) configureLocale(ctx Context) {
diff --git a/ui/build/config_test.go b/ui/build/config_test.go
index 968544b..940d85c 100644
--- a/ui/build/config_test.go
+++ b/ui/build/config_test.go
@@ -90,7 +90,9 @@
t.Fatal(err)
})
+ env := Environment([]string{})
c := &configImpl{
+ environ: &env,
parallel: -1,
keepGoing: -1,
}