Merge "Revert "Export non-apex variants of modules to make""
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/config.go b/android/config.go
index b37d5c8..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
}
@@ -1837,3 +1841,14 @@
c.mixedBuildDisabledModules[moduleName] = struct{}{}
}
}
+
+// ApiSurfaces directory returns the source path inside the api_surfaces repo
+// (relative to workspace root).
+func (c *config) ApiSurfacesDir(s ApiSurface, version string) string {
+ return filepath.Join(
+ "build",
+ "bazel",
+ "api_surfaces",
+ s.String(),
+ version)
+}
diff --git a/android/filegroup.go b/android/filegroup.go
index 7d929bc..0f6e00e 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -78,6 +78,12 @@
Strip_import_prefix *string
}
+// api srcs can be contained in filegroups.
+// this should be generated in api_bp2build workspace as well.
+func (fg *fileGroup) ConvertWithApiBp2build(ctx TopDownMutatorContext) {
+ fg.ConvertWithBp2build(ctx)
+}
+
// ConvertWithBp2build performs bp2build conversion of filegroup
func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) {
srcs := bazel.MakeLabelListAttribute(
diff --git a/android/mutator.go b/android/mutator.go
index 4dacb8d..676f8a5 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -268,6 +268,11 @@
// platforms, as dictated by a given bool attribute: the target will not be buildable in
// any platform for which this bool attribute is false.
CreateBazelTargetModuleWithRestrictions(bazel.BazelTargetModuleProperties, CommonAttributes, interface{}, bazel.BoolAttribute)
+
+ // CreateBazelTargetAliasInDir creates an alias definition in `dir` directory.
+ // This function can be used to create alias definitions in a directory that is different
+ // from the directory of the visited Soong module.
+ CreateBazelTargetAliasInDir(dir string, name string, actual bazel.Label)
}
type topDownMutatorContext struct {
@@ -705,6 +710,34 @@
t.createBazelTargetModule(bazelProps, commonAttrs, attrs, enabledProperty)
}
+var (
+ bazelAliasModuleProperties = bazel.BazelTargetModuleProperties{
+ Rule_class: "alias",
+ }
+)
+
+type bazelAliasAttributes struct {
+ Actual *bazel.LabelAttribute
+}
+
+func (t *topDownMutatorContext) CreateBazelTargetAliasInDir(
+ dir string,
+ name string,
+ actual bazel.Label) {
+ mod := t.Module()
+ attrs := &bazelAliasAttributes{
+ Actual: bazel.MakeLabelAttribute(actual.Label),
+ }
+ info := bp2buildInfo{
+ Dir: dir,
+ BazelProps: bazelAliasModuleProperties,
+ CommonAttrs: CommonAttributes{Name: name},
+ ConstraintAttrs: constraintAttributes{},
+ Attrs: attrs,
+ }
+ mod.base().addBp2buildInfo(info)
+}
+
// ApexAvailableTags converts the apex_available property value of an ApexModule
// module and returns it as a list of keyed tags.
func ApexAvailableTags(mod Module) bazel.StringListAttribute {
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/bp2build/build_conversion.go b/bp2build/build_conversion.go
index ced779c..fde9b69 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -60,6 +60,15 @@
}
}
+// PackageName returns the package of the Bazel target.
+// Defaults to root of tree.
+func (t BazelTarget) PackageName() string {
+ if t.packageName == "" {
+ return "."
+ }
+ return t.packageName
+}
+
// BazelTargets is a typedef for a slice of BazelTarget objects.
type BazelTargets []BazelTarget
@@ -337,7 +346,10 @@
return
}
- buildFileToTargets[dir] = append(buildFileToTargets[dir], targets...)
+ for _, target := range targets {
+ targetDir := target.PackageName()
+ buildFileToTargets[targetDir] = append(buildFileToTargets[targetDir], target)
+ }
})
if len(errs) > 0 {
@@ -454,7 +466,8 @@
targetName := targetNameWithVariant(ctx, m)
return BazelTarget{
- name: targetName,
+ name: targetName,
+ packageName: ctx.ModuleDir(m),
content: fmt.Sprintf(
soongModuleTargetTemplate,
targetName,
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
index 0784f4b..f1d6398 100644
--- a/bp2build/java_library_conversion_test.go
+++ b/bp2build/java_library_conversion_test.go
@@ -755,3 +755,29 @@
},
})
}
+
+func TestJavaLibraryArchVariantSrcsWithExcludes(t *testing.T) {
+ runJavaLibraryTestCase(t, Bp2buildTestCase{
+ Description: "java_library with arch variant libs",
+ Blueprint: `java_library {
+ name: "java-lib-1",
+ srcs: ["a.java", "b.java"],
+ target: {
+ android: {
+ exclude_srcs: ["a.java"],
+ },
+ },
+ bazel_module: { bp2build_available: true },
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
+ "srcs": `["b.java"] + select({
+ "//build/bazel/platforms/os:android": [],
+ "//conditions:default": ["a.java"],
+ })`,
+ }),
+ MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
+ },
+ })
+}
diff --git a/bp2build/testing.go b/bp2build/testing.go
index bac5383..a737ea1 100644
--- a/bp2build/testing.go
+++ b/bp2build/testing.go
@@ -21,6 +21,7 @@
import (
"fmt"
+ "sort"
"strings"
"testing"
@@ -263,6 +264,12 @@
t.Errorf("%s: Expected %d bazel target (%s), got %d (%s)",
description, expectedCount, expectedContents, actualCount, actualTargets)
} else {
+ sort.SliceStable(actualTargets, func(i, j int) bool {
+ return actualTargets[i].name < actualTargets[j].name
+ })
+ sort.SliceStable(expectedContents, func(i, j int) bool {
+ return getTargetName(expectedContents[i]) < getTargetName(expectedContents[j])
+ })
for i, actualTarget := range actualTargets {
if w, g := expectedContents[i], actualTarget.content; w != g {
t.Errorf(
@@ -637,3 +644,13 @@
"exports": `[":` + name + `"]`,
})
}
+
+func getTargetName(targetContent string) string {
+ data := strings.Split(targetContent, "name = \"")
+ if len(data) < 2 {
+ return ""
+ } else {
+ endIndex := strings.Index(data[1], "\"")
+ return data[1][:endIndex]
+ }
+}
diff --git a/cc/config/global.go b/cc/config/global.go
index 05dc773..488af45 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -193,6 +193,7 @@
noOverrideGlobalCflags = []string{
"-Werror=bool-operation",
+ "-Werror=format-insufficient-args",
"-Werror=implicit-int-float-conversion",
"-Werror=int-in-bool-context",
"-Werror=int-to-pointer-cast",
@@ -247,6 +248,8 @@
noOverride64GlobalCflags = []string{}
noOverrideExternalGlobalCflags = []string{
+ // http://b/191699019
+ "-Wno-format-insufficient-args",
"-Wno-sizeof-array-div",
"-Wno-unused-but-set-variable",
"-Wno-unused-but-set-parameter",
@@ -284,9 +287,6 @@
// http://b/239661264
"-Wno-deprecated-non-prototype",
-
- // http://b/191699019
- "-Wno-format-insufficient-args",
}
llvmNextExtraCommonGlobalCflags = []string{
diff --git a/cc/library.go b/cc/library.go
index e73af81..27f0623 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -464,6 +464,21 @@
ctx.CreateBazelTargetModule(stubSuitesProps,
android.CommonAttributes{Name: m.Name() + "_stub_libs"},
stubSuitesAttrs)
+
+ // Add alias for the stub shared_library in @api_surfaces repository
+ currentModuleLibApiDir := ctx.Config().ApiSurfacesDir(android.ModuleLibApi, "current")
+ actualLabelInMainWorkspace := bazel.Label{
+ Label: fmt.Sprintf("@//%s:%s_stub_libs_current", ctx.ModuleDir(), m.Name()),
+ }
+ ctx.CreateBazelTargetAliasInDir(currentModuleLibApiDir, m.Name(), actualLabelInMainWorkspace)
+
+ // Add alias for headers exported by the stub library
+ headerLabelInMainWorkspace := bazel.Label{
+ // This label is generated from cc_stub_suite macro
+ Label: fmt.Sprintf("@//%s:%s_stub_libs_%s_headers", ctx.ModuleDir(), m.Name(), android.ModuleLibApi.String()),
+ }
+ headerAlias := m.Name() + "_headers"
+ ctx.CreateBazelTargetAliasInDir(currentModuleLibApiDir, headerAlias, headerLabelInMainWorkspace)
}
}
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 5c187f6..9b51160 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -136,7 +136,7 @@
ctx.EventHandler.Begin("queryview")
defer ctx.EventHandler.End("queryview")
codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.QueryView, topDir)
- err := createBazelWorkspace(codegenContext, shared.JoinPath(topDir, queryviewDir))
+ err := createBazelWorkspace(codegenContext, shared.JoinPath(topDir, queryviewDir), false)
maybeQuit(err, "")
touch(shared.JoinPath(topDir, queryviewMarker))
}
@@ -174,7 +174,28 @@
// Run codegen to generate BUILD files
codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.ApiBp2build, topDir)
absoluteApiBp2buildDir := shared.JoinPath(topDir, cmdlineArgs.BazelApiBp2buildDir)
- err := createBazelWorkspace(codegenContext, absoluteApiBp2buildDir)
+ // Always generate bp2build_all_srcs filegroups in api_bp2build.
+ // This is necessary to force each Android.bp file to create an equivalent BUILD file
+ // and prevent package boundray issues.
+ // e.g.
+ // Source
+ // f/b/Android.bp
+ // java_library{
+ // name: "foo",
+ // api: "api/current.txt",
+ // }
+ //
+ // f/b/api/Android.bp <- will cause package boundary issues
+ //
+ // Gen
+ // f/b/BUILD
+ // java_contribution{
+ // name: "foo.contribution",
+ // api: "//f/b/api:current.txt",
+ // }
+ //
+ // If we don't generate f/b/api/BUILD, foo.contribution will be unbuildable.
+ err := createBazelWorkspace(codegenContext, absoluteApiBp2buildDir, true)
maybeQuit(err, "")
ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
diff --git a/cmd/soong_build/queryview.go b/cmd/soong_build/queryview.go
index 35ae009..ce32184 100644
--- a/cmd/soong_build/queryview.go
+++ b/cmd/soong_build/queryview.go
@@ -25,11 +25,11 @@
)
// A helper function to generate a Read-only Bazel workspace in outDir
-func createBazelWorkspace(ctx *bp2build.CodegenContext, outDir string) error {
+func createBazelWorkspace(ctx *bp2build.CodegenContext, outDir string, generateFilegroups bool) error {
os.RemoveAll(outDir)
ruleShims := bp2build.CreateRuleShims(android.ModuleTypeFactories())
- res, err := bp2build.GenerateBazelTargets(ctx, false)
+ res, err := bp2build.GenerateBazelTargets(ctx, generateFilegroups)
if err != nil {
panic(err)
}
diff --git a/java/java.go b/java/java.go
index 63c4416..61f5949 100644
--- a/java/java.go
+++ b/java/java.go
@@ -2660,6 +2660,7 @@
}
}
}
+ srcs.ResolveExcludes()
javaSrcPartition := "java"
protoSrcPartition := "proto"
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)
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
index 1ff1b5b..68d7f8d 100755
--- a/tests/bp2build_bazel_test.sh
+++ b/tests/bp2build_bazel_test.sh
@@ -343,4 +343,29 @@
run_bazel build --config=android --config=api_bp2build //:empty
}
+# Verify that an *_api_contribution target can refer to an api file from
+# another Bazel package.
+function test_api_export_from_another_bazel_package() {
+ setup
+ # Parent dir Android.bp
+ mkdir -p foo
+ cat > foo/Android.bp << 'EOF'
+cc_library {
+ name: "libfoo",
+ stubs: {
+ symbol_file: "api/libfoo.map.txt",
+ },
+}
+EOF
+ # Child dir Android.bp
+ mkdir -p foo/api
+ cat > foo/api/Android.bp << 'EOF'
+package{}
+EOF
+ touch foo/api/libfoo.map.txt
+ # Run test
+ run_soong api_bp2build
+ run_bazel build --config=android --config=api_bp2build //foo:libfoo.contribution
+}
+
scan_and_run_tests