Merge "Rename ApexCqueryInfo to ApexInfo"
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/config.go b/android/config.go
index df2c767..50f63ea 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1109,7 +1109,7 @@
return c.config.productVariables.WithDexpreopt
}
-func (c *config) FrameworksBaseDirExists(ctx PathContext) bool {
+func (c *config) FrameworksBaseDirExists(ctx PathGlobContext) bool {
return ExistentPathForSource(ctx, "frameworks", "base", "Android.bp").Valid()
}
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/ninja_deps_test.go b/android/ninja_deps_test.go
index 947c257..d6afcc0 100644
--- a/android/ninja_deps_test.go
+++ b/android/ninja_deps_test.go
@@ -18,21 +18,6 @@
"testing"
)
-func init() {
- // This variable uses ExistentPathForSource on a PackageVarContext, which is a PathContext
- // that is not a PathGlobContext. That requires the deps to be stored in the Config.
- pctx.VariableFunc("test_ninja_deps_variable", func(ctx PackageVarContext) string {
- // Using ExistentPathForSource to look for a file that does not exist in a directory that
- // does exist (test_ninja_deps) from a PackageVarContext adds a dependency from build.ninja
- // to the directory.
- if ExistentPathForSource(ctx, "test_ninja_deps/does_not_exist").Valid() {
- return "true"
- } else {
- return "false"
- }
- })
-}
-
func testNinjaDepsSingletonFactory() Singleton {
return testNinjaDepsSingleton{}
}
@@ -40,33 +25,19 @@
type testNinjaDepsSingleton struct{}
func (testNinjaDepsSingleton) GenerateBuildActions(ctx SingletonContext) {
- // Reference the test_ninja_deps_variable in a build statement so Blueprint is forced to
- // evaluate it.
- ctx.Build(pctx, BuildParams{
- Rule: Cp,
- Input: PathForTesting("foo"),
- Output: PathForOutput(ctx, "test_ninja_deps_out"),
- Args: map[string]string{
- "cpFlags": "${test_ninja_deps_variable}",
- },
- })
+ ctx.Config().addNinjaFileDeps("foo")
}
func TestNinjaDeps(t *testing.T) {
- fs := MockFS{
- "test_ninja_deps/exists": nil,
- }
-
result := GroupFixturePreparers(
FixtureRegisterWithContext(func(ctx RegistrationContext) {
ctx.RegisterSingletonType("test_ninja_deps_singleton", testNinjaDepsSingletonFactory)
ctx.RegisterSingletonType("ninja_deps_singleton", ninjaDepsSingletonFactory)
}),
- fs.AddToFixture(),
).RunTest(t)
// Verify that the ninja file has a dependency on the test_ninja_deps directory.
- if g, w := result.NinjaDeps, "test_ninja_deps"; !InList(w, g) {
+ if g, w := result.NinjaDeps, "foo"; !InList(w, g) {
t.Errorf("expected %q in %q", w, g)
}
}
diff --git a/android/package_ctx.go b/android/package_ctx.go
index f354db8..c348c82 100644
--- a/android/package_ctx.go
+++ b/android/package_ctx.go
@@ -48,7 +48,7 @@
var _ PathContext = &configErrorWrapper{}
var _ errorfContext = &configErrorWrapper{}
-var _ PackageVarContext = &configErrorWrapper{}
+var _ PackageVarContext = &variableFuncContextWrapper{}
var _ PackagePoolContext = &configErrorWrapper{}
var _ PackageRuleContext = &configErrorWrapper{}
@@ -62,21 +62,33 @@
e.config.addNinjaFileDeps(deps...)
}
-type PackageVarContext interface {
+type variableFuncContextWrapper struct {
+ configErrorWrapper
+ blueprint.VariableFuncContext
+}
+
+type PackagePoolContext interface {
PathContext
errorfContext
}
-type PackagePoolContext PackageVarContext
-type PackageRuleContext PackageVarContext
+type PackageRuleContext PackagePoolContext
+
+type PackageVarContext interface {
+ PackagePoolContext
+ PathGlobContext
+}
// VariableFunc wraps blueprint.PackageContext.VariableFunc, converting the interface{} config
// argument to a PackageVarContext.
func (p PackageContext) VariableFunc(name string,
f func(PackageVarContext) string) blueprint.Variable {
- return p.PackageContext.VariableFunc(name, func(config interface{}) (string, error) {
- ctx := &configErrorWrapper{p, config.(Config), nil}
+ return p.PackageContext.VariableFunc(name, func(bpctx blueprint.VariableFuncContext, config interface{}) (string, error) {
+ ctx := &variableFuncContextWrapper{
+ configErrorWrapper: configErrorWrapper{p, config.(Config), nil},
+ VariableFuncContext: bpctx,
+ }
ret := f(ctx)
if len(ctx.errors) > 0 {
return "", ctx.errors[0]
diff --git a/android/paths.go b/android/paths.go
index 375297f..a6a54fa 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -39,6 +39,7 @@
}
type PathGlobContext interface {
+ PathContext
GlobWithDeps(globPattern string, excludes []string) ([]string, error)
}
@@ -56,7 +57,6 @@
// EarlyModulePathContext is a subset of EarlyModuleContext methods required by the
// Path methods. These path methods can be called before any mutators have run.
type EarlyModulePathContext interface {
- PathContext
PathGlobContext
ModuleDir() string
@@ -375,7 +375,7 @@
// ExistentPathsForSources returns a list of Paths rooted from SrcDir, *not* rooted from the
// module's local source directory, that are found in the tree. If any are not found, they are
// omitted from the list, and dependencies are added so that we're re-run when they are added.
-func ExistentPathsForSources(ctx PathContext, paths []string) Paths {
+func ExistentPathsForSources(ctx PathGlobContext, paths []string) Paths {
ret := make(Paths, 0, len(paths))
for _, path := range paths {
p := ExistentPathForSource(ctx, path)
@@ -1087,21 +1087,12 @@
// existsWithDependencies returns true if the path exists, and adds appropriate dependencies to rerun if the
// path does not exist.
-func existsWithDependencies(ctx PathContext, path SourcePath) (exists bool, err error) {
+func existsWithDependencies(ctx PathGlobContext, path SourcePath) (exists bool, err error) {
var files []string
- if gctx, ok := ctx.(PathGlobContext); ok {
- // Use glob to produce proper dependencies, even though we only want
- // a single file.
- files, err = gctx.GlobWithDeps(path.String(), nil)
- } else {
- var result pathtools.GlobResult
- // We cannot add build statements in this context, so we fall back to
- // AddNinjaFileDeps
- result, err = ctx.Config().fs.Glob(path.String(), nil, pathtools.FollowSymlinks)
- ctx.AddNinjaFileDeps(result.Deps...)
- files = result.Matches
- }
+ // Use glob to produce proper dependencies, even though we only want
+ // a single file.
+ files, err = ctx.GlobWithDeps(path.String(), nil)
if err != nil {
return false, fmt.Errorf("glob: %s", err.Error())
@@ -1124,7 +1115,7 @@
}
if modCtx, ok := ctx.(ModuleMissingDepsPathContext); ok && ctx.Config().AllowMissingDependencies() {
- exists, err := existsWithDependencies(ctx, path)
+ exists, err := existsWithDependencies(modCtx, path)
if err != nil {
reportPathError(ctx, err)
}
@@ -1158,7 +1149,7 @@
// rooted from the module's local source directory, if the path exists, or an empty OptionalPath if
// it doesn't exist. Dependencies are added so that the ninja file will be regenerated if the state
// of the path changes.
-func ExistentPathForSource(ctx PathContext, pathComponents ...string) OptionalPath {
+func ExistentPathForSource(ctx PathGlobContext, pathComponents ...string) OptionalPath {
path, err := pathForSource(ctx, pathComponents...)
if err != nil {
reportPathError(ctx, err)
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 b5b3c2f..10adf8d 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4398,12 +4398,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"],
},
}
}
@@ -4415,6 +4418,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: [],
@@ -4444,6 +4459,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/cc/config/global.go b/cc/config/global.go
index cf60414..9f18784 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -76,9 +76,6 @@
// Help catch common 32/64-bit errors.
"-Werror=int-conversion",
- // Enable the new pass manager.
- "-fexperimental-new-pass-manager",
-
// Disable overly aggressive warning for macros defined with a leading underscore
// This happens in AndroidConfig.h, which is included nearly everywhere.
// TODO: can we remove this now?
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/cc/ndk_library.go b/cc/ndk_library.go
index 49a919e..d704e32 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -307,6 +307,7 @@
impl, ok := dep.(*Module)
if !ok {
ctx.ModuleErrorf("Implementation for stub is not correct module type")
+ return nil
}
output := impl.UnstrippedOutputFile()
if output == nil {
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/licenses/Android.bp b/licenses/Android.bp
index 2e5c361..54981e1 100644
--- a/licenses/Android.bp
+++ b/licenses/Android.bp
@@ -1152,7 +1152,7 @@
license_kind {
name: "SPDX-license-identifier-WTFPL",
- conditions: ["notice"],
+ conditions: ["permissive"],
url: "https://spdx.org/licenses/WTFPL.html",
}
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 ba5ba8b..d89e6b7 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -285,6 +285,35 @@
}
+function test_create_global_include_directory() {
+ setup
+ run_soong
+ local mtime1=$(stat -c "%y" out/soong/build.ninja)
+
+ # Soong needs to know if top level directories like hardware/ exist for use
+ # as global include directories. Make sure that doesn't cause regens for
+ # unrelated changes to the top level directory.
+ mkdir -p system/core
+
+ run_soong
+ local mtime2=$(stat -c "%y" out/soong/build.ninja)
+ if [[ "$mtime1" != "$mtime2" ]]; then
+ fail "Output Ninja file changed when top level directory changed"
+ fi
+
+ # Make sure it does regen if a missing directory in the path of a global
+ # include directory is added.
+ mkdir -p system/core/include
+
+ run_soong
+ local mtime3=$(stat -c "%y" out/soong/build.ninja)
+ if [[ "$mtime2" = "$mtime3" ]]; then
+ fail "Output Ninja file did not change when global include directory created"
+ fi
+
+}
+
+
function test_add_file_to_soong_build() {
setup
run_soong
@@ -874,6 +903,7 @@
test_add_file_to_soong_build
test_glob_during_bootstrapping
test_soong_build_rerun_iff_environment_changes
+test_create_global_include_directory
test_multiple_soong_build_modes
test_dump_json_module_graph
test_json_module_graph_back_and_forth_null_build