diff options
| -rw-r--r-- | android/api_levels.go | 20 | ||||
| -rw-r--r-- | android/filegroup.go | 20 | ||||
| -rw-r--r-- | android/mutator.go | 14 | ||||
| -rw-r--r-- | android/sdk.go | 6 | ||||
| -rw-r--r-- | apex/apex.go | 3 | ||||
| -rw-r--r-- | apex/apex_test.go | 98 | ||||
| -rw-r--r-- | bazel/properties.go | 2 | ||||
| -rw-r--r-- | bp2build/testing.go | 50 | ||||
| -rw-r--r-- | cc/cc_test.go | 20 | ||||
| -rw-r--r-- | cc/library.go | 8 | ||||
| -rw-r--r-- | cc/vendor_snapshot.go | 39 | ||||
| -rw-r--r-- | cc/vendor_snapshot_test.go | 15 | ||||
| -rw-r--r-- | filesystem/filesystem.go | 35 | ||||
| -rw-r--r-- | genrule/genrule.go | 19 | ||||
| -rw-r--r-- | java/dexpreopt_bootjars.go | 5 | ||||
| -rw-r--r-- | java/hiddenapi_singleton.go | 62 | ||||
| -rw-r--r-- | java/hiddenapi_singleton_test.go | 56 | ||||
| -rw-r--r-- | java/java.go | 35 | ||||
| -rw-r--r-- | rust/binary.go | 1 | ||||
| -rw-r--r-- | rust/compiler.go | 6 | ||||
| -rw-r--r-- | rust/library.go | 2 | ||||
| -rw-r--r-- | rust/rust.go | 48 | ||||
| -rw-r--r-- | rust/rust_test.go | 7 | ||||
| -rw-r--r-- | sdk/java_sdk_test.go | 7 | ||||
| -rw-r--r-- | sdk/update.go | 16 | ||||
| -rw-r--r-- | zip/zip.go | 3 | ||||
| -rw-r--r-- | zip/zip_test.go | 14 |
27 files changed, 429 insertions, 182 deletions
diff --git a/android/api_levels.go b/android/api_levels.go index 1b53f3f2a..2f6a9d29d 100644 --- a/android/api_levels.go +++ b/android/api_levels.go @@ -24,6 +24,8 @@ func init() { RegisterSingletonType("api_levels", ApiLevelsSingleton) } +const previewAPILevelBase = 9000 + // An API level, which may be a finalized (numbered) API, a preview (codenamed) // API, or the future API level (10000). Can be parsed from a string with // ApiLevelFromUser or ApiLevelOrPanic. @@ -57,6 +59,21 @@ func (this ApiLevel) FinalOrFutureInt() int { } } +// FinalOrPreviewInt distinguishes preview versions from "current" (future). +// This is for "native" stubs and should be in sync with ndkstubgen/getApiLevelsMap(). +// - "current" -> future (10000) +// - preview codenames -> preview base (9000) + index +// - otherwise -> cast to int +func (this ApiLevel) FinalOrPreviewInt() int { + if this.IsCurrent() { + return this.number + } + if this.IsPreview() { + return previewAPILevelBase + this.number + } + return this.number +} + // Returns the canonical name for this API level. For a finalized API level // this will be the API number as a string. For a preview API level this // will be the codename, or "current". @@ -282,7 +299,6 @@ var apiLevelsMapKey = NewOnceKey("ApiLevelsMap") func getApiLevelsMap(config Config) map[string]int { return config.Once(apiLevelsMapKey, func() interface{} { - baseApiLevel := 9000 apiLevelsMap := map[string]int{ "G": 9, "I": 14, @@ -302,7 +318,7 @@ func getApiLevelsMap(config Config) map[string]int { "R": 30, } for i, codename := range config.PlatformVersionActiveCodenames() { - apiLevelsMap[codename] = baseApiLevel + i + apiLevelsMap[codename] = previewAPILevelBase + i } return apiLevelsMap diff --git a/android/filegroup.go b/android/filegroup.go index 7a6cc4ffc..b36238cd1 100644 --- a/android/filegroup.go +++ b/android/filegroup.go @@ -17,8 +17,6 @@ package android import ( "android/soong/bazel" "strings" - - "github.com/google/blueprint/proptools" ) func init() { @@ -28,7 +26,6 @@ func init() { // https://docs.bazel.build/versions/master/be/general.html#filegroup type bazelFilegroupAttributes struct { - Name *string Srcs bazel.LabelList } @@ -50,20 +47,23 @@ func (bfg *bazelFilegroup) Name() string { func (bfg *bazelFilegroup) GenerateAndroidBuildActions(ctx ModuleContext) {} -// TODO: Create helper functions to avoid this boilerplate. func FilegroupBp2Build(ctx TopDownMutatorContext) { fg, ok := ctx.Module().(*fileGroup) if !ok { return } - - name := "__bp2build__" + fg.base().BaseModuleName() - ctx.CreateModule(BazelFileGroupFactory, &bazelFilegroupAttributes{ - Name: proptools.StringPtr(name), + attrs := &bazelFilegroupAttributes{ Srcs: BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs), - }, &bazel.BazelTargetModuleProperties{ + } + + // Can we automate this? + name := "__bp2build__" + fg.Name() + props := bazel.BazelTargetModuleProperties{ + Name: &name, Rule_class: "filegroup", - }) + } + + ctx.CreateBazelTargetModule(BazelFileGroupFactory, props, attrs) } type fileGroupProperties struct { diff --git a/android/mutator.go b/android/mutator.go index 15be65f9a..91753d17d 100644 --- a/android/mutator.go +++ b/android/mutator.go @@ -15,6 +15,7 @@ package android import ( + "android/soong/bazel" "reflect" "github.com/google/blueprint" @@ -275,6 +276,12 @@ type TopDownMutatorContext interface { // CreateModule creates a new module by calling the factory method for the specified moduleType, and applies // the specified property structs to it as if the properties were set in a blueprint file. CreateModule(ModuleFactory, ...interface{}) Module + + // CreateBazelTargetModule creates a BazelTargetModule by calling the + // factory method, just like in CreateModule, but also requires + // BazelTargetModuleProperties containing additional metadata for the + // bp2build codegenerator. + CreateBazelTargetModule(ModuleFactory, bazel.BazelTargetModuleProperties, interface{}) BazelTargetModule } type topDownMutatorContext struct { @@ -502,6 +509,13 @@ func registerDepsMutatorBp2Build(ctx RegisterMutatorsContext) { ctx.BottomUp("deps", depsMutator).Parallel() } +func (t *topDownMutatorContext) CreateBazelTargetModule( + factory ModuleFactory, + bazelProps bazel.BazelTargetModuleProperties, + attrs interface{}) BazelTargetModule { + return t.CreateModule(factory, &bazelProps, attrs).(BazelTargetModule) +} + func (t *topDownMutatorContext) AppendProperties(props ...interface{}) { for _, p := range props { err := proptools.AppendMatchingProperties(t.Module().base().customizableProperties, diff --git a/android/sdk.go b/android/sdk.go index bab0ed8fd..f2cdc880b 100644 --- a/android/sdk.go +++ b/android/sdk.go @@ -177,12 +177,6 @@ type SnapshotBuilder interface { // to the zip CopyToSnapshot(src Path, dest string) - // Return the path to an empty file. - // - // This can be used by sdk member types that need to create an empty file in the snapshot, simply - // pass the value returned from this to the CopyToSnapshot() method. - EmptyFile() Path - // Unzip the supplied zip into the snapshot relative directory destDir. UnzipToSnapshot(zipPath Path, destDir string) diff --git a/apex/apex.go b/apex/apex.go index 724a50b00..cfeac72a0 100644 --- a/apex/apex.go +++ b/apex/apex.go @@ -2348,7 +2348,6 @@ func makeApexAvailableBaseline() map[string][]string { "libFraunhoferAAC", "libaudio-a2dp-hw-utils", "libaudio-hearing-aid-hw-utils", - "libbinder_headers", "libbluetooth", "libbluetooth-types", "libbluetooth-types-header", @@ -2479,7 +2478,6 @@ func makeApexAvailableBaseline() map[string][]string { "libaudiopolicy", "libaudioutils", "libaudioutils_fixedfft", - "libbinder_headers", "libbluetooth-types-header", "libbufferhub", "libbufferhub_headers", @@ -2595,7 +2593,6 @@ func makeApexAvailableBaseline() map[string][]string { "libavcenc", "libavservices_minijail", "libavservices_minijail", - "libbinder_headers", "libbinderthreadstateutils", "libbluetooth-types-header", "libbufferhub_headers", diff --git a/apex/apex_test.go b/apex/apex_test.go index 7f5be7ec5..9f8cd0654 100644 --- a/apex/apex_test.go +++ b/apex/apex_test.go @@ -994,6 +994,80 @@ func TestApexWithStubsWithMinSdkVersion(t *testing.T) { }) } +func TestApex_PlatformUsesLatestStubFromApex(t *testing.T) { + t.Parallel() + // myapex (Z) + // mylib -----------------. + // | + // otherapex (29) | + // libstub's versions: 29 Z current + // | + // <platform> | + // libplatform ----------------' + ctx, _ := testApex(t, ` + apex { + name: "myapex", + key: "myapex.key", + native_shared_libs: ["mylib"], + min_sdk_version: "Z", // non-final + } + + cc_library { + name: "mylib", + srcs: ["mylib.cpp"], + shared_libs: ["libstub"], + apex_available: ["myapex"], + min_sdk_version: "Z", + } + + apex_key { + name: "myapex.key", + public_key: "testkey.avbpubkey", + private_key: "testkey.pem", + } + + apex { + name: "otherapex", + key: "myapex.key", + native_shared_libs: ["libstub"], + min_sdk_version: "29", + } + + cc_library { + name: "libstub", + srcs: ["mylib.cpp"], + stubs: { + versions: ["29", "Z", "current"], + }, + apex_available: ["otherapex"], + min_sdk_version: "29", + } + + // platform module depending on libstub from otherapex should use the latest stub("current") + cc_library { + name: "libplatform", + srcs: ["mylib.cpp"], + shared_libs: ["libstub"], + } + `, func(fs map[string][]byte, config android.Config) { + config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("Z") + config.TestProductVariables.Platform_sdk_final = proptools.BoolPtr(false) + config.TestProductVariables.Platform_version_active_codenames = []string{"Z"} + }) + + // Ensure that mylib from myapex is built against "min_sdk_version" stub ("Z"), which is non-final + mylibCflags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"] + ensureContains(t, mylibCflags, "-D__LIBSTUB_API__=9000 ") + mylibLdflags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"] + ensureContains(t, mylibLdflags, "libstub/android_arm64_armv8-a_shared_Z/libstub.so ") + + // Ensure that libplatform is built against latest stub ("current") of mylib3 from the apex + libplatformCflags := ctx.ModuleForTests("libplatform", "android_arm64_armv8-a_static").Rule("cc").Args["cFlags"] + ensureContains(t, libplatformCflags, "-D__LIBSTUB_API__=10000 ") // "current" maps to 10000 + libplatformLdflags := ctx.ModuleForTests("libplatform", "android_arm64_armv8-a_shared").Rule("ld").Args["libFlags"] + ensureContains(t, libplatformLdflags, "libstub/android_arm64_armv8-a_shared_current/libstub.so ") +} + func TestApexWithExplicitStubsDependency(t *testing.T) { ctx, _ := testApex(t, ` apex { @@ -4288,7 +4362,7 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) { // Empty transformation. } - checkDexJarBuildPath := func(ctx *android.TestContext, name string) { + checkDexJarBuildPath := func(t *testing.T, ctx *android.TestContext, name string) { // Make sure the import has been given the correct path to the dex jar. p := ctx.ModuleForTests(name, "android_common_myapex").Module().(java.Dependency) dexJarBuildPath := p.DexJarBuildPath() @@ -4297,7 +4371,7 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) { } } - ensureNoSourceVariant := func(ctx *android.TestContext) { + ensureNoSourceVariant := func(t *testing.T, ctx *android.TestContext) { // Make sure that an apex variant is not created for the source module. if expected, actual := []string{"android_common"}, ctx.ModuleVariantsForTests("libfoo"); !reflect.DeepEqual(expected, actual) { t.Errorf("invalid set of variants for %q: expected %q, found %q", "libfoo", expected, actual) @@ -4328,7 +4402,7 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) { // Make sure that dexpreopt can access dex implementation files from the prebuilt. ctx := testDexpreoptWithApexes(t, bp, "", transform) - checkDexJarBuildPath(ctx, "libfoo") + checkDexJarBuildPath(t, ctx, "libfoo") }) t.Run("prebuilt with source preferred", func(t *testing.T) { @@ -4360,8 +4434,8 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) { // Make sure that dexpreopt can access dex implementation files from the prebuilt. ctx := testDexpreoptWithApexes(t, bp, "", transform) - checkDexJarBuildPath(ctx, "prebuilt_libfoo") - ensureNoSourceVariant(ctx) + checkDexJarBuildPath(t, ctx, "prebuilt_libfoo") + ensureNoSourceVariant(t, ctx) }) t.Run("prebuilt preferred with source", func(t *testing.T) { @@ -4393,8 +4467,8 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) { // Make sure that dexpreopt can access dex implementation files from the prebuilt. ctx := testDexpreoptWithApexes(t, bp, "", transform) - checkDexJarBuildPath(ctx, "prebuilt_libfoo") - ensureNoSourceVariant(ctx) + checkDexJarBuildPath(t, ctx, "prebuilt_libfoo") + ensureNoSourceVariant(t, ctx) }) } @@ -4403,7 +4477,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { config.BootJars = android.CreateTestConfiguredJarList([]string{"myapex:libfoo"}) } - checkBootDexJarPath := func(ctx *android.TestContext, bootDexJarPath string) { + checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, bootDexJarPath string) { s := ctx.SingletonForTests("dex_bootjars") foundLibfooJar := false for _, output := range s.AllOutputs() { @@ -4444,7 +4518,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { ` ctx := testDexpreoptWithApexes(t, bp, "", transform) - checkBootDexJarPath(ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") + checkBootDexJarPath(t, ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") }) t.Run("prebuilt with source library preferred", func(t *testing.T) { @@ -4513,7 +4587,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { ` ctx := testDexpreoptWithApexes(t, bp, "", transform) - checkBootDexJarPath(ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") + checkBootDexJarPath(t, ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") }) t.Run("prebuilt with source apex preferred", func(t *testing.T) { @@ -4557,7 +4631,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { ` ctx := testDexpreoptWithApexes(t, bp, "", transform) - checkBootDexJarPath(ctx, ".intermediates/libfoo/android_common_apex10000/aligned/libfoo.jar") + checkBootDexJarPath(t, ctx, ".intermediates/libfoo/android_common_apex10000/aligned/libfoo.jar") }) t.Run("prebuilt preferred with source apex disabled", func(t *testing.T) { @@ -4603,7 +4677,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) { ` ctx := testDexpreoptWithApexes(t, bp, "", transform) - checkBootDexJarPath(ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") + checkBootDexJarPath(t, ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar") }) } diff --git a/bazel/properties.go b/bazel/properties.go index 5b98d159d..fbbbfe6f6 100644 --- a/bazel/properties.go +++ b/bazel/properties.go @@ -29,6 +29,8 @@ type Properties struct { // BazelTargetModuleProperties contain properties and metadata used for // Blueprint to BUILD file conversion. type BazelTargetModuleProperties struct { + Name *string + // The Bazel rule class for this target. Rule_class string diff --git a/bp2build/testing.go b/bp2build/testing.go index 5e6481b32..b5f5448be 100644 --- a/bp2build/testing.go +++ b/bp2build/testing.go @@ -3,8 +3,6 @@ package bp2build import ( "android/soong/android" "android/soong/bazel" - - "github.com/google/blueprint/proptools" ) type nestedProps struct { @@ -105,7 +103,6 @@ func customDefaultsModuleFactory() android.Module { } type customBazelModuleAttributes struct { - Name *string String_prop string String_list_prop []string } @@ -127,14 +124,18 @@ func (m *customBazelModule) GenerateAndroidBuildActions(ctx android.ModuleContex func customBp2BuildMutator(ctx android.TopDownMutatorContext) { if m, ok := ctx.Module().(*customModule); ok { - name := "__bp2build__" + m.Name() - ctx.CreateModule(customBazelModuleFactory, &customBazelModuleAttributes{ - Name: proptools.StringPtr(name), + attrs := &customBazelModuleAttributes{ String_prop: m.props.String_prop, String_list_prop: m.props.String_list_prop, - }, &bazel.BazelTargetModuleProperties{ + } + + name := "__bp2build__" + m.Name() + props := bazel.BazelTargetModuleProperties{ + Name: &name, Rule_class: "custom", - }) + } + + ctx.CreateBazelTargetModule(customBazelModuleFactory, props, attrs) } } @@ -142,24 +143,31 @@ func customBp2BuildMutator(ctx android.TopDownMutatorContext) { // module to target. func customBp2BuildMutatorFromStarlark(ctx android.TopDownMutatorContext) { if m, ok := ctx.Module().(*customModule); ok { - baseName := "__bp2build__" + m.Name() - ctx.CreateModule(customBazelModuleFactory, &customBazelModuleAttributes{ - Name: proptools.StringPtr(baseName), - }, &bazel.BazelTargetModuleProperties{ + baseName := m.Name() + attrs := &customBazelModuleAttributes{} + + myLibraryName := "__bp2build__" + baseName + myLibraryProps := bazel.BazelTargetModuleProperties{ + Name: &myLibraryName, Rule_class: "my_library", Bzl_load_location: "//build/bazel/rules:rules.bzl", - }) - ctx.CreateModule(customBazelModuleFactory, &customBazelModuleAttributes{ - Name: proptools.StringPtr(baseName + "_proto_library_deps"), - }, &bazel.BazelTargetModuleProperties{ + } + ctx.CreateBazelTargetModule(customBazelModuleFactory, myLibraryProps, attrs) + + protoLibraryName := "__bp2build__" + baseName + "_proto_library_deps" + protoLibraryProps := bazel.BazelTargetModuleProperties{ + Name: &protoLibraryName, Rule_class: "proto_library", Bzl_load_location: "//build/bazel/rules:proto.bzl", - }) - ctx.CreateModule(customBazelModuleFactory, &customBazelModuleAttributes{ - Name: proptools.StringPtr(baseName + "_my_proto_library_deps"), - }, &bazel.BazelTargetModuleProperties{ + } + ctx.CreateBazelTargetModule(customBazelModuleFactory, protoLibraryProps, attrs) + + myProtoLibraryName := "__bp2build__" + baseName + "_my_proto_library_deps" + myProtoLibraryProps := bazel.BazelTargetModuleProperties{ + Name: &myProtoLibraryName, Rule_class: "my_proto_library", Bzl_load_location: "//build/bazel/rules:proto.bzl", - }) + } + ctx.CreateBazelTargetModule(customBazelModuleFactory, myProtoLibraryProps, attrs) } } diff --git a/cc/cc_test.go b/cc/cc_test.go index 6403547e8..b1c1b2e8d 100644 --- a/cc/cc_test.go +++ b/cc/cc_test.go @@ -266,7 +266,7 @@ func checkVndkModule(t *testing.T, ctx *android.TestContext, name, subDir string } } -func checkSnapshotIncludeExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string, include bool) { +func checkSnapshotIncludeExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string, include bool, fake bool) { t.Helper() mod, ok := ctx.ModuleForTests(moduleName, variant).Module().(android.OutputFileProducer) if !ok { @@ -282,8 +282,14 @@ func checkSnapshotIncludeExclude(t *testing.T, ctx *android.TestContext, singlet if include { out := singleton.Output(snapshotPath) - if out.Input.String() != outputFiles[0].String() { - t.Errorf("The input of snapshot %q must be %q, but %q", moduleName, out.Input.String(), outputFiles[0]) + if fake { + if out.Rule == nil { + t.Errorf("Missing rule for module %q output file %q", moduleName, outputFiles[0]) + } + } else { + if out.Input.String() != outputFiles[0].String() { + t.Errorf("The input of snapshot %q must be %q, but %q", moduleName, out.Input.String(), outputFiles[0]) + } } } else { out := singleton.MaybeOutput(snapshotPath) @@ -294,11 +300,15 @@ func checkSnapshotIncludeExclude(t *testing.T, ctx *android.TestContext, singlet } func checkSnapshot(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) { - checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true) + checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, false) } func checkSnapshotExclude(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) { - checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, false) + checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, false, false) +} + +func checkSnapshotRule(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, moduleName, snapshotFilename, subDir, variant string) { + checkSnapshotIncludeExclude(t, ctx, singleton, moduleName, snapshotFilename, subDir, variant, true, true) } func checkWriteFileOutput(t *testing.T, params android.TestingBuildParams, expected []string) { diff --git a/cc/library.go b/cc/library.go index 29a3c696a..f185cb793 100644 --- a/cc/library.go +++ b/cc/library.go @@ -19,6 +19,7 @@ import ( "io" "path/filepath" "regexp" + "strconv" "strings" "sync" @@ -1362,8 +1363,11 @@ func (library *libraryDecorator) link(ctx ModuleContext, func (library *libraryDecorator) exportVersioningMacroIfNeeded(ctx android.BaseModuleContext) { if library.buildStubs() && library.stubsVersion() != "" && !library.skipAPIDefine { name := versioningMacroName(ctx.Module().(*Module).ImplementationModuleName(ctx)) - ver := library.stubsVersion() - library.reexportFlags("-D" + name + "=" + ver) + apiLevel, err := android.ApiLevelFromUser(ctx, library.stubsVersion()) + if err != nil { + ctx.ModuleErrorf("Can't export version macro: %s", err.Error()) + } + library.reexportFlags("-D" + name + "=" + strconv.Itoa(apiLevel.FinalOrPreviewInt())) } } diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go index 35fc1c1fa..7077b7179 100644 --- a/cc/vendor_snapshot.go +++ b/cc/vendor_snapshot.go @@ -239,10 +239,6 @@ func isSnapshotAware(cfg android.DeviceConfig, m *Module, inProprietaryPath bool if _, ok := m.linker.(*llndkHeadersDecorator); ok { return false } - // If we are using directed snapshot AND we have to exclude this module, skip this - if image.excludeFromDirectedSnapshot(cfg, m.BaseModuleName()) { - return false - } // Libraries if l, ok := m.linker.(snapshotLibraryInterface); ok { @@ -371,18 +367,19 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { var headers android.Paths - copyFile := copyFileRule - if c.fake { - // All prebuilt binaries and headers are installed by copyFile function. This makes a fake - // snapshot just touch prebuilts and headers, rather than installing real files. - copyFile = func(ctx android.SingletonContext, path android.Path, out string) android.OutputPath { + copyFile := func(ctx android.SingletonContext, path android.Path, out string, fake bool) android.OutputPath { + if fake { + // All prebuilt binaries and headers are installed by copyFile function. This makes a fake + // snapshot just touch prebuilts and headers, rather than installing real files. return writeStringToFileRule(ctx, "", out) + } else { + return copyFileRule(ctx, path, out) } } // installSnapshot function copies prebuilt file (.so, .a, or executable) and json flag file. // For executables, init_rc and vintf_fragments files are also copied. - installSnapshot := func(m *Module) android.Paths { + installSnapshot := func(m *Module, fake bool) android.Paths { targetArch := "arch-" + m.Target().Arch.ArchType.String() if m.Target().Arch.ArchVariant != "" { targetArch += "-" + m.Target().Arch.ArchVariant @@ -419,7 +416,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { out := filepath.Join(configsDir, path.Base()) if !installedConfigs[out] { installedConfigs[out] = true - ret = append(ret, copyFile(ctx, path, out)) + ret = append(ret, copyFile(ctx, path, out, fake)) } } @@ -470,7 +467,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { prop.ModuleName += ".cfi" } snapshotLibOut := filepath.Join(snapshotArchDir, targetArch, libType, stem) - ret = append(ret, copyFile(ctx, libPath, snapshotLibOut)) + ret = append(ret, copyFile(ctx, libPath, snapshotLibOut, fake)) } else { stem = ctx.ModuleName(m) } @@ -484,7 +481,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { // install bin binPath := m.outputFile.Path() snapshotBinOut := filepath.Join(snapshotArchDir, targetArch, "binary", binPath.Base()) - ret = append(ret, copyFile(ctx, binPath, snapshotBinOut)) + ret = append(ret, copyFile(ctx, binPath, snapshotBinOut, fake)) propOut = snapshotBinOut + ".json" } else if m.object() { // object files aren't installed to the device, so their names can conflict. @@ -492,7 +489,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { objPath := m.outputFile.Path() snapshotObjOut := filepath.Join(snapshotArchDir, targetArch, "object", ctx.ModuleName(m)+filepath.Ext(objPath.Base())) - ret = append(ret, copyFile(ctx, objPath, snapshotObjOut)) + ret = append(ret, copyFile(ctx, objPath, snapshotObjOut, fake)) propOut = snapshotObjOut + ".json" } else { ctx.Errorf("unknown module %q in vendor snapshot", m.String()) @@ -532,9 +529,17 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { return } - // installSnapshot installs prebuilts and json flag files - snapshotOutputs = append(snapshotOutputs, installSnapshot(m)...) + // If we are using directed snapshot and a module is not included in the + // list, we will still include the module as if it was a fake module. + // The reason is that soong needs all the dependencies to be present, even + // if they are not using during the build. + installAsFake := c.fake + if c.image.excludeFromDirectedSnapshot(ctx.DeviceConfig(), m.BaseModuleName()) { + installAsFake = true + } + // installSnapshot installs prebuilts and json flag files + snapshotOutputs = append(snapshotOutputs, installSnapshot(m, installAsFake)...) // just gather headers and notice files here, because they are to be deduplicated if l, ok := m.linker.(snapshotLibraryInterface); ok { headers = append(headers, l.snapshotHeaders()...) @@ -553,7 +558,7 @@ func (c *snapshotSingleton) GenerateBuildActions(ctx android.SingletonContext) { // install all headers after removing duplicates for _, header := range android.FirstUniquePaths(headers) { - snapshotOutputs = append(snapshotOutputs, copyFile(ctx, header, filepath.Join(includeDir, header.String()))) + snapshotOutputs = append(snapshotOutputs, copyFile(ctx, header, filepath.Join(includeDir, header.String()), c.fake)) } // All artifacts are ready. Sort them to normalize ninja and then zip. diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go index 499d7ae21..659b6931c 100644 --- a/cc/vendor_snapshot_test.go +++ b/cc/vendor_snapshot_test.go @@ -228,7 +228,6 @@ func TestVendorSnapshotDirected(t *testing.T) { snapshotSingleton := ctx.SingletonForTests("vendor-snapshot") var includeJsonFiles []string - var excludeJsonFiles []string for _, arch := range [][]string{ []string{"arm64", "armv8-a"}, @@ -248,9 +247,10 @@ func TestVendorSnapshotDirected(t *testing.T) { checkSnapshot(t, ctx, snapshotSingleton, "prebuilt_libfoo", "libfoo.so", sharedDir, sharedVariant) includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libfoo.so.json")) - // Excluded modules - checkSnapshotExclude(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant) - excludeJsonFiles = append(excludeJsonFiles, filepath.Join(sharedDir, "libvendor_available.so.json")) + // Excluded modules. Modules not included in the directed vendor snapshot + // are still include as fake modules. + checkSnapshotRule(t, ctx, snapshotSingleton, "libvendor_available", "libvendor_available.so", sharedDir, sharedVariant) + includeJsonFiles = append(includeJsonFiles, filepath.Join(sharedDir, "libvendor_available.so.json")) } // Verify that each json file for an included module has a rule. @@ -259,13 +259,6 @@ func TestVendorSnapshotDirected(t *testing.T) { t.Errorf("include json file %q not found", jsonFile) } } - - // Verify that each json file for an excluded module has no rule. - for _, jsonFile := range excludeJsonFiles { - if snapshotSingleton.MaybeOutput(jsonFile).Rule != nil { - t.Errorf("exclude json file %q found", jsonFile) - } - } } func TestVendorSnapshotUse(t *testing.T) { diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go index c06fd4ff7..76581548e 100644 --- a/filesystem/filesystem.go +++ b/filesystem/filesystem.go @@ -48,8 +48,8 @@ type filesystemProperties struct { // Hash and signing algorithm for avbtool. Default is SHA256_RSA4096. Avb_algorithm *string - // Type of the filesystem. Currently, ext4 and compressed_cpio are supported. Default is - // ext4. + // Type of the filesystem. Currently, ext4, cpio, and compressed_cpio are supported. Default + // is ext4. Type *string // file_contexts file to make image. Currently, only ext4 is supported. @@ -83,6 +83,7 @@ type fsType int const ( ext4Type fsType = iota compressedCpioType + cpioType // uncompressed unknown ) @@ -93,6 +94,8 @@ func (f *filesystem) fsType(ctx android.ModuleContext) fsType { return ext4Type case "compressed_cpio": return compressedCpioType + case "cpio": + return cpioType default: ctx.PropertyErrorf("type", "%q not supported", typeStr) return unknown @@ -110,7 +113,9 @@ func (f *filesystem) GenerateAndroidBuildActions(ctx android.ModuleContext) { case ext4Type: f.output = f.buildImageUsingBuildImage(ctx) case compressedCpioType: - f.output = f.buildCompressedCpioImage(ctx) + f.output = f.buildCpioImage(ctx, true) + case cpioType: + f.output = f.buildCpioImage(ctx, false) default: return } @@ -218,7 +223,7 @@ func (f *filesystem) buildPropFile(ctx android.ModuleContext) (propFile android. return propFile, deps } -func (f *filesystem) buildCompressedCpioImage(ctx android.ModuleContext) android.OutputPath { +func (f *filesystem) buildCpioImage(ctx android.ModuleContext, compressed bool) android.OutputPath { if proptools.Bool(f.properties.Use_avb) { ctx.PropertyErrorf("use_avb", "signing compresed cpio image using avbtool is not supported."+ "Consider adding this to bootimg module and signing the entire boot image.") @@ -239,18 +244,22 @@ func (f *filesystem) buildCompressedCpioImage(ctx android.ModuleContext) android Input(zipFile) output := android.PathForModuleOut(ctx, f.installFileName()).OutputPath - builder.Command(). + cmd := builder.Command(). BuiltTool("mkbootfs"). - Text(rootDir.String()). // input directory - Text("|"). - BuiltTool("lz4"). - Flag("--favor-decSpeed"). // for faster boot - Flag("-12"). // maximum compression level - Flag("-l"). // legacy format for kernel - Text(">").Output(output) + Text(rootDir.String()) // input directory + if compressed { + cmd.Text("|"). + BuiltTool("lz4"). + Flag("--favor-decSpeed"). // for faster boot + Flag("-12"). // maximum compression level + Flag("-l"). // legacy format for kernel + Text(">").Output(output) + } else { + cmd.Text(">").Output(output) + } // rootDir is not deleted. Might be useful for quick inspection. - builder.Build("build_compressed_cpio_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName())) + builder.Build("build_cpio_image", fmt.Sprintf("Creating filesystem %s", f.BaseModuleName())) return output } diff --git a/genrule/genrule.go b/genrule/genrule.go index 62aa7f834..427c99583 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -780,7 +780,6 @@ type genRuleProperties struct { } type bazelGenruleAttributes struct { - Name *string Srcs bazel.LabelList Outs []string Tools bazel.LabelList @@ -804,7 +803,7 @@ func GenruleBp2Build(ctx android.TopDownMutatorContext) { if !ok { return } - name := "__bp2build__" + m.Name() + // Bazel only has the "tools" attribute. tools := android.BazelLabelForModuleDeps(ctx, m.properties.Tools) tool_files := android.BazelLabelForModuleSrc(ctx, m.properties.Tool_files) @@ -847,16 +846,22 @@ func GenruleBp2Build(ctx android.TopDownMutatorContext) { } } - // Create the BazelTargetModule. - ctx.CreateModule(BazelGenruleFactory, &bazelGenruleAttributes{ - Name: proptools.StringPtr(name), + attrs := &bazelGenruleAttributes{ Srcs: srcs, Outs: outs, Cmd: cmd, Tools: tools, - }, &bazel.BazelTargetModuleProperties{ + } + + // Can we automate this? + name := "__bp2build__" + m.Name() + props := bazel.BazelTargetModuleProperties{ + Name: &name, Rule_class: "genrule", - }) + } + + // Create the BazelTargetModule. + ctx.CreateBazelTargetModule(BazelGenruleFactory, props, attrs) } func (m *bazelGenrule) Name() string { diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go index 2a7eb42dc..86b189558 100644 --- a/java/dexpreopt_bootjars.go +++ b/java/dexpreopt_bootjars.go @@ -435,6 +435,11 @@ func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonC // Inspect this module to see if it contains a bootclasspath dex jar. // Note that the same jar may occur in multiple modules. // This logic is tested in the apex package to avoid import cycle apex <-> java. +// +// This is similar to logic in isModuleInConfiguredList() so any changes needed here are likely to +// be needed there too. +// +// TODO(b/177892522): Avoid having to perform this type of check or if necessary dedup it. func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, module android.Module) (int, android.Path) { name := ctx.ModuleName(module) diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go index ccb874506..46994c396 100644 --- a/java/hiddenapi_singleton.go +++ b/java/hiddenapi_singleton.go @@ -22,9 +22,13 @@ import ( ) func init() { - android.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory) - android.RegisterSingletonType("hiddenapi_index", hiddenAPIIndexSingletonFactory) - android.RegisterModuleType("hiddenapi_flags", hiddenAPIFlagsFactory) + RegisterHiddenApiSingletonComponents(android.InitRegistrationContext) +} + +func RegisterHiddenApiSingletonComponents(ctx android.RegistrationContext) { + ctx.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory) + ctx.RegisterSingletonType("hiddenapi_index", hiddenAPIIndexSingletonFactory) + ctx.RegisterModuleType("hiddenapi_flags", hiddenAPIFlagsFactory) } type hiddenAPISingletonPathsStruct struct { @@ -213,6 +217,10 @@ func stubFlagsRule(ctx android.SingletonContext) { var bootDexJars android.Paths + // Get the configured non-updatable and updatable boot jars. + nonUpdatableBootJars := ctx.Config().NonUpdatableBootJars() + updatableBootJars := ctx.Config().UpdatableBootJars() + ctx.VisitAllModules(func(module android.Module) { // Collect dex jar paths for the modules listed above. if j, ok := module.(Dependency); ok { @@ -227,11 +235,8 @@ func stubFlagsRule(ctx android.SingletonContext) { // Collect dex jar paths for modules that had hiddenapi encode called on them. if h, ok := module.(hiddenAPIIntf); ok { if jar := h.bootDexJar(); jar != nil { - // For a java lib included in an APEX, only take the one built for - // the platform variant, and skip the variants for APEXes. - // Otherwise, the hiddenapi tool will complain about duplicated classes - apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo) - if !apexInfo.IsForPlatform() { + if !isModuleInConfiguredList(ctx, module, nonUpdatableBootJars) && + !isModuleInConfiguredList(ctx, module, updatableBootJars) { return } @@ -280,6 +285,47 @@ func stubFlagsRule(ctx android.SingletonContext) { rule.Build("hiddenAPIStubFlagsFile", "hiddenapi stub flags") } +// Checks to see whether the supplied module variant is in the list of boot jars. +// +// This is similar to logic in getBootImageJar() so any changes needed here are likely to be needed +// there too. +// +// TODO(b/179354495): Avoid having to perform this type of check or if necessary dedup it. +func isModuleInConfiguredList(ctx android.SingletonContext, module android.Module, configuredBootJars android.ConfiguredJarList) bool { + name := ctx.ModuleName(module) + + // Strip a prebuilt_ prefix so that this can match a prebuilt module that has not been renamed. + name = android.RemoveOptionalPrebuiltPrefix(name) + + // Ignore any module that is not listed in the boot image configuration. + index := configuredBootJars.IndexOfJar(name) + if index == -1 { + return false + } + + // It is an error if the module is not an ApexModule. + if _, ok := module.(android.ApexModule); !ok { + ctx.Errorf("module %q configured in boot jars does not support being added to an apex", module) + return false + } + + apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo) + + // Now match the apex part of the boot image configuration. + requiredApex := configuredBootJars.Apex(index) + if requiredApex == "platform" { + if len(apexInfo.InApexes) != 0 { + // A platform variant is required but this is for an apex so ignore it. + return false + } + } else if !apexInfo.InApexByBaseName(requiredApex) { + // An apex variant for a specific apex is required but this is the wrong apex. + return false + } + + return true +} + func prebuiltFlagsRule(ctx android.SingletonContext) android.Path { outputPath := hiddenAPISingletonPaths(ctx).flags inputPath := android.PathForSource(ctx, ctx.Config().PrebuiltHiddenApiDir(ctx), "hiddenapi-flags.csv") diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go index 27f363e0c..58f1b1d54 100644 --- a/java/hiddenapi_singleton_test.go +++ b/java/hiddenapi_singleton_test.go @@ -15,11 +15,12 @@ package java import ( - "android/soong/android" "fmt" "strings" "testing" + "android/soong/android" + "github.com/google/blueprint/proptools" ) @@ -32,7 +33,7 @@ func testConfigWithBootJars(bp string, bootJars []string, prebuiltHiddenApiDir * func testContextWithHiddenAPI(config android.Config) *android.TestContext { ctx := testContext(config) - ctx.RegisterSingletonType("hiddenapi", hiddenAPISingletonFactory) + RegisterHiddenApiSingletonComponents(ctx) return ctx } @@ -64,7 +65,7 @@ func TestHiddenAPISingleton(t *testing.T) { name: "foo", srcs: ["a.java"], compile_dex: true, - } + } `, []string{"platform:foo"}, nil) hiddenAPI := ctx.SingletonForTests("hiddenapi") @@ -75,6 +76,47 @@ func TestHiddenAPISingleton(t *testing.T) { } } +func checkRuleInputs(t *testing.T, expected string, hiddenAPIRule android.TestingBuildParams) { + actual := strings.TrimSpace(strings.Join(android.NormalizePathsForTesting(hiddenAPIRule.Implicits), "\n")) + expected = strings.TrimSpace(expected) + if actual != expected { + t.Errorf("Expected hiddenapi rule inputs:\n%s\nactual inputs:\n%s", expected, actual) + } +} + +func TestHiddenAPIIndexSingleton(t *testing.T) { + ctx, _ := testHiddenAPIBootJars(t, ` + java_library { + name: "foo", + srcs: ["a.java"], + compile_dex: true, + } + + java_import { + name: "foo", + jars: ["a.jar"], + compile_dex: true, + prefer: false, + } + + java_sdk_library { + name: "bar", + srcs: ["a.java"], + compile_dex: true, + } + `, []string{"platform:foo", "platform:bar"}, nil) + + hiddenAPIIndex := ctx.SingletonForTests("hiddenapi_index") + indexRule := hiddenAPIIndex.Rule("singleton-merged-hiddenapi-index") + checkRuleInputs(t, ` +.intermediates/bar.impl/android_common/hiddenapi/index.csv +.intermediates/bar/android_common/hiddenapi/index.csv +.intermediates/foo/android_common/hiddenapi/index.csv +.intermediates/prebuilt_foo/android_common/hiddenapi/index.csv +`, + indexRule) +} + func TestHiddenAPISingletonWithPrebuilt(t *testing.T) { ctx, _ := testHiddenAPIBootJars(t, ` java_import { @@ -98,14 +140,14 @@ func TestHiddenAPISingletonWithPrebuiltUseSource(t *testing.T) { name: "foo", srcs: ["a.java"], compile_dex: true, - } + } java_import { name: "foo", jars: ["a.jar"], compile_dex: true, prefer: false, - } + } `, []string{"platform:foo"}, nil) hiddenAPI := ctx.SingletonForTests("hiddenapi") @@ -127,14 +169,14 @@ func TestHiddenAPISingletonWithPrebuiltOverrideSource(t *testing.T) { name: "foo", srcs: ["a.java"], compile_dex: true, - } + } java_import { name: "foo", jars: ["a.jar"], compile_dex: true, prefer: true, - } + } `, []string{"platform:foo"}, nil) hiddenAPI := ctx.SingletonForTests("hiddenapi") diff --git a/java/java.go b/java/java.go index 91944f6e3..bed232b4e 100644 --- a/java/java.go +++ b/java/java.go @@ -40,18 +40,21 @@ func init() { // Register sdk member types. android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType) + // Export implementation classes jar as part of the sdk. + exportImplementationClassesJar := func(_ android.SdkMemberContext, j *Library) android.Path { + implementationJars := j.ImplementationAndResourcesJars() + if len(implementationJars) != 1 { + panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name())) + } + return implementationJars[0] + } + // Register java implementation libraries for use only in module_exports (not sdk). android.RegisterSdkMemberType(&librarySdkMemberType{ android.SdkMemberTypeBase{ PropertyName: "java_libs", }, - func(_ android.SdkMemberContext, j *Library) android.Path { - implementationJars := j.ImplementationAndResourcesJars() - if len(implementationJars) != 1 { - panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name())) - } - return implementationJars[0] - }, + exportImplementationClassesJar, sdkSnapshotFilePathForJar, copyEverythingToSnapshot, }) @@ -72,19 +75,11 @@ func init() { PropertyName: "java_boot_libs", SupportsSdk: true, }, - func(ctx android.SdkMemberContext, j *Library) android.Path { - // Java boot libs are only provided in the SDK to provide access to their dex implementation - // jar for use by dexpreopting and boot jars package check. They do not need to provide an - // actual implementation jar but the java_import will need a file that exists so just copy an - // empty file. Any attempt to use that file as a jar will cause a build error. - return ctx.SnapshotBuilder().EmptyFile() - }, - func(osPrefix, name string) string { - // Create a special name for the implementation jar to try and provide some useful information - // to a developer that attempts to compile against this. - // TODO(b/175714559): Provide a proper error message in Soong not ninja. - return filepath.Join(osPrefix, "java_boot_libs", "snapshot", "jars", "are", "invalid", name+jarFileSuffix) - }, + // Temporarily export implementation classes jar for java_boot_libs as it is required for the + // hiddenapi processing. + // TODO(b/179354495): Revert once hiddenapi processing has been modularized. + exportImplementationClassesJar, + sdkSnapshotFilePathForJar, onlyCopyJarToSnapshot, }) diff --git a/rust/binary.go b/rust/binary.go index 0334accef..df489169b 100644 --- a/rust/binary.go +++ b/rust/binary.go @@ -119,6 +119,7 @@ func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps Path outputFile := android.PathForModuleOut(ctx, fileName) flags.RustFlags = append(flags.RustFlags, deps.depFlags...) + flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...) flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...) TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile, deps.linkDirs) diff --git a/rust/compiler.go b/rust/compiler.go index c92182420..586063e91 100644 --- a/rust/compiler.go +++ b/rust/compiler.go @@ -96,7 +96,11 @@ type BaseCompilerProperties struct { // list of C shared library dependencies Shared_libs []string `android:"arch_variant"` - // list of C static library dependencies + // list of C static library dependencies. Note, static libraries prefixed by "lib" will be passed to rustc + // along with "-lstatic=<name>". This will bundle the static library into rlib/static libraries so dependents do + // not need to also declare the static library as a dependency. Static libraries which are not prefixed by "lib" + // cannot be passed to rustc with this flag and will not be bundled into rlib/static libraries, and thus must + // be redeclared in dependents. Static_libs []string `android:"arch_variant"` // crate name, required for modules which produce Rust libraries: rust_library, rust_ffi and SourceProvider diff --git a/rust/library.go b/rust/library.go index b5749a2de..7ff13ec66 100644 --- a/rust/library.go +++ b/rust/library.go @@ -443,6 +443,7 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa } flags.RustFlags = append(flags.RustFlags, deps.depFlags...) + flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...) flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...) if library.dylib() { @@ -482,7 +483,6 @@ func (library *libraryDecorator) compile(ctx ModuleContext, flags Flags, deps Pa if library.rlib() || library.dylib() { library.flagExporter.exportLinkDirs(deps.linkDirs...) - library.flagExporter.exportDepFlags(deps.depFlags...) library.flagExporter.exportLinkObjects(deps.linkObjects...) } diff --git a/rust/rust.go b/rust/rust.go index 504b7a9bd..0b733cc35 100644 --- a/rust/rust.go +++ b/rust/rust.go @@ -280,10 +280,15 @@ type PathDeps struct { SharedLibDeps android.Paths StaticLibs android.Paths ProcMacros RustLibraries - linkDirs []string - depFlags []string - linkObjects []string - //ReexportedDeps android.Paths + + // depFlags and depLinkFlags are rustc and linker (clang) flags. + depFlags []string + depLinkFlags []string + + // linkDirs are link paths passed via -L to rustc. linkObjects are objects passed directly to the linker. + // Both of these are exported and propagate to dependencies. + linkDirs []string + linkObjects []string // Used by bindgen modules which call clang depClangFlags []string @@ -328,12 +333,10 @@ type compiler interface { type exportedFlagsProducer interface { exportLinkDirs(...string) - exportDepFlags(...string) exportLinkObjects(...string) } type flagExporter struct { - depFlags []string linkDirs []string linkObjects []string } @@ -342,17 +345,12 @@ func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) { flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...)) } -func (flagExporter *flagExporter) exportDepFlags(flags ...string) { - flagExporter.depFlags = android.FirstUniqueStrings(append(flagExporter.depFlags, flags...)) -} - func (flagExporter *flagExporter) exportLinkObjects(flags ...string) { flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...)) } func (flagExporter *flagExporter) setProvider(ctx ModuleContext) { ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{ - Flags: flagExporter.depFlags, LinkDirs: flagExporter.linkDirs, LinkObjects: flagExporter.linkObjects, }) @@ -898,8 +896,24 @@ func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps { exportDep := false switch { case cc.IsStaticDepTag(depTag): - depPaths.linkDirs = append(depPaths.linkDirs, linkPath) + // Only pass -lstatic for rlibs as it results in dylib bloat. + if lib, ok := ctx.Module().(*Module).compiler.(libraryInterface); ok && lib.rlib() { + // Link cc static libraries using "-lstatic" so rustc can reason about how to handle these + // (for example, bundling them into rlibs). + // + // rustc does not support linking libraries with the "-l" flag unless they are prefixed by "lib". + // If we need to link a library that isn't prefixed by "lib", we'll just link to it directly through + // linkObjects; such a library may need to be redeclared by static dependents. + if libName, ok := libNameFromFilePath(linkObject.Path()); ok { + depPaths.depFlags = append(depPaths.depFlags, "-lstatic="+libName) + } + } + + // Add this to linkObjects to pass the library directly to the linker as well. This propagates + // to dependencies to avoid having to redeclare static libraries for dependents of the dylib variant. depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String()) + depPaths.linkDirs = append(depPaths.linkDirs, linkPath) + exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo) depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...) depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...) @@ -1213,6 +1227,16 @@ func (mod *Module) IsInstallableToApex() bool { return false } +// If a library file has a "lib" prefix, extract the library name without the prefix. +func libNameFromFilePath(filepath android.Path) (string, bool) { + libName := strings.TrimSuffix(filepath.Base(), filepath.Ext()) + if strings.HasPrefix(libName, "lib") { + libName = libName[3:] + return libName, true + } + return "", false +} + var Bool = proptools.Bool var BoolDefault = proptools.BoolDefault var String = proptools.String diff --git a/rust/rust_test.go b/rust/rust_test.go index abc9af9b1..88d964300 100644 --- a/rust/rust_test.go +++ b/rust/rust_test.go @@ -213,6 +213,7 @@ func TestDepsTracking(t *testing.T) { name: "librlib", srcs: ["foo.rs"], crate_name: "rlib", + static_libs: ["libstatic"], } rust_proc_macro { name: "libpm", @@ -230,6 +231,7 @@ func TestDepsTracking(t *testing.T) { } `) module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module) + rustc := ctx.ModuleForTests("librlib", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc") // Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up. if !android.InList("libdylib", module.Properties.AndroidMkDylibs) { @@ -251,6 +253,11 @@ func TestDepsTracking(t *testing.T) { if !android.InList("libstatic", module.Properties.AndroidMkStaticLibs) { t.Errorf("Static library dependency not detected (dependency missing from AndroidMkStaticLibs)") } + + if !strings.Contains(rustc.Args["rustcFlags"], "-lstatic=static") { + t.Errorf("-lstatic flag not being passed to rustc for static library") + } + } func TestSourceProviderDeps(t *testing.T) { diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go index 488afd84e..17a6ca9b8 100644 --- a/sdk/java_sdk_test.go +++ b/sdk/java_sdk_test.go @@ -503,7 +503,7 @@ java_import { sdk_member_name: "myjavalib", visibility: ["//visibility:public"], apex_available: ["//apex_available:platform"], - jars: ["java_boot_libs/snapshot/jars/are/invalid/myjavalib.jar"], + jars: ["java/myjavalib.jar"], } java_import { @@ -511,7 +511,7 @@ java_import { prefer: false, visibility: ["//visibility:public"], apex_available: ["//apex_available:platform"], - jars: ["java_boot_libs/snapshot/jars/are/invalid/myjavalib.jar"], + jars: ["java/myjavalib.jar"], } module_exports_snapshot { @@ -519,10 +519,9 @@ module_exports_snapshot { visibility: ["//visibility:public"], java_boot_libs: ["myexports_myjavalib@current"], } - `), checkAllCopyRules(` -.intermediates/myexports/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/myjavalib.jar +.intermediates/myjavalib/android_common/withres/myjavalib.jar -> java/myjavalib.jar `), ) } diff --git a/sdk/update.go b/sdk/update.go index b5bc9f434..377aaae76 100644 --- a/sdk/update.go +++ b/sdk/update.go @@ -653,9 +653,6 @@ type snapshotBuilder struct { filesToZip android.Paths zipsToMerge android.Paths - // The path to an empty file. - emptyFile android.WritablePath - prebuiltModules map[string]*bpModule prebuiltOrder []*bpModule @@ -706,19 +703,6 @@ func (s *snapshotBuilder) UnzipToSnapshot(zipPath android.Path, destDir string) s.zipsToMerge = append(s.zipsToMerge, tmpZipPath) } -func (s *snapshotBuilder) EmptyFile() android.Path { - if s.emptyFile == nil { - ctx := s.ctx - s.emptyFile = android.PathForModuleOut(ctx, "empty") - s.ctx.Build(pctx, android.BuildParams{ - Rule: android.Touch, - Output: s.emptyFile, - }) - } - - return s.emptyFile -} - func (s *snapshotBuilder) AddPrebuiltModule(member android.SdkMember, moduleType string) android.BpModule { name := member.Name() if s.prebuiltModules[name] != nil { diff --git a/zip/zip.go b/zip/zip.go index cb85f5ced..f7313291c 100644 --- a/zip/zip.go +++ b/zip/zip.go @@ -172,6 +172,9 @@ func (b *FileArgsBuilder) RspFile(name string) *FileArgsBuilder { arg := b.state arg.SourceFiles = ReadRespFile(list) + for i := range arg.SourceFiles { + arg.SourceFiles[i] = pathtools.MatchEscape(arg.SourceFiles[i]) + } b.fileArgs = append(b.fileArgs, arg) return b } diff --git a/zip/zip_test.go b/zip/zip_test.go index a16e09286..b456ef8f2 100644 --- a/zip/zip_test.go +++ b/zip/zip_test.go @@ -46,13 +46,14 @@ var mockFs = pathtools.MockFs(map[string][]byte{ "dangling -> missing": nil, "a/a/d -> b": nil, "c": fileC, - "l_nl": []byte("a/a/a\na/a/b\nc\n"), - "l_sp": []byte("a/a/a a/a/b c"), + "l_nl": []byte("a/a/a\na/a/b\nc\n\\[\n"), + "l_sp": []byte("a/a/a a/a/b c \\["), "l2": []byte("missing\n"), - "rsp": []byte("'a/a/a'\na/a/b\n'@'\n'foo'\\''bar'"), + "rsp": []byte("'a/a/a'\na/a/b\n'@'\n'foo'\\''bar'\n'['"), "@ -> c": nil, "foo'bar -> c": nil, "manifest.txt": fileCustomManifest, + "[": fileEmpty, }) func fh(name string, contents []byte, method uint16) zip.FileHeader { @@ -127,13 +128,15 @@ func TestZip(t *testing.T) { args: fileArgsBuilder(). File("a/a/a"). File("a/a/b"). - File("c"), + File("c"). + File(`\[`), compressionLevel: 9, files: []zip.FileHeader{ fh("a/a/a", fileA, zip.Deflate), fh("a/a/b", fileB, zip.Deflate), fh("c", fileC, zip.Deflate), + fh("[", fileEmpty, zip.Store), }, }, { @@ -235,6 +238,7 @@ func TestZip(t *testing.T) { fh("a/a/a", fileA, zip.Deflate), fh("a/a/b", fileB, zip.Deflate), fh("c", fileC, zip.Deflate), + fh("[", fileEmpty, zip.Store), }, }, { @@ -247,6 +251,7 @@ func TestZip(t *testing.T) { fh("a/a/a", fileA, zip.Deflate), fh("a/a/b", fileB, zip.Deflate), fh("c", fileC, zip.Deflate), + fh("[", fileEmpty, zip.Store), }, }, { @@ -260,6 +265,7 @@ func TestZip(t *testing.T) { fh("a/a/b", fileB, zip.Deflate), fh("@", fileC, zip.Deflate), fh("foo'bar", fileC, zip.Deflate), + fh("[", fileEmpty, zip.Store), }, }, { |