Merge "Add libselinux to the Rust allowlist so we can run its test."
diff --git a/android/bazel.go b/android/bazel.go
index 7123ed2..8c86a95 100644
--- a/android/bazel.go
+++ b/android/bazel.go
@@ -137,6 +137,7 @@
// build/bazel explicitly.
"build/bazel":/* recursive = */ false,
"build/bazel/examples/android_app":/* recursive = */ true,
+ "build/bazel/examples/java":/* recursive = */ true,
"build/bazel/bazel_skylib":/* recursive = */ true,
"build/bazel/rules":/* recursive = */ true,
"build/bazel/rules_cc":/* recursive = */ true,
@@ -148,7 +149,9 @@
// external/bazelbuild-rules_android/... is needed by mixed builds, otherwise mixed builds analysis fails
// e.g. ERROR: Analysis of target '@soong_injection//mixed_builds:buildroot' failed
"external/bazelbuild-rules_android":/* recursive = */ true,
+ "external/bazel-skylib":/* recursive = */ true,
+ "prebuilts/jdk":/* recursive = */ true,
"prebuilts/sdk":/* recursive = */ false,
"prebuilts/sdk/tools":/* recursive = */ false,
"prebuilts/r8":/* recursive = */ false,
@@ -166,9 +169,10 @@
"system/logging/liblog": Bp2BuildDefaultTrueRecursively,
"system/timezone/apex": Bp2BuildDefaultTrueRecursively,
"system/timezone/output_data": Bp2BuildDefaultTrueRecursively,
- "external/jemalloc_new": Bp2BuildDefaultTrueRecursively,
- "external/fmtlib": Bp2BuildDefaultTrueRecursively,
"external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
+ "external/fmtlib": Bp2BuildDefaultTrueRecursively,
+ "external/jemalloc_new": Bp2BuildDefaultTrueRecursively,
+ "external/libcxxabi": Bp2BuildDefaultTrueRecursively,
"external/scudo": Bp2BuildDefaultTrueRecursively,
"prebuilts/clang/host/linux-x86": Bp2BuildDefaultTrueRecursively,
}
@@ -204,16 +208,11 @@
"libBionicBenchmarksUtils", // cc_library_static, fatal error: 'map' file not found, from libcxx
"fmtlib", // cc_library_static, fatal error: 'cassert' file not found, from libcxx
"fmtlib_ndk", // cc_library_static, fatal error: 'cassert' file not found
+ "liblog", // http://b/186822772: cc_library, 'sys/cdefs.h' file not found
"libbase", // Requires liblog. http://b/186826479, cc_library, fatal error: 'memory' file not found, from libcxx.
+ // Also depends on fmtlib.
- // http://b/186024507: Includes errors because of the system_shared_libs default value.
- // Missing -isystem bionic/libc/include through the libc/libm/libdl
- // default dependencies if system_shared_libs is unset.
- "liblog", // http://b/186822772: cc_library, 'sys/cdefs.h' file not found
- "libjemalloc5_jet", // cc_library, 'sys/cdefs.h' file not found
- "libseccomp_policy", // http://b/186476753: cc_library, 'linux/filter.h' not found
- "note_memtag_heap_async", // http://b/185127353: cc_library_static, error: feature.h not found
- "note_memtag_heap_sync", // http://b/185127353: cc_library_static, error: feature.h not found
+ "libseccomp_policy", // depends on libbase
"gwp_asan_crash_handler", // cc_library, ld.lld: error: undefined symbol: memset
@@ -236,7 +235,10 @@
// Per-module denylist to opt modules out of mixed builds. Such modules will
// still be generated via bp2build.
- mixedBuildsDisabledList = []string{}
+ mixedBuildsDisabledList = []string{
+ "libc++abi", // http://b/195970501, cc_library_static, duplicate symbols because it propagates libc objects.
+ "libc++demangle", // http://b/195970501, cc_library_static, duplicate symbols because it propagates libc objects.
+ }
// Used for quicker lookups
bp2buildModuleDoNotConvert = map[string]bool{}
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
index b050774..c09d218 100644
--- a/android/bazel_paths.go
+++ b/android/bazel_paths.go
@@ -115,6 +115,11 @@
func bazelLabelForModuleDeps(ctx BazelConversionPathContext, modules []string, isWholeLibs bool) bazel.LabelList {
var labels bazel.LabelList
+ // In some cases, a nil string list is different than an explicitly empty list.
+ if len(modules) == 0 && modules != nil {
+ labels.Includes = []bazel.Label{}
+ return labels
+ }
for _, module := range modules {
bpText := module
if m := SrcIsModule(module); m == "" {
diff --git a/apex/apex.go b/apex/apex.go
index e525aff..add506f 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -1587,6 +1587,7 @@
JacocoReportClassesFile() android.Path
Certificate() java.Certificate
BaseModuleName() string
+ LintDepSets() java.LintDepSets
}
var _ androidApp = (*java.AndroidApp)(nil)
@@ -1601,6 +1602,7 @@
fileToCopy := aapp.OutputFile()
af := newApexFile(ctx, fileToCopy, aapp.BaseModuleName(), dirInApex, app, aapp)
af.jacocoReportClassesFile = aapp.JacocoReportClassesFile()
+ af.lintDepSets = aapp.LintDepSets()
af.certificate = aapp.Certificate()
if app, ok := aapp.(interface {
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 41bfcea..f07bf63 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -4663,6 +4663,7 @@
prebuilt_bootclasspath_fragment {
name: "art-bootclasspath-fragment",
+ image_name: "art",
contents: ["core-oj"],
hidden_api: {
annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
@@ -4871,7 +4872,7 @@
func TestBootDexJarsFromSourcesAndPrebuilts(t *testing.T) {
preparer := android.GroupFixturePreparers(
- java.FixtureConfigureBootJars("myapex:libfoo", "myapex:libbar"),
+ java.FixtureConfigureApexBootJars("myapex:libfoo", "myapex:libbar"),
// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
// is disabled.
android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
@@ -4949,6 +4950,7 @@
name: "libfoo",
jars: ["libfoo.jar"],
apex_available: ["myapex"],
+ permitted_packages: ["foo"],
}
java_sdk_library_import {
@@ -4958,6 +4960,7 @@
},
apex_available: ["myapex"],
shared_library: false,
+ permitted_packages: ["bar"],
}
`
@@ -4998,6 +5001,7 @@
name: "libfoo",
jars: ["libfoo.jar"],
apex_available: ["myapex"],
+ permitted_packages: ["foo"],
}
java_sdk_library_import {
@@ -5007,6 +5011,7 @@
},
apex_available: ["myapex"],
shared_library: false,
+ permitted_packages: ["bar"],
}
`
@@ -5120,6 +5125,7 @@
prefer: true,
jars: ["libfoo.jar"],
apex_available: ["myapex"],
+ permitted_packages: ["foo"],
}
java_library {
@@ -5136,6 +5142,7 @@
},
apex_available: ["myapex"],
shared_library: false,
+ permitted_packages: ["bar"],
}
java_sdk_library {
@@ -5209,6 +5216,7 @@
name: "libfoo",
srcs: ["foo/bar/MyClass.java"],
apex_available: ["myapex"],
+ permitted_packages: ["foo"],
}
java_sdk_library_import {
@@ -5225,6 +5233,7 @@
srcs: ["foo/bar/MyClass.java"],
unsafe_ignore_missing_latest_api: true,
apex_available: ["myapex"],
+ permitted_packages: ["bar"],
}
`
@@ -5286,6 +5295,7 @@
prefer: true,
jars: ["libfoo.jar"],
apex_available: ["myapex"],
+ permitted_packages: ["foo"],
}
java_library {
@@ -5302,6 +5312,7 @@
},
apex_available: ["myapex"],
shared_library: false,
+ permitted_packages: ["bar"],
}
java_sdk_library {
@@ -6899,6 +6910,7 @@
apex_available: [
"some-updatable-apex",
],
+ permitted_packages: ["some.updatable.apex.lib"],
}
java_library {
@@ -6908,6 +6920,7 @@
"some-non-updatable-apex",
],
compile_dex: true,
+ permitted_packages: ["some.non.updatable.apex.lib"],
}
bootclasspath_fragment {
@@ -7118,7 +7131,9 @@
"myapex",
],
}
- `)
+ `,
+ dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
+ )
}
func TestNoUpdatableJarsInBootImage(t *testing.T) {
@@ -7148,18 +7163,30 @@
}
t.Run("updatable jar from ART apex in the ART boot image => ok", func(t *testing.T) {
- preparer := java.FixtureConfigureBootJars("com.android.art.debug:some-art-lib")
- fragment := java.ApexVariantReference{
- Apex: proptools.StringPtr("com.android.art.debug"),
- Module: proptools.StringPtr("art-bootclasspath-fragment"),
+ preparer := android.GroupFixturePreparers(
+ java.FixtureConfigureBootJars("com.android.art.debug:some-art-lib"),
+ java.FixtureConfigureApexBootJars("some-non-updatable-apex:some-non-updatable-apex-lib"),
+ )
+ fragments := []java.ApexVariantReference{
+ {
+ Apex: proptools.StringPtr("com.android.art.debug"),
+ Module: proptools.StringPtr("art-bootclasspath-fragment"),
+ },
+ {
+ Apex: proptools.StringPtr("some-non-updatable-apex"),
+ Module: proptools.StringPtr("some-non-updatable-fragment"),
+ },
}
- testNoUpdatableJarsInBootImage(t, "", preparer, fragment)
+ testNoUpdatableJarsInBootImage(t, "", preparer, fragments...)
})
t.Run("updatable jar from ART apex in the framework boot image => error", func(t *testing.T) {
err := `module "some-art-lib" from updatable apexes \["com.android.art.debug"\] is not allowed in the framework boot image`
// Update the dexpreopt BootJars directly.
- preparer := prepareSetBootJars("com.android.art.debug:some-art-lib")
+ preparer := android.GroupFixturePreparers(
+ prepareSetBootJars("com.android.art.debug:some-art-lib"),
+ java.FixtureConfigureApexBootJars("some-non-updatable-apex:some-non-updatable-apex-lib"),
+ )
testNoUpdatableJarsInBootImage(t, err, preparer)
})
@@ -7179,12 +7206,15 @@
t.Run("updatable jar from some other apex in the framework boot image => error", func(t *testing.T) {
err := `module "some-updatable-apex-lib" from updatable apexes \["some-updatable-apex"\] is not allowed in the framework boot image`
- preparer := java.FixtureConfigureBootJars("some-updatable-apex:some-updatable-apex-lib")
+ preparer := android.GroupFixturePreparers(
+ java.FixtureConfigureBootJars("some-updatable-apex:some-updatable-apex-lib"),
+ java.FixtureConfigureApexBootJars("some-non-updatable-apex:some-non-updatable-apex-lib"),
+ )
testNoUpdatableJarsInBootImage(t, err, preparer)
})
t.Run("non-updatable jar from some other apex in the framework boot image => ok", func(t *testing.T) {
- preparer := java.FixtureConfigureBootJars("some-non-updatable-apex:some-non-updatable-apex-lib")
+ preparer := java.FixtureConfigureApexBootJars("some-non-updatable-apex:some-non-updatable-apex-lib")
fragment := java.ApexVariantReference{
Apex: proptools.StringPtr("some-non-updatable-apex"),
Module: proptools.StringPtr("some-non-updatable-fragment"),
@@ -7212,13 +7242,22 @@
})
t.Run("platform jar in the framework boot image => ok", func(t *testing.T) {
- preparer := java.FixtureConfigureBootJars("platform:some-platform-lib")
- testNoUpdatableJarsInBootImage(t, "", preparer)
+ preparer := android.GroupFixturePreparers(
+ java.FixtureConfigureBootJars("platform:some-platform-lib"),
+ java.FixtureConfigureApexBootJars("some-non-updatable-apex:some-non-updatable-apex-lib"),
+ )
+ fragments := []java.ApexVariantReference{
+ {
+ Apex: proptools.StringPtr("some-non-updatable-apex"),
+ Module: proptools.StringPtr("some-non-updatable-fragment"),
+ },
+ }
+ testNoUpdatableJarsInBootImage(t, "", preparer, fragments...)
})
}
func TestDexpreoptAccessDexFilesFromPrebuiltApex(t *testing.T) {
- preparer := java.FixtureConfigureBootJars("myapex:libfoo")
+ preparer := java.FixtureConfigureApexBootJars("myapex:libfoo")
t.Run("prebuilt no source", func(t *testing.T) {
fragment := java.ApexVariantReference{
Apex: proptools.StringPtr("myapex"),
@@ -7256,6 +7295,7 @@
name: "libfoo",
jars: ["libfoo.jar"],
apex_available: ["myapex"],
+ permitted_packages: ["libfoo"],
}
`, "", preparer, fragment)
})
@@ -8168,6 +8208,8 @@
java.PrepareForTestWithJavaDefaultModules,
android.PrepareForTestWithAndroidBuildComponents,
android.FixtureWithRootAndroidBp(bp),
+ dexpreopt.FixtureSetApexBootJars("myapex:mybootclasspathlib"),
+ dexpreopt.FixtureSetApexSystemServerJars("myapex:mysystemserverclasspathlib"),
android.FixtureMergeEnv(map[string]string{
"EMMA_INSTRUMENT": "true",
}),
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 6098989..3e19014 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -130,7 +130,8 @@
result := android.GroupFixturePreparers(
prepareForTestWithBootclasspathFragment,
// Configure some libraries in the art bootclasspath_fragment and platform_bootclasspath.
- java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "platform:foo", "platform:bar"),
+ java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz"),
+ java.FixtureConfigureApexBootJars("someapex:foo", "someapex:bar"),
prepareForTestWithArtApex,
java.PrepareForTestWithJavaSdkLibraryFiles,
@@ -642,7 +643,7 @@
prepareForTestWithBootclasspathFragment,
prepareForTestWithMyapex,
// Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
- java.FixtureConfigureBootJars("myapex:foo", "myapex:bar"),
+ java.FixtureConfigureApexBootJars("myapex:foo", "myapex:bar"),
// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
// is disabled.
android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
@@ -893,7 +894,8 @@
prepareForTestWithArtApex,
prepareForTestWithMyapex,
// Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
- java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "myapex:foo", "myapex:bar"),
+ java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz"),
+ java.FixtureConfigureApexBootJars("myapex:foo", "myapex:bar"),
// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
// is disabled.
android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
@@ -1062,7 +1064,8 @@
prepareForTestWithArtApex,
prepareForTestWithMyapex,
// Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
- java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz", "myapex:foo", "myapex:bar"),
+ java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz"),
+ java.FixtureConfigureApexBootJars("myapex:foo", "myapex:bar"),
// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
// is disabled.
android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
diff --git a/apex/builder.go b/apex/builder.go
index 148f42f..5baa5c0 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -75,7 +75,7 @@
// by default set to (uid/gid/mode) = (1000/1000/0644)
// TODO(b/113082813) make this configurable using config.fs syntax
generateFsConfig = pctx.StaticRule("generateFsConfig", blueprint.RuleParams{
- Command: `( echo '/ 1000 1000 0755' ` +
+ Command: `( set -e; echo '/ 1000 1000 0755' ` +
`&& for i in ${ro_paths}; do echo "/$$i 1000 1000 0644"; done ` +
`&& for i in ${exec_paths}; do echo "/$$i 0 2000 0755"; done ` +
`&& ( tr ' ' '\n' <${out}.apklist | for i in ${apk_paths}; do read apk; echo "/$$i 0 2000 0755"; zipinfo -1 $$apk | sed "s:\(.*\):/$$i/\1 1000 1000 0644:"; done ) ) > ${out}`,
diff --git a/apex/classpath_element_test.go b/apex/classpath_element_test.go
index 0193127..e2d8465 100644
--- a/apex/classpath_element_test.go
+++ b/apex/classpath_element_test.go
@@ -58,6 +58,7 @@
}),
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("foo", "othersdklibrary"),
+ java.FixtureConfigureApexBootJars("myapex:bar"),
android.FixtureWithRootAndroidBp(`
apex {
name: "com.android.art",
@@ -79,6 +80,7 @@
bootclasspath_fragment {
name: "art-bootclasspath-fragment",
+ image_name: "art",
apex_available: [
"com.android.art",
],
@@ -193,6 +195,10 @@
apex: "com.android.art",
module: "art-bootclasspath-fragment",
},
+ {
+ apex: "myapex",
+ module: "mybootclasspath-fragment",
+ },
],
}
`),
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index 3066c79..306e1ea 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -39,7 +39,7 @@
prepareForTestWithMyapex,
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("foo"),
- java.FixtureConfigureBootJars("myapex:bar"),
+ java.FixtureConfigureApexBootJars("myapex:bar"),
android.FixtureWithRootAndroidBp(`
platform_bootclasspath {
name: "platform-bootclasspath",
@@ -195,6 +195,7 @@
bootclasspath_fragment {
name: "art-bootclasspath-fragment",
+ image_name: "art",
apex_available: [
"com.android.art",
],
diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go
index 537f51d..a64c6f4 100644
--- a/apex/systemserver_classpath_fragment_test.go
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -15,6 +15,7 @@
package apex
import (
+ "android/soong/dexpreopt"
"testing"
"android/soong/android"
@@ -30,6 +31,7 @@
result := android.GroupFixturePreparers(
prepareForTestWithSystemserverclasspathFragment,
prepareForTestWithMyapex,
+ dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
).RunTestWithBp(t, `
apex {
name: "myapex",
@@ -81,6 +83,7 @@
result := android.GroupFixturePreparers(
prepareForTestWithSystemserverclasspathFragment,
prepareForTestWithMyapex,
+ dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
).RunTestWithBp(t, `
apex {
name: "myapex",
diff --git a/bazel/configurability.go b/bazel/configurability.go
index f5f0913..7aaff9a 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -56,7 +56,7 @@
// This is consistently named "conditions_default" to mirror the Soong
// config variable default key in an Android.bp file, although there's no
// integration with Soong config variables (yet).
- conditionsDefault = "conditions_default"
+ ConditionsDefaultConfigKey = "conditions_default"
ConditionsDefaultSelectKey = "//conditions:default"
@@ -72,45 +72,45 @@
// A map of architectures to the Bazel label of the constraint_value
// for the @platforms//cpu:cpu constraint_setting
platformArchMap = map[string]string{
- archArm: "//build/bazel/platforms/arch:arm",
- archArm64: "//build/bazel/platforms/arch:arm64",
- archX86: "//build/bazel/platforms/arch:x86",
- archX86_64: "//build/bazel/platforms/arch:x86_64",
- conditionsDefault: ConditionsDefaultSelectKey, // The default condition of as arch select map.
+ archArm: "//build/bazel/platforms/arch:arm",
+ archArm64: "//build/bazel/platforms/arch:arm64",
+ archX86: "//build/bazel/platforms/arch:x86",
+ archX86_64: "//build/bazel/platforms/arch:x86_64",
+ ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of as arch select map.
}
// A map of target operating systems to the Bazel label of the
// constraint_value for the @platforms//os:os constraint_setting
platformOsMap = map[string]string{
- osAndroid: "//build/bazel/platforms/os:android",
- osDarwin: "//build/bazel/platforms/os:darwin",
- osLinux: "//build/bazel/platforms/os:linux",
- osLinuxMusl: "//build/bazel/platforms/os:linux_musl",
- osLinuxBionic: "//build/bazel/platforms/os:linux_bionic",
- osWindows: "//build/bazel/platforms/os:windows",
- conditionsDefault: ConditionsDefaultSelectKey, // The default condition of an os select map.
+ osAndroid: "//build/bazel/platforms/os:android",
+ osDarwin: "//build/bazel/platforms/os:darwin",
+ osLinux: "//build/bazel/platforms/os:linux",
+ osLinuxMusl: "//build/bazel/platforms/os:linux_musl",
+ osLinuxBionic: "//build/bazel/platforms/os:linux_bionic",
+ osWindows: "//build/bazel/platforms/os:windows",
+ ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
}
platformBionicMap = map[string]string{
- "bionic": "//build/bazel/platforms/os:bionic",
- conditionsDefault: ConditionsDefaultSelectKey, // The default condition of an os select map.
+ "bionic": "//build/bazel/platforms/os:bionic",
+ ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
}
platformOsArchMap = map[string]string{
- osArchAndroidArm: "//build/bazel/platforms/os_arch:android_arm",
- osArchAndroidArm64: "//build/bazel/platforms/os_arch:android_arm64",
- osArchAndroidX86: "//build/bazel/platforms/os_arch:android_x86",
- osArchAndroidX86_64: "//build/bazel/platforms/os_arch:android_x86_64",
- osArchDarwinX86_64: "//build/bazel/platforms/os_arch:darwin_x86_64",
- osArchLinuxX86: "//build/bazel/platforms/os_arch:linux_glibc_x86",
- osArchLinuxX86_64: "//build/bazel/platforms/os_arch:linux_glibc_x86_64",
- osArchLinuxMuslX86: "//build/bazel/platforms/os_arch:linux_musl_x86",
- osArchLinuxMuslX86_64: "//build/bazel/platforms/os_arch:linux_musl_x86_64",
- osArchLinuxBionicArm64: "//build/bazel/platforms/os_arch:linux_bionic_arm64",
- osArchLinuxBionicX86_64: "//build/bazel/platforms/os_arch:linux_bionic_x86_64",
- osArchWindowsX86: "//build/bazel/platforms/os_arch:windows_x86",
- osArchWindowsX86_64: "//build/bazel/platforms/os_arch:windows_x86_64",
- conditionsDefault: ConditionsDefaultSelectKey, // The default condition of an os select map.
+ osArchAndroidArm: "//build/bazel/platforms/os_arch:android_arm",
+ osArchAndroidArm64: "//build/bazel/platforms/os_arch:android_arm64",
+ osArchAndroidX86: "//build/bazel/platforms/os_arch:android_x86",
+ osArchAndroidX86_64: "//build/bazel/platforms/os_arch:android_x86_64",
+ osArchDarwinX86_64: "//build/bazel/platforms/os_arch:darwin_x86_64",
+ osArchLinuxX86: "//build/bazel/platforms/os_arch:linux_glibc_x86",
+ osArchLinuxX86_64: "//build/bazel/platforms/os_arch:linux_glibc_x86_64",
+ osArchLinuxMuslX86: "//build/bazel/platforms/os_arch:linux_musl_x86",
+ osArchLinuxMuslX86_64: "//build/bazel/platforms/os_arch:linux_musl_x86_64",
+ osArchLinuxBionicArm64: "//build/bazel/platforms/os_arch:linux_bionic_arm64",
+ osArchLinuxBionicX86_64: "//build/bazel/platforms/os_arch:linux_bionic_x86_64",
+ osArchWindowsX86: "//build/bazel/platforms/os_arch:windows_x86",
+ osArchWindowsX86_64: "//build/bazel/platforms/os_arch:windows_x86_64",
+ ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
}
)
@@ -181,7 +181,7 @@
case bionic:
return platformBionicMap[config]
case productVariables:
- if config == conditionsDefault {
+ if config == ConditionsDefaultConfigKey {
return ConditionsDefaultSelectKey
}
return fmt.Sprintf("%s:%s", productVariableBazelPackage, strings.ToLower(config))
diff --git a/bazel/properties.go b/bazel/properties.go
index 2656bad..1a846ba 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -69,6 +69,23 @@
Excludes []Label
}
+func (ll *LabelList) Equals(other LabelList) bool {
+ if len(ll.Includes) != len(other.Includes) || len(ll.Excludes) != len(other.Excludes) {
+ return false
+ }
+ for i, _ := range ll.Includes {
+ if ll.Includes[i] != other.Includes[i] {
+ return false
+ }
+ }
+ for i, _ := range ll.Excludes {
+ if ll.Excludes[i] != other.Excludes[i] {
+ return false
+ }
+ }
+ return true
+}
+
func (ll *LabelList) IsNil() bool {
return ll.Includes == nil && ll.Excludes == nil
}
@@ -446,7 +463,7 @@
// HasConfigurableValues returns whether there are configurable values within this set of selects.
func (ll labelListSelectValues) HasConfigurableValues() bool {
for _, v := range ll {
- if len(v.Includes) > 0 {
+ if v.Includes != nil {
return true
}
}
@@ -462,6 +479,13 @@
// The configured attribute label list Values. Optional
// a map of independent configurability axes
ConfigurableValues configurableLabelLists
+
+ // If true, differentiate between "nil" and "empty" list. nil means that
+ // this attribute should not be specified at all, and "empty" means that
+ // the attribute should be explicitly specified as an empty list.
+ // This mode facilitates use of attribute defaults: an empty list should
+ // override the default.
+ ForceSpecifyEmptyList bool
}
type configurableLabelLists map[ConfigurationAxis]labelListSelectValues
@@ -546,6 +570,9 @@
// Append all values, including os and arch specific ones, from another
// LabelListAttribute to this LabelListAttribute.
func (lla *LabelListAttribute) Append(other LabelListAttribute) {
+ if lla.ForceSpecifyEmptyList && !other.Value.IsNil() {
+ lla.Value.Includes = []Label{}
+ }
lla.Value.Append(other.Value)
if lla.ConfigurableValues == nil {
lla.ConfigurableValues = make(configurableLabelLists)
@@ -595,7 +622,7 @@
// Now that the Value list is finalized for this axis, compare it with the original
// list, and put the difference into the default condition for the axis.
- lla.ConfigurableValues[axis][conditionsDefault] = SubtractBazelLabelList(baseLabels, lla.Value)
+ lla.ConfigurableValues[axis][ConditionsDefaultConfigKey] = SubtractBazelLabelList(baseLabels, lla.Value)
// if everything ends up without includes, just delete the axis
if !lla.ConfigurableValues[axis].HasConfigurableValues() {
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index 8dcba55..bff192f 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -1454,3 +1454,213 @@
)`},
})
}
+
+func TestCcLibrary_SystemSharedLibsRootEmpty(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ description: "cc_library system_shared_libs empty at root",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ blueprint: soongCcLibraryPreamble + `
+cc_library {
+ name: "root_empty",
+ system_shared_libs: [],
+}
+`,
+ expectedBazelTargets: []string{`cc_library(
+ name = "root_empty",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ system_dynamic_deps = [],
+)`},
+ })
+}
+
+func TestCcLibrary_SystemSharedLibsStaticEmpty(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ description: "cc_library system_shared_libs empty for static variant",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ blueprint: soongCcLibraryPreamble + `
+cc_library {
+ name: "static_empty",
+ static: {
+ system_shared_libs: [],
+ },
+}
+`,
+ expectedBazelTargets: []string{`cc_library(
+ name = "static_empty",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ static = {
+ "system_dynamic_deps": [],
+ },
+)`},
+ })
+}
+
+func TestCcLibrary_SystemSharedLibsSharedEmpty(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ description: "cc_library system_shared_libs empty for shared variant",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ blueprint: soongCcLibraryPreamble + `
+cc_library {
+ name: "shared_empty",
+ shared: {
+ system_shared_libs: [],
+ },
+}
+`,
+ expectedBazelTargets: []string{`cc_library(
+ name = "shared_empty",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ shared = {
+ "system_dynamic_deps": [],
+ },
+)`},
+ })
+}
+
+func TestCcLibrary_SystemSharedLibsSharedBionicEmpty(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ description: "cc_library system_shared_libs empty for shared, bionic variant",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ blueprint: soongCcLibraryPreamble + `
+cc_library {
+ name: "shared_empty",
+ target: {
+ bionic: {
+ shared: {
+ system_shared_libs: [],
+ }
+ }
+ },
+}
+`,
+ expectedBazelTargets: []string{`cc_library(
+ name = "shared_empty",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ shared = {
+ "system_dynamic_deps": [],
+ },
+)`},
+ })
+}
+
+func TestCcLibrary_SystemSharedLibsLinuxBionicEmpty(t *testing.T) {
+ // Note that this behavior is technically incorrect (it's a simplification).
+ // The correct behavior would be if bp2build wrote `system_dynamic_deps = []`
+ // only for linux_bionic, but `android` had `["libc", "libdl", "libm"].
+ // b/195791252 tracks the fix.
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ description: "cc_library system_shared_libs empty for linux_bionic variant",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ blueprint: soongCcLibraryPreamble + `
+cc_library {
+ name: "target_linux_bionic_empty",
+ target: {
+ linux_bionic: {
+ system_shared_libs: [],
+ },
+ },
+}
+`,
+ expectedBazelTargets: []string{`cc_library(
+ name = "target_linux_bionic_empty",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ system_dynamic_deps = [],
+)`},
+ })
+}
+
+func TestCcLibrary_SystemSharedLibsBionicEmpty(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ description: "cc_library system_shared_libs empty for bionic variant",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ blueprint: soongCcLibraryPreamble + `
+cc_library {
+ name: "target_bionic_empty",
+ target: {
+ bionic: {
+ system_shared_libs: [],
+ },
+ },
+}
+`,
+ expectedBazelTargets: []string{`cc_library(
+ name = "target_bionic_empty",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ system_dynamic_deps = [],
+)`},
+ })
+}
+
+func TestCcLibrary_SystemSharedLibsSharedAndRoot(t *testing.T) {
+ runCcLibraryTestCase(t, bp2buildTestCase{
+ description: "cc_library system_shared_libs set for shared and root",
+ moduleTypeUnderTest: "cc_library",
+ moduleTypeUnderTestFactory: cc.LibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryBp2Build,
+ blueprint: soongCcLibraryPreamble + `
+cc_library {name: "libc"}
+cc_library {name: "libm"}
+
+cc_library {
+ name: "foo",
+ system_shared_libs: ["libc"],
+ shared: {
+ system_shared_libs: ["libm"],
+ },
+}
+`,
+ expectedBazelTargets: []string{`cc_library(
+ name = "foo",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ shared = {
+ "system_dynamic_deps": [":libm"],
+ },
+ system_dynamic_deps = [":libc"],
+)`, `cc_library(
+ name = "libc",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+)`, `cc_library(
+ name = "libm",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+)`},
+ })
+}
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
index 1dc6713..d9145f6 100644
--- a/bp2build/cc_library_static_conversion_test.go
+++ b/bp2build/cc_library_static_conversion_test.go
@@ -73,6 +73,8 @@
ctx.RegisterModuleType("toolchain_library", cc.ToolchainLibraryFactory)
ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
+ // Required for system_shared_libs dependencies.
+ ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
}
func runCcLibraryStaticTestCase(t *testing.T, tc bp2buildTestCase) {
@@ -1427,3 +1429,185 @@
)`},
})
}
+
+func TestStaticLibrary_SystemSharedLibsRootEmpty(t *testing.T) {
+ runCcLibraryStaticTestCase(t, bp2buildTestCase{
+ description: "cc_library_static system_shared_lib empty root",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ blueprint: soongCcLibraryStaticPreamble + `
+cc_library_static {
+ name: "root_empty",
+ system_shared_libs: [],
+}
+`,
+ expectedBazelTargets: []string{`cc_library_static(
+ name = "root_empty",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ linkstatic = True,
+ system_dynamic_deps = [],
+)`},
+ })
+}
+
+func TestStaticLibrary_SystemSharedLibsStaticEmpty(t *testing.T) {
+ runCcLibraryStaticTestCase(t, bp2buildTestCase{
+ description: "cc_library_static system_shared_lib empty static default",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ blueprint: soongCcLibraryStaticPreamble + `
+cc_defaults {
+ name: "static_empty_defaults",
+ static: {
+ system_shared_libs: [],
+ },
+}
+cc_library_static {
+ name: "static_empty",
+ defaults: ["static_empty_defaults"],
+}
+`,
+ expectedBazelTargets: []string{`cc_library_static(
+ name = "static_empty",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ linkstatic = True,
+ system_dynamic_deps = [],
+)`},
+ })
+}
+
+func TestStaticLibrary_SystemSharedLibsBionicEmpty(t *testing.T) {
+ runCcLibraryStaticTestCase(t, bp2buildTestCase{
+ description: "cc_library_static system_shared_lib empty for bionic variant",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ blueprint: soongCcLibraryStaticPreamble + `
+cc_library_static {
+ name: "target_bionic_empty",
+ target: {
+ bionic: {
+ system_shared_libs: [],
+ },
+ },
+}
+`,
+ expectedBazelTargets: []string{`cc_library_static(
+ name = "target_bionic_empty",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ linkstatic = True,
+ system_dynamic_deps = [],
+)`},
+ })
+}
+
+func TestStaticLibrary_SystemSharedLibsLinuxBionicEmpty(t *testing.T) {
+ // Note that this behavior is technically incorrect (it's a simplification).
+ // The correct behavior would be if bp2build wrote `system_dynamic_deps = []`
+ // only for linux_bionic, but `android` had `["libc", "libdl", "libm"].
+ // b/195791252 tracks the fix.
+ runCcLibraryStaticTestCase(t, bp2buildTestCase{
+ description: "cc_library_static system_shared_lib empty for linux_bionic variant",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ blueprint: soongCcLibraryStaticPreamble + `
+cc_library_static {
+ name: "target_linux_bionic_empty",
+ target: {
+ linux_bionic: {
+ system_shared_libs: [],
+ },
+ },
+}
+`,
+ expectedBazelTargets: []string{`cc_library_static(
+ name = "target_linux_bionic_empty",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ linkstatic = True,
+ system_dynamic_deps = [],
+)`},
+ })
+}
+
+func TestStaticLibrary_SystemSharedLibsBionic(t *testing.T) {
+ runCcLibraryStaticTestCase(t, bp2buildTestCase{
+ description: "cc_library_static system_shared_libs set for bionic variant",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ blueprint: soongCcLibraryStaticPreamble + `
+cc_library{name: "libc"}
+
+cc_library_static {
+ name: "target_bionic",
+ target: {
+ bionic: {
+ system_shared_libs: ["libc"],
+ },
+ },
+}
+`,
+ expectedBazelTargets: []string{`cc_library_static(
+ name = "target_bionic",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ linkstatic = True,
+ system_dynamic_deps = select({
+ "//build/bazel/platforms/os:bionic": [":libc"],
+ "//conditions:default": [],
+ }),
+)`},
+ })
+}
+
+func TestStaticLibrary_SystemSharedLibsLinuxRootAndLinuxBionic(t *testing.T) {
+ runCcLibraryStaticTestCase(t, bp2buildTestCase{
+ description: "cc_library_static system_shared_libs set for root and linux_bionic variant",
+ moduleTypeUnderTest: "cc_library_static",
+ moduleTypeUnderTestFactory: cc.LibraryStaticFactory,
+ moduleTypeUnderTestBp2BuildMutator: cc.CcLibraryStaticBp2Build,
+ blueprint: soongCcLibraryStaticPreamble + `
+cc_library{name: "libc"}
+cc_library{name: "libm"}
+
+cc_library_static {
+ name: "target_linux_bionic",
+ system_shared_libs: ["libc"],
+ target: {
+ linux_bionic: {
+ system_shared_libs: ["libm"],
+ },
+ },
+}
+`,
+ expectedBazelTargets: []string{`cc_library_static(
+ name = "target_linux_bionic",
+ copts = [
+ "-I.",
+ "-I$(BINDIR)/.",
+ ],
+ linkstatic = True,
+ system_dynamic_deps = [":libc"] + select({
+ "//build/bazel/platforms/os:linux_bionic": [":libm"],
+ "//conditions:default": [],
+ }),
+)`},
+ })
+}
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
index c8105eb..005f13d 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -82,7 +82,12 @@
continue
}
archSelects := map[string]reflect.Value{}
+ defaultVal := configToLabels[bazel.ConditionsDefaultConfigKey]
for config, labels := range configToLabels {
+ // Omit any entries in the map which match the default value, for brevity.
+ if config != bazel.ConditionsDefaultConfigKey && labels.Equals(defaultVal) {
+ continue
+ }
selectKey := axis.SelectKey(config)
if use, value := labelListSelectValue(selectKey, labels); use {
archSelects[selectKey] = value
@@ -118,6 +123,8 @@
var value reflect.Value
var configurableAttrs []selects
var defaultSelectValue *string
+ // If true, print the default attribute value, even if the attribute is zero.
+ shouldPrintDefault := false
switch list := v.(type) {
case bazel.StringListAttribute:
value, configurableAttrs = getStringListValues(list)
@@ -125,6 +132,9 @@
case bazel.LabelListAttribute:
value, configurableAttrs = getLabelListValues(list)
defaultSelectValue = &emptyBazelList
+ if list.ForceSpecifyEmptyList && (!value.IsNil() || list.HasConfigurableValues()) {
+ shouldPrintDefault = true
+ }
case bazel.LabelAttribute:
value, configurableAttrs = getLabelValue(list)
defaultSelectValue = &bazelNone
@@ -166,6 +176,9 @@
}
}
+ if ret == "" && shouldPrintDefault {
+ return *defaultSelectValue, nil
+ }
return ret, nil
}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 68afd0d..1706d72 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -35,6 +35,8 @@
Static_deps bazel.LabelListAttribute
Dynamic_deps bazel.LabelListAttribute
Whole_archive_deps bazel.LabelListAttribute
+
+ System_dynamic_deps bazel.LabelListAttribute
}
func groupSrcsByExtension(ctx android.TopDownMutatorContext, srcs bazel.LabelListAttribute) (cppSrcs, cSrcs, asSrcs bazel.LabelListAttribute) {
@@ -137,12 +139,19 @@
props = lib.SharedProperties.Shared
}
+ system_dynamic_deps := bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, props.System_shared_libs))
+ system_dynamic_deps.ForceSpecifyEmptyList = true
+ if system_dynamic_deps.IsEmpty() && props.System_shared_libs != nil {
+ system_dynamic_deps.Value.Includes = []bazel.Label{}
+ }
+
attrs := staticOrSharedAttributes{
- Copts: bazel.StringListAttribute{Value: props.Cflags},
- Srcs: bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, props.Srcs)),
- Static_deps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, props.Static_libs)),
- Dynamic_deps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, append(props.Shared_libs, props.System_shared_libs...))),
- Whole_archive_deps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleWholeDeps(ctx, props.Whole_static_libs)),
+ Copts: bazel.StringListAttribute{Value: props.Cflags},
+ Srcs: bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, props.Srcs)),
+ Static_deps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, props.Static_libs)),
+ Dynamic_deps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, props.Shared_libs)),
+ Whole_archive_deps: bazel.MakeLabelListAttribute(android.BazelLabelForModuleWholeDeps(ctx, props.Whole_static_libs)),
+ System_dynamic_deps: system_dynamic_deps,
}
setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) {
@@ -151,6 +160,7 @@
attrs.Static_deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, props.Static_libs))
attrs.Dynamic_deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, props.Shared_libs))
attrs.Whole_archive_deps.SetSelectValue(axis, config, android.BazelLabelForModuleWholeDeps(ctx, props.Whole_static_libs))
+ attrs.System_dynamic_deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, props.System_shared_libs))
}
if isStatic {
@@ -230,6 +240,8 @@
// C++ options and sources
cppFlags bazel.StringListAttribute
srcs bazel.LabelListAttribute
+
+ rtti bazel.BoolAttribute
}
// bp2BuildParseCompilerProps returns copts, srcs and hdrs and other attributes.
@@ -239,6 +251,7 @@
var asFlags bazel.StringListAttribute
var conlyFlags bazel.StringListAttribute
var cppFlags bazel.StringListAttribute
+ var rtti bazel.BoolAttribute
// Creates the -I flags for a directory, while making the directory relative
// to the exec root for Bazel to work.
@@ -292,6 +305,7 @@
asFlags.Value = parseCommandLineFlags(baseCompilerProps.Asflags)
conlyFlags.Value = parseCommandLineFlags(baseCompilerProps.Conlyflags)
cppFlags.Value = parseCommandLineFlags(baseCompilerProps.Cppflags)
+ rtti.Value = baseCompilerProps.Rtti
for _, dir := range parseLocalIncludeDirs(baseCompilerProps) {
copts.Value = append(copts.Value, includeFlags(dir)...)
@@ -335,6 +349,7 @@
asFlags.SetSelectValue(axis, config, archVariantAsflags)
conlyFlags.SetSelectValue(axis, config, parseCommandLineFlags(baseCompilerProps.Conlyflags))
cppFlags.SetSelectValue(axis, config, parseCommandLineFlags(baseCompilerProps.Cppflags))
+ rtti.SetSelectValue(axis, config, baseCompilerProps.Rtti)
}
}
}
@@ -370,6 +385,7 @@
cSrcs: cSrcs,
conlyFlags: conlyFlags,
cppFlags: cppFlags,
+ rtti: rtti,
}
}
@@ -377,6 +393,7 @@
type linkerAttributes struct {
deps bazel.LabelListAttribute
dynamicDeps bazel.LabelListAttribute
+ systemDynamicDeps bazel.LabelListAttribute
wholeArchiveDeps bazel.LabelListAttribute
exportedDeps bazel.LabelListAttribute
useLibcrt bazel.BoolAttribute
@@ -406,6 +423,7 @@
var exportedDeps bazel.LabelListAttribute
var dynamicDeps bazel.LabelListAttribute
var wholeArchiveDeps bazel.LabelListAttribute
+ var systemSharedDeps bazel.LabelListAttribute
var linkopts bazel.StringListAttribute
var versionScript bazel.LabelAttribute
var useLibcrt bazel.BoolAttribute
@@ -445,9 +463,16 @@
staticDeps.Value = android.BazelLabelForModuleDepsExcludes(ctx, staticLibs, baseLinkerProps.Exclude_static_libs)
wholeArchiveLibs := android.FirstUniqueStrings(baseLinkerProps.Whole_static_libs)
wholeArchiveDeps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleWholeDepsExcludes(ctx, wholeArchiveLibs, baseLinkerProps.Exclude_static_libs))
- // TODO(b/186024507): Handle system_shared_libs as its own attribute, so that the appropriate default
- // may be supported.
- sharedLibs := android.FirstUniqueStrings(append(baseLinkerProps.Shared_libs, baseLinkerProps.System_shared_libs...))
+
+ systemSharedLibs := android.FirstUniqueStrings(baseLinkerProps.System_shared_libs)
+ systemSharedDeps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, systemSharedLibs))
+ systemSharedDeps.ForceSpecifyEmptyList = true
+ if systemSharedDeps.Value.IsNil() && baseLinkerProps.System_shared_libs != nil {
+ systemSharedDeps.Value.Includes = []bazel.Label{}
+ }
+
+ sharedLibs := android.FirstUniqueStrings(baseLinkerProps.Shared_libs)
+
dynamicDeps = bazel.MakeLabelListAttribute(android.BazelLabelForModuleDepsExcludes(ctx, sharedLibs, baseLinkerProps.Exclude_shared_libs))
headerLibs := android.FirstUniqueStrings(baseLinkerProps.Header_libs)
@@ -474,7 +499,14 @@
staticDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDepsExcludes(ctx, staticLibs, baseLinkerProps.Exclude_static_libs))
wholeArchiveLibs := android.FirstUniqueStrings(baseLinkerProps.Whole_static_libs)
wholeArchiveDeps.SetSelectValue(axis, config, android.BazelLabelForModuleWholeDepsExcludes(ctx, wholeArchiveLibs, baseLinkerProps.Exclude_static_libs))
- sharedLibs := android.FirstUniqueStrings(append(baseLinkerProps.Shared_libs, baseLinkerProps.System_shared_libs...))
+
+ systemSharedLibs := android.FirstUniqueStrings(baseLinkerProps.System_shared_libs)
+ if len(systemSharedLibs) == 0 && baseLinkerProps.System_shared_libs != nil {
+ systemSharedLibs = baseLinkerProps.System_shared_libs
+ }
+ systemSharedDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, systemSharedLibs))
+
+ sharedLibs := android.FirstUniqueStrings(baseLinkerProps.Shared_libs)
dynamicDeps.SetSelectValue(axis, config, android.BazelLabelForModuleDepsExcludes(ctx, sharedLibs, baseLinkerProps.Exclude_shared_libs))
headerLibs := android.FirstUniqueStrings(baseLinkerProps.Header_libs)
@@ -550,13 +582,14 @@
headerDeps.Append(staticDeps)
return linkerAttributes{
- deps: headerDeps,
- exportedDeps: exportedDeps,
- dynamicDeps: dynamicDeps,
- wholeArchiveDeps: wholeArchiveDeps,
- linkopts: linkopts,
- useLibcrt: useLibcrt,
- versionScript: versionScript,
+ deps: headerDeps,
+ exportedDeps: exportedDeps,
+ dynamicDeps: dynamicDeps,
+ systemDynamicDeps: systemSharedDeps,
+ wholeArchiveDeps: wholeArchiveDeps,
+ linkopts: linkopts,
+ useLibcrt: useLibcrt,
+ versionScript: versionScript,
// Strip properties
stripKeepSymbols: stripKeepSymbols,
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 812a245..2d6bcb8 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -96,31 +96,25 @@
pctx.SourcePathVariable("Arm64GccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/aarch64/aarch64-linux-android-${arm64GccVersion}")
- pctx.StaticVariable("Arm64Ldflags", strings.Join(arm64Ldflags, " "))
- pctx.StaticVariable("Arm64Lldflags", strings.Join(arm64Lldflags, " "))
+ exportStringListStaticVariable("Arm64Ldflags", arm64Ldflags)
+ exportStringListStaticVariable("Arm64Lldflags", arm64Lldflags)
- pctx.StaticVariable("Arm64Cflags", strings.Join(arm64Cflags, " "))
- pctx.StaticVariable("Arm64Cppflags", strings.Join(arm64Cppflags, " "))
+ exportStringListStaticVariable("Arm64Cflags", arm64Cflags)
+ exportStringListStaticVariable("Arm64Cppflags", arm64Cppflags)
+
+ exportedStringListDictVars.Set("Arm64ArchVariantCflags", arm64ArchVariantCflags)
+ exportedStringListDictVars.Set("Arm64CpuVariantCflags", arm64CpuVariantCflags)
pctx.StaticVariable("Arm64Armv8ACflags", strings.Join(arm64ArchVariantCflags["armv8-a"], " "))
pctx.StaticVariable("Arm64Armv8ABranchProtCflags", strings.Join(arm64ArchVariantCflags["armv8-a-branchprot"], " "))
pctx.StaticVariable("Arm64Armv82ACflags", strings.Join(arm64ArchVariantCflags["armv8-2a"], " "))
pctx.StaticVariable("Arm64Armv82ADotprodCflags", strings.Join(arm64ArchVariantCflags["armv8-2a-dotprod"], " "))
- pctx.StaticVariable("Arm64CortexA53Cflags",
- strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))
-
- pctx.StaticVariable("Arm64CortexA55Cflags",
- strings.Join(arm64CpuVariantCflags["cortex-a55"], " "))
-
- pctx.StaticVariable("Arm64KryoCflags",
- strings.Join(arm64CpuVariantCflags["kryo"], " "))
-
- pctx.StaticVariable("Arm64ExynosM1Cflags",
- strings.Join(arm64CpuVariantCflags["exynos-m1"], " "))
-
- pctx.StaticVariable("Arm64ExynosM2Cflags",
- strings.Join(arm64CpuVariantCflags["exynos-m2"], " "))
+ pctx.StaticVariable("Arm64CortexA53Cflags", strings.Join(arm64CpuVariantCflags["cortex-a53"], " "))
+ pctx.StaticVariable("Arm64CortexA55Cflags", strings.Join(arm64CpuVariantCflags["cortex-a55"], " "))
+ pctx.StaticVariable("Arm64KryoCflags", strings.Join(arm64CpuVariantCflags["kryo"], " "))
+ pctx.StaticVariable("Arm64ExynosM1Cflags", strings.Join(arm64CpuVariantCflags["exynos-m1"], " "))
+ pctx.StaticVariable("Arm64ExynosM2Cflags", strings.Join(arm64CpuVariantCflags["exynos-m2"], " "))
}
var (
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index b5afe40..0fe5e68 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -188,6 +188,9 @@
exportStringListStaticVariable("ArmArmCflags", armArmCflags)
exportStringListStaticVariable("ArmThumbCflags", armThumbCflags)
+ exportedStringListDictVars.Set("ArmArchVariantCflags", armArchVariantCflags)
+ exportedStringListDictVars.Set("ArmCpuVariantCflags", armCpuVariantCflags)
+
// Clang arch variant cflags
exportStringListStaticVariable("ArmArmv7ACflags", armArchVariantCflags["armv7-a"])
exportStringListStaticVariable("ArmArmv7ANeonCflags", armArchVariantCflags["armv7-a-neon"])
diff --git a/cc/config/bp2build.go b/cc/config/bp2build.go
index e7e94a8..d19f5ac 100644
--- a/cc/config/bp2build.go
+++ b/cc/config/bp2build.go
@@ -15,98 +15,182 @@
package config
import (
- "android/soong/android"
"fmt"
"regexp"
+ "sort"
"strings"
)
+const (
+ bazelIndent = 4
+)
+
+type bazelVarExporter interface {
+ asBazel(exportedStringVariables, exportedStringListVariables) []bazelConstant
+}
+
// Helpers for exporting cc configuration information to Bazel.
var (
// Map containing toolchain variables that are independent of the
// environment variables of the build.
- exportedStringListVars = exportedStringListVariables{}
- exportedStringVars = exportedStringVariables{}
+ exportedStringListVars = exportedStringListVariables{}
+ exportedStringVars = exportedStringVariables{}
+ exportedStringListDictVars = exportedStringListDictVariables{}
)
+// Ensure that string s has no invalid characters to be generated into the bzl file.
+func validateCharacters(s string) string {
+ for _, c := range []string{`\n`, `"`, `\`} {
+ if strings.Contains(s, c) {
+ panic(fmt.Errorf("%s contains illegal character %s", s, c))
+ }
+ }
+ return s
+}
+
+type bazelConstant struct {
+ variableName string
+ internalDefinition string
+}
+
type exportedStringVariables map[string]string
-type exportedStringListVariables map[string][]string
func (m exportedStringVariables) Set(k string, v string) {
m[k] = v
}
+func bazelIndention(level int) string {
+ return strings.Repeat(" ", level*bazelIndent)
+}
+
+func printBazelList(items []string, indentLevel int) string {
+ list := make([]string, 0, len(items)+2)
+ list = append(list, "[")
+ innerIndent := bazelIndention(indentLevel + 1)
+ for _, item := range items {
+ list = append(list, fmt.Sprintf(`%s"%s",`, innerIndent, item))
+ }
+ list = append(list, bazelIndention(indentLevel)+"]")
+ return strings.Join(list, "\n")
+}
+
+func (m exportedStringVariables) asBazel(stringScope exportedStringVariables, stringListScope exportedStringListVariables) []bazelConstant {
+ ret := make([]bazelConstant, 0, len(m))
+ for k, variableValue := range m {
+ expandedVar := expandVar(variableValue, exportedStringVars, exportedStringListVars)
+ if len(expandedVar) > 1 {
+ panic(fmt.Errorf("%s expands to more than one string value: %s", variableValue, expandedVar))
+ }
+ ret = append(ret, bazelConstant{
+ variableName: k,
+ internalDefinition: fmt.Sprintf(`"%s"`, validateCharacters(expandedVar[0])),
+ })
+ }
+ return ret
+}
+
// Convenience function to declare a static variable and export it to Bazel's cc_toolchain.
func exportStringStaticVariable(name string, value string) {
pctx.StaticVariable(name, value)
exportedStringVars.Set(name, value)
}
+type exportedStringListVariables map[string][]string
+
func (m exportedStringListVariables) Set(k string, v []string) {
m[k] = v
}
+func (m exportedStringListVariables) asBazel(stringScope exportedStringVariables, stringListScope exportedStringListVariables) []bazelConstant {
+ ret := make([]bazelConstant, 0, len(m))
+ // For each exported variable, recursively expand elements in the variableValue
+ // list to ensure that interpolated variables are expanded according to their values
+ // in the variable scope.
+ for k, variableValue := range m {
+ var expandedVars []string
+ for _, v := range variableValue {
+ expandedVars = append(expandedVars, expandVar(v, stringScope, stringListScope)...)
+ }
+ // Assign the list as a bzl-private variable; this variable will be exported
+ // out through a constants struct later.
+ ret = append(ret, bazelConstant{
+ variableName: k,
+ internalDefinition: printBazelList(expandedVars, 0),
+ })
+ }
+ return ret
+}
+
// Convenience function to declare a static variable and export it to Bazel's cc_toolchain.
func exportStringListStaticVariable(name string, value []string) {
pctx.StaticVariable(name, strings.Join(value, " "))
exportedStringListVars.Set(name, value)
}
+type exportedStringListDictVariables map[string]map[string][]string
+
+func (m exportedStringListDictVariables) Set(k string, v map[string][]string) {
+ m[k] = v
+}
+
+func printBazelStringListDict(dict map[string][]string) string {
+ bazelDict := make([]string, 0, len(dict)+2)
+ bazelDict = append(bazelDict, "{")
+ for k, v := range dict {
+ bazelDict = append(bazelDict,
+ fmt.Sprintf(`%s"%s": %s,`, bazelIndention(1), k, printBazelList(v, 1)))
+ }
+ bazelDict = append(bazelDict, "}")
+ return strings.Join(bazelDict, "\n")
+}
+
+// Since dictionaries are not supported in Ninja, we do not expand variables for dictionaries
+func (m exportedStringListDictVariables) asBazel(_ exportedStringVariables, _ exportedStringListVariables) []bazelConstant {
+ ret := make([]bazelConstant, 0, len(m))
+ for k, dict := range m {
+ ret = append(ret, bazelConstant{
+ variableName: k,
+ internalDefinition: printBazelStringListDict(dict),
+ })
+ }
+ return ret
+}
+
// BazelCcToolchainVars generates bzl file content containing variables for
// Bazel's cc_toolchain configuration.
func BazelCcToolchainVars() string {
+ return bazelToolchainVars(
+ exportedStringListDictVars,
+ exportedStringListVars,
+ exportedStringVars)
+}
+
+func bazelToolchainVars(vars ...bazelVarExporter) string {
ret := "# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.\n\n"
- // Ensure that string s has no invalid characters to be generated into the bzl file.
- validateCharacters := func(s string) string {
- for _, c := range []string{`\n`, `"`, `\`} {
- if strings.Contains(s, c) {
- panic(fmt.Errorf("%s contains illegal character %s", s, c))
- }
- }
- return s
+ results := []bazelConstant{}
+ for _, v := range vars {
+ results = append(results, v.asBazel(exportedStringVars, exportedStringListVars)...)
}
- // For each exported variable, recursively expand elements in the variableValue
- // list to ensure that interpolated variables are expanded according to their values
- // in the variable scope.
- for _, k := range android.SortedStringKeys(exportedStringListVars) {
- variableValue := exportedStringListVars[k]
- var expandedVars []string
- for _, v := range variableValue {
- expandedVars = append(expandedVars, expandVar(v, exportedStringVars, exportedStringListVars)...)
- }
- // Build the list for this variable.
- list := "["
- for _, flag := range expandedVars {
- list += fmt.Sprintf("\n \"%s\",", validateCharacters(flag))
- }
- list += "\n]"
- // Assign the list as a bzl-private variable; this variable will be exported
- // out through a constants struct later.
- ret += fmt.Sprintf("_%s = %s\n", k, list)
- ret += "\n"
- }
+ sort.Slice(results, func(i, j int) bool { return results[i].variableName < results[j].variableName })
- for _, k := range android.SortedStringKeys(exportedStringVars) {
- variableValue := exportedStringVars[k]
- expandedVar := expandVar(variableValue, exportedStringVars, exportedStringListVars)
- if len(expandedVar) > 1 {
- panic(fmt.Errorf("%s expands to more than one string value: %s", variableValue, expandedVar))
- }
- ret += fmt.Sprintf("_%s = \"%s\"\n", k, validateCharacters(expandedVar[0]))
- ret += "\n"
+ definitions := make([]string, 0, len(results))
+ constants := make([]string, 0, len(results))
+ for _, b := range results {
+ definitions = append(definitions,
+ fmt.Sprintf("_%s = %s", b.variableName, b.internalDefinition))
+ constants = append(constants,
+ fmt.Sprintf("%[1]s%[2]s = _%[2]s,", bazelIndention(1), b.variableName))
}
// Build the exported constants struct.
+ ret += strings.Join(definitions, "\n\n")
+ ret += "\n\n"
ret += "constants = struct(\n"
- for _, k := range android.SortedStringKeys(exportedStringVars) {
- ret += fmt.Sprintf(" %s = _%s,\n", k, k)
- }
- for _, k := range android.SortedStringKeys(exportedStringListVars) {
- ret += fmt.Sprintf(" %s = _%s,\n", k, k)
- }
- ret += ")"
+ ret += strings.Join(constants, "\n")
+ ret += "\n)"
+
return ret
}
diff --git a/cc/config/bp2build_test.go b/cc/config/bp2build_test.go
index a4745e6..883597a 100644
--- a/cc/config/bp2build_test.go
+++ b/cc/config/bp2build_test.go
@@ -115,3 +115,143 @@
})
}
}
+
+func TestBazelToolchainVars(t *testing.T) {
+ testCases := []struct {
+ name string
+ vars []bazelVarExporter
+ expectedOut string
+ }{
+ {
+ name: "exports strings",
+ vars: []bazelVarExporter{
+ exportedStringVariables{
+ "a": "b",
+ "c": "d",
+ },
+ },
+ expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
+
+_a = "b"
+
+_c = "d"
+
+constants = struct(
+ a = _a,
+ c = _c,
+)`,
+ },
+ {
+ name: "exports string lists",
+ vars: []bazelVarExporter{
+ exportedStringListVariables{
+ "a": []string{"b1", "b2"},
+ "c": []string{"d1", "d2"},
+ },
+ },
+ expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
+
+_a = [
+ "b1",
+ "b2",
+]
+
+_c = [
+ "d1",
+ "d2",
+]
+
+constants = struct(
+ a = _a,
+ c = _c,
+)`,
+ },
+ {
+ name: "exports string lists dicts",
+ vars: []bazelVarExporter{
+ exportedStringListDictVariables{
+ "a": map[string][]string{"b1": []string{"b2"}},
+ "c": map[string][]string{"d1": []string{"d2"}},
+ },
+ },
+ expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
+
+_a = {
+ "b1": [
+ "b2",
+ ],
+}
+
+_c = {
+ "d1": [
+ "d2",
+ ],
+}
+
+constants = struct(
+ a = _a,
+ c = _c,
+)`,
+ },
+ {
+ name: "sorts across types",
+ vars: []bazelVarExporter{
+ exportedStringVariables{
+ "b": "b-val",
+ "d": "d-val",
+ },
+ exportedStringListVariables{
+ "c": []string{"c-val"},
+ "e": []string{"e-val"},
+ },
+ exportedStringListDictVariables{
+ "a": map[string][]string{"a1": []string{"a2"}},
+ "f": map[string][]string{"f1": []string{"f2"}},
+ },
+ },
+ expectedOut: `# GENERATED FOR BAZEL FROM SOONG. DO NOT EDIT.
+
+_a = {
+ "a1": [
+ "a2",
+ ],
+}
+
+_b = "b-val"
+
+_c = [
+ "c-val",
+]
+
+_d = "d-val"
+
+_e = [
+ "e-val",
+]
+
+_f = {
+ "f1": [
+ "f2",
+ ],
+}
+
+constants = struct(
+ a = _a,
+ b = _b,
+ c = _c,
+ d = _d,
+ e = _e,
+ f = _f,
+)`,
+ },
+ }
+
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ out := bazelToolchainVars(tc.vars...)
+ if out != tc.expectedOut {
+ t.Errorf("Expected \n%s, got \n%s", tc.expectedOut, out)
+ }
+ })
+ }
+}
diff --git a/cc/config/global.go b/cc/config/global.go
index 3daee38..248822f 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -228,6 +228,8 @@
"-Wno-non-c-typedef-for-linkage", // http://b/161304145
// New warnings to be fixed after clang-r407598
"-Wno-string-concatenation", // http://b/175068488
+ // New warnings to be fixed after clang-r428724
+ "-Wno-align-mismatch", // http://b/193679946
}
// Extra cflags for external third-party projects to disable warnings that
@@ -266,8 +268,8 @@
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r416183b1"
- ClangDefaultShortVersion = "12.0.7"
+ ClangDefaultVersion = "clang-r428724"
+ ClangDefaultShortVersion = "13.0.1"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index c4f47a7..00f07ff 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -77,6 +77,14 @@
"popcnt": []string{"-mpopcnt"},
"aes_ni": []string{"-maes"},
}
+
+ x86_64DefaultArchVariantFeatures = []string{
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "popcnt",
+ }
)
const (
@@ -84,37 +92,38 @@
)
func init() {
- android.RegisterDefaultArchVariantFeatures(android.Android, android.X86_64,
- "ssse3",
- "sse4",
- "sse4_1",
- "sse4_2",
- "popcnt")
+ android.RegisterDefaultArchVariantFeatures(android.Android, android.X86_64, x86_64DefaultArchVariantFeatures...)
+ exportedStringListVars.Set("X86_64DefaultArchVariantFeatures", x86_64DefaultArchVariantFeatures)
pctx.StaticVariable("x86_64GccVersion", x86_64GccVersion)
pctx.SourcePathVariable("X86_64GccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86_64GccVersion}")
- pctx.StaticVariable("X86_64ToolchainCflags", "-m64")
- pctx.StaticVariable("X86_64ToolchainLdflags", "-m64")
+ exportStringListStaticVariable("X86_64ToolchainCflags", []string{"-m64"})
+ exportStringListStaticVariable("X86_64ToolchainLdflags", []string{"-m64"})
- pctx.StaticVariable("X86_64Ldflags", strings.Join(x86_64Ldflags, " "))
- pctx.StaticVariable("X86_64Lldflags", strings.Join(x86_64Ldflags, " "))
+ exportStringListStaticVariable("X86_64Ldflags", x86_64Ldflags)
+ exportStringListStaticVariable("X86_64Lldflags", x86_64Ldflags)
// Clang cflags
- pctx.StaticVariable("X86_64Cflags", strings.Join(x86_64Cflags, " "))
- pctx.StaticVariable("X86_64Cppflags", strings.Join(x86_64Cppflags, " "))
+ exportStringListStaticVariable("X86_64Cflags", x86_64Cflags)
+ exportStringListStaticVariable("X86_64Cppflags", x86_64Cppflags)
// Yasm flags
- pctx.StaticVariable("X86_64YasmFlags", "-f elf64 -m amd64")
+ exportStringListStaticVariable("X86_64YasmFlags", []string{
+ "-f elf64",
+ "-m amd64",
+ })
// Extended cflags
+ exportedStringListDictVars.Set("X86_64ArchVariantCflags", x86_64ArchVariantCflags)
+ exportedStringListDictVars.Set("X86_64ArchFeatureCflags", x86_64ArchFeatureCflags)
+
// Architecture variant cflags
for variant, cflags := range x86_64ArchVariantCflags {
- pctx.StaticVariable("X86_64"+variant+"VariantCflags",
- strings.Join(cflags, " "))
+ pctx.StaticVariable("X86_64"+variant+"VariantCflags", strings.Join(cflags, " "))
}
}
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index 5e510a4..29f0593 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -97,25 +97,29 @@
pctx.SourcePathVariable("X86GccRoot",
"prebuilts/gcc/${HostPrebuiltTag}/x86/x86_64-linux-android-${x86GccVersion}")
- pctx.StaticVariable("X86ToolchainCflags", "-m32")
- pctx.StaticVariable("X86ToolchainLdflags", "-m32")
+ exportStringListStaticVariable("X86ToolchainCflags", []string{"-m32"})
+ exportStringListStaticVariable("X86ToolchainLdflags", []string{"-m32"})
- pctx.StaticVariable("X86Ldflags", strings.Join(x86Ldflags, " "))
- pctx.StaticVariable("X86Lldflags", strings.Join(x86Ldflags, " "))
+ exportStringListStaticVariable("X86Ldflags", x86Ldflags)
+ exportStringListStaticVariable("X86Lldflags", x86Ldflags)
// Clang cflags
- pctx.StaticVariable("X86Cflags", strings.Join(x86Cflags, " "))
- pctx.StaticVariable("X86Cppflags", strings.Join(x86Cppflags, " "))
+ exportStringListStaticVariable("X86Cflags", x86Cflags)
+ exportStringListStaticVariable("X86Cppflags", x86Cppflags)
// Yasm flags
- pctx.StaticVariable("X86YasmFlags", "-f elf32 -m x86")
+ exportStringListStaticVariable("X86YasmFlags", []string{
+ "-f elf32",
+ "-m x86",
+ })
// Extended cflags
+ exportedStringListDictVars.Set("X86ArchVariantCflags", x86ArchVariantCflags)
+ exportedStringListDictVars.Set("X86ArchFeatureCflags", x86ArchFeatureCflags)
// Architecture variant cflags
for variant, cflags := range x86ArchVariantCflags {
- pctx.StaticVariable("X86"+variant+"VariantCflags",
- strings.Join(cflags, " "))
+ pctx.StaticVariable("X86"+variant+"VariantCflags", strings.Join(cflags, " "))
}
}
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 1d66cb7..e7fcfed 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -110,7 +110,7 @@
muslCrtBeginSharedBinary, muslCrtEndSharedBinary = []string{"libc_musl_crtbegin_dynamic", "musl_linker_script"}, []string{"libc_musl_crtend"}
muslCrtBeginSharedLibrary, muslCrtEndSharedLibrary = []string{"libc_musl_crtbegin_so"}, []string{"libc_musl_crtend_so"}
- muslDefaultSharedLibraries = []string{"libjemalloc5", "libc_musl"}
+ muslDefaultSharedLibraries = []string{"libc_musl"}
)
const (
diff --git a/cc/library.go b/cc/library.go
index 8f302fc..51cba20 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -23,13 +23,12 @@
"strings"
"sync"
- "github.com/google/blueprint"
- "github.com/google/blueprint/pathtools"
-
"android/soong/android"
"android/soong/bazel"
"android/soong/bazel/cquery"
"android/soong/cc/config"
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/pathtools"
)
// LibraryProperties is a collection of properties shared by cc library rules.
@@ -233,9 +232,11 @@
Implementation_deps bazel.LabelListAttribute
Dynamic_deps bazel.LabelListAttribute
Whole_archive_deps bazel.LabelListAttribute
+ System_dynamic_deps bazel.LabelListAttribute
Includes bazel.StringListAttribute
Linkopts bazel.StringListAttribute
Use_libcrt bazel.BoolAttribute
+ Rtti bazel.BoolAttribute
// This is shared only.
Version_script bazel.LabelAttribute
@@ -319,9 +320,11 @@
Deps: linkerAttrs.exportedDeps,
Dynamic_deps: linkerAttrs.dynamicDeps,
Whole_archive_deps: linkerAttrs.wholeArchiveDeps,
+ System_dynamic_deps: linkerAttrs.systemDynamicDeps,
Includes: exportedIncludes,
Linkopts: linkerAttrs.linkopts,
Use_libcrt: linkerAttrs.useLibcrt,
+ Rtti: compilerAttrs.rtti,
Version_script: linkerAttrs.versionScript,
@@ -2329,9 +2332,12 @@
Implementation_deps bazel.LabelListAttribute
Deps bazel.LabelListAttribute
Whole_archive_deps bazel.LabelListAttribute
+ Dynamic_deps bazel.LabelListAttribute
+ System_dynamic_deps bazel.LabelListAttribute
Linkopts bazel.StringListAttribute
Linkstatic bool
Use_libcrt bazel.BoolAttribute
+ Rtti bazel.BoolAttribute
Includes bazel.StringListAttribute
Hdrs bazel.LabelListAttribute
@@ -2340,6 +2346,8 @@
Conlyflags bazel.StringListAttribute
Srcs_as bazel.LabelListAttribute
Asflags bazel.StringListAttribute
+
+ Static staticOrSharedAttributes
}
type bazelCcLibraryStatic struct {
@@ -2365,16 +2373,33 @@
asFlags = bazel.MakeStringListAttribute(nil)
}
+ // Append static{} stanza properties. These won't be specified on
+ // cc_library_static itself, but may be specified in cc_defaults that this module
+ // depends on.
+ staticAttrs := bp2BuildParseStaticProps(ctx, module)
+
+ compilerAttrs.srcs.Append(staticAttrs.Srcs)
+ compilerAttrs.cSrcs.Append(staticAttrs.Srcs_c)
+ compilerAttrs.asSrcs.Append(staticAttrs.Srcs_as)
+ compilerAttrs.copts.Append(staticAttrs.Copts)
+ linkerAttrs.exportedDeps.Append(staticAttrs.Static_deps)
+ linkerAttrs.dynamicDeps.Append(staticAttrs.Dynamic_deps)
+ linkerAttrs.wholeArchiveDeps.Append(staticAttrs.Whole_archive_deps)
+ linkerAttrs.systemDynamicDeps.Append(staticAttrs.System_dynamic_deps)
+
attrs := &bazelCcLibraryStaticAttributes{
Copts: compilerAttrs.copts,
Srcs: compilerAttrs.srcs,
Implementation_deps: linkerAttrs.deps,
Deps: linkerAttrs.exportedDeps,
Whole_archive_deps: linkerAttrs.wholeArchiveDeps,
+ Dynamic_deps: linkerAttrs.dynamicDeps,
+ System_dynamic_deps: linkerAttrs.systemDynamicDeps,
Linkopts: linkerAttrs.linkopts,
Linkstatic: true,
Use_libcrt: linkerAttrs.useLibcrt,
+ Rtti: compilerAttrs.rtti,
Includes: exportedIncludes,
Cppflags: compilerAttrs.cppFlags,
diff --git a/cc/library_headers.go b/cc/library_headers.go
index d6b4529..e596ff7 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -108,6 +108,7 @@
Includes bazel.StringListAttribute
Deps bazel.LabelListAttribute
Implementation_deps bazel.LabelListAttribute
+ System_dynamic_deps bazel.LabelListAttribute
}
type bazelCcLibraryHeaders struct {
@@ -146,6 +147,7 @@
Includes: exportedIncludes,
Implementation_deps: linkerAttrs.deps,
Deps: linkerAttrs.exportedDeps,
+ System_dynamic_deps: linkerAttrs.systemDynamicDeps,
}
props := bazel.BazelTargetModuleProperties{
diff --git a/cc/testing.go b/cc/testing.go
index e8f3481..071f1ec 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -451,16 +451,6 @@
name: "note_memtag_heap_sync",
}
-
- cc_library {
- name: "libjemalloc5",
- host_supported: true,
- no_libcrt: true,
- nocrt: true,
- system_shared_libs: [],
- stl: "none",
- }
-
cc_library {
name: "libc_musl",
host_supported: true,
diff --git a/cc/tidy.go b/cc/tidy.go
index b2382e8..fefa7f0 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -146,6 +146,8 @@
tidyChecks = tidyChecks + ",-bugprone-signed-char-misuse"
// http://b/155034972
tidyChecks = tidyChecks + ",-bugprone-branch-clone"
+ // http://b/193716442
+ tidyChecks = tidyChecks + ",-bugprone-implicit-widening-of-multiplication-result"
flags.TidyFlags = append(flags.TidyFlags, tidyChecks)
if ctx.Config().IsEnvTrue("WITH_TIDY") {
diff --git a/cmd/extract_linker/main.go b/cmd/extract_linker/main.go
index f1f7bc7..1280553 100644
--- a/cmd/extract_linker/main.go
+++ b/cmd/extract_linker/main.go
@@ -26,7 +26,7 @@
"io/ioutil"
"log"
"os"
- "strings"
+ "strconv"
)
func main() {
@@ -59,20 +59,16 @@
fmt.Fprintln(script, "ENTRY(__dlwrap__start)")
fmt.Fprintln(script, "SECTIONS {")
+ progsWithFlagsCount := make(map[string]int)
+
for _, prog := range ef.Progs {
if prog.Type != elf.PT_LOAD {
continue
}
- var progName string
- progSection := progToFirstSection(prog, ef.Sections)
- if progSection != nil {
- progName = progSection.Name
- } else {
- progName = fmt.Sprintf(".sect%d", load)
- }
- sectionName := ".linker" + progName
- symName := "__dlwrap_linker" + strings.ReplaceAll(progName, ".", "_")
+ progName := progNameFromFlags(prog.Flags, progsWithFlagsCount)
+ sectionName := ".linker_" + progName
+ symName := "__dlwrap_linker_" + progName
flags := ""
if prog.Flags&elf.PF_W != 0 {
@@ -83,6 +79,12 @@
}
fmt.Fprintf(asm, ".section %s, \"a%s\"\n", sectionName, flags)
+ if load == 0 {
+ fmt.Fprintln(asm, ".globl __dlwrap_linker")
+ fmt.Fprintln(asm, "__dlwrap_linker:")
+ fmt.Fprintln(asm)
+ }
+
fmt.Fprintf(asm, ".globl %s\n%s:\n\n", symName, symName)
fmt.Fprintf(script, " %s 0x%x : {\n", sectionName, baseLoadAddr+prog.Vaddr)
@@ -106,6 +108,10 @@
load += 1
}
+ fmt.Fprintln(asm, ".globl __dlwrap_linker_end")
+ fmt.Fprintln(asm, "__dlwrap_linker_end:")
+ fmt.Fprintln(asm)
+
fmt.Fprintln(asm, `.section .note.android.embedded_linker,"a",%note`)
fmt.Fprintln(script, "}")
@@ -139,11 +145,25 @@
fmt.Fprintln(asm)
}
-func progToFirstSection(prog *elf.Prog, sections []*elf.Section) *elf.Section {
- for _, section := range sections {
- if section.Addr == prog.Vaddr {
- return section
- }
+func progNameFromFlags(flags elf.ProgFlag, progsWithFlagsCount map[string]int) string {
+ s := ""
+ if flags&elf.PF_R != 0 {
+ s += "r"
}
- return nil
+ if flags&elf.PF_W != 0 {
+ s += "w"
+ }
+ if flags&elf.PF_X != 0 {
+ s += "x"
+ }
+
+ count := progsWithFlagsCount[s]
+ count++
+ progsWithFlagsCount[s] = count
+
+ if count > 1 {
+ s += strconv.Itoa(count)
+ }
+
+ return s
}
diff --git a/cmd/multiproduct_kati/Android.bp b/cmd/multiproduct_kati/Android.bp
index 21d8e21..e5be6c0 100644
--- a/cmd/multiproduct_kati/Android.bp
+++ b/cmd/multiproduct_kati/Android.bp
@@ -19,8 +19,8 @@
blueprint_go_binary {
name: "multiproduct_kati",
deps: [
- "soong-ui-build",
"soong-ui-logger",
+ "soong-ui-signal",
"soong-ui-terminal",
"soong-ui-tracer",
"soong-zip",
diff --git a/cmd/multiproduct_kati/main.go b/cmd/multiproduct_kati/main.go
index 55a5470..2846387 100644
--- a/cmd/multiproduct_kati/main.go
+++ b/cmd/multiproduct_kati/main.go
@@ -15,22 +15,24 @@
package main
import (
+ "bufio"
"context"
"flag"
"fmt"
"io"
- "io/ioutil"
+ "log"
"os"
+ "os/exec"
"path/filepath"
+ "regexp"
"runtime"
"strings"
"sync"
"syscall"
"time"
- "android/soong/finder"
- "android/soong/ui/build"
"android/soong/ui/logger"
+ "android/soong/ui/signal"
"android/soong/ui/status"
"android/soong/ui/terminal"
"android/soong/ui/tracer"
@@ -74,36 +76,6 @@
return nil
}
-const errorLeadingLines = 20
-const errorTrailingLines = 20
-
-func errMsgFromLog(filename string) string {
- if filename == "" {
- return ""
- }
-
- data, err := ioutil.ReadFile(filename)
- if err != nil {
- return ""
- }
-
- lines := strings.Split(strings.TrimSpace(string(data)), "\n")
- if len(lines) > errorLeadingLines+errorTrailingLines+1 {
- lines[errorLeadingLines] = fmt.Sprintf("... skipping %d lines ...",
- len(lines)-errorLeadingLines-errorTrailingLines)
-
- lines = append(lines[:errorLeadingLines+1],
- lines[len(lines)-errorTrailingLines:]...)
- }
- var buf strings.Builder
- for _, line := range lines {
- buf.WriteString("> ")
- buf.WriteString(line)
- buf.WriteString("\n")
- }
- return buf.String()
-}
-
// TODO(b/70370883): This tool uses a lot of open files -- over the default
// soft limit of 1024 on some systems. So bump up to the hard limit until I fix
// the algorithm.
@@ -155,28 +127,59 @@
}
type mpContext struct {
- Context context.Context
- Logger logger.Logger
- Status status.ToolStatus
- Tracer tracer.Tracer
- Finder *finder.Finder
- Config build.Config
+ Logger logger.Logger
+ Status status.ToolStatus
- LogsDir string
+ SoongUi string
+ MainOutDir string
+ MainLogsDir string
+}
+
+func detectTotalRAM() uint64 {
+ var info syscall.Sysinfo_t
+ err := syscall.Sysinfo(&info)
+ if err != nil {
+ panic(err)
+ }
+ return info.Totalram * uint64(info.Unit)
+}
+
+func findNamedProducts(soongUi string, log logger.Logger) []string {
+ cmd := exec.Command(soongUi, "--dumpvars-mode", "--vars=all_named_products")
+ output, err := cmd.Output()
+ if err != nil {
+ log.Fatalf("Cannot determine named products: %v", err)
+ }
+
+ rx := regexp.MustCompile(`^all_named_products='(.*)'$`)
+ match := rx.FindStringSubmatch(strings.TrimSpace(string(output)))
+ return strings.Fields(match[1])
+}
+
+// ensureEmptyFileExists ensures that the containing directory exists, and the
+// specified file exists. If it doesn't exist, it will write an empty file.
+func ensureEmptyFileExists(file string, log logger.Logger) {
+ if _, err := os.Stat(file); os.IsNotExist(err) {
+ f, err := os.Create(file)
+ if err != nil {
+ log.Fatalf("Error creating %s: %q\n", file, err)
+ }
+ f.Close()
+ } else if err != nil {
+ log.Fatalf("Error checking %s: %q\n", file, err)
+ }
}
func main() {
stdio := terminal.StdioImpl{}
- output := terminal.NewStatusOutput(stdio.Stdout(), "", false,
- build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD"))
-
+ output := terminal.NewStatusOutput(stdio.Stdout(), "", false, false)
log := logger.New(output)
defer log.Cleanup()
flag.Parse()
- ctx, cancel := context.WithCancel(context.Background())
+ _, cancel := context.WithCancel(context.Background())
defer cancel()
trace := tracer.New(log)
@@ -189,61 +192,59 @@
var failures failureCount
stat.AddOutput(&failures)
- build.SetupSignals(log, cancel, func() {
+ signal.SetupSignals(log, cancel, func() {
trace.Close()
log.Cleanup()
stat.Finish()
})
- buildCtx := build.Context{ContextImpl: &build.ContextImpl{
- Context: ctx,
- Logger: log,
- Tracer: trace,
- Writer: output,
- Status: stat,
- }}
+ soongUi := "build/soong/soong_ui.bash"
- args := ""
- if *alternateResultDir {
- args = "dist"
- }
- config := build.NewConfig(buildCtx, args)
- if *outDir == "" {
+ var outputDir string
+ if *outDir != "" {
+ outputDir = *outDir
+ } else {
name := "multiproduct"
if !*incremental {
name += "-" + time.Now().Format("20060102150405")
}
- *outDir = filepath.Join(config.OutDir(), name)
-
- // Ensure the empty files exist in the output directory
- // containing our output directory too. This is mostly for
- // safety, but also triggers the ninja_build file so that our
- // build servers know that they can parse the output as if it
- // was ninja output.
- build.SetupOutDir(buildCtx, config)
-
- if err := os.MkdirAll(*outDir, 0777); err != nil {
- log.Fatalf("Failed to create tempdir: %v", err)
+ outDirBase := os.Getenv("OUT_DIR")
+ if outDirBase == "" {
+ outDirBase = "out"
}
- }
- config.Environment().Set("OUT_DIR", *outDir)
- log.Println("Output directory:", *outDir)
- logsDir := filepath.Join(config.OutDir(), "logs")
+ outputDir = filepath.Join(outDirBase, name)
+ }
+
+ log.Println("Output directory:", outputDir)
+
+ // The ninja_build file is used by our buildbots to understand that the output
+ // can be parsed as ninja output.
+ if err := os.MkdirAll(outputDir, 0777); err != nil {
+ log.Fatalf("Failed to create output directory: %v", err)
+ }
+ ensureEmptyFileExists(filepath.Join(outputDir, "ninja_build"), log)
+
+ logsDir := filepath.Join(outputDir, "logs")
os.MkdirAll(logsDir, 0777)
- build.SetupOutDir(buildCtx, config)
+ var configLogsDir string
+ if *alternateResultDir {
+ configLogsDir = filepath.Join(outputDir, "dist/logs")
+ } else {
+ configLogsDir = outputDir
+ }
- os.MkdirAll(config.LogsDir(), 0777)
- log.SetOutput(filepath.Join(config.LogsDir(), "soong.log"))
- trace.SetOutput(filepath.Join(config.LogsDir(), "build.trace"))
+ os.MkdirAll(configLogsDir, 0777)
+ log.SetOutput(filepath.Join(configLogsDir, "soong.log"))
+ trace.SetOutput(filepath.Join(configLogsDir, "build.trace"))
var jobs = *numJobs
if jobs < 1 {
jobs = runtime.NumCPU() / 4
- ramGb := int(config.TotalRAM() / 1024 / 1024 / 1024)
+ ramGb := int(detectTotalRAM() / (1024 * 1024 * 1024))
if ramJobs := ramGb / 25; ramGb > 0 && jobs > ramJobs {
jobs = ramJobs
}
@@ -256,17 +257,8 @@
setMaxFiles(log)
- finder := build.NewSourceFinder(buildCtx, config)
- defer finder.Shutdown()
-
- build.FindSources(buildCtx, config, finder)
-
- vars, err := build.DumpMakeVars(buildCtx, config, nil, []string{"all_named_products"})
- if err != nil {
- log.Fatal(err)
- }
+ allProducts := findNamedProducts(soongUi, log)
var productsList []string
- allProducts := strings.Fields(vars["all_named_products"])
if len(includeProducts) > 0 {
var missingProducts []string
@@ -314,19 +306,15 @@
log.Verbose("Got product list: ", finalProductsList)
- s := buildCtx.Status.StartTool()
+ s := stat.StartTool()
s.SetTotalActions(len(finalProductsList))
mpCtx := &mpContext{
- Context: ctx,
- Logger: log,
- Status: s,
- Tracer: trace,
-
- Finder: finder,
- Config: config,
-
- LogsDir: logsDir,
+ Logger: log,
+ Status: s,
+ SoongUi: soongUi,
+ MainOutDir: outputDir,
+ MainLogsDir: logsDir,
}
products := make(chan string, len(productsList))
@@ -348,7 +336,7 @@
if product == "" {
return
}
- buildProduct(mpCtx, product)
+ runSoongUiForProduct(mpCtx, product)
}
}
}()
@@ -360,7 +348,7 @@
FileArgs: []zip.FileArg{
{GlobDir: logsDir, SourcePrefixToStrip: logsDir},
},
- OutputFilePath: filepath.Join(config.RealDistDir(), "logs.zip"),
+ OutputFilePath: filepath.Join(outputDir, "dist/logs.zip"),
NumParallelJobs: runtime.NumCPU(),
CompressionLevel: 5,
}
@@ -380,11 +368,33 @@
}
}
-func buildProduct(mpctx *mpContext, product string) {
- var stdLog string
+func cleanupAfterProduct(outDir, productZip string) {
+ if *keepArtifacts {
+ args := zip.ZipArgs{
+ FileArgs: []zip.FileArg{
+ {
+ GlobDir: outDir,
+ SourcePrefixToStrip: outDir,
+ },
+ },
+ OutputFilePath: productZip,
+ NumParallelJobs: runtime.NumCPU(),
+ CompressionLevel: 5,
+ }
+ if err := zip.Zip(args); err != nil {
+ log.Fatalf("Error zipping artifacts: %v", err)
+ }
+ }
+ if !*incremental {
+ os.RemoveAll(outDir)
+ }
+}
- outDir := filepath.Join(mpctx.Config.OutDir(), product)
- logsDir := filepath.Join(mpctx.LogsDir, product)
+func runSoongUiForProduct(mpctx *mpContext, product string) {
+ outDir := filepath.Join(mpctx.MainOutDir, product)
+ logsDir := filepath.Join(mpctx.MainLogsDir, product)
+ productZip := filepath.Join(mpctx.MainOutDir, product+".zip")
+ consoleLogPath := filepath.Join(logsDir, "std.log")
if err := os.MkdirAll(outDir, 0777); err != nil {
mpctx.Logger.Fatalf("Error creating out directory: %v", err)
@@ -393,98 +403,65 @@
mpctx.Logger.Fatalf("Error creating log directory: %v", err)
}
- stdLog = filepath.Join(logsDir, "std.log")
- f, err := os.Create(stdLog)
+ consoleLogFile, err := os.Create(consoleLogPath)
if err != nil {
- mpctx.Logger.Fatalf("Error creating std.log: %v", err)
+ mpctx.Logger.Fatalf("Error creating console log file: %v", err)
}
- defer f.Close()
+ defer consoleLogFile.Close()
- log := logger.New(f)
- defer log.Cleanup()
- log.SetOutput(filepath.Join(logsDir, "soong.log"))
+ consoleLogWriter := bufio.NewWriter(consoleLogFile)
+ defer consoleLogWriter.Flush()
+
+ args := []string{"--make-mode", "--skip-soong-tests", "--skip-ninja"}
+
+ if !*keepArtifacts {
+ args = append(args, "--empty-ninja-file")
+ }
+
+ if *onlyConfig {
+ args = append(args, "--config-only")
+ } else if *onlySoong {
+ args = append(args, "--soong-only")
+ }
+
+ if *alternateResultDir {
+ args = append(args, "dist")
+ }
+
+ cmd := exec.Command(mpctx.SoongUi, args...)
+ cmd.Stdout = consoleLogWriter
+ cmd.Stderr = consoleLogWriter
+ cmd.Env = append(os.Environ(),
+ "OUT_DIR="+outDir,
+ "TARGET_PRODUCT="+product,
+ "TARGET_BUILD_VARIANT="+*buildVariant,
+ "TARGET_BUILD_TYPE=release",
+ "TARGET_BUILD_APPS=",
+ "TARGET_BUILD_UNBUNDLED=")
action := &status.Action{
Description: product,
Outputs: []string{product},
}
+
mpctx.Status.StartAction(action)
- defer logger.Recover(func(err error) {
- mpctx.Status.FinishAction(status.ActionResult{
- Action: action,
- Error: err,
- Output: errMsgFromLog(stdLog),
- })
- })
-
- ctx := build.Context{ContextImpl: &build.ContextImpl{
- Context: mpctx.Context,
- Logger: log,
- Tracer: mpctx.Tracer,
- Writer: f,
- Thread: mpctx.Tracer.NewThread(product),
- Status: &status.Status{},
- }}
- ctx.Status.AddOutput(terminal.NewStatusOutput(ctx.Writer, "", false,
- build.OsEnvironment().IsEnvTrue("ANDROID_QUIET_BUILD")))
-
- args := append([]string(nil), flag.Args()...)
- args = append(args, "--skip-soong-tests")
- config := build.NewConfig(ctx, args...)
- config.Environment().Set("OUT_DIR", outDir)
- if !*keepArtifacts {
- config.SetEmptyNinjaFile(true)
- }
- build.FindSources(ctx, config, mpctx.Finder)
- config.Lunch(ctx, product, *buildVariant)
-
- defer func() {
- if *keepArtifacts {
- args := zip.ZipArgs{
- FileArgs: []zip.FileArg{
- {
- GlobDir: outDir,
- SourcePrefixToStrip: outDir,
- },
- },
- OutputFilePath: filepath.Join(mpctx.Config.OutDir(), product+".zip"),
- NumParallelJobs: runtime.NumCPU(),
- CompressionLevel: 5,
- }
- if err := zip.Zip(args); err != nil {
- log.Fatalf("Error zipping artifacts: %v", err)
- }
- }
- if !*incremental {
- os.RemoveAll(outDir)
- }
- }()
-
- config.SetSkipNinja(true)
-
- buildWhat := build.RunProductConfig
- if !*onlyConfig {
- buildWhat |= build.RunSoong
- if !*onlySoong {
- buildWhat |= build.RunKati
- }
- }
+ defer cleanupAfterProduct(outDir, productZip)
before := time.Now()
- build.Build(ctx, config)
+ err = cmd.Run()
- // Save std_full.log if Kati re-read the makefiles
- if buildWhat&build.RunKati != 0 {
- if after, err := os.Stat(config.KatiBuildNinjaFile()); err == nil && after.ModTime().After(before) {
- err := copyFile(stdLog, filepath.Join(filepath.Dir(stdLog), "std_full.log"))
+ if !*onlyConfig && !*onlySoong {
+ katiBuildNinjaFile := filepath.Join(outDir, "build-"+product+".ninja")
+ if after, err := os.Stat(katiBuildNinjaFile); err == nil && after.ModTime().After(before) {
+ err := copyFile(consoleLogPath, filepath.Join(filepath.Dir(consoleLogPath), "std_full.log"))
if err != nil {
log.Fatalf("Error copying log file: %s", err)
}
}
}
-
mpctx.Status.FinishAction(status.ActionResult{
Action: action,
+ Error: err,
})
}
diff --git a/cmd/soong_ui/Android.bp b/cmd/soong_ui/Android.bp
index 4f5eea9..9f10b82 100644
--- a/cmd/soong_ui/Android.bp
+++ b/cmd/soong_ui/Android.bp
@@ -20,6 +20,7 @@
name: "soong_ui",
deps: [
"soong-ui-build",
+ "soong-ui-signal",
"soong-ui-logger",
"soong-ui-terminal",
"soong-ui-tracer",
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 02c5229..d709787 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -30,6 +30,7 @@
"android/soong/ui/build"
"android/soong/ui/logger"
"android/soong/ui/metrics"
+ "android/soong/ui/signal"
"android/soong/ui/status"
"android/soong/ui/terminal"
"android/soong/ui/tracer"
@@ -190,7 +191,7 @@
stat.AddOutput(trace.StatusTracer())
// Set up a cleanup procedure in case the normal termination process doesn't work.
- build.SetupSignals(log, cancel, func() {
+ signal.SetupSignals(log, cancel, func() {
trace.Close()
log.Cleanup()
stat.Finish()
diff --git a/cuj/Android.bp b/cuj/Android.bp
index a2da6e6..f9cfdc1 100644
--- a/cuj/Android.bp
+++ b/cuj/Android.bp
@@ -7,6 +7,7 @@
deps: [
"soong-ui-build",
"soong-ui-logger",
+ "soong-ui-signal",
"soong-ui-terminal",
"soong-ui-tracer",
],
diff --git a/cuj/cuj.go b/cuj/cuj.go
index b4ae9a2..413f423 100644
--- a/cuj/cuj.go
+++ b/cuj/cuj.go
@@ -27,6 +27,7 @@
"android/soong/ui/build"
"android/soong/ui/logger"
"android/soong/ui/metrics"
+ "android/soong/ui/signal"
"android/soong/ui/status"
"android/soong/ui/terminal"
"android/soong/ui/tracer"
@@ -65,7 +66,7 @@
stat.AddOutput(output)
stat.AddOutput(trace.StatusTracer())
- build.SetupSignals(log, cancel, func() {
+ signal.SetupSignals(log, cancel, func() {
trace.Close()
log.Cleanup()
stat.Finish()
diff --git a/dexpreopt/testing.go b/dexpreopt/testing.go
index 2f99655..8f5c315 100644
--- a/dexpreopt/testing.go
+++ b/dexpreopt/testing.go
@@ -125,6 +125,20 @@
})
}
+// FixtureSetSystemServerJars sets the SystemServerJars property.
+func FixtureSetSystemServerJars(jars ...string) android.FixturePreparer {
+ return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
+ dexpreoptConfig.SystemServerJars = android.CreateTestConfiguredJarList(jars)
+ })
+}
+
+// FixtureSetApexSystemServerJars sets the ApexSystemServerJars property in the global config.
+func FixtureSetApexSystemServerJars(jars ...string) android.FixturePreparer {
+ return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
+ dexpreoptConfig.ApexSystemServerJars = android.CreateTestConfiguredJarList(jars)
+ })
+}
+
// FixtureSetPreoptWithUpdatableBcp sets the PreoptWithUpdatableBcp property in the global config.
func FixtureSetPreoptWithUpdatableBcp(value bool) android.FixturePreparer {
return FixtureModifyGlobalConfig(func(dexpreoptConfig *GlobalConfig) {
diff --git a/java/app_import.go b/java/app_import.go
index 5a87b07..b5a6084 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -410,6 +410,10 @@
return android.SdkSpecPrivate
}
+func (a *AndroidAppImport) LintDepSets() LintDepSets {
+ return LintDepSets{}
+}
+
var _ android.ApexModule = (*AndroidAppImport)(nil)
// Implements android.ApexModule
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index 3d0e155..d3de675 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -164,6 +164,7 @@
prepareForTestWithBootclasspathFragment,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("mysdklibrary", "mycoveragestubs"),
+ FixtureConfigureApexBootJars("someapex:mybootlib"),
prepareWithBp,
)
@@ -186,6 +187,7 @@
prepareForTestWithBootclasspathFragment,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary", "mycoreplatform"),
+ FixtureConfigureApexBootJars("someapex:mysdklibrary"),
).RunTestWithBp(t, `
bootclasspath_fragment {
name: "myfragment",
diff --git a/rust/project_json.go b/rust/project_json.go
index c28bc7b..faa7db5 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -54,7 +54,6 @@
}
type rustProjectJson struct {
- Roots []string `json:"roots"`
Crates []rustProjectCrate `json:"crates"`
}
@@ -248,9 +247,6 @@
idx := len(singleton.project.Crates)
singleton.knownCrates[rModule.Name()] = crateInfo{Idx: idx, Deps: deps}
singleton.project.Crates = append(singleton.project.Crates, crate)
- // rust-analyzer requires that all crates belong to at least one root:
- // https://github.com/rust-analyzer/rust-analyzer/issues/4735.
- singleton.project.Roots = append(singleton.project.Roots, path.Dir(crate.RootModule))
return idx, true
}
diff --git a/scripts/get_clang_version.py b/scripts/get_clang_version.py
index 622fca1..f6efc5f 100755
--- a/scripts/get_clang_version.py
+++ b/scripts/get_clang_version.py
@@ -30,7 +30,7 @@
with open(global_go) as infile:
contents = infile.read()
- regex_rev = r'\tClangDefaultVersion\s+= "clang-(?P<rev>r\d+[a-z]?\d?)"'
+ regex_rev = r'\tClangDefaultVersion\s+= "(?P<rev>clang-r\d+[a-z]?\d?)"'
match_rev = re.search(regex_rev, contents)
if match_rev is None:
raise RuntimeError('Parsing clang info failed')
diff --git a/scripts/hiddenapi/signature_patterns.py b/scripts/hiddenapi/signature_patterns.py
index 91328e6..a7c5bb4 100755
--- a/scripts/hiddenapi/signature_patterns.py
+++ b/scripts/hiddenapi/signature_patterns.py
@@ -30,11 +30,21 @@
return produce_patterns_from_stream(f)
def produce_patterns_from_stream(stream):
- patterns = []
- allFlagsReader = dict_reader(stream)
- for row in allFlagsReader:
+ # Read in all the signatures into a list and remove member names.
+ patterns = set()
+ for row in dict_reader(stream):
signature = row['signature']
- patterns.append(signature)
+ text = signature.removeprefix("L")
+ # Remove the class specific member signature
+ pieces = text.split(";->")
+ qualifiedClassName = pieces[0]
+ # Remove inner class names as they cannot be separated from the containing outer class.
+ pieces = qualifiedClassName.split("$", maxsplit=1)
+ pattern = pieces[0]
+ patterns.add(pattern)
+
+ patterns = list(patterns)
+ patterns.sort()
return patterns
def main(args):
diff --git a/scripts/hiddenapi/signature_patterns_test.py b/scripts/hiddenapi/signature_patterns_test.py
index 83c9db2..0431f45 100755
--- a/scripts/hiddenapi/signature_patterns_test.py
+++ b/scripts/hiddenapi/signature_patterns_test.py
@@ -28,12 +28,15 @@
def test_generate(self):
patterns = self.produce_patterns_from_string('''
+Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V,blocked
+Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;,public-api
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
Ljava/lang/Object;->toString()Ljava/lang/String;,blocked
''')
expected = [
- "Ljava/lang/Object;->hashCode()I",
- "Ljava/lang/Object;->toString()Ljava/lang/String;",
+ "java/lang/Character",
+ "java/lang/Object",
+ "java/lang/ProcessBuilder",
]
self.assertEqual(expected, patterns)
diff --git a/scripts/hiddenapi/verify_overlaps.py b/scripts/hiddenapi/verify_overlaps.py
index 8579321..a4a423e 100755
--- a/scripts/hiddenapi/verify_overlaps.py
+++ b/scripts/hiddenapi/verify_overlaps.py
@@ -19,12 +19,244 @@
import argparse
import csv
+import sys
from itertools import chain
+class InteriorNode:
+ """
+ An interior node in a trie.
+
+ Each interior node has a dict that maps from an element of a signature to
+ either another interior node or a leaf. Each interior node represents either
+ a package, class or nested class. Class members are represented by a Leaf.
+
+ Associating the set of flags [public-api] with the signature
+ "Ljava/lang/Object;->String()Ljava/lang/String;" will cause the following
+ nodes to be created:
+ Node()
+ ^- package:java -> Node()
+ ^- package:lang -> Node()
+ ^- class:Object -> Node()
+ ^- member:String()Ljava/lang/String; -> Leaf([public-api])
+
+ Associating the set of flags [blocked,core-platform-api] with the signature
+ "Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;"
+ will cause the following nodes to be created:
+ Node()
+ ^- package:java -> Node()
+ ^- package:lang -> Node()
+ ^- class:Character -> Node()
+ ^- class:UnicodeScript -> Node()
+ ^- member:of(I)Ljava/lang/Character$UnicodeScript;
+ -> Leaf([blocked,core-platform-api])
+
+ Attributes:
+ nodes: a dict from an element of the signature to the Node/Leaf
+ containing the next element/value.
+ """
+ def __init__(self):
+ self.nodes = {}
+
+ def signatureToElements(self, signature):
+ """
+ Split a signature or a prefix into a number of elements:
+ 1. The packages (excluding the leading L preceding the first package).
+ 2. The class names, from outermost to innermost.
+ 3. The member signature.
+
+ e.g. Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;
+ will be broken down into these elements:
+ 1. package:java
+ 2. package:lang
+ 3. class:Character
+ 4. class:UnicodeScript
+ 5. member:of(I)Ljava/lang/Character$UnicodeScript;
+ """
+ # Remove the leading L.
+ # - java/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;
+ text = signature.removeprefix("L")
+ # Split the signature between qualified class name and the class member
+ # signature.
+ # 0 - java/lang/Character$UnicodeScript
+ # 1 - of(I)Ljava/lang/Character$UnicodeScript;
+ parts = text.split(";->")
+ member = parts[1:]
+ # Split the qualified class name into packages, and class name.
+ # 0 - java
+ # 1 - lang
+ # 2 - Character$UnicodeScript
+ elements = parts[0].split("/")
+ packages = elements[0:-1]
+ className = elements[-1]
+ if className == "*" or className == "**":
+ # Cannot specify a wildcard and target a specific member
+ if len(member) != 0:
+ raise Exception("Invalid signature %s: contains wildcard %s and member signature %s"
+ % (signature, className, member[0]))
+ wildcard = [className]
+ # Assemble the parts into a single list, adding prefixes to identify
+ # the different parts.
+ # 0 - package:java
+ # 1 - package:lang
+ # 2 - *
+ return list(chain(map(lambda x : "package:" + x, packages),
+ wildcard))
+ else:
+ # Split the class name into outer / inner classes
+ # 0 - Character
+ # 1 - UnicodeScript
+ classes = className.split("$")
+ # Assemble the parts into a single list, adding prefixes to identify
+ # the different parts.
+ # 0 - package:java
+ # 1 - package:lang
+ # 2 - class:Character
+ # 3 - class:UnicodeScript
+ # 4 - member:of(I)Ljava/lang/Character$UnicodeScript;
+ return list(chain(map(lambda x : "package:" + x, packages),
+ map(lambda x : "class:" + x, classes),
+ map(lambda x : "member:" + x, member)))
+
+ def add(self, signature, value):
+ """
+ Associate the value with the specific signature.
+ :param signature: the member signature
+ :param value: the value to associated with the signature
+ :return: n/a
+ """
+ # Split the signature into elements.
+ elements = self.signatureToElements(signature)
+ # Find the Node associated with the deepest class.
+ node = self
+ for element in elements[:-1]:
+ if element in node.nodes:
+ node = node.nodes[element]
+ else:
+ next = InteriorNode()
+ node.nodes[element] = next
+ node = next
+ # Add a Leaf containing the value and associate it with the member
+ # signature within the class.
+ lastElement = elements[-1]
+ if not lastElement.startswith("member:"):
+ raise Exception("Invalid signature: %s, does not identify a specific member" % signature)
+ if lastElement in node.nodes:
+ raise Exception("Duplicate signature: %s" % signature)
+ node.nodes[lastElement] = Leaf(value)
+
+ def getMatchingRows(self, pattern):
+ """
+ Get the values (plural) associated with the pattern.
+
+ e.g. If the pattern is a full signature then this will return a list
+ containing the value associated with that signature.
+
+ If the pattern is a class then this will return a list containing the
+ values associated with all members of that class.
+
+ If the pattern is a package then this will return a list containing the
+ values associated with all the members of all the classes in that
+ package and sub-packages.
+
+ If the pattern ends with "*" then the preceding part is treated as a
+ package and this will return a list containing the values associated
+ with all the members of all the classes in that package.
+
+ If the pattern ends with "**" then the preceding part is treated
+ as a package and this will return a list containing the values
+ associated with all the members of all the classes in that package and
+ all sub-packages.
+
+ :param pattern: the pattern which could be a complete signature or a
+ class, or package wildcard.
+ :return: an iterable containing all the values associated with the
+ pattern.
+ """
+ elements = self.signatureToElements(pattern)
+ node = self
+ # Include all values from this node and all its children.
+ selector = lambda x : True
+ lastElement = elements[-1]
+ if lastElement == "*" or lastElement == "**":
+ elements = elements[:-1]
+ if lastElement == "*":
+ # Do not include values from sub-packages.
+ selector = lambda x : not x.startswith("package:")
+ for element in elements:
+ if element in node.nodes:
+ node = node.nodes[element]
+ else:
+ return []
+ return chain.from_iterable(node.values(selector))
+
+ def values(self, selector):
+ """
+ :param selector: a function that can be applied to a key in the nodes
+ attribute to determine whether to return its values.
+ :return: A list of iterables of all the values associated with this
+ node and its children.
+ """
+ values = []
+ self.appendValues(values, selector)
+ return values
+
+ def appendValues(self, values, selector):
+ """
+ Append the values associated with this node and its children to the
+ list.
+
+ For each item (key, child) in nodes the child node's values are returned
+ if and only if the selector returns True when called on its key. A child
+ node's values are all the values associated with it and all its
+ descendant nodes.
+
+ :param selector: a function that can be applied to a key in the nodes
+ attribute to determine whether to return its values.
+ :param values: a list of a iterables of values.
+ """
+ for key, node in self.nodes.items():
+ if selector(key):
+ node.appendValues(values, lambda x : True)
+
+class Leaf:
+ """
+ A leaf of the trie
+
+ Attributes:
+ value: the value associated with this leaf.
+ """
+ def __init__(self, value):
+ self.value = value
+
+ def values(self, selector):
+ """
+ :return: A list of a list of the value associated with this node.
+ """
+ return [[self.value]]
+
+ def appendValues(self, values, selector):
+ """
+ Appends a list of the value associated with this node to the list.
+ :param values: a list of a iterables of values.
+ """
+ values.append([self.value])
+
def dict_reader(input):
return csv.DictReader(input, delimiter=',', quotechar='|', fieldnames=['signature'])
-def extract_subset_from_monolithic_flags_as_dict_from_file(monolithicFlagsDict, patternsFile):
+def read_flag_trie_from_file(file):
+ with open(file, 'r') as stream:
+ return read_flag_trie_from_stream(stream)
+
+def read_flag_trie_from_stream(stream):
+ trie = InteriorNode()
+ reader = dict_reader(stream)
+ for row in reader:
+ signature = row['signature']
+ trie.add(signature, row)
+ return trie
+
+def extract_subset_from_monolithic_flags_as_dict_from_file(monolithicTrie, patternsFile):
"""
Extract a subset of flags from the dict containing all the monolithic flags.
@@ -34,21 +266,24 @@
:return: the dict from signature to row.
"""
with open(patternsFile, 'r') as stream:
- return extract_subset_from_monolithic_flags_as_dict_from_stream(monolithicFlagsDict, stream)
+ return extract_subset_from_monolithic_flags_as_dict_from_stream(monolithicTrie, stream)
-def extract_subset_from_monolithic_flags_as_dict_from_stream(monolithicFlagsDict, stream):
+def extract_subset_from_monolithic_flags_as_dict_from_stream(monolithicTrie, stream):
"""
- Extract a subset of flags from the dict containing all the monolithic flags.
+ Extract a subset of flags from the trie containing all the monolithic flags.
- :param monolithicFlagsDict: the dict containing all the monolithic flags.
+ :param monolithicTrie: the trie containing all the monolithic flags.
:param stream: a stream containing a list of signature patterns that define
the subset.
:return: the dict from signature to row.
"""
dict = {}
- for signature in stream:
- signature = signature.rstrip()
- dict[signature] = monolithicFlagsDict.get(signature, {})
+ for pattern in stream:
+ pattern = pattern.rstrip()
+ rows = monolithicTrie.getMatchingRows(pattern)
+ for row in rows:
+ signature = row['signature']
+ dict[signature] = row
return dict
def read_signature_csv_from_stream_as_dict(stream):
@@ -108,20 +343,20 @@
args_parser.add_argument('modularFlags', nargs=argparse.REMAINDER, help='Flags produced by individual bootclasspath_fragment modules')
args = args_parser.parse_args(argv[1:])
- # Read in the monolithic flags into a dict indexed by signature
+ # Read in all the flags into the trie
monolithicFlagsPath = args.monolithicFlags
- monolithicFlagsDict = read_signature_csv_from_file_as_dict(monolithicFlagsPath)
+ monolithicTrie = read_flag_trie_from_file(monolithicFlagsPath)
# For each subset specified on the command line, create dicts for the flags
- # provided by the subset and the corresponding flags from the complete set of
- # flags and compare them.
+ # provided by the subset and the corresponding flags from the complete set
+ # of flags and compare them.
failed = False
for modularPair in args.modularFlags:
parts = modularPair.split(":")
modularFlagsPath = parts[0]
modularPatternsPath = parts[1]
modularFlagsDict = read_signature_csv_from_file_as_dict(modularFlagsPath)
- monolithicFlagsSubsetDict = extract_subset_from_monolithic_flags_as_dict_from_file(monolithicFlagsDict, modularPatternsPath)
+ monolithicFlagsSubsetDict = extract_subset_from_monolithic_flags_as_dict_from_file(monolithicTrie, modularPatternsPath)
mismatchingSignatures = compare_signature_flags(monolithicFlagsSubsetDict, modularFlagsDict)
if mismatchingSignatures:
failed = True
diff --git a/scripts/hiddenapi/verify_overlaps_test.py b/scripts/hiddenapi/verify_overlaps_test.py
index b6d5fa3..7477254 100755
--- a/scripts/hiddenapi/verify_overlaps_test.py
+++ b/scripts/hiddenapi/verify_overlaps_test.py
@@ -20,8 +20,52 @@
from verify_overlaps import *
+class TestSignatureToElements(unittest.TestCase):
+
+ def signatureToElements(self, signature):
+ return InteriorNode().signatureToElements(signature)
+
+ def test_signatureToElements_1(self):
+ expected = [
+ 'package:java',
+ 'package:lang',
+ 'class:ProcessBuilder',
+ 'class:Redirect',
+ 'class:1',
+ 'member:<init>()V',
+ ]
+ self.assertEqual(expected, self.signatureToElements(
+ "Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V"))
+
+ def test_signatureToElements_2(self):
+ expected = [
+ 'package:java',
+ 'package:lang',
+ 'class:Object',
+ 'member:hashCode()I',
+ ]
+ self.assertEqual(expected, self.signatureToElements(
+ "Ljava/lang/Object;->hashCode()I"))
+
+ def test_signatureToElements_3(self):
+ expected = [
+ 'package:java',
+ 'package:lang',
+ 'class:CharSequence',
+ 'class:',
+ 'class:ExternalSyntheticLambda0',
+ 'member:<init>(Ljava/lang/CharSequence;)V',
+ ]
+ self.assertEqual(expected, self.signatureToElements(
+ "Ljava/lang/CharSequence$$ExternalSyntheticLambda0;"
+ "-><init>(Ljava/lang/CharSequence;)V"))
+
class TestDetectOverlaps(unittest.TestCase):
+ def read_flag_trie_from_string(self, csv):
+ with io.StringIO(csv) as f:
+ return read_flag_trie_from_stream(f)
+
def read_signature_csv_from_string_as_dict(self, csv):
with io.StringIO(csv) as f:
return read_signature_csv_from_stream_as_dict(f)
@@ -33,13 +77,14 @@
extractInput = '''
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
Ljava/lang/Object;->toString()Ljava/lang/String;,blocked
+Ljava/util/zip/ZipFile;-><clinit>()V,blocked
+Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;,blocked
+Ljava/lang/Character;->serialVersionUID:J,sdk
+Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V,blocked
'''
- def test_extract_subset(self):
- monolithic = self.read_signature_csv_from_string_as_dict(TestDetectOverlaps.extractInput)
- modular = self.read_signature_csv_from_string_as_dict('''
-Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
-''')
+ def test_extract_subset_signature(self):
+ monolithic = self.read_flag_trie_from_string(TestDetectOverlaps.extractInput)
patterns = 'Ljava/lang/Object;->hashCode()I'
@@ -52,6 +97,144 @@
}
self.assertEqual(expected, subset)
+ def test_extract_subset_class(self):
+ monolithic = self.read_flag_trie_from_string(TestDetectOverlaps.extractInput)
+
+ patterns = 'java/lang/Object'
+
+ subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(monolithic, patterns)
+ expected = {
+ 'Ljava/lang/Object;->hashCode()I': {
+ None: ['public-api', 'system-api', 'test-api'],
+ 'signature': 'Ljava/lang/Object;->hashCode()I',
+ },
+ 'Ljava/lang/Object;->toString()Ljava/lang/String;': {
+ None: ['blocked'],
+ 'signature': 'Ljava/lang/Object;->toString()Ljava/lang/String;',
+ },
+ }
+ self.assertEqual(expected, subset)
+
+ def test_extract_subset_outer_class(self):
+ monolithic = self.read_flag_trie_from_string(TestDetectOverlaps.extractInput)
+
+ patterns = 'java/lang/Character'
+
+ subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(monolithic, patterns)
+ expected = {
+ 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;': {
+ None: ['blocked'],
+ 'signature': 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;',
+ },
+ 'Ljava/lang/Character;->serialVersionUID:J': {
+ None: ['sdk'],
+ 'signature': 'Ljava/lang/Character;->serialVersionUID:J',
+ },
+ }
+ self.assertEqual(expected, subset)
+
+ def test_extract_subset_nested_class(self):
+ monolithic = self.read_flag_trie_from_string(TestDetectOverlaps.extractInput)
+
+ patterns = 'java/lang/Character$UnicodeScript'
+
+ subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(monolithic, patterns)
+ expected = {
+ 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;': {
+ None: ['blocked'],
+ 'signature': 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;',
+ },
+ }
+ self.assertEqual(expected, subset)
+
+ def test_extract_subset_package(self):
+ monolithic = self.read_flag_trie_from_string(TestDetectOverlaps.extractInput)
+
+ patterns = 'java/lang/*'
+
+ subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(monolithic, patterns)
+ expected = {
+ 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;': {
+ None: ['blocked'],
+ 'signature': 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;',
+ },
+ 'Ljava/lang/Character;->serialVersionUID:J': {
+ None: ['sdk'],
+ 'signature': 'Ljava/lang/Character;->serialVersionUID:J',
+ },
+ 'Ljava/lang/Object;->hashCode()I': {
+ None: ['public-api', 'system-api', 'test-api'],
+ 'signature': 'Ljava/lang/Object;->hashCode()I',
+ },
+ 'Ljava/lang/Object;->toString()Ljava/lang/String;': {
+ None: ['blocked'],
+ 'signature': 'Ljava/lang/Object;->toString()Ljava/lang/String;',
+ },
+ 'Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V': {
+ None: ['blocked'],
+ 'signature': 'Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V',
+ },
+ }
+ self.assertEqual(expected, subset)
+
+ def test_extract_subset_recursive_package(self):
+ monolithic = self.read_flag_trie_from_string(TestDetectOverlaps.extractInput)
+
+ patterns = 'java/**'
+
+ subset = self.extract_subset_from_monolithic_flags_as_dict_from_string(monolithic, patterns)
+ expected = {
+ 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;': {
+ None: ['blocked'],
+ 'signature': 'Ljava/lang/Character$UnicodeScript;->of(I)Ljava/lang/Character$UnicodeScript;',
+ },
+ 'Ljava/lang/Character;->serialVersionUID:J': {
+ None: ['sdk'],
+ 'signature': 'Ljava/lang/Character;->serialVersionUID:J',
+ },
+ 'Ljava/lang/Object;->hashCode()I': {
+ None: ['public-api', 'system-api', 'test-api'],
+ 'signature': 'Ljava/lang/Object;->hashCode()I',
+ },
+ 'Ljava/lang/Object;->toString()Ljava/lang/String;': {
+ None: ['blocked'],
+ 'signature': 'Ljava/lang/Object;->toString()Ljava/lang/String;',
+ },
+ 'Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V': {
+ None: ['blocked'],
+ 'signature': 'Ljava/lang/ProcessBuilder$Redirect$1;-><init>()V',
+ },
+ 'Ljava/util/zip/ZipFile;-><clinit>()V': {
+ None: ['blocked'],
+ 'signature': 'Ljava/util/zip/ZipFile;-><clinit>()V',
+ },
+ }
+ self.assertEqual(expected, subset)
+
+ def test_extract_subset_invalid_pattern_wildcard_and_member(self):
+ monolithic = self.read_flag_trie_from_string(TestDetectOverlaps.extractInput)
+
+ patterns = 'Ljava/lang/*;->hashCode()I'
+
+ with self.assertRaises(Exception) as context:
+ self.extract_subset_from_monolithic_flags_as_dict_from_string(monolithic, patterns)
+ self.assertTrue("contains wildcard * and member signature hashCode()I" in str(context.exception))
+
+ def test_read_trie_duplicate(self):
+ with self.assertRaises(Exception) as context:
+ self.read_flag_trie_from_string('''
+Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
+Ljava/lang/Object;->hashCode()I,blocked
+''')
+ self.assertTrue("Duplicate signature: Ljava/lang/Object;->hashCode()I" in str(context.exception))
+
+ def test_read_trie_missing_member(self):
+ with self.assertRaises(Exception) as context:
+ self.read_flag_trie_from_string('''
+Ljava/lang/Object,public-api,system-api,test-api
+''')
+ self.assertTrue("Invalid signature: Ljava/lang/Object, does not identify a specific member" in str(context.exception))
+
def test_match(self):
monolithic = self.read_signature_csv_from_string_as_dict('''
Ljava/lang/Object;->hashCode()I,public-api,system-api,test-api
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index 9166109..60cc6b3 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -566,6 +566,7 @@
java.PrepareForTestWithJavaDefaultModules,
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary"),
+ java.FixtureConfigureApexBootJars("someapex:mysdklibrary", "myotherapex:myotherlib"),
prepareForSdkTestWithApex,
// Some additional files needed for the myotherapex.
diff --git a/tests/lib.sh b/tests/lib.sh
index 1d9b8d4..813a9dd 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -113,6 +113,7 @@
symlink_directory prebuilts/bazel
symlink_directory prebuilts/jdk
+ symlink_directory external/bazel-skylib
symlink_file WORKSPACE
symlink_file BUILD
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index 37940ba..3dc87f5 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -61,7 +61,6 @@
"proc_sync.go",
"rbe.go",
"sandbox_config.go",
- "signal.go",
"soong.go",
"test_build.go",
"upload.go",
diff --git a/ui/build/build.go b/ui/build/build.go
index 1ed9014..d869bf0 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -238,6 +238,11 @@
ctx.Verboseln("Skipping use of Kati ninja as requested")
what = what &^ RunKatiNinja
}
+ if config.SkipSoong() {
+ ctx.Verboseln("Skipping use of Soong as requested")
+ what = what &^ RunSoong
+ }
+
if config.SkipNinja() {
ctx.Verboseln("Skipping Ninja as requested")
what = what &^ RunNinja
diff --git a/ui/build/config.go b/ui/build/config.go
index 918a956..9768a44 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -49,6 +49,7 @@
skipConfig bool
skipKati bool
skipKatiNinja bool
+ skipSoong bool
skipNinja bool
skipSoongTests bool
@@ -582,6 +583,8 @@
arg := strings.TrimSpace(args[i])
if arg == "showcommands" {
c.verbose = true
+ } else if arg == "--empty-ninja-file" {
+ c.emptyNinjaFile = true
} else if arg == "--skip-ninja" {
c.skipNinja = true
} else if arg == "--skip-make" {
@@ -596,6 +599,10 @@
} else if arg == "--soong-only" {
c.skipKati = true
c.skipKatiNinja = true
+ } else if arg == "--config-only" {
+ c.skipKati = true
+ c.skipKatiNinja = true
+ c.skipSoong = true
} else if arg == "--skip-config" {
c.skipConfig = true
} else if arg == "--skip-soong-tests" {
@@ -690,54 +697,6 @@
}
}
-// Lunch configures the environment for a specific product similarly to the
-// `lunch` bash function.
-func (c *configImpl) Lunch(ctx Context, product, variant string) {
- if variant != "eng" && variant != "userdebug" && variant != "user" {
- ctx.Fatalf("Invalid variant %q. Must be one of 'user', 'userdebug' or 'eng'", variant)
- }
-
- c.environ.Set("TARGET_PRODUCT", product)
- c.environ.Set("TARGET_BUILD_VARIANT", variant)
- c.environ.Set("TARGET_BUILD_TYPE", "release")
- c.environ.Unset("TARGET_BUILD_APPS")
- c.environ.Unset("TARGET_BUILD_UNBUNDLED")
-}
-
-// Tapas configures the environment to build one or more unbundled apps,
-// similarly to the `tapas` bash function.
-func (c *configImpl) Tapas(ctx Context, apps []string, arch, variant string) {
- if len(apps) == 0 {
- apps = []string{"all"}
- }
- if variant == "" {
- variant = "eng"
- }
-
- if variant != "eng" && variant != "userdebug" && variant != "user" {
- ctx.Fatalf("Invalid variant %q. Must be one of 'user', 'userdebug' or 'eng'", variant)
- }
-
- var product string
- switch arch {
- case "arm", "":
- product = "aosp_arm"
- case "arm64":
- product = "aosm_arm64"
- case "x86":
- product = "aosp_x86"
- case "x86_64":
- product = "aosp_x86_64"
- default:
- ctx.Fatalf("Invalid architecture: %q", arch)
- }
-
- c.environ.Set("TARGET_PRODUCT", product)
- c.environ.Set("TARGET_BUILD_VARIANT", variant)
- c.environ.Set("TARGET_BUILD_TYPE", "release")
- c.environ.Set("TARGET_BUILD_APPS", strings.Join(apps, " "))
-}
-
func (c *configImpl) Environment() *Environment {
return c.environ
}
@@ -817,6 +776,10 @@
return c.skipKatiNinja
}
+func (c *configImpl) SkipSoong() bool {
+ return c.skipSoong
+}
+
func (c *configImpl) SkipNinja() bool {
return c.skipNinja
}
diff --git a/ui/signal/Android.bp b/ui/signal/Android.bp
new file mode 100644
index 0000000..08933a1
--- /dev/null
+++ b/ui/signal/Android.bp
@@ -0,0 +1,28 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-ui-signal",
+ pkgPath: "android/soong/ui/signal",
+ srcs: [
+ "signal.go",
+ ],
+ deps: [
+ "soong-ui-logger",
+ ],
+}
diff --git a/ui/build/signal.go b/ui/signal/signal.go
similarity index 99%
rename from ui/build/signal.go
rename to ui/signal/signal.go
index 6643e2f..4929a7b 100644
--- a/ui/build/signal.go
+++ b/ui/signal/signal.go
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package build
+package signal
import (
"os"