Merge changes I1ff171b9,Id64085d6
* changes:
Add an integration test for API export from another bazel package
Generate a BUILD file for every Android.bp file in api_bp2build workspace.
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index 63495bc..17db472 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -218,6 +218,7 @@
"hardware/interfaces": Bp2BuildDefaultTrue,
"hardware/interfaces/audio/aidl": Bp2BuildDefaultTrue,
+ "hardware/interfaces/audio/aidl/common": Bp2BuildDefaultTrue,
"hardware/interfaces/common/aidl": Bp2BuildDefaultTrue,
"hardware/interfaces/common/fmq/aidl": Bp2BuildDefaultTrue,
"hardware/interfaces/configstore/1.0": Bp2BuildDefaultTrue,
diff --git a/android/androidmk.go b/android/androidmk.go
index aa411d1..a7b69f6 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -560,6 +560,8 @@
a.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", base.katiSymlinks.InstallPaths().Paths())
}
+ a.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", base.commonProperties.SkipInstall)
+
if am, ok := mod.(ApexModule); ok {
a.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform())
}
diff --git a/android/apex.go b/android/apex.go
index 358818f..a0ac5b8 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -603,7 +603,7 @@
// Do not install the module for platform, but still allow it to output
// uninstallable AndroidMk entries in certain cases when they have side
// effects. TODO(jiyong): move this routine to somewhere else
- mod.MakeUninstallable()
+ mod.SkipInstall()
}
if !platformVariation {
mctx.SetVariationProvider(mod, ApexInfoProvider, apexInfos[i-1])
diff --git a/android/config.go b/android/config.go
index 07151f9..979f1ca 100644
--- a/android/config.go
+++ b/android/config.go
@@ -1759,6 +1759,10 @@
return c.config.productVariables.BuildBrokenTrebleSyspropNeverallow
}
+func (c *deviceConfig) BuildBrokenUsesSoongPython2Modules() bool {
+ return c.config.productVariables.BuildBrokenUsesSoongPython2Modules
+}
+
func (c *deviceConfig) BuildDebugfsRestrictionsEnabled() bool {
return c.config.productVariables.BuildDebugfsRestrictionsEnabled
}
diff --git a/android/module.go b/android/module.go
index 773d77b..b45ed95 100644
--- a/android/module.go
+++ b/android/module.go
@@ -505,8 +505,8 @@
PartitionTag(DeviceConfig) string
HideFromMake()
IsHideFromMake() bool
+ SkipInstall()
IsSkipInstall() bool
- MakeUninstallable()
ReplacedByPrebuilt()
IsReplacedByPrebuilt() bool
ExportedToMake() bool
@@ -1964,15 +1964,6 @@
return m.commonProperties.SkipInstall
}
-// Similar to HideFromMake, but if the AndroidMk entry would set
-// LOCAL_UNINSTALLABLE_MODULE then this variant may still output that entry
-// rather than leaving it out altogether. That happens in cases where it would
-// have other side effects, in particular when it adds a NOTICE file target,
-// which other install targets might depend on.
-func (m *ModuleBase) MakeUninstallable() {
- m.HideFromMake()
-}
-
func (m *ModuleBase) ReplacedByPrebuilt() {
m.commonProperties.ReplacedByPrebuilt = true
m.HideFromMake()
diff --git a/android/packaging_test.go b/android/packaging_test.go
index 91ac1f3..f32d1c3 100644
--- a/android/packaging_test.go
+++ b/android/packaging_test.go
@@ -15,6 +15,7 @@
package android
import (
+ "strings"
"testing"
"github.com/google/blueprint"
@@ -28,6 +29,8 @@
Deps []string
Skip_install *bool
}
+
+ builtFile Path
}
// dep tag used in this test. All dependencies are considered as installable.
@@ -48,13 +51,21 @@
}
func (m *componentTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
- builtFile := PathForModuleOut(ctx, m.Name())
+ m.builtFile = PathForModuleOut(ctx, m.Name())
dir := ctx.Target().Arch.ArchType.Multilib
installDir := PathForModuleInstall(ctx, dir)
if proptools.Bool(m.props.Skip_install) {
m.SkipInstall()
}
- ctx.InstallFile(installDir, m.Name(), builtFile)
+ ctx.InstallFile(installDir, m.Name(), m.builtFile)
+}
+
+func (m *componentTestModule) AndroidMkEntries() []AndroidMkEntries {
+ return []AndroidMkEntries{
+ {
+ OutputFile: OptionalPathForPath(m.builtFile),
+ },
+ }
}
// Module that itself is a package
@@ -251,6 +262,35 @@
`, []string{"lib32/foo", "lib64/foo", "lib64/bar"})
}
+func TestSkipInstallProducesLocalUninstallableModule(t *testing.T) {
+ result := GroupFixturePreparers(
+ PrepareForTestWithArchMutator,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("component", componentTestModuleFactory)
+ ctx.RegisterModuleType("package_module", packageTestModuleFactory)
+ }),
+ FixtureWithRootAndroidBp(`
+component {
+ name: "foo",
+ skip_install: true,
+}
+
+package_module {
+ name: "package",
+ deps: ["foo"],
+}
+`),
+ ).RunTest(t)
+ module := result.ModuleForTests("foo", "android_arm64_armv8-a").Module().(*componentTestModule)
+ entries := AndroidMkEntriesForTest(t, result.TestContext, module)
+ builder := &strings.Builder{}
+ entries[0].write(builder)
+ androidMkString := builder.String()
+ if !strings.Contains(androidMkString, "LOCAL_UNINSTALLABLE_MODULE := true") {
+ t.Errorf("Expected android mk entries to contain \"LOCAL_UNINSTALLABLE_MODULE := true\", got: \n%s", androidMkString)
+ }
+}
+
func TestPackagingBaseSingleTarget(t *testing.T) {
multiTarget := false
runPackagingTest(t, multiTarget,
diff --git a/android/variable.go b/android/variable.go
index 1b5d558..8c5c0bc 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -442,6 +442,7 @@
BuildBrokenDepfile *bool `json:",omitempty"`
BuildBrokenEnforceSyspropOwner bool `json:",omitempty"`
BuildBrokenTrebleSyspropNeverallow bool `json:",omitempty"`
+ BuildBrokenUsesSoongPython2Modules bool `json:",omitempty"`
BuildBrokenVendorPropertyNamespace bool `json:",omitempty"`
BuildBrokenInputDirModules []string `json:",omitempty"`
diff --git a/cc/cc.go b/cc/cc.go
index 0e88c56..e592cc5 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -609,7 +609,6 @@
inSanitizerDir() bool
hostToolPath() android.OptionalPath
relativeInstallPath() string
- makeUninstallable(mod *Module)
installInRoot() bool
}
@@ -3535,14 +3534,6 @@
return c.InRecovery()
}
-func (c *Module) MakeUninstallable() {
- if c.installer == nil {
- c.ModuleBase.MakeUninstallable()
- return
- }
- c.installer.makeUninstallable(c)
-}
-
func (c *Module) HostToolPath() android.OptionalPath {
if c.installer == nil {
return android.OptionalPath{}
diff --git a/cc/installer.go b/cc/installer.go
index e2c0e7b..c3618b7 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -121,10 +121,6 @@
return String(installer.Properties.Relative_install_path)
}
-func (installer *baseInstaller) makeUninstallable(mod *Module) {
- mod.ModuleBase.MakeUninstallable()
-}
-
func (installer *baseInstaller) installInRoot() bool {
return Bool(installer.Properties.Install_in_root)
}
diff --git a/cc/library.go b/cc/library.go
index 27f0623..574c4c3 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -2439,17 +2439,6 @@
return nil
}
-func (library *libraryDecorator) makeUninstallable(mod *Module) {
- if library.static() && library.buildStatic() && !library.buildStubs() {
- // If we're asked to make a static library uninstallable we don't do
- // anything since AndroidMkEntries always sets LOCAL_UNINSTALLABLE_MODULE
- // for these entries. This is done to still get the make targets for NOTICE
- // files from notice_files.mk, which other libraries might depend on.
- return
- }
- mod.ModuleBase.MakeUninstallable()
-}
-
func (library *libraryDecorator) getPartition() string {
return library.path.Partition()
}
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index bb517ea..9ac812c 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -214,7 +214,7 @@
// without the prefix hack below.
if p.hasStubsVariants() && !p.buildStubs() && !ctx.Host() &&
!strings.HasPrefix(ctx.baseModuleName(), "libclang_rt.") {
- ctx.Module().MakeUninstallable()
+ ctx.Module().SkipInstall()
}
return outputFile
diff --git a/java/androidmk.go b/java/androidmk.go
index a4dac80..d73ff46 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -76,9 +76,6 @@
entriesList = append(entriesList, dexpreoptEntries...)
}
entriesList = append(entriesList, android.AndroidMkEntries{Disabled: true})
- } else if !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) {
- // Platform variant. If not available for the platform, we don't need Make module.
- entriesList = append(entriesList, android.AndroidMkEntries{Disabled: true})
} else {
entriesList = append(entriesList, android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
@@ -94,7 +91,8 @@
entries.AddStrings("LOCAL_LOGTAGS_FILES", logtags...)
}
- if library.installFile == nil {
+ if library.installFile == nil || !library.ApexModuleBase.AvailableFor(android.AvailableToPlatform) {
+ // If the ApexModule is not available for the platform, it shouldn't be installed.
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true)
}
if library.dexJarFile.IsSet() {
diff --git a/python/python.go b/python/python.go
index 0ae7b36..c7c523d 100644
--- a/python/python.go
+++ b/python/python.go
@@ -263,6 +263,12 @@
versionProps = append(versionProps, props.Version.Py3)
}
if proptools.BoolDefault(props.Version.Py2.Enabled, false) {
+ if !mctx.DeviceConfig().BuildBrokenUsesSoongPython2Modules() &&
+ mctx.ModuleName() != "par_test" &&
+ mctx.ModuleName() != "py2-cmd" &&
+ mctx.ModuleName() != "py2-stdlib" {
+ mctx.PropertyErrorf("version.py2.enabled", "Python 2 is no longer supported, please convert to python 3. This error can be temporarily overridden by setting BUILD_BROKEN_USES_SOONG_PYTHON2_MODULES := true in the product configuration")
+ }
versionNames = append(versionNames, pyVersion2)
versionProps = append(versionProps, props.Version.Py2)
}
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 5dd45cd..ddbba74 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -191,6 +191,17 @@
],
}
+python_test_host {
+ name: "conv_linker_config_test",
+ main: "conv_linker_config_test.py",
+ srcs: [
+ "conv_linker_config_test.py",
+ "conv_linker_config.py",
+ ],
+ libs: ["linker_config_proto"],
+ test_suites: ["general-tests"],
+}
+
python_binary_host {
name: "get_clang_version",
main: "get_clang_version.py",
diff --git a/scripts/conv_linker_config.py b/scripts/conv_linker_config.py
index 784a92f..3ac1b7e 100644
--- a/scripts/conv_linker_config.py
+++ b/scripts/conv_linker_config.py
@@ -27,6 +27,19 @@
from google.protobuf.text_format import MessageToString
+def LoadJsonMessage(path):
+ """
+ Loads a message from a .json file with `//` comments strippedfor convenience.
+ """
+ json_content = ''
+ with open(path) as f:
+ for line in f:
+ if not line.lstrip().startswith('//'):
+ json_content += line
+ obj = json.loads(json_content, object_pairs_hook=collections.OrderedDict)
+ return ParseDict(obj, linker_config_pb2.LinkerConfig())
+
+
def Proto(args):
"""
Merges input json files (--source) into a protobuf message (--output).
@@ -48,13 +61,7 @@
if args.source:
for input in args.source.split(':'):
- json_content = ''
- with open(input) as f:
- for line in f:
- if not line.lstrip().startswith('//'):
- json_content += line
- obj = json.loads(json_content, object_pairs_hook=collections.OrderedDict)
- ParseDict(obj, pb)
+ pb.MergeFrom(LoadJsonMessage(input))
with open(args.output, 'wb') as f:
f.write(pb.SerializeToString())
diff --git a/scripts/conv_linker_config_test.py b/scripts/conv_linker_config_test.py
new file mode 100644
index 0000000..d19a47b
--- /dev/null
+++ b/scripts/conv_linker_config_test.py
@@ -0,0 +1,132 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2023 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Unit tests for conv_linker_config.py."""
+
+import io
+import os
+import shutil
+import tempfile
+import unittest
+
+import conv_linker_config
+from contextlib import redirect_stderr
+from linker_config_pb2 import LinkerConfig
+
+class FileArgs:
+ def __init__(self, files, sep = ':'):
+ self.files = files
+ self.sep = sep
+
+
+class FileArg:
+ def __init__(self, file):
+ self.file = file
+
+
+class TempDirTest(unittest.TestCase):
+
+ def setUp(self):
+ self.tempdir = tempfile.mkdtemp()
+
+
+ def tearDown(self):
+ shutil.rmtree(self.tempdir)
+
+
+ def write(self, name, contents):
+ with open(os.path.join(self.tempdir, name), 'wb') as f:
+ f.write(contents)
+
+
+ def read(self, name):
+ with open(os.path.join(self.tempdir, name), 'rb') as f:
+ return f.read()
+
+
+ def resolve_paths(self, args):
+ for i in range(len(args)):
+ if isinstance(args[i], FileArgs):
+ args[i] = args[i].sep.join(os.path.join(self.tempdir, f.file) for f in args[i].files)
+ elif isinstance(args[i], FileArg):
+ args[i] = os.path.join(self.tempdir, args[i].file)
+ return args
+
+
+class ConvLinkerConfigTest(TempDirTest):
+ """Unit tests for conv_linker_config."""
+
+
+ def test_Proto_empty_input(self):
+ self.command(['proto', '-s', '-o', FileArg('out.pb')])
+ pb = LinkerConfig()
+ pb.ParseFromString(self.read('out.pb'))
+ self.assertEqual(pb, LinkerConfig())
+
+
+ def test_Proto_single_input(self):
+ self.write('foo.json', b'{ "provideLibs": ["libfoo.so"]}')
+ self.command(['proto', '-s', FileArg('foo.json'), '-o', FileArg('out.pb')])
+ pb = LinkerConfig()
+ pb.ParseFromString(self.read('out.pb'))
+ self.assertSequenceEqual(pb.provideLibs, ['libfoo.so'])
+
+
+ def test_Proto_with_multiple_input(self):
+ self.write('foo.json', b'{ "provideLibs": ["libfoo.so"]}')
+ self.write('bar.json', b'{ "provideLibs": ["libbar.so"]}')
+ self.command(['proto', '-s', FileArgs([FileArg('foo.json'), FileArg('bar.json')]), '-o', FileArg('out.pb')])
+ pb = LinkerConfig()
+ pb.ParseFromString(self.read('out.pb'))
+ self.assertSetEqual(set(pb.provideLibs), set(['libfoo.so', 'libbar.so']))
+
+
+ def test_Proto_with_existing_output(self):
+ self.write('out.pb', LinkerConfig(provideLibs=['libfoo.so']).SerializeToString())
+ buf = io.StringIO()
+ with self.assertRaises(SystemExit) as err:
+ with redirect_stderr(buf):
+ self.command(['proto', '-o', FileArg('out.pb')])
+ self.assertEqual(err.exception.code, 1)
+ self.assertRegex(buf.getvalue(), r'.*out\.pb exists')
+
+
+ def test_Proto_with_append(self):
+ self.write('out.pb', LinkerConfig(provideLibs=['libfoo.so']).SerializeToString())
+ self.write('bar.json', b'{ "provideLibs": ["libbar.so"]}')
+ self.command(['proto', '-s', FileArg('bar.json'), '-o', FileArg('out.pb'), '-a'])
+ pb = LinkerConfig()
+ pb.ParseFromString(self.read('out.pb'))
+ self.assertSetEqual(set(pb.provideLibs), set(['libfoo.so', 'libbar.so']))
+
+
+ def test_Proto_with_force(self):
+ self.write('out.pb', LinkerConfig(provideLibs=['libfoo.so']).SerializeToString())
+ self.write('bar.json', b'{ "provideLibs": ["libbar.so"]}')
+ self.command(['proto', '-s', FileArg('bar.json'), '-o', FileArg('out.pb'), '-f'])
+ pb = LinkerConfig()
+ pb.ParseFromString(self.read('out.pb'))
+ self.assertSetEqual(set(pb.provideLibs), set(['libbar.so']))
+
+
+ def command(self, args):
+ parser = conv_linker_config.GetArgParser()
+ parsed_args = parser.parse_args(self.resolve_paths(args))
+ parsed_args.func(parsed_args)
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)