Merge "Build test1_com.android.tzdata and test3_com.android.tzdata with bazel."
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index e901b31..238d24f 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -391,6 +391,8 @@
"external/protobuf":/* recursive = */ false,
"external/python/absl-py":/* recursive = */ true,
+ "external/compiler-rt/lib/cfi":/* recursive = */ false,
+
// this BUILD file is globbed by //external/icu/icu4c/source:icu4c_test_data's "data/**/*".
"external/icu/icu4c/source/data/unidata/norm2":/* recursive = */ false,
diff --git a/android/sdk_version.go b/android/sdk_version.go
index 7ace638..1192f7d 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -28,9 +28,9 @@
// MinSdkVersion returns ApiLevel that corresponds to the min_sdk_version property of the current module,
// or from sdk_version if it is not set.
MinSdkVersion(ctx EarlyModuleContext) ApiLevel
- // ReplaceMaxSdkVersionPlaceholder returns SdkSpec to replace the maxSdkVersion property of permission and
+ // ReplaceMaxSdkVersionPlaceholder returns Apilevel to replace the maxSdkVersion property of permission and
// uses-permission tags if it is set.
- ReplaceMaxSdkVersionPlaceholder(ctx EarlyModuleContext) SdkSpec
+ ReplaceMaxSdkVersionPlaceholder(ctx EarlyModuleContext) ApiLevel
// TargetSdkVersion returns the ApiLevel that corresponds to the target_sdk_version property of the current module,
// or from sdk_version if it is not set.
TargetSdkVersion(ctx EarlyModuleContext) ApiLevel
diff --git a/apex/apex.go b/apex/apex.go
index 1f700c6..0f32f77 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -103,12 +103,13 @@
// to avoid mistakes. When set as true, no force-labelling.
Use_file_contexts_as_is *bool
- // Path to the canned fs config file for customizing file's uid/gid/mod/capabilities. The
- // format is /<path_or_glob> <uid> <gid> <mode> [capabilities=0x<cap>], where path_or_glob is a
- // path or glob pattern for a file or set of files, uid/gid are numerial values of user ID
- // and group ID, mode is octal value for the file mode, and cap is hexadecimal value for the
- // capability. If this property is not set, or a file is missing in the file, default config
- // is used.
+ // Path to the canned fs config file for customizing file's
+ // uid/gid/mod/capabilities. The content of this file is appended to the
+ // default config, so that the custom entries are preferred. The format is
+ // /<path_or_glob> <uid> <gid> <mode> [capabilities=0x<cap>], where
+ // path_or_glob is a path or glob pattern for a file or set of files,
+ // uid/gid are numerial values of user ID and group ID, mode is octal value
+ // for the file mode, and cap is hexadecimal value for the capability.
Canned_fs_config *string `android:"path"`
ApexNativeDependencies
@@ -2831,7 +2832,7 @@
if !baseModuleIsApex {
panic(fmt.Errorf("Base module is not apex module: %s", baseApexModuleName))
}
- attrs, props := convertWithBp2build(a, ctx)
+ attrs, props, commonAttrs := convertWithBp2build(a, ctx)
// We just want the name, not module reference.
baseApexName := strings.TrimPrefix(baseApexModuleName, ":")
@@ -2905,7 +2906,9 @@
}
}
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: o.Name()}, &attrs)
+ commonAttrs.Name = o.Name()
+
+ ctx.CreateBazelTargetModule(props, commonAttrs, &attrs)
}
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -3549,17 +3552,12 @@
return
}
- attrs, props := convertWithBp2build(a, ctx)
- commonAttrs := android.CommonAttributes{
- Name: a.Name(),
- }
- if a.testApex {
- commonAttrs.Testonly = proptools.BoolPtr(a.testApex)
- }
+ attrs, props, commonAttrs := convertWithBp2build(a, ctx)
+ commonAttrs.Name = a.Name()
ctx.CreateBazelTargetModule(props, commonAttrs, &attrs)
}
-func convertWithBp2build(a *apexBundle, ctx android.TopDownMutatorContext) (bazelApexBundleAttributes, bazel.BazelTargetModuleProperties) {
+func convertWithBp2build(a *apexBundle, ctx android.TopDownMutatorContext) (bazelApexBundleAttributes, bazel.BazelTargetModuleProperties, android.CommonAttributes) {
var manifestLabelAttribute bazel.LabelAttribute
manifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json")))
@@ -3687,7 +3685,12 @@
Bzl_load_location: "//build/bazel/rules/apex:apex.bzl",
}
- return attrs, props
+ commonAttrs := android.CommonAttributes{}
+ if a.testApex {
+ commonAttrs.Testonly = proptools.BoolPtr(true)
+ }
+
+ return attrs, props, commonAttrs
}
// The following conversions are based on this table where the rows are the compile_multilib
diff --git a/apex/apex_test.go b/apex/apex_test.go
index c9665a4..05c888a 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -10105,3 +10105,45 @@
android.AssertStringDoesContain(t, "missing lib to trim", libs_to_trim, "libbar")
android.AssertStringDoesNotContain(t, "unexpected libs in the libs to trim", libs_to_trim, "libbaz")
}
+
+func TestCannedFsConfig(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }`)
+ mod := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+ generateFsRule := mod.Rule("generateFsConfig")
+ cmd := generateFsRule.RuleParams.Command
+
+ ensureContains(t, cmd, `( echo '/ 1000 1000 0755'; echo '/apex_manifest.json 1000 1000 0644'; echo '/apex_manifest.pb 1000 1000 0644'; ) >`)
+}
+
+func TestCannedFsConfig_HasCustomConfig(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ canned_fs_config: "my_config",
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }`)
+ mod := ctx.ModuleForTests("myapex", "android_common_myapex_image")
+ generateFsRule := mod.Rule("generateFsConfig")
+ cmd := generateFsRule.RuleParams.Command
+
+ // Ensure that canned_fs_config has "cat my_config" at the end
+ ensureContains(t, cmd, `( echo '/ 1000 1000 0755'; echo '/apex_manifest.json 1000 1000 0644'; echo '/apex_manifest.pb 1000 1000 0644'; cat my_config ) >`)
+}
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
index 03fb5d4..250db7f 100644
--- a/bp2build/apex_conversion_test.go
+++ b/bp2build/apex_conversion_test.go
@@ -58,6 +58,7 @@
ctx.RegisterModuleType("cc_binary", cc.BinaryFactory)
ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
ctx.RegisterModuleType("apex_key", apex.ApexKeyFactory)
+ ctx.RegisterModuleType("apex_test", apex.TestApexBundleFactory)
ctx.RegisterModuleType("android_app_certificate", java.AndroidAppCertificateFactory)
ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
ctx.RegisterModuleType("apex", apex.BundleFactory)
@@ -706,6 +707,125 @@
}})
}
+func TestOverrideApexTest(t *testing.T) {
+ runOverrideApexTestCase(t, Bp2buildTestCase{
+ Description: "override_apex",
+ ModuleTypeUnderTest: "override_apex",
+ ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
+ Filesystem: map[string]string{},
+ Blueprint: `
+apex_key {
+ name: "com.android.apogee.key",
+ public_key: "com.android.apogee.avbpubkey",
+ private_key: "com.android.apogee.pem",
+ bazel_module: { bp2build_available: false },
+}
+
+android_app_certificate {
+ name: "com.android.apogee.certificate",
+ certificate: "com.android.apogee",
+ bazel_module: { bp2build_available: false },
+}
+
+cc_library {
+ name: "native_shared_lib_1",
+ bazel_module: { bp2build_available: false },
+}
+
+prebuilt_etc {
+ name: "prebuilt_1",
+ bazel_module: { bp2build_available: false },
+}
+
+filegroup {
+ name: "com.android.apogee-file_contexts",
+ srcs: [
+ "com.android.apogee-file_contexts",
+ ],
+ bazel_module: { bp2build_available: false },
+}
+
+cc_binary { name: "cc_binary_1", bazel_module: { bp2build_available: false } }
+sh_binary { name: "sh_binary_2", bazel_module: { bp2build_available: false } }
+
+apex_test {
+ name: "com.android.apogee",
+ manifest: "apogee_manifest.json",
+ androidManifest: "ApogeeAndroidManifest.xml",
+ file_contexts: ":com.android.apogee-file_contexts",
+ min_sdk_version: "29",
+ key: "com.android.apogee.key",
+ certificate: ":com.android.apogee.certificate",
+ updatable: false,
+ installable: false,
+ compressible: false,
+ native_shared_libs: [
+ "native_shared_lib_1",
+ ],
+ binaries: [
+ "cc_binary_1",
+ "sh_binary_2",
+ ],
+ prebuilts: [
+ "prebuilt_1",
+ ],
+ bazel_module: { bp2build_available: false },
+}
+
+apex_key {
+ name: "com.google.android.apogee.key",
+ public_key: "com.google.android.apogee.avbpubkey",
+ private_key: "com.google.android.apogee.pem",
+ bazel_module: { bp2build_available: false },
+}
+
+android_app_certificate {
+ name: "com.google.android.apogee.certificate",
+ certificate: "com.google.android.apogee",
+ bazel_module: { bp2build_available: false },
+}
+
+override_apex {
+ name: "com.google.android.apogee",
+ base: ":com.android.apogee",
+ key: "com.google.android.apogee.key",
+ certificate: ":com.google.android.apogee.certificate",
+ prebuilts: [],
+ compressible: true,
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
+ "android_manifest": `"ApogeeAndroidManifest.xml"`,
+ "base_apex_name": `"com.android.apogee"`,
+ "binaries": `[
+ ":cc_binary_1",
+ ":sh_binary_2",
+ ]`,
+ "certificate": `":com.google.android.apogee.certificate"`,
+ "file_contexts": `":com.android.apogee-file_contexts"`,
+ "installable": "False",
+ "key": `":com.google.android.apogee.key"`,
+ "manifest": `"apogee_manifest.json"`,
+ "min_sdk_version": `"29"`,
+ "native_shared_libs_32": `select({
+ "//build/bazel/platforms/arch:arm": [":native_shared_lib_1"],
+ "//build/bazel/platforms/arch:x86": [":native_shared_lib_1"],
+ "//conditions:default": [],
+ })`,
+ "native_shared_libs_64": `select({
+ "//build/bazel/platforms/arch:arm64": [":native_shared_lib_1"],
+ "//build/bazel/platforms/arch:x86_64": [":native_shared_lib_1"],
+ "//conditions:default": [],
+ })`,
+ "testonly": "True",
+ "prebuilts": `[]`,
+ "updatable": "False",
+ "compressible": "True",
+ }),
+ }})
+}
+
func TestApexBundleSimple_manifestIsEmpty_baseApexOverrideApexInDifferentAndroidBp(t *testing.T) {
runOverrideApexTestCase(t, Bp2buildTestCase{
Description: "override_apex - manifest of base apex is empty, base apex and override_apex is in different Android.bp",
diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go
index d915d6b..fdda35b 100644
--- a/bp2build/bp2build_product_config.go
+++ b/bp2build/bp2build_product_config.go
@@ -85,6 +85,11 @@
# TODO: When we start generating the platforms for more than just the
# currently lunched, product, this select should have an arm for each product.
"@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_constraint_value": "@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_product_vars",
+ "@soong_injection//product_config_platforms/products/aosp_arm_for_testing:aosp_arm_for_testing_constraint_value": "@soong_injection//product_config_platforms/products/aosp_arm_for_testing:aosp_arm_for_testing_product_vars",
+ "@soong_injection//product_config_platforms/products/aosp_arm64_for_testing:aosp_arm64_for_testing_constraint_value": "@soong_injection//product_config_platforms/products/aosp_arm64_for_testing:aosp_arm64_for_testing_product_vars",
+ "@soong_injection//product_config_platforms/products/aosp_x86_for_testing:aosp_x86_for_testing_constraint_value": "@soong_injection//product_config_platforms/products/aosp_x86_for_testing:aosp_x86_for_testing_product_vars",
+ "@soong_injection//product_config_platforms/products/aosp_x86_64_for_testing:aosp_x86_64_for_testing_constraint_value": "@soong_injection//product_config_platforms/products/aosp_x86_64_for_testing:aosp_x86_64_for_testing_product_vars",
+ "@soong_injection//product_config_platforms/products/aosp_arm64_for_testing_no_compression:aosp_arm64_for_testing_no_compression_constraint_value": "@soong_injection//product_config_platforms/products/aosp_arm64_for_testing_no_compression:aosp_arm64_for_testing_no_compression_product_vars",
}),
)
`)),
@@ -122,5 +127,42 @@
`)),
}
+ // Add some products for testing
+ for _, arch := range []string{"arm", "arm64", "x86", "x86_64"} {
+ result = append(result, newFile(
+ fmt.Sprintf("product_config_platforms/products/aosp_%s_for_testing", arch),
+ "BUILD",
+ fmt.Sprintf(`
+package(default_visibility=[
+ "@soong_injection//product_config_platforms:__subpackages__",
+ "@//build/bazel/product_config:__subpackages__",
+])
+load("@//build/bazel/tests/products:aosp_%s.variables.bzl", _soong_variables = "variables")
+load("@//build/bazel/product_config:android_product.bzl", "android_product")
+
+android_product(
+ name = "aosp_%s_for_testing",
+ soong_variables = _soong_variables,
+)
+`, arch, arch)))
+ }
+ result = append(result, newFile(
+ "product_config_platforms/products/aosp_arm64_for_testing_no_compression",
+ "BUILD",
+ `
+package(default_visibility=[
+ "@soong_injection//product_config_platforms:__subpackages__",
+ "@//build/bazel/product_config:__subpackages__",
+])
+load("@bazel_skylib//lib:dicts.bzl", "dicts")
+load("@//build/bazel/tests/products:aosp_arm64.variables.bzl", _soong_variables = "variables")
+load("@//build/bazel/product_config:android_product.bzl", "android_product")
+
+android_product(
+ name = "aosp_arm64_for_testing_no_compression",
+ soong_variables = dicts.add(_soong_variables, {"CompressedApex": False}),
+)
+`))
+
return result, nil
}
diff --git a/cc/afdo_test.go b/cc/afdo_test.go
index 335910c..40f705b 100644
--- a/cc/afdo_test.go
+++ b/cc/afdo_test.go
@@ -180,3 +180,100 @@
}
}
}
+
+func TestAfdoEnabledWithMultiArchs(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library_shared {
+ name: "foo",
+ srcs: ["test.c"],
+ afdo: true,
+ compile_multilib: "both",
+ }
+`
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm.afdo", "TEST"),
+ android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm64.afdo", "TEST"),
+ ).RunTestWithBp(t, bp)
+
+ fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon_shared")
+ fooArmCFlags := fooArm.Rule("cc").Args["cFlags"]
+ if w := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/foo_arm.afdo"; !strings.Contains(fooArmCFlags, w) {
+ t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArmCFlags)
+ }
+
+ fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a_shared")
+ fooArm64CFlags := fooArm64.Rule("cc").Args["cFlags"]
+ if w := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/foo_arm64.afdo"; !strings.Contains(fooArm64CFlags, w) {
+ t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", w, fooArm64CFlags)
+ }
+}
+
+func TestMultipleAfdoRDeps(t *testing.T) {
+ t.Parallel()
+ bp := `
+ cc_library_shared {
+ name: "libTest",
+ srcs: ["test.c"],
+ static_libs: ["libFoo"],
+ afdo: true,
+ }
+
+ cc_library_shared {
+ name: "libBar",
+ srcs: ["bar.c"],
+ static_libs: ["libFoo"],
+ afdo: true,
+ }
+
+ cc_library_static {
+ name: "libFoo",
+ srcs: ["foo.c"],
+ }
+ `
+
+ result := android.GroupFixturePreparers(
+ prepareForCcTest,
+ android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libTest.afdo", "TEST"),
+ android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/libBar.afdo", "TEST"),
+ ).RunTestWithBp(t, bp)
+
+ expectedCFlagLibTest := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/libTest.afdo"
+ expectedCFlagLibBar := "-fprofile-sample-use=toolchain/pgo-profiles/sampling/libBar.afdo"
+
+ libTest := result.ModuleForTests("libTest", "android_arm64_armv8-a_shared")
+ libTestAfdoVariantOfLibFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libTest")
+
+ libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_shared")
+ libBarAfdoVariantOfLibFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_afdo-libBar")
+
+ // Check cFlags of afdo-enabled modules and the afdo-variant of their static deps
+ cFlags := libTest.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlagLibTest) {
+ t.Errorf("Expected 'libTest' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibTest, cFlags)
+ }
+ cFlags = libBar.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlagLibBar) {
+ t.Errorf("Expected 'libBar' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
+ }
+
+ cFlags = libTestAfdoVariantOfLibFoo.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlagLibTest) {
+ t.Errorf("Expected 'libTestAfdoVariantOfLibFoo' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibTest, cFlags)
+ }
+
+ cFlags = libBarAfdoVariantOfLibFoo.Rule("cc").Args["cFlags"]
+ if !strings.Contains(cFlags, expectedCFlagLibBar) {
+ t.Errorf("Expected 'libBarAfdoVariantOfLibFoo' to enable afdo, but did not find %q in cflags %q", expectedCFlagLibBar, cFlags)
+ }
+
+ // Check dependency edges of static deps
+ if !hasDirectDep(result, libTest.Module(), libTestAfdoVariantOfLibFoo.Module()) {
+ t.Errorf("libTest missing dependency on afdo variant of libFoo")
+ }
+
+ if !hasDirectDep(result, libBar.Module(), libBarAfdoVariantOfLibFoo.Module()) {
+ t.Errorf("libBar missing dependency on afdo variant of libFoo")
+ }
+}
diff --git a/cc/config/global.go b/cc/config/global.go
index 4d703e4..3eb4577 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -313,6 +313,8 @@
"device/",
"vendor/",
}
+
+ VersionScriptFlagPrefix = "-Wl,--version-script,"
)
// BazelCcToolchainVars generates bzl file content containing variables for
@@ -401,6 +403,8 @@
exportedVars.ExportString("ExperimentalCStdVersion", ExperimentalCStdVersion)
exportedVars.ExportString("ExperimentalCppStdVersion", ExperimentalCppStdVersion)
+ exportedVars.ExportString("VersionScriptFlagPrefix", VersionScriptFlagPrefix)
+
// Everything in these lists is a crime against abstraction and dependency tracking.
// Do not add anything to this list.
commonGlobalIncludes := []string{
diff --git a/cc/linker.go b/cc/linker.go
index e49b97d..257fe86 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -15,11 +15,12 @@
package cc
import (
- "android/soong/android"
- "android/soong/cc/config"
"fmt"
"path/filepath"
+ "android/soong/android"
+ "android/soong/cc/config"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -542,13 +543,13 @@
ctx.PropertyErrorf("version_script", "Not supported on Darwin")
} else {
flags.Local.LdFlags = append(flags.Local.LdFlags,
- "-Wl,--version-script,"+versionScript.String())
+ config.VersionScriptFlagPrefix+versionScript.String())
flags.LdFlagsDeps = append(flags.LdFlagsDeps, versionScript.Path())
if linker.sanitize.isSanitizerEnabled(cfi) {
- cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath)
+ cfiExportsMap := android.PathForSource(ctx, cfiExportsMapPath+"/"+cfiExportsMapFilename)
flags.Local.LdFlags = append(flags.Local.LdFlags,
- "-Wl,--version-script,"+cfiExportsMap.String())
+ config.VersionScriptFlagPrefix+cfiExportsMap.String())
flags.LdFlagsDeps = append(flags.LdFlagsDeps, cfiExportsMap)
}
}
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 5b7ba43..4470f54 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -16,7 +16,6 @@
import (
"path/filepath"
- "strings"
"android/soong/android"
"android/soong/bazel"
@@ -208,12 +207,13 @@
})
// TODO(b/220898484): Mainline module sdk prebuilts of stub libraries use a stub
- // library as their source and must not be installed, but libclang_rt.* libraries
- // have stubs because they are LLNDK libraries, but use an implementation library
- // as their source and need to be installed. This discrepancy should be resolved
- // without the prefix hack below.
- if p.hasStubsVariants() && !p.buildStubs() && !ctx.Host() &&
- !strings.HasPrefix(ctx.baseModuleName(), "libclang_rt.") {
+ // library as their source and must not be installed, but other prebuilts like
+ // libclang_rt.* libraries set `stubs` property because they are LLNDK libraries,
+ // but use an implementation library as their source and need to be installed.
+ // This discrepancy should be resolved without the prefix hack below.
+ isModuleSdkPrebuilts := android.HasAnyPrefix(ctx.ModuleDir(), []string{
+ "prebuilts/runtime/mainline/", "prebuilts/module_sdk/"})
+ if p.hasStubsVariants() && !p.buildStubs() && !ctx.Host() && isModuleSdkPrebuilts {
ctx.Module().MakeUninstallable()
}
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index e3ec9d5..0c79e55 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -670,11 +670,15 @@
}
func TestPrebuiltStubNoinstall(t *testing.T) {
- testFunc := func(t *testing.T, bp string) {
+ testFunc := func(t *testing.T, expectLibfooOnSystemLib bool, fs android.MockFS) {
result := android.GroupFixturePreparers(
prepareForPrebuiltTest,
android.PrepareForTestWithMakevars,
- ).RunTestWithBp(t, bp)
+ android.FixtureMergeMockFs(fs),
+ ).RunTest(t)
+
+ ldRule := result.ModuleForTests("installedlib", "android_arm64_armv8-a_shared").Rule("ld")
+ android.AssertStringDoesContain(t, "", ldRule.Args["libFlags"], "android_arm64_armv8-a_shared/libfoo.so")
installRules := result.InstallMakeRulesForTesting(t)
var installedlibRule *android.InstallMakeRule
@@ -691,50 +695,83 @@
return
}
- android.AssertStringListDoesNotContain(t,
- "installedlib has install dependency on stub",
- installedlibRule.Deps,
- "out/target/product/test_device/system/lib/stublib.so")
- android.AssertStringListDoesNotContain(t,
- "installedlib has order-only install dependency on stub",
- installedlibRule.OrderOnlyDeps,
- "out/target/product/test_device/system/lib/stublib.so")
+ if expectLibfooOnSystemLib {
+ android.AssertStringListContains(t,
+ "installedlib doesn't have install dependency on libfoo impl",
+ installedlibRule.OrderOnlyDeps,
+ "out/target/product/test_device/system/lib/libfoo.so")
+ } else {
+ android.AssertStringListDoesNotContain(t,
+ "installedlib has install dependency on libfoo stub",
+ installedlibRule.Deps,
+ "out/target/product/test_device/system/lib/libfoo.so")
+ android.AssertStringListDoesNotContain(t,
+ "installedlib has order-only install dependency on libfoo stub",
+ installedlibRule.OrderOnlyDeps,
+ "out/target/product/test_device/system/lib/libfoo.so")
+ }
}
- const prebuiltStublibBp = `
+ prebuiltLibfooBp := []byte(`
cc_prebuilt_library {
- name: "stublib",
+ name: "libfoo",
prefer: true,
- srcs: ["foo.so"],
+ srcs: ["libfoo.so"],
stubs: {
versions: ["1"],
},
}
- `
+ `)
- const installedlibBp = `
+ installedlibBp := []byte(`
cc_library {
name: "installedlib",
- shared_libs: ["stublib"],
+ shared_libs: ["libfoo"],
}
- `
+ `)
- t.Run("prebuilt without source", func(t *testing.T) {
- testFunc(t, prebuiltStublibBp+installedlibBp)
+ t.Run("prebuilt stub (without source): no install", func(t *testing.T) {
+ testFunc(
+ t,
+ /*expectLibfooOnSystemLib=*/ false,
+ android.MockFS{
+ "prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
+ "Android.bp": installedlibBp,
+ },
+ )
})
- const disabledSourceStublibBp = `
+ disabledSourceLibfooBp := []byte(`
cc_library {
- name: "stublib",
+ name: "libfoo",
enabled: false,
stubs: {
versions: ["1"],
},
}
- `
+ `)
- t.Run("prebuilt with disabled source", func(t *testing.T) {
- testFunc(t, disabledSourceStublibBp+prebuiltStublibBp+installedlibBp)
+ t.Run("prebuilt stub (with disabled source): no install", func(t *testing.T) {
+ testFunc(
+ t,
+ /*expectLibfooOnSystemLib=*/ false,
+ android.MockFS{
+ "prebuilts/module_sdk/art/current/Android.bp": prebuiltLibfooBp,
+ "impl/Android.bp": disabledSourceLibfooBp,
+ "Android.bp": installedlibBp,
+ },
+ )
+ })
+
+ t.Run("prebuilt impl (with `stubs` property set): install", func(t *testing.T) {
+ testFunc(
+ t,
+ /*expectLibfooOnSystemLib=*/ true,
+ android.MockFS{
+ "impl/Android.bp": prebuiltLibfooBp,
+ "Android.bp": installedlibBp,
+ },
+ )
})
}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index c899cc4..cc81d0e 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -62,14 +62,18 @@
"-fast-isel=false",
}
- cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
- "-fsanitize-ignorelist=external/compiler-rt/lib/cfi/cfi_blocklist.txt"}
+ cfiBlocklistPath = "external/compiler-rt/lib/cfi"
+ cfiBlocklistFilename = "cfi_blocklist.txt"
+ cfiCflags = []string{"-flto", "-fsanitize-cfi-cross-dso",
+ "-fsanitize-ignorelist=" + cfiBlocklistPath + "/" + cfiBlocklistFilename}
// -flto and -fvisibility are required by clang when -fsanitize=cfi is
// used, but have no effect on assembly files
cfiAsflags = []string{"-flto", "-fvisibility=default"}
cfiLdflags = []string{"-flto", "-fsanitize-cfi-cross-dso", "-fsanitize=cfi",
"-Wl,-plugin-opt,O1"}
- cfiExportsMapPath = "build/soong/cc/config/cfi_exports.map"
+ cfiExportsMapPath = "build/soong/cc/config"
+ cfiExportsMapFilename = "cfi_exports.map"
+ cfiAssemblySupportFlag = "-fno-sanitize-cfi-canonical-jump-tables"
intOverflowCflags = []string{"-fsanitize-ignorelist=build/soong/cc/config/integer_overflow_blocklist.txt"}
@@ -388,6 +392,18 @@
exportedVars.ExportStringListStaticVariable("HostOnlySanitizeFlags", hostOnlySanitizeFlags)
exportedVars.ExportStringList("DeviceOnlySanitizeFlags", deviceOnlySanitizeFlags)
+ // Leave out "-flto" from the slices exported to bazel, as we will use the
+ // dedicated LTO feature for this
+ exportedVars.ExportStringList("CfiCFlags", cfiCflags[1:])
+ exportedVars.ExportStringList("CfiAsFlags", cfiAsflags[1:])
+ exportedVars.ExportStringList("CfiLdFlags", cfiLdflags[1:])
+
+ exportedVars.ExportString("CfiBlocklistPath", cfiBlocklistPath)
+ exportedVars.ExportString("CfiBlocklistFilename", cfiBlocklistFilename)
+ exportedVars.ExportString("CfiExportsMapPath", cfiExportsMapPath)
+ exportedVars.ExportString("CfiExportsMapFilename", cfiExportsMapFilename)
+ exportedVars.ExportString("CfiAssemblySupportFlag", cfiAssemblySupportFlag)
+
android.RegisterMakeVarsProvider(pctx, cfiMakeVarsProvider)
android.RegisterMakeVarsProvider(pctx, hwasanMakeVarsProvider)
}
@@ -810,7 +826,7 @@
flags.Local.CFlags = append(flags.Local.CFlags, cfiCflags...)
flags.Local.AsFlags = append(flags.Local.AsFlags, cfiAsflags...)
if Bool(s.Properties.Sanitize.Config.Cfi_assembly_support) {
- flags.Local.CFlags = append(flags.Local.CFlags, "-fno-sanitize-cfi-canonical-jump-tables")
+ flags.Local.CFlags = append(flags.Local.CFlags, cfiAssemblySupportFlag)
}
// Only append the default visibility flag if -fvisibility has not already been set
// to hidden.
diff --git a/java/aar.go b/java/aar.go
index f162a17..47e6efa 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -721,8 +721,8 @@
return a.SdkVersion(ctx).ApiLevel
}
-func (a *AARImport) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
- return android.SdkSpecFrom(ctx, "")
+func (a *AARImport) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
+ return android.SdkSpecFrom(ctx, "").ApiLevel
}
func (a *AARImport) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
diff --git a/java/base.go b/java/base.go
index 2d213a1..1bcff2e 100644
--- a/java/base.go
+++ b/java/base.go
@@ -490,7 +490,7 @@
sdkVersion android.SdkSpec
minSdkVersion android.ApiLevel
- maxSdkVersion android.SdkSpec
+ maxSdkVersion android.ApiLevel
sourceExtensions []string
}
@@ -672,16 +672,20 @@
return j.SdkVersion(ctx).ApiLevel
}
-func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
- maxSdkVersion := proptools.StringDefault(j.deviceProperties.Max_sdk_version, "")
- // SdkSpecFrom returns SdkSpecPrivate for this, which may be confusing.
- // TODO(b/208456999): ideally MaxSdkVersion should be an ApiLevel and not SdkSpec.
- return android.SdkSpecFrom(ctx, maxSdkVersion)
+func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+ if j.deviceProperties.Max_sdk_version != nil {
+ return android.ApiLevelFrom(ctx, *j.deviceProperties.Max_sdk_version)
+ }
+ // Default is PrivateApiLevel
+ return android.SdkSpecPrivate.ApiLevel
}
-func (j *Module) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
- replaceMaxSdkVersionPlaceholder := proptools.StringDefault(j.deviceProperties.Replace_max_sdk_version_placeholder, "")
- return android.SdkSpecFrom(ctx, replaceMaxSdkVersionPlaceholder)
+func (j *Module) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
+ if j.deviceProperties.Replace_max_sdk_version_placeholder != nil {
+ return android.ApiLevelFrom(ctx, *j.deviceProperties.Replace_max_sdk_version_placeholder)
+ }
+ // Default is PrivateApiLevel
+ return android.SdkSpecPrivate.ApiLevel
}
func (j *Module) MinSdkVersionString() string {
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index 45e6175..bc9de50 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -136,11 +136,11 @@
jar.minSdkVersion = s.minSdkVersion.String()
}
}
- if s.maxSdkVersion.ApiLevel.Specified() {
- if s.maxSdkVersion.ApiLevel.IsCurrent() {
+ if s.maxSdkVersion.Specified() {
+ if s.maxSdkVersion.IsCurrent() {
jar.maxSdkVersion = ctx.Config().DefaultAppTargetSdk(ctx).String()
} else {
- jar.maxSdkVersion = s.maxSdkVersion.ApiLevel.String()
+ jar.maxSdkVersion = s.maxSdkVersion.String()
}
}
}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index c5a957e..dbe021d 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -252,8 +252,8 @@
return j.SdkVersion(ctx).ApiLevel
}
-func (j *Javadoc) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
- return j.SdkVersion(ctx)
+func (j *Javadoc) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
+ return j.SdkVersion(ctx).ApiLevel
}
func (j *Javadoc) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
diff --git a/java/java.go b/java/java.go
index 3707815..ebd9f5e 100644
--- a/java/java.go
+++ b/java/java.go
@@ -1613,10 +1613,15 @@
android.ModuleBase
android.DefaultableModuleBase
+ hiddenAPI
+ dexer
+
properties JavaApiLibraryProperties
stubsSrcJar android.WritablePath
stubsJar android.WritablePath
+ // .dex of stubs, used for hiddenapi processing
+ dexJarFile OptionalDexJarPath
}
type JavaApiLibraryProperties struct {
@@ -1794,6 +1799,20 @@
Inputs(staticLibs)
builder.Build("merge_zips", "merge jar files")
+ // compile stubs to .dex for hiddenapi processing
+ dexParams := &compileDexParams{
+ flags: javaBuilderFlags{},
+ sdkVersion: al.SdkVersion(ctx),
+ minSdkVersion: al.MinSdkVersion(ctx),
+ classesJar: al.stubsJar,
+ jarName: ctx.ModuleName() + ".jar",
+ }
+ dexOutputFile := al.dexer.compileDex(ctx, dexParams)
+ uncompressed := true
+ al.initHiddenAPI(ctx, makeDexJarPathFromPath(dexOutputFile), al.stubsJar, &uncompressed)
+ dexOutputFile = al.hiddenAPIEncodeDex(ctx, dexOutputFile)
+ al.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
+
ctx.Phony(ctx.ModuleName(), al.stubsJar)
ctx.SetProvider(JavaInfoProvider, JavaInfo{
@@ -1801,6 +1820,32 @@
})
}
+func (al *ApiLibrary) DexJarBuildPath() OptionalDexJarPath {
+ return al.dexJarFile
+}
+
+func (al *ApiLibrary) DexJarInstallPath() android.Path {
+ return al.dexJarFile.Path()
+}
+
+func (al *ApiLibrary) ClassLoaderContexts() dexpreopt.ClassLoaderContextMap {
+ return nil
+}
+
+// java_api_library constitutes the sdk, and does not build against one
+func (al *ApiLibrary) SdkVersion(ctx android.EarlyModuleContext) android.SdkSpec {
+ return android.SdkSpecNone
+}
+
+// java_api_library is always at "current". Return FutureApiLevel
+func (al *ApiLibrary) MinSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
+ return android.FutureApiLevel
+}
+
+// implement the following interfaces for hiddenapi processing
+var _ hiddenAPIModule = (*ApiLibrary)(nil)
+var _ UsesLibraryDependency = (*ApiLibrary)(nil)
+
//
// Java prebuilts
//
@@ -1898,11 +1943,12 @@
return j.SdkVersion(ctx).ApiLevel
}
-func (j *Import) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
+func (j *Import) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
if j.properties.Replace_max_sdk_version_placeholder != nil {
- return android.SdkSpecFrom(ctx, *j.properties.Replace_max_sdk_version_placeholder)
+ return android.ApiLevelFrom(ctx, *j.properties.Replace_max_sdk_version_placeholder)
}
- return android.SdkSpecFrom(ctx, "")
+ // Default is PrivateApiLevel
+ return android.SdkSpecPrivate.ApiLevel
}
func (j *Import) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
diff --git a/java/rro.go b/java/rro.go
index 6a9ad9a..53faca0 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -182,8 +182,8 @@
return r.SdkVersion(ctx).ApiLevel
}
-func (r *RuntimeResourceOverlay) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.SdkSpec {
- return android.SdkSpecFrom(ctx, "")
+func (r *RuntimeResourceOverlay) ReplaceMaxSdkVersionPlaceholder(ctx android.EarlyModuleContext) android.ApiLevel {
+ return android.SdkSpecPrivate.ApiLevel
}
func (r *RuntimeResourceOverlay) TargetSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
diff --git a/rust/Android.bp b/rust/Android.bp
index 3fd68e5..b01a94a 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -42,6 +42,7 @@
"toolchain_library.go",
],
testSrcs: [
+ "afdo_test.go",
"benchmark_test.go",
"binary_test.go",
"bindgen_test.go",
diff --git a/rust/afdo_test.go b/rust/afdo_test.go
new file mode 100644
index 0000000..fa20eef
--- /dev/null
+++ b/rust/afdo_test.go
@@ -0,0 +1,76 @@
+// Copyright 2023 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 rust
+
+import (
+ "android/soong/android"
+ "fmt"
+ "strings"
+ "testing"
+)
+
+func TestAfdoEnabled(t *testing.T) {
+ bp := `
+ rust_binary {
+ name: "foo",
+ srcs: ["foo.rs"],
+ afdo: true,
+ }
+`
+ result := android.GroupFixturePreparers(
+ prepareForRustTest,
+ android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo.afdo", ""),
+ rustMockedFiles.AddToFixture(),
+ ).RunTestWithBp(t, bp)
+
+ foo := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
+
+ expectedCFlag := fmt.Sprintf(afdoFlagFormat, "toolchain/pgo-profiles/sampling/foo.afdo")
+
+ if !strings.Contains(foo.Args["rustcFlags"], expectedCFlag) {
+ t.Errorf("Expected 'foo' to enable afdo, but did not find %q in cflags %q", expectedCFlag, foo.Args["rustcFlags"])
+ }
+}
+
+func TestAfdoEnabledWithMultiArchs(t *testing.T) {
+ bp := `
+ rust_binary {
+ name: "foo",
+ srcs: ["foo.rs"],
+ afdo: true,
+ compile_multilib: "both",
+ }
+`
+ result := android.GroupFixturePreparers(
+ prepareForRustTest,
+ android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm.afdo", ""),
+ android.FixtureAddTextFile("toolchain/pgo-profiles/sampling/foo_arm64.afdo", ""),
+ rustMockedFiles.AddToFixture(),
+ ).RunTestWithBp(t, bp)
+
+ fooArm := result.ModuleForTests("foo", "android_arm_armv7-a-neon").Rule("rustc")
+ fooArm64 := result.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
+
+ expectedCFlagArm := fmt.Sprintf(afdoFlagFormat, "toolchain/pgo-profiles/sampling/foo_arm.afdo")
+ expectedCFlagArm64 := fmt.Sprintf(afdoFlagFormat, "toolchain/pgo-profiles/sampling/foo_arm64.afdo")
+
+ if !strings.Contains(fooArm.Args["rustcFlags"], expectedCFlagArm) {
+ t.Errorf("Expected 'fooArm' to enable afdo, but did not find %q in cflags %q", expectedCFlagArm, fooArm.Args["rustcFlags"])
+ }
+
+ if !strings.Contains(fooArm64.Args["rustcFlags"], expectedCFlagArm64) {
+ t.Errorf("Expected 'fooArm64' to enable afdo, but did not find %q in cflags %q", expectedCFlagArm64, fooArm64.Args["rustcFlags"])
+ }
+}
diff --git a/tests/apex_cc_module_arch_variant_tests.sh b/tests/apex_cc_module_arch_variant_tests.sh
index b0cade1..1f5e003 100755
--- a/tests/apex_cc_module_arch_variant_tests.sh
+++ b/tests/apex_cc_module_arch_variant_tests.sh
@@ -56,12 +56,12 @@
# Number of CppCompile actions with arch variant flag
actions_with_arch_variant_num=$(call_bazel aquery --config=bp2build --config=ci --config=android \
- 'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex))' | grep -c \'-march=$ARCH_VARIANT_CFLAG\')
+ 'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))' | grep -c \'-march=$ARCH_VARIANT_CFLAG\')
# Number of all CppCompile actions
all_cppcompile_actions_num=0
aquery_summary=$(call_bazel aquery --config=bp2build --config=ci --config=android --output=summary \
- 'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex))' \
+ 'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))' \
| egrep -o '.*opt-ST.*: ([0-9]+)$' \
| cut -d: -f2 -)
@@ -82,7 +82,7 @@
then
# Number of CppCompiler actions with cpu variant flag
actions_with_cpu_variant_num=$(call_bazel aquery --config=bp2build --config=ci --config=android \
- 'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex))' | grep -c "\-mcpu=$CPU_VARIANT_CFLAG")
+ 'mnemonic("CppCompile", deps(//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))' | grep -c "\-mcpu=$CPU_VARIANT_CFLAG")
if [ $actions_with_cpu_variant_num -eq $all_cppcompile_actions_num ]
then
@@ -91,4 +91,4 @@
echo "Error: number of CppCompile actions with cpu variant set: actual=$actions_with_cpu_variant_num, expected=$all_cppcompile_actions_num"
exit 1
fi
-fi
\ No newline at end of file
+fi
diff --git a/tests/apex_comparison_tests.sh b/tests/apex_comparison_tests.sh
index 5007078..e350323 100755
--- a/tests/apex_comparison_tests.sh
+++ b/tests/apex_comparison_tests.sh
@@ -66,10 +66,10 @@
call_bazel build --config=bp2build --config=ci --config=android \
//packages/modules/adb/apex:com.android.adbd \
//system/timezone/apex:com.android.tzdata \
- //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex
+ //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal
BAZEL_ADBD="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //packages/modules/adb/apex:com.android.adbd))"
BAZEL_TZDATA="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //system/timezone/apex:com.android.tzdata))"
-BAZEL_MINIMAL="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex))"
+BAZEL_MINIMAL="$(realpath $(call_bazel cquery --config=bp2build --config=android --config=ci --output=files //build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal))"
# # Build debugfs separately, as it's not a dep of apexer, but needs to be an explicit arg.
call_bazel build --config=bp2build --config=linux_x86_64 //external/e2fsprogs/debugfs //system/apex/tools:deapexer
diff --git a/tests/lib.sh b/tests/lib.sh
index 2bcb630..26608b8 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -91,6 +91,7 @@
symlink_directory prebuilts/go
symlink_directory prebuilts/build-tools
symlink_directory prebuilts/clang/host
+ symlink_directory external/compiler-rt
symlink_directory external/go-cmp
symlink_directory external/golang-protobuf
symlink_directory external/starlark-go