Merge "Streamline AndroidMk generation"
diff --git a/apex/deapexer.go b/apex/deapexer.go
index 8c9030a..fed9cd1 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -140,6 +140,8 @@
Tool(android.PathForSource(ctx, "build/soong/scripts/unpack-prebuilt-apex.sh")).
BuiltTool("deapexer").
BuiltTool("debugfs").
+ BuiltTool("blkid").
+ BuiltTool("fsck.erofs").
Input(p.inputApex).
Text(deapexerOutput.String())
for _, p := range exportedPaths {
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 6fdd50a..0997a68 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -830,6 +830,7 @@
srcsSupplier := func(ctx android.BaseModuleContext, prebuilt android.Module) []string {
return p.properties.prebuiltSrcs(ctx)
}
+ defaultAllowPrerelease := ctx.Config().IsEnvTrue("SOONG_ALLOW_PRERELEASE_APEXES")
apexSet := android.SingleSourcePathFromSupplier(ctx, srcsSupplier, "set")
p.extractedApex = android.PathForModuleOut(ctx, "extracted", apexSet.Base())
// Filter out NativeBridge archs (b/260115309)
@@ -842,7 +843,7 @@
Output: p.extractedApex,
Args: map[string]string{
"abis": strings.Join(abis, ","),
- "allow-prereleased": strconv.FormatBool(proptools.Bool(p.properties.Prerelease)),
+ "allow-prereleased": strconv.FormatBool(proptools.BoolDefault(p.properties.Prerelease, defaultAllowPrerelease)),
"sdk-version": ctx.Config().PlatformSdkVersion().String(),
},
})
@@ -915,6 +916,15 @@
return false
}
+func (a *ApexSet) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case "":
+ return android.Paths{a.outputApex}, nil
+ default:
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ }
+}
+
// prebuilt_apex imports an `.apex` file into the build graph as if it was built with apex.
func apexSetFactory() android.Module {
module := &ApexSet{}
diff --git a/bazel/properties.go b/bazel/properties.go
index ee9609a..6921984 100644
--- a/bazel/properties.go
+++ b/bazel/properties.go
@@ -1207,6 +1207,11 @@
// The configured attribute label list Values. Optional
// a map of independent configurability axes
ConfigurableValues configurableStringLists
+
+ // If a property has struct tag "variant_prepend", this value should
+ // be set to True, so that when bp2build generates BUILD.bazel, variant
+ // properties(select ...) come before general properties.
+ Prepend bool
}
// IsEmpty returns true if the attribute has no values under any configuration.
@@ -1273,6 +1278,9 @@
// Append appends all values, including os and arch specific ones, from another
// StringListAttribute to this StringListAttribute
func (sla *StringListAttribute) Append(other StringListAttribute) *StringListAttribute {
+ if sla.Prepend != other.Prepend {
+ panic(fmt.Errorf("StringListAttribute could not be appended because it has different prepend value"))
+ }
sla.Value = append(sla.Value, other.Value...)
if sla.ConfigurableValues == nil {
sla.ConfigurableValues = make(configurableStringLists)
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index 7c9af1a..2e01789 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -51,6 +51,7 @@
"cc_prebuilt_library_conversion_test.go",
"cc_prebuilt_library_shared_test.go",
"cc_prebuilt_library_static_test.go",
+ "cc_prebuilt_object_conversion_test.go",
"cc_test_conversion_test.go",
"cc_yasm_conversion_test.go",
"conversion_test.go",
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
index a1e83d8..ee6e5b8 100644
--- a/bp2build/cc_library_conversion_test.go
+++ b/bp2build/cc_library_conversion_test.go
@@ -3603,6 +3603,89 @@
})
}
+func TestCcLibraryWithAfdoEnabled(t *testing.T) {
+ bp := `
+cc_library {
+ name: "foo",
+ afdo: true,
+ include_build_directory: false,
+}`
+
+ // TODO(b/260714900): Add test case for arch-specific afdo profile
+ testCases := []struct {
+ description string
+ filesystem map[string]string
+ expectedBazelTargets []string
+ }{
+ {
+ description: "cc_library with afdo enabled and existing profile",
+ filesystem: map[string]string{
+ "vendor/google_data/pgo_profile/sampling/BUILD": "",
+ "vendor/google_data/pgo_profile/sampling/foo.afdo": "",
+ },
+ expectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "fdo_profile": `"//vendor/google_data/pgo_profile/sampling:foo"`,
+ }),
+ },
+ },
+ {
+ description: "cc_library with afdo enabled and existing profile in AOSP",
+ filesystem: map[string]string{
+ "toolchain/pgo-profiles/sampling/BUILD": "",
+ "toolchain/pgo-profiles/sampling/foo.afdo": "",
+ },
+ expectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
+ "fdo_profile": `"//toolchain/pgo-profiles/sampling:foo"`,
+ }),
+ },
+ },
+ {
+ description: "cc_library with afdo enabled but profile filename doesn't match with module name",
+ filesystem: map[string]string{
+ "toolchain/pgo-profiles/sampling/BUILD": "",
+ "toolchain/pgo-profiles/sampling/bar.afdo": "",
+ },
+ expectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{}),
+ },
+ },
+ {
+ description: "cc_library with afdo enabled but profile doesn't exist",
+ expectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{}),
+ },
+ },
+ {
+ description: "cc_library with afdo enabled and existing profile but BUILD file doesn't exist",
+ filesystem: map[string]string{
+ "vendor/google_data/pgo_profile/sampling/foo.afdo": "",
+ },
+ expectedBazelTargets: []string{
+ MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}),
+ MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{}),
+ },
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.description, func(t *testing.T) {
+ runCcLibraryTestCase(t, Bp2buildTestCase{
+ ExpectedBazelTargets: testCase.expectedBazelTargets,
+ ModuleTypeUnderTest: "cc_library",
+ ModuleTypeUnderTestFactory: cc.LibraryFactory,
+ Description: testCase.description,
+ Blueprint: binaryReplacer.Replace(bp),
+ Filesystem: testCase.filesystem,
+ })
+ })
+ }
+}
+
func TestCcLibraryHeaderAbiChecker(t *testing.T) {
runCcLibraryTestCase(t, Bp2buildTestCase{
Description: "cc_library with header abi checker",
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
index 7d9db6f..686c9d5 100644
--- a/bp2build/cc_library_headers_conversion_test.go
+++ b/bp2build/cc_library_headers_conversion_test.go
@@ -107,15 +107,15 @@
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
- "export_includes": `[
- "dir-1",
- "dir-2",
- ] + select({
+ "export_includes": `select({
"//build/bazel/platforms/arch:arm64": ["arch_arm64_exported_include_dir"],
"//build/bazel/platforms/arch:x86": ["arch_x86_exported_include_dir"],
"//build/bazel/platforms/arch:x86_64": ["arch_x86_64_exported_include_dir"],
"//conditions:default": [],
- })`,
+ }) + [
+ "dir-1",
+ "dir-2",
+ ]`,
"sdk_version": `"current"`,
"min_sdk_version": `"29"`,
}),
@@ -340,16 +340,16 @@
}`,
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
- "export_system_includes": `["shared_include_dir"] + select({
- "//build/bazel/platforms/arch:arm": ["arm_include_dir"],
- "//build/bazel/platforms/arch:x86_64": ["x86_64_include_dir"],
- "//conditions:default": [],
- }) + select({
+ "export_system_includes": `select({
"//build/bazel/platforms/os:android": ["android_include_dir"],
"//build/bazel/platforms/os:darwin": ["darwin_include_dir"],
"//build/bazel/platforms/os:linux": ["linux_include_dir"],
"//conditions:default": [],
- })`,
+ }) + select({
+ "//build/bazel/platforms/arch:arm": ["arm_include_dir"],
+ "//build/bazel/platforms/arch:x86_64": ["x86_64_include_dir"],
+ "//conditions:default": [],
+ }) + ["shared_include_dir"]`,
}),
},
})
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
index b8dc690..1377c6b 100644
--- a/bp2build/cc_object_conversion_test.go
+++ b/bp2build/cc_object_conversion_test.go
@@ -24,6 +24,7 @@
func registerCcObjectModuleTypes(ctx android.RegistrationContext) {
// Always register cc_defaults module factory
ctx.RegisterModuleType("cc_defaults", func() android.Module { return cc.DefaultsFactory() })
+ ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
}
func runCcObjectTestCase(t *testing.T, tc Bp2buildTestCase) {
@@ -147,7 +148,7 @@
"system_dynamic_deps": `[]`,
}), MakeBazelTarget("cc_object", "foo", AttrNameToString{
"copts": `["-fno-addrsig"]`,
- "deps": `[":bar"]`,
+ "objs": `[":bar"]`,
"srcs": `["a/b/c.c"]`,
"system_dynamic_deps": `[]`,
}),
@@ -362,7 +363,7 @@
ExpectedBazelTargets: []string{
MakeBazelTarget("cc_object", "foo", AttrNameToString{
"copts": `["-fno-addrsig"]`,
- "deps": `select({
+ "objs": `select({
"//build/bazel/platforms/arch:arm": [":arm_obj"],
"//build/bazel/platforms/arch:x86": [":x86_obj"],
"//build/bazel/platforms/arch:x86_64": [":x86_64_obj"],
@@ -422,3 +423,56 @@
},
})
}
+
+func TestCcObjectHeaderLib(t *testing.T) {
+ runCcObjectTestCase(t, Bp2buildTestCase{
+ Description: "simple cc_object generates cc_object with include header dep",
+ Filesystem: map[string]string{
+ "a/b/foo.h": "",
+ "a/b/bar.h": "",
+ "a/b/exclude.c": "",
+ "a/b/c.c": "",
+ },
+ Blueprint: `cc_object {
+ name: "foo",
+ header_libs: ["libheaders"],
+ system_shared_libs: [],
+ cflags: [
+ "-Wno-gcc-compat",
+ "-Wall",
+ "-Werror",
+ ],
+ srcs: [
+ "a/b/*.c"
+ ],
+ exclude_srcs: ["a/b/exclude.c"],
+ sdk_version: "current",
+ min_sdk_version: "29",
+}
+
+cc_library_headers {
+ name: "libheaders",
+ export_include_dirs: ["include"],
+}
+`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_object", "foo", AttrNameToString{
+ "copts": `[
+ "-fno-addrsig",
+ "-Wno-gcc-compat",
+ "-Wall",
+ "-Werror",
+ ]`,
+ "deps": `[":libheaders"]`,
+ "local_includes": `["."]`,
+ "srcs": `["a/b/c.c"]`,
+ "system_dynamic_deps": `[]`,
+ "sdk_version": `"current"`,
+ "min_sdk_version": `"29"`,
+ }),
+ MakeBazelTarget("cc_library_headers", "libheaders", AttrNameToString{
+ "export_includes": `["include"]`,
+ }),
+ },
+ })
+}
diff --git a/bp2build/cc_prebuilt_object_conversion_test.go b/bp2build/cc_prebuilt_object_conversion_test.go
new file mode 100644
index 0000000..903c816
--- /dev/null
+++ b/bp2build/cc_prebuilt_object_conversion_test.go
@@ -0,0 +1,101 @@
+// Copyright 2022 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
+
+import (
+ "fmt"
+ "testing"
+
+ "android/soong/cc"
+)
+
+func runCcPrebuiltObjectTestCase(t *testing.T, testCase Bp2buildTestCase) {
+ t.Helper()
+ description := fmt.Sprintf("cc_prebuilt_object: %s", testCase.Description)
+ testCase.ModuleTypeUnderTest = "cc_prebuilt_object"
+ testCase.ModuleTypeUnderTestFactory = cc.PrebuiltObjectFactory
+ testCase.Description = description
+ t.Run(description, func(t *testing.T) {
+ t.Helper()
+ RunBp2BuildTestCaseSimple(t, testCase)
+ })
+}
+
+func TestPrebuiltObject(t *testing.T) {
+ runCcPrebuiltObjectTestCase(t,
+ Bp2buildTestCase{
+ Description: "simple",
+ Filesystem: map[string]string{
+ "obj.o": "",
+ },
+ Blueprint: `
+cc_prebuilt_object {
+ name: "objtest",
+ srcs: ["obj.o"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_object", "objtest", AttrNameToString{
+ "src": `"obj.o"`,
+ })},
+ })
+}
+
+func TestPrebuiltObjectWithArchVariance(t *testing.T) {
+ runCcPrebuiltObjectTestCase(t,
+ Bp2buildTestCase{
+ Description: "with arch variance",
+ Filesystem: map[string]string{
+ "obja.o": "",
+ "objb.o": "",
+ },
+ Blueprint: `
+cc_prebuilt_object {
+ name: "objtest",
+ arch: {
+ arm64: { srcs: ["obja.o"], },
+ arm: { srcs: ["objb.o"], },
+ },
+ bazel_module: { bp2build_available: true },
+}`, ExpectedBazelTargets: []string{
+ MakeBazelTarget("cc_prebuilt_object", "objtest", AttrNameToString{
+ "src": `select({
+ "//build/bazel/platforms/arch:arm": "objb.o",
+ "//build/bazel/platforms/arch:arm64": "obja.o",
+ "//conditions:default": None,
+ })`,
+ }),
+ },
+ })
+}
+
+func TestPrebuiltObjectMultipleSrcsFails(t *testing.T) {
+ runCcPrebuiltObjectTestCase(t,
+ Bp2buildTestCase{
+ Description: "fails because multiple sources",
+ Filesystem: map[string]string{
+ "obja": "",
+ "objb": "",
+ },
+ Blueprint: `
+cc_prebuilt_object {
+ name: "objtest",
+ srcs: ["obja.o", "objb.o"],
+ bazel_module: { bp2build_available: true },
+}`,
+ ExpectedErr: fmt.Errorf("Expected at most one source file"),
+ })
+}
+
+// TODO: nosrcs test
diff --git a/bp2build/configurability.go b/bp2build/configurability.go
index 9398d12..112755b 100644
--- a/bp2build/configurability.go
+++ b/bp2build/configurability.go
@@ -37,10 +37,11 @@
return value, []selects{ret}
}
-func getStringListValues(list bazel.StringListAttribute) (reflect.Value, []selects) {
+func getStringListValues(list bazel.StringListAttribute) (reflect.Value, []selects, bool) {
value := reflect.ValueOf(list.Value)
+ prepend := reflect.ValueOf(list.Prepend).Bool()
if !list.HasConfigurableValues() {
- return value, []selects{}
+ return value, []selects{}, prepend
}
var ret []selects
@@ -56,7 +57,7 @@
}
}
- return value, ret
+ return value, ret, prepend
}
func getLabelValue(label bazel.LabelAttribute) (reflect.Value, []selects) {
@@ -156,6 +157,7 @@
func prettyPrintAttribute(v bazel.Attribute, indent int) (string, error) {
var value reflect.Value
var configurableAttrs []selects
+ var prepend bool
var defaultSelectValue *string
var emitZeroValues bool
// If true, print the default attribute value, even if the attribute is zero.
@@ -168,7 +170,7 @@
value, configurableAttrs = getStringValue(list)
defaultSelectValue = &bazelNone
case bazel.StringListAttribute:
- value, configurableAttrs = getStringListValues(list)
+ value, configurableAttrs, prepend = getStringListValues(list)
defaultSelectValue = &emptyBazelList
case bazel.LabelListAttribute:
value, configurableAttrs = getLabelListValues(list)
@@ -203,22 +205,28 @@
ret += s
}
- // Convenience function to append selects components to an attribute value.
- appendSelects := func(selectsData selects, defaultValue *string, s string) (string, error) {
+ // Convenience function to prepend/append selects components to an attribute value.
+ concatenateSelects := func(selectsData selects, defaultValue *string, s string, prepend bool) (string, error) {
selectMap, err := prettyPrintSelectMap(selectsData, defaultValue, indent, emitZeroValues)
if err != nil {
return "", err
}
- if s != "" && selectMap != "" {
- s += " + "
+ var left, right string
+ if prepend {
+ left, right = selectMap, s
+ } else {
+ left, right = s, selectMap
}
- s += selectMap
+ if left != "" && right != "" {
+ left += " + "
+ }
+ left += right
- return s, nil
+ return left, nil
}
for _, configurableAttr := range configurableAttrs {
- ret, err = appendSelects(configurableAttr, defaultSelectValue, ret)
+ ret, err = concatenateSelects(configurableAttr, defaultSelectValue, ret, prepend)
if err != nil {
return "", err
}
diff --git a/cc/bp2build.go b/cc/bp2build.go
index 6caa854..510ecee 100644
--- a/cc/bp2build.go
+++ b/cc/bp2build.go
@@ -337,6 +337,19 @@
}
}
+func bp2BuildParsePrebuiltObjectProps(ctx android.BazelConversionPathContext, module *Module) prebuiltAttributes {
+ var srcLabelAttribute bazel.LabelAttribute
+ bp2BuildPropParseHelper(ctx, module, &prebuiltObjectProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
+ if props, ok := props.(*prebuiltObjectProperties); ok {
+ parseSrc(ctx, &srcLabelAttribute, axis, config, props.Srcs)
+ }
+ })
+
+ return prebuiltAttributes{
+ Src: srcLabelAttribute,
+ }
+}
+
type baseAttributes struct {
compilerAttributes
linkerAttributes
@@ -393,6 +406,8 @@
features bazel.StringListAttribute
suffix bazel.StringAttribute
+
+ fdoProfile bazel.LabelAttribute
}
type filterOutFn func(string) bool
@@ -777,6 +792,13 @@
(&compilerAttrs).srcs.Add(&convertedLSrcs.srcName)
(&compilerAttrs).cSrcs.Add(&convertedLSrcs.cSrcName)
+ if module.afdo != nil && module.afdo.Properties.Afdo {
+ fdoProfileDep := bp2buildFdoProfile(ctx, module)
+ if fdoProfileDep != nil {
+ (&compilerAttrs).fdoProfile.SetValue(*fdoProfileDep)
+ }
+ }
+
if !compilerAttrs.syspropSrcs.IsEmpty() {
(&linkerAttrs).wholeArchiveDeps.Add(bp2buildCcSysprop(ctx, module.Name(), module.Properties.Min_sdk_version, compilerAttrs.syspropSrcs))
}
@@ -793,6 +815,41 @@
}
}
+type fdoProfileAttributes struct {
+ Absolute_path_profile string
+}
+
+func bp2buildFdoProfile(
+ ctx android.Bp2buildMutatorContext,
+ m *Module,
+) *bazel.Label {
+ for _, project := range globalAfdoProfileProjects {
+ // Ensure handcrafted BUILD file exists in the project
+ BUILDPath := android.ExistentPathForSource(ctx, project, "BUILD")
+ if BUILDPath.Valid() {
+ // We handcraft a BUILD file with fdo_profile targets that use the existing profiles in the project
+ // This implementation is assuming that every afdo profile in globalAfdoProfileProjects already has
+ // an associated fdo_profile target declared in the same package.
+ // TODO(b/260714900): Handle arch-specific afdo profiles (e.g. `<module-name>-arm<64>.afdo`)
+ path := android.ExistentPathForSource(ctx, project, m.Name()+".afdo")
+ if path.Valid() {
+ // FIXME: Some profiles only exist internally and are not released to AOSP.
+ // When generated BUILD files are checked in, we'll run into merge conflict.
+ // The cc_library_shared target in AOSP won't have reference to an fdo_profile target because
+ // the profile doesn't exist. Internally, the same cc_library_shared target will
+ // have reference to the fdo_profile.
+ // For more context, see b/258682955#comment2
+ fdoProfileLabel := "//" + strings.TrimSuffix(project, "/") + ":" + m.Name()
+ return &bazel.Label{
+ Label: fdoProfileLabel,
+ }
+ }
+ }
+ }
+
+ return nil
+}
+
func bp2buildCcAidlLibrary(
ctx android.Bp2buildMutatorContext,
m *Module,
@@ -1257,6 +1314,13 @@
} else {
exported = BazelIncludes{}
}
+
+ // cc library Export_include_dirs and Export_system_include_dirs are marked
+ // "variant_prepend" in struct tag, set their prepend property to true to make
+ // sure bp2build generates correct result.
+ exported.Includes.Prepend = true
+ exported.SystemIncludes.Prepend = true
+
bp2BuildPropParseHelper(ctx, module, &FlagExporterProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
if flagExporterProperties, ok := props.(*FlagExporterProperties); ok {
if len(flagExporterProperties.Export_include_dirs) > 0 {
diff --git a/cc/cc.go b/cc/cc.go
index 2ff5bba..29bb84e 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -3775,7 +3775,9 @@
testBinaryBp2build(ctx, c)
}
case object:
- if !prebuilt {
+ if prebuilt {
+ prebuiltObjectBp2Build(ctx, c)
+ } else {
objectBp2Build(ctx, c)
}
case fullLibrary:
diff --git a/cc/library.go b/cc/library.go
index 7059023..ed0ed01 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -417,6 +417,8 @@
Strip: stripAttrsFromLinkerAttrs(&linkerAttrs),
Features: baseAttributes.features,
bazelCcHeaderAbiCheckerAttributes: bp2buildParseAbiCheckerProps(ctx, m),
+
+ Fdo_profile: compilerAttrs.fdoProfile,
}
if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 {
@@ -2930,6 +2932,8 @@
Suffix: compilerAttrs.suffix,
bazelCcHeaderAbiCheckerAttributes: bp2buildParseAbiCheckerProps(ctx, module),
+
+ Fdo_profile: compilerAttrs.fdoProfile,
}
if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 {
hasStubs := true
@@ -3020,6 +3024,8 @@
Suffix bazel.StringAttribute
bazelCcHeaderAbiCheckerAttributes
+
+ Fdo_profile bazel.LabelAttribute
}
type bazelCcStubSuiteAttributes struct {
diff --git a/cc/object.go b/cc/object.go
index 1a96b72..ff04e87 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -133,6 +133,7 @@
Srcs bazel.LabelListAttribute
Srcs_as bazel.LabelListAttribute
Hdrs bazel.LabelListAttribute
+ Objs bazel.LabelListAttribute
Deps bazel.LabelListAttribute
System_dynamic_deps bazel.LabelListAttribute
Copts bazel.StringListAttribute
@@ -155,6 +156,7 @@
// Set arch-specific configurable attributes
baseAttributes := bp2BuildParseBaseProps(ctx, m)
compilerAttrs := baseAttributes.compilerAttributes
+ var objs bazel.LabelListAttribute
var deps bazel.LabelListAttribute
systemDynamicDeps := bazel.LabelListAttribute{ForceSpecifyEmptyList: true}
@@ -167,16 +169,19 @@
label := android.BazelLabelForModuleSrcSingle(ctx, *objectLinkerProps.Linker_script)
linkerScript.SetSelectValue(axis, config, label)
}
- deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, objectLinkerProps.Objs))
+ objs.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, objectLinkerProps.Objs))
systemSharedLibs := objectLinkerProps.System_shared_libs
if len(systemSharedLibs) > 0 {
systemSharedLibs = android.FirstUniqueStrings(systemSharedLibs)
}
systemDynamicDeps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, systemSharedLibs))
+ deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, objectLinkerProps.Static_libs))
+ deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, objectLinkerProps.Shared_libs))
+ deps.SetSelectValue(axis, config, android.BazelLabelForModuleDeps(ctx, objectLinkerProps.Header_libs))
}
}
}
- deps.ResolveExcludes()
+ objs.ResolveExcludes()
// Don't split cc_object srcs across languages. Doing so would add complexity,
// and this isn't typically done for cc_object.
@@ -192,6 +197,7 @@
attrs := &bazelObjectAttributes{
Srcs: srcs,
Srcs_as: compilerAttrs.asSrcs,
+ Objs: objs,
Deps: deps,
System_dynamic_deps: systemDynamicDeps,
Copts: compilerAttrs.copts,
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index 9fbf879..45af303 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -32,7 +32,7 @@
ctx.RegisterModuleType("cc_prebuilt_library_shared", PrebuiltSharedLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_library_static", PrebuiltStaticLibraryFactory)
ctx.RegisterModuleType("cc_prebuilt_test_library_shared", PrebuiltSharedTestLibraryFactory)
- ctx.RegisterModuleType("cc_prebuilt_object", prebuiltObjectFactory)
+ ctx.RegisterModuleType("cc_prebuilt_object", PrebuiltObjectFactory)
ctx.RegisterModuleType("cc_prebuilt_binary", PrebuiltBinaryFactory)
}
@@ -572,6 +572,8 @@
func NewPrebuiltObject(hod android.HostOrDeviceSupported) *Module {
module := newObject(hod)
+ module.bazelHandler = &prebuiltObjectBazelHandler{module: module}
+ module.bazelable = true
prebuilt := &prebuiltObjectLinker{
objectLinker: objectLinker{
baseLinker: NewBaseLinker(nil),
@@ -584,7 +586,55 @@
return module
}
-func prebuiltObjectFactory() android.Module {
+type prebuiltObjectBazelHandler struct {
+ module *Module
+}
+
+var _ BazelHandler = (*prebuiltObjectBazelHandler)(nil)
+
+func (h *prebuiltObjectBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
+ bazelCtx := ctx.Config().BazelContext
+ bazelCtx.QueueBazelRequest(label, cquery.GetOutputFiles, android.GetConfigKey(ctx))
+}
+
+func (h *prebuiltObjectBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
+ bazelCtx := ctx.Config().BazelContext
+ outputs, err := bazelCtx.GetOutputFiles(label, android.GetConfigKey(ctx))
+ if err != nil {
+ ctx.ModuleErrorf(err.Error())
+ return
+ }
+ if len(outputs) != 1 {
+ ctx.ModuleErrorf("Expected a single output for `%s`, but got:\n%v", label, outputs)
+ return
+ }
+ out := android.PathForBazelOut(ctx, outputs[0])
+ h.module.outputFile = android.OptionalPathForPath(out)
+ h.module.maybeUnhideFromMake()
+}
+
+type bazelPrebuiltObjectAttributes struct {
+ Src bazel.LabelAttribute
+}
+
+func prebuiltObjectBp2Build(ctx android.TopDownMutatorContext, module *Module) {
+ prebuiltAttrs := bp2BuildParsePrebuiltObjectProps(ctx, module)
+
+ attrs := &bazelPrebuiltObjectAttributes{
+ Src: prebuiltAttrs.Src,
+ }
+
+ props := bazel.BazelTargetModuleProperties{
+ Rule_class: "cc_prebuilt_object",
+ Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_object.bzl",
+ }
+
+ name := android.RemoveOptionalPrebuiltPrefix(module.Name())
+ tags := android.ApexAvailableTags(module)
+ ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name, Tags: tags}, attrs)
+}
+
+func PrebuiltObjectFactory() android.Module {
module := NewPrebuiltObject(android.HostAndDeviceSupported)
return module.Init()
}
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index aa48e63..c3b192d 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -77,6 +77,7 @@
"add-to-product-copy-files-if-exists": &simpleCallParser{name: baseName + ".copy_if_exists", returnType: starlarkTypeList},
"addprefix": &simpleCallParser{name: baseName + ".addprefix", returnType: starlarkTypeList},
"addsuffix": &simpleCallParser{name: baseName + ".addsuffix", returnType: starlarkTypeList},
+ "and": &andOrParser{isAnd: true},
"copy-files": &simpleCallParser{name: baseName + ".copy_files", returnType: starlarkTypeList},
"dir": &simpleCallParser{name: baseName + ".dir", returnType: starlarkTypeString},
"dist-for-goals": &simpleCallParser{name: baseName + ".mkdist_for_goals", returnType: starlarkTypeVoid, addGlobals: true},
@@ -105,6 +106,7 @@
"math_gt": &mathComparisonCallParser{op: ">"},
"math_lt": &mathComparisonCallParser{op: "<"},
"my-dir": &myDirCallParser{},
+ "or": &andOrParser{isAnd: false},
"patsubst": &substCallParser{fname: "patsubst"},
"product-copy-files-by-pattern": &simpleCallParser{name: baseName + ".product_copy_files_by_pattern", returnType: starlarkTypeList},
"require-artifacts-in-path": &simpleCallParser{name: baseName + ".require_artifacts_in_path", returnType: starlarkTypeVoid, addHandle: true},
@@ -114,6 +116,8 @@
"sort": &simpleCallParser{name: baseName + ".mksort", returnType: starlarkTypeList},
"strip": &simpleCallParser{name: baseName + ".mkstrip", returnType: starlarkTypeString},
"subst": &substCallParser{fname: "subst"},
+ "to-lower": &lowerUpperParser{isUpper: false},
+ "to-upper": &lowerUpperParser{isUpper: true},
"warning": &makeControlFuncParser{name: baseName + ".mkwarning"},
"word": &wordCallParser{},
"words": &wordsCallParser{},
@@ -1430,6 +1434,51 @@
return &stringLiteralExpr{literal: filepath.Dir(ctx.script.mkFile)}
}
+type andOrParser struct {
+ isAnd bool
+}
+
+func (p *andOrParser) parse(ctx *parseContext, node mkparser.Node, args *mkparser.MakeString) starlarkExpr {
+ if args.Empty() {
+ return ctx.newBadExpr(node, "and/or function must have at least 1 argument")
+ }
+ op := "or"
+ if p.isAnd {
+ op = "and"
+ }
+
+ argsParsed := make([]starlarkExpr, 0)
+
+ for _, arg := range args.Split(",") {
+ arg.TrimLeftSpaces()
+ arg.TrimRightSpaces()
+ x := ctx.parseMakeString(node, arg)
+ if xBad, ok := x.(*badExpr); ok {
+ return xBad
+ }
+ argsParsed = append(argsParsed, x)
+ }
+ typ := starlarkTypeUnknown
+ for _, arg := range argsParsed {
+ if typ != arg.typ() && arg.typ() != starlarkTypeUnknown && typ != starlarkTypeUnknown {
+ return ctx.newBadExpr(node, "Expected all arguments to $(or) or $(and) to have the same type, found %q and %q", typ.String(), arg.typ().String())
+ }
+ if arg.typ() != starlarkTypeUnknown {
+ typ = arg.typ()
+ }
+ }
+ result := argsParsed[0]
+ for _, arg := range argsParsed[1:] {
+ result = &binaryOpExpr{
+ left: result,
+ right: arg,
+ op: op,
+ returnType: typ,
+ }
+ }
+ return result
+}
+
type isProductInListCallParser struct{}
func (p *isProductInListCallParser) parse(ctx *parseContext, node mkparser.Node, args *mkparser.MakeString) starlarkExpr {
@@ -1848,6 +1897,24 @@
return []starlarkNode{ctx.newBadNode(node, "Eval expression too complex; only assignments, comments, includes, and inherit-products are supported")}
}
+type lowerUpperParser struct {
+ isUpper bool
+}
+
+func (p *lowerUpperParser) parse(ctx *parseContext, node mkparser.Node, args *mkparser.MakeString) starlarkExpr {
+ fn := "lower"
+ if p.isUpper {
+ fn = "upper"
+ }
+ arg := ctx.parseMakeString(node, args)
+
+ return &callExpr{
+ object: arg,
+ name: fn,
+ returnType: starlarkTypeString,
+ }
+}
+
func (ctx *parseContext) parseMakeString(node mkparser.Node, mk *mkparser.MakeString) starlarkExpr {
if mk.Const() {
return &stringLiteralExpr{mk.Dump()}
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 31555d3..65a3be7 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -1629,6 +1629,58 @@
g["MY_VAR_5"] = rblf.mk2rbc_error("product.mk:6", "reference is too complex: $(MY_VAR_2) bar")
`,
},
+ {
+ desc: "Conditional functions",
+ mkname: "product.mk",
+ in: `
+B := foo
+X := $(or $(A))
+X := $(or $(A),$(B))
+X := $(or $(A),$(B),$(C))
+X := $(and $(A))
+X := $(and $(A),$(B))
+X := $(and $(A),$(B),$(C))
+X := $(or $(A),$(B)) Y
+
+D := $(wildcard *.mk)
+X := $(or $(B),$(D))
+`,
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ g["B"] = "foo"
+ g["X"] = g.get("A", "")
+ g["X"] = g.get("A", "") or g["B"]
+ g["X"] = g.get("A", "") or g["B"] or g.get("C", "")
+ g["X"] = g.get("A", "")
+ g["X"] = g.get("A", "") and g["B"]
+ g["X"] = g.get("A", "") and g["B"] and g.get("C", "")
+ g["X"] = "%s Y" % g.get("A", "") or g["B"]
+ g["D"] = rblf.expand_wildcard("*.mk")
+ g["X"] = rblf.mk2rbc_error("product.mk:12", "Expected all arguments to $(or) or $(and) to have the same type, found \"string\" and \"list\"")
+`,
+ },
+ {
+
+ desc: "is-lower/is-upper",
+ mkname: "product.mk",
+ in: `
+X := $(call to-lower,aBc)
+X := $(call to-upper,aBc)
+X := $(call to-lower,$(VAR))
+X := $(call to-upper,$(VAR))
+`,
+ expected: `load("//build/make/core:product_config.rbc", "rblf")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ g["X"] = ("aBc").lower()
+ g["X"] = ("aBc").upper()
+ g["X"] = (g.get("VAR", "")).lower()
+ g["X"] = (g.get("VAR", "")).upper()
+`,
+ },
}
var known_variables = []struct {
diff --git a/mk2rbc/types.go b/mk2rbc/types.go
index 46c6aa9..ac32507 100644
--- a/mk2rbc/types.go
+++ b/mk2rbc/types.go
@@ -14,6 +14,8 @@
package mk2rbc
+import "fmt"
+
// Starlark expression types we use
type starlarkType int
@@ -31,6 +33,25 @@
starlarkTypeVoid starlarkType = iota
)
+func (t starlarkType) String() string {
+ switch t {
+ case starlarkTypeList:
+ return "list"
+ case starlarkTypeString:
+ return "string"
+ case starlarkTypeInt:
+ return "int"
+ case starlarkTypeBool:
+ return "bool"
+ case starlarkTypeVoid:
+ return "void"
+ case starlarkTypeUnknown:
+ return "unknown"
+ default:
+ panic(fmt.Sprintf("Unknown starlark type %d", t))
+ }
+}
+
type hiddenArgType int
const (
diff --git a/scripts/unpack-prebuilt-apex.sh b/scripts/unpack-prebuilt-apex.sh
index f34a480..b244f79 100755
--- a/scripts/unpack-prebuilt-apex.sh
+++ b/scripts/unpack-prebuilt-apex.sh
@@ -17,23 +17,28 @@
# limitations under the License.
# Tool to unpack an apex file and verify that the required files were extracted.
-if [ $# -lt 5 ]; then
- echo "usage: $0 <deapaxer_path> <debugfs_path> <apex file> <output_dir> <required_files>+" >&2
+if [ $# -lt 7 ]; then
+ echo "usage: $0 <deapaxer_path> <debugfs_path> <blkid_path> <fsck.erofs_path> <apex file> <output_dir> <required_files>+" >&2
exit 1
fi
DEAPEXER_PATH=$1
DEBUGFS_PATH=$2
-APEX_FILE=$3
-OUTPUT_DIR=$4
-shift 4
+BLKID_PATH=$3
+FSCK_EROFS_PATH=$4
+APEX_FILE=$5
+OUTPUT_DIR=$6
+shift 6
REQUIRED_PATHS=$@
rm -fr $OUTPUT_DIR
mkdir -p $OUTPUT_DIR
# Unpack the apex file contents.
-$DEAPEXER_PATH --debugfs_path $DEBUGFS_PATH extract $APEX_FILE $OUTPUT_DIR
+$DEAPEXER_PATH --debugfs_path $DEBUGFS_PATH \
+ --blkid_path $BLKID_PATH \
+ --fsckerofs_path $FSCK_EROFS_PATH \
+ extract $APEX_FILE $OUTPUT_DIR
# Verify that the files that the build expects to be in the .apex file actually
# exist, and make sure they have a fresh mtime to not confuse ninja.
diff --git a/tests/apex_comparison_tests.sh b/tests/apex_comparison_tests.sh
index bfcf42d..d579429 100755
--- a/tests/apex_comparison_tests.sh
+++ b/tests/apex_comparison_tests.sh
@@ -68,10 +68,10 @@
//system/timezone/apex:com.android.tzdata \
//build/bazel/examples/apex/minimal:build.bazel.examples.apex.minimal.apex
-# Build debugfs separately, as it's not a dep of apexer, but needs to be an explicit arg.
+# # Build debugfs separately, as it's not a dep of apexer, but needs to be an explicit arg.
call_bazel build --config=bp2build --config=linux_x86_64 //external/e2fsprogs/debugfs //system/apex/tools:deapexer
-DEBUGFS_PATH="$BAZEL_OUT/linux_x86_64-fastbuild/bin/external/e2fsprogs/debugfs/debugfs"
-DEAPEXER="$BAZEL_OUT/linux_x86_64-fastbuild/bin/system/apex/tools/deapexer --debugfs_path=$DEBUGFS_PATH"
+DEBUGFS_PATH="$BAZEL_OUT/linux_x86_64-opt/bin/external/e2fsprogs/debugfs/debugfs"
+DEAPEXER="$BAZEL_OUT/linux_x86_64-opt/bin/system/apex/tools/deapexer --debugfs_path=$DEBUGFS_PATH"
#######
# Tests
@@ -83,7 +83,7 @@
# Compare the outputs of `deapexer list`, which lists the contents of the apex filesystem image.
local SOONG_APEX="$SOONG_OUTPUT_DIR/$APEX"
- local BAZEL_APEX="$BAZEL_OUT/android_target-fastbuild/bin/$APEX_DIR/$APEX"
+ local BAZEL_APEX="$BAZEL_OUT/android_target-opt/bin/$APEX_DIR/$APEX"
local SOONG_LIST="$OUTPUT_DIR/soong.list"
local BAZEL_LIST="$OUTPUT_DIR/bazel.list"
diff --git a/tests/bootstrap_test.sh b/tests/bootstrap_test.sh
index 7925ab0..17b4419 100755
--- a/tests/bootstrap_test.sh
+++ b/tests/bootstrap_test.sh
@@ -890,34 +890,4 @@
fi
}
-test_smoke
-test_null_build
-test_soong_docs_smoke
-test_null_build_after_soong_docs
-test_soong_build_rebuilt_if_blueprint_changes
-test_glob_noop_incremental
-test_add_file_to_glob
-test_add_android_bp
-test_change_android_bp
-test_delete_android_bp
-test_add_file_to_soong_build
-test_glob_during_bootstrapping
-test_soong_build_rerun_iff_environment_changes
-test_create_global_include_directory
-test_multiple_soong_build_modes
-test_dump_json_module_graph
-test_json_module_graph_back_and_forth_null_build
-test_write_to_source_tree
-test_queryview_smoke
-test_queryview_null_build
-test_bp2build_smoke
-test_bp2build_generates_marker_file
-test_bp2build_null_build
-test_bp2build_back_and_forth_null_build
-test_bp2build_add_android_bp
-test_bp2build_add_irrelevant_file
-test_bp2build_add_to_glob
-test_bp2build_bazel_workspace_structure
-test_bp2build_bazel_workspace_add_file
-test_bp2build_build_file_precedence
-test_bp2build_reports_multiple_errors
+scan_and_run_tests
diff --git a/tests/bp2build_bazel_test.sh b/tests/bp2build_bazel_test.sh
index 679ac55..07738b7 100755
--- a/tests/bp2build_bazel_test.sh
+++ b/tests/bp2build_bazel_test.sh
@@ -8,7 +8,7 @@
readonly GENERATED_BUILD_FILE_NAME="BUILD.bazel"
-function test_bp2build_null_build() {
+function test_bp2build_null_build {
setup
run_soong bp2build
local -r output_mtime1=$(stat -c "%y" out/soong/bp2build_workspace_marker)
@@ -21,9 +21,7 @@
fi
}
-test_bp2build_null_build
-
-function test_bp2build_null_build_with_globs() {
+function test_bp2build_null_build_with_globs {
setup
mkdir -p foo/bar
@@ -46,8 +44,6 @@
fi
}
-test_bp2build_null_build_with_globs
-
function test_different_relative_outdir {
setup
@@ -68,8 +64,6 @@
(export OUT_DIR=$outdir; run_soong bp2build && run_bazel build --config=bp2build //a:g)
}
-test_different_relative_outdir
-
function test_different_absolute_outdir {
setup
@@ -90,9 +84,7 @@
(export OUT_DIR=$outdir; run_soong bp2build && run_bazel build --config=bp2build //a:g)
}
-test_different_absolute_outdir
-
-function test_bp2build_generates_all_buildfiles {
+function _bp2build_generates_all_buildfiles {
setup
mkdir -p foo/convertible_soong_module
@@ -148,7 +140,7 @@
# NOTE: We don't actually use the extra BUILD file for anything here
run_bazel build --config=android --package_path=out/soong/workspace //foo/...
- local the_answer_file="bazel-out/android_target-fastbuild/bin/foo/convertible_soong_module/the_answer.txt"
+ local the_answer_file="bazel-out/android_target-opt/bin/foo/convertible_soong_module/the_answer.txt"
if [[ ! -f "${the_answer_file}" ]]; then
fail "Expected '${the_answer_file}' to be generated, but was missing"
fi
@@ -157,10 +149,12 @@
fi
}
-_save_trap=$(trap -p EXIT)
-trap '[[ $? -ne 0 ]] && echo Are you running this locally? Try changing --sandbox_tmpfs_path to something other than /tmp/ in build/bazel/linux.bazelrc.' EXIT
-test_bp2build_generates_all_buildfiles
-eval ${_save_trap}
+function test_bp2build_generates_all_buildfiles {
+ _save_trap=$(trap -p EXIT)
+ trap '[[ $? -ne 0 ]] && echo Are you running this locally? Try changing --sandbox_tmpfs_path to something other than /tmp/ in build/bazel/linux.bazelrc.' EXIT
+ _bp2build_generates_all_buildfiles
+ eval "${_save_trap}"
+}
function test_cc_correctness {
setup
@@ -213,8 +207,6 @@
fi
}
-test_cc_correctness
-
# Regression test for the following failure during symlink forest creation:
#
# Cannot stat '/tmp/st.rr054/foo/bar/unresolved_symlink': stat /tmp/st.rr054/foo/bar/unresolved_symlink: no such file or directory
@@ -239,4 +231,4 @@
fi
}
-test_bp2build_null_build_with_unresolved_symlink_in_source
+scan_and_run_tests
diff --git a/tests/lib.sh b/tests/lib.sh
index e40f0ad..f68199a 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -150,3 +150,16 @@
export ALLOW_MISSING_DEPENDENCIES=true
export ALLOW_BP_UNDER_SYMLINKS=true
warmup_mock_top
+
+function scan_and_run_tests {
+ # find all test_ functions
+ # NB "declare -F" output is sorted, hence test order is deterministic
+ readarray -t test_fns < <(declare -F | sed -n -e 's/^declare -f \(test_.*\)$/\1/p')
+ info "Found ${#test_fns[*]} tests"
+ if [[ ${#test_fns[*]} -eq 0 ]]; then
+ fail "No tests found"
+ fi
+ for f in ${test_fns[*]}; do
+ $f
+ done
+}
\ No newline at end of file