Merge "Support musl builds in Make"
diff --git a/README.md b/README.md
index 10ddd73..e92349e 100644
--- a/README.md
+++ b/README.md
@@ -451,15 +451,10 @@
The values of the variables can be set from a product's `BoardConfig.mk` file:
```
-SOONG_CONFIG_NAMESPACES += acme
-SOONG_CONFIG_acme += \
- board \
- feature \
- width \
-
-SOONG_CONFIG_acme_board := soc_a
-SOONG_CONFIG_acme_feature := true
-SOONG_CONFIG_acme_width := 200
+$(call add_soong_config_namespace, acme)
+$(call add_soong_config_var_value, acme, board, soc_a)
+$(call add_soong_config_var_value, acme, feature, true)
+$(call add_soong_config_var_value, acme, width, 200)
```
The `acme_cc_defaults` module type can be used anywhere after the definition in
diff --git a/android/config.go b/android/config.go
index 35403b8..23423b7 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1665,8 +1665,9 @@
return ConfiguredJarList{apexes, jars}
}
-// Filter keeps the entries if a jar appears in the given list of jars to keep; returns a new list.
-func (l *ConfiguredJarList) Filter(jarsToKeep []string) ConfiguredJarList {
+// Filter keeps the entries if a jar appears in the given list of jars to keep. Returns a new list
+// and any remaining jars that are not on this list.
+func (l *ConfiguredJarList) Filter(jarsToKeep []string) (ConfiguredJarList, []string) {
var apexes []string
var jars []string
@@ -1677,7 +1678,7 @@
}
}
- return ConfiguredJarList{apexes, jars}
+ return ConfiguredJarList{apexes, jars}, RemoveListFromList(jarsToKeep, jars)
}
// CopyOfJars returns a copy of the list of strings containing jar module name
diff --git a/android/module.go b/android/module.go
index b571f15..cc03418 100644
--- a/android/module.go
+++ b/android/module.go
@@ -986,10 +986,13 @@
// Device is built by default. Host and HostCross are not supported.
DeviceSupported = deviceSupported | deviceDefault
- // Device is built by default. Host and HostCross are supported.
+ // By default, _only_ device variant is built. Device variant can be disabled with `device_supported: false`
+ // Host and HostCross are disabled by default and can be enabled with `host_supported: true`
HostAndDeviceSupported = hostSupported | hostCrossSupported | deviceSupported | deviceDefault
// Host, HostCross, and Device are built by default.
+ // Building Device can be disabled with `device_supported: false`
+ // Building Host and HostCross can be disabled with `host_supported: false`
HostAndDeviceDefault = hostSupported | hostCrossSupported | hostDefault |
deviceSupported | deviceDefault
diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go
index 289e910..17f6d66 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -122,15 +122,10 @@
// }
//
// If an acme BoardConfig.mk file contained:
-//
-// SOONG_CONFIG_NAMESPACES += acme
-// SOONG_CONFIG_acme += \
-// board \
-// feature \
-//
-// SOONG_CONFIG_acme_board := soc_a
-// SOONG_CONFIG_acme_feature := true
-// SOONG_CONFIG_acme_width := 200
+// $(call add_sonng_config_namespace, acme)
+// $(call add_soong_config_var_value, acme, board, soc_a)
+// $(call add_soong_config_var_value, acme, feature, true)
+// $(call add_soong_config_var_value, acme, width, 200)
//
// Then libacme_foo would build with cflags "-DGENERIC -DSOC_A -DFEATURE -DWIDTH=200".
//
diff --git a/apex/apex_test.go b/apex/apex_test.go
index f07bf63..600f6c2 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -1874,6 +1874,45 @@
expectNoLink("libx", "shared_apex10000", "libz", "shared")
}
+func TestApexMinSdkVersion_crtobjectInVendorApex(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["mylib"],
+ updatable: false,
+ vendor: true,
+ min_sdk_version: "29",
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "mylib",
+ vendor_available: true,
+ system_shared_libs: [],
+ stl: "none",
+ apex_available: [ "myapex" ],
+ min_sdk_version: "29",
+ }
+ `)
+
+ vendorVariant := "android_vendor.29_arm64_armv8-a"
+
+ // First check that the correct variant of crtbegin_so is used.
+ ldRule := ctx.ModuleForTests("mylib", vendorVariant+"_shared_apex29").Rule("ld")
+ crtBegin := names(ldRule.Args["crtBegin"])
+ ensureListContains(t, crtBegin, "out/soong/.intermediates/"+cc.DefaultCcCommonTestModulesDir+"crtbegin_so/"+vendorVariant+"_apex29/crtbegin_so.o")
+
+ // Ensure that the crtbegin_so used by the APEX is targeting 29
+ cflags := ctx.ModuleForTests("crtbegin_so", vendorVariant+"_apex29").Rule("cc").Args["cFlags"]
+ android.AssertStringDoesContain(t, "cflags", cflags, "-target aarch64-linux-android29")
+}
+
func TestPlatformUsesLatestStubsFromApexes(t *testing.T) {
ctx := testApex(t, `
apex {
diff --git a/apex/classpath_element_test.go b/apex/classpath_element_test.go
index e2d8465..60f18bd 100644
--- a/apex/classpath_element_test.go
+++ b/apex/classpath_element_test.go
@@ -159,11 +159,6 @@
],
}
- bootclasspath_fragment {
- name: "non-apex-fragment",
- contents: ["othersdklibrary"],
- }
-
apex {
name: "otherapex",
key: "otherapex.key",
@@ -213,7 +208,6 @@
myFragment := result.Module("mybootclasspath-fragment", "android_common_apex10000")
myBar := result.Module("bar", "android_common_apex10000")
- nonApexFragment := result.Module("non-apex-fragment", "android_common")
other := result.Module("othersdklibrary", "android_common_apex10000")
otherApexLibrary := result.Module("otherapexlibrary", "android_common_apex10000")
@@ -253,15 +247,6 @@
assertElementsEquals(t, "elements", expectedElements, elements)
})
- // Verify that CreateClasspathElements detects when a fragment does not have an associated apex.
- t.Run("non apex fragment", func(t *testing.T) {
- ctx := newCtx()
- elements := java.CreateClasspathElements(ctx, []android.Module{}, []android.Module{nonApexFragment})
- android.FailIfNoMatchingErrors(t, "fragment non-apex-fragment{.*} is not part of an apex", ctx.errs)
- expectedElements := java.ClasspathElements{}
- assertElementsEquals(t, "elements", expectedElements, elements)
- })
-
// Verify that CreateClasspathElements detects when an apex has multiple fragments.
t.Run("multiple fragments for same apex", func(t *testing.T) {
ctx := newCtx()
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index e0421f6..513ddc0 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -543,3 +543,140 @@
"out/soong/target/product/test_device/system/etc/classpaths",
)
}
+
+func TestBootJarNotInApex(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForTestWithPlatformBootclasspath,
+ PrepareForTestWithApexBuildComponents,
+ prepareForTestWithMyapex,
+ java.FixtureConfigureApexBootJars("myapex:foo"),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `dependency "foo" of "myplatform-bootclasspath" missing variant`)).
+ RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "foo",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ bootclasspath_fragment {
+ name: "not-in-apex-fragment",
+ contents: [
+ "foo",
+ ],
+ }
+
+ platform_bootclasspath {
+ name: "myplatform-bootclasspath",
+ }
+ `)
+}
+
+func TestBootFragmentNotInApex(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForTestWithPlatformBootclasspath,
+ PrepareForTestWithApexBuildComponents,
+ prepareForTestWithMyapex,
+ java.FixtureConfigureApexBootJars("myapex:foo"),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `library foo.*have no corresponding fragment.*`)).RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ java_libs: ["foo"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "foo",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: ["myapex"],
+ permitted_packages: ["foo"],
+ }
+
+ bootclasspath_fragment {
+ name: "not-in-apex-fragment",
+ contents: ["foo"],
+ }
+
+ platform_bootclasspath {
+ name: "myplatform-bootclasspath",
+ }
+ `)
+}
+
+func TestNonBootJarInFragment(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForTestWithPlatformBootclasspath,
+ PrepareForTestWithApexBuildComponents,
+ prepareForTestWithMyapex,
+ java.FixtureConfigureApexBootJars("myapex:foo"),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `in contents must also be declared in PRODUCT_APEX_BOOT_JARS`)).
+ RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: ["apex-fragment"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "foo",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: ["myapex"],
+ permitted_packages: ["foo"],
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: ["myapex"],
+ permitted_packages: ["bar"],
+ }
+
+ bootclasspath_fragment {
+ name: "apex-fragment",
+ contents: ["foo", "bar"],
+ apex_available:[ "myapex" ],
+ }
+
+ platform_bootclasspath {
+ name: "myplatform-bootclasspath",
+ fragments: [{
+ apex: "myapex",
+ module:"apex-fragment",
+ }],
+ }
+ `)
+}
diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go
index a64c6f4..a8d5931 100644
--- a/apex/systemserver_classpath_fragment_test.go
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -130,3 +130,54 @@
`mysystemserverclasspathfragment`,
})
}
+
+func TestSystemServerClasspathFragmentWithContentNotInMake(t *testing.T) {
+ android.GroupFixturePreparers(
+ prepareForTestWithSystemserverclasspathFragment,
+ prepareForTestWithMyapex,
+ dexpreopt.FixtureSetApexSystemServerJars("myapex:foo"),
+ ).
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ `in contents must also be declared in PRODUCT_UPDATABLE_SYSTEM_SERVER_JARS`)).
+ RunTestWithBp(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ systemserverclasspath_fragments: [
+ "mysystemserverclasspathfragment",
+ ],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_library {
+ name: "foo",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: ["myapex"],
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: ["myapex"],
+ }
+
+ systemserverclasspath_fragment {
+ name: "mysystemserverclasspathfragment",
+ contents: [
+ "foo",
+ "bar",
+ ],
+ apex_available: [
+ "myapex",
+ ],
+ }
+ `)
+}
diff --git a/bloaty/bloaty_merger.py b/bloaty/bloaty_merger.py
index 1034462..46ce57f 100644
--- a/bloaty/bloaty_merger.py
+++ b/bloaty/bloaty_merger.py
@@ -24,58 +24,63 @@
import csv
import gzip
+# pylint: disable=import-error
import ninja_rsp
import file_sections_pb2
BLOATY_EXTENSION = ".bloaty.csv"
+
def parse_csv(path):
- """Parses a Bloaty-generated CSV file into a protobuf.
+ """Parses a Bloaty-generated CSV file into a protobuf.
- Args:
- path: The filepath to the CSV file, relative to $ANDROID_TOP.
+ Args:
+ path: The filepath to the CSV file, relative to $ANDROID_TOP.
- Returns:
- A file_sections_pb2.File if the file was found; None otherwise.
- """
- file_proto = None
- with open(path, newline='') as csv_file:
- file_proto = file_sections_pb2.File()
- if path.endswith(BLOATY_EXTENSION):
- file_proto.path = path[:-len(BLOATY_EXTENSION)]
- section_reader = csv.DictReader(csv_file)
- for row in section_reader:
- section = file_proto.sections.add()
- section.name = row["sections"]
- section.vm_size = int(row["vmsize"])
- section.file_size = int(row["filesize"])
- return file_proto
+ Returns:
+ A file_sections_pb2.File if the file was found; None otherwise.
+ """
+ file_proto = None
+ with open(path, newline='') as csv_file:
+ file_proto = file_sections_pb2.File()
+ if path.endswith(BLOATY_EXTENSION):
+ file_proto.path = path[: -len(BLOATY_EXTENSION)]
+ section_reader = csv.DictReader(csv_file)
+ for row in section_reader:
+ section = file_proto.sections.add()
+ section.name = row["sections"]
+ section.vm_size = int(row["vmsize"])
+ section.file_size = int(row["filesize"])
+ return file_proto
+
def create_file_size_metrics(input_list, output_proto):
- """Creates a FileSizeMetrics proto from a list of CSV files.
+ """Creates a FileSizeMetrics proto from a list of CSV files.
- Args:
- input_list: The path to the file which contains the list of CSV files. Each
- filepath is separated by a space.
- output_proto: The path for the output protobuf. It will be compressed using
- gzip.
- """
- metrics = file_sections_pb2.FileSizeMetrics()
- reader = ninja_rsp.NinjaRspFileReader(input_list)
- for csv_path in reader:
- file_proto = parse_csv(csv_path)
- if file_proto:
- metrics.files.append(file_proto)
- with gzip.open(output_proto, "wb") as output:
- output.write(metrics.SerializeToString())
+ Args:
+ input_list: The path to the file which contains the list of CSV files.
+ Each filepath is separated by a space.
+ output_proto: The path for the output protobuf. It will be compressed
+ using gzip.
+ """
+ metrics = file_sections_pb2.FileSizeMetrics()
+ reader = ninja_rsp.NinjaRspFileReader(input_list)
+ for csv_path in reader:
+ file_proto = parse_csv(csv_path)
+ if file_proto:
+ metrics.files.append(file_proto)
+ with gzip.open(output_proto, "wb") as output:
+ output.write(metrics.SerializeToString())
+
def main():
- parser = argparse.ArgumentParser()
- parser.add_argument("input_list_file", help="List of bloaty csv files.")
- parser.add_argument("output_proto", help="Output proto.")
- args = parser.parse_args()
- create_file_size_metrics(args.input_list_file, args.output_proto)
+ parser = argparse.ArgumentParser()
+ parser.add_argument("input_list_file", help="List of bloaty csv files.")
+ parser.add_argument("output_proto", help="Output proto.")
+ args = parser.parse_args()
+ create_file_size_metrics(args.input_list_file, args.output_proto)
+
if __name__ == '__main__':
- main()
+ main()
diff --git a/bloaty/bloaty_merger_test.py b/bloaty/bloaty_merger_test.py
index 9de049a..83680b9 100644
--- a/bloaty/bloaty_merger_test.py
+++ b/bloaty/bloaty_merger_test.py
@@ -14,6 +14,7 @@
import gzip
import unittest
+# pylint: disable=import-error
from pyfakefs import fake_filesystem_unittest
import bloaty_merger
@@ -21,46 +22,46 @@
class BloatyMergerTestCase(fake_filesystem_unittest.TestCase):
- def setUp(self):
- self.setUpPyfakefs()
+ def setUp(self):
+ self.setUpPyfakefs()
- def test_parse_csv(self):
- csv_content = "sections,vmsize,filesize\nsection1,2,3\n"
- self.fs.create_file("file1.bloaty.csv", contents=csv_content)
- pb = bloaty_merger.parse_csv("file1.bloaty.csv")
- self.assertEqual(pb.path, "file1")
- self.assertEqual(len(pb.sections), 1)
- s = pb.sections[0]
- self.assertEqual(s.name, "section1")
- self.assertEqual(s.vm_size, 2)
- self.assertEqual(s.file_size, 3)
+ def test_parse_csv(self):
+ csv_content = "sections,vmsize,filesize\nsection1,2,3\n"
+ self.fs.create_file("file1.bloaty.csv", contents=csv_content)
+ pb = bloaty_merger.parse_csv("file1.bloaty.csv")
+ self.assertEqual(pb.path, "file1")
+ self.assertEqual(len(pb.sections), 1)
+ s = pb.sections[0]
+ self.assertEqual(s.name, "section1")
+ self.assertEqual(s.vm_size, 2)
+ self.assertEqual(s.file_size, 3)
- def test_missing_file(self):
- with self.assertRaises(FileNotFoundError):
- bloaty_merger.parse_csv("missing.bloaty.csv")
+ def test_missing_file(self):
+ with self.assertRaises(FileNotFoundError):
+ bloaty_merger.parse_csv("missing.bloaty.csv")
- def test_malformed_csv(self):
- csv_content = "header1,heaVder2,header3\n4,5,6\n"
- self.fs.create_file("file1.bloaty.csv", contents=csv_content)
- with self.assertRaises(KeyError):
- bloaty_merger.parse_csv("file1.bloaty.csv")
+ def test_malformed_csv(self):
+ csv_content = "header1,heaVder2,header3\n4,5,6\n"
+ self.fs.create_file("file1.bloaty.csv", contents=csv_content)
+ with self.assertRaises(KeyError):
+ bloaty_merger.parse_csv("file1.bloaty.csv")
- def test_create_file_metrics(self):
- file_list = "file1.bloaty.csv file2.bloaty.csv"
- file1_content = "sections,vmsize,filesize\nsection1,2,3\nsection2,7,8"
- file2_content = "sections,vmsize,filesize\nsection1,4,5\n"
+ def test_create_file_metrics(self):
+ file_list = "file1.bloaty.csv file2.bloaty.csv"
+ file1_content = "sections,vmsize,filesize\nsection1,2,3\nsection2,7,8"
+ file2_content = "sections,vmsize,filesize\nsection1,4,5\n"
- self.fs.create_file("files.lst", contents=file_list)
- self.fs.create_file("file1.bloaty.csv", contents=file1_content)
- self.fs.create_file("file2.bloaty.csv", contents=file2_content)
+ self.fs.create_file("files.lst", contents=file_list)
+ self.fs.create_file("file1.bloaty.csv", contents=file1_content)
+ self.fs.create_file("file2.bloaty.csv", contents=file2_content)
- bloaty_merger.create_file_size_metrics("files.lst", "output.pb.gz")
+ bloaty_merger.create_file_size_metrics("files.lst", "output.pb.gz")
- metrics = file_sections_pb2.FileSizeMetrics()
- with gzip.open("output.pb.gz", "rb") as output:
- metrics.ParseFromString(output.read())
+ metrics = file_sections_pb2.FileSizeMetrics()
+ with gzip.open("output.pb.gz", "rb") as output:
+ metrics.ParseFromString(output.read())
if __name__ == '__main__':
- suite = unittest.TestLoader().loadTestsFromTestCase(BloatyMergerTestCase)
- unittest.TextTestRunner(verbosity=2).run(suite)
+ suite = unittest.TestLoader().loadTestsFromTestCase(BloatyMergerTestCase)
+ unittest.TextTestRunner(verbosity=2).run(suite)
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 78e3a74..b1ccc96 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -42,6 +42,7 @@
"performance_test.go",
"prebuilt_etc_conversion_test.go",
"python_binary_conversion_test.go",
+ "python_library_conversion_test.go",
"sh_conversion_test.go",
"testing.go",
],
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index a64d474..f652a35 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -14,14 +14,20 @@
package bp2build
+/*
+For shareable/common functionality for conversion from soong-module to build files
+for queryview/bp2build
+*/
+
import (
- "android/soong/android"
- "android/soong/bazel"
"fmt"
"reflect"
"sort"
"strings"
+ "android/soong/android"
+ "android/soong/bazel"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index bff192f..c840016 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -15,10 +15,10 @@
package bp2build
import (
+ "testing"
+
"android/soong/android"
"android/soong/cc"
- "strings"
- "testing"
)
const (
@@ -54,59 +54,6 @@
ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
}
-func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc bp2buildTestCase) {
- t.Helper()
- dir := "."
- filesystem := make(map[string][]byte)
- toParse := []string{
- "Android.bp",
- }
- for f, content := range tc.filesystem {
- if strings.HasSuffix(f, "Android.bp") {
- toParse = append(toParse, f)
- }
- filesystem[f] = []byte(content)
- }
- config := android.TestConfig(buildDir, nil, tc.blueprint, filesystem)
- ctx := android.NewTestContext(config)
-
- registerModuleTypes(ctx)
- ctx.RegisterModuleType(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestFactory)
- ctx.RegisterBp2BuildConfig(bp2buildConfig)
- ctx.RegisterBp2BuildMutator(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestBp2BuildMutator)
- ctx.RegisterForBazelConversion()
-
- _, errs := ctx.ParseFileList(dir, toParse)
- if errored(t, tc.description, errs) {
- return
- }
- _, errs = ctx.ResolveDependencies(config)
- if errored(t, tc.description, errs) {
- return
- }
-
- checkDir := dir
- if tc.dir != "" {
- checkDir = tc.dir
- }
- codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
- bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
- if actualCount, expectedCount := len(bazelTargets), len(tc.expectedBazelTargets); actualCount != expectedCount {
- t.Errorf("%s: Expected %d bazel target, got %d", tc.description, expectedCount, actualCount)
- } else {
- for i, target := range bazelTargets {
- if w, g := tc.expectedBazelTargets[i], target.content; w != g {
- t.Errorf(
- "%s: Expected generated Bazel target to be '%s', got '%s'",
- tc.description,
- w,
- g,
- )
- }
- }
- }
-}
-
func TestCcLibrarySimple(t *testing.T) {
runCcLibraryTestCase(t, bp2buildTestCase{
description: "cc_library - simple example",
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 712d0bd..ea2c10a 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -40,17 +40,6 @@
}`
)
-type bp2buildTestCase struct {
- description string
- moduleTypeUnderTest string
- moduleTypeUnderTestFactory android.ModuleFactory
- moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
- blueprint string
- expectedBazelTargets []string
- filesystem map[string]string
- dir string
-}
-
func TestCcLibraryHeadersLoadStatement(t *testing.T) {
testCases := []struct {
bazelTargets BazelTargets
diff --git a/bp2build/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go
index 7bedf71..cf46322 100644
--- a/bp2build/python_binary_conversion_test.go
+++ b/bp2build/python_binary_conversion_test.go
@@ -3,17 +3,11 @@
import (
"testing"
- "android/soong/android"
"android/soong/python"
)
-func runPythonTestCase(t *testing.T, tc bp2buildTestCase) {
- t.Helper()
- runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
-}
-
func TestPythonBinaryHostSimple(t *testing.T) {
- runPythonTestCase(t, bp2buildTestCase{
+ runBp2BuildTestCaseSimple(t, bp2buildTestCase{
description: "simple python_binary_host converts to a native py_binary",
moduleTypeUnderTest: "python_binary_host",
moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
@@ -49,7 +43,7 @@
}
func TestPythonBinaryHostPy2(t *testing.T) {
- runPythonTestCase(t, bp2buildTestCase{
+ runBp2BuildTestCaseSimple(t, bp2buildTestCase{
description: "py2 python_binary_host",
moduleTypeUnderTest: "python_binary_host",
moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
@@ -79,7 +73,7 @@
}
func TestPythonBinaryHostPy3(t *testing.T) {
- runPythonTestCase(t, bp2buildTestCase{
+ runBp2BuildTestCaseSimple(t, bp2buildTestCase{
description: "py3 python_binary_host",
moduleTypeUnderTest: "python_binary_host",
moduleTypeUnderTestFactory: python.PythonBinaryHostFactory,
diff --git a/bp2build/python_library_conversion_test.go b/bp2build/python_library_conversion_test.go
new file mode 100644
index 0000000..e337965
--- /dev/null
+++ b/bp2build/python_library_conversion_test.go
@@ -0,0 +1,134 @@
+package bp2build
+
+import (
+ "testing"
+
+ "android/soong/python"
+)
+
+func TestPythonLibrarySimple(t *testing.T) {
+ runBp2BuildTestCaseSimple(t, bp2buildTestCase{
+ description: "simple python_library converts to a native py_library",
+ moduleTypeUnderTest: "python_library",
+ moduleTypeUnderTestFactory: python.PythonLibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: python.PythonLibraryBp2Build,
+ filesystem: map[string]string{
+ "a.py": "",
+ "b/c.py": "",
+ "b/d.py": "",
+ "b/e.py": "",
+ "files/data.txt": "",
+ },
+ blueprint: `python_library {
+ name: "foo",
+ srcs: ["**/*.py"],
+ exclude_srcs: ["b/e.py"],
+ data: ["files/data.txt",],
+ bazel_module: { bp2build_available: true },
+}
+`,
+ expectedBazelTargets: []string{`py_library(
+ name = "foo",
+ data = ["files/data.txt"],
+ srcs = [
+ "a.py",
+ "b/c.py",
+ "b/d.py",
+ ],
+ srcs_version = "PY3",
+)`,
+ },
+ })
+}
+
+func TestPythonLibraryPy2(t *testing.T) {
+ runBp2BuildTestCaseSimple(t, bp2buildTestCase{
+ description: "py2 python_library",
+ moduleTypeUnderTest: "python_library",
+ moduleTypeUnderTestFactory: python.PythonLibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: python.PythonLibraryBp2Build,
+ blueprint: `python_library {
+ name: "foo",
+ srcs: ["a.py"],
+ version: {
+ py2: {
+ enabled: true,
+ },
+ py3: {
+ enabled: false,
+ },
+ },
+
+ bazel_module: { bp2build_available: true },
+}
+`,
+ expectedBazelTargets: []string{`py_library(
+ name = "foo",
+ srcs = ["a.py"],
+ srcs_version = "PY2",
+)`,
+ },
+ })
+}
+
+func TestPythonLibraryPy3(t *testing.T) {
+ runBp2BuildTestCaseSimple(t, bp2buildTestCase{
+ description: "py3 python_library",
+ moduleTypeUnderTest: "python_library",
+ moduleTypeUnderTestFactory: python.PythonLibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: python.PythonLibraryBp2Build,
+ blueprint: `python_library {
+ name: "foo",
+ srcs: ["a.py"],
+ version: {
+ py2: {
+ enabled: false,
+ },
+ py3: {
+ enabled: true,
+ },
+ },
+
+ bazel_module: { bp2build_available: true },
+}
+`,
+ expectedBazelTargets: []string{
+ `py_library(
+ name = "foo",
+ srcs = ["a.py"],
+ srcs_version = "PY3",
+)`,
+ },
+ })
+}
+
+func TestPythonLibraryPyBoth(t *testing.T) {
+ runBp2BuildTestCaseSimple(t, bp2buildTestCase{
+ description: "py3 python_library",
+ moduleTypeUnderTest: "python_library",
+ moduleTypeUnderTestFactory: python.PythonLibraryFactory,
+ moduleTypeUnderTestBp2BuildMutator: python.PythonLibraryBp2Build,
+ blueprint: `python_library {
+ name: "foo",
+ srcs: ["a.py"],
+ version: {
+ py2: {
+ enabled: true,
+ },
+ py3: {
+ enabled: true,
+ },
+ },
+
+ bazel_module: { bp2build_available: true },
+}
+`,
+ expectedBazelTargets: []string{
+ // srcs_version is PY2ANDPY3 by default.
+ `py_library(
+ name = "foo",
+ srcs = ["a.py"],
+)`,
+ },
+ })
+}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index 266b817..3a77d0e 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -1,6 +1,26 @@
+// 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 bp2build
+/*
+For shareable/common bp2build testing functionality and dumping ground for
+specific-but-shared functionality among tests in package
+*/
+
import (
+ "strings"
"testing"
"android/soong/android"
@@ -16,6 +36,86 @@
buildDir string
)
+func errored(t *testing.T, desc string, errs []error) bool {
+ t.Helper()
+ if len(errs) > 0 {
+ for _, err := range errs {
+ t.Errorf("%s: %s", desc, err)
+ }
+ return true
+ }
+ return false
+}
+
+func runBp2BuildTestCaseSimple(t *testing.T, tc bp2buildTestCase) {
+ t.Helper()
+ runBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
+}
+
+type bp2buildTestCase struct {
+ description string
+ moduleTypeUnderTest string
+ moduleTypeUnderTestFactory android.ModuleFactory
+ moduleTypeUnderTestBp2BuildMutator func(android.TopDownMutatorContext)
+ blueprint string
+ expectedBazelTargets []string
+ filesystem map[string]string
+ dir string
+}
+
+func runBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc bp2buildTestCase) {
+ t.Helper()
+ dir := "."
+ filesystem := make(map[string][]byte)
+ toParse := []string{
+ "Android.bp",
+ }
+ for f, content := range tc.filesystem {
+ if strings.HasSuffix(f, "Android.bp") {
+ toParse = append(toParse, f)
+ }
+ filesystem[f] = []byte(content)
+ }
+ config := android.TestConfig(buildDir, nil, tc.blueprint, filesystem)
+ ctx := android.NewTestContext(config)
+
+ registerModuleTypes(ctx)
+ ctx.RegisterModuleType(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestFactory)
+ ctx.RegisterBp2BuildConfig(bp2buildConfig)
+ ctx.RegisterBp2BuildMutator(tc.moduleTypeUnderTest, tc.moduleTypeUnderTestBp2BuildMutator)
+ ctx.RegisterForBazelConversion()
+
+ _, errs := ctx.ParseFileList(dir, toParse)
+ if errored(t, tc.description, errs) {
+ return
+ }
+ _, errs = ctx.ResolveDependencies(config)
+ if errored(t, tc.description, errs) {
+ return
+ }
+
+ checkDir := dir
+ if tc.dir != "" {
+ checkDir = tc.dir
+ }
+ codegenCtx := NewCodegenContext(config, *ctx.Context, Bp2Build)
+ bazelTargets := generateBazelTargetsForDir(codegenCtx, checkDir)
+ if actualCount, expectedCount := len(bazelTargets), len(tc.expectedBazelTargets); actualCount != expectedCount {
+ t.Errorf("%s: Expected %d bazel target, got %d", tc.description, expectedCount, actualCount)
+ } else {
+ for i, target := range bazelTargets {
+ if w, g := tc.expectedBazelTargets[i], target.content; w != g {
+ t.Errorf(
+ "%s: Expected generated Bazel target to be '%s', got '%s'",
+ tc.description,
+ w,
+ g,
+ )
+ }
+ }
+ }
+}
+
type nestedProps struct {
Nested_prop string
}
@@ -44,17 +144,6 @@
props customProps
}
-func errored(t *testing.T, desc string, errs []error) bool {
- t.Helper()
- if len(errs) > 0 {
- for _, err := range errs {
- t.Errorf("%s: %s", desc, err)
- }
- return true
- }
- return false
-}
-
// OutputFiles is needed because some instances of this module use dist with a
// tag property which requires the module implements OutputFileProducer.
func (m *customModule) OutputFiles(tag string) (android.Paths, error) {
diff --git a/cc/androidmk.go b/cc/androidmk.go
index bda1006..cd52363 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -24,12 +24,12 @@
)
var (
- nativeBridgeSuffix = ".native_bridge"
- productSuffix = ".product"
+ NativeBridgeSuffix = ".native_bridge"
+ ProductSuffix = ".product"
VendorSuffix = ".vendor"
- ramdiskSuffix = ".ramdisk"
+ RamdiskSuffix = ".ramdisk"
VendorRamdiskSuffix = ".vendor_ramdisk"
- recoverySuffix = ".recovery"
+ RecoverySuffix = ".recovery"
sdkSuffix = ".sdk"
)
@@ -182,7 +182,7 @@
if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
var result []string
for _, override := range overrides {
- result = append(result, override+nativeBridgeSuffix)
+ result = append(result, override+NativeBridgeSuffix)
}
return result
}
@@ -294,6 +294,9 @@
if library.buildStubs() {
entries.SetBool("LOCAL_NO_NOTICE_FILE", true)
}
+ if library.apiListCoverageXmlPath.String() != "" {
+ entries.SetString("SOONG_CC_API_XML", "$(SOONG_CC_API_XML) "+library.apiListCoverageXmlPath.String())
+ }
})
}
// If a library providing a stub is included in an APEX, the private APIs of the library
diff --git a/cc/binary.go b/cc/binary.go
index 763d2b9..b423c50 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -156,6 +156,10 @@
}
}
+ if binary.static() {
+ deps.StaticLibs = append(deps.StaticLibs, deps.SystemSharedLibs...)
+ }
+
if ctx.toolchain().Bionic() {
if binary.static() {
if ctx.selectedStl() == "libc++_static" {
@@ -208,7 +212,7 @@
func (binary *binaryDecorator) linkerInit(ctx BaseModuleContext) {
binary.baseLinker.linkerInit(ctx)
- if !ctx.toolchain().Bionic() {
+ if !ctx.toolchain().Bionic() && !ctx.toolchain().Musl() {
if ctx.Os() == android.Linux {
// Unless explicitly specified otherwise, host static binaries are built with -static
// if HostStaticBinaries is true for the product configuration.
diff --git a/cc/cc.go b/cc/cc.go
index f65af30..9c1f559 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -822,6 +822,16 @@
}
func (c *Module) AddJSONData(d *map[string]interface{}) {
+ var hasAidl, hasLex, hasProto, hasRenderscript, hasSysprop, hasWinMsg, hasYacc bool
+ if b, ok := c.compiler.(*baseCompiler); ok {
+ hasAidl = b.hasSrcExt(".aidl")
+ hasLex = b.hasSrcExt(".l") || b.hasSrcExt(".ll")
+ hasProto = b.hasSrcExt(".proto")
+ hasRenderscript = b.hasSrcExt(".rscript") || b.hasSrcExt(".fs")
+ hasSysprop = b.hasSrcExt(".sysprop")
+ hasWinMsg = b.hasSrcExt(".mc")
+ hasYacc = b.hasSrcExt(".y") || b.hasSrcExt(".yy")
+ }
c.AndroidModuleBase().AddJSONData(d)
(*d)["Cc"] = map[string]interface{}{
"SdkVersion": c.SdkVersion(),
@@ -858,6 +868,14 @@
"IsVendorPublicLibrary": c.IsVendorPublicLibrary(),
"ApexSdkVersion": c.apexSdkVersion,
"TestFor": c.TestFor(),
+ "AidlSrcs": hasAidl,
+ "LexSrcs": hasLex,
+ "ProtoSrcs": hasProto,
+ "RenderscriptSrcs": hasRenderscript,
+ "SyspropSrcs": hasSysprop,
+ "WinMsgSrcs": hasWinMsg,
+ "YaccSrsc": hasYacc,
+ "OnlyCSrcs": !(hasAidl || hasLex || hasProto || hasRenderscript || hasSysprop || hasWinMsg || hasYacc),
}
}
@@ -957,16 +975,17 @@
return String(c.Properties.Min_sdk_version)
}
-func (c *Module) SplitPerApiLevel() bool {
- if !c.canUseSdk() {
- return false
- }
+func (c *Module) isCrt() bool {
if linker, ok := c.linker.(*objectLinker); ok {
return linker.isCrt()
}
return false
}
+func (c *Module) SplitPerApiLevel() bool {
+ return c.canUseSdk() && c.isCrt()
+}
+
func (c *Module) AlwaysSdk() bool {
return c.Properties.AlwaysSdk || Bool(c.Properties.Sdk_variant_only)
}
@@ -1428,12 +1447,20 @@
// create versioned variants for. For example, if min_sdk_version is 16, then sdk variant of
// the crt object has local variants of 16, 17, ..., up to the latest version. sdk_version
// and min_sdk_version properties of the variants are set to the corresponding version
- // numbers. However, the platform (non-sdk) variant of the crt object is left untouched.
- // min_sdk_version: 16 doesn't actually mean that the platform variant has to support such
- // an old version. Since the variant is for the platform, it's preferred to target the
- // latest version.
- if ctx.mod.SplitPerApiLevel() && !ctx.isSdkVariant() {
- ver = strconv.Itoa(android.FutureApiLevelInt)
+ // numbers. However, the non-sdk variant (for apex or platform) of the crt object is left
+ // untouched. min_sdk_version: 16 doesn't actually mean that the non-sdk variant has to
+ // support such an old version. The version is set to the later version in case when the
+ // non-sdk variant is for the platform, or the min_sdk_version of the containing APEX if
+ // it's for an APEX.
+ if ctx.mod.isCrt() && !ctx.isSdkVariant() {
+ if ctx.isForPlatform() {
+ ver = strconv.Itoa(android.FutureApiLevelInt)
+ } else { // for apex
+ ver = ctx.apexSdkVersion().String()
+ if ver == "" { // in case when min_sdk_version was not set by the APEX
+ ver = ctx.sdkVersion()
+ }
+ }
}
// Also make sure that minSdkVersion is not greater than sdkVersion, if they are both numbers
@@ -1632,7 +1659,7 @@
return ""
}
vndkVersion = ctx.DeviceConfig().ProductVndkVersion()
- nameSuffix = productSuffix
+ nameSuffix = ProductSuffix
} else {
vndkVersion = ctx.DeviceConfig().VndkVersion()
nameSuffix = VendorSuffix
@@ -1652,7 +1679,7 @@
c.Properties.SubName = ""
if c.Target().NativeBridge == android.NativeBridgeEnabled {
- c.Properties.SubName += nativeBridgeSuffix
+ c.Properties.SubName += NativeBridgeSuffix
}
llndk := c.IsLlndk()
@@ -1668,11 +1695,11 @@
// such suffixes are already hard-coded in prebuilts/vndk/.../Android.bp.
c.Properties.SubName += VendorSuffix
} else if c.InRamdisk() && !c.OnlyInRamdisk() {
- c.Properties.SubName += ramdiskSuffix
+ c.Properties.SubName += RamdiskSuffix
} else if c.InVendorRamdisk() && !c.OnlyInVendorRamdisk() {
c.Properties.SubName += VendorRamdiskSuffix
} else if c.InRecovery() && !c.OnlyInRecovery() {
- c.Properties.SubName += recoverySuffix
+ c.Properties.SubName += RecoverySuffix
} else if c.IsSdkVariant() && (c.Properties.SdkAndPlatformVariantVisibleToMake || c.SplitPerApiLevel()) {
c.Properties.SubName += sdkSuffix
if c.SplitPerApiLevel() {
@@ -3029,13 +3056,13 @@
// core module, so update the dependency name here accordingly.
return libName + ccDep.SubName()
} else if ccDep.InRamdisk() && !ccDep.OnlyInRamdisk() {
- return libName + ramdiskSuffix
+ return libName + RamdiskSuffix
} else if ccDep.InVendorRamdisk() && !ccDep.OnlyInVendorRamdisk() {
return libName + VendorRamdiskSuffix
} else if ccDep.InRecovery() && !ccDep.OnlyInRecovery() {
- return libName + recoverySuffix
+ return libName + RecoverySuffix
} else if ccDep.Target().NativeBridge == android.NativeBridgeEnabled {
- return libName + nativeBridgeSuffix
+ return libName + NativeBridgeSuffix
} else {
return libName
}
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index e7fcfed..ac5d5f7 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -45,6 +45,7 @@
linuxMuslCflags = []string{
"-D_LIBCPP_HAS_MUSL_LIBC",
+ "-DANDROID_HOST_MUSL",
"-nostdlibinc",
}
@@ -106,7 +107,7 @@
"util",
}, "-l")
- muslCrtBeginStaticBinary, muslCrtEndStaticBinary = []string{"libc_musl_crtbegin_static"}, []string{"crtend_android"}
+ muslCrtBeginStaticBinary, muslCrtEndStaticBinary = []string{"libc_musl_crtbegin_static"}, []string{"libc_musl_crtend"}
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"}
diff --git a/cc/coverage.go b/cc/coverage.go
index baf4226..8dd2db1 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -244,3 +244,19 @@
m[1].(Coverage).EnableCoverageIfNeeded()
}
}
+
+func parseSymbolFileForAPICoverage(ctx ModuleContext, symbolFile string) android.ModuleOutPath {
+ apiLevelsJson := android.GetApiLevelsJson(ctx)
+ symbolFilePath := android.PathForModuleSrc(ctx, symbolFile)
+ outputFile := ctx.baseModuleName() + ".xml"
+ parsedApiCoveragePath := android.PathForModuleOut(ctx, outputFile)
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Command().
+ BuiltTool("ndk_api_coverage_parser").
+ Input(symbolFilePath).
+ Output(parsedApiCoveragePath).
+ Implicit(apiLevelsJson).
+ FlagWithArg("--api-map ", apiLevelsJson.String())
+ rule.Build("native_library_api_list", "Generate native API list based on symbol files for coverage measurement")
+ return parsedApiCoveragePath
+}
diff --git a/cc/library.go b/cc/library.go
index 1526f81..196116b 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -536,6 +536,8 @@
*baseInstaller
collectedSnapshotHeaders android.Paths
+
+ apiListCoverageXmlPath android.ModuleOutPath
}
type ccLibraryBazelHandler struct {
@@ -951,6 +953,12 @@
objs := compileStubLibrary(ctx, flags, nativeAbiResult.stubSrc)
library.versionScriptPath = android.OptionalPathForPath(
nativeAbiResult.versionScript)
+
+ // Parse symbol file to get API list for coverage
+ if library.stubsVersion() == "current" && ctx.PrimaryArch() {
+ library.apiListCoverageXmlPath = parseSymbolFileForAPICoverage(ctx, symbolFile)
+ }
+
return objs
}
diff --git a/cc/ndk_api_coverage_parser/__init__.py b/cc/ndk_api_coverage_parser/__init__.py
index 7817c78..8b9cd66 100755
--- a/cc/ndk_api_coverage_parser/__init__.py
+++ b/cc/ndk_api_coverage_parser/__init__.py
@@ -21,7 +21,12 @@
import sys
from xml.etree.ElementTree import Element, SubElement, tostring
-from symbolfile import ALL_ARCHITECTURES, FUTURE_API_LEVEL, MultiplyDefinedSymbolError, SymbolFileParser
+from symbolfile import (
+ ALL_ARCHITECTURES,
+ FUTURE_API_LEVEL,
+ MultiplyDefinedSymbolError,
+ SymbolFileParser,
+)
ROOT_ELEMENT_TAG = 'ndk-library'
@@ -63,6 +68,7 @@
class XmlGenerator(object):
"""Output generator that writes parsed symbol file to a xml file."""
+
def __init__(self, output_file):
self.output_file = output_file
@@ -74,10 +80,14 @@
continue
version_attributes = parse_tags(version.tags)
_, _, postfix = version.name.partition('_')
- is_platform = postfix == 'PRIVATE' or postfix == 'PLATFORM'
+ is_platform = postfix in ('PRIVATE' , 'PLATFORM')
is_deprecated = postfix == 'DEPRECATED'
- version_attributes.update({PLATFORM_ATTRIBUTE_KEY: str(is_platform)})
- version_attributes.update({DEPRECATED_ATTRIBUTE_KEY: str(is_deprecated)})
+ version_attributes.update(
+ {PLATFORM_ATTRIBUTE_KEY: str(is_platform)}
+ )
+ version_attributes.update(
+ {DEPRECATED_ATTRIBUTE_KEY: str(is_deprecated)}
+ )
for symbol in version.symbols:
if VARIABLE_TAG in symbol.tags:
continue
@@ -103,13 +113,20 @@
"""Parses and returns command line arguments."""
parser = argparse.ArgumentParser()
- parser.add_argument('symbol_file', type=os.path.realpath, help='Path to symbol file.')
parser.add_argument(
- 'output_file', type=os.path.realpath,
- help='The output parsed api coverage file.')
+ 'symbol_file', type=os.path.realpath, help='Path to symbol file.'
+ )
parser.add_argument(
- '--api-map', type=os.path.realpath, required=True,
- help='Path to the API level map JSON file.')
+ 'output_file',
+ type=os.path.realpath,
+ help='The output parsed api coverage file.',
+ )
+ parser.add_argument(
+ '--api-map',
+ type=os.path.realpath,
+ required=True,
+ help='Path to the API level map JSON file.',
+ )
return parser.parse_args()
@@ -122,13 +139,15 @@
with open(args.symbol_file) as symbol_file:
try:
- versions = SymbolFileParser(symbol_file, api_map, "", FUTURE_API_LEVEL,
- True, True).parse()
+ versions = SymbolFileParser(
+ symbol_file, api_map, "", FUTURE_API_LEVEL, True, True
+ ).parse()
except MultiplyDefinedSymbolError as ex:
sys.exit('{}: error: {}'.format(args.symbol_file, ex))
generator = XmlGenerator(args.output_file)
generator.write(versions)
+
if __name__ == '__main__':
main()
diff --git a/cc/ndk_api_coverage_parser/test_ndk_api_coverage_parser.py b/cc/ndk_api_coverage_parser/test_ndk_api_coverage_parser.py
index 3ec14c1..141059c 100644
--- a/cc/ndk_api_coverage_parser/test_ndk_api_coverage_parser.py
+++ b/cc/ndk_api_coverage_parser/test_ndk_api_coverage_parser.py
@@ -50,10 +50,12 @@
return False
return all(etree_equal(c1, c2) for c1, c2 in zip(elem1, elem2))
-
+# pylint: disable=line-too-long
class ApiCoverageSymbolFileParserTest(unittest.TestCase):
def test_parse(self):
- input_file = io.StringIO(textwrap.dedent(u"""\
+ input_file = io.StringIO(
+ textwrap.dedent(
+ u"""\
LIBLOG { # introduced-arm64=24 introduced-x86=24 introduced-x86_64=24
global:
android_name_to_log_id; # apex llndk introduced=23
@@ -64,22 +66,28 @@
local:
*;
};
-
+
LIBLOG_PLATFORM {
android_fdtrack; # llndk
android_net; # introduced=23
};
-
+
LIBLOG_FOO { # var
android_var;
};
- """))
- parser = SymbolFileParser(input_file, {}, "", FUTURE_API_LEVEL, True, True)
+ """
+ )
+ )
+ parser = SymbolFileParser(
+ input_file, {}, "", FUTURE_API_LEVEL, True, True
+ )
generator = nparser.XmlGenerator(io.StringIO())
result = generator.convertToXml(parser.parse())
- expected = fromstring('<ndk-library><symbol apex="True" arch="" introduced="23" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_name_to_log_id" /><symbol arch="arm" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_log_id_to_name" /><symbol arch="" introduced-arm64="24" introduced-x86="23" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_assert" /><symbol arch="" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_buf_write" /><symbol arch="" is_deprecated="False" is_platform="True" llndk="True" name="android_fdtrack" /><symbol arch="" introduced="23" is_deprecated="False" is_platform="True" name="android_net" /></ndk-library>')
+ expected = fromstring(
+ '<ndk-library><symbol apex="True" arch="" introduced="23" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_name_to_log_id" /><symbol arch="arm" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" llndk="True" name="android_log_id_to_name" /><symbol arch="" introduced-arm64="24" introduced-x86="23" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_assert" /><symbol arch="" introduced-arm64="24" introduced-x86="24" introduced-x86_64="24" is_deprecated="False" is_platform="False" name="__android_log_buf_write" /><symbol arch="" is_deprecated="False" is_platform="True" llndk="True" name="android_fdtrack" /><symbol arch="" introduced="23" is_deprecated="False" is_platform="True" name="android_net" /></ndk-library>'
+ )
self.assertTrue(etree_equal(expected, result))
-
+# pylint: enable=line-too-long
def main():
suite = unittest.TestLoader().loadTestsFromName(__name__)
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 63e8261..51cdddf 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -29,7 +29,6 @@
func init() {
pctx.HostBinToolVariable("ndkStubGenerator", "ndkstubgen")
- pctx.HostBinToolVariable("ndk_api_coverage_parser", "ndk_api_coverage_parser")
pctx.HostBinToolVariable("abidiff", "abidiff")
pctx.HostBinToolVariable("abitidy", "abitidy")
pctx.HostBinToolVariable("abidw", "abidw")
@@ -43,12 +42,6 @@
CommandDeps: []string{"$ndkStubGenerator"},
}, "arch", "apiLevel", "apiMap", "flags")
- parseNdkApiRule = pctx.AndroidStaticRule("parseNdkApiRule",
- blueprint.RuleParams{
- Command: "$ndk_api_coverage_parser $in $out --api-map $apiMap",
- CommandDeps: []string{"$ndk_api_coverage_parser"},
- }, "apiMap")
-
abidw = pctx.AndroidStaticRule("abidw",
blueprint.RuleParams{
Command: "$abidw --type-id-style hash --no-corpus-path " +
@@ -276,24 +269,6 @@
android.Paths{src}, nil, nil)
}
-func parseSymbolFileForCoverage(ctx ModuleContext, symbolFile string) android.ModuleOutPath {
- apiLevelsJson := android.GetApiLevelsJson(ctx)
- symbolFilePath := android.PathForModuleSrc(ctx, symbolFile)
- outputFileName := strings.Split(symbolFilePath.Base(), ".")[0]
- parsedApiCoveragePath := android.PathForModuleOut(ctx, outputFileName+".xml")
- ctx.Build(pctx, android.BuildParams{
- Rule: parseNdkApiRule,
- Description: "parse ndk api symbol file for api coverage: " + symbolFilePath.Rel(),
- Outputs: []android.WritablePath{parsedApiCoveragePath},
- Input: symbolFilePath,
- Implicits: []android.Path{apiLevelsJson},
- Args: map[string]string{
- "apiMap": apiLevelsJson.String(),
- },
- })
- return parsedApiCoveragePath
-}
-
func (this *stubDecorator) findImplementationLibrary(ctx ModuleContext) android.Path {
dep := ctx.GetDirectDepWithTag(strings.TrimSuffix(ctx.ModuleName(), ndkLibrarySuffix),
stubImplementation)
@@ -454,7 +429,7 @@
}
}
if c.apiLevel.IsCurrent() && ctx.PrimaryArch() {
- c.parsedCoverageXmlPath = parseSymbolFileForCoverage(ctx, symbolFile)
+ c.parsedCoverageXmlPath = parseSymbolFileForAPICoverage(ctx, symbolFile)
}
return objs
}
diff --git a/cc/object_test.go b/cc/object_test.go
index 0e5508a..259a892 100644
--- a/cc/object_test.go
+++ b/cc/object_test.go
@@ -15,8 +15,9 @@
package cc
import (
- "android/soong/android"
"testing"
+
+ "android/soong/android"
)
func TestMinSdkVersionsOfCrtObjects(t *testing.T) {
@@ -27,24 +28,23 @@
crt: true,
stl: "none",
min_sdk_version: "28",
-
+ vendor_available: true,
}`)
- arch := "android_arm64_armv8-a"
- for _, v := range []string{"", "28", "29", "30", "current"} {
- var variant string
- // platform variant
- if v == "" {
- variant = arch
- } else {
- variant = arch + "_sdk_" + v
- }
- cflags := ctx.ModuleForTests("crt_foo", variant).Rule("cc").Args["cFlags"]
- vNum := v
- if v == "current" || v == "" {
- vNum = "10000"
- }
- expected := "-target aarch64-linux-android" + vNum + " "
+ variants := []struct {
+ variant string
+ num string
+ }{
+ {"android_arm64_armv8-a", "10000"},
+ {"android_arm64_armv8-a_sdk_28", "28"},
+ {"android_arm64_armv8-a_sdk_29", "29"},
+ {"android_arm64_armv8-a_sdk_30", "30"},
+ {"android_arm64_armv8-a_sdk_current", "10000"},
+ {"android_vendor.29_arm64_armv8-a", "29"},
+ }
+ for _, v := range variants {
+ cflags := ctx.ModuleForTests("crt_foo", v.variant).Rule("cc").Args["cFlags"]
+ expected := "-target aarch64-linux-android" + v.num + " "
android.AssertStringDoesContain(t, "cflag", cflags, expected)
}
}
diff --git a/cc/sanitize.go b/cc/sanitize.go
index dd15ae1..90974aa 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -41,7 +41,6 @@
hwasanCflags = []string{"-fno-omit-frame-pointer", "-Wno-frame-larger-than=",
"-fsanitize-hwaddress-abi=platform",
- "-fno-experimental-new-pass-manager",
// The following improves debug location information
// availability at the cost of its accuracy. It increases
// the likelihood of a stack variable's frame offset
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index 9672c0f..9570664 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -61,7 +61,7 @@
}
func (recoverySnapshotImage) moduleNameSuffix() string {
- return recoverySuffix
+ return RecoverySuffix
}
// Override existing vendor and recovery snapshot for cc module specific extra functions
diff --git a/cc/testing.go b/cc/testing.go
index 071f1ec..d0dca6b 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -375,26 +375,42 @@
cc_object {
name: "crtbegin_so",
defaults: ["crt_defaults"],
+ srcs: ["crtbegin_so.c"],
+ objs: ["crtbrand"],
}
cc_object {
name: "crtbegin_dynamic",
defaults: ["crt_defaults"],
+ srcs: ["crtbegin.c"],
+ objs: ["crtbrand"],
}
cc_object {
name: "crtbegin_static",
defaults: ["crt_defaults"],
+ srcs: ["crtbegin.c"],
+ objs: ["crtbrand"],
}
cc_object {
name: "crtend_so",
defaults: ["crt_defaults"],
+ srcs: ["crtend_so.c"],
+ objs: ["crtbrand"],
}
cc_object {
name: "crtend_android",
defaults: ["crt_defaults"],
+ srcs: ["crtend.c"],
+ objs: ["crtbrand"],
+ }
+
+ cc_object {
+ name: "crtbrand",
+ defaults: ["crt_defaults"],
+ srcs: ["crtbrand.c"],
}
cc_library {
@@ -585,6 +601,11 @@
"defaults/cc/common/libm.map.txt": nil,
"defaults/cc/common/ndk_libandroid_support": nil,
"defaults/cc/common/ndk_libc++_shared": nil,
+ "defaults/cc/common/crtbegin_so.c": nil,
+ "defaults/cc/common/crtbegin.c": nil,
+ "defaults/cc/common/crtend_so.c": nil,
+ "defaults/cc/common/crtend.c": nil,
+ "defaults/cc/common/crtbrand.c": nil,
}.AddToFixture(),
// Place the default cc test modules that are common to all platforms in a location that will not
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index af935db..8aea037 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -25,9 +25,9 @@
"android/soong/bp2build"
"android/soong/shared"
-
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/deptools"
+ "github.com/google/blueprint/pathtools"
"android/soong/android"
)
@@ -38,6 +38,8 @@
availableEnvFile string
usedEnvFile string
+ globFile string
+ globListDir string
delveListen string
delvePath string
@@ -65,8 +67,8 @@
flag.StringVar(&bp2buildMarker, "bp2build_marker", "", "If set, run bp2build, touch the specified marker file then exit")
flag.StringVar(&cmdlineArgs.OutFile, "o", "build.ninja", "the Ninja file to output")
- flag.StringVar(&cmdlineArgs.GlobFile, "globFile", "build-globs.ninja", "the Ninja file of globs to output")
- flag.StringVar(&cmdlineArgs.GlobListDir, "globListDir", "", "the directory containing the glob list files")
+ flag.StringVar(&globFile, "globFile", "build-globs.ninja", "the Ninja file of globs to output")
+ flag.StringVar(&globListDir, "globListDir", "", "the directory containing the glob list files")
flag.StringVar(&cmdlineArgs.BuildDir, "b", ".", "the build output directory")
flag.StringVar(&cmdlineArgs.NinjaBuildDir, "n", "", "the ninja builddir directory")
flag.StringVar(&cmdlineArgs.DepFile, "d", "", "the dependency file to output")
@@ -143,6 +145,10 @@
secondArgs = cmdlineArgs
ninjaDeps := bootstrap.RunBlueprint(secondArgs, secondCtx.Context, secondConfig)
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
+
+ globListFiles := writeBuildGlobsNinjaFile(secondCtx.SrcDir(), configuration.BuildDir(), secondCtx.Globs, configuration)
+ ninjaDeps = append(ninjaDeps, globListFiles...)
+
err = deptools.WriteDepFile(shared.JoinPath(topDir, secondArgs.DepFile), secondArgs.OutFile, ninjaDeps)
if err != nil {
fmt.Fprintf(os.Stderr, "Error writing depfile '%s': %s\n", secondArgs.DepFile, err)
@@ -191,6 +197,17 @@
writeFakeNinjaFile(extraNinjaDeps, configuration.BuildDir())
}
+func writeBuildGlobsNinjaFile(srcDir, buildDir string, globs func() pathtools.MultipleGlobResults, config interface{}) []string {
+ globDir := bootstrap.GlobDirectory(buildDir, globListDir)
+ bootstrap.WriteBuildGlobsNinjaFile(&bootstrap.GlobSingleton{
+ GlobLister: globs,
+ GlobFile: globFile,
+ GlobDir: globDir,
+ SrcDir: srcDir,
+ }, config)
+ return bootstrap.GlobFileListFiles(globDir)
+}
+
// doChosenActivity runs Soong for a specific activity, like bp2build, queryview
// or the actual Soong build for the build.ninja file. Returns the top level
// output file of the specific activity.
@@ -215,6 +232,10 @@
} else {
ninjaDeps := bootstrap.RunBlueprint(blueprintArgs, ctx.Context, configuration)
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
+
+ globListFiles := writeBuildGlobsNinjaFile(ctx.SrcDir(), configuration.BuildDir(), ctx.Globs, configuration)
+ ninjaDeps = append(ninjaDeps, globListFiles...)
+
err := deptools.WriteDepFile(shared.JoinPath(topDir, blueprintArgs.DepFile), blueprintArgs.OutFile, ninjaDeps)
if err != nil {
fmt.Fprintf(os.Stderr, "Error writing depfile '%s': %s\n", blueprintArgs.DepFile, err)
@@ -484,13 +505,8 @@
ninjaDeps := bootstrap.RunBlueprint(blueprintArgs, bp2buildCtx.Context, configuration)
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
- // Generate out/soong/.bootstrap/build-globs.ninja with the actions to generate flattened globfiles
- // containing the globs seen during bp2build conversion
- if blueprintArgs.GlobFile != "" {
- bootstrap.WriteBuildGlobsNinjaFile(blueprintArgs.GlobListDir, bp2buildCtx.Context, blueprintArgs, configuration)
- }
- // Add the depfile on the expanded globs in out/soong/.primary/globs
- ninjaDeps = append(ninjaDeps, bootstrap.GlobFileListFiles(configuration, blueprintArgs.GlobListDir)...)
+ globListFiles := writeBuildGlobsNinjaFile(bp2buildCtx.SrcDir(), configuration.BuildDir(), bp2buildCtx.Globs, configuration)
+ ninjaDeps = append(ninjaDeps, globListFiles...)
// Run the code-generation phase to convert BazelTargetModules to BUILD files
// and print conversion metrics to the user.
diff --git a/dexpreopt/class_loader_context.go b/dexpreopt/class_loader_context.go
index ebb8959..1bdd040 100644
--- a/dexpreopt/class_loader_context.go
+++ b/dexpreopt/class_loader_context.go
@@ -196,6 +196,10 @@
// If the library is optional or required.
Optional bool
+ // If the library is implicitly infered by Soong (as opposed to explicitly added via `uses_libs`
+ // or `optional_uses_libs`.
+ Implicit bool
+
// On-host build path to the library dex file (used in dex2oat argument --class-loader-context).
Host android.Path
@@ -258,8 +262,9 @@
const AnySdkVersion int = android.FutureApiLevelInt
// Add class loader context for the given library to the map entry for the given SDK version.
-func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathContext, sdkVer int, lib string,
- optional bool, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) error {
+func (clcMap ClassLoaderContextMap) addContext(ctx android.ModuleInstallPathContext, sdkVer int,
+ lib string, optional, implicit bool, hostPath, installPath android.Path,
+ nestedClcMap ClassLoaderContextMap) error {
// For prebuilts, library should have the same name as the source module.
lib = android.RemoveOptionalPrebuiltPrefix(lib)
@@ -308,6 +313,7 @@
clcMap[sdkVer] = append(clcMap[sdkVer], &ClassLoaderContext{
Name: lib,
Optional: optional,
+ Implicit: implicit,
Host: hostPath,
Device: devicePath,
Subcontexts: subcontexts,
@@ -320,9 +326,10 @@
// about paths). For the subset of libraries that are used in dexpreopt, their build/install paths
// are validated later before CLC is used (in validateClassLoaderContext).
func (clcMap ClassLoaderContextMap) AddContext(ctx android.ModuleInstallPathContext, sdkVer int,
- lib string, optional bool, hostPath, installPath android.Path, nestedClcMap ClassLoaderContextMap) {
+ lib string, optional, implicit bool, hostPath, installPath android.Path,
+ nestedClcMap ClassLoaderContextMap) {
- err := clcMap.addContext(ctx, sdkVer, lib, optional, hostPath, installPath, nestedClcMap)
+ err := clcMap.addContext(ctx, sdkVer, lib, optional, implicit, hostPath, installPath, nestedClcMap)
if err != nil {
ctx.ModuleErrorf(err.Error())
}
@@ -366,13 +373,15 @@
// included). This is the list of libraries that should be in the <uses-library> tags in the
// manifest. Some of them may be present in the source manifest, others are added by manifest_fixer.
// Required and optional libraries are in separate lists.
-func (clcMap ClassLoaderContextMap) UsesLibs() (required []string, optional []string) {
+func (clcMap ClassLoaderContextMap) usesLibs(implicit bool) (required []string, optional []string) {
if clcMap != nil {
clcs := clcMap[AnySdkVersion]
required = make([]string, 0, len(clcs))
optional = make([]string, 0, len(clcs))
for _, clc := range clcs {
- if clc.Optional {
+ if implicit && !clc.Implicit {
+ // Skip, this is an explicit library and we need only the implicit ones.
+ } else if clc.Optional {
optional = append(optional, clc.Name)
} else {
required = append(required, clc.Name)
@@ -382,6 +391,14 @@
return required, optional
}
+func (clcMap ClassLoaderContextMap) UsesLibs() ([]string, []string) {
+ return clcMap.usesLibs(false)
+}
+
+func (clcMap ClassLoaderContextMap) ImplicitUsesLibs() ([]string, []string) {
+ return clcMap.usesLibs(true)
+}
+
func (clcMap ClassLoaderContextMap) Dump() string {
jsonCLC := toJsonClassLoaderContext(clcMap)
bytes, err := json.MarshalIndent(jsonCLC, "", " ")
@@ -524,6 +541,8 @@
// the same as Soong representation except that SDK versions and paths are represented with strings.
type jsonClassLoaderContext struct {
Name string
+ Optional bool
+ Implicit bool
Host string
Device string
Subcontexts []*jsonClassLoaderContext
@@ -555,6 +574,8 @@
for _, clc := range jClcs {
clcs = append(clcs, &ClassLoaderContext{
Name: clc.Name,
+ Optional: clc.Optional,
+ Implicit: clc.Implicit,
Host: constructPath(ctx, clc.Host),
Device: clc.Device,
Subcontexts: fromJsonClassLoaderContextRec(ctx, clc.Subcontexts),
@@ -579,6 +600,8 @@
for i, clc := range clcs {
jClcs[i] = &jsonClassLoaderContext{
Name: clc.Name,
+ Optional: clc.Optional,
+ Implicit: clc.Implicit,
Host: clc.Host.String(),
Device: clc.Device,
Subcontexts: toJsonClassLoaderContextRec(clc.Subcontexts),
diff --git a/dexpreopt/class_loader_context_test.go b/dexpreopt/class_loader_context_test.go
index 0b7b546..d81ac2c 100644
--- a/dexpreopt/class_loader_context_test.go
+++ b/dexpreopt/class_loader_context_test.go
@@ -50,33 +50,34 @@
ctx := testContext()
optional := false
+ implicit := true
m := make(ClassLoaderContextMap)
- m.AddContext(ctx, AnySdkVersion, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
- m.AddContext(ctx, AnySdkVersion, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
- m.AddContext(ctx, AnySdkVersion, "c", optional, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
+ m.AddContext(ctx, AnySdkVersion, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+ m.AddContext(ctx, AnySdkVersion, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
+ m.AddContext(ctx, AnySdkVersion, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
// Add some libraries with nested subcontexts.
m1 := make(ClassLoaderContextMap)
- m1.AddContext(ctx, AnySdkVersion, "a1", optional, buildPath(ctx, "a1"), installPath(ctx, "a1"), nil)
- m1.AddContext(ctx, AnySdkVersion, "b1", optional, buildPath(ctx, "b1"), installPath(ctx, "b1"), nil)
+ m1.AddContext(ctx, AnySdkVersion, "a1", optional, implicit, buildPath(ctx, "a1"), installPath(ctx, "a1"), nil)
+ m1.AddContext(ctx, AnySdkVersion, "b1", optional, implicit, buildPath(ctx, "b1"), installPath(ctx, "b1"), nil)
m2 := make(ClassLoaderContextMap)
- m2.AddContext(ctx, AnySdkVersion, "a2", optional, buildPath(ctx, "a2"), installPath(ctx, "a2"), nil)
- m2.AddContext(ctx, AnySdkVersion, "b2", optional, buildPath(ctx, "b2"), installPath(ctx, "b2"), nil)
- m2.AddContext(ctx, AnySdkVersion, "c2", optional, buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)
+ m2.AddContext(ctx, AnySdkVersion, "a2", optional, implicit, buildPath(ctx, "a2"), installPath(ctx, "a2"), nil)
+ m2.AddContext(ctx, AnySdkVersion, "b2", optional, implicit, buildPath(ctx, "b2"), installPath(ctx, "b2"), nil)
+ m2.AddContext(ctx, AnySdkVersion, "c2", optional, implicit, buildPath(ctx, "c2"), installPath(ctx, "c2"), m1)
m3 := make(ClassLoaderContextMap)
- m3.AddContext(ctx, AnySdkVersion, "a3", optional, buildPath(ctx, "a3"), installPath(ctx, "a3"), nil)
- m3.AddContext(ctx, AnySdkVersion, "b3", optional, buildPath(ctx, "b3"), installPath(ctx, "b3"), nil)
+ m3.AddContext(ctx, AnySdkVersion, "a3", optional, implicit, buildPath(ctx, "a3"), installPath(ctx, "a3"), nil)
+ m3.AddContext(ctx, AnySdkVersion, "b3", optional, implicit, buildPath(ctx, "b3"), installPath(ctx, "b3"), nil)
- m.AddContext(ctx, AnySdkVersion, "d", optional, buildPath(ctx, "d"), installPath(ctx, "d"), m2)
+ m.AddContext(ctx, AnySdkVersion, "d", optional, implicit, buildPath(ctx, "d"), installPath(ctx, "d"), m2)
// When the same library is both in conditional and unconditional context, it should be removed
// from conditional context.
- m.AddContext(ctx, 42, "f", optional, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
- m.AddContext(ctx, AnySdkVersion, "f", optional, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
+ m.AddContext(ctx, 42, "f", optional, implicit, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
+ m.AddContext(ctx, AnySdkVersion, "f", optional, implicit, buildPath(ctx, "f"), installPath(ctx, "f"), nil)
// Merge map with implicit root library that is among toplevel contexts => does nothing.
m.AddContextMap(m1, "c")
@@ -85,12 +86,12 @@
m.AddContextMap(m3, "m_g")
// Compatibility libraries with unknown install paths get default paths.
- m.AddContext(ctx, 29, AndroidHidlManager, optional, buildPath(ctx, AndroidHidlManager), nil, nil)
- m.AddContext(ctx, 29, AndroidHidlBase, optional, buildPath(ctx, AndroidHidlBase), nil, nil)
+ m.AddContext(ctx, 29, AndroidHidlManager, optional, implicit, buildPath(ctx, AndroidHidlManager), nil, nil)
+ m.AddContext(ctx, 29, AndroidHidlBase, optional, implicit, buildPath(ctx, AndroidHidlBase), nil, nil)
// Add "android.test.mock" to conditional CLC, observe that is gets removed because it is only
// needed as a compatibility library if "android.test.runner" is in CLC as well.
- m.AddContext(ctx, 30, AndroidTestMock, optional, buildPath(ctx, AndroidTestMock), nil, nil)
+ m.AddContext(ctx, 30, AndroidTestMock, optional, implicit, buildPath(ctx, AndroidTestMock), nil, nil)
valid, validationError := validateClassLoaderContext(m)
@@ -164,11 +165,12 @@
func TestCLCJson(t *testing.T) {
ctx := testContext()
optional := false
+ implicit := true
m := make(ClassLoaderContextMap)
- m.AddContext(ctx, 28, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
- m.AddContext(ctx, 29, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
- m.AddContext(ctx, 30, "c", optional, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
- m.AddContext(ctx, AnySdkVersion, "d", optional, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
+ m.AddContext(ctx, 28, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+ m.AddContext(ctx, 29, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
+ m.AddContext(ctx, 30, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
+ m.AddContext(ctx, AnySdkVersion, "d", optional, implicit, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
jsonCLC := toJsonClassLoaderContext(m)
restored := fromJsonClassLoaderContext(ctx, jsonCLC)
android.AssertIntEquals(t, "The size of the maps should be the same.", len(m), len(restored))
@@ -189,12 +191,13 @@
func testCLCUnknownPath(t *testing.T, whichPath string) {
ctx := testContext()
optional := false
+ implicit := true
m := make(ClassLoaderContextMap)
if whichPath == "build" {
- m.AddContext(ctx, AnySdkVersion, "a", optional, nil, nil, nil)
+ m.AddContext(ctx, AnySdkVersion, "a", optional, implicit, nil, nil, nil)
} else {
- m.AddContext(ctx, AnySdkVersion, "a", optional, buildPath(ctx, "a"), nil, nil)
+ m.AddContext(ctx, AnySdkVersion, "a", optional, implicit, buildPath(ctx, "a"), nil, nil)
}
// The library should be added to <uses-library> tags by the manifest_fixer.
@@ -229,10 +232,11 @@
func TestCLCNestedConditional(t *testing.T) {
ctx := testContext()
optional := false
+ implicit := true
m1 := make(ClassLoaderContextMap)
- m1.AddContext(ctx, 42, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+ m1.AddContext(ctx, 42, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
m := make(ClassLoaderContextMap)
- err := m.addContext(ctx, AnySdkVersion, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), m1)
+ err := m.addContext(ctx, AnySdkVersion, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), m1)
checkError(t, err, "nested class loader context shouldn't have conditional part")
}
@@ -241,11 +245,12 @@
func TestCLCSdkVersionOrder(t *testing.T) {
ctx := testContext()
optional := false
+ implicit := true
m := make(ClassLoaderContextMap)
- m.AddContext(ctx, 28, "a", optional, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
- m.AddContext(ctx, 29, "b", optional, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
- m.AddContext(ctx, 30, "c", optional, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
- m.AddContext(ctx, AnySdkVersion, "d", optional, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
+ m.AddContext(ctx, 28, "a", optional, implicit, buildPath(ctx, "a"), installPath(ctx, "a"), nil)
+ m.AddContext(ctx, 29, "b", optional, implicit, buildPath(ctx, "b"), installPath(ctx, "b"), nil)
+ m.AddContext(ctx, 30, "c", optional, implicit, buildPath(ctx, "c"), installPath(ctx, "c"), nil)
+ m.AddContext(ctx, AnySdkVersion, "d", optional, implicit, buildPath(ctx, "d"), installPath(ctx, "d"), nil)
valid, validationError := validateClassLoaderContext(m)
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 4c6ae82..1401c75 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -430,11 +430,6 @@
}
}
- // Never enable on eng.
- if global.IsEng {
- debugInfo = false
- }
-
if debugInfo {
cmd.Flag("--generate-mini-debug-info")
} else {
diff --git a/java/android_manifest.go b/java/android_manifest.go
index 1f7234d..38065f1 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -71,7 +71,9 @@
args = append(args, "--use-embedded-dex")
}
- requiredUsesLibs, optionalUsesLibs := classLoaderContexts.UsesLibs()
+ // manifest_fixer should add only the implicit SDK libraries inferred by Soong, not those added
+ // explicitly via `uses_libs`/`optional_uses_libs`.
+ requiredUsesLibs, optionalUsesLibs := classLoaderContexts.ImplicitUsesLibs()
for _, usesLib := range requiredUsesLibs {
args = append(args, "--uses-library", usesLib)
}
diff --git a/java/app.go b/java/app.go
index e7661df..5104f07 100755
--- a/java/app.go
+++ b/java/app.go
@@ -1224,17 +1224,28 @@
func (u *usesLibrary) deps(ctx android.BottomUpMutatorContext, hasFrameworkLibs bool) {
if !ctx.Config().UnbundledBuild() || ctx.Config().UnbundledBuildImage() {
- ctx.AddVariationDependencies(nil, usesLibReqTag, u.usesLibraryProperties.Uses_libs...)
- ctx.AddVariationDependencies(nil, usesLibOptTag, u.presentOptionalUsesLibs(ctx)...)
+ reqTag := makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false, false)
+ ctx.AddVariationDependencies(nil, reqTag, u.usesLibraryProperties.Uses_libs...)
+
+ optTag := makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true, false)
+ ctx.AddVariationDependencies(nil, optTag, u.presentOptionalUsesLibs(ctx)...)
+
// Only add these extra dependencies if the module depends on framework libs. This avoids
// creating a cyclic dependency:
// e.g. framework-res -> org.apache.http.legacy -> ... -> framework-res.
if hasFrameworkLibs {
- // Dexpreopt needs paths to the dex jars of these libraries in order to construct
- // class loader context for dex2oat. Add them as a dependency with a special tag.
- ctx.AddVariationDependencies(nil, usesLibCompat29ReqTag, dexpreopt.CompatUsesLibs29...)
- ctx.AddVariationDependencies(nil, usesLibCompat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)
- ctx.AddVariationDependencies(nil, usesLibCompat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
+ // Add implicit <uses-library> dependencies on compatibility libraries. Some of them are
+ // optional, and some required --- this depends on the most common usage of the library
+ // and may be wrong for some apps (they need explicit `uses_libs`/`optional_uses_libs`).
+
+ compat28OptTag := makeUsesLibraryDependencyTag(28, true, true)
+ ctx.AddVariationDependencies(nil, compat28OptTag, dexpreopt.OptionalCompatUsesLibs28...)
+
+ compat29ReqTag := makeUsesLibraryDependencyTag(29, false, true)
+ ctx.AddVariationDependencies(nil, compat29ReqTag, dexpreopt.CompatUsesLibs29...)
+
+ compat30OptTag := makeUsesLibraryDependencyTag(30, true, true)
+ ctx.AddVariationDependencies(nil, compat30OptTag, dexpreopt.OptionalCompatUsesLibs30...)
}
}
}
@@ -1293,7 +1304,7 @@
replaceInList(u.usesLibraryProperties.Uses_libs, dep, libName)
replaceInList(u.usesLibraryProperties.Optional_uses_libs, dep, libName)
}
- clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional,
+ clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional, tag.implicit,
lib.DexJarBuildPath(), lib.DexJarInstallPath(), lib.ClassLoaderContexts())
} else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{dep})
diff --git a/java/app_test.go b/java/app_test.go
index 8de6691..56ad28d 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -2285,6 +2285,49 @@
sdk_version: "current",
}
+ java_library {
+ name: "runtime-required-x",
+ srcs: ["a.java"],
+ installable: true,
+ sdk_version: "current",
+ }
+
+ java_library {
+ name: "runtime-optional-x",
+ srcs: ["a.java"],
+ installable: true,
+ sdk_version: "current",
+ }
+
+ android_library {
+ name: "static-x",
+ uses_libs: ["runtime-required-x"],
+ optional_uses_libs: ["runtime-optional-x"],
+ sdk_version: "current",
+ }
+
+ java_library {
+ name: "runtime-required-y",
+ srcs: ["a.java"],
+ installable: true,
+ sdk_version: "current",
+ }
+
+ java_library {
+ name: "runtime-optional-y",
+ srcs: ["a.java"],
+ installable: true,
+ sdk_version: "current",
+ }
+
+ java_library {
+ name: "static-y",
+ srcs: ["a.java"],
+ uses_libs: ["runtime-required-y"],
+ optional_uses_libs: ["runtime-optional-y"],
+ sdk_version: "current",
+ }
+
// A library that has to use "provides_uses_lib", because:
// - it is not an SDK library
// - its library name is different from its module name
@@ -2307,6 +2350,8 @@
// statically linked component libraries should not pull their SDK libraries,
// so "fred" should not be added to class loader context
"fred.stubs",
+ "static-x",
+ "static-y",
],
uses_libs: [
"foo",
@@ -2353,10 +2398,7 @@
expectManifestFixerArgs := `--extract-native-libs=true ` +
`--uses-library qux ` +
`--uses-library quuz ` +
- `--uses-library foo ` + // TODO(b/132357300): "foo" should not be passed to manifest_fixer
- `--uses-library com.non.sdk.lib ` + // TODO(b/132357300): "com.non.sdk.lib" should not be passed to manifest_fixer
- `--uses-library runtime-library ` +
- `--optional-uses-library bar` // TODO(b/132357300): "bar" should not be passed to manifest_fixer
+ `--uses-library runtime-library`
android.AssertStringEquals(t, "manifest_fixer args", expectManifestFixerArgs, actualManifestFixerArgs)
// Test that all libraries are verified (library order matters).
@@ -2366,8 +2408,12 @@
`--uses-library qux ` +
`--uses-library quuz ` +
`--uses-library runtime-library ` +
+ `--uses-library runtime-required-x ` +
+ `--uses-library runtime-required-y ` +
`--optional-uses-library bar ` +
- `--optional-uses-library baz `
+ `--optional-uses-library baz ` +
+ `--optional-uses-library runtime-optional-x ` +
+ `--optional-uses-library runtime-optional-y `
android.AssertStringDoesContain(t, "verify cmd args", verifyCmd, verifyArgs)
// Test that all libraries are verified for an APK (library order matters).
@@ -2387,7 +2433,11 @@
`PCL[/system/framework/foo.jar]#` +
`PCL[/system/framework/non-sdk-lib.jar]#` +
`PCL[/system/framework/bar.jar]#` +
- `PCL[/system/framework/runtime-library.jar]`
+ `PCL[/system/framework/runtime-library.jar]#` +
+ `PCL[/system/framework/runtime-required-x.jar]#` +
+ `PCL[/system/framework/runtime-optional-x.jar]#` +
+ `PCL[/system/framework/runtime-required-y.jar]#` +
+ `PCL[/system/framework/runtime-optional-y.jar] `
android.AssertStringDoesContain(t, "dexpreopt app cmd args", cmd, w)
// Test conditional context for target SDK version 28.
diff --git a/java/base.go b/java/base.go
index ea5b137..8e6d1cd 100644
--- a/java/base.go
+++ b/java/base.go
@@ -606,10 +606,8 @@
if component, ok := dep.(SdkLibraryComponentDependency); ok {
if lib := component.OptionalSdkLibraryImplementation(); lib != nil {
// Add library as optional if it's one of the optional compatibility libs.
- tag := usesLibReqTag
- if android.InList(*lib, dexpreopt.OptionalCompatUsesLibs) {
- tag = usesLibOptTag
- }
+ optional := android.InList(*lib, dexpreopt.OptionalCompatUsesLibs)
+ tag := makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, optional, true)
ctx.AddVariationDependencies(nil, tag, *lib)
}
}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index bb542c4..7577316 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -538,7 +538,7 @@
global := dexpreopt.GetGlobalConfig(ctx)
possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, b.properties.Contents, bootclasspathFragmentContentDepTag)
- jars := global.ApexBootJars.Filter(possibleUpdatableModules)
+ jars, unknown := global.ApexBootJars.Filter(possibleUpdatableModules)
// TODO(satayev): for apex_test we want to include all contents unconditionally to classpaths
// config. However, any test specific jars would not be present in ApexBootJars. Instead,
@@ -546,6 +546,12 @@
// This is an exception to support end-to-end test for SdkExtensions, until such support exists.
if android.InList("test_framework-sdkextensions", possibleUpdatableModules) {
jars = jars.Append("com.android.sdkext", "test_framework-sdkextensions")
+ } else if global.ApexBootJars.Len() != 0 && !android.IsModuleInVersionedSdk(ctx.Module()) {
+ unknown = android.RemoveListFromList(unknown, b.properties.Coverage.Contents)
+ _, unknown = android.RemoveFromList("core-icu4j", unknown)
+ if len(unknown) > 0 {
+ ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown)
+ }
}
return jars
}
diff --git a/java/java.go b/java/java.go
index 5bf3d79..4c2ca9b 100644
--- a/java/java.go
+++ b/java/java.go
@@ -248,15 +248,24 @@
type usesLibraryDependencyTag struct {
dependencyTag
- sdkVersion int // SDK version in which the library appared as a standalone library.
- optional bool // If the dependency is optional or required.
+
+ // SDK version in which the library appared as a standalone library.
+ sdkVersion int
+
+ // If the dependency is optional or required.
+ optional bool
+
+ // Whether this is an implicit dependency inferred by Soong, or an explicit one added via
+ // `uses_libs`/`optional_uses_libs` properties.
+ implicit bool
}
-func makeUsesLibraryDependencyTag(sdkVersion int, optional bool) usesLibraryDependencyTag {
+func makeUsesLibraryDependencyTag(sdkVersion int, optional bool, implicit bool) usesLibraryDependencyTag {
return usesLibraryDependencyTag{
dependencyTag: dependencyTag{name: fmt.Sprintf("uses-library-%d", sdkVersion)},
sdkVersion: sdkVersion,
optional: optional,
+ implicit: implicit,
}
}
@@ -285,11 +294,6 @@
syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
jniInstallTag = installDependencyTag{name: "jni install"}
binaryInstallTag = installDependencyTag{name: "binary install"}
- usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false)
- usesLibOptTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, true)
- usesLibCompat28OptTag = makeUsesLibraryDependencyTag(28, true)
- usesLibCompat29ReqTag = makeUsesLibraryDependencyTag(29, false)
- usesLibCompat30OptTag = makeUsesLibraryDependencyTag(30, true)
)
func IsLibDepTag(depTag blueprint.DependencyTag) bool {
@@ -511,7 +515,7 @@
j.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, &j.dexpreopter))
}
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
- j.classLoaderContexts = make(dexpreopt.ClassLoaderContextMap)
+ j.classLoaderContexts = j.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
j.compile(ctx, nil)
// Collect the module directory for IDE info in java/jdeps.go.
@@ -530,6 +534,7 @@
func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
j.deps(ctx)
+ j.usesLibrary.deps(ctx, false)
}
const (
@@ -1812,8 +1817,10 @@
depTag := ctx.OtherModuleDependencyTag(depModule)
if depTag == libTag {
// Ok, propagate <uses-library> through non-static library dependencies.
- } else if tag, ok := depTag.(usesLibraryDependencyTag); ok && tag.sdkVersion == dexpreopt.AnySdkVersion {
- // Ok, propagate <uses-library> through non-compatibility <uses-library> dependencies.
+ } else if tag, ok := depTag.(usesLibraryDependencyTag); ok &&
+ tag.sdkVersion == dexpreopt.AnySdkVersion && tag.implicit {
+ // Ok, propagate <uses-library> through non-compatibility implicit <uses-library>
+ // dependencies.
} else if depTag == staticLibTag {
// Propagate <uses-library> through static library dependencies, unless it is a component
// library (such as stubs). Component libraries have a dependency on their SDK library,
@@ -1831,7 +1838,7 @@
// <uses_library> and should not be added to CLC, but the transitive <uses-library> dependencies
// from its CLC should be added to the current CLC.
if sdkLib != nil {
- clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false,
+ clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false, true,
dep.DexJarBuildPath(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
} else {
clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index eeec504..938bb28 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -157,7 +157,7 @@
qux := result.ModuleForTests("qux", "android_common")
if quxLib, ok := qux.Module().(*Library); ok {
requiredSdkLibs, optionalSdkLibs := quxLib.ClassLoaderContexts().UsesLibs()
- android.AssertDeepEquals(t, "qux exports (required)", []string{"foo", "bar", "fred", "quuz"}, requiredSdkLibs)
+ android.AssertDeepEquals(t, "qux exports (required)", []string{"fred", "quuz", "foo", "bar"}, requiredSdkLibs)
android.AssertDeepEquals(t, "qux exports (optional)", []string{}, optionalSdkLibs)
}
}
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 6c2a5b5..5311f62 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -107,7 +107,16 @@
global := dexpreopt.GetGlobalConfig(ctx)
possibleUpdatableModules := gatherPossibleApexModuleNamesAndStems(ctx, s.properties.Contents, systemServerClasspathFragmentContentDepTag)
- return global.ApexSystemServerJars.Filter(possibleUpdatableModules)
+ jars, unknown := global.ApexSystemServerJars.Filter(possibleUpdatableModules)
+ // TODO(satayev): remove geotz ssc_fragment, since geotz is not part of SSCP anymore.
+ _, unknown = android.RemoveFromList("geotz", unknown)
+
+ // For non test apexes, make sure that all contents are actually declared in make.
+ if global.ApexSystemServerJars.Len() > 0 && len(unknown) > 0 {
+ ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_UPDATABLE_SYSTEM_SERVER_JARS", unknown)
+ }
+
+ return jars
}
type systemServerClasspathFragmentContentDependencyTag struct {
diff --git a/python/library.go b/python/library.go
index 9663b3c..c255190 100644
--- a/python/library.go
+++ b/python/library.go
@@ -17,11 +17,16 @@
// This file contains the module types for building Python library.
import (
+ "fmt"
+
"android/soong/android"
+ "android/soong/bazel"
+ "github.com/google/blueprint/proptools"
)
func init() {
registerPythonLibraryComponents(android.InitRegistrationContext)
+ android.RegisterBp2BuildMutator("python_library", PythonLibraryBp2Build)
}
func registerPythonLibraryComponents(ctx android.RegistrationContext) {
@@ -35,8 +40,63 @@
return module.init()
}
+type bazelPythonLibraryAttributes struct {
+ Srcs bazel.LabelListAttribute
+ Data bazel.LabelListAttribute
+ Srcs_version string
+}
+
+func PythonLibraryBp2Build(ctx android.TopDownMutatorContext) {
+ m, ok := ctx.Module().(*Module)
+ if !ok || !m.ConvertWithBp2build(ctx) {
+ return
+ }
+
+ // a Module can be something other than a python_library
+ if ctx.ModuleType() != "python_library" {
+ return
+ }
+
+ // TODO(b/182306917): this doesn't fully handle all nested props versioned
+ // by the python version, which would have been handled by the version split
+ // mutator. This is sufficient for very simple python_library modules under
+ // Bionic.
+ py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, true)
+ py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
+ var python_version string
+ if py2Enabled && !py3Enabled {
+ python_version = "PY2"
+ } else if !py2Enabled && py3Enabled {
+ python_version = "PY3"
+ } else if !py2Enabled && !py3Enabled {
+ panic(fmt.Errorf(
+ "error for '%s' module: bp2build's python_library converter doesn't understand having "+
+ "neither py2 nor py3 enabled", m.Name()))
+ } else {
+ // do nothing, since python_version defaults to PY2ANDPY3
+ }
+
+ srcs := android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
+ data := android.BazelLabelForModuleSrc(ctx, m.properties.Data)
+
+ attrs := &bazelPythonLibraryAttributes{
+ Srcs: bazel.MakeLabelListAttribute(srcs),
+ Data: bazel.MakeLabelListAttribute(data),
+ Srcs_version: python_version,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ // Use the native py_library rule.
+ Rule_class: "py_library",
+ }
+
+ ctx.CreateBazelTargetModule(m.Name(), props, attrs)
+}
+
func PythonLibraryFactory() android.Module {
module := newModule(android.HostAndDeviceSupported, android.MultilibBoth)
+ android.InitBazelModule(module)
+
return module.init()
}
diff --git a/python/python.go b/python/python.go
index 0f5b788..83844e6 100644
--- a/python/python.go
+++ b/python/python.go
@@ -675,7 +675,7 @@
if !isPythonLibModule(child) {
ctx.PropertyErrorf("libs",
"the dependency %q of module %q is not Python library!",
- ctx.ModuleName(), ctx.OtherModuleName(child))
+ ctx.OtherModuleName(child), ctx.ModuleName())
}
// collect source and data paths, checking that there are no duplicate output file conflicts
if dep, ok := child.(pythonDependency); ok {
diff --git a/rust/compiler.go b/rust/compiler.go
index d9e21ff..7bd9af4 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -397,8 +397,15 @@
}
if compiler.location == InstallInData && ctx.RustModule().UseVndk() {
- dir = filepath.Join(dir, "vendor")
+ if ctx.RustModule().InProduct() {
+ dir = filepath.Join(dir, "product")
+ } else if ctx.RustModule().InVendor() {
+ dir = filepath.Join(dir, "vendor")
+ } else {
+ ctx.ModuleErrorf("Unknown data+VNDK installation kind")
+ }
}
+
return android.PathForModuleInstall(ctx, dir, compiler.subDir,
compiler.relativeInstallPath(), compiler.relative)
}
diff --git a/rust/config/allowed_list.go b/rust/config/allowed_list.go
index 926d2ac..ee9be6e 100644
--- a/rust/config/allowed_list.go
+++ b/rust/config/allowed_list.go
@@ -25,6 +25,7 @@
"system/extras/simpleperf",
"system/hardware/interfaces/keystore2",
"system/librustutils",
+ "system/logging/liblog",
"system/logging/rust",
"system/security",
"system/tools/aidl",
diff --git a/rust/doc.go b/rust/doc.go
index e7f1371..fe3581b 100644
--- a/rust/doc.go
+++ b/rust/doc.go
@@ -29,6 +29,14 @@
type rustdocSingleton struct{}
func (n *rustdocSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ docDir := android.PathForOutput(ctx, "rustdoc")
+ docZip := android.PathForOutput(ctx, "rustdoc.zip")
+ rule := android.NewRuleBuilder(pctx, ctx)
+ zipCmd := rule.Command().BuiltTool("soong_zip").
+ FlagWithOutput("-o ", docZip).
+ FlagWithArg("-C ", docDir.String()).
+ FlagWithArg("-D ", docDir.String())
+
ctx.VisitAllModules(func(module android.Module) {
if !module.Enabled() {
return
@@ -36,8 +44,10 @@
if m, ok := module.(*Module); ok {
if m.docTimestampFile.Valid() {
- ctx.Phony("rustdoc", m.docTimestampFile.Path())
+ zipCmd.Implicit(m.docTimestampFile.Path())
}
}
})
+ rule.Build("rustdoc-zip", "Zipping all built Rust documentation...")
+ ctx.Phony("rustdoc", docZip)
}
diff --git a/rust/image.go b/rust/image.go
index 3b54f12..5d57f15 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -34,11 +34,11 @@
}
func (mod *Module) ProductAvailable() bool {
- return false
+ return Bool(mod.VendorProperties.Product_available)
}
func (mod *Module) RamdiskAvailable() bool {
- return false
+ return Bool(mod.Properties.Ramdisk_available)
}
func (mod *Module) VendorRamdiskAvailable() bool {
@@ -50,7 +50,7 @@
}
func (mod *Module) RecoveryAvailable() bool {
- return false
+ return Bool(mod.Properties.Recovery_available)
}
func (mod *Module) ExtraVariants() []string {
@@ -62,9 +62,7 @@
}
func (mod *Module) SetRamdiskVariantNeeded(b bool) {
- if b {
- panic("Setting ramdisk variant needed for Rust module is unsupported: " + mod.BaseModuleName())
- }
+ mod.Properties.RamdiskVariantNeeded = b
}
func (mod *Module) SetVendorRamdiskVariantNeeded(b bool) {
@@ -72,9 +70,7 @@
}
func (mod *Module) SetRecoveryVariantNeeded(b bool) {
- if b {
- panic("Setting recovery variant needed for Rust module is unsupported: " + mod.BaseModuleName())
- }
+ mod.Properties.RecoveryVariantNeeded = b
}
func (mod *Module) SetCoreVariantNeeded(b bool) {
@@ -99,7 +95,7 @@
}
func (mod *Module) RamdiskVariantNeeded(android.BaseModuleContext) bool {
- return mod.InRamdisk()
+ return mod.Properties.RamdiskVariantNeeded
}
func (mod *Module) DebugRamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
@@ -107,7 +103,7 @@
}
func (mod *Module) RecoveryVariantNeeded(android.BaseModuleContext) bool {
- return mod.InRecovery()
+ return mod.Properties.RecoveryVariantNeeded
}
func (mod *Module) ExtraImageVariations(android.BaseModuleContext) []string {
@@ -140,12 +136,17 @@
}
func (ctx *moduleContext) ProductSpecific() bool {
- return false
+ return ctx.ModuleContext.ProductSpecific() || ctx.RustModule().productSpecificModuleContext()
+}
+
+func (c *Module) productSpecificModuleContext() bool {
+ // Additionally check if this module is inProduct() that means it is a "product" variant of a
+ // module. As well as product specific modules, product variants must be installed to /product.
+ return c.InProduct()
}
func (mod *Module) InRecovery() bool {
- // TODO(b/165791368)
- return false
+ return mod.ModuleBase.InRecovery() || mod.ModuleBase.InstallInRecovery()
}
func (mod *Module) InVendorRamdisk() bool {
@@ -166,6 +167,11 @@
return false
}
+func (mod *Module) OnlyInProduct() bool {
+ //TODO(b/165791368)
+ return false
+}
+
// Returns true when this module is configured to have core and vendor variants.
func (mod *Module) HasVendorVariant() bool {
return Bool(mod.VendorProperties.Vendor_available) || Bool(mod.VendorProperties.Odm_available)
@@ -181,7 +187,7 @@
}
func (mod *Module) InProduct() bool {
- return false
+ return mod.Properties.ImageVariationPrefix == cc.ProductVariationPrefix
}
// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
@@ -193,6 +199,8 @@
m := module.(*Module)
if variant == android.VendorRamdiskVariation {
m.MakeAsPlatform()
+ } else if variant == android.RecoveryVariation {
+ m.MakeAsPlatform()
} else if strings.HasPrefix(variant, cc.VendorVariationPrefix) {
m.Properties.ImageVariationPrefix = cc.VendorVariationPrefix
m.Properties.VndkVersion = strings.TrimPrefix(variant, cc.VendorVariationPrefix)
@@ -204,6 +212,9 @@
m.Properties.HideFromMake = true
m.HideFromMake()
}
+ } else if strings.HasPrefix(variant, cc.ProductVariationPrefix) {
+ m.Properties.ImageVariationPrefix = cc.ProductVariationPrefix
+ m.Properties.VndkVersion = strings.TrimPrefix(variant, cc.ProductVariationPrefix)
}
}
@@ -211,10 +222,7 @@
// Rust does not support installing to the product image yet.
vendorSpecific := mctx.SocSpecific() || mctx.DeviceSpecific()
- if Bool(mod.VendorProperties.Product_available) {
- mctx.PropertyErrorf("product_available",
- "Rust modules do not yet support being available to the product image")
- } else if mctx.ProductSpecific() {
+ if mctx.ProductSpecific() {
mctx.PropertyErrorf("product_specific",
"Rust modules do not yet support installing to the product image.")
} else if Bool(mod.VendorProperties.Double_loadable) {
diff --git a/rust/rust.go b/rust/rust.go
index 4ceeef1..0cd299d 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -84,6 +84,8 @@
// Set by imageMutator
CoreVariantNeeded bool `blueprint:"mutated"`
VendorRamdiskVariantNeeded bool `blueprint:"mutated"`
+ RamdiskVariantNeeded bool `blueprint:"mutated"`
+ RecoveryVariantNeeded bool `blueprint:"mutated"`
ExtraVariants []string `blueprint:"mutated"`
// Allows this module to use non-APEX version of libraries. Useful
@@ -94,11 +96,18 @@
SnapshotSharedLibs []string `blueprint:"mutated"`
SnapshotStaticLibs []string `blueprint:"mutated"`
+ // Make this module available when building for ramdisk.
+ // On device without a dedicated recovery partition, the module is only
+ // available after switching root into
+ // /first_stage_ramdisk. To expose the module before switching root, install
+ // the recovery variant instead.
+ Ramdisk_available *bool
+
// Make this module available when building for vendor ramdisk.
// On device without a dedicated recovery partition, the module is only
// available after switching root into
// /first_stage_ramdisk. To expose the module before switching root, install
- // the recovery variant instead (TODO(b/165791368) recovery not yet supported)
+ // the recovery variant instead
Vendor_ramdisk_available *bool
// Normally Soong uses the directory structure to decide which modules
@@ -115,6 +124,9 @@
// framework module from the recovery snapshot.
Exclude_from_recovery_snapshot *bool
+ // Make this module available when building for recovery
+ Recovery_available *bool
+
// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
Min_sdk_version *string
@@ -762,6 +774,10 @@
}
func (mod *Module) nativeCoverage() bool {
+ // Bug: http://b/137883967 - native-bridge modules do not currently work with coverage
+ if mod.Target().NativeBridge == android.NativeBridgeEnabled {
+ return false
+ }
return mod.compiler != nil && mod.compiler.nativeCoverage()
}
@@ -804,9 +820,21 @@
// Differentiate static libraries that are vendor available
if mod.UseVndk() {
- mod.Properties.SubName += cc.VendorSuffix
+ if mod.InProduct() && !mod.OnlyInProduct() {
+ mod.Properties.SubName += cc.ProductSuffix
+ } else {
+ mod.Properties.SubName += cc.VendorSuffix
+ }
+ } else if mod.InRamdisk() && !mod.OnlyInRamdisk() {
+ mod.Properties.SubName += cc.RamdiskSuffix
} else if mod.InVendorRamdisk() && !mod.OnlyInVendorRamdisk() {
mod.Properties.SubName += cc.VendorRamdiskSuffix
+ } else if mod.InRecovery() && !mod.OnlyInRecovery() {
+ mod.Properties.SubName += cc.RecoverySuffix
+ }
+
+ if mod.Target().NativeBridge == android.NativeBridgeEnabled {
+ mod.Properties.SubName += cc.NativeBridgeSuffix
}
if !toolchain.Supported() {
@@ -1205,6 +1233,18 @@
return mod.compiler.inData()
}
+func (mod *Module) InstallInRamdisk() bool {
+ return mod.InRamdisk()
+}
+
+func (mod *Module) InstallInVendorRamdisk() bool {
+ return mod.InVendorRamdisk()
+}
+
+func (mod *Module) InstallInRecovery() bool {
+ return mod.InRecovery()
+}
+
func linkPathFromFilePath(filepath android.Path) string {
return strings.Split(filepath.String(), filepath.Base())[0]
}
diff --git a/scripts/build-rustdocs.sh b/scripts/build-rustdocs.sh
index ad8ba16..fda9688 100755
--- a/scripts/build-rustdocs.sh
+++ b/scripts/build-rustdocs.sh
@@ -27,5 +27,5 @@
if [ -n "${DIST_DIR}" ]; then
mkdir -p ${DIST_DIR}
- cp -r ${OUT_DIR}/soong/rustdoc $DIST_DIR/rustdoc
+ cp ${OUT_DIR}/soong/rustdoc.zip $DIST_DIR
fi
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index 9342d75..76b2ee9 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -477,7 +477,8 @@
run_soong
local mtime1=$(stat -c "%y" out/soong/build.ninja)
- prebuilts/build-tools/linux-x86/bin/ninja -f out/soong/build.ninja soong_docs
+ prebuilts/build-tools/linux-x86/bin/ninja -f out/combined.ninja soong_docs
+
run_soong
local mtime2=$(stat -c "%y" out/soong/build.ninja)