summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--android/Android.bp4
-rw-r--r--android/android_test.go2
-rw-r--r--android/apex.go10
-rw-r--r--android/arch.go106
-rw-r--r--android/bazel.go57
-rw-r--r--android/bazel_handler.go235
-rw-r--r--android/config.go32
-rw-r--r--android/defs.go9
-rw-r--r--android/env.go73
-rw-r--r--android/filegroup.go15
-rw-r--r--android/fixture.go810
-rw-r--r--android/fixture_test.go49
-rw-r--r--android/license.go2
-rw-r--r--android/license_test.go6
-rw-r--r--android/licenses.go2
-rw-r--r--android/licenses_test.go116
-rw-r--r--android/module.go61
-rw-r--r--android/mutator.go68
-rw-r--r--android/override_module.go7
-rw-r--r--android/package.go2
-rw-r--r--android/path_properties.go87
-rw-r--r--android/path_properties_test.go37
-rw-r--r--android/paths.go4
-rw-r--r--android/prebuilt.go19
-rw-r--r--android/prebuilt_test.go47
-rw-r--r--android/queryview.go18
-rw-r--r--android/register.go122
-rw-r--r--android/sandbox.go25
-rw-r--r--android/soongconfig/modules.go11
-rw-r--r--android/soongconfig/modules_test.go38
-rw-r--r--android/testing.go318
-rw-r--r--android/variable.go1
-rw-r--r--android/visibility.go9
-rw-r--r--android/visibility_test.go163
-rw-r--r--android/writedocs.go7
-rw-r--r--androidmk/androidmk/androidmk.go16
-rw-r--r--apex/OWNERS2
-rw-r--r--apex/allowed_deps.txt15
-rw-r--r--apex/apex.go42
-rw-r--r--apex/apex_test.go740
-rw-r--r--apex/boot_image_test.go6
-rw-r--r--apex/deapexer.go12
-rw-r--r--apex/key.go8
-rw-r--r--apex/prebuilt.go45
-rw-r--r--apex/vndk.go34
-rw-r--r--apex/vndk_test.go34
-rw-r--r--bazel/aquery.go46
-rw-r--r--bazel/properties.go95
-rw-r--r--bloaty/bloaty.go7
-rw-r--r--bp2build/Android.bp2
-rw-r--r--bp2build/bp2build.go6
-rw-r--r--bp2build/build_conversion.go99
-rw-r--r--bp2build/build_conversion_test.go22
-rw-r--r--bp2build/cc_library_headers_conversion_test.go3
-rw-r--r--bp2build/cc_object_conversion_test.go202
-rw-r--r--bp2build/configurability.go15
-rw-r--r--bp2build/conversion.go1
-rw-r--r--bp2build/metrics.go30
-rw-r--r--bp2build/sh_conversion_test.go3
-rw-r--r--bp2build/testing.go58
-rw-r--r--bpfix/bpfix/bpfix.go20
-rw-r--r--bpfix/bpfix/bpfix_test.go68
-rwxr-xr-xbuild_kzip.bash13
-rw-r--r--cc/cc.go123
-rw-r--r--cc/cc_test.go272
-rw-r--r--cc/compiler.go7
-rw-r--r--cc/config/tidy.go1
-rw-r--r--cc/gen.go51
-rw-r--r--cc/library.go20
-rw-r--r--cc/library_headers.go13
-rw-r--r--cc/library_sdk_member.go68
-rw-r--r--cc/object.go61
-rw-r--r--cc/prebuilt.go2
-rw-r--r--cc/snapshot_prebuilt.go61
-rw-r--r--cc/testing.go2
-rw-r--r--cc/tidy.go23
-rw-r--r--cc/vendor_snapshot_test.go6
-rw-r--r--cmd/soong_build/Android.bp1
-rw-r--r--cmd/soong_build/main.go39
-rw-r--r--cmd/soong_build/queryview.go7
-rw-r--r--cmd/soong_env/soong_env.go57
-rw-r--r--cmd/soong_ui/main.go3
-rw-r--r--dexpreopt/config.go2
-rw-r--r--dexpreopt/dexpreopt.go11
-rw-r--r--env/Android.bp11
-rw-r--r--filesystem/Android.bp1
-rw-r--r--filesystem/bootimg.go43
-rw-r--r--filesystem/logical_partition.go210
-rw-r--r--genrule/genrule.go17
-rw-r--r--java/Android.bp1
-rw-r--r--java/aar.go20
-rw-r--r--java/android_manifest.go4
-rw-r--r--java/androidmk.go11
-rwxr-xr-xjava/app.go38
-rw-r--r--java/app_import.go24
-rw-r--r--java/app_import_test.go18
-rw-r--r--java/app_test.go136
-rw-r--r--java/builder.go3
-rw-r--r--java/device_host_converter.go16
-rw-r--r--java/dex.go3
-rw-r--r--java/dexpreopt_bootjars.go18
-rw-r--r--java/droiddoc.go30
-rw-r--r--java/hiddenapi.go70
-rw-r--r--java/hiddenapi_singleton.go19
-rw-r--r--java/hiddenapi_singleton_test.go30
-rw-r--r--java/java.go244
-rw-r--r--java/java_test.go19
-rw-r--r--java/legacy_core_platform_api_usage.go5
-rw-r--r--java/lint.go164
-rw-r--r--java/robolectric.go20
-rw-r--r--java/rro_test.go9
-rw-r--r--java/sdk_library.go43
-rw-r--r--java/sdk_library_external.go9
-rw-r--r--java/sysprop.go64
-rw-r--r--java/testing.go1
-rw-r--r--remoteexec/remoteexec.go7
-rw-r--r--rust/builder.go2
-rw-r--r--rust/config/allowed_list.go1
-rw-r--r--rust/config/lints.go1
-rw-r--r--rust/testing.go2
-rwxr-xr-xscripts/build-mainline-modules.sh4
-rwxr-xr-xscripts/hiddenapi/merge_csv.py34
-rwxr-xr-xscripts/strip.sh2
-rw-r--r--sdk/bp_test.go14
-rw-r--r--sdk/cc_sdk_test.go843
-rw-r--r--sdk/exports.go8
-rw-r--r--sdk/java_sdk_test.go2
-rw-r--r--sdk/sdk.go12
-rw-r--r--sdk/sdk_test.go11
-rw-r--r--sdk/testing.go123
-rw-r--r--sdk/update.go32
-rw-r--r--sh/sh_binary.go13
-rw-r--r--sh/sh_binary_test.go7
-rw-r--r--shared/Android.bp5
-rw-r--r--shared/debug.go69
-rw-r--r--shared/env.go (renamed from env/env.go)34
-rw-r--r--shared/paths.go15
-rw-r--r--shared/paths_test.go (renamed from cmd/soong_env/Android.bp)28
-rw-r--r--sysprop/sysprop_library.go119
-rw-r--r--sysprop/sysprop_test.go166
-rw-r--r--ui/build/cleanbuild.go2
-rw-r--r--ui/build/environment.go13
-rw-r--r--ui/build/paths/logs_test.go3
-rw-r--r--ui/build/soong.go97
-rw-r--r--vnames.go.json9
-rw-r--r--vnames.json3
146 files changed, 5621 insertions, 2407 deletions
diff --git a/android/Android.bp b/android/Android.bp
index 00139d8ab..f17a8a047 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -12,7 +12,6 @@ bootstrap_go_package {
"soong",
"soong-android-soongconfig",
"soong-bazel",
- "soong-env",
"soong-shared",
"soong-ui-metrics_proto",
],
@@ -22,6 +21,7 @@ bootstrap_go_package {
"api_levels.go",
"arch.go",
"arch_list.go",
+ "bazel.go",
"bazel_handler.go",
"config.go",
"csuite_config.go",
@@ -33,6 +33,7 @@ bootstrap_go_package {
"deptag.go",
"expand.go",
"filegroup.go",
+ "fixture.go",
"hooks.go",
"image.go",
"license.go",
@@ -86,6 +87,7 @@ bootstrap_go_package {
"depset_test.go",
"deptag_test.go",
"expand_test.go",
+ "fixture_test.go",
"license_kind_test.go",
"license_test.go",
"licenses_test.go",
diff --git a/android/android_test.go b/android/android_test.go
index 46b705468..68cb70543 100644
--- a/android/android_test.go
+++ b/android/android_test.go
@@ -44,3 +44,5 @@ func TestMain(m *testing.M) {
os.Exit(run())
}
+
+var emptyTestFixtureFactory = NewFixtureFactory(&buildDir)
diff --git a/android/apex.go b/android/apex.go
index 463794245..a014592ef 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -739,6 +739,8 @@ func (d *ApexBundleDepsInfo) BuildDepsInfoLists(ctx ModuleContext, minSdkVersion
d.flatListPath = PathForModuleOut(ctx, "depsinfo", "flatlist.txt").OutputPath
WriteFileRule(ctx, d.flatListPath, flatContent.String())
+
+ ctx.Phony(fmt.Sprintf("%s-depsinfo", ctx.ModuleName()), d.fullListPath, d.flatListPath)
}
// TODO(b/158059172): remove minSdkVersion allowlist
@@ -847,8 +849,12 @@ func CheckMinSdkVersion(m UpdatableModule, ctx ModuleContext, minSdkVersion ApiL
if err := to.ShouldSupportSdkVersion(ctx, minSdkVersion); err != nil {
toName := ctx.OtherModuleName(to)
if ver, ok := minSdkVersionAllowlist[toName]; !ok || ver.GreaterThan(minSdkVersion) {
- ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v. Dependency path: %s",
- minSdkVersion, ctx.ModuleName(), err.Error(), ctx.GetPathString(false))
+ ctx.OtherModuleErrorf(to, "should support min_sdk_version(%v) for %q: %v."+
+ "\n\nDependency path: %s\n\n"+
+ "Consider adding 'min_sdk_version: %q' to %q",
+ minSdkVersion, ctx.ModuleName(), err.Error(),
+ ctx.GetPathString(false),
+ minSdkVersion, ctx.ModuleName())
return false
}
}
diff --git a/android/arch.go b/android/arch.go
index 6fb70c9f1..20b4ab07d 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -616,16 +616,8 @@ func archMutator(bpctx blueprint.BottomUpMutatorContext) {
osTargets = []Target{osTargets[0]}
}
- // Some modules want compile_multilib: "first" to mean 32-bit, not 64-bit.
- // This is used for HOST_PREFER_32_BIT=true support for Art modules.
- prefer32 := false
- if base.prefer32 != nil {
- prefer32 = base.prefer32(mctx, base, os)
- }
- if os == Windows {
- // Windows builds always prefer 32-bit
- prefer32 = true
- }
+ // Windows builds always prefer 32-bit
+ prefer32 := os == Windows
// Determine the multilib selection for this module.
multilib, extraMultilib := decodeMultilib(base, os.Class)
@@ -1623,3 +1615,97 @@ func decodeMultilibTargets(multilib string, targets []Target, prefer32 bool) ([]
return buildTargets, nil
}
+
+// GetArchProperties returns a map of architectures to the values of the
+// properties of the 'dst' struct that are specific to that architecture.
+//
+// For example, passing a struct { Foo bool, Bar string } will return an
+// interface{} that can be type asserted back into the same struct, containing
+// the arch specific property value specified by the module if defined.
+func (m *ModuleBase) GetArchProperties(dst interface{}) map[ArchType]interface{} {
+ // Return value of the arch types to the prop values for that arch.
+ archToProp := map[ArchType]interface{}{}
+
+ // Nothing to do for non-arch-specific modules.
+ if !m.ArchSpecific() {
+ return archToProp
+ }
+
+ // archProperties has the type of [][]interface{}. Looks complicated, so let's
+ // explain this step by step.
+ //
+ // Loop over the outer index, which determines the property struct that
+ // contains a matching set of properties in dst that we're interested in.
+ // For example, BaseCompilerProperties or BaseLinkerProperties.
+ for i := range m.archProperties {
+ if m.archProperties[i] == nil {
+ // Skip over nil arch props
+ continue
+ }
+
+ // Non-nil arch prop, let's see if the props match up.
+ for _, arch := range ArchTypeList() {
+ // e.g X86, Arm
+ field := arch.Field
+
+ // If it's not nil, loop over the inner index, which determines the arch variant
+ // of the prop type. In an Android.bp file, this is like looping over:
+ //
+ // arch: { arm: { key: value, ... }, x86: { key: value, ... } }
+ for _, archProperties := range m.archProperties[i] {
+ archPropValues := reflect.ValueOf(archProperties).Elem()
+
+ // This is the archPropRoot struct. Traverse into the Arch nested struct.
+ src := archPropValues.FieldByName("Arch").Elem()
+
+ // Step into non-nil pointers to structs in the src value.
+ if src.Kind() == reflect.Ptr {
+ if src.IsNil() {
+ // Ignore nil pointers.
+ continue
+ }
+ src = src.Elem()
+ }
+
+ // Find the requested field (e.g. x86, x86_64) in the src struct.
+ src = src.FieldByName(field)
+ if !src.IsValid() {
+ continue
+ }
+
+ // We only care about structs. These are not the droids you are looking for.
+ if src.Kind() != reflect.Struct {
+ continue
+ }
+
+ // If the value of the field is a struct then step into the
+ // BlueprintEmbed field. The special "BlueprintEmbed" name is
+ // used by createArchPropTypeDesc to embed the arch properties
+ // in the parent struct, so the src arch prop should be in this
+ // field.
+ //
+ // See createArchPropTypeDesc for more details on how Arch-specific
+ // module properties are processed from the nested props and written
+ // into the module's archProperties.
+ src = src.FieldByName("BlueprintEmbed")
+
+ // Clone the destination prop, since we want a unique prop struct per arch.
+ dstClone := reflect.New(reflect.ValueOf(dst).Elem().Type()).Interface()
+
+ // Copy the located property struct into the cloned destination property struct.
+ err := proptools.ExtendMatchingProperties([]interface{}{dstClone}, src.Interface(), nil, proptools.OrderReplace)
+ if err != nil {
+ // This is fine, it just means the src struct doesn't match.
+ continue
+ }
+
+ // Found the prop for the arch, you have.
+ archToProp[arch] = dstClone
+
+ // Go to the next prop.
+ break
+ }
+ }
+ }
+ return archToProp
+}
diff --git a/android/bazel.go b/android/bazel.go
new file mode 100644
index 000000000..9939bd5e2
--- /dev/null
+++ b/android/bazel.go
@@ -0,0 +1,57 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import "android/soong/bazel"
+
+// BazelModuleBase contains the property structs with metadata for modules which can be converted to
+// Bazel.
+type BazelModuleBase struct {
+ bazelProperties bazel.Properties
+}
+
+// Bazelable is specifies the interface for modules that can be converted to Bazel.
+type Bazelable interface {
+ bazelProps() *bazel.Properties
+ GetBazelLabel() string
+ ConvertWithBp2build() bool
+}
+
+// BazelModule is a lightweight wrapper interface around Module for Bazel-convertible modules.
+type BazelModule interface {
+ Module
+ Bazelable
+}
+
+// InitBazelModule is a wrapper function that decorates a BazelModule with Bazel-conversion
+// properties.
+func InitBazelModule(module BazelModule) {
+ module.AddProperties(module.bazelProps())
+}
+
+// bazelProps returns the Bazel properties for the given BazelModuleBase.
+func (b *BazelModuleBase) bazelProps() *bazel.Properties {
+ return &b.bazelProperties
+}
+
+// GetBazelLabel returns the Bazel label for the given BazelModuleBase.
+func (b *BazelModuleBase) GetBazelLabel() string {
+ return b.bazelProperties.Bazel_module.Label
+}
+
+// ConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build.
+func (b *BazelModuleBase) ConvertWithBp2build() bool {
+ return b.bazelProperties.Bazel_module.Bp2build_available
+}
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
index a5c4bedc5..9cd9fadfe 100644
--- a/android/bazel_handler.go
+++ b/android/bazel_handler.go
@@ -36,12 +36,14 @@ type CqueryRequestType int
const (
getAllFiles CqueryRequestType = iota
+ getCcObjectFiles
)
// Map key to describe bazel cquery requests.
type cqueryKey struct {
label string
requestType CqueryRequestType
+ archType ArchType
}
type BazelContext interface {
@@ -50,7 +52,11 @@ type BazelContext interface {
// has been queued to be run later.
// Returns result files built by building the given bazel target label.
- GetAllFiles(label string) ([]string, bool)
+ GetAllFiles(label string, archType ArchType) ([]string, bool)
+
+ // Returns object files produced by compiling the given cc-related target.
+ // Retrieves these files from Bazel's CcInfo provider.
+ GetCcObjectFiles(label string, archType ArchType) ([]string, bool)
// TODO(cparsons): Other cquery-related methods should be added here.
// ** End cquery methods
@@ -100,7 +106,12 @@ type MockBazelContext struct {
AllFiles map[string][]string
}
-func (m MockBazelContext) GetAllFiles(label string) ([]string, bool) {
+func (m MockBazelContext) GetAllFiles(label string, archType ArchType) ([]string, bool) {
+ result, ok := m.AllFiles[label]
+ return result, ok
+}
+
+func (m MockBazelContext) GetCcObjectFiles(label string, archType ArchType) ([]string, bool) {
result, ok := m.AllFiles[label]
return result, ok
}
@@ -123,8 +134,18 @@ func (m MockBazelContext) BuildStatementsToRegister() []bazel.BuildStatement {
var _ BazelContext = MockBazelContext{}
-func (bazelCtx *bazelContext) GetAllFiles(label string) ([]string, bool) {
- result, ok := bazelCtx.cquery(label, getAllFiles)
+func (bazelCtx *bazelContext) GetAllFiles(label string, archType ArchType) ([]string, bool) {
+ result, ok := bazelCtx.cquery(label, getAllFiles, archType)
+ if ok {
+ bazelOutput := strings.TrimSpace(result)
+ return strings.Split(bazelOutput, ", "), true
+ } else {
+ return nil, false
+ }
+}
+
+func (bazelCtx *bazelContext) GetCcObjectFiles(label string, archType ArchType) ([]string, bool) {
+ result, ok := bazelCtx.cquery(label, getCcObjectFiles, archType)
if ok {
bazelOutput := strings.TrimSpace(result)
return strings.Split(bazelOutput, ", "), true
@@ -133,7 +154,11 @@ func (bazelCtx *bazelContext) GetAllFiles(label string) ([]string, bool) {
}
}
-func (n noopBazelContext) GetAllFiles(label string) ([]string, bool) {
+func (n noopBazelContext) GetAllFiles(label string, archType ArchType) ([]string, bool) {
+ panic("unimplemented")
+}
+
+func (n noopBazelContext) GetCcObjectFiles(label string, archType ArchType) ([]string, bool) {
panic("unimplemented")
}
@@ -207,8 +232,9 @@ func (context *bazelContext) BazelEnabled() bool {
// If the given request was already made (and the results are available), then
// returns (result, true). If the request is queued but no results are available,
// then returns ("", false).
-func (context *bazelContext) cquery(label string, requestType CqueryRequestType) (string, bool) {
- key := cqueryKey{label, requestType}
+func (context *bazelContext) cquery(label string, requestType CqueryRequestType,
+ archType ArchType) (string, bool) {
+ key := cqueryKey{label, requestType, archType}
if result, ok := context.results[key]; ok {
return result, true
} else {
@@ -241,17 +267,21 @@ func (context *bazelContext) issueBazelCommand(runName bazel.RunName, command st
fmt.Sprintf("--platforms=%s", canonicalizeLabel("//build/bazel/platforms:generic_x86_64")))
cmdFlags = append(cmdFlags,
fmt.Sprintf("--extra_toolchains=%s", canonicalizeLabel("//prebuilts/clang/host/linux-x86:all")))
+ // Explicitly disable downloading rules (such as canonical C++ and Java rules) from the network.
+ cmdFlags = append(cmdFlags, "--experimental_repository_disable_download")
cmdFlags = append(cmdFlags, extraFlags...)
bazelCmd := exec.Command(context.bazelPath, cmdFlags...)
bazelCmd.Dir = context.workspaceDir
- bazelCmd.Env = append(os.Environ(), "HOME="+context.homeDir, pwdPrefix())
-
+ bazelCmd.Env = append(os.Environ(), "HOME="+context.homeDir, pwdPrefix(),
+ // Disables local host detection of gcc; toolchain information is defined
+ // explicitly in BUILD files.
+ "BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1")
stderr := &bytes.Buffer{}
bazelCmd.Stderr = stderr
if output, err := bazelCmd.Output(); err != nil {
- return "", fmt.Errorf("bazel command failed. command: [%s], error [%s]", bazelCmd, stderr)
+ return "", fmt.Errorf("bazel command failed. command: [%s], env: [%s], error [%s]", bazelCmd, bazelCmd.Env, stderr)
} else {
return string(output), nil
}
@@ -273,20 +303,81 @@ local_repository(
}
func (context *bazelContext) mainBzlFileContents() []byte {
+ // TODO(cparsons): Define configuration transitions programmatically based
+ // on available archs.
contents := `
#####################################################
# This file is generated by soong_build. Do not edit.
#####################################################
+def _x86_64_transition_impl(settings, attr):
+ return {
+ "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_x86_64",
+ }
+
+def _x86_transition_impl(settings, attr):
+ return {
+ "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_x86",
+ }
+
+def _arm64_transition_impl(settings, attr):
+ return {
+ "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_arm64",
+ }
+
+def _arm_transition_impl(settings, attr):
+ return {
+ "//command_line_option:platforms": "@sourceroot//build/bazel/platforms:generic_arm",
+ }
+
+x86_64_transition = transition(
+ implementation = _x86_64_transition_impl,
+ inputs = [],
+ outputs = [
+ "//command_line_option:platforms",
+ ],
+)
+
+x86_transition = transition(
+ implementation = _x86_transition_impl,
+ inputs = [],
+ outputs = [
+ "//command_line_option:platforms",
+ ],
+)
+
+arm64_transition = transition(
+ implementation = _arm64_transition_impl,
+ inputs = [],
+ outputs = [
+ "//command_line_option:platforms",
+ ],
+)
+
+arm_transition = transition(
+ implementation = _arm_transition_impl,
+ inputs = [],
+ outputs = [
+ "//command_line_option:platforms",
+ ],
+)
+
def _mixed_build_root_impl(ctx):
- return [DefaultInfo(files = depset(ctx.files.deps))]
+ all_files = ctx.files.deps_x86_64 + ctx.files.deps_x86 + ctx.files.deps_arm64 + ctx.files.deps_arm
+ return [DefaultInfo(files = depset(all_files))]
# Rule representing the root of the build, to depend on all Bazel targets that
# are required for the build. Building this target will build the entire Bazel
# build tree.
mixed_build_root = rule(
implementation = _mixed_build_root_impl,
- attrs = {"deps" : attr.label_list()},
+ attrs = {
+ "deps_x86_64" : attr.label_list(cfg = x86_64_transition),
+ "deps_x86" : attr.label_list(cfg = x86_transition),
+ "deps_arm64" : attr.label_list(cfg = arm64_transition),
+ "deps_arm" : attr.label_list(cfg = arm_transition),
+ "_allowlist_function_transition": attr.label(default = "@bazel_tools//tools/allowlists/function_transition_allowlist"),
+ },
)
def _phony_root_impl(ctx):
@@ -317,25 +408,48 @@ func canonicalizeLabel(label string) string {
}
func (context *bazelContext) mainBuildFileContents() []byte {
+ // TODO(cparsons): Map label to attribute programmatically; don't use hard-coded
+ // architecture mapping.
formatString := `
# This file is generated by soong_build. Do not edit.
load(":main.bzl", "mixed_build_root", "phony_root")
mixed_build_root(name = "buildroot",
- deps = [%s],
+ deps_x86_64 = [%s],
+ deps_x86 = [%s],
+ deps_arm64 = [%s],
+ deps_arm = [%s],
)
phony_root(name = "phonyroot",
deps = [":buildroot"],
)
`
- var buildRootDeps []string = nil
+ var deps_x86_64 []string = nil
+ var deps_x86 []string = nil
+ var deps_arm64 []string = nil
+ var deps_arm []string = nil
for val, _ := range context.requests {
- buildRootDeps = append(buildRootDeps, fmt.Sprintf("\"%s\"", canonicalizeLabel(val.label)))
+ labelString := fmt.Sprintf("\"%s\"", canonicalizeLabel(val.label))
+ switch getArchString(val) {
+ case "x86_64":
+ deps_x86_64 = append(deps_x86_64, labelString)
+ case "x86":
+ deps_x86 = append(deps_x86, labelString)
+ case "arm64":
+ deps_arm64 = append(deps_arm64, labelString)
+ case "arm":
+ deps_arm = append(deps_arm, labelString)
+ default:
+ panic(fmt.Sprintf("unhandled architecture %s for %v", getArchString(val), val))
+ }
}
- buildRootDepsString := strings.Join(buildRootDeps, ",\n ")
- return []byte(fmt.Sprintf(formatString, buildRootDepsString))
+ return []byte(fmt.Sprintf(formatString,
+ strings.Join(deps_x86_64, ",\n "),
+ strings.Join(deps_x86, ",\n "),
+ strings.Join(deps_arm64, ",\n "),
+ strings.Join(deps_arm, ",\n ")))
}
func (context *bazelContext) cqueryStarlarkFileContents() []byte {
@@ -345,23 +459,64 @@ getAllFilesLabels = {
%s
}
+getCcObjectFilesLabels = {
+ %s
+}
+
+def get_cc_object_files(target):
+ result = []
+ linker_inputs = providers(target)["CcInfo"].linking_context.linker_inputs.to_list()
+
+ for linker_input in linker_inputs:
+ for library in linker_input.libraries:
+ for object in library.objects:
+ result += [object.path]
+ return result
+
+def get_arch(target):
+ buildoptions = build_options(target)
+ platforms = build_options(target)["//command_line_option:platforms"]
+ if len(platforms) != 1:
+ # An individual configured target should have only one platform architecture.
+ # Note that it's fine for there to be multiple architectures for the same label,
+ # but each is its own configured target.
+ fail("expected exactly 1 platform for " + str(target.label) + " but got " + str(platforms))
+ platform_name = build_options(target)["//command_line_option:platforms"][0].name
+ if platform_name == "host":
+ return "HOST"
+ elif not platform_name.startswith("generic_"):
+ fail("expected platform name of the form 'generic_<arch>', but was " + str(platforms))
+ return "UNKNOWN"
+ return platform_name[len("generic_"):]
+
def format(target):
- if str(target.label) in getAllFilesLabels:
- return str(target.label) + ">>" + ', '.join([f.path for f in target.files.to_list()])
+ id_string = str(target.label) + "|" + get_arch(target)
+ if id_string in getAllFilesLabels:
+ return id_string + ">>" + ', '.join([f.path for f in target.files.to_list()])
+ elif id_string in getCcObjectFilesLabels:
+ return id_string + ">>" + ', '.join(get_cc_object_files(target))
else:
# This target was not requested via cquery, and thus must be a dependency
# of a requested target.
- return ""
+ return id_string + ">>NONE"
`
- var buildRootDeps []string = nil
- // TODO(cparsons): Sort by request type instead of assuming all requests
- // are of GetAllFiles type.
+ var getAllFilesDeps []string = nil
+ var getCcObjectFilesDeps []string = nil
+
for val, _ := range context.requests {
- buildRootDeps = append(buildRootDeps, fmt.Sprintf("\"%s\" : True", canonicalizeLabel(val.label)))
+ labelWithArch := getCqueryId(val)
+ mapEntryString := fmt.Sprintf("%q : True", labelWithArch)
+ switch val.requestType {
+ case getAllFiles:
+ getAllFilesDeps = append(getAllFilesDeps, mapEntryString)
+ case getCcObjectFiles:
+ getCcObjectFilesDeps = append(getCcObjectFilesDeps, mapEntryString)
+ }
}
- buildRootDepsString := strings.Join(buildRootDeps, ",\n ")
+ getAllFilesDepsString := strings.Join(getAllFilesDeps, ",\n ")
+ getCcObjectFilesDepsString := strings.Join(getCcObjectFilesDeps, ",\n ")
- return []byte(fmt.Sprintf(formatString, buildRootDepsString))
+ return []byte(fmt.Sprintf(formatString, getAllFilesDepsString, getCcObjectFilesDepsString))
}
// Returns a workspace-relative path containing build-related metadata required
@@ -414,9 +569,15 @@ func (context *bazelContext) InvokeBazel() error {
}
buildrootLabel := "//:buildroot"
cqueryOutput, err = context.issueBazelCommand(bazel.CqueryBuildRootRunName, "cquery",
- []string{fmt.Sprintf("deps(%s)", buildrootLabel)},
+ []string{fmt.Sprintf("kind(rule, deps(%s))", buildrootLabel)},
"--output=starlark",
"--starlark:file="+cqueryFileRelpath)
+ err = ioutil.WriteFile(
+ absolutePath(filepath.Join(context.intermediatesDir(), "cquery.out")),
+ []byte(cqueryOutput), 0666)
+ if err != nil {
+ return err
+ }
if err != nil {
return err
@@ -431,10 +592,10 @@ func (context *bazelContext) InvokeBazel() error {
}
for val, _ := range context.requests {
- if cqueryResult, ok := cqueryResults[canonicalizeLabel(val.label)]; ok {
+ if cqueryResult, ok := cqueryResults[getCqueryId(val)]; ok {
context.results[val] = string(cqueryResult)
} else {
- return fmt.Errorf("missing result for bazel target %s", val.label)
+ return fmt.Errorf("missing result for bazel target %s. query output: [%s]", getCqueryId(val), cqueryOutput)
}
}
@@ -510,6 +671,9 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
// Register bazel-owned build statements (obtained from the aquery invocation).
for index, buildStatement := range ctx.Config().BazelContext.BuildStatementsToRegister() {
+ if len(buildStatement.Command) < 1 {
+ panic(fmt.Sprintf("unhandled build statement: %s", buildStatement))
+ }
rule := NewRuleBuilder(pctx, ctx)
cmd := rule.Command()
cmd.Text(fmt.Sprintf("cd %s/execroot/__main__ && %s",
@@ -531,3 +695,16 @@ func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
rule.Build(fmt.Sprintf("bazel %d", index), buildStatement.Mnemonic)
}
}
+
+func getCqueryId(key cqueryKey) string {
+ return canonicalizeLabel(key.label) + "|" + getArchString(key)
+}
+
+func getArchString(key cqueryKey) string {
+ arch := key.archType.Name
+ if len(arch) > 0 {
+ return arch
+ } else {
+ return "x86_64"
+ }
+}
diff --git a/android/config.go b/android/config.go
index 6a093fc7a..949119d5a 100644
--- a/android/config.go
+++ b/android/config.go
@@ -232,7 +232,7 @@ func TestConfig(buildDir string, env map[string]string, bp string, fs map[string
// Copy the real PATH value to the test environment, it's needed by
// NonHermeticHostSystemTool() used in x86_darwin_host.go
- envCopy["PATH"] = originalEnv["PATH"]
+ envCopy["PATH"] = os.Getenv("PATH")
config := &config{
productVariables: productVariables{
@@ -305,10 +305,7 @@ func TestArchConfigFuchsia(buildDir string, env map[string]string, bp string, fs
return testConfig
}
-// TestArchConfig returns a Config object suitable for using for tests that
-// need to run the arch mutator.
-func TestArchConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
- testConfig := TestConfig(buildDir, env, bp, fs)
+func modifyTestConfigToSupportArchMutator(testConfig Config) {
config := testConfig.config
config.Targets = map[OsType][]Target{
@@ -334,7 +331,13 @@ func TestArchConfig(buildDir string, env map[string]string, bp string, fs map[st
config.TestProductVariables.DeviceArchVariant = proptools.StringPtr("armv8-a")
config.TestProductVariables.DeviceSecondaryArch = proptools.StringPtr("arm")
config.TestProductVariables.DeviceSecondaryArchVariant = proptools.StringPtr("armv7-a-neon")
+}
+// TestArchConfig returns a Config object suitable for using for tests that
+// need to run the arch mutator.
+func TestArchConfig(buildDir string, env map[string]string, bp string, fs map[string][]byte) Config {
+ testConfig := TestConfig(buildDir, env, bp, fs)
+ modifyTestConfigToSupportArchMutator(testConfig)
return testConfig
}
@@ -913,6 +916,25 @@ func (c *config) XrefCuEncoding() string {
return "json"
}
+// XrefCuJavaSourceMax returns the maximum number of the Java source files
+// in a single compilation unit
+const xrefJavaSourceFileMaxDefault = "1000"
+
+func (c Config) XrefCuJavaSourceMax() string {
+ v := c.Getenv("KYTHE_JAVA_SOURCE_BATCH_SIZE")
+ if v == "" {
+ return xrefJavaSourceFileMaxDefault
+ }
+ if _, err := strconv.ParseUint(v, 0, 0); err != nil {
+ fmt.Fprintf(os.Stderr,
+ "bad KYTHE_JAVA_SOURCE_BATCH_SIZE value: %s, will use %s",
+ err, xrefJavaSourceFileMaxDefault)
+ return xrefJavaSourceFileMaxDefault
+ }
+ return v
+
+}
+
func (c *config) EmitXrefRules() bool {
return c.XrefCorpusName() != ""
}
diff --git a/android/defs.go b/android/defs.go
index 38ecb0505..1a767214c 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -57,6 +57,15 @@ var (
},
"cpFlags")
+ // A copy rule that only updates the output if it changed.
+ CpIfChanged = pctx.AndroidStaticRule("CpIfChanged",
+ blueprint.RuleParams{
+ Command: "if ! cmp -s $in $out; then cp $in $out; fi",
+ Description: "cp if changed $out",
+ Restat: true,
+ },
+ "cpFlags")
+
CpExecutable = pctx.AndroidStaticRule("CpExecutable",
blueprint.RuleParams{
Command: "rm -f $out && cp $cpPreserveSymlinks $cpFlags $in $out && chmod +x $out",
diff --git a/android/env.go b/android/env.go
index 57617e71c..16de86769 100644
--- a/android/env.go
+++ b/android/env.go
@@ -15,13 +15,10 @@
package android
import (
- "fmt"
"os"
- "os/exec"
"strings"
- "syscall"
- "android/soong/env"
+ "android/soong/shared"
)
// This file supports dependencies on environment variables. During build manifest generation,
@@ -32,75 +29,25 @@ import (
// a manifest regeneration.
var originalEnv map[string]string
-var soongDelveListen string
-var soongDelvePath string
-var soongDelveEnv []string
var SdclangEnv map[string]string
var QiifaBuildConfig string
-func init() {
- // Delve support needs to read this environment variable very early, before NewConfig has created a way to
- // access originalEnv with dependencies. Store the value where soong_build can find it, it will manually
- // ensure the dependencies are created.
- soongDelveListen = os.Getenv("SOONG_DELVE")
- soongDelvePath = os.Getenv("SOONG_DELVE_PATH")
- if soongDelvePath == "" {
- soongDelvePath, _ = exec.LookPath("dlv")
- }
- originalEnv = make(map[string]string)
- soongDelveEnv = []string{}
+func InitEnvironment(envFile string) {
+ var err error
+ originalEnv, err = shared.EnvFromFile(envFile)
+ if err != nil {
+ panic(err)
+ }
+ // TODO(b/182662723) move functionality as necessary
SdclangEnv = make(map[string]string)
for _, env := range os.Environ() {
idx := strings.IndexRune(env, '=')
if idx != -1 {
- originalEnv[env[:idx]] = env[idx+1:]
- if env[:idx] != "SOONG_DELVE" && env[:idx] != "SOONG_DELVE_PATH" {
- soongDelveEnv = append(soongDelveEnv, env)
- }
SdclangEnv[env[:idx]] = env[idx+1:]
}
}
QiifaBuildConfig = originalEnv["QIIFA_BUILD_CONFIG"]
- // Clear the environment to prevent use of os.Getenv(), which would not provide dependencies on environment
- // variable values. The environment is available through ctx.Config().Getenv, ctx.Config().IsEnvTrue, etc.
- os.Clearenv()
-}
-
-func ReexecWithDelveMaybe() {
- if soongDelveListen == "" {
- return
- }
-
- if soongDelvePath == "" {
- fmt.Fprintln(os.Stderr, "SOONG_DELVE is set but failed to find dlv")
- os.Exit(1)
- }
- dlvArgv := []string{
- soongDelvePath,
- "--listen=:" + soongDelveListen,
- "--headless=true",
- "--api-version=2",
- "exec",
- os.Args[0],
- "--",
- }
- dlvArgv = append(dlvArgv, os.Args[1:]...)
- os.Chdir(absSrcDir)
- syscall.Exec(soongDelvePath, dlvArgv, soongDelveEnv)
- fmt.Fprintln(os.Stderr, "exec() failed while trying to reexec with Delve")
- os.Exit(1)
-}
-
-// getenv checks either os.Getenv or originalEnv so that it works before or after the init()
-// function above. It doesn't add any dependencies on the environment variable, so it should
-// only be used for values that won't change. For values that might change use ctx.Config().Getenv.
-func getenv(key string) string {
- if originalEnv == nil {
- return os.Getenv(key)
- } else {
- return originalEnv[key]
- }
}
func EnvSingleton() Singleton {
@@ -112,12 +59,12 @@ type envSingleton struct{}
func (c *envSingleton) GenerateBuildActions(ctx SingletonContext) {
envDeps := ctx.Config().EnvDeps()
- envFile := PathForOutput(ctx, ".soong.environment")
+ envFile := PathForOutput(ctx, "soong.environment.used")
if ctx.Failed() {
return
}
- data, err := env.EnvFileContents(envDeps)
+ data, err := shared.EnvFileContents(envDeps)
if err != nil {
ctx.Errorf(err.Error())
}
diff --git a/android/filegroup.go b/android/filegroup.go
index 674a196cb..2eb474187 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -24,6 +24,10 @@ func init() {
RegisterBp2BuildMutator("filegroup", FilegroupBp2Build)
}
+var PrepareForTestWithFilegroup = FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("filegroup", FileGroupFactory)
+})
+
// https://docs.bazel.build/versions/master/be/general.html#filegroup
type bazelFilegroupAttributes struct {
Srcs bazel.LabelList
@@ -49,7 +53,7 @@ func (bfg *bazelFilegroup) GenerateAndroidBuildActions(ctx ModuleContext) {}
func FilegroupBp2Build(ctx TopDownMutatorContext) {
fg, ok := ctx.Module().(*fileGroup)
- if !ok || !fg.properties.Bazel_module.Bp2build_available {
+ if !ok || !fg.ConvertWithBp2build() {
return
}
@@ -57,9 +61,9 @@ func FilegroupBp2Build(ctx TopDownMutatorContext) {
Srcs: BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs),
}
- props := bazel.NewBazelTargetModuleProperties(fg.Name(), "filegroup", "")
+ props := bazel.BazelTargetModuleProperties{Rule_class: "filegroup"}
- ctx.CreateBazelTargetModule(BazelFileGroupFactory, props, attrs)
+ ctx.CreateBazelTargetModule(BazelFileGroupFactory, fg.Name(), props, attrs)
}
type fileGroupProperties struct {
@@ -77,13 +81,11 @@ type fileGroupProperties struct {
// Create a make variable with the specified name that contains the list of files in the
// filegroup, relative to the root of the source tree.
Export_to_make_var *string
-
- // Properties for Bazel migration purposes.
- bazel.Properties
}
type fileGroup struct {
ModuleBase
+ BazelModuleBase
properties fileGroupProperties
srcs Paths
}
@@ -97,6 +99,7 @@ func FileGroupFactory() Module {
module := &fileGroup{}
module.AddProperties(&module.properties)
InitAndroidModule(module)
+ InitBazelModule(module)
return module
}
diff --git a/android/fixture.go b/android/fixture.go
new file mode 100644
index 000000000..485ca2321
--- /dev/null
+++ b/android/fixture.go
@@ -0,0 +1,810 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import (
+ "fmt"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+// Provides support for creating test fixtures on which tests can be run. Reduces duplication
+// of test setup by allow tests to easily reuse setup code.
+//
+// Fixture
+// =======
+// These determine the environment within which a test can be run. Fixtures are mutable and are
+// created by FixtureFactory instances and mutated by FixturePreparer instances. They are created by
+// first creating a base Fixture (which is essentially empty) and then applying FixturePreparer
+// instances to it to modify the environment.
+//
+// FixtureFactory
+// ==============
+// These are responsible for creating fixtures. Factories are immutable and are intended to be
+// initialized once and reused to create multiple fixtures. Each factory has a list of fixture
+// preparers that prepare a fixture for running a test. Factories can also be used to create other
+// factories by extending them with additional fixture preparers.
+//
+// FixturePreparer
+// ===============
+// These are responsible for modifying a Fixture in preparation for it to run a test. Preparers are
+// intended to be immutable and able to prepare multiple Fixture objects simultaneously without
+// them sharing any data.
+//
+// FixturePreparers are only ever invoked once per test fixture. Prior to invocation the list of
+// FixturePreparers are flattened and deduped while preserving the order they first appear in the
+// list. This makes it easy to reuse, group and combine FixturePreparers together.
+//
+// Each small self contained piece of test setup should be their own FixturePreparer. e.g.
+// * A group of related modules.
+// * A group of related mutators.
+// * A combination of both.
+// * Configuration.
+//
+// They should not overlap, e.g. the same module type should not be registered by different
+// FixturePreparers as using them both would cause a build error. In that case the preparer should
+// be split into separate parts and combined together using FixturePreparers(...).
+//
+// e.g. attempting to use AllPreparers in preparing a Fixture would break as it would attempt to
+// register module bar twice:
+// var Preparer1 = FixtureRegisterWithContext(RegisterModuleFooAndBar)
+// var Preparer2 = FixtureRegisterWithContext(RegisterModuleBarAndBaz)
+// var AllPreparers = GroupFixturePreparers(Preparer1, Preparer2)
+//
+// However, when restructured like this it would work fine:
+// var PreparerFoo = FixtureRegisterWithContext(RegisterModuleFoo)
+// var PreparerBar = FixtureRegisterWithContext(RegisterModuleBar)
+// var PreparerBaz = FixtureRegisterWithContext(RegisterModuleBaz)
+// var Preparer1 = GroupFixturePreparers(RegisterModuleFoo, RegisterModuleBar)
+// var Preparer2 = GroupFixturePreparers(RegisterModuleBar, RegisterModuleBaz)
+// var AllPreparers = GroupFixturePreparers(Preparer1, Preparer2)
+//
+// As after deduping and flattening AllPreparers would result in the following preparers being
+// applied:
+// 1. PreparerFoo
+// 2. PreparerBar
+// 3. PreparerBaz
+//
+// Preparers can be used for both integration and unit tests.
+//
+// Integration tests typically use all the module types, mutators and singletons that are available
+// for that package to try and replicate the behavior of the runtime build as closely as possible.
+// However, that realism comes at a cost of increased fragility (as they can be broken by changes in
+// many different parts of the build) and also increased runtime, especially if they use lots of
+// singletons and mutators.
+//
+// Unit tests on the other hand try and minimize the amount of code being tested which makes them
+// less susceptible to changes elsewhere in the build and quick to run but at a cost of potentially
+// not testing realistic scenarios.
+//
+// Supporting unit tests effectively require that preparers are available at the lowest granularity
+// possible. Supporting integration tests effectively require that the preparers are organized into
+// groups that provide all the functionality available.
+//
+// At least in terms of tests that check the behavior of build components via processing
+// `Android.bp` there is no clear separation between a unit test and an integration test. Instead
+// they vary from one end that tests a single module (e.g. filegroup) to the other end that tests a
+// whole system of modules, mutators and singletons (e.g. apex + hiddenapi).
+//
+// TestResult
+// ==========
+// These are created by running tests in a Fixture and provide access to the Config and TestContext
+// in which the tests were run.
+//
+// Example
+// =======
+//
+// An exported preparer for use by other packages that need to use java modules.
+//
+// package java
+// var PrepareForIntegrationTestWithJava = GroupFixturePreparers(
+// android.PrepareForIntegrationTestWithAndroid,
+// FixtureRegisterWithContext(RegisterAGroupOfRelatedModulesMutatorsAndSingletons),
+// FixtureRegisterWithContext(RegisterAnotherGroupOfRelatedModulesMutatorsAndSingletons),
+// ...
+// )
+//
+// Some files to use in tests in the java package.
+//
+// var javaMockFS = android.MockFS{
+// "api/current.txt": nil,
+// "api/removed.txt": nil,
+// ...
+// }
+//
+// A package private factory for use for testing java within the java package.
+//
+// var javaFixtureFactory = NewFixtureFactory(
+// PrepareForIntegrationTestWithJava,
+// FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+// ctx.RegisterModuleType("test_module", testModule)
+// }),
+// javaMockFS.AddToFixture(),
+// ...
+// }
+//
+// func TestJavaStuff(t *testing.T) {
+// result := javaFixtureFactory.RunTest(t,
+// android.FixtureWithRootAndroidBp(`java_library {....}`),
+// android.MockFS{...}.AddToFixture(),
+// )
+// ... test result ...
+// }
+//
+// package cc
+// var PrepareForTestWithCC = GroupFixturePreparers(
+// android.PrepareForArchMutator,
+// android.prepareForPrebuilts,
+// FixtureRegisterWithContext(RegisterRequiredBuildComponentsForTest),
+// ...
+// )
+//
+// package apex
+//
+// var PrepareForApex = GroupFixturePreparers(
+// ...
+// )
+//
+// Use modules and mutators from java, cc and apex. Any duplicate preparers (like
+// android.PrepareForArchMutator) will be automatically deduped.
+//
+// var apexFixtureFactory = android.NewFixtureFactory(
+// PrepareForJava,
+// PrepareForCC,
+// PrepareForApex,
+// )
+
+// Factory for Fixture objects.
+//
+// This is configured with a set of FixturePreparer objects that are used to
+// initialize each Fixture instance this creates.
+type FixtureFactory interface {
+
+ // Creates a copy of this instance and adds some additional preparers.
+ //
+ // Before the preparers are used they are combined with the preparers provided when the factory
+ // was created, any groups of preparers are flattened, and the list is deduped so that each
+ // preparer is only used once. See the file documentation in android/fixture.go for more details.
+ Extend(preparers ...FixturePreparer) FixtureFactory
+
+ // Create a Fixture.
+ Fixture(t *testing.T, preparers ...FixturePreparer) Fixture
+
+ // ExtendWithErrorHandler creates a new FixtureFactory that will use the supplied error handler
+ // to check the errors (may be 0) reported by the test.
+ //
+ // The default handlers is FixtureExpectsNoErrors which will fail the go test immediately if any
+ // errors are reported.
+ ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory
+
+ // Run the test, checking any errors reported and returning a TestResult instance.
+ //
+ // Shorthand for Fixture(t, preparers...).RunTest()
+ RunTest(t *testing.T, preparers ...FixturePreparer) *TestResult
+
+ // Run the test with the supplied Android.bp file.
+ //
+ // Shorthand for RunTest(t, android.FixtureWithRootAndroidBp(bp))
+ RunTestWithBp(t *testing.T, bp string) *TestResult
+}
+
+// Create a new FixtureFactory that will apply the supplied preparers.
+//
+// The buildDirSupplier is a pointer to the package level buildDir variable that is initialized by
+// the package level setUp method. It has to be a pointer to the variable as the variable will not
+// have been initialized at the time the factory is created.
+func NewFixtureFactory(buildDirSupplier *string, preparers ...FixturePreparer) FixtureFactory {
+ return &fixtureFactory{
+ buildDirSupplier: buildDirSupplier,
+ preparers: dedupAndFlattenPreparers(nil, preparers),
+
+ // Set the default error handler.
+ errorHandler: FixtureExpectsNoErrors,
+ }
+}
+
+// A set of mock files to add to the mock file system.
+type MockFS map[string][]byte
+
+func (fs MockFS) Merge(extra map[string][]byte) {
+ for p, c := range extra {
+ fs[p] = c
+ }
+}
+
+func (fs MockFS) AddToFixture() FixturePreparer {
+ return FixtureMergeMockFs(fs)
+}
+
+// Modify the config
+func FixtureModifyConfig(mutator func(config Config)) FixturePreparer {
+ return newSimpleFixturePreparer(func(f *fixture) {
+ mutator(f.config)
+ })
+}
+
+// Modify the config and context
+func FixtureModifyConfigAndContext(mutator func(config Config, ctx *TestContext)) FixturePreparer {
+ return newSimpleFixturePreparer(func(f *fixture) {
+ mutator(f.config, f.ctx)
+ })
+}
+
+// Modify the context
+func FixtureModifyContext(mutator func(ctx *TestContext)) FixturePreparer {
+ return newSimpleFixturePreparer(func(f *fixture) {
+ mutator(f.ctx)
+ })
+}
+
+func FixtureRegisterWithContext(registeringFunc func(ctx RegistrationContext)) FixturePreparer {
+ return FixtureModifyContext(func(ctx *TestContext) { registeringFunc(ctx) })
+}
+
+// Modify the mock filesystem
+func FixtureModifyMockFS(mutator func(fs MockFS)) FixturePreparer {
+ return newSimpleFixturePreparer(func(f *fixture) {
+ mutator(f.mockFS)
+ })
+}
+
+// Merge the supplied file system into the mock filesystem.
+//
+// Paths that already exist in the mock file system are overridden.
+func FixtureMergeMockFs(mockFS MockFS) FixturePreparer {
+ return FixtureModifyMockFS(func(fs MockFS) {
+ fs.Merge(mockFS)
+ })
+}
+
+// Add a file to the mock filesystem
+func FixtureAddFile(path string, contents []byte) FixturePreparer {
+ return FixtureModifyMockFS(func(fs MockFS) {
+ fs[path] = contents
+ })
+}
+
+// Add a text file to the mock filesystem
+func FixtureAddTextFile(path string, contents string) FixturePreparer {
+ return FixtureAddFile(path, []byte(contents))
+}
+
+// Add the root Android.bp file with the supplied contents.
+func FixtureWithRootAndroidBp(contents string) FixturePreparer {
+ return FixtureAddTextFile("Android.bp", contents)
+}
+
+// Merge some environment variables into the fixture.
+func FixtureMergeEnv(env map[string]string) FixturePreparer {
+ return FixtureModifyConfig(func(config Config) {
+ for k, v := range env {
+ if k == "PATH" {
+ panic("Cannot set PATH environment variable")
+ }
+ config.env[k] = v
+ }
+ })
+}
+
+// Modify the env.
+//
+// Will panic if the mutator changes the PATH environment variable.
+func FixtureModifyEnv(mutator func(env map[string]string)) FixturePreparer {
+ return FixtureModifyConfig(func(config Config) {
+ oldPath := config.env["PATH"]
+ mutator(config.env)
+ newPath := config.env["PATH"]
+ if newPath != oldPath {
+ panic(fmt.Errorf("Cannot change PATH environment variable from %q to %q", oldPath, newPath))
+ }
+ })
+}
+
+// Allow access to the product variables when preparing the fixture.
+type FixtureProductVariables struct {
+ *productVariables
+}
+
+// Modify product variables.
+func FixtureModifyProductVariables(mutator func(variables FixtureProductVariables)) FixturePreparer {
+ return FixtureModifyConfig(func(config Config) {
+ productVariables := FixtureProductVariables{&config.productVariables}
+ mutator(productVariables)
+ })
+}
+
+// GroupFixturePreparers creates a composite FixturePreparer that is equivalent to applying each of
+// the supplied FixturePreparer instances in order.
+//
+// Before preparing the fixture the list of preparers is flattened by replacing each
+// instance of GroupFixturePreparers with its contents.
+func GroupFixturePreparers(preparers ...FixturePreparer) FixturePreparer {
+ return &compositeFixturePreparer{dedupAndFlattenPreparers(nil, preparers)}
+}
+
+type simpleFixturePreparerVisitor func(preparer *simpleFixturePreparer)
+
+// FixturePreparer is an opaque interface that can change a fixture.
+type FixturePreparer interface {
+ // visit calls the supplied visitor with each *simpleFixturePreparer instances in this preparer,
+ visit(simpleFixturePreparerVisitor)
+}
+
+type fixturePreparers []FixturePreparer
+
+func (f fixturePreparers) visit(visitor simpleFixturePreparerVisitor) {
+ for _, p := range f {
+ p.visit(visitor)
+ }
+}
+
+// dedupAndFlattenPreparers removes any duplicates and flattens any composite FixturePreparer
+// instances.
+//
+// base - a list of already flattened and deduped preparers that will be applied first before
+// the list of additional preparers. Any duplicates of these in the additional preparers
+// will be ignored.
+//
+// preparers - a list of additional unflattened, undeduped preparers that will be applied after the
+// base preparers.
+//
+// Returns a deduped and flattened list of the preparers minus any that exist in the base preparers.
+func dedupAndFlattenPreparers(base []*simpleFixturePreparer, preparers fixturePreparers) []*simpleFixturePreparer {
+ var list []*simpleFixturePreparer
+ visited := make(map[*simpleFixturePreparer]struct{})
+
+ // Mark the already flattened and deduped preparers, if any, as having been seen so that
+ // duplicates of these in the additional preparers will be discarded.
+ for _, s := range base {
+ visited[s] = struct{}{}
+ }
+
+ preparers.visit(func(preparer *simpleFixturePreparer) {
+ if _, seen := visited[preparer]; !seen {
+ visited[preparer] = struct{}{}
+ list = append(list, preparer)
+ }
+ })
+ return list
+}
+
+// compositeFixturePreparer is a FixturePreparer created from a list of fixture preparers.
+type compositeFixturePreparer struct {
+ preparers []*simpleFixturePreparer
+}
+
+func (c *compositeFixturePreparer) visit(visitor simpleFixturePreparerVisitor) {
+ for _, p := range c.preparers {
+ p.visit(visitor)
+ }
+}
+
+// simpleFixturePreparer is a FixturePreparer that applies a function to a fixture.
+type simpleFixturePreparer struct {
+ function func(fixture *fixture)
+}
+
+func (s *simpleFixturePreparer) visit(visitor simpleFixturePreparerVisitor) {
+ visitor(s)
+}
+
+func newSimpleFixturePreparer(preparer func(fixture *fixture)) FixturePreparer {
+ return &simpleFixturePreparer{function: preparer}
+}
+
+// FixtureErrorHandler determines how to respond to errors reported by the code under test.
+//
+// Some possible responses:
+// * Fail the test if any errors are reported, see FixtureExpectsNoErrors.
+// * Fail the test if at least one error that matches a pattern is not reported see
+// FixtureExpectsAtLeastOneErrorMatchingPattern
+// * Fail the test if any unexpected errors are reported.
+//
+// Although at the moment all the error handlers are implemented as simply a wrapper around a
+// function this is defined as an interface to allow future enhancements, e.g. provide different
+// ways other than patterns to match an error and to combine handlers together.
+type FixtureErrorHandler interface {
+ // CheckErrors checks the errors reported.
+ //
+ // The supplied result can be used to access the state of the code under test just as the main
+ // body of the test would but if any errors other than ones expected are reported the state may
+ // be indeterminate.
+ CheckErrors(result *TestResult)
+}
+
+type simpleErrorHandler struct {
+ function func(result *TestResult)
+}
+
+func (h simpleErrorHandler) CheckErrors(result *TestResult) {
+ result.Helper()
+ h.function(result)
+}
+
+// The default fixture error handler.
+//
+// Will fail the test immediately if any errors are reported.
+//
+// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
+// which the test is being run which means that the RunTest() method will not return.
+var FixtureExpectsNoErrors = FixtureCustomErrorHandler(
+ func(result *TestResult) {
+ result.Helper()
+ FailIfErrored(result.T, result.Errs)
+ },
+)
+
+// FixtureExpectsAtLeastOneMatchingError returns an error handler that will cause the test to fail
+// if at least one error that matches the regular expression is not found.
+//
+// The test will be failed if:
+// * No errors are reported.
+// * One or more errors are reported but none match the pattern.
+//
+// The test will not fail if:
+// * Multiple errors are reported that do not match the pattern as long as one does match.
+//
+// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
+// which the test is being run which means that the RunTest() method will not return.
+func FixtureExpectsAtLeastOneErrorMatchingPattern(pattern string) FixtureErrorHandler {
+ return FixtureCustomErrorHandler(func(result *TestResult) {
+ result.Helper()
+ if !FailIfNoMatchingErrors(result.T, pattern, result.Errs) {
+ result.FailNow()
+ }
+ })
+}
+
+// FixtureExpectsOneErrorToMatchPerPattern returns an error handler that will cause the test to fail
+// if there are any unexpected errors.
+//
+// The test will be failed if:
+// * The number of errors reported does not exactly match the patterns.
+// * One or more of the reported errors do not match a pattern.
+// * No patterns are provided and one or more errors are reported.
+//
+// The test will not fail if:
+// * One or more of the patterns does not match an error.
+//
+// If the test fails this handler will call `result.FailNow()` which will exit the goroutine within
+// which the test is being run which means that the RunTest() method will not return.
+func FixtureExpectsAllErrorsToMatchAPattern(patterns []string) FixtureErrorHandler {
+ return FixtureCustomErrorHandler(func(result *TestResult) {
+ result.Helper()
+ CheckErrorsAgainstExpectations(result.T, result.Errs, patterns)
+ })
+}
+
+// FixtureCustomErrorHandler creates a custom error handler
+func FixtureCustomErrorHandler(function func(result *TestResult)) FixtureErrorHandler {
+ return simpleErrorHandler{
+ function: function,
+ }
+}
+
+// Fixture defines the test environment.
+type Fixture interface {
+ // Run the test, checking any errors reported and returning a TestResult instance.
+ RunTest() *TestResult
+}
+
+// Provides general test support.
+type TestHelper struct {
+ *testing.T
+}
+
+// AssertBoolEquals checks if the expected and actual values are equal and if they are not then it
+// reports an error prefixed with the supplied message and including a reason for why it failed.
+func (h *TestHelper) AssertBoolEquals(message string, expected bool, actual bool) {
+ h.Helper()
+ if actual != expected {
+ h.Errorf("%s: expected %t, actual %t", message, expected, actual)
+ }
+}
+
+// AssertStringEquals checks if the expected and actual values are equal and if they are not then
+// it reports an error prefixed with the supplied message and including a reason for why it failed.
+func (h *TestHelper) AssertStringEquals(message string, expected string, actual string) {
+ h.Helper()
+ if actual != expected {
+ h.Errorf("%s: expected %s, actual %s", message, expected, actual)
+ }
+}
+
+// AssertErrorMessageEquals checks if the error is not nil and has the expected message. If it does
+// not then this reports an error prefixed with the supplied message and including a reason for why
+// it failed.
+func (h *TestHelper) AssertErrorMessageEquals(message string, expected string, actual error) {
+ h.Helper()
+ if actual == nil {
+ h.Errorf("Expected error but was nil")
+ } else if actual.Error() != expected {
+ h.Errorf("%s: expected %s, actual %s", message, expected, actual.Error())
+ }
+}
+
+// AssertTrimmedStringEquals checks if the expected and actual values are the same after trimming
+// leading and trailing spaces from them both. If they are not then it reports an error prefixed
+// with the supplied message and including a reason for why it failed.
+func (h *TestHelper) AssertTrimmedStringEquals(message string, expected string, actual string) {
+ h.Helper()
+ h.AssertStringEquals(message, strings.TrimSpace(expected), strings.TrimSpace(actual))
+}
+
+// AssertStringDoesContain checks if the string contains the expected substring. If it does not
+// then it reports an error prefixed with the supplied message and including a reason for why it
+// failed.
+func (h *TestHelper) AssertStringDoesContain(message string, s string, expectedSubstring string) {
+ h.Helper()
+ if !strings.Contains(s, expectedSubstring) {
+ h.Errorf("%s: could not find %q within %q", message, expectedSubstring, s)
+ }
+}
+
+// AssertStringDoesNotContain checks if the string contains the expected substring. If it does then
+// it reports an error prefixed with the supplied message and including a reason for why it failed.
+func (h *TestHelper) AssertStringDoesNotContain(message string, s string, unexpectedSubstring string) {
+ h.Helper()
+ if strings.Contains(s, unexpectedSubstring) {
+ h.Errorf("%s: unexpectedly found %q within %q", message, unexpectedSubstring, s)
+ }
+}
+
+// AssertArrayString checks if the expected and actual values are equal and if they are not then it
+// reports an error prefixed with the supplied message and including a reason for why it failed.
+func (h *TestHelper) AssertArrayString(message string, expected, actual []string) {
+ h.Helper()
+ if len(actual) != len(expected) {
+ h.Errorf("%s: expected %d (%q), actual (%d) %q", message, len(expected), expected, len(actual), actual)
+ return
+ }
+ for i := range actual {
+ if actual[i] != expected[i] {
+ h.Errorf("%s: expected %d-th, %q (%q), actual %q (%q)",
+ message, i, expected[i], expected, actual[i], actual)
+ return
+ }
+ }
+}
+
+// AssertArrayString checks if the expected and actual values are equal using reflect.DeepEqual and
+// if they are not then it reports an error prefixed with the supplied message and including a
+// reason for why it failed.
+func (h *TestHelper) AssertDeepEquals(message string, expected interface{}, actual interface{}) {
+ h.Helper()
+ if !reflect.DeepEqual(actual, expected) {
+ h.Errorf("%s: expected:\n %#v\n got:\n %#v", message, expected, actual)
+ }
+}
+
+// AssertPanic checks that the supplied function panics as expected.
+func (h *TestHelper) AssertPanic(message string, funcThatShouldPanic func()) {
+ h.Helper()
+ panicked := false
+ func() {
+ defer func() {
+ if x := recover(); x != nil {
+ panicked = true
+ }
+ }()
+ funcThatShouldPanic()
+ }()
+ if !panicked {
+ h.Error(message)
+ }
+}
+
+// Struct to allow TestResult to embed a *TestContext and allow call forwarding to its methods.
+type testContext struct {
+ *TestContext
+}
+
+// The result of running a test.
+type TestResult struct {
+ TestHelper
+ testContext
+
+ fixture *fixture
+ Config Config
+
+ // The errors that were reported during the test.
+ Errs []error
+}
+
+var _ FixtureFactory = (*fixtureFactory)(nil)
+
+type fixtureFactory struct {
+ buildDirSupplier *string
+ preparers []*simpleFixturePreparer
+ errorHandler FixtureErrorHandler
+}
+
+func (f *fixtureFactory) Extend(preparers ...FixturePreparer) FixtureFactory {
+ // Create a new slice to avoid accidentally sharing the preparers slice from this factory with
+ // the extending factories.
+ var all []*simpleFixturePreparer
+ all = append(all, f.preparers...)
+ all = append(all, dedupAndFlattenPreparers(f.preparers, preparers)...)
+ // Copy the existing factory.
+ extendedFactory := &fixtureFactory{}
+ *extendedFactory = *f
+ // Use the extended list of preparers.
+ extendedFactory.preparers = all
+ return extendedFactory
+}
+
+func (f *fixtureFactory) Fixture(t *testing.T, preparers ...FixturePreparer) Fixture {
+ config := TestConfig(*f.buildDirSupplier, nil, "", nil)
+ ctx := NewTestContext(config)
+ fixture := &fixture{
+ factory: f,
+ t: t,
+ config: config,
+ ctx: ctx,
+ mockFS: make(MockFS),
+ errorHandler: f.errorHandler,
+ }
+
+ for _, preparer := range f.preparers {
+ preparer.function(fixture)
+ }
+
+ for _, preparer := range dedupAndFlattenPreparers(f.preparers, preparers) {
+ preparer.function(fixture)
+ }
+
+ return fixture
+}
+
+func (f *fixtureFactory) ExtendWithErrorHandler(errorHandler FixtureErrorHandler) FixtureFactory {
+ newFactory := &fixtureFactory{}
+ *newFactory = *f
+ newFactory.errorHandler = errorHandler
+ return newFactory
+}
+
+func (f *fixtureFactory) RunTest(t *testing.T, preparers ...FixturePreparer) *TestResult {
+ t.Helper()
+ fixture := f.Fixture(t, preparers...)
+ return fixture.RunTest()
+}
+
+func (f *fixtureFactory) RunTestWithBp(t *testing.T, bp string) *TestResult {
+ t.Helper()
+ return f.RunTest(t, FixtureWithRootAndroidBp(bp))
+}
+
+type fixture struct {
+ // The factory used to create this fixture.
+ factory *fixtureFactory
+
+ // The gotest state of the go test within which this was created.
+ t *testing.T
+
+ // The configuration prepared for this fixture.
+ config Config
+
+ // The test context prepared for this fixture.
+ ctx *TestContext
+
+ // The mock filesystem prepared for this fixture.
+ mockFS MockFS
+
+ // The error handler used to check the errors, if any, that are reported.
+ errorHandler FixtureErrorHandler
+}
+
+func (f *fixture) RunTest() *TestResult {
+ f.t.Helper()
+
+ ctx := f.ctx
+
+ // The TestConfig() method assumes that the mock filesystem is available when creating so creates
+ // the mock file system immediately. Similarly, the NewTestContext(Config) method assumes that the
+ // supplied Config's FileSystem has been properly initialized before it is called and so it takes
+ // its own reference to the filesystem. However, fixtures create the Config and TestContext early
+ // so they can be modified by preparers at which time the mockFS has not been populated (because
+ // it too is modified by preparers). So, this reinitializes the Config and TestContext's
+ // FileSystem using the now populated mockFS.
+ f.config.mockFileSystem("", f.mockFS)
+ ctx.SetFs(ctx.config.fs)
+ if ctx.config.mockBpList != "" {
+ ctx.SetModuleListFile(ctx.config.mockBpList)
+ }
+
+ ctx.Register()
+ _, errs := ctx.ParseBlueprintsFiles("ignored")
+ if len(errs) == 0 {
+ _, errs = ctx.PrepareBuildActions(f.config)
+ }
+
+ result := &TestResult{
+ TestHelper: TestHelper{T: f.t},
+ testContext: testContext{ctx},
+ fixture: f,
+ Config: f.config,
+ Errs: errs,
+ }
+
+ f.errorHandler.CheckErrors(result)
+
+ return result
+}
+
+// NormalizePathForTesting removes the test invocation specific build directory from the supplied
+// path.
+//
+// If the path is within the build directory (e.g. an OutputPath) then this returns the relative
+// path to avoid tests having to deal with the dynamically generated build directory.
+//
+// Otherwise, this returns the supplied path as it is almost certainly a source path that is
+// relative to the root of the source tree.
+//
+// Even though some information is removed from some paths and not others it should be possible to
+// differentiate between them by the paths themselves, e.g. output paths will likely include
+// ".intermediates" but source paths won't.
+func (r *TestResult) NormalizePathForTesting(path Path) string {
+ pathContext := PathContextForTesting(r.Config)
+ pathAsString := path.String()
+ if rel, isRel := MaybeRel(pathContext, r.Config.BuildDir(), pathAsString); isRel {
+ return rel
+ }
+ return pathAsString
+}
+
+// NormalizePathsForTesting normalizes each path in the supplied list and returns their normalized
+// forms.
+func (r *TestResult) NormalizePathsForTesting(paths Paths) []string {
+ var result []string
+ for _, path := range paths {
+ result = append(result, r.NormalizePathForTesting(path))
+ }
+ return result
+}
+
+// NewFixture creates a new test fixture that is based on the one that created this result. It is
+// intended to test the output of module types that generate content to be processed by the build,
+// e.g. sdk snapshots.
+func (r *TestResult) NewFixture(preparers ...FixturePreparer) Fixture {
+ return r.fixture.factory.Fixture(r.T, preparers...)
+}
+
+// RunTest is shorthand for NewFixture(preparers...).RunTest().
+func (r *TestResult) RunTest(preparers ...FixturePreparer) *TestResult {
+ r.Helper()
+ return r.fixture.factory.Fixture(r.T, preparers...).RunTest()
+}
+
+// Module returns the module with the specific name and of the specified variant.
+func (r *TestResult) Module(name string, variant string) Module {
+ return r.ModuleForTests(name, variant).Module()
+}
+
+// Create a *TestResult object suitable for use within a subtest.
+//
+// This ensures that any errors reported by the TestResult, e.g. from within one of its
+// Assert... methods, will be associated with the sub test and not the main test.
+//
+// result := ....RunTest()
+// t.Run("subtest", func(t *testing.T) {
+// subResult := result.ResultForSubTest(t)
+// subResult.AssertStringEquals("something", ....)
+// })
+func (r *TestResult) ResultForSubTest(t *testing.T) *TestResult {
+ subTestResult := *r
+ r.T = t
+ return &subTestResult
+}
diff --git a/android/fixture_test.go b/android/fixture_test.go
new file mode 100644
index 000000000..5a7bf3b6e
--- /dev/null
+++ b/android/fixture_test.go
@@ -0,0 +1,49 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package android
+
+import "testing"
+
+// Make sure that FixturePreparer instances are only called once per fixture and in the order in
+// which they were added.
+func TestFixtureDedup(t *testing.T) {
+ list := []string{}
+
+ appendToList := func(s string) FixturePreparer {
+ return FixtureModifyConfig(func(_ Config) {
+ list = append(list, s)
+ })
+ }
+
+ preparer1 := appendToList("preparer1")
+ preparer2 := appendToList("preparer2")
+ preparer3 := appendToList("preparer3")
+ preparer4 := appendToList("preparer4")
+
+ preparer1Then2 := GroupFixturePreparers(preparer1, preparer2)
+
+ preparer2Then1 := GroupFixturePreparers(preparer2, preparer1)
+
+ buildDir := "build"
+ factory := NewFixtureFactory(&buildDir, preparer1, preparer2, preparer1, preparer1Then2)
+
+ extension := factory.Extend(preparer4, preparer2)
+
+ extension.Fixture(t, preparer1, preparer2, preparer2Then1, preparer3)
+
+ h := TestHelper{t}
+ h.AssertDeepEquals("preparers called in wrong order",
+ []string{"preparer1", "preparer2", "preparer4", "preparer3"}, list)
+}
diff --git a/android/license.go b/android/license.go
index b140b55b1..3bc6199b2 100644
--- a/android/license.go
+++ b/android/license.go
@@ -19,7 +19,7 @@ import (
)
type licenseKindDependencyTag struct {
- blueprint.BaseDependencyTag
+ blueprint.BaseDependencyTag
}
var (
diff --git a/android/license_test.go b/android/license_test.go
index 552bbaee0..9f6871374 100644
--- a/android/license_test.go
+++ b/android/license_test.go
@@ -49,9 +49,9 @@ var licenseTests = []struct {
}`),
},
expectedErrors: []string{
- `other/Blueprints:2:5: module "arule": depends on //top:top_allowed_as_notice `+
+ `other/Blueprints:2:5: module "arule": depends on //top:top_allowed_as_notice ` +
`which is not visible to this module`,
- `yetmore/Blueprints:2:5: module "//yetmore": depends on //top:top_allowed_as_notice `+
+ `yetmore/Blueprints:2:5: module "//yetmore": depends on //top:top_allowed_as_notice ` +
`which is not visible to this module`,
},
},
@@ -70,7 +70,7 @@ var licenseTests = []struct {
}`),
},
expectedErrors: []string{
- `top/Blueprints:6:5: module "top_proprietary": license_kinds property `+
+ `top/Blueprints:6:5: module "top_proprietary": license_kinds property ` +
`"top_by_exception_only" is not a license_kind module`,
},
},
diff --git a/android/licenses.go b/android/licenses.go
index 100042911..2838f5d28 100644
--- a/android/licenses.go
+++ b/android/licenses.go
@@ -51,7 +51,7 @@ type applicableLicensesPropertyImpl struct {
func newApplicableLicensesProperty(name string, licensesProperty *[]string) applicableLicensesProperty {
return applicableLicensesPropertyImpl{
- name: name,
+ name: name,
licensesProperty: licensesProperty,
}
}
diff --git a/android/licenses_test.go b/android/licenses_test.go
index b94add7cf..c04379108 100644
--- a/android/licenses_test.go
+++ b/android/licenses_test.go
@@ -7,15 +7,15 @@ import (
)
var licensesTests = []struct {
- name string
- fs map[string][]byte
- expectedErrors []string
- effectiveLicenses map[string][]string
- effectiveInheritedLicenses map[string][]string
- effectivePackage map[string]string
- effectiveNotices map[string][]string
- effectiveKinds map[string][]string
- effectiveConditions map[string][]string
+ name string
+ fs map[string][]byte
+ expectedErrors []string
+ effectiveLicenses map[string][]string
+ effectiveInheritedLicenses map[string][]string
+ effectivePackage map[string]string
+ effectiveNotices map[string][]string
+ effectiveKinds map[string][]string
+ effectiveConditions map[string][]string
}{
{
name: "invalid module type without licenses property",
@@ -71,28 +71,28 @@ var licensesTests = []struct {
},
effectiveLicenses: map[string][]string{
"libexample1": []string{"top_Apache2"},
- "libnested": []string{"top_Apache2"},
- "libother": []string{"top_Apache2"},
+ "libnested": []string{"top_Apache2"},
+ "libother": []string{"top_Apache2"},
},
effectiveKinds: map[string][]string{
"libexample1": []string{"notice"},
- "libnested": []string{"notice"},
- "libother": []string{"notice"},
+ "libnested": []string{"notice"},
+ "libother": []string{"notice"},
},
effectivePackage: map[string]string{
"libexample1": "topDog",
- "libnested": "topDog",
- "libother": "topDog",
+ "libnested": "topDog",
+ "libother": "topDog",
},
effectiveConditions: map[string][]string{
"libexample1": []string{"shownotice"},
- "libnested": []string{"shownotice"},
- "libother": []string{"shownotice"},
+ "libnested": []string{"shownotice"},
+ "libother": []string{"shownotice"},
},
effectiveNotices: map[string][]string{
"libexample1": []string{"top/LICENSE", "top/NOTICE"},
- "libnested": []string{"top/LICENSE", "top/NOTICE"},
- "libother": []string{"top/LICENSE", "top/NOTICE"},
+ "libnested": []string{"top/LICENSE", "top/NOTICE"},
+ "libother": []string{"top/LICENSE", "top/NOTICE"},
},
},
@@ -147,28 +147,28 @@ var licensesTests = []struct {
}`),
},
effectiveLicenses: map[string][]string{
- "libexample": []string{"nested_other", "top_other"},
+ "libexample": []string{"nested_other", "top_other"},
"libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
+ "libnested": []string{},
+ "libother": []string{},
},
effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"nested_other", "top_other"},
+ "libexample": []string{"nested_other", "top_other"},
"libsamepackage": []string{"nested_other", "top_other"},
- "libnested": []string{"nested_other", "top_other"},
- "libother": []string{"nested_other", "top_other"},
+ "libnested": []string{"nested_other", "top_other"},
+ "libother": []string{"nested_other", "top_other"},
},
effectiveKinds: map[string][]string{
- "libexample": []string{"nested_notice", "top_notice"},
+ "libexample": []string{"nested_notice", "top_notice"},
"libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
+ "libnested": []string{},
+ "libother": []string{},
},
effectiveConditions: map[string][]string{
- "libexample": []string{"notice"},
+ "libexample": []string{"notice"},
"libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
+ "libnested": []string{},
+ "libother": []string{},
},
},
{
@@ -218,32 +218,32 @@ var licensesTests = []struct {
}`),
},
effectiveLicenses: map[string][]string{
- "libexample": []string{"other", "top_nested"},
+ "libexample": []string{"other", "top_nested"},
"libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
- "liboutsider": []string{},
+ "libnested": []string{},
+ "libother": []string{},
+ "liboutsider": []string{},
},
effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"other", "top_nested"},
+ "libexample": []string{"other", "top_nested"},
"libsamepackage": []string{"other", "top_nested"},
- "libnested": []string{"other", "top_nested"},
- "libother": []string{"other", "top_nested"},
- "liboutsider": []string{"other", "top_nested"},
+ "libnested": []string{"other", "top_nested"},
+ "libother": []string{"other", "top_nested"},
+ "liboutsider": []string{"other", "top_nested"},
},
effectiveKinds: map[string][]string{
- "libexample": []string{},
+ "libexample": []string{},
"libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
- "liboutsider": []string{},
+ "libnested": []string{},
+ "libother": []string{},
+ "liboutsider": []string{},
},
effectiveNotices: map[string][]string{
- "libexample": []string{"top/nested/LICENSE.txt"},
+ "libexample": []string{"top/nested/LICENSE.txt"},
"libsamepackage": []string{},
- "libnested": []string{},
- "libother": []string{},
- "liboutsider": []string{},
+ "libnested": []string{},
+ "libother": []string{},
+ "liboutsider": []string{},
},
},
@@ -285,11 +285,11 @@ var licensesTests = []struct {
}`),
},
effectiveLicenses: map[string][]string{
- "libexample": []string{"by_exception_only"},
+ "libexample": []string{"by_exception_only"},
"libdefaults": []string{"notice"},
},
effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"by_exception_only"},
+ "libexample": []string{"by_exception_only"},
"libdefaults": []string{"notice"},
},
},
@@ -327,11 +327,11 @@ var licensesTests = []struct {
}`),
},
effectiveLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
+ "libexample": []string{"top_notice"},
"liboutsider": []string{},
},
effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
+ "libexample": []string{"top_notice"},
"liboutsider": []string{"top_notice"},
},
},
@@ -370,15 +370,15 @@ var licensesTests = []struct {
}`),
},
effectiveLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
- "libnested": []string{"outsider"},
- "libother": []string{},
+ "libexample": []string{"top_notice"},
+ "libnested": []string{"outsider"},
+ "libother": []string{},
"liboutsider": []string{},
},
effectiveInheritedLicenses: map[string][]string{
- "libexample": []string{"top_notice"},
- "libnested": []string{"outsider"},
- "libother": []string{},
+ "libexample": []string{"top_notice"},
+ "libnested": []string{"outsider"},
+ "libother": []string{},
"liboutsider": []string{"top_notice", "outsider"},
},
},
@@ -449,7 +449,7 @@ var licensesTests = []struct {
},
effectiveInheritedLicenses: map[string][]string{
"module": []string{"prebuilt", "top_sources"},
- "other": []string{"prebuilt", "top_sources"},
+ "other": []string{"prebuilt", "top_sources"},
},
},
}
diff --git a/android/module.go b/android/module.go
index bf74cad07..9f923e2d0 100644
--- a/android/module.go
+++ b/android/module.go
@@ -443,6 +443,7 @@ type Module interface {
Disable()
Enabled() bool
Target() Target
+ MultiTargets() []Target
Owner() string
InstallInData() bool
InstallInTestcases() bool
@@ -507,13 +508,17 @@ type Module interface {
type BazelTargetModule interface {
Module
- BazelTargetModuleProperties() *bazel.BazelTargetModuleProperties
+ bazelTargetModuleProperties() *bazel.BazelTargetModuleProperties
+ SetBazelTargetModuleProperties(props bazel.BazelTargetModuleProperties)
+
+ RuleClass() string
+ BzlLoadLocation() string
}
// InitBazelTargetModule is a wrapper function that decorates BazelTargetModule
// with property structs containing metadata for bp2build conversion.
func InitBazelTargetModule(module BazelTargetModule) {
- module.AddProperties(module.BazelTargetModuleProperties())
+ module.AddProperties(module.bazelTargetModuleProperties())
InitAndroidModule(module)
}
@@ -524,11 +529,26 @@ type BazelTargetModuleBase struct {
Properties bazel.BazelTargetModuleProperties
}
-// BazelTargetModuleProperties getter.
-func (btmb *BazelTargetModuleBase) BazelTargetModuleProperties() *bazel.BazelTargetModuleProperties {
+// bazelTargetModuleProperties getter.
+func (btmb *BazelTargetModuleBase) bazelTargetModuleProperties() *bazel.BazelTargetModuleProperties {
return &btmb.Properties
}
+// SetBazelTargetModuleProperties setter for BazelTargetModuleProperties
+func (btmb *BazelTargetModuleBase) SetBazelTargetModuleProperties(props bazel.BazelTargetModuleProperties) {
+ btmb.Properties = props
+}
+
+// RuleClass returns the rule class for this Bazel target
+func (b *BazelTargetModuleBase) RuleClass() string {
+ return b.bazelTargetModuleProperties().Rule_class
+}
+
+// BzlLoadLocation returns the rule class for this Bazel target
+func (b *BazelTargetModuleBase) BzlLoadLocation() string {
+ return b.bazelTargetModuleProperties().Bzl_load_location
+}
+
// Qualified id for a module
type qualifiedModuleName struct {
// The package (i.e. directory) in which the module is defined, without trailing /
@@ -733,7 +753,7 @@ type commonProperties struct {
// Whether this module is installed to vendor ramdisk
Vendor_ramdisk *bool
- // Whether this module is built for non-native architecures (also known as native bridge binary)
+ // Whether this module is built for non-native architectures (also known as native bridge binary)
Native_bridge_supported *bool `android:"arch_variant"`
// init.rc files to be installed if this module is installed
@@ -1104,8 +1124,15 @@ type ModuleBase struct {
variableProperties interface{}
hostAndDeviceProperties hostAndDeviceProperties
generalProperties []interface{}
- archProperties [][]interface{}
- customizableProperties []interface{}
+
+ // Arch specific versions of structs in generalProperties. The outer index
+ // has the same order as generalProperties as initialized in
+ // InitAndroidArchModule, and the inner index chooses the props specific to
+ // the architecture. The interface{} value is an archPropRoot that is
+ // filled with arch specific values by the arch mutator.
+ archProperties [][]interface{}
+
+ customizableProperties []interface{}
// Properties specific to the Blueprint to BUILD migration.
bazelTargetModuleProperties bazel.BazelTargetModuleProperties
@@ -1149,8 +1176,6 @@ type ModuleBase struct {
initRcPaths Paths
vintfFragmentsPaths Paths
-
- prefer32 func(ctx BaseModuleContext, base *ModuleBase, os OsType) bool
}
func (m *ModuleBase) ComponentDepsMutator(BottomUpMutatorContext) {}
@@ -1177,10 +1202,6 @@ func (m *ModuleBase) VariablesForTests() map[string]string {
return m.variables
}
-func (m *ModuleBase) Prefer32(prefer32 func(ctx BaseModuleContext, base *ModuleBase, os OsType) bool) {
- m.prefer32 = prefer32
-}
-
// Name returns the name of the module. It may be overridden by individual module types, for
// example prebuilts will prepend prebuilt_ to the name.
func (m *ModuleBase) Name() string {
@@ -1811,6 +1832,18 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
return
}
+ m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
+ rcDir := PathForModuleInstall(ctx, "etc", "init")
+ for _, src := range m.initRcPaths {
+ ctx.PackageFile(rcDir, filepath.Base(src.String()), src)
+ }
+
+ m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
+ vintfDir := PathForModuleInstall(ctx, "etc", "vintf", "manifest")
+ for _, src := range m.vintfFragmentsPaths {
+ ctx.PackageFile(vintfDir, filepath.Base(src.String()), src)
+ }
+
// Create the set of tagged dist files after calling GenerateAndroidBuildActions
// as GenerateTaggedDistFiles() calls OutputFiles(tag) and so relies on the
// output paths being set which must be done before or during
@@ -1823,8 +1856,6 @@ func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext)
m.installFiles = append(m.installFiles, ctx.installFiles...)
m.checkbuildFiles = append(m.checkbuildFiles, ctx.checkbuildFiles...)
m.packagingSpecs = append(m.packagingSpecs, ctx.packagingSpecs...)
- m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
- m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
for k, v := range ctx.phonies {
m.phonies[k] = append(m.phonies[k], v...)
}
diff --git a/android/mutator.go b/android/mutator.go
index c38719334..9552aa15c 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -33,22 +33,8 @@ import (
// run FinalDeps mutators (CreateVariations disallowed in this phase)
// continue on to GenerateAndroidBuildActions
-func registerMutatorsToContext(ctx *blueprint.Context, mutators []*mutator) {
- for _, t := range mutators {
- var handle blueprint.MutatorHandle
- if t.bottomUpMutator != nil {
- handle = ctx.RegisterBottomUpMutator(t.name, t.bottomUpMutator)
- } else if t.topDownMutator != nil {
- handle = ctx.RegisterTopDownMutator(t.name, t.topDownMutator)
- }
- if t.parallel {
- handle.Parallel()
- }
- }
-}
-
// RegisterMutatorsForBazelConversion is a alternate registration pipeline for bp2build. Exported for testing.
-func RegisterMutatorsForBazelConversion(ctx *blueprint.Context, preArchMutators, depsMutators, bp2buildMutators []RegisterMutatorFunc) {
+func RegisterMutatorsForBazelConversion(ctx *Context, preArchMutators, depsMutators, bp2buildMutators []RegisterMutatorFunc) {
mctx := &registerMutatorsContext{
bazelConversionMode: true,
}
@@ -80,10 +66,17 @@ func RegisterMutatorsForBazelConversion(ctx *blueprint.Context, preArchMutators,
f(mctx)
}
- registerMutatorsToContext(ctx, mctx.mutators)
+ mctx.mutators.registerAll(ctx)
+}
+
+// collateGloballyRegisteredMutators constructs the list of mutators that have been registered
+// with the InitRegistrationContext and will be used at runtime.
+func collateGloballyRegisteredMutators() sortableComponents {
+ return collateRegisteredMutators(preArch, preDeps, postDeps, finalDeps)
}
-func registerMutators(ctx *blueprint.Context, preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc) {
+// collateRegisteredMutators constructs a single list of mutators from the separate lists.
+func collateRegisteredMutators(preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc) sortableComponents {
mctx := &registerMutatorsContext{}
register := func(funcs []RegisterMutatorFunc) {
@@ -103,11 +96,11 @@ func registerMutators(ctx *blueprint.Context, preArch, preDeps, postDeps, finalD
mctx.finalPhase = true
register(finalDeps)
- registerMutatorsToContext(ctx, mctx.mutators)
+ return mctx.mutators
}
type registerMutatorsContext struct {
- mutators []*mutator
+ mutators sortableComponents
finalPhase bool
bazelConversionMode bool
}
@@ -283,7 +276,7 @@ type TopDownMutatorContext interface {
// factory method, just like in CreateModule, but also requires
// BazelTargetModuleProperties containing additional metadata for the
// bp2build codegenerator.
- CreateBazelTargetModule(ModuleFactory, bazel.BazelTargetModuleProperties, interface{}) BazelTargetModule
+ CreateBazelTargetModule(ModuleFactory, string, bazel.BazelTargetModuleProperties, interface{}) BazelTargetModule
}
type topDownMutatorContext struct {
@@ -473,6 +466,23 @@ func (x *registerMutatorsContext) TopDown(name string, m TopDownMutator) Mutator
return mutator
}
+func (mutator *mutator) componentName() string {
+ return mutator.name
+}
+
+func (mutator *mutator) register(ctx *Context) {
+ blueprintCtx := ctx.Context
+ var handle blueprint.MutatorHandle
+ if mutator.bottomUpMutator != nil {
+ handle = blueprintCtx.RegisterBottomUpMutator(mutator.name, mutator.bottomUpMutator)
+ } else if mutator.topDownMutator != nil {
+ handle = blueprintCtx.RegisterTopDownMutator(mutator.name, mutator.topDownMutator)
+ }
+ if mutator.parallel {
+ handle.Parallel()
+ }
+}
+
type MutatorHandle interface {
Parallel() MutatorHandle
}
@@ -513,17 +523,25 @@ func registerDepsMutatorBp2Build(ctx RegisterMutatorsContext) {
func (t *topDownMutatorContext) CreateBazelTargetModule(
factory ModuleFactory,
+ name string,
bazelProps bazel.BazelTargetModuleProperties,
attrs interface{}) BazelTargetModule {
- if !strings.HasPrefix(*bazelProps.Name, bazel.BazelTargetModuleNamePrefix) {
+ if strings.HasPrefix(name, bazel.BazelTargetModuleNamePrefix) {
panic(fmt.Errorf(
- "bp2build error: the bazel target module name must start with '%s': %s",
+ "The %s name prefix is added automatically, do not set it manually: %s",
bazel.BazelTargetModuleNamePrefix,
- *bazelProps.Name,
- ))
+ name))
+ }
+ name = bazel.BazelTargetModuleNamePrefix + name
+ nameProp := struct {
+ Name *string
+ }{
+ Name: &name,
}
- return t.CreateModule(factory, &bazelProps, attrs).(BazelTargetModule)
+ b := t.CreateModule(factory, &nameProp, attrs).(BazelTargetModule)
+ b.SetBazelTargetModuleProperties(bazelProps)
+ return b
}
func (t *topDownMutatorContext) AppendProperties(props ...interface{}) {
diff --git a/android/override_module.go b/android/override_module.go
index fa0856631..97acc5c36 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -215,7 +215,14 @@ func RegisterOverridePostDepsMutators(ctx RegisterMutatorsContext) {
ctx.BottomUp("override_deps", overrideModuleDepsMutator).Parallel()
ctx.TopDown("register_override", registerOverrideMutator).Parallel()
ctx.BottomUp("perform_override", performOverrideMutator).Parallel()
+ // overridableModuleDepsMutator calls OverridablePropertiesDepsMutator so that overridable modules can
+ // add deps from overridable properties.
ctx.BottomUp("overridable_deps", overridableModuleDepsMutator).Parallel()
+ // Because overridableModuleDepsMutator is run after PrebuiltPostDepsMutator,
+ // prebuilt's ReplaceDependencies doesn't affect to those deps added by overridable properties.
+ // By running PrebuiltPostDepsMutator again after overridableModuleDepsMutator, deps via overridable properties
+ // can be replaced with prebuilts.
+ ctx.BottomUp("replace_deps_on_prebuilts_for_overridable_deps_again", PrebuiltPostDepsMutator).Parallel()
ctx.BottomUp("replace_deps_on_override", replaceDepsOnOverridingModuleMutator).Parallel()
}
diff --git a/android/package.go b/android/package.go
index 7012fc7d8..878e4c4ed 100644
--- a/android/package.go
+++ b/android/package.go
@@ -23,6 +23,8 @@ func init() {
RegisterPackageBuildComponents(InitRegistrationContext)
}
+var PrepareForTestWithPackageModule = FixtureRegisterWithContext(RegisterPackageBuildComponents)
+
// Register the package module type.
func RegisterPackageBuildComponents(ctx RegistrationContext) {
ctx.RegisterModuleType("package", PackageFactory)
diff --git a/android/path_properties.go b/android/path_properties.go
index 4bb706aa8..853e5a9a7 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -76,52 +76,73 @@ func pathPropertiesForPropertyStruct(ps interface{}) []string {
var ret []string
for _, i := range pathPropertyIndexes {
- // Turn an index into a field.
- sv := fieldByIndex(v, i)
- if !sv.IsValid() {
- // Skip properties inside a nil pointer.
- continue
- }
-
- // If the field is a non-nil pointer step into it.
- if sv.Kind() == reflect.Ptr {
- if sv.IsNil() {
+ var values []reflect.Value
+ fieldsByIndex(v, i, &values)
+ for _, sv := range values {
+ if !sv.IsValid() {
+ // Skip properties inside a nil pointer.
continue
}
- sv = sv.Elem()
- }
- // Collect paths from all strings and slices of strings.
- switch sv.Kind() {
- case reflect.String:
- ret = append(ret, sv.String())
- case reflect.Slice:
- ret = append(ret, sv.Interface().([]string)...)
- default:
- panic(fmt.Errorf(`field %s in type %s has tag android:"path" but is not a string or slice of strings, it is a %s`,
- v.Type().FieldByIndex(i).Name, v.Type(), sv.Type()))
+ // If the field is a non-nil pointer step into it.
+ if sv.Kind() == reflect.Ptr {
+ if sv.IsNil() {
+ continue
+ }
+ sv = sv.Elem()
+ }
+
+ // Collect paths from all strings and slices of strings.
+ switch sv.Kind() {
+ case reflect.String:
+ ret = append(ret, sv.String())
+ case reflect.Slice:
+ ret = append(ret, sv.Interface().([]string)...)
+ default:
+ panic(fmt.Errorf(`field %s in type %s has tag android:"path" but is not a string or slice of strings, it is a %s`,
+ v.Type().FieldByIndex(i).Name, v.Type(), sv.Type()))
+ }
}
}
return ret
}
-// fieldByIndex is like reflect.Value.FieldByIndex, but returns an invalid reflect.Value when
-// traversing a nil pointer to a struct.
-func fieldByIndex(v reflect.Value, index []int) reflect.Value {
+// fieldsByIndex is similar to reflect.Value.FieldByIndex, but is more robust: it doesn't track
+// nil pointers and it returns multiple values when there's slice of struct.
+func fieldsByIndex(v reflect.Value, index []int, values *[]reflect.Value) {
+ // leaf case
if len(index) == 1 {
- return v.Field(index[0])
- }
- for _, x := range index {
- if v.Kind() == reflect.Ptr {
- if v.IsNil() {
- return reflect.Value{}
+ if isSliceOfStruct(v) {
+ for i := 0; i < v.Len(); i++ {
+ *values = append(*values, v.Index(i).Field(index[0]))
}
- v = v.Elem()
+ } else {
+ *values = append(*values, v.Field(index[0]))
}
- v = v.Field(x)
+ return
}
- return v
+
+ // recursion
+ if v.Kind() == reflect.Ptr {
+ // don't track nil pointer
+ if v.IsNil() {
+ return
+ }
+ v = v.Elem()
+ } else if isSliceOfStruct(v) {
+ // do the recursion for all elements
+ for i := 0; i < v.Len(); i++ {
+ fieldsByIndex(v.Index(i).Field(index[0]), index[1:], values)
+ }
+ return
+ }
+ fieldsByIndex(v.Field(index[0]), index[1:], values)
+ return
+}
+
+func isSliceOfStruct(v reflect.Value) bool {
+ return v.Kind() == reflect.Slice && v.Type().Elem().Kind() == reflect.Struct
}
var pathPropertyIndexesCache OncePer
diff --git a/android/path_properties_test.go b/android/path_properties_test.go
index f964d9f1e..2aab74835 100644
--- a/android/path_properties_test.go
+++ b/android/path_properties_test.go
@@ -33,12 +33,21 @@ type pathDepsMutatorTestModule struct {
Foo string `android:"path"`
}
+ // nested slices of struct
+ props3 struct {
+ X []struct {
+ Y []struct {
+ Z []string `android:"path"`
+ }
+ }
+ }
+
sourceDeps []string
}
func pathDepsMutatorTestModuleFactory() Module {
module := &pathDepsMutatorTestModule{}
- module.AddProperties(&module.props, &module.props2)
+ module.AddProperties(&module.props, &module.props2, &module.props3)
InitAndroidArchModule(module, DeviceSupported, MultilibBoth)
return module
}
@@ -73,8 +82,20 @@ func TestPathDepsMutator(t *testing.T) {
bar: [":b"],
baz: ":c{.bar}",
qux: ":d",
+ x: [
+ {
+ y: [
+ {
+ z: [":x", ":y"],
+ },
+ {
+ z: [":z"],
+ },
+ ],
+ },
+ ],
}`,
- deps: []string{"a", "b", "c"},
+ deps: []string{"a", "b", "c", "x", "y", "z"},
},
{
name: "arch variant",
@@ -113,6 +134,18 @@ func TestPathDepsMutator(t *testing.T) {
filegroup {
name: "d",
}
+
+ filegroup {
+ name: "x",
+ }
+
+ filegroup {
+ name: "y",
+ }
+
+ filegroup {
+ name: "z",
+ }
`
config := TestArchConfig(buildDir, nil, bp, nil)
diff --git a/android/paths.go b/android/paths.go
index ada4da692..3f4d3f281 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -1662,9 +1662,9 @@ func modulePartition(ctx ModuleInstallPathContext, os OsType) string {
// on a device without a dedicated recovery partition, install the
// recovery variant.
if ctx.DeviceConfig().BoardMoveRecoveryResourcesToVendorBoot() {
- partition = "vendor-ramdisk/first_stage_ramdisk"
+ partition = "vendor_ramdisk/first_stage_ramdisk"
} else {
- partition = "vendor-ramdisk"
+ partition = "vendor_ramdisk"
}
if !ctx.InstallInRoot() {
partition += "/system"
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 39d30c5ec..04864a1d0 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -100,7 +100,7 @@ func (p *Prebuilt) Prefer() bool {
// more modules like this.
func (p *Prebuilt) SingleSourcePath(ctx ModuleContext) Path {
if p.srcsSupplier != nil {
- srcs := p.srcsSupplier(ctx)
+ srcs := p.srcsSupplier(ctx, ctx.Module())
if len(srcs) == 0 {
ctx.PropertyErrorf(p.srcsPropertyName, "missing prebuilt source file")
@@ -128,8 +128,11 @@ func (p *Prebuilt) UsePrebuilt() bool {
// Called to provide the srcs value for the prebuilt module.
//
+// This can be called with a context for any module not just the prebuilt one itself. It can also be
+// called concurrently.
+//
// Return the src value or nil if it is not available.
-type PrebuiltSrcsSupplier func(ctx BaseModuleContext) []string
+type PrebuiltSrcsSupplier func(ctx BaseModuleContext, prebuilt Module) []string
// Initialize the module as a prebuilt module that uses the provided supplier to access the
// prebuilt sources of the module.
@@ -163,7 +166,7 @@ func InitPrebuiltModule(module PrebuiltInterface, srcs *[]string) {
panic(fmt.Errorf("srcs must not be nil"))
}
- srcsSupplier := func(ctx BaseModuleContext) []string {
+ srcsSupplier := func(ctx BaseModuleContext, _ Module) []string {
return *srcs
}
@@ -184,7 +187,7 @@ func InitSingleSourcePrebuiltModule(module PrebuiltInterface, srcProps interface
srcFieldIndex := srcStructField.Index
srcPropertyName := proptools.PropertyNameForField(srcField)
- srcsSupplier := func(ctx BaseModuleContext) []string {
+ srcsSupplier := func(ctx BaseModuleContext, _ Module) []string {
if !module.Enabled() {
return nil
}
@@ -256,12 +259,12 @@ func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) {
panic(fmt.Errorf("prebuilt module did not have InitPrebuiltModule called on it"))
}
if !p.properties.SourceExists {
- p.properties.UsePrebuilt = p.usePrebuilt(ctx, nil)
+ p.properties.UsePrebuilt = p.usePrebuilt(ctx, nil, m)
}
} else if s, ok := ctx.Module().(Module); ok {
ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(m Module) {
p := m.(PrebuiltInterface).Prebuilt()
- if p.usePrebuilt(ctx, s) {
+ if p.usePrebuilt(ctx, s, m) {
p.properties.UsePrebuilt = true
s.ReplacedByPrebuilt()
}
@@ -296,8 +299,8 @@ func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) {
// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt
// will be used if it is marked "prefer" or if the source module is disabled.
-func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module) bool {
- if p.srcsSupplier != nil && len(p.srcsSupplier(ctx)) == 0 {
+func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module, prebuilt Module) bool {
+ if p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0 {
return false
}
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index 9ac38750c..32af5df4b 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -262,7 +262,7 @@ var prebuiltsTests = []struct {
}
func TestPrebuilts(t *testing.T) {
- fs := map[string][]byte{
+ fs := MockFS{
"prebuilt_file": nil,
"source_file": nil,
}
@@ -277,32 +277,33 @@ func TestPrebuilts(t *testing.T) {
deps: [":bar"],
}`
}
- config := TestArchConfig(buildDir, nil, bp, fs)
// Add windows to the target list to test the logic when a variant is
// disabled by default.
if !Windows.DefaultDisabled {
t.Errorf("windows is assumed to be disabled by default")
}
- config.config.Targets[Windows] = []Target{
- {Windows, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", true},
- }
-
- ctx := NewTestArchContext(config)
- registerTestPrebuiltBuildComponents(ctx)
- ctx.RegisterModuleType("filegroup", FileGroupFactory)
- ctx.Register()
- _, errs := ctx.ParseBlueprintsFiles("Android.bp")
- FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- FailIfErrored(t, errs)
+ result := emptyTestFixtureFactory.Extend(
+ PrepareForTestWithArchMutator,
+ PrepareForTestWithPrebuilts,
+ PrepareForTestWithOverrides,
+ PrepareForTestWithFilegroup,
+ // Add a Windows target to the configuration.
+ FixtureModifyConfig(func(config Config) {
+ config.Targets[Windows] = []Target{
+ {Windows, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", true},
+ }
+ }),
+ fs.AddToFixture(),
+ FixtureRegisterWithContext(registerTestPrebuiltModules),
+ ).RunTestWithBp(t, bp)
- for _, variant := range ctx.ModuleVariantsForTests("foo") {
- foo := ctx.ModuleForTests("foo", variant)
+ for _, variant := range result.ModuleVariantsForTests("foo") {
+ foo := result.ModuleForTests("foo", variant)
t.Run(foo.Module().Target().Os.String(), func(t *testing.T) {
var dependsOnSourceModule, dependsOnPrebuiltModule bool
- ctx.VisitDirectDeps(foo.Module(), func(m blueprint.Module) {
+ result.VisitDirectDeps(foo.Module(), func(m blueprint.Module) {
if _, ok := m.(*sourceModule); ok {
dependsOnSourceModule = true
}
@@ -381,14 +382,20 @@ func TestPrebuilts(t *testing.T) {
}
func registerTestPrebuiltBuildComponents(ctx RegistrationContext) {
- ctx.RegisterModuleType("prebuilt", newPrebuiltModule)
- ctx.RegisterModuleType("source", newSourceModule)
- ctx.RegisterModuleType("override_source", newOverrideSourceModule)
+ registerTestPrebuiltModules(ctx)
RegisterPrebuiltMutators(ctx)
ctx.PostDepsMutators(RegisterOverridePostDepsMutators)
}
+var prepareForTestWithFakePrebuiltModules = FixtureRegisterWithContext(registerTestPrebuiltModules)
+
+func registerTestPrebuiltModules(ctx RegistrationContext) {
+ ctx.RegisterModuleType("prebuilt", newPrebuiltModule)
+ ctx.RegisterModuleType("source", newSourceModule)
+ ctx.RegisterModuleType("override_source", newOverrideSourceModule)
+}
+
type prebuiltModule struct {
ModuleBase
prebuilt Prebuilt
diff --git a/android/queryview.go b/android/queryview.go
index 9e3e45a32..12d14dfb6 100644
--- a/android/queryview.go
+++ b/android/queryview.go
@@ -66,12 +66,20 @@ func generateBuildActionsForBazelConversion(ctx SingletonContext, converterMode
bazelQueryView := ctx.Rule(pctx, "bazelQueryView",
blueprint.RuleParams{
Command: fmt.Sprintf(
- "rm -rf ${outDir}/* && "+
- "%s --bazel_queryview_dir ${outDir} %s && "+
- "echo WORKSPACE: `cat %s` > ${outDir}/.queryview-depfile.d",
- primaryBuilder.String(),
- strings.Join(os.Args[1:], " "),
+ `rm -rf "${outDir}/"* && `+
+ `mkdir -p "${outDir}" && `+
+ `echo WORKSPACE: cat "%s" > "${outDir}/.queryview-depfile.d" && `+
+ `BUILDER="%s" && `+
+ `echo BUILDER=$$BUILDER && `+
+ `cd "$$(dirname "$$BUILDER")" && `+
+ `echo PWD=$$PWD && `+
+ `ABSBUILDER="$$PWD/$$(basename "$$BUILDER")" && `+
+ `echo ABSBUILDER=$$ABSBUILDER && `+
+ `cd / && `+
+ `env -i "$$ABSBUILDER" --bazel_queryview_dir "${outDir}" "%s"`,
moduleListFilePath.String(), // Use the contents of Android.bp.list as the depfile.
+ primaryBuilder.String(),
+ strings.Join(os.Args[1:], "\" \""),
),
CommandDeps: []string{primaryBuilder.String()},
Description: fmt.Sprintf(
diff --git a/android/register.go b/android/register.go
index 18c743f19..c9e66e966 100644
--- a/android/register.go
+++ b/android/register.go
@@ -21,21 +21,78 @@ import (
"github.com/google/blueprint"
)
+// A sortable component is one whose registration order affects the order in which it is executed
+// and so affects the behavior of the build system. As a result it is important for the order in
+// which they are registered during tests to match the order used at runtime and so the test
+// infrastructure will sort them to match.
+//
+// The sortable components are mutators, singletons and pre-singletons. Module types are not
+// sortable because their order of registration does not affect the runtime behavior.
+type sortableComponent interface {
+ // componentName returns the name of the component.
+ //
+ // Uniquely identifies the components within the set of components used at runtimr and during
+ // tests.
+ componentName() string
+
+ // register registers this component in the supplied context.
+ register(ctx *Context)
+}
+
+type sortableComponents []sortableComponent
+
+// registerAll registers all components in this slice with the supplied context.
+func (r sortableComponents) registerAll(ctx *Context) {
+ for _, c := range r {
+ c.register(ctx)
+ }
+}
+
type moduleType struct {
name string
factory ModuleFactory
}
+func (t moduleType) register(ctx *Context) {
+ ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory))
+}
+
var moduleTypes []moduleType
var moduleTypesForDocs = map[string]reflect.Value{}
type singleton struct {
+ // True if this should be registered as a pre-singleton, false otherwise.
+ pre bool
+
name string
factory SingletonFactory
}
-var singletons []singleton
-var preSingletons []singleton
+func newSingleton(name string, factory SingletonFactory) singleton {
+ return singleton{false, name, factory}
+}
+
+func newPreSingleton(name string, factory SingletonFactory) singleton {
+ return singleton{true, name, factory}
+}
+
+func (s singleton) componentName() string {
+ return s.name
+}
+
+func (s singleton) register(ctx *Context) {
+ adaptor := SingletonFactoryAdaptor(ctx, s.factory)
+ if s.pre {
+ ctx.RegisterPreSingletonType(s.name, adaptor)
+ } else {
+ ctx.RegisterSingletonType(s.name, adaptor)
+ }
+}
+
+var _ sortableComponent = singleton{}
+
+var singletons sortableComponents
+var preSingletons sortableComponents
type mutator struct {
name string
@@ -44,6 +101,8 @@ type mutator struct {
parallel bool
}
+var _ sortableComponent = &mutator{}
+
type ModuleFactory func() Module
// ModuleFactoryAdaptor wraps a ModuleFactory into a blueprint.ModuleFactory by converting a Module
@@ -84,11 +143,11 @@ func RegisterModuleTypeForDocs(name string, factory reflect.Value) {
}
func RegisterSingletonType(name string, factory SingletonFactory) {
- singletons = append(singletons, singleton{name, factory})
+ singletons = append(singletons, newSingleton(name, factory))
}
func RegisterPreSingletonType(name string, factory SingletonFactory) {
- preSingletons = append(preSingletons, singleton{name, factory})
+ preSingletons = append(preSingletons, newPreSingleton(name, factory))
}
type Context struct {
@@ -107,46 +166,51 @@ func NewContext(config Config) *Context {
// files to semantically equivalent BUILD files.
func (ctx *Context) RegisterForBazelConversion() {
for _, t := range moduleTypes {
- ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory))
+ t.register(ctx)
}
// Required for SingletonModule types, even though we are not using them.
for _, t := range singletons {
- ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
+ t.register(ctx)
}
- RegisterMutatorsForBazelConversion(ctx.Context, bp2buildPreArchMutators, bp2buildDepsMutators, bp2buildMutators)
+ RegisterMutatorsForBazelConversion(ctx, bp2buildPreArchMutators, bp2buildDepsMutators, bp2buildMutators)
}
// Register the pipeline of singletons, module types, and mutators for
// generating build.ninja and other files for Kati, from Android.bp files.
func (ctx *Context) Register() {
- for _, t := range preSingletons {
- ctx.RegisterPreSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
- }
+ preSingletons.registerAll(ctx)
for _, t := range moduleTypes {
- ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory))
+ t.register(ctx)
}
- for _, t := range singletons {
- ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
- }
+ mutators := collateGloballyRegisteredMutators()
+ mutators.registerAll(ctx)
+
+ singletons := collateGloballyRegisteredSingletons()
+ singletons.registerAll(ctx)
+}
- registerMutators(ctx.Context, preArch, preDeps, postDeps, finalDeps)
+func collateGloballyRegisteredSingletons() sortableComponents {
+ allSingletons := append(sortableComponents(nil), singletons...)
+ allSingletons = append(allSingletons,
+ singleton{false, "bazeldeps", BazelSingleton},
- ctx.RegisterSingletonType("bazeldeps", SingletonFactoryAdaptor(ctx, BazelSingleton))
+ // Register phony just before makevars so it can write out its phony rules as Make rules
+ singleton{false, "phony", phonySingletonFactory},
- // Register phony just before makevars so it can write out its phony rules as Make rules
- ctx.RegisterSingletonType("phony", SingletonFactoryAdaptor(ctx, phonySingletonFactory))
+ // Register makevars after other singletons so they can export values through makevars
+ singleton{false, "makevars", makeVarsSingletonFunc},
- // Register makevars after other singletons so they can export values through makevars
- ctx.RegisterSingletonType("makevars", SingletonFactoryAdaptor(ctx, makeVarsSingletonFunc))
+ // Register env and ninjadeps last so that they can track all used environment variables and
+ // Ninja file dependencies stored in the config.
+ singleton{false, "env", EnvSingleton},
+ singleton{false, "ninjadeps", ninjaDepsSingletonFactory},
+ )
- // Register env and ninjadeps last so that they can track all used environment variables and
- // Ninja file dependencies stored in the config.
- ctx.RegisterSingletonType("env", SingletonFactoryAdaptor(ctx, EnvSingleton))
- ctx.RegisterSingletonType("ninjadeps", SingletonFactoryAdaptor(ctx, ninjaDepsSingletonFactory))
+ return allSingletons
}
func ModuleTypeFactories() map[string]ModuleFactory {
@@ -168,6 +232,7 @@ func ModuleTypeFactoriesForDocs() map[string]reflect.Value {
type RegistrationContext interface {
RegisterModuleType(name string, factory ModuleFactory)
RegisterSingletonModuleType(name string, factory SingletonModuleFactory)
+ RegisterPreSingletonType(name string, factory SingletonFactory)
RegisterSingletonType(name string, factory SingletonFactory)
PreArchMutators(f RegisterMutatorFunc)
@@ -208,6 +273,7 @@ var _ RegistrationContext = (*TestContext)(nil)
type initRegistrationContext struct {
moduleTypes map[string]ModuleFactory
singletonTypes map[string]SingletonFactory
+ preSingletonTypes map[string]SingletonFactory
moduleTypesForDocs map[string]reflect.Value
}
@@ -238,6 +304,14 @@ func (ctx *initRegistrationContext) RegisterSingletonType(name string, factory S
RegisterSingletonType(name, factory)
}
+func (ctx *initRegistrationContext) RegisterPreSingletonType(name string, factory SingletonFactory) {
+ if _, present := ctx.preSingletonTypes[name]; present {
+ panic(fmt.Sprintf("pre singleton type %q is already registered", name))
+ }
+ ctx.preSingletonTypes[name] = factory
+ RegisterPreSingletonType(name, factory)
+}
+
func (ctx *initRegistrationContext) PreArchMutators(f RegisterMutatorFunc) {
PreArchMutators(f)
}
diff --git a/android/sandbox.go b/android/sandbox.go
index ed022fb87..28e903ad4 100644
--- a/android/sandbox.go
+++ b/android/sandbox.go
@@ -14,29 +14,8 @@
package android
-import (
- "fmt"
- "os"
-)
-
-func init() {
- // Stash the working directory in a private variable and then change the working directory
- // to "/", which will prevent untracked accesses to files by Go Soong plugins. The
- // SOONG_SANDBOX_SOONG_BUILD environment variable is set by soong_ui, and is not
- // overrideable on the command line.
-
- orig, err := os.Getwd()
- if err != nil {
- panic(fmt.Errorf("failed to get working directory: %s", err))
- }
- absSrcDir = orig
-
- if getenv("SOONG_SANDBOX_SOONG_BUILD") == "true" {
- err = os.Chdir("/")
- if err != nil {
- panic(fmt.Errorf("failed to change working directory to '/': %s", err))
- }
- }
+func InitSandbox(topDir string) {
+ absSrcDir = topDir
}
// DO NOT USE THIS FUNCTION IN NEW CODE.
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index c62e76dd6..34b180d7d 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -295,18 +295,25 @@ func createAffectablePropertiesType(affectableProperties []string, factoryProps
recurse = func(prefix string, aps []string) ([]string, reflect.Type) {
var fields []reflect.StructField
+ // Iterate while the list is non-empty so it can be modified in the loop.
for len(affectableProperties) > 0 {
p := affectableProperties[0]
if !strings.HasPrefix(affectableProperties[0], prefix) {
+ // The properties are sorted and recurse is always called with a prefix that matches
+ // the first property in the list, so if we've reached one that doesn't match the
+ // prefix we are done with this prefix.
break
}
- affectableProperties = affectableProperties[1:]
nestedProperty := strings.TrimPrefix(p, prefix)
if i := strings.IndexRune(nestedProperty, '.'); i >= 0 {
var nestedType reflect.Type
nestedPrefix := nestedProperty[:i+1]
+ // Recurse to handle the properties with the found prefix. This will return
+ // an updated affectableProperties with the handled entries removed from the front
+ // of the list, and the type that contains the handled entries. The type may be
+ // nil if none of the entries matched factoryProps.
affectableProperties, nestedType = recurse(prefix+nestedPrefix, affectableProperties)
if nestedType != nil {
@@ -325,6 +332,8 @@ func createAffectablePropertiesType(affectableProperties []string, factoryProps
Type: typ,
})
}
+ // The first element in the list has been handled, remove it from the list.
+ affectableProperties = affectableProperties[1:]
}
}
diff --git a/android/soongconfig/modules_test.go b/android/soongconfig/modules_test.go
index b824c7898..48cdfe776 100644
--- a/android/soongconfig/modules_test.go
+++ b/android/soongconfig/modules_test.go
@@ -235,6 +235,44 @@ func Test_createAffectablePropertiesType(t *testing.T) {
}{},
want: "",
},
+ {
+ name: "nested",
+ affectableProperties: []string{"multilib.lib32.cflags"},
+ factoryProps: struct {
+ Multilib struct {
+ Lib32 struct {
+ Cflags string
+ }
+ }
+ }{},
+ want: "*struct { Multilib struct { Lib32 struct { Cflags string } } }",
+ },
+ {
+ name: "complex",
+ affectableProperties: []string{
+ "cflags",
+ "multilib.lib32.cflags",
+ "multilib.lib32.ldflags",
+ "multilib.lib64.cflags",
+ "multilib.lib64.ldflags",
+ "zflags",
+ },
+ factoryProps: struct {
+ Cflags string
+ Multilib struct {
+ Lib32 struct {
+ Cflags string
+ Ldflags string
+ }
+ Lib64 struct {
+ Cflags string
+ Ldflags string
+ }
+ }
+ Zflags string
+ }{},
+ want: "*struct { Cflags string; Multilib struct { Lib32 struct { Cflags string; Ldflags string }; Lib64 struct { Cflags string; Ldflags string } }; Zflags string }",
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
diff --git a/android/testing.go b/android/testing.go
index 7852b604b..03d7bd5a6 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -20,6 +20,7 @@ import (
"regexp"
"sort"
"strings"
+ "sync"
"testing"
"github.com/google/blueprint"
@@ -48,6 +49,62 @@ func NewTestContext(config Config) *TestContext {
return ctx
}
+var PrepareForTestWithArchMutator = GroupFixturePreparers(
+ // Configure architecture targets in the fixture config.
+ FixtureModifyConfig(modifyTestConfigToSupportArchMutator),
+
+ // Add the arch mutator to the context.
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.PreDepsMutators(registerArchMutator)
+ }),
+)
+
+var PrepareForTestWithDefaults = FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
+})
+
+var PrepareForTestWithComponentsMutator = FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.PreArchMutators(RegisterComponentsMutator)
+})
+
+var PrepareForTestWithPrebuilts = FixtureRegisterWithContext(RegisterPrebuiltMutators)
+
+var PrepareForTestWithOverrides = FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.PostDepsMutators(RegisterOverridePostDepsMutators)
+})
+
+// Test fixture preparer that will register most java build components.
+//
+// Singletons and mutators should only be added here if they are needed for a majority of java
+// module types, otherwise they should be added under a separate preparer to allow them to be
+// selected only when needed to reduce test execution time.
+//
+// Module types do not have much of an overhead unless they are used so this should include as many
+// module types as possible. The exceptions are those module types that require mutators and/or
+// singletons in order to function in which case they should be kept together in a separate
+// preparer.
+//
+// The mutators in this group were chosen because they are needed by the vast majority of tests.
+var PrepareForTestWithAndroidBuildComponents = GroupFixturePreparers(
+ // Sorted alphabetically as the actual order does not matter as tests automatically enforce the
+ // correct order.
+ PrepareForTestWithArchMutator,
+ PrepareForTestWithComponentsMutator,
+ PrepareForTestWithDefaults,
+ PrepareForTestWithFilegroup,
+ PrepareForTestWithOverrides,
+ PrepareForTestWithPackageModule,
+ PrepareForTestWithPrebuilts,
+ PrepareForTestWithVisibility,
+)
+
+// Prepares an integration test with all build components from the android package.
+//
+// This should only be used by tests that want to run with as much of the build enabled as possible.
+var PrepareForIntegrationTestWithAndroid = GroupFixturePreparers(
+ PrepareForTestWithAndroidBuildComponents,
+)
+
func NewTestArchContext(config Config) *TestContext {
ctx := NewTestContext(config)
ctx.preDeps = append(ctx.preDeps, registerArchMutator)
@@ -59,6 +116,13 @@ type TestContext struct {
preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc
bp2buildPreArch, bp2buildDeps, bp2buildMutators []RegisterMutatorFunc
NameResolver *NameResolver
+
+ // The list of pre-singletons and singletons registered for the test.
+ preSingletons, singletons sortableComponents
+
+ // The order in which the pre-singletons, mutators and singletons will be run in this test
+ // context; for debugging.
+ preSingletonOrder, mutatorOrder, singletonOrder []string
}
func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
@@ -103,15 +167,244 @@ func (ctx *TestContext) DepsBp2BuildMutators(f RegisterMutatorFunc) {
ctx.bp2buildDeps = append(ctx.bp2buildDeps, f)
}
+// registeredComponentOrder defines the order in which a sortableComponent type is registered at
+// runtime and provides support for reordering the components registered for a test in the same
+// way.
+type registeredComponentOrder struct {
+ // The name of the component type, used for error messages.
+ componentType string
+
+ // The names of the registered components in the order in which they were registered.
+ namesInOrder []string
+
+ // Maps from the component name to its position in the runtime ordering.
+ namesToIndex map[string]int
+
+ // A function that defines the order between two named components that can be used to sort a slice
+ // of component names into the same order as they appear in namesInOrder.
+ less func(string, string) bool
+}
+
+// registeredComponentOrderFromExistingOrder takes an existing slice of sortableComponents and
+// creates a registeredComponentOrder that contains a less function that can be used to sort a
+// subset of that list of names so it is in the same order as the original sortableComponents.
+func registeredComponentOrderFromExistingOrder(componentType string, existingOrder sortableComponents) registeredComponentOrder {
+ // Only the names from the existing order are needed for this so create a list of component names
+ // in the correct order.
+ namesInOrder := componentsToNames(existingOrder)
+
+ // Populate the map from name to position in the list.
+ nameToIndex := make(map[string]int)
+ for i, n := range namesInOrder {
+ nameToIndex[n] = i
+ }
+
+ // A function to use to map from a name to an index in the original order.
+ indexOf := func(name string) int {
+ index, ok := nameToIndex[name]
+ if !ok {
+ // Should never happen as tests that use components that are not known at runtime do not sort
+ // so should never use this function.
+ panic(fmt.Errorf("internal error: unknown %s %q should be one of %s", componentType, name, strings.Join(namesInOrder, ", ")))
+ }
+ return index
+ }
+
+ // The less function.
+ less := func(n1, n2 string) bool {
+ i1 := indexOf(n1)
+ i2 := indexOf(n2)
+ return i1 < i2
+ }
+
+ return registeredComponentOrder{
+ componentType: componentType,
+ namesInOrder: namesInOrder,
+ namesToIndex: nameToIndex,
+ less: less,
+ }
+}
+
+// componentsToNames maps from the slice of components to a slice of their names.
+func componentsToNames(components sortableComponents) []string {
+ names := make([]string, len(components))
+ for i, c := range components {
+ names[i] = c.componentName()
+ }
+ return names
+}
+
+// enforceOrdering enforces the supplied components are in the same order as is defined in this
+// object.
+//
+// If the supplied components contains any components that are not registered at runtime, i.e. test
+// specific components, then it is impossible to sort them into an order that both matches the
+// runtime and also preserves the implicit ordering defined in the test. In that case it will not
+// sort the components, instead it will just check that the components are in the correct order.
+//
+// Otherwise, this will sort the supplied components in place.
+func (o *registeredComponentOrder) enforceOrdering(components sortableComponents) {
+ // Check to see if the list of components contains any components that are
+ // not registered at runtime.
+ var unknownComponents []string
+ testOrder := componentsToNames(components)
+ for _, name := range testOrder {
+ if _, ok := o.namesToIndex[name]; !ok {
+ unknownComponents = append(unknownComponents, name)
+ break
+ }
+ }
+
+ // If the slice contains some unknown components then it is not possible to
+ // sort them into an order that matches the runtime while also preserving the
+ // order expected from the test, so in that case don't sort just check that
+ // the order of the known mutators does match.
+ if len(unknownComponents) > 0 {
+ // Check order.
+ o.checkTestOrder(testOrder, unknownComponents)
+ } else {
+ // Sort the components.
+ sort.Slice(components, func(i, j int) bool {
+ n1 := components[i].componentName()
+ n2 := components[j].componentName()
+ return o.less(n1, n2)
+ })
+ }
+}
+
+// checkTestOrder checks that the supplied testOrder matches the one defined by this object,
+// panicking if it does not.
+func (o *registeredComponentOrder) checkTestOrder(testOrder []string, unknownComponents []string) {
+ lastMatchingTest := -1
+ matchCount := 0
+ // Take a copy of the runtime order as it is modified during the comparison.
+ runtimeOrder := append([]string(nil), o.namesInOrder...)
+ componentType := o.componentType
+ for i, j := 0, 0; i < len(testOrder) && j < len(runtimeOrder); {
+ test := testOrder[i]
+ runtime := runtimeOrder[j]
+
+ if test == runtime {
+ testOrder[i] = test + fmt.Sprintf(" <-- matched with runtime %s %d", componentType, j)
+ runtimeOrder[j] = runtime + fmt.Sprintf(" <-- matched with test %s %d", componentType, i)
+ lastMatchingTest = i
+ i += 1
+ j += 1
+ matchCount += 1
+ } else if _, ok := o.namesToIndex[test]; !ok {
+ // The test component is not registered globally so assume it is the correct place, treat it
+ // as having matched and skip it.
+ i += 1
+ matchCount += 1
+ } else {
+ // Assume that the test list is in the same order as the runtime list but the runtime list
+ // contains some components that are not present in the tests. So, skip the runtime component
+ // to try and find the next one that matches the current test component.
+ j += 1
+ }
+ }
+
+ // If every item in the test order was either test specific or matched one in the runtime then
+ // it is in the correct order. Otherwise, it was not so fail.
+ if matchCount != len(testOrder) {
+ // The test component names were not all matched with a runtime component name so there must
+ // either be a component present in the test that is not present in the runtime or they must be
+ // in the wrong order.
+ testOrder[lastMatchingTest+1] = testOrder[lastMatchingTest+1] + " <--- unmatched"
+ panic(fmt.Errorf("the tests uses test specific components %q and so cannot be automatically sorted."+
+ " Unfortunately it uses %s components in the wrong order.\n"+
+ "test order:\n %s\n"+
+ "runtime order\n %s\n",
+ SortedUniqueStrings(unknownComponents),
+ componentType,
+ strings.Join(testOrder, "\n "),
+ strings.Join(runtimeOrder, "\n ")))
+ }
+}
+
+// registrationSorter encapsulates the information needed to ensure that the test mutators are
+// registered, and thereby executed, in the same order as they are at runtime.
+//
+// It MUST be populated lazily AFTER all package initialization has been done otherwise it will
+// only define the order for a subset of all the registered build components that are available for
+// the packages being tested.
+//
+// e.g if this is initialized during say the cc package initialization then any tests run in the
+// java package will not sort build components registered by the java package's init() functions.
+type registrationSorter struct {
+ // Used to ensure that this is only created once.
+ once sync.Once
+
+ // The order of pre-singletons
+ preSingletonOrder registeredComponentOrder
+
+ // The order of mutators
+ mutatorOrder registeredComponentOrder
+
+ // The order of singletons
+ singletonOrder registeredComponentOrder
+}
+
+// populate initializes this structure from globally registered build components.
+//
+// Only the first call has any effect.
+func (s *registrationSorter) populate() {
+ s.once.Do(func() {
+ // Create an ordering from the globally registered pre-singletons.
+ s.preSingletonOrder = registeredComponentOrderFromExistingOrder("pre-singleton", preSingletons)
+
+ // Created an ordering from the globally registered mutators.
+ globallyRegisteredMutators := collateGloballyRegisteredMutators()
+ s.mutatorOrder = registeredComponentOrderFromExistingOrder("mutator", globallyRegisteredMutators)
+
+ // Create an ordering from the globally registered singletons.
+ globallyRegisteredSingletons := collateGloballyRegisteredSingletons()
+ s.singletonOrder = registeredComponentOrderFromExistingOrder("singleton", globallyRegisteredSingletons)
+ })
+}
+
+// Provides support for enforcing the same order in which build components are registered globally
+// to the order in which they are registered during tests.
+//
+// MUST only be accessed via the globallyRegisteredComponentsOrder func.
+var globalRegistrationSorter registrationSorter
+
+// globallyRegisteredComponentsOrder returns the globalRegistrationSorter after ensuring it is
+// correctly populated.
+func globallyRegisteredComponentsOrder() *registrationSorter {
+ globalRegistrationSorter.populate()
+ return &globalRegistrationSorter
+}
+
func (ctx *TestContext) Register() {
- registerMutators(ctx.Context.Context, ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
+ globalOrder := globallyRegisteredComponentsOrder()
+
+ // Ensure that the pre-singletons used in the test are in the same order as they are used at
+ // runtime.
+ globalOrder.preSingletonOrder.enforceOrdering(ctx.preSingletons)
+ ctx.preSingletons.registerAll(ctx.Context)
+ mutators := collateRegisteredMutators(ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
+ // Ensure that the mutators used in the test are in the same order as they are used at runtime.
+ globalOrder.mutatorOrder.enforceOrdering(mutators)
+ mutators.registerAll(ctx.Context)
+
+ // Register the env singleton with this context before sorting.
ctx.RegisterSingletonType("env", EnvSingleton)
+
+ // Ensure that the singletons used in the test are in the same order as they are used at runtime.
+ globalOrder.singletonOrder.enforceOrdering(ctx.singletons)
+ ctx.singletons.registerAll(ctx.Context)
+
+ // Save the sorted components order away to make them easy to access while debugging.
+ ctx.preSingletonOrder = componentsToNames(preSingletons)
+ ctx.mutatorOrder = componentsToNames(mutators)
+ ctx.singletonOrder = componentsToNames(singletons)
}
// RegisterForBazelConversion prepares a test context for bp2build conversion.
func (ctx *TestContext) RegisterForBazelConversion() {
- RegisterMutatorsForBazelConversion(ctx.Context.Context, ctx.bp2buildPreArch, ctx.bp2buildDeps, ctx.bp2buildMutators)
+ RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch, ctx.bp2buildDeps, ctx.bp2buildMutators)
}
func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
@@ -137,7 +430,11 @@ func (ctx *TestContext) RegisterSingletonModuleType(name string, factory Singlet
}
func (ctx *TestContext) RegisterSingletonType(name string, factory SingletonFactory) {
- ctx.Context.RegisterSingletonType(name, SingletonFactoryAdaptor(ctx.Context, factory))
+ ctx.singletons = append(ctx.singletons, newSingleton(name, factory))
+}
+
+func (ctx *TestContext) RegisterPreSingletonType(name string, factory SingletonFactory) {
+ ctx.preSingletons = append(ctx.preSingletons, newPreSingleton(name, factory))
}
func (ctx *TestContext) ModuleForTests(name, variant string) TestingModule {
@@ -415,12 +712,15 @@ func FailIfErrored(t *testing.T, errs []error) {
}
}
-func FailIfNoMatchingErrors(t *testing.T, pattern string, errs []error) {
+// Fail if no errors that matched the regular expression were found.
+//
+// Returns true if a matching error was found, false otherwise.
+func FailIfNoMatchingErrors(t *testing.T, pattern string, errs []error) bool {
t.Helper()
matcher, err := regexp.Compile(pattern)
if err != nil {
- t.Errorf("failed to compile regular expression %q because %s", pattern, err)
+ t.Fatalf("failed to compile regular expression %q because %s", pattern, err)
}
found := false
@@ -436,6 +736,8 @@ func FailIfNoMatchingErrors(t *testing.T, pattern string, errs []error) {
t.Errorf("errs[%d] = %q", i, err)
}
}
+
+ return found
}
func CheckErrorsAgainstExpectations(t *testing.T, errs []error, expectedErrorPatterns []string) {
@@ -456,9 +758,9 @@ func CheckErrorsAgainstExpectations(t *testing.T, errs []error, expectedErrorPat
for i, err := range errs {
t.Errorf("errs[%d] = %s", i, err)
}
+ t.FailNow()
}
}
-
}
func SetKatiEnabledForTests(config Config) {
@@ -504,10 +806,6 @@ func NormalizePathForTesting(path Path) string {
return "<nil path>"
}
p := path.String()
- // Allow absolute paths to /dev/
- if strings.HasPrefix(p, "/dev/") {
- return p
- }
if w, ok := path.(WritablePath); ok {
rel, err := filepath.Rel(w.buildDir(), p)
if err != nil {
diff --git a/android/variable.go b/android/variable.go
index 060069257..3a9738d25 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -124,6 +124,7 @@ type variableProperties struct {
Arc struct {
Cflags []string `android:"arch_variant"`
Exclude_srcs []string `android:"arch_variant"`
+ Header_libs []string `android:"arch_variant"`
Include_dirs []string `android:"arch_variant"`
Shared_libs []string `android:"arch_variant"`
Static_libs []string `android:"arch_variant"`
diff --git a/android/visibility.go b/android/visibility.go
index 7eac47166..5d1be6b47 100644
--- a/android/visibility.go
+++ b/android/visibility.go
@@ -202,6 +202,15 @@ type ExcludeFromVisibilityEnforcementTag interface {
ExcludeFromVisibilityEnforcement()
}
+// The visibility mutators.
+var PrepareForTestWithVisibility = FixtureRegisterWithContext(registerVisibilityMutators)
+
+func registerVisibilityMutators(ctx RegistrationContext) {
+ ctx.PreArchMutators(RegisterVisibilityRuleChecker)
+ ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
+ ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
+}
+
// The rule checker needs to be registered before defaults expansion to correctly check that
// //visibility:xxx isn't combined with other packages in the same list in any one module.
func RegisterVisibilityRuleChecker(ctx RegisterMutatorsContext) {
diff --git a/android/visibility_test.go b/android/visibility_test.go
index 87a295e23..eb4071eb7 100644
--- a/android/visibility_test.go
+++ b/android/visibility_test.go
@@ -9,13 +9,13 @@ import (
var visibilityTests = []struct {
name string
- fs map[string][]byte
+ fs MockFS
expectedErrors []string
effectiveVisibility map[qualifiedModuleName][]string
}{
{
name: "invalid visibility: empty list",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -26,7 +26,7 @@ var visibilityTests = []struct {
},
{
name: "invalid visibility: empty rule",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -37,7 +37,7 @@ var visibilityTests = []struct {
},
{
name: "invalid visibility: unqualified",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -48,7 +48,7 @@ var visibilityTests = []struct {
},
{
name: "invalid visibility: empty namespace",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -59,7 +59,7 @@ var visibilityTests = []struct {
},
{
name: "invalid visibility: empty module",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -70,7 +70,7 @@ var visibilityTests = []struct {
},
{
name: "invalid visibility: empty namespace and module",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -81,7 +81,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:unknown",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -92,7 +92,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:xxx mixed",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -113,7 +113,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:legacy_public",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -129,7 +129,7 @@ var visibilityTests = []struct {
// Verify that //visibility:public will allow the module to be referenced from anywhere, e.g.
// the current directory, a nested directory and a directory in a separate tree.
name: "//visibility:public",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -156,7 +156,7 @@ var visibilityTests = []struct {
// Verify that //visibility:private allows the module to be referenced from the current
// directory only.
name: "//visibility:private",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -188,7 +188,7 @@ var visibilityTests = []struct {
{
// Verify that :__pkg__ allows the module to be referenced from the current directory only.
name: ":__pkg__",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -221,7 +221,7 @@ var visibilityTests = []struct {
// Verify that //top/nested allows the module to be referenced from the current directory and
// the top/nested directory only, not a subdirectory of top/nested and not peak directory.
name: "//top/nested",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -259,7 +259,7 @@ var visibilityTests = []struct {
// Verify that :__subpackages__ allows the module to be referenced from the current directory
// and sub directories but nowhere else.
name: ":__subpackages__",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -290,7 +290,7 @@ var visibilityTests = []struct {
// Verify that //top/nested:__subpackages__ allows the module to be referenced from the current
// directory and sub directories but nowhere else.
name: "//top/nested:__subpackages__",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -321,7 +321,7 @@ var visibilityTests = []struct {
// Verify that ["//top/nested", "//peak:__subpackages"] allows the module to be referenced from
// the current directory, top/nested and peak and all its subpackages.
name: `["//top/nested", "//peak:__subpackages__"]`,
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -347,7 +347,7 @@ var visibilityTests = []struct {
{
// Verify that //vendor... cannot be used outside vendor apart from //vendor:__subpackages__
name: `//vendor`,
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -381,7 +381,7 @@ var visibilityTests = []struct {
{
// Check that visibility is the union of the defaults modules.
name: "defaults union, basic",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults",
@@ -419,7 +419,7 @@ var visibilityTests = []struct {
},
{
name: "defaults union, multiple defaults",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults_1",
@@ -460,7 +460,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:public mixed with other in defaults",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults",
@@ -478,7 +478,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:public overriding defaults",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults",
@@ -501,7 +501,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:public mixed with other from different defaults 1",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults_1",
@@ -524,7 +524,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:public mixed with other from different defaults 2",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults_1",
@@ -547,7 +547,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:private in defaults",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults",
@@ -581,7 +581,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:private mixed with other in defaults",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults",
@@ -599,7 +599,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:private overriding defaults",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults",
@@ -618,7 +618,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:private in defaults overridden",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults",
@@ -637,7 +637,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:private override //visibility:public",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults",
@@ -655,7 +655,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:public override //visibility:private",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults",
@@ -673,7 +673,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:override must be first in the list",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_library {
name: "libexample",
@@ -686,7 +686,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:override discards //visibility:private",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults",
@@ -707,7 +707,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:override discards //visibility:public",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults",
@@ -736,7 +736,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:override discards defaults supplied rules",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults",
@@ -765,7 +765,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:override can override //visibility:public with //visibility:private",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults",
@@ -788,7 +788,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:override can override //visibility:private with //visibility:public",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults",
@@ -808,7 +808,7 @@ var visibilityTests = []struct {
},
{
name: "//visibility:private mixed with itself",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "libexample_defaults_1",
@@ -838,7 +838,7 @@ var visibilityTests = []struct {
// Defaults module's defaults_visibility tests
{
name: "defaults_visibility invalid",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_defaults {
name: "top_defaults",
@@ -851,7 +851,7 @@ var visibilityTests = []struct {
},
{
name: "defaults_visibility overrides package default",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
package {
default_visibility: ["//visibility:private"],
@@ -871,7 +871,7 @@ var visibilityTests = []struct {
// Package default_visibility tests
{
name: "package default_visibility property is checked",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
package {
default_visibility: ["//visibility:invalid"],
@@ -882,7 +882,7 @@ var visibilityTests = []struct {
{
// This test relies on the default visibility being legacy_public.
name: "package default_visibility property used when no visibility specified",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
package {
default_visibility: ["//visibility:private"],
@@ -904,7 +904,7 @@ var visibilityTests = []struct {
},
{
name: "package default_visibility public does not override visibility private",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
package {
default_visibility: ["//visibility:public"],
@@ -927,7 +927,7 @@ var visibilityTests = []struct {
},
{
name: "package default_visibility private does not override visibility public",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
package {
default_visibility: ["//visibility:private"],
@@ -946,7 +946,7 @@ var visibilityTests = []struct {
},
{
name: "package default_visibility :__subpackages__",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
package {
default_visibility: [":__subpackages__"],
@@ -973,7 +973,7 @@ var visibilityTests = []struct {
},
{
name: "package default_visibility inherited to subpackages",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
package {
default_visibility: ["//outsider"],
@@ -1001,7 +1001,7 @@ var visibilityTests = []struct {
},
{
name: "package default_visibility inherited to subpackages",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
package {
default_visibility: ["//visibility:private"],
@@ -1031,7 +1031,7 @@ var visibilityTests = []struct {
},
{
name: "verify that prebuilt dependencies are ignored for visibility reasons (not preferred)",
- fs: map[string][]byte{
+ fs: MockFS{
"prebuilts/Blueprints": []byte(`
prebuilt {
name: "module",
@@ -1053,7 +1053,7 @@ var visibilityTests = []struct {
},
{
name: "verify that prebuilt dependencies are ignored for visibility reasons (preferred)",
- fs: map[string][]byte{
+ fs: MockFS{
"prebuilts/Blueprints": []byte(`
prebuilt {
name: "module",
@@ -1076,7 +1076,7 @@ var visibilityTests = []struct {
},
{
name: "ensure visibility properties are checked for correctness",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_parent {
name: "parent",
@@ -1093,7 +1093,7 @@ var visibilityTests = []struct {
},
{
name: "invalid visibility added to child detected during gather phase",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_parent {
name: "parent",
@@ -1115,7 +1115,7 @@ var visibilityTests = []struct {
},
{
name: "automatic visibility inheritance enabled",
- fs: map[string][]byte{
+ fs: MockFS{
"top/Blueprints": []byte(`
mock_parent {
name: "parent",
@@ -1142,55 +1142,44 @@ var visibilityTests = []struct {
func TestVisibility(t *testing.T) {
for _, test := range visibilityTests {
t.Run(test.name, func(t *testing.T) {
- ctx, errs := testVisibility(buildDir, test.fs)
+ result := emptyTestFixtureFactory.Extend(
+ // General preparers in alphabetical order as test infrastructure will enforce correct
+ // registration order.
+ PrepareForTestWithArchMutator,
+ PrepareForTestWithDefaults,
+ PrepareForTestWithOverrides,
+ PrepareForTestWithPackageModule,
+ PrepareForTestWithPrebuilts,
+ PrepareForTestWithVisibility,
- CheckErrorsAgainstExpectations(t, errs, test.expectedErrors)
+ // Additional test specific preparers.
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("mock_library", newMockLibraryModule)
+ ctx.RegisterModuleType("mock_parent", newMockParentFactory)
+ ctx.RegisterModuleType("mock_defaults", defaultsFactory)
+ }),
+ prepareForTestWithFakePrebuiltModules,
+ // Add additional files to the mock filesystem
+ test.fs.AddToFixture(),
+ ).
+ ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern(test.expectedErrors)).
+ RunTest(t)
if test.effectiveVisibility != nil {
- checkEffectiveVisibility(t, ctx, test.effectiveVisibility)
+ checkEffectiveVisibility(result, test.effectiveVisibility)
}
})
}
}
-func checkEffectiveVisibility(t *testing.T, ctx *TestContext, effectiveVisibility map[qualifiedModuleName][]string) {
+func checkEffectiveVisibility(result *TestResult, effectiveVisibility map[qualifiedModuleName][]string) {
for moduleName, expectedRules := range effectiveVisibility {
- rule := effectiveVisibilityRules(ctx.config, moduleName)
+ rule := effectiveVisibilityRules(result.Config, moduleName)
stringRules := rule.Strings()
- if !reflect.DeepEqual(expectedRules, stringRules) {
- t.Errorf("effective rules mismatch: expected %q, found %q", expectedRules, stringRules)
- }
+ result.AssertDeepEquals("effective rules mismatch", expectedRules, stringRules)
}
}
-func testVisibility(buildDir string, fs map[string][]byte) (*TestContext, []error) {
-
- // Create a new config per test as visibility information is stored in the config.
- config := TestArchConfig(buildDir, nil, "", fs)
-
- ctx := NewTestArchContext(config)
- ctx.RegisterModuleType("mock_library", newMockLibraryModule)
- ctx.RegisterModuleType("mock_parent", newMockParentFactory)
- ctx.RegisterModuleType("mock_defaults", defaultsFactory)
-
- // Order of the following method calls is significant.
- RegisterPackageBuildComponents(ctx)
- registerTestPrebuiltBuildComponents(ctx)
- ctx.PreArchMutators(RegisterVisibilityRuleChecker)
- ctx.PreArchMutators(RegisterDefaultsPreArchMutators)
- ctx.PreArchMutators(RegisterVisibilityRuleGatherer)
- ctx.PostDepsMutators(RegisterVisibilityRuleEnforcer)
- ctx.Register()
-
- _, errs := ctx.ParseBlueprintsFiles(".")
- if len(errs) > 0 {
- return ctx, errs
- }
-
- _, errs = ctx.PrepareBuildActions(config)
- return ctx, errs
-}
-
type mockLibraryProperties struct {
Deps []string
}
diff --git a/android/writedocs.go b/android/writedocs.go
index 91c2318f1..6cb2f1024 100644
--- a/android/writedocs.go
+++ b/android/writedocs.go
@@ -34,7 +34,8 @@ func DocsSingleton() Singleton {
type docsSingleton struct{}
func primaryBuilderPath(ctx SingletonContext) Path {
- primaryBuilder, err := filepath.Rel(ctx.Config().BuildDir(), os.Args[0])
+ buildDir := absolutePath(ctx.Config().BuildDir())
+ primaryBuilder, err := filepath.Rel(buildDir, os.Args[0])
if err != nil {
ctx.Errorf("path to primary builder %q is not in build dir %q",
os.Args[0], ctx.Config().BuildDir())
@@ -65,7 +66,9 @@ func (c *docsSingleton) GenerateBuildActions(ctx SingletonContext) {
soongDocs := ctx.Rule(pctx, "soongDocs",
blueprint.RuleParams{
Command: fmt.Sprintf("rm -f ${outDir}/* && %s --soong_docs %s %s",
- primaryBuilder.String(), docsFile.String(), strings.Join(os.Args[1:], " ")),
+ primaryBuilder.String(),
+ docsFile.String(),
+ "\""+strings.Join(os.Args[1:], "\" \"")+"\""),
CommandDeps: []string{primaryBuilder.String()},
Description: fmt.Sprintf("%s docs $out", primaryBuilder.Base()),
},
diff --git a/androidmk/androidmk/androidmk.go b/androidmk/androidmk/androidmk.go
index 2d1bbb4a8..b8316a361 100644
--- a/androidmk/androidmk/androidmk.go
+++ b/androidmk/androidmk/androidmk.go
@@ -48,6 +48,22 @@ var invalidVariableStringToReplacement = map[string]string{
"-": "_dash_",
}
+// Fix steps that should only run in the androidmk tool, i.e. should only be applied to
+// newly-converted Android.bp files.
+var fixSteps = bpfix.FixStepsExtension{
+ Name: "androidmk",
+ Steps: []bpfix.FixStep{
+ {
+ Name: "RewriteRuntimeResourceOverlay",
+ Fix: bpfix.RewriteRuntimeResourceOverlay,
+ },
+ },
+}
+
+func init() {
+ bpfix.RegisterFixStepExtension(&fixSteps)
+}
+
func (f *bpFile) insertComment(s string) {
f.comments = append(f.comments, &bpparser.CommentGroup{
Comments: []*bpparser.Comment{
diff --git a/apex/OWNERS b/apex/OWNERS
index 793f3ed19..fee739b56 100644
--- a/apex/OWNERS
+++ b/apex/OWNERS
@@ -1,4 +1,4 @@
per-file * = jiyong@google.com
per-file allowed_deps.txt = set noparent
-per-file allowed_deps.txt = dariofreni@google.com,hansson@google.com,harpin@google.com,jiyong@google.com,narayan@google.com,omakoto@google.com,jham@google.com
+per-file allowed_deps.txt = dariofreni@google.com,hansson@google.com,harpin@google.com,jiyong@google.com,narayan@google.com,jham@google.com
diff --git a/apex/allowed_deps.txt b/apex/allowed_deps.txt
index 321a428e8..d9d8f4309 100644
--- a/apex/allowed_deps.txt
+++ b/apex/allowed_deps.txt
@@ -193,11 +193,14 @@ crtend_android(minSdkVersion:apex_inherit)
crtend_so(minSdkVersion:16)
crtend_so(minSdkVersion:apex_inherit)
datastallprotosnano(minSdkVersion:29)
+derive_classpath(minSdkVersion:30)
derive_sdk(minSdkVersion:30)
derive_sdk(minSdkVersion:current)
derive_sdk_prefer32(minSdkVersion:30)
derive_sdk_prefer32(minSdkVersion:current)
+dnsresolver_aidl_interface-lateststable-ndk_platform(minSdkVersion:29)
dnsresolver_aidl_interface-unstable-ndk_platform(minSdkVersion:29)
+dnsresolver_aidl_interface-V7-ndk_platform(minSdkVersion:29)
dnsresolver_aidl_interface-V8-ndk_platform(minSdkVersion:29)
DocumentsUI-res-lib(minSdkVersion:29)
exoplayer2-extractor(minSdkVersion:16)
@@ -356,6 +359,7 @@ libdmabufheap(minSdkVersion:29)
libeigen(minSdkVersion:(no version))
libextservices(minSdkVersion:30)
libextservices_jni(minSdkVersion:30)
+libfft2d(minSdkVersion:30)
libfifo(minSdkVersion:29)
libFLAC(minSdkVersion:29)
libFLAC-config(minSdkVersion:29)
@@ -401,6 +405,7 @@ liblua(minSdkVersion:30)
liblz4(minSdkVersion:(no version))
libm(minSdkVersion:(no version))
libmath(minSdkVersion:29)
+libmath_headers(minSdkVersion:apex_inherit)
libmdnssd(minSdkVersion:(no version))
libmedia_codecserviceregistrant(minSdkVersion:29)
libmedia_datasource_headers(minSdkVersion:29)
@@ -460,6 +465,7 @@ libquiche_ffi_headers(minSdkVersion:29)
libring(minSdkVersion:(no version))
libring-core(minSdkVersion:29)
librustc_demangle.rust_sysroot(minSdkVersion:(no version))
+libruy_static(minSdkVersion:30)
libsdk_proto(minSdkVersion:30)
libsfplugin_ccodec_utils(minSdkVersion:29)
libshmemcompat(minSdkVersion:29)
@@ -493,6 +499,7 @@ libstagefright_mpeg2extractor(minSdkVersion:29)
libstagefright_mpeg2support_nocrypto(minSdkVersion:29)
libstats_jni(minSdkVersion:(no version))
libstats_jni(minSdkVersion:30)
+libstatslog_media(minSdkVersion:29)
libstatslog_resolv(minSdkVersion:29)
libstatslog_statsd(minSdkVersion:(no version))
libstatslog_statsd(minSdkVersion:30)
@@ -549,7 +556,9 @@ mediatranscoding(minSdkVersion:29)
mediatranscoding_aidl_interface-java(minSdkVersion:29)
mediatranscoding_aidl_interface-ndk_platform(minSdkVersion:29)
metrics-constants-protos(minSdkVersion:29)
+modules-annotation-minsdk(minSdkVersion:29)
modules-utils-build(minSdkVersion:29)
+modules-utils-build_system(minSdkVersion:29)
modules-utils-os(minSdkVersion:30)
ndk_crtbegin_so.19(minSdkVersion:(no version))
ndk_crtbegin_so.21(minSdkVersion:(no version))
@@ -573,8 +582,10 @@ netd_aidl_interface-V3-java(minSdkVersion:29)
netd_aidl_interface-V5-java(minSdkVersion:29)
netd_aidl_interface-V6-java(minSdkVersion:29)
netd_event_listener_interface-java(minSdkVersion:29)
+netd_event_listener_interface-lateststable-ndk_platform(minSdkVersion:29)
netd_event_listener_interface-ndk_platform(minSdkVersion:29)
netd_event_listener_interface-unstable-ndk_platform(minSdkVersion:29)
+netd_event_listener_interface-V1-ndk_platform(minSdkVersion:29)
netd_event_listener_interface-V2-ndk_platform(minSdkVersion:29)
netlink-client(minSdkVersion:29)
networkstack-aidl-interfaces-java(minSdkVersion:29)
@@ -582,9 +593,13 @@ networkstack-aidl-interfaces-unstable-java(minSdkVersion:29)
networkstack-aidl-interfaces-V10-java(minSdkVersion:29)
networkstack-aidl-interfaces-V9-java(minSdkVersion:29)
networkstack-client(minSdkVersion:29)
+NetworkStackApi29Shims(minSdkVersion:29)
+NetworkStackApi30Shims(minSdkVersion:29)
NetworkStackApiStableDependencies(minSdkVersion:29)
NetworkStackApiStableLib(minSdkVersion:29)
+NetworkStackApiStableShims(minSdkVersion:29)
networkstackprotos(minSdkVersion:29)
+NetworkStackShimsCommon(minSdkVersion:29)
neuralnetworks_types(minSdkVersion:30)
neuralnetworks_utils_hal_1_0(minSdkVersion:30)
neuralnetworks_utils_hal_1_1(minSdkVersion:30)
diff --git a/apex/apex.go b/apex/apex.go
index 74df28ea9..d37bd483e 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -39,23 +39,25 @@ import (
)
func init() {
- android.RegisterModuleType("apex", BundleFactory)
- android.RegisterModuleType("apex_test", testApexBundleFactory)
- android.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
- android.RegisterModuleType("apex_defaults", defaultsFactory)
- android.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
- android.RegisterModuleType("override_apex", overrideApexFactory)
- android.RegisterModuleType("apex_set", apexSetFactory)
+ registerApexBuildComponents(android.InitRegistrationContext)
+}
+
+func registerApexBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("apex", BundleFactory)
+ ctx.RegisterModuleType("apex_test", testApexBundleFactory)
+ ctx.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
+ ctx.RegisterModuleType("apex_defaults", defaultsFactory)
+ ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
+ ctx.RegisterModuleType("override_apex", overrideApexFactory)
+ ctx.RegisterModuleType("apex_set", apexSetFactory)
- android.PreDepsMutators(RegisterPreDepsMutators)
- android.PostDepsMutators(RegisterPostDepsMutators)
+ ctx.PreDepsMutators(RegisterPreDepsMutators)
+ ctx.PostDepsMutators(RegisterPostDepsMutators)
}
func RegisterPreDepsMutators(ctx android.RegisterMutatorsContext) {
ctx.TopDown("apex_vndk", apexVndkMutator).Parallel()
ctx.BottomUp("apex_vndk_deps", apexVndkDepsMutator).Parallel()
- ctx.BottomUp("prebuilt_apex_select_source", prebuiltSelectSourceMutator).Parallel()
- ctx.BottomUp("deapexer_select_source", deapexerSelectSourceMutator).Parallel()
}
func RegisterPostDepsMutators(ctx android.RegisterMutatorsContext) {
@@ -123,7 +125,7 @@ type apexBundleProperties struct {
// Whether this APEX is considered updatable or not. When set to true, this will enforce
// additional rules for making sure that the APEX is truly updatable. To be updatable,
// min_sdk_version should be set as well. This will also disable the size optimizations like
- // symlinking to the system libs. Default is false.
+ // symlinking to the system libs. Default is true.
Updatable *bool
// Whether this APEX is installable to one of the partitions like system, vendor, etc.
@@ -1234,7 +1236,7 @@ var _ android.ApexBundleDepsInfoIntf = (*apexBundle)(nil)
// Implements android.ApexBudleDepsInfoIntf
func (a *apexBundle) Updatable() bool {
- return proptools.Bool(a.properties.Updatable)
+ return proptools.BoolDefault(a.properties.Updatable, true)
}
// getCertString returns the name of the cert that should be used to sign this APEX. This is
@@ -2246,8 +2248,10 @@ func (a *apexBundle) checkApexAvailability(ctx android.ModuleContext) {
if to.AvailableFor(apexName) || baselineApexAvailable(apexName, toName) {
return true
}
- ctx.ModuleErrorf("%q requires %q that doesn't list the APEX under 'apex_available'. Dependency path:%s",
- fromName, toName, ctx.GetPathString(true))
+ ctx.ModuleErrorf("%q requires %q that doesn't list the APEX under 'apex_available'."+
+ "\n\nDependency path:%s\n\n"+
+ "Consider adding %q to 'apex_available' property of %q",
+ fromName, toName, ctx.GetPathString(true), apexName, toName)
// Visit this module's dependencies to check and report any issues with their availability.
return true
})
@@ -2853,14 +2857,6 @@ func makeApexAvailableBaseline() map[string][]string {
//
// Module separator
//
- m["com.android.sdkext"] = []string{
- "fmtlib_ndk",
- "libbase_ndk",
- "libprotobuf-cpp-lite-ndk",
- }
- //
- // Module separator
- //
m["com.android.os.statsd"] = []string{
"libstatssocket",
}
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 3f5604741..08f54f724 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -19,6 +19,7 @@ import (
"io/ioutil"
"os"
"path"
+ "path/filepath"
"reflect"
"regexp"
"sort"
@@ -66,14 +67,14 @@ func testApexError(t *testing.T, pattern, bp string, handlers ...testCustomizer)
t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
}
-func testApex(t *testing.T, bp string, handlers ...testCustomizer) (*android.TestContext, android.Config) {
+func testApex(t *testing.T, bp string, handlers ...testCustomizer) *android.TestContext {
t.Helper()
ctx, config := testApexContext(t, bp, handlers...)
_, errs := ctx.ParseBlueprintsFiles(".")
android.FailIfErrored(t, errs)
_, errs = ctx.PrepareBuildActions(config)
android.FailIfErrored(t, errs)
- return ctx, config
+ return ctx
}
type testCustomizer func(fs map[string][]byte, config android.Config)
@@ -143,17 +144,18 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr
bp = bp + java.GatherRequiredDepsForTest()
fs := map[string][]byte{
- "a.java": nil,
- "PrebuiltAppFoo.apk": nil,
- "PrebuiltAppFooPriv.apk": nil,
- "build/make/target/product/security": nil,
- "apex_manifest.json": nil,
- "AndroidManifest.xml": nil,
- "system/sepolicy/apex/myapex-file_contexts": nil,
- "system/sepolicy/apex/myapex.updatable-file_contexts": nil,
- "system/sepolicy/apex/myapex2-file_contexts": nil,
- "system/sepolicy/apex/otherapex-file_contexts": nil,
- "system/sepolicy/apex/com.android.vndk-file_contexts": nil,
+ "a.java": nil,
+ "PrebuiltAppFoo.apk": nil,
+ "PrebuiltAppFooPriv.apk": nil,
+ "build/make/target/product/security": nil,
+ "apex_manifest.json": nil,
+ "AndroidManifest.xml": nil,
+ "system/sepolicy/apex/myapex-file_contexts": nil,
+ "system/sepolicy/apex/myapex.updatable-file_contexts": nil,
+ "system/sepolicy/apex/myapex2-file_contexts": nil,
+ "system/sepolicy/apex/otherapex-file_contexts": nil,
+ "system/sepolicy/apex/com.android.vndk-file_contexts": nil,
+ "system/sepolicy/apex/com.android.vndk.current-file_contexts": nil,
"mylib.cpp": nil,
"mytest.cpp": nil,
"mytest1.cpp": nil,
@@ -191,6 +193,7 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr
"AppSet.apks": nil,
"foo.rs": nil,
"libfoo.jar": nil,
+ "libbar.jar": nil,
}
cc.GatherRequiredFilesForTest(fs)
@@ -226,18 +229,11 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr
android.RegisterPackageBuildComponents(ctx)
ctx.PreArchMutators(android.RegisterVisibilityRuleChecker)
- ctx.RegisterModuleType("apex", BundleFactory)
- ctx.RegisterModuleType("apex_test", testApexBundleFactory)
- ctx.RegisterModuleType("apex_vndk", vndkApexBundleFactory)
- ctx.RegisterModuleType("apex_key", ApexKeyFactory)
- ctx.RegisterModuleType("apex_defaults", defaultsFactory)
- ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
- ctx.RegisterModuleType("override_apex", overrideApexFactory)
- ctx.RegisterModuleType("apex_set", apexSetFactory)
+ registerApexBuildComponents(ctx)
+ registerApexKeyBuildComponents(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
ctx.PreArchMutators(android.RegisterComponentsMutator)
- ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
android.RegisterPrebuiltMutators(ctx)
@@ -246,6 +242,10 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr
ctx.PreArchMutators(android.RegisterVisibilityRuleGatherer)
ctx.PostDepsMutators(android.RegisterVisibilityRuleEnforcer)
+ // These must come after prebuilts and visibility rules to match runtime.
+ ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
+
+ // These must come after override rules to match the runtime.
cc.RegisterRequiredBuildComponentsForTest(ctx)
rust.RegisterRequiredBuildComponentsForTest(ctx)
java.RegisterRequiredBuildComponentsForTest(ctx)
@@ -257,12 +257,8 @@ func testApexContext(_ *testing.T, bp string, handlers ...testCustomizer) (*andr
ctx.RegisterModuleType("platform_compat_config", java.PlatformCompatConfigFactory)
ctx.RegisterModuleType("sh_binary", sh.ShBinaryFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- ctx.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
ctx.RegisterModuleType("bpf", bpf.BpfFactory)
- ctx.PreDepsMutators(RegisterPreDepsMutators)
- ctx.PostDepsMutators(RegisterPostDepsMutators)
-
ctx.Register()
return ctx, config
@@ -354,7 +350,7 @@ func ensureListNotEmpty(t *testing.T, result []string) {
// Minimal test
func TestBasicApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_defaults {
name: "myapex-defaults",
manifest: ":myapex.manifest",
@@ -375,6 +371,7 @@ func TestBasicApex(t *testing.T) {
"myjar",
"myjar_dex",
],
+ updatable: false,
}
apex {
@@ -475,6 +472,7 @@ func TestBasicApex(t *testing.T) {
binaries: ["foo"],
key: "myapex.key",
file_contexts: ":myapex-file_contexts",
+ updatable: false,
}
cc_library_shared {
@@ -658,7 +656,7 @@ func TestBasicApex(t *testing.T) {
}
func TestDefaults(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_defaults {
name: "myapex-defaults",
key: "myapex.key",
@@ -668,6 +666,7 @@ func TestDefaults(t *testing.T) {
apps: ["AppFoo"],
rros: ["rro"],
bpfs: ["bpf"],
+ updatable: false,
}
prebuilt_etc {
@@ -732,10 +731,11 @@ func TestDefaults(t *testing.T) {
}
func TestApexManifest(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
+ updatable: false,
}
apex_key {
@@ -753,12 +753,13 @@ func TestApexManifest(t *testing.T) {
}
func TestBasicZipApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
payload_type: "zip",
native_shared_libs: ["mylib"],
+ updatable: false,
}
apex_key {
@@ -803,11 +804,12 @@ func TestBasicZipApex(t *testing.T) {
}
func TestApexWithStubs(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib", "mylib3"],
+ updatable: false,
}
apex_key {
@@ -897,7 +899,7 @@ func TestApexWithStubs(t *testing.T) {
func TestApexWithStubsWithMinSdkVersion(t *testing.T) {
t.Parallel()
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -970,8 +972,8 @@ func TestApexWithStubsWithMinSdkVersion(t *testing.T) {
mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex29").Rule("ld").Args["libFlags"]
- // Ensure that mylib is linking with the version 29 stubs for mylib2
- ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_29/mylib2.so")
+ // Ensure that mylib is linking with the latest version of stub for mylib2
+ ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
// ... and not linking to the non-stub (impl) variant of mylib2
ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
@@ -1004,7 +1006,7 @@ func TestApex_PlatformUsesLatestStubFromApex(t *testing.T) {
// |
// <platform> |
// libplatform ----------------'
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1055,11 +1057,11 @@ func TestApex_PlatformUsesLatestStubFromApex(t *testing.T) {
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
+ // Ensure that mylib from myapex is built against the latest stub (current)
mylibCflags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_static_apex10000").Rule("cc").Args["cFlags"]
- ensureContains(t, mylibCflags, "-D__LIBSTUB_API__=9000 ")
+ ensureContains(t, mylibCflags, "-D__LIBSTUB_API__=10000 ")
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 ")
+ ensureContains(t, mylibLdflags, "libstub/android_arm64_armv8-a_shared_current/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"]
@@ -1069,11 +1071,12 @@ func TestApex_PlatformUsesLatestStubFromApex(t *testing.T) {
}
func TestApexWithExplicitStubsDependency(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex2",
key: "myapex2.key",
native_shared_libs: ["mylib"],
+ updatable: false,
}
apex_key {
@@ -1164,11 +1167,12 @@ func TestApexWithRuntimeLibsDependency(t *testing.T) {
|
`------> libbar
*/
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib"],
+ updatable: false,
}
apex_key {
@@ -1225,12 +1229,13 @@ func TestApexWithRuntimeLibsDependency(t *testing.T) {
}
func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) {
- ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) {
+ ctx := testApex(t, "", func(fs map[string][]byte, config android.Config) {
bp := `
apex {
name: "com.android.runtime",
key: "com.android.runtime.key",
native_shared_libs: ["libc"],
+ updatable: false,
}
apex_key {
@@ -1288,12 +1293,13 @@ func TestRuntimeApexShouldInstallHwasanIfLibcDependsOnIt(t *testing.T) {
}
func TestRuntimeApexShouldInstallHwasanIfHwaddressSanitized(t *testing.T) {
- ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) {
+ ctx := testApex(t, "", func(fs map[string][]byte, config android.Config) {
bp := `
apex {
name: "com.android.runtime",
key: "com.android.runtime.key",
native_shared_libs: ["libc"],
+ updatable: false,
}
apex_key {
@@ -1357,28 +1363,29 @@ func TestApexDependsOnLLNDKTransitively(t *testing.T) {
shouldNotLink []string
}{
{
- name: "should link to the latest",
+ name: "unspecified version links to the latest",
minSdkVersion: "",
apexVariant: "apex10000",
shouldLink: "30",
shouldNotLink: []string{"29"},
},
{
- name: "should link to llndk#29",
+ name: "always use the latest",
minSdkVersion: "min_sdk_version: \"29\",",
apexVariant: "apex29",
- shouldLink: "29",
- shouldNotLink: []string{"30"},
+ shouldLink: "30",
+ shouldNotLink: []string{"29"},
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
use_vendor: true,
native_shared_libs: ["mylib"],
+ updatable: false,
`+tc.minSdkVersion+`
}
@@ -1439,11 +1446,12 @@ func TestApexDependsOnLLNDKTransitively(t *testing.T) {
}
func TestApexWithSystemLibsStubs(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib", "mylib_shared", "libdl", "libm"],
+ updatable: false,
}
apex_key {
@@ -1530,11 +1538,11 @@ func TestApexWithSystemLibsStubs(t *testing.T) {
}
func TestApexMinSdkVersion_NativeModulesShouldBeBuiltAgainstStubs(t *testing.T) {
- // there are three links between liba --> libz
- // 1) myapex -> libx -> liba -> libz : this should be #29 link, but fallback to #28
+ // there are three links between liba --> libz.
+ // 1) myapex -> libx -> liba -> libz : this should be #30 link
// 2) otherapex -> liby -> liba -> libz : this should be #30 link
// 3) (platform) -> liba -> libz : this should be non-stub link
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1605,9 +1613,9 @@ func TestApexMinSdkVersion_NativeModulesShouldBeBuiltAgainstStubs(t *testing.T)
}
// platform liba is linked to non-stub version
expectLink("liba", "shared", "libz", "shared")
- // liba in myapex is linked to #28
- expectLink("liba", "shared_apex29", "libz", "shared_28")
- expectNoLink("liba", "shared_apex29", "libz", "shared_30")
+ // liba in myapex is linked to #30
+ expectLink("liba", "shared_apex29", "libz", "shared_30")
+ expectNoLink("liba", "shared_apex29", "libz", "shared_28")
expectNoLink("liba", "shared_apex29", "libz", "shared")
// liba in otherapex is linked to #30
expectLink("liba", "shared_apex30", "libz", "shared_30")
@@ -1616,7 +1624,7 @@ func TestApexMinSdkVersion_NativeModulesShouldBeBuiltAgainstStubs(t *testing.T)
}
func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1665,11 +1673,12 @@ func TestApexMinSdkVersion_SupportsCodeNames(t *testing.T) {
}
func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["libx"],
+ updatable: false,
}
apex_key {
@@ -1710,11 +1719,12 @@ func TestApexMinSdkVersion_DefaultsToLatest(t *testing.T) {
}
func TestPlatformUsesLatestStubsFromApexes(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["libx"],
+ updatable: false,
}
apex_key {
@@ -1757,7 +1767,7 @@ func TestPlatformUsesLatestStubsFromApexes(t *testing.T) {
}
func TestQApexesUseLatestStubsInBundledBuildsAndHWASAN(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1796,7 +1806,7 @@ func TestQApexesUseLatestStubsInBundledBuildsAndHWASAN(t *testing.T) {
}
func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -1825,41 +1835,6 @@ func TestQTargetApexUsesStaticUnwinder(t *testing.T) {
ensureListNotContains(t, cm.Properties.AndroidMkStaticLibs, "libunwind")
}
-func TestApexMinSdkVersion_ErrorIfIncompatibleStubs(t *testing.T) {
- testApexError(t, `"libz" .*: not found a version\(<=29\)`, `
- apex {
- name: "myapex",
- key: "myapex.key",
- native_shared_libs: ["libx"],
- min_sdk_version: "29",
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "libx",
- shared_libs: ["libz"],
- system_shared_libs: [],
- stl: "none",
- apex_available: [ "myapex" ],
- min_sdk_version: "29",
- }
-
- cc_library {
- name: "libz",
- system_shared_libs: [],
- stl: "none",
- stubs: {
- versions: ["30"],
- },
- }
- `)
-}
-
func TestApexMinSdkVersion_ErrorIfIncompatibleVersion(t *testing.T) {
testApexError(t, `module "mylib".*: should support min_sdk_version\(29\)`, `
apex {
@@ -1976,6 +1951,7 @@ func TestJavaStableSdkVersion(t *testing.T) {
name: "myapex",
java_libs: ["myjar"],
key: "myapex.key",
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -2157,7 +2133,7 @@ func TestApexMinSdkVersion_ErrorIfDepIsNewer_Java(t *testing.T) {
}
func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2171,7 +2147,7 @@ func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion
private_key: "testkey.pem",
}
- // mylib in myapex will link to mylib2#29
+ // mylib in myapex will link to mylib2#30
// mylib in otherapex will link to mylib2(non-stub) in otherapex as well
cc_library {
name: "mylib",
@@ -2205,7 +2181,7 @@ func TestApexMinSdkVersion_OkayEvenWhenDepIsNewer_IfItSatisfiesApexMinSdkVersion
libFlags := ld.Args["libFlags"]
ensureContains(t, libFlags, "android_arm64_armv8-a_"+to_variant+"/"+to+".so")
}
- expectLink("mylib", "shared_apex29", "mylib2", "shared_29")
+ expectLink("mylib", "shared_apex29", "mylib2", "shared_30")
expectLink("mylib", "shared_apex30", "mylib2", "shared_apex30")
}
@@ -2244,7 +2220,7 @@ func TestApexMinSdkVersion_WorksWithActiveCodenames(t *testing.T) {
config.TestProductVariables.Platform_sdk_codename = proptools.StringPtr("S")
config.TestProductVariables.Platform_version_active_codenames = []string{"S", "T"}
}
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2274,11 +2250,11 @@ func TestApexMinSdkVersion_WorksWithActiveCodenames(t *testing.T) {
// ensure libfoo is linked with "S" version of libbar stub
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared_apex10000")
libFlags := libfoo.Rule("ld").Args["libFlags"]
- ensureContains(t, libFlags, "android_arm64_armv8-a_shared_S/libbar.so")
+ ensureContains(t, libFlags, "android_arm64_armv8-a_shared_T/libbar.so")
}
func TestFilesInSubDir(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2286,6 +2262,7 @@ func TestFilesInSubDir(t *testing.T) {
binaries: ["mybin"],
prebuilts: ["myetc"],
compile_multilib: "both",
+ updatable: false,
}
apex_key {
@@ -2340,7 +2317,7 @@ func TestFilesInSubDir(t *testing.T) {
}
func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -2352,6 +2329,7 @@ func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) {
},
compile_multilib: "both",
native_bridge_supported: true,
+ updatable: false,
}
apex_key {
@@ -2398,12 +2376,13 @@ func TestFilesInSubDirWhenNativeBridgeEnabled(t *testing.T) {
}
func TestUseVendor(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib"],
use_vendor: true,
+ updatable: false,
}
apex_key {
@@ -2472,6 +2451,7 @@ func TestUseVendorNotAllowedForSystemApexes(t *testing.T) {
name: "myapex",
key: "myapex.key",
use_vendor: true,
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -2490,6 +2470,7 @@ func TestUseVendorFailsIfNotVendorAvailable(t *testing.T) {
key: "myapex.key",
native_shared_libs: ["mylib"],
use_vendor: true,
+ updatable: false,
}
apex_key {
@@ -2508,12 +2489,13 @@ func TestUseVendorFailsIfNotVendorAvailable(t *testing.T) {
}
func TestVendorApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
binaries: ["mybin"],
vendor: true,
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -2545,7 +2527,8 @@ func TestVendorApex(t *testing.T) {
var builder strings.Builder
data.Custom(&builder, name, prefix, "", data)
androidMk := builder.String()
- ensureContains(t, androidMk, `LOCAL_MODULE_PATH := /tmp/target/product/test_device/vendor/apex`)
+ installPath := path.Join(buildDir, "../target/product/test_device/vendor/apex")
+ ensureContains(t, androidMk, "LOCAL_MODULE_PATH := "+installPath)
apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex_image").Rule("apexManifestRule")
requireNativeLibs := names(apexManifestRule.Args["requireNativeLibs"])
@@ -2553,13 +2536,14 @@ func TestVendorApex(t *testing.T) {
}
func TestVendorApex_use_vndk_as_stable(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
binaries: ["mybin"],
vendor: true,
use_vndk_as_stable: true,
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -2616,11 +2600,12 @@ func TestApex_withPrebuiltFirmware(t *testing.T) {
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
prebuilts: ["myfirmware"],
+ updatable: false,
`+tc.additionalProp+`
}
apex_key {
@@ -2643,12 +2628,13 @@ func TestApex_withPrebuiltFirmware(t *testing.T) {
}
func TestAndroidMk_UseVendorRequired(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
use_vendor: true,
native_shared_libs: ["mylib"],
+ updatable: false,
}
apex_key {
@@ -2677,12 +2663,13 @@ func TestAndroidMk_UseVendorRequired(t *testing.T) {
}
func TestAndroidMk_VendorApexRequired(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
vendor: true,
native_shared_libs: ["mylib"],
+ updatable: false,
}
apex_key {
@@ -2708,12 +2695,13 @@ func TestAndroidMk_VendorApexRequired(t *testing.T) {
}
func TestAndroidMkWritesCommonProperties(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
vintf_fragments: ["fragment.xml"],
init_rc: ["init.rc"],
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -2737,11 +2725,12 @@ func TestAndroidMkWritesCommonProperties(t *testing.T) {
}
func TestStaticLinking(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib"],
+ updatable: false,
}
apex_key {
@@ -2781,13 +2770,14 @@ func TestStaticLinking(t *testing.T) {
}
func TestKeys(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex_keytest",
key: "myapex.key",
certificate: ":myapex.certificate",
native_shared_libs: ["mylib"],
file_contexts: ":myapex-file_contexts",
+ updatable: false,
}
cc_library {
@@ -2838,10 +2828,11 @@ func TestKeys(t *testing.T) {
func TestCertificate(t *testing.T) {
t.Run("if unspecified, it defaults to DefaultAppCertificate", func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -2855,11 +2846,12 @@ func TestCertificate(t *testing.T) {
}
})
t.Run("override when unspecified", func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex_keytest",
key: "myapex.key",
file_contexts: ":myapex-file_contexts",
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -2877,11 +2869,12 @@ func TestCertificate(t *testing.T) {
}
})
t.Run("if specified as :module, it respects the prop", func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
certificate: ":myapex.certificate",
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -2899,12 +2892,13 @@ func TestCertificate(t *testing.T) {
}
})
t.Run("override when specifiec as <:module>", func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex_keytest",
key: "myapex.key",
file_contexts: ":myapex-file_contexts",
certificate: ":myapex.certificate",
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -2922,11 +2916,12 @@ func TestCertificate(t *testing.T) {
}
})
t.Run("if specified as name, finds it from DefaultDevKeyDir", func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
certificate: "testkey",
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -2940,12 +2935,13 @@ func TestCertificate(t *testing.T) {
}
})
t.Run("override when specified as <name>", func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex_keytest",
key: "myapex.key",
file_contexts: ":myapex-file_contexts",
certificate: "testkey",
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -2965,11 +2961,12 @@ func TestCertificate(t *testing.T) {
}
func TestMacro(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib", "mylib2"],
+ updatable: false,
}
apex {
@@ -3092,11 +3089,12 @@ func TestMacro(t *testing.T) {
}
func TestHeaderLibsDependency(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib"],
+ updatable: false,
}
apex_key {
@@ -3235,14 +3233,15 @@ func ensureExactContents(t *testing.T, ctx *android.TestContext, moduleName, var
}
func TestVndkApexCurrent(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
- name: "myapex",
- key: "myapex.key",
+ name: "com.android.vndk.current",
+ key: "com.android.vndk.current.key",
+ updatable: false,
}
apex_key {
- name: "myapex.key",
+ name: "com.android.vndk.current.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
@@ -3257,7 +3256,7 @@ func TestVndkApexCurrent(t *testing.T) {
},
system_shared_libs: [],
stl: "none",
- apex_available: [ "myapex" ],
+ apex_available: [ "com.android.vndk.current" ],
}
cc_library {
@@ -3271,11 +3270,11 @@ func TestVndkApexCurrent(t *testing.T) {
},
system_shared_libs: [],
stl: "none",
- apex_available: [ "myapex" ],
+ apex_available: [ "com.android.vndk.current" ],
}
`+vndkLibrariesTxtFiles("current"))
- ensureExactContents(t, ctx, "myapex", "android_common_image", []string{
+ ensureExactContents(t, ctx, "com.android.vndk.current", "android_common_image", []string{
"lib/libvndk.so",
"lib/libvndksp.so",
"lib/libc++.so",
@@ -3291,14 +3290,15 @@ func TestVndkApexCurrent(t *testing.T) {
}
func TestVndkApexWithPrebuilt(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
- name: "myapex",
- key: "myapex.key",
+ name: "com.android.vndk.current",
+ key: "com.android.vndk.current.key",
+ updatable: false,
}
apex_key {
- name: "myapex.key",
+ name: "com.android.vndk.current.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
@@ -3313,7 +3313,7 @@ func TestVndkApexWithPrebuilt(t *testing.T) {
},
system_shared_libs: [],
stl: "none",
- apex_available: [ "myapex" ],
+ apex_available: [ "com.android.vndk.current" ],
}
cc_prebuilt_library_shared {
@@ -3332,15 +3332,14 @@ func TestVndkApexWithPrebuilt(t *testing.T) {
},
system_shared_libs: [],
stl: "none",
- apex_available: [ "myapex" ],
+ apex_available: [ "com.android.vndk.current" ],
}
`+vndkLibrariesTxtFiles("current"),
withFiles(map[string][]byte{
"libvndk.so": nil,
"libvndk.arm.so": nil,
}))
-
- ensureExactContents(t, ctx, "myapex", "android_common_image", []string{
+ ensureExactContents(t, ctx, "com.android.vndk.current", "android_common_image", []string{
"lib/libvndk.so",
"lib/libvndk.arm.so",
"lib64/libvndk.so",
@@ -3375,12 +3374,13 @@ func vndkLibrariesTxtFiles(vers ...string) (result string) {
}
func TestVndkApexVersion(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
- name: "myapex_v27",
+ name: "com.android.vndk.v27",
key: "myapex.key",
file_contexts: ":myapex-file_contexts",
vndk_version: "27",
+ updatable: false,
}
apex_key {
@@ -3406,7 +3406,7 @@ func TestVndkApexVersion(t *testing.T) {
srcs: ["libvndk27_arm64.so"],
},
},
- apex_available: [ "myapex_v27" ],
+ apex_available: [ "com.android.vndk.v27" ],
}
vndk_prebuilt_shared {
@@ -3435,73 +3435,27 @@ func TestVndkApexVersion(t *testing.T) {
"libvndk27_x86_64.so": nil,
}))
- ensureExactContents(t, ctx, "myapex_v27", "android_common_image", []string{
+ ensureExactContents(t, ctx, "com.android.vndk.v27", "android_common_image", []string{
"lib/libvndk27_arm.so",
"lib64/libvndk27_arm64.so",
"etc/*",
})
}
-func TestVndkApexErrorWithDuplicateVersion(t *testing.T) {
- testApexError(t, `module "myapex_v27.*" .*: vndk_version: 27 is already defined in "myapex_v27.*"`, `
- apex_vndk {
- name: "myapex_v27",
- key: "myapex.key",
- file_contexts: ":myapex-file_contexts",
- vndk_version: "27",
- }
- apex_vndk {
- name: "myapex_v27_other",
- key: "myapex.key",
- file_contexts: ":myapex-file_contexts",
- vndk_version: "27",
- }
-
- apex_key {
- name: "myapex.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "libvndk",
- srcs: ["mylib.cpp"],
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- system_shared_libs: [],
- stl: "none",
- }
-
- vndk_prebuilt_shared {
- name: "libvndk",
- version: "27",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- srcs: ["libvndk.so"],
- }
- `, withFiles(map[string][]byte{
- "libvndk.so": nil,
- }))
-}
-
func TestVndkApexNameRule(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
- name: "myapex",
+ name: "com.android.vndk.current",
key: "myapex.key",
file_contexts: ":myapex-file_contexts",
+ updatable: false,
}
apex_vndk {
- name: "myapex_v28",
+ name: "com.android.vndk.v28",
key: "myapex.key",
file_contexts: ":myapex-file_contexts",
vndk_version: "28",
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -3517,20 +3471,21 @@ func TestVndkApexNameRule(t *testing.T) {
}
}
- assertApexName("com.android.vndk.vVER", "myapex")
- assertApexName("com.android.vndk.v28", "myapex_v28")
+ assertApexName("com.android.vndk.vVER", "com.android.vndk.current")
+ assertApexName("com.android.vndk.v28", "com.android.vndk.v28")
}
func TestVndkApexSkipsNativeBridgeSupportedModules(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
- name: "myapex",
- key: "myapex.key",
+ name: "com.android.vndk.current",
+ key: "com.android.vndk.current.key",
file_contexts: ":myapex-file_contexts",
+ updatable: false,
}
apex_key {
- name: "myapex.key",
+ name: "com.android.vndk.current.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
@@ -3547,11 +3502,12 @@ func TestVndkApexSkipsNativeBridgeSupportedModules(t *testing.T) {
},
system_shared_libs: [],
stl: "none",
- apex_available: [ "myapex" ],
+ apex_available: [ "com.android.vndk.current" ],
}
- `+vndkLibrariesTxtFiles("current"), withNativeBridgeEnabled)
+ `+vndkLibrariesTxtFiles("current"),
+ withNativeBridgeEnabled)
- ensureExactContents(t, ctx, "myapex", "android_common_image", []string{
+ ensureExactContents(t, ctx, "com.android.vndk.current", "android_common_image", []string{
"lib/libvndk.so",
"lib64/libvndk.so",
"lib/libc++.so",
@@ -3561,16 +3517,16 @@ func TestVndkApexSkipsNativeBridgeSupportedModules(t *testing.T) {
}
func TestVndkApexDoesntSupportNativeBridgeSupported(t *testing.T) {
- testApexError(t, `module "myapex" .*: native_bridge_supported: .* doesn't support native bridge binary`, `
+ testApexError(t, `module "com.android.vndk.current" .*: native_bridge_supported: .* doesn't support native bridge binary`, `
apex_vndk {
- name: "myapex",
- key: "myapex.key",
+ name: "com.android.vndk.current",
+ key: "com.android.vndk.current.key",
file_contexts: ":myapex-file_contexts",
native_bridge_supported: true,
}
apex_key {
- name: "myapex.key",
+ name: "com.android.vndk.current.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
@@ -3592,12 +3548,13 @@ func TestVndkApexDoesntSupportNativeBridgeSupported(t *testing.T) {
}
func TestVndkApexWithBinder32(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
- name: "myapex_v27",
+ name: "com.android.vndk.v27",
key: "myapex.key",
file_contexts: ":myapex-file_contexts",
vndk_version: "27",
+ updatable: false,
}
apex_key {
@@ -3637,7 +3594,7 @@ func TestVndkApexWithBinder32(t *testing.T) {
srcs: ["libvndk27binder32.so"],
}
},
- apex_available: [ "myapex_v27" ],
+ apex_available: [ "com.android.vndk.v27" ],
}
`+vndkLibrariesTxtFiles("27"),
withFiles(map[string][]byte{
@@ -3653,22 +3610,23 @@ func TestVndkApexWithBinder32(t *testing.T) {
}),
)
- ensureExactContents(t, ctx, "myapex_v27", "android_common_image", []string{
+ ensureExactContents(t, ctx, "com.android.vndk.v27", "android_common_image", []string{
"lib/libvndk27binder32.so",
"etc/*",
})
}
func TestVndkApexShouldNotProvideNativeLibs(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
- name: "myapex",
- key: "myapex.key",
+ name: "com.android.vndk.current",
+ key: "com.android.vndk.current.key",
file_contexts: ":myapex-file_contexts",
+ updatable: false,
}
apex_key {
- name: "myapex.key",
+ name: "com.android.vndk.current.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
@@ -3689,19 +3647,20 @@ func TestVndkApexShouldNotProvideNativeLibs(t *testing.T) {
"libz.map.txt": nil,
}))
- apexManifestRule := ctx.ModuleForTests("myapex", "android_common_image").Rule("apexManifestRule")
+ apexManifestRule := ctx.ModuleForTests("com.android.vndk.current", "android_common_image").Rule("apexManifestRule")
provideNativeLibs := names(apexManifestRule.Args["provideNativeLibs"])
ensureListEmpty(t, provideNativeLibs)
}
func TestDependenciesInApexManifest(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex_nodep",
key: "myapex.key",
native_shared_libs: ["lib_nodep"],
compile_multilib: "both",
file_contexts: ":myapex-file_contexts",
+ updatable: false,
}
apex {
@@ -3710,6 +3669,7 @@ func TestDependenciesInApexManifest(t *testing.T) {
native_shared_libs: ["lib_dep"],
compile_multilib: "both",
file_contexts: ":myapex-file_contexts",
+ updatable: false,
}
apex {
@@ -3718,6 +3678,7 @@ func TestDependenciesInApexManifest(t *testing.T) {
native_shared_libs: ["libfoo"],
compile_multilib: "both",
file_contexts: ":myapex-file_contexts",
+ updatable: false,
}
apex {
@@ -3726,6 +3687,7 @@ func TestDependenciesInApexManifest(t *testing.T) {
native_shared_libs: ["lib_dep", "libfoo"],
compile_multilib: "both",
file_contexts: ":myapex-file_contexts",
+ updatable: false,
}
apex_key {
@@ -3799,12 +3761,13 @@ func TestDependenciesInApexManifest(t *testing.T) {
}
func TestApexName(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
apex_name: "com.android.myapex",
native_shared_libs: ["mylib"],
+ updatable: false,
}
apex_key {
@@ -3843,11 +3806,12 @@ func TestApexName(t *testing.T) {
}
func TestNonTestApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib_common"],
+ updatable: false,
}
apex_key {
@@ -3895,11 +3859,12 @@ func TestNonTestApex(t *testing.T) {
}
func TestTestApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_test {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib_common_test"],
+ updatable: false,
}
apex_key {
@@ -3943,10 +3908,11 @@ func TestTestApex(t *testing.T) {
}
func TestApexWithTarget(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
+ updatable: false,
multilib: {
first: {
native_shared_libs: ["mylib_common"],
@@ -4033,10 +3999,11 @@ func TestApexWithTarget(t *testing.T) {
}
func TestApexWithArch(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
+ updatable: false,
arch: {
arm64: {
native_shared_libs: ["mylib.arm64"],
@@ -4091,11 +4058,12 @@ func TestApexWithArch(t *testing.T) {
}
func TestApexWithShBinary(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
binaries: ["myscript"],
+ updatable: false,
}
apex_key {
@@ -4131,10 +4099,11 @@ func TestApexInVariousPartition(t *testing.T) {
}
for _, tc := range testcases {
t.Run(tc.propName+":"+tc.parition, func(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
+ updatable: false,
`+tc.propName+`
}
@@ -4163,10 +4132,11 @@ func TestApexInVariousPartition(t *testing.T) {
}
func TestFileContexts_FindInDefaultLocationIfNotSet(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
+ updatable: false,
}
apex_key {
@@ -4186,6 +4156,7 @@ func TestFileContexts_ShouldBeUnderSystemSepolicyForSystemApexes(t *testing.T) {
name: "myapex",
key: "myapex.key",
file_contexts: "my_own_file_contexts",
+ updatable: false,
}
apex_key {
@@ -4205,6 +4176,7 @@ func TestFileContexts_ProductSpecificApexes(t *testing.T) {
key: "myapex.key",
product_specific: true,
file_contexts: "product_specific_file_contexts",
+ updatable: false,
}
apex_key {
@@ -4214,12 +4186,13 @@ func TestFileContexts_ProductSpecificApexes(t *testing.T) {
}
`)
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
product_specific: true,
file_contexts: "product_specific_file_contexts",
+ updatable: false,
}
apex_key {
@@ -4236,12 +4209,13 @@ func TestFileContexts_ProductSpecificApexes(t *testing.T) {
}
func TestFileContexts_SetViaFileGroup(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
product_specific: true,
file_contexts: ":my-file-contexts",
+ updatable: false,
}
apex_key {
@@ -4263,7 +4237,7 @@ func TestFileContexts_SetViaFileGroup(t *testing.T) {
}
func TestApexKeyFromOtherModule(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_key {
name: "myapex.key",
public_key: ":my.avbpubkey",
@@ -4296,7 +4270,7 @@ func TestApexKeyFromOtherModule(t *testing.T) {
}
func TestPrebuilt(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
prebuilt_apex {
name: "myapex",
arch: {
@@ -4319,7 +4293,7 @@ func TestPrebuilt(t *testing.T) {
}
func TestPrebuiltFilenameOverride(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
prebuilt_apex {
name: "myapex",
src: "myapex-arm.apex",
@@ -4336,7 +4310,7 @@ func TestPrebuiltFilenameOverride(t *testing.T) {
}
func TestPrebuiltOverrides(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
prebuilt_apex {
name: "myapex.prebuilt",
src: "myapex-arm.apex",
@@ -4366,14 +4340,15 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) {
// Make sure the import has been given the correct path to the dex jar.
p := ctx.ModuleForTests(name, "android_common_myapex").Module().(java.UsesLibraryDependency)
dexJarBuildPath := p.DexJarBuildPath()
- if expected, actual := ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar", android.NormalizePathForTesting(dexJarBuildPath); actual != expected {
+ stem := android.RemoveOptionalPrebuiltPrefix(name)
+ if expected, actual := ".intermediates/myapex.deapexer/android_common/deapexer/javalib/"+stem+".jar", android.NormalizePathForTesting(dexJarBuildPath); actual != expected {
t.Errorf("Incorrect DexJarBuildPath value '%s', expected '%s'", actual, expected)
}
}
- ensureNoSourceVariant := func(t *testing.T, ctx *android.TestContext) {
+ ensureNoSourceVariant := func(t *testing.T, ctx *android.TestContext, name string) {
// 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) {
+ if expected, actual := []string{"android_common"}, ctx.ModuleVariantsForTests(name); !reflect.DeepEqual(expected, actual) {
t.Errorf("invalid set of variants for %q: expected %q, found %q", "libfoo", expected, actual)
}
}
@@ -4390,19 +4365,42 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) {
src: "myapex-arm.apex",
},
},
- exported_java_libs: ["libfoo"],
+ exported_java_libs: ["libfoo", "libbar"],
}
java_import {
name: "libfoo",
jars: ["libfoo.jar"],
}
+
+ java_sdk_library_import {
+ name: "libbar",
+ public: {
+ jars: ["libbar.jar"],
+ },
+ }
`
// Make sure that dexpreopt can access dex implementation files from the prebuilt.
ctx := testDexpreoptWithApexes(t, bp, "", transform)
+ // Make sure that the deapexer has the correct input APEX.
+ deapexer := ctx.ModuleForTests("myapex.deapexer", "android_common")
+ rule := deapexer.Rule("deapexer")
+ if expected, actual := []string{"myapex-arm64.apex"}, android.NormalizePathsForTesting(rule.Implicits); !reflect.DeepEqual(expected, actual) {
+ t.Errorf("expected: %q, found: %q", expected, actual)
+ }
+
+ // Make sure that the prebuilt_apex has the correct input APEX.
+ prebuiltApex := ctx.ModuleForTests("myapex", "android_common")
+ rule = prebuiltApex.Rule("android/soong/android.Cp")
+ if expected, actual := "myapex-arm64.apex", android.NormalizePathForTesting(rule.Input); !reflect.DeepEqual(expected, actual) {
+ t.Errorf("expected: %q, found: %q", expected, actual)
+ }
+
checkDexJarBuildPath(t, ctx, "libfoo")
+
+ checkDexJarBuildPath(t, ctx, "libbar")
})
t.Run("prebuilt with source preferred", func(t *testing.T) {
@@ -4418,7 +4416,7 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) {
src: "myapex-arm.apex",
},
},
- exported_java_libs: ["libfoo"],
+ exported_java_libs: ["libfoo", "libbar"],
}
java_import {
@@ -4429,13 +4427,29 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) {
java_library {
name: "libfoo",
}
+
+ java_sdk_library_import {
+ name: "libbar",
+ public: {
+ jars: ["libbar.jar"],
+ },
+ }
+
+ java_sdk_library {
+ name: "libbar",
+ srcs: ["foo/bar/MyClass.java"],
+ unsafe_ignore_missing_latest_api: true,
+ }
`
// Make sure that dexpreopt can access dex implementation files from the prebuilt.
ctx := testDexpreoptWithApexes(t, bp, "", transform)
checkDexJarBuildPath(t, ctx, "prebuilt_libfoo")
- ensureNoSourceVariant(t, ctx)
+ ensureNoSourceVariant(t, ctx, "libfoo")
+
+ checkDexJarBuildPath(t, ctx, "prebuilt_libbar")
+ ensureNoSourceVariant(t, ctx, "libbar")
})
t.Run("prebuilt preferred with source", func(t *testing.T) {
@@ -4450,7 +4464,7 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) {
src: "myapex-arm.apex",
},
},
- exported_java_libs: ["libfoo"],
+ exported_java_libs: ["libfoo", "libbar"],
}
java_import {
@@ -4462,26 +4476,45 @@ func TestPrebuiltExportDexImplementationJars(t *testing.T) {
java_library {
name: "libfoo",
}
+
+ java_sdk_library_import {
+ name: "libbar",
+ prefer: true,
+ public: {
+ jars: ["libbar.jar"],
+ },
+ }
+
+ java_sdk_library {
+ name: "libbar",
+ srcs: ["foo/bar/MyClass.java"],
+ unsafe_ignore_missing_latest_api: true,
+ }
`
// Make sure that dexpreopt can access dex implementation files from the prebuilt.
ctx := testDexpreoptWithApexes(t, bp, "", transform)
checkDexJarBuildPath(t, ctx, "prebuilt_libfoo")
- ensureNoSourceVariant(t, ctx)
+ ensureNoSourceVariant(t, ctx, "libfoo")
+
+ checkDexJarBuildPath(t, ctx, "prebuilt_libbar")
+ ensureNoSourceVariant(t, ctx, "libbar")
})
}
func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
transform := func(config *dexpreopt.GlobalConfig) {
- config.BootJars = android.CreateTestConfiguredJarList([]string{"myapex:libfoo"})
+ config.BootJars = android.CreateTestConfiguredJarList([]string{"myapex:libfoo", "myapex:libbar"})
}
- checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, bootDexJarPath string) {
+ checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, stem string, bootDexJarPath string) {
+ t.Helper()
s := ctx.SingletonForTests("dex_bootjars")
foundLibfooJar := false
+ base := stem + ".jar"
for _, output := range s.AllOutputs() {
- if strings.HasSuffix(output, "/libfoo.jar") {
+ if filepath.Base(output) == base {
foundLibfooJar = true
buildRule := s.Output(output)
actual := android.NormalizePathForTesting(buildRule.Input)
@@ -4496,6 +4529,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
}
checkHiddenAPIIndexInputs := func(t *testing.T, ctx *android.TestContext, expectedInputs string) {
+ t.Helper()
hiddenAPIIndex := ctx.SingletonForTests("hiddenapi_index")
indexRule := hiddenAPIIndex.Rule("singleton-merged-hiddenapi-index")
java.CheckHiddenAPIRuleInputs(t, expectedInputs, indexRule)
@@ -4513,7 +4547,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
src: "myapex-arm.apex",
},
},
- exported_java_libs: ["libfoo"],
+ exported_java_libs: ["libfoo", "libbar"],
}
java_import {
@@ -4521,13 +4555,23 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
jars: ["libfoo.jar"],
apex_available: ["myapex"],
}
+
+ java_sdk_library_import {
+ name: "libbar",
+ public: {
+ jars: ["libbar.jar"],
+ },
+ apex_available: ["myapex"],
+ }
`
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- checkBootDexJarPath(t, ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libfoo", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libbar", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
+.intermediates/libbar/android_common_myapex/hiddenapi/index.csv
.intermediates/libfoo/android_common_myapex/hiddenapi/index.csv
`)
})
@@ -4544,7 +4588,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
src: "myapex-arm.apex",
},
},
- exported_java_libs: ["libfoo"],
+ exported_java_libs: ["libfoo", "libbar"],
}
java_import {
@@ -4558,6 +4602,21 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
srcs: ["foo/bar/MyClass.java"],
apex_available: ["myapex"],
}
+
+ java_sdk_library_import {
+ name: "libbar",
+ public: {
+ jars: ["libbar.jar"],
+ },
+ apex_available: ["myapex"],
+ }
+
+ java_sdk_library {
+ name: "libbar",
+ srcs: ["foo/bar/MyClass.java"],
+ unsafe_ignore_missing_latest_api: true,
+ apex_available: ["myapex"],
+ }
`
// In this test the source (java_library) libfoo is active since the
@@ -4580,7 +4639,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
src: "myapex-arm.apex",
},
},
- exported_java_libs: ["libfoo"],
+ exported_java_libs: ["libfoo", "libbar"],
}
java_import {
@@ -4595,13 +4654,31 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
srcs: ["foo/bar/MyClass.java"],
apex_available: ["myapex"],
}
+
+ java_sdk_library_import {
+ name: "libbar",
+ prefer: true,
+ public: {
+ jars: ["libbar.jar"],
+ },
+ apex_available: ["myapex"],
+ }
+
+ java_sdk_library {
+ name: "libbar",
+ srcs: ["foo/bar/MyClass.java"],
+ unsafe_ignore_missing_latest_api: true,
+ apex_available: ["myapex"],
+ }
`
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- checkBootDexJarPath(t, ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libfoo", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libbar", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
+.intermediates/prebuilt_libbar/android_common_myapex/hiddenapi/index.csv
.intermediates/prebuilt_libfoo/android_common_myapex/hiddenapi/index.csv
`)
})
@@ -4611,7 +4688,8 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
apex {
name: "myapex",
key: "myapex.key",
- java_libs: ["libfoo"],
+ java_libs: ["libfoo", "libbar"],
+ updatable: false,
}
apex_key {
@@ -4630,7 +4708,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
src: "myapex-arm.apex",
},
},
- exported_java_libs: ["libfoo"],
+ exported_java_libs: ["libfoo", "libbar"],
}
java_import {
@@ -4644,13 +4722,30 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
srcs: ["foo/bar/MyClass.java"],
apex_available: ["myapex"],
}
+
+ java_sdk_library_import {
+ name: "libbar",
+ public: {
+ jars: ["libbar.jar"],
+ },
+ apex_available: ["myapex"],
+ }
+
+ java_sdk_library {
+ name: "libbar",
+ srcs: ["foo/bar/MyClass.java"],
+ unsafe_ignore_missing_latest_api: true,
+ apex_available: ["myapex"],
+ }
`
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- checkBootDexJarPath(t, ctx, ".intermediates/libfoo/android_common_apex10000/hiddenapi/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libfoo", ".intermediates/libfoo/android_common_apex10000/hiddenapi/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libbar", ".intermediates/libbar/android_common_myapex/hiddenapi/libbar.jar")
// Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
+.intermediates/libbar/android_common_myapex/hiddenapi/index.csv
.intermediates/libfoo/android_common_apex10000/hiddenapi/index.csv
`)
})
@@ -4680,7 +4775,7 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
src: "myapex-arm.apex",
},
},
- exported_java_libs: ["libfoo"],
+ exported_java_libs: ["libfoo", "libbar"],
}
java_import {
@@ -4695,23 +4790,42 @@ func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
srcs: ["foo/bar/MyClass.java"],
apex_available: ["myapex"],
}
+
+ java_sdk_library_import {
+ name: "libbar",
+ prefer: true,
+ public: {
+ jars: ["libbar.jar"],
+ },
+ apex_available: ["myapex"],
+ }
+
+ java_sdk_library {
+ name: "libbar",
+ srcs: ["foo/bar/MyClass.java"],
+ unsafe_ignore_missing_latest_api: true,
+ apex_available: ["myapex"],
+ }
`
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- checkBootDexJarPath(t, ctx, ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libfoo", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libbar", ".intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Make sure that the dex file from the prebuilt_apex contributes to the hiddenapi index file.
checkHiddenAPIIndexInputs(t, ctx, `
+.intermediates/prebuilt_libbar/android_common_prebuilt_myapex/hiddenapi/index.csv
.intermediates/prebuilt_libfoo/android_common_prebuilt_myapex/hiddenapi/index.csv
`)
})
}
func TestApexWithTests(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_test {
name: "myapex",
key: "myapex.key",
+ updatable: false,
tests: [
"mytest",
"mytests",
@@ -4819,10 +4933,11 @@ func TestApexWithTests(t *testing.T) {
}
func TestInstallExtraFlattenedApexes(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -4888,11 +5003,12 @@ func TestErrorsIfDepsAreNotEnabled(t *testing.T) {
}
func TestApexWithJavaImport(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
java_libs: ["myjavaimport"],
+ updatable: false,
}
apex_key {
@@ -4916,7 +5032,7 @@ func TestApexWithJavaImport(t *testing.T) {
}
func TestApexWithApps(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -4924,6 +5040,7 @@ func TestApexWithApps(t *testing.T) {
"AppFoo",
"AppFooPriv",
],
+ updatable: false,
}
apex_key {
@@ -4994,7 +5111,7 @@ func TestApexWithApps(t *testing.T) {
}
func TestApexWithAppImports(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5002,6 +5119,7 @@ func TestApexWithAppImports(t *testing.T) {
"AppFooPrebuilt",
"AppFooPrivPrebuilt",
],
+ updatable: false,
}
apex_key {
@@ -5042,13 +5160,14 @@ func TestApexWithAppImports(t *testing.T) {
}
func TestApexWithAppImportsPrefer(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
apps: [
"AppFoo",
],
+ updatable: false,
}
apex_key {
@@ -5083,13 +5202,14 @@ func TestApexWithAppImportsPrefer(t *testing.T) {
}
func TestApexWithTestHelperApp(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
apps: [
"TesterHelpAppFoo",
],
+ updatable: false,
}
apex_key {
@@ -5120,6 +5240,7 @@ func TestApexPropertiesShouldBeDefaultable(t *testing.T) {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["libfoo"],
+ updatable: false,
}
apex_key {
@@ -5132,6 +5253,7 @@ func TestApexPropertiesShouldBeDefaultable(t *testing.T) {
name: "otherapex",
key: "myapex.key",
native_shared_libs: ["libfoo"],
+ updatable: false,
}
cc_defaults {
@@ -5154,6 +5276,7 @@ func TestApexAvailable_DirectDep(t *testing.T) {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["libfoo"],
+ updatable: false,
}
apex_key {
@@ -5166,6 +5289,7 @@ func TestApexAvailable_DirectDep(t *testing.T) {
name: "otherapex",
key: "otherapex.key",
native_shared_libs: ["libfoo"],
+ updatable: false,
}
apex_key {
@@ -5184,7 +5308,7 @@ func TestApexAvailable_DirectDep(t *testing.T) {
func TestApexAvailable_IndirectDep(t *testing.T) {
// libbbaz is an indirect dep
- testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'. Dependency path:
+ testApexError(t, `requires "libbaz" that doesn't list the APEX under 'apex_available'.\n\nDependency path:
.*via tag apex\.dependencyTag.*name:sharedLib.*
.*-> libfoo.*link:shared.*
.*via tag cc\.libraryDependencyTag.*Kind:sharedLibraryDependency.*
@@ -5195,6 +5319,7 @@ func TestApexAvailable_IndirectDep(t *testing.T) {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["libfoo"],
+ updatable: false,
}
apex_key {
@@ -5232,6 +5357,7 @@ func TestApexAvailable_InvalidApexName(t *testing.T) {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["libfoo"],
+ updatable: false,
}
apex_key {
@@ -5252,6 +5378,7 @@ func TestApexAvailable_InvalidApexName(t *testing.T) {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["libfoo", "libbar"],
+ updatable: false,
}
apex_key {
@@ -5286,11 +5413,12 @@ func TestApexAvailable_InvalidApexName(t *testing.T) {
}
func TestApexAvailable_CheckForPlatform(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["libbar", "libbaz"],
+ updatable: false,
}
apex_key {
@@ -5348,11 +5476,12 @@ func TestApexAvailable_CheckForPlatform(t *testing.T) {
}
func TestApexAvailable_CreatedForApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["libfoo"],
+ updatable: false,
}
apex_key {
@@ -5382,12 +5511,13 @@ func TestApexAvailable_CreatedForApex(t *testing.T) {
}
func TestOverrideApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
apps: ["app"],
overrides: ["oldapex"],
+ updatable: false,
}
override_apex {
@@ -5465,7 +5595,7 @@ func TestOverrideApex(t *testing.T) {
}
func TestLegacyAndroid10Support(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
@@ -5525,11 +5655,12 @@ var filesForSdkLibrary = map[string][]byte{
}
func TestJavaSDKLibrary(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
java_libs: ["foo"],
+ updatable: false,
}
apex_key {
@@ -5562,11 +5693,12 @@ func TestJavaSDKLibrary(t *testing.T) {
}
func TestJavaSDKLibrary_WithinApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
java_libs: ["foo", "bar"],
+ updatable: false,
}
apex_key {
@@ -5614,11 +5746,12 @@ func TestJavaSDKLibrary_WithinApex(t *testing.T) {
}
func TestJavaSDKLibrary_CrossBoundary(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
java_libs: ["foo"],
+ updatable: false,
}
apex_key {
@@ -5664,7 +5797,7 @@ func TestJavaSDKLibrary_CrossBoundary(t *testing.T) {
}
func TestJavaSDKLibrary_ImportPreferred(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
prebuilt_apis {
name: "sdk",
api_dirs: ["100"],
@@ -5681,6 +5814,7 @@ func TestJavaSDKLibrary_ImportPreferred(t *testing.T) {
name: "myapex",
key: "myapex.key",
java_libs: ["foo", "bar"],
+ updatable: false,
}
apex_key {
@@ -5758,6 +5892,7 @@ func TestJavaSDKLibrary_ImportOnly(t *testing.T) {
name: "myapex",
key: "myapex.key",
java_libs: ["foo"],
+ updatable: false,
}
apex_key {
@@ -5779,12 +5914,13 @@ func TestJavaSDKLibrary_ImportOnly(t *testing.T) {
}
func TestCompatConfig(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
prebuilts: ["myjar-platform-compat-config"],
java_libs: ["myjar"],
+ updatable: false,
}
apex_key {
@@ -5818,6 +5954,7 @@ func TestRejectNonInstallableJavaLibrary(t *testing.T) {
name: "myapex",
key: "myapex.key",
java_libs: ["myjar"],
+ updatable: false,
}
apex_key {
@@ -5838,11 +5975,12 @@ func TestRejectNonInstallableJavaLibrary(t *testing.T) {
}
func TestCarryRequiredModuleNames(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib"],
+ updatable: false,
}
apex_key {
@@ -5882,6 +6020,7 @@ func TestSymlinksFromApexToSystem(t *testing.T) {
key: "myapex.key",
native_shared_libs: ["mylib"],
java_libs: ["myjar"],
+ updatable: false,
}
apex {
@@ -5980,7 +6119,7 @@ func TestSymlinksFromApexToSystem(t *testing.T) {
// For unbundled build, symlink shouldn't exist regardless of whether an APEX
// is updatable or not
- ctx, _ := testApex(t, bp, withUnbundledBuild)
+ ctx := testApex(t, bp, withUnbundledBuild)
files := getFiles(t, ctx, "myapex", "android_common_myapex_image")
ensureRealfileExists(t, files, "javalib/myjar.jar")
ensureRealfileExists(t, files, "lib64/mylib.so")
@@ -5992,7 +6131,7 @@ func TestSymlinksFromApexToSystem(t *testing.T) {
ensureRealfileExists(t, files, "lib64/myotherlib.so")
// For bundled build, symlink to the system for the non-updatable APEXes only
- ctx, _ = testApex(t, bp)
+ ctx = testApex(t, bp)
files = getFiles(t, ctx, "myapex", "android_common_myapex_image")
ensureRealfileExists(t, files, "javalib/myjar.jar")
ensureRealfileExists(t, files, "lib64/mylib.so")
@@ -6005,11 +6144,12 @@ func TestSymlinksFromApexToSystem(t *testing.T) {
}
func TestSymlinksFromApexToSystemRequiredModuleNames(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib"],
+ updatable: false,
}
apex_key {
@@ -6056,11 +6196,12 @@ func TestSymlinksFromApexToSystemRequiredModuleNames(t *testing.T) {
}
func TestApexWithJniLibs(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
jni_libs: ["mylib"],
+ updatable: false,
}
apex_key {
@@ -6097,10 +6238,11 @@ func TestApexWithJniLibs(t *testing.T) {
}
func TestApexMutatorsDontRunIfDisabled(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -6118,11 +6260,12 @@ func TestApexMutatorsDontRunIfDisabled(t *testing.T) {
}
func TestAppBundle(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
apps: ["AppFoo"],
+ updatable: false,
}
apex_key {
@@ -6148,11 +6291,12 @@ func TestAppBundle(t *testing.T) {
}
func TestAppSetBundle(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
apps: ["AppSet"],
+ updatable: false,
}
apex_key {
@@ -6180,7 +6324,7 @@ func TestAppSetBundle(t *testing.T) {
}
func TestAppSetBundlePrebuilt(t *testing.T) {
- ctx, _ := testApex(t, "", func(fs map[string][]byte, config android.Config) {
+ ctx := testApex(t, "", func(fs map[string][]byte, config android.Config) {
bp := `
apex_set {
name: "myapex",
@@ -6259,6 +6403,7 @@ func testNoUpdatableJarsInBootImage(t *testing.T, errmsg string, transformDexpre
name: "some-non-updatable-apex",
key: "some-non-updatable-apex.key",
java_libs: ["some-non-updatable-apex-lib"],
+ updatable: false,
}
apex_key {
@@ -6319,6 +6464,9 @@ func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, transformDexpreopt
}
cc.GatherRequiredFilesForTest(fs)
+ for k, v := range filesForSdkLibrary {
+ fs[k] = v
+ }
config := android.TestArchConfig(buildDir, nil, bp, fs)
ctx := android.NewTestArchContext(config)
@@ -6327,6 +6475,7 @@ func testDexpreoptWithApexes(t *testing.T, bp, errmsg string, transformDexpreopt
ctx.RegisterModuleType("prebuilt_apex", PrebuiltFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+ ctx.PreArchMutators(android.RegisterComponentsMutator)
android.RegisterPrebuiltMutators(ctx)
cc.RegisterRequiredBuildComponentsForTest(ctx)
java.RegisterRequiredBuildComponentsForTest(ctx)
@@ -6378,6 +6527,21 @@ func TestUpdatable_should_set_min_sdk_version(t *testing.T) {
`)
}
+func TestUpdatableDefault_should_set_min_sdk_version(t *testing.T) {
+ testApexError(t, `"myapex" .*: updatable: updatable APEXes should set min_sdk_version`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ `)
+}
+
func TestNoUpdatableJarsInBootImage(t *testing.T) {
var err string
var transform func(*dexpreopt.GlobalConfig)
@@ -6592,6 +6756,7 @@ func TestApexPermittedPackagesRules(t *testing.T) {
name: "myapex",
key: "myapex.key",
java_libs: ["bcp_lib1", "nonbcp_lib2"],
+ updatable: false,
}`,
bootJars: []string{"bcp_lib1"},
modulesPackages: map[string][]string{
@@ -6624,6 +6789,7 @@ func TestApexPermittedPackagesRules(t *testing.T) {
name: "myapex",
key: "myapex.key",
java_libs: ["bcp_lib1", "bcp_lib2"],
+ updatable: false,
}
`,
bootJars: []string{"bcp_lib1", "bcp_lib2"},
@@ -6643,11 +6809,12 @@ func TestApexPermittedPackagesRules(t *testing.T) {
}
func TestTestFor(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib", "myprivlib"],
+ updatable: false,
}
apex_key {
@@ -6728,7 +6895,7 @@ func intPtr(i int) *int {
}
func TestApexSet(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_set {
name: "myapex",
set: "myapex.apks",
@@ -6772,6 +6939,7 @@ func TestNoStaticLinkingToStubsLib(t *testing.T) {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib"],
+ updatable: false,
}
apex_key {
@@ -6803,10 +6971,11 @@ func TestNoStaticLinkingToStubsLib(t *testing.T) {
}
func TestApexKeysTxt(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
+ updatable: false,
}
apex_key {
@@ -6843,12 +7012,13 @@ func TestApexKeysTxt(t *testing.T) {
}
func TestAllowedFiles(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
apps: ["app"],
allowed_files: "allowed.txt",
+ updatable: false,
}
apex_key {
@@ -6898,11 +7068,12 @@ func TestAllowedFiles(t *testing.T) {
}
func TestNonPreferredPrebuiltDependency(t *testing.T) {
- _, _ = testApex(t, `
+ testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib"],
+ updatable: false,
}
apex_key {
@@ -6933,11 +7104,12 @@ func TestNonPreferredPrebuiltDependency(t *testing.T) {
}
func TestCompressedApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
compressible: true,
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -6967,11 +7139,12 @@ func TestCompressedApex(t *testing.T) {
}
func TestPreferredPrebuiltSharedLibDep(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib"],
+ updatable: false,
}
apex_key {
@@ -7018,11 +7191,12 @@ func TestPreferredPrebuiltSharedLibDep(t *testing.T) {
}
func TestExcludeDependency(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib"],
+ updatable: false,
}
apex_key {
@@ -7072,6 +7246,7 @@ func TestPrebuiltStubLibDep(t *testing.T) {
name: "myapex",
key: "myapex.key",
native_shared_libs: ["mylib"],
+ updatable: false,
}
apex_key {
name: "myapex.key",
@@ -7090,6 +7265,7 @@ func TestPrebuiltStubLibDep(t *testing.T) {
enabled: %s,
key: "myapex.key",
native_shared_libs: ["stublib"],
+ updatable: false,
}
`
@@ -7159,7 +7335,7 @@ func TestPrebuiltStubLibDep(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
for _, otherApexEnabled := range test.otherApexEnabled {
t.Run("otherapex_enabled_"+otherApexEnabled, func(t *testing.T) {
- ctx, _ := testApex(t, fmt.Sprintf(bpBase, otherApexEnabled)+test.stublibBp)
+ ctx := testApex(t, fmt.Sprintf(bpBase, otherApexEnabled)+test.stublibBp)
type modAndMkEntries struct {
mod *cc.Module
diff --git a/apex/boot_image_test.go b/apex/boot_image_test.go
index 27a15624d..2e6ed824e 100644
--- a/apex/boot_image_test.go
+++ b/apex/boot_image_test.go
@@ -28,7 +28,7 @@ import (
// modules from the ART apex.
func TestBootImages(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
java_sdk_library {
name: "foo",
srcs: ["b.java"],
@@ -48,6 +48,7 @@ func TestBootImages(t *testing.T) {
"baz",
"quuz",
],
+ updatable: false,
}
apex_key {
@@ -180,13 +181,14 @@ func withFrameworkBootImageJars(bootJars ...string) func(fs map[string][]byte, c
}
func TestBootImageInApex(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex {
name: "myapex",
key: "myapex.key",
boot_images: [
"mybootimage",
],
+ updatable: false,
}
apex_key {
diff --git a/apex/deapexer.go b/apex/deapexer.go
index 8f4a28569..46ce41f4d 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -65,7 +65,7 @@ func privateDeapexerFactory() android.Module {
&module.properties,
&module.apexFileProperties,
)
- android.InitSingleSourcePrebuiltModule(module, &module.apexFileProperties, "Source")
+ android.InitPrebuiltModuleWithSrcSupplier(module, module.apexFileProperties.prebuiltApexSelector, "src")
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
return module
}
@@ -78,16 +78,6 @@ func (p *Deapexer) Name() string {
return p.prebuilt.Name(p.ModuleBase.Name())
}
-func deapexerSelectSourceMutator(ctx android.BottomUpMutatorContext) {
- p, ok := ctx.Module().(*Deapexer)
- if !ok {
- return
- }
- if err := p.apexFileProperties.selectSource(ctx); err != nil {
- ctx.ModuleErrorf("%s", err)
- }
-}
-
func (p *Deapexer) DepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies from the java modules to which this exports files from the `.apex` file onto
// this module so that they can access the `DeapexerInfo` object that this provides.
diff --git a/apex/key.go b/apex/key.go
index 752888da2..8b33b593f 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -27,8 +27,12 @@ import (
var String = proptools.String
func init() {
- android.RegisterModuleType("apex_key", ApexKeyFactory)
- android.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
+ registerApexKeyBuildComponents(android.InitRegistrationContext)
+}
+
+func registerApexKeyBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("apex_key", ApexKeyFactory)
+ ctx.RegisterSingletonType("apex_keys_text", apexKeysTextFactory)
}
type apexKey struct {
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 6292da648..460e55930 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -108,8 +108,10 @@ type Prebuilt struct {
type ApexFileProperties struct {
// the path to the prebuilt .apex file to import.
- Source string `blueprint:"mutated"`
-
+ //
+ // This cannot be marked as `android:"arch_variant"` because the `prebuilt_apex` is only mutated
+ // for android_common. That is so that it will have the same arch variant as, and so be compatible
+ // with, the source `apex` module type that it replaces.
Src *string
Arch struct {
Arm struct {
@@ -127,15 +129,20 @@ type ApexFileProperties struct {
}
}
-func (p *ApexFileProperties) selectSource(ctx android.BottomUpMutatorContext) error {
- // This is called before prebuilt_select and prebuilt_postdeps mutators
- // The mutators requires that src to be set correctly for each arch so that
- // arch variants are disabled when src is not provided for the arch.
- if len(ctx.MultiTargets()) != 1 {
- return fmt.Errorf("compile_multilib shouldn't be \"both\" for prebuilt_apex")
+// prebuiltApexSelector selects the correct prebuilt APEX file for the build target.
+//
+// The ctx parameter can be for any module not just the prebuilt module so care must be taken not
+// to use methods on it that are specific to the current module.
+//
+// See the ApexFileProperties.Src property.
+func (p *ApexFileProperties) prebuiltApexSelector(ctx android.BaseModuleContext, prebuilt android.Module) []string {
+ multiTargets := prebuilt.MultiTargets()
+ if len(multiTargets) != 1 {
+ ctx.OtherModuleErrorf(prebuilt, "compile_multilib shouldn't be \"both\" for prebuilt_apex")
+ return nil
}
var src string
- switch ctx.MultiTargets()[0].Arch.ArchType {
+ switch multiTargets[0].Arch.ArchType {
case android.Arm:
src = String(p.Arch.Arm.Src)
case android.Arm64:
@@ -145,14 +152,14 @@ func (p *ApexFileProperties) selectSource(ctx android.BottomUpMutatorContext) er
case android.X86_64:
src = String(p.Arch.X86_64.Src)
default:
- return fmt.Errorf("prebuilt_apex does not support %q", ctx.MultiTargets()[0].Arch.String())
+ ctx.OtherModuleErrorf(prebuilt, "prebuilt_apex does not support %q", multiTargets[0].Arch.String())
+ return nil
}
if src == "" {
src = String(p.Src)
}
- p.Source = src
- return nil
+ return []string{src}
}
type PrebuiltProperties struct {
@@ -216,7 +223,7 @@ func (p *Prebuilt) Name() string {
func PrebuiltFactory() android.Module {
module := &Prebuilt{}
module.AddProperties(&module.properties)
- android.InitSingleSourcePrebuiltModule(module, &module.properties, "Source")
+ android.InitPrebuiltModuleWithSrcSupplier(module, module.properties.prebuiltApexSelector, "src")
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.AddLoadHook(module, func(ctx android.LoadHookContext) {
@@ -249,16 +256,6 @@ func prebuiltApexExportedModuleName(ctx android.BottomUpMutatorContext, name str
return name
}
-func prebuiltSelectSourceMutator(ctx android.BottomUpMutatorContext) {
- p, ok := ctx.Module().(*Prebuilt)
- if !ok {
- return
- }
- if err := p.properties.selectSource(ctx); err != nil {
- ctx.ModuleErrorf("%s", err)
- }
-}
-
type exportedDependencyTag struct {
blueprint.BaseDependencyTag
name string
@@ -531,7 +528,7 @@ func apexSetFactory() android.Module {
module := &ApexSet{}
module.AddProperties(&module.properties)
- srcsSupplier := func(ctx android.BaseModuleContext) []string {
+ srcsSupplier := func(ctx android.BaseModuleContext, _ android.Module) []string {
return module.prebuiltSrcs(ctx)
}
diff --git a/apex/vndk.go b/apex/vndk.go
index f4b12b564..75c0fb01b 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -17,7 +17,6 @@ package apex
import (
"path/filepath"
"strings"
- "sync"
"android/soong/android"
"android/soong/cc"
@@ -60,17 +59,6 @@ type apexVndkProperties struct {
Vndk_version *string
}
-var (
- vndkApexListKey = android.NewOnceKey("vndkApexList")
- vndkApexListMutex sync.Mutex
-)
-
-func vndkApexList(config android.Config) map[string]string {
- return config.Once(vndkApexListKey, func() interface{} {
- return map[string]string{}
- }).(map[string]string)
-}
-
func apexVndkMutator(mctx android.TopDownMutatorContext) {
if ab, ok := mctx.Module().(*apexBundle); ok && ab.vndkApex {
if ab.IsNativeBridgeSupported() {
@@ -80,15 +68,6 @@ func apexVndkMutator(mctx android.TopDownMutatorContext) {
vndkVersion := ab.vndkVersion(mctx.DeviceConfig())
// Ensure VNDK APEX mount point is formatted as com.android.vndk.v###
ab.properties.Apex_name = proptools.StringPtr(vndkApexNamePrefix + vndkVersion)
-
- // vndk_version should be unique
- vndkApexListMutex.Lock()
- defer vndkApexListMutex.Unlock()
- vndkApexList := vndkApexList(mctx.Config())
- if other, ok := vndkApexList[vndkVersion]; ok {
- mctx.PropertyErrorf("vndk_version", "%v is already defined in %q", vndkVersion, other)
- }
- vndkApexList[vndkVersion] = mctx.ModuleName()
}
}
@@ -99,9 +78,16 @@ func apexVndkDepsMutator(mctx android.BottomUpMutatorContext) {
if vndkVersion == "" {
vndkVersion = mctx.DeviceConfig().PlatformVndkVersion()
}
- vndkApexList := vndkApexList(mctx.Config())
- if vndkApex, ok := vndkApexList[vndkVersion]; ok {
- mctx.AddReverseDependency(mctx.Module(), sharedLibTag, vndkApex)
+ if vndkVersion == mctx.DeviceConfig().PlatformVndkVersion() {
+ vndkVersion = "current"
+ } else {
+ vndkVersion = "v" + vndkVersion
+ }
+
+ vndkApexName := "com.android.vndk." + vndkVersion
+
+ if mctx.OtherModuleExists(vndkApexName) {
+ mctx.AddReverseDependency(mctx.Module(), sharedLibTag, vndkApexName)
}
} else if a, ok := mctx.Module().(*apexBundle); ok && a.vndkApex {
vndkVersion := proptools.StringDefault(a.vndkProperties.Vndk_version, "current")
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index ccf4e57e6..34b940896 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -9,14 +9,15 @@ import (
)
func TestVndkApexForVndkLite(t *testing.T) {
- ctx, _ := testApex(t, `
+ ctx := testApex(t, `
apex_vndk {
- name: "myapex",
- key: "myapex.key",
+ name: "com.android.vndk.current",
+ key: "com.android.vndk.current.key",
+ updatable: false,
}
apex_key {
- name: "myapex.key",
+ name: "com.android.vndk.current.key",
public_key: "testkey.avbpubkey",
private_key: "testkey.pem",
}
@@ -31,7 +32,7 @@ func TestVndkApexForVndkLite(t *testing.T) {
},
system_shared_libs: [],
stl: "none",
- apex_available: [ "myapex" ],
+ apex_available: [ "com.android.vndk.current" ],
}
cc_library {
@@ -45,13 +46,13 @@ func TestVndkApexForVndkLite(t *testing.T) {
},
system_shared_libs: [],
stl: "none",
- apex_available: [ "myapex" ],
+ apex_available: [ "com.android.vndk.current" ],
}
`+vndkLibrariesTxtFiles("current"), func(fs map[string][]byte, config android.Config) {
config.TestProductVariables.DeviceVndkVersion = proptools.StringPtr("")
})
// VNDK-Lite contains only core variants of VNDK-Sp libraries
- ensureExactContents(t, ctx, "myapex", "android_common_image", []string{
+ ensureExactContents(t, ctx, "com.android.vndk.current", "android_common_image", []string{
"lib/libvndksp.so",
"lib/libc++.so",
"lib64/libvndksp.so",
@@ -67,8 +68,9 @@ func TestVndkApexForVndkLite(t *testing.T) {
func TestVndkApexUsesVendorVariant(t *testing.T) {
bp := `
apex_vndk {
- name: "myapex",
+ name: "com.android.vndk.current",
key: "mykey",
+ updatable: false,
}
apex_key {
name: "mykey",
@@ -94,11 +96,11 @@ func TestVndkApexUsesVendorVariant(t *testing.T) {
return
}
}
- t.Fail()
+ t.Errorf("expected path %q not found", path)
}
t.Run("VNDK lib doesn't have an apex variant", func(t *testing.T) {
- ctx, _ := testApex(t, bp)
+ ctx := testApex(t, bp)
// libfoo doesn't have apex variants
for _, variant := range ctx.ModuleVariantsForTests("libfoo") {
@@ -106,30 +108,30 @@ func TestVndkApexUsesVendorVariant(t *testing.T) {
}
// VNDK APEX doesn't create apex variant
- files := getFiles(t, ctx, "myapex", "android_common_image")
+ files := getFiles(t, ctx, "com.android.vndk.current", "android_common_image")
ensureFileSrc(t, files, "lib/libfoo.so", "libfoo/android_vendor.VER_arm_armv7-a-neon_shared/libfoo.so")
})
t.Run("VNDK APEX gathers only vendor variants even if product variants are available", func(t *testing.T) {
- ctx, _ := testApex(t, bp, func(fs map[string][]byte, config android.Config) {
+ ctx := testApex(t, bp, func(fs map[string][]byte, config android.Config) {
// Now product variant is available
config.TestProductVariables.ProductVndkVersion = proptools.StringPtr("current")
})
- files := getFiles(t, ctx, "myapex", "android_common_image")
+ files := getFiles(t, ctx, "com.android.vndk.current", "android_common_image")
ensureFileSrc(t, files, "lib/libfoo.so", "libfoo/android_vendor.VER_arm_armv7-a-neon_shared/libfoo.so")
})
t.Run("VNDK APEX supports coverage variants", func(t *testing.T) {
- ctx, _ := testApex(t, bp, func(fs map[string][]byte, config android.Config) {
+ ctx := testApex(t, bp, func(fs map[string][]byte, config android.Config) {
config.TestProductVariables.GcovCoverage = proptools.BoolPtr(true)
config.TestProductVariables.Native_coverage = proptools.BoolPtr(true)
})
- files := getFiles(t, ctx, "myapex", "android_common_image")
+ files := getFiles(t, ctx, "com.android.vndk.current", "android_common_image")
ensureFileSrc(t, files, "lib/libfoo.so", "libfoo/android_vendor.VER_arm_armv7-a-neon_shared/libfoo.so")
- files = getFiles(t, ctx, "myapex", "android_common_cov_image")
+ files = getFiles(t, ctx, "com.android.vndk.current", "android_common_cov_image")
ensureFileSrc(t, files, "lib/libfoo.so", "libfoo/android_vendor.VER_arm_armv7-a-neon_shared_cov/libfoo.so")
})
}
diff --git a/bazel/aquery.go b/bazel/aquery.go
index eb4bdfe99..c82b464ad 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -115,7 +115,23 @@ func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, error) {
// may be an expensive operation.
depsetIdToArtifactIdsCache := map[int][]int{}
+ // Do a pass through all actions to identify which artifacts are middleman artifacts.
+ // These will be omitted from the inputs of other actions.
+ // TODO(b/180945500): Handle middleman actions; without proper handling, depending on generated
+ // headers may cause build failures.
+ middlemanArtifactIds := map[int]bool{}
for _, actionEntry := range aqueryResult.Actions {
+ if actionEntry.Mnemonic == "Middleman" {
+ for _, outputId := range actionEntry.OutputIds {
+ middlemanArtifactIds[outputId] = true
+ }
+ }
+ }
+
+ for _, actionEntry := range aqueryResult.Actions {
+ if shouldSkipAction(actionEntry) {
+ continue
+ }
outputPaths := []string{}
for _, outputId := range actionEntry.OutputIds {
outputPath, exists := artifactIdToPath[outputId]
@@ -132,6 +148,10 @@ func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, error) {
return nil, err
}
for _, inputId := range inputArtifacts {
+ if _, isMiddlemanArtifact := middlemanArtifactIds[inputId]; isMiddlemanArtifact {
+ // Omit middleman artifacts.
+ continue
+ }
inputPath, exists := artifactIdToPath[inputId]
if !exists {
return nil, fmt.Errorf("undefined input artifactId %d", inputId)
@@ -145,12 +165,38 @@ func AqueryBuildStatements(aqueryJsonProto []byte) ([]BuildStatement, error) {
InputPaths: inputPaths,
Env: actionEntry.EnvironmentVariables,
Mnemonic: actionEntry.Mnemonic}
+ if len(actionEntry.Arguments) < 1 {
+ return nil, fmt.Errorf("received action with no command: [%s]", buildStatement)
+ continue
+ }
buildStatements = append(buildStatements, buildStatement)
}
return buildStatements, nil
}
+func shouldSkipAction(a action) bool {
+ // TODO(b/180945121): Handle symlink actions.
+ if a.Mnemonic == "Symlink" || a.Mnemonic == "SourceSymlinkManifest" || a.Mnemonic == "SymlinkTree" {
+ return true
+ }
+ // TODO(b/180945500): Handle middleman actions; without proper handling, depending on generated
+ // headers may cause build failures.
+ if a.Mnemonic == "Middleman" {
+ return true
+ }
+ // Skip "Fail" actions, which are placeholder actions designed to always fail.
+ if a.Mnemonic == "Fail" {
+ return true
+ }
+ // TODO(b/180946980): Handle FileWrite. The aquery proto currently contains no information
+ // about the contents that are written.
+ if a.Mnemonic == "FileWrite" {
+ return true
+ }
+ return false
+}
+
func artifactIdsFromDepsetId(depsetIdToDepset map[int]depSetOfFiles,
depsetIdToArtifactIdsCache map[int][]int, depsetId int) ([]int, error) {
if result, exists := depsetIdToArtifactIdsCache[depsetId]; exists {
diff --git a/bazel/properties.go b/bazel/properties.go
index 8055306b2..a5ffa55cb 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -14,10 +14,7 @@
package bazel
-import (
- "fmt"
- "strings"
-)
+import "fmt"
type bazelModuleProperties struct {
// The label of the Bazel target replacing this Soong module.
@@ -37,32 +34,15 @@ 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
+ Rule_class string `blueprint:"mutated"`
// The target label for the bzl file containing the definition of the rule class.
- Bzl_load_location string
+ Bzl_load_location string `blueprint:"mutated"`
}
const BazelTargetModuleNamePrefix = "__bp2build__"
-func NewBazelTargetModuleProperties(name string, ruleClass string, bzlLoadLocation string) BazelTargetModuleProperties {
- if strings.HasPrefix(name, BazelTargetModuleNamePrefix) {
- panic(fmt.Errorf(
- "The %s name prefix is added automatically, do not set it manually: %s",
- BazelTargetModuleNamePrefix,
- name))
- }
- name = BazelTargetModuleNamePrefix + name
- return BazelTargetModuleProperties{
- Name: &name,
- Rule_class: ruleClass,
- Bzl_load_location: bzlLoadLocation,
- }
-}
-
// Label is used to represent a Bazel compatible Label. Also stores the original bp text to support
// string replacement.
type Label struct {
@@ -85,3 +65,72 @@ func (ll *LabelList) Append(other LabelList) {
ll.Excludes = append(other.Excludes, other.Excludes...)
}
}
+
+// StringListAttribute corresponds to the string_list Bazel attribute type with
+// support for additional metadata, like configurations.
+type StringListAttribute struct {
+ // The base value of the string list attribute.
+ Value []string
+
+ // Optional additive set of list values to the base value.
+ ArchValues stringListArchValues
+}
+
+// Arch-specific string_list typed Bazel attribute values. This should correspond
+// to the types of architectures supported for compilation in arch.go.
+type stringListArchValues struct {
+ X86 []string
+ X86_64 []string
+ Arm []string
+ Arm64 []string
+ Default []string
+ // TODO(b/181299724): this is currently missing the "common" arch, which
+ // doesn't have an equivalent platform() definition yet.
+}
+
+// HasArchSpecificValues returns true if the attribute contains
+// architecture-specific string_list values.
+func (attrs *StringListAttribute) HasArchSpecificValues() bool {
+ for _, arch := range []string{"x86", "x86_64", "arm", "arm64", "default"} {
+ if len(attrs.GetValueForArch(arch)) > 0 {
+ return true
+ }
+ }
+ return false
+}
+
+// GetValueForArch returns the string_list attribute value for an architecture.
+func (attrs *StringListAttribute) GetValueForArch(arch string) []string {
+ switch arch {
+ case "x86":
+ return attrs.ArchValues.X86
+ case "x86_64":
+ return attrs.ArchValues.X86_64
+ case "arm":
+ return attrs.ArchValues.Arm
+ case "arm64":
+ return attrs.ArchValues.Arm64
+ case "default":
+ return attrs.ArchValues.Default
+ default:
+ panic(fmt.Errorf("Unknown arch: %s", arch))
+ }
+}
+
+// SetValueForArch sets the string_list attribute value for an architecture.
+func (attrs *StringListAttribute) SetValueForArch(arch string, value []string) {
+ switch arch {
+ case "x86":
+ attrs.ArchValues.X86 = value
+ case "x86_64":
+ attrs.ArchValues.X86_64 = value
+ case "arm":
+ attrs.ArchValues.Arm = value
+ case "arm64":
+ attrs.ArchValues.Arm64 = value
+ case "default":
+ attrs.ArchValues.Default = value
+ default:
+ panic(fmt.Errorf("Unknown arch: %s", arch))
+ }
+}
diff --git a/bloaty/bloaty.go b/bloaty/bloaty.go
index 0bff8aac7..21bf4acf1 100644
--- a/bloaty/bloaty.go
+++ b/bloaty/bloaty.go
@@ -23,6 +23,7 @@ import (
)
const bloatyDescriptorExt = "bloaty.csv"
+const protoFilename = "binary_sizes.pb"
var (
fileSizeMeasurerKey blueprint.ProviderKey
@@ -87,6 +88,10 @@ func (singleton *sizesSingleton) GenerateBuildActions(ctx android.SingletonConte
ctx.Build(pctx, android.BuildParams{
Rule: bloatyMerger,
Inputs: android.SortedUniquePaths(deps),
- Output: android.PathForOutput(ctx, "binary_sizes.pb"),
+ Output: android.PathForOutput(ctx, protoFilename),
})
}
+
+func (singleton *sizesSingleton) MakeVars(ctx android.MakeVarsContext) {
+ ctx.DistForGoalWithFilename("checkbuild", android.PathForOutput(ctx, protoFilename), protoFilename)
+}
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 521bb0601..8deb5a217 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -10,7 +10,9 @@ bootstrap_go_package {
"bp2build.go",
"build_conversion.go",
"bzl_conversion.go",
+ "configurability.go",
"conversion.go",
+ "metrics.go",
],
deps: [
"soong-android",
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
index b89d0a07f..7169d7e97 100644
--- a/bp2build/bp2build.go
+++ b/bp2build/bp2build.go
@@ -22,13 +22,13 @@ import (
// The Bazel bp2build code generator is responsible for writing .bzl files that are equivalent to
// Android.bp files that are capable of being built with Bazel.
-func Codegen(ctx CodegenContext) {
+func Codegen(ctx CodegenContext) CodegenMetrics {
outputDir := android.PathForOutput(ctx, "bp2build")
android.RemoveAllOutputDir(outputDir)
ruleShims := CreateRuleShims(android.ModuleTypeFactories())
- buildToTargets := GenerateBazelTargets(ctx.Context(), ctx.mode)
+ buildToTargets, metrics := GenerateBazelTargets(ctx)
filesToWrite := CreateBazelFiles(ruleShims, buildToTargets, ctx.mode)
for _, f := range filesToWrite {
@@ -36,6 +36,8 @@ func Codegen(ctx CodegenContext) {
fmt.Errorf("Failed to write %q (dir %q) due to %q", f.Basename, f.Dir, err)
}
}
+
+ return metrics
}
func writeFile(outputDir android.OutputPath, ctx android.PathContext, f BazelFile) error {
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 7ffcfa4a3..7fa499683 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -19,7 +19,6 @@ import (
"android/soong/bazel"
"fmt"
"reflect"
- "strconv"
"strings"
"github.com/google/blueprint"
@@ -105,6 +104,10 @@ type CodegenContext struct {
mode CodegenMode
}
+func (c *CodegenContext) Mode() CodegenMode {
+ return c.mode
+}
+
// CodegenMode is an enum to differentiate code-generation modes.
type CodegenMode int
@@ -160,65 +163,58 @@ func propsToAttributes(props map[string]string) string {
return attributes
}
-func GenerateBazelTargets(ctx bpToBuildContext, codegenMode CodegenMode) map[string]BazelTargets {
+func GenerateBazelTargets(ctx CodegenContext) (map[string]BazelTargets, CodegenMetrics) {
buildFileToTargets := make(map[string]BazelTargets)
- ctx.VisitAllModules(func(m blueprint.Module) {
- dir := ctx.ModuleDir(m)
+
+ // Simple metrics tracking for bp2build
+ totalModuleCount := 0
+ ruleClassCount := make(map[string]int)
+
+ bpCtx := ctx.Context()
+ bpCtx.VisitAllModules(func(m blueprint.Module) {
+ dir := bpCtx.ModuleDir(m)
var t BazelTarget
- switch codegenMode {
+ switch ctx.Mode() {
case Bp2Build:
- if _, ok := m.(android.BazelTargetModule); !ok {
+ if b, ok := m.(android.BazelTargetModule); !ok {
+ // Only include regular Soong modules (non-BazelTargetModules) into the total count.
+ totalModuleCount += 1
return
+ } else {
+ t = generateBazelTarget(bpCtx, m, b)
+ ruleClassCount[t.ruleClass] += 1
}
- t = generateBazelTarget(ctx, m)
case QueryView:
// Blocklist certain module types from being generated.
- if canonicalizeModuleType(ctx.ModuleType(m)) == "package" {
+ if canonicalizeModuleType(bpCtx.ModuleType(m)) == "package" {
// package module name contain slashes, and thus cannot
// be mapped cleanly to a bazel label.
return
}
- t = generateSoongModuleTarget(ctx, m)
+ t = generateSoongModuleTarget(bpCtx, m)
default:
- panic(fmt.Errorf("Unknown code-generation mode: %s", codegenMode))
+ panic(fmt.Errorf("Unknown code-generation mode: %s", ctx.Mode()))
}
buildFileToTargets[dir] = append(buildFileToTargets[dir], t)
})
- return buildFileToTargets
-}
-// Helper method to trim quotes around strings.
-func trimQuotes(s string) string {
- if s == "" {
- // strconv.Unquote would error out on empty strings, but this method
- // allows them, so return the empty string directly.
- return ""
+ metrics := CodegenMetrics{
+ TotalModuleCount: totalModuleCount,
+ RuleClassCount: ruleClassCount,
}
- ret, err := strconv.Unquote(s)
- if err != nil {
- // Panic the error immediately.
- panic(fmt.Errorf("Trying to unquote '%s', but got error: %s", s, err))
- }
- return ret
+
+ return buildFileToTargets, metrics
}
-func generateBazelTarget(ctx bpToBuildContext, m blueprint.Module) BazelTarget {
+func generateBazelTarget(ctx bpToBuildContext, m blueprint.Module, b android.BazelTargetModule) BazelTarget {
+ ruleClass := b.RuleClass()
+ bzlLoadLocation := b.BzlLoadLocation()
+
// extract the bazel attributes from the module.
props := getBuildProperties(ctx, m)
- // extract the rule class name from the attributes. Since the string value
- // will be string-quoted, remove the quotes here.
- ruleClass := trimQuotes(props.Attrs["rule_class"])
- // Delete it from being generated in the BUILD file.
- delete(props.Attrs, "rule_class")
-
- // extract the bzl_load_location, and also remove the quotes around it here.
- bzlLoadLocation := trimQuotes(props.Attrs["bzl_load_location"])
- // Delete it from being generated in the BUILD file.
- delete(props.Attrs, "bzl_load_location")
-
delete(props.Attrs, "bp2build_available")
// Return the Bazel target with rule class and attributes, ready to be
@@ -358,11 +354,42 @@ func prettyPrint(propertyValue reflect.Value, indent int) (string, error) {
ret += makeIndent(indent)
ret += "]"
case reflect.Struct:
+ // Special cases where the bp2build sends additional information to the codegenerator
+ // by wrapping the attributes in a custom struct type.
if labels, ok := propertyValue.Interface().(bazel.LabelList); ok {
// TODO(b/165114590): convert glob syntax
return prettyPrint(reflect.ValueOf(labels.Includes), indent)
} else if label, ok := propertyValue.Interface().(bazel.Label); ok {
return fmt.Sprintf("%q", label.Label), nil
+ } else if stringList, ok := propertyValue.Interface().(bazel.StringListAttribute); ok {
+ // A Bazel string_list attribute that may contain a select statement.
+ ret, err := prettyPrint(reflect.ValueOf(stringList.Value), indent)
+ if err != nil {
+ return ret, err
+ }
+
+ if !stringList.HasArchSpecificValues() {
+ // Select statement not needed.
+ return ret, nil
+ }
+
+ ret += " + " + "select({\n"
+ for _, arch := range android.ArchTypeList() {
+ value := stringList.GetValueForArch(arch.Name)
+ if len(value) > 0 {
+ ret += makeIndent(indent + 1)
+ list, _ := prettyPrint(reflect.ValueOf(value), indent+1)
+ ret += fmt.Sprintf("\"%s\": %s,\n", platformArchMap[arch], list)
+ }
+ }
+
+ ret += makeIndent(indent + 1)
+ list, _ := prettyPrint(reflect.ValueOf(stringList.GetValueForArch("default")), indent+1)
+ ret += fmt.Sprintf("\"%s\": %s,\n", "//conditions:default", list)
+
+ ret += makeIndent(indent)
+ ret += "})"
+ return ret, err
}
ret = "{\n"
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
index 422422b1f..aa4fc1d97 100644
--- a/bp2build/build_conversion_test.go
+++ b/bp2build/build_conversion_test.go
@@ -194,6 +194,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) {
for _, testCase := range testCases {
config := android.TestConfig(buildDir, nil, testCase.bp, nil)
ctx := android.NewTestContext(config)
+
ctx.RegisterModuleType("custom", customModuleFactory)
ctx.Register()
@@ -202,7 +203,8 @@ func TestGenerateSoongModuleTargets(t *testing.T) {
_, errs = ctx.PrepareBuildActions(config)
android.FailIfErrored(t, errs)
- bazelTargets := GenerateBazelTargets(ctx.Context.Context, QueryView)[dir]
+ codegenCtx := NewCodegenContext(config, *ctx.Context, QueryView)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
}
@@ -245,6 +247,7 @@ func TestGenerateBazelTargetModules(t *testing.T) {
for _, testCase := range testCases {
config := android.TestConfig(buildDir, nil, testCase.bp, nil)
ctx := android.NewTestContext(config)
+
ctx.RegisterModuleType("custom", customModuleFactory)
ctx.RegisterBp2BuildMutator("custom", customBp2BuildMutator)
ctx.RegisterForBazelConversion()
@@ -258,7 +261,9 @@ func TestGenerateBazelTargetModules(t *testing.T) {
continue
}
- bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[dir]
+ codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
+
if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
t.Errorf("Expected %d bazel target, got %d", expectedCount, actualCount)
} else {
@@ -415,7 +420,8 @@ load("//build/bazel/rules:rules.bzl", "my_library")`,
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
- bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[dir]
+ codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
if actualCount := len(bazelTargets); actualCount != testCase.expectedBazelTargetCount {
t.Fatalf("Expected %d bazel target, got %d", testCase.expectedBazelTargetCount, actualCount)
}
@@ -904,7 +910,9 @@ genrule {
if testCase.dir != "" {
checkDir = testCase.dir
}
- bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[checkDir]
+
+ codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
} else {
@@ -1118,7 +1126,8 @@ genrule {
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
- bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[dir]
+ codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
if actualCount := len(bazelTargets); actualCount != 1 {
t.Fatalf("%s: Expected 1 bazel target, got %d", testCase.description, actualCount)
}
@@ -1205,7 +1214,8 @@ func TestAllowlistingBp2buildTargets(t *testing.T) {
_, errs = ctx.ResolveDependencies(config)
android.FailIfErrored(t, errs)
- bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[dir]
+ codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
if actualCount := len(bazelTargets); actualCount != testCase.expectedCount {
t.Fatalf("%s: Expected %d bazel target, got %d", testCase.description, testCase.expectedCount, actualCount)
}
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 3cd37628f..5bf5c802f 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -202,7 +202,8 @@ cc_library_headers {
if testCase.dir != "" {
checkDir = testCase.dir
}
- bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[checkDir]
+ codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
} else {
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index e4ffe1680..1d4e32221 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -38,9 +38,10 @@ func TestCcObjectBp2Build(t *testing.T) {
moduleTypeUnderTestFactory: cc.ObjectFactory,
moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
filesystem: map[string]string{
- "a/b/foo.h": "",
- "a/b/bar.h": "",
- "a/b/c.c": "",
+ "a/b/foo.h": "",
+ "a/b/bar.h": "",
+ "a/b/exclude.c": "",
+ "a/b/c.c": "",
},
blueprint: `cc_object {
name: "foo",
@@ -52,8 +53,9 @@ func TestCcObjectBp2Build(t *testing.T) {
],
srcs: [
"a/b/*.h",
- "a/b/c.c"
+ "a/b/*.c"
],
+ exclude_srcs: ["a/b/exclude.c"],
bazel_module: { bp2build_available: true },
}
@@ -97,15 +99,6 @@ func TestCcObjectBp2Build(t *testing.T) {
cc_defaults {
name: "foo_defaults",
defaults: ["foo_bar_defaults"],
- // TODO(b/178130668): handle configurable attributes that depend on the platform
- arch: {
- x86: {
- cflags: ["-fPIC"],
- },
- x86_64: {
- cflags: ["-fPIC"],
- },
- },
}
cc_defaults {
@@ -134,6 +127,52 @@ cc_defaults {
)`,
},
},
+ {
+ description: "cc_object with cc_object deps in objs props",
+ moduleTypeUnderTest: "cc_object",
+ moduleTypeUnderTestFactory: cc.ObjectFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ filesystem: map[string]string{
+ "a/b/c.c": "",
+ "x/y/z.c": "",
+ },
+ blueprint: `cc_object {
+ name: "foo",
+ srcs: ["a/b/c.c"],
+ objs: ["bar"],
+
+ bazel_module: { bp2build_available: true },
+}
+
+cc_object {
+ name: "bar",
+ srcs: ["x/y/z.c"],
+
+ bazel_module: { bp2build_available: true },
+}
+`,
+ expectedBazelTargets: []string{`cc_object(
+ name = "bar",
+ copts = [
+ "-fno-addrsig",
+ ],
+ srcs = [
+ "x/y/z.c",
+ ],
+)`, `cc_object(
+ name = "foo",
+ copts = [
+ "-fno-addrsig",
+ ],
+ deps = [
+ ":bar",
+ ],
+ srcs = [
+ "a/b/c.c",
+ ],
+)`,
+ },
+ },
}
dir := "."
@@ -166,7 +205,142 @@ cc_defaults {
continue
}
- bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[dir]
+ codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
+ if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
+ fmt.Println(bazelTargets)
+ t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
+ } else {
+ for i, target := range bazelTargets {
+ if w, g := testCase.expectedBazelTargets[i], target.content; w != g {
+ t.Errorf(
+ "%s: Expected generated Bazel target to be '%s', got '%s'",
+ testCase.description,
+ w,
+ g,
+ )
+ }
+ }
+ }
+ }
+}
+
+func TestCcObjectConfigurableAttributesBp2Build(t *testing.T) {
+ testCases := []struct {
+ description string
+ moduleTypeUnderTest string
+ moduleTypeUnderTestFactory android.ModuleFactory
+ moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
+ blueprint string
+ expectedBazelTargets []string
+ filesystem map[string]string
+ }{
+ {
+ description: "cc_object setting cflags for one arch",
+ moduleTypeUnderTest: "cc_object",
+ moduleTypeUnderTestFactory: cc.ObjectFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ blueprint: `cc_object {
+ name: "foo",
+ arch: {
+ x86: {
+ cflags: ["-fPIC"],
+ },
+ },
+ bazel_module: { bp2build_available: true },
+}
+`,
+ expectedBazelTargets: []string{
+ `cc_object(
+ name = "foo",
+ copts = [
+ "-fno-addrsig",
+ ] + select({
+ "@bazel_tools//platforms:x86_32": [
+ "-fPIC",
+ ],
+ "//conditions:default": [
+ ],
+ }),
+)`,
+ },
+ },
+ {
+ description: "cc_object setting cflags for 4 architectures",
+ moduleTypeUnderTest: "cc_object",
+ moduleTypeUnderTestFactory: cc.ObjectFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.ObjectBp2Build,
+ blueprint: `cc_object {
+ name: "foo",
+ arch: {
+ x86: {
+ cflags: ["-fPIC"],
+ },
+ x86_64: {
+ cflags: ["-fPIC"],
+ },
+ arm: {
+ cflags: ["-Wall"],
+ },
+ arm64: {
+ cflags: ["-Wall"],
+ },
+ },
+ bazel_module: { bp2build_available: true },
+}
+`,
+ expectedBazelTargets: []string{
+ `cc_object(
+ name = "foo",
+ copts = [
+ "-fno-addrsig",
+ ] + select({
+ "@bazel_tools//platforms:arm": [
+ "-Wall",
+ ],
+ "@bazel_tools//platforms:aarch64": [
+ "-Wall",
+ ],
+ "@bazel_tools//platforms:x86_32": [
+ "-fPIC",
+ ],
+ "@bazel_tools//platforms:x86_64": [
+ "-fPIC",
+ ],
+ "//conditions:default": [
+ ],
+ }),
+)`,
+ },
+ },
+ }
+
+ dir := "."
+ for _, testCase := range testCases {
+ filesystem := make(map[string][]byte)
+ toParse := []string{
+ "Android.bp",
+ }
+ config := android.TestConfig(buildDir, nil, testCase.blueprint, filesystem)
+ ctx := android.NewTestContext(config)
+ // Always register cc_defaults module factory
+ ctx.RegisterModuleType("cc_defaults", func() android.Module { return cc.DefaultsFactory() })
+
+ ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
+ ctx.RegisterBp2BuildMutator(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestBp2BuildMutator)
+ ctx.RegisterForBazelConversion()
+
+ _, errs := ctx.ParseFileList(dir, toParse)
+ if Errored(t, testCase.description, errs) {
+ continue
+ }
+ _, errs = ctx.ResolveDependencies(config)
+ if Errored(t, testCase.description, errs) {
+ continue
+ }
+
+ codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, dir)
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
fmt.Println(bazelTargets)
t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
new file mode 100644
index 000000000..47cf3c612
--- /dev/null
+++ b/bp2build/configurability.go
@@ -0,0 +1,15 @@
+package bp2build
+
+import "android/soong/android"
+
+// Configurability support for bp2build.
+
+var (
+ // A map of architectures to the Bazel label of the constraint_value.
+ platformArchMap = map[android.ArchType]string{
+ android.Arm: "@bazel_tools//platforms:arm",
+ android.Arm64: "@bazel_tools//platforms:aarch64",
+ android.X86: "@bazel_tools//platforms:x86_32",
+ android.X86_64: "@bazel_tools//platforms:x86_64",
+ }
+)
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index 081e08243..1225f2bed 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -93,6 +93,7 @@ var (
"name": true, // redundant, since this is explicitly generated for every target
"from": true, // reserved keyword
"in": true, // reserved keyword
+ "size": true, // reserved for tests
"arch": true, // interface prop type is not supported yet.
"multilib": true, // interface prop type is not supported yet.
"target": true, // interface prop type is not supported yet.
diff --git a/bp2build/metrics.go b/bp2build/metrics.go
new file mode 100644
index 000000000..916129fba
--- /dev/null
+++ b/bp2build/metrics.go
@@ -0,0 +1,30 @@
+package bp2build
+
+import (
+ "android/soong/android"
+ "fmt"
+)
+
+// Simple metrics struct to collect information about a Blueprint to BUILD
+// conversion process.
+type CodegenMetrics struct {
+ // Total number of Soong/Blueprint modules
+ TotalModuleCount int
+
+ // Counts of generated Bazel targets per Bazel rule class
+ RuleClassCount map[string]int
+}
+
+// Print the codegen metrics to stdout.
+func (metrics CodegenMetrics) Print() {
+ generatedTargetCount := 0
+ for _, ruleClass := range android.SortedStringKeys(metrics.RuleClassCount) {
+ count := metrics.RuleClassCount[ruleClass]
+ fmt.Printf("[bp2build] %s: %d targets\n", ruleClass, count)
+ generatedTargetCount += count
+ }
+ fmt.Printf(
+ "[bp2build] Generated %d total BUILD targets from %d Android.bp modules.\n",
+ generatedTargetCount,
+ metrics.TotalModuleCount)
+}
diff --git a/bp2build/sh_conversion_test.go b/bp2build/sh_conversion_test.go
index dcc75bd5c..2aa373c3f 100644
--- a/bp2build/sh_conversion_test.go
+++ b/bp2build/sh_conversion_test.go
@@ -115,7 +115,8 @@ func TestShBinaryBp2Build(t *testing.T) {
if testCase.dir != "" {
checkDir = testCase.dir
}
- bazelTargets := GenerateBazelTargets(ctx.Context.Context, Bp2Build)[checkDir]
+ codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
if actualCount, expectedCount := len(bazelTargets), len(testCase.expectedBazelTargets); actualCount != expectedCount {
t.Errorf("%s: Expected %d bazel target, got %d", testCase.description, expectedCount, actualCount)
} else {
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 2e59999c2..bd75a8fc8 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -25,10 +25,9 @@ type customProps struct {
type customModule struct {
android.ModuleBase
+ android.BazelModuleBase
props customProps
-
- bazelProps bazel.Properties
}
// OutputFiles is needed because some instances of this module use dist with a
@@ -44,7 +43,7 @@ func (m *customModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
func customModuleFactoryBase() android.Module {
module := &customModule{}
module.AddProperties(&module.props)
- module.AddProperties(&module.bazelProps)
+ android.InitBazelModule(module)
return module
}
@@ -127,7 +126,7 @@ func (m *customBazelModule) GenerateAndroidBuildActions(ctx android.ModuleContex
func customBp2BuildMutator(ctx android.TopDownMutatorContext) {
if m, ok := ctx.Module().(*customModule); ok {
- if !m.bazelProps.Bazel_module.Bp2build_available {
+ if !m.ConvertWithBp2build() {
return
}
@@ -136,9 +135,11 @@ func customBp2BuildMutator(ctx android.TopDownMutatorContext) {
String_list_prop: m.props.String_list_prop,
}
- props := bazel.NewBazelTargetModuleProperties(m.Name(), "custom", "")
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "custom",
+ }
- ctx.CreateBazelTargetModule(customBazelModuleFactory, props, attrs)
+ ctx.CreateBazelTargetModule(customBazelModuleFactory, m.Name(), props, attrs)
}
}
@@ -146,32 +147,35 @@ func customBp2BuildMutator(ctx android.TopDownMutatorContext) {
// module to target.
func customBp2BuildMutatorFromStarlark(ctx android.TopDownMutatorContext) {
if m, ok := ctx.Module().(*customModule); ok {
- if !m.bazelProps.Bazel_module.Bp2build_available {
+ if !m.ConvertWithBp2build() {
return
}
baseName := m.Name()
attrs := &customBazelModuleAttributes{}
- myLibraryProps := bazel.NewBazelTargetModuleProperties(
- baseName,
- "my_library",
- "//build/bazel/rules:rules.bzl",
- )
- ctx.CreateBazelTargetModule(customBazelModuleFactory, myLibraryProps, attrs)
-
- protoLibraryProps := bazel.NewBazelTargetModuleProperties(
- baseName+"_proto_library_deps",
- "proto_library",
- "//build/bazel/rules:proto.bzl",
- )
- ctx.CreateBazelTargetModule(customBazelModuleFactory, protoLibraryProps, attrs)
-
- myProtoLibraryProps := bazel.NewBazelTargetModuleProperties(
- baseName+"_my_proto_library_deps",
- "my_proto_library",
- "//build/bazel/rules:proto.bzl",
- )
- ctx.CreateBazelTargetModule(customBazelModuleFactory, myProtoLibraryProps, attrs)
+ myLibraryProps := bazel.BazelTargetModuleProperties{
+ Rule_class: "my_library",
+ Bzl_load_location: "//build/bazel/rules:rules.bzl",
+ }
+ ctx.CreateBazelTargetModule(customBazelModuleFactory, baseName, myLibraryProps, attrs)
+
+ protoLibraryProps := bazel.BazelTargetModuleProperties{
+ Rule_class: "proto_library",
+ Bzl_load_location: "//build/bazel/rules:proto.bzl",
+ }
+ ctx.CreateBazelTargetModule(customBazelModuleFactory, baseName+"_proto_library_deps", protoLibraryProps, attrs)
+
+ myProtoLibraryProps := bazel.BazelTargetModuleProperties{
+ Rule_class: "my_proto_library",
+ Bzl_load_location: "//build/bazel/rules:proto.bzl",
+ }
+ ctx.CreateBazelTargetModule(customBazelModuleFactory, baseName+"_my_proto_library_deps", myProtoLibraryProps, attrs)
}
}
+
+// Helper method for tests to easily access the targets in a dir.
+func generateBazelTargetsForDir(codegenCtx CodegenContext, dir string) BazelTargets {
+ buildFileToTargets, _ := GenerateBazelTargets(codegenCtx)
+ return buildFileToTargets[dir]
+}
diff --git a/bpfix/bpfix/bpfix.go b/bpfix/bpfix/bpfix.go
index 94b825208..fae610189 100644
--- a/bpfix/bpfix/bpfix.go
+++ b/bpfix/bpfix/bpfix.go
@@ -670,6 +670,26 @@ func rewriteAndroidAppImport(f *Fixer) error {
return nil
}
+func RewriteRuntimeResourceOverlay(f *Fixer) error {
+ for _, def := range f.tree.Defs {
+ mod, ok := def.(*parser.Module)
+ if !(ok && mod.Type == "runtime_resource_overlay") {
+ continue
+ }
+ // runtime_resource_overlays are always product specific in Make.
+ if _, ok := mod.GetProperty("product_specific"); !ok {
+ prop := &parser.Property{
+ Name: "product_specific",
+ Value: &parser.Bool{
+ Value: true,
+ },
+ }
+ mod.Properties = append(mod.Properties, prop)
+ }
+ }
+ return nil
+}
+
// Removes library dependencies which are empty (and restricted from usage in Soong)
func removeEmptyLibDependencies(f *Fixer) error {
emptyLibraries := []string{
diff --git a/bpfix/bpfix/bpfix_test.go b/bpfix/bpfix/bpfix_test.go
index ef9814fb8..61dfe1af4 100644
--- a/bpfix/bpfix/bpfix_test.go
+++ b/bpfix/bpfix/bpfix_test.go
@@ -1056,3 +1056,71 @@ func TestRemovePdkProperty(t *testing.T) {
})
}
}
+
+func TestRewriteRuntimeResourceOverlay(t *testing.T) {
+ tests := []struct {
+ name string
+ in string
+ out string
+ }{
+ {
+ name: "product_specific runtime_resource_overlay",
+ in: `
+ runtime_resource_overlay {
+ name: "foo",
+ resource_dirs: ["res"],
+ product_specific: true,
+ }
+ `,
+ out: `
+ runtime_resource_overlay {
+ name: "foo",
+ resource_dirs: ["res"],
+ product_specific: true,
+ }
+ `,
+ },
+ {
+ // It's probably wrong for runtime_resource_overlay not to be product specific, but let's not
+ // debate it here.
+ name: "non-product_specific runtime_resource_overlay",
+ in: `
+ runtime_resource_overlay {
+ name: "foo",
+ resource_dirs: ["res"],
+ product_specific: false,
+ }
+ `,
+ out: `
+ runtime_resource_overlay {
+ name: "foo",
+ resource_dirs: ["res"],
+ product_specific: false,
+ }
+ `,
+ },
+ {
+ name: "runtime_resource_overlay without product_specific value",
+ in: `
+ runtime_resource_overlay {
+ name: "foo",
+ resource_dirs: ["res"],
+ }
+ `,
+ out: `
+ runtime_resource_overlay {
+ name: "foo",
+ resource_dirs: ["res"],
+ product_specific: true,
+ }
+ `,
+ },
+ }
+ for _, test := range tests {
+ t.Run(test.name, func(t *testing.T) {
+ runPass(t, test.in, test.out, func(fixer *Fixer) error {
+ return RewriteRuntimeResourceOverlay(fixer)
+ })
+ })
+ }
+}
diff --git a/build_kzip.bash b/build_kzip.bash
index 0018ea9b2..a4659d4c8 100755
--- a/build_kzip.bash
+++ b/build_kzip.bash
@@ -7,14 +7,17 @@
# BUILD_NUMBER build number, used to generate unique ID (will use UUID if not set)
# DIST_DIR where the resulting all.kzip will be placed
# KYTHE_KZIP_ENCODING proto or json (proto is default)
+# KYTHE_JAVA_SOURCE_BATCH_SIZE maximum number of the Java source files in a compilation unit
# OUT_DIR output directory (out if not specified})
# TARGET_BUILD_VARIANT variant, e.g., `userdebug`
# TARGET_PRODUCT target device name, e.g., 'aosp_blueline'
# XREF_CORPUS source code repository URI, e.g., 'android.googlesource.com/platform/superproject'
: ${BUILD_NUMBER:=$(uuidgen)}
+: ${KYTHE_JAVA_SOURCE_BATCH_SIZE:=500}
: ${KYTHE_KZIP_ENCODING:=proto}
-export KYTHE_KZIP_ENCODING
+: ${XREF_CORPUS:?should be set}
+export KYTHE_JAVA_SOURCE_BATCH_SIZE KYTHE_KZIP_ENCODING
# The extraction might fail for some source files, so run with -k and then check that
# sufficiently many files were generated.
@@ -27,11 +30,15 @@ build/soong/soong_ui.bash --build-mode --all-modules --dir=$PWD -k merge_zips xr
declare -r abspath_out=$(realpath "${out}")
declare -r go_extractor=$(realpath prebuilts/build-tools/linux-x86/bin/go_extractor)
declare -r go_root=$(realpath prebuilts/go/linux-x86)
-declare -r vnames_path=$(realpath build/soong/vnames.go.json)
declare -r source_root=$PWD
+
+# TODO(asmundak): Until b/182183061 is fixed, default corpus has to be specified
+# in the rules file. Generate this file on the fly with corpus value set from the
+# environment variable.
for dir in blueprint soong; do
(cd "build/$dir";
- KYTHE_ROOT_DIRECTORY="${source_root}" "$go_extractor" --goroot="$go_root" --rules="${vnames_path}" \
+ KYTHE_ROOT_DIRECTORY="${source_root}" "$go_extractor" --goroot="$go_root" \
+ --rules=<(printf '[{"pattern": "(.*)","vname": {"path": "@1@", "corpus":"%s"}}]' "${XREF_CORPUS}") \
--canonicalize_package_corpus --output "${abspath_out}/soong/build_${dir}.go.kzip" ./...
)
done
diff --git a/cc/cc.go b/cc/cc.go
index a873b041a..f7c4f855a 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -28,7 +28,6 @@ import (
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel"
"android/soong/cc/config"
"android/soong/genrule"
)
@@ -369,8 +368,6 @@ type BaseProperties struct {
// can depend on libraries that are not exported by the APEXes and use private symbols
// from the exported libraries.
Test_for []string
-
- bazel.Properties
}
type VendorProperties struct {
@@ -584,6 +581,17 @@ type installer interface {
makeUninstallable(mod *Module)
}
+// bazelHandler is the interface for a helper object related to deferring to Bazel for
+// processing a module (during Bazel mixed builds). Individual module types should define
+// their own bazel handler if they support deferring to Bazel.
+type bazelHandler interface {
+ // Issue query to Bazel to retrieve information about Bazel's view of the current module.
+ // If Bazel returns this information, set module properties on the current module to reflect
+ // the returned information.
+ // Returns true if information was available from Bazel, false if bazel invocation still needs to occur.
+ generateBazelBuildActions(ctx android.ModuleContext, label string) bool
+}
+
type xref interface {
XrefCcFiles() android.Paths
}
@@ -769,6 +777,7 @@ type Module struct {
android.DefaultableModuleBase
android.ApexModuleBase
android.SdkBase
+ android.BazelModuleBase
Properties BaseProperties
VendorProperties VendorProperties
@@ -785,9 +794,10 @@ type Module struct {
// type-specific logic. These members may reference different objects or the same object.
// Functions of these decorators will be invoked to initialize and register type-specific
// build statements.
- compiler compiler
- linker linker
- installer installer
+ compiler compiler
+ linker linker
+ installer installer
+ bazelHandler bazelHandler
features []feature
stl *stl
@@ -1058,6 +1068,7 @@ func (c *Module) Init() android.Module {
}
android.InitAndroidArchModule(c, c.hod, c.multilib)
+ android.InitBazelModule(c)
android.InitApexModule(c)
android.InitSdkAwareModule(c)
android.InitDefaultableModule(c)
@@ -1564,24 +1575,7 @@ func (c *Module) getNameSuffixWithVndkVersion(ctx android.ModuleContext) string
return nameSuffix
}
-func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
- // Handle the case of a test module split by `test_per_src` mutator.
- //
- // The `test_per_src` mutator adds an extra variation named "", depending on all the other
- // `test_per_src` variations of the test module. Set `outputFile` to an empty path for this
- // module and return early, as this module does not produce an output file per se.
- if c.IsTestPerSrcAllTestsVariation() {
- c.outputFile = android.OptionalPath{}
- return
- }
-
- apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- if !apexInfo.IsForPlatform() {
- c.hideApexVariantFromMake = true
- }
-
- c.makeLinkType = GetMakeLinkType(actx, c)
-
+func (c *Module) setSubnameProperty(actx android.ModuleContext) {
c.Properties.SubName = ""
if c.Target().NativeBridge == android.NativeBridgeEnabled {
@@ -1611,6 +1605,43 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
c.Properties.SubName += "." + c.SdkVersion()
}
}
+}
+
+// Returns true if Bazel was successfully used for the analysis of this module.
+func (c *Module) maybeGenerateBazelActions(actx android.ModuleContext) bool {
+ bazelModuleLabel := c.GetBazelLabel()
+ bazelActionsUsed := false
+ if c.bazelHandler != nil && actx.Config().BazelContext.BazelEnabled() && len(bazelModuleLabel) > 0 {
+ bazelActionsUsed = c.bazelHandler.generateBazelBuildActions(actx, bazelModuleLabel)
+ }
+ return bazelActionsUsed
+}
+
+func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
+ // TODO(cparsons): Any logic in this method occurring prior to querying Bazel should be
+ // requested from Bazel instead.
+
+ // Handle the case of a test module split by `test_per_src` mutator.
+ //
+ // The `test_per_src` mutator adds an extra variation named "", depending on all the other
+ // `test_per_src` variations of the test module. Set `outputFile` to an empty path for this
+ // module and return early, as this module does not produce an output file per se.
+ if c.IsTestPerSrcAllTestsVariation() {
+ c.outputFile = android.OptionalPath{}
+ return
+ }
+
+ c.setSubnameProperty(actx)
+ apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ if !apexInfo.IsForPlatform() {
+ c.hideApexVariantFromMake = true
+ }
+
+ if c.maybeGenerateBazelActions(actx) {
+ return
+ }
+
+ c.makeLinkType = GetMakeLinkType(actx, c)
ctx := &moduleContext{
ModuleContext: actx,
@@ -2426,36 +2457,6 @@ func checkDoubleLoadableLibraries(ctx android.TopDownMutatorContext) {
}
}
-// Returns the highest version which is <= maxSdkVersion.
-// For example, with maxSdkVersion is 10 and versionList is [9,11]
-// it returns 9 as string. The list of stubs must be in order from
-// oldest to newest.
-func (c *Module) chooseSdkVersion(ctx android.PathContext, stubsInfo []SharedStubLibrary,
- maxSdkVersion android.ApiLevel) (SharedStubLibrary, error) {
-
- for i := range stubsInfo {
- stubInfo := stubsInfo[len(stubsInfo)-i-1]
- var ver android.ApiLevel
- if stubInfo.Version == "" {
- ver = android.FutureApiLevel
- } else {
- var err error
- ver, err = android.ApiLevelFromUser(ctx, stubInfo.Version)
- if err != nil {
- return SharedStubLibrary{}, err
- }
- }
- if ver.LessThanOrEqualTo(maxSdkVersion) {
- return stubInfo, nil
- }
- }
- var versionList []string
- for _, stubInfo := range stubsInfo {
- versionList = append(versionList, stubInfo.Version)
- }
- return SharedStubLibrary{}, fmt.Errorf("not found a version(<=%s) in versionList: %v", maxSdkVersion.String(), versionList)
-}
-
func (c *Module) sdclang(ctx BaseModuleContext) bool {
sdclang := Bool(c.Properties.Sdclang)
@@ -2654,16 +2655,12 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
useStubs = !android.DirectlyInAllApexes(apexInfo, depName)
}
- // when to use (unspecified) stubs, check min_sdk_version and choose the right one
+ // when to use (unspecified) stubs, use the latest one.
if useStubs {
- sharedLibraryStubsInfo, err :=
- c.chooseSdkVersion(ctx, sharedLibraryStubsInfo.SharedStubLibraries, c.apexSdkVersion)
- if err != nil {
- ctx.OtherModuleErrorf(dep, err.Error())
- return
- }
- sharedLibraryInfo = sharedLibraryStubsInfo.SharedLibraryInfo
- depExporterInfo = sharedLibraryStubsInfo.FlagExporterInfo
+ stubs := sharedLibraryStubsInfo.SharedStubLibraries
+ toUse := stubs[len(stubs)-1]
+ sharedLibraryInfo = toUse.SharedLibraryInfo
+ depExporterInfo = toUse.FlagExporterInfo
}
}
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 2283d5977..e640f123e 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -20,6 +20,7 @@ import (
"os"
"path/filepath"
"reflect"
+ "regexp"
"strings"
"testing"
@@ -3910,3 +3911,274 @@ func TestSanitizeMemtagHeapWithSanitizeDeviceDiag(t *testing.T) {
checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_true_nodiag", variant), Async)
checkHasMemtagNote(t, ctx.ModuleForTests("sync_binary_true_diag", variant), Sync)
}
+
+func TestIncludeDirsExporting(t *testing.T) {
+
+ // Trim spaces from the beginning, end and immediately after any newline characters. Leaves
+ // embedded newline characters alone.
+ trimIndentingSpaces := func(s string) string {
+ return strings.TrimSpace(regexp.MustCompile("(^|\n)\\s+").ReplaceAllString(s, "$1"))
+ }
+
+ checkPaths := func(t *testing.T, message string, expected string, paths android.Paths) {
+ t.Helper()
+ expected = trimIndentingSpaces(expected)
+ actual := trimIndentingSpaces(strings.Join(android.FirstUniqueStrings(android.NormalizePathsForTesting(paths)), "\n"))
+ if expected != actual {
+ t.Errorf("%s: expected:\n%s\n actual:\n%s\n", message, expected, actual)
+ }
+ }
+
+ type exportedChecker func(t *testing.T, name string, exported FlagExporterInfo)
+
+ checkIncludeDirs := func(t *testing.T, ctx *android.TestContext, module android.Module, checkers ...exportedChecker) {
+ t.Helper()
+ exported := ctx.ModuleProvider(module, FlagExporterInfoProvider).(FlagExporterInfo)
+ name := module.Name()
+
+ for _, checker := range checkers {
+ checker(t, name, exported)
+ }
+ }
+
+ expectedIncludeDirs := func(expectedPaths string) exportedChecker {
+ return func(t *testing.T, name string, exported FlagExporterInfo) {
+ t.Helper()
+ checkPaths(t, fmt.Sprintf("%s: include dirs", name), expectedPaths, exported.IncludeDirs)
+ }
+ }
+
+ expectedSystemIncludeDirs := func(expectedPaths string) exportedChecker {
+ return func(t *testing.T, name string, exported FlagExporterInfo) {
+ t.Helper()
+ checkPaths(t, fmt.Sprintf("%s: system include dirs", name), expectedPaths, exported.SystemIncludeDirs)
+ }
+ }
+
+ expectedGeneratedHeaders := func(expectedPaths string) exportedChecker {
+ return func(t *testing.T, name string, exported FlagExporterInfo) {
+ t.Helper()
+ checkPaths(t, fmt.Sprintf("%s: generated headers", name), expectedPaths, exported.GeneratedHeaders)
+ }
+ }
+
+ expectedOrderOnlyDeps := func(expectedPaths string) exportedChecker {
+ return func(t *testing.T, name string, exported FlagExporterInfo) {
+ t.Helper()
+ checkPaths(t, fmt.Sprintf("%s: order only deps", name), expectedPaths, exported.Deps)
+ }
+ }
+
+ genRuleModules := `
+ genrule {
+ name: "genrule_foo",
+ cmd: "generate-foo",
+ out: [
+ "generated_headers/foo/generated_header.h",
+ ],
+ export_include_dirs: [
+ "generated_headers",
+ ],
+ }
+
+ genrule {
+ name: "genrule_bar",
+ cmd: "generate-bar",
+ out: [
+ "generated_headers/bar/generated_header.h",
+ ],
+ export_include_dirs: [
+ "generated_headers",
+ ],
+ }
+ `
+
+ t.Run("ensure exported include dirs are not automatically re-exported from shared_libs", func(t *testing.T) {
+ ctx := testCc(t, genRuleModules+`
+ cc_library {
+ name: "libfoo",
+ srcs: ["foo.c"],
+ export_include_dirs: ["foo/standard"],
+ export_system_include_dirs: ["foo/system"],
+ generated_headers: ["genrule_foo"],
+ export_generated_headers: ["genrule_foo"],
+ }
+
+ cc_library {
+ name: "libbar",
+ srcs: ["bar.c"],
+ shared_libs: ["libfoo"],
+ export_include_dirs: ["bar/standard"],
+ export_system_include_dirs: ["bar/system"],
+ generated_headers: ["genrule_bar"],
+ export_generated_headers: ["genrule_bar"],
+ }
+ `)
+ foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+ checkIncludeDirs(t, ctx, foo,
+ expectedIncludeDirs(`
+ foo/standard
+ .intermediates/genrule_foo/gen/generated_headers
+ `),
+ expectedSystemIncludeDirs(`foo/system`),
+ expectedGeneratedHeaders(`.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h`),
+ expectedOrderOnlyDeps(`.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h`),
+ )
+
+ bar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
+ checkIncludeDirs(t, ctx, bar,
+ expectedIncludeDirs(`
+ bar/standard
+ .intermediates/genrule_bar/gen/generated_headers
+ `),
+ expectedSystemIncludeDirs(`bar/system`),
+ expectedGeneratedHeaders(`.intermediates/genrule_bar/gen/generated_headers/bar/generated_header.h`),
+ expectedOrderOnlyDeps(`.intermediates/genrule_bar/gen/generated_headers/bar/generated_header.h`),
+ )
+ })
+
+ t.Run("ensure exported include dirs are automatically re-exported from whole_static_libs", func(t *testing.T) {
+ ctx := testCc(t, genRuleModules+`
+ cc_library {
+ name: "libfoo",
+ srcs: ["foo.c"],
+ export_include_dirs: ["foo/standard"],
+ export_system_include_dirs: ["foo/system"],
+ generated_headers: ["genrule_foo"],
+ export_generated_headers: ["genrule_foo"],
+ }
+
+ cc_library {
+ name: "libbar",
+ srcs: ["bar.c"],
+ whole_static_libs: ["libfoo"],
+ export_include_dirs: ["bar/standard"],
+ export_system_include_dirs: ["bar/system"],
+ generated_headers: ["genrule_bar"],
+ export_generated_headers: ["genrule_bar"],
+ }
+ `)
+ foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+ checkIncludeDirs(t, ctx, foo,
+ expectedIncludeDirs(`
+ foo/standard
+ .intermediates/genrule_foo/gen/generated_headers
+ `),
+ expectedSystemIncludeDirs(`foo/system`),
+ expectedGeneratedHeaders(`.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h`),
+ expectedOrderOnlyDeps(`.intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h`),
+ )
+
+ bar := ctx.ModuleForTests("libbar", "android_arm64_armv8-a_shared").Module()
+ checkIncludeDirs(t, ctx, bar,
+ expectedIncludeDirs(`
+ bar/standard
+ foo/standard
+ .intermediates/genrule_foo/gen/generated_headers
+ .intermediates/genrule_bar/gen/generated_headers
+ `),
+ expectedSystemIncludeDirs(`
+ bar/system
+ foo/system
+ `),
+ expectedGeneratedHeaders(`
+ .intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h
+ .intermediates/genrule_bar/gen/generated_headers/bar/generated_header.h
+ `),
+ expectedOrderOnlyDeps(`
+ .intermediates/genrule_foo/gen/generated_headers/foo/generated_header.h
+ .intermediates/genrule_bar/gen/generated_headers/bar/generated_header.h
+ `),
+ )
+ })
+
+ t.Run("ensure only aidl headers are exported", func(t *testing.T) {
+ ctx := testCc(t, genRuleModules+`
+ cc_library_shared {
+ name: "libfoo",
+ srcs: [
+ "foo.c",
+ "b.aidl",
+ "a.proto",
+ ],
+ aidl: {
+ export_aidl_headers: true,
+ }
+ }
+ `)
+ foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+ checkIncludeDirs(t, ctx, foo,
+ expectedIncludeDirs(`
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl
+ `),
+ expectedSystemIncludeDirs(``),
+ expectedGeneratedHeaders(`
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/b.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bnb.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bpb.h
+ `),
+ expectedOrderOnlyDeps(`
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/b.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bnb.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/aidl/Bpb.h
+ `),
+ )
+ })
+
+ t.Run("ensure only proto headers are exported", func(t *testing.T) {
+ ctx := testCc(t, genRuleModules+`
+ cc_library_shared {
+ name: "libfoo",
+ srcs: [
+ "foo.c",
+ "b.aidl",
+ "a.proto",
+ ],
+ proto: {
+ export_proto_headers: true,
+ }
+ }
+ `)
+ foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+ checkIncludeDirs(t, ctx, foo,
+ expectedIncludeDirs(`
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/proto
+ `),
+ expectedSystemIncludeDirs(``),
+ expectedGeneratedHeaders(`
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/proto/a.pb.h
+ `),
+ expectedOrderOnlyDeps(`
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/proto/a.pb.h
+ `),
+ )
+ })
+
+ t.Run("ensure only sysprop headers are exported", func(t *testing.T) {
+ ctx := testCc(t, genRuleModules+`
+ cc_library_shared {
+ name: "libfoo",
+ srcs: [
+ "foo.c",
+ "a.sysprop",
+ "b.aidl",
+ "a.proto",
+ ],
+ }
+ `)
+ foo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+ checkIncludeDirs(t, ctx, foo,
+ expectedIncludeDirs(`
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/include
+ `),
+ expectedSystemIncludeDirs(``),
+ expectedGeneratedHeaders(`
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/include/a.sysprop.h
+ `),
+ expectedOrderOnlyDeps(`
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/include/a.sysprop.h
+ .intermediates/libfoo/android_arm64_armv8-a_shared/gen/sysprop/public/include/a.sysprop.h
+ `),
+ )
+ })
+}
diff --git a/cc/compiler.go b/cc/compiler.go
index 5f30d3d6e..2e71922e1 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -230,6 +230,8 @@ type baseCompiler struct {
// other modules and filegroups. May include source files that have not yet been translated to
// C/C++ (.aidl, .proto, etc.)
srcsBeforeGen android.Paths
+
+ generatedSourceInfo
}
var _ compiler = (*baseCompiler)(nil)
@@ -440,7 +442,7 @@ func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps
fmt.Sprintf("${config.%sClangGlobalCflags}", hod))
if isThirdParty(modulePath) {
- flags.Global.CommonFlags = append([]string{"${config.ClangExternalCflags}"}, flags.Global.CommonFlags...)
+ flags.Global.CommonFlags = append(flags.Global.CommonFlags, "${config.ClangExternalCflags}")
}
if tc.Bionic() {
@@ -634,10 +636,11 @@ func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathD
srcs := append(android.Paths(nil), compiler.srcsBeforeGen...)
- srcs, genDeps := genSources(ctx, srcs, buildFlags)
+ srcs, genDeps, info := genSources(ctx, srcs, buildFlags)
pathDeps = append(pathDeps, genDeps...)
compiler.pathDeps = pathDeps
+ compiler.generatedSourceInfo = info
compiler.cFlagsDeps = flags.CFlagsDeps
// Save src, buildFlags and context
diff --git a/cc/config/tidy.go b/cc/config/tidy.go
index 7c20dd543..c4563e273 100644
--- a/cc/config/tidy.go
+++ b/cc/config/tidy.go
@@ -31,7 +31,6 @@ func init() {
}
checks := strings.Join([]string{
"-*",
- "abseil-*",
"android-*",
"bugprone-*",
"cert-*",
diff --git a/cc/gen.go b/cc/gen.go
index 75b9e49e5..83c019c33 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -220,8 +220,35 @@ func genWinMsg(ctx android.ModuleContext, srcFile android.Path, flags builderFla
return rcFile, headerFile
}
+// Used to communicate information from the genSources method back to the library code that uses
+// it.
+type generatedSourceInfo struct {
+ // The headers created from .proto files
+ protoHeaders android.Paths
+
+ // The files that can be used as order only dependencies in order to ensure that the proto header
+ // files are up to date.
+ protoOrderOnlyDeps android.Paths
+
+ // The headers created from .aidl files
+ aidlHeaders android.Paths
+
+ // The files that can be used as order only dependencies in order to ensure that the aidl header
+ // files are up to date.
+ aidlOrderOnlyDeps android.Paths
+
+ // The headers created from .sysprop files
+ syspropHeaders android.Paths
+
+ // The files that can be used as order only dependencies in order to ensure that the sysprop
+ // header files are up to date.
+ syspropOrderOnlyDeps android.Paths
+}
+
func genSources(ctx android.ModuleContext, srcFiles android.Paths,
- buildFlags builderFlags) (android.Paths, android.Paths) {
+ buildFlags builderFlags) (android.Paths, android.Paths, generatedSourceInfo) {
+
+ var info generatedSourceInfo
var deps android.Paths
var rsFiles android.Paths
@@ -258,7 +285,9 @@ func genSources(ctx android.ModuleContext, srcFiles android.Paths,
case ".proto":
ccFile, headerFile := genProto(ctx, srcFile, buildFlags)
srcFiles[i] = ccFile
- deps = append(deps, headerFile)
+ info.protoHeaders = append(info.protoHeaders, headerFile)
+ // Use the generated header as an order only dep to ensure that it is up to date when needed.
+ info.protoOrderOnlyDeps = append(info.protoOrderOnlyDeps, headerFile)
case ".aidl":
if aidlRule == nil {
aidlRule = android.NewRuleBuilder(pctx, ctx).Sbox(android.PathForModuleGen(ctx, "aidl"),
@@ -267,7 +296,12 @@ func genSources(ctx android.ModuleContext, srcFiles android.Paths,
cppFile := android.GenPathWithExt(ctx, "aidl", srcFile, "cpp")
depFile := android.GenPathWithExt(ctx, "aidl", srcFile, "cpp.d")
srcFiles[i] = cppFile
- deps = append(deps, genAidl(ctx, aidlRule, srcFile, cppFile, depFile, buildFlags.aidlFlags)...)
+ aidlHeaders := genAidl(ctx, aidlRule, srcFile, cppFile, depFile, buildFlags.aidlFlags)
+ info.aidlHeaders = append(info.aidlHeaders, aidlHeaders...)
+ // Use the generated headers as order only deps to ensure that they are up to date when
+ // needed.
+ // TODO: Reduce the size of the ninja file by using one order only dep for the whole rule
+ info.aidlOrderOnlyDeps = append(info.aidlOrderOnlyDeps, aidlHeaders...)
case ".rscript", ".fs":
cppFile := rsGeneratedCppFile(ctx, srcFile)
rsFiles = append(rsFiles, srcFiles[i])
@@ -279,7 +313,10 @@ func genSources(ctx android.ModuleContext, srcFiles android.Paths,
case ".sysprop":
cppFile, headerFiles := genSysprop(ctx, srcFile)
srcFiles[i] = cppFile
- deps = append(deps, headerFiles...)
+ info.syspropHeaders = append(info.syspropHeaders, headerFiles...)
+ // Use the generated headers as order only deps to ensure that they are up to date when
+ // needed.
+ info.syspropOrderOnlyDeps = append(info.syspropOrderOnlyDeps, headerFiles...)
}
}
@@ -291,9 +328,13 @@ func genSources(ctx android.ModuleContext, srcFiles android.Paths,
yaccRule_.Build("yacc", "gen yacc")
}
+ deps = append(deps, info.protoOrderOnlyDeps...)
+ deps = append(deps, info.aidlOrderOnlyDeps...)
+ deps = append(deps, info.syspropOrderOnlyDeps...)
+
if len(rsFiles) > 0 {
deps = append(deps, rsGenerateCpp(ctx, rsFiles, buildFlags.rsFlags)...)
}
- return srcFiles, deps
+ return srcFiles, deps, info
}
diff --git a/cc/library.go b/cc/library.go
index d75059182..6acbc5b8e 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -1331,9 +1331,8 @@ func (library *libraryDecorator) link(ctx ModuleContext,
dir := android.PathForModuleGen(ctx, "aidl")
library.reexportDirs(dir)
- // TODO: restrict to aidl deps
- library.reexportDeps(library.baseCompiler.pathDeps...)
- library.addExportedGeneratedHeaders(library.baseCompiler.pathDeps...)
+ library.reexportDeps(library.baseCompiler.aidlOrderOnlyDeps...)
+ library.addExportedGeneratedHeaders(library.baseCompiler.aidlHeaders...)
}
}
@@ -1347,9 +1346,8 @@ func (library *libraryDecorator) link(ctx ModuleContext,
includes = append(includes, flags.proto.Dir)
library.reexportDirs(includes...)
- // TODO: restrict to proto deps
- library.reexportDeps(library.baseCompiler.pathDeps...)
- library.addExportedGeneratedHeaders(library.baseCompiler.pathDeps...)
+ library.reexportDeps(library.baseCompiler.protoOrderOnlyDeps...)
+ library.addExportedGeneratedHeaders(library.baseCompiler.protoHeaders...)
}
}
@@ -1368,10 +1366,16 @@ func (library *libraryDecorator) link(ctx ModuleContext,
}
}
+ // Make sure to only export headers which are within the include directory.
+ _, headers := android.FilterPathListPredicate(library.baseCompiler.syspropHeaders, func(path android.Path) bool {
+ _, isRel := android.MaybeRel(ctx, dir.String(), path.String())
+ return isRel
+ })
+
// Add sysprop-related directories to the exported directories of this library.
library.reexportDirs(dir)
- library.reexportDeps(library.baseCompiler.pathDeps...)
- library.addExportedGeneratedHeaders(library.baseCompiler.pathDeps...)
+ library.reexportDeps(library.baseCompiler.syspropOrderOnlyDeps...)
+ library.addExportedGeneratedHeaders(headers...)
}
// Add stub-related flags if this library is a stub library.
diff --git a/cc/library_headers.go b/cc/library_headers.go
index e5a555729..dc851a59c 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -86,7 +86,7 @@ func CcLibraryHeadersBp2Build(ctx android.TopDownMutatorContext) {
return
}
- if !module.Properties.Bazel_module.Bp2build_available {
+ if !module.ConvertWithBp2build() {
return
}
@@ -129,13 +129,12 @@ func CcLibraryHeadersBp2Build(ctx android.TopDownMutatorContext) {
Deps: headerLibLabels,
}
- props := bazel.NewBazelTargetModuleProperties(
- module.Name(),
- "cc_library_headers",
- "//build/bazel/rules:cc_library_headers.bzl",
- )
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_library_headers",
+ Bzl_load_location: "//build/bazel/rules:cc_library_headers.bzl",
+ }
- ctx.CreateBazelTargetModule(BazelCcLibraryHeadersFactory, props, attrs)
+ ctx.CreateBazelTargetModule(BazelCcLibraryHeadersFactory, module.Name(), props, attrs)
}
func (m *bazelCcLibraryHeaders) Name() string {
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index 14029919e..d5f2adf8b 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -206,22 +206,22 @@ var includeDirProperties = []includeDirsProperty{
dirs: true,
},
{
- // exportedGeneratedIncludeDirs lists directories that contains some header files
- // that are explicitly listed in the exportedGeneratedHeaders property. So, the contents
+ // ExportedGeneratedIncludeDirs lists directories that contains some header files
+ // that are explicitly listed in the ExportedGeneratedHeaders property. So, the contents
// of these directories do not need to be copied, but these directories do need adding to
// the export_include_dirs property in the prebuilt module in the snapshot.
- pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.exportedGeneratedIncludeDirs },
+ pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.ExportedGeneratedIncludeDirs },
propertyName: "export_include_dirs",
snapshotDir: nativeGeneratedIncludeDir,
copy: false,
dirs: true,
},
{
- // exportedGeneratedHeaders lists header files that are in one of the directories
- // specified in exportedGeneratedIncludeDirs must be copied into the snapshot.
- // As they are in a directory in exportedGeneratedIncludeDirs they do not need adding to a
+ // ExportedGeneratedHeaders lists header files that are in one of the directories
+ // specified in ExportedGeneratedIncludeDirs must be copied into the snapshot.
+ // As they are in a directory in ExportedGeneratedIncludeDirs they do not need adding to a
// property in the prebuilt module in the snapshot.
- pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.exportedGeneratedHeaders },
+ pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.ExportedGeneratedHeaders },
propertyName: "",
snapshotDir: nativeGeneratedIncludeDir,
copy: true,
@@ -258,42 +258,52 @@ func addPossiblyArchSpecificProperties(sdkModuleContext android.ModuleContext, b
// values where necessary.
for _, propertyInfo := range includeDirProperties {
// Calculate the base directory in the snapshot into which the files will be copied.
- // lib.ArchType is "" for common properties.
+ // lib.archType is "" for common properties.
targetDir := filepath.Join(libInfo.OsPrefix(), libInfo.archType, propertyInfo.snapshotDir)
propertyName := propertyInfo.propertyName
// Iterate over each path in one of the include directory properties.
for _, path := range propertyInfo.pathsGetter(libInfo) {
+ inputPath := path.String()
+
+ // Map the input path to a snapshot relative path. The mapping is independent of the module
+ // that references them so that if multiple modules within the same snapshot export the same
+ // header files they end up in the same place in the snapshot and so do not get duplicated.
+ targetRelativePath := inputPath
+ if isGeneratedHeaderDirectory(path) {
+ // Remove everything up to the .intermediates/ from the generated output directory to
+ // leave a module relative path.
+ base := android.PathForIntermediates(sdkModuleContext, "")
+ targetRelativePath = android.Rel(sdkModuleContext, base.String(), inputPath)
+ }
+
+ snapshotRelativePath := filepath.Join(targetDir, targetRelativePath)
// Copy the files/directories when necessary.
if propertyInfo.copy {
if propertyInfo.dirs {
// When copying a directory glob and copy all the headers within it.
// TODO(jiyong) copy headers having other suffixes
- headers, _ := sdkModuleContext.GlobWithDeps(path.String()+"/**/*.h", nil)
+ headers, _ := sdkModuleContext.GlobWithDeps(inputPath+"/**/*.h", nil)
for _, file := range headers {
src := android.PathForSource(sdkModuleContext, file)
- dest := filepath.Join(targetDir, file)
+
+ // The destination path in the snapshot is constructed from the snapshot relative path
+ // of the input directory and the input directory relative path of the header file.
+ inputRelativePath := android.Rel(sdkModuleContext, inputPath, file)
+ dest := filepath.Join(snapshotRelativePath, inputRelativePath)
builder.CopyToSnapshot(src, dest)
}
} else {
- // Otherwise, just copy the files.
- dest := filepath.Join(targetDir, libInfo.name, path.Rel())
- builder.CopyToSnapshot(path, dest)
+ // Otherwise, just copy the file to its snapshot relative path.
+ builder.CopyToSnapshot(path, snapshotRelativePath)
}
}
// Only directories are added to a property.
if propertyInfo.dirs {
- var snapshotPath string
- if isGeneratedHeaderDirectory(path) {
- snapshotPath = filepath.Join(targetDir, libInfo.name)
- } else {
- snapshotPath = filepath.Join(targetDir, path.String())
- }
-
- includeDirs[propertyName] = append(includeDirs[propertyName], snapshotPath)
+ includeDirs[propertyName] = append(includeDirs[propertyName], snapshotRelativePath)
}
}
}
@@ -330,9 +340,6 @@ type nativeLibInfoProperties struct {
memberType *librarySdkMemberType
- // The name of the library, is not exported as this must not be changed during optimization.
- name string
-
// archType is not exported as if set (to a non default value) it is always arch specific.
// This is "" for common properties.
archType string
@@ -344,13 +351,13 @@ type nativeLibInfoProperties struct {
// The list of arch specific exported generated include dirs.
//
- // This field is not exported as its contents are always arch specific.
- exportedGeneratedIncludeDirs android.Paths
+ // This field is exported as its contents may not be arch specific, e.g. protos.
+ ExportedGeneratedIncludeDirs android.Paths `android:"arch_variant"`
// The list of arch specific exported generated header files.
//
- // This field is not exported as its contents are is always arch specific.
- exportedGeneratedHeaders android.Paths
+ // This field is exported as its contents may not be arch specific, e.g. protos.
+ ExportedGeneratedHeaders android.Paths `android:"arch_variant"`
// The list of possibly common exported system include dirs.
//
@@ -419,12 +426,11 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte
exportedIncludeDirs, exportedGeneratedIncludeDirs := android.FilterPathListPredicate(
exportedInfo.IncludeDirs, isGeneratedHeaderDirectory)
- p.name = variant.Name()
p.archType = ccModule.Target().Arch.ArchType.String()
// Make sure that the include directories are unique.
p.ExportedIncludeDirs = android.FirstUniquePaths(exportedIncludeDirs)
- p.exportedGeneratedIncludeDirs = android.FirstUniquePaths(exportedGeneratedIncludeDirs)
+ p.ExportedGeneratedIncludeDirs = android.FirstUniquePaths(exportedGeneratedIncludeDirs)
// Take a copy before filtering out duplicates to avoid changing the slice owned by the
// ccModule.
@@ -450,7 +456,7 @@ func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberConte
}
p.SystemSharedLibs = specifiedDeps.systemSharedLibs
}
- p.exportedGeneratedHeaders = exportedInfo.GeneratedHeaders
+ p.ExportedGeneratedHeaders = exportedInfo.GeneratedHeaders
if !p.memberType.noOutputFiles && addOutputFile {
p.outputFile = getRequiredMemberOutputFile(ctx, ccModule)
diff --git a/cc/object.go b/cc/object.go
index d92e1109f..126bd657b 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -46,6 +46,26 @@ type objectLinker struct {
Properties ObjectLinkerProperties
}
+type objectBazelHandler struct {
+ bazelHandler
+
+ module *Module
+}
+
+func (handler *objectBazelHandler) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
+ bazelCtx := ctx.Config().BazelContext
+ objPaths, ok := bazelCtx.GetCcObjectFiles(label, ctx.Arch().ArchType)
+ if ok {
+ if len(objPaths) != 1 {
+ ctx.ModuleErrorf("expected exactly one object file for '%s', but got %s", label, objPaths)
+ return false
+ }
+
+ handler.module.outputFile = android.OptionalPathForPath(android.PathForBazelOut(ctx, objPaths[0]))
+ }
+ return ok
+}
+
type ObjectLinkerProperties struct {
// list of modules that should only provide headers for this module.
Header_libs []string `android:"arch_variant,variant_prepend"`
@@ -80,6 +100,7 @@ func ObjectFactory() android.Module {
baseLinker: NewBaseLinker(module.sanitize),
}
module.compiler = NewBaseCompiler()
+ module.bazelHandler = &objectBazelHandler{module: module}
// Clang's address-significance tables are incompatible with ld -r.
module.compiler.appendCflags([]string{"-fno-addrsig"})
@@ -92,7 +113,8 @@ func ObjectFactory() android.Module {
// For bp2build conversion.
type bazelObjectAttributes struct {
Srcs bazel.LabelList
- Copts []string
+ Deps bazel.LabelList
+ Copts bazel.StringListAttribute
Local_include_dirs []string
}
@@ -118,7 +140,7 @@ func BazelObjectFactory() android.Module {
// Bazel equivalent target, plus any necessary include deps for the cc_object.
func ObjectBp2Build(ctx android.TopDownMutatorContext) {
m, ok := ctx.Module().(*Module)
- if !ok || !m.Properties.Bazel_module.Bp2build_available {
+ if !ok || !m.ConvertWithBp2build() {
return
}
@@ -132,31 +154,48 @@ func ObjectBp2Build(ctx android.TopDownMutatorContext) {
ctx.ModuleErrorf("compiler must not be nil for a cc_object module")
}
- var copts []string
+ // Set arch-specific configurable attributes
+ var copts bazel.StringListAttribute
var srcs []string
+ var excludeSrcs []string
var localIncludeDirs []string
for _, props := range m.compiler.compilerProps() {
if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
- copts = baseCompilerProps.Cflags
+ copts.Value = baseCompilerProps.Cflags
srcs = baseCompilerProps.Srcs
+ excludeSrcs = baseCompilerProps.Exclude_srcs
localIncludeDirs = baseCompilerProps.Local_include_dirs
break
}
}
+ var deps bazel.LabelList
+ for _, props := range m.linker.linkerProps() {
+ if objectLinkerProps, ok := props.(*ObjectLinkerProperties); ok {
+ deps = android.BazelLabelForModuleDeps(ctx, objectLinkerProps.Objs)
+ }
+ }
+
+ for arch, p := range m.GetArchProperties(&BaseCompilerProperties{}) {
+ if cProps, ok := p.(*BaseCompilerProperties); ok {
+ copts.SetValueForArch(arch.Name, cProps.Cflags)
+ }
+ }
+ copts.SetValueForArch("default", []string{})
+
attrs := &bazelObjectAttributes{
- Srcs: android.BazelLabelForModuleSrc(ctx, srcs),
+ Srcs: android.BazelLabelForModuleSrcExcludes(ctx, srcs, excludeSrcs),
+ Deps: deps,
Copts: copts,
Local_include_dirs: localIncludeDirs,
}
- props := bazel.NewBazelTargetModuleProperties(
- m.Name(),
- "cc_object",
- "//build/bazel/rules:cc_object.bzl",
- )
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_object",
+ Bzl_load_location: "//build/bazel/rules:cc_object.bzl",
+ }
- ctx.CreateBazelTargetModule(BazelObjectFactory, props, attrs)
+ ctx.CreateBazelTargetModule(BazelObjectFactory, m.Name(), props, attrs)
}
func (object *objectLinker) appendLdflags(flags []string) {
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 2cd18cb99..6b9a3d529 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -246,7 +246,7 @@ func NewPrebuiltLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDec
module.AddProperties(&prebuilt.properties)
- srcsSupplier := func(ctx android.BaseModuleContext) []string {
+ srcsSupplier := func(ctx android.BaseModuleContext, _ android.Module) []string {
return prebuilt.prebuiltSrcs(ctx)
}
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index 62daafde4..f9aea0cfe 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -280,50 +280,36 @@ func (s *snapshot) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Nothing, the snapshot module is only used to forward dependency information in DepsMutator.
}
-func (s *snapshot) DepsMutator(ctx android.BottomUpMutatorContext) {
- collectSnapshotMap := func(variations []blueprint.Variation, depTag blueprint.DependencyTag,
- names []string, snapshotSuffix, moduleSuffix string) map[string]string {
-
- decoratedNames := make([]string, 0, len(names))
- for _, name := range names {
- decoratedNames = append(decoratedNames, name+
- snapshotSuffix+moduleSuffix+
- s.baseSnapshot.version()+
- "."+ctx.Arch().ArchType.Name)
- }
+func getSnapshotNameSuffix(moduleSuffix, version, arch string) string {
+ versionSuffix := version
+ if arch != "" {
+ versionSuffix += "." + arch
+ }
+ return moduleSuffix + versionSuffix
+}
- deps := ctx.AddVariationDependencies(variations, depTag, decoratedNames...)
+func (s *snapshot) DepsMutator(ctx android.BottomUpMutatorContext) {
+ collectSnapshotMap := func(names []string, snapshotSuffix, moduleSuffix string) map[string]string {
snapshotMap := make(map[string]string)
- for _, dep := range deps {
- if dep == nil {
- continue
- }
-
- snapshotMap[dep.(*Module).BaseModuleName()] = ctx.OtherModuleName(dep)
+ for _, name := range names {
+ snapshotMap[name] = name +
+ getSnapshotNameSuffix(snapshotSuffix+moduleSuffix,
+ s.baseSnapshot.version(), ctx.Arch().ArchType.Name)
}
return snapshotMap
}
snapshotSuffix := s.image.moduleNameSuffix()
- headers := collectSnapshotMap(nil, HeaderDepTag(), s.properties.Header_libs, snapshotSuffix, snapshotHeaderSuffix)
- binaries := collectSnapshotMap(nil, nil, s.properties.Binaries, snapshotSuffix, snapshotBinarySuffix)
- objects := collectSnapshotMap(nil, nil, s.properties.Objects, snapshotSuffix, snapshotObjectSuffix)
-
- staticLibs := collectSnapshotMap([]blueprint.Variation{
- {Mutator: "link", Variation: "static"},
- }, StaticDepTag(), s.properties.Static_libs, snapshotSuffix, snapshotStaticSuffix)
-
- sharedLibs := collectSnapshotMap([]blueprint.Variation{
- {Mutator: "link", Variation: "shared"},
- }, SharedDepTag(), s.properties.Shared_libs, snapshotSuffix, snapshotSharedSuffix)
-
- vndkLibs := collectSnapshotMap([]blueprint.Variation{
- {Mutator: "link", Variation: "shared"},
- }, SharedDepTag(), s.properties.Vndk_libs, "", vndkSuffix)
-
+ headers := collectSnapshotMap(s.properties.Header_libs, snapshotSuffix, snapshotHeaderSuffix)
+ binaries := collectSnapshotMap(s.properties.Binaries, snapshotSuffix, snapshotBinarySuffix)
+ objects := collectSnapshotMap(s.properties.Objects, snapshotSuffix, snapshotObjectSuffix)
+ staticLibs := collectSnapshotMap(s.properties.Static_libs, snapshotSuffix, snapshotStaticSuffix)
+ sharedLibs := collectSnapshotMap(s.properties.Shared_libs, snapshotSuffix, snapshotSharedSuffix)
+ vndkLibs := collectSnapshotMap(s.properties.Vndk_libs, "", vndkSuffix)
for k, v := range vndkLibs {
sharedLibs[k] = v
}
+
ctx.SetProvider(SnapshotInfoProvider, SnapshotInfo{
HeaderLibs: headers,
Binaries: binaries,
@@ -395,12 +381,7 @@ func (p *baseSnapshotDecorator) Name(name string) string {
}
func (p *baseSnapshotDecorator) NameSuffix() string {
- versionSuffix := p.version()
- if p.arch() != "" {
- versionSuffix += "." + p.arch()
- }
-
- return p.baseProperties.ModuleSuffix + versionSuffix
+ return getSnapshotNameSuffix(p.moduleSuffix(), p.version(), p.arch())
}
func (p *baseSnapshotDecorator) version() string {
diff --git a/cc/testing.go b/cc/testing.go
index 45e531208..f62c5f114 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -25,7 +25,6 @@ func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) {
RegisterBinaryBuildComponents(ctx)
RegisterLibraryBuildComponents(ctx)
RegisterLibraryHeadersBuildComponents(ctx)
- genrule.RegisterGenruleBuildComponents(ctx)
ctx.RegisterModuleType("toolchain_library", ToolchainLibraryFactory)
ctx.RegisterModuleType("llndk_library", LlndkLibraryFactory)
@@ -591,6 +590,7 @@ func TestConfig(buildDir string, os android.OsType, env map[string]string,
func CreateTestContext(config android.Config) *android.TestContext {
ctx := android.NewTestArchContext(config)
+ genrule.RegisterGenruleBuildComponents(ctx)
ctx.RegisterModuleType("cc_fuzz", FuzzFactory)
ctx.RegisterModuleType("cc_test", TestFactory)
ctx.RegisterModuleType("cc_test_library", TestLibraryFactory)
diff --git a/cc/tidy.go b/cc/tidy.go
index 251c67b07..616cf8ab4 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -42,6 +42,21 @@ type tidyFeature struct {
Properties TidyProperties
}
+var quotedFlagRegexp, _ = regexp.Compile(`^-?-[^=]+=('|").*('|")$`)
+
+// When passing flag -name=value, if user add quotes around 'value',
+// the quotation marks will be preserved by NinjaAndShellEscapeList
+// and the 'value' string with quotes won't work like the intended value.
+// So here we report an error if -*='*' is found.
+func checkNinjaAndShellEscapeList(ctx ModuleContext, prop string, slice []string) []string {
+ for _, s := range slice {
+ if quotedFlagRegexp.MatchString(s) {
+ ctx.PropertyErrorf(prop, "Extra quotes in: %s", s)
+ }
+ }
+ return proptools.NinjaAndShellEscapeList(slice)
+}
+
func (tidy *tidyFeature) props() []interface{} {
return []interface{}{&tidy.Properties}
}
@@ -74,8 +89,8 @@ func (tidy *tidyFeature) flags(ctx ModuleContext, flags Flags) Flags {
if len(withTidyFlags) > 0 {
flags.TidyFlags = append(flags.TidyFlags, withTidyFlags)
}
- esc := proptools.NinjaAndShellEscapeList
- flags.TidyFlags = append(flags.TidyFlags, esc(tidy.Properties.Tidy_flags)...)
+ esc := checkNinjaAndShellEscapeList
+ flags.TidyFlags = append(flags.TidyFlags, esc(ctx, "tidy_flags", tidy.Properties.Tidy_flags)...)
// If TidyFlags does not contain -header-filter, add default header filter.
// Find the substring because the flag could also appear as --header-filter=...
// and with or without single or double quotes.
@@ -119,7 +134,7 @@ func (tidy *tidyFeature) flags(ctx ModuleContext, flags Flags) Flags {
tidyChecks += config.TidyChecksForDir(ctx.ModuleDir())
}
if len(tidy.Properties.Tidy_checks) > 0 {
- tidyChecks = tidyChecks + "," + strings.Join(esc(
+ tidyChecks = tidyChecks + "," + strings.Join(esc(ctx, "tidy_checks",
config.ClangRewriteTidyChecks(tidy.Properties.Tidy_checks)), ",")
}
if ctx.Windows() {
@@ -165,7 +180,7 @@ func (tidy *tidyFeature) flags(ctx ModuleContext, flags Flags) Flags {
flags.TidyFlags = append(flags.TidyFlags, "-warnings-as-errors=-*")
}
} else if len(tidy.Properties.Tidy_checks_as_errors) > 0 {
- tidyChecksAsErrors := "-warnings-as-errors=" + strings.Join(esc(tidy.Properties.Tidy_checks_as_errors), ",")
+ tidyChecksAsErrors := "-warnings-as-errors=" + strings.Join(esc(ctx, "tidy_checks_as_errors", tidy.Properties.Tidy_checks_as_errors), ",")
flags.TidyFlags = append(flags.TidyFlags, tidyChecksAsErrors)
}
return flags
diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go
index 7e283fb89..083327740 100644
--- a/cc/vendor_snapshot_test.go
+++ b/cc/vendor_snapshot_test.go
@@ -416,7 +416,13 @@ func TestVendorSnapshotUse(t *testing.T) {
name: "libvendor",
version: "BOARD",
target_arch: "arm64",
+ compile_multilib: "64",
vendor: true,
+ shared_libs: [
+ "libvendor_without_snapshot",
+ "libvendor_available",
+ "libvndk",
+ ],
arch: {
arm64: {
src: "libvendor.so",
diff --git a/cmd/soong_build/Android.bp b/cmd/soong_build/Android.bp
index 6a0a87bc6..9f0922449 100644
--- a/cmd/soong_build/Android.bp
+++ b/cmd/soong_build/Android.bp
@@ -25,7 +25,6 @@ bootstrap_go_binary {
"soong",
"soong-android",
"soong-bp2build",
- "soong-env",
"soong-ui-metrics_proto",
],
srcs: [
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index c17e23d3a..4586f44a6 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -21,6 +21,7 @@ import (
"path/filepath"
"strings"
+ "android/soong/shared"
"github.com/google/blueprint/bootstrap"
"android/soong/android"
@@ -28,13 +29,21 @@ import (
)
var (
+ topDir string
+ outDir string
docFile string
bazelQueryViewDir string
+ delveListen string
+ delvePath string
)
func init() {
+ flag.StringVar(&topDir, "top", "", "Top directory of the Android source tree")
+ flag.StringVar(&outDir, "out", "", "Soong output directory (usually $TOP/out/soong)")
+ flag.StringVar(&delveListen, "delve_listen", "", "Delve port to listen on for debugging")
+ flag.StringVar(&delvePath, "delve_path", "", "Path to Delve. Only used if --delve_listen is set")
flag.StringVar(&docFile, "soong_docs", "", "build documentation file to output")
- flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory")
+ flag.StringVar(&bazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory relative to --top")
}
func newNameResolver(config android.Config) *android.NameResolver {
@@ -80,18 +89,23 @@ func newConfig(srcDir string) android.Config {
}
func main() {
- android.ReexecWithDelveMaybe()
flag.Parse()
+ shared.ReexecWithDelveMaybe(delveListen, delvePath)
+ android.InitSandbox(topDir)
+ android.InitEnvironment(shared.JoinPath(topDir, outDir, "soong.environment.available"))
+
// The top-level Blueprints file is passed as the first argument.
srcDir := filepath.Dir(flag.Arg(0))
var ctx *android.Context
configuration := newConfig(srcDir)
extraNinjaDeps := []string{configuration.ProductVariablesFileName}
- // Read the SOONG_DELVE again through configuration so that there is a dependency on the environment variable
- // and soong_build will rerun when it is set for the first time.
- if listen := configuration.Getenv("SOONG_DELVE"); listen != "" {
+ // These two are here so that we restart a non-debugged soong_build when the
+ // user sets SOONG_DELVE the first time.
+ configuration.Getenv("SOONG_DELVE")
+ configuration.Getenv("SOONG_DELVE_PATH")
+ if shared.IsDebugging() {
// Add a non-existent file to the dependencies so that soong_build will rerun when the debugger is
// enabled even if it completed successfully.
extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve"))
@@ -134,7 +148,10 @@ func main() {
// Convert the Soong module graph into Bazel BUILD files.
if bazelQueryViewDir != "" {
- if err := createBazelQueryView(ctx, bazelQueryViewDir); err != nil {
+ // Run the code-generation phase to convert BazelTargetModules to BUILD files.
+ codegenContext := bp2build.NewCodegenContext(configuration, *ctx, bp2build.QueryView)
+ absoluteQueryViewDir := shared.JoinPath(topDir, bazelQueryViewDir)
+ if err := createBazelQueryView(codegenContext, absoluteQueryViewDir); err != nil {
fmt.Fprintf(os.Stderr, "%s", err)
os.Exit(1)
}
@@ -188,9 +205,15 @@ func runBp2Build(srcDir string, configuration android.Config) {
// from the regular Modules.
bootstrap.Main(bp2buildCtx.Context, configuration, extraNinjaDeps...)
- // Run the code-generation phase to convert BazelTargetModules to BUILD files.
+ // Run the code-generation phase to convert BazelTargetModules to BUILD files
+ // and print conversion metrics to the user.
codegenContext := bp2build.NewCodegenContext(configuration, *bp2buildCtx, bp2build.Bp2Build)
- bp2build.Codegen(codegenContext)
+ metrics := bp2build.Codegen(codegenContext)
+
+ // Only report metrics when in bp2build mode. The metrics aren't relevant
+ // for queryview, since that's a total repo-wide conversion and there's a
+ // 1:1 mapping for each module.
+ metrics.Print()
// Workarounds to support running bp2build in a clean AOSP checkout with no
// prior builds, and exiting early as soon as the BUILD files get generated,
diff --git a/cmd/soong_build/queryview.go b/cmd/soong_build/queryview.go
index dc0b3234e..0a77d67a9 100644
--- a/cmd/soong_build/queryview.go
+++ b/cmd/soong_build/queryview.go
@@ -22,9 +22,12 @@ import (
"path/filepath"
)
-func createBazelQueryView(ctx *android.Context, bazelQueryViewDir string) error {
+func createBazelQueryView(ctx bp2build.CodegenContext, bazelQueryViewDir string) error {
ruleShims := bp2build.CreateRuleShims(android.ModuleTypeFactories())
- buildToTargets := bp2build.GenerateBazelTargets(*ctx, bp2build.QueryView)
+
+ // Ignore metrics reporting for queryview, since queryview is already a full-repo
+ // conversion and can use data from bazel query directly.
+ buildToTargets, _ := bp2build.GenerateBazelTargets(ctx)
filesToWrite := bp2build.CreateBazelFiles(ruleShims, buildToTargets, bp2build.QueryView)
for _, f := range filesToWrite {
diff --git a/cmd/soong_env/soong_env.go b/cmd/soong_env/soong_env.go
deleted file mode 100644
index 8020b17a0..000000000
--- a/cmd/soong_env/soong_env.go
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2015 Google Inc. All rights reserved.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// soong_env determines if the given soong environment file (usually ".soong.environment") is stale
-// by comparing its contents to the current corresponding environment variable values.
-// It fails if the file cannot be opened or corrupted, or its contents differ from the current
-// values.
-
-package main
-
-import (
- "flag"
- "fmt"
- "os"
-
- "android/soong/env"
-)
-
-func usage() {
- fmt.Fprintf(os.Stderr, "usage: soong_env env_file\n")
- fmt.Fprintf(os.Stderr, "exits with success if the environment varibles in env_file match\n")
- fmt.Fprintf(os.Stderr, "the current environment\n")
- flag.PrintDefaults()
- os.Exit(2)
-}
-
-// This is a simple executable packaging, and the real work happens in env.StaleEnvFile.
-func main() {
- flag.Parse()
-
- if flag.NArg() != 1 {
- usage()
- }
-
- stale, err := env.StaleEnvFile(flag.Arg(0))
- if err != nil {
- fmt.Fprintf(os.Stderr, "error: %s\n", err.Error())
- os.Exit(1)
- }
-
- if stale {
- os.Exit(1)
- }
-
- os.Exit(0)
-}
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 74ede68b1..1c5e78ad6 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -25,6 +25,7 @@ import (
"strings"
"time"
+ "android/soong/shared"
"android/soong/ui/build"
"android/soong/ui/logger"
"android/soong/ui/metrics"
@@ -118,6 +119,8 @@ func inList(s string, list []string) bool {
// Command is the type of soong_ui execution. Only one type of
// execution is specified. The args are specific to the command.
func main() {
+ shared.ReexecWithDelveMaybe(os.Getenv("SOONG_UI_DELVE"), shared.ResolveDelveBinary())
+
buildStarted := time.Now()
c, args, err := getCommand(os.Args)
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index 36a5e2aa2..888466a2f 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -85,7 +85,7 @@ type GlobalConfig struct {
Dex2oatImageXmx string // max heap size for dex2oat for the boot image
Dex2oatImageXms string // initial heap size for dex2oat for the boot image
- // If true, downgrade the compiler filter of dexpreopt to "extract" when verify_uses_libraries
+ // If true, downgrade the compiler filter of dexpreopt to "verify" when verify_uses_libraries
// check fails, instead of failing the build. This will disable any AOT-compilation.
//
// The intended use case for this flag is to have a smoother migration path for the Java
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 6e0fe01f9..fdb00bd89 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -288,12 +288,9 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
} else {
// Other libraries or APKs for which the exact <uses-library> list is unknown.
- // Pass special class loader context to skip the classpath and collision check.
- // This will get removed once LOCAL_USES_LIBRARIES is enforced.
- // Right now LOCAL_USES_LIBRARIES is opt in, for the case where it's not specified we still default
- // to the &.
+ // We assume the class loader context is empty.
rule.Command().
- Text(`class_loader_context_arg=--class-loader-context=\&`).
+ Text(`class_loader_context_arg=--class-loader-context=PCL[]`).
Text(`stored_class_loader_context_arg=""`)
}
@@ -369,11 +366,11 @@ func dexpreoptCommand(ctx android.PathContext, globalSoong *GlobalSoongConfig, g
}
if module.EnforceUsesLibraries {
// If the verify_uses_libraries check failed (in this case status file contains a
- // non-empty error message), then use "extract" compiler filter to avoid compiling any
+ // non-empty error message), then use "verify" compiler filter to avoid compiling any
// code (it would be rejected on device because of a class loader context mismatch).
cmd.Text("--compiler-filter=$(if test -s ").
Input(module.EnforceUsesLibrariesStatusFile).
- Text(" ; then echo extract ; else echo " + compilerFilter + " ; fi)")
+ Text(" ; then echo verify ; else echo " + compilerFilter + " ; fi)")
} else {
cmd.FlagWithArg("--compiler-filter=", compilerFilter)
}
diff --git a/env/Android.bp b/env/Android.bp
deleted file mode 100644
index c6a97b1e6..000000000
--- a/env/Android.bp
+++ /dev/null
@@ -1,11 +0,0 @@
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-bootstrap_go_package {
- name: "soong-env",
- pkgPath: "android/soong/env",
- srcs: [
- "env.go",
- ],
-}
diff --git a/filesystem/Android.bp b/filesystem/Android.bp
index 42a4c88b5..dcdbdcf43 100644
--- a/filesystem/Android.bp
+++ b/filesystem/Android.bp
@@ -13,6 +13,7 @@ bootstrap_go_package {
srcs: [
"bootimg.go",
"filesystem.go",
+ "logical_partition.go",
],
testSrcs: [
],
diff --git a/filesystem/bootimg.go b/filesystem/bootimg.go
index 29e83da07..764f0452b 100644
--- a/filesystem/bootimg.go
+++ b/filesystem/bootimg.go
@@ -107,14 +107,8 @@ func (b *bootimg) partitionName() string {
}
func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- var unsignedOutput android.OutputPath
- if proptools.Bool(b.properties.Vendor_boot) {
- unsignedOutput = b.buildVendorBootImage(ctx)
- } else {
- // TODO(jiyong): fix this
- ctx.PropertyErrorf("vendor_boot", "only vendor_boot:true is supported")
- return
- }
+ vendor := proptools.Bool(b.properties.Vendor_boot)
+ unsignedOutput := b.buildBootImage(ctx, vendor)
if proptools.Bool(b.properties.Use_avb) {
b.output = b.signImage(ctx, unsignedOutput)
@@ -126,17 +120,24 @@ func (b *bootimg) GenerateAndroidBuildActions(ctx android.ModuleContext) {
ctx.InstallFile(b.installDir, b.installFileName(), b.output)
}
-func (b *bootimg) buildVendorBootImage(ctx android.ModuleContext) android.OutputPath {
+func (b *bootimg) buildBootImage(ctx android.ModuleContext, vendor bool) android.OutputPath {
output := android.PathForModuleOut(ctx, "unsigned", b.installFileName()).OutputPath
builder := android.NewRuleBuilder(pctx, ctx)
cmd := builder.Command().BuiltTool("mkbootimg")
- kernel := android.OptionalPathForModuleSrc(ctx, b.properties.Kernel_prebuilt)
- if kernel.Valid() {
+ kernel := proptools.String(b.properties.Kernel_prebuilt)
+ if vendor && kernel != "" {
ctx.PropertyErrorf("kernel_prebuilt", "vendor_boot partition can't have kernel")
return output
}
+ if !vendor && kernel == "" {
+ ctx.PropertyErrorf("kernel_prebuilt", "boot partition must have kernel")
+ return output
+ }
+ if kernel != "" {
+ cmd.FlagWithInput("--kernel ", android.PathForModuleSrc(ctx, kernel))
+ }
dtbName := proptools.String(b.properties.Dtb_prebuilt)
if dtbName == "" {
@@ -148,7 +149,11 @@ func (b *bootimg) buildVendorBootImage(ctx android.ModuleContext) android.Output
cmdline := proptools.String(b.properties.Cmdline)
if cmdline != "" {
- cmd.FlagWithArg("--vendor_cmdline ", "\""+cmdline+"\"")
+ flag := "--cmdline "
+ if vendor {
+ flag = "--vendor_cmdline "
+ }
+ cmd.FlagWithArg(flag, "\""+proptools.ShellEscape(cmdline)+"\"")
}
headerVersion := proptools.String(b.properties.Header_version)
@@ -174,15 +179,23 @@ func (b *bootimg) buildVendorBootImage(ctx android.ModuleContext) android.Output
}
ramdisk := ctx.GetDirectDepWithTag(ramdiskName, bootimgRamdiskDep)
if filesystem, ok := ramdisk.(*filesystem); ok {
- cmd.FlagWithInput("--vendor_ramdisk ", filesystem.OutputPath())
+ flag := "--ramdisk "
+ if vendor {
+ flag = "--vendor_ramdisk "
+ }
+ cmd.FlagWithInput(flag, filesystem.OutputPath())
} else {
ctx.PropertyErrorf("ramdisk", "%q is not android_filesystem module", ramdisk.Name())
return output
}
- cmd.FlagWithOutput("--vendor_boot ", output)
+ flag := "--output "
+ if vendor {
+ flag = "--vendor_boot "
+ }
+ cmd.FlagWithOutput(flag, output)
- builder.Build("build_vendor_bootimg", fmt.Sprintf("Creating %s", b.BaseModuleName()))
+ builder.Build("build_bootimg", fmt.Sprintf("Creating %s", b.BaseModuleName()))
return output
}
diff --git a/filesystem/logical_partition.go b/filesystem/logical_partition.go
new file mode 100644
index 000000000..e547203bc
--- /dev/null
+++ b/filesystem/logical_partition.go
@@ -0,0 +1,210 @@
+// Copyright (C) 2021 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package filesystem
+
+import (
+ "fmt"
+ "strconv"
+
+ "github.com/google/blueprint/proptools"
+
+ "android/soong/android"
+)
+
+func init() {
+ android.RegisterModuleType("logical_partition", logicalPartitionFactory)
+}
+
+type logicalPartition struct {
+ android.ModuleBase
+
+ properties logicalPartitionProperties
+
+ output android.OutputPath
+ installDir android.InstallPath
+}
+
+type logicalPartitionProperties struct {
+ // Set the name of the output. Defaults to <module_name>.img.
+ Stem *string
+
+ // Total size of the logical partition
+ Size *string
+
+ // List of groups. A group defines a fixed sized region. It can host one or more logical
+ // partitions and their total size is limited by the size of the group they are in.
+ Groups []groupProperties
+
+ // Whether the output is a sparse image or not. Default is false.
+ Sparse *bool
+}
+
+type groupProperties struct {
+ // Name of the partition group
+ Name *string
+
+ // Size of the partition group
+ Size *string
+
+ // List of logical partitions in this group
+ Partitions []partitionProperties
+}
+
+type partitionProperties struct {
+ // Name of the partition
+ Name *string
+
+ // Filesystem that is placed on the partition
+ Filesystem *string `android:"path"`
+}
+
+// logical_partition is a partition image which has one or more logical partitions in it.
+func logicalPartitionFactory() android.Module {
+ module := &logicalPartition{}
+ module.AddProperties(&module.properties)
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ return module
+}
+
+func (l *logicalPartition) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // do nothing
+}
+
+func (l *logicalPartition) installFileName() string {
+ return proptools.StringDefault(l.properties.Stem, l.BaseModuleName()+".img")
+}
+
+func (l *logicalPartition) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ builder := android.NewRuleBuilder(pctx, ctx)
+
+ // Sparse the filesystem images and calculate their sizes
+ sparseImages := make(map[string]android.OutputPath)
+ sparseImageSizes := make(map[string]android.OutputPath)
+ for _, group := range l.properties.Groups {
+ for _, part := range group.Partitions {
+ sparseImg, sizeTxt := sparseFilesystem(ctx, part, builder)
+ pName := proptools.String(part.Name)
+ sparseImages[pName] = sparseImg
+ sparseImageSizes[pName] = sizeTxt
+ }
+ }
+
+ cmd := builder.Command().BuiltTool("lpmake")
+
+ size := proptools.String(l.properties.Size)
+ if size == "" {
+ ctx.PropertyErrorf("size", "must be set")
+ }
+ if _, err := strconv.Atoi(size); err != nil {
+ ctx.PropertyErrorf("size", "must be a number")
+ }
+ cmd.FlagWithArg("--device-size=", size)
+
+ // TODO(jiyong): consider supporting A/B devices. Then we need to adjust num of slots.
+ cmd.FlagWithArg("--metadata-slots=", "2")
+ cmd.FlagWithArg("--metadata-size=", "65536")
+
+ if proptools.Bool(l.properties.Sparse) {
+ cmd.Flag("--sparse")
+ }
+
+ groupNames := make(map[string]bool)
+ partitionNames := make(map[string]bool)
+
+ for _, group := range l.properties.Groups {
+ gName := proptools.String(group.Name)
+ if gName == "" {
+ ctx.PropertyErrorf("groups.name", "must be set")
+ }
+ if _, ok := groupNames[gName]; ok {
+ ctx.PropertyErrorf("group.name", "already exists")
+ } else {
+ groupNames[gName] = true
+ }
+ gSize := proptools.String(group.Size)
+ if gSize == "" {
+ ctx.PropertyErrorf("groups.size", "must be set")
+ }
+ if _, err := strconv.Atoi(gSize); err != nil {
+ ctx.PropertyErrorf("groups.size", "must be a number")
+ }
+ cmd.FlagWithArg("--group=", gName+":"+gSize)
+
+ for _, part := range group.Partitions {
+ pName := proptools.String(part.Name)
+ if pName == "" {
+ ctx.PropertyErrorf("groups.partitions.name", "must be set")
+ }
+ if _, ok := partitionNames[pName]; ok {
+ ctx.PropertyErrorf("groups.partitions.name", "already exists")
+ } else {
+ partitionNames[pName] = true
+ }
+ // Get size of the partition by reading the -size.txt file
+ pSize := fmt.Sprintf("$(cat %s)", sparseImageSizes[pName])
+ cmd.FlagWithArg("--partition=", fmt.Sprintf("%s:readonly:%s:%s", pName, pSize, gName))
+ cmd.FlagWithInput("--image="+pName+"=", sparseImages[pName])
+ }
+ }
+
+ l.output = android.PathForModuleOut(ctx, l.installFileName()).OutputPath
+ cmd.FlagWithOutput("--output=", l.output)
+
+ builder.Build("build_logical_partition", fmt.Sprintf("Creating %s", l.BaseModuleName()))
+
+ l.installDir = android.PathForModuleInstall(ctx, "etc")
+ ctx.InstallFile(l.installDir, l.installFileName(), l.output)
+}
+
+// Add a rule that converts the filesystem for the given partition to the given rule builder. The
+// path to the sparse file and the text file having the size of the partition are returned.
+func sparseFilesystem(ctx android.ModuleContext, p partitionProperties, builder *android.RuleBuilder) (sparseImg android.OutputPath, sizeTxt android.OutputPath) {
+ img := android.PathForModuleSrc(ctx, proptools.String(p.Filesystem))
+ name := proptools.String(p.Name)
+ sparseImg = android.PathForModuleOut(ctx, name+".img").OutputPath
+
+ builder.Temporary(sparseImg)
+ builder.Command().BuiltTool("img2simg").Input(img).Output(sparseImg)
+
+ sizeTxt = android.PathForModuleOut(ctx, name+"-size.txt").OutputPath
+ builder.Temporary(sizeTxt)
+ builder.Command().BuiltTool("sparse_img").Flag("--get_partition_size").Input(sparseImg).
+ Text("| ").Text("tr").FlagWithArg("-d ", "'\n'").
+ Text("> ").Output(sizeTxt)
+
+ return sparseImg, sizeTxt
+}
+
+var _ android.AndroidMkEntriesProvider = (*logicalPartition)(nil)
+
+// Implements android.AndroidMkEntriesProvider
+func (l *logicalPartition) AndroidMkEntries() []android.AndroidMkEntries {
+ return []android.AndroidMkEntries{android.AndroidMkEntries{
+ Class: "ETC",
+ OutputFile: android.OptionalPathForPath(l.output),
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetString("LOCAL_MODULE_PATH", l.installDir.ToMakePath().String())
+ entries.SetString("LOCAL_INSTALLED_MODULE_STEM", l.installFileName())
+ },
+ },
+ }}
+}
+
+var _ Filesystem = (*logicalPartition)(nil)
+
+func (l *logicalPartition) OutputPath() android.Path {
+ return l.output
+}
diff --git a/genrule/genrule.go b/genrule/genrule.go
index 9fa6c484f..50c77cf9a 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -124,14 +124,12 @@ type generatorProperties struct {
// input files to exclude
Exclude_srcs []string `android:"path,arch_variant"`
-
- // Properties for Bazel migration purposes.
- bazel.Properties
}
type Module struct {
android.ModuleBase
android.DefaultableModuleBase
+ android.BazelModuleBase
android.ApexModuleBase
// For other packages to make their own genrules with extra
@@ -208,7 +206,7 @@ func toolDepsMutator(ctx android.BottomUpMutatorContext) {
// Returns true if information was available from Bazel, false if bazel invocation still needs to occur.
func (c *Module) generateBazelBuildActions(ctx android.ModuleContext, label string) bool {
bazelCtx := ctx.Config().BazelContext
- filePaths, ok := bazelCtx.GetAllFiles(label)
+ filePaths, ok := bazelCtx.GetAllFiles(label, ctx.Arch().ArchType)
if ok {
var bazelOutputFiles android.Paths
for _, bazelOutputFile := range filePaths {
@@ -519,7 +517,7 @@ func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
g.outputFiles = outputFiles.Paths()
- bazelModuleLabel := g.properties.Bazel_module.Label
+ bazelModuleLabel := g.GetBazelLabel()
bazelActionsUsed := false
if ctx.Config().BazelContext.BazelEnabled() && len(bazelModuleLabel) > 0 {
bazelActionsUsed = g.generateBazelBuildActions(ctx, bazelModuleLabel)
@@ -771,6 +769,7 @@ func GenRuleFactory() android.Module {
m := NewGenRule()
android.InitAndroidModule(m)
android.InitDefaultableModule(m)
+ android.InitBazelModule(m)
return m
}
@@ -800,7 +799,7 @@ func BazelGenruleFactory() android.Module {
func GenruleBp2Build(ctx android.TopDownMutatorContext) {
m, ok := ctx.Module().(*Module)
- if !ok || !m.properties.Bazel_module.Bp2build_available {
+ if !ok || !m.ConvertWithBp2build() {
return
}
@@ -853,10 +852,12 @@ func GenruleBp2Build(ctx android.TopDownMutatorContext) {
Tools: tools,
}
- props := bazel.NewBazelTargetModuleProperties(m.Name(), "genrule", "")
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "genrule",
+ }
// Create the BazelTargetModule.
- ctx.CreateBazelTargetModule(BazelGenruleFactory, props, attrs)
+ ctx.CreateBazelTargetModule(BazelGenruleFactory, m.Name(), props, attrs)
}
func (m *bazelGenrule) Name() string {
diff --git a/java/Android.bp b/java/Android.bp
index 9bfd009c6..461b16d58 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -58,7 +58,6 @@ bootstrap_go_package {
"sdk_library.go",
"sdk_library_external.go",
"support_libraries.go",
- "sysprop.go",
"system_modules.go",
"testing.go",
"tradefed.go",
diff --git a/java/aar.go b/java/aar.go
index 602d2c49c..554ea670b 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -805,14 +805,6 @@ func (a *AARImport) HeaderJars() android.Paths {
return android.Paths{a.classpathFile}
}
-func (a *AARImport) ImplementationJars() android.Paths {
- return android.Paths{a.classpathFile}
-}
-
-func (a *AARImport) ResourceJars() android.Paths {
- return nil
-}
-
func (a *AARImport) ImplementationAndResourcesJars() android.Paths {
return android.Paths{a.classpathFile}
}
@@ -825,22 +817,10 @@ func (a *AARImport) DexJarInstallPath() android.Path {
return nil
}
-func (a *AARImport) AidlIncludeDirs() android.Paths {
- return nil
-}
-
func (a *AARImport) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
return nil
}
-func (d *AARImport) ExportedPlugins() (android.Paths, []string, bool) {
- return nil, nil, false
-}
-
-func (a *AARImport) SrcJarArgs() ([]string, android.Paths) {
- return nil, nil
-}
-
var _ android.ApexModule = (*AARImport)(nil)
// Implements android.ApexModule
diff --git a/java/android_manifest.go b/java/android_manifest.go
index c76bb2fda..b30f3d2c8 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -91,7 +91,7 @@ func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext
if err != nil {
ctx.ModuleErrorf("invalid targetSdkVersion: %s", err)
}
- if UseApiFingerprint(ctx) {
+ if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
targetSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
deps = append(deps, ApiFingerprintPath(ctx))
}
@@ -100,7 +100,7 @@ func manifestFixer(ctx android.ModuleContext, manifest android.Path, sdkContext
if err != nil {
ctx.ModuleErrorf("invalid minSdkVersion: %s", err)
}
- if UseApiFingerprint(ctx) {
+ if UseApiFingerprint(ctx) && ctx.ModuleName() != "framework-res" {
minSdkVersion = ctx.Config().PlatformSdkCodename() + fmt.Sprintf(".$$(cat %s)", ApiFingerprintPath(ctx).String())
deps = append(deps, ApiFingerprintPath(ctx))
}
diff --git a/java/androidmk.go b/java/androidmk.go
index e7261f894..3d3eae530 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -220,7 +220,7 @@ func (prebuilt *DexImport) AndroidMkEntries() []android.AndroidMkEntries {
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
- OutputFile: android.OptionalPathForPath(prebuilt.maybeStrippedDexJarFile),
+ OutputFile: android.OptionalPathForPath(prebuilt.dexJarFile),
Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
@@ -287,9 +287,16 @@ func (binary *Binary) AndroidMkEntries() []android.AndroidMkEntries {
},
}}
} else {
+ outputFile := binary.wrapperFile
+ // Have Make installation trigger Soong installation by using Soong's install path as
+ // the output file.
+ if binary.Host() {
+ outputFile = binary.binaryFile
+ }
+
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "EXECUTABLES",
- OutputFile: android.OptionalPathForPath(binary.wrapperFile),
+ OutputFile: android.OptionalPathForPath(outputFile),
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_STRIP_MODULE", false)
diff --git a/java/app.go b/java/app.go
index 8287533e0..0660aa62e 100755
--- a/java/app.go
+++ b/java/app.go
@@ -469,7 +469,7 @@ func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
a.Module.compile(ctx, a.aaptSrcJar)
}
- return a.maybeStrippedDexJarFile
+ return a.dexJarFile
}
func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, ctx android.ModuleContext) android.WritablePath {
@@ -1217,6 +1217,15 @@ func (u *usesLibrary) presentOptionalUsesLibs(ctx android.BaseModuleContext) []s
return optionalUsesLibs
}
+// Helper function to replace string in a list.
+func replaceInList(list []string, oldstr, newstr string) {
+ for i, str := range list {
+ if str == oldstr {
+ list[i] = newstr
+ }
+ }
+}
+
// Returns a map of module names of shared library dependencies to the paths
// to their dex jars on host and on device.
func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext) dexpreopt.ClassLoaderContextMap {
@@ -1227,7 +1236,16 @@ func (u *usesLibrary) classLoaderContextForUsesLibDeps(ctx android.ModuleContext
if tag, ok := ctx.OtherModuleDependencyTag(m).(usesLibraryDependencyTag); ok {
dep := ctx.OtherModuleName(m)
if lib, ok := m.(UsesLibraryDependency); ok {
- clcMap.AddContext(ctx, tag.sdkVersion, dep,
+ libName := dep
+ if ulib, ok := m.(ProvidesUsesLib); ok && ulib.ProvidesUsesLib() != nil {
+ libName = *ulib.ProvidesUsesLib()
+ // Replace module name with library name in `uses_libs`/`optional_uses_libs`
+ // in order to pass verify_uses_libraries check (which compares these
+ // properties against library names written in the manifest).
+ replaceInList(u.usesLibraryProperties.Uses_libs, dep, libName)
+ replaceInList(u.usesLibraryProperties.Optional_uses_libs, dep, libName)
+ }
+ clcMap.AddContext(ctx, tag.sdkVersion, libName,
lib.DexJarBuildPath(), lib.DexJarInstallPath(), lib.ClassLoaderContexts())
} else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{dep})
@@ -1262,6 +1280,14 @@ func (u *usesLibrary) verifyUsesLibrariesManifest(ctx android.ModuleContext, man
outputFile := android.PathForModuleOut(ctx, "manifest_check", "AndroidManifest.xml")
statusFile := dexpreopt.UsesLibrariesStatusFile(ctx)
+ // Disable verify_uses_libraries check if dexpreopt is globally disabled. Without dexpreopt the
+ // check is not necessary, and although it is good to have, it is difficult to maintain on
+ // non-linux build platforms where dexpreopt is generally disabled (the check may fail due to
+ // various unrelated reasons, such as a failure to get manifest from an APK).
+ if dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
+ return manifest
+ }
+
rule := android.NewRuleBuilder(pctx, ctx)
cmd := rule.Command().BuiltTool("manifest_check").
Flag("--enforce-uses-libraries").
@@ -1292,6 +1318,14 @@ func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk andr
outputFile := android.PathForModuleOut(ctx, "verify_uses_libraries", apk.Base())
statusFile := dexpreopt.UsesLibrariesStatusFile(ctx)
+ // Disable verify_uses_libraries check if dexpreopt is globally disabled. Without dexpreopt the
+ // check is not necessary, and although it is good to have, it is difficult to maintain on
+ // non-linux build platforms where dexpreopt is generally disabled (the check may fail due to
+ // various unrelated reasons, such as a failure to get manifest from an APK).
+ if dexpreopt.GetGlobalConfig(ctx).DisablePreopt {
+ return apk
+ }
+
rule := android.NewRuleBuilder(pctx, ctx)
aapt := ctx.Config().HostToolPath(ctx, "aapt")
rule.Command().
diff --git a/java/app_import.go b/java/app_import.go
index 59eb10a9b..d38f63e06 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -67,6 +67,9 @@ type AndroidAppImportProperties struct {
// module name in the form ":module". Should be empty if presigned or default_dev_cert is set.
Certificate *string
+ // Names of extra android_app_certificate modules to sign the apk with in the form ":module".
+ Additional_certificates []string
+
// Set this flag to true if the prebuilt apk is already signed. The certificate property must not
// be set for presigned modules.
Presigned *bool
@@ -156,6 +159,16 @@ func (a *AndroidAppImport) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.AddDependency(ctx.Module(), certificateTag, cert)
}
+ for _, cert := range a.properties.Additional_certificates {
+ cert = android.SrcIsModule(cert)
+ if cert != "" {
+ ctx.AddDependency(ctx.Module(), certificateTag, cert)
+ } else {
+ ctx.PropertyErrorf("additional_certificates",
+ `must be names of android_app_certificate modules in the form ":module"`)
+ }
+ }
+
a.usesLibrary.deps(ctx, !a.isPrebuiltFrameworkRes())
}
@@ -244,10 +257,6 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
srcApk := a.prebuilt.SingleSourcePath(ctx)
- if a.usesLibrary.enforceUsesLibraries() {
- srcApk = a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
- }
-
// TODO: Install or embed JNI libraries
// Uncompress JNI libraries in the apk
@@ -276,6 +285,10 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
a.dexpreopter.enforceUsesLibs = a.usesLibrary.enforceUsesLibraries()
a.dexpreopter.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
+ if a.usesLibrary.enforceUsesLibraries() {
+ srcApk = a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
+ }
+
a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
if a.dexpreopter.uncompressedDex {
dexUncompressed := android.PathForModuleOut(ctx, "dex-uncompressed", ctx.ModuleName()+".apk")
@@ -303,9 +316,6 @@ func (a *AndroidAppImport) generateAndroidBuildActions(ctx android.ModuleContext
// If the certificate property is empty at this point, default_dev_cert must be set to true.
// Which makes processMainCert's behavior for the empty cert string WAI.
certificates = processMainCert(a.ModuleBase, String(a.properties.Certificate), certificates, ctx)
- if len(certificates) != 1 {
- ctx.ModuleErrorf("Unexpected number of certificates were extracted: %q", certificates)
- }
a.certificate = certificates[0]
signed := android.PathForModuleOut(ctx, "signed", apkFilename)
var lineageFile android.Path
diff --git a/java/app_import_test.go b/java/app_import_test.go
index dc31d07c9..00406aa2e 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -109,16 +109,30 @@ func TestAndroidAppImport_SigningLineage(t *testing.T) {
name: "foo",
apk: "prebuilts/apk/app.apk",
certificate: "platform",
+ additional_certificates: [":additional_certificate"],
lineage: "lineage.bin",
}
+
+ android_app_certificate {
+ name: "additional_certificate",
+ certificate: "cert/additional_cert",
+ }
`)
variant := ctx.ModuleForTests("foo", "android_common")
- // Check cert signing lineage flag.
signedApk := variant.Output("signed/foo.apk")
+ // Check certificates
+ certificatesFlag := signedApk.Args["certificates"]
+ expected := "build/make/target/product/security/platform.x509.pem " +
+ "build/make/target/product/security/platform.pk8 " +
+ "cert/additional_cert.x509.pem cert/additional_cert.pk8"
+ if expected != certificatesFlag {
+ t.Errorf("Incorrect certificates flags, expected: %q, got: %q", expected, certificatesFlag)
+ }
+ // Check cert signing lineage flag.
signingFlag := signedApk.Args["flags"]
- expected := "--lineage lineage.bin"
+ expected = "--lineage lineage.bin"
if expected != signingFlag {
t.Errorf("Incorrect signing flags, expected: %q, got: %q", expected, signingFlag)
}
diff --git a/java/app_test.go b/java/app_test.go
index b1abe3db3..f41047aa6 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -685,6 +685,51 @@ func TestLibraryAssets(t *testing.T) {
}
}
+func TestAppJavaResources(t *testing.T) {
+ bp := `
+ android_app {
+ name: "foo",
+ sdk_version: "current",
+ java_resources: ["resources/a"],
+ srcs: ["a.java"],
+ }
+
+ android_app {
+ name: "bar",
+ sdk_version: "current",
+ java_resources: ["resources/a"],
+ }
+ `
+
+ ctx := testApp(t, bp)
+
+ foo := ctx.ModuleForTests("foo", "android_common")
+ fooResources := foo.Output("res/foo.jar")
+ fooDexJar := foo.Output("dex-withres/foo.jar")
+ fooDexJarAligned := foo.Output("dex-withres-aligned/foo.jar")
+ fooApk := foo.Rule("combineApk")
+
+ if g, w := fooDexJar.Inputs.Strings(), fooResources.Output.String(); !android.InList(w, g) {
+ t.Errorf("expected resource jar %q in foo dex jar inputs %q", w, g)
+ }
+
+ if g, w := fooDexJarAligned.Input.String(), fooDexJar.Output.String(); g != w {
+ t.Errorf("expected dex jar %q in foo aligned dex jar inputs %q", w, g)
+ }
+
+ if g, w := fooApk.Inputs.Strings(), fooDexJarAligned.Output.String(); !android.InList(w, g) {
+ t.Errorf("expected aligned dex jar %q in foo apk inputs %q", w, g)
+ }
+
+ bar := ctx.ModuleForTests("bar", "android_common")
+ barResources := bar.Output("res/bar.jar")
+ barApk := bar.Rule("combineApk")
+
+ if g, w := barApk.Inputs.Strings(), barResources.Output.String(); !android.InList(w, g) {
+ t.Errorf("expected resources jar %q in bar apk inputs %q", w, g)
+ }
+}
+
func TestAndroidResources(t *testing.T) {
testCases := []struct {
name string
@@ -2245,17 +2290,33 @@ func TestUsesLibraries(t *testing.T) {
sdk_version: "current",
}
+ // A library that has to use "provides_uses_lib", because:
+ // - it is not an SDK library
+ // - its library name is different from its module name
+ java_library {
+ name: "non-sdk-lib",
+ provides_uses_lib: "com.non.sdk.lib",
+ installable: true,
+ srcs: ["a.java"],
+ }
+
android_app {
name: "app",
srcs: ["a.java"],
- libs: ["qux", "quuz.stubs"],
+ libs: [
+ "qux",
+ "quuz.stubs"
+ ],
static_libs: [
"static-runtime-helper",
// statically linked component libraries should not pull their SDK libraries,
// so "fred" should not be added to class loader context
"fred.stubs",
],
- uses_libs: ["foo"],
+ uses_libs: [
+ "foo",
+ "non-sdk-lib"
+ ],
sdk_version: "current",
optional_uses_libs: [
"bar",
@@ -2267,7 +2328,11 @@ func TestUsesLibraries(t *testing.T) {
name: "prebuilt",
apk: "prebuilts/apk/app.apk",
certificate: "platform",
- uses_libs: ["foo", "android.test.runner"],
+ uses_libs: [
+ "foo",
+ "non-sdk-lib",
+ "android.test.runner"
+ ],
optional_uses_libs: [
"bar",
"baz",
@@ -2286,39 +2351,51 @@ func TestUsesLibraries(t *testing.T) {
prebuilt := ctx.ModuleForTests("prebuilt", "android_common")
// Test that implicit dependencies on java_sdk_library instances are passed to the manifest.
- manifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
- for _, w := range []string{"qux", "quuz", "runtime-library"} {
- if !strings.Contains(manifestFixerArgs, "--uses-library "+w) {
- t.Errorf("unexpected manifest_fixer args: wanted %q in %q", w, manifestFixerArgs)
- }
- }
-
- // Test that all libraries are verified
- cmd := app.Rule("verify_uses_libraries").RuleParams.Command
- if w := "--uses-library foo"; !strings.Contains(cmd, w) {
- t.Errorf("wanted %q in %q", w, cmd)
- }
-
- if w := "--optional-uses-library bar --optional-uses-library baz"; !strings.Contains(cmd, w) {
- t.Errorf("wanted %q in %q", w, cmd)
- }
-
- cmd = prebuilt.Rule("verify_uses_libraries").RuleParams.Command
-
- if w := `uses_library_names="foo android.test.runner"`; !strings.Contains(cmd, w) {
- t.Errorf("wanted %q in %q", w, cmd)
- }
-
- if w := `optional_uses_library_names="bar baz"`; !strings.Contains(cmd, w) {
- t.Errorf("wanted %q in %q", w, cmd)
+ // This should not include explicit `uses_libs`/`optional_uses_libs` entries.
+ actualManifestFixerArgs := app.Output("manifest_fixer/AndroidManifest.xml").Args["args"]
+ expectManifestFixerArgs := `--extract-native-libs=true ` +
+ `--uses-library qux ` +
+ `--uses-library quuz ` +
+ `--uses-library foo ` + // TODO(b/132357300): "foo" should not be passed to manifest_fixer
+ `--uses-library com.non.sdk.lib ` + // TODO(b/132357300): "com.non.sdk.lib" should not be passed to manifest_fixer
+ `--uses-library bar ` + // TODO(b/132357300): "bar" should not be passed to manifest_fixer
+ `--uses-library runtime-library`
+ if actualManifestFixerArgs != expectManifestFixerArgs {
+ t.Errorf("unexpected manifest_fixer args:\n\texpect: %q\n\tactual: %q",
+ expectManifestFixerArgs, actualManifestFixerArgs)
+ }
+
+ // Test that all libraries are verified (library order matters).
+ verifyCmd := app.Rule("verify_uses_libraries").RuleParams.Command
+ verifyArgs := `--uses-library foo ` +
+ `--uses-library com.non.sdk.lib ` +
+ `--uses-library qux ` +
+ `--uses-library quuz ` +
+ `--uses-library runtime-library ` +
+ `--optional-uses-library bar ` +
+ `--optional-uses-library baz `
+ if !strings.Contains(verifyCmd, verifyArgs) {
+ t.Errorf("wanted %q in %q", verifyArgs, verifyCmd)
+ }
+
+ // Test that all libraries are verified for an APK (library order matters).
+ verifyApkCmd := prebuilt.Rule("verify_uses_libraries").RuleParams.Command
+ verifyApkReqLibs := `uses_library_names="foo com.non.sdk.lib android.test.runner"`
+ verifyApkOptLibs := `optional_uses_library_names="bar baz"`
+ if !strings.Contains(verifyApkCmd, verifyApkReqLibs) {
+ t.Errorf("wanted %q in %q", verifyApkReqLibs, verifyApkCmd)
+ }
+ if !strings.Contains(verifyApkCmd, verifyApkOptLibs) {
+ t.Errorf("wanted %q in %q", verifyApkOptLibs, verifyApkCmd)
}
// Test that all present libraries are preopted, including implicit SDK dependencies, possibly stubs
- cmd = app.Rule("dexpreopt").RuleParams.Command
+ cmd := app.Rule("dexpreopt").RuleParams.Command
w := `--target-context-for-sdk any ` +
`PCL[/system/framework/qux.jar]#` +
`PCL[/system/framework/quuz.jar]#` +
`PCL[/system/framework/foo.jar]#` +
+ `PCL[/system/framework/non-sdk-lib.jar]#` +
`PCL[/system/framework/bar.jar]#` +
`PCL[/system/framework/runtime-library.jar]`
if !strings.Contains(cmd, w) {
@@ -2348,6 +2425,7 @@ func TestUsesLibraries(t *testing.T) {
cmd = prebuilt.Rule("dexpreopt").RuleParams.Command
if w := `--target-context-for-sdk any` +
` PCL[/system/framework/foo.jar]` +
+ `#PCL[/system/framework/non-sdk-lib.jar]` +
`#PCL[/system/framework/android.test.runner.jar]` +
`#PCL[/system/framework/bar.jar] `; !strings.Contains(cmd, w) {
t.Errorf("wanted %q in %q", w, cmd)
diff --git a/java/builder.go b/java/builder.go
index 22a891ae1..33206ceeb 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -80,6 +80,8 @@ var (
func(ctx android.PackageVarContext) string { return ctx.Config().XrefCorpusName() })
_ = pctx.VariableFunc("kytheCuEncoding",
func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuEncoding() })
+ _ = pctx.VariableFunc("kytheCuJavaSourceMax",
+ func(ctx android.PackageVarContext) string { return ctx.Config().XrefCuJavaSourceMax() })
_ = pctx.SourcePathVariable("kytheVnames", "build/soong/vnames.json")
// Run it with -add-opens=java.base/java.nio=ALL-UNNAMED to avoid JDK9's warning about
// "Illegal reflective access by com.google.protobuf.Utf8$UnsafeProcessor ...
@@ -93,6 +95,7 @@ var (
`KYTHE_CORPUS=${kytheCorpus} ` +
`KYTHE_VNAMES=${kytheVnames} ` +
`KYTHE_KZIP_ENCODING=${kytheCuEncoding} ` +
+ `KYTHE_JAVA_SOURCE_BATCH_SIZE=${kytheCuJavaSourceMax} ` +
`${config.SoongJavacWrapper} ${config.JavaCmd} ` +
`--add-opens=java.base/java.nio=ALL-UNNAMED ` +
`-jar ${config.JavaKytheExtractorJar} ` +
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index ee7d01820..39fb04a8e 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -146,14 +146,6 @@ func (d *DeviceHostConverter) HeaderJars() android.Paths {
return d.headerJars
}
-func (d *DeviceHostConverter) ImplementationJars() android.Paths {
- return d.implementationJars
-}
-
-func (d *DeviceHostConverter) ResourceJars() android.Paths {
- return d.resourceJars
-}
-
func (d *DeviceHostConverter) ImplementationAndResourcesJars() android.Paths {
return d.implementationAndResourceJars
}
@@ -174,14 +166,6 @@ func (d *DeviceHostConverter) ClassLoaderContexts() dexpreopt.ClassLoaderContext
return nil
}
-func (d *DeviceHostConverter) ExportedPlugins() (android.Paths, []string, bool) {
- return nil, nil, false
-}
-
-func (d *DeviceHostConverter) SrcJarArgs() ([]string, android.Paths) {
- return d.srcJarArgs, d.srcJarDeps
-}
-
func (d *DeviceHostConverter) JacocoReportClassesFile() android.Path {
return nil
}
diff --git a/java/dex.go b/java/dex.go
index e52fdb5d9..b2a998f78 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -260,6 +260,9 @@ func (d *dexer) r8Flags(ctx android.ModuleContext, flags javaBuilderFlags) (r8Fl
r8Flags = append(r8Flags, "--debug")
}
+ // TODO(b/180878971): missing classes should be added to the relevant builds.
+ r8Flags = append(r8Flags, "-ignorewarnings")
+
return r8Flags, r8Deps
}
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 86b189558..e94b20c55 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -210,6 +210,15 @@ import (
// apps instead of the Framework boot image extension (see DEXPREOPT_USE_ART_IMAGE and UseArtImage).
//
+var artApexNames = []string{
+ "com.android.art",
+ "com.android.art.debug",
+ "com.android.art,testing",
+ "com.google.android.art",
+ "com.google.android.art.debug",
+ "com.google.android.art.testing",
+}
+
func init() {
RegisterDexpreoptBootJarsComponents(android.InitRegistrationContext)
}
@@ -485,7 +494,14 @@ func getBootImageJar(ctx android.SingletonContext, image *bootImageConfig, modul
switch image.name {
case artBootImageName:
- if apexInfo.InApexByBaseName("com.android.art") || apexInfo.InApexByBaseName("com.android.art.debug") || apexInfo.InApexByBaseName("com.android.art,testing") {
+ inArtApex := false
+ for _, n := range artApexNames {
+ if apexInfo.InApexByBaseName(n) {
+ inArtApex = true
+ break
+ }
+ }
+ if inArtApex {
// ok: found the jar in the ART apex
} else if name == "jacocoagent" && ctx.Config().IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK") {
// exception (skip and continue): Jacoco platform variant for a coverage build
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 8f1644c7f..f0decec74 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -1203,8 +1203,14 @@ func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *a
}
func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersion javaVersion, srcs android.Paths,
- srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths, implicitsRsp android.WritablePath, sandbox bool) *android.RuleBuilderCommand {
+ srcJarList android.Path, bootclasspath, classpath classpath, sourcepaths android.Paths,
+ implicitsRsp, homeDir android.WritablePath, sandbox bool) *android.RuleBuilderCommand {
+ rule.Command().Text("rm -rf").Flag(homeDir.String())
+ rule.Command().Text("mkdir -p").Flag(homeDir.String())
+
cmd := rule.Command()
+ cmd.FlagWithArg("ANDROID_SDK_HOME=", homeDir.String())
+
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_METALAVA") {
rule.Remoteable(android.RemoteRuleSupports{RBE: true})
pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "metalava")
@@ -1214,17 +1220,21 @@ func metalavaCmd(ctx android.ModuleContext, rule *android.RuleBuilder, javaVersi
execStrategy = remoteexec.LocalExecStrategy
labels["shallow"] = "true"
}
- inputs := []string{android.PathForOutput(ctx, "host", ctx.Config().PrebuiltOS(), "framework", "metalava.jar").String()}
+ inputs := []string{
+ ctx.Config().HostJavaToolPath(ctx, "metalava").String(),
+ homeDir.String(),
+ }
if v := ctx.Config().Getenv("RBE_METALAVA_INPUTS"); v != "" {
inputs = append(inputs, strings.Split(v, ",")...)
}
cmd.Text((&remoteexec.REParams{
- Labels: labels,
- ExecStrategy: execStrategy,
- Inputs: inputs,
- RSPFile: implicitsRsp.String(),
- ToolchainInputs: []string{config.JavaCmd(ctx).String()},
- Platform: map[string]string{remoteexec.PoolKey: pool},
+ Labels: labels,
+ ExecStrategy: execStrategy,
+ Inputs: inputs,
+ RSPFile: implicitsRsp.String(),
+ ToolchainInputs: []string{config.JavaCmd(ctx).String()},
+ Platform: map[string]string{remoteexec.PoolKey: pool},
+ EnvironmentVariables: []string{"ANDROID_SDK_HOME"},
}).NoVarTemplate(ctx.Config()))
}
@@ -1302,9 +1312,9 @@ func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
implicitsRsp := android.PathForModuleOut(ctx, ctx.ModuleName()+"-"+"implicits.rsp")
-
+ homeDir := android.PathForModuleOut(ctx, "metalava-home")
cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList,
- deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths, implicitsRsp,
+ deps.bootClasspath, deps.classpath, d.Javadoc.sourcepaths, implicitsRsp, homeDir,
Bool(d.Javadoc.properties.Sandbox))
cmd.Implicits(d.Javadoc.implicits)
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index f8e41c458..208ced769 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -15,8 +15,6 @@
package java
import (
- "strings"
-
"github.com/google/blueprint"
"android/soong/android"
@@ -29,8 +27,8 @@ var hiddenAPIGenerateCSVRule = pctx.AndroidStaticRule("hiddenAPIGenerateCSV", bl
type hiddenAPI struct {
// The name of the module as it would be used in the boot jars configuration, e.g. without any
- // prebuilt_ prefix (if it is a prebuilt), without any "-hiddenapi" suffix if it just provides
- // annotations and without any ".impl" suffix if it is a java_sdk_library implementation library.
+ // prebuilt_ prefix (if it is a prebuilt) and without any ".impl" suffix if it is a
+ // java_sdk_library implementation library.
configurationName string
// True if the module containing this structure contributes to the hiddenapi information or has
@@ -49,11 +47,6 @@ type hiddenAPI struct {
// annotation information.
primary bool
- // True if the module only contains additional annotations and so does not require hiddenapi
- // information to be encoded in its dex file and should not be used to generate the
- // hiddenAPISingletonPathsStruct.stubFlags file.
- annotationsOnly bool
-
// The path to the dex jar that is in the boot class path. If this is nil then the associated
// module is not a boot jar, but could be one of the <x>-hiddenapi modules that provide additional
// annotations for the <x> boot dex jar but which do not actually provide a boot dex jar
@@ -119,55 +112,67 @@ type hiddenAPIIntf interface {
var _ hiddenAPIIntf = (*hiddenAPI)(nil)
// Initialize the hiddenapi structure
-func (h *hiddenAPI) initHiddenAPI(ctx android.BaseModuleContext, name string) {
+func (h *hiddenAPI) initHiddenAPI(ctx android.BaseModuleContext, configurationName string) {
// If hiddenapi processing is disabled treat this as inactive.
if ctx.Config().IsEnvTrue("UNSAFE_DISABLE_HIDDENAPI_FLAGS") {
return
}
- // Modules whose names are of the format <x>-hiddenapi provide hiddenapi information for the boot
- // jar module <x>. Otherwise, the module provides information for itself. Either way extract the
- // configurationName of the boot jar module.
- configurationName := strings.TrimSuffix(name, "-hiddenapi")
h.configurationName = configurationName
// It is important that hiddenapi information is only gathered for/from modules that are actually
// on the boot jars list because the runtime only enforces access to the hidden API for the
// bootclassloader. If information is gathered for modules not on the list then that will cause
// failures in the CtsHiddenApiBlocklist... tests.
- h.active = inList(configurationName, ctx.Config().BootJars())
+ module := ctx.Module()
+ h.active = isModuleInBootClassPath(ctx, module)
if !h.active {
// The rest of the properties will be ignored if active is false.
return
}
- // If this module has a suffix of -hiddenapi then it only provides additional annotation
- // information for a module on the boot jars list.
- h.annotationsOnly = strings.HasSuffix(name, "-hiddenapi")
-
// Determine whether this module is the primary module or not.
primary := true
// A prebuilt module is only primary if it is preferred and conversely a source module is only
// primary if it has not been replaced by a prebuilt module.
- module := ctx.Module()
if pi, ok := module.(android.PrebuiltInterface); ok {
if p := pi.Prebuilt(); p != nil {
primary = p.UsePrebuilt()
}
} else {
- // The only module that will pass a different name to its module name to this method is the
- // implementation library of a java_sdk_library. It has a configuration name of <x> the same
- // as its parent java_sdk_library but a module name of <x>.impl. It is not the primary module,
- // the java_sdk_library with the name of <x> is.
- primary = name == ctx.ModuleName()
+ // The only module that will pass a different configurationName to its module name to this
+ // method is the implementation library of a java_sdk_library. It has a configuration name of
+ // <x> the same as its parent java_sdk_library but a module name of <x>.impl. It is not the
+ // primary module, the java_sdk_library with the name of <x> is.
+ primary = configurationName == ctx.ModuleName()
// A source module that has been replaced by a prebuilt can never be the primary module.
- primary = primary && !module.IsReplacedByPrebuilt()
+ if module.IsReplacedByPrebuilt() {
+ ctx.VisitDirectDepsWithTag(android.PrebuiltDepTag, func(prebuilt android.Module) {
+ if h, ok := prebuilt.(hiddenAPIIntf); ok && h.bootDexJar() != nil {
+ primary = false
+ } else {
+ ctx.ModuleErrorf(
+ "hiddenapi has determined that the source module %q should be ignored as it has been"+
+ " replaced by the prebuilt module %q but unfortunately it does not provide a"+
+ " suitable boot dex jar", ctx.ModuleName(), ctx.OtherModuleName(prebuilt))
+ }
+ })
+ }
}
h.primary = primary
}
+func isModuleInBootClassPath(ctx android.BaseModuleContext, module android.Module) bool {
+ // Get the configured non-updatable and updatable boot jars.
+ nonUpdatableBootJars := ctx.Config().NonUpdatableBootJars()
+ updatableBootJars := ctx.Config().UpdatableBootJars()
+ active := isModuleInConfiguredList(ctx, module, nonUpdatableBootJars) ||
+ isModuleInConfiguredList(ctx, module, updatableBootJars)
+ return active
+}
+
// hiddenAPIExtractAndEncode is called by any module that could contribute to the hiddenapi
// processing.
//
@@ -191,15 +196,13 @@ func (h *hiddenAPI) hiddenAPIExtractAndEncode(ctx android.ModuleContext, dexJar
h.hiddenAPIExtractInformation(ctx, dexJar, implementationJar)
- if !h.annotationsOnly {
- hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", h.configurationName+".jar").OutputPath
+ hiddenAPIJar := android.PathForModuleOut(ctx, "hiddenapi", h.configurationName+".jar").OutputPath
- // Create a copy of the dex jar which has been encoded with hiddenapi flags.
- hiddenAPIEncodeDex(ctx, hiddenAPIJar, dexJar, uncompressDex)
+ // Create a copy of the dex jar which has been encoded with hiddenapi flags.
+ hiddenAPIEncodeDex(ctx, hiddenAPIJar, dexJar, uncompressDex)
- // Use the encoded dex jar from here onwards.
- dexJar = hiddenAPIJar
- }
+ // Use the encoded dex jar from here onwards.
+ dexJar = hiddenAPIJar
return dexJar
}
@@ -262,6 +265,7 @@ func (h *hiddenAPI) hiddenAPIExtractInformation(ctx android.ModuleContext, dexJa
rule.Command().
BuiltTool("merge_csv").
Flag("--zip_input").
+ Flag("--key_field signature").
FlagWithOutput("--output=", indexCSV).
Inputs(classesJars)
rule.Build("merged-hiddenapi-index", "Merged Hidden API index")
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 6341a3406..82e8b3f75 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -217,10 +217,6 @@ 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.(UsesLibraryDependency); ok {
@@ -235,11 +231,6 @@ 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 {
- if !isModuleInConfiguredList(ctx, module, nonUpdatableBootJars) &&
- !isModuleInConfiguredList(ctx, module, updatableBootJars) {
- return
- }
-
bootDexJars = append(bootDexJars, jar)
}
}
@@ -291,8 +282,8 @@ func stubFlagsRule(ctx android.SingletonContext) {
// 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)
+func isModuleInConfiguredList(ctx android.BaseModuleContext, module android.Module, configuredBootJars android.ConfiguredJarList) bool {
+ name := ctx.OtherModuleName(module)
// Strip a prebuilt_ prefix so that this can match a prebuilt module that has not been renamed.
name = android.RemoveOptionalPrebuiltPrefix(name)
@@ -305,11 +296,11 @@ func isModuleInConfiguredList(ctx android.SingletonContext, module android.Modul
// 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)
+ ctx.ModuleErrorf("is configured in boot jars but does not support being added to an apex")
return false
}
- apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo := ctx.OtherModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
// Now match the apex part of the boot image configuration.
requiredApex := configuredBootJars.Apex(index)
@@ -433,6 +424,7 @@ func metadataRule(ctx android.SingletonContext) android.Path {
rule.Command().
BuiltTool("merge_csv").
+ Flag("--key_field signature").
FlagWithOutput("--output=", outputPath).
Inputs(metadataCSV)
@@ -544,6 +536,7 @@ func (h *hiddenAPIIndexSingleton) GenerateBuildActions(ctx android.SingletonCont
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
BuiltTool("merge_csv").
+ Flag("--key_field signature").
FlagWithArg("--header=", "signature,file,startline,startcol,endline,endcol,properties").
FlagWithOutput("--output=", hiddenAPISingletonPaths(ctx).index).
Inputs(indexes)
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index 4670d0311..fb63820a8 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -89,12 +89,6 @@ func TestHiddenAPIIndexSingleton(t *testing.T) {
}
java_library {
- name: "foo-hiddenapi",
- srcs: ["a.java"],
- compile_dex: true,
- }
-
- java_library {
name: "foo-hiddenapi-annotations",
srcs: ["a.java"],
compile_dex: true,
@@ -118,7 +112,6 @@ func TestHiddenAPIIndexSingleton(t *testing.T) {
indexRule := hiddenAPIIndex.Rule("singleton-merged-hiddenapi-index")
CheckHiddenAPIRuleInputs(t, `
.intermediates/bar/android_common/hiddenapi/index.csv
-.intermediates/foo-hiddenapi/android_common/hiddenapi/index.csv
.intermediates/foo/android_common/hiddenapi/index.csv
`,
indexRule)
@@ -133,6 +126,29 @@ func TestHiddenAPIIndexSingleton(t *testing.T) {
`, indexParams)
}
+func TestHiddenAPISingletonWithSourceAndPrebuiltPreferredButNoDex(t *testing.T) {
+ config := testConfigWithBootJars(`
+ java_library {
+ name: "foo",
+ srcs: ["a.java"],
+ compile_dex: true,
+ }
+
+ java_import {
+ name: "foo",
+ jars: ["a.jar"],
+ prefer: true,
+ }
+ `, []string{"platform:foo"}, nil)
+
+ ctx := testContextWithHiddenAPI(config)
+
+ runWithErrors(t, ctx, config,
+ "hiddenapi has determined that the source module \"foo\" should be ignored as it has been"+
+ " replaced by the prebuilt module \"prebuilt_foo\" but unfortunately it does not provide a"+
+ " suitable boot dex jar")
+}
+
func TestHiddenAPISingletonWithPrebuilt(t *testing.T) {
ctx, _ := testHiddenAPIBootJars(t, `
java_import {
diff --git a/java/java.go b/java/java.go
index dbfad029b..9e3583501 100644
--- a/java/java.go
+++ b/java/java.go
@@ -370,6 +370,10 @@ type CompilerDeviceProperties struct {
// If true, generate the signature file of APK Signing Scheme V4, along side the signed APK file.
// Defaults to false.
V4_signature *bool
+
+ // Only for libraries created by a sysprop_library module, SyspropPublicStub is the name of the
+ // public stubs library.
+ SyspropPublicStub string `blueprint:"mutated"`
}
// Functionality common to Module and Import
@@ -434,9 +438,6 @@ type Module struct {
// output file containing classes.dex and resources
dexJarFile android.Path
- // output file that contains classes.dex if it should be in the output file
- maybeStrippedDexJarFile android.Path
-
// output file containing uninstrumented classes that will be instrumented by jacoco
jacocoReportClassesFile android.Path
@@ -583,6 +584,16 @@ type JavaInfo struct {
var JavaInfoProvider = blueprint.NewProvider(JavaInfo{})
+// SyspropPublicStubInfo contains info about the sysprop public stub library that corresponds to
+// the sysprop implementation library.
+type SyspropPublicStubInfo struct {
+ // JavaInfo is the JavaInfoProvider of the sysprop public stub library that corresponds to
+ // the sysprop implementation library.
+ JavaInfo JavaInfo
+}
+
+var SyspropPublicStubInfoProvider = blueprint.NewProvider(SyspropPublicStubInfo{})
+
// Methods that need to be implemented for a module that is added to apex java_libs property.
type ApexDependency interface {
HeaderJars() android.Paths
@@ -652,29 +663,30 @@ func IsJniDepTag(depTag blueprint.DependencyTag) bool {
}
var (
- dataNativeBinsTag = dependencyTag{name: "dataNativeBins"}
- staticLibTag = dependencyTag{name: "staticlib"}
- libTag = dependencyTag{name: "javalib"}
- java9LibTag = dependencyTag{name: "java9lib"}
- pluginTag = dependencyTag{name: "plugin"}
- errorpronePluginTag = dependencyTag{name: "errorprone-plugin"}
- exportedPluginTag = dependencyTag{name: "exported-plugin"}
- bootClasspathTag = dependencyTag{name: "bootclasspath"}
- systemModulesTag = dependencyTag{name: "system modules"}
- frameworkResTag = dependencyTag{name: "framework-res"}
- kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"}
- kotlinAnnotationsTag = dependencyTag{name: "kotlin-annotations"}
- proguardRaiseTag = dependencyTag{name: "proguard-raise"}
- certificateTag = dependencyTag{name: "certificate"}
- instrumentationForTag = dependencyTag{name: "instrumentation_for"}
- extraLintCheckTag = dependencyTag{name: "extra-lint-check"}
- jniLibTag = dependencyTag{name: "jnilib"}
- jniInstallTag = installDependencyTag{name: "jni install"}
- binaryInstallTag = installDependencyTag{name: "binary install"}
- usesLibTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion)
- usesLibCompat28Tag = makeUsesLibraryDependencyTag(28)
- usesLibCompat29Tag = makeUsesLibraryDependencyTag(29)
- usesLibCompat30Tag = makeUsesLibraryDependencyTag(30)
+ dataNativeBinsTag = dependencyTag{name: "dataNativeBins"}
+ staticLibTag = dependencyTag{name: "staticlib"}
+ libTag = dependencyTag{name: "javalib"}
+ java9LibTag = dependencyTag{name: "java9lib"}
+ pluginTag = dependencyTag{name: "plugin"}
+ errorpronePluginTag = dependencyTag{name: "errorprone-plugin"}
+ exportedPluginTag = dependencyTag{name: "exported-plugin"}
+ bootClasspathTag = dependencyTag{name: "bootclasspath"}
+ systemModulesTag = dependencyTag{name: "system modules"}
+ frameworkResTag = dependencyTag{name: "framework-res"}
+ kotlinStdlibTag = dependencyTag{name: "kotlin-stdlib"}
+ kotlinAnnotationsTag = dependencyTag{name: "kotlin-annotations"}
+ proguardRaiseTag = dependencyTag{name: "proguard-raise"}
+ certificateTag = dependencyTag{name: "certificate"}
+ instrumentationForTag = dependencyTag{name: "instrumentation_for"}
+ extraLintCheckTag = dependencyTag{name: "extra-lint-check"}
+ jniLibTag = dependencyTag{name: "jnilib"}
+ syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
+ jniInstallTag = installDependencyTag{name: "jni install"}
+ binaryInstallTag = installDependencyTag{name: "binary install"}
+ usesLibTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion)
+ usesLibCompat28Tag = makeUsesLibraryDependencyTag(28)
+ usesLibCompat29Tag = makeUsesLibraryDependencyTag(29)
+ usesLibCompat30Tag = makeUsesLibraryDependencyTag(30)
)
func IsLibDepTag(depTag blueprint.DependencyTag) bool {
@@ -813,35 +825,17 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
j.linter.deps(ctx)
sdkDeps(ctx, sdkContext(j), j.dexer)
- }
-
- syspropPublicStubs := syspropPublicStubs(ctx.Config())
-
- // rewriteSyspropLibs validates if a java module can link against platform's sysprop_library,
- // and redirects dependency to public stub depending on the link type.
- rewriteSyspropLibs := func(libs []string, prop string) []string {
- // make a copy
- ret := android.CopyOf(libs)
-
- for idx, lib := range libs {
- stub, ok := syspropPublicStubs[lib]
- if !ok {
- continue
- }
-
- linkType, _ := j.getLinkType(ctx.ModuleName())
- // only platform modules can use internal props
- if linkType != javaPlatform {
- ret[idx] = stub
- }
+ if j.deviceProperties.SyspropPublicStub != "" {
+ // This is a sysprop implementation library that has a corresponding sysprop public
+ // stubs library, and a dependency on it so that dependencies on the implementation can
+ // be forwarded to the public stubs library when necessary.
+ ctx.AddVariationDependencies(nil, syspropPublicStubDepTag, j.deviceProperties.SyspropPublicStub)
}
-
- return ret
}
- libDeps := ctx.AddVariationDependencies(nil, libTag, rewriteSyspropLibs(j.properties.Libs, "libs")...)
- ctx.AddVariationDependencies(nil, staticLibTag, rewriteSyspropLibs(j.properties.Static_libs, "static_libs")...)
+ libDeps := ctx.AddVariationDependencies(nil, libTag, j.properties.Libs...)
+ ctx.AddVariationDependencies(nil, staticLibTag, j.properties.Static_libs...)
// Add dependency on libraries that provide additional hidden api annotations.
ctx.AddVariationDependencies(nil, hiddenApiAnnotationsTag, j.properties.Hiddenapi_additional_annotations...)
@@ -856,15 +850,11 @@ func (j *Module) deps(ctx android.BottomUpMutatorContext) {
// if true, enable enforcement
// PRODUCT_INTER_PARTITION_JAVA_LIBRARY_ALLOWLIST
// exception list of java_library names to allow inter-partition dependency
- for idx, lib := range j.properties.Libs {
+ for idx := range j.properties.Libs {
if libDeps[idx] == nil {
continue
}
- if _, ok := syspropPublicStubs[lib]; ok {
- continue
- }
-
if javaDep, ok := libDeps[idx].(javaSdkLibraryEnforceContext); ok {
// java_sdk_library is always allowed at inter-partition dependency.
// So, skip check.
@@ -1038,7 +1028,7 @@ func (lt linkType) String() string {
case javaPlatform:
return "private API"
default:
- panic(fmt.Errorf("unrecognized linktype: %v", lt))
+ panic(fmt.Errorf("unrecognized linktype: %d", lt))
}
}
@@ -1134,6 +1124,8 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
}
}
+ linkType, _ := j.getLinkType(ctx.ModuleName())
+
ctx.VisitDirectDeps(func(module android.Module) {
otherName := ctx.OtherModuleName(module)
tag := ctx.OtherModuleDependencyTag(module)
@@ -1156,6 +1148,14 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
}
} else if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ if linkType != javaPlatform &&
+ ctx.OtherModuleHasProvider(module, SyspropPublicStubInfoProvider) {
+ // dep is a sysprop implementation library, but this module is not linking against
+ // the platform, so it gets the sysprop public stubs library instead. Replace
+ // dep with the JavaInfo from the SyspropPublicStubInfoProvider.
+ syspropDep := ctx.OtherModuleProvider(module, SyspropPublicStubInfoProvider).(SyspropPublicStubInfo)
+ dep = syspropDep.JavaInfo
+ }
switch tag {
case bootClasspathTag:
deps.bootClasspath = append(deps.bootClasspath, dep.HeaderJars...)
@@ -1214,6 +1214,12 @@ func (j *Module) collectDeps(ctx android.ModuleContext) deps {
deps.kotlinStdlib = append(deps.kotlinStdlib, dep.HeaderJars...)
case kotlinAnnotationsTag:
deps.kotlinAnnotations = dep.HeaderJars
+ case syspropPublicStubDepTag:
+ // This is a sysprop implementation library, forward the JavaInfoProvider from
+ // the corresponding sysprop public stub library as SyspropPublicStubInfoProvider.
+ ctx.SetProvider(SyspropPublicStubInfoProvider, SyspropPublicStubInfo{
+ JavaInfo: dep,
+ })
}
} else if dep, ok := module.(android.SourceFileProducer); ok {
switch tag {
@@ -1818,46 +1824,50 @@ func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
}
}
- if ctx.Device() && j.hasCode(ctx) &&
- (Bool(j.properties.Installable) || Bool(j.dexProperties.Compile_dex)) {
- if j.shouldInstrumentStatic(ctx) {
- j.dexer.extraProguardFlagFiles = append(j.dexer.extraProguardFlagFiles,
- android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
- }
- // Dex compilation
- var dexOutputFile android.OutputPath
- dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
- if ctx.Failed() {
- return
- }
+ if ctx.Device() && (Bool(j.properties.Installable) || Bool(j.dexProperties.Compile_dex)) {
+ if j.hasCode(ctx) {
+ if j.shouldInstrumentStatic(ctx) {
+ j.dexer.extraProguardFlagFiles = append(j.dexer.extraProguardFlagFiles,
+ android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
+ }
+ // Dex compilation
+ var dexOutputFile android.OutputPath
+ dexOutputFile = j.dexer.compileDex(ctx, flags, j.minSdkVersion(), outputFile, jarName)
+ if ctx.Failed() {
+ return
+ }
- // Hidden API CSV generation and dex encoding
- dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, j.implementationJarFile,
- proptools.Bool(j.dexProperties.Uncompress_dex))
+ // Hidden API CSV generation and dex encoding
+ dexOutputFile = j.hiddenAPIExtractAndEncode(ctx, dexOutputFile, j.implementationJarFile,
+ proptools.Bool(j.dexProperties.Uncompress_dex))
- // merge dex jar with resources if necessary
- if j.resourceJar != nil {
- jars := android.Paths{dexOutputFile, j.resourceJar}
- combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName).OutputPath
- TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
- false, nil, nil)
- if *j.dexProperties.Uncompress_dex {
- combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName).OutputPath
- TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
- dexOutputFile = combinedAlignedJar
- } else {
- dexOutputFile = combinedJar
+ // merge dex jar with resources if necessary
+ if j.resourceJar != nil {
+ jars := android.Paths{dexOutputFile, j.resourceJar}
+ combinedJar := android.PathForModuleOut(ctx, "dex-withres", jarName).OutputPath
+ TransformJarsToJar(ctx, combinedJar, "for dex resources", jars, android.OptionalPath{},
+ false, nil, nil)
+ if *j.dexProperties.Uncompress_dex {
+ combinedAlignedJar := android.PathForModuleOut(ctx, "dex-withres-aligned", jarName).OutputPath
+ TransformZipAlign(ctx, combinedAlignedJar, combinedJar)
+ dexOutputFile = combinedAlignedJar
+ } else {
+ dexOutputFile = combinedJar
+ }
}
- }
-
- j.dexJarFile = dexOutputFile
- // Dexpreopting
- j.dexpreopt(ctx, dexOutputFile)
+ j.dexJarFile = dexOutputFile
- j.maybeStrippedDexJarFile = dexOutputFile
+ // Dexpreopting
+ j.dexpreopt(ctx, dexOutputFile)
- outputFile = dexOutputFile
+ outputFile = dexOutputFile
+ } else {
+ // There is no code to compile into a dex jar, make sure the resources are propagated
+ // to the APK if this is an app.
+ outputFile = implementationAndResourcesJar
+ j.dexJarFile = j.resourceJar
+ }
if ctx.Failed() {
return
@@ -2036,13 +2046,6 @@ func (j *Module) DexJarInstallPath() android.Path {
return j.installFile
}
-func (j *Module) ResourceJars() android.Paths {
- if j.resourceJar == nil {
- return nil
- }
- return android.Paths{j.resourceJar}
-}
-
func (j *Module) ImplementationAndResourcesJars() android.Paths {
if j.implementationAndResourcesJar == nil {
return nil
@@ -2059,17 +2062,6 @@ func (j *Module) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
return j.classLoaderContexts
}
-// ExportedPlugins returns the list of jars needed to run the exported plugins, the list of
-// classes for the plugins, and a boolean for whether turbine needs to be disabled due to plugins
-// that generate APIs.
-func (j *Module) ExportedPlugins() (android.Paths, []string, bool) {
- return j.exportedPluginJars, j.exportedPluginClasses, j.exportedDisableTurbine
-}
-
-func (j *Module) SrcJarArgs() ([]string, android.Paths) {
- return j.srcJarArgs, j.srcJarDeps
-}
-
var _ logtagsProducer = (*Module)(nil)
func (j *Module) logtags() android.Paths {
@@ -2505,6 +2497,11 @@ func (j *TestHost) DepsMutator(ctx android.BottomUpMutatorContext) {
}
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if j.testProperties.Test_options.Unit_test == nil && ctx.Host() {
+ // TODO(b/): Clean temporary heuristic to avoid unexpected onboarding.
+ defaultUnitTest := !inList("tradefed", j.properties.Static_libs) && !inList("tradefed", j.properties.Libs) && !inList("cts", j.testProperties.Test_suites) && !inList("robolectric-host-android_all", j.properties.Static_libs) && !inList("robolectric-host-android_all", j.properties.Libs)
+ j.testProperties.Test_options.Unit_test = proptools.BoolPtr(defaultUnitTest)
+ }
j.testConfig = tradefed.AutoGenJavaTestConfig(ctx, j.testProperties.Test_config, j.testProperties.Test_config_template,
j.testProperties.Test_suites, j.testProperties.Auto_gen_config, j.testProperties.Test_options.Unit_test)
@@ -2665,6 +2662,7 @@ func TestHostFactory() android.Module {
module.Module.properties.Installable = proptools.BoolPtr(true)
InitJavaModuleMultiTargets(module, android.HostSupported)
+
return module
}
@@ -3036,17 +3034,6 @@ func (j *Import) HeaderJars() android.Paths {
return android.Paths{j.combinedClasspathFile}
}
-func (j *Import) ImplementationJars() android.Paths {
- if j.combinedClasspathFile == nil {
- return nil
- }
- return android.Paths{j.combinedClasspathFile}
-}
-
-func (j *Import) ResourceJars() android.Paths {
- return nil
-}
-
func (j *Import) ImplementationAndResourcesJars() android.Paths {
if j.combinedClasspathFile == nil {
return nil
@@ -3062,22 +3049,10 @@ func (j *Import) DexJarInstallPath() android.Path {
return nil
}
-func (j *Import) AidlIncludeDirs() android.Paths {
- return j.exportAidlIncludeDirs
-}
-
func (j *Import) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
return j.classLoaderContexts
}
-func (j *Import) ExportedPlugins() (android.Paths, []string, bool) {
- return nil, nil, false
-}
-
-func (j *Import) SrcJarArgs() ([]string, android.Paths) {
- return nil, nil
-}
-
var _ android.ApexModule = (*Import)(nil)
// Implements android.ApexModule
@@ -3183,8 +3158,7 @@ type DexImport struct {
properties DexImportProperties
- dexJarFile android.Path
- maybeStrippedDexJarFile android.Path
+ dexJarFile android.Path
dexpreopter
@@ -3271,8 +3245,6 @@ func (j *DexImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.dexpreopt(ctx, dexOutputFile)
- j.maybeStrippedDexJarFile = dexOutputFile
-
if apexInfo.IsForPlatform() {
ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
j.Stem()+".jar", dexOutputFile)
diff --git a/java/java_test.go b/java/java_test.go
index 11f6a7c21..911265532 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -25,6 +25,7 @@ import (
"strings"
"testing"
+ "android/soong/genrule"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -74,11 +75,13 @@ func testContext(config android.Config) *android.TestContext {
ctx.PreDepsMutators(python.RegisterPythonPreDepsMutators)
ctx.PostDepsMutators(android.RegisterOverridePostDepsMutators)
- ctx.RegisterPreSingletonType("overlay", android.SingletonFactoryAdaptor(ctx.Context, OverlaySingletonFactory))
- ctx.RegisterPreSingletonType("sdk_versions", android.SingletonFactoryAdaptor(ctx.Context, sdkPreSingletonFactory))
+ ctx.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
+ ctx.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
android.RegisterPrebuiltMutators(ctx)
+ genrule.RegisterGenruleBuildComponents(ctx)
+
// Register module types and mutators from cc needed for JNI testing
cc.RegisterRequiredBuildComponentsForTest(ctx)
@@ -114,20 +117,26 @@ func testJavaErrorWithConfig(t *testing.T, pattern string, config android.Config
pathCtx := android.PathContextForTesting(config)
dexpreopt.SetTestGlobalConfig(config, dexpreopt.GlobalConfigForTests(pathCtx))
+ runWithErrors(t, ctx, config, pattern)
+
+ return ctx, config
+}
+
+func runWithErrors(t *testing.T, ctx *android.TestContext, config android.Config, pattern string) {
ctx.Register()
_, errs := ctx.ParseBlueprintsFiles("Android.bp")
if len(errs) > 0 {
android.FailIfNoMatchingErrors(t, pattern, errs)
- return ctx, config
+ return
}
_, errs = ctx.PrepareBuildActions(config)
if len(errs) > 0 {
android.FailIfNoMatchingErrors(t, pattern, errs)
- return ctx, config
+ return
}
t.Fatalf("missing expected error %q (0 errors are returned)", pattern)
- return ctx, config
+ return
}
func testJavaWithFS(t *testing.T, bp string, fs map[string][]byte) (*android.TestContext, android.Config) {
diff --git a/java/legacy_core_platform_api_usage.go b/java/legacy_core_platform_api_usage.go
index d6ff47974..b5668a1c2 100644
--- a/java/legacy_core_platform_api_usage.go
+++ b/java/legacy_core_platform_api_usage.go
@@ -22,6 +22,7 @@ import (
var legacyCorePlatformApiModules = []string{
"AAECarSystemUI",
"AAECarSystemUI-tests",
+ "ArcSettings",
"ahat-test-dump",
"android.car",
"android.test.mock",
@@ -77,6 +78,7 @@ var legacyCorePlatformApiModules = []string{
"DownloadProvider",
"DownloadProviderTests",
"DownloadProviderUi",
+ "ds-car-docs", // for AAOS API documentation only
"DynamicSystemInstallationService",
"EmergencyInfo-lib",
"ethernet-service",
@@ -141,7 +143,7 @@ var legacyCorePlatformApiModules = []string{
"saminterfacelibrary",
"sammanagerlibrary",
"service-blobstore",
- "service-connectivity",
+ "service-connectivity-pre-jarjar",
"service-jobscheduler",
"services",
"services.accessibility",
@@ -152,6 +154,7 @@ var legacyCorePlatformApiModules = []string{
"services.usage",
"services.usb",
"Settings-core",
+ "SettingsGoogle",
"SettingsGoogleOverlayCoral",
"SettingsGoogleOverlayFlame",
"SettingsLib",
diff --git a/java/lint.go b/java/lint.go
index 827259573..f9a89d0f7 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -22,6 +22,8 @@ import (
"github.com/google/blueprint/proptools"
"android/soong/android"
+ "android/soong/java/config"
+ "android/soong/remoteexec"
)
type LintProperties struct {
@@ -172,8 +174,38 @@ func (l *linter) deps(ctx android.BottomUpMutatorContext) {
extraLintCheckTag, extraCheckModules...)
}
-func (l *linter) writeLintProjectXML(ctx android.ModuleContext,
- rule *android.RuleBuilder) (projectXMLPath, configXMLPath, cacheDir, homeDir android.WritablePath, deps android.Paths) {
+type lintPaths struct {
+ projectXML android.WritablePath
+ configXML android.WritablePath
+ cacheDir android.WritablePath
+ homeDir android.WritablePath
+ srcjarDir android.WritablePath
+
+ deps android.Paths
+
+ remoteInputs android.Paths
+ remoteRSPInputs android.Paths
+}
+
+func (l *linter) writeLintProjectXML(ctx android.ModuleContext, rule *android.RuleBuilder) lintPaths {
+ var deps android.Paths
+ var remoteInputs android.Paths
+ var remoteRSPInputs android.Paths
+
+ // Paths passed to trackInputDependency will be added as dependencies of the rule that runs
+ // lint and passed as inputs to the remote execution proxy.
+ trackInputDependency := func(paths ...android.Path) {
+ deps = append(deps, paths...)
+ remoteInputs = append(remoteInputs, paths...)
+ }
+
+ // Paths passed to trackRSPDependency will be added as dependencies of the rule that runs
+ // lint, but the RSP file will be used by the remote execution proxy to find the files so that
+ // it doesn't overflow command line limits.
+ trackRSPDependency := func(paths android.Paths, rsp android.Path) {
+ deps = append(deps, paths...)
+ remoteRSPInputs = append(remoteRSPInputs, rsp)
+ }
var resourcesList android.WritablePath
if len(l.resources) > 0 {
@@ -184,17 +216,27 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext,
resListRule := android.NewRuleBuilder(pctx, ctx)
resListRule.Command().Text("cp").FlagWithRspFileInputList("", l.resources).Output(resourcesList)
resListRule.Build("lint_resources_list", "lint resources list")
- deps = append(deps, l.resources...)
+ trackRSPDependency(l.resources, resourcesList)
}
- projectXMLPath = android.PathForModuleOut(ctx, "lint", "project.xml")
+ projectXMLPath := android.PathForModuleOut(ctx, "lint", "project.xml")
// Lint looks for a lint.xml file next to the project.xml file, give it one.
- configXMLPath = android.PathForModuleOut(ctx, "lint", "lint.xml")
- cacheDir = android.PathForModuleOut(ctx, "lint", "cache")
- homeDir = android.PathForModuleOut(ctx, "lint", "home")
+ configXMLPath := android.PathForModuleOut(ctx, "lint", "lint.xml")
+ cacheDir := android.PathForModuleOut(ctx, "lint", "cache")
+ homeDir := android.PathForModuleOut(ctx, "lint", "home")
srcJarDir := android.PathForModuleOut(ctx, "lint-srcjars")
srcJarList := zipSyncCmd(ctx, rule, srcJarDir, l.srcJars)
+ // TODO(ccross): this is a little fishy. The files extracted from the srcjars are referenced
+ // by the project.xml and used by the later lint rule, but the lint rule depends on the srcjars,
+ // not the extracted files.
+ trackRSPDependency(l.srcJars, srcJarList)
+
+ // TODO(ccross): some of the files in l.srcs are generated sources and should be passed to
+ // lint separately.
+ srcsList := android.PathForModuleOut(ctx, "lint", "srcs.list")
+ rule.Command().Text("cp").FlagWithRspFileInputList("", l.srcs).Output(srcsList)
+ trackRSPDependency(l.srcs, srcsList)
cmd := rule.Command().
BuiltTool("lint-project-xml").
@@ -209,38 +251,39 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext,
cmd.Flag("--test")
}
if l.manifest != nil {
- deps = append(deps, l.manifest)
cmd.FlagWithArg("--manifest ", l.manifest.String())
+ trackInputDependency(l.manifest)
}
if l.mergedManifest != nil {
- deps = append(deps, l.mergedManifest)
cmd.FlagWithArg("--merged_manifest ", l.mergedManifest.String())
+ trackInputDependency(l.mergedManifest)
}
- // TODO(ccross): some of the files in l.srcs are generated sources and should be passed to
- // lint separately.
- cmd.FlagWithRspFileInputList("--srcs ", l.srcs)
- deps = append(deps, l.srcs...)
+ cmd.FlagWithInput("--srcs ", srcsList)
cmd.FlagWithInput("--generated_srcs ", srcJarList)
- deps = append(deps, l.srcJars...)
if resourcesList != nil {
cmd.FlagWithInput("--resources ", resourcesList)
}
if l.classes != nil {
- deps = append(deps, l.classes)
cmd.FlagWithArg("--classes ", l.classes.String())
+ trackInputDependency(l.classes)
}
cmd.FlagForEachArg("--classpath ", l.classpath.Strings())
- deps = append(deps, l.classpath...)
+ trackInputDependency(l.classpath...)
cmd.FlagForEachArg("--extra_checks_jar ", l.extraLintCheckJars.Strings())
- deps = append(deps, l.extraLintCheckJars...)
+ trackInputDependency(l.extraLintCheckJars...)
- cmd.FlagWithArg("--root_dir ", "$PWD")
+ if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_LINT") {
+ // TODO(b/181912787): remove these and use "." instead.
+ cmd.FlagWithArg("--root_dir ", "/b/f/w")
+ } else {
+ cmd.FlagWithArg("--root_dir ", "$PWD")
+ }
// The cache tag in project.xml is relative to the root dir, or the project.xml file if
// the root dir is not set.
@@ -254,7 +297,18 @@ func (l *linter) writeLintProjectXML(ctx android.ModuleContext,
cmd.FlagForEachArg("--error_check ", l.properties.Lint.Error_checks)
cmd.FlagForEachArg("--fatal_check ", l.properties.Lint.Fatal_checks)
- return projectXMLPath, configXMLPath, cacheDir, homeDir, deps
+ return lintPaths{
+ projectXML: projectXMLPath,
+ configXML: configXMLPath,
+ cacheDir: cacheDir,
+ homeDir: homeDir,
+
+ deps: deps,
+
+ remoteInputs: remoteInputs,
+ remoteRSPInputs: remoteRSPInputs,
+ }
+
}
// generateManifest adds a command to the rule to write a simple manifest that contains the
@@ -297,7 +351,7 @@ func (l *linter) lint(ctx android.ModuleContext) {
l.manifest = manifest
}
- projectXML, lintXML, cacheDir, homeDir, deps := l.writeLintProjectXML(ctx, rule)
+ lintPaths := l.writeLintProjectXML(ctx, rule)
html := android.PathForModuleOut(ctx, "lint-report.html")
text := android.PathForModuleOut(ctx, "lint-report.txt")
@@ -311,8 +365,9 @@ func (l *linter) lint(ctx android.ModuleContext) {
}
})
- rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
- rule.Command().Text("mkdir -p").Flag(cacheDir.String()).Flag(homeDir.String())
+ rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
+ rule.Command().Text("mkdir -p").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
+ rule.Command().Text("rm -f").Output(html).Output(text).Output(xml)
var annotationsZipPath, apiVersionsXMLPath android.Path
if ctx.Config().AlwaysUsePrebuiltSdks() {
@@ -323,17 +378,52 @@ func (l *linter) lint(ctx android.ModuleContext) {
apiVersionsXMLPath = copiedAPIVersionsXmlPath(ctx)
}
- cmd := rule.Command().
- Text("(").
- Flag("JAVA_OPTS=-Xmx3072m").
- FlagWithArg("ANDROID_SDK_HOME=", homeDir.String()).
+ cmd := rule.Command()
+
+ cmd.Flag("JAVA_OPTS=-Xmx3072m").
+ FlagWithArg("ANDROID_SDK_HOME=", lintPaths.homeDir.String()).
FlagWithInput("SDK_ANNOTATIONS=", annotationsZipPath).
- FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath).
- Tool(android.PathForSource(ctx, "prebuilts/cmdline-tools/tools/bin/lint")).
- Implicit(android.PathForSource(ctx, "prebuilts/cmdline-tools/tools/lib/lint-classpath.jar")).
+ FlagWithInput("LINT_OPTS=-DLINT_API_DATABASE=", apiVersionsXMLPath)
+
+ if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_LINT") {
+ pool := ctx.Config().GetenvWithDefault("RBE_LINT_POOL", "java16")
+ // TODO(b/181912787): this should be local fallback once the hack that passes /b/f/w in project.xml
+ // is removed.
+ execStrategy := ctx.Config().GetenvWithDefault("RBE_LINT_EXEC_STRATEGY", remoteexec.RemoteExecStrategy)
+ labels := map[string]string{"type": "tool", "name": "lint"}
+ rule.Remoteable(android.RemoteRuleSupports{RBE: true})
+ remoteInputs := lintPaths.remoteInputs
+ remoteInputs = append(remoteInputs,
+ lintPaths.projectXML,
+ lintPaths.configXML,
+ lintPaths.homeDir,
+ lintPaths.cacheDir,
+ ctx.Config().HostJavaToolPath(ctx, "lint.jar"),
+ annotationsZipPath,
+ apiVersionsXMLPath,
+ )
+
+ cmd.Text((&remoteexec.REParams{
+ Labels: labels,
+ ExecStrategy: execStrategy,
+ ToolchainInputs: []string{config.JavaCmd(ctx).String()},
+ Inputs: remoteInputs.Strings(),
+ OutputFiles: android.Paths{html, text, xml}.Strings(),
+ RSPFile: strings.Join(lintPaths.remoteRSPInputs.Strings(), ","),
+ EnvironmentVariables: []string{
+ "JAVA_OPTS",
+ "ANDROID_SDK_HOME",
+ "SDK_ANNOTATIONS",
+ "LINT_OPTS",
+ },
+ Platform: map[string]string{remoteexec.PoolKey: pool},
+ }).NoVarTemplate(ctx.Config()))
+ }
+
+ cmd.BuiltTool("lint").
Flag("--quiet").
- FlagWithInput("--project ", projectXML).
- FlagWithInput("--config ", lintXML).
+ FlagWithInput("--project ", lintPaths.projectXML).
+ FlagWithInput("--config ", lintPaths.configXML).
FlagWithOutput("--html ", html).
FlagWithOutput("--text ", text).
FlagWithOutput("--xml ", xml).
@@ -343,7 +433,9 @@ func (l *linter) lint(ctx android.ModuleContext) {
FlagWithArg("--url ", fmt.Sprintf(".=.,%s=out", android.PathForOutput(ctx).String())).
Flag("--exitcode").
Flags(l.properties.Lint.Flags).
- Implicits(deps)
+ Implicit(annotationsZipPath).
+ Implicit(apiVersionsXMLPath).
+ Implicits(lintPaths.deps)
if checkOnly := ctx.Config().Getenv("ANDROID_LINT_CHECK"); checkOnly != "" {
cmd.FlagWithArg("--check ", checkOnly)
@@ -362,9 +454,9 @@ func (l *linter) lint(ctx android.ModuleContext) {
}
}
- cmd.Text("|| (").Text("cat").Input(text).Text("; exit 7)").Text(")")
+ cmd.Text("|| (").Text("if [ -e").Input(text).Text("]; then cat").Input(text).Text("; fi; exit 7)")
- rule.Command().Text("rm -rf").Flag(cacheDir.String()).Flag(homeDir.String())
+ rule.Command().Text("rm -rf").Flag(lintPaths.cacheDir.String()).Flag(lintPaths.homeDir.String())
rule.Build("lint", "lint")
@@ -438,13 +530,13 @@ func (l *lintSingleton) copyLintDependencies(ctx android.SingletonContext) {
}
ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
+ Rule: android.CpIfChanged,
Input: android.OutputFileForModule(ctx, frameworkDocStubs, ".annotations.zip"),
Output: copiedAnnotationsZipPath(ctx),
})
ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
+ Rule: android.CpIfChanged,
Input: android.OutputFileForModule(ctx, frameworkDocStubs, ".api_versions.xml"),
Output: copiedAPIVersionsXmlPath(ctx),
})
diff --git a/java/robolectric.go b/java/robolectric.go
index 54ee8232b..9fe1f0e0f 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -31,13 +31,15 @@ func init() {
}
var robolectricDefaultLibs = []string{
- "Robolectric_all-target",
"mockito-robolectric-prebuilt",
"truth-prebuilt",
// TODO(ccross): this is not needed at link time
"junitxml",
}
+const robolectricCurrentLib = "Robolectric_all-target"
+const robolectricPrebuiltLibPattern = "platform-robolectric-%s-prebuilt"
+
var (
roboCoverageLibsTag = dependencyTag{name: "roboCoverageLibs"}
roboRuntimesTag = dependencyTag{name: "roboRuntimes"}
@@ -57,6 +59,10 @@ type robolectricProperties struct {
// Number of shards to use when running the tests.
Shards *int64
}
+
+ // The version number of a robolectric prebuilt to use from prebuilts/misc/common/robolectric
+ // instead of the one built from source in external/robolectric-shadows.
+ Robolectric_prebuilt_version *string
}
type robolectricTest struct {
@@ -94,6 +100,12 @@ func (r *robolectricTest) DepsMutator(ctx android.BottomUpMutatorContext) {
ctx.PropertyErrorf("instrumentation_for", "missing required instrumented module")
}
+ if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
+ ctx.AddVariationDependencies(nil, libTag, fmt.Sprintf(robolectricPrebuiltLibPattern, v))
+ } else {
+ ctx.AddVariationDependencies(nil, libTag, robolectricCurrentLib)
+ }
+
ctx.AddVariationDependencies(nil, libTag, robolectricDefaultLibs...)
ctx.AddVariationDependencies(nil, roboCoverageLibsTag, r.robolectricProperties.Coverage_libs...)
@@ -298,7 +310,11 @@ func (r *robolectricTest) writeTestRunner(w io.Writer, module, name string, test
if t := r.robolectricProperties.Test_options.Timeout; t != nil {
fmt.Fprintln(w, "LOCAL_ROBOTEST_TIMEOUT :=", *t)
}
- fmt.Fprintln(w, "-include external/robolectric-shadows/run_robotests.mk")
+ if v := String(r.robolectricProperties.Robolectric_prebuilt_version); v != "" {
+ fmt.Fprintf(w, "-include prebuilts/misc/common/robolectric/%s/run_robotests.mk\n", v)
+ } else {
+ fmt.Fprintln(w, "-include external/robolectric-shadows/run_robotests.mk")
+ }
}
// An android_robolectric_test module compiles tests against the Robolectric framework that can run on the local host
diff --git a/java/rro_test.go b/java/rro_test.go
index edbf1708b..061d9d348 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -20,6 +20,7 @@ import (
"testing"
"android/soong/android"
+ "android/soong/shared"
)
func TestRuntimeResourceOverlay(t *testing.T) {
@@ -105,7 +106,7 @@ func TestRuntimeResourceOverlay(t *testing.T) {
// Check device location.
path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
- expectedPath = []string{"/tmp/target/product/test_device/product/overlay"}
+ expectedPath = []string{shared.JoinPath(buildDir, "../target/product/test_device/product/overlay")}
if !reflect.DeepEqual(path, expectedPath) {
t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
}
@@ -114,7 +115,7 @@ func TestRuntimeResourceOverlay(t *testing.T) {
m = ctx.ModuleForTests("foo_themed", "android_common")
androidMkEntries = android.AndroidMkEntriesForTest(t, ctx, m.Module())[0]
path = androidMkEntries.EntryMap["LOCAL_MODULE_PATH"]
- expectedPath = []string{"/tmp/target/product/test_device/product/overlay/faza"}
+ expectedPath = []string{shared.JoinPath(buildDir, "../target/product/test_device/product/overlay/faza")}
if !reflect.DeepEqual(path, expectedPath) {
t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
}
@@ -160,7 +161,7 @@ func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) {
// Check device location.
path := android.AndroidMkEntriesForTest(t, ctx, m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
- expectedPath := []string{"/tmp/target/product/test_device/product/overlay/default_theme"}
+ expectedPath := []string{shared.JoinPath(buildDir, "../target/product/test_device/product/overlay/default_theme")}
if !reflect.DeepEqual(path, expectedPath) {
t.Errorf("Unexpected LOCAL_MODULE_PATH value: %q, expected: %q", path, expectedPath)
}
@@ -179,7 +180,7 @@ func TestRuntimeResourceOverlay_JavaDefaults(t *testing.T) {
// Check device location.
path = android.AndroidMkEntriesForTest(t, ctx, m.Module())[0].EntryMap["LOCAL_MODULE_PATH"]
- expectedPath = []string{"/tmp/target/product/test_device/system/overlay"}
+ expectedPath = []string{shared.JoinPath(buildDir, "../target/product/test_device/system/overlay")}
if !reflect.DeepEqual(path, expectedPath) {
t.Errorf("Unexpected LOCAL_MODULE_PATH value: %v, expected: %v", path, expectedPath)
}
diff --git a/java/sdk_library.go b/java/sdk_library.go
index 90823a0c6..30d120d5c 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -1772,6 +1772,8 @@ type SdkLibraryImport struct {
android.ApexModuleBase
android.SdkBase
+ hiddenAPI
+
properties sdkLibraryImportProperties
// Map from api scope to the scope specific property structure.
@@ -1786,6 +1788,9 @@ type SdkLibraryImport struct {
// The reference to the xml permissions module created by the source module.
// Is nil if the source module does not exist.
xmlPermissionsFileModule *sdkLibraryXml
+
+ // Path to the dex implementation jar obtained from the prebuilt_apex, if any.
+ dexJarFile android.Path
}
var _ SdkLibraryDependency = (*SdkLibraryImport)(nil)
@@ -1982,6 +1987,8 @@ func (module *SdkLibraryImport) OutputFiles(tag string) (android.Paths, error) {
func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
module.generateCommonBuildActions(ctx)
+ var deapexerModule android.Module
+
// Record the paths to the prebuilt stubs library and stubs source.
ctx.VisitDirectDeps(func(to android.Module) {
tag := ctx.OtherModuleDependencyTag(to)
@@ -2007,6 +2014,11 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
ctx.ModuleErrorf("xml permissions file module must be of type *sdkLibraryXml but was %T", to)
}
}
+
+ // Save away the `deapexer` module on which this depends, if any.
+ if tag == android.DeapexerTag {
+ deapexerModule = to
+ }
})
// Populate the scope paths with information from the properties.
@@ -2019,6 +2031,32 @@ func (module *SdkLibraryImport) GenerateAndroidBuildActions(ctx android.ModuleCo
paths.currentApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Current_api)
paths.removedApiFilePath = android.OptionalPathForModuleSrc(ctx, scopeProperties.Removed_api)
}
+
+ if ctx.Device() {
+ // If this is a variant created for a prebuilt_apex then use the dex implementation jar
+ // obtained from the associated deapexer module.
+ ai := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ if ai.ForPrebuiltApex {
+ if deapexerModule == nil {
+ // This should never happen as a variant for a prebuilt_apex is only created if the
+ // deapxer module has been configured to export the dex implementation jar for this module.
+ ctx.ModuleErrorf("internal error: module %q does not depend on a `deapexer` module for prebuilt_apex %q",
+ module.Name(), ai.ApexVariationName)
+ }
+
+ // Get the path of the dex implementation jar from the `deapexer` module.
+ di := ctx.OtherModuleProvider(deapexerModule, android.DeapexerProvider).(android.DeapexerInfo)
+ if dexOutputPath := di.PrebuiltExportPath(module.BaseModuleName(), ".dexjar"); dexOutputPath != nil {
+ module.dexJarFile = dexOutputPath
+ module.initHiddenAPI(ctx, module.configurationName)
+ module.hiddenAPIExtractInformation(ctx, dexOutputPath, module.findScopePaths(apiScopePublic).stubsImplPath[0])
+ } else {
+ // This should never happen as a variant for a prebuilt_apex is only created if the
+ // prebuilt_apex has been configured to export the java library dex file.
+ ctx.ModuleErrorf("internal error: no dex implementation jar available from prebuilt_apex %q", deapexerModule.Name())
+ }
+ }
+ }
}
func (module *SdkLibraryImport) sdkJars(ctx android.BaseModuleContext, sdkVersion sdkSpec, headerJars bool) android.Paths {
@@ -2051,6 +2089,11 @@ func (module *SdkLibraryImport) SdkImplementationJars(ctx android.BaseModuleCont
// to satisfy UsesLibraryDependency interface
func (module *SdkLibraryImport) DexJarBuildPath() android.Path {
+ // The dex implementation jar extracted from the .apex file should be used in preference to the
+ // source.
+ if module.dexJarFile != nil {
+ return module.dexJarFile
+ }
if module.implLibraryModule == nil {
return nil
} else {
diff --git a/java/sdk_library_external.go b/java/sdk_library_external.go
index 293493685..0acaa13b2 100644
--- a/java/sdk_library_external.go
+++ b/java/sdk_library_external.go
@@ -75,10 +75,15 @@ func (j *Module) allowListedInterPartitionJavaLibrary(ctx android.EarlyModuleCon
return inList(j.Name(), ctx.Config().InterPartitionJavaLibraryAllowList())
}
+func (j *Module) syspropWithPublicStubs() bool {
+ return j.deviceProperties.SyspropPublicStub != ""
+}
+
type javaSdkLibraryEnforceContext interface {
Name() string
allowListedInterPartitionJavaLibrary(ctx android.EarlyModuleContext) bool
partitionGroup(ctx android.EarlyModuleContext) partitionGroup
+ syspropWithPublicStubs() bool
}
var _ javaSdkLibraryEnforceContext = (*Module)(nil)
@@ -88,6 +93,10 @@ func (j *Module) checkPartitionsForJavaDependency(ctx android.EarlyModuleContext
return
}
+ if dep.syspropWithPublicStubs() {
+ return
+ }
+
// If product interface is not enforced, skip check between system and product partition.
// But still need to check between product and vendor partition because product interface flag
// just represents enforcement between product and system, and vendor interface enforcement
diff --git a/java/sysprop.go b/java/sysprop.go
deleted file mode 100644
index e41aef68a..000000000
--- a/java/sysprop.go
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package java
-
-// This file contains a map to redirect dependencies towards sysprop_library. If a sysprop_library
-// is owned by Platform, and the client module links against system API, the public stub of the
-// sysprop_library should be used. The map will contain public stub names of sysprop_libraries.
-
-import (
- "sync"
-
- "android/soong/android"
-)
-
-type syspropLibraryInterface interface {
- BaseModuleName() string
- Owner() string
- HasPublicStub() bool
- JavaPublicStubName() string
-}
-
-var (
- syspropPublicStubsKey = android.NewOnceKey("syspropPublicStubsJava")
- syspropPublicStubsLock sync.Mutex
-)
-
-func init() {
- android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("sysprop_java", SyspropMutator).Parallel()
- })
-}
-
-func syspropPublicStubs(config android.Config) map[string]string {
- return config.Once(syspropPublicStubsKey, func() interface{} {
- return make(map[string]string)
- }).(map[string]string)
-}
-
-// gather list of sysprop libraries owned by platform.
-func SyspropMutator(mctx android.BottomUpMutatorContext) {
- if m, ok := mctx.Module().(syspropLibraryInterface); ok {
- if m.Owner() != "Platform" || !m.HasPublicStub() {
- return
- }
-
- syspropPublicStubs := syspropPublicStubs(mctx.Config())
- syspropPublicStubsLock.Lock()
- defer syspropPublicStubsLock.Unlock()
-
- syspropPublicStubs[m.BaseModuleName()] = m.JavaPublicStubName()
- }
-}
diff --git a/java/testing.go b/java/testing.go
index 781106ff2..bfa1e6b2a 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -240,6 +240,7 @@ func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, varia
}
func CheckHiddenAPIRuleInputs(t *testing.T, expected string, hiddenAPIRule android.TestingBuildParams) {
+ t.Helper()
actual := strings.TrimSpace(strings.Join(android.NormalizePathsForTesting(hiddenAPIRule.Implicits), "\n"))
expected = strings.TrimSpace(expected)
if actual != expected {
diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go
index d6e2c0a75..5f0426a7f 100644
--- a/remoteexec/remoteexec.go
+++ b/remoteexec/remoteexec.go
@@ -81,6 +81,9 @@ type REParams struct {
// ToolchainInputs is a list of paths or ninja variables pointing to the location of
// toolchain binaries used by the rule.
ToolchainInputs []string
+ // EnvironmentVariables is a list of environment variables whose values should be passed through
+ // to the remote execution.
+ EnvironmentVariables []string
}
func init() {
@@ -162,6 +165,10 @@ func (r *REParams) wrapperArgs() string {
args += " --toolchain_inputs=" + strings.Join(r.ToolchainInputs, ",")
}
+ if len(r.EnvironmentVariables) > 0 {
+ args += " --env_var_allowlist=" + strings.Join(r.EnvironmentVariables, ",")
+ }
+
return args + " -- "
}
diff --git a/rust/builder.go b/rust/builder.go
index 547d70569..632612457 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -230,6 +230,8 @@ func transformSrctoCrate(ctx ModuleContext, main android.Path, deps PathDeps, fl
envVars = append(envVars, "OUT_DIR="+filepath.Join(outDirPrefix, moduleGenDir.String()))
}
+ envVars = append(envVars, "ANDROID_RUST_VERSION="+config.RustDefaultVersion)
+
if flags.Clippy {
clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy")
ctx.Build(pctx, android.BuildParams{
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index fc11d2901..408d433c9 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -14,6 +14,7 @@ var (
"external/rust",
"external/vm_tools/p9",
"frameworks/native/libs/binder/rust",
+ "frameworks/proto_logging/stats",
"packages/modules/DnsResolver",
"packages/modules/Virtualization",
"prebuilts/rust",
diff --git a/rust/config/lints.go b/rust/config/lints.go
index ac8165b22..7c05e4f1d 100644
--- a/rust/config/lints.go
+++ b/rust/config/lints.go
@@ -53,6 +53,7 @@ var (
defaultClippyLints = []string{
"-A clippy::type-complexity",
"-A clippy::unnecessary-wraps",
+ "-A clippy::unusual-byte-groupings",
}
// Rust lints for vendor code.
diff --git a/rust/testing.go b/rust/testing.go
index 1afe27ef0..9534ab580 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -17,6 +17,7 @@ package rust
import (
"android/soong/android"
"android/soong/cc"
+ "android/soong/genrule"
)
func GatherRequiredDepsForTest() string {
@@ -211,6 +212,7 @@ func CreateTestContext(config android.Config) *android.TestContext {
ctx := android.NewTestArchContext(config)
android.RegisterPrebuiltMutators(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
+ genrule.RegisterGenruleBuildComponents(ctx)
cc.RegisterRequiredBuildComponentsForTest(ctx)
RegisterRequiredBuildComponentsForTest(ctx)
diff --git a/scripts/build-mainline-modules.sh b/scripts/build-mainline-modules.sh
index b93c88349..18174a452 100755
--- a/scripts/build-mainline-modules.sh
+++ b/scripts/build-mainline-modules.sh
@@ -29,14 +29,16 @@ MODULES_SDK_AND_EXPORTS=(
runtime-module-sdk
stats-log-api-gen-exports
statsd-module-sdk
+ statsd-module-sdk-for-art
tzdata-module-test-exports
)
# List of libraries installed on the platform that are needed for ART chroot
# testing.
PLATFORM_LIBRARIES=(
- liblog
+ heapprofd_client_api
libartpalette-system
+ liblog
)
# We want to create apex modules for all supported architectures.
diff --git a/scripts/hiddenapi/merge_csv.py b/scripts/hiddenapi/merge_csv.py
index 5ad61b2f6..b047aab71 100755
--- a/scripts/hiddenapi/merge_csv.py
+++ b/scripts/hiddenapi/merge_csv.py
@@ -20,6 +20,9 @@ Merge multiple CSV files, possibly with different columns.
import argparse
import csv
import io
+import heapq
+import itertools
+import operator
from zipfile import ZipFile
@@ -28,6 +31,10 @@ args_parser.add_argument('--header', help='Comma separated field names; '
'if missing determines the header from input files.')
args_parser.add_argument('--zip_input', help='Treat files as ZIP archives containing CSV files to merge.',
action="store_true")
+args_parser.add_argument('--key_field', help='The name of the field by which the rows should be sorted. '
+ 'Must be in the field names. '
+ 'Will be the first field in the output. '
+ 'All input files must be sorted by that field.')
args_parser.add_argument('--output', help='Output file for merged CSV.',
default='-', type=argparse.FileType('w'))
args_parser.add_argument('files', nargs=argparse.REMAINDER)
@@ -57,10 +64,29 @@ else:
headers = headers.union(reader.fieldnames)
fieldnames = sorted(headers)
-# Concatenate all files to output:
+# By default chain the csv readers together so that the resulting output is
+# the concatenation of the rows from each of them:
+all_rows = itertools.chain.from_iterable(csv_readers)
+
+if len(csv_readers) > 0:
+ keyField = args.key_field
+ if keyField:
+ assert keyField in fieldnames, (
+ "--key_field {} not found, must be one of {}\n").format(
+ keyField, ",".join(fieldnames))
+ # Make the key field the first field in the output
+ keyFieldIndex = fieldnames.index(args.key_field)
+ fieldnames.insert(0, fieldnames.pop(keyFieldIndex))
+ # Create an iterable that performs a lazy merge sort on the csv readers
+ # sorting the rows by the key field.
+ all_rows = heapq.merge(*csv_readers, key=operator.itemgetter(keyField))
+
+# Write all rows from the input files to the output:
writer = csv.DictWriter(args.output, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL,
dialect='unix', fieldnames=fieldnames)
writer.writeheader()
-for reader in csv_readers:
- for row in reader:
- writer.writerow(row)
+
+# Read all the rows from the input and write them to the output in the correct
+# order:
+for row in all_rows:
+ writer.writerow(row)
diff --git a/scripts/strip.sh b/scripts/strip.sh
index 40f018425..5b7a6da7e 100755
--- a/scripts/strip.sh
+++ b/scripts/strip.sh
@@ -89,7 +89,7 @@ do_strip_keep_mini_debug_info() {
"${CROSS_COMPILE}objcopy" --rename-section .debug_frame=saved_debug_frame "${outfile}.debug" "${outfile}.mini_debuginfo"
"${CROSS_COMPILE}objcopy" -S --remove-section .gdb_index --remove-section .comment --keep-symbols="${outfile}.keep_symbols" "${outfile}.mini_debuginfo"
"${CROSS_COMPILE}objcopy" --rename-section saved_debug_frame=.debug_frame "${outfile}.mini_debuginfo"
- "${XZ}" "${outfile}.mini_debuginfo"
+ "${XZ}" --block-size=64k --threads=0 "${outfile}.mini_debuginfo"
"${CLANG_BIN}/llvm-objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp"
rm -f "${outfile}.dynsyms" "${outfile}.funcsyms" "${outfile}.keep_symbols" "${outfile}.debug" "${outfile}.mini_debuginfo" "${outfile}.mini_debuginfo.xz"
diff --git a/sdk/bp_test.go b/sdk/bp_test.go
index e1edc5131..a7164a5e9 100644
--- a/sdk/bp_test.go
+++ b/sdk/bp_test.go
@@ -54,7 +54,7 @@ func propertyStructFixture() interface{} {
return str
}
-func checkPropertySetFixture(h *TestHelper, val interface{}, hasTags bool) {
+func checkPropertySetFixture(h android.TestHelper, val interface{}, hasTags bool) {
set := val.(*bpPropertySet)
h.AssertDeepEquals("wrong x value", "taxi", set.getValue("x"))
h.AssertDeepEquals("wrong y value", 1729, set.getValue("y"))
@@ -73,7 +73,7 @@ func checkPropertySetFixture(h *TestHelper, val interface{}, hasTags bool) {
}
func TestAddPropertySimple(t *testing.T) {
- h := &TestHelper{t}
+ h := android.TestHelper{t}
set := newPropertySet()
for name, val := range map[string]interface{}{
"x": "taxi",
@@ -92,7 +92,7 @@ func TestAddPropertySimple(t *testing.T) {
}
func TestAddPropertySubset(t *testing.T) {
- h := &TestHelper{t}
+ h := android.TestHelper{t}
getFixtureMap := map[string]func() interface{}{
"property set": propertySetFixture,
"property struct": propertyStructFixture,
@@ -139,7 +139,7 @@ func TestAddPropertySubset(t *testing.T) {
}
func TestAddPropertySetNew(t *testing.T) {
- h := &TestHelper{t}
+ h := android.TestHelper{t}
set := newPropertySet()
subset := set.AddPropertySet("sub")
subset.AddProperty("new", "d^^b")
@@ -147,7 +147,7 @@ func TestAddPropertySetNew(t *testing.T) {
}
func TestAddPropertySetExisting(t *testing.T) {
- h := &TestHelper{t}
+ h := android.TestHelper{t}
set := propertySetFixture().(*bpPropertySet)
subset := set.AddPropertySet("sub")
subset.AddProperty("new", "d^^b")
@@ -181,7 +181,7 @@ func (t removeFredTransformation) transformPropertySetAfterContents(name string,
func TestTransformRemoveProperty(t *testing.T) {
- helper := &TestHelper{t}
+ helper := android.TestHelper{t}
set := newPropertySet()
set.AddProperty("name", "name")
@@ -196,7 +196,7 @@ func TestTransformRemoveProperty(t *testing.T) {
func TestTransformRemovePropertySet(t *testing.T) {
- helper := &TestHelper{t}
+ helper := android.TestHelper{t}
set := newPropertySet()
set.AddProperty("name", "name")
diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go
index b1eebe98c..359177771 100644
--- a/sdk/cc_sdk_test.go
+++ b/sdk/cc_sdk_test.go
@@ -22,14 +22,14 @@ import (
)
var ccTestFs = map[string][]byte{
- "Test.cpp": nil,
- "include/Test.h": nil,
- "include-android/AndroidTest.h": nil,
- "include-host/HostTest.h": nil,
- "arm64/include/Arm64Test.h": nil,
- "libfoo.so": nil,
- "aidl/foo/bar/Test.aidl": nil,
- "some/where/stubslib.map.txt": nil,
+ "Test.cpp": nil,
+ "myinclude/Test.h": nil,
+ "myinclude-android/AndroidTest.h": nil,
+ "myinclude-host/HostTest.h": nil,
+ "arm64/include/Arm64Test.h": nil,
+ "libfoo.so": nil,
+ "aidl/foo/bar/Test.aidl": nil,
+ "some/where/stubslib.map.txt": nil,
}
func testSdkWithCc(t *testing.T, bp string) *testSdkResult {
@@ -102,16 +102,15 @@ func TestSdkCompileMultilibOverride(t *testing.T) {
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "mysdk_sdkmember@current",
- sdk_member_name: "sdkmember",
+ name: "sdkmember",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
host_supported: true,
- installable: false,
stl: "none",
compile_multilib: "64",
target: {
@@ -127,13 +126,17 @@ cc_prebuilt_library_shared {
},
},
}
+`),
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "sdkmember",
- prefer: false,
+ name: "mysdk_sdkmember@current",
+ sdk_member_name: "sdkmember",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
host_supported: true,
+ installable: false,
stl: "none",
compile_multilib: "64",
target: {
@@ -248,6 +251,7 @@ func TestBasicSdkWithCc(t *testing.T) {
uses_sdks: ["mysdk@1"],
key: "myapex.key",
certificate: ":myapex.cert",
+ updatable: false,
}
apex {
@@ -256,6 +260,7 @@ func TestBasicSdkWithCc(t *testing.T) {
uses_sdks: ["mysdk@2"],
key: "myapex.key",
certificate: ":myapex.cert",
+ updatable: false,
}
apex {
@@ -263,6 +268,7 @@ func TestBasicSdkWithCc(t *testing.T) {
native_shared_libs: ["sdkmember"],
key: "myapex.key",
certificate: ":myapex.cert",
+ updatable: false,
}
`)
@@ -348,12 +354,12 @@ func TestSnapshotWithObject(t *testing.T) {
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_object {
- name: "mysdk_crtobj@current",
- sdk_member_name: "crtobj",
+ name: "crtobj",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
stl: "none",
@@ -370,10 +376,14 @@ cc_prebuilt_object {
},
},
}
+`),
+ // Make sure that the generated sdk_snapshot uses the native_objects property.
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
cc_prebuilt_object {
- name: "crtobj",
- prefer: false,
+ name: "mysdk_crtobj@current",
+ sdk_member_name: "crtobj",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
stl: "none",
@@ -416,7 +426,7 @@ func TestSnapshotWithCcDuplicateHeaders(t *testing.T) {
srcs: [
"Test.cpp",
],
- export_include_dirs: ["include"],
+ export_include_dirs: ["myinclude"],
stl: "none",
}
@@ -425,14 +435,14 @@ func TestSnapshotWithCcDuplicateHeaders(t *testing.T) {
srcs: [
"Test.cpp",
],
- export_include_dirs: ["include"],
+ export_include_dirs: ["myinclude"],
stl: "none",
}
`)
result.CheckSnapshot("mysdk", "",
checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
.intermediates/mynativelib1/android_arm64_armv8-a_shared/mynativelib1.so -> arm64/lib/mynativelib1.so
.intermediates/mynativelib1/android_arm_armv7-a-neon_shared/mynativelib1.so -> arm/lib/mynativelib1.so
.intermediates/mynativelib2/android_arm64_armv8-a_shared/mynativelib2.so -> arm64/lib/mynativelib2.so
@@ -441,6 +451,76 @@ include/Test.h -> include/include/Test.h
)
}
+func TestSnapshotWithCcExportGeneratedHeaders(t *testing.T) {
+ result := testSdkWithCc(t, `
+ sdk {
+ name: "mysdk",
+ native_shared_libs: ["mynativelib"],
+ }
+
+ cc_library_shared {
+ name: "mynativelib",
+ srcs: [
+ "Test.cpp",
+ ],
+ generated_headers: [
+ "generated_foo",
+ ],
+ export_generated_headers: [
+ "generated_foo",
+ ],
+ export_include_dirs: ["myinclude"],
+ stl: "none",
+ }
+
+ genrule {
+ name: "generated_foo",
+ cmd: "generate-foo",
+ out: [
+ "generated_foo/protos/foo/bar.h",
+ ],
+ export_include_dirs: [
+ ".",
+ "protos",
+ ],
+ }
+ `)
+
+ result.CheckSnapshot("mysdk", "",
+ checkUnversionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
+
+cc_prebuilt_library_shared {
+ name: "mynativelib",
+ prefer: false,
+ visibility: ["//visibility:public"],
+ apex_available: ["//apex_available:platform"],
+ stl: "none",
+ compile_multilib: "both",
+ export_include_dirs: [
+ "include/myinclude",
+ "include_gen/generated_foo/gen",
+ "include_gen/generated_foo/gen/protos",
+ ],
+ arch: {
+ arm64: {
+ srcs: ["arm64/lib/mynativelib.so"],
+ },
+ arm: {
+ srcs: ["arm/lib/mynativelib.so"],
+ },
+ },
+}
+`),
+ checkAllCopyRules(`
+myinclude/Test.h -> include/myinclude/Test.h
+.intermediates/generated_foo/gen/generated_foo/protos/foo/bar.h -> include_gen/generated_foo/gen/generated_foo/protos/foo/bar.h
+.intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
+.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so
+`),
+ )
+}
+
// Verify that when the shared library has some common and some arch specific
// properties that the generated snapshot is optimized properly. Substruct
// handling is tested with the sanitize clauses (but note there's a lot of
@@ -458,7 +538,7 @@ func TestSnapshotWithCcSharedLibraryCommonProperties(t *testing.T) {
"Test.cpp",
"aidl/foo/bar/Test.aidl",
],
- export_include_dirs: ["include"],
+ export_include_dirs: ["myinclude"],
sanitize: {
fuzzer: false,
integer_overflow: true,
@@ -477,49 +557,17 @@ func TestSnapshotWithCcSharedLibraryCommonProperties(t *testing.T) {
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "mysdk_mynativelib@current",
- sdk_member_name: "mynativelib",
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
- installable: false,
- stl: "none",
- compile_multilib: "both",
- export_include_dirs: ["include/include"],
- sanitize: {
- fuzzer: false,
- diag: {
- undefined: false,
- },
- },
- arch: {
- arm64: {
- srcs: ["arm64/lib/mynativelib.so"],
- export_system_include_dirs: ["arm64/include/arm64/include"],
- sanitize: {
- integer_overflow: false,
- },
- },
- arm: {
- srcs: ["arm/lib/mynativelib.so"],
- sanitize: {
- integer_overflow: true,
- },
- },
- },
-}
-
-cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
stl: "none",
compile_multilib: "both",
- export_include_dirs: ["include/include"],
+ export_include_dirs: ["include/myinclude"],
sanitize: {
fuzzer: false,
diag: {
@@ -542,15 +590,9 @@ cc_prebuilt_library_shared {
},
},
}
-
-sdk_snapshot {
- name: "mysdk@current",
- visibility: ["//visibility:public"],
- native_shared_libs: ["mysdk_mynativelib@current"],
-}
`),
checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
.intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
arm64/include/Arm64Test.h -> arm64/include/arm64/include/Arm64Test.h
.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so`),
@@ -574,15 +616,14 @@ func TestSnapshotWithCcBinary(t *testing.T) {
`)
result.CheckSnapshot("mymodule_exports", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_binary {
- name: "mymodule_exports_mynativebinary@current",
- sdk_member_name: "mynativebinary",
+ name: "mynativebinary",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
- installable: false,
compile_multilib: "both",
arch: {
arm64: {
@@ -593,12 +634,17 @@ cc_prebuilt_binary {
},
},
}
+`),
+ // Make sure that the generated sdk_snapshot uses the native_binaries property.
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
cc_prebuilt_binary {
- name: "mynativebinary",
- prefer: false,
+ name: "mymodule_exports_mynativebinary@current",
+ sdk_member_name: "mynativebinary",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
+ installable: false,
compile_multilib: "both",
arch: {
arm64: {
@@ -655,17 +701,16 @@ func TestMultipleHostOsTypesSnapshotWithCcBinary(t *testing.T) {
`)
result.CheckSnapshot("myexports", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_binary {
- name: "myexports_mynativebinary@current",
- sdk_member_name: "mynativebinary",
+ name: "mynativebinary",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
- installable: false,
stl: "none",
target: {
host: {
@@ -691,14 +736,18 @@ cc_prebuilt_binary {
},
},
}
+`),
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
cc_prebuilt_binary {
- name: "mynativebinary",
- prefer: false,
+ name: "myexports_mynativebinary@current",
+ sdk_member_name: "mynativebinary",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
+ installable: false,
stl: "none",
target: {
host: {
@@ -805,17 +854,16 @@ func TestSnapshotWithSingleHostOsType(t *testing.T) {
result := runTests(t, ctx, config)
result.CheckSnapshot("myexports", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_binary {
- name: "myexports_mynativebinary@current",
- sdk_member_name: "mynativebinary",
+ name: "mynativebinary",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
- installable: false,
stl: "none",
compile_multilib: "64",
target: {
@@ -829,8 +877,8 @@ cc_prebuilt_binary {
},
}
-cc_prebuilt_binary {
- name: "mynativebinary",
+cc_prebuilt_library_shared {
+ name: "mynativelib",
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
@@ -844,14 +892,17 @@ cc_prebuilt_binary {
},
linux_bionic_x86_64: {
enabled: true,
- srcs: ["x86_64/bin/mynativebinary"],
+ srcs: ["x86_64/lib/mynativelib.so"],
},
},
}
+`),
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
-cc_prebuilt_library_shared {
- name: "myexports_mynativelib@current",
- sdk_member_name: "mynativelib",
+cc_prebuilt_binary {
+ name: "myexports_mynativebinary@current",
+ sdk_member_name: "mynativebinary",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
@@ -865,18 +916,19 @@ cc_prebuilt_library_shared {
},
linux_bionic_x86_64: {
enabled: true,
- srcs: ["x86_64/lib/mynativelib.so"],
+ srcs: ["x86_64/bin/mynativebinary"],
},
},
}
cc_prebuilt_library_shared {
- name: "mynativelib",
- prefer: false,
+ name: "myexports_mynativelib@current",
+ sdk_member_name: "mynativelib",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
+ installable: false,
stl: "none",
compile_multilib: "64",
target: {
@@ -940,17 +992,16 @@ func TestSnapshotWithCcStaticNocrtBinary(t *testing.T) {
`)
result.CheckSnapshot("mymodule_exports", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_binary {
- name: "mymodule_exports_linker@current",
- sdk_member_name: "linker",
+ name: "linker",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
- installable: false,
stl: "none",
compile_multilib: "both",
static_executable: true,
@@ -969,14 +1020,18 @@ cc_prebuilt_binary {
},
},
}
+`),
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
cc_prebuilt_binary {
- name: "linker",
- prefer: false,
+ name: "mymodule_exports_linker@current",
+ sdk_member_name: "linker",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
+ installable: false,
stl: "none",
compile_multilib: "both",
static_executable: true,
@@ -1036,7 +1091,7 @@ func TestSnapshotWithCcSharedLibrary(t *testing.T) {
"aidl/foo/bar/Test.aidl",
],
apex_available: ["apex1", "apex2"],
- export_include_dirs: ["include"],
+ export_include_dirs: ["myinclude"],
aidl: {
export_aidl_headers: true,
},
@@ -1045,34 +1100,10 @@ func TestSnapshotWithCcSharedLibrary(t *testing.T) {
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "mysdk_mynativelib@current",
- sdk_member_name: "mynativelib",
- visibility: ["//visibility:public"],
- apex_available: [
- "apex1",
- "apex2",
- ],
- installable: false,
- stl: "none",
- compile_multilib: "both",
- export_include_dirs: ["include/include"],
- arch: {
- arm64: {
- srcs: ["arm64/lib/mynativelib.so"],
- export_include_dirs: ["arm64/include_gen/mynativelib"],
- },
- arm: {
- srcs: ["arm/lib/mynativelib.so"],
- export_include_dirs: ["arm/include_gen/mynativelib"],
- },
- },
-}
-
-cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
visibility: ["//visibility:public"],
@@ -1082,35 +1113,29 @@ cc_prebuilt_library_shared {
],
stl: "none",
compile_multilib: "both",
- export_include_dirs: ["include/include"],
+ export_include_dirs: ["include/myinclude"],
arch: {
arm64: {
srcs: ["arm64/lib/mynativelib.so"],
- export_include_dirs: ["arm64/include_gen/mynativelib"],
+ export_include_dirs: ["arm64/include_gen/mynativelib/android_arm64_armv8-a_shared/gen/aidl"],
},
arm: {
srcs: ["arm/lib/mynativelib.so"],
- export_include_dirs: ["arm/include_gen/mynativelib"],
+ export_include_dirs: ["arm/include_gen/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl"],
},
},
}
-
-sdk_snapshot {
- name: "mysdk@current",
- visibility: ["//visibility:public"],
- native_shared_libs: ["mysdk_mynativelib@current"],
-}
`),
checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
.intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
-.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/Test.h -> arm64/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BnTest.h -> arm64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BpTest.h -> arm64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/Test.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BnTest.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BpTest.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_shared/gen/aidl/aidl/foo/bar/BpTest.h
.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so
-.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/Test.h -> arm/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BnTest.h -> arm/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BpTest.h -> arm/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/Test.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BnTest.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BpTest.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_shared/gen/aidl/aidl/foo/bar/BpTest.h
`),
)
}
@@ -1176,32 +1201,10 @@ func TestSnapshotWithCcSharedLibrarySharedLibs(t *testing.T) {
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "mysdk_mynativelib@current",
- sdk_member_name: "mynativelib",
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
- installable: false,
- stl: "none",
- compile_multilib: "both",
- shared_libs: [
- "mysdk_myothernativelib@current",
- "libc",
- ],
- arch: {
- arm64: {
- srcs: ["arm64/lib/mynativelib.so"],
- },
- arm: {
- srcs: ["arm/lib/mynativelib.so"],
- },
- },
-}
-
-cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
visibility: ["//visibility:public"],
@@ -1223,25 +1226,6 @@ cc_prebuilt_library_shared {
}
cc_prebuilt_library_shared {
- name: "mysdk_myothernativelib@current",
- sdk_member_name: "myothernativelib",
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
- installable: false,
- stl: "none",
- compile_multilib: "both",
- system_shared_libs: ["libm"],
- arch: {
- arm64: {
- srcs: ["arm64/lib/myothernativelib.so"],
- },
- arm: {
- srcs: ["arm/lib/myothernativelib.so"],
- },
- },
-}
-
-cc_prebuilt_library_shared {
name: "myothernativelib",
prefer: false,
visibility: ["//visibility:public"],
@@ -1260,24 +1244,6 @@ cc_prebuilt_library_shared {
}
cc_prebuilt_library_shared {
- name: "mysdk_mysystemnativelib@current",
- sdk_member_name: "mysystemnativelib",
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
- installable: false,
- stl: "none",
- compile_multilib: "both",
- arch: {
- arm64: {
- srcs: ["arm64/lib/mysystemnativelib.so"],
- },
- arm: {
- srcs: ["arm/lib/mysystemnativelib.so"],
- },
- },
-}
-
-cc_prebuilt_library_shared {
name: "mysystemnativelib",
prefer: false,
visibility: ["//visibility:public"],
@@ -1293,16 +1259,6 @@ cc_prebuilt_library_shared {
},
},
}
-
-sdk_snapshot {
- name: "mysdk@current",
- visibility: ["//visibility:public"],
- native_shared_libs: [
- "mysdk_mynativelib@current",
- "mysdk_myothernativelib@current",
- "mysdk_mysystemnativelib@current",
- ],
-}
`),
checkAllCopyRules(`
.intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
@@ -1332,7 +1288,7 @@ func TestHostSnapshotWithCcSharedLibrary(t *testing.T) {
"Test.cpp",
"aidl/foo/bar/Test.aidl",
],
- export_include_dirs: ["include"],
+ export_include_dirs: ["myinclude"],
aidl: {
export_aidl_headers: true,
},
@@ -1342,21 +1298,20 @@ func TestHostSnapshotWithCcSharedLibrary(t *testing.T) {
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "mysdk_mynativelib@current",
- sdk_member_name: "mynativelib",
+ name: "mynativelib",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
- installable: false,
sdk_version: "minimum",
stl: "none",
compile_multilib: "both",
- export_include_dirs: ["include/include"],
+ export_include_dirs: ["include/myinclude"],
target: {
host: {
enabled: false,
@@ -1364,27 +1319,31 @@ cc_prebuilt_library_shared {
linux_glibc_x86_64: {
enabled: true,
srcs: ["x86_64/lib/mynativelib.so"],
- export_include_dirs: ["x86_64/include_gen/mynativelib"],
+ export_include_dirs: ["x86_64/include_gen/mynativelib/linux_glibc_x86_64_shared/gen/aidl"],
},
linux_glibc_x86: {
enabled: true,
srcs: ["x86/lib/mynativelib.so"],
- export_include_dirs: ["x86/include_gen/mynativelib"],
+ export_include_dirs: ["x86/include_gen/mynativelib/linux_glibc_x86_shared/gen/aidl"],
},
},
}
+`),
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "mynativelib",
- prefer: false,
+ name: "mysdk_mynativelib@current",
+ sdk_member_name: "mynativelib",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
+ installable: false,
sdk_version: "minimum",
stl: "none",
compile_multilib: "both",
- export_include_dirs: ["include/include"],
+ export_include_dirs: ["include/myinclude"],
target: {
host: {
enabled: false,
@@ -1392,12 +1351,12 @@ cc_prebuilt_library_shared {
linux_glibc_x86_64: {
enabled: true,
srcs: ["x86_64/lib/mynativelib.so"],
- export_include_dirs: ["x86_64/include_gen/mynativelib"],
+ export_include_dirs: ["x86_64/include_gen/mynativelib/linux_glibc_x86_64_shared/gen/aidl"],
},
linux_glibc_x86: {
enabled: true,
srcs: ["x86/lib/mynativelib.so"],
- export_include_dirs: ["x86/include_gen/mynativelib"],
+ export_include_dirs: ["x86/include_gen/mynativelib/linux_glibc_x86_shared/gen/aidl"],
},
},
}
@@ -1422,15 +1381,15 @@ sdk_snapshot {
}
`),
checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
.intermediates/mynativelib/linux_glibc_x86_64_shared/mynativelib.so -> x86_64/lib/mynativelib.so
-.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_shared/gen/aidl/aidl/foo/bar/BpTest.h
.intermediates/mynativelib/linux_glibc_x86_shared/mynativelib.so -> x86/lib/mynativelib.so
-.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/Test.h -> x86/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BnTest.h -> x86/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BpTest.h -> x86/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/Test.h -> x86/include_gen/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BnTest.h -> x86/include_gen/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BpTest.h -> x86/include_gen/mynativelib/linux_glibc_x86_shared/gen/aidl/aidl/foo/bar/BpTest.h
`),
)
}
@@ -1466,17 +1425,16 @@ func TestMultipleHostOsTypesSnapshotWithCcSharedLibrary(t *testing.T) {
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "mysdk_mynativelib@current",
- sdk_member_name: "mynativelib",
+ name: "mynativelib",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
- installable: false,
stl: "none",
target: {
host: {
@@ -1502,14 +1460,18 @@ cc_prebuilt_library_shared {
},
},
}
+`),
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "mynativelib",
- prefer: false,
+ name: "mysdk_mynativelib@current",
+ sdk_member_name: "mynativelib",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
+ installable: false,
stl: "none",
target: {
host: {
@@ -1582,7 +1544,7 @@ func TestSnapshotWithCcStaticLibrary(t *testing.T) {
"Test.cpp",
"aidl/foo/bar/Test.aidl",
],
- export_include_dirs: ["include"],
+ export_include_dirs: ["myinclude"],
aidl: {
export_aidl_headers: true,
},
@@ -1591,66 +1553,39 @@ func TestSnapshotWithCcStaticLibrary(t *testing.T) {
`)
result.CheckSnapshot("myexports", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_static {
- name: "myexports_mynativelib@current",
- sdk_member_name: "mynativelib",
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
- installable: false,
- stl: "none",
- compile_multilib: "both",
- export_include_dirs: ["include/include"],
- arch: {
- arm64: {
- srcs: ["arm64/lib/mynativelib.a"],
- export_include_dirs: ["arm64/include_gen/mynativelib"],
- },
- arm: {
- srcs: ["arm/lib/mynativelib.a"],
- export_include_dirs: ["arm/include_gen/mynativelib"],
- },
- },
-}
-
-cc_prebuilt_library_static {
name: "mynativelib",
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
stl: "none",
compile_multilib: "both",
- export_include_dirs: ["include/include"],
+ export_include_dirs: ["include/myinclude"],
arch: {
arm64: {
srcs: ["arm64/lib/mynativelib.a"],
- export_include_dirs: ["arm64/include_gen/mynativelib"],
+ export_include_dirs: ["arm64/include_gen/mynativelib/android_arm64_armv8-a_static/gen/aidl"],
},
arm: {
srcs: ["arm/lib/mynativelib.a"],
- export_include_dirs: ["arm/include_gen/mynativelib"],
+ export_include_dirs: ["arm/include_gen/mynativelib/android_arm_armv7-a-neon_static/gen/aidl"],
},
},
}
-
-module_exports_snapshot {
- name: "myexports@current",
- visibility: ["//visibility:public"],
- native_static_libs: ["myexports_mynativelib@current"],
-}
`),
checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
.intermediates/mynativelib/android_arm64_armv8-a_static/mynativelib.a -> arm64/lib/mynativelib.a
-.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/Test.h -> arm64/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BnTest.h -> arm64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BpTest.h -> arm64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/Test.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BnTest.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BpTest.h -> arm64/include_gen/mynativelib/android_arm64_armv8-a_static/gen/aidl/aidl/foo/bar/BpTest.h
.intermediates/mynativelib/android_arm_armv7-a-neon_static/mynativelib.a -> arm/lib/mynativelib.a
-.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/Test.h -> arm/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BnTest.h -> arm/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BpTest.h -> arm/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/Test.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BnTest.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BpTest.h -> arm/include_gen/mynativelib/android_arm_armv7-a-neon_static/gen/aidl/aidl/foo/bar/BpTest.h
`),
)
}
@@ -1672,7 +1607,7 @@ func TestHostSnapshotWithCcStaticLibrary(t *testing.T) {
"Test.cpp",
"aidl/foo/bar/Test.aidl",
],
- export_include_dirs: ["include"],
+ export_include_dirs: ["myinclude"],
aidl: {
export_aidl_headers: true,
},
@@ -1681,20 +1616,19 @@ func TestHostSnapshotWithCcStaticLibrary(t *testing.T) {
`)
result.CheckSnapshot("myexports", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_static {
- name: "myexports_mynativelib@current",
- sdk_member_name: "mynativelib",
+ name: "mynativelib",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
- installable: false,
stl: "none",
compile_multilib: "both",
- export_include_dirs: ["include/include"],
+ export_include_dirs: ["include/myinclude"],
target: {
host: {
enabled: false,
@@ -1702,26 +1636,30 @@ cc_prebuilt_library_static {
linux_glibc_x86_64: {
enabled: true,
srcs: ["x86_64/lib/mynativelib.a"],
- export_include_dirs: ["x86_64/include_gen/mynativelib"],
+ export_include_dirs: ["x86_64/include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl"],
},
linux_glibc_x86: {
enabled: true,
srcs: ["x86/lib/mynativelib.a"],
- export_include_dirs: ["x86/include_gen/mynativelib"],
+ export_include_dirs: ["x86/include_gen/mynativelib/linux_glibc_x86_static/gen/aidl"],
},
},
}
+`),
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_static {
- name: "mynativelib",
- prefer: false,
+ name: "myexports_mynativelib@current",
+ sdk_member_name: "mynativelib",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
+ installable: false,
stl: "none",
compile_multilib: "both",
- export_include_dirs: ["include/include"],
+ export_include_dirs: ["include/myinclude"],
target: {
host: {
enabled: false,
@@ -1729,12 +1667,12 @@ cc_prebuilt_library_static {
linux_glibc_x86_64: {
enabled: true,
srcs: ["x86_64/lib/mynativelib.a"],
- export_include_dirs: ["x86_64/include_gen/mynativelib"],
+ export_include_dirs: ["x86_64/include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl"],
},
linux_glibc_x86: {
enabled: true,
srcs: ["x86/lib/mynativelib.a"],
- export_include_dirs: ["x86/include_gen/mynativelib"],
+ export_include_dirs: ["x86/include_gen/mynativelib/linux_glibc_x86_static/gen/aidl"],
},
},
}
@@ -1759,15 +1697,15 @@ module_exports_snapshot {
}
`),
checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
.intermediates/mynativelib/linux_glibc_x86_64_static/mynativelib.a -> x86_64/lib/mynativelib.a
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h
.intermediates/mynativelib/linux_glibc_x86_static/mynativelib.a -> x86/lib/mynativelib.a
-.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/Test.h -> x86/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86/include_gen/mynativelib/aidl/foo/bar/BpTest.h
+.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/Test.h -> x86/include_gen/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86/include_gen/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86/include_gen/mynativelib/linux_glibc_x86_static/gen/aidl/aidl/foo/bar/BpTest.h
`),
)
}
@@ -1784,7 +1722,7 @@ func TestSnapshotWithCcLibrary(t *testing.T) {
srcs: [
"Test.cpp",
],
- export_include_dirs: ["include"],
+ export_include_dirs: ["myinclude"],
stl: "none",
recovery_available: true,
vendor_available: true,
@@ -1792,20 +1730,19 @@ func TestSnapshotWithCcLibrary(t *testing.T) {
`)
result.CheckSnapshot("myexports", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library {
- name: "myexports_mynativelib@current",
- sdk_member_name: "mynativelib",
+ name: "mynativelib",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
- installable: false,
recovery_available: true,
vendor_available: true,
stl: "none",
compile_multilib: "both",
- export_include_dirs: ["include/include"],
+ export_include_dirs: ["include/myinclude"],
arch: {
arm64: {
static: {
@@ -1825,17 +1762,22 @@ cc_prebuilt_library {
},
},
}
+`),
+ // Make sure that the generated sdk_snapshot uses the native_libs property.
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library {
- name: "mynativelib",
- prefer: false,
+ name: "myexports_mynativelib@current",
+ sdk_member_name: "mynativelib",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
+ installable: false,
recovery_available: true,
vendor_available: true,
stl: "none",
compile_multilib: "both",
- export_include_dirs: ["include/include"],
+ export_include_dirs: ["include/myinclude"],
arch: {
arm64: {
static: {
@@ -1863,7 +1805,7 @@ module_exports_snapshot {
}
`),
checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
.intermediates/mynativelib/android_arm64_armv8-a_static/mynativelib.a -> arm64/lib/mynativelib.a
.intermediates/mynativelib/android_arm64_armv8-a_shared/mynativelib.so -> arm64/lib/mynativelib.so
.intermediates/mynativelib/android_arm_armv7-a-neon_static/mynativelib.a -> arm/lib/mynativelib.a
@@ -1893,7 +1835,7 @@ func TestHostSnapshotWithMultiLib64(t *testing.T) {
"Test.cpp",
"aidl/foo/bar/Test.aidl",
],
- export_include_dirs: ["include"],
+ export_include_dirs: ["myinclude"],
aidl: {
export_aidl_headers: true,
},
@@ -1902,20 +1844,22 @@ func TestHostSnapshotWithMultiLib64(t *testing.T) {
`)
result.CheckSnapshot("myexports", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_static {
- name: "myexports_mynativelib@current",
- sdk_member_name: "mynativelib",
+ name: "mynativelib",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
- installable: false,
stl: "none",
compile_multilib: "64",
- export_include_dirs: ["include/include"],
+ export_include_dirs: [
+ "include/myinclude",
+ "include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl",
+ ],
target: {
host: {
enabled: false,
@@ -1923,21 +1867,27 @@ cc_prebuilt_library_static {
linux_glibc_x86_64: {
enabled: true,
srcs: ["x86_64/lib/mynativelib.a"],
- export_include_dirs: ["x86_64/include_gen/mynativelib"],
},
},
}
+`),
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_static {
- name: "mynativelib",
- prefer: false,
+ name: "myexports_mynativelib@current",
+ sdk_member_name: "mynativelib",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
+ installable: false,
stl: "none",
compile_multilib: "64",
- export_include_dirs: ["include/include"],
+ export_include_dirs: [
+ "include/myinclude",
+ "include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl",
+ ],
target: {
host: {
enabled: false,
@@ -1945,7 +1895,6 @@ cc_prebuilt_library_static {
linux_glibc_x86_64: {
enabled: true,
srcs: ["x86_64/lib/mynativelib.a"],
- export_include_dirs: ["x86_64/include_gen/mynativelib"],
},
},
}
@@ -1965,13 +1914,14 @@ module_exports_snapshot {
enabled: true,
},
},
-}`),
+}
+`),
checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h -> include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h -> include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h
+.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h -> include_gen/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h
.intermediates/mynativelib/linux_glibc_x86_64_static/mynativelib.a -> x86_64/lib/mynativelib.a
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/Test.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/Test.h
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BnTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BnTest.h
-.intermediates/mynativelib/linux_glibc_x86_64_static/gen/aidl/aidl/foo/bar/BpTest.h -> x86_64/include_gen/mynativelib/aidl/foo/bar/BpTest.h
`),
)
}
@@ -1985,43 +1935,27 @@ func TestSnapshotWithCcHeadersLibrary(t *testing.T) {
cc_library_headers {
name: "mynativeheaders",
- export_include_dirs: ["include"],
+ export_include_dirs: ["myinclude"],
stl: "none",
}
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_headers {
- name: "mysdk_mynativeheaders@current",
- sdk_member_name: "mynativeheaders",
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
- stl: "none",
- compile_multilib: "both",
- export_include_dirs: ["include/include"],
-}
-
-cc_prebuilt_library_headers {
name: "mynativeheaders",
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
stl: "none",
compile_multilib: "both",
- export_include_dirs: ["include/include"],
-}
-
-sdk_snapshot {
- name: "mysdk@current",
- visibility: ["//visibility:public"],
- native_header_libs: ["mysdk_mynativeheaders@current"],
+ export_include_dirs: ["include/myinclude"],
}
`),
checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
`),
)
}
@@ -2039,25 +1973,25 @@ func TestHostSnapshotWithCcHeadersLibrary(t *testing.T) {
name: "mynativeheaders",
device_supported: false,
host_supported: true,
- export_include_dirs: ["include"],
+ export_include_dirs: ["myinclude"],
stl: "none",
}
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_headers {
- name: "mysdk_mynativeheaders@current",
- sdk_member_name: "mynativeheaders",
+ name: "mynativeheaders",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
stl: "none",
compile_multilib: "both",
- export_include_dirs: ["include/include"],
+ export_include_dirs: ["include/myinclude"],
target: {
host: {
enabled: false,
@@ -2070,17 +2004,20 @@ cc_prebuilt_library_headers {
},
},
}
+`),
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_headers {
- name: "mynativeheaders",
- prefer: false,
+ name: "mysdk_mynativeheaders@current",
+ sdk_member_name: "mynativeheaders",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
device_supported: false,
host_supported: true,
stl: "none",
compile_multilib: "both",
- export_include_dirs: ["include/include"],
+ export_include_dirs: ["include/myinclude"],
target: {
host: {
enabled: false,
@@ -2114,7 +2051,7 @@ sdk_snapshot {
}
`),
checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
`),
)
}
@@ -2131,40 +2068,40 @@ func TestDeviceAndHostSnapshotWithCcHeadersLibrary(t *testing.T) {
name: "mynativeheaders",
host_supported: true,
stl: "none",
- export_system_include_dirs: ["include"],
+ export_system_include_dirs: ["myinclude"],
target: {
android: {
- export_include_dirs: ["include-android"],
+ export_include_dirs: ["myinclude-android"],
},
host: {
- export_include_dirs: ["include-host"],
+ export_include_dirs: ["myinclude-host"],
},
},
}
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_headers {
- name: "mysdk_mynativeheaders@current",
- sdk_member_name: "mynativeheaders",
+ name: "mynativeheaders",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
host_supported: true,
stl: "none",
compile_multilib: "both",
- export_system_include_dirs: ["common_os/include/include"],
+ export_system_include_dirs: ["common_os/include/myinclude"],
target: {
host: {
enabled: false,
},
android: {
- export_include_dirs: ["android/include/include-android"],
+ export_include_dirs: ["android/include/myinclude-android"],
},
linux_glibc: {
- export_include_dirs: ["linux_glibc/include/include-host"],
+ export_include_dirs: ["linux_glibc/include/myinclude-host"],
},
linux_glibc_x86_64: {
enabled: true,
@@ -2174,25 +2111,29 @@ cc_prebuilt_library_headers {
},
},
}
+`),
+ // Verifi
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_headers {
- name: "mynativeheaders",
- prefer: false,
+ name: "mysdk_mynativeheaders@current",
+ sdk_member_name: "mynativeheaders",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
host_supported: true,
stl: "none",
compile_multilib: "both",
- export_system_include_dirs: ["common_os/include/include"],
+ export_system_include_dirs: ["common_os/include/myinclude"],
target: {
host: {
enabled: false,
},
android: {
- export_include_dirs: ["android/include/include-android"],
+ export_include_dirs: ["android/include/myinclude-android"],
},
linux_glibc: {
- export_include_dirs: ["linux_glibc/include/include-host"],
+ export_include_dirs: ["linux_glibc/include/myinclude-host"],
},
linux_glibc_x86_64: {
enabled: true,
@@ -2222,9 +2163,9 @@ sdk_snapshot {
}
`),
checkAllCopyRules(`
-include/Test.h -> common_os/include/include/Test.h
-include-android/AndroidTest.h -> android/include/include-android/AndroidTest.h
-include-host/HostTest.h -> linux_glibc/include/include-host/HostTest.h
+myinclude/Test.h -> common_os/include/myinclude/Test.h
+myinclude-android/AndroidTest.h -> android/include/myinclude-android/AndroidTest.h
+myinclude-host/HostTest.h -> linux_glibc/include/myinclude-host/HostTest.h
`),
)
}
@@ -2253,27 +2194,10 @@ func TestSystemSharedLibPropagation(t *testing.T) {
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "mysdk_sslnil@current",
- sdk_member_name: "sslnil",
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
- installable: false,
- compile_multilib: "both",
- arch: {
- arm64: {
- srcs: ["arm64/lib/sslnil.so"],
- },
- arm: {
- srcs: ["arm/lib/sslnil.so"],
- },
- },
-}
-
-cc_prebuilt_library_shared {
name: "sslnil",
prefer: false,
visibility: ["//visibility:public"],
@@ -2290,24 +2214,6 @@ cc_prebuilt_library_shared {
}
cc_prebuilt_library_shared {
- name: "mysdk_sslempty@current",
- sdk_member_name: "sslempty",
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
- installable: false,
- compile_multilib: "both",
- system_shared_libs: [],
- arch: {
- arm64: {
- srcs: ["arm64/lib/sslempty.so"],
- },
- arm: {
- srcs: ["arm/lib/sslempty.so"],
- },
- },
-}
-
-cc_prebuilt_library_shared {
name: "sslempty",
prefer: false,
visibility: ["//visibility:public"],
@@ -2325,24 +2231,6 @@ cc_prebuilt_library_shared {
}
cc_prebuilt_library_shared {
- name: "mysdk_sslnonempty@current",
- sdk_member_name: "sslnonempty",
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
- installable: false,
- compile_multilib: "both",
- system_shared_libs: ["mysdk_sslnil@current"],
- arch: {
- arm64: {
- srcs: ["arm64/lib/sslnonempty.so"],
- },
- arm: {
- srcs: ["arm/lib/sslnonempty.so"],
- },
- },
-}
-
-cc_prebuilt_library_shared {
name: "sslnonempty",
prefer: false,
visibility: ["//visibility:public"],
@@ -2358,16 +2246,6 @@ cc_prebuilt_library_shared {
},
},
}
-
-sdk_snapshot {
- name: "mysdk@current",
- visibility: ["//visibility:public"],
- native_shared_libs: [
- "mysdk_sslnil@current",
- "mysdk_sslempty@current",
- "mysdk_sslnonempty@current",
- ],
-}
`))
result = testSdkWithCc(t, `
@@ -2389,16 +2267,15 @@ sdk_snapshot {
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "mysdk_sslvariants@current",
- sdk_member_name: "sslvariants",
+ name: "sslvariants",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
host_supported: true,
- installable: false,
compile_multilib: "both",
target: {
host: {
@@ -2423,13 +2300,17 @@ cc_prebuilt_library_shared {
},
},
}
+`),
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "sslvariants",
- prefer: false,
+ name: "mysdk_sslvariants@current",
+ sdk_member_name: "sslvariants",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
host_supported: true,
+ installable: false,
compile_multilib: "both",
target: {
host: {
@@ -2497,34 +2378,10 @@ func TestStubsLibrary(t *testing.T) {
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "mysdk_stubslib@current",
- sdk_member_name: "stubslib",
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
- installable: false,
- compile_multilib: "both",
- stubs: {
- versions: [
- "1",
- "2",
- "3",
- ],
- },
- arch: {
- arm64: {
- srcs: ["arm64/lib/stubslib.so"],
- },
- arm: {
- srcs: ["arm/lib/stubslib.so"],
- },
- },
-}
-
-cc_prebuilt_library_shared {
name: "stubslib",
prefer: false,
visibility: ["//visibility:public"],
@@ -2546,12 +2403,6 @@ cc_prebuilt_library_shared {
},
},
}
-
-sdk_snapshot {
- name: "mysdk@current",
- visibility: ["//visibility:public"],
- native_shared_libs: ["mysdk_stubslib@current"],
-}
`))
}
@@ -2580,16 +2431,15 @@ func TestDeviceAndHostSnapshotWithStubsLibrary(t *testing.T) {
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "mysdk_stubslib@current",
- sdk_member_name: "stubslib",
+ name: "stubslib",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
host_supported: true,
- installable: false,
compile_multilib: "both",
stubs: {
versions: [
@@ -2618,13 +2468,17 @@ cc_prebuilt_library_shared {
},
},
}
+`),
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "stubslib",
- prefer: false,
+ name: "mysdk_stubslib@current",
+ sdk_member_name: "stubslib",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
host_supported: true,
+ installable: false,
compile_multilib: "both",
stubs: {
versions: [
@@ -2690,16 +2544,15 @@ func TestUniqueHostSoname(t *testing.T) {
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "mysdk_mylib@current",
- sdk_member_name: "mylib",
+ name: "mylib",
+ prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
host_supported: true,
- installable: false,
unique_host_soname: true,
compile_multilib: "both",
target: {
@@ -2722,13 +2575,17 @@ cc_prebuilt_library_shared {
},
},
}
+`),
+ checkVersionedAndroidBpContents(`
+// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "mylib",
- prefer: false,
+ name: "mysdk_mylib@current",
+ sdk_member_name: "mylib",
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
host_supported: true,
+ installable: false,
unique_host_soname: true,
compile_multilib: "both",
target: {
@@ -2789,7 +2646,7 @@ func TestNoSanitizerMembers(t *testing.T) {
cc_library_shared {
name: "mynativelib",
srcs: ["Test.cpp"],
- export_include_dirs: ["include"],
+ export_include_dirs: ["myinclude"],
arch: {
arm64: {
export_system_include_dirs: ["arm64/include"],
@@ -2802,34 +2659,16 @@ func TestNoSanitizerMembers(t *testing.T) {
`)
result.CheckSnapshot("mysdk", "",
- checkAndroidBpContents(`
+ checkUnversionedAndroidBpContents(`
// This is auto-generated. DO NOT EDIT.
cc_prebuilt_library_shared {
- name: "mysdk_mynativelib@current",
- sdk_member_name: "mynativelib",
- visibility: ["//visibility:public"],
- apex_available: ["//apex_available:platform"],
- installable: false,
- compile_multilib: "both",
- export_include_dirs: ["include/include"],
- arch: {
- arm64: {
- export_system_include_dirs: ["arm64/include/arm64/include"],
- },
- arm: {
- srcs: ["arm/lib/mynativelib.so"],
- },
- },
-}
-
-cc_prebuilt_library_shared {
name: "mynativelib",
prefer: false,
visibility: ["//visibility:public"],
apex_available: ["//apex_available:platform"],
compile_multilib: "both",
- export_include_dirs: ["include/include"],
+ export_include_dirs: ["include/myinclude"],
arch: {
arm64: {
export_system_include_dirs: ["arm64/include/arm64/include"],
@@ -2839,15 +2678,9 @@ cc_prebuilt_library_shared {
},
},
}
-
-sdk_snapshot {
- name: "mysdk@current",
- visibility: ["//visibility:public"],
- native_shared_libs: ["mysdk_mynativelib@current"],
-}
`),
checkAllCopyRules(`
-include/Test.h -> include/include/Test.h
+myinclude/Test.h -> include/myinclude/Test.h
arm64/include/Arm64Test.h -> arm64/include/arm64/include/Arm64Test.h
.intermediates/mynativelib/android_arm_armv7-a-neon_shared/mynativelib.so -> arm/lib/mynativelib.so`),
)
diff --git a/sdk/exports.go b/sdk/exports.go
index d3130574e..9a0ba4e32 100644
--- a/sdk/exports.go
+++ b/sdk/exports.go
@@ -17,8 +17,12 @@ package sdk
import "android/soong/android"
func init() {
- android.RegisterModuleType("module_exports", ModuleExportsFactory)
- android.RegisterModuleType("module_exports_snapshot", ModuleExportsSnapshotsFactory)
+ registerModuleExportsBuildComponents(android.InitRegistrationContext)
+}
+
+func registerModuleExportsBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("module_exports", ModuleExportsFactory)
+ ctx.RegisterModuleType("module_exports_snapshot", ModuleExportsSnapshotsFactory)
}
// module_exports defines the exports of a mainline module. The exports are Soong modules
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 17a6ca9b8..111b22c68 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -211,6 +211,7 @@ func TestBasicSdkWithJavaLibrary(t *testing.T) {
uses_sdks: ["mysdk@1"],
key: "myapex.key",
certificate: ":myapex.cert",
+ updatable: false,
}
apex {
@@ -219,6 +220,7 @@ func TestBasicSdkWithJavaLibrary(t *testing.T) {
uses_sdks: ["mysdk@2"],
key: "myapex.key",
certificate: ":myapex.cert",
+ updatable: false,
}
`)
diff --git a/sdk/sdk.go b/sdk/sdk.go
index f3d075022..2c84a2e88 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -33,10 +33,14 @@ func init() {
pctx.Import("android/soong/android")
pctx.Import("android/soong/java/config")
- android.RegisterModuleType("sdk", SdkModuleFactory)
- android.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
- android.PreDepsMutators(RegisterPreDepsMutators)
- android.PostDepsMutators(RegisterPostDepsMutators)
+ registerSdkBuildComponents(android.InitRegistrationContext)
+}
+
+func registerSdkBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("sdk", SdkModuleFactory)
+ ctx.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
+ ctx.PreDepsMutators(RegisterPreDepsMutators)
+ ctx.PostDepsMutators(RegisterPostDepsMutators)
}
type sdk struct {
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index c4dc41beb..a7acd0c5f 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -309,16 +309,13 @@ func TestPrebuiltVisibilityProperty_AddPrivate(t *testing.T) {
`)
}
-func TestSDkInstall(t *testing.T) {
+func TestSdkInstall(t *testing.T) {
sdk := `
sdk {
name: "mysdk",
}
`
- result := testSdkWithFs(t, ``,
- map[string][]byte{
- "Android.bp": []byte(sdk),
- })
+ result := testSdkWithFs(t, sdk, nil)
result.CheckSnapshot("mysdk", "",
checkAllOtherCopyRules(`.intermediates/mysdk/common_os/mysdk-current.zip -> mysdk-current.zip`),
@@ -390,7 +387,7 @@ func TestCommonValueOptimization(t *testing.T) {
extractor := newCommonValueExtractor(common)
- h := TestHelper{t}
+ h := android.TestHelper{t}
err := extractor.extractCommonProperties(common, structs)
h.AssertDeepEquals("unexpected error", nil, err)
@@ -465,7 +462,7 @@ func TestCommonValueOptimization_InvalidArchSpecificVariants(t *testing.T) {
extractor := newCommonValueExtractor(common)
- h := TestHelper{t}
+ h := android.TestHelper{t}
err := extractor.extractCommonProperties(common, structs)
h.AssertErrorMessageEquals("unexpected error", `field "S_Common" is not tagged as "arch_variant" but has arch specific properties:
diff --git a/sdk/testing.go b/sdk/testing.go
index 1ac873b4f..e291bdbdf 100644
--- a/sdk/testing.go
+++ b/sdk/testing.go
@@ -19,13 +19,13 @@ import (
"io/ioutil"
"os"
"path/filepath"
- "reflect"
"strings"
"testing"
"android/soong/android"
"android/soong/apex"
"android/soong/cc"
+ "android/soong/genrule"
"android/soong/java"
)
@@ -109,6 +109,9 @@ func testSdkContext(bp string, fs map[string][]byte, extraOsTypes []android.OsTy
// from java package
java.RegisterRequiredBuildComponentsForTest(ctx)
+ // from genrule package
+ genrule.RegisterGenruleBuildComponents(ctx)
+
// from cc package
cc.RegisterRequiredBuildComponentsForTest(ctx)
@@ -118,12 +121,8 @@ func testSdkContext(bp string, fs map[string][]byte, extraOsTypes []android.OsTy
ctx.PostDepsMutators(apex.RegisterPostDepsMutators)
// from this package
- ctx.RegisterModuleType("sdk", SdkModuleFactory)
- ctx.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
- ctx.RegisterModuleType("module_exports", ModuleExportsFactory)
- ctx.RegisterModuleType("module_exports_snapshot", ModuleExportsSnapshotsFactory)
- ctx.PreDepsMutators(RegisterPreDepsMutators)
- ctx.PostDepsMutators(RegisterPostDepsMutators)
+ registerModuleExportsBuildComponents(ctx)
+ registerSdkBuildComponents(ctx)
ctx.Register()
@@ -137,7 +136,7 @@ func runTests(t *testing.T, ctx *android.TestContext, config android.Config) *te
_, errs = ctx.PrepareBuildActions(config)
android.FailIfErrored(t, errs)
return &testSdkResult{
- TestHelper: TestHelper{t: t},
+ TestHelper: android.TestHelper{T: t},
ctx: ctx,
config: config,
}
@@ -181,59 +180,10 @@ func pathsToStrings(paths android.Paths) []string {
return ret
}
-// Provides general test support.
-type TestHelper struct {
- t *testing.T
-}
-
-func (h *TestHelper) AssertStringEquals(message string, expected string, actual string) {
- h.t.Helper()
- if actual != expected {
- h.t.Errorf("%s: expected %s, actual %s", message, expected, actual)
- }
-}
-
-func (h *TestHelper) AssertErrorMessageEquals(message string, expected string, actual error) {
- h.t.Helper()
- if actual == nil {
- h.t.Errorf("Expected error but was nil")
- } else if actual.Error() != expected {
- h.t.Errorf("%s: expected %s, actual %s", message, expected, actual.Error())
- }
-}
-
-func (h *TestHelper) AssertTrimmedStringEquals(message string, expected string, actual string) {
- h.t.Helper()
- h.AssertStringEquals(message, strings.TrimSpace(expected), strings.TrimSpace(actual))
-}
-
-func (h *TestHelper) AssertDeepEquals(message string, expected interface{}, actual interface{}) {
- h.t.Helper()
- if !reflect.DeepEqual(actual, expected) {
- h.t.Errorf("%s: expected %#v, actual %#v", message, expected, actual)
- }
-}
-
-func (h *TestHelper) AssertPanic(message string, funcThatShouldPanic func()) {
- h.t.Helper()
- panicked := false
- func() {
- defer func() {
- if x := recover(); x != nil {
- panicked = true
- }
- }()
- funcThatShouldPanic()
- }()
- if !panicked {
- h.t.Error(message)
- }
-}
-
// Encapsulates result of processing an SDK definition. Provides support for
// checking the state of the build structures.
type testSdkResult struct {
- TestHelper
+ android.TestHelper
ctx *android.TestContext
config android.Config
}
@@ -243,11 +193,11 @@ type testSdkResult struct {
// e.g. find the src/dest pairs from each cp command, the various zip files
// generated, etc.
func (r *testSdkResult) getSdkSnapshotBuildInfo(sdk *sdk) *snapshotBuildInfo {
- androidBpContents := sdk.GetAndroidBpContentsForTests()
-
info := &snapshotBuildInfo{
- r: r,
- androidBpContents: androidBpContents,
+ r: r,
+ androidBpContents: sdk.GetAndroidBpContentsForTests(),
+ androidUnversionedBpContents: sdk.GetUnversionedAndroidBpContentsForTests(),
+ androidVersionedBpContents: sdk.GetVersionedAndroidBpContentsForTests(),
}
buildParams := sdk.BuildParamsForTests()
@@ -287,7 +237,7 @@ func (r *testSdkResult) getSdkSnapshotBuildInfo(sdk *sdk) *snapshotBuildInfo {
info.intermediateZip = info.outputZip
mergeInput := android.NormalizePathForTesting(bp.Input)
if info.intermediateZip != mergeInput {
- r.t.Errorf("Expected intermediate zip %s to be an input to merge zips but found %s instead",
+ r.Errorf("Expected intermediate zip %s to be an input to merge zips but found %s instead",
info.intermediateZip, mergeInput)
}
@@ -320,7 +270,7 @@ func (r *testSdkResult) ModuleForTests(name string, variant string) android.Test
// Allows each test to customize what is checked without duplicating lots of code
// or proliferating check methods of different flavors.
func (r *testSdkResult) CheckSnapshot(name string, dir string, checkers ...snapshotBuildInfoChecker) {
- r.t.Helper()
+ r.Helper()
// The sdk CommonOS variant is always responsible for generating the snapshot.
variant := android.CommonOS.Name
@@ -350,7 +300,7 @@ func (r *testSdkResult) CheckSnapshot(name string, dir string, checkers ...snaps
}
// Process the generated bp file to make sure it is valid.
- testSdkWithFs(r.t, snapshotBuildInfo.androidBpContents, fs)
+ testSdkWithFs(r.T, snapshotBuildInfo.androidBpContents, fs)
}
type snapshotBuildInfoChecker func(info *snapshotBuildInfo)
@@ -360,11 +310,38 @@ type snapshotBuildInfoChecker func(info *snapshotBuildInfo)
// Both the expected and actual string are both trimmed before comparing.
func checkAndroidBpContents(expected string) snapshotBuildInfoChecker {
return func(info *snapshotBuildInfo) {
- info.r.t.Helper()
+ info.r.Helper()
info.r.AssertTrimmedStringEquals("Android.bp contents do not match", expected, info.androidBpContents)
}
}
+// Check that the snapshot's unversioned generated Android.bp is correct.
+//
+// This func should be used to check the general snapshot generation code.
+//
+// Both the expected and actual string are both trimmed before comparing.
+func checkUnversionedAndroidBpContents(expected string) snapshotBuildInfoChecker {
+ return func(info *snapshotBuildInfo) {
+ info.r.Helper()
+ info.r.AssertTrimmedStringEquals("unversioned Android.bp contents do not match", expected, info.androidUnversionedBpContents)
+ }
+}
+
+// Check that the snapshot's versioned generated Android.bp is correct.
+//
+// This func should only be used to check the version specific snapshot generation code,
+// i.e. the encoding of version into module names and the generation of the _snapshot module. The
+// general snapshot generation code should be checked using the checkUnversionedAndroidBpContents()
+// func.
+//
+// Both the expected and actual string are both trimmed before comparing.
+func checkVersionedAndroidBpContents(expected string) snapshotBuildInfoChecker {
+ return func(info *snapshotBuildInfo) {
+ info.r.Helper()
+ info.r.AssertTrimmedStringEquals("versioned Android.bp contents do not match", expected, info.androidVersionedBpContents)
+ }
+}
+
// Check that the snapshot's copy rules are correct.
//
// The copy rules are formatted as <src> -> <dest>, one per line and then compared
@@ -372,14 +349,14 @@ func checkAndroidBpContents(expected string) snapshotBuildInfoChecker {
// before comparing.
func checkAllCopyRules(expected string) snapshotBuildInfoChecker {
return func(info *snapshotBuildInfo) {
- info.r.t.Helper()
+ info.r.Helper()
info.r.AssertTrimmedStringEquals("Incorrect copy rules", expected, info.copyRules)
}
}
func checkAllOtherCopyRules(expected string) snapshotBuildInfoChecker {
return func(info *snapshotBuildInfo) {
- info.r.t.Helper()
+ info.r.Helper()
info.r.AssertTrimmedStringEquals("Incorrect copy rules", expected, info.otherCopyRules)
}
}
@@ -387,9 +364,9 @@ func checkAllOtherCopyRules(expected string) snapshotBuildInfoChecker {
// Check that the specified paths match the list of zips to merge with the intermediate zip.
func checkMergeZips(expected ...string) snapshotBuildInfoChecker {
return func(info *snapshotBuildInfo) {
- info.r.t.Helper()
+ info.r.Helper()
if info.intermediateZip == "" {
- info.r.t.Errorf("No intermediate zip file was created")
+ info.r.Errorf("No intermediate zip file was created")
}
info.r.AssertDeepEquals("mismatching merge zip files", expected, info.mergeZips)
@@ -407,6 +384,12 @@ type snapshotBuildInfo struct {
// The contents of the generated Android.bp file
androidBpContents string
+ // The contents of the unversioned Android.bp file
+ androidUnversionedBpContents string
+
+ // The contents of the versioned Android.bp file
+ androidVersionedBpContents string
+
// The paths, relative to the snapshot root, of all files and directories copied into the
// snapshot.
snapshotContents []string
diff --git a/sdk/update.go b/sdk/update.go
index 377aaae76..828c7b67d 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -572,12 +572,20 @@ func (t pruneEmptySetTransformer) transformPropertySetAfterContents(name string,
}
func generateBpContents(contents *generatedContents, bpFile *bpFile) {
+ generateFilteredBpContents(contents, bpFile, func(*bpModule) bool {
+ return true
+ })
+}
+
+func generateFilteredBpContents(contents *generatedContents, bpFile *bpFile, moduleFilter func(module *bpModule) bool) {
contents.Printfln("// This is auto-generated. DO NOT EDIT.")
for _, bpModule := range bpFile.order {
- contents.Printfln("")
- contents.Printfln("%s {", bpModule.moduleType)
- outputPropertySet(contents, bpModule.bpPropertySet)
- contents.Printfln("}")
+ if moduleFilter(bpModule) {
+ contents.Printfln("")
+ contents.Printfln("%s {", bpModule.moduleType)
+ outputPropertySet(contents, bpModule.bpPropertySet)
+ contents.Printfln("}")
+ }
}
}
@@ -639,6 +647,22 @@ func (s *sdk) GetAndroidBpContentsForTests() string {
return contents.content.String()
}
+func (s *sdk) GetUnversionedAndroidBpContentsForTests() string {
+ contents := &generatedContents{}
+ generateFilteredBpContents(contents, s.builderForTests.bpFile, func(module *bpModule) bool {
+ return !strings.Contains(module.properties["name"].(string), "@")
+ })
+ return contents.content.String()
+}
+
+func (s *sdk) GetVersionedAndroidBpContentsForTests() string {
+ contents := &generatedContents{}
+ generateFilteredBpContents(contents, s.builderForTests.bpFile, func(module *bpModule) bool {
+ return strings.Contains(module.properties["name"].(string), "@")
+ })
+ return contents.content.String()
+}
+
type snapshotBuilder struct {
ctx android.ModuleContext
sdk *sdk
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 58f8cf69e..031cd4717 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -84,9 +84,6 @@ type shBinaryProperties struct {
// Make this module available when building for recovery.
Recovery_available *bool
-
- // Properties for Bazel migration purposes.
- bazel.Properties
}
type TestProperties struct {
@@ -132,6 +129,7 @@ type TestProperties struct {
type ShBinary struct {
android.ModuleBase
+ android.BazelModuleBase
properties shBinaryProperties
@@ -427,6 +425,7 @@ func (s *ShTest) AndroidMkEntries() []android.AndroidMkEntries {
func InitShBinaryModule(s *ShBinary) {
s.AddProperties(&s.properties)
+ android.InitBazelModule(s)
}
// sh_binary is for a shell script or batch file to be installed as an
@@ -504,7 +503,7 @@ func BazelShBinaryFactory() android.Module {
func ShBinaryBp2Build(ctx android.TopDownMutatorContext) {
m, ok := ctx.Module().(*ShBinary)
- if !ok || !m.properties.Bazel_module.Bp2build_available {
+ if !ok || !m.ConvertWithBp2build() {
return
}
@@ -514,9 +513,11 @@ func ShBinaryBp2Build(ctx android.TopDownMutatorContext) {
Srcs: srcs,
}
- props := bazel.NewBazelTargetModuleProperties(m.Name(), "sh_binary", "")
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "sh_binary",
+ }
- ctx.CreateBazelTargetModule(BazelShBinaryFactory, props, attrs)
+ ctx.CreateBazelTargetModule(BazelShBinaryFactory, m.Name(), props, attrs)
}
func (m *bazelShBinary) Name() string {
diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go
index fb7ab1358..f48f7fb29 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -3,6 +3,7 @@ package sh
import (
"io/ioutil"
"os"
+ "path"
"path/filepath"
"reflect"
"testing"
@@ -73,7 +74,8 @@ func TestShTestSubDir(t *testing.T) {
entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
- expectedPath := "/tmp/target/product/test_device/data/nativetest64/foo_test"
+ expectedPath := path.Join(buildDir,
+ "../target/product/test_device/data/nativetest64/foo_test")
actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0]
if expectedPath != actualPath {
t.Errorf("Unexpected LOCAL_MODULE_PATH expected: %q, actual: %q", expectedPath, actualPath)
@@ -97,7 +99,8 @@ func TestShTest(t *testing.T) {
entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
- expectedPath := "/tmp/target/product/test_device/data/nativetest64/foo"
+ expectedPath := path.Join(buildDir,
+ "../target/product/test_device/data/nativetest64/foo")
actualPath := entries.EntryMap["LOCAL_MODULE_PATH"][0]
if expectedPath != actualPath {
t.Errorf("Unexpected LOCAL_MODULE_PATH expected: %q, actual: %q", expectedPath, actualPath)
diff --git a/shared/Android.bp b/shared/Android.bp
index 5aa9d54f7..deb17f8f6 100644
--- a/shared/Android.bp
+++ b/shared/Android.bp
@@ -6,7 +6,12 @@ bootstrap_go_package {
name: "soong-shared",
pkgPath: "android/soong/shared",
srcs: [
+ "env.go",
"paths.go",
+ "debug.go",
+ ],
+ testSrcs: [
+ "paths_test.go",
],
deps: [
"soong-bazel",
diff --git a/shared/debug.go b/shared/debug.go
new file mode 100644
index 000000000..5392f2b79
--- /dev/null
+++ b/shared/debug.go
@@ -0,0 +1,69 @@
+package shared
+
+import (
+ "fmt"
+ "os"
+ "os/exec"
+ "strings"
+ "syscall"
+)
+
+var (
+ isDebugging bool
+)
+
+// Finds the Delve binary to use. Either uses the SOONG_DELVE_PATH environment
+// variable or if that is unset, looks at $PATH.
+func ResolveDelveBinary() string {
+ result := os.Getenv("SOONG_DELVE_PATH")
+ if result == "" {
+ result, _ = exec.LookPath("dlv")
+ }
+
+ return result
+}
+
+// Returns whether the current process is running under Delve due to
+// ReexecWithDelveMaybe().
+func IsDebugging() bool {
+ return isDebugging
+}
+
+// Re-executes the binary in question under the control of Delve when
+// delveListen is not the empty string. delvePath gives the path to the Delve.
+func ReexecWithDelveMaybe(delveListen, delvePath string) {
+ isDebugging = os.Getenv("SOONG_DELVE_REEXECUTED") == "true"
+ if isDebugging || delveListen == "" {
+ return
+ }
+
+ if delvePath == "" {
+ fmt.Fprintln(os.Stderr, "Delve debugging requested but failed to find dlv")
+ os.Exit(1)
+ }
+
+ soongDelveEnv := []string{}
+ for _, env := range os.Environ() {
+ idx := strings.IndexRune(env, '=')
+ if idx != -1 {
+ soongDelveEnv = append(soongDelveEnv, env)
+ }
+ }
+
+ soongDelveEnv = append(soongDelveEnv, "SOONG_DELVE_REEXECUTED=true")
+
+ dlvArgv := []string{
+ delvePath,
+ "--listen=:" + delveListen,
+ "--headless=true",
+ "--api-version=2",
+ "exec",
+ os.Args[0],
+ "--",
+ }
+
+ dlvArgv = append(dlvArgv, os.Args[1:]...)
+ syscall.Exec(delvePath, dlvArgv, soongDelveEnv)
+ fmt.Fprintln(os.Stderr, "exec() failed while trying to reexec with Delve")
+ os.Exit(1)
+}
diff --git a/env/env.go b/shared/env.go
index 735a38aa4..152729ba0 100644
--- a/env/env.go
+++ b/shared/env.go
@@ -12,15 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-// env implements the environment JSON file handling for the soong_env command line tool run before
-// the builder and for the env writer in the builder.
-package env
+// Implements the environment JSON file handling for serializing the
+// environment variables that were used in soong_build so that soong_ui can
+// check whether they have changed
+package shared
import (
"encoding/json"
"fmt"
"io/ioutil"
- "os"
"sort"
)
@@ -57,7 +57,7 @@ func EnvFileContents(envDeps map[string]string) ([]byte, error) {
// Reads and deserializes a Soong environment file located at the given file path to determine its
// staleness. If any environment variable values have changed, it prints them out and returns true.
// Failing to read or parse the file also causes it to return true.
-func StaleEnvFile(filepath string) (bool, error) {
+func StaleEnvFile(filepath string, getenv func(string) string) (bool, error) {
data, err := ioutil.ReadFile(filepath)
if err != nil {
return true, err
@@ -74,7 +74,7 @@ func StaleEnvFile(filepath string) (bool, error) {
for _, entry := range contents {
key := entry.Key
old := entry.Value
- cur := os.Getenv(key)
+ cur := getenv(key)
if old != cur {
changed = append(changed, fmt.Sprintf("%s (%q -> %q)", key, old, cur))
}
@@ -91,6 +91,28 @@ func StaleEnvFile(filepath string) (bool, error) {
return false, nil
}
+// Deserializes and environment serialized by EnvFileContents() and returns it
+// as a map[string]string.
+func EnvFromFile(envFile string) (map[string]string, error) {
+ result := make(map[string]string)
+ data, err := ioutil.ReadFile(envFile)
+ if err != nil {
+ return result, err
+ }
+
+ var contents envFileData
+ err = json.Unmarshal(data, &contents)
+ if err != nil {
+ return result, err
+ }
+
+ for _, entry := range contents {
+ result[entry.Key] = entry.Value
+ }
+
+ return result, nil
+}
+
// Implements sort.Interface so that we can use sort.Sort on envFileData arrays.
func (e envFileData) Len() int {
return len(e)
diff --git a/shared/paths.go b/shared/paths.go
index 1b9ff6098..fca8b4c15 100644
--- a/shared/paths.go
+++ b/shared/paths.go
@@ -30,6 +30,21 @@ type SharedPaths interface {
BazelMetricsDir() string
}
+// Joins the path strings in the argument list, taking absolute paths into
+// account. That is, if one of the strings is an absolute path, the ones before
+// are ignored.
+func JoinPath(base string, rest ...string) string {
+ result := base
+ for _, next := range rest {
+ if filepath.IsAbs(next) {
+ result = next
+ } else {
+ result = filepath.Join(result, next)
+ }
+ }
+ return result
+}
+
// Given the out directory, returns the root of the temp directory (to be cleared at the start of each execution of Soong)
func TempDirForOutDir(outDir string) (tempPath string) {
return filepath.Join(outDir, ".temp")
diff --git a/cmd/soong_env/Android.bp b/shared/paths_test.go
index ad717d0b1..018d55f34 100644
--- a/cmd/soong_env/Android.bp
+++ b/shared/paths_test.go
@@ -1,4 +1,4 @@
-// Copyright 2015 Google Inc. All rights reserved.
+// Copyright 2021 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -12,17 +12,21 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
+package shared
+
+import (
+ "testing"
+)
+
+func assertEqual(t *testing.T, expected, actual string) {
+ t.Helper()
+ if expected != actual {
+ t.Errorf("expected %q != got %q", expected, actual)
+ }
}
-bootstrap_go_binary {
- name: "soong_env",
- deps: [
- "soong-env",
- ],
- srcs: [
- "soong_env.go",
- ],
- default: true,
+func TestJoinPath(t *testing.T) {
+ assertEqual(t, "/a/b", JoinPath("c/d", "/a/b"))
+ assertEqual(t, "a/b", JoinPath("a", "b"))
+ assertEqual(t, "/a/b", JoinPath("x", "/a", "b"))
}
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index 2ccce1524..892a16c8d 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -37,9 +37,10 @@ type dependencyTag struct {
}
type syspropGenProperties struct {
- Srcs []string `android:"path"`
- Scope string
- Name *string
+ Srcs []string `android:"path"`
+ Scope string
+ Name *string
+ Check_api *string
}
type syspropJavaGenRule struct {
@@ -68,10 +69,6 @@ var (
func init() {
pctx.HostBinToolVariable("soongZipCmd", "soong_zip")
pctx.HostBinToolVariable("syspropJavaCmd", "sysprop_java")
-
- android.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("sysprop_deps", syspropDepsMutator).Parallel()
- })
}
// syspropJavaGenRule module generates srcjar containing generated java APIs.
@@ -103,6 +100,12 @@ func (g *syspropJavaGenRule) GenerateAndroidBuildActions(ctx android.ModuleConte
}
}
+func (g *syspropJavaGenRule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // Add a dependency from the stubs to sysprop library so that the generator rule can depend on
+ // the check API rule of the sysprop library.
+ ctx.AddFarVariationDependencies(nil, nil, proptools.String(g.properties.Check_api))
+}
+
func (g *syspropJavaGenRule) OutputFiles(tag string) (android.Paths, error) {
switch tag {
case "":
@@ -157,14 +160,17 @@ type syspropLibraryProperties struct {
// If set to true, build a variant of the module for the host. Defaults to false.
Host_supported *bool
- // Whether public stub exists or not.
- Public_stub *bool `blueprint:"mutated"`
-
Cpp struct {
// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
// Forwarded to cc_library.min_sdk_version
Min_sdk_version *string
}
+
+ Java struct {
+ // Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
+ // Forwarded to java_library.min_sdk_version
+ Min_sdk_version *string
+ }
}
var (
@@ -202,11 +208,8 @@ func (m *syspropLibrary) CcImplementationModuleName() string {
return "lib" + m.BaseModuleName()
}
-func (m *syspropLibrary) JavaPublicStubName() string {
- if proptools.Bool(m.properties.Public_stub) {
- return m.BaseModuleName() + "_public"
- }
- return ""
+func (m *syspropLibrary) javaPublicStubName() string {
+ return m.BaseModuleName() + "_public"
}
func (m *syspropLibrary) javaGenModuleName() string {
@@ -221,10 +224,6 @@ func (m *syspropLibrary) BaseModuleName() string {
return m.ModuleBase.Name()
}
-func (m *syspropLibrary) HasPublicStub() bool {
- return proptools.Bool(m.properties.Public_stub)
-}
-
func (m *syspropLibrary) CurrentSyspropApiFile() android.OptionalPath {
return m.currentApiFile
}
@@ -399,16 +398,19 @@ type ccLibraryProperties struct {
}
type javaLibraryProperties struct {
- Name *string
- Srcs []string
- Soc_specific *bool
- Device_specific *bool
- Product_specific *bool
- Required []string
- Sdk_version *string
- Installable *bool
- Libs []string
- Stem *string
+ Name *string
+ Srcs []string
+ Soc_specific *bool
+ Device_specific *bool
+ Product_specific *bool
+ Required []string
+ Sdk_version *string
+ Installable *bool
+ Libs []string
+ Stem *string
+ SyspropPublicStub string
+ Apex_available []string
+ Min_sdk_version *string
}
func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
@@ -490,35 +492,44 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
// Contrast to C++, syspropJavaGenRule module will generate srcjar and the srcjar will be fed
// to Java implementation library.
ctx.CreateModule(syspropJavaGenFactory, &syspropGenProperties{
- Srcs: m.properties.Srcs,
- Scope: scope,
- Name: proptools.StringPtr(m.javaGenModuleName()),
- })
-
- ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{
- Name: proptools.StringPtr(m.BaseModuleName()),
- Srcs: []string{":" + m.javaGenModuleName()},
- Soc_specific: proptools.BoolPtr(ctx.SocSpecific()),
- Device_specific: proptools.BoolPtr(ctx.DeviceSpecific()),
- Product_specific: proptools.BoolPtr(ctx.ProductSpecific()),
- Installable: m.properties.Installable,
- Sdk_version: proptools.StringPtr("core_current"),
- Libs: []string{javaSyspropStub},
+ Srcs: m.properties.Srcs,
+ Scope: scope,
+ Name: proptools.StringPtr(m.javaGenModuleName()),
+ Check_api: proptools.StringPtr(ctx.ModuleName()),
})
// if platform sysprop_library is installed in /system or /system-ext, we regard it as an API
// and allow any modules (even from different partition) to link against the sysprop_library.
// To do that, we create a public stub and expose it to modules with sdk_version: system_*.
+ var publicStub string
if isOwnerPlatform && installedInSystem {
- m.properties.Public_stub = proptools.BoolPtr(true)
+ publicStub = m.javaPublicStubName()
+ }
+
+ ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{
+ Name: proptools.StringPtr(m.BaseModuleName()),
+ Srcs: []string{":" + m.javaGenModuleName()},
+ Soc_specific: proptools.BoolPtr(ctx.SocSpecific()),
+ Device_specific: proptools.BoolPtr(ctx.DeviceSpecific()),
+ Product_specific: proptools.BoolPtr(ctx.ProductSpecific()),
+ Installable: m.properties.Installable,
+ Sdk_version: proptools.StringPtr("core_current"),
+ Libs: []string{javaSyspropStub},
+ SyspropPublicStub: publicStub,
+ Apex_available: m.ApexProperties.Apex_available,
+ Min_sdk_version: m.properties.Java.Min_sdk_version,
+ })
+
+ if publicStub != "" {
ctx.CreateModule(syspropJavaGenFactory, &syspropGenProperties{
- Srcs: m.properties.Srcs,
- Scope: "public",
- Name: proptools.StringPtr(m.javaGenPublicStubName()),
+ Srcs: m.properties.Srcs,
+ Scope: "public",
+ Name: proptools.StringPtr(m.javaGenPublicStubName()),
+ Check_api: proptools.StringPtr(ctx.ModuleName()),
})
ctx.CreateModule(java.LibraryFactory, &javaLibraryProperties{
- Name: proptools.StringPtr(m.JavaPublicStubName()),
+ Name: proptools.StringPtr(publicStub),
Srcs: []string{":" + m.javaGenPublicStubName()},
Installable: proptools.BoolPtr(false),
Sdk_version: proptools.StringPtr("core_current"),
@@ -537,15 +548,3 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
*libraries = append(*libraries, "//"+ctx.ModuleDir()+":"+ctx.ModuleName())
}
}
-
-// syspropDepsMutator adds dependencies from java implementation library to sysprop library.
-// java implementation library then depends on check API rule of sysprop library.
-func syspropDepsMutator(ctx android.BottomUpMutatorContext) {
- if m, ok := ctx.Module().(*syspropLibrary); ok {
- ctx.AddReverseDependency(m, nil, m.javaGenModuleName())
-
- if proptools.Bool(m.properties.Public_stub) {
- ctx.AddReverseDependency(m, nil, m.javaGenPublicStubName())
- }
- }
-}
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 5cb9e64ee..fde41d67e 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -26,7 +26,6 @@ import (
"strings"
"testing"
- "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -61,16 +60,10 @@ func testContext(config android.Config) *android.TestContext {
java.RegisterRequiredBuildComponentsForTest(ctx)
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
- ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("sysprop_deps", syspropDepsMutator).Parallel()
- })
android.RegisterPrebuiltMutators(ctx)
cc.RegisterRequiredBuildComponentsForTest(ctx)
- ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.BottomUp("sysprop_java", java.SyspropMutator).Parallel()
- })
ctx.RegisterModuleType("sysprop_library", syspropLibraryFactory)
@@ -88,6 +81,51 @@ func run(t *testing.T, ctx *android.TestContext, config android.Config) {
}
func testConfig(env map[string]string, bp string, fs map[string][]byte) android.Config {
+ bp += `
+ cc_library {
+ name: "libbase",
+ host_supported: true,
+ }
+
+ cc_library_headers {
+ name: "libbase_headers",
+ vendor_available: true,
+ recovery_available: true,
+ }
+
+ cc_library {
+ name: "liblog",
+ no_libcrt: true,
+ nocrt: true,
+ system_shared_libs: [],
+ recovery_available: true,
+ host_supported: true,
+ llndk_stubs: "liblog.llndk",
+ }
+
+ llndk_library {
+ name: "liblog.llndk",
+ symbol_file: "",
+ }
+
+ java_library {
+ name: "sysprop-library-stub-platform",
+ sdk_version: "core_current",
+ }
+
+ java_library {
+ name: "sysprop-library-stub-vendor",
+ soc_specific: true,
+ sdk_version: "core_current",
+ }
+
+ java_library {
+ name: "sysprop-library-stub-product",
+ product_specific: true,
+ sdk_version: "core_current",
+ }
+ `
+
bp += cc.GatherRequiredDepsForTest(android.Android)
mockFS := map[string][]byte{
@@ -257,54 +295,11 @@ func TestSyspropLibrary(t *testing.T) {
static_libs: ["sysprop-platform", "sysprop-vendor"],
}
- cc_library {
- name: "libbase",
- host_supported: true,
- }
-
- cc_library_headers {
- name: "libbase_headers",
- vendor_available: true,
- recovery_available: true,
- }
-
- cc_library {
- name: "liblog",
- no_libcrt: true,
- nocrt: true,
- system_shared_libs: [],
- recovery_available: true,
- host_supported: true,
- llndk_stubs: "liblog.llndk",
- }
-
cc_binary_host {
name: "hostbin",
static_libs: ["sysprop-platform"],
}
-
- llndk_library {
- name: "liblog.llndk",
- symbol_file: "",
- }
-
- java_library {
- name: "sysprop-library-stub-platform",
- sdk_version: "core_current",
- }
-
- java_library {
- name: "sysprop-library-stub-vendor",
- soc_specific: true,
- sdk_version: "core_current",
- }
-
- java_library {
- name: "sysprop-library-stub-product",
- product_specific: true,
- sdk_version: "core_current",
- }
- `)
+ `)
// Check for generated cc_library
for _, variant := range []string{
@@ -392,15 +387,68 @@ func TestSyspropLibrary(t *testing.T) {
}
// Java modules linking against system API should use public stub
- javaSystemApiClient := ctx.ModuleForTests("java-platform", "android_common")
- publicStubFound := false
- ctx.VisitDirectDeps(javaSystemApiClient.Module(), func(dep blueprint.Module) {
- if dep.Name() == "sysprop-platform_public" {
- publicStubFound = true
+ javaSystemApiClient := ctx.ModuleForTests("java-platform", "android_common").Rule("javac")
+ syspropPlatformPublic := ctx.ModuleForTests("sysprop-platform_public", "android_common").Description("for turbine")
+ if g, w := javaSystemApiClient.Implicits.Strings(), syspropPlatformPublic.Output.String(); !android.InList(w, g) {
+ t.Errorf("system api client should use public stub %q, got %q", w, g)
+ }
+}
+
+func TestApexAvailabilityIsForwarded(t *testing.T) {
+ ctx := test(t, `
+ sysprop_library {
+ name: "sysprop-platform",
+ apex_available: ["//apex_available:platform"],
+ srcs: ["android/sysprop/PlatformProperties.sysprop"],
+ api_packages: ["android.sysprop"],
+ property_owner: "Platform",
+ }
+ `)
+
+ expected := []string{"//apex_available:platform"}
+
+ ccModule := ctx.ModuleForTests("libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+ propFromCc := ccModule.ApexProperties.Apex_available
+ if !reflect.DeepEqual(propFromCc, expected) {
+ t.Errorf("apex_available not forwarded to cc module. expected %#v, got %#v",
+ expected, propFromCc)
+ }
+
+ javaModule := ctx.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
+ propFromJava := javaModule.ApexProperties.Apex_available
+ if !reflect.DeepEqual(propFromJava, expected) {
+ t.Errorf("apex_available not forwarded to java module. expected %#v, got %#v",
+ expected, propFromJava)
+ }
+}
+
+func TestMinSdkVersionIsForwarded(t *testing.T) {
+ ctx := test(t, `
+ sysprop_library {
+ name: "sysprop-platform",
+ srcs: ["android/sysprop/PlatformProperties.sysprop"],
+ api_packages: ["android.sysprop"],
+ property_owner: "Platform",
+ cpp: {
+ min_sdk_version: "29",
+ },
+ java: {
+ min_sdk_version: "30",
+ },
}
- })
- if !publicStubFound {
- t.Errorf("system api client should use public stub")
+ `)
+
+ ccModule := ctx.ModuleForTests("libsysprop-platform", "android_arm64_armv8-a_shared").Module().(*cc.Module)
+ propFromCc := proptools.String(ccModule.Properties.Min_sdk_version)
+ if propFromCc != "29" {
+ t.Errorf("min_sdk_version not forwarded to cc module. expected %#v, got %#v",
+ "29", propFromCc)
}
+ javaModule := ctx.ModuleForTests("sysprop-platform", "android_common").Module().(*java.Library)
+ propFromJava := javaModule.MinSdkVersion()
+ if propFromJava != "30" {
+ t.Errorf("min_sdk_version not forwarded to java module. expected %#v, got %#v",
+ "30", propFromJava)
+ }
}
diff --git a/ui/build/cleanbuild.go b/ui/build/cleanbuild.go
index b1f8551ed..6ba497c3f 100644
--- a/ui/build/cleanbuild.go
+++ b/ui/build/cleanbuild.go
@@ -124,7 +124,7 @@ func installClean(ctx Context, config Config) {
productOut("obj/PACKAGING"),
productOut("ramdisk"),
productOut("debug_ramdisk"),
- productOut("vendor-ramdisk"),
+ productOut("vendor_ramdisk"),
productOut("vendor_debug_ramdisk"),
productOut("test_harness_ramdisk"),
productOut("recovery"),
diff --git a/ui/build/environment.go b/ui/build/environment.go
index 6d8a28fdf..50d059f8d 100644
--- a/ui/build/environment.go
+++ b/ui/build/environment.go
@@ -33,6 +33,19 @@ func OsEnvironment() *Environment {
return &env
}
+// Returns a copy of the environment as a map[string]string.
+func (e *Environment) AsMap() map[string]string {
+ result := make(map[string]string)
+
+ for _, envVar := range *e {
+ if k, v, ok := decodeKeyValue(envVar); ok {
+ result[k] = v
+ }
+ }
+
+ return result
+}
+
// Get returns the value associated with the key, and whether it exists.
// It's equivalent to the os.LookupEnv function, but with this copy of the
// Environment.
diff --git a/ui/build/paths/logs_test.go b/ui/build/paths/logs_test.go
index 3b1005fb5..067f3f3fe 100644
--- a/ui/build/paths/logs_test.go
+++ b/ui/build/paths/logs_test.go
@@ -26,6 +26,9 @@ import (
)
func TestSendLog(t *testing.T) {
+ if testing.Short() {
+ t.Skip("skipping in short mode, sometimes hangs")
+ }
t.Run("Short name", func(t *testing.T) {
d, err := ioutil.TempDir("", "s")
if err != nil {
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 899ab5da5..5f4a203f7 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -19,7 +19,8 @@ import (
"os"
"path/filepath"
"strconv"
- "strings"
+
+ "android/soong/shared"
soong_metrics_proto "android/soong/ui/metrics/metrics_proto"
@@ -30,6 +31,15 @@ import (
"android/soong/ui/status"
)
+func writeEnvironmentFile(ctx Context, envFile string, envDeps map[string]string) error {
+ data, err := shared.EnvFileContents(envDeps)
+ if err != nil {
+ return err
+ }
+
+ return ioutil.WriteFile(envFile, data, 0644)
+}
+
// This uses Android.bp files and various tools to generate <builddir>/build.ninja.
//
// However, the execution of <builddir>/build.ninja happens later in build/soong/ui/build/build.go#Build()
@@ -47,6 +57,12 @@ func runSoong(ctx Context, config Config) {
ctx.BeginTrace(metrics.RunSoong, "soong")
defer ctx.EndTrace()
+ // We have two environment files: .available is the one with every variable,
+ // .used with the ones that were actually used. The latter is used to
+ // determine whether Soong needs to be re-run since why re-run it if only
+ // unused variables were changed?
+ envFile := filepath.Join(config.SoongOutDir(), "soong.environment.available")
+
// Use an anonymous inline function for tracing purposes (this pattern is used several times below).
func() {
ctx.BeginTrace(metrics.RunSoong, "blueprint bootstrap")
@@ -61,6 +77,7 @@ func runSoong(ctx Context, config Config) {
}
cmd := Command(ctx, config, "blueprint bootstrap", "build/blueprint/bootstrap.bash", args...)
+
cmd.Environment.Set("BLUEPRINTDIR", "./build/blueprint")
cmd.Environment.Set("BOOTSTRAP", "./build/blueprint/bootstrap.bash")
cmd.Environment.Set("BUILDDIR", config.SoongOutDir())
@@ -74,34 +91,36 @@ func runSoong(ctx Context, config Config) {
cmd.RunAndPrintOrFatal()
}()
+ soongBuildEnv := config.Environment().Copy()
+ soongBuildEnv.Set("TOP", os.Getenv("TOP"))
+ // These two dependencies are read from bootstrap.go, but also need to be here
+ // so that soong_build can declare a dependency on them
+ soongBuildEnv.Set("SOONG_DELVE", os.Getenv("SOONG_DELVE"))
+ soongBuildEnv.Set("SOONG_DELVE_PATH", os.Getenv("SOONG_DELVE_PATH"))
+ soongBuildEnv.Set("SOONG_OUTDIR", config.SoongOutDir())
+ // For Bazel mixed builds.
+ soongBuildEnv.Set("BAZEL_PATH", "./tools/bazel")
+ soongBuildEnv.Set("BAZEL_HOME", filepath.Join(config.BazelOutDir(), "bazelhome"))
+ soongBuildEnv.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output"))
+ soongBuildEnv.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
+ soongBuildEnv.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
+
+ err := writeEnvironmentFile(ctx, envFile, soongBuildEnv.AsMap())
+ if err != nil {
+ ctx.Fatalf("failed to write environment file %s: %s", envFile, err)
+ }
+
func() {
ctx.BeginTrace(metrics.RunSoong, "environment check")
defer ctx.EndTrace()
- envFile := filepath.Join(config.SoongOutDir(), ".soong.environment")
- envTool := filepath.Join(config.SoongOutDir(), ".bootstrap/bin/soong_env")
- if _, err := os.Stat(envFile); err == nil {
- if _, err := os.Stat(envTool); err == nil {
- cmd := Command(ctx, config, "soong_env", envTool, envFile)
- cmd.Sandbox = soongSandbox
-
- var buf strings.Builder
- cmd.Stdout = &buf
- cmd.Stderr = &buf
- if err := cmd.Run(); err != nil {
- ctx.Verboseln("soong_env failed, forcing manifest regeneration")
- os.Remove(envFile)
- }
-
- if buf.Len() > 0 {
- ctx.Verboseln(buf.String())
- }
- } else {
- ctx.Verboseln("Missing soong_env tool, forcing manifest regeneration")
- os.Remove(envFile)
- }
- } else if !os.IsNotExist(err) {
- ctx.Fatalf("Failed to stat %f: %v", envFile, err)
+ envFile := filepath.Join(config.SoongOutDir(), "soong.environment.used")
+ getenv := func(k string) string {
+ v, _ := config.Environment().Get(k)
+ return v
+ }
+ if stale, _ := shared.StaleEnvFile(envFile, getenv); stale {
+ os.Remove(envFile)
}
}()
@@ -151,14 +170,28 @@ func runSoong(ctx Context, config Config) {
"--frontend_file", fifo,
"-f", filepath.Join(config.SoongOutDir(), file))
- // For Bazel mixed builds.
- cmd.Environment.Set("BAZEL_PATH", "./tools/bazel")
- cmd.Environment.Set("BAZEL_HOME", filepath.Join(config.BazelOutDir(), "bazelhome"))
- cmd.Environment.Set("BAZEL_OUTPUT_BASE", filepath.Join(config.BazelOutDir(), "output"))
- cmd.Environment.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
- cmd.Environment.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
+ var ninjaEnv Environment
+
+ // This is currently how the command line to invoke soong_build finds the
+ // root of the source tree and the output root
+ ninjaEnv.Set("TOP", os.Getenv("TOP"))
+ ninjaEnv.Set("SOONG_OUTDIR", config.SoongOutDir())
+
+ // Needed for NonHermeticHostSystemTool() and that, only in tests. We should
+ // probably find a better way of running tests other than making $PATH
+ // available also to production builds. Note that this is not get same as
+ // os.Getenv("PATH"): config.Environment() contains the $PATH that redirects
+ // every binary through the path interposer.
+ configPath, _ := config.Environment().Get("PATH")
+ ninjaEnv.Set("PATH", configPath)
+
+ // For debugging
+ if os.Getenv("SOONG_DELVE") != "" {
+ // SOONG_DELVE is already in cmd.Environment
+ ninjaEnv.Set("SOONG_DELVE_PATH", shared.ResolveDelveBinary())
+ }
- cmd.Environment.Set("SOONG_SANDBOX_SOONG_BUILD", "true")
+ cmd.Environment = &ninjaEnv
cmd.Sandbox = soongSandbox
cmd.RunAndStreamOrFatal()
}
diff --git a/vnames.go.json b/vnames.go.json
deleted file mode 100644
index 7ce2d4b49..000000000
--- a/vnames.go.json
+++ /dev/null
@@ -1,9 +0,0 @@
-[
- {
- "pattern": "(.*)",
- "vname": {
- "corpus": "android.googlesource.com/platform/superproject",
- "path": "@1@"
- }
- }
-]
diff --git a/vnames.json b/vnames.json
index f9d3adc8b..096260f6a 100644
--- a/vnames.json
+++ b/vnames.json
@@ -2,7 +2,6 @@
{
"pattern": "out/(.*)",
"vname": {
- "corpus": "android.googlesource.com/platform/superproject",
"root": "out",
"path": "@1@"
}
@@ -10,9 +9,7 @@
{
"pattern": "(.*)",
"vname": {
- "corpus": "android.googlesource.com/platform/superproject",
"path": "@1@"
}
}
]
-