Merge "Revert "Integrate Rust-specific System Properties into rules generation."" into main
diff --git a/Android.bp b/Android.bp
index 63de015..b1db8e9 100644
--- a/Android.bp
+++ b/Android.bp
@@ -130,3 +130,8 @@
// Currently, only microdroid can refer to buildinfo.prop
visibility: ["//packages/modules/Virtualization/microdroid"],
}
+
+// container for apex_contributions selected using build flags
+all_apex_contributions {
+ name: "all_apex_contributions",
+}
diff --git a/OWNERS b/OWNERS
index 9221d3e..01025fb 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,30 +1,17 @@
+# Bug component: 99142
# This file is included by several other projects as the list of people
# approving build related projects.
# AMER
-agespino@google.com
ccross@android.com
colefaust@google.com
-cparsons@google.com
-dacek@google.com
-delmerico@google.com
dwillemsen@google.com
-eakammer@google.com
jihoonkang@google.com
-jobredeaux@google.com
joeo@google.com
-juu@google.com
lamontjones@google.com
mrziwang@google.com
spandandas@google.com
-tradical@google.com
-usta@google.com
-vinhdaitran@google.com
weiwli@google.com
yudiliu@google.com
-# APAC
-jingwen@google.com
-
-# EMEA
-lberki@google.com
+per-file build/soong/ui/build/androidmk_denylist.go = joeo@google.com, weiwli@google.com
\ No newline at end of file
diff --git a/README.md b/README.md
index 22daa95..f471c47 100644
--- a/README.md
+++ b/README.md
@@ -603,7 +603,7 @@
* [Build Performance](docs/perf.md)
* [Generating CLion Projects](docs/clion.md)
* [Generating YouCompleteMe/VSCode compile\_commands.json file](docs/compdb.md)
-* Make-specific documentation: [build/make/README.md](https://android.googlesource.com/platform/build/+/master/README.md)
+* Make-specific documentation: [build/make/README.md](https://android.googlesource.com/platform/build/+/main/README.md)
## Developing for Soong
@@ -648,8 +648,8 @@
SOONG_DELVE=2345 SOONG_DELVE_STEPS='build,modulegraph' m
```
results in only `build` (main build step) and `modulegraph` being run in the debugger.
-The allowed step names are `api_bp2build`, `bp2build_files`, `bp2build_workspace`,
-`build`, `modulegraph`, `queryview`, `soong_docs`.
+The allowed step names are `bp2build_files`, `bp2build_workspace`, `build`,
+`modulegraph`, `queryview`, `soong_docs`.
Note setting or unsetting `SOONG_DELVE` causes a recompilation of `soong_build`. This
is because in order to debug the binary, it needs to be built with debug
diff --git a/aconfig/Android.bp b/aconfig/Android.bp
index d2ddfdf..402cf16 100644
--- a/aconfig/Android.bp
+++ b/aconfig/Android.bp
@@ -11,27 +11,21 @@
"sbox_proto",
"soong",
"soong-android",
- "soong-bazel",
- "soong-android",
- "soong-java",
- "soong-rust",
],
srcs: [
"aconfig_declarations.go",
"aconfig_values.go",
"aconfig_value_set.go",
"all_aconfig_declarations.go",
- "cc_aconfig_library.go",
+ "exported_java_aconfig_library.go",
"init.go",
- "java_aconfig_library.go",
"testing.go",
- "rust_aconfig_library.go",
],
testSrcs: [
"aconfig_declarations_test.go",
"aconfig_values_test.go",
"aconfig_value_set_test.go",
- "java_aconfig_library_test.go",
+ "all_aconfig_declarations_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/aconfig/aconfig_declarations.go b/aconfig/aconfig_declarations.go
index 5cdf5b6..78f506a 100644
--- a/aconfig/aconfig_declarations.go
+++ b/aconfig/aconfig_declarations.go
@@ -15,10 +15,11 @@
package aconfig
import (
- "android/soong/android"
"fmt"
"strings"
+ "android/soong/android"
+
"github.com/google/blueprint"
)
@@ -36,6 +37,9 @@
// Values from TARGET_RELEASE / RELEASE_ACONFIG_VALUE_SETS
Values []string `blueprint:"mutated"`
+
+ // Container(system/vendor/apex) that this module belongs to
+ Container string
}
intermediatePath android.WritablePath
@@ -47,8 +51,6 @@
android.InitAndroidModule(module)
android.InitDefaultableModule(module)
module.AddProperties(&module.properties)
- // TODO: bp2build
- //android.InitBazelModule(module)
return module
}
@@ -68,12 +70,16 @@
if len(module.properties.Package) == 0 {
ctx.PropertyErrorf("package", "missing package property")
}
+ // TODO(b/311155208): Add mandatory check for container after all pre-existing
+ // ones are changed.
// Add a dependency on the aconfig_value_sets defined in
// RELEASE_ACONFIG_VALUE_SETS, and add any aconfig_values that
// match our package.
valuesFromConfig := ctx.Config().ReleaseAconfigValueSets()
- ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig...)
+ if len(valuesFromConfig) > 0 {
+ ctx.AddDependency(ctx.Module(), implicitValuesTag, valuesFromConfig...)
+ }
}
func (module *DeclarationsModule) OutputFiles(tag string) (android.Paths, error) {
@@ -106,42 +112,31 @@
return sb.String()
}
-// Provider published by aconfig_value_set
-type declarationsProviderData struct {
- Package string
- IntermediatePath android.WritablePath
-}
-
-var declarationsProviderKey = blueprint.NewProvider(declarationsProviderData{})
-
func (module *DeclarationsModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
// Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
valuesFiles := make([]android.Path, 0)
ctx.VisitDirectDeps(func(dep android.Module) {
- if !ctx.OtherModuleHasProvider(dep, valueSetProviderKey) {
- // Other modules get injected as dependencies too, for example the license modules
- return
- }
- depData := ctx.OtherModuleProvider(dep, valueSetProviderKey).(valueSetProviderData)
- paths, ok := depData.AvailablePackages[module.properties.Package]
- if ok {
- valuesFiles = append(valuesFiles, paths...)
- for _, path := range paths {
- module.properties.Values = append(module.properties.Values, path.String())
+ if depData, ok := android.OtherModuleProvider(ctx, dep, valueSetProviderKey); ok {
+ paths, ok := depData.AvailablePackages[module.properties.Package]
+ if ok {
+ valuesFiles = append(valuesFiles, paths...)
+ for _, path := range paths {
+ module.properties.Values = append(module.properties.Values, path.String())
+ }
}
}
})
// Intermediate format
declarationFiles := android.PathsForModuleSrc(ctx, module.properties.Srcs)
- intermediatePath := android.PathForModuleOut(ctx, "intermediate.pb")
+ intermediateCacheFilePath := android.PathForModuleOut(ctx, "intermediate.pb")
defaultPermission := ctx.Config().ReleaseAconfigFlagDefaultPermission()
inputFiles := make([]android.Path, len(declarationFiles))
copy(inputFiles, declarationFiles)
inputFiles = append(inputFiles, valuesFiles...)
ctx.Build(pctx, android.BuildParams{
Rule: aconfigRule,
- Output: intermediatePath,
+ Output: intermediateCacheFilePath,
Inputs: inputFiles,
Description: "aconfig_declarations",
Args: map[string]string{
@@ -153,9 +148,19 @@
},
})
- ctx.SetProvider(declarationsProviderKey, declarationsProviderData{
- Package: module.properties.Package,
- IntermediatePath: intermediatePath,
+ intermediateDumpFilePath := android.PathForModuleOut(ctx, "intermediate.txt")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: aconfigTextRule,
+ Output: intermediateDumpFilePath,
+ Inputs: android.Paths{intermediateCacheFilePath},
+ Description: "aconfig_text",
+ })
+
+ android.SetProvider(ctx, android.AconfigDeclarationsProviderKey, android.AconfigDeclarationsProviderData{
+ Package: module.properties.Package,
+ Container: module.properties.Container,
+ IntermediateCacheOutputPath: intermediateCacheFilePath,
+ IntermediateDumpOutputPath: intermediateDumpFilePath,
})
}
diff --git a/aconfig/aconfig_declarations_test.go b/aconfig/aconfig_declarations_test.go
index e0d8f7d..d508af7 100644
--- a/aconfig/aconfig_declarations_test.go
+++ b/aconfig/aconfig_declarations_test.go
@@ -26,6 +26,7 @@
aconfig_declarations {
name: "module_name",
package: "com.example.package",
+ container: "com.android.foo",
srcs: [
"foo.aconfig",
"bar.aconfig",
@@ -37,9 +38,13 @@
module := result.ModuleForTests("module_name", "").Module().(*DeclarationsModule)
// Check that the provider has the right contents
- depData := result.ModuleProvider(module, declarationsProviderKey).(declarationsProviderData)
+ depData, _ := android.SingletonModuleProvider(result, module, android.AconfigDeclarationsProviderKey)
android.AssertStringEquals(t, "package", depData.Package, "com.example.package")
- if !strings.HasSuffix(depData.IntermediatePath.String(), "/intermediate.pb") {
- t.Errorf("Missing intermediates path in provider: %s", depData.IntermediatePath.String())
+ android.AssertStringEquals(t, "container", depData.Container, "com.android.foo")
+ if !strings.HasSuffix(depData.IntermediateCacheOutputPath.String(), "/intermediate.pb") {
+ t.Errorf("Missing intermediates proto path in provider: %s", depData.IntermediateCacheOutputPath.String())
+ }
+ if !strings.HasSuffix(depData.IntermediateDumpOutputPath.String(), "/intermediate.txt") {
+ t.Errorf("Missing intermediates text path in provider: %s", depData.IntermediateDumpOutputPath.String())
}
}
diff --git a/aconfig/aconfig_value_set.go b/aconfig/aconfig_value_set.go
index 252908f..7ba76c0 100644
--- a/aconfig/aconfig_value_set.go
+++ b/aconfig/aconfig_value_set.go
@@ -36,8 +36,6 @@
android.InitAndroidModule(module)
android.InitDefaultableModule(module)
module.AddProperties(&module.properties)
- // TODO: bp2build
- //android.InitBazelModule(module)
return module
}
@@ -56,7 +54,7 @@
AvailablePackages map[string]android.Paths
}
-var valueSetProviderKey = blueprint.NewProvider(valueSetProviderData{})
+var valueSetProviderKey = blueprint.NewProvider[valueSetProviderData]()
func (module *ValueSetModule) DepsMutator(ctx android.BottomUpMutatorContext) {
deps := ctx.AddDependency(ctx.Module(), valueSetTag, module.properties.Values...)
@@ -75,18 +73,14 @@
// to append values to their aconfig actions.
packages := make(map[string]android.Paths)
ctx.VisitDirectDeps(func(dep android.Module) {
- if !ctx.OtherModuleHasProvider(dep, valuesProviderKey) {
- // Other modules get injected as dependencies too, for example the license modules
- return
+ if depData, ok := android.OtherModuleProvider(ctx, dep, valuesProviderKey); ok {
+ srcs := make([]android.Path, len(depData.Values))
+ copy(srcs, depData.Values)
+ packages[depData.Package] = srcs
}
- depData := ctx.OtherModuleProvider(dep, valuesProviderKey).(valuesProviderData)
-
- srcs := make([]android.Path, len(depData.Values))
- copy(srcs, depData.Values)
- packages[depData.Package] = srcs
})
- ctx.SetProvider(valueSetProviderKey, valueSetProviderData{
+ android.SetProvider(ctx, valueSetProviderKey, valueSetProviderData{
AvailablePackages: packages,
})
}
diff --git a/aconfig/aconfig_value_set_test.go b/aconfig/aconfig_value_set_test.go
index 9127872..7d18999 100644
--- a/aconfig/aconfig_value_set_test.go
+++ b/aconfig/aconfig_value_set_test.go
@@ -38,6 +38,6 @@
module := result.ModuleForTests("module_name", "").Module().(*ValueSetModule)
// Check that the provider has the right contents
- depData := result.ModuleProvider(module, valueSetProviderKey).(valueSetProviderData)
+ depData, _ := android.SingletonModuleProvider(result, module, valueSetProviderKey)
android.AssertStringEquals(t, "AvailablePackages", "blah.aconfig_values", depData.AvailablePackages["foo.package"][0].String())
}
diff --git a/aconfig/aconfig_values.go b/aconfig/aconfig_values.go
index 91f1c90..239b10c 100644
--- a/aconfig/aconfig_values.go
+++ b/aconfig/aconfig_values.go
@@ -39,8 +39,6 @@
android.InitAndroidModule(module)
android.InitDefaultableModule(module)
module.AddProperties(&module.properties)
- // TODO: bp2build
- //android.InitBazelModule(module)
return module
}
@@ -54,7 +52,7 @@
Values android.Paths
}
-var valuesProviderKey = blueprint.NewProvider(valuesProviderData{})
+var valuesProviderKey = blueprint.NewProvider[valuesProviderData]()
func (module *ValuesModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
if len(module.properties.Package) == 0 {
@@ -66,5 +64,5 @@
Package: module.properties.Package,
Values: android.PathsForModuleSrc(ctx, module.properties.Srcs),
}
- ctx.SetProvider(valuesProviderKey, providerData)
+ android.SetProvider(ctx, valuesProviderKey, providerData)
}
diff --git a/aconfig/aconfig_values_test.go b/aconfig/aconfig_values_test.go
index ab457f0..526579c 100644
--- a/aconfig/aconfig_values_test.go
+++ b/aconfig/aconfig_values_test.go
@@ -33,7 +33,7 @@
module := result.ModuleForTests("module_name", "").Module().(*ValuesModule)
// Check that the provider has the right contents
- depData := result.ModuleProvider(module, valuesProviderKey).(valuesProviderData)
+ depData, _ := android.SingletonModuleProvider(result, module, valuesProviderKey)
android.AssertStringEquals(t, "package", "foo.package", depData.Package)
android.AssertPathsEndWith(t, "srcs", []string{"blah.aconfig_values"}, depData.Values)
}
diff --git a/aconfig/all_aconfig_declarations.go b/aconfig/all_aconfig_declarations.go
index 6096c6c..b6c9023 100644
--- a/aconfig/all_aconfig_declarations.go
+++ b/aconfig/all_aconfig_declarations.go
@@ -16,6 +16,7 @@
import (
"android/soong/android"
+ "fmt"
)
// A singleton module that collects all of the aconfig flags declared in the
@@ -35,19 +36,33 @@
func (this *allAconfigDeclarationsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
// Find all of the aconfig_declarations modules
+ var packages = make(map[string]int)
var cacheFiles android.Paths
ctx.VisitAllModules(func(module android.Module) {
- if !ctx.ModuleHasProvider(module, declarationsProviderKey) {
+ decl, ok := android.SingletonModuleProvider(ctx, module, android.AconfigDeclarationsProviderKey)
+ if !ok {
return
}
- decl := ctx.ModuleProvider(module, declarationsProviderKey).(declarationsProviderData)
- cacheFiles = append(cacheFiles, decl.IntermediatePath)
+ cacheFiles = append(cacheFiles, decl.IntermediateCacheOutputPath)
+ packages[decl.Package]++
})
+ var numOffendingPkg = 0
+ for pkg, cnt := range packages {
+ if cnt > 1 {
+ fmt.Printf("%d aconfig_declarations found for package %s\n", cnt, pkg)
+ numOffendingPkg++
+ }
+ }
+
+ if numOffendingPkg > 0 {
+ panic(fmt.Errorf("Only one aconfig_declarations allowed for each package."))
+ }
+
// Generate build action for aconfig
this.intermediatePath = android.PathForIntermediates(ctx, "all_aconfig_declarations.pb")
ctx.Build(pctx, android.BuildParams{
- Rule: allDeclarationsRule,
+ Rule: AllDeclarationsRule,
Inputs: cacheFiles,
Output: this.intermediatePath,
Description: "all_aconfig_declarations",
diff --git a/aconfig/all_aconfig_declarations_test.go b/aconfig/all_aconfig_declarations_test.go
new file mode 100644
index 0000000..0b2021e
--- /dev/null
+++ b/aconfig/all_aconfig_declarations_test.go
@@ -0,0 +1,48 @@
+// Copyright 2024 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 aconfig
+
+import (
+ "testing"
+
+ "android/soong/android"
+)
+
+func TestTwoAconfigDeclarationsPerPackage(t *testing.T) {
+ bp := `
+ aconfig_declarations {
+ name: "module_name.foo",
+ package: "com.example.package",
+ container: "com.android.foo",
+ srcs: [
+ "foo.aconfig",
+ ],
+ }
+
+ aconfig_declarations {
+ name: "module_name.bar",
+ package: "com.example.package",
+ container: "com.android.foo",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ `
+ errMsg := "Only one aconfig_declarations allowed for each package."
+ android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents).
+ ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(errMsg)).
+ RunTestWithBp(t, bp)
+}
diff --git a/aconfig/codegen/Android.bp b/aconfig/codegen/Android.bp
new file mode 100644
index 0000000..494f7e6
--- /dev/null
+++ b/aconfig/codegen/Android.bp
@@ -0,0 +1,32 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-aconfig-codegen",
+ pkgPath: "android/soong/aconfig/codegen",
+ deps: [
+ "blueprint",
+ "blueprint-pathtools",
+ "sbox_proto",
+ "soong",
+ "soong-aconfig",
+ "soong-android",
+ "soong-bazel",
+ "soong-java",
+ "soong-rust",
+ ],
+ srcs: [
+ "cc_aconfig_library.go",
+ "init.go",
+ "java_aconfig_library.go",
+ "rust_aconfig_library.go",
+ "testing.go",
+ ],
+ testSrcs: [
+ "java_aconfig_library_test.go",
+ "cc_aconfig_library_test.go",
+ "rust_aconfig_library_test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/aconfig/cc_aconfig_library.go b/aconfig/codegen/cc_aconfig_library.go
similarity index 77%
rename from aconfig/cc_aconfig_library.go
rename to aconfig/codegen/cc_aconfig_library.go
index 14090bc..50cd4de 100644
--- a/aconfig/cc_aconfig_library.go
+++ b/aconfig/codegen/cc_aconfig_library.go
@@ -12,12 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package aconfig
+package codegen
import (
"android/soong/android"
"android/soong/cc"
+
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
"fmt"
"strings"
@@ -29,9 +31,18 @@
var ccDeclarationsTag = ccDeclarationsTagType{}
+const baseLibDep = "server_configurable_flags"
+
type CcAconfigLibraryProperties struct {
// name of the aconfig_declarations module to generate a library for
Aconfig_declarations string
+
+ // default mode is "production", the other accepted modes are:
+ // "test": to generate test mode version of the library
+ // "exported": to generate exported mode version of the library
+ // "force-read-only": to generate force-read-only mode version of the library
+ // an error will be thrown if the mode is not supported
+ Mode *string
}
type CcAconfigLibraryCallbacks struct {
@@ -66,8 +77,12 @@
ctx.AddDependency(ctx.Module(), ccDeclarationsTag, declarations)
}
- // Add a dependency for the aconfig flags base library
- deps.SharedLibs = append(deps.SharedLibs, "server_configurable_flags")
+ mode := proptools.StringDefault(this.properties.Mode, "production")
+
+ // Add a dependency for the aconfig flags base library if it is not forced read only
+ if mode != "force-read-only" {
+ deps.SharedLibs = append(deps.SharedLibs, baseLibDep)
+ }
// TODO: It'd be really nice if we could reexport this library and not make everyone do it.
return deps
@@ -81,7 +96,7 @@
if len(declarationsModules) != 1 {
panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
}
- declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)
+ declarations, _ := android.OtherModuleProvider(ctx, declarationsModules[0], android.AconfigDeclarationsProviderKey)
// Figure out the generated file paths. This has to match aconfig's codegen_cpp.rs.
this.generatedDir = android.PathForModuleGen(ctx)
@@ -111,11 +126,16 @@
if len(declarationsModules) != 1 {
panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
}
- declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)
+ declarations, _ := android.OtherModuleProvider(ctx, declarationsModules[0], android.AconfigDeclarationsProviderKey)
+
+ mode := proptools.StringDefault(this.properties.Mode, "production")
+ if !isModeSupported(mode) {
+ ctx.PropertyErrorf("mode", "%q is not a supported mode", mode)
+ }
ctx.Build(pctx, android.BuildParams{
Rule: cppRule,
- Input: declarations.IntermediatePath,
+ Input: declarations.IntermediateCacheOutputPath,
Outputs: []android.WritablePath{
this.generatedCpp,
this.generatedH,
@@ -123,6 +143,7 @@
Description: "cc_aconfig_library",
Args: map[string]string{
"gendir": this.generatedDir.String(),
+ "mode": mode,
},
})
}
diff --git a/aconfig/codegen/cc_aconfig_library_test.go b/aconfig/codegen/cc_aconfig_library_test.go
new file mode 100644
index 0000000..05449bc
--- /dev/null
+++ b/aconfig/codegen/cc_aconfig_library_test.go
@@ -0,0 +1,198 @@
+// Copyright 2023 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 codegen
+
+import (
+ "fmt"
+ "testing"
+
+ "android/soong/android"
+ "android/soong/cc"
+
+ "github.com/google/blueprint"
+)
+
+var ccCodegenModeTestData = []struct {
+ setting, expected string
+}{
+ {"", "production"},
+ {"mode: `production`,", "production"},
+ {"mode: `test`,", "test"},
+ {"mode: `exported`,", "exported"},
+ {"mode: `force-read-only`,", "force-read-only"},
+}
+
+func TestCCCodegenMode(t *testing.T) {
+ for _, testData := range ccCodegenModeTestData {
+ testCCCodegenModeHelper(t, testData.setting, testData.expected)
+ }
+}
+
+func testCCCodegenModeHelper(t *testing.T, bpMode string, ruleMode string) {
+ t.Helper()
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ cc.PrepareForTestWithCcDefaultModules).
+ ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
+ RunTestWithBp(t, fmt.Sprintf(`
+ aconfig_declarations {
+ name: "my_aconfig_declarations",
+ package: "com.example.package",
+ srcs: ["foo.aconfig"],
+ }
+
+ cc_library {
+ name: "server_configurable_flags",
+ srcs: ["server_configurable_flags.cc"],
+ }
+
+ cc_aconfig_library {
+ name: "my_cc_aconfig_library",
+ aconfig_declarations: "my_aconfig_declarations",
+ %s
+ }
+ `, bpMode))
+
+ module := result.ModuleForTests("my_cc_aconfig_library", "android_arm64_armv8-a_shared")
+ rule := module.Rule("cc_aconfig_library")
+ android.AssertStringEquals(t, "rule must contain test mode", rule.Args["mode"], ruleMode)
+}
+
+var incorrectCCCodegenModeTestData = []struct {
+ setting, expectedErr string
+}{
+ {"mode: `unsupported`,", "mode: \"unsupported\" is not a supported mode"},
+}
+
+func TestIncorrectCCCodegenMode(t *testing.T) {
+ for _, testData := range incorrectCCCodegenModeTestData {
+ testIncorrectCCCodegenModeHelper(t, testData.setting, testData.expectedErr)
+ }
+}
+
+func testIncorrectCCCodegenModeHelper(t *testing.T, bpMode string, err string) {
+ t.Helper()
+ android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ cc.PrepareForTestWithCcDefaultModules).
+ ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(err)).
+ RunTestWithBp(t, fmt.Sprintf(`
+ aconfig_declarations {
+ name: "my_aconfig_declarations",
+ package: "com.example.package",
+ srcs: ["foo.aconfig"],
+ }
+
+ cc_library {
+ name: "server_configurable_flags",
+ srcs: ["server_configurable_flags.cc"],
+ }
+
+ cc_aconfig_library {
+ name: "my_cc_aconfig_library",
+ aconfig_declarations: "my_aconfig_declarations",
+ %s
+ }
+ `, bpMode))
+}
+
+func TestAndroidMkCcLibrary(t *testing.T) {
+ bp := `
+ aconfig_declarations {
+ name: "my_aconfig_declarations_foo",
+ package: "com.example.package",
+ srcs: ["foo.aconfig"],
+ container: "vendor",
+ }
+
+ cc_aconfig_library {
+ name: "my_cc_aconfig_library_foo",
+ aconfig_declarations: "my_aconfig_declarations_foo",
+ vendor_available: true,
+ }
+
+ aconfig_declarations {
+ name: "my_aconfig_declarations_bar",
+ package: "com.example.package",
+ srcs: ["bar.aconfig"],
+ }
+
+ cc_aconfig_library {
+ name: "my_cc_aconfig_library_bar",
+ aconfig_declarations: "my_aconfig_declarations_bar",
+ vendor_available: true,
+ }
+
+ cc_library {
+ name: "my_cc_library",
+ srcs: [
+ "src/foo.cc",
+ ],
+ static_libs: [
+ "my_cc_aconfig_library_foo",
+ "my_cc_aconfig_library_bar",
+ ],
+ vendor: true,
+ }
+
+ cc_library {
+ name: "server_configurable_flags",
+ srcs: ["server_configurable_flags.cc"],
+ vendor_available: true,
+ }
+ `
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ cc.PrepareForTestWithCcDefaultModules).
+ ExtendWithErrorHandler(android.FixtureExpectsNoErrors).RunTestWithBp(t, bp)
+
+ module := result.ModuleForTests("my_cc_library", "android_vendor_arm64_armv8-a_shared").Module()
+
+ entry := android.AndroidMkEntriesForTest(t, result.TestContext, module)[0]
+
+ makeVar := entry.EntryMap["LOCAL_ACONFIG_FILES"]
+ android.EnsureListContainsSuffix(t, makeVar, "my_aconfig_declarations_foo/intermediate.pb")
+}
+
+func TestForceReadOnly(t *testing.T) {
+ t.Helper()
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ cc.PrepareForTestWithCcDefaultModules).
+ ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
+ RunTestWithBp(t, fmt.Sprintf(`
+ aconfig_declarations {
+ name: "my_aconfig_declarations",
+ package: "com.example.package",
+ srcs: ["foo.aconfig"],
+ }
+
+ cc_aconfig_library {
+ name: "my_cc_aconfig_library",
+ aconfig_declarations: "my_aconfig_declarations",
+ mode: "force-read-only",
+ }
+ `))
+
+ module := result.ModuleForTests("my_cc_aconfig_library", "android_arm64_armv8-a_shared").Module()
+ dependOnBaseLib := false
+ result.VisitDirectDeps(module, func(dep blueprint.Module) {
+ if dep.Name() == baseLibDep {
+ dependOnBaseLib = true
+ }
+ })
+ android.AssertBoolEquals(t, "should not have dependency on server_configuriable_flags",
+ dependOnBaseLib, false)
+}
diff --git a/aconfig/codegen/init.go b/aconfig/codegen/init.go
new file mode 100644
index 0000000..0bff9d2
--- /dev/null
+++ b/aconfig/codegen/init.go
@@ -0,0 +1,83 @@
+// Copyright 2023 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 codegen
+
+import (
+ "android/soong/android"
+
+ "github.com/google/blueprint"
+)
+
+var (
+ pctx = android.NewPackageContext("android/soong/aconfig/codegen")
+
+ // For java_aconfig_library: Generate java library
+ javaRule = pctx.AndroidStaticRule("java_aconfig_library",
+ blueprint.RuleParams{
+ Command: `rm -rf ${out}.tmp` +
+ ` && mkdir -p ${out}.tmp` +
+ ` && ${aconfig} create-java-lib` +
+ ` --mode ${mode}` +
+ ` --cache ${in}` +
+ ` --out ${out}.tmp` +
+ ` && $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` +
+ ` && rm -rf ${out}.tmp`,
+ CommandDeps: []string{
+ "$aconfig",
+ "$soong_zip",
+ },
+ Restat: true,
+ }, "mode")
+
+ // For cc_aconfig_library: Generate C++ library
+ cppRule = pctx.AndroidStaticRule("cc_aconfig_library",
+ blueprint.RuleParams{
+ Command: `rm -rf ${gendir}` +
+ ` && mkdir -p ${gendir}` +
+ ` && ${aconfig} create-cpp-lib` +
+ ` --mode ${mode}` +
+ ` --cache ${in}` +
+ ` --out ${gendir}`,
+ CommandDeps: []string{
+ "$aconfig",
+ },
+ }, "gendir", "mode")
+
+ // For rust_aconfig_library: Generate Rust library
+ rustRule = pctx.AndroidStaticRule("rust_aconfig_library",
+ blueprint.RuleParams{
+ Command: `rm -rf ${gendir}` +
+ ` && mkdir -p ${gendir}` +
+ ` && ${aconfig} create-rust-lib` +
+ ` --mode ${mode}` +
+ ` --cache ${in}` +
+ ` --out ${gendir}`,
+ CommandDeps: []string{
+ "$aconfig",
+ },
+ }, "gendir", "mode")
+)
+
+func init() {
+ RegisterBuildComponents(android.InitRegistrationContext)
+ pctx.HostBinToolVariable("aconfig", "aconfig")
+ pctx.HostBinToolVariable("soong_zip", "soong_zip")
+}
+
+func RegisterBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("cc_aconfig_library", CcAconfigLibraryFactory)
+ ctx.RegisterModuleType("java_aconfig_library", JavaDeclarationsLibraryFactory)
+ ctx.RegisterModuleType("rust_aconfig_library", RustAconfigLibraryFactory)
+}
diff --git a/aconfig/codegen/java_aconfig_library.go b/aconfig/codegen/java_aconfig_library.go
new file mode 100644
index 0000000..e6817e0
--- /dev/null
+++ b/aconfig/codegen/java_aconfig_library.go
@@ -0,0 +1,110 @@
+// Copyright 2023 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 codegen
+
+import (
+ "fmt"
+
+ "android/soong/android"
+ "android/soong/java"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+type declarationsTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+var declarationsTag = declarationsTagType{}
+
+var aconfigSupportedModes = []string{"production", "test", "exported", "force-read-only"}
+
+type JavaAconfigDeclarationsLibraryProperties struct {
+ // name of the aconfig_declarations module to generate a library for
+ Aconfig_declarations string
+
+ // default mode is "production", the other accepted modes are:
+ // "test": to generate test mode version of the library
+ // "exported": to generate exported mode version of the library
+ // "force-read-only": to generate force-read-only mode version of the library
+ // an error will be thrown if the mode is not supported
+ Mode *string
+}
+
+type JavaAconfigDeclarationsLibraryCallbacks struct {
+ properties JavaAconfigDeclarationsLibraryProperties
+}
+
+func JavaDeclarationsLibraryFactory() android.Module {
+ callbacks := &JavaAconfigDeclarationsLibraryCallbacks{}
+ return java.GeneratedJavaLibraryModuleFactory("java_aconfig_library", callbacks, &callbacks.properties)
+}
+
+func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) DepsMutator(module *java.GeneratedJavaLibraryModule, ctx android.BottomUpMutatorContext) {
+ declarations := callbacks.properties.Aconfig_declarations
+ if len(declarations) == 0 {
+ // TODO: Add test for this case
+ ctx.PropertyErrorf("aconfig_declarations", "aconfig_declarations property required")
+ } else {
+ ctx.AddDependency(ctx.Module(), declarationsTag, declarations)
+ }
+
+ // "libcore_aconfig_flags_lib" module has a circular dependency because the shared libraries
+ // are built on core_current and the module is used to flag the APIs in the core_current.
+ // http://b/316554963#comment2 has the details of the circular dependency chain.
+ // If a java_aconfig_library uses "none" sdk_version, it should include and build these
+ // annotation files as the shared library themselves.
+ var addLibraries bool = module.Library.Module.SdkVersion(ctx).Kind != android.SdkNone
+ if addLibraries {
+ // Add aconfig-annotations-lib as a dependency for the optimization / code stripping annotations
+ module.AddSharedLibrary("aconfig-annotations-lib")
+ // TODO(b/303773055): Remove the annotation after access issue is resolved.
+ module.AddSharedLibrary("unsupportedappusage")
+ }
+}
+
+func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuildActions(module *java.GeneratedJavaLibraryModule, ctx android.ModuleContext) android.Path {
+ // Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
+ declarationsModules := ctx.GetDirectDepsWithTag(declarationsTag)
+ if len(declarationsModules) != 1 {
+ panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
+ }
+ declarations, _ := android.OtherModuleProvider(ctx, declarationsModules[0], android.AconfigDeclarationsProviderKey)
+
+ // Generate the action to build the srcjar
+ srcJarPath := android.PathForModuleGen(ctx, ctx.ModuleName()+".srcjar")
+
+ mode := proptools.StringDefault(callbacks.properties.Mode, "production")
+ if !isModeSupported(mode) {
+ ctx.PropertyErrorf("mode", "%q is not a supported mode", mode)
+ }
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: javaRule,
+ Input: declarations.IntermediateCacheOutputPath,
+ Output: srcJarPath,
+ Description: "aconfig.srcjar",
+ Args: map[string]string{
+ "mode": mode,
+ },
+ })
+
+ return srcJarPath
+}
+
+func isModeSupported(mode string) bool {
+ return android.InList(mode, aconfigSupportedModes)
+}
diff --git a/aconfig/java_aconfig_library_test.go b/aconfig/codegen/java_aconfig_library_test.go
similarity index 69%
rename from aconfig/java_aconfig_library_test.go
rename to aconfig/codegen/java_aconfig_library_test.go
index af50848..85d2675 100644
--- a/aconfig/java_aconfig_library_test.go
+++ b/aconfig/codegen/java_aconfig_library_test.go
@@ -12,11 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package aconfig
+package codegen
import (
"fmt"
- "strings"
"testing"
"android/soong/android"
@@ -34,14 +33,25 @@
ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
RunTestWithBp(t, bp+`
aconfig_declarations {
- name: "my_aconfig_declarations",
- package: "com.example.package",
+ name: "my_aconfig_declarations_foo",
+ package: "com.example.package.foo",
srcs: ["foo.aconfig"],
}
java_aconfig_library {
- name: "my_java_aconfig_library",
- aconfig_declarations: "my_aconfig_declarations",
+ name: "my_java_aconfig_library_foo",
+ aconfig_declarations: "my_aconfig_declarations_foo",
+ }
+
+ aconfig_declarations {
+ name: "my_aconfig_declarations_bar",
+ package: "com.example.package.bar",
+ srcs: ["bar.aconfig"],
+ }
+
+ java_aconfig_library {
+ name: "my_java_aconfig_library_bar",
+ aconfig_declarations: "my_aconfig_declarations_bar",
}
`)
@@ -50,10 +60,7 @@
entry := android.AndroidMkEntriesForTest(t, result.TestContext, module)[0]
makeVar := entry.EntryMap["LOCAL_ACONFIG_FILES"]
- android.AssertIntEquals(t, "len(LOCAL_ACONFIG_FILES)", 1, len(makeVar))
- if !strings.HasSuffix(makeVar[0], "intermediate.pb") {
- t.Errorf("LOCAL_ACONFIG_FILES should end with /intermediates.pb, instead it is: %s", makeVar[0])
- }
+ android.EnsureListContainsSuffix(t, makeVar, "android_common/aconfig_merged.pb")
}
func TestAndroidMkJavaLibrary(t *testing.T) {
@@ -64,7 +71,8 @@
"src/foo.java",
],
static_libs: [
- "my_java_aconfig_library",
+ "my_java_aconfig_library_foo",
+ "my_java_aconfig_library_bar",
],
platform_apis: true,
}
@@ -81,7 +89,8 @@
"src/foo.java",
],
static_libs: [
- "my_java_aconfig_library",
+ "my_java_aconfig_library_foo",
+ "my_java_aconfig_library_bar",
],
platform_apis: true,
}
@@ -98,7 +107,8 @@
"src/foo.java",
],
static_libs: [
- "my_java_aconfig_library",
+ "my_java_aconfig_library_foo",
+ "my_java_aconfig_library_bar",
],
platform_apis: true,
main_class: "foo",
@@ -116,7 +126,8 @@
"src/foo.java",
],
static_libs: [
- "my_java_aconfig_library",
+ "my_java_aconfig_library_foo",
+ "my_java_aconfig_library_bar",
],
platform_apis: true,
}
@@ -134,7 +145,8 @@
"src/foo.java",
],
static_libs: [
- "my_java_aconfig_library",
+ "my_java_aconfig_library_foo",
+ "my_java_aconfig_library_bar",
],
platform_apis: true,
}
@@ -178,14 +190,46 @@
android.AssertStringEquals(t, "rule must contain test mode", rule.Args["mode"], ruleMode)
}
+func testCodegenModeWithError(t *testing.T, bpMode string, err string) {
+ android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ java.PrepareForTestWithJavaDefaultModules).
+ ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(err)).
+ RunTestWithBp(t, fmt.Sprintf(`
+ aconfig_declarations {
+ name: "my_aconfig_declarations",
+ package: "com.example.package",
+ srcs: ["foo.aconfig"],
+ }
+
+ java_aconfig_library {
+ name: "my_java_aconfig_library",
+ aconfig_declarations: "my_aconfig_declarations",
+ %s
+ }
+ `, bpMode))
+}
+
func TestDefaultProdMode(t *testing.T) {
testCodegenMode(t, "", "production")
}
func TestProdMode(t *testing.T) {
- testCodegenMode(t, "test: false,", "production")
+ testCodegenMode(t, "mode: `production`,", "production")
}
func TestTestMode(t *testing.T) {
- testCodegenMode(t, "test: true,", "test")
+ testCodegenMode(t, "mode: `test`,", "test")
+}
+
+func TestExportedMode(t *testing.T) {
+ testCodegenMode(t, "mode: `exported`,", "exported")
+}
+
+func TestForceReadOnlyMode(t *testing.T) {
+ testCodegenMode(t, "mode: `force-read-only`,", "force-read-only")
+}
+
+func TestUnsupportedMode(t *testing.T) {
+ testCodegenModeWithError(t, "mode: `unsupported`,", "mode: \"unsupported\" is not a supported mode")
}
diff --git a/aconfig/rust_aconfig_library.go b/aconfig/codegen/rust_aconfig_library.go
similarity index 76%
rename from aconfig/rust_aconfig_library.go
rename to aconfig/codegen/rust_aconfig_library.go
index de41776..2ab54b6 100644
--- a/aconfig/rust_aconfig_library.go
+++ b/aconfig/codegen/rust_aconfig_library.go
@@ -1,9 +1,10 @@
-package aconfig
+package codegen
import (
+ "fmt"
+
"android/soong/android"
"android/soong/rust"
- "fmt"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -18,7 +19,13 @@
type RustAconfigLibraryProperties struct {
// name of the aconfig_declarations module to generate a library for
Aconfig_declarations string
- Test *bool
+
+ // default mode is "production", the other accepted modes are:
+ // "test": to generate test mode version of the library
+ // "exported": to generate exported mode version of the library
+ // "force-read-only": to generate force-read-only mode version of the library
+ // an error will be thrown if the mode is not supported
+ Mode *string
}
type aconfigDecorator struct {
@@ -58,16 +65,16 @@
if len(declarationsModules) != 1 {
panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
}
- declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)
+ declarations, _ := android.OtherModuleProvider(ctx, declarationsModules[0], android.AconfigDeclarationsProviderKey)
- mode := "production"
- if proptools.Bool(a.Properties.Test) {
- mode = "test"
+ mode := proptools.StringDefault(a.Properties.Mode, "production")
+ if !isModeSupported(mode) {
+ ctx.PropertyErrorf("mode", "%q is not a supported mode", mode)
}
ctx.Build(pctx, android.BuildParams{
Rule: rustRule,
- Input: declarations.IntermediatePath,
+ Input: declarations.IntermediateCacheOutputPath,
Outputs: []android.WritablePath{
generatedSource,
},
@@ -84,6 +91,7 @@
func (a *aconfigDecorator) SourceProviderDeps(ctx rust.DepsContext, deps rust.Deps) rust.Deps {
deps = a.BaseSourceProvider.SourceProviderDeps(ctx, deps)
deps.Rustlibs = append(deps.Rustlibs, "libflags_rust")
+ deps.Rustlibs = append(deps.Rustlibs, "liblazy_static")
ctx.AddDependency(ctx.Module(), rustDeclarationsTag, a.Properties.Aconfig_declarations)
return deps
}
diff --git a/aconfig/codegen/rust_aconfig_library_test.go b/aconfig/codegen/rust_aconfig_library_test.go
new file mode 100644
index 0000000..60bc9f7
--- /dev/null
+++ b/aconfig/codegen/rust_aconfig_library_test.go
@@ -0,0 +1,160 @@
+package codegen
+
+import (
+ "fmt"
+ "testing"
+
+ "android/soong/android"
+ "android/soong/rust"
+)
+
+func TestRustAconfigLibrary(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ rust.PrepareForTestWithRustIncludeVndk,
+ android.PrepareForTestWithArchMutator,
+ android.PrepareForTestWithDefaults,
+ android.PrepareForTestWithPrebuilts,
+ ).
+ ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
+ RunTestWithBp(t, fmt.Sprintf(`
+ rust_library {
+ name: "libflags_rust", // test mock
+ crate_name: "flags_rust",
+ srcs: ["lib.rs"],
+ }
+ rust_library {
+ name: "liblazy_static", // test mock
+ crate_name: "lazy_static",
+ srcs: ["src/lib.rs"],
+ }
+ aconfig_declarations {
+ name: "my_aconfig_declarations",
+ package: "com.example.package",
+ srcs: ["foo.aconfig"],
+ }
+
+ rust_aconfig_library {
+ name: "libmy_rust_aconfig_library",
+ crate_name: "my_rust_aconfig_library",
+ aconfig_declarations: "my_aconfig_declarations",
+ }
+ `))
+
+ sourceVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_source")
+ rule := sourceVariant.Rule("rust_aconfig_library")
+ android.AssertStringEquals(t, "rule must contain production mode", rule.Args["mode"], "production")
+
+ dylibVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_dylib")
+ rlibRlibStdVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_rlib_rlib-std")
+ rlibDylibStdVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_rlib_dylib-std")
+
+ variants := []android.TestingModule{
+ dylibVariant,
+ rlibDylibStdVariant,
+ rlibRlibStdVariant,
+ }
+
+ for _, variant := range variants {
+ android.AssertStringEquals(
+ t,
+ "dylib variant builds from generated rust code",
+ "out/soong/.intermediates/libmy_rust_aconfig_library/android_arm64_armv8-a_source/gen/src/lib.rs",
+ variant.Rule("rustc").Inputs[0].RelativeToTop().String(),
+ )
+ }
+}
+
+var rustCodegenModeTestData = []struct {
+ setting, expected string
+}{
+ {"", "production"},
+ {"mode: `production`,", "production"},
+ {"mode: `test`,", "test"},
+ {"mode: `exported`,", "exported"},
+ {"mode: `force-read-only`,", "force-read-only"},
+}
+
+func TestRustCodegenMode(t *testing.T) {
+ for _, testData := range rustCodegenModeTestData {
+ testRustCodegenModeHelper(t, testData.setting, testData.expected)
+ }
+}
+
+func testRustCodegenModeHelper(t *testing.T, bpMode string, ruleMode string) {
+ t.Helper()
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ rust.PrepareForTestWithRustIncludeVndk).
+ ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
+ RunTestWithBp(t, fmt.Sprintf(`
+ rust_library {
+ name: "libflags_rust", // test mock
+ crate_name: "flags_rust",
+ srcs: ["lib.rs"],
+ }
+ rust_library {
+ name: "liblazy_static", // test mock
+ crate_name: "lazy_static",
+ srcs: ["src/lib.rs"],
+ }
+ aconfig_declarations {
+ name: "my_aconfig_declarations",
+ package: "com.example.package",
+ srcs: ["foo.aconfig"],
+ }
+ rust_aconfig_library {
+ name: "libmy_rust_aconfig_library",
+ crate_name: "my_rust_aconfig_library",
+ aconfig_declarations: "my_aconfig_declarations",
+ %s
+ }
+ `, bpMode))
+
+ module := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_source")
+ rule := module.Rule("rust_aconfig_library")
+ android.AssertStringEquals(t, "rule must contain test mode", rule.Args["mode"], ruleMode)
+}
+
+var incorrectRustCodegenModeTestData = []struct {
+ setting, expectedErr string
+}{
+ {"mode: `unsupported`,", "mode: \"unsupported\" is not a supported mode"},
+}
+
+func TestIncorrectRustCodegenMode(t *testing.T) {
+ for _, testData := range incorrectRustCodegenModeTestData {
+ testIncorrectRustCodegenModeHelper(t, testData.setting, testData.expectedErr)
+ }
+}
+
+func testIncorrectRustCodegenModeHelper(t *testing.T, bpMode string, err string) {
+ t.Helper()
+ android.GroupFixturePreparers(
+ PrepareForTestWithAconfigBuildComponents,
+ rust.PrepareForTestWithRustIncludeVndk).
+ ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(err)).
+ RunTestWithBp(t, fmt.Sprintf(`
+ rust_library {
+ name: "libflags_rust", // test mock
+ crate_name: "flags_rust",
+ srcs: ["lib.rs"],
+ }
+ rust_library {
+ name: "liblazy_static", // test mock
+ crate_name: "lazy_static",
+ srcs: ["src/lib.rs"],
+ }
+ aconfig_declarations {
+ name: "my_aconfig_declarations",
+ package: "com.example.package",
+ srcs: ["foo.aconfig"],
+ }
+ rust_aconfig_library {
+ name: "libmy_rust_aconfig_library",
+ crate_name: "my_rust_aconfig_library",
+ aconfig_declarations: "my_aconfig_declarations",
+ %s
+ }
+ `, bpMode))
+}
diff --git a/aconfig/codegen/testing.go b/aconfig/codegen/testing.go
new file mode 100644
index 0000000..3e1c22e
--- /dev/null
+++ b/aconfig/codegen/testing.go
@@ -0,0 +1,25 @@
+// Copyright (C) 2021 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.
+
+package codegen
+
+import (
+ "android/soong/aconfig"
+ "android/soong/android"
+)
+
+var PrepareForTestWithAconfigBuildComponents = android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("aconfig_declarations", aconfig.DeclarationsFactory)
+ RegisterBuildComponents(ctx)
+})
diff --git a/aconfig/exported_java_aconfig_library.go b/aconfig/exported_java_aconfig_library.go
new file mode 100644
index 0000000..291938f
--- /dev/null
+++ b/aconfig/exported_java_aconfig_library.go
@@ -0,0 +1,56 @@
+// Copyright 2023 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 aconfig
+
+import (
+ "android/soong/android"
+)
+
+func ExportedJavaDeclarationsLibraryFactory() android.Singleton {
+ return &exportedJavaDeclarationsLibrarySingleton{}
+}
+
+type exportedJavaDeclarationsLibrarySingleton struct {
+ intermediatePath android.OutputPath
+}
+
+func (this *exportedJavaDeclarationsLibrarySingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ // Find all of the aconfig_declarations modules
+ var cacheFiles android.Paths
+ ctx.VisitAllModules(func(module android.Module) {
+ decl, ok := android.SingletonModuleProvider(ctx, module, android.AconfigDeclarationsProviderKey)
+ if !ok {
+ return
+ }
+ cacheFiles = append(cacheFiles, decl.IntermediateCacheOutputPath)
+ })
+
+ // Generate build action for aconfig
+ this.intermediatePath = android.PathForIntermediates(ctx, "exported_java_aconfig_library.jar")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: exportedJavaRule,
+ Inputs: cacheFiles,
+ Output: this.intermediatePath,
+ Description: "exported_java_aconfig_library",
+ Args: map[string]string{
+ "cache_files": android.JoinPathsWithPrefix(cacheFiles, " "),
+ },
+ })
+ ctx.Phony("exported_java_aconfig_library", this.intermediatePath)
+}
+
+func (this *exportedJavaDeclarationsLibrarySingleton) MakeVars(ctx android.MakeVarsContext) {
+ ctx.DistForGoalWithFilename("sdk", this.intermediatePath, "android-flags.jar")
+}
diff --git a/aconfig/init.go b/aconfig/init.go
index 797388d..3e9d297 100644
--- a/aconfig/init.go
+++ b/aconfig/init.go
@@ -40,74 +40,62 @@
Restat: true,
}, "release_version", "package", "declarations", "values", "default-permission")
- // For java_aconfig_library: Generate java file
- javaRule = pctx.AndroidStaticRule("java_aconfig_library",
+ // For create-device-config-sysprops: Generate aconfig flag value map text file
+ aconfigTextRule = pctx.AndroidStaticRule("aconfig_text",
blueprint.RuleParams{
- Command: `rm -rf ${out}.tmp` +
- ` && mkdir -p ${out}.tmp` +
- ` && ${aconfig} create-java-lib` +
- ` --mode ${mode}` +
- ` --cache ${in}` +
- ` --out ${out}.tmp` +
- ` && $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` +
- ` && rm -rf ${out}.tmp`,
- CommandDeps: []string{
- "$aconfig",
- "$soong_zip",
- },
- Restat: true,
- }, "mode")
-
- // For java_aconfig_library: Generate java file
- cppRule = pctx.AndroidStaticRule("cc_aconfig_library",
- blueprint.RuleParams{
- Command: `rm -rf ${gendir}` +
- ` && mkdir -p ${gendir}` +
- ` && ${aconfig} create-cpp-lib` +
- ` --cache ${in}` +
- ` --out ${gendir}`,
- CommandDeps: []string{
- "$aconfig",
- "$soong_zip",
- },
- }, "gendir")
-
- rustRule = pctx.AndroidStaticRule("rust_aconfig_library",
- blueprint.RuleParams{
- Command: `rm -rf ${gendir}` +
- ` && mkdir -p ${gendir}` +
- ` && ${aconfig} create-rust-lib` +
- ` --mode ${mode}` +
- ` --cache ${in}` +
- ` --out ${gendir}`,
- CommandDeps: []string{
- "$aconfig",
- "$soong_zip",
- },
- }, "gendir", "mode")
-
- // For all_aconfig_declarations
- allDeclarationsRule = pctx.AndroidStaticRule("all_aconfig_declarations_dump",
- blueprint.RuleParams{
- Command: `${aconfig} dump --format protobuf --out ${out} ${cache_files}`,
+ Command: `${aconfig} dump-cache --format='{fully_qualified_name}={state:bool}'` +
+ ` --cache ${in}` +
+ ` --out ${out}.tmp` +
+ ` && ( if cmp -s ${out}.tmp ${out} ; then rm ${out}.tmp ; else mv ${out}.tmp ${out} ; fi )`,
CommandDeps: []string{
"${aconfig}",
},
+ Restat: true,
+ })
+
+ // For all_aconfig_declarations: Combine all parsed_flags proto files
+ AllDeclarationsRule = pctx.AndroidStaticRule("All_aconfig_declarations_dump",
+ blueprint.RuleParams{
+ Command: `${aconfig} dump-cache --format protobuf --out ${out} ${cache_files}`,
+ CommandDeps: []string{
+ "${aconfig}",
+ },
+ }, "cache_files")
+
+ // For exported_java_aconfig_library: Generate a JAR from all
+ // java_aconfig_libraries to be consumed by apps built outside the
+ // platform
+ exportedJavaRule = pctx.AndroidStaticRule("exported_java_aconfig_library",
+ // For each aconfig cache file, if the cache contains any
+ // exported flags, generate Java flag lookup code for the
+ // exported flags (only). Finally collect all generated code
+ // into the ${out} JAR file.
+ blueprint.RuleParams{
+ Command: `rm -rf ${out}.tmp` +
+ `&& for cache in ${cache_files}; do ` +
+ ` if [ -n "$$(${aconfig} dump-cache --cache $$cache --filter=is_exported:true --format='{fully_qualified_name}')" ]; then ` +
+ ` ${aconfig} create-java-lib --cache $$cache --mode=exported --out ${out}.tmp; ` +
+ ` fi ` +
+ `done` +
+ `&& $soong_zip -write_if_changed -jar -o ${out} -C ${out}.tmp -D ${out}.tmp` +
+ `&& rm -rf ${out}.tmp`,
+ CommandDeps: []string{
+ "$aconfig",
+ "$soong_zip",
+ },
}, "cache_files")
)
func init() {
- registerBuildComponents(android.InitRegistrationContext)
+ RegisterBuildComponents(android.InitRegistrationContext)
pctx.HostBinToolVariable("aconfig", "aconfig")
pctx.HostBinToolVariable("soong_zip", "soong_zip")
}
-func registerBuildComponents(ctx android.RegistrationContext) {
+func RegisterBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("aconfig_declarations", DeclarationsFactory)
ctx.RegisterModuleType("aconfig_values", ValuesFactory)
ctx.RegisterModuleType("aconfig_value_set", ValueSetFactory)
- ctx.RegisterModuleType("cc_aconfig_library", CcAconfigLibraryFactory)
- ctx.RegisterModuleType("java_aconfig_library", JavaDeclarationsLibraryFactory)
- ctx.RegisterModuleType("rust_aconfig_library", RustAconfigLibraryFactory)
ctx.RegisterParallelSingletonType("all_aconfig_declarations", AllAconfigDeclarationsFactory)
+ ctx.RegisterParallelSingletonType("exported_java_aconfig_library", ExportedJavaDeclarationsLibraryFactory)
}
diff --git a/aconfig/java_aconfig_library.go b/aconfig/java_aconfig_library.go
deleted file mode 100644
index 4db0ef7..0000000
--- a/aconfig/java_aconfig_library.go
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2023 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 aconfig
-
-import (
- "android/soong/android"
- "android/soong/java"
- "fmt"
- "github.com/google/blueprint"
-)
-
-type declarationsTagType struct {
- blueprint.BaseDependencyTag
-}
-
-var declarationsTag = declarationsTagType{}
-
-type JavaAconfigDeclarationsLibraryProperties struct {
- // name of the aconfig_declarations module to generate a library for
- Aconfig_declarations string
-
- // whether to generate test mode version of the library
- Test bool
-}
-
-type JavaAconfigDeclarationsLibraryCallbacks struct {
- properties JavaAconfigDeclarationsLibraryProperties
-}
-
-func JavaDeclarationsLibraryFactory() android.Module {
- callbacks := &JavaAconfigDeclarationsLibraryCallbacks{}
- return java.GeneratedJavaLibraryModuleFactory("java_aconfig_library", callbacks, &callbacks.properties)
-}
-
-func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) DepsMutator(module *java.GeneratedJavaLibraryModule, ctx android.BottomUpMutatorContext) {
- declarations := callbacks.properties.Aconfig_declarations
- if len(declarations) == 0 {
- // TODO: Add test for this case
- ctx.PropertyErrorf("aconfig_declarations", "aconfig_declarations property required")
- } else {
- ctx.AddDependency(ctx.Module(), declarationsTag, declarations)
- }
-
- // Add aconfig-annotations-lib as a dependency for the optimization / code stripping annotations
- module.AddSharedLibrary("aconfig-annotations-lib")
-}
-
-func (callbacks *JavaAconfigDeclarationsLibraryCallbacks) GenerateSourceJarBuildActions(module *java.GeneratedJavaLibraryModule, ctx android.ModuleContext) android.Path {
- // Get the values that came from the global RELEASE_ACONFIG_VALUE_SETS flag
- declarationsModules := ctx.GetDirectDepsWithTag(declarationsTag)
- if len(declarationsModules) != 1 {
- panic(fmt.Errorf("Exactly one aconfig_declarations property required"))
- }
- declarations := ctx.OtherModuleProvider(declarationsModules[0], declarationsProviderKey).(declarationsProviderData)
-
- // Generate the action to build the srcjar
- srcJarPath := android.PathForModuleGen(ctx, ctx.ModuleName()+".srcjar")
- var mode string
- if callbacks.properties.Test {
- mode = "test"
- } else {
- mode = "production"
- }
- ctx.Build(pctx, android.BuildParams{
- Rule: javaRule,
- Input: declarations.IntermediatePath,
- Output: srcJarPath,
- Description: "aconfig.srcjar",
- Args: map[string]string{
- "mode": mode,
- },
- })
-
- // Tell the java module about the .aconfig files, so they can be propagated up the dependency chain.
- // TODO: It would be nice to have that propagation code here instead of on java.Module and java.JavaInfo.
- module.AddAconfigIntermediate(declarations.IntermediatePath)
-
- return srcJarPath
-}
diff --git a/aconfig/rust_aconfig_library_test.go b/aconfig/rust_aconfig_library_test.go
deleted file mode 100644
index 17385c3..0000000
--- a/aconfig/rust_aconfig_library_test.go
+++ /dev/null
@@ -1,60 +0,0 @@
-package aconfig
-
-import (
- "android/soong/android"
- "android/soong/rust"
- "fmt"
- "testing"
-)
-
-func TestRustAconfigLibrary(t *testing.T) {
- result := android.GroupFixturePreparers(
- PrepareForTestWithAconfigBuildComponents,
- rust.PrepareForTestWithRustIncludeVndk,
- android.PrepareForTestWithArchMutator,
- android.PrepareForTestWithDefaults,
- android.PrepareForTestWithPrebuilts,
- ).
- ExtendWithErrorHandler(android.FixtureExpectsNoErrors).
- RunTestWithBp(t, fmt.Sprintf(`
- rust_library {
- name: "libflags_rust", // test mock
- crate_name: "flags_rust",
- srcs: ["lib.rs"],
- }
- aconfig_declarations {
- name: "my_aconfig_declarations",
- package: "com.example.package",
- srcs: ["foo.aconfig"],
- }
-
- rust_aconfig_library {
- name: "libmy_rust_aconfig_library",
- crate_name: "my_rust_aconfig_library",
- aconfig_declarations: "my_aconfig_declarations",
- }
- `))
-
- sourceVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_source")
- rule := sourceVariant.Rule("rust_aconfig_library")
- android.AssertStringEquals(t, "rule must contain production mode", rule.Args["mode"], "production")
-
- dylibVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_dylib")
- rlibRlibStdVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_rlib_rlib-std")
- rlibDylibStdVariant := result.ModuleForTests("libmy_rust_aconfig_library", "android_arm64_armv8-a_rlib_dylib-std")
-
- variants := []android.TestingModule{
- dylibVariant,
- rlibDylibStdVariant,
- rlibRlibStdVariant,
- }
-
- for _, variant := range variants {
- android.AssertStringEquals(
- t,
- "dylib variant builds from generated rust code",
- "out/soong/.intermediates/libmy_rust_aconfig_library/android_arm64_armv8-a_source/gen/src/lib.rs",
- variant.Rule("rustc").Inputs[0].RelativeToTop().String(),
- )
- }
-}
diff --git a/aconfig/testing.go b/aconfig/testing.go
index 60cefeb..f6489ec 100644
--- a/aconfig/testing.go
+++ b/aconfig/testing.go
@@ -20,7 +20,7 @@
"android/soong/android"
)
-var PrepareForTestWithAconfigBuildComponents = android.FixtureRegisterWithContext(registerBuildComponents)
+var PrepareForTestWithAconfigBuildComponents = android.FixtureRegisterWithContext(RegisterBuildComponents)
func runTest(t *testing.T, errorHandler android.FixtureErrorHandler, bp string) *android.TestResult {
return android.GroupFixturePreparers(PrepareForTestWithAconfigBuildComponents).
diff --git a/aidl_library/aidl_library.go b/aidl_library/aidl_library.go
index 7449d67..0141545 100644
--- a/aidl_library/aidl_library.go
+++ b/aidl_library/aidl_library.go
@@ -16,8 +16,6 @@
import (
"android/soong/android"
- "android/soong/bazel"
-
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -53,57 +51,9 @@
type AidlLibrary struct {
android.ModuleBase
- android.BazelModuleBase
properties aidlLibraryProperties
}
-type bazelAidlLibraryAttributes struct {
- Srcs bazel.LabelListAttribute
- Hdrs bazel.LabelListAttribute
- Strip_import_prefix *string
- Deps bazel.LabelListAttribute
-}
-
-func (lib *AidlLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- srcs := bazel.MakeLabelListAttribute(
- android.BazelLabelForModuleSrc(
- ctx,
- lib.properties.Srcs,
- ),
- )
-
- hdrs := bazel.MakeLabelListAttribute(
- android.BazelLabelForModuleSrc(
- ctx,
- lib.properties.Hdrs,
- ),
- )
-
- tags := []string{"apex_available=//apex_available:anyapex"}
- deps := bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, lib.properties.Deps))
-
- attrs := &bazelAidlLibraryAttributes{
- Srcs: srcs,
- Hdrs: hdrs,
- Strip_import_prefix: lib.properties.Strip_import_prefix,
- Deps: deps,
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "aidl_library",
- Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
- }
-
- ctx.CreateBazelTargetModule(
- props,
- android.CommonAttributes{
- Name: lib.Name(),
- Tags: bazel.MakeStringListAttribute(tags),
- },
- attrs,
- )
-}
-
type AidlLibraryInfo struct {
// The direct aidl files of the module
Srcs android.Paths
@@ -114,7 +64,7 @@
}
// AidlLibraryProvider provides the srcs and the transitive include dirs
-var AidlLibraryProvider = blueprint.NewProvider(AidlLibraryInfo{})
+var AidlLibraryProvider = blueprint.NewProvider[AidlLibraryInfo]()
func (lib *AidlLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
includeDirsDepSetBuilder := android.NewDepSetBuilder[android.Path](android.PREORDER)
@@ -149,14 +99,13 @@
includeDirsDepSetBuilder.Direct(includeDir)
for _, dep := range ctx.GetDirectDepsWithTag(aidlLibraryTag) {
- if ctx.OtherModuleHasProvider(dep, AidlLibraryProvider) {
- info := ctx.OtherModuleProvider(dep, AidlLibraryProvider).(AidlLibraryInfo)
+ if info, ok := android.OtherModuleProvider(ctx, dep, AidlLibraryProvider); ok {
includeDirsDepSetBuilder.Transitive(&info.IncludeDirs)
hdrsDepSetBuilder.Transitive(&info.Hdrs)
}
}
- ctx.SetProvider(AidlLibraryProvider, AidlLibraryInfo{
+ android.SetProvider(ctx, AidlLibraryProvider, AidlLibraryInfo{
Srcs: srcs,
IncludeDirs: *includeDirsDepSetBuilder.Build(),
Hdrs: *hdrsDepSetBuilder.Build(),
@@ -170,7 +119,6 @@
module := &AidlLibrary{}
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
- android.InitBazelModule(module)
return module
}
diff --git a/aidl_library/aidl_library_test.go b/aidl_library/aidl_library_test.go
index 0205629..01eab0e 100644
--- a/aidl_library/aidl_library_test.go
+++ b/aidl_library/aidl_library_test.go
@@ -46,7 +46,7 @@
).RunTest(t).TestContext
foo := ctx.ModuleForTests("foo", "").Module().(*AidlLibrary)
- actualInfo := ctx.ModuleProvider(foo, AidlLibraryProvider).(AidlLibraryInfo)
+ actualInfo, _ := android.SingletonModuleProvider(ctx, foo, AidlLibraryProvider)
android.AssertArrayString(
t,
@@ -95,7 +95,7 @@
).RunTest(t).TestContext
foo := ctx.ModuleForTests("foo", "").Module().(*AidlLibrary)
- actualInfo := ctx.ModuleProvider(foo, AidlLibraryProvider).(AidlLibraryInfo)
+ actualInfo, _ := android.SingletonModuleProvider(ctx, foo, AidlLibraryProvider)
android.AssertArrayString(
t,
diff --git a/android/Android.bp b/android/Android.bp
index f5bb785..e73f355 100644
--- a/android/Android.bp
+++ b/android/Android.bp
@@ -11,15 +11,13 @@
"blueprint-metrics",
"sbox_proto",
"soong",
+ "soong-android_team_proto",
"soong-android-soongconfig",
- "soong-bazel",
- "soong-cquery",
"soong-remoteexec",
"soong-response",
"soong-shared",
"soong-starlark",
"soong-starlark-format",
- "soong-ui-bp2build_metrics_proto",
"soong-ui-metrics_proto",
"soong-android-allowlists",
@@ -30,15 +28,17 @@
"androidmk-parser",
],
srcs: [
+ "aconfig_providers.go",
+ "all_teams.go",
"androidmk.go",
"apex.go",
+ "apex_contributions.go",
"api_domain.go",
"api_levels.go",
"arch.go",
"arch_list.go",
- "bazel.go",
- "bazel_handler.go",
- "bazel_paths.go",
+ "arch_module_context.go",
+ "base_module_context.go",
"buildinfo_prop.go",
"config.go",
"test_config.go",
@@ -50,6 +50,7 @@
"defs.go",
"depset_generic.go",
"deptag.go",
+ "early_module_context.go",
"expand.go",
"filegroup.go",
"fixture.go",
@@ -64,6 +65,8 @@
"makevars.go",
"metrics.go",
"module.go",
+ "module_context.go",
+ "module_info_json.go",
"mutator.go",
"namespace.go",
"neverallow.go",
@@ -81,6 +84,8 @@
"prebuilt.go",
"prebuilt_build_tool.go",
"proto.go",
+ "provider.go",
+ "raw_files.go",
"register.go",
"rule_builder.go",
"sandbox.go",
@@ -89,6 +94,7 @@
"singleton.go",
"singleton_module.go",
"soong_config_modules.go",
+ "team.go",
"test_asserts.go",
"test_suites.go",
"testing.go",
@@ -102,11 +108,7 @@
"androidmk_test.go",
"apex_test.go",
"arch_test.go",
- "bazel_handler_test.go",
- "bazel_paths_test.go",
- "bazel_test.go",
"config_test.go",
- "config_bp2build_test.go",
"configured_jars_test.go",
"csuite_config_test.go",
"defaults_test.go",
diff --git a/android/aconfig_providers.go b/android/aconfig_providers.go
new file mode 100644
index 0000000..be9beb1
--- /dev/null
+++ b/android/aconfig_providers.go
@@ -0,0 +1,226 @@
+// Copyright 2023 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 android
+
+import (
+ "fmt"
+ "io"
+ "reflect"
+
+ "github.com/google/blueprint"
+)
+
+var (
+ mergeAconfigFilesRule = pctx.AndroidStaticRule("mergeAconfigFilesRule",
+ blueprint.RuleParams{
+ Command: `${aconfig} dump --dedup --format protobuf --out $out $flags`,
+ CommandDeps: []string{"${aconfig}"},
+ }, "flags")
+ _ = pctx.HostBinToolVariable("aconfig", "aconfig")
+)
+
+// Provider published by aconfig_value_set
+type AconfigDeclarationsProviderData struct {
+ Package string
+ Container string
+ IntermediateCacheOutputPath WritablePath
+ IntermediateDumpOutputPath WritablePath
+}
+
+var AconfigDeclarationsProviderKey = blueprint.NewProvider[AconfigDeclarationsProviderData]()
+
+// This is used to collect the aconfig declarations info on the transitive closure,
+// the data is keyed on the container.
+type AconfigTransitiveDeclarationsInfo struct {
+ AconfigFiles map[string]Paths
+}
+
+var AconfigTransitiveDeclarationsInfoProvider = blueprint.NewProvider[AconfigTransitiveDeclarationsInfo]()
+
+// CollectDependencyAconfigFiles is used by some module types to provide finer dependency graphing than
+// we can do in ModuleBase.
+func CollectDependencyAconfigFiles(ctx ModuleContext, mergedAconfigFiles *map[string]Paths) {
+ if *mergedAconfigFiles == nil {
+ *mergedAconfigFiles = make(map[string]Paths)
+ }
+ ctx.VisitDirectDepsIgnoreBlueprint(func(module Module) {
+ if dep, _ := OtherModuleProvider(ctx, module, AconfigDeclarationsProviderKey); dep.IntermediateCacheOutputPath != nil {
+ (*mergedAconfigFiles)[dep.Container] = append((*mergedAconfigFiles)[dep.Container], dep.IntermediateCacheOutputPath)
+ return
+ }
+ if dep, ok := OtherModuleProvider(ctx, module, aconfigPropagatingProviderKey); ok {
+ for container, v := range dep.AconfigFiles {
+ (*mergedAconfigFiles)[container] = append((*mergedAconfigFiles)[container], v...)
+ }
+ }
+ // We process these last, so that they determine the final value, eliminating any duplicates that we picked up
+ // from UpdateAndroidBuildActions.
+ if dep, ok := OtherModuleProvider(ctx, module, AconfigTransitiveDeclarationsInfoProvider); ok {
+ for container, v := range dep.AconfigFiles {
+ (*mergedAconfigFiles)[container] = append((*mergedAconfigFiles)[container], v...)
+ }
+ }
+ })
+
+ for container, aconfigFiles := range *mergedAconfigFiles {
+ (*mergedAconfigFiles)[container] = mergeAconfigFiles(ctx, container, aconfigFiles, false)
+ }
+
+ SetProvider(ctx, AconfigTransitiveDeclarationsInfoProvider, AconfigTransitiveDeclarationsInfo{
+ AconfigFiles: *mergedAconfigFiles,
+ })
+}
+
+func SetAconfigFileMkEntries(m *ModuleBase, entries *AndroidMkEntries, aconfigFiles map[string]Paths) {
+ setAconfigFileMkEntries(m, entries, aconfigFiles)
+}
+
+type aconfigPropagatingDeclarationsInfo struct {
+ AconfigFiles map[string]Paths
+}
+
+var aconfigPropagatingProviderKey = blueprint.NewProvider[aconfigPropagatingDeclarationsInfo]()
+
+func aconfigUpdateAndroidBuildActions(ctx ModuleContext) {
+ mergedAconfigFiles := make(map[string]Paths)
+ ctx.VisitDirectDepsIgnoreBlueprint(func(module Module) {
+ // If any of our dependencies have aconfig declarations (directly or propagated), then merge those and provide them.
+ if dep, ok := OtherModuleProvider(ctx, module, AconfigDeclarationsProviderKey); ok {
+ mergedAconfigFiles[dep.Container] = append(mergedAconfigFiles[dep.Container], dep.IntermediateCacheOutputPath)
+ }
+ if dep, ok := OtherModuleProvider(ctx, module, aconfigPropagatingProviderKey); ok {
+ for container, v := range dep.AconfigFiles {
+ mergedAconfigFiles[container] = append(mergedAconfigFiles[container], v...)
+ }
+ }
+ if dep, ok := OtherModuleProvider(ctx, module, AconfigTransitiveDeclarationsInfoProvider); ok {
+ for container, v := range dep.AconfigFiles {
+ mergedAconfigFiles[container] = append(mergedAconfigFiles[container], v...)
+ }
+ }
+ })
+ // We only need to set the provider if we have aconfig files.
+ if len(mergedAconfigFiles) > 0 {
+ for container, aconfigFiles := range mergedAconfigFiles {
+ mergedAconfigFiles[container] = mergeAconfigFiles(ctx, container, aconfigFiles, true)
+ }
+
+ SetProvider(ctx, aconfigPropagatingProviderKey, aconfigPropagatingDeclarationsInfo{
+ AconfigFiles: mergedAconfigFiles,
+ })
+ }
+}
+
+func aconfigUpdateAndroidMkData(ctx fillInEntriesContext, mod Module, data *AndroidMkData) {
+ info, ok := SingletonModuleProvider(ctx, mod, aconfigPropagatingProviderKey)
+ // If there is no aconfigPropagatingProvider, or there are no AconfigFiles, then we are done.
+ if !ok || len(info.AconfigFiles) == 0 {
+ return
+ }
+ data.Extra = append(data.Extra, func(w io.Writer, outputFile Path) {
+ AndroidMkEmitAssignList(w, "LOCAL_ACONFIG_FILES", getAconfigFilePaths(mod.base(), info.AconfigFiles).Strings())
+ })
+ // If there is a Custom writer, it needs to support this provider.
+ if data.Custom != nil {
+ switch reflect.TypeOf(mod).String() {
+ case "*aidl.aidlApi": // writes non-custom before adding .phony
+ case "*android_sdk.sdkRepoHost": // doesn't go through base_rules
+ case "*apex.apexBundle": // aconfig_file properties written
+ case "*bpf.bpf": // properties written (both for module and objs)
+ case "*genrule.Module": // writes non-custom before adding .phony
+ case "*java.SystemModules": // doesn't go through base_rules
+ case "*phony.phony": // properties written
+ case "*phony.PhonyRule": // writes phony deps and acts like `.PHONY`
+ case "*sysprop.syspropLibrary": // properties written
+ default:
+ panic(fmt.Errorf("custom make rules do not handle aconfig files for %q (%q) module %q", ctx.ModuleType(mod), reflect.TypeOf(mod), mod))
+ }
+ }
+}
+
+func aconfigUpdateAndroidMkEntries(ctx fillInEntriesContext, mod Module, entries *[]AndroidMkEntries) {
+ // If there are no entries, then we can ignore this module, even if it has aconfig files.
+ if len(*entries) == 0 {
+ return
+ }
+ info, ok := SingletonModuleProvider(ctx, mod, aconfigPropagatingProviderKey)
+ if !ok || len(info.AconfigFiles) == 0 {
+ return
+ }
+ // All of the files in the module potentially depend on the aconfig flag values.
+ for idx, _ := range *entries {
+ (*entries)[idx].ExtraEntries = append((*entries)[idx].ExtraEntries,
+ func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries) {
+ setAconfigFileMkEntries(mod.base(), entries, info.AconfigFiles)
+ },
+ )
+
+ }
+}
+
+func mergeAconfigFiles(ctx ModuleContext, container string, inputs Paths, generateRule bool) Paths {
+ inputs = LastUniquePaths(inputs)
+ if len(inputs) == 1 {
+ return Paths{inputs[0]}
+ }
+
+ output := PathForModuleOut(ctx, container, "aconfig_merged.pb")
+
+ if generateRule {
+ ctx.Build(pctx, BuildParams{
+ Rule: mergeAconfigFilesRule,
+ Description: "merge aconfig files",
+ Inputs: inputs,
+ Output: output,
+ Args: map[string]string{
+ "flags": JoinWithPrefix(inputs.Strings(), "--cache "),
+ },
+ })
+ }
+
+ return Paths{output}
+}
+
+func setAconfigFileMkEntries(m *ModuleBase, entries *AndroidMkEntries, aconfigFiles map[string]Paths) {
+ entries.AddPaths("LOCAL_ACONFIG_FILES", getAconfigFilePaths(m, aconfigFiles))
+}
+
+func getAconfigFilePaths(m *ModuleBase, aconfigFiles map[string]Paths) (paths Paths) {
+ // TODO(b/311155208): The default container here should be system.
+ container := "system"
+
+ if m.SocSpecific() {
+ container = "vendor"
+ } else if m.ProductSpecific() {
+ container = "product"
+ } else if m.SystemExtSpecific() {
+ container = "system_ext"
+ }
+
+ paths = append(paths, aconfigFiles[container]...)
+ if container == "system" {
+ // TODO(b/311155208): Once the default container is system, we can drop this.
+ paths = append(paths, aconfigFiles[""]...)
+ }
+ if container != "system" {
+ if len(aconfigFiles[container]) == 0 && len(aconfigFiles[""]) > 0 {
+ // TODO(b/308625757): Either we guessed the container wrong, or the flag is misdeclared.
+ // For now, just include the system (aka "") container if we get here.
+ //fmt.Printf("container_mismatch: module=%v container=%v files=%v\n", m, container, aconfigFiles)
+ }
+ paths = append(paths, aconfigFiles[""]...)
+ }
+ return
+}
diff --git a/android/all_teams.go b/android/all_teams.go
new file mode 100644
index 0000000..6c3a219
--- /dev/null
+++ b/android/all_teams.go
@@ -0,0 +1,158 @@
+package android
+
+import (
+ "android/soong/android/team_proto"
+ "path/filepath"
+
+ "google.golang.org/protobuf/proto"
+)
+
+const ownershipDirectory = "ownership"
+const allTeamsFile = "all_teams.pb"
+
+func AllTeamsFactory() Singleton {
+ return &allTeamsSingleton{}
+}
+
+func init() {
+ registerAllTeamBuildComponents(InitRegistrationContext)
+}
+
+func registerAllTeamBuildComponents(ctx RegistrationContext) {
+ ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory)
+}
+
+// For each module, list the team or the bpFile the module is defined in.
+type moduleTeamInfo struct {
+ teamName string
+ bpFile string
+}
+
+type allTeamsSingleton struct {
+ // Path where the collected metadata is stored after successful validation.
+ outputPath OutputPath
+
+ // Map of all package modules we visit during GenerateBuildActions
+ packages map[string]packageProperties
+ // Map of all team modules we visit during GenerateBuildActions
+ teams map[string]teamProperties
+ // Keeps track of team information or bp file for each module we visit.
+ teams_for_mods map[string]moduleTeamInfo
+}
+
+// See if there is a package module for the given bpFilePath with a team defined, if so return the team.
+// If not ascend up to the parent directory and do the same.
+func (this *allTeamsSingleton) lookupDefaultTeam(bpFilePath string) (teamProperties, bool) {
+ // return the Default_team listed in the package if is there.
+ if p, ok := this.packages[bpFilePath]; ok {
+ if t := p.Default_team; t != nil {
+ return this.teams[*p.Default_team], true
+ }
+ }
+ // Strip a directory and go up.
+ // Does android/paths.go basePath,SourcePath help?
+ current, base := filepath.Split(bpFilePath)
+ current = filepath.Clean(current) // removes trailing slash, convert "" -> "."
+ parent, _ := filepath.Split(current)
+ if current == "." {
+ return teamProperties{}, false
+ }
+ return this.lookupDefaultTeam(filepath.Join(parent, base))
+}
+
+// Create a rule to run a tool to collect all the intermediate files
+// which list the team per module into one proto file.
+func (this *allTeamsSingleton) GenerateBuildActions(ctx SingletonContext) {
+ this.packages = make(map[string]packageProperties)
+ this.teams = make(map[string]teamProperties)
+ this.teams_for_mods = make(map[string]moduleTeamInfo)
+
+ ctx.VisitAllModules(func(module Module) {
+ if !module.Enabled() {
+ return
+ }
+
+ bpFile := ctx.BlueprintFile(module)
+
+ // Package Modules and Team Modules are stored in a map so we can look them up by name for
+ // modules without a team.
+ if pack, ok := module.(*packageModule); ok {
+ // Packages don't have names, use the blueprint file as the key. we can't get qualifiedModuleId in this context.
+ pkgKey := bpFile
+ this.packages[pkgKey] = pack.properties
+ return
+ }
+ if team, ok := module.(*teamModule); ok {
+ this.teams[team.Name()] = team.properties
+ return
+ }
+
+ // If a team name is given for a module, store it.
+ // Otherwise store the bpFile so we can do a package walk later.
+ if module.base().Team() != "" {
+ this.teams_for_mods[module.Name()] = moduleTeamInfo{teamName: module.base().Team(), bpFile: bpFile}
+ } else {
+ this.teams_for_mods[module.Name()] = moduleTeamInfo{bpFile: bpFile}
+ }
+ })
+
+ // Visit all modules again and lookup the team name in the package or parent package if the team
+ // isn't assignged at the module level.
+ allTeams := this.lookupTeamForAllModules()
+
+ this.outputPath = PathForOutput(ctx, ownershipDirectory, allTeamsFile)
+ data, err := proto.Marshal(allTeams)
+ if err != nil {
+ ctx.Errorf("Unable to marshal team data. %s", err)
+ }
+
+ WriteFileRuleVerbatim(ctx, this.outputPath, string(data))
+ ctx.Phony("all_teams", this.outputPath)
+}
+
+func (this *allTeamsSingleton) MakeVars(ctx MakeVarsContext) {
+ ctx.DistForGoal("all_teams", this.outputPath)
+}
+
+// Visit every (non-package, non-team) module and write out a proto containing
+// either the declared team data for that module or the package default team data for that module.
+func (this *allTeamsSingleton) lookupTeamForAllModules() *team_proto.AllTeams {
+ teamsProto := make([]*team_proto.Team, len(this.teams_for_mods))
+ i := 0
+ for moduleName, m := range this.teams_for_mods {
+ teamName := m.teamName
+ var teamProperties teamProperties
+ found := false
+ if teamName != "" {
+ teamProperties, found = this.teams[teamName]
+ } else {
+ teamProperties, found = this.lookupDefaultTeam(m.bpFile)
+ }
+
+ trendy_team_id := ""
+ if found {
+ trendy_team_id = *teamProperties.Trendy_team_id
+ }
+
+ var files []string
+ teamData := new(team_proto.Team)
+ if trendy_team_id != "" {
+ *teamData = team_proto.Team{
+ TrendyTeamId: proto.String(trendy_team_id),
+ TargetName: proto.String(moduleName),
+ Path: proto.String(m.bpFile),
+ File: files,
+ }
+ } else {
+ // Clients rely on the TrendyTeamId optional field not being set.
+ *teamData = team_proto.Team{
+ TargetName: proto.String(moduleName),
+ Path: proto.String(m.bpFile),
+ File: files,
+ }
+ }
+ teamsProto[i] = teamData
+ i++
+ }
+ return &team_proto.AllTeams{Teams: teamsProto}
+}
diff --git a/android/all_teams_test.go b/android/all_teams_test.go
new file mode 100644
index 0000000..a02b86e
--- /dev/null
+++ b/android/all_teams_test.go
@@ -0,0 +1,208 @@
+// Copyright 2024 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 android
+
+import (
+ "android/soong/android/team_proto"
+ "log"
+ "testing"
+
+ "google.golang.org/protobuf/proto"
+)
+
+func TestAllTeams(t *testing.T) {
+ t.Parallel()
+ ctx := GroupFixturePreparers(
+ PrepareForTestWithTeamBuildComponents,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("fake", fakeModuleFactory)
+ ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory)
+ }),
+ ).RunTestWithBp(t, `
+ fake {
+ name: "main_test",
+ team: "someteam",
+ }
+ team {
+ name: "someteam",
+ trendy_team_id: "cool_team",
+ }
+
+ team {
+ name: "team2",
+ trendy_team_id: "22222",
+ }
+
+ fake {
+ name: "tool",
+ team: "team2",
+ }
+
+ fake {
+ name: "noteam",
+ }
+ `)
+
+ var teams *team_proto.AllTeams
+ teams = getTeamProtoOutput(t, ctx)
+
+ // map of module name -> trendy team name.
+ actualTeams := make(map[string]*string)
+ for _, teamProto := range teams.Teams {
+ actualTeams[teamProto.GetTargetName()] = teamProto.TrendyTeamId
+ }
+ expectedTeams := map[string]*string{
+ "main_test": proto.String("cool_team"),
+ "tool": proto.String("22222"),
+ "noteam": nil,
+ }
+
+ AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams)
+}
+
+func getTeamProtoOutput(t *testing.T, ctx *TestResult) *team_proto.AllTeams {
+ teams := new(team_proto.AllTeams)
+ config := ctx.SingletonForTests("all_teams")
+ allOutputs := config.AllOutputs()
+
+ protoPath := allOutputs[0]
+
+ out := config.MaybeOutput(protoPath)
+ outProto := []byte(ContentFromFileRuleForTests(t, ctx.TestContext, out))
+ if err := proto.Unmarshal(outProto, teams); err != nil {
+ log.Fatalln("Failed to parse teams proto:", err)
+ }
+ return teams
+}
+
+// Android.bp
+//
+// team: team_top
+//
+// # dir1 has no modules with teams,
+// # but has a dir with no Android.bp
+// dir1/Android.bp
+//
+// module_dir1
+//
+// # dirs without and Android.bp should be fine.
+// dir1/dir2/dir3/Android.bp
+//
+// package {}
+// module_dir123
+//
+// teams_dir/Android.bp
+//
+// module_with_team1: team1
+// team1: 111
+//
+// # team comes from upper package default
+// teams_dir/deeper/Android.bp
+//
+// module2_with_team1: team1
+//
+// package_defaults/Android.bp
+// package_defaults/pd2/Android.bp
+//
+// package{ default_team: team_top}
+// module_pd2 ## should get team_top
+//
+// package_defaults/pd2/pd3/Android.bp
+//
+// module_pd3 ## should get team_top
+func TestPackageLookup(t *testing.T) {
+ t.Parallel()
+ rootBp := `
+ team {
+ name: "team_top",
+ trendy_team_id: "trendy://team_top",
+ } `
+
+ dir1Bp := `
+ fake {
+ name: "module_dir1",
+ } `
+ dir3Bp := `
+ package {}
+ fake {
+ name: "module_dir123",
+ } `
+ teamsDirBp := `
+ fake {
+ name: "module_with_team1",
+ team: "team1"
+
+ }
+ team {
+ name: "team1",
+ trendy_team_id: "111",
+ } `
+ teamsDirDeeper := `
+ fake {
+ name: "module2_with_team1",
+ team: "team1"
+ } `
+ // create an empty one.
+ packageDefaultsBp := ""
+ packageDefaultspd2 := `
+ package { default_team: "team_top"}
+ fake {
+ name: "modulepd2",
+ } `
+
+ packageDefaultspd3 := `
+ fake {
+ name: "modulepd3",
+ }
+ fake {
+ name: "modulepd3b",
+ team: "team1"
+ } `
+
+ ctx := GroupFixturePreparers(
+ PrepareForTestWithTeamBuildComponents,
+ PrepareForTestWithPackageModule,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("fake", fakeModuleFactory)
+ ctx.RegisterParallelSingletonType("all_teams", AllTeamsFactory)
+ }),
+ FixtureAddTextFile("Android.bp", rootBp),
+ FixtureAddTextFile("dir1/Android.bp", dir1Bp),
+ FixtureAddTextFile("dir1/dir2/dir3/Android.bp", dir3Bp),
+ FixtureAddTextFile("teams_dir/Android.bp", teamsDirBp),
+ FixtureAddTextFile("teams_dir/deeper/Android.bp", teamsDirDeeper),
+ FixtureAddTextFile("package_defaults/Android.bp", packageDefaultsBp),
+ FixtureAddTextFile("package_defaults/pd2/Android.bp", packageDefaultspd2),
+ FixtureAddTextFile("package_defaults/pd2/pd3/Android.bp", packageDefaultspd3),
+ ).RunTest(t)
+
+ var teams *team_proto.AllTeams
+ teams = getTeamProtoOutput(t, ctx)
+
+ // map of module name -> trendy team name.
+ actualTeams := make(map[string]*string)
+ for _, teamProto := range teams.Teams {
+ actualTeams[teamProto.GetTargetName()] = teamProto.TrendyTeamId
+ }
+ expectedTeams := map[string]*string{
+ "module_with_team1": proto.String("111"),
+ "module2_with_team1": proto.String("111"),
+ "modulepd2": proto.String("trendy://team_top"),
+ "modulepd3": proto.String("trendy://team_top"),
+ "modulepd3b": proto.String("111"),
+ "module_dir1": nil,
+ "module_dir123": nil,
+ }
+ AssertDeepEquals(t, "compare maps", expectedTeams, actualTeams)
+}
diff --git a/android/allowlists/allowlists.go b/android/allowlists/allowlists.go
index e82e754..a52bff3 100644
--- a/android/allowlists/allowlists.go
+++ b/android/allowlists/allowlists.go
@@ -14,30 +14,7 @@
package allowlists
-// Configuration to decide if modules in a directory should default to true/false for bp2build_available
-type Bp2BuildConfig map[string]BazelConversionConfigEntry
-type BazelConversionConfigEntry int
-
const (
- // iota + 1 ensures that the int value is not 0 when used in the Bp2buildAllowlist map,
- // which can also mean that the key doesn't exist in a lookup.
-
- // all modules in this package and subpackages default to bp2build_available: true.
- // allows modules to opt-out.
- Bp2BuildDefaultTrueRecursively BazelConversionConfigEntry = iota + 1
-
- // all modules in this package (not recursively) default to bp2build_available: true.
- // allows modules to opt-out.
- Bp2BuildDefaultTrue
-
- // all modules in this package (not recursively) default to bp2build_available: false.
- // allows modules to opt-in.
- Bp2BuildDefaultFalse
-
- // all modules in this package and subpackages default to bp2build_available: false.
- // allows modules to opt-in.
- Bp2BuildDefaultFalseRecursively
-
// Modules with build time of more than half a minute should have high priority.
DEFAULT_PRIORITIZED_WEIGHT = 1000
// Modules with build time of more than a few minute should have higher priority.
@@ -48,1657 +25,6 @@
)
var (
- Bp2buildDefaultConfig = Bp2BuildConfig{
- "art": Bp2BuildDefaultTrue,
- "art/libartbase": Bp2BuildDefaultTrueRecursively,
- "art/libartpalette": Bp2BuildDefaultTrueRecursively,
- "art/libdexfile": Bp2BuildDefaultTrueRecursively,
- "art/libnativebridge": Bp2BuildDefaultTrueRecursively,
- "art/runtime": Bp2BuildDefaultTrueRecursively,
- "art/tools": Bp2BuildDefaultTrue,
- "bionic": Bp2BuildDefaultTrueRecursively,
- "bootable/recovery/applypatch": Bp2BuildDefaultTrue,
- "bootable/recovery/minadbd": Bp2BuildDefaultTrue,
- "bootable/recovery/minui": Bp2BuildDefaultTrue,
- "bootable/recovery/recovery_utils": Bp2BuildDefaultTrue,
- "bootable/recovery/tools/recovery_l10n": Bp2BuildDefaultTrue,
-
- "build/bazel": Bp2BuildDefaultTrueRecursively,
- "build/make/target/product/security": Bp2BuildDefaultTrue,
- "build/make/tools/protos": Bp2BuildDefaultTrue,
- "build/make/tools/releasetools": Bp2BuildDefaultTrue,
- "build/make/tools/sbom": Bp2BuildDefaultTrue,
- "build/make/tools/signapk": Bp2BuildDefaultTrue,
- "build/make/tools/zipalign": Bp2BuildDefaultTrueRecursively,
- "build/soong": Bp2BuildDefaultTrue,
- "build/soong/cc/libbuildversion": Bp2BuildDefaultTrue, // Skip tests subdir
- "build/soong/cc/ndkstubgen": Bp2BuildDefaultTrue,
- "build/soong/cc/symbolfile": Bp2BuildDefaultTrue,
- "build/soong/licenses": Bp2BuildDefaultTrue,
- "build/soong/linkerconfig": Bp2BuildDefaultTrueRecursively,
- "build/soong/scripts": Bp2BuildDefaultTrueRecursively,
-
- "cts/common/device-side/nativetesthelper/jni": Bp2BuildDefaultTrueRecursively,
-
- "dalvik/tools/dexdeps": Bp2BuildDefaultTrueRecursively,
-
- "development/apps/DevelopmentSettings": Bp2BuildDefaultTrue,
- "development/apps/Fallback": Bp2BuildDefaultTrue,
- "development/apps/WidgetPreview": Bp2BuildDefaultTrue,
- "development/python-packages/adb": Bp2BuildDefaultTrueRecursively,
- "development/samples/BasicGLSurfaceView": Bp2BuildDefaultTrue,
- "development/samples/BluetoothChat": Bp2BuildDefaultTrue,
- "development/samples/BrokenKeyDerivation": Bp2BuildDefaultTrue,
- "development/samples/Compass": Bp2BuildDefaultTrue,
- "development/samples/ContactManager": Bp2BuildDefaultTrue,
- "development/samples/FixedGridLayout": Bp2BuildDefaultTrue,
- "development/samples/HelloEffects": Bp2BuildDefaultTrue,
- "development/samples/Home": Bp2BuildDefaultTrue,
- "development/samples/HoneycombGallery": Bp2BuildDefaultTrue,
- "development/samples/JetBoy": Bp2BuildDefaultTrue,
- "development/samples/KeyChainDemo": Bp2BuildDefaultTrue,
- "development/samples/LceDemo": Bp2BuildDefaultTrue,
- "development/samples/LunarLander": Bp2BuildDefaultTrue,
- "development/samples/MultiResolution": Bp2BuildDefaultTrue,
- "development/samples/MultiWindow": Bp2BuildDefaultTrue,
- "development/samples/NotePad": Bp2BuildDefaultTrue,
- "development/samples/Obb": Bp2BuildDefaultTrue,
- "development/samples/RSSReader": Bp2BuildDefaultTrue,
- "development/samples/ReceiveShareDemo": Bp2BuildDefaultTrue,
- "development/samples/SearchableDictionary": Bp2BuildDefaultTrue,
- "development/samples/SipDemo": Bp2BuildDefaultTrue,
- "development/samples/SkeletonApp": Bp2BuildDefaultTrue,
- "development/samples/Snake": Bp2BuildDefaultTrue,
- "development/samples/SpellChecker/": Bp2BuildDefaultTrueRecursively,
- "development/samples/ThemedNavBarKeyboard": Bp2BuildDefaultTrue,
- "development/samples/ToyVpn": Bp2BuildDefaultTrue,
- "development/samples/TtsEngine": Bp2BuildDefaultTrue,
- "development/samples/USB/AdbTest": Bp2BuildDefaultTrue,
- "development/samples/USB/MissileLauncher": Bp2BuildDefaultTrue,
- "development/samples/VoiceRecognitionService": Bp2BuildDefaultTrue,
- "development/samples/VoicemailProviderDemo": Bp2BuildDefaultTrue,
- "development/samples/WiFiDirectDemo": Bp2BuildDefaultTrue,
- "development/sdk": Bp2BuildDefaultTrueRecursively,
-
- "external/aac": Bp2BuildDefaultTrueRecursively,
- "external/abseil-cpp": Bp2BuildDefaultTrueRecursively,
- "external/arm-optimized-routines": Bp2BuildDefaultTrueRecursively,
- "external/auto": Bp2BuildDefaultTrue,
- "external/auto/android-annotation-stubs": Bp2BuildDefaultTrueRecursively,
- "external/auto/common": Bp2BuildDefaultTrueRecursively,
- "external/auto/service": Bp2BuildDefaultTrueRecursively,
- "external/boringssl": Bp2BuildDefaultTrueRecursively,
- "external/bouncycastle": Bp2BuildDefaultTrue,
- "external/brotli": Bp2BuildDefaultTrue,
- "external/bsdiff": Bp2BuildDefaultTrueRecursively,
- "external/bzip2": Bp2BuildDefaultTrueRecursively,
- "external/clang/lib": Bp2BuildDefaultTrue,
- "external/conscrypt": Bp2BuildDefaultTrue,
- "external/e2fsprogs": Bp2BuildDefaultTrueRecursively,
- "external/eigen": Bp2BuildDefaultTrueRecursively,
- "external/erofs-utils": Bp2BuildDefaultTrueRecursively,
- "external/error_prone": Bp2BuildDefaultTrueRecursively,
- "external/escapevelocity": Bp2BuildDefaultTrueRecursively,
- "external/expat": Bp2BuildDefaultTrueRecursively,
- "external/f2fs-tools": Bp2BuildDefaultTrue,
- "external/flac": Bp2BuildDefaultTrueRecursively,
- "external/flatbuffers": Bp2BuildDefaultTrueRecursively,
- "external/fmtlib": Bp2BuildDefaultTrueRecursively,
- "external/fsverity-utils": Bp2BuildDefaultTrueRecursively,
- "external/gflags": Bp2BuildDefaultTrueRecursively,
- "external/google-benchmark": Bp2BuildDefaultTrueRecursively,
- "external/googletest": Bp2BuildDefaultTrueRecursively,
- "external/guava": Bp2BuildDefaultTrueRecursively,
- "external/gwp_asan": Bp2BuildDefaultTrueRecursively,
- "external/hamcrest": Bp2BuildDefaultTrueRecursively,
- "external/icu": Bp2BuildDefaultTrueRecursively,
- "external/icu/android_icu4j": Bp2BuildDefaultFalse, // java rules incomplete
- "external/icu/icu4j": Bp2BuildDefaultFalse, // java rules incomplete
- "external/jacoco": Bp2BuildDefaultTrueRecursively,
- "external/jarjar": Bp2BuildDefaultTrueRecursively,
- "external/javaparser": Bp2BuildDefaultTrueRecursively,
- "external/javapoet": Bp2BuildDefaultTrueRecursively,
- "external/javassist": Bp2BuildDefaultTrueRecursively,
- "external/jemalloc_new": Bp2BuildDefaultTrueRecursively,
- "external/jsoncpp": Bp2BuildDefaultTrueRecursively,
- "external/jsr305": Bp2BuildDefaultTrueRecursively,
- "external/jsr330": Bp2BuildDefaultTrueRecursively,
- "external/junit": Bp2BuildDefaultTrueRecursively,
- "external/kotlinc": Bp2BuildDefaultTrueRecursively,
- "external/libaom": Bp2BuildDefaultTrueRecursively,
- "external/libavc": Bp2BuildDefaultTrueRecursively,
- "external/libcap": Bp2BuildDefaultTrueRecursively,
- "external/libcxx": Bp2BuildDefaultTrueRecursively,
- "external/libcxxabi": Bp2BuildDefaultTrueRecursively,
- "external/libdivsufsort": Bp2BuildDefaultTrueRecursively,
- "external/libdrm": Bp2BuildDefaultTrue,
- "external/libevent": Bp2BuildDefaultTrueRecursively,
- "external/libgav1": Bp2BuildDefaultTrueRecursively,
- "external/libhevc": Bp2BuildDefaultTrueRecursively,
- "external/libjpeg-turbo": Bp2BuildDefaultTrueRecursively,
- "external/libmpeg2": Bp2BuildDefaultTrueRecursively,
- "external/libpng": Bp2BuildDefaultTrueRecursively,
- "external/libphonenumber": Bp2BuildDefaultTrueRecursively,
- "external/libvpx": Bp2BuildDefaultTrueRecursively,
- "external/libyuv": Bp2BuildDefaultTrueRecursively,
- "external/lz4/lib": Bp2BuildDefaultTrue,
- "external/lz4/programs": Bp2BuildDefaultTrue,
- "external/lzma/C": Bp2BuildDefaultTrueRecursively,
- "external/mdnsresponder": Bp2BuildDefaultTrueRecursively,
- "external/minijail": Bp2BuildDefaultTrueRecursively,
- "external/musl": Bp2BuildDefaultTrueRecursively,
- "external/objenesis": Bp2BuildDefaultTrueRecursively,
- "external/openscreen": Bp2BuildDefaultTrueRecursively,
- "external/ow2-asm": Bp2BuildDefaultTrueRecursively,
- "external/pcre": Bp2BuildDefaultTrueRecursively,
- "external/protobuf": Bp2BuildDefaultTrueRecursively,
- "external/python/pyyaml/lib/yaml": Bp2BuildDefaultTrueRecursively,
- "external/python/six": Bp2BuildDefaultTrueRecursively,
- "external/python/jinja/src": Bp2BuildDefaultTrueRecursively,
- "external/python/markupsafe/src": Bp2BuildDefaultTrueRecursively,
- "external/python/setuptools": Bp2BuildDefaultTrueRecursively,
- "external/rappor": Bp2BuildDefaultTrueRecursively,
- "external/scudo": Bp2BuildDefaultTrueRecursively,
- "external/selinux/checkpolicy": Bp2BuildDefaultTrueRecursively,
- "external/selinux/libselinux": Bp2BuildDefaultTrueRecursively,
- "external/selinux/libsepol": Bp2BuildDefaultTrueRecursively,
- "external/speex": Bp2BuildDefaultTrueRecursively,
- "external/sqlite": Bp2BuildDefaultTrueRecursively,
- "external/tinyalsa": Bp2BuildDefaultTrueRecursively,
- "external/tinyalsa_new": Bp2BuildDefaultTrueRecursively,
- "external/toybox": Bp2BuildDefaultTrueRecursively,
- "external/zlib": Bp2BuildDefaultTrueRecursively,
- "external/zopfli": Bp2BuildDefaultTrueRecursively,
- "external/zstd": Bp2BuildDefaultTrueRecursively,
-
- "frameworks/av": Bp2BuildDefaultTrue,
- "frameworks/av/media/audioaidlconversion": Bp2BuildDefaultTrueRecursively,
- "frameworks/av/media/codec2/components/aom": Bp2BuildDefaultTrueRecursively,
- "frameworks/av/media/codecs": Bp2BuildDefaultTrueRecursively,
- "frameworks/av/media/liberror": Bp2BuildDefaultTrueRecursively,
- "frameworks/av/media/libmediahelper": Bp2BuildDefaultTrue,
- "frameworks/av/media/libshmem": Bp2BuildDefaultTrueRecursively,
- "frameworks/av/media/module/codecs": Bp2BuildDefaultTrueRecursively,
- "frameworks/av/media/module/foundation": Bp2BuildDefaultTrueRecursively,
- "frameworks/av/media/module/minijail": Bp2BuildDefaultTrueRecursively,
- "frameworks/av/services/minijail": Bp2BuildDefaultTrueRecursively,
- "frameworks/base/libs/androidfw": Bp2BuildDefaultTrue,
- "frameworks/base/libs/services": Bp2BuildDefaultTrue,
- "frameworks/base/media/tests/MediaDump": Bp2BuildDefaultTrue,
- "frameworks/base/proto": Bp2BuildDefaultTrue,
- "frameworks/base/services/tests/servicestests/aidl": Bp2BuildDefaultTrue,
- "frameworks/base/startop/apps/test": Bp2BuildDefaultTrue,
- "frameworks/base/tests/appwidgets/AppWidgetHostTest": Bp2BuildDefaultTrueRecursively,
- "frameworks/base/tools/aapt": Bp2BuildDefaultTrue,
- "frameworks/base/tools/aapt2": Bp2BuildDefaultTrue,
- "frameworks/base/tools/codegen": Bp2BuildDefaultTrueRecursively,
- "frameworks/base/tools/streaming_proto": Bp2BuildDefaultTrueRecursively,
- "frameworks/hardware/interfaces/stats/aidl": Bp2BuildDefaultTrue,
- "frameworks/libs/modules-utils/build": Bp2BuildDefaultTrueRecursively,
- "frameworks/libs/net/common/native": Bp2BuildDefaultTrueRecursively, // TODO(b/296014682): Remove this path
- "frameworks/native": Bp2BuildDefaultTrue,
- "frameworks/native/libs/adbd_auth": Bp2BuildDefaultTrueRecursively,
- "frameworks/native/libs/arect": Bp2BuildDefaultTrueRecursively,
- "frameworks/native/libs/gui": Bp2BuildDefaultTrue,
- "frameworks/native/libs/math": Bp2BuildDefaultTrueRecursively,
- "frameworks/native/libs/nativebase": Bp2BuildDefaultTrueRecursively,
- "frameworks/native/libs/permission": Bp2BuildDefaultTrueRecursively,
- "frameworks/native/libs/vr": Bp2BuildDefaultTrueRecursively,
- "frameworks/native/opengl/tests/gl2_cameraeye": Bp2BuildDefaultTrue,
- "frameworks/native/opengl/tests/gl2_java": Bp2BuildDefaultTrue,
- "frameworks/native/opengl/tests/testLatency": Bp2BuildDefaultTrue,
- "frameworks/native/opengl/tests/testPauseResume": Bp2BuildDefaultTrue,
- "frameworks/native/opengl/tests/testViewport": Bp2BuildDefaultTrue,
- "frameworks/native/services/batteryservice": Bp2BuildDefaultTrue,
- "frameworks/proto_logging/stats": Bp2BuildDefaultTrueRecursively,
-
- "hardware/interfaces": Bp2BuildDefaultTrue,
- "hardware/interfaces/audio/aidl": Bp2BuildDefaultTrue,
- "hardware/interfaces/audio/aidl/common": Bp2BuildDefaultTrue,
- "hardware/interfaces/audio/aidl/default": Bp2BuildDefaultTrue,
- "hardware/interfaces/audio/aidl/sounddose": Bp2BuildDefaultTrue,
- "hardware/interfaces/camera/metadata/aidl": Bp2BuildDefaultTrueRecursively,
- "hardware/interfaces/common/aidl": Bp2BuildDefaultTrue,
- "hardware/interfaces/common/fmq/aidl": Bp2BuildDefaultTrue,
- "hardware/interfaces/common/support": Bp2BuildDefaultTrue,
- "hardware/interfaces/configstore/1.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/configstore/1.1": Bp2BuildDefaultTrue,
- "hardware/interfaces/configstore/utils": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/allocator/2.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/allocator/3.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/allocator/4.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/allocator/aidl": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/bufferqueue/1.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/bufferqueue/2.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/common/1.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/common/1.1": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/common/1.2": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/common/aidl": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/mapper/2.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/mapper/2.1": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/mapper/3.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/graphics/mapper/4.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/health/1.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/health/1.0/default": Bp2BuildDefaultTrue,
- "hardware/interfaces/health/2.0": Bp2BuildDefaultTrue,
- "hardware/interfaces/health/2.0/default": Bp2BuildDefaultTrue,
- "hardware/interfaces/health/2.0/utils": Bp2BuildDefaultTrueRecursively,
- "hardware/interfaces/health/2.1": Bp2BuildDefaultTrue,
- "hardware/interfaces/health/aidl": Bp2BuildDefaultTrue,
- "hardware/interfaces/health/utils": Bp2BuildDefaultTrueRecursively,
- "hardware/interfaces/media": Bp2BuildDefaultTrueRecursively,
- "hardware/interfaces/media/bufferpool/aidl/default/tests": Bp2BuildDefaultFalseRecursively,
- "hardware/interfaces/media/omx/1.0/vts": Bp2BuildDefaultFalseRecursively,
- "hardware/interfaces/neuralnetworks": Bp2BuildDefaultTrueRecursively,
- "hardware/interfaces/neuralnetworks/aidl/vts": Bp2BuildDefaultFalseRecursively,
- "hardware/interfaces/neuralnetworks/1.0/vts": Bp2BuildDefaultFalseRecursively,
- "hardware/interfaces/neuralnetworks/1.1/vts": Bp2BuildDefaultFalseRecursively,
- "hardware/interfaces/neuralnetworks/1.2/vts": Bp2BuildDefaultFalseRecursively,
- "hardware/interfaces/neuralnetworks/1.3/vts": Bp2BuildDefaultFalseRecursively,
- "hardware/interfaces/neuralnetworks/1.4/vts": Bp2BuildDefaultFalseRecursively,
-
- "libnativehelper": Bp2BuildDefaultTrueRecursively,
-
- "packages/apps/DevCamera": Bp2BuildDefaultTrue,
- "packages/apps/HTMLViewer": Bp2BuildDefaultTrue,
- "packages/apps/Protips": Bp2BuildDefaultTrue,
- "packages/apps/SafetyRegulatoryInfo": Bp2BuildDefaultTrue,
- "packages/apps/WallpaperPicker": Bp2BuildDefaultTrue,
- "packages/modules/NeuralNetworks/driver/cache": Bp2BuildDefaultTrueRecursively,
- "packages/modules/StatsD/lib/libstatssocket": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb": Bp2BuildDefaultTrue,
- "packages/modules/adb/apex": Bp2BuildDefaultTrue,
- "packages/modules/adb/fastdeploy": Bp2BuildDefaultTrue,
- "packages/modules/adb/crypto": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb/libs": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb/pairing_auth": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb/pairing_connection": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb/proto": Bp2BuildDefaultTrueRecursively,
- "packages/modules/adb/tls": Bp2BuildDefaultTrueRecursively,
- "packages/modules/Connectivity/staticlibs/native": Bp2BuildDefaultTrueRecursively,
- "packages/modules/Gki/libkver": Bp2BuildDefaultTrue,
- "packages/modules/NetworkStack/common/captiveportal": Bp2BuildDefaultTrue,
- "packages/modules/NeuralNetworks/apex": Bp2BuildDefaultTrue,
- "packages/modules/NeuralNetworks/apex/testing": Bp2BuildDefaultTrue,
- "packages/providers/MediaProvider/tools/dialogs": Bp2BuildDefaultFalse, // TODO(b/242834374)
- "packages/screensavers/Basic": Bp2BuildDefaultTrue,
- "packages/services/Car/tests/SampleRearViewCamera": Bp2BuildDefaultFalse, // TODO(b/242834321)
-
- "platform_testing/tests/example": Bp2BuildDefaultTrueRecursively,
-
- "prebuilts/clang/host/linux-x86": Bp2BuildDefaultTrueRecursively,
- "prebuilts/gradle-plugin": Bp2BuildDefaultTrueRecursively,
- "prebuilts/runtime/mainline/platform/sdk": Bp2BuildDefaultTrueRecursively,
- "prebuilts/sdk": Bp2BuildDefaultTrue,
- "prebuilts/sdk/current/androidx": Bp2BuildDefaultTrue,
- "prebuilts/sdk/current/androidx-legacy": Bp2BuildDefaultTrue,
- "prebuilts/sdk/current/extras/constraint-layout-x": Bp2BuildDefaultTrue,
- "prebuilts/sdk/current/extras/material-design-x": Bp2BuildDefaultTrue,
- "prebuilts/sdk/current/extras/app-toolkit": Bp2BuildDefaultTrue,
- "prebuilts/sdk/current/support": Bp2BuildDefaultTrue,
- "prebuilts/tools": Bp2BuildDefaultTrue,
- "prebuilts/tools/common/m2": Bp2BuildDefaultTrue,
- "prebuilts/r8": Bp2BuildDefaultTrueRecursively,
-
- "sdk/dumpeventlog": Bp2BuildDefaultTrue,
- "sdk/eventanalyzer": Bp2BuildDefaultTrue,
-
- "system/apex": Bp2BuildDefaultFalse, // TODO(b/207466993): flaky failures
- "system/apex/apexer": Bp2BuildDefaultTrue,
- "system/apex/libs": Bp2BuildDefaultTrueRecursively,
- "system/apex/libs/libapexsupport": Bp2BuildDefaultFalseRecursively, // TODO(b/267572288): depends on rust
- "system/apex/proto": Bp2BuildDefaultTrueRecursively,
- "system/apex/tools": Bp2BuildDefaultTrueRecursively,
- "system/core/debuggerd": Bp2BuildDefaultTrueRecursively,
- "system/core/diagnose_usb": Bp2BuildDefaultTrueRecursively,
- "system/core/healthd": Bp2BuildDefaultTrue,
- "system/core/healthd/testdata": Bp2BuildDefaultTrue,
- "system/core/libasyncio": Bp2BuildDefaultTrue,
- "system/core/libcrypto_utils": Bp2BuildDefaultTrueRecursively,
- "system/core/libcutils": Bp2BuildDefaultTrueRecursively,
- "system/core/libpackagelistparser": Bp2BuildDefaultTrueRecursively,
- "system/core/libprocessgroup": Bp2BuildDefaultTrue,
- "system/core/libprocessgroup/cgrouprc": Bp2BuildDefaultTrue,
- "system/core/libprocessgroup/cgrouprc_format": Bp2BuildDefaultTrue,
- "system/core/libsparse": Bp2BuildDefaultTrueRecursively,
- "system/core/libsuspend": Bp2BuildDefaultTrue,
- "system/core/libsystem": Bp2BuildDefaultTrueRecursively,
- "system/core/libsysutils": Bp2BuildDefaultTrueRecursively,
- "system/core/libutils": Bp2BuildDefaultTrueRecursively,
- "system/core/libvndksupport": Bp2BuildDefaultTrueRecursively,
- "system/core/mkbootfs": Bp2BuildDefaultTrueRecursively,
- "system/core/property_service/libpropertyinfoparser": Bp2BuildDefaultTrueRecursively,
- "system/core/property_service/libpropertyinfoserializer": Bp2BuildDefaultTrueRecursively,
- "system/extras/f2fs_utils": Bp2BuildDefaultTrueRecursively,
- "system/extras/toolchain-extras": Bp2BuildDefaultTrue,
- "system/extras/verity": Bp2BuildDefaultTrueRecursively,
- "system/hardware/interfaces/media": Bp2BuildDefaultTrueRecursively,
- "system/incremental_delivery/incfs": Bp2BuildDefaultTrue,
- "system/libartpalette": Bp2BuildDefaultTrueRecursively,
- "system/libbase": Bp2BuildDefaultTrueRecursively,
- "system/libfmq": Bp2BuildDefaultTrue,
- "system/libhidl/libhidlmemory": Bp2BuildDefaultTrue,
- "system/libhidl/transport": Bp2BuildDefaultTrue,
- "system/libhidl/transport/allocator/1.0": Bp2BuildDefaultTrue,
- "system/libhidl/transport/base/1.0": Bp2BuildDefaultTrue,
- "system/libhidl/transport/manager/1.0": Bp2BuildDefaultTrue,
- "system/libhidl/transport/manager/1.1": Bp2BuildDefaultTrue,
- "system/libhidl/transport/manager/1.2": Bp2BuildDefaultTrue,
- "system/libhidl/transport/memory/1.0": Bp2BuildDefaultTrue,
- "system/libhidl/transport/memory/token/1.0": Bp2BuildDefaultTrue,
- "system/libhidl/transport/safe_union/1.0": Bp2BuildDefaultTrue,
- "system/libhidl/transport/token/1.0": Bp2BuildDefaultTrue,
- "system/libhidl/transport/token/1.0/utils": Bp2BuildDefaultTrue,
- "system/libhwbinder": Bp2BuildDefaultTrueRecursively,
- "system/libprocinfo": Bp2BuildDefaultTrue,
- "system/libvintf": Bp2BuildDefaultTrue,
- "system/libziparchive": Bp2BuildDefaultTrueRecursively,
- "system/logging": Bp2BuildDefaultTrueRecursively,
- "system/media": Bp2BuildDefaultTrue,
- "system/media/audio": Bp2BuildDefaultTrueRecursively,
- "system/media/alsa_utils": Bp2BuildDefaultTrueRecursively,
- "system/media/audio_utils": Bp2BuildDefaultTrueRecursively,
- "system/media/camera": Bp2BuildDefaultTrueRecursively,
- "system/memory/libion": Bp2BuildDefaultTrueRecursively,
- "system/memory/libmemunreachable": Bp2BuildDefaultTrueRecursively,
- "system/sepolicy/apex": Bp2BuildDefaultTrueRecursively,
- "system/security/fsverity": Bp2BuildDefaultTrueRecursively,
- "system/testing/gtest_extras": Bp2BuildDefaultTrueRecursively,
- "system/timezone/apex": Bp2BuildDefaultTrueRecursively,
- "system/timezone/output_data": Bp2BuildDefaultTrueRecursively,
- "system/timezone/testdata": Bp2BuildDefaultTrueRecursively,
- "system/timezone/testing": Bp2BuildDefaultTrueRecursively,
- "system/tools/aidl/build/tests_bp2build": Bp2BuildDefaultTrue,
- "system/tools/aidl/metadata": Bp2BuildDefaultTrue,
- "system/tools/hidl/metadata": Bp2BuildDefaultTrue,
- "system/tools/hidl/utils": Bp2BuildDefaultTrue,
- "system/tools/mkbootimg": Bp2BuildDefaultTrueRecursively,
- "system/tools/sysprop": Bp2BuildDefaultTrue,
- "system/tools/xsdc/utils": Bp2BuildDefaultTrueRecursively,
- "system/unwinding/libunwindstack": Bp2BuildDefaultTrueRecursively,
-
- "tools/apifinder": Bp2BuildDefaultTrue,
- "tools/apksig": Bp2BuildDefaultTrue,
- "tools/external_updater": Bp2BuildDefaultTrueRecursively,
- "tools/metalava": Bp2BuildDefaultTrueRecursively,
- "tools/platform-compat/java/android/compat": Bp2BuildDefaultTrueRecursively,
- "tools/tradefederation/prebuilts/filegroups": Bp2BuildDefaultTrueRecursively,
- }
-
- Bp2buildKeepExistingBuildFile = map[string]bool{
- // This is actually build/bazel/build.BAZEL symlinked to ./BUILD
- ".":/*recursive = */ false,
-
- "build/bazel":/* recursive = */ true,
- "build/make/core":/* recursive = */ false,
- "build/bazel_common_rules":/* recursive = */ true,
- "build/make/target/product/security":/* recursive = */ false,
- // build/make/tools/signapk BUILD file is generated, so build/make/tools is not recursive.
- "build/make/tools":/* recursive = */ false,
- "build/pesto":/* recursive = */ true,
- "build/soong":/* recursive = */ true,
-
- // external/bazelbuild-rules_android/... is needed by mixed builds, otherwise mixed builds analysis fails
- // e.g. ERROR: Analysis of target '@soong_injection//mixed_builds:buildroot' failed
- "external/bazelbuild-rules_android":/* recursive = */ true,
- "external/bazelbuild-rules_cc":/* recursive = */ true,
- "external/bazelbuild-rules_java":/* recursive = */ true,
- "external/bazelbuild-rules_license":/* recursive = */ true,
- "external/bazelbuild-rules_go":/* recursive = */ true,
- "external/bazelbuild-rules_python":/* recursive = */ true,
- "external/bazelbuild-rules_rust":/* recursive = */ true,
- "external/bazelbuild-kotlin-rules":/* recursive = */ true,
- "external/bazel-skylib":/* recursive = */ true,
- "external/protobuf":/* recursive = */ false,
- "external/python/absl-py":/* recursive = */ true,
-
- "external/compiler-rt/lib/cfi":/* recursive = */ false,
-
- // this BUILD file is globbed by //external/icu/icu4c/source:icu4c_test_data's "data/**/*".
- "external/icu/icu4c/source/data/unidata/norm2":/* recursive = */ false,
-
- // Building manually due to b/179889880: resource files cross package boundary
- "packages/apps/Music":/* recursive = */ true,
-
- "prebuilts/abi-dumps/platform":/* recursive = */ true,
- "prebuilts/abi-dumps/ndk":/* recursive = */ true,
- "prebuilts/bazel":/* recursive = */ true,
- "prebuilts/bundletool":/* recursive = */ true,
- "prebuilts/clang/host/linux-x86":/* recursive = */ false,
- "prebuilts/clang-tools":/* recursive = */ true,
- "prebuilts/gcc":/* recursive = */ true,
- "prebuilts/build-tools":/* recursive = */ true,
- "prebuilts/jdk/jdk17":/* recursive = */ true,
- "prebuilts/misc":/* recursive = */ false, // not recursive because we need bp2build converted build files in prebuilts/misc/common/asm
- "prebuilts/sdk":/* recursive = */ false,
- "prebuilts/sdk/tools":/* recursive = */ false,
- "prebuilts/r8":/* recursive = */ false,
- "prebuilts/runtime":/* recursive = */ false,
- "prebuilts/rust":/* recursive = */ true,
-
- // not recursive due to conflicting workspace paths in tools/atest/bazel/rules
- "tools/asuite/atest":/* recursive = */ false,
- "tools/asuite/atest/bazel/reporter":/* recursive = */ true,
-
- // TODO(b/266459895): remove this and the placeholder BUILD file after re-enabling libunwindstack
- "external/rust/crates/rustc-demangle-capi":/* recursive = */ false,
-
- // Used for testing purposes only. Should not actually exist in the real source tree.
- "testpkg/keep_build_file":/* recursive = */ false,
- }
-
- Bp2buildModuleAlwaysConvertList = []string{
- // aconfig
- "libonce_cell",
- "libanyhow",
- "libunicode_segmentation",
- "libmemchr",
- "libbitflags-1.3.2",
- "libryu",
- "libitoa",
- "libos_str_bytes",
- "libheck",
- "libclap_lex",
- "libsyn",
- "libquote",
- "libunicode_ident",
- "libproc_macro2",
- "libthiserror_impl",
- "libserde_derive",
- "libclap_derive",
- "libthiserror",
- "libserde",
- "libclap",
- "libbytes",
- "libprotobuf_support",
- "libtinytemplate",
- "libserde_json",
- "libprotobuf",
-
- "protoc-gen-rust",
- "libprotobuf_codegen",
- "libprotobuf_parse",
- "libregex",
- "libtempfile",
- "libwhich",
- "libregex_syntax",
- "libfastrand",
- "libeither",
- "libaho_corasick",
- "liblibc",
- "libcfg_if",
- "liblog_rust",
- "libgetrandom",
- "libremove_dir_all",
- "libahash",
- "libhashbrown",
- "libindexmap",
- "libaconfig_protos",
- "libpaste",
- "aconfig",
-
- // ext
- "tagsoup",
-
- // framework-res
- "remote-color-resources-compile-public",
- "remote-color-resources-compile-colors",
-
- // framework-minus-apex
- "android.mime.types.minimized",
- "debian.mime.types.minimized",
- "framework-javastream-protos",
- "libview-inspector-annotation-processor",
-
- // services
- "apache-commons-math",
- "cbor-java",
- "icu4j_calendar_astronomer",
- "json",
- "remote-color-resources-compile-public",
- "statslog-art-java-gen",
- "statslog-framework-java-gen",
-
- "AndroidCommonLint",
- "ImmutabilityAnnotation",
- "ImmutabilityAnnotationProcessorHostLibrary",
-
- "libidmap2_policies",
- "libSurfaceFlingerProp",
- "toolbox_input_labels",
-
- // cc mainline modules
-
- // com.android.media.swcodec
- "com.android.media.swcodec",
- "com.android.media.swcodec-androidManifest",
- "com.android.media.swcodec-ld.config.txt",
- "com.android.media.swcodec-mediaswcodec.32rc",
- "com.android.media.swcodec-mediaswcodec.rc",
- "com.android.media.swcodec.certificate",
- "com.android.media.swcodec.key",
- "test_com.android.media.swcodec",
-
- // deps
- "code_coverage.policy",
- "code_coverage.policy.other",
- "codec2_soft_exports",
- "compatibility_matrix_schema",
- "framework-connectivity-protos",
- "gemmlowp_headers",
- "gl_headers",
- "libandroid_runtime_lazy",
- "libandroid_runtime_vm_headers",
- "libaudioclient_aidl_conversion_util",
- "libbinder",
- "libbinder_device_interface_sources",
- "libbinder_aidl",
- "libbinder_headers",
- "libbinder_headers_platform_shared",
- "libbinderthreadstateutils",
- "libbluetooth-types-header",
- "libcodec2",
- "libcodec2_headers",
- "libcodec2_internal",
- "libdmabufheap",
- "libgsm",
- "libgrallocusage",
- "libgralloctypes",
- "libnativewindow",
- "libneuralnetworks",
- "libneuralnetworks_static",
- "libgraphicsenv",
- "libhardware",
- "libhardware_headers",
- "libnativeloader-headers",
- "libnativewindow_headers",
- "libneuralnetworks_headers",
- "libneuralnetworks_packageinfo",
- "libopus",
- "libprocpartition",
- "libruy_static",
- "libandroidio",
- "libandroidio_srcs",
- "libserviceutils",
- "libsurfaceflinger_headers",
- "libsync",
- "libtextclassifier_hash_headers",
- "libtextclassifier_hash_static",
- "libtflite_kernel_utils",
- "libtinyxml2",
- "libui",
- "libui-types",
- "libui_headers",
- "libvorbisidec",
- "media_ndk_headers",
- "media_plugin_headers",
- "mediaswcodec.policy",
- "mediaswcodec.xml",
- "neuralnetworks_types",
- "libneuralnetworks_common",
- // packagemanager_aidl_interface is created implicitly in packagemanager_aidl module
- "packagemanager_aidl_interface",
- "philox_random",
- "philox_random_headers",
- "server_configurable_flags",
- "service-permission-streaming-proto-sources",
- "statslog_neuralnetworks.cpp",
- "statslog_neuralnetworks.h",
- "tensorflow_headers",
-
- "libstagefright_bufferpool@2.0",
- "libstagefright_bufferpool@2.0.1",
- "libSurfaceFlingerProp",
-
- // prebuilts
- "prebuilt_stats-log-api-gen",
-
- // fastboot
- "fastboot",
- "libfastboot",
- "liblp",
- "libstorage_literals_headers",
-
- "PluginCoreLib",
- "dagger2",
- "dagger2-android-annotation-stubs",
- "dagger2-bootstrap-compiler",
- "dagger2-producers",
- "okio-lib",
- "setupdesign-strings",
-
- //external/avb
- "avbtool",
- "libavb",
- "avb_headers",
-
- //external/libxml2
- "xmllint",
- "libxml2",
-
- //external/fec
- "libfec_rs",
-
- //frameworks/base/core/java
- "IDropBoxManagerService_aidl",
-
- //system/extras/ext4_utils
- "libext4_utils",
- "mke2fs_conf",
- "mkuserimg_mke2fs",
- "blk_alloc_to_base_fs",
-
- //system/extras/libfec
- "libfec",
-
- //system/extras/squashfs_utils
- "libsquashfs_utils",
-
- //packages/apps/Car/libs/car-ui-lib/car-ui-androidx
- // genrule dependencies for java_imports
- "car-ui-androidx-annotation-nodeps",
- "car-ui-androidx-collection-nodeps",
- "car-ui-androidx-core-common-nodeps",
- "car-ui-androidx-lifecycle-common-nodeps",
- "car-ui-androidx-constraintlayout-solver-nodeps",
-
- //system/libhidl
- "libhidlbase", // needed by cc_hidl_library
- "libhidl_gtest_helper",
-
- //frameworks/native/libs/input
- "inputconstants_aidl",
-
- // needed for aidl_interface's ndk backend
- "libbinder_ndk",
-
- "libusb",
-
- // needed by liblogd
- "ILogcatManagerService_aidl",
- "libincremental_aidl-cpp",
- "incremental_aidl",
-
- //frameworks/native/cmds/cmd
- "libcmd",
-
- //system/chre
- "chre_api",
-
- //system/core/fs_mgr/libdm
- "libdm",
-
- //system/core/fs_mgr/libfiemap
- "libfiemap_headers",
- "libfiemap_passthrough_srcs",
- "libfiemap_srcs",
-
- //system/gsid
- "libgsi",
- "libgsi_headers",
-
- //system/core/libkeyutils
- "libkeyutils",
-
- //bootable/recovery/otautil
- "libotautil",
-
- //system/vold
- "libvold_headers",
-
- //system/extras/libfscrypt
- "libfscrypt",
-
- //system/core/fs_mgr
- "libfstab",
-
- //bootable/recovery/fuse_sideload
- "libfusesideload",
-
- //system/core/fs_mgr/libfs_avb
- "libfs_avb",
-
- //system/core/fs_mgr
- "libfs_mgr",
-
- "libcodec2_hidl@1.0",
- "libcodec2_hidl@1.1",
- "libcodec2_hidl@1.2",
- "libcodec2_hidl_plugin_stub",
- "libcodec2_hidl_plugin",
- "libcodec2_hal_common",
- "libstagefright_bufferqueue_helper_novndk",
- "libGLESv2",
- "libEGL",
- "libcodec2_vndk",
- "libnativeloader_lazy",
- "libnativeloader",
- "libEGL_getProcAddress",
- "libEGL_blobCache",
-
- "mediaswcodec",
- "libmedia_headers",
- "libmedia_codecserviceregistrant",
- "libsfplugin_ccodec_utils",
- "libcodec2_soft_aacenc",
- "libcodec2_soft_amrnbdec",
- "libcodec2_soft_amrnbenc",
- "libcodec2_soft_amrwbdec",
- "libcodec2_soft_amrwbenc",
- "libcodec2_soft_hevcdec",
- "libcodec2_soft_hevcenc",
- "libcodec2_soft_g711alawdec",
- "libcodec2_soft_g711mlawdec",
- "libcodec2_soft_mpeg2dec",
- "libcodec2_soft_h263dec",
- "libcodec2_soft_h263enc",
- "libcodec2_soft_mpeg4dec",
- "libcodec2_soft_mpeg4enc",
- "libcodec2_soft_mp3dec",
- "libcodec2_soft_vorbisdec",
- "libcodec2_soft_opusdec",
- "libcodec2_soft_opusenc",
- "libcodec2_soft_vp8dec",
- "libcodec2_soft_vp9dec",
- "libcodec2_soft_av1dec_gav1",
- "libcodec2_soft_vp8enc",
- "libcodec2_soft_vp9enc",
- "libcodec2_soft_rawdec",
- "libcodec2_soft_flacdec",
- "libcodec2_soft_flacenc",
- "libcodec2_soft_gsmdec",
- "libcodec2_soft_avcdec",
- "libcodec2_soft_avcenc",
- "libcodec2_soft_aacdec",
- "libcodec2_soft_common",
-
- // kotlin srcs in java libs
- "kotlinx_atomicfu",
-
- // kotlin srcs in java binary
- "AnalyzerKt",
- "trebuchet-core",
-
- // kotlin srcs in android_library
- "renderscript_toolkit",
-
- //kotlin srcs in android_binary
- "MusicKotlin",
-
- // java_library with prebuilt sdk_version
- "android-common",
-
- // checked in current.txt for merged_txts
- "non-updatable-current.txt",
- "non-updatable-system-current.txt",
- "non-updatable-module-lib-current.txt",
- "non-updatable-system-server-current.txt",
-
- // for api_fingerprint.txt generation
- "api_fingerprint",
-
- // allowlisting for kotlinx_coroutines
- "annotations",
- "kotlinx-coroutines-android-annotation-stubs",
- "kotlinx-coroutines-core",
- "kotlinx_coroutines",
- "kotlinx_coroutines-device",
- "kotlinx_coroutines-host",
-
- // for building com.android.neuralnetworks
- "libimapper_stablec",
- "libimapper_providerutils",
-
- // min_sdk_version in android_app
- "CtsShimUpgrade",
-
- "art_cmdlineparser_headers",
-
- // Mainline Module Apps
- "CaptivePortalLogin",
- "ModuleMetadata",
-
- "libstagefright_headers",
-
- // aidl
- "aidl",
- "libaidl-common",
-
- // java_resources containing only a single filegroup
- "libauto_value_plugin",
- "auto_value_plugin_resources",
- "auto_value_extension",
-
- // Used by xsd_config
- "xsdc",
-
- // cc_test that can be run by b test
- "binderRpcWireProtocolTest",
- "binderUnitTest",
- "cpu_features-bit_utils_test",
- "liblp_test",
- "android.hardware.audio.common.test.utility_tests",
- "HalAudioStreamWorkerTest",
- "libjavacore-unit-tests",
- "NeuralNetworksTest_utils",
- "NeuralNetworksTest_logtag",
- "NeuralNetworksTest_operations",
- "nanoapp_chqts_shared_tests",
- "fakeservicemanager_test",
- "tristate_test",
- "binderUtilsHostTest",
- "run_dex2oat_test",
- "bluetooth-address-unit-tests",
-
- // for platform_compat_config
- "process-compat-config",
-
- // cc_* modules with rscript srcs
- "rstest-latency",
- "libRScpp_static",
- "rs-headers",
- "rs_script_api",
- "libRSDispatch",
-
- // hal_unit_tests and deps
- "android.hardware.contexthub_interface", // created implicitly by android.hardware.contexthub
- "chre_flatbuffers",
- "event_logger",
- "hal_unit_tests",
-
- "merge_annotation_zips_test",
-
- // bouncycastle dep
- "platform-test-annotations",
-
- // java_resources with multiple resource_dirs
- "emma",
- }
-
- Bp2buildModuleTypeAlwaysConvertList = []string{
- "aidl_interface_headers",
- "bpf",
- "combined_apis",
- "license",
- "linker_config",
- "java_import",
- "java_import_host",
- "java_sdk_library",
- "sysprop_library",
- "xsd_config",
- }
-
- // Add the names of modules that bp2build should never convert, if it is
- // in the package allowlist. An error will be thrown if a module must
- // not be here and in the alwaysConvert lists.
- //
- // For prebuilt modules (e.g. android_library_import), remember to add
- // the "prebuilt_" prefix to the name, so that it's differentiable from
- // the source versions within Soong's module graph.
- Bp2buildModuleDoNotConvertList = []string{
- // rust modules that have cc deps
- "liblogger",
- "libbssl_ffi",
- "libbssl_ffi_nostd",
- "pull_rust",
- "libstatslog_rust",
- "libstatslog_rust_header",
- "libflatbuffers",
- "liblog_event_list",
- "libminijail_rust",
- "libminijail_sys",
- "libfsverity_rs",
- "libtombstoned_client_rust",
-
- // TODO(b/263326760): Failed already.
- "minijail_compiler_unittest",
- "minijail_parser_unittest",
-
- // Depends on unconverted libandroid, libgui
- "dvr_buffer_queue-test",
- "dvr_display-test",
- // Depends on unconverted libchrome
- "pdx_benchmarks",
- "buffer_hub_queue-test",
- "buffer_hub_queue_producer-test",
-
- // cc bugs
-
- // TODO(b/198619163) module has same name as source
- "logtagd.rc",
-
- "libgtest_ndk_c++", "libgtest_main_ndk_c++", // TODO(b/201816222): Requires sdk_version support.
-
- // TODO(b/202876379): has arch-variant static_executable
- "linkerconfig",
- "mdnsd",
- "libcutils_test_static",
- "KernelLibcutilsTest",
-
- "linker", // TODO(b/228316882): cc_binary uses link_crt
- "versioner", // TODO(b/228313961): depends on prebuilt shared library libclang-cpp_host as a shared library, which does not supply expected providers for a shared library
-
- // requires host tools for apexer
- "apexer_test", "apexer_test_host_tools", "host_apex_verifier",
-
- // java bugs
- "libbase_ndk", // TODO(b/186826477): fails to link libctscamera2_jni for device (required for CtsCameraTestCases)
- "bouncycastle", // TODO(b/274474005): Need support for custom system_modules.
- "bouncycastle-test-lib", // TODO(b/274474005): Reverse dependency of bouncycastle
-
- // genrule incompatibilities
- "brotli-fuzzer-corpus", // TODO(b/202015218): outputs are in location incompatible with bazel genrule handling.
- "platform_tools_properties", "build_tools_source_properties", // TODO(b/203369847): multiple genrules in the same package creating the same file
-
- // aar support
- "prebuilt_car-ui-androidx-core-common", // TODO(b/224773339), genrule dependency creates an .aar, not a .jar
- // ERROR: The dependencies for the following 1 jar(s) are not complete.
- // 1.bazel-out/android_target-fastbuild/bin/prebuilts/tools/common/m2/_aar/robolectric-monitor-1.0.2-alpha1/classes_and_libs_merged.jar
- "prebuilt_robolectric-monitor-1.0.2-alpha1",
-
- // path property for filegroups
- "conscrypt", // TODO(b/210751803), we don't handle path property for filegroups
- "conscrypt-for-host", // TODO(b/210751803), we don't handle path property for filegroups
- "host-libprotobuf-java-full", // TODO(b/210751803), we don't handle path property for filegroups
- "libprotobuf-internal-python-srcs", // TODO(b/210751803), we don't handle path property for filegroups
- "libprotobuf-java-full", // TODO(b/210751803), we don't handle path property for filegroups
- "libprotobuf-java-util-full", // TODO(b/210751803), we don't handle path property for filegroups
-
- // go deps:
- "analyze_bcpf", // depends on bpmodify a blueprint_go_binary.
- "analyze_bcpf_test", // depends on bpmodify a blueprint_go_binary.
- "host_bionic_linker_asm", // depends on extract_linker, a go binary.
- "host_bionic_linker_script", // depends on extract_linker, a go binary.
-
- // rust support
- "libtombstoned_client_rust_bridge_code", "libtombstoned_client_wrapper", // rust conversions are not supported
-
- // unconverted deps
- "apexer_with_DCLA_preprocessing_test", // depends on unconverted modules: apexer_test_host_tools, com.android.example.apex
- "adb", // depends on unconverted modules: AdbWinApi, libandroidfw, libopenscreen-discovery, libopenscreen-platform-impl, libusb, bin2c_fastdeployagent, AdbWinUsbApi
- "android_icu4j_srcgen", // depends on unconverted modules: currysrc
- "android_icu4j_srcgen_binary", // depends on unconverted modules: android_icu4j_srcgen, currysrc
- "apex_compression_test", // depends on unconverted modules: soong_zip, com.android.example.apex
- "apex_manifest_proto_java", // b/210751803, depends on libprotobuf-java-full
- "art-script", // depends on unconverted modules: dalvikvm, dex2oat
- "bin2c_fastdeployagent", // depends on unconverted modules: deployagent
- "CarHTMLViewer", // depends on unconverted modules android.car-stubs, car-ui-lib
- "com.android.runtime", // depends on unconverted modules: bionic-linker-config, linkerconfig
- "currysrc", // depends on unconverted modules: currysrc_org.eclipse, guavalib, jopt-simple-4.9
- "dex2oat-script", // depends on unconverted modules: dex2oat
- "generated_android_icu4j_resources", // depends on unconverted modules: android_icu4j_srcgen_binary
- "generated_android_icu4j_test_resources", // depends on unconverted modules: android_icu4j_srcgen_binary
- "host-libprotobuf-java-nano", // b/220869005, depends on libprotobuf-java-nano
- "jacoco-stubs", // b/245767077, depends on droidstubs
- "libapexutil", // depends on unconverted modules: apex-info-list-tinyxml
- "libart", // depends on unconverted modules: apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api, art_operator_srcs, libcpu_features, libodrstatslog, libelffile, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfile, libnativebridge, libnativeloader, libsigchain, libartbase, libprofile, cpp-define-generator-asm-support
- "libart-runtime-gtest", // depends on unconverted modules: libgtest_isolated, libart-compiler, libdexfile, libprofile, libartbase, libartbase-art-gtest
- "libart_headers", // depends on unconverted modules: art_libartbase_headers
- "libartbase-art-gtest", // depends on unconverted modules: libgtest_isolated, libart, libart-compiler, libdexfile, libprofile
- "libartbased-art-gtest", // depends on unconverted modules: libgtest_isolated, libartd, libartd-compiler, libdexfiled, libprofiled
- "libart-runtime", // depends on unconverted modules: apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api, art_operator_srcs, libcpu_features, libodrstatslog, libelffile, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfile, libnativebridge, libnativeloader, libsigchain, libartbase, libprofile, cpp-define-generator-asm-support
- "libart-runtime-for-test", // depends on unconverted modules: apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api, art_operator_srcs, libcpu_features, libodrstatslog, libelffile, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfile, libnativebridge, libnativeloader, libsigchain, libartbase, libprofile, cpp-define-generator-asm-support
- "libartd", // depends on unconverted modules: art_operator_srcs, libcpu_features, libodrstatslog, libelffiled, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfiled, libnativebridge, libnativeloader, libsigchain, libartbased, libprofiled, cpp-define-generator-asm-support, apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api
- "libartd-runtime", // depends on unconverted modules: art_operator_srcs, libcpu_features, libodrstatslog, libelffiled, art_cmdlineparser_headers, cpp-define-generator-definitions, libdexfiled, libnativebridge, libnativeloader, libsigchain, libartbased, libprofiled, cpp-define-generator-asm-support, apex-info-list-tinyxml, libtinyxml2, libnativeloader-headers, heapprofd_client_api
- "libartd-runtime-gtest", // depends on unconverted modules: libgtest_isolated, libartd-compiler, libdexfiled, libprofiled, libartbased, libartbased-art-gtest
- "libdebuggerd", // depends on unconverted module: libdexfile
- "libdebuggerd_handler", // depends on unconverted module libdebuggerd_handler_core
- "libdebuggerd_handler_core", "libdebuggerd_handler_fallback", // depends on unconverted module libdebuggerd
- "libdexfiled", // depends on unconverted modules: dexfile_operator_srcs, libartbased, libartpalette
- "libgmock_main_ndk", // depends on unconverted modules: libgtest_ndk_c++
- "libgmock_ndk", // depends on unconverted modules: libgtest_ndk_c++
- "libnativehelper_lazy_mts_jni", "libnativehelper_mts_jni", // depends on unconverted modules: libnativetesthelper_jni, libgmock_ndk
- "libnativetesthelper_jni", // depends on unconverted modules: libgtest_ndk_c++
- "libphonenumber_test", // depends on android.test.mock
- "libstatslog", // depends on unconverted modules: libstatspull, statsd-aidl-ndk
- "libstatslog_art", // depends on unconverted modules: statslog_art.cpp, statslog_art.h
- "linker_reloc_bench_main", // depends on unconverted modules: liblinker_reloc_bench_*
- "malloc-rss-benchmark", // depends on unconverted modules: libmeminfo
- "pbtombstone", "crash_dump", // depends on libdebuggerd, libunwindstack
- "releasetools_test", // depends on unconverted modules: com.android.apex.compressed.v1
- "robolectric-sqlite4java-0.282", // depends on unconverted modules: robolectric-sqlite4java-import, robolectric-sqlite4java-native
- "static_crasher", // depends on unconverted modules: libdebuggerd_handler
- "test_fips", // depends on unconverted modules: adb
- "timezone-host", // depends on unconverted modules: art.module.api.annotations
-
- // aidl files not created
- "overlayable_policy_aidl_interface",
-
- //prebuilts/tools/common/m2
- // depends on //external/okio:okio-lib, which uses kotlin
- "wire-runtime",
-
- // depends on adbd_system_api_recovery, which is a unconverted `phony` module type
- "minadbd",
-
- // depends on android.hardware.health-V2.0-java
- "android.hardware.health-translate-java",
-
- //system/libvintf
- // depends on apex-info-list-tinyxml, unconverted xsd_config Soong module type.
- "libassemblevintf",
- "assemble_vintf",
- "checkvintf",
-
- // depends on audio_policy_configuration_aidl_default, xsd_config module.
- "libaudioserviceexampleimpl",
- "android.hardware.audio.service-aidl.example",
-
- // depends on //system/tools/aidl/build:aidl_metadata_json, which is an aidl_interfaces_metadata custom Soong type.
- "aidl_metadata_in_cpp",
- "libaidlmetadata",
- "libaidlmetadata_test",
-
- // depends on //system/tools/hidl/build:hidl_metadata_json, which is an hidl_interfaces_metadata custom Soong type.
- "hidl_metadata_in_cpp",
- "libhidlmetadata",
- "hidl_metadata_test",
-
- // cc_test related.
- // b/274164834 "Could not open Configuration file test.cfg"
- "svcenc", "svcdec",
-
- // Failing host cc_tests
- "gtest_isolated_tests",
- "libunwindstack_unit_test",
- "power_tests", // failing test on server, but not on host
-
- // reflect: call of reflect.Value.NumField on interface Value
- // affects all cc_tests that depend on art_defaults
- "libnativebridge-tests",
- "libnativeloader_test",
- "art_libnativebridge_cts_tests",
- "art_standalone_libdexfile_external_tests",
- "art_standalone_libdexfile_support_tests",
- "libnativebridge-lazy-tests",
- "libnativebridge-test-case",
- "libnativebridge2-test-case",
- "libnativebridge3-test-case",
- "libnativebridge6-test-case",
- "libnativebridge6prezygotefork",
-
- "libandroidfw_tests", // failing due to data path issues
-
- // error: overriding commands for target
- // `out/host/linux-x86/nativetest64/gmock_tests/gmock_tests__cc_runner_test',
- // previously defined at out/soong/installs-aosp_arm.mk:64919`
- "gmock_tests",
-
- // cc_test with unconverted deps, or are device-only (and not verified to pass yet)
- "AMRWBEncTest",
- "AmrnbDecoderTest", // depends on unconverted modules: libaudioutils, libsndfile
- "AmrnbEncoderTest", // depends on unconverted modules: libaudioutils, libsndfile
- "AmrwbDecoderTest", // depends on unconverted modules: libsndfile, libaudioutils
- "AmrwbEncoderTest", // depends on unconverted modules: libaudioutils, libsndfile
- "Mp3DecoderTest", // depends on unconverted modules: libsndfile, libaudioutils
- "avcdec",
- "avcenc",
- "bionic-benchmarks-tests",
- "bionic-fortify-runtime-asan-test",
- "bionic-stress-tests",
- "bionic-unit-tests",
- "bionic-unit-tests-glibc",
- "bionic-unit-tests-static",
- "boringssl_crypto_test",
- "boringssl_ssl_test",
- "boringssl_test_support", //b/244431896
- "cfi_test_helper",
- "cfi_test_helper2",
- "cintltst32",
- "cintltst64",
- "compare",
- "cpuid",
- "debuggerd_test", // depends on unconverted modules: libdebuggerd
- "elftls_dlopen_ie_error_helper",
- "exec_linker_helper",
- "fastdeploy_test", // depends on unconverted modules: AdbWinApi, libadb_host, libandroidfw, libfastdeploy_host, libopenscreen-discovery, libopenscreen-platform-impl, libusb
- "fdtrack_test",
- "google-benchmark-test",
- "googletest-param-test-test_ndk", // depends on unconverted modules: libgtest_ndk_c++
- "gtest-typed-test_test",
- "gtest-typed-test_test_ndk", // depends on unconverted modules: libgtest_ndk_c++, libgtest_main_ndk_c++
- "gtest_ndk_tests", // depends on unconverted modules: libgtest_ndk_c++, libgtest_main_ndk_c++
- "gtest_ndk_tests_no_main", // depends on unconverted modules: libgtest_ndk_c++
- "gtest_prod_test_ndk", // depends on unconverted modules: libgtest_ndk_c++, libgtest_main_ndk_c++
- "gtest_tests",
- "gtest_tests_no_main",
- "gwp_asan_unittest",
- "half_test",
- "hashcombine_test",
- "hevcdec",
- "hevcenc",
- "hwbinderThroughputTest", // depends on unconverted modules: android.hardware.tests.libhwbinder@1.0-impl.test, android.hardware.tests.libhwbinder@1.0
- "i444tonv12_eg",
- "icu4c_sample_break",
- "intltest32",
- "intltest64",
- "ion-unit-tests",
- "jemalloc5_integrationtests",
- "jemalloc5_unittests",
- "jemalloc5_stresstests", // run by run_jemalloc_tests.sh and will be deleted after V
- "ld_config_test_helper",
- "ld_preload_test_helper",
- "libBionicCtsGtestMain", // depends on unconverted modules: libgtest_isolated
- "libBionicLoaderTests", // depends on unconverted modules: libmeminfo
- "libapexutil_tests", // depends on unconverted modules: apex-info-list-tinyxml, libapexutil
- "libcutils_sockets_test",
- "libhwbinder_latency",
- "liblog-host-test", // failing tests
- "libminijail_test",
- "libminijail_unittest_gtest",
- "libpackagelistparser_test",
- "libprotobuf_vendor_suffix_test",
- "libstagefright_amrnbdec_test", // depends on unconverted modules: libsndfile, libaudioutils
- "libstagefright_amrnbenc_test",
- "libstagefright_amrwbdec_test", // depends on unconverted modules: libsndfile, libaudioutils
- "libstagefright_m4vh263enc_test",
- "libstagefright_mp3dec_test", // depends on unconverted modules: libsndfile, libaudioutils
- "libstatssocket_test",
- "libvndksupport-tests",
- "libyuv_unittest",
- "linker-unit-tests",
- "malloc_debug_system_tests",
- "malloc_debug_unit_tests",
- "malloc_hooks_system_tests",
- "mat_test",
- "mathtest",
- "memunreachable_binder_test", // depends on unconverted modules: libbinder
- "memunreachable_test",
- "metadata_tests",
- "mpeg2dec",
- "mvcdec",
- "ns_hidden_child_helper",
- "pngtest",
- "preinit_getauxval_test_helper",
- "preinit_syscall_test_helper",
- "psnr",
- "quat_test",
- "rappor-tests", // depends on unconverted modules: jsr305, guava
- "scudo_unit_tests",
- "stats-log-api-gen-test", // depends on unconverted modules: libstats_proto_host
- "thread_exit_cb_helper",
- "tls_properties_helper",
- "ulp",
- "vec_test",
- "yuvconstants",
- "yuvconvert",
-
- // cc_test_library
- "clang_diagnostic_tests",
- "exec_linker_helper_lib",
- "fortify_disabled_for_tidy",
- "ld_config_test_helper_lib1",
- "ld_config_test_helper_lib2",
- "ld_config_test_helper_lib3",
- "ld_preload_test_helper_lib1",
- "ld_preload_test_helper_lib2",
- "libBionicElfTlsLoaderTests",
- "libBionicElfTlsTests",
- "libBionicElfTlsTests",
- "libBionicFramePointerTests",
- "libBionicFramePointerTests",
- "libBionicStandardTests",
- "libBionicStandardTests",
- "libBionicTests",
- "libart-broken",
- "libatest_simple_zip",
- "libcfi-test",
- "libcfi-test-bad",
- "libcrash_test",
- "libcrypto_fuzz_unsafe",
- "libdl_preempt_test_1",
- "libdl_preempt_test_2",
- "libdl_test_df_1_global",
- "libdlext_test",
- "libdlext_test_different_soname",
- "libdlext_test_fd",
- "libdlext_test_norelro",
- "libdlext_test_recursive",
- "libdlext_test_zip",
- "libdvrcommon_test",
- "libfortify1-new-tests-clang",
- "libfortify1-new-tests-clang",
- "libfortify1-tests-clang",
- "libfortify1-tests-clang",
- "libfortify2-new-tests-clang",
- "libfortify2-new-tests-clang",
- "libfortify2-tests-clang",
- "libfortify2-tests-clang",
- "libgnu-hash-table-library",
- "libicutest_static",
- "liblinker_reloc_bench_000",
- "liblinker_reloc_bench_001",
- "liblinker_reloc_bench_002",
- "liblinker_reloc_bench_003",
- "liblinker_reloc_bench_004",
- "liblinker_reloc_bench_005",
- "liblinker_reloc_bench_006",
- "liblinker_reloc_bench_007",
- "liblinker_reloc_bench_008",
- "liblinker_reloc_bench_009",
- "liblinker_reloc_bench_010",
- "liblinker_reloc_bench_011",
- "liblinker_reloc_bench_012",
- "liblinker_reloc_bench_013",
- "liblinker_reloc_bench_014",
- "liblinker_reloc_bench_015",
- "liblinker_reloc_bench_016",
- "liblinker_reloc_bench_017",
- "liblinker_reloc_bench_018",
- "liblinker_reloc_bench_019",
- "liblinker_reloc_bench_020",
- "liblinker_reloc_bench_021",
- "liblinker_reloc_bench_022",
- "liblinker_reloc_bench_023",
- "liblinker_reloc_bench_024",
- "liblinker_reloc_bench_025",
- "liblinker_reloc_bench_026",
- "liblinker_reloc_bench_027",
- "liblinker_reloc_bench_028",
- "liblinker_reloc_bench_029",
- "liblinker_reloc_bench_030",
- "liblinker_reloc_bench_031",
- "liblinker_reloc_bench_032",
- "liblinker_reloc_bench_033",
- "liblinker_reloc_bench_034",
- "liblinker_reloc_bench_035",
- "liblinker_reloc_bench_036",
- "liblinker_reloc_bench_037",
- "liblinker_reloc_bench_038",
- "liblinker_reloc_bench_039",
- "liblinker_reloc_bench_040",
- "liblinker_reloc_bench_041",
- "liblinker_reloc_bench_042",
- "liblinker_reloc_bench_043",
- "liblinker_reloc_bench_044",
- "liblinker_reloc_bench_045",
- "liblinker_reloc_bench_046",
- "liblinker_reloc_bench_047",
- "liblinker_reloc_bench_048",
- "liblinker_reloc_bench_049",
- "liblinker_reloc_bench_050",
- "liblinker_reloc_bench_051",
- "liblinker_reloc_bench_052",
- "liblinker_reloc_bench_053",
- "liblinker_reloc_bench_054",
- "liblinker_reloc_bench_055",
- "liblinker_reloc_bench_056",
- "liblinker_reloc_bench_057",
- "liblinker_reloc_bench_058",
- "liblinker_reloc_bench_059",
- "liblinker_reloc_bench_060",
- "liblinker_reloc_bench_061",
- "liblinker_reloc_bench_062",
- "liblinker_reloc_bench_063",
- "liblinker_reloc_bench_064",
- "liblinker_reloc_bench_065",
- "liblinker_reloc_bench_066",
- "liblinker_reloc_bench_067",
- "liblinker_reloc_bench_068",
- "liblinker_reloc_bench_069",
- "liblinker_reloc_bench_070",
- "liblinker_reloc_bench_071",
- "liblinker_reloc_bench_072",
- "liblinker_reloc_bench_073",
- "liblinker_reloc_bench_074",
- "liblinker_reloc_bench_075",
- "liblinker_reloc_bench_076",
- "liblinker_reloc_bench_077",
- "liblinker_reloc_bench_078",
- "liblinker_reloc_bench_079",
- "liblinker_reloc_bench_080",
- "liblinker_reloc_bench_081",
- "liblinker_reloc_bench_082",
- "liblinker_reloc_bench_083",
- "liblinker_reloc_bench_084",
- "liblinker_reloc_bench_085",
- "liblinker_reloc_bench_086",
- "liblinker_reloc_bench_087",
- "liblinker_reloc_bench_088",
- "liblinker_reloc_bench_089",
- "liblinker_reloc_bench_090",
- "liblinker_reloc_bench_091",
- "liblinker_reloc_bench_092",
- "liblinker_reloc_bench_093",
- "liblinker_reloc_bench_094",
- "liblinker_reloc_bench_095",
- "liblinker_reloc_bench_096",
- "liblinker_reloc_bench_097",
- "liblinker_reloc_bench_098",
- "liblinker_reloc_bench_099",
- "liblinker_reloc_bench_100",
- "liblinker_reloc_bench_101",
- "liblinker_reloc_bench_102",
- "liblinker_reloc_bench_103",
- "liblinker_reloc_bench_104",
- "liblinker_reloc_bench_105",
- "liblinker_reloc_bench_106",
- "liblinker_reloc_bench_107",
- "liblinker_reloc_bench_108",
- "liblinker_reloc_bench_109",
- "liblinker_reloc_bench_110",
- "liblinker_reloc_bench_111",
- "liblinker_reloc_bench_112",
- "liblinker_reloc_bench_113",
- "liblinker_reloc_bench_114",
- "liblinker_reloc_bench_115",
- "liblinker_reloc_bench_116",
- "liblinker_reloc_bench_117",
- "liblinker_reloc_bench_118",
- "liblinker_reloc_bench_119",
- "liblinker_reloc_bench_120",
- "liblinker_reloc_bench_121",
- "liblinker_reloc_bench_122",
- "liblinker_reloc_bench_123",
- "liblinker_reloc_bench_124",
- "liblinker_reloc_bench_125",
- "liblinker_reloc_bench_126",
- "liblinker_reloc_bench_127",
- "liblinker_reloc_bench_128",
- "liblinker_reloc_bench_129",
- "liblinker_reloc_bench_130",
- "liblinker_reloc_bench_131",
- "liblinker_reloc_bench_132",
- "liblinker_reloc_bench_133",
- "liblinker_reloc_bench_134",
- "liblinker_reloc_bench_135",
- "liblinker_reloc_bench_136",
- "liblinker_reloc_bench_137",
- "liblinker_reloc_bench_138",
- "liblinker_reloc_bench_139",
- "liblinker_reloc_bench_140",
- "liblinker_reloc_bench_141",
- "liblinker_reloc_bench_142",
- "liblinker_reloc_bench_143",
- "liblinker_reloc_bench_144",
- "liblinker_reloc_bench_145",
- "liblinker_reloc_bench_146",
- "liblinker_reloc_bench_147",
- "liblinker_reloc_bench_148",
- "liblinker_reloc_bench_149",
- "liblinker_reloc_bench_150",
- "liblinker_reloc_bench_151",
- "liblinker_reloc_bench_152",
- "liblinker_reloc_bench_153",
- "liblinker_reloc_bench_154",
- "liblinker_reloc_bench_155",
- "liblinker_reloc_bench_156",
- "liblinker_reloc_bench_157",
- "liblinker_reloc_bench_158",
- "liblinker_reloc_bench_159",
- "liblinker_reloc_bench_160",
- "liblinker_reloc_bench_161",
- "liblinker_reloc_bench_162",
- "liblinker_reloc_bench_163",
- "liblinker_reloc_bench_164",
- "liblinker_reloc_bench_165",
- "liblinker_reloc_bench_166",
- "liblinker_reloc_bench_167",
- "liblinker_reloc_bench_168",
- "libns_hidden_child_app",
- "libns_hidden_child_global",
- "libns_hidden_child_internal",
- "libns_hidden_child_public",
- "libnstest_dlopened",
- "libnstest_ns_a_public1",
- "libnstest_ns_a_public1_internal",
- "libnstest_ns_b_public2",
- "libnstest_ns_b_public3",
- "libnstest_private",
- "libnstest_private_external",
- "libnstest_public",
- "libnstest_public_internal",
- "libnstest_root",
- "libnstest_root_not_isolated",
- "librelocations-ANDROID_REL",
- "librelocations-ANDROID_RELR",
- "librelocations-RELR",
- "librelocations-fat",
- "libsegment_gap_inner",
- "libsegment_gap_outer",
- "libssl_fuzz_unsafe",
- "libstatssocket_private",
- "libsysv-hash-table-library",
- "libtest_atexit",
- "libtest_check_order_dlsym",
- "libtest_check_order_dlsym_1_left",
- "libtest_check_order_dlsym_2_right",
- "libtest_check_order_dlsym_3_c",
- "libtest_check_order_dlsym_a",
- "libtest_check_order_dlsym_b",
- "libtest_check_order_dlsym_d",
- "libtest_check_order_reloc_root",
- "libtest_check_order_reloc_root_1",
- "libtest_check_order_reloc_root_2",
- "libtest_check_order_reloc_siblings",
- "libtest_check_order_reloc_siblings_1",
- "libtest_check_order_reloc_siblings_2",
- "libtest_check_order_reloc_siblings_3",
- "libtest_check_order_reloc_siblings_a",
- "libtest_check_order_reloc_siblings_b",
- "libtest_check_order_reloc_siblings_c",
- "libtest_check_order_reloc_siblings_c_1",
- "libtest_check_order_reloc_siblings_c_2",
- "libtest_check_order_reloc_siblings_d",
- "libtest_check_order_reloc_siblings_e",
- "libtest_check_order_reloc_siblings_f",
- "libtest_check_rtld_next_from_library",
- "libtest_dlopen_df_1_global",
- "libtest_dlopen_from_ctor",
- "libtest_dlopen_from_ctor_main",
- "libtest_dlopen_weak_undefined_func",
- "libtest_dlsym_df_1_global",
- "libtest_dlsym_from_this",
- "libtest_dlsym_from_this_child",
- "libtest_dlsym_from_this_grandchild",
- "libtest_dlsym_weak_func",
- "libtest_dt_runpath_a",
- "libtest_dt_runpath_b",
- "libtest_dt_runpath_c",
- "libtest_dt_runpath_d",
- "libtest_dt_runpath_d_zip",
- "libtest_dt_runpath_x",
- "libtest_dt_runpath_y",
- "libtest_elftls_dynamic",
- "libtest_elftls_dynamic_filler_1",
- "libtest_elftls_dynamic_filler_2",
- "libtest_elftls_dynamic_filler_3",
- "libtest_elftls_shared_var",
- "libtest_elftls_shared_var_ie",
- "libtest_elftls_tprel",
- "libtest_empty",
- "libtest_ifunc",
- "libtest_ifunc_variable",
- "libtest_ifunc_variable_impl",
- "libtest_indirect_thread_local_dtor",
- "libtest_init_fini_order_child",
- "libtest_init_fini_order_grand_child",
- "libtest_init_fini_order_root",
- "libtest_init_fini_order_root2",
- "libtest_missing_symbol",
- "libtest_missing_symbol_child_private",
- "libtest_missing_symbol_child_public",
- "libtest_missing_symbol_root",
- "libtest_nodelete_1",
- "libtest_nodelete_2",
- "libtest_nodelete_dt_flags_1",
- "libtest_pthread_atfork",
- "libtest_relo_check_dt_needed_order",
- "libtest_relo_check_dt_needed_order_1",
- "libtest_relo_check_dt_needed_order_2",
- "libtest_simple",
- "libtest_thread_local_dtor",
- "libtest_thread_local_dtor2",
- "libtest_two_parents_child",
- "libtest_two_parents_parent1",
- "libtest_two_parents_parent2",
- "libtest_versioned_lib",
- "libtest_versioned_libv1",
- "libtest_versioned_libv2",
- "libtest_versioned_otherlib",
- "libtest_versioned_otherlib_empty",
- "libtest_versioned_uselibv1",
- "libtest_versioned_uselibv2",
- "libtest_versioned_uselibv2_other",
- "libtest_versioned_uselibv3_other",
- "libtest_with_dependency",
- "libtest_with_dependency_loop",
- "libtest_with_dependency_loop_a",
- "libtest_with_dependency_loop_b",
- "libtest_with_dependency_loop_b_tmp",
- "libtest_with_dependency_loop_c",
- "libtestshared",
-
- // depends on unconverted libprotobuf-java-nano
- "dnsresolverprotosnano",
- "launcherprotosnano",
- "datastallprotosnano",
- "devicepolicyprotosnano",
- "ota_metadata_proto_java",
- "merge_ota",
-
- // releasetools
- "verity_utils",
- "check_ota_package_signature",
- "check_target_files_vintf",
- "releasetools_check_target_files_vintf",
- "ota_from_target_files",
- "releasetools_ota_from_target_files",
- "add_img_to_target_files",
- "releasetools_add_img_to_target_files",
- "fsverity_metadata_generator",
- "sign_target_files_apks",
-
- // depends on the support of yacc file
- "libapplypatch",
- "libapplypatch_modes",
- "applypatch",
-
- // TODO(b/254476335): disable the following due to this bug
- "libapexinfo",
- "libapexinfo_tests",
-
- // uses glob in $(locations)
- "libc_musl_sysroot",
-
- // TODO(b/266459895): depends on libunwindstack
- "libutils_test",
-
- // Has dependencies on other tools like ziptool, bp2build'd data properties don't work with these tests atm
- "ziparchive_tests_large",
- "mkbootimg_test",
- "certify_bootimg_test",
-
- // Despite being _host module types, these require devices to run
- "logd_integration_test",
- "mobly-hello-world-test",
- "mobly-multidevice-test",
-
- // TODO(b/274805756): Support core_platform and current java APIs
- "fake-framework",
-
- // TODO(b/277616982): These modules depend on private java APIs, but maybe they don't need to.
- "StreamingProtoTest",
- "textclassifierprotoslite",
- "styleprotoslite",
- "CtsPkgInstallerConstants",
- "guava-android-testlib",
-
- "MetaDataBaseUnitTest", // depends on libstagefright
- "AVCUtilsUnitTest", // depends on libstagefright
- "ColorUtilsTest", // depends on libmediandk
-
- // python_test_host with test data
- "sbom_writers_test",
-
- // TODO(B/283193845): tradefed and its java_test_host dependents
- "tradefed",
- "permissive_mte_test",
- "ICU4CTestRunner",
- "DeviceLongPollingStubTest",
- "FastDeployHostTests",
-
- "libprotobuf-full-test", // TODO(b/246997908): cannot convert proto_libraries which implicitly include other srcs in the same directory
- "libprotobuf-lite-test", // TODO(b/246997908): cannot convert proto_libraries which implicitly include other srcs in the same directory
-
- "logcat", // TODO(b/246997908): cannot convert proto_libraries which implicitly include other srcs in the same directory
-
- "expresscatalogvalidator", // TODO(b/246997908): cannot convert proto_libraries which implicitly include other srcs in the same directory
-
- // depends on other //art modules
- "libart-for-test",
- "libart_generated_headers",
- "libart-runtime-gtest",
- "libartd-runtime-gtest",
- "libart-unstripped",
-
- // depends on libart-unstripped and new module type llvm_prebuilt_build_tool
- "check_cfi",
-
- // depends on unconverted module tradefed
- "HelloWorldPerformanceTest",
-
- // r8 is a java_binary, which creates an implicit "r8.jar" target, but the
- // same package contains a "r8.jar" file which gets overshadowed by the implicit target.
- // We don't need this target as we're not using the Soong wrapper for now
- "r8",
-
- // Depends on the module defined in the directory not bp2build default allowed
- "ota_from_raw_img",
- }
-
- // Bazel prod-mode allowlist. Modules in this list are built by Bazel
- // in either prod mode or staging mode.
- ProdMixedBuildsEnabledList = []string{
- // M5: tzdata launch
- "com.android.tzdata",
- "test1_com.android.tzdata",
- "test3_com.android.tzdata",
- // M7: adbd launch
- "com.android.adbd",
- "test_com.android.adbd",
- "adbd_test",
- "adb_crypto_test",
- "adb_pairing_auth_test",
- "adb_pairing_connection_test",
- "adb_tls_connection_test",
- // M9: mixed builds for mainline trains launch
- "api_fingerprint",
- // M11: neuralnetworks launch
- "com.android.neuralnetworks",
- "test_com.android.neuralnetworks",
- "libneuralnetworks",
- "libneuralnetworks_static",
- // M13: media.swcodec launch
- "com.android.media.swcodec",
- "test_com.android.media.swcodec",
- "libstagefright_foundation",
- "libcodec2_hidl@1.0",
- }
-
- // Staging-mode allowlist. Modules in this list are only built
- // by Bazel with --bazel-mode-staging. This list should contain modules
- // which will soon be added to the prod allowlist.
- // It is implicit that all modules in ProdMixedBuildsEnabledList will
- // also be built - do not add them to this list.
- StagingMixedBuildsEnabledList = []string{}
-
- // These should be the libs that are included by the apexes in the ProdMixedBuildsEnabledList
- ProdDclaMixedBuildsEnabledList = []string{
- "libbase",
- "libc++",
- "libcrypto",
- "libcutils",
- "libstagefright_flacdec",
- "libutils",
- }
-
- // These should be the libs that are included by the apexes in the StagingMixedBuildsEnabledList
- StagingDclaMixedBuildsEnabledList = []string{}
-
- // TODO(b/269342245): Enable the rest of the DCLA libs
- // "libssl",
-
// The list of module types which are expected to spend lots of build time.
// With `--ninja_weight_source=soong`, ninja builds these module types and deps first.
HugeModuleTypePrefixMap = map[string]int{
@@ -1707,18 +33,4 @@
"art_": DEFAULT_PRIORITIZED_WEIGHT,
"ndk_library": DEFAULT_PRIORITIZED_WEIGHT,
}
-
- BazelSandwichTargets = []struct {
- Label string
- Host bool
- }{
- {
- Label: "//build/bazel/examples/partitions:system_image",
- Host: false,
- },
- {
- Label: "//build/bazel/examples/partitions:run_test",
- Host: false,
- },
- }
)
diff --git a/android/androidmk.go b/android/androidmk.go
index 62f82f2..07f7c58 100644
--- a/android/androidmk.go
+++ b/android/androidmk.go
@@ -30,6 +30,7 @@
"reflect"
"runtime"
"sort"
+ "strconv"
"strings"
"github.com/google/blueprint"
@@ -159,7 +160,7 @@
}
type AndroidMkExtraEntriesContext interface {
- Provider(provider blueprint.ProviderKey) interface{}
+ Provider(provider blueprint.AnyProviderKey) (any, bool)
}
type androidMkExtraEntriesContext struct {
@@ -167,8 +168,8 @@
mod blueprint.Module
}
-func (a *androidMkExtraEntriesContext) Provider(provider blueprint.ProviderKey) interface{} {
- return a.ctx.ModuleProvider(a.mod, provider)
+func (a *androidMkExtraEntriesContext) Provider(provider blueprint.AnyProviderKey) (any, bool) {
+ return a.ctx.moduleProvider(a.mod, provider)
}
type AndroidMkExtraEntriesFunc func(ctx AndroidMkExtraEntriesContext, entries *AndroidMkEntries)
@@ -275,14 +276,17 @@
}
// AddCompatibilityTestSuites adds the supplied test suites to the EntryMap, with special handling
-// for partial MTS test suites.
+// for partial MTS and MCTS test suites.
func (a *AndroidMkEntries) AddCompatibilityTestSuites(suites ...string) {
- // MTS supports a full test suite and partial per-module MTS test suites, with naming mts-${MODULE}.
- // To reduce repetition, if we find a partial MTS test suite without an full MTS test suite,
+ // M(C)TS supports a full test suite and partial per-module MTS test suites, with naming mts-${MODULE}.
+ // To reduce repetition, if we find a partial M(C)TS test suite without an full M(C)TS test suite,
// we add the full test suite to our list.
if PrefixInList(suites, "mts-") && !InList("mts", suites) {
suites = append(suites, "mts")
}
+ if PrefixInList(suites, "mcts-") && !InList("mcts", suites) {
+ suites = append(suites, "mcts")
+ }
a.AddStrings("LOCAL_COMPATIBILITY_SUITE", suites...)
}
@@ -486,25 +490,13 @@
return generateDistContributionsForMake(distContributions)
}
-// Write the license variables to Make for AndroidMkData.Custom(..) methods that do not call WriteAndroidMkData(..)
-// It's required to propagate the license metadata even for module types that have non-standard interfaces to Make.
-func (a *AndroidMkEntries) WriteLicenseVariables(w io.Writer) {
- AndroidMkEmitAssignList(w, "LOCAL_LICENSE_KINDS", a.EntryMap["LOCAL_LICENSE_KINDS"])
- AndroidMkEmitAssignList(w, "LOCAL_LICENSE_CONDITIONS", a.EntryMap["LOCAL_LICENSE_CONDITIONS"])
- AndroidMkEmitAssignList(w, "LOCAL_NOTICE_FILE", a.EntryMap["LOCAL_NOTICE_FILE"])
- if pn, ok := a.EntryMap["LOCAL_LICENSE_PACKAGE_NAME"]; ok {
- AndroidMkEmitAssignList(w, "LOCAL_LICENSE_PACKAGE_NAME", pn)
- }
-}
-
// fillInEntries goes through the common variable processing and calls the extra data funcs to
// generate and fill in AndroidMkEntries's in-struct data, ready to be flushed to a file.
type fillInEntriesContext interface {
ModuleDir(module blueprint.Module) string
ModuleSubDir(module blueprint.Module) string
Config() Config
- ModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{}
- ModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool
+ moduleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
ModuleType(module blueprint.Module) string
}
@@ -534,15 +526,6 @@
// Collect make variable assignment entries.
a.SetString("LOCAL_PATH", ctx.ModuleDir(mod))
a.SetString("LOCAL_MODULE", name+a.SubName)
- a.AddStrings("LOCAL_LICENSE_KINDS", base.commonProperties.Effective_license_kinds...)
- a.AddStrings("LOCAL_LICENSE_CONDITIONS", base.commonProperties.Effective_license_conditions...)
- a.AddStrings("LOCAL_NOTICE_FILE", base.commonProperties.Effective_license_text.Strings()...)
- // TODO(b/151177513): Does this code need to set LOCAL_MODULE_IS_CONTAINER ?
- if base.commonProperties.Effective_package_name != nil {
- a.SetString("LOCAL_LICENSE_PACKAGE_NAME", *base.commonProperties.Effective_package_name)
- } else if len(base.commonProperties.Effective_licenses) > 0 {
- a.SetString("LOCAL_LICENSE_PACKAGE_NAME", strings.Join(base.commonProperties.Effective_licenses, " "))
- }
a.SetString("LOCAL_MODULE_CLASS", a.Class)
a.SetString("LOCAL_PREBUILT_MODULE_FILE", a.OutputFile.String())
a.AddStrings("LOCAL_REQUIRED_MODULES", a.Required...)
@@ -560,6 +543,10 @@
a.SetPaths("LOCAL_SOONG_INSTALL_SYMLINKS", base.katiSymlinks.InstallPaths().Paths())
}
+ if len(base.testData) > 0 {
+ a.AddStrings("LOCAL_TEST_DATA", androidMkDataPaths(base.testData)...)
+ }
+
if am, ok := mod.(ApexModule); ok {
a.SetBoolIfTrue("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", am.NotAvailableForPlatform())
}
@@ -639,11 +626,14 @@
}
}
- if ctx.ModuleHasProvider(mod, LicenseMetadataProvider) {
- licenseMetadata := ctx.ModuleProvider(mod, LicenseMetadataProvider).(*LicenseMetadataInfo)
+ if licenseMetadata, ok := SingletonModuleProvider(ctx, mod, LicenseMetadataProvider); ok {
a.SetPath("LOCAL_SOONG_LICENSE_METADATA", licenseMetadata.LicenseMetadataPath)
}
+ if _, ok := SingletonModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
+ a.SetBool("LOCAL_SOONG_MODULE_INFO_JSON", true)
+ }
+
extraCtx := &androidMkExtraEntriesContext{
ctx: ctx,
mod: mod,
@@ -661,14 +651,14 @@
}
}
+func (a *AndroidMkEntries) disabled() bool {
+ return a.Disabled || !a.OutputFile.Valid()
+}
+
// write flushes the AndroidMkEntries's in-struct data populated by AndroidMkEntries into the
// given Writer object.
func (a *AndroidMkEntries) write(w io.Writer) {
- if a.Disabled {
- return
- }
-
- if !a.OutputFile.Valid() {
+ if a.disabled() {
return
}
@@ -714,7 +704,9 @@
return
}
- err := translateAndroidMk(ctx, absolutePath(transMk.String()), androidMkModulesList)
+ moduleInfoJSON := PathForOutput(ctx, "module-info"+String(ctx.Config().productVariables.Make_suffix)+".json")
+
+ err := translateAndroidMk(ctx, absolutePath(transMk.String()), moduleInfoJSON, androidMkModulesList)
if err != nil {
ctx.Errorf(err.Error())
}
@@ -725,14 +717,16 @@
})
}
-func translateAndroidMk(ctx SingletonContext, absMkFile string, mods []blueprint.Module) error {
+func translateAndroidMk(ctx SingletonContext, absMkFile string, moduleInfoJSONPath WritablePath, mods []blueprint.Module) error {
buf := &bytes.Buffer{}
+ var moduleInfoJSONs []*ModuleInfoJSON
+
fmt.Fprintln(buf, "LOCAL_MODULE_MAKEFILE := $(lastword $(MAKEFILE_LIST))")
typeStats := make(map[string]int)
for _, mod := range mods {
- err := translateAndroidMkModule(ctx, buf, mod)
+ err := translateAndroidMkModule(ctx, buf, &moduleInfoJSONs, mod)
if err != nil {
os.Remove(absMkFile)
return err
@@ -754,10 +748,36 @@
fmt.Fprintf(buf, "STATS.SOONG_MODULE_TYPE.%s := %d\n", mod_type, typeStats[mod_type])
}
- return pathtools.WriteFileIfChanged(absMkFile, buf.Bytes(), 0666)
+ err := pathtools.WriteFileIfChanged(absMkFile, buf.Bytes(), 0666)
+ if err != nil {
+ return err
+ }
+
+ return writeModuleInfoJSON(ctx, moduleInfoJSONs, moduleInfoJSONPath)
}
-func translateAndroidMkModule(ctx SingletonContext, w io.Writer, mod blueprint.Module) error {
+func writeModuleInfoJSON(ctx SingletonContext, moduleInfoJSONs []*ModuleInfoJSON, moduleInfoJSONPath WritablePath) error {
+ moduleInfoJSONBuf := &strings.Builder{}
+ moduleInfoJSONBuf.WriteString("[")
+ for i, moduleInfoJSON := range moduleInfoJSONs {
+ if i != 0 {
+ moduleInfoJSONBuf.WriteString(",\n")
+ }
+ moduleInfoJSONBuf.WriteString("{")
+ moduleInfoJSONBuf.WriteString(strconv.Quote(moduleInfoJSON.core.RegisterName))
+ moduleInfoJSONBuf.WriteString(":")
+ err := encodeModuleInfoJSON(moduleInfoJSONBuf, moduleInfoJSON)
+ moduleInfoJSONBuf.WriteString("}")
+ if err != nil {
+ return err
+ }
+ }
+ moduleInfoJSONBuf.WriteString("]")
+ WriteFileRule(ctx, moduleInfoJSONPath, moduleInfoJSONBuf.String())
+ return nil
+}
+
+func translateAndroidMkModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON, mod blueprint.Module) error {
defer func() {
if r := recover(); r != nil {
panic(fmt.Errorf("%s in translateAndroidMkModule for module %s variant %s",
@@ -766,17 +786,23 @@
}()
// Additional cases here require review for correct license propagation to make.
+ var err error
switch x := mod.(type) {
case AndroidMkDataProvider:
- return translateAndroidModule(ctx, w, mod, x)
+ err = translateAndroidModule(ctx, w, moduleInfoJSONs, mod, x)
case bootstrap.GoBinaryTool:
- return translateGoBinaryModule(ctx, w, mod, x)
+ err = translateGoBinaryModule(ctx, w, mod, x)
case AndroidMkEntriesProvider:
- return translateAndroidMkEntriesModule(ctx, w, mod, x)
+ err = translateAndroidMkEntriesModule(ctx, w, moduleInfoJSONs, mod, x)
default:
// Not exported to make so no make variables to set.
- return nil
}
+
+ if err != nil {
+ return err
+ }
+
+ return err
}
// A simple, special Android.mk entry output func to make it possible to build blueprint tools using
@@ -819,8 +845,8 @@
// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
// instead.
-func translateAndroidModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
- provider AndroidMkDataProvider) error {
+func translateAndroidModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON,
+ mod blueprint.Module, provider AndroidMkDataProvider) error {
amod := mod.(Module).base()
if shouldSkipAndroidMkProcessing(amod) {
@@ -833,6 +859,7 @@
}
data.fillInData(ctx, mod)
+ aconfigUpdateAndroidMkData(ctx, mod.(Module), &data)
prefix := ""
if amod.ArchSpecific() {
@@ -870,6 +897,7 @@
case "*java.SystemModules": // doesn't go through base_rules
case "*java.systemModulesImport": // doesn't go through base_rules
case "*phony.phony": // license properties written
+ case "*phony.PhonyRule": // writes phony deps and acts like `.PHONY`
case "*selinux.selinuxContextsModule": // license properties written
case "*sysprop.syspropLibrary": // license properties written
default:
@@ -882,17 +910,19 @@
WriteAndroidMkData(w, data)
}
+ if !data.Entries.disabled() {
+ if moduleInfoJSON, ok := SingletonModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
+ *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON)
+ }
+ }
+
return nil
}
// A support func for the deprecated AndroidMkDataProvider interface. Use AndroidMkEntryProvider
// instead.
func WriteAndroidMkData(w io.Writer, data AndroidMkData) {
- if data.Disabled {
- return
- }
-
- if !data.OutputFile.Valid() {
+ if data.Entries.disabled() {
return
}
@@ -907,18 +937,27 @@
fmt.Fprintln(w, "include "+data.Include)
}
-func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, mod blueprint.Module,
- provider AndroidMkEntriesProvider) error {
+func translateAndroidMkEntriesModule(ctx SingletonContext, w io.Writer, moduleInfoJSONs *[]*ModuleInfoJSON,
+ mod blueprint.Module, provider AndroidMkEntriesProvider) error {
if shouldSkipAndroidMkProcessing(mod.(Module).base()) {
return nil
}
+ entriesList := provider.AndroidMkEntries()
+ aconfigUpdateAndroidMkEntries(ctx, mod.(Module), &entriesList)
+
// Any new or special cases here need review to verify correct propagation of license information.
- for _, entries := range provider.AndroidMkEntries() {
+ for _, entries := range entriesList {
entries.fillInEntries(ctx, mod)
entries.write(w)
}
+ if len(entriesList) > 0 && !entriesList[0].disabled() {
+ if moduleInfoJSON, ok := SingletonModuleProvider(ctx, mod, ModuleInfoJSONProvider); ok {
+ *moduleInfoJSONs = append(*moduleInfoJSONs, moduleInfoJSON)
+ }
+ }
+
return nil
}
@@ -956,10 +995,13 @@
// A utility func to format LOCAL_TEST_DATA outputs. See the comments on DataPath to understand how
// to use this func.
-func AndroidMkDataPaths(data []DataPath) []string {
+func androidMkDataPaths(data []DataPath) []string {
var testFiles []string
for _, d := range data {
rel := d.SrcPath.Rel()
+ if d.WithoutRel {
+ rel = d.SrcPath.Base()
+ }
path := d.SrcPath.String()
// LOCAL_TEST_DATA requires the rel portion of the path to be removed from the path.
if !strings.HasSuffix(path, rel) {
diff --git a/android/apex.go b/android/apex.go
index d84499b..4d36a93 100644
--- a/android/apex.go
+++ b/android/apex.go
@@ -89,7 +89,7 @@
TestApexes []string
}
-var ApexInfoProvider = blueprint.NewMutatorProvider(ApexInfo{}, "apex")
+var ApexInfoProvider = blueprint.NewMutatorProvider[ApexInfo]("apex")
func (i ApexInfo) AddJSONData(d *map[string]interface{}) {
(*d)["Apex"] = map[string]interface{}{
@@ -145,7 +145,14 @@
ApexContents []*ApexContents
}
-var ApexTestForInfoProvider = blueprint.NewMutatorProvider(ApexTestForInfo{}, "apex_test_for")
+var ApexTestForInfoProvider = blueprint.NewMutatorProvider[ApexTestForInfo]("apex_test_for")
+
+// ApexBundleInfo contains information about the dependencies of an apex
+type ApexBundleInfo struct {
+ Contents *ApexContents
+}
+
+var ApexBundleInfoProvider = blueprint.NewMutatorProvider[ApexBundleInfo]("apex_info")
// DepIsInSameApex defines an interface that should be used to determine whether a given dependency
// should be considered as part of the same APEX as the current module or not. Note: this was
@@ -482,7 +489,9 @@
}
return InList(what, apex_available) ||
(what != AvailableToPlatform && InList(AvailableToAnyApex, apex_available)) ||
- (strings.HasPrefix(what, "com.android.gki.") && InList(AvailableToGkiApex, apex_available))
+ (strings.HasPrefix(what, "com.android.gki.") && InList(AvailableToGkiApex, apex_available)) ||
+ (what == "com.google.mainline.primary.libs") || // TODO b/248601389
+ (what == "com.google.mainline.go.primary.libs") // TODO b/248601389
}
// Implements ApexModule
@@ -952,3 +961,18 @@
// Return true if the apex bundle is an apex_test
IsTestApex() bool
}
+
+var ApexExportsInfoProvider = blueprint.NewProvider[ApexExportsInfo]()
+
+// ApexExportsInfo contains information about the artifacts provided by apexes to dexpreopt and hiddenapi
+type ApexExportsInfo struct {
+ // Canonical name of this APEX. Used to determine the path to the activated APEX on
+ // device (/apex/<apex_name>)
+ ApexName string
+
+ // Path to the image profile file on host (or empty, if profile is not generated).
+ ProfilePathOnHost Path
+
+ // Map from the apex library name (without prebuilt_ prefix) to the dex file path on host
+ LibraryNameToDexJarPathOnHost map[string]Path
+}
diff --git a/android/apex_contributions.go b/android/apex_contributions.go
new file mode 100644
index 0000000..236abf6
--- /dev/null
+++ b/android/apex_contributions.go
@@ -0,0 +1,173 @@
+// Copyright 2023 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 android
+
+import (
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+func init() {
+ RegisterApexContributionsBuildComponents(InitRegistrationContext)
+}
+
+func RegisterApexContributionsBuildComponents(ctx RegistrationContext) {
+ ctx.RegisterModuleType("apex_contributions", apexContributionsFactory)
+ ctx.RegisterSingletonModuleType("all_apex_contributions", allApexContributionsFactory)
+}
+
+type apexContributions struct {
+ ModuleBase
+ properties contributionProps
+}
+
+type contributionProps struct {
+ // Name of the mainline module
+ Api_domain *string
+ // A list of module names that should be used when this contribution
+ // is selected via product_config
+ // The name should be explicit (foo or prebuilt_foo)
+ Contents []string
+}
+
+func (m *apexContributions) ApiDomain() string {
+ return proptools.String(m.properties.Api_domain)
+}
+
+func (m *apexContributions) Contents() []string {
+ return m.properties.Contents
+}
+
+// apex_contributions contains a list of module names (source or
+// prebuilt) belonging to the mainline module
+// An apex can have multiple apex_contributions modules
+// with different combinations of source or prebuilts, but only one can be
+// selected via product_config.
+func apexContributionsFactory() Module {
+ module := &apexContributions{}
+ module.AddProperties(&module.properties)
+ InitAndroidModule(module)
+ return module
+}
+
+// This module type does not have any build actions.
+// It provides metadata that is used in post-deps mutator phase for source vs
+// prebuilts selection.
+func (m *apexContributions) GenerateAndroidBuildActions(ctx ModuleContext) {
+}
+
+// A container for apex_contributions.
+// Based on product_config, it will create a dependency on the selected
+// apex_contributions per mainline module
+type allApexContributions struct {
+ SingletonModuleBase
+}
+
+func allApexContributionsFactory() SingletonModule {
+ module := &allApexContributions{}
+ InitAndroidModule(module)
+ return module
+}
+
+type apexContributionsDepTag struct {
+ blueprint.BaseDependencyTag
+}
+
+var (
+ acDepTag = apexContributionsDepTag{}
+)
+
+// Creates a dep to each selected apex_contributions
+func (a *allApexContributions) DepsMutator(ctx BottomUpMutatorContext) {
+ ctx.AddDependency(ctx.Module(), acDepTag, ctx.Config().AllApexContributions()...)
+}
+
+// Set PrebuiltSelectionInfoProvider in post deps phase
+func (a *allApexContributions) SetPrebuiltSelectionInfoProvider(ctx BaseModuleContext) {
+ addContentsToProvider := func(p *PrebuiltSelectionInfoMap, m *apexContributions) {
+ for _, content := range m.Contents() {
+ if !ctx.OtherModuleExists(content) && !ctx.Config().AllowMissingDependencies() {
+ ctx.ModuleErrorf("%s listed in apex_contributions %s does not exist\n", content, m.Name())
+ }
+ pi := &PrebuiltSelectionInfo{
+ selectedModuleName: content,
+ metadataModuleName: m.Name(),
+ apiDomain: m.ApiDomain(),
+ }
+ p.Add(ctx, pi)
+ }
+ }
+
+ p := PrebuiltSelectionInfoMap{}
+ ctx.VisitDirectDepsWithTag(acDepTag, func(child Module) {
+ if m, ok := child.(*apexContributions); ok {
+ addContentsToProvider(&p, m)
+ } else {
+ ctx.ModuleErrorf("%s is not an apex_contributions module\n", child.Name())
+ }
+ })
+ SetProvider(ctx, PrebuiltSelectionInfoProvider, p)
+}
+
+// A provider containing metadata about whether source or prebuilt should be used
+// This provider will be used in prebuilt_select mutator to redirect deps
+var PrebuiltSelectionInfoProvider = blueprint.NewMutatorProvider[PrebuiltSelectionInfoMap]("prebuilt_select")
+
+// Map of selected module names to a metadata object
+// The metadata contains information about the api_domain of the selected module
+type PrebuiltSelectionInfoMap map[string]PrebuiltSelectionInfo
+
+// Add a new entry to the map with some validations
+func (pm *PrebuiltSelectionInfoMap) Add(ctx BaseModuleContext, p *PrebuiltSelectionInfo) {
+ if p == nil {
+ return
+ }
+ (*pm)[p.selectedModuleName] = *p
+}
+
+type PrebuiltSelectionInfo struct {
+ // e.g. (libc|prebuilt_libc)
+ selectedModuleName string
+ // Name of the apex_contributions module
+ metadataModuleName string
+ // e.g. com.android.runtime
+ apiDomain string
+}
+
+// Returns true if `name` is explicitly requested using one of the selected
+// apex_contributions metadata modules.
+func (p *PrebuiltSelectionInfoMap) IsSelected(name string) bool {
+ _, exists := (*p)[name]
+ return exists
+}
+
+// Return the list of soong modules selected for this api domain
+// In the case of apexes, it is the canonical name of the apex on device (/apex/<apex_name>)
+func (p *PrebuiltSelectionInfoMap) GetSelectedModulesForApiDomain(apiDomain string) []string {
+ selected := []string{}
+ for _, entry := range *p {
+ if entry.apiDomain == apiDomain {
+ selected = append(selected, entry.selectedModuleName)
+ }
+ }
+ return selected
+}
+
+// This module type does not have any build actions.
+func (a *allApexContributions) GenerateAndroidBuildActions(ctx ModuleContext) {
+}
+
+func (a *allApexContributions) GenerateSingletonBuildActions(ctx SingletonContext) {
+}
diff --git a/android/api_domain.go b/android/api_domain.go
index 587ceae..0a66c3d 100644
--- a/android/api_domain.go
+++ b/android/api_domain.go
@@ -14,20 +14,6 @@
package android
-import (
- "github.com/google/blueprint"
-
- "android/soong/bazel"
-)
-
-func init() {
- RegisterApiDomainBuildComponents(InitRegistrationContext)
-}
-
-func RegisterApiDomainBuildComponents(ctx RegistrationContext) {
- ctx.RegisterModuleType("api_domain", ApiDomainFactory)
-}
-
type ApiSurface int
// TODO(b/246656800): Reconcile with android.SdkKind
@@ -50,81 +36,3 @@
return "invalid"
}
}
-
-type apiDomain struct {
- ModuleBase
- BazelModuleBase
-
- properties apiDomainProperties
-}
-
-type apiDomainProperties struct {
- // cc library contributions (.h files/.map.txt) of this API domain
- // This dependency is a no-op in Soong, but the corresponding Bazel target in the api_bp2build workspace
- // will provide a `CcApiContributionInfo` provider
- Cc_api_contributions []string
-
- // java library contributions (as .txt) of this API domain
- // This dependency is a no-op in Soong, but the corresponding Bazel target in the api_bp2build workspace
- // will provide a `JavaApiContributionInfo` provider
- Java_api_contributions []string
-}
-
-func ApiDomainFactory() Module {
- m := &apiDomain{}
- m.AddProperties(&m.properties)
- InitAndroidArchModule(m, DeviceSupported, MultilibBoth)
- return m
-}
-
-// Do not create any dependency edges in Soong for now to skip visibility checks for some systemapi libraries.
-// Currently, all api_domain modules reside in build/orchestrator/apis/Android.bp
-// However, cc libraries like libsigchain (com.android.art) restrict their visibility to art/*
-// When the api_domain module types are collocated with their contributions, this dependency edge can be restored
-func (a *apiDomain) DepsMutator(ctx BottomUpMutatorContext) {
-}
-
-// API domain does not have any builld actions yet
-func (a *apiDomain) GenerateAndroidBuildActions(ctx ModuleContext) {
-}
-
-const (
- apiContributionSuffix = ".contribution"
-)
-
-// ApiContributionTargetName returns the name of the bp2build target (e.g. cc_api_contribution) of contribution modules (e.g. ndk_library)
-// A suffix is necessary to prevent a name collision with the base target in the same bp2build bazel package
-func ApiContributionTargetName(moduleName string) string {
- return moduleName + apiContributionSuffix
-}
-
-// For each contributing cc_library, format the name to its corresponding contribution bazel target in the bp2build workspace
-func contributionBazelAttributes(ctx TopDownMutatorContext, contributions []string) bazel.LabelListAttribute {
- addSuffix := func(ctx BazelConversionPathContext, module blueprint.Module) string {
- baseLabel := BazelModuleLabel(ctx, module)
- return ApiContributionTargetName(baseLabel)
- }
- bazelLabels := BazelLabelForModuleDepsWithFn(ctx, contributions, addSuffix)
- return bazel.MakeLabelListAttribute(bazelLabels)
-}
-
-type bazelApiDomainAttributes struct {
- Cc_api_contributions bazel.LabelListAttribute
- Java_api_contributions bazel.LabelListAttribute
-}
-
-var _ ApiProvider = (*apiDomain)(nil)
-
-func (a *apiDomain) ConvertWithApiBp2build(ctx TopDownMutatorContext) {
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "api_domain",
- Bzl_load_location: "//build/bazel/rules/apis:api_domain.bzl",
- }
- attrs := &bazelApiDomainAttributes{
- Cc_api_contributions: contributionBazelAttributes(ctx, a.properties.Cc_api_contributions),
- Java_api_contributions: contributionBazelAttributes(ctx, a.properties.Java_api_contributions),
- }
- ctx.CreateBazelTargetModule(props, CommonAttributes{
- Name: ctx.ModuleName(),
- }, attrs)
-}
diff --git a/android/api_levels.go b/android/api_levels.go
index 3f538c0..c019f99 100644
--- a/android/api_levels.go
+++ b/android/api_levels.go
@@ -336,7 +336,7 @@
// ApiLevelFromUser for more details.
func ApiLevelFromUserWithConfig(config Config, raw string) (ApiLevel, error) {
// This logic is replicated in starlark, if changing logic here update starlark code too
- // https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/common/api.bzl;l=42;drc=231c7e8c8038fd478a79eb68aa5b9f5c64e0e061
+ // https://cs.android.com/android/platform/superproject/+/main:build/bazel/rules/common/api.bzl;l=42;drc=231c7e8c8038fd478a79eb68aa5b9f5c64e0e061
if raw == "" {
panic("API level string must be non-empty")
}
@@ -449,7 +449,7 @@
err error
}
// This logic is replicated in starlark, if changing logic here update starlark code too
- // https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/common/api.bzl;l=30;drc=231c7e8c8038fd478a79eb68aa5b9f5c64e0e061
+ // https://cs.android.com/android/platform/superproject/+/main:build/bazel/rules/common/api.bzl;l=30;drc=231c7e8c8038fd478a79eb68aa5b9f5c64e0e061
result := config.Once(finalCodenamesMapKey, func() interface{} {
apiLevelsMap, err := getApiLevelsMapReleasedVersions()
@@ -482,7 +482,7 @@
err error
}
// This logic is replicated in starlark, if changing logic here update starlark code too
- // https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/common/api.bzl;l=23;drc=231c7e8c8038fd478a79eb68aa5b9f5c64e0e061
+ // https://cs.android.com/android/platform/superproject/+/main:build/bazel/rules/common/api.bzl;l=23;drc=231c7e8c8038fd478a79eb68aa5b9f5c64e0e061
result := config.Once(apiLevelsMapKey, func() interface{} {
apiLevelsMap, err := getApiLevelsMapReleasedVersions()
if err == nil {
diff --git a/android/arch.go b/android/arch.go
index 152016c..c39db02 100644
--- a/android/arch.go
+++ b/android/arch.go
@@ -425,7 +425,7 @@
// blueprint.BottomUpMutatorContext because android.BottomUpMutatorContext
// filters out non-Soong modules. Now that we've handled them, create a
// normal android.BottomUpMutatorContext.
- mctx := bottomUpMutatorContextFactory(bpctx, module, false, false)
+ mctx := bottomUpMutatorContextFactory(bpctx, module, false)
base := module.base()
@@ -446,8 +446,10 @@
}
}
+ createCommonOSVariant := base.commonProperties.CreateCommonOSVariant
+
// If there are no supported OSes then disable the module.
- if len(moduleOSList) == 0 {
+ if len(moduleOSList) == 0 && !createCommonOSVariant {
base.Disable()
return
}
@@ -458,7 +460,6 @@
osNames[i] = os.String()
}
- createCommonOSVariant := base.commonProperties.CreateCommonOSVariant
if createCommonOSVariant {
// A CommonOS variant was requested so add it to the list of OS variants to
// create. It needs to be added to the end because it needs to depend on the
@@ -570,7 +571,7 @@
// blueprint.BottomUpMutatorContext because android.BottomUpMutatorContext
// filters out non-Soong modules. Now that we've handled them, create a
// normal android.BottomUpMutatorContext.
- mctx := bottomUpMutatorContextFactory(bpctx, module, false, false)
+ mctx := bottomUpMutatorContextFactory(bpctx, module, false)
base := module.base()
diff --git a/android/arch_list.go b/android/arch_list.go
index ab644a4..f4409a9 100644
--- a/android/arch_list.go
+++ b/android/arch_list.go
@@ -34,6 +34,11 @@
"broadwell",
"goldmont",
"goldmont-plus",
+ // Target arch is goldmont, but without supporting SHA and XSAVES.
+ // This ensures efficient execution on a broad range of Intel/AMD CPUs used
+ // in Chromebooks, including those lacking SHA or XSAVES support.
+ // (e.g. Kaby Lake, Gemini Lake, Alder Lake and AMD Zen series)
+ "goldmont-without-sha-xsaves",
"haswell",
"icelake",
"ivybridge",
@@ -52,6 +57,7 @@
"broadwell",
"goldmont",
"goldmont-plus",
+ "goldmont-without-sha-xsaves",
"haswell",
"icelake",
"ivybridge",
@@ -197,6 +203,15 @@
"popcnt",
"movbe",
},
+ "goldmont-without-sha-xsaves": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "aes_ni",
+ "popcnt",
+ "movbe",
+ },
"haswell": {
"ssse3",
"sse4",
@@ -358,6 +373,14 @@
"aes_ni",
"popcnt",
},
+ "goldmont-without-sha-xsaves": {
+ "ssse3",
+ "sse4",
+ "sse4_1",
+ "sse4_2",
+ "aes_ni",
+ "popcnt",
+ },
"haswell": {
"ssse3",
"sse4",
diff --git a/android/arch_module_context.go b/android/arch_module_context.go
new file mode 100644
index 0000000..3cf4b41
--- /dev/null
+++ b/android/arch_module_context.go
@@ -0,0 +1,83 @@
+// Copyright 2024 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 android
+
+// ArchModuleContext can be embedded in other contexts to provide information about the module set by
+// the archMutator.
+type ArchModuleContext interface {
+ Target() Target
+ TargetPrimary() bool
+
+ // The additional arch specific targets (e.g. 32/64 bit) that this module variant is
+ // responsible for creating.
+ MultiTargets() []Target
+ Arch() Arch
+ Os() OsType
+ Host() bool
+ Device() bool
+ Darwin() bool
+ Windows() bool
+ PrimaryArch() bool
+}
+
+type archModuleContext struct {
+ // TODO: these should eventually go through a (possibly cached) provider like any other configuration instead
+ // of being special cased.
+ os OsType
+ target Target
+ targetPrimary bool
+ multiTargets []Target
+ primaryArch bool
+}
+
+func (a *archModuleContext) Target() Target {
+ return a.target
+}
+
+func (a *archModuleContext) TargetPrimary() bool {
+ return a.targetPrimary
+}
+
+func (a *archModuleContext) MultiTargets() []Target {
+ return a.multiTargets
+}
+
+func (a *archModuleContext) Arch() Arch {
+ return a.target.Arch
+}
+
+func (a *archModuleContext) Os() OsType {
+ return a.os
+}
+
+func (a *archModuleContext) Host() bool {
+ return a.os.Class == Host
+}
+
+func (a *archModuleContext) Device() bool {
+ return a.os.Class == Device
+}
+
+func (a *archModuleContext) Darwin() bool {
+ return a.os == Darwin
+}
+
+func (a *archModuleContext) Windows() bool {
+ return a.os == Windows
+}
+
+func (b *archModuleContext) PrimaryArch() bool {
+ return b.primaryArch
+}
diff --git a/android/base_module_context.go b/android/base_module_context.go
new file mode 100644
index 0000000..b9c1153
--- /dev/null
+++ b/android/base_module_context.go
@@ -0,0 +1,566 @@
+// Copyright 2015 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 android
+
+import (
+ "fmt"
+ "github.com/google/blueprint"
+ "regexp"
+ "strings"
+)
+
+// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
+// a Config instead of an interface{}, and some methods have been wrapped to use an android.Module
+// instead of a blueprint.Module, plus some extra methods that return Android-specific information
+// about the current module.
+type BaseModuleContext interface {
+ ArchModuleContext
+ EarlyModuleContext
+
+ blueprintBaseModuleContext() blueprint.BaseModuleContext
+
+ // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information.
+ // It is intended for use inside the visit functions of Visit* and WalkDeps.
+ OtherModuleName(m blueprint.Module) string
+
+ // OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information.
+ // It is intended for use inside the visit functions of Visit* and WalkDeps.
+ OtherModuleDir(m blueprint.Module) string
+
+ // OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information.
+ // It is intended for use inside the visit functions of Visit* and WalkDeps.
+ OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
+
+ // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
+ // on the module. When called inside a Visit* method with current module being visited, and there are multiple
+ // dependencies on the module being visited, it returns the dependency tag used for the current dependency.
+ OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
+
+ // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
+ // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
+ OtherModuleExists(name string) bool
+
+ // OtherModuleDependencyVariantExists returns true if a module with the
+ // specified name and variant exists. The variant must match the given
+ // variations. It must also match all the non-local variations of the current
+ // module. In other words, it checks for the module that AddVariationDependencies
+ // would add a dependency on with the same arguments.
+ OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool
+
+ // OtherModuleFarDependencyVariantExists returns true if a module with the
+ // specified name and variant exists. The variant must match the given
+ // variations, but not the non-local variations of the current module. In
+ // other words, it checks for the module that AddFarVariationDependencies
+ // would add a dependency on with the same arguments.
+ OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool
+
+ // OtherModuleReverseDependencyVariantExists returns true if a module with the
+ // specified name exists with the same variations as the current module. In
+ // other words, it checks for the module that AddReverseDependency would add a
+ // dependency on with the same argument.
+ OtherModuleReverseDependencyVariantExists(name string) bool
+
+ // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information.
+ // It is intended for use inside the visit functions of Visit* and WalkDeps.
+ OtherModuleType(m blueprint.Module) string
+
+ // otherModuleProvider returns the value for a provider for the given module. If the value is
+ // not set it returns nil and false. The value returned may be a deep copy of the value originally
+ // passed to SetProvider.
+ //
+ // This method shouldn't be used directly, prefer the type-safe android.OtherModuleProvider instead.
+ otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
+
+ // Provider returns the value for a provider for the current module. If the value is
+ // not set it returns nil and false. It panics if called before the appropriate
+ // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep
+ // copy of the value originally passed to SetProvider.
+ //
+ // This method shouldn't be used directly, prefer the type-safe android.ModuleProvider instead.
+ provider(provider blueprint.AnyProviderKey) (any, bool)
+
+ // setProvider sets the value for a provider for the current module. It panics if not called
+ // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
+ // is not of the appropriate type, or if the value has already been set. The value should not
+ // be modified after being passed to SetProvider.
+ //
+ // This method shouldn't be used directly, prefer the type-safe android.SetProvider instead.
+ setProvider(provider blueprint.AnyProviderKey, value any)
+
+ GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
+
+ // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
+ // none exists. It panics if the dependency does not have the specified tag. It skips any
+ // dependencies that are not an android.Module.
+ GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
+
+ // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
+ // name, or nil if none exists. If there are multiple dependencies on the same module it returns
+ // the first DependencyTag.
+ GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
+
+ // VisitDirectDepsBlueprint calls visit for each direct dependency. If there are multiple
+ // direct dependencies on the same module visit will be called multiple times on that module
+ // and OtherModuleDependencyTag will return a different tag for each.
+ //
+ // The Module passed to the visit function should not be retained outside of the visit
+ // function, it may be invalidated by future mutators.
+ VisitDirectDepsBlueprint(visit func(blueprint.Module))
+
+ // VisitDirectDepsIgnoreBlueprint calls visit for each direct dependency. If there are multiple
+ // direct dependencies on the same module visit will be called multiple times on that module
+ // and OtherModuleDependencyTag will return a different tag for each. It silently ignores any
+ // dependencies that are not an android.Module.
+ //
+ // The Module passed to the visit function should not be retained outside of the visit
+ // function, it may be invalidated by future mutators.
+ VisitDirectDepsIgnoreBlueprint(visit func(Module))
+
+ // VisitDirectDeps calls visit for each direct dependency. If there are multiple
+ // direct dependencies on the same module visit will be called multiple times on that module
+ // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
+ // dependencies are not an android.Module.
+ //
+ // The Module passed to the visit function should not be retained outside of the visit
+ // function, it may be invalidated by future mutators.
+ VisitDirectDeps(visit func(Module))
+
+ VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
+
+ // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are
+ // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
+ // OtherModuleDependencyTag will return a different tag for each. It skips any
+ // dependencies that are not an android.Module.
+ //
+ // The Module passed to the visit function should not be retained outside of the visit function, it may be
+ // invalidated by future mutators.
+ VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
+ // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
+ VisitDepsDepthFirst(visit func(Module))
+ // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
+ VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
+
+ // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
+ // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
+ // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
+ // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
+ // any dependencies that are not an android.Module.
+ //
+ // The Modules passed to the visit function should not be retained outside of the visit function, they may be
+ // invalidated by future mutators.
+ WalkDeps(visit func(child, parent Module) bool)
+
+ // WalkDepsBlueprint calls visit for each transitive dependency, traversing the dependency
+ // tree in top down order. visit may be called multiple times for the same (child, parent)
+ // pair if there are multiple direct dependencies between the child and parent with different
+ // tags. OtherModuleDependencyTag will return the tag for the currently visited
+ // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down
+ // to child.
+ //
+ // The Modules passed to the visit function should not be retained outside of the visit function, they may be
+ // invalidated by future mutators.
+ WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool)
+
+ // GetWalkPath is supposed to be called in visit function passed in WalkDeps()
+ // and returns a top-down dependency path from a start module to current child module.
+ GetWalkPath() []Module
+
+ // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in
+ // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
+ // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are
+ // only done once for all variants of a module.
+ PrimaryModule() Module
+
+ // FinalModule returns the last variant of the current module. Variants of a module are always visited in
+ // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
+ // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform
+ // singleton actions that are only done once for all variants of a module.
+ FinalModule() Module
+
+ // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always
+ // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
+ // from all variants if the current module == FinalModule(). Otherwise, care must be taken to not access any
+ // data modified by the current mutator.
+ VisitAllModuleVariants(visit func(Module))
+
+ // GetTagPath is supposed to be called in visit function passed in WalkDeps()
+ // and returns a top-down dependency tags path from a start module to current child module.
+ // It has one less entry than GetWalkPath() as it contains the dependency tags that
+ // exist between each adjacent pair of modules in the GetWalkPath().
+ // GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1]
+ GetTagPath() []blueprint.DependencyTag
+
+ // GetPathString is supposed to be called in visit function passed in WalkDeps()
+ // and returns a multi-line string showing the modules and dependency tags
+ // among them along the top-down dependency path from a start module to current child module.
+ // skipFirst when set to true, the output doesn't include the start module,
+ // which is already printed when this function is used along with ModuleErrorf().
+ GetPathString(skipFirst bool) string
+
+ AddMissingDependencies(missingDeps []string)
+
+ // getMissingDependencies returns the list of missing dependencies.
+ // Calling this function prevents adding new dependencies.
+ getMissingDependencies() []string
+}
+
+type baseModuleContext struct {
+ bp blueprint.BaseModuleContext
+ earlyModuleContext
+ archModuleContext
+
+ walkPath []Module
+ tagPath []blueprint.DependencyTag
+
+ strictVisitDeps bool // If true, enforce that all dependencies are enabled
+
+}
+
+func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
+ return b.bp.OtherModuleName(m)
+}
+func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { return b.bp.OtherModuleDir(m) }
+func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
+ b.bp.OtherModuleErrorf(m, fmt, args...)
+}
+func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
+ return b.bp.OtherModuleDependencyTag(m)
+}
+func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
+func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
+ return b.bp.OtherModuleDependencyVariantExists(variations, name)
+}
+func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool {
+ return b.bp.OtherModuleFarDependencyVariantExists(variations, name)
+}
+func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
+ return b.bp.OtherModuleReverseDependencyVariantExists(name)
+}
+func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
+ return b.bp.OtherModuleType(m)
+}
+
+func (b *baseModuleContext) otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
+ return b.bp.OtherModuleProvider(m, provider)
+}
+
+func (b *baseModuleContext) provider(provider blueprint.AnyProviderKey) (any, bool) {
+ return b.bp.Provider(provider)
+}
+
+func (b *baseModuleContext) setProvider(provider blueprint.AnyProviderKey, value any) {
+ b.bp.SetProvider(provider, value)
+}
+
+func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
+ return b.bp.GetDirectDepWithTag(name, tag)
+}
+
+func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
+ return b.bp
+}
+
+func (b *baseModuleContext) AddMissingDependencies(deps []string) {
+ if deps != nil {
+ missingDeps := &b.Module().base().commonProperties.MissingDeps
+ *missingDeps = append(*missingDeps, deps...)
+ *missingDeps = FirstUniqueStrings(*missingDeps)
+ }
+}
+
+func (b *baseModuleContext) checkedMissingDeps() bool {
+ return b.Module().base().commonProperties.CheckedMissingDeps
+}
+
+func (b *baseModuleContext) getMissingDependencies() []string {
+ checked := &b.Module().base().commonProperties.CheckedMissingDeps
+ *checked = true
+ var missingDeps []string
+ missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...)
+ missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...)
+ missingDeps = FirstUniqueStrings(missingDeps)
+ return missingDeps
+}
+
+type AllowDisabledModuleDependency interface {
+ blueprint.DependencyTag
+ AllowDisabledModuleDependency(target Module) bool
+}
+
+func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool, ignoreBlueprint bool) Module {
+ aModule, _ := module.(Module)
+
+ if !strict {
+ return aModule
+ }
+
+ if aModule == nil {
+ if !ignoreBlueprint {
+ b.ModuleErrorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag)
+ }
+ return nil
+ }
+
+ if !aModule.Enabled() {
+ if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) {
+ if b.Config().AllowMissingDependencies() {
+ b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
+ } else {
+ b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
+ }
+ }
+ return nil
+ }
+ return aModule
+}
+
+type dep struct {
+ mod blueprint.Module
+ tag blueprint.DependencyTag
+}
+
+func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []dep {
+ var deps []dep
+ b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+ if aModule, _ := module.(Module); aModule != nil {
+ if aModule.base().BaseModuleName() == name {
+ returnedTag := b.bp.OtherModuleDependencyTag(aModule)
+ if tag == nil || returnedTag == tag {
+ deps = append(deps, dep{aModule, returnedTag})
+ }
+ }
+ } else if b.bp.OtherModuleName(module) == name {
+ returnedTag := b.bp.OtherModuleDependencyTag(module)
+ if tag == nil || returnedTag == tag {
+ deps = append(deps, dep{module, returnedTag})
+ }
+ }
+ })
+ return deps
+}
+
+func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
+ deps := b.getDirectDepsInternal(name, tag)
+ if len(deps) == 1 {
+ return deps[0].mod, deps[0].tag
+ } else if len(deps) >= 2 {
+ panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
+ name, b.ModuleName()))
+ } else {
+ return nil, nil
+ }
+}
+
+func (b *baseModuleContext) getDirectDepFirstTag(name string) (blueprint.Module, blueprint.DependencyTag) {
+ foundDeps := b.getDirectDepsInternal(name, nil)
+ deps := map[blueprint.Module]bool{}
+ for _, dep := range foundDeps {
+ deps[dep.mod] = true
+ }
+ if len(deps) == 1 {
+ return foundDeps[0].mod, foundDeps[0].tag
+ } else if len(deps) >= 2 {
+ // this could happen if two dependencies have the same name in different namespaces
+ // TODO(b/186554727): this should not occur if namespaces are handled within
+ // getDirectDepsInternal.
+ panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
+ name, b.ModuleName()))
+ } else {
+ return nil, nil
+ }
+}
+
+func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
+ var deps []Module
+ b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
+ if aModule, _ := module.(Module); aModule != nil {
+ if b.bp.OtherModuleDependencyTag(aModule) == tag {
+ deps = append(deps, aModule)
+ }
+ }
+ })
+ return deps
+}
+
+// GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
+// name, or nil if none exists. If there are multiple dependencies on the same module it returns the
+// first DependencyTag.
+func (b *baseModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
+ return b.getDirectDepFirstTag(name)
+}
+
+func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
+ b.bp.VisitDirectDeps(visit)
+}
+
+func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
+ b.visitDirectDeps(visit, false)
+}
+
+func (b *baseModuleContext) VisitDirectDepsIgnoreBlueprint(visit func(Module)) {
+ b.visitDirectDeps(visit, true)
+}
+
+func (b *baseModuleContext) visitDirectDeps(visit func(Module), ignoreBlueprint bool) {
+ b.bp.VisitDirectDeps(func(module blueprint.Module) {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, ignoreBlueprint); aModule != nil {
+ visit(aModule)
+ }
+ })
+}
+
+func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
+ b.bp.VisitDirectDeps(func(module blueprint.Module) {
+ if b.bp.OtherModuleDependencyTag(module) == tag {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
+ visit(aModule)
+ }
+ }
+ })
+}
+
+func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
+ b.bp.VisitDirectDepsIf(
+ // pred
+ func(module blueprint.Module) bool {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
+ return pred(aModule)
+ } else {
+ return false
+ }
+ },
+ // visit
+ func(module blueprint.Module) {
+ visit(module.(Module))
+ })
+}
+
+func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
+ b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
+ visit(aModule)
+ }
+ })
+}
+
+func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
+ b.bp.VisitDepsDepthFirstIf(
+ // pred
+ func(module blueprint.Module) bool {
+ if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps, false); aModule != nil {
+ return pred(aModule)
+ } else {
+ return false
+ }
+ },
+ // visit
+ func(module blueprint.Module) {
+ visit(module.(Module))
+ })
+}
+
+func (b *baseModuleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) {
+ b.bp.WalkDeps(visit)
+}
+
+func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
+ b.walkPath = []Module{b.Module()}
+ b.tagPath = []blueprint.DependencyTag{}
+ b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
+ childAndroidModule, _ := child.(Module)
+ parentAndroidModule, _ := parent.(Module)
+ if childAndroidModule != nil && parentAndroidModule != nil {
+ // record walkPath before visit
+ for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
+ b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
+ b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
+ }
+ b.walkPath = append(b.walkPath, childAndroidModule)
+ b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
+ return visit(childAndroidModule, parentAndroidModule)
+ } else {
+ return false
+ }
+ })
+}
+
+func (b *baseModuleContext) GetWalkPath() []Module {
+ return b.walkPath
+}
+
+func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
+ return b.tagPath
+}
+
+func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
+ b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
+ visit(module.(Module))
+ })
+}
+
+func (b *baseModuleContext) PrimaryModule() Module {
+ return b.bp.PrimaryModule().(Module)
+}
+
+func (b *baseModuleContext) FinalModule() Module {
+ return b.bp.FinalModule().(Module)
+}
+
+// IsMetaDependencyTag returns true for cross-cutting metadata dependencies.
+func IsMetaDependencyTag(tag blueprint.DependencyTag) bool {
+ if tag == licenseKindTag {
+ return true
+ } else if tag == licensesTag {
+ return true
+ } else if tag == acDepTag {
+ return true
+ }
+ return false
+}
+
+// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
+// a dependency tag.
+var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
+
+// PrettyPrintTag returns string representation of the tag, but prefers
+// custom String() method if available.
+func PrettyPrintTag(tag blueprint.DependencyTag) string {
+ // Use tag's custom String() method if available.
+ if stringer, ok := tag.(fmt.Stringer); ok {
+ return stringer.String()
+ }
+
+ // Otherwise, get a default string representation of the tag's struct.
+ tagString := fmt.Sprintf("%T: %+v", tag, tag)
+
+ // Remove the boilerplate from BaseDependencyTag as it adds no value.
+ tagString = tagCleaner.ReplaceAllString(tagString, "")
+ return tagString
+}
+
+func (b *baseModuleContext) GetPathString(skipFirst bool) string {
+ sb := strings.Builder{}
+ tagPath := b.GetTagPath()
+ walkPath := b.GetWalkPath()
+ if !skipFirst {
+ sb.WriteString(walkPath[0].String())
+ }
+ for i, m := range walkPath[1:] {
+ sb.WriteString("\n")
+ sb.WriteString(fmt.Sprintf(" via tag %s\n", PrettyPrintTag(tagPath[i])))
+ sb.WriteString(fmt.Sprintf(" -> %s", m.String()))
+ }
+ return sb.String()
+}
diff --git a/android/bazel.go b/android/bazel.go
deleted file mode 100644
index e764b18..0000000
--- a/android/bazel.go
+++ /dev/null
@@ -1,703 +0,0 @@
-// 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 android
-
-import (
- "bufio"
- "errors"
- "fmt"
- "strings"
-
- "android/soong/ui/metrics/bp2build_metrics_proto"
-
- "github.com/google/blueprint"
- "github.com/google/blueprint/bootstrap"
- "github.com/google/blueprint/proptools"
-
- "android/soong/android/allowlists"
-)
-
-const (
- // A sentinel value to be used as a key in Bp2BuildConfig for modules with
- // no package path. This is also the module dir for top level Android.bp
- // modules.
- Bp2BuildTopLevel = "."
-)
-
-type MixedBuildEnabledStatus int
-
-const (
- // This module can be mixed_built.
- MixedBuildEnabled = iota
-
- // There is a technical incompatibility preventing this module from being
- // bazel-analyzed. Note: the module might also be incompatible.
- TechnicalIncompatibility
-
- // This module cannot be mixed_built due to some incompatibility with it
- // that is not a platform incompatibility. Example: the module-type is not
- // enabled, or is not bp2build-converted.
- ModuleIncompatibility
-
- // Missing dependencies. We can't query Bazel for modules if it has missing dependencies, there
- // will be failures.
- ModuleMissingDeps
-)
-
-// FileGroupAsLibrary describes a filegroup module that is converted to some library
-// such as aidl_library or proto_library.
-type FileGroupAsLibrary interface {
- ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) bool
- ShouldConvertToProtoLibrary(ctx BazelConversionPathContext) bool
- GetAidlLibraryLabel(ctx BazelConversionPathContext) string
- GetProtoLibraryLabel(ctx BazelConversionPathContext) string
-}
-
-type BazelConversionStatus struct {
- // Information about _all_ bp2build targets generated by this module. Multiple targets are
- // supported as Soong handles some things within a single target that we may choose to split into
- // multiple targets, e.g. renderscript, protos, yacc within a cc module.
- Bp2buildInfo []bp2buildInfo `blueprint:"mutated"`
-
- // UnconvertedBp2buildDep stores the module names of direct dependency that were not converted to
- // Bazel
- UnconvertedDeps []string `blueprint:"mutated"`
-
- // MissingBp2buildDep stores the module names of direct dependency that were not found
- MissingDeps []string `blueprint:"mutated"`
-
- // If non-nil, indicates that the module could not be converted successfully
- // with bp2build. This will describe the reason the module could not be converted.
- UnconvertedReason *UnconvertedReason
-}
-
-// The reason a module could not be converted to a BUILD target via bp2build.
-// This should match bp2build_metrics_proto.UnconvertedReason, but omits private
-// proto-related fields that prevent copying this struct.
-type UnconvertedReason struct {
- // Should correspond to a valid value in bp2build_metrics_proto.UnconvertedReasonType.
- // A raw int is used here instead, because blueprint logic requires that all transitive
- // fields of module definitions be primitives.
- ReasonType int
- Detail string
-}
-
-type BazelModuleProperties struct {
- // The label of the Bazel target replacing this Soong module. When run in conversion mode, this
- // will import the handcrafted build target into the autogenerated file. Note: this may result in
- // a conflict due to duplicate targets if bp2build_available is also set.
- Label *string
-
- // If true, bp2build will generate the converted Bazel target for this module. Note: this may
- // cause a conflict due to the duplicate targets if label is also set.
- //
- // This is a bool pointer to support tristates: true, false, not set.
- //
- // To opt in a module, set bazel_module: { bp2build_available: true }
- // To opt out a module, set bazel_module: { bp2build_available: false }
- // To defer the default setting for the directory, do not set the value.
- Bp2build_available *bool
-
- // CanConvertToBazel is set via InitBazelModule to indicate that a module type can be converted to
- // Bazel with Bp2build.
- CanConvertToBazel bool `blueprint:"mutated"`
-}
-
-// Properties contains common module properties for Bazel migration purposes.
-type properties struct {
- // In "Bazel mixed build" mode, this represents the Bazel target replacing
- // this Soong module.
- Bazel_module BazelModuleProperties
-}
-
-// namespacedVariableProperties is a map from a string representing a Soong
-// config variable namespace, like "android" or "vendor_name" to a slice of
-// pointer to a struct containing a single field called Soong_config_variables
-// whose value mirrors the structure in the Blueprint file.
-type namespacedVariableProperties map[string][]interface{}
-
-// BazelModuleBase contains the property structs with metadata for modules which can be converted to
-// Bazel.
-type BazelModuleBase struct {
- bazelProperties properties
-
- // namespacedVariableProperties is used for soong_config_module_type support
- // in bp2build. Soong config modules allow users to set module properties
- // based on custom product variables defined in Android.bp files. These
- // variables are namespaced to prevent clobbering, especially when set from
- // Makefiles.
- namespacedVariableProperties namespacedVariableProperties
-
- // baseModuleType is set when this module was created from a module type
- // defined by a soong_config_module_type. Every soong_config_module_type
- // "wraps" another module type, e.g. a soong_config_module_type can wrap a
- // cc_defaults to a custom_cc_defaults, or cc_binary to a custom_cc_binary.
- // This baseModuleType is set to the wrapped module type.
- baseModuleType string
-}
-
-// Bazelable is specifies the interface for modules that can be converted to Bazel.
-type Bazelable interface {
- bazelProps() *properties
- HasHandcraftedLabel() bool
- HandcraftedLabel() string
- GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string
- ShouldConvertWithBp2build(ctx ShouldConvertWithBazelContext) bool
- shouldConvertWithBp2build(shouldConvertModuleContext, shouldConvertParams) bool
-
- // ConvertWithBp2build either converts the module to a Bazel build target or
- // declares the module as unconvertible (for logging and metrics).
- // Modules must implement this function to be bp2build convertible. The function
- // must either create at least one Bazel target module (using ctx.CreateBazelTargetModule or
- // its related functions), or declare itself unconvertible using ctx.MarkBp2buildUnconvertible.
- ConvertWithBp2build(ctx TopDownMutatorContext)
-
- // namespacedVariableProps is a map from a soong config variable namespace
- // (e.g. acme, android) to a map of interfaces{}, which are really
- // reflect.Struct pointers, representing the value of the
- // soong_config_variables property of a module. The struct pointer is the
- // one with the single member called Soong_config_variables, which itself is
- // a struct containing fields for each supported feature in that namespace.
- //
- // The reason for using a slice of interface{} is to support defaults
- // propagation of the struct pointers.
- namespacedVariableProps() namespacedVariableProperties
- setNamespacedVariableProps(props namespacedVariableProperties)
- BaseModuleType() string
- SetBaseModuleType(baseModuleType string)
-}
-
-// ApiProvider is implemented by modules that contribute to an API surface
-type ApiProvider interface {
- ConvertWithApiBp2build(ctx TopDownMutatorContext)
-}
-
-// MixedBuildBuildable is an interface that module types should implement in order
-// to be "handled by Bazel" in a mixed build.
-type MixedBuildBuildable interface {
- // IsMixedBuildSupported returns true if and only if this module should be
- // "handled by Bazel" in a mixed build.
- // This "escape hatch" allows modules with corner-case scenarios to opt out
- // of being built with Bazel.
- IsMixedBuildSupported(ctx BaseModuleContext) bool
-
- // QueueBazelCall invokes request-queueing functions on the BazelContext
- // so that these requests are handled when Bazel's cquery is invoked.
- QueueBazelCall(ctx BaseModuleContext)
-
- // ProcessBazelQueryResponse uses Bazel information (obtained from the BazelContext)
- // to set module fields and providers to propagate this module's metadata upstream.
- // This effectively "bridges the gap" between Bazel and Soong in a mixed build.
- // Soong modules depending on this module should be oblivious to the fact that
- // this module was handled by Bazel.
- ProcessBazelQueryResponse(ctx ModuleContext)
-}
-
-// BazelModule is a lightweight wrapper interface around Module for Bazel-convertible modules.
-type BazelModule interface {
- Module
- Bazelable
-}
-
-// InitBazelModule is a wrapper function that decorates a BazelModule with Bazel-conversion
-// properties.
-func InitBazelModule(module BazelModule) {
- module.AddProperties(module.bazelProps())
- module.bazelProps().Bazel_module.CanConvertToBazel = true
-}
-
-// bazelProps returns the Bazel properties for the given BazelModuleBase.
-func (b *BazelModuleBase) bazelProps() *properties {
- return &b.bazelProperties
-}
-
-func (b *BazelModuleBase) namespacedVariableProps() namespacedVariableProperties {
- return b.namespacedVariableProperties
-}
-
-func (b *BazelModuleBase) setNamespacedVariableProps(props namespacedVariableProperties) {
- b.namespacedVariableProperties = props
-}
-
-func (b *BazelModuleBase) BaseModuleType() string {
- return b.baseModuleType
-}
-
-func (b *BazelModuleBase) SetBaseModuleType(baseModuleType string) {
- b.baseModuleType = baseModuleType
-}
-
-// HasHandcraftedLabel returns whether this module has a handcrafted Bazel label.
-func (b *BazelModuleBase) HasHandcraftedLabel() bool {
- return b.bazelProperties.Bazel_module.Label != nil
-}
-
-// HandcraftedLabel returns the handcrafted label for this module, or empty string if there is none
-func (b *BazelModuleBase) HandcraftedLabel() string {
- return proptools.String(b.bazelProperties.Bazel_module.Label)
-}
-
-// GetBazelLabel returns the Bazel label for the given BazelModuleBase.
-func (b *BazelModuleBase) GetBazelLabel(ctx BazelConversionPathContext, module blueprint.Module) string {
- if b.HasHandcraftedLabel() {
- return b.HandcraftedLabel()
- }
- if b.ShouldConvertWithBp2build(ctx) {
- return bp2buildModuleLabel(ctx, module)
- }
- panic(fmt.Errorf("requested non-existent label for module %s", module.Name()))
-}
-
-type Bp2BuildConversionAllowlist struct {
- // Configure modules in these directories to enable bp2build_available: true or false by default.
- defaultConfig allowlists.Bp2BuildConfig
-
- // Keep any existing BUILD files (and do not generate new BUILD files) for these directories
- // in the synthetic Bazel workspace.
- keepExistingBuildFile map[string]bool
-
- // Per-module allowlist to always opt modules into both bp2build and Bazel Dev Mode mixed
- // builds. These modules are usually in directories with many other modules that are not ready
- // for conversion.
- //
- // A module can either be in this list or its directory allowlisted entirely
- // in bp2buildDefaultConfig, but not both at the same time.
- moduleAlwaysConvert map[string]bool
-
- // Per-module-type allowlist to always opt modules in to both bp2build and
- // Bazel Dev Mode mixed builds when they have the same type as one listed.
- moduleTypeAlwaysConvert map[string]bool
-
- // Per-module denylist to always opt modules out of bp2build conversion.
- moduleDoNotConvert map[string]bool
-}
-
-// NewBp2BuildAllowlist creates a new, empty Bp2BuildConversionAllowlist
-// which can be populated using builder pattern Set* methods
-func NewBp2BuildAllowlist() Bp2BuildConversionAllowlist {
- return Bp2BuildConversionAllowlist{
- allowlists.Bp2BuildConfig{},
- map[string]bool{},
- map[string]bool{},
- map[string]bool{},
- map[string]bool{},
- }
-}
-
-// SetDefaultConfig copies the entries from defaultConfig into the allowlist
-func (a Bp2BuildConversionAllowlist) SetDefaultConfig(defaultConfig allowlists.Bp2BuildConfig) Bp2BuildConversionAllowlist {
- if a.defaultConfig == nil {
- a.defaultConfig = allowlists.Bp2BuildConfig{}
- }
- for k, v := range defaultConfig {
- a.defaultConfig[k] = v
- }
-
- return a
-}
-
-// SetKeepExistingBuildFile copies the entries from keepExistingBuildFile into the allowlist
-func (a Bp2BuildConversionAllowlist) SetKeepExistingBuildFile(keepExistingBuildFile map[string]bool) Bp2BuildConversionAllowlist {
- if a.keepExistingBuildFile == nil {
- a.keepExistingBuildFile = map[string]bool{}
- }
- for k, v := range keepExistingBuildFile {
- a.keepExistingBuildFile[k] = v
- }
-
- return a
-}
-
-// SetModuleAlwaysConvertList copies the entries from moduleAlwaysConvert into the allowlist
-func (a Bp2BuildConversionAllowlist) SetModuleAlwaysConvertList(moduleAlwaysConvert []string) Bp2BuildConversionAllowlist {
- if a.moduleAlwaysConvert == nil {
- a.moduleAlwaysConvert = map[string]bool{}
- }
- for _, m := range moduleAlwaysConvert {
- a.moduleAlwaysConvert[m] = true
- }
-
- return a
-}
-
-// SetModuleTypeAlwaysConvertList copies the entries from moduleTypeAlwaysConvert into the allowlist
-func (a Bp2BuildConversionAllowlist) SetModuleTypeAlwaysConvertList(moduleTypeAlwaysConvert []string) Bp2BuildConversionAllowlist {
- if a.moduleTypeAlwaysConvert == nil {
- a.moduleTypeAlwaysConvert = map[string]bool{}
- }
- for _, m := range moduleTypeAlwaysConvert {
- a.moduleTypeAlwaysConvert[m] = true
- }
-
- return a
-}
-
-// SetModuleDoNotConvertList copies the entries from moduleDoNotConvert into the allowlist
-func (a Bp2BuildConversionAllowlist) SetModuleDoNotConvertList(moduleDoNotConvert []string) Bp2BuildConversionAllowlist {
- if a.moduleDoNotConvert == nil {
- a.moduleDoNotConvert = map[string]bool{}
- }
- for _, m := range moduleDoNotConvert {
- a.moduleDoNotConvert[m] = true
- }
-
- return a
-}
-
-// ShouldKeepExistingBuildFileForDir returns whether an existing BUILD file should be
-// added to the build symlink forest based on the current global configuration.
-func (a Bp2BuildConversionAllowlist) ShouldKeepExistingBuildFileForDir(dir string) bool {
- if _, ok := a.keepExistingBuildFile[dir]; ok {
- // Exact dir match
- return true
- }
- var i int
- // Check if subtree match
- for {
- j := strings.Index(dir[i:], "/")
- if j == -1 {
- return false //default
- }
- prefix := dir[0 : i+j]
- i = i + j + 1 // skip the "/"
- if recursive, ok := a.keepExistingBuildFile[prefix]; ok && recursive {
- return true
- }
- }
-}
-
-var bp2BuildAllowListKey = NewOnceKey("Bp2BuildAllowlist")
-var bp2buildAllowlist OncePer
-
-func GetBp2BuildAllowList() Bp2BuildConversionAllowlist {
- return bp2buildAllowlist.Once(bp2BuildAllowListKey, func() interface{} {
- return NewBp2BuildAllowlist().SetDefaultConfig(allowlists.Bp2buildDefaultConfig).
- SetKeepExistingBuildFile(allowlists.Bp2buildKeepExistingBuildFile).
- SetModuleAlwaysConvertList(allowlists.Bp2buildModuleAlwaysConvertList).
- SetModuleTypeAlwaysConvertList(allowlists.Bp2buildModuleTypeAlwaysConvertList).
- SetModuleDoNotConvertList(allowlists.Bp2buildModuleDoNotConvertList)
- }).(Bp2BuildConversionAllowlist)
-}
-
-// MixedBuildsEnabled returns a MixedBuildEnabledStatus regarding whether
-// a module is ready to be replaced by a converted or handcrafted Bazel target.
-// As a side effect, calling this method will also log whether this module is
-// mixed build enabled for metrics reporting.
-func MixedBuildsEnabled(ctx BaseModuleContext) MixedBuildEnabledStatus {
- platformIncompatible := isPlatformIncompatible(ctx.Os(), ctx.Arch().ArchType)
- if platformIncompatible {
- ctx.Config().LogMixedBuild(ctx, false)
- return TechnicalIncompatibility
- }
-
- if ctx.Config().AllowMissingDependencies() {
- missingDeps := ctx.getMissingDependencies()
- // If there are missing dependencies, querying Bazel will fail. Soong instead fails at execution
- // time, not loading/analysis. disable mixed builds and fall back to Soong to maintain that
- // behavior.
- if len(missingDeps) > 0 {
- ctx.Config().LogMixedBuild(ctx, false)
- return ModuleMissingDeps
- }
- }
-
- module := ctx.Module()
- apexInfo := ctx.Provider(ApexInfoProvider).(ApexInfo)
- withinApex := !apexInfo.IsForPlatform()
- mixedBuildEnabled := ctx.Config().IsMixedBuildsEnabled() &&
- module.Enabled() &&
- convertedToBazel(ctx, module) &&
- ctx.Config().BazelContext.IsModuleNameAllowed(module.Name(), withinApex)
- ctx.Config().LogMixedBuild(ctx, mixedBuildEnabled)
-
- if mixedBuildEnabled {
- return MixedBuildEnabled
- }
- return ModuleIncompatibility
-}
-
-func isGoModule(module blueprint.Module) bool {
- if _, ok := module.(*bootstrap.GoPackage); ok {
- return true
- }
- if _, ok := module.(*bootstrap.GoBinary); ok {
- return true
- }
- return false
-}
-
-// ConvertedToBazel returns whether this module has been converted (with bp2build or manually) to Bazel.
-func convertedToBazel(ctx BazelConversionContext, module blueprint.Module) bool {
- // Special-case bootstrap_go_package and bootstrap_go_binary
- // These do not implement Bazelable, but have been converted
- if isGoModule(module) {
- return true
- }
- b, ok := module.(Bazelable)
- if !ok {
- return false
- }
-
- return b.HasHandcraftedLabel() || b.shouldConvertWithBp2build(ctx, shouldConvertParams{
- module: module,
- moduleDir: ctx.OtherModuleDir(module),
- moduleName: ctx.OtherModuleName(module),
- moduleType: ctx.OtherModuleType(module),
- })
-}
-
-type ShouldConvertWithBazelContext interface {
- ModuleErrorf(format string, args ...interface{})
- Module() Module
- Config() Config
- ModuleType() string
- ModuleName() string
- ModuleDir() string
-}
-
-// ShouldConvertWithBp2build returns whether the given BazelModuleBase should be converted with bp2build
-func (b *BazelModuleBase) ShouldConvertWithBp2build(ctx ShouldConvertWithBazelContext) bool {
- return b.shouldConvertWithBp2build(ctx, shouldConvertParams{
- module: ctx.Module(),
- moduleDir: ctx.ModuleDir(),
- moduleName: ctx.ModuleName(),
- moduleType: ctx.ModuleType(),
- })
-}
-
-type bazelOtherModuleContext interface {
- ModuleErrorf(format string, args ...interface{})
- Config() Config
- OtherModuleType(m blueprint.Module) string
- OtherModuleName(m blueprint.Module) string
- OtherModuleDir(m blueprint.Module) string
-}
-
-func isPlatformIncompatible(osType OsType, arch ArchType) bool {
- return osType == Windows || // Windows toolchains are not currently supported.
- osType == LinuxBionic || // Linux Bionic toolchains are not currently supported.
- osType == LinuxMusl || // Linux musl toolchains are not currently supported (b/259266326).
- arch == Riscv64 // TODO(b/262192655) Riscv64 toolchains are not currently supported.
-}
-
-type shouldConvertModuleContext interface {
- ModuleErrorf(format string, args ...interface{})
- Config() Config
-}
-
-type shouldConvertParams struct {
- module blueprint.Module
- moduleType string
- moduleDir string
- moduleName string
-}
-
-func (b *BazelModuleBase) shouldConvertWithBp2build(ctx shouldConvertModuleContext, p shouldConvertParams) bool {
- if !b.bazelProps().Bazel_module.CanConvertToBazel {
- return false
- }
-
- module := p.module
-
- propValue := b.bazelProperties.Bazel_module.Bp2build_available
- packagePath := moduleDirWithPossibleOverride(ctx, module, p.moduleDir)
-
- // Modules in unit tests which are enabled in the allowlist by type or name
- // trigger this conditional because unit tests run under the "." package path
- isTestModule := packagePath == Bp2BuildTopLevel && proptools.BoolDefault(propValue, false)
- if isTestModule {
- return true
- }
-
- moduleName := moduleNameWithPossibleOverride(ctx, module, p.moduleName)
- allowlist := ctx.Config().Bp2buildPackageConfig
- moduleNameAllowed := allowlist.moduleAlwaysConvert[moduleName]
- moduleTypeAllowed := allowlist.moduleTypeAlwaysConvert[p.moduleType]
- allowlistConvert := moduleNameAllowed || moduleTypeAllowed
- if moduleNameAllowed && moduleTypeAllowed {
- ctx.ModuleErrorf("A module %q of type %q cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert", moduleName, p.moduleType)
- return false
- }
-
- if allowlist.moduleDoNotConvert[moduleName] {
- if moduleNameAllowed {
- ctx.ModuleErrorf("a module %q cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert", moduleName)
- }
- return false
- }
-
- // This is a tristate value: true, false, or unset.
- if ok, directoryPath := bp2buildDefaultTrueRecursively(packagePath, allowlist.defaultConfig); ok {
- if moduleNameAllowed {
- ctx.ModuleErrorf("A module cannot be in a directory marked Bp2BuildDefaultTrue"+
- " or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: '%s'"+
- " Module: '%s'", directoryPath, moduleName)
- return false
- }
-
- // Allow modules to explicitly opt-out.
- return proptools.BoolDefault(propValue, true)
- }
-
- // Allow modules to explicitly opt-in.
- return proptools.BoolDefault(propValue, allowlistConvert)
-}
-
-// bp2buildDefaultTrueRecursively checks that the package contains a prefix from the
-// set of package prefixes where all modules must be converted. That is, if the
-// package is x/y/z, and the list contains either x, x/y, or x/y/z, this function will
-// return true.
-//
-// However, if the package is x/y, and it matches a Bp2BuildDefaultFalse "x/y" entry
-// exactly, this module will return false early.
-//
-// This function will also return false if the package doesn't match anything in
-// the config.
-//
-// This function will also return the allowlist entry which caused a particular
-// package to be enabled. Since packages can be enabled via a recursive declaration,
-// the path returned will not always be the same as the one provided.
-func bp2buildDefaultTrueRecursively(packagePath string, config allowlists.Bp2BuildConfig) (bool, string) {
- // Check if the package path has an exact match in the config.
- if config[packagePath] == allowlists.Bp2BuildDefaultTrue || config[packagePath] == allowlists.Bp2BuildDefaultTrueRecursively {
- return true, packagePath
- } else if config[packagePath] == allowlists.Bp2BuildDefaultFalse || config[packagePath] == allowlists.Bp2BuildDefaultFalseRecursively {
- return false, packagePath
- }
-
- // If not, check for the config recursively.
- packagePrefix := packagePath
-
- // e.g. for x/y/z, iterate over x/y, then x, taking the most-specific value from the allowlist.
- for strings.Contains(packagePrefix, "/") {
- dirIndex := strings.LastIndex(packagePrefix, "/")
- packagePrefix = packagePrefix[:dirIndex]
- switch value := config[packagePrefix]; value {
- case allowlists.Bp2BuildDefaultTrueRecursively:
- // package contains this prefix and this prefix should convert all modules
- return true, packagePrefix
- case allowlists.Bp2BuildDefaultFalseRecursively:
- //package contains this prefix and this prefix should NOT convert any modules
- return false, packagePrefix
- }
- // Continue to the next part of the package dir.
-
- }
-
- return false, packagePath
-}
-
-func registerBp2buildConversionMutator(ctx RegisterMutatorsContext) {
- ctx.TopDown("bp2build_conversion", bp2buildConversionMutator).Parallel()
-}
-
-func bp2buildConversionMutator(ctx TopDownMutatorContext) {
- if ctx.Config().HasBazelBuildTargetInSource(ctx) {
- // Defer to the BUILD target. Generating an additional target would
- // cause a BUILD file conflict.
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, "")
- return
- }
-
- bModule, ok := ctx.Module().(Bazelable)
- if !ok {
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
- return
- }
- // There may be cases where the target is created by a macro rather than in a BUILD file, those
- // should be captured as well.
- if bModule.HasHandcraftedLabel() {
- // Defer to the BUILD target. Generating an additional target would
- // cause a BUILD file conflict.
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE, "")
- return
- }
- // TODO: b/285631638 - Differentiate between denylisted modules and missing bp2build capabilities.
- if !bModule.shouldConvertWithBp2build(ctx, shouldConvertParams{
- module: ctx.Module(),
- moduleDir: ctx.ModuleDir(),
- moduleName: ctx.ModuleName(),
- moduleType: ctx.ModuleType(),
- }) {
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, "")
- return
- }
- bModule.ConvertWithBp2build(ctx)
-
- if !ctx.Module().base().IsConvertedByBp2build() && ctx.Module().base().GetUnconvertedReason() == nil {
- panic(fmt.Errorf("illegal bp2build invariant: module '%s' was neither converted nor marked unconvertible", ctx.ModuleName()))
- }
-}
-
-func registerApiBp2buildConversionMutator(ctx RegisterMutatorsContext) {
- ctx.TopDown("apiBp2build_conversion", convertWithApiBp2build).Parallel()
-}
-
-// Generate API contribution targets if the Soong module provides APIs
-func convertWithApiBp2build(ctx TopDownMutatorContext) {
- if m, ok := ctx.Module().(ApiProvider); ok {
- m.ConvertWithApiBp2build(ctx)
- }
-}
-
-// GetMainClassInManifest scans the manifest file specified in filepath and returns
-// the value of attribute Main-Class in the manifest file if it exists, or returns error.
-// WARNING: this is for bp2build converters of java_* modules only.
-func GetMainClassInManifest(c Config, filepath string) (string, error) {
- file, err := c.fs.Open(filepath)
- if err != nil {
- return "", err
- }
- defer file.Close()
- scanner := bufio.NewScanner(file)
- for scanner.Scan() {
- line := scanner.Text()
- if strings.HasPrefix(line, "Main-Class:") {
- return strings.TrimSpace(line[len("Main-Class:"):]), nil
- }
- }
-
- return "", errors.New("Main-Class is not found.")
-}
-
-func AttachValidationActions(ctx ModuleContext, outputFilePath Path, validations Paths) ModuleOutPath {
- validatedOutputFilePath := PathForModuleOut(ctx, "validated", outputFilePath.Base())
- ctx.Build(pctx, BuildParams{
- Rule: CpNoPreserveSymlink,
- Description: "run validations " + outputFilePath.Base(),
- Output: validatedOutputFilePath,
- Input: outputFilePath,
- Validations: validations,
- })
- return validatedOutputFilePath
-}
-
-func RunsOn(hostSupported bool, deviceSupported bool, unitTest bool) []string {
- var runsOn []string
-
- if hostSupported && deviceSupported {
- runsOn = []string{"host_without_device", "device"}
- } else if hostSupported {
- if unitTest {
- runsOn = []string{"host_without_device"}
- } else {
- runsOn = []string{"host_with_device"}
- }
- } else if deviceSupported {
- runsOn = []string{"device"}
- }
-
- return runsOn
-}
diff --git a/android/bazel_handler.go b/android/bazel_handler.go
deleted file mode 100644
index 4b98345..0000000
--- a/android/bazel_handler.go
+++ /dev/null
@@ -1,1591 +0,0 @@
-// Copyright 2020 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 android
-
-import (
- "bytes"
- "crypto/sha1"
- "encoding/hex"
- "fmt"
- "os"
- "path"
- "path/filepath"
- "regexp"
- "runtime"
- "sort"
- "strings"
- "sync"
-
- "android/soong/android/allowlists"
- "android/soong/bazel/cquery"
- "android/soong/shared"
- "android/soong/starlark_import"
-
- "github.com/google/blueprint"
- "github.com/google/blueprint/metrics"
-
- "android/soong/bazel"
-)
-
-var (
- _ = pctx.HostBinToolVariable("bazelBuildRunfilesTool", "build-runfiles")
- buildRunfilesRule = pctx.AndroidStaticRule("bazelBuildRunfiles", blueprint.RuleParams{
- Command: "${bazelBuildRunfilesTool} ${in} ${outDir}",
- Depfile: "",
- Description: "",
- CommandDeps: []string{"${bazelBuildRunfilesTool}"},
- }, "outDir")
-)
-
-func registerMixedBuildsMutator(ctx RegisterMutatorsContext) {
- ctx.BottomUp("mixed_builds_prep", mixedBuildsPrepareMutator).Parallel()
-}
-
-func RegisterMixedBuildsMutator(ctx RegistrationContext) {
- ctx.FinalDepsMutators(registerMixedBuildsMutator)
-}
-
-func mixedBuildsPrepareMutator(ctx BottomUpMutatorContext) {
- if m := ctx.Module(); m.Enabled() {
- if mixedBuildMod, ok := m.(MixedBuildBuildable); ok {
- mixedBuildEnabled := MixedBuildsEnabled(ctx)
- queueMixedBuild := mixedBuildMod.IsMixedBuildSupported(ctx) && mixedBuildEnabled == MixedBuildEnabled
- if queueMixedBuild {
- mixedBuildMod.QueueBazelCall(ctx)
- }
- }
- }
-}
-
-type cqueryRequest interface {
- // Name returns a string name for this request type. Such request type names must be unique,
- // and must only consist of alphanumeric characters.
- Name() string
-
- // StarlarkFunctionBody returns a starlark function body to process this request type.
- // The returned string is the body of a Starlark function which obtains
- // all request-relevant information about a target and returns a string containing
- // this information.
- // The function should have the following properties:
- // - The arguments are `target` (a configured target) and `id_string` (the label + configuration).
- // - The return value must be a string.
- // - The function body should not be indented outside of its own scope.
- StarlarkFunctionBody() string
-}
-
-// Portion of cquery map key to describe target configuration.
-type configKey struct {
- arch string
- osType OsType
- apexKey ApexConfigKey
-}
-
-type ApexConfigKey struct {
- WithinApex bool
- ApexSdkVersion string
- ApiDomain string
-}
-
-func (c ApexConfigKey) String() string {
- return fmt.Sprintf("%s_%s_%s", withinApexToString(c.WithinApex), c.ApexSdkVersion, c.ApiDomain)
-}
-
-func withinApexToString(withinApex bool) string {
- if withinApex {
- return "within_apex"
- }
- return ""
-}
-
-func (c configKey) String() string {
- return fmt.Sprintf("%s::%s::%s", c.arch, c.osType, c.apexKey)
-}
-
-// Map key to describe bazel cquery requests.
-type cqueryKey struct {
- label string
- requestType cqueryRequest
- configKey configKey
-}
-
-func makeCqueryKey(label string, cqueryRequest cqueryRequest, cfgKey configKey) cqueryKey {
- if strings.HasPrefix(label, "//") {
- // Normalize Bazel labels to specify main repository explicitly.
- label = "@" + label
- }
- return cqueryKey{label, cqueryRequest, cfgKey}
-}
-
-func (c cqueryKey) String() string {
- return fmt.Sprintf("cquery(%s,%s,%s)", c.label, c.requestType.Name(), c.configKey)
-}
-
-type invokeBazelContext interface {
- GetEventHandler() *metrics.EventHandler
-}
-
-// BazelContext is a context object useful for interacting with Bazel during
-// the course of a build. Use of Bazel to evaluate part of the build graph
-// is referred to as a "mixed build". (Some modules are managed by Soong,
-// some are managed by Bazel). To facilitate interop between these build
-// subgraphs, Soong may make requests to Bazel and evaluate their responses
-// so that Soong modules may accurately depend on Bazel targets.
-type BazelContext interface {
- // Add a cquery request to the bazel request queue. All queued requests
- // will be sent to Bazel on a subsequent invocation of InvokeBazel.
- QueueBazelRequest(label string, requestType cqueryRequest, cfgKey configKey)
-
- // ** Cquery Results Retrieval Functions
- // The below functions pertain to retrieving cquery results from a prior
- // InvokeBazel function call and parsing the results.
-
- // Returns result files built by building the given bazel target label.
- GetOutputFiles(label string, cfgKey configKey) ([]string, error)
-
- // Returns the results of GetOutputFiles and GetCcObjectFiles in a single query (in that order).
- GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, error)
-
- // Returns the results of the GetApexInfo query (including output files)
- GetApexInfo(label string, cfgkey configKey) (cquery.ApexInfo, error)
-
- // Returns the results of the GetCcUnstrippedInfo query
- GetCcUnstrippedInfo(label string, cfgkey configKey) (cquery.CcUnstrippedInfo, error)
-
- // Returns the results of the GetPrebuiltFileInfo query
- GetPrebuiltFileInfo(label string, cfgKey configKey) (cquery.PrebuiltFileInfo, error)
-
- // ** end Cquery Results Retrieval Functions
-
- // Issues commands to Bazel to receive results for all cquery requests
- // queued in the BazelContext. The ctx argument is optional and is only
- // used for performance data collection
- InvokeBazel(config Config, ctx invokeBazelContext) error
-
- // Returns true if Bazel handling is enabled for the module with the given name.
- // Note that this only implies "bazel mixed build" allowlisting. The caller
- // should independently verify the module is eligible for Bazel handling
- // (for example, that it is MixedBuildBuildable).
- IsModuleNameAllowed(moduleName string, withinApex bool) bool
-
- // Returns the bazel output base (the root directory for all bazel intermediate outputs).
- OutputBase() string
-
- // Returns build statements which should get registered to reflect Bazel's outputs.
- BuildStatementsToRegister() []*bazel.BuildStatement
-
- // Returns the depsets defined in Bazel's aquery response.
- AqueryDepsets() []bazel.AqueryDepset
-
- QueueBazelSandwichCqueryRequests(config Config) error
-}
-
-type bazelRunner interface {
- issueBazelCommand(cmdRequest bazel.CmdRequest, paths *bazelPaths, eventHandler *metrics.EventHandler) (output string, errorMessage string, error error)
-}
-
-type bazelPaths struct {
- homeDir string
- bazelPath string
- outputBase string
- workspaceDir string
- soongOutDir string
- metricsDir string
- bazelDepsFile string
-}
-
-// A context object which tracks queued requests that need to be made to Bazel,
-// and their results after the requests have been made.
-type mixedBuildBazelContext struct {
- bazelRunner
- paths *bazelPaths
- // cquery requests that have not yet been issued to Bazel. This list is maintained
- // in a sorted state, and is guaranteed to have no duplicates.
- requests []cqueryKey
- requestMutex sync.Mutex // requests can be written in parallel
-
- results map[cqueryKey]string // Results of cquery requests after Bazel invocations
-
- // Build statements which should get registered to reflect Bazel's outputs.
- buildStatements []*bazel.BuildStatement
-
- // Depsets which should be used for Bazel's build statements.
- depsets []bazel.AqueryDepset
-
- // Per-module allowlist/denylist functionality to control whether analysis of
- // modules are handled by Bazel. For modules which do not have a Bazel definition
- // (or do not sufficiently support bazel handling via MixedBuildBuildable),
- // this allowlist will have no effect, even if the module is explicitly allowlisted here.
- // Per-module denylist to opt modules out of bazel handling.
- bazelDisabledModules map[string]bool
- // Per-module allowlist to opt modules in to bazel handling.
- bazelEnabledModules map[string]bool
- // DCLA modules are enabled when used in apex.
- bazelDclaEnabledModules map[string]bool
-
- targetProduct string
- targetBuildVariant string
-}
-
-var _ BazelContext = &mixedBuildBazelContext{}
-
-// A bazel context to use when Bazel is disabled.
-type noopBazelContext struct{}
-
-var _ BazelContext = noopBazelContext{}
-
-// A bazel context to use for tests.
-type MockBazelContext struct {
- OutputBaseDir string
-
- LabelToOutputFiles map[string][]string
- LabelToCcInfo map[string]cquery.CcInfo
- LabelToPythonBinary map[string]string
- LabelToApexInfo map[string]cquery.ApexInfo
- LabelToCcBinary map[string]cquery.CcUnstrippedInfo
- LabelToPrebuiltFileInfo map[string]cquery.PrebuiltFileInfo
-
- BazelRequests map[string]bool
-}
-
-func (m MockBazelContext) QueueBazelRequest(label string, requestType cqueryRequest, cfgKey configKey) {
- key := BuildMockBazelContextRequestKey(label, requestType, cfgKey.arch, cfgKey.osType, cfgKey.apexKey)
- if m.BazelRequests == nil {
- m.BazelRequests = make(map[string]bool)
- }
- m.BazelRequests[key] = true
-}
-
-func (m MockBazelContext) QueueBazelSandwichCqueryRequests(config Config) error {
- panic("unimplemented")
-}
-
-func (m MockBazelContext) GetOutputFiles(label string, _ configKey) ([]string, error) {
- result, ok := m.LabelToOutputFiles[label]
- if !ok {
- return []string{}, fmt.Errorf("no target with label %q in LabelToOutputFiles", label)
- }
- return result, nil
-}
-
-func (m MockBazelContext) GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, error) {
- result, ok := m.LabelToCcInfo[label]
- if !ok {
- key := BuildMockBazelContextResultKey(label, cfgKey.arch, cfgKey.osType, cfgKey.apexKey)
- result, ok = m.LabelToCcInfo[key]
- if !ok {
- return cquery.CcInfo{}, fmt.Errorf("no target with label %q in LabelToCcInfo", label)
- }
- }
- return result, nil
-}
-
-func (m MockBazelContext) GetApexInfo(label string, _ configKey) (cquery.ApexInfo, error) {
- result, ok := m.LabelToApexInfo[label]
- if !ok {
- return cquery.ApexInfo{}, fmt.Errorf("no target with label %q in LabelToApexInfo", label)
- }
- return result, nil
-}
-
-func (m MockBazelContext) GetCcUnstrippedInfo(label string, _ configKey) (cquery.CcUnstrippedInfo, error) {
- result, ok := m.LabelToCcBinary[label]
- if !ok {
- return cquery.CcUnstrippedInfo{}, fmt.Errorf("no target with label %q in LabelToCcBinary", label)
- }
- return result, nil
-}
-
-func (m MockBazelContext) GetPrebuiltFileInfo(label string, _ configKey) (cquery.PrebuiltFileInfo, error) {
- result, ok := m.LabelToPrebuiltFileInfo[label]
- if !ok {
- return cquery.PrebuiltFileInfo{}, fmt.Errorf("no target with label %q in LabelToPrebuiltFileInfo", label)
- }
- return result, nil
-}
-
-func (m MockBazelContext) InvokeBazel(_ Config, _ invokeBazelContext) error {
- panic("unimplemented")
-}
-
-func (m MockBazelContext) IsModuleNameAllowed(_ string, _ bool) bool {
- return true
-}
-
-func (m MockBazelContext) OutputBase() string { return m.OutputBaseDir }
-
-func (m MockBazelContext) BuildStatementsToRegister() []*bazel.BuildStatement {
- return []*bazel.BuildStatement{}
-}
-
-func (m MockBazelContext) AqueryDepsets() []bazel.AqueryDepset {
- return []bazel.AqueryDepset{}
-}
-
-var _ BazelContext = MockBazelContext{}
-
-func BuildMockBazelContextRequestKey(label string, request cqueryRequest, arch string, osType OsType, apexKey ApexConfigKey) string {
- cfgKey := configKey{
- arch: arch,
- osType: osType,
- apexKey: apexKey,
- }
-
- return strings.Join([]string{label, request.Name(), cfgKey.String()}, "_")
-}
-
-func BuildMockBazelContextResultKey(label string, arch string, osType OsType, apexKey ApexConfigKey) string {
- cfgKey := configKey{
- arch: arch,
- osType: osType,
- apexKey: apexKey,
- }
-
- return strings.Join([]string{label, cfgKey.String()}, "_")
-}
-
-func (bazelCtx *mixedBuildBazelContext) QueueBazelRequest(label string, requestType cqueryRequest, cfgKey configKey) {
- key := makeCqueryKey(label, requestType, cfgKey)
- bazelCtx.requestMutex.Lock()
- defer bazelCtx.requestMutex.Unlock()
-
- // Insert key into requests, maintaining the sort, and only if it's not duplicate.
- keyString := key.String()
- foundEqual := false
- notLessThanKeyString := func(i int) bool {
- s := bazelCtx.requests[i].String()
- v := strings.Compare(s, keyString)
- if v == 0 {
- foundEqual = true
- }
- return v >= 0
- }
- targetIndex := sort.Search(len(bazelCtx.requests), notLessThanKeyString)
- if foundEqual {
- return
- }
-
- if targetIndex == len(bazelCtx.requests) {
- bazelCtx.requests = append(bazelCtx.requests, key)
- } else {
- bazelCtx.requests = append(bazelCtx.requests[:targetIndex+1], bazelCtx.requests[targetIndex:]...)
- bazelCtx.requests[targetIndex] = key
- }
-}
-
-func (bazelCtx *mixedBuildBazelContext) GetOutputFiles(label string, cfgKey configKey) ([]string, error) {
- key := makeCqueryKey(label, cquery.GetOutputFiles, cfgKey)
- if rawString, ok := bazelCtx.results[key]; ok {
- bazelOutput := strings.TrimSpace(rawString)
-
- return cquery.GetOutputFiles.ParseResult(bazelOutput), nil
- }
- return nil, fmt.Errorf("no bazel response found for %v", key)
-}
-
-func (bazelCtx *mixedBuildBazelContext) GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, error) {
- key := makeCqueryKey(label, cquery.GetCcInfo, cfgKey)
- if rawString, ok := bazelCtx.results[key]; ok {
- bazelOutput := strings.TrimSpace(rawString)
- return cquery.GetCcInfo.ParseResult(bazelOutput)
- }
- return cquery.CcInfo{}, fmt.Errorf("no bazel response found for %v", key)
-}
-
-func (bazelCtx *mixedBuildBazelContext) GetApexInfo(label string, cfgKey configKey) (cquery.ApexInfo, error) {
- key := makeCqueryKey(label, cquery.GetApexInfo, cfgKey)
- if rawString, ok := bazelCtx.results[key]; ok {
- return cquery.GetApexInfo.ParseResult(strings.TrimSpace(rawString))
- }
- return cquery.ApexInfo{}, fmt.Errorf("no bazel response found for %v", key)
-}
-
-func (bazelCtx *mixedBuildBazelContext) GetCcUnstrippedInfo(label string, cfgKey configKey) (cquery.CcUnstrippedInfo, error) {
- key := makeCqueryKey(label, cquery.GetCcUnstrippedInfo, cfgKey)
- if rawString, ok := bazelCtx.results[key]; ok {
- return cquery.GetCcUnstrippedInfo.ParseResult(strings.TrimSpace(rawString))
- }
- return cquery.CcUnstrippedInfo{}, fmt.Errorf("no bazel response for %s", key)
-}
-
-func (bazelCtx *mixedBuildBazelContext) GetPrebuiltFileInfo(label string, cfgKey configKey) (cquery.PrebuiltFileInfo, error) {
- key := makeCqueryKey(label, cquery.GetPrebuiltFileInfo, cfgKey)
- if rawString, ok := bazelCtx.results[key]; ok {
- return cquery.GetPrebuiltFileInfo.ParseResult(strings.TrimSpace(rawString))
- }
- return cquery.PrebuiltFileInfo{}, fmt.Errorf("no bazel response for %s", key)
-}
-
-func (n noopBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
- panic("unimplemented")
-}
-
-func (n noopBazelContext) QueueBazelSandwichCqueryRequests(config Config) error {
- panic("unimplemented")
-}
-
-func (n noopBazelContext) GetOutputFiles(_ string, _ configKey) ([]string, error) {
- panic("unimplemented")
-}
-
-func (n noopBazelContext) GetCcInfo(_ string, _ configKey) (cquery.CcInfo, error) {
- panic("unimplemented")
-}
-
-func (n noopBazelContext) GetApexInfo(_ string, _ configKey) (cquery.ApexInfo, error) {
- panic("unimplemented")
-}
-
-func (n noopBazelContext) GetCcUnstrippedInfo(_ string, _ configKey) (cquery.CcUnstrippedInfo, error) {
- //TODO implement me
- panic("implement me")
-}
-
-func (n noopBazelContext) GetPrebuiltFileInfo(_ string, _ configKey) (cquery.PrebuiltFileInfo, error) {
- panic("implement me")
-}
-
-func (n noopBazelContext) InvokeBazel(_ Config, _ invokeBazelContext) error {
- panic("unimplemented")
-}
-
-func (m noopBazelContext) OutputBase() string {
- return ""
-}
-
-func (n noopBazelContext) IsModuleNameAllowed(_ string, _ bool) bool {
- return false
-}
-
-func (m noopBazelContext) BuildStatementsToRegister() []*bazel.BuildStatement {
- return []*bazel.BuildStatement{}
-}
-
-func (m noopBazelContext) AqueryDepsets() []bazel.AqueryDepset {
- return []bazel.AqueryDepset{}
-}
-
-func AddToStringSet(set map[string]bool, items []string) {
- for _, item := range items {
- set[item] = true
- }
-}
-
-func GetBazelEnabledAndDisabledModules(buildMode SoongBuildMode, forceEnabled map[string]struct{}) (map[string]bool, map[string]bool) {
- disabledModules := map[string]bool{}
- enabledModules := map[string]bool{}
-
- switch buildMode {
- case BazelProdMode:
- AddToStringSet(enabledModules, allowlists.ProdMixedBuildsEnabledList)
- for enabledAdHocModule := range forceEnabled {
- enabledModules[enabledAdHocModule] = true
- }
- case BazelStagingMode:
- // Staging mode includes all prod modules plus all staging modules.
- AddToStringSet(enabledModules, allowlists.ProdMixedBuildsEnabledList)
- AddToStringSet(enabledModules, allowlists.StagingMixedBuildsEnabledList)
- for enabledAdHocModule := range forceEnabled {
- enabledModules[enabledAdHocModule] = true
- }
- default:
- panic("Expected BazelProdMode or BazelStagingMode")
- }
- return enabledModules, disabledModules
-}
-
-func GetBazelEnabledModules(buildMode SoongBuildMode) []string {
- enabledModules, disabledModules := GetBazelEnabledAndDisabledModules(buildMode, nil)
- enabledList := make([]string, 0, len(enabledModules))
- for module := range enabledModules {
- if !disabledModules[module] {
- enabledList = append(enabledList, module)
- }
- }
- sort.Strings(enabledList)
- return enabledList
-}
-
-func NewBazelContext(c *config) (BazelContext, error) {
- if c.BuildMode != BazelProdMode && c.BuildMode != BazelStagingMode {
- return noopBazelContext{}, nil
- }
-
- enabledModules, disabledModules := GetBazelEnabledAndDisabledModules(c.BuildMode, c.BazelModulesForceEnabledByFlag())
-
- paths := bazelPaths{
- soongOutDir: c.soongOutDir,
- }
- var missing []string
- vars := []struct {
- name string
- ptr *string
-
- // True if the environment variable needs to be tracked so that changes to the variable
- // cause the ninja file to be regenerated, false otherwise. False should only be set for
- // environment variables that have no effect on the generated ninja file.
- track bool
- }{
- {"BAZEL_HOME", &paths.homeDir, true},
- {"BAZEL_PATH", &paths.bazelPath, true},
- {"BAZEL_OUTPUT_BASE", &paths.outputBase, true},
- {"BAZEL_WORKSPACE", &paths.workspaceDir, true},
- {"BAZEL_METRICS_DIR", &paths.metricsDir, false},
- {"BAZEL_DEPS_FILE", &paths.bazelDepsFile, true},
- }
- for _, v := range vars {
- if v.track {
- if s := c.Getenv(v.name); len(s) > 1 {
- *v.ptr = s
- continue
- }
- } else if s, ok := c.env[v.name]; ok {
- *v.ptr = s
- } else {
- missing = append(missing, v.name)
- }
- }
- if len(missing) > 0 {
- return nil, fmt.Errorf("missing required env vars to use bazel: %s", missing)
- }
-
- targetBuildVariant := "user"
- if c.Eng() {
- targetBuildVariant = "eng"
- } else if c.Debuggable() {
- targetBuildVariant = "userdebug"
- }
- targetProduct := "unknown"
- if c.HasDeviceProduct() {
- targetProduct = c.DeviceProduct()
- }
- dclaMixedBuildsEnabledList := []string{}
- if c.BuildMode == BazelProdMode {
- dclaMixedBuildsEnabledList = allowlists.ProdDclaMixedBuildsEnabledList
- } else if c.BuildMode == BazelStagingMode {
- dclaMixedBuildsEnabledList = append(allowlists.ProdDclaMixedBuildsEnabledList,
- allowlists.StagingDclaMixedBuildsEnabledList...)
- }
- dclaEnabledModules := map[string]bool{}
- AddToStringSet(dclaEnabledModules, dclaMixedBuildsEnabledList)
- return &mixedBuildBazelContext{
- bazelRunner: &builtinBazelRunner{c.UseBazelProxy, absolutePath(c.outDir)},
- paths: &paths,
- bazelEnabledModules: enabledModules,
- bazelDisabledModules: disabledModules,
- bazelDclaEnabledModules: dclaEnabledModules,
- targetProduct: targetProduct,
- targetBuildVariant: targetBuildVariant,
- }, nil
-}
-
-func (p *bazelPaths) BazelMetricsDir() string {
- return p.metricsDir
-}
-
-func (context *mixedBuildBazelContext) IsModuleNameAllowed(moduleName string, withinApex bool) bool {
- if context.bazelDisabledModules[moduleName] {
- return false
- }
- if context.bazelEnabledModules[moduleName] {
- return true
- }
- if withinApex && context.bazelDclaEnabledModules[moduleName] {
- return true
- }
-
- return false
-}
-
-func pwdPrefix() string {
- // Darwin doesn't have /proc
- if runtime.GOOS != "darwin" {
- return "PWD=/proc/self/cwd"
- }
- return ""
-}
-
-type bazelCommand struct {
- command string
- // query or label
- expression string
-}
-
-type builtinBazelRunner struct {
- useBazelProxy bool
- outDir string
-}
-
-// Issues the given bazel command with given build label and additional flags.
-// Returns (stdout, stderr, error). The first and second return values are strings
-// containing the stdout and stderr of the run command, and an error is returned if
-// the invocation returned an error code.
-func (r *builtinBazelRunner) issueBazelCommand(cmdRequest bazel.CmdRequest, paths *bazelPaths, eventHandler *metrics.EventHandler) (string, string, error) {
- if r.useBazelProxy {
- eventHandler.Begin("client_proxy")
- defer eventHandler.End("client_proxy")
- proxyClient := bazel.NewProxyClient(r.outDir)
- resp, err := proxyClient.IssueCommand(cmdRequest)
-
- if err != nil {
- return "", "", err
- }
- if len(resp.ErrorString) > 0 {
- return "", "", fmt.Errorf(resp.ErrorString)
- }
- return resp.Stdout, resp.Stderr, nil
- } else {
- eventHandler.Begin("bazel command")
- defer eventHandler.End("bazel command")
-
- stdout, stderr, err := bazel.ExecBazel(paths.bazelPath, absolutePath(paths.syntheticWorkspaceDir()), cmdRequest)
- return string(stdout), string(stderr), err
- }
-}
-
-func (context *mixedBuildBazelContext) createBazelCommand(config Config, runName bazel.RunName, command bazelCommand,
- extraFlags ...string) bazel.CmdRequest {
- if runtime.GOOS != "linux" && runtime.GOOS != "darwin" {
- panic("Unknown GOOS: " + runtime.GOOS)
- }
- cmdFlags := []string{
- "--output_base=" + absolutePath(context.paths.outputBase),
- command.command,
- command.expression,
- "--profile=" + shared.BazelMetricsFilename(context.paths, runName),
-
- "--host_platform=@soong_injection//product_config_platforms:mixed_builds_product-" + context.targetBuildVariant + "_" + runtime.GOOS + "_x86_64",
- // Don't specify --platforms, because on some products/branches (like kernel-build-tools)
- // the main platform for mixed_builds_product-variant doesn't exist because an arch isn't
- // specified in product config. The derivative platforms that config_node transitions into
- // will still work.
-
- // Suppress noise
- "--ui_event_filters=-INFO",
- "--noshow_progress",
- "--norun_validations",
- }
- cmdFlags = append(cmdFlags, extraFlags...)
-
- extraEnv := []string{
- "HOME=" + context.paths.homeDir,
- pwdPrefix(),
- "BUILD_DIR=" + absolutePath(context.paths.soongOutDir),
- // Make OUT_DIR absolute here so build/bazel/bin/bazel uses the correct
- // OUT_DIR at <root>/out, instead of <root>/out/soong/workspace/out.
- "OUT_DIR=" + absolutePath(context.paths.outDir()),
- // Disables local host detection of gcc; toolchain information is defined
- // explicitly in BUILD files.
- "BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1",
- }
- capturedEnvVars, err := starlark_import.GetStarlarkValue[[]string]("captured_env_vars")
- if err != nil {
- panic(err)
- }
- for _, envvar := range capturedEnvVars {
- val := config.Getenv(envvar)
- if val == "" {
- continue
- }
- extraEnv = append(extraEnv, fmt.Sprintf("%s=%s", envvar, val))
- }
- envVars := append(os.Environ(), extraEnv...)
-
- return bazel.CmdRequest{cmdFlags, envVars}
-}
-
-func (context *mixedBuildBazelContext) printableCqueryCommand(bazelCmd bazel.CmdRequest) string {
- args := append([]string{context.paths.bazelPath}, bazelCmd.Argv...)
- outputString := strings.Join(bazelCmd.Env, " ") + " \"" + strings.Join(args, "\" \"") + "\""
- return outputString
-}
-
-func (context *mixedBuildBazelContext) mainBzlFileContents() []byte {
- // TODO(cparsons): Define configuration transitions programmatically based
- // on available archs.
- contents := `
-#####################################################
-# This file is generated by soong_build. Do not edit.
-#####################################################
-def _config_node_transition_impl(settings, attr):
- if attr.os == "android" and attr.arch == "target":
- target = "mixed_builds_product-{VARIANT}"
- else:
- target = "mixed_builds_product-{VARIANT}_%s_%s" % (attr.os, attr.arch)
- apex_name = ""
- if attr.within_apex:
- # //build/bazel/rules/apex:apex_name has to be set to a non_empty value,
- # otherwise //build/bazel/rules/apex:non_apex will be true and the
- # "-D__ANDROID_APEX__" compiler flag will be missing. Apex_name is used
- # in some validation on bazel side which don't really apply in mixed
- # build because soong will do the work, so we just set it to a fixed
- # value here.
- apex_name = "dcla_apex"
- outputs = {
- "//command_line_option:platforms": "@soong_injection//product_config_platforms:%s" % target,
- "@//build/bazel/rules/apex:within_apex": attr.within_apex,
- "@//build/bazel/rules/apex:min_sdk_version": attr.apex_sdk_version,
- "@//build/bazel/rules/apex:apex_name": apex_name,
- "@//build/bazel/rules/apex:api_domain": attr.api_domain,
- }
-
- return outputs
-
-_config_node_transition = transition(
- implementation = _config_node_transition_impl,
- inputs = [],
- outputs = [
- "//command_line_option:platforms",
- "@//build/bazel/rules/apex:within_apex",
- "@//build/bazel/rules/apex:min_sdk_version",
- "@//build/bazel/rules/apex:apex_name",
- "@//build/bazel/rules/apex:api_domain",
- ],
-)
-
-def _passthrough_rule_impl(ctx):
- return [DefaultInfo(files = depset(ctx.files.deps))]
-
-config_node = rule(
- implementation = _passthrough_rule_impl,
- attrs = {
- "arch" : attr.string(mandatory = True),
- "os" : attr.string(mandatory = True),
- "within_apex" : attr.bool(default = False),
- "apex_sdk_version" : attr.string(mandatory = True),
- "api_domain" : attr.string(mandatory = True),
- "deps" : attr.label_list(cfg = _config_node_transition, allow_files = True),
- "_allowlist_function_transition": attr.label(default = "@bazel_tools//tools/allowlists/function_transition_allowlist"),
- },
-)
-
-
-# Rule representing the root of the build, to depend on all Bazel targets that
-# are required for the build. Building this target will build the entire Bazel
-# build tree.
-mixed_build_root = rule(
- implementation = _passthrough_rule_impl,
- attrs = {
- "deps" : attr.label_list(),
- },
-)
-
-def _phony_root_impl(ctx):
- return []
-
-# Rule to depend on other targets but build nothing.
-# This is useful as follows: building a target of this rule will generate
-# symlink forests for all dependencies of the target, without executing any
-# actions of the build.
-phony_root = rule(
- implementation = _phony_root_impl,
- attrs = {"deps" : attr.label_list()},
-)
-`
-
- productReplacer := strings.NewReplacer(
- "{PRODUCT}", context.targetProduct,
- "{VARIANT}", context.targetBuildVariant)
-
- return []byte(productReplacer.Replace(contents))
-}
-
-func (context *mixedBuildBazelContext) mainBuildFileContents() []byte {
- // TODO(cparsons): Map label to attribute programmatically; don't use hard-coded
- // architecture mapping.
- formatString := `
-# This file is generated by soong_build. Do not edit.
-load(":main.bzl", "config_node", "mixed_build_root", "phony_root")
-
-%s
-
-mixed_build_root(name = "buildroot",
- deps = [%s],
- testonly = True, # Unblocks testonly deps.
-)
-
-phony_root(name = "phonyroot",
- deps = [":buildroot"],
- testonly = True, # Unblocks testonly deps.
-)
-`
- configNodeFormatString := `
-config_node(name = "%s",
- arch = "%s",
- os = "%s",
- within_apex = %s,
- apex_sdk_version = "%s",
- api_domain = "%s",
- deps = [%s],
- testonly = True, # Unblocks testonly deps.
-)
-`
-
- configNodesSection := ""
-
- labelsByConfig := map[string][]string{}
-
- for _, val := range context.requests {
- labelString := fmt.Sprintf("\"@%s\"", val.label)
- configString := getConfigString(val)
- labelsByConfig[configString] = append(labelsByConfig[configString], labelString)
- }
-
- // Configs need to be sorted to maintain determinism of the BUILD file.
- sortedConfigs := make([]string, 0, len(labelsByConfig))
- for val := range labelsByConfig {
- sortedConfigs = append(sortedConfigs, val)
- }
- sort.Slice(sortedConfigs, func(i, j int) bool { return sortedConfigs[i] < sortedConfigs[j] })
-
- allLabels := []string{}
- for _, configString := range sortedConfigs {
- labels := labelsByConfig[configString]
- configTokens := strings.Split(configString, "|")
- if len(configTokens) < 2 {
- panic(fmt.Errorf("Unexpected config string format: %s", configString))
- }
- archString := configTokens[0]
- osString := configTokens[1]
- withinApex := "False"
- apexSdkVerString := ""
- apiDomainString := ""
- if osString == "android" {
- // api domains are meaningful only for device variants
- apiDomainString = "system"
- }
- targetString := fmt.Sprintf("%s_%s", osString, archString)
- if len(configTokens) > 2 {
- targetString += "_" + configTokens[2]
- if configTokens[2] == withinApexToString(true) {
- withinApex = "True"
- }
- }
- if len(configTokens) > 3 {
- targetString += "_" + configTokens[3]
- apexSdkVerString = configTokens[3]
- }
- if len(configTokens) > 4 {
- apiDomainString = configTokens[4]
- targetString += "_" + apiDomainString
- }
- allLabels = append(allLabels, fmt.Sprintf("\":%s\"", targetString))
- labelsString := strings.Join(labels, ",\n ")
- configNodesSection += fmt.Sprintf(configNodeFormatString, targetString, archString, osString, withinApex, apexSdkVerString, apiDomainString,
- labelsString)
- }
-
- return []byte(fmt.Sprintf(formatString, configNodesSection, strings.Join(allLabels, ",\n ")))
-}
-
-func indent(original string) string {
- result := ""
- for _, line := range strings.Split(original, "\n") {
- result += " " + line + "\n"
- }
- return result
-}
-
-// Returns the file contents of the buildroot.cquery file that should be used for the cquery
-// expression in order to obtain information about buildroot and its dependencies.
-// The contents of this file depend on the mixedBuildBazelContext's requests; requests are enumerated
-// and grouped by their request type. The data retrieved for each label depends on its
-// request type.
-func (context *mixedBuildBazelContext) cqueryStarlarkFileContents() []byte {
- requestTypeToCqueryIdEntries := map[cqueryRequest][]string{}
- requestTypes := []cqueryRequest{}
- for _, val := range context.requests {
- cqueryId := getCqueryId(val)
- mapEntryString := fmt.Sprintf("%q : True", cqueryId)
- if _, seenKey := requestTypeToCqueryIdEntries[val.requestType]; !seenKey {
- requestTypes = append(requestTypes, val.requestType)
- }
- requestTypeToCqueryIdEntries[val.requestType] =
- append(requestTypeToCqueryIdEntries[val.requestType], mapEntryString)
- }
- labelRegistrationMapSection := ""
- functionDefSection := ""
- mainSwitchSection := ""
-
- mapDeclarationFormatString := `
-%s = {
- %s
-}
-`
- functionDefFormatString := `
-def %s(target, id_string):
-%s
-`
- mainSwitchSectionFormatString := `
- if id_string in %s:
- return id_string + ">>" + %s(target, id_string)
-`
-
- for _, requestType := range requestTypes {
- labelMapName := requestType.Name() + "_Labels"
- functionName := requestType.Name() + "_Fn"
- labelRegistrationMapSection += fmt.Sprintf(mapDeclarationFormatString,
- labelMapName,
- strings.Join(requestTypeToCqueryIdEntries[requestType], ",\n "))
- functionDefSection += fmt.Sprintf(functionDefFormatString,
- functionName,
- indent(requestType.StarlarkFunctionBody()))
- mainSwitchSection += fmt.Sprintf(mainSwitchSectionFormatString,
- labelMapName, functionName)
- }
-
- formatString := `
-# This file is generated by soong_build. Do not edit.
-
-{LABEL_REGISTRATION_MAP_SECTION}
-
-{FUNCTION_DEF_SECTION}
-
-def get_arch(target):
- # TODO(b/199363072): filegroups and file targets aren't associated with any
- # specific platform architecture in mixed builds. This is consistent with how
- # Soong treats filegroups, but it may not be the case with manually-written
- # filegroup BUILD targets.
- buildoptions = build_options(target)
-
- if buildoptions == None:
- # File targets do not have buildoptions. File targets aren't associated with
- # any specific platform architecture in mixed builds, so use the host.
- return "x86_64|linux"
- platforms = buildoptions["//command_line_option:platforms"]
- if len(platforms) != 1:
- # An individual configured target should have only one platform architecture.
- # Note that it's fine for there to be multiple architectures for the same label,
- # but each is its own configured target.
- fail("expected exactly 1 platform for " + str(target.label) + " but got " + str(platforms))
- platform_name = platforms[0].name
- if platform_name == "host":
- return "HOST"
- if not platform_name.startswith("mixed_builds_product-{TARGET_BUILD_VARIANT}"):
- fail("expected platform name of the form 'mixed_builds_product-{TARGET_BUILD_VARIANT}_android_<arch>' or 'mixed_builds_product-{TARGET_BUILD_VARIANT}_linux_<arch>', but was " + str(platforms))
- platform_name = platform_name.removeprefix("mixed_builds_product-{TARGET_BUILD_VARIANT}").removeprefix("_")
- config_key = ""
- if not platform_name:
- config_key = "target|android"
- elif platform_name.startswith("android_"):
- config_key = platform_name.removeprefix("android_") + "|android"
- elif platform_name.startswith("linux_"):
- config_key = platform_name.removeprefix("linux_") + "|linux"
- else:
- fail("expected platform name of the form 'mixed_builds_product-{TARGET_BUILD_VARIANT}_android_<arch>' or 'mixed_builds_product-{TARGET_BUILD_VARIANT}_linux_<arch>', but was " + str(platforms))
-
- within_apex = buildoptions.get("//build/bazel/rules/apex:within_apex")
- apex_sdk_version = buildoptions.get("//build/bazel/rules/apex:min_sdk_version")
- api_domain = buildoptions.get("//build/bazel/rules/apex:api_domain")
-
- if within_apex:
- config_key += "|within_apex"
- if apex_sdk_version != None and len(apex_sdk_version) > 0:
- config_key += "|" + apex_sdk_version
- if api_domain != None and len(api_domain) > 0:
- config_key += "|" + api_domain
-
- return config_key
-
-def format(target):
- id_string = str(target.label) + "|" + get_arch(target)
-
- # TODO(b/248106697): Remove once Bazel is updated to always normalize labels.
- if id_string.startswith("//"):
- id_string = "@" + id_string
-
- {MAIN_SWITCH_SECTION}
-
- # This target was not requested via cquery, and thus must be a dependency
- # of a requested target.
- return id_string + ">>NONE"
-`
- replacer := strings.NewReplacer(
- "{TARGET_PRODUCT}", context.targetProduct,
- "{TARGET_BUILD_VARIANT}", context.targetBuildVariant,
- "{LABEL_REGISTRATION_MAP_SECTION}", labelRegistrationMapSection,
- "{FUNCTION_DEF_SECTION}", functionDefSection,
- "{MAIN_SWITCH_SECTION}", mainSwitchSection)
-
- return []byte(replacer.Replace(formatString))
-}
-
-// Returns a path containing build-related metadata required for interfacing
-// with Bazel. Example: out/soong/bazel.
-func (p *bazelPaths) intermediatesDir() string {
- return filepath.Join(p.soongOutDir, "bazel")
-}
-
-// Returns the path where the contents of the @soong_injection repository live.
-// It is used by Soong to tell Bazel things it cannot over the command line.
-func (p *bazelPaths) injectedFilesDir() string {
- return filepath.Join(p.soongOutDir, bazel.SoongInjectionDirName)
-}
-
-// Returns the path of the synthetic Bazel workspace that contains a symlink
-// forest composed the whole source tree and BUILD files generated by bp2build.
-func (p *bazelPaths) syntheticWorkspaceDir() string {
- return filepath.Join(p.soongOutDir, "workspace")
-}
-
-// Returns the path to the top level out dir ($OUT_DIR).
-func (p *bazelPaths) outDir() string {
- return filepath.Dir(p.soongOutDir)
-}
-
-const buildrootLabel = "@soong_injection//mixed_builds:buildroot"
-
-var (
- cqueryCmd = bazelCommand{"cquery", fmt.Sprintf("deps(%s, 2)", buildrootLabel)}
- aqueryCmd = bazelCommand{"aquery", fmt.Sprintf("deps(%s)", buildrootLabel)}
- buildCmd = bazelCommand{"build", "@soong_injection//mixed_builds:phonyroot"}
- allBazelCommands = []bazelCommand{aqueryCmd, cqueryCmd, buildCmd}
-)
-
-func GetBazelSandwichCqueryRequests(config Config) ([]cqueryKey, error) {
- result := make([]cqueryKey, 0, len(allowlists.BazelSandwichTargets))
- labelRegex := regexp.MustCompile("^@?//([a-zA-Z0-9/_-]+):[a-zA-Z0-9_-]+$")
- // Note that bazel "targets" are different from soong "targets", the bazel targets are
- // synonymous with soong modules, and soong targets are a configuration a module is built in.
- for _, target := range allowlists.BazelSandwichTargets {
- match := labelRegex.FindStringSubmatch(target.Label)
- if match == nil {
- return nil, fmt.Errorf("invalid label, must match `^@?//([a-zA-Z0-9/_-]+):[a-zA-Z0-9_-]+$`: %s", target.Label)
- }
- if _, err := os.Stat(absolutePath(match[1])); err != nil {
- if os.IsNotExist(err) {
- // Ignore bazel sandwich targets that don't exist.
- continue
- } else {
- return nil, err
- }
- }
-
- var soongTarget Target
- if target.Host {
- soongTarget = config.BuildOSTarget
- } else {
- soongTarget = config.AndroidCommonTarget
- if soongTarget.Os.Class != Device {
- // kernel-build-tools seems to set the AndroidCommonTarget to a linux host
- // target for some reason, disable device builds in that case.
- continue
- }
- }
-
- result = append(result, cqueryKey{
- label: target.Label,
- requestType: cquery.GetOutputFiles,
- configKey: configKey{
- arch: soongTarget.Arch.String(),
- osType: soongTarget.Os,
- },
- })
- }
- return result, nil
-}
-
-// QueueBazelSandwichCqueryRequests queues cquery requests for all the bazel labels in
-// bazel_sandwich_targets. These will later be given phony targets so that they can be built on the
-// command line.
-func (context *mixedBuildBazelContext) QueueBazelSandwichCqueryRequests(config Config) error {
- requests, err := GetBazelSandwichCqueryRequests(config)
- if err != nil {
- return err
- }
- for _, request := range requests {
- context.QueueBazelRequest(request.label, request.requestType, request.configKey)
- }
-
- return nil
-}
-
-// Issues commands to Bazel to receive results for all cquery requests
-// queued in the BazelContext.
-func (context *mixedBuildBazelContext) InvokeBazel(config Config, ctx invokeBazelContext) error {
- eventHandler := ctx.GetEventHandler()
- eventHandler.Begin("bazel")
- defer eventHandler.End("bazel")
-
- if metricsDir := context.paths.BazelMetricsDir(); metricsDir != "" {
- if err := os.MkdirAll(metricsDir, 0777); err != nil {
- return err
- }
- }
- context.results = make(map[cqueryKey]string)
- if err := context.runCquery(config, ctx); err != nil {
- return err
- }
- if err := context.runAquery(config, ctx); err != nil {
- return err
- }
- if err := context.generateBazelSymlinks(config, ctx); err != nil {
- return err
- }
-
- // Clear requests.
- context.requests = []cqueryKey{}
- return nil
-}
-
-func (context *mixedBuildBazelContext) runCquery(config Config, ctx invokeBazelContext) error {
- eventHandler := ctx.GetEventHandler()
- eventHandler.Begin("cquery")
- defer eventHandler.End("cquery")
- soongInjectionPath := absolutePath(context.paths.injectedFilesDir())
- mixedBuildsPath := filepath.Join(soongInjectionPath, "mixed_builds")
- if _, err := os.Stat(mixedBuildsPath); os.IsNotExist(err) {
- err = os.MkdirAll(mixedBuildsPath, 0777)
- if err != nil {
- return err
- }
- }
- if err := writeFileBytesIfChanged(filepath.Join(soongInjectionPath, "WORKSPACE.bazel"), []byte{}, 0666); err != nil {
- return err
- }
- if err := writeFileBytesIfChanged(filepath.Join(mixedBuildsPath, "main.bzl"), context.mainBzlFileContents(), 0666); err != nil {
- return err
- }
- if err := writeFileBytesIfChanged(filepath.Join(mixedBuildsPath, "BUILD.bazel"), context.mainBuildFileContents(), 0666); err != nil {
- return err
- }
- cqueryFileRelpath := filepath.Join(context.paths.injectedFilesDir(), "buildroot.cquery")
- if err := writeFileBytesIfChanged(absolutePath(cqueryFileRelpath), context.cqueryStarlarkFileContents(), 0666); err != nil {
- return err
- }
-
- extraFlags := []string{"--output=starlark", "--starlark:file=" + absolutePath(cqueryFileRelpath)}
- if Bool(config.productVariables.ClangCoverage) {
- extraFlags = append(extraFlags, "--collect_code_coverage")
- }
-
- cqueryCmdRequest := context.createBazelCommand(config, bazel.CqueryBuildRootRunName, cqueryCmd, extraFlags...)
- cqueryOutput, cqueryErrorMessage, cqueryErr := context.issueBazelCommand(cqueryCmdRequest, context.paths, eventHandler)
- if cqueryErr != nil {
- return cqueryErr
- }
- cqueryCommandPrint := fmt.Sprintf("cquery command line:\n %s \n\n\n", context.printableCqueryCommand(cqueryCmdRequest))
- if err := os.WriteFile(filepath.Join(soongInjectionPath, "cquery.out"), []byte(cqueryCommandPrint+cqueryOutput), 0666); err != nil {
- return err
- }
- cqueryResults := map[string]string{}
- for _, outputLine := range strings.Split(cqueryOutput, "\n") {
- if strings.Contains(outputLine, ">>") {
- splitLine := strings.SplitN(outputLine, ">>", 2)
- cqueryResults[splitLine[0]] = splitLine[1]
- }
- }
- for _, val := range context.requests {
- if cqueryResult, ok := cqueryResults[getCqueryId(val)]; ok {
- context.results[val] = cqueryResult
- } else {
- return fmt.Errorf("missing result for bazel target %s. query output: [%s], cquery err: [%s]",
- getCqueryId(val), cqueryOutput, cqueryErrorMessage)
- }
- }
- return nil
-}
-
-func writeFileBytesIfChanged(path string, contents []byte, perm os.FileMode) error {
- oldContents, err := os.ReadFile(path)
- if err != nil || !bytes.Equal(contents, oldContents) {
- err = os.WriteFile(path, contents, perm)
- }
- return nil
-}
-
-func (context *mixedBuildBazelContext) runAquery(config Config, ctx invokeBazelContext) error {
- eventHandler := ctx.GetEventHandler()
- eventHandler.Begin("aquery")
- defer eventHandler.End("aquery")
- // Issue an aquery command to retrieve action information about the bazel build tree.
- //
- // Use jsonproto instead of proto; actual proto parsing would require a dependency on Bazel's
- // proto sources, which would add a number of unnecessary dependencies.
- extraFlags := []string{"--output=proto", "--include_file_write_contents"}
- if Bool(config.productVariables.ClangCoverage) {
- extraFlags = append(extraFlags, "--collect_code_coverage")
- paths := make([]string, 0, 2)
- if p := config.productVariables.NativeCoveragePaths; len(p) > 0 {
- for i := range p {
- // TODO(b/259404593) convert path wildcard to regex values
- if p[i] == "*" {
- p[i] = ".*"
- }
- }
- paths = append(paths, JoinWithPrefixAndSeparator(p, "+", ","))
- }
- if p := config.productVariables.NativeCoverageExcludePaths; len(p) > 0 {
- paths = append(paths, JoinWithPrefixAndSeparator(p, "-", ","))
- }
- if len(paths) > 0 {
- extraFlags = append(extraFlags, "--instrumentation_filter="+strings.Join(paths, ","))
- }
- }
- aqueryOutput, _, err := context.issueBazelCommand(context.createBazelCommand(config, bazel.AqueryBuildRootRunName, aqueryCmd,
- extraFlags...), context.paths, eventHandler)
- if err != nil {
- return err
- }
- context.buildStatements, context.depsets, err = bazel.AqueryBuildStatements([]byte(aqueryOutput), eventHandler)
- return err
-}
-
-func (context *mixedBuildBazelContext) generateBazelSymlinks(config Config, ctx invokeBazelContext) error {
- eventHandler := ctx.GetEventHandler()
- eventHandler.Begin("symlinks")
- defer eventHandler.End("symlinks")
- // Issue a build command of the phony root to generate symlink forests for dependencies of the
- // Bazel build. This is necessary because aquery invocations do not generate this symlink forest,
- // but some of symlinks may be required to resolve source dependencies of the build.
- _, _, err := context.issueBazelCommand(context.createBazelCommand(config, bazel.BazelBuildPhonyRootRunName, buildCmd), context.paths, eventHandler)
- return err
-}
-
-func (context *mixedBuildBazelContext) BuildStatementsToRegister() []*bazel.BuildStatement {
- return context.buildStatements
-}
-
-func (context *mixedBuildBazelContext) AqueryDepsets() []bazel.AqueryDepset {
- return context.depsets
-}
-
-func (context *mixedBuildBazelContext) OutputBase() string {
- return context.paths.outputBase
-}
-
-// Singleton used for registering BUILD file ninja dependencies (needed
-// for correctness of builds which use Bazel.
-func BazelSingleton() Singleton {
- return &bazelSingleton{}
-}
-
-type bazelSingleton struct{}
-
-func (c *bazelSingleton) GenerateBuildActions(ctx SingletonContext) {
- // bazelSingleton is a no-op if mixed-soong-bazel-builds are disabled.
- if !ctx.Config().IsMixedBuildsEnabled() {
- return
- }
-
- // Add ninja file dependencies for files which all bazel invocations require.
- bazelBuildList := absolutePath(filepath.Join(
- filepath.Dir(ctx.Config().moduleListFile), "bazel.list"))
- ctx.AddNinjaFileDeps(bazelBuildList)
-
- data, err := os.ReadFile(bazelBuildList)
- if err != nil {
- ctx.Errorf(err.Error())
- }
- files := strings.Split(strings.TrimSpace(string(data)), "\n")
- for _, file := range files {
- ctx.AddNinjaFileDeps(file)
- }
-
- depsetHashToDepset := map[string]bazel.AqueryDepset{}
-
- for _, depset := range ctx.Config().BazelContext.AqueryDepsets() {
- depsetHashToDepset[depset.ContentHash] = depset
-
- var outputs []Path
- var orderOnlies []Path
- for _, depsetDepHash := range depset.TransitiveDepSetHashes {
- otherDepsetName := bazelDepsetName(depsetDepHash)
- outputs = append(outputs, PathForPhony(ctx, otherDepsetName))
- }
- for _, artifactPath := range depset.DirectArtifacts {
- pathInBazelOut := PathForBazelOut(ctx, artifactPath)
- if artifactPath == "bazel-out/volatile-status.txt" {
- // See https://bazel.build/docs/user-manual#workspace-status
- orderOnlies = append(orderOnlies, pathInBazelOut)
- } else {
- outputs = append(outputs, pathInBazelOut)
- }
- }
- thisDepsetName := bazelDepsetName(depset.ContentHash)
- ctx.Build(pctx, BuildParams{
- Rule: blueprint.Phony,
- Outputs: []WritablePath{PathForPhony(ctx, thisDepsetName)},
- Implicits: outputs,
- OrderOnly: orderOnlies,
- })
- }
-
- executionRoot := path.Join(ctx.Config().BazelContext.OutputBase(), "execroot", "__main__")
- bazelOutDir := path.Join(executionRoot, "bazel-out")
- rel, err := filepath.Rel(ctx.Config().OutDir(), executionRoot)
- if err != nil {
- ctx.Errorf("%s", err.Error())
- }
- dotdotsToOutRoot := strings.Repeat("../", strings.Count(rel, "/")+1)
- for index, buildStatement := range ctx.Config().BazelContext.BuildStatementsToRegister() {
- // nil build statements are a valid case where we do not create an action because it is
- // unnecessary or handled by other processing
- if buildStatement == nil {
- continue
- }
- if len(buildStatement.Command) > 0 {
- rule := NewRuleBuilder(pctx, ctx)
- intermediateDir, intermediateDirHash := intermediatePathForSboxMixedBuildAction(ctx, buildStatement)
- if buildStatement.ShouldRunInSbox {
- // Create a rule to build the output inside a sandbox
- // This will create two changes of working directory
- // 1. From ANDROID_BUILD_TOP to sbox top
- // 2. From sbox top to a a synthetic mixed build execution root relative to it
- // Finally, the outputs will be copied to intermediateDir
- rule.Sbox(intermediateDir,
- PathForOutput(ctx, "mixed_build_sbox_intermediates", intermediateDirHash+".textproto")).
- SandboxInputs().
- // Since we will cd to mixed build execution root, set sbox's out subdir to empty
- // Without this, we will try to copy from $SBOX_SANDBOX_DIR/out/out/bazel/output/execroot/__main__/...
- SetSboxOutDirDirAsEmpty()
-
- // Create another set of rules to copy files from the intermediate dir to mixed build execution root
- for _, outputPath := range buildStatement.OutputPaths {
- ctx.Build(pctx, BuildParams{
- Rule: CpIfChanged,
- Input: intermediateDir.Join(ctx, executionRoot, outputPath),
- Output: PathForBazelOut(ctx, outputPath),
- })
- }
- }
- createCommand(rule.Command(), buildStatement, executionRoot, bazelOutDir, ctx, depsetHashToDepset, dotdotsToOutRoot)
-
- desc := fmt.Sprintf("%s: %s", buildStatement.Mnemonic, buildStatement.OutputPaths)
- rule.Build(fmt.Sprintf("bazel %d", index), desc)
- continue
- }
- // Certain actions returned by aquery (for instance FileWrite) do not contain a command
- // and thus require special treatment. If BuildStatement were an interface implementing
- // buildRule(ctx) function, the code here would just call it.
- // Unfortunately, the BuildStatement is defined in
- // the 'bazel' package, which cannot depend on 'android' package where ctx is defined,
- // because this would cause circular dependency. So, until we move aquery processing
- // to the 'android' package, we need to handle special cases here.
- switch buildStatement.Mnemonic {
- case "RepoMappingManifest":
- // It appears RepoMappingManifest files currently have
- // non-deterministic content. Just emit empty files for
- // now because they're unused.
- out := PathForBazelOut(ctx, buildStatement.OutputPaths[0])
- WriteFileRuleVerbatim(ctx, out, "")
- case "FileWrite", "SourceSymlinkManifest":
- out := PathForBazelOut(ctx, buildStatement.OutputPaths[0])
- if buildStatement.IsExecutable {
- WriteExecutableFileRuleVerbatim(ctx, out, buildStatement.FileContents)
- } else {
- WriteFileRuleVerbatim(ctx, out, buildStatement.FileContents)
- }
- case "SymlinkTree":
- // build-runfiles arguments are the manifest file and the target directory
- // where it creates the symlink tree according to this manifest (and then
- // writes the MANIFEST file to it).
- outManifest := PathForBazelOut(ctx, buildStatement.OutputPaths[0])
- outManifestPath := outManifest.String()
- if !strings.HasSuffix(outManifestPath, "MANIFEST") {
- panic("the base name of the symlink tree action should be MANIFEST, got " + outManifestPath)
- }
- outDir := filepath.Dir(outManifestPath)
- ctx.Build(pctx, BuildParams{
- Rule: buildRunfilesRule,
- Output: outManifest,
- Inputs: []Path{PathForBazelOut(ctx, buildStatement.InputPaths[0])},
- Description: "symlink tree for " + outDir,
- Args: map[string]string{
- "outDir": outDir,
- },
- })
- default:
- panic(fmt.Sprintf("unhandled build statement: %v", buildStatement))
- }
- }
-
- // Create phony targets for all the bazel sandwich output files
- requests, err := GetBazelSandwichCqueryRequests(ctx.Config())
- if err != nil {
- ctx.Errorf(err.Error())
- }
- for _, request := range requests {
- files, err := ctx.Config().BazelContext.GetOutputFiles(request.label, request.configKey)
- if err != nil {
- ctx.Errorf(err.Error())
- }
- filesAsPaths := make([]Path, 0, len(files))
- for _, file := range files {
- filesAsPaths = append(filesAsPaths, PathForBazelOut(ctx, file))
- }
- ctx.Phony("bazel_sandwich", filesAsPaths...)
- }
- ctx.Phony("checkbuild", PathForPhony(ctx, "bazel_sandwich"))
-}
-
-// Returns a out dir path for a sandboxed mixed build action
-func intermediatePathForSboxMixedBuildAction(ctx PathContext, statement *bazel.BuildStatement) (OutputPath, string) {
- // An artifact can be generated by a single buildstatement.
- // Use the hash of the first artifact to create a unique path
- uniqueDir := sha1.New()
- uniqueDir.Write([]byte(statement.OutputPaths[0]))
- uniqueDirHashString := hex.EncodeToString(uniqueDir.Sum(nil))
- return PathForOutput(ctx, "mixed_build_sbox_intermediates", uniqueDirHashString), uniqueDirHashString
-}
-
-// Register bazel-owned build statements (obtained from the aquery invocation).
-func createCommand(cmd *RuleBuilderCommand, buildStatement *bazel.BuildStatement, executionRoot string, bazelOutDir string, ctx BuilderContext, depsetHashToDepset map[string]bazel.AqueryDepset, dotdotsToOutRoot string) {
- // executionRoot is the action cwd.
- if buildStatement.ShouldRunInSbox {
- // mkdir -p ensures that the directory exists when run via sbox
- cmd.Text(fmt.Sprintf("mkdir -p '%s' && cd '%s' &&", executionRoot, executionRoot))
- } else {
- cmd.Text(fmt.Sprintf("cd '%s' &&", executionRoot))
- }
-
- // Remove old outputs, as some actions might not rerun if the outputs are detected.
- if len(buildStatement.OutputPaths) > 0 {
- cmd.Text("rm -rf") // -r because outputs can be Bazel dir/tree artifacts.
- for _, outputPath := range buildStatement.OutputPaths {
- cmd.Text(fmt.Sprintf("'%s'", outputPath))
- }
- cmd.Text("&&")
- }
-
- for _, pair := range buildStatement.Env {
- // Set per-action env variables, if any.
- cmd.Flag(pair.Key + "=" + pair.Value)
- }
-
- command := buildStatement.Command
- command = strings.ReplaceAll(command, "{DOTDOTS_TO_OUTPUT_ROOT}", dotdotsToOutRoot)
-
- // The actual Bazel action.
- if len(command) > 16*1024 {
- commandFile := PathForBazelOut(ctx, buildStatement.OutputPaths[0]+".sh")
- WriteFileRule(ctx, commandFile, command)
-
- cmd.Text("bash").Text(buildStatement.OutputPaths[0] + ".sh").Implicit(commandFile)
- } else {
- cmd.Text(command)
- }
-
- for _, outputPath := range buildStatement.OutputPaths {
- if buildStatement.ShouldRunInSbox {
- // The full path has three components that get joined together
- // 1. intermediate output dir that `sbox` will place the artifacts at
- // 2. mixed build execution root
- // 3. artifact path returned by aquery
- intermediateDir, _ := intermediatePathForSboxMixedBuildAction(ctx, buildStatement)
- cmd.ImplicitOutput(intermediateDir.Join(ctx, executionRoot, outputPath))
- } else {
- cmd.ImplicitOutput(PathForBazelOut(ctx, outputPath))
- }
- }
- for _, inputPath := range buildStatement.InputPaths {
- cmd.Implicit(PathForBazelOut(ctx, inputPath))
- }
- for _, inputDepsetHash := range buildStatement.InputDepsetHashes {
- if buildStatement.ShouldRunInSbox {
- // Bazel depsets are phony targets that are used to group files.
- // We need to copy the grouped files into the sandbox
- ds, _ := depsetHashToDepset[inputDepsetHash]
- cmd.Implicits(PathsForBazelOut(ctx, ds.DirectArtifacts))
- } else {
- otherDepsetName := bazelDepsetName(inputDepsetHash)
- cmd.Implicit(PathForPhony(ctx, otherDepsetName))
- }
- }
- for _, implicitPath := range buildStatement.ImplicitDeps {
- cmd.Implicit(PathForArbitraryOutput(ctx, implicitPath))
- }
-
- if depfile := buildStatement.Depfile; depfile != nil {
- // The paths in depfile are relative to `executionRoot`.
- // Hence, they need to be corrected by replacing "bazel-out"
- // with the full `bazelOutDir`.
- // Otherwise, implicit outputs and implicit inputs under "bazel-out/"
- // would be deemed missing.
- // (Note: The regexp uses a capture group because the version of sed
- // does not support a look-behind pattern.)
- replacement := fmt.Sprintf(`&& sed -i'' -E 's@(^|\s|")bazel-out/@\1%s/@g' '%s'`,
- bazelOutDir, *depfile)
- cmd.Text(replacement)
- cmd.ImplicitDepFile(PathForBazelOut(ctx, *depfile))
- }
-
- for _, symlinkPath := range buildStatement.SymlinkPaths {
- cmd.ImplicitSymlinkOutput(PathForBazelOut(ctx, symlinkPath))
- }
-}
-
-func getCqueryId(key cqueryKey) string {
- return key.label + "|" + getConfigString(key)
-}
-
-func getConfigString(key cqueryKey) string {
- arch := key.configKey.arch
- if len(arch) == 0 || arch == "common" {
- if key.configKey.osType.Class == Device {
- // For the generic Android, the expected result is "target|android", which
- // corresponds to the product_variable_config named "android_target" in
- // build/bazel/platforms/BUILD.bazel.
- arch = "target"
- } else {
- // Use host platform, which is currently hardcoded to be x86_64.
- arch = "x86_64"
- }
- }
- osName := key.configKey.osType.Name
- if len(osName) == 0 || osName == "common_os" || osName == "linux_glibc" || osName == "linux_musl" {
- // Use host OS, which is currently hardcoded to be linux.
- osName = "linux"
- }
- keyString := arch + "|" + osName
- if key.configKey.apexKey.WithinApex {
- keyString += "|" + withinApexToString(key.configKey.apexKey.WithinApex)
- }
-
- if len(key.configKey.apexKey.ApexSdkVersion) > 0 {
- keyString += "|" + key.configKey.apexKey.ApexSdkVersion
- }
-
- if len(key.configKey.apexKey.ApiDomain) > 0 {
- keyString += "|" + key.configKey.apexKey.ApiDomain
- }
-
- return keyString
-}
-
-func GetConfigKey(ctx BaseModuleContext) configKey {
- return configKey{
- // use string because Arch is not a valid key in go
- arch: ctx.Arch().String(),
- osType: ctx.Os(),
- }
-}
-
-func GetConfigKeyApexVariant(ctx BaseModuleContext, apexKey *ApexConfigKey) configKey {
- configKey := GetConfigKey(ctx)
-
- if apexKey != nil {
- configKey.apexKey = ApexConfigKey{
- WithinApex: apexKey.WithinApex,
- ApexSdkVersion: apexKey.ApexSdkVersion,
- ApiDomain: apexKey.ApiDomain,
- }
- }
-
- return configKey
-}
-
-func bazelDepsetName(contentHash string) string {
- return fmt.Sprintf("bazel_depset_%s", contentHash)
-}
diff --git a/android/bazel_handler_test.go b/android/bazel_handler_test.go
deleted file mode 100644
index 9a3c8fc..0000000
--- a/android/bazel_handler_test.go
+++ /dev/null
@@ -1,426 +0,0 @@
-package android
-
-import (
- "encoding/json"
- "os"
- "path/filepath"
- "reflect"
- "strings"
- "testing"
-
- "android/soong/bazel"
- "android/soong/bazel/cquery"
- analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
-
- "github.com/google/blueprint/metrics"
- "google.golang.org/protobuf/proto"
-)
-
-var testConfig = TestConfig("out", nil, "", nil)
-
-type testInvokeBazelContext struct{}
-
-type mockBazelRunner struct {
- testHelper *testing.T
- // Stores mock behavior. If an issueBazelCommand request is made for command
- // k, and {k:v} is present in this map, then the mock will return v.
- bazelCommandResults map[bazelCommand]string
- // Requests actually made of the mockBazelRunner with issueBazelCommand,
- // keyed by the command they represent.
- bazelCommandRequests map[bazelCommand]bazel.CmdRequest
-}
-
-func (r *mockBazelRunner) bazelCommandForRequest(cmdRequest bazel.CmdRequest) bazelCommand {
- for _, arg := range cmdRequest.Argv {
- for _, cmdType := range allBazelCommands {
- if arg == cmdType.command {
- return cmdType
- }
- }
- }
- r.testHelper.Fatalf("Unrecognized bazel request: %s", cmdRequest)
- return cqueryCmd
-}
-
-func (r *mockBazelRunner) issueBazelCommand(cmdRequest bazel.CmdRequest, paths *bazelPaths, eventHandler *metrics.EventHandler) (string, string, error) {
- command := r.bazelCommandForRequest(cmdRequest)
- r.bazelCommandRequests[command] = cmdRequest
- return r.bazelCommandResults[command], "", nil
-}
-
-func (t *testInvokeBazelContext) GetEventHandler() *metrics.EventHandler {
- return &metrics.EventHandler{}
-}
-
-func TestRequestResultsAfterInvokeBazel(t *testing.T) {
- label_foo := "@//foo:foo"
- label_bar := "@//foo:bar"
- apexKey := ApexConfigKey{
- WithinApex: true,
- ApexSdkVersion: "29",
- ApiDomain: "myapex",
- }
- cfg_foo := configKey{"arm64_armv8-a", Android, apexKey}
- cfg_bar := configKey{arch: "arm64_armv8-a", osType: Android}
- cmd_results := []string{
- `@//foo:foo|arm64_armv8-a|android|within_apex|29|myapex>>out/foo/foo.txt`,
- `@//foo:bar|arm64_armv8-a|android>>out/foo/bar.txt`,
- }
- bazelContext, _ := testBazelContext(t, map[bazelCommand]string{cqueryCmd: strings.Join(cmd_results, "\n")})
-
- bazelContext.QueueBazelRequest(label_foo, cquery.GetOutputFiles, cfg_foo)
- bazelContext.QueueBazelRequest(label_bar, cquery.GetOutputFiles, cfg_bar)
- err := bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
- if err != nil {
- t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
- }
- verifyCqueryResult(t, bazelContext, label_foo, cfg_foo, "out/foo/foo.txt")
- verifyCqueryResult(t, bazelContext, label_bar, cfg_bar, "out/foo/bar.txt")
-}
-
-func verifyCqueryResult(t *testing.T, ctx *mixedBuildBazelContext, label string, cfg configKey, result string) {
- g, err := ctx.GetOutputFiles(label, cfg)
- if err != nil {
- t.Errorf("Expected cquery results after running InvokeBazel(), but got err %v", err)
- } else if w := []string{result}; !reflect.DeepEqual(w, g) {
- t.Errorf("Expected output %s, got %s", w, g)
- }
-}
-
-func TestInvokeBazelWritesBazelFiles(t *testing.T) {
- bazelContext, baseDir := testBazelContext(t, map[bazelCommand]string{})
- err := bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
- if err != nil {
- t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
- }
- if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "mixed_builds", "main.bzl")); os.IsNotExist(err) {
- t.Errorf("Expected main.bzl to exist, but it does not")
- } else if err != nil {
- t.Errorf("Unexpected error stating main.bzl %s", err)
- }
-
- if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "mixed_builds", "BUILD.bazel")); os.IsNotExist(err) {
- t.Errorf("Expected BUILD.bazel to exist, but it does not")
- } else if err != nil {
- t.Errorf("Unexpected error stating BUILD.bazel %s", err)
- }
-
- if _, err := os.Stat(filepath.Join(baseDir, "soong_injection", "WORKSPACE.bazel")); os.IsNotExist(err) {
- t.Errorf("Expected WORKSPACE.bazel to exist, but it does not")
- } else if err != nil {
- t.Errorf("Unexpected error stating WORKSPACE.bazel %s", err)
- }
-}
-
-func TestInvokeBazelPopulatesBuildStatements(t *testing.T) {
- type testCase struct {
- input string
- command string
- }
-
- var testCases = []testCase{
- {`
-{
- "artifacts": [
- { "id": 1, "path_fragment_id": 1 },
- { "id": 2, "path_fragment_id": 2 }],
- "actions": [{
- "target_Id": 1,
- "action_Key": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "input_dep_set_ids": [1],
- "output_Ids": [1],
- "primary_output_id": 1
- }],
- "dep_set_of_files": [
- { "id": 1, "direct_artifact_ids": [1, 2] }],
- "path_fragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two" }]
-}`,
- "cd 'test/exec_root' && rm -rf 'one' && touch foo",
- }, {`
-{
- "artifacts": [
- { "id": 1, "path_fragment_id": 10 },
- { "id": 2, "path_fragment_id": 20 }],
- "actions": [{
- "target_Id": 100,
- "action_Key": "x",
- "mnemonic": "x",
- "arguments": ["bogus", "command"],
- "output_Ids": [1, 2],
- "primary_output_id": 1
- }],
- "path_fragments": [
- { "id": 10, "label": "one", "parent_id": 30 },
- { "id": 20, "label": "one.d", "parent_id": 30 },
- { "id": 30, "label": "parent" }]
-}`,
- `cd 'test/exec_root' && rm -rf 'parent/one' && bogus command && sed -i'' -E 's@(^|\s|")bazel-out/@\1test/bazel_out/@g' 'parent/one.d'`,
- },
- }
-
- for i, testCase := range testCases {
- data, err := JsonToActionGraphContainer(testCase.input)
- if err != nil {
- t.Error(err)
- }
- bazelContext, _ := testBazelContext(t, map[bazelCommand]string{aqueryCmd: string(data)})
-
- err = bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
- if err != nil {
- t.Fatalf("testCase #%d: did not expect error invoking Bazel, but got %s", i+1, err)
- }
-
- got := bazelContext.BuildStatementsToRegister()
- if want := 1; len(got) != want {
- t.Fatalf("expected %d registered build statements, but got %#v", want, got)
- }
-
- cmd := RuleBuilderCommand{}
- ctx := builderContextForTests{PathContextForTesting(TestConfig("out", nil, "", nil))}
- createCommand(&cmd, got[0], "test/exec_root", "test/bazel_out", ctx, map[string]bazel.AqueryDepset{}, "")
- if actual, expected := cmd.buf.String(), testCase.command; expected != actual {
- t.Errorf("expected: [%s], actual: [%s]", expected, actual)
- }
- }
-}
-
-func TestMixedBuildSandboxedAction(t *testing.T) {
- input := `{
- "artifacts": [
- { "id": 1, "path_fragment_id": 1 },
- { "id": 2, "path_fragment_id": 2 }],
- "actions": [{
- "target_Id": 1,
- "action_Key": "x",
- "mnemonic": "x",
- "arguments": ["touch", "foo"],
- "input_dep_set_ids": [1],
- "output_Ids": [1],
- "primary_output_id": 1
- }],
- "dep_set_of_files": [
- { "id": 1, "direct_artifact_ids": [1, 2] }],
- "path_fragments": [
- { "id": 1, "label": "one" },
- { "id": 2, "label": "two" }]
-}`
- data, err := JsonToActionGraphContainer(input)
- if err != nil {
- t.Error(err)
- }
- bazelContext, _ := testBazelContext(t, map[bazelCommand]string{aqueryCmd: string(data)})
-
- err = bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
- if err != nil {
- t.Fatalf("TestMixedBuildSandboxedAction did not expect error invoking Bazel, but got %s", err)
- }
-
- statement := bazelContext.BuildStatementsToRegister()[0]
- statement.ShouldRunInSbox = true
-
- cmd := RuleBuilderCommand{}
- ctx := builderContextForTests{PathContextForTesting(TestConfig("out", nil, "", nil))}
- createCommand(&cmd, statement, "test/exec_root", "test/bazel_out", ctx, map[string]bazel.AqueryDepset{}, "")
- // Assert that the output is generated in an intermediate directory
- // fe05bcdcdc4928012781a5f1a2a77cbb5398e106 is the sha1 checksum of "one"
- if actual, expected := cmd.outputs[0].String(), "out/soong/mixed_build_sbox_intermediates/fe05bcdcdc4928012781a5f1a2a77cbb5398e106/test/exec_root/one"; expected != actual {
- t.Errorf("expected: [%s], actual: [%s]", expected, actual)
- }
-
- // Assert the actual command remains unchanged inside the sandbox
- if actual, expected := cmd.buf.String(), "mkdir -p 'test/exec_root' && cd 'test/exec_root' && rm -rf 'one' && touch foo"; expected != actual {
- t.Errorf("expected: [%s], actual: [%s]", expected, actual)
- }
-}
-
-func TestCoverageFlagsAfterInvokeBazel(t *testing.T) {
- testConfig.productVariables.ClangCoverage = boolPtr(true)
-
- testConfig.productVariables.NativeCoveragePaths = []string{"foo1", "foo2"}
- testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1", "bar2"}
- verifyAqueryContainsFlags(t, testConfig, "--collect_code_coverage", "--instrumentation_filter=+foo1,+foo2,-bar1,-bar2")
-
- testConfig.productVariables.NativeCoveragePaths = []string{"foo1"}
- testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
- verifyAqueryContainsFlags(t, testConfig, "--collect_code_coverage", "--instrumentation_filter=+foo1,-bar1")
-
- testConfig.productVariables.NativeCoveragePaths = []string{"foo1"}
- testConfig.productVariables.NativeCoverageExcludePaths = nil
- verifyAqueryContainsFlags(t, testConfig, "--collect_code_coverage", "--instrumentation_filter=+foo1")
-
- testConfig.productVariables.NativeCoveragePaths = nil
- testConfig.productVariables.NativeCoverageExcludePaths = []string{"bar1"}
- verifyAqueryContainsFlags(t, testConfig, "--collect_code_coverage", "--instrumentation_filter=-bar1")
-
- testConfig.productVariables.NativeCoveragePaths = []string{"*"}
- testConfig.productVariables.NativeCoverageExcludePaths = nil
- verifyAqueryContainsFlags(t, testConfig, "--collect_code_coverage", "--instrumentation_filter=+.*")
-
- testConfig.productVariables.ClangCoverage = boolPtr(false)
- verifyAqueryDoesNotContainSubstrings(t, testConfig, "collect_code_coverage", "instrumentation_filter")
-}
-
-func TestBazelRequestsSorted(t *testing.T) {
- bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
-
- cfgKeyArm64Android := configKey{arch: "arm64_armv8-a", osType: Android}
- cfgKeyArm64Linux := configKey{arch: "arm64_armv8-a", osType: Linux}
- cfgKeyOtherAndroid := configKey{arch: "otherarch", osType: Android}
-
- bazelContext.QueueBazelRequest("zzz", cquery.GetOutputFiles, cfgKeyArm64Android)
- bazelContext.QueueBazelRequest("ccc", cquery.GetApexInfo, cfgKeyArm64Android)
- bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, cfgKeyArm64Android)
- bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, cfgKeyArm64Android)
- bazelContext.QueueBazelRequest("xxx", cquery.GetOutputFiles, cfgKeyArm64Linux)
- bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, cfgKeyArm64Android)
- bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, cfgKeyOtherAndroid)
- bazelContext.QueueBazelRequest("bbb", cquery.GetOutputFiles, cfgKeyOtherAndroid)
-
- if len(bazelContext.requests) != 7 {
- t.Error("Expected 7 request elements, but got", len(bazelContext.requests))
- }
-
- lastString := ""
- for _, val := range bazelContext.requests {
- thisString := val.String()
- if thisString <= lastString {
- t.Errorf("Requests are not ordered correctly. '%s' came before '%s'", lastString, thisString)
- }
- lastString = thisString
- }
-}
-
-func TestIsModuleNameAllowed(t *testing.T) {
- libDisabled := "lib_disabled"
- libEnabled := "lib_enabled"
- libDclaWithinApex := "lib_dcla_within_apex"
- libDclaNonApex := "lib_dcla_non_apex"
- libNotConverted := "lib_not_converted"
-
- disabledModules := map[string]bool{
- libDisabled: true,
- }
- enabledModules := map[string]bool{
- libEnabled: true,
- }
- dclaEnabledModules := map[string]bool{
- libDclaWithinApex: true,
- libDclaNonApex: true,
- }
-
- bazelContext := &mixedBuildBazelContext{
- bazelEnabledModules: enabledModules,
- bazelDisabledModules: disabledModules,
- bazelDclaEnabledModules: dclaEnabledModules,
- }
-
- if bazelContext.IsModuleNameAllowed(libDisabled, true) {
- t.Fatalf("%s shouldn't be allowed for mixed build", libDisabled)
- }
-
- if !bazelContext.IsModuleNameAllowed(libEnabled, true) {
- t.Fatalf("%s should be allowed for mixed build", libEnabled)
- }
-
- if !bazelContext.IsModuleNameAllowed(libDclaWithinApex, true) {
- t.Fatalf("%s should be allowed for mixed build", libDclaWithinApex)
- }
-
- if bazelContext.IsModuleNameAllowed(libDclaNonApex, false) {
- t.Fatalf("%s shouldn't be allowed for mixed build", libDclaNonApex)
- }
-
- if bazelContext.IsModuleNameAllowed(libNotConverted, true) {
- t.Fatalf("%s shouldn't be allowed for mixed build", libNotConverted)
- }
-}
-
-func verifyAqueryContainsFlags(t *testing.T, config Config, expected ...string) {
- t.Helper()
- bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
-
- err := bazelContext.InvokeBazel(config, &testInvokeBazelContext{})
- if err != nil {
- t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
- }
-
- sliceContains := func(slice []string, x string) bool {
- for _, s := range slice {
- if s == x {
- return true
- }
- }
- return false
- }
-
- aqueryArgv := bazelContext.bazelRunner.(*mockBazelRunner).bazelCommandRequests[aqueryCmd].Argv
-
- for _, expectedFlag := range expected {
- if !sliceContains(aqueryArgv, expectedFlag) {
- t.Errorf("aquery does not contain expected flag %#v. Argv was: %#v", expectedFlag, aqueryArgv)
- }
- }
-}
-
-func verifyAqueryDoesNotContainSubstrings(t *testing.T, config Config, substrings ...string) {
- t.Helper()
- bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
-
- err := bazelContext.InvokeBazel(config, &testInvokeBazelContext{})
- if err != nil {
- t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
- }
-
- sliceContainsSubstring := func(slice []string, substring string) bool {
- for _, s := range slice {
- if strings.Contains(s, substring) {
- return true
- }
- }
- return false
- }
-
- aqueryArgv := bazelContext.bazelRunner.(*mockBazelRunner).bazelCommandRequests[aqueryCmd].Argv
-
- for _, substring := range substrings {
- if sliceContainsSubstring(aqueryArgv, substring) {
- t.Errorf("aquery contains unexpected substring %#v. Argv was: %#v", substring, aqueryArgv)
- }
- }
-}
-
-func testBazelContext(t *testing.T, bazelCommandResults map[bazelCommand]string) (*mixedBuildBazelContext, string) {
- t.Helper()
- p := bazelPaths{
- soongOutDir: t.TempDir(),
- outputBase: "outputbase",
- workspaceDir: "workspace_dir",
- }
- if _, exists := bazelCommandResults[aqueryCmd]; !exists {
- bazelCommandResults[aqueryCmd] = ""
- }
- runner := &mockBazelRunner{
- testHelper: t,
- bazelCommandResults: bazelCommandResults,
- bazelCommandRequests: map[bazelCommand]bazel.CmdRequest{},
- }
- return &mixedBuildBazelContext{
- bazelRunner: runner,
- paths: &p,
- }, p.soongOutDir
-}
-
-// Transform the json format to ActionGraphContainer
-func JsonToActionGraphContainer(inputString string) ([]byte, error) {
- var aqueryProtoResult analysis_v2_proto.ActionGraphContainer
- err := json.Unmarshal([]byte(inputString), &aqueryProtoResult)
- if err != nil {
- return []byte(""), err
- }
- data, _ := proto.Marshal(&aqueryProtoResult)
- return data, err
-}
diff --git a/android/bazel_paths.go b/android/bazel_paths.go
deleted file mode 100644
index 86829ce..0000000
--- a/android/bazel_paths.go
+++ /dev/null
@@ -1,622 +0,0 @@
-// Copyright 2015 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 android
-
-import (
- "fmt"
- "path/filepath"
- "strings"
-
- "android/soong/bazel"
-
- "github.com/google/blueprint"
- "github.com/google/blueprint/pathtools"
-)
-
-// bazel_paths contains methods to:
-// * resolve Soong path and module references into bazel.LabelList
-// * resolve Bazel path references into Soong-compatible paths
-//
-// There is often a similar method for Bazel as there is for Soong path handling and should be used
-// in similar circumstances
-//
-// Bazel Soong
-// ==============================================================
-// BazelLabelForModuleSrc PathForModuleSrc
-// BazelLabelForModuleSrcExcludes PathForModuleSrcExcludes
-// BazelLabelForModuleDeps n/a
-// tbd PathForSource
-// tbd ExistentPathsForSources
-// PathForBazelOut PathForModuleOut
-//
-// Use cases:
-// * Module contains a property (often tagged `android:"path"`) that expects paths *relative to the
-// module directory*:
-// * BazelLabelForModuleSrcExcludes, if the module also contains an excludes_<propname> property
-// * BazelLabelForModuleSrc, otherwise
-// * Converting references to other modules to Bazel Labels:
-// BazelLabelForModuleDeps
-// * Converting a path obtained from bazel_handler cquery results:
-// PathForBazelOut
-//
-// NOTE: all Soong globs are expanded within Soong rather than being converted to a Bazel glob
-// syntax. This occurs because Soong does not have a concept of crossing package boundaries,
-// so the glob as computed by Soong may contain paths that cross package-boundaries. These
-// would be unknowingly omitted if the glob were handled by Bazel. By expanding globs within
-// Soong, we support identification and detection (within Bazel) use of paths that cross
-// package boundaries.
-//
-// Path resolution:
-// * filepath/globs: resolves as itself or is converted to an absolute Bazel label (e.g.
-// //path/to/dir:<filepath>) if path exists in a separate package or subpackage.
-// * references to other modules (using the ":name{.tag}" syntax). These resolve as a Bazel label
-// for a target. If the Bazel target is in the local module directory, it will be returned
-// relative to the current package (e.g. ":<target>"). Otherwise, it will be returned as an
-// absolute Bazel label (e.g. "//path/to/dir:<target>"). If the reference to another module
-// cannot be resolved,the function will panic. This is often due to the dependency not being added
-// via an AddDependency* method.
-
-// BazelConversionContext is a minimal context interface to check if a module should be converted by bp2build,
-// with functions containing information to match against allowlists and denylists.
-// If a module is deemed to be convertible by bp2build, then it should rely on a
-// BazelConversionPathContext for more functions for dep/path features.
-type BazelConversionContext interface {
- Config() Config
-
- Module() Module
- OtherModuleType(m blueprint.Module) string
- OtherModuleName(m blueprint.Module) string
- OtherModuleDir(m blueprint.Module) string
- ModuleErrorf(format string, args ...interface{})
-}
-
-// A subset of the ModuleContext methods which are sufficient to resolve references to paths/deps in
-// order to form a Bazel-compatible label for conversion.
-type BazelConversionPathContext interface {
- EarlyModulePathContext
- BazelConversionContext
-
- ModuleName() string
- ModuleType() string
- ModuleErrorf(fmt string, args ...interface{})
- PropertyErrorf(property, fmt string, args ...interface{})
- GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
- ModuleFromName(name string) (blueprint.Module, bool)
- AddUnconvertedBp2buildDep(string)
- AddMissingBp2buildDep(dep string)
-}
-
-// BazelLabelForModuleDeps expects a list of reference to other modules, ("<module>"
-// or ":<module>") and returns a Bazel-compatible label which corresponds to dependencies on the
-// module within the given ctx.
-func BazelLabelForModuleDeps(ctx BazelConversionPathContext, modules []string) bazel.LabelList {
- return BazelLabelForModuleDepsWithFn(ctx, modules, BazelModuleLabel)
-}
-
-// BazelLabelForModuleWholeDepsExcludes expects two lists: modules (containing modules to include in
-// the list), and excludes (modules to exclude from the list). Both of these should contain
-// references to other modules, ("<module>" or ":<module>"). It returns a Bazel-compatible label
-// list which corresponds to dependencies on the module within the given ctx, and the excluded
-// dependencies. Prebuilt dependencies will be appended with _alwayslink so they can be handled as
-// whole static libraries.
-func BazelLabelForModuleDepsExcludes(ctx BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
- return BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, BazelModuleLabel)
-}
-
-// BazelLabelForModuleDepsWithFn expects a list of reference to other modules, ("<module>"
-// or ":<module>") and applies moduleToLabelFn to determine and return a Bazel-compatible label
-// which corresponds to dependencies on the module within the given ctx.
-func BazelLabelForModuleDepsWithFn(ctx BazelConversionPathContext, modules []string,
- moduleToLabelFn func(BazelConversionPathContext, blueprint.Module) string) bazel.LabelList {
- var labels bazel.LabelList
- // In some cases, a nil string list is different than an explicitly empty list.
- if len(modules) == 0 && modules != nil {
- labels.Includes = []bazel.Label{}
- return labels
- }
- modules = FirstUniqueStrings(modules)
- for _, module := range modules {
- bpText := module
- if m := SrcIsModule(module); m == "" {
- module = ":" + module
- }
- if m, t := SrcIsModuleWithTag(module); m != "" {
- l := getOtherModuleLabel(ctx, m, t, moduleToLabelFn)
- if l != nil {
- l.OriginalModuleName = bpText
- labels.Includes = append(labels.Includes, *l)
- }
- } else {
- ctx.ModuleErrorf("%q, is not a module reference", module)
- }
- }
- return labels
-}
-
-// BazelLabelForModuleDepsExcludesWithFn expects two lists: modules (containing modules to include in the
-// list), and excludes (modules to exclude from the list). Both of these should contain references
-// to other modules, ("<module>" or ":<module>"). It applies moduleToLabelFn to determine and return a
-// Bazel-compatible label list which corresponds to dependencies on the module within the given ctx, and
-// the excluded dependencies.
-func BazelLabelForModuleDepsExcludesWithFn(ctx BazelConversionPathContext, modules, excludes []string,
- moduleToLabelFn func(BazelConversionPathContext, blueprint.Module) string) bazel.LabelList {
- moduleLabels := BazelLabelForModuleDepsWithFn(ctx, RemoveListFromList(modules, excludes), moduleToLabelFn)
- if len(excludes) == 0 {
- return moduleLabels
- }
- excludeLabels := BazelLabelForModuleDepsWithFn(ctx, excludes, moduleToLabelFn)
- return bazel.LabelList{
- Includes: moduleLabels.Includes,
- Excludes: excludeLabels.Includes,
- }
-}
-
-func BazelLabelForModuleSrcSingle(ctx BazelConversionPathContext, path string) bazel.Label {
- if srcs := BazelLabelForModuleSrcExcludes(ctx, []string{path}, []string(nil)).Includes; len(srcs) > 0 {
- return srcs[0]
- }
- return bazel.Label{}
-}
-
-func BazelLabelForModuleDepSingle(ctx BazelConversionPathContext, path string) bazel.Label {
- if srcs := BazelLabelForModuleDepsExcludes(ctx, []string{path}, []string(nil)).Includes; len(srcs) > 0 {
- return srcs[0]
- }
- return bazel.Label{}
-}
-
-// BazelLabelForModuleSrc expects a list of path (relative to local module directory) and module
-// references (":<module>") and returns a bazel.LabelList{} containing the resolved references in
-// paths, relative to the local module, or Bazel-labels (absolute if in a different package or
-// relative if within the same package).
-// Properties must have been annotated with struct tag `android:"path"` so that dependencies modules
-// will have already been handled by the pathdeps mutator.
-func BazelLabelForModuleSrc(ctx BazelConversionPathContext, paths []string) bazel.LabelList {
- return BazelLabelForModuleSrcExcludes(ctx, paths, []string(nil))
-}
-
-// BazelLabelForModuleSrc expects lists of path and excludes (relative to local module directory)
-// and module references (":<module>") and returns a bazel.LabelList{} containing the resolved
-// references in paths, minus those in excludes, relative to the local module, or Bazel-labels
-// (absolute if in a different package or relative if within the same package).
-// Properties must have been annotated with struct tag `android:"path"` so that dependencies modules
-// will have already been handled by the pathdeps mutator.
-func BazelLabelForModuleSrcExcludes(ctx BazelConversionPathContext, paths, excludes []string) bazel.LabelList {
- excludeLabels := expandSrcsForBazel(ctx, excludes, []string(nil))
- excluded := make([]string, 0, len(excludeLabels.Includes))
- for _, e := range excludeLabels.Includes {
- excluded = append(excluded, e.Label)
- }
- labels := expandSrcsForBazel(ctx, paths, excluded)
- labels.Excludes = excludeLabels.Includes
- labels = TransformSubpackagePaths(ctx.Config(), ctx.ModuleDir(), labels)
- return labels
-}
-
-func BazelLabelForSrcPatternExcludes(ctx BazelConversionPathContext, dir, pattern string, excludes []string) bazel.LabelList {
- topRelPaths, err := ctx.GlobWithDeps(filepath.Join(dir, pattern), excludes)
- if err != nil {
- ctx.ModuleErrorf("Could not search dir: %s for pattern %s due to %v\n", dir, pattern, err)
- }
- // An intermediate list of labels relative to `dir` that assumes that there no subpacakges beneath `dir`
- dirRelLabels := []bazel.Label{}
- for _, topRelPath := range topRelPaths {
- dirRelPath := Rel(ctx, dir, topRelPath)
- dirRelLabels = append(dirRelLabels, bazel.Label{Label: "./" + dirRelPath})
- }
- // Return the package boudary resolved labels
- return TransformSubpackagePaths(ctx.Config(), dir, bazel.MakeLabelList(dirRelLabels))
-}
-
-// Returns true if a prefix + components[:i] is a package boundary.
-//
-// A package boundary is determined by a BUILD file in the directory. This can happen in 2 cases:
-//
-// 1. An Android.bp exists, which bp2build will always convert to a sibling BUILD file.
-// 2. An Android.bp doesn't exist, but a checked-in BUILD/BUILD.bazel file exists, and that file
-// is allowlisted by the bp2build configuration to be merged into the symlink forest workspace.
-func isPackageBoundary(config Config, prefix string, components []string, componentIndex int) bool {
- prefix = filepath.Join(prefix, filepath.Join(components[:componentIndex+1]...))
- if exists, _, _ := config.fs.Exists(filepath.Join(prefix, "Android.bp")); exists {
- return true
- } else if config.Bp2buildPackageConfig.ShouldKeepExistingBuildFileForDir(prefix) {
- if exists, _, _ := config.fs.Exists(filepath.Join(prefix, "BUILD")); exists {
- return true
- } else if exists, _, _ := config.fs.Exists(filepath.Join(prefix, "BUILD.bazel")); exists {
- return true
- }
- }
-
- return false
-}
-
-// Transform a path (if necessary) to acknowledge package boundaries
-//
-// e.g. something like
-//
-// async_safe/include/async_safe/CHECK.h
-//
-// might become
-//
-// //bionic/libc/async_safe:include/async_safe/CHECK.h
-//
-// if the "async_safe" directory is actually a package and not just a directory.
-//
-// In particular, paths that extend into packages are transformed into absolute labels beginning with //.
-func transformSubpackagePath(cfg Config, dir string, path bazel.Label) bazel.Label {
- var newPath bazel.Label
-
- // Don't transform OriginalModuleName
- newPath.OriginalModuleName = path.OriginalModuleName
- // if it wasn't a module, store the original path. We may need the original path to replace
- // references if it is actually in another package
- if path.OriginalModuleName == "" {
- newPath.OriginalModuleName = path.Label
- }
-
- if strings.HasPrefix(path.Label, "//") {
- // Assume absolute labels are already correct (e.g. //path/to/some/package:foo.h)
- newPath.Label = path.Label
- return newPath
- }
- if strings.HasPrefix(path.Label, "./") {
- // Drop "./" for consistent handling of paths.
- // Specifically, to not let "." be considered a package boundary.
- // Say `inputPath` is `x/Android.bp` and that file has some module
- // with `srcs=["y/a.c", "z/b.c"]`.
- // And say the directory tree is:
- // x
- // ├── Android.bp
- // ├── y
- // │ ├── a.c
- // │ └── Android.bp
- // └── z
- // └── b.c
- // Then bazel equivalent labels in srcs should be:
- // //x/y:a.c, x/z/b.c
- // The above should still be the case if `x/Android.bp` had
- // srcs=["./y/a.c", "./z/b.c"]
- // However, if we didn't strip "./", we'd get
- // //x/./y:a.c, //x/.:z/b.c
- path.Label = strings.TrimPrefix(path.Label, "./")
- }
- pathComponents := strings.Split(path.Label, "/")
- newLabel := ""
- foundPackageBoundary := false
- // Check the deepest subdirectory first and work upwards
- for i := len(pathComponents) - 1; i >= 0; i-- {
- pathComponent := pathComponents[i]
- var sep string
- if !foundPackageBoundary && isPackageBoundary(cfg, dir, pathComponents, i) {
- sep = ":"
- foundPackageBoundary = true
- } else {
- sep = "/"
- }
- if newLabel == "" {
- newLabel = pathComponent
- } else {
- newLabel = pathComponent + sep + newLabel
- }
- }
- if foundPackageBoundary {
- // Ensure paths end up looking like //bionic/... instead of //./bionic/...
- moduleDir := dir
- if strings.HasPrefix(moduleDir, ".") {
- moduleDir = moduleDir[1:]
- }
- // Make the path into an absolute label (e.g. //bionic/libc/foo:bar.h instead of just foo:bar.h)
- if moduleDir == "" {
- newLabel = "//" + newLabel
- } else {
- newLabel = "//" + moduleDir + "/" + newLabel
- }
- }
- newPath.Label = newLabel
-
- return newPath
-}
-
-// Transform paths to acknowledge package boundaries
-// See transformSubpackagePath() for more information
-func TransformSubpackagePaths(cfg Config, dir string, paths bazel.LabelList) bazel.LabelList {
- var newPaths bazel.LabelList
- for _, include := range paths.Includes {
- newPaths.Includes = append(newPaths.Includes, transformSubpackagePath(cfg, dir, include))
- }
- for _, exclude := range paths.Excludes {
- newPaths.Excludes = append(newPaths.Excludes, transformSubpackagePath(cfg, dir, exclude))
- }
- return newPaths
-}
-
-// Converts root-relative Paths to a list of bazel.Label relative to the module in ctx.
-func RootToModuleRelativePaths(ctx BazelConversionPathContext, paths Paths) []bazel.Label {
- var newPaths []bazel.Label
- for _, path := range PathsWithModuleSrcSubDir(ctx, paths, "") {
- s := path.Rel()
- newPaths = append(newPaths, bazel.Label{Label: s})
- }
- return newPaths
-}
-
-// expandSrcsForBazel returns bazel.LabelList with paths rooted from the module's local source
-// directory and Bazel target labels, excluding those included in the excludes argument (which
-// should already be expanded to resolve references to Soong-modules). Valid elements of paths
-// include:
-// - filepath, relative to local module directory, resolves as a filepath relative to the local
-// source directory
-// - glob, relative to the local module directory, resolves as filepath(s), relative to the local
-// module directory. Because Soong does not have a concept of crossing package boundaries, the
-// glob as computed by Soong may contain paths that cross package-boundaries that would be
-// unknowingly omitted if the glob were handled by Bazel. To allow identification and detect
-// (within Bazel) use of paths that cross package boundaries, we expand globs within Soong rather
-// than converting Soong glob syntax to Bazel glob syntax. **Invalid for excludes.**
-// - other modules using the ":name{.tag}" syntax. These modules must implement SourceFileProducer
-// or OutputFileProducer. These resolve as a Bazel label for a target. If the Bazel target is in
-// the local module directory, it will be returned relative to the current package (e.g.
-// ":<target>"). Otherwise, it will be returned as an absolute Bazel label (e.g.
-// "//path/to/dir:<target>"). If the reference to another module cannot be resolved,the function
-// will panic.
-//
-// Properties passed as the paths or excludes argument must have been annotated with struct tag
-// `android:"path"` so that dependencies on other modules will have already been handled by the
-// pathdeps mutator.
-func expandSrcsForBazel(ctx BazelConversionPathContext, paths, expandedExcludes []string) bazel.LabelList {
- if paths == nil {
- return bazel.LabelList{}
- }
- labels := bazel.LabelList{
- Includes: []bazel.Label{},
- }
-
- // expandedExcludes contain module-dir relative paths, but root-relative paths
- // are needed for GlobFiles later.
- var rootRelativeExpandedExcludes []string
- for _, e := range expandedExcludes {
- rootRelativeExpandedExcludes = append(rootRelativeExpandedExcludes, filepath.Join(ctx.ModuleDir(), e))
- }
-
- for _, p := range paths {
- if m, tag := SrcIsModuleWithTag(p); m != "" {
- l := getOtherModuleLabel(ctx, m, tag, BazelModuleLabel)
- if l != nil && !InList(l.Label, expandedExcludes) {
- if strings.HasPrefix(m, "//") {
- // this is a module in a soong namespace
- // It appears as //<namespace>:<module_name> in srcs, and not ://<namespace>:<module_name>
- l.OriginalModuleName = m
- } else {
- l.OriginalModuleName = fmt.Sprintf(":%s", m)
- }
- labels.Includes = append(labels.Includes, *l)
- }
- } else {
- var expandedPaths []bazel.Label
- if pathtools.IsGlob(p) {
- // e.g. turn "math/*.c" in
- // external/arm-optimized-routines to external/arm-optimized-routines/math/*.c
- rootRelativeGlobPath := pathForModuleSrc(ctx, p).String()
- expandedPaths = RootToModuleRelativePaths(ctx, GlobFiles(ctx, rootRelativeGlobPath, rootRelativeExpandedExcludes))
- } else {
- if !InList(p, expandedExcludes) {
- expandedPaths = append(expandedPaths, bazel.Label{Label: p})
- }
- }
- labels.Includes = append(labels.Includes, expandedPaths...)
- }
- }
- return labels
-}
-
-// getOtherModuleLabel returns a bazel.Label for the given dependency/tag combination for the
-// module. The label will be relative to the current directory if appropriate. The dependency must
-// already be resolved by either deps mutator or path deps mutator.
-func getOtherModuleLabel(ctx BazelConversionPathContext, dep, tag string,
- labelFromModule func(BazelConversionPathContext, blueprint.Module) string) *bazel.Label {
- m, _ := ctx.ModuleFromName(dep)
- // The module was not found in an Android.bp file, this is often due to:
- // * a limited manifest
- // * a required module not being converted from Android.mk
- if m == nil {
- ctx.AddMissingBp2buildDep(dep)
- return &bazel.Label{
- Label: ":" + dep + "__BP2BUILD__MISSING__DEP",
- }
- }
- if !convertedToBazel(ctx, m) {
- ctx.AddUnconvertedBp2buildDep(dep)
- }
- label := BazelModuleLabel(ctx, ctx.Module())
- otherLabel := labelFromModule(ctx, m)
-
- // TODO(b/165114590): Convert tag (":name{.tag}") to corresponding Bazel implicit output targets.
-
- if samePackage(label, otherLabel) {
- otherLabel = bazelShortLabel(otherLabel)
- }
-
- return &bazel.Label{
- Label: otherLabel,
- }
-}
-
-func BazelModuleLabel(ctx BazelConversionPathContext, module blueprint.Module) string {
- // TODO(b/165114590): Convert tag (":name{.tag}") to corresponding Bazel implicit output targets.
- if !convertedToBazel(ctx, module) || isGoModule(module) {
- return bp2buildModuleLabel(ctx, module)
- }
- b, _ := module.(Bazelable)
- return b.GetBazelLabel(ctx, module)
-}
-
-func bazelShortLabel(label string) string {
- i := strings.Index(label, ":")
- if i == -1 {
- panic(fmt.Errorf("Could not find the ':' character in '%s', expected a fully qualified label.", label))
- }
- return label[i:]
-}
-
-func bazelPackage(label string) string {
- i := strings.Index(label, ":")
- if i == -1 {
- panic(fmt.Errorf("Could not find the ':' character in '%s', expected a fully qualified label.", label))
- }
- return label[0:i]
-}
-
-func samePackage(label1, label2 string) bool {
- return bazelPackage(label1) == bazelPackage(label2)
-}
-
-func bp2buildModuleLabel(ctx BazelConversionContext, module blueprint.Module) string {
- moduleName := moduleNameWithPossibleOverride(ctx, module, ctx.OtherModuleName(module))
- moduleDir := moduleDirWithPossibleOverride(ctx, module, ctx.OtherModuleDir(module))
- if moduleDir == Bp2BuildTopLevel {
- moduleDir = ""
- }
- return fmt.Sprintf("//%s:%s", moduleDir, moduleName)
-}
-
-// BazelOutPath is a Bazel output path compatible to be used for mixed builds within Soong/Ninja.
-type BazelOutPath struct {
- OutputPath
-}
-
-// ensure BazelOutPath implements Path
-var _ Path = BazelOutPath{}
-
-// ensure BazelOutPath implements genPathProvider
-var _ genPathProvider = BazelOutPath{}
-
-// ensure BazelOutPath implements objPathProvider
-var _ objPathProvider = BazelOutPath{}
-
-func (p BazelOutPath) genPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleGenPath {
- return PathForModuleGen(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
-}
-
-func (p BazelOutPath) objPathWithExt(ctx ModuleOutPathContext, subdir, ext string) ModuleObjPath {
- return PathForModuleObj(ctx, subdir, pathtools.ReplaceExtension(p.path, ext))
-}
-
-// PathForBazelOutRelative returns a BazelOutPath representing the path under an output directory dedicated to
-// bazel-owned outputs. Calling .Rel() on the result will give the input path as relative to the given
-// relativeRoot.
-func PathForBazelOutRelative(ctx PathContext, relativeRoot string, path string) BazelOutPath {
- validatedPath, err := validatePath(filepath.Join("execroot", "__main__", path))
- if err != nil {
- reportPathError(ctx, err)
- }
- var relativeRootPath string
- if pathComponents := strings.SplitN(path, "/", 4); len(pathComponents) >= 3 &&
- pathComponents[0] == "bazel-out" && pathComponents[2] == "bin" {
- // If the path starts with something like: bazel-out/linux_x86_64-fastbuild-ST-b4ef1c4402f9/bin/
- // make it relative to that folder. bazel-out/volatile-status.txt is an example
- // of something that starts with bazel-out but is not relative to the bin folder
- relativeRootPath = filepath.Join("execroot", "__main__", pathComponents[0], pathComponents[1], pathComponents[2], relativeRoot)
- } else {
- relativeRootPath = filepath.Join("execroot", "__main__", relativeRoot)
- }
-
- var relPath string
- if relPath, err = filepath.Rel(relativeRootPath, validatedPath); err != nil || strings.HasPrefix(relPath, "../") {
- // We failed to make this path relative to execroot/__main__, fall back to a non-relative path
- // One case where this happens is when path is ../bazel_tools/something
- relativeRootPath = ""
- relPath = validatedPath
- }
-
- outputPath := OutputPath{
- basePath{"", ""},
- ctx.Config().soongOutDir,
- ctx.Config().BazelContext.OutputBase(),
- }
-
- return BazelOutPath{
- // .withRel() appends its argument onto the current path, and only the most
- // recently appended part is returned by outputPath.rel().
- // So outputPath.rel() will return relPath.
- OutputPath: outputPath.withRel(relativeRootPath).withRel(relPath),
- }
-}
-
-// PathForBazelOut returns a BazelOutPath representing the path under an output directory dedicated to
-// bazel-owned outputs.
-func PathForBazelOut(ctx PathContext, path string) BazelOutPath {
- return PathForBazelOutRelative(ctx, "", path)
-}
-
-// PathsForBazelOut returns a list of paths representing the paths under an output directory
-// dedicated to Bazel-owned outputs.
-func PathsForBazelOut(ctx PathContext, paths []string) Paths {
- outs := make(Paths, 0, len(paths))
- for _, p := range paths {
- outs = append(outs, PathForBazelOut(ctx, p))
- }
- return outs
-}
-
-// BazelStringOrLabelFromProp splits a Soong module property that can be
-// either a string literal, path (with android:path tag) or a module reference
-// into separate bazel string or label attributes. Bazel treats string and label
-// attributes as distinct types, so this function categorizes a string property
-// into either one of them.
-//
-// e.g. apex.private_key = "foo.pem" can either refer to:
-//
-// 1. "foo.pem" in the current directory -> file target
-// 2. "foo.pem" module -> rule target
-// 3. "foo.pem" file in a different directory, prefixed by a product variable handled
-// in a bazel macro. -> string literal
-//
-// For the first two cases, they are defined using the label attribute. For the third case,
-// it's defined with the string attribute.
-func BazelStringOrLabelFromProp(
- ctx TopDownMutatorContext,
- propToDistinguish *string) (bazel.LabelAttribute, bazel.StringAttribute) {
-
- var labelAttr bazel.LabelAttribute
- var strAttr bazel.StringAttribute
-
- if propToDistinguish == nil {
- // nil pointer
- return labelAttr, strAttr
- }
-
- prop := String(propToDistinguish)
- if SrcIsModule(prop) != "" {
- // If it's a module (SrcIsModule will return the module name), set the
- // resolved label to the label attribute.
- labelAttr.SetValue(BazelLabelForModuleDepSingle(ctx, prop))
- } else {
- // Not a module name. This could be a string literal or a file target in
- // the current dir. Check if the path exists:
- path := ExistentPathForSource(ctx, ctx.ModuleDir(), prop)
-
- if path.Valid() && parentDir(path.String()) == ctx.ModuleDir() {
- // If it exists and the path is relative to the current dir, resolve the bazel label
- // for the _file target_ and set it to the label attribute.
- //
- // Resolution is necessary because this could be a file in a subpackage.
- labelAttr.SetValue(BazelLabelForModuleSrcSingle(ctx, prop))
- } else {
- // Otherwise, treat it as a string literal and assign to the string attribute.
- strAttr.Value = propToDistinguish
- }
- }
-
- return labelAttr, strAttr
-}
diff --git a/android/bazel_paths_test.go b/android/bazel_paths_test.go
deleted file mode 100644
index bed719c..0000000
--- a/android/bazel_paths_test.go
+++ /dev/null
@@ -1,240 +0,0 @@
-// 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 android
-
-import (
- "fmt"
- "path/filepath"
- "testing"
-
- "android/soong/bazel"
-
- "github.com/google/blueprint"
- "github.com/google/blueprint/pathtools"
-)
-
-type TestBazelPathContext struct{}
-
-func (*TestBazelPathContext) Config() Config {
- cfg := NullConfig("out", "out/soong")
- cfg.BazelContext = MockBazelContext{
- OutputBaseDir: "out/bazel",
- }
- return cfg
-}
-
-func (*TestBazelPathContext) AddNinjaFileDeps(...string) {
- panic("Unimplemented")
-}
-
-func TestPathForBazelOut(t *testing.T) {
- ctx := &TestBazelPathContext{}
- out := PathForBazelOut(ctx, "foo/bar/baz/boq.txt")
- expectedPath := filepath.Join(ctx.Config().BazelContext.OutputBase(), "execroot/__main__/foo/bar/baz/boq.txt")
- if out.String() != expectedPath {
- t.Errorf("incorrect OutputPath: expected %q, got %q", expectedPath, out.String())
- }
-
- expectedRelPath := "foo/bar/baz/boq.txt"
- if out.Rel() != expectedRelPath {
- t.Errorf("incorrect OutputPath.Rel(): expected %q, got %q", expectedRelPath, out.Rel())
- }
-}
-
-func TestPathForBazelOutRelative(t *testing.T) {
- ctx := &TestBazelPathContext{}
- out := PathForBazelOutRelative(ctx, "foo/bar", "foo/bar/baz/boq.txt")
-
- expectedPath := filepath.Join(ctx.Config().BazelContext.OutputBase(), "execroot/__main__/foo/bar/baz/boq.txt")
- if out.String() != expectedPath {
- t.Errorf("incorrect OutputPath: expected %q, got %q", expectedPath, out.String())
- }
-
- expectedRelPath := "baz/boq.txt"
- if out.Rel() != expectedRelPath {
- t.Errorf("incorrect OutputPath.Rel(): expected %q, got %q", expectedRelPath, out.Rel())
- }
-}
-
-func TestPathForBazelOutRelativeUnderBinFolder(t *testing.T) {
- ctx := &TestBazelPathContext{}
- out := PathForBazelOutRelative(ctx, "foo/bar", "bazel-out/linux_x86_64-fastbuild-ST-b4ef1c4402f9/bin/foo/bar/baz/boq.txt")
-
- expectedPath := filepath.Join(ctx.Config().BazelContext.OutputBase(), "execroot/__main__/bazel-out/linux_x86_64-fastbuild-ST-b4ef1c4402f9/bin/foo/bar/baz/boq.txt")
- if out.String() != expectedPath {
- t.Errorf("incorrect OutputPath: expected %q, got %q", expectedPath, out.String())
- }
-
- expectedRelPath := "baz/boq.txt"
- if out.Rel() != expectedRelPath {
- t.Errorf("incorrect OutputPath.Rel(): expected %q, got %q", expectedRelPath, out.Rel())
- }
-}
-
-func TestPathForBazelOutOutsideOfExecroot(t *testing.T) {
- ctx := &TestBazelPathContext{}
- out := PathForBazelOut(ctx, "../bazel_tools/linux_x86_64-fastbuild/bin/tools/android/java_base_extras.jar")
-
- expectedPath := filepath.Join(ctx.Config().BazelContext.OutputBase(), "execroot/bazel_tools/linux_x86_64-fastbuild/bin/tools/android/java_base_extras.jar")
- if out.String() != expectedPath {
- t.Errorf("incorrect OutputPath: expected %q, got %q", expectedPath, out.String())
- }
-
- expectedRelPath := "execroot/bazel_tools/linux_x86_64-fastbuild/bin/tools/android/java_base_extras.jar"
- if out.Rel() != expectedRelPath {
- t.Errorf("incorrect OutputPath.Rel(): expected %q, got %q", expectedRelPath, out.Rel())
- }
-}
-
-func TestPathForBazelOutRelativeWithParentDirectoryRoot(t *testing.T) {
- ctx := &TestBazelPathContext{}
- out := PathForBazelOutRelative(ctx, "../bazel_tools", "../bazel_tools/foo/bar/baz.sh")
-
- expectedPath := filepath.Join(ctx.Config().BazelContext.OutputBase(), "execroot/bazel_tools/foo/bar/baz.sh")
- if out.String() != expectedPath {
- t.Errorf("incorrect OutputPath: expected %q, got %q", expectedPath, out.String())
- }
-
- expectedRelPath := "foo/bar/baz.sh"
- if out.Rel() != expectedRelPath {
- t.Errorf("incorrect OutputPath.Rel(): expected %q, got %q", expectedRelPath, out.Rel())
- }
-}
-
-type TestBazelConversionPathContext struct {
- TestBazelConversionContext
- moduleDir string
- cfg Config
- mockGlobResults *[]string
-}
-
-func (ctx *TestBazelConversionPathContext) AddNinjaFileDeps(...string) {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) GlobWithDeps(string, []string) ([]string, error) {
- if ctx.mockGlobResults == nil {
- return []string{}, fmt.Errorf("Set mock glob results first")
- }
- return *ctx.mockGlobResults, nil
-}
-
-func (ctx *TestBazelConversionPathContext) PropertyErrorf(string, string, ...interface{}) {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) GetDirectDep(string) (blueprint.Module, blueprint.DependencyTag) {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) ModuleFromName(string) (blueprint.Module, bool) {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) AddUnconvertedBp2buildDep(string) {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) AddMissingBp2buildDep(string) {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) Module() Module {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) Config() Config {
- return ctx.cfg
-}
-
-func (ctx *TestBazelConversionPathContext) ModuleDir() string {
- return ctx.moduleDir
-}
-
-func (ctx *TestBazelConversionPathContext) ModuleName() string {
- panic("Unimplemented")
-}
-
-func (ctx *TestBazelConversionPathContext) ModuleType() string {
- panic("Unimplemented")
-}
-
-func TestTransformSubpackagePath(t *testing.T) {
- cfg := NullConfig("out", "out/soong")
- cfg.fs = pathtools.MockFs(map[string][]byte{
- "x/Android.bp": nil,
- "x/y/Android.bp": nil,
- })
-
- var ctx BazelConversionPathContext = &TestBazelConversionPathContext{
- moduleDir: "x",
- cfg: cfg,
- }
- pairs := map[string]string{
- "y/a.c": "//x/y:a.c",
- "./y/a.c": "//x/y:a.c",
- "z/b.c": "z/b.c",
- "./z/b.c": "z/b.c",
- }
- for in, out := range pairs {
- actual := transformSubpackagePath(ctx.Config(), ctx.ModuleDir(), bazel.Label{Label: in}).Label
- if actual != out {
- t.Errorf("expected:\n%v\nactual:\n%v", out, actual)
- }
- }
-}
-
-// Check that the files in a specific directory are returned with labels that respect package boundaries
-// Since the test uses a mock for GlobWithDeps, the params passed to BazelLabelForSrcPatternExcludes are no-ops
-func TestBazelLabelForSrcPatternExcludes(t *testing.T) {
- cfg := NullConfig("out", "out/soong")
- cfg.fs = pathtools.MockFs(map[string][]byte{
- "x/Android.bp": nil,
- "x/y/Android.bp": nil,
- // .proto files
- "foo.proto": nil,
- "x/bar.proto": nil,
- "x/baz.proto": nil,
- "x/y/qux.proto": nil,
- })
-
- var ctx BazelConversionPathContext = &TestBazelConversionPathContext{
- cfg: cfg,
- }
-
- // Root dir
- ctx.(*TestBazelConversionPathContext).mockGlobResults = &[]string{"foo.proto", "x/bar.proto", "x/baz.proto", "x/y/qux.proto"}
- actualLabelsFromRoot := BazelLabelForSrcPatternExcludes(ctx, ".", "**/*.proto", []string{})
- expectedLabelsAsString := []string{"foo.proto", "//x:bar.proto", "//x:baz.proto", "//x/y:qux.proto"}
- for i, actual := range actualLabelsFromRoot.Includes {
- AssertStringEquals(t, "Error in finding src labels relative to root directory", expectedLabelsAsString[i], actual.Label)
- }
-
- // x dir
- ctx.(*TestBazelConversionPathContext).mockGlobResults = &[]string{"x/bar.proto", "x/baz.proto", "x/y/qux.proto"}
- actualLabelsFromRoot = BazelLabelForSrcPatternExcludes(ctx, "x", "**/*.proto", []string{})
- expectedLabelsAsString = []string{"bar.proto", "baz.proto", "//x/y:qux.proto"}
- for i, actual := range actualLabelsFromRoot.Includes {
- AssertStringEquals(t, "Error in finding src labels relative to x directory", expectedLabelsAsString[i], actual.Label)
- }
-
- // y dir
- ctx.(*TestBazelConversionPathContext).mockGlobResults = &[]string{"x/y/qux.proto"}
- actualLabelsFromRoot = BazelLabelForSrcPatternExcludes(ctx, "x/y", "**/*.proto", []string{})
- expectedLabelsAsString = []string{"qux.proto"}
- for i, actual := range actualLabelsFromRoot.Includes {
- AssertStringEquals(t, "Error in finding src labels relative to x/y directory", expectedLabelsAsString[i], actual.Label)
- }
-}
diff --git a/android/bazel_test.go b/android/bazel_test.go
deleted file mode 100644
index 15d3a6b..0000000
--- a/android/bazel_test.go
+++ /dev/null
@@ -1,592 +0,0 @@
-// 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 android
-
-import (
- "fmt"
- "testing"
-
- "android/soong/android/allowlists"
- "android/soong/bazel"
-
- "github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
-)
-
-func TestConvertAllModulesInPackage(t *testing.T) {
- testCases := []struct {
- prefixes allowlists.Bp2BuildConfig
- packageDir string
- }{
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
- "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultTrueRecursively,
- "d/e/f": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultFalse,
- "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
- "a/b/c": allowlists.Bp2BuildDefaultFalse,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultTrueRecursively,
- "a/b": allowlists.Bp2BuildDefaultFalse,
- "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultFalseRecursively,
- "a/b": allowlists.Bp2BuildDefaultTrue,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultFalseRecursively,
- "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a/b/c",
- },
- }
-
- for _, test := range testCases {
- if ok, _ := bp2buildDefaultTrueRecursively(test.packageDir, test.prefixes); !ok {
- t.Errorf("Expected to convert all modules in %s based on %v, but failed.", test.packageDir, test.prefixes)
- }
- }
-}
-
-func TestModuleOptIn(t *testing.T) {
- testCases := []struct {
- prefixes allowlists.Bp2BuildConfig
- packageDir string
- }{
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a/b": allowlists.Bp2BuildDefaultFalse,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultFalse,
- "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a", // opt-in by default
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultTrueRecursively,
- "d/e/f": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "foo/bar",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultTrueRecursively,
- "a/b": allowlists.Bp2BuildDefaultFalse,
- "a/b/c": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- packageDir: "a/b",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultFalse,
- "a/b": allowlists.Bp2BuildDefaultTrueRecursively,
- "a/b/c": allowlists.Bp2BuildDefaultFalse,
- },
- packageDir: "a",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultFalseRecursively,
- "a/b": allowlists.Bp2BuildDefaultTrue,
- },
- packageDir: "a/b/c",
- },
- {
- prefixes: allowlists.Bp2BuildConfig{
- "a": allowlists.Bp2BuildDefaultTrueRecursively,
- "a/b": allowlists.Bp2BuildDefaultFalseRecursively,
- },
- packageDir: "a/b/c",
- },
- }
-
- for _, test := range testCases {
- if ok, _ := bp2buildDefaultTrueRecursively(test.packageDir, test.prefixes); ok {
- t.Errorf("Expected to allow module opt-in in %s based on %v, but failed.", test.packageDir, test.prefixes)
- }
- }
-}
-
-type TestBazelModule struct {
- bazel.TestModuleInfo
- BazelModuleBase
-}
-
-var _ blueprint.Module = TestBazelModule{}
-
-func (m TestBazelModule) Name() string {
- return m.TestModuleInfo.ModuleName
-}
-
-func (m TestBazelModule) GenerateBuildActions(blueprint.ModuleContext) {
-}
-
-type TestBazelConversionContext struct {
- omc bazel.OtherModuleTestContext
- allowlist Bp2BuildConversionAllowlist
- errors []string
-}
-
-var _ bazelOtherModuleContext = &TestBazelConversionContext{}
-
-func (bcc *TestBazelConversionContext) OtherModuleType(m blueprint.Module) string {
- return bcc.omc.OtherModuleType(m)
-}
-
-func (bcc *TestBazelConversionContext) OtherModuleName(m blueprint.Module) string {
- return bcc.omc.OtherModuleName(m)
-}
-
-func (bcc *TestBazelConversionContext) OtherModuleDir(m blueprint.Module) string {
- return bcc.omc.OtherModuleDir(m)
-}
-
-func (bcc *TestBazelConversionContext) ModuleErrorf(format string, args ...interface{}) {
- bcc.errors = append(bcc.errors, fmt.Sprintf(format, args...))
-}
-
-func (bcc *TestBazelConversionContext) Config() Config {
- return Config{
- &config{
- Bp2buildPackageConfig: bcc.allowlist,
- },
- }
-}
-
-var bazelableBazelModuleBase = BazelModuleBase{
- bazelProperties: properties{
- Bazel_module: BazelModuleProperties{
- CanConvertToBazel: true,
- },
- },
-}
-
-func TestBp2BuildAllowlist(t *testing.T) {
- testCases := []struct {
- description string
- shouldConvert bool
- expectedErrors []string
- module TestBazelModule
- allowlist Bp2BuildConversionAllowlist
- }{
- {
- description: "allowlist enables module",
- shouldConvert: true,
- module: TestBazelModule{
- TestModuleInfo: bazel.TestModuleInfo{
- ModuleName: "foo",
- Typ: "rule1",
- Dir: "dir1",
- },
- BazelModuleBase: bazelableBazelModuleBase,
- },
- allowlist: Bp2BuildConversionAllowlist{
- moduleAlwaysConvert: map[string]bool{
- "foo": true,
- },
- },
- },
- {
- description: "module in name allowlist and type allowlist fails",
- shouldConvert: false,
- expectedErrors: []string{"A module \"foo\" of type \"rule1\" cannot be in moduleAlwaysConvert and also be in moduleTypeAlwaysConvert"},
- module: TestBazelModule{
- TestModuleInfo: bazel.TestModuleInfo{
- ModuleName: "foo",
- Typ: "rule1",
- Dir: "dir1",
- },
- BazelModuleBase: bazelableBazelModuleBase,
- },
- allowlist: Bp2BuildConversionAllowlist{
- moduleAlwaysConvert: map[string]bool{
- "foo": true,
- },
- moduleTypeAlwaysConvert: map[string]bool{
- "rule1": true,
- },
- },
- },
- {
- description: "module in allowlist and denylist fails",
- shouldConvert: false,
- expectedErrors: []string{"a module \"foo\" cannot be in moduleDoNotConvert and also be in moduleAlwaysConvert"},
- module: TestBazelModule{
- TestModuleInfo: bazel.TestModuleInfo{
- ModuleName: "foo",
- Typ: "rule1",
- Dir: "dir1",
- },
- BazelModuleBase: bazelableBazelModuleBase,
- },
- allowlist: Bp2BuildConversionAllowlist{
- moduleAlwaysConvert: map[string]bool{
- "foo": true,
- },
- moduleDoNotConvert: map[string]bool{
- "foo": true,
- },
- },
- },
- {
- description: "module allowlist and enabled directory",
- shouldConvert: false,
- expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir' Module: 'foo'"},
- module: TestBazelModule{
- TestModuleInfo: bazel.TestModuleInfo{
- ModuleName: "foo",
- Typ: "rule1",
- Dir: "existing/build/dir",
- },
- BazelModuleBase: bazelableBazelModuleBase,
- },
- allowlist: Bp2BuildConversionAllowlist{
- moduleAlwaysConvert: map[string]bool{
- "foo": true,
- },
- defaultConfig: allowlists.Bp2BuildConfig{
- "existing/build/dir": allowlists.Bp2BuildDefaultTrue,
- },
- },
- },
- {
- description: "module allowlist and enabled subdirectory",
- shouldConvert: false,
- expectedErrors: []string{"A module cannot be in a directory marked Bp2BuildDefaultTrue or Bp2BuildDefaultTrueRecursively and also be in moduleAlwaysConvert. Directory: 'existing/build/dir' Module: 'foo'"},
- module: TestBazelModule{
- TestModuleInfo: bazel.TestModuleInfo{
- ModuleName: "foo",
- Typ: "rule1",
- Dir: "existing/build/dir/subdir",
- },
- BazelModuleBase: bazelableBazelModuleBase,
- },
- allowlist: Bp2BuildConversionAllowlist{
- moduleAlwaysConvert: map[string]bool{
- "foo": true,
- },
- defaultConfig: allowlists.Bp2BuildConfig{
- "existing/build/dir": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- },
- },
- {
- description: "module enabled in unit test short-circuits other allowlists",
- shouldConvert: true,
- module: TestBazelModule{
- TestModuleInfo: bazel.TestModuleInfo{
- ModuleName: "foo",
- Typ: "rule1",
- Dir: ".",
- },
- BazelModuleBase: BazelModuleBase{
- bazelProperties: properties{
- Bazel_module: BazelModuleProperties{
- CanConvertToBazel: true,
- Bp2build_available: proptools.BoolPtr(true),
- },
- },
- },
- },
- allowlist: Bp2BuildConversionAllowlist{
- moduleAlwaysConvert: map[string]bool{
- "foo": true,
- },
- moduleDoNotConvert: map[string]bool{
- "foo": true,
- },
- },
- },
- }
-
- for _, test := range testCases {
- t.Run(test.description, func(t *testing.T) {
- bcc := &TestBazelConversionContext{
- omc: bazel.OtherModuleTestContext{
- Modules: []bazel.TestModuleInfo{
- test.module.TestModuleInfo,
- },
- },
- allowlist: test.allowlist,
- }
-
- shouldConvert := test.module.shouldConvertWithBp2build(bcc,
- shouldConvertParams{
- module: test.module.TestModuleInfo,
- moduleDir: test.module.TestModuleInfo.Dir,
- moduleType: test.module.TestModuleInfo.Typ,
- moduleName: test.module.TestModuleInfo.ModuleName,
- },
- )
- if test.shouldConvert != shouldConvert {
- t.Errorf("Module shouldConvert expected to be: %v, but was: %v", test.shouldConvert, shouldConvert)
- }
-
- errorsMatch := true
- if len(test.expectedErrors) != len(bcc.errors) {
- errorsMatch = false
- } else {
- for i, err := range test.expectedErrors {
- if err != bcc.errors[i] {
- errorsMatch = false
- }
- }
- }
- if !errorsMatch {
- t.Errorf("Expected errors to be: %v, but were: %v", test.expectedErrors, bcc.errors)
- }
- })
- }
-}
-
-func TestBp2buildAllowList(t *testing.T) {
- allowlist := GetBp2BuildAllowList()
- for k, v := range allowlists.Bp2buildDefaultConfig {
- if allowlist.defaultConfig[k] != v {
- t.Errorf("bp2build default config of %s: expected: %v, got: %v", k, v, allowlist.defaultConfig[k])
- }
- }
- for k, v := range allowlists.Bp2buildKeepExistingBuildFile {
- if allowlist.keepExistingBuildFile[k] != v {
- t.Errorf("bp2build keep existing build file of %s: expected: %v, got: %v", k, v, allowlist.keepExistingBuildFile[k])
- }
- }
- for _, k := range allowlists.Bp2buildModuleTypeAlwaysConvertList {
- if !allowlist.moduleTypeAlwaysConvert[k] {
- t.Errorf("bp2build module type always convert of %s: expected: true, got: %v", k, allowlist.moduleTypeAlwaysConvert[k])
- }
- }
- for _, k := range allowlists.Bp2buildModuleDoNotConvertList {
- if !allowlist.moduleDoNotConvert[k] {
- t.Errorf("bp2build module do not convert of %s: expected: true, got: %v", k, allowlist.moduleDoNotConvert[k])
- }
- }
-}
-
-func TestShouldKeepExistingBuildFileForDir(t *testing.T) {
- allowlist := NewBp2BuildAllowlist()
- // entry "a/b2/c2" is moot because of its parent "a/b2"
- allowlist.SetKeepExistingBuildFile(map[string]bool{"a": false, "a/b1": false, "a/b2": true, "a/b1/c1": true, "a/b2/c2": false})
- truths := []string{"a", "a/b1", "a/b2", "a/b1/c1", "a/b2/c", "a/b2/c2", "a/b2/c2/d"}
- falsities := []string{"a1", "a/b", "a/b1/c"}
- for _, dir := range truths {
- if !allowlist.ShouldKeepExistingBuildFileForDir(dir) {
- t.Errorf("%s expected TRUE but was FALSE", dir)
- }
- }
- for _, dir := range falsities {
- if allowlist.ShouldKeepExistingBuildFileForDir(dir) {
- t.Errorf("%s expected FALSE but was TRUE", dir)
- }
- }
-}
-
-type mixedBuildModule struct {
- ModuleBase
- BazelModuleBase
- props struct {
- Deps []string
- Mixed_build_incompatible *bool
- QueuedBazelCall bool `blueprint:"mutated"`
- }
-}
-
-type mixedBuildModuleInfo struct {
- QueuedBazelCall bool
-}
-
-var mixedBuildModuleProvider = blueprint.NewProvider(mixedBuildModuleInfo{})
-
-func mixedBuildModuleFactory() Module {
- m := &mixedBuildModule{}
- m.AddProperties(&m.props)
- InitAndroidArchModule(m, HostAndDeviceDefault, MultilibBoth)
- InitBazelModule(m)
-
- return m
-}
-
-func (m *mixedBuildModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
-}
-
-func (m *mixedBuildModule) DepsMutator(ctx BottomUpMutatorContext) {
- ctx.AddDependency(ctx.Module(), installDepTag{}, m.props.Deps...)
-}
-
-func (m *mixedBuildModule) GenerateAndroidBuildActions(ctx ModuleContext) {
-}
-
-func (m *mixedBuildModule) IsMixedBuildSupported(ctx BaseModuleContext) bool {
- return !proptools.Bool(m.props.Mixed_build_incompatible)
-}
-
-func (m *mixedBuildModule) QueueBazelCall(ctx BaseModuleContext) {
- m.props.QueuedBazelCall = true
-}
-
-func (m *mixedBuildModule) ProcessBazelQueryResponse(ctx ModuleContext) {
- ctx.SetProvider(mixedBuildModuleProvider, mixedBuildModuleInfo{
- QueuedBazelCall: m.props.QueuedBazelCall,
- })
-}
-
-var prepareForMixedBuildTests = FixtureRegisterWithContext(func(ctx RegistrationContext) {
- ctx.RegisterModuleType("deps", mixedBuildModuleFactory)
- RegisterMixedBuildsMutator(ctx)
-})
-
-func TestMixedBuildsEnabledForType(t *testing.T) {
- baseBp := `
- deps {
- name: "foo",
- deps: ["bar"],
- target: { windows: { enabled: true } },
- %s
- }
-`
- depBp := `
- deps {
- name: "bar",
- target: {
- windows: {
- enabled: true,
- },
- },
- }
-`
- testCases := []struct {
- desc string
- variant *string
- missingDeps bool
- extraBpInfo string
- mixedBuildsEnabled bool
- }{
- {
- desc: "mixed builds works",
- mixedBuildsEnabled: true,
- extraBpInfo: `bazel_module: { bp2build_available: true },`,
- },
- {
- desc: "missing deps",
- missingDeps: true,
- mixedBuildsEnabled: false,
- extraBpInfo: `bazel_module: { bp2build_available: true },`,
- },
- {
- desc: "windows no mixed builds",
- mixedBuildsEnabled: false,
- variant: proptools.StringPtr("windows_x86"),
- extraBpInfo: `bazel_module: { bp2build_available: true },`,
- },
- {
- desc: "mixed builds disabled by type",
- mixedBuildsEnabled: false,
- extraBpInfo: `mixed_build_incompatible: true,
- bazel_module: { bp2build_available: true },`,
- },
- {
- desc: "mixed builds not bp2build available",
- mixedBuildsEnabled: false,
- extraBpInfo: `bazel_module: { bp2build_available: false },`,
- },
- }
-
- for _, tc := range testCases {
- t.Run(tc.desc, func(t *testing.T) {
- handlers := GroupFixturePreparers(
- prepareForMixedBuildTests,
- PrepareForTestWithArchMutator,
- FixtureModifyConfig(func(config Config) {
- config.BazelContext = MockBazelContext{
- OutputBaseDir: "base",
- }
- config.Targets[Windows] = []Target{
- {Windows, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", true},
- {Windows, Arch{ArchType: X86}, NativeBridgeDisabled, "", "", true},
- }
- }),
- )
- bp := fmt.Sprintf(baseBp, tc.extraBpInfo)
- if tc.missingDeps {
- handlers = GroupFixturePreparers(
- handlers,
- PrepareForTestWithAllowMissingDependencies,
- )
- } else {
- bp += depBp
- }
- result := handlers.RunTestWithBp(t, bp)
-
- variant := proptools.StringDefault(tc.variant, "android_arm64_armv8-a")
-
- m := result.ModuleForTests("foo", variant)
- mixedBuildModuleInfo := result.TestContext.ModuleProvider(m.Module(), mixedBuildModuleProvider).(mixedBuildModuleInfo)
- if w, g := tc.mixedBuildsEnabled, mixedBuildModuleInfo.QueuedBazelCall; w != g {
- t.Errorf("Expected mixed builds enabled %t, got mixed builds enabled %t", w, g)
- }
- })
- }
-}
diff --git a/android/config.go b/android/config.go
index 645a263..d94a86f 100644
--- a/android/config.go
+++ b/android/config.go
@@ -18,6 +18,7 @@
// product variables necessary for soong_build's operation.
import (
+ "android/soong/shared"
"encoding/json"
"fmt"
"os"
@@ -84,22 +85,14 @@
SoongOutDir string
SoongVariables string
- SymlinkForestMarker string
- Bp2buildMarker string
- BazelQueryViewDir string
- ModuleGraphFile string
- ModuleActionsFile string
- DocFile string
+ BazelQueryViewDir string
+ ModuleGraphFile string
+ ModuleActionsFile string
+ DocFile string
MultitreeBuild bool
- BazelMode bool
- BazelModeStaging bool
- BazelForceEnabledModules string
-
- UseBazelProxy bool
-
- BuildFromTextStub bool
+ BuildFromSourceStub bool
EnsureAllowlistIntegrity bool
}
@@ -109,12 +102,6 @@
// Don't use bazel at all during module analysis.
AnalysisNoBazel SoongBuildMode = iota
- // Symlink fores mode: merge two directory trees into a symlink forest
- SymlinkForest
-
- // Bp2build mode: Generate BUILD files from blueprint files and exit.
- Bp2build
-
// Generate BUILD files which faithfully represent the dependency graph of
// blueprint modules. Individual BUILD targets will not, however, faitfhully
// express build semantics.
@@ -125,15 +112,6 @@
// Generate a documentation file for module type definitions and exit.
GenerateDocFile
-
- // Use bazel during analysis of a few allowlisted build modules. The allowlist
- // is considered "staging, as these are modules being prepared to be released
- // into prod mode shortly after.
- BazelStagingMode
-
- // Use bazel during analysis of build modules from an allowlist carefully
- // curated by the build team to be proven stable.
- BazelProdMode
)
// SoongOutDir returns the build output directory for the configuration.
@@ -141,6 +119,11 @@
return c.soongOutDir
}
+// tempDir returns the path to out/soong/.temp, which is cleared at the beginning of every build.
+func (c Config) tempDir() string {
+ return shared.TempDirForOutDir(c.soongOutDir)
+}
+
func (c Config) OutDir() string {
return c.outDir
}
@@ -179,6 +162,15 @@
Bool(c.productVariables.Eng))
}
+// DisableVerifyOverlaps returns true if verify_overlaps is skipped.
+// Mismatch in version of apexes and module SDK is required for mainline prebuilts to work in
+// trunk stable.
+// Thus, verify_overlaps is disabled when RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE is set to false.
+// TODO(b/308174018): Re-enable verify_overlaps for both builr from source/mainline prebuilts.
+func (c Config) DisableVerifyOverlaps() bool {
+ return c.IsEnvTrue("DISABLE_VERIFY_OVERLAPS") || !c.ReleaseDefaultModuleBuildFromSource()
+}
+
// MaxPageSizeSupported returns the max page size supported by the device. This
// value will define the ELF segment alignment for binaries (executables and
// shared libraries).
@@ -186,10 +178,12 @@
return String(c.config.productVariables.DeviceMaxPageSizeSupported)
}
-// PageSizeAgnostic returns true when AOSP is page size agnostic,
-// othersise it returns false.
-func (c Config) PageSizeAgnostic() bool {
- return Bool(c.config.productVariables.DevicePageSizeAgnostic)
+// NoBionicPageSizeMacro returns true when AOSP is page size agnostic.
+// This means that the bionic's macro PAGE_SIZE won't be defined.
+// Returns false when AOSP is NOT page size agnostic.
+// This means that bionic's macro PAGE_SIZE is defined.
+func (c Config) NoBionicPageSizeMacro() bool {
+ return Bool(c.config.productVariables.DeviceNoBionicPageSizeMacro)
}
// The release version passed to aconfig, derived from RELEASE_VERSION
@@ -197,7 +191,7 @@
return c.config.productVariables.ReleaseVersion
}
-// The flag values files passed to aconfig, derived from RELEASE_VERSION
+// The aconfig value set passed to aconfig, derived from RELEASE_VERSION
func (c Config) ReleaseAconfigValueSets() []string {
return c.config.productVariables.ReleaseAconfigValueSets
}
@@ -208,6 +202,22 @@
return c.config.productVariables.ReleaseAconfigFlagDefaultPermission
}
+// The flag indicating behavior for the tree wrt building modules or using prebuilts
+// derived from RELEASE_DEFAULT_MODULE_BUILD_FROM_SOURCE
+func (c Config) ReleaseDefaultModuleBuildFromSource() bool {
+ return c.config.productVariables.ReleaseDefaultModuleBuildFromSource == nil ||
+ Bool(c.config.productVariables.ReleaseDefaultModuleBuildFromSource)
+}
+
+// Enables ABI monitoring of NDK libraries
+func (c Config) ReleaseNdkAbiMonitored() bool {
+ return c.config.productVariables.GetBuildFlagBool("RELEASE_NDK_ABI_MONITORED")
+}
+
+func (c Config) ReleaseHiddenApiExportableStubs() bool {
+ return c.config.productVariables.GetBuildFlagBool("RELEASE_HIDDEN_API_EXPORTABLE_STUBS")
+}
+
// A DeviceConfig object represents the configuration for a particular device
// being built. For now there will only be one of these, but in the future there
// may be multiple devices being built.
@@ -227,10 +237,6 @@
// Only available on configs created by TestConfig
TestProductVariables *ProductVariables
- // A specialized context object for Bazel/Soong mixed builds and migration
- // purposes.
- BazelContext BazelContext
-
ProductVariablesFileName string
// BuildOS stores the OsType for the OS that the build is running on.
@@ -272,9 +278,7 @@
fs pathtools.FileSystem
mockBpList string
- BuildMode SoongBuildMode
- Bp2buildPackageConfig Bp2BuildConversionAllowlist
- Bp2buildSoongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions
+ BuildMode SoongBuildMode
// If MultitreeBuild is true then this is one inner tree of a multitree
// build directed by the multitree orchestrator.
@@ -290,32 +294,9 @@
OncePer
- // These fields are only used for metrics collection. A module should be added
- // to these maps only if its implementation supports Bazel handling in mixed
- // builds. A module being in the "enabled" list indicates that there is a
- // variant of that module for which bazel-handling actually took place.
- // A module being in the "disabled" list indicates that there is a variant of
- // that module for which bazel-handling was denied.
- mixedBuildsLock sync.Mutex
- mixedBuildEnabledModules map[string]struct{}
- mixedBuildDisabledModules map[string]struct{}
-
- // These are modules to be built with Bazel beyond the allowlisted/build-mode
- // specified modules. They are passed via the command-line flag
- // "--bazel-force-enabled-modules"
- bazelForceEnabledModules map[string]struct{}
-
- // Names of Bazel targets as defined by BUILD files in the source tree,
- // keyed by the directory in which they are defined.
- bazelTargetsByDir map[string][]string
-
- // If true, for any requests to Bazel, communicate with a Bazel proxy using
- // unix sockets, instead of spawning Bazel as a subprocess.
- UseBazelProxy bool
-
- // If buildFromTextStub is true then the Java API stubs are
- // built from the signature text files, not the source Java files.
- buildFromTextStub bool
+ // If buildFromSourceStub is true then the Java API stubs are
+ // built from the source Java files, not the signature text files.
+ buildFromSourceStub bool
// If ensureAllowlistIntegrity is true, then the presence of any allowlisted
// modules that aren't mixed-built for at least one variant will cause a build
@@ -523,24 +504,18 @@
runGoTests: cmdArgs.RunGoTests,
multilibConflicts: make(map[ArchType]bool),
- moduleListFile: cmdArgs.ModuleListFile,
- fs: pathtools.NewOsFs(absSrcDir),
- mixedBuildDisabledModules: make(map[string]struct{}),
- mixedBuildEnabledModules: make(map[string]struct{}),
- bazelForceEnabledModules: make(map[string]struct{}),
+ moduleListFile: cmdArgs.ModuleListFile,
+ fs: pathtools.NewOsFs(absSrcDir),
MultitreeBuild: cmdArgs.MultitreeBuild,
- UseBazelProxy: cmdArgs.UseBazelProxy,
- buildFromTextStub: cmdArgs.BuildFromTextStub,
+ buildFromSourceStub: cmdArgs.BuildFromSourceStub,
}
config.deviceConfig = &deviceConfig{
config: config,
}
- config.productVariables.Build_from_text_stub = boolPtr(config.buildFromTextStub)
-
// Soundness check of the build and source directories. This won't catch strange
// configurations with symlinks, but at least checks the obvious case.
absBuildDir, err := filepath.Abs(cmdArgs.SoongOutDir)
@@ -625,28 +600,9 @@
config.BuildMode = mode
}
}
- setBazelMode := func(arg bool, argName string, mode SoongBuildMode) {
- if arg {
- if config.BuildMode != AnalysisNoBazel {
- fmt.Fprintf(os.Stderr, "buildMode is already set, illegal argument: %s", argName)
- os.Exit(1)
- }
- config.BuildMode = mode
- }
- }
- setBuildMode(cmdArgs.SymlinkForestMarker, SymlinkForest)
- setBuildMode(cmdArgs.Bp2buildMarker, Bp2build)
setBuildMode(cmdArgs.BazelQueryViewDir, GenerateQueryView)
setBuildMode(cmdArgs.ModuleGraphFile, GenerateModuleGraph)
setBuildMode(cmdArgs.DocFile, GenerateDocFile)
- setBazelMode(cmdArgs.BazelMode, "--bazel-mode", BazelProdMode)
- setBazelMode(cmdArgs.BazelModeStaging, "--bazel-mode-staging", BazelStagingMode)
-
- for _, module := range getForceEnabledModulesFromFlag(cmdArgs.BazelForceEnabledModules) {
- config.bazelForceEnabledModules[module] = struct{}{}
- }
- config.BazelContext, err = NewBazelContext(config)
- config.Bp2buildPackageConfig = GetBp2BuildAllowList()
// TODO(b/276958307): Replace the hardcoded list to a sdk_library local prop.
config.apiLibraries = map[string]struct{}{
@@ -659,9 +615,12 @@
"framework-connectivity": {},
"framework-connectivity-t": {},
"framework-graphics": {},
+ "framework-location": {},
"framework-media": {},
"framework-mediaprovider": {},
+ "framework-nfc": {},
"framework-ondevicepersonalization": {},
+ "framework-pdf": {},
"framework-permission": {},
"framework-permission-s": {},
"framework-scheduling": {},
@@ -675,14 +634,9 @@
"i18n.module.public.api": {},
}
- return Config{config}, err
-}
+ config.productVariables.Build_from_text_stub = boolPtr(config.BuildFromTextStub())
-func getForceEnabledModulesFromFlag(forceEnabledFlag string) []string {
- if forceEnabledFlag == "" {
- return []string{}
- }
- return strings.Split(forceEnabledFlag, ",")
+ return Config{config}, err
}
// mockFileSystem replaces all reads with accesses to the provided map of
@@ -715,41 +669,6 @@
c.mockBpList = blueprint.MockModuleListFile
}
-// TODO(b/265062549): Add a field to our collected (and uploaded) metrics which
-// describes a reason that we fell back to non-mixed builds.
-// Returns true if "Bazel builds" is enabled. In this mode, part of build
-// analysis is handled by Bazel.
-func (c *config) IsMixedBuildsEnabled() bool {
- globalMixedBuildsSupport := c.Once(OnceKey{"globalMixedBuildsSupport"}, func() interface{} {
- if c.productVariables.DeviceArch != nil && *c.productVariables.DeviceArch == "riscv64" {
- return false
- }
- // Disable Bazel when Kythe is running
- if c.EmitXrefRules() {
- return false
- }
- if c.IsEnvTrue("GLOBAL_THINLTO") {
- return false
- }
- if len(c.productVariables.SanitizeHost) > 0 {
- return false
- }
- if len(c.productVariables.SanitizeDevice) > 0 {
- return false
- }
- if len(c.productVariables.SanitizeDeviceDiag) > 0 {
- return false
- }
- if len(c.productVariables.SanitizeDeviceArch) > 0 {
- return false
- }
- return true
- }).(bool)
-
- bazelModeEnabled := c.BuildMode == BazelProdMode || c.BuildMode == BazelStagingMode
- return globalMixedBuildsSupport && bazelModeEnabled
-}
-
func (c *config) SetAllowMissingDependencies() {
c.productVariables.Allow_missing_dependencies = proptools.BoolPtr(true)
}
@@ -765,7 +684,7 @@
}
func (c *config) HostToolPath(ctx PathContext, tool string) Path {
- path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "bin", false, tool)
+ path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "bin", tool)
return path
}
@@ -774,12 +693,12 @@
if runtime.GOOS == "darwin" {
ext = ".dylib"
}
- path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "lib64", false, lib+ext)
+ path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "lib64", lib+ext)
return path
}
func (c *config) HostJavaToolPath(ctx PathContext, tool string) Path {
- path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "framework", false, tool)
+ path := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "framework", tool)
return path
}
@@ -788,7 +707,7 @@
if ctx.Config().BuildArch.Multilib == "lib64" {
libDir = "lib64"
}
- return pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, libDir, false, lib+".so")
+ return pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, libDir, lib+".so")
}
// PrebuiltOS returns the name of the host OS used in prebuilts directories.
@@ -876,6 +795,10 @@
return c.katiEnabled
}
+func (c *config) ProductVariables() ProductVariables {
+ return c.productVariables
+}
+
func (c *config) BuildId() string {
return String(c.productVariables.BuildId)
}
@@ -986,12 +909,18 @@
func (c *config) PreviewApiLevels() []ApiLevel {
var levels []ApiLevel
- for i, codename := range c.PlatformVersionActiveCodenames() {
+ i := 0
+ for _, codename := range c.PlatformVersionActiveCodenames() {
+ if codename == "REL" {
+ continue
+ }
+
levels = append(levels, ApiLevel{
value: codename,
number: i,
isPreview: true,
})
+ i++
}
return levels
}
@@ -1015,8 +944,6 @@
// DefaultAppTargetSdk returns the API level that platform apps are targeting.
// This converts a codename to the exact ApiLevel it represents.
func (c *config) DefaultAppTargetSdk(ctx EarlyModuleContext) ApiLevel {
- // This logic is replicated in starlark, if changing logic here update starlark code too
- // https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/common/api.bzl;l=72;drc=231c7e8c8038fd478a79eb68aa5b9f5c64e0e061
if Bool(c.productVariables.Platform_sdk_final) {
return c.PlatformSdkVersion()
}
@@ -1374,14 +1301,18 @@
return String(c.productVariables.PrebuiltHiddenApiDir)
}
-func (c *config) BazelModulesForceEnabledByFlag() map[string]struct{} {
- return c.bazelForceEnabledModules
-}
-
func (c *config) IsVndkDeprecated() bool {
return !Bool(c.productVariables.KeepVndk)
}
+func (c *config) VendorApiLevel() string {
+ return String(c.productVariables.VendorApiLevel)
+}
+
+func (c *config) VendorApiLevelFrozen() bool {
+ return c.productVariables.GetBuildFlagBool("RELEASE_BOARD_API_LEVEL_FROZEN")
+}
+
func (c *deviceConfig) Arches() []Arch {
var arches []Arch
for _, target := range c.config.Targets[Android] {
@@ -1421,16 +1352,12 @@
return String(c.config.productVariables.Platform_vndk_version)
}
-func (c *deviceConfig) ProductVndkVersion() string {
- return String(c.config.productVariables.ProductVndkVersion)
-}
-
func (c *deviceConfig) ExtraVndkVersions() []string {
return c.config.productVariables.ExtraVndkVersions
}
func (c *deviceConfig) VndkUseCoreVariant() bool {
- return Bool(c.config.productVariables.VndkUseCoreVariant)
+ return Bool(c.config.productVariables.VndkUseCoreVariant) && Bool(c.config.productVariables.KeepVndk)
}
func (c *deviceConfig) SystemSdkVersions() []string {
@@ -1930,6 +1857,10 @@
return InList(name, c.config.productVariables.BuildBrokenInputDirModules)
}
+func (c *deviceConfig) BuildBrokenDontCheckSystemSdk() bool {
+ return c.config.productVariables.BuildBrokenDontCheckSystemSdk
+}
+
func (c *config) BuildWarningBadOptionalUsesLibsAllowlist() []string {
return c.productVariables.BuildWarningBadOptionalUsesLibsAllowlist
}
@@ -1990,39 +1921,6 @@
return Bool(c.productVariables.HostMusl)
}
-func (c *config) GetMixedBuildsEnabledModules() map[string]struct{} {
- return c.mixedBuildEnabledModules
-}
-
-func (c *config) GetMixedBuildsDisabledModules() map[string]struct{} {
- return c.mixedBuildDisabledModules
-}
-
-func (c *config) LogMixedBuild(ctx BaseModuleContext, useBazel bool) {
- moduleName := ctx.Module().Name()
- c.mixedBuildsLock.Lock()
- defer c.mixedBuildsLock.Unlock()
- if useBazel {
- c.mixedBuildEnabledModules[moduleName] = struct{}{}
- } else {
- c.mixedBuildDisabledModules[moduleName] = struct{}{}
- }
-}
-
-func (c *config) HasBazelBuildTargetInSource(ctx BaseModuleContext) bool {
- moduleName := ctx.Module().Name()
- for _, buildTarget := range c.bazelTargetsByDir[ctx.ModuleDir()] {
- if moduleName == buildTarget {
- return true
- }
- }
- return false
-}
-
-func (c *config) SetBazelBuildFileTargets(bazelTargetsByDir map[string][]string) {
- c.bazelTargetsByDir = bazelTargetsByDir
-}
-
// ApiSurfaces directory returns the source path inside the api_surfaces repo
// (relative to workspace root).
func (c *config) ApiSurfacesDir(s ApiSurface, version string) string {
@@ -2034,21 +1932,28 @@
version)
}
+func (c *config) JavaCoverageEnabled() bool {
+ return c.IsEnvTrue("EMMA_INSTRUMENT") || c.IsEnvTrue("EMMA_INSTRUMENT_STATIC") || c.IsEnvTrue("EMMA_INSTRUMENT_FRAMEWORK")
+}
+
+func (c *deviceConfig) BuildFromSourceStub() bool {
+ return Bool(c.config.productVariables.BuildFromSourceStub)
+}
+
func (c *config) BuildFromTextStub() bool {
- return c.buildFromTextStub
+ // TODO: b/302320354 - Remove the coverage build specific logic once the
+ // robust solution for handling native properties in from-text stub build
+ // is implemented.
+ return !c.buildFromSourceStub &&
+ !c.JavaCoverageEnabled() &&
+ !c.deviceConfig.BuildFromSourceStub()
}
func (c *config) SetBuildFromTextStub(b bool) {
- c.buildFromTextStub = b
+ c.buildFromSourceStub = !b
c.productVariables.Build_from_text_stub = boolPtr(b)
}
-func (c *config) AddForceEnabledModules(forceEnabled []string) {
- for _, forceEnabledModule := range forceEnabled {
- c.bazelForceEnabledModules[forceEnabledModule] = struct{}{}
- }
-}
-
func (c *config) SetApiLibraries(libs []string) {
c.apiLibraries = make(map[string]struct{})
for _, lib := range libs {
@@ -2063,3 +1968,50 @@
func (c *deviceConfig) CheckVendorSeappViolations() bool {
return Bool(c.config.productVariables.CheckVendorSeappViolations)
}
+
+func (c *config) GetBuildFlag(name string) (string, bool) {
+ val, ok := c.productVariables.BuildFlags[name]
+ return val, ok
+}
+
+func (c *config) UseResourceProcessorByDefault() bool {
+ return c.productVariables.GetBuildFlagBool("RELEASE_USE_RESOURCE_PROCESSOR_BY_DEFAULT")
+}
+
+var (
+ mainlineApexContributionBuildFlags = []string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES",
+ "RELEASE_APEX_CONTRIBUTIONS_APPSEARCH",
+ "RELEASE_APEX_CONTRIBUTIONS_ART",
+ "RELEASE_APEX_CONTRIBUTIONS_BLUETOOTH",
+ "RELEASE_APEX_CONTRIBUTIONS_CONFIGINFRASTRUCTURE",
+ "RELEASE_APEX_CONTRIBUTIONS_CONNECTIVITY",
+ "RELEASE_APEX_CONTRIBUTIONS_CONSCRYPT",
+ "RELEASE_APEX_CONTRIBUTIONS_CRASHRECOVERY",
+ "RELEASE_APEX_CONTRIBUTIONS_DEVICELOCK",
+ "RELEASE_APEX_CONTRIBUTIONS_HEALTHFITNESS",
+ "RELEASE_APEX_CONTRIBUTIONS_IPSEC",
+ "RELEASE_APEX_CONTRIBUTIONS_MEDIA",
+ "RELEASE_APEX_CONTRIBUTIONS_MEDIAPROVIDER",
+ "RELEASE_APEX_CONTRIBUTIONS_ONDEVICEPERSONALIZATION",
+ "RELEASE_APEX_CONTRIBUTIONS_PERMISSION",
+ "RELEASE_APEX_CONTRIBUTIONS_REMOTEKEYPROVISIONING",
+ "RELEASE_APEX_CONTRIBUTIONS_SCHEDULING",
+ "RELEASE_APEX_CONTRIBUTIONS_SDKEXTENSIONS",
+ "RELEASE_APEX_CONTRIBUTIONS_STATSD",
+ "RELEASE_APEX_CONTRIBUTIONS_UWB",
+ "RELEASE_APEX_CONTRIBUTIONS_WIFI",
+ }
+)
+
+// Returns the list of _selected_ apex_contributions
+// Each mainline module will have one entry in the list
+func (c *config) AllApexContributions() []string {
+ ret := []string{}
+ for _, f := range mainlineApexContributionBuildFlags {
+ if val, exists := c.GetBuildFlag(f); exists && val != "" {
+ ret = append(ret, val)
+ }
+ }
+ return ret
+}
diff --git a/android/config_bp2build.go b/android/config_bp2build.go
index 2beeb51..4c2fb5e 100644
--- a/android/config_bp2build.go
+++ b/android/config_bp2build.go
@@ -15,24 +15,11 @@
package android
import (
- "fmt"
- "reflect"
- "regexp"
- "sort"
"strings"
- "android/soong/bazel"
- "android/soong/starlark_fmt"
-
"github.com/google/blueprint"
)
-// BazelVarExporter is a collection of configuration variables that can be exported for use in Bazel rules
-type BazelVarExporter interface {
- // asBazel expands strings of configuration variables into their concrete values
- asBazel(Config, ExportedStringVariables, ExportedStringListVariables, ExportedConfigDependingVariables) []bazelConstant
-}
-
// ExportedVariables is a collection of interdependent configuration variables
type ExportedVariables struct {
// Maps containing toolchain variables that are independent of the
@@ -61,18 +48,6 @@
}
}
-func (ev ExportedVariables) asBazel(config Config,
- stringVars ExportedStringVariables, stringListVars ExportedStringListVariables, cfgDepVars ExportedConfigDependingVariables) []bazelConstant {
- ret := []bazelConstant{}
- ret = append(ret, ev.exportedStringVars.asBazel(config, stringVars, stringListVars, cfgDepVars)...)
- ret = append(ret, ev.exportedStringListVars.asBazel(config, stringVars, stringListVars, cfgDepVars)...)
- ret = append(ret, ev.exportedStringListDictVars.asBazel(config, stringVars, stringListVars, cfgDepVars)...)
- // Note: ExportedVariableReferenceDictVars collections can only contain references to other variables and must be printed last
- ret = append(ret, ev.exportedVariableReferenceDictVars.asBazel(config, stringVars, stringListVars, cfgDepVars)...)
- ret = append(ret, ev.exportedConfigDependingVars.asBazel(config, stringVars, stringListVars, cfgDepVars)...)
- return ret
-}
-
// ExportStringStaticVariable declares a static string variable and exports it to
// Bazel's toolchain.
func (ev ExportedVariables) ExportStringStaticVariable(name string, value string) {
@@ -142,49 +117,6 @@
m[k] = v
}
-func (m ExportedConfigDependingVariables) asBazel(config Config,
- stringVars ExportedStringVariables, stringListVars ExportedStringListVariables, cfgDepVars ExportedConfigDependingVariables) []bazelConstant {
- ret := make([]bazelConstant, 0, len(m))
- for variable, unevaluatedVar := range m {
- evalFunc := reflect.ValueOf(unevaluatedVar)
- validateVariableMethod(variable, evalFunc)
- evaluatedResult := evalFunc.Call([]reflect.Value{reflect.ValueOf(config)})
- evaluatedValue := evaluatedResult[0].Interface().(string)
- expandedVars, err := expandVar(config, evaluatedValue, stringVars, stringListVars, cfgDepVars)
- if err != nil {
- panic(fmt.Errorf("error expanding config variable %s: %s", variable, err))
- }
- if len(expandedVars) > 1 {
- ret = append(ret, bazelConstant{
- variableName: variable,
- internalDefinition: starlark_fmt.PrintStringList(expandedVars, 0),
- })
- } else {
- ret = append(ret, bazelConstant{
- variableName: variable,
- internalDefinition: fmt.Sprintf(`"%s"`, validateCharacters(expandedVars[0])),
- })
- }
- }
- return ret
-}
-
-// Ensure that string s has no invalid characters to be generated into the bzl file.
-func validateCharacters(s string) string {
- for _, c := range []string{`\n`, `"`, `\`} {
- if strings.Contains(s, c) {
- panic(fmt.Errorf("%s contains illegal character %s", s, c))
- }
- }
- return s
-}
-
-type bazelConstant struct {
- variableName string
- internalDefinition string
- sortLast bool
-}
-
// ExportedStringVariables is a mapping of variable names to string values
type ExportedStringVariables map[string]string
@@ -192,25 +124,6 @@
m[k] = v
}
-func (m ExportedStringVariables) asBazel(config Config,
- stringVars ExportedStringVariables, stringListVars ExportedStringListVariables, cfgDepVars ExportedConfigDependingVariables) []bazelConstant {
- ret := make([]bazelConstant, 0, len(m))
- for k, variableValue := range m {
- expandedVar, err := expandVar(config, variableValue, stringVars, stringListVars, cfgDepVars)
- if err != nil {
- panic(fmt.Errorf("error expanding config variable %s: %s", k, err))
- }
- if len(expandedVar) > 1 {
- panic(fmt.Errorf("%s expands to more than one string value: %s", variableValue, expandedVar))
- }
- ret = append(ret, bazelConstant{
- variableName: k,
- internalDefinition: fmt.Sprintf(`"%s"`, validateCharacters(expandedVar[0])),
- })
- }
- return ret
-}
-
// ExportedStringListVariables is a mapping of variable names to a list of strings
type ExportedStringListVariables map[string][]string
@@ -218,32 +131,6 @@
m[k] = v
}
-func (m ExportedStringListVariables) asBazel(config Config,
- stringScope ExportedStringVariables, stringListScope ExportedStringListVariables,
- exportedVars ExportedConfigDependingVariables) []bazelConstant {
- ret := make([]bazelConstant, 0, len(m))
- // For each exported variable, recursively expand elements in the variableValue
- // list to ensure that interpolated variables are expanded according to their values
- // in the variable scope.
- for k, variableValue := range m {
- var expandedVars []string
- for _, v := range variableValue {
- expandedVar, err := expandVar(config, v, stringScope, stringListScope, exportedVars)
- if err != nil {
- panic(fmt.Errorf("Error expanding config variable %s=%s: %s", k, v, err))
- }
- expandedVars = append(expandedVars, expandedVar...)
- }
- // Assign the list as a bzl-private variable; this variable will be exported
- // out through a constants struct later.
- ret = append(ret, bazelConstant{
- variableName: k,
- internalDefinition: starlark_fmt.PrintStringList(expandedVars, 0),
- })
- }
- return ret
-}
-
// ExportedStringListDictVariables is a mapping from variable names to a
// dictionary which maps keys to lists of strings
type ExportedStringListDictVariables map[string]map[string][]string
@@ -252,19 +139,6 @@
m[k] = v
}
-// Since dictionaries are not supported in Ninja, we do not expand variables for dictionaries
-func (m ExportedStringListDictVariables) asBazel(_ Config, _ ExportedStringVariables,
- _ ExportedStringListVariables, _ ExportedConfigDependingVariables) []bazelConstant {
- ret := make([]bazelConstant, 0, len(m))
- for k, dict := range m {
- ret = append(ret, bazelConstant{
- variableName: k,
- internalDefinition: starlark_fmt.PrintStringListDict(dict, 0),
- })
- }
- return ret
-}
-
// ExportedVariableReferenceDictVariables is a mapping from variable names to a
// dictionary which references previously defined variables. This is used to
// create a Starlark output such as:
@@ -281,237 +155,3 @@
func (m ExportedVariableReferenceDictVariables) set(k string, v map[string]string) {
m[k] = v
}
-
-func (m ExportedVariableReferenceDictVariables) asBazel(_ Config, _ ExportedStringVariables,
- _ ExportedStringListVariables, _ ExportedConfigDependingVariables) []bazelConstant {
- ret := make([]bazelConstant, 0, len(m))
- for n, dict := range m {
- for k, v := range dict {
- matches, err := variableReference(v)
- if err != nil {
- panic(err)
- } else if !matches.matches {
- panic(fmt.Errorf("Expected a variable reference, got %q", v))
- } else if len(matches.fullVariableReference) != len(v) {
- panic(fmt.Errorf("Expected only a variable reference, got %q", v))
- }
- dict[k] = "_" + matches.variable
- }
- ret = append(ret, bazelConstant{
- variableName: n,
- internalDefinition: starlark_fmt.PrintDict(dict, 0),
- sortLast: true,
- })
- }
- return ret
-}
-
-// BazelToolchainVars expands an ExportedVariables collection and returns a string
-// of formatted Starlark variable definitions
-func BazelToolchainVars(config Config, exportedVars ExportedVariables) string {
- results := exportedVars.asBazel(
- config,
- exportedVars.exportedStringVars,
- exportedVars.exportedStringListVars,
- exportedVars.exportedConfigDependingVars,
- )
-
- sort.Slice(results, func(i, j int) bool {
- if results[i].sortLast != results[j].sortLast {
- return !results[i].sortLast
- }
- return results[i].variableName < results[j].variableName
- })
-
- definitions := make([]string, 0, len(results))
- constants := make([]string, 0, len(results))
- for _, b := range results {
- definitions = append(definitions,
- fmt.Sprintf("_%s = %s", b.variableName, b.internalDefinition))
- constants = append(constants,
- fmt.Sprintf("%[1]s%[2]s = _%[2]s,", starlark_fmt.Indention(1), b.variableName))
- }
-
- // Build the exported constants struct.
- ret := bazel.GeneratedBazelFileWarning
- ret += "\n\n"
- ret += strings.Join(definitions, "\n\n")
- ret += "\n\n"
- ret += "constants = struct(\n"
- ret += strings.Join(constants, "\n")
- ret += "\n)"
-
- return ret
-}
-
-type match struct {
- matches bool
- fullVariableReference string
- variable string
-}
-
-func variableReference(input string) (match, error) {
- // e.g. "${ExternalCflags}"
- r := regexp.MustCompile(`\${(?:config\.)?([a-zA-Z0-9_]+)}`)
-
- matches := r.FindStringSubmatch(input)
- if len(matches) == 0 {
- return match{}, nil
- }
- if len(matches) != 2 {
- return match{}, fmt.Errorf("Expected to only match 1 subexpression in %s, got %d", input, len(matches)-1)
- }
- return match{
- matches: true,
- fullVariableReference: matches[0],
- // Index 1 of FindStringSubmatch contains the subexpression match
- // (variable name) of the capture group.
- variable: matches[1],
- }, nil
-}
-
-// expandVar recursively expand interpolated variables in the exportedVars scope.
-//
-// We're using a string slice to track the seen variables to avoid
-// stackoverflow errors with infinite recursion. it's simpler to use a
-// string slice than to handle a pass-by-referenced map, which would make it
-// quite complex to track depth-first interpolations. It's also unlikely the
-// interpolation stacks are deep (n > 1).
-func expandVar(config Config, toExpand string, stringScope ExportedStringVariables,
- stringListScope ExportedStringListVariables, exportedVars ExportedConfigDependingVariables) ([]string, error) {
-
- // Internal recursive function.
- var expandVarInternal func(string, map[string]bool) (string, error)
- expandVarInternal = func(toExpand string, seenVars map[string]bool) (string, error) {
- var ret string
- remainingString := toExpand
- for len(remainingString) > 0 {
- matches, err := variableReference(remainingString)
- if err != nil {
- panic(err)
- }
- if !matches.matches {
- return ret + remainingString, nil
- }
- matchIndex := strings.Index(remainingString, matches.fullVariableReference)
- ret += remainingString[:matchIndex]
- remainingString = remainingString[matchIndex+len(matches.fullVariableReference):]
-
- variable := matches.variable
- // toExpand contains a variable.
- if _, ok := seenVars[variable]; ok {
- return ret, fmt.Errorf(
- "Unbounded recursive interpolation of variable: %s", variable)
- }
- // A map is passed-by-reference. Create a new map for
- // this scope to prevent variables seen in one depth-first expansion
- // to be also treated as "seen" in other depth-first traversals.
- newSeenVars := map[string]bool{}
- for k := range seenVars {
- newSeenVars[k] = true
- }
- newSeenVars[variable] = true
- if unexpandedVars, ok := stringListScope[variable]; ok {
- expandedVars := []string{}
- for _, unexpandedVar := range unexpandedVars {
- expandedVar, err := expandVarInternal(unexpandedVar, newSeenVars)
- if err != nil {
- return ret, err
- }
- expandedVars = append(expandedVars, expandedVar)
- }
- ret += strings.Join(expandedVars, " ")
- } else if unexpandedVar, ok := stringScope[variable]; ok {
- expandedVar, err := expandVarInternal(unexpandedVar, newSeenVars)
- if err != nil {
- return ret, err
- }
- ret += expandedVar
- } else if unevaluatedVar, ok := exportedVars[variable]; ok {
- evalFunc := reflect.ValueOf(unevaluatedVar)
- validateVariableMethod(variable, evalFunc)
- evaluatedResult := evalFunc.Call([]reflect.Value{reflect.ValueOf(config)})
- evaluatedValue := evaluatedResult[0].Interface().(string)
- expandedVar, err := expandVarInternal(evaluatedValue, newSeenVars)
- if err != nil {
- return ret, err
- }
- ret += expandedVar
- } else {
- return "", fmt.Errorf("Unbound config variable %s", variable)
- }
- }
- return ret, nil
- }
- var ret []string
- stringFields := splitStringKeepingQuotedSubstring(toExpand, ' ')
- for _, v := range stringFields {
- val, err := expandVarInternal(v, map[string]bool{})
- if err != nil {
- return ret, err
- }
- ret = append(ret, val)
- }
-
- return ret, nil
-}
-
-// splitStringKeepingQuotedSubstring splits a string on a provided separator,
-// but it will not split substrings inside unescaped double quotes. If the double
-// quotes are escaped, then the returned string will only include the quote, and
-// not the escape.
-func splitStringKeepingQuotedSubstring(s string, delimiter byte) []string {
- var ret []string
- quote := byte('"')
-
- var substring []byte
- quoted := false
- escaped := false
-
- for i := range s {
- if !quoted && s[i] == delimiter {
- ret = append(ret, string(substring))
- substring = []byte{}
- continue
- }
-
- characterIsEscape := i < len(s)-1 && s[i] == '\\' && s[i+1] == quote
- if characterIsEscape {
- escaped = true
- continue
- }
-
- if s[i] == quote {
- if !escaped {
- quoted = !quoted
- }
- escaped = false
- }
-
- substring = append(substring, s[i])
- }
-
- ret = append(ret, string(substring))
-
- return ret
-}
-
-func validateVariableMethod(name string, methodValue reflect.Value) {
- methodType := methodValue.Type()
- if methodType.Kind() != reflect.Func {
- panic(fmt.Errorf("method given for variable %s is not a function",
- name))
- }
- if n := methodType.NumIn(); n != 1 {
- panic(fmt.Errorf("method for variable %s has %d inputs (should be 1)",
- name, n))
- }
- if n := methodType.NumOut(); n != 1 {
- panic(fmt.Errorf("method for variable %s has %d outputs (should be 1)",
- name, n))
- }
- if kind := methodType.Out(0).Kind(); kind != reflect.String {
- panic(fmt.Errorf("method for variable %s does not return a string",
- name))
- }
-}
diff --git a/android/config_bp2build_test.go b/android/config_bp2build_test.go
deleted file mode 100644
index 1a0ba7b..0000000
--- a/android/config_bp2build_test.go
+++ /dev/null
@@ -1,454 +0,0 @@
-// 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 android
-
-import (
- "android/soong/bazel"
- "testing"
-)
-
-func TestExpandVars(t *testing.T) {
- android_arm64_config := TestConfig("out", nil, "", nil)
- android_arm64_config.BuildOS = Android
- android_arm64_config.BuildArch = Arm64
-
- testCases := []struct {
- description string
- config Config
- stringScope ExportedStringVariables
- stringListScope ExportedStringListVariables
- configVars ExportedConfigDependingVariables
- toExpand string
- expectedValues []string
- }{
- {
- description: "no expansion for non-interpolated value",
- toExpand: "foo",
- expectedValues: []string{"foo"},
- },
- {
- description: "single level expansion for string var",
- stringScope: ExportedStringVariables{
- "foo": "bar",
- },
- toExpand: "${foo}",
- expectedValues: []string{"bar"},
- },
- {
- description: "single level expansion with short-name for string var",
- stringScope: ExportedStringVariables{
- "foo": "bar",
- },
- toExpand: "${config.foo}",
- expectedValues: []string{"bar"},
- },
- {
- description: "single level expansion string list var",
- stringListScope: ExportedStringListVariables{
- "foo": []string{"bar"},
- },
- toExpand: "${foo}",
- expectedValues: []string{"bar"},
- },
- {
- description: "mixed level expansion for string list var",
- stringScope: ExportedStringVariables{
- "foo": "${bar}",
- "qux": "hello",
- },
- stringListScope: ExportedStringListVariables{
- "bar": []string{"baz", "${qux}"},
- },
- toExpand: "${foo}",
- expectedValues: []string{"baz hello"},
- },
- {
- description: "double level expansion",
- stringListScope: ExportedStringListVariables{
- "foo": []string{"${bar}"},
- "bar": []string{"baz"},
- },
- toExpand: "${foo}",
- expectedValues: []string{"baz"},
- },
- {
- description: "double level expansion with a literal",
- stringListScope: ExportedStringListVariables{
- "a": []string{"${b}", "c"},
- "b": []string{"d"},
- },
- toExpand: "${a}",
- expectedValues: []string{"d c"},
- },
- {
- description: "double level expansion, with two variables in a string",
- stringListScope: ExportedStringListVariables{
- "a": []string{"${b} ${c}"},
- "b": []string{"d"},
- "c": []string{"e"},
- },
- toExpand: "${a}",
- expectedValues: []string{"d e"},
- },
- {
- description: "triple level expansion with two variables in a string",
- stringListScope: ExportedStringListVariables{
- "a": []string{"${b} ${c}"},
- "b": []string{"${c}", "${d}"},
- "c": []string{"${d}"},
- "d": []string{"foo"},
- },
- toExpand: "${a}",
- expectedValues: []string{"foo foo foo"},
- },
- {
- description: "expansion with config depending vars",
- configVars: ExportedConfigDependingVariables{
- "a": func(c Config) string { return c.BuildOS.String() },
- "b": func(c Config) string { return c.BuildArch.String() },
- },
- config: android_arm64_config,
- toExpand: "${a}-${b}",
- expectedValues: []string{"android-arm64"},
- },
- {
- description: "double level multi type expansion",
- stringListScope: ExportedStringListVariables{
- "platform": []string{"${os}-${arch}"},
- "const": []string{"const"},
- },
- configVars: ExportedConfigDependingVariables{
- "os": func(c Config) string { return c.BuildOS.String() },
- "arch": func(c Config) string { return c.BuildArch.String() },
- "foo": func(c Config) string { return "foo" },
- },
- config: android_arm64_config,
- toExpand: "${const}/${platform}/${foo}",
- expectedValues: []string{"const/android-arm64/foo"},
- },
- }
-
- for _, testCase := range testCases {
- t.Run(testCase.description, func(t *testing.T) {
- output, _ := expandVar(testCase.config, testCase.toExpand, testCase.stringScope, testCase.stringListScope, testCase.configVars)
- if len(output) != len(testCase.expectedValues) {
- t.Errorf("Expected %d values, got %d", len(testCase.expectedValues), len(output))
- }
- for i, actual := range output {
- expectedValue := testCase.expectedValues[i]
- if actual != expectedValue {
- t.Errorf("Actual value '%s' doesn't match expected value '%s'", actual, expectedValue)
- }
- }
- })
- }
-}
-
-func TestBazelToolchainVars(t *testing.T) {
- testCases := []struct {
- name string
- config Config
- vars ExportedVariables
- expectedOut string
- }{
- {
- name: "exports strings",
- vars: ExportedVariables{
- exportedStringVars: ExportedStringVariables{
- "a": "b",
- "c": "d",
- },
- },
- expectedOut: bazel.GeneratedBazelFileWarning + `
-
-_a = "b"
-
-_c = "d"
-
-constants = struct(
- a = _a,
- c = _c,
-)`,
- },
- {
- name: "exports string lists",
- vars: ExportedVariables{
- exportedStringListVars: ExportedStringListVariables{
- "a": []string{"b1", "b2"},
- "c": []string{"d1", "d2"},
- },
- },
- expectedOut: bazel.GeneratedBazelFileWarning + `
-
-_a = [
- "b1",
- "b2",
-]
-
-_c = [
- "d1",
- "d2",
-]
-
-constants = struct(
- a = _a,
- c = _c,
-)`,
- },
- {
- name: "exports string lists dicts",
- vars: ExportedVariables{
- exportedStringListDictVars: ExportedStringListDictVariables{
- "a": map[string][]string{"b1": {"b2"}},
- "c": map[string][]string{"d1": {"d2"}},
- },
- },
- expectedOut: bazel.GeneratedBazelFileWarning + `
-
-_a = {
- "b1": ["b2"],
-}
-
-_c = {
- "d1": ["d2"],
-}
-
-constants = struct(
- a = _a,
- c = _c,
-)`,
- },
- {
- name: "exports dict with var refs",
- vars: ExportedVariables{
- exportedVariableReferenceDictVars: ExportedVariableReferenceDictVariables{
- "a": map[string]string{"b1": "${b2}"},
- "c": map[string]string{"d1": "${config.d2}"},
- },
- },
- expectedOut: bazel.GeneratedBazelFileWarning + `
-
-_a = {
- "b1": _b2,
-}
-
-_c = {
- "d1": _d2,
-}
-
-constants = struct(
- a = _a,
- c = _c,
-)`,
- },
- {
- name: "sorts across types with variable references last",
- vars: ExportedVariables{
- exportedStringVars: ExportedStringVariables{
- "b": "b-val",
- "d": "d-val",
- },
- exportedStringListVars: ExportedStringListVariables{
- "c": []string{"c-val"},
- "e": []string{"e-val"},
- },
- exportedStringListDictVars: ExportedStringListDictVariables{
- "a": map[string][]string{"a1": {"a2"}},
- "f": map[string][]string{"f1": {"f2"}},
- },
- exportedVariableReferenceDictVars: ExportedVariableReferenceDictVariables{
- "aa": map[string]string{"b1": "${b}"},
- "cc": map[string]string{"d1": "${config.d}"},
- },
- },
- expectedOut: bazel.GeneratedBazelFileWarning + `
-
-_a = {
- "a1": ["a2"],
-}
-
-_b = "b-val"
-
-_c = ["c-val"]
-
-_d = "d-val"
-
-_e = ["e-val"]
-
-_f = {
- "f1": ["f2"],
-}
-
-_aa = {
- "b1": _b,
-}
-
-_cc = {
- "d1": _d,
-}
-
-constants = struct(
- a = _a,
- b = _b,
- c = _c,
- d = _d,
- e = _e,
- f = _f,
- aa = _aa,
- cc = _cc,
-)`,
- },
- }
-
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- out := BazelToolchainVars(tc.config, tc.vars)
- if out != tc.expectedOut {
- t.Errorf("Expected \n%s, got \n%s", tc.expectedOut, out)
- }
- })
- }
-}
-
-func TestSplitStringKeepingQuotedSubstring(t *testing.T) {
- testCases := []struct {
- description string
- s string
- delimiter byte
- split []string
- }{
- {
- description: "empty string returns single empty string",
- s: "",
- delimiter: ' ',
- split: []string{
- "",
- },
- },
- {
- description: "string with single space returns two empty strings",
- s: " ",
- delimiter: ' ',
- split: []string{
- "",
- "",
- },
- },
- {
- description: "string with two spaces returns three empty strings",
- s: " ",
- delimiter: ' ',
- split: []string{
- "",
- "",
- "",
- },
- },
- {
- description: "string with four words returns four word string",
- s: "hello world with words",
- delimiter: ' ',
- split: []string{
- "hello",
- "world",
- "with",
- "words",
- },
- },
- {
- description: "string with words and nested quote returns word strings and quote string",
- s: `hello "world with" words`,
- delimiter: ' ',
- split: []string{
- "hello",
- `"world with"`,
- "words",
- },
- },
- {
- description: "string with escaped quote inside real quotes",
- s: `hello \"world "with\" words"`,
- delimiter: ' ',
- split: []string{
- "hello",
- `"world`,
- `"with" words"`,
- },
- },
- {
- description: "string with words and escaped quotes returns word strings",
- s: `hello \"world with\" words`,
- delimiter: ' ',
- split: []string{
- "hello",
- `"world`,
- `with"`,
- "words",
- },
- },
- {
- description: "string which is single quoted substring returns only substring",
- s: `"hello world with words"`,
- delimiter: ' ',
- split: []string{
- `"hello world with words"`,
- },
- },
- {
- description: "string starting with quote returns quoted string",
- s: `"hello world with" words`,
- delimiter: ' ',
- split: []string{
- `"hello world with"`,
- "words",
- },
- },
- {
- description: "string with starting quote and no ending quote returns quote to end of string",
- s: `hello "world with words`,
- delimiter: ' ',
- split: []string{
- "hello",
- `"world with words`,
- },
- },
- {
- description: "quoted string is treated as a single \"word\" unless separated by delimiter",
- s: `hello "world"with words`,
- delimiter: ' ',
- split: []string{
- "hello",
- `"world"with`,
- "words",
- },
- },
- }
-
- for _, tc := range testCases {
- t.Run(tc.description, func(t *testing.T) {
- split := splitStringKeepingQuotedSubstring(tc.s, tc.delimiter)
- if len(split) != len(tc.split) {
- t.Fatalf("number of split string elements (%d) differs from expected (%d): split string (%v), expected (%v)",
- len(split), len(tc.split), split, tc.split,
- )
- }
- for i := range split {
- if split[i] != tc.split[i] {
- t.Errorf("split string element (%d), %v, differs from expected, %v", i, split[i], tc.split[i])
- }
- }
- })
- }
-}
diff --git a/android/deapexer.go b/android/deapexer.go
index 6a93f60..61ae64e 100644
--- a/android/deapexer.go
+++ b/android/deapexer.go
@@ -15,6 +15,7 @@
package android
import (
+ "fmt"
"strings"
"github.com/google/blueprint"
@@ -78,6 +79,14 @@
//
// See Prebuilt.ApexInfoMutator for more information.
exports map[string]WritablePath
+
+ // name of the java libraries exported from the apex
+ // e.g. core-libart
+ exportedModuleNames []string
+
+ // name of the java libraries exported from the apex that should be dexpreopt'd with the .prof
+ // file embedded in the apex
+ dexpreoptProfileGuidedExportedModuleNames []string
}
// ApexModuleName returns the name of the APEX module that provided the info.
@@ -96,21 +105,34 @@
return path
}
+func (i DeapexerInfo) GetExportedModuleNames() []string {
+ return i.exportedModuleNames
+}
+
// Provider that can be used from within the `GenerateAndroidBuildActions` of a module that depends
// on a `deapexer` module to retrieve its `DeapexerInfo`.
-var DeapexerProvider = blueprint.NewProvider(DeapexerInfo{})
+var DeapexerProvider = blueprint.NewProvider[DeapexerInfo]()
// NewDeapexerInfo creates and initializes a DeapexerInfo that is suitable
// for use with a prebuilt_apex module.
//
// See apex/deapexer.go for more information.
-func NewDeapexerInfo(apexModuleName string, exports map[string]WritablePath) DeapexerInfo {
+func NewDeapexerInfo(apexModuleName string, exports map[string]WritablePath, moduleNames []string) DeapexerInfo {
return DeapexerInfo{
- apexModuleName: apexModuleName,
- exports: exports,
+ apexModuleName: apexModuleName,
+ exports: exports,
+ exportedModuleNames: moduleNames,
}
}
+func (i *DeapexerInfo) GetDexpreoptProfileGuidedExportedModuleNames() []string {
+ return i.dexpreoptProfileGuidedExportedModuleNames
+}
+
+func (i *DeapexerInfo) AddDexpreoptProfileGuidedExportedModuleNames(names ...string) {
+ i.dexpreoptProfileGuidedExportedModuleNames = append(i.dexpreoptProfileGuidedExportedModuleNames, names...)
+}
+
type deapexerTagStruct struct {
blueprint.BaseDependencyTag
}
@@ -133,6 +155,9 @@
// the path to the extracted file will be stored in the DeapexerInfo using the APEX relative file
// path as the key, The path can then be retrieved using the PrebuiltExportPath(key) method.
RequiredFilesFromPrebuiltApex(ctx BaseModuleContext) []string
+
+ // Returns true if a transitive dependency of an apex should use a .prof file to guide dexpreopt
+ UseProfileGuidedDexpreopt() bool
}
// Marker interface that identifies dependencies on modules that may require files from a prebuilt
@@ -146,11 +171,17 @@
// FindDeapexerProviderForModule searches through the direct dependencies of the current context
// module for a DeapexerTag dependency and returns its DeapexerInfo. If a single nonambiguous
-// deapexer module isn't found then errors are reported with ctx.ModuleErrorf and nil is returned.
-func FindDeapexerProviderForModule(ctx ModuleContext) *DeapexerInfo {
+// deapexer module isn't found then it returns it an error
+// clients should check the value of error and call ctx.ModuleErrof if a non nil error is received
+func FindDeapexerProviderForModule(ctx ModuleContext) (*DeapexerInfo, error) {
var di *DeapexerInfo
+ var err error
ctx.VisitDirectDepsWithTag(DeapexerTag, func(m Module) {
- c := ctx.OtherModuleProvider(m, DeapexerProvider).(DeapexerInfo)
+ if err != nil {
+ // An err has been found. Do not visit further.
+ return
+ }
+ c, _ := OtherModuleProvider(ctx, m, DeapexerProvider)
p := &c
if di != nil {
// If two DeapexerInfo providers have been found then check if they are
@@ -159,17 +190,18 @@
di = selected
return
}
- ctx.ModuleErrorf("Multiple installable prebuilt APEXes provide ambiguous deapexers: %s and %s",
- di.ApexModuleName(), p.ApexModuleName())
+ err = fmt.Errorf("Multiple installable prebuilt APEXes provide ambiguous deapexers: %s and %s", di.ApexModuleName(), p.ApexModuleName())
}
di = p
})
- if di != nil {
- return di
+ if err != nil {
+ return nil, err
}
- ai := ctx.Provider(ApexInfoProvider).(ApexInfo)
- ctx.ModuleErrorf("No prebuilt APEX provides a deapexer module for APEX variant %s", ai.ApexVariationName)
- return nil
+ if di != nil {
+ return di, nil
+ }
+ ai, _ := ModuleProvider(ctx, ApexInfoProvider)
+ return nil, fmt.Errorf("No prebuilt APEX provides a deapexer module for APEX variant %s", ai.ApexVariationName)
}
// removeCompressedApexSuffix removes the _compressed suffix from the name if present.
diff --git a/android/defaults.go b/android/defaults.go
index e0e6e5c..ff79002 100644
--- a/android/defaults.go
+++ b/android/defaults.go
@@ -17,7 +17,6 @@
import (
"reflect"
- "android/soong/ui/metrics/bp2build_metrics_proto"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -118,11 +117,6 @@
type DefaultsModuleBase struct {
DefaultableModuleBase
-
- // Included to support setting bazel_module.label for multiple Soong modules to the same Bazel
- // target. This is primarily useful for modules that were architecture specific and instead are
- // handled in Bazel as a select().
- BazelModuleBase
}
// The common pattern for defaults modules is to register separate instances of
@@ -165,7 +159,6 @@
type DefaultsModule interface {
Module
Defaults
- Bazelable
}
func (d *DefaultsModuleBase) properties() []interface{} {
@@ -178,13 +171,6 @@
func (d *DefaultsModuleBase) GenerateAndroidBuildActions(ctx ModuleContext) {}
-// ConvertWithBp2build to fulfill Bazelable interface; however, at this time defaults module are
-// *NOT* converted with bp2build
-func (defaultable *DefaultsModuleBase) ConvertWithBp2build(ctx TopDownMutatorContext) {
- // Defaults types are never convertible.
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
-}
-
func InitDefaultsModule(module DefaultsModule) {
commonProperties := &commonProperties{}
@@ -194,8 +180,6 @@
&ApexProperties{},
&distProperties{})
- // Bazel module must be initialized _before_ Defaults to be included in cc_defaults module.
- InitBazelModule(module)
initAndroidModuleBase(module)
initProductVariableModule(module)
initArchModule(module)
@@ -225,60 +209,10 @@
var _ Defaults = (*DefaultsModuleBase)(nil)
-// applyNamespacedVariableDefaults only runs in bp2build mode for
-// defaultable/defaults modules. Its purpose is to merge namespaced product
-// variable props from defaults deps, even if those defaults are custom module
-// types created from soong_config_module_type, e.g. one that's wrapping a
-// cc_defaults or java_defaults.
-func applyNamespacedVariableDefaults(defaultDep Defaults, ctx TopDownMutatorContext) {
- var dep, b Bazelable
-
- dep, ok := defaultDep.(Bazelable)
- if !ok {
- if depMod, ok := defaultDep.(Module); ok {
- // Track that this dependency hasn't been converted to bp2build yet.
- ctx.AddUnconvertedBp2buildDep(depMod.Name())
- return
- } else {
- panic("Expected default dep to be a Module.")
- }
- }
-
- b, ok = ctx.Module().(Bazelable)
- if !ok {
- return
- }
-
- // namespacedVariableProps is a map from namespaces (e.g. acme, android,
- // vendor_foo) to a slice of soong_config_variable struct pointers,
- // containing properties for that particular module.
- src := dep.namespacedVariableProps()
- dst := b.namespacedVariableProps()
- if dst == nil {
- dst = make(namespacedVariableProperties)
- }
-
- // Propagate all soong_config_variable structs from the dep. We'll merge the
- // actual property values later in variable.go.
- for namespace := range src {
- if dst[namespace] == nil {
- dst[namespace] = []interface{}{}
- }
- for _, i := range src[namespace] {
- dst[namespace] = append(dst[namespace], i)
- }
- }
-
- b.setNamespacedVariableProps(dst)
-}
-
func (defaultable *DefaultableModuleBase) applyDefaults(ctx TopDownMutatorContext,
defaultsList []Defaults) {
for _, defaults := range defaultsList {
- if ctx.Config().BuildMode == Bp2build {
- applyNamespacedVariableDefaults(defaults, ctx)
- }
for _, prop := range defaultable.defaultableProperties {
if prop == defaultable.defaultableVariableProperties {
defaultable.applyDefaultVariableProperties(ctx, defaults, prop)
diff --git a/android/defaults_test.go b/android/defaults_test.go
index a7542ab..0ad0fb8 100644
--- a/android/defaults_test.go
+++ b/android/defaults_test.go
@@ -16,10 +16,13 @@
import (
"testing"
+
+ "github.com/google/blueprint"
)
type defaultsTestProperties struct {
- Foo []string
+ Foo []string
+ Path_prop []string `android:"path"`
}
type defaultsTestModule struct {
@@ -130,3 +133,40 @@
// TODO: missing transitive defaults is currently not handled
_ = missingTransitiveDefaults
}
+
+func TestDefaultsPathProperties(t *testing.T) {
+ bp := `
+ defaults {
+ name: "defaults",
+ path_prop: [":gen"],
+ }
+
+ test {
+ name: "foo",
+ defaults: ["defaults"],
+ }
+
+ test {
+ name: "gen",
+ }
+ `
+
+ result := GroupFixturePreparers(
+ prepareForDefaultsTest,
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
+
+ collectDeps := func(m Module) []string {
+ var deps []string
+ result.VisitDirectDeps(m, func(dep blueprint.Module) {
+ deps = append(deps, result.ModuleName(dep))
+ })
+ return deps
+ }
+
+ foo := result.Module("foo", "")
+ defaults := result.Module("defaults", "")
+
+ AssertStringListContains(t, "foo should depend on gen", collectDeps(foo), "gen")
+ AssertStringListDoesNotContain(t, "defaults should not depend on gen", collectDeps(defaults), "gen")
+}
diff --git a/android/defs.go b/android/defs.go
index b28d2fa..dab012d 100644
--- a/android/defs.go
+++ b/android/defs.go
@@ -15,13 +15,8 @@
package android
import (
- "fmt"
- "strings"
- "testing"
-
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
- "github.com/google/blueprint/proptools"
)
var (
@@ -72,8 +67,7 @@
Command: "if ! cmp -s $in $out; then cp $in $out; fi",
Description: "cp if changed $out",
Restat: true,
- },
- "cpFlags")
+ })
CpExecutable = pctx.AndroidStaticRule("CpExecutable",
blueprint.RuleParams{
@@ -92,9 +86,8 @@
// A symlink rule.
Symlink = pctx.AndroidStaticRule("Symlink",
blueprint.RuleParams{
- Command: "rm -f $out && ln -f -s $fromPath $out",
- Description: "symlink $out",
- SymlinkOutputs: []string{"$out"},
+ Command: "rm -f $out && ln -f -s $fromPath $out",
+ Description: "symlink $out",
},
"fromPath")
@@ -142,110 +135,6 @@
exportedVars.ExportStringList("NeverAllowNoUseIncludeDir", neverallowNoUseIncludeDir)
}
-func BazelCcToolchainVars(config Config) string {
- return BazelToolchainVars(config, exportedVars)
-}
-
-var (
- // echoEscaper escapes a string such that passing it to "echo -e" will produce the input value.
- echoEscaper = strings.NewReplacer(
- `\`, `\\`, // First escape existing backslashes so they aren't interpreted by `echo -e`.
- "\n", `\n`, // Then replace newlines with \n
- )
-
- // echoEscaper reverses echoEscaper.
- echoUnescaper = strings.NewReplacer(
- `\n`, "\n",
- `\\`, `\`,
- )
-
- // shellUnescaper reverses the replacer in proptools.ShellEscape
- shellUnescaper = strings.NewReplacer(`'\''`, `'`)
-)
-
-func buildWriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) {
- content = echoEscaper.Replace(content)
- content = proptools.NinjaEscape(proptools.ShellEscapeIncludingSpaces(content))
- if content == "" {
- content = "''"
- }
- ctx.Build(pctx, BuildParams{
- Rule: writeFile,
- Output: outputFile,
- Description: "write " + outputFile.Base(),
- Args: map[string]string{
- "content": content,
- },
- })
-}
-
-// WriteFileRule creates a ninja rule to write contents to a file. The contents will be escaped
-// so that the file contains exactly the contents passed to the function, plus a trailing newline.
-func WriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) {
- WriteFileRuleVerbatim(ctx, outputFile, content+"\n")
-}
-
-// WriteFileRuleVerbatim creates a ninja rule to write contents to a file. The contents will be
-// escaped so that the file contains exactly the contents passed to the function.
-func WriteFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string) {
- // This is MAX_ARG_STRLEN subtracted with some safety to account for shell escapes
- const SHARD_SIZE = 131072 - 10000
-
- if len(content) > SHARD_SIZE {
- var chunks WritablePaths
- for i, c := range ShardString(content, SHARD_SIZE) {
- tempPath := outputFile.ReplaceExtension(ctx, fmt.Sprintf("%s.%d", outputFile.Ext(), i))
- buildWriteFileRule(ctx, tempPath, c)
- chunks = append(chunks, tempPath)
- }
- ctx.Build(pctx, BuildParams{
- Rule: Cat,
- Inputs: chunks.Paths(),
- Output: outputFile,
- Description: "Merging to " + outputFile.Base(),
- })
- return
- }
- buildWriteFileRule(ctx, outputFile, content)
-}
-
-// WriteExecutableFileRuleVerbatim is the same as WriteFileRuleVerbatim, but runs chmod +x on the result
-func WriteExecutableFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string) {
- intermediate := PathForIntermediates(ctx, "write_executable_file_intermediates").Join(ctx, outputFile.String())
- WriteFileRuleVerbatim(ctx, intermediate, content)
- ctx.Build(pctx, BuildParams{
- Rule: CpExecutable,
- Output: outputFile,
- Input: intermediate,
- })
-}
-
-// shellUnescape reverses proptools.ShellEscape
-func shellUnescape(s string) string {
- // Remove leading and trailing quotes if present
- if len(s) >= 2 && s[0] == '\'' {
- s = s[1 : len(s)-1]
- }
- s = shellUnescaper.Replace(s)
- return s
-}
-
-// ContentFromFileRuleForTests returns the content that was passed to a WriteFileRule for use
-// in tests.
-func ContentFromFileRuleForTests(t *testing.T, params TestingBuildParams) string {
- t.Helper()
- if g, w := params.Rule, writeFile; g != w {
- t.Errorf("expected params.Rule to be %q, was %q", w, g)
- return ""
- }
-
- content := params.Args["content"]
- content = shellUnescape(content)
- content = echoUnescaper.Replace(content)
-
- return content
-}
-
// GlobToListFileRule creates a rule that writes a list of files matching a pattern to a file.
func GlobToListFileRule(ctx ModuleContext, pattern string, excludes []string, file WritablePath) {
bootstrap.GlobFile(ctx.blueprintModuleContext(), pattern, excludes, file.String())
diff --git a/android/early_module_context.go b/android/early_module_context.go
new file mode 100644
index 0000000..8f75773
--- /dev/null
+++ b/android/early_module_context.go
@@ -0,0 +1,169 @@
+// Copyright 2015 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 android
+
+import (
+ "github.com/google/blueprint"
+ "os"
+ "text/scanner"
+)
+
+// EarlyModuleContext provides methods that can be called early, as soon as the properties have
+// been parsed into the module and before any mutators have run.
+type EarlyModuleContext interface {
+ // Module returns the current module as a Module. It should rarely be necessary, as the module already has a
+ // reference to itself.
+ Module() Module
+
+ // ModuleName returns the name of the module. This is generally the value that was returned by Module.Name() when
+ // the module was created, but may have been modified by calls to BaseMutatorContext.Rename.
+ ModuleName() string
+
+ // ModuleDir returns the path to the directory that contains the definition of the module.
+ ModuleDir() string
+
+ // ModuleType returns the name of the module type that was used to create the module, as specified in
+ // RegisterModuleType.
+ ModuleType() string
+
+ // BlueprintFile returns the name of the blueprint file that contains the definition of this
+ // module.
+ BlueprintsFile() string
+
+ // ContainsProperty returns true if the specified property name was set in the module definition.
+ ContainsProperty(name string) bool
+
+ // Errorf reports an error at the specified position of the module definition file.
+ Errorf(pos scanner.Position, fmt string, args ...interface{})
+
+ // ModuleErrorf reports an error at the line number of the module type in the module definition.
+ ModuleErrorf(fmt string, args ...interface{})
+
+ // PropertyErrorf reports an error at the line number of a property in the module definition.
+ PropertyErrorf(property, fmt string, args ...interface{})
+
+ // Failed returns true if any errors have been reported. In most cases the module can continue with generating
+ // build rules after an error, allowing it to report additional errors in a single run, but in cases where the error
+ // has prevented the module from creating necessary data it can return early when Failed returns true.
+ Failed() bool
+
+ // AddNinjaFileDeps adds dependencies on the specified files to the rule that creates the ninja manifest. The
+ // primary builder will be rerun whenever the specified files are modified.
+ AddNinjaFileDeps(deps ...string)
+
+ DeviceSpecific() bool
+ SocSpecific() bool
+ ProductSpecific() bool
+ SystemExtSpecific() bool
+ Platform() bool
+
+ Config() Config
+ DeviceConfig() DeviceConfig
+
+ // Deprecated: use Config()
+ AConfig() Config
+
+ // GlobWithDeps returns a list of files that match the specified pattern but do not match any
+ // of the patterns in excludes. It also adds efficient dependencies to rerun the primary
+ // builder whenever a file matching the pattern as added or removed, without rerunning if a
+ // file that does not match the pattern is added to a searched directory.
+ GlobWithDeps(pattern string, excludes []string) ([]string, error)
+
+ Glob(globPattern string, excludes []string) Paths
+ GlobFiles(globPattern string, excludes []string) Paths
+ IsSymlink(path Path) bool
+ Readlink(path Path) string
+
+ // Namespace returns the Namespace object provided by the NameInterface set by Context.SetNameInterface, or the
+ // default SimpleNameInterface if Context.SetNameInterface was not called.
+ Namespace() *Namespace
+}
+
+// Deprecated: use EarlyModuleContext instead
+type BaseContext interface {
+ EarlyModuleContext
+}
+
+type earlyModuleContext struct {
+ blueprint.EarlyModuleContext
+
+ kind moduleKind
+ config Config
+}
+
+func (e *earlyModuleContext) Glob(globPattern string, excludes []string) Paths {
+ return Glob(e, globPattern, excludes)
+}
+
+func (e *earlyModuleContext) GlobFiles(globPattern string, excludes []string) Paths {
+ return GlobFiles(e, globPattern, excludes)
+}
+
+func (e *earlyModuleContext) IsSymlink(path Path) bool {
+ fileInfo, err := e.config.fs.Lstat(path.String())
+ if err != nil {
+ e.ModuleErrorf("os.Lstat(%q) failed: %s", path.String(), err)
+ }
+ return fileInfo.Mode()&os.ModeSymlink == os.ModeSymlink
+}
+
+func (e *earlyModuleContext) Readlink(path Path) string {
+ dest, err := e.config.fs.Readlink(path.String())
+ if err != nil {
+ e.ModuleErrorf("os.Readlink(%q) failed: %s", path.String(), err)
+ }
+ return dest
+}
+
+func (e *earlyModuleContext) Module() Module {
+ module, _ := e.EarlyModuleContext.Module().(Module)
+ return module
+}
+
+func (e *earlyModuleContext) Config() Config {
+ return e.EarlyModuleContext.Config().(Config)
+}
+
+func (e *earlyModuleContext) AConfig() Config {
+ return e.config
+}
+
+func (e *earlyModuleContext) DeviceConfig() DeviceConfig {
+ return DeviceConfig{e.config.deviceConfig}
+}
+
+func (e *earlyModuleContext) Platform() bool {
+ return e.kind == platformModule
+}
+
+func (e *earlyModuleContext) DeviceSpecific() bool {
+ return e.kind == deviceSpecificModule
+}
+
+func (e *earlyModuleContext) SocSpecific() bool {
+ return e.kind == socSpecificModule
+}
+
+func (e *earlyModuleContext) ProductSpecific() bool {
+ return e.kind == productSpecificModule
+}
+
+func (e *earlyModuleContext) SystemExtSpecific() bool {
+ return e.kind == systemExtSpecificModule
+}
+
+func (e *earlyModuleContext) Namespace() *Namespace {
+ return e.EarlyModuleContext.Namespace().(*Namespace)
+}
diff --git a/android/filegroup.go b/android/filegroup.go
index 6cc9232..bc881ed 100644
--- a/android/filegroup.go
+++ b/android/filegroup.go
@@ -15,16 +15,9 @@
package android
import (
- "path/filepath"
- "regexp"
"strings"
- "android/soong/bazel"
- "android/soong/bazel/cquery"
- "android/soong/ui/metrics/bp2build_metrics_proto"
-
"github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
)
func init() {
@@ -40,185 +33,6 @@
ctx.RegisterModuleType("filegroup_defaults", FileGroupDefaultsFactory)
}
-var convertedProtoLibrarySuffix = "_bp2build_converted"
-
-// IsFilegroup checks that a module is a filegroup type
-func IsFilegroup(ctx bazel.OtherModuleContext, m blueprint.Module) bool {
- return ctx.OtherModuleType(m) == "filegroup"
-}
-
-var (
- // ignoring case, checks for proto or protos as an independent word in the name, whether at the
- // beginning, end, or middle. e.g. "proto.foo", "bar-protos", "baz_proto_srcs" would all match
- filegroupLikelyProtoPattern = regexp.MustCompile("(?i)(^|[^a-z])proto(s)?([^a-z]|$)")
- filegroupLikelyAidlPattern = regexp.MustCompile("(?i)(^|[^a-z])aidl([^a-z]|$)")
-
- ProtoSrcLabelPartition = bazel.LabelPartition{
- Extensions: []string{".proto"},
- LabelMapper: isFilegroupWithPattern(filegroupLikelyProtoPattern),
- }
- AidlSrcLabelPartition = bazel.LabelPartition{
- Extensions: []string{".aidl"},
- LabelMapper: isFilegroupWithPattern(filegroupLikelyAidlPattern),
- }
-)
-
-func isFilegroupWithPattern(pattern *regexp.Regexp) bazel.LabelMapper {
- return func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
- m, exists := ctx.ModuleFromName(label.OriginalModuleName)
- labelStr := label.Label
- if !exists || !IsFilegroup(ctx, m) {
- return labelStr, false
- }
- likelyMatched := pattern.MatchString(label.OriginalModuleName)
- return labelStr, likelyMatched
- }
-}
-
-// https://docs.bazel.build/versions/master/be/general.html#filegroup
-type bazelFilegroupAttributes struct {
- Srcs bazel.LabelListAttribute
- Applicable_licenses bazel.LabelListAttribute
-}
-
-type bazelAidlLibraryAttributes struct {
- Srcs bazel.LabelListAttribute
- 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(
- BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs))
-
- // For Bazel compatibility, don't generate the filegroup if there is only 1
- // source file, and that the source file is named the same as the module
- // itself. In Bazel, eponymous filegroups like this would be an error.
- //
- // Instead, dependents on this single-file filegroup can just depend
- // on the file target, instead of rule target, directly.
- //
- // You may ask: what if a filegroup has multiple files, and one of them
- // shares the name? The answer: we haven't seen that in the wild, and
- // should lock Soong itself down to prevent the behavior. For now,
- // we raise an error if bp2build sees this problem.
- for _, f := range srcs.Value.Includes {
- if f.Label == fg.Name() {
- if len(srcs.Value.Includes) > 1 {
- ctx.ModuleErrorf("filegroup '%s' cannot contain a file with the same name", fg.Name())
- }
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_SRC_NAME_COLLISION, "")
- return
- }
- }
-
- // Convert module that has only AIDL files to aidl_library
- // If the module has a mixed bag of AIDL and non-AIDL files, split the filegroup manually
- // and then convert
- if fg.ShouldConvertToAidlLibrary(ctx) {
- tags := []string{"apex_available=//apex_available:anyapex"}
- attrs := &bazelAidlLibraryAttributes{
- Srcs: srcs,
- Strip_import_prefix: fg.properties.Path,
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "aidl_library",
- Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
- }
-
- ctx.CreateBazelTargetModule(
- props,
- CommonAttributes{
- Name: fg.Name(),
- Tags: bazel.MakeStringListAttribute(tags),
- },
- attrs)
- } else {
- if fg.ShouldConvertToProtoLibrary(ctx) {
- pkgToSrcs := partitionSrcsByPackage(ctx.ModuleDir(), bazel.MakeLabelList(srcs.Value.Includes))
- if len(pkgToSrcs) > 1 {
- ctx.ModuleErrorf("TODO: Add bp2build support for multiple package .protosrcs in filegroup")
- return
- }
- pkg := SortedKeys(pkgToSrcs)[0]
- attrs := &ProtoAttrs{
- Srcs: bazel.MakeLabelListAttribute(pkgToSrcs[pkg]),
- Strip_import_prefix: fg.properties.Path,
- }
-
- tags := []string{
- "apex_available=//apex_available:anyapex",
- // TODO(b/246997908): we can remove this tag if we could figure out a solution for this bug.
- "manual",
- }
- if pkg != ctx.ModuleDir() {
- // Since we are creating the proto_library in a subpackage, create an import_prefix relative to the current package
- if rel, err := filepath.Rel(ctx.ModuleDir(), pkg); err != nil {
- ctx.ModuleErrorf("Could not get relative path for %v %v", pkg, err)
- } else if rel != "." {
- attrs.Import_prefix = &rel
- // Strip the package prefix
- attrs.Strip_import_prefix = proptools.StringPtr("")
- }
- }
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
- CommonAttributes{
- Name: fg.Name() + "_proto",
- Dir: proptools.StringPtr(pkg),
- Tags: bazel.MakeStringListAttribute(tags),
- },
- attrs)
-
- // Create an alias in the current dir. The actual target might exist in a different package, but rdeps
- // can reliabily use this alias
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{Rule_class: "alias"},
- CommonAttributes{
- Name: fg.Name() + convertedProtoLibrarySuffix,
- // TODO(b/246997908): we can remove this tag if we could figure out a solution for this bug.
- Tags: bazel.MakeStringListAttribute(tags),
- },
- &bazelAliasAttributes{
- Actual: bazel.MakeLabelAttribute("//" + pkg + ":" + fg.Name() + "_proto"),
- },
- )
- }
-
- // TODO(b/242847534): Still convert to a filegroup because other unconverted
- // modules may depend on the filegroup
- attrs := &bazelFilegroupAttributes{
- Srcs: srcs,
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "filegroup",
- Bzl_load_location: "//build/bazel/rules:filegroup.bzl",
- }
-
- ctx.CreateBazelTargetModule(props, CommonAttributes{Name: fg.Name()}, attrs)
- }
-}
-
-type FileGroupPath interface {
- GetPath(ctx TopDownMutatorContext) string
-}
-
-func (fg *fileGroup) GetPath(ctx TopDownMutatorContext) string {
- if fg.properties.Path != nil {
- return *fg.properties.Path
- }
- return ""
-}
-
type fileGroupProperties struct {
// srcs lists files that will be included in this filegroup
Srcs []string `android:"path"`
@@ -238,18 +52,15 @@
type fileGroup struct {
ModuleBase
- BazelModuleBase
DefaultableModuleBase
- FileGroupAsLibrary
- FileGroupPath
properties fileGroupProperties
srcs Paths
+
+ // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo
+ mergedAconfigFiles map[string]Paths
}
-var _ MixedBuildBuildable = (*fileGroup)(nil)
var _ SourceFileProducer = (*fileGroup)(nil)
-var _ FileGroupAsLibrary = (*fileGroup)(nil)
-var _ FileGroupPath = (*fileGroup)(nil)
// filegroup contains a list of files that are referenced by other modules
// properties (such as "srcs") using the syntax ":<name>". filegroup are
@@ -258,7 +69,6 @@
module := &fileGroup{}
module.AddProperties(&module.properties)
InitAndroidModule(module)
- InitBazelModule(module)
InitDefaultableModule(module)
return module
}
@@ -285,6 +95,8 @@
if fg.properties.Path != nil {
fg.srcs = PathsWithModuleSrcSubDir(ctx, fg.srcs, String(fg.properties.Path))
}
+ SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: fg.srcs.Strings()})
+ CollectDependencyAconfigFiles(ctx, &fg.mergedAconfigFiles)
}
func (fg *fileGroup) Srcs() Paths {
@@ -297,101 +109,6 @@
}
}
-func (fg *fileGroup) QueueBazelCall(ctx BaseModuleContext) {
- bazelCtx := ctx.Config().BazelContext
-
- bazelCtx.QueueBazelRequest(
- fg.GetBazelLabel(ctx, fg),
- cquery.GetOutputFiles,
- configKey{arch: Common.String(), osType: CommonOS})
-}
-
-func (fg *fileGroup) IsMixedBuildSupported(ctx BaseModuleContext) bool {
- // TODO(b/247782695), TODO(b/242847534) Fix mixed builds for filegroups
- return false
-}
-
-func (fg *fileGroup) ProcessBazelQueryResponse(ctx ModuleContext) {
- bazelCtx := ctx.Config().BazelContext
- // This is a short-term solution because we rely on info from Android.bp to handle
- // a converted module. This will block when we want to remove Android.bp for all
- // converted modules at some point.
- // TODO(b/242847534): Implement a long-term solution in which we don't need to rely
- // on info form Android.bp for modules that are already converted to Bazel
- relativeRoot := ctx.ModuleDir()
- if fg.properties.Path != nil {
- relativeRoot = filepath.Join(relativeRoot, *fg.properties.Path)
- }
-
- filePaths, err := bazelCtx.GetOutputFiles(fg.GetBazelLabel(ctx, fg), configKey{arch: Common.String(), osType: CommonOS})
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- return
- }
-
- bazelOuts := make(Paths, 0, len(filePaths))
- for _, p := range filePaths {
- bazelOuts = append(bazelOuts, PathForBazelOutRelative(ctx, relativeRoot, p))
- }
- fg.srcs = bazelOuts
-}
-
-func (fg *fileGroup) ShouldConvertToAidlLibrary(ctx BazelConversionPathContext) bool {
- return fg.shouldConvertToLibrary(ctx, ".aidl")
-}
-
-func (fg *fileGroup) ShouldConvertToProtoLibrary(ctx BazelConversionPathContext) bool {
- return fg.shouldConvertToLibrary(ctx, ".proto")
-}
-
-func (fg *fileGroup) shouldConvertToLibrary(ctx BazelConversionPathContext, suffix string) bool {
- if len(fg.properties.Srcs) == 0 || !fg.ShouldConvertWithBp2build(ctx) {
- return false
- }
- for _, src := range fg.properties.Srcs {
- if !strings.HasSuffix(src, suffix) {
- return false
- }
- }
- return true
-}
-
-func (fg *fileGroup) GetAidlLibraryLabel(ctx BazelConversionPathContext) string {
- return fg.getFileGroupAsLibraryLabel(ctx)
-}
-
-func (fg *fileGroup) GetProtoLibraryLabel(ctx BazelConversionPathContext) string {
- return fg.getFileGroupAsLibraryLabel(ctx) + convertedProtoLibrarySuffix
-}
-
-func (fg *fileGroup) getFileGroupAsLibraryLabel(ctx BazelConversionPathContext) string {
- if ctx.OtherModuleDir(fg.module) == ctx.ModuleDir() {
- return ":" + fg.Name()
- } else {
- return fg.GetBazelLabel(ctx, fg)
- }
-}
-
-// Given a name in srcs prop, check to see if the name references a filegroup
-// and the filegroup is converted to aidl_library
-func IsConvertedToAidlLibrary(ctx BazelConversionPathContext, name string) bool {
- if fg, ok := ToFileGroupAsLibrary(ctx, name); ok {
- return fg.ShouldConvertToAidlLibrary(ctx)
- }
- return false
-}
-
-func ToFileGroupAsLibrary(ctx BazelConversionPathContext, name string) (FileGroupAsLibrary, bool) {
- if module, ok := ctx.ModuleFromName(name); ok {
- if IsFilegroup(ctx, module) {
- if fg, ok := module.(FileGroupAsLibrary); ok {
- return fg, true
- }
- }
- }
- return nil, false
-}
-
// Defaults
type FileGroupDefaults struct {
ModuleBase
diff --git a/android/filegroup_test.go b/android/filegroup_test.go
index 893da57..14e9368 100644
--- a/android/filegroup_test.go
+++ b/android/filegroup_test.go
@@ -40,17 +40,8 @@
}
for _, testCase := range testCases {
- outBaseDir := "outputbase"
result := GroupFixturePreparers(
PrepareForTestWithFilegroup,
- FixtureModifyConfig(func(config Config) {
- config.BazelContext = MockBazelContext{
- OutputBaseDir: outBaseDir,
- LabelToOutputFiles: map[string][]string{
- "//:baz": []string{"a/b/c/d/test.aidl"},
- },
- }
- }),
).RunTestWithBp(t, testCase.bp)
fg := result.Module("baz", "").(*fileGroup)
diff --git a/android/fixture.go b/android/fixture.go
index 6660afd..5ad47e8 100644
--- a/android/fixture.go
+++ b/android/fixture.go
@@ -275,6 +275,15 @@
})
}
+// Sync the mock filesystem with the current config, then modify the context,
+// This allows context modification that requires filesystem access.
+func FixtureModifyContextWithMockFs(mutator func(ctx *TestContext)) FixturePreparer {
+ return newSimpleFixturePreparer(func(f *fixture) {
+ f.config.mockFileSystem("", f.mockFS)
+ mutator(f.ctx)
+ })
+}
+
func FixtureRegisterWithContext(registeringFunc func(ctx RegistrationContext)) FixturePreparer {
return FixtureModifyContext(func(ctx *TestContext) { registeringFunc(ctx) })
}
diff --git a/android/license.go b/android/license.go
index a09422b..5bffc25 100644
--- a/android/license.go
+++ b/android/license.go
@@ -15,12 +15,7 @@
package android
import (
- "fmt"
- "os"
-
"github.com/google/blueprint"
-
- "android/soong/bazel"
)
type licenseKindDependencyTag struct {
@@ -53,54 +48,13 @@
Visibility []string
}
-var _ Bazelable = &licenseModule{}
-
type licenseModule struct {
ModuleBase
DefaultableModuleBase
- BazelModuleBase
properties licenseProperties
}
-type bazelLicenseAttributes struct {
- License_kinds []string
- Copyright_notice *string
- License_text bazel.LabelAttribute
- Package_name *string
- Visibility []string
-}
-
-func (m *licenseModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
- attrs := &bazelLicenseAttributes{
- License_kinds: m.properties.License_kinds,
- Copyright_notice: m.properties.Copyright_notice,
- Package_name: m.properties.Package_name,
- Visibility: m.properties.Visibility,
- }
-
- // TODO(asmundak): Soong supports multiple license texts while Bazel's license
- // rule does not. Have android_license create a genrule to concatenate multiple
- // license texts.
- if len(m.properties.License_text) > 1 && ctx.Config().IsEnvTrue("BP2BUILD_VERBOSE") {
- fmt.Fprintf(os.Stderr, "warning: using only the first license_text item from //%s:%s\n",
- ctx.ModuleDir(), m.Name())
- }
- if len(m.properties.License_text) >= 1 {
- attrs.License_text.SetValue(BazelLabelForModuleSrcSingle(ctx, m.properties.License_text[0]))
- }
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "android_license",
- Bzl_load_location: "//build/bazel/rules/license:license.bzl",
- },
- CommonAttributes{
- Name: m.Name(),
- },
- attrs)
-}
-
func (m *licenseModule) DepsMutator(ctx BottomUpMutatorContext) {
for i, license := range m.properties.License_kinds {
for j := i + 1; j < len(m.properties.License_kinds); j++ {
@@ -131,14 +85,13 @@
module := &licenseModule{}
base := module.base()
- module.AddProperties(&base.nameProperties, &module.properties, &base.commonProperties.BazelConversionStatus)
+ module.AddProperties(&base.nameProperties, &module.properties)
// The visibility property needs to be checked and parsed by the visibility module.
setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
initAndroidModuleBase(module)
InitDefaultableModule(module)
- InitBazelModule(module)
return module
}
diff --git a/android/license_kind.go b/android/license_kind.go
index 24b91e4..838dedd 100644
--- a/android/license_kind.go
+++ b/android/license_kind.go
@@ -14,8 +14,6 @@
package android
-import "android/soong/bazel"
-
func init() {
RegisterLicenseKindBuildComponents(InitRegistrationContext)
}
@@ -34,39 +32,13 @@
Visibility []string
}
-var _ Bazelable = &licenseKindModule{}
-
type licenseKindModule struct {
ModuleBase
DefaultableModuleBase
- BazelModuleBase
properties licenseKindProperties
}
-type bazelLicenseKindAttributes struct {
- Conditions []string
- Url string
- Visibility []string
-}
-
-func (m *licenseKindModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
- attrs := &bazelLicenseKindAttributes{
- Conditions: m.properties.Conditions,
- Url: m.properties.Url,
- Visibility: m.properties.Visibility,
- }
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "license_kind",
- Bzl_load_location: "@rules_license//rules:license_kind.bzl",
- },
- CommonAttributes{
- Name: m.Name(),
- },
- attrs)
-}
-
func (m *licenseKindModule) DepsMutator(ctx BottomUpMutatorContext) {
// Nothing to do.
}
@@ -79,14 +51,13 @@
module := &licenseKindModule{}
base := module.base()
- module.AddProperties(&base.nameProperties, &module.properties, &base.commonProperties.BazelConversionStatus)
+ module.AddProperties(&base.nameProperties, &module.properties)
// The visibility property needs to be checked and parsed by the visibility module.
setPrimaryVisibilityProperty(module, "visibility", &module.properties.Visibility)
initAndroidModuleBase(module)
InitDefaultableModule(module)
- InitBazelModule(module)
return module
}
diff --git a/android/license_metadata.go b/android/license_metadata.go
index 8933bd5..463fd07 100644
--- a/android/license_metadata.go
+++ b/android/license_metadata.go
@@ -50,7 +50,14 @@
outputFiles = PathsIfNonNil(outputFiles...)
}
- isContainer := isContainerFromFileExtensions(base.installFiles, outputFiles)
+ // Only pass the last installed file to isContainerFromFileExtensions so a *.zip file in test data
+ // doesn't mark the whole module as a container.
+ var installFiles InstallPaths
+ if len(base.installFiles) > 0 {
+ installFiles = InstallPaths{base.installFiles[len(base.installFiles)-1]}
+ }
+
+ isContainer := isContainerFromFileExtensions(installFiles, outputFiles)
var allDepMetadataFiles Paths
var allDepMetadataArgs []string
@@ -71,8 +78,7 @@
return
}
- if ctx.OtherModuleHasProvider(dep, LicenseMetadataProvider) {
- info := ctx.OtherModuleProvider(dep, LicenseMetadataProvider).(*LicenseMetadataInfo)
+ if info, ok := OtherModuleProvider(ctx, dep, LicenseMetadataProvider); ok {
allDepMetadataFiles = append(allDepMetadataFiles, info.LicenseMetadataPath)
if isContainer || isInstallDepNeeded(dep, ctx.OtherModuleDependencyTag(dep)) {
allDepMetadataDepSets = append(allDepMetadataDepSets, info.LicenseMetadataDepSet)
@@ -168,7 +174,7 @@
},
})
- ctx.SetProvider(LicenseMetadataProvider, &LicenseMetadataInfo{
+ SetProvider(ctx, LicenseMetadataProvider, &LicenseMetadataInfo{
LicenseMetadataPath: licenseMetadataFile,
LicenseMetadataDepSet: NewDepSet(TOPOLOGICAL, Paths{licenseMetadataFile}, allDepMetadataDepSets),
})
@@ -193,7 +199,7 @@
}
// LicenseMetadataProvider is used to propagate license metadata paths between modules.
-var LicenseMetadataProvider = blueprint.NewProvider(&LicenseMetadataInfo{})
+var LicenseMetadataProvider = blueprint.NewProvider[*LicenseMetadataInfo]()
// LicenseMetadataInfo stores the license metadata path for a module.
type LicenseMetadataInfo struct {
diff --git a/android/licenses.go b/android/licenses.go
index c6b3243..be1eede 100644
--- a/android/licenses.go
+++ b/android/licenses.go
@@ -230,7 +230,7 @@
licenseInfo := LicenseInfo{
Licenses: licenses,
}
- ctx.SetProvider(LicenseInfoProvider, licenseInfo)
+ SetProvider(ctx, LicenseInfoProvider, licenseInfo)
}
// Update a property string array with a distinct union of its values and a list of new values.
@@ -322,7 +322,7 @@
Licenses []string
}
-var LicenseInfoProvider = blueprint.NewProvider(LicenseInfo{})
+var LicenseInfoProvider = blueprint.NewProvider[LicenseInfo]()
func init() {
RegisterMakeVarsProvider(pctx, licensesMakeVarsProvider)
diff --git a/android/makevars.go b/android/makevars.go
index 0800190..4039e7e 100644
--- a/android/makevars.go
+++ b/android/makevars.go
@@ -16,9 +16,11 @@
import (
"bytes"
+ "cmp"
"fmt"
"path/filepath"
"runtime"
+ "slices"
"sort"
"strings"
@@ -92,7 +94,7 @@
ModuleDir(module blueprint.Module) string
ModuleSubDir(module blueprint.Module) string
ModuleType(module blueprint.Module) string
- ModuleProvider(module blueprint.Module, key blueprint.ProviderKey) interface{}
+ moduleProvider(module blueprint.Module, key blueprint.AnyProviderKey) (any, bool)
BlueprintFile(module blueprint.Module) string
ModuleErrorf(module blueprint.Module, format string, args ...interface{})
@@ -242,6 +244,8 @@
var dists []dist
var phonies []phony
var katiInstalls []katiInstall
+ var katiInitRcInstalls []katiInstall
+ var katiVintfManifestInstalls []katiInstall
var katiSymlinks []katiInstall
providers := append([]makeVarsProvider(nil), makeVarsInitProviders...)
@@ -275,10 +279,33 @@
if m.ExportedToMake() {
katiInstalls = append(katiInstalls, m.base().katiInstalls...)
+ katiInitRcInstalls = append(katiInitRcInstalls, m.base().katiInitRcInstalls...)
+ katiVintfManifestInstalls = append(katiVintfManifestInstalls, m.base().katiVintfInstalls...)
katiSymlinks = append(katiSymlinks, m.base().katiSymlinks...)
}
})
+ compareKatiInstalls := func(a, b katiInstall) int {
+ aTo, bTo := a.to.String(), b.to.String()
+ if cmpTo := cmp.Compare(aTo, bTo); cmpTo != 0 {
+ return cmpTo
+ }
+
+ aFrom, bFrom := a.from.String(), b.from.String()
+ return cmp.Compare(aFrom, bFrom)
+ }
+
+ slices.SortFunc(katiInitRcInstalls, compareKatiInstalls)
+ katiInitRcInstalls = slices.CompactFunc(katiInitRcInstalls, func(a, b katiInstall) bool {
+ return compareKatiInstalls(a, b) == 0
+ })
+ katiInstalls = append(katiInstalls, katiInitRcInstalls...)
+
+ slices.SortFunc(katiVintfManifestInstalls, compareKatiInstalls)
+ katiVintfManifestInstalls = slices.CompactFunc(katiVintfManifestInstalls, func(a, b katiInstall) bool {
+ return compareKatiInstalls(a, b) == 0
+ })
+
if ctx.Failed() {
return
}
@@ -316,7 +343,7 @@
ctx.Errorf(err.Error())
}
- installsBytes := s.writeInstalls(katiInstalls, katiSymlinks)
+ installsBytes := s.writeInstalls(katiInstalls, katiSymlinks, katiVintfManifestInstalls)
if err := pathtools.WriteFileIfChanged(installsFile, installsBytes, 0666); err != nil {
ctx.Errorf(err.Error())
}
@@ -438,7 +465,7 @@
// writeInstalls writes the list of install rules generated by Soong to a makefile. The rules
// are exported to Make instead of written directly to the ninja file so that main.mk can add
// the dependencies from the `required` property that are hard to resolve in Soong.
-func (s *makeVarsSingleton) writeInstalls(installs, symlinks []katiInstall) []byte {
+func (s *makeVarsSingleton) writeInstalls(installs, symlinks, katiVintfManifestInstalls []katiInstall) []byte {
buf := &bytes.Buffer{}
fmt.Fprint(buf, `# Autogenerated file
@@ -486,9 +513,9 @@
for _, symlink := range symlinks {
fmt.Fprintf(buf, "%s:", symlink.to.String())
if symlink.from != nil {
- // The symlink doesn't need updating when the target is modified, but we sometimes
- // have a dependency on a symlink to a binary instead of to the binary directly, and
- // the mtime of the symlink must be updated when the binary is modified, so use a
+ // The katiVintfManifestInstall doesn't need updating when the target is modified, but we sometimes
+ // have a dependency on a katiVintfManifestInstall to a binary instead of to the binary directly, and
+ // the mtime of the katiVintfManifestInstall must be updated when the binary is modified, so use a
// normal dependency here instead of an order-only dependency.
fmt.Fprintf(buf, " %s", symlink.from.String())
}
@@ -507,7 +534,7 @@
if symlink.from != nil {
rel, err := filepath.Rel(filepath.Dir(symlink.to.String()), symlink.from.String())
if err != nil {
- panic(fmt.Errorf("failed to find relative path for symlink from %q to %q: %w",
+ panic(fmt.Errorf("failed to find relative path for katiVintfManifestInstall from %q to %q: %w",
symlink.from.String(), symlink.to.String(), err))
}
fromStr = rel
@@ -521,6 +548,19 @@
fmt.Fprintln(buf)
}
+ for _, install := range katiVintfManifestInstalls {
+ // Write a rule for each vintf install request that calls the copy-vintf-manifest-chedk make function.
+ fmt.Fprintf(buf, "$(eval $(call copy-vintf-manifest-checked, %s, %s))\n", install.from.String(), install.to.String())
+
+ if len(install.implicitDeps) > 0 {
+ panic(fmt.Errorf("unsupported implicitDeps %q in vintf install rule %q", install.implicitDeps, install.to))
+ }
+ if len(install.orderOnlyDeps) > 0 {
+ panic(fmt.Errorf("unsupported orderOnlyDeps %q in vintf install rule %q", install.orderOnlyDeps, install.to))
+ }
+
+ fmt.Fprintln(buf)
+ }
return buf.Bytes()
}
diff --git a/android/metrics.go b/android/metrics.go
index 63c72cd..6834b1b 100644
--- a/android/metrics.go
+++ b/android/metrics.go
@@ -15,9 +15,12 @@
package android
import (
+ "bytes"
"io/ioutil"
+ "os"
"runtime"
- "sort"
+ "strconv"
+ "time"
"github.com/google/blueprint/metrics"
"google.golang.org/protobuf/proto"
@@ -27,18 +30,21 @@
var soongMetricsOnceKey = NewOnceKey("soong metrics")
-type SoongMetrics struct {
- Modules int
- Variants int
+type soongMetrics struct {
+ modules int
+ variants int
+ perfCollector perfCollector
}
-func readSoongMetrics(config Config) (SoongMetrics, bool) {
- soongMetrics, ok := config.Peek(soongMetricsOnceKey)
- if ok {
- return soongMetrics.(SoongMetrics), true
- } else {
- return SoongMetrics{}, false
- }
+type perfCollector struct {
+ events []*soong_metrics_proto.PerfCounters
+ stop chan<- bool
+}
+
+func getSoongMetrics(config Config) *soongMetrics {
+ return config.Once(soongMetricsOnceKey, func() interface{} {
+ return &soongMetrics{}
+ }).(*soongMetrics)
}
func init() {
@@ -50,27 +56,27 @@
type soongMetricsSingleton struct{}
func (soongMetricsSingleton) GenerateBuildActions(ctx SingletonContext) {
- metrics := SoongMetrics{}
+ metrics := getSoongMetrics(ctx.Config())
ctx.VisitAllModules(func(m Module) {
if ctx.PrimaryModule(m) == m {
- metrics.Modules++
+ metrics.modules++
}
- metrics.Variants++
- })
- ctx.Config().Once(soongMetricsOnceKey, func() interface{} {
- return metrics
+ metrics.variants++
})
}
func collectMetrics(config Config, eventHandler *metrics.EventHandler) *soong_metrics_proto.SoongBuildMetrics {
metrics := &soong_metrics_proto.SoongBuildMetrics{}
- soongMetrics, ok := readSoongMetrics(config)
- if ok {
- metrics.Modules = proto.Uint32(uint32(soongMetrics.Modules))
- metrics.Variants = proto.Uint32(uint32(soongMetrics.Variants))
+ soongMetrics := getSoongMetrics(config)
+ if soongMetrics.modules > 0 {
+ metrics.Modules = proto.Uint32(uint32(soongMetrics.modules))
+ metrics.Variants = proto.Uint32(uint32(soongMetrics.variants))
}
+ soongMetrics.perfCollector.stop <- true
+ metrics.PerfCounters = soongMetrics.perfCollector.events
+
memStats := runtime.MemStats{}
runtime.ReadMemStats(&memStats)
metrics.MaxHeapSize = proto.Uint64(memStats.HeapSys)
@@ -86,27 +92,117 @@
}
metrics.Events = append(metrics.Events, &perfInfo)
}
- mixedBuildsInfo := soong_metrics_proto.MixedBuildsInfo{}
- mixedBuildEnabledModules := make([]string, 0, len(config.mixedBuildEnabledModules))
- for module, _ := range config.mixedBuildEnabledModules {
- mixedBuildEnabledModules = append(mixedBuildEnabledModules, module)
- }
-
- mixedBuildDisabledModules := make([]string, 0, len(config.mixedBuildDisabledModules))
- for module, _ := range config.mixedBuildDisabledModules {
- mixedBuildDisabledModules = append(mixedBuildDisabledModules, module)
- }
- // Sorted for deterministic output.
- sort.Strings(mixedBuildEnabledModules)
- sort.Strings(mixedBuildDisabledModules)
-
- mixedBuildsInfo.MixedBuildEnabledModules = mixedBuildEnabledModules
- mixedBuildsInfo.MixedBuildDisabledModules = mixedBuildDisabledModules
- metrics.MixedBuildsInfo = &mixedBuildsInfo
return metrics
}
+func StartBackgroundMetrics(config Config) {
+ perfCollector := &getSoongMetrics(config).perfCollector
+ stop := make(chan bool)
+ perfCollector.stop = stop
+
+ previousTime := time.Now()
+ previousCpuTime := readCpuTime()
+
+ ticker := time.NewTicker(time.Second)
+
+ go func() {
+ for {
+ select {
+ case <-stop:
+ ticker.Stop()
+ return
+ case <-ticker.C:
+ // carry on
+ }
+
+ currentTime := time.Now()
+
+ var memStats runtime.MemStats
+ runtime.ReadMemStats(&memStats)
+
+ currentCpuTime := readCpuTime()
+
+ interval := currentTime.Sub(previousTime)
+ intervalCpuTime := currentCpuTime - previousCpuTime
+ intervalCpuPercent := intervalCpuTime * 100 / interval
+
+ // heapAlloc is the memory that has been allocated on the heap but not yet GC'd. It may be referenced,
+ // or unrefenced but not yet GC'd.
+ heapAlloc := memStats.HeapAlloc
+ // heapUnused is the memory that was previously used by the heap, but is currently not used. It does not
+ // count memory that was used and then returned to the OS.
+ heapUnused := memStats.HeapIdle - memStats.HeapReleased
+ // heapOverhead is the memory used by the allocator and GC
+ heapOverhead := memStats.MSpanSys + memStats.MCacheSys + memStats.GCSys
+ // otherMem is the memory used outside of the heap.
+ otherMem := memStats.Sys - memStats.HeapSys - heapOverhead
+
+ perfCollector.events = append(perfCollector.events, &soong_metrics_proto.PerfCounters{
+ Time: proto.Uint64(uint64(currentTime.UnixNano())),
+ Groups: []*soong_metrics_proto.PerfCounterGroup{
+ {
+ Name: proto.String("cpu"),
+ Counters: []*soong_metrics_proto.PerfCounter{
+ {Name: proto.String("cpu_percent"), Value: proto.Int64(int64(intervalCpuPercent))},
+ },
+ }, {
+ Name: proto.String("memory"),
+ Counters: []*soong_metrics_proto.PerfCounter{
+ {Name: proto.String("heap_alloc"), Value: proto.Int64(int64(heapAlloc))},
+ {Name: proto.String("heap_unused"), Value: proto.Int64(int64(heapUnused))},
+ {Name: proto.String("heap_overhead"), Value: proto.Int64(int64(heapOverhead))},
+ {Name: proto.String("other"), Value: proto.Int64(int64(otherMem))},
+ },
+ },
+ },
+ })
+
+ previousTime = currentTime
+ previousCpuTime = currentCpuTime
+ }
+ }()
+}
+
+func readCpuTime() time.Duration {
+ if runtime.GOOS != "linux" {
+ return 0
+ }
+
+ stat, err := os.ReadFile("/proc/self/stat")
+ if err != nil {
+ return 0
+ }
+
+ endOfComm := bytes.LastIndexByte(stat, ')')
+ if endOfComm < 0 || endOfComm > len(stat)-2 {
+ return 0
+ }
+
+ stat = stat[endOfComm+2:]
+
+ statFields := bytes.Split(stat, []byte{' '})
+ // This should come from sysconf(_SC_CLK_TCK), but there's no way to call that from Go. Assume it's 100,
+ // which is the value for all platforms we support.
+ const HZ = 100
+ const MS_PER_HZ = 1e3 / HZ * time.Millisecond
+
+ const STAT_UTIME_FIELD = 14 - 2
+ const STAT_STIME_FIELD = 15 - 2
+ if len(statFields) < STAT_STIME_FIELD {
+ return 0
+ }
+ userCpuTicks, err := strconv.ParseUint(string(statFields[STAT_UTIME_FIELD]), 10, 64)
+ if err != nil {
+ return 0
+ }
+ kernelCpuTicks, _ := strconv.ParseUint(string(statFields[STAT_STIME_FIELD]), 10, 64)
+ if err != nil {
+ return 0
+ }
+ return time.Duration(userCpuTicks+kernelCpuTicks) * MS_PER_HZ
+}
+
func WriteMetrics(config Config, eventHandler *metrics.EventHandler, metricsFile string) error {
metrics := collectMetrics(config, eventHandler)
diff --git a/android/module.go b/android/module.go
index 516810f..5c7bbbf 100644
--- a/android/module.go
+++ b/android/module.go
@@ -15,22 +15,17 @@
package android
import (
+ "android/soong/bazel"
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"net/url"
- "os"
- "path"
"path/filepath"
"reflect"
- "regexp"
+ "slices"
"sort"
"strings"
- "text/scanner"
-
- "android/soong/bazel"
- "android/soong/ui/metrics/bp2build_metrics_proto"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -41,470 +36,6 @@
DeviceStaticLibrary = "static_library"
)
-// BuildParameters describes the set of potential parameters to build a Ninja rule.
-// In general, these correspond to a Ninja concept.
-type BuildParams struct {
- // A Ninja Rule that will be written to the Ninja file. This allows factoring out common code
- // among multiple modules to reduce repetition in the Ninja file of action requirements. A rule
- // can contain variables that should be provided in Args.
- Rule blueprint.Rule
- // Deps represents the depfile format. When using RuleBuilder, this defaults to GCC when depfiles
- // are used.
- Deps blueprint.Deps
- // Depfile is a writeable path that allows correct incremental builds when the inputs have not
- // been fully specified by the Ninja rule. Ninja supports a subset of the Makefile depfile syntax.
- Depfile WritablePath
- // A description of the build action.
- Description string
- // Output is an output file of the action. When using this field, references to $out in the Ninja
- // command will refer to this file.
- Output WritablePath
- // Outputs is a slice of output file of the action. When using this field, references to $out in
- // the Ninja command will refer to these files.
- Outputs WritablePaths
- // SymlinkOutput is an output file specifically that is a symlink.
- SymlinkOutput WritablePath
- // SymlinkOutputs is a slice of output files specifically that is a symlink.
- SymlinkOutputs WritablePaths
- // ImplicitOutput is an output file generated by the action. Note: references to `$out` in the
- // Ninja command will NOT include references to this file.
- ImplicitOutput WritablePath
- // ImplicitOutputs is a slice of output files generated by the action. Note: references to `$out`
- // in the Ninja command will NOT include references to these files.
- ImplicitOutputs WritablePaths
- // Input is an input file to the Ninja action. When using this field, references to $in in the
- // Ninja command will refer to this file.
- Input Path
- // Inputs is a slice of input files to the Ninja action. When using this field, references to $in
- // in the Ninja command will refer to these files.
- Inputs Paths
- // Implicit is an input file to the Ninja action. Note: references to `$in` in the Ninja command
- // will NOT include references to this file.
- Implicit Path
- // Implicits is a slice of input files to the Ninja action. Note: references to `$in` in the Ninja
- // command will NOT include references to these files.
- Implicits Paths
- // OrderOnly are Ninja order-only inputs to the action. When these are out of date, the output is
- // not rebuilt until they are built, but changes in order-only dependencies alone do not cause the
- // output to be rebuilt.
- OrderOnly Paths
- // Validation is an output path for a validation action. Validation outputs imply lower
- // non-blocking priority to building non-validation outputs.
- Validation Path
- // Validations is a slice of output path for a validation action. Validation outputs imply lower
- // non-blocking priority to building non-validation outputs.
- Validations Paths
- // Whether to skip outputting a default target statement which will be built by Ninja when no
- // targets are specified on Ninja's command line.
- Default bool
- // Args is a key value mapping for replacements of variables within the Rule
- Args map[string]string
-}
-
-type ModuleBuildParams BuildParams
-
-// EarlyModuleContext provides methods that can be called early, as soon as the properties have
-// been parsed into the module and before any mutators have run.
-type EarlyModuleContext interface {
- // Module returns the current module as a Module. It should rarely be necessary, as the module already has a
- // reference to itself.
- Module() Module
-
- // ModuleName returns the name of the module. This is generally the value that was returned by Module.Name() when
- // the module was created, but may have been modified by calls to BaseMutatorContext.Rename.
- ModuleName() string
-
- // ModuleDir returns the path to the directory that contains the definition of the module.
- ModuleDir() string
-
- // ModuleType returns the name of the module type that was used to create the module, as specified in
- // RegisterModuleType.
- ModuleType() string
-
- // BlueprintFile returns the name of the blueprint file that contains the definition of this
- // module.
- BlueprintsFile() string
-
- // ContainsProperty returns true if the specified property name was set in the module definition.
- ContainsProperty(name string) bool
-
- // Errorf reports an error at the specified position of the module definition file.
- Errorf(pos scanner.Position, fmt string, args ...interface{})
-
- // ModuleErrorf reports an error at the line number of the module type in the module definition.
- ModuleErrorf(fmt string, args ...interface{})
-
- // PropertyErrorf reports an error at the line number of a property in the module definition.
- PropertyErrorf(property, fmt string, args ...interface{})
-
- // Failed returns true if any errors have been reported. In most cases the module can continue with generating
- // build rules after an error, allowing it to report additional errors in a single run, but in cases where the error
- // has prevented the module from creating necessary data it can return early when Failed returns true.
- Failed() bool
-
- // AddNinjaFileDeps adds dependencies on the specified files to the rule that creates the ninja manifest. The
- // primary builder will be rerun whenever the specified files are modified.
- AddNinjaFileDeps(deps ...string)
-
- DeviceSpecific() bool
- SocSpecific() bool
- ProductSpecific() bool
- SystemExtSpecific() bool
- Platform() bool
-
- Config() Config
- DeviceConfig() DeviceConfig
-
- // Deprecated: use Config()
- AConfig() Config
-
- // GlobWithDeps returns a list of files that match the specified pattern but do not match any
- // of the patterns in excludes. It also adds efficient dependencies to rerun the primary
- // builder whenever a file matching the pattern as added or removed, without rerunning if a
- // file that does not match the pattern is added to a searched directory.
- GlobWithDeps(pattern string, excludes []string) ([]string, error)
-
- Glob(globPattern string, excludes []string) Paths
- GlobFiles(globPattern string, excludes []string) Paths
- IsSymlink(path Path) bool
- Readlink(path Path) string
-
- // Namespace returns the Namespace object provided by the NameInterface set by Context.SetNameInterface, or the
- // default SimpleNameInterface if Context.SetNameInterface was not called.
- Namespace() *Namespace
-}
-
-// BaseModuleContext is the same as blueprint.BaseModuleContext except that Config() returns
-// a Config instead of an interface{}, and some methods have been wrapped to use an android.Module
-// instead of a blueprint.Module, plus some extra methods that return Android-specific information
-// about the current module.
-type BaseModuleContext interface {
- EarlyModuleContext
-
- blueprintBaseModuleContext() blueprint.BaseModuleContext
-
- // OtherModuleName returns the name of another Module. See BaseModuleContext.ModuleName for more information.
- // It is intended for use inside the visit functions of Visit* and WalkDeps.
- OtherModuleName(m blueprint.Module) string
-
- // OtherModuleDir returns the directory of another Module. See BaseModuleContext.ModuleDir for more information.
- // It is intended for use inside the visit functions of Visit* and WalkDeps.
- OtherModuleDir(m blueprint.Module) string
-
- // OtherModuleErrorf reports an error on another Module. See BaseModuleContext.ModuleErrorf for more information.
- // It is intended for use inside the visit functions of Visit* and WalkDeps.
- OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{})
-
- // OtherModuleDependencyTag returns the dependency tag used to depend on a module, or nil if there is no dependency
- // on the module. When called inside a Visit* method with current module being visited, and there are multiple
- // dependencies on the module being visited, it returns the dependency tag used for the current dependency.
- OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag
-
- // OtherModuleExists returns true if a module with the specified name exists, as determined by the NameInterface
- // passed to Context.SetNameInterface, or SimpleNameInterface if it was not called.
- OtherModuleExists(name string) bool
-
- // OtherModuleDependencyVariantExists returns true if a module with the
- // specified name and variant exists. The variant must match the given
- // variations. It must also match all the non-local variations of the current
- // module. In other words, it checks for the module that AddVariationDependencies
- // would add a dependency on with the same arguments.
- OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool
-
- // OtherModuleFarDependencyVariantExists returns true if a module with the
- // specified name and variant exists. The variant must match the given
- // variations, but not the non-local variations of the current module. In
- // other words, it checks for the module that AddFarVariationDependencies
- // would add a dependency on with the same arguments.
- OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool
-
- // OtherModuleReverseDependencyVariantExists returns true if a module with the
- // specified name exists with the same variations as the current module. In
- // other words, it checks for the module that AddReverseDependency would add a
- // dependency on with the same argument.
- OtherModuleReverseDependencyVariantExists(name string) bool
-
- // OtherModuleType returns the type of another Module. See BaseModuleContext.ModuleType for more information.
- // It is intended for use inside the visit functions of Visit* and WalkDeps.
- OtherModuleType(m blueprint.Module) string
-
- // OtherModuleProvider returns the value for a provider for the given module. If the value is
- // not set it returns the zero value of the type of the provider, so the return value can always
- // be type asserted to the type of the provider. The value returned may be a deep copy of the
- // value originally passed to SetProvider.
- OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{}
-
- // OtherModuleHasProvider returns true if the provider for the given module has been set.
- OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool
-
- // Provider returns the value for a provider for the current module. If the value is
- // not set it returns the zero value of the type of the provider, so the return value can always
- // be type asserted to the type of the provider. It panics if called before the appropriate
- // mutator or GenerateBuildActions pass for the provider. The value returned may be a deep
- // copy of the value originally passed to SetProvider.
- Provider(provider blueprint.ProviderKey) interface{}
-
- // HasProvider returns true if the provider for the current module has been set.
- HasProvider(provider blueprint.ProviderKey) bool
-
- // SetProvider sets the value for a provider for the current module. It panics if not called
- // during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
- // is not of the appropriate type, or if the value has already been set. The value should not
- // be modified after being passed to SetProvider.
- SetProvider(provider blueprint.ProviderKey, value interface{})
-
- GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module
-
- // GetDirectDepWithTag returns the Module the direct dependency with the specified name, or nil if
- // none exists. It panics if the dependency does not have the specified tag. It skips any
- // dependencies that are not an android.Module.
- GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module
-
- // GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
- // name, or nil if none exists. If there are multiple dependencies on the same module it returns
- // the first DependencyTag.
- GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag)
-
- ModuleFromName(name string) (blueprint.Module, bool)
-
- // VisitDirectDepsBlueprint calls visit for each direct dependency. If there are multiple
- // direct dependencies on the same module visit will be called multiple times on that module
- // and OtherModuleDependencyTag will return a different tag for each.
- //
- // The Module passed to the visit function should not be retained outside of the visit
- // function, it may be invalidated by future mutators.
- VisitDirectDepsBlueprint(visit func(blueprint.Module))
-
- // VisitDirectDeps calls visit for each direct dependency. If there are multiple
- // direct dependencies on the same module visit will be called multiple times on that module
- // and OtherModuleDependencyTag will return a different tag for each. It raises an error if any of the
- // dependencies are not an android.Module.
- //
- // The Module passed to the visit function should not be retained outside of the visit
- // function, it may be invalidated by future mutators.
- VisitDirectDeps(visit func(Module))
-
- VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module))
-
- // VisitDirectDepsIf calls pred for each direct dependency, and if pred returns true calls visit. If there are
- // multiple direct dependencies on the same module pred and visit will be called multiple times on that module and
- // OtherModuleDependencyTag will return a different tag for each. It skips any
- // dependencies that are not an android.Module.
- //
- // The Module passed to the visit function should not be retained outside of the visit function, it may be
- // invalidated by future mutators.
- VisitDirectDepsIf(pred func(Module) bool, visit func(Module))
- // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
- VisitDepsDepthFirst(visit func(Module))
- // Deprecated: use WalkDeps instead to support multiple dependency tags on the same module
- VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module))
-
- // WalkDeps calls visit for each transitive dependency, traversing the dependency tree in top down order. visit may
- // be called multiple times for the same (child, parent) pair if there are multiple direct dependencies between the
- // child and parent with different tags. OtherModuleDependencyTag will return the tag for the currently visited
- // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down to child. It skips
- // any dependencies that are not an android.Module.
- //
- // The Modules passed to the visit function should not be retained outside of the visit function, they may be
- // invalidated by future mutators.
- WalkDeps(visit func(child, parent Module) bool)
-
- // WalkDepsBlueprint calls visit for each transitive dependency, traversing the dependency
- // tree in top down order. visit may be called multiple times for the same (child, parent)
- // pair if there are multiple direct dependencies between the child and parent with different
- // tags. OtherModuleDependencyTag will return the tag for the currently visited
- // (child, parent) pair. If visit returns false WalkDeps will not continue recursing down
- // to child.
- //
- // The Modules passed to the visit function should not be retained outside of the visit function, they may be
- // invalidated by future mutators.
- WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool)
-
- // GetWalkPath is supposed to be called in visit function passed in WalkDeps()
- // and returns a top-down dependency path from a start module to current child module.
- GetWalkPath() []Module
-
- // PrimaryModule returns the first variant of the current module. Variants of a module are always visited in
- // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from the
- // Module returned by PrimaryModule without data races. This can be used to perform singleton actions that are
- // only done once for all variants of a module.
- PrimaryModule() Module
-
- // FinalModule returns the last variant of the current module. Variants of a module are always visited in
- // order by mutators and GenerateBuildActions, so the data created by the current mutator can be read from all
- // variants using VisitAllModuleVariants if the current module == FinalModule(). This can be used to perform
- // singleton actions that are only done once for all variants of a module.
- FinalModule() Module
-
- // VisitAllModuleVariants calls visit for each variant of the current module. Variants of a module are always
- // visited in order by mutators and GenerateBuildActions, so the data created by the current mutator can be read
- // from all variants if the current module == FinalModule(). Otherwise, care must be taken to not access any
- // data modified by the current mutator.
- VisitAllModuleVariants(visit func(Module))
-
- // GetTagPath is supposed to be called in visit function passed in WalkDeps()
- // and returns a top-down dependency tags path from a start module to current child module.
- // It has one less entry than GetWalkPath() as it contains the dependency tags that
- // exist between each adjacent pair of modules in the GetWalkPath().
- // GetTagPath()[i] is the tag between GetWalkPath()[i] and GetWalkPath()[i+1]
- GetTagPath() []blueprint.DependencyTag
-
- // GetPathString is supposed to be called in visit function passed in WalkDeps()
- // and returns a multi-line string showing the modules and dependency tags
- // among them along the top-down dependency path from a start module to current child module.
- // skipFirst when set to true, the output doesn't include the start module,
- // which is already printed when this function is used along with ModuleErrorf().
- GetPathString(skipFirst bool) string
-
- AddMissingDependencies(missingDeps []string)
-
- // getMissingDependencies returns the list of missing dependencies.
- // Calling this function prevents adding new dependencies.
- getMissingDependencies() []string
-
- // AddUnconvertedBp2buildDep stores module name of a direct dependency that was not converted via bp2build
- AddUnconvertedBp2buildDep(dep string)
-
- // AddMissingBp2buildDep stores the module name of a direct dependency that was not found.
- AddMissingBp2buildDep(dep string)
-
- Target() Target
- TargetPrimary() bool
-
- // The additional arch specific targets (e.g. 32/64 bit) that this module variant is
- // responsible for creating.
- MultiTargets() []Target
- Arch() Arch
- Os() OsType
- Host() bool
- Device() bool
- Darwin() bool
- Windows() bool
- Debug() bool
- PrimaryArch() bool
-}
-
-// Deprecated: use EarlyModuleContext instead
-type BaseContext interface {
- EarlyModuleContext
-}
-
-type ModuleContext interface {
- BaseModuleContext
-
- blueprintModuleContext() blueprint.ModuleContext
-
- // Deprecated: use ModuleContext.Build instead.
- ModuleBuild(pctx PackageContext, params ModuleBuildParams)
-
- // Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must
- // be tagged with `android:"path" to support automatic source module dependency resolution.
- //
- // Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
- ExpandSources(srcFiles, excludes []string) Paths
-
- // Returns a single path expanded from globs and modules referenced using ":module" syntax. The property must
- // be tagged with `android:"path" to support automatic source module dependency resolution.
- //
- // Deprecated: use PathForModuleSrc instead.
- ExpandSource(srcFile, prop string) Path
-
- ExpandOptionalSource(srcFile *string, prop string) OptionalPath
-
- // InstallExecutable creates a rule to copy srcPath to name in the installPath directory,
- // with the given additional dependencies. The file is marked executable after copying.
- //
- // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
- // installed file will be returned by PackagingSpecs() on this module or by
- // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
- // for which IsInstallDepNeeded returns true.
- InstallExecutable(installPath InstallPath, name string, srcPath Path, deps ...Path) InstallPath
-
- // InstallFile creates a rule to copy srcPath to name in the installPath directory,
- // with the given additional dependencies.
- //
- // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
- // installed file will be returned by PackagingSpecs() on this module or by
- // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
- // for which IsInstallDepNeeded returns true.
- InstallFile(installPath InstallPath, name string, srcPath Path, deps ...Path) InstallPath
-
- // InstallFileWithExtraFilesZip creates a rule to copy srcPath to name in the installPath
- // directory, and also unzip a zip file containing extra files to install into the same
- // directory.
- //
- // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
- // installed file will be returned by PackagingSpecs() on this module or by
- // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
- // for which IsInstallDepNeeded returns true.
- InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path, extraZip Path, deps ...Path) InstallPath
-
- // InstallSymlink creates a rule to create a symlink from src srcPath to name in the installPath
- // directory.
- //
- // The installed symlink will be returned by FilesToInstall(), and the PackagingSpec for the
- // installed file will be returned by PackagingSpecs() on this module or by
- // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
- // for which IsInstallDepNeeded returns true.
- InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath
-
- // InstallAbsoluteSymlink creates a rule to create an absolute symlink from src srcPath to name
- // in the installPath directory.
- //
- // The installed symlink will be returned by FilesToInstall(), and the PackagingSpec for the
- // installed file will be returned by PackagingSpecs() on this module or by
- // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
- // for which IsInstallDepNeeded returns true.
- InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath
-
- // PackageFile creates a PackagingSpec as if InstallFile was called, but without creating
- // the rule to copy the file. This is useful to define how a module would be packaged
- // without installing it into the global installation directories.
- //
- // The created PackagingSpec for the will be returned by PackagingSpecs() on this module or by
- // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
- // for which IsInstallDepNeeded returns true.
- PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec
-
- CheckbuildFile(srcPath Path)
-
- InstallInData() bool
- InstallInTestcases() bool
- InstallInSanitizerDir() bool
- InstallInRamdisk() bool
- InstallInVendorRamdisk() bool
- InstallInDebugRamdisk() bool
- InstallInRecovery() bool
- InstallInRoot() bool
- InstallInVendor() bool
- InstallForceOS() (*OsType, *ArchType)
-
- RequiredModuleNames() []string
- HostRequiredModuleNames() []string
- TargetRequiredModuleNames() []string
-
- ModuleSubDir() string
- SoongConfigTraceHash() string
-
- Variable(pctx PackageContext, name, value string)
- Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
- // Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
- // and performs more verification.
- Build(pctx PackageContext, params BuildParams)
- // Phony creates a Make-style phony rule, a rule with no commands that can depend on other
- // phony rules or real files. Phony can be called on the same name multiple times to add
- // additional dependencies.
- Phony(phony string, deps ...Path)
-
- // GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods,
- // but do not exist.
- GetMissingDependencies() []string
-
- // LicenseMetadataFile returns the path where the license metadata for this module will be
- // generated.
- LicenseMetadataFile() Path
-}
-
type Module interface {
blueprint.Module
@@ -547,6 +78,8 @@
InstallInDebugRamdisk() bool
InstallInRecovery() bool
InstallInRoot() bool
+ InstallInOdm() bool
+ InstallInProduct() bool
InstallInVendor() bool
InstallForceOS() (*OsType, *ArchType)
PartitionTag(DeviceConfig) string
@@ -565,15 +98,6 @@
AddProperties(props ...interface{})
GetProperties() []interface{}
- // IsConvertedByBp2build returns whether this module was converted via bp2build
- IsConvertedByBp2build() bool
- GetUnconvertedReason() *UnconvertedReason
-
- // Bp2buildTargets returns the target(s) generated for Bazel via bp2build for this module
- Bp2buildTargets() []bp2buildInfo
- GetUnconvertedBp2buildDeps() []string
- GetMissingBp2buildDeps() []string
-
BuildParamsForTests() []BuildParams
RuleParamsForTests() map[blueprint.Rule]blueprint.RuleParams
VariablesForTests() map[string]string
@@ -802,7 +326,7 @@
// defaults module, use the `defaults_visibility` property on the defaults module;
// not to be confused with the `default_visibility` property on the package module.
//
- // See https://android.googlesource.com/platform/build/soong/+/master/README.md#visibility for
+ // See https://android.googlesource.com/platform/build/soong/+/main/README.md#visibility for
// more details.
Visibility []string
@@ -988,9 +512,6 @@
// constants in image.go, but can also be set to a custom value by individual module types.
ImageVariation string `blueprint:"mutated"`
- // Bazel conversion status
- BazelConversionStatus BazelConversionStatus `blueprint:"mutated"`
-
// SoongConfigTrace records accesses to VendorVars (soong_config). The trace will be hashed
// and used as a subdir of PathForModuleOut. Note that we mainly focus on incremental
// builds among similar products (e.g. aosp_cf_x86_64_phone and aosp_cf_x86_64_foldable),
@@ -998,41 +519,9 @@
// trace, but influence modules among products.
SoongConfigTrace soongConfigTrace `blueprint:"mutated"`
SoongConfigTraceHash string `blueprint:"mutated"`
-}
-// CommonAttributes represents the common Bazel attributes from which properties
-// in `commonProperties` are translated/mapped; such properties are annotated in
-// a list their corresponding attribute. It is embedded within `bp2buildInfo`.
-type CommonAttributes struct {
- // Soong nameProperties -> Bazel name
- Name string
-
- // Data mapped from: Required
- Data bazel.LabelListAttribute
-
- // SkipData is neither a Soong nor Bazel target attribute
- // If true, this will not fill the data attribute automatically
- // This is useful for Soong modules that have 1:many Bazel targets
- // Some of the generated Bazel targets might not have a data attribute
- SkipData *bool
-
- Tags bazel.StringListAttribute
-
- Applicable_licenses bazel.LabelListAttribute
-
- Testonly *bool
-
- // Dir is neither a Soong nor Bazel target attribute
- // If set, the bazel target will be created in this directory
- // If unset, the bazel target will default to be created in the directory of the visited soong module
- Dir *string
-}
-
-// constraintAttributes represents Bazel attributes pertaining to build constraints,
-// which make restrict building a Bazel target for some set of platforms.
-type constraintAttributes struct {
- // Constraint values this target can be built for.
- Target_compatible_with bazel.LabelListAttribute
+ // The team (defined by the owner/vendor) who owns the property.
+ Team *string `android:"path"`
}
type distProperties struct {
@@ -1045,6 +534,12 @@
Dists []Dist `android:"arch_variant"`
}
+type TeamDepTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+var teamDepTag = TeamDepTagType{}
+
// CommonTestOptions represents the common `test_options` properties in
// Android.bp.
type CommonTestOptions struct {
@@ -1272,221 +767,6 @@
m.base().commonProperties.CreateCommonOSVariant = true
}
-func (attrs *CommonAttributes) fillCommonBp2BuildModuleAttrs(ctx *topDownMutatorContext,
- enabledPropertyOverrides bazel.BoolAttribute) constraintAttributes {
-
- mod := ctx.Module().base()
- // Assert passed-in attributes include Name
- if len(attrs.Name) == 0 {
- if ctx.ModuleType() != "package" {
- ctx.ModuleErrorf("CommonAttributes in fillCommonBp2BuildModuleAttrs expects a `.Name`!")
- }
- }
-
- depsToLabelList := func(deps []string) bazel.LabelListAttribute {
- return bazel.MakeLabelListAttribute(BazelLabelForModuleDeps(ctx, deps))
- }
-
- var enabledProperty bazel.BoolAttribute
-
- onlyAndroid := false
- neitherHostNorDevice := false
-
- osSupport := map[string]bool{}
-
- // if the target is enabled and supports arch variance, determine the defaults based on the module
- // type's host or device property and host_supported/device_supported properties
- if mod.commonProperties.ArchSpecific {
- moduleSupportsDevice := mod.DeviceSupported()
- moduleSupportsHost := mod.HostSupported()
- if moduleSupportsHost && !moduleSupportsDevice {
- // for host only, we specify as unsupported on android rather than listing all host osSupport
- // TODO(b/220874839): consider replacing this with a constraint that covers all host osSupport
- // instead
- enabledProperty.SetSelectValue(bazel.OsConfigurationAxis, Android.Name, proptools.BoolPtr(false))
- } else if moduleSupportsDevice && !moduleSupportsHost {
- enabledProperty.SetSelectValue(bazel.OsConfigurationAxis, Android.Name, proptools.BoolPtr(true))
- // specify as a positive to ensure any target-specific enabled can be resolved
- // also save that a target is only android, as if there is only the positive restriction on
- // android, it'll be dropped, so we may need to add it back later
- onlyAndroid = true
- } else if !moduleSupportsHost && !moduleSupportsDevice {
- neitherHostNorDevice = true
- }
-
- for _, osType := range OsTypeList() {
- if osType.Class == Host {
- osSupport[osType.Name] = moduleSupportsHost
- } else if osType.Class == Device {
- osSupport[osType.Name] = moduleSupportsDevice
- }
- }
- }
-
- if neitherHostNorDevice {
- // we can't build this, disable
- enabledProperty.Value = proptools.BoolPtr(false)
- } else if mod.commonProperties.Enabled != nil {
- enabledProperty.SetValue(mod.commonProperties.Enabled)
- if !*mod.commonProperties.Enabled {
- for oss, enabled := range osSupport {
- if val := enabledProperty.SelectValue(bazel.OsConfigurationAxis, oss); enabled && val != nil && *val {
- // if this should be disabled by default, clear out any enabling we've done
- enabledProperty.SetSelectValue(bazel.OsConfigurationAxis, oss, nil)
- }
- }
- }
- }
-
- attrs.Applicable_licenses = bazel.MakeLabelListAttribute(BazelLabelForModuleDeps(ctx, mod.commonProperties.Licenses))
-
- // The required property can contain the module itself. This causes a cycle
- // when generated as the 'data' label list attribute in Bazel. Remove it if
- // it exists. See b/247985196.
- _, requiredWithoutCycles := RemoveFromList(ctx.ModuleName(), mod.commonProperties.Required)
- requiredWithoutCycles = FirstUniqueStrings(requiredWithoutCycles)
- required := depsToLabelList(requiredWithoutCycles)
- archVariantProps := mod.GetArchVariantProperties(ctx, &commonProperties{})
- for axis, configToProps := range archVariantProps {
- for config, _props := range configToProps {
- if archProps, ok := _props.(*commonProperties); ok {
- _, requiredWithoutCycles := RemoveFromList(ctx.ModuleName(), archProps.Required)
- requiredWithoutCycles = FirstUniqueStrings(requiredWithoutCycles)
- required.SetSelectValue(axis, config, depsToLabelList(requiredWithoutCycles).Value)
- if !neitherHostNorDevice {
- if archProps.Enabled != nil {
- if axis != bazel.OsConfigurationAxis || osSupport[config] {
- enabledProperty.SetSelectValue(axis, config, archProps.Enabled)
- }
- }
- }
- }
- }
- }
-
- if !neitherHostNorDevice {
- if enabledPropertyOverrides.Value != nil {
- enabledProperty.Value = enabledPropertyOverrides.Value
- }
- for _, axis := range enabledPropertyOverrides.SortedConfigurationAxes() {
- configToBools := enabledPropertyOverrides.ConfigurableValues[axis]
- for cfg, val := range configToBools {
- if axis != bazel.OsConfigurationAxis || osSupport[cfg] || val /*If enabled is explicitly requested via overrides */ {
- enabledProperty.SetSelectValue(axis, cfg, &val)
- }
- }
- }
- }
-
- productConfigEnabledAttribute := bazel.LabelListAttribute{}
- // TODO(b/234497586): Soong config variables and product variables have different overriding behavior, we
- // should handle it correctly
- if !proptools.BoolDefault(enabledProperty.Value, true) && !neitherHostNorDevice {
- // If the module is not enabled by default, then we can check if a
- // product variable enables it
- productConfigEnabledAttribute = productVariableConfigEnableAttribute(ctx)
-
- if len(productConfigEnabledAttribute.ConfigurableValues) > 0 {
- // In this case, an existing product variable configuration overrides any
- // module-level `enable: false` definition
- newValue := true
- enabledProperty.Value = &newValue
- }
- }
-
- platformEnabledAttribute, err := enabledProperty.ToLabelListAttribute(
- bazel.LabelList{[]bazel.Label{{Label: "@platforms//:incompatible"}}, nil},
- bazel.LabelList{[]bazel.Label{}, nil})
- if err != nil {
- ctx.ModuleErrorf("Error processing platform enabled attribute: %s", err)
- }
-
- // if android is the only arch/os enabled, then add a restriction to only be compatible with android
- if platformEnabledAttribute.IsNil() && onlyAndroid {
- l := bazel.LabelAttribute{}
- l.SetValue(bazel.Label{Label: bazel.OsConfigurationAxis.SelectKey(Android.Name)})
- platformEnabledAttribute.Add(&l)
- }
-
- if !proptools.Bool(attrs.SkipData) {
- attrs.Data.Append(required)
- }
- // SkipData is not an attribute of any Bazel target
- // Set this to nil so that it does not appear in the generated build file
- attrs.SkipData = nil
-
- moduleEnableConstraints := bazel.LabelListAttribute{}
- moduleEnableConstraints.Append(platformEnabledAttribute)
- moduleEnableConstraints.Append(productConfigEnabledAttribute)
- addCompatibilityConstraintForCompileMultilib(ctx, &moduleEnableConstraints)
-
- return constraintAttributes{Target_compatible_with: moduleEnableConstraints}
-}
-
-var (
- incompatible = bazel.LabelList{[]bazel.Label{{Label: "@platforms//:incompatible"}}, nil}
-)
-
-// If compile_mulitilib is set to
-// 1. 32: Add an incompatibility constraint for non-32 arches
-// 1. 64: Add an incompatibility constraint for non-64 arches
-func addCompatibilityConstraintForCompileMultilib(ctx *topDownMutatorContext, enabled *bazel.LabelListAttribute) {
- mod := ctx.Module().base()
- multilib, _ := decodeMultilib(mod, mod.commonProperties.CompileOS, ctx.Config().IgnorePrefer32OnDevice())
-
- switch multilib {
- case "32":
- // Add an incompatibility constraint for all known 64-bit arches
- enabled.SetSelectValue(bazel.ArchConfigurationAxis, "arm64", incompatible)
- enabled.SetSelectValue(bazel.ArchConfigurationAxis, "x86_64", incompatible)
- enabled.SetSelectValue(bazel.ArchConfigurationAxis, "riscv64", incompatible)
- case "64":
- // Add an incompatibility constraint for all known 32-bit arches
- enabled.SetSelectValue(bazel.ArchConfigurationAxis, "arm", incompatible)
- enabled.SetSelectValue(bazel.ArchConfigurationAxis, "x86", incompatible)
- case "both":
- // Do nothing: "both" is trivially compatible with 32-bit and 64-bit
- // The top level rule (e.g. apex/partition) will be responsible for building this module in both variants via an
- // outgoing_transition.
- default: // e.g. first, common
- // TODO - b/299135307: Add bp2build support for these properties.
- }
-
-}
-
-// Check product variables for `enabled: true` flag override.
-// Returns a list of the constraint_value targets who enable this override.
-func productVariableConfigEnableAttribute(ctx *topDownMutatorContext) bazel.LabelListAttribute {
- result := bazel.LabelListAttribute{}
- productVariableProps := ProductVariableProperties(ctx, ctx.Module())
- if productConfigProps, exists := productVariableProps["Enabled"]; exists {
- for productConfigProp, prop := range productConfigProps {
- flag, ok := prop.(*bool)
- if !ok {
- ctx.ModuleErrorf("Could not convert product variable enabled property")
- }
-
- if flag == nil {
- // soong config var is not used to set `enabled`. nothing to do.
- continue
- } else if *flag {
- axis := productConfigProp.ConfigurationAxis()
- result.SetSelectValue(axis, bazel.ConditionsDefaultConfigKey, bazel.MakeLabelList([]bazel.Label{{Label: "@platforms//:incompatible"}}))
- result.SetSelectValue(axis, productConfigProp.SelectKey(), bazel.LabelList{Includes: []bazel.Label{}})
- } else if scp, isSoongConfigProperty := productConfigProp.(SoongConfigProperty); isSoongConfigProperty && scp.value == bazel.ConditionsDefaultConfigKey {
- // productVariableConfigEnableAttribute runs only if `enabled: false` is set at the top-level outside soong_config_variables
- // conditions_default { enabled: false} is a no-op in this case
- continue
- } else {
- // TODO(b/210546943): handle negative case where `enabled: false`
- ctx.ModuleErrorf("`enabled: false` is not currently supported for configuration variables. See b/210546943")
- }
- }
- }
-
- return result
-}
-
// A ModuleBase object contains the properties that are common to all Android
// modules. It should be included as an anonymous field in every module
// struct definition. InitAndroidModule should then be called from the module's
@@ -1569,7 +849,12 @@
// katiInstalls tracks the install rules that were created by Soong but are being exported
// to Make to convert to ninja rules so that Make can add additional dependencies.
katiInstalls katiInstalls
- katiSymlinks katiInstalls
+ // katiInitRcInstalls and katiVintfInstalls track the install rules created by Soong that are
+ // allowed to have duplicates across modules and variants.
+ katiInitRcInstalls katiInstalls
+ katiVintfInstalls katiInstalls
+ katiSymlinks katiInstalls
+ testData []DataPath
// The files to copy to the dist as explicitly specified in the .bp file.
distFiles TaggedDistFiles
@@ -1592,101 +877,19 @@
initRcPaths Paths
vintfFragmentsPaths Paths
+ installedInitRcPaths InstallPaths
+ installedVintfFragmentsPaths InstallPaths
+
// set of dependency module:location mappings used to populate the license metadata for
// apex containers.
licenseInstallMap []string
// The path to the generated license metadata file for the module.
licenseMetadataFile WritablePath
-}
-// A struct containing all relevant information about a Bazel target converted via bp2build.
-type bp2buildInfo struct {
- Dir string
- BazelProps bazel.BazelTargetModuleProperties
- CommonAttrs CommonAttributes
- ConstraintAttrs constraintAttributes
- Attrs interface{}
-}
-
-// TargetName returns the Bazel target name of a bp2build converted target.
-func (b bp2buildInfo) TargetName() string {
- return b.CommonAttrs.Name
-}
-
-// TargetPackage returns the Bazel package of a bp2build converted target.
-func (b bp2buildInfo) TargetPackage() string {
- return b.Dir
-}
-
-// BazelRuleClass returns the Bazel rule class of a bp2build converted target.
-func (b bp2buildInfo) BazelRuleClass() string {
- return b.BazelProps.Rule_class
-}
-
-// BazelRuleLoadLocation returns the location of the Bazel rule of a bp2build converted target.
-// This may be empty as native Bazel rules do not need to be loaded.
-func (b bp2buildInfo) BazelRuleLoadLocation() string {
- return b.BazelProps.Bzl_load_location
-}
-
-// BazelAttributes returns the Bazel attributes of a bp2build converted target.
-func (b bp2buildInfo) BazelAttributes() []interface{} {
- return []interface{}{&b.CommonAttrs, &b.ConstraintAttrs, b.Attrs}
-}
-
-func (m *ModuleBase) addBp2buildInfo(info bp2buildInfo) {
- if m.commonProperties.BazelConversionStatus.UnconvertedReason != nil {
- panic(fmt.Errorf("bp2build: module '%s' marked unconvertible and also is converted", m.Name()))
- }
- m.commonProperties.BazelConversionStatus.Bp2buildInfo = append(m.commonProperties.BazelConversionStatus.Bp2buildInfo, info)
-}
-
-func (m *ModuleBase) setBp2buildUnconvertible(reasonType bp2build_metrics_proto.UnconvertedReasonType, detail string) {
- if len(m.commonProperties.BazelConversionStatus.Bp2buildInfo) > 0 {
- panic(fmt.Errorf("bp2build: module '%s' marked unconvertible and also is converted", m.Name()))
- }
- m.commonProperties.BazelConversionStatus.UnconvertedReason = &UnconvertedReason{
- ReasonType: int(reasonType),
- Detail: detail,
- }
-}
-
-// IsConvertedByBp2build returns whether this module was converted via bp2build.
-func (m *ModuleBase) IsConvertedByBp2build() bool {
- return len(m.commonProperties.BazelConversionStatus.Bp2buildInfo) > 0
-}
-
-func (m *ModuleBase) GetUnconvertedReason() *UnconvertedReason {
- return m.commonProperties.BazelConversionStatus.UnconvertedReason
-}
-
-// Bp2buildTargets returns the Bazel targets bp2build generated for this module.
-func (m *ModuleBase) Bp2buildTargets() []bp2buildInfo {
- return m.commonProperties.BazelConversionStatus.Bp2buildInfo
-}
-
-// AddUnconvertedBp2buildDep stores module name of a dependency that was not converted to Bazel.
-func (b *baseModuleContext) AddUnconvertedBp2buildDep(dep string) {
- unconvertedDeps := &b.Module().base().commonProperties.BazelConversionStatus.UnconvertedDeps
- *unconvertedDeps = append(*unconvertedDeps, dep)
-}
-
-// AddMissingBp2buildDep stores module name of a dependency that was not found in a Android.bp file.
-func (b *baseModuleContext) AddMissingBp2buildDep(dep string) {
- missingDeps := &b.Module().base().commonProperties.BazelConversionStatus.MissingDeps
- *missingDeps = append(*missingDeps, dep)
-}
-
-// GetUnconvertedBp2buildDeps returns the list of module names of this module's direct dependencies that
-// were not converted to Bazel.
-func (m *ModuleBase) GetUnconvertedBp2buildDeps() []string {
- return FirstUniqueStrings(m.commonProperties.BazelConversionStatus.UnconvertedDeps)
-}
-
-// GetMissingBp2buildDeps returns the list of module names that were not found in Android.bp files.
-func (m *ModuleBase) GetMissingBp2buildDeps() []string {
- return FirstUniqueStrings(m.commonProperties.BazelConversionStatus.MissingDeps)
+ // moduleInfoJSON can be filled out by GenerateAndroidBuildActions to write a JSON file that will
+ // be included in the final module-info.json produced by Make.
+ moduleInfoJSON *ModuleInfoJSON
}
func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
@@ -1798,6 +1001,12 @@
func (m *ModuleBase) DepsMutator(BottomUpMutatorContext) {}
+func (m *ModuleBase) baseDepsMutator(ctx BottomUpMutatorContext) {
+ if m.Team() != "" {
+ ctx.AddDependency(ctx.Module(), teamDepTag, m.Team())
+ }
+}
+
// AddProperties "registers" the provided props
// each value in props MUST be a pointer to a struct
func (m *ModuleBase) AddProperties(props ...interface{}) {
@@ -2219,6 +1428,14 @@
return Bool(m.commonProperties.Recovery)
}
+func (m *ModuleBase) InstallInOdm() bool {
+ return false
+}
+
+func (m *ModuleBase) InstallInProduct() bool {
+ return false
+}
+
func (m *ModuleBase) InstallInVendor() bool {
return Bool(m.commonProperties.Vendor) || Bool(m.commonProperties.Soc_specific) || Bool(m.commonProperties.Proprietary)
}
@@ -2235,6 +1452,10 @@
return String(m.commonProperties.Owner)
}
+func (m *ModuleBase) Team() string {
+ return String(m.commonProperties.Team)
+}
+
func (m *ModuleBase) setImageVariation(variant string) {
m.commonProperties.ImageVariation = variant
}
@@ -2420,14 +1641,31 @@
func (m *ModuleBase) baseModuleContextFactory(ctx blueprint.BaseModuleContext) baseModuleContext {
return baseModuleContext{
bp: ctx,
+ archModuleContext: m.archModuleContextFactory(ctx),
earlyModuleContext: m.earlyModuleContextFactory(ctx),
- os: m.commonProperties.CompileOS,
- target: m.commonProperties.CompileTarget,
- targetPrimary: m.commonProperties.CompilePrimary,
- multiTargets: m.commonProperties.CompileMultiTargets,
}
}
+func (m *ModuleBase) archModuleContextFactory(ctx blueprint.IncomingTransitionContext) archModuleContext {
+ config := ctx.Config().(Config)
+ target := m.Target()
+ primaryArch := false
+ if len(config.Targets[target.Os]) <= 1 {
+ primaryArch = true
+ } else {
+ primaryArch = target.Arch.ArchType == config.Targets[target.Os][0].Arch.ArchType
+ }
+
+ return archModuleContext{
+ os: m.commonProperties.CompileOS,
+ target: m.commonProperties.CompileTarget,
+ targetPrimary: m.commonProperties.CompilePrimary,
+ multiTargets: m.commonProperties.CompileMultiTargets,
+ primaryArch: primaryArch,
+ }
+
+}
+
func (m *ModuleBase) GenerateBuildActions(blueprintCtx blueprint.ModuleContext) {
ctx := &moduleContext{
module: m.module,
@@ -2468,7 +1706,7 @@
if !ctx.PrimaryArch() {
suffix = append(suffix, ctx.Arch().ArchType.String())
}
- if apexInfo := ctx.Provider(ApexInfoProvider).(ApexInfo); !apexInfo.IsForPlatform() {
+ if apexInfo, _ := ModuleProvider(ctx, ApexInfoProvider); !apexInfo.IsForPlatform() {
suffix = append(suffix, apexInfo.ApexVariationName)
}
@@ -2490,34 +1728,58 @@
// ensure all direct android.Module deps are enabled
ctx.VisitDirectDepsBlueprint(func(bm blueprint.Module) {
if m, ok := bm.(Module); ok {
- ctx.validateAndroidModule(bm, ctx.OtherModuleDependencyTag(m), ctx.baseModuleContext.strictVisitDeps)
+ ctx.validateAndroidModule(bm, ctx.OtherModuleDependencyTag(m), ctx.baseModuleContext.strictVisitDeps, false)
}
})
+ if m.Device() {
+ // Handle any init.rc and vintf fragment files requested by the module. All files installed by this
+ // module will automatically have a dependency on the installed init.rc or vintf fragment file.
+ // The same init.rc or vintf fragment file may be requested by multiple modules or variants,
+ // so instead of installing them now just compute the install path and store it for later.
+ // The full list of all init.rc and vintf fragment install rules will be deduplicated later
+ // so only a single rule is created for each init.rc or vintf fragment file.
+
+ if !m.InVendorRamdisk() {
+ m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
+ rcDir := PathForModuleInstall(ctx, "etc", "init")
+ for _, src := range m.initRcPaths {
+ installedInitRc := rcDir.Join(ctx, src.Base())
+ m.katiInitRcInstalls = append(m.katiInitRcInstalls, katiInstall{
+ from: src,
+ to: installedInitRc,
+ })
+ ctx.PackageFile(rcDir, src.Base(), src)
+ m.installedInitRcPaths = append(m.installedInitRcPaths, installedInitRc)
+ }
+ }
+
+ m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
+ vintfDir := PathForModuleInstall(ctx, "etc", "vintf", "manifest")
+ for _, src := range m.vintfFragmentsPaths {
+ installedVintfFragment := vintfDir.Join(ctx, src.Base())
+ m.katiVintfInstalls = append(m.katiVintfInstalls, katiInstall{
+ from: src,
+ to: installedVintfFragment,
+ })
+ ctx.PackageFile(vintfDir, src.Base(), src)
+ m.installedVintfFragmentsPaths = append(m.installedVintfFragmentsPaths, installedVintfFragment)
+ }
+ }
+
licensesPropertyFlattener(ctx)
if ctx.Failed() {
return
}
- if mixedBuildMod, handled := m.isHandledByBazel(ctx); handled {
- mixedBuildMod.ProcessBazelQueryResponse(ctx)
- } else {
- m.module.GenerateAndroidBuildActions(ctx)
- }
+ m.module.GenerateAndroidBuildActions(ctx)
if ctx.Failed() {
return
}
- m.initRcPaths = PathsForModuleSrc(ctx, m.commonProperties.Init_rc)
- rcDir := PathForModuleInstall(ctx, "etc", "init")
- for _, src := range m.initRcPaths {
- ctx.PackageFile(rcDir, filepath.Base(src.String()), src)
- }
-
- m.vintfFragmentsPaths = PathsForModuleSrc(ctx, m.commonProperties.Vintf_fragments)
- vintfDir := PathForModuleInstall(ctx, "etc", "vintf", "manifest")
- for _, src := range m.vintfFragmentsPaths {
- ctx.PackageFile(vintfDir, filepath.Base(src.String()), src)
+ aconfigUpdateAndroidBuildActions(ctx)
+ if ctx.Failed() {
+ return
}
// Create the set of tagged dist files after calling GenerateAndroidBuildActions
@@ -2534,6 +1796,7 @@
m.packagingSpecs = append(m.packagingSpecs, ctx.packagingSpecs...)
m.katiInstalls = append(m.katiInstalls, ctx.katiInstalls...)
m.katiSymlinks = append(m.katiSymlinks, ctx.katiSymlinks...)
+ m.testData = append(m.testData, ctx.testData...)
} else if ctx.Config().AllowMissingDependencies() {
// If the module is not enabled it will not create any build rules, nothing will call
// ctx.GetMissingDependencies(), and blueprint will consider the missing dependencies to be unhandled
@@ -2554,18 +1817,88 @@
buildLicenseMetadata(ctx, m.licenseMetadataFile)
+ if m.moduleInfoJSON != nil {
+ var installed InstallPaths
+ installed = append(installed, m.katiInstalls.InstallPaths()...)
+ installed = append(installed, m.katiSymlinks.InstallPaths()...)
+ installed = append(installed, m.katiInitRcInstalls.InstallPaths()...)
+ installed = append(installed, m.katiVintfInstalls.InstallPaths()...)
+ installedStrings := installed.Strings()
+
+ var targetRequired, hostRequired []string
+ if ctx.Host() {
+ targetRequired = m.commonProperties.Target_required
+ } else {
+ hostRequired = m.commonProperties.Host_required
+ }
+
+ var data []string
+ for _, d := range m.testData {
+ data = append(data, d.ToRelativeInstallPath())
+ }
+
+ if m.moduleInfoJSON.Uninstallable {
+ installedStrings = nil
+ if len(m.moduleInfoJSON.CompatibilitySuites) == 1 && m.moduleInfoJSON.CompatibilitySuites[0] == "null-suite" {
+ m.moduleInfoJSON.CompatibilitySuites = nil
+ m.moduleInfoJSON.TestConfig = nil
+ m.moduleInfoJSON.AutoTestConfig = nil
+ data = nil
+ }
+ }
+
+ m.moduleInfoJSON.core = CoreModuleInfoJSON{
+ RegisterName: m.moduleInfoRegisterName(ctx, m.moduleInfoJSON.SubName),
+ Path: []string{ctx.ModuleDir()},
+ Installed: installedStrings,
+ ModuleName: m.BaseModuleName() + m.moduleInfoJSON.SubName,
+ SupportedVariants: []string{m.moduleInfoVariant(ctx)},
+ TargetDependencies: targetRequired,
+ HostDependencies: hostRequired,
+ Data: data,
+ }
+ SetProvider(ctx, ModuleInfoJSONProvider, m.moduleInfoJSON)
+ }
+
m.buildParams = ctx.buildParams
m.ruleParams = ctx.ruleParams
m.variables = ctx.variables
}
-func (m *ModuleBase) isHandledByBazel(ctx ModuleContext) (MixedBuildBuildable, bool) {
- if mixedBuildMod, ok := m.module.(MixedBuildBuildable); ok {
- if mixedBuildMod.IsMixedBuildSupported(ctx) && (MixedBuildsEnabled(ctx) == MixedBuildEnabled) {
- return mixedBuildMod, true
+func (m *ModuleBase) moduleInfoRegisterName(ctx ModuleContext, subName string) string {
+ name := m.BaseModuleName()
+
+ prefix := ""
+ if ctx.Host() {
+ if ctx.Os() != ctx.Config().BuildOS {
+ prefix = "host_cross_"
}
}
- return nil, false
+ suffix := ""
+ arches := slices.Clone(ctx.Config().Targets[ctx.Os()])
+ arches = slices.DeleteFunc(arches, func(target Target) bool {
+ return target.NativeBridge != ctx.Target().NativeBridge
+ })
+ if len(arches) > 0 && ctx.Arch().ArchType != arches[0].Arch.ArchType {
+ if ctx.Arch().ArchType.Multilib == "lib32" {
+ suffix = "_32"
+ } else {
+ suffix = "_64"
+ }
+ }
+ return prefix + name + subName + suffix
+}
+
+func (m *ModuleBase) moduleInfoVariant(ctx ModuleContext) string {
+ variant := "DEVICE"
+ if ctx.Host() {
+ if ctx.Os() != ctx.Config().BuildOS {
+ variant = "HOST_CROSS"
+ } else {
+ variant = "HOST"
+ }
+ }
+ return variant
}
// Check the supplied dist structure to make sure that it is valid.
@@ -2594,163 +1927,6 @@
}
-type earlyModuleContext struct {
- blueprint.EarlyModuleContext
-
- kind moduleKind
- config Config
-}
-
-func (e *earlyModuleContext) Glob(globPattern string, excludes []string) Paths {
- return Glob(e, globPattern, excludes)
-}
-
-func (e *earlyModuleContext) GlobFiles(globPattern string, excludes []string) Paths {
- return GlobFiles(e, globPattern, excludes)
-}
-
-func (e *earlyModuleContext) IsSymlink(path Path) bool {
- fileInfo, err := e.config.fs.Lstat(path.String())
- if err != nil {
- e.ModuleErrorf("os.Lstat(%q) failed: %s", path.String(), err)
- }
- return fileInfo.Mode()&os.ModeSymlink == os.ModeSymlink
-}
-
-func (e *earlyModuleContext) Readlink(path Path) string {
- dest, err := e.config.fs.Readlink(path.String())
- if err != nil {
- e.ModuleErrorf("os.Readlink(%q) failed: %s", path.String(), err)
- }
- return dest
-}
-
-func (e *earlyModuleContext) Module() Module {
- module, _ := e.EarlyModuleContext.Module().(Module)
- return module
-}
-
-func (e *earlyModuleContext) Config() Config {
- return e.EarlyModuleContext.Config().(Config)
-}
-
-func (e *earlyModuleContext) AConfig() Config {
- return e.config
-}
-
-func (e *earlyModuleContext) DeviceConfig() DeviceConfig {
- return DeviceConfig{e.config.deviceConfig}
-}
-
-func (e *earlyModuleContext) Platform() bool {
- return e.kind == platformModule
-}
-
-func (e *earlyModuleContext) DeviceSpecific() bool {
- return e.kind == deviceSpecificModule
-}
-
-func (e *earlyModuleContext) SocSpecific() bool {
- return e.kind == socSpecificModule
-}
-
-func (e *earlyModuleContext) ProductSpecific() bool {
- return e.kind == productSpecificModule
-}
-
-func (e *earlyModuleContext) SystemExtSpecific() bool {
- return e.kind == systemExtSpecificModule
-}
-
-func (e *earlyModuleContext) Namespace() *Namespace {
- return e.EarlyModuleContext.Namespace().(*Namespace)
-}
-
-type baseModuleContext struct {
- bp blueprint.BaseModuleContext
- earlyModuleContext
- os OsType
- target Target
- multiTargets []Target
- targetPrimary bool
- debug bool
-
- walkPath []Module
- tagPath []blueprint.DependencyTag
-
- strictVisitDeps bool // If true, enforce that all dependencies are enabled
-
- bazelConversionMode bool
-}
-
-func (b *baseModuleContext) isBazelConversionMode() bool {
- return b.bazelConversionMode
-}
-func (b *baseModuleContext) OtherModuleName(m blueprint.Module) string {
- return b.bp.OtherModuleName(m)
-}
-func (b *baseModuleContext) OtherModuleDir(m blueprint.Module) string { return b.bp.OtherModuleDir(m) }
-func (b *baseModuleContext) OtherModuleErrorf(m blueprint.Module, fmt string, args ...interface{}) {
- b.bp.OtherModuleErrorf(m, fmt, args...)
-}
-func (b *baseModuleContext) OtherModuleDependencyTag(m blueprint.Module) blueprint.DependencyTag {
- return b.bp.OtherModuleDependencyTag(m)
-}
-func (b *baseModuleContext) OtherModuleExists(name string) bool { return b.bp.OtherModuleExists(name) }
-func (b *baseModuleContext) OtherModuleDependencyVariantExists(variations []blueprint.Variation, name string) bool {
- return b.bp.OtherModuleDependencyVariantExists(variations, name)
-}
-func (b *baseModuleContext) OtherModuleFarDependencyVariantExists(variations []blueprint.Variation, name string) bool {
- return b.bp.OtherModuleFarDependencyVariantExists(variations, name)
-}
-func (b *baseModuleContext) OtherModuleReverseDependencyVariantExists(name string) bool {
- return b.bp.OtherModuleReverseDependencyVariantExists(name)
-}
-func (b *baseModuleContext) OtherModuleType(m blueprint.Module) string {
- return b.bp.OtherModuleType(m)
-}
-func (b *baseModuleContext) OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{} {
- return b.bp.OtherModuleProvider(m, provider)
-}
-func (b *baseModuleContext) OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool {
- return b.bp.OtherModuleHasProvider(m, provider)
-}
-func (b *baseModuleContext) Provider(provider blueprint.ProviderKey) interface{} {
- return b.bp.Provider(provider)
-}
-func (b *baseModuleContext) HasProvider(provider blueprint.ProviderKey) bool {
- return b.bp.HasProvider(provider)
-}
-func (b *baseModuleContext) SetProvider(provider blueprint.ProviderKey, value interface{}) {
- b.bp.SetProvider(provider, value)
-}
-
-func (b *baseModuleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
- return b.bp.GetDirectDepWithTag(name, tag)
-}
-
-func (b *baseModuleContext) blueprintBaseModuleContext() blueprint.BaseModuleContext {
- return b.bp
-}
-
-type moduleContext struct {
- bp blueprint.ModuleContext
- baseModuleContext
- packagingSpecs []PackagingSpec
- installFiles InstallPaths
- checkbuildFiles Paths
- module Module
- phonies map[string]Paths
-
- katiInstalls []katiInstall
- katiSymlinks []katiInstall
-
- // For tests
- buildParams []BuildParams
- ruleParams map[blueprint.Rule]blueprint.RuleParams
- variables map[string]string
-}
-
// katiInstall stores a request from Soong to Make to create an install rule.
type katiInstall struct {
from Path
@@ -2794,517 +1970,6 @@
return paths
}
-func (m *moduleContext) ninjaError(params BuildParams, err error) (PackageContext, BuildParams) {
- return pctx, BuildParams{
- Rule: ErrorRule,
- Description: params.Description,
- Output: params.Output,
- Outputs: params.Outputs,
- ImplicitOutput: params.ImplicitOutput,
- ImplicitOutputs: params.ImplicitOutputs,
- Args: map[string]string{
- "error": err.Error(),
- },
- }
-}
-
-func (m *moduleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) {
- m.Build(pctx, BuildParams(params))
-}
-
-func validateBuildParams(params blueprint.BuildParams) error {
- // Validate that the symlink outputs are declared outputs or implicit outputs
- allOutputs := map[string]bool{}
- for _, output := range params.Outputs {
- allOutputs[output] = true
- }
- for _, output := range params.ImplicitOutputs {
- allOutputs[output] = true
- }
- for _, symlinkOutput := range params.SymlinkOutputs {
- if !allOutputs[symlinkOutput] {
- return fmt.Errorf(
- "Symlink output %s is not a declared output or implicit output",
- symlinkOutput)
- }
- }
- return nil
-}
-
-// Convert build parameters from their concrete Android types into their string representations,
-// and combine the singular and plural fields of the same type (e.g. Output and Outputs).
-func convertBuildParams(params BuildParams) blueprint.BuildParams {
- bparams := blueprint.BuildParams{
- Rule: params.Rule,
- Description: params.Description,
- Deps: params.Deps,
- Outputs: params.Outputs.Strings(),
- ImplicitOutputs: params.ImplicitOutputs.Strings(),
- SymlinkOutputs: params.SymlinkOutputs.Strings(),
- Inputs: params.Inputs.Strings(),
- Implicits: params.Implicits.Strings(),
- OrderOnly: params.OrderOnly.Strings(),
- Validations: params.Validations.Strings(),
- Args: params.Args,
- Optional: !params.Default,
- }
-
- if params.Depfile != nil {
- bparams.Depfile = params.Depfile.String()
- }
- if params.Output != nil {
- bparams.Outputs = append(bparams.Outputs, params.Output.String())
- }
- if params.SymlinkOutput != nil {
- bparams.SymlinkOutputs = append(bparams.SymlinkOutputs, params.SymlinkOutput.String())
- }
- if params.ImplicitOutput != nil {
- bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String())
- }
- if params.Input != nil {
- bparams.Inputs = append(bparams.Inputs, params.Input.String())
- }
- if params.Implicit != nil {
- bparams.Implicits = append(bparams.Implicits, params.Implicit.String())
- }
- if params.Validation != nil {
- bparams.Validations = append(bparams.Validations, params.Validation.String())
- }
-
- bparams.Outputs = proptools.NinjaEscapeList(bparams.Outputs)
- bparams.ImplicitOutputs = proptools.NinjaEscapeList(bparams.ImplicitOutputs)
- bparams.SymlinkOutputs = proptools.NinjaEscapeList(bparams.SymlinkOutputs)
- bparams.Inputs = proptools.NinjaEscapeList(bparams.Inputs)
- bparams.Implicits = proptools.NinjaEscapeList(bparams.Implicits)
- bparams.OrderOnly = proptools.NinjaEscapeList(bparams.OrderOnly)
- bparams.Validations = proptools.NinjaEscapeList(bparams.Validations)
- bparams.Depfile = proptools.NinjaEscape(bparams.Depfile)
-
- return bparams
-}
-
-func (m *moduleContext) Variable(pctx PackageContext, name, value string) {
- if m.config.captureBuild {
- m.variables[name] = value
- }
-
- m.bp.Variable(pctx.PackageContext, name, value)
-}
-
-func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
- argNames ...string) blueprint.Rule {
-
- if m.config.UseRemoteBuild() {
- if params.Pool == nil {
- // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
- // jobs to the local parallelism value
- params.Pool = localPool
- } else if params.Pool == remotePool {
- // remotePool is a fake pool used to identify rule that are supported for remoting. If the rule's
- // pool is the remotePool, replace with nil so that ninja runs it at NINJA_REMOTE_NUM_JOBS
- // parallelism.
- params.Pool = nil
- }
- }
-
- rule := m.bp.Rule(pctx.PackageContext, name, params, argNames...)
-
- if m.config.captureBuild {
- m.ruleParams[rule] = params
- }
-
- return rule
-}
-
-func (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
- if params.Description != "" {
- params.Description = "${moduleDesc}" + params.Description + "${moduleDescSuffix}"
- }
-
- if missingDeps := m.GetMissingDependencies(); len(missingDeps) > 0 {
- pctx, params = m.ninjaError(params, fmt.Errorf("module %s missing dependencies: %s\n",
- m.ModuleName(), strings.Join(missingDeps, ", ")))
- }
-
- if m.config.captureBuild {
- m.buildParams = append(m.buildParams, params)
- }
-
- bparams := convertBuildParams(params)
- err := validateBuildParams(bparams)
- if err != nil {
- m.ModuleErrorf(
- "%s: build parameter validation failed: %s",
- m.ModuleName(),
- err.Error())
- }
- m.bp.Build(pctx.PackageContext, bparams)
-}
-
-func (m *moduleContext) Phony(name string, deps ...Path) {
- addPhony(m.config, name, deps...)
-}
-
-func (m *moduleContext) GetMissingDependencies() []string {
- var missingDeps []string
- missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...)
- missingDeps = append(missingDeps, m.bp.GetMissingDependencies()...)
- missingDeps = FirstUniqueStrings(missingDeps)
- return missingDeps
-}
-
-func (b *baseModuleContext) AddMissingDependencies(deps []string) {
- if deps != nil {
- missingDeps := &b.Module().base().commonProperties.MissingDeps
- *missingDeps = append(*missingDeps, deps...)
- *missingDeps = FirstUniqueStrings(*missingDeps)
- }
-}
-
-func (b *baseModuleContext) checkedMissingDeps() bool {
- return b.Module().base().commonProperties.CheckedMissingDeps
-}
-
-func (b *baseModuleContext) getMissingDependencies() []string {
- checked := &b.Module().base().commonProperties.CheckedMissingDeps
- *checked = true
- var missingDeps []string
- missingDeps = append(missingDeps, b.Module().base().commonProperties.MissingDeps...)
- missingDeps = append(missingDeps, b.bp.EarlyGetMissingDependencies()...)
- missingDeps = FirstUniqueStrings(missingDeps)
- return missingDeps
-}
-
-type AllowDisabledModuleDependency interface {
- blueprint.DependencyTag
- AllowDisabledModuleDependency(target Module) bool
-}
-
-func (b *baseModuleContext) validateAndroidModule(module blueprint.Module, tag blueprint.DependencyTag, strict bool) Module {
- aModule, _ := module.(Module)
-
- if !strict {
- return aModule
- }
-
- if aModule == nil {
- b.ModuleErrorf("module %q (%#v) not an android module", b.OtherModuleName(module), tag)
- return nil
- }
-
- if !aModule.Enabled() {
- if t, ok := tag.(AllowDisabledModuleDependency); !ok || !t.AllowDisabledModuleDependency(aModule) {
- if b.Config().AllowMissingDependencies() {
- b.AddMissingDependencies([]string{b.OtherModuleName(aModule)})
- } else {
- b.ModuleErrorf("depends on disabled module %q", b.OtherModuleName(aModule))
- }
- }
- return nil
- }
- return aModule
-}
-
-type dep struct {
- mod blueprint.Module
- tag blueprint.DependencyTag
-}
-
-func (b *baseModuleContext) getDirectDepsInternal(name string, tag blueprint.DependencyTag) []dep {
- var deps []dep
- b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
- if aModule, _ := module.(Module); aModule != nil {
- if aModule.base().BaseModuleName() == name {
- returnedTag := b.bp.OtherModuleDependencyTag(aModule)
- if tag == nil || returnedTag == tag {
- deps = append(deps, dep{aModule, returnedTag})
- }
- }
- } else if b.bp.OtherModuleName(module) == name {
- returnedTag := b.bp.OtherModuleDependencyTag(module)
- if tag == nil || returnedTag == tag {
- deps = append(deps, dep{module, returnedTag})
- }
- }
- })
- return deps
-}
-
-func (b *baseModuleContext) getDirectDepInternal(name string, tag blueprint.DependencyTag) (blueprint.Module, blueprint.DependencyTag) {
- deps := b.getDirectDepsInternal(name, tag)
- if len(deps) == 1 {
- return deps[0].mod, deps[0].tag
- } else if len(deps) >= 2 {
- panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
- name, b.ModuleName()))
- } else {
- return nil, nil
- }
-}
-
-func (b *baseModuleContext) getDirectDepFirstTag(name string) (blueprint.Module, blueprint.DependencyTag) {
- foundDeps := b.getDirectDepsInternal(name, nil)
- deps := map[blueprint.Module]bool{}
- for _, dep := range foundDeps {
- deps[dep.mod] = true
- }
- if len(deps) == 1 {
- return foundDeps[0].mod, foundDeps[0].tag
- } else if len(deps) >= 2 {
- // this could happen if two dependencies have the same name in different namespaces
- // TODO(b/186554727): this should not occur if namespaces are handled within
- // getDirectDepsInternal.
- panic(fmt.Errorf("Multiple dependencies having same BaseModuleName() %q found from %q",
- name, b.ModuleName()))
- } else {
- return nil, nil
- }
-}
-
-func (b *baseModuleContext) GetDirectDepsWithTag(tag blueprint.DependencyTag) []Module {
- var deps []Module
- b.VisitDirectDepsBlueprint(func(module blueprint.Module) {
- if aModule, _ := module.(Module); aModule != nil {
- if b.bp.OtherModuleDependencyTag(aModule) == tag {
- deps = append(deps, aModule)
- }
- }
- })
- return deps
-}
-
-func (m *moduleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
- module, _ := m.getDirectDepInternal(name, tag)
- return module
-}
-
-// GetDirectDep returns the Module and DependencyTag for the direct dependency with the specified
-// name, or nil if none exists. If there are multiple dependencies on the same module it returns the
-// first DependencyTag.
-func (b *baseModuleContext) GetDirectDep(name string) (blueprint.Module, blueprint.DependencyTag) {
- return b.getDirectDepFirstTag(name)
-}
-
-func (b *baseModuleContext) ModuleFromName(name string) (blueprint.Module, bool) {
- if !b.isBazelConversionMode() {
- panic("cannot call ModuleFromName if not in bazel conversion mode")
- }
- if moduleName, _ := SrcIsModuleWithTag(name); moduleName != "" {
- return b.bp.ModuleFromName(moduleName)
- } else {
- return b.bp.ModuleFromName(name)
- }
-}
-
-func (b *baseModuleContext) VisitDirectDepsBlueprint(visit func(blueprint.Module)) {
- b.bp.VisitDirectDeps(visit)
-}
-
-func (b *baseModuleContext) VisitDirectDeps(visit func(Module)) {
- b.bp.VisitDirectDeps(func(module blueprint.Module) {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
- visit(aModule)
- }
- })
-}
-
-func (b *baseModuleContext) VisitDirectDepsWithTag(tag blueprint.DependencyTag, visit func(Module)) {
- b.bp.VisitDirectDeps(func(module blueprint.Module) {
- if b.bp.OtherModuleDependencyTag(module) == tag {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
- visit(aModule)
- }
- }
- })
-}
-
-func (b *baseModuleContext) VisitDirectDepsIf(pred func(Module) bool, visit func(Module)) {
- b.bp.VisitDirectDepsIf(
- // pred
- func(module blueprint.Module) bool {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
- return pred(aModule)
- } else {
- return false
- }
- },
- // visit
- func(module blueprint.Module) {
- visit(module.(Module))
- })
-}
-
-func (b *baseModuleContext) VisitDepsDepthFirst(visit func(Module)) {
- b.bp.VisitDepsDepthFirst(func(module blueprint.Module) {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
- visit(aModule)
- }
- })
-}
-
-func (b *baseModuleContext) VisitDepsDepthFirstIf(pred func(Module) bool, visit func(Module)) {
- b.bp.VisitDepsDepthFirstIf(
- // pred
- func(module blueprint.Module) bool {
- if aModule := b.validateAndroidModule(module, b.bp.OtherModuleDependencyTag(module), b.strictVisitDeps); aModule != nil {
- return pred(aModule)
- } else {
- return false
- }
- },
- // visit
- func(module blueprint.Module) {
- visit(module.(Module))
- })
-}
-
-func (b *baseModuleContext) WalkDepsBlueprint(visit func(blueprint.Module, blueprint.Module) bool) {
- b.bp.WalkDeps(visit)
-}
-
-func (b *baseModuleContext) WalkDeps(visit func(Module, Module) bool) {
- b.walkPath = []Module{b.Module()}
- b.tagPath = []blueprint.DependencyTag{}
- b.bp.WalkDeps(func(child, parent blueprint.Module) bool {
- childAndroidModule, _ := child.(Module)
- parentAndroidModule, _ := parent.(Module)
- if childAndroidModule != nil && parentAndroidModule != nil {
- // record walkPath before visit
- for b.walkPath[len(b.walkPath)-1] != parentAndroidModule {
- b.walkPath = b.walkPath[0 : len(b.walkPath)-1]
- b.tagPath = b.tagPath[0 : len(b.tagPath)-1]
- }
- b.walkPath = append(b.walkPath, childAndroidModule)
- b.tagPath = append(b.tagPath, b.OtherModuleDependencyTag(childAndroidModule))
- return visit(childAndroidModule, parentAndroidModule)
- } else {
- return false
- }
- })
-}
-
-func (b *baseModuleContext) GetWalkPath() []Module {
- return b.walkPath
-}
-
-func (b *baseModuleContext) GetTagPath() []blueprint.DependencyTag {
- return b.tagPath
-}
-
-func (b *baseModuleContext) VisitAllModuleVariants(visit func(Module)) {
- b.bp.VisitAllModuleVariants(func(module blueprint.Module) {
- visit(module.(Module))
- })
-}
-
-func (b *baseModuleContext) PrimaryModule() Module {
- return b.bp.PrimaryModule().(Module)
-}
-
-func (b *baseModuleContext) FinalModule() Module {
- return b.bp.FinalModule().(Module)
-}
-
-// IsMetaDependencyTag returns true for cross-cutting metadata dependencies.
-func IsMetaDependencyTag(tag blueprint.DependencyTag) bool {
- if tag == licenseKindTag {
- return true
- } else if tag == licensesTag {
- return true
- }
- return false
-}
-
-// A regexp for removing boilerplate from BaseDependencyTag from the string representation of
-// a dependency tag.
-var tagCleaner = regexp.MustCompile(`\QBaseDependencyTag:{}\E(, )?`)
-
-// PrettyPrintTag returns string representation of the tag, but prefers
-// custom String() method if available.
-func PrettyPrintTag(tag blueprint.DependencyTag) string {
- // Use tag's custom String() method if available.
- if stringer, ok := tag.(fmt.Stringer); ok {
- return stringer.String()
- }
-
- // Otherwise, get a default string representation of the tag's struct.
- tagString := fmt.Sprintf("%T: %+v", tag, tag)
-
- // Remove the boilerplate from BaseDependencyTag as it adds no value.
- tagString = tagCleaner.ReplaceAllString(tagString, "")
- return tagString
-}
-
-func (b *baseModuleContext) GetPathString(skipFirst bool) string {
- sb := strings.Builder{}
- tagPath := b.GetTagPath()
- walkPath := b.GetWalkPath()
- if !skipFirst {
- sb.WriteString(walkPath[0].String())
- }
- for i, m := range walkPath[1:] {
- sb.WriteString("\n")
- sb.WriteString(fmt.Sprintf(" via tag %s\n", PrettyPrintTag(tagPath[i])))
- sb.WriteString(fmt.Sprintf(" -> %s", m.String()))
- }
- return sb.String()
-}
-
-func (m *moduleContext) ModuleSubDir() string {
- return m.bp.ModuleSubDir()
-}
-
-func (m *moduleContext) SoongConfigTraceHash() string {
- return m.module.base().commonProperties.SoongConfigTraceHash
-}
-
-func (b *baseModuleContext) Target() Target {
- return b.target
-}
-
-func (b *baseModuleContext) TargetPrimary() bool {
- return b.targetPrimary
-}
-
-func (b *baseModuleContext) MultiTargets() []Target {
- return b.multiTargets
-}
-
-func (b *baseModuleContext) Arch() Arch {
- return b.target.Arch
-}
-
-func (b *baseModuleContext) Os() OsType {
- return b.os
-}
-
-func (b *baseModuleContext) Host() bool {
- return b.os.Class == Host
-}
-
-func (b *baseModuleContext) Device() bool {
- return b.os.Class == Device
-}
-
-func (b *baseModuleContext) Darwin() bool {
- return b.os == Darwin
-}
-
-func (b *baseModuleContext) Windows() bool {
- return b.os == Windows
-}
-
-func (b *baseModuleContext) Debug() bool {
- return b.debug
-}
-
-func (b *baseModuleContext) PrimaryArch() bool {
- if len(b.config.Targets[b.target.Os]) <= 1 {
- return true
- }
- return b.target.Arch.ArchType == b.config.Targets[b.target.Os][0].Arch.ArchType
-}
-
// Makes this module a platform module, i.e. not specific to soc, device,
// product, or system_ext.
func (m *ModuleBase) MakeAsPlatform() {
@@ -3328,272 +1993,16 @@
return proptools.Bool(m.commonProperties.Native_bridge_supported)
}
-func (m *moduleContext) InstallInData() bool {
- return m.module.InstallInData()
-}
-
-func (m *moduleContext) InstallInTestcases() bool {
- return m.module.InstallInTestcases()
-}
-
-func (m *moduleContext) InstallInSanitizerDir() bool {
- return m.module.InstallInSanitizerDir()
-}
-
-func (m *moduleContext) InstallInRamdisk() bool {
- return m.module.InstallInRamdisk()
-}
-
-func (m *moduleContext) InstallInVendorRamdisk() bool {
- return m.module.InstallInVendorRamdisk()
-}
-
-func (m *moduleContext) InstallInDebugRamdisk() bool {
- return m.module.InstallInDebugRamdisk()
-}
-
-func (m *moduleContext) InstallInRecovery() bool {
- return m.module.InstallInRecovery()
-}
-
-func (m *moduleContext) InstallInRoot() bool {
- return m.module.InstallInRoot()
-}
-
-func (m *moduleContext) InstallForceOS() (*OsType, *ArchType) {
- return m.module.InstallForceOS()
-}
-
-func (m *moduleContext) InstallInVendor() bool {
- return m.module.InstallInVendor()
-}
-
-func (m *moduleContext) skipInstall() bool {
- if m.module.base().commonProperties.SkipInstall {
- return true
- }
-
- if m.module.base().commonProperties.HideFromMake {
- return true
- }
-
- // We'll need a solution for choosing which of modules with the same name in different
- // namespaces to install. For now, reuse the list of namespaces exported to Make as the
- // list of namespaces to install in a Soong-only build.
- if !m.module.base().commonProperties.NamespaceExportedToMake {
- return true
- }
-
- return false
-}
-
-func (m *moduleContext) InstallFile(installPath InstallPath, name string, srcPath Path,
- deps ...Path) InstallPath {
- return m.installFile(installPath, name, srcPath, deps, false, nil)
-}
-
-func (m *moduleContext) InstallExecutable(installPath InstallPath, name string, srcPath Path,
- deps ...Path) InstallPath {
- return m.installFile(installPath, name, srcPath, deps, true, nil)
-}
-
-func (m *moduleContext) InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path,
- extraZip Path, deps ...Path) InstallPath {
- return m.installFile(installPath, name, srcPath, deps, false, &extraFilesZip{
- zip: extraZip,
- dir: installPath,
- })
-}
-
-func (m *moduleContext) PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec {
- fullInstallPath := installPath.Join(m, name)
- return m.packageFile(fullInstallPath, srcPath, false)
-}
-
-func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec {
- licenseFiles := m.Module().EffectiveLicenseFiles()
- spec := PackagingSpec{
- relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
- srcPath: srcPath,
- symlinkTarget: "",
- executable: executable,
- effectiveLicenseFiles: &licenseFiles,
- partition: fullInstallPath.partition,
- }
- m.packagingSpecs = append(m.packagingSpecs, spec)
- return spec
-}
-
-func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path, deps []Path,
- executable bool, extraZip *extraFilesZip) InstallPath {
-
- fullInstallPath := installPath.Join(m, name)
- m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
-
- if !m.skipInstall() {
- deps = append(deps, InstallPaths(m.module.base().installFilesDepSet.ToList()).Paths()...)
-
- var implicitDeps, orderOnlyDeps Paths
-
- if m.Host() {
- // Installed host modules might be used during the build, depend directly on their
- // dependencies so their timestamp is updated whenever their dependency is updated
- implicitDeps = deps
- } else {
- orderOnlyDeps = deps
+// ModuleNameWithPossibleOverride returns the name of the OverrideModule that overrides the current
+// variant of this OverridableModule, or ctx.ModuleName() if this module is not an OverridableModule
+// or if this variant is not overridden.
+func ModuleNameWithPossibleOverride(ctx BaseModuleContext) string {
+ if overridable, ok := ctx.Module().(OverridableModule); ok {
+ if o := overridable.GetOverriddenBy(); o != "" {
+ return o
}
-
- if m.Config().KatiEnabled() {
- // When creating the install rule in Soong but embedding in Make, write the rule to a
- // makefile instead of directly to the ninja file so that main.mk can add the
- // dependencies from the `required` property that are hard to resolve in Soong.
- m.katiInstalls = append(m.katiInstalls, katiInstall{
- from: srcPath,
- to: fullInstallPath,
- implicitDeps: implicitDeps,
- orderOnlyDeps: orderOnlyDeps,
- executable: executable,
- extraFiles: extraZip,
- })
- } else {
- rule := Cp
- if executable {
- rule = CpExecutable
- }
-
- extraCmds := ""
- if extraZip != nil {
- extraCmds += fmt.Sprintf(" && ( unzip -qDD -d '%s' '%s' 2>&1 | grep -v \"zipfile is empty\"; exit $${PIPESTATUS[0]} )",
- extraZip.dir.String(), extraZip.zip.String())
- extraCmds += " || ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )"
- implicitDeps = append(implicitDeps, extraZip.zip)
- }
-
- m.Build(pctx, BuildParams{
- Rule: rule,
- Description: "install " + fullInstallPath.Base(),
- Output: fullInstallPath,
- Input: srcPath,
- Implicits: implicitDeps,
- OrderOnly: orderOnlyDeps,
- Default: !m.Config().KatiEnabled(),
- Args: map[string]string{
- "extraCmds": extraCmds,
- },
- })
- }
-
- m.installFiles = append(m.installFiles, fullInstallPath)
}
-
- m.packageFile(fullInstallPath, srcPath, executable)
-
- m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
-
- return fullInstallPath
-}
-
-func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath {
- fullInstallPath := installPath.Join(m, name)
- m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, true)
-
- relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
- if err != nil {
- panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
- }
- if !m.skipInstall() {
-
- if m.Config().KatiEnabled() {
- // When creating the symlink rule in Soong but embedding in Make, write the rule to a
- // makefile instead of directly to the ninja file so that main.mk can add the
- // dependencies from the `required` property that are hard to resolve in Soong.
- m.katiSymlinks = append(m.katiSymlinks, katiInstall{
- from: srcPath,
- to: fullInstallPath,
- })
- } else {
- // The symlink doesn't need updating when the target is modified, but we sometimes
- // have a dependency on a symlink to a binary instead of to the binary directly, and
- // the mtime of the symlink must be updated when the binary is modified, so use a
- // normal dependency here instead of an order-only dependency.
- m.Build(pctx, BuildParams{
- Rule: Symlink,
- Description: "install symlink " + fullInstallPath.Base(),
- Output: fullInstallPath,
- Input: srcPath,
- Default: !m.Config().KatiEnabled(),
- Args: map[string]string{
- "fromPath": relPath,
- },
- })
- }
-
- m.installFiles = append(m.installFiles, fullInstallPath)
- m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
- }
-
- m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
- relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
- srcPath: nil,
- symlinkTarget: relPath,
- executable: false,
- partition: fullInstallPath.partition,
- })
-
- return fullInstallPath
-}
-
-// installPath/name -> absPath where absPath might be a path that is available only at runtime
-// (e.g. /apex/...)
-func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath {
- fullInstallPath := installPath.Join(m, name)
- m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)
-
- if !m.skipInstall() {
- if m.Config().KatiEnabled() {
- // When creating the symlink rule in Soong but embedding in Make, write the rule to a
- // makefile instead of directly to the ninja file so that main.mk can add the
- // dependencies from the `required` property that are hard to resolve in Soong.
- m.katiSymlinks = append(m.katiSymlinks, katiInstall{
- absFrom: absPath,
- to: fullInstallPath,
- })
- } else {
- m.Build(pctx, BuildParams{
- Rule: Symlink,
- Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
- Output: fullInstallPath,
- Default: !m.Config().KatiEnabled(),
- Args: map[string]string{
- "fromPath": absPath,
- },
- })
- }
-
- m.installFiles = append(m.installFiles, fullInstallPath)
- }
-
- m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
- relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
- srcPath: nil,
- symlinkTarget: absPath,
- executable: false,
- partition: fullInstallPath.partition,
- })
-
- return fullInstallPath
-}
-
-func (m *moduleContext) CheckbuildFile(srcPath Path) {
- m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
-}
-
-func (m *moduleContext) blueprintModuleContext() blueprint.ModuleContext {
- return m.bp
-}
-
-func (m *moduleContext) LicenseMetadataFile() Path {
- return m.module.base().licenseMetadataFile
+ return ctx.ModuleName()
}
// SrcIsModule decodes module references in the format ":unqualified-name" or "//namespace:name"
@@ -3802,44 +2211,6 @@
HostToolPath() OptionalPath
}
-// Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must
-// be tagged with `android:"path" to support automatic source module dependency resolution.
-//
-// Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
-func (m *moduleContext) ExpandSources(srcFiles, excludes []string) Paths {
- return PathsForModuleSrcExcludes(m, srcFiles, excludes)
-}
-
-// Returns a single path expanded from globs and modules referenced using ":module" syntax. The property must
-// be tagged with `android:"path" to support automatic source module dependency resolution.
-//
-// Deprecated: use PathForModuleSrc instead.
-func (m *moduleContext) ExpandSource(srcFile, _ string) Path {
- return PathForModuleSrc(m, srcFile)
-}
-
-// Returns an optional single path expanded from globs and modules referenced using ":module" syntax if
-// the srcFile is non-nil. The property must be tagged with `android:"path" to support automatic source module
-// dependency resolution.
-func (m *moduleContext) ExpandOptionalSource(srcFile *string, _ string) OptionalPath {
- if srcFile != nil {
- return OptionalPathForPath(PathForModuleSrc(m, *srcFile))
- }
- return OptionalPath{}
-}
-
-func (m *moduleContext) RequiredModuleNames() []string {
- return m.module.RequiredModuleNames()
-}
-
-func (m *moduleContext) HostRequiredModuleNames() []string {
- return m.module.HostRequiredModuleNames()
-}
-
-func (m *moduleContext) TargetRequiredModuleNames() []string {
- return m.module.TargetRequiredModuleNames()
-}
-
func init() {
RegisterParallelSingletonType("buildtarget", BuildTargetSingleton)
RegisterParallelSingletonType("soongconfigtrace", soongConfigTraceSingletonFunc)
@@ -4056,36 +2427,3 @@
WriteFileRule(ctx, outFile, string(j))
ctx.Phony("soong_config_trace", outFile)
}
-
-// Interface implemented by xsd_config which has 1:many mappings in bp2build workspace
-// This interface exists because we want to
-// 1. Determine the name of the additional targets generated by the primary soong module
-// 2. Enable distinguishing an xsd_config module from other Soong modules using type assertion
-type XsdConfigBp2buildTargets interface {
- CppBp2buildTargetName() string
- JavaBp2buildTargetName() string
-}
-
-// XsdModuleToTargetName is a function that takes an XsdConfigBp2buildTarget
-type XsdModuleToTargetName func(xsd XsdConfigBp2buildTargets) string
-
-// XsdLabelMapper returns a bazel.LabelMapper for partitioning XSD sources/headers given an
-// XsdModuleToTargetName function.
-func XsdLabelMapper(targetName XsdModuleToTargetName) bazel.LabelMapper {
- return func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
- mod, exists := ctx.ModuleFromName(label.OriginalModuleName)
- if !exists {
- return label.Label, false
- }
- xsdMod, isXsd := mod.(XsdConfigBp2buildTargets)
- if !isXsd {
- return label.Label, false
- }
-
- // Remove the base module name
- ret := strings.TrimSuffix(label.Label, mod.Name())
- // Append the language specific target name
- ret += targetName(xsdMod)
- return ret, true
- }
-}
diff --git a/android/module_context.go b/android/module_context.go
new file mode 100644
index 0000000..1cab630
--- /dev/null
+++ b/android/module_context.go
@@ -0,0 +1,716 @@
+// Copyright 2015 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 android
+
+import (
+ "fmt"
+ "path"
+ "path/filepath"
+ "strings"
+
+ "github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
+)
+
+// BuildParameters describes the set of potential parameters to build a Ninja rule.
+// In general, these correspond to a Ninja concept.
+type BuildParams struct {
+ // A Ninja Rule that will be written to the Ninja file. This allows factoring out common code
+ // among multiple modules to reduce repetition in the Ninja file of action requirements. A rule
+ // can contain variables that should be provided in Args.
+ Rule blueprint.Rule
+ // Deps represents the depfile format. When using RuleBuilder, this defaults to GCC when depfiles
+ // are used.
+ Deps blueprint.Deps
+ // Depfile is a writeable path that allows correct incremental builds when the inputs have not
+ // been fully specified by the Ninja rule. Ninja supports a subset of the Makefile depfile syntax.
+ Depfile WritablePath
+ // A description of the build action.
+ Description string
+ // Output is an output file of the action. When using this field, references to $out in the Ninja
+ // command will refer to this file.
+ Output WritablePath
+ // Outputs is a slice of output file of the action. When using this field, references to $out in
+ // the Ninja command will refer to these files.
+ Outputs WritablePaths
+ // ImplicitOutput is an output file generated by the action. Note: references to `$out` in the
+ // Ninja command will NOT include references to this file.
+ ImplicitOutput WritablePath
+ // ImplicitOutputs is a slice of output files generated by the action. Note: references to `$out`
+ // in the Ninja command will NOT include references to these files.
+ ImplicitOutputs WritablePaths
+ // Input is an input file to the Ninja action. When using this field, references to $in in the
+ // Ninja command will refer to this file.
+ Input Path
+ // Inputs is a slice of input files to the Ninja action. When using this field, references to $in
+ // in the Ninja command will refer to these files.
+ Inputs Paths
+ // Implicit is an input file to the Ninja action. Note: references to `$in` in the Ninja command
+ // will NOT include references to this file.
+ Implicit Path
+ // Implicits is a slice of input files to the Ninja action. Note: references to `$in` in the Ninja
+ // command will NOT include references to these files.
+ Implicits Paths
+ // OrderOnly are Ninja order-only inputs to the action. When these are out of date, the output is
+ // not rebuilt until they are built, but changes in order-only dependencies alone do not cause the
+ // output to be rebuilt.
+ OrderOnly Paths
+ // Validation is an output path for a validation action. Validation outputs imply lower
+ // non-blocking priority to building non-validation outputs.
+ Validation Path
+ // Validations is a slice of output path for a validation action. Validation outputs imply lower
+ // non-blocking priority to building non-validation outputs.
+ Validations Paths
+ // Whether to skip outputting a default target statement which will be built by Ninja when no
+ // targets are specified on Ninja's command line.
+ Default bool
+ // Args is a key value mapping for replacements of variables within the Rule
+ Args map[string]string
+}
+
+type ModuleBuildParams BuildParams
+
+type ModuleContext interface {
+ BaseModuleContext
+
+ blueprintModuleContext() blueprint.ModuleContext
+
+ // Deprecated: use ModuleContext.Build instead.
+ ModuleBuild(pctx PackageContext, params ModuleBuildParams)
+
+ // Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must
+ // be tagged with `android:"path" to support automatic source module dependency resolution.
+ //
+ // Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
+ ExpandSources(srcFiles, excludes []string) Paths
+
+ // Returns a single path expanded from globs and modules referenced using ":module" syntax. The property must
+ // be tagged with `android:"path" to support automatic source module dependency resolution.
+ //
+ // Deprecated: use PathForModuleSrc instead.
+ ExpandSource(srcFile, prop string) Path
+
+ ExpandOptionalSource(srcFile *string, prop string) OptionalPath
+
+ // InstallExecutable creates a rule to copy srcPath to name in the installPath directory,
+ // with the given additional dependencies. The file is marked executable after copying.
+ //
+ // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
+ // installed file will be returned by PackagingSpecs() on this module or by
+ // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
+ // for which IsInstallDepNeeded returns true.
+ InstallExecutable(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
+
+ // InstallFile creates a rule to copy srcPath to name in the installPath directory,
+ // with the given additional dependencies.
+ //
+ // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
+ // installed file will be returned by PackagingSpecs() on this module or by
+ // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
+ // for which IsInstallDepNeeded returns true.
+ InstallFile(installPath InstallPath, name string, srcPath Path, deps ...InstallPath) InstallPath
+
+ // InstallFileWithExtraFilesZip creates a rule to copy srcPath to name in the installPath
+ // directory, and also unzip a zip file containing extra files to install into the same
+ // directory.
+ //
+ // The installed file will be returned by FilesToInstall(), and the PackagingSpec for the
+ // installed file will be returned by PackagingSpecs() on this module or by
+ // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
+ // for which IsInstallDepNeeded returns true.
+ InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path, extraZip Path, deps ...InstallPath) InstallPath
+
+ // InstallSymlink creates a rule to create a symlink from src srcPath to name in the installPath
+ // directory.
+ //
+ // The installed symlink will be returned by FilesToInstall(), and the PackagingSpec for the
+ // installed file will be returned by PackagingSpecs() on this module or by
+ // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
+ // for which IsInstallDepNeeded returns true.
+ InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath
+
+ // InstallAbsoluteSymlink creates a rule to create an absolute symlink from src srcPath to name
+ // in the installPath directory.
+ //
+ // The installed symlink will be returned by FilesToInstall(), and the PackagingSpec for the
+ // installed file will be returned by PackagingSpecs() on this module or by
+ // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
+ // for which IsInstallDepNeeded returns true.
+ InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath
+
+ // InstallTestData creates rules to install test data (e.g. data files used during a test) into
+ // the installPath directory.
+ //
+ // The installed files will be returned by FilesToInstall(), and the PackagingSpec for the
+ // installed files will be returned by PackagingSpecs() on this module or by
+ // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
+ // for which IsInstallDepNeeded returns true.
+ InstallTestData(installPath InstallPath, data []DataPath) InstallPaths
+
+ // PackageFile creates a PackagingSpec as if InstallFile was called, but without creating
+ // the rule to copy the file. This is useful to define how a module would be packaged
+ // without installing it into the global installation directories.
+ //
+ // The created PackagingSpec for the will be returned by PackagingSpecs() on this module or by
+ // TransitivePackagingSpecs() on modules that depend on this module through dependency tags
+ // for which IsInstallDepNeeded returns true.
+ PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec
+
+ CheckbuildFile(srcPath Path)
+
+ InstallInData() bool
+ InstallInTestcases() bool
+ InstallInSanitizerDir() bool
+ InstallInRamdisk() bool
+ InstallInVendorRamdisk() bool
+ InstallInDebugRamdisk() bool
+ InstallInRecovery() bool
+ InstallInRoot() bool
+ InstallInOdm() bool
+ InstallInProduct() bool
+ InstallInVendor() bool
+ InstallForceOS() (*OsType, *ArchType)
+
+ RequiredModuleNames() []string
+ HostRequiredModuleNames() []string
+ TargetRequiredModuleNames() []string
+
+ ModuleSubDir() string
+ SoongConfigTraceHash() string
+
+ Variable(pctx PackageContext, name, value string)
+ Rule(pctx PackageContext, name string, params blueprint.RuleParams, argNames ...string) blueprint.Rule
+ // Similar to blueprint.ModuleContext.Build, but takes Paths instead of []string,
+ // and performs more verification.
+ Build(pctx PackageContext, params BuildParams)
+ // Phony creates a Make-style phony rule, a rule with no commands that can depend on other
+ // phony rules or real files. Phony can be called on the same name multiple times to add
+ // additional dependencies.
+ Phony(phony string, deps ...Path)
+
+ // GetMissingDependencies returns the list of dependencies that were passed to AddDependencies or related methods,
+ // but do not exist.
+ GetMissingDependencies() []string
+
+ // LicenseMetadataFile returns the path where the license metadata for this module will be
+ // generated.
+ LicenseMetadataFile() Path
+
+ // ModuleInfoJSON returns a pointer to the ModuleInfoJSON struct that can be filled out by
+ // GenerateAndroidBuildActions. If it is called then the struct will be written out and included in
+ // the module-info.json generated by Make, and Make will not generate its own data for this module.
+ ModuleInfoJSON() *ModuleInfoJSON
+}
+
+type moduleContext struct {
+ bp blueprint.ModuleContext
+ baseModuleContext
+ packagingSpecs []PackagingSpec
+ installFiles InstallPaths
+ checkbuildFiles Paths
+ module Module
+ phonies map[string]Paths
+
+ katiInstalls []katiInstall
+ katiSymlinks []katiInstall
+
+ testData []DataPath
+
+ // For tests
+ buildParams []BuildParams
+ ruleParams map[blueprint.Rule]blueprint.RuleParams
+ variables map[string]string
+}
+
+func (m *moduleContext) ninjaError(params BuildParams, err error) (PackageContext, BuildParams) {
+ return pctx, BuildParams{
+ Rule: ErrorRule,
+ Description: params.Description,
+ Output: params.Output,
+ Outputs: params.Outputs,
+ ImplicitOutput: params.ImplicitOutput,
+ ImplicitOutputs: params.ImplicitOutputs,
+ Args: map[string]string{
+ "error": err.Error(),
+ },
+ }
+}
+
+func (m *moduleContext) ModuleBuild(pctx PackageContext, params ModuleBuildParams) {
+ m.Build(pctx, BuildParams(params))
+}
+
+// Convert build parameters from their concrete Android types into their string representations,
+// and combine the singular and plural fields of the same type (e.g. Output and Outputs).
+func convertBuildParams(params BuildParams) blueprint.BuildParams {
+ bparams := blueprint.BuildParams{
+ Rule: params.Rule,
+ Description: params.Description,
+ Deps: params.Deps,
+ Outputs: params.Outputs.Strings(),
+ ImplicitOutputs: params.ImplicitOutputs.Strings(),
+ Inputs: params.Inputs.Strings(),
+ Implicits: params.Implicits.Strings(),
+ OrderOnly: params.OrderOnly.Strings(),
+ Validations: params.Validations.Strings(),
+ Args: params.Args,
+ Optional: !params.Default,
+ }
+
+ if params.Depfile != nil {
+ bparams.Depfile = params.Depfile.String()
+ }
+ if params.Output != nil {
+ bparams.Outputs = append(bparams.Outputs, params.Output.String())
+ }
+ if params.ImplicitOutput != nil {
+ bparams.ImplicitOutputs = append(bparams.ImplicitOutputs, params.ImplicitOutput.String())
+ }
+ if params.Input != nil {
+ bparams.Inputs = append(bparams.Inputs, params.Input.String())
+ }
+ if params.Implicit != nil {
+ bparams.Implicits = append(bparams.Implicits, params.Implicit.String())
+ }
+ if params.Validation != nil {
+ bparams.Validations = append(bparams.Validations, params.Validation.String())
+ }
+
+ bparams.Outputs = proptools.NinjaEscapeList(bparams.Outputs)
+ bparams.ImplicitOutputs = proptools.NinjaEscapeList(bparams.ImplicitOutputs)
+ bparams.Inputs = proptools.NinjaEscapeList(bparams.Inputs)
+ bparams.Implicits = proptools.NinjaEscapeList(bparams.Implicits)
+ bparams.OrderOnly = proptools.NinjaEscapeList(bparams.OrderOnly)
+ bparams.Validations = proptools.NinjaEscapeList(bparams.Validations)
+ bparams.Depfile = proptools.NinjaEscape(bparams.Depfile)
+
+ return bparams
+}
+
+func (m *moduleContext) Variable(pctx PackageContext, name, value string) {
+ if m.config.captureBuild {
+ m.variables[name] = value
+ }
+
+ m.bp.Variable(pctx.PackageContext, name, value)
+}
+
+func (m *moduleContext) Rule(pctx PackageContext, name string, params blueprint.RuleParams,
+ argNames ...string) blueprint.Rule {
+
+ if m.config.UseRemoteBuild() {
+ if params.Pool == nil {
+ // When USE_GOMA=true or USE_RBE=true are set and the rule is not supported by goma/RBE, restrict
+ // jobs to the local parallelism value
+ params.Pool = localPool
+ } else if params.Pool == remotePool {
+ // remotePool is a fake pool used to identify rule that are supported for remoting. If the rule's
+ // pool is the remotePool, replace with nil so that ninja runs it at NINJA_REMOTE_NUM_JOBS
+ // parallelism.
+ params.Pool = nil
+ }
+ }
+
+ rule := m.bp.Rule(pctx.PackageContext, name, params, argNames...)
+
+ if m.config.captureBuild {
+ m.ruleParams[rule] = params
+ }
+
+ return rule
+}
+
+func (m *moduleContext) Build(pctx PackageContext, params BuildParams) {
+ if params.Description != "" {
+ params.Description = "${moduleDesc}" + params.Description + "${moduleDescSuffix}"
+ }
+
+ if missingDeps := m.GetMissingDependencies(); len(missingDeps) > 0 {
+ pctx, params = m.ninjaError(params, fmt.Errorf("module %s missing dependencies: %s\n",
+ m.ModuleName(), strings.Join(missingDeps, ", ")))
+ }
+
+ if m.config.captureBuild {
+ m.buildParams = append(m.buildParams, params)
+ }
+
+ bparams := convertBuildParams(params)
+ m.bp.Build(pctx.PackageContext, bparams)
+}
+
+func (m *moduleContext) Phony(name string, deps ...Path) {
+ addPhony(m.config, name, deps...)
+}
+
+func (m *moduleContext) GetMissingDependencies() []string {
+ var missingDeps []string
+ missingDeps = append(missingDeps, m.Module().base().commonProperties.MissingDeps...)
+ missingDeps = append(missingDeps, m.bp.GetMissingDependencies()...)
+ missingDeps = FirstUniqueStrings(missingDeps)
+ return missingDeps
+}
+
+func (m *moduleContext) GetDirectDepWithTag(name string, tag blueprint.DependencyTag) blueprint.Module {
+ module, _ := m.getDirectDepInternal(name, tag)
+ return module
+}
+
+func (m *moduleContext) ModuleSubDir() string {
+ return m.bp.ModuleSubDir()
+}
+
+func (m *moduleContext) SoongConfigTraceHash() string {
+ return m.module.base().commonProperties.SoongConfigTraceHash
+}
+
+func (m *moduleContext) InstallInData() bool {
+ return m.module.InstallInData()
+}
+
+func (m *moduleContext) InstallInTestcases() bool {
+ return m.module.InstallInTestcases()
+}
+
+func (m *moduleContext) InstallInSanitizerDir() bool {
+ return m.module.InstallInSanitizerDir()
+}
+
+func (m *moduleContext) InstallInRamdisk() bool {
+ return m.module.InstallInRamdisk()
+}
+
+func (m *moduleContext) InstallInVendorRamdisk() bool {
+ return m.module.InstallInVendorRamdisk()
+}
+
+func (m *moduleContext) InstallInDebugRamdisk() bool {
+ return m.module.InstallInDebugRamdisk()
+}
+
+func (m *moduleContext) InstallInRecovery() bool {
+ return m.module.InstallInRecovery()
+}
+
+func (m *moduleContext) InstallInRoot() bool {
+ return m.module.InstallInRoot()
+}
+
+func (m *moduleContext) InstallForceOS() (*OsType, *ArchType) {
+ return m.module.InstallForceOS()
+}
+
+func (m *moduleContext) InstallInOdm() bool {
+ return m.module.InstallInOdm()
+}
+
+func (m *moduleContext) InstallInProduct() bool {
+ return m.module.InstallInProduct()
+}
+
+func (m *moduleContext) InstallInVendor() bool {
+ return m.module.InstallInVendor()
+}
+
+func (m *moduleContext) skipInstall() bool {
+ if m.module.base().commonProperties.SkipInstall {
+ return true
+ }
+
+ if m.module.base().commonProperties.HideFromMake {
+ return true
+ }
+
+ // We'll need a solution for choosing which of modules with the same name in different
+ // namespaces to install. For now, reuse the list of namespaces exported to Make as the
+ // list of namespaces to install in a Soong-only build.
+ if !m.module.base().commonProperties.NamespaceExportedToMake {
+ return true
+ }
+
+ return false
+}
+
+func (m *moduleContext) InstallFile(installPath InstallPath, name string, srcPath Path,
+ deps ...InstallPath) InstallPath {
+ return m.installFile(installPath, name, srcPath, deps, false, true, nil)
+}
+
+func (m *moduleContext) InstallExecutable(installPath InstallPath, name string, srcPath Path,
+ deps ...InstallPath) InstallPath {
+ return m.installFile(installPath, name, srcPath, deps, true, true, nil)
+}
+
+func (m *moduleContext) InstallFileWithExtraFilesZip(installPath InstallPath, name string, srcPath Path,
+ extraZip Path, deps ...InstallPath) InstallPath {
+ return m.installFile(installPath, name, srcPath, deps, false, true, &extraFilesZip{
+ zip: extraZip,
+ dir: installPath,
+ })
+}
+
+func (m *moduleContext) PackageFile(installPath InstallPath, name string, srcPath Path) PackagingSpec {
+ fullInstallPath := installPath.Join(m, name)
+ return m.packageFile(fullInstallPath, srcPath, false)
+}
+
+func (m *moduleContext) packageFile(fullInstallPath InstallPath, srcPath Path, executable bool) PackagingSpec {
+ licenseFiles := m.Module().EffectiveLicenseFiles()
+ spec := PackagingSpec{
+ relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
+ srcPath: srcPath,
+ symlinkTarget: "",
+ executable: executable,
+ effectiveLicenseFiles: &licenseFiles,
+ partition: fullInstallPath.partition,
+ }
+ m.packagingSpecs = append(m.packagingSpecs, spec)
+ return spec
+}
+
+func (m *moduleContext) installFile(installPath InstallPath, name string, srcPath Path, deps []InstallPath,
+ executable bool, hooks bool, extraZip *extraFilesZip) InstallPath {
+
+ fullInstallPath := installPath.Join(m, name)
+ if hooks {
+ m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, false)
+ }
+
+ if !m.skipInstall() {
+ deps = append(deps, InstallPaths(m.module.base().installFilesDepSet.ToList())...)
+ deps = append(deps, m.module.base().installedInitRcPaths...)
+ deps = append(deps, m.module.base().installedVintfFragmentsPaths...)
+
+ var implicitDeps, orderOnlyDeps Paths
+
+ if m.Host() {
+ // Installed host modules might be used during the build, depend directly on their
+ // dependencies so their timestamp is updated whenever their dependency is updated
+ implicitDeps = InstallPaths(deps).Paths()
+ } else {
+ orderOnlyDeps = InstallPaths(deps).Paths()
+ }
+
+ if m.Config().KatiEnabled() {
+ // When creating the install rule in Soong but embedding in Make, write the rule to a
+ // makefile instead of directly to the ninja file so that main.mk can add the
+ // dependencies from the `required` property that are hard to resolve in Soong.
+ m.katiInstalls = append(m.katiInstalls, katiInstall{
+ from: srcPath,
+ to: fullInstallPath,
+ implicitDeps: implicitDeps,
+ orderOnlyDeps: orderOnlyDeps,
+ executable: executable,
+ extraFiles: extraZip,
+ })
+ } else {
+ rule := Cp
+ if executable {
+ rule = CpExecutable
+ }
+
+ extraCmds := ""
+ if extraZip != nil {
+ extraCmds += fmt.Sprintf(" && ( unzip -qDD -d '%s' '%s' 2>&1 | grep -v \"zipfile is empty\"; exit $${PIPESTATUS[0]} )",
+ extraZip.dir.String(), extraZip.zip.String())
+ extraCmds += " || ( code=$$?; if [ $$code -ne 0 -a $$code -ne 1 ]; then exit $$code; fi )"
+ implicitDeps = append(implicitDeps, extraZip.zip)
+ }
+
+ m.Build(pctx, BuildParams{
+ Rule: rule,
+ Description: "install " + fullInstallPath.Base(),
+ Output: fullInstallPath,
+ Input: srcPath,
+ Implicits: implicitDeps,
+ OrderOnly: orderOnlyDeps,
+ Default: !m.Config().KatiEnabled(),
+ Args: map[string]string{
+ "extraCmds": extraCmds,
+ },
+ })
+ }
+
+ m.installFiles = append(m.installFiles, fullInstallPath)
+ }
+
+ m.packageFile(fullInstallPath, srcPath, executable)
+
+ m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
+
+ return fullInstallPath
+}
+
+func (m *moduleContext) InstallSymlink(installPath InstallPath, name string, srcPath InstallPath) InstallPath {
+ fullInstallPath := installPath.Join(m, name)
+ m.module.base().hooks.runInstallHooks(m, srcPath, fullInstallPath, true)
+
+ relPath, err := filepath.Rel(path.Dir(fullInstallPath.String()), srcPath.String())
+ if err != nil {
+ panic(fmt.Sprintf("Unable to generate symlink between %q and %q: %s", fullInstallPath.Base(), srcPath.Base(), err))
+ }
+ if !m.skipInstall() {
+
+ if m.Config().KatiEnabled() {
+ // When creating the symlink rule in Soong but embedding in Make, write the rule to a
+ // makefile instead of directly to the ninja file so that main.mk can add the
+ // dependencies from the `required` property that are hard to resolve in Soong.
+ m.katiSymlinks = append(m.katiSymlinks, katiInstall{
+ from: srcPath,
+ to: fullInstallPath,
+ })
+ } else {
+ // The symlink doesn't need updating when the target is modified, but we sometimes
+ // have a dependency on a symlink to a binary instead of to the binary directly, and
+ // the mtime of the symlink must be updated when the binary is modified, so use a
+ // normal dependency here instead of an order-only dependency.
+ m.Build(pctx, BuildParams{
+ Rule: Symlink,
+ Description: "install symlink " + fullInstallPath.Base(),
+ Output: fullInstallPath,
+ Input: srcPath,
+ Default: !m.Config().KatiEnabled(),
+ Args: map[string]string{
+ "fromPath": relPath,
+ },
+ })
+ }
+
+ m.installFiles = append(m.installFiles, fullInstallPath)
+ m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
+ }
+
+ m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
+ relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
+ srcPath: nil,
+ symlinkTarget: relPath,
+ executable: false,
+ partition: fullInstallPath.partition,
+ })
+
+ return fullInstallPath
+}
+
+// installPath/name -> absPath where absPath might be a path that is available only at runtime
+// (e.g. /apex/...)
+func (m *moduleContext) InstallAbsoluteSymlink(installPath InstallPath, name string, absPath string) InstallPath {
+ fullInstallPath := installPath.Join(m, name)
+ m.module.base().hooks.runInstallHooks(m, nil, fullInstallPath, true)
+
+ if !m.skipInstall() {
+ if m.Config().KatiEnabled() {
+ // When creating the symlink rule in Soong but embedding in Make, write the rule to a
+ // makefile instead of directly to the ninja file so that main.mk can add the
+ // dependencies from the `required` property that are hard to resolve in Soong.
+ m.katiSymlinks = append(m.katiSymlinks, katiInstall{
+ absFrom: absPath,
+ to: fullInstallPath,
+ })
+ } else {
+ m.Build(pctx, BuildParams{
+ Rule: Symlink,
+ Description: "install symlink " + fullInstallPath.Base() + " -> " + absPath,
+ Output: fullInstallPath,
+ Default: !m.Config().KatiEnabled(),
+ Args: map[string]string{
+ "fromPath": absPath,
+ },
+ })
+ }
+
+ m.installFiles = append(m.installFiles, fullInstallPath)
+ }
+
+ m.packagingSpecs = append(m.packagingSpecs, PackagingSpec{
+ relPathInPackage: Rel(m, fullInstallPath.PartitionDir(), fullInstallPath.String()),
+ srcPath: nil,
+ symlinkTarget: absPath,
+ executable: false,
+ partition: fullInstallPath.partition,
+ })
+
+ return fullInstallPath
+}
+
+func (m *moduleContext) InstallTestData(installPath InstallPath, data []DataPath) InstallPaths {
+ m.testData = append(m.testData, data...)
+
+ ret := make(InstallPaths, 0, len(data))
+ for _, d := range data {
+ relPath := d.ToRelativeInstallPath()
+ installed := m.installFile(installPath, relPath, d.SrcPath, nil, false, false, nil)
+ ret = append(ret, installed)
+ }
+
+ return ret
+}
+
+func (m *moduleContext) CheckbuildFile(srcPath Path) {
+ m.checkbuildFiles = append(m.checkbuildFiles, srcPath)
+}
+
+func (m *moduleContext) blueprintModuleContext() blueprint.ModuleContext {
+ return m.bp
+}
+
+func (m *moduleContext) LicenseMetadataFile() Path {
+ return m.module.base().licenseMetadataFile
+}
+
+func (m *moduleContext) ModuleInfoJSON() *ModuleInfoJSON {
+ if moduleInfoJSON := m.module.base().moduleInfoJSON; moduleInfoJSON != nil {
+ return moduleInfoJSON
+ }
+ moduleInfoJSON := &ModuleInfoJSON{}
+ m.module.base().moduleInfoJSON = moduleInfoJSON
+ return moduleInfoJSON
+}
+
+// Returns a list of paths expanded from globs and modules referenced using ":module" syntax. The property must
+// be tagged with `android:"path" to support automatic source module dependency resolution.
+//
+// Deprecated: use PathsForModuleSrc or PathsForModuleSrcExcludes instead.
+func (m *moduleContext) ExpandSources(srcFiles, excludes []string) Paths {
+ return PathsForModuleSrcExcludes(m, srcFiles, excludes)
+}
+
+// Returns a single path expanded from globs and modules referenced using ":module" syntax. The property must
+// be tagged with `android:"path" to support automatic source module dependency resolution.
+//
+// Deprecated: use PathForModuleSrc instead.
+func (m *moduleContext) ExpandSource(srcFile, _ string) Path {
+ return PathForModuleSrc(m, srcFile)
+}
+
+// Returns an optional single path expanded from globs and modules referenced using ":module" syntax if
+// the srcFile is non-nil. The property must be tagged with `android:"path" to support automatic source module
+// dependency resolution.
+func (m *moduleContext) ExpandOptionalSource(srcFile *string, _ string) OptionalPath {
+ if srcFile != nil {
+ return OptionalPathForPath(PathForModuleSrc(m, *srcFile))
+ }
+ return OptionalPath{}
+}
+
+func (m *moduleContext) RequiredModuleNames() []string {
+ return m.module.RequiredModuleNames()
+}
+
+func (m *moduleContext) HostRequiredModuleNames() []string {
+ return m.module.HostRequiredModuleNames()
+}
+
+func (m *moduleContext) TargetRequiredModuleNames() []string {
+ return m.module.TargetRequiredModuleNames()
+}
diff --git a/android/module_info_json.go b/android/module_info_json.go
new file mode 100644
index 0000000..1c0a38e
--- /dev/null
+++ b/android/module_info_json.go
@@ -0,0 +1,103 @@
+package android
+
+import (
+ "encoding/json"
+ "io"
+ "slices"
+
+ "github.com/google/blueprint"
+)
+
+type CoreModuleInfoJSON struct {
+ RegisterName string `json:"-"`
+ Path []string `json:"path,omitempty"` // $(sort $(ALL_MODULES.$(m).PATH))
+ Installed []string `json:"installed,omitempty"` // $(sort $(ALL_MODULES.$(m).INSTALLED))
+ ModuleName string `json:"module_name,omitempty"` // $(ALL_MODULES.$(m).MODULE_NAME)
+ SupportedVariants []string `json:"supported_variants,omitempty"` // $(sort $(ALL_MODULES.$(m).SUPPORTED_VARIANTS))
+ HostDependencies []string `json:"host_dependencies,omitempty"` // $(sort $(ALL_MODULES.$(m).HOST_REQUIRED_FROM_TARGET))
+ TargetDependencies []string `json:"target_dependencies,omitempty"` // $(sort $(ALL_MODULES.$(m).TARGET_REQUIRED_FROM_HOST))
+ Data []string `json:"data,omitempty"` // $(sort $(ALL_MODULES.$(m).TEST_DATA))
+}
+
+type ModuleInfoJSON struct {
+ core CoreModuleInfoJSON
+ SubName string `json:"-"`
+ Uninstallable bool `json:"-"`
+ Class []string `json:"class,omitempty"` // $(sort $(ALL_MODULES.$(m).CLASS))
+ Tags []string `json:"tags,omitempty"` // $(sort $(ALL_MODULES.$(m).TAGS))
+ Dependencies []string `json:"dependencies,omitempty"` // $(sort $(ALL_DEPS.$(m).ALL_DEPS))
+ SharedLibs []string `json:"shared_libs,omitempty"` // $(sort $(ALL_MODULES.$(m).SHARED_LIBS))
+ StaticLibs []string `json:"static_libs,omitempty"` // $(sort $(ALL_MODULES.$(m).STATIC_LIBS))
+ SystemSharedLibs []string `json:"system_shared_libs,omitempty"` // $(sort $(ALL_MODULES.$(m).SYSTEM_SHARED_LIBS))
+ Srcs []string `json:"srcs,omitempty"` // $(sort $(ALL_MODULES.$(m).SRCS))
+ SrcJars []string `json:"srcjars,omitempty"` // $(sort $(ALL_MODULES.$(m).SRCJARS))
+ ClassesJar []string `json:"classes_jar,omitempty"` // $(sort $(ALL_MODULES.$(m).CLASSES_JAR))
+ TestMainlineModules []string `json:"test_mainline_modules,omitempty"` // $(sort $(ALL_MODULES.$(m).TEST_MAINLINE_MODULES))
+ IsUnitTest bool `json:"is_unit_test,omitempty"` // $(ALL_MODULES.$(m).IS_UNIT_TEST)
+ TestOptionsTags []string `json:"test_options_tags,omitempty"` // $(sort $(ALL_MODULES.$(m).TEST_OPTIONS_TAGS))
+ RuntimeDependencies []string `json:"runtime_dependencies,omitempty"` // $(sort $(ALL_MODULES.$(m).LOCAL_RUNTIME_LIBRARIES))
+ StaticDependencies []string `json:"static_dependencies,omitempty"` // $(sort $(ALL_MODULES.$(m).LOCAL_STATIC_LIBRARIES))
+ DataDependencies []string `json:"data_dependencies,omitempty"` // $(sort $(ALL_MODULES.$(m).TEST_DATA_BINS))
+
+ CompatibilitySuites []string `json:"compatibility_suites,omitempty"` // $(sort $(ALL_MODULES.$(m).COMPATIBILITY_SUITES))
+ AutoTestConfig []string `json:"auto_test_config,omitempty"` // $(ALL_MODULES.$(m).auto_test_config)
+ TestConfig []string `json:"test_config,omitempty"` // $(strip $(ALL_MODULES.$(m).TEST_CONFIG) $(ALL_MODULES.$(m).EXTRA_TEST_CONFIGS)
+}
+
+//ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS := $(sort \
+//$(ALL_DEPS.$(LOCAL_MODULE).ALL_DEPS) \
+//$(LOCAL_STATIC_LIBRARIES) \
+//$(LOCAL_WHOLE_STATIC_LIBRARIES) \
+//$(LOCAL_SHARED_LIBRARIES) \
+//$(LOCAL_DYLIB_LIBRARIES) \
+//$(LOCAL_RLIB_LIBRARIES) \
+//$(LOCAL_PROC_MACRO_LIBRARIES) \
+//$(LOCAL_HEADER_LIBRARIES) \
+//$(LOCAL_STATIC_JAVA_LIBRARIES) \
+//$(LOCAL_JAVA_LIBRARIES) \
+//$(LOCAL_JNI_SHARED_LIBRARIES))
+
+type combinedModuleInfoJSON struct {
+ *CoreModuleInfoJSON
+ *ModuleInfoJSON
+}
+
+func encodeModuleInfoJSON(w io.Writer, moduleInfoJSON *ModuleInfoJSON) error {
+ moduleInfoJSONCopy := *moduleInfoJSON
+
+ sortAndUnique := func(s *[]string) {
+ *s = slices.Clone(*s)
+ slices.Sort(*s)
+ *s = slices.Compact(*s)
+ }
+
+ sortAndUnique(&moduleInfoJSONCopy.core.Path)
+ sortAndUnique(&moduleInfoJSONCopy.core.Installed)
+ sortAndUnique(&moduleInfoJSONCopy.core.SupportedVariants)
+ sortAndUnique(&moduleInfoJSONCopy.core.HostDependencies)
+ sortAndUnique(&moduleInfoJSONCopy.core.TargetDependencies)
+ sortAndUnique(&moduleInfoJSONCopy.core.Data)
+
+ sortAndUnique(&moduleInfoJSONCopy.Class)
+ sortAndUnique(&moduleInfoJSONCopy.Tags)
+ sortAndUnique(&moduleInfoJSONCopy.Dependencies)
+ sortAndUnique(&moduleInfoJSONCopy.SharedLibs)
+ sortAndUnique(&moduleInfoJSONCopy.StaticLibs)
+ sortAndUnique(&moduleInfoJSONCopy.SystemSharedLibs)
+ sortAndUnique(&moduleInfoJSONCopy.Srcs)
+ sortAndUnique(&moduleInfoJSONCopy.SrcJars)
+ sortAndUnique(&moduleInfoJSONCopy.ClassesJar)
+ sortAndUnique(&moduleInfoJSONCopy.TestMainlineModules)
+ sortAndUnique(&moduleInfoJSONCopy.TestOptionsTags)
+ sortAndUnique(&moduleInfoJSONCopy.RuntimeDependencies)
+ sortAndUnique(&moduleInfoJSONCopy.StaticDependencies)
+ sortAndUnique(&moduleInfoJSONCopy.DataDependencies)
+ sortAndUnique(&moduleInfoJSONCopy.CompatibilitySuites)
+ sortAndUnique(&moduleInfoJSONCopy.AutoTestConfig)
+ sortAndUnique(&moduleInfoJSONCopy.TestConfig)
+
+ encoder := json.NewEncoder(w)
+ return encoder.Encode(combinedModuleInfoJSON{&moduleInfoJSONCopy.core, &moduleInfoJSONCopy})
+}
+
+var ModuleInfoJSONProvider = blueprint.NewProvider[*ModuleInfoJSON]()
diff --git a/android/module_test.go b/android/module_test.go
index 1ca7422..1f3db5c 100644
--- a/android/module_test.go
+++ b/android/module_test.go
@@ -15,10 +15,11 @@
package android
import (
- "github.com/google/blueprint"
"path/filepath"
"runtime"
"testing"
+
+ "github.com/google/blueprint"
)
func TestSrcIsModule(t *testing.T) {
@@ -244,52 +245,6 @@
RunTestWithBp(t, bp)
}
-func TestValidateCorrectBuildParams(t *testing.T) {
- config := TestConfig(t.TempDir(), nil, "", nil)
- pathContext := PathContextForTesting(config)
- bparams := convertBuildParams(BuildParams{
- // Test with Output
- Output: PathForOutput(pathContext, "undeclared_symlink"),
- SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"),
- })
-
- err := validateBuildParams(bparams)
- if err != nil {
- t.Error(err)
- }
-
- bparams = convertBuildParams(BuildParams{
- // Test with ImplicitOutput
- ImplicitOutput: PathForOutput(pathContext, "undeclared_symlink"),
- SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"),
- })
-
- err = validateBuildParams(bparams)
- if err != nil {
- t.Error(err)
- }
-}
-
-func TestValidateIncorrectBuildParams(t *testing.T) {
- config := TestConfig(t.TempDir(), nil, "", nil)
- pathContext := PathContextForTesting(config)
- params := BuildParams{
- Output: PathForOutput(pathContext, "regular_output"),
- Outputs: PathsForOutput(pathContext, []string{"out1", "out2"}),
- ImplicitOutput: PathForOutput(pathContext, "implicit_output"),
- ImplicitOutputs: PathsForOutput(pathContext, []string{"i_out1", "_out2"}),
- SymlinkOutput: PathForOutput(pathContext, "undeclared_symlink"),
- }
-
- bparams := convertBuildParams(params)
- err := validateBuildParams(bparams)
- if err != nil {
- FailIfNoMatchingErrors(t, "undeclared_symlink is not a declared output or implicit output", []error{err})
- } else {
- t.Errorf("Expected build params to fail validation: %+v", bparams)
- }
-}
-
func TestDistErrorChecking(t *testing.T) {
bp := `
deps {
diff --git a/android/mutator.go b/android/mutator.go
index 41477b8..22e9160 100644
--- a/android/mutator.go
+++ b/android/mutator.go
@@ -15,10 +15,6 @@
package android
import (
- "android/soong/bazel"
- "android/soong/ui/metrics/bp2build_metrics_proto"
- "path/filepath"
-
"github.com/google/blueprint"
)
@@ -31,46 +27,9 @@
// run FinalDeps mutators (CreateVariations disallowed in this phase)
// continue on to GenerateAndroidBuildActions
-// RegisterMutatorsForBazelConversion is a alternate registration pipeline for bp2build. Exported for testing.
-func RegisterMutatorsForBazelConversion(ctx *Context, preArchMutators []RegisterMutatorFunc) {
- bp2buildMutators := append(preArchMutators, registerBp2buildConversionMutator)
- registerMutatorsForBazelConversion(ctx, bp2buildMutators)
-}
-
-// RegisterMutatorsForApiBazelConversion is an alternate registration pipeline for api_bp2build
-// This pipeline restricts generation of Bazel targets to Soong modules that contribute APIs
-func RegisterMutatorsForApiBazelConversion(ctx *Context, preArchMutators []RegisterMutatorFunc) {
- bp2buildMutators := append(preArchMutators, registerApiBp2buildConversionMutator)
- registerMutatorsForBazelConversion(ctx, bp2buildMutators)
-}
-
-func registerMutatorsForBazelConversion(ctx *Context, bp2buildMutators []RegisterMutatorFunc) {
- mctx := ®isterMutatorsContext{
- bazelConversionMode: true,
- }
-
- allMutators := append([]RegisterMutatorFunc{
- RegisterNamespaceMutator,
- RegisterDefaultsPreArchMutators,
- // TODO(b/165114590): this is required to resolve deps that are only prebuilts, but we should
- // evaluate the impact on conversion.
- RegisterPrebuiltsPreArchMutators,
- },
- bp2buildMutators...)
-
- // Register bp2build mutators
- for _, f := range allMutators {
- f(mctx)
- }
-
- mctx.mutators.registerAll(ctx)
-}
-
// collateGloballyRegisteredMutators constructs the list of mutators that have been registered
// with the InitRegistrationContext and will be used at runtime.
func collateGloballyRegisteredMutators() sortableComponents {
- // ensure mixed builds mutator is the last mutator
- finalDeps = append(finalDeps, registerMixedBuildsMutator)
return collateRegisteredMutators(preArch, preDeps, postDeps, finalDeps)
}
@@ -99,9 +58,8 @@
}
type registerMutatorsContext struct {
- mutators sortableComponents
- finalPhase bool
- bazelConversionMode bool
+ mutators sortableComponents
+ finalPhase bool
}
type RegisterMutatorsContext interface {
@@ -224,22 +182,6 @@
finalDeps = append(finalDeps, f)
}
-var bp2buildPreArchMutators = []RegisterMutatorFunc{}
-
-// A minimal context for Bp2build conversion
-type Bp2buildMutatorContext interface {
- BazelConversionPathContext
-
- CreateBazelTargetModule(bazel.BazelTargetModuleProperties, CommonAttributes, interface{})
- CreateBazelTargetModuleWithRestrictions(bazel.BazelTargetModuleProperties, CommonAttributes, interface{}, bazel.BoolAttribute)
-}
-
-// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
-// into Bazel BUILD targets that should run prior to deps and conversion.
-func PreArchBp2BuildMutators(f RegisterMutatorFunc) {
- bp2buildPreArchMutators = append(bp2buildPreArchMutators, f)
-}
-
type BaseMutatorContext interface {
BaseModuleContext
@@ -259,35 +201,6 @@
// CreateModule creates a new module by calling the factory method for the specified moduleType, and applies
// the specified property structs to it as if the properties were set in a blueprint file.
CreateModule(ModuleFactory, ...interface{}) Module
-
- // CreateBazelTargetModule creates a BazelTargetModule by calling the
- // factory method, just like in CreateModule, but also requires
- // BazelTargetModuleProperties containing additional metadata for the
- // bp2build codegenerator.
- CreateBazelTargetModule(bazel.BazelTargetModuleProperties, CommonAttributes, interface{})
-
- // CreateBazelTargetModuleWithRestrictions creates a BazelTargetModule by calling the
- // factory method, just like in CreateModule, but also requires
- // BazelTargetModuleProperties containing additional metadata for the
- // bp2build codegenerator. The generated target is restricted to only be buildable for certain
- // 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)
-
- // MarkBp2buildUnconvertible registers the current module as "unconvertible to bp2build" for the
- // given reason.
- MarkBp2buildUnconvertible(reasonType bp2build_metrics_proto.UnconvertedReasonType, detail string)
-
- // 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)
-
- // CreateBazelConfigSetting creates a config_setting in <dir>/BUILD.bazel
- // build/bazel has several static config_setting(s) that are used in Bazel builds.
- // This function can be used to createa additional config_setting(s) based on the build graph
- // (e.g. a config_setting specific to an apex variant)
- CreateBazelConfigSetting(csa bazel.ConfigSettingAttributes, ca CommonAttributes, dir string)
}
type topDownMutatorContext struct {
@@ -412,7 +325,7 @@
// if the value is not of the appropriate type, or if the module is not a newly created
// variant of the current module. The value should not be modified after being passed to
// SetVariationProvider.
- SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{})
+ SetVariationProvider(module blueprint.Module, provider blueprint.AnyProviderKey, value interface{})
}
type bottomUpMutatorContext struct {
@@ -422,10 +335,9 @@
}
func bottomUpMutatorContextFactory(ctx blueprint.BottomUpMutatorContext, a Module,
- finalPhase, bazelConversionMode bool) BottomUpMutatorContext {
+ finalPhase bool) BottomUpMutatorContext {
moduleContext := a.base().baseModuleContextFactory(ctx)
- moduleContext.bazelConversionMode = bazelConversionMode
return &bottomUpMutatorContext{
bp: ctx,
@@ -436,10 +348,9 @@
func (x *registerMutatorsContext) BottomUp(name string, m BottomUpMutator) MutatorHandle {
finalPhase := x.finalPhase
- bazelConversionMode := x.bazelConversionMode
f := func(ctx blueprint.BottomUpMutatorContext) {
if a, ok := ctx.Module().(Module); ok {
- m(bottomUpMutatorContextFactory(ctx, a, finalPhase, bazelConversionMode))
+ m(bottomUpMutatorContextFactory(ctx, a, finalPhase))
}
}
mutator := &mutator{name: x.mutatorName(name), bottomUpMutator: f}
@@ -454,15 +365,21 @@
}
type IncomingTransitionContext interface {
+ ArchModuleContext
+
// Module returns the target of the dependency edge for which the transition
// is being computed
Module() Module
// Config returns the configuration for the build.
Config() Config
+
+ DeviceConfig() DeviceConfig
}
type OutgoingTransitionContext interface {
+ ArchModuleContext
+
// Module returns the target of the dependency edge for which the transition
// is being computed
Module() Module
@@ -470,9 +387,14 @@
// DepTag() Returns the dependency tag through which this dependency is
// reached
DepTag() blueprint.DependencyTag
+
+ // Config returns the configuration for the build.
+ Config() Config
+
+ DeviceConfig() DeviceConfig
}
-// Transition mutators implement a top-down mechanism where a module tells its
+// TransitionMutator implements a top-down mechanism where a module tells its
// direct dependencies what variation they should be built in but the dependency
// has the final say.
//
@@ -537,18 +459,18 @@
// called on.
Split(ctx BaseModuleContext) []string
- // Called on a module to determine which variation it wants from its direct
- // dependencies. The dependency itself can override this decision. This method
- // should not mutate the module itself.
+ // OutgoingTransition is called on a module to determine which variation it wants
+ // from its direct dependencies. The dependency itself can override this decision.
+ // This method should not mutate the module itself.
OutgoingTransition(ctx OutgoingTransitionContext, sourceVariation string) string
- // Called on a module to determine which variation it should be in based on
- // the variation modules that depend on it want. This gives the module a final
- // say about its own variations. This method should not mutate the module
+ // IncomingTransition is called on a module to determine which variation it should
+ // be in based on the variation modules that depend on it want. This gives the module
+ // a final say about its own variations. This method should not mutate the module
// itself.
IncomingTransition(ctx IncomingTransitionContext, incomingVariation string) string
- // Called after a module was split into multiple variations on each variation.
+ // Mutate is called after a module was split into multiple variations on each variation.
// It should not split the module any further but adding new dependencies is
// fine. Unlike all the other methods on TransitionMutator, this method is
// allowed to mutate the module.
@@ -556,15 +478,13 @@
}
type androidTransitionMutator struct {
- finalPhase bool
- bazelConversionMode bool
- mutator TransitionMutator
+ finalPhase bool
+ mutator TransitionMutator
}
func (a *androidTransitionMutator) Split(ctx blueprint.BaseModuleContext) []string {
if m, ok := ctx.Module().(Module); ok {
moduleContext := m.base().baseModuleContextFactory(ctx)
- moduleContext.bazelConversionMode = a.bazelConversionMode
return a.mutator.Split(&moduleContext)
} else {
return []string{""}
@@ -572,6 +492,7 @@
}
type outgoingTransitionContextImpl struct {
+ archModuleContext
bp blueprint.OutgoingTransitionContext
}
@@ -583,15 +504,28 @@
return c.bp.DepTag()
}
-func (a *androidTransitionMutator) OutgoingTransition(ctx blueprint.OutgoingTransitionContext, sourceVariation string) string {
- if _, ok := ctx.Module().(Module); ok {
- return a.mutator.OutgoingTransition(&outgoingTransitionContextImpl{bp: ctx}, sourceVariation)
+func (c *outgoingTransitionContextImpl) Config() Config {
+ return c.bp.Config().(Config)
+}
+
+func (c *outgoingTransitionContextImpl) DeviceConfig() DeviceConfig {
+ return DeviceConfig{c.bp.Config().(Config).deviceConfig}
+}
+
+func (a *androidTransitionMutator) OutgoingTransition(bpctx blueprint.OutgoingTransitionContext, sourceVariation string) string {
+ if m, ok := bpctx.Module().(Module); ok {
+ ctx := &outgoingTransitionContextImpl{
+ archModuleContext: m.base().archModuleContextFactory(bpctx),
+ bp: bpctx,
+ }
+ return a.mutator.OutgoingTransition(ctx, sourceVariation)
} else {
return ""
}
}
type incomingTransitionContextImpl struct {
+ archModuleContext
bp blueprint.IncomingTransitionContext
}
@@ -603,9 +537,17 @@
return c.bp.Config().(Config)
}
-func (a *androidTransitionMutator) IncomingTransition(ctx blueprint.IncomingTransitionContext, incomingVariation string) string {
- if _, ok := ctx.Module().(Module); ok {
- return a.mutator.IncomingTransition(&incomingTransitionContextImpl{bp: ctx}, incomingVariation)
+func (c *incomingTransitionContextImpl) DeviceConfig() DeviceConfig {
+ return DeviceConfig{c.bp.Config().(Config).deviceConfig}
+}
+
+func (a *androidTransitionMutator) IncomingTransition(bpctx blueprint.IncomingTransitionContext, incomingVariation string) string {
+ if m, ok := bpctx.Module().(Module); ok {
+ ctx := &incomingTransitionContextImpl{
+ archModuleContext: m.base().archModuleContextFactory(bpctx),
+ bp: bpctx,
+ }
+ return a.mutator.IncomingTransition(ctx, incomingVariation)
} else {
return ""
}
@@ -613,15 +555,14 @@
func (a *androidTransitionMutator) Mutate(ctx blueprint.BottomUpMutatorContext, variation string) {
if am, ok := ctx.Module().(Module); ok {
- a.mutator.Mutate(bottomUpMutatorContextFactory(ctx, am, a.finalPhase, a.bazelConversionMode), variation)
+ a.mutator.Mutate(bottomUpMutatorContextFactory(ctx, am, a.finalPhase), variation)
}
}
func (x *registerMutatorsContext) Transition(name string, m TransitionMutator) {
atm := &androidTransitionMutator{
- finalPhase: x.finalPhase,
- bazelConversionMode: x.bazelConversionMode,
- mutator: m,
+ finalPhase: x.finalPhase,
+ mutator: m,
}
mutator := &mutator{
name: name,
@@ -630,9 +571,6 @@
}
func (x *registerMutatorsContext) mutatorName(name string) string {
- if x.bazelConversionMode {
- return name + "_bp2build"
- }
return name
}
@@ -640,7 +578,6 @@
f := func(ctx blueprint.TopDownMutatorContext) {
if a, ok := ctx.Module().(Module); ok {
moduleContext := a.base().baseModuleContextFactory(ctx)
- moduleContext.bazelConversionMode = x.bazelConversionMode
actx := &topDownMutatorContext{
bp: ctx,
baseModuleContext: moduleContext,
@@ -696,6 +633,7 @@
func depsMutator(ctx BottomUpMutatorContext) {
if m := ctx.Module(); m.Enabled() {
+ m.base().baseDepsMutator(ctx)
m.DepsMutator(ctx)
}
}
@@ -704,185 +642,6 @@
ctx.BottomUp("deps", depsMutator).Parallel()
}
-func registerDepsMutatorBp2Build(ctx RegisterMutatorsContext) {
- // TODO(b/179313531): Consider a separate mutator that only runs depsMutator for modules that are
- // being converted to build targets.
- ctx.BottomUp("deps", depsMutator).Parallel()
-}
-
-func (t *topDownMutatorContext) CreateBazelTargetModule(
- bazelProps bazel.BazelTargetModuleProperties,
- commonAttrs CommonAttributes,
- attrs interface{}) {
- t.createBazelTargetModule(bazelProps, commonAttrs, attrs, bazel.BoolAttribute{})
-}
-
-func (t *topDownMutatorContext) CreateBazelTargetModuleWithRestrictions(
- bazelProps bazel.BazelTargetModuleProperties,
- commonAttrs CommonAttributes,
- attrs interface{},
- enabledProperty bazel.BoolAttribute) {
- t.createBazelTargetModule(bazelProps, commonAttrs, attrs, enabledProperty)
-}
-
-func (t *topDownMutatorContext) MarkBp2buildUnconvertible(
- reasonType bp2build_metrics_proto.UnconvertedReasonType, detail string) {
- mod := t.Module()
- mod.base().setBp2buildUnconvertible(reasonType, detail)
-}
-
-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)
-}
-
-// Returns the directory in which the bazel target will be generated
-// If ca.Dir is not nil, use that
-// Otherwise default to the directory of the soong module
-func dirForBazelTargetGeneration(t *topDownMutatorContext, ca *CommonAttributes) string {
- dir := t.OtherModuleDir(t.Module())
- if ca.Dir != nil {
- dir = *ca.Dir
- // Restrict its use to dirs that contain an Android.bp file.
- // There are several places in bp2build where we use the existence of Android.bp/BUILD on the filesystem
- // to curate a compatible label for src files (e.g. headers for cc).
- // If we arbritrarily create BUILD files, then it might render those curated labels incompatible.
- if exists, _, _ := t.Config().fs.Exists(filepath.Join(dir, "Android.bp")); !exists {
- t.ModuleErrorf("Cannot use ca.Dir to create a BazelTarget in dir: %v since it does not contain an Android.bp file", dir)
- }
-
- // Set ca.Dir to nil so that it does not get emitted to the BUILD files
- ca.Dir = nil
- }
- return dir
-}
-
-func (t *topDownMutatorContext) CreateBazelConfigSetting(
- csa bazel.ConfigSettingAttributes,
- ca CommonAttributes,
- dir string) {
- mod := t.Module()
- info := bp2buildInfo{
- Dir: dir,
- BazelProps: bazel.BazelTargetModuleProperties{
- Rule_class: "config_setting",
- },
- CommonAttrs: ca,
- ConstraintAttrs: constraintAttributes{},
- Attrs: &csa,
- }
- 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 {
- attr := bazel.StringListAttribute{}
- // Transform specific attributes into tags.
- if am, ok := mod.(ApexModule); ok {
- // TODO(b/218841706): hidl_interface has the apex_available prop, but it's
- // defined directly as a prop and not via ApexModule, so this doesn't
- // pick those props up.
- apexAvailable := am.apexModuleBase().ApexAvailable()
- // If a user does not specify apex_available in Android.bp, then soong provides a default.
- // To avoid verbosity of BUILD files, remove this default from user-facing BUILD files.
- if len(am.apexModuleBase().ApexProperties.Apex_available) == 0 {
- apexAvailable = []string{}
- }
- attr.Value = ConvertApexAvailableToTags(apexAvailable)
- }
- return attr
-}
-
-func ApexAvailableTagsWithoutTestApexes(ctx BaseModuleContext, mod Module) bazel.StringListAttribute {
- attr := bazel.StringListAttribute{}
- if am, ok := mod.(ApexModule); ok {
- apexAvailableWithoutTestApexes := removeTestApexes(ctx, am.apexModuleBase().ApexAvailable())
- // If a user does not specify apex_available in Android.bp, then soong provides a default.
- // To avoid verbosity of BUILD files, remove this default from user-facing BUILD files.
- if len(am.apexModuleBase().ApexProperties.Apex_available) == 0 {
- apexAvailableWithoutTestApexes = []string{}
- }
- attr.Value = ConvertApexAvailableToTags(apexAvailableWithoutTestApexes)
- }
- return attr
-}
-
-func removeTestApexes(ctx BaseModuleContext, apex_available []string) []string {
- testApexes := []string{}
- for _, aa := range apex_available {
- // ignore the wildcards
- if InList(aa, AvailableToRecognziedWildcards) {
- continue
- }
- mod, _ := ctx.ModuleFromName(aa)
- if apex, ok := mod.(ApexTestInterface); ok && apex.IsTestApex() {
- testApexes = append(testApexes, aa)
- }
- }
- return RemoveListFromList(CopyOf(apex_available), testApexes)
-}
-
-func ConvertApexAvailableToTags(apexAvailable []string) []string {
- if len(apexAvailable) == 0 {
- // We need nil specifically to make bp2build not add the tags property at all,
- // instead of adding it with an empty list
- return nil
- }
- result := make([]string, 0, len(apexAvailable))
- for _, a := range apexAvailable {
- result = append(result, "apex_available="+a)
- }
- return result
-}
-
-// ConvertApexAvailableToTagsWithoutTestApexes converts a list of apex names to a list of bazel tags
-// This function drops any test apexes from the input.
-func ConvertApexAvailableToTagsWithoutTestApexes(ctx BaseModuleContext, apexAvailable []string) []string {
- noTestApexes := removeTestApexes(ctx, apexAvailable)
- return ConvertApexAvailableToTags(noTestApexes)
-}
-
-func (t *topDownMutatorContext) createBazelTargetModule(
- bazelProps bazel.BazelTargetModuleProperties,
- commonAttrs CommonAttributes,
- attrs interface{},
- enabledProperty bazel.BoolAttribute) {
- constraintAttributes := commonAttrs.fillCommonBp2BuildModuleAttrs(t, enabledProperty)
- mod := t.Module()
- info := bp2buildInfo{
- Dir: dirForBazelTargetGeneration(t, &commonAttrs),
- BazelProps: bazelProps,
- CommonAttrs: commonAttrs,
- ConstraintAttrs: constraintAttributes,
- Attrs: attrs,
- }
- mod.base().addBp2buildInfo(info)
-}
-
// android.topDownMutatorContext either has to embed blueprint.TopDownMutatorContext, in which case every method that
// has an overridden version in android.BaseModuleContext has to be manually forwarded to BaseModuleContext to avoid
// ambiguous method errors, or it has to store a blueprint.TopDownMutatorContext non-embedded, in which case every
@@ -1021,6 +780,6 @@
b.bp.CreateAliasVariation(fromVariationName, toVariationName)
}
-func (b *bottomUpMutatorContext) SetVariationProvider(module blueprint.Module, provider blueprint.ProviderKey, value interface{}) {
+func (b *bottomUpMutatorContext) SetVariationProvider(module blueprint.Module, provider blueprint.AnyProviderKey, value interface{}) {
b.bp.SetVariationProvider(module, provider, value)
}
diff --git a/android/mutator_test.go b/android/mutator_test.go
index dbdfa33..21eebd2 100644
--- a/android/mutator_test.go
+++ b/android/mutator_test.go
@@ -16,7 +16,6 @@
import (
"fmt"
- "reflect"
"strings"
"testing"
@@ -268,22 +267,3 @@
FixtureWithRootAndroidBp(`test {name: "foo"}`),
).RunTest(t)
}
-
-func TestConvertApexAvailableToTags(t *testing.T) {
- input := []string{
- "com.android.adbd",
- "//apex_available:platform",
- }
- actual := ConvertApexAvailableToTags(input)
- expected := []string{
- "apex_available=com.android.adbd",
- "apex_available=//apex_available:platform",
- }
- if !reflect.DeepEqual(actual, expected) {
- t.Errorf("Expected: %v, actual: %v", expected, actual)
- }
-
- if ConvertApexAvailableToTags(nil) != nil {
- t.Errorf("Expected providing nil to return nil")
- }
-}
diff --git a/android/neverallow.go b/android/neverallow.go
index 2be6a74..62c5e59 100644
--- a/android/neverallow.go
+++ b/android/neverallow.go
@@ -57,7 +57,6 @@
AddNeverAllowRules(createUncompressDexRules()...)
AddNeverAllowRules(createInitFirstStageRules()...)
AddNeverAllowRules(createProhibitFrameworkAccessRules()...)
- AddNeverAllowRules(createBp2BuildRule())
AddNeverAllowRules(createCcStubsRule())
AddNeverAllowRules(createJavaExcludeStaticLibsRule())
AddNeverAllowRules(createProhibitHeaderOnlyRule())
@@ -68,14 +67,6 @@
neverallows = append(neverallows, rules...)
}
-func createBp2BuildRule() Rule {
- return NeverAllow().
- With("bazel_module.bp2build_available", "true").
- NotIn("soong_tests"). // only used in tests
- Because("setting bp2build_available in Android.bp is not " +
- "supported for custom conversion, use allowlists.go instead.")
-}
-
var (
neverallowNotInIncludeDir = []string{
"art",
@@ -169,6 +160,8 @@
"external/kotlinx.coroutines",
"external/robolectric-shadows",
"external/robolectric",
+ "frameworks/base/ravenwood",
+ "frameworks/base/tools/hoststubgen",
"frameworks/layoutlib",
}
diff --git a/android/override_module.go b/android/override_module.go
index 9e0de6f..1341f53 100644
--- a/android/override_module.go
+++ b/android/override_module.go
@@ -214,17 +214,6 @@
}
b.overridableModuleProperties.OverriddenBy = o.Name()
b.overridableModuleProperties.OverriddenByModuleDir = o.ModuleDir()
-
- if oBazelable, ok := o.base().module.(Bazelable); ok {
- if bBazelable, ok := m.(Bazelable); ok {
- oProps := oBazelable.bazelProps()
- bProps := bBazelable.bazelProps()
- bProps.Bazel_module.Bp2build_available = oProps.Bazel_module.Bp2build_available
- bProps.Bazel_module.Label = oProps.Bazel_module.Label
- } else {
- ctx.ModuleErrorf("Override type cannot be Bazelable if original module type is not Bazelable %v %v.", o.Name(), m.Name())
- }
- }
}
// GetOverriddenBy returns the name of the override module that has overridden this module.
@@ -348,31 +337,3 @@
}
}
}
-
-// ModuleNameWithPossibleOverride returns the name of the OverrideModule that overrides the current
-// variant of this OverridableModule, or ctx.ModuleName() if this module is not an OverridableModule
-// or if this variant is not overridden.
-func ModuleNameWithPossibleOverride(ctx BazelConversionContext) string {
- return moduleNameWithPossibleOverride(ctx, ctx.Module(), ctx.OtherModuleName(ctx.Module()))
-}
-
-func moduleNameWithPossibleOverride(ctx shouldConvertModuleContext, module blueprint.Module, name string) string {
- if overridable, ok := module.(OverridableModule); ok {
- if o := overridable.GetOverriddenBy(); o != "" {
- return o
- }
- }
- return name
-}
-
-// moduleDirWithPossibleOverride returns the dir of the OverrideModule that overrides the current
-// variant of the given OverridableModule, or ctx.OtherModuleName() if the module is not an
-// OverridableModule or if the variant is not overridden.
-func moduleDirWithPossibleOverride(ctx shouldConvertModuleContext, module blueprint.Module, dir string) string {
- if overridable, ok := module.(OverridableModule); ok {
- if o := overridable.GetOverriddenByModuleDir(); o != "" {
- return o
- }
- }
- return dir
-}
diff --git a/android/package.go b/android/package.go
index 7fbc700..eb76751 100644
--- a/android/package.go
+++ b/android/package.go
@@ -15,9 +15,6 @@
package android
import (
- "path/filepath"
-
- "android/soong/bazel"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -38,58 +35,26 @@
Default_visibility []string
// Specifies the default license terms for all modules defined in this package.
Default_applicable_licenses []string
-}
-
-type bazelPackageAttributes struct {
- Default_visibility []string
- Default_package_metadata bazel.LabelListAttribute
+ Default_team *string `android:"path"`
}
type packageModule struct {
ModuleBase
- BazelModuleBase
properties packageProperties
}
-var _ Bazelable = &packageModule{}
-
-func (p *packageModule) ConvertWithBp2build(ctx TopDownMutatorContext) {
- defaultPackageMetadata := bazel.MakeLabelListAttribute(BazelLabelForModuleDeps(ctx, p.properties.Default_applicable_licenses))
- // If METADATA file exists in the package, add it to package(default_package_metadata=) using a
- // filegroup(name="default_metadata_file") which can be accessed later on each module in Bazel
- // using attribute "applicable_licenses".
- // Attribute applicable_licenses of filegroup "default_metadata_file" has to be set to [],
- // otherwise Bazel reports cyclic reference error.
- if existed, _, _ := ctx.Config().fs.Exists(filepath.Join(ctx.ModuleDir(), "METADATA")); existed {
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "filegroup",
- },
- CommonAttributes{Name: "default_metadata_file"},
- &bazelFilegroupAttributes{
- Srcs: bazel.MakeLabelListAttribute(BazelLabelForModuleSrc(ctx, []string{"METADATA"})),
- Applicable_licenses: bazel.LabelListAttribute{Value: bazel.LabelList{Includes: []bazel.Label{}}, EmitEmptyList: true},
- })
- defaultPackageMetadata.Value.Add(&bazel.Label{Label: ":default_metadata_file"})
- }
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "package",
- },
- CommonAttributes{},
- &bazelPackageAttributes{
- Default_package_metadata: defaultPackageMetadata,
- // FIXME(asmundak): once b/221436821 is resolved
- Default_visibility: []string{"//visibility:public"},
- })
-}
-
func (p *packageModule) GenerateAndroidBuildActions(ModuleContext) {
// Nothing to do.
}
+func (p *packageModule) DepsMutator(ctx BottomUpMutatorContext) {
+ // Add the dependency to do a validity check
+ if p.properties.Default_team != nil {
+ ctx.AddDependency(ctx.Module(), nil, *p.properties.Default_team)
+ }
+}
+
func (p *packageModule) GenerateBuildActions(ctx blueprint.ModuleContext) {
// Nothing to do.
}
@@ -102,7 +67,7 @@
func PackageFactory() Module {
module := &packageModule{}
- module.AddProperties(&module.properties, &module.commonProperties.BazelConversionStatus)
+ module.AddProperties(&module.properties)
// The name is the relative path from build root to the directory containing this
// module. Set that name at the earliest possible moment that information is available
@@ -119,7 +84,5 @@
// its checking and parsing phases so make it the primary licenses property.
setPrimaryLicensesProperty(module, "default_applicable_licenses", &module.properties.Default_applicable_licenses)
- InitBazelModule(module)
-
return module
}
diff --git a/android/packaging.go b/android/packaging.go
index 503bb97..8873540 100644
--- a/android/packaging.go
+++ b/android/packaging.go
@@ -17,6 +17,7 @@
import (
"fmt"
"path/filepath"
+ "strings"
"github.com/google/blueprint"
)
@@ -239,7 +240,14 @@
// CopySpecsToDir is a helper that will add commands to the rule builder to copy the PackagingSpec
// entries into the specified directory.
func (p *PackagingBase) CopySpecsToDir(ctx ModuleContext, builder *RuleBuilder, specs map[string]PackagingSpec, dir WritablePath) (entries []string) {
+ if len(specs) == 0 {
+ return entries
+ }
seenDir := make(map[string]bool)
+ preparerPath := PathForModuleOut(ctx, "preparer.sh")
+ cmd := builder.Command().Tool(preparerPath)
+ var sb strings.Builder
+ sb.WriteString("set -e\n")
for _, k := range SortedKeys(specs) {
ps := specs[k]
destPath := filepath.Join(dir.String(), ps.relPathInPackage)
@@ -247,18 +255,21 @@
entries = append(entries, ps.relPathInPackage)
if _, ok := seenDir[destDir]; !ok {
seenDir[destDir] = true
- builder.Command().Text("mkdir").Flag("-p").Text(destDir)
+ sb.WriteString(fmt.Sprintf("mkdir -p %s\n", destDir))
}
if ps.symlinkTarget == "" {
- builder.Command().Text("cp").Input(ps.srcPath).Text(destPath)
+ cmd.Implicit(ps.srcPath)
+ sb.WriteString(fmt.Sprintf("cp %s %s\n", ps.srcPath, destPath))
} else {
- builder.Command().Text("ln").Flag("-sf").Text(ps.symlinkTarget).Text(destPath)
+ sb.WriteString(fmt.Sprintf("ln -sf %s %s\n", ps.symlinkTarget, destPath))
}
if ps.executable {
- builder.Command().Text("chmod").Flag("a+x").Text(destPath)
+ sb.WriteString(fmt.Sprintf("chmod a+x %s\n", destPath))
}
}
+ WriteExecutableFileRuleVerbatim(ctx, preparerPath, sb.String())
+
return entries
}
diff --git a/android/path_properties.go b/android/path_properties.go
index fdc4d91..bbfaa8c 100644
--- a/android/path_properties.go
+++ b/android/path_properties.go
@@ -33,6 +33,11 @@
// The pathDepsMutator automatically adds dependencies on any module that is listed with the
// ":module" module reference syntax in a property that is tagged with `android:"path"`.
func pathDepsMutator(ctx BottomUpMutatorContext) {
+ if _, ok := ctx.Module().(DefaultsModule); ok {
+ // Defaults modules shouldn't have dependencies added for path properties, they have already been
+ // squashed into the real modules.
+ return
+ }
props := ctx.Module().base().GetProperties()
addPathDepsForProps(ctx, props)
}
diff --git a/android/paths.go b/android/paths.go
index 325a953..95f53ea 100644
--- a/android/paths.go
+++ b/android/paths.go
@@ -111,11 +111,68 @@
InstallInDebugRamdisk() bool
InstallInRecovery() bool
InstallInRoot() bool
+ InstallInOdm() bool
+ InstallInProduct() bool
+ InstallInVendor() bool
InstallForceOS() (*OsType, *ArchType)
}
var _ ModuleInstallPathContext = ModuleContext(nil)
+type baseModuleContextToModuleInstallPathContext struct {
+ BaseModuleContext
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInData() bool {
+ return ctx.Module().InstallInData()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInTestcases() bool {
+ return ctx.Module().InstallInTestcases()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInSanitizerDir() bool {
+ return ctx.Module().InstallInSanitizerDir()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInRamdisk() bool {
+ return ctx.Module().InstallInRamdisk()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInVendorRamdisk() bool {
+ return ctx.Module().InstallInVendorRamdisk()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInDebugRamdisk() bool {
+ return ctx.Module().InstallInDebugRamdisk()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInRecovery() bool {
+ return ctx.Module().InstallInRecovery()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInRoot() bool {
+ return ctx.Module().InstallInRoot()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInOdm() bool {
+ return ctx.Module().InstallInOdm()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInProduct() bool {
+ return ctx.Module().InstallInProduct()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallInVendor() bool {
+ return ctx.Module().InstallInVendor()
+}
+
+func (ctx *baseModuleContextToModuleInstallPathContext) InstallForceOS() (*OsType, *ArchType) {
+ return ctx.Module().InstallForceOS()
+}
+
+var _ ModuleInstallPathContext = (*baseModuleContextToModuleInstallPathContext)(nil)
+
// errorfContext is the interface containing the Errorf method matching the
// Errorf method in blueprint.SingletonContext.
type errorfContext interface {
@@ -124,13 +181,13 @@
var _ errorfContext = blueprint.SingletonContext(nil)
-// moduleErrorf is the interface containing the ModuleErrorf method matching
+// ModuleErrorfContext is the interface containing the ModuleErrorf method matching
// the ModuleErrorf method in blueprint.ModuleContext.
-type moduleErrorf interface {
+type ModuleErrorfContext interface {
ModuleErrorf(format string, args ...interface{})
}
-var _ moduleErrorf = blueprint.ModuleContext(nil)
+var _ ModuleErrorfContext = blueprint.ModuleContext(nil)
// reportPathError will register an error with the attached context. It
// attempts ctx.ModuleErrorf for a better error message first, then falls
@@ -143,7 +200,7 @@
// attempts ctx.ModuleErrorf for a better error message first, then falls
// back to ctx.Errorf.
func ReportPathErrorf(ctx PathContext, format string, args ...interface{}) {
- if mctx, ok := ctx.(moduleErrorf); ok {
+ if mctx, ok := ctx.(ModuleErrorfContext); ok {
mctx.ModuleErrorf(format, args...)
} else if ectx, ok := ctx.(errorfContext); ok {
ectx.Errorf(format, args...)
@@ -480,7 +537,7 @@
// PathForGoBinary returns the path to the installed location of a bootstrap_go_binary module.
func PathForGoBinary(ctx PathContext, goBinary bootstrap.GoBinaryTool) Path {
- goBinaryInstallDir := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "bin", false)
+ goBinaryInstallDir := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "bin")
rel := Rel(ctx, goBinaryInstallDir.String(), goBinary.InstallPath())
return goBinaryInstallDir.Join(ctx, rel)
}
@@ -1683,20 +1740,20 @@
// module appended with paths...
func PathForModuleInstall(ctx ModuleInstallPathContext, pathComponents ...string) InstallPath {
os, arch := osAndArch(ctx)
- partition := modulePartition(ctx, os)
- return makePathForInstall(ctx, os, arch, partition, ctx.Debug(), pathComponents...)
+ partition := modulePartition(ctx, os.Class == Device)
+ return pathForInstall(ctx, os, arch, partition, pathComponents...)
}
// PathForHostDexInstall returns an InstallPath representing the install path for the
// module appended with paths...
func PathForHostDexInstall(ctx ModuleInstallPathContext, pathComponents ...string) InstallPath {
- return makePathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "", ctx.Debug(), pathComponents...)
+ return pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "", pathComponents...)
}
// PathForModuleInPartitionInstall is similar to PathForModuleInstall but partition is provided by the caller
func PathForModuleInPartitionInstall(ctx ModuleInstallPathContext, partition string, pathComponents ...string) InstallPath {
os, arch := osAndArch(ctx)
- return makePathForInstall(ctx, os, arch, partition, ctx.Debug(), pathComponents...)
+ return pathForInstall(ctx, os, arch, partition, pathComponents...)
}
func osAndArch(ctx ModuleInstallPathContext) (OsType, ArchType) {
@@ -1712,12 +1769,7 @@
return os, arch
}
-func makePathForInstall(ctx ModuleInstallPathContext, os OsType, arch ArchType, partition string, debug bool, pathComponents ...string) InstallPath {
- ret := pathForInstall(ctx, os, arch, partition, debug, pathComponents...)
- return ret
-}
-
-func pathForInstall(ctx PathContext, os OsType, arch ArchType, partition string, debug bool,
+func pathForInstall(ctx PathContext, os OsType, arch ArchType, partition string,
pathComponents ...string) InstallPath {
var partitionPaths []string
@@ -1747,9 +1799,6 @@
}
partitionPaths = []string{"host", osName + "-" + archName, partition}
}
- if debug {
- partitionPaths = append([]string{"debug"}, partitionPaths...)
- }
partitionPath, err := validatePath(partitionPaths...)
if err != nil {
@@ -1793,12 +1842,12 @@
return "/" + rel
}
-func modulePartition(ctx ModuleInstallPathContext, os OsType) string {
+func modulePartition(ctx ModuleInstallPathContext, device bool) string {
var partition string
if ctx.InstallInTestcases() {
// "testcases" install directory can be used for host or device modules.
partition = "testcases"
- } else if os.Class == Device {
+ } else if device {
if ctx.InstallInData() {
partition = "data"
} else if ctx.InstallInRamdisk() {
@@ -1832,11 +1881,11 @@
// the layout of recovery partion is the same as that of system partition
partition = "recovery/root/system"
}
- } else if ctx.SocSpecific() {
+ } else if ctx.SocSpecific() || ctx.InstallInVendor() {
partition = ctx.DeviceConfig().VendorPath()
- } else if ctx.DeviceSpecific() {
+ } else if ctx.DeviceSpecific() || ctx.InstallInOdm() {
partition = ctx.DeviceConfig().OdmPath()
- } else if ctx.ProductSpecific() {
+ } else if ctx.ProductSpecific() || ctx.InstallInProduct() {
partition = ctx.DeviceConfig().ProductPath()
} else if ctx.SystemExtSpecific() {
partition = ctx.DeviceConfig().SystemExtPath()
@@ -1881,7 +1930,9 @@
// validatePathInternal ensures that a path does not leave its component, and
// optionally doesn't contain Ninja variables.
func validatePathInternal(allowNinjaVariables bool, pathComponents ...string) (string, error) {
- for _, path := range pathComponents {
+ initialEmpty := 0
+ finalEmpty := 0
+ for i, path := range pathComponents {
if !allowNinjaVariables && strings.Contains(path, "$") {
return "", fmt.Errorf("Path contains invalid character($): %s", path)
}
@@ -1890,11 +1941,25 @@
if path == ".." || strings.HasPrefix(path, "../") || strings.HasPrefix(path, "/") {
return "", fmt.Errorf("Path is outside directory: %s", path)
}
+
+ if i == initialEmpty && pathComponents[i] == "" {
+ initialEmpty++
+ }
+ if i == finalEmpty && pathComponents[len(pathComponents)-1-i] == "" {
+ finalEmpty++
+ }
}
+ // Optimization: filepath.Join("foo", "") returns a newly allocated copy
+ // of "foo", while filepath.Join("foo") does not. Strip out any empty
+ // path components.
+ if initialEmpty == len(pathComponents) {
+ return "", nil
+ }
+ nonEmptyPathComponents := pathComponents[initialEmpty : len(pathComponents)-finalEmpty]
// TODO: filepath.Join isn't necessarily correct with embedded ninja
// variables. '..' may remove the entire ninja variable, even if it
// will be expanded to multiple nested directories.
- return filepath.Join(pathComponents...), nil
+ return filepath.Join(nonEmptyPathComponents...), nil
}
// validateSafePath validates a path that we trust (may contain ninja
@@ -2016,6 +2081,9 @@
inDebugRamdisk bool
inRecovery bool
inRoot bool
+ inOdm bool
+ inProduct bool
+ inVendor bool
forceOS *OsType
forceArch *ArchType
}
@@ -2058,6 +2126,18 @@
return m.inRoot
}
+func (m testModuleInstallPathContext) InstallInOdm() bool {
+ return m.inOdm
+}
+
+func (m testModuleInstallPathContext) InstallInProduct() bool {
+ return m.inProduct
+}
+
+func (m testModuleInstallPathContext) InstallInVendor() bool {
+ return m.inVendor
+}
+
func (m testModuleInstallPathContext) InstallForceOS() (*OsType, *ArchType) {
return m.forceOS, m.forceArch
}
@@ -2158,6 +2238,19 @@
SrcPath Path
// The install path of the data file, relative to the install root.
RelativeInstallPath string
+ // If WithoutRel is true, use SrcPath.Base() instead of SrcPath.Rel() as the filename.
+ WithoutRel bool
+}
+
+func (d *DataPath) ToRelativeInstallPath() string {
+ relPath := d.SrcPath.Rel()
+ if d.WithoutRel {
+ relPath = d.SrcPath.Base()
+ }
+ if d.RelativeInstallPath != "" {
+ relPath = filepath.Join(d.RelativeInstallPath, relPath)
+ }
+ return relPath
}
// PathsIfNonNil returns a Paths containing only the non-nil input arguments.
diff --git a/android/paths_test.go b/android/paths_test.go
index 2f87977..93b9b9a 100644
--- a/android/paths_test.go
+++ b/android/paths_test.go
@@ -37,6 +37,22 @@
out: "",
},
{
+ in: []string{"", ""},
+ out: "",
+ },
+ {
+ in: []string{"a", ""},
+ out: "a",
+ },
+ {
+ in: []string{"", "a"},
+ out: "a",
+ },
+ {
+ in: []string{"", "a", ""},
+ out: "a",
+ },
+ {
in: []string{"a/b"},
out: "a/b",
},
@@ -252,8 +268,10 @@
name: "host binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: hostTarget.Os,
- target: hostTarget,
+ archModuleContext: archModuleContext{
+ os: hostTarget.Os,
+ target: hostTarget,
+ },
},
},
in: []string{"bin", "my_test"},
@@ -265,8 +283,10 @@
name: "system binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
},
in: []string{"bin", "my_test"},
@@ -277,8 +297,10 @@
name: "vendor binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: socSpecificModule,
},
@@ -292,8 +314,10 @@
name: "odm binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: deviceSpecificModule,
},
@@ -307,8 +331,10 @@
name: "product binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: productSpecificModule,
},
@@ -322,8 +348,10 @@
name: "system_ext binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: systemExtSpecificModule,
},
@@ -337,8 +365,10 @@
name: "root binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
inRoot: true,
},
@@ -350,8 +380,10 @@
name: "recovery binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
inRecovery: true,
},
@@ -363,8 +395,10 @@
name: "recovery root binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
inRecovery: true,
inRoot: true,
@@ -378,8 +412,10 @@
name: "ramdisk binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
inRamdisk: true,
},
@@ -391,8 +427,10 @@
name: "ramdisk root binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
inRamdisk: true,
inRoot: true,
@@ -405,8 +443,10 @@
name: "vendor_ramdisk binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
inVendorRamdisk: true,
},
@@ -418,8 +458,10 @@
name: "vendor_ramdisk root binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
inVendorRamdisk: true,
inRoot: true,
@@ -432,8 +474,10 @@
name: "debug_ramdisk binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
inDebugRamdisk: true,
},
@@ -445,8 +489,10 @@
name: "system native test binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
inData: true,
},
@@ -458,8 +504,10 @@
name: "vendor native test binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: socSpecificModule,
},
@@ -474,8 +522,10 @@
name: "odm native test binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: deviceSpecificModule,
},
@@ -490,8 +540,10 @@
name: "product native test binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: productSpecificModule,
},
@@ -507,8 +559,10 @@
name: "system_ext native test binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: systemExtSpecificModule,
},
@@ -524,8 +578,10 @@
name: "sanitized system binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
inSanitizerDir: true,
},
@@ -537,8 +593,10 @@
name: "sanitized vendor binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: socSpecificModule,
},
@@ -553,8 +611,10 @@
name: "sanitized odm binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: deviceSpecificModule,
},
@@ -569,8 +629,10 @@
name: "sanitized product binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: productSpecificModule,
},
@@ -586,8 +648,10 @@
name: "sanitized system_ext binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: systemExtSpecificModule,
},
@@ -603,8 +667,10 @@
name: "sanitized system native test binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
inData: true,
inSanitizerDir: true,
@@ -617,8 +683,10 @@
name: "sanitized vendor native test binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: socSpecificModule,
},
@@ -634,8 +702,10 @@
name: "sanitized odm native test binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: deviceSpecificModule,
},
@@ -651,8 +721,10 @@
name: "sanitized product native test binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: productSpecificModule,
},
@@ -668,8 +740,10 @@
name: "sanitized system_ext native test binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
earlyModuleContext: earlyModuleContext{
kind: systemExtSpecificModule,
},
@@ -684,8 +758,10 @@
name: "device testcases",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
inTestcases: true,
},
@@ -696,8 +772,10 @@
name: "host testcases",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: hostTarget.Os,
- target: hostTarget,
+ archModuleContext: archModuleContext{
+ os: hostTarget.Os,
+ target: hostTarget,
+ },
},
inTestcases: true,
},
@@ -708,8 +786,10 @@
name: "forced host testcases",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
inTestcases: true,
forceOS: &Linux,
@@ -755,8 +835,10 @@
name: "ramdisk binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
inRamdisk: true,
inRoot: true,
@@ -770,8 +852,10 @@
name: "vendor_ramdisk binary",
ctx: &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
inVendorRamdisk: true,
inRoot: true,
@@ -805,8 +889,10 @@
ctx := &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
}
ctx.baseModuleContext.config = testConfig
@@ -1475,8 +1561,10 @@
ctx := &testModuleInstallPathContext{
baseModuleContext: baseModuleContext{
- os: deviceTarget.Os,
- target: deviceTarget,
+ archModuleContext: archModuleContext{
+ os: deviceTarget.Os,
+ target: deviceTarget,
+ },
},
}
ctx.baseModuleContext.config = testConfig
diff --git a/android/plugin.go b/android/plugin.go
index 4672453..d62fc94 100644
--- a/android/plugin.go
+++ b/android/plugin.go
@@ -16,8 +16,6 @@
import (
"encoding/json"
- "fmt"
- "io/ioutil"
"os"
"strings"
@@ -72,28 +70,30 @@
"xsdc-soong-rules": true,
}
-const (
- internalPluginsPath = "vendor/google/build/soong/internal_plugins.json"
-)
+var internalPluginsPaths = []string{
+ "vendor/google/build/soong/internal_plugins.json",
+}
type pluginProvider interface {
IsPluginFor(string) bool
}
func maybeAddInternalPluginsToAllowlist(ctx SingletonContext) {
- if path := ExistentPathForSource(ctx, internalPluginsPath); path.Valid() {
- ctx.AddNinjaFileDeps(path.String())
- absPath := absolutePath(path.String())
- var moreAllowed map[string]bool
- data, err := ioutil.ReadFile(absPath)
- if err != nil {
- ctx.Errorf("Failed to open internal plugins path %q %q", internalPluginsPath, err)
- }
- if err := json.Unmarshal(data, &moreAllowed); err != nil {
- fmt.Fprintf(os.Stderr, "Internal plugins file %q did not parse correctly: %q", data, err)
- }
- for k, v := range moreAllowed {
- allowedPluginsByName[k] = v
+ for _, internalPluginsPath := range internalPluginsPaths {
+ if path := ExistentPathForSource(ctx, internalPluginsPath); path.Valid() {
+ ctx.AddNinjaFileDeps(path.String())
+ absPath := absolutePath(path.String())
+ var moreAllowed map[string]bool
+ data, err := os.ReadFile(absPath)
+ if err != nil {
+ ctx.Errorf("Failed to open internal plugins path %q %q", internalPluginsPath, err)
+ }
+ if err := json.Unmarshal(data, &moreAllowed); err != nil {
+ ctx.Errorf("Internal plugins file %q did not parse correctly: %q", data, err)
+ }
+ for k, v := range moreAllowed {
+ allowedPluginsByName[k] = v
+ }
}
}
}
diff --git a/android/prebuilt.go b/android/prebuilt.go
index 95b772d..a94f5b7 100644
--- a/android/prebuilt.go
+++ b/android/prebuilt.go
@@ -277,6 +277,9 @@
}
value := srcPropsValue.FieldByIndex(srcFieldIndex)
if value.Kind() == reflect.Ptr {
+ if value.IsNil() {
+ return nil
+ }
value = value.Elem()
}
if value.Kind() != reflect.String {
@@ -387,16 +390,23 @@
func RegisterPrebuiltsPostDepsMutators(ctx RegisterMutatorsContext) {
ctx.BottomUp("prebuilt_source", PrebuiltSourceDepsMutator).Parallel()
- ctx.TopDown("prebuilt_select", PrebuiltSelectModuleMutator).Parallel()
+ ctx.BottomUp("prebuilt_select", PrebuiltSelectModuleMutator).Parallel()
ctx.BottomUp("prebuilt_postdeps", PrebuiltPostDepsMutator).Parallel()
}
+// Returns the name of the source module corresponding to a prebuilt module
+// For source modules, it returns its own name
+type baseModuleName interface {
+ BaseModuleName() string
+}
+
// PrebuiltRenameMutator ensures that there always is a module with an
// undecorated name.
func PrebuiltRenameMutator(ctx BottomUpMutatorContext) {
m := ctx.Module()
if p := GetEmbeddedPrebuilt(m); p != nil {
- name := m.base().BaseModuleName()
+ bmn, _ := m.(baseModuleName)
+ name := bmn.BaseModuleName()
if !ctx.OtherModuleExists(name) {
ctx.Rename(name)
p.properties.PrebuiltRenamedToSource = true
@@ -406,16 +416,27 @@
// PrebuiltSourceDepsMutator adds dependencies to the prebuilt module from the
// corresponding source module, if one exists for the same variant.
+// Add a dependency from the prebuilt to `all_apex_contributions`
+// The metadata will be used for source vs prebuilts selection
func PrebuiltSourceDepsMutator(ctx BottomUpMutatorContext) {
m := ctx.Module()
// If this module is a prebuilt, is enabled and has not been renamed to source then add a
// dependency onto the source if it is present.
if p := GetEmbeddedPrebuilt(m); p != nil && m.Enabled() && !p.properties.PrebuiltRenamedToSource {
- name := m.base().BaseModuleName()
+ bmn, _ := m.(baseModuleName)
+ name := bmn.BaseModuleName()
if ctx.OtherModuleReverseDependencyVariantExists(name) {
ctx.AddReverseDependency(ctx.Module(), PrebuiltDepTag, name)
p.properties.SourceExists = true
}
+ // Add a dependency from the prebuilt to the `all_apex_contributions`
+ // metadata module
+ // TODO: When all branches contain this singleton module, make this strict
+ // TODO: Add this dependency only for mainline prebuilts and not every prebuilt module
+ if ctx.OtherModuleExists("all_apex_contributions") {
+ ctx.AddDependency(m, acDepTag, "all_apex_contributions")
+ }
+
}
}
@@ -435,7 +456,11 @@
// PrebuiltSelectModuleMutator marks prebuilts that are used, either overriding source modules or
// because the source module doesn't exist. It also disables installing overridden source modules.
-func PrebuiltSelectModuleMutator(ctx TopDownMutatorContext) {
+//
+// If the visited module is the metadata module `all_apex_contributions`, it sets a
+// provider containing metadata about whether source or prebuilt of mainline modules should be used.
+// This logic was added here to prevent the overhead of creating a new mutator.
+func PrebuiltSelectModuleMutator(ctx BottomUpMutatorContext) {
m := ctx.Module()
if p := GetEmbeddedPrebuilt(m); p != nil {
if p.srcsSupplier == nil && p.srcsPropertyName == "" {
@@ -444,7 +469,21 @@
if !p.properties.SourceExists {
p.properties.UsePrebuilt = p.usePrebuilt(ctx, nil, m)
}
+ // Propagate the provider received from `all_apex_contributions`
+ // to the source module
+ ctx.VisitDirectDepsWithTag(acDepTag, func(am Module) {
+ psi, _ := OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider)
+ SetProvider(ctx, PrebuiltSelectionInfoProvider, psi)
+ })
+
} else if s, ok := ctx.Module().(Module); ok {
+ // Use `all_apex_contributions` for source vs prebuilt selection.
+ psi := PrebuiltSelectionInfoMap{}
+ ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(am Module) {
+ // The value of psi gets overwritten with the provider from the last visited prebuilt.
+ // But all prebuilts have the same value of the provider, so this should be idempontent.
+ psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider)
+ })
ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(prebuiltModule Module) {
p := GetEmbeddedPrebuilt(prebuiltModule)
if p.usePrebuilt(ctx, s, prebuiltModule) {
@@ -454,6 +493,49 @@
s.ReplacedByPrebuilt()
}
})
+
+ // If any module in this mainline module family has been flagged using apex_contributions, disable every other module in that family
+ // Add source
+ allModules := []Module{s}
+ // Add each prebuilt
+ ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(prebuiltModule Module) {
+ allModules = append(allModules, prebuiltModule)
+ })
+ hideUnflaggedModules(ctx, psi, allModules)
+
+ }
+
+ // If this is `all_apex_contributions`, set a provider containing
+ // metadata about source vs prebuilts selection
+ if am, ok := m.(*allApexContributions); ok {
+ am.SetPrebuiltSelectionInfoProvider(ctx)
+ }
+}
+
+// If any module in this mainline module family has been flagged using apex_contributions, disable every other module in that family
+func hideUnflaggedModules(ctx BottomUpMutatorContext, psi PrebuiltSelectionInfoMap, allModulesInFamily []Module) {
+ var selectedModuleInFamily Module
+ // query all_apex_contributions to see if any module in this family has been selected
+ for _, moduleInFamily := range allModulesInFamily {
+ // validate that are no duplicates
+ if psi.IsSelected(moduleInFamily.Name()) {
+ if selectedModuleInFamily == nil {
+ // Store this so we can validate that there are no duplicates
+ selectedModuleInFamily = moduleInFamily
+ } else {
+ // There are duplicate modules from the same mainline module family
+ ctx.ModuleErrorf("Found duplicate variations of the same module in apex_contributions: %s and %s. Please remove one of these.\n", selectedModuleInFamily.Name(), moduleInFamily.Name())
+ }
+ }
+ }
+
+ // If a module has been selected, hide all other modules
+ if selectedModuleInFamily != nil {
+ for _, moduleInFamily := range allModulesInFamily {
+ if moduleInFamily.Name() != selectedModuleInFamily.Name() {
+ moduleInFamily.HideFromMake()
+ }
+ }
}
}
@@ -463,7 +545,8 @@
func PrebuiltPostDepsMutator(ctx BottomUpMutatorContext) {
m := ctx.Module()
if p := GetEmbeddedPrebuilt(m); p != nil {
- name := m.base().BaseModuleName()
+ bmn, _ := m.(baseModuleName)
+ name := bmn.BaseModuleName()
if p.properties.UsePrebuilt {
if p.properties.SourceExists {
ctx.ReplaceDependenciesIf(name, func(from blueprint.Module, tag blueprint.DependencyTag, to blueprint.Module) bool {
@@ -480,9 +563,64 @@
}
}
+// A wrapper around PrebuiltSelectionInfoMap.IsSelected with special handling for java_sdk_library
+// java_sdk_library is a macro that creates
+// 1. top-level impl library
+// 2. stub libraries (suffixed with .stubs...)
+//
+// java_sdk_library_import is a macro that creates
+// 1. top-level "impl" library
+// 2. stub libraries (suffixed with .stubs...)
+//
+// the impl of java_sdk_library_import is a "hook" for hiddenapi and dexpreopt processing. It does not have an impl jar, but acts as a shim
+// to provide the jar deapxed from the prebuilt apex
+//
+// isSelected uses `all_apex_contributions` to supersede source vs prebuilts selection of the stub libraries. It does not supersede the
+// selection of the top-level "impl" library so that this hook can work
+//
+// TODO (b/308174306) - Fix this when we need to support multiple prebuilts in main
+func isSelected(psi PrebuiltSelectionInfoMap, m Module) bool {
+ if sdkLibrary, ok := m.(interface{ SdkLibraryName() *string }); ok && sdkLibrary.SdkLibraryName() != nil {
+ sln := proptools.String(sdkLibrary.SdkLibraryName())
+ // This is the top-level library
+ // Do not supersede the existing prebuilts vs source selection mechanisms
+ if sln == m.base().BaseModuleName() {
+ return false
+ }
+
+ // Stub library created by java_sdk_library_import
+ if p := GetEmbeddedPrebuilt(m); p != nil {
+ return psi.IsSelected(PrebuiltNameFromSource(sln))
+ }
+
+ // Stub library created by java_sdk_library
+ return psi.IsSelected(sln)
+ }
+ return psi.IsSelected(m.Name())
+}
+
// usePrebuilt returns true if a prebuilt should be used instead of the source module. The prebuilt
// will be used if it is marked "prefer" or if the source module is disabled.
-func (p *Prebuilt) usePrebuilt(ctx TopDownMutatorContext, source Module, prebuilt Module) bool {
+func (p *Prebuilt) usePrebuilt(ctx BaseMutatorContext, source Module, prebuilt Module) bool {
+ // Use `all_apex_contributions` for source vs prebuilt selection.
+ psi := PrebuiltSelectionInfoMap{}
+ ctx.VisitDirectDepsWithTag(PrebuiltDepTag, func(am Module) {
+ psi, _ = OtherModuleProvider(ctx, am, PrebuiltSelectionInfoProvider)
+ })
+
+ // If the source module is explicitly listed in the metadata module, use that
+ if source != nil && isSelected(psi, source) {
+ return false
+ }
+ // If the prebuilt module is explicitly listed in the metadata module, use that
+ if isSelected(psi, prebuilt) {
+ return true
+ }
+
+ // If the baseModuleName could not be found in the metadata module,
+ // fall back to the existing source vs prebuilt selection.
+ // TODO: Drop the fallback mechanisms
+
if p.srcsSupplier != nil && len(p.srcsSupplier(ctx, prebuilt)) == 0 {
return false
}
diff --git a/android/prebuilt_build_tool.go b/android/prebuilt_build_tool.go
index aeae20f..17b3230 100644
--- a/android/prebuilt_build_tool.go
+++ b/android/prebuilt_build_tool.go
@@ -17,7 +17,7 @@
import "path/filepath"
func init() {
- RegisterModuleType("prebuilt_build_tool", prebuiltBuildToolFactory)
+ RegisterModuleType("prebuilt_build_tool", NewPrebuiltBuildTool)
}
type prebuiltBuildToolProperties struct {
@@ -101,10 +101,6 @@
// prebuilt_build_tool is to declare prebuilts to be used during the build, particularly for use
// in genrules with the "tools" property.
-func prebuiltBuildToolFactory() Module {
- return NewPrebuiltBuildTool()
-}
-
func NewPrebuiltBuildTool() Module {
module := &prebuiltBuildTool{}
module.AddProperties(&module.properties)
diff --git a/android/prebuilt_test.go b/android/prebuilt_test.go
index fc47cfd..4a69628 100644
--- a/android/prebuilt_test.go
+++ b/android/prebuilt_test.go
@@ -335,6 +335,78 @@
prebuilt: []OsType{Android, buildOS},
},
{
+ name: "apex_contributions supersedes any source preferred via use_source_config_var",
+ modules: `
+ source {
+ name: "bar",
+ }
+
+ prebuilt {
+ name: "bar",
+ use_source_config_var: {config_namespace: "acme", var_name: "use_source"},
+ srcs: ["prebuilt_file"],
+ }
+ apex_contributions {
+ name: "my_mainline_module_contribution",
+ api_domain: "apexfoo",
+ // this metadata module contains prebuilt
+ contents: ["prebuilt_bar"],
+ }
+ all_apex_contributions {
+ name: "all_apex_contributions",
+ }
+ `,
+ preparer: FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+ variables.VendorVars = map[string]map[string]string{
+ "acme": {
+ "use_source": "true",
+ },
+ }
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contribution",
+ }
+ }),
+ // use_source_config_var indicates that source should be used
+ // but this is superseded by `my_mainline_module_contribution`
+ prebuilt: []OsType{Android, buildOS},
+ },
+ {
+ name: "apex_contributions supersedes any prebuilt preferred via use_source_config_var",
+ modules: `
+ source {
+ name: "bar",
+ }
+
+ prebuilt {
+ name: "bar",
+ use_source_config_var: {config_namespace: "acme", var_name: "use_source"},
+ srcs: ["prebuilt_file"],
+ }
+ apex_contributions {
+ name: "my_mainline_module_contribution",
+ api_domain: "apexfoo",
+ // this metadata module contains source
+ contents: ["bar"],
+ }
+ all_apex_contributions {
+ name: "all_apex_contributions",
+ }
+ `,
+ preparer: FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+ variables.VendorVars = map[string]map[string]string{
+ "acme": {
+ "use_source": "false",
+ },
+ }
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contribution",
+ }
+ }),
+ // use_source_config_var indicates that prebuilt should be used
+ // but this is superseded by `my_mainline_module_contribution`
+ prebuilt: nil,
+ },
+ {
name: "prebuilt use_source_config_var={acme, use_source} - acme_use_source=true",
modules: `
source {
@@ -497,7 +569,7 @@
}
}
-func testPrebuiltError(t *testing.T, expectedError, bp string) {
+func testPrebuiltErrorWithFixture(t *testing.T, expectedError, bp string, fixture FixturePreparer) {
t.Helper()
fs := MockFS{
"prebuilt_file": nil,
@@ -508,9 +580,15 @@
PrepareForTestWithOverrides,
fs.AddToFixture(),
FixtureRegisterWithContext(registerTestPrebuiltModules),
+ OptionalFixturePreparer(fixture),
).
ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern(expectedError)).
RunTestWithBp(t, bp)
+
+}
+
+func testPrebuiltError(t *testing.T, expectedError, bp string) {
+ testPrebuiltErrorWithFixture(t, expectedError, bp, nil)
}
func TestPrebuiltShouldNotChangePartition(t *testing.T) {
@@ -559,6 +637,7 @@
ctx.RegisterModuleType("soong_config_module_type", SoongConfigModuleTypeFactory)
ctx.RegisterModuleType("soong_config_string_variable", SoongConfigStringVariableDummyFactory)
ctx.RegisterModuleType("soong_config_bool_variable", SoongConfigBoolVariableDummyFactory)
+ RegisterApexContributionsBuildComponents(ctx)
}
type prebuiltModule struct {
@@ -653,3 +732,33 @@
InitOverrideModule(m)
return m
}
+
+func TestPrebuiltErrorCannotListBothSourceAndPrebuiltInContributions(t *testing.T) {
+ selectMainlineModuleContritbutions := GroupFixturePreparers(
+ FixtureModifyProductVariables(func(variables FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_apex_contributions",
+ }
+ }),
+ )
+ testPrebuiltErrorWithFixture(t, `Found duplicate variations of the same module in apex_contributions: foo and prebuilt_foo. Please remove one of these`, `
+ source {
+ name: "foo",
+ }
+ prebuilt {
+ name: "foo",
+ srcs: ["prebuilt_file"],
+ }
+ apex_contributions {
+ name: "my_apex_contributions",
+ api_domain: "my_mainline_module",
+ contents: [
+ "foo",
+ "prebuilt_foo",
+ ],
+ }
+ all_apex_contributions {
+ name: "all_apex_contributions",
+ }
+ `, selectMainlineModuleContritbutions)
+}
diff --git a/android/proto.go b/android/proto.go
index fc21d01..0d8e097 100644
--- a/android/proto.go
+++ b/android/proto.go
@@ -15,11 +15,7 @@
package android
import (
- "path/filepath"
"strings"
- "sync"
-
- "android/soong/bazel"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -154,278 +150,3 @@
rule.Command().
BuiltTool("dep_fixer").Flag(depFile.String())
}
-
-// Bp2buildProtoInfo contains information necessary to pass on to language specific conversion.
-type Bp2buildProtoInfo struct {
- Type *string
- Proto_libs bazel.LabelList
- Transitive_proto_libs bazel.LabelList
-}
-
-type ProtoAttrs struct {
- Srcs bazel.LabelListAttribute
- Import_prefix *string
- Strip_import_prefix *string
- Deps bazel.LabelListAttribute
-}
-
-// For each package in the include_dirs property a proto_library target should
-// be added to the BUILD file in that package and a mapping should be added here
-var includeDirsToProtoDeps = map[string]string{
- "external/protobuf/src": "//external/protobuf:libprotobuf-proto",
-}
-
-// Partitions srcs by the pkg it is in
-// srcs has been created using `TransformSubpackagePaths`
-// This function uses existence of Android.bp/BUILD files to create a label that is compatible with the package structure of bp2build workspace
-func partitionSrcsByPackage(currentDir string, srcs bazel.LabelList) map[string]bazel.LabelList {
- getPackageFromLabel := func(label string) string {
- // Remove any preceding //
- label = strings.TrimPrefix(label, "//")
- split := strings.Split(label, ":")
- if len(split) == 1 {
- // e.g. foo.proto
- return currentDir
- } else if split[0] == "" {
- // e.g. :foo.proto
- return currentDir
- } else {
- return split[0]
- }
- }
-
- pkgToSrcs := map[string]bazel.LabelList{}
- for _, src := range srcs.Includes {
- pkg := getPackageFromLabel(src.Label)
- list := pkgToSrcs[pkg]
- list.Add(&src)
- pkgToSrcs[pkg] = list
- }
- return pkgToSrcs
-}
-
-// Bp2buildProtoProperties converts proto properties, creating a proto_library and returning the
-// information necessary for language-specific handling.
-func Bp2buildProtoProperties(ctx Bp2buildMutatorContext, m *ModuleBase, srcs bazel.LabelListAttribute) (Bp2buildProtoInfo, bool) {
- var info Bp2buildProtoInfo
- if srcs.IsEmpty() {
- return info, false
- }
-
- var protoLibraries bazel.LabelList
- var transitiveProtoLibraries bazel.LabelList
- var directProtoSrcs bazel.LabelList
-
- // For filegroups that should be converted to proto_library just collect the
- // labels of converted proto_library targets.
- for _, protoSrc := range srcs.Value.Includes {
- src := protoSrc.OriginalModuleName
- if fg, ok := ToFileGroupAsLibrary(ctx, src); ok &&
- fg.ShouldConvertToProtoLibrary(ctx) {
- protoLibraries.Add(&bazel.Label{
- Label: fg.GetProtoLibraryLabel(ctx),
- })
- } else {
- directProtoSrcs.Add(&protoSrc)
- }
- }
-
- name := m.Name() + "_proto"
-
- depsFromFilegroup := protoLibraries
- var canonicalPathFromRoot bool
-
- if len(directProtoSrcs.Includes) > 0 {
- pkgToSrcs := partitionSrcsByPackage(ctx.ModuleDir(), directProtoSrcs)
- protoIncludeDirs := []string{}
- for _, pkg := range SortedStringKeys(pkgToSrcs) {
- srcs := pkgToSrcs[pkg]
- attrs := ProtoAttrs{
- Srcs: bazel.MakeLabelListAttribute(srcs),
- }
- attrs.Deps.Append(bazel.MakeLabelListAttribute(depsFromFilegroup))
-
- for axis, configToProps := range m.GetArchVariantProperties(ctx, &ProtoProperties{}) {
- for _, rawProps := range configToProps {
- var props *ProtoProperties
- var ok bool
- if props, ok = rawProps.(*ProtoProperties); !ok {
- ctx.ModuleErrorf("Could not cast ProtoProperties to expected type")
- }
- if axis == bazel.NoConfigAxis {
- info.Type = props.Proto.Type
-
- canonicalPathFromRoot = proptools.BoolDefault(props.Proto.Canonical_path_from_root, canonicalPathFromRootDefault)
- if !canonicalPathFromRoot {
- // an empty string indicates to strips the package path
- path := ""
- attrs.Strip_import_prefix = &path
- }
-
- for _, dir := range props.Proto.Include_dirs {
- if dep, ok := includeDirsToProtoDeps[dir]; ok {
- attrs.Deps.Add(bazel.MakeLabelAttribute(dep))
- } else {
- protoIncludeDirs = append(protoIncludeDirs, dir)
- }
- }
-
- // proto.local_include_dirs are similar to proto.include_dirs, except that it is relative to the module directory
- for _, dir := range props.Proto.Local_include_dirs {
- relativeToTop := pathForModuleSrc(ctx, dir).String()
- protoIncludeDirs = append(protoIncludeDirs, relativeToTop)
- }
-
- } else if props.Proto.Type != info.Type && props.Proto.Type != nil {
- ctx.ModuleErrorf("Cannot handle arch-variant types for protos at this time.")
- }
- }
- }
-
- if p, ok := m.module.(PkgPathInterface); ok && p.PkgPath(ctx) != nil {
- // python_library with pkg_path
- // proto_library for this module should have the pkg_path as the import_prefix
- attrs.Import_prefix = p.PkgPath(ctx)
- attrs.Strip_import_prefix = proptools.StringPtr("")
- }
-
- tags := ApexAvailableTagsWithoutTestApexes(ctx.(TopDownMutatorContext), ctx.Module())
-
- moduleDir := ctx.ModuleDir()
- if !canonicalPathFromRoot {
- // Since we are creating the proto_library in a subpackage, set the import_prefix relative to the current package
- if rel, err := filepath.Rel(moduleDir, pkg); err != nil {
- ctx.ModuleErrorf("Could not get relative path for %v %v", pkg, err)
- } else if rel != "." {
- attrs.Import_prefix = &rel
- }
- }
-
- // TODO - b/246997908: Handle potential orphaned proto_library targets
- // To create proto_library targets in the same package, we split the .proto files
- // This means that if a proto_library in a subpackage imports another proto_library from the parent package
- // (or a different subpackage), it will not find it.
- // The CcProtoGen action itself runs fine because we construct the correct ProtoInfo,
- // but the FileDescriptorSet of each proto_library might not be compile-able
- //
- // Add manual tag if either
- // 1. .proto files are in more than one package
- // 2. proto.include_dirs is not empty
- if len(SortedStringKeys(pkgToSrcs)) > 1 || len(protoIncludeDirs) > 0 {
- tags.Append(bazel.MakeStringListAttribute([]string{"manual"}))
- }
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
- CommonAttributes{Name: name, Dir: proptools.StringPtr(pkg), Tags: tags},
- &attrs,
- )
-
- l := ""
- if pkg == moduleDir { // same package that the original module lives in
- l = ":" + name
- } else {
- l = "//" + pkg + ":" + name
- }
- protoLibraries.Add(&bazel.Label{
- Label: l,
- })
- }
- // Partitioning by packages can create dupes of protoIncludeDirs, so dedupe it first.
- protoLibrariesInIncludeDir := createProtoLibraryTargetsForIncludeDirs(ctx, SortedUniqueStrings(protoIncludeDirs))
- transitiveProtoLibraries.Append(protoLibrariesInIncludeDir)
- }
-
- info.Proto_libs = protoLibraries
- info.Transitive_proto_libs = transitiveProtoLibraries
-
- return info, true
-}
-
-// PkgPathInterface is used as a type assertion in bp2build to get pkg_path property of python_library_host
-type PkgPathInterface interface {
- PkgPath(ctx BazelConversionContext) *string
-}
-
-var (
- protoIncludeDirGeneratedSuffix = ".include_dir_bp2build_generated_proto"
- protoIncludeDirsBp2buildKey = NewOnceKey("protoIncludeDirsBp2build")
-)
-
-func getProtoIncludeDirsBp2build(config Config) *sync.Map {
- return config.Once(protoIncludeDirsBp2buildKey, func() interface{} {
- return &sync.Map{}
- }).(*sync.Map)
-}
-
-// key for dynamically creating proto_library per proto.include_dirs
-type protoIncludeDirKey struct {
- dir string
- subpackgeInDir string
-}
-
-// createProtoLibraryTargetsForIncludeDirs creates additional proto_library targets for .proto files in includeDirs
-// Since Bazel imposes a constratint that the proto_library must be in the same package as the .proto file, this function
-// might create the targets in a subdirectory of `includeDir`
-// Returns the labels of the proto_library targets
-func createProtoLibraryTargetsForIncludeDirs(ctx Bp2buildMutatorContext, includeDirs []string) bazel.LabelList {
- var ret bazel.LabelList
- for _, dir := range includeDirs {
- if exists, _, _ := ctx.Config().fs.Exists(filepath.Join(dir, "Android.bp")); !exists {
- ctx.ModuleErrorf("TODO: Add support for proto.include_dir: %v. This directory does not contain an Android.bp file", dir)
- }
- dirMap := getProtoIncludeDirsBp2build(ctx.Config())
- // Find all proto file targets in this dir
- protoLabelsInDir := BazelLabelForSrcPatternExcludes(ctx, dir, "**/*.proto", []string{})
- // Partition the labels by package and subpackage(s)
- protoLabelelsPartitionedByPkg := partitionSrcsByPackage(dir, protoLabelsInDir)
- for _, pkg := range SortedStringKeys(protoLabelelsPartitionedByPkg) {
- label := strings.ReplaceAll(dir, "/", ".") + protoIncludeDirGeneratedSuffix
- ret.Add(&bazel.Label{
- Label: "//" + pkg + ":" + label,
- })
- key := protoIncludeDirKey{dir: dir, subpackgeInDir: pkg}
- if _, exists := dirMap.LoadOrStore(key, true); exists {
- // A proto_library has already been created for this package relative to this include dir
- continue
- }
- srcs := protoLabelelsPartitionedByPkg[pkg]
- rel, err := filepath.Rel(dir, pkg)
- if err != nil {
- ctx.ModuleErrorf("Could not create a proto_library in pkg %v due to %v\n", pkg, err)
- }
- // Create proto_library
- attrs := ProtoAttrs{
- Srcs: bazel.MakeLabelListAttribute(srcs),
- Strip_import_prefix: proptools.StringPtr(""),
- }
- if rel != "." {
- attrs.Import_prefix = proptools.StringPtr(rel)
- }
-
- // If a specific directory is listed in proto.include_dirs of two separate modules (one host-specific and another device-specific),
- // we do not want to create the proto_library with target_compatible_with of the first visited of these two modules
- // As a workarounds, delete `target_compatible_with`
- alwaysEnabled := bazel.BoolAttribute{}
- alwaysEnabled.Value = proptools.BoolPtr(true)
- // Add android and linux explicitly so that fillcommonbp2buildmoduleattrs can override these configs
- // When we extend b support for other os'es (darwin/windows), we should add those configs here as well
- alwaysEnabled.SetSelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid, proptools.BoolPtr(true))
- alwaysEnabled.SetSelectValue(bazel.OsConfigurationAxis, bazel.OsLinux, proptools.BoolPtr(true))
-
- ctx.CreateBazelTargetModuleWithRestrictions(
- bazel.BazelTargetModuleProperties{Rule_class: "proto_library"},
- CommonAttributes{
- Name: label,
- Dir: proptools.StringPtr(pkg),
- // This proto_library is used to construct a ProtoInfo
- // But it might not be buildable on its own
- Tags: bazel.MakeStringListAttribute([]string{"manual"}),
- },
- &attrs,
- alwaysEnabled,
- )
- }
- }
- return ret
-}
diff --git a/android/provider.go b/android/provider.go
new file mode 100644
index 0000000..3b9c5d2
--- /dev/null
+++ b/android/provider.go
@@ -0,0 +1,120 @@
+package android
+
+import (
+ "github.com/google/blueprint"
+)
+
+// OtherModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
+// TopDownMutatorContext for use in OtherModuleProvider.
+type OtherModuleProviderContext interface {
+ otherModuleProvider(m blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
+}
+
+var _ OtherModuleProviderContext = BaseModuleContext(nil)
+var _ OtherModuleProviderContext = ModuleContext(nil)
+var _ OtherModuleProviderContext = BottomUpMutatorContext(nil)
+var _ OtherModuleProviderContext = TopDownMutatorContext(nil)
+
+// OtherModuleProvider reads the provider for the given module. If the provider has been set the value is
+// returned and the boolean is true. If it has not been set the zero value of the provider's type is returned
+// and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider.
+//
+// OtherModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
+// TopDownMutatorContext.
+func OtherModuleProvider[K any](ctx OtherModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) (K, bool) {
+ value, ok := ctx.otherModuleProvider(module, provider)
+ if !ok {
+ var k K
+ return k, false
+ }
+ return value.(K), ok
+}
+
+// ModuleProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
+// TopDownMutatorContext for use in ModuleProvider.
+type ModuleProviderContext interface {
+ provider(provider blueprint.AnyProviderKey) (any, bool)
+}
+
+var _ ModuleProviderContext = BaseModuleContext(nil)
+var _ ModuleProviderContext = ModuleContext(nil)
+var _ ModuleProviderContext = BottomUpMutatorContext(nil)
+var _ ModuleProviderContext = TopDownMutatorContext(nil)
+
+// ModuleProvider reads the provider for the current module. If the provider has been set the value is
+// returned and the boolean is true. If it has not been set the zero value of the provider's type is returned
+// and the boolean is false. The value returned may be a deep copy of the value originally passed to SetProvider.
+//
+// ModuleProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
+// TopDownMutatorContext.
+func ModuleProvider[K any](ctx ModuleProviderContext, provider blueprint.ProviderKey[K]) (K, bool) {
+ value, ok := ctx.provider(provider)
+ if !ok {
+ var k K
+ return k, false
+ }
+ return value.(K), ok
+}
+
+type SingletonModuleProviderContext interface {
+ moduleProvider(blueprint.Module, blueprint.AnyProviderKey) (any, bool)
+}
+
+var _ SingletonModuleProviderContext = SingletonContext(nil)
+var _ SingletonModuleProviderContext = (*TestContext)(nil)
+
+// SingletonModuleProvider wraps blueprint.SingletonModuleProvider to provide a type-safe method to retrieve the value
+// of the given provider from a module using a SingletonContext. If the provider has not been set the first return
+// value will be the zero value of the provider's type, and the second return value will be false. If the provider has
+// been set the second return value will be true.
+func SingletonModuleProvider[K any](ctx SingletonModuleProviderContext, module blueprint.Module, provider blueprint.ProviderKey[K]) (K, bool) {
+ value, ok := ctx.moduleProvider(module, provider)
+ if !ok {
+ var k K
+ return k, false
+ }
+ return value.(K), ok
+}
+
+// SetProviderContext is a helper interface that is a subset of ModuleContext, BottomUpMutatorContext, or
+// TopDownMutatorContext for use in SetProvider.
+type SetProviderContext interface {
+ setProvider(provider blueprint.AnyProviderKey, value any)
+}
+
+var _ SetProviderContext = BaseModuleContext(nil)
+var _ SetProviderContext = ModuleContext(nil)
+var _ SetProviderContext = BottomUpMutatorContext(nil)
+var _ SetProviderContext = TopDownMutatorContext(nil)
+
+// SetProvider sets the value for a provider for the current module. It panics if not called
+// during the appropriate mutator or GenerateBuildActions pass for the provider, if the value
+// is not of the appropriate type, or if the value has already been set. The value should not
+// be modified after being passed to SetProvider.
+//
+// SetProviderContext is a helper interface that accepts ModuleContext, BottomUpMutatorContext, or
+// TopDownMutatorContext.
+func SetProvider[K any](ctx SetProviderContext, provider blueprint.ProviderKey[K], value K) {
+ ctx.setProvider(provider, value)
+}
+
+var _ OtherModuleProviderContext = (*otherModuleProviderAdaptor)(nil)
+
+// An OtherModuleProviderFunc can be passed to NewOtherModuleProviderAdaptor to create an OtherModuleProviderContext
+// for use in tests.
+type OtherModuleProviderFunc func(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
+
+type otherModuleProviderAdaptor struct {
+ otherModuleProviderFunc OtherModuleProviderFunc
+}
+
+func (p *otherModuleProviderAdaptor) otherModuleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
+ return p.otherModuleProviderFunc(module, provider)
+}
+
+// NewOtherModuleProviderAdaptor returns an OtherModuleProviderContext that proxies calls to otherModuleProvider to
+// the provided OtherModuleProviderFunc. It can be used in tests to unit test methods that need to call
+// android.OtherModuleProvider.
+func NewOtherModuleProviderAdaptor(otherModuleProviderFunc OtherModuleProviderFunc) OtherModuleProviderContext {
+ return &otherModuleProviderAdaptor{otherModuleProviderFunc}
+}
diff --git a/android/raw_files.go b/android/raw_files.go
new file mode 100644
index 0000000..9d7f5e8
--- /dev/null
+++ b/android/raw_files.go
@@ -0,0 +1,279 @@
+// Copyright 2023 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 android
+
+import (
+ "crypto/sha1"
+ "encoding/hex"
+ "fmt"
+ "github.com/google/blueprint"
+ "io"
+ "io/fs"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/google/blueprint/proptools"
+)
+
+// WriteFileRule creates a ninja rule to write contents to a file by immediately writing the
+// contents, plus a trailing newline, to a file in out/soong/raw-${TARGET_PRODUCT}, and then creating
+// a ninja rule to copy the file into place.
+func WriteFileRule(ctx BuilderContext, outputFile WritablePath, content string) {
+ writeFileRule(ctx, outputFile, content, true, false)
+}
+
+// WriteFileRuleVerbatim creates a ninja rule to write contents to a file by immediately writing the
+// contents to a file in out/soong/raw-${TARGET_PRODUCT}, and then creating a ninja rule to copy the file into place.
+func WriteFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string) {
+ writeFileRule(ctx, outputFile, content, false, false)
+}
+
+// WriteExecutableFileRuleVerbatim is the same as WriteFileRuleVerbatim, but runs chmod +x on the result
+func WriteExecutableFileRuleVerbatim(ctx BuilderContext, outputFile WritablePath, content string) {
+ writeFileRule(ctx, outputFile, content, false, true)
+}
+
+// tempFile provides a testable wrapper around a file in out/soong/.temp. It writes to a temporary file when
+// not in tests, but writes to a buffer in memory when used in tests.
+type tempFile struct {
+ // tempFile contains wraps an io.Writer, which will be file if testMode is false, or testBuf if it is true.
+ io.Writer
+
+ file *os.File
+ testBuf *strings.Builder
+}
+
+func newTempFile(ctx BuilderContext, pattern string, testMode bool) *tempFile {
+ if testMode {
+ testBuf := &strings.Builder{}
+ return &tempFile{
+ Writer: testBuf,
+ testBuf: testBuf,
+ }
+ } else {
+ f, err := os.CreateTemp(absolutePath(ctx.Config().tempDir()), pattern)
+ if err != nil {
+ panic(fmt.Errorf("failed to open temporary raw file: %w", err))
+ }
+ return &tempFile{
+ Writer: f,
+ file: f,
+ }
+ }
+}
+
+func (t *tempFile) close() error {
+ if t.file != nil {
+ return t.file.Close()
+ }
+ return nil
+}
+
+func (t *tempFile) name() string {
+ if t.file != nil {
+ return t.file.Name()
+ }
+ return "temp_file_in_test"
+}
+
+func (t *tempFile) rename(to string) {
+ if t.file != nil {
+ os.MkdirAll(filepath.Dir(to), 0777)
+ err := os.Rename(t.file.Name(), to)
+ if err != nil {
+ panic(fmt.Errorf("failed to rename %s to %s: %w", t.file.Name(), to, err))
+ }
+ }
+}
+
+func (t *tempFile) remove() error {
+ if t.file != nil {
+ return os.Remove(t.file.Name())
+ }
+ return nil
+}
+
+func writeContentToTempFileAndHash(ctx BuilderContext, content string, newline bool) (*tempFile, string) {
+ tempFile := newTempFile(ctx, "raw", ctx.Config().captureBuild)
+ defer tempFile.close()
+
+ hash := sha1.New()
+ w := io.MultiWriter(tempFile, hash)
+
+ _, err := io.WriteString(w, content)
+ if err == nil && newline {
+ _, err = io.WriteString(w, "\n")
+ }
+ if err != nil {
+ panic(fmt.Errorf("failed to write to temporary raw file %s: %w", tempFile.name(), err))
+ }
+ return tempFile, hex.EncodeToString(hash.Sum(nil))
+}
+
+func writeFileRule(ctx BuilderContext, outputFile WritablePath, content string, newline bool, executable bool) {
+ // Write the contents to a temporary file while computing its hash.
+ tempFile, hash := writeContentToTempFileAndHash(ctx, content, newline)
+
+ // Shard the final location of the raw file into a subdirectory based on the first two characters of the
+ // hash to avoid making the raw directory too large and slowing down accesses.
+ relPath := filepath.Join(hash[0:2], hash)
+
+ // These files are written during soong_build. If something outside the build deleted them there would be no
+ // trigger to rerun soong_build, and the build would break with dependencies on missing files. Writing them
+ // to their final locations would risk having them deleted when cleaning a module, and would also pollute the
+ // output directory with files for modules that have never been built.
+ // Instead, the files are written to a separate "raw" directory next to the build.ninja file, and a ninja
+ // rule is created to copy the files into their final location as needed.
+ // Obsolete files written by previous runs of soong_build must be cleaned up to avoid continually growing
+ // disk usage as the hashes of the files change over time. The cleanup must not remove files that were
+ // created by previous runs of soong_build for other products, as the build.ninja files for those products
+ // may still exist and still reference those files. The raw files from different products are kept
+ // separate by appending the Make_suffix to the directory name.
+ rawPath := PathForOutput(ctx, "raw"+proptools.String(ctx.Config().productVariables.Make_suffix), relPath)
+
+ rawFileInfo := rawFileInfo{
+ relPath: relPath,
+ }
+
+ if ctx.Config().captureBuild {
+ // When running tests tempFile won't write to disk, instead store the contents for later retrieval by
+ // ContentFromFileRuleForTests.
+ rawFileInfo.contentForTests = tempFile.testBuf.String()
+ }
+
+ rawFileSet := getRawFileSet(ctx.Config())
+ if _, exists := rawFileSet.LoadOrStore(hash, rawFileInfo); exists {
+ // If a raw file with this hash has already been created delete the temporary file.
+ tempFile.remove()
+ } else {
+ // If this is the first time this hash has been seen then move it from the temporary directory
+ // to the raw directory. If the file already exists in the raw directory assume it has the correct
+ // contents.
+ absRawPath := absolutePath(rawPath.String())
+ _, err := os.Stat(absRawPath)
+ if os.IsNotExist(err) {
+ tempFile.rename(absRawPath)
+ } else if err != nil {
+ panic(fmt.Errorf("failed to stat %q: %w", absRawPath, err))
+ } else {
+ tempFile.remove()
+ }
+ }
+
+ // Emit a rule to copy the file from raw directory to the final requested location in the output tree.
+ // Restat is used to ensure that two different products that produce identical files copied from their
+ // own raw directories they don't cause everything downstream to rebuild.
+ rule := rawFileCopy
+ if executable {
+ rule = rawFileCopyExecutable
+ }
+ ctx.Build(pctx, BuildParams{
+ Rule: rule,
+ Input: rawPath,
+ Output: outputFile,
+ Description: "raw " + outputFile.Base(),
+ })
+}
+
+var (
+ rawFileCopy = pctx.AndroidStaticRule("rawFileCopy",
+ blueprint.RuleParams{
+ Command: "if ! cmp -s $in $out; then cp $in $out; fi",
+ Description: "copy raw file $out",
+ Restat: true,
+ })
+ rawFileCopyExecutable = pctx.AndroidStaticRule("rawFileCopyExecutable",
+ blueprint.RuleParams{
+ Command: "if ! cmp -s $in $out; then cp $in $out; fi && chmod +x $out",
+ Description: "copy raw exectuable file $out",
+ Restat: true,
+ })
+)
+
+type rawFileInfo struct {
+ relPath string
+ contentForTests string
+}
+
+var rawFileSetKey OnceKey = NewOnceKey("raw file set")
+
+func getRawFileSet(config Config) *SyncMap[string, rawFileInfo] {
+ return config.Once(rawFileSetKey, func() any {
+ return &SyncMap[string, rawFileInfo]{}
+ }).(*SyncMap[string, rawFileInfo])
+}
+
+// ContentFromFileRuleForTests returns the content that was passed to a WriteFileRule for use
+// in tests.
+func ContentFromFileRuleForTests(t *testing.T, ctx *TestContext, params TestingBuildParams) string {
+ t.Helper()
+ if params.Rule != rawFileCopy && params.Rule != rawFileCopyExecutable {
+ t.Errorf("expected params.Rule to be rawFileCopy or rawFileCopyExecutable, was %q", params.Rule)
+ return ""
+ }
+
+ key := filepath.Base(params.Input.String())
+ rawFileSet := getRawFileSet(ctx.Config())
+ rawFileInfo, _ := rawFileSet.Load(key)
+
+ return rawFileInfo.contentForTests
+}
+
+func rawFilesSingletonFactory() Singleton {
+ return &rawFilesSingleton{}
+}
+
+type rawFilesSingleton struct{}
+
+func (rawFilesSingleton) GenerateBuildActions(ctx SingletonContext) {
+ if ctx.Config().captureBuild {
+ // Nothing to do when running in tests, no temporary files were created.
+ return
+ }
+ rawFileSet := getRawFileSet(ctx.Config())
+ rawFilesDir := PathForOutput(ctx, "raw"+proptools.String(ctx.Config().productVariables.Make_suffix)).String()
+ absRawFilesDir := absolutePath(rawFilesDir)
+ err := filepath.WalkDir(absRawFilesDir, func(path string, d fs.DirEntry, err error) error {
+ if err != nil {
+ return err
+ }
+ if d.IsDir() {
+ // Ignore obsolete directories for now.
+ return nil
+ }
+
+ // Assume the basename of the file is a hash
+ key := filepath.Base(path)
+ relPath, err := filepath.Rel(absRawFilesDir, path)
+ if err != nil {
+ return err
+ }
+
+ // Check if a file with the same hash was written by this run of soong_build. If the file was not written,
+ // or if a file with the same hash was written but to a different path in the raw directory, then delete it.
+ // Checking that the path matches allows changing the structure of the raw directory, for example to increase
+ // the sharding.
+ rawFileInfo, written := rawFileSet.Load(key)
+ if !written || rawFileInfo.relPath != relPath {
+ os.Remove(path)
+ }
+ return nil
+ })
+ if err != nil {
+ panic(fmt.Errorf("failed to clean %q: %w", rawFilesDir, err))
+ }
+}
diff --git a/android/register.go b/android/register.go
index df97c75..d00c15f 100644
--- a/android/register.go
+++ b/android/register.go
@@ -16,9 +16,8 @@
import (
"fmt"
- "reflect"
-
"github.com/google/blueprint"
+ "reflect"
)
// A sortable component is one whose registration order affects the order in which it is executed
@@ -62,9 +61,6 @@
var moduleTypeByFactory = map[reflect.Value]string{}
type singleton struct {
- // True if this should be registered as a pre-singleton, false otherwise.
- pre bool
-
// True if this should be registered as a parallel singleton.
parallel bool
@@ -73,11 +69,7 @@
}
func newSingleton(name string, factory SingletonFactory, parallel bool) singleton {
- return singleton{pre: false, parallel: parallel, name: name, factory: factory}
-}
-
-func newPreSingleton(name string, factory SingletonFactory) singleton {
- return singleton{pre: true, parallel: false, name: name, factory: factory}
+ return singleton{parallel: parallel, name: name, factory: factory}
}
func (s singleton) componentName() string {
@@ -86,17 +78,12 @@
func (s singleton) register(ctx *Context) {
adaptor := SingletonFactoryAdaptor(ctx, s.factory)
- if s.pre {
- ctx.RegisterPreSingletonType(s.name, adaptor)
- } else {
- ctx.RegisterSingletonType(s.name, adaptor, s.parallel)
- }
+ ctx.RegisterSingletonType(s.name, adaptor, s.parallel)
}
var _ sortableComponent = singleton{}
var singletons sortableComponents
-var preSingletons sortableComponents
type mutator struct {
name string
@@ -160,10 +147,6 @@
registerSingletonType(name, factory, true)
}
-func RegisterPreSingletonType(name string, factory SingletonFactory) {
- preSingletons = append(preSingletons, newPreSingleton(name, factory))
-}
-
type Context struct {
*blueprint.Context
config Config
@@ -177,31 +160,9 @@
return ctx
}
-// Helper function to register the module types used in bp2build and
-// api_bp2build.
-func registerModuleTypes(ctx *Context) {
- for _, t := range moduleTypes {
- t.register(ctx)
- }
- // Required for SingletonModule types, even though we are not using them.
- for _, t := range singletons {
- t.register(ctx)
- }
-}
-
-// RegisterForBazelConversion registers an alternate shadow pipeline of
-// singletons, module types and mutators to register for converting Blueprint
-// files to semantically equivalent BUILD files.
-func (ctx *Context) RegisterForBazelConversion() {
- registerModuleTypes(ctx)
- RegisterMutatorsForBazelConversion(ctx, bp2buildPreArchMutators)
-}
-
// Register the pipeline of singletons, module types, and mutators for
// generating build.ninja and other files for Kati, from Android.bp files.
func (ctx *Context) Register() {
- preSingletons.registerAll(ctx)
-
for _, t := range moduleTypes {
t.register(ctx)
}
@@ -224,17 +185,16 @@
func collateGloballyRegisteredSingletons() sortableComponents {
allSingletons := append(sortableComponents(nil), singletons...)
allSingletons = append(allSingletons,
- singleton{pre: false, parallel: true, name: "bazeldeps", factory: BazelSingleton},
-
// Register phony just before makevars so it can write out its phony rules as Make rules
- singleton{pre: false, parallel: false, name: "phony", factory: phonySingletonFactory},
+ singleton{parallel: false, name: "phony", factory: phonySingletonFactory},
// Register makevars after other singletons so they can export values through makevars
- singleton{pre: false, parallel: false, name: "makevars", factory: makeVarsSingletonFunc},
+ singleton{parallel: false, name: "makevars", factory: makeVarsSingletonFunc},
- // Register env and ninjadeps last so that they can track all used environment variables and
+ // Register rawfiles and ninjadeps last so that they can track all used environment variables and
// Ninja file dependencies stored in the config.
- singleton{pre: false, parallel: false, name: "ninjadeps", factory: ninjaDepsSingletonFactory},
+ singleton{parallel: false, name: "rawfiles", factory: rawFilesSingletonFactory},
+ singleton{parallel: false, name: "ninjadeps", factory: ninjaDepsSingletonFactory},
)
return allSingletons
@@ -264,7 +224,6 @@
RegisterModuleType(name string, factory ModuleFactory)
RegisterSingletonModuleType(name string, factory SingletonModuleFactory)
RegisterParallelSingletonModuleType(name string, factory SingletonModuleFactory)
- RegisterPreSingletonType(name string, factory SingletonFactory)
RegisterParallelSingletonType(name string, factory SingletonFactory)
RegisterSingletonType(name string, factory SingletonFactory)
PreArchMutators(f RegisterMutatorFunc)
@@ -296,9 +255,8 @@
// ctx := android.NewTestContext(config)
// RegisterBuildComponents(ctx)
var InitRegistrationContext RegistrationContext = &initRegistrationContext{
- moduleTypes: make(map[string]ModuleFactory),
- singletonTypes: make(map[string]SingletonFactory),
- preSingletonTypes: make(map[string]SingletonFactory),
+ moduleTypes: make(map[string]ModuleFactory),
+ singletonTypes: make(map[string]SingletonFactory),
}
// Make sure the TestContext implements RegistrationContext.
@@ -307,7 +265,6 @@
type initRegistrationContext struct {
moduleTypes map[string]ModuleFactory
singletonTypes map[string]SingletonFactory
- preSingletonTypes map[string]SingletonFactory
moduleTypesForDocs map[string]reflect.Value
}
@@ -353,14 +310,6 @@
ctx.registerSingletonType(name, factory, true)
}
-func (ctx *initRegistrationContext) RegisterPreSingletonType(name string, factory SingletonFactory) {
- if _, present := ctx.preSingletonTypes[name]; present {
- panic(fmt.Sprintf("pre singleton type %q is already registered", name))
- }
- ctx.preSingletonTypes[name] = factory
- RegisterPreSingletonType(name, factory)
-}
-
func (ctx *initRegistrationContext) PreArchMutators(f RegisterMutatorFunc) {
PreArchMutators(f)
}
diff --git a/android/rule_builder.go b/android/rule_builder.go
index 777c1cf..e8dbd48 100644
--- a/android/rule_builder.go
+++ b/android/rule_builder.go
@@ -336,41 +336,6 @@
return outputList
}
-func (r *RuleBuilder) symlinkOutputSet() map[string]WritablePath {
- symlinkOutputs := make(map[string]WritablePath)
- for _, c := range r.commands {
- for _, symlinkOutput := range c.symlinkOutputs {
- symlinkOutputs[symlinkOutput.String()] = symlinkOutput
- }
- }
- return symlinkOutputs
-}
-
-// SymlinkOutputs returns the list of paths that the executor (Ninja) would
-// verify, after build edge completion, that:
-//
-// 1) Created output symlinks match the list of paths in this list exactly (no more, no fewer)
-// 2) Created output files are *not* declared in this list.
-//
-// These symlink outputs are expected to be a subset of outputs or implicit
-// outputs, or they would fail validation at build param construction time
-// later, to support other non-rule-builder approaches for constructing
-// statements.
-func (r *RuleBuilder) SymlinkOutputs() WritablePaths {
- symlinkOutputs := r.symlinkOutputSet()
-
- var symlinkOutputList WritablePaths
- for _, symlinkOutput := range symlinkOutputs {
- symlinkOutputList = append(symlinkOutputList, symlinkOutput)
- }
-
- sort.Slice(symlinkOutputList, func(i, j int) bool {
- return symlinkOutputList[i].String() < symlinkOutputList[j].String()
- })
-
- return symlinkOutputList
-}
-
func (r *RuleBuilder) depFileSet() map[string]WritablePath {
depFiles := make(map[string]WritablePath)
for _, c := range r.commands {
@@ -474,13 +439,23 @@
Inputs(depFiles.Paths())
}
+// BuildWithNinjaVars adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for
+// Outputs. This function will not escape Ninja variables, so it may be used to write sandbox manifests using Ninja variables.
+func (r *RuleBuilder) BuildWithUnescapedNinjaVars(name string, desc string) {
+ r.build(name, desc, false)
+}
+
// Build adds the built command line to the build graph, with dependencies on Inputs and Tools, and output files for
// Outputs.
func (r *RuleBuilder) Build(name string, desc string) {
+ r.build(name, desc, true)
+}
+
+func (r *RuleBuilder) build(name string, desc string, ninjaEscapeCommandString bool) {
name = ninjaNameEscape(name)
if len(r.missingDeps) > 0 {
- r.ctx.Build(pctx, BuildParams{
+ r.ctx.Build(r.pctx, BuildParams{
Rule: ErrorRule,
Outputs: r.Outputs(),
Description: desc,
@@ -580,7 +555,7 @@
To: proto.String(sboxOutSubDir),
},
{
- From: proto.String(PathForOutput(r.ctx).String()),
+ From: proto.String(r.ctx.Config().OutDir()),
To: proto.String(sboxOutSubDir),
},
},
@@ -619,12 +594,36 @@
name, r.sboxManifestPath.String(), r.outDir.String())
}
- // Create a rule to write the manifest as a the textproto.
- pbText, err := prototext.Marshal(&manifest)
+ // Create a rule to write the manifest as textproto. Pretty print it by indenting and
+ // splitting across multiple lines.
+ pbText, err := prototext.MarshalOptions{Indent: " "}.Marshal(&manifest)
if err != nil {
ReportPathErrorf(r.ctx, "sbox manifest failed to marshal: %q", err)
}
- WriteFileRule(r.ctx, r.sboxManifestPath, string(pbText))
+ if ninjaEscapeCommandString {
+ WriteFileRule(r.ctx, r.sboxManifestPath, string(pbText))
+ } else {
+ // We need to have a rule to write files that is
+ // defined on the RuleBuilder's pctx in order to
+ // write Ninja variables in the string.
+ // The WriteFileRule function above rule can only write
+ // raw strings because it is defined on the android
+ // package's pctx, and it can't access variables defined
+ // in another context.
+ r.ctx.Build(r.pctx, BuildParams{
+ Rule: r.ctx.Rule(r.pctx, "unescapedWriteFile", blueprint.RuleParams{
+ Command: `rm -rf ${out} && cat ${out}.rsp > ${out}`,
+ Rspfile: "${out}.rsp",
+ RspfileContent: "${content}",
+ Description: "write file",
+ }, "content"),
+ Output: r.sboxManifestPath,
+ Description: "write sbox manifest " + r.sboxManifestPath.Base(),
+ Args: map[string]string{
+ "content": string(pbText),
+ },
+ })
+ }
// Generate a new string to use as the command line of the sbox rule. This uses
// a RuleBuilderCommand as a convenience method of building the command line, then
@@ -723,9 +722,13 @@
pool = localPool
}
+ if ninjaEscapeCommandString {
+ commandString = proptools.NinjaEscape(commandString)
+ }
+
r.ctx.Build(r.pctx, BuildParams{
- Rule: r.ctx.Rule(pctx, name, blueprint.RuleParams{
- Command: proptools.NinjaEscape(commandString),
+ Rule: r.ctx.Rule(r.pctx, name, blueprint.RuleParams{
+ Command: commandString,
CommandDeps: proptools.NinjaEscapeList(tools.Strings()),
Restat: r.restat,
Rspfile: proptools.NinjaEscape(rspFile),
@@ -738,7 +741,6 @@
Validations: r.Validations(),
Output: output,
ImplicitOutputs: implicitOutputs,
- SymlinkOutputs: r.SymlinkOutputs(),
Depfile: depFile,
Deps: depFormat,
Description: desc,
@@ -752,17 +754,16 @@
type RuleBuilderCommand struct {
rule *RuleBuilder
- buf strings.Builder
- inputs Paths
- implicits Paths
- orderOnlys Paths
- validations Paths
- outputs WritablePaths
- symlinkOutputs WritablePaths
- depFiles WritablePaths
- tools Paths
- packagedTools []PackagingSpec
- rspFiles []rspFileAndPaths
+ buf strings.Builder
+ inputs Paths
+ implicits Paths
+ orderOnlys Paths
+ validations Paths
+ outputs WritablePaths
+ depFiles WritablePaths
+ tools Paths
+ packagedTools []PackagingSpec
+ rspFiles []rspFileAndPaths
}
type rspFileAndPaths struct {
@@ -834,7 +835,7 @@
func sboxPathForToolRel(ctx BuilderContext, path Path) string {
// Errors will be handled in RuleBuilder.Build where we have a context to report them
- toolDir := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "", false)
+ toolDir := pathForInstall(ctx, ctx.Config().BuildOS, ctx.Config().BuildArch, "")
relOutSoong, isRelOutSoong, _ := maybeRelErr(toolDir.String(), path.String())
if isRelOutSoong {
// The tool is in the Soong output directory, it will be copied to __SBOX_OUT_DIR__/tools/out
@@ -854,7 +855,7 @@
// When sandboxing inputs all inputs have to be copied into the sandbox. Input files that
// are outputs of other rules could be an arbitrary absolute path if OUT_DIR is set, so they
// will be copied to relative paths under __SBOX_OUT_DIR__/out.
- rel, isRelOut, _ := maybeRelErr(PathForOutput(r.ctx).String(), path.String())
+ rel, isRelOut, _ := maybeRelErr(r.ctx.Config().OutDir(), path.String())
if isRelOut {
return filepath.Join(sboxOutSubDir, rel), true
}
@@ -1186,42 +1187,6 @@
return c
}
-// ImplicitSymlinkOutput declares the specified path as an implicit output that
-// will be a symlink instead of a regular file. Does not modify the command
-// line.
-func (c *RuleBuilderCommand) ImplicitSymlinkOutput(path WritablePath) *RuleBuilderCommand {
- checkPathNotNil(path)
- c.symlinkOutputs = append(c.symlinkOutputs, path)
- return c.ImplicitOutput(path)
-}
-
-// ImplicitSymlinkOutputs declares the specified paths as implicit outputs that
-// will be a symlinks instead of regular files. Does not modify the command
-// line.
-func (c *RuleBuilderCommand) ImplicitSymlinkOutputs(paths WritablePaths) *RuleBuilderCommand {
- for _, path := range paths {
- c.ImplicitSymlinkOutput(path)
- }
- return c
-}
-
-// SymlinkOutput declares the specified path as an output that will be a symlink
-// instead of a regular file. Modifies the command line.
-func (c *RuleBuilderCommand) SymlinkOutput(path WritablePath) *RuleBuilderCommand {
- checkPathNotNil(path)
- c.symlinkOutputs = append(c.symlinkOutputs, path)
- return c.Output(path)
-}
-
-// SymlinkOutputsl declares the specified paths as outputs that will be symlinks
-// instead of regular files. Modifies the command line.
-func (c *RuleBuilderCommand) SymlinkOutputs(paths WritablePaths) *RuleBuilderCommand {
- for _, path := range paths {
- c.SymlinkOutput(path)
- }
- return c
-}
-
// ImplicitDepFile adds the specified depfile path to the paths returned by RuleBuilder.DepFiles without modifying
// the command line, and causes RuleBuilder.Build file to set the depfile flag for ninja. If multiple depfiles
// are added to commands in a single RuleBuilder then RuleBuilder.Build will add an extra command to merge the
@@ -1304,9 +1269,9 @@
// RuleBuilderSboxProtoForTests takes the BuildParams for the manifest passed to RuleBuilder.Sbox()
// and returns sbox testproto generated by the RuleBuilder.
-func RuleBuilderSboxProtoForTests(t *testing.T, params TestingBuildParams) *sbox_proto.Manifest {
+func RuleBuilderSboxProtoForTests(t *testing.T, ctx *TestContext, params TestingBuildParams) *sbox_proto.Manifest {
t.Helper()
- content := ContentFromFileRuleForTests(t, params)
+ content := ContentFromFileRuleForTests(t, ctx, params)
manifest := sbox_proto.Manifest{}
err := prototext.Unmarshal([]byte(content), &manifest)
if err != nil {
diff --git a/android/rule_builder_test.go b/android/rule_builder_test.go
index 86647eb..6a8a964 100644
--- a/android/rule_builder_test.go
+++ b/android/rule_builder_test.go
@@ -28,6 +28,17 @@
"android/soong/shared"
)
+var (
+ pctx_ruleBuilderTest = NewPackageContext("android/soong/rule_builder")
+ pctx_ruleBuilderTestSubContext = NewPackageContext("android/soong/rule_builder/config")
+)
+
+func init() {
+ pctx_ruleBuilderTest.Import("android/soong/rule_builder/config")
+ pctx_ruleBuilderTest.StaticVariable("cmdFlags", "${config.ConfigFlags}")
+ pctx_ruleBuilderTestSubContext.StaticVariable("ConfigFlags", "--some-clang-flag")
+}
+
func builderContext() BuilderContext {
return BuilderContextForTesting(TestConfig("out", nil, "", map[string][]byte{
"ld": nil,
@@ -37,7 +48,6 @@
"a": nil,
"b": nil,
"ls": nil,
- "ln": nil,
"turbine": nil,
"java": nil,
"javac": nil,
@@ -70,32 +80,6 @@
// outputs: ["out/soong/linked"]
}
-func ExampleRuleBuilder_SymlinkOutputs() {
- ctx := builderContext()
-
- rule := NewRuleBuilder(pctx, ctx)
-
- rule.Command().
- Tool(PathForSource(ctx, "ln")).
- FlagWithInput("-s ", PathForTesting("a.o")).
- SymlinkOutput(PathForOutput(ctx, "a"))
- rule.Command().Text("cp out/soong/a out/soong/b").
- ImplicitSymlinkOutput(PathForOutput(ctx, "b"))
-
- fmt.Printf("commands: %q\n", strings.Join(rule.Commands(), " && "))
- fmt.Printf("tools: %q\n", rule.Tools())
- fmt.Printf("inputs: %q\n", rule.Inputs())
- fmt.Printf("outputs: %q\n", rule.Outputs())
- fmt.Printf("symlink_outputs: %q\n", rule.SymlinkOutputs())
-
- // Output:
- // commands: "ln -s a.o out/soong/a && cp out/soong/a out/soong/b"
- // tools: ["ln"]
- // inputs: ["a.o"]
- // outputs: ["out/soong/a" "out/soong/b"]
- // symlink_outputs: ["out/soong/a" "out/soong/b"]
-}
-
func ExampleRuleBuilder_Temporary() {
ctx := builderContext()
@@ -323,8 +307,6 @@
Output(PathForOutput(ctx, "module/Output")).
OrderOnly(PathForSource(ctx, "OrderOnly")).
Validation(PathForSource(ctx, "Validation")).
- SymlinkOutput(PathForOutput(ctx, "module/SymlinkOutput")).
- ImplicitSymlinkOutput(PathForOutput(ctx, "module/ImplicitSymlinkOutput")).
Text("Text").
Tool(PathForSource(ctx, "Tool"))
@@ -356,15 +338,13 @@
wantRspFileInputs := Paths{PathForSource(ctx, "RspInput"),
PathForOutput(ctx, "other/RspOutput2")}
wantOutputs := PathsForOutput(ctx, []string{
- "module/ImplicitOutput", "module/ImplicitSymlinkOutput", "module/Output", "module/SymlinkOutput",
- "module/output", "module/output2", "module/output3"})
+ "module/ImplicitOutput", "module/Output", "module/output", "module/output2",
+ "module/output3"})
wantDepFiles := PathsForOutput(ctx, []string{
"module/DepFile", "module/depfile", "module/ImplicitDepFile", "module/depfile2"})
wantTools := PathsForSource(ctx, []string{"Tool", "tool2"})
wantOrderOnlys := PathsForSource(ctx, []string{"OrderOnly", "OrderOnlys"})
wantValidations := PathsForSource(ctx, []string{"Validation", "Validations"})
- wantSymlinkOutputs := PathsForOutput(ctx, []string{
- "module/ImplicitSymlinkOutput", "module/SymlinkOutput"})
t.Run("normal", func(t *testing.T) {
rule := NewRuleBuilder(pctx, ctx)
@@ -373,7 +353,7 @@
wantCommands := []string{
"out_local/soong/module/DepFile Flag FlagWithArg=arg FlagWithDepFile=out_local/soong/module/depfile " +
"FlagWithInput=input FlagWithOutput=out_local/soong/module/output FlagWithRspFileInputList=out_local/soong/rsp " +
- "Input out_local/soong/module/Output out_local/soong/module/SymlinkOutput Text Tool after command2 old cmd",
+ "Input out_local/soong/module/Output Text Tool after command2 old cmd",
"command2 out_local/soong/module/depfile2 input2 out_local/soong/module/output2 tool2",
"command3 input3 out_local/soong/module/output2 out_local/soong/module/output3 input3 out_local/soong/module/output2",
}
@@ -386,7 +366,6 @@
AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
- AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
@@ -404,7 +383,7 @@
"__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
"FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
"FlagWithRspFileInputList=out_local/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
- "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text Tool after command2 old cmd",
+ "Text Tool after command2 old cmd",
"command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 tool2",
"command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
}
@@ -416,7 +395,6 @@
AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
- AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
@@ -434,7 +412,7 @@
"__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
"FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
"FlagWithRspFileInputList=out_local/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
- "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
+ "Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
"command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/tools/src/tool2",
"command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
}
@@ -446,7 +424,6 @@
AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
- AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
@@ -463,8 +440,8 @@
wantCommands := []string{
"__SBOX_SANDBOX_DIR__/out/DepFile Flag FlagWithArg=arg FlagWithDepFile=__SBOX_SANDBOX_DIR__/out/depfile " +
"FlagWithInput=input FlagWithOutput=__SBOX_SANDBOX_DIR__/out/output " +
- "FlagWithRspFileInputList=__SBOX_SANDBOX_DIR__/out/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
- "__SBOX_SANDBOX_DIR__/out/SymlinkOutput Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
+ "FlagWithRspFileInputList=__SBOX_SANDBOX_DIR__/out/soong/rsp Input __SBOX_SANDBOX_DIR__/out/Output " +
+ "Text __SBOX_SANDBOX_DIR__/tools/src/Tool after command2 old cmd",
"command2 __SBOX_SANDBOX_DIR__/out/depfile2 input2 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/tools/src/tool2",
"command3 input3 __SBOX_SANDBOX_DIR__/out/output2 __SBOX_SANDBOX_DIR__/out/output3 input3 __SBOX_SANDBOX_DIR__/out/output2",
}
@@ -476,7 +453,6 @@
AssertDeepEquals(t, "rule.Inputs()", wantInputs, rule.Inputs())
AssertDeepEquals(t, "rule.RspfileInputs()", wantRspFileInputs, rule.RspFileInputs())
AssertDeepEquals(t, "rule.Outputs()", wantOutputs, rule.Outputs())
- AssertDeepEquals(t, "rule.SymlinkOutputs()", wantSymlinkOutputs, rule.SymlinkOutputs())
AssertDeepEquals(t, "rule.DepFiles()", wantDepFiles, rule.DepFiles())
AssertDeepEquals(t, "rule.Tools()", wantTools, rule.Tools())
AssertDeepEquals(t, "rule.OrderOnlys()", wantOrderOnlys, rule.OrderOnlys())
@@ -496,11 +472,13 @@
type testRuleBuilderModule struct {
ModuleBase
properties struct {
- Srcs []string
+ Srcs []string
+ Flags []string
- Restat bool
- Sbox bool
- Sbox_inputs bool
+ Restat bool
+ Sbox bool
+ Sbox_inputs bool
+ Unescape_ninja_vars bool
}
}
@@ -518,8 +496,9 @@
rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"})
manifestPath := PathForModuleOut(ctx, "sbox.textproto")
- testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, out, outDep, outDir,
- manifestPath, t.properties.Restat, t.properties.Sbox, t.properties.Sbox_inputs,
+ testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, t.properties.Flags,
+ out, outDep, outDir,
+ manifestPath, t.properties.Restat, t.properties.Sbox, t.properties.Sbox_inputs, t.properties.Unescape_ninja_vars,
rspFile, rspFileContents, rspFile2, rspFileContents2)
}
@@ -543,17 +522,18 @@
rspFileContents2 := PathsForSource(ctx, []string{"rsp_in2"})
manifestPath := PathForOutput(ctx, "singleton/sbox.textproto")
- testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, out, outDep, outDir,
- manifestPath, true, false, false,
+ testRuleBuilder_Build(ctx, in, implicit, orderOnly, validation, nil, out, outDep, outDir,
+ manifestPath, true, false, false, false,
rspFile, rspFileContents, rspFile2, rspFileContents2)
}
func testRuleBuilder_Build(ctx BuilderContext, in Paths, implicit, orderOnly, validation Path,
+ flags []string,
out, outDep, outDir, manifestPath WritablePath,
- restat, sbox, sboxInputs bool,
+ restat, sbox, sboxInputs, unescapeNinjaVars bool,
rspFile WritablePath, rspFileContents Paths, rspFile2 WritablePath, rspFileContents2 Paths) {
- rule := NewRuleBuilder(pctx, ctx)
+ rule := NewRuleBuilder(pctx_ruleBuilderTest, ctx)
if sbox {
rule.Sbox(outDir, manifestPath)
@@ -564,6 +544,7 @@
rule.Command().
Tool(PathForSource(ctx, "cp")).
+ Flags(flags).
Inputs(in).
Implicit(implicit).
OrderOnly(orderOnly).
@@ -577,7 +558,11 @@
rule.Restat()
}
- rule.Build("rule", "desc")
+ if unescapeNinjaVars {
+ rule.BuildWithUnescapedNinjaVars("rule", "desc")
+ } else {
+ rule.Build("rule", "desc")
+ }
}
var prepareForRuleBuilderTest = FixtureRegisterWithContext(func(ctx RegistrationContext) {
@@ -663,7 +648,7 @@
t.Errorf("want Deps = %q, got %q", blueprint.DepsGCC, params.Deps)
}
- rspFile2Content := ContentFromFileRuleForTests(t, rspFile2Params)
+ rspFile2Content := ContentFromFileRuleForTests(t, result.TestContext, rspFile2Params)
AssertStringEquals(t, "rspFile2 content", "rsp_in2\n", rspFile2Content)
}
@@ -777,7 +762,7 @@
t.Run(test.name, func(t *testing.T) {
t.Run("sbox", func(t *testing.T) {
gen := result.ModuleForTests(test.name+"_sbox", "")
- manifest := RuleBuilderSboxProtoForTests(t, gen.Output("sbox.textproto"))
+ manifest := RuleBuilderSboxProtoForTests(t, result.TestContext, gen.Output("sbox.textproto"))
hash := manifest.Commands[0].GetInputHash()
AssertStringEquals(t, "hash", test.expectedHash, hash)
@@ -792,3 +777,48 @@
})
}
}
+
+func TestRuleBuilderWithNinjaVarEscaping(t *testing.T) {
+ bp := `
+ rule_builder_test {
+ name: "foo_sbox_escaped",
+ flags: ["${cmdFlags}"],
+ sbox: true,
+ sbox_inputs: true,
+ }
+ rule_builder_test {
+ name: "foo_sbox_unescaped",
+ flags: ["${cmdFlags}"],
+ sbox: true,
+ sbox_inputs: true,
+ unescape_ninja_vars: true,
+ }
+ `
+ result := GroupFixturePreparers(
+ prepareForRuleBuilderTest,
+ FixtureWithRootAndroidBp(bp),
+ ).RunTest(t)
+
+ escapedNinjaMod := result.ModuleForTests("foo_sbox_escaped", "").Output("sbox.textproto")
+ AssertStringEquals(t, "expected rule", "android/soong/android.rawFileCopy", escapedNinjaMod.Rule.String())
+ AssertStringDoesContain(
+ t,
+ "",
+ ContentFromFileRuleForTests(t, result.TestContext, escapedNinjaMod),
+ "${cmdFlags}",
+ )
+
+ unescapedNinjaMod := result.ModuleForTests("foo_sbox_unescaped", "").Rule("unescapedWriteFile")
+ AssertStringDoesContain(
+ t,
+ "",
+ unescapedNinjaMod.BuildParams.Args["content"],
+ "${cmdFlags}",
+ )
+ AssertStringDoesNotContain(
+ t,
+ "",
+ unescapedNinjaMod.BuildParams.Args["content"],
+ "$${cmdFlags}",
+ )
+}
diff --git a/android/sdk.go b/android/sdk.go
index 6b598ab..6d5293e 100644
--- a/android/sdk.go
+++ b/android/sdk.go
@@ -860,11 +860,11 @@
Components []string
}
-var ExportedComponentsInfoProvider = blueprint.NewProvider(ExportedComponentsInfo{})
+var ExportedComponentsInfoProvider = blueprint.NewProvider[ExportedComponentsInfo]()
// AdditionalSdkInfo contains additional properties to add to the generated SDK info file.
type AdditionalSdkInfo struct {
Properties map[string]interface{}
}
-var AdditionalSdkInfoProvider = blueprint.NewProvider(AdditionalSdkInfo{})
+var AdditionalSdkInfoProvider = blueprint.NewProvider[AdditionalSdkInfo]()
diff --git a/android/sdk_version.go b/android/sdk_version.go
index 1fadda0..9355667 100644
--- a/android/sdk_version.go
+++ b/android/sdk_version.go
@@ -16,6 +16,7 @@
import (
"fmt"
+ "reflect"
"strconv"
"strings"
)
@@ -48,6 +49,7 @@
SdkPublic
SdkSystem
SdkTest
+ SdkTestFrameworksCore
SdkModule
SdkSystemServer
SdkPrivate
@@ -67,6 +69,8 @@
return "system"
case SdkTest:
return "test"
+ case SdkTestFrameworksCore:
+ return "test_frameworks_core"
case SdkCore:
return "core"
case SdkCorePlatform:
@@ -92,6 +96,8 @@
return "android_system_stubs_current"
case SdkTest:
return "android_test_stubs_current"
+ case SdkTestFrameworksCore:
+ return "android_test_frameworks_core_stubs_current"
case SdkCore:
return "core.current.stubs"
case SdkModule:
@@ -103,6 +109,17 @@
}
}
+func (k SdkKind) DefaultExportableJavaLibraryName() string {
+ switch k {
+ case SdkPublic, SdkSystem, SdkTest, SdkModule, SdkSystemServer:
+ return k.DefaultJavaLibraryName() + "_exportable"
+ case SdkCore:
+ return k.DefaultJavaLibraryName() + ".exportable"
+ default:
+ panic(fmt.Errorf("API surface %v does not provide exportable stubs", k))
+ }
+}
+
// SdkSpec represents the kind and the version of an SDK for a module to build against
type SdkSpec struct {
Kind SdkKind
@@ -137,7 +154,7 @@
return true
case SdkCore, SdkPublic, SdkSystem, SdkModule, SdkSystemServer:
return true
- case SdkCorePlatform, SdkTest, SdkPrivate:
+ case SdkCorePlatform, SdkTest, SdkTestFrameworksCore, SdkPrivate:
return false
default:
panic(fmt.Errorf("unknown SdkKind=%v", s.Kind))
@@ -157,6 +174,17 @@
// If BOARD_CURRENT_API_LEVEL_FOR_VENDOR_MODULES has a numeric value,
// use it instead of "current" for the vendor partition.
currentSdkVersion := ctx.DeviceConfig().CurrentApiLevelForVendorModules()
+ // b/314011075: special case for Java modules in vendor partition. They can no longer use
+ // SDK 35 or later. Their maximum API level is limited to 34 (Android U). This is to
+ // discourage the use of Java APIs in the vendor partition which hasn't been officially
+ // supported since the Project Treble back in Android 10. We would like to eventually
+ // evacuate all Java modules from the partition, but that shall be done progressively.
+ // Note that the check for the availability of SDK 34 is to not break existing tests where
+ // any of the frozen SDK version is unavailable.
+ if isJava(ctx.Module()) && isSdkVersion34AvailableIn(ctx.Config()) {
+ currentSdkVersion = "34"
+ }
+
if currentSdkVersion == "current" {
return s
}
@@ -185,7 +213,8 @@
return ctx.Config().AlwaysUsePrebuiltSdks()
} else if !s.ApiLevel.IsPreview() {
// validation check
- if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest && s.Kind != SdkModule && s.Kind != SdkSystemServer {
+ if s.Kind != SdkPublic && s.Kind != SdkSystem && s.Kind != SdkTest &&
+ s.Kind != SdkTestFrameworksCore && s.Kind != SdkModule && s.Kind != SdkSystemServer {
panic(fmt.Errorf("prebuilt SDK is not not available for SdkKind=%q", s.Kind))
return false
}
@@ -266,6 +295,8 @@
kind = SdkSystem
case "test":
kind = SdkTest
+ case "test_frameworks_core":
+ kind = SdkTestFrameworksCore
case "module":
kind = SdkModule
case "system_server":
@@ -282,28 +313,79 @@
}
}
+// Checks if the use of this SDK `s` is valid for the given module context `ctx`.
func (s SdkSpec) ValidateSystemSdk(ctx EarlyModuleContext) bool {
- // Ensures that the specified system SDK version is one of BOARD_SYSTEMSDK_VERSIONS (for vendor/product Java module)
- // Assuming that BOARD_SYSTEMSDK_VERSIONS := 28 29,
- // sdk_version of the modules in vendor/product that use system sdk must be either system_28, system_29 or system_current
- if s.Kind != SdkSystem || s.ApiLevel.IsPreview() {
+ // Do some early checks. This check is currently only for Java modules. And our only concern
+ // is the use of "system" SDKs.
+ if !isJava(ctx.Module()) || s.Kind != SdkSystem || ctx.DeviceConfig().BuildBrokenDontCheckSystemSdk() {
return true
}
- allowedVersions := ctx.DeviceConfig().PlatformSystemSdkVersions()
- if ctx.DeviceSpecific() || ctx.SocSpecific() || (ctx.ProductSpecific() && ctx.Config().EnforceProductPartitionInterface()) {
- systemSdkVersions := ctx.DeviceConfig().SystemSdkVersions()
- if len(systemSdkVersions) > 0 {
- allowedVersions = systemSdkVersions
+
+ inVendor := ctx.DeviceSpecific() || ctx.SocSpecific()
+ inProduct := ctx.ProductSpecific()
+ isProductUnbundled := ctx.Config().EnforceProductPartitionInterface()
+ inApex := false
+ if am, ok := ctx.Module().(ApexModule); ok {
+ inApex = am.InAnyApex()
+ }
+ isUnbundled := inVendor || (inProduct && isProductUnbundled) || inApex
+
+ // Bundled modules can use any SDK
+ if !isUnbundled {
+ return true
+ }
+
+ // Unbundled modules are allowed to use BOARD_SYSTEMSDK_VERSIONS
+ supportedVersions := ctx.DeviceConfig().SystemSdkVersions()
+
+ // b/314011075: special case for vendor modules. Java modules in the vendor partition can
+ // not use SDK 35 or later. This is to discourage the use of Java APIs in the vendor
+ // partition which hasn't been officially supported since the Project Treble back in Android
+ // 10. We would like to eventually evacuate all Java modules from the partition, but that
+ // shall be done progressively.
+ if inVendor {
+ // 28 was the API when BOARD_SYSTEMSDK_VERSIONS was introduced, so that's the oldest
+ // we should allow.
+ supportedVersions = []string{}
+ for v := 28; v <= 34; v++ {
+ supportedVersions = append(supportedVersions, strconv.Itoa(v))
}
}
- if len(allowedVersions) > 0 && !InList(s.ApiLevel.String(), allowedVersions) {
+
+ // APEXes in the system partition are still considered as part of the platform, thus can use
+ // more SDKs from PLATFORM_SYSTEMSDK_VERSIONS
+ if inApex && !inVendor {
+ supportedVersions = ctx.DeviceConfig().PlatformSystemSdkVersions()
+ }
+
+ thisVer, err := s.EffectiveVersion(ctx)
+ if err != nil {
+ ctx.PropertyErrorf("sdk_version", "invalid sdk version %q", s.Raw)
+ return false
+ }
+
+ thisVerString := strconv.Itoa(thisVer.FinalOrPreviewInt())
+ if thisVer.IsPreview() {
+ thisVerString = *ctx.Config().productVariables.Platform_sdk_version_or_codename
+ }
+
+ if !InList(thisVerString, supportedVersions) {
ctx.PropertyErrorf("sdk_version", "incompatible sdk version %q. System SDK version should be one of %q",
- s.Raw, allowedVersions)
+ s.Raw, supportedVersions)
return false
}
return true
}
+func isJava(m Module) bool {
+ moduleType := reflect.TypeOf(m).String()
+ return strings.HasPrefix(moduleType, "*java.")
+}
+
+func isSdkVersion34AvailableIn(c Config) bool {
+ return c.PlatformSdkVersion().FinalInt() >= 34
+}
+
func init() {
RegisterMakeVarsProvider(pctx, javaSdkMakeVars)
}
diff --git a/android/singleton.go b/android/singleton.go
index 7c6cf4f..e0e552e 100644
--- a/android/singleton.go
+++ b/android/singleton.go
@@ -20,6 +20,8 @@
// SingletonContext
type SingletonContext interface {
+ blueprintSingletonContext() blueprint.SingletonContext
+
Config() Config
DeviceConfig() DeviceConfig
@@ -33,15 +35,7 @@
// Allows generating build actions for `referer` based on the metadata for `name` deferred until the singleton context.
ModuleVariantsFromName(referer Module, name string) []Module
- // ModuleProvider returns the value, if any, for the provider for a module. If the value for the
- // provider was not set it returns the zero value of the type of the provider, which means the
- // return value can always be type-asserted to the type of the provider. The return value should
- // always be considered read-only. It panics if called before the appropriate mutator or
- // GenerateBuildActions pass for the provider on the module.
- ModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{}
-
- // ModuleHasProvider returns true if the provider for the given module has been set.
- ModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool
+ moduleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool)
ModuleErrorf(module blueprint.Module, format string, args ...interface{})
Errorf(format string, args ...interface{})
@@ -135,6 +129,10 @@
ruleParams map[blueprint.Rule]blueprint.RuleParams
}
+func (s *singletonContextAdaptor) blueprintSingletonContext() blueprint.SingletonContext {
+ return s.SingletonContext
+}
+
func (s *singletonContextAdaptor) Config() Config {
return s.SingletonContext.Config().(Config)
}
@@ -172,12 +170,7 @@
s.buildParams = append(s.buildParams, params)
}
bparams := convertBuildParams(params)
- err := validateBuildParams(bparams)
- if err != nil {
- s.Errorf("%s: build parameter validation failed: %s", s.Name(), err.Error())
- }
s.SingletonContext.Build(pctx.PackageContext, bparams)
-
}
func (s *singletonContextAdaptor) Phony(name string, deps ...Path) {
@@ -282,3 +275,7 @@
}
return result
}
+
+func (s *singletonContextAdaptor) moduleProvider(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
+ return s.SingletonContext.ModuleProvider(module, provider)
+}
diff --git a/android/singleton_module_test.go b/android/singleton_module_test.go
index 9d98478..3b1bf39 100644
--- a/android/singleton_module_test.go
+++ b/android/singleton_module_test.go
@@ -103,6 +103,9 @@
}
func TestVariantSingletonModule(t *testing.T) {
+ if testing.Short() {
+ t.Skip("test fails with data race enabled")
+ }
bp := `
test_singleton_module {
name: "test_singleton_module",
diff --git a/android/soong_config_modules.go b/android/soong_config_modules.go
index 0246a08..90b49eb 100644
--- a/android/soong_config_modules.go
+++ b/android/soong_config_modules.go
@@ -41,6 +41,7 @@
ctx.RegisterModuleType("soong_config_module_type", SoongConfigModuleTypeFactory)
ctx.RegisterModuleType("soong_config_string_variable", SoongConfigStringVariableDummyFactory)
ctx.RegisterModuleType("soong_config_bool_variable", SoongConfigBoolVariableDummyFactory)
+ ctx.RegisterModuleType("soong_config_value_variable", SoongConfigValueVariableDummyFactory)
}
var PrepareForTestWithSoongConfigModuleBuildComponents = FixtureRegisterWithContext(RegisterSoongConfigModuleBuildComponents)
@@ -187,7 +188,6 @@
type soongConfigModuleTypeModule struct {
ModuleBase
- BazelModuleBase
properties soongconfig.ModuleTypeProperties
}
@@ -304,6 +304,11 @@
properties soongconfig.VariableProperties
}
+type soongConfigValueVariableDummyModule struct {
+ ModuleBase
+ properties soongconfig.VariableProperties
+}
+
// soong_config_string_variable defines a variable and a set of possible string values for use
// in a soong_config_module_type definition.
func SoongConfigStringVariableDummyFactory() Module {
@@ -322,6 +327,15 @@
return module
}
+// soong_config_value_variable defines a variable whose value can be expanded into
+// the value of a string property.
+func SoongConfigValueVariableDummyFactory() Module {
+ module := &soongConfigValueVariableDummyModule{}
+ module.AddProperties(&module.properties)
+ initAndroidModuleBase(module)
+ return module
+}
+
func (m *soongConfigStringVariableDummyModule) Name() string {
return m.properties.Name + fmt.Sprintf("%p", m)
}
@@ -334,6 +348,12 @@
func (*soongConfigBoolVariableDummyModule) Namespaceless() {}
func (*soongConfigBoolVariableDummyModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
+func (m *soongConfigValueVariableDummyModule) Name() string {
+ return m.properties.Name + fmt.Sprintf("%p", m)
+}
+func (*soongConfigValueVariableDummyModule) Namespaceless() {}
+func (*soongConfigValueVariableDummyModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
+
// importModuleTypes registers the module factories for a list of module types defined
// in an Android.bp file. These module factories are scoped for the current Android.bp
// file only.
@@ -395,10 +415,6 @@
return (map[string]blueprint.ModuleFactory)(nil)
}
- if ctx.Config().BuildMode == Bp2build {
- ctx.Config().Bp2buildSoongConfigDefinitions.AddVars(mtDef)
- }
-
globalModuleTypes := ctx.moduleFactories()
factories := make(map[string]blueprint.ModuleFactory)
@@ -406,7 +422,7 @@
for name, moduleType := range mtDef.ModuleTypes {
factory := globalModuleTypes[moduleType.BaseModuleType]
if factory != nil {
- factories[name] = configModuleFactory(factory, moduleType, ctx.Config().BuildMode == Bp2build)
+ factories[name] = configModuleFactory(factory, moduleType)
} else {
reportErrors(ctx, from,
fmt.Errorf("missing global module type factory for %q", moduleType.BaseModuleType))
@@ -474,7 +490,7 @@
// configModuleFactory takes an existing soongConfigModuleFactory and a
// ModuleType to create a new ModuleFactory that uses a custom loadhook.
-func configModuleFactory(factory blueprint.ModuleFactory, moduleType *soongconfig.ModuleType, bp2build bool) blueprint.ModuleFactory {
+func configModuleFactory(factory blueprint.ModuleFactory, moduleType *soongconfig.ModuleType) blueprint.ModuleFactory {
// Defer creation of conditional properties struct until the first call from the factory
// method. That avoids having to make a special call to the factory to create the properties
// structs from which the conditional properties struct is created. This is needed in order to
@@ -515,40 +531,22 @@
conditionalProps := proptools.CloneEmptyProperties(conditionalFactoryProps)
props = append(props, conditionalProps.Interface())
- if bp2build {
- // The loadhook is different for bp2build, since we don't want to set a specific
- // set of property values based on a vendor var -- we want __all of them__ to
- // generate select statements, so we put the entire soong_config_variables
- // struct, together with the namespace representing those variables, while
- // creating the custom module with the factory.
- AddLoadHook(module, func(ctx LoadHookContext) {
- if m, ok := module.(Bazelable); ok {
- m.SetBaseModuleType(moduleType.BaseModuleType)
- // Instead of applying all properties, keep the entire conditionalProps struct as
- // part of the custom module so dependent modules can create the selects accordingly
- m.setNamespacedVariableProps(namespacedVariableProperties{
- moduleType.ConfigNamespace: []interface{}{conditionalProps.Interface()},
- })
- }
- })
- } else {
- // Regular Soong operation wraps the existing module factory with a
- // conditional on Soong config variables by reading the product
- // config variables from Make.
- AddLoadHook(module, func(ctx LoadHookContext) {
- tracingConfig := newTracingConfig(ctx.Config().VendorConfig(moduleType.ConfigNamespace))
- newProps, err := soongconfig.PropertiesToApply(moduleType, conditionalProps, tracingConfig)
- if err != nil {
- ctx.ModuleErrorf("%s", err)
- return
- }
- for _, ps := range newProps {
- ctx.AppendProperties(ps)
- }
+ // Regular Soong operation wraps the existing module factory with a
+ // conditional on Soong config variables by reading the product
+ // config variables from Make.
+ AddLoadHook(module, func(ctx LoadHookContext) {
+ tracingConfig := newTracingConfig(ctx.Config().VendorConfig(moduleType.ConfigNamespace))
+ newProps, err := soongconfig.PropertiesToApply(moduleType, conditionalProps, tracingConfig)
+ if err != nil {
+ ctx.ModuleErrorf("%s", err)
+ return
+ }
+ for _, ps := range newProps {
+ ctx.AppendProperties(ps)
+ }
- module.(Module).base().commonProperties.SoongConfigTrace = tracingConfig.getTrace()
- })
- }
+ module.(Module).base().commonProperties.SoongConfigTrace = tracingConfig.getTrace()
+ })
return module, props
}
}
diff --git a/android/soong_config_modules_test.go b/android/soong_config_modules_test.go
index 79bdeb8..a6b2c51 100644
--- a/android/soong_config_modules_test.go
+++ b/android/soong_config_modules_test.go
@@ -376,8 +376,7 @@
prepareForSoongConfigTestModule,
FixtureWithRootAndroidBp(bp),
).ExtendWithErrorHandler(FixtureExpectsAllErrorsToMatchAPattern([]string{
- // TODO(b/171232169): improve the error message for non-existent properties
- `unrecognized property "soong_config_variables`,
+ `unrecognized property "soong_config_variables.feature1.made_up_property`,
})).RunTest(t)
}
diff --git a/android/soongconfig/modules.go b/android/soongconfig/modules.go
index 23c8afa..d525bdc 100644
--- a/android/soongconfig/modules.go
+++ b/android/soongconfig/modules.go
@@ -20,12 +20,9 @@
"reflect"
"sort"
"strings"
- "sync"
"github.com/google/blueprint/parser"
"github.com/google/blueprint/proptools"
-
- "android/soong/starlark_fmt"
)
const conditionsDefault = "conditions_default"
@@ -236,110 +233,6 @@
variables map[string]soongConfigVariable
}
-// Bp2BuildSoongConfigDefinition keeps a global record of all soong config
-// string vars, bool vars and value vars created by every
-// soong_config_module_type in this build.
-type Bp2BuildSoongConfigDefinitions struct {
- StringVars map[string]map[string]bool
- BoolVars map[string]bool
- ValueVars map[string]bool
-}
-
-var bp2buildSoongConfigVarsLock sync.Mutex
-
-// SoongConfigVariablesForBp2build extracts information from a
-// SoongConfigDefinition that bp2build needs to generate constraint settings and
-// values for, in order to migrate soong_config_module_type usages to Bazel.
-func (defs *Bp2BuildSoongConfigDefinitions) AddVars(mtDef *SoongConfigDefinition) {
- // In bp2build mode, this method is called concurrently in goroutines from
- // loadhooks while parsing soong_config_module_type, so add a mutex to
- // prevent concurrent map writes. See b/207572723
- bp2buildSoongConfigVarsLock.Lock()
- defer bp2buildSoongConfigVarsLock.Unlock()
-
- if defs.StringVars == nil {
- defs.StringVars = make(map[string]map[string]bool)
- }
- if defs.BoolVars == nil {
- defs.BoolVars = make(map[string]bool)
- }
- if defs.ValueVars == nil {
- defs.ValueVars = make(map[string]bool)
- }
- // varCache contains a cache of string variables namespace + property
- // The same variable may be used in multiple module types (for example, if need support
- // for cc_default and java_default), only need to process once
- varCache := map[string]bool{}
-
- for _, moduleType := range mtDef.ModuleTypes {
- for _, v := range moduleType.Variables {
- key := strings.Join([]string{moduleType.ConfigNamespace, v.variableProperty()}, "__")
-
- // The same variable may be used in multiple module types (for example, if need support
- // for cc_default and java_default), only need to process once
- if _, keyInCache := varCache[key]; keyInCache {
- continue
- } else {
- varCache[key] = true
- }
-
- if strVar, ok := v.(*stringVariable); ok {
- if _, ok := defs.StringVars[key]; !ok {
- defs.StringVars[key] = make(map[string]bool, len(strVar.values))
- }
- for _, value := range strVar.values {
- defs.StringVars[key][value] = true
- }
- } else if _, ok := v.(*boolVariable); ok {
- defs.BoolVars[key] = true
- } else if _, ok := v.(*valueVariable); ok {
- defs.ValueVars[key] = true
- } else {
- panic(fmt.Errorf("Unsupported variable type: %+v", v))
- }
- }
- }
-}
-
-// This is a copy of the one available in soong/android/util.go, but depending
-// on the android package causes a cyclic dependency. A refactoring here is to
-// extract common utils out from android/utils.go for other packages like this.
-func sortedStringKeys(m interface{}) []string {
- v := reflect.ValueOf(m)
- if v.Kind() != reflect.Map {
- panic(fmt.Sprintf("%#v is not a map", m))
- }
- keys := v.MapKeys()
- s := make([]string, 0, len(keys))
- for _, key := range keys {
- s = append(s, key.String())
- }
- sort.Strings(s)
- return s
-}
-
-// String emits the Soong config variable definitions as Starlark dictionaries.
-func (defs Bp2BuildSoongConfigDefinitions) String() string {
- ret := ""
- ret += "soong_config_bool_variables = "
- ret += starlark_fmt.PrintBoolDict(defs.BoolVars, 0)
- ret += "\n\n"
-
- ret += "soong_config_value_variables = "
- ret += starlark_fmt.PrintBoolDict(defs.ValueVars, 0)
- ret += "\n\n"
-
- stringVars := make(map[string][]string, len(defs.StringVars))
- for k, v := range defs.StringVars {
- stringVars[k] = sortedStringKeys(v)
- }
-
- ret += "soong_config_string_variables = "
- ret += starlark_fmt.PrintStringListDict(stringVars, 0)
-
- return ret
-}
-
// CreateProperties returns a reflect.Value of a newly constructed type that contains the desired
// property layout for the Soong config variables, with each possible value an interface{} that
// contains a nil pointer to another newly constructed type that contains the affectable properties.
@@ -796,6 +689,7 @@
continue
}
field = field.Elem()
+ kind = field.Kind()
}
switch kind {
case reflect.String:
diff --git a/android/soongconfig/modules_test.go b/android/soongconfig/modules_test.go
index a5fa349..db2c83c 100644
--- a/android/soongconfig/modules_test.go
+++ b/android/soongconfig/modules_test.go
@@ -299,7 +299,7 @@
Conditions_default *properties
}
-type soongConfigVars struct {
+type boolSoongConfigVars struct {
Bool_var interface{}
}
@@ -307,7 +307,11 @@
String_var interface{}
}
-func Test_PropertiesToApply(t *testing.T) {
+type valueSoongConfigVars struct {
+ My_value_var interface{}
+}
+
+func Test_PropertiesToApply_Bool(t *testing.T) {
mt, _ := newModuleType(&ModuleTypeProperties{
Module_type: "foo",
Config_namespace: "bar",
@@ -323,9 +327,9 @@
B: false,
}
actualProps := &struct {
- Soong_config_variables soongConfigVars
+ Soong_config_variables boolSoongConfigVars
}{
- Soong_config_variables: soongConfigVars{
+ Soong_config_variables: boolSoongConfigVars{
Bool_var: &boolVarProps{
A: boolVarPositive.A,
B: boolVarPositive.B,
@@ -369,6 +373,62 @@
}
}
+func Test_PropertiesToApply_Value(t *testing.T) {
+ mt, _ := newModuleType(&ModuleTypeProperties{
+ Module_type: "foo",
+ Config_namespace: "bar",
+ Value_variables: []string{"my_value_var"},
+ Properties: []string{"a", "b"},
+ })
+ conditionsDefault := &properties{
+ A: proptools.StringPtr("default"),
+ B: false,
+ }
+ actualProps := &struct {
+ Soong_config_variables valueSoongConfigVars
+ }{
+ Soong_config_variables: valueSoongConfigVars{
+ My_value_var: &boolVarProps{
+ A: proptools.StringPtr("A=%s"),
+ B: true,
+ Conditions_default: conditionsDefault,
+ },
+ },
+ }
+ props := reflect.ValueOf(actualProps)
+
+ testCases := []struct {
+ name string
+ config SoongConfig
+ wantProps []interface{}
+ }{
+ {
+ name: "no_vendor_config",
+ config: Config(map[string]string{}),
+ wantProps: []interface{}{conditionsDefault},
+ },
+ {
+ name: "value_var_set",
+ config: Config(map[string]string{"my_value_var": "Hello"}),
+ wantProps: []interface{}{&properties{
+ A: proptools.StringPtr("A=Hello"),
+ B: true,
+ }},
+ },
+ }
+
+ for _, tc := range testCases {
+ gotProps, err := PropertiesToApply(mt, props, tc.config)
+ if err != nil {
+ t.Errorf("%s: Unexpected error in PropertiesToApply: %s", tc.name, err)
+ }
+
+ if !reflect.DeepEqual(gotProps, tc.wantProps) {
+ t.Errorf("%s: Expected %s, got %s", tc.name, tc.wantProps, gotProps)
+ }
+ }
+}
+
func Test_PropertiesToApply_String_Error(t *testing.T) {
mt, _ := newModuleType(&ModuleTypeProperties{
Module_type: "foo",
@@ -413,220 +473,3 @@
t.Fatalf("Error message was not correct, expected %q, got %q", expected, err.Error())
}
}
-
-func Test_Bp2BuildSoongConfigDefinitionsAddVars(t *testing.T) {
- testCases := []struct {
- desc string
- defs []*SoongConfigDefinition
- expected Bp2BuildSoongConfigDefinitions
- }{
- {
- desc: "non-overlapping",
- defs: []*SoongConfigDefinition{
- &SoongConfigDefinition{
- ModuleTypes: map[string]*ModuleType{
- "a": &ModuleType{
- ConfigNamespace: "foo",
- Variables: []soongConfigVariable{
- &stringVariable{
- baseVariable: baseVariable{"string_var"},
- values: []string{"a", "b", "c"},
- },
- },
- },
- },
- },
- &SoongConfigDefinition{
- ModuleTypes: map[string]*ModuleType{
- "b": &ModuleType{
- ConfigNamespace: "foo",
- Variables: []soongConfigVariable{
- &stringVariable{
- baseVariable: baseVariable{"string_var"},
- values: []string{"a", "b", "c"},
- },
- &boolVariable{baseVariable: baseVariable{"bool_var"}},
- &valueVariable{baseVariable: baseVariable{"variable_var"}},
- },
- },
- },
- },
- },
- expected: Bp2BuildSoongConfigDefinitions{
- StringVars: map[string]map[string]bool{
- "foo__string_var": map[string]bool{"a": true, "b": true, "c": true},
- },
- BoolVars: map[string]bool{"foo__bool_var": true},
- ValueVars: map[string]bool{"foo__variable_var": true},
- },
- },
- {
- desc: "overlapping",
- defs: []*SoongConfigDefinition{
- &SoongConfigDefinition{
- ModuleTypes: map[string]*ModuleType{
- "a": &ModuleType{
- ConfigNamespace: "foo",
- Variables: []soongConfigVariable{
- &stringVariable{
- baseVariable: baseVariable{"string_var"},
- values: []string{"a", "b", "c"},
- },
- },
- },
- },
- },
- &SoongConfigDefinition{
- ModuleTypes: map[string]*ModuleType{
- "b": &ModuleType{
- ConfigNamespace: "foo",
- Variables: []soongConfigVariable{
- &stringVariable{
- baseVariable: baseVariable{"string_var"},
- values: []string{"b", "c", "d"},
- },
- &boolVariable{baseVariable: baseVariable{"bool_var"}},
- &valueVariable{baseVariable: baseVariable{"variable_var"}},
- },
- },
- },
- },
- },
- expected: Bp2BuildSoongConfigDefinitions{
- StringVars: map[string]map[string]bool{
- "foo__string_var": map[string]bool{"a": true, "b": true, "c": true, "d": true},
- },
- BoolVars: map[string]bool{"foo__bool_var": true},
- ValueVars: map[string]bool{"foo__variable_var": true},
- },
- },
- }
-
- for _, tc := range testCases {
- t.Run(tc.desc, func(t *testing.T) {
- actual := &Bp2BuildSoongConfigDefinitions{}
- for _, d := range tc.defs {
- func(def *SoongConfigDefinition) {
- actual.AddVars(def)
- }(d)
- }
- if !reflect.DeepEqual(*actual, tc.expected) {
- t.Errorf("Expected %#v, got %#v", tc.expected, *actual)
- }
- })
- }
-
-}
-
-func Test_Bp2BuildSoongConfigDefinitions(t *testing.T) {
- testCases := []struct {
- desc string
- defs Bp2BuildSoongConfigDefinitions
- expected string
- }{
- {
- desc: "all empty",
- defs: Bp2BuildSoongConfigDefinitions{},
- expected: `soong_config_bool_variables = {}
-
-soong_config_value_variables = {}
-
-soong_config_string_variables = {}`}, {
- desc: "only bool",
- defs: Bp2BuildSoongConfigDefinitions{
- BoolVars: map[string]bool{
- "bool_var": true,
- },
- },
- expected: `soong_config_bool_variables = {
- "bool_var": True,
-}
-
-soong_config_value_variables = {}
-
-soong_config_string_variables = {}`}, {
- desc: "only value vars",
- defs: Bp2BuildSoongConfigDefinitions{
- ValueVars: map[string]bool{
- "value_var": true,
- },
- },
- expected: `soong_config_bool_variables = {}
-
-soong_config_value_variables = {
- "value_var": True,
-}
-
-soong_config_string_variables = {}`}, {
- desc: "only string vars",
- defs: Bp2BuildSoongConfigDefinitions{
- StringVars: map[string]map[string]bool{
- "string_var": map[string]bool{
- "choice1": true,
- "choice2": true,
- "choice3": true,
- },
- },
- },
- expected: `soong_config_bool_variables = {}
-
-soong_config_value_variables = {}
-
-soong_config_string_variables = {
- "string_var": [
- "choice1",
- "choice2",
- "choice3",
- ],
-}`}, {
- desc: "all vars",
- defs: Bp2BuildSoongConfigDefinitions{
- BoolVars: map[string]bool{
- "bool_var_one": true,
- },
- ValueVars: map[string]bool{
- "value_var_one": true,
- "value_var_two": true,
- },
- StringVars: map[string]map[string]bool{
- "string_var_one": map[string]bool{
- "choice1": true,
- "choice2": true,
- "choice3": true,
- },
- "string_var_two": map[string]bool{
- "foo": true,
- "bar": true,
- },
- },
- },
- expected: `soong_config_bool_variables = {
- "bool_var_one": True,
-}
-
-soong_config_value_variables = {
- "value_var_one": True,
- "value_var_two": True,
-}
-
-soong_config_string_variables = {
- "string_var_one": [
- "choice1",
- "choice2",
- "choice3",
- ],
- "string_var_two": [
- "bar",
- "foo",
- ],
-}`},
- }
- for _, test := range testCases {
- t.Run(test.desc, func(t *testing.T) {
- actual := test.defs.String()
- if actual != test.expected {
- t.Errorf("Expected:\n%s\nbut got:\n%s", test.expected, actual)
- }
- })
- }
-}
diff --git a/android/team.go b/android/team.go
new file mode 100644
index 0000000..df61f40
--- /dev/null
+++ b/android/team.go
@@ -0,0 +1,58 @@
+// Copyright 2020 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 android
+
+func init() {
+ RegisterTeamBuildComponents(InitRegistrationContext)
+}
+
+func RegisterTeamBuildComponents(ctx RegistrationContext) {
+ ctx.RegisterModuleType("team", TeamFactory)
+}
+
+var PrepareForTestWithTeamBuildComponents = GroupFixturePreparers(
+ FixtureRegisterWithContext(RegisterTeamBuildComponents),
+)
+
+type teamProperties struct {
+ Trendy_team_id *string `json:"trendy_team_id"`
+}
+
+type teamModule struct {
+ ModuleBase
+ DefaultableModuleBase
+
+ properties teamProperties
+}
+
+// Real work is done for the module that depends on us.
+// If needed, the team can serialize the config to json/proto file as well.
+func (t *teamModule) GenerateAndroidBuildActions(ctx ModuleContext) {}
+
+func (t *teamModule) TrendyTeamId(ctx ModuleContext) string {
+ return *t.properties.Trendy_team_id
+}
+
+func TeamFactory() Module {
+ module := &teamModule{}
+
+ base := module.base()
+ module.AddProperties(&base.nameProperties, &module.properties)
+
+ InitAndroidModule(module)
+ InitDefaultableModule(module)
+
+ return module
+}
diff --git a/android/team_proto/Android.bp b/android/team_proto/Android.bp
new file mode 100644
index 0000000..7e2a4c1
--- /dev/null
+++ b/android/team_proto/Android.bp
@@ -0,0 +1,43 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-android_team_proto",
+ pkgPath: "android/soong/android/team_proto",
+ deps: [
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ ],
+ srcs: [
+ "team.pb.go",
+ ],
+}
+
+python_library_host {
+ name: "teams-proto-py",
+ pkg_path: "teams",
+ srcs: [
+ "team.proto",
+ ],
+ libs: [
+ "libprotobuf-python",
+ ],
+ proto: {
+ canonical_path_from_root: false,
+ },
+}
diff --git a/android/team_proto/OWNERS b/android/team_proto/OWNERS
new file mode 100644
index 0000000..2beb4f4
--- /dev/null
+++ b/android/team_proto/OWNERS
@@ -0,0 +1,5 @@
+dariofreni@google.com
+joeo@google.com
+ronish@google.com
+caditya@google.com
+rbraunstein@google.com
diff --git a/android/team_proto/regen.sh b/android/team_proto/regen.sh
new file mode 100755
index 0000000..63b2016
--- /dev/null
+++ b/android/team_proto/regen.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+aprotoc --go_out=paths=source_relative:. team.proto
diff --git a/android/team_proto/team.pb.go b/android/team_proto/team.pb.go
new file mode 100644
index 0000000..61260cf
--- /dev/null
+++ b/android/team_proto/team.pb.go
@@ -0,0 +1,253 @@
+// 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc v3.21.12
+// source: team.proto
+
+package team_proto
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type Team struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // REQUIRED: Name of the build target
+ TargetName *string `protobuf:"bytes,1,opt,name=target_name,json=targetName" json:"target_name,omitempty"`
+ // REQUIRED: Code location of the target.
+ // To be used to support legacy/backup systems that use OWNERS file and is
+ // also required for our dashboard to support per code location basis UI
+ Path *string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"`
+ // REQUIRED: Team ID of the team that owns this target.
+ TrendyTeamId *string `protobuf:"bytes,3,opt,name=trendy_team_id,json=trendyTeamId" json:"trendy_team_id,omitempty"`
+ // OPTIONAL: Files directly owned by this module.
+ File []string `protobuf:"bytes,4,rep,name=file" json:"file,omitempty"`
+}
+
+func (x *Team) Reset() {
+ *x = Team{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_team_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *Team) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*Team) ProtoMessage() {}
+
+func (x *Team) ProtoReflect() protoreflect.Message {
+ mi := &file_team_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use Team.ProtoReflect.Descriptor instead.
+func (*Team) Descriptor() ([]byte, []int) {
+ return file_team_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *Team) GetTargetName() string {
+ if x != nil && x.TargetName != nil {
+ return *x.TargetName
+ }
+ return ""
+}
+
+func (x *Team) GetPath() string {
+ if x != nil && x.Path != nil {
+ return *x.Path
+ }
+ return ""
+}
+
+func (x *Team) GetTrendyTeamId() string {
+ if x != nil && x.TrendyTeamId != nil {
+ return *x.TrendyTeamId
+ }
+ return ""
+}
+
+func (x *Team) GetFile() []string {
+ if x != nil {
+ return x.File
+ }
+ return nil
+}
+
+type AllTeams struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ Teams []*Team `protobuf:"bytes,1,rep,name=teams" json:"teams,omitempty"`
+}
+
+func (x *AllTeams) Reset() {
+ *x = AllTeams{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_team_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *AllTeams) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*AllTeams) ProtoMessage() {}
+
+func (x *AllTeams) ProtoReflect() protoreflect.Message {
+ mi := &file_team_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use AllTeams.ProtoReflect.Descriptor instead.
+func (*AllTeams) Descriptor() ([]byte, []int) {
+ return file_team_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *AllTeams) GetTeams() []*Team {
+ if x != nil {
+ return x.Teams
+ }
+ return nil
+}
+
+var File_team_proto protoreflect.FileDescriptor
+
+var file_team_proto_rawDesc = []byte{
+ 0x0a, 0x0a, 0x74, 0x65, 0x61, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0a, 0x74, 0x65,
+ 0x61, 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x75, 0x0a, 0x04, 0x54, 0x65, 0x61, 0x6d,
+ 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x61, 0x6d,
+ 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
+ 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x5f,
+ 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74,
+ 0x72, 0x65, 0x6e, 0x64, 0x79, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x66,
+ 0x69, 0x6c, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22,
+ 0x32, 0x0a, 0x08, 0x41, 0x6c, 0x6c, 0x54, 0x65, 0x61, 0x6d, 0x73, 0x12, 0x26, 0x0a, 0x05, 0x74,
+ 0x65, 0x61, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x65, 0x61,
+ 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x65, 0x61, 0x6d, 0x52, 0x05, 0x74, 0x65,
+ 0x61, 0x6d, 0x73, 0x42, 0x22, 0x5a, 0x20, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73,
+ 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x74, 0x65, 0x61,
+ 0x6d, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+}
+
+var (
+ file_team_proto_rawDescOnce sync.Once
+ file_team_proto_rawDescData = file_team_proto_rawDesc
+)
+
+func file_team_proto_rawDescGZIP() []byte {
+ file_team_proto_rawDescOnce.Do(func() {
+ file_team_proto_rawDescData = protoimpl.X.CompressGZIP(file_team_proto_rawDescData)
+ })
+ return file_team_proto_rawDescData
+}
+
+var file_team_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_team_proto_goTypes = []interface{}{
+ (*Team)(nil), // 0: team_proto.Team
+ (*AllTeams)(nil), // 1: team_proto.AllTeams
+}
+var file_team_proto_depIdxs = []int32{
+ 0, // 0: team_proto.AllTeams.teams:type_name -> team_proto.Team
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_team_proto_init() }
+func file_team_proto_init() {
+ if File_team_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_team_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*Team); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_team_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*AllTeams); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_team_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_team_proto_goTypes,
+ DependencyIndexes: file_team_proto_depIdxs,
+ MessageInfos: file_team_proto_msgTypes,
+ }.Build()
+ File_team_proto = out.File
+ file_team_proto_rawDesc = nil
+ file_team_proto_goTypes = nil
+ file_team_proto_depIdxs = nil
+}
diff --git a/android/team_proto/team.proto b/android/team_proto/team.proto
new file mode 100644
index 0000000..401eccc
--- /dev/null
+++ b/android/team_proto/team.proto
@@ -0,0 +1,34 @@
+// 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.
+
+syntax = "proto2";
+package team_proto;
+option go_package = "android/soong/android/team_proto";
+
+message Team {
+ // REQUIRED: Name of the build target
+ optional string target_name = 1;
+
+ // REQUIRED: Code location of the target.
+ // To be used to support legacy/backup systems that use OWNERS file and is
+ // also required for our dashboard to support per code location basis UI
+ optional string path = 2;
+
+ // REQUIRED: Team ID of the team that owns this target.
+ optional string trendy_team_id = 3;
+
+ // OPTIONAL: Files directly owned by this module.
+ repeated string file = 4;
+}
+
+message AllTeams {
+ repeated Team teams = 1;
+}
diff --git a/android/team_test.go b/android/team_test.go
new file mode 100644
index 0000000..75b3e9f
--- /dev/null
+++ b/android/team_test.go
@@ -0,0 +1,99 @@
+// Copyright 2024 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 android
+
+import (
+ "testing"
+)
+
+type fakeModuleForTests struct {
+ ModuleBase
+}
+
+func fakeModuleFactory() Module {
+ module := &fakeModuleForTests{}
+ InitAndroidModule(module)
+ return module
+}
+
+func (*fakeModuleForTests) GenerateAndroidBuildActions(ModuleContext) {}
+
+func TestTeam(t *testing.T) {
+ t.Parallel()
+ ctx := GroupFixturePreparers(
+ PrepareForTestWithTeamBuildComponents,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("fake", fakeModuleFactory)
+ }),
+ ).RunTestWithBp(t, `
+ fake {
+ name: "main_test",
+ team: "someteam",
+ }
+ team {
+ name: "someteam",
+ trendy_team_id: "cool_team",
+ }
+
+ team {
+ name: "team2",
+ trendy_team_id: "22222",
+ }
+
+ fake {
+ name: "tool",
+ team: "team2",
+ }
+ `)
+
+ // Assert the rule from GenerateAndroidBuildActions exists.
+ m := ctx.ModuleForTests("main_test", "")
+ AssertStringEquals(t, "msg", m.Module().base().Team(), "someteam")
+ m = ctx.ModuleForTests("tool", "")
+ AssertStringEquals(t, "msg", m.Module().base().Team(), "team2")
+}
+
+func TestMissingTeamFails(t *testing.T) {
+ t.Parallel()
+ GroupFixturePreparers(
+ PrepareForTestWithTeamBuildComponents,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("fake", fakeModuleFactory)
+ }),
+ ).
+ ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern("depends on undefined module \"ring-bearer")).
+ RunTestWithBp(t, `
+ fake {
+ name: "you_cannot_pass",
+ team: "ring-bearer",
+ }
+ `)
+}
+
+func TestPackageBadTeamNameFails(t *testing.T) {
+ t.Parallel()
+ GroupFixturePreparers(
+ PrepareForTestWithTeamBuildComponents,
+ PrepareForTestWithPackageModule,
+ FixtureRegisterWithContext(func(ctx RegistrationContext) {
+ ctx.RegisterModuleType("fake", fakeModuleFactory)
+ }),
+ ).
+ ExtendWithErrorHandler(FixtureExpectsAtLeastOneErrorMatchingPattern("depends on undefined module \"ring-bearer")).
+ RunTestWithBp(t, `
+ package {
+ default_team: "ring-bearer",
+ }
+ `)
+}
diff --git a/android/test_asserts.go b/android/test_asserts.go
index 3a2cb1a..c33ade5 100644
--- a/android/test_asserts.go
+++ b/android/test_asserts.go
@@ -148,7 +148,7 @@
return
}
if !ok {
- t.Errorf("%s does not match regular expression %s", s, expectedRex)
+ t.Errorf("%s: %s does not match regular expression %s", message, s, expectedRex)
}
}
diff --git a/android/test_config.go b/android/test_config.go
index 2a59d92..a15343a 100644
--- a/android/test_config.go
+++ b/android/test_config.go
@@ -39,11 +39,12 @@
DeviceName: stringPtr("test_device"),
DeviceProduct: stringPtr("test_product"),
Platform_sdk_version: intPtr(30),
+ Platform_sdk_version_or_codename: stringPtr("S"),
Platform_sdk_codename: stringPtr("S"),
Platform_base_sdk_extension_version: intPtr(1),
Platform_version_active_codenames: []string{"S", "Tiramisu"},
- DeviceSystemSdkVersions: []string{"14", "15"},
- Platform_systemsdk_versions: []string{"29", "30"},
+ DeviceSystemSdkVersions: []string{"29", "30", "S"},
+ Platform_systemsdk_versions: []string{"29", "30", "S", "Tiramisu"},
AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
AAPTPreferredConfig: stringPtr("xhdpi"),
AAPTCharacteristics: stringPtr("nosdcard"),
@@ -61,11 +62,7 @@
// passed to PathForSource or PathForModuleSrc.
TestAllowNonExistentPaths: true,
- BazelContext: noopBazelContext{},
- BuildMode: BazelProdMode,
- mixedBuildDisabledModules: make(map[string]struct{}),
- mixedBuildEnabledModules: make(map[string]struct{}),
- bazelForceEnabledModules: make(map[string]struct{}),
+ BuildMode: AnalysisNoBazel,
}
config.deviceConfig = &deviceConfig{
config: config,
diff --git a/android/test_suites.go b/android/test_suites.go
index 63a709f..9ded998 100644
--- a/android/test_suites.go
+++ b/android/test_suites.go
@@ -60,7 +60,7 @@
for _, module := range SortedKeys(files) {
installedPaths = append(installedPaths, files[module]...)
}
- testCasesDir := pathForInstall(ctx, ctx.Config().BuildOS, X86, "testcases", false)
+ testCasesDir := pathForInstall(ctx, ctx.Config().BuildOS, X86, "testcases")
outputFile := PathForOutput(ctx, "packaging", "robolectric-tests.zip")
rule := NewRuleBuilder(pctx, ctx)
@@ -69,7 +69,7 @@
FlagWithArg("-P ", "host/testcases").
FlagWithArg("-C ", testCasesDir.String()).
FlagWithRspFileInputList("-r ", outputFile.ReplaceExtension(ctx, "rsp"), installedPaths.Paths()).
- Flag("-sha256")
+ Flag("-sha256")
rule.Build("robolectric_tests_zip", "robolectric-tests.zip")
return outputFile
diff --git a/android/testing.go b/android/testing.go
index 32357db..7b4411e 100644
--- a/android/testing.go
+++ b/android/testing.go
@@ -183,15 +183,14 @@
type TestContext struct {
*Context
preArch, preDeps, postDeps, finalDeps []RegisterMutatorFunc
- bp2buildPreArch, bp2buildMutators []RegisterMutatorFunc
NameResolver *NameResolver
- // The list of pre-singletons and singletons registered for the test.
- preSingletons, singletons sortableComponents
+ // The list of singletons registered for the test.
+ singletons sortableComponents
- // The order in which the pre-singletons, mutators and singletons will be run in this test
+ // The order in which the mutators and singletons will be run in this test
// context; for debugging.
- preSingletonOrder, mutatorOrder, singletonOrder []string
+ mutatorOrder, singletonOrder []string
}
func (ctx *TestContext) PreArchMutators(f RegisterMutatorFunc) {
@@ -203,7 +202,7 @@
ctx.PreArchMutators(f)
}
-func (ctx *TestContext) ModuleProvider(m blueprint.Module, p blueprint.ProviderKey) interface{} {
+func (ctx *TestContext) moduleProvider(m blueprint.Module, p blueprint.AnyProviderKey) (any, bool) {
return ctx.Context.ModuleProvider(m, p)
}
@@ -219,14 +218,10 @@
ctx.finalDeps = append(ctx.finalDeps, f)
}
-func (ctx *TestContext) RegisterBp2BuildConfig(config Bp2BuildConversionAllowlist) {
- ctx.config.Bp2buildPackageConfig = config
-}
-
-// PreArchBp2BuildMutators adds mutators to be register for converting Android Blueprint modules
-// into Bazel BUILD targets that should run prior to deps and conversion.
-func (ctx *TestContext) PreArchBp2BuildMutators(f RegisterMutatorFunc) {
- ctx.bp2buildPreArch = append(ctx.bp2buildPreArch, f)
+func (ctx *TestContext) OtherModuleProviderAdaptor() OtherModuleProviderContext {
+ return NewOtherModuleProviderAdaptor(func(module blueprint.Module, provider blueprint.AnyProviderKey) (any, bool) {
+ return ctx.moduleProvider(module, provider)
+ })
}
// registeredComponentOrder defines the order in which a sortableComponent type is registered at
@@ -397,9 +392,6 @@
// Used to ensure that this is only created once.
once sync.Once
- // The order of pre-singletons
- preSingletonOrder registeredComponentOrder
-
// The order of mutators
mutatorOrder registeredComponentOrder
@@ -412,9 +404,6 @@
// Only the first call has any effect.
func (s *registrationSorter) populate() {
s.once.Do(func() {
- // Create an ordering from the globally registered pre-singletons.
- s.preSingletonOrder = registeredComponentOrderFromExistingOrder("pre-singleton", preSingletons)
-
// Created an ordering from the globally registered mutators.
globallyRegisteredMutators := collateGloballyRegisteredMutators()
s.mutatorOrder = registeredComponentOrderFromExistingOrder("mutator", globallyRegisteredMutators)
@@ -441,11 +430,6 @@
func (ctx *TestContext) Register() {
globalOrder := globallyRegisteredComponentsOrder()
- // Ensure that the pre-singletons used in the test are in the same order as they are used at
- // runtime.
- globalOrder.preSingletonOrder.enforceOrdering(ctx.preSingletons)
- ctx.preSingletons.registerAll(ctx.Context)
-
mutators := collateRegisteredMutators(ctx.preArch, ctx.preDeps, ctx.postDeps, ctx.finalDeps)
// Ensure that the mutators used in the test are in the same order as they are used at runtime.
globalOrder.mutatorOrder.enforceOrdering(mutators)
@@ -456,17 +440,10 @@
ctx.singletons.registerAll(ctx.Context)
// Save the sorted components order away to make them easy to access while debugging.
- ctx.preSingletonOrder = componentsToNames(preSingletons)
ctx.mutatorOrder = componentsToNames(mutators)
ctx.singletonOrder = componentsToNames(singletons)
}
-// RegisterForBazelConversion prepares a test context for bp2build conversion.
-func (ctx *TestContext) RegisterForBazelConversion() {
- ctx.config.BuildMode = Bp2build
- RegisterMutatorsForBazelConversion(ctx.Context, ctx.bp2buildPreArch)
-}
-
func (ctx *TestContext) ParseFileList(rootDir string, filePaths []string) (deps []string, errs []error) {
// This function adapts the old style ParseFileList calls that are spread throughout the tests
// to the new style that takes a config.
@@ -503,10 +480,6 @@
ctx.singletons = append(ctx.singletons, newSingleton(name, factory, true))
}
-func (ctx *TestContext) RegisterPreSingletonType(name string, factory SingletonFactory) {
- ctx.preSingletons = append(ctx.preSingletons, newPreSingleton(name, factory))
-}
-
// ModuleVariantForTests selects a specific variant of the module with the given
// name by matching the variations map against the variations of each module
// variant. A module variant matches the map if every variation that exists in
@@ -752,7 +725,6 @@
// - Depfile
// - Rspfile
// - RspfileContent
-// - SymlinkOutputs
// - CommandDeps
// - CommandOrderOnly
//
@@ -774,8 +746,6 @@
bparams.Depfile = normalizeWritablePathRelativeToTop(bparams.Depfile)
bparams.Output = normalizeWritablePathRelativeToTop(bparams.Output)
bparams.Outputs = bparams.Outputs.RelativeToTop()
- bparams.SymlinkOutput = normalizeWritablePathRelativeToTop(bparams.SymlinkOutput)
- bparams.SymlinkOutputs = bparams.SymlinkOutputs.RelativeToTop()
bparams.ImplicitOutput = normalizeWritablePathRelativeToTop(bparams.ImplicitOutput)
bparams.ImplicitOutputs = bparams.ImplicitOutputs.RelativeToTop()
bparams.Input = normalizePathRelativeToTop(bparams.Input)
@@ -793,7 +763,6 @@
rparams.Depfile = normalizeStringRelativeToTop(p.config, rparams.Depfile)
rparams.Rspfile = normalizeStringRelativeToTop(p.config, rparams.Rspfile)
rparams.RspfileContent = normalizeStringRelativeToTop(p.config, rparams.RspfileContent)
- rparams.SymlinkOutputs = normalizeStringArrayRelativeToTop(p.config, rparams.SymlinkOutputs)
rparams.CommandDeps = normalizeStringArrayRelativeToTop(p.config, rparams.CommandDeps)
rparams.CommandOrderOnly = normalizeStringArrayRelativeToTop(p.config, rparams.CommandOrderOnly)
@@ -1152,6 +1121,7 @@
}
entriesList := p.AndroidMkEntries()
+ aconfigUpdateAndroidMkEntries(ctx, mod.(Module), &entriesList)
for i, _ := range entriesList {
entriesList[i].fillInEntries(ctx, mod)
}
@@ -1167,6 +1137,7 @@
}
data := p.AndroidMk()
data.fillInData(ctx, mod)
+ aconfigUpdateAndroidMkData(ctx, mod.(Module), &data)
return data
}
@@ -1309,3 +1280,10 @@
func StringsRelativeToTop(config Config, command []string) []string {
return normalizeStringArrayRelativeToTop(config, command)
}
+
+func EnsureListContainsSuffix(t *testing.T, result []string, expected string) {
+ t.Helper()
+ if !SuffixInList(result, expected) {
+ t.Errorf("%q is not found in %v", expected, result)
+ }
+}
diff --git a/android/updatable_modules.go b/android/updatable_modules.go
index 71c76c5..6d0eeb7 100644
--- a/android/updatable_modules.go
+++ b/android/updatable_modules.go
@@ -14,9 +14,9 @@
package android
-// This file contains branch specific constants for building updatable modules.
-// They are stored in a separate file to minimise the potential of merge
-// conflicts between branches when the code from the package is changed.
+// This file contains branch specific constants. They are stored in a separate
+// file to minimise the potential of merge conflicts between branches when
+// the code from the package is changed.
// The default manifest version for all the modules on this branch.
// This version code will be used only if there is no version field in the
@@ -33,4 +33,4 @@
// * AOSP - xx9990000
// * x-mainline-prod - xx9990000
// * master - 990090000
-const DefaultUpdatableModuleVersion = "339990000"
+const DefaultUpdatableModuleVersion = "340090000"
diff --git a/android/util.go b/android/util.go
index 5375373..363b31c 100644
--- a/android/util.go
+++ b/android/util.go
@@ -15,6 +15,7 @@
package android
import (
+ "cmp"
"fmt"
"path/filepath"
"reflect"
@@ -22,6 +23,7 @@
"runtime"
"sort"
"strings"
+ "sync"
)
// CopyOf returns a new slice that has the same contents as s.
@@ -61,17 +63,39 @@
// JoinWithPrefixAndSeparator prepends the prefix to each string in the list and
// returns them joined together with the given separator.
func JoinWithPrefixAndSeparator(strs []string, prefix string, sep string) string {
+ return JoinWithPrefixSuffixAndSeparator(strs, prefix, "", sep)
+}
+
+// JoinWithSuffixAndSeparator appends the suffix to each string in the list and
+// returns them joined together with the given separator.
+func JoinWithSuffixAndSeparator(strs []string, suffix string, sep string) string {
+ return JoinWithPrefixSuffixAndSeparator(strs, "", suffix, sep)
+}
+
+// JoinWithPrefixSuffixAndSeparator appends the prefix/suffix to each string in the list and
+// returns them joined together with the given separator.
+func JoinWithPrefixSuffixAndSeparator(strs []string, prefix, suffix, sep string) string {
if len(strs) == 0 {
return ""
}
+ // Pre-calculate the length of the result
+ length := 0
+ for _, s := range strs {
+ length += len(s)
+ }
+ length += (len(prefix)+len(suffix))*len(strs) + len(sep)*(len(strs)-1)
+
var buf strings.Builder
+ buf.Grow(length)
buf.WriteString(prefix)
buf.WriteString(strs[0])
+ buf.WriteString(suffix)
for i := 1; i < len(strs); i++ {
buf.WriteString(sep)
buf.WriteString(prefix)
buf.WriteString(strs[i])
+ buf.WriteString(suffix)
}
return buf.String()
}
@@ -83,15 +107,8 @@
return SortedKeys(m)
}
-type Ordered interface {
- ~string |
- ~float32 | ~float64 |
- ~int | ~int8 | ~int16 | ~int32 | ~int64 |
- ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr
-}
-
// SortedKeys returns the keys of the given map in the ascending order.
-func SortedKeys[T Ordered, V any](m map[T]V) []T {
+func SortedKeys[T cmp.Ordered, V any](m map[T]V) []T {
if len(m) == 0 {
return nil
}
@@ -569,3 +586,38 @@
}
return "", false
}
+
+func AddToStringSet(set map[string]bool, items []string) {
+ for _, item := range items {
+ set[item] = true
+ }
+}
+
+// SyncMap is a wrapper around sync.Map that provides type safety via generics.
+type SyncMap[K comparable, V any] struct {
+ sync.Map
+}
+
+// Load returns the value stored in the map for a key, or the zero value if no
+// value is present.
+// The ok result indicates whether value was found in the map.
+func (m *SyncMap[K, V]) Load(key K) (value V, ok bool) {
+ v, ok := m.Map.Load(key)
+ if !ok {
+ return *new(V), false
+ }
+ return v.(V), true
+}
+
+// Store sets the value for a key.
+func (m *SyncMap[K, V]) Store(key K, value V) {
+ m.Map.Store(key, value)
+}
+
+// LoadOrStore returns the existing value for the key if present.
+// Otherwise, it stores and returns the given value.
+// The loaded result is true if the value was loaded, false if stored.
+func (m *SyncMap[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) {
+ v, loaded := m.Map.LoadOrStore(key, value)
+ return v.(V), loaded
+}
diff --git a/android/util_test.go b/android/util_test.go
index 20161e5..8e73d83 100644
--- a/android/util_test.go
+++ b/android/util_test.go
@@ -15,6 +15,7 @@
package android
import (
+ "cmp"
"fmt"
"reflect"
"strconv"
@@ -650,7 +651,7 @@
}
}
-func testSortedKeysHelper[K Ordered, V any](t *testing.T, name string, input map[K]V, expected []K) {
+func testSortedKeysHelper[K cmp.Ordered, V any](t *testing.T, name string, input map[K]V, expected []K) {
t.Helper()
t.Run(name, func(t *testing.T) {
actual := SortedKeys(input)
@@ -811,7 +812,7 @@
if !reflect.DeepEqual(slice, testCase.expected) {
t.Errorf("expected %#v, got %#v", testCase.expected, slice)
}
- if slice != nil && unsafe.SliceData(testCase.in) == unsafe.SliceData(slice) {
+ if cap(slice) > 0 && unsafe.SliceData(testCase.in) == unsafe.SliceData(slice) {
t.Errorf("expected slices to have different backing arrays")
}
})
diff --git a/android/variable.go b/android/variable.go
index 524cdf7..a4917c5 100644
--- a/android/variable.go
+++ b/android/variable.go
@@ -20,7 +20,6 @@
"runtime"
"strings"
- "android/soong/android/soongconfig"
"android/soong/bazel"
"github.com/google/blueprint/proptools"
@@ -74,6 +73,7 @@
Cflags []string `android:"arch_variant"`
Shared_libs []string `android:"arch_variant"`
Whole_static_libs []string `android:"arch_variant"`
+ Static_libs []string `android:"arch_variant"`
Exclude_static_libs []string `android:"arch_variant"`
Srcs []string `android:"arch_variant"`
Header_libs []string `android:"arch_variant"`
@@ -224,7 +224,9 @@
DeviceCurrentApiLevelForVendorModules *string `json:",omitempty"`
DeviceSystemSdkVersions []string `json:",omitempty"`
DeviceMaxPageSizeSupported *string `json:",omitempty"`
- DevicePageSizeAgnostic *bool `json:",omitempty"`
+ DeviceNoBionicPageSizeMacro *bool `json:",omitempty"`
+
+ VendorApiLevel *string `json:",omitempty"`
RecoverySnapshotVersion *string `json:",omitempty"`
@@ -418,8 +420,6 @@
ProductPublicSepolicyDirs []string `json:",omitempty"`
ProductPrivateSepolicyDirs []string `json:",omitempty"`
- ProductVndkVersion *string `json:",omitempty"`
-
TargetFSConfigGen []string `json:",omitempty"`
EnforceProductPartitionInterface *bool `json:",omitempty"`
@@ -449,6 +449,7 @@
BuildBrokenVendorPropertyNamespace bool `json:",omitempty"`
BuildBrokenIncorrectPartitionImages bool `json:",omitempty"`
BuildBrokenInputDirModules []string `json:",omitempty"`
+ BuildBrokenDontCheckSystemSdk bool `json:",omitempty"`
BuildWarningBadOptionalUsesLibsAllowlist []string `json:",omitempty"`
@@ -481,9 +482,76 @@
ReleaseAconfigFlagDefaultPermission string `json:",omitempty"`
+ ReleaseDefaultModuleBuildFromSource *bool `json:",omitempty"`
+
KeepVndk *bool `json:",omitempty"`
CheckVendorSeappViolations *bool `json:",omitempty"`
+
+ // PartitionVarsForBazelMigrationOnlyDoNotUse are extra variables that are used to define the
+ // partition images. They should not be read from soong modules.
+ PartitionVarsForBazelMigrationOnlyDoNotUse PartitionVariables `json:",omitempty"`
+
+ BuildFlags map[string]string `json:",omitempty"`
+
+ BuildFromSourceStub *bool `json:",omitempty"`
+}
+
+type PartitionQualifiedVariablesType struct {
+ BuildingImage bool `json:",omitempty"`
+ BoardErofsCompressor string `json:",omitempty"`
+ BoardErofsCompressHints string `json:",omitempty"`
+ BoardErofsPclusterSize string `json:",omitempty"`
+ BoardExtfsInodeCount string `json:",omitempty"`
+ BoardExtfsRsvPct string `json:",omitempty"`
+ BoardF2fsSloadCompressFlags string `json:",omitempty"`
+ BoardFileSystemCompress string `json:",omitempty"`
+ BoardFileSystemType string `json:",omitempty"`
+ BoardJournalSize string `json:",omitempty"`
+ BoardPartitionReservedSize string `json:",omitempty"`
+ BoardPartitionSize string `json:",omitempty"`
+ BoardSquashfsBlockSize string `json:",omitempty"`
+ BoardSquashfsCompressor string `json:",omitempty"`
+ BoardSquashfsCompressorOpt string `json:",omitempty"`
+ BoardSquashfsDisable4kAlign string `json:",omitempty"`
+ ProductBaseFsPath string `json:",omitempty"`
+ ProductHeadroom string `json:",omitempty"`
+ ProductVerityPartition string `json:",omitempty"`
+
+ BoardAvbAddHashtreeFooterArgs string `json:",omitempty"`
+ BoardAvbKeyPath string `json:",omitempty"`
+ BoardAvbAlgorithm string `json:",omitempty"`
+ BoardAvbRollbackIndex string `json:",omitempty"`
+ BoardAvbRollbackIndexLocation string `json:",omitempty"`
+}
+
+type PartitionVariables struct {
+ ProductDirectory string `json:",omitempty"`
+ PartitionQualifiedVariables map[string]PartitionQualifiedVariablesType
+ TargetUserimagesUseExt2 bool `json:",omitempty"`
+ TargetUserimagesUseExt3 bool `json:",omitempty"`
+ TargetUserimagesUseExt4 bool `json:",omitempty"`
+
+ TargetUserimagesSparseExtDisabled bool `json:",omitempty"`
+ TargetUserimagesSparseErofsDisabled bool `json:",omitempty"`
+ TargetUserimagesSparseSquashfsDisabled bool `json:",omitempty"`
+ TargetUserimagesSparseF2fsDisabled bool `json:",omitempty"`
+
+ BoardErofsCompressor string `json:",omitempty"`
+ BoardErofsCompressorHints string `json:",omitempty"`
+ BoardErofsPclusterSize string `json:",omitempty"`
+ BoardErofsShareDupBlocks string `json:",omitempty"`
+ BoardErofsUseLegacyCompression string `json:",omitempty"`
+ BoardExt4ShareDupBlocks string `json:",omitempty"`
+ BoardFlashLogicalBlockSize string `json:",omitempty"`
+ BoardFlashEraseBlockSize string `json:",omitempty"`
+ BoardUsesRecoveryAsBoot bool `json:",omitempty"`
+ ProductUseDynamicPartitionSize bool `json:",omitempty"`
+ CopyImagesForTargetFilesZip bool `json:",omitempty"`
+
+ BoardAvbEnable bool `json:",omitempty"`
+
+ ProductPackages []string `json:",omitempty"`
}
func boolPtr(v bool) *bool {
@@ -511,20 +579,20 @@
Platform_version_all_preview_codenames: []string{"S"},
Platform_vndk_version: stringPtr("S"),
- HostArch: stringPtr("x86_64"),
- HostSecondaryArch: stringPtr("x86"),
- DeviceName: stringPtr("generic_arm64"),
- DeviceProduct: stringPtr("aosp_arm-eng"),
- DeviceArch: stringPtr("arm64"),
- DeviceArchVariant: stringPtr("armv8-a"),
- DeviceCpuVariant: stringPtr("generic"),
- DeviceAbi: []string{"arm64-v8a"},
- DeviceSecondaryArch: stringPtr("arm"),
- DeviceSecondaryArchVariant: stringPtr("armv8-a"),
- DeviceSecondaryCpuVariant: stringPtr("generic"),
- DeviceSecondaryAbi: []string{"armeabi-v7a", "armeabi"},
- DeviceMaxPageSizeSupported: stringPtr("4096"),
- DevicePageSizeAgnostic: boolPtr(false),
+ HostArch: stringPtr("x86_64"),
+ HostSecondaryArch: stringPtr("x86"),
+ DeviceName: stringPtr("generic_arm64"),
+ DeviceProduct: stringPtr("aosp_arm-eng"),
+ DeviceArch: stringPtr("arm64"),
+ DeviceArchVariant: stringPtr("armv8-a"),
+ DeviceCpuVariant: stringPtr("generic"),
+ DeviceAbi: []string{"arm64-v8a"},
+ DeviceSecondaryArch: stringPtr("arm"),
+ DeviceSecondaryArchVariant: stringPtr("armv8-a"),
+ DeviceSecondaryCpuVariant: stringPtr("generic"),
+ DeviceSecondaryAbi: []string{"armeabi-v7a", "armeabi"},
+ DeviceMaxPageSizeSupported: stringPtr("4096"),
+ DeviceNoBionicPageSizeMacro: boolPtr(false),
AAPTConfig: []string{"normal", "large", "xlarge", "hdpi", "xhdpi", "xxhdpi"},
AAPTPreferredConfig: stringPtr("xhdpi"),
@@ -549,6 +617,14 @@
}
}
+func (this *ProductVariables) GetBuildFlagBool(flag string) bool {
+ val, ok := this.BuildFlags[flag]
+ if !ok {
+ return false
+ }
+ return val == "true"
+}
+
// ProductConfigContext requires the access to the Module to get product config properties.
type ProductConfigContext interface {
Module() Module
@@ -667,40 +743,6 @@
// property, like ["-DDEFINES"] for cflags.
type ProductConfigProperties map[string]map[ProductConfigOrSoongConfigProperty]interface{}
-// ProductVariableProperties returns a ProductConfigProperties containing only the properties which
-// have been set for the given module.
-func ProductVariableProperties(ctx ArchVariantContext, module Module) ProductConfigProperties {
- moduleBase := module.base()
-
- productConfigProperties := ProductConfigProperties{}
-
- if moduleBase.variableProperties != nil {
- productVariablesProperty := proptools.FieldNameForProperty("product_variables")
- if moduleBase.ArchSpecific() {
- for /* axis */ _, configToProps := range moduleBase.GetArchVariantProperties(ctx, moduleBase.variableProperties) {
- for config, props := range configToProps {
- variableValues := reflect.ValueOf(props).Elem().FieldByName(productVariablesProperty)
- productConfigProperties.AddProductConfigProperties(variableValues, config)
- }
- }
- } else {
- variableValues := reflect.ValueOf(moduleBase.variableProperties).Elem().FieldByName(productVariablesProperty)
- productConfigProperties.AddProductConfigProperties(variableValues, "")
- }
- }
-
- if m, ok := module.(Bazelable); ok && m.namespacedVariableProps() != nil {
- for namespace, namespacedVariableProps := range m.namespacedVariableProps() {
- for _, namespacedVariableProp := range namespacedVariableProps {
- variableValues := reflect.ValueOf(namespacedVariableProp).Elem().FieldByName(soongconfig.SoongConfigProperty)
- productConfigProperties.AddSoongConfigProperties(namespace, variableValues)
- }
- }
- }
-
- return productConfigProperties
-}
-
func (p *ProductConfigProperties) AddProductConfigProperty(
propertyName, productVariableName, arch string, propertyValue interface{}) {
@@ -750,10 +792,6 @@
}
}
-var (
- conditionsDefaultField string = proptools.FieldNameForProperty(bazel.ConditionsDefaultConfigKey)
-)
-
// maybeExtractConfigVarProp attempts to read this value as a config var struct
// wrapped by interfaces and ptrs. If it's not the right type, the second return
// value is false.
@@ -820,7 +858,7 @@
}
-func (productConfigProperties *ProductConfigProperties) AddSoongConfigProperties(namespace string, soongConfigVariablesStruct reflect.Value) {
+func (productConfigProperties *ProductConfigProperties) AddSoongConfigProperties(namespace string, soongConfigVariablesStruct reflect.Value) error {
//
// Example of soong_config_variables:
//
@@ -917,7 +955,7 @@
if propertyName == "Target" {
productConfigProperties.AddSoongConfigPropertiesFromTargetStruct(namespace, variableName, proptools.PropertyNameForField(propertyOrValueName), field.Field(k))
} else if propertyName == "Arch" || propertyName == "Multilib" {
- panic("Arch/Multilib are not currently supported in soong config variable structs")
+ return fmt.Errorf("Arch/Multilib are not currently supported in soong config variable structs")
} else {
productConfigProperties.AddSoongConfigProperty(propertyName, namespace, variableName, proptools.PropertyNameForField(propertyOrValueName), "", field.Field(k).Interface())
}
@@ -928,13 +966,14 @@
if propertyOrValueName == "Target" {
productConfigProperties.AddSoongConfigPropertiesFromTargetStruct(namespace, variableName, "", propertyOrStruct)
} else if propertyOrValueName == "Arch" || propertyOrValueName == "Multilib" {
- panic("Arch/Multilib are not currently supported in soong config variable structs")
+ return fmt.Errorf("Arch/Multilib are not currently supported in soong config variable structs")
} else {
productConfigProperties.AddSoongConfigProperty(propertyOrValueName, namespace, variableName, "", "", propertyOrStruct.Interface())
}
}
}
}
+ return nil
}
func (productConfigProperties *ProductConfigProperties) AddSoongConfigPropertiesFromTargetStruct(namespace, soongConfigVariableName string, soongConfigVariableValue string, targetStruct reflect.Value) {
diff --git a/android_sdk/sdk_repo_host.go b/android_sdk/sdk_repo_host.go
index 7212a07..373e883 100644
--- a/android_sdk/sdk_repo_host.go
+++ b/android_sdk/sdk_repo_host.go
@@ -165,10 +165,11 @@
Flag(dir.Join(ctx, strip).String())
}
} else {
+ llvmObjCopy := config.ClangPath(ctx, "bin/llvm-objcopy")
llvmStrip := config.ClangPath(ctx, "bin/llvm-strip")
llvmLib := config.ClangPath(ctx, "lib/x86_64-unknown-linux-gnu/libc++.so")
for _, strip := range s.properties.Strip_files {
- cmd := builder.Command().Tool(llvmStrip).ImplicitTool(llvmLib)
+ cmd := builder.Command().Tool(llvmStrip).ImplicitTool(llvmLib).ImplicitTool(llvmObjCopy)
if !ctx.Windows() {
cmd.Flag("-x")
}
diff --git a/androidmk/androidmk/android.go b/androidmk/androidmk/android.go
index 954f8d0..9d61e1c 100644
--- a/androidmk/androidmk/android.go
+++ b/androidmk/androidmk/android.go
@@ -64,6 +64,8 @@
"LOCAL_SANITIZE_DIAG": sanitize("diag."),
"LOCAL_STRIP_MODULE": strip(),
"LOCAL_CFLAGS": cflags,
+ "LOCAL_PROTOC_FLAGS": protoLocalIncludeDirs,
+ "LOCAL_PROTO_JAVA_OUTPUT_PARAMS": protoOutputParams,
"LOCAL_UNINSTALLABLE_MODULE": invert("installable"),
"LOCAL_PROGUARD_ENABLED": proguardEnabled,
"LOCAL_MODULE_PATH": prebuiltModulePath,
@@ -86,6 +88,7 @@
"LOCAL_ANNOTATION_PROCESSOR_CLASSES": skip, // Soong gets the processor classes from the plugin
"LOCAL_CTS_TEST_PACKAGE": skip, // Obsolete
+ "LOCAL_XTS_TEST_PACKAGE": skip, // Obsolete
"LOCAL_JACK_ENABLED": skip, // Obselete
"LOCAL_JACK_FLAGS": skip, // Obselete
}
@@ -106,6 +109,7 @@
"LOCAL_ARM_MODE_HACK": "instruction_set",
"LOCAL_SDK_VERSION": "sdk_version",
"LOCAL_MIN_SDK_VERSION": "min_sdk_version",
+ "LOCAL_TARGET_SDK_VERSION": "target_sdk_version",
"LOCAL_NDK_STL_VARIANT": "stl",
"LOCAL_JAR_MANIFEST": "manifest",
"LOCAL_CERTIFICATE": "certificate",
@@ -758,6 +762,27 @@
return includeVariableNow(bpVariable{"cflags", bpparser.ListType}, ctx)
}
+func protoOutputParams(ctx variableAssignmentContext) error {
+ // The Soong replacement for LOCAL_PROTO_JAVA_OUTPUT_PARAMS doesn't need ","
+ ctx.mkvalue = ctx.mkvalue.Clone()
+ ctx.mkvalue.ReplaceLiteral(`, `, ` `)
+ return includeVariableNow(bpVariable{"proto.output_params", bpparser.ListType}, ctx)
+}
+
+func protoLocalIncludeDirs(ctx variableAssignmentContext) error {
+ // The Soong replacement for LOCAL_PROTOC_FLAGS includes "--proto_path=$(LOCAL_PATH)/..."
+ ctx.mkvalue = ctx.mkvalue.Clone()
+ if len(ctx.mkvalue.Strings) >= 1 && strings.Contains(ctx.mkvalue.Strings[0], "--proto_path=") {
+ ctx.mkvalue.Strings[0] = strings.Replace(ctx.mkvalue.Strings[0], "--proto_path=", "", 1)
+ paths, err := localizePaths(ctx)
+ if err == nil {
+ err = setVariable(ctx.file, ctx.append, ctx.prefix, "proto.local_include_dirs", paths, true)
+ }
+ return err
+ }
+ return fmt.Errorf("Currently LOCAL_PROTOC_FLAGS only support with value '--proto_path=$(LOCAL_PATH)/...'")
+}
+
func proguardEnabled(ctx variableAssignmentContext) error {
val, err := makeVariableToBlueprint(ctx.file, ctx.mkvalue, bpparser.ListType)
if err != nil {
diff --git a/androidmk/androidmk/androidmk_test.go b/androidmk/androidmk/androidmk_test.go
index afde68b..460f1ff 100644
--- a/androidmk/androidmk/androidmk_test.go
+++ b/androidmk/androidmk/androidmk_test.go
@@ -823,6 +823,26 @@
`,
},
{
+ desc: "IGNORE_LOCAL_XTS_TEST_PACKAGE",
+ in: `
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := FooTest
+LOCAL_COMPATIBILITY_SUITE := cts
+LOCAL_XTS_TEST_PACKAGE := foo.bar
+LOCAL_COMPATIBILITY_SUPPORT_FILES := file1
+include $(BUILD_CTS_PACKAGE)
+`,
+ expected: `
+android_test {
+ name: "FooTest",
+ defaults: ["cts_defaults"],
+ test_suites: ["cts"],
+
+ data: ["file1"],
+}
+`,
+ },
+ {
desc: "BUILD_CTS_*_JAVA_LIBRARY",
in: `
include $(CLEAR_VARS)
@@ -1450,6 +1470,7 @@
LOCAL_PRODUCT_MODULE := true
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_SDK_VERSION := current
+LOCAL_TARGET_SDK_VERSION := target_version
LOCAL_RRO_THEME := FooTheme
include $(BUILD_RRO_PACKAGE)
@@ -1460,6 +1481,7 @@
product_specific: true,
sdk_version: "current",
+ target_sdk_version: "target_version",
theme: "FooTheme",
}
@@ -1705,9 +1727,34 @@
}
`,
},
+ {
+ desc: "LOCAL_PROTO_JAVA_OUTPUT_PARAMS",
+ in: `
+include $(CLEAR_VARS)
+LOCAL_MODULE := foo
+LOCAL_PROTO_JAVA_OUTPUT_PARAMS := enum_style=java, parcelable_messages=true
+LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/protos
+include $(BUILD_PACKAGE)
+ `,
+ expected: `
+android_app {
+ name: "foo",
+ proto: {
+ output_params: [
+ "enum_style=java",
+ "parcelable_messages=true",
+ ],
+ local_include_dirs: ["protos"],
+ },
+}
+`,
+ },
}
func TestEndToEnd(t *testing.T) {
+ // Skip checking Android.mk path with cleaning "ANDROID_BUILD_TOP"
+ t.Setenv("ANDROID_BUILD_TOP", "")
+
for i, test := range testCases {
expected, err := bpfix.Reformat(test.expected)
if err != nil {
diff --git a/apex/Android.bp b/apex/Android.bp
index 0791497..27017ae 100644
--- a/apex/Android.bp
+++ b/apex/Android.bp
@@ -8,8 +8,9 @@
deps: [
"blueprint",
"soong",
+ "soong-aconfig",
+ "soong-aconfig-codegen",
"soong-android",
- "soong-bazel",
"soong-bpf",
"soong-cc",
"soong-filesystem",
@@ -26,7 +27,6 @@
"apex_sdk_member.go",
"apex_singleton.go",
"builder.go",
- "bp2build.go",
"deapexer.go",
"key.go",
"prebuilt.go",
diff --git a/apex/androidmk.go b/apex/androidmk.go
index 2f5d8d4..619be8d 100644
--- a/apex/androidmk.go
+++ b/apex/androidmk.go
@@ -124,6 +124,10 @@
pathForSymbol := filepath.Join("$(PRODUCT_OUT)", "apex", apexBundleName, fi.installDir)
modulePath := pathForSymbol
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", modulePath)
+ // AconfigUpdateAndroidMkData may have added elements to Extra. Process them here.
+ for _, extra := range apexAndroidMkData.Extra {
+ extra(w, fi.builtFile)
+ }
// For non-flattend APEXes, the merged notice file is attached to the APEX itself.
// We don't need to have notice file for the individual modules in it. Otherwise,
@@ -139,9 +143,6 @@
archStr := fi.module.Target().Arch.ArchType.String()
fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", archStr)
}
- } else if fi.isBazelPrebuilt && fi.arch != "" {
- // This apexFile comes from Bazel
- fmt.Fprintln(w, "LOCAL_MODULE_TARGET_ARCH :=", fi.arch)
}
if fi.jacocoReportClassesFile != nil {
fmt.Fprintln(w, "LOCAL_SOONG_JACOCO_REPORT_CLASSES_JAR :=", fi.jacocoReportClassesFile.String())
@@ -185,21 +186,17 @@
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_android_app_set.mk")
case nativeSharedLib, nativeExecutable, nativeTest:
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", fi.stem())
- if fi.isBazelPrebuilt {
- fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", fi.unstrippedBuiltFile)
- } else {
- if ccMod, ok := fi.module.(*cc.Module); ok {
- if ccMod.UnstrippedOutputFile() != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", ccMod.UnstrippedOutputFile().String())
- }
- ccMod.AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
- if ccMod.CoverageOutputFile().Valid() {
- fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", ccMod.CoverageOutputFile().String())
- }
- } else if rustMod, ok := fi.module.(*rust.Module); ok {
- if rustMod.UnstrippedOutputFile() != nil {
- fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", rustMod.UnstrippedOutputFile().String())
- }
+ if ccMod, ok := fi.module.(*cc.Module); ok {
+ if ccMod.UnstrippedOutputFile() != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", ccMod.UnstrippedOutputFile().String())
+ }
+ ccMod.AndroidMkWriteAdditionalDependenciesForSourceAbiDiff(w)
+ if ccMod.CoverageOutputFile().Valid() {
+ fmt.Fprintln(w, "LOCAL_PREBUILT_COVERAGE_ARCHIVE :=", ccMod.CoverageOutputFile().String())
+ }
+ } else if rustMod, ok := fi.module.(*rust.Module); ok {
+ if rustMod.UnstrippedOutputFile() != nil {
+ fmt.Fprintln(w, "LOCAL_SOONG_UNSTRIPPED_BINARY :=", rustMod.UnstrippedOutputFile().String())
}
}
fmt.Fprintln(w, "include $(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk")
@@ -236,6 +233,7 @@
func (a *apexBundle) androidMkForType() android.AndroidMkData {
return android.AndroidMkData{
+ // While we do not provide a value for `Extra`, AconfigUpdateAndroidMkData may add some, which we must honor.
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
moduleNames := []string{}
if a.installable() {
@@ -245,7 +243,6 @@
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS) # apex.apexBundle")
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
fmt.Fprintln(w, "LOCAL_MODULE :=", name)
- data.Entries.WriteLicenseVariables(w)
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC") // do we need a new class?
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", a.outputFile.String())
fmt.Fprintln(w, "LOCAL_MODULE_PATH :=", a.installDir.String())
@@ -260,6 +257,7 @@
fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_PAIRS :=", a.outputFile.String()+":"+a.installedFile.String())
fmt.Fprintln(w, "LOCAL_SOONG_INSTALL_SYMLINKS := ", strings.Join(a.compatSymlinks.Strings(), " "))
}
+ fmt.Fprintln(w, "LOCAL_APEX_KEY_PATH := ", a.apexKeysPath.String())
// Because apex writes .mk with Custom(), we need to write manually some common properties
// which are available via data.Entries
@@ -276,6 +274,10 @@
android.AndroidMkEmitAssignList(w, "LOCAL_OVERRIDES_MODULES", a.overridableProperties.Overrides)
a.writeRequiredModules(w, moduleNames)
+ // AconfigUpdateAndroidMkData may have added elements to Extra. Process them here.
+ for _, extra := range data.Extra {
+ extra(w, a.outputFile)
+ }
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
fmt.Fprintln(w, "ALL_MODULES.$(my_register_name).BUNDLE :=", a.bundleModuleFile.String())
diff --git a/apex/apex.go b/apex/apex.go
index a116b85..276ac80 100644
--- a/apex/apex.go
+++ b/apex/apex.go
@@ -24,13 +24,10 @@
"sort"
"strings"
- "android/soong/bazel/cquery"
-
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel"
"android/soong/bpf"
"android/soong/cc"
prebuilt_etc "android/soong/etc"
@@ -135,6 +132,11 @@
// List of filesystem images that are embedded inside this APEX bundle.
Filesystems []string
+ // List of module names which we don't want to add as transitive deps. This can be used as
+ // a workaround when the current implementation collects more than necessary. For example,
+ // Rust binaries with prefer_rlib:true add unnecessary dependencies.
+ Unwanted_transitive_deps []string
+
// The minimum SDK version that this APEX must support at minimum. This is usually set to
// the SDK version that the APEX was first introduced.
Min_sdk_version *string
@@ -233,6 +235,9 @@
// List of filesystem images that are embedded inside this APEX bundle.
Filesystems []string
+ // List of prebuilt_etcs that are embedded inside this APEX bundle.
+ Prebuilts []string
+
// List of native libraries to exclude from this APEX.
Exclude_native_shared_libs []string
@@ -250,6 +255,9 @@
// List of filesystem images to exclude from this APEX bundle.
Exclude_filesystems []string
+
+ // List of prebuilt_etcs to exclude from this APEX bundle.
+ Exclude_prebuilts []string
}
// Merge combines another ApexNativeDependencies into this one
@@ -260,6 +268,7 @@
a.Binaries = append(a.Binaries, b.Binaries...)
a.Tests = append(a.Tests, b.Tests...)
a.Filesystems = append(a.Filesystems, b.Filesystems...)
+ a.Prebuilts = append(a.Prebuilts, b.Prebuilts...)
a.Exclude_native_shared_libs = append(a.Exclude_native_shared_libs, b.Exclude_native_shared_libs...)
a.Exclude_jni_libs = append(a.Exclude_jni_libs, b.Exclude_jni_libs...)
@@ -267,6 +276,7 @@
a.Exclude_binaries = append(a.Exclude_binaries, b.Exclude_binaries...)
a.Exclude_tests = append(a.Exclude_tests, b.Exclude_tests...)
a.Exclude_filesystems = append(a.Exclude_filesystems, b.Exclude_filesystems...)
+ a.Exclude_prebuilts = append(a.Exclude_prebuilts, b.Exclude_prebuilts...)
}
type apexMultilibProperties struct {
@@ -383,7 +393,6 @@
android.ModuleBase
android.DefaultableModuleBase
android.OverridableModuleBase
- android.BazelModuleBase
multitree.ExportableModuleBase
// Properties
@@ -454,6 +463,9 @@
// Path where this APEX was installed.
installedFile android.InstallPath
+ // fragment for this apex for apexkeys.txt
+ apexKeysPath android.WritablePath
+
// Installed locations of symlinks for backward compatibility.
compatSymlinks android.InstallPaths
@@ -475,8 +487,10 @@
nativeApisBackedByModuleFile android.ModuleOutPath
javaApisUsedByModuleFile android.ModuleOutPath
- // Collect the module directory for IDE info in java/jdeps.go.
- modulePaths []string
+ aconfigFiles []android.Path
+
+ // Single aconfig "cache file" merged from this module and all dependencies.
+ mergedAconfigFiles map[string]android.Paths
}
// apexFileClass represents a type of file that can be included in APEX.
@@ -539,10 +553,6 @@
multilib string
- isBazelPrebuilt bool
- unstrippedBuiltFile android.Path
- arch string
-
// TODO(jiyong): remove this
module android.Module
}
@@ -712,6 +722,8 @@
android.RemoveListFromList(nativeModules.Rust_dyn_libs, nativeModules.Exclude_rust_dyn_libs)...)
ctx.AddFarVariationDependencies(target.Variations(), fsTag,
android.RemoveListFromList(nativeModules.Filesystems, nativeModules.Exclude_filesystems)...)
+ ctx.AddFarVariationDependencies(target.Variations(), prebuiltTag,
+ android.RemoveListFromList(nativeModules.Prebuilts, nativeModules.Exclude_prebuilts)...)
}
func (a *apexBundle) combineProperties(ctx android.BottomUpMutatorContext) {
@@ -720,7 +732,7 @@
// getImageVariationPair returns a pair for the image variation name as its
// prefix and suffix. The prefix indicates whether it's core/vendor/product and the
-// suffix indicates the vndk version when it's vendor or product.
+// suffix indicates the vndk version for vendor/product if vndk is enabled.
// getImageVariation can simply join the result of this function to get the
// image variation name.
func (a *apexBundle) getImageVariationPair(deviceConfig android.DeviceConfig) (string, string) {
@@ -728,25 +740,28 @@
return cc.VendorVariationPrefix, a.vndkVersion(deviceConfig)
}
- var prefix string
- var vndkVersion string
+ prefix := android.CoreVariation
+ vndkVersion := ""
if deviceConfig.VndkVersion() != "" {
if a.SocSpecific() || a.DeviceSpecific() {
prefix = cc.VendorVariationPrefix
vndkVersion = deviceConfig.VndkVersion()
} else if a.ProductSpecific() {
prefix = cc.ProductVariationPrefix
- vndkVersion = deviceConfig.ProductVndkVersion()
+ vndkVersion = deviceConfig.PlatformVndkVersion()
+ }
+ } else {
+ if a.SocSpecific() || a.DeviceSpecific() {
+ prefix = cc.VendorVariation
+ } else if a.ProductSpecific() {
+ prefix = cc.ProductVariation
}
}
if vndkVersion == "current" {
vndkVersion = deviceConfig.PlatformVndkVersion()
}
- if vndkVersion != "" {
- return prefix, vndkVersion
- }
- return android.CoreVariation, "" // The usual case
+ return prefix, vndkVersion
}
// getImageVariation returns the image variant name for this apexBundle. In most cases, it's simply
@@ -912,13 +927,7 @@
ProvidedLibs []string
}
-var DCLAInfoProvider = blueprint.NewMutatorProvider(DCLAInfo{}, "apex_info")
-
-type ApexBundleInfo struct {
- Contents *android.ApexContents
-}
-
-var ApexBundleInfoProvider = blueprint.NewMutatorProvider(ApexBundleInfo{}, "apex_info")
+var DCLAInfoProvider = blueprint.NewMutatorProvider[DCLAInfo]("apex_info")
var _ ApexInfoMutator = (*apexBundle)(nil)
@@ -1020,7 +1029,7 @@
// The membership information is saved for later access
apexContents := android.NewApexContents(contents)
- mctx.SetProvider(ApexBundleInfoProvider, ApexBundleInfo{
+ android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{
Contents: apexContents,
})
@@ -1058,7 +1067,7 @@
})
if a.dynamic_common_lib_apex() {
- mctx.SetProvider(DCLAInfoProvider, DCLAInfo{
+ android.SetProvider(mctx, DCLAInfoProvider, DCLAInfo{
ProvidedLibs: a.properties.Native_shared_libs,
})
}
@@ -1137,15 +1146,42 @@
// Skip these mainline modules for now
var (
skipStrictUpdatabilityLintAllowlist = []string{
+ // go/keep-sorted start
+ "PackageManagerTestApex",
+ "com.android.adservices",
+ "com.android.appsearch",
"com.android.art",
"com.android.art.debug",
+ "com.android.btservices",
+ "com.android.cellbroadcast",
+ "com.android.configinfrastructure",
"com.android.conscrypt",
+ "com.android.extservices",
+ "com.android.extservices_tplus",
+ "com.android.healthfitness",
+ "com.android.ipsec",
"com.android.media",
- // test apexes
+ "com.android.mediaprovider",
+ "com.android.ondevicepersonalization",
+ "com.android.os.statsd",
+ "com.android.permission",
+ "com.android.rkpd",
+ "com.android.scheduling",
+ "com.android.tethering",
+ "com.android.uwb",
+ "com.android.wifi",
"test_com.android.art",
+ "test_com.android.cellbroadcast",
"test_com.android.conscrypt",
+ "test_com.android.extservices",
+ "test_com.android.ipsec",
"test_com.android.media",
+ "test_com.android.mediaprovider",
+ "test_com.android.os.statsd",
+ "test_com.android.permission",
+ "test_com.android.wifi",
"test_jitzygote_com.android.art",
+ // go/keep-sorted end
}
// TODO: b/215736885 Remove this list
@@ -1201,10 +1237,10 @@
if _, ok := mctx.Module().(android.ApexModule); ok {
var contents []*android.ApexContents
for _, testFor := range mctx.GetDirectDepsWithTag(testForTag) {
- abInfo := mctx.OtherModuleProvider(testFor, ApexBundleInfoProvider).(ApexBundleInfo)
+ abInfo, _ := android.OtherModuleProvider(mctx, testFor, android.ApexBundleInfoProvider)
contents = append(contents, abInfo.Contents)
}
- mctx.SetProvider(android.ApexTestForInfoProvider, android.ApexTestForInfo{
+ android.SetProvider(mctx, android.ApexTestForInfoProvider, android.ApexTestForInfo{
ApexContents: contents,
})
}
@@ -1376,7 +1412,7 @@
var _ cc.Coverage = (*apexBundle)(nil)
// Implements cc.Coverage
-func (a *apexBundle) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool {
+func (a *apexBundle) IsNativeCoverageNeeded(ctx android.IncomingTransitionContext) bool {
return ctx.DeviceConfig().NativeCoverageEnabled()
}
@@ -1465,7 +1501,7 @@
panic(fmt.Errorf("expected exactly at most one dcla dependency, got %d", len(dclaModules)))
}
if len(dclaModules) > 0 {
- DCLAInfo := ctx.OtherModuleProvider(dclaModules[0], DCLAInfoProvider).(DCLAInfo)
+ DCLAInfo, _ := android.OtherModuleProvider(ctx, dclaModules[0], DCLAInfoProvider)
return DCLAInfo.ProvidedLibs
}
return []string{}
@@ -1626,7 +1662,7 @@
type javaModule interface {
android.Module
BaseModuleName() string
- DexJarBuildPath() java.OptionalDexJarPath
+ DexJarBuildPath(ctx android.ModuleErrorfContext) java.OptionalDexJarPath
JacocoReportClassesFile() android.Path
LintDepSets() java.LintDepSets
Stem() string
@@ -1640,7 +1676,7 @@
// apexFileForJavaModule creates an apexFile for a java module's dex implementation jar.
func apexFileForJavaModule(ctx android.BaseModuleContext, module javaModule) apexFile {
- return apexFileForJavaModuleWithFile(ctx, module, module.DexJarBuildPath().PathOrNil())
+ return apexFileForJavaModuleWithFile(ctx, module, module.DexJarBuildPath(ctx).PathOrNil())
}
// apexFileForJavaModuleWithFile creates an apexFile for a java module with the supplied file.
@@ -1783,7 +1819,7 @@
return false
}
- ai := ctx.OtherModuleProvider(child, android.ApexInfoProvider).(android.ApexInfo)
+ ai, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
externalDep := !android.InList(ctx.ModuleName(), ai.InApexVariants)
// Visit actually
@@ -1813,118 +1849,6 @@
}
}
-var _ android.MixedBuildBuildable = (*apexBundle)(nil)
-
-func (a *apexBundle) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
- return true
-}
-
-func (a *apexBundle) QueueBazelCall(ctx android.BaseModuleContext) {
- bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(a.GetBazelLabel(ctx, a), cquery.GetApexInfo, android.GetConfigKey(ctx))
-}
-
-// GetBazelLabel returns the bazel label of this apexBundle, or the label of the
-// override_apex module overriding this apexBundle. An apexBundle can be
-// overridden by different override_apex modules (e.g. Google or Go variants),
-// which is handled by the overrides mutators.
-func (a *apexBundle) GetBazelLabel(ctx android.BazelConversionPathContext, module blueprint.Module) string {
- return a.BazelModuleBase.GetBazelLabel(ctx, a)
-}
-
-func (a *apexBundle) ProcessBazelQueryResponse(ctx android.ModuleContext) {
- if !a.commonBuildActions(ctx) {
- return
- }
-
- a.setPayloadFsType(ctx)
- a.setSystemLibLink(ctx)
- a.compatSymlinks = makeCompatSymlinks(a.BaseModuleName(), ctx)
-
- bazelCtx := ctx.Config().BazelContext
- outputs, err := bazelCtx.GetApexInfo(a.GetBazelLabel(ctx, a), android.GetConfigKey(ctx))
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- return
- }
- a.installDir = android.PathForModuleInstall(ctx, "apex")
-
- // Set the output file to .apex or .capex depending on the compression configuration.
- a.setCompression(ctx)
- if a.isCompressed {
- a.outputApexFile = android.PathForBazelOutRelative(ctx, ctx.ModuleDir(), outputs.SignedCompressedOutput)
- } else {
- a.outputApexFile = android.PathForBazelOutRelative(ctx, ctx.ModuleDir(), outputs.SignedOutput)
- }
- a.outputFile = a.outputApexFile
-
- if len(outputs.TidyFiles) > 0 {
- tidyFiles := android.PathsForBazelOut(ctx, outputs.TidyFiles)
- a.outputFile = android.AttachValidationActions(ctx, a.outputFile, tidyFiles)
- }
-
- // TODO(b/257829940): These are used by the apex_keys_text singleton; would probably be a clearer
- // interface if these were set in a provider rather than the module itself
- a.publicKeyFile = android.PathForBazelOut(ctx, outputs.BundleKeyInfo[0])
- a.privateKeyFile = android.PathForBazelOut(ctx, outputs.BundleKeyInfo[1])
- a.containerCertificateFile = android.PathForBazelOut(ctx, outputs.ContainerKeyInfo[0])
- a.containerPrivateKeyFile = android.PathForBazelOut(ctx, outputs.ContainerKeyInfo[1])
-
- // Ensure ApexMkInfo.install_to_system make module names are installed as
- // part of a bundled build.
- a.makeModulesToInstall = append(a.makeModulesToInstall, outputs.MakeModulesToInstall...)
-
- a.bundleModuleFile = android.PathForBazelOut(ctx, outputs.BundleFile)
- a.nativeApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.SymbolsUsedByApex))
- a.nativeApisBackedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.BackingLibs))
- // TODO(b/239084755): Generate the java api using.xml file from Bazel.
- a.javaApisUsedByModuleFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.JavaSymbolsUsedByApex))
- a.installedFilesFile = android.ModuleOutPath(android.PathForBazelOut(ctx, outputs.InstalledFiles))
- installSuffix := imageApexSuffix
- if a.isCompressed {
- installSuffix = imageCapexSuffix
- }
- a.installedFile = ctx.InstallFile(a.installDir, a.Name()+installSuffix, a.outputFile,
- a.compatSymlinks.Paths()...)
-
- // filesInfo in mixed mode must retrieve all information about the apex's
- // contents completely from the Starlark providers. It should never rely on
- // Android.bp information, as they might not exist for fully migrated
- // dependencies.
- //
- // Prevent accidental writes to filesInfo in the earlier parts Soong by
- // asserting it to be nil.
- if a.filesInfo != nil {
- panic(
- fmt.Errorf("internal error: filesInfo must be nil for an apex handled by Bazel. " +
- "Did something else set filesInfo before this line of code?"))
- }
- for _, f := range outputs.PayloadFilesInfo {
- fileInfo := apexFile{
- isBazelPrebuilt: true,
-
- builtFile: android.PathForBazelOut(ctx, f["built_file"]),
- unstrippedBuiltFile: android.PathForBazelOut(ctx, f["unstripped_built_file"]),
- androidMkModuleName: f["make_module_name"],
- installDir: f["install_dir"],
- class: classes[f["class"]],
- customStem: f["basename"],
- moduleDir: f["package"],
- }
-
- arch := f["arch"]
- fileInfo.arch = arch
- if len(arch) > 0 {
- fileInfo.multilib = "lib32"
- if strings.HasSuffix(arch, "64") {
- fileInfo.multilib = "lib64"
- }
- }
-
- a.filesInfo = append(a.filesInfo, fileInfo)
- }
-}
-
func (a *apexBundle) setCompression(ctx android.ModuleContext) {
if a.testOnlyShouldForceCompression() {
a.isCompressed = true
@@ -1999,11 +1923,23 @@
// if true, raise error on duplicate apexFile
checkDuplicate bool
+
+ // visitor skips these from this list of module names
+ unwantedTransitiveDeps []string
+
+ aconfigFiles []android.Path
}
func (vctx *visitorContext) normalizeFileInfo(mctx android.ModuleContext) {
encountered := make(map[string]apexFile)
for _, f := range vctx.filesInfo {
+ // Skips unwanted transitive deps. This happens, for example, with Rust binaries with prefer_rlib:true.
+ // TODO(b/295593640)
+ // Needs additional verification for the resulting APEX to ensure that skipped artifacts don't make problems.
+ // For example, DT_NEEDED modules should be found within the APEX unless they are marked in `requiredNativeLibs`.
+ if f.transitiveDep && f.module != nil && android.InList(mctx.OtherModuleName(f.module), vctx.unwantedTransitiveDeps) {
+ continue
+ }
dest := filepath.Join(f.installDir, f.builtFile.Base())
if e, ok := encountered[dest]; !ok {
encountered[dest] = f
@@ -2046,11 +1982,19 @@
switch depTag {
case sharedLibTag, jniLibTag:
isJniLib := depTag == jniLibTag
+ propertyName := "native_shared_libs"
+ if isJniLib {
+ propertyName = "jni_libs"
+ }
switch ch := child.(type) {
case *cc.Module:
+ if ch.IsStubs() {
+ ctx.PropertyErrorf(propertyName, "%q is a stub. Remove it from the list.", depName)
+ }
fi := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs)
fi.isJniLib = isJniLib
vctx.filesInfo = append(vctx.filesInfo, fi)
+ addAconfigFiles(vctx, ctx, child)
// Collect the list of stub-providing libs except:
// - VNDK libs are only for vendors
// - bootstrap bionic libs are treated as provided by system
@@ -2062,21 +2006,20 @@
fi := apexFileForRustLibrary(ctx, ch)
fi.isJniLib = isJniLib
vctx.filesInfo = append(vctx.filesInfo, fi)
+ addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
default:
- propertyName := "native_shared_libs"
- if isJniLib {
- propertyName = "jni_libs"
- }
ctx.PropertyErrorf(propertyName, "%q is not a cc_library or cc_library_shared module", depName)
}
case executableTag:
switch ch := child.(type) {
case *cc.Module:
vctx.filesInfo = append(vctx.filesInfo, apexFileForExecutable(ctx, ch))
+ addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
case *rust.Module:
vctx.filesInfo = append(vctx.filesInfo, apexFileForRustExecutable(ctx, ch))
+ addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
default:
ctx.PropertyErrorf("binaries",
@@ -2116,6 +2059,7 @@
return false
}
vctx.filesInfo = append(vctx.filesInfo, af)
+ addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
default:
ctx.PropertyErrorf("java_libs", "%q of type %q is not supported", depName, ctx.OtherModuleType(child))
@@ -2124,6 +2068,7 @@
switch ap := child.(type) {
case *java.AndroidApp:
vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
+ addAconfigFiles(vctx, ctx, child)
return true // track transitive dependencies
case *java.AndroidAppImport:
vctx.filesInfo = append(vctx.filesInfo, apexFilesForAndroidApp(ctx, ap)...)
@@ -2235,13 +2180,13 @@
}
//TODO: b/296491928 Vendor APEX should use libbinder.ndk instead of libbinder once VNDK is fully deprecated.
- if ch.UseVndk() && ctx.Config().IsVndkDeprecated() && child.Name() == "libbinder" {
+ if ch.InVendorOrProduct() && ctx.Config().IsVndkDeprecated() && child.Name() == "libbinder" {
return false
}
af := apexFileForNativeLibrary(ctx, ch, vctx.handleSpecialLibs)
af.transitiveDep = true
- abInfo := ctx.Provider(ApexBundleInfoProvider).(ApexBundleInfo)
+ abInfo, _ := android.ModuleProvider(ctx, android.ApexBundleInfoProvider)
if !abInfo.Contents.DirectlyInApex(depName) && (ch.IsStubs() || ch.HasStubsVariants()) {
// If the dependency is a stubs lib, don't include it in this APEX,
// but make sure that the lib is installed on the device.
@@ -2362,15 +2307,18 @@
return false
}
+func addAconfigFiles(vctx *visitorContext, ctx android.ModuleContext, module blueprint.Module) {
+ dep, _ := android.OtherModuleProvider(ctx, module, android.AconfigTransitiveDeclarationsInfoProvider)
+ if len(dep.AconfigFiles) > 0 && dep.AconfigFiles[ctx.ModuleName()] != nil {
+ vctx.aconfigFiles = append(vctx.aconfigFiles, dep.AconfigFiles[ctx.ModuleName()]...)
+ }
+}
+
func (a *apexBundle) shouldCheckDuplicate(ctx android.ModuleContext) bool {
// TODO(b/263308293) remove this
if a.properties.IsCoverageVariant {
return false
}
- // TODO(b/263308515) remove this
- if a.testApex {
- return false
- }
if ctx.DeviceConfig().DeviceArch() == "" {
return false
}
@@ -2391,14 +2339,13 @@
}
////////////////////////////////////////////////////////////////////////////////////////////
// 2) traverse the dependency tree to collect apexFile structs from them.
- // Collect the module directory for IDE info in java/jdeps.go.
- a.modulePaths = append(a.modulePaths, ctx.ModuleDir())
// TODO(jiyong): do this using WalkPayloadDeps
// TODO(jiyong): make this clean!!!
vctx := visitorContext{
- handleSpecialLibs: !android.Bool(a.properties.Ignore_system_library_special_case),
- checkDuplicate: a.shouldCheckDuplicate(ctx),
+ handleSpecialLibs: !android.Bool(a.properties.Ignore_system_library_special_case),
+ checkDuplicate: a.shouldCheckDuplicate(ctx),
+ unwantedTransitiveDeps: a.properties.Unwanted_transitive_deps,
}
ctx.WalkDepsBlueprint(func(child, parent blueprint.Module) bool { return a.depVisitor(&vctx, ctx, child, parent) })
vctx.normalizeFileInfo(ctx)
@@ -2443,11 +2390,13 @@
return
}
}
+ android.CollectDependencyAconfigFiles(ctx, &a.mergedAconfigFiles)
////////////////////////////////////////////////////////////////////////////////////////////
// 3) some fields in apexBundle struct are configured
a.installDir = android.PathForModuleInstall(ctx, "apex")
a.filesInfo = vctx.filesInfo
+ a.aconfigFiles = android.FirstUniquePaths(vctx.aconfigFiles)
a.setPayloadFsType(ctx)
a.setSystemLibLink(ctx)
@@ -2459,12 +2408,31 @@
a.buildApex(ctx)
a.buildApexDependencyInfo(ctx)
a.buildLintReports(ctx)
+
+ // Set a provider for dexpreopt of bootjars
+ a.provideApexExportsInfo(ctx)
+}
+
+// Set a provider containing information about the jars and .prof provided by the apex
+// Apexes built from source retrieve this information by visiting `bootclasspath_fragments`
+// Used by dex_bootjars to generate the boot image
+func (a *apexBundle) provideApexExportsInfo(ctx android.ModuleContext) {
+ ctx.VisitDirectDepsWithTag(bcpfTag, func(child android.Module) {
+ if info, ok := android.OtherModuleProvider(ctx, child, java.BootclasspathFragmentApexContentInfoProvider); ok {
+ exports := android.ApexExportsInfo{
+ ApexName: a.ApexVariationName(),
+ ProfilePathOnHost: info.ProfilePathOnHost(),
+ LibraryNameToDexJarPathOnHost: info.DexBootJarPathMap(),
+ }
+ android.SetProvider(ctx, android.ApexExportsInfoProvider, exports)
+ }
+ })
}
// apexBootclasspathFragmentFiles returns the list of apexFile structures defining the files that
// the bootclasspath_fragment contributes to the apex.
func apexBootclasspathFragmentFiles(ctx android.ModuleContext, module blueprint.Module) []apexFile {
- bootclasspathFragmentInfo := ctx.OtherModuleProvider(module, java.BootclasspathFragmentApexContentInfoProvider).(java.BootclasspathFragmentApexContentInfo)
+ bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, module, java.BootclasspathFragmentApexContentInfoProvider)
var filesToAdd []apexFile
// Add classpaths.proto config.
@@ -2513,7 +2481,7 @@
// apexClasspathFragmentProtoFile returns *apexFile structure defining the classpath.proto config that
// the module contributes to the apex; or nil if the proto config was not generated.
func apexClasspathFragmentProtoFile(ctx android.ModuleContext, module blueprint.Module) *apexFile {
- info := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo)
+ info, _ := android.OtherModuleProvider(ctx, module, java.ClasspathFragmentProtoContentInfoProvider)
if !info.ClasspathFragmentProtoGenerated {
return nil
}
@@ -2525,7 +2493,7 @@
// apexFileForBootclasspathFragmentContentModule creates an apexFile for a bootclasspath_fragment
// content module, i.e. a library that is part of the bootclasspath.
func apexFileForBootclasspathFragmentContentModule(ctx android.ModuleContext, fragmentModule blueprint.Module, javaModule javaModule) apexFile {
- bootclasspathFragmentInfo := ctx.OtherModuleProvider(fragmentModule, java.BootclasspathFragmentApexContentInfoProvider).(java.BootclasspathFragmentApexContentInfo)
+ bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, fragmentModule, java.BootclasspathFragmentApexContentInfoProvider)
// Get the dexBootJar from the bootclasspath_fragment as that is responsible for performing the
// hidden API encpding.
@@ -2555,7 +2523,6 @@
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
android.InitOverridableModule(module, &module.overridableProperties.Overrides)
- android.InitBazelModule(module)
multitree.InitExportableModule(module)
return module
}
@@ -2583,6 +2550,9 @@
type Defaults struct {
android.ModuleBase
android.DefaultsModuleBase
+
+ // Single aconfig "cache file" merged from this module and all dependencies.
+ mergedAconfigFiles map[string]android.Paths
}
// apex_defaults provides defaultable properties to other apex modules.
@@ -2603,7 +2573,10 @@
type OverrideApex struct {
android.ModuleBase
android.OverrideModuleBase
- android.BazelModuleBase
+}
+
+func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles)
}
func (o *OverrideApex) GenerateAndroidBuildActions(_ android.ModuleContext) {
@@ -2619,104 +2592,9 @@
android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibCommon)
android.InitOverrideModule(m)
- android.InitBazelModule(m)
return m
}
-func (o *OverrideApex) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- if ctx.ModuleType() != "override_apex" {
- return
- }
-
- baseApexModuleName := o.OverrideModuleBase.GetOverriddenModuleName()
- baseModule, baseApexExists := ctx.ModuleFromName(baseApexModuleName)
- if !baseApexExists {
- panic(fmt.Errorf("Base apex module doesn't exist: %s", baseApexModuleName))
- }
-
- a, baseModuleIsApex := baseModule.(*apexBundle)
- if !baseModuleIsApex {
- panic(fmt.Errorf("Base module is not apex module: %s", baseApexModuleName))
- }
- attrs, props, commonAttrs := convertWithBp2build(a, ctx)
-
- // We just want the name, not module reference.
- baseApexName := strings.TrimPrefix(baseApexModuleName, ":")
- attrs.Base_apex_name = &baseApexName
-
- for _, p := range o.GetProperties() {
- overridableProperties, ok := p.(*overridableProperties)
- if !ok {
- continue
- }
-
- // Manifest is either empty or a file in the directory of base APEX and is not overridable.
- // After it is converted in convertWithBp2build(baseApex, ctx),
- // the attrs.Manifest.Value.Label is the file path relative to the directory
- // of base apex. So the following code converts it to a label that looks like
- // <package of base apex>:<path of manifest file> if base apex and override
- // apex are not in the same package.
- baseApexPackage := ctx.OtherModuleDir(a)
- overrideApexPackage := ctx.ModuleDir()
- if baseApexPackage != overrideApexPackage {
- attrs.Manifest.Value.Label = "//" + baseApexPackage + ":" + attrs.Manifest.Value.Label
- }
-
- // Key
- if overridableProperties.Key != nil {
- attrs.Key = bazel.LabelAttribute{}
- attrs.Key.SetValue(android.BazelLabelForModuleDepSingle(ctx, *overridableProperties.Key))
- }
-
- // Certificate
- if overridableProperties.Certificate == nil {
- // If overridableProperties.Certificate is nil, clear this out as
- // well with zeroed structs, so the override_apex does not use the
- // base apex's certificate.
- attrs.Certificate = bazel.LabelAttribute{}
- attrs.Certificate_name = bazel.StringAttribute{}
- } else {
- attrs.Certificate, attrs.Certificate_name = android.BazelStringOrLabelFromProp(ctx, overridableProperties.Certificate)
- }
-
- // Prebuilts
- if overridableProperties.Prebuilts != nil {
- prebuiltsLabelList := android.BazelLabelForModuleDeps(ctx, overridableProperties.Prebuilts)
- attrs.Prebuilts = bazel.MakeLabelListAttribute(prebuiltsLabelList)
- }
-
- // Compressible
- if overridableProperties.Compressible != nil {
- attrs.Compressible = bazel.BoolAttribute{Value: overridableProperties.Compressible}
- }
-
- // Package name
- //
- // e.g. com.android.adbd's package name is com.android.adbd, but
- // com.google.android.adbd overrides the package name to com.google.android.adbd
- //
- // TODO: this can be overridden from the product configuration, see
- // getOverrideManifestPackageName and
- // PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES.
- //
- // Instead of generating the BUILD files differently based on the product config
- // at the point of conversion, this should be handled by the BUILD file loading
- // from the soong_injection's product_vars, so product config is decoupled from bp2build.
- if overridableProperties.Package_name != "" {
- attrs.Package_name = &overridableProperties.Package_name
- }
-
- // Logging parent
- if overridableProperties.Logging_parent != "" {
- attrs.Logging_parent = &overridableProperties.Logging_parent
- }
- }
-
- commonAttrs.Name = o.Name()
-
- ctx.CreateBazelTargetModule(props, commonAttrs, &attrs)
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////////
// Vality check routines
//
@@ -2774,7 +2652,7 @@
return
}
- abInfo := ctx.Provider(ApexBundleInfoProvider).(ApexBundleInfo)
+ abInfo, _ := android.ModuleProvider(ctx, android.ApexBundleInfoProvider)
a.WalkPayloadDeps(ctx, func(ctx android.ModuleContext, from blueprint.Module, to android.ApexModule, externalDep bool) bool {
if ccm, ok := to.(*cc.Module); ok {
@@ -2835,7 +2713,7 @@
func (a *apexBundle) checkClasspathFragments(ctx android.ModuleContext) {
ctx.VisitDirectDeps(func(module android.Module) {
if tag := ctx.OtherModuleDependencyTag(module); tag == bcpfTag || tag == sscpfTag {
- info := ctx.OtherModuleProvider(module, java.ClasspathFragmentProtoContentInfoProvider).(java.ClasspathFragmentProtoContentInfo)
+ info, _ := android.OtherModuleProvider(ctx, module, java.ClasspathFragmentProtoContentInfoProvider)
if !info.ClasspathFragmentProtoGenerated {
ctx.OtherModuleErrorf(module, "is included in updatable apex %v, it must not set generate_classpaths_proto to false", ctx.ModuleName())
}
@@ -2956,7 +2834,6 @@
dpInfo.Deps = append(dpInfo.Deps, a.properties.Java_libs...)
dpInfo.Deps = append(dpInfo.Deps, a.properties.Bootclasspath_fragments...)
dpInfo.Deps = append(dpInfo.Deps, a.properties.Systemserverclasspath_fragments...)
- dpInfo.Paths = append(dpInfo.Paths, a.modulePaths...)
}
var (
@@ -3021,130 +2898,8 @@
//
// Module separator
//
- m["com.android.appsearch"] = []string{
- "icing-java-proto-lite",
- }
- //
- // Module separator
- //
- m["com.android.btservices"] = []string{
- // empty
- }
- //
- // Module separator
- //
- m["com.android.cellbroadcast"] = []string{}
- //
- // Module separator
- //
- m["com.android.extservices"] = []string{
- "ExtServices-core",
- "libtextclassifier-java",
- "textclassifier-statsd",
- "TextClassifierNotificationLibNoManifest",
- "TextClassifierServiceLibNoManifest",
- }
- //
- // Module separator
- //
- m["com.android.neuralnetworks"] = []string{
- "android.hardware.neuralnetworks@1.0",
- "android.hardware.neuralnetworks@1.1",
- "android.hardware.neuralnetworks@1.2",
- "android.hardware.neuralnetworks@1.3",
- "android.hidl.allocator@1.0",
- "android.hidl.memory.token@1.0",
- "android.hidl.memory@1.0",
- "android.hidl.safe_union@1.0",
- "libarect",
- "libprocpartition",
- }
- //
- // Module separator
- //
- m["com.android.media"] = []string{
- // empty
- }
- //
- // Module separator
- //
- m["com.android.media.swcodec"] = []string{
- // empty
- }
- //
- // Module separator
- //
- m["com.android.mediaprovider"] = []string{
- "MediaProvider",
- "MediaProviderGoogle",
- "fmtlib_ndk",
- "libbase_ndk",
- "libfuse",
- "libfuse_jni",
- }
- //
- // Module separator
- //
m["com.android.runtime"] = []string{
- "libdebuggerd",
- "libdebuggerd_common_headers",
- "libdebuggerd_handler_core",
- "libdl_static",
- "libjemalloc5",
- "liblinker_main",
- "liblinker_malloc",
- "liblzma",
- "libprocinfo",
- "libpropertyinfoparser",
- "libscudo",
- "libsystemproperties",
- "libtombstoned_client_static",
- "libunwindstack",
"libz",
- "libziparchive",
- }
- //
- // Module separator
- //
- m["com.android.tethering"] = []string{
- "android.hardware.tetheroffload.config-V1.0-java",
- "android.hardware.tetheroffload.control-V1.0-java",
- "net-utils-framework-common",
- }
- //
- // Module separator
- //
- m["com.android.wifi"] = []string{
- "PlatformProperties",
- "android.hardware.wifi-V1.0-java",
- "android.hardware.wifi-V1.0-java-constants",
- "android.hardware.wifi-V1.1-java",
- "android.hardware.wifi-V1.2-java",
- "android.hardware.wifi-V1.3-java",
- "android.hardware.wifi-V1.4-java",
- "android.hardware.wifi.hostapd-V1.0-java",
- "android.hardware.wifi.hostapd-V1.1-java",
- "android.hardware.wifi.hostapd-V1.2-java",
- "android.hardware.wifi.supplicant-V1.0-java",
- "android.hardware.wifi.supplicant-V1.1-java",
- "android.hardware.wifi.supplicant-V1.2-java",
- "android.hardware.wifi.supplicant-V1.3-java",
- "bouncycastle-unbundled",
- "framework-wifi-util-lib",
- "ksoap2",
- "libnanohttpd",
- "wifi-lite-protos",
- "wifi-nano-protos",
- "wifi-service-pre-jarjar",
- }
- //
- // Module separator
- //
- m[android.AvailableToAnyApex] = []string{
- "libprofile-clang-extras",
- "libprofile-clang-extras_ndk",
- "libprofile-extras",
- "libprofile-extras_ndk",
}
return m
}
@@ -3225,303 +2980,6 @@
}
}
-// For Bazel / bp2build
-
-type bazelApexBundleAttributes struct {
- Manifest bazel.LabelAttribute
- Android_manifest bazel.LabelAttribute
- File_contexts bazel.LabelAttribute
- Canned_fs_config bazel.LabelAttribute
- Key bazel.LabelAttribute
- Certificate bazel.LabelAttribute // used when the certificate prop is a module
- Certificate_name bazel.StringAttribute // used when the certificate prop is a string
- Min_sdk_version bazel.StringAttribute
- Updatable bazel.BoolAttribute
- Installable bazel.BoolAttribute
- Binaries bazel.LabelListAttribute
- Prebuilts bazel.LabelListAttribute
- Native_shared_libs_32 bazel.LabelListAttribute
- Native_shared_libs_64 bazel.LabelListAttribute
- Compressible bazel.BoolAttribute
- Package_name *string
- Logging_parent *string
- Tests bazel.LabelListAttribute
- Base_apex_name *string
- Apex_available_name *string
- Variant_version *string
-}
-
-type convertedNativeSharedLibs struct {
- Native_shared_libs_32 bazel.LabelListAttribute
- Native_shared_libs_64 bazel.LabelListAttribute
-}
-
-const (
- minSdkVersionPropName = "Min_sdk_version"
-)
-
-// ConvertWithBp2build performs bp2build conversion of an apex
-func (a *apexBundle) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- // We only convert apex and apex_test modules at this time
- if ctx.ModuleType() != "apex" && ctx.ModuleType() != "apex_test" {
- return
- }
-
- attrs, props, commonAttrs := convertWithBp2build(a, ctx)
- commonAttrs.Name = a.Name()
- ctx.CreateBazelTargetModule(props, commonAttrs, &attrs)
-}
-
-func convertWithBp2build(a *apexBundle, ctx android.TopDownMutatorContext) (bazelApexBundleAttributes, bazel.BazelTargetModuleProperties, android.CommonAttributes) {
- var manifestLabelAttribute bazel.LabelAttribute
- manifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, proptools.StringDefault(a.properties.Manifest, "apex_manifest.json")))
-
- var androidManifestLabelAttribute bazel.LabelAttribute
- if a.properties.AndroidManifest != nil {
- androidManifestLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.AndroidManifest))
- }
-
- var fileContextsLabelAttribute bazel.LabelAttribute
- if a.properties.File_contexts == nil {
- // See buildFileContexts(), if file_contexts is not specified the default one is used, which is //system/sepolicy/apex:<module name>-file_contexts
- fileContextsLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, a.Name()+"-file_contexts"))
- } else if strings.HasPrefix(*a.properties.File_contexts, ":") {
- // File_contexts is a module
- fileContextsLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *a.properties.File_contexts))
- } else {
- // File_contexts is a file
- fileContextsLabelAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.File_contexts))
- }
-
- var cannedFsConfigAttribute bazel.LabelAttribute
- if a.properties.Canned_fs_config != nil {
- cannedFsConfigAttribute.SetValue(android.BazelLabelForModuleSrcSingle(ctx, *a.properties.Canned_fs_config))
- }
-
- productVariableProps := android.ProductVariableProperties(ctx, a)
- // TODO(b/219503907) this would need to be set to a.MinSdkVersionValue(ctx) but
- // given it's coming via config, we probably don't want to put it in here.
- var minSdkVersion bazel.StringAttribute
- if a.properties.Min_sdk_version != nil {
- minSdkVersion.SetValue(*a.properties.Min_sdk_version)
- }
- if props, ok := productVariableProps[minSdkVersionPropName]; ok {
- for c, p := range props {
- if val, ok := p.(*string); ok {
- minSdkVersion.SetSelectValue(c.ConfigurationAxis(), c.SelectKey(), val)
- }
- }
- }
-
- var keyLabelAttribute bazel.LabelAttribute
- if a.overridableProperties.Key != nil {
- keyLabelAttribute.SetValue(android.BazelLabelForModuleDepSingle(ctx, *a.overridableProperties.Key))
- }
-
- // Certificate
- certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableProperties.Certificate)
-
- nativeSharedLibs := &convertedNativeSharedLibs{
- Native_shared_libs_32: bazel.LabelListAttribute{},
- Native_shared_libs_64: bazel.LabelListAttribute{},
- }
-
- // https://cs.android.com/android/platform/superproject/+/master:build/soong/android/arch.go;l=698;drc=f05b0d35d2fbe51be9961ce8ce8031f840295c68
- // https://cs.android.com/android/platform/superproject/+/master:build/soong/apex/apex.go;l=2549;drc=ec731a83e3e2d80a1254e32fd4ad7ef85e262669
- // In Soong, decodeMultilib, used to get multilib, return "first" if defaultMultilib is set to "common".
- // Since apex sets defaultMultilib to be "common", equivalent compileMultilib in bp2build for apex should be "first"
- compileMultilib := "first"
- if a.CompileMultilib() != nil {
- compileMultilib = *a.CompileMultilib()
- }
-
- // properties.Native_shared_libs is treated as "both"
- convertBothLibs(ctx, compileMultilib, a.properties.Native_shared_libs, nativeSharedLibs)
- convertBothLibs(ctx, compileMultilib, a.properties.Multilib.Both.Native_shared_libs, nativeSharedLibs)
- convert32Libs(ctx, compileMultilib, a.properties.Multilib.Lib32.Native_shared_libs, nativeSharedLibs)
- convert64Libs(ctx, compileMultilib, a.properties.Multilib.Lib64.Native_shared_libs, nativeSharedLibs)
- convertFirstLibs(ctx, compileMultilib, a.properties.Multilib.First.Native_shared_libs, nativeSharedLibs)
-
- prebuilts := a.overridableProperties.Prebuilts
- prebuiltsLabelList := android.BazelLabelForModuleDeps(ctx, prebuilts)
- prebuiltsLabelListAttribute := bazel.MakeLabelListAttribute(prebuiltsLabelList)
-
- binaries := android.BazelLabelForModuleDeps(ctx, a.properties.ApexNativeDependencies.Binaries)
- binariesLabelListAttribute := bazel.MakeLabelListAttribute(binaries)
-
- var testsAttrs bazel.LabelListAttribute
- if a.testApex && len(a.properties.ApexNativeDependencies.Tests) > 0 {
- tests := android.BazelLabelForModuleDeps(ctx, a.properties.ApexNativeDependencies.Tests)
- testsAttrs = bazel.MakeLabelListAttribute(tests)
- }
-
- var updatableAttribute bazel.BoolAttribute
- if a.properties.Updatable != nil {
- updatableAttribute.Value = a.properties.Updatable
- }
-
- var installableAttribute bazel.BoolAttribute
- if a.properties.Installable != nil {
- installableAttribute.Value = a.properties.Installable
- }
-
- var compressibleAttribute bazel.BoolAttribute
- if a.overridableProperties.Compressible != nil {
- compressibleAttribute.Value = a.overridableProperties.Compressible
- }
-
- var packageName *string
- if a.overridableProperties.Package_name != "" {
- packageName = &a.overridableProperties.Package_name
- }
-
- var loggingParent *string
- if a.overridableProperties.Logging_parent != "" {
- loggingParent = &a.overridableProperties.Logging_parent
- }
-
- attrs := bazelApexBundleAttributes{
- Manifest: manifestLabelAttribute,
- Android_manifest: androidManifestLabelAttribute,
- File_contexts: fileContextsLabelAttribute,
- Canned_fs_config: cannedFsConfigAttribute,
- Min_sdk_version: minSdkVersion,
- Key: keyLabelAttribute,
- Certificate: certificate,
- Certificate_name: certificateName,
- Updatable: updatableAttribute,
- Installable: installableAttribute,
- Native_shared_libs_32: nativeSharedLibs.Native_shared_libs_32,
- Native_shared_libs_64: nativeSharedLibs.Native_shared_libs_64,
- Binaries: binariesLabelListAttribute,
- Prebuilts: prebuiltsLabelListAttribute,
- Compressible: compressibleAttribute,
- Package_name: packageName,
- Logging_parent: loggingParent,
- Tests: testsAttrs,
- Apex_available_name: a.properties.Apex_available_name,
- Variant_version: a.properties.Variant_version,
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "apex",
- Bzl_load_location: "//build/bazel/rules/apex:apex.bzl",
- }
-
- commonAttrs := android.CommonAttributes{}
- if a.testApex {
- commonAttrs.Testonly = proptools.BoolPtr(true)
- // Set the api_domain of the test apex
- attrs.Base_apex_name = proptools.StringPtr(cc.GetApiDomain(a.Name()))
- }
-
- return attrs, props, commonAttrs
-}
-
-// The following conversions are based on this table where the rows are the compile_multilib
-// values and the columns are the properties.Multilib.*.Native_shared_libs. Each cell
-// represents how the libs should be compiled for a 64-bit/32-bit device: 32 means it
-// should be compiled as 32-bit, 64 means it should be compiled as 64-bit, none means it
-// should not be compiled.
-// multib/compile_multilib, 32, 64, both, first
-// 32, 32/32, none/none, 32/32, none/32
-// 64, none/none, 64/none, 64/none, 64/none
-// both, 32/32, 64/none, 32&64/32, 64/32
-// first, 32/32, 64/none, 64/32, 64/32
-
-func convert32Libs(ctx android.TopDownMutatorContext, compileMultilb string,
- libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
- libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
- switch compileMultilb {
- case "both", "32":
- makeNoConfig32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
- case "first":
- make32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
- case "64":
- // Incompatible, ignore
- default:
- invalidCompileMultilib(ctx, compileMultilb)
- }
-}
-
-func convert64Libs(ctx android.TopDownMutatorContext, compileMultilb string,
- libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
- libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
- switch compileMultilb {
- case "both", "64", "first":
- make64SharedLibsAttributes(libsLabelList, nativeSharedLibs)
- case "32":
- // Incompatible, ignore
- default:
- invalidCompileMultilib(ctx, compileMultilb)
- }
-}
-
-func convertBothLibs(ctx android.TopDownMutatorContext, compileMultilb string,
- libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
- libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
- switch compileMultilb {
- case "both":
- makeNoConfig32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
- make64SharedLibsAttributes(libsLabelList, nativeSharedLibs)
- case "first":
- makeFirstSharedLibsAttributes(libsLabelList, nativeSharedLibs)
- case "32":
- makeNoConfig32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
- case "64":
- make64SharedLibsAttributes(libsLabelList, nativeSharedLibs)
- default:
- invalidCompileMultilib(ctx, compileMultilb)
- }
-}
-
-func convertFirstLibs(ctx android.TopDownMutatorContext, compileMultilb string,
- libs []string, nativeSharedLibs *convertedNativeSharedLibs) {
- libsLabelList := android.BazelLabelForModuleDeps(ctx, libs)
- switch compileMultilb {
- case "both", "first":
- makeFirstSharedLibsAttributes(libsLabelList, nativeSharedLibs)
- case "32":
- make32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
- case "64":
- make64SharedLibsAttributes(libsLabelList, nativeSharedLibs)
- default:
- invalidCompileMultilib(ctx, compileMultilb)
- }
-}
-
-func makeFirstSharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) {
- make32SharedLibsAttributes(libsLabelList, nativeSharedLibs)
- make64SharedLibsAttributes(libsLabelList, nativeSharedLibs)
-}
-
-func makeNoConfig32SharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) {
- list := bazel.LabelListAttribute{}
- list.SetSelectValue(bazel.NoConfigAxis, "", libsLabelList)
- nativeSharedLibs.Native_shared_libs_32.Append(list)
-}
-
-func make32SharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) {
- makeSharedLibsAttributes("x86", libsLabelList, &nativeSharedLibs.Native_shared_libs_32)
- makeSharedLibsAttributes("arm", libsLabelList, &nativeSharedLibs.Native_shared_libs_32)
-}
-
-func make64SharedLibsAttributes(libsLabelList bazel.LabelList, nativeSharedLibs *convertedNativeSharedLibs) {
- makeSharedLibsAttributes("x86_64", libsLabelList, &nativeSharedLibs.Native_shared_libs_64)
- makeSharedLibsAttributes("arm64", libsLabelList, &nativeSharedLibs.Native_shared_libs_64)
-}
-
-func makeSharedLibsAttributes(config string, libsLabelList bazel.LabelList,
- labelListAttr *bazel.LabelListAttribute) {
- list := bazel.LabelListAttribute{}
- list.SetSelectValue(bazel.ArchConfigurationAxis, config, libsLabelList)
- labelListAttr.Append(list)
-}
-
-func invalidCompileMultilib(ctx android.TopDownMutatorContext, value string) {
- ctx.PropertyErrorf("compile_multilib", "Invalid value: %s", value)
-}
-
func (a *apexBundle) IsTestApex() bool {
return a.testApex
}
diff --git a/apex/apex_singleton.go b/apex/apex_singleton.go
index a63344f..25c0cc4 100644
--- a/apex/apex_singleton.go
+++ b/apex/apex_singleton.go
@@ -83,7 +83,7 @@
updatableFlatLists := android.Paths{}
ctx.VisitAllModules(func(module android.Module) {
if binaryInfo, ok := module.(android.ApexBundleDepsInfoIntf); ok {
- apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.SingletonModuleProvider(ctx, module, android.ApexInfoProvider)
if path := binaryInfo.FlatListPath(); path != nil {
if binaryInfo.Updatable() || apexInfo.Updatable {
updatableFlatLists = append(updatableFlatLists, path)
diff --git a/apex/apex_test.go b/apex/apex_test.go
index 9475f5d..d3959ec 100644
--- a/apex/apex_test.go
+++ b/apex/apex_test.go
@@ -25,6 +25,8 @@
"strings"
"testing"
+ "android/soong/aconfig/codegen"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -151,6 +153,7 @@
prebuilt_etc.PrepareForTestWithPrebuiltEtc,
rust.PrepareForTestWithRustDefaultModules,
sh.PrepareForTestWithShBuildComponents,
+ codegen.PrepareForTestWithAconfigBuildComponents,
PrepareForTestWithApexBuildComponents,
@@ -595,13 +598,15 @@
t.Errorf("Could not find all expected symlinks! foo: %t, foo_link_64: %t. Command was %s", found_foo, found_foo_link_64, copyCmds)
}
- fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex").Output("depsinfo/fulllist.txt").Args["content"], "\\n")
+ fullDepsInfo := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
+ ctx.ModuleForTests("myapex", "android_common_myapex").Output("depsinfo/fulllist.txt")), "\n")
ensureListContains(t, fullDepsInfo, " myjar(minSdkVersion:(no version)) <- myapex")
ensureListContains(t, fullDepsInfo, " mylib2(minSdkVersion:(no version)) <- mylib")
ensureListContains(t, fullDepsInfo, " myotherjar(minSdkVersion:(no version)) <- myjar")
ensureListContains(t, fullDepsInfo, " mysharedjar(minSdkVersion:(no version)) (external) <- myjar")
- flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex", "android_common_myapex").Output("depsinfo/flatlist.txt").Args["content"], "\\n")
+ flatDepsInfo := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
+ ctx.ModuleForTests("myapex", "android_common_myapex").Output("depsinfo/flatlist.txt")), "\n")
ensureListContains(t, flatDepsInfo, "myjar(minSdkVersion:(no version))")
ensureListContains(t, flatDepsInfo, "mylib2(minSdkVersion:(no version))")
ensureListContains(t, flatDepsInfo, "myotherjar(minSdkVersion:(no version))")
@@ -948,7 +953,7 @@
// Ensure that stub dependency from a rust module is not included
ensureNotContains(t, copyCmds, "image.apex/lib64/libfoo.shared_from_rust.so")
// The rust module is linked to the stub cc library
- rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustLink").Args["linkFlags"]
+ rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").Args["linkFlags"]
ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so")
ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so")
@@ -956,6 +961,32 @@
ensureListContains(t, names(apexManifestRule.Args["requireNativeLibs"]), "libfoo.shared_from_rust.so")
}
+func TestApexShouldNotEmbedStubVariant(t *testing.T) {
+ testApexError(t, `module "myapex" .*: native_shared_libs: "libbar" is a stub`, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ vendor: true,
+ updatable: false,
+ native_shared_libs: ["libbar"], // should not add an LLNDK stub in a vendor apex
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libbar",
+ srcs: ["mylib.cpp"],
+ llndk: {
+ symbol_file: "libbar.map.txt",
+ }
+ }
+ `)
+}
+
func TestApexCanUsePrivateApis(t *testing.T) {
ctx := testApex(t, `
apex {
@@ -1024,7 +1055,7 @@
mylibLdFlags := ctx.ModuleForTests("mylib", "android_arm64_armv8-a_shared_apex10000").Rule("ld").Args["libFlags"]
ensureNotContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared_current/mylib2.so")
ensureContains(t, mylibLdFlags, "mylib2/android_arm64_armv8-a_shared/mylib2.so")
- rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustLink").Args["linkFlags"]
+ rustDeps := ctx.ModuleForTests("foo.rust", "android_arm64_armv8-a_apex10000").Rule("rustc").Args["linkFlags"]
ensureNotContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared_current/libfoo.shared_from_rust.so")
ensureContains(t, rustDeps, "libfoo.shared_from_rust/android_arm64_armv8-a_shared/libfoo.shared_from_rust.so")
}
@@ -1281,10 +1312,12 @@
// Ensure that libfoo stubs is not linking to libbar (since it is a stubs)
ensureNotContains(t, libFooStubsLdFlags, "libbar.so")
- fullDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2").Output("depsinfo/fulllist.txt").Args["content"], "\\n")
+ fullDepsInfo := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
+ ctx.ModuleForTests("myapex2", "android_common_myapex2").Output("depsinfo/fulllist.txt")), "\n")
ensureListContains(t, fullDepsInfo, " libfoo(minSdkVersion:(no version)) (external) <- mylib")
- flatDepsInfo := strings.Split(ctx.ModuleForTests("myapex2", "android_common_myapex2").Output("depsinfo/flatlist.txt").Args["content"], "\\n")
+ flatDepsInfo := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
+ ctx.ModuleForTests("myapex2", "android_common_myapex2").Output("depsinfo/flatlist.txt")), "\n")
ensureListContains(t, flatDepsInfo, "libfoo(minSdkVersion:(no version)) (external)")
}
@@ -1422,6 +1455,7 @@
name: "libc",
no_libcrt: true,
nocrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
stubs: { versions: ["1"] },
@@ -1436,6 +1470,7 @@
name: "libclang_rt.hwasan",
no_libcrt: true,
nocrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
srcs: [""],
@@ -1478,6 +1513,7 @@
name: "libc",
no_libcrt: true,
nocrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
stubs: { versions: ["1"] },
@@ -1488,6 +1524,7 @@
name: "libclang_rt.hwasan",
no_libcrt: true,
nocrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
srcs: [""],
@@ -2030,7 +2067,8 @@
"out/soong/.intermediates/myapex2/android_common_myapex2/depsinfo/flatlist.txt")
myapex := ctx.ModuleForTests("myapex", "android_common_myapex")
- flatlist := strings.Split(myapex.Output("depsinfo/flatlist.txt").BuildParams.Args["content"], "\\n")
+ flatlist := strings.Split(android.ContentFromFileRuleForTests(t, ctx,
+ myapex.Output("depsinfo/flatlist.txt")), "\n")
android.AssertStringListContains(t, "deps with stubs should be tracked in depsinfo as external dep",
flatlist, "libbar(minSdkVersion:(no version)) (external)")
android.AssertStringListDoesNotContain(t, "do not track if not available for platform",
@@ -3088,10 +3126,7 @@
apex_available: ["myapex"],
srcs: ["foo.cpp"],
}
- `, android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.ProductVndkVersion = proptools.StringPtr("current")
- }),
- )
+ `)
cflags := strings.Fields(
ctx.ModuleForTests("foo", "android_product.29_arm64_armv8-a_myapex").Rule("cc").Args["cFlags"])
@@ -3694,7 +3729,7 @@
}
func ensureExactDeapexedContents(t *testing.T, ctx *android.TestContext, moduleName string, variant string, files []string) {
- deapexer := ctx.ModuleForTests(moduleName+".deapexer", variant).Rule("deapexer")
+ deapexer := ctx.ModuleForTests(moduleName+".deapexer", variant).Description("deapex")
outputs := make([]string, 0, len(deapexer.ImplicitOutputs)+1)
if deapexer.Output != nil {
outputs = append(outputs, deapexer.Output.String())
@@ -3737,13 +3772,6 @@
"lib64/libvndk.so",
"lib64/libvndksp.so"),
},
- {
- vndkVersion: "",
- expectedFiles: append(commonFiles,
- // Legacy VNDK APEX contains only VNDK-SP files (of core variant)
- "lib/libvndksp.so",
- "lib64/libvndksp.so"),
- },
}
for _, tc := range testCases {
t.Run("VNDK.current with DeviceVndkVersion="+tc.vndkVersion, func(t *testing.T) {
@@ -3885,13 +3913,24 @@
func vndkLibrariesTxtFiles(vers ...string) (result string) {
for _, v := range vers {
if v == "current" {
- for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate", "vndkproduct"} {
+ for _, txt := range []string{"vndkcore", "vndksp", "vndkprivate", "vndkproduct"} {
result += `
` + txt + `_libraries_txt {
name: "` + txt + `.libraries.txt",
+ insert_vndk_version: true,
}
`
}
+ result += `
+ llndk_libraries_txt {
+ name: "llndk.libraries.txt",
+ }
+ llndk_libraries_txt_for_apex {
+ name: "llndk.libraries.txt.apex",
+ stem: "llndk.libraries.txt",
+ insert_vndk_version: true,
+ }
+ `
} else {
for _, txt := range []string{"llndk", "vndkcore", "vndksp", "vndkprivate", "vndkproduct"} {
result += `
@@ -4695,6 +4734,72 @@
ensureListContains(t, ctx.ModuleVariantsForTests("mylib_common_test"), "android_arm64_armv8-a_shared")
}
+func TestLibzVendorIsntStable(t *testing.T) {
+ ctx := testApex(t, `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ updatable: false,
+ binaries: ["mybin"],
+ }
+ apex {
+ name: "myvendorapex",
+ key: "myapex.key",
+ file_contexts: "myvendorapex_file_contexts",
+ vendor: true,
+ updatable: false,
+ binaries: ["mybin"],
+ }
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+ cc_binary {
+ name: "mybin",
+ vendor_available: true,
+ system_shared_libs: [],
+ stl: "none",
+ shared_libs: ["libz"],
+ apex_available: ["//apex_available:anyapex"],
+ }
+ cc_library {
+ name: "libz",
+ vendor_available: true,
+ system_shared_libs: [],
+ stl: "none",
+ stubs: {
+ versions: ["28", "30"],
+ },
+ target: {
+ vendor: {
+ no_stubs: true,
+ },
+ },
+ }
+ `, withFiles(map[string][]byte{
+ "myvendorapex_file_contexts": nil,
+ }))
+
+ // libz provides stubs for core variant.
+ {
+ ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
+ "bin/mybin",
+ })
+ apexManifestRule := ctx.ModuleForTests("myapex", "android_common_myapex").Rule("apexManifestRule")
+ android.AssertStringEquals(t, "should require libz", apexManifestRule.Args["requireNativeLibs"], "libz.so")
+ }
+ // libz doesn't provide stubs for vendor variant.
+ {
+ ensureExactContents(t, ctx, "myvendorapex", "android_common_myvendorapex", []string{
+ "bin/mybin",
+ "lib64/libz.so",
+ })
+ apexManifestRule := ctx.ModuleForTests("myvendorapex", "android_common_myvendorapex").Rule("apexManifestRule")
+ android.AssertStringEquals(t, "should not require libz", apexManifestRule.Args["requireNativeLibs"], "")
+ }
+}
+
func TestApexWithTarget(t *testing.T) {
ctx := testApex(t, `
apex {
@@ -5247,6 +5352,13 @@
).RunTest(t)
}
+// A minimal context object for use with DexJarBuildPath
+type moduleErrorfTestCtx struct {
+}
+
+func (ctx moduleErrorfTestCtx) ModuleErrorf(format string, args ...interface{}) {
+}
+
// These tests verify that the prebuilt_apex/deapexer to java_import wiring allows for the
// propagation of paths to dex implementation jars from the former to the latter.
func TestPrebuiltExportDexImplementationJars(t *testing.T) {
@@ -5256,10 +5368,10 @@
t.Helper()
// Make sure the import has been given the correct path to the dex jar.
p := ctx.ModuleForTests(name, "android_common_myapex").Module().(java.UsesLibraryDependency)
- dexJarBuildPath := p.DexJarBuildPath().PathOrNil()
+ dexJarBuildPath := p.DexJarBuildPath(moduleErrorfTestCtx{}).PathOrNil()
stem := android.RemoveOptionalPrebuiltPrefix(name)
android.AssertStringEquals(t, "DexJarBuildPath should be apex-related path.",
- ".intermediates/myapex.deapexer/android_common/deapexer/javalib/"+stem+".jar",
+ ".intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/"+stem+".jar",
android.NormalizePathForTesting(dexJarBuildPath))
}
@@ -5313,8 +5425,8 @@
// Make sure that dexpreopt can access dex implementation files from the prebuilt.
ctx := testDexpreoptWithApexes(t, bp, "", transform)
- deapexerName := deapexerModuleName("myapex")
- android.AssertStringEquals(t, "APEX module name from deapexer name", "myapex", apexModuleName(deapexerName))
+ deapexerName := deapexerModuleName("prebuilt_myapex")
+ android.AssertStringEquals(t, "APEX module name from deapexer name", "prebuilt_myapex", apexModuleName(deapexerName))
// Make sure that the deapexer has the correct input APEX.
deapexer := ctx.ModuleForTests(deapexerName, "android_common")
@@ -5451,7 +5563,7 @@
checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, stem string, bootDexJarPath string) {
t.Helper()
- s := ctx.ModuleForTests("platform-bootclasspath", "android_common")
+ s := ctx.ModuleForTests("dex_bootjars", "android_common")
foundLibfooJar := false
base := stem + ".jar"
for _, output := range s.AllOutputs() {
@@ -5537,8 +5649,8 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
+ checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, ``)
@@ -5615,8 +5727,8 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
+ checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, ``)
@@ -5629,7 +5741,7 @@
myApex := ctx.ModuleForTests("myapex", "android_common_myapex").Module()
overrideNames := []string{
- "",
+ "myapex",
"myjavalib.myapex",
"libfoo.myapex",
"libbar.myapex",
@@ -5804,8 +5916,8 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
+ checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, ``)
@@ -5901,8 +6013,8 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/libfoo/android_common_apex10000/hiddenapi/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/libbar/android_common_myapex/hiddenapi/libbar.jar")
+ checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/my-bootclasspath-fragment/android_common_myapex/hiddenapi-modular/encoded/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/my-bootclasspath-fragment/android_common_myapex/hiddenapi-modular/encoded/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, ``)
@@ -6001,8 +6113,8 @@
`
ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
- checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
- checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
+ checkBootDexJarPath(t, ctx, "libfoo", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libfoo.jar")
+ checkBootDexJarPath(t, ctx, "libbar", "out/soong/.intermediates/prebuilt_myapex.deapexer/android_common/deapexer/javalib/libbar.jar")
// Verify the correct module jars contribute to the hiddenapi index file.
checkHiddenAPIIndexFromClassesInputs(t, ctx, ``)
@@ -6012,6 +6124,84 @@
out/soong/.intermediates/packages/modules/com.android.art/art-bootclasspath-fragment/android_common_apex10000/modular-hiddenapi/index.csv
`)
})
+
+ t.Run("Co-existing unflagged apexes should create a duplicate deapexer error in hiddenapi processing", func(t *testing.T) {
+ bp := `
+ // Source
+ apex {
+ name: "myapex",
+ enabled: false,
+ key: "myapex.key",
+ bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ // Prebuilt
+ prebuilt_apex {
+ name: "myapex.v1",
+ source_apex_name: "myapex",
+ arch: {
+ arm64: {
+ src: "myapex-arm64.apex",
+ },
+ arm: {
+ src: "myapex-arm.apex",
+ },
+ },
+ exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ prefer: true,
+ }
+ prebuilt_apex {
+ name: "myapex.v2",
+ source_apex_name: "myapex",
+ arch: {
+ arm64: {
+ src: "myapex-arm64.apex",
+ },
+ arm: {
+ src: "myapex-arm.apex",
+ },
+ },
+ exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ prefer: true,
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "my-bootclasspath-fragment",
+ contents: ["libfoo", "libbar"],
+ apex_available: ["myapex"],
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
+ prefer: true,
+ }
+
+ java_import {
+ name: "libfoo",
+ jars: ["libfoo.jar"],
+ apex_available: ["myapex"],
+ prefer: true,
+ }
+ java_import {
+ name: "libbar",
+ jars: ["libbar.jar"],
+ apex_available: ["myapex"],
+ prefer: true,
+ }
+ `
+
+ testDexpreoptWithApexes(t, bp, "Multiple installable prebuilt APEXes provide ambiguous deapexers: prebuilt_myapex.v1 and prebuilt_myapex.v2", preparer, fragment)
+ })
+
}
func TestApexWithTests(t *testing.T) {
@@ -7701,6 +7891,42 @@
`)
}
+func TestApexUnwantedTransitiveDeps(t *testing.T) {
+ bp := `
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ native_shared_libs: ["libfoo"],
+ updatable: false,
+ unwanted_transitive_deps: ["libbar"],
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ cc_library {
+ name: "libfoo",
+ srcs: ["foo.cpp"],
+ shared_libs: ["libbar"],
+ apex_available: ["myapex"],
+ }
+
+ cc_library {
+ name: "libbar",
+ srcs: ["bar.cpp"],
+ apex_available: ["myapex"],
+ }`
+ ctx := testApex(t, bp)
+ ensureExactContents(t, ctx, "myapex", "android_common_myapex", []string{
+ "*/libc++.so",
+ "*/libfoo.so",
+ // not libbar.so
+ })
+}
+
func TestRejectNonInstallableJavaLibrary(t *testing.T) {
testApexError(t, `"myjar" is not configured to be compiled into dex`, `
apex {
@@ -8110,7 +8336,7 @@
`, withManifestPackageNameOverrides([]string{"AppFoo:com.android.foo"}))
bundleConfigRule := ctx.ModuleForTests("myapex", "android_common_myapex").Output("bundle_config.json")
- content := bundleConfigRule.Args["content"]
+ content := android.ContentFromFileRuleForTests(t, ctx, bundleConfigRule)
ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
ensureContains(t, content, `"apex_config":{"apex_embedded_apk_config":[{"package_name":"com.android.foo","path":"app/AppFoo@TEST.BUILD_ID/AppFoo.apk"}]}`)
@@ -8137,7 +8363,7 @@
}`)
mod := ctx.ModuleForTests("myapex", "android_common_myapex")
bundleConfigRule := mod.Output("bundle_config.json")
- content := bundleConfigRule.Args["content"]
+ content := android.ContentFromFileRuleForTests(t, ctx, bundleConfigRule)
ensureContains(t, content, `"compression":{"uncompressed_glob":["apex_payload.img","apex_manifest.*"]}`)
s := mod.Rule("apexRule").Args["copy_commands"]
copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
@@ -8169,9 +8395,9 @@
ctx := testApex(t, bp, prepareForTestWithSantitizeHwaddress)
// Check that the extractor produces the correct output file from the correct input file.
- extractorOutput := "out/soong/.intermediates/myapex.apex.extractor/android_common/extracted/myapex.hwasan.apks"
+ extractorOutput := "out/soong/.intermediates/prebuilt_myapex.apex.extractor/android_common/extracted/myapex.hwasan.apks"
- m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.hwasan.apks"}, extractedApex.Inputs.Strings())
@@ -8196,10 +8422,10 @@
}
`)
- m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
// Check that the extractor produces the correct apks file from the input module
- extractorOutput := "out/soong/.intermediates/myapex.apex.extractor/android_common/extracted/myapex.apks"
+ extractorOutput := "out/soong/.intermediates/prebuilt_myapex.apex.extractor/android_common/extracted/myapex.apks"
extractedApex := m.Output(extractorOutput)
android.AssertArrayString(t, "extractor input", []string{"myapex.apks"}, extractedApex.Inputs.Strings())
@@ -8264,30 +8490,39 @@
func TestDuplicateDeapexersFromPrebuiltApexes(t *testing.T) {
preparers := android.GroupFixturePreparers(
java.PrepareForTestWithJavaDefaultModules,
+ prepareForTestWithBootclasspathFragment,
+ dexpreopt.FixtureSetTestOnlyArtBootImageJars("com.android.art:libfoo"),
PrepareForTestWithApexBuildComponents,
).
ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
- "Multiple installable prebuilt APEXes provide ambiguous deapexers: com.android.myapex and com.mycompany.android.myapex"))
+ "Multiple installable prebuilt APEXes provide ambiguous deapexers: prebuilt_com.android.art and prebuilt_com.mycompany.android.art"))
bpBase := `
apex_set {
- name: "com.android.myapex",
+ name: "com.android.art",
installable: true,
- exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
set: "myapex.apks",
}
apex_set {
- name: "com.mycompany.android.myapex",
- apex_name: "com.android.myapex",
+ name: "com.mycompany.android.art",
+ apex_name: "com.android.art",
installable: true,
- exported_bootclasspath_fragments: ["my-bootclasspath-fragment"],
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
set: "company-myapex.apks",
}
prebuilt_bootclasspath_fragment {
- name: "my-bootclasspath-fragment",
- apex_available: ["com.android.myapex"],
+ name: "art-bootclasspath-fragment",
+ apex_available: ["com.android.art"],
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
%s
}
`
@@ -8297,7 +8532,7 @@
java_import {
name: "libfoo",
jars: ["libfoo.jar"],
- apex_available: ["com.android.myapex"],
+ apex_available: ["com.android.art"],
}
`)
})
@@ -8309,7 +8544,8 @@
public: {
jars: ["libbar.jar"],
},
- apex_available: ["com.android.myapex"],
+ shared_library: false,
+ apex_available: ["com.android.art"],
}
`)
})
@@ -8324,7 +8560,8 @@
public: {
jars: ["libbar.jar"],
},
- apex_available: ["com.android.myapex"],
+ shared_library: false,
+ apex_available: ["com.android.art"],
}
`)
})
@@ -8336,6 +8573,8 @@
PrepareForTestWithApexBuildComponents,
)
+ errCtx := moduleErrorfTestCtx{}
+
bpBase := `
apex_set {
name: "com.android.myapex",
@@ -8384,8 +8623,8 @@
module := result.Module("libfoo", "android_common_com.android.myapex")
usesLibraryDep := module.(java.UsesLibraryDependency)
android.AssertPathRelativeToTopEquals(t, "dex jar path",
- "out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
- usesLibraryDep.DexJarBuildPath().Path())
+ "out/soong/.intermediates/prebuilt_com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
+ usesLibraryDep.DexJarBuildPath(errCtx).Path())
})
t.Run("java_sdk_library_import", func(t *testing.T) {
@@ -8407,8 +8646,8 @@
module := result.Module("libfoo", "android_common_com.android.myapex")
usesLibraryDep := module.(java.UsesLibraryDependency)
android.AssertPathRelativeToTopEquals(t, "dex jar path",
- "out/soong/.intermediates/com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
- usesLibraryDep.DexJarBuildPath().Path())
+ "out/soong/.intermediates/prebuilt_com.android.myapex.deapexer/android_common/deapexer/javalib/libfoo.jar",
+ usesLibraryDep.DexJarBuildPath(errCtx).Path())
})
t.Run("prebuilt_bootclasspath_fragment", func(t *testing.T) {
@@ -8980,7 +9219,7 @@
}),
)
- m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
// Check extract_apks tool parameters.
extractedApex := m.Output("extracted/myapex.apks")
@@ -9021,7 +9260,7 @@
}),
)
- m := ctx.ModuleForTests("myapex.apex.extractor", "android_common")
+ m := ctx.ModuleForTests("prebuilt_myapex.apex.extractor", "android_common")
// Check extract_apks tool parameters. No native bridge arch expected
extractedApex := m.Output("extracted/myapex.apks")
@@ -9081,8 +9320,8 @@
}
`)
- apexKeysText := ctx.SingletonForTests("apex_keys_text")
- content := apexKeysText.MaybeDescription("apexkeys.txt").BuildParams.Args["content"]
+ myapex := ctx.ModuleForTests("myapex", "android_common_myapex")
+ content := android.ContentFromFileRuleForTests(t, ctx, myapex.Output("apexkeys.txt"))
ensureContains(t, content, `name="myapex.apex" public_key="vendor/foo/devkeys/testkey.avbpubkey" private_key="vendor/foo/devkeys/testkey.pem" container_certificate="vendor/foo/devkeys/test.x509.pem" container_private_key="vendor/foo/devkeys/test.pk8" partition="system" sign_tool="sign_myapex"`)
}
@@ -9122,10 +9361,12 @@
}
`)
- apexKeysText := ctx.SingletonForTests("apex_keys_text")
- content := apexKeysText.MaybeDescription("apexkeys.txt").BuildParams.Args["content"]
+ content := android.ContentFromFileRuleForTests(t, ctx,
+ ctx.ModuleForTests("myapex", "android_common_myapex").Output("apexkeys.txt"))
+ ensureContains(t, content, `name="myapex.apex" public_key="vendor/foo/devkeys/testkey.avbpubkey" private_key="vendor/foo/devkeys/testkey.pem" container_certificate="vendor/foo/devkeys/test.x509.pem" container_private_key="vendor/foo/devkeys/test.pk8" partition="system" sign_tool="sign_myapex"`)
+ content = android.ContentFromFileRuleForTests(t, ctx,
+ ctx.ModuleForTests("myapex_set", "android_common_myapex_set").Output("apexkeys.txt"))
ensureContains(t, content, `name="myapex_set.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
- ensureContains(t, content, `name="myapex.apex" public_key="PRESIGNED" private_key="PRESIGNED" container_certificate="PRESIGNED" container_private_key="PRESIGNED" partition="system"`)
}
func TestAllowedFiles(t *testing.T) {
@@ -10521,6 +10762,7 @@
min_sdk_version: "29",
recovery_available: true,
vendor_available: true,
+ product_available: true,
}
api_imports {
name: "api_imports",
@@ -10711,3 +10953,889 @@
inputs.Strings(),
"out/soong/.intermediates/libbar/android_arm64_armv8-a_shared/libbar.so")
}
+
+var apex_default_bp = `
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ filegroup {
+ name: "myapex.manifest",
+ srcs: ["apex_manifest.json"],
+ }
+
+ filegroup {
+ name: "myapex.androidmanifest",
+ srcs: ["AndroidManifest.xml"],
+ }
+`
+
+func TestAconfigFilesJavaDeps(t *testing.T) {
+ ctx := testApex(t, apex_default_bp+`
+ apex {
+ name: "myapex",
+ manifest: ":myapex.manifest",
+ androidManifest: ":myapex.androidmanifest",
+ key: "myapex.key",
+ java_libs: [
+ "my_java_library_foo",
+ "my_java_library_bar",
+ ],
+ updatable: false,
+ }
+
+ java_library {
+ name: "my_java_library_foo",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ static_libs: ["my_java_aconfig_library_foo"],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ java_library {
+ name: "my_java_library_bar",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ static_libs: ["my_java_aconfig_library_bar"],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ aconfig_declarations {
+ name: "my_aconfig_declarations_foo",
+ package: "com.example.package",
+ container: "myapex",
+ srcs: ["foo.aconfig"],
+ }
+
+ java_aconfig_library {
+ name: "my_java_aconfig_library_foo",
+ aconfig_declarations: "my_aconfig_declarations_foo",
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ aconfig_declarations {
+ name: "my_aconfig_declarations_bar",
+ package: "com.example.package",
+ container: "myapex",
+ srcs: ["bar.aconfig"],
+ }
+
+ java_aconfig_library {
+ name: "my_java_aconfig_library_bar",
+ aconfig_declarations: "my_aconfig_declarations_bar",
+ apex_available: [
+ "myapex",
+ ],
+ }
+ `)
+
+ mod := ctx.ModuleForTests("myapex", "android_common_myapex")
+ s := mod.Rule("apexRule").Args["copy_commands"]
+ copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
+ if len(copyCmds) != 5 {
+ t.Fatalf("Expected 5 commands, got %d in:\n%s", len(copyCmds), s)
+ }
+
+ ensureMatches(t, copyCmds[4], "^cp -f .*/aconfig_flags.pb .*/image.apex$")
+
+ combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
+ s = " " + combineAconfigRule.Args["cache_files"]
+ aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
+ if len(aconfigArgs) != 2 {
+ t.Fatalf("Expected 2 commands, got %d in:\n%s", len(aconfigArgs), s)
+ }
+ android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
+ android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_bar/intermediate.pb")
+
+ buildParams := combineAconfigRule.BuildParams
+ android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
+ android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_bar/intermediate.pb")
+ ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
+}
+
+func TestAconfigFilesJavaAndCcDeps(t *testing.T) {
+ ctx := testApex(t, apex_default_bp+`
+ apex {
+ name: "myapex",
+ manifest: ":myapex.manifest",
+ androidManifest: ":myapex.androidmanifest",
+ key: "myapex.key",
+ java_libs: [
+ "my_java_library_foo",
+ ],
+ native_shared_libs: [
+ "my_cc_library_bar",
+ ],
+ binaries: [
+ "my_cc_binary_baz",
+ ],
+ updatable: false,
+ }
+
+ java_library {
+ name: "my_java_library_foo",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ static_libs: ["my_java_aconfig_library_foo"],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ cc_library {
+ name: "my_cc_library_bar",
+ srcs: ["foo/bar/MyClass.cc"],
+ static_libs: [
+ "my_cc_aconfig_library_bar",
+ "my_cc_aconfig_library_baz",
+ ],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ cc_binary {
+ name: "my_cc_binary_baz",
+ srcs: ["foo/bar/MyClass.cc"],
+ static_libs: ["my_cc_aconfig_library_baz"],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ aconfig_declarations {
+ name: "my_aconfig_declarations_foo",
+ package: "com.example.package",
+ container: "myapex",
+ srcs: ["foo.aconfig"],
+ }
+
+ java_aconfig_library {
+ name: "my_java_aconfig_library_foo",
+ aconfig_declarations: "my_aconfig_declarations_foo",
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ aconfig_declarations {
+ name: "my_aconfig_declarations_bar",
+ package: "com.example.package",
+ container: "myapex",
+ srcs: ["bar.aconfig"],
+ }
+
+ cc_aconfig_library {
+ name: "my_cc_aconfig_library_bar",
+ aconfig_declarations: "my_aconfig_declarations_bar",
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ aconfig_declarations {
+ name: "my_aconfig_declarations_baz",
+ package: "com.example.package",
+ container: "myapex",
+ srcs: ["baz.aconfig"],
+ }
+
+ cc_aconfig_library {
+ name: "my_cc_aconfig_library_baz",
+ aconfig_declarations: "my_aconfig_declarations_baz",
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ cc_library {
+ name: "server_configurable_flags",
+ srcs: ["server_configurable_flags.cc"],
+ }
+ `)
+
+ mod := ctx.ModuleForTests("myapex", "android_common_myapex")
+ s := mod.Rule("apexRule").Args["copy_commands"]
+ copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
+ if len(copyCmds) != 9 {
+ t.Fatalf("Expected 9 commands, got %d in:\n%s", len(copyCmds), s)
+ }
+
+ ensureMatches(t, copyCmds[8], "^cp -f .*/aconfig_flags.pb .*/image.apex$")
+
+ combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
+ s = " " + combineAconfigRule.Args["cache_files"]
+ aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
+ if len(aconfigArgs) != 3 {
+ t.Fatalf("Expected 3 commands, got %d in:\n%s", len(aconfigArgs), s)
+ }
+ android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
+ android.EnsureListContainsSuffix(t, aconfigArgs, "my_cc_library_bar/android_arm64_armv8-a_shared_apex10000/myapex/aconfig_merged.pb")
+ android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_baz/intermediate.pb")
+
+ buildParams := combineAconfigRule.BuildParams
+ if len(buildParams.Inputs) != 3 {
+ t.Fatalf("Expected 3 input, got %d", len(buildParams.Inputs))
+ }
+ android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
+ android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_cc_library_bar/android_arm64_armv8-a_shared_apex10000/myapex/aconfig_merged.pb")
+ android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_baz/intermediate.pb")
+ ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
+}
+
+func TestAconfigFilesRustDeps(t *testing.T) {
+ ctx := testApex(t, apex_default_bp+`
+ apex {
+ name: "myapex",
+ manifest: ":myapex.manifest",
+ androidManifest: ":myapex.androidmanifest",
+ key: "myapex.key",
+ native_shared_libs: [
+ "libmy_rust_library",
+ ],
+ binaries: [
+ "my_rust_binary",
+ ],
+ rust_dyn_libs: [
+ "libmy_rust_dylib",
+ ],
+ updatable: false,
+ }
+
+ rust_library {
+ name: "libflags_rust", // test mock
+ crate_name: "flags_rust",
+ srcs: ["lib.rs"],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ rust_library {
+ name: "liblazy_static", // test mock
+ crate_name: "lazy_static",
+ srcs: ["src/lib.rs"],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ rust_ffi_shared {
+ name: "libmy_rust_library",
+ srcs: ["src/lib.rs"],
+ rustlibs: ["libmy_rust_aconfig_library_foo"],
+ crate_name: "my_rust_library",
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ rust_library_dylib {
+ name: "libmy_rust_dylib",
+ srcs: ["foo/bar/MyClass.rs"],
+ rustlibs: ["libmy_rust_aconfig_library_bar"],
+ crate_name: "my_rust_dylib",
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ rust_binary {
+ name: "my_rust_binary",
+ srcs: ["foo/bar/MyClass.rs"],
+ rustlibs: [
+ "libmy_rust_aconfig_library_baz",
+ "libmy_rust_dylib",
+ ],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ aconfig_declarations {
+ name: "my_aconfig_declarations_foo",
+ package: "com.example.package",
+ container: "myapex",
+ srcs: ["foo.aconfig"],
+ }
+
+ aconfig_declarations {
+ name: "my_aconfig_declarations_bar",
+ package: "com.example.package",
+ container: "myapex",
+ srcs: ["bar.aconfig"],
+ }
+
+ aconfig_declarations {
+ name: "my_aconfig_declarations_baz",
+ package: "com.example.package",
+ container: "myapex",
+ srcs: ["baz.aconfig"],
+ }
+
+ rust_aconfig_library {
+ name: "libmy_rust_aconfig_library_foo",
+ aconfig_declarations: "my_aconfig_declarations_foo",
+ crate_name: "my_rust_aconfig_library_foo",
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ rust_aconfig_library {
+ name: "libmy_rust_aconfig_library_bar",
+ aconfig_declarations: "my_aconfig_declarations_bar",
+ crate_name: "my_rust_aconfig_library_bar",
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ rust_aconfig_library {
+ name: "libmy_rust_aconfig_library_baz",
+ aconfig_declarations: "my_aconfig_declarations_baz",
+ crate_name: "my_rust_aconfig_library_baz",
+ apex_available: [
+ "myapex",
+ ],
+ }
+ `)
+
+ mod := ctx.ModuleForTests("myapex", "android_common_myapex")
+ s := mod.Rule("apexRule").Args["copy_commands"]
+ copyCmds := regexp.MustCompile(" *&& *").Split(s, -1)
+ if len(copyCmds) != 23 {
+ t.Fatalf("Expected 23 commands, got %d in:\n%s", len(copyCmds), s)
+ }
+
+ ensureMatches(t, copyCmds[22], "^cp -f .*/aconfig_flags.pb .*/image.apex$")
+
+ combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
+ s = " " + combineAconfigRule.Args["cache_files"]
+ aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
+ if len(aconfigArgs) != 2 {
+ t.Fatalf("Expected 2 commands, got %d in:\n%s", len(aconfigArgs), s)
+ }
+ android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
+ android.EnsureListContainsSuffix(t, aconfigArgs, "my_rust_binary/android_arm64_armv8-a_apex10000/myapex/aconfig_merged.pb")
+
+ buildParams := combineAconfigRule.BuildParams
+ if len(buildParams.Inputs) != 2 {
+ t.Fatalf("Expected 3 input, got %d", len(buildParams.Inputs))
+ }
+ android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
+ android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_rust_binary/android_arm64_armv8-a_apex10000/myapex/aconfig_merged.pb")
+ ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
+}
+
+func TestAconfigFilesOnlyMatchCurrentApex(t *testing.T) {
+ ctx := testApex(t, apex_default_bp+`
+ apex {
+ name: "myapex",
+ manifest: ":myapex.manifest",
+ androidManifest: ":myapex.androidmanifest",
+ key: "myapex.key",
+ java_libs: [
+ "my_java_library_foo",
+ "other_java_library_bar",
+ ],
+ updatable: false,
+ }
+
+ java_library {
+ name: "my_java_library_foo",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ static_libs: ["my_java_aconfig_library_foo"],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ java_library {
+ name: "other_java_library_bar",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ static_libs: ["other_java_aconfig_library_bar"],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ aconfig_declarations {
+ name: "my_aconfig_declarations_foo",
+ package: "com.example.package",
+ container: "myapex",
+ srcs: ["foo.aconfig"],
+ }
+
+ java_aconfig_library {
+ name: "my_java_aconfig_library_foo",
+ aconfig_declarations: "my_aconfig_declarations_foo",
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ aconfig_declarations {
+ name: "other_aconfig_declarations_bar",
+ package: "com.example.package",
+ container: "otherapex",
+ srcs: ["bar.aconfig"],
+ }
+
+ java_aconfig_library {
+ name: "other_java_aconfig_library_bar",
+ aconfig_declarations: "other_aconfig_declarations_bar",
+ apex_available: [
+ "myapex",
+ ],
+ }
+ `)
+
+ mod := ctx.ModuleForTests("myapex", "android_common_myapex")
+ combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
+ s := " " + combineAconfigRule.Args["cache_files"]
+ aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
+ if len(aconfigArgs) != 1 {
+ t.Fatalf("Expected 1 commands, got %d in:\n%s", len(aconfigArgs), s)
+ }
+ android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
+
+ buildParams := combineAconfigRule.BuildParams
+ if len(buildParams.Inputs) != 1 {
+ t.Fatalf("Expected 1 input, got %d", len(buildParams.Inputs))
+ }
+ android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
+ ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
+}
+
+func TestAconfigFilesRemoveDuplicates(t *testing.T) {
+ ctx := testApex(t, apex_default_bp+`
+ apex {
+ name: "myapex",
+ manifest: ":myapex.manifest",
+ androidManifest: ":myapex.androidmanifest",
+ key: "myapex.key",
+ java_libs: [
+ "my_java_library_foo",
+ "my_java_library_bar",
+ ],
+ updatable: false,
+ }
+
+ java_library {
+ name: "my_java_library_foo",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ static_libs: ["my_java_aconfig_library_foo"],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ java_library {
+ name: "my_java_library_bar",
+ srcs: ["foo/bar/MyClass.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ static_libs: ["my_java_aconfig_library_bar"],
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ aconfig_declarations {
+ name: "my_aconfig_declarations_foo",
+ package: "com.example.package",
+ container: "myapex",
+ srcs: ["foo.aconfig"],
+ }
+
+ java_aconfig_library {
+ name: "my_java_aconfig_library_foo",
+ aconfig_declarations: "my_aconfig_declarations_foo",
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ java_aconfig_library {
+ name: "my_java_aconfig_library_bar",
+ aconfig_declarations: "my_aconfig_declarations_foo",
+ apex_available: [
+ "myapex",
+ ],
+ }
+ `)
+
+ mod := ctx.ModuleForTests("myapex", "android_common_myapex")
+ combineAconfigRule := mod.Rule("All_aconfig_declarations_dump")
+ s := " " + combineAconfigRule.Args["cache_files"]
+ aconfigArgs := regexp.MustCompile(" --cache ").Split(s, -1)[1:]
+ if len(aconfigArgs) != 1 {
+ t.Fatalf("Expected 1 commands, got %d in:\n%s", len(aconfigArgs), s)
+ }
+ android.EnsureListContainsSuffix(t, aconfigArgs, "my_aconfig_declarations_foo/intermediate.pb")
+
+ buildParams := combineAconfigRule.BuildParams
+ if len(buildParams.Inputs) != 1 {
+ t.Fatalf("Expected 1 input, got %d", len(buildParams.Inputs))
+ }
+ android.EnsureListContainsSuffix(t, buildParams.Inputs.Strings(), "my_aconfig_declarations_foo/intermediate.pb")
+ ensureContains(t, buildParams.Output.String(), "android_common_myapex/aconfig_flags.pb")
+}
+
+// Test that the boot jars come from the _selected_ apex prebuilt
+// RELEASE_APEX_CONTIRBUTIONS_* build flags will be used to select the correct prebuilt for a specific release config
+func TestBootDexJarsMultipleApexPrebuilts(t *testing.T) {
+ checkBootDexJarPath := func(t *testing.T, ctx *android.TestContext, stem string, bootDexJarPath string) {
+ t.Helper()
+ s := ctx.ModuleForTests("dex_bootjars", "android_common")
+ foundLibfooJar := false
+ base := stem + ".jar"
+ for _, output := range s.AllOutputs() {
+ if filepath.Base(output) == base {
+ foundLibfooJar = true
+ buildRule := s.Output(output)
+ android.AssertStringEquals(t, "boot dex jar path", bootDexJarPath, buildRule.Input.String())
+ }
+ }
+ if !foundLibfooJar {
+ t.Errorf("Rule for libfoo.jar missing in dex_bootjars singleton outputs %q", android.StringPathsRelativeToTop(ctx.Config().SoongOutDir(), s.AllOutputs()))
+ }
+ }
+
+ // Check that the boot jars of the selected apex are run through boot_jars_package_check
+ // This validates that the jars on the bootclasspath do not contain packages outside an allowlist
+ checkBootJarsPackageCheck := func(t *testing.T, ctx *android.TestContext, expectedBootJar string) {
+ platformBcp := ctx.ModuleForTests("platform-bootclasspath", "android_common")
+ bootJarsCheckRule := platformBcp.Rule("boot_jars_package_check")
+ android.AssertStringMatches(t, "Could not find the correct boot dex jar in package check rule", bootJarsCheckRule.RuleParams.Command, "build/soong/scripts/check_boot_jars/package_allowed_list.txt.*"+expectedBootJar)
+ }
+
+ // Check that the boot jars used to generate the monolithic hiddenapi flags come from the selected apex
+ checkBootJarsForMonolithicHiddenapi := func(t *testing.T, ctx *android.TestContext, expectedBootJar string) {
+ monolithicHiddenapiFlagsCmd := ctx.ModuleForTests("platform-bootclasspath", "android_common").Output("out/soong/hiddenapi/hiddenapi-stub-flags.txt").RuleParams.Command
+ android.AssertStringMatches(t, "Could not find the correct boot dex jar in monolithic hiddenapi flags generation command", monolithicHiddenapiFlagsCmd, "--boot-dex="+expectedBootJar)
+ }
+
+ bp := `
+ // Source APEX.
+
+ java_library {
+ name: "framework-foo",
+ srcs: ["foo.java"],
+ installable: true,
+ apex_available: [
+ "com.android.foo",
+ ],
+ }
+
+ bootclasspath_fragment {
+ name: "foo-bootclasspath-fragment",
+ contents: ["framework-foo"],
+ apex_available: [
+ "com.android.foo",
+ ],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+
+ apex_key {
+ name: "com.android.foo.key",
+ public_key: "com.android.foo.avbpubkey",
+ private_key: "com.android.foo.pem",
+ }
+
+ apex {
+ name: "com.android.foo",
+ key: "com.android.foo.key",
+ bootclasspath_fragments: ["foo-bootclasspath-fragment"],
+ updatable: false,
+ }
+
+ // Prebuilt APEX.
+
+ java_sdk_library_import {
+ name: "framework-foo",
+ public: {
+ jars: ["foo.jar"],
+ },
+ apex_available: ["com.android.foo"],
+ shared_library: false,
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "foo-bootclasspath-fragment",
+ contents: ["framework-foo"],
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
+ apex_available: [
+ "com.android.foo",
+ ],
+ }
+
+ prebuilt_apex {
+ name: "com.android.foo",
+ apex_name: "com.android.foo",
+ src: "com.android.foo-arm.apex",
+ exported_bootclasspath_fragments: ["foo-bootclasspath-fragment"],
+ }
+
+ // Another Prebuilt ART APEX
+ prebuilt_apex {
+ name: "com.android.foo.v2",
+ apex_name: "com.android.foo", // Used to determine the API domain
+ src: "com.android.foo-arm.apex",
+ exported_bootclasspath_fragments: ["foo-bootclasspath-fragment"],
+ }
+
+ // APEX contribution modules
+
+ apex_contributions {
+ name: "foo.source.contributions",
+ api_domain: "com.android.foo",
+ contents: ["com.android.foo"],
+ }
+
+ apex_contributions {
+ name: "foo.prebuilt.contributions",
+ api_domain: "com.android.foo",
+ contents: ["prebuilt_com.android.foo"],
+ }
+
+ apex_contributions {
+ name: "foo.prebuilt.v2.contributions",
+ api_domain: "com.android.foo",
+ contents: ["com.android.foo.v2"], // prebuilt_ prefix is missing because of prebuilt_rename mutator
+ }
+ `
+
+ testCases := []struct {
+ desc string
+ selectedApexContributions string
+ expectedBootJar string
+ }{
+ {
+ desc: "Source apex com.android.foo is selected, bootjar should come from source java library",
+ selectedApexContributions: "foo.source.contributions",
+ expectedBootJar: "out/soong/.intermediates/foo-bootclasspath-fragment/android_common_apex10000/hiddenapi-modular/encoded/framework-foo.jar",
+ },
+ {
+ desc: "Prebuilt apex prebuilt_com.android.foo is selected, profile should come from .prof deapexed from the prebuilt",
+ selectedApexContributions: "foo.prebuilt.contributions",
+ expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo.deapexer/android_common/deapexer/javalib/framework-foo.jar",
+ },
+ {
+ desc: "Prebuilt apex prebuilt_com.android.foo.v2 is selected, profile should come from .prof deapexed from the prebuilt",
+ selectedApexContributions: "foo.prebuilt.v2.contributions",
+ expectedBootJar: "out/soong/.intermediates/prebuilt_com.android.foo.v2.deapexer/android_common/deapexer/javalib/framework-foo.jar",
+ },
+ }
+
+ fragment := java.ApexVariantReference{
+ Apex: proptools.StringPtr("com.android.foo"),
+ Module: proptools.StringPtr("foo-bootclasspath-fragment"),
+ }
+
+ for _, tc := range testCases {
+ preparer := android.GroupFixturePreparers(
+ java.FixtureConfigureApexBootJars("com.android.foo:framework-foo"),
+ android.FixtureMergeMockFs(map[string][]byte{
+ "system/sepolicy/apex/com.android.foo-file_contexts": nil,
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": tc.selectedApexContributions,
+ }
+ }),
+ )
+ ctx := testDexpreoptWithApexes(t, bp, "", preparer, fragment)
+ checkBootDexJarPath(t, ctx, "framework-foo", tc.expectedBootJar)
+ checkBootJarsPackageCheck(t, ctx, tc.expectedBootJar)
+ checkBootJarsForMonolithicHiddenapi(t, ctx, tc.expectedBootJar)
+ }
+}
+
+// Test that product packaging installs the selected mainline module (either source or a specific prebuilt)
+// RELEASE_APEX_CONTIRBUTIONS_* build flags will be used to select the correct prebuilt for a specific release config
+func TestInstallationRulesForMultipleApexPrebuilts(t *testing.T) {
+ // check that the LOCAL_MODULE in the generated mk file matches the name used in PRODUCT_PACKAGES
+ // Since the name used in PRODUCT_PACKAGES does not contain prebuilt_ prefix, LOCAL_MODULE should not contain any prefix either
+ checkLocalModuleName := func(t *testing.T, ctx *android.TestContext, soongApexModuleName string, expectedLocalModuleName string) {
+ // Variations are created based on apex_name
+ entries := android.AndroidMkEntriesForTest(t, ctx, ctx.ModuleForTests(soongApexModuleName, "android_common_com.android.foo").Module())
+ android.AssertStringEquals(t, "LOCAL_MODULE of the prebuilt apex must match the name listed in PRODUCT_PACKAGES", expectedLocalModuleName, entries[0].EntryMap["LOCAL_MODULE"][0])
+ }
+ // for a mainline module family, check that only the flagged soong module is visible to make
+ checkHideFromMake := func(t *testing.T, ctx *android.TestContext, visibleModuleName string, hiddenModuleNames []string) {
+ variation := func(moduleName string) string {
+ ret := "android_common_com.android.foo"
+ if moduleName == "com.google.android.foo" {
+ ret = "android_common_com.google.android.foo_com.android.foo"
+ }
+ return ret
+ }
+
+ visibleModule := ctx.ModuleForTests(visibleModuleName, variation(visibleModuleName)).Module()
+ android.AssertBoolEquals(t, "Apex "+visibleModuleName+" selected using apex_contributions should be visible to make", false, visibleModule.IsHideFromMake())
+
+ for _, hiddenModuleName := range hiddenModuleNames {
+ hiddenModule := ctx.ModuleForTests(hiddenModuleName, variation(hiddenModuleName)).Module()
+ android.AssertBoolEquals(t, "Apex "+hiddenModuleName+" not selected using apex_contributions should be hidden from make", true, hiddenModule.IsHideFromMake())
+
+ }
+ }
+
+ bp := `
+ apex_key {
+ name: "com.android.foo.key",
+ public_key: "com.android.foo.avbpubkey",
+ private_key: "com.android.foo.pem",
+ }
+
+ // AOSP source apex
+ apex {
+ name: "com.android.foo",
+ key: "com.android.foo.key",
+ updatable: false,
+ }
+
+ // Google source apex
+ override_apex {
+ name: "com.google.android.foo",
+ base: "com.android.foo",
+ key: "com.android.foo.key",
+ }
+
+ // Prebuilt Google APEX.
+
+ prebuilt_apex {
+ name: "com.google.android.foo",
+ apex_name: "com.android.foo",
+ src: "com.android.foo-arm.apex",
+ prefer: true, // prefer is set to true on both the prebuilts to induce an error if flagging is not present
+ }
+
+ // Another Prebuilt Google APEX
+ prebuilt_apex {
+ name: "com.google.android.foo.v2",
+ apex_name: "com.android.foo",
+ source_apex_name: "com.google.android.foo", // source_apex_name becomes LOCAL_MODULE in the generated mk file
+ src: "com.android.foo-arm.apex",
+ prefer: true, // prefer is set to true on both the prebuilts to induce an error if flagging is not present
+ }
+
+ // APEX contribution modules
+
+ apex_contributions {
+ name: "foo.source.contributions",
+ api_domain: "com.android.foo",
+ contents: ["com.google.android.foo"],
+ }
+
+ apex_contributions {
+ name: "foo.prebuilt.contributions",
+ api_domain: "com.android.foo",
+ contents: ["prebuilt_com.google.android.foo"],
+ }
+
+ apex_contributions {
+ name: "foo.prebuilt.v2.contributions",
+ api_domain: "com.android.foo",
+ contents: ["prebuilt_com.google.android.foo.v2"],
+ }
+
+ // This is an incompatible module because it selects multiple versions of the same mainline module
+ apex_contributions {
+ name: "foo.prebuilt.duplicate.contributions",
+ api_domain: "com.android.foo",
+ contents: [
+ "prebuilt_com.google.android.foo",
+ "prebuilt_com.google.android.foo.v2",
+ ],
+ }
+ `
+
+ testCases := []struct {
+ desc string
+ selectedApexContributions string
+ expectedVisibleModuleName string
+ expectedHiddenModuleNames []string
+ expectedError string
+ }{
+ {
+ desc: "Source apex is selected, prebuilts should be hidden from make",
+ selectedApexContributions: "foo.source.contributions",
+ expectedVisibleModuleName: "com.google.android.foo",
+ expectedHiddenModuleNames: []string{"prebuilt_com.google.android.foo", "prebuilt_com.google.android.foo.v2"},
+ },
+ {
+ desc: "Prebuilt apex prebuilt_com.android.foo is selected, source and the other prebuilt should be hidden from make",
+ selectedApexContributions: "foo.prebuilt.contributions",
+ expectedVisibleModuleName: "prebuilt_com.google.android.foo",
+ expectedHiddenModuleNames: []string{"com.google.android.foo", "prebuilt_com.google.android.foo.v2"},
+ },
+ {
+ desc: "Prebuilt apex prebuilt_com.android.fooi.v2 is selected, source and the other prebuilt should be hidden from make",
+ selectedApexContributions: "foo.prebuilt.v2.contributions",
+ expectedVisibleModuleName: "prebuilt_com.google.android.foo.v2",
+ expectedHiddenModuleNames: []string{"com.google.android.foo", "prebuilt_com.google.android.foo"},
+ },
+ {
+ desc: "Multiple versions of a prebuilt apex is selected in the same release config",
+ selectedApexContributions: "foo.prebuilt.duplicate.contributions",
+ expectedError: "Found duplicate variations of the same module in apex_contributions: prebuilt_com.google.android.foo and prebuilt_com.google.android.foo.v2",
+ },
+ }
+
+ for _, tc := range testCases {
+ preparer := android.GroupFixturePreparers(
+ android.FixtureMergeMockFs(map[string][]byte{
+ "system/sepolicy/apex/com.android.foo-file_contexts": nil,
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": tc.selectedApexContributions,
+ }
+ }),
+ )
+ if tc.expectedError != "" {
+ preparer = preparer.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(tc.expectedError))
+ testApex(t, bp, preparer)
+ return
+ }
+ ctx := testApex(t, bp, preparer)
+
+ // Check that the LOCAL_MODULE of the two prebuilts is com.android.foo
+ // This ensures that product packaging can pick them for installation if it has been flagged by apex_contributions
+ checkLocalModuleName(t, ctx, "prebuilt_com.google.android.foo", "com.google.android.foo")
+ checkLocalModuleName(t, ctx, "prebuilt_com.google.android.foo.v2", "com.google.android.foo")
+
+ // Check that
+ // 1. The contents of the selected apex_contributions are visible to make
+ // 2. The rest of the apexes in the mainline module family (source or other prebuilt) is hidden from make
+ checkHideFromMake(t, ctx, tc.expectedVisibleModuleName, tc.expectedHiddenModuleNames)
+ }
+}
diff --git a/apex/bootclasspath_fragment_test.go b/apex/bootclasspath_fragment_test.go
index 89ea004..778c20a 100644
--- a/apex/bootclasspath_fragment_test.go
+++ b/apex/bootclasspath_fragment_test.go
@@ -53,7 +53,11 @@
java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz"),
java.FixtureConfigureApexBootJars("someapex:foo", "someapex:bar"),
prepareForTestWithArtApex,
-
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("foo", "baz"),
).RunTestWithBp(t, `
@@ -152,11 +156,11 @@
// Check stub dex paths exported by art.
artFragment := result.Module("art-bootclasspath-fragment", "android_common")
- artInfo := result.ModuleProvider(artFragment, java.HiddenAPIInfoProvider).(java.HiddenAPIInfo)
+ artInfo, _ := android.SingletonModuleProvider(result, artFragment, java.HiddenAPIInfoProvider)
- bazPublicStubs := "out/soong/.intermediates/baz.stubs/android_common/dex/baz.stubs.jar"
- bazSystemStubs := "out/soong/.intermediates/baz.stubs.system/android_common/dex/baz.stubs.system.jar"
- bazTestStubs := "out/soong/.intermediates/baz.stubs.test/android_common/dex/baz.stubs.test.jar"
+ bazPublicStubs := "out/soong/.intermediates/baz.stubs.exportable/android_common/dex/baz.stubs.exportable.jar"
+ bazSystemStubs := "out/soong/.intermediates/baz.stubs.exportable.system/android_common/dex/baz.stubs.exportable.system.jar"
+ bazTestStubs := "out/soong/.intermediates/baz.stubs.exportable.test/android_common/dex/baz.stubs.exportable.test.jar"
checkAPIScopeStubs("art", artInfo, java.PublicHiddenAPIScope, bazPublicStubs)
checkAPIScopeStubs("art", artInfo, java.SystemHiddenAPIScope, bazSystemStubs)
@@ -165,10 +169,10 @@
// Check stub dex paths exported by other.
otherFragment := result.Module("other-bootclasspath-fragment", "android_common")
- otherInfo := result.ModuleProvider(otherFragment, java.HiddenAPIInfoProvider).(java.HiddenAPIInfo)
+ otherInfo, _ := android.SingletonModuleProvider(result, otherFragment, java.HiddenAPIInfoProvider)
- fooPublicStubs := "out/soong/.intermediates/foo.stubs/android_common/dex/foo.stubs.jar"
- fooSystemStubs := "out/soong/.intermediates/foo.stubs.system/android_common/dex/foo.stubs.system.jar"
+ fooPublicStubs := "out/soong/.intermediates/foo.stubs.exportable/android_common/dex/foo.stubs.exportable.jar"
+ fooSystemStubs := "out/soong/.intermediates/foo.stubs.exportable.system/android_common/dex/foo.stubs.exportable.system.jar"
checkAPIScopeStubs("other", otherInfo, java.PublicHiddenAPIScope, bazPublicStubs, fooPublicStubs)
checkAPIScopeStubs("other", otherInfo, java.SystemHiddenAPIScope, bazSystemStubs, fooSystemStubs)
@@ -312,6 +316,7 @@
java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{
`art-bootclasspath-fragment`,
`com.android.art.key`,
+ `dex2oatd`,
})
// Make sure that the source bootclasspath_fragment copies its dex files to the predefined
@@ -374,7 +379,7 @@
java.FixtureSetBootImageInstallDirOnDevice("art", "apex/com.android.art/javalib"),
).RunTest(t)
- ensureExactDeapexedContents(t, result.TestContext, "com.android.art", "android_common", []string{
+ ensureExactDeapexedContents(t, result.TestContext, "prebuilt_com.android.art", "android_common", []string{
"etc/boot-image.prof",
"javalib/bar.jar",
"javalib/foo.jar",
@@ -383,6 +388,7 @@
java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{
`art-bootclasspath-fragment`,
`com.android.art.key`,
+ `dex2oatd`,
`prebuilt_com.android.art`,
})
@@ -529,14 +535,16 @@
result := preparers.RunTestWithBp(t, fmt.Sprintf(bp, "enabled: false,"))
java.CheckModuleDependencies(t, result.TestContext, "com.android.art", "android_common_com.android.art", []string{
- `com.android.art.apex.selector`,
+ `dex2oatd`,
`prebuilt_art-bootclasspath-fragment`,
+ `prebuilt_com.android.art.apex.selector`,
+ `prebuilt_com.android.art.deapexer`,
})
java.CheckModuleDependencies(t, result.TestContext, "art-bootclasspath-fragment", "android_common_com.android.art", []string{
- `com.android.art.deapexer`,
`dex2oatd`,
`prebuilt_bar`,
+ `prebuilt_com.android.art.deapexer`,
`prebuilt_foo`,
})
@@ -546,7 +554,7 @@
t.Run("enabled alternative APEX", func(t *testing.T) {
preparers.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
- "Multiple installable prebuilt APEXes provide ambiguous deapexers: com.android.art and com.mycompany.android.art")).
+ "Multiple installable prebuilt APEXes provide ambiguous deapexers: prebuilt_com.android.art and prebuilt_com.mycompany.android.art")).
RunTestWithBp(t, fmt.Sprintf(bp, ""))
})
}
@@ -644,6 +652,7 @@
})
java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex", []string{
+ `dex2oatd`,
`myapex.key`,
`mybootclasspathfragment`,
})
@@ -655,7 +664,7 @@
// Make sure that the fragment provides the hidden API encoded dex jars to the APEX.
fragment := result.Module("mybootclasspathfragment", "android_common_apex10000")
- info := result.ModuleProvider(fragment, java.BootclasspathFragmentApexContentInfoProvider).(java.BootclasspathFragmentApexContentInfo)
+ info, _ := android.SingletonModuleProvider(result, fragment, java.BootclasspathFragmentApexContentInfoProvider)
checkFragmentExportedDexJar := func(name string, expectedDexJar string) {
module := result.Module(name, "android_common_apex10000")
@@ -675,7 +684,7 @@
func getDexJarPath(result *android.TestResult, name string) string {
module := result.Module(name, "android_common")
- return module.(java.UsesLibraryDependency).DexJarBuildPath().Path().RelativeToTop().String()
+ return module.(java.UsesLibraryDependency).DexJarBuildPath(moduleErrorfTestCtx{}).Path().RelativeToTop().String()
}
// TestBootclasspathFragment_HiddenAPIList checks to make sure that the correct parameters are
@@ -694,6 +703,11 @@
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("foo", "quuz"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTestWithBp(t, `
apex {
name: "com.android.art",
@@ -805,11 +819,11 @@
"foo",
})
- fooStubs := getDexJarPath(result, "foo.stubs")
- quuzPublicStubs := getDexJarPath(result, "quuz.stubs")
- quuzSystemStubs := getDexJarPath(result, "quuz.stubs.system")
- quuzTestStubs := getDexJarPath(result, "quuz.stubs.test")
- quuzModuleLibStubs := getDexJarPath(result, "quuz.stubs.module_lib")
+ fooStubs := getDexJarPath(result, "foo.stubs.exportable")
+ quuzPublicStubs := getDexJarPath(result, "quuz.stubs.exportable")
+ quuzSystemStubs := getDexJarPath(result, "quuz.stubs.exportable.system")
+ quuzTestStubs := getDexJarPath(result, "quuz.stubs.exportable.test")
+ quuzModuleLibStubs := getDexJarPath(result, "quuz.stubs.exportable.module_lib")
// Make sure that the fragment uses the quuz stub dex jars when generating the hidden API flags.
fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
@@ -832,7 +846,7 @@
// TestBootclasspathFragment_AndroidNonUpdatable checks to make sure that setting
// additional_stubs: ["android-non-updatable"] causes the source android-non-updatable modules to be
// added to the hiddenapi list tool.
-func TestBootclasspathFragment_AndroidNonUpdatable(t *testing.T) {
+func TestBootclasspathFragment_AndroidNonUpdatable_FromSource(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForTestWithBootclasspathFragment,
prepareForTestWithArtApex,
@@ -843,6 +857,9 @@
// Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
// is disabled.
android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.SetBuildFromTextStub(false)
+ }),
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("foo", "android-non-updatable"),
@@ -1000,6 +1017,168 @@
android.AssertStringDoesContain(t, "test", command, "--test-stub-classpath="+nonUpdatableTestStubs)
}
+func TestBootclasspathFragment_AndroidNonUpdatable_FromText(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithBootclasspathFragment,
+ prepareForTestWithArtApex,
+ prepareForTestWithMyapex,
+ // Configure bootclasspath jars to ensure that hidden API encoding is performed on them.
+ java.FixtureConfigureBootJars("com.android.art:baz", "com.android.art:quuz"),
+ java.FixtureConfigureApexBootJars("myapex:foo", "myapex:bar"),
+ // Make sure that the frameworks/base/Android.bp file exists as otherwise hidden API encoding
+ // is disabled.
+ android.FixtureAddTextFile("frameworks/base/Android.bp", ""),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.SetBuildFromTextStub(true)
+ }),
+
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.FixtureWithLastReleaseApis("foo", "android-non-updatable"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "android-non-updatable",
+ srcs: ["b.java"],
+ compile_dex: true,
+ public: {
+ enabled: true,
+ },
+ system: {
+ enabled: true,
+ },
+ test: {
+ enabled: true,
+ },
+ module_lib: {
+ enabled: true,
+ },
+ }
+
+ apex {
+ name: "com.android.art",
+ key: "com.android.art.key",
+ bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "com.android.art.key",
+ public_key: "com.android.art.avbpubkey",
+ private_key: "com.android.art.pem",
+ }
+
+ java_library {
+ name: "baz",
+ apex_available: [
+ "com.android.art",
+ ],
+ srcs: ["b.java"],
+ compile_dex: true,
+ }
+
+ java_library {
+ name: "quuz",
+ apex_available: [
+ "com.android.art",
+ ],
+ srcs: ["b.java"],
+ compile_dex: true,
+ }
+
+ bootclasspath_fragment {
+ name: "art-bootclasspath-fragment",
+ image_name: "art",
+ // Must match the "com.android.art:" entries passed to FixtureConfigureBootJars above.
+ contents: ["baz", "quuz"],
+ apex_available: [
+ "com.android.art",
+ ],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+
+ apex {
+ name: "myapex",
+ key: "myapex.key",
+ bootclasspath_fragments: [
+ "mybootclasspathfragment",
+ ],
+ updatable: false,
+ }
+
+ apex_key {
+ name: "myapex.key",
+ public_key: "testkey.avbpubkey",
+ private_key: "testkey.pem",
+ }
+
+ java_sdk_library {
+ name: "foo",
+ srcs: ["b.java"],
+ shared_library: false,
+ public: {enabled: true},
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ java_library {
+ name: "bar",
+ srcs: ["b.java"],
+ installable: true,
+ apex_available: [
+ "myapex",
+ ],
+ }
+
+ bootclasspath_fragment {
+ name: "mybootclasspathfragment",
+ contents: [
+ "foo",
+ "bar",
+ ],
+ apex_available: [
+ "myapex",
+ ],
+ additional_stubs: ["android-non-updatable"],
+ fragments: [
+ {
+ apex: "com.android.art",
+ module: "art-bootclasspath-fragment",
+ },
+ ],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+ `)
+
+ java.CheckModuleDependencies(t, result.TestContext, "mybootclasspathfragment", "android_common_apex10000", []string{
+ "android-non-updatable.stubs",
+ "android-non-updatable.stubs.system",
+ "android-non-updatable.stubs.test",
+ "android-non-updatable.stubs.test_module_lib",
+ "art-bootclasspath-fragment",
+ "bar",
+ "dex2oatd",
+ "foo",
+ })
+
+ nonUpdatableTestModuleLibStubs := getDexJarPath(result, "android-non-updatable.stubs.test_module_lib")
+
+ // Make sure that the fragment uses the android-non-updatable modules when generating the hidden
+ // API flags.
+ fragment := result.ModuleForTests("mybootclasspathfragment", "android_common_apex10000")
+
+ rule := fragment.Rule("modularHiddenAPIStubFlagsFile")
+ command := rule.RuleParams.Command
+ android.AssertStringDoesContain(t, "check correct rule", command, "hiddenapi list")
+
+ // Make sure that the test_module_lib non-updatable stubs are available for resolving references from
+ // the implementation boot dex jars provided by this module.
+ android.AssertStringDoesContain(t, "android-non-updatable widest", command, "--dependency-stub-dex="+nonUpdatableTestModuleLibStubs)
+}
+
// TestBootclasspathFragment_AndroidNonUpdatable_AlwaysUsePrebuiltSdks checks to make sure that
// setting additional_stubs: ["android-non-updatable"] causes the prebuilt android-non-updatable
// modules to be added to the hiddenapi list tool.
diff --git a/apex/bp2build.go b/apex/bp2build.go
deleted file mode 100644
index a3dda83..0000000
--- a/apex/bp2build.go
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2022 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.
-package apex
-
-import (
- "android/soong/android"
- "encoding/json"
- "strings"
-)
-
-// This file contains the bp2build integration for the apex package.
-
-// Export constants as Starlark using bp2build to Bazel.
-func BazelApexToolchainVars() (string, error) {
- marshalled, err := json.Marshal(apexAvailBaseline)
- if err != nil {
- return "", err
- }
- content := []string{
- "# GENERATED BY SOONG. DO NOT EDIT.",
- "default_manifest_version = " + android.DefaultUpdatableModuleVersion, // constants.go is different in every branch.
- "apex_available_baseline = json.decode('''" + string(marshalled) + "''')",
- }
- return strings.Join(content, "\n"), nil
-}
diff --git a/apex/bp2build_test.go b/apex/bp2build_test.go
deleted file mode 100644
index 6bab67d..0000000
--- a/apex/bp2build_test.go
+++ /dev/null
@@ -1,545 +0,0 @@
-// 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 apex
-
-import (
- "android/soong/android"
- "android/soong/android/allowlists"
- "android/soong/bazel/cquery"
- "fmt"
- "path/filepath"
- "strings"
- "testing"
-)
-
-func TestApexImageInMixedBuilds(t *testing.T) {
- bp := `
-apex_key{
- name: "foo_key",
-}
-
-apex {
- name: "foo",
- key: "foo_key",
- updatable: true,
- min_sdk_version: "31",
- file_contexts: ":myapex-file_contexts",
- bazel_module: { label: "//:foo" },
-}`
-
- outputBaseDir := "out/bazel"
- result := android.GroupFixturePreparers(
- prepareForApexTest,
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: outputBaseDir,
- LabelToApexInfo: map[string]cquery.ApexInfo{
- "//:foo": cquery.ApexInfo{
- // ApexInfo Starlark provider.
- SignedOutput: "signed_out.apex",
- SignedCompressedOutput: "signed_out.capex",
- UnsignedOutput: "unsigned_out.apex",
- BundleKeyInfo: []string{"public_key", "private_key"},
- ContainerKeyInfo: []string{"container_cert", "container_private"},
- SymbolsUsedByApex: "foo_using.txt",
- JavaSymbolsUsedByApex: "foo_using.xml",
- BundleFile: "apex_bundle.zip",
- InstalledFiles: "installed-files.txt",
- RequiresLibs: []string{"//path/c:c", "//path/d:d"},
-
- // unused
- PackageName: "pkg_name",
- ProvidesLibs: []string{"a", "b"},
-
- // ApexMkInfo Starlark provider
- PayloadFilesInfo: []map[string]string{
- {
- "built_file": "bazel-out/adbd",
- "install_dir": "bin",
- "class": "nativeExecutable",
- "make_module_name": "adbd",
- "basename": "adbd",
- "package": "foo",
- },
- },
- MakeModulesToInstall: []string{"c"}, // d deliberately omitted
- },
- },
- }
- }),
- ).RunTestWithBp(t, bp)
-
- m := result.ModuleForTests("foo", "android_common_foo").Module()
- ab, ok := m.(*apexBundle)
-
- if !ok {
- t.Fatalf("Expected module to be an apexBundle, was not")
- }
-
- // TODO: refactor to android.AssertStringEquals
- if w, g := "out/bazel/execroot/__main__/public_key", ab.publicKeyFile.String(); w != g {
- t.Errorf("Expected public key %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/private_key", ab.privateKeyFile.String(); w != g {
- t.Errorf("Expected private key %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/container_cert", ab.containerCertificateFile.String(); w != g {
- t.Errorf("Expected public container key %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/container_private", ab.containerPrivateKeyFile.String(); w != g {
- t.Errorf("Expected private container key %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/signed_out.apex", ab.outputFile.String(); w != g {
- t.Errorf("Expected output file %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/foo_using.txt", ab.nativeApisUsedByModuleFile.String(); w != g {
- t.Errorf("Expected output file %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/foo_using.xml", ab.javaApisUsedByModuleFile.String(); w != g {
- t.Errorf("Expected output file %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/installed-files.txt", ab.installedFilesFile.String(); w != g {
- t.Errorf("Expected installed-files.txt %q, got %q", w, g)
- }
-
- mkData := android.AndroidMkDataForTest(t, result.TestContext, m)
- var builder strings.Builder
- mkData.Custom(&builder, "foo", "BAZEL_TARGET_", "", mkData)
-
- data := builder.String()
- if w := "ALL_MODULES.$(my_register_name).BUNDLE := out/bazel/execroot/__main__/apex_bundle.zip"; !strings.Contains(data, w) {
- t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
- }
- if w := "$(call dist-for-goals,checkbuild,out/bazel/execroot/__main__/installed-files.txt:foo-installed-files.txt)"; !strings.Contains(data, w) {
- t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
- }
-
- // make modules to be installed to system
- if len(ab.makeModulesToInstall) != 1 && ab.makeModulesToInstall[0] != "c" {
- t.Errorf("Expected makeModulesToInstall slice to only contain 'c', got %q", ab.makeModulesToInstall)
- }
- if w := "LOCAL_REQUIRED_MODULES := adbd.foo c"; !strings.Contains(data, w) {
- t.Errorf("Expected %q in androidmk data, but did not find it in %q", w, data)
- }
-}
-
-func TestApexImageCreatesFilesInfoForMake(t *testing.T) {
- bp := `
-apex_key{
- name: "foo_key",
-}
-
-apex {
- name: "foo",
- key: "foo_key",
- updatable: true,
- min_sdk_version: "31",
- file_contexts: ":myapex-file_contexts",
- bazel_module: { label: "//:foo" },
-}`
-
- outputBaseDir := "out/bazel"
- result := android.GroupFixturePreparers(
- prepareForApexTest,
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: outputBaseDir,
- LabelToApexInfo: map[string]cquery.ApexInfo{
- "//:foo": {
- // ApexInfo Starlark provider. Necessary for the test.
- SignedOutput: "signed_out.apex",
- BundleKeyInfo: []string{"public_key", "private_key"},
- ContainerKeyInfo: []string{"container_cert", "container_private"},
-
- // ApexMkInfo Starlark provider
- PayloadFilesInfo: []map[string]string{
- {
- "arch": "arm64",
- "basename": "libcrypto.so",
- "built_file": "bazel-out/64/libcrypto.so",
- "class": "nativeSharedLib",
- "install_dir": "lib64",
- "make_module_name": "libcrypto",
- "package": "foo/bar",
- "unstripped_built_file": "bazel-out/64/unstripped_libcrypto.so",
- },
- {
- "arch": "arm",
- "basename": "libcrypto.so",
- "built_file": "bazel-out/32/libcrypto.so",
- "class": "nativeSharedLib",
- "install_dir": "lib",
- "make_module_name": "libcrypto",
- "package": "foo/bar",
- },
- {
- "arch": "arm64",
- "basename": "adbd",
- "built_file": "bazel-out/adbd",
- "class": "nativeExecutable",
- "install_dir": "bin",
- "make_module_name": "adbd",
- "package": "foo",
- },
- },
- },
- },
- }
- }),
- ).RunTestWithBp(t, bp)
-
- m := result.ModuleForTests("foo", "android_common_foo").Module()
- ab, ok := m.(*apexBundle)
-
- if !ok {
- t.Fatalf("Expected module to be an apexBundle, was not")
- }
-
- expectedFilesInfo := []apexFile{
- {
- androidMkModuleName: "libcrypto",
- builtFile: android.PathForTesting("out/bazel/execroot/__main__/bazel-out/64/libcrypto.so"),
- class: nativeSharedLib,
- customStem: "libcrypto.so",
- installDir: "lib64",
- moduleDir: "foo/bar",
- arch: "arm64",
- unstrippedBuiltFile: android.PathForTesting("out/bazel/execroot/__main__/bazel-out/64/unstripped_libcrypto.so"),
- },
- {
- androidMkModuleName: "libcrypto",
- builtFile: android.PathForTesting("out/bazel/execroot/__main__/bazel-out/32/libcrypto.so"),
- class: nativeSharedLib,
- customStem: "libcrypto.so",
- installDir: "lib",
- moduleDir: "foo/bar",
- arch: "arm",
- },
- {
- androidMkModuleName: "adbd",
- builtFile: android.PathForTesting("out/bazel/execroot/__main__/bazel-out/adbd"),
- class: nativeExecutable,
- customStem: "adbd",
- installDir: "bin",
- moduleDir: "foo",
- arch: "arm64",
- },
- }
-
- if len(ab.filesInfo) != len(expectedFilesInfo) {
- t.Errorf("Expected %d entries in ab.filesInfo, but got %d", len(ab.filesInfo), len(expectedFilesInfo))
- }
-
- for idx, f := range ab.filesInfo {
- expected := expectedFilesInfo[idx]
- android.AssertSame(t, "different class", expected.class, f.class)
- android.AssertStringEquals(t, "different built file", expected.builtFile.String(), f.builtFile.String())
- android.AssertStringEquals(t, "different custom stem", expected.customStem, f.customStem)
- android.AssertStringEquals(t, "different install dir", expected.installDir, f.installDir)
- android.AssertStringEquals(t, "different make module name", expected.androidMkModuleName, f.androidMkModuleName)
- android.AssertStringEquals(t, "different moduleDir", expected.moduleDir, f.moduleDir)
- android.AssertStringEquals(t, "different arch", expected.arch, f.arch)
- if expected.unstrippedBuiltFile != nil {
- if f.unstrippedBuiltFile == nil {
- t.Errorf("expected an unstripped built file path.")
- }
- android.AssertStringEquals(t, "different unstripped built file", expected.unstrippedBuiltFile.String(), f.unstrippedBuiltFile.String())
- }
- }
-}
-
-func TestCompressedApexImageInMixedBuilds(t *testing.T) {
- bp := `
-apex_key{
- name: "foo_key",
-}
-apex {
- name: "foo",
- key: "foo_key",
- updatable: true,
- min_sdk_version: "31",
- file_contexts: ":myapex-file_contexts",
- bazel_module: { label: "//:foo" },
- test_only_force_compression: true, // force compression
-}`
-
- outputBaseDir := "out/bazel"
- result := android.GroupFixturePreparers(
- prepareForApexTest,
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: outputBaseDir,
- LabelToApexInfo: map[string]cquery.ApexInfo{
- "//:foo": cquery.ApexInfo{
- SignedOutput: "signed_out.apex",
- SignedCompressedOutput: "signed_out.capex",
- BundleKeyInfo: []string{"public_key", "private_key"},
- ContainerKeyInfo: []string{"container_cert", "container_private"},
- },
- },
- }
- }),
- ).RunTestWithBp(t, bp)
-
- m := result.ModuleForTests("foo", "android_common_foo").Module()
- ab, ok := m.(*apexBundle)
- if !ok {
- t.Fatalf("Expected module to be an apexBundle, was not")
- }
-
- if w, g := "out/bazel/execroot/__main__/signed_out.capex", ab.outputFile.String(); w != g {
- t.Errorf("Expected output file to be compressed apex %q, got %q", w, g)
- }
-
- mkData := android.AndroidMkDataForTest(t, result.TestContext, m)
- var builder strings.Builder
- mkData.Custom(&builder, "foo", "BAZEL_TARGET_", "", mkData)
-
- data := builder.String()
-
- expectedAndroidMk := []string{
- "LOCAL_PREBUILT_MODULE_FILE := out/bazel/execroot/__main__/signed_out.capex",
-
- // Check that the source install file is the capex. The dest is not important.
- "LOCAL_SOONG_INSTALL_PAIRS := out/bazel/execroot/__main__/signed_out.capex:",
- }
- for _, androidMk := range expectedAndroidMk {
- if !strings.Contains(data, androidMk) {
- t.Errorf("Expected %q in androidmk data, but did not find %q", androidMk, data)
- }
- }
-}
-
-func TestOverrideApexImageInMixedBuilds(t *testing.T) {
- originalBp := `
-apex_key{
- name: "foo_key",
-}
-apex_key{
- name: "override_foo_key",
-}
-apex {
- name: "foo",
- key: "foo_key",
- updatable: true,
- min_sdk_version: "31",
- package_name: "pkg_name",
- file_contexts: ":myapex-file_contexts",
- %s
-}`
- overrideBp := `
-override_apex {
- name: "override_foo",
- key: "override_foo_key",
- package_name: "override_pkg_name",
- base: "foo",
- %s
-}
-`
-
- originalApexBpDir := "original"
- originalApexName := "foo"
- overrideApexBpDir := "override"
- overrideApexName := "override_foo"
-
- defaultApexLabel := fmt.Sprintf("//%s:%s", originalApexBpDir, originalApexName)
- defaultOverrideApexLabel := fmt.Sprintf("//%s:%s", overrideApexBpDir, overrideApexName)
-
- testCases := []struct {
- desc string
- bazelModuleProp string
- apexLabel string
- overrideBazelModuleProp string
- overrideApexLabel string
- bp2buildConfiguration android.Bp2BuildConversionAllowlist
- }{
- {
- desc: "both explicit labels",
- bazelModuleProp: `bazel_module: { label: "//:foo" },`,
- apexLabel: "//:foo",
- overrideBazelModuleProp: `bazel_module: { label: "//:override_foo" },`,
- overrideApexLabel: "//:override_foo",
- bp2buildConfiguration: android.NewBp2BuildAllowlist(),
- },
- {
- desc: "both explicitly allowed",
- bazelModuleProp: `bazel_module: { bp2build_available: true },`,
- apexLabel: defaultApexLabel,
- overrideBazelModuleProp: `bazel_module: { bp2build_available: true },`,
- overrideApexLabel: defaultOverrideApexLabel,
- bp2buildConfiguration: android.NewBp2BuildAllowlist(),
- },
- {
- desc: "original allowed by dir, override allowed by name",
- apexLabel: defaultApexLabel,
- overrideApexLabel: defaultOverrideApexLabel,
- bp2buildConfiguration: android.NewBp2BuildAllowlist().SetDefaultConfig(
- map[string]allowlists.BazelConversionConfigEntry{
- originalApexBpDir: allowlists.Bp2BuildDefaultTrue,
- }).SetModuleAlwaysConvertList([]string{
- overrideApexName,
- }),
- },
- {
- desc: "both allowed by name",
- apexLabel: defaultApexLabel,
- overrideApexLabel: defaultOverrideApexLabel,
- bp2buildConfiguration: android.NewBp2BuildAllowlist().SetModuleAlwaysConvertList([]string{
- originalApexName,
- overrideApexName,
- }),
- },
- {
- desc: "override allowed by name",
- apexLabel: defaultApexLabel,
- overrideApexLabel: defaultOverrideApexLabel,
- bp2buildConfiguration: android.NewBp2BuildAllowlist().SetModuleAlwaysConvertList([]string{
- overrideApexName,
- }),
- },
- {
- desc: "override allowed by dir",
- apexLabel: defaultApexLabel,
- overrideApexLabel: defaultOverrideApexLabel,
- bp2buildConfiguration: android.NewBp2BuildAllowlist().SetDefaultConfig(
- map[string]allowlists.BazelConversionConfigEntry{
- overrideApexBpDir: allowlists.Bp2BuildDefaultTrue,
- }).SetModuleAlwaysConvertList([]string{}),
- },
- }
-
- for _, tc := range testCases {
- t.Run(tc.desc, func(t *testing.T) {
- outputBaseDir := "out/bazel"
- result := android.GroupFixturePreparers(
- prepareForApexTest,
- android.FixtureAddTextFile(filepath.Join(originalApexBpDir, "Android.bp"), fmt.Sprintf(originalBp, tc.bazelModuleProp)),
- android.FixtureAddTextFile(filepath.Join(overrideApexBpDir, "Android.bp"), fmt.Sprintf(overrideBp, tc.overrideBazelModuleProp)),
- android.FixtureModifyContext(func(ctx *android.TestContext) {
- ctx.RegisterBp2BuildConfig(tc.bp2buildConfiguration)
- }),
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: outputBaseDir,
- LabelToApexInfo: map[string]cquery.ApexInfo{
- tc.apexLabel: cquery.ApexInfo{
- // ApexInfo Starlark provider
- SignedOutput: "signed_out.apex",
- UnsignedOutput: "unsigned_out.apex",
- BundleKeyInfo: []string{"public_key", "private_key"},
- ContainerKeyInfo: []string{"container_cert", "container_private"},
- SymbolsUsedByApex: "foo_using.txt",
- JavaSymbolsUsedByApex: "foo_using.xml",
- BundleFile: "apex_bundle.zip",
- InstalledFiles: "installed-files.txt",
- RequiresLibs: []string{"//path/c:c", "//path/d:d"},
-
- // unused
- PackageName: "pkg_name",
- ProvidesLibs: []string{"a", "b"},
-
- // ApexMkInfo Starlark provider
- MakeModulesToInstall: []string{"c"}, // d deliberately omitted
- },
- tc.overrideApexLabel: cquery.ApexInfo{
- // ApexInfo Starlark provider
- SignedOutput: "override_signed_out.apex",
- UnsignedOutput: "override_unsigned_out.apex",
- BundleKeyInfo: []string{"override_public_key", "override_private_key"},
- ContainerKeyInfo: []string{"override_container_cert", "override_container_private"},
- SymbolsUsedByApex: "override_foo_using.txt",
- JavaSymbolsUsedByApex: "override_foo_using.xml",
- BundleFile: "override_apex_bundle.zip",
- InstalledFiles: "override_installed-files.txt",
- RequiresLibs: []string{"//path/c:c", "//path/d:d"},
-
- // unused
- PackageName: "override_pkg_name",
- ProvidesLibs: []string{"a", "b"},
-
- // ApexMkInfo Starlark provider
- MakeModulesToInstall: []string{"c"}, // d deliberately omitted
- },
- },
- }
- }),
- ).RunTest(t)
-
- m := result.ModuleForTests("foo", "android_common_override_foo_foo").Module()
- ab, ok := m.(*apexBundle)
- if !ok {
- t.Fatalf("Expected module to be an apexBundle, was not")
- }
-
- if w, g := "out/bazel/execroot/__main__/override_public_key", ab.publicKeyFile.String(); w != g {
- t.Errorf("Expected public key %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/override_private_key", ab.privateKeyFile.String(); w != g {
- t.Errorf("Expected private key %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/override_container_cert", ab.containerCertificateFile; g != nil && w != g.String() {
- t.Errorf("Expected public container key %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/override_container_private", ab.containerPrivateKeyFile; g != nil && w != g.String() {
- t.Errorf("Expected private container key %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/override_signed_out.apex", ab.outputFile.String(); w != g {
- t.Errorf("Expected output file %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/override_foo_using.txt", ab.nativeApisUsedByModuleFile.String(); w != g {
- t.Errorf("Expected output file %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/override_foo_using.xml", ab.javaApisUsedByModuleFile.String(); w != g {
- t.Errorf("Expected output file %q, got %q", w, g)
- }
-
- if w, g := "out/bazel/execroot/__main__/override_installed-files.txt", ab.installedFilesFile.String(); w != g {
- t.Errorf("Expected installed-files.txt %q, got %q", w, g)
- }
-
- mkData := android.AndroidMkDataForTest(t, result.TestContext, m)
- var builder strings.Builder
- mkData.Custom(&builder, "override_foo", "BAZEL_TARGET_", "", mkData)
-
- data := builder.String()
- if w := "ALL_MODULES.$(my_register_name).BUNDLE := out/bazel/execroot/__main__/override_apex_bundle.zip"; !strings.Contains(data, w) {
- t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
- }
- if w := "$(call dist-for-goals,checkbuild,out/bazel/execroot/__main__/override_installed-files.txt:override_foo-installed-files.txt)"; !strings.Contains(data, w) {
- t.Errorf("Expected %q in androidmk data, but did not find %q", w, data)
- }
-
- // make modules to be installed to system
- if len(ab.makeModulesToInstall) != 1 || ab.makeModulesToInstall[0] != "c" {
- t.Errorf("Expected makeModulestoInstall slice to only contain 'c', got %q", ab.makeModulesToInstall)
- }
- if w := "LOCAL_REQUIRED_MODULES := c"; !strings.Contains(data, w) {
- t.Errorf("Expected %q in androidmk data, but did not find it in %q", w, data)
- }
- })
- }
-}
diff --git a/apex/builder.go b/apex/builder.go
index 4b42b74..3078863 100644
--- a/apex/builder.go
+++ b/apex/builder.go
@@ -17,12 +17,14 @@
import (
"encoding/json"
"fmt"
+ "path"
"path/filepath"
"runtime"
"sort"
"strconv"
"strings"
+ "android/soong/aconfig"
"android/soong/android"
"android/soong/java"
@@ -35,6 +37,7 @@
)
func init() {
+ pctx.Import("android/soong/aconfig")
pctx.Import("android/soong/android")
pctx.Import("android/soong/cc/config")
pctx.Import("android/soong/java")
@@ -74,7 +77,12 @@
pctx.HostBinToolVariable("apex_sepolicy_tests", "apex_sepolicy_tests")
pctx.HostBinToolVariable("deapexer", "deapexer")
pctx.HostBinToolVariable("debugfs_static", "debugfs_static")
+ pctx.HostBinToolVariable("fsck_erofs", "fsck.erofs")
pctx.SourcePathVariable("genNdkUsedbyApexPath", "build/soong/scripts/gen_ndk_usedby_apex.sh")
+ pctx.HostBinToolVariable("conv_linker_config", "conv_linker_config")
+ pctx.HostBinToolVariable("assemble_vintf", "assemble_vintf")
+ pctx.HostBinToolVariable("apex_elf_checker", "apex_elf_checker")
+ pctx.HostBinToolVariable("aconfig", "aconfig")
}
var (
@@ -222,6 +230,24 @@
CommandDeps: []string{"${apex_sepolicy_tests}", "${deapexer}", "${debugfs_static}"},
Description: "run apex_sepolicy_tests",
})
+
+ apexLinkerconfigValidationRule = pctx.StaticRule("apexLinkerconfigValidationRule", blueprint.RuleParams{
+ Command: `${conv_linker_config} validate --type apex ${image_dir} && touch ${out}`,
+ CommandDeps: []string{"${conv_linker_config}"},
+ Description: "run apex_linkerconfig_validation",
+ }, "image_dir")
+
+ assembleVintfRule = pctx.StaticRule("assembleVintfRule", blueprint.RuleParams{
+ Command: `rm -f $out && VINTF_IGNORE_TARGET_FCM_VERSION=true ${assemble_vintf} -i $in -o $out`,
+ CommandDeps: []string{"${assemble_vintf}"},
+ Description: "run assemble_vintf",
+ })
+
+ apexElfCheckerUnwantedRule = pctx.StaticRule("apexElfCheckerUnwantedRule", blueprint.RuleParams{
+ Command: `${apex_elf_checker} --tool_path ${tool_path} --unwanted ${unwanted} ${in} && touch ${out}`,
+ CommandDeps: []string{"${apex_elf_checker}", "${deapexer}", "${debugfs_static}", "${fsck_erofs}", "${config.ClangBin}/llvm-readelf"},
+ Description: "run apex_elf_checker --unwanted",
+ }, "tool_path", "unwanted")
)
// buildManifest creates buile rules to modify the input apex_manifest.json to add information
@@ -321,10 +347,12 @@
func (a *apexBundle) buildFileContexts(ctx android.ModuleContext) android.OutputPath {
var fileContexts android.Path
var fileContextsDir string
+ isFileContextsModule := false
if a.properties.File_contexts == nil {
fileContexts = android.PathForSource(ctx, "system/sepolicy/apex", ctx.ModuleName()+"-file_contexts")
} else {
if m, t := android.SrcIsModuleWithTag(*a.properties.File_contexts); m != "" {
+ isFileContextsModule = true
otherModule := android.GetModuleFromPathDep(ctx, m, t)
fileContextsDir = ctx.OtherModuleDir(otherModule)
}
@@ -340,7 +368,7 @@
ctx.PropertyErrorf("file_contexts", "should be under system/sepolicy, but found in %q", fileContextsDir)
}
}
- if !android.ExistentPathForSource(ctx, fileContexts.String()).Valid() {
+ if !isFileContextsModule && !android.ExistentPathForSource(ctx, fileContexts.String()).Valid() {
ctx.PropertyErrorf("file_contexts", "cannot find file_contexts file: %q", fileContexts.String())
}
@@ -349,12 +377,12 @@
output := android.PathForModuleOut(ctx, "file_contexts")
rule := android.NewRuleBuilder(pctx, ctx)
- forceLabel := "u:object_r:system_file:s0"
+ labelForRoot := "u:object_r:system_file:s0"
+ labelForManifest := "u:object_r:system_file:s0"
if a.SocSpecific() && !a.vndkApex {
- // APEX on /vendor should label ./ and ./apex_manifest.pb as vendor_apex_metadata_file.
- // The reason why we skip VNDK APEX is that aosp_{pixel device} targets install VNDK APEX on /vendor
- // even though VNDK APEX is supposed to be installed on /system. (See com.android.vndk.current.on_vendor)
- forceLabel = "u:object_r:vendor_apex_metadata_file:s0"
+ // APEX on /vendor should label ./ and ./apex_manifest.pb as vendor file.
+ labelForRoot = "u:object_r:vendor_file:s0"
+ labelForManifest = "u:object_r:vendor_apex_metadata_file:s0"
}
// remove old file
rule.Command().Text("rm").FlagWithOutput("-f ", output)
@@ -364,8 +392,8 @@
rule.Command().Text("echo").Text(">>").Output(output)
if !useFileContextsAsIs {
// force-label /apex_manifest.pb and /
- rule.Command().Text("echo").Text("/apex_manifest\\\\.pb").Text(forceLabel).Text(">>").Output(output)
- rule.Command().Text("echo").Text("/").Text(forceLabel).Text(">>").Output(output)
+ rule.Command().Text("echo").Text("/apex_manifest\\\\.pb").Text(labelForManifest).Text(">>").Output(output)
+ rule.Command().Text("echo").Text("/").Text(labelForRoot).Text(">>").Output(output)
}
rule.Build("file_contexts."+a.Name(), "Generate file_contexts")
@@ -444,6 +472,22 @@
})
}
+func isVintfFragment(fi apexFile) bool {
+ isVintfFragment, _ := path.Match("etc/vintf/*.xml", fi.path())
+ return isVintfFragment
+}
+
+func runAssembleVintf(ctx android.ModuleContext, vintfFragment android.Path) android.Path {
+ processed := android.PathForModuleOut(ctx, "vintf", vintfFragment.Base())
+ ctx.Build(pctx, android.BuildParams{
+ Rule: assembleVintfRule,
+ Input: vintfFragment,
+ Output: processed,
+ Description: "run assemble_vintf for VINTF in APEX",
+ })
+ return processed
+}
+
// buildApex creates build rules to build an APEX using apexer.
func (a *apexBundle) buildApex(ctx android.ModuleContext) {
suffix := imageApexSuffix
@@ -481,7 +525,15 @@
copyCommands = append(copyCommands, "ln -sfn "+pathOnDevice+" "+destPath)
} else {
// Copy the file into APEX
- copyCommands = append(copyCommands, "cp -f "+fi.builtFile.String()+" "+destPath)
+ if !a.testApex && isVintfFragment(fi) {
+ // copy the output of assemble_vintf instead of the original
+ vintfFragment := runAssembleVintf(ctx, fi.builtFile)
+ copyCommands = append(copyCommands, "cp -f "+vintfFragment.String()+" "+destPath)
+ implicitInputs = append(implicitInputs, vintfFragment)
+ } else {
+ copyCommands = append(copyCommands, "cp -f "+fi.builtFile.String()+" "+destPath)
+ implicitInputs = append(implicitInputs, fi.builtFile)
+ }
var installedPath android.InstallPath
if fi.class == appSet {
@@ -499,7 +551,6 @@
installedPath = ctx.InstallFile(apexDir.Join(ctx, fi.installDir), fi.stem(), fi.builtFile)
}
}
- implicitInputs = append(implicitInputs, fi.builtFile)
// Create additional symlinks pointing the file inside the APEX (if any). Note that
// this is independent from the symlink optimization.
@@ -517,13 +568,8 @@
// Copy the test files (if any)
for _, d := range fi.dataPaths {
// TODO(eakammer): This is now the third repetition of ~this logic for test paths, refactoring should be possible
- relPath := d.SrcPath.Rel()
- dataPath := d.SrcPath.String()
- if !strings.HasSuffix(dataPath, relPath) {
- panic(fmt.Errorf("path %q does not end with %q", dataPath, relPath))
- }
-
- dataDest := imageDir.Join(ctx, fi.apexRelativePath(relPath), d.RelativeInstallPath).String()
+ relPath := d.ToRelativeInstallPath()
+ dataDest := imageDir.Join(ctx, fi.apexRelativePath(relPath)).String()
copyCommands = append(copyCommands, "cp -f "+d.SrcPath.String()+" "+dataDest)
implicitInputs = append(implicitInputs, d.SrcPath)
@@ -531,6 +577,7 @@
installMapSet[installMapPath.String()+":"+fi.installDir+"/"+fi.builtFile.Base()] = true
}
+
implicitInputs = append(implicitInputs, a.manifestPbOut)
if len(installMapSet) > 0 {
@@ -585,10 +632,28 @@
outHostBinDir := ctx.Config().HostToolPath(ctx, "").String()
prebuiltSdkToolsBinDir := filepath.Join("prebuilts", "sdk", "tools", runtime.GOOS, "bin")
+ defaultReadOnlyFiles := []string{"apex_manifest.json", "apex_manifest.pb"}
+ if len(a.aconfigFiles) > 0 {
+ apexAconfigFile := android.PathForModuleOut(ctx, "aconfig_flags.pb")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: aconfig.AllDeclarationsRule,
+ Inputs: a.aconfigFiles,
+ Output: apexAconfigFile,
+ Description: "combine_aconfig_declarations",
+ Args: map[string]string{
+ "cache_files": android.JoinPathsWithPrefix(a.aconfigFiles, "--cache "),
+ },
+ })
+
+ copyCommands = append(copyCommands, "cp -f "+apexAconfigFile.String()+" "+imageDir.String())
+ implicitInputs = append(implicitInputs, apexAconfigFile)
+ defaultReadOnlyFiles = append(defaultReadOnlyFiles, apexAconfigFile.Base())
+ }
+
////////////////////////////////////////////////////////////////////////////////////
// Step 2: create canned_fs_config which encodes filemode,uid,gid of each files
// in this APEX. The file will be used by apexer in later steps.
- cannedFsConfig := a.buildCannedFsConfig(ctx)
+ cannedFsConfig := a.buildCannedFsConfig(ctx, defaultReadOnlyFiles)
implicitInputs = append(implicitInputs, cannedFsConfig)
////////////////////////////////////////////////////////////////////////////////////
@@ -843,10 +908,15 @@
args["outCommaList"] = signedOutputFile.String()
}
var validations android.Paths
+ validations = append(validations, runApexLinkerconfigValidation(ctx, unsignedOutputFile.OutputPath, imageDir.OutputPath))
// TODO(b/279688635) deapexer supports [ext4]
if suffix == imageApexSuffix && ext4 == a.payloadFsType {
validations = append(validations, runApexSepolicyTests(ctx, unsignedOutputFile.OutputPath))
}
+ if !a.testApex && len(a.properties.Unwanted_transitive_deps) > 0 {
+ validations = append(validations,
+ runApexElfCheckerUnwanted(ctx, unsignedOutputFile.OutputPath, a.properties.Unwanted_transitive_deps))
+ }
ctx.Build(pctx, android.BuildParams{
Rule: rule,
Description: "signapk",
@@ -905,10 +975,12 @@
// Install to $OUT/soong/{target,host}/.../apex.
a.installedFile = ctx.InstallFile(a.installDir, a.Name()+installSuffix, a.outputFile,
- a.compatSymlinks.Paths()...)
+ a.compatSymlinks...)
// installed-files.txt is dist'ed
a.installedFilesFile = a.buildInstalledFilesFile(ctx, a.outputFile, imageDir)
+
+ a.apexKeysPath = writeApexKeys(ctx, a)
}
// getCertificateAndPrivateKey retrieves the cert and the private key that will be used to sign
@@ -1032,8 +1104,8 @@
a.lintReports = java.BuildModuleLintReportZips(ctx, depSetsBuilder.Build())
}
-func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext) android.OutputPath {
- var readOnlyPaths = []string{"apex_manifest.json", "apex_manifest.pb"}
+func (a *apexBundle) buildCannedFsConfig(ctx android.ModuleContext, defaultReadOnlyFiles []string) android.OutputPath {
+ var readOnlyPaths = defaultReadOnlyFiles
var executablePaths []string // this also includes dirs
var appSetDirs []string
appSetFiles := make(map[string]android.Path)
@@ -1042,7 +1114,8 @@
if f.installDir == "bin" || strings.HasPrefix(f.installDir, "bin/") {
executablePaths = append(executablePaths, pathInApex)
for _, d := range f.dataPaths {
- readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, d.RelativeInstallPath, d.SrcPath.Rel()))
+ rel := d.ToRelativeInstallPath()
+ readOnlyPaths = append(readOnlyPaths, filepath.Join(f.installDir, rel))
}
for _, s := range f.symlinks {
executablePaths = append(executablePaths, filepath.Join(f.installDir, s))
@@ -1097,6 +1170,19 @@
return cannedFsConfig.OutputPath
}
+func runApexLinkerconfigValidation(ctx android.ModuleContext, apexFile android.OutputPath, imageDir android.OutputPath) android.Path {
+ timestamp := android.PathForModuleOut(ctx, "apex_linkerconfig_validation.timestamp")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: apexLinkerconfigValidationRule,
+ Input: apexFile,
+ Output: timestamp,
+ Args: map[string]string{
+ "image_dir": imageDir.String(),
+ },
+ })
+ return timestamp
+}
+
// Runs apex_sepolicy_tests
//
// $ deapexer list -Z {apex_file} > {file_contexts}
@@ -1110,3 +1196,17 @@
})
return timestamp
}
+
+func runApexElfCheckerUnwanted(ctx android.ModuleContext, apexFile android.OutputPath, unwanted []string) android.Path {
+ timestamp := android.PathForModuleOut(ctx, "apex_elf_unwanted.timestamp")
+ ctx.Build(pctx, android.BuildParams{
+ Rule: apexElfCheckerUnwantedRule,
+ Input: apexFile,
+ Output: timestamp,
+ Args: map[string]string{
+ "unwanted": android.JoinWithSuffixAndSeparator(unwanted, ".so", ":"),
+ "tool_path": ctx.Config().HostToolPath(ctx, "").String() + ":${config.ClangBin}",
+ },
+ })
+ return timestamp
+}
diff --git a/apex/classpath_element_test.go b/apex/classpath_element_test.go
index 9142eed..b9a9198 100644
--- a/apex/classpath_element_test.go
+++ b/apex/classpath_element_test.go
@@ -20,7 +20,6 @@
"android/soong/android"
"android/soong/java"
- "github.com/google/blueprint"
)
// Contains tests for java.CreateClasspathElements logic from java/classpath_element.go that
@@ -28,19 +27,12 @@
// testClasspathElementContext is a ClasspathElementContext suitable for use in tests.
type testClasspathElementContext struct {
+ android.OtherModuleProviderContext
testContext *android.TestContext
module android.Module
errs []error
}
-func (t *testClasspathElementContext) OtherModuleHasProvider(module blueprint.Module, provider blueprint.ProviderKey) bool {
- return t.testContext.ModuleHasProvider(module, provider)
-}
-
-func (t *testClasspathElementContext) OtherModuleProvider(module blueprint.Module, provider blueprint.ProviderKey) interface{} {
- return t.testContext.ModuleProvider(module, provider)
-}
-
func (t *testClasspathElementContext) ModuleErrorf(fmt string, args ...interface{}) {
t.errs = append(t.errs, t.testContext.ModuleErrorf(t.module, fmt, args...))
}
@@ -238,7 +230,11 @@
}
newCtx := func() *testClasspathElementContext {
- return &testClasspathElementContext{testContext: result.TestContext, module: bootclasspath}
+ return &testClasspathElementContext{
+ OtherModuleProviderContext: result.TestContext.OtherModuleProviderAdaptor(),
+ testContext: result.TestContext,
+ module: bootclasspath,
+ }
}
// Verify that CreateClasspathElements works when given valid input.
diff --git a/apex/deapexer.go b/apex/deapexer.go
index 3b7c77d..a673108 100644
--- a/apex/deapexer.go
+++ b/apex/deapexer.go
@@ -53,6 +53,10 @@
// all architectures, e.g. java.
CommonModules []string
+ // List of modules that use an embedded .prof to guide optimization of the equivalent dexpreopt artifact
+ // This is a subset of CommonModules
+ DexpreoptProfileGuidedModules []string
+
// List of files exported from the .apex file by this module
//
// Each entry is a path from the apex root, e.g. javalib/core-libart.jar.
@@ -98,6 +102,7 @@
func (p *Deapexer) DepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies from the java modules to which this exports files from the `.apex` file onto
// this module so that they can access the `DeapexerInfo` object that this provides.
+ // TODO: b/308174306 - Once all the mainline modules have been flagged, drop this dependency edge
for _, lib := range p.properties.CommonModules {
dep := prebuiltApexExportedModuleName(ctx, lib)
ctx.AddReverseDependency(ctx.Module(), android.DeapexerTag, dep)
@@ -126,8 +131,9 @@
// apex relative path to extracted file path available for other modules.
if len(exports) > 0 {
// Make the information available for other modules.
- di := android.NewDeapexerInfo(apexModuleName(ctx.ModuleName()), exports)
- ctx.SetProvider(android.DeapexerProvider, di)
+ di := android.NewDeapexerInfo(apexModuleName(ctx.ModuleName()), exports, p.properties.CommonModules)
+ di.AddDexpreoptProfileGuidedExportedModuleNames(p.properties.DexpreoptProfileGuidedModules...)
+ android.SetProvider(ctx, android.DeapexerProvider, di)
// Create a sorted list of the files that this exports.
exportedPaths = android.SortedUniquePaths(exportedPaths)
diff --git a/apex/dexpreopt_bootjars_test.go b/apex/dexpreopt_bootjars_test.go
index 2e828ca..7a17f50 100644
--- a/apex/dexpreopt_bootjars_test.go
+++ b/apex/dexpreopt_bootjars_test.go
@@ -164,6 +164,7 @@
"out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar",
"out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/art-bootclasspath-fragment/boot.prof",
"out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
+ "out/soong/dexpreopt/uffd_gc_flag.txt",
}
expectedOutputs := []string{
@@ -199,8 +200,9 @@
"out/soong/dexpreopt_arm64/dex_bootjars_input/foo.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/bar.jar",
"out/soong/dexpreopt_arm64/dex_bootjars_input/baz.jar",
- "out/soong/.intermediates/com.android.art.deapexer/android_common/deapexer/etc/boot-image.prof",
+ "out/soong/.intermediates/prebuilt_com.android.art.deapexer/android_common/deapexer/etc/boot-image.prof",
"out/soong/.intermediates/default/java/dex_bootjars/android_common/boot/boot.prof",
+ "out/soong/dexpreopt/uffd_gc_flag.txt",
}
expectedOutputs := []string{
@@ -252,3 +254,162 @@
testDexpreoptBoot(t, ruleFile, expectedInputs, expectedOutputs, false)
}
+
+// Multiple ART apexes might exist in the tree.
+// The profile should correspond to the apex selected using release build flags
+func TestDexpreoptProfileWithMultiplePrebuiltArtApexes(t *testing.T) {
+ ruleFile := "out/soong/dexpreopt_arm64/dex_bootjars/android/system/framework/arm64/boot.art"
+ bp := `
+ // Platform.
+
+ platform_bootclasspath {
+ name: "platform-bootclasspath",
+ fragments: [
+ {
+ apex: "com.android.art",
+ module: "art-bootclasspath-fragment",
+ },
+ ],
+ }
+
+ // Source ART APEX.
+
+ java_library {
+ name: "core-oj",
+ srcs: ["core-oj.java"],
+ installable: true,
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ bootclasspath_fragment {
+ name: "art-bootclasspath-fragment",
+ image_name: "art",
+ contents: ["core-oj"],
+ apex_available: [
+ "com.android.art",
+ ],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+
+ apex_key {
+ name: "com.android.art.key",
+ public_key: "com.android.art.avbpubkey",
+ private_key: "com.android.art.pem",
+ }
+
+ apex {
+ name: "com.android.art",
+ key: "com.android.art.key",
+ bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ updatable: false,
+ }
+
+ // Prebuilt ART APEX.
+
+ java_import {
+ name: "core-oj",
+ jars: ["core-oj.jar"],
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ prebuilt_bootclasspath_fragment {
+ name: "art-bootclasspath-fragment",
+ image_name: "art",
+ contents: ["core-oj"],
+ hidden_api: {
+ annotation_flags: "my-bootclasspath-fragment/annotation-flags.csv",
+ metadata: "my-bootclasspath-fragment/metadata.csv",
+ index: "my-bootclasspath-fragment/index.csv",
+ stub_flags: "my-bootclasspath-fragment/stub-flags.csv",
+ all_flags: "my-bootclasspath-fragment/all-flags.csv",
+ },
+ apex_available: [
+ "com.android.art",
+ ],
+ }
+
+ prebuilt_apex {
+ name: "com.android.art",
+ apex_name: "com.android.art",
+ src: "com.android.art-arm.apex",
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ }
+
+ // Another Prebuilt ART APEX
+ prebuilt_apex {
+ name: "com.android.art.v2",
+ apex_name: "com.android.art", // Used to determine the API domain
+ src: "com.android.art-arm.apex",
+ exported_bootclasspath_fragments: ["art-bootclasspath-fragment"],
+ }
+
+ // APEX contribution modules
+
+ apex_contributions {
+ name: "art.source.contributions",
+ api_domain: "com.android.art",
+ contents: ["com.android.art"],
+ }
+
+ apex_contributions {
+ name: "art.prebuilt.contributions",
+ api_domain: "com.android.art",
+ contents: ["prebuilt_com.android.art"],
+ }
+
+ apex_contributions {
+ name: "art.prebuilt.v2.contributions",
+ api_domain: "com.android.art",
+ contents: ["com.android.art.v2"], // prebuilt_ prefix is missing because of prebuilt_rename mutator
+ }
+
+ `
+
+ testCases := []struct {
+ desc string
+ selectedArtApexContributions string
+ expectedProfile string
+ }{
+ {
+ desc: "Source apex com.android.art is selected, profile should come from source java library",
+ selectedArtApexContributions: "art.source.contributions",
+ expectedProfile: "out/soong/.intermediates/art-bootclasspath-fragment/android_common_apex10000/art-bootclasspath-fragment/boot.prof",
+ },
+ {
+ desc: "Prebuilt apex prebuilt_com.android.art is selected, profile should come from .prof deapexed from the prebuilt",
+ selectedArtApexContributions: "art.prebuilt.contributions",
+ expectedProfile: "out/soong/.intermediates/prebuilt_com.android.art.deapexer/android_common/deapexer/etc/boot-image.prof",
+ },
+ {
+ desc: "Prebuilt apex prebuilt_com.android.art.v2 is selected, profile should come from .prof deapexed from the prebuilt",
+ selectedArtApexContributions: "art.prebuilt.v2.contributions",
+ expectedProfile: "out/soong/.intermediates/prebuilt_com.android.art.v2.deapexer/android_common/deapexer/etc/boot-image.prof",
+ },
+ }
+ for _, tc := range testCases {
+ result := android.GroupFixturePreparers(
+ java.PrepareForTestWithDexpreopt,
+ java.PrepareForTestWithJavaSdkLibraryFiles,
+ java.FixtureConfigureBootJars("com.android.art:core-oj"),
+ PrepareForTestWithApexBuildComponents,
+ prepareForTestWithArtApex,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ART": tc.selectedArtApexContributions,
+ }
+ }),
+ ).RunTestWithBp(t, bp)
+
+ dexBootJars := result.ModuleForTests("dex_bootjars", "android_common")
+ rule := dexBootJars.Output(ruleFile)
+
+ inputs := rule.Implicits.Strings()
+ android.AssertStringListContains(t, tc.desc, inputs, tc.expectedProfile)
+ }
+}
diff --git a/apex/key.go b/apex/key.go
index 65e739a..e4214f0 100644
--- a/apex/key.go
+++ b/apex/key.go
@@ -16,12 +16,8 @@
import (
"fmt"
- "sort"
- "strings"
"android/soong/android"
- "android/soong/bazel"
-
"github.com/google/blueprint/proptools"
)
@@ -33,12 +29,10 @@
func registerApexKeyBuildComponents(ctx android.RegistrationContext) {
ctx.RegisterModuleType("apex_key", ApexKeyFactory)
- ctx.RegisterParallelSingletonType("apex_keys_text", apexKeysTextFactory)
}
type apexKey struct {
android.ModuleBase
- android.BazelModuleBase
properties apexKeyProperties
@@ -61,7 +55,6 @@
module := &apexKey{}
module.AddProperties(&module.properties)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
- android.InitBazelModule(module)
return module
}
@@ -102,135 +95,63 @@
}
}
-// //////////////////////////////////////////////////////////////////////
-// apex_keys_text
-type apexKeysText struct {
- output android.OutputPath
+type apexKeyEntry struct {
+ name string
+ presigned bool
+ publicKey string
+ privateKey string
+ containerCertificate string
+ containerPrivateKey string
+ partition string
+ signTool string
}
-func (s *apexKeysText) GenerateBuildActions(ctx android.SingletonContext) {
- s.output = android.PathForOutput(ctx, "apexkeys.txt")
- type apexKeyEntry struct {
- name string
- presigned bool
- publicKey string
- privateKey string
- containerCertificate string
- containerPrivateKey string
- partition string
- signTool string
+func (e apexKeyEntry) String() string {
+ signTool := ""
+ if e.signTool != "" {
+ signTool = fmt.Sprintf(" sign_tool=%q", e.signTool)
}
- toString := func(e apexKeyEntry) string {
- signTool := ""
- if e.signTool != "" {
- signTool = fmt.Sprintf(" sign_tool=%q", e.signTool)
+ format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q%s\n"
+ if e.presigned {
+ return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", e.partition, signTool)
+ } else {
+ return fmt.Sprintf(format, e.name, e.publicKey, e.privateKey, e.containerCertificate, e.containerPrivateKey, e.partition, signTool)
+ }
+}
+
+func apexKeyEntryFor(ctx android.ModuleContext, module android.Module) apexKeyEntry {
+ switch m := module.(type) {
+ case *apexBundle:
+ pem, key := m.getCertificateAndPrivateKey(ctx)
+ return apexKeyEntry{
+ name: m.Name() + ".apex",
+ presigned: false,
+ publicKey: m.publicKeyFile.String(),
+ privateKey: m.privateKeyFile.String(),
+ containerCertificate: pem.String(),
+ containerPrivateKey: key.String(),
+ partition: m.PartitionTag(ctx.DeviceConfig()),
+ signTool: proptools.String(m.properties.Custom_sign_tool),
}
- format := "name=%q public_key=%q private_key=%q container_certificate=%q container_private_key=%q partition=%q%s\n"
- if e.presigned {
- return fmt.Sprintf(format, e.name, "PRESIGNED", "PRESIGNED", "PRESIGNED", "PRESIGNED", e.partition, signTool)
- } else {
- return fmt.Sprintf(format, e.name, e.publicKey, e.privateKey, e.containerCertificate, e.containerPrivateKey, e.partition, signTool)
+ case *Prebuilt:
+ return apexKeyEntry{
+ name: m.InstallFilename(),
+ presigned: true,
+ partition: m.PartitionTag(ctx.DeviceConfig()),
+ }
+ case *ApexSet:
+ return apexKeyEntry{
+ name: m.InstallFilename(),
+ presigned: true,
+ partition: m.PartitionTag(ctx.DeviceConfig()),
}
}
-
- apexKeyMap := make(map[string]apexKeyEntry)
- ctx.VisitAllModules(func(module android.Module) {
- if m, ok := module.(*apexBundle); ok && m.Enabled() && m.installable() {
- pem, key := m.getCertificateAndPrivateKey(ctx)
- apexKeyMap[m.Name()] = apexKeyEntry{
- name: m.Name() + ".apex",
- presigned: false,
- publicKey: m.publicKeyFile.String(),
- privateKey: m.privateKeyFile.String(),
- containerCertificate: pem.String(),
- containerPrivateKey: key.String(),
- partition: m.PartitionTag(ctx.DeviceConfig()),
- signTool: proptools.String(m.properties.Custom_sign_tool),
- }
- }
- })
-
- // Find prebuilts and let them override apexBundle if they are preferred
- ctx.VisitAllModules(func(module android.Module) {
- if m, ok := module.(*Prebuilt); ok && m.Enabled() && m.installable() &&
- m.Prebuilt().UsePrebuilt() {
- apexKeyMap[m.BaseModuleName()] = apexKeyEntry{
- name: m.InstallFilename(),
- presigned: true,
- partition: m.PartitionTag(ctx.DeviceConfig()),
- }
- }
- })
-
- // Find apex_set and let them override apexBundle or prebuilts. This is done in a separate pass
- // so that apex_set are not overridden by prebuilts.
- ctx.VisitAllModules(func(module android.Module) {
- if m, ok := module.(*ApexSet); ok && m.Enabled() {
- entry := apexKeyEntry{
- name: m.InstallFilename(),
- presigned: true,
- partition: m.PartitionTag(ctx.DeviceConfig()),
- }
- apexKeyMap[m.BaseModuleName()] = entry
- }
- })
-
- // iterating over map does not give consistent ordering in golang
- var moduleNames []string
- for key, _ := range apexKeyMap {
- moduleNames = append(moduleNames, key)
- }
- sort.Strings(moduleNames)
-
- var filecontent strings.Builder
- for _, name := range moduleNames {
- filecontent.WriteString(toString(apexKeyMap[name]))
- }
- android.WriteFileRule(ctx, s.output, filecontent.String())
+ panic(fmt.Errorf("unknown type(%t) for apexKeyEntry", module))
}
-func apexKeysTextFactory() android.Singleton {
- return &apexKeysText{}
-}
-
-func (s *apexKeysText) MakeVars(ctx android.MakeVarsContext) {
- ctx.Strict("SOONG_APEX_KEYS_FILE", s.output.String())
-}
-
-// For Bazel / bp2build
-
-type bazelApexKeyAttributes struct {
- Public_key bazel.LabelAttribute
- Public_key_name bazel.StringAttribute
-
- Private_key bazel.LabelAttribute
- Private_key_name bazel.StringAttribute
-}
-
-// ConvertWithBp2build performs conversion apexKey for bp2build
-func (m *apexKey) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- apexKeyBp2BuildInternal(ctx, m)
-}
-
-func apexKeyBp2BuildInternal(ctx android.TopDownMutatorContext, module *apexKey) {
- privateKeyLabelAttribute, privateKeyNameAttribute :=
- android.BazelStringOrLabelFromProp(ctx, module.properties.Private_key)
-
- publicKeyLabelAttribute, publicKeyNameAttribute :=
- android.BazelStringOrLabelFromProp(ctx, module.properties.Public_key)
-
- attrs := &bazelApexKeyAttributes{
- Private_key: privateKeyLabelAttribute,
- Private_key_name: privateKeyNameAttribute,
-
- Public_key: publicKeyLabelAttribute,
- Public_key_name: publicKeyNameAttribute,
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "apex_key",
- Bzl_load_location: "//build/bazel/rules/apex:apex_key.bzl",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
+func writeApexKeys(ctx android.ModuleContext, module android.Module) android.WritablePath {
+ path := android.PathForModuleOut(ctx, "apexkeys.txt")
+ entry := apexKeyEntryFor(ctx, module)
+ android.WriteFileRuleVerbatim(ctx, path, entry.String())
+ return path
}
diff --git a/apex/platform_bootclasspath_test.go b/apex/platform_bootclasspath_test.go
index 05bb136..2bd3159 100644
--- a/apex/platform_bootclasspath_test.go
+++ b/apex/platform_bootclasspath_test.go
@@ -152,10 +152,10 @@
).RunTest(t)
pbcp := result.Module("platform-bootclasspath", "android_common")
- info := result.ModuleProvider(pbcp, java.MonolithicHiddenAPIInfoProvider).(java.MonolithicHiddenAPIInfo)
+ info, _ := android.SingletonModuleProvider(result, pbcp, java.MonolithicHiddenAPIInfoProvider)
for _, category := range java.HiddenAPIFlagFileCategories {
- name := category.PropertyName
+ name := category.PropertyName()
message := fmt.Sprintf("category %s", name)
filename := strings.ReplaceAll(name, "_", "-")
expected := []string{fmt.Sprintf("%s.txt", filename), fmt.Sprintf("bar-%s.txt", filename)}
@@ -234,7 +234,7 @@
)
pbcp := result.Module("myplatform-bootclasspath", "android_common")
- info := result.ModuleProvider(pbcp, java.MonolithicHiddenAPIInfoProvider).(java.MonolithicHiddenAPIInfo)
+ info, _ := android.SingletonModuleProvider(result, pbcp, java.MonolithicHiddenAPIInfoProvider)
android.AssertArrayString(t, "stub flags", []string{"prebuilt-stub-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv"}, info.StubFlagSubsets.RelativeToTop())
android.AssertArrayString(t, "all flags", []string{"prebuilt-all-flags.csv:out/soong/.intermediates/mybootclasspath-fragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv"}, info.FlagSubsets.RelativeToTop())
@@ -252,6 +252,11 @@
java.FixtureWithLastReleaseApis("foo"),
java.PrepareForTestWithDexpreopt,
dexpreopt.FixtureDisableDexpreoptBootImages(false),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTestWithBp(t, `
apex {
name: "com.android.art",
@@ -382,11 +387,14 @@
// Make sure that the myplatform-bootclasspath has the correct dependencies.
CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
+ // source vs prebuilt selection metadata module
+ `platform:all_apex_contributions`,
+
// The following are stubs.
- `platform:android_stubs_current`,
- `platform:android_system_stubs_current`,
- `platform:android_test_stubs_current`,
- `platform:legacy.core.platform.api.stubs`,
+ `platform:android_stubs_current_exportable`,
+ `platform:android_system_stubs_current_exportable`,
+ `platform:android_test_stubs_current_exportable`,
+ `platform:legacy.core.platform.api.stubs.exportable`,
// Needed for generating the boot image.
`platform:dex2oatd`,
@@ -419,6 +427,9 @@
java.PrepareForTestWithJavaSdkLibraryFiles,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.Always_use_prebuilt_sdks = proptools.BoolPtr(true)
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
}),
java.FixtureWithPrebuiltApis(map[string][]string{
"current": {},
@@ -534,13 +545,16 @@
// Make sure that the myplatform-bootclasspath has the correct dependencies.
CheckModuleDependencies(t, result.TestContext, "myplatform-bootclasspath", "android_common", []string{
+ // source vs prebuilt selection metadata module
+ `platform:all_apex_contributions`,
+
// The following are stubs.
"platform:prebuilt_sdk_public_current_android",
"platform:prebuilt_sdk_system_current_android",
"platform:prebuilt_sdk_test_current_android",
// Not a prebuilt as no prebuilt existed when it was added.
- "platform:legacy.core.platform.api.stubs",
+ "platform:legacy.core.platform.api.stubs.exportable",
// The platform_bootclasspath intentionally adds dependencies on both source and prebuilt
// modules when available as it does not know which one will be preferred.
diff --git a/apex/prebuilt.go b/apex/prebuilt.go
index 1a90c3a..399d9b9 100644
--- a/apex/prebuilt.go
+++ b/apex/prebuilt.go
@@ -22,6 +22,7 @@
"strings"
"android/soong/android"
+ "android/soong/dexpreopt"
"android/soong/java"
"android/soong/provenance"
@@ -50,6 +51,7 @@
type prebuiltCommon struct {
android.ModuleBase
+ java.Dexpreopter
prebuilt android.Prebuilt
// Properties common to both prebuilt_apex and apex_set.
@@ -60,6 +62,9 @@
installedFile android.InstallPath
outputApex android.WritablePath
+ // fragment for this apex for apexkeys.txt
+ apexKeysPath android.WritablePath
+
// A list of apexFile objects created in prebuiltCommon.initApexFilesForAndroidMk which are used
// to create make modules in prebuiltCommon.AndroidMkEntries.
apexFilesForAndroidMk []apexFile
@@ -82,6 +87,12 @@
// device (/apex/<apex_name>). If unspecified, follows the name property.
Apex_name *string
+ // Name of the source APEX that gets shadowed by this prebuilt
+ // e.g. com.mycompany.android.myapex
+ // If unspecified, follows the naming convention that the source apex of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_apex_name *string
+
ForceDisable bool `blueprint:"mutated"`
// whether the extracted apex file is installable.
@@ -121,7 +132,11 @@
}
func (p *prebuiltCommon) ApexVariationName() string {
- return proptools.StringDefault(p.prebuiltCommonProperties.Apex_name, p.ModuleBase.BaseModuleName())
+ return proptools.StringDefault(p.prebuiltCommonProperties.Apex_name, p.BaseModuleName())
+}
+
+func (p *prebuiltCommon) BaseModuleName() string {
+ return proptools.StringDefault(p.prebuiltCommonProperties.Source_apex_name, p.ModuleBase.BaseModuleName())
}
func (p *prebuiltCommon) Prebuilt() *android.Prebuilt {
@@ -167,50 +182,46 @@
return proptools.BoolDefault(p.prebuiltCommonProperties.Installable, true)
}
-// initApexFilesForAndroidMk initializes the prebuiltCommon.apexFilesForAndroidMk field from the
-// modules that this depends upon.
+// To satisfy java.DexpreopterInterface
+func (p *prebuiltCommon) IsInstallable() bool {
+ return p.installable()
+}
+
+// initApexFilesForAndroidMk initializes the prebuiltCommon.requiredModuleNames field with the install only deps of the prebuilt apex
func (p *prebuiltCommon) initApexFilesForAndroidMk(ctx android.ModuleContext) {
- // Walk the dependencies of this module looking for the java modules that it exports.
- ctx.WalkDeps(func(child, parent android.Module) bool {
- tag := ctx.OtherModuleDependencyTag(child)
+ // If this apex contains a system server jar, then the dexpreopt artifacts should be added as required
+ for _, install := range p.Dexpreopter.DexpreoptBuiltInstalledForApex() {
+ p.requiredModuleNames = append(p.requiredModuleNames, install.FullModuleName())
+ }
+}
- name := android.RemoveOptionalPrebuiltPrefix(ctx.OtherModuleName(child))
- if java.IsBootclasspathFragmentContentDepTag(tag) ||
- java.IsSystemServerClasspathFragmentContentDepTag(tag) || tag == exportedJavaLibTag {
- // If the exported java module provides a dex jar path then add it to the list of apexFiles.
- path := child.(interface {
- DexJarBuildPath() java.OptionalDexJarPath
- }).DexJarBuildPath()
- if path.IsSet() {
- af := apexFile{
- module: child,
- moduleDir: ctx.OtherModuleDir(child),
- androidMkModuleName: name,
- builtFile: path.Path(),
- class: javaSharedLib,
- }
- if module, ok := child.(java.DexpreopterInterface); ok {
- for _, install := range module.DexpreoptBuiltInstalledForApex() {
- af.requiredModuleNames = append(af.requiredModuleNames, install.FullModuleName())
- }
- }
- p.apexFilesForAndroidMk = append(p.apexFilesForAndroidMk, af)
- }
- } else if tag == exportedBootclasspathFragmentTag {
- _, ok := child.(*java.PrebuiltBootclasspathFragmentModule)
- if !ok {
- ctx.PropertyErrorf("exported_bootclasspath_fragments", "%q is not a prebuilt_bootclasspath_fragment module", name)
- return false
- }
- // Visit the children of the bootclasspath_fragment.
- return true
- } else if tag == exportedSystemserverclasspathFragmentTag {
- // Visit the children of the systemserver_fragment.
- return true
+// If this prebuilt has system server jar, create the rules to dexpreopt it and install it alongside the prebuilt apex
+func (p *prebuiltCommon) dexpreoptSystemServerJars(ctx android.ModuleContext) {
+ // If this apex does not export anything, return
+ if !p.hasExportedDeps() {
+ return
+ }
+ // If this prebuilt apex has not been selected, return
+ if p.IsHideFromMake() {
+ return
+ }
+ // Use apex_name to determine the api domain of this prebuilt apex
+ apexName := p.ApexVariationName()
+ di, err := android.FindDeapexerProviderForModule(ctx)
+ if err != nil {
+ ctx.ModuleErrorf(err.Error())
+ }
+ dc := dexpreopt.GetGlobalConfig(ctx)
+ systemServerJarList := dc.AllApexSystemServerJars(ctx)
+
+ for i := 0; i < systemServerJarList.Len(); i++ {
+ sscpApex := systemServerJarList.Apex(i)
+ sscpJar := systemServerJarList.Jar(i)
+ if apexName != sscpApex {
+ continue
}
-
- return false
- })
+ p.Dexpreopter.DexpreoptPrebuiltApexSystemServerJars(ctx, sscpJar, di)
+ }
}
func (p *prebuiltCommon) addRequiredModules(entries *android.AndroidMkEntries) {
@@ -229,6 +240,7 @@
OutputFile: android.OptionalPathForPath(p.outputApex),
Include: "$(BUILD_PREBUILT)",
Host_required: p.hostRequired,
+ OverrideName: p.BaseModuleName(),
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetString("LOCAL_MODULE_PATH", p.installDir.String())
@@ -238,12 +250,18 @@
entries.AddStrings("LOCAL_SOONG_INSTALL_SYMLINKS", p.compatSymlinks.Strings()...)
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", !p.installable())
entries.AddStrings("LOCAL_OVERRIDES_MODULES", p.prebuiltCommonProperties.Overrides...)
+ entries.SetString("LOCAL_APEX_KEY_PATH", p.apexKeysPath.String())
p.addRequiredModules(entries)
},
},
},
}
+ // Add the dexpreopt artifacts to androidmk
+ for _, install := range p.Dexpreopter.DexpreoptBuiltInstalledForApex() {
+ entriesList = append(entriesList, install.ToMakeEntries())
+ }
+
// Iterate over the apexFilesForAndroidMk list and create an AndroidMkEntries struct for each
// file. This provides similar behavior to that provided in apexBundle.AndroidMk() as it makes the
// apex specific variants of the exported java modules available for use from within make.
@@ -424,7 +442,7 @@
// Create contents for the prebuilt_apex and store it away for later use.
apexContents := android.NewApexContents(contents)
- mctx.SetProvider(ApexBundleInfoProvider, ApexBundleInfo{
+ android.SetProvider(mctx, android.ApexBundleInfoProvider, android.ApexBundleInfo{
Contents: apexContents,
})
@@ -433,7 +451,7 @@
apexInfo := android.ApexInfo{
ApexVariationName: apexVariationName,
InApexVariants: []string{apexVariationName},
- InApexModules: []string{p.ModuleBase.BaseModuleName()}, // BaseModuleName() to avoid the prebuilt_ prefix.
+ InApexModules: []string{p.BaseModuleName()}, // BaseModuleName() to avoid the prebuilt_ prefix.
ApexContents: []*android.ApexContents{apexContents},
ForPrebuiltApex: true,
}
@@ -480,6 +498,9 @@
inputApex android.Path
provenanceMetaDataFile android.OutputPath
+
+ // Single aconfig "cache file" merged from this module and all dependencies.
+ mergedAconfigFiles map[string]android.Paths
}
type ApexFileProperties struct {
@@ -608,6 +629,7 @@
// Compute the deapexer properties from the transitive dependencies of this module.
commonModules := []string{}
+ dexpreoptProfileGuidedModules := []string{}
exportedFiles := []string{}
ctx.WalkDeps(func(child, parent android.Module) bool {
tag := ctx.OtherModuleDependencyTag(child)
@@ -621,9 +643,14 @@
if _, ok := tag.(android.RequiresFilesFromPrebuiltApexTag); ok {
commonModules = append(commonModules, name)
- requiredFiles := child.(android.RequiredFilesFromPrebuiltApex).RequiredFilesFromPrebuiltApex(ctx)
+ extract := child.(android.RequiredFilesFromPrebuiltApex)
+ requiredFiles := extract.RequiredFilesFromPrebuiltApex(ctx)
exportedFiles = append(exportedFiles, requiredFiles...)
+ if extract.UseProfileGuidedDexpreopt() {
+ dexpreoptProfileGuidedModules = append(dexpreoptProfileGuidedModules, name)
+ }
+
// Visit the dependencies of this module just in case they also require files from the
// prebuilt apex.
return true
@@ -636,7 +663,8 @@
deapexerProperties := &DeapexerProperties{
// Remove any duplicates from the common modules lists as a module may be included via a direct
// dependency as well as transitive ones.
- CommonModules: android.SortedUniqueStrings(commonModules),
+ CommonModules: android.SortedUniqueStrings(commonModules),
+ DexpreoptProfileGuidedModules: android.SortedUniqueStrings(dexpreoptProfileGuidedModules),
}
// Populate the exported files property in a fixed order.
@@ -736,13 +764,11 @@
// V V V
// selector <--- deapexer <--- exported java lib
func (p *Prebuilt) createPrebuiltApexModules(ctx android.TopDownMutatorContext) {
- baseModuleName := p.BaseModuleName()
-
- apexSelectorModuleName := apexSelectorModuleName(baseModuleName)
+ apexSelectorModuleName := apexSelectorModuleName(p.Name())
createApexSelectorModule(ctx, apexSelectorModuleName, &p.properties.ApexFileProperties)
apexFileSource := ":" + apexSelectorModuleName
- p.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(baseModuleName), apexFileSource)
+ p.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(p.Name()), apexFileSource)
// Add a source reference to retrieve the selected apex from the selector module.
p.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource)
@@ -752,13 +778,49 @@
p.prebuiltApexContentsDeps(ctx)
}
+func (p *prebuiltCommon) DepsMutator(ctx android.BottomUpMutatorContext) {
+ if p.hasExportedDeps() {
+ // Create a dependency from the prebuilt apex (prebuilt_apex/apex_set) to the internal deapexer module
+ // The deapexer will return a provider that will be bubbled up to the rdeps of apexes (e.g. dex_bootjars)
+ ctx.AddDependency(ctx.Module(), android.DeapexerTag, deapexerModuleName(p.Name()))
+ }
+}
+
var _ ApexInfoMutator = (*Prebuilt)(nil)
func (p *Prebuilt) ApexInfoMutator(mctx android.TopDownMutatorContext) {
p.apexInfoMutator(mctx)
}
+// Set a provider containing information about the jars and .prof provided by the apex
+// Apexes built from prebuilts retrieve this information by visiting its internal deapexer module
+// Used by dex_bootjars to generate the boot image
+func (p *prebuiltCommon) provideApexExportsInfo(ctx android.ModuleContext) {
+ if !p.hasExportedDeps() {
+ // nothing to do
+ return
+ }
+ if di, err := android.FindDeapexerProviderForModule(ctx); err == nil {
+ javaModuleToDexPath := map[string]android.Path{}
+ for _, commonModule := range di.GetExportedModuleNames() {
+ if dex := di.PrebuiltExportPath(java.ApexRootRelativePathToJavaLib(commonModule)); dex != nil {
+ javaModuleToDexPath[commonModule] = dex
+ }
+ }
+
+ exports := android.ApexExportsInfo{
+ ApexName: p.ApexVariationName(),
+ ProfilePathOnHost: di.PrebuiltExportPath(java.ProfileInstallPathInApex),
+ LibraryNameToDexJarPathOnHost: javaModuleToDexPath,
+ }
+ android.SetProvider(ctx, android.ApexExportsInfoProvider, exports)
+ } else {
+ ctx.ModuleErrorf(err.Error())
+ }
+}
+
func (p *Prebuilt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ p.apexKeysPath = writeApexKeys(ctx, p)
// TODO(jungjw): Check the key validity.
p.inputApex = android.OptionalPathForModuleSrc(ctx, p.prebuiltCommonProperties.Selected_apex).Path()
p.installDir = android.PathForModuleInstall(ctx, "apex")
@@ -778,6 +840,12 @@
return
}
+ // dexpreopt any system server jars if present
+ p.dexpreoptSystemServerJars(ctx)
+
+ // provide info used for generating the boot image
+ p.provideApexExportsInfo(ctx)
+
// Save the files that need to be made available to Make.
p.initApexFilesForAndroidMk(ctx)
@@ -789,9 +857,11 @@
}
if p.installable() {
- p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, p.compatSymlinks.Paths()...)
+ p.installedFile = ctx.InstallFile(p.installDir, p.installFilename, p.inputApex, p.compatSymlinks...)
p.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, p.inputApex, p.installedFile)
}
+
+ android.CollectDependencyAconfigFiles(ctx, &p.mergedAconfigFiles)
}
func (p *Prebuilt) ProvenanceMetaDataFile() android.OutputPath {
@@ -952,13 +1022,11 @@
// from those provided this creates an extractor module which extracts the appropriate .apex file
// from the zip file containing them.
func (a *ApexSet) createPrebuiltApexModules(ctx android.TopDownMutatorContext) {
- baseModuleName := a.BaseModuleName()
-
- apexExtractorModuleName := apexExtractorModuleName(baseModuleName)
+ apexExtractorModuleName := apexExtractorModuleName(a.Name())
createApexExtractorModule(ctx, apexExtractorModuleName, &a.properties.ApexExtractorProperties)
apexFileSource := ":" + apexExtractorModuleName
- a.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(baseModuleName), apexFileSource)
+ a.createDeapexerModuleIfNeeded(ctx, deapexerModuleName(a.Name()), apexFileSource)
// After passing the arch specific src properties to the creating the apex selector module
a.prebuiltCommonProperties.Selected_apex = proptools.StringPtr(apexFileSource)
@@ -975,6 +1043,7 @@
}
func (a *ApexSet) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ a.apexKeysPath = writeApexKeys(ctx, a)
a.installFilename = a.InstallFilename()
if !strings.HasSuffix(a.installFilename, imageApexSuffix) && !strings.HasSuffix(a.installFilename, imageCapexSuffix) {
ctx.ModuleErrorf("filename should end in %s or %s for apex_set", imageApexSuffix, imageCapexSuffix)
@@ -993,6 +1062,12 @@
return
}
+ // dexpreopt any system server jars if present
+ a.dexpreoptSystemServerJars(ctx)
+
+ // provide info used for generating the boot image
+ a.provideApexExportsInfo(ctx)
+
// Save the files that need to be made available to Make.
a.initApexFilesForAndroidMk(ctx)
diff --git a/apex/systemserver_classpath_fragment_test.go b/apex/systemserver_classpath_fragment_test.go
index 40d0581..f6c53b2 100644
--- a/apex/systemserver_classpath_fragment_test.go
+++ b/apex/systemserver_classpath_fragment_test.go
@@ -106,6 +106,7 @@
})
java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{
+ `dex2oatd`,
`myapex.key`,
`mysystemserverclasspathfragment`,
})
@@ -162,6 +163,7 @@
})
java.CheckModuleDependencies(t, result.TestContext, "myapex", "android_common_myapex", []string{
+ `dex2oatd`,
`myapex.key`,
`mysystemserverclasspathfragment`,
})
@@ -272,24 +274,26 @@
ctx := result.TestContext
java.CheckModuleDependencies(t, ctx, "myapex", "android_common_myapex", []string{
- `myapex.apex.selector`,
+ `dex2oatd`,
+ `prebuilt_myapex.apex.selector`,
+ `prebuilt_myapex.deapexer`,
`prebuilt_mysystemserverclasspathfragment`,
})
java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
- `myapex.deapexer`,
`prebuilt_bar`,
`prebuilt_foo`,
+ `prebuilt_myapex.deapexer`,
})
- ensureExactDeapexedContents(t, ctx, "myapex", "android_common", []string{
+ ensureExactDeapexedContents(t, ctx, "prebuilt_myapex", "android_common", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
})
- assertProfileGuided(t, ctx, "foo", "android_common_myapex", false)
- assertProfileGuided(t, ctx, "bar", "android_common_myapex", true)
+ assertProfileGuidedPrebuilt(t, ctx, "myapex", "foo", false)
+ assertProfileGuidedPrebuilt(t, ctx, "myapex", "bar", true)
}
func TestSystemserverclasspathFragmentStandaloneContents(t *testing.T) {
@@ -428,19 +432,19 @@
ctx := result.TestContext
java.CheckModuleDependencies(t, ctx, "mysystemserverclasspathfragment", "android_common_myapex", []string{
- `myapex.deapexer`,
`prebuilt_bar`,
`prebuilt_foo`,
+ `prebuilt_myapex.deapexer`,
})
- ensureExactDeapexedContents(t, ctx, "myapex", "android_common", []string{
+ ensureExactDeapexedContents(t, ctx, "prebuilt_myapex", "android_common", []string{
"javalib/foo.jar",
"javalib/bar.jar",
"javalib/bar.jar.prof",
})
- assertProfileGuided(t, ctx, "foo", "android_common_myapex", false)
- assertProfileGuided(t, ctx, "bar", "android_common_myapex", true)
+ assertProfileGuidedPrebuilt(t, ctx, "myapex", "foo", false)
+ assertProfileGuidedPrebuilt(t, ctx, "myapex", "bar", true)
}
func assertProfileGuided(t *testing.T, ctx *android.TestContext, moduleName string, variant string, expected bool) {
@@ -450,3 +454,11 @@
t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual)
}
}
+
+func assertProfileGuidedPrebuilt(t *testing.T, ctx *android.TestContext, apexName string, moduleName string, expected bool) {
+ dexpreopt := ctx.ModuleForTests(apexName, "android_common_"+apexName).Rule("dexpreopt." + moduleName)
+ actual := strings.Contains(dexpreopt.RuleParams.Command, "--profile-file=")
+ if expected != actual {
+ t.Fatalf("Expected profile-guided to be %v, got %v", expected, actual)
+ }
+}
diff --git a/apex/vndk.go b/apex/vndk.go
index 26c60ed..377c1c0 100644
--- a/apex/vndk.go
+++ b/apex/vndk.go
@@ -65,24 +65,27 @@
}
vndkVersion := ab.vndkVersion(mctx.DeviceConfig())
- apiLevel, err := android.ApiLevelFromUser(mctx, vndkVersion)
- if err != nil {
- mctx.PropertyErrorf("vndk_version", "%s", err.Error())
- return
- }
+ if vndkVersion != "" {
+ apiLevel, err := android.ApiLevelFromUser(mctx, vndkVersion)
+ if err != nil {
+ mctx.PropertyErrorf("vndk_version", "%s", err.Error())
+ return
+ }
- targets := mctx.MultiTargets()
- if len(targets) > 0 && apiLevel.LessThan(cc.MinApiForArch(mctx, targets[0].Arch.ArchType)) &&
- vndkVersion != mctx.DeviceConfig().PlatformVndkVersion() {
- // Disable VNDK APEXes for VNDK versions less than the minimum supported API
- // level for the primary architecture. This validation is skipped if the VNDK
- // version matches the platform VNDK version, which can occur when the device
- // config targets the 'current' VNDK (see `vndkVersion`).
- ab.Disable()
- }
- if proptools.String(ab.vndkProperties.Vndk_version) != "" &&
- apiLevel.GreaterThanOrEqualTo(android.ApiLevelOrPanic(mctx, mctx.DeviceConfig().PlatformVndkVersion())) {
- ab.Disable()
+ targets := mctx.MultiTargets()
+ if len(targets) > 0 && apiLevel.LessThan(cc.MinApiForArch(mctx, targets[0].Arch.ArchType)) &&
+ vndkVersion != mctx.DeviceConfig().PlatformVndkVersion() {
+ // Disable VNDK APEXes for VNDK versions less than the minimum supported API
+ // level for the primary architecture. This validation is skipped if the VNDK
+ // version matches the platform VNDK version, which can occur when the device
+ // config targets the 'current' VNDK (see `vndkVersion`).
+ ab.Disable()
+ }
+ if proptools.String(ab.vndkProperties.Vndk_version) != "" &&
+ mctx.DeviceConfig().PlatformVndkVersion() != "" &&
+ apiLevel.GreaterThanOrEqualTo(android.ApiLevelOrPanic(mctx, mctx.DeviceConfig().PlatformVndkVersion())) {
+ ab.Disable()
+ }
}
}
}
@@ -94,6 +97,11 @@
if vndkVersion == "" {
vndkVersion = mctx.DeviceConfig().PlatformVndkVersion()
}
+
+ if vndkVersion == "" {
+ return
+ }
+
if vndkVersion == mctx.DeviceConfig().PlatformVndkVersion() {
vndkVersion = "current"
} else {
diff --git a/apex/vndk_test.go b/apex/vndk_test.go
index 2b86e53..894aece 100644
--- a/apex/vndk_test.go
+++ b/apex/vndk_test.go
@@ -8,66 +8,6 @@
"android/soong/android"
)
-func TestVndkApexForVndkLite(t *testing.T) {
- ctx := testApex(t, `
- apex_vndk {
- name: "com.android.vndk.current",
- key: "com.android.vndk.current.key",
- updatable: false,
- }
-
- apex_key {
- name: "com.android.vndk.current.key",
- public_key: "testkey.avbpubkey",
- private_key: "testkey.pem",
- }
-
- cc_library {
- name: "libvndk",
- srcs: ["mylib.cpp"],
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- system_shared_libs: [],
- stl: "none",
- apex_available: [ "com.android.vndk.current" ],
- }
-
- cc_library {
- name: "libvndksp",
- srcs: ["mylib.cpp"],
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- support_system_process: true,
- },
- system_shared_libs: [],
- stl: "none",
- apex_available: [ "com.android.vndk.current" ],
- }
- `+vndkLibrariesTxtFiles("current"),
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.DeviceVndkVersion = proptools.StringPtr("")
- variables.KeepVndk = proptools.BoolPtr(true)
- }),
- )
- // VNDK-Lite contains only core variants of VNDK-Sp libraries
- ensureExactContents(t, ctx, "com.android.vndk.current", "android_common", []string{
- "lib/libvndksp.so",
- "lib/libc++.so",
- "lib64/libvndksp.so",
- "lib64/libc++.so",
- "etc/llndk.libraries.29.txt",
- "etc/vndkcore.libraries.29.txt",
- "etc/vndksp.libraries.29.txt",
- "etc/vndkprivate.libraries.29.txt",
- "etc/vndkproduct.libraries.29.txt",
- })
-}
-
func TestVndkApexUsesVendorVariant(t *testing.T) {
bp := `
apex_vndk {
@@ -115,12 +55,7 @@
})
t.Run("VNDK APEX gathers only vendor variants even if product variants are available", func(t *testing.T) {
- ctx := testApex(t, bp,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- // Now product variant is available
- variables.ProductVndkVersion = proptools.StringPtr("current")
- }),
- )
+ ctx := testApex(t, bp)
files := getFiles(t, ctx, "com.android.vndk.current", "android_common")
ensureFileSrc(t, files, "lib/libfoo.so", "libfoo/android_vendor.29_arm_armv7-a-neon_shared/libfoo.so")
diff --git a/bazel/aquery.go b/bazel/aquery.go
index c355712..35942bc 100644
--- a/bazel/aquery.go
+++ b/bazel/aquery.go
@@ -18,14 +18,16 @@
"crypto/sha256"
"encoding/base64"
"encoding/json"
+ "errors"
"fmt"
"path/filepath"
- analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
"reflect"
"sort"
"strings"
"sync"
+ analysis_v2_proto "prebuilts/bazel/common/proto/analysis_v2"
+
"github.com/google/blueprint/metrics"
"github.com/google/blueprint/proptools"
"google.golang.org/protobuf/proto"
@@ -35,19 +37,6 @@
type depsetId int
type pathFragmentId int
-// artifact contains relevant portions of Bazel's aquery proto, Artifact.
-// Represents a single artifact, whether it's a source file or a derived output file.
-type artifact struct {
- Id artifactId
- PathFragmentId pathFragmentId
-}
-
-type pathFragment struct {
- Id pathFragmentId
- Label string
- ParentId pathFragmentId
-}
-
// KeyValuePair represents Bazel's aquery proto, KeyValuePair.
type KeyValuePair struct {
Key string
@@ -68,37 +57,6 @@
TransitiveDepSetHashes []string
}
-// depSetOfFiles contains relevant portions of Bazel's aquery proto, DepSetOfFiles.
-// Represents a data structure containing one or more files. Depsets in Bazel are an efficient
-// data structure for storing large numbers of file paths.
-type depSetOfFiles struct {
- Id depsetId
- DirectArtifactIds []artifactId
- TransitiveDepSetIds []depsetId
-}
-
-// action contains relevant portions of Bazel's aquery proto, Action.
-// Represents a single command line invocation in the Bazel build graph.
-type action struct {
- Arguments []string
- EnvironmentVariables []KeyValuePair
- InputDepSetIds []depsetId
- Mnemonic string
- OutputIds []artifactId
- TemplateContent string
- Substitutions []KeyValuePair
- FileContents string
-}
-
-// actionGraphContainer contains relevant portions of Bazel's aquery proto, ActionGraphContainer.
-// An aquery response from Bazel contains a single ActionGraphContainer proto.
-type actionGraphContainer struct {
- Artifacts []artifact
- Actions []action
- DepSetOfFiles []depSetOfFiles
- PathFragments []pathFragment
-}
-
// BuildStatement contains information to register a build statement corresponding (one to one)
// with a Bazel action from Bazel's action graph.
type BuildStatement struct {
@@ -370,13 +328,20 @@
defer eventHandler.End("build_statements")
wg := sync.WaitGroup{}
var errOnce sync.Once
-
+ id2targets := make(map[uint32]string, len(aqueryProto.Targets))
+ for _, t := range aqueryProto.Targets {
+ id2targets[t.GetId()] = t.GetLabel()
+ }
for i, actionEntry := range aqueryProto.Actions {
wg.Add(1)
go func(i int, actionEntry *analysis_v2_proto.Action) {
- buildStatement, aErr := aqueryHandler.actionToBuildStatement(actionEntry)
- if aErr != nil {
+ if strings.HasPrefix(id2targets[actionEntry.TargetId], "@bazel_tools//") {
+ // bazel_tools are removed depsets in `populateDepsetMaps()` so skipping
+ // conversion to build statements as well
+ buildStatements[i] = nil
+ } else if buildStatement, aErr := aqueryHandler.actionToBuildStatement(actionEntry); aErr != nil {
errOnce.Do(func() {
+ aErr = fmt.Errorf("%s: [%s] [%s]", aErr.Error(), actionEntry.GetMnemonic(), id2targets[actionEntry.TargetId])
err = aErr
})
} else {
@@ -478,26 +443,21 @@
// escapes the args received from aquery and creates a command string
func commandString(actionEntry *analysis_v2_proto.Action) string {
- switch actionEntry.Mnemonic {
- case "GoCompilePkg", "GoStdlib":
- argsEscaped := []string{}
- for _, arg := range actionEntry.Arguments {
- if arg == "" {
- // If this is an empty string, add ''
- // And not
- // 1. (literal empty)
- // 2. `''\'''\'''` (escaped version of '')
- //
- // If we had used (1), then this would appear as a whitespace when we strings.Join
- argsEscaped = append(argsEscaped, "''")
- } else {
- argsEscaped = append(argsEscaped, proptools.ShellEscapeIncludingSpaces(arg))
- }
+ argsEscaped := make([]string, len(actionEntry.Arguments))
+ for i, arg := range actionEntry.Arguments {
+ if arg == "" {
+ // If this is an empty string, add ''
+ // And not
+ // 1. (literal empty)
+ // 2. `''\'''\'''` (escaped version of '')
+ //
+ // If we had used (1), then this would appear as a whitespace when we strings.Join
+ argsEscaped[i] = "''"
+ } else {
+ argsEscaped[i] = proptools.ShellEscapeIncludingSpaces(arg)
}
- return strings.Join(argsEscaped, " ")
- default:
- return strings.Join(proptools.ShellEscapeListIncludingSpaces(actionEntry.Arguments), " ")
}
+ return strings.Join(argsEscaped, " ")
}
func (a *aqueryArtifactHandler) normalActionBuildStatement(actionEntry *analysis_v2_proto.Action) (*BuildStatement, error) {
@@ -782,7 +742,7 @@
}
if len(actionEntry.Arguments) < 1 {
- return nil, fmt.Errorf("received action with no command: [%s]", actionEntry.Mnemonic)
+ return nil, errors.New("received action with no command")
}
return a.normalActionBuildStatement(actionEntry)
diff --git a/bazel/aquery_test.go b/bazel/aquery_test.go
index 32c87a0..cbd2791 100644
--- a/bazel/aquery_test.go
+++ b/bazel/aquery_test.go
@@ -178,8 +178,8 @@
{ "id": 2, "path_fragment_id": 2 }],
"actions": [{
"target_id": 1,
- "action_key": "x",
- "mnemonic": "x",
+ "action_key": "action_x",
+ "mnemonic": "X",
"arguments": ["touch", "foo"],
"input_dep_set_ids": [1],
"output_ids": [3],
@@ -198,7 +198,7 @@
return
}
_, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
- assertError(t, err, "undefined outputId 3")
+ assertError(t, err, "undefined outputId 3: [X] []")
}
func TestInvalidInputDepsetIdFromAction(t *testing.T) {
@@ -209,13 +209,17 @@
{ "id": 2, "path_fragment_id": 2 }],
"actions": [{
"target_id": 1,
- "action_key": "x",
- "mnemonic": "x",
+ "action_key": "action_x",
+ "mnemonic": "X",
"arguments": ["touch", "foo"],
"input_dep_set_ids": [2],
"output_ids": [1],
"primary_output_id": 1
}],
+ "targets": [{
+ "id": 1,
+ "label": "target_x"
+ }],
"dep_set_of_files": [
{ "id": 1, "direct_artifact_ids": [1, 2] }],
"path_fragments": [
@@ -229,7 +233,7 @@
return
}
_, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
- assertError(t, err, "undefined (not even empty) input depsetId 2")
+ assertError(t, err, "undefined (not even empty) input depsetId 2: [X] [target_x]")
}
func TestInvalidInputDepsetIdFromDepset(t *testing.T) {
@@ -383,8 +387,8 @@
{ "id": 4, "path_fragment_id": 4 }],
"actions": [{
"target_id": 1,
- "action_key": "x",
- "mnemonic": "x",
+ "action_key": "action_x",
+ "mnemonic": "X",
"arguments": ["touch", "foo"],
"input_dep_set_ids": [1],
"output_ids": [2,3,4],
@@ -407,7 +411,7 @@
return
}
_, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
- assertError(t, err, `found multiple potential depfiles "two.d", "other.d"`)
+ assertError(t, err, `found multiple potential depfiles "two.d", "other.d": [X] []`)
}
func TestTransitiveInputDepsets(t *testing.T) {
@@ -559,7 +563,7 @@
}, actual)
}
-func TestBazelOutRemovalFromInputDepsets(t *testing.T) {
+func TestBazelToolsRemovalFromInputDepsets(t *testing.T) {
const inputString = `{
"artifacts": [
{ "id": 1, "path_fragment_id": 10 },
@@ -637,7 +641,55 @@
}
}
-func TestBazelOutRemovalFromTransitiveInputDepsets(t *testing.T) {
+func TestBazelToolsRemovalFromTargets(t *testing.T) {
+ const inputString = `{
+ "artifacts": [{ "id": 1, "path_fragment_id": 10 }],
+ "targets": [
+ { "id": 100, "label": "targetX" },
+ { "id": 200, "label": "@bazel_tools//tool_y" }
+],
+ "actions": [{
+ "target_id": 100,
+ "action_key": "actionX",
+ "arguments": ["bogus", "command"],
+ "mnemonic" : "x",
+ "output_ids": [1]
+ }, {
+ "target_id": 200,
+ "action_key": "y"
+ }],
+ "path_fragments": [{ "id": 10, "label": "outputX"}]
+}`
+ data, err := JsonToActionGraphContainer(inputString)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ actualBuildStatements, actualDepsets, _ := AqueryBuildStatements(data, &metrics.EventHandler{})
+ if len(actualDepsets) != 0 {
+ t.Errorf("expected 0 depset but found %#v", actualDepsets)
+ return
+ }
+ expectedBuildStatement := &BuildStatement{
+ Command: "bogus command",
+ OutputPaths: []string{"outputX"},
+ Mnemonic: "x",
+ SymlinkPaths: []string{},
+ }
+ buildStatementFound := false
+ for _, actualBuildStatement := range actualBuildStatements {
+ if buildStatementEquals(actualBuildStatement, expectedBuildStatement) == "" {
+ buildStatementFound = true
+ break
+ }
+ }
+ if !buildStatementFound {
+ t.Errorf("expected but missing %#v in %#v build statements", expectedBuildStatement, len(actualBuildStatements))
+ return
+ }
+}
+
+func TestBazelToolsRemovalFromTransitiveInputDepsets(t *testing.T) {
const inputString = `{
"artifacts": [
{ "id": 1, "path_fragment_id": 10 },
@@ -939,7 +991,7 @@
{ "id": 3, "path_fragment_id": 3 }],
"actions": [{
"target_id": 1,
- "action_key": "x",
+ "action_key": "action_x",
"mnemonic": "Symlink",
"input_dep_set_ids": [1],
"output_ids": [3],
@@ -958,7 +1010,7 @@
return
}
_, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
- assertError(t, err, `Expect 1 input and 1 output to symlink action, got: input ["file" "other_file"], output ["symlink"]`)
+ assertError(t, err, `Expect 1 input and 1 output to symlink action, got: input ["file" "other_file"], output ["symlink"]: [Symlink] []`)
}
func TestSymlinkMultipleOutputs(t *testing.T) {
@@ -989,7 +1041,7 @@
return
}
_, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
- assertError(t, err, "undefined outputId 2")
+ assertError(t, err, "undefined outputId 2: [Symlink] []")
}
func TestTemplateExpandActionSubstitutions(t *testing.T) {
@@ -1066,7 +1118,7 @@
return
}
_, _, err = AqueryBuildStatements(data, &metrics.EventHandler{})
- assertError(t, err, `Expect 1 output to template expand action, got: output []`)
+ assertError(t, err, `Expect 1 output to template expand action, got: output []: [TemplateExpand] []`)
}
func TestFileWrite(t *testing.T) {
diff --git a/bazel/configurability.go b/bazel/configurability.go
index 1fe8442..2c9a536 100644
--- a/bazel/configurability.go
+++ b/bazel/configurability.go
@@ -71,6 +71,7 @@
AndroidAndInApex = "android-in_apex"
AndroidPlatform = "system"
+ Unbundled_app = "unbundled_app"
InApex = "in_apex"
NonApex = "non_apex"
@@ -132,7 +133,7 @@
}
result := make(map[string]string)
for arch, allFeatures := range archFeatures {
- result[arch] = "//build/bazel/platforms/arch:" + arch
+ result[arch] = "//build/bazel_common_rules/platforms/arch:" + arch
// Sometimes we want to select on multiple features being active, so
// add the power set of all possible features to the map. More details
// in android.ModuleBase.GetArchVariantProperties
@@ -159,33 +160,33 @@
// A map of target operating systems to the Bazel label of the
// constraint_value for the @platforms//os:os constraint_setting
platformOsMap = map[string]string{
- OsAndroid: "//build/bazel/platforms/os:android",
- OsDarwin: "//build/bazel/platforms/os:darwin",
- OsLinux: "//build/bazel/platforms/os:linux_glibc",
- osLinuxMusl: "//build/bazel/platforms/os:linux_musl",
- osLinuxBionic: "//build/bazel/platforms/os:linux_bionic",
- OsWindows: "//build/bazel/platforms/os:windows",
+ OsAndroid: "//build/bazel_common_rules/platforms/os:android",
+ OsDarwin: "//build/bazel_common_rules/platforms/os:darwin",
+ OsLinux: "//build/bazel_common_rules/platforms/os:linux_glibc",
+ osLinuxMusl: "//build/bazel_common_rules/platforms/os:linux_musl",
+ osLinuxBionic: "//build/bazel_common_rules/platforms/os:linux_bionic",
+ OsWindows: "//build/bazel_common_rules/platforms/os:windows",
ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
}
platformOsArchMap = map[string]string{
- osArchAndroidArm: "//build/bazel/platforms/os_arch:android_arm",
- OsArchAndroidArm64: "//build/bazel/platforms/os_arch:android_arm64",
- osArchAndroidRiscv64: "//build/bazel/platforms/os_arch:android_riscv64",
- osArchAndroidX86: "//build/bazel/platforms/os_arch:android_x86",
- osArchAndroidX86_64: "//build/bazel/platforms/os_arch:android_x86_64",
- osArchDarwinArm64: "//build/bazel/platforms/os_arch:darwin_arm64",
- osArchDarwinX86_64: "//build/bazel/platforms/os_arch:darwin_x86_64",
- osArchLinuxX86: "//build/bazel/platforms/os_arch:linux_glibc_x86",
- osArchLinuxX86_64: "//build/bazel/platforms/os_arch:linux_glibc_x86_64",
- osArchLinuxMuslArm: "//build/bazel/platforms/os_arch:linux_musl_arm",
- osArchLinuxMuslArm64: "//build/bazel/platforms/os_arch:linux_musl_arm64",
- osArchLinuxMuslX86: "//build/bazel/platforms/os_arch:linux_musl_x86",
- osArchLinuxMuslX86_64: "//build/bazel/platforms/os_arch:linux_musl_x86_64",
- osArchLinuxBionicArm64: "//build/bazel/platforms/os_arch:linux_bionic_arm64",
- osArchLinuxBionicX86_64: "//build/bazel/platforms/os_arch:linux_bionic_x86_64",
- osArchWindowsX86: "//build/bazel/platforms/os_arch:windows_x86",
- osArchWindowsX86_64: "//build/bazel/platforms/os_arch:windows_x86_64",
+ osArchAndroidArm: "//build/bazel_common_rules/platforms/os_arch:android_arm",
+ OsArchAndroidArm64: "//build/bazel_common_rules/platforms/os_arch:android_arm64",
+ osArchAndroidRiscv64: "//build/bazel_common_rules/platforms/os_arch:android_riscv64",
+ osArchAndroidX86: "//build/bazel_common_rules/platforms/os_arch:android_x86",
+ osArchAndroidX86_64: "//build/bazel_common_rules/platforms/os_arch:android_x86_64",
+ osArchDarwinArm64: "//build/bazel_common_rules/platforms/os_arch:darwin_arm64",
+ osArchDarwinX86_64: "//build/bazel_common_rules/platforms/os_arch:darwin_x86_64",
+ osArchLinuxX86: "//build/bazel_common_rules/platforms/os_arch:linux_glibc_x86",
+ osArchLinuxX86_64: "//build/bazel_common_rules/platforms/os_arch:linux_glibc_x86_64",
+ osArchLinuxMuslArm: "//build/bazel_common_rules/platforms/os_arch:linux_musl_arm",
+ osArchLinuxMuslArm64: "//build/bazel_common_rules/platforms/os_arch:linux_musl_arm64",
+ osArchLinuxMuslX86: "//build/bazel_common_rules/platforms/os_arch:linux_musl_x86",
+ osArchLinuxMuslX86_64: "//build/bazel_common_rules/platforms/os_arch:linux_musl_x86_64",
+ osArchLinuxBionicArm64: "//build/bazel_common_rules/platforms/os_arch:linux_bionic_arm64",
+ osArchLinuxBionicX86_64: "//build/bazel_common_rules/platforms/os_arch:linux_bionic_x86_64",
+ osArchWindowsX86: "//build/bazel_common_rules/platforms/os_arch:windows_x86",
+ osArchWindowsX86_64: "//build/bazel_common_rules/platforms/os_arch:windows_x86_64",
ConditionsDefaultConfigKey: ConditionsDefaultSelectKey, // The default condition of an os select map.
}
@@ -207,11 +208,12 @@
osAndInApexMap = map[string]string{
AndroidAndInApex: "//build/bazel/rules/apex:android-in_apex",
AndroidPlatform: "//build/bazel/rules/apex:system",
- OsDarwin: "//build/bazel/platforms/os:darwin",
- OsLinux: "//build/bazel/platforms/os:linux_glibc",
- osLinuxMusl: "//build/bazel/platforms/os:linux_musl",
- osLinuxBionic: "//build/bazel/platforms/os:linux_bionic",
- OsWindows: "//build/bazel/platforms/os:windows",
+ Unbundled_app: "//build/bazel/rules/apex:unbundled_app",
+ OsDarwin: "//build/bazel_common_rules/platforms/os:darwin",
+ OsLinux: "//build/bazel_common_rules/platforms/os:linux_glibc",
+ osLinuxMusl: "//build/bazel_common_rules/platforms/os:linux_musl",
+ osLinuxBionic: "//build/bazel_common_rules/platforms/os:linux_bionic",
+ OsWindows: "//build/bazel_common_rules/platforms/os:windows",
ConditionsDefaultConfigKey: ConditionsDefaultSelectKey,
}
diff --git a/bin/soongdbg b/bin/soongdbg
new file mode 100755
index 0000000..132a0f0
--- /dev/null
+++ b/bin/soongdbg
@@ -0,0 +1,313 @@
+#!/usr/bin/env python3
+
+import argparse
+import fnmatch
+import json
+import os
+import pathlib
+import types
+import sys
+
+
+class Graph:
+ def __init__(self, modules):
+ def get_or_make_node(dictionary, id, module):
+ node = dictionary.get(id)
+ if node:
+ if module and not node.module:
+ node.module = module
+ return node
+ node = Node(id, module)
+ dictionary[id] = node
+ return node
+ self.nodes = dict()
+ for module in modules.values():
+ node = get_or_make_node(self.nodes, module.id, module)
+ for d in module.deps:
+ dep = get_or_make_node(self.nodes, d.id, None)
+ node.deps.add(dep)
+ dep.rdeps.add(node)
+
+ def find_paths(self, id1, id2):
+ # Throws KeyError if one of the names isn't found
+ def recurse(node1, node2, visited):
+ result = set()
+ for dep in node1.rdeps:
+ if dep == node2:
+ result.add(node2)
+ if dep not in visited:
+ visited.add(dep)
+ found = recurse(dep, node2, visited)
+ if found:
+ result |= found
+ result.add(dep)
+ return result
+ node1 = self.nodes[id1]
+ node2 = self.nodes[id2]
+ # Take either direction
+ p = recurse(node1, node2, set())
+ if p:
+ p.add(node1)
+ return p
+ p = recurse(node2, node1, set())
+ p.add(node2)
+ return p
+
+
+class Node:
+ def __init__(self, id, module):
+ self.id = id
+ self.module = module
+ self.deps = set()
+ self.rdeps = set()
+
+
+PROVIDERS = [
+ "android/soong/java.JarJarProviderData",
+ "android/soong/java.BaseJarJarProviderData",
+]
+
+
+def format_node_label(node):
+ if not node.module:
+ return node.id
+ if node.module.debug:
+ module_debug = f"<tr><td>{node.module.debug}</td></tr>"
+ else:
+ module_debug = ""
+
+ result = (f"<<table border=\"0\" cellborder=\"0\" cellspacing=\"0\" cellpadding=\"0\">"
+ + f"<tr><td><b>{node.module.name}</b></td></tr>"
+ + module_debug
+ + f"<tr><td>{node.module.type}</td></tr>")
+ for p in node.module.providers:
+ if p.type in PROVIDERS:
+ result += "<tr><td><font color=\"#666666\">" + format_provider(p) + "</font></td></tr>"
+ result += "</table>>"
+ return result
+
+
+def format_source_pos(file, lineno):
+ result = file
+ if lineno:
+ result += f":{lineno}"
+ return result
+
+
+STRIP_TYPE_PREFIXES = [
+ "android/soong/",
+ "github.com/google/",
+]
+
+
+def format_provider(provider):
+ result = ""
+ for prefix in STRIP_TYPE_PREFIXES:
+ if provider.type.startswith(prefix):
+ result = provider.type[len(prefix):]
+ break
+ if not result:
+ result = provider.type
+ if True and provider.debug:
+ result += " (" + provider.debug + ")"
+ return result
+
+
+def load_soong_debug():
+ # Read the json
+ try:
+ with open(SOONG_DEBUG_DATA_FILENAME) as f:
+ info = json.load(f, object_hook=lambda d: types.SimpleNamespace(**d))
+ except IOError:
+ sys.stderr.write(f"error: Unable to open {SOONG_DEBUG_DATA_FILENAME}. Make sure you have"
+ + " built with GENERATE_SOONG_DEBUG.\n")
+ sys.exit(1)
+
+ # Construct IDs, which are name + variant if the
+ name_counts = dict()
+ for m in info.modules:
+ name_counts[m.name] = name_counts.get(m.name, 0) + 1
+ def get_id(m):
+ result = m.name
+ if name_counts[m.name] > 1 and m.variant:
+ result += "@@" + m.variant
+ return result
+ for m in info.modules:
+ m.id = get_id(m)
+ for dep in m.deps:
+ dep.id = get_id(dep)
+
+ return info
+
+
+def load_modules():
+ info = load_soong_debug()
+
+ # Filter out unnamed modules
+ modules = dict()
+ for m in info.modules:
+ if not m.name:
+ continue
+ modules[m.id] = m
+
+ return modules
+
+
+def load_graph():
+ modules=load_modules()
+ return Graph(modules)
+
+
+def module_selection_args(parser):
+ parser.add_argument("modules", nargs="*",
+ help="Modules to match. Can be glob-style wildcards.")
+ parser.add_argument("--provider", nargs="+",
+ help="Match the given providers.")
+ parser.add_argument("--dep", nargs="+",
+ help="Match the given providers.")
+
+
+def load_and_filter_modules(args):
+ # Which modules are printed
+ matchers = []
+ if args.modules:
+ matchers.append(lambda m: [True for pattern in args.modules
+ if fnmatch.fnmatchcase(m.name, pattern)])
+ if args.provider:
+ matchers.append(lambda m: [True for pattern in args.provider
+ if [True for p in m.providers if p.type.endswith(pattern)]])
+ if args.dep:
+ matchers.append(lambda m: [True for pattern in args.dep
+ if [True for d in m.deps if d.id == pattern]])
+
+ if not matchers:
+ sys.stderr.write("error: At least one module matcher must be supplied\n")
+ sys.exit(1)
+
+ info = load_soong_debug()
+ for m in sorted(info.modules, key=lambda m: (m.name, m.variant)):
+ if len([matcher for matcher in matchers if matcher(m)]) == len(matchers):
+ yield m
+
+
+def print_nodes(nodes):
+ print("digraph {")
+ for node in nodes:
+ print(f"\"{node.id}\"[label={format_node_label(node)}];")
+ for dep in node.deps:
+ if dep in nodes:
+ print(f"\"{node.id}\" -> \"{dep.id}\";")
+ print("}")
+
+
+def get_deps(nodes, root):
+ if root in nodes:
+ return
+ nodes.add(root)
+ for dep in root.deps:
+ get_deps(nodes, dep)
+
+
+class BetweenCommand:
+ help = "Print the module graph between two nodes."
+
+ def args(self, parser):
+ parser.add_argument("module", nargs=2,
+ help="The two modules")
+
+ def run(self, args):
+ graph = load_graph()
+ print_nodes(graph.find_paths(args.module[0], args.module[1]))
+
+
+class DepsCommand:
+ help = "Print the module graph of dependencies of one or more modules"
+
+ def args(self, parser):
+ parser.add_argument("module", nargs="+",
+ help="Module to print dependencies of")
+
+ def run(self, args):
+ graph = load_graph()
+ nodes = set()
+ err = False
+ for id in sys.argv[3:]:
+ root = graph.nodes.get(id)
+ if not root:
+ sys.stderr.write(f"error: Can't find root: {id}\n")
+ err = True
+ continue
+ get_deps(nodes, root)
+ if err:
+ sys.exit(1)
+ print_nodes(nodes)
+
+
+class IdCommand:
+ help = "Print the id (name + variant) of matching modules"
+
+ def args(self, parser):
+ module_selection_args(parser)
+
+ def run(self, args):
+ for m in load_and_filter_modules(args):
+ print(m.id)
+
+
+class QueryCommand:
+ help = "Query details about modules"
+
+ def args(self, parser):
+ module_selection_args(parser)
+
+ def run(self, args):
+ for m in load_and_filter_modules(args):
+ print(m.id)
+ print(f" type: {m.type}")
+ print(f" location: {format_source_pos(m.source_file, m.source_line)}")
+ for p in m.providers:
+ print(f" provider: {format_provider(p)}")
+ for d in m.deps:
+ print(f" dep: {d.id}")
+
+
+COMMANDS = {
+ "between": BetweenCommand(),
+ "deps": DepsCommand(),
+ "id": IdCommand(),
+ "query": QueryCommand(),
+}
+
+
+def assert_env(name):
+ val = os.getenv(name)
+ if not val:
+ sys.stderr.write(f"{name} not set. please make sure you've run lunch.")
+ return val
+
+ANDROID_BUILD_TOP = assert_env("ANDROID_BUILD_TOP")
+
+TARGET_PRODUCT = assert_env("TARGET_PRODUCT")
+OUT_DIR = os.getenv("OUT_DIR")
+if not OUT_DIR:
+ OUT_DIR = "out"
+if OUT_DIR[0] != "/":
+ OUT_DIR = pathlib.Path(ANDROID_BUILD_TOP).joinpath(OUT_DIR)
+SOONG_DEBUG_DATA_FILENAME = pathlib.Path(OUT_DIR).joinpath("soong/soong-debug-info.json")
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ subparsers = parser.add_subparsers(required=True, dest="command")
+ for name in sorted(COMMANDS.keys()):
+ command = COMMANDS[name]
+ subparser = subparsers.add_parser(name, help=command.help)
+ command.args(subparser)
+ args = parser.parse_args()
+ COMMANDS[args.command].run(args)
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
+
diff --git a/bloaty/bloaty.go b/bloaty/bloaty.go
index 3cff60f..43fb71d 100644
--- a/bloaty/bloaty.go
+++ b/bloaty/bloaty.go
@@ -26,7 +26,7 @@
const protoFilename = "binary_sizes.pb.gz"
var (
- fileSizeMeasurerKey blueprint.ProviderKey
+ fileSizeMeasurerKey blueprint.ProviderKey[measuredFiles]
pctx = android.NewPackageContext("android/soong/bloaty")
// bloaty is used to measure a binary section sizes.
@@ -52,7 +52,7 @@
pctx.SourcePathVariable("bloaty", "prebuilts/build-tools/${hostPrebuiltTag}/bin/bloaty")
pctx.HostBinToolVariable("bloatyMerger", "bloaty_merger")
android.RegisterParallelSingletonType("file_metrics", fileSizesSingleton)
- fileSizeMeasurerKey = blueprint.NewProvider(measuredFiles{})
+ fileSizeMeasurerKey = blueprint.NewProvider[measuredFiles]()
}
// measuredFiles contains the paths of the files measured by a module.
@@ -73,7 +73,7 @@
mf.paths = append(mf.paths, p)
}
}
- ctx.SetProvider(fileSizeMeasurerKey, mf)
+ android.SetProvider(ctx, fileSizeMeasurerKey, mf)
}
type sizesSingleton struct{}
@@ -85,10 +85,10 @@
func (singleton *sizesSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var deps android.Paths
ctx.VisitAllModules(func(m android.Module) {
- if !ctx.ModuleHasProvider(m, fileSizeMeasurerKey) {
+ filePaths, ok := android.SingletonModuleProvider(ctx, m, fileSizeMeasurerKey)
+ if !ok {
return
}
- filePaths := ctx.ModuleProvider(m, fileSizeMeasurerKey).(measuredFiles)
for _, path := range filePaths.paths {
filePath := path.(android.ModuleOutPath)
sizeFile := filePath.InSameDir(ctx, filePath.Base()+bloatyDescriptorExt)
diff --git a/bp2build/Android.bp b/bp2build/Android.bp
index b675e5e..ba12682 100644
--- a/bp2build/Android.bp
+++ b/bp2build/Android.bp
@@ -7,20 +7,16 @@
pkgPath: "android/soong/bp2build",
srcs: [
"androidbp_to_build_templates.go",
- "bp2build.go",
- "bp2build_product_config.go",
"build_conversion.go",
"bzl_conversion.go",
"configurability.go",
"constants.go",
"conversion.go",
- "metrics.go",
- "symlink_forest.go",
- "testing.go",
],
deps: [
"blueprint-bootstrap",
"soong-aidl-library",
+ "soong-aconfig",
"soong-android",
"soong-android-allowlists",
"soong-android-soongconfig",
@@ -39,56 +35,7 @@
"soong-ui-metrics",
],
testSrcs: [
- "go_conversion_test.go",
- "aar_conversion_test.go",
- "aidl_library_conversion_test.go",
- "android_app_certificate_conversion_test.go",
- "android_app_conversion_test.go",
- "apex_conversion_test.go",
- "apex_key_conversion_test.go",
- "build_conversion_test.go",
- "bp2build_product_config_test.go",
- "bzl_conversion_test.go",
- "cc_binary_conversion_test.go",
- "cc_library_conversion_test.go",
- "cc_library_headers_conversion_test.go",
- "cc_library_shared_conversion_test.go",
- "cc_library_static_conversion_test.go",
- "cc_object_conversion_test.go",
- "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",
- "filegroup_conversion_test.go",
- "genrule_conversion_test.go",
- "gensrcs_conversion_test.go",
- "java_binary_host_conversion_test.go",
- "java_host_for_device_conversion_test.go",
- "java_import_conversion_test.go",
- "java_library_conversion_test.go",
- "java_library_host_conversion_test.go",
- "java_plugin_conversion_test.go",
- "java_proto_conversion_test.go",
- "license_conversion_test.go",
- "license_kind_conversion_test.go",
- "linker_config_conversion_test.go",
- "package_conversion_test.go",
- "performance_test.go",
- "platform_compat_config_conversion_test.go",
- "prebuilt_etc_conversion_test.go",
- "python_binary_conversion_test.go",
- "python_library_conversion_test.go",
- "python_test_conversion_test.go",
- "rust_binary_conversion_test.go",
- "rust_library_conversion_test.go",
- "rust_proc_macro_conversion_test.go",
- "rust_protobuf_conversion_test.go",
- "sh_conversion_test.go",
- "sh_test_conversion_test.go",
- "soong_config_module_type_conversion_test.go",
],
pluginFor: [
"soong_build",
diff --git a/bp2build/aar_conversion_test.go b/bp2build/aar_conversion_test.go
deleted file mode 100644
index a24378c..0000000
--- a/bp2build/aar_conversion_test.go
+++ /dev/null
@@ -1,216 +0,0 @@
-// 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 (
- "android/soong/android"
- "android/soong/java"
- "fmt"
-
- "testing"
-)
-
-func TestConvertAndroidLibrary(t *testing.T) {
- t.Helper()
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
- Description: "Android Library - simple example",
- ModuleTypeUnderTest: "android_library",
- ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
- Filesystem: map[string]string{
- "lib.java": "",
- "arm.java": "",
- "x86.java": "",
- "res/res.png": "",
- "manifest/AndroidManifest.xml": "",
- },
- Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
-android_library {
- name: "TestLib",
- srcs: ["lib.java"],
- arch: {
- arm: {
- srcs: ["arm.java"],
- },
- x86: {
- srcs: ["x86.java"],
- }
- },
- manifest: "manifest/AndroidManifest.xml",
- static_libs: ["static_lib_dep"],
- sdk_version: "current",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget(
- "android_library",
- "TestLib",
- AttrNameToString{
- "srcs": `["lib.java"] + select({
- "//build/bazel/platforms/arch:arm": ["arm.java"],
- "//build/bazel/platforms/arch:x86": ["x86.java"],
- "//conditions:default": [],
- })`,
- "manifest": `"manifest/AndroidManifest.xml"`,
- "resource_files": `["res/res.png"]`,
- "deps": `[":static_lib_dep"]`,
- "exports": `[":static_lib_dep"]`,
- "sdk_version": `"current"`, // use as default
- }),
- MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
- }})
-}
-
-func TestConvertAndroidLibraryWithNoSources(t *testing.T) {
- t.Helper()
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
- Description: "Android Library - modules with deps must have sources",
- ModuleTypeUnderTest: "android_library",
- ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
- Filesystem: map[string]string{
- "res/res.png": "",
- "AndroidManifest.xml": "",
- },
- Blueprint: simpleModuleDoNotConvertBp2build("android_library", "lib_dep") + `
-android_library {
- name: "TestLib",
- srcs: [],
- manifest: "AndroidManifest.xml",
- libs: ["lib_dep"],
- sdk_version: "current",
-}
-`,
- ExpectedErr: fmt.Errorf("Module has direct dependencies but no sources. Bazel will not allow this."),
- ExpectedBazelTargets: []string{},
- })
-}
-
-func TestConvertAndroidLibraryImport(t *testing.T) {
- t.Helper()
- RunBp2BuildTestCase(
- t,
- func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("android_library", java.AndroidLibraryFactory)
- },
- Bp2buildTestCase{
- Description: "Android Library Import",
- ModuleTypeUnderTest: "android_library_import",
- ModuleTypeUnderTestFactory: java.AARImportFactory,
- Filesystem: map[string]string{
- "import.aar": "",
- },
- // Bazel's aar_import can only export *_import targets, so we expect
- // only "static_import_dep" in exports, but both "static_lib_dep" and
- // "static_import_dep" in deps
- Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") +
- simpleModuleDoNotConvertBp2build("android_library_import", "static_import_dep") + `
-android_library_import {
- name: "TestImport",
- aars: ["import.aar"],
- static_libs: ["static_lib_dep", "static_import_dep"],
- sdk_version: "current",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget(
- "aar_import",
- "TestImport",
- AttrNameToString{
- "aar": `"import.aar"`,
- "deps": `[
- ":static_lib_dep",
- ":static_import_dep",
- ]`,
- "exports": `[":static_import_dep"]`,
- "sdk_version": `"current"`, // use as default
- },
- ),
- MakeNeverlinkDuplicateTarget("android_library", "TestImport"),
- },
- },
- )
-}
-
-func TestConvertAndroidLibraryKotlin(t *testing.T) {
- t.Helper()
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
- Description: "Android Library with .kt srcs and common_srcs attribute",
- ModuleTypeUnderTest: "android_library",
- ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
- Filesystem: map[string]string{
- "AndroidManifest.xml": "",
- },
- Blueprint: `
-android_library {
- name: "TestLib",
- srcs: ["a.java", "b.kt"],
- common_srcs: ["c.kt"],
- sdk_version: "current",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget(
- "android_library",
- "TestLib",
- AttrNameToString{
- "srcs": `[
- "a.java",
- "b.kt",
- ]`,
- "common_srcs": `["c.kt"]`,
- "manifest": `"AndroidManifest.xml"`,
- "resource_files": `[]`,
- "sdk_version": `"current"`, // use as default
- }),
- MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
- }})
-}
-
-func TestConvertAndroidLibraryKotlinCflags(t *testing.T) {
- t.Helper()
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
- Description: "Android Library with .kt srcs and kotlincflags ",
- ModuleTypeUnderTest: "android_library",
- ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
- Filesystem: map[string]string{
- "AndroidManifest.xml": "",
- },
- Blueprint: `
-android_library {
- name: "TestLib",
- srcs: ["a.java", "b.kt"],
- kotlincflags: ["-flag1", "-flag2"],
- sdk_version: "current",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget(
- "android_library",
- "TestLib",
- AttrNameToString{
- "srcs": `[
- "a.java",
- "b.kt",
- ]`,
- "kotlincflags": `[
- "-flag1",
- "-flag2",
- ]`,
- "manifest": `"AndroidManifest.xml"`,
- "resource_files": `[]`,
- "sdk_version": `"current"`, // use as default
- }),
- MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
- }})
-}
diff --git a/bp2build/aidl_library_conversion_test.go b/bp2build/aidl_library_conversion_test.go
deleted file mode 100644
index 0522da4..0000000
--- a/bp2build/aidl_library_conversion_test.go
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2023 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 (
- "testing"
-
- "android/soong/aidl_library"
- "android/soong/android"
-)
-
-func runAidlLibraryTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "aidl_library"
- (&tc).ModuleTypeUnderTestFactory = aidl_library.AidlLibraryFactory
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
-}
-
-func TestAidlLibrary(t *testing.T) {
- testcases := []struct {
- name string
- bp string
- expectedBazelAttrs AttrNameToString
- }{
- {
- name: "aidl_library with strip_import_prefix",
- bp: `
- aidl_library {
- name: "foo",
- srcs: ["aidl/foo.aidl"],
- hdrs: ["aidl/header.aidl"],
- strip_import_prefix: "aidl",
- }`,
- expectedBazelAttrs: AttrNameToString{
- "srcs": `["aidl/foo.aidl"]`,
- "hdrs": `["aidl/header.aidl"]`,
- "strip_import_prefix": `"aidl"`,
- "tags": `["apex_available=//apex_available:anyapex"]`,
- },
- },
- {
- name: "aidl_library without strip_import_prefix",
- bp: `
- aidl_library {
- name: "foo",
- srcs: ["aidl/foo.aidl"],
- hdrs: ["aidl/header.aidl"],
- }`,
- expectedBazelAttrs: AttrNameToString{
- "srcs": `["aidl/foo.aidl"]`,
- "hdrs": `["aidl/header.aidl"]`,
- "tags": `["apex_available=//apex_available:anyapex"]`,
- },
- },
- }
-
- for _, test := range testcases {
- t.Run(test.name, func(t *testing.T) {
- expectedBazelTargets := []string{
- MakeBazelTargetNoRestrictions("aidl_library", "foo", test.expectedBazelAttrs),
- }
- runAidlLibraryTestCase(t, Bp2buildTestCase{
- Description: test.name,
- Blueprint: test.bp,
- ExpectedBazelTargets: expectedBazelTargets,
- })
- })
- }
-}
-
-func TestAidlLibraryWithDeps(t *testing.T) {
- bp := `
- aidl_library {
- name: "bar",
- srcs: ["Bar.aidl"],
- hdrs: ["aidl/BarHeader.aidl"],
- }
- aidl_library {
- name: "foo",
- srcs: ["aidl/Foo.aidl"],
- hdrs: ["aidl/FooHeader.aidl"],
- strip_import_prefix: "aidl",
- deps: ["bar"],
- }`
-
- t.Run("aidl_library with deps", func(t *testing.T) {
- expectedBazelTargets := []string{
- MakeBazelTargetNoRestrictions("aidl_library", "bar", AttrNameToString{
- "srcs": `["Bar.aidl"]`,
- "hdrs": `["aidl/BarHeader.aidl"]`,
- "tags": `["apex_available=//apex_available:anyapex"]`,
- }),
- MakeBazelTargetNoRestrictions("aidl_library", "foo", AttrNameToString{
- "srcs": `["aidl/Foo.aidl"]`,
- "hdrs": `["aidl/FooHeader.aidl"]`,
- "strip_import_prefix": `"aidl"`,
- "deps": `[":bar"]`,
- "tags": `["apex_available=//apex_available:anyapex"]`,
- }),
- }
- runAidlLibraryTestCase(t, Bp2buildTestCase{
- Description: "aidl_library with deps",
- Blueprint: bp,
- ExpectedBazelTargets: expectedBazelTargets,
- })
- })
-}
diff --git a/bp2build/android_app_certificate_conversion_test.go b/bp2build/android_app_certificate_conversion_test.go
deleted file mode 100644
index 0104513..0000000
--- a/bp2build/android_app_certificate_conversion_test.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// 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
-
-import (
- "android/soong/android"
- "android/soong/java"
-
- "testing"
-)
-
-func runAndroidAppCertificateTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, registerAndroidAppCertificateModuleTypes, tc)
-}
-
-func registerAndroidAppCertificateModuleTypes(ctx android.RegistrationContext) {
-}
-
-func TestAndroidAppCertificateSimple(t *testing.T) {
- runAndroidAppCertificateTestCase(t, Bp2buildTestCase{
- Description: "Android app certificate - simple example",
- ModuleTypeUnderTest: "android_app_certificate",
- ModuleTypeUnderTestFactory: java.AndroidAppCertificateFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-android_app_certificate {
- name: "com.android.apogee.cert",
- certificate: "chamber_of_secrets_dir",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("android_app_certificate", "com.android.apogee.cert", AttrNameToString{
- "certificate": `"chamber_of_secrets_dir"`,
- }),
- }})
-}
diff --git a/bp2build/android_app_conversion_test.go b/bp2build/android_app_conversion_test.go
deleted file mode 100644
index f2ee322..0000000
--- a/bp2build/android_app_conversion_test.go
+++ /dev/null
@@ -1,475 +0,0 @@
-// 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
-
-import (
- "android/soong/android"
- "android/soong/java"
-
- "testing"
-)
-
-func runAndroidAppTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, registerAndroidAppModuleTypes, tc)
-}
-
-func registerAndroidAppModuleTypes(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- ctx.RegisterModuleType("java_library", java.LibraryFactory)
-}
-
-func TestMinimalAndroidApp(t *testing.T) {
- runAndroidAppTestCase(t, Bp2buildTestCase{
- Description: "Android app - simple example",
- ModuleTypeUnderTest: "android_app",
- ModuleTypeUnderTestFactory: java.AndroidAppFactory,
- Filesystem: map[string]string{
- "app.java": "",
- "res/res.png": "",
- "AndroidManifest.xml": "",
- "assets/asset.png": "",
- },
- Blueprint: `
-android_app {
- name: "TestApp",
- srcs: ["app.java"],
- sdk_version: "current",
- optimize: {
- shrink: true,
- optimize: true,
- obfuscate: true,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("android_binary", "TestApp", AttrNameToString{
- "srcs": `["app.java"]`,
- "manifest": `"AndroidManifest.xml"`,
- "resource_files": `["res/res.png"]`,
- "sdk_version": `"current"`,
- "assets": `["assets/asset.png"]`,
- "assets_dir": `"assets"`,
- }),
- }})
-}
-
-func TestAndroidAppAllSupportedFields(t *testing.T) {
- runAndroidAppTestCase(t, Bp2buildTestCase{
- Description: "Android app - all supported fields",
- ModuleTypeUnderTest: "android_app",
- ModuleTypeUnderTestFactory: java.AndroidAppFactory,
- Filesystem: map[string]string{
- "app.java": "",
- "resa/res.png": "",
- "resb/res.png": "",
- "manifest/AndroidManifest.xml": "",
- "assets_/asset.png": "",
- },
- Blueprint: simpleModuleDoNotConvertBp2build("android_app", "static_lib_dep") + `
-android_app {
- name: "TestApp",
- srcs: ["app.java"],
- sdk_version: "current",
- package_name: "com.google",
- resource_dirs: ["resa", "resb"],
- manifest: "manifest/AndroidManifest.xml",
- static_libs: ["static_lib_dep"],
- java_version: "7",
- certificate: "foocert",
- required: ["static_lib_dep"],
- asset_dirs: ["assets_"],
- optimize: {
- enabled: true,
- optimize: false,
- proguard_flags_files: ["proguard.flags"],
- shrink: false,
- obfuscate: false,
- ignore_warnings: true,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("android_binary", "TestApp", AttrNameToString{
- "srcs": `["app.java"]`,
- "manifest": `"manifest/AndroidManifest.xml"`,
- "resource_files": `[
- "resa/res.png",
- "resb/res.png",
- ]`,
- "assets": `["assets_/asset.png"]`,
- "assets_dir": `"assets_"`,
- "custom_package": `"com.google"`,
- "deps": `[":static_lib_dep"]`,
- "java_version": `"7"`,
- "sdk_version": `"current"`,
- "certificate_name": `"foocert"`,
- "proguard_specs": `[
- "proguard.flags",
- ":TestApp_proguard_flags",
- ]`,
- }),
- MakeBazelTarget("genrule", "TestApp_proguard_flags", AttrNameToString{
- "outs": `["TestApp_proguard.flags"]`,
- "cmd": `"echo -ignorewarning -dontshrink -dontoptimize -dontobfuscate > $(OUTS)"`,
- }),
- }})
-}
-
-func TestAndroidAppArchVariantSrcs(t *testing.T) {
- runAndroidAppTestCase(t, Bp2buildTestCase{
- Description: "Android app - arch variant srcs",
- ModuleTypeUnderTest: "android_app",
- ModuleTypeUnderTestFactory: java.AndroidAppFactory,
- Filesystem: map[string]string{
- "arm.java": "",
- "x86.java": "",
- "res/res.png": "",
- "AndroidManifest.xml": "",
- },
- Blueprint: `
-android_app {
- name: "TestApp",
- sdk_version: "current",
- arch: {
- arm: {
- srcs: ["arm.java"],
- },
- x86: {
- srcs: ["x86.java"],
- }
- },
- optimize: {
- enabled: false,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("android_binary", "TestApp", AttrNameToString{
- "srcs": `select({
- "//build/bazel/platforms/arch:arm": ["arm.java"],
- "//build/bazel/platforms/arch:x86": ["x86.java"],
- "//conditions:default": [],
- })`,
- "manifest": `"AndroidManifest.xml"`,
- "resource_files": `["res/res.png"]`,
- "sdk_version": `"current"`,
- "optimize": `False`,
- }),
- }})
-}
-
-func TestAndroidAppCertIsModule(t *testing.T) {
- runAndroidAppTestCase(t, Bp2buildTestCase{
- Description: "Android app - cert is module",
- ModuleTypeUnderTest: "android_app",
- ModuleTypeUnderTestFactory: java.AndroidAppFactory,
- Filesystem: map[string]string{},
- Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") + `
-android_app {
- name: "TestApp",
- certificate: ":foocert",
- sdk_version: "current",
- optimize: {
- enabled: false,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("android_binary", "TestApp", AttrNameToString{
- "certificate": `":foocert"`,
- "manifest": `"AndroidManifest.xml"`,
- "resource_files": `[]`,
- "sdk_version": `"current"`, // use as default
- "optimize": `False`,
- }),
- }})
-}
-
-func TestAndroidAppCertIsSrcFile(t *testing.T) {
- runAndroidAppTestCase(t, Bp2buildTestCase{
- Description: "Android app - cert is src file",
- ModuleTypeUnderTest: "android_app",
- ModuleTypeUnderTestFactory: java.AndroidAppFactory,
- Filesystem: map[string]string{
- "foocert": "",
- },
- Blueprint: `
-android_app {
- name: "TestApp",
- certificate: "foocert",
- sdk_version: "current",
- optimize: {
- enabled: false,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("android_binary", "TestApp", AttrNameToString{
- "certificate": `"foocert"`,
- "manifest": `"AndroidManifest.xml"`,
- "resource_files": `[]`,
- "sdk_version": `"current"`, // use as default
- "optimize": `False`,
- }),
- }})
-}
-
-func TestAndroidAppCertIsNotSrcOrModule(t *testing.T) {
- runAndroidAppTestCase(t, Bp2buildTestCase{
- Description: "Android app - cert is not src or module",
- ModuleTypeUnderTest: "android_app",
- ModuleTypeUnderTestFactory: java.AndroidAppFactory,
- Filesystem: map[string]string{
- // deliberate empty
- },
- Blueprint: `
-android_app {
- name: "TestApp",
- certificate: "foocert",
- sdk_version: "current",
- optimize: {
- enabled: false,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("android_binary", "TestApp", AttrNameToString{
- "certificate_name": `"foocert"`,
- "manifest": `"AndroidManifest.xml"`,
- "resource_files": `[]`,
- "sdk_version": `"current"`, // use as default
- "optimize": `False`,
- }),
- }})
-}
-
-func TestAndroidAppLibs(t *testing.T) {
- runAndroidAppTestCase(t, Bp2buildTestCase{
- Description: "Android app with libs",
- ModuleTypeUnderTest: "android_app",
- ModuleTypeUnderTestFactory: java.AndroidAppFactory,
- Filesystem: map[string]string{},
- Blueprint: simpleModuleDoNotConvertBp2build("java_library", "barLib") + `
-android_app {
- name: "foo",
- libs: ["barLib"],
- sdk_version: "current",
- optimize: {
- enabled: false,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("android_binary", "foo", AttrNameToString{
- "manifest": `"AndroidManifest.xml"`,
- "resource_files": `[]`,
- "deps": `[":barLib-neverlink"]`,
- "sdk_version": `"current"`, // use as default
- "optimize": `False`,
- }),
- }})
-}
-
-func TestAndroidAppKotlinSrcs(t *testing.T) {
- runAndroidAppTestCase(t, Bp2buildTestCase{
- Description: "Android app with kotlin sources and common_srcs",
- ModuleTypeUnderTest: "android_app",
- ModuleTypeUnderTestFactory: java.AndroidAppFactory,
- Filesystem: map[string]string{
- "res/res.png": "",
- },
- Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "foocert") +
- simpleModuleDoNotConvertBp2build("java_library", "barLib") + `
-android_app {
- name: "foo",
- srcs: ["a.java", "b.kt"],
- certificate: ":foocert",
- manifest: "fooManifest.xml",
- libs: ["barLib"],
- sdk_version: "current",
- optimize: {
- enabled: false,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("android_library", "foo_kt", AttrNameToString{
- "srcs": `[
- "a.java",
- "b.kt",
- ]`,
- "manifest": `"fooManifest.xml"`,
- "resource_files": `["res/res.png"]`,
- "deps": `[":barLib-neverlink"]`,
- "sdk_version": `"current"`, // use as default
- }),
- MakeBazelTarget("android_binary", "foo", AttrNameToString{
- "deps": `[":foo_kt"]`,
- "certificate": `":foocert"`,
- "manifest": `"fooManifest.xml"`,
- "sdk_version": `"current"`, // use as default
- "optimize": `False`,
- }),
- }})
-}
-
-func TestAndroidAppCommonSrcs(t *testing.T) {
- runAndroidAppTestCase(t, Bp2buildTestCase{
- Description: "Android app with common_srcs",
- ModuleTypeUnderTest: "android_app",
- ModuleTypeUnderTestFactory: java.AndroidAppFactory,
- Filesystem: map[string]string{
- "res/res.png": "",
- },
- Blueprint: `
-android_app {
- name: "foo",
- srcs: ["a.java"],
- common_srcs: ["b.kt"],
- manifest: "fooManifest.xml",
- libs: ["barLib"],
- sdk_version: "current",
- optimize: {
- enabled: false,
- },
-}
-java_library{
- name: "barLib",
- bazel_module: { bp2build_available: false },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("android_library", "foo_kt", AttrNameToString{
- "srcs": `["a.java"]`,
- "common_srcs": `["b.kt"]`,
- "manifest": `"fooManifest.xml"`,
- "resource_files": `["res/res.png"]`,
- "deps": `[":barLib-neverlink"]`,
- "sdk_version": `"current"`, // use as default
- }),
- MakeBazelTarget("android_binary", "foo", AttrNameToString{
- "deps": `[":foo_kt"]`,
- "manifest": `"fooManifest.xml"`,
- "sdk_version": `"current"`, // use as default
- "optimize": `False`,
- }),
- }})
-}
-
-func TestAndroidAppKotlinCflags(t *testing.T) {
- runAndroidAppTestCase(t, Bp2buildTestCase{
- Description: "Android app with kotlincflags",
- ModuleTypeUnderTest: "android_app",
- ModuleTypeUnderTestFactory: java.AndroidAppFactory,
- Filesystem: map[string]string{
- "res/res.png": "",
- },
- Blueprint: `
-android_app {
- name: "foo",
- srcs: ["a.java", "b.kt"],
- manifest: "fooManifest.xml",
- kotlincflags: ["-flag1", "-flag2"],
- sdk_version: "current",
- optimize: {
- enabled: false,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("android_library", "foo_kt", AttrNameToString{
- "srcs": `[
- "a.java",
- "b.kt",
- ]`,
- "manifest": `"fooManifest.xml"`,
- "resource_files": `["res/res.png"]`,
- "kotlincflags": `[
- "-flag1",
- "-flag2",
- ]`,
- "sdk_version": `"current"`, // use as default
- }),
- MakeBazelTarget("android_binary", "foo", AttrNameToString{
- "deps": `[":foo_kt"]`,
- "manifest": `"fooManifest.xml"`,
- "sdk_version": `"current"`,
- "optimize": `False`,
- }),
- }})
-}
-
-func TestAndroidAppManifestSdkVersionsProvided(t *testing.T) {
- runAndroidAppTestCase(t, Bp2buildTestCase{
- Description: "Android app with value for min_sdk_version",
- ModuleTypeUnderTest: "android_app",
- ModuleTypeUnderTestFactory: java.AndroidAppFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-android_app {
- name: "foo",
- sdk_version: "current",
- min_sdk_version: "24",
- max_sdk_version: "30",
- target_sdk_version: "29",
- optimize: {
- enabled: false,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("android_binary", "foo", AttrNameToString{
- "manifest": `"AndroidManifest.xml"`,
- "resource_files": `[]`,
- "manifest_values": `{
- "maxSdkVersion": "30",
- "minSdkVersion": "24",
- "targetSdkVersion": "29",
- }`,
- "sdk_version": `"current"`,
- "optimize": `False`,
- }),
- }})
-}
-
-func TestAndroidAppMinAndTargetSdkDefaultToSdkVersion(t *testing.T) {
- runAndroidAppTestCase(t, Bp2buildTestCase{
- Description: "Android app with value for sdk_version",
- ModuleTypeUnderTest: "android_app",
- ModuleTypeUnderTestFactory: java.AndroidAppFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-android_app {
- name: "foo",
- sdk_version: "30",
- optimize: {
- enabled: false,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("android_binary", "foo", AttrNameToString{
- "manifest": `"AndroidManifest.xml"`,
- "resource_files": `[]`,
- "manifest_values": `{
- "minSdkVersion": "30",
- "targetSdkVersion": "30",
- }`,
- "sdk_version": `"30"`,
- "optimize": `False`,
- }),
- }})
-}
diff --git a/bp2build/apex_conversion_test.go b/bp2build/apex_conversion_test.go
deleted file mode 100644
index 2383247..0000000
--- a/bp2build/apex_conversion_test.go
+++ /dev/null
@@ -1,1595 +0,0 @@
-// 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
-
-import (
- "android/soong/android"
- "android/soong/apex"
- "android/soong/cc"
- "android/soong/etc"
- "android/soong/java"
- "android/soong/sh"
-
- "fmt"
- "testing"
-)
-
-func runApexTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, registerApexModuleTypes, tc)
-}
-
-func registerApexModuleTypes(ctx android.RegistrationContext) {
- // CC module types needed as they can be APEX dependencies
- cc.RegisterCCBuildComponents(ctx)
-
- ctx.RegisterModuleType("sh_binary", sh.ShBinaryFactory)
- ctx.RegisterModuleType("cc_binary", cc.BinaryFactory)
- ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
- ctx.RegisterModuleType("apex_key", apex.ApexKeyFactory)
- ctx.RegisterModuleType("android_app_certificate", java.AndroidAppCertificateFactory)
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- ctx.RegisterModuleType("prebuilt_etc", etc.PrebuiltEtcFactory)
- ctx.RegisterModuleType("cc_test", cc.TestFactory)
-}
-
-func runOverrideApexTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, registerOverrideApexModuleTypes, tc)
-}
-
-func registerOverrideApexModuleTypes(ctx android.RegistrationContext) {
- // CC module types needed as they can be APEX dependencies
- cc.RegisterCCBuildComponents(ctx)
-
- ctx.RegisterModuleType("sh_binary", sh.ShBinaryFactory)
- ctx.RegisterModuleType("cc_binary", cc.BinaryFactory)
- ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
- ctx.RegisterModuleType("apex_key", apex.ApexKeyFactory)
- ctx.RegisterModuleType("apex_test", apex.TestApexBundleFactory)
- ctx.RegisterModuleType("android_app_certificate", java.AndroidAppCertificateFactory)
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- ctx.RegisterModuleType("apex", apex.BundleFactory)
- ctx.RegisterModuleType("apex_defaults", apex.DefaultsFactory)
- ctx.RegisterModuleType("prebuilt_etc", etc.PrebuiltEtcFactory)
- ctx.RegisterModuleType("soong_config_module_type", android.SoongConfigModuleTypeFactory)
- ctx.RegisterModuleType("soong_config_string_variable", android.SoongConfigStringVariableDummyFactory)
-}
-
-func TestApexBundleSimple(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - example with all props, file_context is a module in same Android.bp",
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-apex_key {
- name: "com.android.apogee.key",
- public_key: "com.android.apogee.avbpubkey",
- private_key: "com.android.apogee.pem",
- bazel_module: { bp2build_available: false },
-}
-
-android_app_certificate {
- name: "com.android.apogee.certificate",
- certificate: "com.android.apogee",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "native_shared_lib_1",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "native_shared_lib_2",
- bazel_module: { bp2build_available: false },
-}
-
-prebuilt_etc {
- name: "prebuilt_1",
- bazel_module: { bp2build_available: false },
-}
-
-prebuilt_etc {
- name: "prebuilt_2",
- bazel_module: { bp2build_available: false },
-}
-
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [
- "com.android.apogee-file_contexts",
- ],
- bazel_module: { bp2build_available: false },
-}
-
-cc_binary { name: "cc_binary_1", bazel_module: { bp2build_available: false } }
-sh_binary { name: "sh_binary_2", bazel_module: { bp2build_available: false } }
-
-apex {
- name: "com.android.apogee",
- manifest: "apogee_manifest.json",
- androidManifest: "ApogeeAndroidManifest.xml",
- apex_available_name: "apogee_apex_name",
- file_contexts: ":com.android.apogee-file_contexts",
- min_sdk_version: "29",
- key: "com.android.apogee.key",
- certificate: ":com.android.apogee.certificate",
- updatable: false,
- installable: false,
- compressible: false,
- native_shared_libs: [
- "native_shared_lib_1",
- "native_shared_lib_2",
- ],
- binaries: [
- "cc_binary_1",
- "sh_binary_2",
- ],
- prebuilts: [
- "prebuilt_1",
- "prebuilt_2",
- ],
- package_name: "com.android.apogee.test.package",
- logging_parent: "logging.parent",
- variant_version: "3",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
- "android_manifest": `"ApogeeAndroidManifest.xml"`,
- "apex_available_name": `"apogee_apex_name"`,
- "binaries": `[
- ":cc_binary_1",
- ":sh_binary_2",
- ]`,
- "certificate": `":com.android.apogee.certificate"`,
- "file_contexts": `":com.android.apogee-file_contexts"`,
- "installable": "False",
- "key": `":com.android.apogee.key"`,
- "manifest": `"apogee_manifest.json"`,
- "min_sdk_version": `"29"`,
- "native_shared_libs_32": `select({
- "//build/bazel/platforms/arch:arm": [
- ":native_shared_lib_1",
- ":native_shared_lib_2",
- ],
- "//build/bazel/platforms/arch:x86": [
- ":native_shared_lib_1",
- ":native_shared_lib_2",
- ],
- "//conditions:default": [],
- })`,
- "native_shared_libs_64": `select({
- "//build/bazel/platforms/arch:arm64": [
- ":native_shared_lib_1",
- ":native_shared_lib_2",
- ],
- "//build/bazel/platforms/arch:x86_64": [
- ":native_shared_lib_1",
- ":native_shared_lib_2",
- ],
- "//conditions:default": [],
- })`,
- "prebuilts": `[
- ":prebuilt_1",
- ":prebuilt_2",
- ]`,
- "updatable": "False",
- "compressible": "False",
- "package_name": `"com.android.apogee.test.package"`,
- "logging_parent": `"logging.parent"`,
- "variant_version": `"3"`,
- }),
- }})
-}
-
-func TestApexBundleSimple_fileContextsInAnotherAndroidBp(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - file contexts is a module in another Android.bp",
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{
- "a/b/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [
- "com.android.apogee-file_contexts",
- ],
- bazel_module: { bp2build_available: false },
-}
-`,
- },
- Blueprint: `
-apex {
- name: "com.android.apogee",
- file_contexts: ":com.android.apogee-file_contexts",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
- "file_contexts": `"//a/b:com.android.apogee-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- }),
- }})
-}
-
-func TestApexBundleSimple_fileContextsIsFile(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - file contexts is a file",
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-apex {
- name: "com.android.apogee",
- file_contexts: "file_contexts_file",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
- "file_contexts": `"file_contexts_file"`,
- "manifest": `"apex_manifest.json"`,
- }),
- }})
-}
-
-func TestApexBundleSimple_fileContextsIsNotSpecified(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - file contexts is not specified",
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [
- "com.android.apogee-file_contexts",
- ],
- bazel_module: { bp2build_available: false },
-}
-`,
- },
- Blueprint: `
-apex {
- name: "com.android.apogee",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- }),
- }})
-}
-
-func TestApexBundleCompileMultilibBoth(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - example with compile_multilib=both",
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}
-`,
- },
- Blueprint: createMultilibBlueprint(`compile_multilib: "both",`),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
- "native_shared_libs_32": `[
- ":unnested_native_shared_lib",
- ":native_shared_lib_for_both",
- ":native_shared_lib_for_lib32",
- ] + select({
- "//build/bazel/platforms/arch:arm": [":native_shared_lib_for_first"],
- "//build/bazel/platforms/arch:x86": [":native_shared_lib_for_first"],
- "//conditions:default": [],
- })`,
- "native_shared_libs_64": `select({
- "//build/bazel/platforms/arch:arm64": [
- ":unnested_native_shared_lib",
- ":native_shared_lib_for_both",
- ":native_shared_lib_for_lib64",
- ":native_shared_lib_for_first",
- ],
- "//build/bazel/platforms/arch:x86_64": [
- ":unnested_native_shared_lib",
- ":native_shared_lib_for_both",
- ":native_shared_lib_for_lib64",
- ":native_shared_lib_for_first",
- ],
- "//conditions:default": [],
- })`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- }),
- }})
-}
-
-func TestApexBundleCompileMultilibFirstAndDefaultValue(t *testing.T) {
- expectedBazelTargets := []string{
- MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
- "native_shared_libs_32": `select({
- "//build/bazel/platforms/arch:arm": [
- ":unnested_native_shared_lib",
- ":native_shared_lib_for_both",
- ":native_shared_lib_for_lib32",
- ":native_shared_lib_for_first",
- ],
- "//build/bazel/platforms/arch:x86": [
- ":unnested_native_shared_lib",
- ":native_shared_lib_for_both",
- ":native_shared_lib_for_lib32",
- ":native_shared_lib_for_first",
- ],
- "//conditions:default": [],
- })`,
- "native_shared_libs_64": `select({
- "//build/bazel/platforms/arch:arm64": [
- ":unnested_native_shared_lib",
- ":native_shared_lib_for_both",
- ":native_shared_lib_for_lib64",
- ":native_shared_lib_for_first",
- ],
- "//build/bazel/platforms/arch:x86_64": [
- ":unnested_native_shared_lib",
- ":native_shared_lib_for_both",
- ":native_shared_lib_for_lib64",
- ":native_shared_lib_for_first",
- ],
- "//conditions:default": [],
- })`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- }),
- }
-
- // "first" is the default value of compile_multilib prop so `compile_multilib_: "first"` and unset compile_multilib
- // should result to the same bp2build output
- compileMultiLibPropValues := []string{`compile_multilib: "first",`, ""}
- for _, compileMultiLibProp := range compileMultiLibPropValues {
- descriptionSuffix := compileMultiLibProp
- if descriptionSuffix == "" {
- descriptionSuffix = "compile_multilib unset"
- }
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - example with " + compileMultiLibProp,
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
- filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
- }
- `,
- },
- Blueprint: createMultilibBlueprint(compileMultiLibProp),
- ExpectedBazelTargets: expectedBazelTargets,
- })
- }
-}
-
-func TestApexBundleCompileMultilib32(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - example with compile_multilib=32",
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}
-`,
- },
- Blueprint: createMultilibBlueprint(`compile_multilib: "32",`),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
- "native_shared_libs_32": `[
- ":unnested_native_shared_lib",
- ":native_shared_lib_for_both",
- ":native_shared_lib_for_lib32",
- ] + select({
- "//build/bazel/platforms/arch:arm": [":native_shared_lib_for_first"],
- "//build/bazel/platforms/arch:x86": [":native_shared_lib_for_first"],
- "//conditions:default": [],
- })`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- }),
- }})
-}
-
-func TestApexBundleCompileMultilib64(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - example with compile_multilib=64",
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}
-`,
- },
- Blueprint: createMultilibBlueprint(`compile_multilib: "64",`),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
- "native_shared_libs_64": `select({
- "//build/bazel/platforms/arch:arm64": [
- ":unnested_native_shared_lib",
- ":native_shared_lib_for_both",
- ":native_shared_lib_for_lib64",
- ":native_shared_lib_for_first",
- ],
- "//build/bazel/platforms/arch:x86_64": [
- ":unnested_native_shared_lib",
- ":native_shared_lib_for_both",
- ":native_shared_lib_for_lib64",
- ":native_shared_lib_for_first",
- ],
- "//conditions:default": [],
- })`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- }),
- }})
-}
-
-func createMultilibBlueprint(compile_multilib string) string {
- return fmt.Sprintf(`
-cc_library {
- name: "native_shared_lib_for_both",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "native_shared_lib_for_first",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "native_shared_lib_for_lib32",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "native_shared_lib_for_lib64",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "unnested_native_shared_lib",
- bazel_module: { bp2build_available: false },
-}
-
-apex {
- name: "com.android.apogee",
- %s
- native_shared_libs: ["unnested_native_shared_lib"],
- multilib: {
- both: {
- native_shared_libs: [
- "native_shared_lib_for_both",
- ],
- },
- first: {
- native_shared_libs: [
- "native_shared_lib_for_first",
- ],
- },
- lib32: {
- native_shared_libs: [
- "native_shared_lib_for_lib32",
- ],
- },
- lib64: {
- native_shared_libs: [
- "native_shared_lib_for_lib64",
- ],
- },
- },
-}`, compile_multilib)
-}
-
-func TestApexBundleDefaultPropertyValues(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - default property values",
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}
-`,
- },
- Blueprint: `
-apex {
- name: "com.android.apogee",
- manifest: "apogee_manifest.json",
-}
-`,
- ExpectedBazelTargets: []string{MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
- "manifest": `"apogee_manifest.json"`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- }),
- }})
-}
-
-func TestApexBundleHasBazelModuleProps(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - has bazel module props",
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}
-`,
- },
- Blueprint: `
-apex {
- name: "apogee",
- manifest: "manifest.json",
- bazel_module: { bp2build_available: true },
-}
-`,
- ExpectedBazelTargets: []string{MakeBazelTarget("apex", "apogee", AttrNameToString{
- "manifest": `"manifest.json"`,
- "file_contexts": `"//system/sepolicy/apex:apogee-file_contexts"`,
- }),
- }})
-}
-
-func TestBp2BuildOverrideApex(t *testing.T) {
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "override_apex",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-apex_key {
- name: "com.android.apogee.key",
- public_key: "com.android.apogee.avbpubkey",
- private_key: "com.android.apogee.pem",
- bazel_module: { bp2build_available: false },
-}
-
-android_app_certificate {
- name: "com.android.apogee.certificate",
- certificate: "com.android.apogee",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "native_shared_lib_1",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "native_shared_lib_2",
- bazel_module: { bp2build_available: false },
-}
-
-prebuilt_etc {
- name: "prebuilt_1",
- bazel_module: { bp2build_available: false },
-}
-
-prebuilt_etc {
- name: "prebuilt_2",
- bazel_module: { bp2build_available: false },
-}
-
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [
- "com.android.apogee-file_contexts",
- ],
- bazel_module: { bp2build_available: false },
-}
-
-cc_binary { name: "cc_binary_1", bazel_module: { bp2build_available: false } }
-sh_binary { name: "sh_binary_2", bazel_module: { bp2build_available: false } }
-
-apex {
- name: "com.android.apogee",
- manifest: "apogee_manifest.json",
- androidManifest: "ApogeeAndroidManifest.xml",
- file_contexts: ":com.android.apogee-file_contexts",
- min_sdk_version: "29",
- key: "com.android.apogee.key",
- certificate: ":com.android.apogee.certificate",
- updatable: false,
- installable: false,
- compressible: false,
- native_shared_libs: [
- "native_shared_lib_1",
- "native_shared_lib_2",
- ],
- binaries: [
- "cc_binary_1",
- "sh_binary_2",
- ],
- prebuilts: [
- "prebuilt_1",
- "prebuilt_2",
- ],
- bazel_module: { bp2build_available: false },
-}
-
-apex_key {
- name: "com.google.android.apogee.key",
- public_key: "com.google.android.apogee.avbpubkey",
- private_key: "com.google.android.apogee.pem",
- bazel_module: { bp2build_available: false },
-}
-
-android_app_certificate {
- name: "com.google.android.apogee.certificate",
- certificate: "com.google.android.apogee",
- bazel_module: { bp2build_available: false },
-}
-
-override_apex {
- name: "com.google.android.apogee",
- base: ":com.android.apogee",
- key: "com.google.android.apogee.key",
- certificate: ":com.google.android.apogee.certificate",
- prebuilts: [],
- compressible: true,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
- "android_manifest": `"ApogeeAndroidManifest.xml"`,
- "base_apex_name": `"com.android.apogee"`,
- "binaries": `[
- ":cc_binary_1",
- ":sh_binary_2",
- ]`,
- "certificate": `":com.google.android.apogee.certificate"`,
- "file_contexts": `":com.android.apogee-file_contexts"`,
- "installable": "False",
- "key": `":com.google.android.apogee.key"`,
- "manifest": `"apogee_manifest.json"`,
- "min_sdk_version": `"29"`,
- "native_shared_libs_32": `select({
- "//build/bazel/platforms/arch:arm": [
- ":native_shared_lib_1",
- ":native_shared_lib_2",
- ],
- "//build/bazel/platforms/arch:x86": [
- ":native_shared_lib_1",
- ":native_shared_lib_2",
- ],
- "//conditions:default": [],
- })`,
- "native_shared_libs_64": `select({
- "//build/bazel/platforms/arch:arm64": [
- ":native_shared_lib_1",
- ":native_shared_lib_2",
- ],
- "//build/bazel/platforms/arch:x86_64": [
- ":native_shared_lib_1",
- ":native_shared_lib_2",
- ],
- "//conditions:default": [],
- })`,
- "prebuilts": `[]`,
- "updatable": "False",
- "compressible": "True",
- }),
- }})
-}
-
-func TestOverrideApexTest(t *testing.T) {
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "override_apex",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-apex_key {
- name: "com.android.apogee.key",
- public_key: "com.android.apogee.avbpubkey",
- private_key: "com.android.apogee.pem",
- bazel_module: { bp2build_available: false },
-}
-
-android_app_certificate {
- name: "com.android.apogee.certificate",
- certificate: "com.android.apogee",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "native_shared_lib_1",
- bazel_module: { bp2build_available: false },
-}
-
-prebuilt_etc {
- name: "prebuilt_1",
- bazel_module: { bp2build_available: false },
-}
-
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [
- "com.android.apogee-file_contexts",
- ],
- bazel_module: { bp2build_available: false },
-}
-
-cc_binary { name: "cc_binary_1", bazel_module: { bp2build_available: false } }
-sh_binary { name: "sh_binary_2", bazel_module: { bp2build_available: false } }
-
-apex_test {
- name: "com.android.apogee",
- manifest: "apogee_manifest.json",
- androidManifest: "ApogeeAndroidManifest.xml",
- file_contexts: ":com.android.apogee-file_contexts",
- min_sdk_version: "29",
- key: "com.android.apogee.key",
- certificate: ":com.android.apogee.certificate",
- updatable: false,
- installable: false,
- compressible: false,
- native_shared_libs: [
- "native_shared_lib_1",
- ],
- binaries: [
- "cc_binary_1",
- "sh_binary_2",
- ],
- prebuilts: [
- "prebuilt_1",
- ],
- bazel_module: { bp2build_available: false },
-}
-
-apex_key {
- name: "com.google.android.apogee.key",
- public_key: "com.google.android.apogee.avbpubkey",
- private_key: "com.google.android.apogee.pem",
- bazel_module: { bp2build_available: false },
-}
-
-android_app_certificate {
- name: "com.google.android.apogee.certificate",
- certificate: "com.google.android.apogee",
- bazel_module: { bp2build_available: false },
-}
-
-override_apex {
- name: "com.google.android.apogee",
- base: ":com.android.apogee",
- key: "com.google.android.apogee.key",
- certificate: ":com.google.android.apogee.certificate",
- prebuilts: [],
- compressible: true,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
- "android_manifest": `"ApogeeAndroidManifest.xml"`,
- "base_apex_name": `"com.android.apogee"`,
- "binaries": `[
- ":cc_binary_1",
- ":sh_binary_2",
- ]`,
- "certificate": `":com.google.android.apogee.certificate"`,
- "file_contexts": `":com.android.apogee-file_contexts"`,
- "installable": "False",
- "key": `":com.google.android.apogee.key"`,
- "manifest": `"apogee_manifest.json"`,
- "min_sdk_version": `"29"`,
- "native_shared_libs_32": `select({
- "//build/bazel/platforms/arch:arm": [":native_shared_lib_1"],
- "//build/bazel/platforms/arch:x86": [":native_shared_lib_1"],
- "//conditions:default": [],
- })`,
- "native_shared_libs_64": `select({
- "//build/bazel/platforms/arch:arm64": [":native_shared_lib_1"],
- "//build/bazel/platforms/arch:x86_64": [":native_shared_lib_1"],
- "//conditions:default": [],
- })`,
- "testonly": "True",
- "prebuilts": `[]`,
- "updatable": "False",
- "compressible": "True",
- }),
- }})
-}
-
-func TestApexBundleSimple_manifestIsEmpty_baseApexOverrideApexInDifferentAndroidBp(t *testing.T) {
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "override_apex - manifest of base apex is empty, base apex and override_apex is in different Android.bp",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}`,
- "a/b/Android.bp": `
-apex {
- name: "com.android.apogee",
- bazel_module: { bp2build_available: false },
-}
-`,
- },
- Blueprint: `
-override_apex {
- name: "com.google.android.apogee",
- base: ":com.android.apogee",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
- "base_apex_name": `"com.android.apogee"`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"//a/b:apex_manifest.json"`,
- }),
- }})
-}
-
-func TestApexBundleSimple_manifestIsSet_baseApexOverrideApexInDifferentAndroidBp(t *testing.T) {
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "override_apex - manifest of base apex is set, base apex and override_apex is in different Android.bp",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}`,
- "a/b/Android.bp": `
-apex {
- name: "com.android.apogee",
- manifest: "apogee_manifest.json",
- bazel_module: { bp2build_available: false },
-}
-`,
- },
- Blueprint: `
-override_apex {
- name: "com.google.android.apogee",
- base: ":com.android.apogee",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
- "base_apex_name": `"com.android.apogee"`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"//a/b:apogee_manifest.json"`,
- }),
- }})
-}
-
-func TestApexBundleSimple_manifestIsEmpty_baseApexOverrideApexInSameAndroidBp(t *testing.T) {
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "override_apex - manifest of base apex is empty, base apex and override_apex is in same Android.bp",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}`,
- },
- Blueprint: `
-apex {
- name: "com.android.apogee",
- bazel_module: { bp2build_available: false },
-}
-
-override_apex {
- name: "com.google.android.apogee",
- base: ":com.android.apogee",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
- "base_apex_name": `"com.android.apogee"`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- }),
- }})
-}
-
-func TestApexBundleSimple_manifestIsSet_baseApexOverrideApexInSameAndroidBp(t *testing.T) {
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "override_apex - manifest of base apex is set, base apex and override_apex is in same Android.bp",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}`,
- },
- Blueprint: `
-apex {
- name: "com.android.apogee",
- manifest: "apogee_manifest.json",
- bazel_module: { bp2build_available: false },
-}
-
-override_apex {
- name: "com.google.android.apogee",
- base: ":com.android.apogee",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
- "base_apex_name": `"com.android.apogee"`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"apogee_manifest.json"`,
- }),
- }})
-}
-
-func TestApexBundleSimple_packageNameOverride(t *testing.T) {
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "override_apex - override package name",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}`,
- },
- Blueprint: `
-apex {
- name: "com.android.apogee",
- bazel_module: { bp2build_available: false },
-}
-
-override_apex {
- name: "com.google.android.apogee",
- base: ":com.android.apogee",
- package_name: "com.google.android.apogee",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
- "base_apex_name": `"com.android.apogee"`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- "package_name": `"com.google.android.apogee"`,
- }),
- }})
-}
-
-func TestApexBundleSimple_NoPrebuiltsOverride(t *testing.T) {
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "override_apex - no override",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}`,
- },
- Blueprint: `
-prebuilt_etc {
- name: "prebuilt_file",
- bazel_module: { bp2build_available: false },
-}
-
-apex {
- name: "com.android.apogee",
- bazel_module: { bp2build_available: false },
- prebuilts: ["prebuilt_file"]
-}
-
-override_apex {
- name: "com.google.android.apogee",
- base: ":com.android.apogee",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
- "base_apex_name": `"com.android.apogee"`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- "prebuilts": `[":prebuilt_file"]`,
- }),
- }})
-}
-
-func TestApexBundleSimple_PrebuiltsOverride(t *testing.T) {
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "override_apex - ooverride",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}`,
- },
- Blueprint: `
-prebuilt_etc {
- name: "prebuilt_file",
- bazel_module: { bp2build_available: false },
-}
-
-prebuilt_etc {
- name: "prebuilt_file2",
- bazel_module: { bp2build_available: false },
-}
-
-apex {
- name: "com.android.apogee",
- bazel_module: { bp2build_available: false },
- prebuilts: ["prebuilt_file"]
-}
-
-override_apex {
- name: "com.google.android.apogee",
- base: ":com.android.apogee",
- prebuilts: ["prebuilt_file2"]
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
- "base_apex_name": `"com.android.apogee"`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- "prebuilts": `[":prebuilt_file2"]`,
- }),
- }})
-}
-
-func TestApexBundleSimple_PrebuiltsOverrideEmptyList(t *testing.T) {
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "override_apex - override with empty list",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}`,
- },
- Blueprint: `
-prebuilt_etc {
- name: "prebuilt_file",
- bazel_module: { bp2build_available: false },
-}
-
-apex {
- name: "com.android.apogee",
- bazel_module: { bp2build_available: false },
- prebuilts: ["prebuilt_file"]
-}
-
-override_apex {
- name: "com.google.android.apogee",
- base: ":com.android.apogee",
- prebuilts: [],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
- "base_apex_name": `"com.android.apogee"`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- "prebuilts": `[]`,
- }),
- }})
-}
-
-func TestApexBundleSimple_NoLoggingParentOverride(t *testing.T) {
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "override_apex - logging_parent - no override",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}`,
- },
- Blueprint: `
-apex {
- name: "com.android.apogee",
- bazel_module: { bp2build_available: false },
- logging_parent: "foo.bar.baz",
-}
-
-override_apex {
- name: "com.google.android.apogee",
- base: ":com.android.apogee",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
- "base_apex_name": `"com.android.apogee"`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- "logging_parent": `"foo.bar.baz"`,
- }),
- }})
-}
-
-func TestApexBundleSimple_LoggingParentOverride(t *testing.T) {
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "override_apex - logging_parent - override",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Filesystem: map[string]string{
- "system/sepolicy/apex/Android.bp": `
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [ "apogee-file_contexts", ],
- bazel_module: { bp2build_available: false },
-}`,
- },
- Blueprint: `
-apex {
- name: "com.android.apogee",
- bazel_module: { bp2build_available: false },
- logging_parent: "foo.bar.baz",
-}
-
-override_apex {
- name: "com.google.android.apogee",
- base: ":com.android.apogee",
- logging_parent: "foo.bar.baz.override",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
- "base_apex_name": `"com.android.apogee"`,
- "file_contexts": `"//system/sepolicy/apex:com.android.apogee-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- "logging_parent": `"foo.bar.baz.override"`,
- }),
- }})
-}
-
-func TestBp2BuildOverrideApex_CertificateNil(t *testing.T) {
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "override_apex - don't set default certificate",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-android_app_certificate {
- name: "com.android.apogee.certificate",
- certificate: "com.android.apogee",
- bazel_module: { bp2build_available: false },
-}
-
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [
- "com.android.apogee-file_contexts",
- ],
- bazel_module: { bp2build_available: false },
-}
-
-apex {
- name: "com.android.apogee",
- manifest: "apogee_manifest.json",
- file_contexts: ":com.android.apogee-file_contexts",
- certificate: ":com.android.apogee.certificate",
- bazel_module: { bp2build_available: false },
-}
-
-override_apex {
- name: "com.google.android.apogee",
- base: ":com.android.apogee",
- // certificate is deliberately omitted, and not converted to bazel,
- // because the overridden apex shouldn't be using the base apex's cert.
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
- "base_apex_name": `"com.android.apogee"`,
- "file_contexts": `":com.android.apogee-file_contexts"`,
- "manifest": `"apogee_manifest.json"`,
- }),
- }})
-}
-
-func TestApexCertificateIsModule(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - certificate is module",
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-android_app_certificate {
- name: "com.android.apogee.certificate",
- certificate: "com.android.apogee",
- bazel_module: { bp2build_available: false },
-}
-
-apex {
- name: "com.android.apogee",
- manifest: "apogee_manifest.json",
- file_contexts: ":com.android.apogee-file_contexts",
- certificate: ":com.android.apogee.certificate",
-}
-` + simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee-file_contexts"),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
- "certificate": `":com.android.apogee.certificate"`,
- "file_contexts": `":com.android.apogee-file_contexts"`,
- "manifest": `"apogee_manifest.json"`,
- }),
- }})
-}
-
-func TestApexWithStubLib(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - static variant of stub lib should not have apex_available tag",
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-cc_library{
- name: "foo",
- stubs: { symbol_file: "foo.map.txt", versions: ["28", "29", "current"] },
- apex_available: ["myapex"],
-}
-
-cc_binary{
- name: "bar",
- static_libs: ["foo"],
- apex_available: ["myapex"],
-}
-
-apex {
- name: "myapex",
- manifest: "myapex_manifest.json",
- file_contexts: ":myapex-file_contexts",
- binaries: ["bar"],
- native_shared_libs: ["foo"],
-}
-` + simpleModuleDoNotConvertBp2build("filegroup", "myapex-file_contexts"),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_binary", "bar", AttrNameToString{
- "local_includes": `["."]`,
- "deps": `[":foo_bp2build_cc_library_static"]`,
- "tags": `["apex_available=myapex"]`,
- }),
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "stubs_symbol_file": `"foo.map.txt"`,
- "tags": `["apex_available=myapex"]`,
- }),
- MakeBazelTarget("cc_stub_suite", "foo_stub_libs", AttrNameToString{
- "soname": `"foo.so"`,
- "source_library_label": `"//:foo"`,
- "symbol_file": `"foo.map.txt"`,
- "versions": `[
- "28",
- "29",
- "current",
- ]`,
- }),
- MakeBazelTarget("apex", "myapex", AttrNameToString{
- "file_contexts": `":myapex-file_contexts"`,
- "manifest": `"myapex_manifest.json"`,
- "binaries": `[":bar"]`,
- "native_shared_libs_32": `select({
- "//build/bazel/platforms/arch:arm": [":foo"],
- "//build/bazel/platforms/arch:x86": [":foo"],
- "//conditions:default": [],
- })`,
- "native_shared_libs_64": `select({
- "//build/bazel/platforms/arch:arm64": [":foo"],
- "//build/bazel/platforms/arch:x86_64": [":foo"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestApexCertificateIsSrc(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - certificate is src",
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-apex {
- name: "com.android.apogee",
- manifest: "apogee_manifest.json",
- file_contexts: ":com.android.apogee-file_contexts",
- certificate: "com.android.apogee.certificate",
-}
-` + simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee-file_contexts"),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
- "certificate_name": `"com.android.apogee.certificate"`,
- "file_contexts": `":com.android.apogee-file_contexts"`,
- "manifest": `"apogee_manifest.json"`,
- }),
- }})
-}
-
-func TestBp2BuildOverrideApex_CertificateIsModule(t *testing.T) {
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "override_apex - certificate is module",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-android_app_certificate {
- name: "com.android.apogee.certificate",
- certificate: "com.android.apogee",
- bazel_module: { bp2build_available: false },
-}
-
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [
- "com.android.apogee-file_contexts",
- ],
- bazel_module: { bp2build_available: false },
-}
-
-apex {
- name: "com.android.apogee",
- manifest: "apogee_manifest.json",
- file_contexts: ":com.android.apogee-file_contexts",
- certificate: ":com.android.apogee.certificate",
- bazel_module: { bp2build_available: false },
-}
-
-android_app_certificate {
- name: "com.google.android.apogee.certificate",
- certificate: "com.google.android.apogee",
- bazel_module: { bp2build_available: false },
-}
-
-override_apex {
- name: "com.google.android.apogee",
- base: ":com.android.apogee",
- certificate: ":com.google.android.apogee.certificate",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
- "base_apex_name": `"com.android.apogee"`,
- "file_contexts": `":com.android.apogee-file_contexts"`,
- "certificate": `":com.google.android.apogee.certificate"`,
- "manifest": `"apogee_manifest.json"`,
- }),
- }})
-}
-
-func TestBp2BuildOverrideApex_CertificateIsSrc(t *testing.T) {
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "override_apex - certificate is src",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-android_app_certificate {
- name: "com.android.apogee.certificate",
- certificate: "com.android.apogee",
- bazel_module: { bp2build_available: false },
-}
-
-filegroup {
- name: "com.android.apogee-file_contexts",
- srcs: [
- "com.android.apogee-file_contexts",
- ],
- bazel_module: { bp2build_available: false },
-}
-
-apex {
- name: "com.android.apogee",
- manifest: "apogee_manifest.json",
- file_contexts: ":com.android.apogee-file_contexts",
- certificate: ":com.android.apogee.certificate",
- bazel_module: { bp2build_available: false },
-}
-
-override_apex {
- name: "com.google.android.apogee",
- base: ":com.android.apogee",
- certificate: "com.google.android.apogee.certificate",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.google.android.apogee", AttrNameToString{
- "base_apex_name": `"com.android.apogee"`,
- "file_contexts": `":com.android.apogee-file_contexts"`,
- "certificate_name": `"com.google.android.apogee.certificate"`,
- "manifest": `"apogee_manifest.json"`,
- }),
- }})
-}
-
-func TestApexTestBundleSimple(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex_test - simple",
- ModuleTypeUnderTest: "apex_test",
- ModuleTypeUnderTestFactory: apex.TestApexBundleFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-cc_test { name: "cc_test_1", bazel_module: { bp2build_available: false } }
-
-apex_test {
- name: "test_com.android.apogee",
- file_contexts: "file_contexts_file",
- tests: ["cc_test_1"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "test_com.android.apogee", AttrNameToString{
- "file_contexts": `"file_contexts_file"`,
- "base_apex_name": `"com.android.apogee"`,
- "manifest": `"apex_manifest.json"`,
- "testonly": `True`,
- "tests": `[":cc_test_1"]`,
- }),
- }})
-}
-
-func TestApexBundle_overridePlusProductVars(t *testing.T) {
- // Reproduction of b/271424349
- // Tests that overriding an apex that uses product variables correctly copies the product var
- // selects over to the override.
- runOverrideApexTestCase(t, Bp2buildTestCase{
- Description: "apex - overriding a module that uses product vars",
- ModuleTypeUnderTest: "override_apex",
- ModuleTypeUnderTestFactory: apex.OverrideApexFactory,
- Blueprint: `
-soong_config_string_variable {
- name: "library_linking_strategy",
- values: [
- "prefer_static",
- ],
-}
-
-soong_config_module_type {
- name: "library_linking_strategy_apex_defaults",
- module_type: "apex_defaults",
- config_namespace: "ANDROID",
- variables: ["library_linking_strategy"],
- properties: [
- "manifest",
- "min_sdk_version",
- ],
-}
-
-library_linking_strategy_apex_defaults {
- name: "higher_min_sdk_when_prefer_static",
- soong_config_variables: {
- library_linking_strategy: {
- // Use the R min_sdk_version
- prefer_static: {},
- // Override the R min_sdk_version to min_sdk_version that supports dcla
- conditions_default: {
- min_sdk_version: "31",
- },
- },
- },
-}
-
-filegroup {
- name: "foo-file_contexts",
- srcs: [
- "com.android.apogee-file_contexts",
- ],
- bazel_module: { bp2build_available: false },
-}
-
-apex {
- name: "foo",
- defaults: ["higher_min_sdk_when_prefer_static"],
- min_sdk_version: "30",
- package_name: "pkg_name",
- file_contexts: ":foo-file_contexts",
-}
-override_apex {
- name: "override_foo",
- base: ":foo",
- package_name: "override_pkg_name",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "foo", AttrNameToString{
- "file_contexts": `":foo-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- "min_sdk_version": `select({
- "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": "30",
- "//conditions:default": "31",
- })`,
- "package_name": `"pkg_name"`,
- }), MakeBazelTarget("apex", "override_foo", AttrNameToString{
- "base_apex_name": `"foo"`,
- "file_contexts": `":foo-file_contexts"`,
- "manifest": `"apex_manifest.json"`,
- "min_sdk_version": `select({
- "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": "30",
- "//conditions:default": "31",
- })`,
- "package_name": `"override_pkg_name"`,
- }),
- }})
-}
-
-func TestApexBundleSimple_customCannedFsConfig(t *testing.T) {
- runApexTestCase(t, Bp2buildTestCase{
- Description: "apex - custom canned_fs_config",
- ModuleTypeUnderTest: "apex",
- ModuleTypeUnderTestFactory: apex.BundleFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-apex {
- name: "com.android.apogee",
- canned_fs_config: "custom.canned_fs_config",
- file_contexts: "file_contexts_file",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("apex", "com.android.apogee", AttrNameToString{
- "canned_fs_config": `"custom.canned_fs_config"`,
- "file_contexts": `"file_contexts_file"`,
- "manifest": `"apex_manifest.json"`,
- }),
- }})
-}
diff --git a/bp2build/apex_key_conversion_test.go b/bp2build/apex_key_conversion_test.go
deleted file mode 100644
index 1230a48..0000000
--- a/bp2build/apex_key_conversion_test.go
+++ /dev/null
@@ -1,100 +0,0 @@
-// 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
-
-import (
- "android/soong/android"
- "android/soong/apex"
-
- "testing"
-)
-
-func runApexKeyTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, registerApexKeyModuleTypes, tc)
-}
-
-func registerApexKeyModuleTypes(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
-}
-
-func TestApexKeySimple_KeysAreSrcFilesInSameDir(t *testing.T) {
- runApexKeyTestCase(t, Bp2buildTestCase{
- Description: "apex key - keys are src files, use key attributes",
- ModuleTypeUnderTest: "apex_key",
- ModuleTypeUnderTestFactory: apex.ApexKeyFactory,
- Filesystem: map[string]string{
- "com.android.apogee.avbpubkey": "",
- "com.android.apogee.pem": "",
- },
- Blueprint: `
-apex_key {
- name: "com.android.apogee.key",
- public_key: "com.android.apogee.avbpubkey",
- private_key: "com.android.apogee.pem",
-}
-`,
- ExpectedBazelTargets: []string{MakeBazelTargetNoRestrictions("apex_key", "com.android.apogee.key", AttrNameToString{
- "private_key": `"com.android.apogee.pem"`,
- "public_key": `"com.android.apogee.avbpubkey"`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- }),
- }})
-}
-
-func TestApexKeySimple_KeysAreSrcFilesNotInDir(t *testing.T) {
- runApexKeyTestCase(t, Bp2buildTestCase{
- Description: "apex key - keys are not src or module, use key_name attributes",
- ModuleTypeUnderTest: "apex_key",
- ModuleTypeUnderTestFactory: apex.ApexKeyFactory,
- Filesystem: map[string]string{
- // deliberately left empty
- },
- Blueprint: `
-apex_key {
- name: "com.android.apogee.key",
- public_key: "com.android.apogee.avbpubkey",
- private_key: "com.android.apogee.pem",
-}
-`,
- ExpectedBazelTargets: []string{MakeBazelTargetNoRestrictions("apex_key", "com.android.apogee.key", AttrNameToString{
- "private_key_name": `"com.android.apogee.pem"`,
- "public_key_name": `"com.android.apogee.avbpubkey"`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- }),
- }})
-}
-
-func TestApexKey_KeysAreModules(t *testing.T) {
- runApexKeyTestCase(t, Bp2buildTestCase{
- Description: "apex key - keys are modules, use key attributes",
- ModuleTypeUnderTest: "apex_key",
- ModuleTypeUnderTestFactory: apex.ApexKeyFactory,
- Filesystem: map[string]string{},
- Blueprint: `
-apex_key {
- name: "com.android.apogee.key",
- public_key: ":com.android.apogee.avbpubkey",
- private_key: ":com.android.apogee.pem",
-}
-` + simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee.avbpubkey") +
- simpleModuleDoNotConvertBp2build("filegroup", "com.android.apogee.pem"),
- ExpectedBazelTargets: []string{MakeBazelTargetNoRestrictions("apex_key", "com.android.apogee.key", AttrNameToString{
- "private_key": `":com.android.apogee.pem"`,
- "public_key": `":com.android.apogee.avbpubkey"`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- }),
- }})
-}
diff --git a/bp2build/bp2build.go b/bp2build/bp2build.go
deleted file mode 100644
index 5f7b382..0000000
--- a/bp2build/bp2build.go
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2020 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"
- "os"
- "path/filepath"
- "strings"
-
- "android/soong/android"
- "android/soong/bazel"
- "android/soong/shared"
- "android/soong/starlark_import"
-)
-
-func deleteFilesExcept(ctx *CodegenContext, rootOutputPath android.OutputPath, except []BazelFile) {
- // Delete files that should no longer be present.
- bp2buildDirAbs := shared.JoinPath(ctx.topDir, rootOutputPath.String())
-
- filesToDelete := make(map[string]struct{})
- err := filepath.Walk(bp2buildDirAbs,
- func(path string, info os.FileInfo, err error) error {
- if err != nil {
- return err
- }
- if !info.IsDir() {
- relPath, err := filepath.Rel(bp2buildDirAbs, path)
- if err != nil {
- return err
- }
- filesToDelete[relPath] = struct{}{}
- }
- return nil
- })
- if err != nil {
- fmt.Printf("ERROR reading %s: %s", bp2buildDirAbs, err)
- os.Exit(1)
- }
-
- for _, bazelFile := range except {
- filePath := filepath.Join(bazelFile.Dir, bazelFile.Basename)
- delete(filesToDelete, filePath)
- }
- for f, _ := range filesToDelete {
- absPath := shared.JoinPath(bp2buildDirAbs, f)
- if err := os.RemoveAll(absPath); err != nil {
- fmt.Printf("ERROR deleting %s: %s", absPath, err)
- os.Exit(1)
- }
- }
-}
-
-// Codegen is the backend of bp2build. The code generator is responsible for
-// writing .bzl files that are equivalent to Android.bp files that are capable
-// of being built with Bazel.
-func Codegen(ctx *CodegenContext) *CodegenMetrics {
- ctx.Context().BeginEvent("Codegen")
- defer ctx.Context().EndEvent("Codegen")
- // This directory stores BUILD files that could be eventually checked-in.
- bp2buildDir := android.PathForOutput(ctx, "bp2build")
-
- res, errs := GenerateBazelTargets(ctx, true)
- if len(errs) > 0 {
- errMsgs := make([]string, len(errs))
- for i, err := range errs {
- errMsgs[i] = fmt.Sprintf("%q", err)
- }
- fmt.Printf("ERROR: Encountered %d error(s): \nERROR: %s", len(errs), strings.Join(errMsgs, "\n"))
- os.Exit(1)
- }
- var bp2buildFiles []BazelFile
- ctx.Context().EventHandler.Do("CreateBazelFile", func() {
- bp2buildFiles = CreateBazelFiles(nil, res.buildFileToTargets, ctx.mode)
- })
- injectionFiles, additionalBp2buildFiles, err := CreateSoongInjectionDirFiles(ctx, res.metrics)
- if err != nil {
- fmt.Printf("%s\n", err.Error())
- os.Exit(1)
- }
- bp2buildFiles = append(bp2buildFiles, additionalBp2buildFiles...)
- writeFiles(ctx, bp2buildDir, bp2buildFiles)
- // Delete files under the bp2build root which weren't just written. An
- // alternative would have been to delete the whole directory and write these
- // files. However, this would regenerate files which were otherwise unchanged
- // since the last bp2build run, which would have negative incremental
- // performance implications.
- deleteFilesExcept(ctx, bp2buildDir, bp2buildFiles)
-
- writeFiles(ctx, android.PathForOutput(ctx, bazel.SoongInjectionDirName), injectionFiles)
- starlarkDeps, err := starlark_import.GetNinjaDeps()
- if err != nil {
- fmt.Fprintf(os.Stderr, "%s\n", err)
- os.Exit(1)
- }
- ctx.AddNinjaFileDeps(starlarkDeps...)
- return &res.metrics
-}
-
-// Wrapper function that will be responsible for all files in soong_injection directory
-// This includes
-// 1. config value(s) that are hardcoded in Soong
-// 2. product_config variables
-func CreateSoongInjectionDirFiles(ctx *CodegenContext, metrics CodegenMetrics) ([]BazelFile, []BazelFile, error) {
- var ret []BazelFile
-
- productConfigInjectionFiles, productConfigBp2BuildDirFiles, err := CreateProductConfigFiles(ctx, metrics)
- if err != nil {
- return nil, nil, err
- }
- ret = append(ret, productConfigInjectionFiles...)
- injectionFiles, err := soongInjectionFiles(ctx.Config(), metrics)
- if err != nil {
- return nil, nil, err
- }
- ret = append(injectionFiles, ret...)
- return ret, productConfigBp2BuildDirFiles, nil
-}
-
-// Get the output directory and create it if it doesn't exist.
-func getOrCreateOutputDir(outputDir android.OutputPath, ctx android.PathContext, dir string) android.OutputPath {
- dirPath := outputDir.Join(ctx, dir)
- if err := android.CreateOutputDirIfNonexistent(dirPath, os.ModePerm); err != nil {
- fmt.Printf("ERROR: path %s: %s", dirPath, err.Error())
- }
- return dirPath
-}
-
-// writeFiles materializes a list of BazelFile rooted at outputDir.
-func writeFiles(ctx android.PathContext, outputDir android.OutputPath, files []BazelFile) {
- for _, f := range files {
- p := getOrCreateOutputDir(outputDir, ctx, f.Dir).Join(ctx, f.Basename)
- if err := writeFile(p, f.Contents); err != nil {
- panic(fmt.Errorf("Failed to write %q (dir %q) due to %q", f.Basename, f.Dir, err))
- }
- }
-}
-
-func writeFile(pathToFile android.OutputPath, content string) error {
- // These files are made editable to allow users to modify and iterate on them
- // in the source tree.
- return android.WriteFileToOutputDir(pathToFile, []byte(content), 0644)
-}
diff --git a/bp2build/bp2build_product_config.go b/bp2build/bp2build_product_config.go
deleted file mode 100644
index 20355d7..0000000
--- a/bp2build/bp2build_product_config.go
+++ /dev/null
@@ -1,421 +0,0 @@
-package bp2build
-
-import (
- "encoding/json"
- "fmt"
- "os"
- "path/filepath"
- "reflect"
- "strings"
-
- "android/soong/android"
- "android/soong/android/soongconfig"
- "android/soong/starlark_import"
-
- "github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
- "go.starlark.net/starlark"
-)
-
-func CreateProductConfigFiles(
- ctx *CodegenContext,
- metrics CodegenMetrics) ([]BazelFile, []BazelFile, error) {
- cfg := &ctx.config
- targetProduct := "unknown"
- if cfg.HasDeviceProduct() {
- targetProduct = cfg.DeviceProduct()
- }
- targetBuildVariant := "user"
- if cfg.Eng() {
- targetBuildVariant = "eng"
- } else if cfg.Debuggable() {
- targetBuildVariant = "userdebug"
- }
-
- productVariablesFileName := cfg.ProductVariablesFileName
- if !strings.HasPrefix(productVariablesFileName, "/") {
- productVariablesFileName = filepath.Join(ctx.topDir, productVariablesFileName)
- }
- productVariablesBytes, err := os.ReadFile(productVariablesFileName)
- if err != nil {
- return nil, nil, err
- }
- productVariables := android.ProductVariables{}
- err = json.Unmarshal(productVariablesBytes, &productVariables)
- if err != nil {
- return nil, nil, err
- }
-
- // Visit all modules to determine the list of ndk libraries
- // This list will be used to add additional flags for cc stub generation
- ndkLibsStringFormatted := []string{}
- ctx.Context().VisitAllModules(func(m blueprint.Module) {
- if ctx.Context().ModuleType(m) == "ndk_library" {
- ndkLibsStringFormatted = append(ndkLibsStringFormatted, fmt.Sprintf(`"%s"`, m.Name())) // name will be `"libc.ndk"`
- }
- })
-
- // TODO(b/249685973): the name is product_config_platforms because product_config
- // was already used for other files. Deduplicate them.
- currentProductFolder := fmt.Sprintf("product_config_platforms/products/%s-%s", targetProduct, targetBuildVariant)
-
- productReplacer := strings.NewReplacer(
- "{PRODUCT}", targetProduct,
- "{VARIANT}", targetBuildVariant,
- "{PRODUCT_FOLDER}", currentProductFolder)
-
- platformMappingContent, err := platformMappingContent(
- productReplacer.Replace("@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}"),
- &productVariables,
- ctx.Config().Bp2buildSoongConfigDefinitions,
- metrics.convertedModulePathMap)
- if err != nil {
- return nil, nil, err
- }
-
- productsForTestingMap, err := starlark_import.GetStarlarkValue[map[string]map[string]starlark.Value]("products_for_testing")
- if err != nil {
- return nil, nil, err
- }
- productsForTesting := android.SortedKeys(productsForTestingMap)
- for i := range productsForTesting {
- productsForTesting[i] = fmt.Sprintf(" \"@//build/bazel/tests/products:%s\",", productsForTesting[i])
- }
-
- injectionDirFiles := []BazelFile{
- newFile(
- currentProductFolder,
- "soong.variables.bzl",
- `variables = json.decode("""`+strings.ReplaceAll(string(productVariablesBytes), "\\", "\\\\")+`""")`),
- newFile(
- currentProductFolder,
- "BUILD",
- productReplacer.Replace(`
-package(default_visibility=[
- "@soong_injection//product_config_platforms:__subpackages__",
- "@//build/bazel/product_config:__subpackages__",
-])
-load(":soong.variables.bzl", _soong_variables = "variables")
-load("@//build/bazel/product_config:android_product.bzl", "android_product")
-
-android_product(
- name = "{PRODUCT}-{VARIANT}",
- soong_variables = _soong_variables,
-)
-`)),
- newFile(
- "product_config_platforms",
- "BUILD.bazel",
- productReplacer.Replace(`
-package(default_visibility = [
- "@//build/bazel/product_config:__subpackages__",
- "@soong_injection//product_config_platforms:__subpackages__",
-])
-
-load("//{PRODUCT_FOLDER}:soong.variables.bzl", _soong_variables = "variables")
-load("@//build/bazel/product_config:android_product.bzl", "android_product")
-
-# Bazel will qualify its outputs by the platform name. When switching between products, this
-# means that soong-built files that depend on bazel-built files will suddenly get different
-# dependency files, because the path changes, and they will be rebuilt. In order to avoid this
-# extra rebuilding, make mixed builds always use a single platform so that the bazel artifacts
-# are always under the same path.
-android_product(
- name = "mixed_builds_product-{VARIANT}",
- soong_variables = _soong_variables,
- extra_constraints = ["@//build/bazel/platforms:mixed_builds"],
-)
-`)),
- newFile(
- "product_config_platforms",
- "product_labels.bzl",
- productReplacer.Replace(`
-# This file keeps a list of all the products in the android source tree, because they're
-# discovered as part of a preprocessing step before bazel runs.
-# TODO: When we start generating the platforms for more than just the
-# currently lunched product, they should all be listed here
-product_labels = [
- "@soong_injection//product_config_platforms:mixed_builds_product-{VARIANT}",
- "@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}",
-`)+strings.Join(productsForTesting, "\n")+"\n]\n"),
- newFile(
- "product_config_platforms",
- "common.bazelrc",
- productReplacer.Replace(`
-build --platform_mappings=platform_mappings
-build --platforms @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
-
-build:android --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}
-build:linux_x86 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86
-build:linux_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
-build:linux_bionic_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_bionic_x86_64
-build:linux_musl_x86 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_musl_x86
-build:linux_musl_x86_64 --platforms=@soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_musl_x86_64
-`)),
- newFile(
- "product_config_platforms",
- "linux.bazelrc",
- productReplacer.Replace(`
-build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_linux_x86_64
-`)),
- newFile(
- "product_config_platforms",
- "darwin.bazelrc",
- productReplacer.Replace(`
-build --host_platform @soong_injection//{PRODUCT_FOLDER}:{PRODUCT}-{VARIANT}_darwin_x86_64
-`)),
- newFile(
- "cc_toolchain",
- "ndk_libs.bzl",
- fmt.Sprintf("ndk_libs = [%v]", strings.Join(ndkLibsStringFormatted, ", ")),
- ),
- }
- bp2buildDirFiles := []BazelFile{
- newFile(
- "",
- "platform_mappings",
- platformMappingContent),
- }
- return injectionDirFiles, bp2buildDirFiles, nil
-}
-
-func platformMappingContent(
- mainProductLabel string,
- mainProductVariables *android.ProductVariables,
- soongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions,
- convertedModulePathMap map[string]string) (string, error) {
- productsForTesting, err := starlark_import.GetStarlarkValue[map[string]map[string]starlark.Value]("products_for_testing")
- if err != nil {
- return "", err
- }
- var result strings.Builder
-
- mergedConvertedModulePathMap := make(map[string]string)
- for k, v := range convertedModulePathMap {
- mergedConvertedModulePathMap[k] = v
- }
- additionalModuleNamesToPackages, err := starlark_import.GetStarlarkValue[map[string]string]("additional_module_names_to_packages")
- if err != nil {
- return "", err
- }
- for k, v := range additionalModuleNamesToPackages {
- mergedConvertedModulePathMap[k] = v
- }
-
- result.WriteString("platforms:\n")
- platformMappingSingleProduct(mainProductLabel, mainProductVariables, soongConfigDefinitions, mergedConvertedModulePathMap, &result)
- for product, productVariablesStarlark := range productsForTesting {
- productVariables, err := starlarkMapToProductVariables(productVariablesStarlark)
- if err != nil {
- return "", err
- }
- platformMappingSingleProduct("@//build/bazel/tests/products:"+product, &productVariables, soongConfigDefinitions, mergedConvertedModulePathMap, &result)
- }
- return result.String(), nil
-}
-
-var bazelPlatformSuffixes = []string{
- "",
- "_darwin_arm64",
- "_darwin_x86_64",
- "_linux_bionic_arm64",
- "_linux_bionic_x86_64",
- "_linux_musl_x86",
- "_linux_musl_x86_64",
- "_linux_x86",
- "_linux_x86_64",
- "_windows_x86",
- "_windows_x86_64",
-}
-
-func platformMappingSingleProduct(
- label string,
- productVariables *android.ProductVariables,
- soongConfigDefinitions soongconfig.Bp2BuildSoongConfigDefinitions,
- convertedModulePathMap map[string]string,
- result *strings.Builder) {
- targetBuildVariant := "user"
- if proptools.Bool(productVariables.Eng) {
- targetBuildVariant = "eng"
- } else if proptools.Bool(productVariables.Debuggable) {
- targetBuildVariant = "userdebug"
- }
-
- platform_sdk_version := -1
- if productVariables.Platform_sdk_version != nil {
- platform_sdk_version = *productVariables.Platform_sdk_version
- }
-
- defaultAppCertificateFilegroup := "//build/bazel/utils:empty_filegroup"
- if proptools.String(productVariables.DefaultAppCertificate) != "" {
- defaultAppCertificateFilegroup = "@//" + filepath.Dir(proptools.String(productVariables.DefaultAppCertificate)) + ":android_certificate_directory"
- }
-
- for _, suffix := range bazelPlatformSuffixes {
- result.WriteString(" ")
- result.WriteString(label)
- result.WriteString(suffix)
- result.WriteString("\n")
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:always_use_prebuilt_sdks=%t\n", proptools.Bool(productVariables.Always_use_prebuilt_sdks)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:arc=%t\n", proptools.Bool(productVariables.Arc)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:apex_global_min_sdk_version_override=%s\n", proptools.String(productVariables.ApexGlobalMinSdkVersionOverride)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:binder32bit=%t\n", proptools.Bool(productVariables.Binder32bit)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:build_from_text_stub=%t\n", proptools.Bool(productVariables.Build_from_text_stub)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:build_broken_incorrect_partition_images=%t\n", productVariables.BuildBrokenIncorrectPartitionImages))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:build_id=%s\n", proptools.String(productVariables.BuildId)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:build_version_tags=%s\n", strings.Join(productVariables.BuildVersionTags, ",")))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:cfi_exclude_paths=%s\n", strings.Join(productVariables.CFIExcludePaths, ",")))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:cfi_include_paths=%s\n", strings.Join(productVariables.CFIIncludePaths, ",")))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:compressed_apex=%t\n", proptools.Bool(productVariables.CompressedApex)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:debuggable=%t\n", proptools.Bool(productVariables.Debuggable)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:default_app_certificate=%s\n", proptools.String(productVariables.DefaultAppCertificate)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:default_app_certificate_filegroup=%s\n", defaultAppCertificateFilegroup))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_abi=%s\n", strings.Join(productVariables.DeviceAbi, ",")))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_max_page_size_supported=%s\n", proptools.String(productVariables.DeviceMaxPageSizeSupported)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_name=%s\n", proptools.String(productVariables.DeviceName)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_page_size_agnostic=%t\n", proptools.Bool(productVariables.DevicePageSizeAgnostic)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_product=%s\n", proptools.String(productVariables.DeviceProduct)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:device_platform=%s\n", label))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:enable_cfi=%t\n", proptools.BoolDefault(productVariables.EnableCFI, true)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:enforce_vintf_manifest=%t\n", proptools.Bool(productVariables.Enforce_vintf_manifest)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:eng=%t\n", proptools.Bool(productVariables.Eng)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:malloc_not_svelte=%t\n", proptools.Bool(productVariables.Malloc_not_svelte)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:malloc_pattern_fill_contents=%t\n", proptools.Bool(productVariables.Malloc_pattern_fill_contents)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:malloc_zero_contents=%t\n", proptools.Bool(productVariables.Malloc_zero_contents)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:memtag_heap_exclude_paths=%s\n", strings.Join(productVariables.MemtagHeapExcludePaths, ",")))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:memtag_heap_async_include_paths=%s\n", strings.Join(productVariables.MemtagHeapAsyncIncludePaths, ",")))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:memtag_heap_sync_include_paths=%s\n", strings.Join(productVariables.MemtagHeapSyncIncludePaths, ",")))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:manifest_package_name_overrides=%s\n", strings.Join(productVariables.ManifestPackageNameOverrides, ",")))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:native_coverage=%t\n", proptools.Bool(productVariables.Native_coverage)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:platform_version_name=%s\n", proptools.String(productVariables.Platform_version_name)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:product_brand=%s\n", productVariables.ProductBrand))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:product_manufacturer=%s\n", productVariables.ProductManufacturer))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:platform_sdk_version=%d\n", platform_sdk_version))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:safestack=%t\n", proptools.Bool(productVariables.Safestack)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:target_build_variant=%s\n", targetBuildVariant))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:treble_linker_namespaces=%t\n", proptools.Bool(productVariables.Treble_linker_namespaces)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:tidy_checks=%s\n", proptools.String(productVariables.TidyChecks)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:uml=%t\n", proptools.Bool(productVariables.Uml)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:unbundled_build=%t\n", proptools.Bool(productVariables.Unbundled_build)))
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config:unbundled_build_apps=%s\n", strings.Join(productVariables.Unbundled_build_apps, ",")))
-
- for _, override := range productVariables.CertificateOverrides {
- parts := strings.SplitN(override, ":", 2)
- if apexPath, ok := convertedModulePathMap[parts[0]]; ok {
- if overrideCertPath, ok := convertedModulePathMap[parts[1]]; ok {
- result.WriteString(fmt.Sprintf(" --%s:%s_certificate_override=%s:%s\n", apexPath, parts[0], overrideCertPath, parts[1]))
- }
- }
- }
-
- for namespace, namespaceContents := range productVariables.VendorVars {
- for variable, value := range namespaceContents {
- key := namespace + "__" + variable
- _, hasBool := soongConfigDefinitions.BoolVars[key]
- _, hasString := soongConfigDefinitions.StringVars[key]
- _, hasValue := soongConfigDefinitions.ValueVars[key]
- if !hasBool && !hasString && !hasValue {
- // Not all soong config variables are defined in Android.bp files. For example,
- // prebuilt_bootclasspath_fragment uses soong config variables in a nonstandard
- // way, that causes them to be present in the soong.variables file but not
- // defined in an Android.bp file. There's also nothing stopping you from setting
- // a variable in make that doesn't exist in soong. We only generate build
- // settings for the ones that exist in soong, so skip all others.
- continue
- }
- if hasBool && hasString || hasBool && hasValue || hasString && hasValue {
- panic(fmt.Sprintf("Soong config variable %s:%s appears to be of multiple types. bool? %t, string? %t, value? %t", namespace, variable, hasBool, hasString, hasValue))
- }
- if hasBool {
- // Logic copied from soongConfig.Bool()
- value = strings.ToLower(value)
- if value == "1" || value == "y" || value == "yes" || value == "on" || value == "true" {
- value = "true"
- } else {
- value = "false"
- }
- }
- result.WriteString(fmt.Sprintf(" --//build/bazel/product_config/soong_config_variables:%s=%s\n", strings.ToLower(key), value))
- }
- }
- }
-}
-
-func starlarkMapToProductVariables(in map[string]starlark.Value) (android.ProductVariables, error) {
- result := android.ProductVariables{}
- productVarsReflect := reflect.ValueOf(&result).Elem()
- for i := 0; i < productVarsReflect.NumField(); i++ {
- field := productVarsReflect.Field(i)
- fieldType := productVarsReflect.Type().Field(i)
- name := fieldType.Name
- if name == "BootJars" || name == "ApexBootJars" || name == "VendorSnapshotModules" ||
- name == "RecoverySnapshotModules" {
- // These variables have more complicated types, and we don't need them right now
- continue
- }
- if _, ok := in[name]; ok {
- if name == "VendorVars" {
- vendorVars, err := starlark_import.Unmarshal[map[string]map[string]string](in[name])
- if err != nil {
- return result, err
- }
- field.Set(reflect.ValueOf(vendorVars))
- continue
- }
- switch field.Type().Kind() {
- case reflect.Bool:
- val, err := starlark_import.Unmarshal[bool](in[name])
- if err != nil {
- return result, err
- }
- field.SetBool(val)
- case reflect.String:
- val, err := starlark_import.Unmarshal[string](in[name])
- if err != nil {
- return result, err
- }
- field.SetString(val)
- case reflect.Slice:
- if field.Type().Elem().Kind() != reflect.String {
- return result, fmt.Errorf("slices of types other than strings are unimplemented")
- }
- val, err := starlark_import.UnmarshalReflect(in[name], field.Type())
- if err != nil {
- return result, err
- }
- field.Set(val)
- case reflect.Pointer:
- switch field.Type().Elem().Kind() {
- case reflect.Bool:
- val, err := starlark_import.UnmarshalNoneable[bool](in[name])
- if err != nil {
- return result, err
- }
- field.Set(reflect.ValueOf(val))
- case reflect.String:
- val, err := starlark_import.UnmarshalNoneable[string](in[name])
- if err != nil {
- return result, err
- }
- field.Set(reflect.ValueOf(val))
- case reflect.Int:
- val, err := starlark_import.UnmarshalNoneable[int](in[name])
- if err != nil {
- return result, err
- }
- field.Set(reflect.ValueOf(val))
- default:
- return result, fmt.Errorf("pointers of types other than strings/bools are unimplemented: %s", field.Type().Elem().Kind().String())
- }
- default:
- return result, fmt.Errorf("unimplemented type: %s", field.Type().String())
- }
- }
- }
-
- result.Native_coverage = proptools.BoolPtr(
- proptools.Bool(result.GcovCoverage) ||
- proptools.Bool(result.ClangCoverage))
-
- return result, nil
-}
diff --git a/bp2build/bp2build_product_config_test.go b/bp2build/bp2build_product_config_test.go
deleted file mode 100644
index 02d83b4..0000000
--- a/bp2build/bp2build_product_config_test.go
+++ /dev/null
@@ -1,89 +0,0 @@
-package bp2build
-
-import (
- "android/soong/android"
- "android/soong/starlark_import"
- "encoding/json"
- "reflect"
- "testing"
-
- "github.com/google/blueprint/proptools"
- "go.starlark.net/starlark"
-)
-
-func createStarlarkValue(t *testing.T, code string) starlark.Value {
- t.Helper()
- result, err := starlark.ExecFile(&starlark.Thread{}, "main.bzl", "x = "+code, nil)
- if err != nil {
- t.Error(err)
- }
- return result["x"]
-}
-
-func createStarlarkProductVariablesMap(t *testing.T, code string) map[string]starlark.Value {
- t.Helper()
- rawValue := createStarlarkValue(t, code)
- value, err := starlark_import.Unmarshal[map[string]starlark.Value](rawValue)
- if err != nil {
- t.Error(err)
- }
- return value
-}
-
-func TestStarlarkMapToProductVariables(t *testing.T) {
- thirty := 30
- cases := []struct {
- starlark string
- result android.ProductVariables
- }{
- {
- starlark: `{"CompressedApex": True}`,
- result: android.ProductVariables{CompressedApex: proptools.BoolPtr(true)},
- },
- {
- starlark: `{"ApexGlobalMinSdkVersionOverride": "Tiramisu"}`,
- result: android.ProductVariables{ApexGlobalMinSdkVersionOverride: proptools.StringPtr("Tiramisu")},
- },
- {
- starlark: `{"ProductManufacturer": "Google"}`,
- result: android.ProductVariables{ProductManufacturer: "Google"},
- },
- {
- starlark: `{"Unbundled_build_apps": ["app1", "app2"]}`,
- result: android.ProductVariables{Unbundled_build_apps: []string{"app1", "app2"}},
- },
- {
- starlark: `{"Platform_sdk_version": 30}`,
- result: android.ProductVariables{Platform_sdk_version: &thirty},
- },
- {
- starlark: `{"HostFakeSnapshotEnabled": True}`,
- result: android.ProductVariables{HostFakeSnapshotEnabled: true},
- },
- }
-
- for _, testCase := range cases {
- productVariables, err := starlarkMapToProductVariables(createStarlarkProductVariablesMap(t,
- testCase.starlark))
- if err != nil {
- t.Error(err)
- continue
- }
- testCase.result.Native_coverage = proptools.BoolPtr(false)
- if !reflect.DeepEqual(testCase.result, productVariables) {
- expected, err := json.Marshal(testCase.result)
- if err != nil {
- t.Error(err)
- continue
- }
- actual, err := json.Marshal(productVariables)
- if err != nil {
- t.Error(err)
- continue
- }
- expectedStr := string(expected)
- actualStr := string(actual)
- t.Errorf("expected %q, but got %q", expectedStr, actualStr)
- }
- }
-}
diff --git a/bp2build/bpf_conversion_test.go b/bp2build/bpf_conversion_test.go
deleted file mode 100644
index 1259f9e..0000000
--- a/bp2build/bpf_conversion_test.go
+++ /dev/null
@@ -1,65 +0,0 @@
-// 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 (
- "android/soong/android"
- "android/soong/bpf"
-
- "testing"
-)
-
-func runBpfTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "bpf"
- (&tc).ModuleTypeUnderTestFactory = bpf.BpfFactory
- RunBp2BuildTestCase(t, registerBpfModuleTypes, tc)
-}
-
-func registerBpfModuleTypes(ctx android.RegistrationContext) {}
-
-func TestBpfSupportedAttrs(t *testing.T) {
- runBpfTestCase(t, Bp2buildTestCase{
- Description: "Bpf module only converts supported attributes",
- Filesystem: map[string]string{},
- Blueprint: `
-bpf {
- name: "bpfTestOut.o",
- srcs: ["bpfTestSrcOne.c",
- "bpfTestSrcTwo.c"],
- btf: true,
- cflags: ["-bpfCflagOne",
- "-bpfCflagTwo"],
- include_dirs: ["ia/ib/ic"],
- sub_dir: "sa/ab",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("bpf", "bpfTestOut.o", AttrNameToString{
- "absolute_includes": `["ia/ib/ic"]`,
- "btf": `True`,
- "copts": `[
- "-bpfCflagOne",
- "-bpfCflagTwo",
- ]`,
- "srcs": `[
- "bpfTestSrcOne.c",
- "bpfTestSrcTwo.c",
- ]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- }),
- },
- })
-}
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index 9060363..bd56768 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -28,10 +28,7 @@
"android/soong/android"
"android/soong/bazel"
"android/soong/starlark_fmt"
- "android/soong/ui/metrics/bp2build_metrics_proto"
-
"github.com/google/blueprint"
- "github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/proptools"
)
@@ -39,18 +36,24 @@
Attrs map[string]string
}
-type BazelTarget struct {
- name string
- packageName string
- content string
- ruleClass string
- bzlLoadLocation string
+type BazelLoadSymbol struct {
+ // The name of the symbol in the file being loaded
+ symbol string
+ // The name the symbol wil have in this file. Can be left blank to use the same name as symbol.
+ alias string
}
-// IsLoadedFromStarlark determines if the BazelTarget's rule class is loaded from a .bzl file,
-// as opposed to a native rule built into Bazel.
-func (t BazelTarget) IsLoadedFromStarlark() bool {
- return t.bzlLoadLocation != ""
+type BazelLoad struct {
+ file string
+ symbols []BazelLoadSymbol
+}
+
+type BazelTarget struct {
+ name string
+ packageName string
+ content string
+ ruleClass string
+ loads []BazelLoad
}
// Label is the fully qualified Bazel label constructed from the BazelTarget's
@@ -110,30 +113,62 @@
// LoadStatements return the string representation of the sorted and deduplicated
// Starlark rule load statements needed by a group of BazelTargets.
func (targets BazelTargets) LoadStatements() string {
- bzlToLoadedSymbols := map[string][]string{}
+ // First, merge all the load statements from all the targets onto one list
+ bzlToLoadedSymbols := map[string][]BazelLoadSymbol{}
for _, target := range targets {
- if target.IsLoadedFromStarlark() {
- bzlToLoadedSymbols[target.bzlLoadLocation] =
- append(bzlToLoadedSymbols[target.bzlLoadLocation], target.ruleClass)
+ for _, load := range target.loads {
+ outer:
+ for _, symbol := range load.symbols {
+ alias := symbol.alias
+ if alias == "" {
+ alias = symbol.symbol
+ }
+ for _, otherSymbol := range bzlToLoadedSymbols[load.file] {
+ otherAlias := otherSymbol.alias
+ if otherAlias == "" {
+ otherAlias = otherSymbol.symbol
+ }
+ if symbol.symbol == otherSymbol.symbol && alias == otherAlias {
+ continue outer
+ } else if alias == otherAlias {
+ panic(fmt.Sprintf("Conflicting destination (%s) for loads of %s and %s", alias, symbol.symbol, otherSymbol.symbol))
+ }
+ }
+ bzlToLoadedSymbols[load.file] = append(bzlToLoadedSymbols[load.file], symbol)
+ }
}
}
- var loadStatements []string
- for bzl, ruleClasses := range bzlToLoadedSymbols {
- loadStatement := "load(\""
- loadStatement += bzl
- loadStatement += "\", "
- ruleClasses = android.SortedUniqueStrings(ruleClasses)
- for i, ruleClass := range ruleClasses {
- loadStatement += "\"" + ruleClass + "\""
- if i != len(ruleClasses)-1 {
- loadStatement += ", "
+ var loadStatements strings.Builder
+ for i, bzl := range android.SortedKeys(bzlToLoadedSymbols) {
+ symbols := bzlToLoadedSymbols[bzl]
+ loadStatements.WriteString("load(\"")
+ loadStatements.WriteString(bzl)
+ loadStatements.WriteString("\", ")
+ sort.Slice(symbols, func(i, j int) bool {
+ if symbols[i].symbol < symbols[j].symbol {
+ return true
+ }
+ return symbols[i].alias < symbols[j].alias
+ })
+ for j, symbol := range symbols {
+ if symbol.alias != "" && symbol.alias != symbol.symbol {
+ loadStatements.WriteString(symbol.alias)
+ loadStatements.WriteString(" = ")
+ }
+ loadStatements.WriteString("\"")
+ loadStatements.WriteString(symbol.symbol)
+ loadStatements.WriteString("\"")
+ if j != len(symbols)-1 {
+ loadStatements.WriteString(", ")
}
}
- loadStatement += ")"
- loadStatements = append(loadStatements, loadStatement)
+ loadStatements.WriteString(")")
+ if i != len(bzlToLoadedSymbols)-1 {
+ loadStatements.WriteString("\n")
+ }
}
- return strings.Join(android.SortedUniqueStrings(loadStatements), "\n")
+ return loadStatements.String()
}
type bpToBuildContext interface {
@@ -163,18 +198,13 @@
type CodegenMode int
const (
- // Bp2Build - generate BUILD files with targets buildable by Bazel directly.
- //
- // This mode is used for the Soong->Bazel build definition conversion.
- Bp2Build CodegenMode = iota
-
// QueryView - generate BUILD files with targets representing fully mutated
// Soong modules, representing the fully configured Soong module graph with
// variants and dependency edges.
//
// This mode is used for discovering and introspecting the existing Soong
// module graph.
- QueryView
+ QueryView CodegenMode = iota
)
type unconvertedDepsMode int
@@ -189,8 +219,6 @@
func (mode CodegenMode) String() string {
switch mode {
- case Bp2Build:
- return "Bp2Build"
case QueryView:
return "QueryView"
default:
@@ -218,9 +246,6 @@
// writing BUILD files in the output directory.
func NewCodegenContext(config android.Config, context *android.Context, mode CodegenMode, topDir string) *CodegenContext {
var unconvertedDeps unconvertedDepsMode
- if config.IsEnvTrue("BP2BUILD_ERROR_UNCONVERTED") {
- unconvertedDeps = errorModulesUnconvertedDeps
- }
return &CodegenContext{
context: context,
config: config,
@@ -241,522 +266,32 @@
}
type conversionResults struct {
- buildFileToTargets map[string]BazelTargets
- metrics CodegenMetrics
+ buildFileToTargets map[string]BazelTargets
+ moduleNameToPartition map[string]string
}
func (r conversionResults) BuildDirToTargets() map[string]BazelTargets {
return r.buildFileToTargets
}
-// struct to store state of go bazel targets
-// this implements bp2buildModule interface and is passed to generateBazelTargets
-type goBazelTarget struct {
- targetName string
- targetPackage string
- bazelRuleClass string
- bazelRuleLoadLocation string
- bazelAttributes []interface{}
-}
-
-var _ bp2buildModule = (*goBazelTarget)(nil)
-
-func (g goBazelTarget) TargetName() string {
- return g.targetName
-}
-
-func (g goBazelTarget) TargetPackage() string {
- return g.targetPackage
-}
-
-func (g goBazelTarget) BazelRuleClass() string {
- return g.bazelRuleClass
-}
-
-func (g goBazelTarget) BazelRuleLoadLocation() string {
- return g.bazelRuleLoadLocation
-}
-
-func (g goBazelTarget) BazelAttributes() []interface{} {
- return g.bazelAttributes
-}
-
-// Creates a target_compatible_with entry that is *not* compatible with android
-func targetNotCompatibleWithAndroid() bazel.LabelListAttribute {
- ret := bazel.LabelListAttribute{}
- ret.SetSelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid,
- bazel.MakeLabelList(
- []bazel.Label{
- bazel.Label{
- Label: "@platforms//:incompatible",
- },
- },
- ),
- )
- return ret
-}
-
-// helper function to return labels for srcs used in bootstrap_go_package and bootstrap_go_binary
-// this function has the following limitations which make it unsuitable for widespread use
-// - wildcard patterns in srcs
-// This is ok for go since build/blueprint does not support it.
-//
-// Prefer to use `BazelLabelForModuleSrc` instead
-func goSrcLabels(cfg android.Config, moduleDir string, srcs []string, linuxSrcs, darwinSrcs []string) bazel.LabelListAttribute {
- labels := func(srcs []string) bazel.LabelList {
- ret := []bazel.Label{}
- for _, src := range srcs {
- srcLabel := bazel.Label{
- Label: src,
- }
- ret = append(ret, srcLabel)
- }
- // Respect package boundaries
- return android.TransformSubpackagePaths(
- cfg,
- moduleDir,
- bazel.MakeLabelList(ret),
- )
- }
-
- ret := bazel.LabelListAttribute{}
- // common
- ret.SetSelectValue(bazel.NoConfigAxis, "", labels(srcs))
- // linux
- ret.SetSelectValue(bazel.OsConfigurationAxis, bazel.OsLinux, labels(linuxSrcs))
- // darwin
- ret.SetSelectValue(bazel.OsConfigurationAxis, bazel.OsDarwin, labels(darwinSrcs))
- return ret
-}
-
-func goDepLabels(deps []string, goModulesMap nameToGoLibraryModule) bazel.LabelListAttribute {
- labels := []bazel.Label{}
- for _, dep := range deps {
- moduleDir := goModulesMap[dep].Dir
- if moduleDir == "." {
- moduleDir = ""
- }
- label := bazel.Label{
- Label: fmt.Sprintf("//%s:%s", moduleDir, dep),
- }
- labels = append(labels, label)
- }
- return bazel.MakeLabelListAttribute(bazel.MakeLabelList(labels))
-}
-
-// attributes common to blueprint_go_binary and bootstap_go_package
-type goAttributes struct {
- Importpath bazel.StringAttribute
- Srcs bazel.LabelListAttribute
- Deps bazel.LabelListAttribute
- Data bazel.LabelListAttribute
- Target_compatible_with bazel.LabelListAttribute
-
- // attributes for the dynamically generated go_test target
- Embed bazel.LabelListAttribute
-}
-
-type goTestProperties struct {
- name string
- dir string
- testSrcs []string
- linuxTestSrcs []string
- darwinTestSrcs []string
- testData []string
- // Name of the target that should be compiled together with the test
- embedName string
-}
-
-// Creates a go_test target for bootstrap_go_package / blueprint_go_binary
-func generateBazelTargetsGoTest(ctx *android.Context, goModulesMap nameToGoLibraryModule, gp goTestProperties) (BazelTarget, error) {
- ca := android.CommonAttributes{
- Name: gp.name,
- }
- ga := goAttributes{
- Srcs: goSrcLabels(ctx.Config(), gp.dir, gp.testSrcs, gp.linuxTestSrcs, gp.darwinTestSrcs),
- Data: goSrcLabels(ctx.Config(), gp.dir, gp.testData, []string{}, []string{}),
- Embed: bazel.MakeLabelListAttribute(
- bazel.MakeLabelList(
- []bazel.Label{bazel.Label{Label: ":" + gp.embedName}},
- ),
- ),
- Target_compatible_with: targetNotCompatibleWithAndroid(),
- }
-
- libTest := goBazelTarget{
- targetName: gp.name,
- targetPackage: gp.dir,
- bazelRuleClass: "go_test",
- bazelRuleLoadLocation: "@io_bazel_rules_go//go:def.bzl",
- bazelAttributes: []interface{}{&ca, &ga},
- }
- return generateBazelTarget(ctx, libTest)
-}
-
-// TODO - b/288491147: testSrcs of certain bootstrap_go_package/blueprint_go_binary are not hermetic and depend on
-// testdata checked into the filesystem.
-// Denylist the generation of go_test targets for these Soong modules.
-// The go_library/go_binary will still be generated, since those are hermitic.
-var (
- goTestsDenylist = []string{
- "android-archive-zip",
- "bazel_notice_gen",
- "blueprint-bootstrap-bpdoc",
- "blueprint-microfactory",
- "blueprint-pathtools",
- "bssl_ar",
- "compliance_checkmetadata",
- "compliance_checkshare",
- "compliance_dumpgraph",
- "compliance_dumpresolutions",
- "compliance_listshare",
- "compliance-module",
- "compliancenotice_bom",
- "compliancenotice_shippedlibs",
- "compliance_rtrace",
- "compliance_sbom",
- "golang-protobuf-internal-fuzz-jsonfuzz",
- "golang-protobuf-internal-fuzz-textfuzz",
- "golang-protobuf-internal-fuzz-wirefuzz",
- "htmlnotice",
- "protoc-gen-go",
- "rbcrun-module",
- "spdx-tools-builder",
- "spdx-tools-builder2v1",
- "spdx-tools-builder2v2",
- "spdx-tools-builder2v3",
- "spdx-tools-idsearcher",
- "spdx-tools-spdx-json",
- "spdx-tools-utils",
- "soong-ui-build",
- "textnotice",
- "xmlnotice",
- }
-)
-
-func testOfGoPackageIsIncompatible(g *bootstrap.GoPackage) bool {
- return android.InList(g.Name(), goTestsDenylist) ||
- // Denylist tests of soong_build
- // Theses tests have a guard that prevent usage outside a test environment
- // The guard (`ensureTestOnly`) looks for a `-test` in os.Args, which is present in soong's gotestrunner, but missing in `b test`
- g.IsPluginFor("soong_build") ||
- // soong-android is a dep of soong_build
- // This dependency is created by soong_build by listing it in its deps explicitly in Android.bp, and not via `plugin_for` in `soong-android`
- g.Name() == "soong-android"
-}
-
-func testOfGoBinaryIsIncompatible(g *bootstrap.GoBinary) bool {
- return android.InList(g.Name(), goTestsDenylist)
-}
-
-func generateBazelTargetsGoPackage(ctx *android.Context, g *bootstrap.GoPackage, goModulesMap nameToGoLibraryModule) ([]BazelTarget, []error) {
- ca := android.CommonAttributes{
- Name: g.Name(),
- }
-
- // For this bootstrap_go_package dep chain,
- // A --> B --> C ( ---> depends on)
- // Soong provides the convenience of only listing B as deps of A even if a src file of A imports C
- // Bazel OTOH
- // 1. requires C to be listed in `deps` expllicity.
- // 2. does not require C to be listed if src of A does not import C
- //
- // bp2build does not have sufficient info on whether C is a direct dep of A or not, so for now collect all transitive deps and add them to deps
- transitiveDeps := transitiveGoDeps(g.Deps(), goModulesMap)
-
- ga := goAttributes{
- Importpath: bazel.StringAttribute{
- Value: proptools.StringPtr(g.GoPkgPath()),
- },
- Srcs: goSrcLabels(ctx.Config(), ctx.ModuleDir(g), g.Srcs(), g.LinuxSrcs(), g.DarwinSrcs()),
- Deps: goDepLabels(
- android.FirstUniqueStrings(transitiveDeps),
- goModulesMap,
- ),
- Target_compatible_with: targetNotCompatibleWithAndroid(),
- }
-
- lib := goBazelTarget{
- targetName: g.Name(),
- targetPackage: ctx.ModuleDir(g),
- bazelRuleClass: "go_library",
- bazelRuleLoadLocation: "@io_bazel_rules_go//go:def.bzl",
- bazelAttributes: []interface{}{&ca, &ga},
- }
- retTargets := []BazelTarget{}
- var retErrs []error
- if libTarget, err := generateBazelTarget(ctx, lib); err == nil {
- retTargets = append(retTargets, libTarget)
- } else {
- retErrs = []error{err}
- }
-
- // If the library contains test srcs, create an additional go_test target
- if !testOfGoPackageIsIncompatible(g) && (len(g.TestSrcs()) > 0 || len(g.LinuxTestSrcs()) > 0 || len(g.DarwinTestSrcs()) > 0) {
- gp := goTestProperties{
- name: g.Name() + "-test",
- dir: ctx.ModuleDir(g),
- testSrcs: g.TestSrcs(),
- linuxTestSrcs: g.LinuxTestSrcs(),
- darwinTestSrcs: g.DarwinTestSrcs(),
- testData: g.TestData(),
- embedName: g.Name(), // embed the source go_library in the test so that its .go files are included in the compilation unit
- }
- if libTestTarget, err := generateBazelTargetsGoTest(ctx, goModulesMap, gp); err == nil {
- retTargets = append(retTargets, libTestTarget)
- } else {
- retErrs = append(retErrs, err)
- }
- }
-
- return retTargets, retErrs
-}
-
-type goLibraryModule struct {
- Dir string
- Deps []string
-}
-
-type nameToGoLibraryModule map[string]goLibraryModule
-
-// Visit each module in the graph
-// If a module is of type `bootstrap_go_package`, return a map containing metadata like its dir and deps
-func createGoLibraryModuleMap(ctx *android.Context) nameToGoLibraryModule {
- ret := nameToGoLibraryModule{}
- ctx.VisitAllModules(func(m blueprint.Module) {
- moduleType := ctx.ModuleType(m)
- // We do not need to store information about blueprint_go_binary since it does not have any rdeps
- if moduleType == "bootstrap_go_package" {
- ret[m.Name()] = goLibraryModule{
- Dir: ctx.ModuleDir(m),
- Deps: m.(*bootstrap.GoPackage).Deps(),
- }
- }
- })
- return ret
-}
-
-// Returns the deps in the transitive closure of a go target
-func transitiveGoDeps(directDeps []string, goModulesMap nameToGoLibraryModule) []string {
- allDeps := directDeps
- i := 0
- for i < len(allDeps) {
- curr := allDeps[i]
- allDeps = append(allDeps, goModulesMap[curr].Deps...)
- i += 1
- }
- allDeps = android.SortedUniqueStrings(allDeps)
- return allDeps
-}
-
-func generateBazelTargetsGoBinary(ctx *android.Context, g *bootstrap.GoBinary, goModulesMap nameToGoLibraryModule) ([]BazelTarget, []error) {
- ca := android.CommonAttributes{
- Name: g.Name(),
- }
-
- retTargets := []BazelTarget{}
- var retErrs []error
-
- // For this bootstrap_go_package dep chain,
- // A --> B --> C ( ---> depends on)
- // Soong provides the convenience of only listing B as deps of A even if a src file of A imports C
- // Bazel OTOH
- // 1. requires C to be listed in `deps` expllicity.
- // 2. does not require C to be listed if src of A does not import C
- //
- // bp2build does not have sufficient info on whether C is a direct dep of A or not, so for now collect all transitive deps and add them to deps
- transitiveDeps := transitiveGoDeps(g.Deps(), goModulesMap)
-
- goSource := ""
- // If the library contains test srcs, create an additional go_test target
- // The go_test target will embed a go_source containining the source .go files it tests
- if !testOfGoBinaryIsIncompatible(g) && (len(g.TestSrcs()) > 0 || len(g.LinuxTestSrcs()) > 0 || len(g.DarwinTestSrcs()) > 0) {
- // Create a go_source containing the source .go files of go_library
- // This target will be an `embed` of the go_binary and go_test
- goSource = g.Name() + "-source"
- ca := android.CommonAttributes{
- Name: goSource,
- }
- ga := goAttributes{
- Srcs: goSrcLabels(ctx.Config(), ctx.ModuleDir(g), g.Srcs(), g.LinuxSrcs(), g.DarwinSrcs()),
- Deps: goDepLabels(transitiveDeps, goModulesMap),
- Target_compatible_with: targetNotCompatibleWithAndroid(),
- }
- libTestSource := goBazelTarget{
- targetName: goSource,
- targetPackage: ctx.ModuleDir(g),
- bazelRuleClass: "go_source",
- bazelRuleLoadLocation: "@io_bazel_rules_go//go:def.bzl",
- bazelAttributes: []interface{}{&ca, &ga},
- }
- if libSourceTarget, err := generateBazelTarget(ctx, libTestSource); err == nil {
- retTargets = append(retTargets, libSourceTarget)
- } else {
- retErrs = append(retErrs, err)
- }
-
- // Create a go_test target
- gp := goTestProperties{
- name: g.Name() + "-test",
- dir: ctx.ModuleDir(g),
- testSrcs: g.TestSrcs(),
- linuxTestSrcs: g.LinuxTestSrcs(),
- darwinTestSrcs: g.DarwinTestSrcs(),
- testData: g.TestData(),
- // embed the go_source in the test
- embedName: g.Name() + "-source",
- }
- if libTestTarget, err := generateBazelTargetsGoTest(ctx, goModulesMap, gp); err == nil {
- retTargets = append(retTargets, libTestTarget)
- } else {
- retErrs = append(retErrs, err)
- }
-
- }
-
- // Create a go_binary target
- ga := goAttributes{
- Deps: goDepLabels(transitiveDeps, goModulesMap),
- Target_compatible_with: targetNotCompatibleWithAndroid(),
- }
-
- // If the binary has testSrcs, embed the common `go_source`
- if goSource != "" {
- ga.Embed = bazel.MakeLabelListAttribute(
- bazel.MakeLabelList(
- []bazel.Label{bazel.Label{Label: ":" + goSource}},
- ),
- )
- } else {
- ga.Srcs = goSrcLabels(ctx.Config(), ctx.ModuleDir(g), g.Srcs(), g.LinuxSrcs(), g.DarwinSrcs())
- }
-
- bin := goBazelTarget{
- targetName: g.Name(),
- targetPackage: ctx.ModuleDir(g),
- bazelRuleClass: "go_binary",
- bazelRuleLoadLocation: "@io_bazel_rules_go//go:def.bzl",
- bazelAttributes: []interface{}{&ca, &ga},
- }
-
- if binTarget, err := generateBazelTarget(ctx, bin); err == nil {
- retTargets = append(retTargets, binTarget)
- } else {
- retErrs = []error{err}
- }
-
- return retTargets, retErrs
-}
-
func GenerateBazelTargets(ctx *CodegenContext, generateFilegroups bool) (conversionResults, []error) {
ctx.Context().BeginEvent("GenerateBazelTargets")
defer ctx.Context().EndEvent("GenerateBazelTargets")
buildFileToTargets := make(map[string]BazelTargets)
- // Simple metrics tracking for bp2build
- metrics := CreateCodegenMetrics()
-
dirs := make(map[string]bool)
+ moduleNameToPartition := make(map[string]string)
var errs []error
- // Visit go libraries in a pre-run and store its state in a map
- // The time complexity remains O(N), and this does not add significant wall time.
- nameToGoLibMap := createGoLibraryModuleMap(ctx.Context())
-
bpCtx := ctx.Context()
bpCtx.VisitAllModules(func(m blueprint.Module) {
dir := bpCtx.ModuleDir(m)
- moduleType := bpCtx.ModuleType(m)
dirs[dir] = true
var targets []BazelTarget
- var targetErrs []error
switch ctx.Mode() {
- case Bp2Build:
- // There are two main ways of converting a Soong module to Bazel:
- // 1) Manually handcrafting a Bazel target and associating the module with its label
- // 2) Automatically generating with bp2build converters
- //
- // bp2build converters are used for the majority of modules.
- if b, ok := m.(android.Bazelable); ok && b.HasHandcraftedLabel() {
- if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() {
- panic(fmt.Errorf("module %q [%s] [%s] was both converted with bp2build and has a handcrafted label", bpCtx.ModuleName(m), moduleType, dir))
- }
- // Handle modules converted to handcrafted targets.
- //
- // Since these modules are associated with some handcrafted
- // target in a BUILD file, we don't autoconvert them.
-
- // Log the module.
- metrics.AddUnconvertedModule(m, moduleType, dir,
- android.UnconvertedReason{
- ReasonType: int(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE),
- })
- } else if aModule, ok := m.(android.Module); ok && aModule.IsConvertedByBp2build() {
- // Handle modules converted to generated targets.
-
- // Log the module.
- metrics.AddConvertedModule(aModule, moduleType, dir)
-
- // Handle modules with unconverted deps. By default, emit a warning.
- if unconvertedDeps := aModule.GetUnconvertedBp2buildDeps(); len(unconvertedDeps) > 0 {
- msg := fmt.Sprintf("%s %s:%s depends on unconverted modules: %s",
- moduleType, bpCtx.ModuleDir(m), m.Name(), strings.Join(unconvertedDeps, ", "))
- switch ctx.unconvertedDepMode {
- case warnUnconvertedDeps:
- metrics.moduleWithUnconvertedDepsMsgs = append(metrics.moduleWithUnconvertedDepsMsgs, msg)
- case errorModulesUnconvertedDeps:
- errs = append(errs, fmt.Errorf(msg))
- return
- }
- }
- if unconvertedDeps := aModule.GetMissingBp2buildDeps(); len(unconvertedDeps) > 0 {
- msg := fmt.Sprintf("%s %s:%s depends on missing modules: %s",
- moduleType, bpCtx.ModuleDir(m), m.Name(), strings.Join(unconvertedDeps, ", "))
- switch ctx.unconvertedDepMode {
- case warnUnconvertedDeps:
- metrics.moduleWithMissingDepsMsgs = append(metrics.moduleWithMissingDepsMsgs, msg)
- case errorModulesUnconvertedDeps:
- errs = append(errs, fmt.Errorf(msg))
- return
- }
- }
- targets, targetErrs = generateBazelTargets(bpCtx, aModule)
- errs = append(errs, targetErrs...)
- for _, t := range targets {
- // A module can potentially generate more than 1 Bazel
- // target, each of a different rule class.
- metrics.IncrementRuleClassCount(t.ruleClass)
- }
- } else if _, ok := ctx.Config().BazelModulesForceEnabledByFlag()[m.Name()]; ok && m.Name() != "" {
- err := fmt.Errorf("Force Enabled Module %s not converted", m.Name())
- errs = append(errs, err)
- } else if aModule, ok := m.(android.Module); ok {
- reason := aModule.GetUnconvertedReason()
- if reason == nil {
- panic(fmt.Errorf("module '%s' was neither converted nor marked unconvertible with bp2build", aModule.Name()))
- } else {
- metrics.AddUnconvertedModule(m, moduleType, dir, *reason)
- }
- return
- } else if glib, ok := m.(*bootstrap.GoPackage); ok {
- targets, targetErrs = generateBazelTargetsGoPackage(bpCtx, glib, nameToGoLibMap)
- errs = append(errs, targetErrs...)
- metrics.IncrementRuleClassCount("go_library")
- metrics.AddConvertedModule(glib, "go_library", dir)
- } else if gbin, ok := m.(*bootstrap.GoBinary); ok {
- targets, targetErrs = generateBazelTargetsGoBinary(bpCtx, gbin, nameToGoLibMap)
- errs = append(errs, targetErrs...)
- metrics.IncrementRuleClassCount("go_binary")
- metrics.AddConvertedModule(gbin, "go_binary", dir)
- } else {
- metrics.AddUnconvertedModule(m, moduleType, dir, android.UnconvertedReason{
- ReasonType: int(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED),
- })
- return
- }
case QueryView:
// Blocklist certain module types from being generated.
if canonicalizeModuleType(bpCtx.ModuleType(m)) == "package" {
@@ -799,73 +334,18 @@
for dir := range dirs {
buildFileToTargets[dir] = append(buildFileToTargets[dir], BazelTarget{
name: "bp2build_all_srcs",
- content: `filegroup(name = "bp2build_all_srcs", srcs = glob(["**/*"]))`,
+ content: `filegroup(name = "bp2build_all_srcs", srcs = glob(["**/*"]), tags = ["manual"])`,
ruleClass: "filegroup",
})
}
}
return conversionResults{
- buildFileToTargets: buildFileToTargets,
- metrics: metrics,
+ buildFileToTargets: buildFileToTargets,
+ moduleNameToPartition: moduleNameToPartition,
}, errs
}
-func generateBazelTargets(ctx bpToBuildContext, m android.Module) ([]BazelTarget, []error) {
- var targets []BazelTarget
- var errs []error
- for _, m := range m.Bp2buildTargets() {
- target, err := generateBazelTarget(ctx, m)
- if err != nil {
- errs = append(errs, err)
- return targets, errs
- }
- targets = append(targets, target)
- }
- return targets, errs
-}
-
-type bp2buildModule interface {
- TargetName() string
- TargetPackage() string
- BazelRuleClass() string
- BazelRuleLoadLocation() string
- BazelAttributes() []interface{}
-}
-
-func generateBazelTarget(ctx bpToBuildContext, m bp2buildModule) (BazelTarget, error) {
- ruleClass := m.BazelRuleClass()
- bzlLoadLocation := m.BazelRuleLoadLocation()
-
- // extract the bazel attributes from the module.
- attrs := m.BazelAttributes()
- props, err := extractModuleProperties(attrs, true)
- if err != nil {
- return BazelTarget{}, err
- }
-
- // name is handled in a special manner
- delete(props.Attrs, "name")
-
- // Return the Bazel target with rule class and attributes, ready to be
- // code-generated.
- attributes := propsToAttributes(props.Attrs)
- var content string
- targetName := m.TargetName()
- if targetName != "" {
- content = fmt.Sprintf(ruleTargetTemplate, ruleClass, targetName, attributes)
- } else {
- content = fmt.Sprintf(unnamedRuleTargetTemplate, ruleClass, attributes)
- }
- return BazelTarget{
- name: targetName,
- packageName: m.TargetPackage(),
- ruleClass: ruleClass,
- bzlLoadLocation: bzlLoadLocation,
- content: content,
- }, nil
-}
-
// Convert a module and its deps and props into a Bazel macro/rule
// representation in the BUILD file.
func generateSoongModuleTarget(ctx bpToBuildContext, m blueprint.Module) (BazelTarget, error) {
@@ -966,7 +446,7 @@
if !emitZeroValues && isZero(propertyValue) {
// A property value being set or unset actually matters -- Soong does set default
// values for unset properties, like system_shared_libs = ["libc", "libm", "libdl"] at
- // https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=281-287;drc=f70926eef0b9b57faf04c17a1062ce50d209e480
+ // https://cs.android.com/android/platform/superproject/+/main:build/soong/cc/linker.go;l=281-287;drc=f70926eef0b9b57faf04c17a1062ce50d209e480
//
// In Bazel-parlance, we would use "attr.<type>(default = <default
// value>)" to set the default value of unset attributes. In the cases
diff --git a/bp2build/build_conversion_test.go b/bp2build/build_conversion_test.go
deleted file mode 100644
index 3887c5d..0000000
--- a/bp2build/build_conversion_test.go
+++ /dev/null
@@ -1,1970 +0,0 @@
-// Copyright 2020 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"
- "strings"
- "testing"
-
- "android/soong/android"
- "android/soong/android/allowlists"
- "android/soong/bazel"
- "android/soong/python"
-)
-
-func TestGenerateSoongModuleTargets(t *testing.T) {
- testCases := []struct {
- description string
- bp string
- expectedBazelTarget string
- }{
- {
- description: "only name",
- bp: `custom { name: "foo" }
- `,
- expectedBazelTarget: `soong_module(
- name = "foo",
- soong_module_name = "foo",
- soong_module_type = "custom",
- soong_module_variant = "",
- soong_module_deps = [
- ],
- bool_prop = False,
- string_prop = "",
-)`,
- },
- {
- description: "handles bool",
- bp: `custom {
- name: "foo",
- bool_prop: true,
-}
- `,
- expectedBazelTarget: `soong_module(
- name = "foo",
- soong_module_name = "foo",
- soong_module_type = "custom",
- soong_module_variant = "",
- soong_module_deps = [
- ],
- bool_prop = True,
- string_prop = "",
-)`,
- },
- {
- description: "string escaping",
- bp: `custom {
- name: "foo",
- owner: "a_string_with\"quotes\"_and_\\backslashes\\\\",
-}
- `,
- expectedBazelTarget: `soong_module(
- name = "foo",
- soong_module_name = "foo",
- soong_module_type = "custom",
- soong_module_variant = "",
- soong_module_deps = [
- ],
- bool_prop = False,
- owner = "a_string_with\"quotes\"_and_\\backslashes\\\\",
- string_prop = "",
-)`,
- },
- {
- description: "single item string list",
- bp: `custom {
- name: "foo",
- required: ["bar"],
-}
- `,
- expectedBazelTarget: `soong_module(
- name = "foo",
- soong_module_name = "foo",
- soong_module_type = "custom",
- soong_module_variant = "",
- soong_module_deps = [
- ],
- bool_prop = False,
- required = ["bar"],
- string_prop = "",
-)`,
- },
- {
- description: "list of strings",
- bp: `custom {
- name: "foo",
- target_required: ["qux", "bazqux"],
-}
- `,
- expectedBazelTarget: `soong_module(
- name = "foo",
- soong_module_name = "foo",
- soong_module_type = "custom",
- soong_module_variant = "",
- soong_module_deps = [
- ],
- bool_prop = False,
- string_prop = "",
- target_required = [
- "qux",
- "bazqux",
- ],
-)`,
- },
- {
- description: "dist/dists",
- bp: `custom {
- name: "foo",
- dist: {
- targets: ["goal_foo"],
- tag: ".foo",
- },
- dists: [{
- targets: ["goal_bar"],
- tag: ".bar",
- }],
-}
- `,
- expectedBazelTarget: `soong_module(
- name = "foo",
- soong_module_name = "foo",
- soong_module_type = "custom",
- soong_module_variant = "",
- soong_module_deps = [
- ],
- bool_prop = False,
- dist = {
- "tag": ".foo",
- "targets": ["goal_foo"],
- },
- dists = [{
- "tag": ".bar",
- "targets": ["goal_bar"],
- }],
- string_prop = "",
-)`,
- },
- {
- description: "put it together",
- bp: `custom {
- name: "foo",
- required: ["bar"],
- target_required: ["qux", "bazqux"],
- bool_prop: true,
- owner: "custom_owner",
- dists: [
- {
- tag: ".tag",
- targets: ["my_goal"],
- },
- ],
-}
- `,
- expectedBazelTarget: `soong_module(
- name = "foo",
- soong_module_name = "foo",
- soong_module_type = "custom",
- soong_module_variant = "",
- soong_module_deps = [
- ],
- bool_prop = True,
- dists = [{
- "tag": ".tag",
- "targets": ["my_goal"],
- }],
- owner = "custom_owner",
- required = ["bar"],
- string_prop = "",
- target_required = [
- "qux",
- "bazqux",
- ],
-)`,
- },
- }
-
- dir := "."
- for _, testCase := range testCases {
- t.Run(testCase.description, func(t *testing.T) {
- config := android.TestConfig(buildDir, nil, testCase.bp, nil)
- ctx := android.NewTestContext(config)
-
- ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
- ctx.Register()
-
- _, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.PrepareBuildActions(config)
- android.FailIfErrored(t, errs)
-
- codegenCtx := NewCodegenContext(config, ctx.Context, QueryView, "")
- bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
- android.FailIfErrored(t, err)
- if actualCount, expectedCount := len(bazelTargets), 1; actualCount != expectedCount {
- t.Fatalf("Expected %d bazel target, got %d", expectedCount, actualCount)
- }
-
- actualBazelTarget := bazelTargets[0]
- if actualBazelTarget.content != testCase.expectedBazelTarget {
- t.Errorf(
- "Expected generated Bazel target to be '%s', got '%s'",
- testCase.expectedBazelTarget,
- actualBazelTarget.content,
- )
- }
- })
- }
-}
-
-func TestGenerateBazelTargetModules(t *testing.T) {
- testCases := []Bp2buildTestCase{
- {
- Description: "string prop empty",
- Blueprint: `custom {
- name: "foo",
- string_literal_prop: "",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("custom", "foo", AttrNameToString{
- "string_literal_prop": `""`,
- }),
- },
- },
- {
- Description: `string prop "PROP"`,
- Blueprint: `custom {
- name: "foo",
- string_literal_prop: "PROP",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("custom", "foo", AttrNameToString{
- "string_literal_prop": `"PROP"`,
- }),
- },
- },
- {
- Description: `string prop arch variant`,
- Blueprint: `custom {
- name: "foo",
- arch: {
- arm: { string_literal_prop: "ARM" },
- arm64: { string_literal_prop: "ARM64" },
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("custom", "foo", AttrNameToString{
- "string_literal_prop": `select({
- "//build/bazel/platforms/arch:arm": "ARM",
- "//build/bazel/platforms/arch:arm64": "ARM64",
- "//conditions:default": None,
- })`,
- }),
- },
- },
- {
- Description: "string ptr props",
- Blueprint: `custom {
- name: "foo",
- string_ptr_prop: "",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("custom", "foo", AttrNameToString{
- "string_ptr_prop": `""`,
- }),
- },
- },
- {
- Description: "string list props",
- Blueprint: `custom {
- name: "foo",
- string_list_prop: ["a", "b"],
- string_ptr_prop: "a",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("custom", "foo", AttrNameToString{
- "string_list_prop": `[
- "a",
- "b",
- ]`,
- "string_ptr_prop": `"a"`,
- }),
- },
- },
- {
- Description: "control characters",
- Blueprint: `custom {
- name: "foo",
- string_list_prop: ["\t", "\n"],
- string_ptr_prop: "a\t\n\r",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("custom", "foo", AttrNameToString{
- "string_list_prop": `[
- "\t",
- "\n",
- ]`,
- "string_ptr_prop": `"a\t\n\r"`,
- }),
- },
- },
- {
- Description: "handles dep",
- Blueprint: `custom {
- name: "has_dep",
- arch_paths: [":dep"],
- bazel_module: { bp2build_available: true },
-}
-
-custom {
- name: "dep",
- arch_paths: ["abc"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("custom", "dep", AttrNameToString{
- "arch_paths": `["abc"]`,
- }),
- MakeBazelTarget("custom", "has_dep", AttrNameToString{
- "arch_paths": `[":dep"]`,
- }),
- },
- },
- {
- Description: "non-existent dep",
- Blueprint: `custom {
- name: "has_dep",
- arch_paths: [":dep"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("custom", "has_dep", AttrNameToString{
- "arch_paths": `[":dep__BP2BUILD__MISSING__DEP"]`,
- }),
- },
- },
- {
- Description: "arch-variant srcs",
- Blueprint: `custom {
- name: "arch_paths",
- arch: {
- x86: { arch_paths: ["x86.txt"] },
- x86_64: { arch_paths: ["x86_64.txt"] },
- arm: { arch_paths: ["arm.txt"] },
- arm64: { arch_paths: ["arm64.txt"] },
- riscv64: { arch_paths: ["riscv64.txt"] },
- },
- target: {
- linux: { arch_paths: ["linux.txt"] },
- bionic: { arch_paths: ["bionic.txt"] },
- host: { arch_paths: ["host.txt"] },
- not_windows: { arch_paths: ["not_windows.txt"] },
- android: { arch_paths: ["android.txt"] },
- linux_musl: { arch_paths: ["linux_musl.txt"] },
- musl: { arch_paths: ["musl.txt"] },
- linux_glibc: { arch_paths: ["linux_glibc.txt"] },
- glibc: { arch_paths: ["glibc.txt"] },
- linux_bionic: { arch_paths: ["linux_bionic.txt"] },
- darwin: { arch_paths: ["darwin.txt"] },
- windows: { arch_paths: ["windows.txt"] },
- },
- multilib: {
- lib32: { arch_paths: ["lib32.txt"] },
- lib64: { arch_paths: ["lib64.txt"] },
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("custom", "arch_paths", AttrNameToString{
- "arch_paths": `select({
- "//build/bazel/platforms/arch:arm": [
- "arm.txt",
- "lib32.txt",
- ],
- "//build/bazel/platforms/arch:arm64": [
- "arm64.txt",
- "lib64.txt",
- ],
- "//build/bazel/platforms/arch:riscv64": [
- "riscv64.txt",
- "lib64.txt",
- ],
- "//build/bazel/platforms/arch:x86": [
- "x86.txt",
- "lib32.txt",
- ],
- "//build/bazel/platforms/arch:x86_64": [
- "x86_64.txt",
- "lib64.txt",
- ],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os:android": [
- "linux.txt",
- "bionic.txt",
- "android.txt",
- ],
- "//build/bazel/platforms/os:darwin": [
- "host.txt",
- "darwin.txt",
- "not_windows.txt",
- ],
- "//build/bazel/platforms/os:linux_bionic": [
- "host.txt",
- "linux.txt",
- "bionic.txt",
- "linux_bionic.txt",
- "not_windows.txt",
- ],
- "//build/bazel/platforms/os:linux_glibc": [
- "host.txt",
- "linux.txt",
- "glibc.txt",
- "linux_glibc.txt",
- "not_windows.txt",
- ],
- "//build/bazel/platforms/os:linux_musl": [
- "host.txt",
- "linux.txt",
- "musl.txt",
- "linux_musl.txt",
- "not_windows.txt",
- ],
- "//build/bazel/platforms/os:windows": [
- "host.txt",
- "windows.txt",
- ],
- "//conditions:default": [],
- })`,
- }),
- },
- },
- {
- Description: "arch-variant deps",
- Blueprint: `custom {
- name: "has_dep",
- arch: {
- x86: {
- arch_paths: [":dep"],
- },
- },
- bazel_module: { bp2build_available: true },
-}
-
-custom {
- name: "dep",
- arch_paths: ["abc"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("custom", "dep", AttrNameToString{
- "arch_paths": `["abc"]`,
- }),
- MakeBazelTarget("custom", "has_dep", AttrNameToString{
- "arch_paths": `select({
- "//build/bazel/platforms/arch:x86": [":dep"],
- "//conditions:default": [],
- })`,
- }),
- },
- },
- {
- Description: "embedded props",
- Blueprint: `custom {
- name: "embedded_props",
- embedded_prop: "abc",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("custom", "embedded_props", AttrNameToString{
- "embedded_attr": `"abc"`,
- }),
- },
- },
- {
- Description: "ptr to embedded props",
- Blueprint: `custom {
- name: "ptr_to_embedded_props",
- other_embedded_prop: "abc",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("custom", "ptr_to_embedded_props", AttrNameToString{
- "other_embedded_attr": `"abc"`,
- }),
- },
- },
- }
-
- dir := "."
- for _, testCase := range testCases {
- t.Run(testCase.Description, func(t *testing.T) {
- config := android.TestConfig(buildDir, nil, testCase.Blueprint, nil)
- ctx := android.NewTestContext(config)
-
- registerCustomModuleForBp2buildConversion(ctx)
-
- _, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
- if errored(t, testCase, errs) {
- return
- }
- _, errs = ctx.ResolveDependencies(config)
- if errored(t, testCase, errs) {
- return
- }
-
- codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
- bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
- android.FailIfErrored(t, err)
-
- if actualCount, expectedCount := len(bazelTargets), len(testCase.ExpectedBazelTargets); actualCount != expectedCount {
- t.Errorf("Expected %d bazel target (%s),\ngot %d (%s)", expectedCount, testCase.ExpectedBazelTargets, actualCount, bazelTargets)
- } else {
- for i, expectedBazelTarget := range testCase.ExpectedBazelTargets {
- actualBazelTarget := bazelTargets[i]
- if actualBazelTarget.content != expectedBazelTarget {
- t.Errorf(
- "Expected generated Bazel target to be '%s', got '%s'",
- expectedBazelTarget,
- actualBazelTarget.content,
- )
- }
- }
- }
- })
- }
-}
-
-func TestBp2buildHostAndDevice(t *testing.T) {
- testCases := []Bp2buildTestCase{
- {
- Description: "host and device, device only",
- ModuleTypeUnderTest: "custom",
- ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
- Blueprint: `custom {
- name: "foo",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.DeviceSupported),
- },
- },
- {
- Description: "host and device, both",
- ModuleTypeUnderTest: "custom",
- ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
- Blueprint: `custom {
- name: "foo",
- host_supported: true,
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{}),
- },
- },
- {
- Description: "host and device, host explicitly disabled",
- ModuleTypeUnderTest: "custom",
- ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
- Blueprint: `custom {
- name: "foo",
- host_supported: false,
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.DeviceSupported),
- },
- },
- {
- Description: "host and device, neither",
- ModuleTypeUnderTest: "custom",
- ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
- Blueprint: `custom {
- name: "foo",
- host_supported: false,
- device_supported: false,
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{
- "target_compatible_with": `["@platforms//:incompatible"]`,
- }),
- },
- },
- {
- Description: "host and device, neither, cannot override with product_var",
- ModuleTypeUnderTest: "custom",
- ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
- Blueprint: `custom {
- name: "foo",
- host_supported: false,
- device_supported: false,
- product_variables: { unbundled_build: { enabled: true } },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{
- "target_compatible_with": `["@platforms//:incompatible"]`,
- }),
- },
- },
- {
- Description: "host and device, both, disabled overrided with product_var",
- ModuleTypeUnderTest: "custom",
- ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
- Blueprint: `custom {
- name: "foo",
- host_supported: true,
- device_supported: true,
- enabled: false,
- product_variables: { unbundled_build: { enabled: true } },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{
- "target_compatible_with": `select({
- "//build/bazel/product_config/config_settings:unbundled_build": [],
- "//conditions:default": ["@platforms//:incompatible"],
- })`,
- }),
- },
- },
- {
- Description: "host and device, neither, cannot override with arch enabled",
- ModuleTypeUnderTest: "custom",
- ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
- Blueprint: `custom {
- name: "foo",
- host_supported: false,
- device_supported: false,
- arch: { x86: { enabled: true } },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{
- "target_compatible_with": `["@platforms//:incompatible"]`,
- }),
- },
- },
- {
- Description: "host and device, host only",
- ModuleTypeUnderTest: "custom",
- ModuleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
- Blueprint: `custom {
- name: "foo",
- host_supported: true,
- device_supported: false,
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.HostSupported),
- },
- },
- {
- Description: "host only",
- ModuleTypeUnderTest: "custom",
- ModuleTypeUnderTestFactory: customModuleFactoryHostSupported,
- Blueprint: `custom {
- name: "foo",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.HostSupported),
- },
- },
- {
- Description: "device only",
- ModuleTypeUnderTest: "custom",
- ModuleTypeUnderTestFactory: customModuleFactoryDeviceSupported,
- Blueprint: `custom {
- name: "foo",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.DeviceSupported),
- },
- },
- {
- Description: "host and device default, default",
- ModuleTypeUnderTest: "custom",
- ModuleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault,
- Blueprint: `custom {
- name: "foo",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{}),
- },
- },
- {
- Description: "host and device default, device only",
- ModuleTypeUnderTest: "custom",
- ModuleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault,
- Blueprint: `custom {
- name: "foo",
- host_supported: false,
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.DeviceSupported),
- },
- },
- {
- Description: "host and device default, host only",
- ModuleTypeUnderTest: "custom",
- ModuleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault,
- Blueprint: `custom {
- name: "foo",
- device_supported: false,
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- makeBazelTargetHostOrDevice("custom", "foo", AttrNameToString{}, android.HostSupported),
- },
- },
- {
- Description: "host and device default, neither",
- ModuleTypeUnderTest: "custom",
- ModuleTypeUnderTestFactory: customModuleFactoryHostAndDeviceDefault,
- Blueprint: `custom {
- name: "foo",
- host_supported: false,
- device_supported: false,
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("custom", "foo", AttrNameToString{
- "target_compatible_with": `["@platforms//:incompatible"]`,
- }),
- },
- },
- }
-
- for _, tc := range testCases {
- t.Run(tc.Description, func(t *testing.T) {
- RunBp2BuildTestCaseSimple(t, tc)
- })
- }
-}
-
-func TestLoadStatements(t *testing.T) {
- testCases := []struct {
- bazelTargets BazelTargets
- expectedLoadStatements string
- }{
- {
- bazelTargets: BazelTargets{
- BazelTarget{
- name: "foo",
- ruleClass: "cc_library",
- bzlLoadLocation: "//build/bazel/rules:cc.bzl",
- },
- },
- expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`,
- },
- {
- bazelTargets: BazelTargets{
- BazelTarget{
- name: "foo",
- ruleClass: "cc_library",
- bzlLoadLocation: "//build/bazel/rules:cc.bzl",
- },
- BazelTarget{
- name: "bar",
- ruleClass: "cc_library",
- bzlLoadLocation: "//build/bazel/rules:cc.bzl",
- },
- },
- expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_library")`,
- },
- {
- bazelTargets: BazelTargets{
- BazelTarget{
- name: "foo",
- ruleClass: "cc_library",
- bzlLoadLocation: "//build/bazel/rules:cc.bzl",
- },
- BazelTarget{
- name: "bar",
- ruleClass: "cc_binary",
- bzlLoadLocation: "//build/bazel/rules:cc.bzl",
- },
- },
- expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library")`,
- },
- {
- bazelTargets: BazelTargets{
- BazelTarget{
- name: "foo",
- ruleClass: "cc_library",
- bzlLoadLocation: "//build/bazel/rules:cc.bzl",
- },
- BazelTarget{
- name: "bar",
- ruleClass: "cc_binary",
- bzlLoadLocation: "//build/bazel/rules:cc.bzl",
- },
- BazelTarget{
- name: "baz",
- ruleClass: "java_binary",
- bzlLoadLocation: "//build/bazel/rules:java.bzl",
- },
- },
- expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary", "cc_library")
-load("//build/bazel/rules:java.bzl", "java_binary")`,
- },
- {
- bazelTargets: BazelTargets{
- BazelTarget{
- name: "foo",
- ruleClass: "cc_binary",
- bzlLoadLocation: "//build/bazel/rules:cc.bzl",
- },
- BazelTarget{
- name: "bar",
- ruleClass: "java_binary",
- bzlLoadLocation: "//build/bazel/rules:java.bzl",
- },
- BazelTarget{
- name: "baz",
- ruleClass: "genrule",
- // Note: no bzlLoadLocation for native rules
- },
- },
- expectedLoadStatements: `load("//build/bazel/rules:cc.bzl", "cc_binary")
-load("//build/bazel/rules:java.bzl", "java_binary")`,
- },
- }
-
- for _, testCase := range testCases {
- actual := testCase.bazelTargets.LoadStatements()
- expected := testCase.expectedLoadStatements
- if actual != expected {
- t.Fatalf("Expected load statements to be %s, got %s", expected, actual)
- }
- }
-
-}
-
-func TestGenerateBazelTargetModules_OneToMany_LoadedFromStarlark(t *testing.T) {
- testCases := []struct {
- bp string
- expectedBazelTarget string
- expectedBazelTargetCount int
- expectedLoadStatements string
- }{
- {
- bp: `custom {
- name: "bar",
- host_supported: true,
- one_to_many_prop: true,
- bazel_module: { bp2build_available: true },
-}`,
- expectedBazelTarget: `my_library(
- name = "bar",
-)
-
-proto_library(
- name = "bar_proto_library_deps",
-)
-
-my_proto_library(
- name = "bar_my_proto_library_deps",
-)`,
- expectedBazelTargetCount: 3,
- expectedLoadStatements: `load("//build/bazel/rules:proto.bzl", "my_proto_library", "proto_library")
-load("//build/bazel/rules:rules.bzl", "my_library")`,
- },
- }
-
- dir := "."
- for _, testCase := range testCases {
- config := android.TestConfig(buildDir, nil, testCase.bp, nil)
- ctx := android.NewTestContext(config)
- ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
- ctx.RegisterForBazelConversion()
-
- _, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.ResolveDependencies(config)
- android.FailIfErrored(t, errs)
-
- codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
- bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
- android.FailIfErrored(t, err)
- if actualCount := len(bazelTargets); actualCount != testCase.expectedBazelTargetCount {
- t.Fatalf("Expected %d bazel target, got %d", testCase.expectedBazelTargetCount, actualCount)
- }
-
- actualBazelTargets := bazelTargets.String()
- if actualBazelTargets != testCase.expectedBazelTarget {
- t.Errorf(
- "Expected generated Bazel target to be '%s', got '%s'",
- testCase.expectedBazelTarget,
- actualBazelTargets,
- )
- }
-
- actualLoadStatements := bazelTargets.LoadStatements()
- if actualLoadStatements != testCase.expectedLoadStatements {
- t.Errorf(
- "Expected generated load statements to be '%s', got '%s'",
- testCase.expectedLoadStatements,
- actualLoadStatements,
- )
- }
- }
-}
-
-func TestModuleTypeBp2Build(t *testing.T) {
- testCases := []Bp2buildTestCase{
- {
- Description: "filegroup with does not specify srcs",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: `filegroup {
- name: "fg_foo",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{}),
- },
- },
- {
- Description: "filegroup with no srcs",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: `filegroup {
- name: "fg_foo",
- srcs: [],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{}),
- },
- },
- {
- Description: "filegroup with srcs",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: `filegroup {
- name: "fg_foo",
- srcs: ["a", "b"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "a",
- "b",
- ]`,
- }),
- },
- },
- {
- Description: "filegroup with dot-slash-prefixed srcs",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: `filegroup {
- name: "fg_foo",
- srcs: ["./a", "./b"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "a",
- "b",
- ]`,
- }),
- },
- },
- {
- Description: "filegroup with excludes srcs",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: `filegroup {
- name: "fg_foo",
- srcs: ["a", "b"],
- exclude_srcs: ["a"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `["b"]`,
- }),
- },
- },
- {
- Description: "depends_on_other_dir_module",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: `filegroup {
- name: "fg_foo",
- srcs: [
- ":foo",
- "c",
- ],
- bazel_module: { bp2build_available: true },
-}`,
- Filesystem: map[string]string{
- "other/Android.bp": `filegroup {
- name: "foo",
- srcs: ["a", "b"],
- bazel_module: { bp2build_available: true },
-}`,
- },
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "//other:foo",
- "c",
- ]`,
- }),
- },
- },
- {
- Description: "depends_on_other_unconverted_module_error",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- UnconvertedDepsMode: errorModulesUnconvertedDeps,
- Blueprint: `filegroup {
- name: "foobar",
- srcs: [
- ":foo",
- "c",
- ],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedErr: fmt.Errorf(`filegroup .:foobar depends on unconverted modules: foo`),
- Filesystem: map[string]string{
- "other/Android.bp": `filegroup {
- name: "foo",
- srcs: ["a", "b"],
-}`,
- },
- },
- {
- Description: "depends_on_other_missing_module_error",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- UnconvertedDepsMode: errorModulesUnconvertedDeps,
- Blueprint: `filegroup {
- name: "foobar",
- srcs: [
- "c",
- "//other:foo",
- "//other:goo",
- ],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedErr: fmt.Errorf(`filegroup .:foobar depends on missing modules: //other:goo`),
- Filesystem: map[string]string{"other/Android.bp": `filegroup {
- name: "foo",
- srcs: ["a"],
- bazel_module: { bp2build_available: true },
-}
-`,
- },
- },
- }
-
- for _, testCase := range testCases {
- t.Run(testCase.Description, func(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, testCase)
- })
- }
-}
-
-func TestAllowlistingBp2buildTargetsExplicitly(t *testing.T) {
- testCases := []struct {
- moduleTypeUnderTest string
- moduleTypeUnderTestFactory android.ModuleFactory
- bp string
- expectedCount int
- description string
- }{
- {
- description: "explicitly unavailable",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- bp: `filegroup {
- name: "foo",
- srcs: ["a", "b"],
- bazel_module: { bp2build_available: false },
-}`,
- expectedCount: 0,
- },
- {
- description: "implicitly unavailable",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- bp: `filegroup {
- name: "foo",
- srcs: ["a", "b"],
-}`,
- expectedCount: 0,
- },
- {
- description: "explicitly available",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- bp: `filegroup {
- name: "foo",
- srcs: ["a", "b"],
- bazel_module: { bp2build_available: true },
-}`,
- expectedCount: 1,
- },
- {
- description: "generates more than 1 target if needed",
- moduleTypeUnderTest: "custom",
- moduleTypeUnderTestFactory: customModuleFactoryHostAndDevice,
- bp: `custom {
- name: "foo",
- one_to_many_prop: true,
- bazel_module: { bp2build_available: true },
-}`,
- expectedCount: 3,
- },
- }
-
- dir := "."
- for _, testCase := range testCases {
- t.Run(testCase.description, func(t *testing.T) {
- config := android.TestConfig(buildDir, nil, testCase.bp, nil)
- ctx := android.NewTestContext(config)
- ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
- ctx.RegisterForBazelConversion()
-
- _, errs := ctx.ParseFileList(dir, []string{"Android.bp"})
- android.FailIfErrored(t, errs)
- _, errs = ctx.ResolveDependencies(config)
- android.FailIfErrored(t, errs)
-
- codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
- bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
- android.FailIfErrored(t, err)
- if actualCount := len(bazelTargets); actualCount != testCase.expectedCount {
- t.Fatalf("%s: Expected %d bazel target, got %d", testCase.description, testCase.expectedCount, actualCount)
- }
- })
- }
-}
-
-func TestAllowlistingBp2buildTargetsWithConfig(t *testing.T) {
- testCases := []struct {
- moduleTypeUnderTest string
- moduleTypeUnderTestFactory android.ModuleFactory
- expectedCount map[string]int
- description string
- bp2buildConfig allowlists.Bp2BuildConfig
- checkDir string
- fs map[string]string
- forceEnabledModules []string
- expectedErrorMessages []string
- }{
- {
- description: "test bp2build config package and subpackages config",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- expectedCount: map[string]int{
- "migrated": 1,
- "migrated/but_not_really": 0,
- "migrated/but_not_really/but_really": 1,
- "not_migrated": 0,
- "also_not_migrated": 0,
- },
- bp2buildConfig: allowlists.Bp2BuildConfig{
- "migrated": allowlists.Bp2BuildDefaultTrueRecursively,
- "migrated/but_not_really": allowlists.Bp2BuildDefaultFalse,
- "not_migrated": allowlists.Bp2BuildDefaultFalse,
- },
- fs: map[string]string{
- "migrated/Android.bp": `filegroup { name: "a" }`,
- "migrated/but_not_really/Android.bp": `filegroup { name: "b" }`,
- "migrated/but_not_really/but_really/Android.bp": `filegroup { name: "c" }`,
- "not_migrated/Android.bp": `filegroup { name: "d" }`,
- "also_not_migrated/Android.bp": `filegroup { name: "e" }`,
- },
- },
- {
- description: "test bp2build config opt-in and opt-out",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- expectedCount: map[string]int{
- "package-opt-in": 2,
- "package-opt-in/subpackage": 0,
- "package-opt-out": 1,
- "package-opt-out/subpackage": 0,
- },
- bp2buildConfig: allowlists.Bp2BuildConfig{
- "package-opt-in": allowlists.Bp2BuildDefaultFalse,
- "package-opt-out": allowlists.Bp2BuildDefaultTrueRecursively,
- },
- fs: map[string]string{
- "package-opt-in/Android.bp": `
-filegroup { name: "opt-in-a" }
-filegroup { name: "opt-in-b", bazel_module: { bp2build_available: true } }
-filegroup { name: "opt-in-c", bazel_module: { bp2build_available: true } }
-`,
-
- "package-opt-in/subpackage/Android.bp": `
-filegroup { name: "opt-in-d" } // parent package not configured to DefaultTrueRecursively
-`,
-
- "package-opt-out/Android.bp": `
-filegroup { name: "opt-out-a" }
-filegroup { name: "opt-out-b", bazel_module: { bp2build_available: false } }
-filegroup { name: "opt-out-c", bazel_module: { bp2build_available: false } }
-`,
-
- "package-opt-out/subpackage/Android.bp": `
-filegroup { name: "opt-out-g", bazel_module: { bp2build_available: false } }
-filegroup { name: "opt-out-h", bazel_module: { bp2build_available: false } }
-`,
- },
- },
- {
- description: "test force-enabled errors out",
- moduleTypeUnderTest: "filegroup",
- moduleTypeUnderTestFactory: android.FileGroupFactory,
- expectedCount: map[string]int{
- "migrated": 0,
- "not_migrated": 0,
- },
- bp2buildConfig: allowlists.Bp2BuildConfig{
- "migrated/but_not_really": allowlists.Bp2BuildDefaultFalse,
- "not_migrated": allowlists.Bp2BuildDefaultFalse,
- },
- fs: map[string]string{
- "migrated/Android.bp": `filegroup { name: "a" }`,
- },
- forceEnabledModules: []string{"a"},
- expectedErrorMessages: []string{"Force Enabled Module a not converted"},
- },
- }
-
- dir := "."
- for _, testCase := range testCases {
- fs := make(map[string][]byte)
- toParse := []string{
- "Android.bp",
- }
- for f, content := range testCase.fs {
- if strings.HasSuffix(f, "Android.bp") {
- toParse = append(toParse, f)
- }
- fs[f] = []byte(content)
- }
- config := android.TestConfig(buildDir, nil, "", fs)
- config.AddForceEnabledModules(testCase.forceEnabledModules)
- ctx := android.NewTestContext(config)
- ctx.RegisterModuleType(testCase.moduleTypeUnderTest, testCase.moduleTypeUnderTestFactory)
- allowlist := android.NewBp2BuildAllowlist().SetDefaultConfig(testCase.bp2buildConfig)
- ctx.RegisterBp2BuildConfig(allowlist)
- ctx.RegisterForBazelConversion()
-
- _, errs := ctx.ParseFileList(dir, toParse)
- android.FailIfErrored(t, errs)
- _, errs = ctx.ResolveDependencies(config)
- android.FailIfErrored(t, errs)
-
- codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
-
- // For each directory, test that the expected number of generated targets is correct.
- for dir, expectedCount := range testCase.expectedCount {
- bazelTargets, err := generateBazelTargetsForDir(codegenCtx, dir)
- android.CheckErrorsAgainstExpectations(t, err, testCase.expectedErrorMessages)
- if actualCount := len(bazelTargets); actualCount != expectedCount {
- t.Fatalf(
- "%s: Expected %d bazel target for %s package, got %d",
- testCase.description,
- expectedCount,
- dir,
- actualCount)
- }
-
- }
- }
-}
-
-func TestCombineBuildFilesBp2buildTargets(t *testing.T) {
- testCases := []Bp2buildTestCase{
- {
- Description: "filegroup bazel_module.label",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: `filegroup {
- name: "fg_foo",
- bazel_module: { label: "//other:fg_foo" },
-}`,
- ExpectedBazelTargets: []string{},
- Filesystem: map[string]string{
- "other/BUILD.bazel": `// BUILD file`,
- },
- },
- {
- Description: "multiple bazel_module.label same BUILD",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: `filegroup {
- name: "fg_foo",
- bazel_module: { label: "//other:fg_foo" },
- }
-
- filegroup {
- name: "foo",
- bazel_module: { label: "//other:foo" },
- }`,
- ExpectedBazelTargets: []string{},
- Filesystem: map[string]string{
- "other/BUILD.bazel": `// BUILD file`,
- },
- },
- {
- Description: "filegroup bazel_module.label and bp2build in subdir",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Dir: "other",
- Blueprint: ``,
- Filesystem: map[string]string{
- "other/Android.bp": `filegroup {
- name: "fg_foo",
- bazel_module: {
- bp2build_available: true,
- },
- }
- filegroup {
- name: "fg_bar",
- bazel_module: {
- label: "//other:fg_bar"
- },
- }`,
- "other/BUILD.bazel": `// definition for fg_bar`,
- },
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{}),
- },
- },
- {
- Description: "filegroup bazel_module.label and filegroup bp2build",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
-
- Filesystem: map[string]string{
- "other/BUILD.bazel": `// BUILD file`,
- },
- Blueprint: `filegroup {
- name: "fg_foo",
- bazel_module: {
- label: "//other:fg_foo",
- },
- }
-
- filegroup {
- name: "fg_bar",
- bazel_module: {
- bp2build_available: true,
- },
- }`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_bar", map[string]string{}),
- },
- },
- }
-
- dir := "."
- for _, testCase := range testCases {
- t.Run(testCase.Description, func(t *testing.T) {
- fs := make(map[string][]byte)
- toParse := []string{
- "Android.bp",
- }
- for f, content := range testCase.Filesystem {
- if strings.HasSuffix(f, "Android.bp") {
- toParse = append(toParse, f)
- }
- fs[f] = []byte(content)
- }
- config := android.TestConfig(buildDir, nil, testCase.Blueprint, fs)
- ctx := android.NewTestContext(config)
- ctx.RegisterModuleType(testCase.ModuleTypeUnderTest, testCase.ModuleTypeUnderTestFactory)
- ctx.RegisterForBazelConversion()
-
- _, errs := ctx.ParseFileList(dir, toParse)
- if errored(t, testCase, errs) {
- return
- }
- _, errs = ctx.ResolveDependencies(config)
- if errored(t, testCase, errs) {
- return
- }
-
- checkDir := dir
- if testCase.Dir != "" {
- checkDir = testCase.Dir
- }
- codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
- bazelTargets, err := generateBazelTargetsForDir(codegenCtx, checkDir)
- android.FailIfErrored(t, err)
- bazelTargets.sort()
- actualCount := len(bazelTargets)
- expectedCount := len(testCase.ExpectedBazelTargets)
- if actualCount != expectedCount {
- t.Errorf("Expected %d bazel target, got %d\n%s", expectedCount, actualCount, bazelTargets)
- }
- for i, target := range bazelTargets {
- actualContent := target.content
- expectedContent := testCase.ExpectedBazelTargets[i]
- if expectedContent != actualContent {
- t.Errorf(
- "Expected generated Bazel target to be '%s', got '%s'",
- expectedContent,
- actualContent,
- )
- }
- }
- })
- }
-}
-
-func TestGlob(t *testing.T) {
- testCases := []Bp2buildTestCase{
- {
- Description: "filegroup with glob",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: `filegroup {
- name: "fg_foo",
- srcs: ["**/*.txt"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "other/a.txt",
- "other/b.txt",
- "other/subdir/a.txt",
- ]`,
- }),
- },
- Filesystem: map[string]string{
- "other/a.txt": "",
- "other/b.txt": "",
- "other/subdir/a.txt": "",
- "other/file": "",
- },
- },
- {
- Description: "filegroup with glob in subdir",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Dir: "other",
- Filesystem: map[string]string{
- "other/Android.bp": `filegroup {
- name: "fg_foo",
- srcs: ["**/*.txt"],
- bazel_module: { bp2build_available: true },
-}`,
- "other/a.txt": "",
- "other/b.txt": "",
- "other/subdir/a.txt": "",
- "other/file": "",
- },
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "a.txt",
- "b.txt",
- "subdir/a.txt",
- ]`,
- }),
- },
- },
- {
- Description: "filegroup with glob with no kept BUILD files",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- KeepBuildFileForDirs: []string{
- // empty
- },
- Blueprint: `filegroup {
- name: "fg_foo",
- srcs: ["**/*.txt"],
- bazel_module: { bp2build_available: true },
-}`,
- Filesystem: map[string]string{
- "a.txt": "",
- "b.txt": "",
- "foo/BUILD": "",
- "foo/a.txt": "",
- "foo/bar/BUILD": "",
- "foo/bar/b.txt": "",
- },
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "a.txt",
- "b.txt",
- "foo/a.txt",
- "foo/bar/b.txt",
- ]`,
- }),
- },
- },
- {
- Description: "filegroup with glob with kept BUILD file",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- KeepBuildFileForDirs: []string{
- "foo",
- },
- Blueprint: `filegroup {
- name: "fg_foo",
- srcs: ["**/*.txt"],
- bazel_module: { bp2build_available: true },
-}`,
- Filesystem: map[string]string{
- "a.txt": "",
- "b.txt": "",
- "foo/BUILD": "",
- "foo/a.txt": "",
- "foo/bar/BUILD": "",
- "foo/bar/b.txt": "",
- },
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "a.txt",
- "b.txt",
- "//foo:a.txt",
- "//foo:bar/b.txt",
- ]`,
- }),
- },
- },
- {
- Description: "filegroup with glob with kept BUILD.bazel file",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- KeepBuildFileForDirs: []string{
- "foo",
- },
- Blueprint: `filegroup {
- name: "fg_foo",
- srcs: ["**/*.txt"],
- bazel_module: { bp2build_available: true },
-}`,
- Filesystem: map[string]string{
- "a.txt": "",
- "b.txt": "",
- "foo/BUILD.bazel": "",
- "foo/a.txt": "",
- "foo/bar/BUILD.bazel": "",
- "foo/bar/b.txt": "",
- },
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "a.txt",
- "b.txt",
- "//foo:a.txt",
- "//foo:bar/b.txt",
- ]`,
- }),
- },
- },
- {
- Description: "filegroup with glob with Android.bp file as boundary",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: `filegroup {
- name: "fg_foo",
- srcs: ["**/*.txt"],
- bazel_module: { bp2build_available: true },
-}`,
- Filesystem: map[string]string{
- "a.txt": "",
- "b.txt": "",
- "foo/Android.bp": "",
- "foo/a.txt": "",
- "foo/bar/Android.bp": "",
- "foo/bar/b.txt": "",
- },
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "a.txt",
- "b.txt",
- "//foo:a.txt",
- "//foo/bar:b.txt",
- ]`,
- }),
- },
- },
- {
- Description: "filegroup with glob in subdir with kept BUILD and BUILD.bazel file",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Dir: "other",
- KeepBuildFileForDirs: []string{
- "other/foo",
- "other/foo/bar",
- // deliberately not other/foo/baz/BUILD.
- },
- Filesystem: map[string]string{
- "other/Android.bp": `filegroup {
- name: "fg_foo",
- srcs: ["**/*.txt"],
- bazel_module: { bp2build_available: true },
-}`,
- "other/a.txt": "",
- "other/b.txt": "",
- "other/foo/BUILD": "",
- "other/foo/a.txt": "",
- "other/foo/bar/BUILD.bazel": "",
- "other/foo/bar/b.txt": "",
- "other/foo/baz/BUILD": "",
- "other/foo/baz/c.txt": "",
- },
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "a.txt",
- "b.txt",
- "//other/foo:a.txt",
- "//other/foo/bar:b.txt",
- "//other/foo:baz/c.txt",
- ]`,
- }),
- },
- },
- }
-
- for _, testCase := range testCases {
- t.Run(testCase.Description, func(t *testing.T) {
- RunBp2BuildTestCaseSimple(t, testCase)
- })
- }
-}
-
-func TestGlobExcludeSrcs(t *testing.T) {
- testCases := []Bp2buildTestCase{
- {
- Description: "filegroup top level exclude_srcs",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: `filegroup {
- name: "fg_foo",
- srcs: ["**/*.txt"],
- exclude_srcs: ["c.txt"],
- bazel_module: { bp2build_available: true },
-}`,
- Filesystem: map[string]string{
- "a.txt": "",
- "b.txt": "",
- "c.txt": "",
- "dir/Android.bp": "",
- "dir/e.txt": "",
- "dir/f.txt": "",
- },
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "a.txt",
- "b.txt",
- "//dir:e.txt",
- "//dir:f.txt",
- ]`,
- }),
- },
- },
- {
- Description: "filegroup in subdir exclude_srcs",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: "",
- Dir: "dir",
- Filesystem: map[string]string{
- "dir/Android.bp": `filegroup {
- name: "fg_foo",
- srcs: ["**/*.txt"],
- exclude_srcs: ["b.txt"],
- bazel_module: { bp2build_available: true },
-}
-`,
- "dir/a.txt": "",
- "dir/b.txt": "",
- "dir/subdir/Android.bp": "",
- "dir/subdir/e.txt": "",
- "dir/subdir/f.txt": "",
- },
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "srcs": `[
- "a.txt",
- "//dir/subdir:e.txt",
- "//dir/subdir:f.txt",
- ]`,
- }),
- },
- },
- }
-
- for _, testCase := range testCases {
- t.Run(testCase.Description, func(t *testing.T) {
- RunBp2BuildTestCaseSimple(t, testCase)
- })
- }
-}
-
-func TestCommonBp2BuildModuleAttrs(t *testing.T) {
- testCases := []Bp2buildTestCase{
- {
- Description: "Required into data test",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + `
-filegroup {
- name: "fg_foo",
- required: ["reqd"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "data": `[":reqd"]`,
- }),
- },
- },
- {
- Description: "Required into data test, cyclic self reference is filtered out",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + `
-filegroup {
- name: "fg_foo",
- required: ["reqd", "fg_foo"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "data": `[":reqd"]`,
- }),
- },
- },
- {
- Description: "Required via arch into data test",
- ModuleTypeUnderTest: "python_library",
- ModuleTypeUnderTestFactory: python.PythonLibraryFactory,
- Blueprint: simpleModuleDoNotConvertBp2build("python_library", "reqdx86") +
- simpleModuleDoNotConvertBp2build("python_library", "reqdarm") + `
-python_library {
- name: "fg_foo",
- arch: {
- arm: {
- required: ["reqdarm"],
- },
- x86: {
- required: ["reqdx86"],
- },
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("py_library", "fg_foo", map[string]string{
- "data": `select({
- "//build/bazel/platforms/arch:arm": [":reqdarm"],
- "//build/bazel/platforms/arch:x86": [":reqdx86"],
- "//conditions:default": [],
- })`,
- "srcs_version": `"PY3"`,
- "imports": `["."]`,
- }),
- },
- },
- {
- Description: "Required appended to data test",
- ModuleTypeUnderTest: "python_library",
- ModuleTypeUnderTestFactory: python.PythonLibraryFactory,
- Filesystem: map[string]string{
- "data.bin": "",
- "src.py": "",
- },
- Blueprint: simpleModuleDoNotConvertBp2build("python_library", "reqd") + `
-python_library {
- name: "fg_foo",
- data: ["data.bin"],
- required: ["reqd"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("py_library", "fg_foo", map[string]string{
- "data": `[
- "data.bin",
- ":reqd",
- ]`,
- "srcs_version": `"PY3"`,
- "imports": `["."]`,
- }),
- },
- },
- {
- Description: "All props-to-attrs at once together test",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: simpleModuleDoNotConvertBp2build("filegroup", "reqd") + `
-filegroup {
- name: "fg_foo",
- required: ["reqd"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "fg_foo", map[string]string{
- "data": `[":reqd"]`,
- }),
- },
- },
- }
-
- for _, tc := range testCases {
- t.Run(tc.Description, func(t *testing.T) {
- RunBp2BuildTestCaseSimple(t, tc)
- })
- }
-}
-
-func TestLicensesAttrConversion(t *testing.T) {
- RunBp2BuildTestCase(t,
- func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("license", android.LicenseFactory)
- },
- Bp2buildTestCase{
- Description: "Test that licenses: attribute is converted",
- ModuleTypeUnderTest: "filegroup",
- ModuleTypeUnderTestFactory: android.FileGroupFactory,
- Blueprint: `
-license {
- name: "my_license",
-}
-filegroup {
- name: "my_filegroup",
- licenses: ["my_license"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "my_filegroup", AttrNameToString{
- "applicable_licenses": `[":my_license"]`,
- }),
- MakeBazelTargetNoRestrictions("android_license", "my_license", AttrNameToString{}),
- },
- })
-}
-
-func TestGenerateConfigSetting(t *testing.T) {
- bp := `
- custom {
- name: "foo",
- test_config_setting: true,
- }
- `
- expectedBazelTargets := []string{
- MakeBazelTargetNoRestrictions(
- "config_setting",
- "foo_config_setting",
- AttrNameToString{
- "flag_values": `{
- "//build/bazel/rules/my_string_setting": "foo",
- }`,
- },
- ),
- MakeBazelTarget(
- "custom",
- "foo",
- AttrNameToString{},
- ),
- }
- registerCustomModule := func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
- }
- RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
- Blueprint: bp,
- ExpectedBazelTargets: expectedBazelTargets,
- Description: "Generating API contribution Bazel targets for custom module",
- })
-}
-
-// If values of all keys in an axis are equal to //conditions:default, drop the axis and print the common value
-func TestPrettyPrintSelectMapEqualValues(t *testing.T) {
- lla := bazel.LabelListAttribute{
- Value: bazel.LabelList{},
- }
- libFooImplLabel := bazel.Label{
- Label: ":libfoo.impl",
- }
- lla.SetSelectValue(bazel.OsAndInApexAxis, bazel.AndroidPlatform, bazel.MakeLabelList([]bazel.Label{libFooImplLabel}))
- lla.SetSelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, bazel.MakeLabelList([]bazel.Label{libFooImplLabel}))
- actual, _ := prettyPrintAttribute(lla, 0)
- android.AssertStringEquals(t, "Print the common value if all keys in an axis have the same value", `[":libfoo.impl"]`, actual)
-}
-
-// If CommonAttributes.Dir is set, the bazel target should be created in that dir
-func TestCreateBazelTargetInDifferentDir(t *testing.T) {
- t.Parallel()
- bp := `
- custom {
- name: "foo",
- dir: "subdir",
- }
- `
- registerCustomModule := func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
- }
- // Check that foo is not created in root dir
- RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
- Description: "foo is not created in root dir because it sets dir explicitly",
- Blueprint: bp,
- Filesystem: map[string]string{
- "subdir/Android.bp": "",
- },
- ExpectedBazelTargets: []string{},
- })
- // Check that foo is created in `subdir`
- RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
- Description: "foo is created in `subdir` because it sets dir explicitly",
- Blueprint: bp,
- Filesystem: map[string]string{
- "subdir/Android.bp": "",
- },
- Dir: "subdir",
- ExpectedBazelTargets: []string{
- MakeBazelTarget("custom", "foo", AttrNameToString{}),
- },
- })
- // Check that we cannot create target in different dir if it is does not an Android.bp
- RunBp2BuildTestCase(t, registerCustomModule, Bp2buildTestCase{
- Description: "foo cannot be created in `subdir` because it does not contain an Android.bp file",
- Blueprint: bp,
- Dir: "subdir",
- ExpectedErr: fmt.Errorf("Cannot use ca.Dir to create a BazelTarget in dir: subdir since it does not contain an Android.bp file"),
- })
-
-}
diff --git a/bp2build/bzl_conversion_test.go b/bp2build/bzl_conversion_test.go
deleted file mode 100644
index 402d4b0..0000000
--- a/bp2build/bzl_conversion_test.go
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright 2020 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 (
- "io/ioutil"
- "os"
- "strings"
- "testing"
-
- "android/soong/android"
-)
-
-func setUp() {
- var err error
- buildDir, err = ioutil.TempDir("", "bazel_queryview_test")
- if err != nil {
- panic(err)
- }
-}
-
-func tearDown() {
- os.RemoveAll(buildDir)
-}
-
-func TestMain(m *testing.M) {
- run := func() int {
- setUp()
- defer tearDown()
-
- return m.Run()
- }
-
- os.Exit(run())
-}
-
-func TestGenerateModuleRuleShims(t *testing.T) {
- moduleTypeFactories := map[string]android.ModuleFactory{
- "custom": customModuleFactoryBase,
- "custom_test": customTestModuleFactoryBase,
- "custom_defaults": customDefaultsModuleFactoryBasic,
- }
- ruleShims := CreateRuleShims(moduleTypeFactories)
-
- if len(ruleShims) != 1 {
- t.Errorf("Expected to generate 1 rule shim, but got %d", len(ruleShims))
- }
-
- ruleShim := ruleShims["bp2build"]
- expectedRules := []string{
- "custom",
- "custom_defaults",
- "custom_test_",
- }
-
- if len(ruleShim.rules) != len(expectedRules) {
- t.Errorf("Expected %d rules, but got %d", len(expectedRules), len(ruleShim.rules))
- }
-
- for i, rule := range ruleShim.rules {
- if rule != expectedRules[i] {
- t.Errorf("Expected rule shim to contain %s, but got %s", expectedRules[i], rule)
- }
- }
- expectedBzl := `load("//build/bazel/queryview_rules:providers.bzl", "SoongModuleInfo")
-
-def _custom_impl(ctx):
- return [SoongModuleInfo()]
-
-custom = rule(
- implementation = _custom_impl,
- attrs = {
- "soong_module_name": attr.string(mandatory = True),
- "soong_module_variant": attr.string(),
- "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
- "api": attr.string(),
- "arch_paths": attr.string_list(),
- "arch_paths_exclude": attr.string_list(),
- # bazel_module start
-# "label": attr.string(),
-# "bp2build_available": attr.bool(),
- # bazel_module end
- "bool_prop": attr.bool(),
- "bool_ptr_prop": attr.bool(),
- "dir": attr.string(),
- "embedded_prop": attr.string(),
- "int64_ptr_prop": attr.int(),
- # nested_props start
-# "nested_prop": attr.string(),
- # nested_props end
- # nested_props_ptr start
-# "nested_prop": attr.string(),
- # nested_props_ptr end
- "one_to_many_prop": attr.bool(),
- "other_embedded_prop": attr.string(),
- "string_list_prop": attr.string_list(),
- "string_literal_prop": attr.string(),
- "string_prop": attr.string(),
- "string_ptr_prop": attr.string(),
- "test_config_setting": attr.bool(),
- },
-)
-
-def _custom_defaults_impl(ctx):
- return [SoongModuleInfo()]
-
-custom_defaults = rule(
- implementation = _custom_defaults_impl,
- attrs = {
- "soong_module_name": attr.string(mandatory = True),
- "soong_module_variant": attr.string(),
- "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
- "api": attr.string(),
- "arch_paths": attr.string_list(),
- "arch_paths_exclude": attr.string_list(),
- "bool_prop": attr.bool(),
- "bool_ptr_prop": attr.bool(),
- "dir": attr.string(),
- "embedded_prop": attr.string(),
- "int64_ptr_prop": attr.int(),
- # nested_props start
-# "nested_prop": attr.string(),
- # nested_props end
- # nested_props_ptr start
-# "nested_prop": attr.string(),
- # nested_props_ptr end
- "one_to_many_prop": attr.bool(),
- "other_embedded_prop": attr.string(),
- "string_list_prop": attr.string_list(),
- "string_literal_prop": attr.string(),
- "string_prop": attr.string(),
- "string_ptr_prop": attr.string(),
- "test_config_setting": attr.bool(),
- },
-)
-
-def _custom_test__impl(ctx):
- return [SoongModuleInfo()]
-
-custom_test_ = rule(
- implementation = _custom_test__impl,
- attrs = {
- "soong_module_name": attr.string(mandatory = True),
- "soong_module_variant": attr.string(),
- "soong_module_deps": attr.label_list(providers = [SoongModuleInfo]),
- "api": attr.string(),
- "arch_paths": attr.string_list(),
- "arch_paths_exclude": attr.string_list(),
- "bool_prop": attr.bool(),
- "bool_ptr_prop": attr.bool(),
- "dir": attr.string(),
- "embedded_prop": attr.string(),
- "int64_ptr_prop": attr.int(),
- # nested_props start
-# "nested_prop": attr.string(),
- # nested_props end
- # nested_props_ptr start
-# "nested_prop": attr.string(),
- # nested_props_ptr end
- "one_to_many_prop": attr.bool(),
- "other_embedded_prop": attr.string(),
- "string_list_prop": attr.string_list(),
- "string_literal_prop": attr.string(),
- "string_prop": attr.string(),
- "string_ptr_prop": attr.string(),
- "test_config_setting": attr.bool(),
- # test_prop start
-# "test_string_prop": attr.string(),
- # test_prop end
- },
-)
-`
-
- if ruleShim.content != expectedBzl {
- t.Errorf(
- "Expected the generated rule shim bzl to be:\n%s\nbut got:\n%s",
- expectedBzl,
- ruleShim.content)
- }
-}
-
-func TestGenerateSoongModuleBzl(t *testing.T) {
- ruleShims := map[string]RuleShim{
- "file1": RuleShim{
- rules: []string{"a", "b"},
- content: "irrelevant",
- },
- "file2": RuleShim{
- rules: []string{"c", "d"},
- content: "irrelevant",
- },
- }
- files := CreateBazelFiles(ruleShims, make(map[string]BazelTargets), QueryView)
-
- var actualSoongModuleBzl BazelFile
- for _, f := range files {
- if f.Basename == "soong_module.bzl" {
- actualSoongModuleBzl = f
- }
- }
-
- expectedLoad := `load("//build/bazel/queryview_rules:file1.bzl", "a", "b")
-load("//build/bazel/queryview_rules:file2.bzl", "c", "d")
-`
- expectedRuleMap := `soong_module_rule_map = {
- "a": a,
- "b": b,
- "c": c,
- "d": d,
-}`
- if !strings.Contains(actualSoongModuleBzl.Contents, expectedLoad) {
- t.Errorf(
- "Generated soong_module.bzl:\n\n%s\n\n"+
- "Could not find the load statement in the generated soong_module.bzl:\n%s",
- actualSoongModuleBzl.Contents,
- expectedLoad)
- }
-
- if !strings.Contains(actualSoongModuleBzl.Contents, expectedRuleMap) {
- t.Errorf(
- "Generated soong_module.bzl:\n\n%s\n\n"+
- "Could not find the module -> rule map in the generated soong_module.bzl:\n%s",
- actualSoongModuleBzl.Contents,
- expectedRuleMap)
- }
-}
diff --git a/bp2build/cc_binary_conversion_test.go b/bp2build/cc_binary_conversion_test.go
deleted file mode 100644
index 90db365..0000000
--- a/bp2build/cc_binary_conversion_test.go
+++ /dev/null
@@ -1,1302 +0,0 @@
-// 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
-
-import (
- "fmt"
- "strings"
- "testing"
-
- "android/soong/android"
- "android/soong/cc"
- "android/soong/genrule"
-)
-
-const (
- ccBinaryTypePlaceHolder = "{rule_name}"
-)
-
-type testBazelTarget struct {
- typ string
- name string
- attrs AttrNameToString
-}
-
-func generateBazelTargetsForTest(targets []testBazelTarget, hod android.HostOrDeviceSupported) []string {
- ret := make([]string, 0, len(targets))
- for _, t := range targets {
- attrs := t.attrs.clone()
- ret = append(ret, makeBazelTargetHostOrDevice(t.typ, t.name, attrs, hod))
- }
- return ret
-}
-
-type ccBinaryBp2buildTestCase struct {
- description string
- filesystem map[string]string
- blueprint string
- targets []testBazelTarget
-}
-
-func registerCcBinaryModuleTypes(ctx android.RegistrationContext) {
- cc.RegisterCCBuildComponents(ctx)
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
- ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
- ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
-}
-
-var binaryReplacer = strings.NewReplacer(ccBinaryTypePlaceHolder, "cc_binary")
-var hostBinaryReplacer = strings.NewReplacer(ccBinaryTypePlaceHolder, "cc_binary_host")
-
-func runCcBinaryTests(t *testing.T, tc ccBinaryBp2buildTestCase) {
- t.Helper()
- runCcBinaryTestCase(t, tc)
- runCcHostBinaryTestCase(t, tc)
-}
-
-func runCcBinaryTestCase(t *testing.T, testCase ccBinaryBp2buildTestCase) {
- t.Helper()
- moduleTypeUnderTest := "cc_binary"
-
- description := fmt.Sprintf("%s %s", moduleTypeUnderTest, testCase.description)
- t.Run(description, func(t *testing.T) {
- t.Helper()
- RunBp2BuildTestCase(t, registerCcBinaryModuleTypes, Bp2buildTestCase{
- ExpectedBazelTargets: generateBazelTargetsForTest(testCase.targets, android.DeviceSupported),
- ModuleTypeUnderTest: moduleTypeUnderTest,
- ModuleTypeUnderTestFactory: cc.BinaryFactory,
- Description: description,
- Blueprint: binaryReplacer.Replace(testCase.blueprint),
- Filesystem: testCase.filesystem,
- })
- })
-}
-
-func runCcHostBinaryTestCase(t *testing.T, testCase ccBinaryBp2buildTestCase) {
- t.Helper()
- moduleTypeUnderTest := "cc_binary_host"
- description := fmt.Sprintf("%s %s", moduleTypeUnderTest, testCase.description)
- t.Run(description, func(t *testing.T) {
- RunBp2BuildTestCase(t, registerCcBinaryModuleTypes, Bp2buildTestCase{
- ExpectedBazelTargets: generateBazelTargetsForTest(testCase.targets, android.HostSupported),
- ModuleTypeUnderTest: moduleTypeUnderTest,
- ModuleTypeUnderTestFactory: cc.BinaryHostFactory,
- Description: description,
- Blueprint: hostBinaryReplacer.Replace(testCase.blueprint),
- Filesystem: testCase.filesystem,
- })
- })
-}
-
-func TestBasicCcBinary(t *testing.T) {
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: "basic -- properties -> attrs with little/no transformation",
- filesystem: map[string]string{
- soongCcVersionLibBpPath: soongCcVersionLibBp,
- },
- blueprint: `
-{rule_name} {
- name: "foo",
- srcs: ["a.cc"],
- local_include_dirs: ["dir"],
- include_dirs: ["absolute_dir"],
- cflags: ["-Dcopt"],
- cppflags: ["-Dcppflag"],
- conlyflags: ["-Dconlyflag"],
- asflags: ["-Dasflag"],
- ldflags: ["ld-flag"],
- rtti: true,
- strip: {
- all: true,
- keep_symbols: true,
- keep_symbols_and_debug_frame: true,
- keep_symbols_list: ["symbol"],
- none: true,
- },
- sdk_version: "current",
- min_sdk_version: "29",
- use_version_lib: true,
-}
-`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "absolute_includes": `["absolute_dir"]`,
- "asflags": `["-Dasflag"]`,
- "conlyflags": `["-Dconlyflag"]`,
- "copts": `["-Dcopt"]`,
- "cppflags": `["-Dcppflag"]`,
- "linkopts": `["ld-flag"]`,
- "local_includes": `[
- "dir",
- ".",
- ]`,
- "rtti": `True`,
- "srcs": `["a.cc"]`,
- "strip": `{
- "all": True,
- "keep_symbols": True,
- "keep_symbols_and_debug_frame": True,
- "keep_symbols_list": ["symbol"],
- "none": True,
- }`,
- "sdk_version": `"current"`,
- "min_sdk_version": `"29"`,
- "use_version_lib": `True`,
- "whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
- },
- },
- },
- })
-}
-
-func TestCcBinaryWithSharedLdflagDisableFeature(t *testing.T) {
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: `ldflag "-shared" disables static_flag feature`,
- blueprint: `
-{rule_name} {
- name: "foo",
- ldflags: ["-shared"],
- include_build_directory: false,
-}
-`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "features": `["-static_flag"]`,
- "linkopts": `["-shared"]`,
- },
- },
- },
- })
-}
-
-func TestCcBinaryWithLinkStatic(t *testing.T) {
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: "link static",
- blueprint: `
-{rule_name} {
- name: "foo",
- static_executable: true,
- include_build_directory: false,
-}
-`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "linkshared": `False`,
- },
- },
- },
- })
-}
-
-func TestCcBinaryVersionScriptAndDynamicList(t *testing.T) {
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: `version script and dynamic list`,
- blueprint: `
-{rule_name} {
- name: "foo",
- include_build_directory: false,
- version_script: "vs",
- dynamic_list: "dynamic.list",
-}
-`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "additional_linker_inputs": `[
- "vs",
- "dynamic.list",
- ]`,
- "linkopts": `[
- "-Wl,--version-script,$(location vs)",
- "-Wl,--dynamic-list,$(location dynamic.list)",
- ]`,
- "features": `["android_cfi_exports_map"]`,
- },
- },
- },
- })
-}
-
-func TestCcBinaryLdflagsSplitBySpaceExceptSoongAdded(t *testing.T) {
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: "ldflags are split by spaces except for the ones added by soong (version script and dynamic list)",
- blueprint: `
-{rule_name} {
- name: "foo",
- ldflags: [
- "--nospace_flag",
- "-z spaceflag",
- ],
- version_script: "version_script",
- dynamic_list: "dynamic.list",
- include_build_directory: false,
-}
-`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "additional_linker_inputs": `[
- "version_script",
- "dynamic.list",
- ]`,
- "features": `["android_cfi_exports_map"]`,
- "linkopts": `[
- "--nospace_flag",
- "-z",
- "spaceflag",
- "-Wl,--version-script,$(location version_script)",
- "-Wl,--dynamic-list,$(location dynamic.list)",
- ]`,
- }}},
- })
-}
-
-func TestCcBinarySplitSrcsByLang(t *testing.T) {
- runCcHostBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "split srcs by lang",
- blueprint: `
-{rule_name} {
- name: "foo",
- srcs: [
- "asonly.S",
- "conly.c",
- "cpponly.cpp",
- ":fg_foo",
- ],
- include_build_directory: false,
-}
-` + simpleModuleDoNotConvertBp2build("filegroup", "fg_foo"),
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "srcs": `[
- "cpponly.cpp",
- ":fg_foo_cpp_srcs",
- ]`,
- "srcs_as": `[
- "asonly.S",
- ":fg_foo_as_srcs",
- ]`,
- "srcs_c": `[
- "conly.c",
- ":fg_foo_c_srcs",
- ]`,
- },
- },
- },
- })
-}
-
-func TestCcBinaryDoNotDistinguishBetweenDepsAndImplementationDeps(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "no implementation deps",
- blueprint: `
-genrule {
- name: "generated_hdr",
- cmd: "nothing to see here",
- bazel_module: { bp2build_available: false },
-}
-
-genrule {
- name: "export_generated_hdr",
- cmd: "nothing to see here",
- bazel_module: { bp2build_available: false },
-}
-
-{rule_name} {
- name: "foo",
- srcs: ["foo.cpp"],
- shared_libs: ["implementation_shared_dep", "shared_dep"],
- export_shared_lib_headers: ["shared_dep"],
- static_libs: ["implementation_static_dep", "static_dep"],
- export_static_lib_headers: ["static_dep", "whole_static_dep"],
- whole_static_libs: ["not_explicitly_exported_whole_static_dep", "whole_static_dep"],
- include_build_directory: false,
- generated_headers: ["generated_hdr", "export_generated_hdr"],
- export_generated_headers: ["export_generated_hdr"],
-}
-` +
- simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep") +
- simpleModuleDoNotConvertBp2build("cc_library", "shared_dep") +
- simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep"),
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "deps": `[
- ":implementation_static_dep",
- ":static_dep",
- ]`,
- "dynamic_deps": `[
- ":implementation_shared_dep",
- ":shared_dep",
- ]`,
- "srcs": `[
- "foo.cpp",
- ":generated_hdr",
- ":export_generated_hdr",
- ]`,
- "whole_archive_deps": `[
- ":not_explicitly_exported_whole_static_dep",
- ":whole_static_dep",
- ]`,
- "local_includes": `["."]`,
- },
- },
- },
- })
-}
-
-func TestCcBinaryNocrtTests(t *testing.T) {
- baseTestCases := []struct {
- description string
- soongProperty string
- bazelAttr AttrNameToString
- }{
- {
- description: "nocrt: true",
- soongProperty: `nocrt: true,`,
- bazelAttr: AttrNameToString{"features": `["-link_crt"]`},
- },
- {
- description: "nocrt: false",
- soongProperty: `nocrt: false,`,
- bazelAttr: AttrNameToString{},
- },
- {
- description: "nocrt: not set",
- bazelAttr: AttrNameToString{},
- },
- }
-
- baseBlueprint := `{rule_name} {
- name: "foo",%s
- include_build_directory: false,
-}
-`
-
- for _, btc := range baseTestCases {
- prop := btc.soongProperty
- if len(prop) > 0 {
- prop = "\n" + prop
- }
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: btc.description,
- blueprint: fmt.Sprintf(baseBlueprint, prop),
- targets: []testBazelTarget{
- {"cc_binary", "foo", btc.bazelAttr},
- },
- })
- }
-}
-
-func TestCcBinaryNo_libcrtTests(t *testing.T) {
- baseTestCases := []struct {
- description string
- soongProperty string
- bazelAttr AttrNameToString
- }{
- {
- description: "no_libcrt: true",
- soongProperty: `no_libcrt: true,`,
- bazelAttr: AttrNameToString{"features": `["-use_libcrt"]`},
- },
- {
- description: "no_libcrt: false",
- soongProperty: `no_libcrt: false,`,
- bazelAttr: AttrNameToString{},
- },
- {
- description: "no_libcrt: not set",
- bazelAttr: AttrNameToString{},
- },
- }
-
- baseBlueprint := `{rule_name} {
- name: "foo",%s
- include_build_directory: false,
-}
-`
-
- for _, btc := range baseTestCases {
- prop := btc.soongProperty
- if len(prop) > 0 {
- prop = "\n" + prop
- }
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: btc.description,
- blueprint: fmt.Sprintf(baseBlueprint, prop),
- targets: []testBazelTarget{
- {"cc_binary", "foo", btc.bazelAttr},
- },
- })
- }
-}
-
-func TestCcBinaryPropertiesToFeatures(t *testing.T) {
- baseTestCases := []struct {
- description string
- soongProperty string
- bazelAttr AttrNameToString
- }{
- {
- description: "pack_relocation: true",
- soongProperty: `pack_relocations: true,`,
- bazelAttr: AttrNameToString{},
- },
- {
- description: "pack_relocations: false",
- soongProperty: `pack_relocations: false,`,
- bazelAttr: AttrNameToString{"features": `["disable_pack_relocations"]`},
- },
- {
- description: "pack_relocations: not set",
- bazelAttr: AttrNameToString{},
- },
- {
- description: "pack_relocation: true",
- soongProperty: `allow_undefined_symbols: true,`,
- bazelAttr: AttrNameToString{"features": `["-no_undefined_symbols"]`},
- },
- {
- description: "allow_undefined_symbols: false",
- soongProperty: `allow_undefined_symbols: false,`,
- bazelAttr: AttrNameToString{},
- },
- {
- description: "allow_undefined_symbols: not set",
- bazelAttr: AttrNameToString{},
- },
- }
-
- baseBlueprint := `{rule_name} {
- name: "foo",%s
- include_build_directory: false,
-}
-`
- for _, btc := range baseTestCases {
- prop := btc.soongProperty
- if len(prop) > 0 {
- prop = "\n" + prop
- }
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: btc.description,
- blueprint: fmt.Sprintf(baseBlueprint, prop),
- targets: []testBazelTarget{
- {"cc_binary", "foo", btc.bazelAttr},
- },
- })
- }
-}
-
-func TestCcBinarySharedProto(t *testing.T) {
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- blueprint: soongCcProtoLibraries + `{rule_name} {
- name: "foo",
- srcs: ["foo.proto"],
- proto: {
- },
- include_build_directory: false,
-}`,
- targets: []testBazelTarget{
- {"proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- }}, {"cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
- "deps": `[":foo_proto"]`,
- }}, {"cc_binary", "foo", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }},
- },
- })
-}
-
-func TestCcBinaryStaticProto(t *testing.T) {
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- blueprint: soongCcProtoLibraries + `{rule_name} {
- name: "foo",
- srcs: ["foo.proto"],
- static_executable: true,
- proto: {
- },
- include_build_directory: false,
-}`,
- targets: []testBazelTarget{
- {"proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- }}, {"cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
- "deps": `[":foo_proto"]`,
- }}, {"cc_binary", "foo", AttrNameToString{
- "deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":foo_cc_proto_lite"]`,
- "linkshared": `False`,
- }},
- },
- })
-}
-
-func TestCcBinaryConvertLex(t *testing.T) {
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: `.l and .ll sources converted to .c and .cc`,
- blueprint: `
-{rule_name} {
- name: "foo",
- srcs: ["foo.c", "bar.cc", "foo1.l", "foo2.l", "bar1.ll", "bar2.ll"],
- lex: { flags: ["--foo_opt", "--bar_opt"] },
- include_build_directory: false,
-}
-`,
- targets: []testBazelTarget{
- {"genlex", "foo_genlex_l", AttrNameToString{
- "srcs": `[
- "foo1.l",
- "foo2.l",
- ]`,
- "lexopts": `[
- "--foo_opt",
- "--bar_opt",
- ]`,
- }},
- {"genlex", "foo_genlex_ll", AttrNameToString{
- "srcs": `[
- "bar1.ll",
- "bar2.ll",
- ]`,
- "lexopts": `[
- "--foo_opt",
- "--bar_opt",
- ]`,
- }},
- {"cc_binary", "foo", AttrNameToString{
- "srcs": `[
- "bar.cc",
- ":foo_genlex_ll",
- ]`,
- "srcs_c": `[
- "foo.c",
- ":foo_genlex_l",
- ]`,
- }},
- },
- })
-}
-
-func TestCcBinaryRuntimeLibs(t *testing.T) {
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: "cc_binary with runtime libs",
- blueprint: `
-cc_library {
- name: "bar",
- srcs: ["b.cc"],
-}
-
-{rule_name} {
- name: "foo",
- srcs: ["a.cc"],
- runtime_libs: ["bar"],
-}
-`,
- targets: []testBazelTarget{
- {"cc_library_static", "bar_bp2build_cc_library_static", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `["b.cc"]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- },
- },
- {"cc_library_shared", "bar", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `["b.cc"]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- },
- },
- {"cc_binary", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `["a.cc"]`,
- "runtime_deps": `[":bar"]`,
- },
- },
- },
- })
-}
-
-func TestCcBinaryWithInstructionSet(t *testing.T) {
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: "instruction set",
- blueprint: `
-{rule_name} {
- name: "foo",
- arch: {
- arm: {
- instruction_set: "arm",
- }
- }
-}
-`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/arch:arm": ["arm_isa_arm"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }},
- },
- })
-}
-
-func TestCcBinaryEmptySuffix(t *testing.T) {
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: "binary with empty suffix",
- blueprint: `
-{rule_name} {
- name: "foo",
- suffix: "",
-}`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "suffix": `""`,
- }},
- },
- })
-}
-
-func TestCcBinarySuffix(t *testing.T) {
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: "binary with suffix",
- blueprint: `
-{rule_name} {
- name: "foo",
- suffix: "-suf",
-}
-`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "suffix": `"-suf"`,
- }},
- },
- })
-}
-
-func TestCcArchVariantBinarySuffix(t *testing.T) {
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: "binary with suffix",
- blueprint: `
-{rule_name} {
- name: "foo",
- arch: {
- arm64: { suffix: "-64" },
- arm: { suffix: "-32" },
- },
-}
-`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "suffix": `select({
- "//build/bazel/platforms/arch:arm": "-32",
- "//build/bazel/platforms/arch:arm64": "-64",
- "//conditions:default": None,
- })`,
- }},
- },
- })
-}
-
-func TestCcBinaryWithSyspropSrcs(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary with sysprop sources",
- blueprint: `
-{rule_name} {
- name: "foo",
- srcs: [
- "bar.sysprop",
- "baz.sysprop",
- "blah.cpp",
- ],
- min_sdk_version: "5",
-}`,
- targets: []testBazelTarget{
- {"sysprop_library", "foo_sysprop_library", AttrNameToString{
- "srcs": `[
- "bar.sysprop",
- "baz.sysprop",
- ]`,
- }},
- {"cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
- "dep": `":foo_sysprop_library"`,
- "min_sdk_version": `"5"`,
- }},
- {"cc_binary", "foo", AttrNameToString{
- "srcs": `["blah.cpp"]`,
- "local_includes": `["."]`,
- "min_sdk_version": `"5"`,
- "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`,
- }},
- },
- })
-}
-
-func TestCcBinaryWithSyspropSrcsSomeConfigs(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary with sysprop sources in some configs but not others",
- blueprint: `
-{rule_name} {
- name: "foo",
- srcs: [
- "blah.cpp",
- ],
- target: {
- android: {
- srcs: ["bar.sysprop"],
- },
- },
- min_sdk_version: "5",
-}`,
- targets: []testBazelTarget{
- {"sysprop_library", "foo_sysprop_library", AttrNameToString{
- "srcs": `select({
- "//build/bazel/platforms/os:android": ["bar.sysprop"],
- "//conditions:default": [],
- })`,
- }},
- {"cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
- "dep": `":foo_sysprop_library"`,
- "min_sdk_version": `"5"`,
- }},
- {"cc_binary", "foo", AttrNameToString{
- "srcs": `["blah.cpp"]`,
- "local_includes": `["."]`,
- "min_sdk_version": `"5"`,
- "whole_archive_deps": `select({
- "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"],
- "//conditions:default": [],
- })`,
- }},
- },
- })
-}
-
-func TestCcBinaryWithIntegerOverflowProperty(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary with integer overflow property specified",
- blueprint: `
-{rule_name} {
- name: "foo",
- sanitize: {
- integer_overflow: true,
- },
-}`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `["ubsan_integer_overflow"]`,
- }},
- },
- })
-}
-
-func TestCcBinaryWithMiscUndefinedProperty(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary with miscellaneous properties specified",
- blueprint: `
-{rule_name} {
- name: "foo",
- sanitize: {
- misc_undefined: ["undefined", "nullability"],
- },
-}`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `[
- "ubsan_undefined",
- "ubsan_nullability",
- ]`,
- }},
- },
- })
-}
-
-func TestCcBinaryWithUBSanPropertiesArchSpecific(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary has correct feature select when UBSan props are specified in arch specific blocks",
- blueprint: `
-{rule_name} {
- name: "foo",
- sanitize: {
- misc_undefined: ["undefined", "nullability"],
- },
- target: {
- android: {
- sanitize: {
- misc_undefined: ["alignment"],
- },
- },
- linux_glibc: {
- sanitize: {
- integer_overflow: true,
- },
- },
- },
-}`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `[
- "ubsan_undefined",
- "ubsan_nullability",
- ] + select({
- "//build/bazel/platforms/os:android": ["ubsan_alignment"],
- "//build/bazel/platforms/os:linux_glibc": ["ubsan_integer_overflow"],
- "//conditions:default": [],
- })`,
- }},
- },
- })
-}
-
-func TestCcBinaryWithSanitizerBlocklist(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary has the correct feature when sanitize.blocklist is provided",
- blueprint: `
-{rule_name} {
- name: "foo",
- sanitize: {
- blocklist: "foo_blocklist.txt",
- },
-}`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "copts": `select({
- "//build/bazel/rules/cc:sanitizers_enabled": ["-fsanitize-ignorelist=$(location foo_blocklist.txt)"],
- "//conditions:default": [],
- })`,
- "additional_compiler_inputs": `select({
- "//build/bazel/rules/cc:sanitizers_enabled": [":foo_blocklist.txt"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }},
- },
- })
-}
-
-func TestCcBinaryWithThinLto(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary has correct features when thin LTO is enabled",
- blueprint: `
-{rule_name} {
- name: "foo",
- lto: {
- thin: true,
- },
-}`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `["android_thin_lto"]`,
- }},
- },
- })
-}
-
-func TestCcBinaryWithLtoNever(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary has correct features when LTO is explicitly disabled",
- blueprint: `
-{rule_name} {
- name: "foo",
- lto: {
- never: true,
- },
-}`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `["-android_thin_lto"]`,
- }},
- },
- })
-}
-
-func TestCcBinaryWithThinLtoArchSpecific(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary has correct features when LTO differs across arch and os variants",
- blueprint: `
-{rule_name} {
- name: "foo",
- target: {
- android: {
- lto: {
- thin: true,
- },
- },
- },
- arch: {
- riscv64: {
- lto: {
- thin: false,
- },
- },
- },
-}`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm": ["android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_arm64": ["android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_riscv64": ["-android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_x86": ["android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_x86_64": ["android_thin_lto"],
- "//conditions:default": [],
- })`,
- }},
- },
- })
-}
-
-func TestCcBinaryWithThinLtoDisabledDefaultEnabledVariant(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary has correct features when LTO disabled by default but enabled on a particular variant",
- blueprint: `
-{rule_name} {
- name: "foo",
- lto: {
- never: true,
- },
- target: {
- android: {
- lto: {
- thin: true,
- never: false,
- },
- },
- },
-}`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `select({
- "//build/bazel/platforms/os:android": ["android_thin_lto"],
- "//conditions:default": ["-android_thin_lto"],
- })`,
- }},
- },
- })
-}
-
-func TestCcBinaryWithThinLtoAndWholeProgramVtables(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary has correct features when thin LTO is enabled with whole_program_vtables",
- blueprint: `
-{rule_name} {
- name: "foo",
- lto: {
- thin: true,
- },
- whole_program_vtables: true,
-}`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `[
- "android_thin_lto",
- "android_thin_lto_whole_program_vtables",
- ]`,
- }},
- },
- })
-}
-
-func TestCcBinaryHiddenVisibilityConvertedToFeature(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary changes hidden visibility to feature",
- blueprint: `
-{rule_name} {
- name: "foo",
- cflags: ["-fvisibility=hidden"],
-}`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `["visibility_hidden"]`,
- }},
- },
- })
-}
-
-func TestCcBinaryHiddenVisibilityConvertedToFeatureOsSpecific(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary changes hidden visibility to feature for specific os",
- blueprint: `
-{rule_name} {
- name: "foo",
- target: {
- android: {
- cflags: ["-fvisibility=hidden"],
- },
- },
-}`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `select({
- "//build/bazel/platforms/os:android": ["visibility_hidden"],
- "//conditions:default": [],
- })`,
- }},
- },
- })
-}
-
-func TestCcBinaryWithCfi(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary has correct features when cfi is enabled",
- blueprint: `
-{rule_name} {
- name: "foo",
- sanitize: {
- cfi: true,
- },
-}`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "features": `["android_cfi"]`,
- "local_includes": `["."]`,
- }},
- },
- })
-}
-
-func TestCcBinaryWithCfiOsSpecific(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary has correct features when cfi is enabled for specific variants",
- blueprint: `
-{rule_name} {
- name: "foo",
- target: {
- android: {
- sanitize: {
- cfi: true,
- },
- },
- },
-}`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/os:android": ["android_cfi"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }},
- },
- })
-}
-
-func TestCcBinaryWithCfiAndCfiAssemblySupport(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary has correct features when cfi is enabled with cfi assembly support",
- blueprint: `
-{rule_name} {
- name: "foo",
- sanitize: {
- cfi: true,
- config: {
- cfi_assembly_support: true,
- },
- },
-}`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "features": `[
- "android_cfi",
- "android_cfi_assembly_support",
- ]`,
- "local_includes": `["."]`,
- }},
- },
- })
-}
-
-func TestCcBinaryExplicitlyDisablesCfiWhenFalse(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary disables cfi when explciitly set to false in the bp",
- blueprint: `
-{rule_name} {
- name: "foo",
- sanitize: {
- cfi: false,
- },
-}
-`,
- targets: []testBazelTarget{
- {"cc_binary", "foo", AttrNameToString{
- "features": `["-android_cfi"]`,
- "local_includes": `["."]`,
- }},
- },
- })
-}
-
-func TestCcBinaryStem(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_binary with stem property",
- blueprint: `
-cc_binary {
- name: "foo_with_stem_simple",
- stem: "foo",
-}
-cc_binary {
- name: "foo_with_arch_variant_stem",
- arch: {
- arm: {
- stem: "foo-arm",
- },
- arm64: {
- stem: "foo-arm64",
- },
- },
-}
-`,
- targets: []testBazelTarget{
- {"cc_binary", "foo_with_stem_simple", AttrNameToString{
- "stem": `"foo"`,
- "local_includes": `["."]`,
- }},
- {"cc_binary", "foo_with_arch_variant_stem", AttrNameToString{
- "stem": `select({
- "//build/bazel/platforms/arch:arm": "foo-arm",
- "//build/bazel/platforms/arch:arm64": "foo-arm64",
- "//conditions:default": None,
- })`,
- "local_includes": `["."]`,
- }},
- },
- })
-}
-
-func TestCCBinaryRscriptSrc(t *testing.T) {
- runCcBinaryTests(t, ccBinaryBp2buildTestCase{
- description: `cc_binary with rscript files in sources`,
- blueprint: `
-{rule_name} {
- name : "foo",
- srcs : [
- "ccSrc.cc",
- "rsSrc.rscript",
- ],
- include_build_directory: false,
-}
-`,
- targets: []testBazelTarget{
- {"rscript_to_cpp", "foo_renderscript", AttrNameToString{
- "srcs": `["rsSrc.rscript"]`,
- }},
- {"cc_binary", "foo", AttrNameToString{
- "absolute_includes": `[
- "frameworks/rs",
- "frameworks/rs/cpp",
- ]`,
- "local_includes": `["."]`,
- "srcs": `[
- "ccSrc.cc",
- "foo_renderscript",
- ]`,
- }},
- },
- })
-}
-
-func TestCcBinaryStatic_SystemSharedLibUsedAsDep(t *testing.T) {
- runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{
- description: "cc_library_static system_shared_lib empty for linux_bionic variant",
- blueprint: soongCcLibraryStaticPreamble +
- simpleModuleDoNotConvertBp2build("cc_library", "libc") + `
-
-cc_library {
- name: "libm",
- bazel_module: { bp2build_available: false },
-}
-
-cc_binary {
- name: "used_in_bionic_oses",
- target: {
- android: {
- static_libs: ["libc"],
- },
- linux_bionic: {
- static_libs: ["libc"],
- },
- },
- include_build_directory: false,
- static_executable: true,
-}
-
-cc_binary {
- name: "all",
- static_libs: ["libc"],
- include_build_directory: false,
- static_executable: true,
-}
-
-cc_binary {
- name: "keep_for_empty_system_shared_libs",
- static_libs: ["libc"],
- system_shared_libs: [],
- include_build_directory: false,
- static_executable: true,
-}
-
-cc_binary {
- name: "used_with_stubs",
- static_libs: ["libm"],
- include_build_directory: false,
- static_executable: true,
-}
-
-cc_binary {
- name: "keep_with_stubs",
- static_libs: ["libm"],
- system_shared_libs: [],
- include_build_directory: false,
- static_executable: true,
-}
-`,
- targets: []testBazelTarget{
- {"cc_binary", "all", AttrNameToString{
- "linkshared": "False",
- }},
- {"cc_binary", "keep_for_empty_system_shared_libs", AttrNameToString{
- "deps": `[":libc_bp2build_cc_library_static"]`,
- "system_deps": `[]`,
- "linkshared": "False",
- }},
- {"cc_binary", "keep_with_stubs", AttrNameToString{
- "linkshared": "False",
- "deps": `[":libm_bp2build_cc_library_static"]`,
- "system_deps": `[]`,
- }},
- {"cc_binary", "used_in_bionic_oses", AttrNameToString{
- "linkshared": "False",
- }},
- {"cc_binary", "used_with_stubs", AttrNameToString{
- "linkshared": "False",
- }},
- },
- })
-}
diff --git a/bp2build/cc_library_conversion_test.go b/bp2build/cc_library_conversion_test.go
deleted file mode 100644
index 9bb1713..0000000
--- a/bp2build/cc_library_conversion_test.go
+++ /dev/null
@@ -1,5132 +0,0 @@
-// 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
-
-import (
- "fmt"
- "testing"
-
- "android/soong/aidl_library"
- "android/soong/android"
- "android/soong/cc"
-)
-
-const (
- // See cc/testing.go for more context
- soongCcLibraryPreamble = `
-cc_defaults {
- name: "linux_bionic_supported",
-}
-`
-
- soongCcVersionLibBpPath = "build/soong/cc/libbuildversion/Android.bp"
- soongCcVersionLibBp = `
-cc_library_static {
- name: "libbuildversion",
- bazel_module: { bp2build_available: false },
-}
-`
-
- soongCcProtoLibraries = `
-cc_library {
- name: "libprotobuf-cpp-lite",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "libprotobuf-cpp-full",
- bazel_module: { bp2build_available: false },
-}`
-
- soongCcProtoPreamble = soongCcLibraryPreamble + soongCcProtoLibraries
-)
-
-func runCcLibraryTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, registerCcLibraryModuleTypes, tc)
-}
-
-func registerCcLibraryModuleTypes(ctx android.RegistrationContext) {
- cc.RegisterCCBuildComponents(ctx)
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
- ctx.RegisterModuleType("cc_prebuilt_library_static", cc.PrebuiltStaticLibraryFactory)
- ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
- ctx.RegisterModuleType("aidl_library", aidl_library.AidlLibraryFactory)
-}
-
-func TestCcLibrarySimple(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library - simple example",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- soongCcVersionLibBpPath: soongCcVersionLibBp,
- "android.cpp": "",
- "bionic.cpp": "",
- "darwin.cpp": "",
- // Refer to cc.headerExts for the supported header extensions in Soong.
- "header.h": "",
- "header.hh": "",
- "header.hpp": "",
- "header.hxx": "",
- "header.h++": "",
- "header.inl": "",
- "header.inc": "",
- "header.ipp": "",
- "header.h.generic": "",
- "impl.cpp": "",
- "linux.cpp": "",
- "x86.cpp": "",
- "x86_64.cpp": "",
- "foo-dir/a.h": "",
- },
- Blueprint: soongCcLibraryPreamble +
- simpleModuleDoNotConvertBp2build("cc_library_headers", "some-headers") + `
-cc_library {
- name: "foo-lib",
- srcs: ["impl.cpp"],
- cflags: ["-Wall"],
- header_libs: ["some-headers"],
- export_include_dirs: ["foo-dir"],
- ldflags: ["-Wl,--exclude-libs=bar.a"],
- arch: {
- x86: {
- ldflags: ["-Wl,--exclude-libs=baz.a"],
- srcs: ["x86.cpp"],
- },
- x86_64: {
- ldflags: ["-Wl,--exclude-libs=qux.a"],
- srcs: ["x86_64.cpp"],
- },
- },
- target: {
- android: {
- srcs: ["android.cpp"],
- },
- linux_glibc: {
- srcs: ["linux.cpp"],
- },
- darwin: {
- srcs: ["darwin.cpp"],
- },
- bionic: {
- srcs: ["bionic.cpp"]
- },
- },
- include_build_directory: false,
- sdk_version: "current",
- min_sdk_version: "29",
- use_version_lib: true,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo-lib", AttrNameToString{
- "copts": `["-Wall"]`,
- "export_includes": `["foo-dir"]`,
- "implementation_deps": `[":some-headers"]`,
- "linkopts": `["-Wl,--exclude-libs=bar.a"] + select({
- "//build/bazel/platforms/arch:x86": ["-Wl,--exclude-libs=baz.a"],
- "//build/bazel/platforms/arch:x86_64": ["-Wl,--exclude-libs=qux.a"],
- "//conditions:default": [],
- })`,
- "srcs": `["impl.cpp"] + select({
- "//build/bazel/platforms/arch:x86": ["x86.cpp"],
- "//build/bazel/platforms/arch:x86_64": ["x86_64.cpp"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os:android": [
- "bionic.cpp",
- "android.cpp",
- ],
- "//build/bazel/platforms/os:darwin": ["darwin.cpp"],
- "//build/bazel/platforms/os:linux_bionic": ["bionic.cpp"],
- "//build/bazel/platforms/os:linux_glibc": ["linux.cpp"],
- "//conditions:default": [],
- })`,
- "sdk_version": `"current"`,
- "min_sdk_version": `"29"`,
- "use_version_lib": `True`,
- "whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
- }),
- })
-}
-
-func TestCcLibraryTrimmedLdAndroid(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library - trimmed example of //bionic/linker:ld-android",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "ld-android.cpp": "",
- "linked_list.h": "",
- "linker.h": "",
- "linker_block_allocator.h": "",
- "linker_cfi.h": "",
- },
- Blueprint: soongCcLibraryPreamble +
- simpleModuleDoNotConvertBp2build("cc_library_headers", "libc_headers") + `
-cc_library {
- name: "fake-ld-android",
- srcs: ["ld_android.cpp"],
- cflags: [
- "-Wall",
- "-Wextra",
- "-Wunused",
- "-Werror",
- ],
- header_libs: ["libc_headers"],
- ldflags: [
- "-Wl,--exclude-libs=libgcc.a",
- "-Wl,--exclude-libs=libgcc_stripped.a",
- "-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
- "-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
- "-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a",
- "-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
- ],
- arch: {
- x86: {
- ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
- },
- x86_64: {
- ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("fake-ld-android", AttrNameToString{
- "srcs": `["ld_android.cpp"]`,
- "copts": `[
- "-Wall",
- "-Wextra",
- "-Wunused",
- "-Werror",
- ]`,
- "implementation_deps": `[":libc_headers"]`,
- "linkopts": `[
- "-Wl,--exclude-libs=libgcc.a",
- "-Wl,--exclude-libs=libgcc_stripped.a",
- "-Wl,--exclude-libs=libclang_rt.builtins-arm-android.a",
- "-Wl,--exclude-libs=libclang_rt.builtins-aarch64-android.a",
- "-Wl,--exclude-libs=libclang_rt.builtins-i686-android.a",
- "-Wl,--exclude-libs=libclang_rt.builtins-x86_64-android.a",
- ] + select({
- "//build/bazel/platforms/arch:x86": ["-Wl,--exclude-libs=libgcc_eh.a"],
- "//build/bazel/platforms/arch:x86_64": ["-Wl,--exclude-libs=libgcc_eh.a"],
- "//conditions:default": [],
- })`,
- }),
- })
-}
-
-func TestCcLibraryExcludeSrcs(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library exclude_srcs - trimmed example of //external/arm-optimized-routines:libarm-optimized-routines-math",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Dir: "external",
- Filesystem: map[string]string{
- "external/math/cosf.c": "",
- "external/math/erf.c": "",
- "external/math/erf_data.c": "",
- "external/math/erff.c": "",
- "external/math/erff_data.c": "",
- "external/Android.bp": `
-cc_library {
- name: "fake-libarm-optimized-routines-math",
- exclude_srcs: [
- // Provided by:
- // bionic/libm/upstream-freebsd/lib/msun/src/s_erf.c
- // bionic/libm/upstream-freebsd/lib/msun/src/s_erff.c
- "math/erf.c",
- "math/erf_data.c",
- "math/erff.c",
- "math/erff_data.c",
- ],
- srcs: [
- "math/*.c",
- ],
- // arch-specific settings
- arch: {
- arm64: {
- cflags: [
- "-DHAVE_FAST_FMA=1",
- ],
- },
- },
- bazel_module: { bp2build_available: true },
-}
-`,
- },
- Blueprint: soongCcLibraryPreamble,
- ExpectedBazelTargets: makeCcLibraryTargets("fake-libarm-optimized-routines-math", AttrNameToString{
- "copts": `select({
- "//build/bazel/platforms/arch:arm64": ["-DHAVE_FAST_FMA=1"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- "srcs_c": `["math/cosf.c"]`,
- }),
- })
-}
-
-func TestCcLibrarySharedStaticProps(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library shared/static props",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "both.cpp": "",
- "sharedonly.cpp": "",
- "staticonly.cpp": "",
- },
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "a",
- srcs: ["both.cpp"],
- cflags: ["bothflag"],
- shared_libs: ["shared_dep_for_both"],
- static_libs: ["static_dep_for_both", "whole_and_static_lib_for_both"],
- whole_static_libs: ["whole_static_lib_for_both", "whole_and_static_lib_for_both"],
- static: {
- srcs: ["staticonly.cpp"],
- cflags: ["staticflag"],
- shared_libs: ["shared_dep_for_static"],
- static_libs: ["static_dep_for_static"],
- whole_static_libs: ["whole_static_lib_for_static"],
- },
- shared: {
- srcs: ["sharedonly.cpp"],
- cflags: ["sharedflag"],
- shared_libs: ["shared_dep_for_shared"],
- static_libs: ["static_dep_for_shared"],
- whole_static_libs: ["whole_static_lib_for_shared"],
- },
- include_build_directory: false,
-}
-
-cc_library_static {
- name: "static_dep_for_shared",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "static_dep_for_static",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "static_dep_for_both",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "whole_static_lib_for_shared",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "whole_static_lib_for_static",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "whole_static_lib_for_both",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "whole_and_static_lib_for_both",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "shared_dep_for_shared",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "shared_dep_for_static",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "shared_dep_for_both",
- bazel_module: { bp2build_available: false },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
- "copts": `[
- "bothflag",
- "staticflag",
- ]`,
- "implementation_deps": `[
- ":static_dep_for_both",
- ":static_dep_for_static",
- ]`,
- "implementation_dynamic_deps": `[
- ":shared_dep_for_both",
- ":shared_dep_for_static",
- ]`,
- "srcs": `[
- "both.cpp",
- "staticonly.cpp",
- ]`,
- "whole_archive_deps": `[
- ":whole_static_lib_for_both",
- ":whole_and_static_lib_for_both",
- ":whole_static_lib_for_static",
- ]`}),
- MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
- "copts": `[
- "bothflag",
- "sharedflag",
- ]`,
- "implementation_deps": `[
- ":static_dep_for_both",
- ":static_dep_for_shared",
- ]`,
- "implementation_dynamic_deps": `[
- ":shared_dep_for_both",
- ":shared_dep_for_shared",
- ]`,
- "srcs": `[
- "both.cpp",
- "sharedonly.cpp",
- ]`,
- "whole_archive_deps": `[
- ":whole_static_lib_for_both",
- ":whole_and_static_lib_for_both",
- ":whole_static_lib_for_shared",
- ]`,
- }),
- },
- })
-}
-
-func TestCcLibraryDeps(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library shared/static props",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "both.cpp": "",
- "sharedonly.cpp": "",
- "staticonly.cpp": "",
- },
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "a",
- srcs: ["both.cpp"],
- cflags: ["bothflag"],
- shared_libs: ["implementation_shared_dep_for_both", "shared_dep_for_both"],
- export_shared_lib_headers: ["shared_dep_for_both"],
- static_libs: ["implementation_static_dep_for_both", "static_dep_for_both"],
- export_static_lib_headers: ["static_dep_for_both", "whole_static_dep_for_both"],
- whole_static_libs: ["not_explicitly_exported_whole_static_dep_for_both", "whole_static_dep_for_both"],
- static: {
- srcs: ["staticonly.cpp"],
- cflags: ["staticflag"],
- shared_libs: ["implementation_shared_dep_for_static", "shared_dep_for_static"],
- export_shared_lib_headers: ["shared_dep_for_static"],
- static_libs: ["implementation_static_dep_for_static", "static_dep_for_static"],
- export_static_lib_headers: ["static_dep_for_static", "whole_static_dep_for_static"],
- whole_static_libs: ["not_explicitly_exported_whole_static_dep_for_static", "whole_static_dep_for_static"],
- },
- shared: {
- srcs: ["sharedonly.cpp"],
- cflags: ["sharedflag"],
- shared_libs: ["implementation_shared_dep_for_shared", "shared_dep_for_shared"],
- export_shared_lib_headers: ["shared_dep_for_shared"],
- static_libs: ["implementation_static_dep_for_shared", "static_dep_for_shared"],
- export_static_lib_headers: ["static_dep_for_shared", "whole_static_dep_for_shared"],
- whole_static_libs: ["not_explicitly_exported_whole_static_dep_for_shared", "whole_static_dep_for_shared"],
- },
- include_build_directory: false,
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep_for_shared") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep_for_shared") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep_for_static") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep_for_static") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep_for_both") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep_for_both") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep_for_shared") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep_for_shared") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep_for_static") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep_for_static") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep_for_both") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep_for_both") +
- simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_shared") +
- simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_shared") +
- simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_static") +
- simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_static") +
- simpleModuleDoNotConvertBp2build("cc_library", "shared_dep_for_both") +
- simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep_for_both"),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
- "copts": `[
- "bothflag",
- "staticflag",
- ]`,
- "deps": `[
- ":static_dep_for_both",
- ":static_dep_for_static",
- ]`,
- "dynamic_deps": `[
- ":shared_dep_for_both",
- ":shared_dep_for_static",
- ]`,
- "implementation_deps": `[
- ":implementation_static_dep_for_both",
- ":implementation_static_dep_for_static",
- ]`,
- "implementation_dynamic_deps": `[
- ":implementation_shared_dep_for_both",
- ":implementation_shared_dep_for_static",
- ]`,
- "srcs": `[
- "both.cpp",
- "staticonly.cpp",
- ]`,
- "whole_archive_deps": `[
- ":not_explicitly_exported_whole_static_dep_for_both",
- ":whole_static_dep_for_both",
- ":not_explicitly_exported_whole_static_dep_for_static",
- ":whole_static_dep_for_static",
- ]`,
- }),
- MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
- "copts": `[
- "bothflag",
- "sharedflag",
- ]`,
- "deps": `[
- ":static_dep_for_both",
- ":static_dep_for_shared",
- ]`,
- "dynamic_deps": `[
- ":shared_dep_for_both",
- ":shared_dep_for_shared",
- ]`,
- "implementation_deps": `[
- ":implementation_static_dep_for_both",
- ":implementation_static_dep_for_shared",
- ]`,
- "implementation_dynamic_deps": `[
- ":implementation_shared_dep_for_both",
- ":implementation_shared_dep_for_shared",
- ]`,
- "srcs": `[
- "both.cpp",
- "sharedonly.cpp",
- ]`,
- "whole_archive_deps": `[
- ":not_explicitly_exported_whole_static_dep_for_both",
- ":whole_static_dep_for_both",
- ":not_explicitly_exported_whole_static_dep_for_shared",
- ":whole_static_dep_for_shared",
- ]`,
- })},
- },
- )
-}
-
-func TestCcLibraryWholeStaticLibsAlwaysLink(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Dir: "foo/bar",
- Filesystem: map[string]string{
- "foo/bar/Android.bp": `
-cc_library {
- name: "a",
- whole_static_libs: ["whole_static_lib_for_both"],
- static: {
- whole_static_libs: ["whole_static_lib_for_static"],
- },
- shared: {
- whole_static_libs: ["whole_static_lib_for_shared"],
- },
- bazel_module: { bp2build_available: true },
- include_build_directory: false,
-}
-
-cc_prebuilt_library_static { name: "whole_static_lib_for_shared" }
-
-cc_prebuilt_library_static { name: "whole_static_lib_for_static" }
-
-cc_prebuilt_library_static { name: "whole_static_lib_for_both" }
-`,
- },
- Blueprint: soongCcLibraryPreamble,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
- "whole_archive_deps": `[
- ":whole_static_lib_for_both_alwayslink",
- ":whole_static_lib_for_static_alwayslink",
- ]`,
- }),
- MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
- "whole_archive_deps": `[
- ":whole_static_lib_for_both_alwayslink",
- ":whole_static_lib_for_shared_alwayslink",
- ]`,
- }),
- },
- },
- )
-}
-
-func TestCcLibrarySharedStaticPropsInArch(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library shared/static props in arch",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Dir: "foo/bar",
- Filesystem: map[string]string{
- "foo/bar/arm.cpp": "",
- "foo/bar/x86.cpp": "",
- "foo/bar/sharedonly.cpp": "",
- "foo/bar/staticonly.cpp": "",
- "foo/bar/Android.bp": `
-cc_library {
- name: "a",
- arch: {
- arm: {
- shared: {
- srcs: ["arm_shared.cpp"],
- cflags: ["-DARM_SHARED"],
- static_libs: ["arm_static_dep_for_shared"],
- whole_static_libs: ["arm_whole_static_dep_for_shared"],
- shared_libs: ["arm_shared_dep_for_shared"],
- },
- },
- x86: {
- static: {
- srcs: ["x86_static.cpp"],
- cflags: ["-DX86_STATIC"],
- static_libs: ["x86_dep_for_static"],
- },
- },
- },
- target: {
- android: {
- shared: {
- srcs: ["android_shared.cpp"],
- cflags: ["-DANDROID_SHARED"],
- static_libs: ["android_dep_for_shared"],
- },
- },
- android_arm: {
- shared: {
- cflags: ["-DANDROID_ARM_SHARED"],
- },
- },
- },
- srcs: ["both.cpp"],
- cflags: ["bothflag"],
- static_libs: ["static_dep_for_both"],
- static: {
- srcs: ["staticonly.cpp"],
- cflags: ["staticflag"],
- static_libs: ["static_dep_for_static"],
- },
- shared: {
- srcs: ["sharedonly.cpp"],
- cflags: ["sharedflag"],
- static_libs: ["static_dep_for_shared"],
- },
- bazel_module: { bp2build_available: true },
-}
-
-cc_library_static { name: "static_dep_for_shared" }
-cc_library_static { name: "static_dep_for_static" }
-cc_library_static { name: "static_dep_for_both" }
-
-cc_library_static { name: "arm_static_dep_for_shared" }
-cc_library_static { name: "arm_whole_static_dep_for_shared" }
-cc_library_static { name: "arm_shared_dep_for_shared" }
-
-cc_library_static { name: "x86_dep_for_static" }
-
-cc_library_static { name: "android_dep_for_shared" }
-`,
- },
- Blueprint: soongCcLibraryPreamble,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
- "copts": `[
- "bothflag",
- "staticflag",
- ] + select({
- "//build/bazel/platforms/arch:x86": ["-DX86_STATIC"],
- "//conditions:default": [],
- })`,
- "implementation_deps": `[
- ":static_dep_for_both",
- ":static_dep_for_static",
- ] + select({
- "//build/bazel/platforms/arch:x86": [":x86_dep_for_static"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- "srcs": `[
- "both.cpp",
- "staticonly.cpp",
- ] + select({
- "//build/bazel/platforms/arch:x86": ["x86_static.cpp"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
- "copts": `[
- "bothflag",
- "sharedflag",
- ] + select({
- "//build/bazel/platforms/arch:arm": ["-DARM_SHARED"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os:android": ["-DANDROID_SHARED"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os_arch:android_arm": ["-DANDROID_ARM_SHARED"],
- "//conditions:default": [],
- })`,
- "implementation_deps": `[
- ":static_dep_for_both",
- ":static_dep_for_shared",
- ] + select({
- "//build/bazel/platforms/arch:arm": [":arm_static_dep_for_shared"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os:android": [":android_dep_for_shared"],
- "//conditions:default": [],
- })`,
- "implementation_dynamic_deps": `select({
- "//build/bazel/platforms/arch:arm": [":arm_shared_dep_for_shared"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- "srcs": `[
- "both.cpp",
- "sharedonly.cpp",
- ] + select({
- "//build/bazel/platforms/arch:arm": ["arm_shared.cpp"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os:android": ["android_shared.cpp"],
- "//conditions:default": [],
- })`,
- "whole_archive_deps": `select({
- "//build/bazel/platforms/arch:arm": [":arm_whole_static_dep_for_shared"],
- "//conditions:default": [],
- })`,
- }),
- },
- },
- )
-}
-
-func TestCcLibrarySharedStaticPropsWithMixedSources(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library shared/static props with c/cpp/s mixed sources",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Dir: "foo/bar",
- Filesystem: map[string]string{
- "foo/bar/both_source.cpp": "",
- "foo/bar/both_source.cc": "",
- "foo/bar/both_source.c": "",
- "foo/bar/both_source.s": "",
- "foo/bar/both_source.S": "",
- "foo/bar/shared_source.cpp": "",
- "foo/bar/shared_source.cc": "",
- "foo/bar/shared_source.c": "",
- "foo/bar/shared_source.s": "",
- "foo/bar/shared_source.S": "",
- "foo/bar/static_source.cpp": "",
- "foo/bar/static_source.cc": "",
- "foo/bar/static_source.c": "",
- "foo/bar/static_source.s": "",
- "foo/bar/static_source.S": "",
- "foo/bar/Android.bp": `
-cc_library {
- name: "a",
- srcs: [
- "both_source.cpp",
- "both_source.cc",
- "both_source.c",
- "both_source.s",
- "both_source.S",
- ":both_filegroup",
- ],
- static: {
- srcs: [
- "static_source.cpp",
- "static_source.cc",
- "static_source.c",
- "static_source.s",
- "static_source.S",
- ":static_filegroup",
- ],
- },
- shared: {
- srcs: [
- "shared_source.cpp",
- "shared_source.cc",
- "shared_source.c",
- "shared_source.s",
- "shared_source.S",
- ":shared_filegroup",
- ],
- },
- bazel_module: { bp2build_available: true },
-}
-
-filegroup {
- name: "both_filegroup",
- srcs: [
- // Not relevant, handled by filegroup macro
- ],
-}
-
-filegroup {
- name: "shared_filegroup",
- srcs: [
- // Not relevant, handled by filegroup macro
- ],
-}
-
-filegroup {
- name: "static_filegroup",
- srcs: [
- // Not relevant, handled by filegroup macro
- ],
-}
-`,
- },
- Blueprint: soongCcLibraryPreamble,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `[
- "both_source.cpp",
- "both_source.cc",
- ":both_filegroup_cpp_srcs",
- "static_source.cpp",
- "static_source.cc",
- ":static_filegroup_cpp_srcs",
- ]`,
- "srcs_as": `[
- "both_source.s",
- "both_source.S",
- ":both_filegroup_as_srcs",
- "static_source.s",
- "static_source.S",
- ":static_filegroup_as_srcs",
- ]`,
- "srcs_c": `[
- "both_source.c",
- ":both_filegroup_c_srcs",
- "static_source.c",
- ":static_filegroup_c_srcs",
- ]`,
- }),
- MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `[
- "both_source.cpp",
- "both_source.cc",
- ":both_filegroup_cpp_srcs",
- "shared_source.cpp",
- "shared_source.cc",
- ":shared_filegroup_cpp_srcs",
- ]`,
- "srcs_as": `[
- "both_source.s",
- "both_source.S",
- ":both_filegroup_as_srcs",
- "shared_source.s",
- "shared_source.S",
- ":shared_filegroup_as_srcs",
- ]`,
- "srcs_c": `[
- "both_source.c",
- ":both_filegroup_c_srcs",
- "shared_source.c",
- ":shared_filegroup_c_srcs",
- ]`,
- })}})
-}
-
-func TestCcLibraryNonConfiguredVersionScriptAndDynamicList(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library non-configured version script and dynamic list",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Dir: "foo/bar",
- Filesystem: map[string]string{
- "foo/bar/Android.bp": `
-cc_library {
- name: "a",
- srcs: ["a.cpp"],
- version_script: "v.map",
- dynamic_list: "dynamic.list",
- bazel_module: { bp2build_available: true },
- include_build_directory: false,
-}
-`,
- },
- Blueprint: soongCcLibraryPreamble,
- ExpectedBazelTargets: makeCcLibraryTargets("a", AttrNameToString{
- "additional_linker_inputs": `[
- "v.map",
- "dynamic.list",
- ]`,
- "linkopts": `[
- "-Wl,--version-script,$(location v.map)",
- "-Wl,--dynamic-list,$(location dynamic.list)",
- ]`,
- "srcs": `["a.cpp"]`,
- "features": `["android_cfi_exports_map"]`,
- }),
- },
- )
-}
-
-func TestCcLibraryConfiguredVersionScriptAndDynamicList(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library configured version script and dynamic list",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Dir: "foo/bar",
- Filesystem: map[string]string{
- "foo/bar/Android.bp": `
-cc_library {
- name: "a",
- srcs: ["a.cpp"],
- arch: {
- arm: {
- version_script: "arm.map",
- dynamic_list: "dynamic_arm.list",
- },
- arm64: {
- version_script: "arm64.map",
- dynamic_list: "dynamic_arm64.list",
- },
- },
-
- bazel_module: { bp2build_available: true },
- include_build_directory: false,
-}
- `,
- },
- Blueprint: soongCcLibraryPreamble,
- ExpectedBazelTargets: makeCcLibraryTargets("a", AttrNameToString{
- "additional_linker_inputs": `select({
- "//build/bazel/platforms/arch:arm": [
- "arm.map",
- "dynamic_arm.list",
- ],
- "//build/bazel/platforms/arch:arm64": [
- "arm64.map",
- "dynamic_arm64.list",
- ],
- "//conditions:default": [],
- })`,
- "linkopts": `select({
- "//build/bazel/platforms/arch:arm": [
- "-Wl,--version-script,$(location arm.map)",
- "-Wl,--dynamic-list,$(location dynamic_arm.list)",
- ],
- "//build/bazel/platforms/arch:arm64": [
- "-Wl,--version-script,$(location arm64.map)",
- "-Wl,--dynamic-list,$(location dynamic_arm64.list)",
- ],
- "//conditions:default": [],
- })`,
- "srcs": `["a.cpp"]`,
- "features": `select({
- "//build/bazel/platforms/arch:arm": ["android_cfi_exports_map"],
- "//build/bazel/platforms/arch:arm64": ["android_cfi_exports_map"],
- "//conditions:default": [],
- })`,
- }),
- },
- )
-}
-
-func TestCcLibraryLdflagsSplitBySpaceExceptSoongAdded(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "ldflags are split by spaces except for the ones added by soong (version script and dynamic list)",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "version_script": "",
- "dynamic.list": "",
- },
- Blueprint: `
-cc_library {
- name: "foo",
- ldflags: [
- "--nospace_flag",
- "-z spaceflag",
- ],
- version_script: "version_script",
- dynamic_list: "dynamic.list",
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "features": `["android_cfi_exports_map"]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "additional_linker_inputs": `[
- "version_script",
- "dynamic.list",
- ]`,
- "features": `["android_cfi_exports_map"]`,
- "linkopts": `[
- "--nospace_flag",
- "-z",
- "spaceflag",
- "-Wl,--version-script,$(location version_script)",
- "-Wl,--dynamic-list,$(location dynamic.list)",
- ]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedLibs(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library shared_libs",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "mylib",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "a",
- shared_libs: ["mylib",],
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("a", AttrNameToString{
- "implementation_dynamic_deps": `[":mylib"]`,
- }),
- },
- )
-}
-
-func TestCcLibraryFeatures(t *testing.T) {
- expected_targets := []string{}
- expected_targets = append(expected_targets, makeCcLibraryTargets("a", AttrNameToString{
- "features": `[
- "disable_pack_relocations",
- "-no_undefined_symbols",
- ]`,
- "native_coverage": `False`,
- "srcs": `["a.cpp"]`,
- })...)
- expected_targets = append(expected_targets, makeCcLibraryTargets("b", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/arch:x86_64": [
- "disable_pack_relocations",
- "-no_undefined_symbols",
- ],
- "//conditions:default": [],
- })`,
- "native_coverage": `False`,
- "srcs": `["b.cpp"]`,
- })...)
- expected_targets = append(expected_targets, makeCcLibraryTargets("c", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/os:darwin": [
- "disable_pack_relocations",
- "-no_undefined_symbols",
- ],
- "//conditions:default": [],
- })`,
- "srcs": `["c.cpp"]`,
- })...)
-
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library pack_relocations test",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "a",
- srcs: ["a.cpp"],
- pack_relocations: false,
- allow_undefined_symbols: true,
- include_build_directory: false,
- native_coverage: false,
-}
-
-cc_library {
- name: "b",
- srcs: ["b.cpp"],
- arch: {
- x86_64: {
- pack_relocations: false,
- allow_undefined_symbols: true,
- },
- },
- include_build_directory: false,
- native_coverage: false,
-}
-
-cc_library {
- name: "c",
- srcs: ["c.cpp"],
- target: {
- darwin: {
- pack_relocations: false,
- allow_undefined_symbols: true,
- },
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: expected_targets,
- })
-}
-
-func TestCcLibrarySpacesInCopts(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library spaces in copts",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "a",
- cflags: ["-include header.h",],
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("a", AttrNameToString{
- "copts": `[
- "-include",
- "header.h",
- ]`,
- }),
- },
- )
-}
-
-func TestCcLibraryCppFlagsGoesIntoCopts(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library cppflags usage",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `cc_library {
- name: "a",
- srcs: ["a.cpp"],
- cflags: ["-Wall"],
- cppflags: [
- "-fsigned-char",
- "-pedantic",
- ],
- arch: {
- arm64: {
- cppflags: ["-DARM64=1"],
- },
- },
- target: {
- android: {
- cppflags: ["-DANDROID=1"],
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("a", AttrNameToString{
- "copts": `["-Wall"]`,
- "cppflags": `[
- "-fsigned-char",
- "-pedantic",
- ] + select({
- "//build/bazel/platforms/arch:arm64": ["-DARM64=1"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os:android": ["-DANDROID=1"],
- "//conditions:default": [],
- })`,
- "srcs": `["a.cpp"]`,
- }),
- },
- )
-}
-
-func TestCcLibraryExcludeLibs(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library {
- name: "foo_static",
- srcs: ["common.c"],
- whole_static_libs: [
- "arm_whole_static_lib_excludes",
- "malloc_not_svelte_whole_static_lib_excludes"
- ],
- static_libs: [
- "arm_static_lib_excludes",
- "malloc_not_svelte_static_lib_excludes"
- ],
- shared_libs: [
- "arm_shared_lib_excludes",
- ],
- arch: {
- arm: {
- exclude_shared_libs: [
- "arm_shared_lib_excludes",
- ],
- exclude_static_libs: [
- "arm_static_lib_excludes",
- "arm_whole_static_lib_excludes",
- ],
- },
- },
- product_variables: {
- malloc_not_svelte: {
- shared_libs: ["malloc_not_svelte_shared_lib"],
- whole_static_libs: ["malloc_not_svelte_whole_static_lib"],
- exclude_static_libs: [
- "malloc_not_svelte_static_lib_excludes",
- "malloc_not_svelte_whole_static_lib_excludes",
- ],
- },
- },
- include_build_directory: false,
-}
-
-cc_library {
- name: "arm_whole_static_lib_excludes",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "malloc_not_svelte_whole_static_lib",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "malloc_not_svelte_whole_static_lib_excludes",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "arm_static_lib_excludes",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "malloc_not_svelte_static_lib_excludes",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "arm_shared_lib_excludes",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "malloc_not_svelte_shared_lib",
- bazel_module: { bp2build_available: false },
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo_static", AttrNameToString{
- "implementation_deps": `select({
- "//build/bazel/platforms/arch:arm": [],
- "//conditions:default": [":arm_static_lib_excludes_bp2build_cc_library_static"],
- }) + select({
- "//build/bazel/product_config/config_settings:malloc_not_svelte": [],
- "//conditions:default": [":malloc_not_svelte_static_lib_excludes_bp2build_cc_library_static"],
- })`,
- "implementation_dynamic_deps": `select({
- "//build/bazel/platforms/arch:arm": [],
- "//conditions:default": [":arm_shared_lib_excludes"],
- }) + select({
- "//build/bazel/product_config/config_settings:malloc_not_svelte": [":malloc_not_svelte_shared_lib"],
- "//conditions:default": [],
- })`,
- "srcs_c": `["common.c"]`,
- "whole_archive_deps": `select({
- "//build/bazel/platforms/arch:arm": [],
- "//conditions:default": [":arm_whole_static_lib_excludes_bp2build_cc_library_static"],
- }) + select({
- "//build/bazel/product_config/config_settings:malloc_not_svelte": [":malloc_not_svelte_whole_static_lib_bp2build_cc_library_static"],
- "//conditions:default": [":malloc_not_svelte_whole_static_lib_excludes_bp2build_cc_library_static"],
- })`,
- }),
- },
- )
-}
-
-func TestCcLibraryProductVariablesHeaderLibs(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library {
- name: "foo_static",
- srcs: ["common.c"],
- product_variables: {
- malloc_not_svelte: {
- header_libs: ["malloc_not_svelte_header_lib"],
- },
- },
- include_build_directory: false,
-}
-
-cc_library {
- name: "malloc_not_svelte_header_lib",
- bazel_module: { bp2build_available: false },
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo_static", AttrNameToString{
- "implementation_deps": `select({
- "//build/bazel/product_config/config_settings:malloc_not_svelte": [":malloc_not_svelte_header_lib"],
- "//conditions:default": [],
- })`,
- "srcs_c": `["common.c"]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- }),
- },
- )
-}
-
-func TestCCLibraryNoCrtTrue(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library - nocrt: true disables feature",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "impl.cpp": "",
- },
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "foo-lib",
- srcs: ["impl.cpp"],
- nocrt: true,
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo-lib", AttrNameToString{
- "features": `["-link_crt"]`,
- "srcs": `["impl.cpp"]`,
- }),
- },
- )
-}
-
-func TestCCLibraryNoCrtFalse(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library - nocrt: false - does not emit attribute",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "impl.cpp": "",
- },
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "foo-lib",
- srcs: ["impl.cpp"],
- nocrt: false,
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo-lib", AttrNameToString{
- "srcs": `["impl.cpp"]`,
- }),
- })
-}
-
-func TestCCLibraryNoCrtArchVariant(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library - nocrt in select",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "impl.cpp": "",
- },
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "foo-lib",
- srcs: ["impl.cpp"],
- arch: {
- arm: {
- nocrt: true,
- },
- x86: {
- nocrt: false,
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo-lib", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/arch:arm": ["-link_crt"],
- "//conditions:default": [],
- })`,
- "srcs": `["impl.cpp"]`,
- }),
- })
-}
-
-func TestCCLibraryNoLibCrtTrue(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "impl.cpp": "",
- },
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "foo-lib",
- srcs: ["impl.cpp"],
- no_libcrt: true,
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo-lib", AttrNameToString{
- "features": `["-use_libcrt"]`,
- "srcs": `["impl.cpp"]`,
- }),
- })
-}
-
-func makeCcLibraryTargets(name string, attrs AttrNameToString) []string {
- STATIC_ONLY_ATTRS := map[string]bool{}
- SHARED_ONLY_ATTRS := map[string]bool{
- "link_crt": true,
- "additional_linker_inputs": true,
- "linkopts": true,
- "strip": true,
- "inject_bssl_hash": true,
- "stubs_symbol_file": true,
- "use_version_lib": true,
- }
-
- sharedAttrs := AttrNameToString{}
- staticAttrs := AttrNameToString{}
- for key, val := range attrs {
- if _, staticOnly := STATIC_ONLY_ATTRS[key]; !staticOnly {
- sharedAttrs[key] = val
- }
- if _, sharedOnly := SHARED_ONLY_ATTRS[key]; !sharedOnly {
- staticAttrs[key] = val
- }
- }
- sharedTarget := MakeBazelTarget("cc_library_shared", name, sharedAttrs)
- staticTarget := MakeBazelTarget("cc_library_static", name+"_bp2build_cc_library_static", staticAttrs)
-
- return []string{staticTarget, sharedTarget}
-}
-
-func TestCCLibraryNoLibCrtFalse(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "impl.cpp": "",
- },
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "foo-lib",
- srcs: ["impl.cpp"],
- no_libcrt: false,
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo-lib", AttrNameToString{
- "srcs": `["impl.cpp"]`,
- }),
- })
-}
-
-func TestCCLibraryNoLibCrtArchVariant(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "impl.cpp": "",
- },
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "foo-lib",
- srcs: ["impl.cpp"],
- arch: {
- arm: {
- no_libcrt: true,
- },
- x86: {
- no_libcrt: true,
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo-lib", AttrNameToString{
- "srcs": `["impl.cpp"]`,
- "features": `select({
- "//build/bazel/platforms/arch:arm": ["-use_libcrt"],
- "//build/bazel/platforms/arch:x86": ["-use_libcrt"],
- "//conditions:default": [],
- })`,
- }),
- })
-}
-
-func TestCCLibraryNoLibCrtArchAndTargetVariant(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "impl.cpp": "",
- },
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "foo-lib",
- srcs: ["impl.cpp"],
- arch: {
- arm: {
- no_libcrt: true,
- },
- x86: {
- no_libcrt: true,
- },
- },
- target: {
- darwin: {
- no_libcrt: true,
- }
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo-lib", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/arch:arm": ["-use_libcrt"],
- "//build/bazel/platforms/arch:x86": ["-use_libcrt"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os:darwin": ["-use_libcrt"],
- "//conditions:default": [],
- })`,
- "srcs": `["impl.cpp"]`,
- }),
- })
-}
-
-func TestCCLibraryNoLibCrtArchAndTargetVariantConflict(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "impl.cpp": "",
- },
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "foo-lib",
- srcs: ["impl.cpp"],
- arch: {
- arm: {
- no_libcrt: true,
- },
- // This is expected to override the value for darwin_x86_64.
- x86_64: {
- no_libcrt: true,
- },
- },
- target: {
- darwin: {
- no_libcrt: false,
- }
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo-lib", AttrNameToString{
- "srcs": `["impl.cpp"]`,
- "features": `select({
- "//build/bazel/platforms/arch:arm": ["-use_libcrt"],
- "//build/bazel/platforms/arch:x86_64": ["-use_libcrt"],
- "//conditions:default": [],
- })`,
- }),
- })
-}
-
-func TestCcLibraryStrip(t *testing.T) {
- expectedTargets := []string{}
- expectedTargets = append(expectedTargets, makeCcLibraryTargets("all", AttrNameToString{
- "strip": `{
- "all": True,
- }`,
- })...)
- expectedTargets = append(expectedTargets, makeCcLibraryTargets("keep_symbols", AttrNameToString{
- "strip": `{
- "keep_symbols": True,
- }`,
- })...)
- expectedTargets = append(expectedTargets, makeCcLibraryTargets("keep_symbols_and_debug_frame", AttrNameToString{
- "strip": `{
- "keep_symbols_and_debug_frame": True,
- }`,
- })...)
- expectedTargets = append(expectedTargets, makeCcLibraryTargets("keep_symbols_list", AttrNameToString{
- "strip": `{
- "keep_symbols_list": ["symbol"],
- }`,
- })...)
- expectedTargets = append(expectedTargets, makeCcLibraryTargets("none", AttrNameToString{
- "strip": `{
- "none": True,
- }`,
- })...)
- expectedTargets = append(expectedTargets, makeCcLibraryTargets("nothing", AttrNameToString{})...)
-
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library strip args",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "nothing",
- include_build_directory: false,
-}
-cc_library {
- name: "keep_symbols",
- strip: {
- keep_symbols: true,
- },
- include_build_directory: false,
-}
-cc_library {
- name: "keep_symbols_and_debug_frame",
- strip: {
- keep_symbols_and_debug_frame: true,
- },
- include_build_directory: false,
-}
-cc_library {
- name: "none",
- strip: {
- none: true,
- },
- include_build_directory: false,
-}
-cc_library {
- name: "keep_symbols_list",
- strip: {
- keep_symbols_list: ["symbol"],
- },
- include_build_directory: false,
-}
-cc_library {
- name: "all",
- strip: {
- all: true,
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: expectedTargets,
- })
-}
-
-func TestCcLibraryStripWithArch(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library strip args",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "multi-arch",
- target: {
- darwin: {
- strip: {
- keep_symbols_list: ["foo", "bar"]
- }
- },
- },
- arch: {
- arm: {
- strip: {
- keep_symbols_and_debug_frame: true,
- },
- },
- arm64: {
- strip: {
- keep_symbols: true,
- },
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("multi-arch", AttrNameToString{
- "strip": `{
- "keep_symbols": select({
- "//build/bazel/platforms/arch:arm64": True,
- "//conditions:default": None,
- }),
- "keep_symbols_and_debug_frame": select({
- "//build/bazel/platforms/arch:arm": True,
- "//conditions:default": None,
- }),
- "keep_symbols_list": select({
- "//build/bazel/platforms/os:darwin": [
- "foo",
- "bar",
- ],
- "//conditions:default": [],
- }),
- }`,
- }),
- },
- )
-}
-
-func TestCcLibrary_SystemSharedLibsRootEmpty(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library system_shared_libs empty at root",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "root_empty",
- system_shared_libs: [],
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("root_empty", AttrNameToString{
- "system_dynamic_deps": `[]`,
- }),
- },
- )
-}
-
-func TestCcLibrary_SystemSharedLibsStaticEmpty(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library system_shared_libs empty for static variant",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "static_empty",
- static: {
- system_shared_libs: [],
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "static_empty_bp2build_cc_library_static", AttrNameToString{
- "system_dynamic_deps": "[]",
- }),
- MakeBazelTarget("cc_library_shared", "static_empty", AttrNameToString{}),
- },
- })
-}
-
-func TestCcLibrary_SystemSharedLibsSharedEmpty(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library system_shared_libs empty for shared variant",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "shared_empty",
- shared: {
- system_shared_libs: [],
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "shared_empty_bp2build_cc_library_static", AttrNameToString{}),
- MakeBazelTarget("cc_library_shared", "shared_empty", AttrNameToString{
- "system_dynamic_deps": "[]",
- }),
- },
- })
-}
-
-func TestCcLibrary_SystemSharedLibsSharedBionicEmpty(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library system_shared_libs empty for shared, bionic variant",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "shared_empty",
- target: {
- bionic: {
- shared: {
- system_shared_libs: [],
- }
- }
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "shared_empty_bp2build_cc_library_static", AttrNameToString{}),
- MakeBazelTarget("cc_library_shared", "shared_empty", AttrNameToString{
- "system_dynamic_deps": "[]",
- }),
- },
- })
-}
-
-func TestCcLibrary_SystemSharedLibsLinuxBionicEmpty(t *testing.T) {
- // Note that this behavior is technically incorrect (it's a simplification).
- // The correct behavior would be if bp2build wrote `system_dynamic_deps = []`
- // only for linux_bionic, but `android` had `["libc", "libdl", "libm"].
- // b/195791252 tracks the fix.
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library system_shared_libs empty for linux_bionic variant",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "libc_musl",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "target_linux_bionic_empty",
- target: {
- linux_bionic: {
- system_shared_libs: [],
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("target_linux_bionic_empty", AttrNameToString{
- "system_dynamic_deps": `select({
- "//build/bazel/platforms/os:linux_musl": [":libc_musl"],
- "//conditions:default": [],
- })`,
- }),
- },
- )
-}
-
-func TestCcLibrary_SystemSharedLibsBionicEmpty(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library system_shared_libs empty for bionic variant",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "libc_musl",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "target_bionic_empty",
- target: {
- bionic: {
- system_shared_libs: [],
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("target_bionic_empty", AttrNameToString{
- "system_dynamic_deps": `select({
- "//build/bazel/platforms/os:linux_musl": [":libc_musl"],
- "//conditions:default": [],
- })`,
- }),
- },
- )
-}
-
-func TestCcLibrary_SystemSharedLibsMuslEmpty(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library system_shared_lib empty for musl variant",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "libc_musl",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "target_musl_empty",
- target: {
- musl: {
- system_shared_libs: [],
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("target_musl_empty", AttrNameToString{
- "system_dynamic_deps": `[]`,
- }),
- })
-}
-
-func TestCcLibrary_SystemSharedLibsLinuxMuslEmpty(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library system_shared_lib empty for linux_musl variant",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "libc_musl",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "target_linux_musl_empty",
- target: {
- linux_musl: {
- system_shared_libs: [],
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("target_linux_musl_empty", AttrNameToString{
- "system_dynamic_deps": `[]`,
- }),
- })
-}
-func TestCcLibrary_SystemSharedLibsSharedAndRoot(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library system_shared_libs set for shared and root",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "libc",
- bazel_module: { bp2build_available: false },
-}
-cc_library {
- name: "libm",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library {
- name: "foo",
- system_shared_libs: ["libc"],
- shared: {
- system_shared_libs: ["libm"],
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "system_dynamic_deps": `[":libc"]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "system_dynamic_deps": `[
- ":libc",
- ":libm",
- ]`,
- }),
- },
- })
-}
-
-func TestCcLibraryOsSelects(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library - selects for all os targets",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "foo-lib",
- srcs: ["base.cpp"],
- target: {
- android: {
- srcs: ["android.cpp"],
- },
- linux: {
- srcs: ["linux.cpp"],
- },
- linux_glibc: {
- srcs: ["linux_glibc.cpp"],
- },
- darwin: {
- srcs: ["darwin.cpp"],
- },
- bionic: {
- srcs: ["bionic.cpp"],
- },
- linux_musl: {
- srcs: ["linux_musl.cpp"],
- },
- windows: {
- srcs: ["windows.cpp"],
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo-lib", AttrNameToString{
- "srcs": `["base.cpp"] + select({
- "//build/bazel/platforms/os:android": [
- "linux.cpp",
- "bionic.cpp",
- "android.cpp",
- ],
- "//build/bazel/platforms/os:darwin": ["darwin.cpp"],
- "//build/bazel/platforms/os:linux_bionic": [
- "linux.cpp",
- "bionic.cpp",
- ],
- "//build/bazel/platforms/os:linux_glibc": [
- "linux.cpp",
- "linux_glibc.cpp",
- ],
- "//build/bazel/platforms/os:linux_musl": [
- "linux.cpp",
- "linux_musl.cpp",
- ],
- "//build/bazel/platforms/os:windows": ["windows.cpp"],
- "//conditions:default": [],
- })`,
- }),
- },
- )
-}
-
-func TestLibcryptoHashInjection(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library - libcrypto hash injection",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "libcrypto",
- target: {
- android: {
- inject_bssl_hash: true,
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("libcrypto", AttrNameToString{
- "inject_bssl_hash": `select({
- "//build/bazel/platforms/os:android": True,
- "//conditions:default": None,
- })`,
- }),
- },
- )
-}
-
-func TestCcLibraryCppStdWithGnuExtensions_ConvertsToFeatureAttr(t *testing.T) {
- type testCase struct {
- cpp_std string
- c_std string
- gnu_extensions string
- bazel_cpp_std string
- bazel_c_std string
- }
-
- testCases := []testCase{
- // Existing usages of cpp_std in AOSP are:
- // experimental, c++11, c++17, c++2a, c++98, gnu++11, gnu++17
- //
- // not set, only emit if gnu_extensions is disabled. the default (gnu+17
- // is set in the toolchain.)
- {cpp_std: "", gnu_extensions: "", bazel_cpp_std: ""},
- {cpp_std: "", gnu_extensions: "false", bazel_cpp_std: "cpp_std_default_no_gnu", bazel_c_std: "c_std_default_no_gnu"},
- {cpp_std: "", gnu_extensions: "true", bazel_cpp_std: ""},
- // experimental defaults to gnu++2a
- {cpp_std: "experimental", gnu_extensions: "", bazel_cpp_std: "cpp_std_experimental"},
- {cpp_std: "experimental", gnu_extensions: "false", bazel_cpp_std: "cpp_std_experimental_no_gnu", bazel_c_std: "c_std_default_no_gnu"},
- {cpp_std: "experimental", gnu_extensions: "true", bazel_cpp_std: "cpp_std_experimental"},
- // Explicitly setting a c++ std does not use replace gnu++ std even if
- // gnu_extensions is true.
- // "c++11",
- {cpp_std: "c++11", gnu_extensions: "", bazel_cpp_std: "c++11"},
- {cpp_std: "c++11", gnu_extensions: "false", bazel_cpp_std: "c++11", bazel_c_std: "c_std_default_no_gnu"},
- {cpp_std: "c++11", gnu_extensions: "true", bazel_cpp_std: "c++11"},
- // "c++17",
- {cpp_std: "c++17", gnu_extensions: "", bazel_cpp_std: "c++17"},
- {cpp_std: "c++17", gnu_extensions: "false", bazel_cpp_std: "c++17", bazel_c_std: "c_std_default_no_gnu"},
- {cpp_std: "c++17", gnu_extensions: "true", bazel_cpp_std: "c++17"},
- // "c++2a",
- {cpp_std: "c++2a", gnu_extensions: "", bazel_cpp_std: "c++2a"},
- {cpp_std: "c++2a", gnu_extensions: "false", bazel_cpp_std: "c++2a", bazel_c_std: "c_std_default_no_gnu"},
- {cpp_std: "c++2a", gnu_extensions: "true", bazel_cpp_std: "c++2a"},
- // "c++98",
- {cpp_std: "c++98", gnu_extensions: "", bazel_cpp_std: "c++98"},
- {cpp_std: "c++98", gnu_extensions: "false", bazel_cpp_std: "c++98", bazel_c_std: "c_std_default_no_gnu"},
- {cpp_std: "c++98", gnu_extensions: "true", bazel_cpp_std: "c++98"},
- // gnu++ is replaced with c++ if gnu_extensions is explicitly false.
- // "gnu++11",
- {cpp_std: "gnu++11", gnu_extensions: "", bazel_cpp_std: "gnu++11"},
- {cpp_std: "gnu++11", gnu_extensions: "false", bazel_cpp_std: "c++11", bazel_c_std: "c_std_default_no_gnu"},
- {cpp_std: "gnu++11", gnu_extensions: "true", bazel_cpp_std: "gnu++11"},
- // "gnu++17",
- {cpp_std: "gnu++17", gnu_extensions: "", bazel_cpp_std: "gnu++17"},
- {cpp_std: "gnu++17", gnu_extensions: "false", bazel_cpp_std: "c++17", bazel_c_std: "c_std_default_no_gnu"},
- {cpp_std: "gnu++17", gnu_extensions: "true", bazel_cpp_std: "gnu++17"},
-
- // some c_std test cases
- {c_std: "experimental", gnu_extensions: "", bazel_c_std: "c_std_experimental"},
- {c_std: "experimental", gnu_extensions: "false", bazel_cpp_std: "cpp_std_default_no_gnu", bazel_c_std: "c_std_experimental_no_gnu"},
- {c_std: "experimental", gnu_extensions: "true", bazel_c_std: "c_std_experimental"},
- {c_std: "gnu11", cpp_std: "gnu++17", gnu_extensions: "", bazel_cpp_std: "gnu++17", bazel_c_std: "gnu11"},
- {c_std: "gnu11", cpp_std: "gnu++17", gnu_extensions: "false", bazel_cpp_std: "c++17", bazel_c_std: "c11"},
- {c_std: "gnu11", cpp_std: "gnu++17", gnu_extensions: "true", bazel_cpp_std: "gnu++17", bazel_c_std: "gnu11"},
- }
- for i, tc := range testCases {
- name := fmt.Sprintf("cpp std: %q, c std: %q, gnu_extensions: %q", tc.cpp_std, tc.c_std, tc.gnu_extensions)
- t.Run(name, func(t *testing.T) {
- name_prefix := fmt.Sprintf("a_%v", i)
- cppStdProp := ""
- if tc.cpp_std != "" {
- cppStdProp = fmt.Sprintf(" cpp_std: \"%s\",", tc.cpp_std)
- }
- cStdProp := ""
- if tc.c_std != "" {
- cStdProp = fmt.Sprintf(" c_std: \"%s\",", tc.c_std)
- }
- gnuExtensionsProp := ""
- if tc.gnu_extensions != "" {
- gnuExtensionsProp = fmt.Sprintf(" gnu_extensions: %s,", tc.gnu_extensions)
- }
- attrs := AttrNameToString{}
- if tc.bazel_cpp_std != "" {
- attrs["cpp_std"] = fmt.Sprintf(`"%s"`, tc.bazel_cpp_std)
- }
- if tc.bazel_c_std != "" {
- attrs["c_std"] = fmt.Sprintf(`"%s"`, tc.bazel_c_std)
- }
-
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: fmt.Sprintf(
- "cc_library with cpp_std: %s and gnu_extensions: %s", tc.cpp_std, tc.gnu_extensions),
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + fmt.Sprintf(`
-cc_library {
- name: "%s_full",
-%s // cpp_std: *string
-%s // c_std: *string
-%s // gnu_extensions: *bool
- include_build_directory: false,
-}
-`, name_prefix, cppStdProp, cStdProp, gnuExtensionsProp),
- ExpectedBazelTargets: makeCcLibraryTargets(name_prefix+"_full", attrs),
- })
-
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: fmt.Sprintf(
- "cc_library_static with cpp_std: %s and gnu_extensions: %s", tc.cpp_std, tc.gnu_extensions),
- ModuleTypeUnderTest: "cc_library_static",
- ModuleTypeUnderTestFactory: cc.LibraryStaticFactory,
- Blueprint: soongCcLibraryPreamble + fmt.Sprintf(`
-cc_library_static {
- name: "%s_static",
-%s // cpp_std: *string
-%s // c_std: *string
-%s // gnu_extensions: *bool
- include_build_directory: false,
-}
-`, name_prefix, cppStdProp, cStdProp, gnuExtensionsProp),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", name_prefix+"_static", attrs),
- },
- })
-
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: fmt.Sprintf(
- "cc_library_shared with cpp_std: %s and gnu_extensions: %s", tc.cpp_std, tc.gnu_extensions),
- ModuleTypeUnderTest: "cc_library_shared",
- ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
- Blueprint: soongCcLibraryPreamble + fmt.Sprintf(`
-cc_library_shared {
- name: "%s_shared",
-%s // cpp_std: *string
-%s // c_std: *string
-%s // gnu_extensions: *bool
- include_build_directory: false,
-}
-`, name_prefix, cppStdProp, cStdProp, gnuExtensionsProp),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", name_prefix+"_shared", attrs),
- },
- })
- })
- }
-}
-
-func TestCcLibraryProtoSimple(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble + `cc_library {
- name: "foo",
- srcs: ["foo.proto"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
- "deps": `[":foo_proto"]`,
- }), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
- "deps": `[":libprotobuf-cpp-lite"]`,
- }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
- "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryProtoNoCanonicalPathFromRoot(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble + `cc_library {
- name: "foo",
- srcs: ["foo.proto"],
- proto: { canonical_path_from_root: false},
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- "strip_import_prefix": `""`,
- }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
- "deps": `[":foo_proto"]`,
- }), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
- "deps": `[":libprotobuf-cpp-lite"]`,
- }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
- "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryProtoExplicitCanonicalPathFromRoot(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble + `cc_library {
- name: "foo",
- srcs: ["foo.proto"],
- proto: { canonical_path_from_root: true},
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
- "deps": `[":foo_proto"]`,
- }), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
- "deps": `[":libprotobuf-cpp-lite"]`,
- }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
- "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryProtoFull(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble + `cc_library {
- name: "foo",
- srcs: ["foo.proto"],
- proto: {
- type: "full",
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- }), MakeBazelTarget("cc_proto_library", "foo_cc_proto", AttrNameToString{
- "deps": `[":foo_proto"]`,
- }), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "implementation_whole_archive_deps": `[":foo_cc_proto"]`,
- "deps": `[":libprotobuf-cpp-full"]`,
- }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-full"]`,
- "implementation_whole_archive_deps": `[":foo_cc_proto"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryProtoLite(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble + `cc_library {
- name: "foo",
- srcs: ["foo.proto"],
- proto: {
- type: "lite",
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
- "deps": `[":foo_proto"]`,
- }), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
- "deps": `[":libprotobuf-cpp-lite"]`,
- }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
- "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryProtoExportHeaders(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble + `cc_library {
- name: "foo",
- srcs: ["foo.proto"],
- proto: {
- export_proto_headers: true,
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
- "deps": `[":foo_proto"]`,
- }), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryProtoIncludeDirs(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble + `cc_library {
- name: "foo",
- srcs: ["foo.proto"],
- proto: {
- include_dirs: ["external/protobuf/src"],
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- "deps": `["//external/protobuf:libprotobuf-proto"]`,
- }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
- "deps": `[":foo_proto"]`,
- }), MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "deps": `[":libprotobuf-cpp-lite"]`,
- "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
- "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryProtoIncludeDirsUnknown(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble + `cc_library {
- name: "foo",
- srcs: ["foo.proto"],
- proto: {
- include_dirs: ["external/protobuf/abc"],
- },
- include_build_directory: false,
-}`,
- ExpectedErr: fmt.Errorf("module \"foo\": TODO: Add support for proto.include_dir: external/protobuf/abc. This directory does not contain an Android.bp file"),
- })
-}
-
-func TestCcLibraryConvertedProtoFilegroups(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble + `
-filegroup {
- name: "a_fg_proto",
- srcs: ["a_fg.proto"],
-}
-
-cc_library {
- name: "a",
- srcs: [
- ":a_fg_proto",
- "a.proto",
- ],
- proto: {
- export_proto_headers: true,
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("proto_library", "a_proto", AttrNameToString{
- "deps": `[":a_fg_proto_bp2build_converted"]`,
- "srcs": `["a.proto"]`,
- }), MakeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", AttrNameToString{
- "deps": `[
- ":a_fg_proto_bp2build_converted",
- ":a_proto",
- ]`,
- }), MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
- "deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":a_cc_proto_lite"]`,
- }), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":a_cc_proto_lite"]`,
- }), MakeBazelTargetNoRestrictions("proto_library", "a_fg_proto_proto", AttrNameToString{
- "srcs": `["a_fg.proto"]`,
- "tags": `[
- "apex_available=//apex_available:anyapex",
- "manual",
- ]`,
- }), MakeBazelTargetNoRestrictions("alias", "a_fg_proto_bp2build_converted", AttrNameToString{
- "actual": `"//.:a_fg_proto_proto"`,
- "tags": `[
- "apex_available=//apex_available:anyapex",
- "manual",
- ]`,
- }), MakeBazelTargetNoRestrictions("filegroup", "a_fg_proto", AttrNameToString{
- "srcs": `["a_fg.proto"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryConvertedProtoFilegroupsNoProtoFiles(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble + `
-filegroup {
- name: "a_fg_proto",
- srcs: ["a_fg.proto"],
-}
-
-cc_library {
- name: "a",
- srcs: [
- ":a_fg_proto",
- ],
- proto: {
- export_proto_headers: true,
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", AttrNameToString{
- "deps": `[":a_fg_proto_bp2build_converted"]`,
- }), MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
- "deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":a_cc_proto_lite"]`,
- }), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":a_cc_proto_lite"]`,
- }), MakeBazelTargetNoRestrictions("proto_library", "a_fg_proto_proto", AttrNameToString{
- "srcs": `["a_fg.proto"]`,
- "tags": `[
- "apex_available=//apex_available:anyapex",
- "manual",
- ]`,
- }), MakeBazelTargetNoRestrictions("alias", "a_fg_proto_bp2build_converted", AttrNameToString{
- "actual": `"//.:a_fg_proto_proto"`,
- "tags": `[
- "apex_available=//apex_available:anyapex",
- "manual",
- ]`,
- }), MakeBazelTargetNoRestrictions("filegroup", "a_fg_proto", AttrNameToString{
- "srcs": `["a_fg.proto"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryExternalConvertedProtoFilegroups(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "path/to/A/Android.bp": `
-filegroup {
- name: "a_fg_proto",
- srcs: ["a_fg.proto"],
-}`,
- },
- Blueprint: soongCcProtoPreamble + `
-cc_library {
- name: "a",
- srcs: [
- ":a_fg_proto",
- "a.proto",
- ],
- proto: {
- export_proto_headers: true,
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("proto_library", "a_proto", AttrNameToString{
- "deps": `["//path/to/A:a_fg_proto_bp2build_converted"]`,
- "srcs": `["a.proto"]`,
- }), MakeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", AttrNameToString{
- "deps": `[
- "//path/to/A:a_fg_proto_bp2build_converted",
- ":a_proto",
- ]`,
- }), MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
- "deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":a_cc_proto_lite"]`,
- }), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":a_cc_proto_lite"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryProtoFilegroups(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble +
- simpleModuleDoNotConvertBp2build("filegroup", "a_fg_proto") +
- simpleModuleDoNotConvertBp2build("filegroup", "b_protos") +
- simpleModuleDoNotConvertBp2build("filegroup", "c-proto-srcs") +
- simpleModuleDoNotConvertBp2build("filegroup", "proto-srcs-d") + `
-cc_library {
- name: "a",
- srcs: [":a_fg_proto"],
- proto: {
- export_proto_headers: true,
- },
- include_build_directory: false,
-}
-
-cc_library {
- name: "b",
- srcs: [":b_protos"],
- proto: {
- export_proto_headers: true,
- },
- include_build_directory: false,
-}
-
-cc_library {
- name: "c",
- srcs: [":c-proto-srcs"],
- proto: {
- export_proto_headers: true,
- },
- include_build_directory: false,
-}
-
-cc_library {
- name: "d",
- srcs: [":proto-srcs-d"],
- proto: {
- export_proto_headers: true,
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("proto_library", "a_proto", AttrNameToString{
- "srcs": `[":a_fg_proto"]`,
- }), MakeBazelTarget("cc_lite_proto_library", "a_cc_proto_lite", AttrNameToString{
- "deps": `[":a_proto"]`,
- }), MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
- "deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":a_cc_proto_lite"]`,
- "srcs": `[":a_fg_proto_cpp_srcs"]`,
- "srcs_as": `[":a_fg_proto_as_srcs"]`,
- "srcs_c": `[":a_fg_proto_c_srcs"]`,
- }), MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":a_cc_proto_lite"]`,
- "srcs": `[":a_fg_proto_cpp_srcs"]`,
- "srcs_as": `[":a_fg_proto_as_srcs"]`,
- "srcs_c": `[":a_fg_proto_c_srcs"]`,
- }), MakeBazelTarget("proto_library", "b_proto", AttrNameToString{
- "srcs": `[":b_protos"]`,
- }), MakeBazelTarget("cc_lite_proto_library", "b_cc_proto_lite", AttrNameToString{
- "deps": `[":b_proto"]`,
- }), MakeBazelTarget("cc_library_static", "b_bp2build_cc_library_static", AttrNameToString{
- "deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":b_cc_proto_lite"]`,
- "srcs": `[":b_protos_cpp_srcs"]`,
- "srcs_as": `[":b_protos_as_srcs"]`,
- "srcs_c": `[":b_protos_c_srcs"]`,
- }), MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":b_cc_proto_lite"]`,
- "srcs": `[":b_protos_cpp_srcs"]`,
- "srcs_as": `[":b_protos_as_srcs"]`,
- "srcs_c": `[":b_protos_c_srcs"]`,
- }), MakeBazelTarget("proto_library", "c_proto", AttrNameToString{
- "srcs": `[":c-proto-srcs"]`,
- }), MakeBazelTarget("cc_lite_proto_library", "c_cc_proto_lite", AttrNameToString{
- "deps": `[":c_proto"]`,
- }), MakeBazelTarget("cc_library_static", "c_bp2build_cc_library_static", AttrNameToString{
- "deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":c_cc_proto_lite"]`,
- "srcs": `[":c-proto-srcs_cpp_srcs"]`,
- "srcs_as": `[":c-proto-srcs_as_srcs"]`,
- "srcs_c": `[":c-proto-srcs_c_srcs"]`,
- }), MakeBazelTarget("cc_library_shared", "c", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":c_cc_proto_lite"]`,
- "srcs": `[":c-proto-srcs_cpp_srcs"]`,
- "srcs_as": `[":c-proto-srcs_as_srcs"]`,
- "srcs_c": `[":c-proto-srcs_c_srcs"]`,
- }), MakeBazelTarget("proto_library", "d_proto", AttrNameToString{
- "srcs": `[":proto-srcs-d"]`,
- }), MakeBazelTarget("cc_lite_proto_library", "d_cc_proto_lite", AttrNameToString{
- "deps": `[":d_proto"]`,
- }), MakeBazelTarget("cc_library_static", "d_bp2build_cc_library_static", AttrNameToString{
- "deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":d_cc_proto_lite"]`,
- "srcs": `[":proto-srcs-d_cpp_srcs"]`,
- "srcs_as": `[":proto-srcs-d_as_srcs"]`,
- "srcs_c": `[":proto-srcs-d_c_srcs"]`,
- }), MakeBazelTarget("cc_library_shared", "d", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":d_cc_proto_lite"]`,
- "srcs": `[":proto-srcs-d_cpp_srcs"]`,
- "srcs_as": `[":proto-srcs-d_as_srcs"]`,
- "srcs_c": `[":proto-srcs-d_c_srcs"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryDisabledArchAndTarget(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble + `cc_library {
- name: "foo",
- srcs: ["foo.cpp"],
- host_supported: true,
- target: {
- darwin: {
- enabled: false,
- },
- windows: {
- enabled: false,
- },
- linux_glibc_x86: {
- enabled: false,
- },
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo", AttrNameToString{
- "srcs": `["foo.cpp"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os_arch:darwin_arm64": ["@platforms//:incompatible"],
- "//build/bazel/platforms/os_arch:darwin_x86_64": ["@platforms//:incompatible"],
- "//build/bazel/platforms/os_arch:linux_glibc_x86": ["@platforms//:incompatible"],
- "//build/bazel/platforms/os_arch:windows_x86": ["@platforms//:incompatible"],
- "//build/bazel/platforms/os_arch:windows_x86_64": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- })
-}
-
-func TestCcLibraryDisabledArchAndTargetWithDefault(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble + `cc_library {
- name: "foo",
- srcs: ["foo.cpp"],
- enabled: false,
- host_supported: true,
- target: {
- darwin: {
- enabled: true,
- },
- windows: {
- enabled: false,
- },
- linux_glibc_x86: {
- enabled: false,
- },
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo", AttrNameToString{
- "srcs": `["foo.cpp"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os_arch:darwin_arm64": [],
- "//build/bazel/platforms/os_arch:darwin_x86_64": [],
- "//conditions:default": ["@platforms//:incompatible"],
- })`,
- }),
- })
-}
-
-func TestCcLibrarySharedDisabled(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble + `cc_library {
- name: "foo",
- srcs: ["foo.cpp"],
- enabled: false,
- shared: {
- enabled: true,
- },
- target: {
- android: {
- shared: {
- enabled: false,
- },
- }
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "srcs": `["foo.cpp"]`,
- "target_compatible_with": `["@platforms//:incompatible"]`,
- }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "srcs": `["foo.cpp"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticDisabledForSomeArch(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble + `cc_library {
- name: "foo",
- host_supported: true,
- srcs: ["foo.cpp"],
- shared: {
- enabled: false
- },
- target: {
- darwin: {
- enabled: true,
- },
- windows: {
- enabled: false,
- },
- linux_glibc_x86: {
- shared: {
- enabled: true,
- },
- },
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "srcs": `["foo.cpp"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:windows": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "srcs": `["foo.cpp"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os_arch:darwin_arm64": [],
- "//build/bazel/platforms/os_arch:darwin_x86_64": [],
- "//build/bazel/platforms/os_arch:linux_glibc_x86": [],
- "//conditions:default": ["@platforms//:incompatible"],
- })`,
- }),
- }})
-}
-
-func TestCcLibraryStubs(t *testing.T) {
- expectedBazelTargets := makeCcLibraryTargets("a", AttrNameToString{
- "stubs_symbol_file": `"a.map.txt"`,
- })
- expectedBazelTargets = append(expectedBazelTargets, makeCcStubSuiteTargets("a", AttrNameToString{
- "soname": `"a.so"`,
- "source_library_label": `"//foo/bar:a"`,
- "stubs_symbol_file": `"a.map.txt"`,
- "stubs_versions": `[
- "28",
- "29",
- "current",
- ]`,
- }))
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library stubs",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Dir: "foo/bar",
- Filesystem: map[string]string{
- "foo/bar/Android.bp": `
-cc_library {
- name: "a",
- stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
- bazel_module: { bp2build_available: true },
- include_build_directory: false,
-}
-`,
- },
- Blueprint: soongCcLibraryPreamble,
- ExpectedBazelTargets: expectedBazelTargets,
- },
- )
-}
-
-func TestCcLibraryStubsAcrossConfigsDuplicatesRemoved(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "stub target generation of the same lib across configs should not result in duplicates",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "bar.map.txt": "",
- },
- Blueprint: `
-cc_library {
- name: "barlib",
- stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] },
- bazel_module: { bp2build_available: false },
-}
-cc_library {
- name: "foolib",
- shared_libs: ["barlib"],
- target: {
- android: {
- shared_libs: ["barlib"],
- },
- },
- bazel_module: { bp2build_available: true },
- apex_available: ["foo"],
-}`,
- ExpectedBazelTargets: makeCcLibraryTargets("foolib", AttrNameToString{
- "implementation_dynamic_deps": `select({
- "//build/bazel/rules/apex:foo": ["@api_surfaces//module-libapi/current:barlib"],
- "//conditions:default": [":barlib"],
- })`,
- "local_includes": `["."]`,
- "tags": `["apex_available=foo"]`,
- }),
- })
-}
-
-func TestCcLibraryExcludesLibsHost(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "bar.map.txt": "",
- },
- Blueprint: simpleModuleDoNotConvertBp2build("cc_library", "bazlib") + `
-cc_library {
- name: "quxlib",
- stubs: { symbol_file: "bar.map.txt", versions: ["current"] },
- bazel_module: { bp2build_available: false },
-}
-cc_library {
- name: "barlib",
- stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] },
- bazel_module: { bp2build_available: false },
-}
-cc_library {
- name: "foolib",
- shared_libs: ["barlib", "quxlib"],
- target: {
- host: {
- shared_libs: ["bazlib"],
- exclude_shared_libs: ["barlib"],
- },
- },
- include_build_directory: false,
- bazel_module: { bp2build_available: true },
- apex_available: ["foo"],
-}`,
- ExpectedBazelTargets: makeCcLibraryTargets("foolib", AttrNameToString{
- "implementation_dynamic_deps": `select({
- "//build/bazel/platforms/os:darwin": [":bazlib"],
- "//build/bazel/platforms/os:linux_bionic": [":bazlib"],
- "//build/bazel/platforms/os:linux_glibc": [":bazlib"],
- "//build/bazel/platforms/os:linux_musl": [":bazlib"],
- "//build/bazel/platforms/os:windows": [":bazlib"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os:darwin": [":quxlib"],
- "//build/bazel/platforms/os:linux_bionic": [":quxlib"],
- "//build/bazel/platforms/os:linux_glibc": [":quxlib"],
- "//build/bazel/platforms/os:linux_musl": [":quxlib"],
- "//build/bazel/platforms/os:windows": [":quxlib"],
- "//build/bazel/rules/apex:foo": [
- "@api_surfaces//module-libapi/current:barlib",
- "@api_surfaces//module-libapi/current:quxlib",
- ],
- "//conditions:default": [
- ":barlib",
- ":quxlib",
- ],
- })`,
- "tags": `["apex_available=foo"]`,
- }),
- })
-}
-
-func TestCcLibraryEscapeLdflags(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcProtoPreamble + `cc_library {
- name: "foo",
- ldflags: ["-Wl,--rpath,${ORIGIN}"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo", AttrNameToString{
- "linkopts": `["-Wl,--rpath,$${ORIGIN}"]`,
- }),
- })
-}
-
-func TestCcLibraryConvertLex(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "foo.c": "",
- "bar.cc": "",
- "foo1.l": "",
- "bar1.ll": "",
- "foo2.l": "",
- "bar2.ll": "",
- },
- Blueprint: `cc_library {
- name: "foo_lib",
- srcs: ["foo.c", "bar.cc", "foo1.l", "foo2.l", "bar1.ll", "bar2.ll"],
- lex: { flags: ["--foo_flags"] },
- include_build_directory: false,
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: append([]string{
- MakeBazelTarget("genlex", "foo_lib_genlex_l", AttrNameToString{
- "srcs": `[
- "foo1.l",
- "foo2.l",
- ]`,
- "lexopts": `["--foo_flags"]`,
- }),
- MakeBazelTarget("genlex", "foo_lib_genlex_ll", AttrNameToString{
- "srcs": `[
- "bar1.ll",
- "bar2.ll",
- ]`,
- "lexopts": `["--foo_flags"]`,
- }),
- },
- makeCcLibraryTargets("foo_lib", AttrNameToString{
- "srcs": `[
- "bar.cc",
- ":foo_lib_genlex_ll",
- ]`,
- "srcs_c": `[
- "foo.c",
- ":foo_lib_genlex_l",
- ]`,
- })...),
- })
-}
-
-func TestCCLibraryRuntimeDeps(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Blueprint: `cc_library_shared {
- name: "bar",
-}
-
-cc_library {
- name: "foo",
- runtime_libs: ["foo"],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "bar", AttrNameToString{
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "runtime_deps": `[":foo"]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "runtime_deps": `[":foo"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithInstructionSet(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `cc_library {
- name: "foo",
- arch: {
- arm: {
- instruction_set: "arm",
- }
- }
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("foo", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/arch:arm": ["arm_isa_arm"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- })
-}
-
-func TestCcLibraryEmptySuffix(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library with empty suffix",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "foo.c": "",
- },
- Blueprint: `cc_library {
- name: "foo",
- suffix: "",
- srcs: ["foo.c"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "srcs_c": `["foo.c"]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "srcs_c": `["foo.c"]`,
- "suffix": `""`,
- }),
- },
- })
-}
-
-func TestCcLibrarySuffix(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library with suffix",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "foo.c": "",
- },
- Blueprint: `cc_library {
- name: "foo",
- suffix: "-suf",
- srcs: ["foo.c"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "srcs_c": `["foo.c"]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "srcs_c": `["foo.c"]`,
- "suffix": `"-suf"`,
- }),
- },
- })
-}
-
-func TestCcLibraryArchVariantSuffix(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library with arch-variant suffix",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "foo.c": "",
- },
- Blueprint: `cc_library {
- name: "foo",
- arch: {
- arm64: { suffix: "-64" },
- arm: { suffix: "-32" },
- },
- srcs: ["foo.c"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "srcs_c": `["foo.c"]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "srcs_c": `["foo.c"]`,
- "suffix": `select({
- "//build/bazel/platforms/arch:arm": "-32",
- "//build/bazel/platforms/arch:arm64": "-64",
- "//conditions:default": None,
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithAidlLibrary(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library with aidl_library",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-aidl_library {
- name: "A_aidl",
- srcs: ["aidl/A.aidl"],
- hdrs: ["aidl/Header.aidl"],
- strip_import_prefix: "aidl",
-}
-cc_library {
- name: "foo",
- aidl: {
- libs: ["A_aidl"],
- },
- export_include_dirs: ["include"],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("aidl_library", "A_aidl", AttrNameToString{
- "srcs": `["aidl/A.aidl"]`,
- "hdrs": `["aidl/Header.aidl"]`,
- "strip_import_prefix": `"aidl"`,
- "tags": `["apex_available=//apex_available:anyapex"]`,
- }),
- MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
- "deps": `[":A_aidl"]`,
- "local_includes": `["."]`,
- "export_includes": `["include"]`,
- }),
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
- "local_includes": `["."]`,
- "export_includes": `["include"]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
- "local_includes": `["."]`,
- "export_includes": `["include"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithAidlSrcs(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library with aidl srcs",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-filegroup {
- name: "A_aidl",
- srcs: ["aidl/A.aidl"],
- path: "aidl",
-}
-cc_library {
- name: "foo",
- srcs: [
- ":A_aidl",
- "B.aidl",
- ],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("aidl_library", "A_aidl", AttrNameToString{
- "srcs": `["aidl/A.aidl"]`,
- "strip_import_prefix": `"aidl"`,
- "tags": `["apex_available=//apex_available:anyapex"]`,
- }),
- MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
- "srcs": `["B.aidl"]`,
- }),
- MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
- "local_includes": `["."]`,
- "deps": `[
- ":A_aidl",
- ":foo_aidl_library",
- ]`,
- }),
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithNonAdjacentAidlFilegroup(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library with non aidl filegroup",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "path/to/A/Android.bp": `
-filegroup {
- name: "A_aidl",
- srcs: ["aidl/A.aidl"],
- path: "aidl",
-}`,
- },
- Blueprint: `
-cc_library {
- name: "foo",
- srcs: [
- ":A_aidl",
- ],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
- "local_includes": `["."]`,
- "deps": `["//path/to/A:A_aidl"]`,
- }),
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithExportAidlHeaders(t *testing.T) {
- t.Parallel()
-
- expectedBazelTargets := []string{
- MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
- "local_includes": `["."]`,
- "deps": `[":foo_aidl_library"]`,
- }),
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "whole_archive_deps": `[":foo_cc_aidl_library"]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "whole_archive_deps": `[":foo_cc_aidl_library"]`,
- "local_includes": `["."]`,
- }),
- }
- testCases := []struct {
- description string
- bp string
- expectedBazelTargets []string
- }{
- {
- description: "cc_library with aidl srcs and aidl.export_aidl_headers set",
- bp: `
- cc_library {
- name: "foo",
- srcs: [
- "Foo.aidl",
- ],
- aidl: {
- export_aidl_headers: true,
- }
- }`,
- expectedBazelTargets: append(
- expectedBazelTargets,
- MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
- "srcs": `["Foo.aidl"]`,
- })),
- },
- {
- description: "cc_library with aidl.libs and aidl.export_aidl_headers set",
- bp: `
- aidl_library {
- name: "foo_aidl_library",
- srcs: ["Foo.aidl"],
- }
- cc_library {
- name: "foo",
- aidl: {
- libs: ["foo_aidl_library"],
- export_aidl_headers: true,
- }
- }`,
- expectedBazelTargets: append(
- expectedBazelTargets,
- MakeBazelTargetNoRestrictions("aidl_library", "foo_aidl_library", AttrNameToString{
- "srcs": `["Foo.aidl"]`,
- "tags": `["apex_available=//apex_available:anyapex"]`,
- }),
- ),
- },
- }
-
- for _, testCase := range testCases {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library with export aidl headers",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: testCase.bp,
- ExpectedBazelTargets: testCase.expectedBazelTargets,
- })
- }
-}
-
-func TestCcLibraryWithTargetApex(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library with target.apex",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- shared_libs: ["bar", "baz"],
- static_libs: ["baz", "buh"],
- target: {
- apex: {
- exclude_shared_libs: ["bar"],
- exclude_static_libs: ["buh"],
- }
- }
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "implementation_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
- "//build/bazel/rules/apex:in_apex": [],
- "//conditions:default": [":buh__BP2BUILD__MISSING__DEP"],
- })`,
- "implementation_dynamic_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
- "//build/bazel/rules/apex:in_apex": [],
- "//conditions:default": [":bar__BP2BUILD__MISSING__DEP"],
- })`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "implementation_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
- "//build/bazel/rules/apex:in_apex": [],
- "//conditions:default": [":buh__BP2BUILD__MISSING__DEP"],
- })`,
- "implementation_dynamic_deps": `[":baz__BP2BUILD__MISSING__DEP"] + select({
- "//build/bazel/rules/apex:in_apex": [],
- "//conditions:default": [":bar__BP2BUILD__MISSING__DEP"],
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithTargetApexAndExportLibHeaders(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library with target.apex and export_shared|static_lib_headers",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library_static {
- name: "foo",
- shared_libs: ["bar", "baz"],
- static_libs: ["abc"],
- export_shared_lib_headers: ["baz"],
- export_static_lib_headers: ["abc"],
- target: {
- apex: {
- exclude_shared_libs: ["baz", "bar"],
- exclude_static_libs: ["abc"],
- }
- }
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "implementation_dynamic_deps": `select({
- "//build/bazel/rules/apex:in_apex": [],
- "//conditions:default": [":bar__BP2BUILD__MISSING__DEP"],
- })`,
- "dynamic_deps": `select({
- "//build/bazel/rules/apex:in_apex": [],
- "//conditions:default": [":baz__BP2BUILD__MISSING__DEP"],
- })`,
- "deps": `select({
- "//build/bazel/rules/apex:in_apex": [],
- "//conditions:default": [":abc__BP2BUILD__MISSING__DEP"],
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithSyspropSrcs(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library with sysprop sources",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- srcs: [
- "bar.sysprop",
- "baz.sysprop",
- "blah.cpp",
- ],
- min_sdk_version: "5",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("sysprop_library", "foo_sysprop_library", AttrNameToString{
- "srcs": `[
- "bar.sysprop",
- "baz.sysprop",
- ]`,
- }),
- MakeBazelTarget("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
- "dep": `":foo_sysprop_library"`,
- "min_sdk_version": `"5"`,
- }),
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "srcs": `["blah.cpp"]`,
- "local_includes": `["."]`,
- "min_sdk_version": `"5"`,
- "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "srcs": `["blah.cpp"]`,
- "local_includes": `["."]`,
- "min_sdk_version": `"5"`,
- "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithSyspropSrcsSomeConfigs(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library with sysprop sources in some configs but not others",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- host_supported: true,
- srcs: [
- "blah.cpp",
- ],
- target: {
- android: {
- srcs: ["bar.sysprop"],
- },
- },
- min_sdk_version: "5",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("sysprop_library", "foo_sysprop_library", AttrNameToString{
- "srcs": `select({
- "//build/bazel/platforms/os:android": ["bar.sysprop"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTargetNoRestrictions("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
- "dep": `":foo_sysprop_library"`,
- "min_sdk_version": `"5"`,
- }),
- MakeBazelTargetNoRestrictions("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "srcs": `["blah.cpp"]`,
- "local_includes": `["."]`,
- "min_sdk_version": `"5"`,
- "whole_archive_deps": `select({
- "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTargetNoRestrictions("cc_library_shared", "foo", AttrNameToString{
- "srcs": `["blah.cpp"]`,
- "local_includes": `["."]`,
- "min_sdk_version": `"5"`,
- "whole_archive_deps": `select({
- "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithAidlAndLibs(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_aidl_library depends on libs from parent cc_library_static",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library_static {
- name: "foo",
- srcs: [
- "Foo.aidl",
- ],
- static_libs: [
- "bar-static",
- "baz-static",
- ],
- shared_libs: [
- "bar-shared",
- "baz-shared",
- ],
- export_static_lib_headers: [
- "baz-static",
- ],
- export_shared_lib_headers: [
- "baz-shared",
- ],
-}` +
- simpleModuleDoNotConvertBp2build("cc_library_static", "bar-static") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "baz-static") +
- simpleModuleDoNotConvertBp2build("cc_library", "bar-shared") +
- simpleModuleDoNotConvertBp2build("cc_library", "baz-shared"),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("aidl_library", "foo_aidl_library", AttrNameToString{
- "srcs": `["Foo.aidl"]`,
- }),
- MakeBazelTarget("cc_aidl_library", "foo_cc_aidl_library", AttrNameToString{
- "local_includes": `["."]`,
- "deps": `[":foo_aidl_library"]`,
- "implementation_deps": `[
- ":baz-static",
- ":bar-static",
- ]`,
- "implementation_dynamic_deps": `[
- ":baz-shared",
- ":bar-shared",
- ]`,
- }),
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "implementation_whole_archive_deps": `[":foo_cc_aidl_library"]`,
- "deps": `[":baz-static"]`,
- "implementation_deps": `[":bar-static"]`,
- "dynamic_deps": `[":baz-shared"]`,
- "implementation_dynamic_deps": `[":bar-shared"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithTidy(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library uses tidy properties",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library_static {
- name: "foo",
- srcs: ["foo.cpp"],
-}
-cc_library_static {
- name: "foo-no-tidy",
- srcs: ["foo.cpp"],
- tidy: false,
-}
-cc_library_static {
- name: "foo-tidy",
- srcs: ["foo.cpp"],
- tidy: true,
- tidy_checks: ["check1", "check2"],
- tidy_checks_as_errors: ["check1error", "check2error"],
- tidy_disabled_srcs: ["bar.cpp"],
- tidy_timeout_srcs: ["baz.cpp"],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `["foo.cpp"]`,
- }),
- MakeBazelTarget("cc_library_static", "foo-no-tidy", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `["foo.cpp"]`,
- "tidy": `"never"`,
- }),
- MakeBazelTarget("cc_library_static", "foo-tidy", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `["foo.cpp"]`,
- "tidy": `"local"`,
- "tidy_checks": `[
- "check1",
- "check2",
- ]`,
- "tidy_checks_as_errors": `[
- "check1error",
- "check2error",
- ]`,
- "tidy_disabled_srcs": `["bar.cpp"]`,
- "tidy_timeout_srcs": `["baz.cpp"]`,
- }),
- },
- })
-}
-
-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",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `cc_library {
- name: "foo",
- header_abi_checker: {
- enabled: true,
- symbol_file: "a.map.txt",
- exclude_symbol_versions: [
- "29",
- "30",
- ],
- exclude_symbol_tags: [
- "tag1",
- "tag2",
- ],
- check_all_apis: true,
- diff_flags: ["-allow-adding-removing-weak-symbols"],
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{}),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "abi_checker_enabled": `True`,
- "abi_checker_symbol_file": `"a.map.txt"`,
- "abi_checker_exclude_symbol_versions": `[
- "29",
- "30",
- ]`,
- "abi_checker_exclude_symbol_tags": `[
- "tag1",
- "tag2",
- ]`,
- "abi_checker_check_all_apis": `True`,
- "abi_checker_diff_flags": `["-allow-adding-removing-weak-symbols"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryApexAvailable(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library apex_available converted to tags",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "a",
- srcs: ["a.cpp"],
- apex_available: ["com.android.foo"],
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("a", AttrNameToString{
- "tags": `["apex_available=com.android.foo"]`,
- "srcs": `["a.cpp"]`,
- "local_includes": `["."]`,
- }),
- },
- )
-}
-
-func TestCcLibraryApexAvailableMultiple(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library apex_available converted to multiple tags",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "a",
- srcs: ["a.cpp"],
- apex_available: ["com.android.foo", "//apex_available:platform", "com.android.bar"],
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("a", AttrNameToString{
- "tags": `[
- "apex_available=com.android.foo",
- "apex_available=//apex_available:platform",
- "apex_available=com.android.bar",
- ]`,
- "srcs": `["a.cpp"]`,
- "local_includes": `["."]`,
- }),
- },
- )
-}
-
-// Export_include_dirs and Export_system_include_dirs have "variant_prepend" tag.
-// In bp2build output, variant info(select) should go before general info.
-// Internal order of the property should be unchanged. (e.g. ["eid1", "eid2"])
-func TestCcLibraryVariantPrependPropOrder(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library variant prepend properties order",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library {
- name: "a",
- srcs: ["a.cpp"],
- export_include_dirs: ["eid1", "eid2"],
- export_system_include_dirs: ["esid1", "esid2"],
- target: {
- android: {
- export_include_dirs: ["android_eid1", "android_eid2"],
- export_system_include_dirs: ["android_esid1", "android_esid2"],
- },
- android_arm: {
- export_include_dirs: ["android_arm_eid1", "android_arm_eid2"],
- export_system_include_dirs: ["android_arm_esid1", "android_arm_esid2"],
- },
- linux: {
- export_include_dirs: ["linux_eid1", "linux_eid2"],
- export_system_include_dirs: ["linux_esid1", "linux_esid2"],
- },
- },
- multilib: {
- lib32: {
- export_include_dirs: ["lib32_eid1", "lib32_eid2"],
- export_system_include_dirs: ["lib32_esid1", "lib32_esid2"],
- },
- },
- arch: {
- arm: {
- export_include_dirs: ["arm_eid1", "arm_eid2"],
- export_system_include_dirs: ["arm_esid1", "arm_esid2"],
- },
- }
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("a", AttrNameToString{
- "export_includes": `select({
- "//build/bazel/platforms/os_arch:android_arm": [
- "android_arm_eid1",
- "android_arm_eid2",
- ],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os:android": [
- "android_eid1",
- "android_eid2",
- "linux_eid1",
- "linux_eid2",
- ],
- "//build/bazel/platforms/os:linux_bionic": [
- "linux_eid1",
- "linux_eid2",
- ],
- "//build/bazel/platforms/os:linux_glibc": [
- "linux_eid1",
- "linux_eid2",
- ],
- "//build/bazel/platforms/os:linux_musl": [
- "linux_eid1",
- "linux_eid2",
- ],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/arch:arm": [
- "lib32_eid1",
- "lib32_eid2",
- "arm_eid1",
- "arm_eid2",
- ],
- "//build/bazel/platforms/arch:x86": [
- "lib32_eid1",
- "lib32_eid2",
- ],
- "//conditions:default": [],
- }) + [
- "eid1",
- "eid2",
- ]`,
- "export_system_includes": `select({
- "//build/bazel/platforms/os_arch:android_arm": [
- "android_arm_esid1",
- "android_arm_esid2",
- ],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os:android": [
- "android_esid1",
- "android_esid2",
- "linux_esid1",
- "linux_esid2",
- ],
- "//build/bazel/platforms/os:linux_bionic": [
- "linux_esid1",
- "linux_esid2",
- ],
- "//build/bazel/platforms/os:linux_glibc": [
- "linux_esid1",
- "linux_esid2",
- ],
- "//build/bazel/platforms/os:linux_musl": [
- "linux_esid1",
- "linux_esid2",
- ],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/arch:arm": [
- "lib32_esid1",
- "lib32_esid2",
- "arm_esid1",
- "arm_esid2",
- ],
- "//build/bazel/platforms/arch:x86": [
- "lib32_esid1",
- "lib32_esid2",
- ],
- "//conditions:default": [],
- }) + [
- "esid1",
- "esid2",
- ]`,
- "srcs": `["a.cpp"]`,
- "local_includes": `["."]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- }),
- },
- )
-}
-
-func TestCcLibraryWithIntegerOverflowProperty(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library has correct features when integer_overflow property is provided",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- sanitize: {
- integer_overflow: true,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "features": `["ubsan_integer_overflow"]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `["ubsan_integer_overflow"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithMiscUndefinedProperty(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library has correct features when misc_undefined property is provided",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- sanitize: {
- misc_undefined: ["undefined", "nullability"],
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "features": `[
- "ubsan_undefined",
- "ubsan_nullability",
- ]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `[
- "ubsan_undefined",
- "ubsan_nullability",
- ]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithSanitizerBlocklist(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library has correct feature when sanitize.blocklist is provided",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- sanitize: {
- blocklist: "foo_blocklist.txt",
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "copts": `select({
- "//build/bazel/rules/cc:sanitizers_enabled": ["-fsanitize-ignorelist=$(location foo_blocklist.txt)"],
- "//conditions:default": [],
- })`,
- "additional_compiler_inputs": `select({
- "//build/bazel/rules/cc:sanitizers_enabled": [":foo_blocklist.txt"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "copts": `select({
- "//build/bazel/rules/cc:sanitizers_enabled": ["-fsanitize-ignorelist=$(location foo_blocklist.txt)"],
- "//conditions:default": [],
- })`,
- "additional_compiler_inputs": `select({
- "//build/bazel/rules/cc:sanitizers_enabled": [":foo_blocklist.txt"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithUBSanPropertiesArchSpecific(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library has correct feature select when UBSan props are specified in arch specific blocks",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- sanitize: {
- misc_undefined: ["undefined", "nullability"],
- },
- target: {
- android: {
- sanitize: {
- misc_undefined: ["alignment"],
- },
- },
- linux_glibc: {
- sanitize: {
- integer_overflow: true,
- },
- },
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "features": `[
- "ubsan_undefined",
- "ubsan_nullability",
- ] + select({
- "//build/bazel/platforms/os:android": ["ubsan_alignment"],
- "//build/bazel/platforms/os:linux_glibc": ["ubsan_integer_overflow"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `[
- "ubsan_undefined",
- "ubsan_nullability",
- ] + select({
- "//build/bazel/platforms/os:android": ["ubsan_alignment"],
- "//build/bazel/platforms/os:linux_glibc": ["ubsan_integer_overflow"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryInApexWithStubSharedLibs(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library with in apex with stub shared_libs and export_shared_lib_headers",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "barlib",
- stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] },
- bazel_module: { bp2build_available: false },
- apex_available: ["//apex_available:platform",],
-}
-cc_library {
- name: "bazlib",
- stubs: { symbol_file: "bar.map.txt", versions: ["28", "29", "current"] },
- bazel_module: { bp2build_available: false },
- apex_available: ["//apex_available:platform",],
-}
-cc_library {
- name: "foo",
- shared_libs: ["barlib", "bazlib"],
- export_shared_lib_headers: ["bazlib"],
- apex_available: [
- "//apex_available:platform",
- ],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "implementation_dynamic_deps": `[":barlib"]`,
- "dynamic_deps": `[":bazlib"]`,
- "local_includes": `["."]`,
- "tags": `["apex_available=//apex_available:platform"]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "implementation_dynamic_deps": `[":barlib"]`,
- "dynamic_deps": `[":bazlib"]`,
- "local_includes": `["."]`,
- "tags": `["apex_available=//apex_available:platform"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithThinLto(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library has correct features when thin LTO is enabled",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- lto: {
- thin: true,
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "features": `["android_thin_lto"]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `["android_thin_lto"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithLtoNever(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library has correct features when LTO is explicitly disabled",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- lto: {
- never: true,
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "features": `["-android_thin_lto"]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `["-android_thin_lto"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithThinLtoArchSpecific(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library has correct features when LTO differs across arch and os variants",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- target: {
- android: {
- lto: {
- thin: true,
- },
- },
- },
- arch: {
- riscv64: {
- lto: {
- thin: false,
- },
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "local_includes": `["."]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm": ["android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_arm64": ["android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_riscv64": ["-android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_x86": ["android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_x86_64": ["android_thin_lto"],
- "//conditions:default": [],
- })`}),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm": ["android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_arm64": ["android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_riscv64": ["-android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_x86": ["android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_x86_64": ["android_thin_lto"],
- "//conditions:default": [],
- })`}),
- },
- })
-}
-
-func TestCcLibraryWithThinLtoDisabledDefaultEnabledVariant(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library has correct features when LTO disabled by default but enabled on a particular variant",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- lto: {
- never: true,
- },
- target: {
- android: {
- lto: {
- thin: true,
- never: false,
- },
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "local_includes": `["."]`,
- "features": `select({
- "//build/bazel/platforms/os:android": ["android_thin_lto"],
- "//conditions:default": ["-android_thin_lto"],
- })`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `select({
- "//build/bazel/platforms/os:android": ["android_thin_lto"],
- "//conditions:default": ["-android_thin_lto"],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithThinLtoWholeProgramVtables(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library has correct features when thin LTO is enabled with whole_program_vtables",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- lto: {
- thin: true,
- },
- whole_program_vtables: true,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "features": `[
- "android_thin_lto",
- "android_thin_lto_whole_program_vtables",
- ]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `[
- "android_thin_lto",
- "android_thin_lto_whole_program_vtables",
- ]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryHiddenVisibilityConvertedToFeature(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library changes hidden visibility flag to feature",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- cflags: ["-fvisibility=hidden"],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "features": `["visibility_hidden"]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `["visibility_hidden"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryHiddenVisibilityConvertedToFeatureSharedSpecific(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library changes hidden visibility flag to feature when specific to shared variant",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- shared: {
- cflags: ["-fvisibility=hidden"],
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `["visibility_hidden"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryHiddenVisibilityConvertedToFeatureStaticSpecific(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library changes hidden visibility flag to feature when specific to static variant",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- static: {
- cflags: ["-fvisibility=hidden"],
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "features": `["visibility_hidden"]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryHiddenVisibilityConvertedToFeatureOsSpecific(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library changes hidden visibility flag to feature when specific to an os",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- target: {
- android: {
- cflags: ["-fvisibility=hidden"],
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/os:android": ["visibility_hidden"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/os:android": ["visibility_hidden"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-// Test that a config_setting specific to an apex is created by cc_library.
-func TestCcLibraryCreatesInApexConfigSetting(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library creates a config_setting for each apex in apex_available",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Dir: "build/bazel/rules/apex",
- Blueprint: `
-cc_library {
- name: "foo",
- apex_available: [
- "//apex_available:platform", // This will be skipped, since it is equivalent to //build/bazel/rules/apex:android-non_apex
- "myapex"
- ],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions(
- "config_setting",
- "myapex",
- AttrNameToString{
- "flag_values": `{
- "//build/bazel/rules/apex:api_domain": "myapex",
- }`,
- "constraint_values": `["//build/bazel/platforms/os:android"]`,
- },
- ),
- },
- })
-}
-
-func TestCcLibraryCppFlagsInProductVariables(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library cppflags in product variables",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `cc_library {
- name: "a",
- srcs: ["a.cpp"],
- cppflags: [
- "-Wextra",
- "-DDEBUG_ONLY_CODE=0",
- ],
- product_variables: {
- eng: {
- cppflags: [
- "-UDEBUG_ONLY_CODE",
- "-DDEBUG_ONLY_CODE=1",
- ],
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: makeCcLibraryTargets("a", AttrNameToString{
- "cppflags": `[
- "-Wextra",
- "-DDEBUG_ONLY_CODE=0",
- ] + select({
- "//build/bazel/product_config/config_settings:eng": [
- "-UDEBUG_ONLY_CODE",
- "-DDEBUG_ONLY_CODE=1",
- ],
- "//conditions:default": [],
- })`,
- "srcs": `["a.cpp"]`,
- }),
- },
- )
-}
-
-func TestCcLibraryYaccConversion(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library is built from .y/.yy files",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: soongCcLibraryPreamble + `cc_library {
- name: "a",
- srcs: [
- "a.cpp",
- "a.yy",
- ],
- shared_libs: ["sharedlib"],
- static_libs: ["staticlib"],
- yacc: {
- flags: ["someYaccFlag"],
- gen_location_hh: true,
- gen_position_hh: true,
- },
-}
-cc_library_static {
- name: "staticlib",
- bazel_module: { bp2build_available: false },
-}
-cc_library {
- name: "sharedlib",
- bazel_module: { bp2build_available: false },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_yacc_static_library", "a_yacc", AttrNameToString{
- "src": `"a.yy"`,
- "implementation_deps": `[":staticlib"]`,
- "implementation_dynamic_deps": `[":sharedlib"]`,
- "flags": `["someYaccFlag"]`,
- "gen_location_hh": "True",
- "gen_position_hh": "True",
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
- "srcs": `["a.cpp"]`,
- "implementation_deps": `[":staticlib"]`,
- "implementation_dynamic_deps": `[":sharedlib"]`,
- "implementation_whole_archive_deps": `[":a_yacc"]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_static", "a_bp2build_cc_library_static", AttrNameToString{
- "srcs": `["a.cpp"]`,
- "implementation_deps": `[":staticlib"]`,
- "implementation_dynamic_deps": `[":sharedlib"]`,
- "implementation_whole_archive_deps": `[":a_yacc"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryHostLdLibs(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_binary linker flags for host_ldlibs",
- ModuleTypeUnderTest: "cc_binary",
- ModuleTypeUnderTestFactory: cc.BinaryFactory,
- Blueprint: soongCcLibraryPreamble + `cc_binary {
- name: "a",
- host_supported: true,
- ldflags: ["-lcommon"],
- target: {
- linux: {
- host_ldlibs: [
- "-llinux",
- ],
- },
- darwin: {
- ldflags: ["-ldarwinadditional"],
- host_ldlibs: [
- "-ldarwin",
- ],
- },
- windows: {
- host_ldlibs: [
- "-lwindows",
- ],
- },
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("cc_binary", "a", AttrNameToString{
- "linkopts": `["-lcommon"] + select({
- "//build/bazel/platforms/os:darwin": [
- "-ldarwinadditional",
- "-ldarwin",
- ],
- "//build/bazel/platforms/os:linux_glibc": ["-llinux"],
- "//build/bazel/platforms/os:windows": ["-lwindows"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithCfi(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library has correct features when cfi is enabled",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- sanitize: {
- cfi: true,
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "features": `["android_cfi"]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `["android_cfi"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithCfiOsSpecific(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library has correct features when cfi is enabled for specific variants",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- target: {
- android: {
- sanitize: {
- cfi: true,
- },
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/os:android": ["android_cfi"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/os:android": ["android_cfi"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithCfiAndCfiAssemblySupport(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library has correct features when cfi is enabled with cfi_assembly_support",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- sanitize: {
- cfi: true,
- config: {
- cfi_assembly_support: true,
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "features": `[
- "android_cfi",
- "android_cfi_assembly_support",
- ]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `[
- "android_cfi",
- "android_cfi_assembly_support",
- ]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryExplicitlyDisablesCfiWhenFalse(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library disables cfi when explciitly set to false in the bp",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "foo",
- sanitize: {
- cfi: false,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_bp2build_cc_library_static", AttrNameToString{
- "features": `["-android_cfi"]`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `["-android_cfi"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryWithStem(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library with stem property",
- ModuleTypeUnderTest: "cc_library_shared",
- ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library_shared {
- name: "foo_with_stem_simple",
- stem: "foo",
-}
-cc_library_shared {
- name: "foo_with_arch_variant_stem",
- arch: {
- arm: {
- stem: "foo-arm",
- },
- arm64: {
- stem: "foo-arm64",
- },
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo_with_stem_simple", AttrNameToString{
- "stem": `"foo"`,
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo_with_arch_variant_stem", AttrNameToString{
- "stem": `select({
- "//build/bazel/platforms/arch:arm": "foo-arm",
- "//build/bazel/platforms/arch:arm64": "foo-arm64",
- "//conditions:default": None,
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-// Bazel enforces that proto_library and the .proto file are in the same bazel package
-func TestGenerateProtoLibraryInSamePackage(t *testing.T) {
- tc := Bp2buildTestCase{
- Description: "cc_library depends on .proto files from multiple packages",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library_static {
- name: "foo",
- srcs: [
- "foo.proto",
- "bar/bar.proto", // Different package because there is a bar/Android.bp
- "baz/subbaz/baz.proto", // Different package because there is baz/subbaz/Android.bp
- ],
- proto: {
- canonical_path_from_root: true,
- }
-}
-` + simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
- Filesystem: map[string]string{
- "bar/Android.bp": "",
- "baz/subbaz/Android.bp": "",
- },
- }
-
- // We will run the test 3 times and check in the root, bar and baz/subbaz directories
- // Root dir
- tc.ExpectedBazelTargets = []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "deps": `[":libprotobuf-cpp-lite"]`,
- "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }),
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- "tags": `["manual"]`,
- }),
- MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
- "deps": `[
- ":foo_proto",
- "//bar:foo_proto",
- "//baz/subbaz:foo_proto",
- ]`,
- }),
- }
- runCcLibraryTestCase(t, tc)
-
- // bar dir
- tc.Dir = "bar"
- tc.ExpectedBazelTargets = []string{
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["//bar:bar.proto"]`,
- "tags": `["manual"]`,
- }),
- }
- runCcLibraryTestCase(t, tc)
-
- // baz/subbaz dir
- tc.Dir = "baz/subbaz"
- tc.ExpectedBazelTargets = []string{
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["//baz/subbaz:baz.proto"]`,
- "tags": `["manual"]`,
- }),
- }
- runCcLibraryTestCase(t, tc)
-}
-
-// Bazel enforces that proto_library and the .proto file are in the same bazel package
-func TestGenerateProtoLibraryInSamePackageNotCanonicalFromRoot(t *testing.T) {
- tc := Bp2buildTestCase{
- Description: "cc_library depends on .proto files from multiple packages",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library_static {
- name: "foo",
- srcs: [
- "foo.proto",
- "bar/bar.proto", // Different package because there is a bar/Android.bp
- "baz/subbaz/baz.proto", // Different package because there is baz/subbaz/Android.bp
- ],
- proto: {
- canonical_path_from_root: false,
- }
-}
-` + simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
- Filesystem: map[string]string{
- "bar/Android.bp": "",
- "baz/subbaz/Android.bp": "",
- },
- }
-
- // We will run the test 3 times and check in the root, bar and baz/subbaz directories
- // Root dir
- tc.ExpectedBazelTargets = []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "deps": `[":libprotobuf-cpp-lite"]`,
- "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }),
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- "strip_import_prefix": `""`,
- "tags": `["manual"]`,
- }),
- MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
- "deps": `[
- ":foo_proto",
- "//bar:foo_proto",
- "//baz/subbaz:foo_proto",
- ]`,
- }),
- }
- runCcLibraryTestCase(t, tc)
-
- // bar dir
- tc.Dir = "bar"
- tc.ExpectedBazelTargets = []string{
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["//bar:bar.proto"]`,
- "strip_import_prefix": `""`,
- "import_prefix": `"bar"`,
- "tags": `["manual"]`,
- }),
- }
- runCcLibraryTestCase(t, tc)
-
- // baz/subbaz dir
- tc.Dir = "baz/subbaz"
- tc.ExpectedBazelTargets = []string{
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["//baz/subbaz:baz.proto"]`,
- "strip_import_prefix": `""`,
- "import_prefix": `"baz/subbaz"`,
- "tags": `["manual"]`,
- }),
- }
- runCcLibraryTestCase(t, tc)
-}
-
-func TestProtoIncludeDirs(t *testing.T) {
- tc := Bp2buildTestCase{
- Description: "cc_library depends on .proto files using proto.include_dirs",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library_static {
- name: "foo",
- srcs: [
- "foo.proto",
- ],
- proto: {
- include_dirs: ["bar"],
- }
-}
-` + simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
- Filesystem: map[string]string{
- "bar/Android.bp": "",
- "bar/bar.proto": "",
- "bar/baz/Android.bp": "",
- "bar/baz/baz.proto": "",
- },
- }
-
- // We will run the test 3 times and check in the root, bar and bar/baz directories
- // Root dir
- tc.ExpectedBazelTargets = []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "deps": `[":libprotobuf-cpp-lite"]`,
- "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }),
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- "tags": `["manual"]`,
- }),
- MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
- "deps": `[":foo_proto"]`,
- "transitive_deps": `[
- "//bar:bar.include_dir_bp2build_generated_proto",
- "//bar/baz:bar.include_dir_bp2build_generated_proto",
- ]`,
- }),
- }
- runCcLibraryTestCase(t, tc)
-
- // bar dir
- tc.Dir = "bar"
- tc.ExpectedBazelTargets = []string{
- MakeBazelTargetNoRestrictions("proto_library", "bar.include_dir_bp2build_generated_proto", AttrNameToString{
- "srcs": `["bar.proto"]`,
- "strip_import_prefix": `""`,
- "tags": `["manual"]`,
- }),
- }
- runCcLibraryTestCase(t, tc)
-
- // bar/baz dir
- tc.Dir = "bar/baz"
- tc.ExpectedBazelTargets = []string{
- MakeBazelTargetNoRestrictions("proto_library", "bar.include_dir_bp2build_generated_proto", AttrNameToString{
- "srcs": `["//bar/baz:baz.proto"]`,
- "strip_import_prefix": `""`,
- "import_prefix": `"baz"`,
- "tags": `["manual"]`,
- }),
- }
- runCcLibraryTestCase(t, tc)
-}
-
-func TestProtoIncludeDirsWithSrcsInMultiplePackages(t *testing.T) {
- tc := Bp2buildTestCase{
- Description: "cc_library has srcs in multiple bazel packages and uses proto.include_dirs",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library_static {
- name: "foo",
- srcs: [
- "foo.proto",
- "bar/bar.proto",
- ],
- proto: {
- include_dirs: ["baz"],
- }
-}
-` + simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
- Filesystem: map[string]string{
- "bar/Android.bp": "", // package boundary
- "baz/Android.bp": "",
- "baz/baz.proto": "",
- },
- }
-
- tc.ExpectedBazelTargets = []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "deps": `[":libprotobuf-cpp-lite"]`,
- "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }),
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- "tags": `["manual"]`,
- }),
- MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
- "deps": `[
- ":foo_proto",
- "//bar:foo_proto",
- ]`,
- "transitive_deps": `["//baz:baz.include_dir_bp2build_generated_proto"]`,
- }),
- }
- runCcLibraryTestCase(t, tc)
-
-}
-
-func TestProtoLocalIncludeDirs(t *testing.T) {
- tc := Bp2buildTestCase{
- Description: "cc_library depends on .proto files using proto.local_include_dirs",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
- Filesystem: map[string]string{
- "foo/Android.bp": `cc_library_static {
- name: "foo",
- srcs: [
- "foo.proto",
- ],
- proto: {
- local_include_dirs: ["foo_subdir"],
- },
- bazel_module: { bp2build_available: true },
-}`,
- "foo/foo.proto": "",
- "foo/foo_subdir/Android.bp": "",
- "foo/foo_subdir/foo_subdir.proto": "",
- },
- }
-
- // We will run the test 2 times and check in foo and foo/foo_subdir directories
- // foo dir
- tc.Dir = "foo"
- tc.ExpectedBazelTargets = []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "deps": `["//:libprotobuf-cpp-lite"]`,
- "implementation_whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }),
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- "tags": `["manual"]`,
- }),
- MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
- "deps": `[":foo_proto"]`,
- "transitive_deps": `["//foo/foo_subdir:foo.foo_subdir.include_dir_bp2build_generated_proto"]`,
- }),
- }
- runCcLibraryTestCase(t, tc)
-
- // foo/foo_subdir
- tc.Dir = "foo/foo_subdir"
- tc.ExpectedBazelTargets = []string{
- MakeBazelTargetNoRestrictions("proto_library", "foo.foo_subdir.include_dir_bp2build_generated_proto", AttrNameToString{
- "srcs": `["foo_subdir.proto"]`,
- "strip_import_prefix": `""`,
- "tags": `["manual"]`,
- }),
- }
- runCcLibraryTestCase(t, tc)
-}
-
-// `foo_device` and `bar_host` can depend on .proto files of a specific dir,
-// the dynamically generated proto_library should not have any target_compatible_with
-func TestProtoLibraryForIncludeDirsIsOsAgnostic(t *testing.T) {
- tc := Bp2buildTestCase{
- Description: "proto_library generated for proto.include_dirs is compatible for all axes",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite") + `
-cc_library {
- name: "foo_device",
- device_supported: true, // this is the default behavior, but added explicitly here for illustration
- host_supported: false,
- proto: {include_dirs: ["dir"]},
-}
-cc_library {
- name: "bar_host",
- device_supported: false,
- host_supported: true,
- srcs: ["bar.proto"],
- proto: {include_dirs: ["dir"]},
-}
-`,
- Filesystem: map[string]string{
- "dir/Android.bp": "",
- "dir/dir.proto": "",
- },
- Dir: "dir", // check for the generated proto_library
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("proto_library", "dir.include_dir_bp2build_generated_proto", AttrNameToString{
- "srcs": `["dir.proto"]`,
- "strip_import_prefix": `""`,
- "tags": `["manual"]`,
- }),
- },
- }
- runCcLibraryTestCase(t, tc)
-}
-
-func TestCcCompileMultilibConversion(t *testing.T) {
- tc := Bp2buildTestCase{
- Description: "cc_library with compile_multilib",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Blueprint: `
-cc_library {
- name: "lib32",
- compile_multilib: "32",
-}
-cc_library {
- name: "lib64",
- compile_multilib: "64",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("cc_library_shared", "lib32", AttrNameToString{
- "local_includes": `["."]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"] + select({
- "//build/bazel/platforms/arch:arm64": ["@platforms//:incompatible"],
- "//build/bazel/platforms/arch:riscv64": ["@platforms//:incompatible"],
- "//build/bazel/platforms/arch:x86_64": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTargetNoRestrictions("cc_library_static", "lib32_bp2build_cc_library_static", AttrNameToString{
- "local_includes": `["."]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"] + select({
- "//build/bazel/platforms/arch:arm64": ["@platforms//:incompatible"],
- "//build/bazel/platforms/arch:riscv64": ["@platforms//:incompatible"],
- "//build/bazel/platforms/arch:x86_64": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTargetNoRestrictions("cc_library_shared", "lib64", AttrNameToString{
- "local_includes": `["."]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"] + select({
- "//build/bazel/platforms/arch:arm": ["@platforms//:incompatible"],
- "//build/bazel/platforms/arch:x86": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTargetNoRestrictions("cc_library_static", "lib64_bp2build_cc_library_static", AttrNameToString{
- "local_includes": `["."]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"] + select({
- "//build/bazel/platforms/arch:arm": ["@platforms//:incompatible"],
- "//build/bazel/platforms/arch:x86": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- }
- runCcLibraryTestCase(t, tc)
-}
diff --git a/bp2build/cc_library_headers_conversion_test.go b/bp2build/cc_library_headers_conversion_test.go
deleted file mode 100644
index a592ca9..0000000
--- a/bp2build/cc_library_headers_conversion_test.go
+++ /dev/null
@@ -1,415 +0,0 @@
-// 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
-
-import (
- "testing"
-
- "android/soong/android"
- "android/soong/cc"
-)
-
-const (
- // See cc/testing.go for more context
- soongCcLibraryHeadersPreamble = `
-cc_defaults {
- name: "linux_bionic_supported",
-}`
-)
-
-func TestCcLibraryHeadersLoadStatement(t *testing.T) {
- testCases := []struct {
- bazelTargets BazelTargets
- expectedLoadStatements string
- }{
- {
- bazelTargets: BazelTargets{
- BazelTarget{
- name: "cc_library_headers_target",
- ruleClass: "cc_library_headers",
- // Note: no bzlLoadLocation for native rules
- },
- },
- expectedLoadStatements: ``,
- },
- }
-
- for _, testCase := range testCases {
- actual := testCase.bazelTargets.LoadStatements()
- expected := testCase.expectedLoadStatements
- if actual != expected {
- t.Fatalf("Expected load statements to be %s, got %s", expected, actual)
- }
- }
-}
-
-func registerCcLibraryHeadersModuleTypes(ctx android.RegistrationContext) {
- cc.RegisterCCBuildComponents(ctx)
-}
-
-func runCcLibraryHeadersTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, registerCcLibraryHeadersModuleTypes, tc)
-}
-
-func TestCcLibraryHeadersSimple(t *testing.T) {
- runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
- Description: "cc_library_headers test",
- ModuleTypeUnderTest: "cc_library_headers",
- ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
- Filesystem: map[string]string{
- "lib-1/lib1a.h": "",
- "lib-1/lib1b.h": "",
- "lib-2/lib2a.h": "",
- "lib-2/lib2b.h": "",
- "dir-1/dir1a.h": "",
- "dir-1/dir1b.h": "",
- "dir-2/dir2a.h": "",
- "dir-2/dir2b.h": "",
- "arch_arm64_exported_include_dir/a.h": "",
- "arch_x86_exported_include_dir/b.h": "",
- "arch_x86_64_exported_include_dir/c.h": "",
- },
- Blueprint: soongCcLibraryHeadersPreamble + `
-cc_library_headers {
- name: "foo_headers",
- export_include_dirs: ["dir-1", "dir-2"],
- header_libs: ["lib-1", "lib-2"],
-
- arch: {
- arm64: {
- // We expect dir-1 headers to be dropped, because dir-1 is already in export_include_dirs
- export_include_dirs: ["arch_arm64_exported_include_dir", "dir-1"],
- },
- x86: {
- export_include_dirs: ["arch_x86_exported_include_dir"],
- },
- x86_64: {
- export_include_dirs: ["arch_x86_64_exported_include_dir"],
- },
- },
- sdk_version: "current",
- min_sdk_version: "29",
-
- // TODO: Also support export_header_lib_headers
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
- "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"`,
- }),
- },
- })
-}
-
-// header_libs has "variant_prepend" tag. In bp2build output,
-// variant info(select) should go before general info.
-func TestCcLibraryHeadersOsSpecificHeader(t *testing.T) {
- runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
- Description: "cc_library_headers test with os-specific header_libs props",
- ModuleTypeUnderTest: "cc_library_headers",
- ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryPreamble + `
-cc_library_headers {
- name: "android-lib",
- bazel_module: { bp2build_available: false },
-}
-cc_library_headers {
- name: "base-lib",
- bazel_module: { bp2build_available: false },
-}
-cc_library_headers {
- name: "darwin-lib",
- bazel_module: { bp2build_available: false },
-}
-cc_library_headers {
- name: "linux-lib",
- bazel_module: { bp2build_available: false },
-}
-cc_library_headers {
- name: "linux_bionic-lib",
- bazel_module: { bp2build_available: false },
-}
-cc_library_headers {
- name: "windows-lib",
- bazel_module: { bp2build_available: false },
-}
-cc_library_headers {
- name: "foo_headers",
- header_libs: ["base-lib"],
- export_header_lib_headers: ["base-lib"],
- target: {
- android: {
- header_libs: ["android-lib"],
- export_header_lib_headers: ["android-lib"],
- },
- darwin: {
- header_libs: ["darwin-lib"],
- export_header_lib_headers: ["darwin-lib"],
- },
- linux_bionic: {
- header_libs: ["linux_bionic-lib"],
- export_header_lib_headers: ["linux_bionic-lib"],
- },
- linux_glibc: {
- header_libs: ["linux-lib"],
- export_header_lib_headers: ["linux-lib"],
- },
- windows: {
- header_libs: ["windows-lib"],
- export_header_lib_headers: ["windows-lib"],
- },
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
- "deps": `select({
- "//build/bazel/platforms/os:android": [":android-lib"],
- "//build/bazel/platforms/os:darwin": [":darwin-lib"],
- "//build/bazel/platforms/os:linux_bionic": [":linux_bionic-lib"],
- "//build/bazel/platforms/os:linux_glibc": [":linux-lib"],
- "//build/bazel/platforms/os:windows": [":windows-lib"],
- "//conditions:default": [],
- }) + [":base-lib"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryHeadersOsSpecficHeaderLibsExportHeaderLibHeaders(t *testing.T) {
- runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
- Description: "cc_library_headers test with os-specific header_libs and export_header_lib_headers props",
- ModuleTypeUnderTest: "cc_library_headers",
- ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryPreamble + `
-cc_library_headers {
- name: "android-lib",
- bazel_module: { bp2build_available: false },
- }
-cc_library_headers {
- name: "exported-lib",
- bazel_module: { bp2build_available: false },
-}
-cc_library_headers {
- name: "foo_headers",
- target: {
- android: {
- header_libs: ["android-lib", "exported-lib"],
- export_header_lib_headers: ["exported-lib"]
- },
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
- "deps": `select({
- "//build/bazel/platforms/os:android": [":exported-lib"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryHeadersArchAndTargetExportSystemIncludes(t *testing.T) {
- runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
- Description: "cc_library_headers test with arch-specific and target-specific export_system_include_dirs props",
- ModuleTypeUnderTest: "cc_library_headers",
- ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryPreamble + `cc_library_headers {
- name: "foo_headers",
- export_system_include_dirs: [
- "shared_include_dir",
- ],
- target: {
- android: {
- export_system_include_dirs: [
- "android_include_dir",
- ],
- },
- linux_glibc: {
- export_system_include_dirs: [
- "linux_include_dir",
- ],
- },
- darwin: {
- export_system_include_dirs: [
- "darwin_include_dir",
- ],
- },
- },
- arch: {
- arm: {
- export_system_include_dirs: [
- "arm_include_dir",
- ],
- },
- x86_64: {
- export_system_include_dirs: [
- "x86_64_include_dir",
- ],
- },
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
- "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_glibc": ["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"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryHeadersNoCrtIgnored(t *testing.T) {
- runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
- Description: "cc_library_headers test",
- ModuleTypeUnderTest: "cc_library_headers",
- ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
- Filesystem: map[string]string{
- "lib-1/lib1a.h": "",
- "lib-1/lib1b.h": "",
- "lib-2/lib2a.h": "",
- "lib-2/lib2b.h": "",
- "dir-1/dir1a.h": "",
- "dir-1/dir1b.h": "",
- "dir-2/dir2a.h": "",
- "dir-2/dir2b.h": "",
- "arch_arm64_exported_include_dir/a.h": "",
- "arch_x86_exported_include_dir/b.h": "",
- "arch_x86_64_exported_include_dir/c.h": "",
- },
- Blueprint: soongCcLibraryHeadersPreamble + `
-cc_library_headers {
- name: "lib-1",
- export_include_dirs: ["lib-1"],
- no_libcrt: true,
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_headers", "lib-1", AttrNameToString{
- "export_includes": `["lib-1"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryHeadersExportedStaticLibHeadersReexported(t *testing.T) {
- runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
- Description: "cc_library_headers exported_static_lib_headers is reexported",
- ModuleTypeUnderTest: "cc_library_headers",
- ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryHeadersPreamble + `
-cc_library_headers {
- name: "foo_headers",
- export_static_lib_headers: ["foo_export"],
- static_libs: ["foo_export", "foo_no_reexport"],
- bazel_module: { bp2build_available: true },
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
- "deps": `[":foo_export"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryHeadersExportedSharedLibHeadersReexported(t *testing.T) {
- runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
- Description: "cc_library_headers exported_shared_lib_headers is reexported",
- ModuleTypeUnderTest: "cc_library_headers",
- ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryHeadersPreamble + `
-cc_library_headers {
- name: "foo_headers",
- export_shared_lib_headers: ["foo_export"],
- shared_libs: ["foo_export", "foo_no_reexport"],
- bazel_module: { bp2build_available: true },
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
- "deps": `[":foo_export"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryHeadersExportedHeaderLibHeadersReexported(t *testing.T) {
- runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
- Description: "cc_library_headers exported_header_lib_headers is reexported",
- ModuleTypeUnderTest: "cc_library_headers",
- ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryHeadersPreamble + `
-cc_library_headers {
- name: "foo_headers",
- export_header_lib_headers: ["foo_export"],
- header_libs: ["foo_export", "foo_no_reexport"],
- bazel_module: { bp2build_available: true },
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
- "deps": `[":foo_export"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryHeadersWholeStaticLibsReexported(t *testing.T) {
- runCcLibraryHeadersTestCase(t, Bp2buildTestCase{
- Description: "cc_library_headers whole_static_libs is reexported",
- ModuleTypeUnderTest: "cc_library_headers",
- ModuleTypeUnderTestFactory: cc.LibraryHeaderFactory,
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryHeadersPreamble + `
-cc_library_headers {
- name: "foo_headers",
- whole_static_libs: ["foo_export"],
- bazel_module: { bp2build_available: true },
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_headers", "foo_export"),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_headers", "foo_headers", AttrNameToString{
- "deps": `[":foo_export"]`,
- }),
- },
- })
-}
diff --git a/bp2build/cc_library_shared_conversion_test.go b/bp2build/cc_library_shared_conversion_test.go
deleted file mode 100644
index 44b9722..0000000
--- a/bp2build/cc_library_shared_conversion_test.go
+++ /dev/null
@@ -1,1594 +0,0 @@
-// 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
-
-import (
- "testing"
-
- "android/soong/android"
- "android/soong/cc"
-)
-
-const (
- // See cc/testing.go for more context
- // TODO(alexmarquez): Split out the preamble into common code?
- soongCcLibrarySharedPreamble = soongCcLibraryStaticPreamble
-)
-
-func registerCcLibrarySharedModuleTypes(ctx android.RegistrationContext) {
- cc.RegisterCCBuildComponents(ctx)
- ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
- ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
- ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
-}
-
-func runCcLibrarySharedTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- t.Parallel()
- (&tc).ModuleTypeUnderTest = "cc_library_shared"
- (&tc).ModuleTypeUnderTestFactory = cc.LibrarySharedFactory
- RunBp2BuildTestCase(t, registerCcLibrarySharedModuleTypes, tc)
-}
-
-func TestCcLibrarySharedSimple(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared simple overall test",
- Filesystem: map[string]string{
- // NOTE: include_dir headers *should not* appear in Bazel hdrs later (?)
- "include_dir_1/include_dir_1_a.h": "",
- "include_dir_1/include_dir_1_b.h": "",
- "include_dir_2/include_dir_2_a.h": "",
- "include_dir_2/include_dir_2_b.h": "",
- // NOTE: local_include_dir headers *should not* appear in Bazel hdrs later (?)
- "local_include_dir_1/local_include_dir_1_a.h": "",
- "local_include_dir_1/local_include_dir_1_b.h": "",
- "local_include_dir_2/local_include_dir_2_a.h": "",
- "local_include_dir_2/local_include_dir_2_b.h": "",
- // NOTE: export_include_dir headers *should* appear in Bazel hdrs later
- "export_include_dir_1/export_include_dir_1_a.h": "",
- "export_include_dir_1/export_include_dir_1_b.h": "",
- "export_include_dir_2/export_include_dir_2_a.h": "",
- "export_include_dir_2/export_include_dir_2_b.h": "",
- // NOTE: Soong implicitly includes headers in the current directory
- "implicit_include_1.h": "",
- "implicit_include_2.h": "",
- },
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_headers {
- name: "header_lib_1",
- export_include_dirs: ["header_lib_1"],
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_headers {
- name: "header_lib_2",
- export_include_dirs: ["header_lib_2"],
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_shared {
- name: "shared_lib_1",
- srcs: ["shared_lib_1.cc"],
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_shared {
- name: "shared_lib_2",
- srcs: ["shared_lib_2.cc"],
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "whole_static_lib_1",
- srcs: ["whole_static_lib_1.cc"],
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "whole_static_lib_2",
- srcs: ["whole_static_lib_2.cc"],
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_shared {
- name: "foo_shared",
- srcs: [
- "foo_shared1.cc",
- "foo_shared2.cc",
- ],
- cflags: [
- "-Dflag1",
- "-Dflag2"
- ],
- shared_libs: [
- "shared_lib_1",
- "shared_lib_2"
- ],
- whole_static_libs: [
- "whole_static_lib_1",
- "whole_static_lib_2"
- ],
- include_dirs: [
- "include_dir_1",
- "include_dir_2",
- ],
- local_include_dirs: [
- "local_include_dir_1",
- "local_include_dir_2",
- ],
- export_include_dirs: [
- "export_include_dir_1",
- "export_include_dir_2"
- ],
- header_libs: [
- "header_lib_1",
- "header_lib_2"
- ],
- sdk_version: "current",
- min_sdk_version: "29",
-
- // TODO: Also support export_header_lib_headers
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{
- "absolute_includes": `[
- "include_dir_1",
- "include_dir_2",
- ]`,
- "copts": `[
- "-Dflag1",
- "-Dflag2",
- ]`,
- "export_includes": `[
- "export_include_dir_1",
- "export_include_dir_2",
- ]`,
- "implementation_deps": `[
- ":header_lib_1",
- ":header_lib_2",
- ]`,
- "implementation_dynamic_deps": `[
- ":shared_lib_1",
- ":shared_lib_2",
- ]`,
- "local_includes": `[
- "local_include_dir_1",
- "local_include_dir_2",
- ".",
- ]`,
- "srcs": `[
- "foo_shared1.cc",
- "foo_shared2.cc",
- ]`,
- "whole_archive_deps": `[
- ":whole_static_lib_1",
- ":whole_static_lib_2",
- ]`,
- "sdk_version": `"current"`,
- "min_sdk_version": `"29"`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedArchSpecificSharedLib(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared arch-specific shared_libs with whole_static_libs",
- Filesystem: map[string]string{},
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_static {
- name: "static_dep",
- bazel_module: { bp2build_available: false },
-}
-cc_library_shared {
- name: "shared_dep",
- bazel_module: { bp2build_available: false },
-}
-cc_library_shared {
- name: "foo_shared",
- arch: { arm64: { shared_libs: ["shared_dep"], whole_static_libs: ["static_dep"] } },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{
- "implementation_dynamic_deps": `select({
- "//build/bazel/platforms/arch:arm64": [":shared_dep"],
- "//conditions:default": [],
- })`,
- "whole_archive_deps": `select({
- "//build/bazel/platforms/arch:arm64": [":static_dep"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedOsSpecificSharedLib(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared os-specific shared_libs",
- Filesystem: map[string]string{},
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_shared {
- name: "shared_dep",
- bazel_module: { bp2build_available: false },
-}
-cc_library_shared {
- name: "foo_shared",
- target: { android: { shared_libs: ["shared_dep"], } },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{
- "implementation_dynamic_deps": `select({
- "//build/bazel/platforms/os:android": [":shared_dep"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedBaseArchOsSpecificSharedLib(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared base, arch, and os-specific shared_libs",
- Filesystem: map[string]string{},
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_shared {
- name: "shared_dep",
- bazel_module: { bp2build_available: false },
-}
-cc_library_shared {
- name: "shared_dep2",
- bazel_module: { bp2build_available: false },
-}
-cc_library_shared {
- name: "shared_dep3",
- bazel_module: { bp2build_available: false },
-}
-cc_library_shared {
- name: "foo_shared",
- shared_libs: ["shared_dep"],
- target: { android: { shared_libs: ["shared_dep2"] } },
- arch: { arm64: { shared_libs: ["shared_dep3"] } },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{
- "implementation_dynamic_deps": `[":shared_dep"] + select({
- "//build/bazel/platforms/arch:arm64": [":shared_dep3"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os:android": [":shared_dep2"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedSimpleExcludeSrcs(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared simple exclude_srcs",
- Filesystem: map[string]string{
- "common.c": "",
- "foo-a.c": "",
- "foo-excluded.c": "",
- },
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_shared {
- name: "foo_shared",
- srcs: ["common.c", "foo-*.c"],
- exclude_srcs: ["foo-excluded.c"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{
- "srcs_c": `[
- "common.c",
- "foo-a.c",
- ]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedStrip(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared stripping",
- Filesystem: map[string]string{},
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_shared {
- name: "foo_shared",
- strip: {
- keep_symbols: false,
- keep_symbols_and_debug_frame: true,
- keep_symbols_list: ["sym", "sym2"],
- all: true,
- none: false,
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{
- "strip": `{
- "all": True,
- "keep_symbols": False,
- "keep_symbols_and_debug_frame": True,
- "keep_symbols_list": [
- "sym",
- "sym2",
- ],
- "none": False,
- }`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedVersionScriptAndDynamicList(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared version script and dynamic list",
- Filesystem: map[string]string{
- "version_script": "",
- "dynamic.list": "",
- },
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_shared {
- name: "foo_shared",
- version_script: "version_script",
- dynamic_list: "dynamic.list",
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{
- "additional_linker_inputs": `[
- "version_script",
- "dynamic.list",
- ]`,
- "linkopts": `[
- "-Wl,--version-script,$(location version_script)",
- "-Wl,--dynamic-list,$(location dynamic.list)",
- ]`,
- "features": `["android_cfi_exports_map"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryLdflagsSplitBySpaceSoongAdded(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "ldflags are split by spaces except for the ones added by soong (version script and dynamic list)",
- Filesystem: map[string]string{
- "version_script": "",
- "dynamic.list": "",
- },
- Blueprint: `
-cc_library_shared {
- name: "foo",
- ldflags: [
- "--nospace_flag",
- "-z spaceflag",
- ],
- version_script: "version_script",
- dynamic_list: "dynamic.list",
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "additional_linker_inputs": `[
- "version_script",
- "dynamic.list",
- ]`,
- "linkopts": `[
- "--nospace_flag",
- "-z",
- "spaceflag",
- "-Wl,--version-script,$(location version_script)",
- "-Wl,--dynamic-list,$(location dynamic.list)",
- ]`,
- "features": `["android_cfi_exports_map"]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedNoCrtTrue(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared - nocrt: true disables feature",
- Filesystem: map[string]string{
- "impl.cpp": "",
- },
- Blueprint: soongCcLibraryPreamble + `
-cc_library_shared {
- name: "foo_shared",
- srcs: ["impl.cpp"],
- nocrt: true,
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{
- "features": `["-link_crt"]`,
- "srcs": `["impl.cpp"]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedNoCrtFalse(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared - nocrt: false doesn't disable feature",
- Filesystem: map[string]string{
- "impl.cpp": "",
- },
- Blueprint: soongCcLibraryPreamble + `
-cc_library_shared {
- name: "foo_shared",
- srcs: ["impl.cpp"],
- nocrt: false,
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{
- "srcs": `["impl.cpp"]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedNoCrtArchVariant(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared - nocrt in select",
- Filesystem: map[string]string{
- "impl.cpp": "",
- },
- Blueprint: soongCcLibraryPreamble + `
-cc_library_shared {
- name: "foo_shared",
- srcs: ["impl.cpp"],
- arch: {
- arm: {
- nocrt: true,
- },
- x86: {
- nocrt: false,
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/arch:arm": ["-link_crt"],
- "//conditions:default": [],
- })`,
- "srcs": `["impl.cpp"]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedProto(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Blueprint: soongCcProtoPreamble + `cc_library_shared {
- name: "foo",
- srcs: ["foo.proto"],
- proto: {
- export_proto_headers: true,
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
- "deps": `[":foo_proto"]`,
- }), MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "dynamic_deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedUseVersionLib(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Filesystem: map[string]string{
- soongCcVersionLibBpPath: soongCcVersionLibBp,
- },
- Blueprint: soongCcProtoPreamble + `cc_library_shared {
- name: "foo",
- use_version_lib: true,
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "use_version_lib": "True",
- "whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedStubs(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared stubs",
- ModuleTypeUnderTest: "cc_library_shared",
- ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
- Dir: "foo/bar",
- Filesystem: map[string]string{
- "foo/bar/Android.bp": `
-cc_library_shared {
- name: "a",
- stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
- bazel_module: { bp2build_available: true },
- include_build_directory: false,
-}
-`,
- },
- Blueprint: soongCcLibraryPreamble,
- ExpectedBazelTargets: []string{makeCcStubSuiteTargets("a", AttrNameToString{
- "soname": `"a.so"`,
- "source_library_label": `"//foo/bar:a"`,
- "stubs_symbol_file": `"a.map.txt"`,
- "stubs_versions": `[
- "28",
- "29",
- "current",
- ]`,
- }),
- MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
- "stubs_symbol_file": `"a.map.txt"`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedStubs_UseImplementationInSameApex(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared stubs",
- ModuleTypeUnderTest: "cc_library_shared",
- ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_shared {
- name: "a",
- stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
- bazel_module: { bp2build_available: false },
- include_build_directory: false,
- apex_available: ["made_up_apex"],
-}
-cc_library_shared {
- name: "b",
- shared_libs: [":a"],
- include_build_directory: false,
- apex_available: ["made_up_apex"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
- "implementation_dynamic_deps": `[":a"]`,
- "tags": `["apex_available=made_up_apex"]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedStubs_UseStubsInDifferentApex(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared stubs",
- ModuleTypeUnderTest: "cc_library_shared",
- ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_shared {
- name: "a",
- stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
- bazel_module: { bp2build_available: false },
- include_build_directory: false,
- apex_available: ["apex_a"],
-}
-cc_library_shared {
- name: "b",
- shared_libs: [":a"],
- include_build_directory: false,
- apex_available: ["apex_b"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
- "implementation_dynamic_deps": `select({
- "//build/bazel/rules/apex:apex_b": ["@api_surfaces//module-libapi/current:a"],
- "//build/bazel/rules/apex:system": ["@api_surfaces//module-libapi/current:a"],
- "//conditions:default": [":a"],
- })`,
- "tags": `["apex_available=apex_b"]`,
- }),
- },
- })
-}
-
-// Tests that library in apexfoo links against stubs of platform_lib and otherapex_lib
-func TestCcLibrarySharedStubs_UseStubsFromMultipleApiDomains(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared stubs",
- ModuleTypeUnderTest: "cc_library_shared",
- ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_shared {
- name: "libplatform_stable",
- stubs: { symbol_file: "libplatform_stable.map.txt", versions: ["28", "29", "current"] },
- apex_available: ["//apex_available:platform"],
- bazel_module: { bp2build_available: false },
- include_build_directory: false,
-}
-cc_library_shared {
- name: "libapexfoo_stable",
- stubs: { symbol_file: "libapexfoo_stable.map.txt", versions: ["28", "29", "current"] },
- apex_available: ["apexfoo"],
- bazel_module: { bp2build_available: false },
- include_build_directory: false,
-}
-cc_library_shared {
- name: "libutils",
- shared_libs: ["libplatform_stable", "libapexfoo_stable",],
- apex_available: ["//apex_available:platform", "apexfoo", "apexbar"],
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "libutils", AttrNameToString{
- "implementation_dynamic_deps": `select({
- "//build/bazel/rules/apex:apexbar": [
- "@api_surfaces//module-libapi/current:libplatform_stable",
- "@api_surfaces//module-libapi/current:libapexfoo_stable",
- ],
- "//build/bazel/rules/apex:apexfoo": [
- "@api_surfaces//module-libapi/current:libplatform_stable",
- ":libapexfoo_stable",
- ],
- "//build/bazel/rules/apex:system": [
- ":libplatform_stable",
- "@api_surfaces//module-libapi/current:libapexfoo_stable",
- ],
- "//conditions:default": [
- ":libplatform_stable",
- ":libapexfoo_stable",
- ],
- })`,
- "tags": `[
- "apex_available=//apex_available:platform",
- "apex_available=apexfoo",
- "apex_available=apexbar",
- ]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedStubs_IgnorePlatformAvailable(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared stubs",
- ModuleTypeUnderTest: "cc_library_shared",
- ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_shared {
- name: "a",
- stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
- bazel_module: { bp2build_available: false },
- include_build_directory: false,
- apex_available: ["//apex_available:platform", "apex_a"],
-}
-cc_library_shared {
- name: "b",
- shared_libs: [":a"],
- include_build_directory: false,
- apex_available: ["//apex_available:platform", "apex_b"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
- "implementation_dynamic_deps": `select({
- "//build/bazel/rules/apex:apex_b": ["@api_surfaces//module-libapi/current:a"],
- "//build/bazel/rules/apex:system": ["@api_surfaces//module-libapi/current:a"],
- "//conditions:default": [":a"],
- })`,
- "tags": `[
- "apex_available=//apex_available:platform",
- "apex_available=apex_b",
- ]`,
- }),
- },
- })
-}
-
-func TestCcLibraryDoesNotDropStubDepIfNoVariationAcrossAxis(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library depeends on impl for all configurations",
- ModuleTypeUnderTest: "cc_library_shared",
- ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_shared {
- name: "a",
- stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
- bazel_module: { bp2build_available: false },
- apex_available: ["//apex_available:platform"],
-}
-cc_library_shared {
- name: "b",
- shared_libs: [":a"],
- include_build_directory: false,
- apex_available: ["//apex_available:platform"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
- "implementation_dynamic_deps": `[":a"]`,
- "tags": `["apex_available=//apex_available:platform"]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedStubs_MultipleApexAvailable(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_library_shared",
- ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_shared {
- name: "a",
- stubs: { symbol_file: "a.map.txt", versions: ["28", "29", "current"] },
- bazel_module: { bp2build_available: false },
- include_build_directory: false,
- apex_available: ["//apex_available:platform", "apex_a", "apex_b"],
-}
-cc_library_shared {
- name: "b",
- shared_libs: [":a"],
- include_build_directory: false,
- apex_available: ["//apex_available:platform", "apex_b"],
-}
-
-cc_library_shared {
- name: "c",
- shared_libs: [":a"],
- include_build_directory: false,
- apex_available: ["//apex_available:platform", "apex_a", "apex_b"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
- "implementation_dynamic_deps": `select({
- "//build/bazel/rules/apex:system": ["@api_surfaces//module-libapi/current:a"],
- "//conditions:default": [":a"],
- })`,
- "tags": `[
- "apex_available=//apex_available:platform",
- "apex_available=apex_b",
- ]`,
- }),
- MakeBazelTarget("cc_library_shared", "c", AttrNameToString{
- "implementation_dynamic_deps": `[":a"]`,
- "tags": `[
- "apex_available=//apex_available:platform",
- "apex_available=apex_a",
- "apex_available=apex_b",
- ]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedSystemSharedLibsSharedEmpty(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared system_shared_libs empty shared default",
- ModuleTypeUnderTest: "cc_library_shared",
- ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_defaults {
- name: "empty_defaults",
- shared: {
- system_shared_libs: [],
- },
- include_build_directory: false,
-}
-cc_library_shared {
- name: "empty",
- defaults: ["empty_defaults"],
-}
-`,
- ExpectedBazelTargets: []string{MakeBazelTarget("cc_library_shared", "empty", AttrNameToString{
- "system_dynamic_deps": "[]",
- })},
- })
-}
-
-func TestCcLibrarySharedConvertLex(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared with lex files",
- ModuleTypeUnderTest: "cc_library_shared",
- ModuleTypeUnderTestFactory: cc.LibrarySharedFactory,
- Filesystem: map[string]string{
- "foo.c": "",
- "bar.cc": "",
- "foo1.l": "",
- "bar1.ll": "",
- "foo2.l": "",
- "bar2.ll": "",
- },
- Blueprint: `cc_library_shared {
- name: "foo_lib",
- srcs: ["foo.c", "bar.cc", "foo1.l", "foo2.l", "bar1.ll", "bar2.ll"],
- lex: { flags: ["--foo_flags"] },
- include_build_directory: false,
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("genlex", "foo_lib_genlex_l", AttrNameToString{
- "srcs": `[
- "foo1.l",
- "foo2.l",
- ]`,
- "lexopts": `["--foo_flags"]`,
- }),
- MakeBazelTarget("genlex", "foo_lib_genlex_ll", AttrNameToString{
- "srcs": `[
- "bar1.ll",
- "bar2.ll",
- ]`,
- "lexopts": `["--foo_flags"]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo_lib", AttrNameToString{
- "srcs": `[
- "bar.cc",
- ":foo_lib_genlex_ll",
- ]`,
- "srcs_c": `[
- "foo.c",
- ":foo_lib_genlex_l",
- ]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedClangUnknownFlags(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Blueprint: soongCcProtoPreamble + `cc_library_shared {
- name: "foo",
- conlyflags: ["-a", "-finline-functions"],
- cflags: ["-b","-finline-functions"],
- cppflags: ["-c", "-finline-functions"],
- ldflags: ["-d","-finline-functions", "-e"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "conlyflags": `["-a"]`,
- "copts": `["-b"]`,
- "cppflags": `["-c"]`,
- "linkopts": `[
- "-d",
- "-e",
- ]`,
- }),
- },
- })
-}
-
-func TestCCLibraryFlagSpaceSplitting(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Blueprint: soongCcProtoPreamble + `cc_library_shared {
- name: "foo",
- conlyflags: [ "-include header.h"],
- cflags: ["-include header.h"],
- cppflags: ["-include header.h"],
- version_script: "version_script",
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "additional_linker_inputs": `["version_script"]`,
- "conlyflags": `[
- "-include",
- "header.h",
- ]`,
- "copts": `[
- "-include",
- "header.h",
- ]`,
- "cppflags": `[
- "-include",
- "header.h",
- ]`,
- "linkopts": `["-Wl,--version-script,$(location version_script)"]`,
- "features": `["android_cfi_exports_map"]`,
- }),
- },
- })
-}
-
-func TestCCLibrarySharedRuntimeDeps(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Blueprint: `cc_library_shared {
- name: "bar",
-}
-
-cc_library_shared {
- name: "foo",
- runtime_libs: ["foo"],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "bar", AttrNameToString{
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "runtime_deps": `[":foo"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedEmptySuffix(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared with empty suffix",
- Filesystem: map[string]string{
- "foo.c": "",
- },
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_shared {
- name: "foo_shared",
- suffix: "",
- srcs: ["foo.c"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{
- "srcs_c": `["foo.c"]`,
- "suffix": `""`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedSuffix(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared with suffix",
- Filesystem: map[string]string{
- "foo.c": "",
- },
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_shared {
- name: "foo_shared",
- suffix: "-suf",
- srcs: ["foo.c"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{
- "srcs_c": `["foo.c"]`,
- "suffix": `"-suf"`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedArchVariantSuffix(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared with arch-variant suffix",
- Filesystem: map[string]string{
- "foo.c": "",
- },
- Blueprint: soongCcLibrarySharedPreamble + `
-cc_library_shared {
- name: "foo_shared",
- arch: {
- arm64: { suffix: "-64" },
- arm: { suffix: "-32" },
- },
- srcs: ["foo.c"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo_shared", AttrNameToString{
- "srcs_c": `["foo.c"]`,
- "suffix": `select({
- "//build/bazel/platforms/arch:arm": "-32",
- "//build/bazel/platforms/arch:arm64": "-64",
- "//conditions:default": None,
- })`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedWithSyspropSrcs(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared with sysprop sources",
- Blueprint: `
-cc_library_shared {
- name: "foo",
- srcs: [
- "bar.sysprop",
- "baz.sysprop",
- "blah.cpp",
- ],
- min_sdk_version: "5",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("sysprop_library", "foo_sysprop_library", AttrNameToString{
- "srcs": `[
- "bar.sysprop",
- "baz.sysprop",
- ]`,
- }),
- MakeBazelTarget("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
- "dep": `":foo_sysprop_library"`,
- "min_sdk_version": `"5"`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "srcs": `["blah.cpp"]`,
- "local_includes": `["."]`,
- "min_sdk_version": `"5"`,
- "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedWithSyspropSrcsSomeConfigs(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared with sysprop sources in some configs but not others",
- Blueprint: `
-cc_library_shared {
- name: "foo",
- srcs: [
- "blah.cpp",
- ],
- target: {
- android: {
- srcs: ["bar.sysprop"],
- },
- },
- min_sdk_version: "5",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("sysprop_library", "foo_sysprop_library", AttrNameToString{
- "srcs": `select({
- "//build/bazel/platforms/os:android": ["bar.sysprop"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
- "dep": `":foo_sysprop_library"`,
- "min_sdk_version": `"5"`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "srcs": `["blah.cpp"]`,
- "local_includes": `["."]`,
- "min_sdk_version": `"5"`,
- "whole_archive_deps": `select({
- "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedHeaderAbiChecker(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared with header abi checker",
- Blueprint: `cc_library_shared {
- name: "foo",
- header_abi_checker: {
- enabled: true,
- symbol_file: "a.map.txt",
- exclude_symbol_versions: [
- "29",
- "30",
- ],
- exclude_symbol_tags: [
- "tag1",
- "tag2",
- ],
- check_all_apis: true,
- diff_flags: ["-allow-adding-removing-weak-symbols"],
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "abi_checker_enabled": `True`,
- "abi_checker_symbol_file": `"a.map.txt"`,
- "abi_checker_exclude_symbol_versions": `[
- "29",
- "30",
- ]`,
- "abi_checker_exclude_symbol_tags": `[
- "tag1",
- "tag2",
- ]`,
- "abi_checker_check_all_apis": `True`,
- "abi_checker_diff_flags": `["-allow-adding-removing-weak-symbols"]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedWithIntegerOverflowProperty(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared has correct features when integer_overflow property is provided",
- Blueprint: `
-cc_library_shared {
- name: "foo",
- sanitize: {
- integer_overflow: true,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `["ubsan_integer_overflow"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedWithMiscUndefinedProperty(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared has correct features when misc_undefined property is provided",
- Blueprint: `
-cc_library_shared {
- name: "foo",
- sanitize: {
- misc_undefined: ["undefined", "nullability"],
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `[
- "ubsan_undefined",
- "ubsan_nullability",
- ]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedWithUBSanPropertiesArchSpecific(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared has correct feature select when UBSan props are specified in arch specific blocks",
- Blueprint: `
-cc_library_shared {
- name: "foo",
- sanitize: {
- misc_undefined: ["undefined", "nullability"],
- },
- target: {
- android: {
- sanitize: {
- misc_undefined: ["alignment"],
- },
- },
- linux_glibc: {
- sanitize: {
- integer_overflow: true,
- },
- },
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `[
- "ubsan_undefined",
- "ubsan_nullability",
- ] + select({
- "//build/bazel/platforms/os:android": ["ubsan_alignment"],
- "//build/bazel/platforms/os:linux_glibc": ["ubsan_integer_overflow"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedWithSanitizerBlocklist(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared has correct features when sanitize.blocklist is provided",
- Blueprint: `
-cc_library_shared {
- name: "foo",
- sanitize: {
- blocklist: "foo_blocklist.txt",
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "copts": `select({
- "//build/bazel/rules/cc:sanitizers_enabled": ["-fsanitize-ignorelist=$(location foo_blocklist.txt)"],
- "//conditions:default": [],
- })`,
- "additional_compiler_inputs": `select({
- "//build/bazel/rules/cc:sanitizers_enabled": [":foo_blocklist.txt"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedWithThinLto(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared has correct features when thin lto is enabled",
- Blueprint: `
-cc_library_shared {
- name: "foo",
- lto: {
- thin: true,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `["android_thin_lto"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedWithLtoNever(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared has correct features when thin lto is enabled",
- Blueprint: `
-cc_library_shared {
- name: "foo",
- lto: {
- never: true,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `["-android_thin_lto"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedWithThinLtoArchSpecific(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared has correct features when LTO differs across arch and os variants",
- Blueprint: `
-cc_library_shared {
- name: "foo",
- target: {
- android: {
- lto: {
- thin: true,
- },
- },
- },
- arch: {
- riscv64: {
- lto: {
- thin: false,
- },
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm": ["android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_arm64": ["android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_riscv64": ["-android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_x86": ["android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_x86_64": ["android_thin_lto"],
- "//conditions:default": [],
- })`}),
- },
- })
-}
-
-func TestCcLibrarySharedWithThinLtoDisabledDefaultEnabledVariant(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared with thin lto disabled by default but enabled on a particular variant",
- Blueprint: `
-cc_library_shared {
- name: "foo",
- lto: {
- never: true,
- },
- target: {
- android: {
- lto: {
- thin: true,
- never: false,
- },
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `select({
- "//build/bazel/platforms/os:android": ["android_thin_lto"],
- "//conditions:default": ["-android_thin_lto"],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedWithThinLtoAndWholeProgramVtables(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared has correct features when thin LTO is enabled with whole_program_vtables",
- Blueprint: `
-cc_library_shared {
- name: "foo",
- lto: {
- thin: true,
- },
- whole_program_vtables: true,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `[
- "android_thin_lto",
- "android_thin_lto_whole_program_vtables",
- ]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedHiddenVisibilityConvertedToFeature(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared changes hidden visibility flag to feature",
- Blueprint: `
-cc_library_shared{
- name: "foo",
- cflags: ["-fvisibility=hidden"],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `["visibility_hidden"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedHiddenVisibilityConvertedToFeatureOsSpecific(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared changes hidden visibility flag to feature for specific os",
- Blueprint: `
-cc_library_shared{
- name: "foo",
- target: {
- android: {
- cflags: ["-fvisibility=hidden"],
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/os:android": ["visibility_hidden"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedStubsDessertVersionConversion(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared converts dessert codename versions to numerical versions",
- Blueprint: `
-cc_library_shared {
- name: "a",
- include_build_directory: false,
- stubs: {
- symbol_file: "a.map.txt",
- versions: [
- "Q",
- "R",
- "31",
- ],
- },
-}
-cc_library_shared {
- name: "b",
- include_build_directory: false,
- stubs: {
- symbol_file: "b.map.txt",
- versions: [
- "Q",
- "R",
- "31",
- "current",
- ],
- },
-}
-`,
- ExpectedBazelTargets: []string{
- makeCcStubSuiteTargets("a", AttrNameToString{
- "soname": `"a.so"`,
- "source_library_label": `"//:a"`,
- "stubs_symbol_file": `"a.map.txt"`,
- "stubs_versions": `[
- "29",
- "30",
- "31",
- "current",
- ]`,
- }),
- MakeBazelTarget("cc_library_shared", "a", AttrNameToString{
- "stubs_symbol_file": `"a.map.txt"`,
- }),
- makeCcStubSuiteTargets("b", AttrNameToString{
- "soname": `"b.so"`,
- "source_library_label": `"//:b"`,
- "stubs_symbol_file": `"b.map.txt"`,
- "stubs_versions": `[
- "29",
- "30",
- "31",
- "current",
- ]`,
- }),
- MakeBazelTarget("cc_library_shared", "b", AttrNameToString{
- "stubs_symbol_file": `"b.map.txt"`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedWithCfi(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared has correct features when cfi is enabled for specific variants",
- Blueprint: `
-cc_library_shared {
- name: "foo",
- sanitize: {
- cfi: true,
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `["android_cfi"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedWithCfiOsSpecific(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared has correct features when cfi is enabled",
- Blueprint: `
-cc_library_shared {
- name: "foo",
- target: {
- android: {
- sanitize: {
- cfi: true,
- },
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/os:android": ["android_cfi"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedWithCfiAndCfiAssemblySupport(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared has correct features when cfi is enabled with cfi assembly support",
- Blueprint: `
-cc_library_static {
- name: "foo",
- sanitize: {
- cfi: true,
- config: {
- cfi_assembly_support: true,
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "features": `[
- "android_cfi",
- "android_cfi_assembly_support",
- ]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibrarySharedExplicitlyDisablesCfiWhenFalse(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_shared disables cfi when explciitly set to false in the bp",
- Blueprint: `
-cc_library_shared {
- name: "foo",
- sanitize: {
- cfi: false,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "features": `["-android_cfi"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCCLibrarySharedRscriptSrc(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: ``,
- Blueprint: `
-cc_library_shared{
- name : "foo",
- srcs : [
- "ccSrc.cc",
- "rsSrc.rscript",
- ],
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("rscript_to_cpp", "foo_renderscript", AttrNameToString{
- "srcs": `["rsSrc.rscript"]`,
- }),
- MakeBazelTarget("cc_library_shared", "foo", AttrNameToString{
- "absolute_includes": `[
- "frameworks/rs",
- "frameworks/rs/cpp",
- ]`,
- "local_includes": `["."]`,
- "srcs": `[
- "ccSrc.cc",
- "foo_renderscript",
- ]`,
- })}})
-}
diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go
deleted file mode 100644
index 89ec8f9..0000000
--- a/bp2build/cc_library_static_conversion_test.go
+++ /dev/null
@@ -1,2291 +0,0 @@
-// 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
-
-import (
- "fmt"
- "testing"
-
- "android/soong/android"
- "android/soong/cc"
- "android/soong/genrule"
-)
-
-const (
- // See cc/testing.go for more context
- soongCcLibraryStaticPreamble = `
-cc_defaults {
- name: "linux_bionic_supported",
-}`
-)
-
-func TestCcLibraryStaticLoadStatement(t *testing.T) {
- testCases := []struct {
- bazelTargets BazelTargets
- expectedLoadStatements string
- }{
- {
- bazelTargets: BazelTargets{
- BazelTarget{
- name: "cc_library_static_target",
- ruleClass: "cc_library_static",
- // NOTE: No bzlLoadLocation for native rules
- },
- },
- expectedLoadStatements: ``,
- },
- }
-
- for _, testCase := range testCases {
- actual := testCase.bazelTargets.LoadStatements()
- expected := testCase.expectedLoadStatements
- if actual != expected {
- t.Fatalf("Expected load statements to be %s, got %s", expected, actual)
- }
- }
-}
-
-func registerCcLibraryStaticModuleTypes(ctx android.RegistrationContext) {
- cc.RegisterCCBuildComponents(ctx)
- ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
- ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
- // Required for system_shared_libs dependencies.
- ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
-}
-
-func runCcLibraryStaticTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
-
- (&tc).ModuleTypeUnderTest = "cc_library_static"
- (&tc).ModuleTypeUnderTestFactory = cc.LibraryStaticFactory
- RunBp2BuildTestCase(t, registerCcLibraryStaticModuleTypes, tc)
-}
-
-func TestCcLibraryStaticSimple(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static test",
- Filesystem: map[string]string{
- // NOTE: include_dir headers *should not* appear in Bazel hdrs later (?)
- "include_dir_1/include_dir_1_a.h": "",
- "include_dir_1/include_dir_1_b.h": "",
- "include_dir_2/include_dir_2_a.h": "",
- "include_dir_2/include_dir_2_b.h": "",
- // NOTE: local_include_dir headers *should not* appear in Bazel hdrs later (?)
- "local_include_dir_1/local_include_dir_1_a.h": "",
- "local_include_dir_1/local_include_dir_1_b.h": "",
- "local_include_dir_2/local_include_dir_2_a.h": "",
- "local_include_dir_2/local_include_dir_2_b.h": "",
- // NOTE: export_include_dir headers *should* appear in Bazel hdrs later
- "export_include_dir_1/export_include_dir_1_a.h": "",
- "export_include_dir_1/export_include_dir_1_b.h": "",
- "export_include_dir_2/export_include_dir_2_a.h": "",
- "export_include_dir_2/export_include_dir_2_b.h": "",
- // NOTE: Soong implicitly includes headers in the current directory
- "implicit_include_1.h": "",
- "implicit_include_2.h": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_headers {
- name: "header_lib_1",
- export_include_dirs: ["header_lib_1"],
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_headers {
- name: "header_lib_2",
- export_include_dirs: ["header_lib_2"],
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "static_lib_1",
- srcs: ["static_lib_1.cc"],
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "static_lib_2",
- srcs: ["static_lib_2.cc"],
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "whole_static_lib_1",
- srcs: ["whole_static_lib_1.cc"],
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "whole_static_lib_2",
- srcs: ["whole_static_lib_2.cc"],
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "foo_static",
- srcs: [
- "foo_static1.cc",
- "foo_static2.cc",
- ],
- cflags: [
- "-Dflag1",
- "-Dflag2"
- ],
- static_libs: [
- "static_lib_1",
- "static_lib_2"
- ],
- whole_static_libs: [
- "whole_static_lib_1",
- "whole_static_lib_2"
- ],
- include_dirs: [
- "include_dir_1",
- "include_dir_2",
- ],
- local_include_dirs: [
- "local_include_dir_1",
- "local_include_dir_2",
- ],
- export_include_dirs: [
- "export_include_dir_1",
- "export_include_dir_2"
- ],
- header_libs: [
- "header_lib_1",
- "header_lib_2"
- ],
- sdk_version: "current",
- min_sdk_version: "29",
-
- // TODO: Also support export_header_lib_headers
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "absolute_includes": `[
- "include_dir_1",
- "include_dir_2",
- ]`,
- "copts": `[
- "-Dflag1",
- "-Dflag2",
- ]`,
- "export_includes": `[
- "export_include_dir_1",
- "export_include_dir_2",
- ]`,
- "implementation_deps": `[
- ":header_lib_1",
- ":header_lib_2",
- ":static_lib_1",
- ":static_lib_2",
- ]`,
- "local_includes": `[
- "local_include_dir_1",
- "local_include_dir_2",
- ".",
- ]`,
- "srcs": `[
- "foo_static1.cc",
- "foo_static2.cc",
- ]`,
- "whole_archive_deps": `[
- ":whole_static_lib_1",
- ":whole_static_lib_2",
- ]`,
- "sdk_version": `"current"`,
- "min_sdk_version": `"29"`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticSubpackage(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static subpackage test",
- Filesystem: map[string]string{
- // subpackage with subdirectory
- "subpackage/Android.bp": "",
- "subpackage/subpackage_header.h": "",
- "subpackage/subdirectory/subdirectory_header.h": "",
- // subsubpackage with subdirectory
- "subpackage/subsubpackage/Android.bp": "",
- "subpackage/subsubpackage/subsubpackage_header.h": "",
- "subpackage/subsubpackage/subdirectory/subdirectory_header.h": "",
- // subsubsubpackage with subdirectory
- "subpackage/subsubpackage/subsubsubpackage/Android.bp": "",
- "subpackage/subsubpackage/subsubsubpackage/subsubsubpackage_header.h": "",
- "subpackage/subsubpackage/subsubsubpackage/subdirectory/subdirectory_header.h": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- srcs: [],
- include_dirs: [
- "subpackage",
- ],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "absolute_includes": `["subpackage"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticExportIncludeDir(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static export include dir",
- Filesystem: map[string]string{
- // subpackage with subdirectory
- "subpackage/Android.bp": "",
- "subpackage/subpackage_header.h": "",
- "subpackage/subdirectory/subdirectory_header.h": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- export_include_dirs: ["subpackage"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "export_includes": `["subpackage"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticExportSystemIncludeDir(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static export system include dir",
- Filesystem: map[string]string{
- // subpackage with subdirectory
- "subpackage/Android.bp": "",
- "subpackage/subpackage_header.h": "",
- "subpackage/subdirectory/subdirectory_header.h": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- export_system_include_dirs: ["subpackage"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "export_system_includes": `["subpackage"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticManyIncludeDirs(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static include_dirs, local_include_dirs, export_include_dirs (b/183742505)",
- Dir: "subpackage",
- Filesystem: map[string]string{
- // subpackage with subdirectory
- "subpackage/Android.bp": `
-cc_library_static {
- name: "foo_static",
- // include_dirs are workspace/root relative
- include_dirs: [
- "subpackage/subsubpackage",
- "subpackage2",
- "subpackage3/subsubpackage"
- ],
- local_include_dirs: ["subsubpackage2"], // module dir relative
- export_include_dirs: ["./exported_subsubpackage"], // module dir relative
- include_build_directory: true,
- bazel_module: { bp2build_available: true },
-}`,
- "subpackage/subsubpackage/header.h": "",
- "subpackage/subsubpackage2/header.h": "",
- "subpackage/exported_subsubpackage/header.h": "",
- "subpackage2/header.h": "",
- "subpackage3/subsubpackage/header.h": "",
- },
- Blueprint: soongCcLibraryStaticPreamble,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "absolute_includes": `[
- "subpackage/subsubpackage",
- "subpackage2",
- "subpackage3/subsubpackage",
- ]`,
- "export_includes": `["./exported_subsubpackage"]`,
- "local_includes": `[
- "subsubpackage2",
- ".",
- ]`,
- })},
- })
-}
-
-func TestCcLibraryStaticIncludeBuildDirectoryDisabled(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static include_build_directory disabled",
- Filesystem: map[string]string{
- // subpackage with subdirectory
- "subpackage/Android.bp": "",
- "subpackage/subpackage_header.h": "",
- "subpackage/subdirectory/subdirectory_header.h": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- include_dirs: ["subpackage"], // still used, but local_include_dirs is recommended
- local_include_dirs: ["subpackage2"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "absolute_includes": `["subpackage"]`,
- "local_includes": `["subpackage2"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticIncludeBuildDirectoryEnabled(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static include_build_directory enabled",
- Filesystem: map[string]string{
- // subpackage with subdirectory
- "subpackage/Android.bp": "",
- "subpackage/subpackage_header.h": "",
- "subpackage2/Android.bp": "",
- "subpackage2/subpackage2_header.h": "",
- "subpackage/subdirectory/subdirectory_header.h": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- include_dirs: ["subpackage"], // still used, but local_include_dirs is recommended
- local_include_dirs: ["subpackage2"],
- include_build_directory: true,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "absolute_includes": `["subpackage"]`,
- "local_includes": `[
- "subpackage2",
- ".",
- ]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticArchSpecificStaticLib(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static arch-specific static_libs",
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "static_dep",
- bazel_module: { bp2build_available: false },
-}
-cc_library_static {
- name: "static_dep2",
- bazel_module: { bp2build_available: false },
-}
-cc_library_static {
- name: "foo_static",
- arch: { arm64: { static_libs: ["static_dep"], whole_static_libs: ["static_dep2"] } },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "implementation_deps": `select({
- "//build/bazel/platforms/arch:arm64": [":static_dep"],
- "//conditions:default": [],
- })`,
- "whole_archive_deps": `select({
- "//build/bazel/platforms/arch:arm64": [":static_dep2"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticOsSpecificStaticLib(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static os-specific static_libs",
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "static_dep",
- bazel_module: { bp2build_available: false },
-}
-cc_library_static {
- name: "static_dep2",
- bazel_module: { bp2build_available: false },
-}
-cc_library_static {
- name: "foo_static",
- target: { android: { static_libs: ["static_dep"], whole_static_libs: ["static_dep2"] } },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "implementation_deps": `select({
- "//build/bazel/platforms/os:android": [":static_dep"],
- "//conditions:default": [],
- })`,
- "whole_archive_deps": `select({
- "//build/bazel/platforms/os:android": [":static_dep2"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticBaseArchOsSpecificStaticLib(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static base, arch and os-specific static_libs",
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "static_dep",
- bazel_module: { bp2build_available: false },
-}
-cc_library_static {
- name: "static_dep2",
- bazel_module: { bp2build_available: false },
-}
-cc_library_static {
- name: "static_dep3",
- bazel_module: { bp2build_available: false },
-}
-cc_library_static {
- name: "static_dep4",
- bazel_module: { bp2build_available: false },
-}
-cc_library_static {
- name: "foo_static",
- static_libs: ["static_dep"],
- whole_static_libs: ["static_dep2"],
- target: { android: { static_libs: ["static_dep3"] } },
- arch: { arm64: { static_libs: ["static_dep4"] } },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "implementation_deps": `[":static_dep"] + select({
- "//build/bazel/platforms/arch:arm64": [":static_dep4"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os:android": [":static_dep3"],
- "//conditions:default": [],
- })`,
- "whole_archive_deps": `[":static_dep2"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticSimpleExcludeSrcs(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static simple exclude_srcs",
- Filesystem: map[string]string{
- "common.c": "",
- "foo-a.c": "",
- "foo-excluded.c": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- srcs: ["common.c", "foo-*.c"],
- exclude_srcs: ["foo-excluded.c"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "srcs_c": `[
- "common.c",
- "foo-a.c",
- ]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticOneArchSrcs(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static one arch specific srcs",
- Filesystem: map[string]string{
- "common.c": "",
- "foo-arm.c": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- srcs: ["common.c"],
- arch: { arm: { srcs: ["foo-arm.c"] } },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "srcs_c": `["common.c"] + select({
- "//build/bazel/platforms/arch:arm": ["foo-arm.c"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticOneArchSrcsExcludeSrcs(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static one arch specific srcs and exclude_srcs",
- Filesystem: map[string]string{
- "common.c": "",
- "for-arm.c": "",
- "not-for-arm.c": "",
- "not-for-anything.c": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- srcs: ["common.c", "not-for-*.c"],
- exclude_srcs: ["not-for-anything.c"],
- arch: {
- arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "srcs_c": `["common.c"] + select({
- "//build/bazel/platforms/arch:arm": ["for-arm.c"],
- "//conditions:default": ["not-for-arm.c"],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticTwoArchExcludeSrcs(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static arch specific exclude_srcs for 2 architectures",
- Filesystem: map[string]string{
- "common.c": "",
- "for-arm.c": "",
- "for-x86.c": "",
- "not-for-arm.c": "",
- "not-for-x86.c": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- srcs: ["common.c", "not-for-*.c"],
- exclude_srcs: ["not-for-everything.c"],
- arch: {
- arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
- x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] },
- },
- include_build_directory: false,
-} `,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "srcs_c": `["common.c"] + select({
- "//build/bazel/platforms/arch:arm": [
- "not-for-x86.c",
- "for-arm.c",
- ],
- "//build/bazel/platforms/arch:x86": [
- "not-for-arm.c",
- "for-x86.c",
- ],
- "//conditions:default": [
- "not-for-arm.c",
- "not-for-x86.c",
- ],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticFourArchExcludeSrcs(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static arch specific exclude_srcs for 4 architectures",
- Filesystem: map[string]string{
- "common.c": "",
- "for-arm.c": "",
- "for-arm64.c": "",
- "for-x86.c": "",
- "for-x86_64.c": "",
- "not-for-arm.c": "",
- "not-for-arm64.c": "",
- "not-for-x86.c": "",
- "not-for-x86_64.c": "",
- "not-for-everything.c": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- srcs: ["common.c", "not-for-*.c"],
- exclude_srcs: ["not-for-everything.c"],
- arch: {
- arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
- arm64: { srcs: ["for-arm64.c"], exclude_srcs: ["not-for-arm64.c"] },
- x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] },
- x86_64: { srcs: ["for-x86_64.c"], exclude_srcs: ["not-for-x86_64.c"] },
- },
- include_build_directory: false,
-} `,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "srcs_c": `["common.c"] + select({
- "//build/bazel/platforms/arch:arm": [
- "not-for-arm64.c",
- "not-for-x86.c",
- "not-for-x86_64.c",
- "for-arm.c",
- ],
- "//build/bazel/platforms/arch:arm64": [
- "not-for-arm.c",
- "not-for-x86.c",
- "not-for-x86_64.c",
- "for-arm64.c",
- ],
- "//build/bazel/platforms/arch:x86": [
- "not-for-arm.c",
- "not-for-arm64.c",
- "not-for-x86_64.c",
- "for-x86.c",
- ],
- "//build/bazel/platforms/arch:x86_64": [
- "not-for-arm.c",
- "not-for-arm64.c",
- "not-for-x86.c",
- "for-x86_64.c",
- ],
- "//conditions:default": [
- "not-for-arm.c",
- "not-for-arm64.c",
- "not-for-x86.c",
- "not-for-x86_64.c",
- ],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticOneArchEmpty(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static one arch empty",
- Filesystem: map[string]string{
- "common.cc": "",
- "foo-no-arm.cc": "",
- "foo-excluded.cc": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- srcs: ["common.cc", "foo-*.cc"],
- exclude_srcs: ["foo-excluded.cc"],
- arch: {
- arm: { exclude_srcs: ["foo-no-arm.cc"] },
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "srcs": `["common.cc"] + select({
- "//build/bazel/platforms/arch:arm": [],
- "//conditions:default": ["foo-no-arm.cc"],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticOneArchEmptyOtherSet(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static one arch empty other set",
- Filesystem: map[string]string{
- "common.cc": "",
- "foo-no-arm.cc": "",
- "x86-only.cc": "",
- "foo-excluded.cc": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- srcs: ["common.cc", "foo-*.cc"],
- exclude_srcs: ["foo-excluded.cc"],
- arch: {
- arm: { exclude_srcs: ["foo-no-arm.cc"] },
- x86: { srcs: ["x86-only.cc"] },
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "srcs": `["common.cc"] + select({
- "//build/bazel/platforms/arch:arm": [],
- "//build/bazel/platforms/arch:x86": [
- "foo-no-arm.cc",
- "x86-only.cc",
- ],
- "//conditions:default": ["foo-no-arm.cc"],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticMultipleDepSameName(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static multiple dep same name panic",
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "static_dep",
- bazel_module: { bp2build_available: false },
-}
-cc_library_static {
- name: "foo_static",
- static_libs: ["static_dep", "static_dep"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "implementation_deps": `[":static_dep"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticOneMultilibSrcsExcludeSrcs(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static 1 multilib srcs and exclude_srcs",
- Filesystem: map[string]string{
- "common.c": "",
- "for-lib32.c": "",
- "not-for-lib32.c": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- srcs: ["common.c", "not-for-*.c"],
- multilib: {
- lib32: { srcs: ["for-lib32.c"], exclude_srcs: ["not-for-lib32.c"] },
- },
- include_build_directory: false,
-} `,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "srcs_c": `["common.c"] + select({
- "//build/bazel/platforms/arch:arm": ["for-lib32.c"],
- "//build/bazel/platforms/arch:x86": ["for-lib32.c"],
- "//conditions:default": ["not-for-lib32.c"],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticTwoMultilibSrcsExcludeSrcs(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static 2 multilib srcs and exclude_srcs",
- Filesystem: map[string]string{
- "common.c": "",
- "for-lib32.c": "",
- "for-lib64.c": "",
- "not-for-lib32.c": "",
- "not-for-lib64.c": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- srcs: ["common.c", "not-for-*.c"],
- multilib: {
- lib32: { srcs: ["for-lib32.c"], exclude_srcs: ["not-for-lib32.c"] },
- lib64: { srcs: ["for-lib64.c"], exclude_srcs: ["not-for-lib64.c"] },
- },
- include_build_directory: false,
-} `,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "srcs_c": `["common.c"] + select({
- "//build/bazel/platforms/arch:arm": [
- "not-for-lib64.c",
- "for-lib32.c",
- ],
- "//build/bazel/platforms/arch:arm64": [
- "not-for-lib32.c",
- "for-lib64.c",
- ],
- "//build/bazel/platforms/arch:riscv64": [
- "not-for-lib32.c",
- "for-lib64.c",
- ],
- "//build/bazel/platforms/arch:x86": [
- "not-for-lib64.c",
- "for-lib32.c",
- ],
- "//build/bazel/platforms/arch:x86_64": [
- "not-for-lib32.c",
- "for-lib64.c",
- ],
- "//conditions:default": [
- "not-for-lib32.c",
- "not-for-lib64.c",
- ],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibrarySTaticArchMultilibSrcsExcludeSrcs(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static arch and multilib srcs and exclude_srcs",
- Filesystem: map[string]string{
- "common.c": "",
- "for-arm.c": "",
- "for-arm64.c": "",
- "for-x86.c": "",
- "for-x86_64.c": "",
- "for-lib32.c": "",
- "for-lib64.c": "",
- "not-for-arm.c": "",
- "not-for-arm64.c": "",
- "not-for-riscv64.c": "",
- "not-for-x86.c": "",
- "not-for-x86_64.c": "",
- "not-for-lib32.c": "",
- "not-for-lib64.c": "",
- "not-for-everything.c": "",
- },
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- srcs: ["common.c", "not-for-*.c"],
- exclude_srcs: ["not-for-everything.c"],
- arch: {
- arm: { srcs: ["for-arm.c"], exclude_srcs: ["not-for-arm.c"] },
- arm64: { srcs: ["for-arm64.c"], exclude_srcs: ["not-for-arm64.c"] },
- riscv64: { srcs: ["for-riscv64.c"], exclude_srcs: ["not-for-riscv64.c"] },
- x86: { srcs: ["for-x86.c"], exclude_srcs: ["not-for-x86.c"] },
- x86_64: { srcs: ["for-x86_64.c"], exclude_srcs: ["not-for-x86_64.c"] },
- },
- multilib: {
- lib32: { srcs: ["for-lib32.c"], exclude_srcs: ["not-for-lib32.c"] },
- lib64: { srcs: ["for-lib64.c"], exclude_srcs: ["not-for-lib64.c"] },
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "srcs_c": `["common.c"] + select({
- "//build/bazel/platforms/arch:arm": [
- "not-for-arm64.c",
- "not-for-lib64.c",
- "not-for-riscv64.c",
- "not-for-x86.c",
- "not-for-x86_64.c",
- "for-arm.c",
- "for-lib32.c",
- ],
- "//build/bazel/platforms/arch:arm64": [
- "not-for-arm.c",
- "not-for-lib32.c",
- "not-for-riscv64.c",
- "not-for-x86.c",
- "not-for-x86_64.c",
- "for-arm64.c",
- "for-lib64.c",
- ],
- "//build/bazel/platforms/arch:riscv64": [
- "not-for-arm.c",
- "not-for-arm64.c",
- "not-for-lib32.c",
- "not-for-x86.c",
- "not-for-x86_64.c",
- "for-riscv64.c",
- "for-lib64.c",
- ],
- "//build/bazel/platforms/arch:x86": [
- "not-for-arm.c",
- "not-for-arm64.c",
- "not-for-lib64.c",
- "not-for-riscv64.c",
- "not-for-x86_64.c",
- "for-x86.c",
- "for-lib32.c",
- ],
- "//build/bazel/platforms/arch:x86_64": [
- "not-for-arm.c",
- "not-for-arm64.c",
- "not-for-lib32.c",
- "not-for-riscv64.c",
- "not-for-x86.c",
- "for-x86_64.c",
- "for-lib64.c",
- ],
- "//conditions:default": [
- "not-for-arm.c",
- "not-for-arm64.c",
- "not-for-lib32.c",
- "not-for-lib64.c",
- "not-for-riscv64.c",
- "not-for-x86.c",
- "not-for-x86_64.c",
- ],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticGeneratedHeadersAllPartitions(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Blueprint: soongCcLibraryStaticPreamble + `
-genrule {
- name: "generated_hdr",
- cmd: "nothing to see here",
- bazel_module: { bp2build_available: false },
-}
-
-genrule {
- name: "export_generated_hdr",
- cmd: "nothing to see here",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "foo_static",
- srcs: ["cpp_src.cpp", "as_src.S", "c_src.c"],
- generated_headers: ["generated_hdr", "export_generated_hdr"],
- export_generated_headers: ["export_generated_hdr"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "export_includes": `["."]`,
- "local_includes": `["."]`,
- "hdrs": `[":export_generated_hdr"]`,
- "srcs": `[
- "cpp_src.cpp",
- ":generated_hdr",
- ]`,
- "srcs_as": `[
- "as_src.S",
- ":generated_hdr",
- ]`,
- "srcs_c": `[
- "c_src.c",
- ":generated_hdr",
- ]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticGeneratedHeadersMultipleExports(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Blueprint: soongCcLibraryStaticPreamble + `
-genrule {
- name: "generated_hdr",
- cmd: "nothing to see here",
- export_include_dirs: ["foo", "bar"],
- bazel_module: { bp2build_available: false },
-}
-
-genrule {
- name: "export_generated_hdr",
- cmd: "nothing to see here",
- export_include_dirs: ["a", "b"],
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "foo_static",
- generated_headers: ["generated_hdr", "export_generated_hdr"],
- export_generated_headers: ["export_generated_hdr"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "deps": `[":export_generated_hdr__header_library"]`,
- "implementation_deps": `[":generated_hdr__header_library"]`,
- }),
- },
- })
-}
-
-// generated_headers has "variant_prepend" tag. In bp2build output,
-// variant info(select) should go before general info.
-func TestCcLibraryStaticArchSrcsExcludeSrcsGeneratedFiles(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static arch srcs/exclude_srcs with generated files",
- Filesystem: map[string]string{
- "common.cpp": "",
- "for-x86.cpp": "",
- "not-for-x86.cpp": "",
- "not-for-everything.cpp": "",
- "dep/Android.bp": simpleModuleDoNotConvertBp2build("genrule", "generated_src_other_pkg") +
- simpleModuleDoNotConvertBp2build("genrule", "generated_hdr_other_pkg") +
- simpleModuleDoNotConvertBp2build("genrule", "generated_src_other_pkg_x86") +
- simpleModuleDoNotConvertBp2build("genrule", "generated_hdr_other_pkg_x86") +
- simpleModuleDoNotConvertBp2build("genrule", "generated_hdr_other_pkg_android"),
- },
- Blueprint: soongCcLibraryStaticPreamble +
- simpleModuleDoNotConvertBp2build("genrule", "generated_src") +
- simpleModuleDoNotConvertBp2build("genrule", "generated_src_not_x86") +
- simpleModuleDoNotConvertBp2build("genrule", "generated_src_android") +
- simpleModuleDoNotConvertBp2build("genrule", "generated_hdr") + `
-cc_library_static {
- name: "foo_static",
- srcs: ["common.cpp", "not-for-*.cpp"],
- exclude_srcs: ["not-for-everything.cpp"],
- generated_sources: ["generated_src", "generated_src_other_pkg", "generated_src_not_x86"],
- generated_headers: ["generated_hdr", "generated_hdr_other_pkg"],
- export_generated_headers: ["generated_hdr_other_pkg"],
- arch: {
- x86: {
- srcs: ["for-x86.cpp"],
- exclude_srcs: ["not-for-x86.cpp"],
- generated_headers: ["generated_hdr_other_pkg_x86"],
- exclude_generated_sources: ["generated_src_not_x86"],
- export_generated_headers: ["generated_hdr_other_pkg_x86"],
- },
- },
- target: {
- android: {
- generated_sources: ["generated_src_android"],
- generated_headers: ["generated_hdr_other_pkg_android"],
- export_generated_headers: ["generated_hdr_other_pkg_android"],
- },
- },
-
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "srcs": `[
- "common.cpp",
- ":generated_src",
- "//dep:generated_src_other_pkg",
- ":generated_hdr",
- ] + select({
- "//build/bazel/platforms/arch:x86": ["for-x86.cpp"],
- "//conditions:default": [
- "not-for-x86.cpp",
- ":generated_src_not_x86",
- ],
- }) + select({
- "//build/bazel/platforms/os:android": [":generated_src_android"],
- "//conditions:default": [],
- })`,
- "hdrs": `select({
- "//build/bazel/platforms/os:android": ["//dep:generated_hdr_other_pkg_android"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/arch:x86": ["//dep:generated_hdr_other_pkg_x86"],
- "//conditions:default": [],
- }) + ["//dep:generated_hdr_other_pkg"]`,
- "local_includes": `["."]`,
- "export_absolute_includes": `["dep"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticGetTargetProperties(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
-
- Description: "cc_library_static complex GetTargetProperties",
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- target: {
- android: {
- srcs: ["android_src.c"],
- },
- android_arm: {
- srcs: ["android_arm_src.c"],
- },
- android_arm64: {
- srcs: ["android_arm64_src.c"],
- },
- android_x86: {
- srcs: ["android_x86_src.c"],
- },
- android_x86_64: {
- srcs: ["android_x86_64_src.c"],
- },
- linux_bionic_arm64: {
- srcs: ["linux_bionic_arm64_src.c"],
- },
- linux_bionic_x86_64: {
- srcs: ["linux_bionic_x86_64_src.c"],
- },
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "srcs_c": `select({
- "//build/bazel/platforms/os:android": ["android_src.c"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/platforms/os_arch:android_arm": ["android_arm_src.c"],
- "//build/bazel/platforms/os_arch:android_arm64": ["android_arm64_src.c"],
- "//build/bazel/platforms/os_arch:android_x86": ["android_x86_src.c"],
- "//build/bazel/platforms/os_arch:android_x86_64": ["android_x86_64_src.c"],
- "//build/bazel/platforms/os_arch:linux_bionic_arm64": ["linux_bionic_arm64_src.c"],
- "//build/bazel/platforms/os_arch:linux_bionic_x86_64": ["linux_bionic_x86_64_src.c"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticProductVariableSelects(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static product variable selects",
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- srcs: ["common.c"],
- product_variables: {
- malloc_not_svelte: {
- cflags: ["-Wmalloc_not_svelte"],
- },
- malloc_zero_contents: {
- cflags: ["-Wmalloc_zero_contents"],
- },
- binder32bit: {
- cflags: ["-Wbinder32bit"],
- },
- },
- include_build_directory: false,
-} `,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "copts": `select({
- "//build/bazel/product_config/config_settings:binder32bit": ["-Wbinder32bit"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/product_config/config_settings:malloc_not_svelte": ["-Wmalloc_not_svelte"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/product_config/config_settings:malloc_zero_contents": ["-Wmalloc_zero_contents"],
- "//conditions:default": [],
- })`,
- "srcs_c": `["common.c"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticProductVariableArchSpecificSelects(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static arch-specific product variable selects",
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- srcs: ["common.c"],
- product_variables: {
- malloc_not_svelte: {
- cflags: ["-Wmalloc_not_svelte"],
- },
- },
- arch: {
- arm64: {
- product_variables: {
- malloc_not_svelte: {
- cflags: ["-Warm64_malloc_not_svelte"],
- },
- },
- },
- },
- multilib: {
- lib32: {
- product_variables: {
- malloc_not_svelte: {
- cflags: ["-Wlib32_malloc_not_svelte"],
- },
- },
- },
- },
- target: {
- android: {
- product_variables: {
- malloc_not_svelte: {
- cflags: ["-Wandroid_malloc_not_svelte"],
- },
- },
- }
- },
- include_build_directory: false,
-} `,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "copts": `select({
- "//build/bazel/product_config/config_settings:malloc_not_svelte": ["-Wmalloc_not_svelte"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/product_config/config_settings:malloc_not_svelte-android": ["-Wandroid_malloc_not_svelte"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/product_config/config_settings:malloc_not_svelte-arm": ["-Wlib32_malloc_not_svelte"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/product_config/config_settings:malloc_not_svelte-arm64": ["-Warm64_malloc_not_svelte"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/product_config/config_settings:malloc_not_svelte-x86": ["-Wlib32_malloc_not_svelte"],
- "//conditions:default": [],
- })`,
- "srcs_c": `["common.c"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticProductVariableStringReplacement(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static product variable string replacement",
- Filesystem: map[string]string{},
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "foo_static",
- srcs: ["common.S"],
- product_variables: {
- platform_sdk_version: {
- asflags: ["-DPLATFORM_SDK_VERSION=%d"],
- },
- },
- include_build_directory: false,
-} `,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo_static", AttrNameToString{
- "asflags": `select({
- "//build/bazel/product_config/config_settings:platform_sdk_version": ["-DPLATFORM_SDK_VERSION=$(Platform_sdk_version)"],
- "//conditions:default": [],
- })`,
- "srcs_as": `["common.S"]`,
- }),
- },
- })
-}
-
-func TestStaticLibrary_SystemSharedLibsRootEmpty(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static system_shared_lib empty root",
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library_static {
- name: "root_empty",
- system_shared_libs: [],
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "root_empty", AttrNameToString{
- "system_dynamic_deps": `[]`,
- }),
- },
- })
-}
-
-func TestStaticLibrary_SystemSharedLibsStaticEmpty(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static system_shared_lib empty static default",
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_defaults {
- name: "static_empty_defaults",
- static: {
- system_shared_libs: [],
- },
- include_build_directory: false,
-}
-cc_library_static {
- name: "static_empty",
- defaults: ["static_empty_defaults"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "static_empty", AttrNameToString{
- "system_dynamic_deps": `[]`,
- }),
- },
- })
-}
-
-func TestStaticLibrary_SystemSharedLibsBionicEmpty(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static system_shared_lib empty for bionic variant",
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library {
- name: "libc_musl",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "target_bionic_empty",
- target: {
- bionic: {
- system_shared_libs: [],
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "target_bionic_empty", AttrNameToString{
- "system_dynamic_deps": `select({
- "//build/bazel/platforms/os:linux_musl": [":libc_musl"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestStaticLibrary_SystemSharedLibsLinuxBionicEmpty(t *testing.T) {
- // Note that this behavior is technically incorrect (it's a simplification).
- // The correct behavior would be if bp2build wrote `system_dynamic_deps = []`
- // only for linux_bionic, but `android` had `["libc", "libdl", "libm"].
- // b/195791252 tracks the fix.
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static system_shared_lib empty for linux_bionic variant",
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library {
- name: "libc_musl",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "target_linux_bionic_empty",
- target: {
- linux_bionic: {
- system_shared_libs: [],
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "target_linux_bionic_empty", AttrNameToString{
- "system_dynamic_deps": `select({
- "//build/bazel/platforms/os:linux_musl": [":libc_musl"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestStaticLibrary_SystemSharedLibsMuslEmpty(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static system_shared_lib empty for musl variant",
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library {
- name: "libc_musl",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "target_musl_empty",
- target: {
- musl: {
- system_shared_libs: [],
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "target_musl_empty", AttrNameToString{
- "system_dynamic_deps": `[]`,
- }),
- },
- })
-}
-
-func TestStaticLibrary_SystemSharedLibsLinuxMuslEmpty(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static system_shared_lib empty for linux_musl variant",
- Blueprint: soongCcLibraryStaticPreamble + `
-cc_library {
- name: "libc_musl",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "target_linux_musl_empty",
- target: {
- linux_musl: {
- system_shared_libs: [],
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "target_linux_musl_empty", AttrNameToString{
- "system_dynamic_deps": `[]`,
- }),
- },
- })
-}
-
-func TestStaticLibrary_SystemSharedLibsBionic(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static system_shared_libs set for bionic variant",
- Blueprint: soongCcLibraryStaticPreamble +
- simpleModuleDoNotConvertBp2build("cc_library", "libc") + `
-cc_library {
- name: "libc_musl",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "target_bionic",
- target: {
- bionic: {
- system_shared_libs: ["libc"],
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "target_bionic", AttrNameToString{
- "system_dynamic_deps": `select({
- "//build/bazel/platforms/os:android": [":libc"],
- "//build/bazel/platforms/os:linux_bionic": [":libc"],
- "//build/bazel/platforms/os:linux_musl": [":libc_musl"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestStaticLibrary_SystemSharedLibsLinuxRootAndLinuxBionic(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static system_shared_libs set for root and linux_bionic variant",
- Blueprint: soongCcLibraryStaticPreamble +
- simpleModuleDoNotConvertBp2build("cc_library", "libc") +
- simpleModuleDoNotConvertBp2build("cc_library", "libm") + `
-cc_library {
- name: "libc_musl",
- bazel_module: { bp2build_available: false },
-}
-
-cc_library_static {
- name: "target_linux_bionic",
- system_shared_libs: ["libc"],
- target: {
- linux_bionic: {
- system_shared_libs: ["libm"],
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "target_linux_bionic", AttrNameToString{
- "system_dynamic_deps": `[":libc"] + select({
- "//build/bazel/platforms/os:linux_bionic": [":libm"],
- "//build/bazel/platforms/os:linux_musl": [":libc_musl"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibrarystatic_SystemSharedLibUsedAsDep(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static system_shared_lib empty for linux_bionic variant",
- Blueprint: soongCcLibraryStaticPreamble +
- simpleModuleDoNotConvertBp2build("cc_library", "libc") + `
-
-cc_library {
- name: "libm",
- stubs: {
- symbol_file: "libm.map.txt",
- versions: ["current"],
- },
- bazel_module: { bp2build_available: false },
- apex_available: ["com.android.runtime"],
-}
-
-cc_library_static {
- name: "used_in_bionic_oses",
- target: {
- android: {
- shared_libs: ["libc"],
- },
- linux_bionic: {
- shared_libs: ["libc"],
- },
- },
- include_build_directory: false,
- apex_available: ["foo"],
-}
-
-cc_library_static {
- name: "all",
- shared_libs: ["libc"],
- include_build_directory: false,
- apex_available: ["foo"],
-}
-
-cc_library_static {
- name: "keep_for_empty_system_shared_libs",
- shared_libs: ["libc"],
- system_shared_libs: [],
- include_build_directory: false,
- apex_available: ["foo"],
-}
-
-cc_library_static {
- name: "used_with_stubs",
- shared_libs: ["libm"],
- include_build_directory: false,
- apex_available: ["foo"],
-}
-
-cc_library_static {
- name: "keep_with_stubs",
- shared_libs: ["libm"],
- system_shared_libs: [],
- include_build_directory: false,
- apex_available: ["foo"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "all", AttrNameToString{
- "tags": `["apex_available=foo"]`,
- }),
- MakeBazelTarget("cc_library_static", "keep_for_empty_system_shared_libs", AttrNameToString{
- "implementation_dynamic_deps": `[":libc"]`,
- "system_dynamic_deps": `[]`,
- "tags": `["apex_available=foo"]`,
- }),
- MakeBazelTarget("cc_library_static", "keep_with_stubs", AttrNameToString{
- "implementation_dynamic_deps": `select({
- "//build/bazel/rules/apex:foo": ["@api_surfaces//module-libapi/current:libm"],
- "//build/bazel/rules/apex:system": ["@api_surfaces//module-libapi/current:libm"],
- "//conditions:default": [":libm"],
- })`,
- "system_dynamic_deps": `[]`,
- "tags": `["apex_available=foo"]`,
- }),
- MakeBazelTarget("cc_library_static", "used_in_bionic_oses", AttrNameToString{
- "tags": `["apex_available=foo"]`,
- }),
- MakeBazelTarget("cc_library_static", "used_with_stubs", AttrNameToString{
- "tags": `["apex_available=foo"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticProto(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Blueprint: soongCcProtoPreamble + `cc_library_static {
- name: "foo",
- srcs: ["foo.proto"],
- proto: {
- export_proto_headers: true,
- },
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["foo.proto"]`,
- }), MakeBazelTarget("cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{
- "deps": `[":foo_proto"]`,
- }), MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "deps": `[":libprotobuf-cpp-lite"]`,
- "whole_archive_deps": `[":foo_cc_proto_lite"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticUseVersionLib(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Filesystem: map[string]string{
- soongCcVersionLibBpPath: soongCcVersionLibBp,
- },
- Blueprint: soongCcProtoPreamble + `cc_library_static {
- name: "foo",
- use_version_lib: true,
- static_libs: ["libbuildversion"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticUseVersionLibHasDep(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Filesystem: map[string]string{
- soongCcVersionLibBpPath: soongCcVersionLibBp,
- },
- Blueprint: soongCcProtoPreamble + `cc_library_static {
- name: "foo",
- use_version_lib: true,
- whole_static_libs: ["libbuildversion"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticStdInFlags(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Blueprint: soongCcProtoPreamble + `cc_library_static {
- name: "foo",
- cflags: ["-std=candcpp"],
- conlyflags: ["-std=conly"],
- cppflags: ["-std=cpp"],
- include_build_directory: false,
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "conlyflags": `["-std=conly"]`,
- "cppflags": `["-std=cpp"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticStl(t *testing.T) {
- testCases := []struct {
- desc string
- prop string
- attr AttrNameToString
- }{
- {
- desc: "c++_shared deduped to libc++",
- prop: `stl: "c++_shared",`,
- attr: AttrNameToString{
- "stl": `"libc++"`,
- },
- },
- {
- desc: "libc++ to libc++",
- prop: `stl: "libc++",`,
- attr: AttrNameToString{
- "stl": `"libc++"`,
- },
- },
- {
- desc: "c++_static to libc++_static",
- prop: `stl: "c++_static",`,
- attr: AttrNameToString{
- "stl": `"libc++_static"`,
- },
- },
- {
- desc: "libc++_static to libc++_static",
- prop: `stl: "libc++_static",`,
- attr: AttrNameToString{
- "stl": `"libc++_static"`,
- },
- },
- {
- desc: "system to system",
- prop: `stl: "system",`,
- attr: AttrNameToString{
- "stl": `"system"`,
- },
- },
- {
- desc: "none to none",
- prop: `stl: "none",`,
- attr: AttrNameToString{
- "stl": `"none"`,
- },
- },
- {
- desc: "empty to empty",
- attr: AttrNameToString{},
- },
- }
- for _, tc := range testCases {
- t.Run(tc.desc, func(*testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Blueprint: fmt.Sprintf(`cc_library_static {
- name: "foo",
- include_build_directory: false,
- %s
-}`, tc.prop),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", tc.attr),
- },
- })
- })
- }
-}
-
-func TestCCLibraryStaticRuntimeDeps(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Blueprint: `cc_library_shared {
- name: "bar",
-}
-
-cc_library_static {
- name: "foo",
- runtime_libs: ["foo"],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_shared", "bar", AttrNameToString{
- "local_includes": `["."]`,
- }),
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "runtime_deps": `[":foo"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticWithSyspropSrcs(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static with sysprop sources",
- Blueprint: `
-cc_library_static {
- name: "foo",
- srcs: [
- "bar.sysprop",
- "baz.sysprop",
- "blah.cpp",
- ],
- min_sdk_version: "5",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("sysprop_library", "foo_sysprop_library", AttrNameToString{
- "srcs": `[
- "bar.sysprop",
- "baz.sysprop",
- ]`,
- }),
- MakeBazelTarget("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
- "dep": `":foo_sysprop_library"`,
- "min_sdk_version": `"5"`,
- }),
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "srcs": `["blah.cpp"]`,
- "local_includes": `["."]`,
- "min_sdk_version": `"5"`,
- "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticWithSyspropSrcsSomeConfigs(t *testing.T) {
- runCcLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static with sysprop sources in some configs but not others",
- Blueprint: `
-cc_library_static {
- name: "foo",
- srcs: [
- "blah.cpp",
- ],
- target: {
- android: {
- srcs: ["bar.sysprop"],
- },
- },
- min_sdk_version: "5",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("sysprop_library", "foo_sysprop_library", AttrNameToString{
- "srcs": `select({
- "//build/bazel/platforms/os:android": ["bar.sysprop"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{
- "dep": `":foo_sysprop_library"`,
- "min_sdk_version": `"5"`,
- }),
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "srcs": `["blah.cpp"]`,
- "local_includes": `["."]`,
- "min_sdk_version": `"5"`,
- "whole_archive_deps": `select({
- "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticWithIntegerOverflowProperty(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static has correct features when integer_overflow property is provided",
- Blueprint: `
-cc_library_static {
- name: "foo",
- sanitize: {
- integer_overflow: true,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "features": `["ubsan_integer_overflow"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticWithMiscUndefinedProperty(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static has correct features when misc_undefined property is provided",
- Blueprint: `
-cc_library_static {
- name: "foo",
- sanitize: {
- misc_undefined: ["undefined", "nullability"],
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "features": `[
- "ubsan_undefined",
- "ubsan_nullability",
- ]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticWithUBSanPropertiesArchSpecific(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static has correct feature select when UBSan props are specified in arch specific blocks",
- Blueprint: `
-cc_library_static {
- name: "foo",
- sanitize: {
- misc_undefined: ["undefined", "nullability"],
- },
- target: {
- android: {
- sanitize: {
- misc_undefined: ["alignment"],
- },
- },
- linux_glibc: {
- sanitize: {
- integer_overflow: true,
- },
- },
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "features": `[
- "ubsan_undefined",
- "ubsan_nullability",
- ] + select({
- "//build/bazel/platforms/os:android": ["ubsan_alignment"],
- "//build/bazel/platforms/os:linux_glibc": ["ubsan_integer_overflow"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticWithSanitizerBlocklist(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static has correct features when sanitize.blocklist is provided",
- Blueprint: `
-cc_library_static {
- name: "foo",
- sanitize: {
- blocklist: "foo_blocklist.txt",
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "copts": `select({
- "//build/bazel/rules/cc:sanitizers_enabled": ["-fsanitize-ignorelist=$(location foo_blocklist.txt)"],
- "//conditions:default": [],
- })`,
- "additional_compiler_inputs": `select({
- "//build/bazel/rules/cc:sanitizers_enabled": [":foo_blocklist.txt"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticWithThinLto(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static has correct features when thin lto is enabled",
- Blueprint: `
-cc_library_static {
- name: "foo",
- lto: {
- thin: true,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "features": `["android_thin_lto"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticWithLtoNever(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static has correct features when thin lto is enabled",
- Blueprint: `
-cc_library_static {
- name: "foo",
- lto: {
- never: true,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "features": `["-android_thin_lto"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticWithThinLtoArchSpecific(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static has correct features when LTO differs across arch and os variants",
- Blueprint: `
-cc_library_static {
- name: "foo",
- target: {
- android: {
- lto: {
- thin: true,
- },
- },
- },
- arch: {
- riscv64: {
- lto: {
- thin: false,
- },
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm": ["android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_arm64": ["android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_riscv64": ["-android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_x86": ["android_thin_lto"],
- "//build/bazel/platforms/os_arch:android_x86_64": ["android_thin_lto"],
- "//conditions:default": [],
- })`}),
- },
- })
-}
-
-func TestCcLibraryStaticWithThinLtoDisabledDefaultEnabledVariant(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static has correct features when LTO disabled by default but enabled on a particular variant",
- Blueprint: `
-cc_library_static {
- name: "foo",
- lto: {
- never: true,
- },
- target: {
- android: {
- lto: {
- thin: true,
- never: false,
- },
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "local_includes": `["."]`,
- "features": `select({
- "//build/bazel/platforms/os:android": ["android_thin_lto"],
- "//conditions:default": ["-android_thin_lto"],
- })`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticWithThinLtoAndWholeProgramVtables(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static has correct features when thin lto is enabled with whole_program_vtables",
- Blueprint: `
-cc_library_static {
- name: "foo",
- lto: {
- thin: true,
- },
- whole_program_vtables: true,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "features": `[
- "android_thin_lto",
- "android_thin_lto_whole_program_vtables",
- ]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticHiddenVisibilityConvertedToFeature(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static changes hidden visibility flag to feature",
- Blueprint: `
-cc_library_static {
- name: "foo",
- cflags: ["-fvisibility=hidden"],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "features": `["visibility_hidden"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticHiddenVisibilityConvertedToFeatureOsSpecific(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static changes hidden visibility flag to feature for specific os",
- Blueprint: `
-cc_library_static {
- name: "foo",
- target: {
- android: {
- cflags: ["-fvisibility=hidden"],
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/os:android": ["visibility_hidden"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticWithCfi(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static has correct features when cfi is enabled",
- Blueprint: `
-cc_library_static {
- name: "foo",
- sanitize: {
- cfi: true,
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "features": `["android_cfi"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticWithCfiOsSpecific(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static has correct features when cfi is enabled for specific variants",
- Blueprint: `
-cc_library_static {
- name: "foo",
- target: {
- android: {
- sanitize: {
- cfi: true,
- },
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "features": `select({
- "//build/bazel/platforms/os:android": ["android_cfi"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticWithCfiAndCfiAssemblySupport(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static has correct features when cfi is enabled with cfi_assembly_support",
- Blueprint: `
-cc_library_static {
- name: "foo",
- sanitize: {
- cfi: true,
- config: {
- cfi_assembly_support: true,
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "features": `[
- "android_cfi",
- "android_cfi_assembly_support",
- ]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCcLibraryStaticExplicitlyDisablesCfiWhenFalse(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static disables cfi when explciitly set to false in the bp",
- Blueprint: `
-cc_library_static {
- name: "foo",
- sanitize: {
- cfi: false,
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "features": `["-android_cfi"]`,
- "local_includes": `["."]`,
- }),
- },
- })
-}
-
-func TestCCLibraryStaticRscriptSrc(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: `cc_library_static with rscript files in sources`,
- Blueprint: `
-cc_library_static{
- name : "foo",
- srcs : [
- "ccSrc.cc",
- "rsSrc.rscript",
- ],
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("rscript_to_cpp", "foo_renderscript", AttrNameToString{
- "srcs": `["rsSrc.rscript"]`,
- }),
- MakeBazelTarget("cc_library_static", "foo", AttrNameToString{
- "absolute_includes": `[
- "frameworks/rs",
- "frameworks/rs/cpp",
- ]`,
- "local_includes": `["."]`,
- "srcs": `[
- "ccSrc.cc",
- "foo_renderscript",
- ]`,
- })}})
-}
-
-func TestCcLibraryWithProtoInGeneratedSrcs(t *testing.T) {
- runCcLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_library with a .proto file generated from a genrule",
- ModuleTypeUnderTest: "cc_library_static",
- ModuleTypeUnderTestFactory: cc.LibraryStaticFactory,
- Blueprint: soongCcLibraryPreamble + `
-cc_library_static {
- name: "mylib",
- generated_sources: ["myprotogen"],
-}
-genrule {
- name: "myprotogen",
- out: ["myproto.proto"],
-}
-` + simpleModuleDoNotConvertBp2build("cc_library", "libprotobuf-cpp-lite"),
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_library_static", "mylib", AttrNameToString{
- "local_includes": `["."]`,
- "deps": `[":libprotobuf-cpp-lite"]`,
- "implementation_whole_archive_deps": `[":mylib_cc_proto_lite"]`,
- }),
- MakeBazelTarget("cc_lite_proto_library", "mylib_cc_proto_lite", AttrNameToString{
- "deps": `[":mylib_proto"]`,
- }),
- MakeBazelTarget("proto_library", "mylib_proto", AttrNameToString{
- "srcs": `[":myprotogen"]`,
- }),
- MakeBazelTargetNoRestrictions("genrule", "myprotogen", AttrNameToString{
- "cmd": `""`,
- "outs": `["myproto.proto"]`,
- }),
- },
- })
-}
diff --git a/bp2build/cc_object_conversion_test.go b/bp2build/cc_object_conversion_test.go
deleted file mode 100644
index ecfcb5a..0000000
--- a/bp2build/cc_object_conversion_test.go
+++ /dev/null
@@ -1,480 +0,0 @@
-// 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
-
-import (
- "testing"
-
- "android/soong/android"
- "android/soong/cc"
-)
-
-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) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "cc_object"
- (&tc).ModuleTypeUnderTestFactory = cc.ObjectFactory
- RunBp2BuildTestCase(t, registerCcObjectModuleTypes, tc)
-}
-
-func TestCcObjectSimple(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",
- local_include_dirs: ["include"],
- 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",
- crt: true,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_object", "foo", AttrNameToString{
- "copts": `[
- "-fno-addrsig",
- "-Wno-gcc-compat",
- "-Wall",
- "-Werror",
- ]`,
- "local_includes": `[
- "include",
- ".",
- ]`,
- "srcs": `["a/b/c.c"]`,
- "system_dynamic_deps": `[]`,
- "sdk_version": `"current"`,
- "min_sdk_version": `"29"`,
- "crt": "True",
- }),
- },
- })
-}
-
-func TestCcObjectDefaults(t *testing.T) {
- runCcObjectTestCase(t, Bp2buildTestCase{
- Blueprint: `cc_object {
- name: "foo",
- system_shared_libs: [],
- srcs: [
- "a/b/*.h",
- "a/b/c.c"
- ],
-
- defaults: ["foo_defaults"],
-}
-
-cc_defaults {
- name: "foo_defaults",
- defaults: ["foo_bar_defaults"],
-}
-
-cc_defaults {
- name: "foo_bar_defaults",
- cflags: [
- "-Werror",
- ],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_object", "foo", AttrNameToString{
- "copts": `[
- "-Werror",
- "-fno-addrsig",
- ]`,
- "local_includes": `["."]`,
- "srcs": `["a/b/c.c"]`,
- "system_dynamic_deps": `[]`,
- }),
- }})
-}
-
-func TestCcObjectCcObjetDepsInObjs(t *testing.T) {
- runCcObjectTestCase(t, Bp2buildTestCase{
- Description: "cc_object with cc_object deps in objs props",
- Filesystem: map[string]string{
- "a/b/c.c": "",
- "x/y/z.c": "",
- },
- Blueprint: `cc_object {
- name: "foo",
- system_shared_libs: [],
- srcs: ["a/b/c.c"],
- objs: ["bar"],
- include_build_directory: false,
-}
-
-cc_object {
- name: "bar",
- system_shared_libs: [],
- srcs: ["x/y/z.c"],
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_object", "bar", AttrNameToString{
- "copts": `["-fno-addrsig"]`,
- "srcs": `["x/y/z.c"]`,
- "system_dynamic_deps": `[]`,
- }), MakeBazelTarget("cc_object", "foo", AttrNameToString{
- "copts": `["-fno-addrsig"]`,
- "objs": `[":bar"]`,
- "srcs": `["a/b/c.c"]`,
- "system_dynamic_deps": `[]`,
- }),
- },
- })
-}
-
-func TestCcObjectIncludeBuildDirFalse(t *testing.T) {
- runCcObjectTestCase(t, Bp2buildTestCase{
- Description: "cc_object with include_build_dir: false",
- Filesystem: map[string]string{
- "a/b/c.c": "",
- "x/y/z.c": "",
- },
- Blueprint: `cc_object {
- name: "foo",
- system_shared_libs: [],
- srcs: ["a/b/c.c"],
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_object", "foo", AttrNameToString{
- "copts": `["-fno-addrsig"]`,
- "srcs": `["a/b/c.c"]`,
- "system_dynamic_deps": `[]`,
- }),
- },
- })
-}
-
-func TestCcObjectProductVariable(t *testing.T) {
- runCcObjectTestCase(t, Bp2buildTestCase{
- Description: "cc_object with product variable",
- Blueprint: `cc_object {
- name: "foo",
- system_shared_libs: [],
- include_build_directory: false,
- product_variables: {
- platform_sdk_version: {
- asflags: ["-DPLATFORM_SDK_VERSION=%d"],
- },
- },
- srcs: ["src.S"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_object", "foo", AttrNameToString{
- "asflags": `select({
- "//build/bazel/product_config/config_settings:platform_sdk_version": ["-DPLATFORM_SDK_VERSION=$(Platform_sdk_version)"],
- "//conditions:default": [],
- })`,
- "copts": `["-fno-addrsig"]`,
- "srcs_as": `["src.S"]`,
- "system_dynamic_deps": `[]`,
- }),
- },
- })
-}
-
-func TestCcObjectCflagsOneArch(t *testing.T) {
- runCcObjectTestCase(t, Bp2buildTestCase{
- Description: "cc_object setting cflags for one arch",
- Blueprint: `cc_object {
- name: "foo",
- system_shared_libs: [],
- srcs: ["a.cpp"],
- arch: {
- x86: {
- cflags: ["-fPIC"], // string list
- },
- arm: {
- srcs: ["arch/arm/file.cpp"], // label list
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_object", "foo", AttrNameToString{
- "copts": `["-fno-addrsig"] + select({
- "//build/bazel/platforms/arch:x86": ["-fPIC"],
- "//conditions:default": [],
- })`,
- "srcs": `["a.cpp"] + select({
- "//build/bazel/platforms/arch:arm": ["arch/arm/file.cpp"],
- "//conditions:default": [],
- })`,
- "system_dynamic_deps": `[]`,
- }),
- },
- })
-}
-
-func TestCcObjectCflagsFourArch(t *testing.T) {
- runCcObjectTestCase(t, Bp2buildTestCase{
- Description: "cc_object setting cflags for 4 architectures",
- Blueprint: `cc_object {
- name: "foo",
- system_shared_libs: [],
- srcs: ["base.cpp"],
- arch: {
- x86: {
- srcs: ["x86.cpp"],
- cflags: ["-fPIC"],
- },
- x86_64: {
- srcs: ["x86_64.cpp"],
- cflags: ["-fPIC"],
- },
- arm: {
- srcs: ["arm.cpp"],
- cflags: ["-Wall"],
- },
- arm64: {
- srcs: ["arm64.cpp"],
- cflags: ["-Wall"],
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_object", "foo", AttrNameToString{
- "copts": `["-fno-addrsig"] + select({
- "//build/bazel/platforms/arch:arm": ["-Wall"],
- "//build/bazel/platforms/arch:arm64": ["-Wall"],
- "//build/bazel/platforms/arch:x86": ["-fPIC"],
- "//build/bazel/platforms/arch:x86_64": ["-fPIC"],
- "//conditions:default": [],
- })`,
- "srcs": `["base.cpp"] + select({
- "//build/bazel/platforms/arch:arm": ["arm.cpp"],
- "//build/bazel/platforms/arch:arm64": ["arm64.cpp"],
- "//build/bazel/platforms/arch:x86": ["x86.cpp"],
- "//build/bazel/platforms/arch:x86_64": ["x86_64.cpp"],
- "//conditions:default": [],
- })`,
- "system_dynamic_deps": `[]`,
- }),
- },
- })
-}
-
-func TestCcObjectLinkerScript(t *testing.T) {
- runCcObjectTestCase(t, Bp2buildTestCase{
- Description: "cc_object setting linker_script",
- Blueprint: `cc_object {
- name: "foo",
- srcs: ["base.cpp"],
- linker_script: "bunny.lds",
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_object", "foo", AttrNameToString{
- "copts": `["-fno-addrsig"]`,
- "linker_script": `"bunny.lds"`,
- "srcs": `["base.cpp"]`,
- }),
- },
- })
-}
-
-func TestCcObjectDepsAndLinkerScriptSelects(t *testing.T) {
- runCcObjectTestCase(t, Bp2buildTestCase{
- Description: "cc_object setting deps and linker_script across archs",
- Blueprint: `cc_object {
- name: "foo",
- srcs: ["base.cpp"],
- arch: {
- x86: {
- objs: ["x86_obj"],
- linker_script: "x86.lds",
- },
- x86_64: {
- objs: ["x86_64_obj"],
- linker_script: "x86_64.lds",
- },
- arm: {
- objs: ["arm_obj"],
- linker_script: "arm.lds",
- },
- },
- include_build_directory: false,
-}
-
-cc_object {
- name: "x86_obj",
- system_shared_libs: [],
- srcs: ["x86.cpp"],
- include_build_directory: false,
- bazel_module: { bp2build_available: false },
-}
-
-cc_object {
- name: "x86_64_obj",
- system_shared_libs: [],
- srcs: ["x86_64.cpp"],
- include_build_directory: false,
- bazel_module: { bp2build_available: false },
-}
-
-cc_object {
- name: "arm_obj",
- system_shared_libs: [],
- srcs: ["arm.cpp"],
- include_build_directory: false,
- bazel_module: { bp2build_available: false },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_object", "foo", AttrNameToString{
- "copts": `["-fno-addrsig"]`,
- "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"],
- "//conditions:default": [],
- })`,
- "linker_script": `select({
- "//build/bazel/platforms/arch:arm": "arm.lds",
- "//build/bazel/platforms/arch:x86": "x86.lds",
- "//build/bazel/platforms/arch:x86_64": "x86_64.lds",
- "//conditions:default": None,
- })`,
- "srcs": `["base.cpp"]`,
- }),
- },
- })
-}
-
-func TestCcObjectSelectOnLinuxAndBionicArchs(t *testing.T) {
- runCcObjectTestCase(t, Bp2buildTestCase{
- Description: "cc_object setting srcs based on linux and bionic archs",
- Blueprint: `cc_object {
- name: "foo",
- srcs: ["base.cpp"],
- target: {
- linux_arm64: {
- srcs: ["linux_arm64.cpp",]
- },
- linux_x86: {
- srcs: ["linux_x86.cpp",]
- },
- bionic_arm64: {
- srcs: ["bionic_arm64.cpp",]
- },
- },
- include_build_directory: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_object", "foo", AttrNameToString{
- "copts": `["-fno-addrsig"]`,
- "srcs": `["base.cpp"] + select({
- "//build/bazel/platforms/os_arch:android_arm64": [
- "linux_arm64.cpp",
- "bionic_arm64.cpp",
- ],
- "//build/bazel/platforms/os_arch:android_x86": ["linux_x86.cpp"],
- "//build/bazel/platforms/os_arch:linux_bionic_arm64": [
- "linux_arm64.cpp",
- "bionic_arm64.cpp",
- ],
- "//build/bazel/platforms/os_arch:linux_glibc_x86": ["linux_x86.cpp"],
- "//build/bazel/platforms/os_arch:linux_musl_arm64": ["linux_arm64.cpp"],
- "//build/bazel/platforms/os_arch:linux_musl_x86": ["linux_x86.cpp"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-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_binary_conversion_test.go b/bp2build/cc_prebuilt_binary_conversion_test.go
deleted file mode 100644
index 0e8048c..0000000
--- a/bp2build/cc_prebuilt_binary_conversion_test.go
+++ /dev/null
@@ -1,125 +0,0 @@
-// 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 runCcPrebuiltBinaryTestCase(t *testing.T, testCase Bp2buildTestCase) {
- t.Helper()
- description := fmt.Sprintf("cc_prebuilt_binary: %s", testCase.Description)
- testCase.ModuleTypeUnderTest = "cc_prebuilt_binary"
- testCase.ModuleTypeUnderTestFactory = cc.PrebuiltBinaryFactory
- testCase.Description = description
- t.Run(description, func(t *testing.T) {
- t.Helper()
- RunBp2BuildTestCaseSimple(t, testCase)
- })
-}
-
-func TestPrebuiltBinary(t *testing.T) {
- runCcPrebuiltBinaryTestCase(t,
- Bp2buildTestCase{
- Description: "simple",
- Filesystem: map[string]string{
- "bin": "",
- },
- Blueprint: `
-cc_prebuilt_binary {
- name: "bintest",
- srcs: ["bin"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_binary", "bintest", AttrNameToString{
- "src": `"bin"`,
- })},
- })
-}
-
-func TestPrebuiltBinaryWithStrip(t *testing.T) {
- runCcPrebuiltBinaryTestCase(t,
- Bp2buildTestCase{
- Description: "with strip",
- Filesystem: map[string]string{
- "bin": "",
- },
- Blueprint: `
-cc_prebuilt_binary {
- name: "bintest",
- srcs: ["bin"],
- strip: { all: true },
- bazel_module: { bp2build_available: true },
-}`, ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_binary", "bintest", AttrNameToString{
- "src": `"bin"`,
- "strip": `{
- "all": True,
- }`,
- }),
- },
- })
-}
-
-func TestPrebuiltBinaryWithArchVariance(t *testing.T) {
- runCcPrebuiltBinaryTestCase(t,
- Bp2buildTestCase{
- Description: "with arch variance",
- Filesystem: map[string]string{
- "bina": "",
- "binb": "",
- },
- Blueprint: `
-cc_prebuilt_binary {
- name: "bintest",
- arch: {
- arm64: { srcs: ["bina"], },
- arm: { srcs: ["binb"], },
- },
- bazel_module: { bp2build_available: true },
-}`, ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_binary", "bintest", AttrNameToString{
- "src": `select({
- "//build/bazel/platforms/arch:arm": "binb",
- "//build/bazel/platforms/arch:arm64": "bina",
- "//conditions:default": None,
- })`,
- }),
- },
- })
-}
-
-func TestPrebuiltBinaryMultipleSrcsFails(t *testing.T) {
- runCcPrebuiltBinaryTestCase(t,
- Bp2buildTestCase{
- Description: "fails because multiple sources",
- Filesystem: map[string]string{
- "bina": "",
- "binb": "",
- },
- Blueprint: `
-cc_prebuilt_binary {
- name: "bintest",
- srcs: ["bina", "binb"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedErr: fmt.Errorf("Expected at most one source file"),
- })
-}
-
-// TODO: nosrcs test
diff --git a/bp2build/cc_prebuilt_library_conversion_test.go b/bp2build/cc_prebuilt_library_conversion_test.go
deleted file mode 100644
index b88960e..0000000
--- a/bp2build/cc_prebuilt_library_conversion_test.go
+++ /dev/null
@@ -1,362 +0,0 @@
-// 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 runCcPrebuiltLibraryTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "cc_prebuilt_library"
- (&tc).ModuleTypeUnderTestFactory = cc.PrebuiltLibraryFactory
- RunBp2BuildTestCaseSimple(t, tc)
-}
-
-func TestPrebuiltLibraryStaticAndSharedSimple(t *testing.T) {
- runCcPrebuiltLibraryTestCase(t,
- Bp2buildTestCase{
- Description: "prebuilt library static and shared simple",
- Filesystem: map[string]string{
- "libf.so": "",
- },
- Blueprint: `
-cc_prebuilt_library {
- name: "libtest",
- srcs: ["libf.so"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
- "static_library": `"libf.so"`,
- }),
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static_alwayslink", AttrNameToString{
- "static_library": `"libf.so"`,
- "alwayslink": "True",
- }),
- MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
- "shared_library": `"libf.so"`,
- }),
- },
- })
-}
-
-func TestPrebuiltLibraryWithArchVariance(t *testing.T) {
- runCcPrebuiltLibraryTestCase(t,
- Bp2buildTestCase{
- Description: "prebuilt library with arch variance",
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library {
- name: "libtest",
- arch: {
- arm64: { srcs: ["libf.so"], },
- arm: { srcs: ["libg.so"], },
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
- "static_library": `select({
- "//build/bazel/platforms/arch:arm": "libg.so",
- "//build/bazel/platforms/arch:arm64": "libf.so",
- "//conditions:default": None,
- })`}),
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static_alwayslink", AttrNameToString{
- "alwayslink": "True",
- "static_library": `select({
- "//build/bazel/platforms/arch:arm": "libg.so",
- "//build/bazel/platforms/arch:arm64": "libf.so",
- "//conditions:default": None,
- })`}),
- MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
- "shared_library": `select({
- "//build/bazel/platforms/arch:arm": "libg.so",
- "//build/bazel/platforms/arch:arm64": "libf.so",
- "//conditions:default": None,
- })`,
- }),
- },
- })
-}
-
-func TestPrebuiltLibraryAdditionalAttrs(t *testing.T) {
- runCcPrebuiltLibraryTestCase(t,
- Bp2buildTestCase{
- Description: "prebuilt library additional attributes",
- Filesystem: map[string]string{
- "libf.so": "",
- "testdir/1/include.h": "",
- "testdir/2/other.h": "",
- },
- Blueprint: `
-cc_prebuilt_library {
- name: "libtest",
- srcs: ["libf.so"],
- export_include_dirs: ["testdir/1/"],
- export_system_include_dirs: ["testdir/2/"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
- "static_library": `"libf.so"`,
- "export_includes": `["testdir/1/"]`,
- "export_system_includes": `["testdir/2/"]`,
- }),
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static_alwayslink", AttrNameToString{
- "static_library": `"libf.so"`,
- "export_includes": `["testdir/1/"]`,
- "export_system_includes": `["testdir/2/"]`,
- "alwayslink": "True",
- }),
- MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
- "shared_library": `"libf.so"`,
- "export_includes": `["testdir/1/"]`,
- "export_system_includes": `["testdir/2/"]`,
- }),
- },
- })
-}
-
-func TestPrebuiltLibrarySharedStanzaFails(t *testing.T) {
- runCcPrebuiltLibraryTestCase(t,
- Bp2buildTestCase{
- Description: "prebuilt library with shared stanza fails because multiple sources",
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library {
- name: "libtest",
- srcs: ["libf.so"],
- shared: {
- srcs: ["libg.so"],
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedErr: fmt.Errorf("Expected at most one source file"),
- })
-}
-
-func TestPrebuiltLibraryStaticStanzaFails(t *testing.T) {
- RunBp2BuildTestCaseSimple(t,
- Bp2buildTestCase{
- Description: "prebuilt library with static stanza fails because multiple sources",
- ModuleTypeUnderTest: "cc_prebuilt_library",
- ModuleTypeUnderTestFactory: cc.PrebuiltLibraryFactory,
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library {
- name: "libtest",
- srcs: ["libf.so"],
- static: {
- srcs: ["libg.so"],
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedErr: fmt.Errorf("Expected at most one source file"),
- })
-}
-
-func TestPrebuiltLibrarySharedAndStaticStanzas(t *testing.T) {
- runCcPrebuiltLibraryTestCase(t,
- Bp2buildTestCase{
- Description: "prebuilt library with both shared and static stanzas",
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library {
- name: "libtest",
- static: {
- srcs: ["libf.so"],
- },
- shared: {
- srcs: ["libg.so"],
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
- "static_library": `"libf.so"`,
- }),
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static_alwayslink", AttrNameToString{
- "static_library": `"libf.so"`,
- "alwayslink": "True",
- }),
- MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
- "shared_library": `"libg.so"`,
- }),
- },
- })
-}
-
-// TODO(b/228623543): When this bug is fixed, enable this test
-//func TestPrebuiltLibraryOnlyShared(t *testing.T) {
-// runCcPrebuiltLibraryTestCase(t,
-// bp2buildTestCase{
-// description: "prebuilt library shared only",
-// filesystem: map[string]string{
-// "libf.so": "",
-// },
-// blueprint: `
-//cc_prebuilt_library {
-// name: "libtest",
-// srcs: ["libf.so"],
-// static: {
-// enabled: false,
-// },
-// bazel_module: { bp2build_available: true },
-//}`,
-// expectedBazelTargets: []string{
-// makeBazelTarget("cc_prebuilt_library_shared", "libtest", attrNameToString{
-// "shared_library": `"libf.so"`,
-// }),
-// },
-// })
-//}
-
-// TODO(b/228623543): When this bug is fixed, enable this test
-//func TestPrebuiltLibraryOnlyStatic(t *testing.T) {
-// runCcPrebuiltLibraryTestCase(t,
-// bp2buildTestCase{
-// description: "prebuilt library static only",
-// filesystem: map[string]string{
-// "libf.so": "",
-// },
-// blueprint: `
-//cc_prebuilt_library {
-// name: "libtest",
-// srcs: ["libf.so"],
-// shared: {
-// enabled: false,
-// },
-// bazel_module: { bp2build_available: true },
-//}`,
-// expectedBazelTargets: []string{
-// makeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", attrNameToString{
-// "static_library": `"libf.so"`,
-// }),
-// makeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static_always", attrNameToString{
-// "static_library": `"libf.so"`,
-// "alwayslink": "True",
-// }),
-// },
-// })
-//}
-
-func TestPrebuiltLibraryWithExportIncludesArchVariant(t *testing.T) {
- runCcPrebuiltLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_prebuilt_library correctly translates export_includes with arch variance",
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library {
- name: "libtest",
- srcs: ["libf.so"],
- arch: {
- arm: { export_include_dirs: ["testdir/1/"], },
- arm64: { export_include_dirs: ["testdir/2/"], },
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
- "shared_library": `"libf.so"`,
- "export_includes": `select({
- "//build/bazel/platforms/arch:arm": ["testdir/1/"],
- "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
- "static_library": `"libf.so"`,
- "export_includes": `select({
- "//build/bazel/platforms/arch:arm": ["testdir/1/"],
- "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static_alwayslink", AttrNameToString{
- "alwayslink": "True",
- "static_library": `"libf.so"`,
- "export_includes": `select({
- "//build/bazel/platforms/arch:arm": ["testdir/1/"],
- "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestPrebuiltLibraryWithExportSystemIncludesArchVariant(t *testing.T) {
- runCcPrebuiltLibraryTestCase(t, Bp2buildTestCase{
- Description: "cc_prebuilt_ibrary correctly translates export_system_includes with arch variance",
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library {
- name: "libtest",
- srcs: ["libf.so"],
- arch: {
- arm: { export_system_include_dirs: ["testdir/1/"], },
- arm64: { export_system_include_dirs: ["testdir/2/"], },
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
- "shared_library": `"libf.so"`,
- "export_system_includes": `select({
- "//build/bazel/platforms/arch:arm": ["testdir/1/"],
- "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static", AttrNameToString{
- "static_library": `"libf.so"`,
- "export_system_includes": `select({
- "//build/bazel/platforms/arch:arm": ["testdir/1/"],
- "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_bp2build_cc_library_static_alwayslink", AttrNameToString{
- "alwayslink": "True",
- "static_library": `"libf.so"`,
- "export_system_includes": `select({
- "//build/bazel/platforms/arch:arm": ["testdir/1/"],
- "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
diff --git a/bp2build/cc_prebuilt_library_shared_conversion_test.go b/bp2build/cc_prebuilt_library_shared_conversion_test.go
deleted file mode 100644
index 9e975ae..0000000
--- a/bp2build/cc_prebuilt_library_shared_conversion_test.go
+++ /dev/null
@@ -1,165 +0,0 @@
-// 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 (
- "testing"
-
- "android/soong/cc"
-)
-
-func runCcPrebuiltLibrarySharedTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Parallel()
- t.Helper()
- (&tc).ModuleTypeUnderTest = "cc_prebuilt_library_shared"
- (&tc).ModuleTypeUnderTestFactory = cc.PrebuiltSharedLibraryFactory
- RunBp2BuildTestCaseSimple(t, tc)
-}
-
-func TestPrebuiltLibrarySharedSimple(t *testing.T) {
- runCcPrebuiltLibrarySharedTestCase(t,
- Bp2buildTestCase{
- Description: "prebuilt library shared simple",
- Filesystem: map[string]string{
- "libf.so": "",
- },
- Blueprint: `
-cc_prebuilt_library_shared {
- name: "libtest",
- srcs: ["libf.so"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
- "shared_library": `"libf.so"`,
- }),
- },
- })
-}
-
-func TestPrebuiltLibrarySharedWithArchVariance(t *testing.T) {
- runCcPrebuiltLibrarySharedTestCase(t,
- Bp2buildTestCase{
- Description: "prebuilt library shared with arch variance",
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library_shared {
- name: "libtest",
- arch: {
- arm64: { srcs: ["libf.so"], },
- arm: { srcs: ["libg.so"], },
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
- "shared_library": `select({
- "//build/bazel/platforms/arch:arm": "libg.so",
- "//build/bazel/platforms/arch:arm64": "libf.so",
- "//conditions:default": None,
- })`,
- }),
- },
- })
-}
-
-func TestPrebuiltLibrarySharedAdditionalAttrs(t *testing.T) {
- runCcPrebuiltLibrarySharedTestCase(t,
- Bp2buildTestCase{
- Description: "prebuilt library shared additional attributes",
- Filesystem: map[string]string{
- "libf.so": "",
- "testdir/1/include.h": "",
- "testdir/2/other.h": "",
- },
- Blueprint: `
-cc_prebuilt_library_shared {
- name: "libtest",
- srcs: ["libf.so"],
- export_include_dirs: ["testdir/1/"],
- export_system_include_dirs: ["testdir/2/"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
- "shared_library": `"libf.so"`,
- "export_includes": `["testdir/1/"]`,
- "export_system_includes": `["testdir/2/"]`,
- }),
- },
- })
-}
-
-func TestPrebuiltLibrarySharedWithExportIncludesArchVariant(t *testing.T) {
- runCcPrebuiltLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_prebuilt_library_shared correctly translates export_includes with arch variance",
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library_shared {
- name: "libtest",
- srcs: ["libf.so"],
- arch: {
- arm: { export_include_dirs: ["testdir/1/"], },
- arm64: { export_include_dirs: ["testdir/2/"], },
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
- "shared_library": `"libf.so"`,
- "export_includes": `select({
- "//build/bazel/platforms/arch:arm": ["testdir/1/"],
- "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestPrebuiltLibrarySharedWithExportSystemIncludesArchVariant(t *testing.T) {
- runCcPrebuiltLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_prebuilt_library_shared correctly translates export_system_includes with arch variance",
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library_shared {
- name: "libtest",
- srcs: ["libf.so"],
- arch: {
- arm: { export_system_include_dirs: ["testdir/1/"], },
- arm64: { export_system_include_dirs: ["testdir/2/"], },
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
- "shared_library": `"libf.so"`,
- "export_system_includes": `select({
- "//build/bazel/platforms/arch:arm": ["testdir/1/"],
- "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
diff --git a/bp2build/cc_prebuilt_library_shared_test.go b/bp2build/cc_prebuilt_library_shared_test.go
deleted file mode 100644
index 58c0a70..0000000
--- a/bp2build/cc_prebuilt_library_shared_test.go
+++ /dev/null
@@ -1,85 +0,0 @@
-package bp2build
-
-import (
- "fmt"
- "testing"
-
- "android/soong/cc"
-)
-
-func TestSharedPrebuiltLibrary(t *testing.T) {
- RunBp2BuildTestCaseSimple(t,
- Bp2buildTestCase{
- Description: "prebuilt library shared simple",
- ModuleTypeUnderTest: "cc_prebuilt_library_shared",
- ModuleTypeUnderTestFactory: cc.PrebuiltSharedLibraryFactory,
- Filesystem: map[string]string{
- "libf.so": "",
- },
- Blueprint: `
-cc_prebuilt_library_shared {
- name: "libtest",
- srcs: ["libf.so"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
- "shared_library": `"libf.so"`,
- }),
- },
- })
-}
-
-func TestSharedPrebuiltLibraryWithArchVariance(t *testing.T) {
- RunBp2BuildTestCaseSimple(t,
- Bp2buildTestCase{
- Description: "prebuilt library shared with arch variance",
- ModuleTypeUnderTest: "cc_prebuilt_library_shared",
- ModuleTypeUnderTestFactory: cc.PrebuiltSharedLibraryFactory,
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library_shared {
- name: "libtest",
- arch: {
- arm64: { srcs: ["libf.so"], },
- arm: { srcs: ["libg.so"], },
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_shared", "libtest", AttrNameToString{
- "shared_library": `select({
- "//build/bazel/platforms/arch:arm": "libg.so",
- "//build/bazel/platforms/arch:arm64": "libf.so",
- "//conditions:default": None,
- })`,
- }),
- },
- })
-}
-
-func TestSharedPrebuiltLibrarySharedStanzaFails(t *testing.T) {
- RunBp2BuildTestCaseSimple(t,
- Bp2buildTestCase{
- Description: "prebuilt library shared with shared stanza fails because multiple sources",
- ModuleTypeUnderTest: "cc_prebuilt_library_shared",
- ModuleTypeUnderTestFactory: cc.PrebuiltSharedLibraryFactory,
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library_shared {
- name: "libtest",
- srcs: ["libf.so"],
- shared: {
- srcs: ["libg.so"],
- },
- bazel_module: { bp2build_available: true},
-}`,
- ExpectedErr: fmt.Errorf("Expected at most one source file"),
- })
-}
diff --git a/bp2build/cc_prebuilt_library_static_conversion_test.go b/bp2build/cc_prebuilt_library_static_conversion_test.go
deleted file mode 100644
index 77562e7..0000000
--- a/bp2build/cc_prebuilt_library_static_conversion_test.go
+++ /dev/null
@@ -1,199 +0,0 @@
-// 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 (
- "testing"
-
- "android/soong/cc"
-)
-
-func runCcPrebuiltLibraryStaticTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Parallel()
- t.Helper()
- (&tc).ModuleTypeUnderTest = "cc_prebuilt_library_static"
- (&tc).ModuleTypeUnderTestFactory = cc.PrebuiltStaticLibraryFactory
- RunBp2BuildTestCaseSimple(t, tc)
-}
-
-func TestPrebuiltLibraryStaticSimple(t *testing.T) {
- runCcPrebuiltLibraryStaticTestCase(t,
- Bp2buildTestCase{
- Description: "prebuilt library static simple",
- Filesystem: map[string]string{
- "libf.so": "",
- },
- Blueprint: `
-cc_prebuilt_library_static {
- name: "libtest",
- srcs: ["libf.so"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
- "static_library": `"libf.so"`,
- }),
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_alwayslink", AttrNameToString{
- "static_library": `"libf.so"`,
- "alwayslink": "True",
- }),
- },
- })
-}
-
-func TestPrebuiltLibraryStaticWithArchVariance(t *testing.T) {
- runCcPrebuiltLibraryStaticTestCase(t,
- Bp2buildTestCase{
- Description: "prebuilt library with arch variance",
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library_static {
- name: "libtest",
- arch: {
- arm64: { srcs: ["libf.so"], },
- arm: { srcs: ["libg.so"], },
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
- "static_library": `select({
- "//build/bazel/platforms/arch:arm": "libg.so",
- "//build/bazel/platforms/arch:arm64": "libf.so",
- "//conditions:default": None,
- })`}),
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_alwayslink", AttrNameToString{
- "alwayslink": "True",
- "static_library": `select({
- "//build/bazel/platforms/arch:arm": "libg.so",
- "//build/bazel/platforms/arch:arm64": "libf.so",
- "//conditions:default": None,
- })`}),
- },
- })
-}
-
-func TestPrebuiltLibraryStaticAdditionalAttrs(t *testing.T) {
- runCcPrebuiltLibraryStaticTestCase(t,
- Bp2buildTestCase{
- Description: "prebuilt library additional attributes",
- Filesystem: map[string]string{
- "libf.so": "",
- "testdir/1/include.h": "",
- "testdir/2/other.h": "",
- },
- Blueprint: `
-cc_prebuilt_library_static {
- name: "libtest",
- srcs: ["libf.so"],
- export_include_dirs: ["testdir/1/"],
- export_system_include_dirs: ["testdir/2/"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
- "static_library": `"libf.so"`,
- "export_includes": `["testdir/1/"]`,
- "export_system_includes": `["testdir/2/"]`,
- }),
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_alwayslink", AttrNameToString{
- "static_library": `"libf.so"`,
- "export_includes": `["testdir/1/"]`,
- "export_system_includes": `["testdir/2/"]`,
- "alwayslink": "True",
- }),
- },
- })
-}
-
-func TestPrebuiltLibraryStaticWithExportIncludesArchVariant(t *testing.T) {
- runCcPrebuiltLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_prebuilt_library_static correctly translates export_includes with arch variance",
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library_static {
- name: "libtest",
- srcs: ["libf.so"],
- arch: {
- arm: { export_include_dirs: ["testdir/1/"], },
- arm64: { export_include_dirs: ["testdir/2/"], },
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
- "static_library": `"libf.so"`,
- "export_includes": `select({
- "//build/bazel/platforms/arch:arm": ["testdir/1/"],
- "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_alwayslink", AttrNameToString{
- "alwayslink": "True",
- "static_library": `"libf.so"`,
- "export_includes": `select({
- "//build/bazel/platforms/arch:arm": ["testdir/1/"],
- "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestPrebuiltLibraryStaticWithExportSystemIncludesArchVariant(t *testing.T) {
- runCcPrebuiltLibraryStaticTestCase(t, Bp2buildTestCase{
- Description: "cc_prebuilt_library_static correctly translates export_system_includes with arch variance",
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library_static {
- name: "libtest",
- srcs: ["libf.so"],
- arch: {
- arm: { export_system_include_dirs: ["testdir/1/"], },
- arm64: { export_system_include_dirs: ["testdir/2/"], },
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
- "static_library": `"libf.so"`,
- "export_system_includes": `select({
- "//build/bazel/platforms/arch:arm": ["testdir/1/"],
- "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_alwayslink", AttrNameToString{
- "alwayslink": "True",
- "static_library": `"libf.so"`,
- "export_system_includes": `select({
- "//build/bazel/platforms/arch:arm": ["testdir/1/"],
- "//build/bazel/platforms/arch:arm64": ["testdir/2/"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
diff --git a/bp2build/cc_prebuilt_library_static_test.go b/bp2build/cc_prebuilt_library_static_test.go
deleted file mode 100644
index 17da813..0000000
--- a/bp2build/cc_prebuilt_library_static_test.go
+++ /dev/null
@@ -1,157 +0,0 @@
-// 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 TestStaticPrebuiltLibrary(t *testing.T) {
- RunBp2BuildTestCaseSimple(t,
- Bp2buildTestCase{
- Description: "prebuilt library static simple",
- ModuleTypeUnderTest: "cc_prebuilt_library_static",
- ModuleTypeUnderTestFactory: cc.PrebuiltStaticLibraryFactory,
- Filesystem: map[string]string{
- "libf.so": "",
- },
- Blueprint: `
-cc_prebuilt_library_static {
- name: "libtest",
- srcs: ["libf.so"],
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
- "static_library": `"libf.so"`,
- }),
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_alwayslink", AttrNameToString{
- "static_library": `"libf.so"`,
- "alwayslink": "True",
- }),
- },
- })
-}
-
-func TestStaticPrebuiltLibraryWithArchVariance(t *testing.T) {
- RunBp2BuildTestCaseSimple(t,
- Bp2buildTestCase{
- Description: "prebuilt library static with arch variance",
- ModuleTypeUnderTest: "cc_prebuilt_library_static",
- ModuleTypeUnderTestFactory: cc.PrebuiltStaticLibraryFactory,
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library_static {
- name: "libtest",
- arch: {
- arm64: { srcs: ["libf.so"], },
- arm: { srcs: ["libg.so"], },
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_prebuilt_library_static", "libtest", AttrNameToString{
- "static_library": `select({
- "//build/bazel/platforms/arch:arm": "libg.so",
- "//build/bazel/platforms/arch:arm64": "libf.so",
- "//conditions:default": None,
- })`}),
- MakeBazelTarget("cc_prebuilt_library_static", "libtest_alwayslink", AttrNameToString{
- "alwayslink": "True",
- "static_library": `select({
- "//build/bazel/platforms/arch:arm": "libg.so",
- "//build/bazel/platforms/arch:arm64": "libf.so",
- "//conditions:default": None,
- })`}),
- },
- })
-}
-
-func TestStaticPrebuiltLibraryStaticStanzaFails(t *testing.T) {
- RunBp2BuildTestCaseSimple(t,
- Bp2buildTestCase{
- Description: "prebuilt library with static stanza fails because multiple sources",
- ModuleTypeUnderTest: "cc_prebuilt_library_static",
- ModuleTypeUnderTestFactory: cc.PrebuiltStaticLibraryFactory,
- Filesystem: map[string]string{
- "libf.so": "",
- "libg.so": "",
- },
- Blueprint: `
-cc_prebuilt_library_static {
- name: "libtest",
- srcs: ["libf.so"],
- static: {
- srcs: ["libg.so"],
- },
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedErr: fmt.Errorf("Expected at most one source file"),
- })
-}
-
-func TestCcLibraryStaticConvertLex(t *testing.T) {
- runCcLibrarySharedTestCase(t, Bp2buildTestCase{
- Description: "cc_library_static with lex files",
- ModuleTypeUnderTest: "cc_library_static",
- ModuleTypeUnderTestFactory: cc.LibraryStaticFactory,
- Filesystem: map[string]string{
- "foo.c": "",
- "bar.cc": "",
- "foo1.l": "",
- "bar1.ll": "",
- "foo2.l": "",
- "bar2.ll": "",
- },
- Blueprint: `cc_library_static {
- name: "foo_lib",
- srcs: ["foo.c", "bar.cc", "foo1.l", "foo2.l", "bar1.ll", "bar2.ll"],
- lex: { flags: ["--foo_flags"] },
- include_build_directory: false,
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("genlex", "foo_lib_genlex_l", AttrNameToString{
- "srcs": `[
- "foo1.l",
- "foo2.l",
- ]`,
- "lexopts": `["--foo_flags"]`,
- }),
- MakeBazelTarget("genlex", "foo_lib_genlex_ll", AttrNameToString{
- "srcs": `[
- "bar1.ll",
- "bar2.ll",
- ]`,
- "lexopts": `["--foo_flags"]`,
- }),
- MakeBazelTarget("cc_library_static", "foo_lib", AttrNameToString{
- "srcs": `[
- "bar.cc",
- ":foo_lib_genlex_ll",
- ]`,
- "srcs_c": `[
- "foo.c",
- ":foo_lib_genlex_l",
- ]`,
- }),
- },
- })
-}
diff --git a/bp2build/cc_prebuilt_object_conversion_test.go b/bp2build/cc_prebuilt_object_conversion_test.go
deleted file mode 100644
index 903c816..0000000
--- a/bp2build/cc_prebuilt_object_conversion_test.go
+++ /dev/null
@@ -1,101 +0,0 @@
-// 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/cc_test_conversion_test.go b/bp2build/cc_test_conversion_test.go
deleted file mode 100644
index 9639ab9..0000000
--- a/bp2build/cc_test_conversion_test.go
+++ /dev/null
@@ -1,618 +0,0 @@
-// 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/android"
- "android/soong/cc"
- "android/soong/genrule"
-)
-
-type ccTestBp2buildTestCase struct {
- description string
- blueprint string
- filesystem map[string]string
- targets []testBazelTarget
-}
-
-func registerCcTestModuleTypes(ctx android.RegistrationContext) {
- cc.RegisterCCBuildComponents(ctx)
- ctx.RegisterModuleType("cc_binary", cc.BinaryFactory)
- ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
- ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
- ctx.RegisterModuleType("cc_test_library", cc.TestLibraryFactory)
- ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
-}
-
-func runCcTestTestCase(t *testing.T, testCase ccTestBp2buildTestCase) {
- t.Helper()
- moduleTypeUnderTest := "cc_test"
- description := fmt.Sprintf("%s %s", moduleTypeUnderTest, testCase.description)
- t.Run(description, func(t *testing.T) {
- t.Helper()
- RunBp2BuildTestCase(t, registerCcTestModuleTypes, Bp2buildTestCase{
- ExpectedBazelTargets: generateBazelTargetsForTest(testCase.targets, android.HostAndDeviceSupported),
- Filesystem: testCase.filesystem,
- ModuleTypeUnderTest: moduleTypeUnderTest,
- ModuleTypeUnderTestFactory: cc.TestFactory,
- Description: description,
- Blueprint: testCase.blueprint,
- })
- })
-}
-
-func TestBasicCcTest(t *testing.T) {
- runCcTestTestCase(t, ccTestBp2buildTestCase{
- description: "basic cc_test with commonly used attributes",
- blueprint: `
-cc_test {
- name: "mytest",
- host_supported: true,
- srcs: ["test.cpp"],
- target: {
- android: {
- srcs: ["android.cpp"],
- shared_libs: ["foolib"],
- },
- linux: {
- srcs: ["linux.cpp"],
- },
- host: {
- static_libs: ["hostlib"],
- },
- },
- static_libs: ["cc_test_lib1"],
- shared_libs: ["cc_test_lib2"],
- data: [":data_mod", "file.txt"],
- data_bins: [":cc_bin"],
- data_libs: [":cc_lib"],
- cflags: ["-Wall"],
-}
-
-cc_test_library {
- name: "cc_test_lib1",
- host_supported: true,
- include_build_directory: false,
-}
-` + simpleModuleDoNotConvertBp2build("cc_library", "foolib") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "hostlib") +
- simpleModuleDoNotConvertBp2build("genrule", "data_mod") +
- simpleModuleDoNotConvertBp2build("cc_binary", "cc_bin") +
- simpleModuleDoNotConvertBp2build("cc_library", "cc_lib") +
- simpleModuleDoNotConvertBp2build("cc_test_library", "cc_test_lib2") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
- targets: []testBazelTarget{
- {"cc_library_shared", "cc_test_lib1", AttrNameToString{}},
- {"cc_library_static", "cc_test_lib1_bp2build_cc_library_static", AttrNameToString{}},
- {"cc_test", "mytest", AttrNameToString{
- "copts": `["-Wall"]`,
- "data": `[
- ":data_mod",
- "file.txt",
- ":cc_bin",
- ":cc_lib",
- ]`,
- "deps": `[
- ":cc_test_lib1_bp2build_cc_library_static",
- ":libgtest_main",
- ":libgtest",
- ] + select({
- "//build/bazel/platforms/os:darwin": [":hostlib"],
- "//build/bazel/platforms/os:linux_bionic": [":hostlib"],
- "//build/bazel/platforms/os:linux_glibc": [":hostlib"],
- "//build/bazel/platforms/os:linux_musl": [":hostlib"],
- "//build/bazel/platforms/os:windows": [":hostlib"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- "dynamic_deps": `[":cc_test_lib2"] + select({
- "//build/bazel/platforms/os:android": [":foolib"],
- "//conditions:default": [],
- })`,
- "srcs": `["test.cpp"] + select({
- "//build/bazel/platforms/os:android": [
- "linux.cpp",
- "android.cpp",
- ],
- "//build/bazel/platforms/os:linux_bionic": ["linux.cpp"],
- "//build/bazel/platforms/os:linux_glibc": ["linux.cpp"],
- "//build/bazel/platforms/os:linux_musl": ["linux.cpp"],
- "//conditions:default": [],
- })`,
- "runs_on": `[
- "host_without_device",
- "device",
- ]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm64": [
- "memtag_heap",
- "diag_memtag_heap",
- ],
- "//conditions:default": [],
- })`,
- },
- },
- },
- })
-}
-
-func TestBasicCcTestGtestIsolatedDisabled(t *testing.T) {
- runCcTestTestCase(t, ccTestBp2buildTestCase{
- description: "cc test with disabled gtest and isolated props",
- blueprint: `
-cc_test {
- name: "mytest",
- host_supported: true,
- srcs: ["test.cpp"],
- gtest: false,
- isolated: false,
-}
-`,
- targets: []testBazelTarget{
- {"cc_test", "mytest", AttrNameToString{
- "gtest": "False",
- "local_includes": `["."]`,
- "srcs": `["test.cpp"]`,
- "runs_on": `[
- "host_without_device",
- "device",
- ]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm64": [
- "memtag_heap",
- "diag_memtag_heap",
- ],
- "//conditions:default": [],
- })`,
- },
- },
- },
- })
-}
-
-func TestCcTest_TestOptions_Tags(t *testing.T) {
- runCcTestTestCase(t, ccTestBp2buildTestCase{
- description: "cc test with test_options.tags converted to tags",
- blueprint: `
-cc_test {
- name: "mytest",
- host_supported: true,
- srcs: ["test.cpp"],
- test_options: { tags: ["no-remote"] },
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
- targets: []testBazelTarget{
- {"cc_test", "mytest", AttrNameToString{
- "tags": `["no-remote"]`,
- "local_includes": `["."]`,
- "srcs": `["test.cpp"]`,
- "deps": `[
- ":libgtest_main",
- ":libgtest",
- ]`,
- "runs_on": `[
- "host_without_device",
- "device",
- ]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm64": [
- "memtag_heap",
- "diag_memtag_heap",
- ],
- "//conditions:default": [],
- })`,
- },
- },
- },
- })
-}
-
-func TestCcTest_TestConfig(t *testing.T) {
- runCcTestTestCase(t, ccTestBp2buildTestCase{
- description: "cc test that sets a test_config",
- filesystem: map[string]string{
- "test_config.xml": "",
- },
- blueprint: `
-cc_test {
- name: "mytest",
- srcs: ["test.cpp"],
- test_config: "test_config.xml",
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
- targets: []testBazelTarget{
- {"cc_test", "mytest", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `["test.cpp"]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- "test_config": `"test_config.xml"`,
- "deps": `[
- ":libgtest_main",
- ":libgtest",
- ]`,
- "runs_on": `["device"]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm64": [
- "memtag_heap",
- "diag_memtag_heap",
- ],
- "//conditions:default": [],
- })`,
- },
- },
- },
- })
-}
-
-func TestCcTest_TestConfigAndroidTestXML(t *testing.T) {
- runCcTestTestCase(t, ccTestBp2buildTestCase{
- description: "cc test that defaults to test config AndroidTest.xml",
- filesystem: map[string]string{
- "AndroidTest.xml": "",
- "DynamicConfig.xml": "",
- },
- blueprint: `
-cc_test {
- name: "mytest",
- srcs: ["test.cpp"],
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
- targets: []testBazelTarget{
- {"cc_test", "mytest", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `["test.cpp"]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- "test_config": `"AndroidTest.xml"`,
- "dynamic_config": `"DynamicConfig.xml"`,
- "deps": `[
- ":libgtest_main",
- ":libgtest",
- ]`,
- "runs_on": `["device"]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm64": [
- "memtag_heap",
- "diag_memtag_heap",
- ],
- "//conditions:default": [],
- })`,
- },
- },
- },
- })
-}
-
-func TestCcTest_TestConfigTemplateOptions(t *testing.T) {
- runCcTestTestCase(t, ccTestBp2buildTestCase{
- description: "cc test that sets test config template attributes",
- filesystem: map[string]string{
- "test_config_template.xml": "",
- },
- blueprint: `
-cc_test {
- name: "mytest",
- srcs: ["test.cpp"],
- test_config_template: "test_config_template.xml",
- auto_gen_config: true,
- isolated: true,
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
- simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
- targets: []testBazelTarget{
- {"cc_test", "mytest", AttrNameToString{
- "auto_generate_test_config": "True",
- "local_includes": `["."]`,
- "srcs": `["test.cpp"]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- "template_configs": `[
- "'<target_preparer class=\"com.android.tradefed.targetprep.RootTargetPreparer\">\\n <option name=\"force-root\" value=\"false\" />\\n </target_preparer>'",
- "'<option name=\"not-shardable\" value=\"true\" />'",
- ]`,
- "template_install_base": `"/data/local/tmp"`,
- "template_test_config": `"test_config_template.xml"`,
- "deps": `[":libgtest_isolated_main"]`,
- "dynamic_deps": `[":liblog"]`,
- "runs_on": `["device"]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm64": [
- "memtag_heap",
- "diag_memtag_heap",
- ],
- "//conditions:default": [],
- })`,
- },
- },
- },
- })
-}
-
-func TestCcTest_WithExplicitGTestDepInAndroidBp(t *testing.T) {
- runCcTestTestCase(t, ccTestBp2buildTestCase{
- description: "cc test that lists libgtest in Android.bp should not have dups of libgtest in BUILD file",
- blueprint: `
-cc_test {
- name: "mytest",
- srcs: ["test.cpp"],
- static_libs: ["libgtest"],
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
- targets: []testBazelTarget{
- {"cc_test", "mytest", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `["test.cpp"]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- "deps": `[
- ":libgtest",
- ":libgtest_main",
- ]`,
- "runs_on": `["device"]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm64": [
- "memtag_heap",
- "diag_memtag_heap",
- ],
- "//conditions:default": [],
- })`,
- },
- },
- },
- })
-
-}
-
-func TestCcTest_WithIsolatedTurnedOn(t *testing.T) {
- runCcTestTestCase(t, ccTestBp2buildTestCase{
- description: "cc test that sets `isolated: true` should run with ligtest_isolated_main instead of libgtest_main",
- blueprint: `
-cc_test {
- name: "mytest",
- srcs: ["test.cpp"],
- isolated: true,
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
- simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
- targets: []testBazelTarget{
- {"cc_test", "mytest", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `["test.cpp"]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- "deps": `[":libgtest_isolated_main"]`,
- "dynamic_deps": `[":liblog"]`,
- "runs_on": `["device"]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm64": [
- "memtag_heap",
- "diag_memtag_heap",
- ],
- "//conditions:default": [],
- })`,
- },
- },
- },
- })
-
-}
-
-func TestCcTest_GtestExplicitlySpecifiedInAndroidBp(t *testing.T) {
- runCcTestTestCase(t, ccTestBp2buildTestCase{
- description: "If `gtest` is explicit in Android.bp, it should be explicit in BUILD files as well",
- blueprint: `
-cc_test {
- name: "mytest_with_gtest",
- gtest: true,
-}
-cc_test {
- name: "mytest_with_no_gtest",
- gtest: false,
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_main") +
- simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest"),
- targets: []testBazelTarget{
- {"cc_test", "mytest_with_gtest", AttrNameToString{
- "local_includes": `["."]`,
- "deps": `[
- ":libgtest_main",
- ":libgtest",
- ]`,
- "gtest": "True",
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- "runs_on": `["device"]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm64": [
- "memtag_heap",
- "diag_memtag_heap",
- ],
- "//conditions:default": [],
- })`,
- },
- },
- {"cc_test", "mytest_with_no_gtest", AttrNameToString{
- "local_includes": `["."]`,
- "gtest": "False",
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- "runs_on": `["device"]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm64": [
- "memtag_heap",
- "diag_memtag_heap",
- ],
- "//conditions:default": [],
- })`,
- },
- },
- },
- })
-}
-
-func TestCcTest_DisableMemtagHeap(t *testing.T) {
- runCcTestTestCase(t, ccTestBp2buildTestCase{
- description: "cc test that disable memtag_heap",
- blueprint: `
-cc_test {
- name: "mytest",
- srcs: ["test.cpp"],
- isolated: true,
- sanitize: {
- cfi: true,
- memtag_heap: false,
- },
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
- simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
- targets: []testBazelTarget{
- {"cc_test", "mytest", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `["test.cpp"]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- "deps": `[":libgtest_isolated_main"]`,
- "dynamic_deps": `[":liblog"]`,
- "runs_on": `["device"]`,
- "features": `["android_cfi"] + select({
- "//build/bazel/platforms/os_arch:android_arm64": ["-memtag_heap"],
- "//conditions:default": [],
- })`,
- },
- },
- },
- })
-}
-
-func TestCcTest_RespectArm64MemtagHeap(t *testing.T) {
- runCcTestTestCase(t, ccTestBp2buildTestCase{
- description: "cc test that disable memtag_heap",
- blueprint: `
-cc_test {
- name: "mytest",
- srcs: ["test.cpp"],
- isolated: true,
- target: {
- android_arm64: {
- sanitize: {
- memtag_heap: false,
- }
- }
- },
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
- simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
- targets: []testBazelTarget{
- {"cc_test", "mytest", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `["test.cpp"]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- "deps": `[":libgtest_isolated_main"]`,
- "dynamic_deps": `[":liblog"]`,
- "runs_on": `["device"]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm64": ["-memtag_heap"],
- "//conditions:default": [],
- })`,
- },
- },
- },
- })
-}
-
-func TestCcTest_IgnoreNoneArm64MemtagHeap(t *testing.T) {
- runCcTestTestCase(t, ccTestBp2buildTestCase{
- description: "cc test that disable memtag_heap",
- blueprint: `
-cc_test {
- name: "mytest",
- srcs: ["test.cpp"],
- isolated: true,
- arch: {
- x86: {
- sanitize: {
- memtag_heap: false,
- }
- }
- },
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
- simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
- targets: []testBazelTarget{
- {"cc_test", "mytest", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `["test.cpp"]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- "deps": `[":libgtest_isolated_main"]`,
- "dynamic_deps": `[":liblog"]`,
- "runs_on": `["device"]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm64": [
- "memtag_heap",
- "diag_memtag_heap",
- ],
- "//conditions:default": [],
- })`,
- },
- },
- },
- })
-}
-
-func TestCcTest_Arm64MemtagHeapOverrideNoConfigOne(t *testing.T) {
- runCcTestTestCase(t, ccTestBp2buildTestCase{
- description: "cc test that disable memtag_heap",
- blueprint: `
-cc_test {
- name: "mytest",
- srcs: ["test.cpp"],
- isolated: true,
- sanitize: {
- memtag_heap: true,
- },
- target: {
- android_arm64: {
- sanitize: {
- memtag_heap: false,
- diag: {
- memtag_heap: false,
- },
- }
- }
- },
-}
-` + simpleModuleDoNotConvertBp2build("cc_library_static", "libgtest_isolated_main") +
- simpleModuleDoNotConvertBp2build("cc_library", "liblog"),
- targets: []testBazelTarget{
- {"cc_test", "mytest", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `["test.cpp"]`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- "deps": `[":libgtest_isolated_main"]`,
- "dynamic_deps": `[":liblog"]`,
- "runs_on": `["device"]`,
- "features": `select({
- "//build/bazel/platforms/os_arch:android_arm64": [
- "-memtag_heap",
- "-diag_memtag_heap",
- ],
- "//conditions:default": [],
- })`,
- },
- },
- },
- })
-}
diff --git a/bp2build/cc_yasm_conversion_test.go b/bp2build/cc_yasm_conversion_test.go
deleted file mode 100644
index 55d4feb..0000000
--- a/bp2build/cc_yasm_conversion_test.go
+++ /dev/null
@@ -1,179 +0,0 @@
-// 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 (
- "testing"
-
- "android/soong/android"
- "android/soong/cc"
-)
-
-func runYasmTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, registerYasmModuleTypes, tc)
-}
-
-func registerYasmModuleTypes(ctx android.RegistrationContext) {
- cc.RegisterCCBuildComponents(ctx)
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory)
- ctx.RegisterModuleType("cc_prebuilt_library_static", cc.PrebuiltStaticLibraryFactory)
- ctx.RegisterModuleType("cc_library_headers", cc.LibraryHeaderFactory)
-}
-
-func TestYasmSimple(t *testing.T) {
- runYasmTestCase(t, Bp2buildTestCase{
- Description: "Simple yasm test",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "main.cpp": "",
- "myfile.asm": "",
- },
- Blueprint: `
-cc_library {
- name: "foo",
- srcs: ["main.cpp", "myfile.asm"],
-}`,
- ExpectedBazelTargets: append([]string{
- MakeBazelTarget("yasm", "foo_yasm", map[string]string{
- "include_dirs": `["."]`,
- "srcs": `["myfile.asm"]`,
- }),
- }, makeCcLibraryTargets("foo", map[string]string{
- "local_includes": `["."]`,
- "srcs": `[
- "main.cpp",
- ":foo_yasm",
- ]`,
- })...),
- })
-}
-
-func TestYasmWithIncludeDirs(t *testing.T) {
- runYasmTestCase(t, Bp2buildTestCase{
- Description: "Simple yasm test",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "main.cpp": "",
- "myfile.asm": "",
- "include1/foo/myinclude.inc": "",
- "include2/foo/myinclude2.inc": "",
- },
- Blueprint: `
-cc_library {
- name: "foo",
- local_include_dirs: ["include1/foo"],
- export_include_dirs: ["include2/foo"],
- srcs: ["main.cpp", "myfile.asm"],
-}`,
- ExpectedBazelTargets: append([]string{
- MakeBazelTarget("yasm", "foo_yasm", map[string]string{
- "include_dirs": `[
- "include1/foo",
- ".",
- "include2/foo",
- ]`,
- "srcs": `["myfile.asm"]`,
- }),
- }, makeCcLibraryTargets("foo", map[string]string{
- "local_includes": `[
- "include1/foo",
- ".",
- ]`,
- "export_includes": `["include2/foo"]`,
- "srcs": `[
- "main.cpp",
- ":foo_yasm",
- ]`,
- })...),
- })
-}
-
-func TestYasmConditionalBasedOnArch(t *testing.T) {
- runYasmTestCase(t, Bp2buildTestCase{
- Description: "Simple yasm test",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "main.cpp": "",
- "myfile.asm": "",
- },
- Blueprint: `
-cc_library {
- name: "foo",
- srcs: ["main.cpp"],
- arch: {
- x86: {
- srcs: ["myfile.asm"],
- },
- },
-}`,
- ExpectedBazelTargets: append([]string{
- MakeBazelTarget("yasm", "foo_yasm", map[string]string{
- "include_dirs": `["."]`,
- "srcs": `select({
- "//build/bazel/platforms/arch:x86": ["myfile.asm"],
- "//conditions:default": [],
- })`,
- }),
- }, makeCcLibraryTargets("foo", map[string]string{
- "local_includes": `["."]`,
- "srcs": `["main.cpp"] + select({
- "//build/bazel/platforms/arch:x86": [":foo_yasm"],
- "//conditions:default": [],
- })`,
- })...),
- })
-}
-
-func TestYasmPartiallyConditional(t *testing.T) {
- runYasmTestCase(t, Bp2buildTestCase{
- Description: "Simple yasm test",
- ModuleTypeUnderTest: "cc_library",
- ModuleTypeUnderTestFactory: cc.LibraryFactory,
- Filesystem: map[string]string{
- "main.cpp": "",
- "myfile.asm": "",
- "mysecondfile.asm": "",
- },
- Blueprint: `
-cc_library {
- name: "foo",
- srcs: ["main.cpp", "myfile.asm"],
- arch: {
- x86: {
- srcs: ["mysecondfile.asm"],
- },
- },
-}`,
- ExpectedBazelTargets: append([]string{
- MakeBazelTarget("yasm", "foo_yasm", map[string]string{
- "include_dirs": `["."]`,
- "srcs": `["myfile.asm"] + select({
- "//build/bazel/platforms/arch:x86": ["mysecondfile.asm"],
- "//conditions:default": [],
- })`,
- }),
- }, makeCcLibraryTargets("foo", map[string]string{
- "local_includes": `["."]`,
- "srcs": `[
- "main.cpp",
- ":foo_yasm",
- ]`,
- })...),
- })
-}
diff --git a/bp2build/conversion.go b/bp2build/conversion.go
index da4b5cf..9f1aa09 100644
--- a/bp2build/conversion.go
+++ b/bp2build/conversion.go
@@ -1,20 +1,10 @@
package bp2build
import (
- "encoding/json"
- "fmt"
"reflect"
- "strconv"
"strings"
"android/soong/android"
- "android/soong/apex"
- "android/soong/cc"
- cc_config "android/soong/cc/config"
- java_config "android/soong/java/config"
- rust_config "android/soong/rust/config"
- "android/soong/starlark_fmt"
-
"github.com/google/blueprint/proptools"
)
@@ -24,94 +14,6 @@
Contents string
}
-// PRIVATE: Use CreateSoongInjectionDirFiles instead
-func soongInjectionFiles(cfg android.Config, metrics CodegenMetrics) ([]BazelFile, error) {
- var files []BazelFile
-
- files = append(files, newFile("android", GeneratedBuildFileName, "")) // Creates a //cc_toolchain package.
- files = append(files, newFile("android", "constants.bzl", android.BazelCcToolchainVars(cfg)))
-
- files = append(files, newFile("cc_toolchain", GeneratedBuildFileName, "")) // Creates a //cc_toolchain package.
- files = append(files, newFile("cc_toolchain", "config_constants.bzl", cc_config.BazelCcToolchainVars(cfg)))
- files = append(files, newFile("cc_toolchain", "sanitizer_constants.bzl", cc.BazelCcSanitizerToolchainVars(cfg)))
-
- files = append(files, newFile("java_toolchain", GeneratedBuildFileName, "")) // Creates a //java_toolchain package.
- files = append(files, newFile("java_toolchain", "constants.bzl", java_config.BazelJavaToolchainVars(cfg)))
-
- files = append(files, newFile("rust_toolchain", GeneratedBuildFileName, "")) // Creates a //rust_toolchain package.
- files = append(files, newFile("rust_toolchain", "constants.bzl", rust_config.BazelRustToolchainVars(cfg)))
-
- files = append(files, newFile("apex_toolchain", GeneratedBuildFileName, "")) // Creates a //apex_toolchain package.
- apexToolchainVars, err := apex.BazelApexToolchainVars()
- if err != nil {
- return nil, err
- }
- files = append(files, newFile("apex_toolchain", "constants.bzl", apexToolchainVars))
-
- if buf, err := json.MarshalIndent(metrics.convertedModuleWithType, "", " "); err != nil {
- return []BazelFile{}, err
- } else {
- files = append(files, newFile("metrics", "converted_modules.json", string(buf)))
- }
-
- convertedModulePathMap, err := json.MarshalIndent(metrics.convertedModulePathMap, "", "\t")
- if err != nil {
- panic(err)
- }
- files = append(files, newFile("metrics", GeneratedBuildFileName, "")) // Creates a //metrics package.
- files = append(files, newFile("metrics", "converted_modules_path_map.json", string(convertedModulePathMap)))
- files = append(files, newFile("metrics", "converted_modules_path_map.bzl", "modules = "+strings.ReplaceAll(string(convertedModulePathMap), "\\", "\\\\")))
-
- files = append(files, newFile("product_config", "soong_config_variables.bzl", cfg.Bp2buildSoongConfigDefinitions.String()))
-
- files = append(files, newFile("product_config", "arch_configuration.bzl", android.StarlarkArchConfigurations()))
-
- apiLevelsMap, err := android.GetApiLevelsMap(cfg)
- if err != nil {
- return nil, err
- }
- apiLevelsContent, err := json.Marshal(apiLevelsMap)
- if err != nil {
- return nil, err
- }
- files = append(files, newFile("api_levels", GeneratedBuildFileName, `exports_files(["api_levels.json"])`))
- // TODO(b/269691302) value of apiLevelsContent is product variable dependent and should be avoided for soong injection
- files = append(files, newFile("api_levels", "api_levels.json", string(apiLevelsContent)))
- files = append(files, newFile("api_levels", "platform_versions.bzl", platformVersionContents(cfg)))
-
- files = append(files, newFile("allowlists", GeneratedBuildFileName, ""))
- // TODO(b/262781701): Create an alternate soong_build entrypoint for writing out these files only when requested
- files = append(files, newFile("allowlists", "mixed_build_prod_allowlist.txt", strings.Join(android.GetBazelEnabledModules(android.BazelProdMode), "\n")+"\n"))
- files = append(files, newFile("allowlists", "mixed_build_staging_allowlist.txt", strings.Join(android.GetBazelEnabledModules(android.BazelStagingMode), "\n")+"\n"))
-
- return files, nil
-}
-
-func platformVersionContents(cfg android.Config) string {
- // Despite these coming from cfg.productVariables, they are actually hardcoded in global
- // makefiles, not set in individual product config makesfiles, so they're safe to just export
- // and load() directly.
-
- platformVersionActiveCodenames := make([]string, 0, len(cfg.PlatformVersionActiveCodenames()))
- for _, codename := range cfg.PlatformVersionActiveCodenames() {
- platformVersionActiveCodenames = append(platformVersionActiveCodenames, fmt.Sprintf("%q", codename))
- }
-
- platformSdkVersion := "None"
- if cfg.RawPlatformSdkVersion() != nil {
- platformSdkVersion = strconv.Itoa(*cfg.RawPlatformSdkVersion())
- }
-
- return fmt.Sprintf(`
-platform_versions = struct(
- platform_sdk_final = %s,
- platform_sdk_version = %s,
- platform_sdk_codename = %q,
- platform_version_active_codenames = [%s],
-)
-`, starlark_fmt.PrintBool(cfg.PlatformSdkFinal()), platformSdkVersion, cfg.PlatformSdkCodename(), strings.Join(platformVersionActiveCodenames, ", "))
-}
-
func CreateBazelFiles(ruleShims map[string]RuleShim, buildToTargets map[string]BazelTargets, mode CodegenMode) []BazelFile {
var files []BazelFile
@@ -145,20 +47,7 @@
targets.sort()
var content string
- if mode == Bp2Build {
- content = `# READ THIS FIRST:
-# This file was automatically generated by bp2build for the Bazel migration project.
-# Feel free to edit or test it, but do *not* check it into your version control system.
-`
- content += targets.LoadStatements()
- content += "\n\n"
- // Get package rule from the handcrafted BUILD file, otherwise emit the default one.
- prText := "package(default_visibility = [\"//visibility:public\"])\n"
- if pr := targets.packageRule(); pr != nil {
- prText = pr.content
- }
- content += prText
- } else if mode == QueryView {
+ if mode == QueryView {
content = soongModuleLoad
}
if content != "" {
@@ -181,14 +70,6 @@
const (
bazelRulesSubDir = "build/bazel/queryview_rules"
-
- // additional files:
- // * workspace file
- // * base BUILD file
- // * rules BUILD file
- // * rules providers.bzl file
- // * rules soong_module.bzl file
- numAdditionalFiles = 5
)
var (
diff --git a/bp2build/conversion_test.go b/bp2build/conversion_test.go
index 89dd38e..2f806fa 100644
--- a/bp2build/conversion_test.go
+++ b/bp2build/conversion_test.go
@@ -17,8 +17,6 @@
import (
"sort"
"testing"
-
- "android/soong/android"
)
type bazelFilepath struct {
@@ -80,117 +78,3 @@
}
}
}
-
-func TestCreateBazelFiles_Bp2Build_CreatesDefaultFiles(t *testing.T) {
- testConfig := android.TestConfig("", make(map[string]string), "", make(map[string][]byte))
- files, err := soongInjectionFiles(testConfig, CreateCodegenMetrics())
- if err != nil {
- t.Error(err)
- }
- expectedFilePaths := []bazelFilepath{
- {
- dir: "android",
- basename: GeneratedBuildFileName,
- },
- {
- dir: "android",
- basename: "constants.bzl",
- },
- {
- dir: "cc_toolchain",
- basename: GeneratedBuildFileName,
- },
- {
- dir: "cc_toolchain",
- basename: "config_constants.bzl",
- },
- {
- dir: "cc_toolchain",
- basename: "sanitizer_constants.bzl",
- },
- {
- dir: "java_toolchain",
- basename: GeneratedBuildFileName,
- },
- {
- dir: "java_toolchain",
- basename: "constants.bzl",
- },
- {
- dir: "rust_toolchain",
- basename: GeneratedBuildFileName,
- },
- {
- dir: "rust_toolchain",
- basename: "constants.bzl",
- },
- {
- dir: "apex_toolchain",
- basename: GeneratedBuildFileName,
- },
- {
- dir: "apex_toolchain",
- basename: "constants.bzl",
- },
- {
- dir: "metrics",
- basename: "converted_modules.json",
- },
- {
- dir: "metrics",
- basename: "BUILD.bazel",
- },
- {
- dir: "metrics",
- basename: "converted_modules_path_map.json",
- },
- {
- dir: "metrics",
- basename: "converted_modules_path_map.bzl",
- },
- {
- dir: "product_config",
- basename: "soong_config_variables.bzl",
- },
- {
- dir: "product_config",
- basename: "arch_configuration.bzl",
- },
- {
- dir: "api_levels",
- basename: GeneratedBuildFileName,
- },
- {
- dir: "api_levels",
- basename: "api_levels.json",
- },
- {
- dir: "api_levels",
- basename: "platform_versions.bzl",
- },
- {
- dir: "allowlists",
- basename: GeneratedBuildFileName,
- },
- {
- dir: "allowlists",
- basename: "mixed_build_prod_allowlist.txt",
- },
- {
- dir: "allowlists",
- basename: "mixed_build_staging_allowlist.txt",
- },
- }
-
- if len(files) != len(expectedFilePaths) {
- t.Errorf("Expected %d file, got %d", len(expectedFilePaths), len(files))
- }
-
- for i := range files {
- actualFile, expectedFile := files[i], expectedFilePaths[i]
-
- if actualFile.Dir != expectedFile.dir || actualFile.Basename != expectedFile.basename {
- t.Errorf("Did not find expected file %s/%s", actualFile.Dir, actualFile.Basename)
- }
- }
-}
diff --git a/bp2build/filegroup_conversion_test.go b/bp2build/filegroup_conversion_test.go
deleted file mode 100644
index cb2e207..0000000
--- a/bp2build/filegroup_conversion_test.go
+++ /dev/null
@@ -1,203 +0,0 @@
-// 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
-
-import (
- "fmt"
- "testing"
-
- "android/soong/android"
-)
-
-func runFilegroupTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "filegroup"
- (&tc).ModuleTypeUnderTestFactory = android.FileGroupFactory
- RunBp2BuildTestCase(t, registerFilegroupModuleTypes, tc)
-}
-
-func registerFilegroupModuleTypes(ctx android.RegistrationContext) {}
-
-func TestFilegroupSameNameAsFile_OneFile(t *testing.T) {
- runFilegroupTestCase(t, Bp2buildTestCase{
- Description: "filegroup - same name as file, with one file",
- Filesystem: map[string]string{},
- Blueprint: `
-filegroup {
- name: "foo",
- srcs: ["foo"],
-}
-`,
- ExpectedBazelTargets: []string{}})
-}
-
-func TestFilegroupSameNameAsFile_MultipleFiles(t *testing.T) {
- runFilegroupTestCase(t, Bp2buildTestCase{
- Description: "filegroup - same name as file, with multiple files",
- Filesystem: map[string]string{},
- Blueprint: `
-filegroup {
- name: "foo",
- srcs: ["foo", "bar"],
-}
-`,
- ExpectedErr: fmt.Errorf("filegroup 'foo' cannot contain a file with the same name"),
- })
-}
-
-func TestFilegroupWithAidlSrcs(t *testing.T) {
- testcases := []struct {
- name string
- bp string
- expectedBazelAttrs AttrNameToString
- }{
- {
- name: "filegroup with only aidl srcs",
- bp: `
- filegroup {
- name: "foo",
- srcs: ["aidl/foo.aidl"],
- path: "aidl",
- }`,
- expectedBazelAttrs: AttrNameToString{
- "srcs": `["aidl/foo.aidl"]`,
- "strip_import_prefix": `"aidl"`,
- "tags": `["apex_available=//apex_available:anyapex"]`,
- },
- },
- {
- name: "filegroup without path",
- bp: `
- filegroup {
- name: "foo",
- srcs: ["aidl/foo.aidl"],
- }`,
- expectedBazelAttrs: AttrNameToString{
- "srcs": `["aidl/foo.aidl"]`,
- "tags": `["apex_available=//apex_available:anyapex"]`,
- },
- },
- }
-
- for _, test := range testcases {
- t.Run(test.name, func(t *testing.T) {
- expectedBazelTargets := []string{
- MakeBazelTargetNoRestrictions("aidl_library", "foo", test.expectedBazelAttrs),
- }
- runFilegroupTestCase(t, Bp2buildTestCase{
- Description: test.name,
- Blueprint: test.bp,
- ExpectedBazelTargets: expectedBazelTargets,
- })
- })
- }
-}
-
-func TestFilegroupWithAidlAndNonAidlSrcs(t *testing.T) {
- runFilegroupTestCase(t, Bp2buildTestCase{
- Description: "filegroup with aidl and non-aidl srcs",
- Filesystem: map[string]string{},
- Blueprint: `
-filegroup {
- name: "foo",
- srcs: [
- "aidl/foo.aidl",
- "buf.proto",
- ],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "foo", AttrNameToString{
- "srcs": `[
- "aidl/foo.aidl",
- "buf.proto",
- ]`}),
- }})
-}
-
-func TestFilegroupWithProtoSrcs(t *testing.T) {
- runFilegroupTestCase(t, Bp2buildTestCase{
- Description: "filegroup with proto and non-proto srcs",
- Filesystem: map[string]string{},
- Blueprint: `
-filegroup {
- name: "foo",
- srcs: ["proto/foo.proto"],
- path: "proto",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["proto/foo.proto"]`,
- "strip_import_prefix": `"proto"`,
- "tags": `[
- "apex_available=//apex_available:anyapex",
- "manual",
- ]`,
- }),
- MakeBazelTargetNoRestrictions("alias", "foo_bp2build_converted", AttrNameToString{
- "actual": `"//.:foo_proto"`,
- "tags": `[
- "apex_available=//apex_available:anyapex",
- "manual",
- ]`,
- }),
- MakeBazelTargetNoRestrictions("filegroup", "foo", AttrNameToString{
- "srcs": `["proto/foo.proto"]`}),
- }})
-}
-
-func TestFilegroupWithProtoAndNonProtoSrcs(t *testing.T) {
- runFilegroupTestCase(t, Bp2buildTestCase{
- Description: "filegroup with proto and non-proto srcs",
- Filesystem: map[string]string{},
- Blueprint: `
-filegroup {
- name: "foo",
- srcs: [
- "foo.proto",
- "buf.cpp",
- ],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("filegroup", "foo", AttrNameToString{
- "srcs": `[
- "foo.proto",
- "buf.cpp",
- ]`}),
- }})
-}
-
-func TestFilegroupWithProtoInDifferentPackage(t *testing.T) {
- runFilegroupTestCase(t, Bp2buildTestCase{
- Description: "filegroup with .proto in different package",
- Filesystem: map[string]string{
- "subdir/Android.bp": "",
- },
- Blueprint: `
-filegroup {
- name: "foo",
- srcs: ["subdir/foo.proto"],
-}`,
- Dir: "subdir", // check in subdir
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("proto_library", "foo_proto", AttrNameToString{
- "srcs": `["//subdir:foo.proto"]`,
- "import_prefix": `"subdir"`,
- "strip_import_prefix": `""`,
- "tags": `[
- "apex_available=//apex_available:anyapex",
- "manual",
- ]`}),
- }})
-}
diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go
deleted file mode 100644
index 2a10a14..0000000
--- a/bp2build/genrule_conversion_test.go
+++ /dev/null
@@ -1,954 +0,0 @@
-// 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
-
-import (
- "fmt"
- "path/filepath"
- "testing"
-
- "android/soong/android"
- "android/soong/cc"
- "android/soong/genrule"
- "android/soong/java"
-)
-
-func registerGenruleModuleTypes(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("genrule_defaults", func() android.Module { return genrule.DefaultsFactory() })
- ctx.RegisterModuleType("cc_binary", func() android.Module { return cc.BinaryFactory() })
- ctx.RegisterModuleType("soong_namespace", func() android.Module { return android.NamespaceFactory() })
-}
-
-func runGenruleTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "genrule"
- (&tc).ModuleTypeUnderTestFactory = genrule.GenRuleFactory
- RunBp2BuildTestCase(t, registerGenruleModuleTypes, tc)
-}
-
-func otherGenruleBp(genruleTarget string) map[string]string {
- return map[string]string{
- "other/Android.bp": fmt.Sprintf(`%s {
- name: "foo.tool",
- out: ["foo_tool.out"],
- srcs: ["foo_tool.in"],
- cmd: "cp $(in) $(out)",
-}
-%s {
- name: "other.tool",
- out: ["other_tool.out"],
- srcs: ["other_tool.in"],
- cmd: "cp $(in) $(out)",
-}`, genruleTarget, genruleTarget),
- "other/file.txt": "",
- }
-}
-
-func TestGenruleCliVariableReplacement(t *testing.T) {
- testCases := []struct {
- moduleType string
- factory android.ModuleFactory
- genDir string
- hod android.HostOrDeviceSupported
- }{
- {
- moduleType: "genrule",
- factory: genrule.GenRuleFactory,
- genDir: "$(RULEDIR)",
- },
- {
- moduleType: "cc_genrule",
- factory: cc.GenRuleFactory,
- genDir: "$(RULEDIR)",
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule",
- factory: java.GenRuleFactory,
- genDir: "$(RULEDIR)",
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule_host",
- factory: java.GenRuleFactoryHost,
- genDir: "$(RULEDIR)",
- hod: android.HostSupported,
- },
- }
-
- bp := `%s {
- name: "foo.tool",
- out: ["foo_tool.out"],
- srcs: ["foo_tool.in"],
- cmd: "cp $(in) $(out)",
- bazel_module: { bp2build_available: false },
-}
-
-%s {
- name: "foo",
- out: ["foo.out"],
- srcs: ["foo.in"],
- tools: [":foo.tool"],
- cmd: "$(location :foo.tool) --genDir=$(genDir) arg $(in) $(out)",
- bazel_module: { bp2build_available: true },
-}`
-
- for _, tc := range testCases {
- moduleAttrs := AttrNameToString{
- "cmd": fmt.Sprintf(`"$(location :foo.tool) --genDir=%s arg $(SRCS) $(OUTS)"`, tc.genDir),
- "outs": `["foo.out"]`,
- "srcs": `["foo.in"]`,
- "tools": `[":foo.tool"]`,
- }
-
- expectedBazelTargets := []string{
- makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
- }
-
- t.Run(tc.moduleType, func(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
- Bp2buildTestCase{
- ModuleTypeUnderTest: tc.moduleType,
- ModuleTypeUnderTestFactory: tc.factory,
- Blueprint: fmt.Sprintf(bp, tc.moduleType, tc.moduleType),
- ExpectedBazelTargets: expectedBazelTargets,
- })
- })
- }
-}
-
-func TestGenruleLocationsLabel(t *testing.T) {
- testCases := []struct {
- moduleType string
- factory android.ModuleFactory
- hod android.HostOrDeviceSupported
- }{
- {
- moduleType: "genrule",
- factory: genrule.GenRuleFactory,
- },
- {
- moduleType: "cc_genrule",
- factory: cc.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule",
- factory: java.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule_host",
- factory: java.GenRuleFactoryHost,
- hod: android.HostSupported,
- },
- }
-
- bp := `%s {
- name: "foo.tools",
- out: ["foo_tool.out", "foo_tool2.out"],
- srcs: ["foo_tool.in"],
- cmd: "cp $(in) $(out)",
- bazel_module: { bp2build_available: true },
-}
-
-%s {
- name: "foo",
- out: ["foo.out"],
- srcs: ["foo.in"],
- tools: [":foo.tools"],
- cmd: "$(locations :foo.tools) -s $(out) $(in)",
- bazel_module: { bp2build_available: true },
-}`
-
- for _, tc := range testCases {
- fooAttrs := AttrNameToString{
- "cmd": `"$(locations :foo.tools) -s $(OUTS) $(SRCS)"`,
- "outs": `["foo.out"]`,
- "srcs": `["foo.in"]`,
- "tools": `[":foo.tools"]`,
- }
- fooToolsAttrs := AttrNameToString{
- "cmd": `"cp $(SRCS) $(OUTS)"`,
- "outs": `[
- "foo_tool.out",
- "foo_tool2.out",
- ]`,
- "srcs": `["foo_tool.in"]`,
- }
-
- expectedBazelTargets := []string{
- makeBazelTargetHostOrDevice("genrule", "foo", fooAttrs, tc.hod),
- makeBazelTargetHostOrDevice("genrule", "foo.tools", fooToolsAttrs, tc.hod),
- }
-
- t.Run(tc.moduleType, func(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
- Bp2buildTestCase{
- ModuleTypeUnderTest: tc.moduleType,
- ModuleTypeUnderTestFactory: tc.factory,
- Blueprint: fmt.Sprintf(bp, tc.moduleType, tc.moduleType),
- ExpectedBazelTargets: expectedBazelTargets,
- })
- })
- }
-}
-
-func TestGenruleLocationsAbsoluteLabel(t *testing.T) {
- testCases := []struct {
- moduleType string
- factory android.ModuleFactory
- hod android.HostOrDeviceSupported
- }{
- {
- moduleType: "genrule",
- factory: genrule.GenRuleFactory,
- },
- {
- moduleType: "cc_genrule",
- factory: cc.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule",
- factory: java.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule_host",
- factory: java.GenRuleFactoryHost,
- hod: android.HostSupported,
- },
- }
-
- bp := `%s {
- name: "foo",
- out: ["foo.out"],
- srcs: ["foo.in"],
- tool_files: [":foo.tool"],
- cmd: "$(locations :foo.tool) -s $(out) $(in)",
- bazel_module: { bp2build_available: true },
-}`
-
- for _, tc := range testCases {
- moduleAttrs := AttrNameToString{
- "cmd": `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
- "outs": `["foo.out"]`,
- "srcs": `["foo.in"]`,
- "tools": `["//other:foo.tool"]`,
- }
-
- expectedBazelTargets := []string{
- makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
- }
-
- t.Run(tc.moduleType, func(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
- Bp2buildTestCase{
- ModuleTypeUnderTest: tc.moduleType,
- ModuleTypeUnderTestFactory: tc.factory,
- Blueprint: fmt.Sprintf(bp, tc.moduleType),
- ExpectedBazelTargets: expectedBazelTargets,
- Filesystem: otherGenruleBp(tc.moduleType),
- })
- })
- }
-}
-
-func TestGenruleSrcsLocationsAbsoluteLabel(t *testing.T) {
- testCases := []struct {
- moduleType string
- factory android.ModuleFactory
- hod android.HostOrDeviceSupported
- }{
- {
- moduleType: "genrule",
- factory: genrule.GenRuleFactory,
- },
- {
- moduleType: "cc_genrule",
- factory: cc.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule",
- factory: java.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule_host",
- factory: java.GenRuleFactoryHost,
- hod: android.HostSupported,
- },
- }
-
- bp := `%s {
- name: "foo",
- out: ["foo.out"],
- srcs: [":other.tool", "other/file.txt",],
- tool_files: [":foo.tool"],
- cmd: "$(locations :foo.tool) $(location other/file.txt) -s $(out) $(location :other.tool)",
- bazel_module: { bp2build_available: true },
-}`
-
- for _, tc := range testCases {
- moduleAttrs := AttrNameToString{
- "cmd": `"$(locations //other:foo.tool) $(location //other:file.txt) -s $(OUTS) $(location //other:other.tool)"`,
- "outs": `["foo.out"]`,
- "srcs": `[
- "//other:other.tool",
- "//other:file.txt",
- ]`,
- "tools": `["//other:foo.tool"]`,
- }
-
- expectedBazelTargets := []string{
- makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
- }
-
- t.Run(tc.moduleType, func(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
- Bp2buildTestCase{
- ModuleTypeUnderTest: tc.moduleType,
- ModuleTypeUnderTestFactory: tc.factory,
- Blueprint: fmt.Sprintf(bp, tc.moduleType),
- ExpectedBazelTargets: expectedBazelTargets,
- Filesystem: otherGenruleBp(tc.moduleType),
- })
- })
- }
-}
-
-func TestGenruleLocationLabelShouldSubstituteFirstToolLabel(t *testing.T) {
- testCases := []struct {
- moduleType string
- factory android.ModuleFactory
- hod android.HostOrDeviceSupported
- }{
- {
- moduleType: "genrule",
- factory: genrule.GenRuleFactory,
- },
- {
- moduleType: "cc_genrule",
- factory: cc.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule",
- factory: java.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule_host",
- factory: java.GenRuleFactoryHost,
- hod: android.HostSupported,
- },
- }
-
- bp := `%s {
- name: "foo",
- out: ["foo.out"],
- srcs: ["foo.in"],
- tool_files: [":foo.tool", ":other.tool"],
- cmd: "$(location) -s $(out) $(in)",
- bazel_module: { bp2build_available: true },
-}`
-
- for _, tc := range testCases {
- moduleAttrs := AttrNameToString{
- "cmd": `"$(location //other:foo.tool) -s $(OUTS) $(SRCS)"`,
- "outs": `["foo.out"]`,
- "srcs": `["foo.in"]`,
- "tools": `[
- "//other:foo.tool",
- "//other:other.tool",
- ]`,
- }
-
- expectedBazelTargets := []string{
- makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
- }
-
- t.Run(tc.moduleType, func(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
- Bp2buildTestCase{
- ModuleTypeUnderTest: tc.moduleType,
- ModuleTypeUnderTestFactory: tc.factory,
- Blueprint: fmt.Sprintf(bp, tc.moduleType),
- ExpectedBazelTargets: expectedBazelTargets,
- Filesystem: otherGenruleBp(tc.moduleType),
- })
- })
- }
-}
-
-func TestGenruleLocationsLabelShouldSubstituteFirstToolLabel(t *testing.T) {
- testCases := []struct {
- moduleType string
- factory android.ModuleFactory
- hod android.HostOrDeviceSupported
- }{
- {
- moduleType: "genrule",
- factory: genrule.GenRuleFactory,
- },
- {
- moduleType: "cc_genrule",
- factory: cc.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule",
- factory: java.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule_host",
- factory: java.GenRuleFactoryHost,
- hod: android.HostSupported,
- },
- }
-
- bp := `%s {
- name: "foo",
- out: ["foo.out"],
- srcs: ["foo.in"],
- tool_files: [":foo.tool", ":other.tool"],
- cmd: "$(locations) -s $(out) $(in)",
- bazel_module: { bp2build_available: true },
-}`
-
- for _, tc := range testCases {
- moduleAttrs := AttrNameToString{
- "cmd": `"$(locations //other:foo.tool) -s $(OUTS) $(SRCS)"`,
- "outs": `["foo.out"]`,
- "srcs": `["foo.in"]`,
- "tools": `[
- "//other:foo.tool",
- "//other:other.tool",
- ]`,
- }
-
- expectedBazelTargets := []string{
- makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
- }
-
- t.Run(tc.moduleType, func(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
- Bp2buildTestCase{
- ModuleTypeUnderTest: tc.moduleType,
- ModuleTypeUnderTestFactory: tc.factory,
- Blueprint: fmt.Sprintf(bp, tc.moduleType),
- ExpectedBazelTargets: expectedBazelTargets,
- Filesystem: otherGenruleBp(tc.moduleType),
- })
- })
- }
-}
-
-func TestGenruleWithoutToolsOrToolFiles(t *testing.T) {
- testCases := []struct {
- moduleType string
- factory android.ModuleFactory
- hod android.HostOrDeviceSupported
- }{
- {
- moduleType: "genrule",
- factory: genrule.GenRuleFactory,
- },
- {
- moduleType: "cc_genrule",
- factory: cc.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule",
- factory: java.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule_host",
- factory: java.GenRuleFactoryHost,
- hod: android.HostSupported,
- },
- }
-
- bp := `%s {
- name: "foo",
- out: ["foo.out"],
- srcs: ["foo.in"],
- cmd: "cp $(in) $(out)",
- bazel_module: { bp2build_available: true },
-}`
-
- for _, tc := range testCases {
- moduleAttrs := AttrNameToString{
- "cmd": `"cp $(SRCS) $(OUTS)"`,
- "outs": `["foo.out"]`,
- "srcs": `["foo.in"]`,
- }
-
- expectedBazelTargets := []string{
- makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
- }
-
- t.Run(tc.moduleType, func(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
- Bp2buildTestCase{
- ModuleTypeUnderTest: tc.moduleType,
- ModuleTypeUnderTestFactory: tc.factory,
- Blueprint: fmt.Sprintf(bp, tc.moduleType),
- ExpectedBazelTargets: expectedBazelTargets,
- })
- })
- }
-}
-
-func TestGenruleBp2BuildInlinesDefaults(t *testing.T) {
- testCases := []Bp2buildTestCase{
- {
- Description: "genrule applies properties from a genrule_defaults dependency if not specified",
- Blueprint: `genrule_defaults {
- name: "gen_defaults",
- cmd: "do-something $(in) $(out)",
-}
-genrule {
- name: "gen",
- out: ["out"],
- srcs: ["in1"],
- defaults: ["gen_defaults"],
- bazel_module: { bp2build_available: true },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("genrule", "gen", AttrNameToString{
- "cmd": `"do-something $(SRCS) $(OUTS)"`,
- "outs": `["out"]`,
- "srcs": `["in1"]`,
- }),
- },
- },
- {
- Description: "genrule does merges properties from a genrule_defaults dependency, latest-first",
- Blueprint: `genrule_defaults {
- name: "gen_defaults",
- out: ["out-from-defaults"],
- srcs: ["in-from-defaults"],
- cmd: "cmd-from-defaults",
-}
-genrule {
- name: "gen",
- out: ["out"],
- srcs: ["in1"],
- defaults: ["gen_defaults"],
- cmd: "do-something $(in) $(out)",
- bazel_module: { bp2build_available: true },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("genrule", "gen", AttrNameToString{
- "cmd": `"do-something $(SRCS) $(OUTS)"`,
- "outs": `[
- "out-from-defaults",
- "out",
- ]`,
- "srcs": `[
- "in-from-defaults",
- "in1",
- ]`,
- }),
- },
- },
- {
- Description: "genrule applies properties from list of genrule_defaults",
- Blueprint: `genrule_defaults {
- name: "gen_defaults1",
- cmd: "cp $(in) $(out)",
-}
-
-genrule_defaults {
- name: "gen_defaults2",
- srcs: ["in1"],
-}
-
-genrule {
- name: "gen",
- out: ["out"],
- defaults: ["gen_defaults1", "gen_defaults2"],
- bazel_module: { bp2build_available: true },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("genrule", "gen", AttrNameToString{
- "cmd": `"cp $(SRCS) $(OUTS)"`,
- "outs": `["out"]`,
- "srcs": `["in1"]`,
- }),
- },
- },
- {
- Description: "genrule applies properties from genrule_defaults transitively",
- Blueprint: `genrule_defaults {
- name: "gen_defaults1",
- defaults: ["gen_defaults2"],
- cmd: "cmd1 $(in) $(out)", // overrides gen_defaults2's cmd property value.
-}
-
-genrule_defaults {
- name: "gen_defaults2",
- defaults: ["gen_defaults3"],
- cmd: "cmd2 $(in) $(out)",
- out: ["out-from-2"],
- srcs: ["in1"],
-}
-
-genrule_defaults {
- name: "gen_defaults3",
- out: ["out-from-3"],
- srcs: ["srcs-from-3"],
-}
-
-genrule {
- name: "gen",
- out: ["out"],
- defaults: ["gen_defaults1"],
- bazel_module: { bp2build_available: true },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("genrule", "gen", AttrNameToString{
- "cmd": `"cmd1 $(SRCS) $(OUTS)"`,
- "outs": `[
- "out-from-3",
- "out-from-2",
- "out",
- ]`,
- "srcs": `[
- "srcs-from-3",
- "in1",
- ]`,
- }),
- },
- },
- }
-
- for _, testCase := range testCases {
- t.Run(testCase.Description, func(t *testing.T) {
- runGenruleTestCase(t, testCase)
- })
- }
-}
-
-func TestCcGenruleArchAndExcludeSrcs(t *testing.T) {
- name := "cc_genrule with arch"
- bp := `
- cc_genrule {
- name: "foo",
- srcs: [
- "foo1.in",
- "foo2.in",
- ],
- exclude_srcs: ["foo2.in"],
- arch: {
- arm: {
- srcs: [
- "foo1_arch.in",
- "foo2_arch.in",
- ],
- exclude_srcs: ["foo2_arch.in"],
- },
- },
- cmd: "cat $(in) > $(out)",
- bazel_module: { bp2build_available: true },
- }`
-
- expectedBazelAttrs := AttrNameToString{
- "srcs": `["foo1.in"] + select({
- "//build/bazel/platforms/arch:arm": ["foo1_arch.in"],
- "//conditions:default": [],
- })`,
- "cmd": `"cat $(SRCS) > $(OUTS)"`,
- "target_compatible_with": `["//build/bazel/platforms/os:android"]`,
- }
-
- expectedBazelTargets := []string{
- MakeBazelTargetNoRestrictions("genrule", "foo", expectedBazelAttrs),
- }
-
- t.Run(name, func(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
- Bp2buildTestCase{
- ModuleTypeUnderTest: "cc_genrule",
- ModuleTypeUnderTestFactory: cc.GenRuleFactory,
- Blueprint: bp,
- ExpectedBazelTargets: expectedBazelTargets,
- })
- })
-}
-
-func TestGenruleWithExportIncludeDirs(t *testing.T) {
- testCases := []struct {
- moduleType string
- factory android.ModuleFactory
- hod android.HostOrDeviceSupported
- }{
- {
- moduleType: "genrule",
- factory: genrule.GenRuleFactory,
- },
- {
- moduleType: "cc_genrule",
- factory: cc.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule",
- factory: java.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule_host",
- factory: java.GenRuleFactoryHost,
- hod: android.HostSupported,
- },
- }
-
- dir := "baz"
-
- bp := `%s {
- name: "foo",
- out: ["foo.out.h"],
- srcs: ["foo.in"],
- cmd: "cp $(in) $(out)",
- export_include_dirs: ["foo", "bar", "."],
- bazel_module: { bp2build_available: true },
-}`
-
- for _, tc := range testCases {
- moduleAttrs := AttrNameToString{
- "cmd": `"cp $(SRCS) $(OUTS)"`,
- "outs": `["foo.out.h"]`,
- "srcs": `["foo.in"]`,
- }
-
- expectedBazelTargets := []string{
- makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
- makeBazelTargetHostOrDevice("cc_library_headers", "foo__header_library", AttrNameToString{
- "hdrs": `[":foo"]`,
- "export_includes": `[
- "foo",
- "baz/foo",
- "bar",
- "baz/bar",
- ".",
- "baz",
- ]`,
- },
- tc.hod),
- }
-
- t.Run(tc.moduleType, func(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
- Bp2buildTestCase{
- ModuleTypeUnderTest: tc.moduleType,
- ModuleTypeUnderTestFactory: tc.factory,
- Filesystem: map[string]string{
- filepath.Join(dir, "Android.bp"): fmt.Sprintf(bp, tc.moduleType),
- },
- Dir: dir,
- ExpectedBazelTargets: expectedBazelTargets,
- })
- })
- }
-}
-
-func TestGenruleWithSoongConfigVariableConfiguredCmd(t *testing.T) {
- testCases := []struct {
- moduleType string
- factory android.ModuleFactory
- hod android.HostOrDeviceSupported
- }{
- {
- moduleType: "genrule",
- factory: genrule.GenRuleFactory,
- },
- {
- moduleType: "cc_genrule",
- factory: cc.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule",
- factory: java.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule_host",
- factory: java.GenRuleFactoryHost,
- hod: android.HostSupported,
- },
- }
-
- bp := `
-soong_config_module_type {
- name: "my_genrule",
- module_type: "%s",
- config_namespace: "my_namespace",
- bool_variables: ["my_variable"],
- properties: ["cmd"],
-}
-
-my_genrule {
- name: "foo",
- out: ["foo.txt"],
- cmd: "echo 'no variable' > $(out)",
- soong_config_variables: {
- my_variable: {
- cmd: "echo 'with variable' > $(out)",
- },
- },
- bazel_module: { bp2build_available: true },
-}
-`
-
- for _, tc := range testCases {
- moduleAttrs := AttrNameToString{
- "cmd": `select({
- "//build/bazel/product_config/config_settings:my_namespace__my_variable": "echo 'with variable' > $(OUTS)",
- "//conditions:default": "echo 'no variable' > $(OUTS)",
- })`,
- "outs": `["foo.txt"]`,
- }
-
- expectedBazelTargets := []string{
- makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
- }
-
- t.Run(tc.moduleType, func(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) { android.RegisterSoongConfigModuleBuildComponents(ctx) },
- Bp2buildTestCase{
- Blueprint: fmt.Sprintf(bp, tc.moduleType),
- ModuleTypeUnderTest: tc.moduleType,
- ModuleTypeUnderTestFactory: tc.factory,
- ExpectedBazelTargets: expectedBazelTargets,
- })
- })
- }
-}
-
-func TestGenruleWithProductVariableConfiguredCmd(t *testing.T) {
- testCases := []struct {
- moduleType string
- factory android.ModuleFactory
- hod android.HostOrDeviceSupported
- }{
- {
- moduleType: "genrule",
- factory: genrule.GenRuleFactory,
- },
- {
- moduleType: "cc_genrule",
- factory: cc.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule",
- factory: java.GenRuleFactory,
- hod: android.DeviceSupported,
- },
- {
- moduleType: "java_genrule_host",
- factory: java.GenRuleFactoryHost,
- hod: android.HostSupported,
- },
- }
-
- bp := `
-
-%s {
- name: "foo",
- out: ["foo.txt"],
- cmd: "echo 'no variable' > $(out)",
- product_variables: {
- debuggable: {
- cmd: "echo 'with variable' > $(out)",
- },
- },
- bazel_module: { bp2build_available: true },
-}
-`
-
- for _, tc := range testCases {
- moduleAttrs := AttrNameToString{
- "cmd": `select({
- "//build/bazel/product_config/config_settings:debuggable": "echo 'with variable' > $(OUTS)",
- "//conditions:default": "echo 'no variable' > $(OUTS)",
- })`,
- "outs": `["foo.txt"]`,
- }
-
- expectedBazelTargets := []string{
- makeBazelTargetHostOrDevice("genrule", "foo", moduleAttrs, tc.hod),
- }
-
- t.Run(tc.moduleType, func(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) { android.RegisterSoongConfigModuleBuildComponents(ctx) },
- Bp2buildTestCase{
- Blueprint: fmt.Sprintf(bp, tc.moduleType),
- ModuleTypeUnderTest: tc.moduleType,
- ModuleTypeUnderTestFactory: tc.factory,
- ExpectedBazelTargets: expectedBazelTargets,
- })
- })
- }
-}
-
-func TestGenruleWithModulesInNamespaces(t *testing.T) {
- bp := `
-genrule {
- name: "mygenrule",
- cmd: "echo $(location //mynamespace:mymodule) > $(out)",
- srcs: ["//mynamespace:mymodule"],
- out: ["myout"],
-}
-`
- fs := map[string]string{
- "mynamespace/Android.bp": `soong_namespace {}`,
- "mynamespace/dir/Android.bp": `cc_binary {name: "mymodule"}`,
- }
- expectedBazelTargets := []string{
- MakeBazelTargetNoRestrictions("genrule", "mygenrule", AttrNameToString{
- // The fully qualified soong label is <namespace>:<module_name>
- // - here the prefix is mynamespace
- // The fully qualifed bazel label is <package>:<module_name>
- // - here the prefix is mynamespace/dir, since there is a BUILD file at each level of this FS path
- "cmd": `"echo $(location //mynamespace/dir:mymodule) > $(OUTS)"`,
- "outs": `["myout"]`,
- "srcs": `["//mynamespace/dir:mymodule"]`,
- }),
- }
-
- t.Run("genrule that uses module from a different namespace", func(t *testing.T) {
- runGenruleTestCase(t, Bp2buildTestCase{
- Blueprint: bp,
- Filesystem: fs,
- ModuleTypeUnderTest: "genrule",
- ModuleTypeUnderTestFactory: genrule.GenRuleFactory,
- ExpectedBazelTargets: expectedBazelTargets,
- })
- })
-
-}
diff --git a/bp2build/gensrcs_conversion_test.go b/bp2build/gensrcs_conversion_test.go
deleted file mode 100644
index e808340..0000000
--- a/bp2build/gensrcs_conversion_test.go
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2020 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 (
- "android/soong/android"
- "android/soong/genrule"
- "testing"
-)
-
-func TestGensrcs(t *testing.T) {
- testcases := []struct {
- name string
- bp string
- expectedBazelAttrs AttrNameToString
- }{
- {
- name: "gensrcs with common usage of properties",
- bp: `
- gensrcs {
- name: "foo",
- srcs: ["test/input.txt", ":external_files"],
- tool_files: ["program.py"],
- cmd: "$(location program.py) $(in) $(out) $(location foo/file.txt) $(location :external_files)",
- data: ["foo/file.txt", ":external_files"],
- output_extension: "out",
- bazel_module: { bp2build_available: true },
- }`,
- expectedBazelAttrs: AttrNameToString{
- "srcs": `[
- "test/input.txt",
- ":external_files__BP2BUILD__MISSING__DEP",
- ]`,
- "tools": `["program.py"]`,
- "output_extension": `"out"`,
- "cmd": `"$(location program.py) $(SRC) $(OUT) $(location foo/file.txt) $(location :external_files__BP2BUILD__MISSING__DEP)"`,
- "data": `[
- "foo/file.txt",
- ":external_files__BP2BUILD__MISSING__DEP",
- ]`,
- },
- },
- {
- name: "gensrcs with out_extension unset",
- bp: `
- gensrcs {
- name: "foo",
- srcs: ["input.txt"],
- cmd: "cat $(in) > $(out)",
- bazel_module: { bp2build_available: true },
- }`,
- expectedBazelAttrs: AttrNameToString{
- "srcs": `["input.txt"]`,
- "cmd": `"cat $(SRC) > $(OUT)"`,
- },
- },
- }
-
- for _, test := range testcases {
- expectedBazelTargets := []string{
- MakeBazelTargetNoRestrictions("gensrcs", "foo", test.expectedBazelAttrs),
- }
- t.Run(test.name, func(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {},
- Bp2buildTestCase{
- ModuleTypeUnderTest: "gensrcs",
- ModuleTypeUnderTestFactory: genrule.GenSrcsFactory,
- Blueprint: test.bp,
- ExpectedBazelTargets: expectedBazelTargets,
- })
- })
- }
-}
diff --git a/bp2build/go_conversion_test.go b/bp2build/go_conversion_test.go
deleted file mode 100644
index 2387641..0000000
--- a/bp2build/go_conversion_test.go
+++ /dev/null
@@ -1,208 +0,0 @@
-// Copyright 2023 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 (
- "testing"
-
- "github.com/google/blueprint/bootstrap"
-
- "android/soong/android"
-)
-
-func runGoTests(t *testing.T, tc Bp2buildTestCase) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
- tCtx := ctx.(*android.TestContext)
- bootstrap.RegisterGoModuleTypes(tCtx.Context.Context) // android.TestContext --> android.Context --> blueprint.Context
- }, tc)
-}
-
-func TestConvertGoPackage(t *testing.T) {
- bp := `
-bootstrap_go_package {
- name: "foo",
- pkgPath: "android/foo",
- deps: [
- "bar",
- ],
- srcs: [
- "foo1.go",
- "foo2.go",
- ],
- linux: {
- srcs: [
- "foo_linux.go",
- ],
- testSrcs: [
- "foo_linux_test.go",
- ],
- },
- darwin: {
- srcs: [
- "foo_darwin.go",
- ],
- testSrcs: [
- "foo_darwin_test.go",
- ],
- },
- testSrcs: [
- "foo1_test.go",
- "foo2_test.go",
- ],
-}
-`
- depBp := `
-bootstrap_go_package {
- name: "bar",
-}
-`
- t.Parallel()
- runGoTests(t, Bp2buildTestCase{
- Description: "Convert bootstrap_go_package to go_library",
- ModuleTypeUnderTest: "bootrstap_go_package",
- Blueprint: bp,
- Filesystem: map[string]string{
- "bar/Android.bp": depBp, // Put dep in Android.bp to reduce boilerplate in ExpectedBazelTargets
- },
- ExpectedBazelTargets: []string{makeBazelTargetHostOrDevice("go_library", "foo",
- AttrNameToString{
- "deps": `["//bar:bar"]`,
- "importpath": `"android/foo"`,
- "srcs": `[
- "foo1.go",
- "foo2.go",
- ] + select({
- "//build/bazel/platforms/os:darwin": ["foo_darwin.go"],
- "//build/bazel/platforms/os:linux_glibc": ["foo_linux.go"],
- "//conditions:default": [],
- })`,
- },
- android.HostSupported,
- ),
- makeBazelTargetHostOrDevice("go_test", "foo-test",
- AttrNameToString{
- "embed": `[":foo"]`,
- "srcs": `[
- "foo1_test.go",
- "foo2_test.go",
- ] + select({
- "//build/bazel/platforms/os:darwin": ["foo_darwin_test.go"],
- "//build/bazel/platforms/os:linux_glibc": ["foo_linux_test.go"],
- "//conditions:default": [],
- })`,
- },
- android.HostSupported,
- )},
- })
-}
-
-func TestConvertGoBinaryWithTransitiveDeps(t *testing.T) {
- bp := `
-blueprint_go_binary {
- name: "foo",
- srcs: ["main.go"],
- deps: ["bar"],
-}
-`
- depBp := `
-bootstrap_go_package {
- name: "bar",
- deps: ["baz"],
-}
-bootstrap_go_package {
- name: "baz",
-}
-`
- t.Parallel()
- runGoTests(t, Bp2buildTestCase{
- Description: "Convert blueprint_go_binary to go_binary",
- Blueprint: bp,
- Filesystem: map[string]string{
- "bar/Android.bp": depBp, // Put dep in Android.bp to reduce boilerplate in ExpectedBazelTargets
- },
- ExpectedBazelTargets: []string{makeBazelTargetHostOrDevice("go_binary", "foo",
- AttrNameToString{
- "deps": `[
- "//bar:bar",
- "//bar:baz",
- ]`,
- "srcs": `["main.go"]`,
- },
- android.HostSupported,
- )},
- })
-}
-
-func TestConvertGoBinaryWithTestSrcs(t *testing.T) {
- bp := `
-blueprint_go_binary {
- name: "foo",
- srcs: ["main.go"],
- testSrcs: ["main_test.go"],
-}
-`
- t.Parallel()
- runGoTests(t, Bp2buildTestCase{
- Description: "Convert blueprint_go_binary with testSrcs",
- Blueprint: bp,
- ExpectedBazelTargets: []string{
- makeBazelTargetHostOrDevice("go_binary", "foo",
- AttrNameToString{
- "deps": `[]`,
- "embed": `[":foo-source"]`,
- },
- android.HostSupported,
- ),
- makeBazelTargetHostOrDevice("go_source", "foo-source",
- AttrNameToString{
- "deps": `[]`,
- "srcs": `["main.go"]`,
- },
- android.HostSupported,
- ),
- makeBazelTargetHostOrDevice("go_test", "foo-test",
- AttrNameToString{
- "embed": `[":foo-source"]`,
- "srcs": `["main_test.go"]`,
- },
- android.HostSupported,
- ),
- },
- })
-}
-
-func TestConvertGoBinaryWithSrcInDifferentPackage(t *testing.T) {
- bp := `
-blueprint_go_binary {
- name: "foo",
- srcs: ["subdir/main.go"],
-}
-`
- t.Parallel()
- runGoTests(t, Bp2buildTestCase{
- Description: "Convert blueprint_go_binary with src in different package",
- Blueprint: bp,
- Filesystem: map[string]string{
- "subdir/Android.bp": "",
- },
- ExpectedBazelTargets: []string{makeBazelTargetHostOrDevice("go_binary", "foo",
- AttrNameToString{
- "deps": `[]`,
- "srcs": `["//subdir:main.go"]`,
- },
- android.HostSupported,
- )},
- })
-}
diff --git a/bp2build/java_binary_host_conversion_test.go b/bp2build/java_binary_host_conversion_test.go
deleted file mode 100644
index 39e55c4..0000000
--- a/bp2build/java_binary_host_conversion_test.go
+++ /dev/null
@@ -1,337 +0,0 @@
-// 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
-
-import (
- "testing"
-
- "android/soong/android"
- "android/soong/cc"
- "android/soong/java"
-)
-
-func runJavaBinaryHostTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "java_binary_host"
- (&tc).ModuleTypeUnderTestFactory = java.BinaryHostFactory
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("cc_library_host_shared", cc.LibraryHostSharedFactory)
- ctx.RegisterModuleType("java_library", java.LibraryFactory)
- ctx.RegisterModuleType("java_import_host", java.ImportFactory)
- }, tc)
-}
-
-var testFs = map[string]string{
- "test.mf": "Main-Class: com.android.test.MainClass",
- "other/Android.bp": `cc_library_host_shared {
- name: "jni-lib-1",
- stl: "none",
-}`,
-}
-
-func TestJavaBinaryHost(t *testing.T) {
- runJavaBinaryHostTestCase(t, Bp2buildTestCase{
- Description: "java_binary_host with srcs, exclude_srcs, jni_libs, javacflags, and manifest.",
- Filesystem: testFs,
- Blueprint: `java_binary_host {
- name: "java-binary-host-1",
- srcs: ["a.java", "b.java"],
- exclude_srcs: ["b.java"],
- manifest: "test.mf",
- jni_libs: ["jni-lib-1"],
- javacflags: ["-Xdoclint:all/protected"],
- bazel_module: { bp2build_available: true },
- java_version: "8",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-binary-host-1_lib", AttrNameToString{
- "srcs": `["a.java"]`,
- "deps": `["//other:jni-lib-1"]`,
- "java_version": `"8"`,
- "javacopts": `["-Xdoclint:all/protected"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("java_binary", "java-binary-host-1", AttrNameToString{
- "main_class": `"com.android.test.MainClass"`,
- "jvm_flags": `["-Djava.library.path=$${RUNPATH}other/jni-lib-1"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- "runtime_deps": `[":java-binary-host-1_lib"]`,
- }),
- },
- })
-}
-
-func TestJavaBinaryHostRuntimeDeps(t *testing.T) {
- runJavaBinaryHostTestCase(t, Bp2buildTestCase{
- Description: "java_binary_host with srcs, exclude_srcs, jni_libs, javacflags, and manifest.",
- Filesystem: testFs,
- Blueprint: `java_binary_host {
- name: "java-binary-host-1",
- static_libs: ["java-dep-1"],
- manifest: "test.mf",
- bazel_module: { bp2build_available: true },
-}
-
-java_library {
- name: "java-dep-1",
- srcs: ["a.java"],
- bazel_module: { bp2build_available: false },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_binary", "java-binary-host-1", AttrNameToString{
- "main_class": `"com.android.test.MainClass"`,
- "runtime_deps": `[":java-dep-1"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestJavaBinaryHostLibs(t *testing.T) {
- runJavaBinaryHostTestCase(t, Bp2buildTestCase{
- Description: "java_binary_host with srcs, libs.",
- Filesystem: testFs,
- Blueprint: `java_binary_host {
- name: "java-binary-host-libs",
- libs: ["java-lib-dep-1"],
- manifest: "test.mf",
- srcs: ["a.java"],
-}
-
-java_import_host{
- name: "java-lib-dep-1",
- jars: ["foo.jar"],
- bazel_module: { bp2build_available: false },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-binary-host-libs_lib", AttrNameToString{
- "srcs": `["a.java"]`,
- "deps": `[":java-lib-dep-1-neverlink"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("java_binary", "java-binary-host-libs", AttrNameToString{
- "main_class": `"com.android.test.MainClass"`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- "runtime_deps": `[":java-binary-host-libs_lib"]`,
- }),
- },
- })
-}
-
-func TestJavaBinaryHostKotlinSrcs(t *testing.T) {
- runJavaBinaryHostTestCase(t, Bp2buildTestCase{
- Description: "java_binary_host with srcs, libs.",
- Filesystem: testFs,
- Blueprint: `java_binary_host {
- name: "java-binary-host",
- manifest: "test.mf",
- srcs: ["a.java", "b.kt"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("kt_jvm_library", "java-binary-host_lib", AttrNameToString{
- "srcs": `[
- "a.java",
- "b.kt",
- ]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("java_binary", "java-binary-host", AttrNameToString{
- "main_class": `"com.android.test.MainClass"`,
- "runtime_deps": `[":java-binary-host_lib"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestJavaBinaryHostKotlinCommonSrcs(t *testing.T) {
- runJavaBinaryHostTestCase(t, Bp2buildTestCase{
- Description: "java_binary_host with common_srcs",
- Filesystem: testFs,
- Blueprint: `java_binary_host {
- name: "java-binary-host",
- manifest: "test.mf",
- srcs: ["a.java"],
- common_srcs: ["b.kt"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("kt_jvm_library", "java-binary-host_lib", AttrNameToString{
- "srcs": `["a.java"]`,
- "common_srcs": `["b.kt"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("java_binary", "java-binary-host", AttrNameToString{
- "main_class": `"com.android.test.MainClass"`,
- "runtime_deps": `[":java-binary-host_lib"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestJavaBinaryHostKotlinWithResourceDir(t *testing.T) {
- runJavaBinaryHostTestCase(t, Bp2buildTestCase{
- Description: "java_binary_host with srcs, libs, resource dir .",
- Filesystem: map[string]string{
- "test.mf": "Main-Class: com.android.test.MainClass",
- "res/a.res": "",
- "res/dir1/b.res": "",
- },
- Blueprint: `java_binary_host {
- name: "java-binary-host",
- manifest: "test.mf",
- srcs: ["a.java", "b.kt"],
- java_resource_dirs: ["res"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("kt_jvm_library", "java-binary-host_lib", AttrNameToString{
- "srcs": `[
- "a.java",
- "b.kt",
- ]`,
- "resources": `[
- "res/a.res",
- "res/dir1/b.res",
- ]`,
- "resource_strip_prefix": `"res"`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("java_binary", "java-binary-host", AttrNameToString{
- "main_class": `"com.android.test.MainClass"`,
- "runtime_deps": `[":java-binary-host_lib"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestJavaBinaryHostKotlinWithResources(t *testing.T) {
- runJavaBinaryHostTestCase(t, Bp2buildTestCase{
- Description: "java_binary_host with srcs, libs, resources.",
- Filesystem: map[string]string{
- "adir/test.mf": "Main-Class: com.android.test.MainClass",
- "adir/res/a.res": "",
- "adir/res/b.res": "",
- "adir/Android.bp": `java_binary_host {
- name: "java-binary-host",
- manifest: "test.mf",
- srcs: ["a.java", "b.kt"],
- java_resources: ["res/a.res", "res/b.res"],
- bazel_module: { bp2build_available: true },
-}
-`,
- },
- Dir: "adir",
- Blueprint: "",
- ExpectedBazelTargets: []string{
- MakeBazelTarget("kt_jvm_library", "java-binary-host_lib", AttrNameToString{
- "srcs": `[
- "a.java",
- "b.kt",
- ]`,
- "resources": `[
- "res/a.res",
- "res/b.res",
- ]`,
- "resource_strip_prefix": `"adir"`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("java_binary", "java-binary-host", AttrNameToString{
- "main_class": `"com.android.test.MainClass"`,
- "runtime_deps": `[":java-binary-host_lib"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestJavaBinaryHostKotlinCflags(t *testing.T) {
- runJavaBinaryHostTestCase(t, Bp2buildTestCase{
- Description: "java_binary_host with kotlincflags",
- Filesystem: testFs,
- Blueprint: `java_binary_host {
- name: "java-binary-host",
- manifest: "test.mf",
- srcs: ["a.kt"],
- kotlincflags: ["-flag1", "-flag2"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("kt_jvm_library", "java-binary-host_lib", AttrNameToString{
- "srcs": `["a.kt"]`,
- "kotlincflags": `[
- "-flag1",
- "-flag2",
- ]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("java_binary", "java-binary-host", AttrNameToString{
- "main_class": `"com.android.test.MainClass"`,
- "runtime_deps": `[":java-binary-host_lib"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
diff --git a/bp2build/java_host_for_device_conversion_test.go b/bp2build/java_host_for_device_conversion_test.go
deleted file mode 100644
index 1fa7126..0000000
--- a/bp2build/java_host_for_device_conversion_test.go
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright 2023 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 (
- "testing"
-
- "android/soong/android"
- "android/soong/java"
-)
-
-func runJavaHostForDeviceTestCaseWithRegistrationCtxFunc(t *testing.T, tc Bp2buildTestCase, registrationCtxFunc func(ctx android.RegistrationContext)) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "java_host_for_device"
- (&tc).ModuleTypeUnderTestFactory = java.HostForDeviceFactory
- RunBp2BuildTestCase(t, registrationCtxFunc, tc)
-}
-
-func runJavaHostForDeviceTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- runJavaHostForDeviceTestCaseWithRegistrationCtxFunc(t, tc, func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("java_library", java.LibraryFactory)
- })
-}
-
-func TestJavaHostForDevice(t *testing.T) {
- runJavaHostForDeviceTestCase(t, Bp2buildTestCase{
- Description: "java_host_for_device test",
- Blueprint: `java_host_for_device {
- name: "java-lib-1",
- libs: ["java-lib-2"],
- bazel_module: { bp2build_available: true },
-}
-
-java_library {
- name: "java-lib-2",
- srcs: ["b.java"],
- bazel_module: { bp2build_available: true },
- sdk_version: "current",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_host_for_device", "java-lib-1", AttrNameToString{
- "exports": `[":java-lib-2"]`,
- }),
- MakeNeverlinkDuplicateTargetWithAttrs("java_library", "java-lib-1", AttrNameToString{
- "sdk_version": `"none"`,
- }),
- MakeBazelTarget("java_library", "java-lib-2", AttrNameToString{
- "srcs": `["b.java"]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-2"),
- },
- })
-}
diff --git a/bp2build/java_import_conversion_test.go b/bp2build/java_import_conversion_test.go
deleted file mode 100644
index 5661620..0000000
--- a/bp2build/java_import_conversion_test.go
+++ /dev/null
@@ -1,122 +0,0 @@
-// 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 (
- "android/soong/android"
- "android/soong/java"
-
- "testing"
-)
-
-func runJavaImportTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, registerJavaImportModuleTypes, tc)
-}
-
-func registerJavaImportModuleTypes(ctx android.RegistrationContext) {
-}
-
-func TestJavaImportMinimal(t *testing.T) {
- runJavaImportTestCase(t, Bp2buildTestCase{
- Description: "Java import - simple example",
- ModuleTypeUnderTest: "java_import",
- ModuleTypeUnderTestFactory: java.ImportFactory,
- Filesystem: map[string]string{
- "import.jar": "",
- },
- Blueprint: `
-java_import {
- name: "example_import",
- jars: ["import.jar"],
- bazel_module: { bp2build_available: true },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_import", "example_import", AttrNameToString{
- "jars": `["import.jar"]`,
- }),
- MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
- "exports": `[":example_import"]`,
- "neverlink": `True`,
- "sdk_version": `"none"`,
- }),
- }})
-}
-
-func TestJavaImportArchVariant(t *testing.T) {
- runJavaImportTestCase(t, Bp2buildTestCase{
- Description: "Java import - simple example",
- ModuleTypeUnderTest: "java_import",
- ModuleTypeUnderTestFactory: java.ImportFactory,
- Filesystem: map[string]string{
- "import.jar": "",
- },
- Blueprint: `
-java_import {
- name: "example_import",
- target: {
- android: {
- jars: ["android.jar"],
- },
- linux_glibc: {
- jars: ["linux.jar"],
- },
- },
- bazel_module: { bp2build_available: true },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_import", "example_import", AttrNameToString{
- "jars": `select({
- "//build/bazel/platforms/os:android": ["android.jar"],
- "//build/bazel/platforms/os:linux_glibc": ["linux.jar"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
- "exports": `[":example_import"]`,
- "neverlink": `True`,
- "sdk_version": `"none"`,
- }),
- }})
-}
-
-func TestJavaImportHost(t *testing.T) {
- runJavaImportTestCase(t, Bp2buildTestCase{
- Description: "Java import host- simple example",
- ModuleTypeUnderTest: "java_import_host",
- ModuleTypeUnderTestFactory: java.ImportFactory,
- Filesystem: map[string]string{
- "import.jar": "",
- },
- Blueprint: `
-java_import_host {
- name: "example_import",
- jars: ["import.jar"],
- bazel_module: { bp2build_available: true },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_import", "example_import", AttrNameToString{
- "jars": `["import.jar"]`,
- }),
- MakeBazelTarget("java_library", "example_import-neverlink", AttrNameToString{
- "exports": `[":example_import"]`,
- "neverlink": `True`,
- "sdk_version": `"none"`,
- }),
- }})
-}
diff --git a/bp2build/java_library_conversion_test.go b/bp2build/java_library_conversion_test.go
deleted file mode 100644
index 512c1e1..0000000
--- a/bp2build/java_library_conversion_test.go
+++ /dev/null
@@ -1,1060 +0,0 @@
-// 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
-
-import (
- "fmt"
- "testing"
-
- "android/soong/android"
- "android/soong/java"
-)
-
-func runJavaLibraryTestCaseWithRegistrationCtxFunc(t *testing.T, tc Bp2buildTestCase, registrationCtxFunc func(ctx android.RegistrationContext)) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "java_library"
- (&tc).ModuleTypeUnderTestFactory = java.LibraryFactory
- RunBp2BuildTestCase(t, registrationCtxFunc, tc)
-}
-
-func runJavaLibraryTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- runJavaLibraryTestCaseWithRegistrationCtxFunc(t, tc, func(ctx android.RegistrationContext) {})
-}
-
-func TestJavaLibrary(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Description: "java_library with srcs, exclude_srcs and libs",
- Blueprint: `java_library {
- name: "java-lib-1",
- srcs: ["a.java", "b.java"],
- exclude_srcs: ["b.java"],
- libs: ["java-lib-2"],
- sdk_version: "current",
- bazel_module: { bp2build_available: true },
-}
-
-java_library {
- name: "java-lib-2",
- srcs: ["b.java"],
- sdk_version: "current",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "srcs": `["a.java"]`,
- "deps": `[":java-lib-2-neverlink"]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- MakeBazelTarget("java_library", "java-lib-2", AttrNameToString{
- "srcs": `["b.java"]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-2"),
- },
- })
-}
-
-func TestJavaLibraryConvertsStaticLibsToDepsAndExports(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Blueprint: `java_library {
- name: "java-lib-1",
- srcs: ["a.java"],
- libs: ["java-lib-2"],
- static_libs: ["java-lib-3"],
- sdk_version: "current",
- bazel_module: { bp2build_available: true },
-}
-
-java_library {
- name: "java-lib-2",
- srcs: ["b.java"],
- sdk_version: "current",
- bazel_module: { bp2build_available: false },
-}
-
-java_library {
- name: "java-lib-3",
- srcs: ["c.java"],
- sdk_version: "current",
- bazel_module: { bp2build_available: false },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "srcs": `["a.java"]`,
- "deps": `[
- ":java-lib-2-neverlink",
- ":java-lib-3",
- ]`,
- "exports": `[":java-lib-3"]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- },
- })
-}
-
-func TestJavaLibraryConvertsStaticLibsToExportsIfNoSrcs(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Blueprint: `java_library {
- name: "java-lib-1",
- static_libs: ["java-lib-2"],
- sdk_version: "current",
- bazel_module: { bp2build_available: true },
-}
-
-java_library {
- name: "java-lib-2",
- srcs: ["a.java"],
- bazel_module: { bp2build_available: false },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "exports": `[":java-lib-2"]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- },
- })
-}
-
-func TestJavaLibraryFailsToConvertNoSdkVersion(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Blueprint: `
-java_library {
- name: "lib",
- bazel_module: { bp2build_available: true },
-}
-`,
- ExpectedBazelTargets: []string{}, // no targets expected because sdk_version is not set
- })
-}
-
-func TestJavaLibraryFailsToConvertLibsWithNoSrcs(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- ExpectedErr: fmt.Errorf("Module has direct dependencies but no sources. Bazel will not allow this."),
- Blueprint: `java_library {
- name: "java-lib-1",
- libs: ["java-lib-2"],
- sdk_version: "current",
- bazel_module: { bp2build_available: true },
-}
-
-java_library {
- name: "java-lib-2",
- srcs: ["a.java"],
- sdk_version: "current",
- bazel_module: { bp2build_available: false },
-}`,
- ExpectedBazelTargets: []string{},
- })
-}
-
-func TestJavaLibraryPlugins(t *testing.T) {
- runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{
- Blueprint: `java_library {
- name: "java-lib-1",
- plugins: ["java-plugin-1"],
- sdk_version: "current",
- bazel_module: { bp2build_available: true },
-}
-
-java_plugin {
- name: "java-plugin-1",
- srcs: ["a.java"],
- bazel_module: { bp2build_available: false },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "plugins": `[":java-plugin-1"]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- },
- }, func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("java_plugin", java.PluginFactory)
- })
-}
-
-func TestJavaLibraryJavaVersion(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Blueprint: `java_library {
- name: "java-lib-1",
- srcs: ["a.java"],
- java_version: "11",
- sdk_version: "current",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "srcs": `["a.java"]`,
- "java_version": `"11"`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTargetWithAttrs(
- "java_library",
- "java-lib-1",
- AttrNameToString{
- "java_version": `"11"`,
- "sdk_version": `"current"`,
- }),
- },
- })
-}
-
-func TestJavaLibraryErrorproneEnabledManually(t *testing.T) {
- runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{
- Blueprint: `java_library {
- name: "java-lib-1",
- srcs: ["a.java"],
- javacflags: ["-Xsuper-fast"],
- sdk_version: "current",
- errorprone: {
- enabled: true,
- javacflags: ["-Xep:SpeedLimit:OFF"],
- extra_check_modules: ["plugin2"],
- },
-}
-java_plugin {
- name: "plugin2",
- srcs: ["a.java"],
- bazel_module: { bp2build_available: false },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "javacopts": `[
- "-Xsuper-fast",
- "-Xep:SpeedLimit:OFF",
- ]`,
- "plugins": `[":plugin2"]`,
- "srcs": `["a.java"]`,
- "errorprone_force_enable": `True`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- },
- }, func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("java_plugin", java.PluginFactory)
- })
-}
-
-func TestJavaLibraryErrorproneJavacflagsErrorproneDisabledByDefault(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Blueprint: `java_library {
- name: "java-lib-1",
- srcs: ["a.java"],
- sdk_version: "current",
- javacflags: ["-Xsuper-fast"],
- errorprone: {
- javacflags: ["-Xep:SpeedLimit:OFF"],
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "javacopts": `["-Xsuper-fast"]`,
- "srcs": `["a.java"]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- },
- })
-}
-
-func TestJavaLibraryErrorproneDisabledManually(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Blueprint: `java_library {
- name: "java-lib-1",
- srcs: ["a.java"],
- javacflags: ["-Xsuper-fast"],
- sdk_version: "current",
- errorprone: {
- enabled: false,
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "javacopts": `[
- "-Xsuper-fast",
- "-XepDisableAllChecks",
- ]`,
- "srcs": `["a.java"]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- },
- })
-}
-
-func TestJavaLibraryLogTags(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Description: "Java library - logtags creates separate dependency",
- ModuleTypeUnderTest: "java_library",
- ModuleTypeUnderTestFactory: java.LibraryFactory,
- Blueprint: `java_library {
- name: "example_lib",
- srcs: [
- "a.java",
- "b.java",
- "a.logtag",
- "b.logtag",
- ],
- sdk_version: "current",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("event_log_tags", "example_lib_logtags", AttrNameToString{
- "srcs": `[
- "a.logtag",
- "b.logtag",
- ]`,
- }),
- MakeBazelTarget("java_library", "example_lib", AttrNameToString{
- "srcs": `[
- "a.java",
- "b.java",
- ":example_lib_logtags",
- ]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "example_lib"),
- }})
-}
-
-func TestJavaLibraryResources(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Dir: "adir",
- Filesystem: map[string]string{
- "adir/res/a.res": "",
- "adir/res/b.res": "",
- "adir/res/dir1/b.res": "",
- "adir/Android.bp": `java_library {
- name: "java-lib-1",
- java_resources: ["res/a.res", "res/b.res"],
- sdk_version: "current",
- bazel_module: { bp2build_available: true },
-}`,
- },
- Blueprint: "",
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "resources": `[
- "res/a.res",
- "res/b.res",
- ]`,
- "resource_strip_prefix": `"adir"`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- },
- })
-}
-
-func TestJavaLibraryResourceDirs(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Filesystem: map[string]string{
- "res/a.res": "",
- "res/b.res": "",
- "res/dir1/b.res": "",
- },
- Blueprint: `java_library {
- name: "java-lib-1",
- java_resource_dirs: ["res"],
- sdk_version: "current",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "resource_strip_prefix": `"res"`,
- "resources": `[
- "res/a.res",
- "res/b.res",
- "res/dir1/b.res",
- ]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- },
- })
-}
-
-func TestJavaLibraryResourcesExcludeDir(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Filesystem: map[string]string{
- "res/a.res": "",
- "res/exclude/b.res": "",
- },
- Blueprint: `java_library {
- name: "java-lib-1",
- java_resource_dirs: ["res"],
- sdk_version: "current",
- exclude_java_resource_dirs: ["res/exclude"],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "resource_strip_prefix": `"res"`,
- "resources": `["res/a.res"]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- },
- })
-}
-
-func TestJavaLibraryResourcesExcludeFile(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Filesystem: map[string]string{
- "res/a.res": "",
- "res/dir1/b.res": "",
- "res/dir1/exclude.res": "",
- },
- Blueprint: `java_library {
- name: "java-lib-1",
- java_resource_dirs: ["res"],
- sdk_version: "current",
- exclude_java_resources: ["res/dir1/exclude.res"],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "resource_strip_prefix": `"res"`,
- "resources": `[
- "res/a.res",
- "res/dir1/b.res",
- ]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- },
- })
-}
-
-func TestJavaLibraryResourcesWithMultipleDirs(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Filesystem: map[string]string{
- "res/a.res": "",
- "res1/b.res": "",
- "res2/b.java": "",
- },
- Blueprint: `java_library {
- name: "java-lib-1",
- java_resource_dirs: ["res", "res1", "res2"],
- sdk_version: "current",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_resources", "java-lib-1_resource_dir_res1", AttrNameToString{
- "resource_strip_prefix": `"res1"`,
- "resources": `["res1/b.res"]`,
- }),
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "additional_resources": `["java-lib-1_resource_dir_res1"]`,
- "resources": `["res/a.res"]`,
- "resource_strip_prefix": `"res"`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- },
- })
-}
-
-func TestJavaLibraryJavaResourcesAndResourceDirs(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Filesystem: map[string]string{
- "resdir/a.res": "",
- },
- Blueprint: `java_library {
- name: "java-lib-1",
- java_resources: ["res1", "res2"],
- java_resource_dirs: ["resdir"],
- sdk_version: "current",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_resources", "java-lib-1_resource_dir_resdir", AttrNameToString{
- "resource_strip_prefix": `"resdir"`,
- "resources": `["resdir/a.res"]`,
- }),
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "additional_resources": `["java-lib-1_resource_dir_resdir"]`,
- "resource_strip_prefix": `"."`,
- "resources": `[
- "res1",
- "res2",
- ]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- },
- })
-}
-
-func TestJavaLibraryAidl(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Description: "Java library - aidl creates separate dependency",
- ModuleTypeUnderTest: "java_library",
- ModuleTypeUnderTestFactory: java.LibraryFactory,
- Blueprint: `java_library {
- name: "example_lib",
- srcs: [
- "a.java",
- "b.java",
- "a.aidl",
- "b.aidl",
- ],
- bazel_module: { bp2build_available: true },
- sdk_version: "current",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("aidl_library", "example_lib_aidl_library", AttrNameToString{
- "srcs": `[
- "a.aidl",
- "b.aidl",
- ]`,
- }),
- MakeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{
- "deps": `[":example_lib_aidl_library"]`,
- }),
- MakeBazelTarget("java_library", "example_lib", AttrNameToString{
- "deps": `[":example_lib_java_aidl_library"]`,
- "exports": `[":example_lib_java_aidl_library"]`,
- "srcs": `[
- "a.java",
- "b.java",
- ]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "example_lib"),
- }})
-}
-
-func TestJavaLibraryAidlSrcsNoFileGroup(t *testing.T) {
- runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{
- Description: "Java library - aidl filegroup is parsed",
- ModuleTypeUnderTest: "java_library",
- ModuleTypeUnderTestFactory: java.LibraryFactory,
- Blueprint: `
-java_library {
- name: "example_lib",
- srcs: [
- "a.java",
- "b.aidl",
- ],
- sdk_version: "current",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("aidl_library", "example_lib_aidl_library", AttrNameToString{
- "srcs": `["b.aidl"]`,
- }),
- MakeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{
- "deps": `[":example_lib_aidl_library"]`,
- }),
- MakeBazelTarget("java_library", "example_lib", AttrNameToString{
- "deps": `[":example_lib_java_aidl_library"]`,
- "exports": `[":example_lib_java_aidl_library"]`,
- "srcs": `["a.java"]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "example_lib"),
- },
- }, func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- })
-}
-
-func TestJavaLibraryAidlFilegroup(t *testing.T) {
- runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{
- Description: "Java library - aidl filegroup is parsed",
- ModuleTypeUnderTest: "java_library",
- ModuleTypeUnderTestFactory: java.LibraryFactory,
- Blueprint: `
-filegroup {
- name: "random_other_files",
- srcs: [
- "a.java",
- "b.java",
- ],
-}
-filegroup {
- name: "aidl_files",
- srcs: [
- "a.aidl",
- "b.aidl",
- ],
-}
-java_library {
- name: "example_lib",
- srcs: [
- "a.java",
- "b.java",
- ":aidl_files",
- ":random_other_files",
- ],
- sdk_version: "current",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("aidl_library", "aidl_files", AttrNameToString{
- "srcs": `[
- "a.aidl",
- "b.aidl",
- ]`,
- "tags": `["apex_available=//apex_available:anyapex"]`,
- }),
- MakeBazelTarget("java_aidl_library", "example_lib_java_aidl_library", AttrNameToString{
- "deps": `[":aidl_files"]`,
- }),
- MakeBazelTarget("java_library", "example_lib", AttrNameToString{
- "deps": `[":example_lib_java_aidl_library"]`,
- "exports": `[":example_lib_java_aidl_library"]`,
- "srcs": `[
- "a.java",
- "b.java",
- ":random_other_files",
- ]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "example_lib"),
- MakeBazelTargetNoRestrictions("filegroup", "random_other_files", AttrNameToString{
- "srcs": `[
- "a.java",
- "b.java",
- ]`,
- }),
- },
- }, func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- })
-}
-
-func TestJavaLibraryAidlNonAdjacentAidlFilegroup(t *testing.T) {
- runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{
- Description: "java_library with non adjacent aidl filegroup",
- ModuleTypeUnderTest: "java_library",
- ModuleTypeUnderTestFactory: java.LibraryFactory,
- Filesystem: map[string]string{
- "path/to/A/Android.bp": `
-filegroup {
- name: "A_aidl",
- srcs: ["aidl/A.aidl"],
- path: "aidl",
-}`,
- },
- Blueprint: `
-java_library {
- name: "foo",
- srcs: [
- ":A_aidl",
- ],
- sdk_version: "current",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_aidl_library", "foo_java_aidl_library", AttrNameToString{
- "deps": `["//path/to/A:A_aidl"]`,
- }),
- MakeBazelTarget("java_library", "foo", AttrNameToString{
- "exports": `[":foo_java_aidl_library"]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "foo"),
- },
- }, func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- })
-}
-
-func TestConvertArmNeonVariant(t *testing.T) {
- t.Helper()
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
- Description: "Android Library - simple arch feature",
- ModuleTypeUnderTest: "android_library",
- ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
- Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
-android_library {
- name: "TestLib",
- manifest: "manifest/AndroidManifest.xml",
- srcs: ["lib.java"],
- sdk_version: "current",
- arch: {
- arm: {
- neon: {
- srcs: ["arm_neon.java"],
- },
- },
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget(
- "android_library",
- "TestLib",
- AttrNameToString{
- "srcs": `["lib.java"] + select({
- "//build/bazel/platforms/arch/variants:arm-neon": ["arm_neon.java"],
- "//conditions:default": [],
- })`,
- "manifest": `"manifest/AndroidManifest.xml"`,
- "resource_files": `[]`,
- "sdk_version": `"current"`, // use as default
- }),
- MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
- }})
-}
-
-func TestConvertMultipleArchFeatures(t *testing.T) {
- t.Helper()
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
- Description: "Android Library - multiple arch features",
- ModuleTypeUnderTest: "android_library",
- ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
- Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
-android_library {
- name: "TestLib",
- manifest: "manifest/AndroidManifest.xml",
- srcs: ["lib.java"],
- sdk_version: "current",
- arch: {
- x86: {
- ssse3: {
- srcs: ["ssse3.java"],
- },
- sse4_1: {
- srcs: ["sse4_1.java"],
- },
- },
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget(
- "android_library",
- "TestLib",
- AttrNameToString{
- "srcs": `["lib.java"] + select({
- "//build/bazel/platforms/arch/variants:x86-sse4_1": ["sse4_1.java"],
- "//build/bazel/platforms/arch/variants:x86-sse4_1-ssse3": [
- "sse4_1.java",
- "ssse3.java",
- ],
- "//build/bazel/platforms/arch/variants:x86-ssse3": ["ssse3.java"],
- "//conditions:default": [],
- })`,
- "manifest": `"manifest/AndroidManifest.xml"`,
- "resource_files": `[]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
- }})
-}
-
-func TestConvertExcludeSrcsArchFeature(t *testing.T) {
- t.Helper()
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
- Description: "Android Library - exclude_srcs with arch feature",
- ModuleTypeUnderTest: "android_library",
- ModuleTypeUnderTestFactory: java.AndroidLibraryFactory,
- Blueprint: simpleModuleDoNotConvertBp2build("android_library", "static_lib_dep") + `
-android_library {
- name: "TestLib",
- manifest: "manifest/AndroidManifest.xml",
- srcs: ["lib.java"],
- arch: {
- arm: {
- srcs: ["arm_non_neon.java"],
- neon: {
- exclude_srcs: ["arm_non_neon.java"],
- },
- },
- },
- sdk_version: "current",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget(
- "android_library",
- "TestLib",
- AttrNameToString{
- "srcs": `["lib.java"] + select({
- "//build/bazel/platforms/arch/variants:arm-neon": [],
- "//build/bazel/platforms/arch:arm": ["arm_non_neon.java"],
- "//conditions:default": [],
- })`,
- "manifest": `"manifest/AndroidManifest.xml"`,
- "resource_files": `[]`,
- "sdk_version": `"current"`, // use as default
- }),
- MakeNeverlinkDuplicateTarget("android_library", "TestLib"),
- }})
-}
-
-func TestJavaLibraryKotlinSrcs(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Description: "java_library with kotlin srcs",
- Blueprint: `java_library {
- name: "java-lib-1",
- srcs: ["a.java", "b.java", "c.kt"],
- bazel_module: { bp2build_available: true },
- sdk_version: "current",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("kt_jvm_library", "java-lib-1", AttrNameToString{
- "srcs": `[
- "a.java",
- "b.java",
- "c.kt",
- ]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("kt_jvm_library", "java-lib-1"),
- },
- })
-}
-
-func TestJavaLibraryKotlincflags(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Description: "java_library with kotlincfalgs",
- Blueprint: `java_library {
- name: "java-lib-1",
- srcs: [ "a.kt"],
- kotlincflags: ["-flag1", "-flag2"],
- bazel_module: { bp2build_available: true },
- sdk_version: "current",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("kt_jvm_library", "java-lib-1", AttrNameToString{
- "srcs": `["a.kt"]`,
- "kotlincflags": `[
- "-flag1",
- "-flag2",
- ]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("kt_jvm_library", "java-lib-1"),
- },
- })
-}
-
-func TestJavaLibraryKotlinCommonSrcs(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Description: "java_library with kotlin common_srcs",
- Blueprint: `java_library {
- name: "java-lib-1",
- srcs: ["a.java", "b.java"],
- common_srcs: ["c.kt"],
- bazel_module: { bp2build_available: true },
- sdk_version: "current",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("kt_jvm_library", "java-lib-1", AttrNameToString{
- "srcs": `[
- "a.java",
- "b.java",
- ]`,
- "common_srcs": `["c.kt"]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("kt_jvm_library", "java-lib-1"),
- },
- })
-}
-
-func TestJavaLibraryArchVariantDeps(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Description: "java_library with arch variant libs",
- Blueprint: `java_library {
- name: "java-lib-1",
- srcs: ["a.java"],
- libs: ["java-lib-2"],
- sdk_version: "current",
- target: {
- android: {
- libs: ["java-lib-3"],
- static_libs: ["java-lib-4"],
- },
- },
- bazel_module: { bp2build_available: true },
-}
-
- java_library{
- name: "java-lib-2",
- bazel_module: { bp2build_available: false },
-}
-
- java_library{
- name: "java-lib-3",
- bazel_module: { bp2build_available: false },
-}
-
- java_library{
- name: "java-lib-4",
- bazel_module: { bp2build_available: false },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "srcs": `["a.java"]`,
- "exports": `select({
- "//build/bazel/platforms/os:android": [":java-lib-4"],
- "//conditions:default": [],
- })`,
- "deps": `[":java-lib-2-neverlink"] + select({
- "//build/bazel/platforms/os:android": [
- ":java-lib-3-neverlink",
- ":java-lib-4",
- ],
- "//conditions:default": [],
- })`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- },
- })
-}
-
-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"],
- sdk_version: "current",
- 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"],
- })`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- },
- })
-}
-
-func TestJavaLibraryJavaResourcesSingleFilegroup(t *testing.T) {
- runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{
- Filesystem: map[string]string{
- "res/a.res": "",
- "res/b.res": "",
- "res/dir1/b.res": "",
- },
- Description: "java_library",
- Blueprint: `java_library {
- name: "java-lib-1",
- srcs: ["a.java"],
- sdk_version: "current",
- java_resources: [":filegroup1"],
- bazel_module: { bp2build_available: true },
-}
-
-filegroup {
- name: "filegroup1",
- path: "foo",
- srcs: ["foo/a", "foo/b"],
-}
-
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "srcs": `["a.java"]`,
- "resources": `[":filegroup1"]`,
- "resource_strip_prefix": `"foo"`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- MakeBazelTargetNoRestrictions("filegroup", "filegroup1", AttrNameToString{
- "srcs": `[
- "foo/a",
- "foo/b",
- ]`}),
- },
- }, func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- })
-}
-
-func TestJavaLibraryJavaResourcesMultipleFilegroup(t *testing.T) {
- runJavaLibraryTestCaseWithRegistrationCtxFunc(t, Bp2buildTestCase{
- Filesystem: map[string]string{
- "a.res": "",
- },
- Description: "with java_resources that has multiple filegroups",
- Blueprint: `java_library {
- name: "java-lib-1",
- srcs: ["a.java"],
- java_resources: ["a.res", ":filegroup1", ":filegroup2"],
- sdk_version: "current",
- bazel_module: { bp2build_available: true },
-}
-
-filegroup {
- name: "filegroup1",
- path: "foo",
- srcs: ["foo/a"],
-}
-
-filegroup {
- name: "filegroup2",
- path: "bar",
- srcs: ["bar/a"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_resources", "java-lib-1_filegroup_resources_filegroup1", AttrNameToString{
- "resource_strip_prefix": `"foo"`,
- "resources": `[":filegroup1"]`,
- }),
- MakeBazelTarget("java_resources", "java-lib-1_filegroup_resources_filegroup2", AttrNameToString{
- "resource_strip_prefix": `"bar"`,
- "resources": `[":filegroup2"]`,
- }),
- MakeBazelTarget("java_library", "java-lib-1", AttrNameToString{
- "srcs": `["a.java"]`,
- "resources": `["a.res"]`,
- "resource_strip_prefix": `"."`,
- "additional_resources": `[
- "java-lib-1_filegroup_resources_filegroup1",
- "java-lib-1_filegroup_resources_filegroup2",
- ]`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-lib-1"),
- MakeBazelTargetNoRestrictions("filegroup", "filegroup1", AttrNameToString{
- "srcs": `["foo/a"]`}),
- MakeBazelTargetNoRestrictions("filegroup", "filegroup2", AttrNameToString{
- "srcs": `["bar/a"]`}),
- },
- }, func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("filegroup", android.FileGroupFactory)
- })
-}
-
-func TestJavaSdkVersionCorePlatformDoesNotConvert(t *testing.T) {
- runJavaLibraryTestCase(t, Bp2buildTestCase{
- Blueprint: `java_library {
- name: "java-lib-1",
- sdk_version: "core_platform",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{},
- })
-}
diff --git a/bp2build/java_library_host_conversion_test.go b/bp2build/java_library_host_conversion_test.go
deleted file mode 100644
index 9e47b09..0000000
--- a/bp2build/java_library_host_conversion_test.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// 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
-
-import (
- "testing"
-
- "android/soong/android"
- "android/soong/java"
-)
-
-func runJavaLibraryHostTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "java_library_host"
- (&tc).ModuleTypeUnderTestFactory = java.LibraryHostFactory
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
-}
-
-func TestJavaLibraryHost(t *testing.T) {
- runJavaLibraryHostTestCase(t, Bp2buildTestCase{
- Description: "java_library_host with srcs, exclude_srcs and libs",
- Blueprint: `java_library_host {
- name: "java-lib-host-1",
- srcs: ["a.java", "b.java"],
- exclude_srcs: ["b.java"],
- libs: ["java-lib-host-2"],
- bazel_module: { bp2build_available: true },
-}
-
-java_library_host {
- name: "java-lib-host-2",
- srcs: ["c.java"],
- bazel_module: { bp2build_available: true },
- java_version: "9",
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java-lib-host-1", AttrNameToString{
- "srcs": `["a.java"]`,
- "deps": `[":java-lib-host-2-neverlink"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("java_library", "java-lib-host-1-neverlink", AttrNameToString{
- "exports": `[":java-lib-host-1"]`,
- "neverlink": `True`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("java_library", "java-lib-host-2", AttrNameToString{
- "java_version": `"9"`,
- "srcs": `["c.java"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("java_library", "java-lib-host-2-neverlink", AttrNameToString{
- "exports": `[":java-lib-host-2"]`,
- "neverlink": `True`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- "java_version": `"9"`,
- }),
- },
- })
-}
diff --git a/bp2build/java_plugin_conversion_test.go b/bp2build/java_plugin_conversion_test.go
deleted file mode 100644
index f2b6f20..0000000
--- a/bp2build/java_plugin_conversion_test.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// 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
-
-import (
- "testing"
-
- "android/soong/android"
- "android/soong/java"
-)
-
-func runJavaPluginTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "java_plugin"
- (&tc).ModuleTypeUnderTestFactory = java.PluginFactory
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("java_library", java.LibraryFactory)
- }, tc)
-}
-
-func TestJavaPlugin(t *testing.T) {
- runJavaPluginTestCase(t, Bp2buildTestCase{
- Description: "java_plugin with srcs, libs, static_libs",
- Blueprint: `java_plugin {
- name: "java-plug-1",
- srcs: ["a.java", "b.java"],
- libs: ["java-lib-1"],
- static_libs: ["java-lib-2"],
- bazel_module: { bp2build_available: true },
- java_version: "7",
-}
-
-java_library {
- name: "java-lib-1",
- srcs: ["b.java"],
- bazel_module: { bp2build_available: false },
-}
-
-java_library {
- name: "java-lib-2",
- srcs: ["c.java"],
- bazel_module: { bp2build_available: false },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_plugin", "java-plug-1", AttrNameToString{
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- "deps": `[
- ":java-lib-1-neverlink",
- ":java-lib-2",
- ]`,
- "srcs": `[
- "a.java",
- "b.java",
- ]`,
- "java_version": `"7"`,
- }),
- },
- })
-}
-
-func TestJavaPluginNoSrcs(t *testing.T) {
- runJavaPluginTestCase(t, Bp2buildTestCase{
- Description: "java_plugin without srcs converts (static) libs to deps",
- Blueprint: `java_plugin {
- name: "java-plug-1",
- libs: ["java-lib-1"],
- static_libs: ["java-lib-2"],
- bazel_module: { bp2build_available: true },
-}
-
-java_library {
- name: "java-lib-1",
- srcs: ["b.java"],
- bazel_module: { bp2build_available: false },
-}
-
-java_library {
- name: "java-lib-2",
- srcs: ["c.java"],
- bazel_module: { bp2build_available: false },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_plugin", "java-plug-1", AttrNameToString{
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- "deps": `[
- ":java-lib-1-neverlink",
- ":java-lib-2",
- ]`,
- }),
- },
- })
-}
diff --git a/bp2build/java_proto_conversion_test.go b/bp2build/java_proto_conversion_test.go
deleted file mode 100644
index 5d6b088..0000000
--- a/bp2build/java_proto_conversion_test.go
+++ /dev/null
@@ -1,139 +0,0 @@
-// 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
-
-import (
- "fmt"
- "testing"
-
- "android/soong/android"
- "android/soong/java"
-)
-
-func runJavaProtoTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "java_library_static"
- (&tc).ModuleTypeUnderTestFactory = java.LibraryFactory
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
-}
-
-func TestJavaProto(t *testing.T) {
- testCases := []struct {
- protoType string
- javaLibraryType string
- javaLibraryNameExtension string
- }{
- {
- protoType: "nano",
- javaLibraryType: "java_nano_proto_library",
- javaLibraryNameExtension: "java_proto_nano",
- },
- {
- protoType: "micro",
- javaLibraryType: "java_micro_proto_library",
- javaLibraryNameExtension: "java_proto_micro",
- },
- {
- protoType: "lite",
- javaLibraryType: "java_lite_proto_library",
- javaLibraryNameExtension: "java_proto_lite",
- },
- {
- protoType: "stream",
- javaLibraryType: "java_stream_proto_library",
- javaLibraryNameExtension: "java_proto_stream",
- },
- {
- protoType: "full",
- javaLibraryType: "java_proto_library",
- javaLibraryNameExtension: "java_proto",
- },
- }
-
- bp := `java_library_static {
- name: "java-protos",
- proto: {
- type: "%s",
- },
- srcs: ["a.proto"],
- sdk_version: "current",
-}`
-
- protoLibrary := MakeBazelTarget("proto_library", "java-protos_proto", AttrNameToString{
- "srcs": `["a.proto"]`,
- })
-
- for _, tc := range testCases {
- javaLibraryName := fmt.Sprintf("java-protos_%s", tc.javaLibraryNameExtension)
-
- runJavaProtoTestCase(t, Bp2buildTestCase{
- Description: fmt.Sprintf("java_proto %s", tc.protoType),
- Blueprint: fmt.Sprintf(bp, tc.protoType),
- ExpectedBazelTargets: []string{
- protoLibrary,
- MakeBazelTarget(
- tc.javaLibraryType,
- javaLibraryName,
- AttrNameToString{
- "deps": `[":java-protos_proto"]`,
- "sdk_version": `"current"`,
- }),
- MakeBazelTarget("java_library", "java-protos", AttrNameToString{
- "exports": fmt.Sprintf(`[":%s"]`, javaLibraryName),
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTarget("java_library", "java-protos"),
- },
- })
- }
-}
-
-func TestJavaProtoDefault(t *testing.T) {
- runJavaProtoTestCase(t, Bp2buildTestCase{
- Description: "java_library proto default",
- Blueprint: `java_library_static {
- name: "java-protos",
- srcs: ["a.proto"],
- java_version: "7",
- sdk_version: "current",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("proto_library", "java-protos_proto", AttrNameToString{
- "srcs": `["a.proto"]`,
- }),
- MakeBazelTarget(
- "java_lite_proto_library",
- "java-protos_java_proto_lite",
- AttrNameToString{
- "deps": `[":java-protos_proto"]`,
- "java_version": `"7"`,
- "sdk_version": `"current"`,
- }),
- MakeBazelTarget("java_library", "java-protos", AttrNameToString{
- "exports": `[":java-protos_java_proto_lite"]`,
- "java_version": `"7"`,
- "sdk_version": `"current"`,
- }),
- MakeNeverlinkDuplicateTargetWithAttrs(
- "java_library",
- "java-protos",
- AttrNameToString{
- "java_version": `"7"`,
- "sdk_version": `"current"`,
- }),
- },
- })
-}
diff --git a/bp2build/java_sdk_library_conversion_test.go b/bp2build/java_sdk_library_conversion_test.go
deleted file mode 100644
index 9ce7446..0000000
--- a/bp2build/java_sdk_library_conversion_test.go
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2023 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 (
- "testing"
-
- "android/soong/android"
- "android/soong/java"
-)
-
-func runJavaSdkLibraryTestCaseWithRegistrationCtxFunc(t *testing.T, tc Bp2buildTestCase, registrationCtxFunc func(ctx android.RegistrationContext)) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "java_sdk_library"
- (&tc).ModuleTypeUnderTestFactory = java.SdkLibraryFactory
- RunBp2BuildTestCase(t, registrationCtxFunc, tc)
-}
-
-func runJavaSdkLibraryTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- runJavaSdkLibraryTestCaseWithRegistrationCtxFunc(t, tc, func(ctx android.RegistrationContext) {})
-}
-
-func TestJavaSdkLibraryApiSurfaceGeneral(t *testing.T) {
- runJavaSdkLibraryTestCase(t, Bp2buildTestCase{
- Description: "limited java_sdk_library for api surfaces, general conversion",
- Filesystem: map[string]string{
- "build/soong/scripts/gen-java-current-api-files.sh": "",
- "api/current.txt": "",
- "api/system-current.txt": "",
- "api/test-current.txt": "",
- "api/module-lib-current.txt": "",
- "api/system-server-current.txt": "",
- "api/removed.txt": "",
- "api/system-removed.txt": "",
- "api/test-removed.txt": "",
- "api/module-lib-removed.txt": "",
- "api/system-server-removed.txt": "",
- },
- Blueprint: `java_sdk_library {
- name: "java-sdk-lib",
- srcs: ["a.java"],
- public: {enabled: true},
- system: {enabled: true},
- test: {enabled: true},
- module_lib: {enabled: true},
- system_server: {enabled: true},
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_sdk_library", "java-sdk-lib", AttrNameToString{
- "public": `"api/current.txt"`,
- "system": `"api/system-current.txt"`,
- "test": `"api/test-current.txt"`,
- "module_lib": `"api/module-lib-current.txt"`,
- "system_server": `"api/system-server-current.txt"`,
- }),
- },
- })
-}
-
-func TestJavaSdkLibraryApiSurfacePublicDefault(t *testing.T) {
- runJavaSdkLibraryTestCase(t, Bp2buildTestCase{
- Description: "limited java_sdk_library for api surfaces, public prop uses default value",
- Filesystem: map[string]string{
- "build/soong/scripts/gen-java-current-api-files.sh": "",
- "api/current.txt": "",
- "api/system-current.txt": "",
- "api/test-current.txt": "",
- "api/module-lib-current.txt": "",
- "api/system-server-current.txt": "",
- "api/removed.txt": "",
- "api/system-removed.txt": "",
- "api/test-removed.txt": "",
- "api/module-lib-removed.txt": "",
- "api/system-server-removed.txt": "",
- },
- Blueprint: `java_sdk_library {
- name: "java-sdk-lib",
- srcs: ["a.java"],
- system: {enabled: false},
- test: {enabled: false},
- module_lib: {enabled: false},
- system_server: {enabled: false},
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_sdk_library", "java-sdk-lib", AttrNameToString{
- "public": `"api/current.txt"`,
- }),
- },
- })
-}
-
-func TestJavaSdkLibraryApiSurfacePublicNotEnabled(t *testing.T) {
- runJavaSdkLibraryTestCase(t, Bp2buildTestCase{
- Description: "limited java_sdk_library for api surfaces, public enable is false",
- Filesystem: map[string]string{
- "build/soong/scripts/gen-java-current-api-files.sh": "",
- "api/current.txt": "",
- "api/removed.txt": "",
- },
- Blueprint: `java_sdk_library {
- name: "java-sdk-lib",
- srcs: ["a.java"],
- public: {enabled: false},
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_sdk_library", "java-sdk-lib", AttrNameToString{}),
- },
- })
-}
-
-func TestJavaSdkLibraryApiSurfaceNoScopeIsSet(t *testing.T) {
- runJavaSdkLibraryTestCase(t, Bp2buildTestCase{
- Description: "limited java_sdk_library for api surfaces, none of the api scopes is set",
- Filesystem: map[string]string{
- "build/soong/scripts/gen-java-current-api-files.sh": "",
- "api/current.txt": "",
- "api/system-current.txt": "",
- "api/test-current.txt": "",
- "api/removed.txt": "",
- "api/system-removed.txt": "",
- "api/test-removed.txt": "",
- },
- Blueprint: `java_sdk_library {
- name: "java-sdk-lib",
- srcs: ["a.java"],
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_sdk_library", "java-sdk-lib", AttrNameToString{
- "public": `"api/current.txt"`,
- "system": `"api/system-current.txt"`,
- "test": `"api/test-current.txt"`,
- }),
- },
- })
-}
diff --git a/bp2build/java_test_host_conversion_test.go b/bp2build/java_test_host_conversion_test.go
deleted file mode 100644
index f41345e..0000000
--- a/bp2build/java_test_host_conversion_test.go
+++ /dev/null
@@ -1,158 +0,0 @@
-// Copyright 2023 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 (
- "testing"
-
- "android/soong/android"
- "android/soong/java"
-)
-
-func runJavaTestHostTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "java_test_host"
- (&tc).ModuleTypeUnderTestFactory = java.TestHostFactory
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("java_library", java.LibraryFactory)
- }, tc)
-}
-
-func TestJavaTestHostGeneral(t *testing.T) {
- runJavaTestHostTestCase(t, Bp2buildTestCase{
- Description: "java_test_host general",
- Filesystem: map[string]string{},
- Blueprint: `
-java_test_host {
- name: "java_test_host-1",
- srcs: ["a.java", "b.java"],
- libs: ["lib_a"],
- static_libs: ["static_libs_a"],
- exclude_srcs: ["b.java"],
- javacflags: ["-Xdoclint:all/protected"],
- java_version: "8",
-}
-
-java_library {
- name: "lib_a",
- bazel_module: { bp2build_available: false },
-}
-
-java_library {
- name: "static_libs_a",
- bazel_module: { bp2build_available: false },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_library", "java_test_host-1_lib", AttrNameToString{
- "deps": `[
- ":lib_a-neverlink",
- ":static_libs_a",
- ]`,
- "java_version": `"8"`,
- "javacopts": `["-Xdoclint:all/protected"]`,
- "srcs": `["a.java"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("java_test", "java_test_host-1", AttrNameToString{
- "runtime_deps": `[":java_test_host-1_lib"]`,
- "deps": `[
- ":lib_a-neverlink",
- ":static_libs_a",
- ]`,
- "srcs": `["a.java"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestJavaTestHostNoSrcs(t *testing.T) {
- runJavaTestHostTestCase(t, Bp2buildTestCase{
- Description: "java_test_host without srcs",
- Filesystem: map[string]string{},
- Blueprint: `
-java_test_host {
- name: "java_test_host-1",
- libs: ["lib_a"],
- static_libs: ["static_libs_a"],
-}
-
-java_library {
- name: "lib_a",
- bazel_module: { bp2build_available: false },
-}
-
-java_library {
- name: "static_libs_a",
- bazel_module: { bp2build_available: false },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_test", "java_test_host-1", AttrNameToString{
- "runtime_deps": `[
- ":lib_a-neverlink",
- ":static_libs_a",
- ]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestJavaTestHostKotlinSrcs(t *testing.T) {
- runJavaTestHostTestCase(t, Bp2buildTestCase{
- Description: "java_test_host with .kt in srcs",
- Filesystem: map[string]string{},
- Blueprint: `
-java_test_host {
- name: "java_test_host-1",
- srcs: ["a.java", "b.kt"],
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("java_test", "java_test_host-1", AttrNameToString{
- "srcs": `[
- "a.java",
- "b.kt",
- ]`,
- "runtime_deps": `[":java_test_host-1_lib"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- MakeBazelTarget("kt_jvm_library", "java_test_host-1_lib", AttrNameToString{
- "srcs": `[
- "a.java",
- "b.kt",
- ]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
diff --git a/bp2build/license_conversion_test.go b/bp2build/license_conversion_test.go
deleted file mode 100644
index ea6b27a..0000000
--- a/bp2build/license_conversion_test.go
+++ /dev/null
@@ -1,81 +0,0 @@
-// 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 (
- "android/soong/android"
- "testing"
-)
-
-func registerLicenseModuleTypes(_ android.RegistrationContext) {}
-
-func TestLicenseBp2Build(t *testing.T) {
- tests := []struct {
- description string
- module string
- expected ExpectedRuleTarget
- }{
- {
- description: "license kind and text notice",
- module: `
-license {
- name: "my_license",
- license_kinds: [ "SPDX-license-identifier-Apache-2.0"],
- license_text: [ "NOTICE"],
-}`,
- expected: ExpectedRuleTarget{
- "android_license",
- "my_license",
- AttrNameToString{
- "license_kinds": `["SPDX-license-identifier-Apache-2.0"]`,
- "license_text": `"NOTICE"`,
- },
- android.HostAndDeviceDefault,
- },
- },
- {
- description: "visibility, package_name, copyright_notice",
- module: `
-license {
- name: "my_license",
- package_name: "my_package",
- visibility: [":__subpackages__"],
- copyright_notice: "Copyright © 2022",
-}`,
- expected: ExpectedRuleTarget{
- "android_license",
- "my_license",
- AttrNameToString{
- "copyright_notice": `"Copyright © 2022"`,
- "package_name": `"my_package"`,
- "visibility": `[":__subpackages__"]`,
- },
- android.HostAndDeviceDefault,
- },
- },
- }
-
- for _, test := range tests {
- RunBp2BuildTestCase(t,
- registerLicenseModuleTypes,
- Bp2buildTestCase{
- Description: test.description,
- ModuleTypeUnderTest: "license",
- ModuleTypeUnderTestFactory: android.LicenseFactory,
- Blueprint: test.module,
- ExpectedBazelTargets: []string{test.expected.String()},
- })
- }
-}
diff --git a/bp2build/license_kind_conversion_test.go b/bp2build/license_kind_conversion_test.go
deleted file mode 100644
index eda116c..0000000
--- a/bp2build/license_kind_conversion_test.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// 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 (
- "android/soong/android"
- "testing"
-)
-
-func registerLicenseKindModuleTypes(_ android.RegistrationContext) {}
-
-func TestLicenseKindBp2Build(t *testing.T) {
- tests := []struct {
- description string
- module string
- expected ExpectedRuleTarget
- }{
- {
- description: "license_kind",
- module: `
-license_kind {
- name: "my_license",
- conditions: [
- "by_exception_only",
- "not_allowed",
- ],
- url: "https://spdx.org/licenses/0BSD",
- visibility: ["//visibility:public"],
-}`,
- expected: ExpectedRuleTarget{
- "license_kind",
- "my_license",
- AttrNameToString{
- "conditions": `[
- "by_exception_only",
- "not_allowed",
- ]`,
- "url": `"https://spdx.org/licenses/0BSD"`,
- "visibility": `["//visibility:public"]`,
- },
- android.HostAndDeviceDefault,
- },
- },
- }
-
- for _, test := range tests {
- RunBp2BuildTestCase(t,
- registerLicenseKindModuleTypes,
- Bp2buildTestCase{
- Description: test.description,
- ModuleTypeUnderTest: "license_kind",
- ModuleTypeUnderTestFactory: android.LicenseKindFactory,
- Blueprint: test.module,
- ExpectedBazelTargets: []string{test.expected.String()},
- })
- }
-}
diff --git a/bp2build/linker_config_conversion_test.go b/bp2build/linker_config_conversion_test.go
deleted file mode 100644
index 5e7bcd4..0000000
--- a/bp2build/linker_config_conversion_test.go
+++ /dev/null
@@ -1,59 +0,0 @@
-// 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/linkerconfig"
-)
-
-func runLinkerConfigTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "linker_config"
- (&tc).ModuleTypeUnderTestFactory = linkerconfig.LinkerConfigFactory
- RunBp2BuildTestCaseSimple(t, tc)
-}
-
-func TestLinkerConfigConvertsSrc(t *testing.T) {
- runLinkerConfigTestCase(t,
- Bp2buildTestCase{
- Blueprint: `
-linker_config {
- name: "foo",
- src: "a.json",
-}
-`,
- ExpectedBazelTargets: []string{MakeBazelTarget("linker_config", "foo", AttrNameToString{
- "src": `"a.json"`,
- })},
- })
-
-}
-
-func TestLinkerConfigNoSrc(t *testing.T) {
- runLinkerConfigTestCase(t,
- Bp2buildTestCase{
- Blueprint: `
-linker_config {
- name: "foo",
-}
-`,
- ExpectedBazelTargets: []string{},
- ExpectedErr: fmt.Errorf("Android.bp:2:1: module \"foo\": src: empty src is not supported"),
- })
-
-}
diff --git a/bp2build/metrics.go b/bp2build/metrics.go
deleted file mode 100644
index 20002c6..0000000
--- a/bp2build/metrics.go
+++ /dev/null
@@ -1,231 +0,0 @@
-package bp2build
-
-import (
- "fmt"
- "os"
- "path/filepath"
- "strings"
-
- "android/soong/android"
- "android/soong/shared"
- "android/soong/ui/metrics/bp2build_metrics_proto"
-
- "google.golang.org/protobuf/proto"
-
- "github.com/google/blueprint"
-)
-
-type moduleInfo struct {
- Name string `json:"name"`
- Type string `json:"type"`
-}
-
-// CodegenMetrics represents information about the Blueprint-to-BUILD
-// conversion process.
-// Use CreateCodegenMetrics() to get a properly initialized instance
-type CodegenMetrics struct {
- serialized *bp2build_metrics_proto.Bp2BuildMetrics
- // List of modules with unconverted deps
- // NOTE: NOT in the .proto
- moduleWithUnconvertedDepsMsgs []string
-
- // List of modules with missing deps
- // NOTE: NOT in the .proto
- moduleWithMissingDepsMsgs []string
-
- // Map of converted modules and paths to call
- // NOTE: NOT in the .proto
- convertedModulePathMap map[string]string
-
- // Name and type of converted modules
- convertedModuleWithType []moduleInfo
-}
-
-func CreateCodegenMetrics() CodegenMetrics {
- return CodegenMetrics{
- serialized: &bp2build_metrics_proto.Bp2BuildMetrics{
- RuleClassCount: make(map[string]uint64),
- ConvertedModuleTypeCount: make(map[string]uint64),
- TotalModuleTypeCount: make(map[string]uint64),
- UnconvertedModules: make(map[string]*bp2build_metrics_proto.UnconvertedReason),
- },
- convertedModulePathMap: make(map[string]string),
- }
-}
-
-// Serialize returns the protoized version of CodegenMetrics: bp2build_metrics_proto.Bp2BuildMetrics
-func (metrics *CodegenMetrics) Serialize() *bp2build_metrics_proto.Bp2BuildMetrics {
- return metrics.serialized
-}
-
-// Print the codegen metrics to stdout.
-func (metrics *CodegenMetrics) Print() {
- generatedTargetCount := uint64(0)
- for _, ruleClass := range android.SortedKeys(metrics.serialized.RuleClassCount) {
- count := metrics.serialized.RuleClassCount[ruleClass]
- fmt.Printf("[bp2build] %s: %d targets\n", ruleClass, count)
- generatedTargetCount += count
- }
- fmt.Printf(
- `[bp2build] Converted %d Android.bp modules to %d total generated BUILD targets. Included %d handcrafted BUILD targets. There are %d total Android.bp modules.
-%d converted modules have unconverted deps:
- %s
-%d converted modules have missing deps:
- %s
-`,
- metrics.serialized.GeneratedModuleCount,
- generatedTargetCount,
- metrics.serialized.HandCraftedModuleCount,
- metrics.TotalModuleCount(),
- len(metrics.moduleWithUnconvertedDepsMsgs),
- strings.Join(metrics.moduleWithUnconvertedDepsMsgs, "\n\t"),
- len(metrics.moduleWithMissingDepsMsgs),
- strings.Join(metrics.moduleWithMissingDepsMsgs, "\n\t"),
- )
-}
-
-const bp2buildMetricsFilename = "bp2build_metrics.pb"
-
-// fail prints $PWD to stderr, followed by the given printf string and args (vals),
-// then the given alert, and then exits with 1 for failure
-func fail(err error, alertFmt string, vals ...interface{}) {
- cwd, wderr := os.Getwd()
- if wderr != nil {
- cwd = "FAILED TO GET $PWD: " + wderr.Error()
- }
- fmt.Fprintf(os.Stderr, "\nIn "+cwd+":\n"+alertFmt+"\n"+err.Error()+"\n", vals...)
- os.Exit(1)
-}
-
-// Write the bp2build-protoized codegen metrics into the given directory
-func (metrics *CodegenMetrics) Write(dir string) {
- if _, err := os.Stat(dir); os.IsNotExist(err) {
- // The metrics dir doesn't already exist, so create it (and parents)
- if err := os.MkdirAll(dir, 0755); err != nil { // rx for all; w for user
- fail(err, "Failed to `mkdir -p` %s", dir)
- }
- } else if err != nil {
- fail(err, "Failed to `stat` %s", dir)
- }
- metricsFile := filepath.Join(dir, bp2buildMetricsFilename)
- if err := metrics.dump(metricsFile); err != nil {
- fail(err, "Error outputting %s", metricsFile)
- }
- if _, err := os.Stat(metricsFile); err != nil {
- if os.IsNotExist(err) {
- fail(err, "MISSING BP2BUILD METRICS OUTPUT: %s", metricsFile)
- } else {
- fail(err, "FAILED TO `stat` BP2BUILD METRICS OUTPUT: %s", metricsFile)
- }
- }
-}
-
-// ReadCodegenMetrics loads CodegenMetrics from `dir`
-// returns a nil pointer if the file doesn't exist
-func ReadCodegenMetrics(dir string) *CodegenMetrics {
- metricsFile := filepath.Join(dir, bp2buildMetricsFilename)
- if _, err := os.Stat(metricsFile); err != nil {
- if os.IsNotExist(err) {
- return nil
- } else {
- fail(err, "FAILED TO `stat` BP2BUILD METRICS OUTPUT: %s", metricsFile)
- panic("unreachable after fail")
- }
- }
- if buf, err := os.ReadFile(metricsFile); err != nil {
- fail(err, "FAILED TO READ BP2BUILD METRICS OUTPUT: %s", metricsFile)
- panic("unreachable after fail")
- } else {
- bp2BuildMetrics := bp2build_metrics_proto.Bp2BuildMetrics{
- RuleClassCount: make(map[string]uint64),
- ConvertedModuleTypeCount: make(map[string]uint64),
- TotalModuleTypeCount: make(map[string]uint64),
- }
- if err := proto.Unmarshal(buf, &bp2BuildMetrics); err != nil {
- fail(err, "FAILED TO PARSE BP2BUILD METRICS OUTPUT: %s", metricsFile)
- }
- return &CodegenMetrics{
- serialized: &bp2BuildMetrics,
- convertedModulePathMap: make(map[string]string),
- }
- }
-}
-
-func (metrics *CodegenMetrics) IncrementRuleClassCount(ruleClass string) {
- metrics.serialized.RuleClassCount[ruleClass] += 1
-}
-
-func (metrics *CodegenMetrics) AddEvent(event *bp2build_metrics_proto.Event) {
- metrics.serialized.Events = append(metrics.serialized.Events, event)
-}
-
-func (metrics *CodegenMetrics) SetSymlinkCount(n uint64) {
- if m := metrics.serialized.WorkspaceSymlinkCount; m != 0 {
- fmt.Fprintf(os.Stderr, "unexpected non-zero workspaceSymlinkCount of %d", m)
- }
- metrics.serialized.WorkspaceSymlinkCount = n
-}
-
-func (metrics *CodegenMetrics) SetMkDirCount(n uint64) {
- if m := metrics.serialized.WorkspaceMkDirCount; m != 0 {
- fmt.Fprintf(os.Stderr, "unexpected non-zero workspaceDirCount of %d", m)
- }
- metrics.serialized.WorkspaceMkDirCount = n
-}
-
-func (metrics *CodegenMetrics) TotalModuleCount() uint64 {
- return metrics.serialized.HandCraftedModuleCount +
- metrics.serialized.GeneratedModuleCount +
- metrics.serialized.UnconvertedModuleCount
-}
-
-// Dump serializes the metrics to the given filename
-func (metrics *CodegenMetrics) dump(filename string) (err error) {
- ser := metrics.Serialize()
- return shared.Save(ser, filename)
-}
-
-type ConversionType int
-
-const (
- Generated ConversionType = iota
- Handcrafted
-)
-
-func (metrics *CodegenMetrics) AddConvertedModule(m blueprint.Module, moduleType string, dir string) {
- //a package module has empty name
- if moduleType == "package" {
- return
- }
- // Undo prebuilt_ module name prefix modifications
- moduleName := android.RemoveOptionalPrebuiltPrefix(m.Name())
- metrics.serialized.ConvertedModules = append(metrics.serialized.ConvertedModules, moduleName)
- metrics.convertedModuleWithType = append(metrics.convertedModuleWithType, moduleInfo{
- moduleName,
- moduleType,
- })
- metrics.convertedModulePathMap[moduleName] = "//" + dir
- metrics.serialized.ConvertedModuleTypeCount[moduleType] += 1
- metrics.serialized.TotalModuleTypeCount[moduleType] += 1
- metrics.serialized.GeneratedModuleCount += 1
-}
-
-func (metrics *CodegenMetrics) AddUnconvertedModule(m blueprint.Module, moduleType string, dir string,
- reason android.UnconvertedReason) {
- //a package module has empty name
- if moduleType == "package" {
- return
- }
- // Undo prebuilt_ module name prefix modifications
- moduleName := android.RemoveOptionalPrebuiltPrefix(m.Name())
- metrics.serialized.UnconvertedModules[moduleName] = &bp2build_metrics_proto.UnconvertedReason{
- Type: bp2build_metrics_proto.UnconvertedReasonType(reason.ReasonType),
- Detail: reason.Detail,
- }
- metrics.serialized.UnconvertedModuleCount += 1
- metrics.serialized.TotalModuleTypeCount[moduleType] += 1
-
- if reason.ReasonType == int(bp2build_metrics_proto.UnconvertedReasonType_DEFINED_IN_BUILD_FILE) {
- metrics.serialized.HandCraftedModuleCount += 1
- }
-}
diff --git a/bp2build/package_conversion_test.go b/bp2build/package_conversion_test.go
deleted file mode 100644
index ce848e4..0000000
--- a/bp2build/package_conversion_test.go
+++ /dev/null
@@ -1,139 +0,0 @@
-// 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 (
- "testing"
-
- "android/soong/android"
- "android/soong/genrule"
-)
-
-func registerDependentModules(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("license", android.LicenseFactory)
- ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
-}
-
-func TestPackage(t *testing.T) {
- tests := []struct {
- description string
- modules string
- fs map[string]string
- expected []ExpectedRuleTarget
- }{
- {
- description: "with default applicable licenses",
- modules: `
-license {
- name: "my_license",
- visibility: [":__subpackages__"],
- license_kinds: ["SPDX-license-identifier-Apache-2.0"],
- license_text: ["NOTICE"],
-}
-
-package {
- default_applicable_licenses: ["my_license"],
-}
-`,
- expected: []ExpectedRuleTarget{
- {
- "package",
- "",
- AttrNameToString{
- "default_package_metadata": `[":my_license"]`,
- "default_visibility": `["//visibility:public"]`,
- },
- android.HostAndDeviceDefault,
- },
- {
- "android_license",
- "my_license",
- AttrNameToString{
- "license_kinds": `["SPDX-license-identifier-Apache-2.0"]`,
- "license_text": `"NOTICE"`,
- "visibility": `[":__subpackages__"]`,
- },
- android.HostAndDeviceDefault,
- },
- },
- },
- {
- description: "package has METADATA file",
- fs: map[string]string{
- "METADATA": ``,
- },
- modules: `
-license {
- name: "my_license",
- visibility: [":__subpackages__"],
- license_kinds: ["SPDX-license-identifier-Apache-2.0"],
- license_text: ["NOTICE"],
-}
-
-package {
- default_applicable_licenses: ["my_license"],
-}
-`,
- expected: []ExpectedRuleTarget{
- {
- "package",
- "",
- AttrNameToString{
- "default_package_metadata": `[
- ":my_license",
- ":default_metadata_file",
- ]`,
- "default_visibility": `["//visibility:public"]`,
- },
- android.HostAndDeviceDefault,
- },
- {
- "android_license",
- "my_license",
- AttrNameToString{
- "license_kinds": `["SPDX-license-identifier-Apache-2.0"]`,
- "license_text": `"NOTICE"`,
- "visibility": `[":__subpackages__"]`,
- },
- android.HostAndDeviceDefault,
- },
- {
- "filegroup",
- "default_metadata_file",
- AttrNameToString{
- "applicable_licenses": `[]`,
- "srcs": `["METADATA"]`,
- },
- android.HostAndDeviceDefault,
- },
- },
- },
- }
- for _, test := range tests {
- expected := make([]string, 0, len(test.expected))
- for _, e := range test.expected {
- expected = append(expected, e.String())
- }
- RunBp2BuildTestCase(t, registerDependentModules,
- Bp2buildTestCase{
- Description: test.description,
- ModuleTypeUnderTest: "package",
- ModuleTypeUnderTestFactory: android.PackageFactory,
- Blueprint: test.modules,
- ExpectedBazelTargets: expected,
- Filesystem: test.fs,
- })
- }
-}
diff --git a/bp2build/performance_test.go b/bp2build/performance_test.go
deleted file mode 100644
index 5f80b83..0000000
--- a/bp2build/performance_test.go
+++ /dev/null
@@ -1,219 +0,0 @@
-// 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
-
-// to run the benchmarks in this file, you must run go test with the -bench.
-// The benchmarked portion will run for the specified time (can be set via -benchtime)
-// This can mean if you are benchmarking a faster portion of a larger operation, it will take
-// longer.
-// If you are seeing a small number of iterations for a specific run, the data is less reliable, to
-// run for longer, set -benchtime to a larger value.
-
-import (
- "fmt"
- "math"
- "strings"
- "testing"
-
- "android/soong/android"
-)
-
-const (
- performance_test_dir = "."
-)
-
-func genCustomModule(i int, convert bool) string {
- var conversionString string
- if convert {
- conversionString = `bazel_module: { bp2build_available: true },`
- }
- return fmt.Sprintf(`
-custom {
- name: "arch_paths_%[1]d",
- string_list_prop: ["\t", "\n"],
- string_prop: "a\t\n\r",
- arch_paths: ["outer", ":outer_dep_%[1]d"],
- arch: {
- x86: {
- arch_paths: ["abc", ":x86_dep_%[1]d"],
- },
- x86_64: {
- arch_paths: ["64bit"],
- arch_paths_exclude: ["outer"],
- },
- },
- %[2]s
-}
-
-custom {
- name: "outer_dep_%[1]d",
- %[2]s
-}
-
-custom {
- name: "x86_dep_%[1]d",
- %[2]s
-}
-`, i, conversionString)
-}
-
-func genCustomModuleBp(pctConverted float64) string {
- modules := 100
-
- bp := make([]string, 0, modules)
- toConvert := int(math.Round(float64(modules) * pctConverted))
-
- for i := 0; i < modules; i++ {
- bp = append(bp, genCustomModule(i, i < toConvert))
- }
- return strings.Join(bp, "\n\n")
-}
-
-type testConfig struct {
- config android.Config
- ctx *android.TestContext
- codegenCtx *CodegenContext
-}
-
-func (tc testConfig) parse() []error {
- _, errs := tc.ctx.ParseFileList(performance_test_dir, []string{"Android.bp"})
- return errs
-}
-
-func (tc testConfig) resolveDependencies() []error {
- _, errs := tc.ctx.ResolveDependencies(tc.config)
- return errs
-}
-
-func (tc testConfig) convert() {
- generateBazelTargetsForDir(tc.codegenCtx, performance_test_dir)
-}
-
-func setup(builddir string, tcSize float64) testConfig {
- config := android.TestConfig(buildDir, nil, genCustomModuleBp(tcSize), nil)
- ctx := android.NewTestContext(config)
-
- registerCustomModuleForBp2buildConversion(ctx)
- codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
- return testConfig{
- config,
- ctx,
- codegenCtx,
- }
-}
-
-var pctToConvert = []float64{0.0, 0.01, 0.05, 0.10, 0.25, 0.5, 0.75, 1.0}
-
-// This is not intended to test performance, but to verify performance infra continues to work
-func TestConvertManyModulesFull(t *testing.T) {
- for _, tcSize := range pctToConvert {
-
- t.Run(fmt.Sprintf("pctConverted %f", tcSize), func(t *testing.T) {
- testConfig := setup(buildDir, tcSize)
-
- errs := testConfig.parse()
- if len(errs) > 0 {
- t.Fatalf("Unexpected errors: %s", errs)
- }
-
- errs = testConfig.resolveDependencies()
- if len(errs) > 0 {
- t.Fatalf("Unexpected errors: %s", errs)
- }
-
- testConfig.convert()
- })
- }
-}
-
-func BenchmarkManyModulesFull(b *testing.B) {
- for _, tcSize := range pctToConvert {
-
- b.Run(fmt.Sprintf("pctConverted %f", tcSize), func(b *testing.B) {
- for n := 0; n < b.N; n++ {
- b.StopTimer()
- testConfig := setup(buildDir, tcSize)
-
- b.StartTimer()
- errs := testConfig.parse()
- if len(errs) > 0 {
- b.Fatalf("Unexpected errors: %s", errs)
- }
-
- errs = testConfig.resolveDependencies()
- if len(errs) > 0 {
- b.Fatalf("Unexpected errors: %s", errs)
- }
-
- testConfig.convert()
- b.StopTimer()
- }
- })
- }
-}
-
-func BenchmarkManyModulesResolveDependencies(b *testing.B) {
- for _, tcSize := range pctToConvert {
-
- b.Run(fmt.Sprintf("pctConverted %f", tcSize), func(b *testing.B) {
- for n := 0; n < b.N; n++ {
- b.StopTimer()
- // setup we don't want to measure
- testConfig := setup(buildDir, tcSize)
-
- errs := testConfig.parse()
- if len(errs) > 0 {
- b.Fatalf("Unexpected errors: %s", errs)
- }
-
- b.StartTimer()
- errs = testConfig.resolveDependencies()
- b.StopTimer()
- if len(errs) > 0 {
- b.Fatalf("Unexpected errors: %s", errs)
- }
-
- testConfig.convert()
- }
- })
- }
-}
-
-func BenchmarkManyModulesGenerateBazelTargetsForDir(b *testing.B) {
- for _, tcSize := range pctToConvert {
-
- b.Run(fmt.Sprintf("pctConverted %f", tcSize), func(b *testing.B) {
- for n := 0; n < b.N; n++ {
- b.StopTimer()
- // setup we don't want to measure
- testConfig := setup(buildDir, tcSize)
-
- errs := testConfig.parse()
- if len(errs) > 0 {
- b.Fatalf("Unexpected errors: %s", errs)
- }
-
- errs = testConfig.resolveDependencies()
- if len(errs) > 0 {
- b.Fatalf("Unexpected errors: %s", errs)
- }
-
- b.StartTimer()
- testConfig.convert()
- b.StopTimer()
- }
- })
- }
-}
diff --git a/bp2build/platform_compat_config_conversion_test.go b/bp2build/platform_compat_config_conversion_test.go
deleted file mode 100644
index 4dfcce3..0000000
--- a/bp2build/platform_compat_config_conversion_test.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2023 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 (
- "testing"
-
- "android/soong/android"
- "android/soong/java"
-)
-
-func runPlatformCompatConfigTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("java_library", java.LibraryFactory)
- ctx.RegisterModuleType("platform_compat_config", java.PlatformCompatConfigFactory)
- }, tc)
-}
-
-func TestPlatformCompatConfig(t *testing.T) {
- runPlatformCompatConfigTestCase(t, Bp2buildTestCase{
- Description: "platform_compat_config - conversion test",
- Blueprint: `
- platform_compat_config {
- name: "foo",
- src: ":lib",
- }`,
- Filesystem: map[string]string{
- "a/b/Android.bp": `
- java_library {
- name: "lib",
- srcs: ["a.java"],
- }`,
- },
- ExpectedBazelTargets: []string{
- MakeBazelTarget("platform_compat_config", "foo", AttrNameToString{
- "src": `"//a/b:lib"`,
- }),
- },
- })
-}
diff --git a/bp2build/prebuilt_etc_conversion_test.go b/bp2build/prebuilt_etc_conversion_test.go
deleted file mode 100644
index e237303..0000000
--- a/bp2build/prebuilt_etc_conversion_test.go
+++ /dev/null
@@ -1,362 +0,0 @@
-// 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
-
-import (
- "fmt"
- "testing"
-
- "android/soong/android"
- "android/soong/etc"
-)
-
-func runPrebuiltEtcTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "prebuilt_etc"
- (&tc).ModuleTypeUnderTestFactory = etc.PrebuiltEtcFactory
- RunBp2BuildTestCase(t, registerPrebuiltEtcModuleTypes, tc)
-}
-
-func registerPrebuiltEtcModuleTypes(ctx android.RegistrationContext) {
-}
-
-func TestPrebuiltEtcSimple(t *testing.T) {
- runPrebuiltEtcTestCase(t, Bp2buildTestCase{
- Description: "prebuilt_etc - simple example",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc {
- name: "apex_tz_version",
- src: "version/tz_version",
- filename: "tz_version",
- sub_dir: "tz",
- installable: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{
- "filename": `"tz_version"`,
- "installable": `False`,
- "src": `"version/tz_version"`,
- "dir": `"etc/tz"`,
- })}})
-}
-
-func TestPrebuiltEtcArchVariant(t *testing.T) {
- runPrebuiltEtcTestCase(t, Bp2buildTestCase{
- Description: "prebuilt_etc - arch variant",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc {
- name: "apex_tz_version",
- src: "version/tz_version",
- filename: "tz_version",
- sub_dir: "tz",
- installable: false,
- arch: {
- arm: {
- src: "arm",
- },
- arm64: {
- src: "arm64",
- },
- }
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{
- "filename": `"tz_version"`,
- "installable": `False`,
- "src": `select({
- "//build/bazel/platforms/arch:arm": "arm",
- "//build/bazel/platforms/arch:arm64": "arm64",
- "//conditions:default": "version/tz_version",
- })`,
- "dir": `"etc/tz"`,
- })}})
-}
-
-func TestPrebuiltEtcArchAndTargetVariant(t *testing.T) {
- runPrebuiltEtcTestCase(t, Bp2buildTestCase{
- Description: "prebuilt_etc - arch variant",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc {
- name: "apex_tz_version",
- src: "version/tz_version",
- filename: "tz_version",
- sub_dir: "tz",
- installable: false,
- arch: {
- arm: {
- src: "arm",
- },
- arm64: {
- src: "darwin_or_arm64",
- },
- },
- target: {
- darwin: {
- src: "darwin_or_arm64",
- }
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{
- "filename": `"tz_version"`,
- "installable": `False`,
- "src": `select({
- "//build/bazel/platforms/os_arch:android_arm": "arm",
- "//build/bazel/platforms/os_arch:android_arm64": "darwin_or_arm64",
- "//build/bazel/platforms/os_arch:darwin_arm64": "darwin_or_arm64",
- "//build/bazel/platforms/os_arch:darwin_x86_64": "darwin_or_arm64",
- "//build/bazel/platforms/os_arch:linux_bionic_arm64": "darwin_or_arm64",
- "//conditions:default": "version/tz_version",
- })`,
- "dir": `"etc/tz"`,
- })}})
-}
-func TestPrebuiltEtcProductVariables(t *testing.T) {
- runPrebuiltEtcTestCase(t, Bp2buildTestCase{
- Description: "prebuilt etc - product variables",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc {
- name: "apex_tz_version",
- src: "version/tz_version",
- filename: "tz_version",
- product_variables: {
- native_coverage: {
- src: "src1",
- },
- },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{
- "filename": `"tz_version"`,
- "src": `select({
- "//build/bazel/product_config/config_settings:native_coverage": "src1",
- "//conditions:default": "version/tz_version",
- })`,
- "dir": `"etc"`,
- })}})
-}
-
-func runPrebuiltUsrShareTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "prebuilt_usr_share"
- (&tc).ModuleTypeUnderTestFactory = etc.PrebuiltUserShareFactory
- RunBp2BuildTestCase(t, registerPrebuiltEtcModuleTypes, tc)
-}
-
-func registerPrebuiltUsrShareModuleTypes(ctx android.RegistrationContext) {
-}
-
-func TestPrebuiltUsrShareSimple(t *testing.T) {
- runPrebuiltUsrShareTestCase(t, Bp2buildTestCase{
- Description: "prebuilt_usr_share - simple example",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_usr_share {
- name: "apex_tz_version",
- src: "version/tz_version",
- filename: "tz_version",
- sub_dir: "tz",
- installable: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{
- "filename": `"tz_version"`,
- "installable": `False`,
- "src": `"version/tz_version"`,
- "dir": `"usr/share/tz"`,
- })}})
-}
-
-func TestPrebuiltEtcNoSubdir(t *testing.T) {
- runPrebuiltEtcTestCase(t, Bp2buildTestCase{
- Description: "prebuilt_etc - no subdir",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc {
- name: "apex_tz_version",
- src: "version/tz_version",
- filename: "tz_version",
- installable: false,
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_file", "apex_tz_version", AttrNameToString{
- "filename": `"tz_version"`,
- "installable": `False`,
- "src": `"version/tz_version"`,
- "dir": `"etc"`,
- })}})
-}
-
-func TestFilenameAsProperty(t *testing.T) {
- runPrebuiltEtcTestCase(t, Bp2buildTestCase{
- Description: "prebuilt_etc - filename is specified as a property ",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc {
- name: "foo",
- src: "fooSrc",
- filename: "fooFileName",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_file", "foo", AttrNameToString{
- "filename": `"fooFileName"`,
- "src": `"fooSrc"`,
- "dir": `"etc"`,
- })}})
-}
-
-func TestFileNameFromSrc(t *testing.T) {
- runPrebuiltEtcTestCase(t, Bp2buildTestCase{
- Description: "prebuilt_etc - filename_from_src is true ",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc {
- name: "foo",
- filename_from_src: true,
- src: "fooSrc",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_file", "foo", AttrNameToString{
- "filename": `"fooSrc"`,
- "src": `"fooSrc"`,
- "dir": `"etc"`,
- })}})
-}
-
-func TestFileNameFromSrcMultipleSrcs(t *testing.T) {
- runPrebuiltEtcTestCase(t, Bp2buildTestCase{
- Description: "prebuilt_etc - filename_from_src is true but there are multiple srcs",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc {
- name: "foo",
- filename_from_src: true,
- arch: {
- arm: {
- src: "barSrc",
- },
- arm64: {
- src: "bazSrc",
- },
- }
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_file", "foo", AttrNameToString{
- "filename_from_src": `True`,
- "dir": `"etc"`,
- "src": `select({
- "//build/bazel/platforms/arch:arm": "barSrc",
- "//build/bazel/platforms/arch:arm64": "bazSrc",
- "//conditions:default": None,
- })`,
- })}})
-}
-
-func TestFilenameFromModuleName(t *testing.T) {
- runPrebuiltEtcTestCase(t, Bp2buildTestCase{
- Description: "prebuilt_etc - neither filename nor filename_from_src are specified ",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc {
- name: "foo",
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_file", "foo", AttrNameToString{
- "filename": `"foo"`,
- "dir": `"etc"`,
- })}})
-}
-
-func TestPrebuiltEtcProductVariableArchSrcs(t *testing.T) {
- runPrebuiltEtcTestCase(t, Bp2buildTestCase{
- Description: "prebuilt etc- SRcs from arch variant product variables",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc {
- name: "foo",
- filename: "fooFilename",
- arch: {
- arm: {
- src: "armSrc",
- product_variables: {
- native_coverage: {
- src: "nativeCoverageArmSrc",
- },
- },
- },
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("prebuilt_file", "foo", AttrNameToString{
- "filename": `"fooFilename"`,
- "dir": `"etc"`,
- "src": `select({
- "//build/bazel/platforms/arch:arm": "armSrc",
- "//build/bazel/product_config/config_settings:native_coverage-arm": "nativeCoverageArmSrc",
- "//conditions:default": None,
- })`,
- })}})
-}
-
-func TestPrebuiltEtcProductVariableError(t *testing.T) {
- runPrebuiltEtcTestCase(t, Bp2buildTestCase{
- Description: "",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc {
- name: "foo",
- filename: "fooFilename",
- arch: {
- arm: {
- src: "armSrc",
- },
- },
- product_variables: {
- native_coverage: {
- src: "nativeCoverageArmSrc",
- },
- },
-}`,
- ExpectedErr: fmt.Errorf("label attribute could not be collapsed"),
- })
-}
-
-func TestPrebuiltEtcNoConversionIfSrcEqualsName(t *testing.T) {
- runPrebuiltEtcTestCase(t, Bp2buildTestCase{
- Description: "",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc {
- name: "foo",
- filename: "fooFilename",
- src: "foo",
-}`,
- ExpectedBazelTargets: []string{},
- })
-}
diff --git a/bp2build/python_binary_conversion_test.go b/bp2build/python_binary_conversion_test.go
deleted file mode 100644
index 1b538d0..0000000
--- a/bp2build/python_binary_conversion_test.go
+++ /dev/null
@@ -1,319 +0,0 @@
-package bp2build
-
-import (
- "testing"
-
- "android/soong/android"
- "android/soong/genrule"
- "android/soong/python"
-)
-
-func runBp2BuildTestCaseWithPythonLibraries(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("python_library", python.PythonLibraryFactory)
- ctx.RegisterModuleType("python_library_host", python.PythonLibraryHostFactory)
- ctx.RegisterModuleType("genrule", genrule.GenRuleFactory)
- ctx.RegisterModuleType("python_defaults", python.DefaultsFactory)
- }, tc)
-}
-
-func TestPythonBinaryHostSimple(t *testing.T) {
- runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
- Description: "simple python_binary_host converts to a native py_binary",
- ModuleTypeUnderTest: "python_binary_host",
- ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
- Filesystem: map[string]string{
- "a.py": "",
- "b/c.py": "",
- "b/d.py": "",
- "b/e.py": "",
- "files/data.txt": "",
- },
- Blueprint: `python_binary_host {
- name: "foo",
- main: "a.py",
- srcs: ["**/*.py"],
- exclude_srcs: ["b/e.py"],
- data: ["files/data.txt",],
- libs: ["bar"],
- bazel_module: { bp2build_available: true },
-}
- python_library_host {
- name: "bar",
- srcs: ["b/e.py"],
- bazel_module: { bp2build_available: false },
- }`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("py_binary", "foo", AttrNameToString{
- "data": `["files/data.txt"]`,
- "deps": `[":bar"]`,
- "main": `"a.py"`,
- "imports": `["."]`,
- "srcs": `[
- "a.py",
- "b/c.py",
- "b/d.py",
- ]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestPythonBinaryHostPy2(t *testing.T) {
- RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{
- Description: "py2 python_binary_host",
- ModuleTypeUnderTest: "python_binary_host",
- ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
- Blueprint: `python_binary_host {
- name: "foo",
- srcs: ["a.py"],
- version: {
- py2: {
- enabled: true,
- },
- py3: {
- enabled: false,
- },
- },
-
- bazel_module: { bp2build_available: true },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("py_binary", "foo", AttrNameToString{
- "python_version": `"PY2"`,
- "imports": `["."]`,
- "srcs": `["a.py"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestPythonBinaryHostPy3(t *testing.T) {
- RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{
- Description: "py3 python_binary_host",
- ModuleTypeUnderTest: "python_binary_host",
- ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
- Blueprint: `python_binary_host {
- name: "foo",
- srcs: ["a.py"],
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- },
- },
-
- bazel_module: { bp2build_available: true },
-}
-`,
- ExpectedBazelTargets: []string{
- // python_version is PY3 by default.
- MakeBazelTarget("py_binary", "foo", AttrNameToString{
- "imports": `["."]`,
- "srcs": `["a.py"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestPythonBinaryHostArchVariance(t *testing.T) {
- RunBp2BuildTestCaseSimple(t, Bp2buildTestCase{
- Description: "test arch variants",
- ModuleTypeUnderTest: "python_binary_host",
- ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
- Filesystem: map[string]string{
- "dir/arm.py": "",
- "dir/x86.py": "",
- },
- Blueprint: `python_binary_host {
- name: "foo-arm",
- arch: {
- arm: {
- srcs: ["arm.py"],
- },
- x86: {
- srcs: ["x86.py"],
- },
- },
- }`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("py_binary", "foo-arm", AttrNameToString{
- "imports": `["."]`,
- "srcs": `select({
- "//build/bazel/platforms/arch:arm": ["arm.py"],
- "//build/bazel/platforms/arch:x86": ["x86.py"],
- "//conditions:default": [],
- })`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestPythonBinaryMainIsNotSpecified(t *testing.T) {
- runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
- Description: "python_binary_host main label in same package",
- ModuleTypeUnderTest: "python_binary_host",
- ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
- Blueprint: `python_binary_host {
- name: "foo",
- bazel_module: { bp2build_available: true },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("py_binary", "foo", AttrNameToString{
- "imports": `["."]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestPythonBinaryMainIsLabel(t *testing.T) {
- runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
- Description: "python_binary_host main label in same package",
- ModuleTypeUnderTest: "python_binary_host",
- ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
- Blueprint: `python_binary_host {
- name: "foo",
- main: ":a",
- bazel_module: { bp2build_available: true },
-}
-
-genrule {
- name: "a",
- bazel_module: { bp2build_available: false },
-}
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("py_binary", "foo", AttrNameToString{
- "main": `":a"`,
- "imports": `["."]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestPythonBinaryMainIsSubpackageFile(t *testing.T) {
- runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
- Description: "python_binary_host main is subpackage file",
- ModuleTypeUnderTest: "python_binary_host",
- ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
- Filesystem: map[string]string{
- "a/Android.bp": "",
- "a/b.py": "",
- },
- Blueprint: `python_binary_host {
- name: "foo",
- main: "a/b.py",
- bazel_module: { bp2build_available: true },
-}
-
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("py_binary", "foo", AttrNameToString{
- "main": `"//a:b.py"`,
- "imports": `["."]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestPythonBinaryMainIsSubDirFile(t *testing.T) {
- runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
- Description: "python_binary_host main is file in sub directory that is not Bazel package",
- ModuleTypeUnderTest: "python_binary_host",
- ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
- Filesystem: map[string]string{
- "a/b.py": "",
- },
- Blueprint: `python_binary_host {
- name: "foo",
- main: "a/b.py",
- bazel_module: { bp2build_available: true },
-}
-
-`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("py_binary", "foo", AttrNameToString{
- "main": `"a/b.py"`,
- "imports": `["."]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
-
-func TestPythonBinaryDuplicatesInRequired(t *testing.T) {
- runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
- Description: "python_binary_host duplicates in required attribute of the module and its defaults",
- ModuleTypeUnderTest: "python_binary_host",
- ModuleTypeUnderTestFactory: python.PythonBinaryHostFactory,
- Blueprint: `python_binary_host {
- name: "foo",
- main: "a.py",
- defaults: ["d"],
- required: [
- "r1",
- ],
- bazel_module: { bp2build_available: true },
-}
-
-python_defaults {
- name: "d",
- required: [
- "r1",
- "r2",
- ],
-}` + simpleModuleDoNotConvertBp2build("genrule", "r1") +
- simpleModuleDoNotConvertBp2build("genrule", "r2"),
-
- ExpectedBazelTargets: []string{
- MakeBazelTarget("py_binary", "foo", AttrNameToString{
- "main": `"a.py"`,
- "imports": `["."]`,
- "data": `[
- ":r1",
- ":r2",
- ]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
diff --git a/bp2build/python_library_conversion_test.go b/bp2build/python_library_conversion_test.go
deleted file mode 100644
index 595acd2..0000000
--- a/bp2build/python_library_conversion_test.go
+++ /dev/null
@@ -1,390 +0,0 @@
-package bp2build
-
-import (
- "fmt"
- "strings"
- "testing"
-
- "android/soong/android"
- "android/soong/python"
-)
-
-// TODO(alexmarquez): Should be lifted into a generic Bp2Build file
-type PythonLibBp2Build func(ctx android.TopDownMutatorContext)
-
-type pythonLibBp2BuildTestCase struct {
- description string
- filesystem map[string]string
- blueprint string
- expectedBazelTargets []testBazelTarget
- dir string
- expectedError error
-}
-
-func convertPythonLibTestCaseToBp2build_Host(tc pythonLibBp2BuildTestCase) Bp2buildTestCase {
- for i := range tc.expectedBazelTargets {
- tc.expectedBazelTargets[i].attrs["target_compatible_with"] = `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`
- }
-
- return convertPythonLibTestCaseToBp2build(tc)
-}
-
-func convertPythonLibTestCaseToBp2build(tc pythonLibBp2BuildTestCase) Bp2buildTestCase {
- var bp2BuildTargets []string
- for _, t := range tc.expectedBazelTargets {
- bp2BuildTargets = append(bp2BuildTargets, MakeBazelTarget(t.typ, t.name, t.attrs))
- }
- // Copy the filesystem so that we can change stuff in it later without it
- // affecting the original pythonLibBp2BuildTestCase
- filesystemCopy := make(map[string]string)
- for k, v := range tc.filesystem {
- filesystemCopy[k] = v
- }
- return Bp2buildTestCase{
- Description: tc.description,
- Filesystem: filesystemCopy,
- Blueprint: tc.blueprint,
- ExpectedBazelTargets: bp2BuildTargets,
- Dir: tc.dir,
- ExpectedErr: tc.expectedError,
- }
-}
-
-func runPythonLibraryTestCase(t *testing.T, tc pythonLibBp2BuildTestCase) {
- t.Helper()
- testCase := convertPythonLibTestCaseToBp2build(tc)
- testCase.Description = fmt.Sprintf(testCase.Description, "python_library")
- testCase.Blueprint = fmt.Sprintf(testCase.Blueprint, "python_library")
- for name, contents := range testCase.Filesystem {
- if strings.HasSuffix(name, "Android.bp") {
- testCase.Filesystem[name] = fmt.Sprintf(contents, "python_library")
- }
- }
- testCase.ModuleTypeUnderTest = "python_library"
- testCase.ModuleTypeUnderTestFactory = python.PythonLibraryFactory
-
- RunBp2BuildTestCaseSimple(t, testCase)
-}
-
-func runPythonLibraryHostTestCase(t *testing.T, tc pythonLibBp2BuildTestCase) {
- t.Helper()
- testCase := convertPythonLibTestCaseToBp2build_Host(tc)
- testCase.Description = fmt.Sprintf(testCase.Description, "python_library_host")
- testCase.Blueprint = fmt.Sprintf(testCase.Blueprint, "python_library_host")
- for name, contents := range testCase.Filesystem {
- if strings.HasSuffix(name, "Android.bp") {
- testCase.Filesystem[name] = fmt.Sprintf(contents, "python_library_host")
- }
- }
- testCase.ModuleTypeUnderTest = "python_library_host"
- testCase.ModuleTypeUnderTestFactory = python.PythonLibraryHostFactory
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("python_library", python.PythonLibraryFactory)
- },
- testCase)
-}
-
-func runPythonLibraryTestCases(t *testing.T, tc pythonLibBp2BuildTestCase) {
- t.Helper()
- runPythonLibraryTestCase(t, tc)
- runPythonLibraryHostTestCase(t, tc)
-}
-
-func TestSimplePythonLib(t *testing.T) {
- testCases := []pythonLibBp2BuildTestCase{
- {
- description: "simple %s converts to a native py_library",
- filesystem: map[string]string{
- "a.py": "",
- "b/c.py": "",
- "b/d.py": "",
- "b/e.py": "",
- "files/data.txt": "",
- },
- blueprint: `%s {
- name: "foo",
- srcs: ["**/*.py"],
- exclude_srcs: ["b/e.py"],
- data: ["files/data.txt",],
- libs: ["bar"],
- bazel_module: { bp2build_available: true },
-}
- python_library {
- name: "bar",
- srcs: ["b/e.py"],
- bazel_module: { bp2build_available: false },
- }`,
- expectedBazelTargets: []testBazelTarget{
- {
- typ: "py_library",
- name: "foo",
- attrs: AttrNameToString{
- "data": `["files/data.txt"]`,
- "deps": `[":bar"]`,
- "srcs": `[
- "a.py",
- "b/c.py",
- "b/d.py",
- ]`,
- "srcs_version": `"PY3"`,
- "imports": `["."]`,
- },
- },
- },
- },
- {
- description: "py2 %s converts to a native py_library",
- blueprint: `%s {
- name: "foo",
- srcs: ["a.py"],
- version: {
- py2: {
- enabled: true,
- },
- py3: {
- enabled: false,
- },
- },
-
- bazel_module: { bp2build_available: true },
-}`,
- expectedBazelTargets: []testBazelTarget{
- {
- typ: "py_library",
- name: "foo",
- attrs: AttrNameToString{
- "srcs": `["a.py"]`,
- "srcs_version": `"PY2"`,
- "imports": `["."]`,
- },
- },
- },
- },
- {
- description: "py3 %s converts to a native py_library",
- blueprint: `%s {
- name: "foo",
- srcs: ["a.py"],
- version: {
- py2: {
- enabled: false,
- },
- py3: {
- enabled: true,
- },
- },
-
- bazel_module: { bp2build_available: true },
-}`,
- expectedBazelTargets: []testBazelTarget{
- {
- typ: "py_library",
- name: "foo",
- attrs: AttrNameToString{
- "srcs": `["a.py"]`,
- "srcs_version": `"PY3"`,
- "imports": `["."]`,
- },
- },
- },
- },
- {
- description: "py2&3 %s converts to a native py_library",
- blueprint: `%s {
- name: "foo",
- srcs: ["a.py"],
- version: {
- py2: {
- enabled: true,
- },
- py3: {
- enabled: true,
- },
- },
-
- bazel_module: { bp2build_available: true },
-}`,
- expectedBazelTargets: []testBazelTarget{
- {
- // srcs_version is PY2ANDPY3 by default.
- typ: "py_library",
- name: "foo",
- attrs: AttrNameToString{
- "srcs": `["a.py"]`,
- "imports": `["."]`,
- },
- },
- },
- },
- {
- description: "%s: pkg_path in a subdirectory of the same name converts correctly",
- dir: "mylib/subpackage",
- filesystem: map[string]string{
- "mylib/subpackage/a.py": "",
- "mylib/subpackage/Android.bp": `%s {
- name: "foo",
- srcs: ["a.py"],
- pkg_path: "mylib/subpackage",
-
- bazel_module: { bp2build_available: true },
- }`,
- },
- blueprint: `%s {name: "bar"}`,
- expectedBazelTargets: []testBazelTarget{
- {
- // srcs_version is PY2ANDPY3 by default.
- typ: "py_library",
- name: "foo",
- attrs: AttrNameToString{
- "srcs": `["a.py"]`,
- "imports": `["../.."]`,
- "srcs_version": `"PY3"`,
- },
- },
- },
- },
- {
- description: "%s: pkg_path in a subdirectory of a different name fails",
- dir: "mylib/subpackage",
- filesystem: map[string]string{
- "mylib/subpackage/a.py": "",
- "mylib/subpackage/Android.bp": `%s {
- name: "foo",
- srcs: ["a.py"],
- pkg_path: "mylib/subpackage2",
- bazel_module: { bp2build_available: true },
- }`,
- },
- blueprint: `%s {name: "bar"}`,
- expectedError: fmt.Errorf("Currently, bp2build only supports pkg_paths that are the same as the folders the Android.bp file is in."),
- },
- }
-
- for _, tc := range testCases {
- t.Run(tc.description, func(t *testing.T) {
- runPythonLibraryTestCases(t, tc)
- })
- }
-}
-
-func TestPythonArchVariance(t *testing.T) {
- runPythonLibraryTestCases(t, pythonLibBp2BuildTestCase{
- description: "test %s arch variants",
- filesystem: map[string]string{
- "dir/arm.py": "",
- "dir/x86.py": "",
- },
- blueprint: `%s {
- name: "foo",
- arch: {
- arm: {
- srcs: ["arm.py"],
- },
- x86: {
- srcs: ["x86.py"],
- },
- },
- }`,
- expectedBazelTargets: []testBazelTarget{
- {
- typ: "py_library",
- name: "foo",
- attrs: AttrNameToString{
- "srcs": `select({
- "//build/bazel/platforms/arch:arm": ["arm.py"],
- "//build/bazel/platforms/arch:x86": ["x86.py"],
- "//conditions:default": [],
- })`,
- "srcs_version": `"PY3"`,
- "imports": `["."]`,
- },
- },
- },
- })
-}
-
-func TestPythonLibraryWithProtobufs(t *testing.T) {
- runPythonLibraryTestCases(t, pythonLibBp2BuildTestCase{
- description: "test %s protobuf",
- filesystem: map[string]string{
- "dir/mylib.py": "",
- "dir/myproto.proto": "",
- },
- blueprint: `%s {
- name: "foo",
- srcs: [
- "dir/mylib.py",
- "dir/myproto.proto",
- ],
- }`,
- expectedBazelTargets: []testBazelTarget{
- {
- typ: "proto_library",
- name: "foo_proto",
- attrs: AttrNameToString{
- "srcs": `["dir/myproto.proto"]`,
- },
- },
- {
- typ: "py_proto_library",
- name: "foo_py_proto",
- attrs: AttrNameToString{
- "deps": `[":foo_proto"]`,
- },
- },
- {
- typ: "py_library",
- name: "foo",
- attrs: AttrNameToString{
- "srcs": `["dir/mylib.py"]`,
- "srcs_version": `"PY3"`,
- "imports": `["."]`,
- "deps": `[":foo_py_proto"]`,
- },
- },
- },
- })
-}
-
-func TestPythonLibraryWithProtobufsAndPkgPath(t *testing.T) {
- t.Parallel()
- runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
- Description: "test python_library protobuf with pkg_path",
- Filesystem: map[string]string{
- "dir/foo.proto": "",
- "dir/bar.proto": "", // bar contains "import dir/foo.proto"
- "dir/Android.bp": `
-python_library {
- name: "foo",
- pkg_path: "dir",
- srcs: [
- "foo.proto",
- "bar.proto",
- ],
- bazel_module: {bp2build_available: true},
-}`,
- },
- Dir: "dir",
- ExpectedBazelTargets: []string{
- MakeBazelTarget("proto_library", "foo_proto", AttrNameToString{
- "import_prefix": `"dir"`,
- "strip_import_prefix": `""`,
- "srcs": `[
- "foo.proto",
- "bar.proto",
- ]`,
- }),
- MakeBazelTarget("py_proto_library", "foo_py_proto", AttrNameToString{
- "deps": `[":foo_proto"]`,
- }),
- MakeBazelTarget("py_library", "foo", AttrNameToString{
- "srcs_version": `"PY3"`,
- "imports": `[".."]`,
- "deps": `[":foo_py_proto"]`,
- }),
- },
- })
-}
diff --git a/bp2build/python_test_conversion_test.go b/bp2build/python_test_conversion_test.go
deleted file mode 100644
index 4ff1fa1..0000000
--- a/bp2build/python_test_conversion_test.go
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2023 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 (
- "android/soong/python"
- "testing"
-)
-
-func TestPythonTestHostSimple(t *testing.T) {
- runBp2BuildTestCaseWithPythonLibraries(t, Bp2buildTestCase{
- Description: "simple python_test_host converts to a native py_test",
- ModuleTypeUnderTest: "python_test_host",
- ModuleTypeUnderTestFactory: python.PythonTestHostFactory,
- Filesystem: map[string]string{
- "a.py": "",
- "b/c.py": "",
- "b/d.py": "",
- "b/e.py": "",
- "files/data.txt": "",
- },
- Blueprint: `python_test_host {
- name: "foo",
- main: "a.py",
- srcs: ["**/*.py"],
- exclude_srcs: ["b/e.py"],
- data: ["files/data.txt",],
- libs: ["bar"],
- bazel_module: { bp2build_available: true },
-}
- python_library_host {
- name: "bar",
- srcs: ["b/e.py"],
- bazel_module: { bp2build_available: false },
- }`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("py_test", "foo", AttrNameToString{
- "data": `["files/data.txt"]`,
- "deps": `[":bar"]`,
- "main": `"a.py"`,
- "imports": `["."]`,
- "srcs": `[
- "a.py",
- "b/c.py",
- "b/d.py",
- ]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- }),
- },
- })
-}
diff --git a/bp2build/rust_binary_conversion_test.go b/bp2build/rust_binary_conversion_test.go
deleted file mode 100644
index a5abbdb..0000000
--- a/bp2build/rust_binary_conversion_test.go
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright 2023 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 (
- "android/soong/android"
- "android/soong/rust"
- "testing"
-)
-
-func runRustBinaryTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, registerRustBinaryModuleTypes, tc)
-}
-
-func registerRustBinaryModuleTypes(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("rust_binary_host", rust.RustBinaryHostFactory)
- ctx.RegisterModuleType("rust_library_host", rust.RustLibraryHostFactory)
- ctx.RegisterModuleType("rust_proc_macro", rust.ProcMacroFactory)
-
-}
-
-func TestRustBinaryHost(t *testing.T) {
- runRustBinaryTestCase(t, Bp2buildTestCase{
- Dir: "external/rust/crates/foo",
- Blueprint: "",
- Filesystem: map[string]string{
- "external/rust/crates/foo/src/lib.rs": "",
- "external/rust/crates/foo/src/helper.rs": "",
- "external/rust/crates/foo/Android.bp": `
-rust_binary_host {
- name: "libfoo",
- crate_name: "foo",
- srcs: ["src/main.rs"],
- edition: "2021",
- features: ["bah-enabled"],
- cfgs: ["baz"],
- rustlibs: ["libbar"],
- proc_macros: ["libbah"],
- bazel_module: { bp2build_available: true },
-}
-`,
- "external/rust/crates/bar/Android.bp": `
-rust_library_host {
- name: "libbar",
- crate_name: "bar",
- srcs: ["src/lib.rs"],
- bazel_module: { bp2build_available: true },
-}
-`,
- "external/rust/crates/bah/Android.bp": `
-rust_proc_macro {
- name: "libbah",
- crate_name: "bah",
- srcs: ["src/lib.rs"],
- bazel_module: { bp2build_available: true },
-}
-`,
- },
- ExpectedBazelTargets: []string{
- makeBazelTargetHostOrDevice("rust_binary", "libfoo", AttrNameToString{
- "crate_name": `"foo"`,
- "srcs": `[
- "src/helper.rs",
- "src/lib.rs",
- ]`,
- "deps": `["//external/rust/crates/bar:libbar"]`,
- "proc_macro_deps": `["//external/rust/crates/bah:libbah"]`,
- "edition": `"2021"`,
- "crate_features": `["bah-enabled"]`,
- "rustc_flags": `["--cfg=baz"]`,
- }, android.HostSupported),
- },
- },
- )
-}
diff --git a/bp2build/rust_library_conversion_test.go b/bp2build/rust_library_conversion_test.go
deleted file mode 100644
index 0bc80df..0000000
--- a/bp2build/rust_library_conversion_test.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2023 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 (
- "android/soong/android"
- "android/soong/rust"
- "testing"
-)
-
-func runRustLibraryTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, registerRustLibraryModuleTypes, tc)
-}
-
-func registerRustLibraryModuleTypes(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("rust_library", rust.RustLibraryFactory)
- ctx.RegisterModuleType("rust_library_host", rust.RustLibraryHostFactory)
-}
-
-func TestLibProtobuf(t *testing.T) {
- runRustLibraryTestCase(t, Bp2buildTestCase{
- Dir: "external/rust/crates/foo",
- Blueprint: "",
- Filesystem: map[string]string{
- "external/rust/crates/foo/src/lib.rs": "",
- "external/rust/crates/foo/Android.bp": `
-rust_library_host {
- name: "libprotobuf",
- crate_name: "protobuf",
- srcs: ["src/lib.rs"],
- bazel_module: { bp2build_available: true },
-}
-`,
- },
- ExpectedBazelTargets: []string{
- // TODO(b/290790800): Remove the restriction when rust toolchain for android is implemented
- makeBazelTargetHostOrDevice("rust_library", "libprotobuf", AttrNameToString{
- "crate_name": `"protobuf"`,
- "srcs": `["src/lib.rs"]`,
- "deps": `[":libprotobuf_build_script"]`,
- }, android.HostSupported),
- makeBazelTargetHostOrDevice("cargo_build_script", "libprotobuf_build_script", AttrNameToString{
- "srcs": `["build.rs"]`,
- }, android.HostSupported),
- },
- },
- )
-}
-
-func TestRustLibrary(t *testing.T) {
- expectedAttrs := AttrNameToString{
- "crate_name": `"foo"`,
- "srcs": `[
- "src/helper.rs",
- "src/lib.rs",
- ]`,
- "crate_features": `["bah-enabled"]`,
- "edition": `"2021"`,
- "rustc_flags": `["--cfg=baz"]`,
- }
-
- runRustLibraryTestCase(t, Bp2buildTestCase{
- Dir: "external/rust/crates/foo",
- Blueprint: "",
- Filesystem: map[string]string{
- "external/rust/crates/foo/src/lib.rs": "",
- "external/rust/crates/foo/src/helper.rs": "",
- "external/rust/crates/foo/Android.bp": `
-rust_library {
- name: "libfoo",
- crate_name: "foo",
- host_supported: true,
- srcs: ["src/lib.rs"],
- edition: "2021",
- features: ["bah-enabled"],
- cfgs: ["baz"],
- bazel_module: { bp2build_available: true },
-}
-rust_library_host {
- name: "libfoo_host",
- crate_name: "foo",
- srcs: ["src/lib.rs"],
- edition: "2021",
- features: ["bah-enabled"],
- cfgs: ["baz"],
- bazel_module: { bp2build_available: true },
-}
-`,
- },
- ExpectedBazelTargets: []string{
- // TODO(b/290790800): Remove the restriction when rust toolchain for android is implemented
- makeBazelTargetHostOrDevice("rust_library", "libfoo", expectedAttrs, android.HostSupported),
- makeBazelTargetHostOrDevice("rust_library", "libfoo_host", expectedAttrs, android.HostSupported),
- },
- },
- )
-}
diff --git a/bp2build/rust_proc_macro_conversion_test.go b/bp2build/rust_proc_macro_conversion_test.go
deleted file mode 100644
index 7df37ec..0000000
--- a/bp2build/rust_proc_macro_conversion_test.go
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2023 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 (
- "android/soong/android"
- "android/soong/rust"
- "testing"
-)
-
-func rustRustProcMacroTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, registerRustProcMacroModuleTypes, tc)
-}
-
-func registerRustProcMacroModuleTypes(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("rust_library_host", rust.RustLibraryHostFactory)
- ctx.RegisterModuleType("rust_proc_macro", rust.ProcMacroFactory)
-}
-
-func TestRustProcMacroLibrary(t *testing.T) {
- rustRustProcMacroTestCase(t, Bp2buildTestCase{
- Dir: "external/rust/crates/foo",
- Blueprint: "",
- Filesystem: map[string]string{
- "external/rust/crates/foo/src/lib.rs": "",
- "external/rust/crates/foo/src/helper.rs": "",
- "external/rust/crates/foo/Android.bp": `
-rust_proc_macro {
- name: "libfoo",
- crate_name: "foo",
- srcs: ["src/lib.rs"],
- edition: "2021",
- features: ["bah-enabled"],
- cfgs: ["baz"],
- rustlibs: ["libbar"],
- bazel_module: { bp2build_available: true },
-}
-`,
- "external/rust/crates/bar/src/lib.rs": "",
- "external/rust/crates/bar/Android.bp": `
-rust_library_host {
- name: "libbar",
- crate_name: "bar",
- srcs: ["src/lib.rs"],
- bazel_module: { bp2build_available: true },
-}`,
- },
- ExpectedBazelTargets: []string{
- makeBazelTargetHostOrDevice("rust_proc_macro", "libfoo", AttrNameToString{
- "crate_name": `"foo"`,
- "srcs": `[
- "src/helper.rs",
- "src/lib.rs",
- ]`,
- "crate_features": `["bah-enabled"]`,
- "edition": `"2021"`,
- "rustc_flags": `["--cfg=baz"]`,
- "deps": `["//external/rust/crates/bar:libbar"]`,
- }, android.HostSupported),
- },
- },
- )
-}
diff --git a/bp2build/rust_protobuf_conversion_test.go b/bp2build/rust_protobuf_conversion_test.go
deleted file mode 100644
index cf256aa..0000000
--- a/bp2build/rust_protobuf_conversion_test.go
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2023 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 (
- "android/soong/android"
- "android/soong/rust"
- "testing"
-)
-
-func runRustProtobufTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, registerRustProtobufModuleTypes, tc)
-}
-
-func registerRustProtobufModuleTypes(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("rust_protobuf_host", rust.RustProtobufHostFactory)
-
-}
-
-func TestRustProtobufHostTestCase(t *testing.T) {
- runRustProtobufTestCase(t, Bp2buildTestCase{
- Dir: "external/rust/crates/foo",
- Blueprint: "",
- Filesystem: map[string]string{
- "external/rust/crates/foo/src/lib.rs": "",
- "external/rust/crates/foo/src/helper.rs": "",
- "external/rust/crates/foo/Android.bp": `
-rust_protobuf_host {
- name: "libfoo",
- crate_name: "foo",
- protos: ["src/foo.proto"],
- bazel_module: { bp2build_available: true },
-}
-`,
- },
- ExpectedBazelTargets: []string{
- makeBazelTargetHostOrDevice("proto_library", "libfoo_proto", AttrNameToString{
- "srcs": `["src/foo.proto"]`,
- }, android.HostSupported),
- makeBazelTargetHostOrDevice("rust_proto_library", "libfoo", AttrNameToString{
- "crate_name": `"foo"`,
- "deps": `[":libfoo_proto"]`,
- }, android.HostSupported),
- },
- },
- )
-}
diff --git a/bp2build/sh_conversion_test.go b/bp2build/sh_conversion_test.go
deleted file mode 100644
index 92b3a65..0000000
--- a/bp2build/sh_conversion_test.go
+++ /dev/null
@@ -1,92 +0,0 @@
-// 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
-
-import (
- "testing"
-
- "android/soong/android"
- "android/soong/sh"
-)
-
-func TestShBinaryLoadStatement(t *testing.T) {
- testCases := []struct {
- bazelTargets BazelTargets
- expectedLoadStatements string
- }{
- {
- bazelTargets: BazelTargets{
- BazelTarget{
- name: "sh_binary_target",
- ruleClass: "sh_binary",
- // Note: no bzlLoadLocation for native rules
- // TODO(ruperts): Could open source the existing, experimental Starlark sh_ rules?
- },
- },
- expectedLoadStatements: ``,
- },
- }
-
- for _, testCase := range testCases {
- actual := testCase.bazelTargets.LoadStatements()
- expected := testCase.expectedLoadStatements
- if actual != expected {
- t.Fatalf("Expected load statements to be %s, got %s", expected, actual)
- }
- }
-}
-
-func runShBinaryTestCase(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, tc)
-}
-
-func TestShBinarySimple(t *testing.T) {
- runShBinaryTestCase(t, Bp2buildTestCase{
- Description: "sh_binary test",
- ModuleTypeUnderTest: "sh_binary",
- ModuleTypeUnderTestFactory: sh.ShBinaryFactory,
- Blueprint: `sh_binary {
- name: "foo",
- src: "foo.sh",
- filename: "foo.exe",
- sub_dir: "sub",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("sh_binary", "foo", AttrNameToString{
- "srcs": `["foo.sh"]`,
- "filename": `"foo.exe"`,
- "sub_dir": `"sub"`,
- })},
- })
-}
-
-func TestShBinaryDefaults(t *testing.T) {
- runShBinaryTestCase(t, Bp2buildTestCase{
- Description: "sh_binary test",
- ModuleTypeUnderTest: "sh_binary",
- ModuleTypeUnderTestFactory: sh.ShBinaryFactory,
- Blueprint: `sh_binary {
- name: "foo",
- src: "foo.sh",
- bazel_module: { bp2build_available: true },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("sh_binary", "foo", AttrNameToString{
- "srcs": `["foo.sh"]`,
- })},
- })
-}
diff --git a/bp2build/sh_test_conversion_test.go b/bp2build/sh_test_conversion_test.go
deleted file mode 100644
index e99d566..0000000
--- a/bp2build/sh_test_conversion_test.go
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright 2023 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 (
- "testing"
-
- "android/soong/android"
- "android/soong/sh"
-)
-
-func TestShTestSimple(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
- Description: "sh_test test",
- ModuleTypeUnderTest: "sh_test",
- ModuleTypeUnderTestFactory: sh.ShTestFactory,
- Blueprint: `sh_test{
- name: "sts-rootcanal-sidebins",
- src: "empty.sh",
- test_suites: [
- "sts",
- "sts-lite",
- ],
- data_bins: [
- "android.hardware.bluetooth@1.1-service.sim",
- "android.hardware.bluetooth@1.1-impl-sim"
- ],
- data: ["android.hardware.bluetooth@1.1-service.sim.rc"],
- data_libs: ["libc++","libcrypto"],
- test_config: "art-gtests-target-install-apex.xml",
- test_config_template: ":art-run-test-target-template",
- auto_gen_config: false,
- test_options:{tags: ["no-remote"],
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("sh_test", "sts-rootcanal-sidebins", AttrNameToString{
- "srcs": `["empty.sh"]`,
- "data": `[
- "android.hardware.bluetooth@1.1-service.sim.rc",
- "android.hardware.bluetooth@1.1-service.sim",
- "android.hardware.bluetooth@1.1-impl-sim",
- "libc++",
- "libcrypto",
- ]`,
- "test_config": `"art-gtests-target-install-apex.xml"`,
- "test_config_template": `":art-run-test-target-template"`,
- "auto_gen_config": "False",
- "tags": `["no-remote"]`,
- })},
- })
-}
-
-func TestShTestHostSimple(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
- Description: "sh_test_host test",
- ModuleTypeUnderTest: "sh_test_host",
- ModuleTypeUnderTestFactory: sh.ShTestHostFactory,
- Blueprint: `sh_test_host{
- name: "sts-rootcanal-sidebins",
- src: "empty.sh",
- test_suites: [
- "sts",
- "sts-lite",
- ],
- data_bins: [
- "android.hardware.bluetooth@1.1-service.sim",
- "android.hardware.bluetooth@1.1-impl-sim"
- ],
- data: ["android.hardware.bluetooth@1.1-service.sim.rc"],
- data_libs: ["libc++","libcrypto"],
- test_config: "art-gtests-target-install-apex.xml",
- test_config_template: ":art-run-test-target-template",
- auto_gen_config: false,
- test_options:{tags: ["no-remote"],
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("sh_test", "sts-rootcanal-sidebins", AttrNameToString{
- "srcs": `["empty.sh"]`,
- "data": `[
- "android.hardware.bluetooth@1.1-service.sim.rc",
- "android.hardware.bluetooth@1.1-service.sim",
- "android.hardware.bluetooth@1.1-impl-sim",
- "libc++",
- "libcrypto",
- ]`,
- "tags": `["no-remote"]`,
- "test_config": `"art-gtests-target-install-apex.xml"`,
- "test_config_template": `":art-run-test-target-template"`,
- "auto_gen_config": "False",
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- })},
- })
-}
-
-func TestShTestSimpleUnset(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
- Description: "sh_test test",
- ModuleTypeUnderTest: "sh_test",
- ModuleTypeUnderTestFactory: sh.ShTestFactory,
- Blueprint: `sh_test{
- name: "sts-rootcanal-sidebins",
- src: "empty.sh",
- test_suites: [
- "sts",
- "sts-lite",
- ],
- data_bins: [
- "android.hardware.bluetooth@1.1-service.sim",
- "android.hardware.bluetooth@1.1-impl-sim"
- ],
- data: ["android.hardware.bluetooth@1.1-service.sim.rc"],
- data_libs: ["libc++","libcrypto"],
- test_options:{tags: ["no-remote"],
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("sh_test", "sts-rootcanal-sidebins", AttrNameToString{
- "srcs": `["empty.sh"]`,
- "data": `[
- "android.hardware.bluetooth@1.1-service.sim.rc",
- "android.hardware.bluetooth@1.1-service.sim",
- "android.hardware.bluetooth@1.1-impl-sim",
- "libc++",
- "libcrypto",
- ]`,
- "tags": `["no-remote"]`,
- })},
- })
-}
-
-func TestShTestHostSimpleUnset(t *testing.T) {
- RunBp2BuildTestCase(t, func(ctx android.RegistrationContext) {}, Bp2buildTestCase{
- Description: "sh_test_host test",
- ModuleTypeUnderTest: "sh_test_host",
- ModuleTypeUnderTestFactory: sh.ShTestHostFactory,
- Blueprint: `sh_test_host{
- name: "sts-rootcanal-sidebins",
- src: "empty.sh",
- test_suites: [
- "sts",
- "sts-lite",
- ],
- data_bins: [
- "android.hardware.bluetooth@1.1-service.sim",
- "android.hardware.bluetooth@1.1-impl-sim"
- ],
- data: ["android.hardware.bluetooth@1.1-service.sim.rc"],
- data_libs: ["libc++","libcrypto"],
- test_options:{tags: ["no-remote"],
- },
-}`,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("sh_test", "sts-rootcanal-sidebins", AttrNameToString{
- "srcs": `["empty.sh"]`,
- "data": `[
- "android.hardware.bluetooth@1.1-service.sim.rc",
- "android.hardware.bluetooth@1.1-service.sim",
- "android.hardware.bluetooth@1.1-impl-sim",
- "libc++",
- "libcrypto",
- ]`,
- "tags": `["no-remote"]`,
- "target_compatible_with": `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`,
- })},
- })
-}
diff --git a/bp2build/soong_config_module_type_conversion_test.go b/bp2build/soong_config_module_type_conversion_test.go
deleted file mode 100644
index 8302ce8..0000000
--- a/bp2build/soong_config_module_type_conversion_test.go
+++ /dev/null
@@ -1,1601 +0,0 @@
-// 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
-
-import (
- "android/soong/android"
- "android/soong/cc"
- "fmt"
- "testing"
-)
-
-func runSoongConfigModuleTypeTest(t *testing.T, tc Bp2buildTestCase) {
- t.Helper()
- RunBp2BuildTestCase(t, registerSoongConfigModuleTypes, tc)
-}
-
-func registerSoongConfigModuleTypes(ctx android.RegistrationContext) {
- cc.RegisterCCBuildComponents(ctx)
-
- android.RegisterSoongConfigModuleBuildComponents(ctx)
-
- ctx.RegisterModuleType("cc_library", cc.LibraryFactory)
- ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
-}
-
-func TestErrorInBpFileDoesNotPanic(t *testing.T) {
- bp := `
-soong_config_module_type {
- name: "library_linking_strategy_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "ANDROID",
- variables: ["library_linking_strategy"],
- properties: [
- "shared_libs",
- "static_libs",
- ],
-}
-`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - generates selects for library_linking_strategy",
- ModuleTypeUnderTest: "cc_binary",
- ModuleTypeUnderTestFactory: cc.BinaryFactory,
- Blueprint: bp,
- ExpectedErr: fmt.Errorf(`unknown variable "library_linking_strategy" in module type "library_linking_strategy_cc_defaults`),
- })
-}
-
-func TestSoongConfigModuleType(t *testing.T) {
- bp := `
-soong_config_module_type {
- name: "custom_cc_library_static",
- module_type: "cc_library_static",
- config_namespace: "acme",
- bool_variables: ["feature1"],
- properties: ["cflags"],
-}
-
-custom_cc_library_static {
- name: "foo",
- bazel_module: { bp2build_available: true },
- host_supported: true,
- soong_config_variables: {
- feature1: {
- conditions_default: {
- cflags: ["-DDEFAULT1"],
- },
- cflags: ["-DFEATURE1"],
- },
- },
-}
-`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - soong_config_module_type is supported in bp2build",
- ModuleTypeUnderTest: "cc_library_static",
- ModuleTypeUnderTestFactory: cc.LibraryStaticFactory,
- Blueprint: bp,
- ExpectedBazelTargets: []string{`cc_library_static(
- name = "foo",
- copts = select({
- "//build/bazel/product_config/config_settings:acme__feature1": ["-DFEATURE1"],
- "//conditions:default": ["-DDEFAULT1"],
- }),
- local_includes = ["."],
-)`}})
-}
-
-func TestSoongConfigModuleTypeImport(t *testing.T) {
- configBp := `
-soong_config_module_type {
- name: "custom_cc_library_static",
- module_type: "cc_library_static",
- config_namespace: "acme",
- bool_variables: ["feature1"],
- properties: ["cflags"],
-}
-`
- bp := `
-soong_config_module_type_import {
- from: "foo/bar/SoongConfig.bp",
- module_types: ["custom_cc_library_static"],
-}
-
-custom_cc_library_static {
- name: "foo",
- bazel_module: { bp2build_available: true },
- host_supported: true,
- soong_config_variables: {
- feature1: {
- conditions_default: {
- cflags: ["-DDEFAULT1"],
- },
- cflags: ["-DFEATURE1"],
- },
- },
-}
-`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - soong_config_module_type_import is supported in bp2build",
- ModuleTypeUnderTest: "cc_library_static",
- ModuleTypeUnderTestFactory: cc.LibraryStaticFactory,
- Filesystem: map[string]string{
- "foo/bar/SoongConfig.bp": configBp,
- },
- Blueprint: bp,
- ExpectedBazelTargets: []string{`cc_library_static(
- name = "foo",
- copts = select({
- "//build/bazel/product_config/config_settings:acme__feature1": ["-DFEATURE1"],
- "//conditions:default": ["-DDEFAULT1"],
- }),
- local_includes = ["."],
-)`}})
-}
-
-func TestSoongConfigModuleType_StringVar(t *testing.T) {
- bp := `
-soong_config_string_variable {
- name: "board",
- values: ["soc_a", "soc_b", "soc_c"],
-}
-
-soong_config_module_type {
- name: "custom_cc_library_static",
- module_type: "cc_library_static",
- config_namespace: "acme",
- variables: ["board"],
- properties: ["cflags"],
-}
-
-custom_cc_library_static {
- name: "foo",
- bazel_module: { bp2build_available: true },
- host_supported: true,
- soong_config_variables: {
- board: {
- soc_a: {
- cflags: ["-DSOC_A"],
- },
- soc_b: {
- cflags: ["-DSOC_B"],
- },
- soc_c: {},
- conditions_default: {
- cflags: ["-DSOC_DEFAULT"]
- },
- },
- },
-}
-`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - generates selects for string vars",
- ModuleTypeUnderTest: "cc_library_static",
- ModuleTypeUnderTestFactory: cc.LibraryStaticFactory,
- Blueprint: bp,
- ExpectedBazelTargets: []string{`cc_library_static(
- name = "foo",
- copts = select({
- "//build/bazel/product_config/config_settings:acme__board__soc_a": ["-DSOC_A"],
- "//build/bazel/product_config/config_settings:acme__board__soc_b": ["-DSOC_B"],
- "//build/bazel/product_config/config_settings:acme__board__soc_c": [],
- "//conditions:default": ["-DSOC_DEFAULT"],
- }),
- local_includes = ["."],
-)`}})
-}
-
-func TestSoongConfigModuleType_MultipleBoolVar_PartialUseNotPanic(t *testing.T) {
- bp := `
-soong_config_bool_variable {
- name: "feature1",
-}
-
-soong_config_bool_variable {
- name: "feature2",
-}
-
-soong_config_module_type {
- name: "custom_cc_library_static",
- module_type: "cc_library_static",
- config_namespace: "acme",
- variables: ["feature1", "feature2",],
- properties: ["cflags"],
-}
-
-custom_cc_library_static {
- name: "foo",
- bazel_module: { bp2build_available: true },
- host_supported: true,
- soong_config_variables: {
- feature1: {
- conditions_default: {
- cflags: ["-DDEFAULT1"],
- },
- cflags: ["-DFEATURE1"],
- },
- },
-}`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - used part of multiple bool variable do not panic",
- ModuleTypeUnderTest: "cc_library_static",
- ModuleTypeUnderTestFactory: cc.LibraryStaticFactory,
- Blueprint: bp,
- ExpectedBazelTargets: []string{`cc_library_static(
- name = "foo",
- copts = select({
- "//build/bazel/product_config/config_settings:acme__feature1": ["-DFEATURE1"],
- "//conditions:default": ["-DDEFAULT1"],
- }),
- local_includes = ["."],
-)`}})
-}
-
-func TestSoongConfigModuleType_StringAndBoolVar(t *testing.T) {
- bp := `
-soong_config_bool_variable {
- name: "feature1",
-}
-
-soong_config_bool_variable {
- name: "feature2",
-}
-
-soong_config_string_variable {
- name: "board",
- values: ["soc_a", "soc_b", "soc_c", "soc_d"],
-}
-
-soong_config_module_type {
- name: "custom_cc_library_static",
- module_type: "cc_library_static",
- config_namespace: "acme",
- variables: ["feature1", "feature2", "board"],
- properties: ["cflags"],
-}
-
-custom_cc_library_static {
- name: "foo",
- bazel_module: { bp2build_available: true },
- host_supported: true,
- soong_config_variables: {
- feature1: {
- conditions_default: {
- cflags: ["-DDEFAULT1"],
- },
- cflags: ["-DFEATURE1"],
- },
- feature2: {
- cflags: ["-DFEATURE2"],
- conditions_default: {
- cflags: ["-DDEFAULT2"],
- },
- },
- board: {
- soc_a: {
- cflags: ["-DSOC_A"],
- },
- soc_b: {
- cflags: ["-DSOC_B"],
- },
- soc_c: {},
- conditions_default: {
- cflags: ["-DSOC_DEFAULT"]
- },
- },
- },
-}`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - generates selects for multiple variable types",
- ModuleTypeUnderTest: "cc_library_static",
- ModuleTypeUnderTestFactory: cc.LibraryStaticFactory,
- Blueprint: bp,
- ExpectedBazelTargets: []string{`cc_library_static(
- name = "foo",
- copts = select({
- "//build/bazel/product_config/config_settings:acme__board__soc_a": ["-DSOC_A"],
- "//build/bazel/product_config/config_settings:acme__board__soc_b": ["-DSOC_B"],
- "//build/bazel/product_config/config_settings:acme__board__soc_c": [],
- "//conditions:default": ["-DSOC_DEFAULT"],
- }) + select({
- "//build/bazel/product_config/config_settings:acme__feature1": ["-DFEATURE1"],
- "//conditions:default": ["-DDEFAULT1"],
- }) + select({
- "//build/bazel/product_config/config_settings:acme__feature2": ["-DFEATURE2"],
- "//conditions:default": ["-DDEFAULT2"],
- }),
- local_includes = ["."],
-)`}})
-}
-
-func TestSoongConfigModuleType_StringVar_LabelListDeps(t *testing.T) {
- bp := `
-soong_config_string_variable {
- name: "board",
- values: ["soc_a", "soc_b", "soc_c", "soc_d"],
-}
-
-soong_config_module_type {
- name: "custom_cc_library_static",
- module_type: "cc_library_static",
- config_namespace: "acme",
- variables: ["board"],
- properties: ["cflags", "static_libs"],
-}
-
-custom_cc_library_static {
- name: "foo",
- bazel_module: { bp2build_available: true },
- host_supported: true,
- soong_config_variables: {
- board: {
- soc_a: {
- cflags: ["-DSOC_A"],
- static_libs: ["soc_a_dep"],
- },
- soc_b: {
- cflags: ["-DSOC_B"],
- static_libs: ["soc_b_dep"],
- },
- soc_c: {},
- conditions_default: {
- cflags: ["-DSOC_DEFAULT"],
- static_libs: ["soc_default_static_dep"],
- },
- },
- },
-}`
-
- otherDeps := `
-cc_library_static { name: "soc_a_dep", bazel_module: { bp2build_available: false } }
-cc_library_static { name: "soc_b_dep", bazel_module: { bp2build_available: false } }
-cc_library_static { name: "soc_default_static_dep", bazel_module: { bp2build_available: false } }
-`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - generates selects for label list attributes",
- ModuleTypeUnderTest: "cc_library_static",
- ModuleTypeUnderTestFactory: cc.LibraryStaticFactory,
- Blueprint: bp,
- Filesystem: map[string]string{
- "foo/bar/Android.bp": otherDeps,
- },
- ExpectedBazelTargets: []string{`cc_library_static(
- name = "foo",
- copts = select({
- "//build/bazel/product_config/config_settings:acme__board__soc_a": ["-DSOC_A"],
- "//build/bazel/product_config/config_settings:acme__board__soc_b": ["-DSOC_B"],
- "//build/bazel/product_config/config_settings:acme__board__soc_c": [],
- "//conditions:default": ["-DSOC_DEFAULT"],
- }),
- implementation_deps = select({
- "//build/bazel/product_config/config_settings:acme__board__soc_a": ["//foo/bar:soc_a_dep"],
- "//build/bazel/product_config/config_settings:acme__board__soc_b": ["//foo/bar:soc_b_dep"],
- "//build/bazel/product_config/config_settings:acme__board__soc_c": [],
- "//conditions:default": ["//foo/bar:soc_default_static_dep"],
- }),
- local_includes = ["."],
-)`}})
-}
-
-func TestSoongConfigModuleType_Defaults_SingleNamespace(t *testing.T) {
- bp := `
-soong_config_module_type {
- name: "vendor_foo_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "vendor_foo",
- bool_variables: ["feature"],
- properties: ["cflags", "cppflags"],
-}
-
-vendor_foo_cc_defaults {
- name: "foo_defaults_1",
- soong_config_variables: {
- feature: {
- cflags: ["-cflag_feature_1"],
- conditions_default: {
- cflags: ["-cflag_default_1"],
- },
- },
- },
-}
-
-vendor_foo_cc_defaults {
- name: "foo_defaults_2",
- defaults: ["foo_defaults_1"],
- soong_config_variables: {
- feature: {
- cflags: ["-cflag_feature_2"],
- conditions_default: {
- cflags: ["-cflag_default_2"],
- },
- },
- },
-}
-
-cc_library_static {
- name: "lib",
- defaults: ["foo_defaults_2"],
- bazel_module: { bp2build_available: true },
- host_supported: true,
-}
-`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - defaults with a single namespace",
- ModuleTypeUnderTest: "cc_library_static",
- ModuleTypeUnderTestFactory: cc.LibraryStaticFactory,
- Blueprint: bp,
- ExpectedBazelTargets: []string{`cc_library_static(
- name = "lib",
- copts = select({
- "//build/bazel/product_config/config_settings:vendor_foo__feature": [
- "-cflag_feature_2",
- "-cflag_feature_1",
- ],
- "//conditions:default": [
- "-cflag_default_2",
- "-cflag_default_1",
- ],
- }),
- local_includes = ["."],
-)`}})
-}
-
-func TestSoongConfigModuleType_MultipleDefaults_SingleNamespace(t *testing.T) {
- bp := `
-soong_config_module_type {
- name: "foo_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "acme",
- bool_variables: ["feature"],
- properties: ["cflags"],
-}
-
-soong_config_module_type {
- name: "bar_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "acme",
- bool_variables: ["feature"],
- properties: ["cflags", "asflags"],
-}
-
-foo_cc_defaults {
- name: "foo_defaults",
- soong_config_variables: {
- feature: {
- cflags: ["-cflag_foo"],
- conditions_default: {
- cflags: ["-cflag_default_foo"],
- },
- },
- },
-}
-
-bar_cc_defaults {
- name: "bar_defaults",
- srcs: ["file.S"],
- soong_config_variables: {
- feature: {
- cflags: ["-cflag_bar"],
- asflags: ["-asflag_bar"],
- conditions_default: {
- asflags: ["-asflag_default_bar"],
- cflags: ["-cflag_default_bar"],
- },
- },
- },
-}
-
-cc_library_static {
- name: "lib",
- defaults: ["foo_defaults", "bar_defaults"],
- bazel_module: { bp2build_available: true },
- host_supported: true,
-}
-
-cc_library_static {
- name: "lib2",
- defaults: ["bar_defaults", "foo_defaults"],
- bazel_module: { bp2build_available: true },
- host_supported: true,
-}
-`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - multiple defaults with a single namespace",
- ModuleTypeUnderTest: "cc_library_static",
- ModuleTypeUnderTestFactory: cc.LibraryStaticFactory,
- Blueprint: bp,
- ExpectedBazelTargets: []string{`cc_library_static(
- name = "lib",
- asflags = select({
- "//build/bazel/product_config/config_settings:acme__feature": ["-asflag_bar"],
- "//conditions:default": ["-asflag_default_bar"],
- }),
- copts = select({
- "//build/bazel/product_config/config_settings:acme__feature": [
- "-cflag_foo",
- "-cflag_bar",
- ],
- "//conditions:default": [
- "-cflag_default_foo",
- "-cflag_default_bar",
- ],
- }),
- local_includes = ["."],
- srcs_as = ["file.S"],
-)`,
- `cc_library_static(
- name = "lib2",
- asflags = select({
- "//build/bazel/product_config/config_settings:acme__feature": ["-asflag_bar"],
- "//conditions:default": ["-asflag_default_bar"],
- }),
- copts = select({
- "//build/bazel/product_config/config_settings:acme__feature": [
- "-cflag_bar",
- "-cflag_foo",
- ],
- "//conditions:default": [
- "-cflag_default_bar",
- "-cflag_default_foo",
- ],
- }),
- local_includes = ["."],
- srcs_as = ["file.S"],
-)`}})
-}
-
-func TestSoongConfigModuleType_Defaults_MultipleNamespaces(t *testing.T) {
- bp := `
-soong_config_module_type {
- name: "vendor_foo_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "vendor_foo",
- bool_variables: ["feature"],
- properties: ["cflags"],
-}
-
-soong_config_module_type {
- name: "vendor_bar_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "vendor_bar",
- bool_variables: ["feature"],
- properties: ["cflags"],
-}
-
-soong_config_module_type {
- name: "vendor_qux_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "vendor_qux",
- bool_variables: ["feature"],
- properties: ["cflags"],
-}
-
-vendor_foo_cc_defaults {
- name: "foo_defaults",
- soong_config_variables: {
- feature: {
- cflags: ["-DVENDOR_FOO_FEATURE"],
- conditions_default: {
- cflags: ["-DVENDOR_FOO_DEFAULT"],
- },
- },
- },
-}
-
-vendor_bar_cc_defaults {
- name: "bar_defaults",
- soong_config_variables: {
- feature: {
- cflags: ["-DVENDOR_BAR_FEATURE"],
- conditions_default: {
- cflags: ["-DVENDOR_BAR_DEFAULT"],
- },
- },
- },
-}
-
-vendor_qux_cc_defaults {
- name: "qux_defaults",
- defaults: ["bar_defaults"],
- soong_config_variables: {
- feature: {
- cflags: ["-DVENDOR_QUX_FEATURE"],
- conditions_default: {
- cflags: ["-DVENDOR_QUX_DEFAULT"],
- },
- },
- },
-}
-
-cc_library_static {
- name: "lib",
- defaults: ["foo_defaults", "qux_defaults"],
- bazel_module: { bp2build_available: true },
- host_supported: true,
-}
-`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - defaults with multiple namespaces",
- ModuleTypeUnderTest: "cc_library_static",
- ModuleTypeUnderTestFactory: cc.LibraryStaticFactory,
- Blueprint: bp,
- ExpectedBazelTargets: []string{`cc_library_static(
- name = "lib",
- copts = select({
- "//build/bazel/product_config/config_settings:vendor_bar__feature": ["-DVENDOR_BAR_FEATURE"],
- "//conditions:default": ["-DVENDOR_BAR_DEFAULT"],
- }) + select({
- "//build/bazel/product_config/config_settings:vendor_foo__feature": ["-DVENDOR_FOO_FEATURE"],
- "//conditions:default": ["-DVENDOR_FOO_DEFAULT"],
- }) + select({
- "//build/bazel/product_config/config_settings:vendor_qux__feature": ["-DVENDOR_QUX_FEATURE"],
- "//conditions:default": ["-DVENDOR_QUX_DEFAULT"],
- }),
- local_includes = ["."],
-)`}})
-}
-
-func TestSoongConfigModuleType_Defaults_UseBaselineValueForStringProp(t *testing.T) {
- bp := `
-soong_config_string_variable {
- name: "library_linking_strategy",
- values: [
- "prefer_static",
- ],
-}
-
-soong_config_module_type {
- name: "library_linking_strategy_custom",
- module_type: "custom",
- config_namespace: "ANDROID",
- variables: ["library_linking_strategy"],
- properties: [
- "string_literal_prop",
- ],
-}
-
-library_linking_strategy_custom {
- name: "foo",
- string_literal_prop: "29",
- soong_config_variables: {
- library_linking_strategy: {
- prefer_static: {},
- conditions_default: {
- string_literal_prop: "30",
- },
- },
- },
-}`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - generates selects for library_linking_strategy",
- ModuleTypeUnderTest: "cc_binary",
- ModuleTypeUnderTestFactory: cc.BinaryFactory,
- Blueprint: bp,
- Filesystem: map[string]string{},
- ExpectedBazelTargets: []string{
- MakeBazelTarget("custom", "foo", AttrNameToString{
- "string_literal_prop": `select({
- "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": "29",
- "//conditions:default": "30",
- })`,
- }),
- },
- })
-}
-
-func TestSoongConfigModuleType_UnsetConditions(t *testing.T) {
- bp := `
-soong_config_string_variable {
- name: "library_linking_strategy",
- values: [
- "prefer_static",
- ],
-}
-
-soong_config_module_type {
- name: "library_linking_strategy_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "ANDROID",
- variables: ["library_linking_strategy"],
- properties: [
- "shared_libs",
- "static_libs",
- ],
-}
-
-library_linking_strategy_cc_defaults {
- name: "library_linking_strategy_lib_a_defaults",
- soong_config_variables: {
- library_linking_strategy: {
- prefer_static: {},
- conditions_default: {
- shared_libs: [
- "lib_a",
- ],
- },
- },
- },
-}
-
-library_linking_strategy_cc_defaults {
- name: "library_linking_strategy_merged_defaults",
- defaults: ["library_linking_strategy_lib_a_defaults"],
- host_supported: true,
- soong_config_variables: {
- library_linking_strategy: {
- prefer_static: {},
- conditions_default: {
- shared_libs: [
- "lib_b",
- ],
- },
- },
- },
-}
-
-cc_binary {
- name: "library_linking_strategy_sample_binary",
- srcs: ["library_linking_strategy.cc"],
- defaults: ["library_linking_strategy_merged_defaults"],
- include_build_directory: false,
-}`
-
- otherDeps := `
-cc_library { name: "lib_a", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_b", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_default", bazel_module: { bp2build_available: false } }
-`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - generates selects for library_linking_strategy",
- ModuleTypeUnderTest: "cc_binary",
- ModuleTypeUnderTestFactory: cc.BinaryFactory,
- Blueprint: bp,
- Filesystem: map[string]string{
- "foo/bar/Android.bp": otherDeps,
- },
- ExpectedBazelTargets: []string{`cc_binary(
- name = "library_linking_strategy_sample_binary",
- dynamic_deps = select({
- "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": [],
- "//conditions:default": [
- "//foo/bar:lib_b",
- "//foo/bar:lib_a",
- ],
- }),
- srcs = ["library_linking_strategy.cc"],
-)`}})
-}
-
-func TestSoongConfigModuleType_UnsetConditionsExcludeLibs(t *testing.T) {
- bp := `
-soong_config_string_variable {
- name: "library_linking_strategy",
- values: [
- "prefer_static",
- ],
-}
-
-soong_config_module_type {
- name: "library_linking_strategy_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "ANDROID",
- variables: ["library_linking_strategy"],
- properties: ["shared_libs"],
-}
-
-library_linking_strategy_cc_defaults {
- name: "library_linking_strategy_lib_a_defaults",
- soong_config_variables: {
- library_linking_strategy: {
- prefer_static: {},
- conditions_default: {
- shared_libs: [
- "lib_a",
- ],
- },
- },
- },
-}
-
-library_linking_strategy_cc_defaults {
- name: "library_linking_strategy_merged_defaults",
- defaults: ["library_linking_strategy_lib_a_defaults"],
- host_supported: true,
- soong_config_variables: {
- library_linking_strategy: {
- prefer_static: {},
- conditions_default: {
- shared_libs: [
- "lib_b",
- "lib_c",
- ],
- },
- },
- },
- exclude_shared_libs: ["lib_a"],
-}
-
-cc_binary {
- name: "library_linking_strategy_sample_binary",
- defaults: ["library_linking_strategy_merged_defaults"],
- include_build_directory: false,
-}
-
-cc_binary {
- name: "library_linking_strategy_sample_binary_with_excludes",
- defaults: ["library_linking_strategy_merged_defaults"],
- exclude_shared_libs: ["lib_c"],
- include_build_directory: false,
-}`
-
- otherDeps := `
-cc_library { name: "lib_a", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_b", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_c", bazel_module: { bp2build_available: false } }
-`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - generates selects for library_linking_strategy",
- ModuleTypeUnderTest: "cc_binary",
- ModuleTypeUnderTestFactory: cc.BinaryFactory,
- Blueprint: bp,
- Filesystem: map[string]string{
- "foo/bar/Android.bp": otherDeps,
- },
- ExpectedBazelTargets: []string{
- MakeBazelTargetNoRestrictions("cc_binary", "library_linking_strategy_sample_binary", AttrNameToString{
- "dynamic_deps": `select({
- "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": [],
- "//conditions:default": [
- "//foo/bar:lib_b",
- "//foo/bar:lib_c",
- ],
- })`,
- }),
- MakeBazelTargetNoRestrictions("cc_binary", "library_linking_strategy_sample_binary_with_excludes", AttrNameToString{
- "dynamic_deps": `select({
- "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": [],
- "//conditions:default": ["//foo/bar:lib_b"],
- })`,
- }),
- }})
-}
-
-func TestSoongConfigModuleType_Defaults(t *testing.T) {
- bp := `
-soong_config_string_variable {
- name: "library_linking_strategy",
- values: [
- "prefer_static",
- ],
-}
-
-soong_config_module_type {
- name: "library_linking_strategy_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "ANDROID",
- variables: ["library_linking_strategy"],
- properties: [
- "shared_libs",
- "static_libs",
- ],
-}
-
-library_linking_strategy_cc_defaults {
- name: "library_linking_strategy_lib_a_defaults",
- soong_config_variables: {
- library_linking_strategy: {
- prefer_static: {
- static_libs: [
- "lib_a",
- ],
- },
- conditions_default: {
- shared_libs: [
- "lib_a",
- ],
- },
- },
- },
-}
-
-library_linking_strategy_cc_defaults {
- name: "library_linking_strategy_merged_defaults",
- defaults: ["library_linking_strategy_lib_a_defaults"],
- host_supported: true,
- soong_config_variables: {
- library_linking_strategy: {
- prefer_static: {
- static_libs: [
- "lib_b",
- ],
- },
- conditions_default: {
- shared_libs: [
- "lib_b",
- ],
- },
- },
- },
-}
-
-cc_binary {
- name: "library_linking_strategy_sample_binary",
- srcs: ["library_linking_strategy.cc"],
- defaults: ["library_linking_strategy_merged_defaults"],
-}`
-
- otherDeps := `
-cc_library { name: "lib_a", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_b", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_default", bazel_module: { bp2build_available: false } }
-`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - generates selects for library_linking_strategy",
- ModuleTypeUnderTest: "cc_binary",
- ModuleTypeUnderTestFactory: cc.BinaryFactory,
- Blueprint: bp,
- Filesystem: map[string]string{
- "foo/bar/Android.bp": otherDeps,
- },
- ExpectedBazelTargets: []string{`cc_binary(
- name = "library_linking_strategy_sample_binary",
- deps = select({
- "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": [
- "//foo/bar:lib_b_bp2build_cc_library_static",
- "//foo/bar:lib_a_bp2build_cc_library_static",
- ],
- "//conditions:default": [],
- }),
- dynamic_deps = select({
- "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": [],
- "//conditions:default": [
- "//foo/bar:lib_b",
- "//foo/bar:lib_a",
- ],
- }),
- local_includes = ["."],
- srcs = ["library_linking_strategy.cc"],
-)`}})
-}
-
-func TestSoongConfigModuleType_Defaults_Another(t *testing.T) {
- bp := `
-soong_config_string_variable {
- name: "library_linking_strategy",
- values: [
- "prefer_static",
- ],
-}
-
-soong_config_module_type {
- name: "library_linking_strategy_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "ANDROID",
- variables: ["library_linking_strategy"],
- properties: [
- "shared_libs",
- "static_libs",
- ],
-}
-
-library_linking_strategy_cc_defaults {
- name: "library_linking_strategy_sample_defaults",
- soong_config_variables: {
- library_linking_strategy: {
- prefer_static: {
- static_libs: [
- "lib_a",
- "lib_b",
- ],
- },
- conditions_default: {
- shared_libs: [
- "lib_a",
- "lib_b",
- ],
- },
- },
- },
-}
-
-cc_binary {
- name: "library_linking_strategy_sample_binary",
- host_supported: true,
- srcs: ["library_linking_strategy.cc"],
- defaults: ["library_linking_strategy_sample_defaults"],
-}`
-
- otherDeps := `
-cc_library { name: "lib_a", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_b", bazel_module: { bp2build_available: false } }
-`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - generates selects for library_linking_strategy",
- ModuleTypeUnderTest: "cc_binary",
- ModuleTypeUnderTestFactory: cc.BinaryFactory,
- Blueprint: bp,
- Filesystem: map[string]string{
- "foo/bar/Android.bp": otherDeps,
- },
- ExpectedBazelTargets: []string{`cc_binary(
- name = "library_linking_strategy_sample_binary",
- deps = select({
- "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": [
- "//foo/bar:lib_a_bp2build_cc_library_static",
- "//foo/bar:lib_b_bp2build_cc_library_static",
- ],
- "//conditions:default": [],
- }),
- dynamic_deps = select({
- "//build/bazel/product_config/config_settings:android__library_linking_strategy__prefer_static": [],
- "//conditions:default": [
- "//foo/bar:lib_a",
- "//foo/bar:lib_b",
- ],
- }),
- local_includes = ["."],
- srcs = ["library_linking_strategy.cc"],
-)`}})
-}
-
-func TestSoongConfigModuleType_Defaults_UnusedProps(t *testing.T) {
- bp := `
-soong_config_string_variable {
- name: "alphabet",
- values: [
- "a",
- "b",
- "c", // unused
- ],
-}
-
-soong_config_module_type {
- name: "alphabet_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "ANDROID",
- variables: ["alphabet"],
- properties: [
- "cflags", // unused
- "shared_libs",
- "static_libs",
- ],
-}
-
-alphabet_cc_defaults {
- name: "alphabet_sample_cc_defaults",
- soong_config_variables: {
- alphabet: {
- a: {
- shared_libs: [
- "lib_a",
- ],
- },
- b: {
- shared_libs: [
- "lib_b",
- ],
- },
- conditions_default: {
- static_libs: [
- "lib_default",
- ],
- },
- },
- },
-}
-
-cc_binary {
- name: "alphabet_binary",
- host_supported: true,
- srcs: ["main.cc"],
- defaults: ["alphabet_sample_cc_defaults"],
-}`
-
- otherDeps := `
-cc_library { name: "lib_a", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_b", bazel_module: { bp2build_available: false } }
-cc_library { name: "lib_default", bazel_module: { bp2build_available: false } }
-`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - generates selects for library_linking_strategy",
- ModuleTypeUnderTest: "cc_binary",
- ModuleTypeUnderTestFactory: cc.BinaryFactory,
- Blueprint: bp,
- Filesystem: map[string]string{
- "foo/bar/Android.bp": otherDeps,
- },
- ExpectedBazelTargets: []string{`cc_binary(
- name = "alphabet_binary",
- deps = select({
- "//build/bazel/product_config/config_settings:android__alphabet__a": [],
- "//build/bazel/product_config/config_settings:android__alphabet__b": [],
- "//conditions:default": ["//foo/bar:lib_default_bp2build_cc_library_static"],
- }),
- dynamic_deps = select({
- "//build/bazel/product_config/config_settings:android__alphabet__a": ["//foo/bar:lib_a"],
- "//build/bazel/product_config/config_settings:android__alphabet__b": ["//foo/bar:lib_b"],
- "//conditions:default": [],
- }),
- local_includes = ["."],
- srcs = ["main.cc"],
-)`}})
-}
-
-func TestSoongConfigModuleType_ProductVariableConfigWithPlatformConfig(t *testing.T) {
- bp := `
-soong_config_bool_variable {
- name: "special_build",
-}
-
-soong_config_module_type {
- name: "alphabet_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "alphabet_module",
- bool_variables: ["special_build"],
- properties: ["enabled"],
-}
-
-alphabet_cc_defaults {
- name: "alphabet_sample_cc_defaults",
- soong_config_variables: {
- special_build: {
- enabled: true,
- },
- },
-}
-
-cc_binary {
- name: "alphabet_binary",
- srcs: ["main.cc"],
- host_supported: true,
- defaults: ["alphabet_sample_cc_defaults"],
- enabled: false,
- arch: {
- x86_64: {
- enabled: false,
- },
- },
- target: {
- darwin: {
- enabled: false,
- },
- },
-}`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - generates selects for library_linking_strategy",
- ModuleTypeUnderTest: "cc_binary",
- ModuleTypeUnderTestFactory: cc.BinaryFactory,
- Blueprint: bp,
- Filesystem: map[string]string{},
- ExpectedBazelTargets: []string{`cc_binary(
- name = "alphabet_binary",
- local_includes = ["."],
- srcs = ["main.cc"],
- target_compatible_with = select({
- "//build/bazel/platforms/os_arch:android_x86_64": ["@platforms//:incompatible"],
- "//build/bazel/platforms/os_arch:darwin_arm64": ["@platforms//:incompatible"],
- "//build/bazel/platforms/os_arch:darwin_x86_64": ["@platforms//:incompatible"],
- "//build/bazel/platforms/os_arch:linux_bionic_x86_64": ["@platforms//:incompatible"],
- "//build/bazel/platforms/os_arch:linux_glibc_x86_64": ["@platforms//:incompatible"],
- "//build/bazel/platforms/os_arch:linux_musl_x86_64": ["@platforms//:incompatible"],
- "//build/bazel/platforms/os_arch:windows_x86_64": ["@platforms//:incompatible"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/product_config/config_settings:alphabet_module__special_build": [],
- "//conditions:default": ["@platforms//:incompatible"],
- }),
-)`}})
-}
-
-func TestSoongConfigModuleType_ProductVariableConfigOverridesEnable(t *testing.T) {
- bp := `
-soong_config_bool_variable {
- name: "special_build",
-}
-
-soong_config_module_type {
- name: "alphabet_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "alphabet_module",
- bool_variables: ["special_build"],
- properties: ["enabled"],
-}
-
-alphabet_cc_defaults {
- name: "alphabet_sample_cc_defaults",
- soong_config_variables: {
- special_build: {
- enabled: true,
- },
- },
-}
-
-cc_binary {
- name: "alphabet_binary",
- srcs: ["main.cc"],
- defaults: ["alphabet_sample_cc_defaults"],
- enabled: false,
-}
-
-alphabet_cc_defaults {
- name: "alphabet_sample_cc_defaults_conditions_default",
- soong_config_variables: {
- special_build: {
- conditions_default: {
- enabled: false,
- },
- },
- },
-}
-
-cc_binary {
- name: "alphabet_binary_conditions_default",
- srcs: ["main.cc"],
- defaults: ["alphabet_sample_cc_defaults_conditions_default"],
- enabled: false,
-}`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - generates selects for library_linking_strategy",
- ModuleTypeUnderTest: "cc_binary",
- ModuleTypeUnderTestFactory: cc.BinaryFactory,
- Blueprint: bp,
- Filesystem: map[string]string{},
- ExpectedBazelTargets: []string{`cc_binary(
- name = "alphabet_binary",
- local_includes = ["."],
- srcs = ["main.cc"],
- target_compatible_with = select({
- "//build/bazel/product_config/config_settings:alphabet_module__special_build": [],
- "//conditions:default": ["@platforms//:incompatible"],
- }),
-)`,
- MakeBazelTarget("cc_binary", "alphabet_binary_conditions_default", AttrNameToString{
- "local_includes": `["."]`,
- "srcs": `["main.cc"]`,
- "target_compatible_with": `["@platforms//:incompatible"]`,
- }),
- }})
-}
-
-func TestSoongConfigModuleType_ProductVariableIgnoredIfEnabledByDefault(t *testing.T) {
- bp := `
-soong_config_bool_variable {
- name: "special_build",
-}
-
-soong_config_module_type {
- name: "alphabet_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "alphabet_module",
- bool_variables: ["special_build"],
- properties: ["enabled"],
-}
-
-alphabet_cc_defaults {
- name: "alphabet_sample_cc_defaults",
- host_supported: true,
- soong_config_variables: {
- special_build: {
- enabled: true,
- },
- },
-}
-
-cc_binary {
- name: "alphabet_binary",
- srcs: ["main.cc"],
- defaults: ["alphabet_sample_cc_defaults"],
-}`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - generates selects for library_linking_strategy",
- ModuleTypeUnderTest: "cc_binary",
- ModuleTypeUnderTestFactory: cc.BinaryFactory,
- Blueprint: bp,
- Filesystem: map[string]string{},
- ExpectedBazelTargets: []string{`cc_binary(
- name = "alphabet_binary",
- local_includes = ["."],
- srcs = ["main.cc"],
-)`}})
-}
-
-func TestSoongConfigModuleType_CombinedWithArchVariantProperties(t *testing.T) {
- bp := `
-soong_config_bool_variable {
- name: "my_bool_variable",
-}
-
-soong_config_string_variable {
- name: "my_string_variable",
- values: [
- "value1",
- "value2",
- ],
-}
-
-soong_config_module_type {
- name: "special_build_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "my_namespace",
- bool_variables: ["my_bool_variable"],
- variables: ["my_string_variable"],
- properties: ["target.android.cflags", "cflags"],
-}
-
-special_build_cc_defaults {
- name: "sample_cc_defaults",
- target: {
- android: {
- cflags: ["-DFOO"],
- },
- },
- soong_config_variables: {
- my_bool_variable: {
- target: {
- android: {
- cflags: ["-DBAR"],
- },
- },
- conditions_default: {
- target: {
- android: {
- cflags: ["-DBAZ"],
- },
- },
- },
- },
- my_string_variable: {
- value1: {
- cflags: ["-DVALUE1_NOT_ANDROID"],
- target: {
- android: {
- cflags: ["-DVALUE1"],
- },
- },
- },
- value2: {
- target: {
- android: {
- cflags: ["-DVALUE2"],
- },
- },
- },
- conditions_default: {
- target: {
- android: {
- cflags: ["-DSTRING_VAR_CONDITIONS_DEFAULT"],
- },
- },
- },
- },
- },
-}
-
-cc_binary {
- name: "my_binary",
- srcs: ["main.cc"],
- defaults: ["sample_cc_defaults"],
-}`
-
- runSoongConfigModuleTypeTest(t, Bp2buildTestCase{
- Description: "soong config variables - generates selects for library_linking_strategy",
- ModuleTypeUnderTest: "cc_binary",
- ModuleTypeUnderTestFactory: cc.BinaryFactory,
- Blueprint: bp,
- Filesystem: map[string]string{},
- ExpectedBazelTargets: []string{`cc_binary(
- name = "my_binary",
- copts = select({
- "//build/bazel/platforms/os:android": ["-DFOO"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/product_config/config_settings:my_namespace__my_bool_variable__android": ["-DBAR"],
- "//build/bazel/product_config/config_settings:my_namespace__my_bool_variable__conditions_default__android": ["-DBAZ"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/product_config/config_settings:my_namespace__my_string_variable__value1": ["-DVALUE1_NOT_ANDROID"],
- "//conditions:default": [],
- }) + select({
- "//build/bazel/product_config/config_settings:my_namespace__my_string_variable__conditions_default__android": ["-DSTRING_VAR_CONDITIONS_DEFAULT"],
- "//build/bazel/product_config/config_settings:my_namespace__my_string_variable__value1__android": ["-DVALUE1"],
- "//build/bazel/product_config/config_settings:my_namespace__my_string_variable__value2__android": ["-DVALUE2"],
- "//conditions:default": [],
- }),
- local_includes = ["."],
- srcs = ["main.cc"],
- target_compatible_with = ["//build/bazel/platforms/os:android"],
-)`}})
-}
-
-// If we have
-// A. a soong_config_module_type with target.android_<arch>.* in properties
-// B. a module that uses this module type but does not set target.android_<arch>.* via soong config vars
-// Then we should not panic
-func TestPanicsIfSoongConfigModuleTypeHasArchSpecificProperties(t *testing.T) {
- commonBp := `
-soong_config_bool_variable {
- name: "my_bool_variable",
-}
-soong_config_module_type {
- name: "special_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "my_namespace",
- bool_variables: ["my_bool_variable"],
- properties: [
- "cflags",
- "target.android_arm64.shared_libs",
- ],
-}
-cc_binary {
- name: "my_binary",
- defaults: ["my_special_cc_defaults"],
-}
-`
- testCases := []struct {
- desc string
- additionalBp string
- isPanicExpected bool
- }{
- {
- desc: "target.android_arm64 is not set, bp2build should not panic",
- additionalBp: `
-special_cc_defaults {
- name: "my_special_cc_defaults",
- soong_config_variables: {
- my_bool_variable: {
- cflags: ["-DFOO"],
- conditions_default: {
- cflags: ["-DBAR"],
- }
- }
- },
-}
- `,
- isPanicExpected: false,
- },
- {
- desc: "target.android_arm64 is set using the bool soong config var, bp2build should panic",
- additionalBp: `
-special_cc_defaults {
- name: "my_special_cc_defaults",
- soong_config_variables: {
- my_bool_variable: {
- cflags: ["-DFOO"],
- target: {
- android_arm64: {
- shared_libs: ["liblog"],
- },
- },
- conditions_default: {
- cflags: ["-DBAR"],
- }
- }
- },
-}
- `,
- isPanicExpected: true,
- },
- {
- desc: "target.android_arm64 is set using conditions_default for the bool soong config var, bp2build should panic",
- additionalBp: `
-special_cc_defaults {
- name: "my_special_cc_defaults",
- soong_config_variables: {
- my_bool_variable: {
- cflags: ["-DFOO"],
- conditions_default: {
- cflags: ["-DBAR"],
- target: {
- android_arm64: {
- shared_libs: ["liblog"],
- },
- },
- }
- }
- },
-}
- `,
- isPanicExpected: true,
- },
- }
- for _, tc := range testCases {
- bp2buildTestCase := Bp2buildTestCase{
- Description: tc.desc,
- ModuleTypeUnderTest: "cc_binary",
- ModuleTypeUnderTestFactory: cc.BinaryFactory,
- Blueprint: commonBp + tc.additionalBp,
- // Check in `foo` dir so that we can check whether it panics or not and not trip over an empty `ExpectedBazelTargets`
- Dir: "foo",
- ExpectedBazelTargets: []string{},
- }
- if tc.isPanicExpected {
- bp2buildTestCase.ExpectedErr = fmt.Errorf("TODO: support other target types in soong config variable structs: Android_arm64")
- }
- runSoongConfigModuleTypeTest(t, bp2buildTestCase)
- }
-}
-
-func TestNoPanicIfEnabledIsNotUsed(t *testing.T) {
- bp := `
-soong_config_string_variable {
- name: "my_string_variable",
- values: ["val1", "val2"],
-}
-soong_config_module_type {
- name: "special_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "my_namespace",
- variables: ["my_string_variable"],
- properties: [
- "cflags",
- "enabled",
- ],
-}
-special_cc_defaults {
- name: "my_special_cc_defaults",
- soong_config_variables: {
- my_string_variable: {
- val1: {
- cflags: ["-DFOO"],
- },
- val2: {
- cflags: ["-DBAR"],
- },
- },
- },
-}
-cc_binary {
- name: "my_binary",
- enabled: false,
- defaults: ["my_special_cc_defaults"],
-}
-`
- tc := Bp2buildTestCase{
- Description: "Soong config vars is not used to set `enabled` property",
- ModuleTypeUnderTest: "cc_binary",
- ModuleTypeUnderTestFactory: cc.BinaryFactory,
- Blueprint: bp,
- ExpectedBazelTargets: []string{
- MakeBazelTarget("cc_binary", "my_binary", AttrNameToString{
- "copts": `select({
- "//build/bazel/product_config/config_settings:my_namespace__my_string_variable__val1": ["-DFOO"],
- "//build/bazel/product_config/config_settings:my_namespace__my_string_variable__val2": ["-DBAR"],
- "//conditions:default": [],
- })`,
- "local_includes": `["."]`,
- "target_compatible_with": `["@platforms//:incompatible"]`,
- }),
- },
- }
- runSoongConfigModuleTypeTest(t, tc)
-}
diff --git a/bp2build/symlink_forest.go b/bp2build/symlink_forest.go
deleted file mode 100644
index 5c33308..0000000
--- a/bp2build/symlink_forest.go
+++ /dev/null
@@ -1,501 +0,0 @@
-// 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"
- "io/ioutil"
- "os"
- "path/filepath"
- "regexp"
- "sort"
- "strconv"
- "strings"
- "sync"
- "sync/atomic"
-
- "android/soong/shared"
-
- "github.com/google/blueprint/pathtools"
-)
-
-// A tree structure that describes what to do at each directory in the created
-// symlink tree. Currently it is used to enumerate which files/directories
-// should be excluded from symlinking. Each instance of "node" represents a file
-// or a directory. If excluded is true, then that file/directory should be
-// excluded from symlinking. Otherwise, the node is not excluded, but one of its
-// descendants is (otherwise the node in question would not exist)
-
-// This is a version int written to a file called symlink_forest_version at the root of the
-// symlink forest. If the version here does not match the version in the file, then we'll
-// clean the whole symlink forest and recreate it. This number can be bumped whenever there's
-// an incompatible change to the forest layout or a bug in incrementality that needs to be fixed
-// on machines that may still have the bug present in their forest.
-const symlinkForestVersion = 1
-
-type instructionsNode struct {
- name string
- excluded bool // If false, this is just an intermediate node
- children map[string]*instructionsNode
-}
-
-type symlinkForestContext struct {
- verbose bool
- topdir string // $TOPDIR
-
- // State
- wg sync.WaitGroup
- depCh chan string
- mkdirCount atomic.Uint64
- symlinkCount atomic.Uint64
-}
-
-// Ensures that the node for the given path exists in the tree and returns it.
-func ensureNodeExists(root *instructionsNode, path string) *instructionsNode {
- if path == "" {
- return root
- }
-
- if path[len(path)-1] == '/' {
- path = path[:len(path)-1] // filepath.Split() leaves a trailing slash
- }
-
- dir, base := filepath.Split(path)
-
- // First compute the parent node...
- dn := ensureNodeExists(root, dir)
-
- // then create the requested node as its direct child, if needed.
- if child, ok := dn.children[base]; ok {
- return child
- } else {
- dn.children[base] = &instructionsNode{base, false, make(map[string]*instructionsNode)}
- return dn.children[base]
- }
-}
-
-// Turns a list of paths to be excluded into a tree
-func instructionsFromExcludePathList(paths []string) *instructionsNode {
- result := &instructionsNode{"", false, make(map[string]*instructionsNode)}
-
- for _, p := range paths {
- ensureNodeExists(result, p).excluded = true
- }
-
- return result
-}
-
-func mergeBuildFiles(output string, srcBuildFile string, generatedBuildFile string, verbose bool) error {
-
- srcBuildFileContent, err := os.ReadFile(srcBuildFile)
- if err != nil {
- return err
- }
-
- generatedBuildFileContent, err := os.ReadFile(generatedBuildFile)
- if err != nil {
- return err
- }
-
- // There can't be a package() call in both the source and generated BUILD files.
- // bp2build will generate a package() call for licensing information, but if
- // there's no licensing information, it will still generate a package() call
- // that just sets default_visibility=public. If the handcrafted build file
- // also has a package() call, we'll allow it to override the bp2build
- // generated one if it doesn't have any licensing information. If the bp2build
- // one has licensing information and the handcrafted one exists, we'll leave
- // them both in for bazel to throw an error.
- packageRegex := regexp.MustCompile(`(?m)^package\s*\(`)
- packageDefaultVisibilityRegex := regexp.MustCompile(`(?m)^package\s*\(\s*default_visibility\s*=\s*\[\s*"//visibility:public",?\s*]\s*\)`)
- if packageRegex.Find(srcBuildFileContent) != nil {
- if verbose && packageDefaultVisibilityRegex.Find(generatedBuildFileContent) != nil {
- fmt.Fprintf(os.Stderr, "Both '%s' and '%s' have a package() target, removing the first one\n",
- generatedBuildFile, srcBuildFile)
- }
- generatedBuildFileContent = packageDefaultVisibilityRegex.ReplaceAll(generatedBuildFileContent, []byte{})
- }
-
- newContents := generatedBuildFileContent
- if newContents[len(newContents)-1] != '\n' {
- newContents = append(newContents, '\n')
- }
- newContents = append(newContents, srcBuildFileContent...)
-
- // Say you run bp2build 4 times:
- // - The first time there's only an Android.bp file. bp2build will convert it to a build file
- // under out/soong/bp2build, then symlink from the forest to that generated file
- // - Then you add a handcrafted BUILD file in the same directory. bp2build will merge this with
- // the generated one, and write the result to the output file in the forest. But the output
- // file was a symlink to out/soong/bp2build from the previous step! So we erroneously update
- // the file in out/soong/bp2build instead. So far this doesn't cause any problems...
- // - You run a 3rd bp2build with no relevant changes. Everything continues to work.
- // - You then add a comment to the handcrafted BUILD file. This causes a merge with the
- // generated file again. But since we wrote to the generated file in step 2, the generated
- // file has an old copy of the handcrafted file in it! This probably causes duplicate bazel
- // targets.
- // To solve this, if we see that the output file is a symlink from a previous build, remove it.
- stat, err := os.Lstat(output)
- if err != nil && !os.IsNotExist(err) {
- return err
- } else if err == nil {
- if stat.Mode()&os.ModeSymlink == os.ModeSymlink {
- if verbose {
- fmt.Fprintf(os.Stderr, "Removing symlink so that we can replace it with a merged file: %s\n", output)
- }
- err = os.Remove(output)
- if err != nil {
- return err
- }
- }
- }
-
- return pathtools.WriteFileIfChanged(output, newContents, 0666)
-}
-
-// Calls readdir() and returns it as a map from the basename of the files in dir
-// to os.FileInfo.
-func readdirToMap(dir string) map[string]os.FileInfo {
- entryList, err := ioutil.ReadDir(dir)
- result := make(map[string]os.FileInfo)
-
- if err != nil {
- if os.IsNotExist(err) {
- // It's okay if a directory doesn't exist; it just means that one of the
- // trees to be merged contains parts the other doesn't
- return result
- } else {
- fmt.Fprintf(os.Stderr, "Cannot readdir '%s': %s\n", dir, err)
- os.Exit(1)
- }
- }
-
- for _, fi := range entryList {
- result[fi.Name()] = fi
- }
-
- return result
-}
-
-// Creates a symbolic link at dst pointing to src
-func symlinkIntoForest(topdir, dst, src string) uint64 {
- srcPath := shared.JoinPath(topdir, src)
- dstPath := shared.JoinPath(topdir, dst)
-
- // Check if a symlink already exists.
- if dstInfo, err := os.Lstat(dstPath); err != nil {
- if !os.IsNotExist(err) {
- fmt.Fprintf(os.Stderr, "Failed to lstat '%s': %s", dst, err)
- os.Exit(1)
- }
- } else {
- if dstInfo.Mode()&os.ModeSymlink != 0 {
- // Assume that the link's target is correct, i.e. no manual tampering.
- // E.g. OUT_DIR could have been previously used with a different source tree check-out!
- return 0
- } else {
- if err := os.RemoveAll(dstPath); err != nil {
- fmt.Fprintf(os.Stderr, "Failed to remove '%s': %s", dst, err)
- os.Exit(1)
- }
- }
- }
-
- // Create symlink.
- if err := os.Symlink(srcPath, dstPath); err != nil {
- fmt.Fprintf(os.Stderr, "Cannot create symlink at '%s' pointing to '%s': %s", dst, src, err)
- os.Exit(1)
- }
- return 1
-}
-
-func isDir(path string, fi os.FileInfo) bool {
- if (fi.Mode() & os.ModeSymlink) != os.ModeSymlink {
- return fi.IsDir()
- }
-
- fi2, statErr := os.Stat(path)
- if statErr == nil {
- return fi2.IsDir()
- }
-
- // Check if this is a dangling symlink. If so, treat it like a file, not a dir.
- _, lstatErr := os.Lstat(path)
- if lstatErr != nil {
- fmt.Fprintf(os.Stderr, "Cannot stat or lstat '%s': %s\n%s\n", path, statErr, lstatErr)
- os.Exit(1)
- }
-
- return false
-}
-
-// maybeCleanSymlinkForest will remove the whole symlink forest directory if the version recorded
-// in the symlink_forest_version file is not equal to symlinkForestVersion.
-func maybeCleanSymlinkForest(topdir, forest string, verbose bool) error {
- versionFilePath := shared.JoinPath(topdir, forest, "symlink_forest_version")
- versionFileContents, err := os.ReadFile(versionFilePath)
- if err != nil && !os.IsNotExist(err) {
- return err
- }
- versionFileString := strings.TrimSpace(string(versionFileContents))
- symlinkForestVersionString := strconv.Itoa(symlinkForestVersion)
- if err != nil || versionFileString != symlinkForestVersionString {
- if verbose {
- fmt.Fprintf(os.Stderr, "Old symlink_forest_version was %q, current is %q. Cleaning symlink forest before recreating...\n", versionFileString, symlinkForestVersionString)
- }
- err = os.RemoveAll(shared.JoinPath(topdir, forest))
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-// maybeWriteVersionFile will write the symlink_forest_version file containing symlinkForestVersion
-// if it doesn't exist already. If it exists we know it must contain symlinkForestVersion because
-// we checked for that already in maybeCleanSymlinkForest
-func maybeWriteVersionFile(topdir, forest string) error {
- versionFilePath := shared.JoinPath(topdir, forest, "symlink_forest_version")
- _, err := os.Stat(versionFilePath)
- if err != nil {
- if !os.IsNotExist(err) {
- return err
- }
- err = os.WriteFile(versionFilePath, []byte(strconv.Itoa(symlinkForestVersion)+"\n"), 0666)
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-// Recursively plants a symlink forest at forestDir. The symlink tree will
-// contain every file in buildFilesDir and srcDir excluding the files in
-// instructions. Collects every directory encountered during the traversal of
-// srcDir .
-func plantSymlinkForestRecursive(context *symlinkForestContext, instructions *instructionsNode, forestDir string, buildFilesDir string, srcDir string) {
- defer context.wg.Done()
-
- if instructions != nil && instructions.excluded {
- // Excluded paths are skipped at the level of the non-excluded parent.
- fmt.Fprintf(os.Stderr, "may not specify a root-level exclude directory '%s'", srcDir)
- os.Exit(1)
- }
-
- // We don't add buildFilesDir here because the bp2build files marker files is
- // already a dependency which covers it. If we ever wanted to turn this into
- // a generic symlink forest creation tool, we'd need to add it, too.
- context.depCh <- srcDir
-
- srcDirMap := readdirToMap(shared.JoinPath(context.topdir, srcDir))
- buildFilesMap := readdirToMap(shared.JoinPath(context.topdir, buildFilesDir))
-
- renamingBuildFile := false
- if _, ok := srcDirMap["BUILD"]; ok {
- if _, ok := srcDirMap["BUILD.bazel"]; !ok {
- if _, ok := buildFilesMap["BUILD.bazel"]; ok {
- renamingBuildFile = true
- srcDirMap["BUILD.bazel"] = srcDirMap["BUILD"]
- delete(srcDirMap, "BUILD")
- if instructions != nil {
- if _, ok := instructions.children["BUILD"]; ok {
- instructions.children["BUILD.bazel"] = instructions.children["BUILD"]
- delete(instructions.children, "BUILD")
- }
- }
- }
- }
- }
-
- allEntries := make([]string, 0, len(srcDirMap)+len(buildFilesMap))
- for n := range srcDirMap {
- allEntries = append(allEntries, n)
- }
- for n := range buildFilesMap {
- if _, ok := srcDirMap[n]; !ok {
- allEntries = append(allEntries, n)
- }
- }
- // Tests read the error messages generated, so ensure their order is deterministic
- sort.Strings(allEntries)
-
- fullForestPath := shared.JoinPath(context.topdir, forestDir)
- createForestDir := false
- if fi, err := os.Lstat(fullForestPath); err != nil {
- if os.IsNotExist(err) {
- createForestDir = true
- } else {
- fmt.Fprintf(os.Stderr, "Could not read info for '%s': %s\n", forestDir, err)
- }
- } else if fi.Mode()&os.ModeDir == 0 {
- if err := os.RemoveAll(fullForestPath); err != nil {
- fmt.Fprintf(os.Stderr, "Failed to remove '%s': %s", forestDir, err)
- os.Exit(1)
- }
- createForestDir = true
- }
- if createForestDir {
- if err := os.MkdirAll(fullForestPath, 0777); err != nil {
- fmt.Fprintf(os.Stderr, "Could not mkdir '%s': %s\n", forestDir, err)
- os.Exit(1)
- }
- context.mkdirCount.Add(1)
- }
-
- // Start with a list of items that already exist in the forest, and remove
- // each element as it is processed in allEntries. Any remaining items in
- // forestMapForDeletion must be removed. (This handles files which were
- // removed since the previous forest generation).
- forestMapForDeletion := readdirToMap(shared.JoinPath(context.topdir, forestDir))
-
- for _, f := range allEntries {
- if f[0] == '.' {
- continue // Ignore dotfiles
- }
- delete(forestMapForDeletion, f)
- // todo add deletionCount metric
-
- // The full paths of children in the input trees and in the output tree
- forestChild := shared.JoinPath(forestDir, f)
- srcChild := shared.JoinPath(srcDir, f)
- if f == "BUILD.bazel" && renamingBuildFile {
- srcChild = shared.JoinPath(srcDir, "BUILD")
- }
- buildFilesChild := shared.JoinPath(buildFilesDir, f)
-
- // Descend in the instruction tree if it exists
- var instructionsChild *instructionsNode
- if instructions != nil {
- instructionsChild = instructions.children[f]
- }
-
- srcChildEntry, sExists := srcDirMap[f]
- buildFilesChildEntry, bExists := buildFilesMap[f]
-
- if instructionsChild != nil && instructionsChild.excluded {
- if bExists {
- context.symlinkCount.Add(symlinkIntoForest(context.topdir, forestChild, buildFilesChild))
- }
- continue
- }
-
- sDir := sExists && isDir(shared.JoinPath(context.topdir, srcChild), srcChildEntry)
- bDir := bExists && isDir(shared.JoinPath(context.topdir, buildFilesChild), buildFilesChildEntry)
-
- if !sExists {
- if bDir && instructionsChild != nil {
- // Not in the source tree, but we have to exclude something from under
- // this subtree, so descend
- context.wg.Add(1)
- go plantSymlinkForestRecursive(context, instructionsChild, forestChild, buildFilesChild, srcChild)
- } else {
- // Not in the source tree, symlink BUILD file
- context.symlinkCount.Add(symlinkIntoForest(context.topdir, forestChild, buildFilesChild))
- }
- } else if !bExists {
- if sDir && instructionsChild != nil {
- // Not in the build file tree, but we have to exclude something from
- // under this subtree, so descend
- context.wg.Add(1)
- go plantSymlinkForestRecursive(context, instructionsChild, forestChild, buildFilesChild, srcChild)
- } else {
- // Not in the build file tree, symlink source tree, carry on
- context.symlinkCount.Add(symlinkIntoForest(context.topdir, forestChild, srcChild))
- }
- } else if sDir && bDir {
- // Both are directories. Descend.
- context.wg.Add(1)
- go plantSymlinkForestRecursive(context, instructionsChild, forestChild, buildFilesChild, srcChild)
- } else if !sDir && !bDir {
- // Neither is a directory. Merge them.
- srcBuildFile := shared.JoinPath(context.topdir, srcChild)
- generatedBuildFile := shared.JoinPath(context.topdir, buildFilesChild)
- // The Android.bp file that codegen used to produce `buildFilesChild` is
- // already a dependency, we can ignore `buildFilesChild`.
- context.depCh <- srcChild
- if err := mergeBuildFiles(shared.JoinPath(context.topdir, forestChild), srcBuildFile, generatedBuildFile, context.verbose); err != nil {
- fmt.Fprintf(os.Stderr, "Error merging %s and %s: %s",
- srcBuildFile, generatedBuildFile, err)
- os.Exit(1)
- }
- } else {
- // Both exist and one is a file. This is an error.
- fmt.Fprintf(os.Stderr,
- "Conflict in workspace symlink tree creation: both '%s' and '%s' exist and exactly one is a directory\n",
- srcChild, buildFilesChild)
- os.Exit(1)
- }
- }
-
- // Remove all files in the forest that exist in neither the source
- // tree nor the build files tree. (This handles files which were removed
- // since the previous forest generation).
- for f := range forestMapForDeletion {
- var instructionsChild *instructionsNode
- if instructions != nil {
- instructionsChild = instructions.children[f]
- }
-
- if instructionsChild != nil && instructionsChild.excluded {
- // This directory may be excluded because bazel writes to it under the
- // forest root. Thus this path is intentionally left alone.
- continue
- }
- forestChild := shared.JoinPath(context.topdir, forestDir, f)
- if err := os.RemoveAll(forestChild); err != nil {
- fmt.Fprintf(os.Stderr, "Failed to remove '%s/%s': %s", forestDir, f, err)
- os.Exit(1)
- }
- }
-}
-
-// PlantSymlinkForest Creates a symlink forest by merging the directory tree at "buildFiles" and
-// "srcDir" while excluding paths listed in "exclude". Returns the set of paths
-// under srcDir on which readdir() had to be called to produce the symlink
-// forest.
-func PlantSymlinkForest(verbose bool, topdir string, forest string, buildFiles string, exclude []string) (deps []string, mkdirCount, symlinkCount uint64) {
- context := &symlinkForestContext{
- verbose: verbose,
- topdir: topdir,
- depCh: make(chan string),
- mkdirCount: atomic.Uint64{},
- symlinkCount: atomic.Uint64{},
- }
-
- err := maybeCleanSymlinkForest(topdir, forest, verbose)
- if err != nil {
- fmt.Fprintln(os.Stderr, err)
- os.Exit(1)
- }
-
- instructions := instructionsFromExcludePathList(exclude)
- go func() {
- context.wg.Add(1)
- plantSymlinkForestRecursive(context, instructions, forest, buildFiles, ".")
- context.wg.Wait()
- close(context.depCh)
- }()
-
- for dep := range context.depCh {
- deps = append(deps, dep)
- }
-
- err = maybeWriteVersionFile(topdir, forest)
- if err != nil {
- fmt.Fprintln(os.Stderr, err)
- os.Exit(1)
- }
-
- return deps, context.mkdirCount.Load(), context.symlinkCount.Load()
-}
diff --git a/bp2build/testing.go b/bp2build/testing.go
deleted file mode 100644
index 997df64..0000000
--- a/bp2build/testing.go
+++ /dev/null
@@ -1,685 +0,0 @@
-// 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 (
- "fmt"
- "sort"
- "strings"
- "testing"
-
- "github.com/google/blueprint/proptools"
-
- "android/soong/android"
- "android/soong/android/allowlists"
- "android/soong/bazel"
-)
-
-var (
- buildDir string
-)
-
-func checkError(t *testing.T, errs []error, expectedErr error) bool {
- t.Helper()
-
- if len(errs) != 1 {
- return false
- }
- if strings.Contains(errs[0].Error(), expectedErr.Error()) {
- return true
- }
-
- return false
-}
-
-func errored(t *testing.T, tc Bp2buildTestCase, errs []error) bool {
- t.Helper()
- if tc.ExpectedErr != nil {
- // Rely on checkErrors, as this test case is expected to have an error.
- return false
- }
-
- if len(errs) > 0 {
- for _, err := range errs {
- t.Errorf("%s: %s", tc.Description, err)
- }
- return true
- }
-
- // All good, continue execution.
- 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
- // Text to add to the toplevel, root Android.bp file. If Dir is not set, all
- // ExpectedBazelTargets are assumed to be generated by this file.
- Blueprint string
- // ExpectedBazelTargets compares the BazelTargets generated in `Dir` (if not empty).
- // Otherwise, it checks the BazelTargets generated by `Blueprint` in the root directory.
- ExpectedBazelTargets []string
- Filesystem map[string]string
- // Dir sets the directory which will be compared against the targets in ExpectedBazelTargets.
- // This should used in conjunction with the Filesystem property to check for targets
- // generated from a directory that is not the root.
- // If not set, all ExpectedBazelTargets are assumed to be generated by the text in the
- // Blueprint property.
- Dir string
- // An error with a string contained within the string of the expected error
- ExpectedErr error
- UnconvertedDepsMode unconvertedDepsMode
-
- // For every directory listed here, the BUILD file for that directory will
- // be merged with the generated BUILD file. This allows custom BUILD targets
- // to be used in tests, or use BUILD files to draw package boundaries.
- KeepBuildFileForDirs []string
-}
-
-func RunBp2BuildTestCase(t *testing.T, registerModuleTypes func(ctx android.RegistrationContext), tc Bp2buildTestCase) {
- t.Helper()
- bp2buildSetup := android.GroupFixturePreparers(
- android.FixtureRegisterWithContext(registerModuleTypes),
- SetBp2BuildTestRunner,
- )
- runBp2BuildTestCaseWithSetup(t, bp2buildSetup, tc)
-}
-
-func runBp2BuildTestCaseWithSetup(t *testing.T, extraPreparer android.FixturePreparer, tc Bp2buildTestCase) {
- t.Helper()
- dir := "."
- filesystem := make(map[string][]byte)
- for f, content := range tc.Filesystem {
- filesystem[f] = []byte(content)
- }
-
- preparers := []android.FixturePreparer{
- extraPreparer,
- android.FixtureMergeMockFs(filesystem),
- android.FixtureWithRootAndroidBp(tc.Blueprint),
- android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
- ctx.RegisterModuleType(tc.ModuleTypeUnderTest, tc.ModuleTypeUnderTestFactory)
- }),
- android.FixtureModifyContext(func(ctx *android.TestContext) {
- // A default configuration for tests to not have to specify bp2build_available on top level
- // targets.
- bp2buildConfig := android.NewBp2BuildAllowlist().SetDefaultConfig(
- allowlists.Bp2BuildConfig{
- android.Bp2BuildTopLevel: allowlists.Bp2BuildDefaultTrueRecursively,
- },
- )
- for _, f := range tc.KeepBuildFileForDirs {
- bp2buildConfig.SetKeepExistingBuildFile(map[string]bool{
- f: /*recursive=*/ false,
- })
- }
- ctx.RegisterBp2BuildConfig(bp2buildConfig)
- // This setting is added to bp2build invocations. It prevents bp2build
- // from cloning modules to their original state after mutators run. This
- // would lose some data intentionally set by these mutators.
- ctx.SkipCloneModulesAfterMutators = true
- }),
- android.FixtureModifyEnv(func(env map[string]string) {
- if tc.UnconvertedDepsMode == errorModulesUnconvertedDeps {
- env["BP2BUILD_ERROR_UNCONVERTED"] = "true"
- }
- }),
- }
-
- preparer := android.GroupFixturePreparers(preparers...)
- if tc.ExpectedErr != nil {
- pattern := "\\Q" + tc.ExpectedErr.Error() + "\\E"
- preparer = preparer.ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern(pattern))
- }
- result := preparer.RunTestWithCustomResult(t).(*BazelTestResult)
- if len(result.Errs) > 0 {
- return
- }
-
- checkDir := dir
- if tc.Dir != "" {
- checkDir = tc.Dir
- }
- expectedTargets := map[string][]string{
- checkDir: tc.ExpectedBazelTargets,
- }
-
- result.CompareAllBazelTargets(t, tc.Description, expectedTargets, true)
-}
-
-// SetBp2BuildTestRunner customizes the test fixture mechanism to run tests in Bp2Build mode.
-var SetBp2BuildTestRunner = android.FixtureSetTestRunner(&bazelTestRunner{})
-
-// bazelTestRunner customizes the test fixture mechanism to run tests of the bp2build build mode.
-type bazelTestRunner struct{}
-
-func (b *bazelTestRunner) FinalPreparer(result *android.TestResult) android.CustomTestResult {
- ctx := result.TestContext
- ctx.RegisterForBazelConversion()
-
- return &BazelTestResult{TestResult: result}
-}
-
-func (b *bazelTestRunner) PostParseProcessor(result android.CustomTestResult) {
- bazelResult := result.(*BazelTestResult)
- ctx := bazelResult.TestContext
- config := bazelResult.Config
- _, errs := ctx.ResolveDependencies(config)
- if bazelResult.CollateErrs(errs) {
- return
- }
-
- codegenCtx := NewCodegenContext(config, ctx.Context, Bp2Build, "")
- res, errs := GenerateBazelTargets(codegenCtx, false)
- if bazelResult.CollateErrs(errs) {
- return
- }
-
- // Store additional data for access by tests.
- bazelResult.conversionResults = res
-}
-
-// BazelTestResult is a wrapper around android.TestResult to provide type safe access to the bazel
-// specific data stored by the bazelTestRunner.
-type BazelTestResult struct {
- *android.TestResult
-
- // The result returned by the GenerateBazelTargets function.
- conversionResults
-}
-
-// CompareAllBazelTargets compares the BazelTargets produced by the test for all the directories
-// with the supplied set of expected targets.
-//
-// If ignoreUnexpected=false then this enforces an exact match where every BazelTarget produced must
-// have a corresponding expected BazelTarget.
-//
-// If ignoreUnexpected=true then it will ignore directories for which there are no expected targets.
-func (b BazelTestResult) CompareAllBazelTargets(t *testing.T, description string, expectedTargets map[string][]string, ignoreUnexpected bool) {
- t.Helper()
- actualTargets := b.buildFileToTargets
-
- // Generate the sorted set of directories to check.
- dirsToCheck := android.SortedKeys(expectedTargets)
- if !ignoreUnexpected {
- // This needs to perform an exact match so add the directories in which targets were
- // produced to the list of directories to check.
- dirsToCheck = append(dirsToCheck, android.SortedKeys(actualTargets)...)
- dirsToCheck = android.SortedUniqueStrings(dirsToCheck)
- }
-
- for _, dir := range dirsToCheck {
- expected := expectedTargets[dir]
- actual := actualTargets[dir]
-
- if expected == nil {
- if actual != nil {
- t.Errorf("did not expect any bazel modules in %q but found %d", dir, len(actual))
- }
- } else if actual == nil {
- expectedCount := len(expected)
- if expectedCount > 0 {
- t.Errorf("expected %d bazel modules in %q but did not find any", expectedCount, dir)
- }
- } else {
- b.CompareBazelTargets(t, description, expected, actual)
- }
- }
-}
-
-func (b BazelTestResult) CompareBazelTargets(t *testing.T, description string, expectedContents []string, actualTargets BazelTargets) {
- t.Helper()
- if actualCount, expectedCount := len(actualTargets), len(expectedContents); actualCount != expectedCount {
- 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(
- "%s[%d]: Expected generated Bazel target to be `%s`, got `%s`",
- description, i, w, g)
- }
- }
- }
-}
-
-type nestedProps struct {
- Nested_prop *string
-}
-
-type EmbeddedProps struct {
- Embedded_prop *string
-}
-
-type OtherEmbeddedProps struct {
- Other_embedded_prop *string
-}
-
-type customProps struct {
- EmbeddedProps
- *OtherEmbeddedProps
-
- Bool_prop bool
- Bool_ptr_prop *bool
- // Ensure that properties tagged `blueprint:mutated` are omitted
- Int_prop int `blueprint:"mutated"`
- Int64_ptr_prop *int64
- String_prop string
- String_literal_prop *string `android:"arch_variant"`
- String_ptr_prop *string
- String_list_prop []string
-
- Nested_props nestedProps
- Nested_props_ptr *nestedProps
-
- Arch_paths []string `android:"path,arch_variant"`
- Arch_paths_exclude []string `android:"path,arch_variant"`
-
- // Prop used to indicate this conversion should be 1 module -> multiple targets
- One_to_many_prop *bool
-
- Api *string // File describing the APIs of this module
-
- Test_config_setting *bool // Used to test generation of config_setting targets
-
- Dir *string // Dir in which the Bazel Target will be created
-}
-
-type customModule struct {
- android.ModuleBase
- android.BazelModuleBase
-
- props customProps
-}
-
-// 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) {
- return android.PathsForTesting("path" + tag), nil
-}
-
-func (m *customModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- // nothing for now.
-}
-
-func customModuleFactoryBase() android.Module {
- module := &customModule{}
- module.AddProperties(&module.props)
- android.InitBazelModule(module)
- return module
-}
-
-func customModuleFactoryHostAndDevice() android.Module {
- m := customModuleFactoryBase()
- android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibBoth)
- return m
-}
-
-func customModuleFactoryDeviceSupported() android.Module {
- m := customModuleFactoryBase()
- android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibBoth)
- return m
-}
-
-func customModuleFactoryHostSupported() android.Module {
- m := customModuleFactoryBase()
- android.InitAndroidArchModule(m, android.HostSupported, android.MultilibBoth)
- return m
-}
-
-func customModuleFactoryHostAndDeviceDefault() android.Module {
- m := customModuleFactoryBase()
- android.InitAndroidArchModule(m, android.HostAndDeviceDefault, android.MultilibBoth)
- return m
-}
-
-func customModuleFactoryNeitherHostNorDeviceSupported() android.Module {
- m := customModuleFactoryBase()
- android.InitAndroidArchModule(m, android.NeitherHostNorDeviceSupported, android.MultilibBoth)
- return m
-}
-
-type testProps struct {
- Test_prop struct {
- Test_string_prop string
- }
-}
-
-type customTestModule struct {
- android.ModuleBase
-
- props customProps
- test_props testProps
-}
-
-func (m *customTestModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- // nothing for now.
-}
-
-func customTestModuleFactoryBase() android.Module {
- m := &customTestModule{}
- m.AddProperties(&m.props)
- m.AddProperties(&m.test_props)
- return m
-}
-
-func customTestModuleFactory() android.Module {
- m := customTestModuleFactoryBase()
- android.InitAndroidModule(m)
- return m
-}
-
-type customDefaultsModule struct {
- android.ModuleBase
- android.DefaultsModuleBase
-}
-
-func customDefaultsModuleFactoryBase() android.DefaultsModule {
- module := &customDefaultsModule{}
- module.AddProperties(&customProps{})
- return module
-}
-
-func customDefaultsModuleFactoryBasic() android.Module {
- return customDefaultsModuleFactoryBase()
-}
-
-func customDefaultsModuleFactory() android.Module {
- m := customDefaultsModuleFactoryBase()
- android.InitDefaultsModule(m)
- return m
-}
-
-type EmbeddedAttr struct {
- Embedded_attr *string
-}
-
-type OtherEmbeddedAttr struct {
- Other_embedded_attr *string
-}
-
-type customBazelModuleAttributes struct {
- EmbeddedAttr
- *OtherEmbeddedAttr
- String_literal_prop bazel.StringAttribute
- String_ptr_prop *string
- String_list_prop []string
- Arch_paths bazel.LabelListAttribute
- Api bazel.LabelAttribute
-}
-
-func (m *customModule) dir() *string {
- return m.props.Dir
-}
-
-func (m *customModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- if p := m.props.One_to_many_prop; p != nil && *p {
- customBp2buildOneToMany(ctx, m)
- return
- }
-
- paths := bazel.LabelListAttribute{}
- strAttr := bazel.StringAttribute{}
- for axis, configToProps := range m.GetArchVariantProperties(ctx, &customProps{}) {
- for config, props := range configToProps {
- if custProps, ok := props.(*customProps); ok {
- if custProps.Arch_paths != nil {
- paths.SetSelectValue(axis, config, android.BazelLabelForModuleSrcExcludes(ctx, custProps.Arch_paths, custProps.Arch_paths_exclude))
- }
- if custProps.String_literal_prop != nil {
- strAttr.SetSelectValue(axis, config, custProps.String_literal_prop)
- }
- }
- }
- }
- productVariableProps := android.ProductVariableProperties(ctx, ctx.Module())
- if props, ok := productVariableProps["String_literal_prop"]; ok {
- for c, p := range props {
- if val, ok := p.(*string); ok {
- strAttr.SetSelectValue(c.ConfigurationAxis(), c.SelectKey(), val)
- }
- }
- }
-
- paths.ResolveExcludes()
-
- attrs := &customBazelModuleAttributes{
- String_literal_prop: strAttr,
- String_ptr_prop: m.props.String_ptr_prop,
- String_list_prop: m.props.String_list_prop,
- Arch_paths: paths,
- }
-
- attrs.Embedded_attr = m.props.Embedded_prop
- if m.props.OtherEmbeddedProps != nil {
- attrs.OtherEmbeddedAttr = &OtherEmbeddedAttr{Other_embedded_attr: m.props.OtherEmbeddedProps.Other_embedded_prop}
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "custom",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name(), Dir: m.dir()}, attrs)
-
- if proptools.Bool(m.props.Test_config_setting) {
- m.createConfigSetting(ctx)
- }
-
-}
-
-func (m *customModule) createConfigSetting(ctx android.TopDownMutatorContext) {
- csa := bazel.ConfigSettingAttributes{
- Flag_values: bazel.StringMapAttribute{
- "//build/bazel/rules/my_string_setting": m.Name(),
- },
- }
- ca := android.CommonAttributes{
- Name: m.Name() + "_config_setting",
- }
- ctx.CreateBazelConfigSetting(
- csa,
- ca,
- ctx.ModuleDir(),
- )
-}
-
-var _ android.ApiProvider = (*customModule)(nil)
-
-func (c *customModule) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "custom_api_contribution",
- }
- apiAttribute := bazel.MakeLabelAttribute(
- android.BazelLabelForModuleSrcSingle(ctx, proptools.String(c.props.Api)).Label,
- )
- attrs := &customBazelModuleAttributes{
- Api: *apiAttribute,
- }
- ctx.CreateBazelTargetModule(props,
- android.CommonAttributes{Name: c.Name()},
- attrs)
-}
-
-// A bp2build mutator that uses load statements and creates a 1:M mapping from
-// module to target.
-func customBp2buildOneToMany(ctx android.TopDownMutatorContext, m *customModule) {
-
- baseName := m.Name()
- attrs := &customBazelModuleAttributes{}
-
- myLibraryProps := bazel.BazelTargetModuleProperties{
- Rule_class: "my_library",
- Bzl_load_location: "//build/bazel/rules:rules.bzl",
- }
- ctx.CreateBazelTargetModule(myLibraryProps, android.CommonAttributes{Name: baseName}, attrs)
-
- protoLibraryProps := bazel.BazelTargetModuleProperties{
- Rule_class: "proto_library",
- Bzl_load_location: "//build/bazel/rules:proto.bzl",
- }
- ctx.CreateBazelTargetModule(protoLibraryProps, android.CommonAttributes{Name: baseName + "_proto_library_deps"}, attrs)
-
- myProtoLibraryProps := bazel.BazelTargetModuleProperties{
- Rule_class: "my_proto_library",
- Bzl_load_location: "//build/bazel/rules:proto.bzl",
- }
- ctx.CreateBazelTargetModule(myProtoLibraryProps, android.CommonAttributes{Name: baseName + "_my_proto_library_deps"}, attrs)
-}
-
-// Helper method for tests to easily access the targets in a dir.
-func generateBazelTargetsForDir(codegenCtx *CodegenContext, dir string) (BazelTargets, []error) {
- // TODO: Set generateFilegroups to true and/or remove the generateFilegroups argument completely
- res, err := GenerateBazelTargets(codegenCtx, false)
- if err != nil {
- return BazelTargets{}, err
- }
- return res.buildFileToTargets[dir], err
-}
-
-func registerCustomModuleForBp2buildConversion(ctx *android.TestContext) {
- ctx.RegisterModuleType("custom", customModuleFactoryHostAndDevice)
- ctx.RegisterForBazelConversion()
-}
-
-func simpleModuleDoNotConvertBp2build(typ, name string) string {
- return fmt.Sprintf(`
-%s {
- name: "%s",
- bazel_module: { bp2build_available: false },
-}`, typ, name)
-}
-
-type AttrNameToString map[string]string
-
-func (a AttrNameToString) clone() AttrNameToString {
- newAttrs := make(AttrNameToString, len(a))
- for k, v := range a {
- newAttrs[k] = v
- }
- return newAttrs
-}
-
-// makeBazelTargetNoRestrictions returns bazel target build file definition that can be host or
-// device specific, or independent of host/device.
-func makeBazelTargetHostOrDevice(typ, name string, attrs AttrNameToString, hod android.HostOrDeviceSupported) string {
- if _, ok := attrs["target_compatible_with"]; !ok {
- switch hod {
- case android.HostSupported:
- attrs["target_compatible_with"] = `select({
- "//build/bazel/platforms/os:android": ["@platforms//:incompatible"],
- "//conditions:default": [],
- })`
- case android.DeviceSupported:
- attrs["target_compatible_with"] = `["//build/bazel/platforms/os:android"]`
- }
- }
-
- attrStrings := make([]string, 0, len(attrs)+1)
- if name != "" {
- attrStrings = append(attrStrings, fmt.Sprintf(` name = "%s",`, name))
- }
- for _, k := range android.SortedKeys(attrs) {
- attrStrings = append(attrStrings, fmt.Sprintf(" %s = %s,", k, attrs[k]))
- }
- return fmt.Sprintf(`%s(
-%s
-)`, typ, strings.Join(attrStrings, "\n"))
-}
-
-// MakeBazelTargetNoRestrictions returns bazel target build file definition that does not add a
-// target_compatible_with. This is useful for module types like filegroup and genrule that arch not
-// arch variant
-func MakeBazelTargetNoRestrictions(typ, name string, attrs AttrNameToString) string {
- return makeBazelTargetHostOrDevice(typ, name, attrs, android.HostAndDeviceDefault)
-}
-
-// makeBazelTargetNoRestrictions returns bazel target build file definition that is device specific
-// as this is the most common default in Soong.
-func MakeBazelTarget(typ, name string, attrs AttrNameToString) string {
- return makeBazelTargetHostOrDevice(typ, name, attrs, android.DeviceSupported)
-}
-
-type ExpectedRuleTarget struct {
- Rule string
- Name string
- Attrs AttrNameToString
- Hod android.HostOrDeviceSupported
-}
-
-func (ebr ExpectedRuleTarget) String() string {
- return makeBazelTargetHostOrDevice(ebr.Rule, ebr.Name, ebr.Attrs, ebr.Hod)
-}
-
-func makeCcStubSuiteTargets(name string, attrs AttrNameToString) string {
- if _, hasStubs := attrs["stubs_symbol_file"]; !hasStubs {
- return ""
- }
- STUB_SUITE_ATTRS := map[string]string{
- "stubs_symbol_file": "symbol_file",
- "stubs_versions": "versions",
- "soname": "soname",
- "source_library_label": "source_library_label",
- }
-
- stubSuiteAttrs := AttrNameToString{}
- for key, _ := range attrs {
- if _, stubSuiteAttr := STUB_SUITE_ATTRS[key]; stubSuiteAttr {
- stubSuiteAttrs[STUB_SUITE_ATTRS[key]] = attrs[key]
- } else {
- panic(fmt.Sprintf("unused cc_stub_suite attr %q\n", key))
- }
- }
- return MakeBazelTarget("cc_stub_suite", name+"_stub_libs", stubSuiteAttrs)
-}
-
-func MakeNeverlinkDuplicateTarget(moduleType string, name string) string {
- return MakeNeverlinkDuplicateTargetWithAttrs(moduleType, name, AttrNameToString{
- "sdk_version": `"current"`, // use as default
- })
-}
-
-func MakeNeverlinkDuplicateTargetWithAttrs(moduleType string, name string, extraAttrs AttrNameToString) string {
- attrs := extraAttrs
- attrs["neverlink"] = `True`
- attrs["exports"] = `[":` + name + `"]`
- return MakeBazelTarget(moduleType, name+"-neverlink", attrs)
-}
-
-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/bpf/bpf.go b/bpf/bpf.go
index d135d5f..e1b512f 100644
--- a/bpf/bpf.go
+++ b/bpf/bpf.go
@@ -22,8 +22,6 @@
"strings"
"android/soong/android"
- "android/soong/bazel"
- "android/soong/bazel/cquery"
"android/soong/cc"
"github.com/google/blueprint"
@@ -98,7 +96,6 @@
type bpf struct {
android.ModuleBase
- android.BazelModuleBase
properties BpfProperties
@@ -153,8 +150,6 @@
// The architecture doesn't matter here, but asm/types.h is included by linux/types.h.
"-isystem bionic/libc/kernel/uapi/asm-arm64",
"-isystem bionic/libc/kernel/android/uapi",
- // TODO(b/296014682): Remove after the bpf_headers is moved to Connectivity
- "-I frameworks/libs/net/common/native/bpf_headers/include/bpf",
"-I packages/modules/Connectivity/staticlibs/native/bpf_headers/include/bpf",
// TODO(b/149785767): only give access to specific file with AID_* constants
"-I system/core/libcutils/include",
@@ -208,6 +203,7 @@
}
}
+ android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()})
}
func (bpf *bpf) AndroidMk() android.AndroidMkData {
@@ -231,52 +227,25 @@
names = append(names, objName)
fmt.Fprintln(w, "include $(CLEAR_VARS)", " # bpf.bpf.obj")
fmt.Fprintln(w, "LOCAL_MODULE := ", objName)
- data.Entries.WriteLicenseVariables(w)
fmt.Fprintln(w, "LOCAL_PREBUILT_MODULE_FILE :=", obj.String())
fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", obj.Base())
fmt.Fprintln(w, "LOCAL_MODULE_CLASS := ETC")
fmt.Fprintln(w, localModulePath)
+ // AconfigUpdateAndroidMkData may have added elements to Extra. Process them here.
+ for _, extra := range data.Extra {
+ extra(w, nil)
+ }
fmt.Fprintln(w, "include $(BUILD_PREBUILT)")
fmt.Fprintln(w)
}
fmt.Fprintln(w, "include $(CLEAR_VARS)", " # bpf.bpf")
fmt.Fprintln(w, "LOCAL_MODULE := ", name)
- data.Entries.WriteLicenseVariables(w)
android.AndroidMkEmitAssignList(w, "LOCAL_REQUIRED_MODULES", names)
fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
},
}
}
-var _ android.MixedBuildBuildable = (*bpf)(nil)
-
-func (bpf *bpf) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
- return true
-}
-
-func (bpf *bpf) QueueBazelCall(ctx android.BaseModuleContext) {
- bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(
- bpf.GetBazelLabel(ctx, bpf),
- cquery.GetOutputFiles,
- android.GetConfigKey(ctx))
-}
-
-func (bpf *bpf) ProcessBazelQueryResponse(ctx android.ModuleContext) {
- bazelCtx := ctx.Config().BazelContext
- objPaths, err := bazelCtx.GetOutputFiles(bpf.GetBazelLabel(ctx, bpf), android.GetConfigKey(ctx))
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- return
- }
-
- bazelOuts := android.Paths{}
- for _, p := range objPaths {
- bazelOuts = append(bazelOuts, android.PathForBazelOut(ctx, p))
- }
- bpf.objs = bazelOuts
-}
-
// Implements OutputFileFileProducer interface so that the obj output can be used in the data property
// of other modules.
func (bpf *bpf) OutputFiles(tag string) (android.Paths, error) {
@@ -300,39 +269,5 @@
module.AddProperties(&module.properties)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
- android.InitBazelModule(module)
return module
}
-
-type bazelBpfAttributes struct {
- Srcs bazel.LabelListAttribute
- Copts bazel.StringListAttribute
- Absolute_includes bazel.StringListAttribute
- Btf *bool
- // TODO(b/249528391): Add support for sub_dir
-}
-
-// bpf bp2build converter
-func (b *bpf) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- if ctx.ModuleType() != "bpf" {
- return
- }
-
- srcs := bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, b.properties.Srcs))
- copts := bazel.MakeStringListAttribute(b.properties.Cflags)
- absolute_includes := bazel.MakeStringListAttribute(b.properties.Include_dirs)
- btf := b.properties.Btf
-
- attrs := bazelBpfAttributes{
- Srcs: srcs,
- Copts: copts,
- Absolute_includes: absolute_includes,
- Btf: btf,
- }
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "bpf",
- Bzl_load_location: "//build/bazel/rules/bpf:bpf.bzl",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: b.Name()}, &attrs)
-}
diff --git a/bpf/bpf_test.go b/bpf/bpf_test.go
index a2010ff..6e39096 100644
--- a/bpf/bpf_test.go
+++ b/bpf/bpf_test.go
@@ -71,26 +71,3 @@
`\QAndroid.bp:2:3: module "bpf_invalid_name.o" variant "android_common": invalid character '_' in source name\E`)).
RunTestWithBp(t, bp)
}
-
-func TestBpfWithBazel(t *testing.T) {
- bp := `
- bpf {
- name: "bpf.o",
- srcs: ["bpf.c"],
- bazel_module: { label: "//bpf" },
- }
- `
-
- result := android.GroupFixturePreparers(
- prepareForBpfTest, android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: "outputbase",
- LabelToOutputFiles: map[string][]string{
- "//bpf": []string{"bpf.o"}}}
- })).RunTestWithBp(t, bp)
-
- output := result.Module("bpf.o", "android_common").(*bpf)
-
- expectedOutputFiles := []string{"outputbase/execroot/__main__/bpf.o"}
- android.AssertDeepEquals(t, "output files", expectedOutputFiles, output.objs.Strings())
-}
diff --git a/cc/Android.bp b/cc/Android.bp
index c32d854..9e4b763 100644
--- a/cc/Android.bp
+++ b/cc/Android.bp
@@ -9,15 +9,16 @@
"blueprint",
"blueprint-pathtools",
"soong",
+ "soong-aconfig",
"soong-aidl-library",
"soong-android",
- "soong-bazel",
"soong-cc-config",
"soong-etc",
"soong-fuzz",
"soong-genrule",
"soong-multitree",
"soong-snapshot",
+ "soong-testing",
"soong-tradefed",
],
srcs: [
@@ -25,7 +26,6 @@
"fdo_profile.go",
"androidmk.go",
"api_level.go",
- "bp2build.go",
"builder.go",
"cc.go",
"ccdeps.go",
@@ -38,7 +38,6 @@
"lto.go",
"makevars.go",
"orderfile.go",
- "pgo.go",
"prebuilt.go",
"proto.go",
"rs.go",
@@ -49,7 +48,6 @@
"snapshot_utils.go",
"stl.go",
"strip.go",
- "sysprop.go",
"tidy.go",
"util.go",
"vendor_snapshot.go",
diff --git a/cc/afdo.go b/cc/afdo.go
index 23d196d..79fbae1 100644
--- a/cc/afdo.go
+++ b/cc/afdo.go
@@ -24,18 +24,8 @@
"github.com/google/blueprint/proptools"
)
-// TODO(b/267229066): Remove globalAfdoProfileProjects after implementing bp2build converter for fdo_profile
-var (
- globalAfdoProfileProjects = []string{
- "vendor/google_data/pgo_profile/sampling/",
- "toolchain/pgo-profiles/sampling/",
- }
-)
-
-var afdoProfileProjectsConfigKey = android.NewOnceKey("AfdoProfileProjects")
-
// This flag needs to be in both CFlags and LdFlags to ensure correct symbol ordering
-const afdoFlagsFormat = "-fprofile-sample-use=%s"
+const afdoFlagsFormat = "-fprofile-sample-use=%s -fprofile-sample-accurate"
func recordMissingAfdoProfileFile(ctx android.BaseModuleContext, missing string) {
getNamedMapForConfig(ctx.Config(), modulesMissingProfileFileKey).Store(missing, true)
@@ -64,6 +54,13 @@
return []interface{}{&afdo.Properties}
}
+func (afdo *afdo) begin(ctx BaseModuleContext) {
+ // Disable on eng builds for faster build.
+ if ctx.Config().Eng() {
+ afdo.Properties.Afdo = false
+ }
+}
+
// afdoEnabled returns true for binaries and shared libraries
// that set afdo prop to True and there is a profile available
func (afdo *afdo) afdoEnabled() bool {
@@ -84,6 +81,10 @@
// 3. Make the profile searchable by the build system. So it's used the next time the binary
// is built.
flags.Local.CFlags = append([]string{"-funique-internal-linkage-names"}, flags.Local.CFlags...)
+ // Flags for Flow Sensitive AutoFDO
+ flags.Local.CFlags = append([]string{"-mllvm", "-enable-fs-discriminator=true"}, flags.Local.CFlags...)
+ // TODO(b/266595187): Remove the following feature once it is enabled in LLVM by default.
+ flags.Local.CFlags = append([]string{"-mllvm", "-improved-fs-discriminator=true"}, flags.Local.CFlags...)
}
if path := afdo.Properties.FdoProfilePath; path != nil {
// The flags are prepended to allow overriding.
@@ -136,8 +137,7 @@
}
ctx.VisitDirectDepsWithTag(FdoProfileTag, func(m android.Module) {
- if ctx.OtherModuleHasProvider(m, FdoProfileProvider) {
- info := ctx.OtherModuleProvider(m, FdoProfileProvider).(FdoProfileInfo)
+ if info, ok := android.OtherModuleProvider(ctx, m, FdoProfileProvider); ok {
c.afdo.Properties.FdoProfilePath = proptools.StringPtr(info.Path.String())
}
})
diff --git a/cc/androidmk.go b/cc/androidmk.go
index e0e543f..c39668c 100644
--- a/cc/androidmk.go
+++ b/cc/androidmk.go
@@ -50,6 +50,7 @@
InVendorRamdisk() bool
InRecovery() bool
NotInPlatform() bool
+ InVendorOrProduct() bool
}
type subAndroidMkProvider interface {
@@ -82,8 +83,9 @@
// causing multiple ART APEXes (com.android.art and com.android.art.debug)
// to be installed. And this is breaking some older devices (like marlin)
// where system.img is small.
- Required: c.Properties.AndroidMkRuntimeLibs,
- Include: "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk",
+ Required: c.Properties.AndroidMkRuntimeLibs,
+ OverrideName: c.BaseModuleName(),
+ Include: "$(BUILD_SYSTEM)/soong_cc_rust_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
@@ -100,20 +102,11 @@
if len(c.Properties.AndroidMkSharedLibs) > 0 {
entries.AddStrings("LOCAL_SHARED_LIBRARIES", c.Properties.AndroidMkSharedLibs...)
}
- if len(c.Properties.AndroidMkStaticLibs) > 0 {
- entries.AddStrings("LOCAL_STATIC_LIBRARIES", c.Properties.AndroidMkStaticLibs...)
- }
- if len(c.Properties.AndroidMkWholeStaticLibs) > 0 {
- entries.AddStrings("LOCAL_WHOLE_STATIC_LIBRARIES", c.Properties.AndroidMkWholeStaticLibs...)
- }
- if len(c.Properties.AndroidMkHeaderLibs) > 0 {
- entries.AddStrings("LOCAL_HEADER_LIBRARIES", c.Properties.AndroidMkHeaderLibs...)
- }
if len(c.Properties.AndroidMkRuntimeLibs) > 0 {
entries.AddStrings("LOCAL_RUNTIME_LIBRARIES", c.Properties.AndroidMkRuntimeLibs...)
}
entries.SetString("LOCAL_SOONG_LINK_TYPE", c.makeLinkType)
- if c.UseVndk() {
+ if c.InVendorOrProduct() {
entries.SetBool("LOCAL_USE_VNDK", true)
if c.IsVndk() && !c.static() {
entries.SetString("LOCAL_SOONG_VNDK_VERSION", c.VndkVersion())
@@ -133,6 +126,7 @@
entries.SetString("SOONG_SDK_VARIANT_MODULES",
"$(SOONG_SDK_VARIANT_MODULES) $(patsubst %.sdk,%,$(LOCAL_MODULE))")
}
+ android.SetAconfigFileMkEntries(c.AndroidModuleBase(), entries, c.mergedAconfigFiles)
},
},
ExtraFooters: []android.AndroidMkExtraFootersFunc{
@@ -175,15 +169,6 @@
}
}
-func AndroidMkWriteTestData(data []android.DataPath, entries *android.AndroidMkEntries) {
- testFiles := android.AndroidMkDataPaths(data)
- if len(testFiles) > 0 {
- entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- entries.AddStrings("LOCAL_TEST_DATA", testFiles...)
- })
- }
-}
-
func makeOverrideModuleNames(ctx AndroidMkContext, overrides []string) []string {
if ctx.Target().NativeBridge == android.NativeBridgeEnabled {
var result []string
@@ -310,7 +295,7 @@
// they can be exceptionally used directly when APEXes are not available (e.g. during the
// very early stage in the boot process).
if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.NotInPlatform() &&
- !ctx.InRamdisk() && !ctx.InVendorRamdisk() && !ctx.InRecovery() && !ctx.UseVndk() && !ctx.static() {
+ !ctx.InRamdisk() && !ctx.InVendorRamdisk() && !ctx.InRecovery() && !ctx.InVendorOrProduct() && !ctx.static() {
if library.buildStubs() && library.isLatestStubVersion() {
entries.SubName = ""
}
@@ -379,11 +364,6 @@
entries.SetBool("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", true)
}
})
- dataPaths := []android.DataPath{}
- for _, srcPath := range benchmark.data {
- dataPaths = append(dataPaths, android.DataPath{SrcPath: srcPath})
- }
- AndroidMkWriteTestData(dataPaths, entries)
}
func (test *testBinary) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
@@ -411,40 +391,16 @@
test.Properties.Test_options.CommonTestOptions.SetAndroidMkEntries(entries)
})
- AndroidMkWriteTestData(test.data, entries)
androidMkWriteExtraTestConfigs(test.extraTestConfigs, entries)
}
func (fuzz *fuzzBinary) AndroidMkEntries(ctx AndroidMkContext, entries *android.AndroidMkEntries) {
ctx.subAndroidMk(entries, fuzz.binaryDecorator)
- var fuzzFiles []string
- for _, d := range fuzz.fuzzPackagedModule.Corpus {
- fuzzFiles = append(fuzzFiles,
- filepath.Dir(fuzz.fuzzPackagedModule.CorpusIntermediateDir.String())+":corpus/"+d.Base())
- }
-
- for _, d := range fuzz.fuzzPackagedModule.Data {
- fuzzFiles = append(fuzzFiles,
- filepath.Dir(fuzz.fuzzPackagedModule.DataIntermediateDir.String())+":data/"+d.Rel())
- }
-
- if fuzz.fuzzPackagedModule.Dictionary != nil {
- fuzzFiles = append(fuzzFiles,
- filepath.Dir(fuzz.fuzzPackagedModule.Dictionary.String())+":"+fuzz.fuzzPackagedModule.Dictionary.Base())
- }
-
- if fuzz.fuzzPackagedModule.Config != nil {
- fuzzFiles = append(fuzzFiles,
- filepath.Dir(fuzz.fuzzPackagedModule.Config.String())+":config.json")
- }
-
entries.ExtraEntries = append(entries.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_IS_FUZZ_TARGET", true)
- if len(fuzzFiles) > 0 {
- entries.AddStrings("LOCAL_TEST_DATA", fuzzFiles...)
- }
if fuzz.installedSharedDeps != nil {
+ // TOOD: move to install dep
entries.AddStrings("LOCAL_FUZZ_INSTALLED_SHARED_DEPS", fuzz.installedSharedDeps...)
}
})
diff --git a/cc/binary.go b/cc/binary.go
index 4606b62..7aa8e20 100644
--- a/cc/binary.go
+++ b/cc/binary.go
@@ -17,13 +17,8 @@
import (
"path/filepath"
- "android/soong/bazel/cquery"
-
- "github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
-
"android/soong/android"
- "android/soong/bazel"
+ "github.com/google/blueprint"
)
type BinaryLinkerProperties struct {
@@ -71,14 +66,13 @@
// cc_binary produces a binary that is runnable on a device.
func BinaryFactory() android.Module {
- module, _ := newBinary(android.HostAndDeviceSupported, true)
- module.bazelHandler = &ccBinaryBazelHandler{module: module}
+ module, _ := newBinary(android.HostAndDeviceSupported)
return module.Init()
}
// cc_binary_host produces a binary that is runnable on a host.
func BinaryHostFactory() android.Module {
- module, _ := newBinary(android.HostSupported, true)
+ module, _ := newBinary(android.HostSupported)
return module.Init()
}
@@ -196,10 +190,10 @@
// Individual module implementations which comprise a C++ binary should call this function,
// set some fields on the result, and then call the Init function.
func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
- return newBinary(hod, true)
+ return newBinary(hod)
}
-func newBinary(hod android.HostOrDeviceSupported, bazelable bool) (*Module, *binaryDecorator) {
+func newBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
module := newModule(hod, android.MultilibFirst)
binary := &binaryDecorator{
baseLinker: NewBaseLinker(module.sanitize),
@@ -208,7 +202,6 @@
module.compiler = NewBaseCompiler()
module.linker = binary
module.installer = binary
- module.bazelable = bazelable
// Allow module to be added as member of an sdk/module_exports.
module.sdkMemberTypes = []android.SdkMemberType{
@@ -452,6 +445,10 @@
return binary.unstrippedOutputFile
}
+func (binary *binaryDecorator) strippedAllOutputFilePath() android.Path {
+ panic("Not implemented.")
+}
+
func (binary *binaryDecorator) setSymlinkList(ctx ModuleContext) {
for _, symlink := range binary.Properties.Symlinks {
binary.symlinks = append(binary.symlinks,
@@ -544,6 +541,11 @@
return binary.Properties.Overrides
}
+func (binary *binaryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ moduleInfoJSON.Class = []string{"EXECUTABLES"}
+ binary.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON)
+}
+
var _ overridable = (*binaryDecorator)(nil)
func init() {
@@ -568,149 +570,3 @@
},
})
}
-
-type ccBinaryBazelHandler struct {
- module *Module
-}
-
-var _ BazelHandler = (*ccBinaryBazelHandler)(nil)
-
-func (handler *ccBinaryBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
- bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(label, cquery.GetCcUnstrippedInfo, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx)))
-}
-
-func (handler *ccBinaryBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
- bazelCtx := ctx.Config().BazelContext
- info, err := bazelCtx.GetCcUnstrippedInfo(label, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx)))
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- return
- }
-
- var outputFilePath android.Path = android.PathForBazelOut(ctx, info.OutputFile)
- if len(info.TidyFiles) > 0 {
- handler.module.tidyFiles = android.PathsForBazelOut(ctx, info.TidyFiles)
- outputFilePath = android.AttachValidationActions(ctx, outputFilePath, handler.module.tidyFiles)
- }
- handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
- handler.module.linker.(*binaryDecorator).unstrippedOutputFile = android.PathForBazelOut(ctx, info.UnstrippedOutput)
-
- handler.module.setAndroidMkVariablesFromCquery(info.CcAndroidMkInfo)
-}
-
-func binaryBp2buildAttrs(ctx android.TopDownMutatorContext, m *Module) binaryAttributes {
- baseAttrs := bp2BuildParseBaseProps(ctx, m)
- binaryLinkerAttrs := bp2buildBinaryLinkerProps(ctx, m)
-
- if proptools.BoolDefault(binaryLinkerAttrs.Linkshared, true) {
- baseAttrs.implementationDynamicDeps.Add(baseAttrs.protoDependency)
- } else {
- baseAttrs.implementationDeps.Add(baseAttrs.protoDependency)
- }
-
- // binaries don't have implementation_whole_archive_deps
- baseAttrs.wholeArchiveDeps.Append(baseAttrs.implementationWholeArchiveDeps)
-
- attrs := binaryAttributes{
- binaryLinkerAttrs: binaryLinkerAttrs,
-
- Srcs: baseAttrs.srcs,
- Srcs_c: baseAttrs.cSrcs,
- Srcs_as: baseAttrs.asSrcs,
-
- Copts: baseAttrs.copts,
- Cppflags: baseAttrs.cppFlags,
- Conlyflags: baseAttrs.conlyFlags,
- Asflags: baseAttrs.asFlags,
-
- Deps: baseAttrs.implementationDeps,
- Dynamic_deps: baseAttrs.implementationDynamicDeps,
- Whole_archive_deps: baseAttrs.wholeArchiveDeps,
- System_deps: baseAttrs.systemDynamicDeps,
- Runtime_deps: baseAttrs.runtimeDeps,
-
- Local_includes: baseAttrs.localIncludes,
- Absolute_includes: baseAttrs.absoluteIncludes,
- Linkopts: baseAttrs.linkopts,
- Use_version_lib: baseAttrs.useVersionLib,
- Rtti: baseAttrs.rtti,
- Stl: baseAttrs.stl,
- Cpp_std: baseAttrs.cppStd,
-
- Additional_linker_inputs: baseAttrs.additionalLinkerInputs,
- Additional_compiler_inputs: baseAttrs.additionalCompilerInputs,
-
- Strip: stripAttributes{
- Keep_symbols: baseAttrs.stripKeepSymbols,
- Keep_symbols_and_debug_frame: baseAttrs.stripKeepSymbolsAndDebugFrame,
- Keep_symbols_list: baseAttrs.stripKeepSymbolsList,
- All: baseAttrs.stripAll,
- None: baseAttrs.stripNone,
- },
-
- Features: baseAttrs.features,
-
- sdkAttributes: bp2BuildParseSdkAttributes(m),
-
- Native_coverage: baseAttrs.Native_coverage,
- }
-
- m.convertTidyAttributes(ctx, &attrs.tidyAttributes)
-
- return attrs
-}
-
-func binaryBp2build(ctx android.TopDownMutatorContext, m *Module) {
- // shared with cc_test
- binaryAttrs := binaryBp2buildAttrs(ctx, m)
-
- tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
- ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{
- Rule_class: "cc_binary",
- Bzl_load_location: "//build/bazel/rules/cc:cc_binary.bzl",
- },
- android.CommonAttributes{Name: m.Name(), Tags: tags},
- &binaryAttrs)
-}
-
-// binaryAttributes contains Bazel attributes corresponding to a cc binary
-type binaryAttributes struct {
- binaryLinkerAttrs
- Srcs bazel.LabelListAttribute
- Srcs_c bazel.LabelListAttribute
- Srcs_as bazel.LabelListAttribute
-
- Copts bazel.StringListAttribute
- Cppflags bazel.StringListAttribute
- Conlyflags bazel.StringListAttribute
- Asflags bazel.StringListAttribute
- Additional_compiler_inputs bazel.LabelListAttribute
-
- Deps bazel.LabelListAttribute
- Dynamic_deps bazel.LabelListAttribute
- Whole_archive_deps bazel.LabelListAttribute
- System_deps bazel.LabelListAttribute
- Runtime_deps bazel.LabelListAttribute
-
- Local_includes bazel.StringListAttribute
- Absolute_includes bazel.StringListAttribute
-
- Linkopts bazel.StringListAttribute
- Additional_linker_inputs bazel.LabelListAttribute
- Use_version_lib bazel.BoolAttribute
-
- Rtti bazel.BoolAttribute
- Stl *string
- Cpp_std *string
-
- Strip stripAttributes
-
- Features bazel.StringListAttribute
-
- sdkAttributes
-
- tidyAttributes
-
- Native_coverage *bool
-}
diff --git a/cc/binary_test.go b/cc/binary_test.go
index 2fac002..3e18940 100644
--- a/cc/binary_test.go
+++ b/cc/binary_test.go
@@ -17,89 +17,9 @@
import (
"testing"
- "android/soong/bazel/cquery"
-
"android/soong/android"
)
-func TestCcBinaryWithBazel(t *testing.T) {
- t.Parallel()
- bp := `
-cc_binary {
- name: "foo",
- srcs: ["foo.cc"],
- bazel_module: { label: "//foo/bar:bar" },
-}`
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: "outputbase",
- LabelToCcBinary: map[string]cquery.CcUnstrippedInfo{
- "//foo/bar:bar": cquery.CcUnstrippedInfo{
- OutputFile: "foo",
- UnstrippedOutput: "foo.unstripped",
- },
- },
- }
- ctx := testCcWithConfig(t, config)
-
- binMod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module()
- producer := binMod.(android.OutputFileProducer)
- outputFiles, err := producer.OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_binary outputfiles %s", err)
- }
- expectedOutputFiles := []string{"outputbase/execroot/__main__/foo"}
- android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
-
- unStrippedFilePath := binMod.(*Module).UnstrippedOutputFile()
- expectedUnStrippedFile := "outputbase/execroot/__main__/foo.unstripped"
- android.AssertStringEquals(t, "Unstripped output file", expectedUnStrippedFile, unStrippedFilePath.String())
-
- entries := android.AndroidMkEntriesForTest(t, ctx, binMod)[0]
- android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "cc_binary", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
-}
-
-func TestCcBinaryWithBazelValidations(t *testing.T) {
- t.Parallel()
- bp := `
-cc_binary {
- name: "foo",
- srcs: ["foo.cc"],
- bazel_module: { label: "//foo/bar:bar" },
- tidy: true,
-}`
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: "outputbase",
- LabelToCcBinary: map[string]cquery.CcUnstrippedInfo{
- "//foo/bar:bar": cquery.CcUnstrippedInfo{
- OutputFile: "foo",
- UnstrippedOutput: "foo.unstripped",
- TidyFiles: []string{"foo.c.tidy"},
- },
- },
- }
- ctx := android.GroupFixturePreparers(
- prepareForCcTest,
- android.FixtureMergeEnv(map[string]string{
- "ALLOW_LOCAL_TIDY_TRUE": "1",
- }),
- ).RunTestWithConfig(t, config).TestContext
-
- binMod := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Module()
- producer := binMod.(android.OutputFileProducer)
- outputFiles, err := producer.OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_binary outputfiles %s", err)
- }
- expectedOutputFiles := []string{"out/soong/.intermediates/foo/android_arm64_armv8-a/validated/foo"}
- android.AssertPathsRelativeToTopEquals(t, "output files", expectedOutputFiles, outputFiles)
-
- unStrippedFilePath := binMod.(*Module).UnstrippedOutputFile()
- expectedUnStrippedFile := "outputbase/execroot/__main__/foo.unstripped"
- android.AssertStringEquals(t, "Unstripped output file", expectedUnStrippedFile, unStrippedFilePath.String())
-}
-
func TestBinaryLinkerScripts(t *testing.T) {
t.Parallel()
result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, `
diff --git a/cc/bp2build.go b/cc/bp2build.go
deleted file mode 100644
index 62416f7..0000000
--- a/cc/bp2build.go
+++ /dev/null
@@ -1,2088 +0,0 @@
-// 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 cc
-
-import (
- "fmt"
- "path/filepath"
- "strings"
- "sync"
-
- "android/soong/android"
- "android/soong/bazel"
- "android/soong/cc/config"
- "android/soong/genrule"
-
- "github.com/google/blueprint"
-
- "github.com/google/blueprint/proptools"
-)
-
-const (
- cSrcPartition = "c"
- asSrcPartition = "as"
- asmSrcPartition = "asm"
- lSrcPartition = "l"
- llSrcPartition = "ll"
- cppSrcPartition = "cpp"
- protoSrcPartition = "proto"
- aidlSrcPartition = "aidl"
- syspropSrcPartition = "sysprop"
-
- yaccSrcPartition = "yacc"
-
- rScriptSrcPartition = "renderScript"
-
- xsdSrcPartition = "xsd"
-
- genrulePartition = "genrule"
-
- protoFromGenPartition = "proto_gen"
-
- hdrPartition = "hdr"
-
- stubsSuffix = "_stub_libs_current"
-)
-
-// staticOrSharedAttributes are the Bazel-ified versions of StaticOrSharedProperties --
-// properties which apply to either the shared or static version of a cc_library module.
-type staticOrSharedAttributes struct {
- Srcs bazel.LabelListAttribute
- Srcs_c bazel.LabelListAttribute
- Srcs_as bazel.LabelListAttribute
- Srcs_aidl bazel.LabelListAttribute
- Hdrs bazel.LabelListAttribute
- Copts bazel.StringListAttribute
-
- Additional_compiler_inputs bazel.LabelListAttribute
-
- Deps bazel.LabelListAttribute
- Implementation_deps bazel.LabelListAttribute
- Dynamic_deps bazel.LabelListAttribute
- Implementation_dynamic_deps bazel.LabelListAttribute
- Whole_archive_deps bazel.LabelListAttribute
- Implementation_whole_archive_deps bazel.LabelListAttribute
- Runtime_deps bazel.LabelListAttribute
-
- System_dynamic_deps bazel.LabelListAttribute
-
- Enabled bazel.BoolAttribute
-
- Native_coverage *bool
-
- Apex_available []string
-
- Features bazel.StringListAttribute
-
- sdkAttributes
-
- tidyAttributes
-}
-
-type tidyAttributes struct {
- Tidy *string
- Tidy_flags []string
- Tidy_checks []string
- Tidy_checks_as_errors []string
- Tidy_disabled_srcs bazel.LabelListAttribute
- Tidy_timeout_srcs bazel.LabelListAttribute
-}
-
-func (m *Module) convertTidyAttributes(ctx android.BaseMutatorContext, moduleAttrs *tidyAttributes) {
- for _, f := range m.features {
- if tidy, ok := f.(*tidyFeature); ok {
- var tidyAttr *string
- if tidy.Properties.Tidy != nil {
- if *tidy.Properties.Tidy {
- tidyAttr = proptools.StringPtr("local")
- } else {
- tidyAttr = proptools.StringPtr("never")
- }
- }
- moduleAttrs.Tidy = tidyAttr
- moduleAttrs.Tidy_flags = tidy.Properties.Tidy_flags
- moduleAttrs.Tidy_checks = tidy.Properties.Tidy_checks
- moduleAttrs.Tidy_checks_as_errors = tidy.Properties.Tidy_checks_as_errors
- }
-
- }
- archVariantProps := m.GetArchVariantProperties(ctx, &BaseCompilerProperties{})
- for axis, configToProps := range archVariantProps {
- for cfg, _props := range configToProps {
- if archProps, ok := _props.(*BaseCompilerProperties); ok {
- archDisabledSrcs := android.BazelLabelForModuleSrc(ctx, archProps.Tidy_disabled_srcs)
- moduleAttrs.Tidy_disabled_srcs.SetSelectValue(axis, cfg, archDisabledSrcs)
- archTimeoutSrcs := android.BazelLabelForModuleSrc(ctx, archProps.Tidy_timeout_srcs)
- moduleAttrs.Tidy_timeout_srcs.SetSelectValue(axis, cfg, archTimeoutSrcs)
- }
- }
- }
-}
-
-// Returns an unchanged label and a bool indicating whether the dep is a genrule that produces .proto files
-func protoFromGenPartitionMapper(pathCtx android.BazelConversionContext) bazel.LabelMapper {
- return func(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
- mod, exists := ctx.ModuleFromName(label.OriginalModuleName)
- if !exists {
- return label.Label, false
- }
- gen, isGen := mod.(*genrule.Module)
- if !isGen {
- return label.Label, false
- }
- if containsProto(ctx, gen.RawOutputFiles(pathCtx)) {
- // Return unmodified label + true
- // True will ensure that this module gets dropped from `srcs` of the generated cc_* target. `srcs` is reserved for .cpp files
- return label.Label, true
- }
- return label.Label, false
- }
-}
-
-// Returns true if srcs contains only .proto files
-// Raises an exception if there is a combination of .proto and non .proto srcs
-func containsProto(ctx bazel.OtherModuleContext, srcs []string) bool {
- onlyProtos := false
- for _, src := range srcs {
- if strings.HasSuffix(src, ".proto") {
- onlyProtos = true
- } else if onlyProtos {
- // This is not a proto file, and we have encountered a .proto file previously
- ctx.ModuleErrorf("TOOD: Add bp2build support combination of .proto and non .proto files in outs of genrule")
- }
- }
- return onlyProtos
-}
-
-// groupSrcsByExtension partitions `srcs` into groups based on file extension.
-func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute {
- // Convert filegroup dependencies into extension-specific filegroups filtered in the filegroup.bzl
- // macro.
- addSuffixForFilegroup := func(suffix string) bazel.LabelMapper {
- return func(otherModuleCtx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
-
- m, exists := otherModuleCtx.ModuleFromName(label.OriginalModuleName)
- labelStr := label.Label
- if !exists || !android.IsFilegroup(otherModuleCtx, m) {
- return labelStr, false
- }
- // If the filegroup is already converted to aidl_library or proto_library,
- // skip creating _c_srcs, _as_srcs, _cpp_srcs filegroups
- fg, _ := m.(android.FileGroupAsLibrary)
- if fg.ShouldConvertToAidlLibrary(ctx) || fg.ShouldConvertToProtoLibrary(ctx) {
- return labelStr, false
- }
- return labelStr + suffix, true
- }
- }
-
- // TODO(b/190006308): Handle language detection of sources in a Bazel rule.
- labels := bazel.LabelPartitions{
- protoSrcPartition: android.ProtoSrcLabelPartition,
- cSrcPartition: bazel.LabelPartition{Extensions: []string{".c"}, LabelMapper: addSuffixForFilegroup("_c_srcs")},
- asSrcPartition: bazel.LabelPartition{Extensions: []string{".s", ".S"}, LabelMapper: addSuffixForFilegroup("_as_srcs")},
- asmSrcPartition: bazel.LabelPartition{Extensions: []string{".asm"}},
- aidlSrcPartition: android.AidlSrcLabelPartition,
- // TODO(http://b/231968910): If there is ever a filegroup target that
- // contains .l or .ll files we will need to find a way to add a
- // LabelMapper for these that identifies these filegroups and
- // converts them appropriately
- lSrcPartition: bazel.LabelPartition{Extensions: []string{".l"}},
- llSrcPartition: bazel.LabelPartition{Extensions: []string{".ll"}},
- rScriptSrcPartition: bazel.LabelPartition{Extensions: []string{".fs", ".rscript"}},
- xsdSrcPartition: bazel.LabelPartition{LabelMapper: android.XsdLabelMapper(xsdConfigCppTarget)},
- protoFromGenPartition: bazel.LabelPartition{LabelMapper: protoFromGenPartitionMapper(ctx)},
- // C++ is the "catch-all" group, and comprises generated sources because we don't
- // know the language of these sources until the genrule is executed.
- cppSrcPartition: bazel.LabelPartition{Extensions: []string{".cpp", ".cc", ".cxx", ".mm"}, LabelMapper: addSuffixForFilegroup("_cpp_srcs"), Keep_remainder: true},
- syspropSrcPartition: bazel.LabelPartition{Extensions: []string{".sysprop"}},
- yaccSrcPartition: bazel.LabelPartition{Extensions: []string{".y", "yy"}},
- }
-
- return bazel.PartitionLabelListAttribute(ctx, &srcs, labels)
-}
-
-func partitionHeaders(ctx android.BazelConversionPathContext, hdrs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute {
- labels := bazel.LabelPartitions{
- xsdSrcPartition: bazel.LabelPartition{LabelMapper: android.XsdLabelMapper(xsdConfigCppTarget)},
- genrulePartition: bazel.LabelPartition{LabelMapper: genrule.GenruleCcHeaderLabelMapper},
- hdrPartition: bazel.LabelPartition{Keep_remainder: true},
- }
- return bazel.PartitionLabelListAttribute(ctx, &hdrs, labels)
-}
-
-// bp2BuildParseLibProps returns the attributes for a variant of a cc_library.
-func bp2BuildParseLibProps(ctx android.BazelConversionPathContext, module *Module, isStatic bool) staticOrSharedAttributes {
- lib, ok := module.compiler.(*libraryDecorator)
- if !ok {
- return staticOrSharedAttributes{}
- }
- return bp2buildParseStaticOrSharedProps(ctx, module, lib, isStatic)
-}
-
-// bp2buildParseSharedProps returns the attributes for the shared variant of a cc_library.
-func bp2BuildParseSharedProps(ctx android.BazelConversionPathContext, module *Module) staticOrSharedAttributes {
- return bp2BuildParseLibProps(ctx, module, false)
-}
-
-// bp2buildParseStaticProps returns the attributes for the static variant of a cc_library.
-func bp2BuildParseStaticProps(ctx android.BazelConversionPathContext, module *Module) staticOrSharedAttributes {
- return bp2BuildParseLibProps(ctx, module, true)
-}
-
-type depsPartition struct {
- export bazel.LabelList
- implementation bazel.LabelList
-}
-
-type bazelLabelForDepsFn func(android.BazelConversionPathContext, []string) bazel.LabelList
-
-func maybePartitionExportedAndImplementationsDeps(ctx android.BazelConversionPathContext, exportsDeps bool, allDeps, exportedDeps []string, fn bazelLabelForDepsFn) depsPartition {
- if !exportsDeps {
- return depsPartition{
- implementation: fn(ctx, allDeps),
- }
- }
-
- implementation, export := android.FilterList(allDeps, exportedDeps)
-
- return depsPartition{
- export: fn(ctx, export),
- implementation: fn(ctx, implementation),
- }
-}
-
-type bazelLabelForDepsExcludesFn func(android.BazelConversionPathContext, []string, []string) bazel.LabelList
-
-func maybePartitionExportedAndImplementationsDepsExcludes(ctx android.BazelConversionPathContext, exportsDeps bool, allDeps, excludes, exportedDeps []string, fn bazelLabelForDepsExcludesFn) depsPartition {
- if !exportsDeps {
- return depsPartition{
- implementation: fn(ctx, allDeps, excludes),
- }
- }
- implementation, export := android.FilterList(allDeps, exportedDeps)
-
- return depsPartition{
- export: fn(ctx, export, excludes),
- implementation: fn(ctx, implementation, excludes),
- }
-}
-
-func bp2BuildPropParseHelper(ctx android.ArchVariantContext, module *Module, propsType interface{}, parseFunc func(axis bazel.ConfigurationAxis, config string, props interface{})) {
- for axis, configToProps := range module.GetArchVariantProperties(ctx, propsType) {
- for cfg, props := range configToProps {
- parseFunc(axis, cfg, props)
- }
- }
-}
-
-// Parses properties common to static and shared libraries. Also used for prebuilt libraries.
-func bp2buildParseStaticOrSharedProps(ctx android.BazelConversionPathContext, module *Module, lib *libraryDecorator, isStatic bool) staticOrSharedAttributes {
- attrs := staticOrSharedAttributes{}
-
- setAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) {
- attrs.Copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag, filterOutHiddenVisibility))
- attrs.Srcs.SetSelectValue(axis, config, android.BazelLabelForModuleSrc(ctx, props.Srcs))
- attrs.System_dynamic_deps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, props.System_shared_libs))
-
- staticDeps := maybePartitionExportedAndImplementationsDeps(ctx, true, props.Static_libs, props.Export_static_lib_headers, bazelLabelForStaticDeps)
- attrs.Deps.SetSelectValue(axis, config, staticDeps.export)
- attrs.Implementation_deps.SetSelectValue(axis, config, staticDeps.implementation)
-
- sharedDeps := maybePartitionExportedAndImplementationsDeps(ctx, true, props.Shared_libs, props.Export_shared_lib_headers, bazelLabelForSharedDeps)
- attrs.Dynamic_deps.SetSelectValue(axis, config, sharedDeps.export)
- attrs.Implementation_dynamic_deps.SetSelectValue(axis, config, sharedDeps.implementation)
-
- attrs.Whole_archive_deps.SetSelectValue(axis, config, bazelLabelForWholeDeps(ctx, props.Whole_static_libs))
- attrs.Enabled.SetSelectValue(axis, config, props.Enabled)
- }
- // system_dynamic_deps distinguishes between nil/empty list behavior:
- // nil -> use default values
- // empty list -> no values specified
- attrs.System_dynamic_deps.ForceSpecifyEmptyList = true
-
- var apexAvailable []string
- if isStatic {
- apexAvailable = lib.StaticProperties.Static.Apex_available
- bp2BuildPropParseHelper(ctx, module, &StaticProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
- if staticOrSharedProps, ok := props.(*StaticProperties); ok {
- setAttrs(axis, config, staticOrSharedProps.Static)
- }
- })
- } else {
- apexAvailable = lib.SharedProperties.Shared.Apex_available
- bp2BuildPropParseHelper(ctx, module, &SharedProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
- if staticOrSharedProps, ok := props.(*SharedProperties); ok {
- setAttrs(axis, config, staticOrSharedProps.Shared)
- }
- })
- }
-
- partitionedSrcs := groupSrcsByExtension(ctx, attrs.Srcs)
- attrs.Srcs = partitionedSrcs[cppSrcPartition]
- attrs.Srcs_c = partitionedSrcs[cSrcPartition]
- attrs.Srcs_as = partitionedSrcs[asSrcPartition]
-
- attrs.Apex_available = android.ConvertApexAvailableToTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), apexAvailable)
-
- attrs.Features.Append(convertHiddenVisibilityToFeatureStaticOrShared(ctx, module, isStatic))
-
- if !partitionedSrcs[protoSrcPartition].IsEmpty() {
- // TODO(b/208815215): determine whether this is used and add support if necessary
- ctx.ModuleErrorf("Migrating static/shared only proto srcs is not currently supported")
- }
-
- return attrs
-}
-
-// Convenience struct to hold all attributes parsed from prebuilt properties.
-type prebuiltAttributes struct {
- Src bazel.LabelAttribute
- Enabled bazel.BoolAttribute
-}
-
-func parseSrc(ctx android.BazelConversionPathContext, srcLabelAttribute *bazel.LabelAttribute, axis bazel.ConfigurationAxis, config string, srcs []string) {
- srcFileError := func() {
- ctx.ModuleErrorf("parseSrc: Expected at most one source file for %s %s\n", axis, config)
- }
- if len(srcs) > 1 {
- srcFileError()
- return
- } else if len(srcs) == 0 {
- return
- }
- if srcLabelAttribute.SelectValue(axis, config) != nil {
- srcFileError()
- return
- }
- srcLabelAttribute.SetSelectValue(axis, config, android.BazelLabelForModuleSrcSingle(ctx, srcs[0]))
-}
-
-// NOTE: Used outside of Soong repo project, in the clangprebuilts.go bootstrap_go_package
-func Bp2BuildParsePrebuiltLibraryProps(ctx android.BazelConversionPathContext, module *Module, isStatic bool) prebuiltAttributes {
-
- var srcLabelAttribute bazel.LabelAttribute
- bp2BuildPropParseHelper(ctx, module, &prebuiltLinkerProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
- if prebuiltLinkerProperties, ok := props.(*prebuiltLinkerProperties); ok {
- parseSrc(ctx, &srcLabelAttribute, axis, config, prebuiltLinkerProperties.Srcs)
- }
- })
-
- var enabledLabelAttribute bazel.BoolAttribute
- parseAttrs := func(axis bazel.ConfigurationAxis, config string, props StaticOrSharedProperties) {
- if props.Enabled != nil {
- enabledLabelAttribute.SetSelectValue(axis, config, props.Enabled)
- }
- parseSrc(ctx, &srcLabelAttribute, axis, config, props.Srcs)
- }
-
- if isStatic {
- bp2BuildPropParseHelper(ctx, module, &StaticProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
- if staticProperties, ok := props.(*StaticProperties); ok {
- parseAttrs(axis, config, staticProperties.Static)
- }
- })
- } else {
- bp2BuildPropParseHelper(ctx, module, &SharedProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
- if sharedProperties, ok := props.(*SharedProperties); ok {
- parseAttrs(axis, config, sharedProperties.Shared)
- }
- })
- }
-
- return prebuiltAttributes{
- Src: srcLabelAttribute,
- Enabled: enabledLabelAttribute,
- }
-}
-
-func bp2BuildParsePrebuiltBinaryProps(ctx android.BazelConversionPathContext, module *Module) prebuiltAttributes {
- var srcLabelAttribute bazel.LabelAttribute
- bp2BuildPropParseHelper(ctx, module, &prebuiltLinkerProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
- if props, ok := props.(*prebuiltLinkerProperties); ok {
- parseSrc(ctx, &srcLabelAttribute, axis, config, props.Srcs)
- }
- })
-
- return prebuiltAttributes{
- Src: srcLabelAttribute,
- }
-}
-
-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
-
- // A combination of compilerAttributes.features and linkerAttributes.features, as well as sanitizer features
- features bazel.StringListAttribute
- protoDependency *bazel.LabelAttribute
- aidlDependency *bazel.LabelAttribute
- Native_coverage *bool
-}
-
-// Convenience struct to hold all attributes parsed from compiler properties.
-type compilerAttributes struct {
- // Options for all languages
- copts bazel.StringListAttribute
- // Assembly options and sources
- asFlags bazel.StringListAttribute
- asSrcs bazel.LabelListAttribute
- asmSrcs bazel.LabelListAttribute
- // C options and sources
- conlyFlags bazel.StringListAttribute
- cSrcs bazel.LabelListAttribute
- // C++ options and sources
- cppFlags bazel.StringListAttribute
- srcs bazel.LabelListAttribute
-
- // xsd config sources
- xsdSrcs bazel.LabelListAttribute
- exportXsdSrcs bazel.LabelListAttribute
-
- // genrule headers
- genruleHeaders bazel.LabelListAttribute
- exportGenruleHeaders bazel.LabelListAttribute
-
- // Lex sources and options
- lSrcs bazel.LabelListAttribute
- llSrcs bazel.LabelListAttribute
- lexopts bazel.StringListAttribute
-
- // Sysprop sources
- syspropSrcs bazel.LabelListAttribute
-
- // Yacc sources
- yaccSrc *bazel.LabelAttribute
- yaccFlags bazel.StringListAttribute
- yaccGenLocationHeader bazel.BoolAttribute
- yaccGenPositionHeader bazel.BoolAttribute
-
- rsSrcs bazel.LabelListAttribute
-
- hdrs bazel.LabelListAttribute
-
- rtti bazel.BoolAttribute
-
- // Not affected by arch variants
- stl *string
- cStd *string
- cppStd *string
-
- localIncludes bazel.StringListAttribute
- absoluteIncludes bazel.StringListAttribute
-
- includes BazelIncludes
-
- protoSrcs bazel.LabelListAttribute
- aidlSrcs bazel.LabelListAttribute
- rscriptSrcs bazel.LabelListAttribute
-
- stubsSymbolFile *string
- stubsVersions bazel.StringListAttribute
-
- features bazel.StringListAttribute
-
- stem bazel.StringAttribute
- suffix bazel.StringAttribute
-
- fdoProfile bazel.LabelAttribute
-
- additionalCompilerInputs bazel.LabelListAttribute
-}
-
-type filterOutFn func(string) bool
-
-// filterOutHiddenVisibility removes the flag specifying hidden visibility as
-// this flag is converted to a toolchain feature
-func filterOutHiddenVisibility(flag string) bool {
- return flag == config.VisibilityHiddenFlag
-}
-
-func filterOutStdFlag(flag string) bool {
- return strings.HasPrefix(flag, "-std=")
-}
-
-func filterOutClangUnknownCflags(flag string) bool {
- for _, f := range config.ClangUnknownCflags {
- if f == flag {
- return true
- }
- }
- return false
-}
-
-func parseCommandLineFlags(soongFlags []string, filterOut ...filterOutFn) []string {
- var result []string
- for _, flag := range soongFlags {
- skipFlag := false
- for _, filter := range filterOut {
- if filter != nil && filter(flag) {
- skipFlag = true
- }
- }
- if skipFlag {
- continue
- }
- // Soong's cflags can contain spaces, like `-include header.h`. For
- // Bazel's copts, split them up to be compatible with the
- // no_copts_tokenization feature.
- result = append(result, strings.Split(flag, " ")...)
- }
- return result
-}
-
-func (ca *compilerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis, config string, props *BaseCompilerProperties) {
- // If there's arch specific srcs or exclude_srcs, generate a select entry for it.
- // TODO(b/186153868): do this for OS specific srcs and exclude_srcs too.
- srcsList, ok := parseSrcs(ctx, props)
-
- if ok {
- ca.srcs.SetSelectValue(axis, config, srcsList)
- }
-
- localIncludeDirs := props.Local_include_dirs
- if axis == bazel.NoConfigAxis {
- ca.cStd, ca.cppStd = bp2buildResolveCppStdValue(props.C_std, props.Cpp_std, props.Gnu_extensions)
- if includeBuildDirectory(props.Include_build_directory) {
- localIncludeDirs = append(localIncludeDirs, ".")
- }
- }
-
- ca.absoluteIncludes.SetSelectValue(axis, config, props.Include_dirs)
- ca.localIncludes.SetSelectValue(axis, config, localIncludeDirs)
-
- instructionSet := proptools.StringDefault(props.Instruction_set, "")
- if instructionSet == "arm" {
- ca.features.SetSelectValue(axis, config, []string{"arm_isa_arm"})
- } else if instructionSet != "" && instructionSet != "thumb" {
- ctx.ModuleErrorf("Unknown value for instruction_set: %s", instructionSet)
- }
-
- // In Soong, cflags occur on the command line before -std=<val> flag, resulting in the value being
- // overridden. In Bazel we always allow overriding, via flags; however, this can cause
- // incompatibilities, so we remove "-std=" flags from Cflag properties while leaving it in other
- // cases.
- ca.copts.SetSelectValue(axis, config, parseCommandLineFlags(props.Cflags, filterOutStdFlag, filterOutClangUnknownCflags, filterOutHiddenVisibility))
- ca.asFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Asflags, nil))
- ca.conlyFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Conlyflags, filterOutClangUnknownCflags))
- ca.cppFlags.SetSelectValue(axis, config, parseCommandLineFlags(props.Cppflags, filterOutClangUnknownCflags))
- ca.rtti.SetSelectValue(axis, config, props.Rtti)
-}
-
-func (ca *compilerAttributes) convertStlProps(ctx android.ArchVariantContext, module *Module) {
- bp2BuildPropParseHelper(ctx, module, &StlProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
- if stlProps, ok := props.(*StlProperties); ok {
- if stlProps.Stl == nil {
- return
- }
- if ca.stl == nil {
- stl := deduplicateStlInput(*stlProps.Stl)
- ca.stl = &stl
- } else if ca.stl != stlProps.Stl {
- ctx.ModuleErrorf("Unsupported conversion: module with different stl for different variants: %s and %s", *ca.stl, stlProps.Stl)
- }
- }
- })
-}
-
-func (ca *compilerAttributes) convertProductVariables(ctx android.BazelConversionPathContext, productVariableProps android.ProductConfigProperties) {
- productVarPropNameToAttribute := map[string]*bazel.StringListAttribute{
- "Cflags": &ca.copts,
- "Asflags": &ca.asFlags,
- "Cppflags": &ca.cppFlags,
- }
- for propName, attr := range productVarPropNameToAttribute {
- if productConfigProps, exists := productVariableProps[propName]; exists {
- for productConfigProp, prop := range productConfigProps {
- flags, ok := prop.([]string)
- if !ok {
- ctx.ModuleErrorf("Could not convert product variable %s property", proptools.PropertyNameForField(propName))
- }
- newFlags, _ := bazel.TryVariableSubstitutions(flags, productConfigProp.Name())
- attr.SetSelectValue(productConfigProp.ConfigurationAxis(), productConfigProp.SelectKey(), newFlags)
- }
- }
- }
-}
-
-func (ca *compilerAttributes) finalize(ctx android.BazelConversionPathContext, implementationHdrs, exportHdrs bazel.LabelListAttribute) {
- ca.srcs.ResolveExcludes()
- partitionedSrcs := groupSrcsByExtension(ctx, ca.srcs)
- partitionedImplHdrs := partitionHeaders(ctx, implementationHdrs)
- partitionedHdrs := partitionHeaders(ctx, exportHdrs)
-
- ca.protoSrcs = partitionedSrcs[protoSrcPartition]
- ca.protoSrcs.Append(partitionedSrcs[protoFromGenPartition])
- ca.aidlSrcs = partitionedSrcs[aidlSrcPartition]
-
- for p, lla := range partitionedSrcs {
- // if there are no sources, there is no need for headers
- if lla.IsEmpty() {
- continue
- }
- lla.Append(partitionedImplHdrs[hdrPartition])
- partitionedSrcs[p] = lla
- }
-
- ca.hdrs = partitionedHdrs[hdrPartition]
-
- ca.includesFromHeaders(ctx, partitionedImplHdrs[hdrPartition], partitionedHdrs[hdrPartition])
-
- xsdSrcs := bazel.SubtractBazelLabelListAttribute(partitionedSrcs[xsdSrcPartition], partitionedHdrs[xsdSrcPartition])
- xsdSrcs.Append(partitionedImplHdrs[xsdSrcPartition])
- ca.exportXsdSrcs = partitionedHdrs[xsdSrcPartition]
- ca.xsdSrcs = bazel.FirstUniqueBazelLabelListAttribute(xsdSrcs)
-
- ca.genruleHeaders = partitionedImplHdrs[genrulePartition]
- ca.exportGenruleHeaders = partitionedHdrs[genrulePartition]
-
- ca.srcs = partitionedSrcs[cppSrcPartition]
- ca.cSrcs = partitionedSrcs[cSrcPartition]
- ca.asSrcs = partitionedSrcs[asSrcPartition]
- ca.asmSrcs = partitionedSrcs[asmSrcPartition]
- ca.lSrcs = partitionedSrcs[lSrcPartition]
- ca.llSrcs = partitionedSrcs[llSrcPartition]
- if yacc := partitionedSrcs[yaccSrcPartition]; !yacc.IsEmpty() {
- if len(yacc.Value.Includes) > 1 {
- ctx.PropertyErrorf("srcs", "Found multiple yacc (.y/.yy) files in library")
- }
- ca.yaccSrc = bazel.MakeLabelAttribute(yacc.Value.Includes[0].Label)
- }
- ca.syspropSrcs = partitionedSrcs[syspropSrcPartition]
- ca.rscriptSrcs = partitionedSrcs[rScriptSrcPartition]
-
- ca.absoluteIncludes.DeduplicateAxesFromBase()
- ca.localIncludes.DeduplicateAxesFromBase()
-}
-
-// Parse srcs from an arch or OS's props value.
-func parseSrcs(ctx android.BazelConversionPathContext, props *BaseCompilerProperties) (bazel.LabelList, bool) {
- anySrcs := false
- // Add srcs-like dependencies such as generated files.
- // First create a LabelList containing these dependencies, then merge the values with srcs.
- genSrcs := props.Generated_sources
- generatedSrcsLabelList := android.BazelLabelForModuleDepsExcludes(ctx, genSrcs, props.Exclude_generated_sources)
- if len(props.Generated_sources) > 0 || len(props.Exclude_generated_sources) > 0 {
- anySrcs = true
- }
-
- allSrcsLabelList := android.BazelLabelForModuleSrcExcludes(ctx, props.Srcs, props.Exclude_srcs)
-
- if len(props.Srcs) > 0 || len(props.Exclude_srcs) > 0 {
- anySrcs = true
- }
-
- return bazel.AppendBazelLabelLists(allSrcsLabelList, generatedSrcsLabelList), anySrcs
-}
-
-func bp2buildStdVal(std *string, prefix string, useGnu bool) *string {
- defaultVal := prefix + "_std_default"
- // If c{,pp}std properties are not specified, don't generate them in the BUILD file.
- // Defaults are handled by the toolchain definition.
- // However, if gnu_extensions is false, then the default gnu-to-c version must be specified.
- stdVal := proptools.StringDefault(std, defaultVal)
- if stdVal == "experimental" || stdVal == defaultVal {
- if stdVal == "experimental" {
- stdVal = prefix + "_std_experimental"
- }
- if !useGnu {
- stdVal += "_no_gnu"
- }
- } else if !useGnu {
- stdVal = gnuToCReplacer.Replace(stdVal)
- }
-
- if stdVal == defaultVal {
- return nil
- }
- return &stdVal
-}
-
-func bp2buildResolveCppStdValue(c_std *string, cpp_std *string, gnu_extensions *bool) (*string, *string) {
- useGnu := useGnuExtensions(gnu_extensions)
-
- return bp2buildStdVal(c_std, "c", useGnu), bp2buildStdVal(cpp_std, "cpp", useGnu)
-}
-
-// packageFromLabel extracts package from a fully-qualified or relative Label and whether the label
-// is fully-qualified.
-// e.g. fully-qualified "//a/b:foo" -> "a/b", true, relative: ":bar" -> ".", false
-func packageFromLabel(label string) (string, bool) {
- split := strings.Split(label, ":")
- if len(split) != 2 {
- return "", false
- }
- if split[0] == "" {
- return ".", false
- }
- // remove leading "//"
- return split[0][2:], true
-}
-
-// includesFromHeaders gets the include directories needed from generated headers
-func (ca *compilerAttributes) includesFromHeaders(ctx android.BazelConversionPathContext, implHdrs, hdrs bazel.LabelListAttribute) {
- local, absolute := includesFromLabelListAttribute(implHdrs, ca.localIncludes, ca.absoluteIncludes)
- localExport, absoluteExport := includesFromLabelListAttribute(hdrs, ca.includes.Includes, ca.includes.AbsoluteIncludes)
-
- ca.localIncludes = local
- ca.absoluteIncludes = absolute
-
- ca.includes.Includes = localExport
- ca.includes.AbsoluteIncludes = absoluteExport
-}
-
-// includesFromLabelList extracts the packages from a LabelListAttribute that should be includes and
-// combines them with existing local/absolute includes.
-func includesFromLabelListAttribute(attr bazel.LabelListAttribute, existingLocal, existingAbsolute bazel.StringListAttribute) (bazel.StringListAttribute, bazel.StringListAttribute) {
- localAttr := existingLocal.Clone()
- absoluteAttr := existingAbsolute.Clone()
- if !attr.Value.IsEmpty() {
- l, a := includesFromLabelList(attr.Value, existingLocal.Value, existingAbsolute.Value)
- localAttr.SetSelectValue(bazel.NoConfigAxis, "", l)
- absoluteAttr.SetSelectValue(bazel.NoConfigAxis, "", a)
- }
- for axis, configToLabels := range attr.ConfigurableValues {
- for c, labels := range configToLabels {
- local := existingLocal.SelectValue(axis, c)
- absolute := existingAbsolute.SelectValue(axis, c)
- l, a := includesFromLabelList(labels, local, absolute)
- localAttr.SetSelectValue(axis, c, l)
- absoluteAttr.SetSelectValue(axis, c, a)
- }
- }
- return *localAttr, *absoluteAttr
-}
-
-// includesFromLabelList extracts relative/absolute includes from a bazel.LabelList.
-func includesFromLabelList(labelList bazel.LabelList, existingRel, existingAbs []string) ([]string, []string) {
- var relative, absolute []string
- for _, hdr := range labelList.Includes {
- if pkg, hasPkg := packageFromLabel(hdr.Label); hasPkg {
- absolute = append(absolute, pkg)
- } else if pkg != "" {
- relative = append(relative, pkg)
- }
- }
- if len(relative)+len(existingRel) != 0 {
- relative = android.FirstUniqueStrings(append(append([]string{}, existingRel...), relative...))
- }
- if len(absolute)+len(existingAbs) != 0 {
- absolute = android.FirstUniqueStrings(append(append([]string{}, existingAbs...), absolute...))
- }
- return relative, absolute
-}
-
-type YasmAttributes struct {
- Srcs bazel.LabelListAttribute
- Flags bazel.StringListAttribute
- Include_dirs bazel.StringListAttribute
-}
-
-func bp2BuildYasm(ctx android.Bp2buildMutatorContext, m *Module, ca compilerAttributes) *bazel.LabelAttribute {
- if ca.asmSrcs.IsEmpty() {
- return nil
- }
-
- // Yasm needs the include directories from both local_includes and
- // export_include_dirs. We don't care about actually exporting them from the
- // yasm rule though, because they will also be present on the cc_ rule that
- // wraps this yasm rule.
- includes := ca.localIncludes.Clone()
- bp2BuildPropParseHelper(ctx, m, &FlagExporterProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
- if flagExporterProperties, ok := props.(*FlagExporterProperties); ok {
- if len(flagExporterProperties.Export_include_dirs) > 0 {
- x := bazel.StringListAttribute{}
- x.SetSelectValue(axis, config, flagExporterProperties.Export_include_dirs)
- includes.Append(x)
- }
- }
- })
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "yasm",
- Bzl_load_location: "//build/bazel/rules/cc:yasm.bzl",
- },
- android.CommonAttributes{Name: m.Name() + "_yasm"},
- &YasmAttributes{
- Srcs: ca.asmSrcs,
- Flags: ca.asFlags,
- Include_dirs: *includes,
- })
-
- // We only want to add a dependency on the _yasm target if there are asm
- // sources in the current configuration. If there are unconfigured asm
- // sources, always add the dependency. Otherwise, add the dependency only
- // on the configuration axes and values that had asm sources.
- if len(ca.asmSrcs.Value.Includes) > 0 {
- return bazel.MakeLabelAttribute(":" + m.Name() + "_yasm")
- }
-
- ret := &bazel.LabelAttribute{}
- for _, axis := range ca.asmSrcs.SortedConfigurationAxes() {
- for cfg := range ca.asmSrcs.ConfigurableValues[axis] {
- ret.SetSelectValue(axis, cfg, bazel.Label{Label: ":" + m.Name() + "_yasm"})
- }
- }
- return ret
-}
-
-// bp2BuildParseBaseProps returns all compiler, linker, library attributes of a cc module.
-func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) baseAttributes {
- archVariantCompilerProps := module.GetArchVariantProperties(ctx, &BaseCompilerProperties{})
- archVariantLinkerProps := module.GetArchVariantProperties(ctx, &BaseLinkerProperties{})
- archVariantLibraryProperties := module.GetArchVariantProperties(ctx, &LibraryProperties{})
-
- axisToConfigs := map[bazel.ConfigurationAxis]map[string]bool{}
- allAxesAndConfigs := func(cp android.ConfigurationAxisToArchVariantProperties) {
- for axis, configMap := range cp {
- if _, ok := axisToConfigs[axis]; !ok {
- axisToConfigs[axis] = map[string]bool{}
- }
- for cfg := range configMap {
- axisToConfigs[axis][cfg] = true
- }
- }
- }
- allAxesAndConfigs(archVariantCompilerProps)
- allAxesAndConfigs(archVariantLinkerProps)
- allAxesAndConfigs(archVariantLibraryProperties)
-
- compilerAttrs := compilerAttributes{}
- linkerAttrs := linkerAttributes{}
-
- var aidlLibs bazel.LabelList
- var implementationHdrs, exportHdrs bazel.LabelListAttribute
-
- // Iterate through these axes in a deterministic order. This is required
- // because processing certain dependencies may result in concatenating
- // elements along other axes. (For example, processing NoConfig may result
- // in elements being added to InApex). This is thus the only way to ensure
- // that the order of entries in each list is in a predictable order.
- for _, axis := range bazel.SortedConfigurationAxes(axisToConfigs) {
- configs := axisToConfigs[axis]
- for cfg := range configs {
- var allHdrs []string
- if baseCompilerProps, ok := archVariantCompilerProps[axis][cfg].(*BaseCompilerProperties); ok {
- allHdrs = baseCompilerProps.Generated_headers
-
- if baseCompilerProps.Lex != nil {
- compilerAttrs.lexopts.SetSelectValue(axis, cfg, baseCompilerProps.Lex.Flags)
- }
- if baseCompilerProps.Yacc != nil {
- compilerAttrs.yaccFlags.SetSelectValue(axis, cfg, baseCompilerProps.Yacc.Flags)
- compilerAttrs.yaccGenLocationHeader.SetSelectValue(axis, cfg, baseCompilerProps.Yacc.Gen_location_hh)
- compilerAttrs.yaccGenPositionHeader.SetSelectValue(axis, cfg, baseCompilerProps.Yacc.Gen_position_hh)
- }
- (&compilerAttrs).bp2buildForAxisAndConfig(ctx, axis, cfg, baseCompilerProps)
- aidlLibs.Append(android.BazelLabelForModuleDeps(ctx, baseCompilerProps.Aidl.Libs))
- }
-
- var exportedHdrs []string
-
- if baseLinkerProps, ok := archVariantLinkerProps[axis][cfg].(*BaseLinkerProperties); ok {
- exportedHdrs = baseLinkerProps.Export_generated_headers
- (&linkerAttrs).bp2buildForAxisAndConfig(ctx, module, axis, cfg, baseLinkerProps)
- }
-
- headers := maybePartitionExportedAndImplementationsDeps(ctx, !module.Binary(), allHdrs, exportedHdrs, android.BazelLabelForModuleDeps)
-
- implementationHdrs.SetSelectValue(axis, cfg, headers.implementation)
- exportHdrs.SetSelectValue(axis, cfg, headers.export)
-
- if libraryProps, ok := archVariantLibraryProperties[axis][cfg].(*LibraryProperties); ok {
- if axis == bazel.NoConfigAxis {
- if libraryProps.Stubs.Symbol_file != nil {
- compilerAttrs.stubsSymbolFile = libraryProps.Stubs.Symbol_file
- versions := android.CopyOf(libraryProps.Stubs.Versions)
- normalizeVersions(ctx, versions)
- versions = addCurrentVersionIfNotPresent(versions)
- compilerAttrs.stubsVersions.SetSelectValue(axis, cfg, versions)
- }
- }
- if stem := libraryProps.Stem; stem != nil {
- compilerAttrs.stem.SetSelectValue(axis, cfg, stem)
- }
- if suffix := libraryProps.Suffix; suffix != nil {
- compilerAttrs.suffix.SetSelectValue(axis, cfg, suffix)
- }
- }
-
- }
- }
-
- compilerAttrs.convertStlProps(ctx, module)
- (&linkerAttrs).convertStripProps(ctx, module)
-
- var nativeCoverage *bool
- if module.coverage != nil && module.coverage.Properties.Native_coverage != nil &&
- !Bool(module.coverage.Properties.Native_coverage) {
- nativeCoverage = BoolPtr(false)
- }
-
- productVariableProps := android.ProductVariableProperties(ctx, ctx.Module())
-
- (&compilerAttrs).convertProductVariables(ctx, productVariableProps)
- (&linkerAttrs).convertProductVariables(ctx, productVariableProps)
-
- (&compilerAttrs).finalize(ctx, implementationHdrs, exportHdrs)
- (&linkerAttrs).finalize(ctx)
-
- (&compilerAttrs.srcs).Add(bp2BuildYasm(ctx, module, compilerAttrs))
-
- (&linkerAttrs).deps.Append(compilerAttrs.exportGenruleHeaders)
- (&linkerAttrs).implementationDeps.Append(compilerAttrs.genruleHeaders)
-
- (&linkerAttrs).wholeArchiveDeps.Append(compilerAttrs.exportXsdSrcs)
- (&linkerAttrs).implementationWholeArchiveDeps.Append(compilerAttrs.xsdSrcs)
-
- protoDep := bp2buildProto(ctx, module, compilerAttrs.protoSrcs, linkerAttrs)
-
- // bp2buildProto will only set wholeStaticLib or implementationWholeStaticLib, but we don't know
- // which. This will add the newly generated proto library to the appropriate attribute and nothing
- // to the other
- (&linkerAttrs).wholeArchiveDeps.Add(protoDep.wholeStaticLib)
- (&linkerAttrs).implementationWholeArchiveDeps.Add(protoDep.implementationWholeStaticLib)
-
- aidlDep := bp2buildCcAidlLibrary(
- ctx, module,
- compilerAttrs.aidlSrcs,
- bazel.LabelListAttribute{
- Value: aidlLibs,
- },
- linkerAttrs,
- compilerAttrs,
- )
- if aidlDep != nil {
- if lib, ok := module.linker.(*libraryDecorator); ok {
- if proptools.Bool(lib.Properties.Aidl.Export_aidl_headers) {
- (&linkerAttrs).wholeArchiveDeps.Add(aidlDep)
- } else {
- (&linkerAttrs).implementationWholeArchiveDeps.Add(aidlDep)
- }
- }
- }
-
- // Create a cc_yacc_static_library if srcs contains .y/.yy files
- // This internal target will produce an .a file that will be statically linked to the parent library
- if yaccDep := bp2buildCcYaccLibrary(ctx, compilerAttrs, linkerAttrs); yaccDep != nil {
- (&linkerAttrs).implementationWholeArchiveDeps.Add(yaccDep)
- }
-
- convertedLSrcs := bp2BuildLex(ctx, module.Name(), compilerAttrs)
- (&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))
- }
-
- linkerAttrs.wholeArchiveDeps.Prepend = true
- linkerAttrs.deps.Prepend = true
- compilerAttrs.localIncludes.Prepend = true
- compilerAttrs.absoluteIncludes.Prepend = true
- compilerAttrs.hdrs.Prepend = true
-
- convertedRsSrcs, rsAbsIncludes, rsLocalIncludes := bp2buildRScript(ctx, module, compilerAttrs)
- (&compilerAttrs).srcs.Add(&convertedRsSrcs)
- (&compilerAttrs).absoluteIncludes.Append(rsAbsIncludes)
- (&compilerAttrs).localIncludes.Append(rsLocalIncludes)
- (&compilerAttrs).localIncludes.Value = android.FirstUniqueStrings(compilerAttrs.localIncludes.Value)
-
- sanitizerValues := bp2buildSanitizerFeatures(ctx, module)
-
- features := compilerAttrs.features.Clone().Append(linkerAttrs.features).Append(sanitizerValues.features)
- features = features.Append(bp2buildLtoFeatures(ctx, module))
- features = features.Append(convertHiddenVisibilityToFeatureBase(ctx, module))
- features.DeduplicateAxesFromBase()
-
- compilerAttrs.copts = *compilerAttrs.copts.Append(sanitizerValues.copts)
- compilerAttrs.additionalCompilerInputs = *compilerAttrs.additionalCompilerInputs.Append(sanitizerValues.additionalCompilerInputs)
-
- addMuslSystemDynamicDeps(ctx, linkerAttrs)
-
- // Dedupe all deps.
- (&linkerAttrs).deps.Value = bazel.FirstUniqueBazelLabelList((&linkerAttrs).deps.Value)
- (&linkerAttrs).implementationDeps.Value = bazel.FirstUniqueBazelLabelList((&linkerAttrs).implementationDeps.Value)
- (&linkerAttrs).implementationDynamicDeps.Value = bazel.FirstUniqueBazelLabelList((&linkerAttrs).implementationDynamicDeps.Value)
- (&linkerAttrs).wholeArchiveDeps.Value = bazel.FirstUniqueBazelLabelList((&linkerAttrs).wholeArchiveDeps.Value)
- (&linkerAttrs).implementationWholeArchiveDeps.Value = bazel.FirstUniqueBazelLabelList((&linkerAttrs).implementationWholeArchiveDeps.Value)
-
- return baseAttributes{
- compilerAttrs,
- linkerAttrs,
- *features,
- protoDep.protoDep,
- aidlDep,
- nativeCoverage,
- }
-}
-
-type ccYaccLibraryAttributes struct {
- Src bazel.LabelAttribute
- Flags bazel.StringListAttribute
- Gen_location_hh bazel.BoolAttribute
- Gen_position_hh bazel.BoolAttribute
- Local_includes bazel.StringListAttribute
- Implementation_deps bazel.LabelListAttribute
- Implementation_dynamic_deps bazel.LabelListAttribute
-}
-
-func bp2buildCcYaccLibrary(ctx android.Bp2buildMutatorContext, ca compilerAttributes, la linkerAttributes) *bazel.LabelAttribute {
- if ca.yaccSrc == nil {
- return nil
- }
- yaccLibraryLabel := ctx.Module().Name() + "_yacc"
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "cc_yacc_static_library",
- Bzl_load_location: "//build/bazel/rules/cc:cc_yacc_library.bzl",
- },
- android.CommonAttributes{
- Name: yaccLibraryLabel,
- },
- &ccYaccLibraryAttributes{
- Src: *ca.yaccSrc,
- Flags: ca.yaccFlags,
- Gen_location_hh: ca.yaccGenLocationHeader,
- Gen_position_hh: ca.yaccGenPositionHeader,
- Local_includes: ca.localIncludes,
- Implementation_deps: la.implementationDeps,
- Implementation_dynamic_deps: la.implementationDynamicDeps,
- },
- )
-
- yaccLibrary := &bazel.LabelAttribute{
- Value: &bazel.Label{
- Label: ":" + yaccLibraryLabel,
- },
- }
- return yaccLibrary
-}
-
-// As a workaround for b/261657184, we are manually adding the default value
-// of system_dynamic_deps for the linux_musl os.
-// TODO: Solve this properly
-func addMuslSystemDynamicDeps(ctx android.Bp2buildMutatorContext, attrs linkerAttributes) {
- systemDynamicDeps := attrs.systemDynamicDeps.SelectValue(bazel.OsConfigurationAxis, "linux_musl")
- if attrs.systemDynamicDeps.HasAxisSpecificValues(bazel.OsConfigurationAxis) && systemDynamicDeps.IsNil() {
- attrs.systemDynamicDeps.SetSelectValue(bazel.OsConfigurationAxis, "linux_musl", android.BazelLabelForModuleDeps(ctx, config.MuslDefaultSharedLibraries))
- }
-}
-
-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,
- aidlSrcs bazel.LabelListAttribute,
- aidlLibs bazel.LabelListAttribute,
- linkerAttrs linkerAttributes,
- compilerAttrs compilerAttributes,
-) *bazel.LabelAttribute {
- var aidlLibsFromSrcs, aidlFiles bazel.LabelListAttribute
- apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), ctx.Module())
-
- if !aidlSrcs.IsEmpty() {
- aidlLibsFromSrcs, aidlFiles = aidlSrcs.Partition(func(src bazel.Label) bool {
- if fg, ok := android.ToFileGroupAsLibrary(ctx, src.OriginalModuleName); ok &&
- fg.ShouldConvertToAidlLibrary(ctx) {
- return true
- }
- return false
- })
-
- if !aidlFiles.IsEmpty() {
- aidlLibName := m.Name() + "_aidl_library"
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "aidl_library",
- Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
- },
- android.CommonAttributes{
- Name: aidlLibName,
- Tags: apexAvailableTags,
- },
- &aidlLibraryAttributes{
- Srcs: aidlFiles,
- },
- )
- aidlLibsFromSrcs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}})
- }
- }
-
- allAidlLibs := aidlLibs.Clone()
- allAidlLibs.Append(aidlLibsFromSrcs)
-
- if !allAidlLibs.IsEmpty() {
- ccAidlLibrarylabel := m.Name() + "_cc_aidl_library"
- // Since parent cc_library already has these dependencies, we can add them as implementation
- // deps so that they don't re-export
- implementationDeps := linkerAttrs.deps.Clone()
- implementationDeps.Append(linkerAttrs.implementationDeps)
- implementationDynamicDeps := linkerAttrs.dynamicDeps.Clone()
- implementationDynamicDeps.Append(linkerAttrs.implementationDynamicDeps)
-
- sdkAttrs := bp2BuildParseSdkAttributes(m)
-
- exportedIncludes := bp2BuildParseExportedIncludes(ctx, m, &compilerAttrs.includes)
- includeAttrs := includesAttributes{
- Export_includes: exportedIncludes.Includes,
- Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
- Export_system_includes: exportedIncludes.SystemIncludes,
- Local_includes: compilerAttrs.localIncludes,
- Absolute_includes: compilerAttrs.absoluteIncludes,
- }
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "cc_aidl_library",
- Bzl_load_location: "//build/bazel/rules/cc:cc_aidl_library.bzl",
- },
- android.CommonAttributes{Name: ccAidlLibrarylabel},
- &ccAidlLibraryAttributes{
- Deps: *allAidlLibs,
- Implementation_deps: *implementationDeps,
- Implementation_dynamic_deps: *implementationDynamicDeps,
- Tags: apexAvailableTags,
- sdkAttributes: sdkAttrs,
- includesAttributes: includeAttrs,
- },
- )
- label := &bazel.LabelAttribute{
- Value: &bazel.Label{
- Label: ":" + ccAidlLibrarylabel,
- },
- }
- return label
- }
-
- return nil
-}
-
-func bp2BuildParseSdkAttributes(module *Module) sdkAttributes {
- return sdkAttributes{
- Sdk_version: module.Properties.Sdk_version,
- Min_sdk_version: module.Properties.Min_sdk_version,
- }
-}
-
-type sdkAttributes struct {
- Sdk_version *string
- Min_sdk_version *string
-}
-
-// Convenience struct to hold all attributes parsed from linker properties.
-type linkerAttributes struct {
- deps bazel.LabelListAttribute
- implementationDeps bazel.LabelListAttribute
- dynamicDeps bazel.LabelListAttribute
- implementationDynamicDeps bazel.LabelListAttribute
- runtimeDeps bazel.LabelListAttribute
- wholeArchiveDeps bazel.LabelListAttribute
- implementationWholeArchiveDeps bazel.LabelListAttribute
- systemDynamicDeps bazel.LabelListAttribute
- usedSystemDynamicDepAsStaticDep map[string]bool
- usedSystemDynamicDepAsDynamicDep map[string]bool
-
- useVersionLib bazel.BoolAttribute
- linkopts bazel.StringListAttribute
- additionalLinkerInputs bazel.LabelListAttribute
- stripKeepSymbols bazel.BoolAttribute
- stripKeepSymbolsAndDebugFrame bazel.BoolAttribute
- stripKeepSymbolsList bazel.StringListAttribute
- stripAll bazel.BoolAttribute
- stripNone bazel.BoolAttribute
- features bazel.StringListAttribute
-}
-
-var (
- soongSystemSharedLibs = []string{"libc", "libm", "libdl"}
- versionLib = "libbuildversion"
-)
-
-// resolveTargetApex re-adds the shared and static libs in target.apex.exclude_shared|static_libs props to non-apex variant
-// since all libs are already excluded by default
-func (la *linkerAttributes) resolveTargetApexProp(ctx android.BazelConversionPathContext, props *BaseLinkerProperties) {
- excludeSharedLibs := bazelLabelForSharedDeps(ctx, props.Target.Apex.Exclude_shared_libs)
- sharedExcludes := bazel.LabelList{Excludes: excludeSharedLibs.Includes}
- sharedExcludesLabelList := bazel.LabelListAttribute{}
- sharedExcludesLabelList.SetSelectValue(bazel.InApexAxis, bazel.InApex, sharedExcludes)
-
- la.dynamicDeps.Append(sharedExcludesLabelList)
- la.implementationDynamicDeps.Append(sharedExcludesLabelList)
-
- excludeStaticLibs := bazelLabelForStaticDeps(ctx, props.Target.Apex.Exclude_static_libs)
- staticExcludes := bazel.LabelList{Excludes: excludeStaticLibs.Includes}
- staticExcludesLabelList := bazel.LabelListAttribute{}
- staticExcludesLabelList.SetSelectValue(bazel.InApexAxis, bazel.InApex, staticExcludes)
-
- la.deps.Append(staticExcludesLabelList)
- la.implementationDeps.Append(staticExcludesLabelList)
-}
-
-func (la *linkerAttributes) bp2buildForAxisAndConfig(ctx android.BazelConversionPathContext, module *Module, axis bazel.ConfigurationAxis, config string, props *BaseLinkerProperties) {
- isBinary := module.Binary()
- // Use a single variable to capture usage of nocrt in arch variants, so there's only 1 error message for this module
- var axisFeatures []string
-
- wholeStaticLibs := android.FirstUniqueStrings(props.Whole_static_libs)
- staticLibs := android.FirstUniqueStrings(android.RemoveListFromList(props.Static_libs, wholeStaticLibs))
- if axis == bazel.NoConfigAxis {
- la.useVersionLib.SetSelectValue(axis, config, props.Use_version_lib)
- if proptools.Bool(props.Use_version_lib) {
- versionLibAlreadyInDeps := android.InList(versionLib, wholeStaticLibs)
- // remove from static libs so there is no duplicate dependency
- _, staticLibs = android.RemoveFromList(versionLib, staticLibs)
- // only add the dep if it is not in progress
- if !versionLibAlreadyInDeps {
- wholeStaticLibs = append(wholeStaticLibs, versionLib)
- }
- }
- }
-
- // Excludes to parallel Soong:
- // https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/linker.go;l=247-249;drc=088b53577dde6e40085ffd737a1ae96ad82fc4b0
- la.wholeArchiveDeps.SetSelectValue(axis, config, bazelLabelForWholeDepsExcludes(ctx, wholeStaticLibs, props.Exclude_static_libs))
-
- if isBinary && module.StaticExecutable() {
- usedSystemStatic := android.FilterListPred(staticLibs, func(s string) bool {
- return android.InList(s, soongSystemSharedLibs) && !android.InList(s, props.Exclude_static_libs)
- })
-
- for _, el := range usedSystemStatic {
- if la.usedSystemDynamicDepAsStaticDep == nil {
- la.usedSystemDynamicDepAsStaticDep = map[string]bool{}
- }
- la.usedSystemDynamicDepAsStaticDep[el] = true
- }
- }
- staticDeps := maybePartitionExportedAndImplementationsDepsExcludes(
- ctx,
- !isBinary,
- staticLibs,
- props.Exclude_static_libs,
- props.Export_static_lib_headers,
- bazelLabelForStaticDepsExcludes,
- )
-
- headerLibs := android.FirstUniqueStrings(props.Header_libs)
- hDeps := maybePartitionExportedAndImplementationsDeps(ctx, !isBinary, headerLibs, props.Export_header_lib_headers, bazelLabelForHeaderDeps)
-
- (&hDeps.export).Append(staticDeps.export)
- la.deps.SetSelectValue(axis, config, hDeps.export)
-
- (&hDeps.implementation).Append(staticDeps.implementation)
- la.implementationDeps.SetSelectValue(axis, config, hDeps.implementation)
-
- systemSharedLibs := props.System_shared_libs
- // systemSharedLibs distinguishes between nil/empty list behavior:
- // nil -> use default values
- // empty list -> no values specified
- if len(systemSharedLibs) > 0 {
- systemSharedLibs = android.FirstUniqueStrings(systemSharedLibs)
- }
- la.systemDynamicDeps.SetSelectValue(axis, config, bazelLabelForSharedDeps(ctx, systemSharedLibs))
-
- sharedLibs := android.FirstUniqueStrings(props.Shared_libs)
- excludeSharedLibs := props.Exclude_shared_libs
- usedSystem := android.FilterListPred(sharedLibs, func(s string) bool {
- return android.InList(s, soongSystemSharedLibs) && !android.InList(s, excludeSharedLibs)
- })
-
- for _, el := range usedSystem {
- if la.usedSystemDynamicDepAsDynamicDep == nil {
- la.usedSystemDynamicDepAsDynamicDep = map[string]bool{}
- }
- la.usedSystemDynamicDepAsDynamicDep[el] = true
- }
-
- sharedDeps := maybePartitionExportedAndImplementationsDepsExcludes(
- ctx,
- !isBinary,
- sharedLibs,
- props.Exclude_shared_libs,
- props.Export_shared_lib_headers,
- bazelLabelForSharedDepsExcludes,
- )
- la.dynamicDeps.SetSelectValue(axis, config, sharedDeps.export)
- la.implementationDynamicDeps.SetSelectValue(axis, config, sharedDeps.implementation)
- la.resolveTargetApexProp(ctx, props)
-
- if axis == bazel.NoConfigAxis || (axis == bazel.OsConfigurationAxis && config == bazel.OsAndroid) {
- // If a dependency in la.implementationDynamicDeps or la.dynamicDeps has stubs, its
- // stub variant should be used when the dependency is linked in a APEX. The
- // dependencies in NoConfigAxis and OsConfigurationAxis/OsAndroid are grouped by
- // having stubs or not, so Bazel select() statement can be used to choose
- // source/stub variants of them.
- apexAvailable := module.ApexAvailable()
- setStubsForDynamicDeps(ctx, axis, config, apexAvailable, sharedDeps.export, &la.dynamicDeps, 0, false)
- setStubsForDynamicDeps(ctx, axis, config, apexAvailable, sharedDeps.implementation, &la.implementationDynamicDeps, 1, false)
- if len(systemSharedLibs) > 0 {
- setStubsForDynamicDeps(ctx, axis, config, apexAvailable, bazelLabelForSharedDeps(ctx, systemSharedLibs), &la.systemDynamicDeps, 2, true)
- }
- }
-
- if !BoolDefault(props.Pack_relocations, packRelocationsDefault) {
- axisFeatures = append(axisFeatures, "disable_pack_relocations")
- }
-
- if Bool(props.Allow_undefined_symbols) {
- axisFeatures = append(axisFeatures, "-no_undefined_symbols")
- }
-
- var linkerFlags []string
- if len(props.Ldflags) > 0 {
- linkerFlags = append(linkerFlags, proptools.NinjaEscapeList(props.Ldflags)...)
- // binaries remove static flag if -shared is in the linker flags
- if isBinary && android.InList("-shared", linkerFlags) {
- axisFeatures = append(axisFeatures, "-static_flag")
- }
- }
-
- if !props.libCrt() {
- axisFeatures = append(axisFeatures, "-use_libcrt")
- }
- if !props.crt() {
- axisFeatures = append(axisFeatures, "-link_crt")
- }
-
- // This must happen before the addition of flags for Version Script and
- // Dynamic List, as these flags must be split on spaces and those must not
- linkerFlags = parseCommandLineFlags(linkerFlags, filterOutClangUnknownCflags)
-
- additionalLinkerInputs := bazel.LabelList{}
- if props.Version_script != nil {
- label := android.BazelLabelForModuleSrcSingle(ctx, *props.Version_script)
- additionalLinkerInputs.Add(&label)
- linkerFlags = append(linkerFlags, fmt.Sprintf("-Wl,--version-script,$(location %s)", label.Label))
- axisFeatures = append(axisFeatures, "android_cfi_exports_map")
- }
-
- if props.Dynamic_list != nil {
- label := android.BazelLabelForModuleSrcSingle(ctx, *props.Dynamic_list)
- additionalLinkerInputs.Add(&label)
- linkerFlags = append(linkerFlags, fmt.Sprintf("-Wl,--dynamic-list,$(location %s)", label.Label))
- }
-
- la.additionalLinkerInputs.SetSelectValue(axis, config, additionalLinkerInputs)
- if axis == bazel.OsConfigurationAxis && (config == bazel.OsDarwin || config == bazel.OsLinux || config == bazel.OsWindows) {
- linkerFlags = append(linkerFlags, props.Host_ldlibs...)
- }
- la.linkopts.SetSelectValue(axis, config, linkerFlags)
-
- if axisFeatures != nil {
- la.features.SetSelectValue(axis, config, axisFeatures)
- }
-
- runtimeDeps := android.BazelLabelForModuleDepsExcludes(ctx, props.Runtime_libs, props.Exclude_runtime_libs)
- if !runtimeDeps.IsEmpty() {
- la.runtimeDeps.SetSelectValue(axis, config, runtimeDeps)
- }
-}
-
-var (
- apiSurfaceModuleLibCurrentPackage = "@api_surfaces//" + android.ModuleLibApi.String() + "/current:"
-)
-
-func availableToSameApexes(a, b []string) bool {
- if len(a) == 0 && len(b) == 0 {
- return true
- }
- differ, _, _ := android.ListSetDifference(a, b)
- return !differ
-}
-
-var (
- apiDomainConfigSettingKey = android.NewOnceKey("apiDomainConfigSettingKey")
- apiDomainConfigSettingLock sync.Mutex
-)
-
-func getApiDomainConfigSettingMap(config android.Config) *map[string]bool {
- return config.Once(apiDomainConfigSettingKey, func() interface{} {
- return &map[string]bool{}
- }).(*map[string]bool)
-}
-
-var (
- testApexNameToApiDomain = map[string]string{
- "test_broken_com.android.art": "com.android.art",
- }
-)
-
-// GetApiDomain returns the canonical name of the apex. This is synonymous to the apex_name definition.
-// https://cs.android.com/android/_/android/platform/build/soong/+/e3f0281b8897da1fe23b2f4f3a05f1dc87bcc902:apex/prebuilt.go;l=81-83;drc=2dc7244af985a6ad701b22f1271e606cabba527f;bpv=1;bpt=0
-// For test apexes, it uses a naming convention heuristic to determine the api domain.
-// TODO (b/281548611): Move this build/soong/android
-func GetApiDomain(apexName string) string {
- if apiDomain, exists := testApexNameToApiDomain[apexName]; exists {
- return apiDomain
- }
- // Remove `test_` prefix
- return strings.TrimPrefix(apexName, "test_")
-}
-
-// Create a config setting for this apex in build/bazel/rules/apex
-// The use case for this is stub/impl selection in cc libraries
-// Long term, these config_setting(s) should be colocated with the respective apex definitions.
-// Note that this is an anti-pattern: The config_setting should be created from the apex definition
-// and not from a cc_library.
-// This anti-pattern is needed today since not all apexes have been allowlisted.
-func createInApexConfigSetting(ctx android.TopDownMutatorContext, apexName string) {
- if apexName == android.AvailableToPlatform || apexName == android.AvailableToAnyApex {
- // These correspond to android-non_apex and android-in_apex
- return
- }
- apiDomainConfigSettingLock.Lock()
- defer apiDomainConfigSettingLock.Unlock()
-
- // Return if a config_setting has already been created
- apiDomain := GetApiDomain(apexName)
- acsm := getApiDomainConfigSettingMap(ctx.Config())
- if _, exists := (*acsm)[apiDomain]; exists {
- return
- }
- (*acsm)[apiDomain] = true
-
- csa := bazel.ConfigSettingAttributes{
- Flag_values: bazel.StringMapAttribute{
- "//build/bazel/rules/apex:api_domain": apiDomain,
- },
- // Constraint this to android
- Constraint_values: bazel.MakeLabelListAttribute(
- bazel.MakeLabelList(
- []bazel.Label{
- bazel.Label{Label: "//build/bazel/platforms/os:android"},
- },
- ),
- ),
- }
- ca := android.CommonAttributes{
- Name: apiDomain,
- }
- ctx.CreateBazelConfigSetting(
- csa,
- ca,
- "build/bazel/rules/apex",
- )
-}
-
-func inApexConfigSetting(apexAvailable string) string {
- if apexAvailable == android.AvailableToPlatform {
- return bazel.AndroidPlatform
- }
- if apexAvailable == android.AvailableToAnyApex {
- return bazel.AndroidAndInApex
- }
- apiDomain := GetApiDomain(apexAvailable)
- return "//build/bazel/rules/apex:" + apiDomain
-}
-
-// Inputs to stub vs impl selection.
-type stubSelectionInfo struct {
- // Label of the implementation library (e.g. //bionic/libc:libc)
- impl bazel.Label
- // Axis containing the implementation library
- axis bazel.ConfigurationAxis
- // Axis key containing the implementation library
- config string
- // API domain of the apex
- // For test apexes (test_com.android.foo), this will be the source apex (com.android.foo)
- apiDomain string
- // List of dep labels
- dynamicDeps *bazel.LabelListAttribute
- // Boolean value for determining if the dep is in the same api domain
- // If false, the label will be rewritten to to the stub label
- sameApiDomain bool
-}
-
-func useStubOrImplInApexWithName(ssi stubSelectionInfo) {
- lib := ssi.impl
- if !ssi.sameApiDomain {
- lib = bazel.Label{
- Label: apiSurfaceModuleLibCurrentPackage + strings.TrimPrefix(lib.OriginalModuleName, ":"),
- }
- }
- // Create a select statement specific to this apex
- inApexSelectValue := ssi.dynamicDeps.SelectValue(bazel.OsAndInApexAxis, inApexConfigSetting(ssi.apiDomain))
- (&inApexSelectValue).Append(bazel.MakeLabelList([]bazel.Label{lib}))
- ssi.dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, inApexConfigSetting(ssi.apiDomain), bazel.FirstUniqueBazelLabelList(inApexSelectValue))
- // Delete the library from the common config for this apex
- implDynamicDeps := ssi.dynamicDeps.SelectValue(ssi.axis, ssi.config)
- implDynamicDeps = bazel.SubtractBazelLabelList(implDynamicDeps, bazel.MakeLabelList([]bazel.Label{ssi.impl}))
- ssi.dynamicDeps.SetSelectValue(ssi.axis, ssi.config, implDynamicDeps)
- if ssi.axis == bazel.NoConfigAxis {
- // Set defaults. Defaults (i.e. host) should use impl and not stubs.
- defaultSelectValue := ssi.dynamicDeps.SelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey)
- (&defaultSelectValue).Append(bazel.MakeLabelList([]bazel.Label{ssi.impl}))
- ssi.dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, bazel.FirstUniqueBazelLabelList(defaultSelectValue))
- }
-}
-
-func setStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis,
- config string, apexAvailable []string, dynamicLibs bazel.LabelList, dynamicDeps *bazel.LabelListAttribute, ind int, buildNonApexWithStubs bool) {
-
- // Create a config_setting for each apex_available.
- // This will be used to select impl of a dep if dep is available to the same apex.
- for _, aa := range apexAvailable {
- createInApexConfigSetting(ctx.(android.TopDownMutatorContext), aa)
- }
-
- apiDomainForSelects := []string{}
- for _, apex := range apexAvailable {
- apiDomainForSelects = append(apiDomainForSelects, GetApiDomain(apex))
- }
- // Always emit a select statement for the platform variant.
- // This ensures that b build //foo --config=android works
- // Soong always creates a platform variant even when the library might not be available to platform.
- if !android.InList(android.AvailableToPlatform, apiDomainForSelects) {
- apiDomainForSelects = append(apiDomainForSelects, android.AvailableToPlatform)
- }
- apiDomainForSelects = android.SortedUniqueStrings(apiDomainForSelects)
-
- // Create a select for each apex this library could be included in.
- for _, l := range dynamicLibs.Includes {
- dep, _ := ctx.ModuleFromName(l.OriginalModuleName)
- if c, ok := dep.(*Module); !ok || !c.HasStubsVariants() {
- continue
- }
- // TODO (b/280339069): Decrease the verbosity of the generated BUILD files
- for _, apiDomain := range apiDomainForSelects {
- var sameApiDomain bool
- if apiDomain == android.AvailableToPlatform {
- // Platform variants in Soong use equality of apex_available for stub/impl selection.
- // https://cs.android.com/android/_/android/platform/build/soong/+/316b0158fe57ee7764235923e7c6f3d530da39c6:cc/cc.go;l=3393-3404;drc=176271a426496fa2688efe2b40d5c74340c63375;bpv=1;bpt=0
- // One of the factors behind this design choice is cc_test
- // Tests only have a platform variant, and using equality of apex_available ensures
- // that tests of an apex library gets its implementation and not stubs.
- // TODO (b/280343104): Discuss if we can drop this special handling for platform variants.
- sameApiDomain = availableToSameApexes(apexAvailable, dep.(*Module).ApexAvailable())
- if linkable, ok := ctx.Module().(LinkableInterface); ok && linkable.Bootstrap() {
- sameApiDomain = true
- }
- // If dependency has `apex_available: ["//apex_available:platform]`, then the platform variant of rdep should link against its impl.
- // https://cs.android.com/android/_/android/platform/build/soong/+/main:cc/cc.go;l=3617;bpv=1;bpt=0;drc=c6a93d853b37ec90786e745b8d282145e6d3b589
- if depApexAvailable := dep.(*Module).ApexAvailable(); len(depApexAvailable) == 1 && depApexAvailable[0] == android.AvailableToPlatform {
- sameApiDomain = true
- }
- } else {
- sameApiDomain = android.InList(apiDomain, dep.(*Module).ApexAvailable())
- }
- ssi := stubSelectionInfo{
- impl: l,
- axis: axis,
- config: config,
- apiDomain: apiDomain,
- dynamicDeps: dynamicDeps,
- sameApiDomain: sameApiDomain,
- }
- useStubOrImplInApexWithName(ssi)
- }
- }
-}
-
-func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) {
- bp2BuildPropParseHelper(ctx, module, &StripProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
- if stripProperties, ok := props.(*StripProperties); ok {
- la.stripKeepSymbols.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols)
- la.stripKeepSymbolsList.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols_list)
- la.stripKeepSymbolsAndDebugFrame.SetSelectValue(axis, config, stripProperties.Strip.Keep_symbols_and_debug_frame)
- la.stripAll.SetSelectValue(axis, config, stripProperties.Strip.All)
- la.stripNone.SetSelectValue(axis, config, stripProperties.Strip.None)
- }
- })
-}
-
-func (la *linkerAttributes) convertProductVariables(ctx android.BazelConversionPathContext, productVariableProps android.ProductConfigProperties) {
-
- type productVarDep struct {
- // the name of the corresponding excludes field, if one exists
- excludesField string
- // reference to the bazel attribute that should be set for the given product variable config
- attribute *bazel.LabelListAttribute
-
- depResolutionFunc func(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList
- }
-
- // an intermediate attribute that holds Header_libs info, and will be appended to
- // implementationDeps at the end, to solve the confliction that both header_libs
- // and static_libs use implementationDeps.
- var headerDeps bazel.LabelListAttribute
-
- productVarToDepFields := map[string]productVarDep{
- // product variables do not support exclude_shared_libs
- "Shared_libs": {attribute: &la.implementationDynamicDeps, depResolutionFunc: bazelLabelForSharedDepsExcludes},
- "Static_libs": {"Exclude_static_libs", &la.implementationDeps, bazelLabelForStaticDepsExcludes},
- "Whole_static_libs": {"Exclude_static_libs", &la.wholeArchiveDeps, bazelLabelForWholeDepsExcludes},
- "Header_libs": {attribute: &headerDeps, depResolutionFunc: bazelLabelForHeaderDepsExcludes},
- }
-
- for name, dep := range productVarToDepFields {
- props, exists := productVariableProps[name]
- excludeProps, excludesExists := productVariableProps[dep.excludesField]
- // if neither an include nor excludes property exists, then skip it
- if !exists && !excludesExists {
- continue
- }
- // Collect all the configurations that an include or exclude property exists for.
- // We want to iterate all configurations rather than either the include or exclude because, for a
- // particular configuration, we may have either only an include or an exclude to handle.
- productConfigProps := make(map[android.ProductConfigOrSoongConfigProperty]bool, len(props)+len(excludeProps))
- for p := range props {
- productConfigProps[p] = true
- }
- for p := range excludeProps {
- productConfigProps[p] = true
- }
-
- for productConfigProp := range productConfigProps {
- prop, includesExists := props[productConfigProp]
- excludesProp, excludesExists := excludeProps[productConfigProp]
- var includes, excludes []string
- var ok bool
- // if there was no includes/excludes property, casting fails and that's expected
- if includes, ok = prop.([]string); includesExists && !ok {
- ctx.ModuleErrorf("Could not convert product variable %s property", name)
- }
- if excludes, ok = excludesProp.([]string); excludesExists && !ok {
- ctx.ModuleErrorf("Could not convert product variable %s property", dep.excludesField)
- }
-
- dep.attribute.EmitEmptyList = productConfigProp.AlwaysEmit()
- dep.attribute.SetSelectValue(
- productConfigProp.ConfigurationAxis(),
- productConfigProp.SelectKey(),
- dep.depResolutionFunc(ctx, android.FirstUniqueStrings(includes), excludes),
- )
- }
- }
- la.implementationDeps.Append(headerDeps)
-}
-
-func (la *linkerAttributes) finalize(ctx android.BazelConversionPathContext) {
- // if system dynamic deps have the default value, any use of a system dynamic library used will
- // result in duplicate library errors for bionic OSes. Here, we explicitly exclude those libraries
- // from bionic OSes and the no config case as these libraries only build for bionic OSes.
- if la.systemDynamicDeps.IsNil() && len(la.usedSystemDynamicDepAsDynamicDep) > 0 {
- toRemove := bazelLabelForSharedDeps(ctx, android.SortedKeys(la.usedSystemDynamicDepAsDynamicDep))
- la.dynamicDeps.Exclude(bazel.NoConfigAxis, "", toRemove)
- la.dynamicDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
- la.dynamicDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove)
- la.implementationDynamicDeps.Exclude(bazel.NoConfigAxis, "", toRemove)
- la.implementationDynamicDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
- la.implementationDynamicDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove)
-
- la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.ConditionsDefaultConfigKey, toRemove)
- stubsToRemove := make([]bazel.Label, 0, len(la.usedSystemDynamicDepAsDynamicDep))
- for _, lib := range toRemove.Includes {
- stubLabelInApiSurfaces := bazel.Label{
- Label: apiSurfaceModuleLibCurrentPackage + lib.OriginalModuleName,
- }
- stubsToRemove = append(stubsToRemove, stubLabelInApiSurfaces)
- }
- // system libraries (e.g. libc, libm, libdl) belong the com.android.runtime api domain
- // dedupe the stubs of these libraries from the other api domains (platform, other_apexes...)
- for _, aa := range ctx.Module().(*Module).ApexAvailable() {
- la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, inApexConfigSetting(aa), bazel.MakeLabelList(stubsToRemove))
- }
- la.implementationDynamicDeps.Exclude(bazel.OsAndInApexAxis, bazel.AndroidPlatform, bazel.MakeLabelList(stubsToRemove))
- }
- if la.systemDynamicDeps.IsNil() && len(la.usedSystemDynamicDepAsStaticDep) > 0 {
- toRemove := bazelLabelForStaticDeps(ctx, android.SortedKeys(la.usedSystemDynamicDepAsStaticDep))
- la.deps.Exclude(bazel.NoConfigAxis, "", toRemove)
- la.deps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
- la.deps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove)
- la.implementationDeps.Exclude(bazel.NoConfigAxis, "", toRemove)
- la.implementationDeps.Exclude(bazel.OsConfigurationAxis, "android", toRemove)
- la.implementationDeps.Exclude(bazel.OsConfigurationAxis, "linux_bionic", toRemove)
- }
-
- la.deps.ResolveExcludes()
- la.implementationDeps.ResolveExcludes()
- la.dynamicDeps.ResolveExcludes()
- la.implementationDynamicDeps.ResolveExcludes()
- la.wholeArchiveDeps.ResolveExcludes()
- la.systemDynamicDeps.ForceSpecifyEmptyList = true
-
-}
-
-// Relativize a list of root-relative paths with respect to the module's
-// directory.
-//
-// include_dirs Soong prop are root-relative (b/183742505), but
-// local_include_dirs, export_include_dirs and export_system_include_dirs are
-// module dir relative. This function makes a list of paths entirely module dir
-// relative.
-//
-// For the `include` attribute, Bazel wants the paths to be relative to the
-// module.
-func bp2BuildMakePathsRelativeToModule(ctx android.BazelConversionPathContext, paths []string) []string {
- var relativePaths []string
- for _, path := range paths {
- // Semantics of filepath.Rel: join(ModuleDir, rel(ModuleDir, path)) == path
- relativePath, err := filepath.Rel(ctx.ModuleDir(), path)
- if err != nil {
- panic(err)
- }
- relativePaths = append(relativePaths, relativePath)
- }
- return relativePaths
-}
-
-// BazelIncludes contains information about -I and -isystem paths from a module converted to Bazel
-// attributes.
-type BazelIncludes struct {
- AbsoluteIncludes bazel.StringListAttribute
- Includes bazel.StringListAttribute
- SystemIncludes bazel.StringListAttribute
-}
-
-func bp2BuildParseExportedIncludes(ctx android.BazelConversionPathContext, module *Module, includes *BazelIncludes) BazelIncludes {
- var exported BazelIncludes
- if includes != nil {
- exported = *includes
- } 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 {
- exported.Includes.SetSelectValue(axis, config, android.FirstUniqueStrings(append(exported.Includes.SelectValue(axis, config), flagExporterProperties.Export_include_dirs...)))
- }
- if len(flagExporterProperties.Export_system_include_dirs) > 0 {
- exported.SystemIncludes.SetSelectValue(axis, config, android.FirstUniqueStrings(append(exported.SystemIncludes.SelectValue(axis, config), flagExporterProperties.Export_system_include_dirs...)))
- }
- }
- })
- exported.AbsoluteIncludes.DeduplicateAxesFromBase()
- exported.Includes.DeduplicateAxesFromBase()
- exported.SystemIncludes.DeduplicateAxesFromBase()
-
- return exported
-}
-
-func BazelLabelNameForStaticModule(baseLabel string) string {
- return baseLabel + "_bp2build_cc_library_static"
-}
-
-func bazelLabelForStaticModule(ctx android.BazelConversionPathContext, m blueprint.Module) string {
- label := android.BazelModuleLabel(ctx, m)
- if ccModule, ok := m.(*Module); ok && ccModule.typ() == fullLibrary {
- return BazelLabelNameForStaticModule(label)
- }
- return label
-}
-
-func bazelLabelForSharedModule(ctx android.BazelConversionPathContext, m blueprint.Module) string {
- // cc_library, at it's root name, propagates the shared library, which depends on the static
- // library.
- return android.BazelModuleLabel(ctx, m)
-}
-
-func bazelLabelForStaticWholeModuleDeps(ctx android.BazelConversionPathContext, m blueprint.Module) string {
- label := bazelLabelForStaticModule(ctx, m)
- if aModule, ok := m.(android.Module); ok {
- if android.IsModulePrebuilt(aModule) {
- label += "_alwayslink"
- }
- }
- return label
-}
-
-func xsdConfigCppTarget(xsd android.XsdConfigBp2buildTargets) string {
- return xsd.CppBp2buildTargetName()
-}
-
-func bazelLabelForWholeDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList {
- return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticWholeModuleDeps)
-}
-
-func bazelLabelForWholeDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
- return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForStaticWholeModuleDeps)
-}
-
-func bazelLabelForStaticDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
- return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForStaticModule)
-}
-
-func bazelLabelForStaticDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList {
- return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForStaticModule)
-}
-
-func bazelLabelForSharedDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList {
- return android.BazelLabelForModuleDepsWithFn(ctx, modules, bazelLabelForSharedModule)
-}
-
-func bazelLabelForHeaderDeps(ctx android.BazelConversionPathContext, modules []string) bazel.LabelList {
- // This is not elegant, but bp2build's shared library targets only propagate
- // their header information as part of the normal C++ provider.
- return bazelLabelForSharedDeps(ctx, modules)
-}
-
-func bazelLabelForHeaderDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
- // This is only used when product_variable header_libs is processed, to follow
- // the pattern of depResolutionFunc
- return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForSharedModule)
-}
-
-func bazelLabelForSharedDepsExcludes(ctx android.BazelConversionPathContext, modules, excludes []string) bazel.LabelList {
- return android.BazelLabelForModuleDepsExcludesWithFn(ctx, modules, excludes, bazelLabelForSharedModule)
-}
-
-type binaryLinkerAttrs struct {
- Linkshared *bool
- Stem bazel.StringAttribute
- Suffix bazel.StringAttribute
-}
-
-func bp2buildBinaryLinkerProps(ctx android.BazelConversionPathContext, m *Module) binaryLinkerAttrs {
- attrs := binaryLinkerAttrs{}
- bp2BuildPropParseHelper(ctx, m, &BinaryLinkerProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
- linkerProps := props.(*BinaryLinkerProperties)
- staticExecutable := linkerProps.Static_executable
- if axis == bazel.NoConfigAxis {
- if linkBinaryShared := !proptools.Bool(staticExecutable); !linkBinaryShared {
- attrs.Linkshared = &linkBinaryShared
- }
- } else if staticExecutable != nil {
- // TODO(b/202876379): Static_executable is arch-variant; however, linkshared is a
- // nonconfigurable attribute. Only 4 AOSP modules use this feature, defer handling
- ctx.ModuleErrorf("bp2build cannot migrate a module with arch/target-specific static_executable values")
- }
- if stem := linkerProps.Stem; stem != nil {
- attrs.Stem.SetSelectValue(axis, config, stem)
- }
- if suffix := linkerProps.Suffix; suffix != nil {
- attrs.Suffix.SetSelectValue(axis, config, suffix)
- }
- })
-
- return attrs
-}
-
-type sanitizerValues struct {
- features bazel.StringListAttribute
- copts bazel.StringListAttribute
- additionalCompilerInputs bazel.LabelListAttribute
-}
-
-func bp2buildSanitizerFeatures(ctx android.BazelConversionPathContext, m *Module) sanitizerValues {
- sanitizerFeatures := bazel.StringListAttribute{}
- sanitizerCopts := bazel.StringListAttribute{}
- sanitizerCompilerInputs := bazel.LabelListAttribute{}
- memtagFeatures := bazel.StringListAttribute{}
- memtagFeature := ""
- bp2BuildPropParseHelper(ctx, m, &SanitizeProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
- var features []string
- if sanitizerProps, ok := props.(*SanitizeProperties); ok {
- if sanitizerProps.Sanitize.Integer_overflow != nil && *sanitizerProps.Sanitize.Integer_overflow {
- features = append(features, "ubsan_integer_overflow")
- }
- for _, sanitizer := range sanitizerProps.Sanitize.Misc_undefined {
- features = append(features, "ubsan_"+sanitizer)
- }
- blocklist := sanitizerProps.Sanitize.Blocklist
- if blocklist != nil {
- // TODO: b/294868620 - Change this not to use the special axis when completing the bug
- coptValue := fmt.Sprintf("-fsanitize-ignorelist=$(location %s)", *blocklist)
- sanitizerCopts.SetSelectValue(bazel.SanitizersEnabledAxis, bazel.SanitizersEnabled, []string{coptValue})
- sanitizerCompilerInputs.SetSelectValue(bazel.SanitizersEnabledAxis, bazel.SanitizersEnabled, bazel.MakeLabelListFromTargetNames([]string{*blocklist}))
- }
- if sanitizerProps.Sanitize.Cfi != nil && !proptools.Bool(sanitizerProps.Sanitize.Cfi) {
- features = append(features, "-android_cfi")
- } else if proptools.Bool(sanitizerProps.Sanitize.Cfi) {
- features = append(features, "android_cfi")
- if proptools.Bool(sanitizerProps.Sanitize.Config.Cfi_assembly_support) {
- features = append(features, "android_cfi_assembly_support")
- }
- }
-
- if sanitizerProps.Sanitize.Memtag_heap != nil {
- if (axis == bazel.NoConfigAxis && memtagFeature == "") ||
- (axis == bazel.OsArchConfigurationAxis && config == bazel.OsArchAndroidArm64) {
- memtagFeature = setMemtagValue(sanitizerProps, &memtagFeatures)
- }
- }
- sanitizerFeatures.SetSelectValue(axis, config, features)
- }
- })
- sanitizerFeatures.Append(memtagFeatures)
-
- return sanitizerValues{
- features: sanitizerFeatures,
- copts: sanitizerCopts,
- additionalCompilerInputs: sanitizerCompilerInputs,
- }
-}
-
-func setMemtagValue(sanitizerProps *SanitizeProperties, memtagFeatures *bazel.StringListAttribute) string {
- var features []string
- if proptools.Bool(sanitizerProps.Sanitize.Memtag_heap) {
- features = append(features, "memtag_heap")
- } else {
- features = append(features, "-memtag_heap")
- }
- // Logic comes from: https://cs.android.com/android/platform/superproject/main/+/32ea1afbd1148b0b78553f24fa61116c999eb968:build/soong/cc/sanitize.go;l=910
- if sanitizerProps.Sanitize.Diag.Memtag_heap != nil {
- if proptools.Bool(sanitizerProps.Sanitize.Diag.Memtag_heap) {
- features = append(features, "diag_memtag_heap")
- } else {
- features = append(features, "-diag_memtag_heap")
- }
- }
- memtagFeatures.SetSelectValue(bazel.OsArchConfigurationAxis, bazel.OsArchAndroidArm64, features)
-
- return features[0]
-}
-
-func bp2buildLtoFeatures(ctx android.BazelConversionPathContext, m *Module) bazel.StringListAttribute {
- lto_feature_name := "android_thin_lto"
- ltoBoolFeatures := bazel.BoolAttribute{}
- bp2BuildPropParseHelper(ctx, m, <OProperties{}, func(axis bazel.ConfigurationAxis, config string, props interface{}) {
- if ltoProps, ok := props.(*LTOProperties); ok {
- thinProp := ltoProps.Lto.Thin != nil && *ltoProps.Lto.Thin
- thinPropSetToFalse := ltoProps.Lto.Thin != nil && !*ltoProps.Lto.Thin
- neverProp := ltoProps.Lto.Never != nil && *ltoProps.Lto.Never
- if thinProp {
- ltoBoolFeatures.SetSelectValue(axis, config, BoolPtr(true))
- return
- }
- if neverProp || thinPropSetToFalse {
- if thinProp {
- ctx.ModuleErrorf("lto.thin and lto.never are mutually exclusive but were specified together")
- } else {
- ltoBoolFeatures.SetSelectValue(axis, config, BoolPtr(false))
- }
- return
- }
- }
- ltoBoolFeatures.SetSelectValue(axis, config, nil)
- })
-
- props := m.GetArchVariantProperties(ctx, <OProperties{})
- ltoStringFeatures, err := ltoBoolFeatures.ToStringListAttribute(func(boolPtr *bool, axis bazel.ConfigurationAxis, config string) []string {
- if boolPtr == nil {
- return []string{}
- }
- if !*boolPtr {
- return []string{"-" + lto_feature_name}
- }
- features := []string{lto_feature_name}
- if ltoProps, ok := props[axis][config].(*LTOProperties); ok {
- if ltoProps.Whole_program_vtables != nil && *ltoProps.Whole_program_vtables {
- features = append(features, "android_thin_lto_whole_program_vtables")
- }
- }
- return features
- })
- if err != nil {
- ctx.ModuleErrorf("Error processing LTO attributes: %s", err)
- }
- return ltoStringFeatures
-}
-
-func convertHiddenVisibilityToFeatureBase(ctx android.BazelConversionPathContext, m *Module) bazel.StringListAttribute {
- visibilityHiddenFeature := bazel.StringListAttribute{}
- bp2BuildPropParseHelper(ctx, m, &BaseCompilerProperties{}, func(axis bazel.ConfigurationAxis, configString string, props interface{}) {
- if baseCompilerProps, ok := props.(*BaseCompilerProperties); ok {
- convertHiddenVisibilityToFeatureHelper(&visibilityHiddenFeature, axis, configString, baseCompilerProps.Cflags)
- }
- })
- return visibilityHiddenFeature
-}
-
-func convertHiddenVisibilityToFeatureStaticOrShared(ctx android.BazelConversionPathContext, m *Module, isStatic bool) bazel.StringListAttribute {
- visibilityHiddenFeature := bazel.StringListAttribute{}
- if isStatic {
- bp2BuildPropParseHelper(ctx, m, &StaticProperties{}, func(axis bazel.ConfigurationAxis, configString string, props interface{}) {
- if staticProps, ok := props.(*StaticProperties); ok {
- convertHiddenVisibilityToFeatureHelper(&visibilityHiddenFeature, axis, configString, staticProps.Static.Cflags)
- }
- })
- } else {
- bp2BuildPropParseHelper(ctx, m, &SharedProperties{}, func(axis bazel.ConfigurationAxis, configString string, props interface{}) {
- if sharedProps, ok := props.(*SharedProperties); ok {
- convertHiddenVisibilityToFeatureHelper(&visibilityHiddenFeature, axis, configString, sharedProps.Shared.Cflags)
- }
- })
- }
-
- return visibilityHiddenFeature
-}
-
-func convertHiddenVisibilityToFeatureHelper(feature *bazel.StringListAttribute, axis bazel.ConfigurationAxis, configString string, cflags []string) {
- if inList(config.VisibilityHiddenFlag, cflags) {
- feature.SetSelectValue(axis, configString, []string{"visibility_hidden"})
- }
-}
diff --git a/cc/builder.go b/cc/builder.go
index f5e0dcc..e4d5be2 100644
--- a/cc/builder.go
+++ b/cc/builder.go
@@ -534,7 +534,7 @@
toolingCppflags += " ${config.NoOverride64GlobalCflags}"
}
- modulePath := android.PathForModuleSrc(ctx).String()
+ modulePath := ctx.ModuleDir()
if android.IsThirdPartyPath(modulePath) {
cflags += " ${config.NoOverrideExternalGlobalCflags}"
toolingCflags += " ${config.NoOverrideExternalGlobalCflags}"
@@ -681,16 +681,11 @@
tidyCmd := "${config.ClangBin}/clang-tidy"
rule := clangTidy
- reducedCFlags := moduleFlags
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_CLANG_TIDY") {
rule = clangTidyRE
- // b/248371171, work around RBE input processor problem
- // some cflags rejected by input processor, but usually
- // do not affect included files or clang-tidy
- reducedCFlags = config.TidyReduceCFlags(reducedCFlags)
}
- sharedCFlags := shareFlags("cFlags", reducedCFlags)
+ sharedCFlags := shareFlags("cFlags", moduleFlags)
srcRelPath := srcFile.Rel()
// Add the .tidy rule
@@ -875,7 +870,8 @@
// into a single .ldump sAbi dump file
func transformDumpToLinkedDump(ctx android.ModuleContext, sAbiDumps android.Paths, soFile android.Path,
baseName, exportedHeaderFlags string, symbolFile android.OptionalPath,
- excludedSymbolVersions, excludedSymbolTags []string) android.OptionalPath {
+ excludedSymbolVersions, excludedSymbolTags []string,
+ api string) android.OptionalPath {
outputFile := android.PathForModuleOut(ctx, baseName+".lsdump")
@@ -892,6 +888,11 @@
for _, tag := range excludedSymbolTags {
symbolFilterStr += " --exclude-symbol-tag " + tag
}
+ apiLevelsJson := android.GetApiLevelsJson(ctx)
+ implicits = append(implicits, apiLevelsJson)
+ symbolFilterStr += " --api-map " + apiLevelsJson.String()
+ symbolFilterStr += " --api " + api
+
rule := sAbiLink
args := map[string]string{
"symbolFilter": symbolFilterStr,
@@ -1051,6 +1052,9 @@
if flags.StripKeepSymbolsAndDebugFrame {
args += " --keep-symbols-and-debug-frame"
}
+ if ctx.Windows() {
+ args += " --windows"
+ }
ctx.Build(pctx, android.BuildParams{
Rule: strip,
diff --git a/cc/cc.go b/cc/cc.go
index 3b92696..449d38f 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -24,14 +24,13 @@
"strconv"
"strings"
- "android/soong/ui/metrics/bp2build_metrics_proto"
+ "android/soong/testing"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/aidl_library"
"android/soong/android"
- "android/soong/bazel/cquery"
"android/soong/cc/config"
"android/soong/fuzz"
"android/soong/genrule"
@@ -69,16 +68,14 @@
ctx.TopDown("fuzz_deps", fuzzMutatorDeps)
- ctx.BottomUp("coverage", coverageMutator).Parallel()
+ ctx.Transition("coverage", &coverageTransitionMutator{})
ctx.TopDown("afdo_deps", afdoDepsMutator)
ctx.BottomUp("afdo", afdoMutator).Parallel()
- ctx.TopDown("orderfile_deps", orderfileDepsMutator)
- ctx.BottomUp("orderfile", orderfileMutator).Parallel()
+ ctx.Transition("orderfile", &orderfileTransitionMutator{})
- ctx.TopDown("lto_deps", ltoDepsMutator)
- ctx.BottomUp("lto", ltoMutator).Parallel()
+ ctx.Transition("lto", <oTransitionMutator{})
ctx.BottomUp("check_linktype", checkLinkTypeMutator).Parallel()
ctx.TopDown("double_loadable", checkDoubleLoadableLibraries).Parallel()
@@ -140,6 +137,8 @@
// List of libs that need to be excluded for APEX variant
ExcludeLibsForApex []string
+ // List of libs that need to be excluded for non-APEX variant
+ ExcludeLibsForNonApex []string
}
// PathDeps is a struct containing file paths to dependencies of a module.
@@ -300,8 +299,8 @@
// Set by DepsMutator.
AndroidMkSystemSharedLibs []string `blueprint:"mutated"`
- // The name of the image this module is built for, suffixed with a '.'
- ImageVariationPrefix string `blueprint:"mutated"`
+ // The name of the image this module is built for
+ ImageVariation string `blueprint:"mutated"`
// The VNDK version this module is built against. If empty, the module is not
// build against the VNDK.
@@ -524,11 +523,11 @@
inRamdisk() bool
inVendorRamdisk() bool
inRecovery() bool
+ InVendorOrProduct() bool
selectedStl() string
baseModuleName() string
getVndkExtendsModuleName() string
isAfdoCompile() bool
- isPgoCompile() bool
isOrderfileCompile() bool
isCfi() bool
isFuzzer() bool
@@ -544,6 +543,7 @@
isPreventInstall() bool
isCfiAssemblySupportEnabled() bool
getSharedFlags() *SharedFlags
+ notInPlatform() bool
}
type SharedFlags struct {
@@ -617,12 +617,15 @@
link(ctx ModuleContext, flags Flags, deps PathDeps, objs Objects) android.Path
appendLdflags([]string)
unstrippedOutputFilePath() android.Path
+ strippedAllOutputFilePath() android.Path
nativeCoverage() bool
coverageOutputFilePath() android.OptionalPath
// Get the deps that have been explicitly specified in the properties.
linkerSpecifiedDeps(specifiedDeps specifiedDeps) specifiedDeps
+
+ moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON)
}
// specifiedDeps is a tuple struct representing dependencies of a linked binary owned by the linker.
@@ -726,6 +729,8 @@
// Whether or not this dependency has to be followed for the apex variants
excludeInApex bool
+ // Whether or not this dependency has to be followed for the non-apex variants
+ excludeInNonApex bool
// If true, don't automatically export symbols from the static library into a shared library.
unexportedSymbols bool
@@ -825,19 +830,6 @@
return ok && ccDepTag == testPerSrcDepTag
}
-// bazelHandler is the interface for a helper object related to deferring to Bazel for
-// processing a cc module (during Bazel mixed builds). Individual module types should define
-// their own bazel handler if they support being handled by Bazel.
-type BazelHandler interface {
- // QueueBazelCall invokes request-queueing functions on the BazelContext
- //so that these requests are handled when Bazel's cquery is invoked.
- QueueBazelCall(ctx android.BaseModuleContext, label string)
-
- // ProcessBazelQueryResponse uses information retrieved from Bazel to set properties
- // on the current module with given label.
- ProcessBazelQueryResponse(ctx android.ModuleContext, label string)
-}
-
// Module contains the properties and members used by all C/C++ module types, and implements
// the blueprint.Module interface. It delegates to compiler, linker, and installer interfaces
// to construct the output file. Behavior can be customized with a Customizer, or "decorator",
@@ -855,15 +847,13 @@
type Module struct {
fuzz.FuzzModule
- android.BazelModuleBase
-
VendorProperties VendorProperties
Properties BaseProperties
// initialize before calling Init
- hod android.HostOrDeviceSupported
- multilib android.Multilib
- bazelable bool
+ hod android.HostOrDeviceSupported
+ multilib android.Multilib
+ testModule bool
// Allowable SdkMemberTypes of this module type.
sdkMemberTypes []android.SdkMemberType
@@ -873,22 +863,20 @@
// type-specific logic. These members may reference different objects or the same object.
// Functions of these decorators will be invoked to initialize and register type-specific
// build statements.
- generators []Generator
- compiler compiler
- linker linker
- installer installer
- bazelHandler BazelHandler
+ generators []Generator
+ compiler compiler
+ linker linker
+ installer installer
- features []feature
- stl *stl
- sanitize *sanitize
- coverage *coverage
- fuzzer *fuzzer
- sabi *sabi
- vndkdep *vndkdep
- lto *lto
- afdo *afdo
- pgo *pgo
+ features []feature
+ stl *stl
+ sanitize *sanitize
+ coverage *coverage
+ fuzzer *fuzzer
+ sabi *sabi
+ vndkdep *vndkdep
+ lto *lto
+ afdo *afdo
orderfile *orderfile
library libraryInterface
@@ -920,6 +908,9 @@
apexSdkVersion android.ApiLevel
hideApexVariantFromMake bool
+
+ // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo
+ mergedAconfigFiles map[string]android.Paths
}
func (c *Module) AddJSONData(d *map[string]interface{}) {
@@ -1104,6 +1095,16 @@
return false
}
+func (c *Module) IsNdkPrebuiltStl() bool {
+ if c.linker == nil {
+ return false
+ }
+ if _, ok := c.linker.(*ndkPrebuiltStlLinker); ok {
+ return true
+ }
+ return false
+}
+
func (c *Module) RlibStd() bool {
panic(fmt.Errorf("RlibStd called on non-Rust module: %q", c.BaseModuleName()))
}
@@ -1261,9 +1262,6 @@
if c.afdo != nil {
c.AddProperties(c.afdo.props()...)
}
- if c.pgo != nil {
- c.AddProperties(c.pgo.props()...)
- }
if c.orderfile != nil {
c.AddProperties(c.orderfile.props()...)
}
@@ -1272,9 +1270,6 @@
}
android.InitAndroidArchModule(c, c.hod, c.multilib)
- if c.bazelable {
- android.InitBazelModule(c)
- }
android.InitApexModule(c)
android.InitDefaultableModule(c)
@@ -1289,7 +1284,7 @@
func (c *Module) canUseSdk() bool {
return c.Os() == android.Android && c.Target().NativeBridge == android.NativeBridgeDisabled &&
- !c.UseVndk() && !c.InRamdisk() && !c.InRecovery() && !c.InVendorRamdisk()
+ !c.InVendorOrProduct() && !c.InRamdisk() && !c.InRecovery() && !c.InVendorRamdisk()
}
func (c *Module) UseSdk() bool {
@@ -1393,13 +1388,6 @@
return false
}
-func (c *Module) isPgoCompile() bool {
- if pgo := c.pgo; pgo != nil {
- return pgo.Properties.PgoCompile
- }
- return false
-}
-
func (c *Module) isOrderfileCompile() bool {
if orderfile := c.orderfile; orderfile != nil {
return orderfile.Properties.OrderfileLoad
@@ -1537,8 +1525,6 @@
}
func InstallToBootstrap(name string, config android.Config) bool {
- // NOTE: also update //build/bazel/rules/apex/cc.bzl#_installed_to_bootstrap
- // if this list is updated.
if name == "libclang_rt.hwasan" || name == "libc_hwasan" {
return true
}
@@ -1620,9 +1606,10 @@
func (ctx *moduleContextImpl) sdkVersion() string {
if ctx.ctx.Device() {
- if ctx.useVndk() {
+ config := ctx.ctx.Config()
+ if !config.IsVndkDeprecated() && ctx.useVndk() {
vndkVer := ctx.mod.VndkVersion()
- if inList(vndkVer, ctx.ctx.Config().PlatformVersionActiveCodenames()) {
+ if inList(vndkVer, config.PlatformVersionActiveCodenames()) {
return "current"
}
return vndkVer
@@ -1640,6 +1627,17 @@
if ver == "apex_inherit" || ver == "" {
ver = ctx.sdkVersion()
}
+
+ if ctx.ctx.Device() {
+ config := ctx.ctx.Config()
+ if config.IsVndkDeprecated() && ctx.inVendor() {
+ // If building for vendor with final API, then use the latest _stable_ API as "current".
+ if config.VendorApiLevelFrozen() && (ver == "" || ver == "current") {
+ ver = config.PlatformSdkVersion().String()
+ }
+ }
+ }
+
// For crt objects, the meaning of min_sdk_version is very different from other types of
// module. For them, min_sdk_version defines the oldest version that the build system will
// create versioned variants for. For example, if min_sdk_version is 16, then sdk variant of
@@ -1680,6 +1678,10 @@
return ctx.mod.UseVndk()
}
+func (ctx *moduleContextImpl) InVendorOrProduct() bool {
+ return ctx.mod.InVendorOrProduct()
+}
+
func (ctx *moduleContextImpl) isNdk(config android.Config) bool {
return ctx.mod.IsNdk(config)
}
@@ -1708,10 +1710,6 @@
return ctx.mod.isAfdoCompile()
}
-func (ctx *moduleContextImpl) isPgoCompile() bool {
- return ctx.mod.isPgoCompile()
-}
-
func (ctx *moduleContextImpl) isOrderfileCompile() bool {
return ctx.mod.isOrderfileCompile()
}
@@ -1756,7 +1754,7 @@
}
func (ctx *moduleContextImpl) baseModuleName() string {
- return ctx.mod.ModuleBase.BaseModuleName()
+ return ctx.mod.BaseModuleName()
}
func (ctx *moduleContextImpl) getVndkExtendsModuleName() string {
@@ -1764,11 +1762,13 @@
}
func (ctx *moduleContextImpl) isForPlatform() bool {
- return ctx.ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
+ apexInfo, _ := android.ModuleProvider(ctx.ctx, android.ApexInfoProvider)
+ return apexInfo.IsForPlatform()
}
func (ctx *moduleContextImpl) apexVariationName() string {
- return ctx.ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).ApexVariationName
+ apexInfo, _ := android.ModuleProvider(ctx.ctx, android.ApexInfoProvider)
+ return apexInfo.ApexVariationName
}
func (ctx *moduleContextImpl) apexSdkVersion() android.ApiLevel {
@@ -1804,6 +1804,10 @@
return ctx.mod.isCfiAssemblySupportEnabled()
}
+func (ctx *moduleContextImpl) notInPlatform() bool {
+ return ctx.mod.NotInPlatform()
+}
+
func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
return &Module{
hod: hod,
@@ -1824,7 +1828,6 @@
module.vndkdep = &vndkdep{}
module.lto = <o{}
module.afdo = &afdo{}
- module.pgo = &pgo{}
module.orderfile = &orderfile{}
return module
}
@@ -1884,8 +1887,7 @@
// do not add a name suffix because it is a base module.
return ""
}
- vndkVersion = ctx.DeviceConfig().ProductVndkVersion()
- nameSuffix = ProductSuffix
+ return ProductSuffix
} else {
vndkVersion = ctx.DeviceConfig().VndkVersion()
nameSuffix = VendorSuffix
@@ -1909,7 +1911,7 @@
}
llndk := c.IsLlndk()
- if llndk || (c.UseVndk() && c.HasNonSystemVariants()) {
+ if llndk || (c.InVendorOrProduct() && c.HasNonSystemVariants()) {
// .vendor.{version} suffix is added for vendor variant or .product.{version} suffix is
// added for product variant only when we have vendor and product variants with core
// variant. The suffix is not added for vendor-only or product-only module.
@@ -1940,170 +1942,6 @@
return subName
}
-var _ android.MixedBuildBuildable = (*Module)(nil)
-
-func (c *Module) getBazelModuleLabel(ctx android.BaseModuleContext) string {
- var bazelModuleLabel string
- if c.typ() == fullLibrary && c.static() {
- // cc_library is a special case in bp2build; two targets are generated -- one for each
- // of the shared and static variants. The shared variant keeps the module name, but the
- // static variant uses a different suffixed name.
- bazelModuleLabel = bazelLabelForStaticModule(ctx, c)
- } else {
- bazelModuleLabel = c.GetBazelLabel(ctx, c)
- }
- labelNoPrebuilt := bazelModuleLabel
- if c.IsPrebuilt() {
- labelNoPrebuilt = android.RemoveOptionalPrebuiltPrefixFromBazelLabel(bazelModuleLabel)
- }
- return labelNoPrebuilt
-}
-
-func (c *Module) QueueBazelCall(ctx android.BaseModuleContext) {
- c.bazelHandler.QueueBazelCall(ctx, c.getBazelModuleLabel(ctx))
-}
-
-// IsMixedBuildSupported returns true if the module should be analyzed by Bazel
-// in any of the --bazel-mode(s).
-func (c *Module) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
- if !allEnabledSanitizersSupportedByBazel(ctx, c) {
- //TODO(b/278772861) support sanitizers in Bazel rules
- return false
- }
- if !imageVariantSupportedByBazel(c) {
- return false
- }
- if c.IsSdkVariant() {
- return false
- }
- return c.bazelHandler != nil
-}
-
-func imageVariantSupportedByBazel(c *Module) bool {
- if c.IsLlndk() {
- return false
- }
- if c.InVendor() {
- return false
- }
- if c.InProduct() {
- return false
- }
- if c.InRamdisk() {
- return false
- }
- if c.InVendorRamdisk() {
- return false
- }
- if c.InRecovery() {
- return false
- }
- return true
-}
-
-func allEnabledSanitizersSupportedByBazel(ctx android.BaseModuleContext, c *Module) bool {
- if c.sanitize == nil {
- return true
- }
- sanitizeProps := &c.sanitize.Properties.SanitizeMutated
-
- unsupportedSanitizers := []*bool{
- sanitizeProps.Safestack,
- sanitizeProps.Scudo,
- BoolPtr(len(c.sanitize.Properties.Sanitize.Recover) > 0),
- }
- for _, san := range unsupportedSanitizers {
- if Bool(san) {
- return false
- }
- }
-
- for _, san := range Sanitizers {
- if san == intOverflow {
- // TODO(b/261058727): enable mixed builds for all modules with UBSan
- // Currently we can only support ubsan when minimum runtime is used.
- ubsanEnabled := Bool(sanitizeProps.Integer_overflow) || len(sanitizeProps.Misc_undefined) > 0
- if !ubsanEnabled || c.MinimalRuntimeNeeded() {
- continue
- }
- } else if san == cfi {
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- // Only allow cfi if this is an apex variant
- if !apexInfo.IsForPlatform() {
- continue
- }
- }
- if c.sanitize.isSanitizerEnabled(san) {
- return false
- }
- }
-
- return true
-}
-
-func GetApexConfigKey(ctx android.BaseModuleContext) *android.ApexConfigKey {
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- if !apexInfo.IsForPlatform() {
- apexKey := android.ApexConfigKey{
- WithinApex: true,
- ApexSdkVersion: findApexSdkVersion(ctx, apexInfo).String(),
- ApiDomain: findApiDomain(apexInfo),
- }
- return &apexKey
- }
-
- return nil
-}
-
-// Returns the api domain of a module for an apexInfo group
-// Input:
-// ai.InApexModules: [com.android.foo, test_com.android.foo, com.google.android.foo]
-// Return:
-// com.android.foo
-
-// If a module is included in multiple api domains (collated by min_sdk_version), it will return
-// the first match. The other matches have the same build actions since they share a min_sdk_version, so returning
-// the first match is fine.
-func findApiDomain(ai android.ApexInfo) string {
- // Remove any test apexes
- matches, _ := android.FilterList(ai.InApexModules, ai.TestApexes)
- // Remove any google apexes. Rely on naming convention.
- pred := func(s string) bool { return !strings.HasPrefix(s, "com.google") }
- matches = android.FilterListPred(matches, pred)
- if len(matches) > 0 {
- // Return the first match
- return android.SortedUniqueStrings(matches)[0]
- } else {
- // No apex in the tree has a dependency on this module
- return ""
- }
-}
-
-func (c *Module) ProcessBazelQueryResponse(ctx android.ModuleContext) {
- bazelModuleLabel := c.getBazelModuleLabel(ctx)
- c.bazelHandler.ProcessBazelQueryResponse(ctx, bazelModuleLabel)
-
- c.Properties.SubName = GetSubnameProperty(ctx, c)
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- if !apexInfo.IsForPlatform() {
- c.hideApexVariantFromMake = true
- }
-
- c.makeLinkType = GetMakeLinkType(ctx, c)
-
- mctx := &moduleContext{
- ModuleContext: ctx,
- moduleContextImpl: moduleContextImpl{
- mod: c,
- },
- }
- mctx.ctx = mctx
-
- // TODO(b/244432500): Get the tradefed config from the bazel target instead
- // of generating it with Soong.
- c.maybeInstall(mctx, apexInfo)
-}
-
func moduleContextFromAndroidModuleContext(actx android.ModuleContext, c *Module) ModuleContext {
ctx := &moduleContext{
ModuleContext: actx,
@@ -2126,6 +1964,7 @@
"libdl_android": true,
"libm": true,
"libdl": true,
+ "libz": true,
// art apex
"libandroidio": true,
"libdexfile": true,
@@ -2165,6 +2004,10 @@
return false
}
+func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles)
+}
+
func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
// Handle the case of a test module split by `test_per_src` mutator.
//
@@ -2177,7 +2020,7 @@
}
c.Properties.SubName = GetSubnameProperty(actx, c)
- apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(actx, android.ApexInfoProvider)
if !apexInfo.IsForPlatform() {
c.hideApexVariantFromMake = true
}
@@ -2251,9 +2094,6 @@
if c.afdo != nil {
flags = c.afdo.flags(ctx, flags)
}
- if c.pgo != nil {
- flags = c.pgo.flags(ctx, flags)
- }
if c.orderfile != nil {
flags = c.orderfile.flags(ctx, flags)
}
@@ -2319,8 +2159,47 @@
}
}
}
+ if c.testModule {
+ android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
+ }
+ android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: deps.GeneratedSources.Strings()})
+
+ android.CollectDependencyAconfigFiles(ctx, &c.mergedAconfigFiles)
c.maybeInstall(ctx, apexInfo)
+
+ if c.linker != nil {
+ moduleInfoJSON := ctx.ModuleInfoJSON()
+ c.linker.moduleInfoJSON(ctx, moduleInfoJSON)
+ moduleInfoJSON.SharedLibs = c.Properties.AndroidMkSharedLibs
+ moduleInfoJSON.StaticLibs = c.Properties.AndroidMkStaticLibs
+ moduleInfoJSON.SystemSharedLibs = c.Properties.AndroidMkSystemSharedLibs
+ moduleInfoJSON.RuntimeDependencies = c.Properties.AndroidMkRuntimeLibs
+
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, c.Properties.AndroidMkSharedLibs...)
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, c.Properties.AndroidMkStaticLibs...)
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, c.Properties.AndroidMkHeaderLibs...)
+ moduleInfoJSON.Dependencies = append(moduleInfoJSON.Dependencies, c.Properties.AndroidMkWholeStaticLibs...)
+
+ if c.sanitize != nil && len(moduleInfoJSON.Class) > 0 &&
+ (moduleInfoJSON.Class[0] == "STATIC_LIBRARIES" || moduleInfoJSON.Class[0] == "HEADER_LIBRARIES") {
+ if Bool(c.sanitize.Properties.SanitizeMutated.Cfi) {
+ moduleInfoJSON.SubName += ".cfi"
+ }
+ if Bool(c.sanitize.Properties.SanitizeMutated.Hwaddress) {
+ moduleInfoJSON.SubName += ".hwasan"
+ }
+ if Bool(c.sanitize.Properties.SanitizeMutated.Scs) {
+ moduleInfoJSON.SubName += ".scs"
+ }
+ }
+ moduleInfoJSON.SubName += c.Properties.SubName
+
+ if c.Properties.IsSdkVariant && c.Properties.SdkAndPlatformVariantVisibleToMake {
+ moduleInfoJSON.Uninstallable = true
+ }
+
+ }
}
func (c *Module) maybeUnhideFromMake() {
@@ -2332,16 +2211,15 @@
// is explicitly referenced via .bootstrap suffix or the module is marked with
// 'bootstrap: true').
if c.HasStubsVariants() && c.NotInPlatform() && !c.InRamdisk() &&
- !c.InRecovery() && !c.UseVndk() && !c.static() && !c.isCoverageVariant() &&
+ !c.InRecovery() && !c.InVendorOrProduct() && !c.static() && !c.isCoverageVariant() &&
c.IsStubs() && !c.InVendorRamdisk() {
c.Properties.HideFromMake = false // unhide
// Note: this is still non-installable
}
}
-// maybeInstall is called at the end of both GenerateAndroidBuildActions and
-// ProcessBazelQueryResponse to run the install hooks for installable modules,
-// like binaries and tests.
+// maybeInstall is called at the end of both GenerateAndroidBuildActions to run the
+// install hooks for installable modules, like binaries and tests.
func (c *Module) maybeInstall(ctx ModuleContext, apexInfo android.ApexInfo) {
if !proptools.BoolDefault(c.Installable(), true) {
// If the module has been specifically configure to not be installed then
@@ -2364,12 +2242,6 @@
}
}
-func (c *Module) setAndroidMkVariablesFromCquery(info cquery.CcAndroidMkInfo) {
- c.Properties.AndroidMkSharedLibs = info.LocalSharedLibs
- c.Properties.AndroidMkStaticLibs = info.LocalStaticLibs
- c.Properties.AndroidMkWholeStaticLibs = info.LocalWholeStaticLibs
-}
-
func (c *Module) toolchain(ctx android.BaseModuleContext) config.Toolchain {
if c.cachedToolchain == nil {
c.cachedToolchain = config.FindToolchainWithContext(ctx)
@@ -2396,15 +2268,15 @@
if c.coverage != nil {
c.coverage.begin(ctx)
}
+ if c.afdo != nil {
+ c.afdo.begin(ctx)
+ }
if c.lto != nil {
c.lto.begin(ctx)
}
if c.orderfile != nil {
c.orderfile.begin(ctx)
}
- if c.pgo != nil {
- c.pgo.begin(ctx)
- }
if ctx.useSdk() && c.IsSdkVariant() {
version, err := nativeApiLevelFromUser(ctx, ctx.sdkVersion())
if err != nil {
@@ -2558,9 +2430,9 @@
if actx.OtherModuleExists("api_imports") {
apiImportModule = actx.AddDependency(c, nil, "api_imports")
if len(apiImportModule) > 0 && apiImportModule[0] != nil {
- apiInfo := actx.OtherModuleProvider(apiImportModule[0], multitree.ApiImportsProvider).(multitree.ApiImportInfo)
+ apiInfo, _ := android.OtherModuleProvider(actx, apiImportModule[0], multitree.ApiImportsProvider)
apiImportInfo = apiInfo
- actx.SetProvider(multitree.ApiImportsProvider, apiInfo)
+ android.SetProvider(actx, multitree.ApiImportsProvider, apiInfo)
}
}
}
@@ -2575,16 +2447,16 @@
// Only retrieve the snapshot on demand in order to avoid circular dependencies
// between the modules in the snapshot and the snapshot itself.
var snapshotModule []blueprint.Module
- if c.InVendor() && c.VndkVersion() == actx.DeviceConfig().VndkVersion() {
+ if c.InVendor() && c.VndkVersion() == actx.DeviceConfig().VndkVersion() && actx.OtherModuleExists("vendor_snapshot") {
snapshotModule = actx.AddVariationDependencies(nil, nil, "vendor_snapshot")
- } else if recoverySnapshotVersion := actx.DeviceConfig().RecoverySnapshotVersion(); recoverySnapshotVersion != "current" && recoverySnapshotVersion != "" && c.InRecovery() {
+ } else if recoverySnapshotVersion := actx.DeviceConfig().RecoverySnapshotVersion(); recoverySnapshotVersion != "current" && recoverySnapshotVersion != "" && c.InRecovery() && actx.OtherModuleExists("recovery_snapshot") {
snapshotModule = actx.AddVariationDependencies(nil, nil, "recovery_snapshot")
}
if len(snapshotModule) > 0 && snapshotModule[0] != nil {
- snapshot := actx.OtherModuleProvider(snapshotModule[0], SnapshotInfoProvider).(SnapshotInfo)
+ snapshot, _ := android.OtherModuleProvider(actx, snapshotModule[0], SnapshotInfoProvider)
*snapshotInfo = &snapshot
// republish the snapshot for use in later mutators on this module
- actx.SetProvider(SnapshotInfoProvider, snapshot)
+ android.SetProvider(actx, SnapshotInfoProvider, snapshot)
}
}
if *snapshotInfo == nil {
@@ -2804,6 +2676,9 @@
if inList(lib, deps.ExcludeLibsForApex) {
depTag.excludeInApex = true
}
+ if inList(lib, deps.ExcludeLibsForNonApex) {
+ depTag.excludeInNonApex = true
+ }
name, version := StubsLibNameAndVersion(lib)
if apiLibraryName, ok := apiImportInfo.SharedLibs[name]; ok && !ctx.OtherModuleExists(name) {
@@ -3169,7 +3044,7 @@
depPaths.ReexportedGeneratedHeaders = append(depPaths.ReexportedGeneratedHeaders, exporter.GeneratedHeaders...)
}
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
c.apexSdkVersion = findApexSdkVersion(ctx, apexInfo)
skipModuleList := map[string]bool{}
@@ -3179,7 +3054,7 @@
ctx.VisitDirectDeps(func(dep android.Module) {
if dep.Name() == "api_imports" {
- apiImportInfo = ctx.OtherModuleProvider(dep, multitree.ApiImportsProvider).(multitree.ApiImportInfo)
+ apiImportInfo, _ = android.OtherModuleProvider(ctx, dep, multitree.ApiImportsProvider)
hasApiImportInfo = true
}
})
@@ -3230,12 +3105,10 @@
}
if depTag == aidlLibraryTag {
- if ctx.OtherModuleHasProvider(dep, aidl_library.AidlLibraryProvider) {
+ if aidlLibraryInfo, ok := android.OtherModuleProvider(ctx, dep, aidl_library.AidlLibraryProvider); ok {
depPaths.AidlLibraryInfos = append(
depPaths.AidlLibraryInfos,
- ctx.OtherModuleProvider(
- dep,
- aidl_library.AidlLibraryProvider).(aidl_library.AidlLibraryInfo),
+ aidlLibraryInfo,
)
}
}
@@ -3300,10 +3173,10 @@
// version mutator, so the stubs variant is created from the shared variant that
// already has the reuseObjTag dependency on the static variant.
if !c.library.buildStubs() {
- staticAnalogue := ctx.OtherModuleProvider(dep, StaticLibraryInfoProvider).(StaticLibraryInfo)
+ staticAnalogue, _ := android.OtherModuleProvider(ctx, dep, StaticLibraryInfoProvider)
objs := staticAnalogue.ReuseObjects
depPaths.Objs = depPaths.Objs.Append(objs)
- depExporterInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
+ depExporterInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider)
reexportExporter(depExporterInfo)
}
return
@@ -3320,8 +3193,11 @@
if !apexInfo.IsForPlatform() && libDepTag.excludeInApex {
return
}
+ if apexInfo.IsForPlatform() && libDepTag.excludeInNonApex {
+ return
+ }
- depExporterInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
+ depExporterInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider)
var ptr *android.Paths
var depPtr *android.Paths
@@ -3330,7 +3206,7 @@
switch {
case libDepTag.header():
- if !ctx.OtherModuleHasProvider(dep, HeaderLibraryInfoProvider) {
+ if _, isHeaderLib := android.OtherModuleProvider(ctx, dep, HeaderLibraryInfoProvider); !isHeaderLib {
if !ctx.Config().AllowMissingDependencies() {
ctx.ModuleErrorf("module %q is not a header library", depName)
} else {
@@ -3339,7 +3215,7 @@
return
}
case libDepTag.shared():
- if !ctx.OtherModuleHasProvider(dep, SharedLibraryInfoProvider) {
+ if _, isSharedLib := android.OtherModuleProvider(ctx, dep, SharedLibraryInfoProvider); !isSharedLib {
if !ctx.Config().AllowMissingDependencies() {
ctx.ModuleErrorf("module %q is not a shared library", depName)
} else {
@@ -3376,7 +3252,8 @@
panic(fmt.Errorf("unexpected library dependency order %d", libDepTag.Order))
}
case libDepTag.static():
- if !ctx.OtherModuleHasProvider(dep, StaticLibraryInfoProvider) {
+ staticLibraryInfo, isStaticLib := android.OtherModuleProvider(ctx, dep, StaticLibraryInfoProvider)
+ if !isStaticLib {
if !ctx.Config().AllowMissingDependencies() {
ctx.ModuleErrorf("module %q is not a static library", depName)
} else {
@@ -3391,7 +3268,6 @@
break
}
- staticLibraryInfo := ctx.OtherModuleProvider(dep, StaticLibraryInfoProvider).(StaticLibraryInfo)
linkFile = android.OptionalPathForPath(staticLibraryInfo.StaticLibrary)
if libDepTag.wholeStatic {
ptr = &depPaths.WholeStaticLibs
@@ -3501,7 +3377,7 @@
if lib.buildStubs() && dep.(android.ApexModule).InAnyApex() {
// Add the dependency to the APEX(es) providing the library so that
// m <module> can trigger building the APEXes as well.
- depApexInfo := ctx.OtherModuleProvider(dep, android.ApexInfoProvider).(android.ApexInfo)
+ depApexInfo, _ := android.OtherModuleProvider(ctx, dep, android.ApexInfoProvider)
for _, an := range depApexInfo.InApexVariants {
c.Properties.ApexesProvidingSharedLibs = append(
c.Properties.ApexesProvidingSharedLibs, an)
@@ -3577,20 +3453,20 @@
panic(fmt.Errorf("Not an APEX module: %q", ctx.ModuleName()))
}
- useVndk := false
+ inVendorOrProduct := false
bootstrap := false
if linkable, ok := ctx.Module().(LinkableInterface); !ok {
panic(fmt.Errorf("Not a Linkable module: %q", ctx.ModuleName()))
} else {
- useVndk = linkable.UseVndk()
+ inVendorOrProduct = linkable.InVendorOrProduct()
bootstrap = linkable.Bootstrap()
}
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
useStubs := false
- if lib := moduleLibraryInterface(dep); lib.buildStubs() && useVndk { // LLNDK
+ if lib := moduleLibraryInterface(dep); lib.buildStubs() && inVendorOrProduct { // LLNDK
if !apexInfo.IsForPlatform() {
// For platform libraries, use current version of LLNDK
// If this is for use_vendor apex we will apply the same rules
@@ -3620,7 +3496,7 @@
// Another exception: if this module is a test for an APEX, then
// it is linked with the non-stub variant of a module in the APEX
// as if this is part of the APEX.
- testFor := ctx.Provider(android.ApexTestForInfoProvider).(android.ApexTestForInfo)
+ testFor, _ := android.ModuleProvider(ctx, android.ApexTestForInfoProvider)
for _, apexContents := range testFor.ApexContents {
if apexContents.DirectlyInApex(depName) {
useStubs = false
@@ -3666,9 +3542,9 @@
panic(fmt.Errorf("Unexpected dependency tag: %T", depTag))
}
- sharedLibraryInfo := ctx.OtherModuleProvider(dep, SharedLibraryInfoProvider).(SharedLibraryInfo)
- depExporterInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
- sharedLibraryStubsInfo := ctx.OtherModuleProvider(dep, SharedLibraryStubsProvider).(SharedLibraryStubsInfo)
+ sharedLibraryInfo, _ := android.OtherModuleProvider(ctx, dep, SharedLibraryInfoProvider)
+ depExporterInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider)
+ sharedLibraryStubsInfo, _ := android.OtherModuleProvider(ctx, dep, SharedLibraryStubsProvider)
if !libDepTag.explicitlyVersioned && len(sharedLibraryStubsInfo.SharedStubLibraries) > 0 {
// when to use (unspecified) stubs, use the latest one.
@@ -3742,7 +3618,7 @@
// The vendor module is a no-vendor-variant VNDK library. Depend on the
// core module instead.
return libName
- } else if ccDep.UseVndk() && nonSystemVariantsExist {
+ } else if ccDep.InVendorOrProduct() && nonSystemVariantsExist {
// The vendor and product modules in Make will have been renamed to not conflict with the
// core module, so update the dependency name here accordingly.
return libName + ccDep.SubName()
@@ -3819,6 +3695,11 @@
return android.PathsIfNonNil(c.linker.unstrippedOutputFilePath()), nil
}
return nil, nil
+ case "stripped_all":
+ if c.linker != nil {
+ return android.PathsIfNonNil(c.linker.strippedAllOutputFilePath()), nil
+ }
+ return nil, nil
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
@@ -3914,7 +3795,7 @@
}
func GetMakeLinkType(actx android.ModuleContext, c LinkableInterface) string {
- if c.UseVndk() {
+ if c.InVendorOrProduct() {
if c.IsLlndk() {
if !c.IsLlndkPublic() {
return "native:vndk_private"
@@ -4158,6 +4039,7 @@
headerLibrary
testBin // testBinary already declared
ndkLibrary
+ ndkPrebuiltStl
)
func (c *Module) typ() moduleType {
@@ -4196,78 +4078,20 @@
return sharedLibrary
} else if c.isNDKStubLibrary() {
return ndkLibrary
+ } else if c.IsNdkPrebuiltStl() {
+ return ndkPrebuiltStl
}
return unknownType
}
-// ConvertWithBp2build converts Module to Bazel for bp2build.
-func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- prebuilt := c.IsPrebuilt()
- switch c.typ() {
- case binary:
- if prebuilt {
- prebuiltBinaryBp2Build(ctx, c)
- } else {
- binaryBp2build(ctx, c)
- }
- case testBin:
- if !prebuilt {
- testBinaryBp2build(ctx, c)
- }
- case object:
- if prebuilt {
- prebuiltObjectBp2Build(ctx, c)
- } else {
- objectBp2Build(ctx, c)
- }
- case fullLibrary:
- if !prebuilt {
- libraryBp2Build(ctx, c)
- } else {
- prebuiltLibraryBp2Build(ctx, c)
- }
- case headerLibrary:
- libraryHeadersBp2Build(ctx, c)
- case staticLibrary:
- if prebuilt {
- prebuiltLibraryStaticBp2Build(ctx, c, false)
- } else {
- sharedOrStaticLibraryBp2Build(ctx, c, true)
- }
- case sharedLibrary:
- if prebuilt {
- prebuiltLibrarySharedBp2Build(ctx, c)
- } else {
- sharedOrStaticLibraryBp2Build(ctx, c, false)
- }
- default:
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
- }
-}
-
-var _ android.ApiProvider = (*Module)(nil)
-
-func (c *Module) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
- if c.IsPrebuilt() {
- return
- }
- switch c.typ() {
- case fullLibrary:
- apiContributionBp2Build(ctx, c)
- case sharedLibrary:
- apiContributionBp2Build(ctx, c)
- case headerLibrary:
- // Aggressively generate api targets for all header modules
- // This is necessary since the header module does not know if it is a dep of API surface stub library
- apiLibraryHeadersBp2Build(ctx, c)
- }
-}
-
// Defaults
type Defaults struct {
android.ModuleBase
android.DefaultsModuleBase
android.ApexModuleBase
+
+ // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo
+ mergedAconfigFiles map[string]android.Paths
}
// cc_defaults provides a set of properties that can be inherited by other cc
@@ -4309,7 +4133,6 @@
&VndkProperties{},
<OProperties{},
&AfdoProperties{},
- &PgoProperties{},
&OrderfileProperties{},
&android.ProtoProperties{},
// RustBindgenProperties is included here so that cc_defaults can be used for rust_bindgen modules.
@@ -4360,6 +4183,18 @@
return ""
}
+type sourceModuleName interface {
+ sourceModuleName() string
+}
+
+func (c *Module) BaseModuleName() string {
+ if smn, ok := c.linker.(sourceModuleName); ok && smn.sourceModuleName() != "" {
+ // if the prebuilt module sets a source_module_name in Android.bp, use that
+ return smn.sourceModuleName()
+ }
+ return c.ModuleBase.BaseModuleName()
+}
+
var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault
var BoolPtr = proptools.BoolPtr
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 7ce0f37..6cc500b 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -26,7 +26,8 @@
"android/soong/aidl_library"
"android/soong/android"
- "android/soong/bazel/cquery"
+
+ "github.com/google/blueprint"
)
func init() {
@@ -40,33 +41,30 @@
var prepareForCcTest = android.GroupFixturePreparers(
PrepareForTestWithCcIncludeVndk,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.VendorApiLevel = StringPtr("202404")
variables.DeviceVndkVersion = StringPtr("current")
- variables.ProductVndkVersion = StringPtr("current")
+ variables.KeepVndk = BoolPtr(true)
variables.Platform_vndk_version = StringPtr("29")
}),
)
-var ccLibInApex = "cc_lib_in_apex"
+// TODO(b/316829758) Update prepareForCcTest with this configuration and remove prepareForCcTestWithoutVndk
+var prepareForCcTestWithoutVndk = android.GroupFixturePreparers(
+ PrepareForIntegrationTestWithCc,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.VendorApiLevel = StringPtr("202404")
+ }),
+)
+
var apexVariationName = "apex28"
var apexVersion = "28"
func registerTestMutators(ctx android.RegistrationContext) {
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("apex", testApexMutator).Parallel()
- ctx.BottomUp("mixed_builds_prep", mixedBuildsPrepareMutator).Parallel()
})
}
-func mixedBuildsPrepareMutator(ctx android.BottomUpMutatorContext) {
- if m := ctx.Module(); m.Enabled() {
- if mixedBuildMod, ok := m.(android.MixedBuildBuildable); ok {
- if mixedBuildMod.IsMixedBuildSupported(ctx) && android.MixedBuildsEnabled(ctx) == android.MixedBuildEnabled {
- mixedBuildMod.QueueBazelCall(ctx)
- }
- }
- }
-}
-
func testApexMutator(mctx android.BottomUpMutatorContext) {
modules := mctx.CreateVariations(apexVariationName)
apexInfo := android.ApexInfo{
@@ -104,33 +102,6 @@
return result.TestContext
}
-// testCcNoVndk runs tests using the prepareForCcTest
-//
-// See testCc for an explanation as to how to stop using this deprecated method.
-//
-// deprecated
-func testCcNoVndk(t *testing.T, bp string) *android.TestContext {
- t.Helper()
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-
- return testCcWithConfig(t, config)
-}
-
-// testCcNoProductVndk runs tests using the prepareForCcTest
-//
-// See testCc for an explanation as to how to stop using this deprecated method.
-//
-// deprecated
-func testCcNoProductVndk(t *testing.T, bp string) *android.TestContext {
- t.Helper()
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.Platform_vndk_version = StringPtr("29")
-
- return testCcWithConfig(t, config)
-}
-
// testCcErrorWithConfig runs tests using the prepareForCcTest
//
// See testCc for an explanation as to how to stop using this deprecated method.
@@ -167,7 +138,6 @@
t.Helper()
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.ProductVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
testCcErrorWithConfig(t, pattern, config)
return
@@ -235,13 +205,13 @@
}
}
socSpecific := func(m *Module) bool {
- return m.SocSpecific() || m.socSpecificModuleContext()
+ return m.SocSpecific() || m.InstallInVendor()
}
deviceSpecific := func(m *Module) bool {
- return m.DeviceSpecific() || m.deviceSpecificModuleContext()
+ return m.DeviceSpecific() || m.InstallInOdm()
}
productSpecific := func(m *Module) bool {
- return m.ProductSpecific() || m.productSpecificModuleContext()
+ return m.ProductSpecific() || m.InstallInProduct()
}
systemExtSpecific := func(m *Module) bool {
return m.SystemExtSpecific()
@@ -370,9 +340,9 @@
}
}
-func checkWriteFileOutput(t *testing.T, params android.TestingBuildParams, expected []string) {
+func checkWriteFileOutput(t *testing.T, ctx *android.TestContext, params android.TestingBuildParams, expected []string) {
t.Helper()
- content := android.ContentFromFileRuleForTests(t, params)
+ content := android.ContentFromFileRuleForTests(t, ctx, params)
actual := strings.FieldsFunc(content, func(r rune) bool { return r == '\n' })
assertArrayString(t, actual, expected)
}
@@ -380,7 +350,7 @@
func checkVndkOutput(t *testing.T, ctx *android.TestContext, output string, expected []string) {
t.Helper()
vndkSnapshot := ctx.SingletonForTests("vndk-snapshot")
- checkWriteFileOutput(t, vndkSnapshot.Output(output), expected)
+ checkWriteFileOutput(t, ctx, vndkSnapshot.Output(output), expected)
}
func checkVndkLibrariesOutput(t *testing.T, ctx *android.TestContext, module string, expected []string) {
@@ -523,7 +493,6 @@
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.ProductVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
ctx := testCcWithConfig(t, config)
@@ -707,6 +676,7 @@
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
config.TestProductVariables.VndkUseCoreVariant = BoolPtr(true)
+ config.TestProductVariables.KeepVndk = BoolPtr(true)
setVndkMustUseVendorVariantListForTest(config, []string{"libvndk"})
@@ -749,7 +719,7 @@
return
}
if len(testBinary.dataPaths()) != 1 {
- t.Errorf("expected exactly one test data file. test data files: [%s]", testBinary.dataPaths())
+ t.Errorf("expected exactly one test data file. test data files: [%v]", testBinary.dataPaths())
return
}
@@ -806,7 +776,7 @@
t.Fatalf("expected exactly one output file. output files: [%s]", outputFiles)
}
if len(testBinary.dataPaths()) != 2 {
- t.Fatalf("expected exactly one test data file. test data files: [%s]", testBinary.dataPaths())
+ t.Fatalf("expected exactly one test data file. test data files: [%v]", testBinary.dataPaths())
}
outputPath := outputFiles[0].String()
@@ -889,63 +859,6 @@
}
}
-func TestVndkWhenVndkVersionIsNotSet(t *testing.T) {
- t.Parallel()
- ctx := testCcNoVndk(t, `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
- cc_library {
- name: "libvndk-private",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- private: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libllndk",
- llndk: {
- symbol_file: "libllndk.map.txt",
- export_llndk_headers: ["libllndk_headers"],
- }
- }
-
- cc_library_headers {
- name: "libllndk_headers",
- llndk: {
- symbol_file: "libllndk.map.txt",
- },
- export_include_dirs: ["include"],
- }
- `)
-
- checkVndkOutput(t, ctx, "vndk/vndk.libraries.txt", []string{
- "LLNDK: libc.so",
- "LLNDK: libdl.so",
- "LLNDK: libft2.so",
- "LLNDK: libllndk.so",
- "LLNDK: libm.so",
- "VNDK-SP: libc++.so",
- "VNDK-core: libvndk-private.so",
- "VNDK-core: libvndk.so",
- "VNDK-private: libft2.so",
- "VNDK-private: libvndk-private.so",
- "VNDK-product: libc++.so",
- "VNDK-product: libvndk-private.so",
- "VNDK-product: libvndk.so",
- })
-}
-
func TestVndkModuleError(t *testing.T) {
t.Parallel()
// Check the error message for vendor_available and product_available properties.
@@ -1111,6 +1024,7 @@
cc_library {
name: "libnonvndk",
vendor_available: true,
+ product_available: true,
nocrt: true,
}
`)
@@ -1132,6 +1046,7 @@
cc_library {
name: "libnonvndk",
vendor_available: true,
+ product_available: true,
nocrt: true,
}
`)
@@ -1153,6 +1068,7 @@
cc_library {
name: "libnonvndk",
vendor_available: true,
+ product_available: true,
nocrt: true,
}
`)
@@ -1175,6 +1091,7 @@
cc_library {
name: "libnonvndk",
vendor_available: true,
+ product_available: true,
nocrt: true,
}
`)
@@ -1390,6 +1307,7 @@
cc_library {
name: "libanothervndksp",
vendor_available: true,
+ product_available: true,
}
`)
}
@@ -1467,7 +1385,6 @@
`
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.ProductVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
ctx := testCcWithConfig(t, config)
@@ -1482,70 +1399,6 @@
assertString(t, mod_product.outputFile.Path().Base(), "libvndk2-suffix.so")
}
-func TestVndkExtWithoutBoardVndkVersion(t *testing.T) {
- t.Parallel()
- // This test checks the VNDK-Ext properties when BOARD_VNDK_VERSION is not set.
- ctx := testCcNoVndk(t, `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext",
- vendor: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- nocrt: true,
- }
- `)
-
- // Ensures that the core variant of "libvndk_ext" can be found.
- mod := ctx.ModuleForTests("libvndk_ext", coreVariant).Module().(*Module)
- if extends := mod.getVndkExtendsModuleName(); extends != "libvndk" {
- t.Errorf("\"libvndk_ext\" must extend from \"libvndk\" but get %q", extends)
- }
-}
-
-func TestVndkExtWithoutProductVndkVersion(t *testing.T) {
- t.Parallel()
- // This test checks the VNDK-Ext properties when PRODUCT_PRODUCT_VNDK_VERSION is not set.
- ctx := testCcNoProductVndk(t, `
- cc_library {
- name: "libvndk",
- vendor_available: true,
- product_available: true,
- vndk: {
- enabled: true,
- },
- nocrt: true,
- }
-
- cc_library {
- name: "libvndk_ext_product",
- product_specific: true,
- vndk: {
- enabled: true,
- extends: "libvndk",
- },
- nocrt: true,
- }
- `)
-
- // Ensures that the core variant of "libvndk_ext_product" can be found.
- mod := ctx.ModuleForTests("libvndk_ext_product", coreVariant).Module().(*Module)
- if extends := mod.getVndkExtendsModuleName(); extends != "libvndk" {
- t.Errorf("\"libvndk_ext_product\" must extend from \"libvndk\" but get %q", extends)
- }
-}
-
func TestVndkExtError(t *testing.T) {
t.Parallel()
// This test ensures an error is emitted in ill-formed vndk-ext definition.
@@ -1920,7 +1773,6 @@
`
config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
config.TestProductVariables.DeviceVndkVersion = StringPtr("current")
- config.TestProductVariables.ProductVndkVersion = StringPtr("current")
config.TestProductVariables.Platform_vndk_version = StringPtr("29")
testCcWithConfig(t, config)
@@ -2278,11 +2130,13 @@
ensureStringContains(t, vendor_cflags, "-D__ANDROID_VNDK__")
ensureStringContains(t, vendor_cflags, "-D__ANDROID_VENDOR__")
ensureStringNotContains(t, vendor_cflags, "-D__ANDROID_PRODUCT__")
+ ensureStringContains(t, vendor_cflags, "-D__ANDROID_VENDOR_API__=202404")
product_cflags := product_static.Rule("cc").Args["cFlags"]
ensureStringContains(t, product_cflags, "-D__ANDROID_VNDK__")
ensureStringContains(t, product_cflags, "-D__ANDROID_PRODUCT__")
ensureStringNotContains(t, product_cflags, "-D__ANDROID_VENDOR__")
+ ensureStringNotContains(t, product_cflags, "-D__ANDROID_VENDOR_API__=202404")
}
func TestEnforceProductVndkVersionErrors(t *testing.T) {
@@ -2701,8 +2555,8 @@
variant := "android_arm64_armv8-a_static"
moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
- actual := android.Paths(ctx.ModuleProvider(moduleA, StaticLibraryInfoProvider).(StaticLibraryInfo).
- TransitiveStaticLibrariesForOrdering.ToList()).RelativeToTop()
+ staticLibInfo, _ := android.SingletonModuleProvider(ctx, moduleA, StaticLibraryInfoProvider)
+ actual := android.Paths(staticLibInfo.TransitiveStaticLibrariesForOrdering.ToList()).RelativeToTop()
expected := GetOutputPaths(ctx, variant, []string{"a", "c", "b", "d"})
if !reflect.DeepEqual(actual, expected) {
@@ -2737,8 +2591,8 @@
variant := "android_arm64_armv8-a_static"
moduleA := ctx.ModuleForTests("a", variant).Module().(*Module)
- actual := android.Paths(ctx.ModuleProvider(moduleA, StaticLibraryInfoProvider).(StaticLibraryInfo).
- TransitiveStaticLibrariesForOrdering.ToList()).RelativeToTop()
+ staticLibInfo, _ := android.SingletonModuleProvider(ctx, moduleA, StaticLibraryInfoProvider)
+ actual := android.Paths(staticLibInfo.TransitiveStaticLibrariesForOrdering.ToList()).RelativeToTop()
expected := GetOutputPaths(ctx, variant, []string{"a", "c", "b"})
if !reflect.DeepEqual(actual, expected) {
@@ -2797,6 +2651,7 @@
name: "libexternal_headers",
export_include_dirs: ["include"],
vendor_available: true,
+ product_available: true,
}
cc_library_headers {
name: "libexternal_llndk_headers",
@@ -2838,7 +2693,7 @@
checkExportedIncludeDirs := func(module, variant string, expectedDirs ...string) {
t.Helper()
m := result.ModuleForTests(module, variant).Module()
- f := result.ModuleProvider(m, FlagExporterInfoProvider).(FlagExporterInfo)
+ f, _ := android.SingletonModuleProvider(result, m, FlagExporterInfoProvider)
android.AssertPathsRelativeToTopEquals(t, "exported include dirs for "+module+"["+variant+"]",
expectedDirs, f.IncludeDirs)
}
@@ -3034,24 +2889,6 @@
checkRuntimeLibs(t, nil, module)
}
-func TestRuntimeLibsNoVndk(t *testing.T) {
- t.Parallel()
- ctx := testCcNoVndk(t, runtimeLibAndroidBp)
-
- // If DeviceVndkVersion is not defined, then runtime_libs are copied as-is.
-
- variant := "android_arm64_armv8-a_shared"
-
- module := ctx.ModuleForTests("libvendor_available1", variant).Module().(*Module)
- checkRuntimeLibs(t, []string{"liball_available"}, module)
-
- module = ctx.ModuleForTests("libvendor2", variant).Module().(*Module)
- checkRuntimeLibs(t, []string{"liball_available", "libvendor1", "libproduct_vendor"}, module)
-
- module = ctx.ModuleForTests("libproduct2", variant).Module().(*Module)
- checkRuntimeLibs(t, []string{"liball_available", "libproduct1", "libproduct_vendor"}, module)
-}
-
func checkStaticLibs(t *testing.T, expected []string, module *Module) {
t.Helper()
actual := module.Properties.AndroidMkStaticLibs
@@ -3091,258 +2928,6 @@
checkStaticLibs(t, []string{"lib1", "libc++_static", "libc++demangle", "libclang_rt.builtins"}, module)
}
-func TestLibDepAndroidMkExportInMixedBuilds(t *testing.T) {
- bp := `
- cc_library {
- name: "static_dep",
- }
- cc_library {
- name: "whole_static_dep",
- }
- cc_library {
- name: "shared_dep",
- }
- cc_library {
- name: "lib",
- bazel_module: { label: "//:lib" },
- static_libs: ["static_dep"],
- whole_static_libs: ["whole_static_dep"],
- shared_libs: ["shared_dep"],
- }
- cc_test {
- name: "test",
- bazel_module: { label: "//:test" },
- static_libs: ["static_dep"],
- whole_static_libs: ["whole_static_dep"],
- shared_libs: ["shared_dep"],
- gtest: false,
- sanitize: {
- // cc_test modules default to memtag_heap: true,
- // but this adds extra dependencies that we don't care about
- never: true,
- }
- }
- cc_binary {
- name: "binary",
- bazel_module: { label: "//:binary" },
- static_libs: ["static_dep"],
- whole_static_libs: ["whole_static_dep"],
- shared_libs: ["shared_dep"],
- }
- cc_library_headers {
- name: "lib_headers",
- bazel_module: { label: "//:lib_headers" },
- static_libs: ["static_dep"],
- whole_static_libs: ["whole_static_dep"],
- shared_libs: ["shared_dep"],
- }
- cc_prebuilt_library {
- name: "lib_prebuilt",
- bazel_module: { label: "//:lib_prebuilt" },
- static_libs: ["static_dep"],
- whole_static_libs: ["whole_static_dep"],
- shared_libs: ["shared_dep"],
- }
- `
-
- testCases := []struct {
- name string
- moduleName string
- variant string
- androidMkInfo cquery.CcAndroidMkInfo
- }{
- {
- name: "shared lib",
- moduleName: "lib",
- variant: "android_arm64_armv8-a_shared",
- androidMkInfo: cquery.CcAndroidMkInfo{
- LocalStaticLibs: []string{"static_dep"},
- LocalWholeStaticLibs: []string{"whole_static_dep"},
- LocalSharedLibs: []string{"shared_dep"},
- },
- },
- {
- name: "static lib",
- moduleName: "lib",
- variant: "android_arm64_armv8-a_static",
- androidMkInfo: cquery.CcAndroidMkInfo{
- LocalStaticLibs: []string{"static_dep"},
- LocalWholeStaticLibs: []string{"whole_static_dep"},
- LocalSharedLibs: []string{"shared_dep"},
- },
- },
- {
- name: "cc_test arm64",
- moduleName: "test",
- variant: "android_arm64_armv8-a",
- androidMkInfo: cquery.CcAndroidMkInfo{
- LocalStaticLibs: []string{"static_dep"},
- LocalWholeStaticLibs: []string{"whole_static_dep"},
- LocalSharedLibs: []string{"shared_dep"},
- },
- },
- {
- name: "cc_test arm",
- moduleName: "test",
- variant: "android_arm_armv7-a-neon",
- androidMkInfo: cquery.CcAndroidMkInfo{
- LocalStaticLibs: []string{"static_dep"},
- LocalWholeStaticLibs: []string{"whole_static_dep"},
- LocalSharedLibs: []string{"shared_dep"},
- },
- },
- {
- name: "cc_binary",
- moduleName: "binary",
- variant: "android_arm64_armv8-a",
- androidMkInfo: cquery.CcAndroidMkInfo{
- LocalStaticLibs: []string{"static_dep"},
- LocalWholeStaticLibs: []string{"whole_static_dep"},
- LocalSharedLibs: []string{"shared_dep"},
- },
- },
- {
- name: "cc_library_headers",
- moduleName: "lib_headers",
- variant: "android_arm64_armv8-a",
- androidMkInfo: cquery.CcAndroidMkInfo{
- LocalStaticLibs: []string{"static_dep"},
- LocalWholeStaticLibs: []string{"whole_static_dep"},
- LocalSharedLibs: []string{"shared_dep"},
- },
- },
- {
- name: "prebuilt lib static",
- moduleName: "lib_prebuilt",
- variant: "android_arm64_armv8-a_static",
- androidMkInfo: cquery.CcAndroidMkInfo{
- LocalStaticLibs: []string{"static_dep"},
- LocalWholeStaticLibs: []string{"whole_static_dep"},
- LocalSharedLibs: []string{"shared_dep"},
- },
- },
- {
- name: "prebuilt lib shared",
- moduleName: "lib_prebuilt",
- variant: "android_arm64_armv8-a_shared",
- androidMkInfo: cquery.CcAndroidMkInfo{
- LocalStaticLibs: []string{"static_dep"},
- LocalWholeStaticLibs: []string{"whole_static_dep"},
- LocalSharedLibs: []string{"shared_dep"},
- },
- },
- }
-
- outputBaseDir := "out/bazel"
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- result := android.GroupFixturePreparers(
- prepareForCcTest,
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: outputBaseDir,
- LabelToCcInfo: map[string]cquery.CcInfo{
- "//:lib": cquery.CcInfo{
- CcAndroidMkInfo: tc.androidMkInfo,
- RootDynamicLibraries: []string{""},
- },
- "//:lib_bp2build_cc_library_static": cquery.CcInfo{
- CcAndroidMkInfo: tc.androidMkInfo,
- RootStaticArchives: []string{""},
- },
- "//:lib_headers": cquery.CcInfo{
- CcAndroidMkInfo: tc.androidMkInfo,
- OutputFiles: []string{""},
- },
- "//:lib_prebuilt": cquery.CcInfo{
- CcAndroidMkInfo: tc.androidMkInfo,
- },
- "//:lib_prebuilt_bp2build_cc_library_static": cquery.CcInfo{
- CcAndroidMkInfo: tc.androidMkInfo,
- },
- },
- LabelToCcBinary: map[string]cquery.CcUnstrippedInfo{
- "//:test__tf_internal": cquery.CcUnstrippedInfo{
- CcAndroidMkInfo: tc.androidMkInfo,
- },
- "//:binary": cquery.CcUnstrippedInfo{
- CcAndroidMkInfo: tc.androidMkInfo,
- },
- },
- }
- }),
- ).RunTestWithBp(t, bp)
- ctx := result.TestContext
-
- module := ctx.ModuleForTests(tc.moduleName, tc.variant).Module().(*Module)
- entries := android.AndroidMkEntriesForTest(t, ctx, module)[0]
- if !reflect.DeepEqual(module.Properties.AndroidMkStaticLibs, tc.androidMkInfo.LocalStaticLibs) {
- t.Errorf("incorrect static_libs"+
- "\nactual: %v"+
- "\nexpected: %v",
- module.Properties.AndroidMkStaticLibs,
- tc.androidMkInfo.LocalStaticLibs,
- )
- }
- staticDepsDiffer, missingStaticDeps, additionalStaticDeps := android.ListSetDifference(
- entries.EntryMap["LOCAL_STATIC_LIBRARIES"],
- tc.androidMkInfo.LocalStaticLibs,
- )
- if staticDepsDiffer {
- t.Errorf(
- "expected LOCAL_STATIC_LIBRARIES to be %q but was %q; missing: %q; extra %q",
- tc.androidMkInfo.LocalStaticLibs,
- entries.EntryMap["LOCAL_STATIC_LIBRARIES"],
- missingStaticDeps,
- additionalStaticDeps,
- )
- }
-
- if !reflect.DeepEqual(module.Properties.AndroidMkWholeStaticLibs, tc.androidMkInfo.LocalWholeStaticLibs) {
- t.Errorf("expected module.Properties.AndroidMkWholeStaticLibs to be %q, but was %q",
- tc.androidMkInfo.LocalWholeStaticLibs,
- module.Properties.AndroidMkWholeStaticLibs,
- )
- }
- wholeStaticDepsDiffer, missingWholeStaticDeps, additionalWholeStaticDeps := android.ListSetDifference(
- entries.EntryMap["LOCAL_WHOLE_STATIC_LIBRARIES"],
- tc.androidMkInfo.LocalWholeStaticLibs,
- )
- if wholeStaticDepsDiffer {
- t.Errorf(
- "expected LOCAL_WHOLE_STATIC_LIBRARIES to be %q but was %q; missing: %q; extra %q",
- tc.androidMkInfo.LocalWholeStaticLibs,
- entries.EntryMap["LOCAL_WHOLE_STATIC_LIBRARIES"],
- missingWholeStaticDeps,
- additionalWholeStaticDeps,
- )
- }
-
- if !reflect.DeepEqual(module.Properties.AndroidMkSharedLibs, tc.androidMkInfo.LocalSharedLibs) {
- t.Errorf("incorrect shared_libs"+
- "\nactual: %v"+
- "\nexpected: %v",
- module.Properties.AndroidMkSharedLibs,
- tc.androidMkInfo.LocalSharedLibs,
- )
- }
- sharedDepsDiffer, missingSharedDeps, additionalSharedDeps := android.ListSetDifference(
- entries.EntryMap["LOCAL_SHARED_LIBRARIES"],
- tc.androidMkInfo.LocalSharedLibs,
- )
- if sharedDepsDiffer {
- t.Errorf(
- "expected LOCAL_SHARED_LIBRARIES to be %q but was %q; missing %q; extra %q",
- tc.androidMkInfo.LocalSharedLibs,
- entries.EntryMap["LOCAL_SHARED_LIBRARIES"],
- missingSharedDeps,
- additionalSharedDeps,
- )
- }
- })
- }
-}
-
var compilerFlagsTestCases = []struct {
in string
out bool
@@ -3497,7 +3082,7 @@
t.Errorf("expected exactly one output file. output files: [%s]", outputFiles)
}
if len(testBinary.dataPaths()) != 1 {
- t.Errorf("expected exactly one test data file. test data files: [%s]", testBinary.dataPaths())
+ t.Errorf("expected exactly one test data file. test data files: [%v]", testBinary.dataPaths())
}
outputPath := outputFiles[0].String()
@@ -3684,130 +3269,6 @@
}
}
-func TestMixedBuildUsesStubs(t *testing.T) {
- t.Parallel()
- bp := `
- cc_library_shared {
- name: "libFoo",
- bazel_module: { label: "//:libFoo" },
- srcs: ["foo.c"],
- stubs: {
- symbol_file: "foo.map.txt",
- versions: ["current"],
- },
- apex_available: ["bar", "a1"],
- }
-
- cc_library_shared {
- name: "libBar",
- srcs: ["bar.c"],
- shared_libs: ["libFoo"],
- apex_available: ["a1"],
- }
-
- cc_library_shared {
- name: "libA1",
- srcs: ["a1.c"],
- shared_libs: ["libFoo"],
- apex_available: ["a1"],
- }
-
- cc_library_shared {
- name: "libBarA1",
- srcs: ["bara1.c"],
- shared_libs: ["libFoo"],
- apex_available: ["bar", "a1"],
- }
-
- cc_library_shared {
- name: "libAnyApex",
- srcs: ["anyApex.c"],
- shared_libs: ["libFoo"],
- apex_available: ["//apex_available:anyapex"],
- }
-
- cc_library_shared {
- name: "libBaz",
- srcs: ["baz.c"],
- shared_libs: ["libFoo"],
- apex_available: ["baz"],
- }
-
- cc_library_shared {
- name: "libQux",
- srcs: ["qux.c"],
- shared_libs: ["libFoo"],
- apex_available: ["qux", "bar"],
- }`
-
- result := android.GroupFixturePreparers(
- prepareForCcTest,
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: "out/bazel",
- LabelToCcInfo: map[string]cquery.CcInfo{
- "//:libFoo": {
- RootDynamicLibraries: []string{"libFoo.so"},
- },
- "//:libFoo_stub_libs-current": {
- RootDynamicLibraries: []string{"libFoo_stub_libs-current.so"},
- },
- },
- }
- }),
- ).RunTestWithBp(t, bp)
- ctx := result.TestContext
-
- variants := ctx.ModuleVariantsForTests("libFoo")
- expectedVariants := []string{
- "android_arm64_armv8-a_shared",
- "android_arm64_armv8-a_shared_current",
- "android_arm_armv7-a-neon_shared",
- "android_arm_armv7-a-neon_shared_current",
- }
- variantsMismatch := false
- if len(variants) != len(expectedVariants) {
- variantsMismatch = true
- } else {
- for _, v := range expectedVariants {
- if !inList(v, variants) {
- variantsMismatch = false
- }
- }
- }
- if variantsMismatch {
- t.Errorf("variants of libFoo expected:\n")
- for _, v := range expectedVariants {
- t.Errorf("%q\n", v)
- }
- t.Errorf(", but got:\n")
- for _, v := range variants {
- t.Errorf("%q\n", v)
- }
- }
-
- linkAgainstFoo := []string{"libBarA1"}
- linkAgainstFooStubs := []string{"libBar", "libA1", "libBaz", "libQux", "libAnyApex"}
-
- libFooPath := "out/bazel/execroot/__main__/libFoo.so"
- for _, lib := range linkAgainstFoo {
- libLinkRule := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld")
- libFlags := libLinkRule.Args["libFlags"]
- if !strings.Contains(libFlags, libFooPath) {
- t.Errorf("%q: %q is not found in %q", lib, libFooPath, libFlags)
- }
- }
-
- libFooStubPath := "out/bazel/execroot/__main__/libFoo_stub_libs-current.so"
- for _, lib := range linkAgainstFooStubs {
- libLinkRule := ctx.ModuleForTests(lib, "android_arm64_armv8-a_shared").Rule("ld")
- libFlags := libLinkRule.Args["libFlags"]
- if !strings.Contains(libFlags, libFooStubPath) {
- t.Errorf("%q: %q is not found in %q", lib, libFooStubPath, libFlags)
- }
- }
-}
-
func TestVersioningMacro(t *testing.T) {
t.Parallel()
for _, tc := range []struct{ moduleName, expected string }{
@@ -4181,9 +3642,6 @@
shared: {
srcs: ["baz.c"],
},
- bazel_module: {
- bp2build_available: true,
- },
}
cc_library_static {
@@ -4467,7 +3925,7 @@
libfoo.Rule("aidl_library").Implicits,
)
- manifest := android.RuleBuilderSboxProtoForTests(t, libfoo.Output("aidl_library.sbox.textproto"))
+ manifest := android.RuleBuilderSboxProtoForTests(t, ctx, libfoo.Output("aidl_library.sbox.textproto"))
aidlCommand := manifest.Commands[0].GetCommand()
expectedAidlFlags := "-Ipackage_foo/a -Ipackage_bar/x"
@@ -4502,7 +3960,7 @@
`)
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_static")
- manifest := android.RuleBuilderSboxProtoForTests(t, libfoo.Output("aidl.sbox.textproto"))
+ manifest := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, libfoo.Output("aidl.sbox.textproto"))
aidlCommand := manifest.Commands[0].GetCommand()
expectedAidlFlag := "-Werror"
if !strings.Contains(aidlCommand, expectedAidlFlag) {
@@ -4553,7 +4011,7 @@
}
`)
libfoo := ctx.ModuleForTests("libfoo", tc.variant)
- manifest := android.RuleBuilderSboxProtoForTests(t, libfoo.Output("aidl.sbox.textproto"))
+ manifest := android.RuleBuilderSboxProtoForTests(t, ctx, libfoo.Output("aidl.sbox.textproto"))
aidlCommand := manifest.Commands[0].GetCommand()
expectedAidlFlag := "--min_sdk_version=" + tc.expected
if !strings.Contains(aidlCommand, expectedAidlFlag) {
@@ -4667,7 +4125,7 @@
checkIncludeDirs := func(t *testing.T, ctx *android.TestContext, module android.Module, checkers ...exportedChecker) {
t.Helper()
- exported := ctx.ModuleProvider(module, FlagExporterInfoProvider).(FlagExporterInfo)
+ exported, _ := android.SingletonModuleProvider(ctx, module, FlagExporterInfoProvider)
name := module.Name()
for _, checker := range checkers {
@@ -4983,7 +4441,7 @@
cflags := []string{"-Werror", "-std=candcpp"}
cstd := []string{"-std=gnu17", "-std=conly"}
- cppstd := []string{"-std=gnu++17", "-std=cpp", "-fno-rtti"}
+ cppstd := []string{"-std=gnu++20", "-std=cpp", "-fno-rtti"}
lastIncludes := []string{
"out/soong/ndk/sysroot/usr/include",
@@ -5313,308 +4771,116 @@
}
}
-func TestDclaLibraryInApex(t *testing.T) {
+func TestStrippedAllOutputFile(t *testing.T) {
t.Parallel()
bp := `
- cc_library_shared {
- name: "cc_lib_in_apex",
- srcs: ["foo.cc"],
- apex_available: ["myapex"],
- bazel_module: { label: "//foo/bar:bar" },
- }`
- label := "//foo/bar:bar"
- arch64 := "arm64_armv8-a"
- arch32 := "arm_armv7-a-neon"
- apexCfgKey := android.ApexConfigKey{
- WithinApex: true,
- ApexSdkVersion: "28",
- }
-
- result := android.GroupFixturePreparers(
- prepareForCcTest,
- android.FixtureRegisterWithContext(registerTestMutators),
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: "outputbase",
- LabelToCcInfo: map[string]cquery.CcInfo{
- android.BuildMockBazelContextResultKey(label, arch32, android.Android, apexCfgKey): cquery.CcInfo{
- RootDynamicLibraries: []string{"foo.so"},
- },
- android.BuildMockBazelContextResultKey(label, arch64, android.Android, apexCfgKey): cquery.CcInfo{
- RootDynamicLibraries: []string{"foo.so"},
- },
- },
- BazelRequests: make(map[string]bool),
+ cc_library {
+ name: "test_lib",
+ srcs: ["test_lib.cpp"],
+ dist: {
+ targets: [ "dist_target" ],
+ tag: "stripped_all",
}
- }),
- ).RunTestWithBp(t, bp)
- ctx := result.TestContext
-
- // Test if the bazel request is queued correctly
- key := android.BuildMockBazelContextRequestKey(label, cquery.GetCcInfo, arch32, android.Android, apexCfgKey)
- if !ctx.Config().BazelContext.(android.MockBazelContext).BazelRequests[key] {
- t.Errorf("Bazel request was not queued: %s", key)
- }
-
- sharedFoo := ctx.ModuleForTests(ccLibInApex, "android_arm_armv7-a-neon_shared_"+apexVariationName).Module()
- producer := sharedFoo.(android.OutputFileProducer)
- outputFiles, err := producer.OutputFiles("")
+ }
+ `
+ config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
+ ctx := testCcWithConfig(t, config)
+ module := ctx.ModuleForTests("test_lib", "android_arm_armv7-a-neon_shared").Module()
+ outputFile, err := module.(android.OutputFileProducer).OutputFiles("stripped_all")
if err != nil {
- t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
+ t.Errorf("Expected cc_library to produce output files, error: %s", err)
+ return
}
- expectedOutputFiles := []string{"outputbase/execroot/__main__/foo.so"}
- android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
+ if !strings.HasSuffix(outputFile.Strings()[0], "/stripped_all/test_lib.so") {
+ t.Errorf("Unexpected output file: %s", outputFile.Strings()[0])
+ return
+ }
}
-func TestDisableSanitizerVariantsInMixedBuilds(t *testing.T) {
+// TODO(b/316829758) Remove this test and do not set VNDK version from other tests
+func TestImageVariantsWithoutVndk(t *testing.T) {
t.Parallel()
+
bp := `
- cc_library_static {
- name: "foo_ubsan_minimal",
- srcs: ["foo.cc"],
- bazel_module: { label: "//foo_ubsan_minimal" },
- sanitize: {
- all_undefined: true,
- integer_overflow: true,
- },
+ cc_binary {
+ name: "binfoo",
+ srcs: ["binfoo.cc"],
+ vendor_available: true,
+ product_available: true,
+ shared_libs: ["libbar"]
+ }
+ cc_library {
+ name: "libbar",
+ srcs: ["libbar.cc"],
+ vendor_available: true,
+ product_available: true,
+ }
+ `
+
+ ctx := prepareForCcTestWithoutVndk.RunTestWithBp(t, bp)
+
+ hasDep := func(m android.Module, wantDep android.Module) bool {
+ t.Helper()
+ var found bool
+ ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
+ if dep == wantDep {
+ found = true
+ }
+ })
+ return found
+ }
+
+ testDepWithVariant := func(imageVariant string) {
+ imageVariantStr := ""
+ if imageVariant != "core" {
+ imageVariantStr = "_" + imageVariant
}
- cc_library_static {
- name: "foo",
- srcs: ["foo.cc"],
- bazel_module: { label: "//foo" },
- sanitize: {
- address: true,
- hwaddress: true,
- fuzzer: true,
- integer_overflow: true,
- scs: true,
- },
+ binFooModule := ctx.ModuleForTests("binfoo", "android"+imageVariantStr+"_arm64_armv8-a").Module()
+ libBarModule := ctx.ModuleForTests("libbar", "android"+imageVariantStr+"_arm64_armv8-a_shared").Module()
+ android.AssertBoolEquals(t, "binfoo should have dependency on libbar with image variant "+imageVariant, true, hasDep(binFooModule, libBarModule))
+ }
+
+ testDepWithVariant("core")
+ testDepWithVariant("vendor")
+ testDepWithVariant("product")
+}
+
+func TestVendorSdkVersionWithoutVndk(t *testing.T) {
+ t.Parallel()
+
+ bp := `
+ cc_library {
+ name: "libfoo",
+ srcs: ["libfoo.cc"],
+ vendor_available: true,
}
- cc_library_static {
- name: "foo_tsan",
- srcs: ["foo.cc"],
- bazel_module: { label: "//foo_tsan" },
- sanitize: {
- thread: true,
- },
- }
- cc_library_static {
- name: "foo_cfi",
- srcs: ["foo.cc"],
- bazel_module: { label: "//foo_cfi" },
- sanitize: {
- cfi: true,
- },
- }
- cc_library_static {
- name: "foo_memtag_stack",
- srcs: ["foo.cc"],
- bazel_module: { label: "//foo_memtag_stack" },
- sanitize: {
- memtag_stack: true,
- },
- }
- cc_library_static {
- name: "foo_memtag_heap",
- srcs: ["foo.cc"],
- bazel_module: { label: "//foo_memtag_heap" },
- sanitize: {
- memtag_heap: true,
- },
- }
- cc_library_static {
- name: "foo_safestack",
- srcs: ["foo.cc"],
- bazel_module: { label: "//foo_safestack" },
- sanitize: {
- safestack: true,
- },
- }
- cc_library_static {
- name: "foo_scudo",
- srcs: ["foo.cc"],
- bazel_module: { label: "//foo_scudo" },
- sanitize: {
- scudo: true,
- },
+
+ cc_library {
+ name: "libbar",
+ srcs: ["libbar.cc"],
+ vendor_available: true,
+ min_sdk_version: "29",
}
`
- testcases := []struct {
- name string
- variant string
- expectedOutputPaths []string
- }{
- {
- name: "foo_ubsan_minimal",
- variant: "android_arm64_armv8-a_static_apex28",
- expectedOutputPaths: []string{
- "outputbase/execroot/__main__/foo_ubsan_minimal.a",
- },
- },
- {
- name: "foo",
- variant: "android_arm64_armv8-a_static_apex28",
- expectedOutputPaths: []string{
- "outputbase/execroot/__main__/foo.a",
- },
- },
- {
- name: "foo",
- variant: "android_arm_armv7-a-neon_static_asan_apex28",
- expectedOutputPaths: []string{
- "out/soong/.intermediates/foo/android_arm_armv7-a-neon_static_asan_apex28/foo.a",
- },
- },
- {
- name: "foo",
- variant: "android_arm64_armv8-a_static_hwasan_apex28",
- expectedOutputPaths: []string{
- "out/soong/.intermediates/foo/android_arm64_armv8-a_static_hwasan_apex28/foo.a",
- },
- },
- {
- name: "foo",
- variant: "android_arm64_armv8-a_static_fuzzer_apex28",
- expectedOutputPaths: []string{
- "out/soong/.intermediates/foo/android_arm64_armv8-a_static_fuzzer_apex28/foo.a",
- },
- },
- {
- name: "foo",
- variant: "android_arm_armv7-a-neon_static_asan_fuzzer_apex28",
- expectedOutputPaths: []string{
- "out/soong/.intermediates/foo/android_arm_armv7-a-neon_static_asan_fuzzer_apex28/foo.a",
- },
- },
- {
- name: "foo",
- variant: "android_arm64_armv8-a_static_hwasan_fuzzer_apex28",
- expectedOutputPaths: []string{
- "out/soong/.intermediates/foo/android_arm64_armv8-a_static_hwasan_fuzzer_apex28/foo.a",
- },
- },
- {
- name: "foo",
- variant: "android_arm64_armv8-a_static_scs_apex28",
- expectedOutputPaths: []string{
- "out/soong/.intermediates/foo/android_arm64_armv8-a_static_scs_apex28/foo.a",
- },
- },
- {
- name: "foo",
- variant: "android_arm64_armv8-a_static_hwasan_scs_apex28",
- expectedOutputPaths: []string{
- "out/soong/.intermediates/foo/android_arm64_armv8-a_static_hwasan_scs_apex28/foo.a",
- },
- },
- {
- name: "foo",
- variant: "android_arm64_armv8-a_static_hwasan_scs_fuzzer_apex28",
- expectedOutputPaths: []string{
- "out/soong/.intermediates/foo/android_arm64_armv8-a_static_hwasan_scs_fuzzer_apex28/foo.a",
- },
- },
- {
- name: "foo_tsan",
- variant: "android_arm64_armv8-a_static_apex28",
- expectedOutputPaths: []string{
- "outputbase/execroot/__main__/foo_tsan.a",
- },
- },
- {
- name: "foo_tsan",
- variant: "android_arm64_armv8-a_static_tsan_apex28",
- expectedOutputPaths: []string{
- "out/soong/.intermediates/foo_tsan/android_arm64_armv8-a_static_tsan_apex28/foo_tsan.a",
- },
- },
- {
- name: "foo_cfi",
- variant: "android_arm64_armv8-a_static_apex28",
- expectedOutputPaths: []string{
- "outputbase/execroot/__main__/foo_cfi.a",
- },
- },
- {
- name: "foo_cfi",
- variant: "android_arm64_armv8-a_static_cfi_apex28",
- expectedOutputPaths: []string{
- "outputbase/execroot/__main__/foo_cfi.a",
- },
- },
- {
- name: "foo_memtag_stack",
- variant: "android_arm64_armv8-a_static_apex28",
- expectedOutputPaths: []string{
- "out/soong/.intermediates/foo_memtag_stack/android_arm64_armv8-a_static_apex28/foo_memtag_stack.a",
- },
- },
- {
- name: "foo_memtag_heap",
- variant: "android_arm64_armv8-a_static_apex28",
- expectedOutputPaths: []string{
- "out/soong/.intermediates/foo_memtag_heap/android_arm64_armv8-a_static_apex28/foo_memtag_heap.a",
- },
- },
- {
- name: "foo_safestack",
- variant: "android_arm64_armv8-a_static_apex28",
- expectedOutputPaths: []string{
- "out/soong/.intermediates/foo_safestack/android_arm64_armv8-a_static_apex28/foo_safestack.a",
- },
- },
- {
- name: "foo_scudo",
- variant: "android_arm64_armv8-a_static_apex28",
- expectedOutputPaths: []string{
- "out/soong/.intermediates/foo_scudo/android_arm64_armv8-a_static_apex28/foo_scudo.a",
- },
- },
+
+ ctx := prepareForCcTestWithoutVndk.RunTestWithBp(t, bp)
+ testSdkVersionFlag := func(module, version string) {
+ flags := ctx.ModuleForTests(module, "android_vendor_arm64_armv8-a_static").Rule("cc").Args["cFlags"]
+ android.AssertStringDoesContain(t, "min sdk version", flags, "-target aarch64-linux-android"+version)
}
- ctx := android.GroupFixturePreparers(
- prepareForCcTest,
- prepareForAsanTest,
- android.FixtureRegisterWithContext(registerTestMutators),
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: "outputbase",
- LabelToCcInfo: map[string]cquery.CcInfo{
- "//foo_ubsan_minimal": {
- RootStaticArchives: []string{"foo_ubsan_minimal.a"},
- },
- "//foo": {
- RootStaticArchives: []string{"foo.a"},
- },
- "//foo_tsan": {
- RootStaticArchives: []string{"foo_tsan.a"},
- },
- "//foo_cfi": {
- RootStaticArchives: []string{"foo_cfi.a"},
- },
- "//foo_memtag_stack": {
- RootStaticArchives: []string{"INVALID_ARCHIVE.a"},
- },
- "//foo_memtag_heap": {
- RootStaticArchives: []string{"INVALID_ARCHIVE.a"},
- },
- "//foo_safestack": {
- RootStaticArchives: []string{"INVALID_ARCHIVE.a"},
- },
- "//foo_scudo": {
- RootStaticArchives: []string{"INVALID_ARCHIVE.a"},
- },
- },
+ testSdkVersionFlag("libfoo", "10000")
+ testSdkVersionFlag("libbar", "29")
+
+ ctx = android.GroupFixturePreparers(
+ prepareForCcTestWithoutVndk,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ if variables.BuildFlags == nil {
+ variables.BuildFlags = make(map[string]string)
}
+ variables.BuildFlags["RELEASE_BOARD_API_LEVEL_FROZEN"] = "true"
}),
- ).RunTestWithBp(t, bp).TestContext
-
- for _, tc := range testcases {
- fooMod := ctx.ModuleForTests(tc.name, tc.variant).Module()
- outputFiles, err := fooMod.(android.OutputFileProducer).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
- }
- android.AssertPathsRelativeToTopEquals(t, "output files", tc.expectedOutputPaths, outputFiles)
- }
+ ).RunTestWithBp(t, bp)
+ testSdkVersionFlag("libfoo", "30")
+ testSdkVersionFlag("libbar", "29")
}
diff --git a/cc/compiler.go b/cc/compiler.go
index 5bed8a7..de1ae71 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -116,6 +116,10 @@
// if set to false, use -std=c++* instead of -std=gnu++*
Gnu_extensions *bool
+ // cc Build rules targeting BPF must set this to true. The correct fix is to
+ // ban targeting bpf in cc rules instead use bpf_rules. (b/323415017)
+ Bpf_target *bool
+
Yacc *YaccProperties
Lex *LexProperties
@@ -339,7 +343,7 @@
// per-target values, module type values, and per-module Blueprints properties
func (compiler *baseCompiler) compilerFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags {
tc := ctx.toolchain()
- modulePath := android.PathForModuleSrc(ctx).String()
+ modulePath := ctx.ModuleDir()
compiler.srcsBeforeGen = android.PathsForModuleSrcExcludes(ctx, compiler.Properties.Srcs, compiler.Properties.Exclude_srcs)
compiler.srcsBeforeGen = append(compiler.srcsBeforeGen, deps.GeneratedSources...)
@@ -385,7 +389,7 @@
flags.Local.YasmFlags = append(flags.Local.YasmFlags, "-I"+modulePath)
}
- if !(ctx.useSdk() || ctx.useVndk()) || ctx.Host() {
+ if !(ctx.useSdk() || ctx.InVendorOrProduct()) || ctx.Host() {
flags.SystemIncludeFlags = append(flags.SystemIncludeFlags,
"${config.CommonGlobalIncludes}",
tc.IncludeFlags())
@@ -402,10 +406,19 @@
"-isystem "+getCurrentIncludePath(ctx).Join(ctx, config.NDKTriple(tc)).String())
}
- if ctx.useVndk() {
+ if ctx.InVendorOrProduct() {
flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_VNDK__")
if ctx.inVendor() {
flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_VENDOR__")
+
+ vendorApiLevel := ctx.Config().VendorApiLevel()
+ if vendorApiLevel == "" {
+ // TODO(b/314036847): This is a fallback for UDC targets.
+ // This must be a build failure when UDC is no longer built
+ // from this source tree.
+ vendorApiLevel = ctx.Config().PlatformSdkVersion().String()
+ }
+ flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_VENDOR_API__="+vendorApiLevel)
} else if ctx.inProduct() {
flags.Global.CommonFlags = append(flags.Global.CommonFlags, "-D__ANDROID_PRODUCT__")
}
@@ -470,10 +483,15 @@
target += strconv.Itoa(android.FutureApiLevelInt)
} else {
apiLevel := nativeApiLevelOrPanic(ctx, version)
- target += apiLevel.String()
+ target += strconv.Itoa(apiLevel.FinalOrFutureInt())
}
}
+ // bpf targets don't need the default target triple. b/308826679
+ if proptools.Bool(compiler.Properties.Bpf_target) {
+ target = "--target=bpf"
+ }
+
flags.Global.CFlags = append(flags.Global.CFlags, target)
flags.Global.AsFlags = append(flags.Global.AsFlags, target)
flags.Global.LdFlags = append(flags.Global.LdFlags, target)
@@ -489,8 +507,12 @@
flags.Global.AsFlags = append(flags.Global.AsFlags, tc.Asflags())
flags.Global.CppFlags = append([]string{"${config.CommonGlobalCppflags}"}, flags.Global.CppFlags...)
+
+ // bpf targets don't need the target specific toolchain cflags. b/308826679
+ if !proptools.Bool(compiler.Properties.Bpf_target) {
+ flags.Global.CommonFlags = append(flags.Global.CommonFlags, tc.Cflags())
+ }
flags.Global.CommonFlags = append(flags.Global.CommonFlags,
- tc.Cflags(),
"${config.CommonGlobalCflags}",
fmt.Sprintf("${config.%sGlobalCflags}", hod))
@@ -512,7 +534,11 @@
flags.Global.YasmFlags = append(flags.Global.YasmFlags, tc.YasmFlags())
- flags.Global.CommonFlags = append(flags.Global.CommonFlags, tc.ToolchainCflags())
+ // bpf targets don't need the target specific toolchain cflags. b/308826679
+ if !proptools.Bool(compiler.Properties.Bpf_target) {
+ flags.Global.CommonFlags = append(flags.Global.CommonFlags, tc.ToolchainCflags())
+ }
+
cStd := parseCStd(compiler.Properties.C_std)
cppStd := parseCppStd(compiler.Properties.Cpp_std)
@@ -711,7 +737,7 @@
// Compile files listed in c.Properties.Srcs into objects
objs := compileObjs(ctx, buildFlags, "", srcs,
- android.PathsForModuleSrc(ctx, compiler.Properties.Tidy_disabled_srcs),
+ append(android.PathsForModuleSrc(ctx, compiler.Properties.Tidy_disabled_srcs), compiler.generatedSources...),
android.PathsForModuleSrc(ctx, compiler.Properties.Tidy_timeout_srcs),
pathDeps, compiler.cFlagsDeps)
diff --git a/cc/config/arm64_device.go b/cc/config/arm64_device.go
index 12722a7..82beb29 100644
--- a/cc/config/arm64_device.go
+++ b/cc/config/arm64_device.go
@@ -103,7 +103,7 @@
exportedVars.ExportStringList("Arm64Cflags", arm64Cflags)
pctx.VariableFunc("Arm64Cflags", func(ctx android.PackageVarContext) string {
flags := arm64Cflags
- if ctx.Config().PageSizeAgnostic() {
+ if ctx.Config().NoBionicPageSizeMacro() {
flags = append(flags, "-D__BIONIC_NO_PAGE_SIZE_MACRO")
}
return strings.Join(flags, " ")
diff --git a/cc/config/arm64_linux_host.go b/cc/config/arm64_linux_host.go
index 9f5124b..335ad56 100644
--- a/cc/config/arm64_linux_host.go
+++ b/cc/config/arm64_linux_host.go
@@ -46,6 +46,10 @@
"-Wl,--no-undefined-version",
}
+ linuxCrossLldflags = append(linuxCrossLdflags,
+ "-Wl,--compress-debug-sections=zstd",
+ )
+
// Embed the linker into host bionic binaries. This is needed to support host bionic,
// as the linux kernel requires that the ELF interpreter referenced by PT_INTERP be
// either an absolute path, or relative from CWD. To work around this, we extract
@@ -60,6 +64,7 @@
func init() {
exportedVars.ExportStringListStaticVariable("LinuxBionicArm64Cflags", linuxCrossCflags)
exportedVars.ExportStringListStaticVariable("LinuxBionicArm64Ldflags", linuxCrossLdflags)
+ exportedVars.ExportStringListStaticVariable("LinuxBionicArm64Lldflags", linuxCrossLldflags)
}
// toolchain config for ARM64 Linux CrossHost. Almost everything is the same as the ARM64 Android
diff --git a/cc/config/arm_device.go b/cc/config/arm_device.go
index 3d6890c..603bc6d 100644
--- a/cc/config/arm_device.go
+++ b/cc/config/arm_device.go
@@ -28,13 +28,20 @@
armCflags = []string{
"-fomit-frame-pointer",
+ // Revert this after b/322359235 is fixed
+ "-mllvm", "-enable-shrink-wrap=false",
}
- armCppflags = []string{}
+ armCppflags = []string{
+ // Revert this after b/322359235 is fixed
+ "-mllvm", "-enable-shrink-wrap=false",
+ }
armLdflags = []string{
"-Wl,--hash-style=gnu",
"-Wl,-m,armelf",
+ // Revert this after b/322359235 is fixed
+ "-Wl,-mllvm", "-Wl,-enable-shrink-wrap=false",
}
armLldflags = armLdflags
diff --git a/cc/config/arm_linux_host.go b/cc/config/arm_linux_host.go
index 525fb5d..e21c60d 100644
--- a/cc/config/arm_linux_host.go
+++ b/cc/config/arm_linux_host.go
@@ -27,16 +27,24 @@
"-march=armv7a",
}
+ linuxArmLldflags = append(linuxArmLdflags,
+ "-Wl,--compress-debug-sections=zstd",
+ )
+
linuxArm64Ldflags = []string{}
+
+ linuxArm64Lldflags = append(linuxArm64Ldflags,
+ "-Wl,--compress-debug-sections=zstd",
+ )
)
func init() {
exportedVars.ExportStringListStaticVariable("LinuxArmCflags", linuxArmCflags)
exportedVars.ExportStringListStaticVariable("LinuxArm64Cflags", linuxArm64Cflags)
exportedVars.ExportStringListStaticVariable("LinuxArmLdflags", linuxArmLdflags)
- exportedVars.ExportStringListStaticVariable("LinuxArmLldflags", linuxArmLdflags)
+ exportedVars.ExportStringListStaticVariable("LinuxArmLldflags", linuxArmLldflags)
exportedVars.ExportStringListStaticVariable("LinuxArm64Ldflags", linuxArm64Ldflags)
- exportedVars.ExportStringListStaticVariable("LinuxArm64Lldflags", linuxArm64Ldflags)
+ exportedVars.ExportStringListStaticVariable("LinuxArm64Lldflags", linuxArm64Lldflags)
exportedVars.ExportStringListStaticVariable("LinuxArmYasmFlags", []string{"-f elf32 -m arm"})
exportedVars.ExportStringListStaticVariable("LinuxArm64YasmFlags", []string{"-f elf64 -m aarch64"})
diff --git a/cc/config/bionic.go b/cc/config/bionic.go
index a1e3851..ed724f5 100644
--- a/cc/config/bionic.go
+++ b/cc/config/bionic.go
@@ -24,6 +24,7 @@
bionicCrtBeginStaticBinary, bionicCrtEndStaticBinary = []string{"crtbegin_static"}, []string{"crtend_android"}
bionicCrtBeginSharedBinary, bionicCrtEndSharedBinary = []string{"crtbegin_dynamic"}, []string{"crtend_android"}
bionicCrtBeginSharedLibrary, bionicCrtEndSharedLibrary = []string{"crtbegin_so"}, []string{"crtend_so"}
+ bionicCrtPadSegmentSharedLibrary = []string{"crt_pad_segment"}
)
func (toolchainBionic) Bionic() bool { return true }
@@ -36,9 +37,10 @@
func (toolchainBionic) AvailableLibraries() []string { return nil }
-func (toolchainBionic) CrtBeginStaticBinary() []string { return bionicCrtBeginStaticBinary }
-func (toolchainBionic) CrtBeginSharedBinary() []string { return bionicCrtBeginSharedBinary }
-func (toolchainBionic) CrtBeginSharedLibrary() []string { return bionicCrtBeginSharedLibrary }
-func (toolchainBionic) CrtEndStaticBinary() []string { return bionicCrtEndStaticBinary }
-func (toolchainBionic) CrtEndSharedBinary() []string { return bionicCrtEndSharedBinary }
-func (toolchainBionic) CrtEndSharedLibrary() []string { return bionicCrtEndSharedLibrary }
+func (toolchainBionic) CrtBeginStaticBinary() []string { return bionicCrtBeginStaticBinary }
+func (toolchainBionic) CrtBeginSharedBinary() []string { return bionicCrtBeginSharedBinary }
+func (toolchainBionic) CrtBeginSharedLibrary() []string { return bionicCrtBeginSharedLibrary }
+func (toolchainBionic) CrtEndStaticBinary() []string { return bionicCrtEndStaticBinary }
+func (toolchainBionic) CrtEndSharedBinary() []string { return bionicCrtEndSharedBinary }
+func (toolchainBionic) CrtEndSharedLibrary() []string { return bionicCrtEndSharedLibrary }
+func (toolchainBionic) CrtPadSegmentSharedLibrary() []string { return bionicCrtPadSegmentSharedLibrary }
diff --git a/cc/config/darwin_host.go b/cc/config/darwin_host.go
index 2cabdc8..b789590 100644
--- a/cc/config/darwin_host.go
+++ b/cc/config/darwin_host.go
@@ -79,7 +79,7 @@
pctx.VariableFunc("macSdkRoot", func(ctx android.PackageVarContext) string {
return getMacTools(ctx).sdkRoot
})
- pctx.StaticVariable("macMinVersion", "10.13")
+ pctx.StaticVariable("macMinVersion", "10.14")
pctx.VariableFunc("MacArPath", func(ctx android.PackageVarContext) string {
return getMacTools(ctx).arPath
})
diff --git a/cc/config/global.go b/cc/config/global.go
index 174b12c..c562614 100644
--- a/cc/config/global.go
+++ b/cc/config/global.go
@@ -16,6 +16,7 @@
import (
"runtime"
+ "slices"
"strings"
"android/soong/android"
@@ -29,87 +30,121 @@
// Flags used by lots of devices. Putting them in package static variables
// will save bytes in build.ninja so they aren't repeated for every file
commonGlobalCflags = []string{
- "-DANDROID",
- "-fmessage-length=0",
- "-W",
+ // Enable some optimization by default.
+ "-O2",
+
+ // Warnings enabled by default. Reference:
+ // https://clang.llvm.org/docs/DiagnosticsReference.html
"-Wall",
- "-Wno-unused",
+ "-Wextra",
"-Winit-self",
"-Wpointer-arith",
- "-Wunreachable-code-loop-increment",
+ "-Wunguarded-availability",
- // Make paths in deps files relative
- "-no-canonical-prefixes",
+ // Warnings treated as errors by default.
+ // See also noOverrideGlobalCflags for errors that cannot be disabled
+ // from Android.bp files.
- "-DNDEBUG",
- "-UDEBUG",
-
- "-fno-exceptions",
-
- "-O2",
- "-fdebug-default-version=5",
-
- "-fno-strict-aliasing",
-
+ // Using __DATE__/__TIME__ causes build nondeterminism.
"-Werror=date-time",
+ // Detects forgotten */& that usually cause a crash
+ "-Werror=int-conversion",
+ // Detects unterminated alignment modification pragmas, which often lead
+ // to ABI mismatch between modules and hard-to-debug crashes.
"-Werror=pragma-pack",
+ // Same as above, but detects alignment pragmas around a header
+ // inclusion.
"-Werror=pragma-pack-suspicious-include",
+ // Detects dividing an array size by itself, which is a common typo that
+ // leads to bugs.
+ "-Werror=sizeof-array-div",
+ // Detects a typo that cuts off a prefix from a string literal.
"-Werror=string-plus-int",
+ // Detects for loops that will never execute more than once (for example
+ // due to unconditional break), but have a non-empty loop increment
+ // clause. Often a mistake/bug.
"-Werror=unreachable-code-loop-increment",
- // Force deprecation warnings to be warnings for code that compiles with -Werror.
- // Making deprecated usages an error causes extreme pain when trying to deprecate anything.
+ // Warnings that should not be errors even for modules with -Werror.
+
+ // Making deprecated usages an error causes extreme pain when trying to
+ // deprecate anything.
"-Wno-error=deprecated-declarations",
+ // Warnings disabled by default.
+
+ // Designated initializer syntax is recommended by the Google C++ style
+ // and is OK to use even if not formally supported by the chosen C++
+ // version.
+ "-Wno-c99-designator",
+ // Detects uses of a GNU C extension equivalent to a limited form of
+ // constexpr. Enabling this would require replacing many constants with
+ // macros, which is not a good trade-off.
+ "-Wno-gnu-folding-constant",
+ // AIDL generated code redeclares pure virtual methods in each
+ // subsequent version of an interface, so this warning is currently
+ // infeasible to enable.
+ "-Wno-inconsistent-missing-override",
+ // Detects designated initializers that are in a different order than
+ // the fields in the initialized type, which causes the side effects
+ // of initializers to occur out of order with the source code.
+ // In practice, this warning has extremely poor signal to noise ratio,
+ // because it is triggered even for initializers with no side effects.
+ // Individual modules can still opt into it via cflags.
+ "-Wno-error=reorder-init-list",
+ "-Wno-reorder-init-list",
+ // Incompatible with the Google C++ style guidance to use 'int' for loop
+ // indices; poor signal to noise ratio.
+ "-Wno-sign-compare",
+ // Poor signal to noise ratio.
+ "-Wno-unused",
+
+ // Global preprocessor constants.
+
+ "-DANDROID",
+ "-DNDEBUG",
+ "-UDEBUG",
"-D__compiler_offsetof=__builtin_offsetof",
+ // Allows the bionic versioning.h to indirectly determine whether the
+ // option -Wunguarded-availability is on or not.
+ "-D__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__",
+
+ // -f and -g options.
// Emit address-significance table which allows linker to perform safe ICF. Clang does
// not emit the table by default on Android since NDK still uses GNU binutils.
"-faddrsig",
- // Turn on -fcommon explicitly, since Clang now defaults to -fno-common. The cleanup bug
- // tracking this is http://b/151457797.
- "-fcommon",
-
- // Help catch common 32/64-bit errors.
- "-Werror=int-conversion",
+ // Emit debugging data in a modern format (DWARF v5).
+ "-fdebug-default-version=5",
// Force clang to always output color diagnostics. Ninja will strip the ANSI
// color codes if it is not running in a terminal.
"-fcolor-diagnostics",
- // -Wno-sign-compare is incompatible with the Google C++ style guidance
- // to use 'int' for loop indices, and the signal to noise ratio is poor
- // anyway.
- "-Wno-sign-compare",
-
- // AIDL generated code redeclares pure virtual methods in each
- // subsequent version of an interface, so this is currently infeasible
- // to enable.
- "-Wno-inconsistent-missing-override",
-
- // Designated initializer syntax is recommended by the Google C++ style
- // guide and should not be a warning, at least by default.
- "-Wno-c99-designator",
-
- // Warnings from clang-12
- "-Wno-gnu-folding-constant",
-
- // http://b/145210666
- "-Wno-error=reorder-init-list",
-
- // Calls to the APIs that are newer than the min sdk version of the caller should be
- // guarded with __builtin_available.
- "-Wunguarded-availability",
- // This macro allows the bionic versioning.h to indirectly determine whether the
- // option -Wunguarded-availability is on or not.
- "-D__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__",
-
// Turn off FMA which got enabled by default in clang-r445002 (http://b/218805949)
"-ffp-contract=off",
+ // Google C++ style does not allow exceptions, turn them off by default.
+ "-fno-exceptions",
+
+ // Disable optimizations based on strict aliasing by default.
+ // The performance benefit of enabling them currently does not outweigh
+ // the risk of hard-to-reproduce bugs.
+ "-fno-strict-aliasing",
+
+ // Disable line wrapping for error messages - it interferes with
+ // displaying logs in web browsers.
+ "-fmessage-length=0",
+
// Using simple template names reduces the size of debug builds.
"-gsimple-template-names",
+
+ // Use zstd to compress debug data.
+ "-gz=zstd",
+
+ // Make paths in deps files relative.
+ "-no-canonical-prefixes",
}
commonGlobalConlyflags = []string{}
@@ -121,6 +156,7 @@
"-fdebug-default-version=4",
}
+ // Compilation flags for device code; not applied to host code.
deviceGlobalCflags = []string{
"-ffunction-sections",
"-fdata-sections",
@@ -139,9 +175,6 @@
"-Werror=format-security",
"-nostdlibinc",
- // Enable MLGO for register allocation.
- "-mllvm -regalloc-enable-advisor=release",
-
// Emit additional debug info for AutoFDO
"-fdebug-info-for-profiling",
}
@@ -156,6 +189,7 @@
"-fvisibility-inlines-hidden",
}
+ // Linking flags for device code; not applied to host binaries.
deviceGlobalLdflags = []string{
"-Wl,-z,noexecstack",
"-Wl,-z,relro",
@@ -169,11 +203,11 @@
"-Wl,--exclude-libs,libgcc_stripped.a",
"-Wl,--exclude-libs,libunwind_llvm.a",
"-Wl,--exclude-libs,libunwind.a",
- // Enable MLGO for register allocation.
- "-Wl,-mllvm,-regalloc-enable-advisor=release",
}
- deviceGlobalLldflags = append(deviceGlobalLdflags, commonGlobalLldflags...)
+ deviceGlobalLldflags = append(append(deviceGlobalLdflags, commonGlobalLldflags...),
+ "-Wl,--compress-debug-sections=zstd",
+ )
hostGlobalCflags = []string{}
@@ -184,8 +218,6 @@
hostGlobalLldflags = commonGlobalLldflags
commonGlobalCppflags = []string{
- "-Wsign-promo",
-
// -Wimplicit-fallthrough is not enabled by -Wall.
"-Wimplicit-fallthrough",
@@ -198,6 +230,14 @@
// These flags are appended after the module's cflags, so they cannot be
// overridden from Android.bp files.
+ //
+ // NOTE: if you need to disable a warning to unblock a compiler upgrade
+ // and it is only triggered by third party code, add it to
+ // extraExternalCflags (if possible) or noOverrideExternalGlobalCflags
+ // (if the former doesn't work). If the new warning also occurs in first
+ // party code, try adding it to commonGlobalCflags first. Adding it here
+ // should be the last resort, because it prevents all code in Android from
+ // opting into the warning.
noOverrideGlobalCflags = []string{
"-Werror=bool-operation",
"-Werror=format-insufficient-args",
@@ -213,8 +253,17 @@
// http://b/161386391 for -Wno-pointer-to-int-cast
"-Wno-pointer-to-int-cast",
"-Werror=fortify-source",
+ // http://b/315246135 temporarily disabled
+ "-Wno-error=unused-variable",
+ // http://b/315250603 temporarily disabled
+ "-Wno-error=format",
+ // Disabled because it produces many false positives. http://b/323050926
+ "-Wno-missing-field-initializers",
+ // http://b/323050889
+ "-Wno-packed-non-pod",
"-Werror=address-of-temporary",
+ "-Werror=incompatible-function-pointer-types",
"-Werror=null-dereference",
"-Werror=return-type",
@@ -231,7 +280,8 @@
"-Wno-range-loop-construct", // http://b/153747076
"-Wno-zero-as-null-pointer-constant", // http://b/68236239
"-Wno-deprecated-anon-enum-enum-conversion", // http://b/153746485
- "-Wno-pessimizing-move", // http://b/154270751
+ "-Wno-deprecated-enum-enum-conversion",
+ "-Wno-pessimizing-move", // http://b/154270751
// New warnings to be fixed after clang-r399163
"-Wno-non-c-typedef-for-linkage", // http://b/161304145
// New warnings to be fixed after clang-r428724
@@ -245,37 +295,20 @@
// New warnings to be fixed after clang-r475365
"-Wno-error=single-bit-bitfield-constant-conversion", // http://b/243965903
"-Wno-error=enum-constexpr-conversion", // http://b/243964282
+
+ // Irrelevant on Android because _we_ don't use exceptions, but causes
+ // lots of build noise because libcxx/libcxxabi do. This can probably
+ // go away when we're on a new enough libc++, but has to be global
+ // until then because it causes warnings in the _callers_, not the
+ // project itself.
+ "-Wno-deprecated-dynamic-exception-spec",
}
noOverride64GlobalCflags = []string{}
- // Similar to noOverrideGlobalCflags, but applies only to third-party code
- // (anything for which IsThirdPartyPath() in build/soong/android/paths.go
- // returns true - includes external/, most of vendor/ and most of hardware/)
- noOverrideExternalGlobalCflags = []string{
- // http://b/191699019
- "-Wno-format-insufficient-args",
- // http://b/296321145
- // Indicates potential memory or stack corruption, so should be changed
- // to a hard error. Currently triggered by some vendor code.
- "-Wno-incompatible-function-pointer-types",
- // http://b/296321508
- // Introduced in response to a critical security vulnerability and
- // should be a hard error - it requires only whitespace changes to fix.
- "-Wno-misleading-indentation",
- // Triggered by old LLVM code in external/llvm. Likely not worth
- // enabling since it's a cosmetic issue.
- "-Wno-bitwise-instead-of-logical",
-
- "-Wno-unused-but-set-variable",
- "-Wno-unused-but-set-parameter",
- "-Wno-unqualified-std-cast-call",
- "-Wno-array-parameter",
- "-Wno-gnu-offsetof-extensions",
- }
-
- // Extra cflags for external third-party projects to disable warnings that
- // are infeasible to fix in all the external projects and their upstream repos.
+ // Extra cflags applied to third-party code (anything for which
+ // IsThirdPartyPath() in build/soong/android/paths.go returns true;
+ // includes external/, most of vendor/ and most of hardware/)
extraExternalCflags = []string{
"-Wno-enum-compare",
"-Wno-enum-compare-switch",
@@ -303,26 +336,60 @@
// http://b/239661264
"-Wno-deprecated-non-prototype",
+
+ "-Wno-unused",
+ "-Wno-deprecated",
+ }
+
+ // Similar to noOverrideGlobalCflags, but applies only to third-party code
+ // (see extraExternalCflags).
+ // This section can unblock compiler upgrades when a third party module that
+ // enables -Werror and some group of warnings explicitly triggers newly
+ // added warnings.
+ noOverrideExternalGlobalCflags = []string{
+ // http://b/151457797
+ "-fcommon",
+ // http://b/191699019
+ "-Wno-format-insufficient-args",
+ // http://b/296321508
+ // Introduced in response to a critical security vulnerability and
+ // should be a hard error - it requires only whitespace changes to fix.
+ "-Wno-misleading-indentation",
+ // Triggered by old LLVM code in external/llvm. Likely not worth
+ // enabling since it's a cosmetic issue.
+ "-Wno-bitwise-instead-of-logical",
+
+ "-Wno-unused",
+ "-Wno-unused-parameter",
+ "-Wno-unused-but-set-parameter",
+ "-Wno-unqualified-std-cast-call",
+ "-Wno-array-parameter",
+ "-Wno-gnu-offsetof-extensions",
+ // TODO: Enable this warning http://b/315245071
+ "-Wno-fortify-source",
+ "-Wno-tautological-negation-compare",
+ "-Wno-tautological-undefined-compare",
}
llvmNextExtraCommonGlobalCflags = []string{
// Do not report warnings when testing with the top of trunk LLVM.
- "-Wno-error",
+ "-Wno-everything",
}
+ // Flags that must not appear in any command line.
IllegalFlags = []string{
"-w",
}
CStdVersion = "gnu17"
- CppStdVersion = "gnu++17"
+ CppStdVersion = "gnu++20"
ExperimentalCStdVersion = "gnu2x"
- ExperimentalCppStdVersion = "gnu++2a"
+ ExperimentalCppStdVersion = "gnu++2b"
// prebuilts/clang default settings.
ClangDefaultBase = "prebuilts/clang/host"
- ClangDefaultVersion = "clang-r498229b"
- ClangDefaultShortVersion = "17"
+ ClangDefaultVersion = "clang-r510928"
+ ClangDefaultShortVersion = "18"
// Directories with warnings from Android.bp files.
WarningAllowedProjects = []string{
@@ -336,12 +403,6 @@
VisibilityDefaultFlag = "-fvisibility=default"
)
-// BazelCcToolchainVars generates bzl file content containing variables for
-// Bazel's cc_toolchain configuration.
-func BazelCcToolchainVars(config android.Config) string {
- return android.BazelToolchainVars(config, exportedVars)
-}
-
func ExportStringList(name string, value []string) {
exportedVars.ExportStringList(name, value)
}
@@ -364,7 +425,7 @@
exportedVars.ExportStringList("CommonGlobalCflags", commonGlobalCflags)
pctx.VariableFunc("CommonGlobalCflags", func(ctx android.PackageVarContext) string {
- flags := commonGlobalCflags
+ flags := slices.Clone(commonGlobalCflags)
// http://b/131390872
// Automatically initialize any uninitialized stack variables.
@@ -422,6 +483,7 @@
flags := noOverrideGlobalCflags
if ctx.Config().IsEnvTrue("LLVM_NEXT") {
flags = append(noOverrideGlobalCflags, llvmNextExtraCommonGlobalCflags...)
+ IllegalFlags = []string{} // Don't fail build while testing a new compiler.
}
return strings.Join(flags, " ")
})
diff --git a/cc/config/riscv64_device.go b/cc/config/riscv64_device.go
index 40919c0..deb922b 100644
--- a/cc/config/riscv64_device.go
+++ b/cc/config/riscv64_device.go
@@ -25,20 +25,31 @@
riscv64Cflags = []string{
// Help catch common 32/64-bit errors.
"-Werror=implicit-function-declaration",
- "-fno-emulated-tls",
- "-march=rv64gc_zba_zbb_zbs",
+ "-march=rv64gcv_zba_zbb_zbs",
+ // Equivalent to "-munaligned-access", but our clang doesn't have that yet.
+ "-Xclang -target-feature -Xclang +unaligned-scalar-mem",
+ "-Xclang -target-feature -Xclang +unaligned-vector-mem",
+ // Until https://gitlab.com/qemu-project/qemu/-/issues/1976 is fixed...
+ "-mno-implicit-float",
+ // (https://github.com/google/android-riscv64/issues/124)
+ "-mllvm -jump-is-expensive=false",
}
riscv64ArchVariantCflags = map[string][]string{}
riscv64Ldflags = []string{
"-Wl,--hash-style=gnu",
- "-march=rv64gc_zba_zbb_zbs",
+ "-march=rv64gcv_zba_zbb_zbs",
+ // Equivalent to "-munaligned-access", but our clang doesn't have that yet.
+ "-Xclang -target-feature -Xclang +unaligned-scalar-mem",
+ "-Xclang -target-feature -Xclang +unaligned-vector-mem",
+ // We should change the default for this in clang, but for now...
+ // (https://github.com/google/android-riscv64/issues/124)
+ "-Wl,-mllvm -Wl,-jump-is-expensive=false",
}
riscv64Lldflags = append(riscv64Ldflags,
"-Wl,-z,max-page-size=4096",
- "-Wl,-plugin-opt,-emulated-tls=0",
)
riscv64Cppflags = []string{}
diff --git a/cc/config/tidy.go b/cc/config/tidy.go
index efa4549..b40557a 100644
--- a/cc/config/tidy.go
+++ b/cc/config/tidy.go
@@ -16,7 +16,6 @@
import (
"android/soong/android"
- "regexp"
"strings"
)
@@ -281,11 +280,3 @@
}
return flags
}
-
-var (
- removedCFlags = regexp.MustCompile(" -fsanitize=[^ ]*memtag-[^ ]* ")
-)
-
-func TidyReduceCFlags(flags string) string {
- return removedCFlags.ReplaceAllString(flags, " ")
-}
diff --git a/cc/config/toolchain.go b/cc/config/toolchain.go
index 62f75d1..71e98fe 100644
--- a/cc/config/toolchain.go
+++ b/cc/config/toolchain.go
@@ -100,6 +100,7 @@
CrtEndStaticBinary() []string
CrtEndSharedBinary() []string
CrtEndSharedLibrary() []string
+ CrtPadSegmentSharedLibrary() []string
// DefaultSharedLibraries returns the list of shared libraries that will be added to all
// targets unless they explicitly specify system_shared_libs.
@@ -155,12 +156,13 @@
type toolchainNoCrt struct{}
-func (toolchainNoCrt) CrtBeginStaticBinary() []string { return nil }
-func (toolchainNoCrt) CrtBeginSharedBinary() []string { return nil }
-func (toolchainNoCrt) CrtBeginSharedLibrary() []string { return nil }
-func (toolchainNoCrt) CrtEndStaticBinary() []string { return nil }
-func (toolchainNoCrt) CrtEndSharedBinary() []string { return nil }
-func (toolchainNoCrt) CrtEndSharedLibrary() []string { return nil }
+func (toolchainNoCrt) CrtBeginStaticBinary() []string { return nil }
+func (toolchainNoCrt) CrtBeginSharedBinary() []string { return nil }
+func (toolchainNoCrt) CrtBeginSharedLibrary() []string { return nil }
+func (toolchainNoCrt) CrtEndStaticBinary() []string { return nil }
+func (toolchainNoCrt) CrtEndSharedBinary() []string { return nil }
+func (toolchainNoCrt) CrtEndSharedLibrary() []string { return nil }
+func (toolchainNoCrt) CrtPadSegmentSharedLibrary() []string { return nil }
func (toolchainBase) DefaultSharedLibraries() []string {
return nil
diff --git a/cc/config/x86_64_device.go b/cc/config/x86_64_device.go
index 9f093bb..b97d511 100644
--- a/cc/config/x86_64_device.go
+++ b/cc/config/x86_64_device.go
@@ -33,6 +33,8 @@
"-Wl,--hash-style=gnu",
}
+ X86_64Lldflags = x86_64Ldflags
+
x86_64ArchVariantCflags = map[string][]string{
"": []string{
"-march=x86-64",
@@ -47,6 +49,11 @@
"goldmont-plus": []string{
"-march=goldmont-plus",
},
+ "goldmont-without-sha-xsaves": []string{
+ "-march=goldmont",
+ "-mno-sha",
+ "-mno-xsaves",
+ },
"haswell": []string{
"-march=core-avx2",
},
@@ -94,10 +101,23 @@
exportedVars.ExportStringListStaticVariable("X86_64ToolchainLdflags", []string{"-m64"})
exportedVars.ExportStringListStaticVariable("X86_64Ldflags", x86_64Ldflags)
- exportedVars.ExportStringListStaticVariable("X86_64Lldflags", x86_64Ldflags)
+ exportedVars.ExportStringList("X86_64Lldflags", X86_64Lldflags)
+ pctx.VariableFunc("X86_64Lldflags", func(ctx android.PackageVarContext) string {
+ maxPageSizeFlag := "-Wl,-z,max-page-size=" + ctx.Config().MaxPageSizeSupported()
+ flags := append(X86_64Lldflags, maxPageSizeFlag)
+ return strings.Join(flags, " ")
+ })
// Clang cflags
- exportedVars.ExportStringListStaticVariable("X86_64Cflags", x86_64Cflags)
+ exportedVars.ExportStringList("X86_64Cflags", x86_64Cflags)
+ pctx.VariableFunc("X86_64Cflags", func(ctx android.PackageVarContext) string {
+ flags := x86_64Cflags
+ if ctx.Config().NoBionicPageSizeMacro() {
+ flags = append(flags, "-D__BIONIC_NO_PAGE_SIZE_MACRO")
+ }
+ return strings.Join(flags, " ")
+ })
+
exportedVars.ExportStringListStaticVariable("X86_64Cppflags", x86_64Cppflags)
// Yasm flags
diff --git a/cc/config/x86_device.go b/cc/config/x86_device.go
index c826d3c..2faa670 100644
--- a/cc/config/x86_device.go
+++ b/cc/config/x86_device.go
@@ -56,6 +56,11 @@
"goldmont-plus": []string{
"-march=goldmont-plus",
},
+ "goldmont-without-sha-xsaves": []string{
+ "-march=goldmont",
+ "-mno-sha",
+ "-mno-xsaves",
+ },
"haswell": []string{
"-march=core-avx2",
},
diff --git a/cc/config/x86_linux_bionic_host.go b/cc/config/x86_linux_bionic_host.go
index e006471..f80be99 100644
--- a/cc/config/x86_linux_bionic_host.go
+++ b/cc/config/x86_linux_bionic_host.go
@@ -53,6 +53,10 @@
"--gcc-toolchain=${LinuxBionicGccRoot}",
}
+ linuxBionicLldflags = append(linuxBionicLdflags,
+ "-Wl,--compress-debug-sections=zstd",
+ )
+
// Embed the linker into host bionic binaries. This is needed to support host bionic,
// as the linux kernel requires that the ELF interpreter referenced by PT_INTERP be
// either an absolute path, or relative from CWD. To work around this, we extract
@@ -71,7 +75,7 @@
func init() {
exportedVars.ExportStringListStaticVariable("LinuxBionicCflags", linuxBionicCflags)
exportedVars.ExportStringListStaticVariable("LinuxBionicLdflags", linuxBionicLdflags)
- exportedVars.ExportStringListStaticVariable("LinuxBionicLldflags", linuxBionicLdflags)
+ exportedVars.ExportStringListStaticVariable("LinuxBionicLldflags", linuxBionicLldflags)
// Use the device gcc toolchain for now
exportedVars.ExportStringStaticVariable("LinuxBionicGccVersion", x86_64GccVersion)
diff --git a/cc/config/x86_linux_host.go b/cc/config/x86_linux_host.go
index 93aa82e..f497bf9 100644
--- a/cc/config/x86_linux_host.go
+++ b/cc/config/x86_linux_host.go
@@ -59,6 +59,10 @@
"--gcc-toolchain=${LinuxGccRoot}",
}
+ linuxLldflags = append(linuxLdflags,
+ "-Wl,--compress-debug-sections=zstd",
+ )
+
linuxGlibcLdflags = []string{
"--sysroot ${LinuxGccRoot}/sysroot",
}
@@ -138,7 +142,7 @@
exportedVars.ExportStringListStaticVariable("LinuxCflags", linuxCflags)
exportedVars.ExportStringListStaticVariable("LinuxLdflags", linuxLdflags)
- exportedVars.ExportStringListStaticVariable("LinuxLldflags", linuxLdflags)
+ exportedVars.ExportStringListStaticVariable("LinuxLldflags", linuxLldflags)
exportedVars.ExportStringListStaticVariable("LinuxGlibcCflags", linuxGlibcCflags)
exportedVars.ExportStringListStaticVariable("LinuxGlibcLdflags", linuxGlibcLdflags)
exportedVars.ExportStringListStaticVariable("LinuxGlibcLldflags", linuxGlibcLdflags)
@@ -324,12 +328,13 @@
func (toolchainMusl) Musl() bool { return true }
-func (toolchainMusl) CrtBeginStaticBinary() []string { return muslCrtBeginStaticBinary }
-func (toolchainMusl) CrtBeginSharedBinary() []string { return muslCrtBeginSharedBinary }
-func (toolchainMusl) CrtBeginSharedLibrary() []string { return muslCrtBeginSharedLibrary }
-func (toolchainMusl) CrtEndStaticBinary() []string { return muslCrtEndStaticBinary }
-func (toolchainMusl) CrtEndSharedBinary() []string { return muslCrtEndSharedBinary }
-func (toolchainMusl) CrtEndSharedLibrary() []string { return muslCrtEndSharedLibrary }
+func (toolchainMusl) CrtBeginStaticBinary() []string { return muslCrtBeginStaticBinary }
+func (toolchainMusl) CrtBeginSharedBinary() []string { return muslCrtBeginSharedBinary }
+func (toolchainMusl) CrtBeginSharedLibrary() []string { return muslCrtBeginSharedLibrary }
+func (toolchainMusl) CrtEndStaticBinary() []string { return muslCrtEndStaticBinary }
+func (toolchainMusl) CrtEndSharedBinary() []string { return muslCrtEndSharedBinary }
+func (toolchainMusl) CrtEndSharedLibrary() []string { return muslCrtEndSharedLibrary }
+func (toolchainMusl) CrtPadSegmentSharedLibrary() []string { return nil }
func (toolchainMusl) DefaultSharedLibraries() []string { return MuslDefaultSharedLibraries }
diff --git a/cc/coverage.go b/cc/coverage.go
index cbd8a6f..43f5e07 100644
--- a/cc/coverage.go
+++ b/cc/coverage.go
@@ -22,6 +22,29 @@
"android/soong/android"
)
+var (
+ clangCoverageHostLdFlags = []string{
+ "-Wl,--no-as-needed",
+ "-Wl,--wrap,open",
+ }
+ clangContinuousCoverageFlags = []string{
+ "-mllvm",
+ "-runtime-counter-relocation",
+ }
+ clangCoverageCFlags = []string{
+ "-Wno-frame-larger-than=",
+ }
+ clangCoverageCommonFlags = []string{
+ "-fcoverage-mapping",
+ "-Wno-pass-failed",
+ "-D__ANDROID_CLANG_COVERAGE__",
+ }
+ clangCoverageHWASanFlags = []string{
+ "-mllvm",
+ "-hwasan-globals=0",
+ }
+)
+
const profileInstrFlag = "-fprofile-instr-generate=/data/misc/trace/clang-%p-%m.profraw"
type CoverageProperties struct {
@@ -102,19 +125,19 @@
// flags that the module may use.
flags.Local.CFlags = append(flags.Local.CFlags, "-Wno-frame-larger-than=", "-O0")
} else if clangCoverage {
- flags.Local.CommonFlags = append(flags.Local.CommonFlags, profileInstrFlag,
- "-fcoverage-mapping", "-Wno-pass-failed", "-D__ANDROID_CLANG_COVERAGE__")
+ flags.Local.CommonFlags = append(flags.Local.CommonFlags, profileInstrFlag)
+ flags.Local.CommonFlags = append(flags.Local.CommonFlags, clangCoverageCommonFlags...)
// Override -Wframe-larger-than. We can expect frame size increase after
// coverage instrumentation.
- flags.Local.CFlags = append(flags.Local.CFlags, "-Wno-frame-larger-than=")
+ flags.Local.CFlags = append(flags.Local.CFlags, clangCoverageCFlags...)
if EnableContinuousCoverage(ctx) {
- flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-mllvm", "-runtime-counter-relocation")
+ flags.Local.CommonFlags = append(flags.Local.CommonFlags, clangContinuousCoverageFlags...)
}
// http://b/248022906, http://b/247941801 enabling coverage and hwasan-globals
// instrumentation together causes duplicate-symbol errors for __llvm_profile_filename.
if c, ok := ctx.Module().(*Module); ok && c.sanitize.isSanitizerEnabled(Hwasan) {
- flags.Local.CommonFlags = append(flags.Local.CommonFlags, "-mllvm", "-hwasan-globals=0")
+ flags.Local.CommonFlags = append(flags.Local.CommonFlags, clangCoverageHWASanFlags...)
}
}
}
@@ -223,7 +246,7 @@
type UseCoverage interface {
android.Module
- IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool
+ IsNativeCoverageNeeded(ctx android.IncomingTransitionContext) bool
}
// Coverage is an interface for non-CC modules to implement to be mutated for coverage
@@ -235,43 +258,86 @@
EnableCoverageIfNeeded()
}
-func coverageMutator(mctx android.BottomUpMutatorContext) {
- if c, ok := mctx.Module().(*Module); ok && c.coverage != nil {
- needCoverageVariant := c.coverage.Properties.NeedCoverageVariant
- needCoverageBuild := c.coverage.Properties.NeedCoverageBuild
- if needCoverageVariant {
- m := mctx.CreateVariations("", "cov")
+type coverageTransitionMutator struct{}
- // Setup the non-coverage version and set HideFromMake and
- // PreventInstall to true.
- m[0].(*Module).coverage.Properties.CoverageEnabled = false
- m[0].(*Module).coverage.Properties.IsCoverageVariant = false
- m[0].(*Module).Properties.HideFromMake = true
- m[0].(*Module).Properties.PreventInstall = true
+var _ android.TransitionMutator = (*coverageTransitionMutator)(nil)
- // The coverage-enabled version inherits HideFromMake,
- // PreventInstall from the original module.
- m[1].(*Module).coverage.Properties.CoverageEnabled = needCoverageBuild
- m[1].(*Module).coverage.Properties.IsCoverageVariant = true
+func (c coverageTransitionMutator) Split(ctx android.BaseModuleContext) []string {
+ if c, ok := ctx.Module().(*Module); ok && c.coverage != nil {
+ if c.coverage.Properties.NeedCoverageVariant {
+ return []string{"", "cov"}
}
- } else if cov, ok := mctx.Module().(Coverage); ok && cov.IsNativeCoverageNeeded(mctx) {
+ } else if cov, ok := ctx.Module().(Coverage); ok && cov.IsNativeCoverageNeeded(ctx) {
// APEX and Rust modules fall here
// Note: variant "" is also created because an APEX can be depended on by another
// module which are split into "" and "cov" variants. e.g. when cc_test refers
// to an APEX via 'data' property.
- m := mctx.CreateVariations("", "cov")
- m[0].(Coverage).MarkAsCoverageVariant(false)
- m[0].(Coverage).SetPreventInstall()
- m[0].(Coverage).HideFromMake()
-
- m[1].(Coverage).MarkAsCoverageVariant(true)
- m[1].(Coverage).EnableCoverageIfNeeded()
- } else if cov, ok := mctx.Module().(UseCoverage); ok && cov.IsNativeCoverageNeeded(mctx) {
+ return []string{"", "cov"}
+ } else if cov, ok := ctx.Module().(UseCoverage); ok && cov.IsNativeCoverageNeeded(ctx) {
// Module itself doesn't have to have "cov" variant, but it should use "cov" variants of
// deps.
- mctx.CreateVariations("cov")
- mctx.AliasVariation("cov")
+ return []string{"cov"}
+ }
+
+ return []string{""}
+}
+
+func (c coverageTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ return sourceVariation
+}
+
+func (c coverageTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
+ if c, ok := ctx.Module().(*Module); ok && c.coverage != nil {
+ if !c.coverage.Properties.NeedCoverageVariant {
+ return ""
+ }
+ } else if cov, ok := ctx.Module().(Coverage); ok {
+ if !cov.IsNativeCoverageNeeded(ctx) {
+ return ""
+ }
+ } else if cov, ok := ctx.Module().(UseCoverage); ok && cov.IsNativeCoverageNeeded(ctx) {
+ // Module only has a "cov" variation, so all incoming variations should use "cov".
+ return "cov"
+ } else {
+ return ""
+ }
+
+ return incomingVariation
+}
+
+func (c coverageTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
+ if c, ok := ctx.Module().(*Module); ok && c.coverage != nil {
+ if variation == "" && c.coverage.Properties.NeedCoverageVariant {
+ // Setup the non-coverage version and set HideFromMake and
+ // PreventInstall to true.
+ c.coverage.Properties.CoverageEnabled = false
+ c.coverage.Properties.IsCoverageVariant = false
+ c.Properties.HideFromMake = true
+ c.Properties.PreventInstall = true
+ } else if variation == "cov" {
+ // The coverage-enabled version inherits HideFromMake,
+ // PreventInstall from the original module.
+ c.coverage.Properties.CoverageEnabled = c.coverage.Properties.NeedCoverageBuild
+ c.coverage.Properties.IsCoverageVariant = true
+ }
+ } else if cov, ok := ctx.Module().(Coverage); ok && cov.IsNativeCoverageNeeded(ctx) {
+ // APEX and Rust modules fall here
+
+ // Note: variant "" is also created because an APEX can be depended on by another
+ // module which are split into "" and "cov" variants. e.g. when cc_test refers
+ // to an APEX via 'data' property.
+ if variation == "" {
+ cov.MarkAsCoverageVariant(false)
+ cov.SetPreventInstall()
+ cov.HideFromMake()
+ } else if variation == "cov" {
+ cov.MarkAsCoverageVariant(true)
+ cov.EnableCoverageIfNeeded()
+ }
+ } else if cov, ok := ctx.Module().(UseCoverage); ok && cov.IsNativeCoverageNeeded(ctx) {
+ // Module itself doesn't have to have "cov" variant, but it should use "cov" variants of
+ // deps.
}
}
diff --git a/cc/fdo_profile.go b/cc/fdo_profile.go
index 7fbe719..0893da5 100644
--- a/cc/fdo_profile.go
+++ b/cc/fdo_profile.go
@@ -16,7 +16,6 @@
import (
"android/soong/android"
-
"github.com/google/blueprint"
)
@@ -25,7 +24,7 @@
}
func RegisterFdoProfileBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("fdo_profile", fdoProfileFactory)
+ ctx.RegisterModuleType("fdo_profile", FdoProfileFactory)
}
type fdoProfile struct {
@@ -44,7 +43,7 @@
}
// FdoProfileProvider is used to provide path to an fdo profile
-var FdoProfileProvider = blueprint.NewMutatorProvider(FdoProfileInfo{}, "fdo_profile")
+var FdoProfileProvider = blueprint.NewMutatorProvider[FdoProfileInfo]("fdo_profile")
// FdoProfileMutatorInterface is the interface implemented by fdo_profile module type
// module types that can depend on an fdo_profile module
@@ -63,7 +62,7 @@
func (fp *fdoProfile) fdoProfileMutator(ctx android.BottomUpMutatorContext) {
if fp.properties.Profile != nil {
path := android.PathForModuleSrc(ctx, *fp.properties.Profile)
- ctx.SetProvider(FdoProfileProvider, FdoProfileInfo{
+ android.SetProvider(ctx, FdoProfileProvider, FdoProfileInfo{
Path: path,
})
}
@@ -77,7 +76,7 @@
}
}
-func fdoProfileFactory() android.Module {
+func FdoProfileFactory() android.Module {
m := &fdoProfile{}
m.AddProperties(&m.properties)
android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibBoth)
diff --git a/cc/fuzz.go b/cc/fuzz.go
index 227fe8b..2436f33 100644
--- a/cc/fuzz.go
+++ b/cc/fuzz.go
@@ -96,6 +96,7 @@
// your device, or $ANDROID_PRODUCT_OUT/data/fuzz in your build tree.
func LibFuzzFactory() android.Module {
module := NewFuzzer(android.HostAndDeviceSupported)
+ module.testModule = true
return module.Init()
}
@@ -105,6 +106,7 @@
fuzzPackagedModule fuzz.FuzzPackagedModule
installedSharedDeps []string
sharedLibraries android.RuleBuilderInstalls
+ data []android.DataPath
}
func (fuzz *fuzzBinary) fuzzBinary() bool {
@@ -142,25 +144,35 @@
}
func (fuzz *fuzzBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
+ subdir := "lib"
+ if ctx.inVendor() {
+ subdir = "lib/vendor"
+ }
+
flags = fuzz.binaryDecorator.linkerFlags(ctx, flags)
// RunPaths on devices isn't instantiated by the base linker. `../lib` for
// installed fuzz targets (both host and device), and `./lib` for fuzz
// target packages.
- flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/lib`)
+ flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/`+subdir)
// When running on device, fuzz targets with vendor: true set will be in
// fuzzer_name/vendor/fuzzer_name (note the extra 'vendor' and thus need to
// link with libraries in ../../lib/. Non-vendor binaries only need to look
// one level up, in ../lib/.
if ctx.inVendor() {
- flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../../lib`)
+ flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../../`+subdir)
} else {
- flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../lib`)
+ flags.Local.LdFlags = append(flags.Local.LdFlags, `-Wl,-rpath,\$$ORIGIN/../`+subdir)
}
return flags
}
+func (fuzz *fuzzBinary) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ fuzz.binaryDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+ moduleInfoJSON.Class = []string{"EXECUTABLES"}
+}
+
// IsValidSharedDependency takes a module and determines if it is a unique shared library
// that should be installed in the fuzz target output directories. This function
// returns true, unless:
@@ -214,75 +226,91 @@
}
func SharedLibraryInstallLocation(
- libraryBase string, isHost bool, fuzzDir string, archString string) string {
+ libraryBase string, isHost bool, isVendor bool, fuzzDir string, archString string) string {
installLocation := "$(PRODUCT_OUT)/data"
if isHost {
installLocation = "$(HOST_OUT)"
}
+ subdir := "lib"
+ if isVendor {
+ subdir = "lib/vendor"
+ }
installLocation = filepath.Join(
- installLocation, fuzzDir, archString, "lib", libraryBase)
+ installLocation, fuzzDir, archString, subdir, libraryBase)
return installLocation
}
// Get the device-only shared library symbols install directory.
-func SharedLibrarySymbolsInstallLocation(libraryBase string, fuzzDir string, archString string) string {
- return filepath.Join("$(PRODUCT_OUT)/symbols/data/", fuzzDir, archString, "/lib/", libraryBase)
+func SharedLibrarySymbolsInstallLocation(libraryBase string, isVendor bool, fuzzDir string, archString string) string {
+ subdir := "lib"
+ if isVendor {
+ subdir = "lib/vendor"
+ }
+ return filepath.Join("$(PRODUCT_OUT)/symbols/data/", fuzzDir, archString, subdir, libraryBase)
}
func (fuzzBin *fuzzBinary) install(ctx ModuleContext, file android.Path) {
- installBase := "fuzz"
-
- fuzzBin.binaryDecorator.baseInstaller.dir = filepath.Join(
- installBase, ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
- fuzzBin.binaryDecorator.baseInstaller.dir64 = filepath.Join(
- installBase, ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
- fuzzBin.binaryDecorator.baseInstaller.install(ctx, file)
-
fuzzBin.fuzzPackagedModule = PackageFuzzModule(ctx, fuzzBin.fuzzPackagedModule, pctx)
+ installBase := "fuzz"
+
// Grab the list of required shared libraries.
fuzzBin.sharedLibraries, _ = CollectAllSharedDependencies(ctx)
+ // TODO: does not mirror Android linkernamespaces
+ // the logic here has special cases for vendor, but it would need more work to
+ // work in arbitrary partitions, so just surface errors early for a few cases
+ //
+ // Even without these, there are certain situations across linkernamespaces
+ // that this won't support. For instance, you might have:
+ //
+ // my_fuzzer (vendor) -> libbinder_ndk (core) -> libbinder (vendor)
+ //
+ // This dependency chain wouldn't be possible to express in the current
+ // logic because all the deps currently match the variant of the source
+ // module.
+
for _, ruleBuilderInstall := range fuzzBin.sharedLibraries {
install := ruleBuilderInstall.To
fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
SharedLibraryInstallLocation(
- install, ctx.Host(), installBase, ctx.Arch().ArchType.String()))
+ install, ctx.Host(), ctx.inVendor(), installBase, ctx.Arch().ArchType.String()))
// Also add the dependency on the shared library symbols dir.
if !ctx.Host() {
fuzzBin.installedSharedDeps = append(fuzzBin.installedSharedDeps,
- SharedLibrarySymbolsInstallLocation(install, installBase, ctx.Arch().ArchType.String()))
+ SharedLibrarySymbolsInstallLocation(install, ctx.inVendor(), installBase, ctx.Arch().ArchType.String()))
}
}
+
+ for _, d := range fuzzBin.fuzzPackagedModule.Corpus {
+ fuzzBin.data = append(fuzzBin.data, android.DataPath{SrcPath: d, RelativeInstallPath: "corpus", WithoutRel: true})
+ }
+
+ for _, d := range fuzzBin.fuzzPackagedModule.Data {
+ fuzzBin.data = append(fuzzBin.data, android.DataPath{SrcPath: d, RelativeInstallPath: "data"})
+ }
+
+ if d := fuzzBin.fuzzPackagedModule.Dictionary; d != nil {
+ fuzzBin.data = append(fuzzBin.data, android.DataPath{SrcPath: d, WithoutRel: true})
+ }
+
+ if d := fuzzBin.fuzzPackagedModule.Config; d != nil {
+ fuzzBin.data = append(fuzzBin.data, android.DataPath{SrcPath: d, WithoutRel: true})
+ }
+
+ fuzzBin.binaryDecorator.baseInstaller.dir = filepath.Join(
+ installBase, ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
+ fuzzBin.binaryDecorator.baseInstaller.dir64 = filepath.Join(
+ installBase, ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
+ fuzzBin.binaryDecorator.baseInstaller.installTestData(ctx, fuzzBin.data)
+ fuzzBin.binaryDecorator.baseInstaller.install(ctx, file)
}
func PackageFuzzModule(ctx android.ModuleContext, fuzzPackagedModule fuzz.FuzzPackagedModule, pctx android.PackageContext) fuzz.FuzzPackagedModule {
fuzzPackagedModule.Corpus = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Corpus)
- intermediateDir := android.PathForModuleOut(ctx, "corpus")
-
- // Create one rule per file to avoid MAX_ARG_STRLEN hardlimit.
- for _, entry := range fuzzPackagedModule.Corpus {
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Output: intermediateDir.Join(ctx, entry.Base()),
- Input: entry,
- })
- }
- fuzzPackagedModule.CorpusIntermediateDir = intermediateDir
fuzzPackagedModule.Data = android.PathsForModuleSrc(ctx, fuzzPackagedModule.FuzzProperties.Data)
- intermediateDir = android.PathForModuleOut(ctx, "data")
-
- // Create one rule per file to avoid MAX_ARG_STRLEN hardlimit.
- for _, entry := range fuzzPackagedModule.Data {
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Output: intermediateDir.Join(ctx, entry.Rel()),
- Input: entry,
- })
- }
- fuzzPackagedModule.DataIntermediateDir = intermediateDir
if fuzzPackagedModule.FuzzProperties.Dictionary != nil {
fuzzPackagedModule.Dictionary = android.PathForModuleSrc(ctx, *fuzzPackagedModule.FuzzProperties.Dictionary)
@@ -302,7 +330,7 @@
}
func NewFuzzer(hod android.HostOrDeviceSupported) *Module {
- module, binary := newBinary(hod, false)
+ module, binary := newBinary(hod)
baseInstallerPath := "fuzz"
binary.baseInstaller = NewBaseInstaller(baseInstallerPath, baseInstallerPath, InstallInData)
@@ -357,10 +385,10 @@
// their architecture & target/host specific zip file.
type ccRustFuzzPackager struct {
fuzz.FuzzPackager
- fuzzPackagingArchModules string
- fuzzTargetSharedDepsInstallPairs string
- allFuzzTargetsName string
- onlyIncludePresubmits bool
+ fuzzPackagingArchModules string
+ fuzzTargetSharedDepsInstallPairs string
+ allFuzzTargetsName string
+ onlyIncludePresubmits bool
}
func fuzzPackagingFactory() android.Singleton {
@@ -369,7 +397,7 @@
fuzzPackagingArchModules: "SOONG_FUZZ_PACKAGING_ARCH_MODULES",
fuzzTargetSharedDepsInstallPairs: "FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
allFuzzTargetsName: "ALL_FUZZ_TARGETS",
- onlyIncludePresubmits: false,
+ onlyIncludePresubmits: false,
}
return fuzzPackager
}
@@ -380,7 +408,7 @@
fuzzPackagingArchModules: "SOONG_PRESUBMIT_FUZZ_PACKAGING_ARCH_MODULES",
fuzzTargetSharedDepsInstallPairs: "PRESUBMIT_FUZZ_TARGET_SHARED_DEPS_INSTALL_PAIRS",
allFuzzTargetsName: "ALL_PRESUBMIT_FUZZ_TARGETS",
- onlyIncludePresubmits: true,
+ onlyIncludePresubmits: true,
}
return fuzzPackager
}
@@ -410,6 +438,10 @@
}
sharedLibsInstallDirPrefix := "lib"
+ if ccModule.InVendor() {
+ sharedLibsInstallDirPrefix = "lib/vendor"
+ }
+
if !ccModule.IsFuzzModule() {
return
}
@@ -451,7 +483,7 @@
if fpm.FuzzProperties.Fuzz_config == nil {
return
}
- if !BoolDefault(fpm.FuzzProperties.Fuzz_config.Use_for_presubmit, false){
+ if !BoolDefault(fpm.FuzzProperties.Fuzz_config.Use_for_presubmit, false) {
return
}
}
@@ -502,7 +534,7 @@
// install it to the output directory. Setup the install destination here,
// which will be used by $(copy-many-files) in the Make backend.
installDestination := SharedLibraryInstallLocation(
- install, module.Host(), fuzzDir, archString)
+ install, module.Host(), module.InVendor(), fuzzDir, archString)
if (*sharedLibraryInstalled)[installDestination] {
continue
}
@@ -520,7 +552,7 @@
// we want symbolization tools (like `stack`) to be able to find the symbols
// in $ANDROID_PRODUCT_OUT/symbols automagically.
if !module.Host() {
- symbolsInstallDestination := SharedLibrarySymbolsInstallLocation(install, fuzzDir, archString)
+ symbolsInstallDestination := SharedLibrarySymbolsInstallLocation(install, module.InVendor(), fuzzDir, archString)
symbolsInstallDestination = strings.ReplaceAll(symbolsInstallDestination, "$", "$$")
s.SharedLibInstallStrings = append(s.SharedLibInstallStrings,
library.String()+":"+symbolsInstallDestination)
@@ -547,7 +579,8 @@
if !IsValidSharedDependency(dep) {
return
}
- if !ctx.OtherModuleHasProvider(dep, SharedLibraryInfoProvider) {
+ sharedLibraryInfo, hasSharedLibraryInfo := android.OtherModuleProvider(ctx, dep, SharedLibraryInfoProvider)
+ if !hasSharedLibraryInfo {
return
}
if seen[ctx.OtherModuleName(dep)] {
@@ -556,7 +589,6 @@
seen[ctx.OtherModuleName(dep)] = true
deps = append(deps, dep)
- sharedLibraryInfo := ctx.OtherModuleProvider(dep, SharedLibraryInfoProvider).(SharedLibraryInfo)
installDestination := sharedLibraryInfo.SharedLibrary.Base()
ruleBuilderInstall := android.RuleBuilderInstall{android.OutputFileForModule(ctx, dep, "unstripped"), installDestination}
sharedLibraries = append(sharedLibraries, ruleBuilderInstall)
@@ -577,14 +609,14 @@
if !IsValidSharedDependency(child) {
return false
}
- if !ctx.OtherModuleHasProvider(child, SharedLibraryInfoProvider) {
+ sharedLibraryInfo, hasSharedLibraryInfo := android.OtherModuleProvider(ctx, child, SharedLibraryInfoProvider)
+ if !hasSharedLibraryInfo {
return false
}
if !seen[ctx.OtherModuleName(child)] {
seen[ctx.OtherModuleName(child)] = true
deps = append(deps, child)
- sharedLibraryInfo := ctx.OtherModuleProvider(child, SharedLibraryInfoProvider).(SharedLibraryInfo)
installDestination := sharedLibraryInfo.SharedLibrary.Base()
ruleBuilderInstall := android.RuleBuilderInstall{android.OutputFileForModule(ctx, child, "unstripped"), installDestination}
sharedLibraries = append(sharedLibraries, ruleBuilderInstall)
diff --git a/cc/gen.go b/cc/gen.go
index b15f164..e351fdd 100644
--- a/cc/gen.go
+++ b/cc/gen.go
@@ -19,8 +19,6 @@
"strings"
"android/soong/aidl_library"
- "android/soong/bazel"
-
"github.com/google/blueprint"
"android/soong/android"
@@ -180,41 +178,6 @@
})
}
-type LexAttrs struct {
- Srcs bazel.LabelListAttribute
- Lexopts bazel.StringListAttribute
-}
-
-type LexNames struct {
- cSrcName bazel.LabelAttribute
- srcName bazel.LabelAttribute
-}
-
-func bp2BuildLex(ctx android.Bp2buildMutatorContext, moduleName string, ca compilerAttributes) LexNames {
- names := LexNames{}
- if !ca.lSrcs.IsEmpty() {
- names.cSrcName = createLexTargetModule(ctx, moduleName+"_genlex_l", ca.lSrcs, ca.lexopts)
- }
- if !ca.llSrcs.IsEmpty() {
- names.srcName = createLexTargetModule(ctx, moduleName+"_genlex_ll", ca.llSrcs, ca.lexopts)
- }
- return names
-}
-
-func createLexTargetModule(ctx android.Bp2buildMutatorContext, name string, srcs bazel.LabelListAttribute, opts bazel.StringListAttribute) bazel.LabelAttribute {
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "genlex",
- Bzl_load_location: "//build/bazel/rules/cc:flex.bzl",
- },
- android.CommonAttributes{Name: name},
- &LexAttrs{
- Srcs: srcs,
- Lexopts: opts,
- })
- return bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + name}}
-}
-
func genSysprop(ctx android.ModuleContext, syspropFile android.Path) (android.Path, android.Paths) {
headerFile := android.PathForModuleGen(ctx, "sysprop", "include", syspropFile.Rel()+".h")
publicHeaderFile := android.PathForModuleGen(ctx, "sysprop/public", "include", syspropFile.Rel()+".h")
@@ -239,34 +202,6 @@
return cppFile, headers.Paths()
}
-func bp2buildCcSysprop(ctx android.Bp2buildMutatorContext, moduleName string, minSdkVersion *string, srcs bazel.LabelListAttribute) *bazel.LabelAttribute {
- labels := SyspropLibraryLabels{
- SyspropLibraryLabel: moduleName + "_sysprop_library",
- StaticLibraryLabel: moduleName + "_cc_sysprop_library_static",
- }
- Bp2buildSysprop(ctx, labels, srcs, minSdkVersion)
- return createLabelAttributeCorrespondingToSrcs(":"+labels.StaticLibraryLabel, srcs)
-}
-
-// Creates a LabelAttribute for a given label where the value is only set for
-// the same config values that have values in a given LabelListAttribute
-func createLabelAttributeCorrespondingToSrcs(baseLabelName string, srcs bazel.LabelListAttribute) *bazel.LabelAttribute {
- baseLabel := bazel.Label{Label: baseLabelName}
- label := bazel.LabelAttribute{}
- if !srcs.Value.IsNil() && !srcs.Value.IsEmpty() {
- label.Value = &baseLabel
- return &label
- }
- for axis, configToSrcs := range srcs.ConfigurableValues {
- for config, val := range configToSrcs {
- if !val.IsNil() && !val.IsEmpty() {
- label.SetSelectValue(axis, config, baseLabel)
- }
- }
- }
- return &label
-}
-
// Used to communicate information from the genSources method back to the library code that uses
// it.
type generatedSourceInfo struct {
@@ -290,6 +225,10 @@
// The files that can be used as order only dependencies in order to ensure that the sysprop
// header files are up to date.
syspropOrderOnlyDeps android.Paths
+
+ // List of generated code path.
+ // ex) '*.cpp' files generated from '*.ll / *.yy'.
+ generatedSources android.Paths
}
func genSources(
@@ -319,30 +258,37 @@
return yaccRule_
}
+ var generatedSources android.Paths = nil
+
for i, srcFile := range srcFiles {
switch srcFile.Ext() {
case ".y":
cFile := android.GenPathWithExt(ctx, "yacc", srcFile, "c")
srcFiles[i] = cFile
deps = append(deps, genYacc(ctx, yaccRule(), srcFile, cFile, buildFlags.yacc)...)
+ generatedSources = append(generatedSources, cFile)
case ".yy":
cppFile := android.GenPathWithExt(ctx, "yacc", srcFile, "cpp")
srcFiles[i] = cppFile
deps = append(deps, genYacc(ctx, yaccRule(), srcFile, cppFile, buildFlags.yacc)...)
+ generatedSources = append(generatedSources, cppFile)
case ".l":
cFile := android.GenPathWithExt(ctx, "lex", srcFile, "c")
srcFiles[i] = cFile
genLex(ctx, srcFile, cFile, buildFlags.lex)
+ generatedSources = append(generatedSources, cFile)
case ".ll":
cppFile := android.GenPathWithExt(ctx, "lex", srcFile, "cpp")
srcFiles[i] = cppFile
genLex(ctx, srcFile, cppFile, buildFlags.lex)
+ generatedSources = append(generatedSources, cppFile)
case ".proto":
ccFile, headerFile := genProto(ctx, srcFile, buildFlags)
srcFiles[i] = ccFile
info.protoHeaders = append(info.protoHeaders, headerFile)
// Use the generated header as an order only dep to ensure that it is up to date when needed.
info.protoOrderOnlyDeps = append(info.protoOrderOnlyDeps, headerFile)
+ generatedSources = append(generatedSources, ccFile)
case ".aidl":
if aidlRule == nil {
aidlRule = android.NewRuleBuilder(pctx, ctx).Sbox(android.PathForModuleGen(ctx, "aidl"),
@@ -364,10 +310,12 @@
// needed.
// TODO: Reduce the size of the ninja file by using one order only dep for the whole rule
info.aidlOrderOnlyDeps = append(info.aidlOrderOnlyDeps, aidlHeaders...)
+ generatedSources = append(generatedSources, cppFile)
case ".rscript", ".fs":
cppFile := rsGeneratedCppFile(ctx, srcFile)
rsFiles = append(rsFiles, srcFiles[i])
srcFiles[i] = cppFile
+ generatedSources = append(generatedSources, cppFile)
case ".sysprop":
cppFile, headerFiles := genSysprop(ctx, srcFile)
srcFiles[i] = cppFile
@@ -375,9 +323,12 @@
// Use the generated headers as order only deps to ensure that they are up to date when
// needed.
info.syspropOrderOnlyDeps = append(info.syspropOrderOnlyDeps, headerFiles...)
+ generatedSources = append(generatedSources, cppFile)
}
}
+ info.generatedSources = generatedSources
+
for _, aidlLibraryInfo := range aidlLibraryInfos {
if aidlLibraryRule == nil {
aidlLibraryRule = android.NewRuleBuilder(pctx, ctx).Sbox(
diff --git a/cc/gen_test.go b/cc/gen_test.go
index 85df333..439f0a9 100644
--- a/cc/gen_test.go
+++ b/cc/gen_test.go
@@ -67,7 +67,7 @@
t.Errorf("missing aidl includes in global flags")
}
- aidlCommand := android.RuleBuilderSboxProtoForTests(t, aidlManifest).Commands[0].GetCommand()
+ aidlCommand := android.RuleBuilderSboxProtoForTests(t, ctx, aidlManifest).Commands[0].GetCommand()
if !strings.Contains(aidlCommand, "-Isub") {
t.Errorf("aidl command for c.aidl should contain \"-Isub\", but was %q", aidlCommand)
}
diff --git a/cc/generated_cc_library.go b/cc/generated_cc_library.go
index 55e19f9..b1084e4 100644
--- a/cc/generated_cc_library.go
+++ b/cc/generated_cc_library.go
@@ -28,10 +28,6 @@
staticAndSharedLibrarySdkMemberType,
}
- // TODO: Need to be bazelable
- // module.bazelable = true
- // module.bazelHandler = &ccLibraryBazelHandler{module: module}
-
module.generators = append(module.generators, callbacks)
return module.Init()
diff --git a/cc/genrule.go b/cc/genrule.go
index d1c4c2a..0fb3e2d 100644
--- a/cc/genrule.go
+++ b/cc/genrule.go
@@ -62,7 +62,6 @@
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibBoth)
android.InitApexModule(module)
- android.InitBazelModule(module)
return module
}
@@ -80,15 +79,7 @@
func (g *GenruleExtraProperties) ImageMutatorBegin(ctx android.BaseModuleContext) {}
func (g *GenruleExtraProperties) CoreVariantNeeded(ctx android.BaseModuleContext) bool {
- if ctx.DeviceConfig().VndkVersion() == "" {
- return true
- }
-
- if ctx.DeviceConfig().ProductVndkVersion() != "" && ctx.ProductSpecific() {
- return false
- }
-
- return !(ctx.SocSpecific() || ctx.DeviceSpecific())
+ return !(ctx.SocSpecific() || ctx.DeviceSpecific() || ctx.ProductSpecific())
}
func (g *GenruleExtraProperties) RamdiskVariantNeeded(ctx android.BaseModuleContext) bool {
@@ -116,32 +107,32 @@
}
func (g *GenruleExtraProperties) ExtraImageVariations(ctx android.BaseModuleContext) []string {
- if ctx.DeviceConfig().VndkVersion() == "" {
- return nil
- }
-
var variants []string
- if Bool(g.Vendor_available) || Bool(g.Odm_available) || ctx.SocSpecific() || ctx.DeviceSpecific() {
- vndkVersion := ctx.DeviceConfig().VndkVersion()
- // If vndkVersion is current, we can always use PlatformVndkVersion.
- // If not, we assume modules under proprietary paths are compatible for
- // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, that is
- // PLATFORM_VNDK_VERSION.
- if vndkVersion == "current" || !snapshot.IsVendorProprietaryModule(ctx) {
- variants = append(variants, VendorVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
- } else {
- variants = append(variants, VendorVariationPrefix+vndkVersion)
+ vndkVersion := ctx.DeviceConfig().VndkVersion()
+ vendorVariantRequired := Bool(g.Vendor_available) || Bool(g.Odm_available) || ctx.SocSpecific() || ctx.DeviceSpecific()
+ productVariantRequired := Bool(g.Product_available) || ctx.ProductSpecific()
+
+ if vndkVersion == "" {
+ if vendorVariantRequired {
+ variants = append(variants, VendorVariation)
}
- }
-
- if ctx.DeviceConfig().ProductVndkVersion() == "" {
- return variants
- }
-
- if Bool(g.Product_available) || ctx.ProductSpecific() {
- variants = append(variants, ProductVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
- if vndkVersion := ctx.DeviceConfig().ProductVndkVersion(); vndkVersion != "current" {
- variants = append(variants, ProductVariationPrefix+vndkVersion)
+ if productVariantRequired {
+ variants = append(variants, ProductVariation)
+ }
+ } else {
+ if vendorVariantRequired {
+ // If vndkVersion is current, we can always use PlatformVndkVersion.
+ // If not, we assume modules under proprietary paths are compatible for
+ // BOARD_VNDK_VERSION. The other modules are regarded as AOSP, that is
+ // PLATFORM_VNDK_VERSION.
+ if vndkVersion == "current" || !snapshot.IsVendorProprietaryModule(ctx) {
+ variants = append(variants, VendorVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
+ } else {
+ variants = append(variants, VendorVariationPrefix+vndkVersion)
+ }
+ }
+ if productVariantRequired {
+ variants = append(variants, ProductVariationPrefix+ctx.DeviceConfig().PlatformVndkVersion())
}
}
diff --git a/cc/genrule_test.go b/cc/genrule_test.go
index 0d16e62..05c644f 100644
--- a/cc/genrule_test.go
+++ b/cc/genrule_test.go
@@ -16,6 +16,7 @@
import (
"reflect"
+ "slices"
"testing"
"android/soong/android"
@@ -178,7 +179,7 @@
android.OptionalFixturePreparer(tt.preparer),
).RunTestWithBp(t, bp)
gen := result.ModuleForTests("gen", tt.variant)
- sboxProto := android.RuleBuilderSboxProtoForTests(t, gen.Output("genrule.sbox.textproto"))
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, gen.Output("genrule.sbox.textproto"))
cmd := *sboxProto.Commands[0].Command
android.AssertStringDoesContain(t, "incorrect CC_ARCH", cmd, "CC_ARCH="+tt.arch+" ")
android.AssertStringDoesContain(t, "incorrect CC_NATIVE_BRIDGE", cmd, "CC_NATIVE_BRIDGE="+tt.nativeBridge+" ")
@@ -186,3 +187,26 @@
})
}
}
+
+func TestVendorProductVariantGenrule(t *testing.T) {
+ bp := `
+ cc_genrule {
+ name: "gen",
+ tool_files: ["tool"],
+ cmd: "$(location tool) $(in) $(out)",
+ out: ["out"],
+ vendor_available: true,
+ product_available: true,
+ }
+ `
+ t.Helper()
+ ctx := PrepareForTestWithCcIncludeVndk.RunTestWithBp(t, bp)
+
+ variants := ctx.ModuleVariantsForTests("gen")
+ if !slices.Contains(variants, "android_vendor_arm64_armv8-a") {
+ t.Errorf(`expected vendor variant, but does not exist in %v`, variants)
+ }
+ if !slices.Contains(variants, "android_product_arm64_armv8-a") {
+ t.Errorf(`expected product variant, but does not exist in %v`, variants)
+ }
+}
diff --git a/cc/image.go b/cc/image.go
index f91762a..d02a2f3 100644
--- a/cc/image.go
+++ b/cc/image.go
@@ -23,6 +23,8 @@
"android/soong/android"
"android/soong/snapshot"
+
+ "github.com/google/blueprint/proptools"
)
var _ android.ImageInterface = (*Module)(nil)
@@ -40,27 +42,23 @@
)
const (
+ // VendorVariation is the variant name used for /vendor code that does not
+ // compile against the VNDK.
+ VendorVariation = "vendor"
+
// VendorVariationPrefix is the variant prefix used for /vendor code that compiles
// against the VNDK.
VendorVariationPrefix = "vendor."
+ // ProductVariation is the variant name used for /product code that does not
+ // compile against the VNDK.
+ ProductVariation = "product"
+
// ProductVariationPrefix is the variant prefix used for /product code that compiles
// against the VNDK.
ProductVariationPrefix = "product."
)
-func (ctx *moduleContext) ProductSpecific() bool {
- return ctx.ModuleContext.ProductSpecific() || ctx.mod.productSpecificModuleContext()
-}
-
-func (ctx *moduleContext) SocSpecific() bool {
- return ctx.ModuleContext.SocSpecific() || ctx.mod.socSpecificModuleContext()
-}
-
-func (ctx *moduleContext) DeviceSpecific() bool {
- return ctx.ModuleContext.DeviceSpecific() || ctx.mod.deviceSpecificModuleContext()
-}
-
func (ctx *moduleContextImpl) inProduct() bool {
return ctx.mod.InProduct()
}
@@ -81,20 +79,20 @@
return ctx.mod.InRecovery()
}
-func (c *Module) productSpecificModuleContext() bool {
+func (c *Module) InstallInProduct() 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 (c *Module) socSpecificModuleContext() bool {
+func (c *Module) InstallInVendor() bool {
// Additionally check if this module is inVendor() that means it is a "vendor" variant of a
// module. As well as SoC specific modules, vendor variants must be installed to /vendor
// unless they have "odm_available: true".
return c.HasVendorVariant() && c.InVendor() && !c.VendorVariantToOdm()
}
-func (c *Module) deviceSpecificModuleContext() bool {
+func (c *Module) InstallInOdm() bool {
// Some vendor variants want to be installed to /odm by setting "odm_available: true".
return c.InVendor() && c.VendorVariantToOdm()
}
@@ -122,12 +120,18 @@
// Returns true if the module is "product" variant. Usually these modules are installed in /product
func (c *Module) InProduct() bool {
- return c.Properties.ImageVariationPrefix == ProductVariationPrefix
+ return c.Properties.ImageVariation == ProductVariation
}
// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
func (c *Module) InVendor() bool {
- return c.Properties.ImageVariationPrefix == VendorVariationPrefix
+ return c.Properties.ImageVariation == VendorVariation
+}
+
+// Returns true if the module is "vendor" or "product" variant. This replaces previous UseVndk usages
+// which were misused to check if the module variant is vendor or product.
+func (c *Module) InVendorOrProduct() bool {
+ return c.InVendor() || c.InProduct()
}
func (c *Module) InRamdisk() bool {
@@ -427,7 +431,6 @@
platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
boardVndkVersion := mctx.DeviceConfig().VndkVersion()
- productVndkVersion := mctx.DeviceConfig().ProductVndkVersion()
recoverySnapshotVersion := mctx.DeviceConfig().RecoverySnapshotVersion()
usingRecoverySnapshot := recoverySnapshotVersion != "current" &&
recoverySnapshotVersion != ""
@@ -444,42 +447,25 @@
if boardVndkVersion == "current" {
boardVndkVersion = platformVndkVersion
}
- if productVndkVersion == "current" {
- productVndkVersion = platformVndkVersion
- }
if m.NeedsLlndkVariants() {
// This is an LLNDK library. The implementation of the library will be on /system,
// and vendor and product variants will be created with LLNDK stubs.
// The LLNDK libraries need vendor variants even if there is no VNDK.
coreVariantNeeded = true
- if platformVndkVersion != "" {
- vendorVariants = append(vendorVariants, platformVndkVersion)
- productVariants = append(productVariants, platformVndkVersion)
- }
+ vendorVariants = append(vendorVariants, platformVndkVersion)
+ productVariants = append(productVariants, platformVndkVersion)
// Generate vendor variants for boardVndkVersion only if the VNDK snapshot does not
// provide the LLNDK stub libraries.
if needVndkVersionVendorVariantForLlndk {
vendorVariants = append(vendorVariants, boardVndkVersion)
}
- if productVndkVersion != "" {
- productVariants = append(productVariants, productVndkVersion)
- }
} else if m.NeedsVendorPublicLibraryVariants() {
// A vendor public library has the implementation on /vendor, with stub variants
// for system and product.
coreVariantNeeded = true
vendorVariants = append(vendorVariants, boardVndkVersion)
- if platformVndkVersion != "" {
- productVariants = append(productVariants, platformVndkVersion)
- }
- if productVndkVersion != "" {
- productVariants = append(productVariants, productVndkVersion)
- }
- } else if boardVndkVersion == "" {
- // If the device isn't compiling against the VNDK, we always
- // use the core mode.
- coreVariantNeeded = true
+ productVariants = append(productVariants, platformVndkVersion)
} else if m.IsSnapshotPrebuilt() {
// Make vendor variants only for the versions in BOARD_VNDK_VERSION and
// PRODUCT_EXTRA_VNDK_VERSIONS.
@@ -507,10 +493,6 @@
// product_available modules are available to /product.
if m.HasProductVariant() {
productVariants = append(productVariants, platformVndkVersion)
- // VNDK is always PLATFORM_VNDK_VERSION
- if !m.IsVndk() {
- productVariants = append(productVariants, productVndkVersion)
- }
}
} else if vendorSpecific && m.SdkVersion() == "" {
// This will be available in /vendor (or /odm) only
@@ -538,17 +520,10 @@
coreVariantNeeded = true
}
- if boardVndkVersion != "" && productVndkVersion != "" {
- if coreVariantNeeded && productSpecific && m.SdkVersion() == "" {
- // The module has "product_specific: true" that does not create core variant.
- coreVariantNeeded = false
- productVariants = append(productVariants, productVndkVersion)
- }
- } else {
- // Unless PRODUCT_PRODUCT_VNDK_VERSION is set, product partition has no
- // restriction to use system libs.
- // No product variants defined in this case.
- productVariants = []string{}
+ if coreVariantNeeded && productSpecific && m.SdkVersion() == "" {
+ // The module has "product_specific: true" that does not create core variant.
+ coreVariantNeeded = false
+ productVariants = append(productVariants, platformVndkVersion)
}
if m.RamdiskAvailable() {
@@ -588,11 +563,19 @@
}
for _, variant := range android.FirstUniqueStrings(vendorVariants) {
- m.AppendExtraVariant(VendorVariationPrefix + variant)
+ if variant == "" {
+ m.AppendExtraVariant(VendorVariation)
+ } else {
+ m.AppendExtraVariant(VendorVariationPrefix + variant)
+ }
}
for _, variant := range android.FirstUniqueStrings(productVariants) {
- m.AppendExtraVariant(ProductVariationPrefix + variant)
+ if variant == "" {
+ m.AppendExtraVariant(ProductVariation)
+ } else {
+ m.AppendExtraVariant(ProductVariationPrefix + variant)
+ }
}
m.SetRamdiskVariantNeeded(ramdiskVariantNeeded)
@@ -643,6 +626,10 @@
lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
lib.baseCompiler.Properties.Target.Vendor.Exclude_generated_sources...)
+
+ if lib.Properties.Target.Vendor.No_stubs {
+ proptools.Clear(&lib.Properties.Stubs)
+ }
}
}
@@ -656,6 +643,10 @@
lib.baseCompiler.Properties.Exclude_generated_sources = append(lib.baseCompiler.Properties.Exclude_generated_sources,
lib.baseCompiler.Properties.Target.Product.Exclude_generated_sources...)
+
+ if lib.Properties.Target.Product.No_stubs {
+ proptools.Clear(&lib.Properties.Stubs)
+ }
}
}
@@ -695,9 +686,12 @@
} else if variant == android.RecoveryVariation {
m.MakeAsPlatform()
squashRecoverySrcs(m)
- } else if strings.HasPrefix(variant, VendorVariationPrefix) {
- m.Properties.ImageVariationPrefix = VendorVariationPrefix
- m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
+ } else if strings.HasPrefix(variant, VendorVariation) {
+ m.Properties.ImageVariation = VendorVariation
+
+ if strings.HasPrefix(variant, VendorVariationPrefix) {
+ m.Properties.VndkVersion = strings.TrimPrefix(variant, VendorVariationPrefix)
+ }
squashVendorSrcs(m)
// Makefile shouldn't know vendor modules other than BOARD_VNDK_VERSION.
@@ -707,9 +701,11 @@
m.Properties.HideFromMake = true
m.HideFromMake()
}
- } else if strings.HasPrefix(variant, ProductVariationPrefix) {
- m.Properties.ImageVariationPrefix = ProductVariationPrefix
- m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
+ } else if strings.HasPrefix(variant, ProductVariation) {
+ m.Properties.ImageVariation = ProductVariation
+ if strings.HasPrefix(variant, ProductVariationPrefix) {
+ m.Properties.VndkVersion = strings.TrimPrefix(variant, ProductVariationPrefix)
+ }
squashProductSrcs(m)
}
diff --git a/cc/installer.go b/cc/installer.go
index e2c0e7b..30f9612 100644
--- a/cc/installer.go
+++ b/cc/installer.go
@@ -59,6 +59,8 @@
relative string
location installLocation
+ installDeps android.InstallPaths
+
path android.InstallPath
}
@@ -85,7 +87,7 @@
} else if !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
dir = filepath.Join(dir, ctx.Arch().ArchType.String())
}
- if installer.location == InstallInData && ctx.useVndk() {
+ if installer.location == InstallInData && ctx.InVendorOrProduct() {
if ctx.inProduct() {
dir = filepath.Join(dir, "product")
} else {
@@ -97,7 +99,12 @@
}
func (installer *baseInstaller) install(ctx ModuleContext, file android.Path) {
- installer.path = ctx.InstallFile(installer.installDir(ctx), file.Base(), file)
+ installer.path = ctx.InstallFile(installer.installDir(ctx), file.Base(), file, installer.installDeps...)
+}
+
+func (installer *baseInstaller) installTestData(ctx ModuleContext, data []android.DataPath) {
+ installedData := ctx.InstallTestData(installer.installDir(ctx), data)
+ installer.installDeps = append(installer.installDeps, installedData...)
}
func (installer *baseInstaller) everInstallable() bool {
diff --git a/cc/kernel_headers.go b/cc/kernel_headers.go
index 9ea988a..4f685be 100644
--- a/cc/kernel_headers.go
+++ b/cc/kernel_headers.go
@@ -34,7 +34,7 @@
// kernel_headers retrieves the list of kernel headers directories from
// TARGET_BOARD_KERNEL_HEADERS and TARGET_PRODUCT_KERNEL_HEADERS variables in
// a makefile for compilation. See
-// https://android.googlesource.com/platform/build/+/master/core/config.mk
+// https://android.googlesource.com/platform/build/+/main/core/config.mk
// for more details on them.
func kernelHeadersFactory() android.Module {
module, library := NewLibrary(android.HostAndDeviceSupported)
diff --git a/cc/library.go b/cc/library.go
index 2d4d604..4684d32 100644
--- a/cc/library.go
+++ b/cc/library.go
@@ -17,6 +17,7 @@
import (
"fmt"
"io"
+ "log"
"path/filepath"
"regexp"
"strconv"
@@ -24,28 +25,12 @@
"sync"
"android/soong/android"
- "android/soong/bazel"
- "android/soong/bazel/cquery"
"github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
)
-var (
- alwaysLinkLibraries = map[string]bool{
- // Coverage libraries are _always_ added as a whole_static_dep. By converting as these as
- // alwayslink = True, we can add these as to deps (e.g. as a regular static dep) in Bazel
- // without any extra complications in cc_shared_library roots to prevent linking the same
- // library repeatedly.
- "libprofile-extras_ndk": true,
- "libprofile-extras": true,
- "libprofile-clang-extras_ndk": true,
- "libprofile-clang-extras_cfi_support": true,
- "libprofile-clang-extras": true,
- }
-)
-
// LibraryProperties is a collection of properties shared by cc library rules/cc.
type LibraryProperties struct {
// local file name to pass to the linker as -unexported_symbols_list
@@ -107,6 +92,13 @@
Suffix *string `android:"arch_variant"`
Header_abi_checker headerAbiCheckerProperties
+
+ // Disable stubs for vendor/product variants
+ // This is a workaround to keep `stubs` only for "core" variant (not product/vendor).
+ // It would be nice if we could put `stubs` into a `target: { core: {} }`
+ // block but it's not supported in soong yet. This could be removed/simplified once we have
+ // a better syntax.
+ No_stubs bool
}
Platform struct {
@@ -228,436 +220,6 @@
ctx.RegisterModuleType("cc_library_host_shared", LibraryHostSharedFactory)
}
-// TODO(b/199902614): Can this be factored to share with the other Attributes?
-// For bp2build conversion.
-type bazelCcLibraryAttributes struct {
- // Attributes pertaining to both static and shared variants.
- Srcs bazel.LabelListAttribute
- Srcs_c bazel.LabelListAttribute
- Srcs_as bazel.LabelListAttribute
-
- Copts bazel.StringListAttribute
- Cppflags bazel.StringListAttribute
- Conlyflags bazel.StringListAttribute
- Asflags bazel.StringListAttribute
-
- Hdrs bazel.LabelListAttribute
-
- Deps bazel.LabelListAttribute
- Implementation_deps bazel.LabelListAttribute
- Dynamic_deps bazel.LabelListAttribute
- Implementation_dynamic_deps bazel.LabelListAttribute
- Whole_archive_deps bazel.LabelListAttribute
- Implementation_whole_archive_deps bazel.LabelListAttribute
- System_dynamic_deps bazel.LabelListAttribute
-
- Export_includes bazel.StringListAttribute
- Export_system_includes bazel.StringListAttribute
- Local_includes bazel.StringListAttribute
- Absolute_includes bazel.StringListAttribute
- Linkopts bazel.StringListAttribute
- Rtti bazel.BoolAttribute
-
- Stl *string
- Cpp_std *string
- C_std *string
-
- // This is shared only.
- Additional_linker_inputs bazel.LabelListAttribute
-
- // Common properties shared between both shared and static variants.
- Shared staticOrSharedAttributes
- Static staticOrSharedAttributes
-
- Strip stripAttributes
-
- Features bazel.StringListAttribute
-}
-
-type aidlLibraryAttributes struct {
- Srcs bazel.LabelListAttribute
- Include_dir *string
- Tags bazel.StringListAttribute
-}
-
-type ccAidlLibraryAttributes struct {
- Deps bazel.LabelListAttribute
- Implementation_deps bazel.LabelListAttribute
- Implementation_dynamic_deps bazel.LabelListAttribute
- Tags bazel.StringListAttribute
-
- sdkAttributes
- includesAttributes
-}
-
-type stripAttributes struct {
- Keep_symbols bazel.BoolAttribute
- Keep_symbols_and_debug_frame bazel.BoolAttribute
- Keep_symbols_list bazel.StringListAttribute
- All bazel.BoolAttribute
- None bazel.BoolAttribute
-}
-
-func stripAttrsFromLinkerAttrs(la *linkerAttributes) stripAttributes {
- return stripAttributes{
- Keep_symbols: la.stripKeepSymbols,
- Keep_symbols_and_debug_frame: la.stripKeepSymbolsAndDebugFrame,
- Keep_symbols_list: la.stripKeepSymbolsList,
- All: la.stripAll,
- None: la.stripNone,
- }
-}
-
-func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) {
- sharedAttrs := bp2BuildParseSharedProps(ctx, m)
- staticAttrs := bp2BuildParseStaticProps(ctx, m)
- baseAttributes := bp2BuildParseBaseProps(ctx, m)
- compilerAttrs := baseAttributes.compilerAttributes
- linkerAttrs := baseAttributes.linkerAttributes
- exportedIncludes := bp2BuildParseExportedIncludes(ctx, m, &compilerAttrs.includes)
-
- srcs := compilerAttrs.srcs
-
- sharedAttrs.Dynamic_deps.Add(baseAttributes.protoDependency)
- staticAttrs.Deps.Add(baseAttributes.protoDependency)
-
- asFlags := compilerAttrs.asFlags
- if compilerAttrs.asSrcs.IsEmpty() && sharedAttrs.Srcs_as.IsEmpty() && staticAttrs.Srcs_as.IsEmpty() {
- // Skip asflags for BUILD file simplicity if there are no assembly sources.
- asFlags = bazel.MakeStringListAttribute(nil)
- }
-
- sharedFeatures := baseAttributes.features.Clone().Append(sharedAttrs.Features)
- sharedFeatures.DeduplicateAxesFromBase()
- staticFeatures := baseAttributes.features.Clone().Append(staticAttrs.Features)
- staticFeatures.DeduplicateAxesFromBase()
-
- staticCommonAttrs := staticOrSharedAttributes{
- Srcs: *srcs.Clone().Append(staticAttrs.Srcs),
- Srcs_c: *compilerAttrs.cSrcs.Clone().Append(staticAttrs.Srcs_c),
- Srcs_as: *compilerAttrs.asSrcs.Clone().Append(staticAttrs.Srcs_as),
- Copts: *compilerAttrs.copts.Clone().Append(staticAttrs.Copts),
- Hdrs: *compilerAttrs.hdrs.Clone().Append(staticAttrs.Hdrs),
-
- Deps: *linkerAttrs.deps.Clone().Append(staticAttrs.Deps),
- Implementation_deps: *linkerAttrs.implementationDeps.Clone().Append(staticAttrs.Implementation_deps),
- Dynamic_deps: *linkerAttrs.dynamicDeps.Clone().Append(staticAttrs.Dynamic_deps),
- Implementation_dynamic_deps: *linkerAttrs.implementationDynamicDeps.Clone().Append(staticAttrs.Implementation_dynamic_deps),
- Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps,
- Whole_archive_deps: *linkerAttrs.wholeArchiveDeps.Clone().Append(staticAttrs.Whole_archive_deps),
- System_dynamic_deps: *linkerAttrs.systemDynamicDeps.Clone().Append(staticAttrs.System_dynamic_deps),
- Runtime_deps: linkerAttrs.runtimeDeps,
- sdkAttributes: bp2BuildParseSdkAttributes(m),
- Native_coverage: baseAttributes.Native_coverage,
- Additional_compiler_inputs: compilerAttrs.additionalCompilerInputs,
- }
-
- includeAttrs := includesAttributes{
- Export_includes: exportedIncludes.Includes,
- Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
- Export_system_includes: exportedIncludes.SystemIncludes,
- Local_includes: compilerAttrs.localIncludes,
- Absolute_includes: compilerAttrs.absoluteIncludes,
- }
-
- sharedCommonAttrs := staticOrSharedAttributes{
- Srcs: *srcs.Clone().Append(sharedAttrs.Srcs),
- Srcs_c: *compilerAttrs.cSrcs.Clone().Append(sharedAttrs.Srcs_c),
- Srcs_as: *compilerAttrs.asSrcs.Clone().Append(sharedAttrs.Srcs_as),
- Copts: *compilerAttrs.copts.Clone().Append(sharedAttrs.Copts),
- Hdrs: *compilerAttrs.hdrs.Clone().Append(sharedAttrs.Hdrs),
-
- Deps: *linkerAttrs.deps.Clone().Append(sharedAttrs.Deps),
- Implementation_deps: *linkerAttrs.implementationDeps.Clone().Append(sharedAttrs.Implementation_deps),
- Dynamic_deps: *linkerAttrs.dynamicDeps.Clone().Append(sharedAttrs.Dynamic_deps),
- Implementation_dynamic_deps: *linkerAttrs.implementationDynamicDeps.Clone().Append(sharedAttrs.Implementation_dynamic_deps),
- Whole_archive_deps: *linkerAttrs.wholeArchiveDeps.Clone().Append(sharedAttrs.Whole_archive_deps),
- Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps,
- System_dynamic_deps: *linkerAttrs.systemDynamicDeps.Clone().Append(sharedAttrs.System_dynamic_deps),
- Runtime_deps: linkerAttrs.runtimeDeps,
- sdkAttributes: bp2BuildParseSdkAttributes(m),
- Native_coverage: baseAttributes.Native_coverage,
- Additional_compiler_inputs: compilerAttrs.additionalCompilerInputs,
- }
-
- staticTargetAttrs := &bazelCcLibraryStaticAttributes{
- staticOrSharedAttributes: staticCommonAttrs,
- includesAttributes: includeAttrs,
-
- Cppflags: compilerAttrs.cppFlags,
- Conlyflags: compilerAttrs.conlyFlags,
- Asflags: asFlags,
-
- Rtti: compilerAttrs.rtti,
- Stl: compilerAttrs.stl,
- Cpp_std: compilerAttrs.cppStd,
- C_std: compilerAttrs.cStd,
-
- Features: *staticFeatures,
- }
-
- sharedTargetAttrs := &bazelCcLibrarySharedAttributes{
- staticOrSharedAttributes: sharedCommonAttrs,
- includesAttributes: includeAttrs,
-
- Cppflags: compilerAttrs.cppFlags,
- Conlyflags: compilerAttrs.conlyFlags,
- Asflags: asFlags,
-
- Linkopts: linkerAttrs.linkopts,
- Rtti: compilerAttrs.rtti,
- Stl: compilerAttrs.stl,
- Cpp_std: compilerAttrs.cppStd,
- C_std: compilerAttrs.cStd,
- Use_version_lib: linkerAttrs.useVersionLib,
-
- Additional_linker_inputs: linkerAttrs.additionalLinkerInputs,
-
- Strip: stripAttrsFromLinkerAttrs(&linkerAttrs),
- Features: *sharedFeatures,
- bazelCcHeaderAbiCheckerAttributes: bp2buildParseAbiCheckerProps(ctx, m),
-
- Fdo_profile: compilerAttrs.fdoProfile,
- }
-
- if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 {
- sharedTargetAttrs.Stubs_symbol_file = compilerAttrs.stubsSymbolFile
- }
-
- sharedTargetAttrs.Stem = compilerAttrs.stem
- sharedTargetAttrs.Suffix = compilerAttrs.suffix
-
- for axis, configToProps := range m.GetArchVariantProperties(ctx, &LibraryProperties{}) {
- for cfg, props := range configToProps {
- if props, ok := props.(*LibraryProperties); ok {
- if props.Inject_bssl_hash != nil {
- // This is an edge case applies only to libcrypto
- if m.Name() == "libcrypto" || m.Name() == "libcrypto_for_testing" {
- sharedTargetAttrs.Inject_bssl_hash.SetSelectValue(axis, cfg, props.Inject_bssl_hash)
- } else {
- ctx.PropertyErrorf("inject_bssl_hash", "only applies to libcrypto")
- }
- }
- }
- }
- }
-
- staticProps := bazel.BazelTargetModuleProperties{
- Rule_class: "cc_library_static",
- Bzl_load_location: "//build/bazel/rules/cc:cc_library_static.bzl",
- }
- sharedProps := bazel.BazelTargetModuleProperties{
- Rule_class: "cc_library_shared",
- Bzl_load_location: "//build/bazel/rules/cc:cc_library_shared.bzl",
- }
-
- if _, ok := alwaysLinkLibraries[m.Name()]; ok {
- staticTargetAttrs.Alwayslink = proptools.BoolPtr(true)
- }
-
- var tagsForStaticVariant bazel.StringListAttribute
- if compilerAttrs.stubsSymbolFile == nil && len(compilerAttrs.stubsVersions.Value) == 0 {
- tagsForStaticVariant = android.ApexAvailableTagsWithoutTestApexes(ctx, m)
- }
- tagsForStaticVariant.Append(bazel.StringListAttribute{Value: staticAttrs.Apex_available})
-
- tagsForSharedVariant := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
- tagsForSharedVariant.Append(bazel.StringListAttribute{Value: sharedAttrs.Apex_available})
-
- ctx.CreateBazelTargetModuleWithRestrictions(staticProps,
- android.CommonAttributes{
- Name: m.Name() + "_bp2build_cc_library_static",
- Tags: tagsForStaticVariant,
- },
- staticTargetAttrs, staticAttrs.Enabled)
- ctx.CreateBazelTargetModuleWithRestrictions(sharedProps,
- android.CommonAttributes{
- Name: m.Name(),
- Tags: tagsForSharedVariant,
- },
- sharedTargetAttrs, sharedAttrs.Enabled)
-
- createStubsBazelTargetIfNeeded(ctx, m, compilerAttrs, exportedIncludes, baseAttributes)
-}
-
-func createStubsBazelTargetIfNeeded(ctx android.TopDownMutatorContext, m *Module, compilerAttrs compilerAttributes, exportedIncludes BazelIncludes, baseAttributes baseAttributes) {
- if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 {
- stubSuitesProps := bazel.BazelTargetModuleProperties{
- Rule_class: "cc_stub_suite",
- Bzl_load_location: "//build/bazel/rules/cc:cc_stub_library.bzl",
- }
- soname := m.Name() + ".so"
- stubSuitesAttrs := &bazelCcStubSuiteAttributes{
- Symbol_file: compilerAttrs.stubsSymbolFile,
- Versions: compilerAttrs.stubsVersions,
- Export_includes: exportedIncludes.Includes,
- Soname: &soname,
- Source_library_label: proptools.StringPtr(m.GetBazelLabel(ctx, m)),
- Deps: baseAttributes.deps,
- }
- 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%s", ctx.ModuleDir(), m.Name(), stubsSuffix),
- }
- 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)
- }
-}
-
-func apiContributionBp2Build(ctx android.TopDownMutatorContext, module *Module) {
- apiSurfaces := make([]string, 0)
- apiHeaders := make([]string, 0)
- // module-libapi for apexes (non-null `stubs` property)
- if module.HasStubsVariants() {
- apiSurfaces = append(apiSurfaces, android.ModuleLibApi.String())
- apiIncludes := getModuleLibApiIncludes(ctx, module)
- if !apiIncludes.isEmpty() {
- createApiHeaderTarget(ctx, apiIncludes)
- apiHeaders = append(apiHeaders, apiIncludes.name)
- }
- }
- // vendorapi (non-null `llndk` property)
- if module.HasLlndkStubs() {
- apiSurfaces = append(apiSurfaces, android.VendorApi.String())
- apiIncludes := getVendorApiIncludes(ctx, module)
- if !apiIncludes.isEmpty() {
- createApiHeaderTarget(ctx, apiIncludes)
- apiHeaders = append(apiHeaders, apiIncludes.name)
- }
- }
- // create a target only if this module contributes to an api surface
- // TODO: Currently this does not distinguish modulelibapi-only headers and vendrorapi-only headers
- // TODO: Update so that modulelibapi-only headers do not get exported to vendorapi (and vice-versa)
- if len(apiSurfaces) > 0 {
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "cc_api_contribution",
- Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl",
- }
- attrs := &bazelCcApiContributionAttributes{
- Library_name: module.Name(),
- Api_surfaces: bazel.MakeStringListAttribute(apiSurfaces),
- Api: apiLabelAttribute(ctx, module),
- Hdrs: bazel.MakeLabelListAttribute(
- bazel.MakeLabelListFromTargetNames(apiHeaders),
- ),
- }
- ctx.CreateBazelTargetModule(
- props,
- android.CommonAttributes{
- Name: android.ApiContributionTargetName(module.Name()),
- SkipData: proptools.BoolPtr(true),
- },
- attrs,
- )
- }
-}
-
-// Native apis are versioned in a single .map.txt for all api surfaces
-// Pick any one of the .map.txt files
-func apiLabelAttribute(ctx android.TopDownMutatorContext, module *Module) bazel.LabelAttribute {
- var apiFile *string
- linker := module.linker.(*libraryDecorator)
- if llndkApi := linker.Properties.Llndk.Symbol_file; llndkApi != nil {
- apiFile = llndkApi
- } else if moduleLibApi := linker.Properties.Stubs.Symbol_file; moduleLibApi != nil {
- apiFile = moduleLibApi
- } else {
- ctx.ModuleErrorf("API surface library does not have any API file")
- }
- apiLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(apiFile)).Label
- return *bazel.MakeLabelAttribute(apiLabel)
-}
-
-// wrapper struct to flatten the arch and os specific export_include_dirs
-// flattening is necessary since we want to export apis of all arches even when we build for x86 (e.g.)
-type bazelCcApiLibraryHeadersAttributes struct {
- bazelCcLibraryHeadersAttributes
-
- Arch *string
-}
-
-func (a *bazelCcApiLibraryHeadersAttributes) isEmpty() bool {
- return a.Export_includes.IsEmpty() &&
- a.Export_system_includes.IsEmpty() &&
- a.Deps.IsEmpty()
-}
-
-type apiIncludes struct {
- name string // name of the Bazel target in the generated bp2build workspace
- attrs bazelCcApiLibraryHeadersAttributes
-}
-
-func (includes *apiIncludes) isEmpty() bool {
- return includes.attrs.isEmpty()
-}
-
-func (includes *apiIncludes) addDep(name string) {
- l := bazel.Label{Label: ":" + name}
- ll := bazel.MakeLabelList([]bazel.Label{l})
- lla := bazel.MakeLabelListAttribute(ll)
- includes.attrs.Deps.Append(lla)
-}
-
-// includes provided to the module-lib API surface. This API surface is used by apexes.
-func getModuleLibApiIncludes(ctx android.TopDownMutatorContext, c *Module) apiIncludes {
- flagProps := c.library.(*libraryDecorator).flagExporter.Properties
- linkProps := c.library.(*libraryDecorator).baseLinker.Properties
- includes := android.FirstUniqueStrings(flagProps.Export_include_dirs)
- systemIncludes := android.FirstUniqueStrings(flagProps.Export_system_include_dirs)
- headerLibs := android.FirstUniqueStrings(linkProps.Export_header_lib_headers)
- attrs := bazelCcLibraryHeadersAttributes{
- Export_includes: bazel.MakeStringListAttribute(includes),
- Export_system_includes: bazel.MakeStringListAttribute(systemIncludes),
- Deps: bazel.MakeLabelListAttribute(apiHeaderLabels(ctx, headerLibs)),
- }
-
- return apiIncludes{
- name: c.Name() + ".module-libapi.headers",
- attrs: bazelCcApiLibraryHeadersAttributes{
- bazelCcLibraryHeadersAttributes: attrs,
- },
- }
-}
-
-func getVendorApiIncludes(ctx android.TopDownMutatorContext, c *Module) apiIncludes {
- baseProps := c.library.(*libraryDecorator).flagExporter.Properties
- llndkProps := c.library.(*libraryDecorator).Properties.Llndk
- includes := baseProps.Export_include_dirs
- systemIncludes := baseProps.Export_system_include_dirs
- // LLNDK can override the base includes
- if llndkIncludes := llndkProps.Override_export_include_dirs; llndkIncludes != nil {
- includes = llndkIncludes
- }
- if proptools.Bool(llndkProps.Export_headers_as_system) {
- systemIncludes = append(systemIncludes, includes...)
- includes = nil
- }
-
- attrs := bazelCcLibraryHeadersAttributes{
- Export_includes: bazel.MakeStringListAttribute(includes),
- Export_system_includes: bazel.MakeStringListAttribute(systemIncludes),
- Deps: bazel.MakeLabelListAttribute(apiHeaderLabels(ctx, llndkProps.Export_llndk_headers)),
- }
- return apiIncludes{
- name: c.Name() + ".vendorapi.headers",
- attrs: bazelCcApiLibraryHeadersAttributes{
- bazelCcLibraryHeadersAttributes: attrs,
- },
- }
-}
-
// cc_library creates both static and/or shared libraries for a device and/or
// host. By default, a cc_library has a single variant that targets the device.
// Specifying `host_supported: true` also creates a library that targets the
@@ -670,8 +232,6 @@
staticLibrarySdkMemberType,
staticAndSharedLibrarySdkMemberType,
}
- module.bazelable = true
- module.bazelHandler = &ccLibraryBazelHandler{module: module}
return module.Init()
}
@@ -680,8 +240,6 @@
module, library := NewLibrary(android.HostAndDeviceSupported)
library.BuildOnlyStatic()
module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
- module.bazelable = true
- module.bazelHandler = &ccLibraryBazelHandler{module: module}
return module.Init()
}
@@ -690,8 +248,6 @@
module, library := NewLibrary(android.HostAndDeviceSupported)
library.BuildOnlyShared()
module.sdkMemberTypes = []android.SdkMemberType{sharedLibrarySdkMemberType}
- module.bazelable = true
- module.bazelHandler = &ccLibraryBazelHandler{module: module}
return module.Init()
}
@@ -701,8 +257,6 @@
module, library := NewLibrary(android.HostSupported)
library.BuildOnlyStatic()
module.sdkMemberTypes = []android.SdkMemberType{staticLibrarySdkMemberType}
- module.bazelable = true
- module.bazelHandler = &ccLibraryBazelHandler{module: module}
return module.Init()
}
@@ -711,8 +265,6 @@
module, library := NewLibrary(android.HostSupported)
library.BuildOnlyShared()
module.sdkMemberTypes = []android.SdkMemberType{sharedLibrarySdkMemberType}
- module.bazelable = true
- module.bazelHandler = &ccLibraryBazelHandler{module: module}
return module.Init()
}
@@ -791,7 +343,7 @@
}
func (f *flagExporter) setProvider(ctx android.ModuleContext) {
- ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{
+ android.SetProvider(ctx, FlagExporterInfoProvider, FlagExporterInfo{
// Comes from Export_include_dirs property, and those of exported transitive deps
IncludeDirs: android.FirstUniquePaths(f.dirs),
// Comes from Export_system_include_dirs property, and those of exported transitive deps
@@ -850,6 +402,8 @@
// Location of the linked, unstripped library for shared libraries
unstrippedOutputFile android.Path
+ // Location of the linked, stripped library for shared libraries, strip: "all"
+ strippedAllOutputFile android.Path
// Location of the file that should be copied to dist dir when requested
distFile android.Path
@@ -875,145 +429,6 @@
apiListCoverageXmlPath android.ModuleOutPath
}
-type ccLibraryBazelHandler struct {
- module *Module
-}
-
-var _ BazelHandler = (*ccLibraryBazelHandler)(nil)
-
-// generateStaticBazelBuildActions constructs the StaticLibraryInfo Soong
-// provider from a Bazel shared library's CcInfo provider.
-func (handler *ccLibraryBazelHandler) generateStaticBazelBuildActions(ctx android.ModuleContext, label string, ccInfo cquery.CcInfo) {
- rootStaticArchives := ccInfo.RootStaticArchives
- if len(rootStaticArchives) != 1 {
- ctx.ModuleErrorf("expected exactly one root archive file for '%s', but got %s", label, rootStaticArchives)
- return
- }
- var outputFilePath android.Path = android.PathForBazelOut(ctx, rootStaticArchives[0])
- if len(ccInfo.TidyFiles) > 0 {
- handler.module.tidyFiles = android.PathsForBazelOut(ctx, ccInfo.TidyFiles)
- outputFilePath = android.AttachValidationActions(ctx, outputFilePath, handler.module.tidyFiles)
- }
- handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
-
- objPaths := ccInfo.CcObjectFiles
- objFiles := make(android.Paths, len(objPaths))
- for i, objPath := range objPaths {
- objFiles[i] = android.PathForBazelOut(ctx, objPath)
- }
- objects := Objects{
- objFiles: objFiles,
- }
-
- ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
- StaticLibrary: outputFilePath,
- ReuseObjects: objects,
- Objects: objects,
-
- // TODO(b/190524881): Include transitive static libraries in this provider to support
- // static libraries with deps.
- TransitiveStaticLibrariesForOrdering: android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).
- Direct(outputFilePath).
- Build(),
- })
-
- return
-}
-
-// generateSharedBazelBuildActions constructs the SharedLibraryInfo Soong
-// provider from a Bazel shared library's CcInfo provider.
-func (handler *ccLibraryBazelHandler) generateSharedBazelBuildActions(ctx android.ModuleContext, label string, ccInfo cquery.CcInfo) {
- rootDynamicLibraries := ccInfo.RootDynamicLibraries
-
- if len(rootDynamicLibraries) != 1 {
- ctx.ModuleErrorf("expected exactly one root dynamic library file for '%s', but got %s", label, rootDynamicLibraries)
- return
- }
- var outputFilePath android.Path = android.PathForBazelOut(ctx, rootDynamicLibraries[0])
- if len(ccInfo.TidyFiles) > 0 {
- handler.module.tidyFiles = android.PathsForBazelOut(ctx, ccInfo.TidyFiles)
- outputFilePath = android.AttachValidationActions(ctx, outputFilePath, handler.module.tidyFiles)
- }
-
- handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
- handler.module.linker.(*libraryDecorator).unstrippedOutputFile = android.PathForBazelOut(ctx, ccInfo.UnstrippedOutput)
-
- var tocFile android.OptionalPath
- if len(ccInfo.TocFile) > 0 {
- tocFile = android.OptionalPathForPath(android.PathForBazelOut(ctx, ccInfo.TocFile))
- }
- handler.module.linker.(*libraryDecorator).tocFile = tocFile
-
- if len(ccInfo.AbiDiffFiles) > 0 {
- handler.module.linker.(*libraryDecorator).sAbiDiff = android.PathsForBazelOut(ctx, ccInfo.AbiDiffFiles)
- }
-
- ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
- TableOfContents: tocFile,
- SharedLibrary: outputFilePath,
- Target: ctx.Target(),
- // TODO(b/190524881): Include transitive static libraries in this provider to support
- // static libraries with deps. The provider key for this is TransitiveStaticLibrariesForOrdering.
- })
-}
-
-func (handler *ccLibraryBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
- bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(label, cquery.GetCcInfo, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx)))
- if v := handler.module.library.stubsVersion(); v != "" {
- stubsLabel := label + "_stub_libs-" + v
- bazelCtx.QueueBazelRequest(stubsLabel, cquery.GetCcInfo, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx)))
- }
-}
-
-func (handler *ccLibraryBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
- if v := handler.module.library.stubsVersion(); v != "" {
- // if we are a stubs variant, just use the Bazel stubs target
- label = label + "_stub_libs-" + v
- }
- bazelCtx := ctx.Config().BazelContext
- ccInfo, err := bazelCtx.GetCcInfo(label, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx)))
- if err != nil {
- ctx.ModuleErrorf("Error getting Bazel CcInfo: %s", err)
- return
- }
-
- if handler.module.static() {
- handler.generateStaticBazelBuildActions(ctx, label, ccInfo)
- } else if handler.module.Shared() {
- handler.generateSharedBazelBuildActions(ctx, label, ccInfo)
- } else {
- ctx.ModuleErrorf("Unhandled bazel case for %s (neither shared nor static!)", ctx.ModuleName())
- }
-
- handler.module.linker.(*libraryDecorator).setFlagExporterInfoFromCcInfo(ctx, ccInfo)
- handler.module.maybeUnhideFromMake()
-
- if i, ok := handler.module.linker.(snapshotLibraryInterface); ok {
- // Dependencies on this library will expect collectedSnapshotHeaders to
- // be set, otherwise validation will fail. For now, set this to an empty
- // list.
- // TODO(b/190533363): More closely mirror the collectHeadersForSnapshot
- // implementation.
- i.(*libraryDecorator).collectedSnapshotHeaders = android.Paths{}
- }
-
- handler.module.setAndroidMkVariablesFromCquery(ccInfo.CcAndroidMkInfo)
-
- cctx := moduleContextFromAndroidModuleContext(ctx, handler.module)
- addStubDependencyProviders(cctx)
-}
-
-func (library *libraryDecorator) setFlagExporterInfoFromCcInfo(ctx android.ModuleContext, ccInfo cquery.CcInfo) {
- flagExporterInfo := flagExporterInfoFromCcInfo(ctx, ccInfo)
- // flag exporters consolidates properties like includes, flags, dependencies that should be
- // exported from this module to other modules
- ctx.SetProvider(FlagExporterInfoProvider, flagExporterInfo)
- // Store flag info to be passed along to androidmk
- // TODO(b/184387147): Androidmk should be done in Bazel, not Soong.
- library.flagExporterInfo = &flagExporterInfo
-}
-
func GlobHeadersForSnapshot(ctx android.ModuleContext, paths android.Paths) android.Paths {
ret := android.Paths{}
@@ -1028,11 +443,6 @@
continue
}
- // Filter out the generated headers from bazel.
- if strings.HasPrefix(dir, android.PathForBazelOut(ctx, "bazel-out").String()) {
- continue
- }
-
// libeigen wrongly exports the root directory "external/eigen". But only two
// subdirectories "Eigen" and "unsupported" contain exported header files. Even worse
// some of them have no extension. So we need special treatment for libeigen in order
@@ -1462,12 +872,18 @@
func (library *libraryDecorator) getLibName(ctx BaseModuleContext) string {
name := library.getLibNameHelper(ctx.baseModuleName(), ctx.inVendor(), ctx.inProduct())
+ // Replace name with VNDK ext as original lib only when VNDK is enabled
if ctx.IsVndkExt() {
- // vndk-ext lib should have the same name with original lib
- ctx.VisitDirectDepsWithTag(vndkExtDepTag, func(module android.Module) {
- originalName := module.(*Module).outputFile.Path()
- name = strings.TrimSuffix(originalName.Base(), originalName.Ext())
- })
+ if ctx.DeviceConfig().VndkVersion() != "" {
+ // vndk-ext lib should have the same name with original lib
+ ctx.VisitDirectDepsWithTag(vndkExtDepTag, func(module android.Module) {
+ originalName := module.(*Module).outputFile.Path()
+ name = strings.TrimSuffix(originalName.Base(), originalName.Ext())
+ })
+ } else {
+ // TODO(b/320208784) : Suggest a solution for former VNDK-ext libraries before VNDK deprecation.
+ log.Printf("VNDK Extension on module %s will not be available once VNDK is deprecated", ctx.baseModuleName())
+ }
}
if ctx.Host() && Bool(library.Properties.Unique_host_soname) {
@@ -1558,6 +974,10 @@
if library.baseLinker.Properties.crt() {
deps.CrtBegin = append(deps.CrtBegin, ctx.toolchain().CrtBeginSharedLibrary()...)
deps.CrtEnd = append(deps.CrtEnd, ctx.toolchain().CrtEndSharedLibrary()...)
+
+ }
+ if library.baseLinker.Properties.crtPadSegment() {
+ deps.CrtEnd = append(deps.CrtEnd, ctx.toolchain().CrtPadSegmentSharedLibrary()...)
}
deps.WholeStaticLibs = append(deps.WholeStaticLibs, library.SharedProperties.Shared.Whole_static_libs...)
deps.StaticLibs = append(deps.StaticLibs, library.SharedProperties.Shared.Static_libs...)
@@ -1633,6 +1053,40 @@
return specifiedDeps
}
+func (library *libraryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ if library.static() {
+ moduleInfoJSON.Class = []string{"STATIC_LIBRARIES"}
+ moduleInfoJSON.Uninstallable = true
+ } else if library.shared() {
+ moduleInfoJSON.Class = []string{"SHARED_LIBRARIES"}
+ } else if library.header() {
+ moduleInfoJSON.Class = []string{"HEADER_LIBRARIES"}
+ moduleInfoJSON.Uninstallable = true
+ }
+
+ if library.buildStubs() && library.stubsVersion() != "" {
+ moduleInfoJSON.SubName += "." + library.stubsVersion()
+ }
+
+ // If a library providing a stub is included in an APEX, the private APIs of the library
+ // is accessible only inside the APEX. From outside of the APEX, clients can only use the
+ // public APIs via the stub. To enforce this, the (latest version of the) stub gets the
+ // name of the library. The impl library instead gets the `.bootstrap` suffix to so that
+ // they can be exceptionally used directly when APEXes are not available (e.g. during the
+ // very early stage in the boot process).
+ if len(library.Properties.Stubs.Versions) > 0 && !ctx.Host() && ctx.notInPlatform() &&
+ !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() && !ctx.useVndk() && !ctx.static() {
+ if library.buildStubs() && library.isLatestStubVersion() {
+ moduleInfoJSON.SubName = ""
+ }
+ if !library.buildStubs() {
+ moduleInfoJSON.SubName = ".bootstrap"
+ }
+ }
+
+ library.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON)
+}
+
func (library *libraryDecorator) linkStatic(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
@@ -1663,7 +1117,7 @@
ctx.CheckbuildFile(outputFile)
if library.static() {
- ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+ android.SetProvider(ctx, StaticLibraryInfoProvider, StaticLibraryInfo{
StaticLibrary: outputFile,
ReuseObjects: library.reuseObjects,
Objects: library.objects,
@@ -1677,7 +1131,7 @@
}
if library.header() {
- ctx.SetProvider(HeaderLibraryInfoProvider, HeaderLibraryInfo{})
+ android.SetProvider(ctx, HeaderLibraryInfoProvider, HeaderLibraryInfo{})
}
return outputFile
@@ -1795,6 +1249,17 @@
}
}
+ // Generate an output file for dist as if strip: "all" is set on the module.
+ // Currently this is for layoutlib release process only.
+ for _, dist := range ctx.Module().(*Module).Dists() {
+ if dist.Tag != nil && *dist.Tag == "stripped_all" {
+ strippedAllOutputFile := android.PathForModuleOut(ctx, "stripped_all", fileName)
+ transformStrip(ctx, outputFile, strippedAllOutputFile, StripFlags{Toolchain: flags.Toolchain})
+ library.strippedAllOutputFile = strippedAllOutputFile
+ break
+ }
+ }
+
sharedLibs := deps.EarlySharedLibs
sharedLibs = append(sharedLibs, deps.SharedLibs...)
sharedLibs = append(sharedLibs, deps.LateSharedLibs...)
@@ -1816,11 +1281,11 @@
var transitiveStaticLibrariesForOrdering *android.DepSet[android.Path]
if static := ctx.GetDirectDepsWithTag(staticVariantTag); len(static) > 0 {
- s := ctx.OtherModuleProvider(static[0], StaticLibraryInfoProvider).(StaticLibraryInfo)
+ s, _ := android.OtherModuleProvider(ctx, static[0], StaticLibraryInfoProvider)
transitiveStaticLibrariesForOrdering = s.TransitiveStaticLibrariesForOrdering
}
- ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+ android.SetProvider(ctx, SharedLibraryInfoProvider, SharedLibraryInfo{
TableOfContents: android.OptionalPathForPath(tocFile),
SharedLibrary: unstrippedOutputFile,
TransitiveStaticLibrariesForOrdering: transitiveStaticLibrariesForOrdering,
@@ -1837,15 +1302,15 @@
if len(stubs) > 0 {
var stubsInfo []SharedStubLibrary
for _, stub := range stubs {
- stubInfo := ctx.OtherModuleProvider(stub, SharedLibraryInfoProvider).(SharedLibraryInfo)
- flagInfo := ctx.OtherModuleProvider(stub, FlagExporterInfoProvider).(FlagExporterInfo)
+ stubInfo, _ := android.OtherModuleProvider(ctx, stub, SharedLibraryInfoProvider)
+ flagInfo, _ := android.OtherModuleProvider(ctx, stub, FlagExporterInfoProvider)
stubsInfo = append(stubsInfo, SharedStubLibrary{
Version: moduleLibraryInterface(stub).stubsVersion(),
SharedLibraryInfo: stubInfo,
FlagExporterInfo: flagInfo,
})
}
- ctx.SetProvider(SharedLibraryStubsProvider, SharedLibraryStubsInfo{
+ android.SetProvider(ctx, SharedLibraryStubsProvider, SharedLibraryStubsInfo{
SharedStubLibraries: stubsInfo,
IsLLNDK: ctx.IsLlndk(),
})
@@ -1856,6 +1321,10 @@
return library.unstrippedOutputFile
}
+func (library *libraryDecorator) strippedAllOutputFilePath() android.Path {
+ return library.strippedAllOutputFile
+}
+
func (library *libraryDecorator) disableStripping() {
library.stripper.StripProperties.Strip.None = BoolPtr(true)
}
@@ -1885,11 +1354,11 @@
fileName+".lsdump")
}
-func getRefAbiDumpDir(isNdk, isVndk bool) string {
+func getRefAbiDumpDir(isNdk, isLlndk bool) string {
var dirName string
if isNdk {
dirName = "ndk"
- } else if isVndk {
+ } else if isLlndk {
dirName = "vndk"
} else {
dirName = "platform"
@@ -1916,11 +1385,8 @@
}
}
-func currRefAbiDumpVersion(ctx ModuleContext, isVndk bool) string {
- if isVndk {
- // Each version of VNDK is independent, so follow the VNDK version which is the codename or PLATFORM_SDK_VERSION.
- return ctx.Module().(*Module).VndkVersion()
- } else if ctx.Config().PlatformSdkFinal() {
+func currRefAbiDumpVersion(ctx ModuleContext) string {
+ if ctx.Config().PlatformSdkFinal() {
// After sdk finalization, the ABI of the latest API level must be consistent with the source code,
// so choose PLATFORM_SDK_VERSION as the current version.
return ctx.Config().PlatformSdkVersion().String()
@@ -1962,20 +1428,20 @@
func (library *libraryDecorator) crossVersionAbiDiff(ctx android.ModuleContext, referenceDump android.Path,
baseName string, isLlndkOrNdk bool, sourceVersion, prevVersion string) {
- errorMessage := "error: Please follow https://android.googlesource.com/platform/development/+/master/vndk/tools/header-checker/README.md#configure-cross_version-abi-check to resolve the ABI difference between your source code and version " + prevVersion + "."
+ errorMessage := "error: Please follow https://android.googlesource.com/platform/development/+/main/vndk/tools/header-checker/README.md#configure-cross_version-abi-check to resolve the ABI difference between your source code and version " + prevVersion + "."
library.sourceAbiDiff(ctx, referenceDump, baseName, prevVersion,
isLlndkOrNdk, true /* allowExtensions */, sourceVersion, errorMessage)
}
func (library *libraryDecorator) sameVersionAbiDiff(ctx android.ModuleContext, referenceDump android.Path,
- baseName string, isLlndkOrNdk, allowExtensions bool) {
+ baseName string, isLlndkOrNdk bool) {
libName := strings.TrimSuffix(baseName, filepath.Ext(baseName))
errorMessage := "error: Please update ABI references with: $$ANDROID_BUILD_TOP/development/vndk/tools/header-checker/utils/create_reference_dumps.py -l " + libName
library.sourceAbiDiff(ctx, referenceDump, baseName, "",
- isLlndkOrNdk, allowExtensions, "current", errorMessage)
+ isLlndkOrNdk, false /* allowExtensions */, "current", errorMessage)
}
func (library *libraryDecorator) optInAbiDiff(ctx android.ModuleContext, referenceDump android.Path,
@@ -2004,38 +1470,38 @@
}
exportedHeaderFlags := strings.Join(SourceAbiFlags, " ")
headerAbiChecker := library.getHeaderAbiCheckerProperties(ctx)
+ // The logic must be consistent with classifySourceAbiDump.
+ isNdk := ctx.isNdk(ctx.Config())
+ isLlndk := ctx.isImplementationForLLNDKPublic()
+ currVersion := currRefAbiDumpVersion(ctx)
library.sAbiOutputFile = transformDumpToLinkedDump(ctx, objs.sAbiDumpFiles, soFile, fileName, exportedHeaderFlags,
android.OptionalPathForModuleSrc(ctx, library.symbolFileForAbiCheck(ctx)),
headerAbiChecker.Exclude_symbol_versions,
- headerAbiChecker.Exclude_symbol_tags)
+ headerAbiChecker.Exclude_symbol_tags,
+ currVersion)
- addLsdumpPath(classifySourceAbiDump(ctx) + ":" + library.sAbiOutputFile.String())
+ for _, tag := range classifySourceAbiDump(ctx) {
+ addLsdumpPath(tag + ":" + library.sAbiOutputFile.String())
+ }
- // The logic must be consistent with classifySourceAbiDump.
- isVndk := ctx.useVndk() && ctx.isVndk()
- isNdk := ctx.isNdk(ctx.Config())
- isLlndk := ctx.isImplementationForLLNDKPublic()
- dumpDir := getRefAbiDumpDir(isNdk, isVndk)
+ dumpDir := getRefAbiDumpDir(isNdk, isLlndk)
binderBitness := ctx.DeviceConfig().BinderBitness()
- // If NDK or PLATFORM library, check against previous version ABI.
- if !isVndk {
- prevVersionInt := prevRefAbiDumpVersion(ctx, dumpDir)
- prevVersion := strconv.Itoa(prevVersionInt)
- prevDumpDir := filepath.Join(dumpDir, prevVersion, binderBitness)
- prevDumpFile := getRefAbiDumpFile(ctx, prevDumpDir, fileName)
- if prevDumpFile.Valid() {
- library.crossVersionAbiDiff(ctx, prevDumpFile.Path(),
- fileName, isLlndk || isNdk,
- strconv.Itoa(prevVersionInt+1), prevVersion)
- }
+ // Check against the previous version.
+ prevVersionInt := prevRefAbiDumpVersion(ctx, dumpDir)
+ prevVersion := strconv.Itoa(prevVersionInt)
+ prevDumpDir := filepath.Join(dumpDir, prevVersion, binderBitness)
+ prevDumpFile := getRefAbiDumpFile(ctx, prevDumpDir, fileName)
+ if prevDumpFile.Valid() {
+ library.crossVersionAbiDiff(ctx, prevDumpFile.Path(),
+ fileName, isLlndk || isNdk,
+ strconv.Itoa(prevVersionInt+1), prevVersion)
}
// Check against the current version.
- currVersion := currRefAbiDumpVersion(ctx, isVndk)
currDumpDir := filepath.Join(dumpDir, currVersion, binderBitness)
currDumpFile := getRefAbiDumpFile(ctx, currDumpDir, fileName)
if currDumpFile.Valid() {
library.sameVersionAbiDiff(ctx, currDumpFile.Path(),
- fileName, isLlndk || isNdk, ctx.IsVndkExt())
+ fileName, isLlndk || isNdk)
}
// Check against the opt-in reference dumps.
for i, optInDumpDir := range headerAbiChecker.Ref_dump_dirs {
@@ -2295,7 +1761,7 @@
// do not install vndk libs
// vndk libs are packaged into VNDK APEX
- if ctx.isVndk() && !ctx.IsVndkExt() && !ctx.Config().IsVndkDeprecated() {
+ if ctx.isVndk() && !ctx.IsVndkExt() && !ctx.Config().IsVndkDeprecated() && !ctx.inProduct() {
return
}
} else if library.hasStubsVariants() && !ctx.Host() && ctx.directlyInAnyApex() {
@@ -2319,7 +1785,7 @@
}
if Bool(library.Properties.Static_ndk_lib) && library.static() &&
- !ctx.useVndk() && !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() && ctx.Device() &&
+ !ctx.InVendorOrProduct() && !ctx.inRamdisk() && !ctx.inVendorRamdisk() && !ctx.inRecovery() && ctx.Device() &&
library.baseLinker.sanitize.isUnsanitizedVariant() &&
ctx.isForPlatform() && !ctx.isPreventInstall() {
installPath := getUnversionedLibraryInstallPath(ctx).Join(ctx, file.Base())
@@ -2439,7 +1905,7 @@
return nil
}
- if library.hasLLNDKStubs() && ctx.Module().(*Module).UseVndk() {
+ if library.hasLLNDKStubs() && ctx.Module().(*Module).InVendorOrProduct() {
// LLNDK libraries only need a single stubs variant.
return []string{android.FutureApiLevel.String()}
}
@@ -2713,7 +2179,7 @@
// normalizeVersions modifies `versions` in place, so that each raw version
// string becomes its normalized canonical form.
// Validates that the versions in `versions` are specified in least to greatest order.
-func normalizeVersions(ctx android.BazelConversionPathContext, versions []string) {
+func normalizeVersions(ctx android.BaseModuleContext, versions []string) {
var previous android.ApiLevel
for i, v := range versions {
ver, err := android.ApiLevelFromUser(ctx, v)
@@ -2884,250 +2350,3 @@
return outputFile
}
-
-func bp2buildParseAbiCheckerProps(ctx android.TopDownMutatorContext, module *Module) bazelCcHeaderAbiCheckerAttributes {
- lib, ok := module.linker.(*libraryDecorator)
- if !ok {
- return bazelCcHeaderAbiCheckerAttributes{}
- }
-
- abiChecker := lib.getHeaderAbiCheckerProperties(ctx)
-
- abiCheckerAttrs := bazelCcHeaderAbiCheckerAttributes{
- Abi_checker_enabled: abiChecker.Enabled,
- Abi_checker_exclude_symbol_versions: abiChecker.Exclude_symbol_versions,
- Abi_checker_exclude_symbol_tags: abiChecker.Exclude_symbol_tags,
- Abi_checker_check_all_apis: abiChecker.Check_all_apis,
- Abi_checker_diff_flags: abiChecker.Diff_flags,
- }
- if abiChecker.Symbol_file != nil {
- symbolFile := android.BazelLabelForModuleSrcSingle(ctx, *abiChecker.Symbol_file)
- abiCheckerAttrs.Abi_checker_symbol_file = &symbolFile
- }
-
- return abiCheckerAttrs
-}
-
-func sharedOrStaticLibraryBp2Build(ctx android.TopDownMutatorContext, module *Module, isStatic bool) {
- baseAttributes := bp2BuildParseBaseProps(ctx, module)
- compilerAttrs := baseAttributes.compilerAttributes
- linkerAttrs := baseAttributes.linkerAttributes
-
- exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, &compilerAttrs.includes)
- includeAttrs := includesAttributes{
- Export_includes: exportedIncludes.Includes,
- Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
- Export_system_includes: exportedIncludes.SystemIncludes,
- Local_includes: compilerAttrs.localIncludes,
- Absolute_includes: compilerAttrs.absoluteIncludes,
- }
-
- // Append shared/static{} stanza properties. These won't be specified on
- // cc_library_* itself, but may be specified in cc_defaults that this module
- // depends on.
- libSharedOrStaticAttrs := bp2BuildParseLibProps(ctx, module, isStatic)
-
- compilerAttrs.srcs.Append(libSharedOrStaticAttrs.Srcs)
- compilerAttrs.cSrcs.Append(libSharedOrStaticAttrs.Srcs_c)
- compilerAttrs.asSrcs.Append(libSharedOrStaticAttrs.Srcs_as)
- compilerAttrs.copts.Append(libSharedOrStaticAttrs.Copts)
-
- linkerAttrs.deps.Append(libSharedOrStaticAttrs.Deps)
- linkerAttrs.implementationDeps.Append(libSharedOrStaticAttrs.Implementation_deps)
- linkerAttrs.dynamicDeps.Append(libSharedOrStaticAttrs.Dynamic_deps)
- linkerAttrs.implementationDynamicDeps.Append(libSharedOrStaticAttrs.Implementation_dynamic_deps)
- linkerAttrs.systemDynamicDeps.Append(libSharedOrStaticAttrs.System_dynamic_deps)
-
- asFlags := compilerAttrs.asFlags
- if compilerAttrs.asSrcs.IsEmpty() {
- // Skip asflags for BUILD file simplicity if there are no assembly sources.
- asFlags = bazel.MakeStringListAttribute(nil)
- }
-
- features := baseAttributes.features.Clone().Append(libSharedOrStaticAttrs.Features)
- features.DeduplicateAxesFromBase()
-
- commonAttrs := staticOrSharedAttributes{
- Srcs: compilerAttrs.srcs,
- Srcs_c: compilerAttrs.cSrcs,
- Srcs_as: compilerAttrs.asSrcs,
- Copts: compilerAttrs.copts,
- Hdrs: compilerAttrs.hdrs,
-
- Deps: linkerAttrs.deps,
- Implementation_deps: linkerAttrs.implementationDeps,
- Dynamic_deps: linkerAttrs.dynamicDeps,
- Implementation_dynamic_deps: linkerAttrs.implementationDynamicDeps,
- Whole_archive_deps: linkerAttrs.wholeArchiveDeps,
- Implementation_whole_archive_deps: linkerAttrs.implementationWholeArchiveDeps,
- System_dynamic_deps: linkerAttrs.systemDynamicDeps,
- sdkAttributes: bp2BuildParseSdkAttributes(module),
- Runtime_deps: linkerAttrs.runtimeDeps,
- Native_coverage: baseAttributes.Native_coverage,
- Additional_compiler_inputs: compilerAttrs.additionalCompilerInputs,
- }
-
- module.convertTidyAttributes(ctx, &commonAttrs.tidyAttributes)
-
- var attrs interface{}
- if isStatic {
- commonAttrs.Deps.Add(baseAttributes.protoDependency)
- var alwayslink *bool
- if _, ok := alwaysLinkLibraries[module.Name()]; ok && isStatic {
- alwayslink = proptools.BoolPtr(true)
- }
- attrs = &bazelCcLibraryStaticAttributes{
- staticOrSharedAttributes: commonAttrs,
- Rtti: compilerAttrs.rtti,
- Stl: compilerAttrs.stl,
- Cpp_std: compilerAttrs.cppStd,
- C_std: compilerAttrs.cStd,
-
- includesAttributes: includeAttrs,
-
- Cppflags: compilerAttrs.cppFlags,
- Conlyflags: compilerAttrs.conlyFlags,
- Asflags: asFlags,
-
- Alwayslink: alwayslink,
- Features: *features,
- }
-
- } else {
- commonAttrs.Dynamic_deps.Add(baseAttributes.protoDependency)
-
- sharedLibAttrs := &bazelCcLibrarySharedAttributes{
- staticOrSharedAttributes: commonAttrs,
-
- Cppflags: compilerAttrs.cppFlags,
- Conlyflags: compilerAttrs.conlyFlags,
- Asflags: asFlags,
-
- Linkopts: linkerAttrs.linkopts,
- Use_version_lib: linkerAttrs.useVersionLib,
-
- Rtti: compilerAttrs.rtti,
- Stl: compilerAttrs.stl,
- Cpp_std: compilerAttrs.cppStd,
- C_std: compilerAttrs.cStd,
-
- includesAttributes: includeAttrs,
-
- Additional_linker_inputs: linkerAttrs.additionalLinkerInputs,
-
- Strip: stripAttrsFromLinkerAttrs(&linkerAttrs),
-
- Features: *features,
-
- Stem: compilerAttrs.stem,
- Suffix: compilerAttrs.suffix,
-
- bazelCcHeaderAbiCheckerAttributes: bp2buildParseAbiCheckerProps(ctx, module),
-
- Fdo_profile: compilerAttrs.fdoProfile,
- }
- if compilerAttrs.stubsSymbolFile != nil && len(compilerAttrs.stubsVersions.Value) > 0 {
- sharedLibAttrs.Stubs_symbol_file = compilerAttrs.stubsSymbolFile
- }
- attrs = sharedLibAttrs
- }
-
- var modType string
- if isStatic {
- modType = "cc_library_static"
- } else {
- modType = "cc_library_shared"
- createStubsBazelTargetIfNeeded(ctx, module, compilerAttrs, exportedIncludes, baseAttributes)
- }
- props := bazel.BazelTargetModuleProperties{
- Rule_class: modType,
- Bzl_load_location: fmt.Sprintf("//build/bazel/rules/cc:%s.bzl", modType),
- }
-
- tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name(), Tags: tags}, attrs)
-}
-
-type includesAttributes struct {
- Export_includes bazel.StringListAttribute
- Export_absolute_includes bazel.StringListAttribute
- Export_system_includes bazel.StringListAttribute
- Local_includes bazel.StringListAttribute
- Absolute_includes bazel.StringListAttribute
-}
-
-// TODO(b/199902614): Can this be factored to share with the other Attributes?
-type bazelCcLibraryStaticAttributes struct {
- staticOrSharedAttributes
- includesAttributes
-
- Use_version_lib bazel.BoolAttribute
- Rtti bazel.BoolAttribute
- Stl *string
- Cpp_std *string
- C_std *string
-
- Hdrs bazel.LabelListAttribute
-
- Cppflags bazel.StringListAttribute
- Conlyflags bazel.StringListAttribute
- Asflags bazel.StringListAttribute
-
- Alwayslink *bool
- Features bazel.StringListAttribute
-}
-
-// TODO(b/199902614): Can this be factored to share with the other Attributes?
-type bazelCcLibrarySharedAttributes struct {
- staticOrSharedAttributes
- includesAttributes
-
- Linkopts bazel.StringListAttribute
- Use_version_lib bazel.BoolAttribute
-
- Rtti bazel.BoolAttribute
- Stl *string
- Cpp_std *string
- C_std *string
-
- Hdrs bazel.LabelListAttribute
-
- Strip stripAttributes
- Additional_linker_inputs bazel.LabelListAttribute
-
- Cppflags bazel.StringListAttribute
- Conlyflags bazel.StringListAttribute
- Asflags bazel.StringListAttribute
-
- Features bazel.StringListAttribute
-
- Stubs_symbol_file *string
-
- Inject_bssl_hash bazel.BoolAttribute
-
- Stem bazel.StringAttribute
- Suffix bazel.StringAttribute
-
- bazelCcHeaderAbiCheckerAttributes
-
- Fdo_profile bazel.LabelAttribute
-}
-
-type bazelCcStubSuiteAttributes struct {
- Symbol_file *string
- Versions bazel.StringListAttribute
- Export_includes bazel.StringListAttribute
- Source_library_label *string
- Soname *string
- Deps bazel.LabelListAttribute
-}
-
-type bazelCcHeaderAbiCheckerAttributes struct {
- Abi_checker_enabled *bool
- Abi_checker_symbol_file *bazel.Label
- Abi_checker_exclude_symbol_versions []string
- Abi_checker_exclude_symbol_tags []string
- Abi_checker_check_all_apis *bool
- Abi_checker_diff_flags []string
-}
diff --git a/cc/library_headers.go b/cc/library_headers.go
index ce9c4aa..98533b2 100644
--- a/cc/library_headers.go
+++ b/cc/library_headers.go
@@ -15,11 +15,7 @@
package cc
import (
- "github.com/google/blueprint/proptools"
-
"android/soong/android"
- "android/soong/bazel"
- "android/soong/bazel/cquery"
)
func init() {
@@ -50,52 +46,6 @@
ctx.RegisterModuleType("cc_prebuilt_library_headers", prebuiltLibraryHeaderFactory)
}
-type libraryHeaderBazelHandler struct {
- module *Module
- library *libraryDecorator
-}
-
-var _ BazelHandler = (*libraryHeaderBazelHandler)(nil)
-
-func (handler *libraryHeaderBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
- bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(label, cquery.GetCcInfo, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx)))
-}
-
-func (h *libraryHeaderBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
- bazelCtx := ctx.Config().BazelContext
- ccInfo, err := bazelCtx.GetCcInfo(label, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx)))
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- return
- }
-
- outputPaths := ccInfo.OutputFiles
- if len(outputPaths) != 1 {
- ctx.ModuleErrorf("expected exactly one output file for %q, but got %q", label, outputPaths)
- return
- }
-
- var outputPath android.Path = android.PathForBazelOut(ctx, outputPaths[0])
- if len(ccInfo.TidyFiles) > 0 {
- h.module.tidyFiles = android.PathsForBazelOut(ctx, ccInfo.TidyFiles)
- outputPath = android.AttachValidationActions(ctx, outputPath, h.module.tidyFiles)
- }
- h.module.outputFile = android.OptionalPathForPath(outputPath)
-
- // HeaderLibraryInfo is an empty struct to indicate to dependencies that this is a header library
- ctx.SetProvider(HeaderLibraryInfoProvider, HeaderLibraryInfo{})
-
- h.library.setFlagExporterInfoFromCcInfo(ctx, ccInfo)
-
- // Dependencies on this library will expect collectedSnapshotHeaders to be set, otherwise
- // validation will fail. For now, set this to an empty list.
- // TODO(cparsons): More closely mirror the collectHeadersForSnapshot implementation.
- h.library.collectedSnapshotHeaders = android.Paths{}
-
- h.module.setAndroidMkVariablesFromCquery(ccInfo.CcAndroidMkInfo)
-}
-
// cc_library_headers contains a set of c/c++ headers which are imported by
// other soong cc modules using the header_libs property. For best practices,
// use export_include_dirs property or LOCAL_EXPORT_C_INCLUDE_DIRS for
@@ -104,8 +54,6 @@
module, library := NewLibrary(android.HostAndDeviceSupported)
library.HeaderOnly()
module.sdkMemberTypes = []android.SdkMemberType{headersLibrarySdkMemberType}
- module.bazelable = true
- module.bazelHandler = &libraryHeaderBazelHandler{module: module, library: library}
return module.Init()
}
@@ -113,163 +61,5 @@
func prebuiltLibraryHeaderFactory() android.Module {
module, library := NewPrebuiltLibrary(android.HostAndDeviceSupported, "")
library.HeaderOnly()
- module.bazelable = true
- module.bazelHandler = &ccLibraryBazelHandler{module: module}
return module.Init()
}
-
-type bazelCcLibraryHeadersAttributes struct {
- Hdrs bazel.LabelListAttribute
- Export_includes bazel.StringListAttribute
- Export_absolute_includes bazel.StringListAttribute
- Export_system_includes bazel.StringListAttribute
- Deps bazel.LabelListAttribute
- Implementation_deps bazel.LabelListAttribute
- System_dynamic_deps bazel.LabelListAttribute
- sdkAttributes
-}
-
-func libraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) {
- baseAttributes := bp2BuildParseBaseProps(ctx, module)
- exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, &baseAttributes.includes)
- linkerAttrs := baseAttributes.linkerAttributes
- (&linkerAttrs.deps).Append(linkerAttrs.dynamicDeps)
- (&linkerAttrs.deps).Append(linkerAttrs.wholeArchiveDeps)
-
- attrs := &bazelCcLibraryHeadersAttributes{
- Export_includes: exportedIncludes.Includes,
- Export_absolute_includes: exportedIncludes.AbsoluteIncludes,
- Export_system_includes: exportedIncludes.SystemIncludes,
- Deps: linkerAttrs.deps,
- System_dynamic_deps: linkerAttrs.systemDynamicDeps,
- Hdrs: baseAttributes.hdrs,
- sdkAttributes: bp2BuildParseSdkAttributes(module),
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "cc_library_headers",
- Bzl_load_location: "//build/bazel/rules/cc:cc_library_headers.bzl",
- }
-
- tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: module.Name(),
- Tags: tags,
- }, attrs)
-}
-
-// Append .contribution suffix to input labels
-func apiBazelTargets(ll bazel.LabelList) bazel.LabelList {
- labels := make([]bazel.Label, 0)
- for _, l := range ll.Includes {
- labels = append(labels, bazel.Label{
- Label: android.ApiContributionTargetName(l.Label),
- })
- }
- return bazel.MakeLabelList(labels)
-}
-
-func apiLibraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) {
- // cc_api_library_headers have a 1:1 mapping to arch/no-arch
- // For API export, create a top-level arch-agnostic target and list the arch-specific targets as its deps
-
- // arch-agnostic includes
- apiIncludes := getModuleLibApiIncludes(ctx, module)
- // arch and os specific includes
- archApiIncludes, androidOsIncludes := archOsSpecificApiIncludes(ctx, module)
- for _, arch := range allArches { // sorted iteration
- archApiInclude := archApiIncludes[arch]
- if !archApiInclude.isEmpty() {
- createApiHeaderTarget(ctx, archApiInclude)
- apiIncludes.addDep(archApiInclude.name)
- }
- }
- // os==android includes
- if !androidOsIncludes.isEmpty() {
- createApiHeaderTarget(ctx, androidOsIncludes)
- apiIncludes.addDep(androidOsIncludes.name)
- }
-
- if !apiIncludes.isEmpty() {
- // override the name from <mod>.module-libapi.headers --> <mod>.contribution
- apiIncludes.name = android.ApiContributionTargetName(module.Name())
- createApiHeaderTarget(ctx, apiIncludes)
- }
-}
-
-func createApiHeaderTarget(ctx android.TopDownMutatorContext, includes apiIncludes) {
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "cc_api_library_headers",
- Bzl_load_location: "//build/bazel/rules/apis:cc_api_contribution.bzl",
- }
- ctx.CreateBazelTargetModule(
- props,
- android.CommonAttributes{
- Name: includes.name,
- SkipData: proptools.BoolPtr(true),
- },
- &includes.attrs,
- )
-}
-
-var (
- allArches = []string{"arm", "arm64", "x86", "x86_64"}
-)
-
-type archApiIncludes map[string]apiIncludes
-
-func archOsSpecificApiIncludes(ctx android.TopDownMutatorContext, module *Module) (archApiIncludes, apiIncludes) {
- baseProps := bp2BuildParseBaseProps(ctx, module)
- i := bp2BuildParseExportedIncludes(ctx, module, &baseProps.includes)
- archRet := archApiIncludes{}
- for _, arch := range allArches {
- includes := i.Includes.SelectValue(
- bazel.ArchConfigurationAxis,
- arch)
- systemIncludes := i.SystemIncludes.SelectValue(
- bazel.ArchConfigurationAxis,
- arch)
- deps := baseProps.deps.SelectValue(
- bazel.ArchConfigurationAxis,
- arch)
- attrs := bazelCcLibraryHeadersAttributes{
- Export_includes: bazel.MakeStringListAttribute(includes),
- Export_system_includes: bazel.MakeStringListAttribute(systemIncludes),
- }
- apiDeps := apiBazelTargets(deps)
- if !apiDeps.IsEmpty() {
- attrs.Deps = bazel.MakeLabelListAttribute(apiDeps)
- }
- apiIncludes := apiIncludes{
- name: android.ApiContributionTargetName(module.Name()) + "." + arch,
- attrs: bazelCcApiLibraryHeadersAttributes{
- bazelCcLibraryHeadersAttributes: attrs,
- Arch: proptools.StringPtr(arch),
- },
- }
- archRet[arch] = apiIncludes
- }
-
- // apiIncludes for os == Android
- androidOsDeps := baseProps.deps.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid)
- androidOsAttrs := bazelCcLibraryHeadersAttributes{
- Export_includes: bazel.MakeStringListAttribute(
- i.Includes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid),
- ),
- Export_system_includes: bazel.MakeStringListAttribute(
- i.SystemIncludes.SelectValue(bazel.OsConfigurationAxis, bazel.OsAndroid),
- ),
- }
- androidOsApiDeps := apiBazelTargets(androidOsDeps)
- if !androidOsApiDeps.IsEmpty() {
- androidOsAttrs.Deps = bazel.MakeLabelListAttribute(androidOsApiDeps)
- }
- osRet := apiIncludes{
- name: android.ApiContributionTargetName(module.Name()) + ".androidos",
- attrs: bazelCcApiLibraryHeadersAttributes{
- bazelCcLibraryHeadersAttributes: androidOsAttrs,
- },
- }
- return archRet, osRet
-}
diff --git a/cc/library_sdk_member.go b/cc/library_sdk_member.go
index e743bb6..a65b1ba 100644
--- a/cc/library_sdk_member.go
+++ b/cc/library_sdk_member.go
@@ -251,16 +251,9 @@
return &nativeLibInfoProperties{memberType: mt}
}
-func isBazelOutDirectory(p android.Path) bool {
- _, bazel := p.(android.BazelOutPath)
- return bazel
-}
-
func isGeneratedHeaderDirectory(p android.Path) bool {
_, gen := p.(android.WritablePath)
- // TODO(b/183213331): Here we assume that bazel-based headers are not generated; we need
- // to support generated headers in mixed builds.
- return gen && !isBazelOutDirectory(p)
+ return gen
}
type includeDirsProperty struct {
@@ -518,7 +511,7 @@
}
}
- exportedInfo := ctx.SdkModuleContext().OtherModuleProvider(variant, FlagExporterInfoProvider).(FlagExporterInfo)
+ exportedInfo, _ := android.OtherModuleProvider(ctx.SdkModuleContext(), variant, FlagExporterInfoProvider)
// Separate out the generated include dirs (which are arch specific) from the
// include dirs (which may not be).
diff --git a/cc/library_stub.go b/cc/library_stub.go
index 18d3f21..aab6664 100644
--- a/cc/library_stub.go
+++ b/cc/library_stub.go
@@ -48,7 +48,7 @@
return
}
- if m.UseVndk() && apiLibrary.hasLLNDKStubs() {
+ if m.InVendorOrProduct() && apiLibrary.hasLLNDKStubs() {
// Add LLNDK variant dependency
if inList("llndk", apiLibrary.properties.Variants) {
variantName := BuildApiVariantName(m.BaseModuleName(), "llndk", "")
@@ -193,7 +193,7 @@
}
}
- if m.UseVndk() && d.hasLLNDKStubs() {
+ if m.InVendorOrProduct() && d.hasLLNDKStubs() {
// LLNDK variant
load_cc_variant(BuildApiVariantName(m.BaseModuleName(), "llndk", ""))
} else if m.IsSdkVariant() {
@@ -244,7 +244,7 @@
},
})
- ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+ android.SetProvider(ctx, SharedLibraryInfoProvider, SharedLibraryInfo{
SharedLibrary: outputFile,
Target: ctx.Target(),
@@ -262,15 +262,15 @@
if len(stubs) > 0 {
var stubsInfo []SharedStubLibrary
for _, stub := range stubs {
- stubInfo := ctx.OtherModuleProvider(stub, SharedLibraryInfoProvider).(SharedLibraryInfo)
- flagInfo := ctx.OtherModuleProvider(stub, FlagExporterInfoProvider).(FlagExporterInfo)
+ stubInfo, _ := android.OtherModuleProvider(ctx, stub, SharedLibraryInfoProvider)
+ flagInfo, _ := android.OtherModuleProvider(ctx, stub, FlagExporterInfoProvider)
stubsInfo = append(stubsInfo, SharedStubLibrary{
Version: moduleLibraryInterface(stub).stubsVersion(),
SharedLibraryInfo: stubInfo,
FlagExporterInfo: flagInfo,
})
}
- ctx.SetProvider(SharedLibraryStubsProvider, SharedLibraryStubsInfo{
+ android.SetProvider(ctx, SharedLibraryStubsProvider, SharedLibraryStubsInfo{
SharedStubLibraries: stubsInfo,
IsLLNDK: ctx.IsLlndk(),
@@ -312,7 +312,7 @@
}
}
- if d.hasLLNDKStubs() && m.UseVndk() {
+ if d.hasLLNDKStubs() && m.InVendorOrProduct() {
// LLNDK libraries only need a single stubs variant.
return []string{android.FutureApiLevel.String()}
}
diff --git a/cc/library_test.go b/cc/library_test.go
index dbe2be8..2ed2d76 100644
--- a/cc/library_test.go
+++ b/cc/library_test.go
@@ -19,7 +19,6 @@
"testing"
"android/soong/android"
- "android/soong/bazel/cquery"
)
func TestLibraryReuse(t *testing.T) {
@@ -246,137 +245,6 @@
testCcError(t, `"libfoo" .*: versions: "X" could not be parsed as an integer and is not a recognized codename`, bp)
}
-func TestCcLibraryWithBazel(t *testing.T) {
- t.Parallel()
- bp := `
-cc_library {
- name: "foo",
- srcs: ["foo.cc"],
- bazel_module: { label: "//foo/bar:bar" },
-}`
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: "outputbase",
- LabelToCcInfo: map[string]cquery.CcInfo{
- "//foo/bar:bar": cquery.CcInfo{
- CcObjectFiles: []string{"foo.o"},
- Includes: []string{"include"},
- SystemIncludes: []string{"system_include"},
- Headers: []string{"foo.h"},
- RootDynamicLibraries: []string{"foo.so"},
- UnstrippedOutput: "foo_unstripped.so",
- },
- "//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{
- CcObjectFiles: []string{"foo.o"},
- Includes: []string{"include"},
- SystemIncludes: []string{"system_include"},
- Headers: []string{"foo.h"},
- RootStaticArchives: []string{"foo.a"},
- },
- },
- }
- ctx := testCcWithConfig(t, config)
-
- staticFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_static").Module()
- outputFiles, err := staticFoo.(android.OutputFileProducer).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
- }
-
- expectedOutputFiles := []string{"outputbase/execroot/__main__/foo.a"}
- android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
-
- flagExporter := ctx.ModuleProvider(staticFoo, FlagExporterInfoProvider).(FlagExporterInfo)
- android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs)
- android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs)
- android.AssertPathsRelativeToTopEquals(t, "exported headers", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.GeneratedHeaders)
- android.AssertPathsRelativeToTopEquals(t, "deps", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.Deps)
-
- sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
- outputFiles, err = sharedFoo.(android.OutputFileProducer).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_library outputfiles %s", err)
- }
- expectedOutputFiles = []string{"outputbase/execroot/__main__/foo.so"}
- android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
-
- android.AssertStringEquals(t, "unstripped shared library", "outputbase/execroot/__main__/foo_unstripped.so", sharedFoo.(*Module).linker.unstrippedOutputFilePath().String())
- flagExporter = ctx.ModuleProvider(sharedFoo, FlagExporterInfoProvider).(FlagExporterInfo)
- android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs)
- android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs)
- android.AssertPathsRelativeToTopEquals(t, "exported headers", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.GeneratedHeaders)
- android.AssertPathsRelativeToTopEquals(t, "deps", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.Deps)
-}
-
-func TestCcLibraryWithBazelValidations(t *testing.T) {
- t.Parallel()
- bp := `
-cc_library {
- name: "foo",
- srcs: ["foo.cc"],
- bazel_module: { label: "//foo/bar:bar" },
- tidy: true,
-}`
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: "outputbase",
- LabelToCcInfo: map[string]cquery.CcInfo{
- "//foo/bar:bar": cquery.CcInfo{
- CcObjectFiles: []string{"foo.o"},
- Includes: []string{"include"},
- SystemIncludes: []string{"system_include"},
- Headers: []string{"foo.h"},
- RootDynamicLibraries: []string{"foo.so"},
- UnstrippedOutput: "foo_unstripped.so",
- },
- "//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{
- CcObjectFiles: []string{"foo.o"},
- Includes: []string{"include"},
- SystemIncludes: []string{"system_include"},
- Headers: []string{"foo.h"},
- RootStaticArchives: []string{"foo.a"},
- TidyFiles: []string{"foo.c.tidy"},
- },
- },
- }
- ctx := android.GroupFixturePreparers(
- prepareForCcTest,
- android.FixtureMergeEnv(map[string]string{
- "ALLOW_LOCAL_TIDY_TRUE": "1",
- }),
- ).RunTestWithConfig(t, config).TestContext
-
- staticFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_static").Module()
- outputFiles, err := staticFoo.(android.OutputFileProducer).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
- }
-
- expectedOutputFiles := []string{"out/soong/.intermediates/foo/android_arm_armv7-a-neon_static/validated/foo.a"}
- android.AssertPathsRelativeToTopEquals(t, "output files", expectedOutputFiles, outputFiles)
-
- flagExporter := ctx.ModuleProvider(staticFoo, FlagExporterInfoProvider).(FlagExporterInfo)
- android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs)
- android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs)
- android.AssertPathsRelativeToTopEquals(t, "exported headers", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.GeneratedHeaders)
- android.AssertPathsRelativeToTopEquals(t, "deps", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.Deps)
-
- sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
- outputFiles, err = sharedFoo.(android.OutputFileProducer).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_library outputfiles %s", err)
- }
- expectedOutputFiles = []string{"outputbase/execroot/__main__/foo.so"}
- android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
-
- android.AssertStringEquals(t, "unstripped shared library", "outputbase/execroot/__main__/foo_unstripped.so", sharedFoo.(*Module).linker.unstrippedOutputFilePath().String())
- flagExporter = ctx.ModuleProvider(sharedFoo, FlagExporterInfoProvider).(FlagExporterInfo)
- android.AssertPathsRelativeToTopEquals(t, "exported include dirs", []string{"outputbase/execroot/__main__/include"}, flagExporter.IncludeDirs)
- android.AssertPathsRelativeToTopEquals(t, "exported system include dirs", []string{"outputbase/execroot/__main__/system_include"}, flagExporter.SystemIncludeDirs)
- android.AssertPathsRelativeToTopEquals(t, "exported headers", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.GeneratedHeaders)
- android.AssertPathsRelativeToTopEquals(t, "deps", []string{"outputbase/execroot/__main__/foo.h"}, flagExporter.Deps)
-}
-
func TestLibraryVersionScript(t *testing.T) {
t.Parallel()
result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, `
@@ -413,107 +281,6 @@
}
-func TestCcLibrarySharedWithBazelValidations(t *testing.T) {
- t.Parallel()
- bp := `
-cc_library_shared {
- name: "foo",
- srcs: ["foo.cc"],
- bazel_module: { label: "//foo/bar:bar" },
- tidy: true,
-}`
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: "outputbase",
- LabelToCcInfo: map[string]cquery.CcInfo{
- "//foo/bar:bar": cquery.CcInfo{
- CcObjectFiles: []string{"foo.o"},
- Includes: []string{"include"},
- SystemIncludes: []string{"system_include"},
- RootDynamicLibraries: []string{"foo.so"},
- TocFile: "foo.so.toc",
- TidyFiles: []string{"foo.c.tidy"},
- },
- },
- }
- ctx := android.GroupFixturePreparers(
- prepareForCcTest,
- android.FixtureMergeEnv(map[string]string{
- "ALLOW_LOCAL_TIDY_TRUE": "1",
- }),
- ).RunTestWithConfig(t, config).TestContext
-
- sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
- producer := sharedFoo.(android.OutputFileProducer)
- outputFiles, err := producer.OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
- }
- expectedOutputFiles := []string{"out/soong/.intermediates/foo/android_arm_armv7-a-neon_shared/validated/foo.so"}
- android.AssertPathsRelativeToTopEquals(t, "output files", expectedOutputFiles, outputFiles)
-
- tocFilePath := sharedFoo.(*Module).Toc()
- if !tocFilePath.Valid() {
- t.Errorf("Invalid tocFilePath: %s", tocFilePath)
- }
- tocFile := tocFilePath.Path()
- expectedToc := "outputbase/execroot/__main__/foo.so.toc"
- android.AssertStringEquals(t, "toc file", expectedToc, tocFile.String())
-
- entries := android.AndroidMkEntriesForTest(t, ctx, sharedFoo)[0]
- expectedFlags := []string{"-Ioutputbase/execroot/__main__/include", "-isystem outputbase/execroot/__main__/system_include"}
- gotFlags := entries.EntryMap["LOCAL_EXPORT_CFLAGS"]
- android.AssertDeepEquals(t, "androidmk exported cflags", expectedFlags, gotFlags)
- android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "cc_library_shared", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
-}
-
-func TestCcLibrarySharedWithBazel(t *testing.T) {
- t.Parallel()
- bp := `
-cc_library_shared {
- name: "foo",
- srcs: ["foo.cc"],
- bazel_module: { label: "//foo/bar:bar" },
-}`
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: "outputbase",
- LabelToCcInfo: map[string]cquery.CcInfo{
- "//foo/bar:bar": cquery.CcInfo{
- CcObjectFiles: []string{"foo.o"},
- Includes: []string{"include"},
- SystemIncludes: []string{"system_include"},
- RootDynamicLibraries: []string{"foo.so"},
- TocFile: "foo.so.toc",
- },
- },
- }
- ctx := testCcWithConfig(t, config)
-
- sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
- producer := sharedFoo.(android.OutputFileProducer)
- outputFiles, err := producer.OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
- }
- expectedOutputFiles := []string{"outputbase/execroot/__main__/foo.so"}
- android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
-
- tocFilePath := sharedFoo.(*Module).Toc()
- if !tocFilePath.Valid() {
- t.Errorf("Invalid tocFilePath: %s", tocFilePath)
- }
- tocFile := tocFilePath.Path()
- expectedToc := "outputbase/execroot/__main__/foo.so.toc"
- android.AssertStringEquals(t, "toc file", expectedToc, tocFile.String())
-
- entries := android.AndroidMkEntriesForTest(t, ctx, sharedFoo)[0]
- expectedFlags := []string{"-Ioutputbase/execroot/__main__/include", "-isystem outputbase/execroot/__main__/system_include"}
- gotFlags := entries.EntryMap["LOCAL_EXPORT_CFLAGS"]
- android.AssertDeepEquals(t, "androidmk exported cflags", expectedFlags, gotFlags)
- android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "cc_library_shared", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
-}
-
func TestWholeStaticLibPrebuilts(t *testing.T) {
t.Parallel()
result := PrepareForIntegrationTestWithCc.RunTestWithBp(t, `
diff --git a/cc/linkable.go b/cc/linkable.go
index 5b5b856..6f22091 100644
--- a/cc/linkable.go
+++ b/cc/linkable.go
@@ -2,7 +2,6 @@
import (
"android/soong/android"
- "android/soong/bazel/cquery"
"android/soong/fuzz"
"android/soong/snapshot"
@@ -219,6 +218,7 @@
ProductSpecific() bool
InProduct() bool
SdkAndPlatformVariantVisibleToMake() bool
+ InVendorOrProduct() bool
// SubName returns the modules SubName, used for image and NDK/SDK variations.
SubName() string
@@ -369,7 +369,7 @@
TransitiveStaticLibrariesForOrdering *android.DepSet[android.Path]
}
-var SharedLibraryInfoProvider = blueprint.NewProvider(SharedLibraryInfo{})
+var SharedLibraryInfoProvider = blueprint.NewProvider[SharedLibraryInfo]()
// SharedStubLibrary is a struct containing information about a stub shared library.
// Stub libraries are used for cross-APEX dependencies; when a library is to depend on a shared
@@ -392,7 +392,7 @@
IsLLNDK bool
}
-var SharedLibraryStubsProvider = blueprint.NewProvider(SharedLibraryStubsInfo{})
+var SharedLibraryStubsProvider = blueprint.NewProvider[SharedLibraryStubsInfo]()
// StaticLibraryInfo is a provider to propagate information about a static C++ library.
type StaticLibraryInfo struct {
@@ -411,14 +411,14 @@
TransitiveStaticLibrariesForOrdering *android.DepSet[android.Path]
}
-var StaticLibraryInfoProvider = blueprint.NewProvider(StaticLibraryInfo{})
+var StaticLibraryInfoProvider = blueprint.NewProvider[StaticLibraryInfo]()
// HeaderLibraryInfo is a marker provider that identifies a module as a header library.
type HeaderLibraryInfo struct {
}
// HeaderLibraryInfoProvider is a marker provider that identifies a module as a header library.
-var HeaderLibraryInfoProvider = blueprint.NewProvider(HeaderLibraryInfo{})
+var HeaderLibraryInfoProvider = blueprint.NewProvider[HeaderLibraryInfo]()
// FlagExporterInfo is a provider to propagate transitive library information
// pertaining to exported include paths and flags.
@@ -430,20 +430,4 @@
GeneratedHeaders android.Paths
}
-var FlagExporterInfoProvider = blueprint.NewProvider(FlagExporterInfo{})
-
-// flagExporterInfoFromCcInfo populates FlagExporterInfo provider with information from Bazel.
-func flagExporterInfoFromCcInfo(ctx android.ModuleContext, ccInfo cquery.CcInfo) FlagExporterInfo {
-
- includes := android.PathsForBazelOut(ctx, ccInfo.Includes)
- systemIncludes := android.PathsForBazelOut(ctx, ccInfo.SystemIncludes)
- headers := android.PathsForBazelOut(ctx, ccInfo.Headers)
-
- return FlagExporterInfo{
- IncludeDirs: android.FirstUniquePaths(includes),
- SystemIncludeDirs: android.FirstUniquePaths(systemIncludes),
- GeneratedHeaders: headers,
- // necessary to ensure generated headers are considered implicit deps of dependent actions
- Deps: headers,
- }
-}
+var FlagExporterInfoProvider = blueprint.NewProvider[FlagExporterInfo]()
diff --git a/cc/linker.go b/cc/linker.go
index 257fe86..2c50db2 100644
--- a/cc/linker.go
+++ b/cc/linker.go
@@ -91,6 +91,10 @@
// compiling crt or libc.
Nocrt *bool `android:"arch_variant"`
+ // don't link in crt_pad_segment. This flag is currently only used internal to
+ // soong for testing and for vndk prebuilt shared libraries.
+ No_crt_pad_segment *bool `android:"arch_variant"`
+
// deprecated and ignored because lld makes it unnecessary. See b/189475744.
Group_static_libs *bool `android:"arch_variant"`
@@ -214,6 +218,11 @@
// variant of the C/C++ module.
Exclude_static_libs []string
}
+ Non_apex struct {
+ // list of shared libs that should not be used to build the non-apex
+ // variant of the C/C++ module.
+ Exclude_shared_libs []string
+ }
} `android:"arch_variant"`
// make android::build:GetBuildNumber() available containing the build ID.
@@ -248,6 +257,10 @@
return blp.No_libcrt == nil || !*blp.No_libcrt
}
+func (blp *BaseLinkerProperties) crtPadSegment() bool {
+ return blp.No_crt_pad_segment == nil || !*blp.No_crt_pad_segment
+}
+
func NewBaseLinker(sanitize *sanitize) *baseLinker {
return &baseLinker{sanitize: sanitize}
}
@@ -300,6 +313,10 @@
// variants.
deps.ExcludeLibsForApex = append(deps.ExcludeLibsForApex, linker.Properties.Target.Apex.Exclude_shared_libs...)
deps.ExcludeLibsForApex = append(deps.ExcludeLibsForApex, linker.Properties.Target.Apex.Exclude_static_libs...)
+ // Record the libraries that need to be excluded when building for non-APEX variants
+ // for the same reason above. This is used for marking deps and marked deps are
+ // ignored for non-apex variants.
+ deps.ExcludeLibsForNonApex = append(deps.ExcludeLibsForNonApex, linker.Properties.Target.Non_apex.Exclude_shared_libs...)
if Bool(linker.Properties.Use_version_lib) {
deps.WholeStaticLibs = append(deps.WholeStaticLibs, "libbuildversion")
@@ -639,6 +656,9 @@
return specifiedDeps
}
+func (linker *baseLinker) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+}
+
// Injecting version symbols
// Some host modules want a version number, but we don't want to rebuild it every time. Optionally add a step
// after linking that injects a constant placeholder with the current version number.
diff --git a/cc/lto.go b/cc/lto.go
index df9ca0a..b2b4570 100644
--- a/cc/lto.go
+++ b/cc/lto.go
@@ -15,9 +15,12 @@
package cc
import (
- "android/soong/android"
+ "fmt"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
+
+ "android/soong/android"
)
// LTO (link-time optimization) allows the compiler to optimize and generate
@@ -35,11 +38,11 @@
// optimized at link time and may not be compatible with features that require
// LTO, such as CFI.
//
-// This file adds support to soong to automatically propogate LTO options to a
+// This file adds support to soong to automatically propagate LTO options to a
// new variant of all static dependencies for each module with LTO enabled.
type LTOProperties struct {
- // Lto must violate capitialization style for acronyms so that it can be
+ // Lto must violate capitalization style for acronyms so that it can be
// referred to in blueprint files as "lto"
Lto struct {
Never *bool `android:"arch_variant"`
@@ -49,11 +52,6 @@
LtoEnabled bool `blueprint:"mutated"`
LtoDefault bool `blueprint:"mutated"`
- // Dep properties indicate that this module needs to be built with LTO
- // since it is an object dependency of an LTO module.
- LtoDep bool `blueprint:"mutated"`
- NoLtoDep bool `blueprint:"mutated"`
-
// Use -fwhole-program-vtables cflag.
Whole_program_vtables *bool
}
@@ -67,10 +65,12 @@
}
func (lto *lto) begin(ctx BaseModuleContext) {
- // First, determine the module indepedent default LTO mode.
- ltoDefault := GlobalThinLTO(ctx)
+ // First, determine the module independent default LTO mode.
+ ltoDefault := true
if ctx.Config().IsEnvTrue("DISABLE_LTO") {
ltoDefault = false
+ } else if lto.Never() {
+ ltoDefault = false
} else if ctx.Host() {
// Performance and binary size are less important for host binaries.
ltoDefault = false
@@ -114,7 +114,8 @@
// better dead code elimination and CFG simplification, but do
// not perform costly optimizations for a balance between compile
// time, binary size and performance.
- if !lto.ThinLTO() {
+ // Apply the same for Eng builds as well.
+ if !lto.ThinLTO() || ctx.Config().Eng() {
ltoLdFlags = append(ltoLdFlags, "-Wl,--lto-O0")
}
@@ -138,13 +139,25 @@
// Reduce the inlining threshold for a better balance of binary size and
// performance.
if !ctx.Darwin() {
- if ctx.isPgoCompile() || ctx.isAfdoCompile() {
+ if ctx.isAfdoCompile() {
ltoLdFlags = append(ltoLdFlags, "-Wl,-plugin-opt,-import-instr-limit=40")
} else {
ltoLdFlags = append(ltoLdFlags, "-Wl,-plugin-opt,-import-instr-limit=5")
}
}
+ if !ctx.Config().IsEnvFalse("THINLTO_USE_MLGO") {
+ // Register allocation MLGO flags for ARM64.
+ if ctx.Arch().ArchType == android.Arm64 {
+ ltoLdFlags = append(ltoLdFlags, "-Wl,-mllvm,-regalloc-enable-advisor=release")
+ }
+ // Flags for training MLGO model.
+ if ctx.Config().IsEnvTrue("THINLTO_EMIT_INDEXES_AND_IMPORTS") {
+ ltoLdFlags = append(ltoLdFlags, "-Wl,--save-temps=import")
+ ltoLdFlags = append(ltoLdFlags, "-Wl,--thinlto-emit-index-files")
+ }
+ }
+
flags.Local.CFlags = append(flags.Local.CFlags, ltoCFlags...)
flags.Local.AsFlags = append(flags.Local.AsFlags, ltoCFlags...)
flags.Local.LdFlags = append(flags.Local.LdFlags, ltoCFlags...)
@@ -161,92 +174,83 @@
return lto != nil && proptools.Bool(lto.Properties.Lto.Never)
}
-func GlobalThinLTO(ctx android.BaseModuleContext) bool {
- return !ctx.Config().IsEnvFalse("GLOBAL_THINLTO")
-}
-
-// Propagate lto requirements down from binaries
-func ltoDepsMutator(mctx android.TopDownMutatorContext) {
- if m, ok := mctx.Module().(*Module); ok {
- if m.lto == nil || m.lto.Properties.LtoEnabled == m.lto.Properties.LtoDefault {
- return
- }
-
- mctx.WalkDeps(func(dep android.Module, parent android.Module) bool {
- tag := mctx.OtherModuleDependencyTag(dep)
- libTag, isLibTag := tag.(libraryDependencyTag)
-
- // Do not recurse down non-static dependencies
- if isLibTag {
- if !libTag.static() {
- return false
- }
- } else {
- if tag != objDepTag && tag != reuseObjTag {
- return false
- }
- }
-
- if dep, ok := dep.(*Module); ok {
- if m.lto.Properties.LtoEnabled {
- dep.lto.Properties.LtoDep = true
- } else {
- dep.lto.Properties.NoLtoDep = true
- }
- }
-
- // Recursively walk static dependencies
- return true
- })
+func ltoPropagateViaDepTag(tag blueprint.DependencyTag) bool {
+ libTag, isLibTag := tag.(libraryDependencyTag)
+ // Do not recurse down non-static dependencies
+ if isLibTag {
+ return libTag.static()
+ } else {
+ return tag == objDepTag || tag == reuseObjTag || tag == staticVariantTag
}
}
-// Create lto variants for modules that need them
-func ltoMutator(mctx android.BottomUpMutatorContext) {
- globalThinLTO := GlobalThinLTO(mctx)
+// ltoTransitionMutator creates LTO variants of cc modules. Variant "" is the default variant, which may
+// or may not have LTO enabled depending on the config and the module's type and properties. "lto-thin" or
+// "lto-none" variants are created when a module needs to compile in the non-default state for that module.
+type ltoTransitionMutator struct{}
- if m, ok := mctx.Module().(*Module); ok && m.lto != nil {
- // Create variations for LTO types required as static
- // dependencies
- variationNames := []string{""}
- if m.lto.Properties.LtoDep {
- variationNames = append(variationNames, "lto-thin")
- }
- if m.lto.Properties.NoLtoDep {
- variationNames = append(variationNames, "lto-none")
+const LTO_NONE_VARIATION = "lto-none"
+const LTO_THIN_VARIATION = "lto-thin"
+
+func (l *ltoTransitionMutator) Split(ctx android.BaseModuleContext) []string {
+ return []string{""}
+}
+
+func (l *ltoTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ if m, ok := ctx.Module().(*Module); ok && m.lto != nil {
+ if !ltoPropagateViaDepTag(ctx.DepTag()) {
+ return ""
}
- if globalThinLTO && !m.lto.Properties.LtoEnabled {
- mctx.SetDependencyVariation("lto-none")
- }
- if !globalThinLTO && m.lto.Properties.LtoEnabled {
- mctx.SetDependencyVariation("lto-thin")
+ if sourceVariation != "" {
+ return sourceVariation
}
- if len(variationNames) > 1 {
- modules := mctx.CreateVariations(variationNames...)
- for i, name := range variationNames {
- variation := modules[i].(*Module)
- // Default module which will be
- // installed. Variation set above according to
- // explicit LTO properties
- if name == "" {
- continue
- }
-
- // LTO properties for dependencies
- if name == "lto-thin" {
- variation.lto.Properties.LtoEnabled = true
- }
- if name == "lto-none" {
- variation.lto.Properties.LtoEnabled = false
- }
- variation.Properties.PreventInstall = true
- variation.Properties.HideFromMake = true
- variation.lto.Properties.LtoDefault = m.lto.Properties.LtoDefault
- variation.lto.Properties.LtoDep = false
- variation.lto.Properties.NoLtoDep = false
- }
+ // Always request an explicit variation, IncomingTransition will rewrite it back to the default variation
+ // if necessary.
+ if m.lto.Properties.LtoEnabled {
+ return LTO_THIN_VARIATION
+ } else {
+ return LTO_NONE_VARIATION
}
}
+ return ""
+}
+
+func (l *ltoTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
+ if m, ok := ctx.Module().(*Module); ok && m.lto != nil {
+ if m.lto.Never() {
+ return ""
+ }
+ // Rewrite explicit variations back to the default variation if the default variation matches.
+ if incomingVariation == LTO_THIN_VARIATION && m.lto.Properties.LtoDefault {
+ return ""
+ } else if incomingVariation == LTO_NONE_VARIATION && !m.lto.Properties.LtoDefault {
+ return ""
+ }
+ return incomingVariation
+ }
+ return ""
+}
+
+func (l *ltoTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
+ // Default module which will be installed. Variation set above according to explicit LTO properties.
+ if variation == "" {
+ return
+ }
+
+ if m, ok := ctx.Module().(*Module); ok && m.lto != nil {
+ // Non-default variation, set the LTO properties to match the variation.
+ switch variation {
+ case LTO_THIN_VARIATION:
+ m.lto.Properties.LtoEnabled = true
+ case LTO_NONE_VARIATION:
+ m.lto.Properties.LtoEnabled = false
+ default:
+ panic(fmt.Errorf("unknown variation %s", variation))
+ }
+ // Non-default variations are never installed.
+ m.Properties.PreventInstall = true
+ m.Properties.HideFromMake = true
+ }
}
diff --git a/cc/lto_test.go b/cc/lto_test.go
index e0afd4a..e4b5a3a 100644
--- a/cc/lto_test.go
+++ b/cc/lto_test.go
@@ -23,11 +23,19 @@
"github.com/google/blueprint"
)
-var NoGlobalThinLTOPreparer = android.GroupFixturePreparers(
+var LTOPreparer = android.GroupFixturePreparers(
prepareForCcTest,
- android.FixtureModifyEnv(func(env map[string]string) {
- env["GLOBAL_THINLTO"] = "false"
- }))
+)
+
+func hasDep(result *android.TestResult, m android.Module, wantDep android.Module) bool {
+ var found bool
+ result.VisitDirectDeps(m, func(dep blueprint.Module) {
+ if dep == wantDep {
+ found = true
+ }
+ })
+ return found
+}
func TestThinLtoDeps(t *testing.T) {
t.Parallel()
@@ -37,9 +45,6 @@
srcs: ["src.c"],
static_libs: ["foo", "lib_never_lto"],
shared_libs: ["bar"],
- lto: {
- thin: true,
- }
}
cc_library_static {
name: "foo",
@@ -63,50 +68,40 @@
}
`
- result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
+ result := LTOPreparer.RunTestWithBp(t, bp)
libLto := result.ModuleForTests("lto_enabled", "android_arm64_armv8-a_shared").Module()
- hasDep := func(m android.Module, wantDep android.Module) bool {
- var found bool
- result.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
+ libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static").Module()
+ if !hasDep(result, libLto, libFoo) {
+ t.Errorf("'lto_enabled' missing dependency on the default variant of 'foo'")
}
- libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static_lto-thin").Module()
- if !hasDep(libLto, libFoo) {
- t.Errorf("'lto_enabled' missing dependency on thin lto variant of 'foo'")
+ libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static").Module()
+ if !hasDep(result, libFoo, libBaz) {
+ t.Errorf("'foo' missing dependency on the default variant of transitive dep 'baz'")
}
- libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static_lto-thin").Module()
- if !hasDep(libFoo, libBaz) {
- t.Errorf("'foo' missing dependency on thin lto variant of transitive dep 'baz'")
- }
-
- libNeverLto := result.ModuleForTests("lib_never_lto", "android_arm64_armv8-a_static_lto-thin").Module()
- if !hasDep(libLto, libNeverLto) {
- t.Errorf("'lto_enabled' missing dependency on NO-thin lto variant of 'lib_never_lto'")
+ libNeverLto := result.ModuleForTests("lib_never_lto", "android_arm64_armv8-a_static").Module()
+ if !hasDep(result, libLto, libNeverLto) {
+ t.Errorf("'lto_enabled' missing dependency on the default variant of 'lib_never_lto'")
}
libBar := result.ModuleForTests("bar", "android_arm64_armv8-a_shared").Module()
- if !hasDep(libLto, libBar) {
- t.Errorf("'lto_enabled' missing dependency on non-thin lto variant of 'bar'")
+ if !hasDep(result, libLto, libBar) {
+ t.Errorf("'lto_enabled' missing dependency on the default variant of 'bar'")
}
barVariants := result.ModuleVariantsForTests("bar")
for _, v := range barVariants {
- if strings.Contains(v, "lto-thin") {
- t.Errorf("Expected variants for 'bar' to not contain 'lto-thin', but found %q", v)
+ if strings.Contains(v, "lto-none") {
+ t.Errorf("Expected variants for 'bar' to not contain 'lto-none', but found %q", v)
}
}
quxVariants := result.ModuleVariantsForTests("qux")
for _, v := range quxVariants {
- if strings.Contains(v, "lto-thin") {
- t.Errorf("Expected variants for 'qux' to not contain 'lto-thin', but found %q", v)
+ if strings.Contains(v, "lto-none") {
+ t.Errorf("Expected variants for 'qux' to not contain 'lto-none', but found %q", v)
}
}
}
@@ -141,28 +136,19 @@
}
`
- result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
+ result := LTOPreparer.RunTestWithBp(t, bp)
libRoot := result.ModuleForTests("root", "android_arm64_armv8-a_shared").Module()
libRootLtoNever := result.ModuleForTests("root_no_lto", "android_arm64_armv8-a_shared").Module()
- hasDep := func(m android.Module, wantDep android.Module) bool {
- var found bool
- result.VisitDirectDeps(m, func(dep blueprint.Module) {
- if dep == wantDep {
- found = true
- }
- })
- return found
- }
-
libFoo := result.ModuleForTests("foo", "android_arm64_armv8-a_static")
- if !hasDep(libRoot, libFoo.Module()) {
- t.Errorf("'root' missing dependency on thin lto variant of 'foo'")
+ if !hasDep(result, libRoot, libFoo.Module()) {
+ t.Errorf("'root' missing dependency on the default variant of 'foo'")
}
- if !hasDep(libRootLtoNever, libFoo.Module()) {
- t.Errorf("'root_no_lto' missing dependency on thin lto variant of 'foo'")
+ libFooNoLto := result.ModuleForTests("foo", "android_arm64_armv8-a_static_lto-none")
+ if !hasDep(result, libRootLtoNever, libFooNoLto.Module()) {
+ t.Errorf("'root_no_lto' missing dependency on the lto_none variant of 'foo'")
}
libFooCFlags := libFoo.Rule("cc").Args["cFlags"]
@@ -170,9 +156,9 @@
t.Errorf("'foo' expected to have flags %q, but got %q", w, libFooCFlags)
}
- libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static_lto-thin")
- if !hasDep(libFoo.Module(), libBaz.Module()) {
- t.Errorf("'foo' missing dependency on thin lto variant of transitive dep 'baz'")
+ libBaz := result.ModuleForTests("baz", "android_arm64_armv8-a_static")
+ if !hasDep(result, libFoo.Module(), libBaz.Module()) {
+ t.Errorf("'foo' missing dependency on the default variant of transitive dep 'baz'")
}
libBazCFlags := libFoo.Rule("cc").Args["cFlags"]
@@ -199,7 +185,7 @@
},
},
}`
- result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
+ result := LTOPreparer.RunTestWithBp(t, bp)
libFooWithLto := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
libFooWithoutLto := result.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Rule("ld")
@@ -227,7 +213,7 @@
},
}`
- result := NoGlobalThinLTOPreparer.RunTestWithBp(t, bp)
+ result := LTOPreparer.RunTestWithBp(t, bp)
libFoo := result.ModuleForTests("libfoo", "android_arm_armv7-a-neon_shared").Rule("ld")
libBar := result.ModuleForTests("runtime_libbar", "android_arm_armv7-a-neon_shared").Rule("ld")
diff --git a/cc/makevars.go b/cc/makevars.go
index 6c3f551..70fdd57 100644
--- a/cc/makevars.go
+++ b/cc/makevars.go
@@ -123,6 +123,13 @@
ctx.Strict("SOONG_MODULES_USING_WNO_ERROR", makeStringOfKeys(ctx, modulesUsingWnoErrorKey))
ctx.Strict("SOONG_MODULES_MISSING_PGO_PROFILE_FILE", makeStringOfKeys(ctx, modulesMissingProfileFileKey))
+ ctx.Strict("CLANG_COVERAGE_CONFIG_CFLAGS", strings.Join(clangCoverageCFlags, " "))
+ ctx.Strict("CLANG_COVERAGE_CONFIG_COMMFLAGS", strings.Join(clangCoverageCommonFlags, " "))
+ ctx.Strict("CLANG_COVERAGE_HOST_LDFLAGS", strings.Join(clangCoverageHostLdFlags, " "))
+ ctx.Strict("CLANG_COVERAGE_INSTR_PROFILE", profileInstrFlag)
+ ctx.Strict("CLANG_COVERAGE_CONTINUOUS_FLAGS", strings.Join(clangContinuousCoverageFlags, " "))
+ ctx.Strict("CLANG_COVERAGE_HWASAN_FLAGS", strings.Join(clangCoverageHWASanFlags, " "))
+
ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_CFLAGS", strings.Join(asanCflags, " "))
ctx.Strict("ADDRESS_SANITIZER_CONFIG_EXTRA_LDFLAGS", strings.Join(asanLdflags, " "))
diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go
index d0ae4a5..567cb7c 100644
--- a/cc/ndk_headers.go
+++ b/cc/ndk_headers.go
@@ -18,9 +18,8 @@
"fmt"
"path/filepath"
- "github.com/google/blueprint"
-
"android/soong/android"
+ "github.com/google/blueprint"
)
var (
@@ -82,6 +81,7 @@
properties headerProperties
+ srcPaths android.Paths
installPaths android.Paths
licensePath android.Path
}
@@ -125,8 +125,8 @@
m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License))
- srcFiles := android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
- for _, header := range srcFiles {
+ m.srcPaths = android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
+ for _, header := range m.srcPaths {
installDir := getHeaderInstallDir(ctx, header, String(m.properties.From),
String(m.properties.To))
installedPath := ctx.InstallFile(installDir, header.Base(), header)
@@ -154,7 +154,7 @@
// to = "bar"
// header = "include/foo/woodly/doodly.h"
// output path = "ndk/sysroot/usr/include/bar/woodly/doodly.h"
-func ndkHeadersFactory() android.Module {
+func NdkHeadersFactory() android.Module {
module := &headerModule{}
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
@@ -182,7 +182,7 @@
}
// Like ndk_headers, but preprocesses the headers with the bionic versioner:
-// https://android.googlesource.com/platform/bionic/+/master/tools/versioner/README.md.
+// https://android.googlesource.com/platform/bionic/+/main/tools/versioner/README.md.
//
// Unlike ndk_headers, we don't operate on a list of sources but rather a whole directory, the
// module does not have the srcs property, and operates on a full directory (the `from` property).
@@ -193,6 +193,7 @@
properties versionedHeaderProperties
+ srcPaths android.Paths
installPaths android.Paths
licensePath android.Path
}
@@ -211,9 +212,9 @@
fromSrcPath := android.PathForModuleSrc(ctx, String(m.properties.From))
toOutputPath := getCurrentIncludePath(ctx).Join(ctx, String(m.properties.To))
- srcFiles := ctx.GlobFiles(headerGlobPattern(fromSrcPath.String()), nil)
+ m.srcPaths = ctx.GlobFiles(headerGlobPattern(fromSrcPath.String()), nil)
var installPaths []android.WritablePath
- for _, header := range srcFiles {
+ for _, header := range m.srcPaths {
installDir := getHeaderInstallDir(ctx, header, String(m.properties.From), String(m.properties.To))
installPath := installDir.Join(ctx, header.Base())
installPaths = append(installPaths, installPath)
@@ -224,11 +225,11 @@
ctx.ModuleErrorf("glob %q matched zero files", String(m.properties.From))
}
- processHeadersWithVersioner(ctx, fromSrcPath, toOutputPath, srcFiles, installPaths)
+ processHeadersWithVersioner(ctx, fromSrcPath, toOutputPath, m.srcPaths, installPaths)
}
func processHeadersWithVersioner(ctx android.ModuleContext, srcDir, outDir android.Path,
- srcFiles android.Paths, installPaths []android.WritablePath) android.Path {
+ srcPaths android.Paths, installPaths []android.WritablePath) android.Path {
// The versioner depends on a dependencies directory to simplify determining include paths
// when parsing headers. This directory contains architecture specific directories as well
// as a common directory, each of which contains symlinks to the actually directories to
@@ -253,7 +254,7 @@
Rule: versionBionicHeaders,
Description: "versioner preprocess " + srcDir.Rel(),
Output: timestampFile,
- Implicits: append(srcFiles, depsGlob...),
+ Implicits: append(srcPaths, depsGlob...),
ImplicitOutputs: installPaths,
Args: map[string]string{
"depsPath": depsPath.String(),
@@ -266,11 +267,11 @@
}
// versioned_ndk_headers preprocesses the headers with the bionic versioner:
-// https://android.googlesource.com/platform/bionic/+/master/tools/versioner/README.md.
+// https://android.googlesource.com/platform/bionic/+/main/tools/versioner/README.md.
// Unlike the ndk_headers soong module, versioned_ndk_headers operates on a
// directory level specified in `from` property. This is only used to process
// the bionic/libc/include directory.
-func versionedNdkHeadersFactory() android.Module {
+func VersionedNdkHeadersFactory() android.Module {
module := &versionedHeaderModule{}
module.AddProperties(&module.properties)
@@ -317,6 +318,7 @@
properties preprocessedHeadersProperties
+ srcPaths android.Paths
installPaths android.Paths
licensePath android.Path
}
@@ -329,9 +331,9 @@
preprocessor := android.PathForModuleSrc(ctx, String(m.properties.Preprocessor))
m.licensePath = android.PathForModuleSrc(ctx, String(m.properties.License))
- srcFiles := android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
+ m.srcPaths = android.PathsForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
installDir := getCurrentIncludePath(ctx).Join(ctx, String(m.properties.To))
- for _, src := range srcFiles {
+ for _, src := range m.srcPaths {
installPath := installDir.Join(ctx, src.Base())
m.installPaths = append(m.installPaths, installPath)
diff --git a/cc/ndk_library.go b/cc/ndk_library.go
index 9281aeb..183e818 100644
--- a/cc/ndk_library.go
+++ b/cc/ndk_library.go
@@ -25,7 +25,6 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel"
"android/soong/cc/config"
)
@@ -43,11 +42,17 @@
CommandDeps: []string{"$ndkStubGenerator"},
}, "arch", "apiLevel", "apiMap", "flags")
+ // $headersList should include paths to public headers. All types
+ // that are defined outside of public headers will be excluded from
+ // ABI monitoring.
+ //
+ // STG tool doesn't access content of files listed in $headersList,
+ // so there is no need to add them to dependencies.
stg = pctx.AndroidStaticRule("stg",
blueprint.RuleParams{
- Command: "$stg -S :$symbolList --elf $in -o $out",
+ Command: "$stg -S :$symbolList --file-filter :$headersList --elf $in -o $out",
CommandDeps: []string{"$stg"},
- }, "symbolList")
+ }, "symbolList", "headersList")
stgdiff = pctx.AndroidStaticRule("stgdiff",
blueprint.RuleParams{
@@ -55,7 +60,7 @@
// because we don't want to spam the build output with "nothing
// changed" messages, so redirect output message to $out, and if
// changes were detected print the output and fail.
- Command: "$stgdiff $args --stg $in -o $out || (cat $out && false)",
+ Command: "$stgdiff $args --stg $in -o $out || (cat $out && echo 'Run $$ANDROID_BUILD_TOP/development/tools/ndk/update_ndk_abi.sh to update the ABI dumps.' && false)",
CommandDeps: []string{"$stgdiff"},
}, "args")
@@ -328,18 +333,12 @@
return false
}
// http://b/156513478
- // http://b/277624006
- // This step is expensive. We're not able to do anything with the outputs of
- // this step yet (canDiffAbi is flagged off because libabigail isn't able to
- // handle all our libraries), disable it. There's no sense in protecting
- // against checking in code that breaks abidw since by the time any of this
- // can be turned on we'll need to migrate to STG anyway.
- return false
+ return config.ReleaseNdkAbiMonitored()
}
// Feature flag to disable diffing against prebuilts.
-func canDiffAbi() bool {
- return false
+func canDiffAbi(config android.Config) bool {
+ return config.ReleaseNdkAbiMonitored()
}
func (this *stubDecorator) dumpAbi(ctx ModuleContext, symbolList android.Path) {
@@ -347,14 +346,19 @@
this.abiDumpPath = getNdkAbiDumpInstallBase(ctx).Join(ctx,
this.apiLevel.String(), ctx.Arch().ArchType.String(),
this.libraryName(ctx), "abi.stg")
+ headersList := getNdkABIHeadersFile(ctx)
ctx.Build(pctx, android.BuildParams{
Rule: stg,
Description: fmt.Sprintf("stg %s", implementationLibrary),
Input: implementationLibrary,
- Implicit: symbolList,
- Output: this.abiDumpPath,
+ Implicits: []android.Path{
+ symbolList,
+ headersList,
+ },
+ Output: this.abiDumpPath,
Args: map[string]string{
- "symbolList": symbolList.String(),
+ "symbolList": symbolList.String(),
+ "headersList": headersList.String(),
},
})
}
@@ -375,9 +379,11 @@
// level.
abiDiffPath := android.PathForModuleOut(ctx, "stgdiff.timestamp")
prebuiltAbiDump := this.findPrebuiltAbiDump(ctx, this.apiLevel)
+ missingPrebuiltErrorTemplate :=
+ "Did not find prebuilt ABI dump for %q (%q). Generate with " +
+ "//development/tools/ndk/update_ndk_abi.sh."
missingPrebuiltError := fmt.Sprintf(
- "Did not find prebuilt ABI dump for %q (%q). Generate with "+
- "//development/tools/ndk/update_ndk_abi.sh.", this.libraryName(ctx),
+ missingPrebuiltErrorTemplate, this.libraryName(ctx),
prebuiltAbiDump.InvalidReason())
if !prebuiltAbiDump.Valid() {
ctx.Build(pctx, android.BuildParams{
@@ -404,7 +410,7 @@
// Also ensure that the ABI of the next API level (if there is one) matches
// this API level. *New* ABI is allowed, but any changes to APIs that exist
// in this API level are disallowed.
- if !this.apiLevel.IsCurrent() {
+ if !this.apiLevel.IsCurrent() && prebuiltAbiDump.Valid() {
nextApiLevel := findNextApiLevel(ctx, this.apiLevel)
if nextApiLevel == nil {
panic(fmt.Errorf("could not determine which API level follows "+
@@ -413,21 +419,26 @@
nextAbiDiffPath := android.PathForModuleOut(ctx,
"abidiff_next.timestamp")
nextAbiDump := this.findPrebuiltAbiDump(ctx, *nextApiLevel)
+ missingNextPrebuiltError := fmt.Sprintf(
+ missingPrebuiltErrorTemplate, this.libraryName(ctx),
+ nextAbiDump.InvalidReason())
if !nextAbiDump.Valid() {
ctx.Build(pctx, android.BuildParams{
Rule: android.ErrorRule,
Output: nextAbiDiffPath,
Args: map[string]string{
- "error": missingPrebuiltError,
+ "error": missingNextPrebuiltError,
},
})
} else {
ctx.Build(pctx, android.BuildParams{
Rule: stgdiff,
- Description: fmt.Sprintf("abidiff %s %s", this.abiDumpPath,
- nextAbiDump),
+ Description: fmt.Sprintf(
+ "Comparing ABI to the next API level %s %s",
+ prebuiltAbiDump, nextAbiDump),
Output: nextAbiDiffPath,
- Inputs: android.Paths{this.abiDumpPath, nextAbiDump.Path()},
+ Inputs: android.Paths{
+ prebuiltAbiDump.Path(), nextAbiDump.Path()},
Args: map[string]string{
"args": "--format=small --ignore=interface_addition",
},
@@ -458,7 +469,7 @@
c.versionScriptPath = nativeAbiResult.versionScript
if canDumpAbi(ctx.Config()) {
c.dumpAbi(ctx, nativeAbiResult.symbolList)
- if canDiffAbi() {
+ if canDiffAbi(ctx.Config()) {
c.diffAbi(ctx)
}
}
@@ -475,6 +486,12 @@
}
}
+func (linker *stubDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ linker.libraryDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+ // Overwrites the SubName computed by libraryDecorator
+ moduleInfoJSON.SubName = ndkLibrarySuffix + "." + linker.apiLevel.String()
+}
+
func (linker *stubDecorator) Name(name string) string {
return name + ndkLibrarySuffix
}
@@ -551,22 +568,5 @@
func NdkLibraryFactory() android.Module {
module := newStubLibrary()
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
- android.InitBazelModule(module)
return module
}
-
-type bazelCcApiContributionAttributes struct {
- Api bazel.LabelAttribute
- Api_surfaces bazel.StringListAttribute
- Hdrs bazel.LabelListAttribute
- Library_name string
-}
-
-// Names of the cc_api_header targets in the bp2build workspace
-func apiHeaderLabels(ctx android.TopDownMutatorContext, hdrLibs []string) bazel.LabelList {
- addSuffix := func(ctx android.BazelConversionPathContext, module blueprint.Module) string {
- label := android.BazelModuleLabel(ctx, module)
- return android.ApiContributionTargetName(label)
- }
- return android.BazelLabelForModuleDepsWithFn(ctx, hdrLibs, addSuffix)
-}
diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go
index d3a0a00..f503982 100644
--- a/cc/ndk_prebuilt.go
+++ b/cc/ndk_prebuilt.go
@@ -87,9 +87,12 @@
return module.Init()
}
+const (
+ libDir = "current/sources/cxx-stl/llvm-libc++/libs"
+)
+
func getNdkStlLibDir(ctx android.ModuleContext) android.SourcePath {
- libDir := "prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs"
- return android.PathForSource(ctx, libDir).Join(ctx, ctx.Arch().Abi[0])
+ return android.PathForSource(ctx, ctx.ModuleDir(), libDir).Join(ctx, ctx.Arch().Abi[0])
}
func (ndk *ndkPrebuiltStlLinker) link(ctx ModuleContext, flags Flags,
@@ -114,13 +117,13 @@
if ndk.static() {
depSet := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).Direct(lib).Build()
- ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+ android.SetProvider(ctx, StaticLibraryInfoProvider, StaticLibraryInfo{
StaticLibrary: lib,
TransitiveStaticLibrariesForOrdering: depSet,
})
} else {
- ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+ android.SetProvider(ctx, SharedLibraryInfoProvider, SharedLibraryInfo{
SharedLibrary: lib,
Target: ctx.Target(),
})
diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go
index feb3880..483d23b 100644
--- a/cc/ndk_sysroot.go
+++ b/cc/ndk_sysroot.go
@@ -54,6 +54,7 @@
import (
"android/soong/android"
+ "strings"
)
func init() {
@@ -61,9 +62,9 @@
}
func RegisterNdkModuleTypes(ctx android.RegistrationContext) {
- ctx.RegisterModuleType("ndk_headers", ndkHeadersFactory)
+ ctx.RegisterModuleType("ndk_headers", NdkHeadersFactory)
ctx.RegisterModuleType("ndk_library", NdkLibraryFactory)
- ctx.RegisterModuleType("versioned_ndk_headers", versionedNdkHeadersFactory)
+ ctx.RegisterModuleType("versioned_ndk_headers", VersionedNdkHeadersFactory)
ctx.RegisterModuleType("preprocessed_ndk_headers", preprocessedNdkHeadersFactory)
ctx.RegisterParallelSingletonType("ndk", NdkSingleton)
}
@@ -96,15 +97,56 @@
return android.PathForOutput(ctx, "ndk.timestamp")
}
+// The list of all NDK headers as they are located in the repo.
+// Used for ABI monitoring to track only structures defined in NDK headers.
+func getNdkABIHeadersFile(ctx android.PathContext) android.WritablePath {
+ return android.PathForOutput(ctx, "ndk_abi_headers.txt")
+}
+
func NdkSingleton() android.Singleton {
return &ndkSingleton{}
}
+// Collect all NDK exported headers paths into a file that is used to
+// detect public types that should be ABI monitored.
+//
+// Assume that we have the following code in exported header:
+//
+// typedef struct Context Context;
+// typedef struct Output {
+// ...
+// } Output;
+// void DoSomething(Context* ctx, Output* output);
+//
+// If none of public headers exported to end-users contain definition of
+// "struct Context", then "struct Context" layout and members shouldn't be
+// monitored. However we use DWARF information from a real library, which
+// may have access to the definition of "string Context" from
+// implementation headers, and it will leak to ABI.
+//
+// STG tool doesn't access source and header files, only DWARF information
+// from compiled library. And the DWARF contains file name where a type is
+// defined. So we need a rule to build a list of paths to public headers,
+// so STG can distinguish private types from public and do not monitor
+// private types that are not accessible to library users.
+func writeNdkAbiSrcFilter(ctx android.BuilderContext,
+ headerSrcPaths android.Paths, outputFile android.WritablePath) {
+ var filterBuilder strings.Builder
+ filterBuilder.WriteString("[decl_file_allowlist]\n")
+ for _, headerSrcPath := range headerSrcPaths {
+ filterBuilder.WriteString(headerSrcPath.String())
+ filterBuilder.WriteString("\n")
+ }
+
+ android.WriteFileRule(ctx, outputFile, filterBuilder.String())
+}
+
type ndkSingleton struct{}
func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) {
var staticLibInstallPaths android.Paths
- var headerPaths android.Paths
+ var headerSrcPaths android.Paths
+ var headerInstallPaths android.Paths
var installPaths android.Paths
var licensePaths android.Paths
ctx.VisitAllModules(func(module android.Module) {
@@ -113,19 +155,22 @@
}
if m, ok := module.(*headerModule); ok {
- headerPaths = append(headerPaths, m.installPaths...)
+ headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
+ headerInstallPaths = append(headerInstallPaths, m.installPaths...)
installPaths = append(installPaths, m.installPaths...)
licensePaths = append(licensePaths, m.licensePath)
}
if m, ok := module.(*versionedHeaderModule); ok {
- headerPaths = append(headerPaths, m.installPaths...)
+ headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
+ headerInstallPaths = append(headerInstallPaths, m.installPaths...)
installPaths = append(installPaths, m.installPaths...)
licensePaths = append(licensePaths, m.licensePath)
}
if m, ok := module.(*preprocessedHeadersModule); ok {
- headerPaths = append(headerPaths, m.installPaths...)
+ headerSrcPaths = append(headerSrcPaths, m.srcPaths...)
+ headerInstallPaths = append(headerInstallPaths, m.installPaths...)
installPaths = append(installPaths, m.installPaths...)
licensePaths = append(licensePaths, m.licensePath)
}
@@ -175,9 +220,11 @@
ctx.Build(pctx, android.BuildParams{
Rule: android.Touch,
Output: getNdkHeadersTimestampFile(ctx),
- Implicits: headerPaths,
+ Implicits: headerInstallPaths,
})
+ writeNdkAbiSrcFilter(ctx, headerSrcPaths, getNdkABIHeadersFile(ctx))
+
fullDepPaths := append(staticLibInstallPaths, getNdkBaseTimestampFile(ctx))
// There's a phony "ndk" rule defined in core/main.mk that depends on this.
diff --git a/cc/object.go b/cc/object.go
index ca14845..6c0391f 100644
--- a/cc/object.go
+++ b/cc/object.go
@@ -19,8 +19,6 @@
"strings"
"android/soong/android"
- "android/soong/bazel"
- "android/soong/bazel/cquery"
)
//
@@ -50,33 +48,6 @@
ndkSysrootPath android.Path
}
-type objectBazelHandler struct {
- module *Module
-}
-
-var _ BazelHandler = (*objectBazelHandler)(nil)
-
-func (handler *objectBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
- bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(label, cquery.GetOutputFiles, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx)))
-}
-
-func (handler *objectBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
- bazelCtx := ctx.Config().BazelContext
- objPaths, err := bazelCtx.GetOutputFiles(label, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx)))
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- return
- }
-
- if len(objPaths) != 1 {
- ctx.ModuleErrorf("expected exactly one object file for '%s', but got %s", label, objPaths)
- return
- }
-
- handler.module.outputFile = android.OptionalPathForPath(android.PathForBazelOut(ctx, objPaths[0]))
-}
-
type ObjectLinkerProperties struct {
// list of static library modules that should only provide headers for this module.
Static_libs []string `android:"arch_variant,variant_prepend"`
@@ -125,115 +96,15 @@
baseLinker: NewBaseLinker(module.sanitize),
}
module.compiler = NewBaseCompiler()
- module.bazelHandler = &objectBazelHandler{module: module}
// Clang's address-significance tables are incompatible with ld -r.
module.compiler.appendCflags([]string{"-fno-addrsig"})
module.sdkMemberTypes = []android.SdkMemberType{ccObjectSdkMemberType}
- module.bazelable = true
return module.Init()
}
-// For bp2build conversion.
-type bazelObjectAttributes struct {
- Srcs bazel.LabelListAttribute
- Srcs_as bazel.LabelListAttribute
- Hdrs bazel.LabelListAttribute
- Objs bazel.LabelListAttribute
- Deps bazel.LabelListAttribute
- System_dynamic_deps bazel.LabelListAttribute
- Copts bazel.StringListAttribute
- Asflags bazel.StringListAttribute
- Local_includes bazel.StringListAttribute
- Absolute_includes bazel.StringListAttribute
- Stl *string
- Linker_script bazel.LabelAttribute
- Crt *bool
- sdkAttributes
-}
-
-// objectBp2Build is the bp2build converter from cc_object modules to the
-// Bazel equivalent target, plus any necessary include deps for the cc_object.
-func objectBp2Build(ctx android.TopDownMutatorContext, m *Module) {
- if m.compiler == nil {
- // a cc_object must have access to the compiler decorator for its props.
- ctx.ModuleErrorf("compiler must not be nil for a cc_object module")
- }
-
- // 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}
-
- var linkerScript bazel.LabelAttribute
-
- for axis, configToProps := range m.GetArchVariantProperties(ctx, &ObjectLinkerProperties{}) {
- for config, props := range configToProps {
- if objectLinkerProps, ok := props.(*ObjectLinkerProperties); ok {
- if objectLinkerProps.Linker_script != nil {
- label := android.BazelLabelForModuleSrcSingle(ctx, *objectLinkerProps.Linker_script)
- linkerScript.SetSelectValue(axis, config, label)
- }
- 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))
- // static_libs, shared_libs, and header_libs have variant_prepend tag
- deps.Prepend = true
- }
- }
- }
- objs.ResolveExcludes()
-
- // Don't split cc_object srcs across languages. Doing so would add complexity,
- // and this isn't typically done for cc_object.
- srcs := compilerAttrs.srcs
- srcs.Append(compilerAttrs.cSrcs)
-
- asFlags := compilerAttrs.asFlags
- if compilerAttrs.asSrcs.IsEmpty() {
- // Skip asflags for BUILD file simplicity if there are no assembly sources.
- asFlags = bazel.MakeStringListAttribute(nil)
- }
-
- attrs := &bazelObjectAttributes{
- Srcs: srcs,
- Srcs_as: compilerAttrs.asSrcs,
- Objs: objs,
- Deps: deps,
- System_dynamic_deps: systemDynamicDeps,
- Copts: compilerAttrs.copts,
- Asflags: asFlags,
- Local_includes: compilerAttrs.localIncludes,
- Absolute_includes: compilerAttrs.absoluteIncludes,
- Stl: compilerAttrs.stl,
- Linker_script: linkerScript,
- Crt: m.linker.(*objectLinker).Properties.Crt,
- sdkAttributes: bp2BuildParseSdkAttributes(m),
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "cc_object",
- Bzl_load_location: "//build/bazel/rules/cc:cc_object.bzl",
- }
-
- tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: m.Name(),
- Tags: tags,
- }, attrs)
-}
-
func (object *objectLinker) appendLdflags(flags []string) {
panic(fmt.Errorf("appendLdflags on objectLinker not supported"))
}
@@ -348,6 +219,10 @@
return nil
}
+func (object *objectLinker) strippedAllOutputFilePath() android.Path {
+ panic("Not implemented.")
+}
+
func (object *objectLinker) nativeCoverage() bool {
return true
}
@@ -363,3 +238,8 @@
func (object *objectLinker) isCrt() bool {
return Bool(object.Properties.Crt)
}
+
+func (object *objectLinker) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ object.baseLinker.moduleInfoJSON(ctx, moduleInfoJSON)
+ moduleInfoJSON.Class = []string{"STATIC_LIBRARIES"}
+}
diff --git a/cc/object_test.go b/cc/object_test.go
index b1e2a0f..c0d1331 100644
--- a/cc/object_test.go
+++ b/cc/object_test.go
@@ -22,7 +22,7 @@
)
func TestMinSdkVersionsOfCrtObjects(t *testing.T) {
- ctx := testCc(t, `
+ bp := `
cc_object {
name: "crt_foo",
srcs: ["foo.c"],
@@ -30,8 +30,8 @@
stl: "none",
min_sdk_version: "28",
vendor_available: true,
- }`)
-
+ }
+ `
variants := []struct {
variant string
num string
@@ -43,11 +43,17 @@
{"android_arm64_armv8-a_sdk_current", "10000"},
{"android_vendor.29_arm64_armv8-a", "29"},
}
+
+ ctx := prepareForCcTest.RunTestWithBp(t, bp)
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)
}
+ ctx = prepareForCcTestWithoutVndk.RunTestWithBp(t, bp)
+ android.AssertStringDoesContain(t, "cflag",
+ ctx.ModuleForTests("crt_foo", "android_vendor_arm64_armv8-a").Rule("cc").Args["cFlags"],
+ "-target aarch64-linux-android10000 ")
}
func TestUseCrtObjectOfCorrectVersion(t *testing.T) {
@@ -85,30 +91,6 @@
})
}
-func TestCcObjectWithBazel(t *testing.T) {
- bp := `
-cc_object {
- name: "foo",
- srcs: ["baz.o"],
- bazel_module: { label: "//foo/bar:bar" },
-}`
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: "outputbase",
- LabelToOutputFiles: map[string][]string{
- "//foo/bar:bar": []string{"bazel_out.o"}}}
- ctx := testCcWithConfig(t, config)
-
- module := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon").Module()
- outputFiles, err := module.(android.OutputFileProducer).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
- }
-
- expectedOutputFiles := []string{"outputbase/execroot/__main__/bazel_out.o"}
- android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
-}
-
func TestCcObjectOutputFile(t *testing.T) {
testcases := []struct {
name string
diff --git a/cc/orderfile.go b/cc/orderfile.go
index b64c1c7..38b8905 100644
--- a/cc/orderfile.go
+++ b/cc/orderfile.go
@@ -20,6 +20,8 @@
import (
"fmt"
+ "github.com/google/blueprint"
+
"android/soong/android"
)
@@ -58,17 +60,17 @@
type OrderfileProperties struct {
Orderfile struct {
- Instrumentation *bool
- Order_file_path *string `android:"arch_variant"`
- Load_order_file *bool `android:"arch_variant"`
+ Instrumentation *bool
+ Order_file_path *string `android:"arch_variant"`
+ Load_order_file *bool `android:"arch_variant"`
// Additional compiler flags to use when building this module
// for orderfile profiling.
Cflags []string `android:"arch_variant"`
} `android:"arch_variant"`
- ShouldProfileModule bool `blueprint:"mutated"`
- OrderfileLoad bool `blueprint:"mutated"`
- OrderfileInstrLink bool `blueprint:"mutated"`
+ ShouldProfileModule bool `blueprint:"mutated"`
+ OrderfileLoad bool `blueprint:"mutated"`
+ OrderfileInstrLink bool `blueprint:"mutated"`
}
type orderfile struct {
@@ -128,7 +130,6 @@
return flags
}
-
func (props *OrderfileProperties) loadOrderfileFlags(ctx ModuleContext, file string) []string {
flags := []string{fmt.Sprintf(orderfileUseFormat, file)}
flags = append(flags, orderfileOtherFlags...)
@@ -191,66 +192,61 @@
return flags
}
-// Propagate profile orderfile flags down from binaries and shared libraries
-// We do not allow propagation for load flags because the orderfile is specific
-// to the module (binary / shared library)
-func orderfileDepsMutator(mctx android.TopDownMutatorContext) {
- if m, ok := mctx.Module().(*Module); ok {
- if !m.orderfile.orderfileLinkEnabled() {
- return
- }
- mctx.WalkDeps(func(dep android.
- Module, parent android.Module) bool {
- tag := mctx.OtherModuleDependencyTag(dep)
- libTag, isLibTag := tag.(libraryDependencyTag)
-
- // Do not recurse down non-static dependencies
- if isLibTag {
- if !libTag.static() {
- return false
- }
- } else {
- if tag != objDepTag && tag != reuseObjTag {
- return false
- }
- }
-
- if dep, ok := dep.(*Module); ok {
- if m.orderfile.Properties.OrderfileInstrLink {
- dep.orderfile.Properties.OrderfileInstrLink = true;
- }
- }
-
- return true
- })
+func orderfilePropagateViaDepTag(tag blueprint.DependencyTag) bool {
+ libTag, isLibTag := tag.(libraryDependencyTag)
+ // Do not recurse down non-static dependencies
+ if isLibTag {
+ return libTag.static()
+ } else {
+ return tag == objDepTag || tag == reuseObjTag || tag == staticVariantTag
}
}
-// Create orderfile variants for modules that need them
-func orderfileMutator(mctx android.BottomUpMutatorContext) {
- if m, ok := mctx.Module().(*Module); ok && m.orderfile != nil {
- if !m.static() && m.orderfile.orderfileEnabled() {
- mctx.SetDependencyVariation("orderfile")
- return
+// orderfileTransitionMutator creates orderfile variants of cc modules.
+type orderfileTransitionMutator struct{}
+
+const ORDERFILE_VARIATION = "orderfile"
+
+func (o *orderfileTransitionMutator) Split(ctx android.BaseModuleContext) []string {
+ return []string{""}
+}
+
+func (o *orderfileTransitionMutator) OutgoingTransition(ctx android.OutgoingTransitionContext, sourceVariation string) string {
+ if m, ok := ctx.Module().(*Module); ok && m.orderfile != nil {
+ if !orderfilePropagateViaDepTag(ctx.DepTag()) {
+ return ""
}
- variationNames := []string{""}
- if m.orderfile.Properties.OrderfileInstrLink {
- variationNames = append(variationNames, "orderfile")
+ if sourceVariation != "" {
+ return sourceVariation
}
- if len(variationNames) > 1 {
- modules := mctx.CreateVariations(variationNames...)
- for i, name := range variationNames {
- if name == "" {
- continue
- }
- variation := modules[i].(*Module)
- variation.Properties.PreventInstall = true
- variation.Properties.HideFromMake = true
- variation.orderfile.Properties.ShouldProfileModule = true
- variation.orderfile.Properties.OrderfileLoad = false
- }
+ // Propagate profile orderfile flags down from binaries and shared libraries
+ if m.orderfile.orderfileLinkEnabled() {
+ return ORDERFILE_VARIATION
}
}
+ return ""
+}
+
+func (o *orderfileTransitionMutator) IncomingTransition(ctx android.IncomingTransitionContext, incomingVariation string) string {
+ if m, ok := ctx.Module().(*Module); ok && m.orderfile != nil {
+ return incomingVariation
+ }
+ return ""
+}
+
+func (o *orderfileTransitionMutator) Mutate(ctx android.BottomUpMutatorContext, variation string) {
+ if variation == "" {
+ return
+ }
+
+ if m, ok := ctx.Module().(*Module); ok && m.orderfile != nil {
+ m.Properties.PreventInstall = true
+ m.Properties.HideFromMake = true
+ m.orderfile.Properties.ShouldProfileModule = true
+ // We do not allow propagation for load flags because the orderfile is specific
+ // to the module (binary / shared library)
+ m.orderfile.Properties.OrderfileLoad = false
+ }
}
diff --git a/cc/orderfile_test.go b/cc/orderfile_test.go
index f68457d..3486f96 100644
--- a/cc/orderfile_test.go
+++ b/cc/orderfile_test.go
@@ -15,8 +15,8 @@
package cc
import (
- "testing"
"strings"
+ "testing"
"android/soong/android"
)
@@ -193,8 +193,8 @@
}
// Check cFlags of orderfile variant static libraries
- libFooOfVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_orderfile")
- libBarOfVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_orderfile")
+ libFooOfVariant := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static_orderfile")
+ libBarOfVariant := result.ModuleForTests("libBar", "android_arm64_armv8-a_static_orderfile")
cFlags = libFooOfVariant.Rule("cc").Args["cFlags"]
if !strings.Contains(cFlags, expectedCFlag) {
@@ -216,8 +216,8 @@
}
// Check cFlags of the non-orderfile variant static libraries
- libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
- libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+ libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
+ libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
cFlags = libFoo.Rule("cc").Args["cFlags"]
if strings.Contains(cFlags, expectedCFlag) {
@@ -281,8 +281,8 @@
t.Errorf("Expected 'libTest' to load orderfile, but did not find %q in ldFlags %q", expectedCFlag, ldFlags)
}
- libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
- libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+ libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
+ libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
// Check dependency edge from orderfile-enabled module to non-orderfile variant static libraries
if !hasDirectDep(result, libTest.Module(), libFoo.Module()) {
@@ -351,8 +351,8 @@
}
// Check cFlags of the static and shared libraries
- libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_shared")
- libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+ libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_shared")
+ libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
cFlags = libFoo.Rule("cc").Args["cFlags"]
if strings.Contains(cFlags, expectedCFlag) {
@@ -431,8 +431,8 @@
}
// Check cFlags of the static libraries
- libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
- libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
+ libFoo := result.ModuleForTests("libFoo", "android_arm64_armv8-a_static")
+ libBar := result.ModuleForTests("libBar", "android_arm64_armv8-a_static")
cFlags = libFoo.Rule("cc").Args["cFlags"]
if strings.Contains(cFlags, expectedCFlag) {
@@ -467,4 +467,4 @@
t.Errorf("Expected variants for 'libBar' to not contain 'orderfile', but found %q", v)
}
}
-}
\ No newline at end of file
+}
diff --git a/cc/pgo.go b/cc/pgo.go
deleted file mode 100644
index 463e2e6..0000000
--- a/cc/pgo.go
+++ /dev/null
@@ -1,294 +0,0 @@
-// Copyright 2017 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 cc
-
-import (
- "fmt"
- "path/filepath"
- "strings"
-
- "github.com/google/blueprint/proptools"
-
- "android/soong/android"
-)
-
-var (
- // Add flags to ignore warnings that profiles are old or missing for
- // some functions.
- profileUseOtherFlags = []string{
- "-Wno-backend-plugin",
- }
-
- globalPgoProfileProjects = []string{
- "toolchain/pgo-profiles/pgo",
- "vendor/google_data/pgo_profile/pgo",
- }
-)
-
-var pgoProfileProjectsConfigKey = android.NewOnceKey("PgoProfileProjects")
-
-const profileInstrumentFlag = "-fprofile-generate=/data/local/tmp"
-const profileUseInstrumentFormat = "-fprofile-use=%s"
-
-func getPgoProfileProjects(config android.DeviceConfig) []string {
- return config.OnceStringSlice(pgoProfileProjectsConfigKey, func() []string {
- return append(globalPgoProfileProjects, config.PgoAdditionalProfileDirs()...)
- })
-}
-
-func recordMissingProfileFile(ctx BaseModuleContext, missing string) {
- getNamedMapForConfig(ctx.Config(), modulesMissingProfileFileKey).Store(missing, true)
-}
-
-type PgoProperties struct {
- Pgo struct {
- Instrumentation *bool
- Profile_file *string `android:"arch_variant"`
- Benchmarks []string
- Enable_profile_use *bool `android:"arch_variant"`
- // Additional compiler flags to use when building this module
- // for profiling.
- Cflags []string `android:"arch_variant"`
- } `android:"arch_variant"`
-
- PgoPresent bool `blueprint:"mutated"`
- ShouldProfileModule bool `blueprint:"mutated"`
- PgoCompile bool `blueprint:"mutated"`
- PgoInstrLink bool `blueprint:"mutated"`
-}
-
-type pgo struct {
- Properties PgoProperties
-}
-
-func (props *PgoProperties) isInstrumentation() bool {
- return props.Pgo.Instrumentation != nil && *props.Pgo.Instrumentation == true
-}
-
-func (pgo *pgo) props() []interface{} {
- return []interface{}{&pgo.Properties}
-}
-
-func (props *PgoProperties) addInstrumentationProfileGatherFlags(ctx ModuleContext, flags Flags) Flags {
- // Add to C flags iff PGO is explicitly enabled for this module.
- if props.ShouldProfileModule {
- flags.Local.CFlags = append(flags.Local.CFlags, props.Pgo.Cflags...)
- flags.Local.CFlags = append(flags.Local.CFlags, profileInstrumentFlag)
- }
- flags.Local.LdFlags = append(flags.Local.LdFlags, profileInstrumentFlag)
- return flags
-}
-
-func (props *PgoProperties) getPgoProfileFile(ctx BaseModuleContext) android.OptionalPath {
- profileFile := *props.Pgo.Profile_file
-
- // Test if the profile_file is present in any of the PGO profile projects
- for _, profileProject := range getPgoProfileProjects(ctx.DeviceConfig()) {
- // Bug: http://b/74395273 If the profile_file is unavailable,
- // use a versioned file named
- // <profile_file>.<arbitrary-version> when available. This
- // works around an issue where ccache serves stale cache
- // entries when the profile file has changed.
- globPattern := filepath.Join(profileProject, profileFile+".*")
- versionedProfiles, err := ctx.GlobWithDeps(globPattern, nil)
- if err != nil {
- ctx.ModuleErrorf("glob: %s", err.Error())
- }
-
- path := android.ExistentPathForSource(ctx, profileProject, profileFile)
- if path.Valid() {
- if len(versionedProfiles) != 0 {
- ctx.PropertyErrorf("pgo.profile_file", "Profile_file has multiple versions: "+filepath.Join(profileProject, profileFile)+", "+strings.Join(versionedProfiles, ", "))
- }
- return path
- }
-
- if len(versionedProfiles) > 1 {
- ctx.PropertyErrorf("pgo.profile_file", "Profile_file has multiple versions: "+strings.Join(versionedProfiles, ", "))
- } else if len(versionedProfiles) == 1 {
- return android.OptionalPathForPath(android.PathForSource(ctx, versionedProfiles[0]))
- }
- }
-
- // Record that this module's profile file is absent
- missing := *props.Pgo.Profile_file + ":" + ctx.ModuleDir() + "/Android.bp:" + ctx.ModuleName()
- recordMissingProfileFile(ctx, missing)
-
- return android.OptionalPathForPath(nil)
-}
-
-func (props *PgoProperties) profileUseFlags(ctx ModuleContext, file string) []string {
- flags := []string{fmt.Sprintf(profileUseInstrumentFormat, file)}
- flags = append(flags, profileUseOtherFlags...)
- return flags
-}
-
-func (props *PgoProperties) addProfileUseFlags(ctx ModuleContext, flags Flags) Flags {
- // Return if 'pgo' property is not present in this module.
- if !props.PgoPresent {
- return flags
- }
-
- if props.PgoCompile {
- profileFile := props.getPgoProfileFile(ctx)
- profileFilePath := profileFile.Path()
- profileUseFlags := props.profileUseFlags(ctx, profileFilePath.String())
-
- flags.Local.CFlags = append(flags.Local.CFlags, profileUseFlags...)
- flags.Local.LdFlags = append(flags.Local.LdFlags, profileUseFlags...)
-
- // Update CFlagsDeps and LdFlagsDeps so the module is rebuilt
- // if profileFile gets updated
- flags.CFlagsDeps = append(flags.CFlagsDeps, profileFilePath)
- flags.LdFlagsDeps = append(flags.LdFlagsDeps, profileFilePath)
- }
- return flags
-}
-
-func (props *PgoProperties) isPGO(ctx BaseModuleContext) bool {
- isInstrumentation := props.isInstrumentation()
-
- profileKindPresent := isInstrumentation
- filePresent := props.Pgo.Profile_file != nil
- benchmarksPresent := len(props.Pgo.Benchmarks) > 0
-
- // If all three properties are absent, PGO is OFF for this module
- if !profileKindPresent && !filePresent && !benchmarksPresent {
- return false
- }
-
- // profileKindPresent and filePresent are mandatory properties.
- if !profileKindPresent || !filePresent {
- var missing []string
- if !profileKindPresent {
- missing = append(missing, "profile kind")
- }
- if !filePresent {
- missing = append(missing, "profile_file property")
- }
- missingProps := strings.Join(missing, ", ")
- ctx.ModuleErrorf("PGO specification is missing properties: " + missingProps)
- }
-
- // Benchmark property is mandatory for instrumentation PGO.
- if isInstrumentation && !benchmarksPresent {
- ctx.ModuleErrorf("Instrumentation PGO specification is missing benchmark property")
- }
-
- return true
-}
-
-func (pgo *pgo) begin(ctx BaseModuleContext) {
- // TODO Evaluate if we need to support PGO for host modules
- if ctx.Host() {
- return
- }
-
- // Check if PGO is needed for this module
- pgo.Properties.PgoPresent = pgo.Properties.isPGO(ctx)
-
- if !pgo.Properties.PgoPresent {
- return
- }
-
- // This module should be instrumented if ANDROID_PGO_INSTRUMENT is set
- // and includes 'all', 'ALL' or a benchmark listed for this module.
- //
- // TODO Validate that each benchmark instruments at least one module
- pgo.Properties.ShouldProfileModule = false
- pgoBenchmarks := ctx.Config().Getenv("ANDROID_PGO_INSTRUMENT")
- pgoBenchmarksMap := make(map[string]bool)
- for _, b := range strings.Split(pgoBenchmarks, ",") {
- pgoBenchmarksMap[b] = true
- }
-
- if pgoBenchmarksMap["all"] == true || pgoBenchmarksMap["ALL"] == true {
- pgo.Properties.ShouldProfileModule = true
- pgo.Properties.PgoInstrLink = pgo.Properties.isInstrumentation()
- } else {
- for _, b := range pgo.Properties.Pgo.Benchmarks {
- if pgoBenchmarksMap[b] == true {
- pgo.Properties.ShouldProfileModule = true
- pgo.Properties.PgoInstrLink = pgo.Properties.isInstrumentation()
- break
- }
- }
- }
-
- // PGO profile use is not feasible for a Clang coverage build because
- // -fprofile-use and -fprofile-instr-generate are incompatible.
- if ctx.DeviceConfig().ClangCoverageEnabled() {
- return
- }
-
- if !ctx.Config().IsEnvTrue("ANDROID_PGO_NO_PROFILE_USE") &&
- proptools.BoolDefault(pgo.Properties.Pgo.Enable_profile_use, true) {
- if profileFile := pgo.Properties.getPgoProfileFile(ctx); profileFile.Valid() {
- pgo.Properties.PgoCompile = true
- }
- }
-}
-
-func (pgo *pgo) flags(ctx ModuleContext, flags Flags) Flags {
- if ctx.Host() {
- return flags
- }
-
- // Deduce PgoInstrLink property i.e. whether this module needs to be
- // linked with profile-generation flags. Here, we're setting it if any
- // dependency needs PGO instrumentation. It is initially set in
- // begin() if PGO is directly enabled for this module.
- if ctx.static() && !ctx.staticBinary() {
- // For static libraries, check if any whole_static_libs are
- // linked with profile generation
- ctx.VisitDirectDeps(func(m android.Module) {
- if depTag, ok := ctx.OtherModuleDependencyTag(m).(libraryDependencyTag); ok {
- if depTag.static() && depTag.wholeStatic {
- if cc, ok := m.(*Module); ok {
- if cc.pgo.Properties.PgoInstrLink {
- pgo.Properties.PgoInstrLink = true
- }
- }
- }
- }
- })
- } else {
- // For executables and shared libraries, check all static dependencies.
- ctx.VisitDirectDeps(func(m android.Module) {
- if depTag, ok := ctx.OtherModuleDependencyTag(m).(libraryDependencyTag); ok {
- if depTag.static() {
- if cc, ok := m.(*Module); ok {
- if cc.pgo.Properties.PgoInstrLink {
- pgo.Properties.PgoInstrLink = true
- }
- }
- }
- }
- })
- }
-
- props := pgo.Properties
- // Add flags to profile this module based on its profile_kind
- if (props.ShouldProfileModule && props.isInstrumentation()) || props.PgoInstrLink {
- // Instrumentation PGO use and gather flags cannot coexist.
- return props.addInstrumentationProfileGatherFlags(ctx, flags)
- }
-
- if !ctx.Config().IsEnvTrue("ANDROID_PGO_NO_PROFILE_USE") {
- flags = props.addProfileUseFlags(ctx, flags)
- }
-
- return flags
-}
diff --git a/cc/prebuilt.go b/cc/prebuilt.go
index a4ca590..8f4b7df 100644
--- a/cc/prebuilt.go
+++ b/cc/prebuilt.go
@@ -17,9 +17,9 @@
import (
"path/filepath"
+ "github.com/google/blueprint/proptools"
+
"android/soong/android"
- "android/soong/bazel"
- "android/soong/bazel/cquery"
)
func init() {
@@ -38,9 +38,15 @@
type prebuiltLinkerInterface interface {
Name(string) string
prebuilt() *android.Prebuilt
+ sourceModuleName() string
}
type prebuiltLinkerProperties struct {
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
+
// a prebuilt library or binary. Can reference a genrule module that generates an executable file.
Srcs []string `android:"path,arch_variant"`
@@ -57,13 +63,6 @@
// This is needed only if this library is linked by other modules in build time.
// Only makes sense for the Windows target.
Windows_import_lib *string `android:"path,arch_variant"`
-
- // MixedBuildsDisabled is true if and only if building this prebuilt is explicitly disabled in mixed builds for either
- // its static or shared version on the current build variant. This is to prevent Bazel targets for build variants with
- // which either the static or shared version is incompatible from participating in mixed buiods. Please note that this
- // is an override and does not fully determine whether Bazel or Soong will be used. For the full determination, see
- // cc.ProcessBazelQueryResponse, cc.QueueBazelCall, and cc.MixedBuildsDisabled.
- MixedBuildsDisabled bool `blueprint:"mutated"`
}
type prebuiltLinker struct {
@@ -141,7 +140,7 @@
if p.static() {
depSet := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).Direct(in).Build()
- ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+ android.SetProvider(ctx, StaticLibraryInfoProvider, StaticLibraryInfo{
StaticLibrary: in,
TransitiveStaticLibrariesForOrdering: depSet,
@@ -199,7 +198,7 @@
},
})
- ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+ android.SetProvider(ctx, SharedLibraryInfoProvider, SharedLibraryInfo{
SharedLibrary: outputFile,
Target: ctx.Target(),
@@ -222,7 +221,7 @@
}
if p.header() {
- ctx.SetProvider(HeaderLibraryInfoProvider, HeaderLibraryInfo{})
+ android.SetProvider(ctx, HeaderLibraryInfoProvider, HeaderLibraryInfo{})
// Need to return an output path so that the AndroidMk logic doesn't skip
// the prebuilt header. For compatibility, in case Android.mk files use a
@@ -261,7 +260,6 @@
func (p *prebuiltLibraryLinker) disablePrebuilt() {
p.properties.Srcs = nil
- p.properties.MixedBuildsDisabled = true
}
// Implements versionedInterface
@@ -272,8 +270,6 @@
func NewPrebuiltLibrary(hod android.HostOrDeviceSupported, srcsProperty string) (*Module, *libraryDecorator) {
module, library := NewLibrary(hod)
module.compiler = nil
- module.bazelable = true
- module.bazelHandler = &prebuiltLibraryBazelHandler{module: module, library: library}
prebuilt := &prebuiltLibraryLinker{
libraryDecorator: library,
@@ -348,84 +344,12 @@
return module, library
}
-type bazelPrebuiltLibraryStaticAttributes struct {
- Static_library bazel.LabelAttribute
- Export_includes bazel.StringListAttribute
- Export_system_includes bazel.StringListAttribute
- Alwayslink bazel.BoolAttribute
-}
-
-// TODO(b/228623543): The below is not entirely true until the bug is fixed. For now, both targets are always generated
-// Implements bp2build for cc_prebuilt_library modules. This will generate:
-// - Only a cc_prebuilt_library_static if the shared.enabled property is set to false across all variants.
-// - Only a cc_prebuilt_library_shared if the static.enabled property is set to false across all variants
-// - Both a cc_prebuilt_library_static and cc_prebuilt_library_shared if the aforementioned properties are not false across
-// all variants
-//
-// In all cases, cc_prebuilt_library_static target names will be appended with "_bp2build_cc_library_static".
-func prebuiltLibraryBp2Build(ctx android.TopDownMutatorContext, module *Module) {
- prebuiltLibraryStaticBp2Build(ctx, module, true)
- prebuiltLibrarySharedBp2Build(ctx, module)
-}
-
-func prebuiltLibraryStaticBp2Build(ctx android.TopDownMutatorContext, module *Module, fullBuild bool) {
- prebuiltAttrs := Bp2BuildParsePrebuiltLibraryProps(ctx, module, true)
- exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, nil)
-
- attrs := &bazelPrebuiltLibraryStaticAttributes{
- Static_library: prebuiltAttrs.Src,
- Export_includes: exportedIncludes.Includes,
- Export_system_includes: exportedIncludes.SystemIncludes,
- // TODO: ¿Alwayslink?
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "cc_prebuilt_library_static",
- Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_library_static.bzl",
- }
-
- name := android.RemoveOptionalPrebuiltPrefix(module.Name())
- if fullBuild {
- name += "_bp2build_cc_library_static"
- }
-
- tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
- ctx.CreateBazelTargetModuleWithRestrictions(props, android.CommonAttributes{Name: name, Tags: tags}, attrs, prebuiltAttrs.Enabled)
-
- _true := true
- alwayslinkAttrs := *attrs
- alwayslinkAttrs.Alwayslink.SetValue(&_true)
- ctx.CreateBazelTargetModuleWithRestrictions(props, android.CommonAttributes{Name: name + "_alwayslink", Tags: tags}, &alwayslinkAttrs, prebuiltAttrs.Enabled)
-}
-
-type bazelPrebuiltLibrarySharedAttributes struct {
- Shared_library bazel.LabelAttribute
- Export_includes bazel.StringListAttribute
- Export_system_includes bazel.StringListAttribute
-}
-
-func prebuiltLibrarySharedBp2Build(ctx android.TopDownMutatorContext, module *Module) {
- prebuiltAttrs := Bp2BuildParsePrebuiltLibraryProps(ctx, module, false)
- exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, nil)
-
- attrs := &bazelPrebuiltLibrarySharedAttributes{
- Shared_library: prebuiltAttrs.Src,
- Export_includes: exportedIncludes.Includes,
- Export_system_includes: exportedIncludes.SystemIncludes,
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "cc_prebuilt_library_shared",
- Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_library_shared.bzl",
- }
-
- name := android.RemoveOptionalPrebuiltPrefix(module.Name())
- tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
- ctx.CreateBazelTargetModuleWithRestrictions(props, android.CommonAttributes{Name: name, Tags: tags}, attrs, prebuiltAttrs.Enabled)
-}
-
type prebuiltObjectProperties struct {
- Srcs []string `android:"path,arch_variant"`
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
+ Srcs []string `android:"path,arch_variant"`
}
type prebuiltObjectLinker struct {
@@ -435,139 +359,14 @@
properties prebuiltObjectProperties
}
-type prebuiltLibraryBazelHandler struct {
- module *Module
- library *libraryDecorator
-}
-
-var _ BazelHandler = (*prebuiltLibraryBazelHandler)(nil)
-
-func (h *prebuiltLibraryBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
- if h.module.linker.(*prebuiltLibraryLinker).properties.MixedBuildsDisabled {
- return
- }
- bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(label, cquery.GetCcInfo, android.GetConfigKey(ctx))
-}
-
-func (h *prebuiltLibraryBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
- if h.module.linker.(*prebuiltLibraryLinker).properties.MixedBuildsDisabled {
- return
- }
- bazelCtx := ctx.Config().BazelContext
- ccInfo, err := bazelCtx.GetCcInfo(label, android.GetConfigKey(ctx))
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- return
- }
-
- if h.module.static() {
- if ok := h.processStaticBazelQueryResponse(ctx, label, ccInfo); !ok {
- return
- }
- } else if h.module.Shared() {
- if ok := h.processSharedBazelQueryResponse(ctx, label, ccInfo); !ok {
- return
- }
- } else {
- return
- }
-
- h.module.maybeUnhideFromMake()
-
- h.module.setAndroidMkVariablesFromCquery(ccInfo.CcAndroidMkInfo)
-}
-
-func (h *prebuiltLibraryBazelHandler) processStaticBazelQueryResponse(ctx android.ModuleContext, label string, ccInfo cquery.CcInfo) bool {
- staticLibs := ccInfo.CcStaticLibraryFiles
- if len(staticLibs) > 1 {
- ctx.ModuleErrorf("expected 1 static library from bazel target %q, got %s", label, staticLibs)
- return false
- }
-
- // TODO(b/184543518): cc_prebuilt_library_static may have properties for re-exporting flags
-
- // TODO(eakammer):Add stub-related flags if this library is a stub library.
- // h.library.exportVersioningMacroIfNeeded(ctx)
-
- // Dependencies on this library will expect collectedSnapshotHeaders to be set, otherwise
- // validation will fail. For now, set this to an empty list.
- // TODO(cparsons): More closely mirror the collectHeadersForSnapshot implementation.
- h.library.collectedSnapshotHeaders = android.Paths{}
-
- if len(staticLibs) == 0 {
- h.module.outputFile = android.OptionalPath{}
- return true
- }
-
- var outputPath android.Path = android.PathForBazelOut(ctx, staticLibs[0])
- if len(ccInfo.TidyFiles) > 0 {
- h.module.tidyFiles = android.PathsForBazelOut(ctx, ccInfo.TidyFiles)
- outputPath = android.AttachValidationActions(ctx, outputPath, h.module.tidyFiles)
- }
-
- h.module.outputFile = android.OptionalPathForPath(outputPath)
-
- depSet := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).Direct(outputPath).Build()
- ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
- StaticLibrary: outputPath,
- TransitiveStaticLibrariesForOrdering: depSet,
- })
-
- return true
-}
-
-func (h *prebuiltLibraryBazelHandler) processSharedBazelQueryResponse(ctx android.ModuleContext, label string, ccInfo cquery.CcInfo) bool {
- sharedLibs := ccInfo.CcSharedLibraryFiles
- if len(sharedLibs) > 1 {
- ctx.ModuleErrorf("expected 1 shared library from bazel target %s, got %q", label, sharedLibs)
- return false
- }
-
- // TODO(b/184543518): cc_prebuilt_library_shared may have properties for re-exporting flags
-
- // TODO(eakammer):Add stub-related flags if this library is a stub library.
- // h.library.exportVersioningMacroIfNeeded(ctx)
-
- if len(sharedLibs) == 0 {
- h.module.outputFile = android.OptionalPath{}
- return true
- }
-
- var outputPath android.Path = android.PathForBazelOut(ctx, sharedLibs[0])
- if len(ccInfo.TidyFiles) > 0 {
- h.module.tidyFiles = android.PathsForBazelOut(ctx, ccInfo.TidyFiles)
- outputPath = android.AttachValidationActions(ctx, outputPath, h.module.tidyFiles)
- }
-
- h.module.outputFile = android.OptionalPathForPath(outputPath)
-
- // FIXME(b/214600441): We don't yet strip prebuilt shared libraries
- h.library.unstrippedOutputFile = outputPath
-
- var toc android.Path
- if len(ccInfo.TocFile) > 0 {
- toc = android.PathForBazelOut(ctx, ccInfo.TocFile)
- } else {
- toc = outputPath // Just reuse `out` so ninja still gets an input but won't matter
- }
-
- info := SharedLibraryInfo{
- SharedLibrary: outputPath,
- TableOfContents: android.OptionalPathForPath(toc),
- Target: ctx.Target(),
- }
- ctx.SetProvider(SharedLibraryInfoProvider, info)
-
- h.library.setFlagExporterInfoFromCcInfo(ctx, ccInfo)
- h.module.maybeUnhideFromMake()
- return true
-}
-
func (p *prebuiltObjectLinker) prebuilt() *android.Prebuilt {
return &p.Prebuilt
}
+func (p *prebuiltObjectLinker) sourceModuleName() string {
+ return proptools.String(p.properties.Source_module_name)
+}
+
var _ prebuiltLinkerInterface = (*prebuiltObjectLinker)(nil)
func (p *prebuiltObjectLinker) link(ctx ModuleContext,
@@ -593,8 +392,6 @@
func NewPrebuiltObject(hod android.HostOrDeviceSupported) *Module {
module := newObject(hod)
- module.bazelHandler = &prebuiltObjectBazelHandler{module: module}
- module.bazelable = true
prebuilt := &prebuiltObjectLinker{
objectLinker: objectLinker{
baseLinker: NewBaseLinker(nil),
@@ -606,54 +403,6 @@
return 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.ApexAvailableTagsWithoutTestApexes(ctx, module)
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name, Tags: tags}, attrs)
-}
-
func PrebuiltObjectFactory() android.Module {
module := NewPrebuiltObject(android.HostAndDeviceSupported)
return module.Init()
@@ -747,15 +496,9 @@
return module.Init()
}
-type prebuiltBinaryBazelHandler struct {
- module *Module
- decorator *binaryDecorator
-}
-
func NewPrebuiltBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
- module, binary := newBinary(hod, true)
+ module, binary := newBinary(hod)
module.compiler = nil
- module.bazelHandler = &prebuiltBinaryBazelHandler{module, binary}
prebuilt := &prebuiltBinaryLinker{
binaryDecorator: binary,
@@ -769,54 +512,6 @@
return module, binary
}
-var _ BazelHandler = (*prebuiltBinaryBazelHandler)(nil)
-
-func (h *prebuiltBinaryBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
- bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(label, cquery.GetOutputFiles, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(ctx)))
-}
-
-func (h *prebuiltBinaryBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
- bazelCtx := ctx.Config().BazelContext
- outputs, err := bazelCtx.GetOutputFiles(label, android.GetConfigKeyApexVariant(ctx, GetApexConfigKey(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 bazelPrebuiltBinaryAttributes struct {
- Src bazel.LabelAttribute
- Strip stripAttributes
-}
-
-func prebuiltBinaryBp2Build(ctx android.TopDownMutatorContext, module *Module) {
- prebuiltAttrs := bp2BuildParsePrebuiltBinaryProps(ctx, module)
-
- var la linkerAttributes
- la.convertStripProps(ctx, module)
- attrs := &bazelPrebuiltBinaryAttributes{
- Src: prebuiltAttrs.Src,
- Strip: stripAttrsFromLinkerAttrs(&la),
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "cc_prebuilt_binary",
- Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_binary.bzl",
- }
-
- name := android.RemoveOptionalPrebuiltPrefix(module.Name())
- tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module)
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name, Tags: tags}, attrs)
-}
-
type Sanitized struct {
None struct {
Srcs []string `android:"path,arch_variant"`
@@ -841,3 +536,7 @@
}
return sanitized.None.Srcs
}
+
+func (p *prebuiltLinker) sourceModuleName() string {
+ return proptools.String(p.properties.Source_module_name)
+}
diff --git a/cc/prebuilt_test.go b/cc/prebuilt_test.go
index 0c79e55..95fb7ed 100644
--- a/cc/prebuilt_test.go
+++ b/cc/prebuilt_test.go
@@ -15,12 +15,11 @@
package cc
import (
+ "fmt"
"runtime"
"testing"
"android/soong/android"
- "android/soong/bazel/cquery"
-
"github.com/google/blueprint"
)
@@ -386,289 +385,6 @@
assertString(t, static2.OutputFile().Path().Base(), "libf.hwasan.a")
}
-func TestPrebuiltLibraryWithBazel(t *testing.T) {
- const bp = `
-cc_prebuilt_library {
- name: "foo",
- shared: {
- srcs: ["foo.so"],
- },
- static: {
- srcs: ["foo.a"],
- },
- bazel_module: { label: "//foo/bar:bar" },
-}`
- outBaseDir := "outputbase"
- result := android.GroupFixturePreparers(
- prepareForPrebuiltTest,
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: outBaseDir,
- LabelToCcInfo: map[string]cquery.CcInfo{
- "//foo/bar:bar": cquery.CcInfo{
- CcSharedLibraryFiles: []string{"foo.so"},
- },
- "//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{
- CcStaticLibraryFiles: []string{"foo.a"},
- },
- },
- }
- }),
- ).RunTestWithBp(t, bp)
- sharedFoo := result.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
- pathPrefix := outBaseDir + "/execroot/__main__/"
-
- sharedInfo := result.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
- android.AssertPathRelativeToTopEquals(t,
- "prebuilt library shared target path did not exist or did not match expected. If the base path is what does not match, it is likely that Soong built this module instead of Bazel.",
- pathPrefix+"foo.so", sharedInfo.SharedLibrary)
-
- outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
- }
- expectedOutputFiles := []string{pathPrefix + "foo.so"}
- android.AssertDeepEquals(t,
- "prebuilt library shared target output files did not match expected.",
- expectedOutputFiles, outputFiles.Strings())
-
- staticFoo := result.ModuleForTests("foo", "android_arm_armv7-a-neon_static").Module()
- staticInfo := result.ModuleProvider(staticFoo, StaticLibraryInfoProvider).(StaticLibraryInfo)
- android.AssertPathRelativeToTopEquals(t,
- "prebuilt library static target path did not exist or did not match expected. If the base path is what does not match, it is likely that Soong built this module instead of Bazel.",
- pathPrefix+"foo.a", staticInfo.StaticLibrary)
-
- staticOutputFiles, err := staticFoo.(android.OutputFileProducer).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_object staticOutputFiles %s", err)
- }
- expectedStaticOutputFiles := []string{pathPrefix + "foo.a"}
- android.AssertDeepEquals(t,
- "prebuilt library static target output files did not match expected.",
- expectedStaticOutputFiles, staticOutputFiles.Strings())
-}
-
-func TestPrebuiltLibraryWithBazelValidations(t *testing.T) {
- const bp = `
-cc_prebuilt_library {
- name: "foo",
- shared: {
- srcs: ["foo.so"],
- },
- static: {
- srcs: ["foo.a"],
- },
- bazel_module: { label: "//foo/bar:bar" },
- tidy: true,
-}`
- outBaseDir := "outputbase"
- result := android.GroupFixturePreparers(
- prepareForPrebuiltTest,
- android.FixtureMergeEnv(map[string]string{
- "ALLOW_LOCAL_TIDY_TRUE": "1",
- }),
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: outBaseDir,
- LabelToCcInfo: map[string]cquery.CcInfo{
- "//foo/bar:bar": cquery.CcInfo{
- CcSharedLibraryFiles: []string{"foo.so"},
- TidyFiles: []string{"foo.c.tidy"},
- },
- "//foo/bar:bar_bp2build_cc_library_static": cquery.CcInfo{
- CcStaticLibraryFiles: []string{"foo.a"},
- TidyFiles: []string{"foo.c.tidy"},
- },
- },
- }
- }),
- ).RunTestWithBp(t, bp)
- sharedFoo := result.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
-
- expectedOutputFile := "out/soong/.intermediates/foo/android_arm_armv7-a-neon_shared/validated/foo.so"
- sharedInfo := result.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
- android.AssertPathRelativeToTopEquals(t,
- "prebuilt library shared target path did not exist or did not match expected. If the base path is what does not match, it is likely that Soong built this module instead of Bazel.",
- expectedOutputFile, sharedInfo.SharedLibrary)
-
- outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
- }
- expectedOutputFiles := []string{expectedOutputFile}
- android.AssertPathsRelativeToTopEquals(t,
- "prebuilt library shared target output files did not match expected.",
- expectedOutputFiles, outputFiles)
-
- staticFoo := result.ModuleForTests("foo", "android_arm_armv7-a-neon_static").Module()
- staticInfo := result.ModuleProvider(staticFoo, StaticLibraryInfoProvider).(StaticLibraryInfo)
- expectedStaticOutputFile := "out/soong/.intermediates/foo/android_arm_armv7-a-neon_static/validated/foo.a"
- android.AssertPathRelativeToTopEquals(t,
- "prebuilt library static target path did not exist or did not match expected. If the base path is what does not match, it is likely that Soong built this module instead of Bazel.",
- expectedStaticOutputFile, staticInfo.StaticLibrary)
-
- staticOutputFiles, err := staticFoo.(android.OutputFileProducer).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_object staticOutputFiles %s", err)
- }
- expectedStaticOutputFiles := []string{expectedStaticOutputFile}
- android.AssertPathsRelativeToTopEquals(t,
- "prebuilt library static target output files did not match expected.",
- expectedStaticOutputFiles, staticOutputFiles)
-}
-
-func TestPrebuiltLibraryWithBazelStaticDisabled(t *testing.T) {
- const bp = `
-cc_prebuilt_library {
- name: "foo",
- shared: {
- srcs: ["foo.so"],
- },
- static: {
- enabled: false
- },
- bazel_module: { label: "//foo/bar:bar" },
-}`
- outBaseDir := "outputbase"
- result := android.GroupFixturePreparers(
- prepareForPrebuiltTest,
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: outBaseDir,
- LabelToCcInfo: map[string]cquery.CcInfo{
- "//foo/bar:bar": cquery.CcInfo{
- CcSharedLibraryFiles: []string{"foo.so"},
- },
- },
- }
- }),
- ).RunTestWithBp(t, bp)
- sharedFoo := result.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
- pathPrefix := outBaseDir + "/execroot/__main__/"
-
- sharedInfo := result.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
- android.AssertPathRelativeToTopEquals(t,
- "prebuilt library shared target path did not exist or did not match expected. If the base path is what does not match, it is likely that Soong built this module instead of Bazel.",
- pathPrefix+"foo.so", sharedInfo.SharedLibrary)
-
- outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
- }
- expectedOutputFiles := []string{pathPrefix + "foo.so"}
- android.AssertDeepEquals(t,
- "prebuilt library shared target output files did not match expected.",
- expectedOutputFiles, outputFiles.Strings())
-}
-
-func TestPrebuiltLibraryStaticWithBazel(t *testing.T) {
- const bp = `
-cc_prebuilt_library_static {
- name: "foo",
- srcs: ["foo.so"],
- bazel_module: { label: "//foo/bar:bar" },
-}`
- outBaseDir := "outputbase"
- result := android.GroupFixturePreparers(
- prepareForPrebuiltTest,
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: outBaseDir,
- LabelToCcInfo: map[string]cquery.CcInfo{
- "//foo/bar:bar": cquery.CcInfo{
- CcStaticLibraryFiles: []string{"foo.so"},
- },
- },
- }
- }),
- ).RunTestWithBp(t, bp)
- staticFoo := result.ModuleForTests("foo", "android_arm_armv7-a-neon_static").Module()
- pathPrefix := outBaseDir + "/execroot/__main__/"
-
- info := result.ModuleProvider(staticFoo, StaticLibraryInfoProvider).(StaticLibraryInfo)
- android.AssertPathRelativeToTopEquals(t,
- "prebuilt library static path did not match expected. If the base path is what does not match, it is likely that Soong built this module instead of Bazel.",
- pathPrefix+"foo.so", info.StaticLibrary)
-
- outputFiles, err := staticFoo.(android.OutputFileProducer).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
- }
- expectedOutputFiles := []string{pathPrefix + "foo.so"}
- android.AssertDeepEquals(t, "prebuilt library static output files did not match expected.", expectedOutputFiles, outputFiles.Strings())
-}
-
-func TestPrebuiltLibrarySharedWithBazelWithoutToc(t *testing.T) {
- const bp = `
-cc_prebuilt_library_shared {
- name: "foo",
- srcs: ["foo.so"],
- bazel_module: { label: "//foo/bar:bar" },
-}`
- outBaseDir := "outputbase"
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: outBaseDir,
- LabelToCcInfo: map[string]cquery.CcInfo{
- "//foo/bar:bar": cquery.CcInfo{
- CcSharedLibraryFiles: []string{"foo.so"},
- },
- },
- }
- ctx := testCcWithConfig(t, config)
- sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
- pathPrefix := outBaseDir + "/execroot/__main__/"
-
- info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
- android.AssertPathRelativeToTopEquals(t, "prebuilt shared library",
- pathPrefix+"foo.so", info.SharedLibrary)
- android.AssertPathRelativeToTopEquals(t, "prebuilt's 'nullary' ToC",
- pathPrefix+"foo.so", info.TableOfContents.Path())
-
- outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
- }
- expectedOutputFiles := []string{pathPrefix + "foo.so"}
- android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
-}
-
-func TestPrebuiltLibrarySharedWithBazelWithToc(t *testing.T) {
- const bp = `
-cc_prebuilt_library_shared {
- name: "foo",
- srcs: ["foo.so"],
- bazel_module: { label: "//foo/bar:bar" },
-}`
- outBaseDir := "outputbase"
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: outBaseDir,
- LabelToCcInfo: map[string]cquery.CcInfo{
- "//foo/bar:bar": cquery.CcInfo{
- CcSharedLibraryFiles: []string{"foo.so"},
- TocFile: "toc",
- },
- },
- }
- ctx := testCcWithConfig(t, config)
- sharedFoo := ctx.ModuleForTests("foo", "android_arm_armv7-a-neon_shared").Module()
- pathPrefix := outBaseDir + "/execroot/__main__/"
-
- info := ctx.ModuleProvider(sharedFoo, SharedLibraryInfoProvider).(SharedLibraryInfo)
- android.AssertPathRelativeToTopEquals(t, "prebuilt shared library's ToC",
- pathPrefix+"toc", info.TableOfContents.Path())
- android.AssertPathRelativeToTopEquals(t, "prebuilt shared library",
- pathPrefix+"foo.so", info.SharedLibrary)
-
- outputFiles, err := sharedFoo.(android.OutputFileProducer).OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting cc_object outputfiles %s", err)
- }
- expectedOutputFiles := []string{pathPrefix + "foo.so"}
- android.AssertDeepEquals(t, "output files", expectedOutputFiles, outputFiles.Strings())
-}
-
func TestPrebuiltStubNoinstall(t *testing.T) {
testFunc := func(t *testing.T, expectLibfooOnSystemLib bool, fs android.MockFS) {
result := android.GroupFixturePreparers(
@@ -795,26 +511,99 @@
testCcError(t, `Android.bp:4:6: module "bintest" variant "android_arm64_armv8-a": srcs: multiple prebuilt source files`, bp)
}
-func TestPrebuiltBinaryWithBazel(t *testing.T) {
- const bp = `
-cc_prebuilt_binary {
- name: "bintest",
- srcs: ["bin"],
- bazel_module: { label: "//bin/foo:foo" },
-}`
- const outBaseDir = "outputbase"
- const expectedOut = outBaseDir + "/execroot/__main__/bin"
- config := TestConfig(t.TempDir(), android.Android, nil, bp, nil)
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: outBaseDir,
- LabelToOutputFiles: map[string][]string{"//bin/foo:foo": []string{"bin"}},
+func TestMultiplePrebuilts(t *testing.T) {
+ bp := `
+ // an rdep
+ cc_library {
+ name: "libfoo",
+ shared_libs: ["libbar"],
+ }
+
+ // multiple variations of dep
+ // source
+ cc_library {
+ name: "libbar",
+ }
+ // prebuilt "v1"
+ cc_prebuilt_library_shared {
+ name: "libbar",
+ srcs: ["libbar.so"],
+ }
+ // prebuilt "v2"
+ cc_prebuilt_library_shared {
+ name: "libbar.v2",
+ stem: "libbar",
+ source_module_name: "libbar",
+ srcs: ["libbar.so"],
+ }
+
+ // selectors
+ apex_contributions {
+ name: "myapex_contributions",
+ contents: ["%v"],
+ }
+ all_apex_contributions {name: "all_apex_contributions"}
+ `
+ hasDep := func(ctx *android.TestContext, m android.Module, wantDep android.Module) bool {
+ t.Helper()
+ var found bool
+ ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
+ if dep == wantDep {
+ found = true
+ }
+ })
+ return found
}
- ctx := testCcWithConfig(t, config)
- bin := ctx.ModuleForTests("bintest", "android_arm64_armv8-a").Module().(*Module)
- out := bin.OutputFile()
- if !out.Valid() {
- t.Error("Invalid output file")
- return
+
+ testCases := []struct {
+ desc string
+ selectedDependencyName string
+ expectedDependencyName string
+ }{
+ {
+ desc: "Source library is selected using apex_contributions",
+ selectedDependencyName: "libbar",
+ expectedDependencyName: "libbar",
+ },
+ {
+ desc: "Prebuilt library v1 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_libbar",
+ expectedDependencyName: "prebuilt_libbar",
+ },
+ {
+ desc: "Prebuilt library v2 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_libbar.v2",
+ expectedDependencyName: "prebuilt_libbar.v2",
+ },
}
- android.AssertStringEquals(t, "output file", expectedOut, out.String())
+
+ for _, tc := range testCases {
+ preparer := android.GroupFixturePreparers(
+ android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
+ android.RegisterApexContributionsBuildComponents(ctx)
+ }),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
+ }
+ }),
+ )
+ ctx := testPrebuilt(t, fmt.Sprintf(bp, tc.selectedDependencyName), map[string][]byte{
+ "libbar.so": nil,
+ "crtx.o": nil,
+ }, preparer)
+ libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared").Module()
+ expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
+ android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", libfoo.Name(), tc.expectedDependencyName), true, hasDep(ctx, libfoo, expectedDependency))
+
+ // check installation rules
+ // the selected soong module should be exported to make
+ libbar := ctx.ModuleForTests(tc.expectedDependencyName, "android_arm64_armv8-a_shared").Module()
+ android.AssertBoolEquals(t, fmt.Sprintf("dependency %s should be exported to make\n", expectedDependency), true, !libbar.IsHideFromMake())
+
+ // check LOCAL_MODULE of the selected module name
+ // the prebuilt should have the same LOCAL_MODULE when exported to make
+ entries := android.AndroidMkEntriesForTest(t, ctx, libbar)[0]
+ android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "libbar", entries.EntryMap["LOCAL_MODULE"][0])
+ }
}
diff --git a/cc/proto.go b/cc/proto.go
index 0ed4381..4d72f26 100644
--- a/cc/proto.go
+++ b/cc/proto.go
@@ -19,7 +19,6 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel"
)
const (
@@ -163,109 +162,3 @@
return flags
}
-
-type protoAttributes struct {
- Deps bazel.LabelListAttribute
-
- // A list of proto_library targets that that the proto_library in `deps` depends on
- // This list is overestimation.
- // Overestimation is necessary since Soong includes other protos via proto.include_dirs and not
- // a specific .proto file module explicitly.
- Transitive_deps bazel.LabelListAttribute
-
- // A list of cc_library_* targets that the generated cpp code depends on
- Cc_deps bazel.LabelListAttribute
-
- Min_sdk_version *string
-}
-
-type bp2buildProtoDeps struct {
- wholeStaticLib *bazel.LabelAttribute
- implementationWholeStaticLib *bazel.LabelAttribute
- protoDep *bazel.LabelAttribute
-}
-
-func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute, la linkerAttributes) bp2buildProtoDeps {
- var ret bp2buildProtoDeps
-
- protoInfo, ok := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, protoSrcs)
- if !ok || protoInfo.Proto_libs.IsEmpty() {
- return ret
- }
-
- var depName string
- typ := proptools.StringDefault(protoInfo.Type, protoTypeDefault)
- var rule_class string
- suffix := "_cc_proto"
- switch typ {
- case "lite":
- suffix += "_lite"
- rule_class = "cc_lite_proto_library"
- depName = "libprotobuf-cpp-lite"
- case "full":
- rule_class = "cc_proto_library"
- depName = "libprotobuf-cpp-full"
- default:
- ctx.PropertyErrorf("proto.type", "cannot handle conversion at this time: %q", typ)
- }
-
- dep := android.BazelLabelForModuleDepSingle(ctx, depName)
- ret.protoDep = &bazel.LabelAttribute{Value: &dep}
-
- var protoAttrs protoAttributes
- protoAttrs.Deps.SetValue(protoInfo.Proto_libs)
- protoAttrs.Transitive_deps.SetValue(protoInfo.Transitive_proto_libs)
-
- // Add the implementation deps of the top-level cc_library_static
- // This is necessary to compile the internal root of cc_proto_library.
- // Without this, clang might not be able to find .h files that the generated cpp files depends on
- protoAttrs.Cc_deps = *la.implementationDeps.Clone()
- protoAttrs.Cc_deps.Append(la.implementationDynamicDeps)
- protoAttrs.Cc_deps.Append(la.implementationWholeArchiveDeps)
- protoAttrs.Cc_deps.Append(la.wholeArchiveDeps)
- // Subtract myself to prevent possible circular dep
- protoAttrs.Cc_deps = bazel.SubtractBazelLabelListAttribute(
- protoAttrs.Cc_deps,
- bazel.MakeLabelListAttribute(
- bazel.MakeLabelList([]bazel.Label{
- bazel.Label{Label: ":" + m.Name() + suffix},
- }),
- ),
- )
- // Subtract the protobuf libraries since cc_proto_library implicitly adds them
- protoAttrs.Cc_deps = bazel.SubtractBazelLabelListAttribute(
- protoAttrs.Cc_deps,
- bazel.MakeLabelListAttribute(
- bazel.MakeLabelList([]bazel.Label{
- bazel.Label{Label: "//external/protobuf:libprotobuf-cpp-full", OriginalModuleName: "libprotobuf-cpp-full"},
- bazel.Label{Label: "//external/protobuf:libprotobuf-cpp-lite", OriginalModuleName: "libprotobuf-cpp-lite"},
- }),
- ),
- )
-
- protoAttrs.Min_sdk_version = m.Properties.Min_sdk_version
-
- name := m.Name() + suffix
- tags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), m)
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: rule_class,
- Bzl_load_location: "//build/bazel/rules/cc:cc_proto.bzl",
- },
- android.CommonAttributes{Name: name, Tags: tags},
- &protoAttrs)
-
- var privateHdrs bool
- if lib, ok := m.linker.(*libraryDecorator); ok {
- privateHdrs = !proptools.Bool(lib.Properties.Proto.Export_proto_headers)
- }
-
- labelAttr := &bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + name}}
- if privateHdrs {
- ret.implementationWholeStaticLib = labelAttr
- } else {
- ret.wholeStaticLib = labelAttr
- }
-
- return ret
-}
diff --git a/cc/rs.go b/cc/rs.go
index 93acdc7..b0d759b 100644
--- a/cc/rs.go
+++ b/cc/rs.go
@@ -20,7 +20,6 @@
"strings"
"android/soong/android"
- "android/soong/bazel"
"github.com/google/blueprint"
)
@@ -134,35 +133,3 @@
return flags
}
-
-type rscriptAttributes struct {
- // Renderscript source files
- Srcs bazel.LabelListAttribute
-}
-
-func bp2buildRScript(ctx android.Bp2buildMutatorContext, m *Module, ca compilerAttributes) (bazel.LabelAttribute, bazel.StringListAttribute, bazel.StringListAttribute) {
- var rscriptAttrs rscriptAttributes
- var rsAbsIncludes bazel.StringListAttribute
- var localIncludes bazel.StringListAttribute
- var rsModuleName string
- var convertedRsSrcsLabel bazel.LabelAttribute
-
- if !ca.rscriptSrcs.IsEmpty() {
- rscriptAttrs.Srcs = ca.rscriptSrcs
- rsModuleName = m.Name() + "_renderscript"
-
- localIncludes.Value = []string{"."}
- rsAbsIncludes.Value = []string{"frameworks/rs", "frameworks/rs/cpp"}
- convertedRsSrcsLabel = bazel.LabelAttribute{Value: &bazel.Label{Label: rsModuleName}}
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "rscript_to_cpp",
- Bzl_load_location: "//build/bazel/rules/cc:rscript_to_cpp.bzl",
- },
- android.CommonAttributes{Name: rsModuleName},
- &rscriptAttrs)
- }
-
- return convertedRsSrcsLabel, rsAbsIncludes, localIncludes
-}
diff --git a/cc/sabi.go b/cc/sabi.go
index 4cd776a..4ca9f5c 100644
--- a/cc/sabi.go
+++ b/cc/sabi.go
@@ -97,49 +97,34 @@
return sabi != nil && sabi.Properties.ShouldCreateSourceAbiDump
}
-// Returns a string that represents the class of the ABI dump.
-// Returns an empty string if ABI check is disabled for this library.
-func classifySourceAbiDump(ctx android.BaseModuleContext) string {
+// Returns a slice of strings that represent the ABI dumps generated for this module.
+func classifySourceAbiDump(ctx android.BaseModuleContext) []string {
+ result := []string{}
m := ctx.Module().(*Module)
headerAbiChecker := m.library.getHeaderAbiCheckerProperties(ctx)
if headerAbiChecker.explicitlyDisabled() {
- return ""
+ return result
}
- // Return NDK if the library is both NDK and LLNDK.
- if m.IsNdk(ctx.Config()) {
- return "NDK"
- }
- if m.isImplementationForLLNDKPublic() {
- return "LLNDK"
- }
- if m.UseVndk() && m.IsVndk() && !m.IsVndkPrivate() {
- if m.IsVndkSp() {
- if m.IsVndkExt() {
- return "VNDK-SP-ext"
- } else {
- return "VNDK-SP"
- }
- } else {
- if m.IsVndkExt() {
- return "VNDK-ext"
- } else {
- return "VNDK-core"
- }
+ if !m.InProduct() && !m.InVendor() {
+ if m.isImplementationForLLNDKPublic() {
+ result = append(result, "LLNDK")
}
- }
- if m.library.hasStubsVariants() && !m.InProduct() && !m.InVendor() {
- return "PLATFORM"
- }
- if headerAbiChecker.enabled() {
+ // Return NDK if the library is both NDK and APEX.
+ // TODO(b/309880485): Split NDK and APEX ABI.
+ if m.IsNdk(ctx.Config()) {
+ result = append(result, "NDK")
+ } else if m.library.hasStubsVariants() || headerAbiChecker.enabled() {
+ result = append(result, "PLATFORM")
+ }
+ } else if headerAbiChecker.enabled() {
if m.InProduct() {
- return "PRODUCT"
+ result = append(result, "PRODUCT")
}
if m.InVendor() {
- return "VENDOR"
+ result = append(result, "VENDOR")
}
- return "PLATFORM"
}
- return ""
+ return result
}
// Called from sabiDepsMutator to check whether ABI dumps should be created for this module.
@@ -194,8 +179,8 @@
return false
}
- isPlatformVariant := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
- if isPlatformVariant {
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ if apexInfo.IsForPlatform() {
// Bionic libraries that are installed to the bootstrap directory are not ABI checked.
// Only the runtime APEX variants, which are the implementation libraries of bionic NDK stubs,
// are checked.
@@ -208,7 +193,7 @@
return false
}
}
- return classifySourceAbiDump(ctx) != ""
+ return len(classifySourceAbiDump(ctx)) > 0
}
// Mark the direct and transitive dependencies of libraries that need ABI check, so that ABI dumps
diff --git a/cc/sanitize.go b/cc/sanitize.go
index 0abdafc..52b5be9 100644
--- a/cc/sanitize.go
+++ b/cc/sanitize.go
@@ -86,7 +86,7 @@
memtagStackCommonFlags = []string{"-march=armv8-a+memtag", "-mllvm", "-dom-tree-reachability-max-bbs-to-explore=128"}
hostOnlySanitizeFlags = []string{"-fno-sanitize-recover=all"}
- deviceOnlySanitizeFlags = []string{"-fsanitize-trap=all", "-ftrap-function=abort"}
+ deviceOnlySanitizeFlags = []string{"-fsanitize-trap=all"}
noSanitizeLinkRuntimeFlag = "-fno-sanitize-link-runtime"
)
@@ -679,12 +679,6 @@
s.Integer_overflow = nil
}
- // TODO(b/254713216): CFI doesn't work for riscv64 yet because LTO doesn't work.
- if ctx.Arch().ArchType == android.Riscv64 {
- s.Cfi = nil
- s.Diag.Cfi = nil
- }
-
// Disable CFI for musl
if ctx.toolchain().Musl() {
s.Cfi = nil
@@ -1119,12 +1113,15 @@
// indirectly (via a mutator) sets the bool ptr to true, and you can't
// distinguish between the cases. It isn't needed though - both cases can be
// treated identically.
-func (sanitize *sanitize) isSanitizerEnabled(t SanitizerType) bool {
- if sanitize == nil {
+func (s *sanitize) isSanitizerEnabled(t SanitizerType) bool {
+ if s == nil {
+ return false
+ }
+ if proptools.Bool(s.Properties.SanitizeMutated.Never) {
return false
}
- sanitizerVal := sanitize.getSanitizerBoolPtr(t)
+ sanitizerVal := s.getSanitizerBoolPtr(t)
return sanitizerVal != nil && *sanitizerVal == true
}
@@ -1630,7 +1627,7 @@
addStaticDeps := func(dep string, hideSymbols bool) {
// If we're using snapshots, redirect to snapshot whenever possible
- snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo)
+ snapshot, _ := android.ModuleProvider(mctx, SnapshotInfoProvider)
if lib, ok := snapshot.StaticLibs[dep]; ok {
dep = lib
}
@@ -1717,7 +1714,7 @@
addStaticDeps(runtimeSharedLibrary, true)
} else if !c.static() && !c.Header() {
// If we're using snapshots, redirect to snapshot whenever possible
- snapshot := mctx.Provider(SnapshotInfoProvider).(SnapshotInfo)
+ snapshot, _ := android.ModuleProvider(mctx, SnapshotInfoProvider)
if lib, ok := snapshot.SharedLibs[runtimeSharedLibrary]; ok {
runtimeSharedLibrary = lib
}
@@ -1914,7 +1911,3 @@
func hwasanMakeVarsProvider(ctx android.MakeVarsContext) {
hwasanStaticLibs(ctx.Config()).exportToMake(ctx)
}
-
-func BazelCcSanitizerToolchainVars(config android.Config) string {
- return android.BazelToolchainVars(config, exportedVars)
-}
diff --git a/cc/sanitize_test.go b/cc/sanitize_test.go
index 49117a0..44f38e1 100644
--- a/cc/sanitize_test.go
+++ b/cc/sanitize_test.go
@@ -16,13 +16,12 @@
import (
"fmt"
+ "reflect"
"runtime"
"strings"
"testing"
"android/soong/android"
-
- "github.com/google/blueprint"
)
var prepareForAsanTest = android.FixtureAddFile("asan/Android.bp", []byte(`
@@ -48,7 +47,7 @@
`))
type providerInterface interface {
- ModuleProvider(blueprint.Module, blueprint.ProviderKey) interface{}
+ android.SingletonModuleProviderContext
}
// expectSharedLinkDep verifies that the from module links against the to module as a
@@ -56,7 +55,7 @@
func expectSharedLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
t.Helper()
fromLink := from.Description("link")
- toInfo := ctx.ModuleProvider(to.Module(), SharedLibraryInfoProvider).(SharedLibraryInfo)
+ toInfo, _ := android.SingletonModuleProvider(ctx, to.Module(), SharedLibraryInfoProvider)
if g, w := fromLink.OrderOnly.Strings(), toInfo.SharedLibrary.RelativeToTop().String(); !android.InList(w, g) {
t.Errorf("%s should link against %s, expected %q, got %q",
@@ -69,7 +68,7 @@
func expectNoSharedLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
t.Helper()
fromLink := from.Description("link")
- toInfo := ctx.ModuleProvider(to.Module(), SharedLibraryInfoProvider).(SharedLibraryInfo)
+ toInfo, _ := android.SingletonModuleProvider(ctx, to.Module(), SharedLibraryInfoProvider)
if g, w := fromLink.OrderOnly.Strings(), toInfo.SharedLibrary.RelativeToTop().String(); android.InList(w, g) {
t.Errorf("%s should not link against %s, expected %q, got %q",
@@ -82,7 +81,7 @@
func expectStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
t.Helper()
fromLink := from.Description("link")
- toInfo := ctx.ModuleProvider(to.Module(), StaticLibraryInfoProvider).(StaticLibraryInfo)
+ toInfo, _ := android.SingletonModuleProvider(ctx, to.Module(), StaticLibraryInfoProvider)
if g, w := fromLink.Implicits.Strings(), toInfo.StaticLibrary.RelativeToTop().String(); !android.InList(w, g) {
t.Errorf("%s should link against %s, expected %q, got %q",
@@ -96,7 +95,7 @@
func expectNoStaticLinkDep(t *testing.T, ctx providerInterface, from, to android.TestingModule) {
t.Helper()
fromLink := from.Description("link")
- toInfo := ctx.ModuleProvider(to.Module(), StaticLibraryInfoProvider).(StaticLibraryInfo)
+ toInfo, _ := android.SingletonModuleProvider(ctx, to.Module(), StaticLibraryInfoProvider)
if g, w := fromLink.Implicits.Strings(), toInfo.StaticLibrary.RelativeToTop().String(); android.InList(w, g) {
t.Errorf("%s should not link against %s, expected %q, got %q",
@@ -1273,3 +1272,122 @@
t.Errorf("non-CFI variant of baz not expected to contain CFI flags ")
}
}
+
+func TestHwasan(t *testing.T) {
+ t.Parallel()
+
+ bp := `
+ cc_library_shared {
+ name: "shared_with_hwaddress",
+ static_libs: [
+ "static_dep_with_hwaddress",
+ "static_dep_no_hwaddress",
+ ],
+ sanitize: {
+ hwaddress: true,
+ },
+ sdk_version: "current",
+ stl: "c++_shared",
+ }
+
+ cc_library_static {
+ name: "static_dep_with_hwaddress",
+ sanitize: {
+ hwaddress: true,
+ },
+ sdk_version: "current",
+ stl: "c++_shared",
+ }
+
+ cc_library_static {
+ name: "static_dep_no_hwaddress",
+ sdk_version: "current",
+ stl: "c++_shared",
+ }
+`
+
+ androidArm := "android_arm_armv7-a-neon"
+ androidArm64 := "android_arm64_armv8-a"
+ androidX86 := "android_x86_silvermont"
+ sharedSuffix := "_shared"
+ hwasanSuffix := "_hwasan"
+ staticSuffix := "_static"
+ sdkSuffix := "_sdk"
+
+ sharedWithHwasanVariant := sharedSuffix + hwasanSuffix
+ sharedWithSdkVariant := sdkSuffix + sharedSuffix
+ staticWithHwasanVariant := staticSuffix + hwasanSuffix
+ staticWithSdkVariant := sdkSuffix + staticSuffix
+
+ testCases := []struct {
+ buildOs string
+ extraPreparer android.FixturePreparer
+ expectedVariants map[string][]string
+ }{
+ {
+ buildOs: androidArm64,
+ expectedVariants: map[string][]string{
+ "shared_with_hwaddress": []string{
+ androidArm64 + sharedWithHwasanVariant,
+ androidArm64 + sharedWithSdkVariant,
+ androidArm + sharedSuffix,
+ androidArm + sharedWithSdkVariant,
+ },
+ "static_dep_with_hwaddress": []string{
+ androidArm64 + staticSuffix,
+ androidArm64 + staticWithHwasanVariant,
+ androidArm64 + staticWithSdkVariant,
+ androidArm + staticSuffix,
+ androidArm + staticWithSdkVariant,
+ },
+ "static_dep_no_hwaddress": []string{
+ androidArm64 + staticSuffix,
+ androidArm64 + staticWithHwasanVariant,
+ androidArm64 + staticWithSdkVariant,
+ androidArm + staticSuffix,
+ androidArm + staticWithSdkVariant,
+ },
+ },
+ },
+ {
+ buildOs: androidX86,
+ extraPreparer: android.FixtureModifyConfig(func(config android.Config) {
+ config.Targets[android.Android] = []android.Target{
+ {
+ android.Android,
+ android.Arch{
+ ArchType: android.X86, ArchVariant: "silvermont", Abi: []string{"armeabi-v7a"}}, android.NativeBridgeDisabled, "", "", false},
+ }
+ }),
+ expectedVariants: map[string][]string{
+ "shared_with_hwaddress": []string{
+ androidX86 + sharedSuffix,
+ androidX86 + sharedWithSdkVariant,
+ },
+ "static_dep_with_hwaddress": []string{
+ androidX86 + staticSuffix,
+ androidX86 + staticWithSdkVariant,
+ },
+ "static_dep_no_hwaddress": []string{
+ androidX86 + staticSuffix,
+ androidX86 + staticWithSdkVariant,
+ },
+ },
+ },
+ }
+
+ for _, tc := range testCases {
+ preparer := android.GroupFixturePreparers(
+ prepareForCcTest,
+ android.OptionalFixturePreparer(tc.extraPreparer),
+ )
+ result := preparer.RunTestWithBp(t, bp)
+
+ for m, v := range tc.expectedVariants {
+ variants := result.ModuleVariantsForTests(m)
+ if !reflect.DeepEqual(variants, v) {
+ t.Errorf("Expected variants of %q to be %q, but got %q", m, v, variants)
+ }
+ }
+ }
+}
diff --git a/cc/snapshot_prebuilt.go b/cc/snapshot_prebuilt.go
index e29c446..e769fe9 100644
--- a/cc/snapshot_prebuilt.go
+++ b/cc/snapshot_prebuilt.go
@@ -194,7 +194,7 @@
sharedLibs[k] = v
}
- ctx.SetProvider(SnapshotInfoProvider, SnapshotInfo{
+ android.SetProvider(ctx, SnapshotInfoProvider, SnapshotInfo{
HeaderLibs: headers,
Binaries: binaries,
Objects: objects,
@@ -209,7 +209,7 @@
HeaderLibs, Binaries, Objects, StaticLibs, SharedLibs, Rlibs, Dylibs map[string]string
}
-var SnapshotInfoProvider = blueprint.NewMutatorProvider(SnapshotInfo{}, "deps")
+var SnapshotInfoProvider = blueprint.NewMutatorProvider[SnapshotInfo]("deps")
var _ android.ImageInterface = (*snapshotModule)(nil)
@@ -494,7 +494,7 @@
p.tocFile = android.OptionalPathForPath(tocFile)
TransformSharedObjectToToc(ctx, in, tocFile)
- ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+ android.SetProvider(ctx, SharedLibraryInfoProvider, SharedLibraryInfo{
SharedLibrary: in,
Target: ctx.Target(),
@@ -504,7 +504,7 @@
if p.static() {
depSet := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).Direct(in).Build()
- ctx.SetProvider(StaticLibraryInfoProvider, StaticLibraryInfo{
+ android.SetProvider(ctx, StaticLibraryInfoProvider, StaticLibraryInfo{
StaticLibrary: in,
TransitiveStaticLibrariesForOrdering: depSet,
diff --git a/cc/stl.go b/cc/stl.go
index 8f92dcb..63c23d7 100644
--- a/cc/stl.go
+++ b/cc/stl.go
@@ -134,8 +134,6 @@
return "libunwind"
}
-// Should be kept up to date with
-// https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/cc/stl.bzl;l=46;drc=21771b671ae08565033768a6d3d151c54f887fa2
func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps {
switch stl.Properties.SelectedStl {
case "libstdc++":
@@ -172,6 +170,7 @@
// The system STL doesn't have a prebuilt (it uses the system's libstdc++), but it does have
// its own includes. The includes are handled in CCBase.Flags().
deps.SharedLibs = append([]string{"libstdc++"}, deps.SharedLibs...)
+ deps.HeaderLibs = append([]string{"ndk_system"}, deps.HeaderLibs...)
case "ndk_libc++_shared", "ndk_libc++_static":
if stl.Properties.SelectedStl == "ndk_libc++_shared" {
deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl)
@@ -186,8 +185,6 @@
return deps
}
-// Should be kept up to date with
-// https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/cc/stl.bzl;l=94;drc=5bc8e39d2637927dc57dd0850210d43d348a1341
func (stl *stl) flags(ctx ModuleContext, flags Flags) Flags {
switch stl.Properties.SelectedStl {
case "libc++", "libc++_static":
@@ -219,8 +216,7 @@
case "libstdc++":
// Nothing
case "ndk_system":
- ndkSrcRoot := android.PathForSource(ctx, "prebuilts/ndk/current/sources/cxx-stl/system/include")
- flags.Local.CFlags = append(flags.Local.CFlags, "-isystem "+ndkSrcRoot.String())
+ // Nothing: The exports of ndk_system will be added automatically to the local cflags
case "ndk_libc++_shared", "ndk_libc++_static":
if ctx.Arch().ArchType == android.Arm {
// Make sure the _Unwind_XXX symbols are not re-exported.
diff --git a/cc/strip.go b/cc/strip.go
index c60e135..b1f34bb 100644
--- a/cc/strip.go
+++ b/cc/strip.go
@@ -59,7 +59,6 @@
return !forceDisable && (forceEnable || defaultEnable)
}
-// Keep this consistent with //build/bazel/rules/stripped_shared_library.bzl.
func (stripper *Stripper) strip(actx android.ModuleContext, in android.Path, out android.ModuleOutPath,
flags StripFlags, isStaticLib bool) {
if actx.Darwin() {
diff --git a/cc/stub_library.go b/cc/stub_library.go
index 3a6d0ae..47c6cb9 100644
--- a/cc/stub_library.go
+++ b/cc/stub_library.go
@@ -27,7 +27,8 @@
}
type stubLibraries struct {
- stubLibraryMap map[string]bool
+ stubLibraryMap map[string]bool
+ stubVendorLibraryMap map[string]bool
apiListCoverageXmlPaths []string
}
@@ -54,6 +55,9 @@
if IsStubTarget(m) {
if name := getInstalledFileName(m); name != "" {
s.stubLibraryMap[name] = true
+ if m.InVendor() {
+ s.stubVendorLibraryMap[name] = true
+ }
}
}
if m.library != nil {
@@ -67,13 +71,15 @@
func stubLibrariesSingleton() android.Singleton {
return &stubLibraries{
- stubLibraryMap: make(map[string]bool),
+ stubLibraryMap: make(map[string]bool),
+ stubVendorLibraryMap: make(map[string]bool),
}
}
func (s *stubLibraries) MakeVars(ctx android.MakeVarsContext) {
// Convert stub library file names into Makefile variable.
ctx.Strict("STUB_LIBRARIES", strings.Join(android.SortedKeys(s.stubLibraryMap), " "))
+ ctx.Strict("SOONG_STUB_VENDOR_LIBRARIES", strings.Join(android.SortedKeys(s.stubVendorLibraryMap), " "))
// Export the list of API XML files to Make.
sort.Strings(s.apiListCoverageXmlPaths)
diff --git a/cc/symbolfile/__init__.py b/cc/symbolfile/__init__.py
index 94c8567..345e9f9 100644
--- a/cc/symbolfile/__init__.py
+++ b/cc/symbolfile/__init__.py
@@ -46,6 +46,15 @@
Arch('x86_64'),
)
+# TODO: it would be nice to dedupe with 'has_*_tag' property methods
+SUPPORTED_TAGS = ALL_ARCHITECTURES + (
+ Tag('apex'),
+ Tag('llndk'),
+ Tag('platform-only'),
+ Tag('systemapi'),
+ Tag('var'),
+ Tag('weak'),
+)
# Arbitrary magic number. We use the same one in api-level.h for this purpose.
FUTURE_API_LEVEL = 10000
@@ -136,6 +145,8 @@
def is_api_level_tag(tag: Tag) -> bool:
"""Returns true if this tag has an API level that may need decoding."""
+ if tag.startswith('llndk-deprecated='):
+ return True
if tag.startswith('introduced='):
return True
if tag.startswith('introduced-'):
@@ -170,6 +181,9 @@
ParseError: An unknown version name was found in a tag.
"""
if not is_api_level_tag(tag):
+ if tag not in SUPPORTED_TAGS:
+ raise ParseError(f'Unsupported tag: {tag}')
+
return tag
name, value = split_tag(tag)
diff --git a/cc/symbolfile/test_symbolfile.py b/cc/symbolfile/test_symbolfile.py
index 856b9d7..83becc2 100644
--- a/cc/symbolfile/test_symbolfile.py
+++ b/cc/symbolfile/test_symbolfile.py
@@ -40,10 +40,20 @@
self.assertEqual(Tags(), symbolfile.get_tags('foo bar baz', {}))
def test_get_tags(self) -> None:
- self.assertEqual(Tags.from_strs(['foo', 'bar']),
- symbolfile.get_tags('# foo bar', {}))
- self.assertEqual(Tags.from_strs(['bar', 'baz']),
- symbolfile.get_tags('foo # bar baz', {}))
+ self.assertEqual(Tags.from_strs(['llndk', 'apex']),
+ symbolfile.get_tags('# llndk apex', {}))
+ self.assertEqual(Tags.from_strs(['llndk', 'apex']),
+ symbolfile.get_tags('foo # llndk apex', {}))
+
+ def test_get_unrecognized_tags(self) -> None:
+ with self.assertRaises(symbolfile.ParseError):
+ symbolfile.get_tags('# bar', {})
+ with self.assertRaises(symbolfile.ParseError):
+ symbolfile.get_tags('foo # bar', {})
+ with self.assertRaises(symbolfile.ParseError):
+ symbolfile.get_tags('# #', {})
+ with self.assertRaises(symbolfile.ParseError):
+ symbolfile.get_tags('# apex # llndk', {})
def test_split_tag(self) -> None:
self.assertTupleEqual(('foo', 'bar'),
@@ -425,13 +435,13 @@
def test_parse_version(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
- VERSION_1 { # foo bar
+ VERSION_1 { # weak introduced=35
baz;
- qux; # woodly doodly
+ qux; # apex llndk
};
VERSION_2 {
- } VERSION_1; # asdf
+ } VERSION_1; # not-a-tag
"""))
parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
@@ -439,11 +449,11 @@
version = parser.parse_version()
self.assertEqual('VERSION_1', version.name)
self.assertIsNone(version.base)
- self.assertEqual(Tags.from_strs(['foo', 'bar']), version.tags)
+ self.assertEqual(Tags.from_strs(['weak', 'introduced=35']), version.tags)
expected_symbols = [
Symbol('baz', Tags()),
- Symbol('qux', Tags.from_strs(['woodly', 'doodly'])),
+ Symbol('qux', Tags.from_strs(['apex', 'llndk'])),
]
self.assertEqual(expected_symbols, version.symbols)
@@ -476,7 +486,7 @@
def test_parse_symbol(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
foo;
- bar; # baz qux
+ bar; # llndk apex
"""))
parser = symbolfile.SymbolFileParser(input_file, {}, self.filter)
@@ -488,7 +498,7 @@
parser.next_line()
symbol = parser.parse_symbol()
self.assertEqual('bar', symbol.name)
- self.assertEqual(Tags.from_strs(['baz', 'qux']), symbol.tags)
+ self.assertEqual(Tags.from_strs(['llndk', 'apex']), symbol.tags)
def test_wildcard_symbol_global(self) -> None:
input_file = io.StringIO(textwrap.dedent("""\
@@ -537,13 +547,13 @@
hidden1;
global:
foo;
- bar; # baz
+ bar; # llndk
};
- VERSION_2 { # wasd
+ VERSION_2 { # weak
# Implicit global scope.
woodly;
- doodly; # asdf
+ doodly; # llndk
local:
qwerty;
} VERSION_1;
@@ -554,12 +564,12 @@
expected = [
symbolfile.Version('VERSION_1', None, Tags(), [
Symbol('foo', Tags()),
- Symbol('bar', Tags.from_strs(['baz'])),
+ Symbol('bar', Tags.from_strs(['llndk'])),
]),
symbolfile.Version(
- 'VERSION_2', 'VERSION_1', Tags.from_strs(['wasd']), [
+ 'VERSION_2', 'VERSION_1', Tags.from_strs(['weak']), [
Symbol('woodly', Tags()),
- Symbol('doodly', Tags.from_strs(['asdf'])),
+ Symbol('doodly', Tags.from_strs(['llndk'])),
]),
]
diff --git a/cc/sysprop.go b/cc/sysprop.go
deleted file mode 100644
index 7ddd476..0000000
--- a/cc/sysprop.go
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (C) 2019 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.
-
-package cc
-
-import (
- "android/soong/android"
- "android/soong/bazel"
-)
-
-// TODO(b/240463568): Additional properties will be added for API validation
-type bazelSyspropLibraryAttributes struct {
- Srcs bazel.LabelListAttribute
- Tags bazel.StringListAttribute
-}
-
-type bazelCcSyspropLibraryAttributes struct {
- Dep bazel.LabelAttribute
- Min_sdk_version *string
- Tags bazel.StringListAttribute
-}
-
-type SyspropLibraryLabels struct {
- SyspropLibraryLabel string
- SharedLibraryLabel string
- StaticLibraryLabel string
-}
-
-func Bp2buildSysprop(ctx android.Bp2buildMutatorContext, labels SyspropLibraryLabels, srcs bazel.LabelListAttribute, minSdkVersion *string) {
- apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx.(android.TopDownMutatorContext), ctx.Module())
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "sysprop_library",
- Bzl_load_location: "//build/bazel/rules/sysprop:sysprop_library.bzl",
- },
- android.CommonAttributes{Name: labels.SyspropLibraryLabel},
- &bazelSyspropLibraryAttributes{
- Srcs: srcs,
- Tags: apexAvailableTags,
- },
- )
-
- attrs := &bazelCcSyspropLibraryAttributes{
- Dep: *bazel.MakeLabelAttribute(":" + labels.SyspropLibraryLabel),
- Min_sdk_version: minSdkVersion,
- Tags: apexAvailableTags,
- }
-
- if labels.SharedLibraryLabel != "" {
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "cc_sysprop_library_shared",
- Bzl_load_location: "//build/bazel/rules/cc:cc_sysprop_library.bzl",
- },
- android.CommonAttributes{Name: labels.SharedLibraryLabel},
- attrs)
- }
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "cc_sysprop_library_static",
- Bzl_load_location: "//build/bazel/rules/cc:cc_sysprop_library.bzl",
- },
- android.CommonAttributes{Name: labels.StaticLibraryLabel},
- attrs)
-}
diff --git a/cc/test.go b/cc/test.go
index ae62128..3a1a3af 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -22,8 +22,6 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel"
- "android/soong/bazel/cquery"
"android/soong/tradefed"
)
@@ -139,8 +137,7 @@
// specific functionality on a device. The executable binary gets an implicit
// static_libs dependency on libgtests unless the gtest flag is set to false.
func TestFactory() android.Module {
- module := NewTest(android.HostAndDeviceSupported, true)
- module.bazelHandler = &ccTestBazelHandler{module: module}
+ module := NewTest(android.HostAndDeviceSupported)
return module.Init()
}
@@ -158,12 +155,13 @@
// binary.
func BenchmarkFactory() android.Module {
module := NewBenchmark(android.HostAndDeviceSupported)
+ module.testModule = true
return module.Init()
}
// cc_test_host compiles a test host binary.
func TestHostFactory() android.Module {
- module := NewTest(android.HostSupported, true)
+ module := NewTest(android.HostSupported)
return module.Init()
}
@@ -323,6 +321,13 @@
return []interface{}{&test.InstallerProperties}
}
+func (test *testDecorator) moduleInfoJSON(ctx android.ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ if android.PrefixInList(moduleInfoJSON.CompatibilitySuites, "mts-") &&
+ !android.InList("mts", moduleInfoJSON.CompatibilitySuites) {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "mts")
+ }
+}
+
func NewTestInstaller() *baseInstaller {
return NewBaseInstaller("nativetest", "nativetest64", InstallInData)
}
@@ -357,6 +362,38 @@
return flags
}
+func (test *testBinary) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ if ctx.Host() && Bool(test.Properties.Test_options.Unit_test) {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "host-unit-tests")
+ }
+ moduleInfoJSON.TestOptionsTags = append(moduleInfoJSON.TestOptionsTags, test.Properties.Test_options.Tags...)
+ moduleInfoJSON.TestMainlineModules = append(moduleInfoJSON.TestMainlineModules, test.Properties.Test_mainline_modules...)
+ if test.testConfig != nil {
+ if _, ok := test.testConfig.(android.WritablePath); ok {
+ moduleInfoJSON.AutoTestConfig = []string{"true"}
+ }
+ moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, test.testConfig.String())
+ }
+ moduleInfoJSON.TestConfig = append(moduleInfoJSON.TestConfig, test.extraTestConfigs.Strings()...)
+
+ if Bool(test.Properties.Test_per_src) {
+ moduleInfoJSON.SubName = "_" + String(test.binaryDecorator.Properties.Stem)
+ }
+
+ moduleInfoJSON.DataDependencies = append(moduleInfoJSON.DataDependencies, test.Properties.Data_bins...)
+
+ if len(test.InstallerProperties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, test.InstallerProperties.Test_suites...)
+ } else {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
+ }
+
+ test.binaryDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+ test.testDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+ moduleInfoJSON.Class = []string{"NATIVE_TESTS"}
+
+}
+
func (test *testBinary) installerProps() []interface{} {
return append(test.baseInstaller.installerProps(), test.testDecorator.installerProps()...)
}
@@ -393,8 +430,7 @@
}
})
- useVendor := ctx.inVendor() || ctx.useVndk()
- testInstallBase := getTestInstallBase(useVendor)
+ testInstallBase := getTestInstallBase(ctx.InVendorOrProduct())
configs := getTradefedConfigOptions(ctx, &test.Properties, test.isolated(ctx), ctx.Device())
test.testConfig = tradefed.AutoGenTestConfig(ctx, tradefed.AutoGenTestConfigOptions{
@@ -423,6 +459,8 @@
if ctx.Host() && test.gtest() && test.Properties.Test_options.Unit_test == nil {
test.Properties.Test_options.Unit_test = proptools.BoolPtr(true)
}
+
+ test.binaryDecorator.baseInstaller.installTestData(ctx, test.data)
test.binaryDecorator.baseInstaller.install(ctx, file)
}
@@ -485,10 +523,10 @@
return configs
}
-func NewTest(hod android.HostOrDeviceSupported, bazelable bool) *Module {
- module, binary := newBinary(hod, bazelable)
- module.bazelable = bazelable
+func NewTest(hod android.HostOrDeviceSupported) *Module {
+ module, binary := newBinary(hod)
module.multilib = android.MultilibBoth
+ module.testModule = true
binary.baseInstaller = NewTestInstaller()
test := &testBinary{
@@ -532,6 +570,15 @@
return flags
}
+func (test *testLibrary) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ if len(test.InstallerProperties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, test.InstallerProperties.Test_suites...)
+ }
+
+ test.libraryDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+ test.testDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+}
+
func (test *testLibrary) installerProps() []interface{} {
return append(test.baseInstaller.installerProps(), test.testDecorator.installerProps()...)
}
@@ -548,7 +595,6 @@
}
module.linker = test
module.installer = test
- module.bazelable = true
return module
}
@@ -582,7 +628,7 @@
type benchmarkDecorator struct {
*binaryDecorator
Properties BenchmarkProperties
- data android.Paths
+ data []android.DataPath
testConfig android.Path
}
@@ -603,7 +649,9 @@
}
func (benchmark *benchmarkDecorator) install(ctx ModuleContext, file android.Path) {
- benchmark.data = android.PathsForModuleSrc(ctx, benchmark.Properties.Data)
+ for _, d := range android.PathsForModuleSrc(ctx, benchmark.Properties.Data) {
+ benchmark.data = append(benchmark.data, android.DataPath{SrcPath: d})
+ }
var configs []tradefed.Config
if Bool(benchmark.Properties.Require_root) {
@@ -621,11 +669,35 @@
benchmark.binaryDecorator.baseInstaller.dir = filepath.Join("benchmarktest", ctx.ModuleName())
benchmark.binaryDecorator.baseInstaller.dir64 = filepath.Join("benchmarktest64", ctx.ModuleName())
+ benchmark.binaryDecorator.baseInstaller.installTestData(ctx, benchmark.data)
benchmark.binaryDecorator.baseInstaller.install(ctx, file)
}
+func (benchmark *benchmarkDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ benchmark.binaryDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+
+ moduleInfoJSON.Class = []string{"NATIVE_TESTS"}
+ if len(benchmark.Properties.Test_suites) > 0 {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, benchmark.Properties.Test_suites...)
+ } else {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "null-suite")
+ }
+
+ if android.PrefixInList(moduleInfoJSON.CompatibilitySuites, "mts-") &&
+ !android.InList("mts", moduleInfoJSON.CompatibilitySuites) {
+ moduleInfoJSON.CompatibilitySuites = append(moduleInfoJSON.CompatibilitySuites, "mts")
+ }
+
+ if benchmark.testConfig != nil {
+ if _, ok := benchmark.testConfig.(android.WritablePath); ok {
+ moduleInfoJSON.AutoTestConfig = []string{"true"}
+ }
+ moduleInfoJSON.TestConfig = []string{benchmark.testConfig.String()}
+ }
+}
+
func NewBenchmark(hod android.HostOrDeviceSupported) *Module {
- module, binary := newBinary(hod, false)
+ module, binary := newBinary(hod)
module.multilib = android.MultilibBoth
binary.baseInstaller = NewBaseInstaller("benchmarktest", "benchmarktest64", InstallInData)
@@ -636,180 +708,3 @@
module.installer = benchmark
return module
}
-
-type ccTestBazelHandler struct {
- module *Module
-}
-
-var _ BazelHandler = (*ccTestBazelHandler)(nil)
-
-// The top level target named $label is a test_suite target,
-// not the internal cc_test executable target.
-//
-// This is to ensure `b test //$label` runs the test_suite target directly,
-// which depends on tradefed_test targets, instead of the internal cc_test
-// target, which doesn't have tradefed integrations.
-//
-// However, for cquery, we want the internal cc_test executable target, which
-// has the suffix "__tf_internal".
-func mixedBuildsTestLabel(label string) string {
- return label + "__tf_internal"
-}
-
-func (handler *ccTestBazelHandler) QueueBazelCall(ctx android.BaseModuleContext, label string) {
- bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(mixedBuildsTestLabel(label), cquery.GetCcUnstrippedInfo, android.GetConfigKey(ctx))
-}
-
-func (handler *ccTestBazelHandler) ProcessBazelQueryResponse(ctx android.ModuleContext, label string) {
- bazelCtx := ctx.Config().BazelContext
- info, err := bazelCtx.GetCcUnstrippedInfo(mixedBuildsTestLabel(label), android.GetConfigKey(ctx))
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- return
- }
-
- var outputFilePath android.Path = android.PathForBazelOut(ctx, info.OutputFile)
- if len(info.TidyFiles) > 0 {
- handler.module.tidyFiles = android.PathsForBazelOut(ctx, info.TidyFiles)
- outputFilePath = android.AttachValidationActions(ctx, outputFilePath, handler.module.tidyFiles)
- }
- handler.module.outputFile = android.OptionalPathForPath(outputFilePath)
- handler.module.linker.(*testBinary).unstrippedOutputFile = android.PathForBazelOut(ctx, info.UnstrippedOutput)
-
- handler.module.setAndroidMkVariablesFromCquery(info.CcAndroidMkInfo)
-}
-
-// binaryAttributes contains Bazel attributes corresponding to a cc test
-type testBinaryAttributes struct {
- binaryAttributes
-
- Gtest *bool
-
- tidyAttributes
- tradefed.TestConfigAttributes
-
- Runs_on bazel.StringListAttribute
-}
-
-// testBinaryBp2build is the bp2build converter for cc_test modules. A cc_test's
-// dependency graph and compilation/linking steps are functionally similar to a
-// cc_binary, but has additional dependencies on test deps like gtest, and
-// produces additional runfiles like XML plans for Tradefed orchestration
-//
-// TODO(b/244432609): handle `isolated` property.
-// TODO(b/244432134): handle custom runpaths for tests that assume runfile layouts not
-// default to bazel. (see linkerInit function)
-func testBinaryBp2build(ctx android.TopDownMutatorContext, m *Module) {
- var testBinaryAttrs testBinaryAttributes
- testBinaryAttrs.binaryAttributes = binaryBp2buildAttrs(ctx, m)
-
- var data bazel.LabelListAttribute
- var tags bazel.StringListAttribute
-
- testBinaryProps := m.GetArchVariantProperties(ctx, &TestBinaryProperties{})
- for axis, configToProps := range testBinaryProps {
- for config, props := range configToProps {
- if p, ok := props.(*TestBinaryProperties); ok {
- // Combine data, data_bins and data_libs into a single 'data' attribute.
- var combinedData bazel.LabelList
- combinedData.Append(android.BazelLabelForModuleSrc(ctx, p.Data))
- combinedData.Append(android.BazelLabelForModuleDeps(ctx, p.Data_bins))
- combinedData.Append(android.BazelLabelForModuleDeps(ctx, p.Data_libs))
- data.SetSelectValue(axis, config, combinedData)
- tags.SetSelectValue(axis, config, p.Test_options.Tags)
- }
- }
- }
-
- // The logic comes from https://cs.android.com/android/platform/superproject/main/+/0df8153267f96da877febc5332240fa06ceb8533:build/soong/cc/sanitize.go;l=488
- var features bazel.StringListAttribute
- curFeatures := testBinaryAttrs.binaryAttributes.Features.SelectValue(bazel.OsArchConfigurationAxis, bazel.OsArchAndroidArm64)
- var newFeatures []string
- if !android.InList("memtag_heap", curFeatures) && !android.InList("-memtag_heap", curFeatures) {
- newFeatures = append(newFeatures, "memtag_heap")
- if !android.InList("diag_memtag_heap", curFeatures) && !android.InList("-diag_memtag_heap", curFeatures) {
- newFeatures = append(newFeatures, "diag_memtag_heap")
- }
- }
-
- features.SetSelectValue(bazel.OsArchConfigurationAxis, bazel.OsArchAndroidArm64, newFeatures)
- testBinaryAttrs.binaryAttributes.Features.Append(features)
- testBinaryAttrs.binaryAttributes.Features.DeduplicateAxesFromBase()
-
- m.convertTidyAttributes(ctx, &testBinaryAttrs.tidyAttributes)
-
- testBinary := m.linker.(*testBinary)
- gtest := testBinary.gtest()
- gtestIsolated := testBinary.isolated(ctx)
- // Use the underling bool pointer for Gtest in attrs
- // This ensures that if this property is not set in Android.bp file, it will not be set in BUILD file either
- // cc_test macro will default gtest to True
- testBinaryAttrs.Gtest = testBinary.LinkerProperties.Gtest
-
- addImplicitGtestDeps(ctx, &testBinaryAttrs, gtest, gtestIsolated)
-
- var unitTest *bool
-
- for _, testProps := range m.GetProperties() {
- if p, ok := testProps.(*TestBinaryProperties); ok {
- useVendor := false // TODO Bug: 262914724
- testInstallBase := getTestInstallBase(useVendor)
- testConfigAttributes := tradefed.GetTestConfigAttributes(
- ctx,
- p.Test_config,
- p.Test_options.Extra_test_configs,
- p.Auto_gen_config,
- p.Test_options.Test_suite_tag,
- p.Test_config_template,
- getTradefedConfigOptions(ctx, p, gtestIsolated, true),
- &testInstallBase,
- )
- testBinaryAttrs.TestConfigAttributes = testConfigAttributes
- unitTest = p.Test_options.Unit_test
- }
- }
-
- testBinaryAttrs.Runs_on = bazel.MakeStringListAttribute(android.RunsOn(
- m.ModuleBase.HostSupported(),
- m.ModuleBase.DeviceSupported(),
- gtest || (unitTest != nil && *unitTest)))
-
- // TODO (b/262914724): convert to tradefed_cc_test and tradefed_cc_test_host
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "cc_test",
- Bzl_load_location: "//build/bazel/rules/cc:cc_test.bzl",
- },
- android.CommonAttributes{
- Name: m.Name(),
- Data: data,
- Tags: tags,
- },
- &testBinaryAttrs)
-}
-
-// cc_test that builds using gtest needs some additional deps
-// addImplicitGtestDeps makes these deps explicit in the generated BUILD files
-func addImplicitGtestDeps(ctx android.BazelConversionPathContext, attrs *testBinaryAttributes, gtest, gtestIsolated bool) {
- addDepsAndDedupe := func(lla *bazel.LabelListAttribute, modules []string) {
- moduleLabels := android.BazelLabelForModuleDeps(ctx, modules)
- lla.Value.Append(moduleLabels)
- // Dedupe
- lla.Value = bazel.FirstUniqueBazelLabelList(lla.Value)
- }
- // this must be kept in sync with Soong's implementation in:
- // https://cs.android.com/android/_/android/platform/build/soong/+/460fb2d6d546b5ab493a7e5479998c4933a80f73:cc/test.go;l=300-313;drc=ec7314336a2b35ea30ce5438b83949c28e3ac429;bpv=1;bpt=0
- if gtest {
- // TODO - b/244433197: Handle canUseSdk
- if gtestIsolated {
- addDepsAndDedupe(&attrs.Deps, []string{"libgtest_isolated_main"})
- addDepsAndDedupe(&attrs.Dynamic_deps, []string{"liblog"})
- } else {
- addDepsAndDedupe(&attrs.Deps, []string{
- "libgtest_main",
- "libgtest",
- })
- }
- }
-}
diff --git a/cc/testing.go b/cc/testing.go
index d1632aa..9c2900c 100644
--- a/cc/testing.go
+++ b/cc/testing.go
@@ -35,13 +35,14 @@
multitree.RegisterApiImportsModule(ctx)
+ ctx.RegisterModuleType("prebuilt_build_tool", android.NewPrebuiltBuildTool)
ctx.RegisterModuleType("cc_benchmark", BenchmarkFactory)
ctx.RegisterModuleType("cc_object", ObjectFactory)
ctx.RegisterModuleType("cc_genrule", GenRuleFactory)
ctx.RegisterModuleType("ndk_prebuilt_shared_stl", NdkPrebuiltSharedStlFactory)
ctx.RegisterModuleType("ndk_prebuilt_static_stl", NdkPrebuiltStaticStlFactory)
ctx.RegisterModuleType("ndk_library", NdkLibraryFactory)
- ctx.RegisterModuleType("ndk_headers", ndkHeadersFactory)
+ ctx.RegisterModuleType("ndk_headers", NdkHeadersFactory)
}
func GatherRequiredDepsForTest(oses ...android.OsType) string {
@@ -76,6 +77,7 @@
no_libcrt: true,
sdk_version: "minimum",
nocrt: true,
+ no_crt_pad_segment: true,
system_shared_libs: [],
stl: "none",
check_elf_files: false,
@@ -384,6 +386,11 @@
}
cc_object {
+ name: "crt_pad_segment",
+ defaults: ["crt_defaults"],
+ }
+
+ cc_object {
name: "crtbrand",
defaults: ["crt_defaults"],
srcs: ["crtbrand.c"],
@@ -558,7 +565,7 @@
// This includes files that are needed by all, or at least most, instances of a cc module type.
android.MockFS{
// Needed for ndk_prebuilt_(shared|static)_stl.
- "prebuilts/ndk/current/sources/cxx-stl/llvm-libc++/libs": nil,
+ "defaults/cc/common/current/sources/cxx-stl/llvm-libc++/libs": nil,
}.AddToFixture(),
)
@@ -570,6 +577,7 @@
android.MockFS{
"defaults/cc/common/libc.map.txt": nil,
"defaults/cc/common/libdl.map.txt": nil,
+ "defaults/cc/common/libft2.map.txt": nil,
"defaults/cc/common/libm.map.txt": nil,
"defaults/cc/common/ndk_libc++_shared": nil,
"defaults/cc/common/crtbegin_so.c": nil,
@@ -671,7 +679,7 @@
// PrepareForTestWithFdoProfile registers module types to test with fdo_profile
var PrepareForTestWithFdoProfile = android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
ctx.RegisterModuleType("soong_namespace", android.NamespaceFactory)
- ctx.RegisterModuleType("fdo_profile", fdoProfileFactory)
+ ctx.RegisterModuleType("fdo_profile", FdoProfileFactory)
})
// TestConfig is the legacy way of creating a test Config for testing cc modules.
@@ -796,7 +804,7 @@
func checkOverrides(t *testing.T, ctx *android.TestContext, singleton android.TestingSingleton, jsonPath string, expected []string) {
t.Helper()
out := singleton.MaybeOutput(jsonPath)
- content := android.ContentFromFileRuleForTests(t, out)
+ content := android.ContentFromFileRuleForTests(t, ctx, out)
var flags snapshotJsonFlags
if err := json.Unmarshal([]byte(content), &flags); err != nil {
diff --git a/cc/tidy.go b/cc/tidy.go
index 7b123cb..76ac7d5 100644
--- a/cc/tidy.go
+++ b/cc/tidy.go
@@ -68,7 +68,6 @@
// Then, that old style usage will be obsolete and an error.
const NoWarningsAsErrorsInTidyFlags = true
-// keep this up to date with https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/cc/clang_tidy.bzl
func (tidy *tidyFeature) flags(ctx ModuleContext, flags Flags) Flags {
CheckBadTidyFlags(ctx, "tidy_flags", tidy.Properties.Tidy_flags)
CheckBadTidyChecks(ctx, "tidy_checks", tidy.Properties.Tidy_checks)
diff --git a/cc/tidy_test.go b/cc/tidy_test.go
index 7036ecb..9481778 100644
--- a/cc/tidy_test.go
+++ b/cc/tidy_test.go
@@ -244,3 +244,30 @@
})
}
}
+
+func TestWithGeneratedCode(t *testing.T) {
+ bp := `
+ cc_library_shared {
+ name: "libfoo",
+ srcs: ["foo_1.y", "foo_2.yy", "foo_3.l", "foo_4.ll", "foo_5.proto",
+ "foo_6.aidl", "foo_7.rscript", "foo_8.fs", "foo_9.sysprop",
+ "foo_src.cpp"],
+ tidy: true,
+ }`
+ variant := "android_arm64_armv8-a_shared"
+
+ testEnv := map[string]string{}
+ testEnv["ALLOW_LOCAL_TIDY_TRUE"] = "1"
+
+ ctx := android.GroupFixturePreparers(prepareForCcTest, android.FixtureMergeEnv(testEnv)).RunTestWithBp(t, bp)
+
+ t.Run("tidy should be only run for source code, not for generated code", func(t *testing.T) {
+ depFiles := ctx.ModuleForTests("libfoo", variant).Rule("ld").Validations.Strings()
+
+ tidyFileForCpp := "out/soong/.intermediates/libfoo/" + variant + "/obj/foo_src.tidy"
+
+ android.AssertArrayString(t,
+ "only one .tidy file for source code should exist for libfoo",
+ []string{tidyFileForCpp}, depFiles)
+ })
+}
diff --git a/cc/vendor_snapshot.go b/cc/vendor_snapshot.go
index 9ea337b..a33ed5f 100644
--- a/cc/vendor_snapshot.go
+++ b/cc/vendor_snapshot.go
@@ -98,6 +98,11 @@
if !sanitizable.Shared() && sanitizable.IsSanitizerEnabled(scs) {
return false
}
+ // cfi and hwasan cannot be enabled at the same time.
+ // Skip variants that have both cfi and hwasan enabled.
+ if sanitizable.IsSanitizerEnabled(cfi) && sanitizable.IsSanitizerEnabled(Hwasan) {
+ return false
+ }
// cfi and hwasan also export both variants. But for static, we capture both.
// This is because cfi static libraries can't be linked from non-cfi modules,
// and vice versa.
@@ -270,7 +275,7 @@
var propOut string
if m.IsSnapshotLibrary() {
- exporterInfo := ctx.ModuleProvider(m.Module(), FlagExporterInfoProvider).(FlagExporterInfo)
+ exporterInfo, _ := android.SingletonModuleProvider(ctx, m.Module(), FlagExporterInfoProvider)
// library flags
prop.ExportedFlags = exporterInfo.Flags
@@ -402,7 +407,7 @@
moduleDir := ctx.ModuleDir(module)
inProprietaryPath := s.Image.IsProprietaryPath(moduleDir, ctx.DeviceConfig())
- apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.SingletonModuleProvider(ctx, module, android.ApexInfoProvider)
if s.Image.ExcludeFromSnapshot(m) {
if inProprietaryPath {
diff --git a/cc/vendor_snapshot_test.go b/cc/vendor_snapshot_test.go
index c5431b3..0a55431 100644
--- a/cc/vendor_snapshot_test.go
+++ b/cc/vendor_snapshot_test.go
@@ -23,13 +23,14 @@
"testing"
)
-func checkJsonContents(t *testing.T, ctx android.TestingSingleton, jsonPath string, key string, value string) {
- jsonOut := ctx.MaybeOutput(jsonPath)
+func checkJsonContents(t *testing.T, ctx *android.TestContext, snapshotSingleton android.TestingSingleton, jsonPath string, key string, value string) {
+ jsonOut := snapshotSingleton.MaybeOutput(jsonPath)
if jsonOut.Rule == nil {
t.Errorf("%q expected but not found", jsonPath)
return
}
- if !strings.Contains(jsonOut.Args["content"], fmt.Sprintf("%q:%q", key, value)) {
+ content := android.ContentFromFileRuleForTests(t, ctx, jsonOut)
+ if !strings.Contains(content, fmt.Sprintf("%q:%q", key, value)) {
t.Errorf("%q must include %q:%q but it only has %v", jsonPath, key, value, jsonOut.Args["content"])
}
}
@@ -167,8 +168,8 @@
filepath.Join(staticDir, "libvendor_available.a.json"),
filepath.Join(staticDir, "libvendor_available.cfi.a.json"))
- checkJsonContents(t, snapshotSingleton, filepath.Join(staticDir, "libb.a.json"), "MinSdkVersion", "apex_inherit")
- checkJsonContents(t, snapshotSingleton, filepath.Join(staticDir, "libvendor_available.a.json"), "MinSdkVersion", "29")
+ checkJsonContents(t, ctx, snapshotSingleton, filepath.Join(staticDir, "libb.a.json"), "MinSdkVersion", "apex_inherit")
+ checkJsonContents(t, ctx, snapshotSingleton, filepath.Join(staticDir, "libvendor_available.a.json"), "MinSdkVersion", "29")
// For binary executables, all vendor:true and vendor_available modules are captured.
if archType == "arm64" {
@@ -340,6 +341,7 @@
vendor: true,
nocrt: true,
no_libcrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
compile_multilib: "64",
@@ -457,6 +459,7 @@
vendor: true,
nocrt: true,
no_libcrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
}
@@ -466,6 +469,7 @@
vendor: true,
nocrt: true,
no_libcrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
shared_libs: ["libvndk", "libvendor_available", "libllndk"],
@@ -486,6 +490,7 @@
vendor: true,
nocrt: true,
no_libcrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
static_libs: ["libvendor"],
@@ -500,6 +505,7 @@
vendor: true,
nocrt: true,
no_libcrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
vndk: {
@@ -596,6 +602,7 @@
target_arch: "arm64",
compile_multilib: "both",
vendor: true,
+ no_crt_pad_segment: true,
shared_libs: [
"libvendor_without_snapshot",
"libvendor_available",
@@ -619,6 +626,7 @@
target_arch: "arm64",
compile_multilib: "both",
vendor: true,
+ no_crt_pad_segment: true,
overrides: ["libvendor"],
shared_libs: [
"libvendor_without_snapshot",
@@ -656,6 +664,7 @@
target_arch: "arm64",
compile_multilib: "32",
vendor: true,
+ no_crt_pad_segment: true,
arch: {
arm: {
src: "lib32.so",
@@ -682,6 +691,7 @@
target_arch: "arm64",
compile_multilib: "64",
vendor: true,
+ no_crt_pad_segment: true,
arch: {
arm64: {
src: "lib64.so",
@@ -721,6 +731,7 @@
target_arch: "arm64",
compile_multilib: "both",
vendor: true,
+ no_crt_pad_segment: true,
arch: {
arm64: {
src: "libvendor_available.so",
diff --git a/cc/vndk.go b/cc/vndk.go
index 5ac5032..2b2ea64 100644
--- a/cc/vndk.go
+++ b/cc/vndk.go
@@ -28,10 +28,12 @@
"android/soong/snapshot"
"github.com/google/blueprint"
+ "github.com/google/blueprint/proptools"
)
const (
llndkLibrariesTxt = "llndk.libraries.txt"
+ llndkLibrariesTxtForApex = "llndk.libraries.txt.apex"
vndkCoreLibrariesTxt = "vndkcore.libraries.txt"
vndkSpLibrariesTxt = "vndksp.libraries.txt"
vndkPrivateLibrariesTxt = "vndkprivate.libraries.txt"
@@ -40,6 +42,7 @@
)
func VndkLibrariesTxtModules(vndkVersion string, ctx android.BaseModuleContext) []string {
+ // Return the list of vndk txt files for the vndk apex of the vndkVersion.
if vndkVersion == "current" {
// We can assume all txt files are snapshotted if we find one of them.
currentVndkSnapshotted := ctx.OtherModuleExists(insertVndkVersion(llndkLibrariesTxt, ctx.DeviceConfig().PlatformVndkVersion()))
@@ -51,20 +54,13 @@
vndkVersion = ctx.DeviceConfig().PlatformVndkVersion()
} else {
// Use the txt files generated from the source
- result := []string{
+ return []string{
+ llndkLibrariesTxtForApex,
vndkCoreLibrariesTxt,
vndkSpLibrariesTxt,
vndkPrivateLibrariesTxt,
vndkProductLibrariesTxt,
}
-
- // TODO(b/290159430) This part will not be required once deprecation
- // of VNDK is handled with 'ro.vndk.version' property
- if !ctx.Config().IsVndkDeprecated() {
- result = append(result, llndkLibrariesTxt)
- }
-
- return result
}
}
@@ -381,22 +377,17 @@
return false
}
- // ignore prebuilt vndk modules that are newer than or equal to the platform vndk version
- platformVndkApiLevel := android.ApiLevelOrPanic(mctx, mctx.DeviceConfig().PlatformVndkVersion())
- if platformVndkApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(mctx, p.Version())) {
- return false
+ platformVndkVersion := mctx.DeviceConfig().PlatformVndkVersion()
+ if platformVndkVersion != "" {
+ // ignore prebuilt vndk modules that are newer than or equal to the platform vndk version
+ platformVndkApiLevel := android.ApiLevelOrPanic(mctx, platformVndkVersion)
+ if platformVndkApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(mctx, p.Version())) {
+ return false
+ }
}
}
if lib, ok := m.linker.(libraryInterface); ok {
- // VNDK APEX for VNDK-Lite devices will have VNDK-SP libraries from core variants
- if mctx.DeviceConfig().VndkVersion() == "" {
- // b/73296261: filter out libz.so because it is considered as LLNDK for VNDK-lite devices
- if mctx.ModuleName() == "libz" {
- return false
- }
- return m.ImageVariation().Variation == android.CoreVariation && lib.shared() && m.IsVndkSp() && !m.IsVndkExt()
- }
// VNDK APEX doesn't need stub variants
if lib.buildStubs() {
return false
@@ -422,11 +413,11 @@
lib, isLib := m.linker.(*libraryDecorator)
prebuiltLib, isPrebuiltLib := m.linker.(*prebuiltLibraryLinker)
- if m.UseVndk() && isLib && lib.hasLLNDKStubs() {
+ if m.InVendorOrProduct() && isLib && lib.hasLLNDKStubs() {
m.VendorProperties.IsLLNDK = true
m.VendorProperties.IsVNDKPrivate = Bool(lib.Properties.Llndk.Private)
}
- if m.UseVndk() && isPrebuiltLib && prebuiltLib.hasLLNDKStubs() {
+ if m.InVendorOrProduct() && isPrebuiltLib && prebuiltLib.hasLLNDKStubs() {
m.VendorProperties.IsLLNDK = true
m.VendorProperties.IsVNDKPrivate = Bool(prebuiltLib.Properties.Llndk.Private)
}
@@ -451,6 +442,7 @@
func RegisterVndkLibraryTxtTypes(ctx android.RegistrationContext) {
ctx.RegisterParallelSingletonModuleType("llndk_libraries_txt", llndkLibrariesTxtFactory)
+ ctx.RegisterParallelSingletonModuleType("llndk_libraries_txt_for_apex", llndkLibrariesTxtApexOnlyFactory)
ctx.RegisterParallelSingletonModuleType("vndksp_libraries_txt", vndkSPLibrariesTxtFactory)
ctx.RegisterParallelSingletonModuleType("vndkcore_libraries_txt", vndkCoreLibrariesTxtFactory)
ctx.RegisterParallelSingletonModuleType("vndkprivate_libraries_txt", vndkPrivateLibrariesTxtFactory)
@@ -474,22 +466,31 @@
type VndkLibrariesTxtProperties struct {
Insert_vndk_version *bool
+ Stem *string
}
var _ etc.PrebuiltEtcModule = &vndkLibrariesTxt{}
var _ android.OutputFileProducer = &vndkLibrariesTxt{}
// llndk_libraries_txt is a singleton module whose content is a list of LLNDK libraries
-// generated by Soong but can be referenced by other modules.
-// For example, apex_vndk can depend on these files as prebuilt.
+// generated by Soong.
// Make uses LLNDK_LIBRARIES to determine which libraries to install.
-// HWASAN is only part of the LL-NDK in builds in which libc depends on HWASAN.
+// HWASAN is only part of the LLNDK in builds in which libc depends on HWASAN.
// Therefore, by removing the library here, we cause it to only be installed if libc
// depends on it.
func llndkLibrariesTxtFactory() android.SingletonModule {
return newVndkLibrariesWithMakeVarFilter(llndkLibraries, "LLNDK_LIBRARIES", "libclang_rt.hwasan")
}
+// llndk_libraries_txt_for_apex is a singleton module that provide the same LLNDK libraries list
+// with the llndk_libraries_txt, but skips setting make variable LLNDK_LIBRARIES. So, it must not
+// be used without installing llndk_libraries_txt singleton.
+// We include llndk_libraries_txt by default to install the llndk.libraries.txt file to system/etc.
+// This singleton module is to install the llndk.libraries.<ver>.txt file to vndk apex.
+func llndkLibrariesTxtApexOnlyFactory() android.SingletonModule {
+ return newVndkLibrariesWithMakeVarFilter(llndkLibraries, "", "libclang_rt.hwasan")
+}
+
// vndksp_libraries_txt is a singleton module whose content is a list of VNDKSP libraries
// generated by Soong but can be referenced by other modules.
// For example, apex_vndk can depend on these files as prebuilt.
@@ -557,15 +558,10 @@
}
func (txt *vndkLibrariesTxt) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- filename := txt.Name()
+ filename := proptools.StringDefault(txt.properties.Stem, txt.Name())
- shouldInsertVndkVersion := BoolDefault(txt.properties.Insert_vndk_version, true)
- // llndk.libraries.txt file installed in the system image should not contain version info.
- if ctx.Config().IsVndkDeprecated() && txt.Name() == llndkLibrariesTxt {
- shouldInsertVndkVersion = false
- }
- if shouldInsertVndkVersion {
- filename = insertVndkVersion(txt.Name(), ctx.DeviceConfig().PlatformVndkVersion())
+ if Bool(txt.properties.Insert_vndk_version) {
+ filename = insertVndkVersion(filename, ctx.DeviceConfig().PlatformVndkVersion())
}
txt.outputFile = android.PathForModuleOut(ctx, filename).OutputPath
@@ -592,6 +588,10 @@
}
func (txt *vndkLibrariesTxt) MakeVars(ctx android.MakeVarsContext) {
+ if txt.makeVarName == "" {
+ return
+ }
+
filter := func(modules []string, prefix string) []string {
if prefix == "" {
return modules
@@ -767,7 +767,7 @@
prop.MinSdkVersion = m.MinSdkVersion()
if ctx.Config().VndkSnapshotBuildArtifacts() {
- exportedInfo := ctx.ModuleProvider(m, FlagExporterInfoProvider).(FlagExporterInfo)
+ exportedInfo, _ := android.SingletonModuleProvider(ctx, m, FlagExporterInfoProvider)
prop.ExportedFlags = exportedInfo.Flags
prop.ExportedDirs = exportedInfo.IncludeDirs.Strings()
prop.ExportedSystemDirs = exportedInfo.SystemIncludeDirs.Strings()
@@ -792,7 +792,7 @@
return
}
- apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.SingletonModuleProvider(ctx, module, android.ApexInfoProvider)
vndkType, ok := isVndkSnapshotAware(ctx.DeviceConfig(), m, apexInfo)
if !ok {
diff --git a/cc/vndk_prebuilt.go b/cc/vndk_prebuilt.go
index 5e526db..43030b8 100644
--- a/cc/vndk_prebuilt.go
+++ b/cc/vndk_prebuilt.go
@@ -131,11 +131,14 @@
func (p *vndkPrebuiltLibraryDecorator) link(ctx ModuleContext,
flags Flags, deps PathDeps, objs Objects) android.Path {
- platformVndkApiLevel := android.ApiLevelOrPanic(ctx, ctx.DeviceConfig().PlatformVndkVersion())
- if platformVndkApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(ctx, p.Version())) {
- // This prebuilt VNDK module is not required for the current build
- ctx.Module().HideFromMake()
- return nil
+ platformVndkVersion := ctx.DeviceConfig().PlatformVndkVersion()
+ if platformVndkVersion != "" {
+ platformVndkApiLevel := android.ApiLevelOrPanic(ctx, platformVndkVersion)
+ if platformVndkApiLevel.LessThanOrEqualTo(android.ApiLevelOrPanic(ctx, p.Version())) {
+ // This prebuilt VNDK module is not required for the current build
+ ctx.Module().HideFromMake()
+ return nil
+ }
}
if !p.MatchesWithDevice(ctx.DeviceConfig()) {
@@ -171,7 +174,7 @@
p.androidMkSuffix = ""
}
- ctx.SetProvider(SharedLibraryInfoProvider, SharedLibraryInfo{
+ android.SetProvider(ctx, SharedLibraryInfoProvider, SharedLibraryInfo{
SharedLibrary: in,
Target: ctx.Target(),
@@ -187,6 +190,11 @@
return nil
}
+func (p *vndkPrebuiltLibraryDecorator) moduleInfoJSON(ctx ModuleContext, moduleInfoJSON *android.ModuleInfoJSON) {
+ p.libraryDecorator.moduleInfoJSON(ctx, moduleInfoJSON)
+ moduleInfoJSON.SubName += p.androidMkSuffix
+}
+
func (p *vndkPrebuiltLibraryDecorator) MatchesWithDevice(config android.DeviceConfig) bool {
arches := config.Arches()
if len(arches) == 0 || arches[0].ArchType.String() != p.arch() {
@@ -227,6 +235,7 @@
prebuilt.properties.Check_elf_files = BoolPtr(false)
prebuilt.baseLinker.Properties.No_libcrt = BoolPtr(true)
prebuilt.baseLinker.Properties.Nocrt = BoolPtr(true)
+ prebuilt.baseLinker.Properties.No_crt_pad_segment = BoolPtr(true)
// Prevent default system libs (libc, libm, and libdl) from being linked
if prebuilt.baseLinker.Properties.System_shared_libs == nil {
@@ -241,14 +250,6 @@
&prebuilt.properties,
)
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
- // empty BOARD_VNDK_VERSION implies that the device won't support
- // system only OTA. In this case, VNDK snapshots aren't needed.
- if ctx.DeviceConfig().VndkVersion() == "" {
- ctx.Module().Disable()
- }
- })
-
return module
}
diff --git a/cmd/extract_apks/main.go b/cmd/extract_apks/main.go
index 2e71fe1..a7308b4 100644
--- a/cmd/extract_apks/main.go
+++ b/cmd/extract_apks/main.go
@@ -76,8 +76,8 @@
if err != nil {
return nil, err
}
- bytes := make([]byte, tocFile.FileHeader.UncompressedSize64)
- if _, err := rc.Read(bytes); err != nil && err != io.EOF {
+ bytes, err := io.ReadAll(rc)
+ if err != nil {
return nil, err
}
rc.Close()
diff --git a/cmd/merge_module_info_json/Android.bp b/cmd/merge_module_info_json/Android.bp
new file mode 100644
index 0000000..1ae6a47
--- /dev/null
+++ b/cmd/merge_module_info_json/Android.bp
@@ -0,0 +1,30 @@
+// Copyright 2021 Google Inc. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+blueprint_go_binary {
+ name: "merge_module_info_json",
+ srcs: [
+ "merge_module_info_json.go",
+ ],
+ deps: [
+ "soong-response",
+ ],
+ testSrcs: [
+ "merge_module_info_json_test.go",
+ ],
+}
diff --git a/cmd/merge_module_info_json/merge_module_info_json.go b/cmd/merge_module_info_json/merge_module_info_json.go
new file mode 100644
index 0000000..0143984
--- /dev/null
+++ b/cmd/merge_module_info_json/merge_module_info_json.go
@@ -0,0 +1,223 @@
+// 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.
+
+// merge_module_info_json is a utility that merges module_info.json files generated by
+// Soong and Make.
+
+package main
+
+import (
+ "android/soong/response"
+ "cmp"
+ "encoding/json"
+ "flag"
+ "fmt"
+ "os"
+ "slices"
+)
+
+var (
+ out = flag.String("o", "", "output file")
+ listFile = flag.String("l", "", "input file list file")
+)
+
+func usage() {
+ fmt.Fprintf(os.Stderr, "usage: %s -o <output file> <input files>\n", os.Args[0])
+ flag.PrintDefaults()
+ fmt.Fprintln(os.Stderr, "merge_module_info_json reads input files that each contain an array of json objects")
+ fmt.Fprintln(os.Stderr, "and writes them out as a single json array to the output file.")
+
+ os.Exit(2)
+}
+
+func main() {
+ flag.Usage = usage
+ flag.Parse()
+
+ if *out == "" {
+ fmt.Fprintf(os.Stderr, "%s: error: -o is required\n", os.Args[0])
+ usage()
+ }
+
+ inputs := flag.Args()
+ if *listFile != "" {
+ listFileInputs, err := readListFile(*listFile)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "failed to read list file %s: %s", *listFile, err)
+ os.Exit(1)
+ }
+ inputs = append(inputs, listFileInputs...)
+ }
+
+ err := mergeJsonObjects(*out, inputs)
+
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%s: error: %s\n", os.Args[0], err.Error())
+ os.Exit(1)
+ }
+}
+
+func readListFile(file string) ([]string, error) {
+ f, err := os.Open(*listFile)
+ if err != nil {
+ return nil, err
+ }
+ return response.ReadRspFile(f)
+}
+
+func mergeJsonObjects(output string, inputs []string) error {
+ combined := make(map[string]any)
+ for _, input := range inputs {
+ objects, err := decodeObjectFromJson(input)
+ if err != nil {
+ return err
+ }
+
+ for _, object := range objects {
+ for k, v := range object {
+ if old, exists := combined[k]; exists {
+ v = combine(old, v)
+ }
+ combined[k] = v
+ }
+ }
+ }
+
+ f, err := os.Create(output)
+ if err != nil {
+ return fmt.Errorf("failed to open output file: %w", err)
+ }
+ encoder := json.NewEncoder(f)
+ encoder.SetIndent("", " ")
+ err = encoder.Encode(combined)
+ if err != nil {
+ return fmt.Errorf("failed to encode to output file: %w", err)
+ }
+
+ return nil
+}
+
+func decodeObjectFromJson(input string) ([]map[string]any, error) {
+ f, err := os.Open(input)
+ if err != nil {
+ return nil, fmt.Errorf("failed to open input file: %w", err)
+ }
+
+ decoder := json.NewDecoder(f)
+ var object any
+ err = decoder.Decode(&object)
+ if err != nil {
+ return nil, fmt.Errorf("failed to parse input file %q: %w", input, err)
+ }
+
+ switch o := object.(type) {
+ case []any:
+ var ret []map[string]any
+ for _, arrayElement := range o {
+ if m, ok := arrayElement.(map[string]any); ok {
+ ret = append(ret, m)
+ } else {
+ return nil, fmt.Errorf("unknown JSON type in array %T", arrayElement)
+ }
+ }
+ return ret, nil
+
+ case map[string]any:
+ return []map[string]any{o}, nil
+ }
+
+ return nil, fmt.Errorf("unknown JSON type %T", object)
+}
+
+func combine(old, new any) any {
+ // fmt.Printf("%#v %#v\n", old, new)
+ switch oldTyped := old.(type) {
+ case map[string]any:
+ if newObject, ok := new.(map[string]any); ok {
+ return combineObjects(oldTyped, newObject)
+ } else {
+ panic(fmt.Errorf("expected map[string]any, got %#v", new))
+ }
+ case []any:
+ if newArray, ok := new.([]any); ok {
+ return combineArrays(oldTyped, newArray)
+ } else {
+ panic(fmt.Errorf("expected []any, got %#v", new))
+ }
+ case string:
+ if newString, ok := new.(string); ok {
+ if oldTyped != newString {
+ panic(fmt.Errorf("strings %q and %q don't match", oldTyped, newString))
+ }
+ return oldTyped
+ } else {
+ panic(fmt.Errorf("expected []any, got %#v", new))
+ }
+ default:
+ panic(fmt.Errorf("can't combine type %T", old))
+ }
+}
+
+func combineObjects(old, new map[string]any) map[string]any {
+ for k, newField := range new {
+ // HACK: Don't merge "test_config" field. This matches the behavior in base_rules.mk that overwrites
+ // instead of appending ALL_MODULES.$(my_register_name).TEST_CONFIG, keeping the
+ if k == "test_config" {
+ old[k] = newField
+ continue
+ }
+ if oldField, exists := old[k]; exists {
+ oldField = combine(oldField, newField)
+ old[k] = oldField
+ } else {
+ old[k] = newField
+ }
+ }
+
+ return old
+}
+
+func combineArrays(old, new []any) []any {
+ containsNonStrings := false
+ for _, oldElement := range old {
+ switch oldElement.(type) {
+ case string:
+ default:
+ containsNonStrings = true
+ }
+ }
+ for _, newElement := range new {
+ found := false
+ for _, oldElement := range old {
+ if oldElement == newElement {
+ found = true
+ break
+ }
+ }
+ if !found {
+ switch newElement.(type) {
+ case string:
+ default:
+ containsNonStrings = true
+ }
+ old = append(old, newElement)
+ }
+ }
+ if !containsNonStrings {
+ slices.SortFunc(old, func(a, b any) int {
+ return cmp.Compare(a.(string), b.(string))
+ })
+ }
+ return old
+}
diff --git a/cmd/merge_module_info_json/merge_module_info_json_test.go b/cmd/merge_module_info_json/merge_module_info_json_test.go
new file mode 100644
index 0000000..dbf1aa1
--- /dev/null
+++ b/cmd/merge_module_info_json/merge_module_info_json_test.go
@@ -0,0 +1,58 @@
+// 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 main
+
+import (
+ "reflect"
+ "testing"
+)
+
+func Test_combine(t *testing.T) {
+ tests := []struct {
+ name string
+ old any
+ new any
+ want any
+ }{
+ {
+ name: "objects",
+ old: map[string]any{
+ "foo": "bar",
+ "baz": []any{"a"},
+ },
+ new: map[string]any{
+ "foo": "bar",
+ "baz": []any{"b"},
+ },
+ want: map[string]any{
+ "foo": "bar",
+ "baz": []any{"a", "b"},
+ },
+ },
+ {
+ name: "arrays",
+ old: []any{"foo", "bar"},
+ new: []any{"foo", "baz"},
+ want: []any{"bar", "baz", "foo"},
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ if got := combine(tt.old, tt.new); !reflect.DeepEqual(got, tt.want) {
+ t.Errorf("combine() = %v, want %v", got, tt.want)
+ }
+ })
+ }
+}
diff --git a/cmd/merge_zips/merge_zips.go b/cmd/merge_zips/merge_zips.go
index a70a9d1..1aa6f6f 100644
--- a/cmd/merge_zips/merge_zips.go
+++ b/cmd/merge_zips/merge_zips.go
@@ -96,7 +96,9 @@
if err := ze.inputZip.Open(); err != nil {
return err
}
- return zw.CopyFrom(ze.inputZip.Entries()[ze.index], dest)
+ entry := ze.inputZip.Entries()[ze.index]
+ entry.SetModTime(jar.DefaultTime)
+ return zw.CopyFrom(entry, dest)
}
// a ZipEntryFromBuffer is a ZipEntryContents that pulls its content from a []byte
diff --git a/cmd/merge_zips/merge_zips_test.go b/cmd/merge_zips/merge_zips_test.go
index 767d4e61..64b08d0 100644
--- a/cmd/merge_zips/merge_zips_test.go
+++ b/cmd/merge_zips/merge_zips_test.go
@@ -22,40 +22,45 @@
"strconv"
"strings"
"testing"
+ "time"
"android/soong/jar"
"android/soong/third_party/zip"
)
type testZipEntry struct {
- name string
- mode os.FileMode
- data []byte
- method uint16
+ name string
+ mode os.FileMode
+ data []byte
+ method uint16
+ timestamp time.Time
}
var (
- A = testZipEntry{"A", 0755, []byte("foo"), zip.Deflate}
- a = testZipEntry{"a", 0755, []byte("foo"), zip.Deflate}
- a2 = testZipEntry{"a", 0755, []byte("FOO2"), zip.Deflate}
- a3 = testZipEntry{"a", 0755, []byte("Foo3"), zip.Deflate}
- bDir = testZipEntry{"b/", os.ModeDir | 0755, nil, zip.Deflate}
- bbDir = testZipEntry{"b/b/", os.ModeDir | 0755, nil, zip.Deflate}
- bbb = testZipEntry{"b/b/b", 0755, nil, zip.Deflate}
- ba = testZipEntry{"b/a", 0755, []byte("foo"), zip.Deflate}
- bc = testZipEntry{"b/c", 0755, []byte("bar"), zip.Deflate}
- bd = testZipEntry{"b/d", 0700, []byte("baz"), zip.Deflate}
- be = testZipEntry{"b/e", 0700, []byte(""), zip.Deflate}
+ A = testZipEntry{"A", 0755, []byte("foo"), zip.Deflate, jar.DefaultTime}
+ a = testZipEntry{"a", 0755, []byte("foo"), zip.Deflate, jar.DefaultTime}
+ a2 = testZipEntry{"a", 0755, []byte("FOO2"), zip.Deflate, jar.DefaultTime}
+ a3 = testZipEntry{"a", 0755, []byte("Foo3"), zip.Deflate, jar.DefaultTime}
+ bDir = testZipEntry{"b/", os.ModeDir | 0755, nil, zip.Deflate, jar.DefaultTime}
+ bbDir = testZipEntry{"b/b/", os.ModeDir | 0755, nil, zip.Deflate, jar.DefaultTime}
+ bbb = testZipEntry{"b/b/b", 0755, nil, zip.Deflate, jar.DefaultTime}
+ ba = testZipEntry{"b/a", 0755, []byte("foo"), zip.Deflate, jar.DefaultTime}
+ bc = testZipEntry{"b/c", 0755, []byte("bar"), zip.Deflate, jar.DefaultTime}
+ bd = testZipEntry{"b/d", 0700, []byte("baz"), zip.Deflate, jar.DefaultTime}
+ be = testZipEntry{"b/e", 0700, []byte(""), zip.Deflate, jar.DefaultTime}
- service1a = testZipEntry{"META-INF/services/service1", 0755, []byte("class1\nclass2\n"), zip.Store}
- service1b = testZipEntry{"META-INF/services/service1", 0755, []byte("class1\nclass3\n"), zip.Deflate}
- service1combined = testZipEntry{"META-INF/services/service1", 0755, []byte("class1\nclass2\nclass3\n"), zip.Store}
- service2 = testZipEntry{"META-INF/services/service2", 0755, []byte("class1\nclass2\n"), zip.Deflate}
+ withTimestamp = testZipEntry{"timestamped", 0755, nil, zip.Store, jar.DefaultTime.Add(time.Hour)}
+ withoutTimestamp = testZipEntry{"timestamped", 0755, nil, zip.Store, jar.DefaultTime}
- metainfDir = testZipEntry{jar.MetaDir, os.ModeDir | 0755, nil, zip.Deflate}
- manifestFile = testZipEntry{jar.ManifestFile, 0755, []byte("manifest"), zip.Deflate}
- manifestFile2 = testZipEntry{jar.ManifestFile, 0755, []byte("manifest2"), zip.Deflate}
- moduleInfoFile = testZipEntry{jar.ModuleInfoClass, 0755, []byte("module-info"), zip.Deflate}
+ service1a = testZipEntry{"META-INF/services/service1", 0755, []byte("class1\nclass2\n"), zip.Store, jar.DefaultTime}
+ service1b = testZipEntry{"META-INF/services/service1", 0755, []byte("class1\nclass3\n"), zip.Deflate, jar.DefaultTime}
+ service1combined = testZipEntry{"META-INF/services/service1", 0755, []byte("class1\nclass2\nclass3\n"), zip.Store, jar.DefaultTime}
+ service2 = testZipEntry{"META-INF/services/service2", 0755, []byte("class1\nclass2\n"), zip.Deflate, jar.DefaultTime}
+
+ metainfDir = testZipEntry{jar.MetaDir, os.ModeDir | 0755, nil, zip.Deflate, jar.DefaultTime}
+ manifestFile = testZipEntry{jar.ManifestFile, 0755, []byte("manifest"), zip.Deflate, jar.DefaultTime}
+ manifestFile2 = testZipEntry{jar.ManifestFile, 0755, []byte("manifest2"), zip.Deflate, jar.DefaultTime}
+ moduleInfoFile = testZipEntry{jar.ModuleInfoClass, 0755, []byte("module-info"), zip.Deflate, jar.DefaultTime}
)
type testInputZip struct {
@@ -252,6 +257,14 @@
jar: true,
out: []testZipEntry{service1combined, service2},
},
+ {
+ name: "strip timestamps",
+ in: [][]testZipEntry{
+ {withTimestamp},
+ {a},
+ },
+ out: []testZipEntry{withoutTimestamp, a},
+ },
}
for _, test := range testCases {
@@ -307,6 +320,7 @@
}
fh.SetMode(e.mode)
fh.Method = e.method
+ fh.SetModTime(e.timestamp)
fh.UncompressedSize64 = uint64(len(e.data))
fh.CRC32 = crc32.ChecksumIEEE(e.data)
if fh.Method == zip.Store {
@@ -354,7 +368,7 @@
var ret string
for _, f := range zr.File {
- ret += fmt.Sprintf("%v: %v %v %08x\n", f.Name, f.Mode(), f.UncompressedSize64, f.CRC32)
+ ret += fmt.Sprintf("%v: %v %v %08x %s\n", f.Name, f.Mode(), f.UncompressedSize64, f.CRC32, f.ModTime())
}
return ret
diff --git a/cmd/path_interposer/main.go b/cmd/path_interposer/main.go
index 8b9de52..c8c1464 100644
--- a/cmd/path_interposer/main.go
+++ b/cmd/path_interposer/main.go
@@ -140,7 +140,7 @@
defer func() { <-waitForLog }()
}
if config.Error {
- return 1, fmt.Errorf("%q is not allowed to be used. See https://android.googlesource.com/platform/build/+/master/Changes.md#PATH_Tools for more information.", base)
+ return 1, fmt.Errorf("%q is not allowed to be used. See https://android.googlesource.com/platform/build/+/main/Changes.md#PATH_Tools for more information.", base)
}
}
diff --git a/cmd/path_interposer/main_test.go b/cmd/path_interposer/main_test.go
index c89d623..8ae1d7d 100644
--- a/cmd/path_interposer/main_test.go
+++ b/cmd/path_interposer/main_test.go
@@ -138,7 +138,7 @@
args: []string{"path_interposer_test_not_allowed"},
exitCode: 1,
- err: fmt.Errorf(`"path_interposer_test_not_allowed" is not allowed to be used. See https://android.googlesource.com/platform/build/+/master/Changes.md#PATH_Tools for more information.`),
+ err: fmt.Errorf(`"path_interposer_test_not_allowed" is not allowed to be used. See https://android.googlesource.com/platform/build/+/main/Changes.md#PATH_Tools for more information.`),
logEntry: "path_interposer_test_not_allowed",
},
}
diff --git a/cmd/pom2bp/pom2bp.go b/cmd/pom2bp/pom2bp.go
index 3fb4454..6d1caf9 100644
--- a/cmd/pom2bp/pom2bp.go
+++ b/cmd/pom2bp/pom2bp.go
@@ -651,7 +651,7 @@
{{- end}}
],
{{- end}}
- java_version: "1.7",
+ java_version: "1.8",
}
`))
diff --git a/cmd/pom2mk/pom2mk.go b/cmd/pom2mk/pom2mk.go
index b347155..5ca770e 100644
--- a/cmd/pom2mk/pom2mk.go
+++ b/cmd/pom2mk/pom2mk.go
@@ -262,7 +262,7 @@
{{.MkName}}-nodeps{{end}}{{range .MkAarDeps}} \
{{.}}{{end}}
LOCAL_JAR_EXCLUDE_FILES := none
-LOCAL_JAVA_LANGUAGE_VERSION := 1.7
+LOCAL_JAVA_LANGUAGE_VERSION := 1.8
LOCAL_USE_AAPT2 := true
include $(BUILD_STATIC_JAVA_LIBRARY)
`))
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index fc56dd5..e69a930 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -22,6 +22,7 @@
"flag"
"fmt"
"io"
+ "io/fs"
"io/ioutil"
"os"
"os/exec"
@@ -119,6 +120,9 @@
}
manifest, err := readManifest(manifestFile)
+ if err != nil {
+ return err
+ }
if len(manifest.Commands) == 0 {
return fmt.Errorf("at least one commands entry is required in %q", manifestFile)
@@ -475,7 +479,8 @@
// copyOneFile copies a file and its permissions. If forceExecutable is true it adds u+x to the
// permissions. If exists is allowFromNotExists it returns nil if the from path doesn't exist.
// If write is onlyWriteIfChanged then the output file is compared to the input file and not written to
-// if it is the same, avoiding updating the timestamp.
+// if it is the same, avoiding updating the timestamp. If from is a symlink, the symlink itself
+// will be copied, instead of what it points to.
func copyOneFile(from string, to string, forceExecutable bool, exists existsType,
write writeType) error {
err := os.MkdirAll(filepath.Dir(to), 0777)
@@ -483,7 +488,7 @@
return err
}
- stat, err := os.Stat(from)
+ stat, err := os.Lstat(from)
if err != nil {
if os.IsNotExist(err) && exists == allowFromNotExists {
return nil
@@ -491,6 +496,25 @@
return err
}
+ if stat.Mode()&fs.ModeSymlink != 0 {
+ linkTarget, err := os.Readlink(from)
+ if err != nil {
+ return err
+ }
+ if write == onlyWriteIfChanged {
+ toLinkTarget, err := os.Readlink(to)
+ if err == nil && toLinkTarget == linkTarget {
+ return nil
+ }
+ }
+ err = os.Remove(to)
+ if err != nil && !os.IsNotExist(err) {
+ return err
+ }
+
+ return os.Symlink(linkTarget, to)
+ }
+
perm := stat.Mode()
if forceExecutable {
perm = perm | 0100 // u+x
diff --git a/cmd/soong_build/main.go b/cmd/soong_build/main.go
index 626f076..673f305 100644
--- a/cmd/soong_build/main.go
+++ b/cmd/soong_build/main.go
@@ -21,7 +21,6 @@
"fmt"
"os"
"path/filepath"
- "regexp"
"strings"
"time"
@@ -29,7 +28,6 @@
"android/soong/android/allowlists"
"android/soong/bp2build"
"android/soong/shared"
- "android/soong/ui/metrics/bp2build_metrics_proto"
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
@@ -75,18 +73,13 @@
flag.StringVar(&cmdlineArgs.ModuleActionsFile, "module_actions_file", "", "JSON file to output inputs/outputs of actions of modules")
flag.StringVar(&cmdlineArgs.DocFile, "soong_docs", "", "build documentation file to output")
flag.StringVar(&cmdlineArgs.BazelQueryViewDir, "bazel_queryview_dir", "", "path to the bazel queryview directory relative to --top")
- flag.StringVar(&cmdlineArgs.Bp2buildMarker, "bp2build_marker", "", "If set, run bp2build, touch the specified marker file then exit")
- flag.StringVar(&cmdlineArgs.SymlinkForestMarker, "symlink_forest_marker", "", "If set, create the bp2build symlink forest, touch the specified marker file, then exit")
flag.StringVar(&cmdlineArgs.OutFile, "o", "build.ninja", "the Ninja file to output")
flag.StringVar(&cmdlineArgs.SoongVariables, "soong_variables", "soong.variables", "the file contains all build variables")
- flag.StringVar(&cmdlineArgs.BazelForceEnabledModules, "bazel-force-enabled-modules", "", "additional modules to build with Bazel. Comma-delimited")
flag.BoolVar(&cmdlineArgs.EmptyNinjaFile, "empty-ninja-file", false, "write out a 0-byte ninja file")
flag.BoolVar(&cmdlineArgs.MultitreeBuild, "multitree-build", false, "this is a multitree build")
- flag.BoolVar(&cmdlineArgs.BazelMode, "bazel-mode", false, "use bazel for analysis of certain modules")
- flag.BoolVar(&cmdlineArgs.BazelModeStaging, "bazel-mode-staging", false, "use bazel for analysis of certain near-ready modules")
- flag.BoolVar(&cmdlineArgs.UseBazelProxy, "use-bazel-proxy", false, "communicate with bazel using unix socket proxy instead of spawning subprocesses")
- flag.BoolVar(&cmdlineArgs.BuildFromTextStub, "build-from-text-stub", false, "build Java stubs from API text files instead of source files")
+ flag.BoolVar(&cmdlineArgs.BuildFromSourceStub, "build-from-source-stub", false, "build Java stubs from source files instead of API text files")
flag.BoolVar(&cmdlineArgs.EnsureAllowlistIntegrity, "ensure-allowlist-integrity", false, "verify that allowlisted modules are mixed-built")
+ flag.StringVar(&cmdlineArgs.ModuleDebugFile, "soong_module_debug", "", "soong module debug info file to write")
// Flags that probably shouldn't be flags of soong_build, but we haven't found
// the time to remove them yet
flag.BoolVar(&cmdlineArgs.RunGoTests, "t", false, "build and run go tests during bootstrap")
@@ -111,40 +104,6 @@
return ctx
}
-// Bazel-enabled mode. Attaches a mutator to queue Bazel requests, adds a
-// BeforePrepareBuildActionsHook to invoke Bazel, and then uses Bazel metadata
-// for modules that should be handled by Bazel.
-func runMixedModeBuild(ctx *android.Context, extraNinjaDeps []string) string {
- ctx.EventHandler.Begin("mixed_build")
- defer ctx.EventHandler.End("mixed_build")
-
- bazelHook := func() error {
- err := ctx.Config().BazelContext.QueueBazelSandwichCqueryRequests(ctx.Config())
- if err != nil {
- return err
- }
- return ctx.Config().BazelContext.InvokeBazel(ctx.Config(), ctx)
- }
- ctx.SetBeforePrepareBuildActionsHook(bazelHook)
- ninjaDeps, err := bootstrap.RunBlueprint(cmdlineArgs.Args, bootstrap.DoEverything, ctx.Context, ctx.Config())
- maybeQuit(err, "")
- ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
-
- bazelPaths, err := readFileLines(ctx.Config().Getenv("BAZEL_DEPS_FILE"))
- if err != nil {
- panic("Bazel deps file not found: " + err.Error())
- }
- ninjaDeps = append(ninjaDeps, bazelPaths...)
- ninjaDeps = append(ninjaDeps, writeBuildGlobsNinjaFile(ctx)...)
-
- writeDepFile(cmdlineArgs.OutFile, ctx.EventHandler, ninjaDeps)
-
- if needToWriteNinjaHint(ctx) {
- writeNinjaHint(ctx)
- }
- return cmdlineArgs.OutFile
-}
-
func needToWriteNinjaHint(ctx *android.Context) bool {
switch ctx.Config().GetenvWithDefault("SOONG_GENERATES_NINJA_HINT", "") {
case "always":
@@ -229,67 +188,6 @@
maybeQuit(err, "error writing soong_build metrics %s", metricsFile)
}
-// Errors out if any modules expected to be mixed_built were not, unless
-// the modules did not exist.
-func checkForAllowlistIntegrityError(configuration android.Config, isStagingMode bool) error {
- modules := findMisconfiguredModules(configuration, isStagingMode)
- if len(modules) == 0 {
- return nil
- }
-
- return fmt.Errorf("Error: expected the following modules to be mixed_built: %s", modules)
-}
-
-// Returns true if the given module has all of the following true:
-// 1. Is allowlisted to be built with Bazel.
-// 2. Has a variant which is *not* built with Bazel.
-// 3. Has no variant which is built with Bazel.
-//
-// This indicates the allowlisting of this variant had no effect.
-// TODO(b/280457637): Return true for nonexistent modules.
-func isAllowlistMisconfiguredForModule(module string, mixedBuildsEnabled map[string]struct{}, mixedBuildsDisabled map[string]struct{}) bool {
- _, enabled := mixedBuildsEnabled[module]
-
- if enabled {
- return false
- }
-
- _, disabled := mixedBuildsDisabled[module]
- return disabled
-
-}
-
-// Returns the list of modules that should have been mixed_built (per the
-// allowlists and cmdline flags) but were not.
-// Note: nonexistent modules are excluded from the list. See b/280457637
-func findMisconfiguredModules(configuration android.Config, isStagingMode bool) []string {
- retval := []string{}
- forceEnabledModules := configuration.BazelModulesForceEnabledByFlag()
-
- mixedBuildsEnabled := configuration.GetMixedBuildsEnabledModules()
- mixedBuildsDisabled := configuration.GetMixedBuildsDisabledModules()
- for _, module := range allowlists.ProdMixedBuildsEnabledList {
- if isAllowlistMisconfiguredForModule(module, mixedBuildsEnabled, mixedBuildsDisabled) {
- retval = append(retval, module)
- }
- }
-
- if isStagingMode {
- for _, module := range allowlists.StagingMixedBuildsEnabledList {
- if isAllowlistMisconfiguredForModule(module, mixedBuildsEnabled, mixedBuildsDisabled) {
- retval = append(retval, module)
- }
- }
- }
-
- for module, _ := range forceEnabledModules {
- if isAllowlistMisconfiguredForModule(module, mixedBuildsEnabled, mixedBuildsDisabled) {
- retval = append(retval, module)
- }
- }
- return retval
-}
-
func writeJsonModuleGraphAndActions(ctx *android.Context, cmdArgs android.CmdArgs) {
graphFile, graphErr := os.Create(shared.JoinPath(topDir, cmdArgs.ModuleGraphFile))
maybeQuit(graphErr, "graph err")
@@ -300,7 +198,7 @@
ctx.Context.PrintJSONGraphAndActions(graphFile, actionsFile)
}
-func writeBuildGlobsNinjaFile(ctx *android.Context) []string {
+func writeBuildGlobsNinjaFile(ctx *android.Context) {
ctx.EventHandler.Begin("globs_ninja_file")
defer ctx.EventHandler.End("globs_ninja_file")
@@ -312,7 +210,6 @@
SrcDir: ctx.SrcDir(),
}, ctx.Config())
maybeQuit(err, "")
- return bootstrap.GlobFileListFiles(globDir)
}
func writeDepFile(outputFile string, eventHandler *metrics.EventHandler, ninjaDeps []string) {
@@ -342,8 +239,7 @@
maybeQuit(err, "")
ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
- globListFiles := writeBuildGlobsNinjaFile(ctx)
- ninjaDeps = append(ninjaDeps, globListFiles...)
+ writeBuildGlobsNinjaFile(ctx)
// Convert the Soong module graph into Bazel BUILD files.
switch ctx.Config().BuildMode {
@@ -423,38 +319,11 @@
metricsDir := availableEnv["LOG_DIR"]
ctx := newContext(configuration)
+ android.StartBackgroundMetrics(configuration)
- var finalOutputFile string
-
- // Run Soong for a specific activity, like bp2build, queryview
- // or the actual Soong build for the build.ninja file.
- switch configuration.BuildMode {
- case android.SymlinkForest:
- finalOutputFile = runSymlinkForestCreation(ctx, extraNinjaDeps, metricsDir)
- case android.Bp2build:
- // Run the alternate pipeline of bp2build mutators and singleton to convert
- // Blueprint to BUILD files before everything else.
- finalOutputFile = runBp2Build(ctx, extraNinjaDeps, metricsDir)
- default:
- ctx.Register()
- isMixedBuildsEnabled := configuration.IsMixedBuildsEnabled()
- if isMixedBuildsEnabled {
- finalOutputFile = runMixedModeBuild(ctx, extraNinjaDeps)
- if cmdlineArgs.EnsureAllowlistIntegrity {
- if err := checkForAllowlistIntegrityError(configuration, cmdlineArgs.BazelModeStaging); err != nil {
- maybeQuit(err, "")
- }
- }
- } else {
- finalOutputFile = runSoongOnlyBuild(ctx, extraNinjaDeps)
- }
- writeMetrics(configuration, ctx.EventHandler, metricsDir)
- }
-
- // Register this environment variablesas being an implicit dependencies of
- // soong_build. Changes to this environment variable will result in
- // retriggering soong_build.
- configuration.Getenv("USE_BAZEL_VERSION")
+ ctx.Register()
+ finalOutputFile := runSoongOnlyBuild(ctx, extraNinjaDeps)
+ writeMetrics(configuration, ctx.EventHandler, metricsDir)
writeUsedEnvironmentFile(configuration)
@@ -497,246 +366,6 @@
maybeQuit(err, "error touching '%s'", path)
}
-// Read the bazel.list file that the Soong Finder already dumped earlier (hopefully)
-// It contains the locations of BUILD files, BUILD.bazel files, etc. in the source dir
-func getExistingBazelRelatedFiles(topDir string) ([]string, error) {
- bazelFinderFile := filepath.Join(filepath.Dir(cmdlineArgs.ModuleListFile), "bazel.list")
- if !filepath.IsAbs(bazelFinderFile) {
- // Assume this was a relative path under topDir
- bazelFinderFile = filepath.Join(topDir, bazelFinderFile)
- }
- return readFileLines(bazelFinderFile)
-}
-
-func bazelArtifacts() []string {
- return []string{
- "bazel-bin",
- "bazel-genfiles",
- "bazel-out",
- "bazel-testlogs",
- "bazel-workspace",
- "bazel-" + filepath.Base(topDir),
- }
-}
-
-// This could in theory easily be separated into a binary that generically
-// merges two directories into a symlink tree. The main obstacle is that this
-// function currently depends on both Bazel-specific knowledge (the existence
-// of bazel-* symlinks) and configuration (the set of BUILD.bazel files that
-// should and should not be kept)
-//
-// Ideally, bp2build would write a file that contains instructions to the
-// symlink tree creation binary. Then the latter would not need to depend on
-// the very heavy-weight machinery of soong_build .
-func runSymlinkForestCreation(ctx *android.Context, extraNinjaDeps []string, metricsDir string) string {
- var ninjaDeps []string
- var mkdirCount, symlinkCount uint64
-
- ctx.EventHandler.Do("symlink_forest", func() {
- ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
- verbose := ctx.Config().IsEnvTrue("BP2BUILD_VERBOSE")
-
- // PlantSymlinkForest() returns all the directories that were readdir()'ed.
- // Such a directory SHOULD be added to `ninjaDeps` so that a child directory
- // or file created/deleted under it would trigger an update of the symlink forest.
- generatedRoot := shared.JoinPath(ctx.Config().SoongOutDir(), "bp2build")
- workspaceRoot := shared.JoinPath(ctx.Config().SoongOutDir(), "workspace")
- var symlinkForestDeps []string
- ctx.EventHandler.Do("plant", func() {
- symlinkForestDeps, mkdirCount, symlinkCount = bp2build.PlantSymlinkForest(
- verbose, topDir, workspaceRoot, generatedRoot, excludedFromSymlinkForest(ctx, verbose))
- })
- ninjaDeps = append(ninjaDeps, symlinkForestDeps...)
- })
-
- writeDepFile(cmdlineArgs.SymlinkForestMarker, ctx.EventHandler, ninjaDeps)
- touch(shared.JoinPath(topDir, cmdlineArgs.SymlinkForestMarker))
- codegenMetrics := bp2build.ReadCodegenMetrics(metricsDir)
- if codegenMetrics == nil {
- m := bp2build.CreateCodegenMetrics()
- codegenMetrics = &m
- } else {
- //TODO (usta) we cannot determine if we loaded a stale file, i.e. from an unrelated prior
- //invocation of codegen. We should simply use a separate .pb file
- }
- codegenMetrics.SetSymlinkCount(symlinkCount)
- codegenMetrics.SetMkDirCount(mkdirCount)
- writeBp2BuildMetrics(codegenMetrics, ctx.EventHandler, metricsDir)
- return cmdlineArgs.SymlinkForestMarker
-}
-
-func excludedFromSymlinkForest(ctx *android.Context, verbose bool) []string {
- excluded := bazelArtifacts()
- if cmdlineArgs.OutDir[0] != '/' {
- excluded = append(excluded, cmdlineArgs.OutDir)
- }
-
- // Find BUILD files in the srcDir which are not in the allowlist
- // (android.Bp2BuildConversionAllowlist#ShouldKeepExistingBuildFileForDir)
- // and return their paths so they can be left out of the Bazel workspace dir (i.e. ignored)
- existingBazelFiles, err := getExistingBazelRelatedFiles(topDir)
- maybeQuit(err, "Error determining existing Bazel-related files")
-
- for _, path := range existingBazelFiles {
- fullPath := shared.JoinPath(topDir, path)
- fileInfo, err2 := os.Stat(fullPath)
- if err2 != nil {
- // Warn about error, but continue trying to check files
- fmt.Fprintf(os.Stderr, "WARNING: Error accessing path '%s', err: %s\n", fullPath, err2)
- continue
- }
- // Exclude only files named 'BUILD' or 'BUILD.bazel' and unless forcibly kept
- if fileInfo.IsDir() ||
- (fileInfo.Name() != "BUILD" && fileInfo.Name() != "BUILD.bazel") ||
- ctx.Config().Bp2buildPackageConfig.ShouldKeepExistingBuildFileForDir(filepath.Dir(path)) {
- // Don't ignore this existing build file
- continue
- }
- if verbose {
- fmt.Fprintf(os.Stderr, "Ignoring existing BUILD file: %s\n", path)
- }
- excluded = append(excluded, path)
- }
-
- // Temporarily exclude stuff to make `bazel build //external/...` (and `bazel build //frameworks/...`) work
- excluded = append(excluded,
- // FIXME: 'autotest_lib' is a symlink back to external/autotest, and this causes an infinite
- // symlink expansion error for Bazel
- "external/autotest/venv/autotest_lib",
- "external/autotest/autotest_lib",
- "external/autotest/client/autotest_lib/client",
-
- // FIXME: The external/google-fruit/extras/bazel_root/third_party/fruit dir is poison
- // It contains several symlinks back to real source dirs, and those source dirs contain
- // BUILD files we want to ignore
- "external/google-fruit/extras/bazel_root/third_party/fruit",
-
- // FIXME: 'frameworks/compile/slang' has a filegroup error due to an escaping issue
- "frameworks/compile/slang",
- )
- return excluded
-}
-
-// buildTargetsByPackage parses Bazel BUILD.bazel and BUILD files under
-// the workspace, and returns a map containing names of Bazel targets defined in
-// these BUILD files.
-// For example, maps "//foo/bar" to ["baz", "qux"] if `//foo/bar:{baz,qux}` exist.
-func buildTargetsByPackage(ctx *android.Context) map[string][]string {
- existingBazelFiles, err := getExistingBazelRelatedFiles(topDir)
- maybeQuit(err, "Error determining existing Bazel-related files")
-
- result := map[string][]string{}
-
- // Search for instances of `name = "$NAME"` (with arbitrary spacing).
- targetNameRegex := regexp.MustCompile(`(?m)^\s*name\s*=\s*\"([^\"]+)\"`)
-
- for _, path := range existingBazelFiles {
- if !ctx.Config().Bp2buildPackageConfig.ShouldKeepExistingBuildFileForDir(filepath.Dir(path)) {
- continue
- }
- fullPath := shared.JoinPath(topDir, path)
- sourceDir := filepath.Dir(path)
- fileInfo, err := os.Stat(fullPath)
- maybeQuit(err, "Error accessing Bazel file '%s'", fullPath)
-
- if !fileInfo.IsDir() &&
- (fileInfo.Name() == "BUILD" || fileInfo.Name() == "BUILD.bazel") {
- // Process this BUILD file.
- buildFileContent, err := os.ReadFile(fullPath)
- maybeQuit(err, "Error reading Bazel file '%s'", fullPath)
-
- matches := targetNameRegex.FindAllStringSubmatch(string(buildFileContent), -1)
- for _, match := range matches {
- result[sourceDir] = append(result[sourceDir], match[1])
- }
- }
- }
- return result
-}
-
-// Run Soong in the bp2build mode. This creates a standalone context that registers
-// an alternate pipeline of mutators and singletons specifically for generating
-// Bazel BUILD files instead of Ninja files.
-func runBp2Build(ctx *android.Context, extraNinjaDeps []string, metricsDir string) string {
- var codegenMetrics *bp2build.CodegenMetrics
- ctx.EventHandler.Do("bp2build", func() {
-
- ctx.EventHandler.Do("read_build", func() {
- ctx.Config().SetBazelBuildFileTargets(buildTargetsByPackage(ctx))
- })
-
- // Propagate "allow misssing dependencies" bit. This is normally set in
- // newContext(), but we create ctx without calling that method.
- ctx.SetAllowMissingDependencies(ctx.Config().AllowMissingDependencies())
- ctx.SetNameInterface(newNameResolver(ctx.Config()))
- ctx.RegisterForBazelConversion()
- ctx.SetModuleListFile(cmdlineArgs.ModuleListFile)
- // Skip cloning modules during bp2build's blueprint run. Some mutators set
- // bp2build-related module values which should be preserved during codegen.
- ctx.SkipCloneModulesAfterMutators = true
-
- var ninjaDeps []string
- ninjaDeps = append(ninjaDeps, extraNinjaDeps...)
-
- // Run the loading and analysis pipeline to prepare the graph of regular
- // Modules parsed from Android.bp files, and the BazelTargetModules mapped
- // from the regular Modules.
- ctx.EventHandler.Do("bootstrap", func() {
- blueprintArgs := cmdlineArgs
- bootstrapDeps, err := bootstrap.RunBlueprint(blueprintArgs.Args,
- bootstrap.StopBeforePrepareBuildActions, ctx.Context, ctx.Config())
- maybeQuit(err, "")
- ninjaDeps = append(ninjaDeps, bootstrapDeps...)
- })
-
- globListFiles := writeBuildGlobsNinjaFile(ctx)
- ninjaDeps = append(ninjaDeps, globListFiles...)
-
- // Run the code-generation phase to convert BazelTargetModules to BUILD files
- // and print conversion codegenMetrics to the user.
- codegenContext := bp2build.NewCodegenContext(ctx.Config(), ctx, bp2build.Bp2Build, topDir)
- codegenMetrics = bp2build.Codegen(codegenContext)
-
- ninjaDeps = append(ninjaDeps, codegenContext.AdditionalNinjaDeps()...)
-
- writeDepFile(cmdlineArgs.Bp2buildMarker, ctx.EventHandler, ninjaDeps)
- touch(shared.JoinPath(topDir, cmdlineArgs.Bp2buildMarker))
- })
-
- // Only report metrics when in bp2build mode. The metrics aren't relevant
- // for queryview, since that's a total repo-wide conversion and there's a
- // 1:1 mapping for each module.
- if ctx.Config().IsEnvTrue("BP2BUILD_VERBOSE") {
- codegenMetrics.Print()
- }
- writeBp2BuildMetrics(codegenMetrics, ctx.EventHandler, metricsDir)
- return cmdlineArgs.Bp2buildMarker
-}
-
-// Write Bp2Build metrics into $LOG_DIR
-func writeBp2BuildMetrics(codegenMetrics *bp2build.CodegenMetrics, eventHandler *metrics.EventHandler, metricsDir string) {
- for _, event := range eventHandler.CompletedEvents() {
- codegenMetrics.AddEvent(&bp2build_metrics_proto.Event{
- Name: event.Id,
- StartTime: uint64(event.Start.UnixNano()),
- RealTime: event.RuntimeNanoseconds(),
- })
- }
- if len(metricsDir) < 1 {
- fmt.Fprintf(os.Stderr, "\nMissing required env var for generating bp2build metrics: LOG_DIR\n")
- os.Exit(1)
- }
- codegenMetrics.Write(metricsDir)
-}
-
-func readFileLines(path string) ([]string, error) {
- data, err := os.ReadFile(path)
- if err == nil {
- return strings.Split(strings.TrimSpace(string(data)), "\n"), nil
- }
- return nil, err
-
-}
func maybeQuit(err error, format string, args ...interface{}) {
if err == nil {
return
diff --git a/cmd/soong_ui/main.go b/cmd/soong_ui/main.go
index 4097e8a..fe3f8f7 100644
--- a/cmd/soong_ui/main.go
+++ b/cmd/soong_ui/main.go
@@ -18,7 +18,6 @@
"context"
"flag"
"fmt"
- "io/ioutil"
"os"
"path/filepath"
"strconv"
@@ -91,14 +90,6 @@
config: buildActionConfig,
stdio: stdio,
run: runMake,
- }, {
- flag: "--finalize-bazel-metrics",
- description: "finalize b metrics and upload",
- config: build.UploadOnlyConfig,
- stdio: stdio,
- // Finalize-bazel-metrics mode updates metrics files and calls the metrics
- // uploader. This marks the end of a b invocation.
- run: finalizeBazelMetrics,
},
}
@@ -190,26 +181,25 @@
CriticalPath: criticalPath,
}}
- config := c.config(buildCtx, args...)
- config.SetLogsPrefix(c.logsPrefix)
+ freshConfig := func() build.Config {
+ config := c.config(buildCtx, args...)
+ config.SetLogsPrefix(c.logsPrefix)
+ return config
+ }
+ config := freshConfig()
logsDir := config.LogsDir()
buildStarted = config.BuildStartedTimeOrDefault(buildStarted)
buildErrorFile := filepath.Join(logsDir, c.logsPrefix+"build_error")
soongMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_metrics")
rbeMetricsFile := filepath.Join(logsDir, c.logsPrefix+"rbe_metrics.pb")
- bp2buildMetricsFile := filepath.Join(logsDir, c.logsPrefix+"bp2build_metrics.pb")
- bazelMetricsFile := filepath.Join(logsDir, c.logsPrefix+"bazel_metrics.pb")
soongBuildMetricsFile := filepath.Join(logsDir, c.logsPrefix+"soong_build_metrics.pb")
metricsFiles := []string{
- buildErrorFile, // build error strings
- rbeMetricsFile, // high level metrics related to remote build execution.
- bp2buildMetricsFile, // high level metrics related to bp2build.
- soongMetricsFile, // high level metrics related to this build system.
- bazelMetricsFile, // high level metrics related to bazel execution
- soongBuildMetricsFile, // high level metrics related to soong build(except bp2build)
- config.BazelMetricsDir(), // directory that contains a set of bazel metrics.
+ buildErrorFile, // build error strings
+ rbeMetricsFile, // high level metrics related to remote build execution.
+ soongMetricsFile, // high level metrics related to this build system.
+ soongBuildMetricsFile, // high level metrics related to soong build
}
os.MkdirAll(logsDir, 0777)
@@ -223,6 +213,15 @@
log.Verbosef(" [%d] %s", i, arg)
}
+ // We need to call preProductConfigSetup before we can do product config, which is how we get
+ // PRODUCT_CONFIG_RELEASE_MAPS set for the final product config for the build.
+ // When product config uses a declarative language, we won't need to rerun product config.
+ preProductConfigSetup(buildCtx, config)
+ if build.SetProductReleaseConfigMaps(buildCtx, config) {
+ log.Verbose("Product release config maps found\n")
+ config = freshConfig()
+ }
+
defer func() {
stat.Finish()
criticalPath.WriteToMetrics(met)
@@ -235,7 +234,9 @@
}
-func logAndSymlinkSetup(buildCtx build.Context, config build.Config) {
+// This function must not modify config, since product config may cause us to recreate the config,
+// and we won't call this function a second time.
+func preProductConfigSetup(buildCtx build.Context, config build.Config) {
log := buildCtx.ContextImpl.Logger
logsPrefix := config.GetLogsPrefix()
build.SetupOutDir(buildCtx, config)
@@ -247,10 +248,9 @@
soongMetricsFile := filepath.Join(logsDir, logsPrefix+"soong_metrics")
bp2buildMetricsFile := filepath.Join(logsDir, logsPrefix+"bp2build_metrics.pb")
soongBuildMetricsFile := filepath.Join(logsDir, logsPrefix+"soong_build_metrics.pb")
- bazelMetricsFile := filepath.Join(logsDir, logsPrefix+"bazel_metrics.pb")
//Delete the stale metrics files
- staleFileSlice := []string{buildErrorFile, rbeMetricsFile, soongMetricsFile, bp2buildMetricsFile, soongBuildMetricsFile, bazelMetricsFile}
+ staleFileSlice := []string{buildErrorFile, rbeMetricsFile, soongMetricsFile, bp2buildMetricsFile, soongBuildMetricsFile}
if err := deleteStaleMetrics(staleFileSlice); err != nil {
log.Fatalln(err)
}
@@ -289,33 +289,13 @@
}
}
- // Fix up the source tree due to a repo bug where it doesn't remove
- // linkfiles that have been removed
- fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.bp")
- fixBadDanglingLink(buildCtx, "hardware/qcom/sdm710/Android.mk")
-
// Create a source finder.
f := build.NewSourceFinder(buildCtx, config)
defer f.Shutdown()
build.FindSources(buildCtx, config, f)
}
-func fixBadDanglingLink(ctx build.Context, name string) {
- _, err := os.Lstat(name)
- if err != nil {
- return
- }
- _, err = os.Stat(name)
- if os.IsNotExist(err) {
- err = os.Remove(name)
- if err != nil {
- ctx.Fatalf("Failed to remove dangling link %q: %v", name, err)
- }
- }
-}
-
func dumpVar(ctx build.Context, config build.Config, args []string) {
- logAndSymlinkSetup(ctx, config)
flags := flag.NewFlagSet("dumpvar", flag.ExitOnError)
flags.SetOutput(ctx.Writer)
@@ -368,7 +348,6 @@
}
func dumpVars(ctx build.Context, config build.Config, args []string) {
- logAndSymlinkSetup(ctx, config)
flags := flag.NewFlagSet("dumpvars", flag.ExitOnError)
flags.SetOutput(ctx.Writer)
@@ -548,7 +527,6 @@
}
func runMake(ctx build.Context, config build.Config, _ []string) {
- logAndSymlinkSetup(ctx, config)
logsDir := config.LogsDir()
if config.IsVerbose() {
writer := ctx.Writer
@@ -599,81 +577,6 @@
return nil, nil, fmt.Errorf("Command not found: %q\nDid you mean one of these: %q", args[1], listFlags())
}
-// For Bazel support, this moves files and directories from e.g. out/dist/$f to DIST_DIR/$f if necessary.
-func populateExternalDistDir(ctx build.Context, config build.Config) {
- // Make sure that internalDistDirPath and externalDistDirPath are both absolute paths, so we can compare them
- var err error
- var internalDistDirPath string
- var externalDistDirPath string
- if internalDistDirPath, err = filepath.Abs(config.DistDir()); err != nil {
- ctx.Fatalf("Unable to find absolute path of %s: %s", internalDistDirPath, err)
- }
- if externalDistDirPath, err = filepath.Abs(config.RealDistDir()); err != nil {
- ctx.Fatalf("Unable to find absolute path of %s: %s", externalDistDirPath, err)
- }
- if externalDistDirPath == internalDistDirPath {
- return
- }
-
- // Make sure the internal DIST_DIR actually exists before trying to read from it
- if _, err = os.Stat(internalDistDirPath); os.IsNotExist(err) {
- ctx.Println("Skipping Bazel dist dir migration - nothing to do!")
- return
- }
-
- // Make sure the external DIST_DIR actually exists before trying to write to it
- if err = os.MkdirAll(externalDistDirPath, 0755); err != nil {
- ctx.Fatalf("Unable to make directory %s: %s", externalDistDirPath, err)
- }
-
- ctx.Println("Populating external DIST_DIR...")
-
- populateExternalDistDirHelper(ctx, config, internalDistDirPath, externalDistDirPath)
-}
-
-func populateExternalDistDirHelper(ctx build.Context, config build.Config, internalDistDirPath string, externalDistDirPath string) {
- files, err := ioutil.ReadDir(internalDistDirPath)
- if err != nil {
- ctx.Fatalf("Can't read internal distdir %s: %s", internalDistDirPath, err)
- }
- for _, f := range files {
- internalFilePath := filepath.Join(internalDistDirPath, f.Name())
- externalFilePath := filepath.Join(externalDistDirPath, f.Name())
-
- if f.IsDir() {
- // Moving a directory - check if there is an existing directory to merge with
- externalLstat, err := os.Lstat(externalFilePath)
- if err != nil {
- if !os.IsNotExist(err) {
- ctx.Fatalf("Can't lstat external %s: %s", externalDistDirPath, err)
- }
- // Otherwise, if the error was os.IsNotExist, that's fine and we fall through to the rename at the bottom
- } else {
- if externalLstat.IsDir() {
- // Existing dir - try to merge the directories?
- populateExternalDistDirHelper(ctx, config, internalFilePath, externalFilePath)
- continue
- } else {
- // Existing file being replaced with a directory. Delete the existing file...
- if err := os.RemoveAll(externalFilePath); err != nil {
- ctx.Fatalf("Unable to remove existing %s: %s", externalFilePath, err)
- }
- }
- }
- } else {
- // Moving a file (not a dir) - delete any existing file or directory
- if err := os.RemoveAll(externalFilePath); err != nil {
- ctx.Fatalf("Unable to remove existing %s: %s", externalFilePath, err)
- }
- }
-
- // The actual move - do a rename instead of a copy in order to save disk space.
- if err := os.Rename(internalFilePath, externalFilePath); err != nil {
- ctx.Fatalf("Unable to rename %s -> %s due to error %s", internalFilePath, externalFilePath, err)
- }
- }
-}
-
func setMaxFiles(ctx build.Context) {
var limits syscall.Rlimit
@@ -684,9 +587,11 @@
}
ctx.Verbosef("Current file limits: %d soft, %d hard", limits.Cur, limits.Max)
- if limits.Cur == limits.Max {
- return
- }
+
+ // Go 1.21 modifies the file limit but restores the original when
+ // execing subprocesses if it hasn't be overridden. Call Setrlimit
+ // here even if it doesn't appear to be necessary so that the
+ // syscall package considers it set.
limits.Cur = limits.Max
err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &limits)
@@ -694,28 +599,3 @@
ctx.Println("Failed to increase file limit:", err)
}
}
-
-func finalizeBazelMetrics(ctx build.Context, config build.Config, args []string) {
- updateTotalRealTime(ctx, config, args)
-
- logsDir := config.LogsDir()
- logsPrefix := config.GetLogsPrefix()
- bazelMetricsFile := filepath.Join(logsDir, logsPrefix+"bazel_metrics.pb")
- bazelProfileFile := filepath.Join(logsDir, logsPrefix+"analyzed_bazel_profile.txt")
- build.ProcessBazelMetrics(bazelProfileFile, bazelMetricsFile, ctx, config)
-}
-func updateTotalRealTime(ctx build.Context, config build.Config, args []string) {
- soongMetricsFile := filepath.Join(config.LogsDir(), "soong_metrics")
-
- //read file into proto
- data, err := os.ReadFile(soongMetricsFile)
- if err != nil {
- ctx.Fatal(err)
- }
- met := ctx.ContextImpl.Metrics
-
- err = met.UpdateTotalRealTimeAndNonZeroExit(data, config.BazelExitCode())
- if err != nil {
- ctx.Fatal(err)
- }
-}
diff --git a/compliance/OWNERS b/compliance/OWNERS
deleted file mode 100644
index f52e201..0000000
--- a/compliance/OWNERS
+++ /dev/null
@@ -1,8 +0,0 @@
-# OSEP Build
-bbadour@google.com
-kanouche@google.com
-napier@google.com
-
-# Open Source Compliance Tools
-rtp@google.com
-austinyuan@google.com
diff --git a/dexpreopt/DEXPREOPT_IMPLEMENTATION.md b/dexpreopt/DEXPREOPT_IMPLEMENTATION.md
index c3a1730..1cb0add 100644
--- a/dexpreopt/DEXPREOPT_IMPLEMENTATION.md
+++ b/dexpreopt/DEXPREOPT_IMPLEMENTATION.md
@@ -237,22 +237,22 @@
app.
-[make/core/dex_preopt.mk]: https://cs.android.com/android/platform/superproject/+/master:build/make/core/dex_preopt.mk
-[make/core/dex_preopt_config.mk]: https://cs.android.com/android/platform/superproject/+/master:build/make/core/dex_preopt_config.mk
-[make/core/dex_preopt_config_merger.py]: https://cs.android.com/android/platform/superproject/+/master:build/make/core/dex_preopt_config_merger.py
-[make/core/dex_preopt_odex_install.mk]: https://cs.android.com/android/platform/superproject/+/master:build/make/core/dex_preopt_odex_install.mk
-[soong/dexpreopt]: https://cs.android.com/android/platform/superproject/+/master:build/soong/dexpreopt
-[soong/dexpreopt/class_loader_context.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/dexpreopt/class_loader_context.go
-[soong/dexpreopt/config.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/dexpreopt/config.go
-[soong/dexpreopt/dexpreopt.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/dexpreopt/dexpreopt.go
-[soong/java]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java
-[soong/java/app.go:deps]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/app.go?q=%22func%20\(u%20*usesLibrary\)%20deps%22
-[soong/java/app.go:verifyUsesLibraries]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/app.go?q=%22func%20\(u%20*usesLibrary\)%20verifyUsesLibraries%22
-[soong/java/bootclasspath_fragment.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/bootclasspath_fragment.go
-[soong/java/dexpreopt.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/dexpreopt.go
-[soong/java/dexpreopt_bootjars.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/dexpreopt_bootjars.go
-[soong/java/dexpreopt_config.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/dexpreopt_config.go
-[soong/java/java.go:addCLCFromDep]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/java.go?q=%22func%20addCLCfromDep%22
-[soong/java/platform_bootclasspath.go]: https://cs.android.com/android/platform/superproject/+/master:build/soong/java/platform_bootclasspath.go
-[soong/scripts/construct_context.py]: https://cs.android.com/android/platform/superproject/+/master:build/soong/scripts/construct_context.py
-[soong/scripts/manifest_check.py]: https://cs.android.com/android/platform/superproject/+/master:build/soong/scripts/manifest_check.py
+[make/core/dex_preopt.mk]: https://cs.android.com/android/platform/superproject/+/main:build/make/core/dex_preopt.mk
+[make/core/dex_preopt_config.mk]: https://cs.android.com/android/platform/superproject/+/main:build/make/core/dex_preopt_config.mk
+[make/core/dex_preopt_config_merger.py]: https://cs.android.com/android/platform/superproject/+/main:build/make/core/dex_preopt_config_merger.py
+[make/core/dex_preopt_odex_install.mk]: https://cs.android.com/android/platform/superproject/+/main:build/make/core/dex_preopt_odex_install.mk
+[soong/dexpreopt]: https://cs.android.com/android/platform/superproject/+/main:build/soong/dexpreopt
+[soong/dexpreopt/class_loader_context.go]: https://cs.android.com/android/platform/superproject/+/main:build/soong/dexpreopt/class_loader_context.go
+[soong/dexpreopt/config.go]: https://cs.android.com/android/platform/superproject/+/main:build/soong/dexpreopt/config.go
+[soong/dexpreopt/dexpreopt.go]: https://cs.android.com/android/platform/superproject/+/main:build/soong/dexpreopt/dexpreopt.go
+[soong/java]: https://cs.android.com/android/platform/superproject/+/main:build/soong/java
+[soong/java/app.go:deps]: https://cs.android.com/android/platform/superproject/+/main:build/soong/java/app.go?q=%22func%20\(u%20*usesLibrary\)%20deps%22
+[soong/java/app.go:verifyUsesLibraries]: https://cs.android.com/android/platform/superproject/+/main:build/soong/java/app.go?q=%22func%20\(u%20*usesLibrary\)%20verifyUsesLibraries%22
+[soong/java/bootclasspath_fragment.go]: https://cs.android.com/android/platform/superproject/+/main:build/soong/java/bootclasspath_fragment.go
+[soong/java/dexpreopt.go]: https://cs.android.com/android/platform/superproject/+/main:build/soong/java/dexpreopt.go
+[soong/java/dexpreopt_bootjars.go]: https://cs.android.com/android/platform/superproject/+/main:build/soong/java/dexpreopt_bootjars.go
+[soong/java/dexpreopt_config.go]: https://cs.android.com/android/platform/superproject/+/main:build/soong/java/dexpreopt_config.go
+[soong/java/java.go:addCLCFromDep]: https://cs.android.com/android/platform/superproject/+/main:build/soong/java/java.go?q=%22func%20addCLCfromDep%22
+[soong/java/platform_bootclasspath.go]: https://cs.android.com/android/platform/superproject/+/main:build/soong/java/platform_bootclasspath.go
+[soong/scripts/construct_context.py]: https://cs.android.com/android/platform/superproject/+/main:build/soong/scripts/construct_context.py
+[soong/scripts/manifest_check.py]: https://cs.android.com/android/platform/superproject/+/main:build/soong/scripts/manifest_check.py
diff --git a/dexpreopt/config.go b/dexpreopt/config.go
index ba41f4a..fe6317c 100644
--- a/dexpreopt/config.go
+++ b/dexpreopt/config.go
@@ -32,7 +32,7 @@
DisablePreoptBootImages bool // disable prepot for boot images
DisablePreoptModules []string // modules with preopt disabled by product-specific config
- OnlyPreoptBootImageAndSystemServer bool // only preopt jars in the boot image or system server
+ OnlyPreoptArtBootImage bool // only preopt jars in the ART boot image
PreoptWithUpdatableBcp bool // If updatable boot jars are included in dexpreopt or not.
@@ -98,7 +98,9 @@
// measure, as it masks real errors and affects performance.
RelaxUsesLibraryCheck bool
- EnableUffdGc bool // preopt with the assumption that userfaultfd GC will be used on device.
+ // "true" to force preopt with CMC GC (a.k.a., UFFD GC); "false" to force preopt with CC GC;
+ // "default" to determine the GC type based on the kernel version file.
+ EnableUffdGc string
}
var allPlatformSystemServerJarsKey = android.NewOnceKey("allPlatformSystemServerJars")
@@ -154,6 +156,7 @@
Zip2zip android.Path
ManifestCheck android.Path
ConstructContext android.Path
+ UffdGcFlag android.WritablePath
}
type ModuleConfig struct {
@@ -184,8 +187,6 @@
PreoptBootClassPathDexFiles android.Paths // file paths of boot class path files
PreoptBootClassPathDexLocations []string // virtual locations of boot class path files
- PreoptExtractedApk bool // Overrides OnlyPreoptModules
-
NoCreateAppImage bool
ForceCreateAppImage bool
@@ -539,6 +540,7 @@
Zip2zip: ctx.Config().HostToolPath(ctx, "zip2zip"),
ManifestCheck: ctx.Config().HostToolPath(ctx, "manifest_check"),
ConstructContext: ctx.Config().HostToolPath(ctx, "construct_context"),
+ UffdGcFlag: getUffdGcFlagPath(ctx),
}
}
@@ -590,6 +592,7 @@
Zip2zip string
ManifestCheck string
ConstructContext string
+ UffdGcFlag string
}
// ParseGlobalSoongConfig parses the given data assumed to be read from the
@@ -611,6 +614,7 @@
Zip2zip: constructPath(ctx, jc.Zip2zip),
ManifestCheck: constructPath(ctx, jc.ManifestCheck),
ConstructContext: constructPath(ctx, jc.ConstructContext),
+ UffdGcFlag: constructWritablePath(ctx, jc.UffdGcFlag),
}
return config, nil
@@ -635,12 +639,15 @@
}
func (s *globalSoongConfigSingleton) GenerateBuildActions(ctx android.SingletonContext) {
- checkBootJarsConfigConsistency(ctx, GetGlobalConfig(ctx), ctx.Config())
+ global := GetGlobalConfig(ctx)
+ checkBootJarsConfigConsistency(ctx, global, ctx.Config())
- if GetGlobalConfig(ctx).DisablePreopt {
+ if global.DisablePreopt {
return
}
+ buildUffdGcFlag(ctx, global)
+
config := GetCachedGlobalSoongConfig(ctx)
if config == nil {
// No module has enabled dexpreopting, so we assume there will be no calls
@@ -656,6 +663,7 @@
Zip2zip: config.Zip2zip.String(),
ManifestCheck: config.ManifestCheck.String(),
ConstructContext: config.ConstructContext.String(),
+ UffdGcFlag: config.UffdGcFlag.String(),
}
data, err := json.Marshal(jc)
@@ -686,54 +694,77 @@
config.Zip2zip.String(),
config.ManifestCheck.String(),
config.ConstructContext.String(),
+ config.UffdGcFlag.String(),
}, " "))
}
+func buildUffdGcFlag(ctx android.BuilderContext, global *GlobalConfig) {
+ uffdGcFlag := getUffdGcFlagPath(ctx)
+
+ if global.EnableUffdGc == "true" {
+ android.WriteFileRuleVerbatim(ctx, uffdGcFlag, "--runtime-arg -Xgc:CMC")
+ } else if global.EnableUffdGc == "false" {
+ android.WriteFileRuleVerbatim(ctx, uffdGcFlag, "")
+ } else if global.EnableUffdGc == "default" {
+ // Generated by `build/make/core/Makefile`.
+ kernelVersionFile := android.PathForOutput(ctx, "dexpreopt/kernel_version_for_uffd_gc.txt")
+ // Determine the UFFD GC flag by the kernel version file.
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Command().
+ Tool(ctx.Config().HostToolPath(ctx, "construct_uffd_gc_flag")).
+ Input(kernelVersionFile).
+ Output(uffdGcFlag)
+ rule.Restat().Build("dexpreopt_uffd_gc_flag", "dexpreopt_uffd_gc_flag")
+ } else {
+ panic(fmt.Sprintf("Unknown value of PRODUCT_ENABLE_UFFD_GC: %s", global.EnableUffdGc))
+ }
+}
+
func GlobalConfigForTests(ctx android.PathContext) *GlobalConfig {
return &GlobalConfig{
- DisablePreopt: false,
- DisablePreoptModules: nil,
- OnlyPreoptBootImageAndSystemServer: false,
- HasSystemOther: false,
- PatternsOnSystemOther: nil,
- DisableGenerateProfile: false,
- ProfileDir: "",
- BootJars: android.EmptyConfiguredJarList(),
- ApexBootJars: android.EmptyConfiguredJarList(),
- ArtApexJars: android.EmptyConfiguredJarList(),
- TestOnlyArtBootImageJars: android.EmptyConfiguredJarList(),
- SystemServerJars: android.EmptyConfiguredJarList(),
- SystemServerApps: nil,
- ApexSystemServerJars: android.EmptyConfiguredJarList(),
- StandaloneSystemServerJars: android.EmptyConfiguredJarList(),
- ApexStandaloneSystemServerJars: android.EmptyConfiguredJarList(),
- SpeedApps: nil,
- PreoptFlags: nil,
- DefaultCompilerFilter: "",
- SystemServerCompilerFilter: "",
- GenerateDMFiles: false,
- NoDebugInfo: false,
- DontResolveStartupStrings: false,
- AlwaysSystemServerDebugInfo: false,
- NeverSystemServerDebugInfo: false,
- AlwaysOtherDebugInfo: false,
- NeverOtherDebugInfo: false,
- IsEng: false,
- SanitizeLite: false,
- DefaultAppImages: false,
- Dex2oatXmx: "",
- Dex2oatXms: "",
- EmptyDirectory: "empty_dir",
- CpuVariant: nil,
- InstructionSetFeatures: nil,
- BootImageProfiles: nil,
- BootFlags: "",
- Dex2oatImageXmx: "",
- Dex2oatImageXms: "",
+ DisablePreopt: false,
+ DisablePreoptModules: nil,
+ OnlyPreoptArtBootImage: false,
+ HasSystemOther: false,
+ PatternsOnSystemOther: nil,
+ DisableGenerateProfile: false,
+ ProfileDir: "",
+ BootJars: android.EmptyConfiguredJarList(),
+ ApexBootJars: android.EmptyConfiguredJarList(),
+ ArtApexJars: android.EmptyConfiguredJarList(),
+ TestOnlyArtBootImageJars: android.EmptyConfiguredJarList(),
+ SystemServerJars: android.EmptyConfiguredJarList(),
+ SystemServerApps: nil,
+ ApexSystemServerJars: android.EmptyConfiguredJarList(),
+ StandaloneSystemServerJars: android.EmptyConfiguredJarList(),
+ ApexStandaloneSystemServerJars: android.EmptyConfiguredJarList(),
+ SpeedApps: nil,
+ PreoptFlags: nil,
+ DefaultCompilerFilter: "",
+ SystemServerCompilerFilter: "",
+ GenerateDMFiles: false,
+ NoDebugInfo: false,
+ DontResolveStartupStrings: false,
+ AlwaysSystemServerDebugInfo: false,
+ NeverSystemServerDebugInfo: false,
+ AlwaysOtherDebugInfo: false,
+ NeverOtherDebugInfo: false,
+ IsEng: false,
+ SanitizeLite: false,
+ DefaultAppImages: false,
+ Dex2oatXmx: "",
+ Dex2oatXms: "",
+ EmptyDirectory: "empty_dir",
+ CpuVariant: nil,
+ InstructionSetFeatures: nil,
+ BootImageProfiles: nil,
+ BootFlags: "",
+ Dex2oatImageXmx: "",
+ Dex2oatImageXms: "",
}
}
-func globalSoongConfigForTests() *GlobalSoongConfig {
+func globalSoongConfigForTests(ctx android.BuilderContext) *GlobalSoongConfig {
return &GlobalSoongConfig{
Profman: android.PathForTesting("profman"),
Dex2oat: android.PathForTesting("dex2oat"),
@@ -742,5 +773,19 @@
Zip2zip: android.PathForTesting("zip2zip"),
ManifestCheck: android.PathForTesting("manifest_check"),
ConstructContext: android.PathForTesting("construct_context"),
+ UffdGcFlag: android.PathForOutput(ctx, "dexpreopt_test", "uffd_gc_flag.txt"),
}
}
+
+func GetDexpreoptDirName(ctx android.PathContext) string {
+ prefix := "dexpreopt_"
+ targets := ctx.Config().Targets[android.Android]
+ if len(targets) > 0 {
+ return prefix + targets[0].Arch.ArchType.String()
+ }
+ return prefix + "unknown_target"
+}
+
+func getUffdGcFlagPath(ctx android.PathContext) android.WritablePath {
+ return android.PathForOutput(ctx, "dexpreopt/uffd_gc_flag.txt")
+}
diff --git a/dexpreopt/dexpreopt.go b/dexpreopt/dexpreopt.go
index 29ae188..04bc61d 100644
--- a/dexpreopt/dexpreopt.go
+++ b/dexpreopt/dexpreopt.go
@@ -124,12 +124,7 @@
return true
}
- // If OnlyPreoptBootImageAndSystemServer=true and module is not in boot class path skip
- // Also preopt system server jars since selinux prevents system server from loading anything from
- // /data. If we don't do this they will need to be extracted which is not favorable for RAM usage
- // or performance. If PreoptExtractedApk is true, we ignore the only preopt boot image options.
- if global.OnlyPreoptBootImageAndSystemServer && !global.BootJars.ContainsJar(module.Name) &&
- !global.AllSystemServerJars(ctx).ContainsJar(module.Name) && !module.PreoptExtractedApk {
+ if global.OnlyPreoptArtBootImage {
return true
}
@@ -395,7 +390,8 @@
Flag("--generate-build-id").
Flag("--abort-on-hard-verifier-error").
Flag("--force-determinism").
- FlagWithArg("--no-inline-from=", "core-oj.jar")
+ FlagWithArg("--no-inline-from=", "core-oj.jar").
+ Text("$(cat").Input(globalSoong.UffdGcFlag).Text(")")
var preoptFlags []string
if len(module.PreoptFlags) > 0 {
@@ -511,10 +507,6 @@
cmd.FlagWithInput("--profile-file=", profile)
}
- if global.EnableUffdGc {
- cmd.Flag("--runtime-arg").Flag("-Xgc:CMC")
- }
-
rule.Install(odexPath, odexInstallPath)
rule.Install(vdexPath, vdexInstallPath)
}
diff --git a/dexpreopt/dexpreopt_test.go b/dexpreopt/dexpreopt_test.go
index 2b19c9d..7071f3e 100644
--- a/dexpreopt/dexpreopt_test.go
+++ b/dexpreopt/dexpreopt_test.go
@@ -87,7 +87,6 @@
DexPreoptImageLocationsOnHost: []string{},
PreoptBootClassPathDexFiles: nil,
PreoptBootClassPathDexLocations: nil,
- PreoptExtractedApk: false,
NoCreateAppImage: false,
ForceCreateAppImage: false,
PresignedPrebuilt: false,
@@ -97,7 +96,7 @@
func TestDexPreopt(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
- globalSoong := globalSoongConfigForTests()
+ globalSoong := globalSoongConfigForTests(ctx)
global := GlobalConfigForTests(ctx)
module := testSystemModuleConfig(ctx, "test")
productPackages := android.PathForTesting("product_packages.txt")
@@ -115,12 +114,15 @@
if rule.Installs().String() != wantInstalls.String() {
t.Errorf("\nwant installs:\n %v\ngot:\n %v", wantInstalls, rule.Installs())
}
+
+ android.AssertStringListContains(t, "", rule.Inputs().RelativeToTop().Strings(),
+ "out/soong/dexpreopt_test/uffd_gc_flag.txt")
}
func TestDexPreoptSystemOther(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
- globalSoong := globalSoongConfigForTests()
+ globalSoong := globalSoongConfigForTests(ctx)
global := GlobalConfigForTests(ctx)
systemModule := testSystemModuleConfig(ctx, "Stest")
systemProductModule := testSystemProductModuleConfig(ctx, "SPtest")
@@ -181,7 +183,7 @@
func TestDexPreoptApexSystemServerJars(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
- globalSoong := globalSoongConfigForTests()
+ globalSoong := globalSoongConfigForTests(ctx)
global := GlobalConfigForTests(ctx)
module := testApexModuleConfig(ctx, "service-A", "com.android.apex1")
productPackages := android.PathForTesting("product_packages.txt")
@@ -205,7 +207,7 @@
func TestDexPreoptStandaloneSystemServerJars(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
- globalSoong := globalSoongConfigForTests()
+ globalSoong := globalSoongConfigForTests(ctx)
global := GlobalConfigForTests(ctx)
module := testPlatformSystemServerModuleConfig(ctx, "service-A")
productPackages := android.PathForTesting("product_packages.txt")
@@ -229,7 +231,7 @@
func TestDexPreoptSystemExtSystemServerJars(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
- globalSoong := globalSoongConfigForTests()
+ globalSoong := globalSoongConfigForTests(ctx)
global := GlobalConfigForTests(ctx)
module := testSystemExtSystemServerModuleConfig(ctx, "service-A")
productPackages := android.PathForTesting("product_packages.txt")
@@ -253,7 +255,7 @@
func TestDexPreoptApexStandaloneSystemServerJars(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
- globalSoong := globalSoongConfigForTests()
+ globalSoong := globalSoongConfigForTests(ctx)
global := GlobalConfigForTests(ctx)
module := testApexModuleConfig(ctx, "service-A", "com.android.apex1")
productPackages := android.PathForTesting("product_packages.txt")
@@ -277,7 +279,7 @@
func TestDexPreoptProfile(t *testing.T) {
config := android.TestConfig("out", nil, "", nil)
ctx := android.BuilderContextForTesting(config)
- globalSoong := globalSoongConfigForTests()
+ globalSoong := globalSoongConfigForTests(ctx)
global := GlobalConfigForTests(ctx)
module := testSystemModuleConfig(ctx, "test")
productPackages := android.PathForTesting("product_packages.txt")
@@ -317,3 +319,55 @@
after := fmt.Sprintf("%v", parsed)
android.AssertStringEquals(t, "The result must be the same as the original after marshalling and unmarshalling it.", before, after)
}
+
+func TestUffdGcFlagForce(t *testing.T) {
+ for _, enableUffdGc := range []string{"true", "false"} {
+ t.Run(enableUffdGc, func(t *testing.T) {
+ preparers := android.GroupFixturePreparers(
+ PrepareForTestWithFakeDex2oatd,
+ PrepareForTestWithDexpreoptConfig,
+ FixtureSetEnableUffdGc(enableUffdGc),
+ )
+
+ result := preparers.RunTest(t)
+ ctx := result.TestContext
+
+ ctx.SingletonForTests("dexpreopt-soong-config").Output("out/soong/dexpreopt/uffd_gc_flag.txt")
+ })
+ }
+}
+
+func TestUffdGcFlagDefault(t *testing.T) {
+ preparers := android.GroupFixturePreparers(
+ PrepareForTestWithFakeDex2oatd,
+ PrepareForTestWithDexpreoptConfig,
+ FixtureSetEnableUffdGc("default"),
+ )
+
+ result := preparers.RunTest(t)
+ ctx := result.TestContext
+ config := ctx.Config()
+
+ rule := ctx.SingletonForTests("dexpreopt-soong-config").Rule("dexpreopt_uffd_gc_flag")
+
+ android.AssertStringDoesContain(t, "", rule.RuleParams.Command, "construct_uffd_gc_flag")
+ android.AssertStringPathsRelativeToTopEquals(t, "", config, []string{
+ "out/soong/dexpreopt/uffd_gc_flag.txt",
+ }, rule.AllOutputs())
+ android.AssertPathsRelativeToTopEquals(t, "", []string{
+ "out/soong/dexpreopt/kernel_version_for_uffd_gc.txt",
+ }, rule.Implicits)
+}
+
+func TestUffdGcFlagBogus(t *testing.T) {
+ preparers := android.GroupFixturePreparers(
+ PrepareForTestWithFakeDex2oatd,
+ PrepareForTestWithDexpreoptConfig,
+ FixtureSetEnableUffdGc("bogus"),
+ )
+
+ preparers.
+ ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
+ "Unknown value of PRODUCT_ENABLE_UFFD_GC: bogus")).
+ RunTest(t)
+}
diff --git a/dexpreopt/testing.go b/dexpreopt/testing.go
index 147a562..b1fbef5 100644
--- a/dexpreopt/testing.go
+++ b/dexpreopt/testing.go
@@ -88,6 +88,15 @@
FixtureModifyGlobalConfig(func(android.PathContext, *GlobalConfig) {}),
)
+var PrepareForTestWithDexpreoptConfig = android.GroupFixturePreparers(
+ android.PrepareForTestWithAndroidBuildComponents,
+ android.FixtureModifyContext(func(ctx *android.TestContext) {
+ ctx.RegisterParallelSingletonType("dexpreopt-soong-config", func() android.Singleton {
+ return &globalSoongConfigSingleton{}
+ })
+ }),
+)
+
// FixtureModifyGlobalConfig enables dexpreopt (unless modified by the mutator) and modifies the
// configuration.
func FixtureModifyGlobalConfig(configModifier func(ctx android.PathContext, dexpreoptConfig *GlobalConfig)) android.FixturePreparer {
@@ -195,3 +204,10 @@
dexpreoptConfig.DisablePreopt = disable
})
}
+
+// FixtureSetEnableUffdGc sets the EnableUffdGc property in the global config.
+func FixtureSetEnableUffdGc(value string) android.FixturePreparer {
+ return FixtureModifyGlobalConfig(func(_ android.PathContext, dexpreoptConfig *GlobalConfig) {
+ dexpreoptConfig.EnableUffdGc = value
+ })
+}
diff --git a/docs/best_practices.md b/docs/best_practices.md
index bc760b8..48ed996 100644
--- a/docs/best_practices.md
+++ b/docs/best_practices.md
@@ -285,6 +285,6 @@
and will require ongoing maintenance as the build system is changed; so
plugins should be used only when absolutely required.
-See [art/build/art.go](https://android.googlesource.com/platform/art/+/master/build/art.go)
-or [external/llvm/soong/llvm.go](https://android.googlesource.com/platform/external/llvm/+/master/soong/llvm.go)
+See [art/build/art.go](https://android.googlesource.com/platform/art/+/main/build/art.go)
+or [external/llvm/soong/llvm.go](https://android.googlesource.com/platform/external/llvm/+/main/soong/llvm.go)
for examples of more complex conditionals on product variables or environment variables.
diff --git a/docs/clion.md b/docs/clion.md
index d6ae19a..8e2c597 100644
--- a/docs/clion.md
+++ b/docs/clion.md
@@ -3,6 +3,10 @@
Soong can generate CLion projects. This is intended for source code editing
only. Build should still be done via make/m/mm(a)/mmm(a).
+Note: alternatively, you can use
+[aidegen to generate a Clion or VSCode project](https://android.googlesource.com/platform/tools/asuite/+/refs/heads/main/aidegen/README.md)
+with a single command, using the `-i c` flag.
+
CMakeLists.txt project file generation is enabled via environment variable:
```bash
diff --git a/docs/map_files.md b/docs/map_files.md
index 35e8cbb..e1ddefc 100644
--- a/docs/map_files.md
+++ b/docs/map_files.md
@@ -5,8 +5,8 @@
semantically meaningful to [gen_stub_libs.py]. For an example of a map file, see
[libc.map.txt].
-[gen_stub_libs.py]: https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/gen_stub_libs.py
-[libc.map.txt]: https://cs.android.com/android/platform/superproject/+/master:bionic/libc/libc.map.txt
+[gen_stub_libs.py]: https://cs.android.com/android/platform/superproject/+/main:build/soong/cc/gen_stub_libs.py
+[libc.map.txt]: https://cs.android.com/android/platform/superproject/+/main:bionic/libc/libc.map.txt
[linker version scripts]: https://www.gnu.org/software/gnulib/manual/html_node/LD-Version-Scripts.html
## Basic format
@@ -134,6 +134,9 @@
Historically this annotation was spelled `vndk`, but it has always meant LL-NDK.
+When an llndk API is deprecated, the `llndk` tag is dropped and
+`llndk-deprecate=<V>` is added.
+
### platform-only
Indicates that the version or symbol is public in the implementation library but
diff --git a/docs/rbe.md b/docs/rbe.md
index cfe86d7..be60c83 100644
--- a/docs/rbe.md
+++ b/docs/rbe.md
@@ -11,7 +11,7 @@
To enable RBE, you need to set several environment variables before triggering
the build. You can set them through a
-[environment variables config file](https://android.googlesource.com/platform/build/soong/+/master/README.md#environment-variables-config-file).
+[environment variables config file](https://android.googlesource.com/platform/build/soong/+/main/README.md#environment-variables-config-file).
As an example, [build/soong/docs/rbe.json](rbe.json) is a config that enables
RBE in the build. Once the config file is created, you need to let Soong load
the config file by specifying `ANDROID_BUILD_ENVIRONMENT_CONFIG_DIR` environment
diff --git a/docs/tidy.md b/docs/tidy.md
index 2eb8234..ae0ca93 100644
--- a/docs/tidy.md
+++ b/docs/tidy.md
@@ -24,7 +24,7 @@
```
The default global clang-tidy checks and flags are defined in
-[build/soong/cc/config/tidy.go](https://android.googlesource.com/platform/build/soong/+/refs/heads/master/cc/config/tidy.go).
+[build/soong/cc/config/tidy.go](https://android.googlesource.com/platform/build/soong/+/refs/heads/main/cc/config/tidy.go).
## Module clang-tidy properties
@@ -34,7 +34,7 @@
### `tidy`, `tidy_checks`, and `ALLOW_LOCAL_TIDY_TRUE`
For example, in
-[system/bpf/Android.bp](https://android.googlesource.com/platform/system/bpf/+/refs/heads/master/Android.bp),
+[system/bpf/Android.bp](https://android.googlesource.com/platform/system/bpf/+/refs/heads/main/Android.bp),
clang-tidy is enabled explicitly and with a different check list:
```
cc_defaults {
@@ -69,7 +69,7 @@
Some modules might want to disable clang-tidy even when
environment variable `WITH_TIDY=1` is set.
Examples can be found in
-[system/netd/tests/Android.bp](https://android.googlesource.com/platform/system/netd/+/refs/heads/master/tests/Android.bp)
+[system/netd/tests/Android.bp](https://android.googlesource.com/platform/system/netd/+/refs/heads/main/tests/Android.bp)
```
cc_test {
name: "netd_integration_test",
@@ -78,7 +78,7 @@
tidy: false, // cuts test build time by almost 1 minute
```
and in
-[bionic/tests/Android.bp](https://android.googlesource.com/platform/bionic/+/refs/heads/master/tests/Android.bp).
+[bionic/tests/Android.bp](https://android.googlesource.com/platform/bionic/+/refs/heads/main/tests/Android.bp).
```
cc_test_library {
name: "fortify_disabled_for_tidy",
@@ -97,7 +97,7 @@
If a C/C++ module wants to be free of certain clang-tidy warnings,
it can chose those checks to be treated as errors.
For example
-[system/core/libsysutils/Android.bp](https://android.googlesource.com/platform/system/core/+/refs/heads/master/libsysutils/Android.bp)
+[system/core/libsysutils/Android.bp](https://android.googlesource.com/platform/system/core/+/refs/heads/main/libsysutils/Android.bp)
has enabled clang-tidy explicitly, selected its own tidy checks,
and set three groups of tidy checks as errors:
```
@@ -130,7 +130,7 @@
Some other tidy flags examples are `-format-style=` and `-header-filter=`
For example, in
-[art/odrefresh/Android.bp](https://android.googlesource.com/platform/art/+/refs/heads/master/odrefresh/Android.bp),
+[art/odrefresh/Android.bp](https://android.googlesource.com/platform/art/+/refs/heads/main/odrefresh/Android.bp),
we found
```
cc_defaults {
diff --git a/etc/prebuilt_etc.go b/etc/prebuilt_etc.go
index c48bafa..7642378 100644
--- a/etc/prebuilt_etc.go
+++ b/etc/prebuilt_etc.go
@@ -31,16 +31,12 @@
"encoding/json"
"fmt"
"path/filepath"
- "reflect"
"strings"
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel"
- "android/soong/bazel/cquery"
"android/soong/snapshot"
- "android/soong/ui/metrics/bp2build_metrics_proto"
)
var pctx = android.NewPackageContext("android/soong/etc")
@@ -65,6 +61,7 @@
ctx.RegisterModuleType("prebuilt_firmware", PrebuiltFirmwareFactory)
ctx.RegisterModuleType("prebuilt_dsp", PrebuiltDSPFactory)
ctx.RegisterModuleType("prebuilt_rfsa", PrebuiltRFSAFactory)
+ ctx.RegisterModuleType("prebuilt_renderscript_bitcode", PrebuiltRenderScriptBitcodeFactory)
ctx.RegisterModuleType("prebuilt_defaults", defaultsFactory)
@@ -138,7 +135,6 @@
type PrebuiltEtc struct {
android.ModuleBase
android.DefaultableModuleBase
- android.BazelModuleBase
snapshot.VendorSnapshotModuleInterface
snapshot.RecoverySnapshotModuleInterface
@@ -149,12 +145,19 @@
sourceFilePath android.Path
outputFilePath android.OutputPath
// The base install location, e.g. "etc" for prebuilt_etc, "usr/share" for prebuilt_usr_share.
- installDirBase string
+ installDirBase string
+ installDirBase64 string
+ installAvoidMultilibConflict bool
// The base install location when soc_specific property is set to true, e.g. "firmware" for
// prebuilt_firmware.
socInstallDirBase string
installDirPath android.InstallPath
additionalDependencies *android.Paths
+
+ makeClass string
+
+ // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo
+ mergedAconfigFiles map[string]android.Paths
}
type Defaults struct {
@@ -345,9 +348,16 @@
// If soc install dir was specified and SOC specific is set, set the installDirPath to the
// specified socInstallDirBase.
installBaseDir := p.installDirBase
+ if p.Target().Arch.ArchType.Multilib == "lib64" && p.installDirBase64 != "" {
+ installBaseDir = p.installDirBase64
+ }
if p.SocSpecific() && p.socInstallDirBase != "" {
installBaseDir = p.socInstallDirBase
}
+ if p.installAvoidMultilibConflict && !ctx.Host() && ctx.Config().HasMultilibConflict(ctx.Arch().ArchType) {
+ installBaseDir = filepath.Join(installBaseDir, ctx.Arch().ArchType.String())
+ }
+
p.installDirPath = android.PathForModuleInstall(ctx, installBaseDir, p.SubDir())
// Call InstallFile even when uninstallable to make the module included in the package
@@ -358,6 +368,7 @@
symlinks: p.properties.Symlinks,
}
p.addInstallRules(ctx, ip)
+ android.CollectDependencyAconfigFiles(ctx, &p.mergedAconfigFiles)
}
type installProperties struct {
@@ -404,8 +415,14 @@
if p.InRecovery() && !p.onlyInRecovery() {
nameSuffix = ".recovery"
}
+
+ class := p.makeClass
+ if class == "" {
+ class = "ETC"
+ }
+
return []android.AndroidMkEntries{android.AndroidMkEntries{
- Class: "ETC",
+ Class: class,
SubName: nameSuffix,
OutputFile: android.OptionalPathForPath(p.outputFilePath),
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
@@ -420,11 +437,16 @@
if p.additionalDependencies != nil {
entries.AddStrings("LOCAL_ADDITIONAL_DEPENDENCIES", p.additionalDependencies.Strings()...)
}
+ android.SetAconfigFileMkEntries(p.AndroidModuleBase(), entries, p.mergedAconfigFiles)
},
},
}}
}
+func (p *PrebuiltEtc) AndroidModuleBase() *android.ModuleBase {
+ return &p.ModuleBase
+}
+
func InitPrebuiltEtcModule(p *PrebuiltEtc, dirBase string) {
p.installDirBase = dirBase
p.AddProperties(&p.properties)
@@ -444,7 +466,6 @@
// This module is device-only
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
android.InitDefaultableModule(module)
- android.InitBazelModule(module)
return module
}
@@ -474,7 +495,6 @@
// This module is host-only
android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
- android.InitBazelModule(module)
return module
}
@@ -485,7 +505,6 @@
InitPrebuiltEtcModule(module, "cacerts")
// This module is device-only
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
- android.InitBazelModule(module)
return module
}
@@ -519,7 +538,6 @@
// This module is device-only
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
android.InitDefaultableModule(module)
- android.InitBazelModule(module)
return module
}
@@ -571,6 +589,19 @@
return module
}
+// prebuilt_renderscript_bitcode installs a *.bc file into /system/lib or /system/lib64.
+func PrebuiltRenderScriptBitcodeFactory() android.Module {
+ module := &PrebuiltEtc{}
+ module.makeClass = "RENDERSCRIPT_BITCODE"
+ module.installDirBase64 = "lib64"
+ module.installAvoidMultilibConflict = true
+ InitPrebuiltEtcModule(module, "lib")
+ // This module is device-only
+ android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibBoth)
+ android.InitDefaultableModule(module)
+ return module
+}
+
// prebuilt_rfsa installs a firmware file that will be available through Qualcomm's RFSA
// to the <partition>/lib/rfsa directory.
func PrebuiltRFSAFactory() android.Module {
@@ -698,150 +729,3 @@
return snapshot.SnapshotPaths{OutputFiles: snapshotOutputs, NoticeFiles: snapshotNotices}
}
-
-// For Bazel / bp2build
-
-type bazelPrebuiltFileAttributes struct {
- Src bazel.LabelAttribute
- Filename bazel.LabelAttribute
- Dir string
- Installable bazel.BoolAttribute
- Filename_from_src bazel.BoolAttribute
-}
-
-// Bp2buildHelper returns a bazelPrebuiltFileAttributes used for the conversion
-// of prebuilt_* modules. bazelPrebuiltFileAttributes has the common attributes
-// used by both prebuilt_etc_xml and other prebuilt_* moodules
-func (module *PrebuiltEtc) Bp2buildHelper(ctx android.TopDownMutatorContext) (*bazelPrebuiltFileAttributes, bool) {
- var src bazel.LabelAttribute
- for axis, configToProps := range module.GetArchVariantProperties(ctx, &prebuiltEtcProperties{}) {
- for config, p := range configToProps {
- props, ok := p.(*prebuiltEtcProperties)
- if !ok {
- continue
- }
- if props.Src != nil {
- srcStr := proptools.String(props.Src)
- if srcStr == ctx.ModuleName() {
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "src == name")
- return &bazelPrebuiltFileAttributes{}, false
- }
- label := android.BazelLabelForModuleSrcSingle(ctx, srcStr)
- src.SetSelectValue(axis, config, label)
- }
- }
-
- for propName, productConfigProps := range android.ProductVariableProperties(ctx, ctx.Module()) {
- for configProp, propVal := range productConfigProps {
- if propName == "Src" {
- props, ok := propVal.(*string)
- if !ok {
- ctx.PropertyErrorf(" Expected Property to have type string, but was %s\n", reflect.TypeOf(propVal).String())
- continue
- }
- if props != nil {
- label := android.BazelLabelForModuleSrcSingle(ctx, *props)
- src.SetSelectValue(configProp.ConfigurationAxis(), configProp.SelectKey(), label)
- }
- }
- }
- }
- }
-
- var filename string
- var filenameFromSrc bool
- moduleProps := module.properties
-
- if moduleProps.Filename != nil && *moduleProps.Filename != "" {
- filename = *moduleProps.Filename
- } else if moduleProps.Filename_from_src != nil && *moduleProps.Filename_from_src {
- if moduleProps.Src != nil {
- filename = *moduleProps.Src
- }
- filenameFromSrc = true
- } else {
- filename = ctx.ModuleName()
- }
-
- var dir = module.installDirBase
- if subDir := module.subdirProperties.Sub_dir; subDir != nil {
- dir = dir + "/" + *subDir
- }
-
- var installable bazel.BoolAttribute
- if install := module.properties.Installable; install != nil {
- installable.Value = install
- }
-
- attrs := &bazelPrebuiltFileAttributes{
- Src: src,
- Dir: dir,
- Installable: installable,
- }
-
- if filename != "" {
- attrs.Filename = bazel.LabelAttribute{Value: &bazel.Label{Label: filename}}
- } else if filenameFromSrc {
- attrs.Filename_from_src = bazel.BoolAttribute{Value: moduleProps.Filename_from_src}
- }
-
- return attrs, true
-}
-
-// ConvertWithBp2build performs bp2build conversion of PrebuiltEtc
-// prebuilt_* modules (except prebuilt_etc_xml) are PrebuiltEtc,
-// which we treat as *PrebuiltFile*
-func (module *PrebuiltEtc) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- var dir = module.installDirBase
- // prebuilt_file supports only `etc` or `usr/share`
- if !(dir == "etc" || dir == "usr/share") {
- return
- }
-
- attrs, convertible := module.Bp2buildHelper(ctx)
- if !convertible {
- return
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "prebuilt_file",
- Bzl_load_location: "//build/bazel/rules:prebuilt_file.bzl",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
-}
-
-var _ android.MixedBuildBuildable = (*PrebuiltEtc)(nil)
-
-func (pe *PrebuiltEtc) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
- return true
-}
-
-func (pe *PrebuiltEtc) QueueBazelCall(ctx android.BaseModuleContext) {
- ctx.Config().BazelContext.QueueBazelRequest(
- pe.GetBazelLabel(ctx, pe),
- cquery.GetPrebuiltFileInfo,
- android.GetConfigKey(ctx),
- )
-}
-
-func (pe *PrebuiltEtc) ProcessBazelQueryResponse(ctx android.ModuleContext) {
- bazelCtx := ctx.Config().BazelContext
- pfi, err := bazelCtx.GetPrebuiltFileInfo(pe.GetBazelLabel(ctx, pe), android.GetConfigKey(ctx))
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- return
- }
-
- // Set properties for androidmk
- pe.installDirPath = android.PathForModuleInstall(ctx, pfi.Dir)
-
- // Installation rules
- ip := installProperties{
- installable: pfi.Installable,
- filename: pfi.Filename,
- sourceFilePath: android.PathForSource(ctx, pfi.Src),
- // symlinks: pe.properties.Symlinks, // TODO: b/207489266 - Fully support all properties in prebuilt_file
- }
- pe.addInstallRules(ctx, ip)
-}
diff --git a/etc/prebuilt_etc_test.go b/etc/prebuilt_etc_test.go
index 5c4e222..df11709 100644
--- a/etc/prebuilt_etc_test.go
+++ b/etc/prebuilt_etc_test.go
@@ -23,7 +23,6 @@
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel/cquery"
"android/soong/snapshot"
)
@@ -495,41 +494,3 @@
checkIfSnapshotNotTaken(t, result, "recovery", "prebuilt_recovery_indirect")
})
}
-
-func TestPrebuiltEtcAndroidMkEntriesWithBazel(t *testing.T) {
- t.Parallel()
- bp := `
-prebuilt_etc {
- name: "myetc",
- src: "prebuilt_etc.rc", // filename in src tree
- filename: "init.rc", // target filename on device
- sub_dir: "subdir", // relative subdir for installation
- bazel_module: { label: "//foo/bar:myetc" },
-}
-`
- res := android.GroupFixturePreparers(
- prepareForPrebuiltEtcTest,
- android.FixtureModifyConfig(func(cfg android.Config) {
- cfg.BazelContext = android.MockBazelContext{
- LabelToPrebuiltFileInfo: map[string]cquery.PrebuiltFileInfo{
- "//foo/bar:myetc": cquery.PrebuiltFileInfo{
- Src: "foo/bar/prebuilt_etc.rc",
- Dir: "etc/subdir",
- Filename: "init.rc",
- Installable: true,
- },
- },
- }
- }),
- ).RunTestWithBp(t, bp)
- ctx := res.ModuleForTests("myetc", "android_arm64_armv8-a")
- mod := ctx.Module()
- entries := android.AndroidMkEntriesForTest(t, res.TestContext, mod)[0]
- // verify androidmk entries
- android.AssertStringDoesContain(t, "LOCAL_MODULE_PATH should contain", entries.EntryMap["LOCAL_MODULE_PATH"][0], "etc/subdir")
- android.AssertStringEquals(t, "LOCAL_INSTALLED_MODULE_STEM is incorrect", "init.rc", entries.EntryMap["LOCAL_INSTALLED_MODULE_STEM"][0])
- // verify installation rules
- install := ctx.Description("install")
- android.AssertStringEquals(t, "Source location of prebuilt_etc installation", "out/soong/.intermediates/myetc/android_arm64_armv8-a/init.rc", install.Input.String())
- android.AssertStringEquals(t, "Target location of prebuilt_etc installation", "out/soong/target/product/test_device/system/etc/subdir/init.rc", install.Output.String())
-}
diff --git a/filesystem/avb_add_hash_footer.go b/filesystem/avb_add_hash_footer.go
index f3fecd0..469f1fb 100644
--- a/filesystem/avb_add_hash_footer.go
+++ b/filesystem/avb_add_hash_footer.go
@@ -25,6 +25,7 @@
type avbAddHashFooter struct {
android.ModuleBase
+ android.DefaultableModuleBase
properties avbAddHashFooterProperties
@@ -68,6 +69,9 @@
// List of properties to add to the footer
Props []avbProp
+ // The index used to prevent rollback of the image on device.
+ Rollback_index *int64
+
// Include descriptors from images
Include_descriptors_from_images []string `android:"path,arch_variant"`
}
@@ -77,6 +81,7 @@
module := &avbAddHashFooter{}
module.AddProperties(&module.properties)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ android.InitDefaultableModule(module)
return module
}
@@ -128,6 +133,14 @@
addAvbProp(ctx, cmd, prop)
}
+ if a.properties.Rollback_index != nil {
+ rollbackIndex := proptools.Int(a.properties.Rollback_index)
+ if rollbackIndex < 0 {
+ ctx.PropertyErrorf("rollback_index", "Rollback index must be non-negative")
+ }
+ cmd.Flag(fmt.Sprintf(" --rollback_index %d", rollbackIndex))
+ }
+
cmd.FlagWithOutput("--image ", a.output)
builder.Build("avbAddHashFooter", fmt.Sprintf("avbAddHashFooter %s", ctx.ModuleName()))
@@ -195,3 +208,19 @@
func (a *avbAddHashFooter) Srcs() android.Paths {
return append(android.Paths{}, a.output)
}
+
+type avbAddHashFooterDefaults struct {
+ android.ModuleBase
+ android.DefaultsModuleBase
+}
+
+// avb_add_hash_footer_defaults provides a set of properties that can be inherited by other
+// avb_add_hash_footer modules. A module can use the properties from an avb_add_hash_footer_defaults
+// using `defaults: ["<:default_module_name>"]`. Properties of both modules are erged (when
+// possible) by prepending the default module's values to the depending module's values.
+func avbAddHashFooterDefaultsFactory() android.Module {
+ module := &avbAddHashFooterDefaults{}
+ module.AddProperties(&avbAddHashFooterProperties{})
+ android.InitDefaultsModule(module)
+ return module
+}
diff --git a/filesystem/avb_gen_vbmeta_image.go b/filesystem/avb_gen_vbmeta_image.go
index 0f331f9..985f0ea 100644
--- a/filesystem/avb_gen_vbmeta_image.go
+++ b/filesystem/avb_gen_vbmeta_image.go
@@ -24,6 +24,7 @@
type avbGenVbmetaImage struct {
android.ModuleBase
+ android.DefaultableModuleBase
properties avbGenVbmetaImageProperties
@@ -47,6 +48,7 @@
module := &avbGenVbmetaImage{}
module.AddProperties(&module.properties)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
+ android.InitDefaultableModule(module)
return module
}
@@ -106,3 +108,20 @@
}
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
+
+type avbGenVbmetaImageDefaults struct {
+ android.ModuleBase
+ android.DefaultsModuleBase
+}
+
+// avb_gen_vbmeta_image_defaults provides a set of properties that can be inherited by other
+// avb_gen_vbmeta_image modules. A module can use the properties from an
+// avb_gen_vbmeta_image_defaults using `defaults: ["<:default_module_name>"]`. Properties of both
+// modules are erged (when possible) by prepending the default module's values to the depending
+// module's values.
+func avbGenVbmetaImageDefaultsFactory() android.Module {
+ module := &avbGenVbmetaImageDefaults{}
+ module.AddProperties(&avbGenVbmetaImageProperties{})
+ android.InitDefaultsModule(module)
+ return module
+}
diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go
index 023c69a..2f6476c 100644
--- a/filesystem/filesystem.go
+++ b/filesystem/filesystem.go
@@ -36,7 +36,9 @@
ctx.RegisterModuleType("android_filesystem", filesystemFactory)
ctx.RegisterModuleType("android_system_image", systemImageFactory)
ctx.RegisterModuleType("avb_add_hash_footer", avbAddHashFooterFactory)
+ ctx.RegisterModuleType("avb_add_hash_footer_defaults", avbAddHashFooterDefaultsFactory)
ctx.RegisterModuleType("avb_gen_vbmeta_image", avbGenVbmetaImageFactory)
+ ctx.RegisterModuleType("avb_gen_vbmeta_image_defaults", avbGenVbmetaImageDefaultsFactory)
}
type filesystem struct {
@@ -104,6 +106,9 @@
// When set, passed to mkuserimg_mke2fs --mke2fs_uuid & --mke2fs_hash_seed.
// Otherwise, they'll be set as random which might cause indeterministic build output.
Uuid *string
+
+ // Mount point for this image. Default is "/"
+ Mount_point *string
}
// android_filesystem packages a set of modules and their transitive dependencies into a filesystem
@@ -332,7 +337,7 @@
}
addStr("fs_type", fsTypeStr(f.fsType(ctx)))
- addStr("mount_point", "/")
+ addStr("mount_point", proptools.StringDefault(f.properties.Mount_point, "/"))
addStr("use_dynamic_partition_size", "true")
addPath("ext_mkuserimg", ctx.Config().HostToolPath(ctx, "mkuserimg_mke2fs"))
// b/177813163 deps of the host tools have to be added. Remove this.
@@ -347,13 +352,16 @@
addStr("avb_algorithm", algorithm)
key := android.PathForModuleSrc(ctx, proptools.String(f.properties.Avb_private_key))
addPath("avb_key_path", key)
+ partitionName := proptools.StringDefault(f.properties.Partition_name, f.Name())
+ addStr("partition_name", partitionName)
avb_add_hashtree_footer_args := "--do_not_generate_fec"
if hashAlgorithm := proptools.String(f.properties.Avb_hash_algorithm); hashAlgorithm != "" {
avb_add_hashtree_footer_args += " --hash_algorithm " + hashAlgorithm
}
+ securityPatchKey := "com.android.build." + partitionName + ".security_patch"
+ securityPatchValue := ctx.Config().PlatformSecurityPatch()
+ avb_add_hashtree_footer_args += " --prop " + securityPatchKey + ":" + securityPatchValue
addStr("avb_add_hashtree_footer_args", avb_add_hashtree_footer_args)
- partitionName := proptools.StringDefault(f.properties.Partition_name, f.Name())
- addStr("partition_name", partitionName)
addStr("avb_salt", f.salt())
}
@@ -504,6 +512,6 @@
var _ cc.UseCoverage = (*filesystem)(nil)
-func (*filesystem) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool {
+func (*filesystem) IsNativeCoverageNeeded(ctx android.IncomingTransitionContext) bool {
return ctx.Device() && ctx.DeviceConfig().NativeCoverageEnabled()
}
diff --git a/filesystem/vbmeta.go b/filesystem/vbmeta.go
index 63e0aba..43a2f37 100644
--- a/filesystem/vbmeta.go
+++ b/filesystem/vbmeta.go
@@ -63,6 +63,17 @@
// List of chained partitions that this vbmeta deletages the verification.
Chained_partitions []chainedPartitionProperties
+
+ // List of key-value pair of avb properties
+ Avb_properties []avbProperty
+}
+
+type avbProperty struct {
+ // Key of given avb property
+ Key *string
+
+ // Value of given avb property
+ Value *string
}
type chainedPartitionProperties struct {
@@ -135,6 +146,20 @@
}
cmd.FlagWithArg("--rollback_index_location ", strconv.Itoa(ril))
+ for _, avb_prop := range v.properties.Avb_properties {
+ key := proptools.String(avb_prop.Key)
+ if key == "" {
+ ctx.PropertyErrorf("avb_properties", "key must be specified")
+ continue
+ }
+ value := proptools.String(avb_prop.Value)
+ if value == "" {
+ ctx.PropertyErrorf("avb_properties", "value must be specified")
+ continue
+ }
+ cmd.FlagWithArg("--prop ", key+":"+value)
+ }
+
for _, p := range ctx.GetDirectDepsWithTag(vbmetaPartitionDep) {
f, ok := p.(Filesystem)
if !ok {
diff --git a/finder/finder_test.go b/finder/finder_test.go
index 8f73719..be22d13 100644
--- a/finder/finder_test.go
+++ b/finder/finder_test.go
@@ -813,6 +813,7 @@
IncludeFiles: []string{"findme.txt"},
},
)
+ finder.WaitForDbDump()
filesystem.Clock.Tick()
foundPaths := finder.FindNamedAt("/tmp", "findme.txt")
finder.Shutdown()
@@ -1445,6 +1446,7 @@
IncludeFiles: []string{"hi.txt"},
},
)
+ finder.WaitForDbDump()
filesystem.Clock.Tick()
foundPaths := finder.FindAll()
finder.Shutdown()
@@ -1506,6 +1508,7 @@
IncludeFiles: []string{"hi.txt"},
},
)
+ finder.WaitForDbDump()
filesystem.Clock.Tick()
foundPaths := finder.FindAll()
finder.Shutdown()
@@ -1552,6 +1555,7 @@
IncludeFiles: []string{"hi.txt"},
},
)
+ finder.WaitForDbDump()
filesystem.Clock.Tick()
foundPaths := finder.FindAll()
finder.Shutdown()
@@ -1573,6 +1577,7 @@
IncludeFiles: []string{"hi.txt"},
},
)
+ finder.WaitForDbDump()
filesystem.Clock.Tick()
foundPaths := finder.FindAll()
finder.Shutdown()
diff --git a/fuzz/fuzz_common.go b/fuzz/fuzz_common.go
index 94b795f..47fd8f4 100644
--- a/fuzz/fuzz_common.go
+++ b/fuzz/fuzz_common.go
@@ -399,13 +399,11 @@
}
type FuzzPackagedModule struct {
- FuzzProperties FuzzProperties
- Dictionary android.Path
- Corpus android.Paths
- CorpusIntermediateDir android.Path
- Config android.Path
- Data android.Paths
- DataIntermediateDir android.Path
+ FuzzProperties FuzzProperties
+ Dictionary android.Path
+ Corpus android.Paths
+ Config android.Path
+ Data android.Paths
}
func GetFramework(ctx android.LoadHookContext, lang Lang) Framework {
@@ -527,12 +525,10 @@
builder.Build("create-"+fuzzZip.String(),
"Package "+module.Name()+" for "+archString+"-"+hostOrTargetString)
- // Don't add modules to 'make haiku-rust' that are set to not be
- // exported to the fuzzing infrastructure.
if config := fuzzModule.FuzzProperties.Fuzz_config; config != nil {
if strings.Contains(hostOrTargetString, "host") && !BoolDefault(config.Fuzz_on_haiku_host, true) {
return archDirs[archOs], false
- } else if !BoolDefault(config.Fuzz_on_haiku_device, true) {
+ } else if !strings.Contains(hostOrTargetString, "host") && !BoolDefault(config.Fuzz_on_haiku_device, true) {
return archDirs[archOs], false
}
}
diff --git a/genrule/Android.bp b/genrule/Android.bp
index b201cae..7331741 100644
--- a/genrule/Android.bp
+++ b/genrule/Android.bp
@@ -11,7 +11,6 @@
"sbox_proto",
"soong",
"soong-android",
- "soong-bazel",
"soong-shared",
],
srcs: [
diff --git a/genrule/allowlists.go b/genrule/allowlists.go
index afa52cc..60b1366 100644
--- a/genrule/allowlists.go
+++ b/genrule/allowlists.go
@@ -15,130 +15,15 @@
package genrule
var (
- DepfileAllowList = []string{
- "depfile_allowed_for_test",
- "tflite_support_spm_config",
- "tflite_support_spm_encoder_config",
- "gen_uwb_core_proto",
- "libtextclassifier_fbgen_utils_flatbuffers_flatbuffers_test",
- "libtextclassifier_fbgen_utils_lua_utils_tests",
- "libtextclassifier_fbgen_lang_id_common_flatbuffers_model",
- "libtextclassifier_fbgen_lang_id_common_flatbuffers_embedding-network",
- "libtextclassifier_fbgen_annotator_datetime_datetime",
- "libtextclassifier_fbgen_annotator_model",
- "libtextclassifier_fbgen_annotator_experimental_experimental",
- "libtextclassifier_fbgen_annotator_entity-data",
- "libtextclassifier_fbgen_annotator_person_name_person_name_model",
- "libtextclassifier_fbgen_utils_tflite_text_encoder_config",
- "libtextclassifier_fbgen_utils_codepoint-range",
- "libtextclassifier_fbgen_utils_intents_intent-config",
- "libtextclassifier_fbgen_utils_flatbuffers_flatbuffers",
- "libtextclassifier_fbgen_utils_zlib_buffer",
- "libtextclassifier_fbgen_utils_tokenizer",
- "libtextclassifier_fbgen_utils_grammar_rules",
- "libtextclassifier_fbgen_utils_grammar_semantics_expression",
- "libtextclassifier_fbgen_utils_resources",
- "libtextclassifier_fbgen_utils_i18n_language-tag",
- "libtextclassifier_fbgen_utils_normalization",
- "libtextclassifier_fbgen_utils_container_bit-vector",
- "libtextclassifier_fbgen_actions_actions-entity-data",
- "libtextclassifier_fbgen_actions_actions_model",
- "libtextclassifier_fbgen_utils_grammar_testing_value",
- }
-
SandboxingDenyModuleList = []string{
- "RsBalls-rscript",
- "pvmfw_fdt_template_rs",
- "RSTest_v14-rscript",
- "com.android.apex.test.bar_stripped",
- "com.android.apex.test.sharedlibs_secondary_generated",
- "ImageProcessingJB-rscript",
- "RSTest-rscript",
- "BluetoothGeneratedDumpsysBinarySchema_bfbs",
- "TracingVMProtoStub_h",
- "VehicleServerProtoStub_cc",
- "AudioFocusControlProtoStub_cc",
- "AudioFocusControlProtoStub_h",
- "TracingVMProtoStub_cc",
- "VehicleServerProtoStub_h",
- "hidl2aidl_translate_cpp_test_gen_headers",
- "hidl2aidl_translate_cpp_test_gen_src",
- "hidl2aidl_translate_java_test_gen_src",
- "hidl2aidl_translate_ndk_test_gen_headers",
- "hidl2aidl_translate_ndk_test_gen_src",
- "hidl_hash_test_gen",
- "nos_app_avb_service_genc++",
- "nos_app_avb_service_genc++_headers",
- "nos_app_avb_service_genc++_mock",
- "nos_app_identity_service_genc++",
- "nos_app_keymaster_service_genc++",
- "nos_generator_test_service_genc++_headers",
- "nos_generator_test_service_genc++_mock",
- "r8retrace-run-retrace",
- "ltp_config_arm",
- "ltp_config_arm_64_hwasan",
- "ltp_config_arm_lowmem",
- "ltp_config_arm_64",
- "ltp_config_riscv_64",
- "ltp_config_x86_64",
- "vm-tests-tf-lib",
- "hidl_cpp_impl_test_gen-headers",
- "Refocus-rscript",
- "RSTest_v11-rscript",
- "RSTest_v16-rscript",
- "ScriptGroupTest-rscript",
- "ImageProcessing2-rscript",
- "ImageProcessing-rscript",
- "com.android.apex.test.pony_stripped",
- "com.android.apex.test.baz_stripped",
- "com.android.apex.test.foo_stripped",
- "com.android.apex.test.sharedlibs_generated",
- "BlueberryFacadeAndCertGeneratedStub_py",
- "BlueberryFacadeGeneratedStub_cc",
- "BlueberryFacadeGeneratedStub_h",
- "BluetoothGeneratedDumpsysDataSchema_h",
- "c2hal_test_genc++",
- "c2hal_test_genc++_headers",
- "hidl2aidl_test_gen_aidl",
- "hidl_error_test_gen",
- "hidl_export_test_gen-headers",
- "hidl_format_test_diff",
- "hidl_hash_version_gen",
- "libbt_topshim_facade_py_proto",
- "nos_app_identity_service_genc++_headers",
- "nos_app_identity_service_genc++_mock",
- "nos_app_keymaster_service_genc++_headers",
- "nos_app_keymaster_service_genc++_mock",
- "nos_app_weaver_service_genc++",
- "nos_app_weaver_service_genc++_headers",
- "nos_app_weaver_service_genc++_mock",
- "nos_generator_test_service_genc++",
+ // go/keep-sorted start
"aidl_camera_build_version",
- "cronet_aml_base_android_runtime_unchecked_jni_headers",
- "cronet_aml_base_android_runtime_jni_headers",
- "aidl-golden-test-build-hook-gen",
- "PacketStreamerStub_h",
- "FrontendStub_cc",
- "FrontendStub_h",
- "PacketStreamerStub_cc",
- "pixelstatsatoms.h",
- "pixelatoms_defs.h",
- "pixelstatsatoms.cpp",
- "hidl_java_impl_test_gen",
- "cronet_aml_base_android_runtime_jni_headers__testing",
- "cronet_aml_base_android_runtime_unchecked_jni_headers__testing",
- "hidl_cpp_impl_test_gen-sources",
- "fdt_test_tree_multiple_memory_ranges_dtb",
- "fdt_test_tree_one_memory_range_dtb",
- "fdt_test_tree_empty_memory_range_dtb",
- "ltp_config_arm_64_lowmem",
- "ltp_config_arm_64_lowmem_hwasan",
- "ltp_config_x86",
- "libbssl_sys_src_nostd",
+ "com.google.pixel.camera.hal.manifest",
+ // go/keep-sorted end
}
SandboxingDenyPathList = []string{
- "art/test",
- "external/perfetto",
+ // go/keep-sorted start
+ // go/keep-sorted end
}
)
diff --git a/genrule/genrule.go b/genrule/genrule.go
index d1c2f13..6f66088 100644
--- a/genrule/genrule.go
+++ b/genrule/genrule.go
@@ -21,18 +21,14 @@
import (
"fmt"
"io"
- "path/filepath"
"strconv"
"strings"
- "android/soong/bazel/cquery"
-
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel"
)
func init() {
@@ -128,14 +124,10 @@
// $(locations <label>): the paths to the tools, tool_files, inputs or outputs with name <label>. Use $(locations) if <label> refers to a rule that outputs two or more files.
// $(in): one or more input files.
// $(out): a single output file.
- // $(depfile): a file to which dependencies will be written, if the depfile property is set to true.
// $(genDir): the sandbox directory for this tool; contains $(out).
// $$: a literal $
Cmd *string
- // Enable reading a file containing dependencies in gcc format after the command completes
- Depfile *bool
-
// name of the modules (if any) that produces the host executable. Leave empty for
// prebuilts or scripts that do not need a module to build them.
Tools []string
@@ -159,7 +151,6 @@
type Module struct {
android.ModuleBase
android.DefaultableModuleBase
- android.BazelModuleBase
android.ApexModuleBase
// For other packages to make their own genrules with extra
@@ -190,21 +181,17 @@
subName string
subDir string
- // Collect the module directory for IDE info in java/jdeps.go.
- modulePaths []string
+ // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo
+ mergedAconfigFiles map[string]android.Paths
}
-var _ android.MixedBuildBuildable = (*Module)(nil)
-
type taskFunc func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask
type generateTask struct {
in android.Paths
out android.WritablePaths
- depFile android.WritablePath
copyTo android.WritablePaths // For gensrcs to set on gensrcsMerge rule.
genDir android.WritablePath
- extraTools android.Paths // dependencies on tools used by the generator
extraInputs map[string][]string
cmd string
@@ -257,30 +244,6 @@
}
}
-func (g *Module) ProcessBazelQueryResponse(ctx android.ModuleContext) {
- g.generateCommonBuildActions(ctx)
-
- label := g.GetBazelLabel(ctx, g)
- bazelCtx := ctx.Config().BazelContext
- filePaths, err := bazelCtx.GetOutputFiles(label, android.GetConfigKey(ctx))
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- return
- }
-
- var bazelOutputFiles android.Paths
- exportIncludeDirs := map[string]bool{}
- for _, bazelOutputFile := range filePaths {
- bazelOutputFiles = append(bazelOutputFiles, android.PathForBazelOutRelative(ctx, ctx.ModuleDir(), bazelOutputFile))
- exportIncludeDirs[filepath.Dir(bazelOutputFile)] = true
- }
- g.outputFiles = bazelOutputFiles
- g.outputDeps = bazelOutputFiles
- for includePath, _ := range exportIncludeDirs {
- g.exportedIncludeDirs = append(g.exportedIncludeDirs, android.PathForBazelOut(ctx, includePath))
- }
-}
-
// generateCommonBuildActions contains build action generation logic
// common to both the mixed build case and the legacy case of genrule processing.
// To fully support genrule in mixed builds, the contents of this function should
@@ -289,9 +252,6 @@
func (g *Module) generateCommonBuildActions(ctx android.ModuleContext) {
g.subName = ctx.ModuleSubDir()
- // Collect the module directory for IDE info in java/jdeps.go.
- g.modulePaths = append(g.modulePaths, ctx.ModuleDir())
-
if len(g.properties.Export_include_dirs) > 0 {
for _, dir := range g.properties.Export_include_dirs {
g.exportedIncludeDirs = append(g.exportedIncludeDirs,
@@ -430,6 +390,7 @@
return srcFiles
}
srcFiles := addLabelsForInputs("srcs", g.properties.Srcs, g.properties.Exclude_srcs)
+ android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcFiles.Strings()})
var copyFrom android.Paths
var outputFiles android.WritablePaths
@@ -481,8 +442,6 @@
addLocationLabel(out.Rel(), outputLocation{out})
}
- referencedDepfile := false
-
rawCommand, err := android.Expand(task.cmd, func(name string) (string, error) {
// report the error directly without returning an error to android.Expand to catch multiple errors in a
// single run
@@ -514,12 +473,6 @@
sandboxOuts = append(sandboxOuts, cmd.PathForOutput(out))
}
return strings.Join(proptools.ShellEscapeList(sandboxOuts), " "), nil
- case "depfile":
- referencedDepfile = true
- if !Bool(g.properties.Depfile) {
- return reportError("$(depfile) used without depfile property")
- }
- return "__SBOX_DEPFILE__", nil
case "genDir":
return proptools.ShellEscape(cmd.PathForOutput(task.genDir)), nil
default:
@@ -544,7 +497,7 @@
if len(paths) == 0 {
return reportError("label %q has no files", label)
}
- return proptools.ShellEscape(strings.Join(paths, " ")), nil
+ return strings.Join(proptools.ShellEscapeList(paths), " "), nil
} else {
return reportError("unknown locations label %q is not in srcs, out, tools or tool_files.", label)
}
@@ -559,10 +512,6 @@
return
}
- if Bool(g.properties.Depfile) && !referencedDepfile {
- ctx.PropertyErrorf("cmd", "specified depfile=true but did not include a reference to '${depfile}' in cmd")
- return
- }
g.rawCommands = append(g.rawCommands, rawCommand)
cmd.Text(rawCommand)
@@ -571,11 +520,7 @@
cmd.ImplicitOutputs(task.out)
cmd.Implicits(task.in)
cmd.ImplicitTools(tools)
- cmd.ImplicitTools(task.extraTools)
cmd.ImplicitPackagedTools(packagedTools)
- if Bool(g.properties.Depfile) {
- cmd.ImplicitDepFile(task.depFile)
- }
// Create the rule to run the genrule command inside sbox.
rule.Build(name, desc)
@@ -616,21 +561,6 @@
}
func (g *Module) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- // Allowlist genrule to use depfile until we have a solution to remove it.
- // TODO(b/235582219): Remove allowlist for genrule
- if Bool(g.properties.Depfile) {
- sandboxingAllowlistSets := getSandboxingAllowlistSets(ctx)
- // TODO(b/283852474): Checking the GenruleSandboxing flag is temporary in
- // order to pass the presubmit before internal master is updated.
- if ctx.DeviceConfig().GenruleSandboxing() && !sandboxingAllowlistSets.depfileAllowSet[g.Name()] {
- ctx.PropertyErrorf(
- "depfile",
- "Deprecated to ensure the module type is convertible to Bazel. "+
- "Try specifying the dependencies explicitly so that there is no need to use depfile. "+
- "If not possible, the escape hatch is to add the module to allowlists.go to bypass the error.")
- }
- }
-
g.generateCommonBuildActions(ctx)
// For <= 6 outputs, just embed those directly in the users. Right now, that covers >90% of
@@ -648,15 +578,24 @@
})
g.outputDeps = android.Paths{phonyFile}
}
+ android.CollectDependencyAconfigFiles(ctx, &g.mergedAconfigFiles)
}
-func (g *Module) QueueBazelCall(ctx android.BaseModuleContext) {
- bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(g.GetBazelLabel(ctx, g), cquery.GetOutputFiles, android.GetConfigKey(ctx))
+func (g *Module) AndroidMkEntries() []android.AndroidMkEntries {
+ ret := android.AndroidMkEntries{
+ OutputFile: android.OptionalPathForPath(g.outputFiles[0]),
+ ExtraEntries: []android.AndroidMkExtraEntriesFunc{
+ func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ android.SetAconfigFileMkEntries(g.AndroidModuleBase(), entries, g.mergedAconfigFiles)
+ },
+ },
+ }
+
+ return []android.AndroidMkEntries{ret}
}
-func (g *Module) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
- return true
+func (g *Module) AndroidModuleBase() *android.ModuleBase {
+ return &g.ModuleBase
}
// Collect information for opening IDE project files in java/jdeps.go.
@@ -668,7 +607,6 @@
dpInfo.Deps = append(dpInfo.Deps, src)
}
}
- dpInfo.Paths = append(dpInfo.Paths, g.modulePaths...)
}
func (g *Module) AndroidMk() android.AndroidMkData {
@@ -748,7 +686,6 @@
for i, shard := range shards {
var commands []string
var outFiles android.WritablePaths
- var commandDepFiles []string
var copyTo android.WritablePaths
// When sharding is enabled (i.e. len(shards) > 1), the sbox rules for each
@@ -788,12 +725,6 @@
return in.String(), nil
case "out":
return rule.Command().PathForOutput(outFile), nil
- case "depfile":
- // Generate a depfile for each output file. Store the list for
- // later in order to combine them all into a single depfile.
- depFile := rule.Command().PathForOutput(outFile.ReplaceExtension(ctx, "d"))
- commandDepFiles = append(commandDepFiles, depFile)
- return depFile, nil
default:
return "$(" + name + ")", nil
}
@@ -808,30 +739,14 @@
}
fullCommand := strings.Join(commands, " && ")
- var outputDepfile android.WritablePath
- var extraTools android.Paths
- if len(commandDepFiles) > 0 {
- // Each command wrote to a depfile, but ninja can only handle one
- // depfile per rule. Use the dep_fixer tool at the end of the
- // command to combine all the depfiles into a single output depfile.
- outputDepfile = android.PathForModuleGen(ctx, genSubDir, "gensrcs.d")
- depFixerTool := ctx.Config().HostToolPath(ctx, "dep_fixer")
- fullCommand += fmt.Sprintf(" && %s -o $(depfile) %s",
- rule.Command().PathForTool(depFixerTool),
- strings.Join(commandDepFiles, " "))
- extraTools = append(extraTools, depFixerTool)
- }
-
generateTasks = append(generateTasks, generateTask{
- in: shard,
- out: outFiles,
- depFile: outputDepfile,
- copyTo: copyTo,
- genDir: genDir,
- cmd: fullCommand,
- shard: i,
- shards: len(shards),
- extraTools: extraTools,
+ in: shard,
+ out: outFiles,
+ copyTo: copyTo,
+ genDir: genDir,
+ cmd: fullCommand,
+ shard: i,
+ shards: len(shards),
extraInputs: map[string][]string{
"data": properties.Data,
},
@@ -849,7 +764,6 @@
func GenSrcsFactory() android.Module {
m := NewGenSrcs()
android.InitAndroidModule(m)
- android.InitBazelModule(m)
return m
}
@@ -864,14 +778,6 @@
Data []string `android:"path"`
}
-type bazelGensrcsAttributes struct {
- Srcs bazel.LabelListAttribute
- Output_extension *string
- Tools bazel.LabelListAttribute
- Cmd bazel.StringAttribute
- Data bazel.LabelListAttribute
-}
-
const defaultShardSize = 50
func NewGenRule() *Module {
@@ -879,20 +785,14 @@
taskGenerator := func(ctx android.ModuleContext, rawCommand string, srcFiles android.Paths) []generateTask {
outs := make(android.WritablePaths, len(properties.Out))
- var depFile android.WritablePath
for i, out := range properties.Out {
- outPath := android.PathForModuleGen(ctx, out)
- if i == 0 {
- depFile = outPath.ReplaceExtension(ctx, "d")
- }
- outs[i] = outPath
+ outs[i] = android.PathForModuleGen(ctx, out)
}
return []generateTask{{
- in: srcFiles,
- out: outs,
- depFile: depFile,
- genDir: android.PathForModuleGen(ctx),
- cmd: rawCommand,
+ in: srcFiles,
+ out: outs,
+ genDir: android.PathForModuleGen(ctx),
+ cmd: rawCommand,
}}
}
@@ -903,7 +803,6 @@
m := NewGenRule()
android.InitAndroidModule(m)
android.InitDefaultableModule(m)
- android.InitBazelModule(m)
return m
}
@@ -912,212 +811,6 @@
Out []string
}
-type BazelGenruleAttributes struct {
- Srcs bazel.LabelListAttribute
- Outs []string
- Tools bazel.LabelListAttribute
- Cmd bazel.StringAttribute
-}
-
-// ConvertWithBp2build converts a Soong module -> Bazel target.
-func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- // Bazel only has the "tools" attribute.
- tools_prop := android.BazelLabelForModuleDeps(ctx, m.properties.Tools)
- tool_files_prop := android.BazelLabelForModuleSrc(ctx, m.properties.Tool_files)
- tools_prop.Append(tool_files_prop)
-
- tools := bazel.MakeLabelListAttribute(tools_prop)
- srcs := bazel.LabelListAttribute{}
- srcs_labels := bazel.LabelList{}
- // Only cc_genrule is arch specific
- if ctx.ModuleType() == "cc_genrule" {
- for axis, configToProps := range m.GetArchVariantProperties(ctx, &generatorProperties{}) {
- for config, props := range configToProps {
- if props, ok := props.(*generatorProperties); ok {
- labels := android.BazelLabelForModuleSrcExcludes(ctx, props.Srcs, props.Exclude_srcs)
- srcs_labels.Append(labels)
- srcs.SetSelectValue(axis, config, labels)
- }
- }
- }
- } else {
- srcs_labels = android.BazelLabelForModuleSrcExcludes(ctx, m.properties.Srcs, m.properties.Exclude_srcs)
- srcs = bazel.MakeLabelListAttribute(srcs_labels)
- }
-
- var allReplacements bazel.LabelList
- allReplacements.Append(tools.Value)
- allReplacements.Append(bazel.FirstUniqueBazelLabelList(srcs_labels))
-
- // The Output_extension prop is not in an immediately accessible field
- // in the Module struct, so use GetProperties and cast it
- // to the known struct prop.
- var outputExtension *string
- var data bazel.LabelListAttribute
- if ctx.ModuleType() == "gensrcs" {
- for _, propIntf := range m.GetProperties() {
- if props, ok := propIntf.(*genSrcsProperties); ok {
- outputExtension = props.Output_extension
- dataFiles := android.BazelLabelForModuleSrc(ctx, props.Data)
- allReplacements.Append(bazel.FirstUniqueBazelLabelList(dataFiles))
- data = bazel.MakeLabelListAttribute(dataFiles)
- break
- }
- }
- }
-
- replaceVariables := func(cmd string) string {
- // Replace in and out variables with $< and $@
- if ctx.ModuleType() == "gensrcs" {
- cmd = strings.ReplaceAll(cmd, "$(in)", "$(SRC)")
- cmd = strings.ReplaceAll(cmd, "$(out)", "$(OUT)")
- } else {
- cmd = strings.Replace(cmd, "$(in)", "$(SRCS)", -1)
- cmd = strings.Replace(cmd, "$(out)", "$(OUTS)", -1)
- }
- cmd = strings.Replace(cmd, "$(genDir)", "$(RULEDIR)", -1)
- if len(tools.Value.Includes) > 0 {
- cmd = strings.Replace(cmd, "$(location)", fmt.Sprintf("$(location %s)", tools.Value.Includes[0].Label), -1)
- cmd = strings.Replace(cmd, "$(locations)", fmt.Sprintf("$(locations %s)", tools.Value.Includes[0].Label), -1)
- }
- for _, l := range allReplacements.Includes {
- bpLoc := fmt.Sprintf("$(location %s)", l.OriginalModuleName)
- bpLocs := fmt.Sprintf("$(locations %s)", l.OriginalModuleName)
- bazelLoc := fmt.Sprintf("$(location %s)", l.Label)
- bazelLocs := fmt.Sprintf("$(locations %s)", l.Label)
- cmd = strings.Replace(cmd, bpLoc, bazelLoc, -1)
- cmd = strings.Replace(cmd, bpLocs, bazelLocs, -1)
- }
- return cmd
- }
-
- var cmdProp bazel.StringAttribute
- cmdProp.SetValue(replaceVariables(proptools.String(m.properties.Cmd)))
- allProductVariableProps := android.ProductVariableProperties(ctx, m)
- if productVariableProps, ok := allProductVariableProps["Cmd"]; ok {
- for productVariable, value := range productVariableProps {
- var cmd string
- if strValue, ok := value.(*string); ok && strValue != nil {
- cmd = *strValue
- }
- cmd = replaceVariables(cmd)
- cmdProp.SetSelectValue(productVariable.ConfigurationAxis(), productVariable.SelectKey(), &cmd)
- }
- }
-
- tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m)
-
- bazelName := m.Name()
- if ctx.ModuleType() == "gensrcs" {
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "gensrcs",
- Bzl_load_location: "//build/bazel/rules:gensrcs.bzl",
- }
- attrs := &bazelGensrcsAttributes{
- Srcs: srcs,
- Output_extension: outputExtension,
- Cmd: cmdProp,
- Tools: tools,
- Data: data,
- }
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: m.Name(),
- Tags: tags,
- }, attrs)
- } else {
- outs := m.RawOutputFiles(ctx)
- for _, out := range outs {
- if out == bazelName {
- // This is a workaround to circumvent a Bazel warning where a genrule's
- // out may not have the same name as the target itself. This makes no
- // difference for reverse dependencies, because they may depend on the
- // out file by name.
- bazelName = bazelName + "-gen"
- break
- }
- }
- attrs := &BazelGenruleAttributes{
- Srcs: srcs,
- Outs: outs,
- Cmd: cmdProp,
- Tools: tools,
- }
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "genrule",
- }
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: bazelName,
- Tags: tags,
- }, attrs)
- }
-
- if m.needsCcLibraryHeadersBp2build() {
- includeDirs := make([]string, len(m.properties.Export_include_dirs)*2)
- for i, dir := range m.properties.Export_include_dirs {
- includeDirs[i*2] = dir
- includeDirs[i*2+1] = filepath.Clean(filepath.Join(ctx.ModuleDir(), dir))
- }
- attrs := &ccHeaderLibraryAttrs{
- Hdrs: []string{":" + bazelName},
- Export_includes: includeDirs,
- }
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "cc_library_headers",
- Bzl_load_location: "//build/bazel/rules/cc:cc_library_headers.bzl",
- }
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: m.Name() + genruleHeaderLibrarySuffix,
- Tags: tags,
- }, attrs)
- }
-}
-
-const genruleHeaderLibrarySuffix = "__header_library"
-
-func (m *Module) needsCcLibraryHeadersBp2build() bool {
- return len(m.properties.Export_include_dirs) > 0
-}
-
-// GenruleCcHeaderMapper is a bazel.LabelMapper function to map genrules to a cc_library_headers
-// target when they export multiple include directories.
-func GenruleCcHeaderLabelMapper(ctx bazel.OtherModuleContext, label bazel.Label) (string, bool) {
- mod, exists := ctx.ModuleFromName(label.OriginalModuleName)
- if !exists {
- return label.Label, false
- }
- if m, ok := mod.(*Module); ok {
- if m.needsCcLibraryHeadersBp2build() {
- return label.Label + genruleHeaderLibrarySuffix, true
- }
- }
- return label.Label, false
-}
-
-type ccHeaderLibraryAttrs struct {
- Hdrs []string
-
- Export_includes []string
-}
-
-// RawOutputFfiles returns the raw outputs specified in Android.bp
-// This does not contain the fully resolved path relative to the top of the tree
-func (g *Module) RawOutputFiles(ctx android.BazelConversionContext) []string {
- if ctx.Config().BuildMode != android.Bp2build {
- ctx.ModuleErrorf("RawOutputFiles is only supported in bp2build mode")
- }
- // The Out prop is not in an immediately accessible field
- // in the Module struct, so use GetProperties and cast it
- // to the known struct prop.
- var outs []string
- for _, propIntf := range g.GetProperties() {
- if props, ok := propIntf.(*genRuleProperties); ok {
- outs = props.Out
- break
- }
- }
- return outs
-}
-
var Bool = proptools.Bool
var String = proptools.String
@@ -1150,22 +843,18 @@
type sandboxingAllowlistSets struct {
sandboxingDenyModuleSet map[string]bool
sandboxingDenyPathSet map[string]bool
- depfileAllowSet map[string]bool
}
func getSandboxingAllowlistSets(ctx android.PathContext) *sandboxingAllowlistSets {
return ctx.Config().Once(sandboxingAllowlistKey, func() interface{} {
sandboxingDenyModuleSet := map[string]bool{}
sandboxingDenyPathSet := map[string]bool{}
- depfileAllowSet := map[string]bool{}
- android.AddToStringSet(sandboxingDenyModuleSet, append(DepfileAllowList, SandboxingDenyModuleList...))
+ android.AddToStringSet(sandboxingDenyModuleSet, SandboxingDenyModuleList)
android.AddToStringSet(sandboxingDenyPathSet, SandboxingDenyPathList)
- android.AddToStringSet(depfileAllowSet, DepfileAllowList)
return &sandboxingAllowlistSets{
sandboxingDenyModuleSet: sandboxingDenyModuleSet,
sandboxingDenyPathSet: sandboxingDenyPathSet,
- depfileAllowSet: depfileAllowSet,
}
}).(*sandboxingAllowlistSets)
}
diff --git a/genrule/genrule_test.go b/genrule/genrule_test.go
index 7c14531..2dc6a79 100644
--- a/genrule/genrule_test.go
+++ b/genrule/genrule_test.go
@@ -287,16 +287,6 @@
expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out2",
},
{
- name: "depfile",
- moduleName: "depfile_allowed_for_test",
- prop: `
- out: ["out"],
- depfile: true,
- cmd: "echo foo > $(out) && touch $(depfile)",
- `,
- expect: "echo foo > __SBOX_SANDBOX_DIR__/out/out && touch __SBOX_DEPFILE__",
- },
- {
name: "gendir",
prop: `
out: ["out"],
@@ -392,24 +382,6 @@
err: `unknown variable '$(foo)'`,
},
{
- name: "error depfile",
- prop: `
- out: ["out"],
- cmd: "echo foo > $(out) && touch $(depfile)",
- `,
- err: "$(depfile) used without depfile property",
- },
- {
- name: "error no depfile",
- moduleName: "depfile_allowed_for_test",
- prop: `
- out: ["out"],
- depfile: true,
- cmd: "echo foo > $(out)",
- `,
- err: "specified depfile=true but did not include a reference to '${depfile}' in cmd",
- },
- {
name: "error no out",
prop: `
cmd: "echo foo > $(out)",
@@ -543,7 +515,7 @@
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
gen := result.ModuleForTests(test.name, "")
- manifest := android.RuleBuilderSboxProtoForTests(t, gen.Output("genrule.sbox.textproto"))
+ manifest := android.RuleBuilderSboxProtoForTests(t, result.TestContext, gen.Output("genrule.sbox.textproto"))
hash := manifest.Commands[0].GetInputHash()
android.AssertStringEquals(t, "hash", test.expectedHash, hash)
@@ -695,60 +667,6 @@
}
}
-func TestGenruleAllowlistingDepfile(t *testing.T) {
- tests := []struct {
- name string
- prop string
- err string
- moduleName string
- }{
- {
- name: `error when module is not allowlisted`,
- prop: `
- depfile: true,
- cmd: "cat $(in) > $(out) && cat $(depfile)",
- `,
- err: "depfile: Deprecated to ensure the module type is convertible to Bazel",
- },
- {
- name: `no error when module is allowlisted`,
- prop: `
- depfile: true,
- cmd: "cat $(in) > $(out) && cat $(depfile)",
- `,
- moduleName: `depfile_allowed_for_test`,
- },
- }
- for _, test := range tests {
- t.Run(test.name, func(t *testing.T) {
- moduleName := "foo"
- if test.moduleName != "" {
- moduleName = test.moduleName
- }
- bp := fmt.Sprintf(`
- gensrcs {
- name: "%s",
- srcs: ["data.txt"],
- %s
- }`, moduleName, test.prop)
-
- var expectedErrors []string
- if test.err != "" {
- expectedErrors = append(expectedErrors, test.err)
- }
- android.GroupFixturePreparers(
- prepareForGenRuleTest,
- android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
- variables.GenruleSandboxing = proptools.BoolPtr(true)
- }),
- ).
- ExtendWithErrorHandler(android.FixtureExpectsAllErrorsToMatchAPattern(expectedErrors)).
- RunTestWithBp(t, bp)
- })
-
- }
-}
-
func TestGenruleDefaults(t *testing.T) {
bp := `
genrule_defaults {
@@ -1039,31 +957,6 @@
}
}
-func TestGenruleWithBazel(t *testing.T) {
- bp := `
- genrule {
- name: "foo",
- out: ["one.txt", "two.txt"],
- bazel_module: { label: "//foo/bar:bar" },
- }
- `
-
- result := android.GroupFixturePreparers(
- prepareForGenRuleTest, android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: "outputbase",
- LabelToOutputFiles: map[string][]string{
- "//foo/bar:bar": []string{"bazelone.txt", "bazeltwo.txt"}}}
- })).RunTestWithBp(t, testGenruleBp()+bp)
-
- gen := result.Module("foo", "").(*Module)
-
- expectedOutputFiles := []string{"outputbase/execroot/__main__/bazelone.txt",
- "outputbase/execroot/__main__/bazeltwo.txt"}
- android.AssertDeepEquals(t, "output files", expectedOutputFiles, gen.outputFiles.Strings())
- android.AssertDeepEquals(t, "output deps", expectedOutputFiles, gen.outputDeps.Strings())
-}
-
func TestGenruleWithGlobPaths(t *testing.T) {
testcases := []struct {
name string
diff --git a/go.mod b/go.mod
index 0a11bd2..1174958 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module android/soong
-go 1.20
+go 1.21
require (
github.com/google/blueprint v0.0.0
diff --git a/go.work b/go.work
index 67f6549..7c6022b 100644
--- a/go.work
+++ b/go.work
@@ -1,4 +1,4 @@
-go 1.19
+go 1.21
use (
.
diff --git a/jar/jar.go b/jar/jar.go
index f164ee1..54eded9 100644
--- a/jar/jar.go
+++ b/jar/jar.go
@@ -166,10 +166,23 @@
}
s.IsIdentRune = javaIdentRune
- tok := s.Scan()
- if sErr != nil {
- return "", sErr
+ var tok rune
+ for {
+ tok = s.Scan()
+ if sErr != nil {
+ return "", sErr
+ }
+ // If the first token is an annotation, it could be annotating a package declaration, so consume them.
+ // Note that this does not support "complex" annotations with attributes, e.g. @Foo(x=y).
+ if tok != '@' {
+ break
+ }
+ tok = s.Scan()
+ if tok != scanner.Ident || sErr != nil {
+ return "", fmt.Errorf("expected annotation identifier, got @%v", tok)
+ }
}
+
if tok == scanner.Ident {
switch s.TokenText() {
case "package":
@@ -189,9 +202,6 @@
default:
return "", fmt.Errorf(`expected first token of java file to be "package", got %q`, s.TokenText())
}
- } else if tok == '@' {
- // File has no package statement, first token is an annotation
- return "", nil
} else if tok == scanner.EOF {
// File no package statement, it has no non-whitespace non-comment tokens
return "", nil
diff --git a/jar/jar_test.go b/jar/jar_test.go
index c92011e..61da9bb 100644
--- a/jar/jar_test.go
+++ b/jar/jar_test.go
@@ -61,6 +61,16 @@
in: "package 0foo.bar;",
wantErr: true,
},
+ {
+ name: "annotations",
+ in: "@NonNullApi\n@X\npackage foo.bar;",
+ want: "foo.bar",
+ },
+ {
+ name: "complex annotation",
+ in: "@Foo(x=y)\n@package foo.bar;",
+ wantErr: true, // Complex annotation not supported yet.
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
diff --git a/java/Android.bp b/java/Android.bp
index 4450c42..2585cd2 100644
--- a/java/Android.bp
+++ b/java/Android.bp
@@ -9,12 +9,13 @@
"blueprint",
"blueprint-pathtools",
"soong",
+ "soong-aconfig",
"soong-android",
- "soong-bazel",
"soong-cc",
"soong-dexpreopt",
"soong-genrule",
"soong-java-config",
+ "soong-testing",
"soong-provenance",
"soong-python",
"soong-remoteexec",
@@ -66,7 +67,6 @@
"plugin.go",
"prebuilt_apis.go",
"proto.go",
- "resourceshrinker.go",
"robolectric.go",
"rro.go",
"sdk.go",
@@ -85,6 +85,7 @@
"app_import_test.go",
"app_set_test.go",
"app_test.go",
+ "code_metadata_test.go",
"bootclasspath_fragment_test.go",
"device_host_converter_test.go",
"dex_test.go",
@@ -106,12 +107,13 @@
"plugin_test.go",
"prebuilt_apis_test.go",
"proto_test.go",
- "resourceshrinker_test.go",
"rro_test.go",
- "sdk_test.go",
"sdk_library_test.go",
+ "sdk_test.go",
+ "sdk_version_test.go",
"system_modules_test.go",
"systemserver_classpath_fragment_test.go",
+ "test_spec_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/java/aapt2.go b/java/aapt2.go
index 3bb70b5..445e912 100644
--- a/java/aapt2.go
+++ b/java/aapt2.go
@@ -25,17 +25,23 @@
"android/soong/android"
)
+func isPathValueResource(res android.Path) bool {
+ subDir := filepath.Dir(res.String())
+ subDir, lastDir := filepath.Split(subDir)
+ return strings.HasPrefix(lastDir, "values")
+}
+
// Convert input resource file path to output file path.
// values-[config]/<file>.xml -> values-[config]_<file>.arsc.flat;
// For other resource file, just replace the last "/" with "_" and add .flat extension.
func pathToAapt2Path(ctx android.ModuleContext, res android.Path) android.WritablePath {
name := res.Base()
- subDir := filepath.Dir(res.String())
- subDir, lastDir := filepath.Split(subDir)
- if strings.HasPrefix(lastDir, "values") {
+ if isPathValueResource(res) {
name = strings.TrimSuffix(name, ".xml") + ".arsc"
}
+ subDir := filepath.Dir(res.String())
+ subDir, lastDir := filepath.Split(subDir)
name = lastDir + "_" + name + ".flat"
return android.PathForModuleOut(ctx, "aapt2", subDir, name)
}
@@ -63,7 +69,21 @@
// aapt2Compile compiles resources and puts the results in the requested directory.
func aapt2Compile(ctx android.ModuleContext, dir android.Path, paths android.Paths,
- flags []string) android.WritablePaths {
+ flags []string, productToFilter string) android.WritablePaths {
+ if productToFilter != "" && productToFilter != "default" {
+ // --filter-product leaves only product-specific resources. Product-specific resources only exist
+ // in value resources (values/*.xml), so filter value resource files only. Ignore other types of
+ // resources as they don't need to be in product characteristics RRO (and they will cause aapt2
+ // compile errors)
+ filteredPaths := android.Paths{}
+ for _, path := range paths {
+ if isPathValueResource(path) {
+ filteredPaths = append(filteredPaths, path)
+ }
+ }
+ paths = filteredPaths
+ flags = append([]string{"--filter-product " + productToFilter}, flags...)
+ }
// Shard the input paths so that they can be processed in parallel. If we shard them into too
// small chunks, the additional cost of spinning up aapt2 outweighs the performance gain. The
@@ -182,7 +202,8 @@
func aapt2Link(ctx android.ModuleContext,
packageRes, genJar, proguardOptions, rTxt android.WritablePath,
flags []string, deps android.Paths,
- compiledRes, compiledOverlay, assetPackages android.Paths, splitPackages android.WritablePaths) {
+ compiledRes, compiledOverlay, assetPackages android.Paths, splitPackages android.WritablePaths,
+ featureFlagsPaths android.Paths) {
var inFlags []string
@@ -235,6 +256,11 @@
})
}
+ for _, featureFlagsPath := range featureFlagsPaths {
+ deps = append(deps, featureFlagsPath)
+ inFlags = append(inFlags, "--feature-flags", "@"+featureFlagsPath.String())
+ }
+
// Note the absence of splitPackages. The caller is supposed to compose and provide --split flag
// values via the flags parameter when it wants to split outputs.
// TODO(b/174509108): Perhaps we can process it in this func while keeping the code reasonably
diff --git a/java/aar.go b/java/aar.go
index 0216196..f61fc83 100644
--- a/java/aar.go
+++ b/java/aar.go
@@ -17,14 +17,12 @@
import (
"fmt"
"path/filepath"
+ "slices"
"strconv"
"strings"
"android/soong/android"
- "android/soong/bazel"
"android/soong/dexpreopt"
- "android/soong/ui/metrics/bp2build_metrics_proto"
-
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -46,7 +44,7 @@
ctx.RegisterModuleType("android_library_import", AARImportFactory)
ctx.RegisterModuleType("android_library", AndroidLibraryFactory)
ctx.PostDepsMutators(func(ctx android.RegisterMutatorsContext) {
- ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator).Parallel()
+ ctx.TopDown("propagate_rro_enforcement", propagateRROEnforcementMutator)
})
}
@@ -66,6 +64,9 @@
// ones.
Aapt_include_all_resources *bool
+ // list of files to use as assets.
+ Assets []string `android:"path"`
+
// list of directories relative to the Blueprints file containing assets.
// Defaults to ["assets"] if a directory called assets exists. Set to []
// to disable the default.
@@ -99,29 +100,32 @@
// true if RRO is enforced for any of the dependent modules
RROEnforcedForDependent bool `blueprint:"mutated"`
+
+ // Filter only specified product and ignore other products
+ Filter_product *string `blueprint:"mutated"`
}
type aapt struct {
- aaptSrcJar android.Path
- transitiveAaptRJars android.Paths
- transitiveAaptResourcePackages android.Paths
- exportPackage android.Path
- manifestPath android.Path
- proguardOptionsFile android.Path
- rTxt android.Path
- rJar android.Path
- extraAaptPackagesFile android.Path
- mergedManifestFile android.Path
- noticeFile android.OptionalPath
- assetPackage android.OptionalPath
- isLibrary bool
- defaultManifestVersion string
- useEmbeddedNativeLibs bool
- useEmbeddedDex bool
- usesNonSdkApis bool
- hasNoCode bool
- LoggingParent string
- resourceFiles android.Paths
+ aaptSrcJar android.Path
+ transitiveAaptRJars android.Paths
+ transitiveAaptResourcePackagesFile android.Path
+ exportPackage android.Path
+ manifestPath android.Path
+ proguardOptionsFile android.Path
+ rTxt android.Path
+ rJar android.Path
+ extraAaptPackagesFile android.Path
+ mergedManifestFile android.Path
+ noticeFile android.OptionalPath
+ assetPackage android.OptionalPath
+ isLibrary bool
+ defaultManifestVersion string
+ useEmbeddedNativeLibs bool
+ useEmbeddedDex bool
+ usesNonSdkApis bool
+ hasNoCode bool
+ LoggingParent string
+ resourceFiles android.Paths
splitNames []string
splits []split
@@ -131,6 +135,10 @@
resourcesNodesDepSet *android.DepSet[*resourcesNode]
rroDirsDepSet *android.DepSet[rroDir]
manifestsDepSet *android.DepSet[android.Path]
+
+ manifestValues struct {
+ applicationId string
+ }
}
type split struct {
@@ -151,8 +159,12 @@
}
}
-func (a *aapt) useResourceProcessorBusyBox() bool {
- return BoolDefault(a.aaptProperties.Use_resource_processor, false)
+func (a *aapt) useResourceProcessorBusyBox(ctx android.BaseModuleContext) bool {
+ return BoolDefault(a.aaptProperties.Use_resource_processor, ctx.Config().UseResourceProcessorByDefault())
+}
+
+func (a *aapt) filterProduct() string {
+ return String(a.aaptProperties.Filter_product)
}
func (a *aapt) ExportPackage() android.Path {
@@ -192,6 +204,11 @@
linkFlags = append(linkFlags, a.aaptProperties.Aaptflags...)
// Find implicit or explicit asset and resource dirs
+ assets := android.PathsRelativeToModuleSourceDir(android.SourceInput{
+ Context: ctx,
+ Paths: a.aaptProperties.Assets,
+ IncludeDirs: false,
+ })
assetDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets")
resourceDirs := android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res")
resourceZips := android.PathsForModuleSrc(ctx, a.aaptProperties.Resource_zips)
@@ -226,6 +243,28 @@
assetDirStrings = append(assetDirStrings, filepath.Dir(a.noticeFile.Path().String()))
assetDeps = append(assetDeps, a.noticeFile.Path())
}
+ if len(assets) > 0 {
+ // aapt2 doesn't support adding individual asset files. Create a temp directory to hold asset
+ // files and pass it to aapt2.
+ tmpAssetDir := android.PathForModuleOut(ctx, "tmp_asset_dir")
+
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Command().
+ Text("rm -rf").Text(tmpAssetDir.String()).
+ Text("&&").
+ Text("mkdir -p").Text(tmpAssetDir.String())
+
+ for _, asset := range assets {
+ output := tmpAssetDir.Join(ctx, asset.Rel())
+ assetDeps = append(assetDeps, output)
+ rule.Command().Text("mkdir -p").Text(filepath.Dir(output.String()))
+ rule.Command().Text("cp").Input(asset).Output(output)
+ }
+
+ rule.Build("tmp_asset_dir", "tmp_asset_dir")
+
+ assetDirStrings = append(assetDirStrings, tmpAssetDir.String())
+ }
linkFlags = append(linkFlags, "--manifest "+manifestPath.String())
linkDeps = append(linkDeps, manifestPath)
@@ -301,23 +340,30 @@
CommandDeps: []string{"${config.Zip2ZipCmd}"},
})
-func (a *aapt) buildActions(ctx android.ModuleContext, sdkContext android.SdkContext,
- classLoaderContexts dexpreopt.ClassLoaderContextMap, excludedLibs []string,
- enforceDefaultTargetSdkVersion bool, extraLinkFlags ...string) {
+type aaptBuildActionOptions struct {
+ sdkContext android.SdkContext
+ classLoaderContexts dexpreopt.ClassLoaderContextMap
+ excludedLibs []string
+ enforceDefaultTargetSdkVersion bool
+ extraLinkFlags []string
+ aconfigTextFiles android.Paths
+}
- staticResourcesNodesDepSet, staticRRODirsDepSet, staticManifestsDepSet, sharedDeps, libFlags :=
- aaptLibs(ctx, sdkContext, classLoaderContexts)
+func (a *aapt) buildActions(ctx android.ModuleContext, opts aaptBuildActionOptions) {
+
+ staticResourcesNodesDepSet, sharedResourcesNodesDepSet, staticRRODirsDepSet, staticManifestsDepSet, sharedExportPackages, libFlags :=
+ aaptLibs(ctx, opts.sdkContext, opts.classLoaderContexts)
// Exclude any libraries from the supplied list.
- classLoaderContexts = classLoaderContexts.ExcludeLibs(excludedLibs)
+ opts.classLoaderContexts = opts.classLoaderContexts.ExcludeLibs(opts.excludedLibs)
// App manifest file
manifestFile := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
manifestSrcPath := android.PathForModuleSrc(ctx, manifestFile)
manifestPath := ManifestFixer(ctx, manifestSrcPath, ManifestFixerParams{
- SdkContext: sdkContext,
- ClassLoaderContexts: classLoaderContexts,
+ SdkContext: opts.sdkContext,
+ ClassLoaderContexts: opts.classLoaderContexts,
IsLibrary: a.isLibrary,
DefaultManifestVersion: a.defaultManifestVersion,
UseEmbeddedNativeLibs: a.useEmbeddedNativeLibs,
@@ -325,10 +371,11 @@
UseEmbeddedDex: a.useEmbeddedDex,
HasNoCode: a.hasNoCode,
LoggingParent: a.LoggingParent,
- EnforceDefaultTargetSdkVersion: enforceDefaultTargetSdkVersion,
+ EnforceDefaultTargetSdkVersion: opts.enforceDefaultTargetSdkVersion,
})
staticDeps := transitiveAarDeps(staticResourcesNodesDepSet.ToList())
+ sharedDeps := transitiveAarDeps(sharedResourcesNodesDepSet.ToList())
// Add additional manifest files to transitive manifests.
additionalManifests := android.PathsForModuleSrc(ctx, a.aaptProperties.Additional_manifests)
@@ -341,7 +388,12 @@
transitiveManifestPaths = append(transitiveManifestPaths, staticManifestsDepSet.ToList()...)
if len(transitiveManifestPaths) > 1 && !Bool(a.aaptProperties.Dont_merge_manifests) {
- a.mergedManifestFile = manifestMerger(ctx, transitiveManifestPaths[0], transitiveManifestPaths[1:], a.isLibrary)
+ manifestMergerParams := ManifestMergerParams{
+ staticLibManifests: transitiveManifestPaths[1:],
+ isLibrary: a.isLibrary,
+ packageName: a.manifestValues.applicationId,
+ }
+ a.mergedManifestFile = manifestMerger(ctx, transitiveManifestPaths[0], manifestMergerParams)
if !a.isLibrary {
// Only use the merged manifest for applications. For libraries, the transitive closure of manifests
// will be propagated to the final application and merged there. The merged manifest for libraries is
@@ -352,17 +404,17 @@
a.mergedManifestFile = manifestPath
}
- compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, sdkContext, manifestPath)
+ compileFlags, linkFlags, linkDeps, resDirs, overlayDirs, rroDirs, resZips := a.aapt2Flags(ctx, opts.sdkContext, manifestPath)
linkFlags = append(linkFlags, libFlags...)
- linkDeps = append(linkDeps, sharedDeps...)
+ linkDeps = append(linkDeps, sharedExportPackages...)
linkDeps = append(linkDeps, staticDeps.resPackages()...)
- linkFlags = append(linkFlags, extraLinkFlags...)
+ linkFlags = append(linkFlags, opts.extraLinkFlags...)
if a.isLibrary {
linkFlags = append(linkFlags, "--static-lib")
}
- if a.isLibrary && a.useResourceProcessorBusyBox() {
+ if a.isLibrary && a.useResourceProcessorBusyBox(ctx) {
// When building an android_library using ResourceProcessorBusyBox the resources are merged into
// package-res.apk with --merge-only, but --no-static-lib-packages is not used so that R.txt only
// contains resources from this library.
@@ -386,7 +438,7 @@
var compiledResDirs []android.Paths
for _, dir := range resDirs {
a.resourceFiles = append(a.resourceFiles, dir.files...)
- compiledResDirs = append(compiledResDirs, aapt2Compile(ctx, dir.dir, dir.files, compileFlags).Paths())
+ compiledResDirs = append(compiledResDirs, aapt2Compile(ctx, dir.dir, dir.files, compileFlags, a.filterProduct()).Paths())
}
for i, zip := range resZips {
@@ -401,7 +453,7 @@
// of transitiveStaticLibs.
transitiveStaticLibs := android.ReversePaths(staticDeps.resPackages())
- if a.isLibrary && a.useResourceProcessorBusyBox() {
+ if a.isLibrary && a.useResourceProcessorBusyBox(ctx) {
// When building an android_library with ResourceProcessorBusyBox enabled treat static library dependencies
// as imports. The resources from dependencies will not be merged into this module's package-res.apk, and
// instead modules depending on this module will reference package-res.apk from all transitive static
@@ -413,6 +465,11 @@
transitiveRJars = append(transitiveRJars, staticDep.rJar)
}
}
+ for _, sharedDep := range sharedDeps {
+ if sharedDep.usedResourceProcessor {
+ transitiveRJars = append(transitiveRJars, sharedDep.rJar)
+ }
+ }
} else {
// When building an app or building a library without ResourceProcessorBusyBox enabled all static
// dependencies are compiled into this module's package-res.apk as overlays.
@@ -440,7 +497,7 @@
}
for _, dir := range overlayDirs {
- compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files, compileFlags).Paths()...)
+ compiledOverlay = append(compiledOverlay, aapt2Compile(ctx, dir.dir, dir.files, compileFlags, a.filterProduct()).Paths()...)
}
var splitPackages android.WritablePaths
@@ -458,7 +515,7 @@
})
}
- if !a.useResourceProcessorBusyBox() {
+ if !a.useResourceProcessorBusyBox(ctx) {
// the subdir "android" is required to be filtered by package names
srcJar = android.PathForModuleGen(ctx, "android", "R.srcjar")
}
@@ -470,7 +527,8 @@
transitiveAssets = android.ReverseSliceInPlace(staticDeps.assets())
}
aapt2Link(ctx, packageRes, srcJar, proguardOptionsFile, rTxt,
- linkFlags, linkDeps, compiledRes, compiledOverlay, transitiveAssets, splitPackages)
+ linkFlags, linkDeps, compiledRes, compiledOverlay, transitiveAssets, splitPackages,
+ opts.aconfigTextFiles)
// Extract assets from the resource package output so that they can be used later in aapt2link
// for modules that depend on this one.
if android.PrefixInList(linkFlags, "-A ") {
@@ -484,9 +542,9 @@
a.assetPackage = android.OptionalPathForPath(assets)
}
- if a.useResourceProcessorBusyBox() {
+ if a.useResourceProcessorBusyBox(ctx) {
rJar := android.PathForModuleOut(ctx, "busybox/R.jar")
- resourceProcessorBusyBoxGenerateBinaryR(ctx, rTxt, a.mergedManifestFile, rJar, staticDeps, a.isLibrary)
+ resourceProcessorBusyBoxGenerateBinaryR(ctx, rTxt, a.mergedManifestFile, rJar, staticDeps, a.isLibrary, a.aaptProperties.Aaptflags)
aapt2ExtractExtraPackages(ctx, extraPackages, rJar)
transitiveRJars = append(transitiveRJars, rJar)
a.rJar = rJar
@@ -494,9 +552,16 @@
aapt2ExtractExtraPackages(ctx, extraPackages, srcJar)
}
+ transitiveAaptResourcePackages := staticDeps.resPackages().Strings()
+ transitiveAaptResourcePackages = slices.DeleteFunc(transitiveAaptResourcePackages, func(p string) bool {
+ return p == packageRes.String()
+ })
+ transitiveAaptResourcePackagesFile := android.PathForModuleOut(ctx, "transitive-res-packages")
+ android.WriteFileRule(ctx, transitiveAaptResourcePackagesFile, strings.Join(transitiveAaptResourcePackages, "\n"))
+
a.aaptSrcJar = srcJar
a.transitiveAaptRJars = transitiveRJars
- a.transitiveAaptResourcePackages = staticDeps.resPackages()
+ a.transitiveAaptResourcePackagesFile = transitiveAaptResourcePackagesFile
a.exportPackage = packageRes
a.manifestPath = manifestPath
a.proguardOptionsFile = proguardOptionsFile
@@ -512,7 +577,7 @@
rJar: a.rJar,
assets: a.assetPackage,
- usedResourceProcessor: a.useResourceProcessorBusyBox(),
+ usedResourceProcessor: a.useResourceProcessorBusyBox(ctx),
}).
Transitive(staticResourcesNodesDepSet).Build()
a.rroDirsDepSet = android.NewDepSetBuilder[rroDir](android.TOPOLOGICAL).
@@ -539,7 +604,7 @@
// using Bazel's ResourceProcessorBusyBox tool, which is faster than compiling the R.java files and
// supports producing classes for static dependencies that only include resources from that dependency.
func resourceProcessorBusyBoxGenerateBinaryR(ctx android.ModuleContext, rTxt, manifest android.Path,
- rJar android.WritablePath, transitiveDeps transitiveAarDeps, isLibrary bool) {
+ rJar android.WritablePath, transitiveDeps transitiveAarDeps, isLibrary bool, aaptFlags []string) {
var args []string
var deps android.Paths
@@ -556,6 +621,17 @@
args = append(args, "--finalFields=false")
}
+ for i, arg := range aaptFlags {
+ const AAPT_CUSTOM_PACKAGE = "--custom-package"
+ if strings.HasPrefix(arg, AAPT_CUSTOM_PACKAGE) {
+ pkg := strings.TrimSpace(strings.TrimPrefix(arg, AAPT_CUSTOM_PACKAGE))
+ if pkg == "" && i+1 < len(aaptFlags) {
+ pkg = aaptFlags[i+1]
+ }
+ args = append(args, "--packageForR "+pkg)
+ }
+ }
+
deps = append(deps, rTxt, manifest)
ctx.Build(pctx, android.BuildParams{
@@ -621,7 +697,7 @@
// aaptLibs collects libraries from dependencies and sdk_version and converts them into paths
func aaptLibs(ctx android.ModuleContext, sdkContext android.SdkContext, classLoaderContexts dexpreopt.ClassLoaderContextMap) (
- staticResourcesNodes *android.DepSet[*resourcesNode], staticRRODirs *android.DepSet[rroDir],
+ staticResourcesNodes, sharedResourcesNodes *android.DepSet[*resourcesNode], staticRRODirs *android.DepSet[rroDir],
staticManifests *android.DepSet[android.Path], sharedLibs android.Paths, flags []string) {
if classLoaderContexts == nil {
@@ -635,7 +711,8 @@
sharedLibs = append(sharedLibs, sdkDep.jars...)
}
- var resourcesNodeDepSets []*android.DepSet[*resourcesNode]
+ var staticResourcesNodeDepSets []*android.DepSet[*resourcesNode]
+ var sharedResourcesNodeDepSets []*android.DepSet[*resourcesNode]
rroDirsDepSetBuilder := android.NewDepSetBuilder[rroDir](android.TOPOLOGICAL)
manifestsDepSetBuilder := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL)
@@ -653,6 +730,7 @@
// Nothing, instrumentationForTag is treated as libTag for javac but not for aapt2.
case sdkLibTag, libTag:
if exportPackage != nil {
+ sharedResourcesNodeDepSets = append(sharedResourcesNodeDepSets, aarDep.ResourcesNodeDepSet())
sharedLibs = append(sharedLibs, exportPackage)
}
case frameworkResTag:
@@ -661,7 +739,7 @@
}
case staticLibTag:
if exportPackage != nil {
- resourcesNodeDepSets = append(resourcesNodeDepSets, aarDep.ResourcesNodeDepSet())
+ staticResourcesNodeDepSets = append(staticResourcesNodeDepSets, aarDep.ResourcesNodeDepSet())
rroDirsDepSetBuilder.Transitive(aarDep.RRODirsDepSet())
manifestsDepSetBuilder.Transitive(aarDep.ManifestsDepSet())
}
@@ -677,7 +755,9 @@
// dependencies) the highest priority dependency is listed first, but for resources the highest priority
// dependency has to be listed last.
staticResourcesNodes = android.NewDepSet(android.TOPOLOGICAL, nil,
- android.ReverseSliceInPlace(resourcesNodeDepSets))
+ android.ReverseSliceInPlace(staticResourcesNodeDepSets))
+ sharedResourcesNodes = android.NewDepSet(android.TOPOLOGICAL, nil,
+ android.ReverseSliceInPlace(sharedResourcesNodeDepSets))
staticRRODirs = rroDirsDepSetBuilder.Build()
staticManifests = manifestsDepSetBuilder.Build()
@@ -690,13 +770,12 @@
flags = append(flags, "-I "+sharedLib.String())
}
- return staticResourcesNodes, staticRRODirs, staticManifests, sharedLibs, flags
+ return staticResourcesNodes, sharedResourcesNodes, staticRRODirs, staticManifests, sharedLibs, flags
}
type AndroidLibrary struct {
Library
aapt
- android.BazelModuleBase
androidLibraryProperties androidLibraryProperties
@@ -729,15 +808,22 @@
func (a *AndroidLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
a.aapt.isLibrary = true
a.classLoaderContexts = a.usesLibrary.classLoaderContextForUsesLibDeps(ctx)
- a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts, nil, false)
+ a.aapt.buildActions(ctx,
+ aaptBuildActionOptions{
+ sdkContext: android.SdkContext(a),
+ classLoaderContexts: a.classLoaderContexts,
+ enforceDefaultTargetSdkVersion: false,
+ },
+ )
- a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ a.hideApexVariantFromMake = !apexInfo.IsForPlatform()
a.stem = proptools.StringDefault(a.overridableDeviceProperties.Stem, ctx.ModuleName())
ctx.CheckbuildFile(a.aapt.proguardOptionsFile)
ctx.CheckbuildFile(a.aapt.exportPackage)
- if a.useResourceProcessorBusyBox() {
+ if a.useResourceProcessorBusyBox(ctx) {
ctx.CheckbuildFile(a.aapt.rJar)
} else {
ctx.CheckbuildFile(a.aapt.aaptSrcJar)
@@ -750,13 +836,20 @@
a.linter.manifest = a.aapt.manifestPath
a.linter.resources = a.aapt.resourceFiles
- a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles,
- a.proguardOptionsFile)
+ proguardSpecInfo := a.collectProguardSpecInfo(ctx)
+ android.SetProvider(ctx, ProguardSpecInfoProvider, proguardSpecInfo)
+ exportedProguardFlagsFiles := proguardSpecInfo.ProguardFlagsFiles.ToList()
+ a.extraProguardFlagsFiles = append(a.extraProguardFlagsFiles, exportedProguardFlagsFiles...)
+ a.extraProguardFlagsFiles = append(a.extraProguardFlagsFiles, a.proguardOptionsFile)
+
+ combinedExportedProguardFlagFile := android.PathForModuleOut(ctx, "export_proguard_flags")
+ writeCombinedProguardFlagsFile(ctx, combinedExportedProguardFlagFile, exportedProguardFlagsFiles)
+ a.combinedExportedProguardFlagsFile = combinedExportedProguardFlagFile
var extraSrcJars android.Paths
var extraCombinedJars android.Paths
var extraClasspathJars android.Paths
- if a.useResourceProcessorBusyBox() {
+ if a.useResourceProcessorBusyBox(ctx) {
// When building a library with ResourceProcessorBusyBox enabled ResourceProcessorBusyBox for this
// library and each of the transitive static android_library dependencies has already created an
// R.class file for the appropriate package. Add all of those R.class files to the classpath.
@@ -777,23 +870,30 @@
ctx.CheckbuildFile(a.aarFile)
}
- proguardSpecInfo := a.collectProguardSpecInfo(ctx)
- ctx.SetProvider(ProguardSpecInfoProvider, proguardSpecInfo)
- a.exportedProguardFlagFiles = proguardSpecInfo.ProguardFlagsFiles.ToList()
-
prebuiltJniPackages := android.Paths{}
ctx.VisitDirectDeps(func(module android.Module) {
- if info, ok := ctx.OtherModuleProvider(module, JniPackageProvider).(JniPackageInfo); ok {
+ if info, ok := android.OtherModuleProvider(ctx, module, JniPackageProvider); ok {
prebuiltJniPackages = append(prebuiltJniPackages, info.JniPackages...)
}
})
if len(prebuiltJniPackages) > 0 {
- ctx.SetProvider(JniPackageProvider, JniPackageInfo{
+ android.SetProvider(ctx, JniPackageProvider, JniPackageInfo{
JniPackages: prebuiltJniPackages,
})
}
}
+func (a *AndroidLibrary) IDEInfo(dpInfo *android.IdeInfo) {
+ a.Library.IDEInfo(dpInfo)
+ a.aapt.IDEInfo(dpInfo)
+}
+
+func (a *aapt) IDEInfo(dpInfo *android.IdeInfo) {
+ if a.rJar != nil {
+ dpInfo.Jars = append(dpInfo.Jars, a.rJar.String())
+ }
+}
+
// android_library builds and links sources into a `.jar` file for the device along with Android resources.
//
// An android_library has a single variant that produces a `.jar` file containing `.class` files that were
@@ -813,7 +913,6 @@
android.InitApexModule(module)
InitJavaModule(module, android.DeviceSupported)
- android.InitBazelModule(module)
return module
}
@@ -852,7 +951,6 @@
android.ModuleBase
android.DefaultableModuleBase
android.ApexModuleBase
- android.BazelModuleBase
prebuilt android.Prebuilt
// Functionality common to Module and Import.
@@ -862,15 +960,15 @@
properties AARImportProperties
- classpathFile android.WritablePath
- proguardFlags android.WritablePath
- exportPackage android.WritablePath
- transitiveAaptResourcePackages android.Paths
- extraAaptPackagesFile android.WritablePath
- manifest android.WritablePath
- assetsPackage android.WritablePath
- rTxt android.WritablePath
- rJar android.WritablePath
+ classpathFile android.WritablePath
+ proguardFlags android.WritablePath
+ exportPackage android.WritablePath
+ transitiveAaptResourcePackagesFile android.Path
+ extraAaptPackagesFile android.WritablePath
+ manifest android.WritablePath
+ assetsPackage android.WritablePath
+ rTxt android.WritablePath
+ rJar android.WritablePath
resourcesNodesDepSet *android.DepSet[*resourcesNode]
manifestsDepSet *android.DepSet[android.Path]
@@ -882,6 +980,9 @@
sdkVersion android.SdkSpec
minSdkVersion android.ApiLevel
+
+ // Single aconfig "cache file" merged from this module and all dependencies.
+ mergedAconfigFiles map[string]android.Paths
}
var _ android.OutputFileProducer = (*AARImport)(nil)
@@ -983,7 +1084,7 @@
JniPackages android.Paths
}
-var JniPackageProvider = blueprint.NewProvider(JniPackageInfo{})
+var JniPackageProvider = blueprint.NewProvider[JniPackageInfo]()
// Unzip an AAR and extract the JNI libs for $archString.
var extractJNI = pctx.AndroidStaticRule("extractJNI",
@@ -993,7 +1094,7 @@
`jni_files=$$(find $outDir/jni -type f) && ` +
// print error message if there are no JNI libs for this arch
`[ -n "$$jni_files" ] || (echo "ERROR: no JNI libs found for arch ${archString}" && exit 1) && ` +
- `${config.SoongZipCmd} -o $out -P 'lib/${archString}' ` +
+ `${config.SoongZipCmd} -o $out -L 0 -P 'lib/${archString}' ` +
`-C $outDir/jni/${archString} $$(echo $$jni_files | xargs -n1 printf " -f %s")`,
CommandDeps: []string{"${config.SoongZipCmd}"},
},
@@ -1020,7 +1121,8 @@
a.sdkVersion = a.SdkVersion(ctx)
a.minSdkVersion = a.MinSdkVersion(ctx)
- a.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ a.hideApexVariantFromMake = !apexInfo.IsForPlatform()
aarName := ctx.ModuleName() + ".aar"
a.aarPath = android.PathForModuleSrc(ctx, a.properties.Aars[0])
@@ -1037,7 +1139,7 @@
aarRTxt := extractedAARDir.Join(ctx, "R.txt")
a.assetsPackage = android.PathForModuleOut(ctx, "assets.zip")
a.proguardFlags = extractedAARDir.Join(ctx, "proguard.txt")
- ctx.SetProvider(ProguardSpecInfoProvider, ProguardSpecInfo{
+ android.SetProvider(ctx, ProguardSpecInfoProvider, ProguardSpecInfo{
ProguardFlagsFiles: android.NewDepSet[android.Path](
android.POSTORDER,
android.Paths{a.proguardFlags},
@@ -1080,10 +1182,12 @@
linkFlags = append(linkFlags, "--manifest "+a.manifest.String())
linkDeps = append(linkDeps, a.manifest)
- staticResourcesNodesDepSet, staticRRODirsDepSet, staticManifestsDepSet, sharedLibs, libFlags :=
+ staticResourcesNodesDepSet, sharedResourcesNodesDepSet, staticRRODirsDepSet, staticManifestsDepSet, sharedLibs, libFlags :=
aaptLibs(ctx, android.SdkContext(a), nil)
+ _ = sharedResourcesNodesDepSet
_ = staticRRODirsDepSet
+
staticDeps := transitiveAarDeps(staticResourcesNodesDepSet.ToList())
linkDeps = append(linkDeps, sharedLibs...)
@@ -1101,10 +1205,10 @@
transitiveAssets := android.ReverseSliceInPlace(staticDeps.assets())
aapt2Link(ctx, a.exportPackage, nil, proguardOptionsFile, a.rTxt,
- linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil)
+ linkFlags, linkDeps, nil, overlayRes, transitiveAssets, nil, nil)
a.rJar = android.PathForModuleOut(ctx, "busybox/R.jar")
- resourceProcessorBusyBoxGenerateBinaryR(ctx, a.rTxt, a.manifest, a.rJar, nil, true)
+ resourceProcessorBusyBoxGenerateBinaryR(ctx, a.rTxt, a.manifest, a.rJar, nil, true, nil)
aapt2ExtractExtraPackages(ctx, a.extraAaptPackagesFile, a.rJar)
@@ -1131,10 +1235,16 @@
_ = staticManifestsDepSet
a.manifestsDepSet = manifestDepSetBuilder.Build()
- a.transitiveAaptResourcePackages = staticDeps.resPackages()
+ transitiveAaptResourcePackages := staticDeps.resPackages().Strings()
+ transitiveAaptResourcePackages = slices.DeleteFunc(transitiveAaptResourcePackages, func(p string) bool {
+ return p == a.exportPackage.String()
+ })
+ transitiveAaptResourcePackagesFile := android.PathForModuleOut(ctx, "transitive-res-packages")
+ android.WriteFileRule(ctx, transitiveAaptResourcePackagesFile, strings.Join(transitiveAaptResourcePackages, "\n"))
+ a.transitiveAaptResourcePackagesFile = transitiveAaptResourcePackagesFile
a.collectTransitiveHeaderJars(ctx)
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
+ android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
HeaderJars: android.PathsIfNonNil(a.classpathFile),
TransitiveLibsHeaderJars: a.transitiveLibsHeaderJars,
TransitiveStaticLibsHeaderJars: a.transitiveStaticLibsHeaderJars,
@@ -1162,11 +1272,12 @@
},
})
}
-
- ctx.SetProvider(JniPackageProvider, JniPackageInfo{
- JniPackages: a.jniPackages,
- })
}
+
+ android.SetProvider(ctx, JniPackageProvider, JniPackageInfo{
+ JniPackages: a.jniPackages,
+ })
+ android.CollectDependencyAconfigFiles(ctx, &a.mergedAconfigFiles)
}
func (a *AARImport) HeaderJars() android.Paths {
@@ -1177,7 +1288,7 @@
return android.Paths{a.classpathFile}
}
-func (a *AARImport) DexJarBuildPath() android.Path {
+func (a *AARImport) DexJarBuildPath(ctx android.ModuleErrorfContext) android.Path {
return nil
}
@@ -1216,165 +1327,5 @@
android.InitPrebuiltModule(module, &module.properties.Aars)
android.InitApexModule(module)
InitJavaModuleMultiTargets(module, android.DeviceSupported)
- android.InitBazelModule(module)
return module
}
-
-type bazelAapt struct {
- Manifest bazel.Label
- Resource_files bazel.LabelListAttribute
- Assets_dir bazel.StringAttribute
- Assets bazel.LabelListAttribute
-}
-
-type bazelAndroidLibrary struct {
- *javaLibraryAttributes
- *bazelAapt
-}
-
-type bazelAndroidLibraryImport struct {
- Aar bazel.Label
- Deps bazel.LabelListAttribute
- Exports bazel.LabelListAttribute
- Sdk_version bazel.StringAttribute
-}
-
-func (a *aapt) convertAaptAttrsWithBp2Build(ctx android.TopDownMutatorContext) (*bazelAapt, bool) {
- manifest := proptools.StringDefault(a.aaptProperties.Manifest, "AndroidManifest.xml")
-
- resourceFiles := bazel.LabelList{
- Includes: []bazel.Label{},
- }
- for _, dir := range android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Resource_dirs, "res") {
- files := android.RootToModuleRelativePaths(ctx, androidResourceGlob(ctx, dir))
- resourceFiles.Includes = append(resourceFiles.Includes, files...)
- }
-
- assetsDir := bazel.StringAttribute{}
- var assets bazel.LabelList
- for i, dir := range android.PathsWithOptionalDefaultForModuleSrc(ctx, a.aaptProperties.Asset_dirs, "assets") {
- if i > 0 {
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "multiple asset_dirs")
- return &bazelAapt{}, false
- }
- // Assets_dirs are relative to the module dir when specified, but if the default in used in
- // PathsWithOptionalDefaultForModuleSrc, then dir is relative to the top.
- assetsRelDir, error := filepath.Rel(ctx.ModuleDir(), dir.Rel())
- if error != nil {
- assetsRelDir = dir.Rel()
- }
- assetsDir.Value = proptools.StringPtr(assetsRelDir)
- assets = bazel.MakeLabelList(android.RootToModuleRelativePaths(ctx, androidResourceGlob(ctx, dir)))
-
- }
- return &bazelAapt{
- android.BazelLabelForModuleSrcSingle(ctx, manifest),
- bazel.MakeLabelListAttribute(resourceFiles),
- assetsDir,
- bazel.MakeLabelListAttribute(assets),
- }, true
-}
-
-func (a *AARImport) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- aars := android.BazelLabelForModuleSrcExcludes(ctx, a.properties.Aars, []string{})
- exportableStaticLibs := []string{}
- // TODO(b/240716882): investigate and handle static_libs deps that are not imports. They are not supported for export by Bazel.
- for _, depName := range a.properties.Static_libs {
- if dep, ok := ctx.ModuleFromName(depName); ok {
- switch dep.(type) {
- case *AARImport, *Import:
- exportableStaticLibs = append(exportableStaticLibs, depName)
- }
- }
- }
- name := android.RemoveOptionalPrebuiltPrefix(a.Name())
- deps := android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(android.CopyOf(append(a.properties.Static_libs, a.properties.Libs...))))
- exports := android.BazelLabelForModuleDeps(ctx, android.LastUniqueStrings(exportableStaticLibs))
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "aar_import",
- Bzl_load_location: "//build/bazel/rules/android:aar_import.bzl",
- },
- android.CommonAttributes{Name: name},
- &bazelAndroidLibraryImport{
- Aar: aars.Includes[0],
- Deps: bazel.MakeLabelListAttribute(deps),
- Exports: bazel.MakeLabelListAttribute(exports),
- Sdk_version: bazel.StringAttribute{Value: a.properties.Sdk_version},
- },
- )
-
- neverlink := true
- ctx.CreateBazelTargetModule(
- AndroidLibraryBazelTargetModuleProperties(),
- android.CommonAttributes{Name: name + "-neverlink"},
- &bazelAndroidLibrary{
- javaLibraryAttributes: &javaLibraryAttributes{
- Neverlink: bazel.BoolAttribute{Value: &neverlink},
- Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
- javaCommonAttributes: &javaCommonAttributes{
- Sdk_version: bazel.StringAttribute{Value: a.properties.Sdk_version},
- },
- },
- },
- )
-
-}
-func AndroidLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties {
- return bazel.BazelTargetModuleProperties{
- Rule_class: "android_library",
- Bzl_load_location: "//build/bazel/rules/android:android_library.bzl",
- }
-}
-
-func (a *AndroidLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- commonAttrs, bp2buildInfo, supported := a.convertLibraryAttrsBp2Build(ctx)
- if !supported {
- return
- }
-
- depLabels := bp2buildInfo.DepLabels
-
- deps := depLabels.Deps
- if !commonAttrs.Srcs.IsEmpty() {
- deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
- } else if !depLabels.Deps.IsEmpty() {
- ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
- }
- name := a.Name()
- props := AndroidLibraryBazelTargetModuleProperties()
-
- aaptAttrs, supported := a.convertAaptAttrsWithBp2Build(ctx)
- if !supported {
- return
- }
- ctx.CreateBazelTargetModule(
- props,
- android.CommonAttributes{Name: name},
- &bazelAndroidLibrary{
- &javaLibraryAttributes{
- javaCommonAttributes: commonAttrs,
- Deps: deps,
- Exports: depLabels.StaticDeps,
- },
- aaptAttrs,
- },
- )
-
- neverlink := true
- ctx.CreateBazelTargetModule(
- props,
- android.CommonAttributes{Name: name + "-neverlink"},
- &bazelAndroidLibrary{
- javaLibraryAttributes: &javaLibraryAttributes{
- Neverlink: bazel.BoolAttribute{Value: &neverlink},
- Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
- javaCommonAttributes: &javaCommonAttributes{
- Sdk_version: bazel.StringAttribute{Value: a.deviceProperties.Sdk_version},
- Java_version: bazel.StringAttribute{Value: a.properties.Java_version},
- },
- },
- },
- )
-}
diff --git a/java/aar_test.go b/java/aar_test.go
index 8afa039..4d4e5d0 100644
--- a/java/aar_test.go
+++ b/java/aar_test.go
@@ -52,7 +52,7 @@
appMod := ctx.Module(tc.name, "android_common")
appTestMod := ctx.ModuleForTests(tc.name, "android_common")
- info, ok := ctx.ModuleProvider(appMod, JniPackageProvider).(JniPackageInfo)
+ info, ok := android.SingletonModuleProvider(ctx, appMod, JniPackageProvider)
if !ok {
t.Errorf("expected android_library_import to have JniPackageProvider")
}
diff --git a/java/android_manifest.go b/java/android_manifest.go
index f2ebfa6..082b00e 100644
--- a/java/android_manifest.go
+++ b/java/android_manifest.go
@@ -200,13 +200,24 @@
return fixedManifest.WithoutRel()
}
-func manifestMerger(ctx android.ModuleContext, manifest android.Path, staticLibManifests android.Paths,
- isLibrary bool) android.Path {
+type ManifestMergerParams struct {
+ staticLibManifests android.Paths
+ isLibrary bool
+ packageName string
+}
- var args string
- if !isLibrary {
+func manifestMerger(ctx android.ModuleContext, manifest android.Path,
+ params ManifestMergerParams) android.Path {
+
+ var args []string
+ if !params.isLibrary {
// Follow Gradle's behavior, only pass --remove-tools-declarations when merging app manifests.
- args = "--remove-tools-declarations"
+ args = append(args, "--remove-tools-declarations")
+ }
+
+ packageName := params.packageName
+ if packageName != "" {
+ args = append(args, "--property PACKAGE="+packageName)
}
mergedManifest := android.PathForModuleOut(ctx, "manifest_merger", "AndroidManifest.xml")
@@ -214,11 +225,11 @@
Rule: manifestMergerRule,
Description: "merge manifest",
Input: manifest,
- Implicits: staticLibManifests,
+ Implicits: params.staticLibManifests,
Output: mergedManifest,
Args: map[string]string{
- "libs": android.JoinWithPrefix(staticLibManifests.Strings(), "--libs "),
- "args": args,
+ "libs": android.JoinWithPrefix(params.staticLibManifests.Strings(), "--libs "),
+ "args": strings.Join(args, " "),
},
})
diff --git a/java/android_manifest_test.go b/java/android_manifest_test.go
index b12d778..5909b1e 100644
--- a/java/android_manifest_test.go
+++ b/java/android_manifest_test.go
@@ -15,8 +15,9 @@
package java
import (
- "android/soong/android"
"testing"
+
+ "android/soong/android"
)
func TestManifestMerger(t *testing.T) {
@@ -77,10 +78,7 @@
}
`
- result := android.GroupFixturePreparers(
- PrepareForTestWithJavaDefaultModules,
- PrepareForTestWithOverlayBuildComponents,
- ).RunTestWithBp(t, bp)
+ result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, bp)
manifestMergerRule := result.ModuleForTests("app", "android_common").Rule("manifestMerger")
android.AssertPathRelativeToTopEquals(t, "main manifest",
@@ -101,3 +99,38 @@
},
manifestMergerRule.Implicits)
}
+
+func TestManifestValuesApplicationIdSetsPackageName(t *testing.T) {
+ bp := `
+ android_test {
+ name: "test",
+ sdk_version: "current",
+ srcs: ["app/app.java"],
+ manifest: "test/AndroidManifest.xml",
+ additional_manifests: ["test/AndroidManifest2.xml"],
+ static_libs: ["direct"],
+ test_suites: ["device-tests"],
+ manifest_values: {
+ applicationId: "new_package_name"
+ },
+ }
+
+ android_library {
+ name: "direct",
+ sdk_version: "current",
+ srcs: ["direct/direct.java"],
+ resource_dirs: ["direct/res"],
+ manifest: "direct/AndroidManifest.xml",
+ additional_manifests: ["direct/AndroidManifest2.xml"],
+ }
+
+ `
+
+ result := PrepareForTestWithJavaDefaultModules.RunTestWithBp(t, bp)
+
+ manifestMergerRule := result.ModuleForTests("test", "android_common").Rule("manifestMerger")
+ android.AssertStringMatches(t,
+ "manifest merger args",
+ manifestMergerRule.Args["args"],
+ "--property PACKAGE=new_package_name")
+}
diff --git a/java/android_resources.go b/java/android_resources.go
index 8c5908f..038a260 100644
--- a/java/android_resources.go
+++ b/java/android_resources.go
@@ -21,14 +21,6 @@
"android/soong/android"
)
-func init() {
- registerOverlayBuildComponents(android.InitRegistrationContext)
-}
-
-func registerOverlayBuildComponents(ctx android.RegistrationContext) {
- ctx.RegisterPreSingletonType("overlay", OverlaySingletonFactory)
-}
-
var androidResourceIgnoreFilenames = []string{
".svn",
".git",
@@ -84,7 +76,38 @@
func overlayResourceGlob(ctx android.ModuleContext, a *aapt, dir android.Path) (res []globbedResourceDir,
rroDirs []rroDir) {
- overlayData := ctx.Config().Get(overlayDataKey).([]overlayGlobResult)
+ overlayData := ctx.Config().Once(overlayDataKey, func() interface{} {
+ var overlayData []overlayGlobResult
+
+ appendOverlayData := func(overlayDirs []string, t overlayType) {
+ for i := range overlayDirs {
+ // Iterate backwards through the list of overlay directories so that the later, lower-priority
+ // directories in the list show up earlier in the command line to aapt2.
+ overlay := overlayDirs[len(overlayDirs)-1-i]
+ var result overlayGlobResult
+ result.dir = overlay
+ result.overlayType = t
+
+ files, err := ctx.GlobWithDeps(filepath.Join(overlay, "**/*"), androidResourceIgnoreFilenames)
+ if err != nil {
+ ctx.ModuleErrorf("failed to glob resource dir %q: %s", overlay, err.Error())
+ continue
+ }
+ var paths android.Paths
+ for _, f := range files {
+ if !strings.HasSuffix(f, "/") {
+ paths = append(paths, android.PathForSource(ctx, f))
+ }
+ }
+ result.paths = android.PathsToDirectorySortedPaths(paths)
+ overlayData = append(overlayData, result)
+ }
+ }
+
+ appendOverlayData(ctx.Config().DeviceResourceOverlays(), device)
+ appendOverlayData(ctx.Config().ProductResourceOverlays(), product)
+ return overlayData
+ }).([]overlayGlobResult)
// Runtime resource overlays (RRO) may be turned on by the product config for some modules
rroEnabled := a.IsRROEnforced(ctx)
@@ -110,44 +133,3 @@
return res, rroDirs
}
-
-func OverlaySingletonFactory() android.Singleton {
- return overlaySingleton{}
-}
-
-type overlaySingleton struct{}
-
-func (overlaySingleton) GenerateBuildActions(ctx android.SingletonContext) {
- var overlayData []overlayGlobResult
-
- appendOverlayData := func(overlayDirs []string, t overlayType) {
- for i := range overlayDirs {
- // Iterate backwards through the list of overlay directories so that the later, lower-priority
- // directories in the list show up earlier in the command line to aapt2.
- overlay := overlayDirs[len(overlayDirs)-1-i]
- var result overlayGlobResult
- result.dir = overlay
- result.overlayType = t
-
- files, err := ctx.GlobWithDeps(filepath.Join(overlay, "**/*"), androidResourceIgnoreFilenames)
- if err != nil {
- ctx.Errorf("failed to glob resource dir %q: %s", overlay, err.Error())
- continue
- }
- var paths android.Paths
- for _, f := range files {
- if !strings.HasSuffix(f, "/") {
- paths = append(paths, android.PathForSource(ctx, f))
- }
- }
- result.paths = android.PathsToDirectorySortedPaths(paths)
- overlayData = append(overlayData, result)
- }
- }
-
- appendOverlayData(ctx.Config().DeviceResourceOverlays(), device)
- appendOverlayData(ctx.Config().ProductResourceOverlays(), product)
- ctx.Config().Once(overlayDataKey, func() interface{} {
- return overlayData
- })
-}
diff --git a/java/androidmk.go b/java/androidmk.go
index b7e2d2f..b7df9bf 100644
--- a/java/androidmk.go
+++ b/java/androidmk.go
@@ -20,6 +20,8 @@
"strings"
"android/soong/android"
+
+ "github.com/google/blueprint/proptools"
)
func (library *Library) AndroidMkEntriesHostDex() android.AndroidMkEntries {
@@ -79,7 +81,7 @@
} 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 if library.properties.Headers_only {
+ } else if proptools.Bool(library.properties.Headers_only) {
// If generating headers only then don't expose to Make.
entriesList = append(entriesList, android.AndroidMkEntries{Disabled: true})
} else {
@@ -126,8 +128,7 @@
if library.dexpreopter.configPath != nil {
entries.SetPath("LOCAL_SOONG_DEXPREOPT_CONFIG", library.dexpreopter.configPath)
}
-
- entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", library.getTransitiveAconfigFiles().ToList())
+ android.SetAconfigFileMkEntries(&library.ModuleBase, entries, library.mergedAconfigFiles)
},
},
})
@@ -205,16 +206,13 @@
func (prebuilt *Import) AndroidMkEntries() []android.AndroidMkEntries {
if prebuilt.hideApexVariantFromMake {
- // For a library imported from a prebuilt APEX, we don't need a Make module for itself, as we
- // don't need to install it. However, we need to add its dexpreopt outputs as sub-modules, if it
- // is preopted.
- dexpreoptEntries := prebuilt.dexpreopter.AndroidMkEntriesForApex()
- return append(dexpreoptEntries, android.AndroidMkEntries{Disabled: true})
+ return []android.AndroidMkEntries{}
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
- Class: "JAVA_LIBRARIES",
- OutputFile: android.OptionalPathForPath(prebuilt.combinedClasspathFile),
- Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
+ Class: "JAVA_LIBRARIES",
+ OverrideName: prebuilt.BaseModuleName(),
+ OutputFile: android.OptionalPathForPath(prebuilt.combinedClasspathFile),
+ Include: "$(BUILD_SYSTEM)/soong_java_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_UNINSTALLABLE_MODULE", !Bool(prebuilt.properties.Installable))
@@ -272,7 +270,7 @@
entries.SetPath("LOCAL_SOONG_HEADER_JAR", prebuilt.classpathFile)
entries.SetPath("LOCAL_SOONG_CLASSES_JAR", prebuilt.classpathFile)
entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", prebuilt.exportPackage)
- entries.SetPaths("LOCAL_SOONG_TRANSITIVE_RES_PACKAGES", prebuilt.transitiveAaptResourcePackages)
+ entries.SetPath("LOCAL_SOONG_TRANSITIVE_RES_PACKAGES", prebuilt.transitiveAaptResourcePackagesFile)
entries.SetPath("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", prebuilt.proguardFlags)
entries.SetPath("LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES", prebuilt.extraAaptPackagesFile)
entries.SetPath("LOCAL_FULL_MANIFEST_FILE", prebuilt.manifest)
@@ -304,7 +302,7 @@
if len(binary.dexpreopter.builtInstalled) > 0 {
entries.SetString("LOCAL_SOONG_BUILT_INSTALLED", binary.dexpreopter.builtInstalled)
}
- entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", binary.getTransitiveAconfigFiles().ToList())
+ android.SetAconfigFileMkEntries(&binary.ModuleBase, entries, binary.mergedAconfigFiles)
},
},
ExtraFooters: []android.AndroidMkExtraFootersFunc{
@@ -341,10 +339,15 @@
Disabled: true,
}}
}
+ var required []string
+ if proptools.Bool(app.appProperties.Generate_product_characteristics_rro) {
+ required = []string{app.productCharacteristicsRROPackageName()}
+ }
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "APPS",
OutputFile: android.OptionalPathForPath(app.outputFile),
Include: "$(BUILD_SYSTEM)/soong_app_prebuilt.mk",
+ Required: required,
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
// App module names can be overridden.
@@ -452,7 +455,7 @@
entries.SetOptionalPaths("LOCAL_SOONG_LINT_REPORTS", app.linter.reports)
if app.Name() != "framework-res" {
- entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", app.getTransitiveAconfigFiles().ToList())
+ android.SetAconfigFileMkEntries(&app.ModuleBase, entries, app.mergedAconfigFiles)
}
},
},
@@ -525,12 +528,12 @@
}
entries.SetPath("LOCAL_SOONG_RESOURCE_EXPORT_PACKAGE", a.exportPackage)
- entries.SetPaths("LOCAL_SOONG_TRANSITIVE_RES_PACKAGES", a.transitiveAaptResourcePackages)
+ entries.SetPath("LOCAL_SOONG_TRANSITIVE_RES_PACKAGES", a.transitiveAaptResourcePackagesFile)
entries.SetPath("LOCAL_SOONG_STATIC_LIBRARY_EXTRA_PACKAGES", a.extraAaptPackagesFile)
entries.SetPath("LOCAL_FULL_MANIFEST_FILE", a.mergedManifestFile)
- entries.AddStrings("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", a.exportedProguardFlagFiles.Strings()...)
+ entries.SetPath("LOCAL_SOONG_EXPORT_PROGUARD_FLAGS", a.combinedExportedProguardFlagsFile)
entries.SetBoolIfTrue("LOCAL_UNINSTALLABLE_MODULE", true)
- entries.SetOptionalPaths("LOCAL_ACONFIG_FILES", a.getTransitiveAconfigFiles().ToList())
+ android.SetAconfigFileMkEntries(&a.ModuleBase, entries, a.mergedAconfigFiles)
})
return entriesList
@@ -546,8 +549,8 @@
if BoolDefault(jd.properties.Installable, true) {
entries.SetPath("LOCAL_DROIDDOC_DOC_ZIP", jd.docZip)
}
- if jd.stubsSrcJar != nil {
- entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", jd.stubsSrcJar)
+ if jd.exportableStubsSrcJar != nil {
+ entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", jd.exportableStubsSrcJar)
}
},
},
@@ -585,7 +588,7 @@
outputFile = android.OptionalPathForPath(dstubs.apiFile)
}
if !outputFile.Valid() {
- outputFile = android.OptionalPathForPath(dstubs.apiVersionsXml)
+ outputFile = android.OptionalPathForPath(dstubs.everythingArtifacts.apiVersionsXml)
}
return []android.AndroidMkEntries{android.AndroidMkEntries{
Class: "JAVA_LIBRARIES",
@@ -593,17 +596,17 @@
Include: "$(BUILD_SYSTEM)/soong_droiddoc_prebuilt.mk",
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
- if dstubs.Javadoc.stubsSrcJar != nil {
- entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", dstubs.Javadoc.stubsSrcJar)
+ if dstubs.Javadoc.exportableStubsSrcJar != nil {
+ entries.SetPath("LOCAL_DROIDDOC_STUBS_SRCJAR", dstubs.Javadoc.exportableStubsSrcJar)
}
- if dstubs.apiVersionsXml != nil {
- entries.SetPath("LOCAL_DROIDDOC_API_VERSIONS_XML", dstubs.apiVersionsXml)
+ if dstubs.everythingArtifacts.apiVersionsXml != nil {
+ entries.SetPath("LOCAL_DROIDDOC_API_VERSIONS_XML", dstubs.exportableArtifacts.apiVersionsXml)
}
- if dstubs.annotationsZip != nil {
- entries.SetPath("LOCAL_DROIDDOC_ANNOTATIONS_ZIP", dstubs.annotationsZip)
+ if dstubs.everythingArtifacts.annotationsZip != nil {
+ entries.SetPath("LOCAL_DROIDDOC_ANNOTATIONS_ZIP", dstubs.exportableArtifacts.annotationsZip)
}
- if dstubs.metadataZip != nil {
- entries.SetPath("LOCAL_DROIDDOC_METADATA_ZIP", dstubs.metadataZip)
+ if dstubs.everythingArtifacts.metadataZip != nil {
+ entries.SetPath("LOCAL_DROIDDOC_METADATA_ZIP", dstubs.exportableArtifacts.metadataZip)
}
},
},
diff --git a/java/app.go b/java/app.go
index d533b71..0c56d81 100755
--- a/java/app.go
+++ b/java/app.go
@@ -22,11 +22,12 @@
"path/filepath"
"strings"
+ "android/soong/testing"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel"
"android/soong/cc"
"android/soong/dexpreopt"
"android/soong/genrule"
@@ -129,6 +130,16 @@
// Specifies the file that contains the allowlist for this app.
Privapp_allowlist *string `android:"path"`
+
+ // If set, create an RRO package which contains only resources having PRODUCT_CHARACTERISTICS
+ // and install the RRO package to /product partition, instead of passing --product argument
+ // to aapt2. Default is false.
+ // Setting this will make this APK identical to all targets, regardless of
+ // PRODUCT_CHARACTERISTICS.
+ Generate_product_characteristics_rro *bool
+
+ ProductCharacteristicsRROPackageName *string `blueprint:"mutated"`
+ ProductCharacteristicsRROManifestModuleName *string `blueprint:"mutated"`
}
// android_app properties that can be overridden by override_android_app
@@ -158,10 +169,12 @@
// binaries would be installed by default (in PRODUCT_PACKAGES) the other binary will be removed
// from PRODUCT_PACKAGES.
Overrides []string
+
+ // Names of aconfig_declarations modules that specify aconfig flags that the app depends on.
+ Flags_packages []string
}
type AndroidApp struct {
- android.BazelModuleBase
Library
aapt
android.OverridableModuleBase
@@ -304,9 +317,20 @@
`must be names of android_app_certificate modules in the form ":module"`)
}
}
+
+ for _, aconfig_declaration := range a.overridableAppProperties.Flags_packages {
+ ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfig_declaration)
+ }
}
func (a *AndroidTestHelperApp) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ applicationId := a.appTestHelperAppProperties.Manifest_values.ApplicationId
+ if applicationId != nil {
+ if a.overridableAppProperties.Package_name != nil {
+ ctx.PropertyErrorf("manifest_values.applicationId", "property is not supported when property package_name is set.")
+ }
+ a.aapt.manifestValues.applicationId = *applicationId
+ }
a.generateAndroidBuildActions(ctx)
}
@@ -386,7 +410,7 @@
ctx.PropertyErrorf("min_sdk_version", "invalid value %q: %s", a.MinSdkVersion(ctx), err)
}
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
return (minSdkVersion.FinalOrFutureInt() >= 23 && Bool(a.appProperties.Use_embedded_native_libs)) ||
!apexInfo.IsForPlatform()
}
@@ -407,11 +431,11 @@
return false
}
- return shouldUncompressDex(ctx, &a.dexpreopter)
+ return shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &a.dexpreopter)
}
func (a *AndroidApp) shouldEmbedJnis(ctx android.BaseModuleContext) bool {
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
return ctx.Config().UnbundledBuild() || Bool(a.appProperties.Use_embedded_native_libs) ||
!apexInfo.IsForPlatform() || a.appProperties.AlwaysPackageNativeLibs
}
@@ -446,8 +470,9 @@
aaptLinkFlags := []string{}
// Add TARGET_AAPT_CHARACTERISTICS values to AAPT link flags if they exist and --product flags were not provided.
+ autogenerateRRO := proptools.Bool(a.appProperties.Generate_product_characteristics_rro)
hasProduct := android.PrefixInList(a.aaptProperties.Aaptflags, "--product")
- if !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 {
+ if !autogenerateRRO && !hasProduct && len(ctx.Config().ProductAAPTCharacteristics()) > 0 {
aaptLinkFlags = append(aaptLinkFlags, "--product", ctx.Config().ProductAAPTCharacteristics())
}
@@ -480,8 +505,29 @@
if a.Updatable() {
a.aapt.defaultManifestVersion = android.DefaultUpdatableModuleVersion
}
- a.aapt.buildActions(ctx, android.SdkContext(a), a.classLoaderContexts,
- a.usesLibraryProperties.Exclude_uses_libs, a.enforceDefaultTargetSdkVersion(), aaptLinkFlags...)
+
+ var aconfigTextFilePaths android.Paths
+ ctx.VisitDirectDepsWithTag(aconfigDeclarationTag, func(dep android.Module) {
+ if provider, ok := android.OtherModuleProvider(ctx, dep, android.AconfigDeclarationsProviderKey); ok {
+ aconfigTextFilePaths = append(aconfigTextFilePaths, provider.IntermediateDumpOutputPath)
+ } else {
+ ctx.ModuleErrorf("Only aconfig_declarations module type is allowed for "+
+ "flags_packages property, but %s is not aconfig_declarations module type",
+ dep.Name(),
+ )
+ }
+ })
+
+ a.aapt.buildActions(ctx,
+ aaptBuildActionOptions{
+ sdkContext: android.SdkContext(a),
+ classLoaderContexts: a.classLoaderContexts,
+ excludedLibs: a.usesLibraryProperties.Exclude_uses_libs,
+ enforceDefaultTargetSdkVersion: a.enforceDefaultTargetSdkVersion(),
+ extraLinkFlags: aaptLinkFlags,
+ aconfigTextFiles: aconfigTextFilePaths,
+ },
+ )
// apps manifests are handled by aapt, don't let Module see them
a.properties.Manifest = nil
@@ -490,7 +536,7 @@
func (a *AndroidApp) proguardBuildActions(ctx android.ModuleContext) {
var staticLibProguardFlagFiles android.Paths
ctx.VisitDirectDeps(func(m android.Module) {
- depProguardInfo := ctx.OtherModuleProvider(m, ProguardSpecInfoProvider).(ProguardSpecInfo)
+ depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider)
staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, depProguardInfo.UnconditionallyExportedProguardFlags.ToList()...)
if ctx.OtherModuleDependencyTag(m) == staticLibTag {
staticLibProguardFlagFiles = append(staticLibProguardFlagFiles, depProguardInfo.ProguardFlagsFiles.ToList()...)
@@ -499,8 +545,8 @@
staticLibProguardFlagFiles = android.FirstUniquePaths(staticLibProguardFlagFiles)
- a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, staticLibProguardFlagFiles...)
- a.Module.extraProguardFlagFiles = append(a.Module.extraProguardFlagFiles, a.proguardOptionsFile)
+ a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, staticLibProguardFlagFiles...)
+ a.Module.extraProguardFlagsFiles = append(a.Module.extraProguardFlagsFiles, a.proguardOptionsFile)
}
func (a *AndroidApp) installPath(ctx android.ModuleContext) android.InstallPath {
@@ -517,7 +563,7 @@
return android.PathForModuleInstall(ctx, installDir, a.installApkName+".apk")
}
-func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) android.Path {
+func (a *AndroidApp) dexBuildActions(ctx android.ModuleContext) (android.Path, android.Path) {
a.dexpreopter.installPath = a.installPath(ctx)
a.dexpreopter.isApp = true
if a.dexProperties.Uncompress_dex == nil {
@@ -530,11 +576,19 @@
a.dexpreopter.manifestFile = a.mergedManifestFile
a.dexpreopter.preventInstall = a.appProperties.PreventInstall
+ var packageResources = a.exportPackage
+
if ctx.ModuleName() != "framework-res" {
+ if Bool(a.dexProperties.Optimize.Shrink_resources) {
+ protoFile := android.PathForModuleOut(ctx, packageResources.Base()+".proto.apk")
+ aapt2Convert(ctx, protoFile, packageResources, "proto")
+ a.dexer.resourcesInput = android.OptionalPathForPath(protoFile)
+ }
+
var extraSrcJars android.Paths
var extraClasspathJars android.Paths
var extraCombinedJars android.Paths
- if a.useResourceProcessorBusyBox() {
+ if a.useResourceProcessorBusyBox(ctx) {
// When building an app with ResourceProcessorBusyBox enabled ResourceProcessorBusyBox has already
// created R.class files that provide IDs for resources in busybox/R.jar. Pass that file in the
// classpath when compiling everything else, and add it to the final classes jar.
@@ -548,9 +602,14 @@
}
a.Module.compile(ctx, extraSrcJars, extraClasspathJars, extraCombinedJars)
+ if Bool(a.dexProperties.Optimize.Shrink_resources) {
+ binaryResources := android.PathForModuleOut(ctx, packageResources.Base()+".binary.out.apk")
+ aapt2Convert(ctx, binaryResources, a.dexer.resourcesOutput.Path(), "binary")
+ packageResources = binaryResources
+ }
}
- return a.dexJarFile.PathOrNil()
+ return a.dexJarFile.PathOrNil(), packageResources
}
func (a *AndroidApp) jniBuildActions(jniLibs []jniLib, prebuiltJniPackages android.Paths, ctx android.ModuleContext) android.WritablePath {
@@ -685,7 +744,8 @@
func (a *AndroidApp) generateAndroidBuildActions(ctx android.ModuleContext) {
var apkDeps android.Paths
- if !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() {
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ if !apexInfo.IsForPlatform() {
a.hideApexVariantFromMake = true
}
@@ -735,7 +795,6 @@
// Process all building blocks, from AAPT to certificates.
a.aaptBuildActions(ctx)
-
// The decision to enforce <uses-library> checks is made before adding implicit SDK libraries.
a.usesLibrary.freezeEnforceUsesLibraries()
@@ -761,7 +820,7 @@
a.linter.resources = a.aapt.resourceFiles
a.linter.buildModuleReportZip = ctx.Config().UnbundledBuildApps()
- dexJarFile := a.dexBuildActions(ctx)
+ dexJarFile, packageResources := a.dexBuildActions(ctx)
jniLibs, prebuiltJniPackages, certificates := collectAppDeps(ctx, a, a.shouldEmbedJnis(ctx), !Bool(a.appProperties.Jni_uses_platform_apis))
jniJarFile := a.jniBuildActions(jniLibs, prebuiltJniPackages, ctx)
@@ -785,7 +844,7 @@
}
rotationMinSdkVersion := String(a.overridableAppProperties.RotationMinSdkVersion)
- CreateAndSignAppPackage(ctx, packageFile, a.exportPackage, jniJarFile, dexJarFile, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion, Bool(a.dexProperties.Optimize.Shrink_resources))
+ CreateAndSignAppPackage(ctx, packageFile, packageResources, jniJarFile, dexJarFile, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion)
a.outputFile = packageFile
if v4SigningRequested {
a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)
@@ -814,7 +873,7 @@
if v4SigningRequested {
v4SignatureFile = android.PathForModuleOut(ctx, a.installApkName+"_"+split.suffix+".apk.idsig")
}
- CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion, false)
+ CreateAndSignAppPackage(ctx, packageFile, split.path, nil, nil, certificates, apkDeps, v4SignatureFile, lineageFile, rotationMinSdkVersion)
a.extraOutputFiles = append(a.extraOutputFiles, packageFile)
if v4SigningRequested {
a.extraOutputFiles = append(a.extraOutputFiles, v4SignatureFile)
@@ -831,8 +890,6 @@
a.privAppAllowlist = android.OptionalPathForPath(allowlist)
}
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
-
// Install the app package.
shouldInstallAppPackage := (Bool(a.Module.properties.Installable) || ctx.Host()) && apexInfo.IsForPlatform() && !a.appProperties.PreventInstall
if shouldInstallAppPackage {
@@ -842,7 +899,7 @@
ctx.InstallFile(allowlistInstallPath, allowlistInstallFilename, a.privAppAllowlist.Path())
}
- var extraInstalledPaths android.Paths
+ var extraInstalledPaths android.InstallPaths
for _, extra := range a.extraOutputFiles {
installed := ctx.InstallFile(a.installDir, extra.Base(), extra)
extraInstalledPaths = append(extraInstalledPaths, installed)
@@ -916,7 +973,7 @@
return shouldCollectRecursiveNativeDeps
}
- if info, ok := ctx.OtherModuleProvider(module, JniPackageProvider).(JniPackageInfo); ok {
+ if info, ok := android.OtherModuleProvider(ctx, module, JniPackageProvider); ok {
prebuiltJniPackages = append(prebuiltJniPackages, info.JniPackages...)
}
@@ -1041,6 +1098,8 @@
}
case ".export-package.apk":
return []android.Path{a.exportPackage}, nil
+ case ".manifest.xml":
+ return []android.Path{a.aapt.manifestPath}, nil
}
return a.Library.OutputFiles(tag)
}
@@ -1049,7 +1108,7 @@
return Bool(a.appProperties.Privileged)
}
-func (a *AndroidApp) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool {
+func (a *AndroidApp) IsNativeCoverageNeeded(ctx android.IncomingTransitionContext) bool {
return ctx.Device() && ctx.DeviceConfig().NativeCoverageEnabled()
}
@@ -1065,6 +1124,19 @@
var _ cc.Coverage = (*AndroidApp)(nil)
+func (a *AndroidApp) IDEInfo(dpInfo *android.IdeInfo) {
+ a.Library.IDEInfo(dpInfo)
+ a.aapt.IDEInfo(dpInfo)
+}
+
+func (a *AndroidApp) productCharacteristicsRROPackageName() string {
+ return proptools.String(a.appProperties.ProductCharacteristicsRROPackageName)
+}
+
+func (a *AndroidApp) productCharacteristicsRROManifestModuleName() string {
+ return proptools.String(a.appProperties.ProductCharacteristicsRROManifestModuleName)
+}
+
// android_app compiles sources and Android resources into an Android application package `.apk` file.
func AndroidAppFactory() android.Module {
module := &AndroidApp{}
@@ -1089,11 +1161,67 @@
android.InitDefaultableModule(module)
android.InitOverridableModule(module, &module.overridableAppProperties.Overrides)
android.InitApexModule(module)
- android.InitBazelModule(module)
+
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ a := ctx.Module().(*AndroidApp)
+
+ characteristics := ctx.Config().ProductAAPTCharacteristics()
+ if characteristics == "default" || characteristics == "" {
+ module.appProperties.Generate_product_characteristics_rro = nil
+ // no need to create RRO
+ return
+ }
+
+ if !proptools.Bool(module.appProperties.Generate_product_characteristics_rro) {
+ return
+ }
+
+ rroPackageName := a.Name() + "__" + strings.ReplaceAll(characteristics, ",", "_") + "__auto_generated_characteristics_rro"
+ rroManifestName := rroPackageName + "_manifest"
+
+ a.appProperties.ProductCharacteristicsRROPackageName = proptools.StringPtr(rroPackageName)
+ a.appProperties.ProductCharacteristicsRROManifestModuleName = proptools.StringPtr(rroManifestName)
+
+ rroManifestProperties := struct {
+ Name *string
+ Tools []string
+ Out []string
+ Srcs []string
+ Cmd *string
+ }{
+ Name: proptools.StringPtr(rroManifestName),
+ Tools: []string{"characteristics_rro_generator"},
+ Out: []string{"AndroidManifest.xml"},
+ Srcs: []string{":" + a.Name() + "{.manifest.xml}"},
+ Cmd: proptools.StringPtr("$(location characteristics_rro_generator) $(in) $(out)"),
+ }
+ ctx.CreateModule(genrule.GenRuleFactory, &rroManifestProperties)
+
+ rroProperties := struct {
+ Name *string
+ Filter_product *string
+ Aaptflags []string
+ Manifest *string
+ Resource_dirs []string
+ }{
+ Name: proptools.StringPtr(rroPackageName),
+ Filter_product: proptools.StringPtr(characteristics),
+ Aaptflags: []string{"--auto-add-overlay"},
+ Manifest: proptools.StringPtr(":" + rroManifestName),
+ Resource_dirs: a.aaptProperties.Resource_dirs,
+ }
+ ctx.CreateModule(RuntimeResourceOverlayFactory, &rroProperties)
+ })
return module
}
+// A dictionary of values to be overridden in the manifest.
+type Manifest_values struct {
+ // Overrides the value of package_name in the manifest
+ ApplicationId *string
+}
+
type appTestProperties struct {
// The name of the android_app module that the tests will run against.
Instrumentation_for *string
@@ -1103,6 +1231,8 @@
// If specified, the mainline module package name in the test config is overwritten by it.
Mainline_package_name *string
+
+ Manifest_values Manifest_values
}
type AndroidTest struct {
@@ -1145,6 +1275,13 @@
a.additionalAaptFlags = append(a.additionalAaptFlags, "--rename-instrumentation-target-package "+manifestPackageName)
}
}
+ applicationId := a.appTestProperties.Manifest_values.ApplicationId
+ if applicationId != nil {
+ if a.overridableAppProperties.Package_name != nil {
+ ctx.PropertyErrorf("manifest_values.applicationId", "property is not supported when property package_name is set.")
+ }
+ a.aapt.manifestValues.applicationId = *applicationId
+ }
a.generateAndroidBuildActions(ctx)
for _, module := range a.testProperties.Test_mainline_modules {
@@ -1156,6 +1293,7 @@
a.testConfig = a.FixTestConfig(ctx, testConfig)
a.extraTestConfigs = android.PathsForModuleSrc(ctx, a.testProperties.Test_options.Extra_test_configs)
a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data)
+ android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
func (a *AndroidTest) FixTestConfig(ctx android.ModuleContext, testConfig android.Path) android.Path {
@@ -1232,6 +1370,7 @@
android.InitAndroidMultiTargetsArchModule(module, android.DeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
android.InitOverridableModule(module, &module.overridableAppProperties.Overrides)
+
return module
}
@@ -1247,6 +1386,8 @@
// Install the test into a folder named for the module in all test suites.
Per_testcase_directory *bool
+
+ Manifest_values Manifest_values
}
type AndroidTestHelperApp struct {
@@ -1289,7 +1430,6 @@
type AndroidAppCertificate struct {
android.ModuleBase
- android.BazelModuleBase
properties AndroidAppCertificateProperties
Certificate Certificate
@@ -1306,7 +1446,6 @@
module := &AndroidAppCertificate{}
module.AddProperties(&module.properties)
android.InitAndroidModule(module)
- android.InitBazelModule(module)
return module
}
@@ -1500,7 +1639,7 @@
replaceInList(u.usesLibraryProperties.Optional_uses_libs, dep, libName)
}
clcMap.AddContext(ctx, tag.sdkVersion, libName, tag.optional,
- lib.DexJarBuildPath().PathOrNil(), lib.DexJarInstallPath(),
+ lib.DexJarBuildPath(ctx).PathOrNil(), lib.DexJarInstallPath(),
lib.ClassLoaderContexts())
} else if ctx.Config().AllowMissingDependencies() {
ctx.AddMissingDependencies([]string{dep})
@@ -1540,7 +1679,7 @@
// non-linux build platforms where dexpreopt is generally disabled (the check may fail due to
// various unrelated reasons, such as a failure to get manifest from an APK).
global := dexpreopt.GetGlobalConfig(ctx)
- if global.DisablePreopt || global.OnlyPreoptBootImageAndSystemServer {
+ if global.DisablePreopt || global.OnlyPreoptArtBootImage {
return inputFile
}
@@ -1583,171 +1722,3 @@
func (u *usesLibrary) verifyUsesLibrariesAPK(ctx android.ModuleContext, apk android.Path) {
u.verifyUsesLibraries(ctx, apk, nil) // for APKs manifest_check does not write output file
}
-
-// For Bazel / bp2build
-
-type bazelAndroidAppCertificateAttributes struct {
- Certificate string
-}
-
-func (m *AndroidAppCertificate) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- androidAppCertificateBp2Build(ctx, m)
-}
-
-func androidAppCertificateBp2Build(ctx android.TopDownMutatorContext, module *AndroidAppCertificate) {
- var certificate string
- if module.properties.Certificate != nil {
- certificate = *module.properties.Certificate
- }
-
- attrs := &bazelAndroidAppCertificateAttributes{
- Certificate: certificate,
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "android_app_certificate",
- Bzl_load_location: "//build/bazel/rules/android:android_app_certificate.bzl",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, attrs)
-}
-
-type manifestValueAttribute struct {
- MinSdkVersion *string
- MaxSdkVersion *string
- TargetSdkVersion *string
-}
-
-type bazelAndroidAppAttributes struct {
- *javaCommonAttributes
- *bazelAapt
- Deps bazel.LabelListAttribute
- Custom_package *string
- Certificate bazel.LabelAttribute
- Certificate_name bazel.StringAttribute
- Manifest_values *manifestValueAttribute
- Optimize *bool
- Proguard_specs bazel.LabelListAttribute
-}
-
-// ConvertWithBp2build is used to convert android_app to Bazel.
-func (a *AndroidApp) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- commonAttrs, bp2BuildInfo, supported := a.convertLibraryAttrsBp2Build(ctx)
- if !supported {
- return
- }
- depLabels := bp2BuildInfo.DepLabels
-
- deps := depLabels.Deps
- deps.Append(depLabels.StaticDeps)
-
- aapt, supported := a.convertAaptAttrsWithBp2Build(ctx)
- if !supported {
- return
- }
- certificate, certificateName := android.BazelStringOrLabelFromProp(ctx, a.overridableAppProperties.Certificate)
-
- manifestValues := &manifestValueAttribute{}
- // TODO(b/274474008 ): Directly convert deviceProperties.Min_sdk_version in bp2build
- // MinSdkVersion(ctx) calls SdkVersion(ctx) if no value for min_sdk_version is set
- minSdkVersion := a.MinSdkVersion(ctx)
- if !minSdkVersion.IsPreview() && !minSdkVersion.IsInvalid() {
- if minSdkStr, err := minSdkVersion.EffectiveVersionString(ctx); err == nil {
- manifestValues.MinSdkVersion = &minSdkStr
- }
- }
-
- maxSdkVersion := a.MaxSdkVersion(ctx)
- if !maxSdkVersion.IsPreview() && !maxSdkVersion.IsInvalid() {
- if maxSdkStr, err := maxSdkVersion.EffectiveVersionString(ctx); err == nil {
- manifestValues.MaxSdkVersion = &maxSdkStr
- }
- }
-
- targetSdkVersion := a.TargetSdkVersion(ctx)
- if !targetSdkVersion.IsPreview() && !targetSdkVersion.IsInvalid() {
- if targetSdkStr, err := targetSdkVersion.EffectiveVersionString(ctx); err == nil {
- manifestValues.TargetSdkVersion = &targetSdkStr
- }
- }
-
- appAttrs := &bazelAndroidAppAttributes{
- // TODO(b/209576404): handle package name override by product variable PRODUCT_MANIFEST_PACKAGE_NAME_OVERRIDES
- Custom_package: a.overridableAppProperties.Package_name,
- Certificate: certificate,
- Certificate_name: certificateName,
- Manifest_values: manifestValues,
- }
-
- if !BoolDefault(a.dexProperties.Optimize.Enabled, true) {
- appAttrs.Optimize = proptools.BoolPtr(false)
- } else {
- handCraftedFlags := ""
- if Bool(a.dexProperties.Optimize.Ignore_warnings) {
- handCraftedFlags += "-ignorewarning "
- }
- if !Bool(a.dexProperties.Optimize.Shrink) {
- handCraftedFlags += "-dontshrink "
- }
- if !Bool(a.dexProperties.Optimize.Optimize) {
- handCraftedFlags += "-dontoptimize "
- }
- if !Bool(a.dexProperties.Optimize.Obfuscate) {
- handCraftedFlags += "-dontobfuscate "
- }
- appAttrs.Proguard_specs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, a.dexProperties.Optimize.Proguard_flags_files))
- if handCraftedFlags != "" {
- generatedFlagFileRuleName := a.Name() + "_proguard_flags"
- ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{
- Rule_class: "genrule",
- }, android.CommonAttributes{
- Name: generatedFlagFileRuleName,
- SkipData: proptools.BoolPtr(true),
- }, &genrule.BazelGenruleAttributes{
- Outs: []string{a.Name() + "_proguard.flags"},
- Cmd: bazel.StringAttribute{
- Value: proptools.StringPtr("echo " + handCraftedFlags + "> $(OUTS)"),
- },
- })
- appAttrs.Proguard_specs.Add(bazel.MakeLabelAttribute(":" + generatedFlagFileRuleName))
- }
-
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "android_binary",
- Bzl_load_location: "//build/bazel/rules/android:android_binary.bzl",
- }
-
- if !bp2BuildInfo.hasKotlin {
- appAttrs.javaCommonAttributes = commonAttrs
- appAttrs.bazelAapt = aapt
- appAttrs.Deps = deps
- } else {
- ktName := a.Name() + "_kt"
- ctx.CreateBazelTargetModule(
- AndroidLibraryBazelTargetModuleProperties(),
- android.CommonAttributes{Name: ktName},
- &bazelAndroidLibrary{
- javaLibraryAttributes: &javaLibraryAttributes{
- javaCommonAttributes: commonAttrs,
- Deps: deps,
- },
- bazelAapt: aapt,
- },
- )
-
- appAttrs.bazelAapt = &bazelAapt{Manifest: aapt.Manifest}
- appAttrs.Deps = bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + ktName})
- appAttrs.javaCommonAttributes = &javaCommonAttributes{
- Sdk_version: commonAttrs.Sdk_version,
- }
- }
-
- ctx.CreateBazelTargetModule(
- props,
- android.CommonAttributes{Name: a.Name(), SkipData: proptools.BoolPtr(true)},
- appAttrs,
- )
-
-}
diff --git a/java/app_builder.go b/java/app_builder.go
index d397ff7..943ce31 100644
--- a/java/app_builder.go
+++ b/java/app_builder.go
@@ -52,7 +52,7 @@
})
func CreateAndSignAppPackage(ctx android.ModuleContext, outputFile android.WritablePath,
- packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, v4SignatureFile android.WritablePath, lineageFile android.Path, rotationMinSdkVersion string, shrinkResources bool) {
+ packageFile, jniJarFile, dexJarFile android.Path, certificates []Certificate, deps android.Paths, v4SignatureFile android.WritablePath, lineageFile android.Path, rotationMinSdkVersion string) {
unsignedApkName := strings.TrimSuffix(outputFile.Base(), ".apk") + "-unsigned.apk"
unsignedApk := android.PathForModuleOut(ctx, unsignedApkName)
@@ -71,12 +71,6 @@
Output: unsignedApk,
Implicits: deps,
})
-
- if shrinkResources {
- shrunkenApk := android.PathForModuleOut(ctx, "resource-shrunken", unsignedApk.Base())
- ShrinkResources(ctx, unsignedApk, shrunkenApk)
- unsignedApk = shrunkenApk
- }
SignAppPackage(ctx, outputFile, unsignedApk, certificates, v4SignatureFile, lineageFile, rotationMinSdkVersion)
}
diff --git a/java/app_import.go b/java/app_import.go
index 1718d93..12ead0a 100644
--- a/java/app_import.go
+++ b/java/app_import.go
@@ -19,6 +19,7 @@
import (
"fmt"
"reflect"
+ "strings"
"github.com/google/blueprint"
@@ -51,27 +52,11 @@
Description: "Uncompress dex files",
})
- checkDexLibsAreUncompressedRule = pctx.AndroidStaticRule("check-dex-libs-are-uncompressed", blueprint.RuleParams{
- // grep -v ' stor ' will search for lines that don't have ' stor '. stor means the file is stored uncompressed
- Command: "if (zipinfo $in '*.dex' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then " +
- "echo $in: Contains compressed JNI libraries and/or dex files >&2;" +
- "exit 1; " +
- "else " +
- "touch $out; " +
- "fi",
- Description: "Check for compressed JNI libs or dex files",
- })
-
- checkJniLibsAreUncompressedRule = pctx.AndroidStaticRule("check-jni-libs-are-uncompressed", blueprint.RuleParams{
- // grep -v ' stor ' will search for lines that don't have ' stor '. stor means the file is stored uncompressed
- Command: "if (zipinfo $in 'lib/*.so' 2>/dev/null | grep -v ' stor ' >/dev/null) ; then " +
- "echo $in: Contains compressed JNI libraries >&2;" +
- "exit 1; " +
- "else " +
- "touch $out; " +
- "fi",
- Description: "Check for compressed JNI libs or dex files",
- })
+ checkPresignedApkRule = pctx.AndroidStaticRule("check-presigned-apk", blueprint.RuleParams{
+ Command: "build/soong/scripts/check_prebuilt_presigned_apk.py --aapt2 ${config.Aapt2Cmd} --zipalign ${config.ZipAlign} $extraArgs $in $out",
+ CommandDeps: []string{"build/soong/scripts/check_prebuilt_presigned_apk.py", "${config.Aapt2Cmd}", "${config.ZipAlign}"},
+ Description: "Check presigned apk",
+ }, "extraArgs")
)
func RegisterAppImportBuildComponents(ctx android.RegistrationContext) {
@@ -101,6 +86,9 @@
hideApexVariantFromMake bool
provenanceMetaDataFile android.OutputPath
+
+ // Single aconfig "cache file" merged from this module and all dependencies.
+ mergedAconfigFiles map[string]android.Paths
}
type AndroidAppImportProperties struct {
@@ -163,7 +151,9 @@
}
// Updates properties with variant-specific values.
-func (a *AndroidAppImport) processVariants(ctx android.LoadHookContext) {
+// This happens as a DefaultableHook instead of a LoadHook because we want to run it after
+// soong config variables are applied.
+func (a *AndroidAppImport) processVariants(ctx android.DefaultableHookContext) {
config := ctx.Config()
dpiProps := reflect.ValueOf(a.dpiVariants).Elem().FieldByName("Dpi_variants")
@@ -256,7 +246,7 @@
return ctx.Config().UncompressPrivAppDex()
}
- return shouldUncompressDex(ctx, &a.dexpreopter)
+ return shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &a.dexpreopter)
}
func (a *AndroidAppImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -272,7 +262,7 @@
ctx.ModuleErrorf("prebuilt_framework-res found. This used to have special handling in soong, but was removed due to prebuilt_framework-res no longer existing. This check is to ensure it doesn't come back without readding the special handling.")
}
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if !apexInfo.IsForPlatform() {
a.hideApexVariantFromMake = true
}
@@ -334,7 +324,7 @@
a.usesLibrary.verifyUsesLibrariesAPK(ctx, srcApk)
}
- a.dexpreopter.dexpreopt(ctx, jnisUncompressed)
+ a.dexpreopter.dexpreopt(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), jnisUncompressed)
if a.dexpreopter.uncompressedDex {
dexUncompressed := android.PathForModuleOut(ctx, "dex-uncompressed", ctx.ModuleName()+".apk")
ctx.Build(pctx, android.BuildParams{
@@ -352,20 +342,14 @@
// Sign or align the package if package has not been preprocessed
if proptools.Bool(a.properties.Preprocessed) {
- var output android.WritablePath
- if !proptools.Bool(a.properties.Skip_preprocessed_apk_checks) {
- output = android.PathForModuleOut(ctx, "validated-prebuilt", apkFilename)
- a.validatePreprocessedApk(ctx, srcApk, output)
- } else {
- // If using the input APK unmodified, still make a copy of it so that the output filename has the
- // right basename.
- output = android.PathForModuleOut(ctx, apkFilename)
- ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Input: srcApk,
- Output: output,
- })
- }
+ validationStamp := a.validatePresignedApk(ctx, srcApk)
+ output := android.PathForModuleOut(ctx, apkFilename)
+ ctx.Build(pctx, android.BuildParams{
+ Rule: android.Cp,
+ Input: srcApk,
+ Output: output,
+ Validation: validationStamp,
+ })
a.outputFile = output
a.certificate = PresignedCertificate
} else if !Bool(a.properties.Presigned) {
@@ -384,13 +368,9 @@
SignAppPackage(ctx, signed, jnisUncompressed, certificates, nil, lineageFile, rotationMinSdkVersion)
a.outputFile = signed
} else {
- // Presigned without Preprocessed shouldn't really be a thing, currently we disallow
- // it for apps with targetSdk >= 30, because on those targetSdks you must be using signature
- // v2 or later, and signature v2 would be wrecked by uncompressing libs / zipaligning.
- // But ideally we would disallow it for all prebuilt apks, and remove the presigned property.
- targetSdkCheck := a.validateTargetSdkLessThan30(ctx, srcApk)
+ validationStamp := a.validatePresignedApk(ctx, srcApk)
alignedApk := android.PathForModuleOut(ctx, "zip-aligned", apkFilename)
- TransformZipAlign(ctx, alignedApk, jnisUncompressed, []android.Path{targetSdkCheck})
+ TransformZipAlign(ctx, alignedApk, jnisUncompressed, []android.Path{validationStamp})
a.outputFile = alignedApk
a.certificate = PresignedCertificate
}
@@ -402,56 +382,33 @@
artifactPath := android.PathForModuleSrc(ctx, *a.properties.Apk)
a.provenanceMetaDataFile = provenance.GenerateArtifactProvenanceMetaData(ctx, artifactPath, a.installPath)
}
+ android.CollectDependencyAconfigFiles(ctx, &a.mergedAconfigFiles)
// TODO: androidmk converter jni libs
}
-func (a *AndroidAppImport) validatePreprocessedApk(ctx android.ModuleContext, srcApk android.Path, dstApk android.WritablePath) {
- var validations android.Paths
-
- alignmentStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "alignment.stamp")
- ctx.Build(pctx, android.BuildParams{
- Rule: checkZipAlignment,
- Input: srcApk,
- Output: alignmentStamp,
- })
-
- validations = append(validations, alignmentStamp)
- jniCompressionStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "jni_compression.stamp")
- ctx.Build(pctx, android.BuildParams{
- Rule: checkJniLibsAreUncompressedRule,
- Input: srcApk,
- Output: jniCompressionStamp,
- })
- validations = append(validations, jniCompressionStamp)
-
+func (a *AndroidAppImport) validatePresignedApk(ctx android.ModuleContext, srcApk android.Path) android.Path {
+ stamp := android.PathForModuleOut(ctx, "validated-prebuilt", "check.stamp")
+ var extraArgs []string
if a.Privileged() {
- // It's ok for non-privileged apps to have compressed dex files, see go/gms-uncompressed-jni-slides
- dexCompressionStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "dex_compression.stamp")
- ctx.Build(pctx, android.BuildParams{
- Rule: checkDexLibsAreUncompressedRule,
- Input: srcApk,
- Output: dexCompressionStamp,
- })
- validations = append(validations, dexCompressionStamp)
+ extraArgs = append(extraArgs, "--privileged")
+ }
+ if proptools.Bool(a.properties.Skip_preprocessed_apk_checks) {
+ extraArgs = append(extraArgs, "--skip-preprocessed-apk-checks")
+ }
+ if proptools.Bool(a.properties.Preprocessed) {
+ extraArgs = append(extraArgs, "--preprocessed")
}
ctx.Build(pctx, android.BuildParams{
- Rule: android.Cp,
- Input: srcApk,
- Output: dstApk,
- Validations: validations,
- })
-}
-
-func (a *AndroidAppImport) validateTargetSdkLessThan30(ctx android.ModuleContext, srcApk android.Path) android.Path {
- alignmentStamp := android.PathForModuleOut(ctx, "validated-prebuilt", "old_target_sdk.stamp")
- ctx.Build(pctx, android.BuildParams{
- Rule: checkBelowTargetSdk30ForNonPreprocessedApks,
+ Rule: checkPresignedApkRule,
Input: srcApk,
- Output: alignmentStamp,
+ Output: stamp,
+ Args: map[string]string{
+ "extraArgs": strings.Join(extraArgs, " "),
+ },
})
- return alignmentStamp
+ return stamp
}
func (a *AndroidAppImport) Prebuilt() *android.Prebuilt {
@@ -588,7 +545,7 @@
module.AddProperties(&module.dexpreoptProperties)
module.AddProperties(&module.usesLibrary.usesLibraryProperties)
module.populateAllVariantStructs()
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
module.processVariants(ctx)
})
@@ -639,7 +596,7 @@
module.AddProperties(&module.dexpreoptProperties)
module.AddProperties(&module.testProperties)
module.populateAllVariantStructs()
- android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ module.SetDefaultableHook(func(ctx android.DefaultableHookContext) {
module.processVariants(ctx)
})
diff --git a/java/app_import_test.go b/java/app_import_test.go
index 506c734..44f8f16 100644
--- a/java/app_import_test.go
+++ b/java/app_import_test.go
@@ -40,8 +40,8 @@
variant := ctx.ModuleForTests("foo", "android_common")
// Check dexpreopt outputs.
- if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
- variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
+ if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
+ variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule == nil {
t.Errorf("can't find dexpreopt outputs")
}
@@ -74,8 +74,8 @@
variant := ctx.ModuleForTests("foo", "android_common")
// Check dexpreopt outputs. They shouldn't exist.
- if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule != nil ||
- variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule != nil {
+ if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule != nil ||
+ variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule != nil {
t.Errorf("dexpreopt shouldn't have run.")
}
@@ -101,8 +101,8 @@
variant := ctx.ModuleForTests("foo", "android_common")
// Check dexpreopt outputs.
- if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
- variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
+ if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
+ variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule == nil {
t.Errorf("can't find dexpreopt outputs")
}
// Make sure signing was skipped and aligning was done.
@@ -210,8 +210,8 @@
variant := ctx.ModuleForTests("foo", "android_common")
// Check dexpreopt outputs.
- if variant.MaybeOutput("dexpreopt/oat/arm64/package.vdex").Rule == nil ||
- variant.MaybeOutput("dexpreopt/oat/arm64/package.odex").Rule == nil {
+ if variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.vdex").Rule == nil ||
+ variant.MaybeOutput("dexpreopt/foo/oat/arm64/package.odex").Rule == nil {
t.Errorf("can't find dexpreopt outputs")
}
@@ -411,6 +411,27 @@
installPath: "/system/app/foo/foo.apk",
},
{
+ name: "matching arch without default",
+ bp: `
+ android_app_import {
+ name: "foo",
+ apk: "prebuilts/apk/app.apk",
+ arch: {
+ arm64: {
+ apk: "prebuilts/apk/app_arm64.apk",
+ },
+ },
+ presigned: true,
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `,
+ expected: "verify_uses_libraries/apk/app_arm64.apk",
+ artifactPath: "prebuilts/apk/app_arm64.apk",
+ installPath: "/system/app/foo/foo.apk",
+ },
+ {
name: "no matching arch",
bp: `
android_app_import {
@@ -454,26 +475,105 @@
}
for _, test := range testCases {
- ctx, _ := testJava(t, test.bp)
+ t.Run(test.name, func(t *testing.T) {
+ ctx, _ := testJava(t, test.bp)
- variant := ctx.ModuleForTests("foo", "android_common")
- if test.expected == "" {
- if variant.Module().Enabled() {
- t.Error("module should have been disabled, but wasn't")
+ variant := ctx.ModuleForTests("foo", "android_common")
+ if test.expected == "" {
+ if variant.Module().Enabled() {
+ t.Error("module should have been disabled, but wasn't")
+ }
+ rule := variant.MaybeRule("genProvenanceMetaData")
+ android.AssertDeepEquals(t, "Provenance metadata is not empty", android.TestingBuildParams{}, rule)
+ return
}
- rule := variant.MaybeRule("genProvenanceMetaData")
- android.AssertDeepEquals(t, "Provenance metadata is not empty", android.TestingBuildParams{}, rule)
- continue
- }
- input := variant.Output("jnis-uncompressed/foo.apk").Input.String()
- if strings.HasSuffix(input, test.expected) {
- t.Errorf("wrong src apk, expected: %q got: %q", test.expected, input)
- }
- rule := variant.Rule("genProvenanceMetaData")
- android.AssertStringEquals(t, "Invalid input", test.artifactPath, rule.Inputs[0].String())
- android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
- android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
- android.AssertStringEquals(t, "Invalid args", test.installPath, rule.Args["install_path"])
+ input := variant.Output("jnis-uncompressed/foo.apk").Input.String()
+ if strings.HasSuffix(input, test.expected) {
+ t.Errorf("wrong src apk, expected: %q got: %q", test.expected, input)
+ }
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", test.artifactPath, rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", test.installPath, rule.Args["install_path"])
+ })
+ }
+}
+
+func TestAndroidAppImport_SoongConfigVariables(t *testing.T) {
+ testCases := []struct {
+ name string
+ bp string
+ expected string
+ artifactPath string
+ metaDataPath string
+ installPath string
+ }{
+ {
+ name: "matching arch",
+ bp: `
+ soong_config_module_type {
+ name: "my_android_app_import",
+ module_type: "android_app_import",
+ config_namespace: "my_namespace",
+ value_variables: ["my_apk_var"],
+ properties: ["apk"],
+ }
+ soong_config_value_variable {
+ name: "my_apk_var",
+ }
+ my_android_app_import {
+ name: "foo",
+ soong_config_variables: {
+ my_apk_var: {
+ apk: "prebuilts/apk/%s.apk",
+ },
+ },
+ presigned: true,
+ dex_preopt: {
+ enabled: true,
+ },
+ }
+ `,
+ expected: "verify_uses_libraries/apk/name_from_soong_config.apk",
+ artifactPath: "prebuilts/apk/name_from_soong_config.apk",
+ installPath: "/system/app/foo/foo.apk",
+ },
+ }
+
+ for _, test := range testCases {
+ t.Run(test.name, func(t *testing.T) {
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.PrepareForTestWithSoongConfigModuleBuildComponents,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.VendorVars = map[string]map[string]string{
+ "my_namespace": {
+ "my_apk_var": "name_from_soong_config",
+ },
+ }
+ }),
+ ).RunTestWithBp(t, test.bp).TestContext
+
+ variant := ctx.ModuleForTests("foo", "android_common")
+ if test.expected == "" {
+ if variant.Module().Enabled() {
+ t.Error("module should have been disabled, but wasn't")
+ }
+ rule := variant.MaybeRule("genProvenanceMetaData")
+ android.AssertDeepEquals(t, "Provenance metadata is not empty", android.TestingBuildParams{}, rule)
+ return
+ }
+ input := variant.Output("jnis-uncompressed/foo.apk").Input.String()
+ if strings.HasSuffix(input, test.expected) {
+ t.Errorf("wrong src apk, expected: %q got: %q", test.expected, input)
+ }
+ rule := variant.Rule("genProvenanceMetaData")
+ android.AssertStringEquals(t, "Invalid input", test.artifactPath, rule.Inputs[0].String())
+ android.AssertStringEquals(t, "Invalid output", "out/soong/.intermediates/provenance_metadata/foo/provenance_metadata.textproto", rule.Output.String())
+ android.AssertStringEquals(t, "Invalid args", "foo", rule.Args["module_name"])
+ android.AssertStringEquals(t, "Invalid args", test.installPath, rule.Args["install_path"])
+ })
}
}
@@ -659,14 +759,19 @@
apkName := "foo.apk"
variant := ctx.ModuleForTests("foo", "android_common")
- outputBuildParams := variant.Output("validated-prebuilt/" + apkName).BuildParams
+ outputBuildParams := variant.Output(apkName).BuildParams
if outputBuildParams.Rule.String() != android.Cp.String() {
t.Errorf("Unexpected prebuilt android_app_import rule: " + outputBuildParams.Rule.String())
}
// Make sure compression and aligning were validated.
- if len(outputBuildParams.Validations) != 2 {
- t.Errorf("Expected compression/alignment validation rules, found %d validations", len(outputBuildParams.Validations))
+ if outputBuildParams.Validation == nil {
+ t.Errorf("Expected validation rule, but was not found")
+ }
+
+ validationBuildParams := variant.Output("validated-prebuilt/check.stamp").BuildParams
+ if validationBuildParams.Rule.String() != checkPresignedApkRule.String() {
+ t.Errorf("Unexpected validation rule: " + validationBuildParams.Rule.String())
}
}
diff --git a/java/app_test.go b/java/app_test.go
index fc57f44..362bef9 100644
--- a/java/app_test.go
+++ b/java/app_test.go
@@ -558,7 +558,6 @@
t.Run(testCase.name, func(t *testing.T) {
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
- PrepareForTestWithOverlayBuildComponents,
fs.AddToFixture(),
).RunTestWithBp(t, fmt.Sprintf(bp, testCase.prop))
@@ -608,6 +607,15 @@
asset_dirs: ["assets_b"],
}
+ android_library {
+ name: "lib5",
+ sdk_version: "current",
+ assets: [
+ "path/to/asset_file_1",
+ "path/to/asset_file_2",
+ ],
+ }
+
android_library_import {
name: "import",
sdk_version: "current",
@@ -616,9 +624,11 @@
`
testCases := []struct {
- name string
- assetFlag string
- assetPackages []string
+ name string
+ assetFlag string
+ assetPackages []string
+ tmpAssetDirInputs []string
+ tmpAssetDirOutputs []string
}{
{
name: "foo",
@@ -644,6 +654,18 @@
name: "lib4",
assetFlag: "-A assets_b",
},
+ {
+ name: "lib5",
+ assetFlag: "-A out/soong/.intermediates/lib5/android_common/tmp_asset_dir",
+ tmpAssetDirInputs: []string{
+ "path/to/asset_file_1",
+ "path/to/asset_file_2",
+ },
+ tmpAssetDirOutputs: []string{
+ "out/soong/.intermediates/lib5/android_common/tmp_asset_dir/path/to/asset_file_1",
+ "out/soong/.intermediates/lib5/android_common/tmp_asset_dir/path/to/asset_file_2",
+ },
+ },
}
ctx := testApp(t, bp)
@@ -671,6 +693,14 @@
mergeAssets := m.Output("package-res.apk")
android.AssertPathsRelativeToTopEquals(t, "mergeAssets inputs", test.assetPackages, mergeAssets.Inputs)
}
+
+ if len(test.tmpAssetDirInputs) > 0 {
+ rule := m.Rule("tmp_asset_dir")
+ inputs := rule.Implicits
+ outputs := append(android.WritablePaths{rule.Output}, rule.ImplicitOutputs...).Paths()
+ android.AssertPathsRelativeToTopEquals(t, "tmp_asset_dir inputs", test.tmpAssetDirInputs, inputs)
+ android.AssertPathsRelativeToTopEquals(t, "tmp_asset_dir outputs", test.tmpAssetDirOutputs, outputs)
+ }
})
}
}
@@ -722,10 +752,13 @@
func TestAndroidResourceProcessor(t *testing.T) {
testCases := []struct {
- name string
- appUsesRP bool
- directLibUsesRP bool
- transitiveLibUsesRP bool
+ name string
+ appUsesRP bool
+ directLibUsesRP bool
+ transitiveLibUsesRP bool
+ sharedLibUsesRP bool
+ sharedTransitiveStaticLibUsesRP bool
+ sharedTransitiveSharedLibUsesRP bool
dontVerifyApp bool
appResources []string
@@ -760,6 +793,14 @@
transitiveImportResources []string
transitiveImportOverlays []string
transitiveImportImports []string
+
+ dontVerifyShared bool
+ sharedResources []string
+ sharedOverlays []string
+ sharedImports []string
+ sharedSrcJars []string
+ sharedClasspath []string
+ sharedCombined []string
}{
{
// Test with all modules set to use_resource_processor: false (except android_library_import modules,
@@ -779,10 +820,14 @@
"out/soong/.intermediates/direct_import/android_common/package-res.apk",
"out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
},
- appImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ appImports: []string{
+ "out/soong/.intermediates/shared/android_common/package-res.apk",
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ },
appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
appClasspath: []string{
"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
"out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
},
@@ -819,6 +864,26 @@
transitiveClasspath: []string{"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar"},
transitiveCombined: nil,
+ sharedResources: nil,
+ sharedOverlays: []string{
+ "out/soong/.intermediates/shared_transitive_static/android_common/package-res.apk",
+ "out/soong/.intermediates/shared/android_common/aapt2/shared/res/values_strings.arsc.flat",
+ },
+ sharedImports: []string{
+ "out/soong/.intermediates/shared_transitive_shared/android_common/package-res.apk",
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ },
+ sharedSrcJars: []string{"out/soong/.intermediates/shared/android_common/gen/android/R.srcjar"},
+ sharedClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/shared_transitive_shared/android_common/turbine-combined/shared_transitive_shared.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/turbine-combined/shared_transitive_static.jar",
+ },
+ sharedCombined: []string{
+ "out/soong/.intermediates/shared/android_common/javac/shared.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/javac/shared_transitive_static.jar",
+ },
+
directImportResources: nil,
directImportOverlays: []string{"out/soong/.intermediates/direct_import/android_common/flat-res/gen_res.flata"},
directImportImports: []string{
@@ -835,10 +900,13 @@
},
{
// Test with all modules set to use_resource_processor: true.
- name: "resource_processor",
- appUsesRP: true,
- directLibUsesRP: true,
- transitiveLibUsesRP: true,
+ name: "resource_processor",
+ appUsesRP: true,
+ directLibUsesRP: true,
+ transitiveLibUsesRP: true,
+ sharedLibUsesRP: true,
+ sharedTransitiveSharedLibUsesRP: true,
+ sharedTransitiveStaticLibUsesRP: true,
appResources: nil,
appOverlays: []string{
@@ -850,11 +918,15 @@
"out/soong/.intermediates/direct_import/android_common/package-res.apk",
"out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
},
- appImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ appImports: []string{
+ "out/soong/.intermediates/shared/android_common/package-res.apk",
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ },
appSrcJars: nil,
appClasspath: []string{
"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
"out/soong/.intermediates/app/android_common/busybox/R.jar",
+ "out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
"out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
},
@@ -899,6 +971,27 @@
},
transitiveCombined: nil,
+ sharedResources: nil,
+ sharedOverlays: []string{"out/soong/.intermediates/shared/android_common/aapt2/shared/res/values_strings.arsc.flat"},
+ sharedImports: []string{
+ "out/soong/.intermediates/shared_transitive_shared/android_common/package-res.apk",
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ "out/soong/.intermediates/shared_transitive_static/android_common/package-res.apk",
+ },
+ sharedSrcJars: nil,
+ sharedClasspath: []string{
+ "out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/busybox/R.jar",
+ "out/soong/.intermediates/shared_transitive_shared/android_common/busybox/R.jar",
+ "out/soong/.intermediates/shared/android_common/busybox/R.jar",
+ "out/soong/.intermediates/shared_transitive_shared/android_common/turbine-combined/shared_transitive_shared.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/turbine-combined/shared_transitive_static.jar",
+ },
+ sharedCombined: []string{
+ "out/soong/.intermediates/shared/android_common/javac/shared.jar",
+ "out/soong/.intermediates/shared_transitive_static/android_common/javac/shared_transitive_static.jar",
+ },
+
directImportResources: nil,
directImportOverlays: []string{"out/soong/.intermediates/direct_import/android_common/flat-res/gen_res.flata"},
directImportImports: []string{
@@ -930,12 +1023,16 @@
"out/soong/.intermediates/direct_import/android_common/package-res.apk",
"out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
},
- appImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ appImports: []string{
+ "out/soong/.intermediates/shared/android_common/package-res.apk",
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ },
appSrcJars: nil,
appClasspath: []string{
"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
// R.jar has to come before direct.jar
"out/soong/.intermediates/app/android_common/busybox/R.jar",
+ "out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
"out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
},
@@ -948,6 +1045,7 @@
dontVerifyDirect: true,
dontVerifyTransitive: true,
+ dontVerifyShared: true,
dontVerifyDirectImport: true,
dontVerifyTransitiveImport: true,
},
@@ -968,10 +1066,14 @@
"out/soong/.intermediates/direct_import/android_common/package-res.apk",
"out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
},
- appImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ appImports: []string{
+ "out/soong/.intermediates/shared/android_common/package-res.apk",
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ },
appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
appClasspath: []string{
"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
"out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
},
@@ -1005,6 +1107,7 @@
},
dontVerifyTransitive: true,
+ dontVerifyShared: true,
dontVerifyDirectImport: true,
dontVerifyTransitiveImport: true,
},
@@ -1025,10 +1128,14 @@
"out/soong/.intermediates/direct_import/android_common/package-res.apk",
"out/soong/.intermediates/app/android_common/aapt2/app/res/values_strings.arsc.flat",
},
- appImports: []string{"out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk"},
+ appImports: []string{
+ "out/soong/.intermediates/shared/android_common/package-res.apk",
+ "out/soong/.intermediates/default/java/framework-res/android_common/package-res.apk",
+ },
appSrcJars: []string{"out/soong/.intermediates/app/android_common/gen/android/R.srcjar"},
appClasspath: []string{
"out/soong/.intermediates/default/java/android_stubs_current/android_common/turbine-combined/android_stubs_current.jar",
+ "out/soong/.intermediates/shared/android_common/turbine-combined/shared.jar",
"out/soong/.intermediates/direct/android_common/turbine-combined/direct.jar",
"out/soong/.intermediates/direct_import/android_common/aar/classes-combined.jar",
},
@@ -1068,6 +1175,7 @@
},
transitiveCombined: nil,
+ dontVerifyShared: true,
dontVerifyDirectImport: true,
dontVerifyTransitiveImport: true,
},
@@ -1082,6 +1190,7 @@
srcs: ["app/app.java"],
resource_dirs: ["app/res"],
manifest: "app/AndroidManifest.xml",
+ libs: ["shared"],
static_libs: ["direct", "direct_import"],
use_resource_processor: %v,
}
@@ -1105,6 +1214,35 @@
use_resource_processor: %v,
}
+ android_library {
+ name: "shared",
+ sdk_version: "current",
+ srcs: ["shared/shared.java"],
+ resource_dirs: ["shared/res"],
+ manifest: "shared/AndroidManifest.xml",
+ use_resource_processor: %v,
+ libs: ["shared_transitive_shared"],
+ static_libs: ["shared_transitive_static"],
+ }
+
+ android_library {
+ name: "shared_transitive_shared",
+ sdk_version: "current",
+ srcs: ["shared_transitive_shared/shared_transitive_shared.java"],
+ resource_dirs: ["shared_transitive_shared/res"],
+ manifest: "shared_transitive_shared/AndroidManifest.xml",
+ use_resource_processor: %v,
+ }
+
+ android_library {
+ name: "shared_transitive_static",
+ sdk_version: "current",
+ srcs: ["shared_transitive_static/shared.java"],
+ resource_dirs: ["shared_transitive_static/res"],
+ manifest: "shared_transitive_static/AndroidManifest.xml",
+ use_resource_processor: %v,
+ }
+
android_library_import {
name: "direct_import",
sdk_version: "current",
@@ -1130,17 +1268,20 @@
sdk_version: "current",
aars: ["transitive_import_dep.aar"],
}
- `, testCase.appUsesRP, testCase.directLibUsesRP, testCase.transitiveLibUsesRP)
+ `, testCase.appUsesRP, testCase.directLibUsesRP, testCase.transitiveLibUsesRP,
+ testCase.sharedLibUsesRP, testCase.sharedTransitiveSharedLibUsesRP, testCase.sharedTransitiveStaticLibUsesRP)
fs := android.MockFS{
- "app/res/values/strings.xml": nil,
- "direct/res/values/strings.xml": nil,
- "transitive/res/values/strings.xml": nil,
+ "app/res/values/strings.xml": nil,
+ "direct/res/values/strings.xml": nil,
+ "transitive/res/values/strings.xml": nil,
+ "shared/res/values/strings.xml": nil,
+ "shared_transitive_static/res/values/strings.xml": nil,
+ "shared_transitive_shared/res/values/strings.xml": nil,
}
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
- PrepareForTestWithOverlayBuildComponents,
fs.AddToFixture(),
).RunTestWithBp(t, bp)
@@ -1182,6 +1323,7 @@
app := getAaptInfo("app")
direct := getAaptInfo("direct")
transitive := getAaptInfo("transitive")
+ shared := getAaptInfo("shared")
directImport := getAaptInfo("direct_import")
transitiveImport := getAaptInfo("transitive_import")
@@ -1212,6 +1354,15 @@
android.AssertPathsRelativeToTopEquals(t, "transitive combined", testCase.transitiveCombined, transitive.combined)
}
+ if !testCase.dontVerifyShared {
+ android.AssertPathsRelativeToTopEquals(t, "shared resources", testCase.sharedResources, shared.resources)
+ android.AssertPathsRelativeToTopEquals(t, "shared overlays", testCase.sharedOverlays, shared.overlays)
+ android.AssertPathsRelativeToTopEquals(t, "shared imports", testCase.sharedImports, shared.imports)
+ android.AssertPathsRelativeToTopEquals(t, "shared srcjars", testCase.sharedSrcJars, shared.srcJars)
+ android.AssertPathsRelativeToTopEquals(t, "shared classpath", testCase.sharedClasspath, shared.classpath)
+ android.AssertPathsRelativeToTopEquals(t, "shared combined", testCase.sharedCombined, shared.combined)
+ }
+
if !testCase.dontVerifyDirectImport {
android.AssertPathsRelativeToTopEquals(t, "direct_import resources", testCase.directImportResources, directImport.resources)
android.AssertPathsRelativeToTopEquals(t, "direct_import overlays", testCase.directImportOverlays, directImport.overlays)
@@ -1413,7 +1564,6 @@
t.Run(testCase.name, func(t *testing.T) {
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
- PrepareForTestWithOverlayBuildComponents,
fs.AddToFixture(),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.DeviceResourceOverlays = deviceResourceOverlays
@@ -1959,7 +2109,7 @@
Output("libjni.so").Output.String()
sdkJNI := ctx.ModuleForTests("libjni", "android_arm64_armv8-a_sdk_shared").
Output("libjni.so").Output.String()
- vendorJNI := ctx.ModuleForTests("libvendorjni", "android_arm64_armv8-a_shared").
+ vendorJNI := ctx.ModuleForTests("libvendorjni", "android_vendor_arm64_armv8-a_shared").
Output("libvendorjni.so").Output.String()
for _, test := range testCases {
@@ -3207,7 +3357,7 @@
cmd := app.Rule("dexpreopt").RuleParams.Command
android.AssertStringDoesContain(t, "dexpreopt app cmd context", cmd, "--context-json=")
android.AssertStringDoesContain(t, "dexpreopt app cmd product_packages", cmd,
- "--product-packages=out/soong/.intermediates/app/android_common/dexpreopt/product_packages.txt")
+ "--product-packages=out/soong/.intermediates/app/android_common/dexpreopt/app/product_packages.txt")
}
func TestDexpreoptBcp(t *testing.T) {
@@ -4183,3 +4333,48 @@
)
}
+
+func TestAppFlagsPackages(t *testing.T) {
+ ctx := testApp(t, `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ sdk_version: "current",
+ flags_packages: [
+ "bar",
+ "baz",
+ ],
+ }
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package.bar",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ aconfig_declarations {
+ name: "baz",
+ package: "com.example.package.baz",
+ srcs: [
+ "baz.aconfig",
+ ],
+ }
+ `)
+
+ foo := ctx.ModuleForTests("foo", "android_common")
+
+ // android_app module depends on aconfig_declarations listed in flags_packages
+ android.AssertBoolEquals(t, "foo expected to depend on bar", true,
+ CheckModuleHasDependency(t, ctx, "foo", "android_common", "bar"))
+
+ android.AssertBoolEquals(t, "foo expected to depend on baz", true,
+ CheckModuleHasDependency(t, ctx, "foo", "android_common", "baz"))
+
+ aapt2LinkRule := foo.Rule("android/soong/java.aapt2Link")
+ linkInFlags := aapt2LinkRule.Args["inFlags"]
+ android.AssertStringDoesContain(t,
+ "aapt2 link command expected to pass feature flags arguments",
+ linkInFlags,
+ "--feature-flags @out/soong/.intermediates/bar/intermediate.txt --feature-flags @out/soong/.intermediates/baz/intermediate.txt",
+ )
+}
diff --git a/java/base.go b/java/base.go
index 8f48398..e52cedd 100644
--- a/java/base.go
+++ b/java/base.go
@@ -20,8 +20,7 @@
"strconv"
"strings"
- "android/soong/ui/metrics/bp2build_metrics_proto"
-
+ "github.com/google/blueprint"
"github.com/google/blueprint/pathtools"
"github.com/google/blueprint/proptools"
@@ -134,7 +133,7 @@
// supported at compile time. It should only be needed to compile tests in
// packages that exist in libcore and which are inconvenient to move
// elsewhere.
- Patch_module *string `android:"arch_variant"`
+ Patch_module *string
Jacoco struct {
// List of classes to include for instrumentation with jacoco to collect coverage
@@ -194,7 +193,13 @@
Generated_srcjars []android.Path `android:"mutated"`
// If true, then only the headers are built and not the implementation jar.
- Headers_only bool
+ Headers_only *bool
+
+ // A list of files or dependencies to make available to the build sandbox. This is
+ // useful if source files are symlinks, the targets of the symlinks must be listed here.
+ // Note that currently not all actions implemented by android_apps are sandboxed, so you
+ // may only see this being necessary in lint builds.
+ Compile_data []string `android:"path"`
}
// Properties that are specific to device modules. Host module factories should not add these when
@@ -406,7 +411,6 @@
android.ModuleBase
android.DefaultableModuleBase
android.ApexModuleBase
- android.BazelModuleBase
// Functionality common to Module and Import.
embeddableInModuleAndImport
@@ -432,6 +436,9 @@
srcJarArgs []string
srcJarDeps android.Paths
+ // the source files of this module and all its static dependencies
+ transitiveSrcFiles *android.DepSet[android.Path]
+
// jar file containing implementation classes and resources including static library
// dependencies
implementationAndResourcesJar android.Path
@@ -494,9 +501,6 @@
// list of the xref extraction files
kytheFiles android.Paths
- // Collect the module directory for IDE info in java/jdeps.go.
- modulePaths []string
-
hideApexVariantFromMake bool
sdkVersion android.SdkSpec
@@ -512,13 +516,8 @@
// or the module should override Stem().
stem string
- // Aconfig "cache files" that went directly into this module. Transitive ones are
- // tracked via JavaInfo.TransitiveAconfigFiles
- // TODO: Extract to something standalone to propagate tags via GeneratedJavaLibraryModule
- aconfigIntermediates android.Paths
-
- // Aconfig files for all transitive deps. Also exposed via JavaInfo
- transitiveAconfigFiles *android.DepSet[android.Path]
+ // Single aconfig "cache file" merged from this module and all dependencies.
+ mergedAconfigFiles map[string]android.Paths
}
func (j *Module) CheckStableSdkVersion(ctx android.BaseModuleContext) error {
@@ -579,7 +578,7 @@
func (j *Module) checkHeadersOnly(ctx android.ModuleContext) {
if _, ok := ctx.Module().(android.SdkContext); ok {
- headersOnly := proptools.Bool(&j.properties.Headers_only)
+ headersOnly := proptools.Bool(j.properties.Headers_only)
installable := proptools.Bool(j.properties.Installable)
if headersOnly && installable {
@@ -618,7 +617,7 @@
// Populate with package rules from the properties.
hiddenAPIInfo.extractPackageRulesFromProperties(&j.deviceProperties.HiddenAPIPackageProperties)
- ctx.SetProvider(hiddenAPIPropertyInfoProvider, hiddenAPIInfo)
+ android.SetProvider(ctx, hiddenAPIPropertyInfoProvider, hiddenAPIInfo)
}
func (j *Module) OutputFiles(tag string) (android.Paths, error) {
@@ -638,6 +637,11 @@
return nil, fmt.Errorf("%q was requested, but no output file was found.", tag)
case ".generated_srcjars":
return j.properties.Generated_srcjars, nil
+ case ".lint":
+ if j.linter.outputs.xml != nil {
+ return android.Paths{j.linter.outputs.xml}, nil
+ }
+ return nil, fmt.Errorf("%q was requested, but no output file was found.", tag)
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
@@ -680,7 +684,7 @@
// Force enable the instrumentation for java code that is built for APEXes ...
// except for the jacocoagent itself (because instrumenting jacocoagent using jacocoagent
// doesn't make sense) or framework libraries (e.g. libraries found in the InstrumentFrameworkModules list) unless EMMA_INSTRUMENT_FRAMEWORK is true.
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
isJacocoAgent := ctx.ModuleName() == "jacocoagent"
if j.DirectlyInAnyApex() && !isJacocoAgent && !apexInfo.IsForPlatform() {
if !inList(ctx.ModuleName(), config.InstrumentFrameworkModules) {
@@ -711,6 +715,10 @@
return j.SdkVersion(ctx).ApiLevel
}
+func (j *Module) GetDeviceProperties() *DeviceProperties {
+ return &j.deviceProperties
+}
+
func (j *Module) MaxSdkVersion(ctx android.EarlyModuleContext) android.ApiLevel {
if j.deviceProperties.Max_sdk_version != nil {
return android.ApiLevelFrom(ctx, *j.deviceProperties.Max_sdk_version)
@@ -1002,8 +1010,16 @@
ctx android.ModuleContext, flags javaBuilderFlags, srcFiles android.Paths) javaBuilderFlags {
// javac flags.
javacFlags := j.properties.Javacflags
+ var needsDebugInfo bool
- if ctx.Config().MinimizeJavaDebugInfo() && !ctx.Host() {
+ needsDebugInfo = false
+ for _, flag := range javacFlags {
+ if strings.HasPrefix(flag, "-g") {
+ needsDebugInfo = true
+ }
+ }
+
+ if ctx.Config().MinimizeJavaDebugInfo() && !ctx.Host() && !needsDebugInfo {
// For non-host binaries, override the -g flag passed globally to remove
// local variable debug info to reduce disk and memory usage.
javacFlags = append(javacFlags, "-g:source,lines")
@@ -1012,44 +1028,18 @@
if flags.javaVersion.usesJavaModules() {
javacFlags = append(javacFlags, j.properties.Openjdk9.Javacflags...)
+ } else if len(j.properties.Openjdk9.Javacflags) > 0 {
+ // java version defaults higher than openjdk 9, these conditionals should no longer be necessary
+ ctx.PropertyErrorf("openjdk9.javacflags", "JDK version defaults to higher than 9")
+ }
+ if flags.javaVersion.usesJavaModules() {
if j.properties.Patch_module != nil {
// Manually specify build directory in case it is not under the repo root.
// (javac doesn't seem to expand into symbolic links when searching for patch-module targets, so
// just adding a symlink under the root doesn't help.)
patchPaths := []string{".", ctx.Config().SoongOutDir()}
- // b/150878007
- //
- // Workaround to support *Bazel-executed* JDK9 javac in Bazel's
- // execution root for --patch-module. If this javac command line is
- // invoked within Bazel's execution root working directory, the top
- // level directories (e.g. libcore/, tools/, frameworks/) are all
- // symlinks. JDK9 javac does not traverse into symlinks, which causes
- // --patch-module to fail source file lookups when invoked in the
- // execution root.
- //
- // Short of patching javac or enumerating *all* directories as possible
- // input dirs, manually add the top level dir of the source files to be
- // compiled.
- topLevelDirs := map[string]bool{}
- for _, srcFilePath := range srcFiles {
- srcFileParts := strings.Split(srcFilePath.String(), "/")
- // Ignore source files that are already in the top level directory
- // as well as generated files in the out directory. The out
- // directory may be an absolute path, which means srcFileParts[0] is the
- // empty string, so check that as well. Note that "out" in Bazel's execution
- // root is *not* a symlink, which doesn't cause problems for --patch-modules
- // anyway, so it's fine to not apply this workaround for generated
- // source files.
- if len(srcFileParts) > 1 &&
- srcFileParts[0] != "" &&
- srcFileParts[0] != "out" {
- topLevelDirs[srcFileParts[0]] = true
- }
- }
- patchPaths = append(patchPaths, android.SortedKeys(topLevelDirs)...)
-
classPath := flags.classpath.FormJavaClassPath("")
if classPath != "" {
patchPaths = append(patchPaths, classPath)
@@ -1077,8 +1067,8 @@
}
-func (module *Module) addGeneratedSrcJars(path android.Path) {
- module.properties.Generated_srcjars = append(module.properties.Generated_srcjars, path)
+func (j *Module) addGeneratedSrcJars(path android.Path) {
+ j.properties.Generated_srcjars = append(j.properties.Generated_srcjars, path)
}
func (j *Module) compile(ctx android.ModuleContext, extraSrcJars, extraClasspathJars, extraCombinedJars android.Paths) {
@@ -1089,6 +1079,9 @@
if flags.javaVersion.usesJavaModules() {
j.properties.Srcs = append(j.properties.Srcs, j.properties.Openjdk9.Srcs...)
+ } else if len(j.properties.Openjdk9.Javacflags) > 0 {
+ // java version defaults higher than openjdk 9, these conditionals should no longer be necessary
+ ctx.PropertyErrorf("openjdk9.srcs", "JDK version defaults to higher than 9")
}
srcFiles := android.PathsForModuleSrcExcludes(ctx, j.properties.Srcs, j.properties.Exclude_srcs)
@@ -1149,6 +1142,7 @@
uniqueSrcFiles = append(uniqueSrcFiles, uniqueJavaFiles...)
uniqueSrcFiles = append(uniqueSrcFiles, uniqueKtFiles...)
j.uniqueSrcFiles = uniqueSrcFiles
+ android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: uniqueSrcFiles.Strings()})
// We don't currently run annotation processors in turbine, which means we can't use turbine
// generated header jars when an annotation processor that generates API is enabled. One
@@ -1168,7 +1162,7 @@
flags.classpath = append(android.CopyOf(extraClasspathJars), flags.classpath...)
// If compiling headers then compile them and skip the rest
- if j.properties.Headers_only {
+ if proptools.Bool(j.properties.Headers_only) {
if srcFiles.HasExt(".kt") {
ctx.ModuleErrorf("Compiling headers_only with .kt not supported")
}
@@ -1183,7 +1177,7 @@
return
}
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
+ android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
HeaderJars: android.PathsIfNonNil(j.headerJarFile),
TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
@@ -1343,10 +1337,17 @@
jars = append(jars, classes)
}
}
+ // Assume approximately 5 sources per srcjar.
+ // For framework-minus-apex in AOSP at the time this was written, there are 266 srcjars, with a mean
+ // of 5.8 sources per srcjar, but a median of 1, a standard deviation of 10, and a max of 48 source files.
if len(srcJars) > 0 {
- classes := j.compileJavaClasses(ctx, jarName, len(shardSrcs),
- nil, srcJars, flags, extraJarDeps)
- jars = append(jars, classes)
+ startIdx := len(shardSrcs)
+ shardSrcJarsList := android.ShardPaths(srcJars, shardSize/5)
+ for idx, shardSrcJars := range shardSrcJarsList {
+ classes := j.compileJavaClasses(ctx, jarName, startIdx+idx,
+ nil, shardSrcJars, flags, extraJarDeps)
+ jars = append(jars, classes)
+ }
}
} else {
classes := j.compileJavaClasses(ctx, jarName, -1, uniqueJavaFiles, srcJars, flags, extraJarDeps)
@@ -1570,7 +1571,7 @@
// Enable dex compilation for the APEX variants, unless it is disabled explicitly
compileDex := j.dexProperties.Compile_dex
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if j.DirectlyInAnyApex() && !apexInfo.IsForPlatform() {
if compileDex == nil {
compileDex = proptools.BoolPtr(true)
@@ -1583,7 +1584,7 @@
if ctx.Device() && (Bool(j.properties.Installable) || Bool(compileDex)) {
if j.hasCode(ctx) {
if j.shouldInstrumentStatic(ctx) {
- j.dexer.extraProguardFlagFiles = append(j.dexer.extraProguardFlagFiles,
+ j.dexer.extraProguardFlagsFiles = append(j.dexer.extraProguardFlagsFiles,
android.PathForSource(ctx, "build/make/core/proguard.jacoco.flags"))
}
// Dex compilation
@@ -1625,7 +1626,7 @@
j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
// Dexpreopting
- j.dexpreopt(ctx, dexOutputFile)
+ j.dexpreopt(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), dexOutputFile)
outputFile = dexOutputFile
} else {
@@ -1643,30 +1644,11 @@
}
if ctx.Device() {
- lintSDKVersion := func(apiLevel android.ApiLevel) int {
+ lintSDKVersion := func(apiLevel android.ApiLevel) android.ApiLevel {
if !apiLevel.IsPreview() {
- return apiLevel.FinalInt()
+ return apiLevel
} else {
- // When running metalava, we pass --version-codename. When that value
- // is not REL, metalava will add 1 to the --current-version argument.
- // On old branches, PLATFORM_SDK_VERSION is the latest version (for that
- // branch) and the codename is REL, except potentially on the most
- // recent non-master branch. On that branch, it goes through two other
- // phases before it gets to the phase previously described:
- // - PLATFORM_SDK_VERSION has not been updated yet, and the codename
- // is not rel. This happens for most of the internal branch's life
- // while the branch has been cut but is still under active development.
- // - PLATFORM_SDK_VERSION has been set, but the codename is still not
- // REL. This happens briefly during the release process. During this
- // state the code to add --current-version is commented out, and then
- // that commenting out is reverted after the codename is set to REL.
- // On the master branch, the PLATFORM_SDK_VERSION always represents a
- // prior version and the codename is always non-REL.
- //
- // We need to add one here to match metalava adding 1. Technically
- // this means that in the state described in the second bullet point
- // above, this number is 1 higher than it should be.
- return ctx.Config().PlatformSdkVersion().FinalInt() + 1
+ return ctx.Config().DefaultAppTargetSdk(ctx)
}
}
@@ -1681,17 +1663,20 @@
j.linter.compileSdkKind = j.SdkVersion(ctx).Kind
j.linter.javaLanguageLevel = flags.javaVersion.String()
j.linter.kotlinLanguageLevel = "1.3"
+ j.linter.compile_data = android.PathsForModuleSrc(ctx, j.properties.Compile_data)
if !apexInfo.IsForPlatform() && ctx.Config().UnbundledBuildApps() {
j.linter.buildModuleReportZip = true
}
j.linter.lint(ctx)
}
+ j.collectTransitiveSrcFiles(ctx, srcFiles)
+
ctx.CheckbuildFile(outputFile)
- j.collectTransitiveAconfigFiles(ctx)
+ android.CollectDependencyAconfigFiles(ctx, &j.mergedAconfigFiles)
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
+ android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
HeaderJars: android.PathsIfNonNil(j.headerJarFile),
TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
@@ -1701,11 +1686,11 @@
AidlIncludeDirs: j.exportAidlIncludeDirs,
SrcJarArgs: j.srcJarArgs,
SrcJarDeps: j.srcJarDeps,
+ TransitiveSrcFiles: j.transitiveSrcFiles,
ExportedPlugins: j.exportedPluginJars,
ExportedPluginClasses: j.exportedPluginClasses,
ExportedPluginDisableTurbine: j.exportedDisableTurbine,
JacocoReportClassesFile: j.jacocoReportClassesFile,
- TransitiveAconfigFiles: j.transitiveAconfigFiles,
})
// Save the output file with no relative path so that it doesn't end up in a subdirectory when used as a resource
@@ -1721,7 +1706,7 @@
transitiveProguardFlags := []*android.DepSet[android.Path]{}
ctx.VisitDirectDeps(func(m android.Module) {
- depProguardInfo := ctx.OtherModuleProvider(m, ProguardSpecInfoProvider).(ProguardSpecInfo)
+ depProguardInfo, _ := android.OtherModuleProvider(ctx, m, ProguardSpecInfoProvider)
depTag := ctx.OtherModuleDependencyTag(m)
if depProguardInfo.UnconditionallyExportedProguardFlags != nil {
@@ -1907,20 +1892,23 @@
return
}
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
- if dep.TransitiveLibsHeaderJars != nil {
- transitiveLibs = append(transitiveLibs, dep.TransitiveLibsHeaderJars)
- }
- if dep.TransitiveStaticLibsHeaderJars != nil {
- transitiveStaticLibs = append(transitiveStaticLibs, dep.TransitiveStaticLibsHeaderJars)
- }
-
+ dep, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
tag := ctx.OtherModuleDependencyTag(module)
_, isUsesLibDep := tag.(usesLibraryDependencyTag)
if tag == libTag || tag == r8LibraryJarTag || isUsesLibDep {
directLibs = append(directLibs, dep.HeaderJars...)
} else if tag == staticLibTag {
directStaticLibs = append(directStaticLibs, dep.HeaderJars...)
+ } else {
+ // Don't propagate transitive libs for other kinds of dependencies.
+ return
+ }
+
+ if dep.TransitiveLibsHeaderJars != nil {
+ transitiveLibs = append(transitiveLibs, dep.TransitiveLibsHeaderJars)
+ }
+ if dep.TransitiveStaticLibsHeaderJars != nil {
+ transitiveStaticLibs = append(transitiveStaticLibs, dep.TransitiveStaticLibsHeaderJars)
}
})
j.transitiveLibsHeaderJars = android.NewDepSet(android.POSTORDER, directLibs, transitiveLibs)
@@ -1941,7 +1929,7 @@
return android.Paths{j.implementationJarFile}
}
-func (j *Module) DexJarBuildPath() OptionalDexJarPath {
+func (j *Module) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
return j.dexJarFile
}
@@ -1974,7 +1962,6 @@
if j.expandJarjarRules != nil {
dpInfo.Jarjar_rules = append(dpInfo.Jarjar_rules, j.expandJarjarRules.String())
}
- dpInfo.Paths = append(dpInfo.Paths, j.modulePaths...)
dpInfo.Static_libs = append(dpInfo.Static_libs, j.properties.Static_libs...)
dpInfo.Libs = append(dpInfo.Libs, j.properties.Libs...)
dpInfo.SrcJars = append(dpInfo.SrcJars, j.annoSrcJars.Strings()...)
@@ -2025,36 +2012,23 @@
return j.jacocoReportClassesFile
}
-func (j *Module) IsInstallable() bool {
- return Bool(j.properties.Installable)
-}
-
-func (j *Module) collectTransitiveAconfigFiles(ctx android.ModuleContext) {
- // Aconfig files from this module
- mine := j.aconfigIntermediates
-
- // Aconfig files from transitive dependencies
- fromDeps := []*android.DepSet[android.Path]{}
+func (j *Module) collectTransitiveSrcFiles(ctx android.ModuleContext, mine android.Paths) {
+ var fromDeps []*android.DepSet[android.Path]
ctx.VisitDirectDeps(func(module android.Module) {
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
- if dep.TransitiveAconfigFiles != nil {
- fromDeps = append(fromDeps, dep.TransitiveAconfigFiles)
+ tag := ctx.OtherModuleDependencyTag(module)
+ if tag == staticLibTag {
+ depInfo, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
+ if depInfo.TransitiveSrcFiles != nil {
+ fromDeps = append(fromDeps, depInfo.TransitiveSrcFiles)
+ }
}
})
- // DepSet containing aconfig files myself and from dependencies
- j.transitiveAconfigFiles = android.NewDepSet(android.POSTORDER, mine, fromDeps)
+ j.transitiveSrcFiles = android.NewDepSet(android.POSTORDER, mine, fromDeps)
}
-func (j *Module) AddAconfigIntermediate(path android.Path) {
- j.aconfigIntermediates = append(j.aconfigIntermediates, path)
-}
-
-func (j *Module) getTransitiveAconfigFiles() *android.DepSet[android.Path] {
- if j.transitiveAconfigFiles == nil {
- panic(fmt.Errorf("java.Moduile: getTransitiveAconfigFiles called before collectTransitiveAconfigFiles module=%s", j.Name()))
- }
- return j.transitiveAconfigFiles
+func (j *Module) IsInstallable() bool {
+ return Bool(j.properties.Installable)
}
type sdkLinkType int
@@ -2215,15 +2189,14 @@
case staticLibTag:
ctx.ModuleErrorf("dependency on java_sdk_library %q can only be in libs", otherName)
}
- } else if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
- if sdkLinkType != javaPlatform &&
- ctx.OtherModuleHasProvider(module, SyspropPublicStubInfoProvider) {
- // dep is a sysprop implementation library, but this module is not linking against
- // the platform, so it gets the sysprop public stubs library instead. Replace
- // dep with the JavaInfo from the SyspropPublicStubInfoProvider.
- syspropDep := ctx.OtherModuleProvider(module, SyspropPublicStubInfoProvider).(SyspropPublicStubInfo)
- dep = syspropDep.JavaInfo
+ } else if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
+ if sdkLinkType != javaPlatform {
+ if syspropDep, ok := android.OtherModuleProvider(ctx, module, SyspropPublicStubInfoProvider); ok {
+ // dep is a sysprop implementation library, but this module is not linking against
+ // the platform, so it gets the sysprop public stubs library instead. Replace
+ // dep with the JavaInfo from the SyspropPublicStubInfoProvider.
+ dep = syspropDep.JavaInfo
+ }
}
switch tag {
case bootClasspathTag:
@@ -2295,7 +2268,7 @@
case syspropPublicStubDepTag:
// This is a sysprop implementation library, forward the JavaInfoProvider from
// the corresponding sysprop public stub library as SyspropPublicStubInfoProvider.
- ctx.SetProvider(SyspropPublicStubInfoProvider, SyspropPublicStubInfo{
+ android.SetProvider(ctx, SyspropPublicStubInfoProvider, SyspropPublicStubInfo{
JavaInfo: dep,
})
}
@@ -2358,22 +2331,3 @@
}
var _ ModuleWithStem = (*Module)(nil)
-
-func (j *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- switch ctx.ModuleType() {
- case "java_library", "java_library_host", "java_library_static", "tradefed_java_library_host":
- if lib, ok := ctx.Module().(*Library); ok {
- javaLibraryBp2Build(ctx, lib)
- }
- case "java_binary_host":
- if binary, ok := ctx.Module().(*Binary); ok {
- javaBinaryHostBp2Build(ctx, binary)
- }
- case "java_test_host":
- if testHost, ok := ctx.Module().(*TestHost); ok {
- javaTestHostBp2Build(ctx, testHost)
- }
- default:
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
- }
-}
diff --git a/java/bootclasspath_fragment.go b/java/bootclasspath_fragment.go
index dcc2dec..7c45d30 100644
--- a/java/bootclasspath_fragment.go
+++ b/java/bootclasspath_fragment.go
@@ -23,6 +23,7 @@
"android/soong/android"
"android/soong/dexpreopt"
+ "android/soong/testing"
"github.com/google/blueprint/proptools"
@@ -228,6 +229,7 @@
type BootclasspathFragmentModule struct {
android.ModuleBase
+ android.DefaultableModuleBase
android.ApexModuleBase
ClasspathFragmentBase
@@ -238,11 +240,9 @@
sourceOnlyProperties SourceOnlyBootclasspathProperties
- // Collect the module directory for IDE info in java/jdeps.go.
- modulePaths []string
-
// Path to the boot image profile.
- profilePath android.WritablePath
+ profilePath android.WritablePath
+ profilePathErr error
}
// commonBootclasspathFragment defines the methods that are implemented by both source and prebuilt
@@ -268,6 +268,7 @@
android.InitApexModule(m)
initClasspathFragment(m, BOOTCLASSPATH)
android.InitAndroidArchModule(m, android.DeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(m)
android.AddLoadHook(m, func(ctx android.LoadHookContext) {
// If code coverage has been enabled for the framework then append the properties with
@@ -354,7 +355,7 @@
}
}
-var BootclasspathFragmentApexContentInfoProvider = blueprint.NewProvider(BootclasspathFragmentApexContentInfo{})
+var BootclasspathFragmentApexContentInfoProvider = blueprint.NewProvider[BootclasspathFragmentApexContentInfo]()
// BootclasspathFragmentApexContentInfo contains the bootclasspath_fragments contributions to the
// apex contents.
@@ -386,6 +387,10 @@
}
}
+func (i BootclasspathFragmentApexContentInfo) DexBootJarPathMap() bootDexJarByModule {
+ return i.contentModuleDexJarPaths
+}
+
func (i BootclasspathFragmentApexContentInfo) ProfilePathOnHost() android.Path {
return i.profilePathOnHost
}
@@ -396,6 +401,11 @@
func (b *BootclasspathFragmentModule) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
tag := ctx.OtherModuleDependencyTag(dep)
+
+ // If the module is a default module, do not check the tag
+ if _, ok := dep.(*Defaults); ok {
+ return true
+ }
if IsBootclasspathFragmentContentDepTag(tag) {
// Boot image contents are automatically added to apex.
return true
@@ -471,9 +481,6 @@
// Generate classpaths.proto config
b.generateClasspathProtoBuildActions(ctx)
- // Collect the module directory for IDE info in java/jdeps.go.
- b.modulePaths = append(b.modulePaths, ctx.ModuleDir())
-
// Gather the bootclasspath fragment's contents.
var contents []android.Module
ctx.VisitDirectDeps(func(module android.Module) {
@@ -505,6 +512,7 @@
if ctx.Module() != ctx.FinalModule() {
b.HideFromMake()
}
+ android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
// getProfileProviderApex returns the name of the apex that provides a boot image profile, or an
@@ -516,7 +524,7 @@
}
// Bootclasspath fragment modules that are for the platform do not produce boot related files.
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
for _, apex := range apexInfo.InApexVariants {
if isProfileProviderApex(ctx, apex) {
return apex
@@ -537,11 +545,11 @@
if profile != nil {
info.profilePathOnHost = profile
- info.profileInstallPathInApex = profileInstallPathInApex
+ info.profileInstallPathInApex = ProfileInstallPathInApex
}
// Make the apex content info available for other modules.
- ctx.SetProvider(BootclasspathFragmentApexContentInfoProvider, info)
+ android.SetProvider(ctx, BootclasspathFragmentApexContentInfoProvider, info)
}
// generateClasspathProtoBuildActions generates all required build actions for classpath.proto config
@@ -582,7 +590,7 @@
// So ignore it even if it is not in PRODUCT_APEX_BOOT_JARS.
// TODO(b/202896428): Add better way to handle this.
_, unknown = android.RemoveFromList("android.car-module", unknown)
- if len(unknown) > 0 {
+ if isActiveModule(ctx.Module()) && len(unknown) > 0 {
ctx.ModuleErrorf("%s in contents must also be declared in PRODUCT_APEX_BOOT_JARS", unknown)
}
}
@@ -627,26 +635,11 @@
hiddenAPIInfo.HiddenAPIFlagOutput = output.HiddenAPIFlagOutput
// Provide it for use by other modules.
- ctx.SetProvider(HiddenAPIInfoProvider, hiddenAPIInfo)
+ android.SetProvider(ctx, HiddenAPIInfoProvider, hiddenAPIInfo)
return output
}
-// retrieveLegacyEncodedBootDexFiles attempts to retrieve the legacy encoded boot dex jar files.
-func retrieveLegacyEncodedBootDexFiles(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
- // If the current bootclasspath_fragment is the active module or a source module then retrieve the
- // encoded dex files, otherwise return an empty map.
- //
- // An inactive (i.e. not preferred) bootclasspath_fragment needs to retrieve the encoded dex jars
- // as they are still needed by an apex. An inactive prebuilt_bootclasspath_fragment does not need
- // to do so and may not yet have access to dex boot jars from a prebuilt_apex/apex_set.
- if isActiveModule(ctx.Module()) || !android.IsModulePrebuilt(ctx.Module()) {
- return extractEncodedDexJarsFromModules(ctx, contents)
- } else {
- return nil
- }
-}
-
// createHiddenAPIFlagInput creates a HiddenAPIFlagInput struct and initializes it with information derived
// from the properties on this module and its dependencies.
func (b *BootclasspathFragmentModule) createHiddenAPIFlagInput(ctx android.ModuleContext, contents []android.Module, fragments []android.Module) HiddenAPIFlagInput {
@@ -763,7 +756,7 @@
}
// Make the information available for the sdk snapshot.
- ctx.SetProvider(HiddenAPIInfoForSdkProvider, HiddenAPIInfoForSdk{
+ android.SetProvider(ctx, HiddenAPIInfoForSdkProvider, HiddenAPIInfoForSdk{
FlagFilesByCategory: flagFilesByCategory,
HiddenAPIFlagOutput: flagOutput,
})
@@ -782,7 +775,7 @@
dexLocations := make([]string, 0, len(contents))
for _, module := range contents {
dexPaths = append(dexPaths, modules[module.Name()])
- dexLocations = append(dexLocations, filepath.Join("/", "apex", apex, "javalib", module.Name() + ".jar"))
+ dexLocations = append(dexLocations, filepath.Join("/", "apex", apex, "javalib", module.Name()+".jar"))
}
// Build a profile for the modules in this fragment.
@@ -816,7 +809,6 @@
// Collect information for opening IDE project files in java/jdeps.go.
func (b *BootclasspathFragmentModule) IDEInfo(dpInfo *android.IdeInfo) {
dpInfo.Deps = append(dpInfo.Deps, b.properties.Contents...)
- dpInfo.Paths = append(dpInfo.Paths, b.modulePaths...)
}
type bootclasspathFragmentMemberType struct {
@@ -896,7 +888,7 @@
// Get the hidden API information from the module.
mctx := ctx.SdkModuleContext()
- hiddenAPIInfo := mctx.OtherModuleProvider(module, HiddenAPIInfoForSdkProvider).(HiddenAPIInfoForSdk)
+ hiddenAPIInfo, _ := android.OtherModuleProvider(mctx, module, HiddenAPIInfoForSdkProvider)
b.Flag_files_by_category = hiddenAPIInfo.FlagFilesByCategory
// Copy all the generated file paths.
@@ -957,7 +949,7 @@
builder.CopyToSnapshot(p, dest)
dests = append(dests, dest)
}
- hiddenAPISet.AddProperty(category.PropertyName, dests)
+ hiddenAPISet.AddProperty(category.PropertyName(), dests)
}
}
}
@@ -1053,10 +1045,6 @@
return android.PathForModuleSrc(ctx, *src)
}
- // Retrieve the dex files directly from the content modules. They in turn should retrieve the
- // encoded dex jars from the prebuilt .apex files.
- encodedBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, contents)
-
output := HiddenAPIOutput{
HiddenAPIFlagOutput: HiddenAPIFlagOutput{
AnnotationFlagsPath: pathForSrc("hidden_api.annotation_flags", module.prebuiltProperties.Hidden_api.Annotation_flags),
@@ -1067,8 +1055,6 @@
StubFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.Stub_flags, nil),
AllFlagsPath: pathForOptionalSrc(module.prebuiltProperties.Hidden_api.All_flags, nil),
},
-
- EncodedBootDexFilesByModule: encodedBootDexJarsByModule,
}
// TODO: Temporarily fallback to stub_flags/all_flags properties until prebuilts have been updated.
@@ -1085,15 +1071,21 @@
return nil
}
- di := android.FindDeapexerProviderForModule(ctx)
- if di == nil {
+ di, err := android.FindDeapexerProviderForModule(ctx)
+ if err != nil {
+ // An error was found, possibly due to multiple apexes in the tree that export this library
+ // Defer the error till a client tries to call getProfilePath
+ module.profilePathErr = err
return nil // An error has been reported by FindDeapexerProviderForModule.
}
- return di.PrebuiltExportPath(profileInstallPathInApex)
+ return di.PrebuiltExportPath(ProfileInstallPathInApex)
}
func (b *PrebuiltBootclasspathFragmentModule) getProfilePath() android.Path {
+ if b.profilePathErr != nil {
+ panic(b.profilePathErr.Error())
+ }
return b.profilePath
}
@@ -1107,12 +1099,16 @@
func (module *PrebuiltBootclasspathFragmentModule) RequiredFilesFromPrebuiltApex(ctx android.BaseModuleContext) []string {
for _, apex := range module.ApexProperties.Apex_available {
if isProfileProviderApex(ctx, apex) {
- return []string{profileInstallPathInApex}
+ return []string{ProfileInstallPathInApex}
}
}
return nil
}
+func (module *PrebuiltBootclasspathFragmentModule) UseProfileGuidedDexpreopt() bool {
+ return false
+}
+
var _ android.RequiredFilesFromPrebuiltApex = (*PrebuiltBootclasspathFragmentModule)(nil)
func prebuiltBootclasspathFragmentFactory() android.Module {
diff --git a/java/bootclasspath_fragment_test.go b/java/bootclasspath_fragment_test.go
index 888caad..8bc0a7e 100644
--- a/java/bootclasspath_fragment_test.go
+++ b/java/bootclasspath_fragment_test.go
@@ -222,6 +222,11 @@
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("mysdklibrary", "myothersdklibrary", "mycoreplatform"),
FixtureConfigureApexBootJars("someapex:mysdklibrary"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTestWithBp(t, `
bootclasspath_fragment {
name: "myfragment",
@@ -272,16 +277,16 @@
`)
fragment := result.Module("myfragment", "android_common")
- info := result.ModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
+ info, _ := android.SingletonModuleProvider(result, fragment, HiddenAPIInfoProvider)
stubsJar := "out/soong/.intermediates/mystublib/android_common/dex/mystublib.jar"
// Stubs jars for mysdklibrary
- publicStubsJar := "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar"
- systemStubsJar := "out/soong/.intermediates/mysdklibrary.stubs.system/android_common/dex/mysdklibrary.stubs.system.jar"
+ publicStubsJar := "out/soong/.intermediates/mysdklibrary.stubs.exportable/android_common/dex/mysdklibrary.stubs.exportable.jar"
+ systemStubsJar := "out/soong/.intermediates/mysdklibrary.stubs.exportable.system/android_common/dex/mysdklibrary.stubs.exportable.system.jar"
// Stubs jars for myothersdklibrary
- otherPublicStubsJar := "out/soong/.intermediates/myothersdklibrary.stubs/android_common/dex/myothersdklibrary.stubs.jar"
+ otherPublicStubsJar := "out/soong/.intermediates/myothersdklibrary.stubs.exportable/android_common/dex/myothersdklibrary.stubs.exportable.jar"
// Check that SdkPublic uses public stubs for all sdk libraries.
android.AssertPathsRelativeToTopEquals(t, "public dex stubs jar", []string{otherPublicStubsJar, publicStubsJar, stubsJar}, info.TransitiveStubDexJarsByScope.StubDexJarsForScope(PublicHiddenAPIScope))
@@ -316,6 +321,60 @@
android.AssertPathsRelativeToTopEquals(t, "widest dex stubs jar", expectedWidestPaths, info.TransitiveStubDexJarsByScope.StubDexJarsForWidestAPIScope())
}
+func TestFromTextWidestApiScope(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForTestWithBootclasspathFragment,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.SetBuildFromTextStub(true)
+ }),
+ FixtureWithLastReleaseApis("mysdklibrary", "android-non-updatable"),
+ FixtureConfigureApexBootJars("someapex:mysdklibrary"),
+ ).RunTestWithBp(t, `
+ bootclasspath_fragment {
+ name: "myfragment",
+ contents: ["mysdklibrary"],
+ additional_stubs: [
+ "android-non-updatable",
+ ],
+ hidden_api: {
+ split_packages: ["*"],
+ },
+ }
+ java_sdk_library {
+ name: "mysdklibrary",
+ srcs: ["a.java"],
+ shared_library: false,
+ public: {enabled: true},
+ system: {enabled: true},
+ }
+ java_sdk_library {
+ name: "android-non-updatable",
+ srcs: ["b.java"],
+ compile_dex: true,
+ public: {
+ enabled: true,
+ },
+ system: {
+ enabled: true,
+ },
+ test: {
+ enabled: true,
+ },
+ module_lib: {
+ enabled: true,
+ },
+ }
+ `)
+
+ fragment := result.ModuleForTests("myfragment", "android_common")
+ dependencyStubDexFlag := "--dependency-stub-dex=out/soong/.intermediates/default/java/android-non-updatable.stubs.test_module_lib/android_common/dex/android-non-updatable.stubs.test_module_lib.jar"
+ stubFlagsCommand := fragment.Output("modular-hiddenapi/stub-flags.csv").RuleParams.Command
+ android.AssertStringDoesContain(t,
+ "Stub flags generating command does not include the expected dependency stub dex file",
+ stubFlagsCommand, dependencyStubDexFlag)
+}
+
func TestSnapshotWithBootclasspathFragment_HiddenAPI(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForTestWithBootclasspathFragment,
@@ -402,16 +461,16 @@
// Make sure that the library exports hidden API properties for use by the bootclasspath_fragment.
library := result.Module("mynewlibrary", "android_common")
- info := result.ModuleProvider(library, hiddenAPIPropertyInfoProvider).(HiddenAPIPropertyInfo)
+ info, _ := android.SingletonModuleProvider(result, library, hiddenAPIPropertyInfoProvider)
android.AssertArrayString(t, "split packages", []string{"sdklibrary", "newlibrary"}, info.SplitPackages)
android.AssertArrayString(t, "package prefixes", []string{"newlibrary.all.mine"}, info.PackagePrefixes)
android.AssertArrayString(t, "single packages", []string{"newlibrary.mine"}, info.SinglePackages)
for _, c := range HiddenAPIFlagFileCategories {
expectedMaxTargetQPaths := []string(nil)
- if c.PropertyName == "max_target_q" {
+ if c.PropertyName() == "max_target_q" {
expectedMaxTargetQPaths = []string{"my-new-max-target-q.txt"}
}
- android.AssertPathsRelativeToTopEquals(t, c.PropertyName, expectedMaxTargetQPaths, info.FlagFilesByCategory[c])
+ android.AssertPathsRelativeToTopEquals(t, c.PropertyName(), expectedMaxTargetQPaths, info.FlagFilesByCategory[c])
}
// Make sure that the signature-patterns.csv is passed all the appropriate package properties
diff --git a/java/builder.go b/java/builder.go
index bf91917..085e7a1 100644
--- a/java/builder.go
+++ b/java/builder.go
@@ -259,37 +259,45 @@
},
)
- checkZipAlignment = pctx.AndroidStaticRule("checkzipalign",
- blueprint.RuleParams{
- Command: "if ! ${config.ZipAlign} -c -p 4 $in > /dev/null; then " +
- "echo $in: Improper package alignment >&2; " +
- "exit 1; " +
- "else " +
- "touch $out; " +
- "fi",
- CommandDeps: []string{"${config.ZipAlign}"},
- Description: "Check zip alignment",
- },
- )
-
convertImplementationJarToHeaderJarRule = pctx.AndroidStaticRule("convertImplementationJarToHeaderJar",
blueprint.RuleParams{
Command: `${config.Zip2ZipCmd} -i ${in} -o ${out} -x 'META-INF/services/**/*'`,
CommandDeps: []string{"${config.Zip2ZipCmd}"},
})
- checkBelowTargetSdk30ForNonPreprocessedApks = pctx.AndroidStaticRule("checkBelowTargetSdk30ForNonPreprocessedApks",
+ writeCombinedProguardFlagsFileRule = pctx.AndroidStaticRule("writeCombinedProguardFlagsFileRule",
blueprint.RuleParams{
- Command: "build/soong/scripts/check_target_sdk_less_than_30.py ${config.Aapt2Cmd} $in $out",
- CommandDeps: []string{"build/soong/scripts/check_target_sdk_less_than_30.py", "${config.Aapt2Cmd}"},
- Description: "Check prebuilt target sdk version",
- },
- )
+ Command: `rm -f $out && ` +
+ `for f in $in; do ` +
+ ` echo && ` +
+ ` echo "# including $$f" && ` +
+ ` cat $$f; ` +
+ `done > $out`,
+ })
+
+ gatherReleasedFlaggedApisRule = pctx.AndroidStaticRule("gatherReleasedFlaggedApisRule",
+ blueprint.RuleParams{
+ Command: `${aconfig} dump-cache --format='{fully_qualified_name}={state:bool}' ` +
+ `--out ${out} ` +
+ `${flags_path} ` +
+ `${filter_args} `,
+ CommandDeps: []string{"${aconfig}"},
+ Description: "aconfig_bool",
+ }, "flags_path", "filter_args")
+
+ generateMetalavaRevertAnnotationsRule = pctx.AndroidStaticRule("generateMetalavaRevertAnnotationsRule",
+ blueprint.RuleParams{
+ Command: `${keep-flagged-apis} ${in} > ${out}`,
+ CommandDeps: []string{"${keep-flagged-apis}"},
+ })
)
func init() {
pctx.Import("android/soong/android")
pctx.Import("android/soong/java/config")
+
+ pctx.HostBinToolVariable("aconfig", "aconfig")
+ pctx.HostBinToolVariable("keep-flagged-apis", "keep-flagged-apis")
}
type javaBuilderFlags struct {
@@ -707,6 +715,15 @@
})
}
+func writeCombinedProguardFlagsFile(ctx android.ModuleContext, outputFile android.WritablePath, files android.Paths) {
+ ctx.Build(pctx, android.BuildParams{
+ Rule: writeCombinedProguardFlagsFileRule,
+ Description: "write combined proguard flags file",
+ Inputs: files,
+ Output: outputFile,
+ })
+}
+
type classpath android.Paths
func (x *classpath) formJoinedClassPath(optName string, sep string) string {
diff --git a/java/classpath_element.go b/java/classpath_element.go
index 4962916..abbcae7 100644
--- a/java/classpath_element.go
+++ b/java/classpath_element.go
@@ -21,7 +21,6 @@
"strings"
"android/soong/android"
- "github.com/google/blueprint"
)
// Supports constructing a list of ClasspathElement from a set of fragments and modules.
@@ -72,8 +71,7 @@
// ClasspathElementContext defines the context methods needed by CreateClasspathElements
type ClasspathElementContext interface {
- OtherModuleHasProvider(m blueprint.Module, provider blueprint.ProviderKey) bool
- OtherModuleProvider(m blueprint.Module, provider blueprint.ProviderKey) interface{}
+ android.OtherModuleProviderContext
ModuleErrorf(fmt string, args ...interface{})
}
@@ -123,12 +121,12 @@
// associated with a particular apex.
apexToFragment := map[string]android.Module{}
for _, fragment := range fragments {
- if !ctx.OtherModuleHasProvider(fragment, android.ApexInfoProvider) {
+ apexInfo, ok := android.OtherModuleProvider(ctx, fragment, android.ApexInfoProvider)
+ if !ok {
ctx.ModuleErrorf("fragment %s is not part of an apex", fragment)
continue
}
- apexInfo := ctx.OtherModuleProvider(fragment, android.ApexInfoProvider).(android.ApexInfo)
for _, apex := range apexInfo.InApexVariants {
if existing, ok := apexToFragment[apex]; ok {
ctx.ModuleErrorf("apex %s has multiple fragments, %s and %s", apex, fragment, existing)
@@ -146,8 +144,7 @@
// Iterate over the libraries to construct the ClasspathElements list.
for _, library := range libraries {
var element ClasspathElement
- if ctx.OtherModuleHasProvider(library, android.ApexInfoProvider) {
- apexInfo := ctx.OtherModuleProvider(library, android.ApexInfoProvider).(android.ApexInfo)
+ if apexInfo, ok := android.OtherModuleProvider(ctx, library, android.ApexInfoProvider); ok {
var fragment android.Module
diff --git a/java/classpath_fragment.go b/java/classpath_fragment.go
index bc9de50..2017801 100644
--- a/java/classpath_fragment.go
+++ b/java/classpath_fragment.go
@@ -178,7 +178,7 @@
ClasspathFragmentProtoInstallDir: c.installDirPath,
ClasspathFragmentProtoOutput: c.outputFilepath,
}
- ctx.SetProvider(ClasspathFragmentProtoContentInfoProvider, classpathProtoInfo)
+ android.SetProvider(ctx, ClasspathFragmentProtoContentInfoProvider, classpathProtoInfo)
}
func writeClasspathsTextproto(ctx android.ModuleContext, output android.WritablePath, jars []classpathJar) {
@@ -211,7 +211,7 @@
}}
}
-var ClasspathFragmentProtoContentInfoProvider = blueprint.NewProvider(ClasspathFragmentProtoContentInfo{})
+var ClasspathFragmentProtoContentInfoProvider = blueprint.NewProvider[ClasspathFragmentProtoContentInfo]()
type ClasspathFragmentProtoContentInfo struct {
// Whether the classpaths.proto config is generated for the fragment.
diff --git a/java/code_metadata_test.go b/java/code_metadata_test.go
new file mode 100644
index 0000000..0ef348a
--- /dev/null
+++ b/java/code_metadata_test.go
@@ -0,0 +1,114 @@
+package java
+
+import (
+ "strings"
+ "testing"
+
+ "android/soong/android"
+ soongTesting "android/soong/testing"
+ "android/soong/testing/code_metadata_internal_proto"
+ "google.golang.org/protobuf/proto"
+)
+
+func TestCodeMetadata(t *testing.T) {
+ bp := `code_metadata {
+ name: "module-name",
+ teamId: "12345",
+ code: [
+ "foo",
+ ]
+ }
+
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ }`
+ result := runCodeMetadataTest(t, android.FixtureExpectsNoErrors, bp)
+
+ module := result.ModuleForTests("module-name", "")
+
+ // Check that the provider has the right contents
+ data, _ := android.SingletonModuleProvider(result, module.Module(), soongTesting.CodeMetadataProviderKey)
+ if !strings.HasSuffix(
+ data.IntermediatePath.String(), "/intermediateCodeMetadata.pb",
+ ) {
+ t.Errorf(
+ "Missing intermediates path in provider: %s",
+ data.IntermediatePath.String(),
+ )
+ }
+
+ metadata := android.ContentFromFileRuleForTests(t, result.TestContext,
+ module.Output(data.IntermediatePath.String()))
+
+ metadataList := make([]*code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership, 0, 2)
+ teamId := "12345"
+ bpFilePath := "Android.bp"
+ targetName := "foo"
+ srcFile := []string{"a.java"}
+ expectedMetadataProto := code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{
+ TrendyTeamId: &teamId,
+ TargetName: &targetName,
+ Path: &bpFilePath,
+ SourceFiles: srcFile,
+ }
+ metadataList = append(metadataList, &expectedMetadataProto)
+
+ CodeMetadataMetadata := code_metadata_internal_proto.CodeMetadataInternal{TargetOwnershipList: metadataList}
+ protoData, _ := proto.Marshal(&CodeMetadataMetadata)
+ expectedMetadata := string(protoData)
+
+ if metadata != expectedMetadata {
+ t.Errorf(
+ "Retrieved metadata: %s is not equal to expectedMetadata: %s", metadata,
+ expectedMetadata,
+ )
+ }
+
+ // Tests for all_test_spec singleton.
+ singleton := result.SingletonForTests("all_code_metadata")
+ rule := singleton.Rule("all_code_metadata_rule")
+ prebuiltOs := result.Config.PrebuiltOS()
+ expectedCmd := "out/soong/host/" + prebuiltOs + "/bin/metadata -rule code_metadata -inputFile out/soong/all_code_metadata_paths.rsp -outputFile out/soong/ownership/all_code_metadata.pb"
+ expectedOutputFile := "out/soong/ownership/all_code_metadata.pb"
+ expectedInputFile := "out/soong/.intermediates/module-name/intermediateCodeMetadata.pb"
+ if !strings.Contains(
+ strings.TrimSpace(rule.Output.String()),
+ expectedOutputFile,
+ ) {
+ t.Errorf(
+ "Retrieved singletonOutputFile: %s is not equal to expectedSingletonOutputFile: %s",
+ rule.Output.String(), expectedOutputFile,
+ )
+ }
+
+ if !strings.Contains(
+ strings.TrimSpace(rule.Inputs[0].String()),
+ expectedInputFile,
+ ) {
+ t.Errorf(
+ "Retrieved singletonInputFile: %s is not equal to expectedSingletonInputFile: %s",
+ rule.Inputs[0].String(), expectedInputFile,
+ )
+ }
+
+ if !strings.Contains(
+ strings.TrimSpace(rule.RuleParams.Command),
+ expectedCmd,
+ ) {
+ t.Errorf(
+ "Retrieved cmd: %s doesn't contain expectedCmd: %s",
+ rule.RuleParams.Command, expectedCmd,
+ )
+ }
+}
+func runCodeMetadataTest(
+ t *testing.T, errorHandler android.FixtureErrorHandler, bp string,
+) *android.TestResult {
+ return android.GroupFixturePreparers(
+ soongTesting.PrepareForTestWithTestingBuildComponents, prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles, FixtureWithLastReleaseApis("foo"),
+ ).
+ ExtendWithErrorHandler(errorHandler).
+ RunTestWithBp(t, bp)
+}
diff --git a/java/config/Android.bp b/java/config/Android.bp
index 194e2c6..bfe83ab 100644
--- a/java/config/Android.bp
+++ b/java/config/Android.bp
@@ -12,6 +12,7 @@
],
srcs: [
"config.go",
+ "droidstubs.go",
"error_prone.go",
"kotlin.go",
"makevars.go",
diff --git a/java/config/config.go b/java/config/config.go
index 83c27d3..6a945ac 100644
--- a/java/config/config.go
+++ b/java/config/config.go
@@ -95,13 +95,11 @@
"-JXX:TieredStopAtLevel=1",
"-JDcom.android.tools.r8.emitRecordAnnotationsInDex",
"-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex",
- "-JDcom.android.tools.r8.emitRecordAnnotationsExInDex",
}, dexerJavaVmFlagsList...))
exportedVars.ExportStringListStaticVariable("R8Flags", append([]string{
"-JXmx4096M",
"-JDcom.android.tools.r8.emitRecordAnnotationsInDex",
"-JDcom.android.tools.r8.emitPermittedSubclassesAnnotationsInDex",
- "-JDcom.android.tools.r8.emitRecordAnnotationsExInDex",
}, dexerJavaVmFlagsList...))
exportedVars.ExportStringListStaticVariable("CommonJdkFlags", []string{
@@ -133,7 +131,12 @@
if override := ctx.Config().Getenv("OVERRIDE_JLINK_VERSION_NUMBER"); override != "" {
return override
}
- return "17"
+ switch ctx.Config().Getenv("EXPERIMENTAL_USE_OPENJDK21_TOOLCHAIN") {
+ case "true":
+ return "21"
+ default:
+ return "17"
+ }
})
pctx.SourcePathVariable("JavaToolchain", "${JavaHome}/bin")
@@ -216,10 +219,6 @@
hostJNIToolVariableWithSdkToolsPrebuilt("SignapkJniLibrary", "libconscrypt_openjdk_jni")
}
-func BazelJavaToolchainVars(config android.Config) string {
- return android.BazelToolchainVars(config, exportedVars)
-}
-
func hostBinToolVariableWithSdkToolsPrebuilt(name, tool string) {
pctx.VariableFunc(name, func(ctx android.PackageVarContext) string {
if ctx.Config().AlwaysUsePrebuiltSdks() {
diff --git a/java/config/droidstubs.go b/java/config/droidstubs.go
new file mode 100644
index 0000000..f46c893
--- /dev/null
+++ b/java/config/droidstubs.go
@@ -0,0 +1,72 @@
+// Copyright 2023 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 config
+
+import "strings"
+
+var (
+ metalavaFlags = []string{
+ "--color",
+ "--quiet",
+ "--format=v2",
+ "--repeat-errors-max 10",
+ "--hide UnresolvedImport",
+ "--hide InvalidNullabilityOverride",
+
+ // Force metalava to ignore classes on the classpath when an API file contains missing classes.
+ // See b/285140653 for more information.
+ "--api-class-resolution api",
+
+ // Force metalava to sort overloaded methods by their order in the source code.
+ // See b/285312164 for more information.
+ // And add concrete overrides of abstract methods, see b/299366704 for more
+ // information.
+ "--format-defaults overloaded-method-order=source,add-additional-overrides=yes",
+ }
+
+ MetalavaFlags = strings.Join(metalavaFlags, " ")
+
+ metalavaAnnotationsFlags = []string{
+ "--include-annotations",
+ "--exclude-annotation androidx.annotation.RequiresApi",
+ }
+
+ MetalavaAnnotationsFlags = strings.Join(metalavaAnnotationsFlags, " ")
+
+ metalavaAnnotationsWarningsFlags = []string{
+ // TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
+ "--hide HiddenTypedefConstant",
+ "--hide SuperfluousPrefix",
+ "--hide AnnotationExtraction",
+ // b/222738070
+ "--hide BannedThrow",
+ }
+
+ MetalavaAnnotationsWarningsFlags = strings.Join(metalavaAnnotationsWarningsFlags, " ")
+)
+
+const (
+ MetalavaAddOpens = "-J--add-opens=java.base/java.util=ALL-UNNAMED"
+)
+
+func init() {
+ exportedVars.ExportStringList("MetalavaFlags", metalavaFlags)
+
+ exportedVars.ExportString("MetalavaAddOpens", MetalavaAddOpens)
+
+ exportedVars.ExportStringListStaticVariable("MetalavaAnnotationsFlags", metalavaAnnotationsFlags)
+
+ exportedVars.ExportStringListStaticVariable("MetalavaAnnotationWarningsFlags", metalavaAnnotationsWarningsFlags)
+}
diff --git a/java/config/kotlin.go b/java/config/kotlin.go
index fc63f4d..e5e187c 100644
--- a/java/config/kotlin.go
+++ b/java/config/kotlin.go
@@ -49,8 +49,5 @@
"-J--add-opens=java.base/java.util=ALL-UNNAMED", // https://youtrack.jetbrains.com/issue/KT-43704
}, " "))
- pctx.StaticVariable("KotlincGlobalFlags", strings.Join([]string{
- // b/222162908: prevent kotlinc from reading /tmp/build.txt
- "-Didea.plugins.compatible.build=999.SNAPSHOT",
- }, " "))
+ pctx.StaticVariable("KotlincGlobalFlags", strings.Join([]string{}, " "))
}
diff --git a/java/config/makevars.go b/java/config/makevars.go
index 4e09195..649b6c5 100644
--- a/java/config/makevars.go
+++ b/java/config/makevars.go
@@ -34,8 +34,6 @@
ctx.Strict("ANDROID_JAVA_HOME", "${JavaHome}")
ctx.Strict("ANDROID_JAVA8_HOME", "prebuilts/jdk/jdk8/${hostPrebuiltTag}")
- ctx.Strict("ANDROID_JAVA9_HOME", "prebuilts/jdk/jdk9/${hostPrebuiltTag}")
- ctx.Strict("ANDROID_JAVA11_HOME", "prebuilts/jdk/jdk11/${hostPrebuiltTag}")
ctx.Strict("ANDROID_JAVA_TOOLCHAIN", "${JavaToolchain}")
ctx.Strict("JAVA", "${JavaCmd} ${JavaVmFlags}")
ctx.Strict("JAVAC", "${JavacCmd} ${JavacVmFlags}")
diff --git a/java/core-libraries/Android.bp b/java/core-libraries/Android.bp
index 4380f4f..8ffe511 100644
--- a/java/core-libraries/Android.bp
+++ b/java/core-libraries/Android.bp
@@ -38,9 +38,6 @@
visibility: ["//visibility:public"],
sdk_version: "none",
system_modules: "none",
- dist: {
- targets: dist_targets,
- },
}
java_library {
@@ -66,6 +63,7 @@
libs: [
"stub-annotations",
],
+ enable_validation: false,
}
java_library {
@@ -88,6 +86,32 @@
},
}
+java_library {
+ name: "core.current.stubs.exportable.from-source",
+ defaults: [
+ "core.current.stubs.defaults",
+ ],
+ static_libs: [
+ "art.module.public.api.stubs.exportable",
+ "conscrypt.module.public.api.stubs.exportable",
+ "i18n.module.public.api.stubs.exportable",
+ ],
+ dist: {
+ targets: dist_targets,
+ dest: "core.current.stubs.jar",
+ },
+}
+
+java_library {
+ name: "core.current.stubs.exportable",
+ defaults: [
+ "core.current.stubs.defaults",
+ ],
+ static_libs: [
+ "core.current.stubs.exportable.from-source",
+ ],
+}
+
// Distributed with the SDK for turning into system modules to compile apps
// against.
//
@@ -206,6 +230,26 @@
],
}
+java_api_library {
+ name: "core.module_lib.stubs.from-text",
+ api_surface: "module-lib",
+ api_contributions: [
+ "art.module.public.api.stubs.source.api.contribution",
+ "art.module.public.api.stubs.source.system.api.contribution",
+ "art.module.public.api.stubs.source.module_lib.api.contribution",
+
+ // Add the module-lib correspondence when Conscrypt or i18N module
+ // provides @SystemApi(MODULE_LIBRARIES). Currently, assume that only ART module provides
+ // @SystemApi(MODULE_LIBRARIES).
+ "conscrypt.module.public.api.stubs.source.api.contribution",
+ "i18n.module.public.api.stubs.source.api.contribution",
+ ],
+ libs: [
+ "stub-annotations",
+ ],
+ visibility: ["//visibility:private"],
+}
+
// Produces a dist file that is used by the
// prebuilts/sdk/update_prebuilts.py script to update the prebuilts/sdk
// directory.
@@ -277,6 +321,19 @@
],
}
+java_library {
+ name: "legacy.core.platform.api.stubs.exportable.from-source",
+ visibility: core_platform_visibility,
+ defaults: [
+ "core.platform.api.stubs.defaults",
+ ],
+ static_libs: [
+ "art.module.public.api.stubs.exportable.module_lib",
+ "conscrypt.module.platform.api.stubs.exportable",
+ "legacy.i18n.module.platform.api.stubs.exportable",
+ ],
+}
+
java_defaults {
name: "android_core_platform_stubs_current_contributions",
api_surface: "core_platform",
@@ -324,6 +381,17 @@
},
}
+java_library {
+ name: "legacy.core.platform.api.stubs.exportable",
+ visibility: core_platform_visibility,
+ defaults: [
+ "core.platform.api.stubs.defaults",
+ ],
+ static_libs: [
+ "legacy.core.platform.api.stubs.exportable.from-source",
+ ],
+}
+
java_defaults {
name: "core.platform.api.stubs.defaults",
hostdex: true,
@@ -503,7 +571,3 @@
"art-module-intra-core-api-stubs-system-modules-lib",
],
}
-
-build = [
- "TxtStubLibraries.bp",
-]
diff --git a/java/core-libraries/TxtStubLibraries.bp b/java/core-libraries/TxtStubLibraries.bp
deleted file mode 100644
index c46f8b8..0000000
--- a/java/core-libraries/TxtStubLibraries.bp
+++ /dev/null
@@ -1,140 +0,0 @@
-// 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.
-
-// This file contains java_system_modules provided by the SDK.
-// These system modules transitively depend on core stub libraries generated from .txt files.
-
-// Same as core-public-stubs-system-modules, but the stubs are generated from .txt files
-java_system_modules {
- name: "core-public-stubs-system-modules.from-text",
- visibility: ["//visibility:public"],
- libs: [
- "core-current-stubs-for-system-modules-no-annotations.from-text",
- ],
-}
-
-java_library {
- name: "core-current-stubs-for-system-modules-no-annotations.from-text",
- visibility: ["//visibility:private"],
- defaults: [
- "system-modules-no-annotations",
- ],
- static_libs: [
- "core.current.stubs.from-text",
- "core-lambda-stubs.from-text",
- ],
-}
-
-// Same as core-module-lib-stubs-system-modules, but the stubs are generated from .txt files
-java_system_modules {
- name: "core-module-lib-stubs-system-modules.from-text",
- visibility: ["//visibility:public"],
- libs: [
- "core-module-lib-stubs-for-system-modules-no-annotations.from-text",
- ],
-}
-
-java_library {
- name: "core-module-lib-stubs-for-system-modules-no-annotations.from-text",
- visibility: ["//visibility:private"],
- defaults: [
- "system-modules-no-annotations",
- ],
- static_libs: [
- "core.module_lib.stubs.from-text",
- "core-lambda-stubs.from-text",
- ],
-}
-
-java_api_library {
- name: "core.module_lib.stubs.from-text",
- api_surface: "module-lib",
- api_contributions: [
- "art.module.public.api.stubs.source.api.contribution",
- "art.module.public.api.stubs.source.system.api.contribution",
- "art.module.public.api.stubs.source.module_lib.api.contribution",
-
- // Add the module-lib correspondence when Conscrypt or i18N module
- // provides @SystemApi(MODULE_LIBRARIES). Currently, assume that only ART module provides
- // @SystemApi(MODULE_LIBRARIES).
- "conscrypt.module.public.api.stubs.source.api.contribution",
- "i18n.module.public.api.stubs.source.api.contribution",
- ],
- libs: [
- "stub-annotations",
- ],
- visibility: ["//visibility:private"],
-}
-
-// Same as legacy-core-platform-api-stubs-system-modules, but the stubs are generated from .txt files
-java_system_modules {
- name: "legacy-core-platform-api-stubs-system-modules.from-text",
- visibility: core_platform_visibility,
- libs: [
- "legacy.core.platform.api.no.annotations.stubs.from-text",
- "core-lambda-stubs.from-text",
- ],
-}
-
-java_library {
- name: "legacy.core.platform.api.no.annotations.stubs.from-text",
- visibility: core_platform_visibility,
- defaults: [
- "system-modules-no-annotations",
- ],
- hostdex: true,
- compile_dex: true,
-
- static_libs: [
- "legacy.core.platform.api.stubs.from-text",
- ],
- patch_module: "java.base",
-}
-
-// Same as stable-core-platform-api-stubs-system-modules, but the stubs are generated from .txt files
-java_system_modules {
- name: "stable-core-platform-api-stubs-system-modules.from-text",
- visibility: core_platform_visibility,
- libs: [
- "stable.core.platform.api.no.annotations.stubs.from-text",
- "core-lambda-stubs.from-text",
- ],
-}
-
-java_library {
- name: "stable.core.platform.api.no.annotations.stubs.from-text",
- visibility: core_platform_visibility,
- defaults: [
- "system-modules-no-annotations",
- ],
- hostdex: true,
- compile_dex: true,
-
- static_libs: [
- "stable.core.platform.api.stubs.from-text",
- ],
- patch_module: "java.base",
-}
-
-java_api_library {
- name: "core-lambda-stubs.from-text",
- api_surface: "toolchain",
- api_contributions: [
- "art.module.toolchain.api.api.contribution",
- ],
- libs: [
- // LambdaMetaFactory depends on CallSite etc. which is part of the Core API surface
- "core.current.stubs.from-text",
- ],
-}
diff --git a/java/device_host_converter.go b/java/device_host_converter.go
index 5460dc9..efd13b8 100644
--- a/java/device_host_converter.go
+++ b/java/device_host_converter.go
@@ -19,16 +19,12 @@
"io"
"android/soong/android"
- "android/soong/bazel"
"android/soong/dexpreopt"
-
- "github.com/google/blueprint/proptools"
)
type DeviceHostConverter struct {
android.ModuleBase
android.DefaultableModuleBase
- android.BazelModuleBase
properties DeviceHostConverterProperties
@@ -80,7 +76,6 @@
module.AddProperties(&module.properties)
InitJavaModule(module, android.DeviceSupported)
- android.InitBazelModule(module)
return module
}
@@ -102,8 +97,7 @@
}
ctx.VisitDirectDepsWithTag(deviceHostConverterDepTag, func(m android.Module) {
- if ctx.OtherModuleHasProvider(m, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(m, JavaInfoProvider).(JavaInfo)
+ if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
d.headerJars = append(d.headerJars, dep.HeaderJars...)
d.implementationJars = append(d.implementationJars, dep.ImplementationJars...)
d.implementationAndResourceJars = append(d.implementationAndResourceJars, dep.ImplementationAndResourcesJars...)
@@ -136,7 +130,7 @@
d.combinedHeaderJar = d.headerJars[0]
}
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
+ android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
HeaderJars: d.headerJars,
ImplementationAndResourcesJars: d.implementationAndResourceJars,
ImplementationJars: d.implementationJars,
@@ -157,7 +151,7 @@
return d.implementationAndResourceJars
}
-func (d *DeviceHostConverter) DexJarBuildPath() android.Path {
+func (d *DeviceHostConverter) DexJarBuildPath(ctx android.ModuleErrorfContext) android.Path {
return nil
}
@@ -193,32 +187,3 @@
},
}
}
-
-type bazelDeviceHostConverterAttributes struct {
- Exports bazel.LabelListAttribute
-}
-
-func (d *DeviceHostConverter) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "java_host_for_device",
- Bzl_load_location: "//build/bazel/rules/java:host_for_device.bzl",
- },
- android.CommonAttributes{Name: d.Name()},
- &bazelDeviceHostConverterAttributes{
- Exports: bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, d.properties.Libs)),
- },
- )
- neverLinkAttrs := &javaLibraryAttributes{
- Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + d.Name()}),
- Neverlink: bazel.BoolAttribute{Value: proptools.BoolPtr(true)},
- javaCommonAttributes: &javaCommonAttributes{
- Sdk_version: bazel.StringAttribute{Value: proptools.StringPtr("none")},
- },
- }
- ctx.CreateBazelTargetModule(
- javaLibraryBazelTargetModuleProperties(),
- android.CommonAttributes{Name: d.Name() + "-neverlink"},
- neverLinkAttrs)
-
-}
diff --git a/java/dex.go b/java/dex.go
index 5b8cf3d..cdae0a2 100644
--- a/java/dex.go
+++ b/java/dex.go
@@ -91,10 +91,12 @@
dexProperties DexProperties
// list of extra proguard flag files
- extraProguardFlagFiles android.Paths
- proguardDictionary android.OptionalPath
- proguardConfiguration android.OptionalPath
- proguardUsageZip android.OptionalPath
+ extraProguardFlagsFiles android.Paths
+ proguardDictionary android.OptionalPath
+ proguardConfiguration android.OptionalPath
+ proguardUsageZip android.OptionalPath
+ resourcesInput android.OptionalPath
+ resourcesOutput android.OptionalPath
providesTransitiveHeaderJars
}
@@ -106,14 +108,12 @@
var d8, d8RE = pctx.MultiCommandRemoteStaticRules("d8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
- `mkdir -p $$(dirname $tmpJar) && ` +
- `${config.Zip2ZipCmd} -i $in -o $tmpJar -x '**/*.dex' && ` +
- `$d8Template${config.D8Cmd} ${config.D8Flags} --output $outDir $d8Flags $tmpJar && ` +
+ `$d8Template${config.D8Cmd} ${config.D8Flags} $d8Flags --output $outDir --no-dex-input-jar $in && ` +
`$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
- `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in`,
+ `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in && ` +
+ `rm -f "$outDir/classes*.dex" "$outDir/classes.dex.jar"`,
CommandDeps: []string{
"${config.D8Cmd}",
- "${config.Zip2ZipCmd}",
"${config.SoongZipCmd}",
"${config.MergeZipsCmd}",
},
@@ -132,32 +132,29 @@
ExecStrategy: "${config.RED8ExecStrategy}",
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
},
- }, []string{"outDir", "d8Flags", "zipFlags", "tmpJar", "mergeZipsFlags"}, nil)
+ }, []string{"outDir", "d8Flags", "zipFlags", "mergeZipsFlags"}, nil)
var r8, r8RE = pctx.MultiCommandRemoteStaticRules("r8",
blueprint.RuleParams{
Command: `rm -rf "$outDir" && mkdir -p "$outDir" && ` +
`rm -f "$outDict" && rm -f "$outConfig" && rm -rf "${outUsageDir}" && ` +
`mkdir -p $$(dirname ${outUsage}) && ` +
- `mkdir -p $$(dirname $tmpJar) && ` +
- `${config.Zip2ZipCmd} -i $in -o $tmpJar -x '**/*.dex' && ` +
- `$r8Template${config.R8Cmd} ${config.R8Flags} -injars $tmpJar --output $outDir ` +
+ `$r8Template${config.R8Cmd} ${config.R8Flags} $r8Flags -injars $in --output $outDir ` +
`--no-data-resources ` +
`-printmapping ${outDict} ` +
`-printconfiguration ${outConfig} ` +
`-printusage ${outUsage} ` +
- `--deps-file ${out}.d ` +
- `$r8Flags && ` +
+ `--deps-file ${out}.d && ` +
`touch "${outDict}" "${outConfig}" "${outUsage}" && ` +
`${config.SoongZipCmd} -o ${outUsageZip} -C ${outUsageDir} -f ${outUsage} && ` +
`rm -rf ${outUsageDir} && ` +
`$zipTemplate${config.SoongZipCmd} $zipFlags -o $outDir/classes.dex.jar -C $outDir -f "$outDir/classes*.dex" && ` +
- `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in`,
+ `${config.MergeZipsCmd} -D -stripFile "**/*.class" $mergeZipsFlags $out $outDir/classes.dex.jar $in && ` +
+ `rm -f "$outDir/classes*.dex" "$outDir/classes.dex.jar"`,
Depfile: "${out}.d",
Deps: blueprint.DepsGCC,
CommandDeps: []string{
"${config.R8Cmd}",
- "${config.Zip2ZipCmd}",
"${config.SoongZipCmd}",
"${config.MergeZipsCmd}",
},
@@ -165,7 +162,7 @@
"$r8Template": &remoteexec.REParams{
Labels: map[string]string{"type": "compile", "compiler": "r8"},
Inputs: []string{"$implicits", "${config.R8Jar}"},
- OutputFiles: []string{"${outUsage}", "${outConfig}", "${outDict}"},
+ OutputFiles: []string{"${outUsage}", "${outConfig}", "${outDict}", "${resourcesOutput}"},
ExecStrategy: "${config.RER8ExecStrategy}",
ToolchainInputs: []string{"${config.JavaCmd}"},
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
@@ -185,7 +182,7 @@
Platform: map[string]string{remoteexec.PoolKey: "${config.REJavaPool}"},
},
}, []string{"outDir", "outDict", "outConfig", "outUsage", "outUsageZip", "outUsageDir",
- "r8Flags", "zipFlags", "tmpJar", "mergeZipsFlags"}, []string{"implicits"})
+ "r8Flags", "zipFlags", "mergeZipsFlags", "resourcesOutput"}, []string{"implicits"})
func (d *dexer) dexCommonFlags(ctx android.ModuleContext,
dexParams *compileDexParams) (flags []string, deps android.Paths) {
@@ -264,7 +261,7 @@
// See b/20667396
var proguardRaiseDeps classpath
ctx.VisitDirectDepsWithTag(proguardRaiseTag, func(m android.Module) {
- dep := ctx.OtherModuleProvider(m, JavaInfoProvider).(JavaInfo)
+ dep, _ := android.OtherModuleProvider(ctx, m, JavaInfoProvider)
proguardRaiseDeps = append(proguardRaiseDeps, dep.HeaderJars...)
})
@@ -299,11 +296,13 @@
android.PathForSource(ctx, "build/make/core/proguard.flags"),
}
- flagFiles = append(flagFiles, d.extraProguardFlagFiles...)
+ flagFiles = append(flagFiles, d.extraProguardFlagsFiles...)
// TODO(ccross): static android library proguard files
flagFiles = append(flagFiles, android.PathsForModuleSrc(ctx, opt.Proguard_flags_files)...)
+ flagFiles = android.FirstUniquePaths(flagFiles)
+
r8Flags = append(r8Flags, android.JoinWithPrefix(flagFiles.Strings(), "-include "))
r8Deps = append(r8Deps, flagFiles...)
@@ -315,15 +314,14 @@
if BoolDefault(opt.Proguard_compatibility, true) {
r8Flags = append(r8Flags, "--force-proguard-compatibility")
- } else {
+ }
+
+ if Bool(opt.Optimize) || Bool(opt.Obfuscate) {
// TODO(b/213833843): Allow configuration of the prefix via a build variable.
var sourceFilePrefix = "go/retraceme "
var sourceFileTemplate = "\"" + sourceFilePrefix + "%MAP_ID\""
- // TODO(b/200967150): Also tag the source file in compat builds.
- if Bool(opt.Optimize) || Bool(opt.Obfuscate) {
- r8Flags = append(r8Flags, "--map-id-template", "%MAP_HASH")
- r8Flags = append(r8Flags, "--source-file-template", sourceFileTemplate)
- }
+ r8Flags = append(r8Flags, "--map-id-template", "%MAP_HASH")
+ r8Flags = append(r8Flags, "--source-file-template", sourceFileTemplate)
}
// TODO(ccross): Don't shrink app instrumentation tests by default.
@@ -353,6 +351,12 @@
r8Flags = append(r8Flags, "-ignorewarnings")
}
+ if d.resourcesInput.Valid() {
+ r8Flags = append(r8Flags, "--resource-input", d.resourcesInput.Path().String())
+ r8Deps = append(r8Deps, d.resourcesInput.Path())
+ r8Flags = append(r8Flags, "--resource-output", d.resourcesOutput.Path().String())
+ }
+
return r8Flags, r8Deps
}
@@ -369,7 +373,6 @@
// Compile classes.jar into classes.dex and then javalib.jar
javalibJar := android.PathForModuleOut(ctx, "dex", dexParams.jarName).OutputPath
outDir := android.PathForModuleOut(ctx, "dex")
- tmpJar := android.PathForModuleOut(ctx, "withres-withoutdex", dexParams.jarName)
zipFlags := "--ignore_missing_files"
if proptools.Bool(d.dexProperties.Uncompress_dex) {
@@ -395,6 +398,8 @@
android.ModuleNameWithPossibleOverride(ctx), "unused.txt")
proguardUsageZip := android.PathForModuleOut(ctx, "proguard_usage.zip")
d.proguardUsageZip = android.OptionalPathForPath(proguardUsageZip)
+ resourcesOutput := android.PathForModuleOut(ctx, "package-res-shrunken.apk")
+ d.resourcesOutput = android.OptionalPathForPath(resourcesOutput)
r8Flags, r8Deps := d.r8Flags(ctx, dexParams.flags)
r8Deps = append(r8Deps, commonDeps...)
rule := r8
@@ -407,24 +412,28 @@
"outUsage": proguardUsage.String(),
"outUsageZip": proguardUsageZip.String(),
"outDir": outDir.String(),
- "tmpJar": tmpJar.String(),
"mergeZipsFlags": mergeZipsFlags,
}
if ctx.Config().UseRBE() && ctx.Config().IsEnvTrue("RBE_R8") {
rule = r8RE
args["implicits"] = strings.Join(r8Deps.Strings(), ",")
}
+ implicitOutputs := android.WritablePaths{
+ proguardDictionary,
+ proguardUsageZip,
+ proguardConfiguration}
+ if d.resourcesInput.Valid() {
+ implicitOutputs = append(implicitOutputs, resourcesOutput)
+ args["resourcesOutput"] = resourcesOutput.String()
+ }
ctx.Build(pctx, android.BuildParams{
- Rule: rule,
- Description: "r8",
- Output: javalibJar,
- ImplicitOutputs: android.WritablePaths{
- proguardDictionary,
- proguardUsageZip,
- proguardConfiguration},
- Input: dexParams.classesJar,
- Implicits: r8Deps,
- Args: args,
+ Rule: rule,
+ Description: "r8",
+ Output: javalibJar,
+ ImplicitOutputs: implicitOutputs,
+ Input: dexParams.classesJar,
+ Implicits: r8Deps,
+ Args: args,
})
} else {
d8Flags, d8Deps := d8Flags(dexParams.flags)
@@ -443,7 +452,6 @@
"d8Flags": strings.Join(append(commonFlags, d8Flags...), " "),
"zipFlags": zipFlags,
"outDir": outDir.String(),
- "tmpJar": tmpJar.String(),
"mergeZipsFlags": mergeZipsFlags,
},
})
diff --git a/java/dex_test.go b/java/dex_test.go
index ec1ef15..1ecdae0 100644
--- a/java/dex_test.go
+++ b/java/dex_test.go
@@ -385,13 +385,53 @@
func TestProguardFlagsInheritance(t *testing.T) {
directDepFlagsFileName := "direct_dep.flags"
transitiveDepFlagsFileName := "transitive_dep.flags"
- bp := `
- android_app {
- name: "app",
- static_libs: ["androidlib"], // this must be static_libs to initate dexing
- platform_apis: true,
- }
+ topLevelModules := []struct {
+ name string
+ definition string
+ }{
+ {
+ name: "android_app",
+ definition: `
+ android_app {
+ name: "app",
+ static_libs: ["androidlib"], // this must be static_libs to initate dexing
+ platform_apis: true,
+ }
+ `,
+ },
+ {
+ name: "android_library",
+ definition: `
+ android_library {
+ name: "app",
+ static_libs: ["androidlib"], // this must be static_libs to initate dexing
+ installable: true,
+ optimize: {
+ enabled: true,
+ shrink: true,
+ },
+ }
+ `,
+ },
+ {
+ name: "java_library",
+ definition: `
+ java_library {
+ name: "app",
+ static_libs: ["androidlib"], // this must be static_libs to initate dexing
+ srcs: ["Foo.java"],
+ installable: true,
+ optimize: {
+ enabled: true,
+ shrink: true,
+ },
+ }
+ `,
+ },
+ }
+
+ bp := `
android_library {
name: "androidlib",
static_libs: ["app_dep"],
@@ -558,43 +598,46 @@
},
}
- for _, tc := range testcases {
- t.Run(tc.name, func(t *testing.T) {
- result := android.GroupFixturePreparers(
- PrepareForTestWithJavaDefaultModules,
- android.FixtureMergeMockFs(android.MockFS{
- directDepFlagsFileName: nil,
- transitiveDepFlagsFileName: nil,
- }),
- ).RunTestWithBp(t,
- fmt.Sprintf(
- bp,
- tc.depType,
- tc.transitiveDepType,
- tc.depExportsFlagsFiles,
- tc.transitiveDepExportsFlagsFiles,
- ),
- )
- appR8 := result.ModuleForTests("app", "android_common").Rule("r8")
+ for _, topLevelModuleDef := range topLevelModules {
+ for _, tc := range testcases {
+ t.Run(topLevelModuleDef.name+"-"+tc.name, func(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.FixtureMergeMockFs(android.MockFS{
+ directDepFlagsFileName: nil,
+ transitiveDepFlagsFileName: nil,
+ }),
+ ).RunTestWithBp(t,
+ topLevelModuleDef.definition+
+ fmt.Sprintf(
+ bp,
+ tc.depType,
+ tc.transitiveDepType,
+ tc.depExportsFlagsFiles,
+ tc.transitiveDepExportsFlagsFiles,
+ ),
+ )
+ appR8 := result.ModuleForTests("app", "android_common").Rule("r8")
- shouldHaveDepFlags := android.InList(directDepFlagsFileName, tc.expectedFlagsFiles)
- if shouldHaveDepFlags {
- android.AssertStringDoesContain(t, "expected deps's proguard flags",
- appR8.Args["r8Flags"], directDepFlagsFileName)
- } else {
- android.AssertStringDoesNotContain(t, "app did not expect deps's proguard flags",
- appR8.Args["r8Flags"], directDepFlagsFileName)
- }
+ shouldHaveDepFlags := android.InList(directDepFlagsFileName, tc.expectedFlagsFiles)
+ if shouldHaveDepFlags {
+ android.AssertStringDoesContain(t, "expected deps's proguard flags",
+ appR8.Args["r8Flags"], directDepFlagsFileName)
+ } else {
+ android.AssertStringDoesNotContain(t, "app did not expect deps's proguard flags",
+ appR8.Args["r8Flags"], directDepFlagsFileName)
+ }
- shouldHaveTransitiveDepFlags := android.InList(transitiveDepFlagsFileName, tc.expectedFlagsFiles)
- if shouldHaveTransitiveDepFlags {
- android.AssertStringDoesContain(t, "expected transitive deps's proguard flags",
- appR8.Args["r8Flags"], transitiveDepFlagsFileName)
- } else {
- android.AssertStringDoesNotContain(t, "app did not expect transitive deps's proguard flags",
- appR8.Args["r8Flags"], transitiveDepFlagsFileName)
- }
- })
+ shouldHaveTransitiveDepFlags := android.InList(transitiveDepFlagsFileName, tc.expectedFlagsFiles)
+ if shouldHaveTransitiveDepFlags {
+ android.AssertStringDoesContain(t, "expected transitive deps's proguard flags",
+ appR8.Args["r8Flags"], transitiveDepFlagsFileName)
+ } else {
+ android.AssertStringDoesNotContain(t, "app did not expect transitive deps's proguard flags",
+ appR8.Args["r8Flags"], transitiveDepFlagsFileName)
+ }
+ })
+ }
}
}
@@ -606,11 +649,6 @@
platform_apis: true,
}
- android_library {
- name: "androidlib",
- static_libs: ["aarimport"],
- }
-
android_library_import {
name: "aarimport",
aars: ["import.aar"],
diff --git a/java/dexpreopt.go b/java/dexpreopt.go
index 998730e..9db9b1b 100644
--- a/java/dexpreopt.go
+++ b/java/dexpreopt.go
@@ -29,7 +29,7 @@
IsInstallable() bool
// True if dexpreopt is disabled for the java module.
- dexpreoptDisabled(ctx android.BaseModuleContext) bool
+ dexpreoptDisabled(ctx android.BaseModuleContext, libraryName string) bool
// If the java module is to be installed into an APEX, this list contains information about the
// dexpreopt outputs to be installed on devices. Note that these dexpreopt outputs are installed
@@ -79,18 +79,25 @@
func (install dexpreopterInstall) ToMakeEntries() android.AndroidMkEntries {
return android.AndroidMkEntries{
Class: "ETC",
- SubName: install.SubModuleName(),
OutputFile: android.OptionalPathForPath(install.outputPathOnHost),
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
+ entries.SetString("LOCAL_MODULE", install.FullModuleName())
entries.SetString("LOCAL_MODULE_PATH", install.installDirOnDevice.String())
entries.SetString("LOCAL_INSTALLED_MODULE_STEM", install.installFileOnDevice)
entries.SetString("LOCAL_NOT_AVAILABLE_FOR_PLATFORM", "false")
+ // Unset LOCAL_SOONG_INSTALLED_MODULE so that this does not default to the primary .apex file
+ // Without this, installation of the dexpreopt artifacts get skipped
+ entries.SetString("LOCAL_SOONG_INSTALLED_MODULE", "")
},
},
}
}
+type Dexpreopter struct {
+ dexpreopter
+}
+
type dexpreopter struct {
dexpreoptProperties DexpreoptProperties
importDexpreoptProperties ImportDexpreoptProperties
@@ -166,24 +173,18 @@
}
func isApexVariant(ctx android.BaseModuleContext) bool {
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
return !apexInfo.IsForPlatform()
}
func forPrebuiltApex(ctx android.BaseModuleContext) bool {
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
return apexInfo.ForPrebuiltApex
}
-func moduleName(ctx android.BaseModuleContext) string {
- // Remove the "prebuilt_" prefix if the module is from a prebuilt because the prefix is not
- // expected by dexpreopter.
- return android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName())
-}
-
// Returns whether dexpreopt is applicable to the module.
// When it returns true, neither profile nor dexpreopt artifacts will be generated.
-func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext) bool {
+func (d *dexpreopter) dexpreoptDisabled(ctx android.BaseModuleContext, libName string) bool {
if !ctx.Device() {
return true
}
@@ -206,11 +207,20 @@
return true
}
+ if _, isApex := android.ModuleProvider(ctx, android.ApexBundleInfoProvider); isApex {
+ // dexpreopt rules for system server jars can be generated in the ModuleCtx of prebuilt apexes
+ return false
+ }
+
global := dexpreopt.GetGlobalConfig(ctx)
- isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx))
- if isApexVariant(ctx) {
- // Don't preopt APEX variant module unless the module is an APEX system server jar.
+ // Use the libName argument to determine if the library being dexpreopt'd is a system server jar
+ // ctx.ModuleName() is not safe. In case of prebuilt apexes, the dexpreopt rules of system server jars
+ // are created in the ctx object of the top-level prebuilt apex.
+ isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(libName)
+
+ if _, isApex := android.ModuleProvider(ctx, android.ApexBundleInfoProvider); isApex || isApexVariant(ctx) {
+ // dexpreopt rules for system server jars can be generated in the ModuleCtx of prebuilt apexes
if !isApexSystemServerJar {
return true
}
@@ -227,14 +237,20 @@
}
func dexpreoptToolDepsMutator(ctx android.BottomUpMutatorContext) {
- if d, ok := ctx.Module().(DexpreopterInterface); !ok || d.dexpreoptDisabled(ctx) || !dexpreopt.IsDex2oatNeeded(ctx) {
+ if _, isApex := android.ModuleProvider(ctx, android.ApexBundleInfoProvider); isApex && dexpreopt.IsDex2oatNeeded(ctx) {
+ // prebuilt apexes can genererate rules to dexpreopt deapexed jars
+ // Add a dex2oat dep aggressively on _every_ apex module
+ dexpreopt.RegisterToolDeps(ctx)
+ return
+ }
+ if d, ok := ctx.Module().(DexpreopterInterface); !ok || d.dexpreoptDisabled(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName())) || !dexpreopt.IsDex2oatNeeded(ctx) {
return
}
dexpreopt.RegisterToolDeps(ctx)
}
-func (d *dexpreopter) odexOnSystemOther(ctx android.ModuleContext, installPath android.InstallPath) bool {
- return dexpreopt.OdexOnSystemOtherByName(moduleName(ctx), android.InstallPathToOnDevicePath(ctx, installPath), dexpreopt.GetGlobalConfig(ctx))
+func (d *dexpreopter) odexOnSystemOther(ctx android.ModuleContext, libName string, installPath android.InstallPath) bool {
+ return dexpreopt.OdexOnSystemOtherByName(libName, android.InstallPathToOnDevicePath(ctx, installPath), dexpreopt.GetGlobalConfig(ctx))
}
// Returns the install path of the dex jar of a module.
@@ -245,20 +261,42 @@
// This function is on a best-effort basis. It cannot handle the case where an APEX jar is not a
// system server jar, which is fine because we currently only preopt system server jars for APEXes.
func (d *dexpreopter) getInstallPath(
- ctx android.ModuleContext, defaultInstallPath android.InstallPath) android.InstallPath {
+ ctx android.ModuleContext, libName string, defaultInstallPath android.InstallPath) android.InstallPath {
global := dexpreopt.GetGlobalConfig(ctx)
- if global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx)) {
- dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, moduleName(ctx))
+ if global.AllApexSystemServerJars(ctx).ContainsJar(libName) {
+ dexLocation := dexpreopt.GetSystemServerDexLocation(ctx, global, libName)
return android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexLocation, "/"))
}
- if !d.dexpreoptDisabled(ctx) && isApexVariant(ctx) &&
+ if !d.dexpreoptDisabled(ctx, libName) && isApexVariant(ctx) &&
filepath.Base(defaultInstallPath.PartitionDir()) != "apex" {
ctx.ModuleErrorf("unable to get the install path of the dex jar for dexpreopt")
}
return defaultInstallPath
}
-func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, dexJarFile android.WritablePath) {
+// DexpreoptPrebuiltApexSystemServerJars generates the dexpreopt artifacts from a jar file that has been deapexed from a prebuilt apex
+func (d *Dexpreopter) DexpreoptPrebuiltApexSystemServerJars(ctx android.ModuleContext, libraryName string, di *android.DeapexerInfo) {
+ // A single prebuilt apex can have multiple apex system jars
+ // initialize the output path for this dex jar
+ dc := dexpreopt.GetGlobalConfig(ctx)
+ d.installPath = android.PathForModuleInPartitionInstall(ctx, "", strings.TrimPrefix(dexpreopt.GetSystemServerDexLocation(ctx, dc, libraryName), "/"))
+ // generate the rules for creating the .odex and .vdex files for this system server jar
+ dexJarFile := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName))
+
+ d.inputProfilePathOnHost = nil // reset: TODO(spandandas): Make dexpreopter stateless
+ if android.InList(libraryName, di.GetDexpreoptProfileGuidedExportedModuleNames()) {
+ // Set the profile path to guide optimization
+ prof := di.PrebuiltExportPath(ApexRootRelativePathToJavaLib(libraryName) + ".prof")
+ if prof == nil {
+ ctx.ModuleErrorf("Could not find a .prof file in this prebuilt apex")
+ }
+ d.inputProfilePathOnHost = prof
+ }
+
+ d.dexpreopt(ctx, libraryName, dexJarFile)
+}
+
+func (d *dexpreopter) dexpreopt(ctx android.ModuleContext, libName string, dexJarFile android.WritablePath) {
global := dexpreopt.GetGlobalConfig(ctx)
// TODO(b/148690468): The check on d.installPath is to bail out in cases where
@@ -271,7 +309,7 @@
dexLocation := android.InstallPathToOnDevicePath(ctx, d.installPath)
- providesUsesLib := moduleName(ctx)
+ providesUsesLib := libName
if ulib, ok := ctx.Module().(ProvidesUsesLib); ok {
name := ulib.ProvidesUsesLib()
if name != nil {
@@ -281,11 +319,11 @@
// If it is test, make config files regardless of its dexpreopt setting.
// The config files are required for apps defined in make which depend on the lib.
- if d.isTest && d.dexpreoptDisabled(ctx) {
+ if d.isTest && d.dexpreoptDisabled(ctx, libName) {
return
}
- isSystemServerJar := global.AllSystemServerJars(ctx).ContainsJar(moduleName(ctx))
+ isSystemServerJar := global.AllSystemServerJars(ctx).ContainsJar(libName)
bootImage := defaultBootImageConfig(ctx)
// When `global.PreoptWithUpdatableBcp` is true, `bcpForDexpreopt` below includes the mainline
@@ -304,7 +342,7 @@
targets = append(targets, target)
}
}
- if isSystemServerJar && moduleName(ctx) != "com.android.location.provider" {
+ if isSystemServerJar && libName != "com.android.location.provider" {
// If the module is a system server jar, only preopt for the primary arch because the jar can
// only be loaded by system server. "com.android.location.provider" is a special case because
// it's also used by apps as a shared library.
@@ -327,6 +365,7 @@
var profileClassListing android.OptionalPath
var profileBootListing android.OptionalPath
profileIsTextListing := false
+
if d.inputProfilePathOnHost != nil {
profileClassListing = android.OptionalPathForPath(d.inputProfilePathOnHost)
} else if BoolDefault(d.dexpreoptProperties.Dex_preopt.Profile_guided, true) && !forPrebuiltApex(ctx) {
@@ -340,17 +379,21 @@
profileIsTextListing = true
} else if global.ProfileDir != "" {
profileClassListing = android.ExistentPathForSource(ctx,
- global.ProfileDir, moduleName(ctx)+".prof")
+ global.ProfileDir, libName+".prof")
}
}
d.dexpreoptProperties.Dex_preopt_result.Profile_guided = profileClassListing.Valid()
+ // A single apex can have multiple system server jars
+ // Use the dexJar to create a unique scope for each
+ dexJarStem := strings.TrimSuffix(dexJarFile.Base(), dexJarFile.Ext())
+
// Full dexpreopt config, used to create dexpreopt build rules.
dexpreoptConfig := &dexpreopt.ModuleConfig{
- Name: moduleName(ctx),
+ Name: libName,
DexLocation: dexLocation,
- BuildPath: android.PathForModuleOut(ctx, "dexpreopt", moduleName(ctx)+".jar").OutputPath,
+ BuildPath: android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, libName+".jar").OutputPath,
DexPath: dexJarFile,
ManifestPath: android.OptionalPathForPath(d.manifestFile),
UncompressedDex: d.uncompressedDex,
@@ -374,18 +417,16 @@
PreoptBootClassPathDexFiles: dexFiles.Paths(),
PreoptBootClassPathDexLocations: dexLocations,
- PreoptExtractedApk: false,
-
NoCreateAppImage: !BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, true),
ForceCreateAppImage: BoolDefault(d.dexpreoptProperties.Dex_preopt.App_image, false),
PresignedPrebuilt: d.isPresignedPrebuilt,
}
- d.configPath = android.PathForModuleOut(ctx, "dexpreopt", "dexpreopt.config")
+ d.configPath = android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, "dexpreopt.config")
dexpreopt.WriteModuleConfig(ctx, dexpreoptConfig, d.configPath)
- if d.dexpreoptDisabled(ctx) {
+ if d.dexpreoptDisabled(ctx, libName) {
return
}
@@ -396,7 +437,7 @@
// dependencies to create a per-app list, and use `rsync --checksum` to prevent the file's mtime
// from being changed if the contents don't change. This avoids unnecessary dexpreopt reruns.
productPackages := android.PathForModuleInPartitionInstall(ctx, "", "product_packages.txt")
- appProductPackages := android.PathForModuleOut(ctx, "dexpreopt", "product_packages.txt")
+ appProductPackages := android.PathForModuleOut(ctx, "dexpreopt", dexJarStem, "product_packages.txt")
appProductPackagesStaging := appProductPackages.ReplaceExtension(ctx, "txt.tmp")
clcNames, _ := dexpreopt.ComputeClassLoaderContextDependencies(dexpreoptConfig.ClassLoaderContexts)
sort.Strings(clcNames) // The order needs to be deterministic.
@@ -418,7 +459,7 @@
Text("rsync --checksum").
Input(appProductPackagesStaging).
Output(appProductPackages)
- productPackagesRule.Restat().Build("product_packages", "dexpreopt product_packages")
+ productPackagesRule.Restat().Build("product_packages."+dexJarStem, "dexpreopt product_packages")
dexpreoptRule, err := dexpreopt.GenerateDexpreoptRule(
ctx, globalSoong, global, dexpreoptConfig, appProductPackages)
@@ -427,9 +468,11 @@
return
}
- dexpreoptRule.Build("dexpreopt", "dexpreopt")
+ dexpreoptRule.Build("dexpreopt"+"."+dexJarStem, "dexpreopt")
- isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(moduleName(ctx))
+ // The current ctx might be of a deapexer module created by a prebuilt apex
+ // Use the path of the dex file to determine the library name
+ isApexSystemServerJar := global.AllApexSystemServerJars(ctx).ContainsJar(dexJarStem)
for _, install := range dexpreoptRule.Installs() {
// Remove the "/" prefix because the path should be relative to $ANDROID_PRODUCT_OUT.
@@ -454,7 +497,7 @@
// The installs will be handled by Make as sub-modules of the java library.
d.builtInstalledForApex = append(d.builtInstalledForApex, dexpreopterInstall{
name: arch + "-" + installBase,
- moduleName: moduleName(ctx),
+ moduleName: libName,
outputPathOnHost: install.From,
installDirOnDevice: installPath,
installFileOnDevice: installBase,
diff --git a/java/dexpreopt_bootjars.go b/java/dexpreopt_bootjars.go
index 003f2de..01f60d4 100644
--- a/java/dexpreopt_bootjars.go
+++ b/java/dexpreopt_bootjars.go
@@ -21,6 +21,7 @@
"android/soong/android"
"android/soong/dexpreopt"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
)
@@ -224,8 +225,9 @@
}
var (
- dexpreoptBootJarDepTag = bootclasspathDependencyTag{name: "dexpreopt-boot-jar"}
- dexBootJarsFragmentsKey = android.NewOnceKey("dexBootJarsFragments")
+ dexpreoptBootJarDepTag = bootclasspathDependencyTag{name: "dexpreopt-boot-jar"}
+ dexBootJarsFragmentsKey = android.NewOnceKey("dexBootJarsFragments")
+ apexContributionsMetadataDepTag = dependencyTag{name: "all_apex_contributions"}
)
func init() {
@@ -236,8 +238,7 @@
//
// WARNING: All fields in this struct should be initialized in the genBootImageConfigs function.
// Failure to do so can lead to data races if there is no synchronization enforced ordering between
-// the writer and the reader. Fields which break this rule are marked as deprecated and should be
-// removed and replaced with something else, e.g. providers.
+// the writer and the reader.
type bootImageConfig struct {
// If this image is an extension, the image that it extends.
extends *bootImageConfig
@@ -277,16 +278,6 @@
// File path to a zip archive with all image files (or nil, if not needed).
zip android.WritablePath
- // Rules which should be used in make to install the outputs.
- //
- // Deprecated: Not initialized correctly, see struct comment.
- profileInstalls android.RuleBuilderInstalls
-
- // Path to the license metadata file for the module that built the profile.
- //
- // Deprecated: Not initialized correctly, see struct comment.
- profileLicenseMetadataFile android.OptionalPath
-
// Target-dependent fields.
variants []*bootImageVariant
@@ -502,6 +493,11 @@
dexpreoptConfigForMake android.WritablePath
}
+func (dbj *dexpreoptBootJars) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // Create a dependency on all_apex_contributions to determine the selected mainline module
+ ctx.AddDependency(ctx.Module(), apexContributionsMetadataDepTag, "all_apex_contributions")
+}
+
func DexpreoptBootJarsMutator(ctx android.BottomUpMutatorContext) {
if _, ok := ctx.Module().(*dexpreoptBootJars); !ok {
return
@@ -520,6 +516,14 @@
}
// For accessing the boot jars.
addDependenciesOntoBootImageModules(ctx, config.modules, dexpreoptBootJarDepTag)
+ // Create a dependency on the apex selected using RELEASE_APEX_CONTRIBUTIONS_*
+ // TODO: b/308174306 - Remove the direct depedendency edge to the java_library (source/prebuilt) once all mainline modules
+ // have been flagged using RELEASE_APEX_CONTRIBUTIONS_*
+ apexes := []string{}
+ for i := 0; i < config.modules.Len(); i++ {
+ apexes = append(apexes, config.modules.Apex(i))
+ }
+ addDependenciesOntoSelectedBootImageApexes(ctx, android.FirstUniqueStrings(apexes)...)
}
if ctx.OtherModuleExists("platform-bootclasspath") {
@@ -532,6 +536,28 @@
}
}
+// Create a dependency from dex_bootjars to the specific apexes selected using all_apex_contributions
+// This dependency will be used to get the path to the deapexed dex boot jars and profile (via a provider)
+func addDependenciesOntoSelectedBootImageApexes(ctx android.BottomUpMutatorContext, apexes ...string) {
+ psi := android.PrebuiltSelectionInfoMap{}
+ ctx.VisitDirectDepsWithTag(apexContributionsMetadataDepTag, func(am android.Module) {
+ if info, exists := android.OtherModuleProvider(ctx, am, android.PrebuiltSelectionInfoProvider); exists {
+ psi = info
+ }
+ })
+ for _, apex := range apexes {
+ for _, selected := range psi.GetSelectedModulesForApiDomain(apex) {
+ // We need to add a dep on only the apex listed in `contents` of the selected apex_contributions module
+ // This is not available in a structured format in `apex_contributions`, so this hack adds a dep on all `contents`
+ // (some modules like art.module.public.api do not have an apex variation since it is a pure stub module that does not get installed)
+ apexVariationOfSelected := append(ctx.Target().Variations(), blueprint.Variation{Mutator: "apex", Variation: apex})
+ if ctx.OtherModuleDependencyVariantExists(apexVariationOfSelected, selected) {
+ ctx.AddFarVariationDependencies(apexVariationOfSelected, dexpreoptBootJarDepTag, selected)
+ }
+ }
+ }
+}
+
func gatherBootclasspathFragments(ctx android.ModuleContext) map[string]android.Module {
return ctx.Config().Once(dexBootJarsFragmentsKey, func() interface{} {
fragments := make(map[string]android.Module)
@@ -544,7 +570,7 @@
return true
}
if tag == bootclasspathFragmentDepTag {
- apexInfo := ctx.OtherModuleProvider(child, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.OtherModuleProvider(ctx, child, android.ApexInfoProvider)
for _, apex := range apexInfo.InApexVariants {
fragments[apex] = child
}
@@ -565,6 +591,7 @@
imageConfigs := genBootImageConfigs(ctx)
d.defaultBootImage = defaultBootImageConfig(ctx)
d.otherImages = make([]*bootImageConfig, 0, len(imageConfigs)-1)
+ var profileInstalls android.RuleBuilderInstalls
for _, name := range getImageNames() {
config := imageConfigs[name]
if config != d.defaultBootImage {
@@ -573,16 +600,25 @@
if !config.isEnabled(ctx) {
continue
}
- generateBootImage(ctx, config)
+ installs := generateBootImage(ctx, config)
+ profileInstalls = append(profileInstalls, installs...)
if config == d.defaultBootImage {
- bootFrameworkProfileRule(ctx, config)
+ _, installs := bootFrameworkProfileRule(ctx, config)
+ profileInstalls = append(profileInstalls, installs...)
}
}
+ if len(profileInstalls) > 0 {
+ android.SetProvider(ctx, profileInstallInfoProvider, profileInstallInfo{
+ profileInstalls: profileInstalls,
+ profileLicenseMetadataFile: android.OptionalPathForPath(ctx.LicenseMetadataFile()),
+ })
+ }
}
// GenerateSingletonBuildActions generates build rules for the dexpreopt config for Make.
func (d *dexpreoptBootJars) GenerateSingletonBuildActions(ctx android.SingletonContext) {
- d.dexpreoptConfigForMake = android.PathForOutput(ctx, getDexpreoptDirName(ctx), "dexpreopt.config")
+ d.dexpreoptConfigForMake =
+ android.PathForOutput(ctx, dexpreopt.GetDexpreoptDirName(ctx), "dexpreopt.config")
writeGlobalConfigForMake(ctx, d.dexpreoptConfigForMake)
}
@@ -598,7 +634,7 @@
return true
}
-func generateBootImage(ctx android.ModuleContext, imageConfig *bootImageConfig) {
+func generateBootImage(ctx android.ModuleContext, imageConfig *bootImageConfig) android.RuleBuilderInstalls {
apexJarModulePairs := getModulesForImage(ctx, imageConfig)
// Copy module dex jars to their predefined locations.
@@ -607,11 +643,12 @@
// Build a profile for the image config from the profile at the default path. The profile will
// then be used along with profiles imported from APEXes to build the boot image.
- profile := bootImageProfileRule(ctx, imageConfig)
+ profile, profileInstalls := bootImageProfileRule(ctx, imageConfig)
// If dexpreopt of boot image jars should be skipped, stop after generating a profile.
- if SkipDexpreoptBootJars(ctx) {
- return
+ global := dexpreopt.GetGlobalConfig(ctx)
+ if SkipDexpreoptBootJars(ctx) || (global.OnlyPreoptArtBootImage && imageConfig.name != "art") {
+ return profileInstalls
}
// Build boot image files for the android variants.
@@ -625,10 +662,12 @@
// Create a `dump-oat-<image-name>` rule that runs `oatdump` for debugging purposes.
dumpOatRules(ctx, imageConfig)
+
+ return profileInstalls
}
type apexJarModulePair struct {
- apex string
+ apex string
jarModule android.Module
}
@@ -640,7 +679,7 @@
name := android.RemoveOptionalPrebuiltPrefix(module.Name())
if name == imageConfig.modules.Jar(i) {
modules = append(modules, apexJarModulePair{
- apex: imageConfig.modules.Apex(i),
+ apex: imageConfig.modules.Apex(i),
jarModule: module,
})
found = true
@@ -661,38 +700,69 @@
// extractEncodedDexJarsFromModulesOrBootclasspathFragments gets the hidden API encoded dex jars for
// the given modules.
func extractEncodedDexJarsFromModulesOrBootclasspathFragments(ctx android.ModuleContext, apexJarModulePairs []apexJarModulePair) bootDexJarByModule {
+ apexNameToApexExportInfoMap := getApexNameToApexExportsInfoMap(ctx)
encodedDexJarsByModuleName := bootDexJarByModule{}
for _, pair := range apexJarModulePairs {
- var path android.Path
- if android.IsConfiguredJarForPlatform(pair.apex) || android.IsModulePrebuilt(pair.jarModule) {
- // This gives us the dex jar with the hidden API flags encoded from the monolithic hidden API
- // files or the dex jar extracted from a prebuilt APEX. We can't use this for a boot jar for
- // a source APEX because there is no guarantee that it is the same as the jar packed into the
- // APEX. In practice, they are the same when we are building from a full source tree, but they
- // are different when we are building from a thin manifest (e.g., master-art), where there is
- // no monolithic hidden API files at all.
- path = retrieveEncodedBootDexJarFromModule(ctx, pair.jarModule)
- } else {
- // Use exactly the same jar that is packed into the APEX.
- fragment := getBootclasspathFragmentByApex(ctx, pair.apex)
- if fragment == nil {
- ctx.ModuleErrorf("Boot jar '%[1]s' is from APEX '%[2]s', but a bootclasspath_fragment for "+
- "APEX '%[2]s' doesn't exist or is not added as a dependency of dex_bootjars",
- pair.jarModule.Name(),
- pair.apex)
- }
- bootclasspathFragmentInfo := ctx.OtherModuleProvider(fragment, BootclasspathFragmentApexContentInfoProvider).(BootclasspathFragmentApexContentInfo)
- jar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(pair.jarModule)
- if err != nil {
- ctx.ModuleErrorf("%s", err)
- }
- path = jar
- }
- encodedDexJarsByModuleName.addPath(pair.jarModule, path)
+ dexJarPath := getDexJarForApex(ctx, pair, apexNameToApexExportInfoMap)
+ encodedDexJarsByModuleName.addPath(pair.jarModule, dexJarPath)
}
return encodedDexJarsByModuleName
}
+type apexNameToApexExportsInfoMap map[string]android.ApexExportsInfo
+
+// javaLibraryPathOnHost returns the path to the java library which is exported by the apex for hiddenapi and dexpreopt and a boolean indicating whether the java library exists
+// For prebuilt apexes, this is created by deapexing the prebuilt apex
+func (m *apexNameToApexExportsInfoMap) javaLibraryDexPathOnHost(ctx android.ModuleContext, apex string, javalib string) (android.Path, bool) {
+ if info, exists := (*m)[apex]; exists {
+ if dex, exists := info.LibraryNameToDexJarPathOnHost[javalib]; exists {
+ return dex, true
+ } else {
+ ctx.ModuleErrorf("Apex %s does not provide a dex boot jar for library %s\n", apex, javalib)
+ }
+ }
+ // An apex entry could not be found. Return false.
+ // TODO: b/308174306 - When all the mainline modules have been flagged, make this a hard error
+ return nil, false
+}
+
+// Returns the java libraries exported by the apex for hiddenapi and dexpreopt
+// This information can come from two mechanisms
+// 1. New: Direct deps to _selected_ apexes. The apexes return a ApexExportsInfo
+// 2. Legacy: An edge to java_library or java_import (java_sdk_library) module. For prebuilt apexes, this serves as a hook and is populated by deapexers of prebuilt apxes
+// TODO: b/308174306 - Once all mainline modules have been flagged, drop (2)
+func getDexJarForApex(ctx android.ModuleContext, pair apexJarModulePair, apexNameToApexExportsInfoMap apexNameToApexExportsInfoMap) android.Path {
+ if dex, found := apexNameToApexExportsInfoMap.javaLibraryDexPathOnHost(ctx, pair.apex, android.RemoveOptionalPrebuiltPrefix(pair.jarModule.Name())); found {
+ return dex
+ }
+ // TODO: b/308174306 - Remove the legacy mechanism
+ if android.IsConfiguredJarForPlatform(pair.apex) || android.IsModulePrebuilt(pair.jarModule) {
+ // This gives us the dex jar with the hidden API flags encoded from the monolithic hidden API
+ // files or the dex jar extracted from a prebuilt APEX. We can't use this for a boot jar for
+ // a source APEX because there is no guarantee that it is the same as the jar packed into the
+ // APEX. In practice, they are the same when we are building from a full source tree, but they
+ // are different when we are building from a thin manifest (e.g., master-art), where there is
+ // no monolithic hidden API files at all.
+ return retrieveEncodedBootDexJarFromModule(ctx, pair.jarModule)
+ } else {
+ // Use exactly the same jar that is packed into the APEX.
+ fragment := getBootclasspathFragmentByApex(ctx, pair.apex)
+ if fragment == nil {
+ ctx.ModuleErrorf("Boot jar '%[1]s' is from APEX '%[2]s', but a bootclasspath_fragment for "+
+ "APEX '%[2]s' doesn't exist or is not added as a dependency of dex_bootjars",
+ pair.jarModule.Name(),
+ pair.apex)
+ }
+ bootclasspathFragmentInfo, _ := android.OtherModuleProvider(ctx, fragment, BootclasspathFragmentApexContentInfoProvider)
+ jar, err := bootclasspathFragmentInfo.DexBootJarPathForContentModule(pair.jarModule)
+ if err != nil {
+ ctx.ModuleErrorf("%s", err)
+ }
+ return jar
+ }
+ return nil
+}
+
// copyBootJarsToPredefinedLocations generates commands that will copy boot jars to predefined
// paths in the global config.
func copyBootJarsToPredefinedLocations(ctx android.ModuleContext, srcBootDexJarsByModule bootDexJarByModule, dstBootJarsByModule map[string]android.WritablePath) {
@@ -822,6 +892,37 @@
config *bootImageVariant
}
+// Returns the profile file for an apex
+// This information can come from two mechanisms
+// 1. New: Direct deps to _selected_ apexes. The apexes return a BootclasspathFragmentApexContentInfo
+// 2. Legacy: An edge to bootclasspath_fragment module. For prebuilt apexes, this serves as a hook and is populated by deapexers of prebuilt apxes
+// TODO: b/308174306 - Once all mainline modules have been flagged, drop (2)
+func getProfilePathForApex(ctx android.ModuleContext, apexName string, apexNameToBcpInfoMap map[string]android.ApexExportsInfo) android.Path {
+ if info, exists := apexNameToBcpInfoMap[apexName]; exists {
+ return info.ProfilePathOnHost
+ }
+ // TODO: b/308174306 - Remove the legacy mechanism
+ fragment := getBootclasspathFragmentByApex(ctx, apexName)
+ if fragment == nil {
+ ctx.ModuleErrorf("Boot image config imports profile from '%[2]s', but a "+
+ "bootclasspath_fragment for APEX '%[2]s' doesn't exist or is not added as a "+
+ "dependency of dex_bootjars",
+ apexName)
+ return nil
+ }
+ return fragment.(commonBootclasspathFragment).getProfilePath()
+}
+
+func getApexNameToApexExportsInfoMap(ctx android.ModuleContext) apexNameToApexExportsInfoMap {
+ apexNameToApexExportsInfoMap := apexNameToApexExportsInfoMap{}
+ ctx.VisitDirectDepsWithTag(dexpreoptBootJarDepTag, func(am android.Module) {
+ if info, exists := android.OtherModuleProvider(ctx, am, android.ApexExportsInfoProvider); exists {
+ apexNameToApexExportsInfoMap[info.ApexName] = info
+ }
+ })
+ return apexNameToApexExportsInfoMap
+}
+
// Generate boot image build rules for a specific target.
func buildBootImageVariant(ctx android.ModuleContext, image *bootImageVariant, profile android.Path) bootImageVariantOutputs {
@@ -864,6 +965,8 @@
invocationPath := outputPath.ReplaceExtension(ctx, "invocation")
+ apexNameToApexExportsInfoMap := getApexNameToApexExportsInfoMap(ctx)
+
cmd.Tool(globalSoong.Dex2oat).
Flag("--avoid-storing-invocation").
FlagWithOutput("--write-invocation-to=", invocationPath).ImplicitOutput(invocationPath).
@@ -876,16 +979,7 @@
}
for _, apex := range image.profileImports {
- fragment := getBootclasspathFragmentByApex(ctx, apex)
- if fragment == nil {
- ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but a "+
- "bootclasspath_fragment for APEX '%[2]s' doesn't exist or is not added as a "+
- "dependency of dex_bootjars",
- image.name,
- apex)
- return bootImageVariantOutputs{}
- }
- importedProfile := fragment.(commonBootclasspathFragment).getProfilePath()
+ importedProfile := getProfilePathForApex(ctx, apex, apexNameToApexExportsInfoMap)
if importedProfile == nil {
ctx.ModuleErrorf("Boot image config '%[1]s' imports profile from '%[2]s', but '%[2]s' "+
"doesn't provide a profile",
@@ -973,8 +1067,8 @@
cmd.FlagWithArg("--instruction-set-features=", global.InstructionSetFeatures[arch])
}
- if global.EnableUffdGc && image.target.Os == android.Android {
- cmd.Flag("--runtime-arg").Flag("-Xgc:CMC")
+ if image.target.Os == android.Android {
+ cmd.Text("$(cat").Input(globalSoong.UffdGcFlag).Text(")")
}
if global.BootFlags != "" {
@@ -1084,9 +1178,19 @@
return profile
}
-func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) android.WritablePath {
+type profileInstallInfo struct {
+ // Rules which should be used in make to install the outputs.
+ profileInstalls android.RuleBuilderInstalls
+
+ // Path to the license metadata file for the module that built the profile.
+ profileLicenseMetadataFile android.OptionalPath
+}
+
+var profileInstallInfoProvider = blueprint.NewProvider[profileInstallInfo]()
+
+func bootImageProfileRule(ctx android.ModuleContext, image *bootImageConfig) (android.WritablePath, android.RuleBuilderInstalls) {
if !image.isProfileGuided() {
- return nil
+ return nil, nil
}
profile := bootImageProfileRuleCommon(ctx, image.name, image.dexPathsDeps.Paths(), image.getAnyAndroidVariant().dexLocationsDeps)
@@ -1094,21 +1198,19 @@
if image == defaultBootImageConfig(ctx) {
rule := android.NewRuleBuilder(pctx, ctx)
rule.Install(profile, "/system/etc/boot-image.prof")
- image.profileInstalls = append(image.profileInstalls, rule.Installs()...)
- image.profileLicenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile())
+ return profile, rule.Installs()
}
-
- return profile
+ return profile, nil
}
// bootFrameworkProfileRule generates the rule to create the boot framework profile and
// returns a path to the generated file.
-func bootFrameworkProfileRule(ctx android.ModuleContext, image *bootImageConfig) android.WritablePath {
+func bootFrameworkProfileRule(ctx android.ModuleContext, image *bootImageConfig) (android.WritablePath, android.RuleBuilderInstalls) {
globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
global := dexpreopt.GetGlobalConfig(ctx)
if global.DisableGenerateProfile || ctx.Config().UnbundledBuild() {
- return nil
+ return nil, nil
}
defaultProfile := "frameworks/base/config/boot-profile.txt"
@@ -1128,16 +1230,13 @@
rule.Install(profile, "/system/etc/boot-image.bprof")
rule.Build("bootFrameworkProfile", "profile boot framework jars")
- image.profileInstalls = append(image.profileInstalls, rule.Installs()...)
- image.profileLicenseMetadataFile = android.OptionalPathForPath(ctx.LicenseMetadataFile())
-
- return profile
+ return profile, rule.Installs()
}
func dumpOatRules(ctx android.ModuleContext, image *bootImageConfig) {
var allPhonies android.Paths
name := image.name
- global := dexpreopt.GetGlobalConfig(ctx)
+ globalSoong := dexpreopt.GetGlobalSoongConfig(ctx)
for _, image := range image.variants {
arch := image.target.Arch.ArchType
suffix := arch.String()
@@ -1149,6 +1248,7 @@
output := android.PathForOutput(ctx, name+"."+suffix+".oatdump.txt")
rule := android.NewRuleBuilder(pctx, ctx)
imageLocationsOnHost, _ := image.imageLocations()
+
cmd := rule.Command().
BuiltTool("oatdump").
FlagWithInputList("--runtime-arg -Xbootclasspath:", image.dexPathsDeps.Paths(), ":").
@@ -1156,8 +1256,8 @@
FlagWithArg("--image=", strings.Join(imageLocationsOnHost, ":")).Implicits(image.imagesDeps.Paths()).
FlagWithOutput("--output=", output).
FlagWithArg("--instruction-set=", arch.String())
- if global.EnableUffdGc && image.target.Os == android.Android {
- cmd.Flag("--runtime-arg").Flag("-Xgc:CMC")
+ if image.target.Os == android.Android {
+ cmd.Text("$(cat").Input(globalSoong.UffdGcFlag).Text(")")
}
rule.Build("dump-oat-"+name+"-"+suffix, "dump oat "+name+" "+arch.String())
@@ -1178,7 +1278,7 @@
Rule: android.Phony,
Output: phony,
Inputs: allPhonies,
- Description: "dump-oat-"+name,
+ Description: "dump-oat-" + name,
})
}
@@ -1199,9 +1299,11 @@
image := d.defaultBootImage
if image != nil {
- ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", image.profileInstalls.String())
- if image.profileLicenseMetadataFile.Valid() {
- ctx.Strict("DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA", image.profileLicenseMetadataFile.String())
+ if profileInstallInfo, ok := android.SingletonModuleProvider(ctx, d, profileInstallInfoProvider); ok {
+ ctx.Strict("DEXPREOPT_IMAGE_PROFILE_BUILT_INSTALLED", profileInstallInfo.profileInstalls.String())
+ if profileInstallInfo.profileLicenseMetadataFile.Valid() {
+ ctx.Strict("DEXPREOPT_IMAGE_PROFILE_LICENSE_METADATA", profileInstallInfo.profileLicenseMetadataFile.String())
+ }
}
if SkipDexpreoptBootJars(ctx) {
diff --git a/java/dexpreopt_check.go b/java/dexpreopt_check.go
index 7499481..33be603 100644
--- a/java/dexpreopt_check.go
+++ b/java/dexpreopt_check.go
@@ -68,7 +68,7 @@
// The check should be skipped on unbundled builds because system server jars are not preopted on
// unbundled builds since the artifacts are installed into the system image, not the APEXes.
- if global.DisablePreopt || len(targets) == 0 || ctx.Config().UnbundledBuild() {
+ if global.DisablePreopt || global.OnlyPreoptArtBootImage || len(targets) == 0 || ctx.Config().UnbundledBuild() {
return
}
diff --git a/java/dexpreopt_config.go b/java/dexpreopt_config.go
index 0f4bd9b..dc0973c 100644
--- a/java/dexpreopt_config.go
+++ b/java/dexpreopt_config.go
@@ -45,7 +45,7 @@
frameworkBootImageName = "boot"
mainlineBootImageName = "mainline"
bootImageStem = "boot"
- profileInstallPathInApex = "etc/boot-image.prof"
+ ProfileInstallPathInApex = "etc/boot-image.prof"
)
// getImageNames returns an ordered list of image names. The order doesn't matter but needs to be
@@ -115,7 +115,7 @@
func genBootImageConfigs(ctx android.PathContext) map[string]*bootImageConfig {
return ctx.Config().Once(bootImageConfigKey, func() interface{} {
targets := dexpreoptTargets(ctx)
- deviceDir := android.PathForOutput(ctx, getDexpreoptDirName(ctx))
+ deviceDir := android.PathForOutput(ctx, dexpreopt.GetDexpreoptDirName(ctx))
configs := genBootImageConfigRaw(ctx)
@@ -210,57 +210,18 @@
return false
}
-// Apex boot config allows to access build/install paths of apex boot jars without going
-// through the usual trouble of registering dependencies on those modules and extracting build paths
-// from those dependencies.
-type apexBootConfig struct {
- // A list of apex boot jars.
- modules android.ConfiguredJarList
-
- // A list of predefined build paths to apex boot jars. They are configured very early,
- // before the modules for these jars are processed and the actual paths are generated, and
- // later on a singleton adds commands to copy actual jars to the predefined paths.
- dexPaths android.WritablePaths
-
- // Map from module name (without prebuilt_ prefix) to the predefined build path.
- dexPathsByModule map[string]android.WritablePath
-
- // A list of dex locations (a.k.a. on-device paths) to the boot jars.
- dexLocations []string
-}
-
-var updatableBootConfigKey = android.NewOnceKey("apexBootConfig")
-
-// Returns apex boot config.
-func GetApexBootConfig(ctx android.PathContext) apexBootConfig {
- return ctx.Config().Once(updatableBootConfigKey, func() interface{} {
- apexBootJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars
- dir := android.PathForOutput(ctx, getDexpreoptDirName(ctx), "apex_bootjars")
- dexPaths := apexBootJars.BuildPaths(ctx, dir)
- dexPathsByModuleName := apexBootJars.BuildPathsByModule(ctx, dir)
-
- dexLocations := apexBootJars.DevicePaths(ctx.Config(), android.Android)
-
- return apexBootConfig{apexBootJars, dexPaths, dexPathsByModuleName, dexLocations}
- }).(apexBootConfig)
-}
-
// Returns a list of paths and a list of locations for the boot jars used in dexpreopt (to be
// passed in -Xbootclasspath and -Xbootclasspath-locations arguments for dex2oat).
func bcpForDexpreopt(ctx android.PathContext, withUpdatable bool) (android.WritablePaths, []string) {
- // Non-updatable boot jars (they are used both in the boot image and in dexpreopt).
bootImage := defaultBootImageConfig(ctx)
+ if withUpdatable {
+ bootImage = mainlineBootImageConfig(ctx)
+ }
+
dexPaths := bootImage.dexPathsDeps
// The dex locations for all Android variants are identical.
dexLocations := bootImage.getAnyAndroidVariant().dexLocationsDeps
- if withUpdatable {
- // Apex boot jars (they are used only in dexpreopt, but not in the boot image).
- apexBootConfig := GetApexBootConfig(ctx)
- dexPaths = append(dexPaths, apexBootConfig.dexPaths...)
- dexLocations = append(dexLocations, apexBootConfig.dexLocations...)
- }
-
return dexPaths, dexLocations
}
@@ -273,12 +234,3 @@
func dexpreoptConfigMakevars(ctx android.MakeVarsContext) {
ctx.Strict("DEXPREOPT_BOOT_JARS_MODULES", strings.Join(defaultBootImageConfig(ctx).modules.CopyOfApexJarPairs(), ":"))
}
-
-func getDexpreoptDirName(ctx android.PathContext) string {
- prefix := "dexpreopt_"
- targets := ctx.Config().Targets[android.Android]
- if len(targets) > 0 {
- return prefix+targets[0].Arch.ArchType.String()
- }
- return prefix+"unknown_target"
-}
diff --git a/java/dexpreopt_config_testing.go b/java/dexpreopt_config_testing.go
index 176c251..104829f 100644
--- a/java/dexpreopt_config_testing.go
+++ b/java/dexpreopt_config_testing.go
@@ -77,7 +77,7 @@
func PrepareApexBootJarModule(apexName string, moduleName string) android.FixturePreparer {
moduleSourceDir := fmt.Sprintf("packages/modules/%s", apexName)
- fragmentName := apexName+"-bootclasspath-fragment"
+ fragmentName := apexName + "-bootclasspath-fragment"
imageNameProp := ""
if apexName == "com.android.art" {
fragmentName = "art-bootclasspath-fragment"
@@ -523,7 +523,7 @@
},
}
- checkBootImageConfig(t, imageConfig, mutated, expected)
+ checkBootImageConfig(t, result, imageConfig, mutated, expected)
}
// getFrameworkImageConfig gets the framework bootImageConfig that was created during the test.
@@ -904,7 +904,7 @@
profileLicenseMetadataFile: expectedLicenseMetadataFile,
}
- checkBootImageConfig(t, imageConfig, mutated, expected)
+ checkBootImageConfig(t, result, imageConfig, mutated, expected)
}
// getMainlineImageConfig gets the framework bootImageConfig that was created during the test.
@@ -1183,7 +1183,7 @@
profileLicenseMetadataFile: expectedLicenseMetadataFile,
}
- checkBootImageConfig(t, imageConfig, false, expected)
+ checkBootImageConfig(t, result, imageConfig, false, expected)
}
// clearMutatedFields clears fields in the expectedConfig that correspond to fields in the
@@ -1211,19 +1211,19 @@
// zero value so that they will match the unmodified values in the boot image.
//
// It runs the checks in an image specific subtest of the current test.
-func checkBootImageConfig(t *testing.T, imageConfig *bootImageConfig, mutated bool, expected *expectedConfig) {
+func checkBootImageConfig(t *testing.T, result *android.TestResult, imageConfig *bootImageConfig, mutated bool, expected *expectedConfig) {
if !mutated {
clearMutatedFields(expected)
}
t.Run(imageConfig.name, func(t *testing.T) {
- nestedCheckBootImageConfig(t, imageConfig, expected)
+ nestedCheckBootImageConfig(t, result, imageConfig, mutated, expected)
})
}
// nestedCheckBootImageConfig does the work of comparing the image against the expected values and
// is run in an image specific subtest.
-func nestedCheckBootImageConfig(t *testing.T, imageConfig *bootImageConfig, expected *expectedConfig) {
+func nestedCheckBootImageConfig(t *testing.T, result *android.TestResult, imageConfig *bootImageConfig, mutated bool, expected *expectedConfig) {
android.AssertStringEquals(t, "name", expected.name, imageConfig.name)
android.AssertStringEquals(t, "stem", expected.stem, imageConfig.stem)
android.AssertPathRelativeToTopEquals(t, "dir", expected.dir, imageConfig.dir)
@@ -1234,8 +1234,13 @@
android.AssertPathsRelativeToTopEquals(t, "dexPathsDeps", expected.dexPathsDeps, imageConfig.dexPathsDeps.Paths())
// dexPathsByModule is just a different representation of the other information in the config.
android.AssertPathRelativeToTopEquals(t, "zip", expected.zip, imageConfig.zip)
- assertInstallsEqual(t, "profileInstalls", expected.profileInstalls, imageConfig.profileInstalls)
- android.AssertStringEquals(t, "profileLicenseMetadataFile", expected.profileLicenseMetadataFile, imageConfig.profileLicenseMetadataFile.RelativeToTop().String())
+
+ if !mutated {
+ dexBootJarModule := result.ModuleForTests("dex_bootjars", "android_common")
+ profileInstallInfo, _ := android.SingletonModuleProvider(result, dexBootJarModule.Module(), profileInstallInfoProvider)
+ assertInstallsEqual(t, "profileInstalls", expected.profileInstalls, profileInstallInfo.profileInstalls)
+ android.AssertStringEquals(t, "profileLicenseMetadataFile", expected.profileLicenseMetadataFile, profileInstallInfo.profileLicenseMetadataFile.RelativeToTop().String())
+ }
android.AssertIntEquals(t, "variant count", 4, len(imageConfig.variants))
for i, variant := range imageConfig.variants {
diff --git a/java/dexpreopt_test.go b/java/dexpreopt_test.go
index fedd564..73e33f4 100644
--- a/java/dexpreopt_test.go
+++ b/java/dexpreopt_test.go
@@ -410,7 +410,7 @@
verifyEntries(t,
"entriesList[0]",
"service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
- "/dexpreopt/oat/arm64/javalib.odex",
+ "/dexpreopt/service-foo/oat/arm64/javalib.odex",
"/system/framework/oat/arm64",
"apex@com.android.apex1@javalib@service-foo.jar@classes.odex",
entriesList[0])
@@ -418,7 +418,7 @@
verifyEntries(t,
"entriesList[1]",
"service-foo-dexpreopt-arm64-apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
- "/dexpreopt/oat/arm64/javalib.vdex",
+ "/dexpreopt/service-foo/oat/arm64/javalib.vdex",
"/system/framework/oat/arm64",
"apex@com.android.apex1@javalib@service-foo.jar@classes.vdex",
entriesList[1])
@@ -459,7 +459,7 @@
ctx := result.TestContext
dexpreopt := ctx.ModuleForTests("foo", "android_common").MaybeRule("dexpreopt")
- expected := []string{"out/soong/.intermediates/foo/android_common/dexpreopt/profile.prof"}
+ expected := []string{"out/soong/.intermediates/foo/android_common/dexpreopt/foo/profile.prof"}
android.AssertArrayString(t, "outputs", expected, dexpreopt.AllOutputs())
}
diff --git a/java/droiddoc.go b/java/droiddoc.go
index 3ba3065..cfbf2b4 100644
--- a/java/droiddoc.go
+++ b/java/droiddoc.go
@@ -135,6 +135,9 @@
// At some point, this might be improved to show more warnings.
Todo_file *string `android:"path"`
+ // A file containing a baseline for allowed lint errors.
+ Lint_baseline *string `android:"path"`
+
// directory under current module source that provide additional resources (images).
Resourcesdir *string
@@ -179,6 +182,17 @@
func apiCheckEnabled(ctx android.ModuleContext, apiToCheck ApiToCheck, apiVersionTag string) bool {
if ctx.Config().IsEnvTrue("WITHOUT_CHECK_API") {
+ if ctx.Config().BuildFromTextStub() {
+ ctx.ModuleErrorf("Generating stubs from api signature files is not available " +
+ "with WITHOUT_CHECK_API=true, as sync between the source Java files and the " +
+ "api signature files is not guaranteed.\n" +
+ "In order to utilize WITHOUT_CHECK_API, generate stubs from the source Java " +
+ "files with BUILD_FROM_SOURCE_STUB=true.\n" +
+ "However, the usage of WITHOUT_CHECK_API is not preferred as the incremental " +
+ "build is slower when generating stubs from the source Java files.\n" +
+ "Consider updating the api signature files and generating the stubs from " +
+ "them instead.")
+ }
return false
} else if String(apiToCheck.Api_file) != "" && String(apiToCheck.Removed_api_file) != "" {
return true
@@ -205,6 +219,8 @@
docZip android.WritablePath
stubsSrcJar android.WritablePath
+
+ exportableStubsSrcJar android.WritablePath
}
func (j *Javadoc) OutputFiles(tag string) (android.Paths, error) {
@@ -299,7 +315,7 @@
}
flags = append(flags, android.JoinWithPrefix(aidlIncludes.Strings(), "-I"))
- flags = append(flags, "-I"+android.PathForModuleSrc(ctx).String())
+ flags = append(flags, "-I"+ctx.ModuleDir())
if src := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "src"); src.Valid() {
flags = append(flags, "-I"+src.String())
}
@@ -360,8 +376,7 @@
switch tag {
case bootClasspathTag:
- if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
deps.bootClasspath = append(deps.bootClasspath, dep.ImplementationJars...)
} else if sm, ok := module.(SystemModulesProvider); ok {
// A system modules dependency has been added to the bootclasspath
@@ -373,8 +388,7 @@
case libTag, sdkLibTag:
if dep, ok := module.(SdkLibraryDependency); ok {
deps.classpath = append(deps.classpath, dep.SdkHeaderJars(ctx, j.SdkVersion(ctx))...)
- } else if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ } else if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
deps.classpath = append(deps.classpath, dep.HeaderJars...)
deps.aidlIncludeDirs = append(deps.aidlIncludeDirs, dep.AidlIncludeDirs...)
} else if dep, ok := module.(android.SourceFileProducer); ok {
@@ -384,8 +398,7 @@
ctx.ModuleErrorf("depends on non-java module %q", otherName)
}
case java9LibTag:
- if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
deps.java9Classpath = append(deps.java9Classpath, dep.HeaderJars...)
} else {
ctx.ModuleErrorf("depends on non-java module %q", otherName)
@@ -397,6 +410,15 @@
sm := module.(SystemModulesProvider)
outputDir, outputDeps := sm.OutputDirAndDeps()
deps.systemModules = &systemModules{outputDir, outputDeps}
+ case aconfigDeclarationTag:
+ if dep, ok := android.OtherModuleProvider(ctx, module, android.AconfigDeclarationsProviderKey); ok {
+ deps.aconfigProtoFiles = append(deps.aconfigProtoFiles, dep.IntermediateCacheOutputPath)
+ } else {
+ ctx.ModuleErrorf("Only aconfig_declarations module type is allowed for "+
+ "flags_packages property, but %s is not aconfig_declarations module type",
+ module.Name(),
+ )
+ }
}
})
// do not pass exclude_srcs directly when expanding srcFiles since exclude_srcs
@@ -664,6 +686,10 @@
ImplicitOutput(android.PathForModuleOut(ctx, String(d.properties.Todo_file)))
}
+ if String(d.properties.Lint_baseline) != "" {
+ cmd.FlagWithInput("-lintbaseline ", android.PathForModuleSrc(ctx, String(d.properties.Lint_baseline)))
+ }
+
if String(d.properties.Resourcesdir) != "" {
// TODO: should we add files under resourcesDir to the implicits? It seems that
// resourcesDir is one sub dir of htmlDir
diff --git a/java/droidstubs.go b/java/droidstubs.go
index f05ef1f..4267545 100644
--- a/java/droidstubs.go
+++ b/java/droidstubs.go
@@ -18,13 +18,11 @@
"fmt"
"path/filepath"
"regexp"
- "sort"
"strings"
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel"
"android/soong/java/config"
"android/soong/remoteexec"
)
@@ -32,6 +30,28 @@
// The values allowed for Droidstubs' Api_levels_sdk_type
var allowedApiLevelSdkTypes = []string{"public", "system", "module-lib", "system-server"}
+type StubsType int
+
+const (
+ Everything StubsType = iota
+ Runtime
+ Exportable
+ Unavailable
+)
+
+func (s StubsType) String() string {
+ switch s {
+ case Everything:
+ return "everything"
+ case Runtime:
+ return "runtime"
+ case Exportable:
+ return "exportable"
+ default:
+ return ""
+ }
+}
+
func init() {
RegisterStubsBuildComponents(android.InitRegistrationContext)
}
@@ -45,14 +65,22 @@
ctx.RegisterModuleType("prebuilt_stubs_sources", PrebuiltStubsSourcesFactory)
}
+type stubsArtifacts struct {
+ nullabilityWarningsFile android.WritablePath
+ annotationsZip android.WritablePath
+ apiVersionsXml android.WritablePath
+ metadataZip android.WritablePath
+ metadataDir android.WritablePath
+}
+
// Droidstubs
type Droidstubs struct {
Javadoc
+ embeddableInModuleAndImport
- properties DroidstubsProperties
- apiFile android.Path
- removedApiFile android.Path
- nullabilityWarningsFile android.WritablePath
+ properties DroidstubsProperties
+ apiFile android.Path
+ removedApiFile android.Path
checkCurrentApiTimestamp android.WritablePath
updateCurrentApiTimestamp android.WritablePath
@@ -62,11 +90,14 @@
checkNullabilityWarningsTimestamp android.WritablePath
- annotationsZip android.WritablePath
- apiVersionsXml android.WritablePath
+ everythingArtifacts stubsArtifacts
+ exportableArtifacts stubsArtifacts
- metadataZip android.WritablePath
- metadataDir android.WritablePath
+ // Single aconfig "cache file" merged from this module and all dependencies.
+ mergedAconfigFiles map[string]android.Paths
+
+ exportableApiFile android.WritablePath
+ exportableRemovedApiFile android.WritablePath
}
type DroidstubsProperties struct {
@@ -123,7 +154,7 @@
Generate_stubs *bool
// if set to true, provides a hint to the build system that this rule uses a lot of memory,
- // whicih can be used for scheduling purposes
+ // which can be used for scheduling purposes
High_mem *bool
// if set to true, Metalava will allow framework SDK to contain API levels annotations.
@@ -152,26 +183,64 @@
// API surface of this module. If set, the module contributes to an API surface.
// For the full list of available API surfaces, refer to soong/android/sdk_version.go
Api_surface *string
+
+ // a list of aconfig_declarations module names that the stubs generated in this module
+ // depend on.
+ Aconfig_declarations []string
}
// Used by xsd_config
type ApiFilePath interface {
- ApiFilePath() android.Path
+ ApiFilePath(StubsType) (android.Path, error)
}
type ApiStubsSrcProvider interface {
- StubsSrcJar() android.Path
+ StubsSrcJar(StubsType) (android.Path, error)
}
// Provider of information about API stubs, used by java_sdk_library.
type ApiStubsProvider interface {
- AnnotationsZip() android.Path
+ AnnotationsZip(StubsType) (android.Path, error)
ApiFilePath
- RemovedApiFilePath() android.Path
+ RemovedApiFilePath(StubsType) (android.Path, error)
ApiStubsSrcProvider
}
+type currentApiTimestampProvider interface {
+ CurrentApiTimestamp() android.Path
+}
+
+type annotationFlagsParams struct {
+ migratingNullability bool
+ validatingNullability bool
+ nullabilityWarningsFile android.WritablePath
+ annotationsZip android.WritablePath
+}
+type stubsCommandParams struct {
+ srcJarDir android.ModuleOutPath
+ stubsDir android.OptionalPath
+ stubsSrcJar android.WritablePath
+ metadataZip android.WritablePath
+ metadataDir android.WritablePath
+ apiVersionsXml android.WritablePath
+ nullabilityWarningsFile android.WritablePath
+ annotationsZip android.WritablePath
+ stubConfig stubsCommandConfigParams
+}
+type stubsCommandConfigParams struct {
+ stubsType StubsType
+ javaVersion javaVersion
+ deps deps
+ checkApi bool
+ generateStubs bool
+ doApiLint bool
+ doCheckReleased bool
+ writeSdkValues bool
+ migratingNullability bool
+ validatingNullability bool
+}
+
// droidstubs passes sources files through Metalava to generate stub .java files that only contain the API to be
// documented, filtering out hidden classes and methods. The resulting .java files are intended to be passed to
// a droiddoc module to generate documentation.
@@ -180,6 +249,7 @@
module.AddProperties(&module.properties,
&module.Javadoc.properties)
+ module.initModuleAndImport(module)
InitDroiddocModule(module, android.HostAndDeviceSupported)
@@ -203,46 +273,160 @@
return module
}
+func getStubsTypeAndTag(tag string) (StubsType, string, error) {
+ if len(tag) == 0 {
+ return Everything, "", nil
+ }
+ if tag[0] != '.' {
+ return Unavailable, "", fmt.Errorf("tag must begin with \".\"")
+ }
+
+ stubsType := Everything
+ // Check if the tag has a stubs type prefix (e.g. ".exportable")
+ for st := Everything; st <= Exportable; st++ {
+ if strings.HasPrefix(tag, "."+st.String()) {
+ stubsType = st
+ }
+ }
+
+ return stubsType, strings.TrimPrefix(tag, "."+stubsType.String()), nil
+}
+
+// Droidstubs' tag supports specifying with the stubs type.
+// While supporting the pre-existing tags, it also supports tags with
+// the stubs type prefix. Some examples are shown below:
+// {.annotations.zip} - pre-existing behavior. Returns the path to the
+// annotation zip.
+// {.exportable} - Returns the path to the exportable stubs src jar.
+// {.exportable.annotations.zip} - Returns the path to the exportable
+// annotations zip file.
+// {.runtime.api_versions.xml} - Runtime stubs does not generate api versions
+// xml file. For unsupported combinations, the default everything output file
+// is returned.
func (d *Droidstubs) OutputFiles(tag string) (android.Paths, error) {
- switch tag {
+ stubsType, prefixRemovedTag, err := getStubsTypeAndTag(tag)
+ if err != nil {
+ return nil, err
+ }
+ switch prefixRemovedTag {
case "":
- return android.Paths{d.stubsSrcJar}, nil
+ stubsSrcJar, err := d.StubsSrcJar(stubsType)
+ return android.Paths{stubsSrcJar}, err
case ".docs.zip":
- return android.Paths{d.docZip}, nil
+ docZip, err := d.DocZip(stubsType)
+ return android.Paths{docZip}, err
case ".api.txt", android.DefaultDistTag:
// This is the default dist path for dist properties that have no tag property.
- return android.Paths{d.apiFile}, nil
+ apiFilePath, err := d.ApiFilePath(stubsType)
+ return android.Paths{apiFilePath}, err
case ".removed-api.txt":
- return android.Paths{d.removedApiFile}, nil
+ removedApiFilePath, err := d.RemovedApiFilePath(stubsType)
+ return android.Paths{removedApiFilePath}, err
case ".annotations.zip":
- return android.Paths{d.annotationsZip}, nil
+ annotationsZip, err := d.AnnotationsZip(stubsType)
+ return android.Paths{annotationsZip}, err
case ".api_versions.xml":
- return android.Paths{d.apiVersionsXml}, nil
+ apiVersionsXmlFilePath, err := d.ApiVersionsXmlFilePath(stubsType)
+ return android.Paths{apiVersionsXmlFilePath}, err
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
}
-func (d *Droidstubs) AnnotationsZip() android.Path {
- return d.annotationsZip
+func (d *Droidstubs) AnnotationsZip(stubsType StubsType) (ret android.Path, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = d.everythingArtifacts.annotationsZip, nil
+ case Exportable:
+ ret, err = d.exportableArtifacts.annotationsZip, nil
+ default:
+ ret, err = nil, fmt.Errorf("annotations zip not supported for the stub type %s", stubsType.String())
+ }
+ return ret, err
}
-func (d *Droidstubs) ApiFilePath() android.Path {
- return d.apiFile
+func (d *Droidstubs) ApiFilePath(stubsType StubsType) (ret android.Path, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = d.apiFile, nil
+ case Exportable:
+ ret, err = d.exportableApiFile, nil
+ default:
+ ret, err = nil, fmt.Errorf("api file path not supported for the stub type %s", stubsType.String())
+ }
+ if ret == nil && err == nil {
+ err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
}
-func (d *Droidstubs) RemovedApiFilePath() android.Path {
- return d.removedApiFile
+func (d *Droidstubs) ApiVersionsXmlFilePath(stubsType StubsType) (ret android.Path, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = d.everythingArtifacts.apiVersionsXml, nil
+ case Exportable:
+ ret, err = d.exportableArtifacts.apiVersionsXml, nil
+ default:
+ ret, err = nil, fmt.Errorf("api versions xml file path not supported for the stub type %s", stubsType.String())
+ }
+ if ret == nil && err == nil {
+ err = fmt.Errorf("api versions xml file is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
}
-func (d *Droidstubs) StubsSrcJar() android.Path {
- return d.stubsSrcJar
+func (d *Droidstubs) DocZip(stubsType StubsType) (ret android.Path, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = d.docZip, nil
+ default:
+ ret, err = nil, fmt.Errorf("docs zip not supported for the stub type %s", stubsType.String())
+ }
+ if ret == nil && err == nil {
+ err = fmt.Errorf("docs zip is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
+}
+
+func (d *Droidstubs) RemovedApiFilePath(stubsType StubsType) (ret android.Path, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = d.removedApiFile, nil
+ case Exportable:
+ ret, err = d.exportableRemovedApiFile, nil
+ default:
+ ret, err = nil, fmt.Errorf("removed api file path not supported for the stub type %s", stubsType.String())
+ }
+ if ret == nil && err == nil {
+ err = fmt.Errorf("removed api file is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
+}
+
+func (d *Droidstubs) StubsSrcJar(stubsType StubsType) (ret android.Path, err error) {
+ switch stubsType {
+ case Everything:
+ ret, err = d.stubsSrcJar, nil
+ case Exportable:
+ ret, err = d.exportableStubsSrcJar, nil
+ default:
+ ret, err = nil, fmt.Errorf("stubs srcjar not supported for the stub type %s", stubsType.String())
+ }
+ if ret == nil && err == nil {
+ err = fmt.Errorf("stubs srcjar is null for the stub type %s", stubsType.String())
+ }
+ return ret, err
+}
+
+func (d *Droidstubs) CurrentApiTimestamp() android.Path {
+ return d.checkCurrentApiTimestamp
}
var metalavaMergeAnnotationsDirTag = dependencyTag{name: "metalava-merge-annotations-dir"}
var metalavaMergeInclusionAnnotationsDirTag = dependencyTag{name: "metalava-merge-inclusion-annotations-dir"}
var metalavaAPILevelsAnnotationsDirTag = dependencyTag{name: "metalava-api-levels-annotations-dir"}
var metalavaAPILevelsModuleTag = dependencyTag{name: "metalava-api-levels-module-tag"}
+var metalavaCurrentApiTimestampTag = dependencyTag{name: "metalava-current-api-timestamp-tag"}
func (d *Droidstubs) DepsMutator(ctx android.BottomUpMutatorContext) {
d.Javadoc.addDeps(ctx)
@@ -265,41 +449,52 @@
}
}
+ if len(d.properties.Aconfig_declarations) != 0 {
+ for _, aconfigDeclarationModuleName := range d.properties.Aconfig_declarations {
+ ctx.AddDependency(ctx.Module(), aconfigDeclarationTag, aconfigDeclarationModuleName)
+ }
+ }
+
if d.properties.Api_levels_module != nil {
ctx.AddDependency(ctx.Module(), metalavaAPILevelsModuleTag, proptools.String(d.properties.Api_levels_module))
}
}
-func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath) {
- if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
- apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") ||
- String(d.properties.Api_filename) != "" {
+func (d *Droidstubs) sdkValuesFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, metadataDir android.WritablePath) {
+ cmd.FlagWithArg("--sdk-values ", metadataDir.String())
+}
+
+func (d *Droidstubs) stubsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsDir android.OptionalPath, stubsType StubsType, checkApi bool) {
+ if checkApi || String(d.properties.Api_filename) != "" {
filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
- uncheckedApiFile := android.PathForModuleOut(ctx, "metalava", filename)
+ uncheckedApiFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
cmd.FlagWithOutput("--api ", uncheckedApiFile)
- d.apiFile = uncheckedApiFile
+
+ if stubsType == Everything {
+ d.apiFile = uncheckedApiFile
+ } else if stubsType == Exportable {
+ d.exportableApiFile = uncheckedApiFile
+ }
} else if sourceApiFile := proptools.String(d.properties.Check_api.Current.Api_file); sourceApiFile != "" {
// If check api is disabled then make the source file available for export.
d.apiFile = android.PathForModuleSrc(ctx, sourceApiFile)
}
- if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
- apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") ||
- String(d.properties.Removed_api_filename) != "" {
+ if checkApi || String(d.properties.Removed_api_filename) != "" {
filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_removed.txt")
- uncheckedRemovedFile := android.PathForModuleOut(ctx, "metalava", filename)
+ uncheckedRemovedFile := android.PathForModuleOut(ctx, stubsType.String(), filename)
cmd.FlagWithOutput("--removed-api ", uncheckedRemovedFile)
- d.removedApiFile = uncheckedRemovedFile
+
+ if stubsType == Everything {
+ d.removedApiFile = uncheckedRemovedFile
+ } else if stubsType == Exportable {
+ d.exportableRemovedApiFile = uncheckedRemovedFile
+ }
} else if sourceRemovedApiFile := proptools.String(d.properties.Check_api.Current.Removed_api_file); sourceRemovedApiFile != "" {
// If check api is disabled then make the source removed api file available for export.
d.removedApiFile = android.PathForModuleSrc(ctx, sourceRemovedApiFile)
}
- if Bool(d.properties.Write_sdk_values) {
- d.metadataDir = android.PathForModuleOut(ctx, "metalava", "metadata")
- cmd.FlagWithArg("--sdk-values ", d.metadataDir.String())
- }
-
if stubsDir.Valid() {
if Bool(d.properties.Create_doc_stubs) {
cmd.FlagWithArg("--doc-stubs ", stubsDir.String())
@@ -312,18 +507,11 @@
}
}
-func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
+func (d *Droidstubs) annotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, params annotationFlagsParams) {
if Bool(d.properties.Annotations_enabled) {
- cmd.Flag("--include-annotations")
+ cmd.Flag(config.MetalavaAnnotationsFlags)
- cmd.FlagWithArg("--exclude-annotation ", "androidx.annotation.RequiresApi")
-
- validatingNullability :=
- strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
- String(d.properties.Validate_nullability_from_list) != ""
-
- migratingNullability := String(d.properties.Previous_api) != ""
- if migratingNullability {
+ if params.migratingNullability {
previousApi := android.PathForModuleSrc(ctx, String(d.properties.Previous_api))
cmd.FlagWithInput("--migrate-nullness ", previousApi)
}
@@ -332,26 +520,17 @@
cmd.FlagWithInput("--validate-nullability-from-list ", android.PathForModuleSrc(ctx, s))
}
- if validatingNullability {
- d.nullabilityWarningsFile = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"_nullability_warnings.txt")
- cmd.FlagWithOutput("--nullability-warnings-txt ", d.nullabilityWarningsFile)
+ if params.validatingNullability {
+ cmd.FlagWithOutput("--nullability-warnings-txt ", params.nullabilityWarningsFile)
}
- d.annotationsZip = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"_annotations.zip")
- cmd.FlagWithOutput("--extract-annotations ", d.annotationsZip)
+ cmd.FlagWithOutput("--extract-annotations ", params.annotationsZip)
if len(d.properties.Merge_annotations_dirs) != 0 {
d.mergeAnnoDirFlags(ctx, cmd)
}
- // TODO(tnorbye): find owners to fix these warnings when annotation was enabled.
- cmd.FlagWithArg("--hide ", "HiddenTypedefConstant").
- FlagWithArg("--hide ", "SuperfluousPrefix").
- FlagWithArg("--hide ", "AnnotationExtraction").
- // b/222738070
- FlagWithArg("--hide ", "BannedThrow").
- // b/223382732
- FlagWithArg("--hide ", "ChangedDefault")
+ cmd.Flag(config.MetalavaAnnotationsWarningsFlags)
}
}
@@ -377,15 +556,21 @@
})
}
-func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
+func (d *Droidstubs) apiLevelsAnnotationsFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
var apiVersions android.Path
if proptools.Bool(d.properties.Api_levels_annotations_enabled) {
- d.apiLevelsGenerationFlags(ctx, cmd)
- apiVersions = d.apiVersionsXml
+ d.apiLevelsGenerationFlags(ctx, cmd, stubsType, apiVersionsXml)
+ apiVersions = apiVersionsXml
} else {
ctx.VisitDirectDepsWithTag(metalavaAPILevelsModuleTag, func(m android.Module) {
if s, ok := m.(*Droidstubs); ok {
- apiVersions = s.apiVersionsXml
+ if stubsType == Everything {
+ apiVersions = s.everythingArtifacts.apiVersionsXml
+ } else if stubsType == Exportable {
+ apiVersions = s.exportableArtifacts.apiVersionsXml
+ } else {
+ ctx.ModuleErrorf("%s stubs type does not generate api-versions.xml file", stubsType.String())
+ }
} else {
ctx.PropertyErrorf("api_levels_module",
"module %q is not a droidstubs module", ctx.OtherModuleName(m))
@@ -399,14 +584,13 @@
}
}
-func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand) {
+func (d *Droidstubs) apiLevelsGenerationFlags(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, apiVersionsXml android.WritablePath) {
if len(d.properties.Api_levels_annotations_dirs) == 0 {
ctx.PropertyErrorf("api_levels_annotations_dirs",
"has to be non-empty if api levels annotations was enabled!")
}
- d.apiVersionsXml = android.PathForModuleOut(ctx, "metalava", "api-versions.xml")
- cmd.FlagWithOutput("--generate-api-levels ", d.apiVersionsXml)
+ cmd.FlagWithOutput("--generate-api-levels ", apiVersionsXml)
filename := proptools.StringDefault(d.properties.Api_levels_jar_filename, "android.jar")
@@ -498,20 +682,26 @@
if metalavaUseRbe(ctx) {
rule.Remoteable(android.RemoteRuleSupports{RBE: true})
execStrategy := ctx.Config().GetenvWithDefault("RBE_METALAVA_EXEC_STRATEGY", remoteexec.LocalExecStrategy)
+ compare := ctx.Config().IsEnvTrue("RBE_METALAVA_COMPARE")
+ remoteUpdateCache := !ctx.Config().IsEnvFalse("RBE_METALAVA_REMOTE_UPDATE_CACHE")
labels := map[string]string{"type": "tool", "name": "metalava"}
// TODO: metalava pool rejects these jobs
pool := ctx.Config().GetenvWithDefault("RBE_METALAVA_POOL", "java16")
rule.Rewrapper(&remoteexec.REParams{
- Labels: labels,
- ExecStrategy: execStrategy,
- ToolchainInputs: []string{config.JavaCmd(ctx).String()},
- Platform: map[string]string{remoteexec.PoolKey: pool},
+ Labels: labels,
+ ExecStrategy: execStrategy,
+ ToolchainInputs: []string{config.JavaCmd(ctx).String()},
+ Platform: map[string]string{remoteexec.PoolKey: pool},
+ Compare: compare,
+ NumLocalRuns: 1,
+ NumRemoteRuns: 1,
+ NoRemoteUpdateCache: !remoteUpdateCache,
})
}
cmd.BuiltTool("metalava").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "metalava.jar")).
Flag(config.JavacVmFlags).
- Flag("-J--add-opens=java.base/java.util=ALL-UNNAMED").
+ Flag(config.MetalavaAddOpens).
FlagWithArg("--java-source ", javaVersion.String()).
FlagWithRspFileInputList("@", android.PathForModuleOut(ctx, "metalava.rsp"), srcs).
FlagWithInput("@", srcJarList)
@@ -524,67 +714,96 @@
cmd.FlagWithInputList("--classpath ", combinedPaths, ":")
}
- cmd.Flag("--color").
- Flag("--quiet").
- Flag("--format=v2").
- FlagWithArg("--repeat-errors-max ", "10").
- FlagWithArg("--hide ", "UnresolvedImport").
- FlagWithArg("--hide ", "InvalidNullabilityOverride").
- // b/223382732
- FlagWithArg("--hide ", "ChangedDefault")
-
- // Force metalava to ignore classes on the classpath when an API file contains missing classes.
- // See b/285140653 for more information.
- cmd.FlagWithArg("--api-class-resolution ", "api")
-
- // Force metalava to sort overloaded methods by their order in the source code.
- // See b/285312164 for more information.
- cmd.FlagWithArg("--api-overloaded-method-order ", "source")
+ cmd.Flag(config.MetalavaFlags)
return cmd
}
-func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- deps := d.Javadoc.collectDeps(ctx)
+// Pass flagged apis related flags to metalava. When aconfig_declarations property is not
+// defined for a module, simply revert all flagged apis annotations. If aconfig_declarations
+// property is defined, apply transformations and only revert the flagged apis that are not
+// enabled via release configurations and are not specified in aconfig_declarations
+func (d *Droidstubs) generateRevertAnnotationArgs(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, stubsType StubsType, aconfigFlagsPaths android.Paths) {
- javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
+ if len(aconfigFlagsPaths) == 0 {
+ cmd.Flag("--revert-annotation android.annotation.FlaggedApi")
+ return
+ }
- // Create rule for metalava
+ releasedFlaggedApisFile := android.PathForModuleOut(ctx, fmt.Sprintf("released-flagged-apis-%s.txt", stubsType.String()))
+ revertAnnotationsFile := android.PathForModuleOut(ctx, fmt.Sprintf("revert-annotations-%s.txt", stubsType.String()))
- srcJarDir := android.PathForModuleOut(ctx, "metalava", "srcjars")
+ var filterArgs string
+ switch stubsType {
+ // No flagged apis specific flags need to be passed to metalava when generating
+ // everything stubs
+ case Everything:
+ return
- rule := android.NewRuleBuilder(pctx, ctx)
+ case Runtime:
+ filterArgs = "--filter='state:ENABLED+permission:READ_ONLY' --filter='permission:READ_WRITE'"
- rule.Sbox(android.PathForModuleOut(ctx, "metalava"),
- android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
- SandboxInputs()
+ case Exportable:
+ filterArgs = "--filter='state:ENABLED+permission:READ_ONLY'"
+ }
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: gatherReleasedFlaggedApisRule,
+ Inputs: aconfigFlagsPaths,
+ Output: releasedFlaggedApisFile,
+ Description: fmt.Sprintf("%s gather aconfig flags", stubsType),
+ Args: map[string]string{
+ "flags_path": android.JoinPathsWithPrefix(aconfigFlagsPaths, "--cache "),
+ "filter_args": filterArgs,
+ },
+ })
+
+ ctx.Build(pctx, android.BuildParams{
+ Rule: generateMetalavaRevertAnnotationsRule,
+ Input: releasedFlaggedApisFile,
+ Output: revertAnnotationsFile,
+ Description: fmt.Sprintf("%s revert annotations", stubsType),
+ })
+
+ cmd.FlagWithInput("@", revertAnnotationsFile)
+}
+
+func (d *Droidstubs) commonMetalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
+ params stubsCommandParams) *android.RuleBuilderCommand {
if BoolDefault(d.properties.High_mem, false) {
// This metalava run uses lots of memory, restrict the number of metalava jobs that can run in parallel.
rule.HighMem()
}
- generateStubs := BoolDefault(d.properties.Generate_stubs, true)
- var stubsDir android.OptionalPath
- if generateStubs {
- d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
- stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, "metalava", "stubsDir"))
- rule.Command().Text("rm -rf").Text(stubsDir.String())
- rule.Command().Text("mkdir -p").Text(stubsDir.String())
+ if params.stubConfig.generateStubs {
+ rule.Command().Text("rm -rf").Text(params.stubsDir.String())
+ rule.Command().Text("mkdir -p").Text(params.stubsDir.String())
}
- srcJarList := zipSyncCmd(ctx, rule, srcJarDir, d.Javadoc.srcJars)
+ srcJarList := zipSyncCmd(ctx, rule, params.srcJarDir, d.Javadoc.srcJars)
- homeDir := android.PathForModuleOut(ctx, "metalava", "home")
- cmd := metalavaCmd(ctx, rule, javaVersion, d.Javadoc.srcFiles, srcJarList,
- deps.bootClasspath, deps.classpath, homeDir)
+ homeDir := android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "home")
+ cmd := metalavaCmd(ctx, rule, params.stubConfig.javaVersion, d.Javadoc.srcFiles, srcJarList,
+ params.stubConfig.deps.bootClasspath, params.stubConfig.deps.classpath, homeDir)
cmd.Implicits(d.Javadoc.implicits)
- d.stubsFlags(ctx, cmd, stubsDir)
+ d.stubsFlags(ctx, cmd, params.stubsDir, params.stubConfig.stubsType, params.stubConfig.checkApi)
- d.annotationsFlags(ctx, cmd)
+ if params.stubConfig.writeSdkValues {
+ d.sdkValuesFlags(ctx, cmd, params.metadataDir)
+ }
+
+ annotationParams := annotationFlagsParams{
+ migratingNullability: params.stubConfig.migratingNullability,
+ validatingNullability: params.stubConfig.validatingNullability,
+ nullabilityWarningsFile: params.nullabilityWarningsFile,
+ annotationsZip: params.annotationsZip,
+ }
+
+ d.annotationsFlags(ctx, cmd, annotationParams)
d.inclusionAnnotationsFlags(ctx, cmd)
- d.apiLevelsAnnotationsFlags(ctx, cmd)
+ d.apiLevelsAnnotationsFlags(ctx, cmd, params.stubConfig.stubsType, params.apiVersionsXml)
d.expandArgs(ctx, cmd)
@@ -592,24 +811,105 @@
cmd.ImplicitOutput(android.PathForModuleGen(ctx, o))
}
- // Add options for the other optional tasks: API-lint and check-released.
- // We generate separate timestamp files for them.
+ return cmd
+}
- doApiLint := false
- doCheckReleased := false
+// Sandbox rule for generating the everything stubs and other artifacts
+func (d *Droidstubs) everythingStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
+ srcJarDir := android.PathForModuleOut(ctx, Everything.String(), "srcjars")
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Sbox(android.PathForModuleOut(ctx, Everything.String()),
+ android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
+ SandboxInputs()
+
+ var stubsDir android.OptionalPath
+ if params.generateStubs {
+ stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, Everything.String(), "stubsDir"))
+ d.Javadoc.stubsSrcJar = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
+ }
+
+ if params.writeSdkValues {
+ d.everythingArtifacts.metadataDir = android.PathForModuleOut(ctx, Everything.String(), "metadata")
+ d.everythingArtifacts.metadataZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"-metadata.zip")
+ }
+
+ if Bool(d.properties.Annotations_enabled) {
+ if params.validatingNullability {
+ d.everythingArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_nullability_warnings.txt")
+ }
+ d.everythingArtifacts.annotationsZip = android.PathForModuleOut(ctx, Everything.String(), ctx.ModuleName()+"_annotations.zip")
+ }
+ if Bool(d.properties.Api_levels_annotations_enabled) {
+ d.everythingArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, Everything.String(), "api-versions.xml")
+ }
+
+ commonCmdParams := stubsCommandParams{
+ srcJarDir: srcJarDir,
+ stubsDir: stubsDir,
+ stubsSrcJar: d.Javadoc.stubsSrcJar,
+ metadataDir: d.everythingArtifacts.metadataDir,
+ apiVersionsXml: d.everythingArtifacts.apiVersionsXml,
+ nullabilityWarningsFile: d.everythingArtifacts.nullabilityWarningsFile,
+ annotationsZip: d.everythingArtifacts.annotationsZip,
+ stubConfig: params,
+ }
+
+ cmd := d.commonMetalavaStubCmd(ctx, rule, commonCmdParams)
+
+ d.everythingOptionalCmd(ctx, cmd, params.doApiLint, params.doCheckReleased)
+
+ if params.generateStubs {
+ rule.Command().
+ BuiltTool("soong_zip").
+ Flag("-write_if_changed").
+ Flag("-jar").
+ FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
+ FlagWithArg("-C ", stubsDir.String()).
+ FlagWithArg("-D ", stubsDir.String())
+ }
+
+ if params.writeSdkValues {
+ rule.Command().
+ BuiltTool("soong_zip").
+ Flag("-write_if_changed").
+ Flag("-d").
+ FlagWithOutput("-o ", d.everythingArtifacts.metadataZip).
+ FlagWithArg("-C ", d.everythingArtifacts.metadataDir.String()).
+ FlagWithArg("-D ", d.everythingArtifacts.metadataDir.String())
+ }
+
+ // TODO: We don't really need two separate API files, but this is a reminiscence of how
+ // we used to run metalava separately for API lint and the "last_released" check. Unify them.
+ if params.doApiLint {
+ rule.Command().Text("touch").Output(d.apiLintTimestamp)
+ }
+ if params.doCheckReleased {
+ rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
+ }
+
+ // TODO(b/183630617): rewrapper doesn't support restat rules
+ if !metalavaUseRbe(ctx) {
+ rule.Restat()
+ }
+
+ zipSyncCleanupCmd(rule, srcJarDir)
+
+ rule.Build("metalava", "metalava merged")
+}
+
+// Sandbox rule for generating the everything artifacts that are not run by
+// default but only run based on the module configurations
+func (d *Droidstubs) everythingOptionalCmd(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, doApiLint bool, doCheckReleased bool) {
// Add API lint options.
-
- if BoolDefault(d.properties.Check_api.Api_lint.Enabled, false) {
- doApiLint = true
-
+ if doApiLint {
newSince := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.New_since)
if newSince.Valid() {
cmd.FlagWithInput("--api-lint ", newSince.Path())
} else {
cmd.Flag("--api-lint")
}
- d.apiLintReport = android.PathForModuleOut(ctx, "metalava", "api_lint_report.txt")
+ d.apiLintReport = android.PathForModuleOut(ctx, Everything.String(), "api_lint_report.txt")
cmd.FlagWithOutput("--report-even-if-suppressed ", d.apiLintReport) // TODO: Change to ":api-lint"
// TODO(b/154317059): Clean up this allowlist by baselining and/or checking in last-released.
@@ -620,8 +920,8 @@
}
baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
- updatedBaselineOutput := android.PathForModuleOut(ctx, "metalava", "api_lint_baseline.txt")
- d.apiLintTimestamp = android.PathForModuleOut(ctx, "metalava", "api_lint.timestamp")
+ updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "api_lint_baseline.txt")
+ d.apiLintTimestamp = android.PathForModuleOut(ctx, Everything.String(), "api_lint.timestamp")
// Note this string includes a special shell quote $' ... ', which decodes the "\n"s.
//
@@ -662,10 +962,7 @@
}
// Add "check released" options. (Detect incompatible API changes from the last public release)
-
- if apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released") {
- doCheckReleased = true
-
+ if doCheckReleased {
if len(d.Javadoc.properties.Out) > 0 {
ctx.PropertyErrorf("out", "out property may not be combined with check_api")
}
@@ -673,9 +970,9 @@
apiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Api_file))
removedApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Last_released.Removed_api_file))
baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Last_released.Baseline_file)
- updatedBaselineOutput := android.PathForModuleOut(ctx, "metalava", "last_released_baseline.txt")
+ updatedBaselineOutput := android.PathForModuleOut(ctx, Everything.String(), "last_released_baseline.txt")
- d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, "metalava", "check_last_released_api.timestamp")
+ d.checkLastReleasedApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_last_released_api.timestamp")
cmd.FlagWithInput("--check-compatibility:api:released ", apiFile)
cmd.FlagWithInput("--check-compatibility:removed:released ", removedApiFile)
@@ -700,35 +997,96 @@
currentApiFile := android.PathForModuleSrc(ctx, String(d.properties.Check_api.Current.Api_file))
cmd.FlagWithInput("--use-same-format-as ", currentApiFile)
}
+}
- if generateStubs {
+// Sandbox rule for generating exportable stubs and other artifacts
+func (d *Droidstubs) exportableStubCmd(ctx android.ModuleContext, params stubsCommandConfigParams) {
+ optionalCmdParams := stubsCommandParams{
+ stubConfig: params,
+ }
+
+ if params.generateStubs {
+ d.Javadoc.exportableStubsSrcJar = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-"+"stubs.srcjar")
+ optionalCmdParams.stubsSrcJar = d.Javadoc.exportableStubsSrcJar
+ }
+
+ if params.writeSdkValues {
+ d.exportableArtifacts.metadataZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"-metadata.zip")
+ d.exportableArtifacts.metadataDir = android.PathForModuleOut(ctx, params.stubsType.String(), "metadata")
+ optionalCmdParams.metadataZip = d.exportableArtifacts.metadataZip
+ optionalCmdParams.metadataDir = d.exportableArtifacts.metadataDir
+ }
+
+ if Bool(d.properties.Annotations_enabled) {
+ if params.validatingNullability {
+ d.exportableArtifacts.nullabilityWarningsFile = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_nullability_warnings.txt")
+ optionalCmdParams.nullabilityWarningsFile = d.exportableArtifacts.nullabilityWarningsFile
+ }
+ d.exportableArtifacts.annotationsZip = android.PathForModuleOut(ctx, params.stubsType.String(), ctx.ModuleName()+"_annotations.zip")
+ optionalCmdParams.annotationsZip = d.exportableArtifacts.annotationsZip
+ }
+ if Bool(d.properties.Api_levels_annotations_enabled) {
+ d.exportableArtifacts.apiVersionsXml = android.PathForModuleOut(ctx, params.stubsType.String(), "api-versions.xml")
+ optionalCmdParams.apiVersionsXml = d.exportableArtifacts.apiVersionsXml
+ }
+
+ if params.checkApi || String(d.properties.Api_filename) != "" {
+ filename := proptools.StringDefault(d.properties.Api_filename, ctx.ModuleName()+"_api.txt")
+ d.exportableApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
+ }
+
+ if params.checkApi || String(d.properties.Removed_api_filename) != "" {
+ filename := proptools.StringDefault(d.properties.Removed_api_filename, ctx.ModuleName()+"_api.txt")
+ d.exportableRemovedApiFile = android.PathForModuleOut(ctx, params.stubsType.String(), filename)
+ }
+
+ d.optionalStubCmd(ctx, optionalCmdParams)
+}
+
+func (d *Droidstubs) optionalStubCmd(ctx android.ModuleContext, params stubsCommandParams) {
+
+ params.srcJarDir = android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "srcjars")
+ rule := android.NewRuleBuilder(pctx, ctx)
+ rule.Sbox(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String()),
+ android.PathForModuleOut(ctx, fmt.Sprintf("metalava_%s.sbox.textproto", params.stubConfig.stubsType.String()))).
+ SandboxInputs()
+
+ if params.stubConfig.generateStubs {
+ params.stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, params.stubConfig.stubsType.String(), "stubsDir"))
+ }
+
+ cmd := d.commonMetalavaStubCmd(ctx, rule, params)
+
+ d.generateRevertAnnotationArgs(ctx, cmd, params.stubConfig.stubsType, params.stubConfig.deps.aconfigProtoFiles)
+
+ if params.stubConfig.doApiLint {
+ // Pass the lint baseline file as an input to resolve the lint errors.
+ // The exportable stubs generation does not update the lint baseline file.
+ // Lint baseline file update is handled by the everything stubs
+ baselineFile := android.OptionalPathForModuleSrc(ctx, d.properties.Check_api.Api_lint.Baseline_file)
+ if baselineFile.Valid() {
+ cmd.FlagWithInput("--baseline:api-lint ", baselineFile.Path())
+ }
+ }
+
+ if params.stubConfig.generateStubs {
rule.Command().
BuiltTool("soong_zip").
Flag("-write_if_changed").
Flag("-jar").
- FlagWithOutput("-o ", d.Javadoc.stubsSrcJar).
- FlagWithArg("-C ", stubsDir.String()).
- FlagWithArg("-D ", stubsDir.String())
+ FlagWithOutput("-o ", params.stubsSrcJar).
+ FlagWithArg("-C ", params.stubsDir.String()).
+ FlagWithArg("-D ", params.stubsDir.String())
}
- if Bool(d.properties.Write_sdk_values) {
- d.metadataZip = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-metadata.zip")
+ if params.stubConfig.writeSdkValues {
rule.Command().
BuiltTool("soong_zip").
Flag("-write_if_changed").
Flag("-d").
- FlagWithOutput("-o ", d.metadataZip).
- FlagWithArg("-C ", d.metadataDir.String()).
- FlagWithArg("-D ", d.metadataDir.String())
- }
-
- // TODO: We don't really need two separate API files, but this is a reminiscence of how
- // we used to run metalava separately for API lint and the "last_released" check. Unify them.
- if doApiLint {
- rule.Command().Text("touch").Output(d.apiLintTimestamp)
- }
- if doCheckReleased {
- rule.Command().Text("touch").Output(d.checkLastReleasedApiTimestamp)
+ FlagWithOutput("-o ", params.metadataZip).
+ FlagWithArg("-C ", params.metadataDir.String()).
+ FlagWithArg("-D ", params.metadataDir.String())
}
// TODO(b/183630617): rewrapper doesn't support restat rules
@@ -736,9 +1094,53 @@
rule.Restat()
}
- zipSyncCleanupCmd(rule, srcJarDir)
+ zipSyncCleanupCmd(rule, params.srcJarDir)
- rule.Build("metalava", "metalava merged")
+ rule.Build(fmt.Sprintf("metalava_%s", params.stubConfig.stubsType.String()), "metalava merged")
+}
+
+func (d *Droidstubs) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ deps := d.Javadoc.collectDeps(ctx)
+
+ javaVersion := getJavaVersion(ctx, String(d.Javadoc.properties.Java_version), android.SdkContext(d))
+ generateStubs := BoolDefault(d.properties.Generate_stubs, true)
+
+ // Add options for the other optional tasks: API-lint and check-released.
+ // We generate separate timestamp files for them.
+ doApiLint := BoolDefault(d.properties.Check_api.Api_lint.Enabled, false)
+ doCheckReleased := apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
+
+ writeSdkValues := Bool(d.properties.Write_sdk_values)
+
+ annotationsEnabled := Bool(d.properties.Annotations_enabled)
+
+ migratingNullability := annotationsEnabled && String(d.properties.Previous_api) != ""
+ validatingNullability := annotationsEnabled && (strings.Contains(String(d.Javadoc.properties.Args), "--validate-nullability-from-merged-stubs") ||
+ String(d.properties.Validate_nullability_from_list) != "")
+
+ checkApi := apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") ||
+ apiCheckEnabled(ctx, d.properties.Check_api.Last_released, "last_released")
+
+ stubCmdParams := stubsCommandConfigParams{
+ javaVersion: javaVersion,
+ deps: deps,
+ checkApi: checkApi,
+ generateStubs: generateStubs,
+ doApiLint: doApiLint,
+ doCheckReleased: doCheckReleased,
+ writeSdkValues: writeSdkValues,
+ migratingNullability: migratingNullability,
+ validatingNullability: validatingNullability,
+ }
+ stubCmdParams.stubsType = Everything
+ // Create default (i.e. "everything" stubs) rule for metalava
+ d.everythingStubCmd(ctx, stubCmdParams)
+
+ // The module generates "exportable" (and "runtime" eventually) stubs regardless of whether
+ // aconfig_declarations property is defined or not. If the property is not defined, the module simply
+ // strips all flagged apis to generate the "exportable" stubs
+ stubCmdParams.stubsType = Exportable
+ d.exportableStubCmd(ctx, stubCmdParams)
if apiCheckEnabled(ctx, d.properties.Check_api.Current, "current") {
@@ -754,7 +1156,7 @@
ctx.PropertyErrorf("baseline_file", "current API check can't have a baseline file. (module %s)", ctx.ModuleName())
}
- d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, "metalava", "check_current_api.timestamp")
+ d.checkCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_current_api.timestamp")
rule := android.NewRuleBuilder(pctx, ctx)
@@ -781,6 +1183,12 @@
` m %s-update-current-api\n\n`+
` To submit the revised current.txt to the main Android repository,\n`+
` you will need approval.\n`+
+ `If your build failed due to stub validation, you can resolve the errors with\n`+
+ `either of the two choices above and try re-building the target.\n`+
+ `If the mismatch between the stubs and the current.txt is intended,\n`+
+ `you can try re-building the target by executing the following command:\n`+
+ `m DISABLE_STUB_VALIDATION=true <your build target>.\n`+
+ `Note that DISABLE_STUB_VALIDATION=true does not bypass checkapi.\n`+
`******************************\n`, ctx.ModuleName())
rule.Command().
@@ -792,7 +1200,7 @@
rule.Build("metalavaCurrentApiCheck", "check current API")
- d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, "metalava", "update_current_api.timestamp")
+ d.updateCurrentApiTimestamp = android.PathForModuleOut(ctx, Everything.String(), "update_current_api.timestamp")
// update API rule
rule = android.NewRuleBuilder(pctx, ctx)
@@ -820,14 +1228,14 @@
}
if String(d.properties.Check_nullability_warnings) != "" {
- if d.nullabilityWarningsFile == nil {
+ if d.everythingArtifacts.nullabilityWarningsFile == nil {
ctx.PropertyErrorf("check_nullability_warnings",
"Cannot specify check_nullability_warnings unless validating nullability")
}
checkNullabilityWarnings := android.PathForModuleSrc(ctx, String(d.properties.Check_nullability_warnings))
- d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, "metalava", "check_nullability_warnings.timestamp")
+ d.checkNullabilityWarningsTimestamp = android.PathForModuleOut(ctx, Everything.String(), "check_nullability_warnings.timestamp")
msg := fmt.Sprintf(`\n******************************\n`+
`The warnings encountered during nullability annotation validation did\n`+
@@ -837,13 +1245,13 @@
` 2. Update the file of expected warnings by running:\n`+
` cp %s %s\n`+
` and submitting the updated file as part of your change.`,
- d.nullabilityWarningsFile, checkNullabilityWarnings)
+ d.everythingArtifacts.nullabilityWarningsFile, checkNullabilityWarnings)
rule := android.NewRuleBuilder(pctx, ctx)
rule.Command().
Text("(").
- Text("diff").Input(checkNullabilityWarnings).Input(d.nullabilityWarningsFile).
+ Text("diff").Input(checkNullabilityWarnings).Input(d.everythingArtifacts.nullabilityWarningsFile).
Text("&&").
Text("touch").Output(d.checkNullabilityWarningsTimestamp).
Text(") || (").
@@ -853,34 +1261,7 @@
rule.Build("nullabilityWarningsCheck", "nullability warnings check")
}
-}
-
-var _ android.ApiProvider = (*Droidstubs)(nil)
-
-type bazelJavaApiContributionAttributes struct {
- Api bazel.LabelAttribute
- Api_surface *string
-}
-
-func (d *Droidstubs) ConvertWithApiBp2build(ctx android.TopDownMutatorContext) {
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "java_api_contribution",
- Bzl_load_location: "//build/bazel/rules/apis:java_api_contribution.bzl",
- }
- apiFile := d.properties.Check_api.Current.Api_file
- // Do not generate a target if check_api is not set
- if apiFile == nil {
- return
- }
- attrs := &bazelJavaApiContributionAttributes{
- Api: *bazel.MakeLabelAttribute(
- android.BazelLabelForModuleSrcSingle(ctx, proptools.String(apiFile)).Label,
- ),
- Api_surface: proptools.StringPtr(bazelApiSurfaceName(d.Name())),
- }
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: android.ApiContributionTargetName(ctx.ModuleName()),
- }, attrs)
+ android.CollectDependencyAconfigFiles(ctx, &d.mergedAconfigFiles)
}
func (d *Droidstubs) createApiContribution(ctx android.DefaultableHookContext) {
@@ -922,28 +1303,6 @@
}
)
-// A helper function that returns the api surface of the corresponding java_api_contribution Bazel target
-// The api_surface is populated using the naming convention of the droidstubs module.
-func bazelApiSurfaceName(name string) string {
- // Sort the keys so that longer strings appear first
- // Otherwise substrings like system will match both system and system_server
- sortedKeys := make([]string, 0)
- for key := range droidstubsModuleNamingToSdkKind {
- sortedKeys = append(sortedKeys, key)
- }
- sort.Slice(sortedKeys, func(i, j int) bool {
- return len(sortedKeys[i]) > len(sortedKeys[j])
- })
- for _, sortedKey := range sortedKeys {
- if strings.Contains(name, sortedKey) {
- sdkKind := droidstubsModuleNamingToSdkKind[sortedKey]
- return sdkKind.String() + "api"
- }
- }
- // Default is publicapi
- return android.SdkPublic.String() + "api"
-}
-
func StubsDefaultsFactory() android.Module {
module := &DocDefaults{}
@@ -966,6 +1325,8 @@
type PrebuiltStubsSources struct {
android.ModuleBase
android.DefaultableModuleBase
+ embeddableInModuleAndImport
+
prebuilt android.Prebuilt
properties PrebuiltStubsSourcesProperties
@@ -975,15 +1336,17 @@
func (p *PrebuiltStubsSources) OutputFiles(tag string) (android.Paths, error) {
switch tag {
- case "":
+ // prebuilt droidstubs does not output "exportable" stubs.
+ // Output the "everything" stubs srcjar file if the tag is ".exportable".
+ case "", ".exportable":
return android.Paths{p.stubsSrcJar}, nil
default:
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
}
}
-func (d *PrebuiltStubsSources) StubsSrcJar() android.Path {
- return d.stubsSrcJar
+func (d *PrebuiltStubsSources) StubsSrcJar(_ StubsType) (android.Path, error) {
+ return d.stubsSrcJar, nil
}
func (p *PrebuiltStubsSources) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1044,6 +1407,7 @@
module := &PrebuiltStubsSources{}
module.AddProperties(&module.properties)
+ module.initModuleAndImport(module)
android.InitPrebuiltModule(module, &module.properties.Srcs)
InitDroiddocModule(module, android.HostAndDeviceSupported)
diff --git a/java/droidstubs_test.go b/java/droidstubs_test.go
index 7a04d73..52cd1c5 100644
--- a/java/droidstubs_test.go
+++ b/java/droidstubs_test.go
@@ -82,7 +82,7 @@
for _, c := range testcases {
m := ctx.ModuleForTests(c.moduleName, "android_common")
manifest := m.Output("metalava.sbox.textproto")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, manifest)
cmdline := String(sboxProto.Commands[0].Command)
android.AssertStringContainsEquals(t, "api-versions generation flag", cmdline, "--generate-api-levels", c.generate_xml)
if c.expectedJarFilename != "" {
@@ -131,7 +131,7 @@
m := ctx.ModuleForTests("foo-stubs", "android_common")
manifest := m.Output("metalava.sbox.textproto")
- cmd := String(android.RuleBuilderSboxProtoForTests(t, manifest).Commands[0].Command)
+ cmd := String(android.RuleBuilderSboxProtoForTests(t, ctx, manifest).Commands[0].Command)
r := regexp.MustCompile(`--android-jar-pattern [^ ]+/android.jar`)
return r.FindAllString(cmd, -1)
}
@@ -210,8 +210,8 @@
t.Errorf("Expected inputs %q, got %q", w, g)
}
- manifest := android.RuleBuilderSboxProtoForTests(t, m.Output("metalava.sbox.textproto"))
- if g, w := manifest.Commands[0].GetCommand(), "reference __SBOX_SANDBOX_DIR__/out/.intermediates/foo/gen/foo.txt"; !strings.Contains(g, w) {
+ manifest := android.RuleBuilderSboxProtoForTests(t, ctx, m.Output("metalava.sbox.textproto"))
+ if g, w := manifest.Commands[0].GetCommand(), "reference __SBOX_SANDBOX_DIR__/out/soong/.intermediates/foo/gen/foo.txt"; !strings.Contains(g, w) {
t.Errorf("Expected command to contain %q, got %q", w, g)
}
}
@@ -300,53 +300,11 @@
})
m := ctx.ModuleForTests("baz-stubs", "android_common")
manifest := m.Output("metalava.sbox.textproto")
- cmdline := String(android.RuleBuilderSboxProtoForTests(t, manifest).Commands[0].Command)
+ cmdline := String(android.RuleBuilderSboxProtoForTests(t, ctx, manifest).Commands[0].Command)
android.AssertStringDoesContain(t, "sdk-extensions-root present", cmdline, "--sdk-extensions-root sdk/extensions")
android.AssertStringDoesContain(t, "sdk-extensions-info present", cmdline, "--sdk-extensions-info sdk/extensions/info.txt")
}
-func TestApiSurfaceFromDroidStubsName(t *testing.T) {
- testCases := []struct {
- desc string
- name string
- expectedApiSurface string
- }{
- {
- desc: "Default is publicapi",
- name: "mydroidstubs",
- expectedApiSurface: "publicapi",
- },
- {
- desc: "name contains system substring",
- name: "mydroidstubs.system.suffix",
- expectedApiSurface: "systemapi",
- },
- {
- desc: "name contains system_server substring",
- name: "mydroidstubs.system_server.suffix",
- expectedApiSurface: "system-serverapi",
- },
- {
- desc: "name contains module_lib substring",
- name: "mydroidstubs.module_lib.suffix",
- expectedApiSurface: "module-libapi",
- },
- {
- desc: "name contains test substring",
- name: "mydroidstubs.test.suffix",
- expectedApiSurface: "testapi",
- },
- {
- desc: "name contains intra.core substring",
- name: "mydroidstubs.intra.core.suffix",
- expectedApiSurface: "intracoreapi",
- },
- }
- for _, tc := range testCases {
- android.AssertStringEquals(t, tc.desc, tc.expectedApiSurface, bazelApiSurfaceName(tc.name))
- }
-}
-
func TestDroidStubsApiContributionGeneration(t *testing.T) {
ctx, _ := testJavaWithFS(t, `
droidstubs {
@@ -390,7 +348,7 @@
removed_api_file: "A/removed.txt",
}
},
- visibility: ["//a"],
+ visibility: ["//a", "//b"],
}
`,
map[string][]byte{
@@ -403,3 +361,54 @@
ctx.ModuleForTests("bar", "android_common")
}
+
+func TestAconfigDeclarations(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ }),
+ android.FixtureMergeMockFs(map[string][]byte{
+ "a/A.java": nil,
+ "a/current.txt": nil,
+ "a/removed.txt": nil,
+ }),
+ ).RunTestWithBp(t, `
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ droidstubs {
+ name: "foo",
+ srcs: ["a/A.java"],
+ api_surface: "public",
+ check_api: {
+ current: {
+ api_file: "a/current.txt",
+ removed_api_file: "a/removed.txt",
+ }
+ },
+ aconfig_declarations: [
+ "bar",
+ ],
+ }
+ `)
+
+ // Check that droidstubs depend on aconfig_declarations
+ android.AssertBoolEquals(t, "foo expected to depend on bar",
+ CheckModuleHasDependency(t, result.TestContext, "foo", "android_common", "bar"), true)
+
+ m := result.ModuleForTests("foo", "android_common")
+ android.AssertStringDoesContain(t, "foo generates revert annotations file",
+ strings.Join(m.AllOutputs(), ""), "revert-annotations-exportable.txt")
+
+ // revert-annotations.txt passed to exportable stubs generation metalava command
+ manifest := m.Output("metalava_exportable.sbox.textproto")
+ cmdline := String(android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest).Commands[0].Command)
+ android.AssertStringDoesContain(t, "flagged api hide command not included", cmdline, "revert-annotations-exportable.txt")
+
+ android.AssertStringDoesContain(t, "foo generates exportable stubs jar",
+ strings.Join(m.AllOutputs(), ""), "exportable/foo-stubs.srcjar")
+}
diff --git a/java/fuzz.go b/java/fuzz.go
index b3c2fd4..dc4c6be 100644
--- a/java/fuzz.go
+++ b/java/fuzz.go
@@ -121,7 +121,7 @@
_, sharedDeps := cc.CollectAllSharedDependencies(ctx)
for _, dep := range sharedDeps {
- sharedLibInfo := ctx.OtherModuleProvider(dep, cc.SharedLibraryInfoProvider).(cc.SharedLibraryInfo)
+ sharedLibInfo, _ := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider)
if sharedLibInfo.SharedLibrary != nil {
arch := "lib"
if sharedLibInfo.Target.Arch.ArchType.Multilib == "lib64" {
diff --git a/java/gen.go b/java/gen.go
index 638da25..68a9b53 100644
--- a/java/gen.go
+++ b/java/gen.go
@@ -129,19 +129,7 @@
baseDir = filepath.Clean(baseDir)
baseDirSeen := android.InList(baseDir, baseDirs) || android.InList(baseDir, excludeDirsStrings)
- // For go/bp2build mixed builds, a file may be listed under a
- // directory in the Bazel output tree that is symlinked to a
- // directory under the android source tree. We should only
- // include one copy of this directory so that the AIDL tool
- // doesn't find multiple definitions of the same AIDL class.
- // This code comes into effect when filegroups are used in mixed builds.
- bazelPathPrefix := android.PathForBazelOut(ctx, "").String()
- bazelBaseDir, err := filepath.Rel(bazelPathPrefix, baseDir)
- bazelBaseDirSeen := err == nil &&
- android.InList(bazelBaseDir, baseDirs) ||
- android.InList(bazelBaseDir, excludeDirsStrings)
-
- if baseDir != "" && !baseDirSeen && !bazelBaseDirSeen {
+ if baseDir != "" && !baseDirSeen {
baseDirs = append(baseDirs, baseDir)
}
}
diff --git a/java/generated_java_library.go b/java/generated_java_library.go
index 578237e..40f780c 100644
--- a/java/generated_java_library.go
+++ b/java/generated_java_library.go
@@ -55,7 +55,6 @@
module.addHostAndDeviceProperties()
module.initModuleAndImport(module)
android.InitApexModule(module)
- android.InitBazelModule(module)
InitJavaModule(module, android.HostAndDeviceSupported)
if properties != nil {
module.AddProperties(properties)
diff --git a/java/generated_java_library_test.go b/java/generated_java_library_test.go
index 7f52fd1..be816cd 100644
--- a/java/generated_java_library_test.go
+++ b/java/generated_java_library_test.go
@@ -37,7 +37,6 @@
}
func (callbacks *JavaGenLibTestCallbacks) GenerateSourceJarBuildActions(module *GeneratedJavaLibraryModule, ctx android.ModuleContext) android.Path {
- module.AddAconfigIntermediate(android.PathForOutput(ctx, "aconfig_cache_file"))
return android.PathForOutput(ctx, "blah.srcjar")
}
diff --git a/java/genrule.go b/java/genrule.go
index 208e1f4..b84225f 100644
--- a/java/genrule.go
+++ b/java/genrule.go
@@ -65,7 +65,6 @@
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
- android.InitBazelModule(module)
return module
}
@@ -79,7 +78,6 @@
android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommon)
android.InitDefaultableModule(module)
- android.InitBazelModule(module)
return module
}
diff --git a/java/hiddenapi.go b/java/hiddenapi.go
index fe3fe7b..5441a3b 100644
--- a/java/hiddenapi.go
+++ b/java/hiddenapi.go
@@ -44,7 +44,8 @@
//
// This must be the path to the unencoded dex jar as the encoded dex jar indirectly depends on
// this file so using the encoded dex jar here would result in a cycle in the ninja rules.
- bootDexJarPath OptionalDexJarPath
+ bootDexJarPath OptionalDexJarPath
+ bootDexJarPathErr error
// The paths to the classes jars that contain classes and class members annotated with
// the UnsupportedAppUsage annotation that need to be extracted as part of the hidden API
@@ -56,7 +57,10 @@
uncompressDexState *bool
}
-func (h *hiddenAPI) bootDexJar() OptionalDexJarPath {
+func (h *hiddenAPI) bootDexJar(ctx android.ModuleErrorfContext) OptionalDexJarPath {
+ if h.bootDexJarPathErr != nil {
+ ctx.ModuleErrorf(h.bootDexJarPathErr.Error())
+ }
return h.bootDexJarPath
}
@@ -77,7 +81,7 @@
}
type hiddenAPIIntf interface {
- bootDexJar() OptionalDexJarPath
+ bootDexJar(ctx android.ModuleErrorfContext) OptionalDexJarPath
classesJars() android.Paths
uncompressDex() *bool
}
@@ -94,7 +98,7 @@
// processing.
classesJars := android.Paths{classesJar}
ctx.VisitDirectDepsWithTag(hiddenApiAnnotationsTag, func(dep android.Module) {
- javaInfo := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
+ javaInfo, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
classesJars = append(classesJars, javaInfo.ImplementationJars...)
})
h.classesJarPaths = classesJars
@@ -126,6 +130,11 @@
h.active = isModuleInBootClassPath(ctx, module)
}
+// Store any error encountered during the initialization of hiddenapi structure (e.g. unflagged co-existing prebuilt apexes)
+func (h *hiddenAPI) initHiddenAPIError(err error) {
+ h.bootDexJarPathErr = err
+}
+
func isModuleInBootClassPath(ctx android.BaseModuleContext, module android.Module) bool {
// Get the configured platform and apex boot jars.
nonApexBootJars := ctx.Config().NonApexBootJars()
diff --git a/java/hiddenapi_modular.go b/java/hiddenapi_modular.go
index f31f5d1..e4beb5e 100644
--- a/java/hiddenapi_modular.go
+++ b/java/hiddenapi_modular.go
@@ -19,6 +19,7 @@
"strings"
"android/soong/android"
+ "android/soong/dexpreopt"
"github.com/google/blueprint"
)
@@ -38,10 +39,14 @@
// The option needed to passed to "hiddenapi list".
hiddenAPIListOption string
- // The name sof the source stub library modules that contain the API provided by the platform,
+ // The names of the source stub library modules that contain the API provided by the platform,
// i.e. by modules that are not in an APEX.
nonUpdatableSourceModule string
+ // The names of from-text stub library modules that contain the API provided by the platform,
+ // i.e. by modules that are not in an APEX.
+ nonUpdatableFromTextModule string
+
// The names of the prebuilt stub library modules that contain the API provided by the platform,
// i.e. by modules that are not in an APEX.
nonUpdatablePrebuiltModule string
@@ -86,6 +91,9 @@
if ctx.Config().AlwaysUsePrebuiltSdks() {
return l.nonUpdatablePrebuiltModule
} else {
+ if l.nonUpdatableFromTextModule != "" && ctx.Config().BuildFromTextStub() {
+ return l.nonUpdatableFromTextModule
+ }
return l.nonUpdatableSourceModule
}
} else {
@@ -117,8 +125,9 @@
hiddenAPIListOption: "--test-stub-classpath",
})
ModuleLibHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
- name: "module-lib",
- sdkKind: android.SdkModule,
+ name: "module-lib",
+ sdkKind: android.SdkModule,
+ nonUpdatableFromTextModule: "android-non-updatable.stubs.test_module_lib",
})
CorePlatformHiddenAPIScope = initHiddenAPIScope(&HiddenAPIScope{
name: "core-platform",
@@ -236,12 +245,22 @@
testStubModules = append(testStubModules, "sdk_test_current_android")
} else {
// Use stub modules built from source
- publicStubModules = append(publicStubModules, android.SdkPublic.DefaultJavaLibraryName())
- systemStubModules = append(systemStubModules, android.SdkSystem.DefaultJavaLibraryName())
- testStubModules = append(testStubModules, android.SdkTest.DefaultJavaLibraryName())
+ if config.ReleaseHiddenApiExportableStubs() {
+ publicStubModules = append(publicStubModules, android.SdkPublic.DefaultExportableJavaLibraryName())
+ systemStubModules = append(systemStubModules, android.SdkSystem.DefaultExportableJavaLibraryName())
+ testStubModules = append(testStubModules, android.SdkTest.DefaultExportableJavaLibraryName())
+ } else {
+ publicStubModules = append(publicStubModules, android.SdkPublic.DefaultJavaLibraryName())
+ systemStubModules = append(systemStubModules, android.SdkSystem.DefaultJavaLibraryName())
+ testStubModules = append(testStubModules, android.SdkTest.DefaultJavaLibraryName())
+ }
}
// We do not have prebuilts of the core platform api yet
- corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
+ if config.ReleaseHiddenApiExportableStubs() {
+ corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs.exportable")
+ } else {
+ corePlatformStubModules = append(corePlatformStubModules, "legacy.core.platform.api.stubs")
+ }
// Allow products to define their own stubs for custom product jars that apps can use.
publicStubModules = append(publicStubModules, config.ProductHiddenAPIStubs()...)
@@ -280,9 +299,14 @@
func hiddenAPIRetrieveDexJarBuildPath(ctx android.ModuleContext, module android.Module, kind android.SdkKind) android.Path {
var dexJar OptionalDexJarPath
if sdkLibrary, ok := module.(SdkLibraryDependency); ok {
- dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
+ if ctx.Config().ReleaseHiddenApiExportableStubs() {
+ dexJar = sdkLibrary.SdkApiExportableStubDexJar(ctx, kind)
+ } else {
+ dexJar = sdkLibrary.SdkApiStubDexJar(ctx, kind)
+ }
+
} else if j, ok := module.(UsesLibraryDependency); ok {
- dexJar = j.DexJarBuildPath()
+ dexJar = j.DexJarBuildPath(ctx)
} else {
ctx.ModuleErrorf("dependency %s of module type %s does not support providing a dex jar", module, ctx.OtherModuleType(module))
return nil
@@ -350,7 +374,7 @@
// If there are stub flag files that have been generated by fragments on which this depends then
// use them to validate the stub flag file generated by the rules created by this method.
- if len(stubFlagSubsets) > 0 {
+ if !ctx.Config().DisableVerifyOverlaps() && len(stubFlagSubsets) > 0 {
validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, stubFlagSubsets,
HIDDENAPI_STUB_FLAGS_IMPL_FLAGS)
@@ -411,122 +435,118 @@
}
}
-type hiddenAPIFlagFileCategory struct {
- // PropertyName is the name of the property for this category.
- PropertyName string
+type hiddenAPIFlagFileCategory int
- // propertyValueReader retrieves the value of the property for this category from the set of
- // properties.
- propertyValueReader func(properties *HiddenAPIFlagFileProperties) []string
+const (
+ // The flag file category for removed members of the API.
+ //
+ // This is extracted from HiddenAPIFlagFileCategories as it is needed to add the dex signatures
+ // list of removed API members that are generated automatically from the removed.txt files provided
+ // by API stubs.
+ hiddenAPIFlagFileCategoryRemoved hiddenAPIFlagFileCategory = iota
+ hiddenAPIFlagFileCategoryUnsupported
+ hiddenAPIFlagFileCategoryMaxTargetRLowPriority
+ hiddenAPIFlagFileCategoryMaxTargetQ
+ hiddenAPIFlagFileCategoryMaxTargetP
+ hiddenAPIFlagFileCategoryMaxTargetOLowPriority
+ hiddenAPIFlagFileCategoryBlocked
+ hiddenAPIFlagFileCategoryUnsupportedPackages
+)
- // commandMutator adds the appropriate command line options for this category to the supplied
- // command
- commandMutator func(command *android.RuleBuilderCommand, path android.Path)
-}
-
-// The flag file category for removed members of the API.
-//
-// This is extracted from HiddenAPIFlagFileCategories as it is needed to add the dex signatures
-// list of removed API members that are generated automatically from the removed.txt files provided
-// by API stubs.
-var hiddenAPIRemovedFlagFileCategory = &hiddenAPIFlagFileCategory{
- // See HiddenAPIFlagFileProperties.Removed
- PropertyName: "removed",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Hidden_api.Removed
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
- },
-}
-
-type hiddenAPIFlagFileCategories []*hiddenAPIFlagFileCategory
-
-func (c hiddenAPIFlagFileCategories) byProperty(name string) *hiddenAPIFlagFileCategory {
- for _, category := range c {
- if category.PropertyName == name {
- return category
- }
+func (c hiddenAPIFlagFileCategory) PropertyName() string {
+ switch c {
+ case hiddenAPIFlagFileCategoryRemoved:
+ return "removed"
+ case hiddenAPIFlagFileCategoryUnsupported:
+ return "unsupported"
+ case hiddenAPIFlagFileCategoryMaxTargetRLowPriority:
+ return "max_target_r_low_priority"
+ case hiddenAPIFlagFileCategoryMaxTargetQ:
+ return "max_target_q"
+ case hiddenAPIFlagFileCategoryMaxTargetP:
+ return "max_target_p"
+ case hiddenAPIFlagFileCategoryMaxTargetOLowPriority:
+ return "max_target_o_low_priority"
+ case hiddenAPIFlagFileCategoryBlocked:
+ return "blocked"
+ case hiddenAPIFlagFileCategoryUnsupportedPackages:
+ return "unsupported_packages"
+ default:
+ panic(fmt.Sprintf("Unknown hidden api flag file category type: %d", c))
}
- panic(fmt.Errorf("no category exists with property name %q in %v", name, c))
}
+// propertyValueReader retrieves the value of the property for this category from the set of properties.
+func (c hiddenAPIFlagFileCategory) propertyValueReader(properties *HiddenAPIFlagFileProperties) []string {
+ switch c {
+ case hiddenAPIFlagFileCategoryRemoved:
+ return properties.Hidden_api.Removed
+ case hiddenAPIFlagFileCategoryUnsupported:
+ return properties.Hidden_api.Unsupported
+ case hiddenAPIFlagFileCategoryMaxTargetRLowPriority:
+ return properties.Hidden_api.Max_target_r_low_priority
+ case hiddenAPIFlagFileCategoryMaxTargetQ:
+ return properties.Hidden_api.Max_target_q
+ case hiddenAPIFlagFileCategoryMaxTargetP:
+ return properties.Hidden_api.Max_target_p
+ case hiddenAPIFlagFileCategoryMaxTargetOLowPriority:
+ return properties.Hidden_api.Max_target_o_low_priority
+ case hiddenAPIFlagFileCategoryBlocked:
+ return properties.Hidden_api.Blocked
+ case hiddenAPIFlagFileCategoryUnsupportedPackages:
+ return properties.Hidden_api.Unsupported_packages
+ default:
+ panic(fmt.Sprintf("Unknown hidden api flag file category type: %d", c))
+ }
+}
+
+// commandMutator adds the appropriate command line options for this category to the supplied command
+func (c hiddenAPIFlagFileCategory) commandMutator(command *android.RuleBuilderCommand, path android.Path) {
+ switch c {
+ case hiddenAPIFlagFileCategoryRemoved:
+ command.FlagWithInput("--unsupported ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "removed")
+ case hiddenAPIFlagFileCategoryUnsupported:
+ command.FlagWithInput("--unsupported ", path)
+ case hiddenAPIFlagFileCategoryMaxTargetRLowPriority:
+ command.FlagWithInput("--max-target-r ", path).FlagWithArg("--tag ", "lo-prio")
+ case hiddenAPIFlagFileCategoryMaxTargetQ:
+ command.FlagWithInput("--max-target-q ", path)
+ case hiddenAPIFlagFileCategoryMaxTargetP:
+ command.FlagWithInput("--max-target-p ", path)
+ case hiddenAPIFlagFileCategoryMaxTargetOLowPriority:
+ command.FlagWithInput("--max-target-o ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio")
+ case hiddenAPIFlagFileCategoryBlocked:
+ command.FlagWithInput("--blocked ", path)
+ case hiddenAPIFlagFileCategoryUnsupportedPackages:
+ command.FlagWithInput("--unsupported ", path).Flag("--packages ")
+ default:
+ panic(fmt.Sprintf("Unknown hidden api flag file category type: %d", c))
+ }
+}
+
+type hiddenAPIFlagFileCategories []hiddenAPIFlagFileCategory
+
var HiddenAPIFlagFileCategories = hiddenAPIFlagFileCategories{
// See HiddenAPIFlagFileProperties.Unsupported
- {
- PropertyName: "unsupported",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Hidden_api.Unsupported
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--unsupported ", path)
- },
- },
- hiddenAPIRemovedFlagFileCategory,
+ hiddenAPIFlagFileCategoryUnsupported,
+ // See HiddenAPIFlagFileProperties.Removed
+ hiddenAPIFlagFileCategoryRemoved,
// See HiddenAPIFlagFileProperties.Max_target_r_low_priority
- {
- PropertyName: "max_target_r_low_priority",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Hidden_api.Max_target_r_low_priority
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--max-target-r ", path).FlagWithArg("--tag ", "lo-prio")
- },
- },
+ hiddenAPIFlagFileCategoryMaxTargetRLowPriority,
// See HiddenAPIFlagFileProperties.Max_target_q
- {
- PropertyName: "max_target_q",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Hidden_api.Max_target_q
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--max-target-q ", path)
- },
- },
+ hiddenAPIFlagFileCategoryMaxTargetQ,
// See HiddenAPIFlagFileProperties.Max_target_p
- {
- PropertyName: "max_target_p",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Hidden_api.Max_target_p
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--max-target-p ", path)
- },
- },
+ hiddenAPIFlagFileCategoryMaxTargetP,
// See HiddenAPIFlagFileProperties.Max_target_o_low_priority
- {
- PropertyName: "max_target_o_low_priority",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Hidden_api.Max_target_o_low_priority
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--max-target-o ", path).Flag("--ignore-conflicts ").FlagWithArg("--tag ", "lo-prio")
- },
- },
+ hiddenAPIFlagFileCategoryMaxTargetOLowPriority,
// See HiddenAPIFlagFileProperties.Blocked
- {
- PropertyName: "blocked",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Hidden_api.Blocked
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--blocked ", path)
- },
- },
+ hiddenAPIFlagFileCategoryBlocked,
// See HiddenAPIFlagFileProperties.Unsupported_packages
- {
- PropertyName: "unsupported_packages",
- propertyValueReader: func(properties *HiddenAPIFlagFileProperties) []string {
- return properties.Hidden_api.Unsupported_packages
- },
- commandMutator: func(command *android.RuleBuilderCommand, path android.Path) {
- command.FlagWithInput("--unsupported ", path).Flag("--packages ")
- },
- },
+ hiddenAPIFlagFileCategoryUnsupportedPackages,
}
// FlagFilesByCategory maps a hiddenAPIFlagFileCategory to the paths to the files in that category.
-type FlagFilesByCategory map[*hiddenAPIFlagFileCategory]android.Paths
+type FlagFilesByCategory map[hiddenAPIFlagFileCategory]android.Paths
// append the supplied flags files to the corresponding category in this map.
func (s FlagFilesByCategory) append(other FlagFilesByCategory) {
@@ -571,8 +591,7 @@
// Merge all the information from the fragments. The fragments form a DAG so it is possible that
// this will introduce duplicates so they will be resolved after processing all the fragments.
for _, fragment := range fragments {
- if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
- info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
+ if info, ok := android.OtherModuleProvider(ctx, fragment, HiddenAPIInfoProvider); ok {
i.TransitiveStubDexJarsByScope.addStubDexJarsByModule(info.TransitiveStubDexJarsByScope)
}
}
@@ -592,7 +611,7 @@
return SignatureCsvSubset{i.FilteredFlagsPath, i.SignaturePatternsPath}
}
-var HiddenAPIInfoProvider = blueprint.NewProvider(HiddenAPIInfo{})
+var HiddenAPIInfoProvider = blueprint.NewProvider[HiddenAPIInfo]()
// HiddenAPIInfoForSdk contains information provided by the hidden API processing for use
// by the sdk snapshot.
@@ -609,7 +628,7 @@
}
// Provides hidden API info for the sdk snapshot.
-var HiddenAPIInfoForSdkProvider = blueprint.NewProvider(HiddenAPIInfoForSdk{})
+var HiddenAPIInfoForSdkProvider = blueprint.NewProvider[HiddenAPIInfoForSdk]()
// ModuleStubDexJars contains the stub dex jars provided by a single module.
//
@@ -647,7 +666,7 @@
// public version is provided by the art.module.public.api module. In those cases it is necessary
// to treat all those modules as they were the same name, otherwise it will result in multiple
// definitions of a single class being passed to hidden API processing which will cause an error.
- if name == scope.nonUpdatablePrebuiltModule || name == scope.nonUpdatableSourceModule {
+ if name == scope.nonUpdatablePrebuiltModule || name == scope.nonUpdatableSourceModule || name == scope.nonUpdatableFromTextModule {
// Treat all *android-non-updatable* modules as if they were part of an android-non-updatable
// java_sdk_library.
// TODO(b/192067200): Remove once android-non-updatable is a java_sdk_library or equivalent.
@@ -741,7 +760,7 @@
SplitPackages []string
}
-var hiddenAPIPropertyInfoProvider = blueprint.NewProvider(HiddenAPIPropertyInfo{})
+var hiddenAPIPropertyInfoProvider = blueprint.NewProvider[HiddenAPIPropertyInfo]()
// newHiddenAPIPropertyInfo creates a new initialized HiddenAPIPropertyInfo struct.
func newHiddenAPIPropertyInfo() HiddenAPIPropertyInfo {
@@ -769,8 +788,7 @@
func (i *HiddenAPIPropertyInfo) gatherPropertyInfo(ctx android.ModuleContext, contents []android.Module) {
for _, module := range contents {
- if ctx.OtherModuleHasProvider(module, hiddenAPIPropertyInfoProvider) {
- info := ctx.OtherModuleProvider(module, hiddenAPIPropertyInfoProvider).(HiddenAPIPropertyInfo)
+ if info, ok := android.OtherModuleProvider(ctx, module, hiddenAPIPropertyInfoProvider); ok {
i.FlagFilesByCategory.append(info.FlagFilesByCategory)
i.PackagePrefixes = append(i.PackagePrefixes, info.PackagePrefixes...)
i.SinglePackages = append(i.SinglePackages, info.SinglePackages...)
@@ -941,6 +959,7 @@
HiddenAPIFlagOutput
// The map from base module name to the path to the encoded boot dex file.
+ // This field is not available in prebuilt apexes
EncodedBootDexFilesByModule bootDexJarByModule
}
@@ -991,14 +1010,14 @@
// If available then pass the automatically generated file containing dex signatures of removed
// API members to the rule so they can be marked as removed.
if generatedRemovedDexSignatures.Valid() {
- hiddenAPIRemovedFlagFileCategory.commandMutator(command, generatedRemovedDexSignatures.Path())
+ hiddenAPIFlagFileCategoryRemoved.commandMutator(command, generatedRemovedDexSignatures.Path())
}
commitChangeForRestat(rule, tempPath, outputPath)
// If there are flag files that have been generated by fragments on which this depends then use
// them to validate the flag file generated by the rules created by this method.
- if len(flagSubsets) > 0 {
+ if !ctx.Config().DisableVerifyOverlaps() && len(flagSubsets) > 0 {
validFile := buildRuleValidateOverlappingCsvFiles(ctx, name, desc, outputPath, flagSubsets,
HIDDENAPI_FLAGS_CSV_IMPL_FLAGS)
@@ -1243,9 +1262,27 @@
}
// extractBootDexJarsFromModules extracts the boot dex jars from the supplied modules.
+// This information can come from two mechanisms
+// 1. New: Direct deps to _selected_ apexes. The apexes contain a ApexExportsInfo
+// 2. Legacy: An edge to java_sdk_library(_import) module. For prebuilt apexes, this serves as a hook and is populated by deapexers of prebuilt apxes
+// TODO: b/308174306 - Once all mainline modules have been flagged, drop (2)
func extractBootDexJarsFromModules(ctx android.ModuleContext, contents []android.Module) bootDexJarByModule {
bootDexJars := bootDexJarByModule{}
+
+ apexNameToApexExportsInfoMap := getApexNameToApexExportsInfoMap(ctx)
+ // For ART and mainline module jars, query apexNameToApexExportsInfoMap to get the dex file
+ apexJars := dexpreopt.GetGlobalConfig(ctx).ArtApexJars.AppendList(&dexpreopt.GetGlobalConfig(ctx).ApexBootJars)
+ for i := 0; i < apexJars.Len(); i++ {
+ if dex, found := apexNameToApexExportsInfoMap.javaLibraryDexPathOnHost(ctx, apexJars.Apex(i), apexJars.Jar(i)); found {
+ bootDexJars[apexJars.Jar(i)] = dex
+ }
+ }
+
+ // TODO - b/308174306: Drop the legacy mechanism
for _, module := range contents {
+ if _, exists := bootDexJars[android.RemoveOptionalPrebuiltPrefix(module.Name())]; exists {
+ continue
+ }
hiddenAPIModule := hiddenAPIModuleFromModule(ctx, module)
if hiddenAPIModule == nil {
continue
@@ -1316,7 +1353,7 @@
// invalid, then create a fake path and either report an error immediately or defer reporting of the
// error until the path is actually used.
func retrieveBootDexJarFromHiddenAPIModule(ctx android.ModuleContext, module hiddenAPIModule) android.Path {
- bootDexJar := module.bootDexJar()
+ bootDexJar := module.bootDexJar(ctx)
if !bootDexJar.Valid() {
fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/boot-dex/%s.jar", module.Name()))
handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())
@@ -1396,7 +1433,7 @@
}
if am, ok := module.(android.ApexModule); ok && am.InAnyApex() {
- apexInfo := ctx.OtherModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.OtherModuleProvider(ctx, module, android.ApexInfoProvider)
if apexInfo.IsForPlatform() {
return true
}
@@ -1431,7 +1468,9 @@
// However, under certain conditions, e.g. errors, or special build configurations it will return
// a path to a fake file.
func retrieveEncodedBootDexJarFromModule(ctx android.ModuleContext, module android.Module) android.Path {
- bootDexJar := module.(interface{ DexJarBuildPath() OptionalDexJarPath }).DexJarBuildPath()
+ bootDexJar := module.(interface {
+ DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath
+ }).DexJarBuildPath(ctx)
if !bootDexJar.Valid() {
fake := android.PathForModuleOut(ctx, fmt.Sprintf("fake/encoded-dex/%s.jar", module.Name()))
handleMissingDexBootFile(ctx, module, fake, bootDexJar.InvalidReason())
diff --git a/java/hiddenapi_monolithic.go b/java/hiddenapi_monolithic.go
index 5956e3c..a61018d 100644
--- a/java/hiddenapi_monolithic.go
+++ b/java/hiddenapi_monolithic.go
@@ -67,8 +67,7 @@
case *ClasspathFragmentElement:
fragment := e.Module()
- if ctx.OtherModuleHasProvider(fragment, HiddenAPIInfoProvider) {
- info := ctx.OtherModuleProvider(fragment, HiddenAPIInfoProvider).(HiddenAPIInfo)
+ if info, ok := android.OtherModuleProvider(ctx, fragment, HiddenAPIInfoProvider); ok {
monolithicInfo.append(&info)
} else {
ctx.ModuleErrorf("%s does not provide hidden API information", fragment)
@@ -90,4 +89,4 @@
i.FlagSubsets = append(i.FlagSubsets, other.FlagSubset())
}
-var MonolithicHiddenAPIInfoProvider = blueprint.NewProvider(MonolithicHiddenAPIInfo{})
+var MonolithicHiddenAPIInfoProvider = blueprint.NewProvider[MonolithicHiddenAPIInfo]()
diff --git a/java/hiddenapi_singleton.go b/java/hiddenapi_singleton.go
index 8ec1797..8cb78cd 100644
--- a/java/hiddenapi_singleton.go
+++ b/java/hiddenapi_singleton.go
@@ -162,7 +162,7 @@
return false
}
- apexInfo := ctx.OtherModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.OtherModuleProvider(ctx, module, android.ApexInfoProvider)
// Now match the apex part of the boot image configuration.
requiredApex := configuredBootJars.Apex(index)
diff --git a/java/hiddenapi_singleton_test.go b/java/hiddenapi_singleton_test.go
index ef792f9..c1fee21 100644
--- a/java/hiddenapi_singleton_test.go
+++ b/java/hiddenapi_singleton_test.go
@@ -177,10 +177,10 @@
{
name: "testBundled",
unbundledBuild: false,
- publicStub: "android_stubs_current",
- systemStub: "android_system_stubs_current",
- testStub: "android_test_stubs_current",
- corePlatformStub: "legacy.core.platform.api.stubs",
+ publicStub: "android_stubs_current_exportable",
+ systemStub: "android_system_stubs_current_exportable",
+ testStub: "android_test_stubs_current_exportable",
+ corePlatformStub: "legacy.core.platform.api.stubs.exportable",
preparer: android.GroupFixturePreparers(),
}, {
name: "testUnbundled",
@@ -188,7 +188,7 @@
publicStub: "sdk_public_current_android",
systemStub: "sdk_system_current_android",
testStub: "sdk_test_current_android",
- corePlatformStub: "legacy.core.platform.api.stubs",
+ corePlatformStub: "legacy.core.platform.api.stubs.exportable",
preparer: PrepareForTestWithPrebuiltsOfCurrentApi,
},
}
@@ -200,6 +200,9 @@
prepareForTestWithDefaultPlatformBootclasspath,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.Always_use_prebuilt_sdks = proptools.BoolPtr(tc.unbundledBuild)
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
}),
).RunTest(t)
@@ -309,7 +312,8 @@
android.AssertStringEquals(t, "encode embedded java_library", unencodedDexJar, actualUnencodedDexJar.String())
// Make sure that the encoded dex jar is the exported one.
- exportedDexJar := moduleForTests.Module().(UsesLibraryDependency).DexJarBuildPath().Path()
+ errCtx := moduleErrorfTestCtx{}
+ exportedDexJar := moduleForTests.Module().(UsesLibraryDependency).DexJarBuildPath(errCtx).Path()
android.AssertPathRelativeToTopEquals(t, "encode embedded java_library", encodedDexJar, exportedDexJar)
}
diff --git a/java/jacoco.go b/java/jacoco.go
index f8012b8..a820b38 100644
--- a/java/jacoco.go
+++ b/java/jacoco.go
@@ -34,13 +34,11 @@
`${config.Zip2ZipCmd} -i $in -o $strippedJar $stripSpec && ` +
`${config.JavaCmd} ${config.JavaVmFlags} -jar ${config.JacocoCLIJar} ` +
` instrument --quiet --dest $tmpDir $strippedJar && ` +
- `${config.Ziptime} $tmpJar && ` +
`${config.MergeZipsCmd} --ignore-duplicates -j $out $tmpJar $in`,
CommandDeps: []string{
"${config.Zip2ZipCmd}",
"${config.JavaCmd}",
"${config.JacocoCLIJar}",
- "${config.Ziptime}",
"${config.MergeZipsCmd}",
},
},
diff --git a/java/java.go b/java/java.go
index 99bb1b3..cd249ed 100644
--- a/java/java.go
+++ b/java/java.go
@@ -24,10 +24,8 @@
"sort"
"strings"
- "android/soong/bazel"
- "android/soong/bazel/cquery"
"android/soong/remoteexec"
- "android/soong/ui/metrics/bp2build_metrics_proto"
+ "android/soong/testing"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -64,6 +62,7 @@
ctx.RegisterModuleType("dex_import", DexImportFactory)
ctx.RegisterModuleType("java_api_library", ApiLibraryFactory)
ctx.RegisterModuleType("java_api_contribution", ApiContributionFactory)
+ ctx.RegisterModuleType("java_api_contribution_import", ApiContributionImportFactory)
// This mutator registers dependencies on dex2oat for modules that should be
// dexpreopted. This is done late when the final variants have been
@@ -241,7 +240,7 @@
UnconditionallyExportedProguardFlags *android.DepSet[android.Path]
}
-var ProguardSpecInfoProvider = blueprint.NewProvider(ProguardSpecInfo{})
+var ProguardSpecInfoProvider = blueprint.NewProvider[ProguardSpecInfo]()
// JavaInfo contains information about a java module for use by modules that depend on it.
type JavaInfo struct {
@@ -277,6 +276,9 @@
// SrcJarDeps is a list of paths to depend on when packaging the sources of this module.
SrcJarDeps android.Paths
+ // The source files of this module and all its transitive static dependencies.
+ TransitiveSrcFiles *android.DepSet[android.Path]
+
// ExportedPlugins is a list of paths that should be used as annotation processors for any
// module that depends on this module.
ExportedPlugins android.Paths
@@ -292,18 +294,9 @@
// JacocoReportClassesFile is the path to a jar containing uninstrumented classes that will be
// instrumented by jacoco.
JacocoReportClassesFile android.Path
-
- // set of aconfig flags for all transitive libs deps
- // TODO(joeo): It would be nice if this were over in the aconfig package instead of here.
- // In order to do that, generated_java_library would need a way doing
- // collectTransitiveAconfigFiles with one of the callbacks, and having that automatically
- // propagated. If we were to clean up more of the stuff on JavaInfo that's not part of
- // core java rules (e.g. AidlIncludeDirs), then maybe adding more framework to do that would be
- // worth it.
- TransitiveAconfigFiles *android.DepSet[android.Path]
}
-var JavaInfoProvider = blueprint.NewProvider(JavaInfo{})
+var JavaInfoProvider = blueprint.NewProvider[JavaInfo]()
// SyspropPublicStubInfo contains info about the sysprop public stub library that corresponds to
// the sysprop implementation library.
@@ -313,7 +306,7 @@
JavaInfo JavaInfo
}
-var SyspropPublicStubInfoProvider = blueprint.NewProvider(SyspropPublicStubInfo{})
+var SyspropPublicStubInfoProvider = blueprint.NewProvider[SyspropPublicStubInfo]()
// Methods that need to be implemented for a module that is added to apex java_libs property.
type ApexDependency interface {
@@ -323,7 +316,7 @@
// Provides build path and install path to DEX jars.
type UsesLibraryDependency interface {
- DexJarBuildPath() OptionalDexJarPath
+ DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath
DexJarInstallPath() android.Path
ClassLoaderContexts() dexpreopt.ClassLoaderContextMap
}
@@ -413,6 +406,7 @@
syspropPublicStubDepTag = dependencyTag{name: "sysprop public stub"}
javaApiContributionTag = dependencyTag{name: "java-api-contribution"}
depApiSrcsTag = dependencyTag{name: "dep-api-srcs"}
+ aconfigDeclarationTag = dependencyTag{name: "aconfig-declaration"}
jniInstallTag = installDependencyTag{name: "jni install"}
binaryInstallTag = installDependencyTag{name: "binary install"}
usesLibReqTag = makeUsesLibraryDependencyTag(dexpreopt.AnySdkVersion, false)
@@ -526,6 +520,7 @@
kotlinStdlib android.Paths
kotlinAnnotations android.Paths
kotlinPlugins android.Paths
+ aconfigProtoFiles android.Paths
disableTurbine bool
}
@@ -569,9 +564,11 @@
func (v javaVersion) String() string {
switch v {
case JAVA_VERSION_6:
- return "1.6"
+ // Java version 1.6 no longer supported, bumping to 1.8
+ return "1.8"
case JAVA_VERSION_7:
- return "1.7"
+ // Java version 1.7 no longer supported, bumping to 1.8
+ return "1.8"
case JAVA_VERSION_8:
return "1.8"
case JAVA_VERSION_9:
@@ -588,10 +585,12 @@
func (v javaVersion) StringForKotlinc() string {
// $ ./external/kotlinc/bin/kotlinc -jvm-target foo
// error: unknown JVM target version: foo
- // Supported versions: 1.6, 1.8, 9, 10, 11, 12, 13, 14, 15, 16, 17
+ // Supported versions: 1.8, 9, 10, 11, 12, 13, 14, 15, 16, 17
switch v {
+ case JAVA_VERSION_6:
+ return "1.8"
case JAVA_VERSION_7:
- return "1.6"
+ return "1.8"
case JAVA_VERSION_9:
return "9"
default:
@@ -607,9 +606,11 @@
func normalizeJavaVersion(ctx android.BaseModuleContext, javaVersion string) javaVersion {
switch javaVersion {
case "1.6", "6":
- return JAVA_VERSION_6
+ // Java version 1.6 no longer supported, bumping to 1.8
+ return JAVA_VERSION_8
case "1.7", "7":
- return JAVA_VERSION_7
+ // Java version 1.7 no longer supported, bumping to 1.8
+ return JAVA_VERSION_8
case "1.8", "8":
return JAVA_VERSION_8
case "1.9", "9":
@@ -634,9 +635,9 @@
type Library struct {
Module
- exportedProguardFlagFiles android.Paths
+ combinedExportedProguardFlagsFile android.Path
- InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.Paths)
+ InstallMixin func(ctx android.ModuleContext, installPath android.Path) (extraInstallDeps android.InstallPaths)
}
var _ android.ApexModule = (*Library)(nil)
@@ -652,9 +653,9 @@
return j.properties.Permitted_packages
}
-func shouldUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter) bool {
+func shouldUncompressDex(ctx android.ModuleContext, libName string, dexpreopter *dexpreopter) bool {
// Store uncompressed (and aligned) any dex files from jars in APEXes.
- if apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo); !apexInfo.IsForPlatform() {
+ if apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider); !apexInfo.IsForPlatform() {
return true
}
@@ -664,7 +665,7 @@
}
// Store uncompressed dex files that are preopted on /system.
- if !dexpreopter.dexpreoptDisabled(ctx) && (ctx.Host() || !dexpreopter.odexOnSystemOther(ctx, dexpreopter.installPath)) {
+ if !dexpreopter.dexpreoptDisabled(ctx, libName) && (ctx.Host() || !dexpreopter.odexOnSystemOther(ctx, libName, dexpreopter.installPath)) {
return true
}
if ctx.Config().UncompressPrivAppDex() &&
@@ -679,7 +680,7 @@
func setUncompressDex(ctx android.ModuleContext, dexpreopter *dexpreopter, dexer *dexer) {
if dexer.dexProperties.Uncompress_dex == nil {
// If the value was not force-set by the user, use reasonable default based on the module.
- dexer.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, dexpreopter))
+ dexer.dexProperties.Uncompress_dex = proptools.BoolPtr(shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), dexpreopter))
}
}
@@ -693,7 +694,16 @@
j.stem = proptools.StringDefault(j.overridableDeviceProperties.Stem, ctx.ModuleName())
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ proguardSpecInfo := j.collectProguardSpecInfo(ctx)
+ android.SetProvider(ctx, ProguardSpecInfoProvider, proguardSpecInfo)
+ exportedProguardFlagsFiles := proguardSpecInfo.ProguardFlagsFiles.ToList()
+ j.extraProguardFlagsFiles = append(j.extraProguardFlagsFiles, exportedProguardFlagsFiles...)
+
+ combinedExportedProguardFlagFile := android.PathForModuleOut(ctx, "export_proguard_flags")
+ writeCombinedProguardFlagsFile(ctx, combinedExportedProguardFlagFile, exportedProguardFlagsFiles)
+ j.combinedExportedProguardFlagsFile = combinedExportedProguardFlagFile
+
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if !apexInfo.IsForPlatform() {
j.hideApexVariantFromMake = true
}
@@ -702,7 +712,7 @@
j.checkHeadersOnly(ctx)
if ctx.Device() {
j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
- ctx, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
+ ctx, j.Name(), android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
j.dexpreopter.isSDKLibrary = j.deviceProperties.IsSDKLibrary
setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
@@ -710,12 +720,9 @@
}
j.compile(ctx, nil, nil, nil)
- // Collect the module directory for IDE info in java/jdeps.go.
- j.modulePaths = append(j.modulePaths, ctx.ModuleDir())
-
exclusivelyForApex := !apexInfo.IsForPlatform()
if (Bool(j.properties.Installable) || ctx.Host()) && !exclusivelyForApex {
- var extraInstallDeps android.Paths
+ var extraInstallDeps android.InstallPaths
if j.InstallMixin != nil {
extraInstallDeps = j.InstallMixin(ctx, j.outputFile)
}
@@ -737,10 +744,6 @@
}
j.installFile = ctx.InstallFile(installDir, j.Stem()+".jar", j.outputFile, extraInstallDeps...)
}
-
- proguardSpecInfo := j.collectProguardSpecInfo(ctx)
- ctx.SetProvider(ProguardSpecInfoProvider, proguardSpecInfo)
- j.exportedProguardFlagFiles = proguardSpecInfo.ProguardFlagsFiles.ToList()
}
func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -910,7 +913,6 @@
module.initModuleAndImport(module)
android.InitApexModule(module)
- android.InitBazelModule(module)
InitJavaModule(module, android.HostAndDeviceSupported)
return module
}
@@ -932,7 +934,6 @@
module.Module.properties.Installable = proptools.BoolPtr(true)
android.InitApexModule(module)
- android.InitBazelModule(module)
InitJavaModule(module, android.HostSupported)
return module
}
@@ -1083,6 +1084,10 @@
return true
}
+func (j *TestHost) IsNativeCoverageNeeded(ctx android.IncomingTransitionContext) bool {
+ return ctx.DeviceConfig().NativeCoverageEnabled()
+}
+
func (j *TestHost) addDataDeviceBinsDeps(ctx android.BottomUpMutatorContext) {
if len(j.testHostProperties.Data_device_bins_first) > 0 {
deviceVariations := ctx.Config().AndroidFirstDeviceTarget.Variations()
@@ -1219,10 +1224,12 @@
}
j.Test.generateAndroidBuildActionsWithConfig(ctx, configs)
+ android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
func (j *Test) GenerateAndroidBuildActions(ctx android.ModuleContext) {
j.generateAndroidBuildActionsWithConfig(ctx, nil)
+ android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
func (j *Test) generateAndroidBuildActionsWithConfig(ctx android.ModuleContext, configs []tradefed.Config) {
@@ -1258,7 +1265,7 @@
})
ctx.VisitDirectDepsWithTag(jniLibTag, func(dep android.Module) {
- sharedLibInfo := ctx.OtherModuleProvider(dep, cc.SharedLibraryInfoProvider).(cc.SharedLibraryInfo)
+ sharedLibInfo, _ := android.OtherModuleProvider(ctx, dep, cc.SharedLibraryInfoProvider)
if sharedLibInfo.SharedLibrary != nil {
// Copy to an intermediate output directory to append "lib[64]" to the path,
// so that it's compatible with the default rpath values.
@@ -1436,8 +1443,6 @@
nil,
nil)
- android.InitBazelModule(module)
-
InitJavaModuleMultiTargets(module, android.HostSupported)
return module
@@ -1578,7 +1583,6 @@
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommonFirst)
android.InitDefaultableModule(module)
- android.InitBazelModule(module)
return module
}
@@ -1597,13 +1601,13 @@
android.InitAndroidArchModule(module, android.HostSupported, android.MultilibCommonFirst)
android.InitDefaultableModule(module)
- android.InitBazelModule(module)
return module
}
type JavaApiContribution struct {
android.ModuleBase
android.DefaultableModuleBase
+ embeddableInModuleAndImport
properties struct {
// name of the API surface
@@ -1619,14 +1623,16 @@
android.InitAndroidModule(module)
android.InitDefaultableModule(module)
module.AddProperties(&module.properties)
+ module.initModuleAndImport(module)
return module
}
type JavaApiImportInfo struct {
- ApiFile android.Path
+ ApiFile android.Path
+ ApiSurface string
}
-var JavaApiImportProvider = blueprint.NewProvider(JavaApiImportInfo{})
+var JavaApiImportProvider = blueprint.NewProvider[JavaApiImportInfo]()
func (ap *JavaApiContribution) GenerateAndroidBuildActions(ctx android.ModuleContext) {
var apiFile android.Path = nil
@@ -1634,8 +1640,9 @@
apiFile = android.PathForModuleSrc(ctx, String(apiFileString))
}
- ctx.SetProvider(JavaApiImportProvider, JavaApiImportInfo{
- ApiFile: apiFile,
+ android.SetProvider(ctx, JavaApiImportProvider, JavaApiImportInfo{
+ ApiFile: apiFile,
+ ApiSurface: proptools.String(ap.properties.Api_surface),
})
}
@@ -1645,6 +1652,7 @@
hiddenAPI
dexer
+ embeddableInModuleAndImport
properties JavaApiLibraryProperties
@@ -1654,6 +1662,8 @@
extractedSrcJar android.WritablePath
// .dex of stubs, used for hiddenapi processing
dexJarFile OptionalDexJarPath
+
+ validationPaths android.Paths
}
type JavaApiLibraryProperties struct {
@@ -1664,11 +1674,6 @@
// This is a list of Soong modules
Api_contributions []string
- // list of api.txt files relative to this directory that contribute to the
- // API surface.
- // This is a list of relative paths
- Api_files []string `android:"path"`
-
// List of flags to be passed to the javac compiler to generate jar file
Javacflags []string
@@ -1688,12 +1693,25 @@
// Version of previously released API file for compatibility check.
Previous_api *string `android:"path"`
+
+ // java_system_modules module providing the jar to be added to the
+ // bootclasspath when compiling the stubs.
+ // The jar will also be passed to metalava as a classpath to
+ // generate compilable stubs.
+ System_modules *string
+
+ // If true, the module runs validation on the API signature files provided
+ // by the modules passed via api_contributions by checking if the files are
+ // in sync with the source Java files. However, the environment variable
+ // DISABLE_STUB_VALIDATION has precedence over this property.
+ Enable_validation *bool
}
func ApiLibraryFactory() android.Module {
module := &ApiLibrary{}
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
module.AddProperties(&module.properties)
+ module.initModuleAndImport(module)
android.InitDefaultableModule(module)
return module
}
@@ -1707,7 +1725,8 @@
}
func metalavaStubCmd(ctx android.ModuleContext, rule *android.RuleBuilder,
- srcs android.Paths, homeDir android.WritablePath) *android.RuleBuilderCommand {
+ srcs android.Paths, homeDir android.WritablePath,
+ classpath android.Paths) *android.RuleBuilderCommand {
rule.Command().Text("rm -rf").Flag(homeDir.String())
rule.Command().Text("mkdir -p").Flag(homeDir.String())
@@ -1746,12 +1765,17 @@
FlagWithArg("--hide ", "InvalidNullabilityOverride").
FlagWithArg("--hide ", "ChangedDefault")
- // The main purpose of the `--api-class-resolution api` option is to force metalava to ignore
- // classes on the classpath when an API file contains missing classes. However, as this command
- // does not specify `--classpath` this is not needed for that. However, this is also used as a
- // signal to the special metalava code for generating stubs from text files that it needs to add
- // some additional items into the API (e.g. default constructors).
- cmd.FlagWithArg("--api-class-resolution ", "api")
+ if len(classpath) == 0 {
+ // The main purpose of the `--api-class-resolution api` option is to force metalava to ignore
+ // classes on the classpath when an API file contains missing classes. However, as this command
+ // does not specify `--classpath` this is not needed for that. However, this is also used as a
+ // signal to the special metalava code for generating stubs from text files that it needs to add
+ // some additional items into the API (e.g. default constructors).
+ cmd.FlagWithArg("--api-class-resolution ", "api")
+ } else {
+ cmd.FlagWithArg("--api-class-resolution ", "api:classpath")
+ cmd.FlagWithInputList("--classpath ", classpath, ":")
+ }
return cmd
}
@@ -1770,6 +1794,12 @@
}
}
+func (al *ApiLibrary) addValidation(ctx android.ModuleContext, cmd *android.RuleBuilderCommand, validationPaths android.Paths) {
+ for _, validationPath := range validationPaths {
+ cmd.Validation(validationPath)
+ }
+}
+
// This method extracts the stub class files from the stub jar file provided
// from full_api_surface_stub module instead of compiling the srcjar generated from invoking metalava.
// This method is used because metalava can generate compilable from-text stubs only when
@@ -1798,6 +1828,7 @@
Flag("-jar").
Flag("-write_if_changed").
Flag("-ignore_missing_files").
+ Flag("-quiet").
FlagWithArg("-C ", unzippedSrcJarDir.String()).
FlagWithInput("-l ", classFilesList).
FlagWithOutput("-o ", al.stubsJarWithoutStaticLibs)
@@ -1805,36 +1836,56 @@
func (al *ApiLibrary) DepsMutator(ctx android.BottomUpMutatorContext) {
apiContributions := al.properties.Api_contributions
+ addValidations := !ctx.Config().IsEnvTrue("DISABLE_STUB_VALIDATION") &&
+ !ctx.Config().IsEnvTrue("WITHOUT_CHECK_API") &&
+ proptools.BoolDefault(al.properties.Enable_validation, true)
for _, apiContributionName := range apiContributions {
ctx.AddDependency(ctx.Module(), javaApiContributionTag, apiContributionName)
+
+ // Add the java_api_contribution module generating droidstubs module
+ // as dependency when validation adding conditions are met and
+ // the java_api_contribution module name has ".api.contribution" suffix.
+ // All droidstubs-generated modules possess the suffix in the name,
+ // but there is no such guarantee for tests.
+ if addValidations {
+ if strings.HasSuffix(apiContributionName, ".api.contribution") {
+ ctx.AddDependency(ctx.Module(), metalavaCurrentApiTimestampTag, strings.TrimSuffix(apiContributionName, ".api.contribution"))
+ } else {
+ ctx.ModuleErrorf("Validation is enabled for module %s but a "+
+ "current timestamp provider is not found for the api "+
+ "contribution %s",
+ ctx.ModuleName(),
+ apiContributionName,
+ )
+ }
+ }
}
ctx.AddVariationDependencies(nil, libTag, al.properties.Libs...)
ctx.AddVariationDependencies(nil, staticLibTag, al.properties.Static_libs...)
if al.properties.Full_api_surface_stub != nil {
ctx.AddVariationDependencies(nil, depApiSrcsTag, String(al.properties.Full_api_surface_stub))
}
+ if al.properties.System_modules != nil {
+ ctx.AddVariationDependencies(nil, systemModulesTag, String(al.properties.System_modules))
+ }
}
-// API signature file names sorted from
-// the narrowest api scope to the widest api scope
-var scopeOrderedSourceFileNames = allApiScopes.Strings(
- func(s *apiScope) string { return s.apiFilePrefix + "current.txt" })
+// Map where key is the api scope name and value is the int value
+// representing the order of the api scope, narrowest to the widest
+var scopeOrderMap = allApiScopes.MapToIndex(
+ func(s *apiScope) string { return s.name })
-func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFiles android.Paths) android.Paths {
- sortedSrcFiles := android.Paths{}
-
- for _, scopeSourceFileName := range scopeOrderedSourceFileNames {
- for _, sourceFileName := range srcFiles {
- if sourceFileName.Base() == scopeSourceFileName {
- sortedSrcFiles = append(sortedSrcFiles, sourceFileName)
- }
+func (al *ApiLibrary) sortApiFilesByApiScope(ctx android.ModuleContext, srcFilesInfo []JavaApiImportInfo) []JavaApiImportInfo {
+ for _, srcFileInfo := range srcFilesInfo {
+ if srcFileInfo.ApiSurface == "" {
+ ctx.ModuleErrorf("Api surface not defined for the associated api file %s", srcFileInfo.ApiFile)
}
}
- if len(srcFiles) != len(sortedSrcFiles) {
- ctx.ModuleErrorf("Unrecognizable source file found within %s", srcFiles)
- }
+ sort.Slice(srcFilesInfo, func(i, j int) bool {
+ return scopeOrderMap[srcFilesInfo[i].ApiSurface] < scopeOrderMap[srcFilesInfo[j].ApiSurface]
+ })
- return sortedSrcFiles
+ return srcFilesInfo
}
func (al *ApiLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -1845,51 +1896,56 @@
android.PathForModuleOut(ctx, "metalava.sbox.textproto")).
SandboxInputs()
- var stubsDir android.OptionalPath
- stubsDir = android.OptionalPathForPath(android.PathForModuleOut(ctx, "metalava", "stubsDir"))
+ stubsDir := android.OptionalPathForPath(android.PathForModuleOut(ctx, "metalava", "stubsDir"))
rule.Command().Text("rm -rf").Text(stubsDir.String())
rule.Command().Text("mkdir -p").Text(stubsDir.String())
homeDir := android.PathForModuleOut(ctx, "metalava", "home")
- var srcFiles android.Paths
+ var srcFilesInfo []JavaApiImportInfo
var classPaths android.Paths
var staticLibs android.Paths
var depApiSrcsStubsJar android.Path
+ var systemModulesPaths android.Paths
ctx.VisitDirectDeps(func(dep android.Module) {
tag := ctx.OtherModuleDependencyTag(dep)
switch tag {
case javaApiContributionTag:
- provider := ctx.OtherModuleProvider(dep, JavaApiImportProvider).(JavaApiImportInfo)
- providerApiFile := provider.ApiFile
- if providerApiFile == nil && !ctx.Config().AllowMissingDependencies() {
+ provider, _ := android.OtherModuleProvider(ctx, dep, JavaApiImportProvider)
+ if provider.ApiFile == nil && !ctx.Config().AllowMissingDependencies() {
ctx.ModuleErrorf("Error: %s has an empty api file.", dep.Name())
}
- srcFiles = append(srcFiles, android.PathForSource(ctx, providerApiFile.String()))
+ srcFilesInfo = append(srcFilesInfo, provider)
case libTag:
- provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
+ provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
classPaths = append(classPaths, provider.HeaderJars...)
case staticLibTag:
- provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
+ provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
staticLibs = append(staticLibs, provider.HeaderJars...)
case depApiSrcsTag:
- provider := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
+ provider, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
depApiSrcsStubsJar = provider.HeaderJars[0]
+ case systemModulesTag:
+ module := dep.(SystemModulesProvider)
+ systemModulesPaths = append(systemModulesPaths, module.HeaderJars()...)
+ case metalavaCurrentApiTimestampTag:
+ if currentApiTimestampProvider, ok := dep.(currentApiTimestampProvider); ok {
+ al.validationPaths = append(al.validationPaths, currentApiTimestampProvider.CurrentApiTimestamp())
+ }
}
})
- // Add the api_files inputs
- for _, api := range al.properties.Api_files {
- srcFiles = append(srcFiles, android.PathForModuleSrc(ctx, api))
+ srcFilesInfo = al.sortApiFilesByApiScope(ctx, srcFilesInfo)
+ var srcFiles android.Paths
+ for _, srcFileInfo := range srcFilesInfo {
+ srcFiles = append(srcFiles, android.PathForSource(ctx, srcFileInfo.ApiFile.String()))
}
if srcFiles == nil && !ctx.Config().AllowMissingDependencies() {
ctx.ModuleErrorf("Error: %s has an empty api file.", ctx.ModuleName())
}
- srcFiles = al.sortApiFilesByApiScope(ctx, srcFiles)
-
- cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir)
+ cmd := metalavaStubCmd(ctx, rule, srcFiles, homeDir, systemModulesPaths)
al.stubsFlags(ctx, cmd, stubsDir)
@@ -1899,6 +1955,8 @@
cmd.FlagWithInput("--migrate-nullness ", previousApi)
}
+ al.addValidation(ctx, cmd, al.validationPaths)
+
al.stubsSrcJar = android.PathForModuleOut(ctx, "metalava", ctx.ModuleName()+"-"+"stubs.srcjar")
al.stubsJarWithoutStaticLibs = android.PathForModuleOut(ctx, "metalava", "stubs.jar")
al.stubsJar = android.PathForModuleOut(ctx, ctx.ModuleName(), fmt.Sprintf("%s.jar", ctx.ModuleName()))
@@ -1921,6 +1979,7 @@
flags.javaVersion = getStubsJavaVersion()
flags.javacFlags = strings.Join(al.properties.Javacflags, " ")
flags.classpath = classpath(classPaths)
+ flags.bootClasspath = classpath(systemModulesPaths)
annoSrcJar := android.PathForModuleOut(ctx, ctx.ModuleName(), "anno.srcjar")
@@ -1952,7 +2011,7 @@
ctx.Phony(ctx.ModuleName(), al.stubsJar)
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
+ android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
HeaderJars: android.PathsIfNonNil(al.stubsJar),
ImplementationAndResourcesJars: android.PathsIfNonNil(al.stubsJar),
ImplementationJars: android.PathsIfNonNil(al.stubsJar),
@@ -1961,7 +2020,7 @@
})
}
-func (al *ApiLibrary) DexJarBuildPath() OptionalDexJarPath {
+func (al *ApiLibrary) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
return al.dexJarFile
}
@@ -2031,13 +2090,17 @@
// that depend on this module, as well as to aidl for this module.
Export_include_dirs []string
}
+
+ // Name of the source soong module that gets shadowed by this prebuilt
+ // If unspecified, follows the naming convention that the source module of
+ // the prebuilt is Name() without "prebuilt_" prefix
+ Source_module_name *string
}
type Import struct {
android.ModuleBase
android.DefaultableModuleBase
android.ApexModuleBase
- android.BazelModuleBase
prebuilt android.Prebuilt
// Functionality common to Module and Import.
@@ -2051,6 +2114,7 @@
// output file containing classes.dex and resources
dexJarFile OptionalDexJarPath
+ dexJarFileErr error
dexJarInstallFile android.Path
combinedClasspathFile android.Path
@@ -2104,12 +2168,16 @@
return j.properties.Jars
}
+func (j *Import) BaseModuleName() string {
+ return proptools.StringDefault(j.properties.Source_module_name, j.ModuleBase.Name())
+}
+
func (j *Import) Name() string {
return j.prebuilt.Name(j.ModuleBase.Name())
}
func (j *Import) Stem() string {
- return proptools.StringDefault(j.properties.Stem, j.ModuleBase.Name())
+ return proptools.StringDefault(j.properties.Stem, j.BaseModuleName())
}
func (a *Import) JacocoReportClassesFile() android.Path {
@@ -2136,11 +2204,11 @@
}
func (j *Import) commonBuildActions(ctx android.ModuleContext) {
- //TODO(b/231322772) these should come from Bazel once available
j.sdkVersion = j.SdkVersion(ctx)
j.minSdkVersion = j.MinSdkVersion(ctx)
- if !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform() {
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ if !apexInfo.IsForPlatform() {
j.hideApexVariantFromMake = true
}
@@ -2171,8 +2239,7 @@
j.collectTransitiveHeaderJars(ctx)
ctx.VisitDirectDeps(func(module android.Module) {
tag := ctx.OtherModuleDependencyTag(module)
- if ctx.OtherModuleHasProvider(module, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ if dep, ok := android.OtherModuleProvider(ctx, module, JavaInfoProvider); ok {
switch tag {
case libTag, sdkLibTag:
flags.classpath = append(flags.classpath, dep.HeaderJars...)
@@ -2199,21 +2266,25 @@
if ctx.Device() {
// If this is a variant created for a prebuilt_apex then use the dex implementation jar
// obtained from the associated deapexer module.
- ai := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if ai.ForPrebuiltApex {
// Get the path of the dex implementation jar from the `deapexer` module.
- di := android.FindDeapexerProviderForModule(ctx)
- if di == nil {
- return // An error has been reported by FindDeapexerProviderForModule.
+ di, err := android.FindDeapexerProviderForModule(ctx)
+ if err != nil {
+ // An error was found, possibly due to multiple apexes in the tree that export this library
+ // Defer the error till a client tries to call DexJarBuildPath
+ j.dexJarFileErr = err
+ j.initHiddenAPIError(err)
+ return
}
- dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(j.BaseModuleName())
+ dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(j.BaseModuleName())
if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
dexJarFile := makeDexJarPathFromPath(dexOutputPath)
j.dexJarFile = dexJarFile
- installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, apexRootRelativePathToJavaLib(j.BaseModuleName()))
+ installPath := android.PathForModuleInPartitionInstall(ctx, "apex", ai.ApexVariationName, ApexRootRelativePathToJavaLib(j.BaseModuleName()))
j.dexJarInstallFile = installPath
- j.dexpreopter.installPath = j.dexpreopter.getInstallPath(ctx, installPath)
+ j.dexpreopter.installPath = j.dexpreopter.getInstallPath(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), installPath)
setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
@@ -2221,8 +2292,6 @@
j.dexpreopter.inputProfilePathOnHost = profilePath
}
- j.dexpreopt(ctx, dexOutputPath)
-
// Initialize the hiddenapi structure.
j.initHiddenAPI(ctx, dexJarFile, outputFile, j.dexProperties.Uncompress_dex)
} else {
@@ -2243,7 +2312,7 @@
// Dex compilation
j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
- ctx, android.PathForModuleInstall(ctx, "framework", jarName))
+ ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), android.PathForModuleInstall(ctx, "framework", jarName))
setUncompressDex(ctx, &j.dexpreopter, &j.dexer)
j.dexpreopter.uncompressedDex = *j.dexProperties.Uncompress_dex
@@ -2272,7 +2341,7 @@
}
}
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
+ android.SetProvider(ctx, JavaInfoProvider, JavaInfo{
HeaderJars: android.PathsIfNonNil(j.combinedClasspathFile),
TransitiveLibsHeaderJars: j.transitiveLibsHeaderJars,
TransitiveStaticLibsHeaderJars: j.transitiveStaticLibsHeaderJars,
@@ -2326,7 +2395,10 @@
return android.Paths{j.combinedClasspathFile}
}
-func (j *Import) DexJarBuildPath() OptionalDexJarPath {
+func (j *Import) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
+ if j.dexJarFileErr != nil {
+ ctx.ModuleErrorf(j.dexJarFileErr.Error())
+ }
return j.dexJarFile
}
@@ -2367,7 +2439,7 @@
// java_sdk_library_import with the specified base module name requires to be exported from a
// prebuilt_apex/apex_set.
func requiredFilesFromPrebuiltApexForImport(name string, d *dexpreopter) []string {
- dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(name)
+ dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(name)
// Add the dex implementation jar to the set of exported files.
files := []string{
dexJarFileApexRootRelative,
@@ -2378,9 +2450,9 @@
return files
}
-// apexRootRelativePathToJavaLib returns the path, relative to the root of the apex's contents, for
+// ApexRootRelativePathToJavaLib returns the path, relative to the root of the apex's contents, for
// the java library with the specified name.
-func apexRootRelativePathToJavaLib(name string) string {
+func ApexRootRelativePathToJavaLib(name string) string {
return filepath.Join("javalib", name+".jar")
}
@@ -2391,6 +2463,10 @@
return requiredFilesFromPrebuiltApexForImport(name, &j.dexpreopter)
}
+func (j *Import) UseProfileGuidedDexpreopt() bool {
+ return proptools.Bool(j.importDexpreoptProperties.Dex_preopt.Profile_guided)
+}
+
// Add compile time check for interface implementation
var _ android.IDEInfo = (*Import)(nil)
var _ android.IDECustomizedModuleName = (*Import)(nil)
@@ -2438,7 +2514,6 @@
android.InitPrebuiltModule(module, &module.properties.Jars)
android.InitApexModule(module)
- android.InitBazelModule(module)
InitJavaModule(module, android.HostAndDeviceSupported)
return module
}
@@ -2455,7 +2530,6 @@
android.InitPrebuiltModule(module, &module.properties.Jars)
android.InitApexModule(module)
- android.InitBazelModule(module)
InitJavaModule(module, android.HostSupported)
return module
}
@@ -2524,14 +2598,14 @@
ctx.PropertyErrorf("jars", "exactly one jar must be provided")
}
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if !apexInfo.IsForPlatform() {
j.hideApexVariantFromMake = true
}
j.dexpreopter.installPath = j.dexpreopter.getInstallPath(
- ctx, android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
- j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &j.dexpreopter)
+ ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), android.PathForModuleInstall(ctx, "framework", j.Stem()+".jar"))
+ j.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &j.dexpreopter)
inputJar := ctx.ExpandSource(j.properties.Jars[0], "jars")
dexOutputFile := android.PathForModuleOut(ctx, ctx.ModuleName()+".jar")
@@ -2570,7 +2644,7 @@
j.dexJarFile = makeDexJarPathFromPath(dexOutputFile)
- j.dexpreopt(ctx, dexOutputFile)
+ j.dexpreopt(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), dexOutputFile)
if apexInfo.IsForPlatform() {
ctx.InstallFile(android.PathForModuleInstall(ctx, "framework"),
@@ -2578,7 +2652,7 @@
}
}
-func (j *DexImport) DexJarBuildPath() OptionalDexJarPath {
+func (j *DexImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
return j.dexJarFile
}
@@ -2671,6 +2745,8 @@
&LintProperties{},
&appTestHelperAppProperties{},
&JavaApiLibraryProperties{},
+ &bootclasspathFragmentProperties{},
+ &SourceOnlyBootclasspathProperties{},
)
android.InitDefaultsModule(module)
@@ -2746,678 +2822,36 @@
// from its CLC should be added to the current CLC.
if sdkLib != nil {
clcMap.AddContext(ctx, dexpreopt.AnySdkVersion, *sdkLib, false,
- dep.DexJarBuildPath().PathOrNil(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
+ dep.DexJarBuildPath(ctx).PathOrNil(), dep.DexJarInstallPath(), dep.ClassLoaderContexts())
} else {
clcMap.AddContextMap(dep.ClassLoaderContexts(), depName)
}
}
-type javaResourcesAttributes struct {
- Resources bazel.LabelListAttribute
- Resource_strip_prefix *string
- Additional_resources bazel.LabelListAttribute
+type JavaApiContributionImport struct {
+ JavaApiContribution
+
+ prebuilt android.Prebuilt
}
-func (m *Library) getResourceFilegroupStripPrefix(ctx android.TopDownMutatorContext, resourceFilegroup string) (*string, bool) {
- if otherM, ok := ctx.ModuleFromName(resourceFilegroup); ok {
- if fg, isFilegroup := otherM.(android.FileGroupPath); isFilegroup {
- return proptools.StringPtr(filepath.Join(ctx.OtherModuleDir(otherM), fg.GetPath(ctx))), true
- }
- }
- return proptools.StringPtr(""), false
+func ApiContributionImportFactory() android.Module {
+ module := &JavaApiContributionImport{}
+ android.InitAndroidModule(module)
+ android.InitDefaultableModule(module)
+ android.InitPrebuiltModule(module, &[]string{""})
+ module.AddProperties(&module.properties)
+ module.AddProperties(&module.sdkLibraryComponentProperties)
+ return module
}
-func (m *Library) convertJavaResourcesAttributes(ctx android.TopDownMutatorContext) *javaResourcesAttributes {
- var resources bazel.LabelList
- var resourceStripPrefix *string
-
- additionalJavaResourcesMap := make(map[string]*javaResourcesAttributes)
-
- if m.properties.Java_resources != nil {
- for _, res := range m.properties.Java_resources {
- if prefix, isFilegroup := m.getResourceFilegroupStripPrefix(ctx, res); isFilegroup {
- otherM, _ := ctx.ModuleFromName(res)
- resourcesTargetName := ctx.ModuleName() + "_filegroup_resources_" + otherM.Name()
- additionalJavaResourcesMap[resourcesTargetName] = &javaResourcesAttributes{
- Resources: bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, []string{res})),
- Resource_strip_prefix: prefix,
- }
- } else {
- resources.Append(android.BazelLabelForModuleSrc(ctx, []string{res}))
- }
- }
-
- if !resources.IsEmpty() {
- resourceStripPrefix = proptools.StringPtr(ctx.ModuleDir())
- }
- }
-
- //TODO(b/179889880) handle case where glob includes files outside package
- resDeps := ResourceDirsToFiles(
- ctx,
- m.properties.Java_resource_dirs,
- m.properties.Exclude_java_resource_dirs,
- m.properties.Exclude_java_resources,
- )
-
- for _, resDep := range resDeps {
- dir, files := resDep.dir, resDep.files
-
- // Bazel includes the relative path from the WORKSPACE root when placing the resource
- // inside the JAR file, so we need to remove that prefix
- prefix := proptools.StringPtr(dir.String())
- resourcesTargetName := ctx.ModuleName() + "_resource_dir_" + dir.String()
- additionalJavaResourcesMap[resourcesTargetName] = &javaResourcesAttributes{
- Resources: bazel.MakeLabelListAttribute(bazel.MakeLabelList(android.RootToModuleRelativePaths(ctx, files))),
- Resource_strip_prefix: prefix,
- }
- }
-
- var additionalResourceLabels bazel.LabelList
- if len(additionalJavaResourcesMap) > 0 {
- var additionalResources []string
- for resName, _ := range additionalJavaResourcesMap {
- additionalResources = append(additionalResources, resName)
- }
- sort.Strings(additionalResources)
-
- for i, resName := range additionalResources {
- resAttr := additionalJavaResourcesMap[resName]
- if resourceStripPrefix == nil && i == 0 {
- resourceStripPrefix = resAttr.Resource_strip_prefix
- resources = resAttr.Resources.Value
- } else if !resAttr.Resources.IsEmpty() {
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "java_resources",
- Bzl_load_location: "//build/bazel/rules/java:java_resources.bzl",
- },
- android.CommonAttributes{Name: resName},
- resAttr,
- )
- additionalResourceLabels.Append(android.BazelLabelForModuleSrc(ctx, []string{resName}))
- }
- }
-
- }
-
- return &javaResourcesAttributes{
- Resources: bazel.MakeLabelListAttribute(resources),
- Resource_strip_prefix: resourceStripPrefix,
- Additional_resources: bazel.MakeLabelListAttribute(additionalResourceLabels),
- }
+func (module *JavaApiContributionImport) Prebuilt() *android.Prebuilt {
+ return &module.prebuilt
}
-type javaCommonAttributes struct {
- *javaResourcesAttributes
- *kotlinAttributes
- Srcs bazel.LabelListAttribute
- Plugins bazel.LabelListAttribute
- Javacopts bazel.StringListAttribute
- Sdk_version bazel.StringAttribute
- Java_version bazel.StringAttribute
- Errorprone_force_enable bazel.BoolAttribute
+func (module *JavaApiContributionImport) Name() string {
+ return module.prebuilt.Name(module.ModuleBase.Name())
}
-type javaDependencyLabels struct {
- // Dependencies which DO NOT contribute to the API visible to upstream dependencies.
- Deps bazel.LabelListAttribute
- // Dependencies which DO contribute to the API visible to upstream dependencies.
- StaticDeps bazel.LabelListAttribute
-}
-
-type eventLogTagsAttributes struct {
- Srcs bazel.LabelListAttribute
-}
-
-type aidlLibraryAttributes struct {
- Srcs bazel.LabelListAttribute
- Tags bazel.StringListAttribute
-}
-
-type javaAidlLibraryAttributes struct {
- Deps bazel.LabelListAttribute
- Tags bazel.StringListAttribute
-}
-
-// bp2BuildJavaInfo has information needed for the conversion of java*_modules
-// that is needed bor Bp2Build conversion but that requires different handling
-// depending on the module type.
-type bp2BuildJavaInfo struct {
- // separates dependencies into dynamic dependencies and static dependencies.
- DepLabels *javaDependencyLabels
- hasKotlin bool
-}
-
-func javaXsdTargetName(xsd android.XsdConfigBp2buildTargets) string {
- return xsd.JavaBp2buildTargetName()
-}
-
-// convertLibraryAttrsBp2Build returns a javaCommonAttributes struct with
-// converted attributes shared across java_* modules and a bp2BuildJavaInfo struct
-// which has other non-attribute information needed for bp2build conversion
-// that needs different handling depending on the module types, and thus needs
-// to be returned to the calling function.
-func (m *Library) convertLibraryAttrsBp2Build(ctx android.TopDownMutatorContext) (*javaCommonAttributes, *bp2BuildJavaInfo, bool) {
- var srcs bazel.LabelListAttribute
- var deps bazel.LabelListAttribute
- var staticDeps bazel.LabelListAttribute
-
- if proptools.String(m.deviceProperties.Sdk_version) == "" && m.DeviceSupported() {
- // TODO(b/297356704): handle platform apis in bp2build
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "sdk_version unset")
- return &javaCommonAttributes{}, &bp2BuildJavaInfo{}, false
- } else if proptools.String(m.deviceProperties.Sdk_version) == "core_platform" {
- // TODO(b/297356582): handle core_platform in bp2build
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "sdk_version core_platform")
- return &javaCommonAttributes{}, &bp2BuildJavaInfo{}, false
- }
-
- archVariantProps := m.GetArchVariantProperties(ctx, &CommonProperties{})
- for axis, configToProps := range archVariantProps {
- for config, _props := range configToProps {
- if archProps, ok := _props.(*CommonProperties); ok {
- archSrcs := android.BazelLabelForModuleSrcExcludes(ctx, archProps.Srcs, archProps.Exclude_srcs)
- srcs.SetSelectValue(axis, config, archSrcs)
- if archProps.Jarjar_rules != nil {
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_PROPERTY_UNSUPPORTED, "jarjar_rules")
- return &javaCommonAttributes{}, &bp2BuildJavaInfo{}, false
- }
- }
- }
- }
- srcs.ResolveExcludes()
-
- javaSrcPartition := "java"
- protoSrcPartition := "proto"
- xsdSrcPartition := "xsd"
- logtagSrcPartition := "logtag"
- aidlSrcPartition := "aidl"
- kotlinPartition := "kotlin"
- srcPartitions := bazel.PartitionLabelListAttribute(ctx, &srcs, bazel.LabelPartitions{
- javaSrcPartition: bazel.LabelPartition{Extensions: []string{".java"}, Keep_remainder: true},
- logtagSrcPartition: bazel.LabelPartition{Extensions: []string{".logtags", ".logtag"}},
- protoSrcPartition: android.ProtoSrcLabelPartition,
- aidlSrcPartition: android.AidlSrcLabelPartition,
- xsdSrcPartition: bazel.LabelPartition{LabelMapper: android.XsdLabelMapper(javaXsdTargetName)},
- kotlinPartition: bazel.LabelPartition{Extensions: []string{".kt"}},
- })
-
- javaSrcs := srcPartitions[javaSrcPartition]
- kotlinSrcs := srcPartitions[kotlinPartition]
- javaSrcs.Append(kotlinSrcs)
-
- staticDeps.Append(srcPartitions[xsdSrcPartition])
-
- if !srcPartitions[logtagSrcPartition].IsEmpty() {
- logtagsLibName := m.Name() + "_logtags"
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "event_log_tags",
- Bzl_load_location: "//build/bazel/rules/java:event_log_tags.bzl",
- },
- android.CommonAttributes{Name: logtagsLibName},
- &eventLogTagsAttributes{
- Srcs: srcPartitions[logtagSrcPartition],
- },
- )
-
- logtagsSrcs := bazel.MakeLabelList([]bazel.Label{{Label: ":" + logtagsLibName}})
- javaSrcs.Append(bazel.MakeLabelListAttribute(logtagsSrcs))
- }
-
- if !srcPartitions[aidlSrcPartition].IsEmpty() {
- aidlLibs, aidlSrcs := srcPartitions[aidlSrcPartition].Partition(func(src bazel.Label) bool {
- return android.IsConvertedToAidlLibrary(ctx, src.OriginalModuleName)
- })
-
- apexAvailableTags := android.ApexAvailableTagsWithoutTestApexes(ctx, ctx.Module())
-
- if !aidlSrcs.IsEmpty() {
- aidlLibName := m.Name() + "_aidl_library"
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "aidl_library",
- Bzl_load_location: "//build/bazel/rules/aidl:aidl_library.bzl",
- },
- android.CommonAttributes{Name: aidlLibName},
- &aidlLibraryAttributes{
- Srcs: aidlSrcs,
- Tags: apexAvailableTags,
- },
- )
- aidlLibs.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + aidlLibName}})
- }
-
- javaAidlLibName := m.Name() + "_java_aidl_library"
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "java_aidl_library",
- Bzl_load_location: "//build/bazel/rules/java:java_aidl_library.bzl",
- },
- android.CommonAttributes{Name: javaAidlLibName},
- &javaAidlLibraryAttributes{
- Deps: aidlLibs,
- Tags: apexAvailableTags,
- },
- )
-
- staticDeps.Append(bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + javaAidlLibName}))
- }
-
- var javacopts bazel.StringListAttribute //[]string
- plugins := bazel.MakeLabelListAttribute(
- android.BazelLabelForModuleDeps(ctx, m.properties.Plugins),
- )
- if m.properties.Javacflags != nil {
- javacopts = bazel.MakeStringListAttribute(m.properties.Javacflags)
- }
-
- epEnabled := m.properties.Errorprone.Enabled
- epJavacflags := m.properties.Errorprone.Javacflags
- var errorproneForceEnable bazel.BoolAttribute
- if epEnabled == nil {
- //TODO(b/227504307) add configuration that depends on RUN_ERROR_PRONE environment variable
- } else if *epEnabled {
- plugins.Append(bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, m.properties.Errorprone.Extra_check_modules)))
- javacopts.Append(bazel.MakeStringListAttribute(epJavacflags))
- errorproneForceEnable.Value = epEnabled
- } else {
- javacopts.Append(bazel.MakeStringListAttribute([]string{"-XepDisableAllChecks"}))
- }
-
- commonAttrs := &javaCommonAttributes{
- Srcs: javaSrcs,
- javaResourcesAttributes: m.convertJavaResourcesAttributes(ctx),
- Plugins: plugins,
- Javacopts: javacopts,
- Java_version: bazel.StringAttribute{Value: m.properties.Java_version},
- Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
- Errorprone_force_enable: errorproneForceEnable,
- }
-
- for axis, configToProps := range archVariantProps {
- for config, _props := range configToProps {
- if archProps, ok := _props.(*CommonProperties); ok {
- var libLabels []bazel.Label
- for _, d := range archProps.Libs {
- neverlinkLabel := android.BazelLabelForModuleDepSingle(ctx, d)
- neverlinkLabel.Label = neverlinkLabel.Label + "-neverlink"
- libLabels = append(libLabels, neverlinkLabel)
- }
- deps.SetSelectValue(axis, config, bazel.MakeLabelList(libLabels))
- }
- }
- }
-
- protoDepLabel := bp2buildProto(ctx, &m.Module, srcPartitions[protoSrcPartition])
- // Soong does not differentiate between a java_library and the Bazel equivalent of
- // a java_proto_library + proto_library pair. Instead, in Soong proto sources are
- // listed directly in the srcs of a java_library, and the classes produced
- // by protoc are included directly in the resulting JAR. Thus upstream dependencies
- // that depend on a java_library with proto sources can link directly to the protobuf API,
- // and so this should be a static dependency.
- if protoDepLabel != nil {
- staticDeps.Append(bazel.MakeSingleLabelListAttribute(*protoDepLabel))
- }
-
- depLabels := &javaDependencyLabels{}
- depLabels.Deps = deps
-
- for axis, configToProps := range archVariantProps {
- for config, _props := range configToProps {
- if archProps, ok := _props.(*CommonProperties); ok {
- archStaticLibs := android.BazelLabelForModuleDeps(
- ctx,
- android.LastUniqueStrings(android.CopyOf(archProps.Static_libs)))
- depLabels.StaticDeps.SetSelectValue(axis, config, archStaticLibs)
- }
- }
- }
- depLabels.StaticDeps.Append(staticDeps)
-
- hasKotlin := !kotlinSrcs.IsEmpty()
- commonAttrs.kotlinAttributes = &kotlinAttributes{
- Kotlincflags: &m.properties.Kotlincflags,
- }
- if len(m.properties.Common_srcs) != 0 {
- hasKotlin = true
- commonAttrs.kotlinAttributes.Common_srcs = bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Common_srcs))
- }
-
- bp2BuildInfo := &bp2BuildJavaInfo{
- DepLabels: depLabels,
- hasKotlin: hasKotlin,
- }
-
- return commonAttrs, bp2BuildInfo, true
-}
-
-type javaLibraryAttributes struct {
- *javaCommonAttributes
- Deps bazel.LabelListAttribute
- Exports bazel.LabelListAttribute
- Neverlink bazel.BoolAttribute
-}
-
-type kotlinAttributes struct {
- Common_srcs bazel.LabelListAttribute
- Kotlincflags *[]string
-}
-
-func ktJvmLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties {
- return bazel.BazelTargetModuleProperties{
- Rule_class: "kt_jvm_library",
- Bzl_load_location: "//build/bazel/rules/kotlin:kt_jvm_library.bzl",
- }
-}
-
-func javaLibraryBazelTargetModuleProperties() bazel.BazelTargetModuleProperties {
- return bazel.BazelTargetModuleProperties{
- Rule_class: "java_library",
- Bzl_load_location: "//build/bazel/rules/java:library.bzl",
- }
-}
-
-func javaLibraryBp2Build(ctx android.TopDownMutatorContext, m *Library) {
- commonAttrs, bp2BuildInfo, supported := m.convertLibraryAttrsBp2Build(ctx)
- if !supported {
- return
- }
- depLabels := bp2BuildInfo.DepLabels
-
- deps := depLabels.Deps
- if !commonAttrs.Srcs.IsEmpty() {
- deps.Append(depLabels.StaticDeps) // we should only append these if there are sources to use them
- } else if !deps.IsEmpty() {
- ctx.ModuleErrorf("Module has direct dependencies but no sources. Bazel will not allow this.")
- }
- var props bazel.BazelTargetModuleProperties
- attrs := &javaLibraryAttributes{
- javaCommonAttributes: commonAttrs,
- Deps: deps,
- Exports: depLabels.StaticDeps,
- }
- name := m.Name()
-
- if !bp2BuildInfo.hasKotlin {
- props = javaLibraryBazelTargetModuleProperties()
- } else {
- props = ktJvmLibraryBazelTargetModuleProperties()
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
- neverlinkProp := true
- neverLinkAttrs := &javaLibraryAttributes{
- Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
- Neverlink: bazel.BoolAttribute{Value: &neverlinkProp},
- javaCommonAttributes: &javaCommonAttributes{
- Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
- Java_version: bazel.StringAttribute{Value: m.properties.Java_version},
- },
- }
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name + "-neverlink"}, neverLinkAttrs)
-
-}
-
-type javaBinaryHostAttributes struct {
- *javaCommonAttributes
- Deps bazel.LabelListAttribute
- Runtime_deps bazel.LabelListAttribute
- Main_class string
- Jvm_flags bazel.StringListAttribute
-}
-
-// JavaBinaryHostBp2Build is for java_binary_host bp2build.
-func javaBinaryHostBp2Build(ctx android.TopDownMutatorContext, m *Binary) {
- commonAttrs, bp2BuildInfo, supported := m.convertLibraryAttrsBp2Build(ctx)
- if !supported {
- return
- }
- depLabels := bp2BuildInfo.DepLabels
-
- deps := depLabels.Deps
- deps.Append(depLabels.StaticDeps)
- if m.binaryProperties.Jni_libs != nil {
- deps.Append(bazel.MakeLabelListAttribute(android.BazelLabelForModuleDeps(ctx, m.binaryProperties.Jni_libs)))
- }
-
- var runtimeDeps bazel.LabelListAttribute
- if commonAttrs.Srcs.IsEmpty() {
- // if there are no sources, then the dependencies can only be used at runtime
- runtimeDeps = deps
- deps = bazel.LabelListAttribute{}
- }
-
- mainClass := ""
- if m.binaryProperties.Main_class != nil {
- mainClass = *m.binaryProperties.Main_class
- }
- if m.properties.Manifest != nil {
- mainClassInManifest, err := android.GetMainClassInManifest(ctx.Config(), android.PathForModuleSrc(ctx, *m.properties.Manifest).String())
- if err != nil {
- return
- }
- mainClass = mainClassInManifest
- }
-
- // Attribute jvm_flags
- var jvmFlags bazel.StringListAttribute
- if m.binaryProperties.Jni_libs != nil {
- jniLibPackages := []string{}
- for _, jniLib := range m.binaryProperties.Jni_libs {
- if jniLibModule, exists := ctx.ModuleFromName(jniLib); exists {
- otherDir := ctx.OtherModuleDir(jniLibModule)
- jniLibPackages = append(jniLibPackages, filepath.Join(otherDir, jniLib))
- }
- }
- jniLibPaths := []string{}
- for _, jniLibPackage := range jniLibPackages {
- // See cs/f:.*/third_party/bazel/.*java_stub_template.txt for the use of RUNPATH
- jniLibPaths = append(jniLibPaths, "$${RUNPATH}"+jniLibPackage)
- }
- jvmFlags = bazel.MakeStringListAttribute([]string{"-Djava.library.path=" + strings.Join(jniLibPaths, ":")})
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "java_binary",
- Bzl_load_location: "@rules_java//java:defs.bzl",
- }
- binAttrs := &javaBinaryHostAttributes{
- Runtime_deps: runtimeDeps,
- Main_class: mainClass,
- Jvm_flags: jvmFlags,
- }
-
- if commonAttrs.Srcs.IsEmpty() {
- binAttrs.javaCommonAttributes = commonAttrs
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, binAttrs)
- return
- }
-
- libInfo := libraryCreationInfo{
- deps: deps,
- attrs: commonAttrs,
- baseName: m.Name(),
- hasKotlin: bp2BuildInfo.hasKotlin,
- }
- libName := createLibraryTarget(ctx, libInfo)
- binAttrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}})
-
- // Create the BazelTargetModule.
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, binAttrs)
-}
-
-type javaTestHostAttributes struct {
- *javaCommonAttributes
- Srcs bazel.LabelListAttribute
- Deps bazel.LabelListAttribute
- Runtime_deps bazel.LabelListAttribute
-}
-
-// javaTestHostBp2Build is for java_test_host bp2build.
-func javaTestHostBp2Build(ctx android.TopDownMutatorContext, m *TestHost) {
- commonAttrs, bp2BuildInfo, supported := m.convertLibraryAttrsBp2Build(ctx)
- if !supported {
- return
- }
- depLabels := bp2BuildInfo.DepLabels
-
- deps := depLabels.Deps
- deps.Append(depLabels.StaticDeps)
-
- var runtimeDeps bazel.LabelListAttribute
- attrs := &javaTestHostAttributes{
- Runtime_deps: runtimeDeps,
- }
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "java_test",
- Bzl_load_location: "//build/bazel/rules/java:test.bzl",
- }
-
- if commonAttrs.Srcs.IsEmpty() {
- // if there are no sources, then the dependencies can only be used at runtime
- attrs.Runtime_deps = deps
- attrs.javaCommonAttributes = commonAttrs
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
- return
- }
-
- libInfo := libraryCreationInfo{
- deps: deps,
- attrs: commonAttrs,
- baseName: m.Name(),
- hasKotlin: bp2BuildInfo.hasKotlin,
- }
- libName := createLibraryTarget(ctx, libInfo)
-
- attrs.Srcs = commonAttrs.Srcs
- attrs.Deps = deps
- attrs.Runtime_deps.Add(&bazel.LabelAttribute{Value: &bazel.Label{Label: ":" + libName}})
- // Create the BazelTargetModule.
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
-}
-
-// libraryCreationInfo encapsulates the info needed to create java_library target from
-// java_binary_host or java_test_host.
-type libraryCreationInfo struct {
- deps bazel.LabelListAttribute
- attrs *javaCommonAttributes
- baseName string
- hasKotlin bool
-}
-
-// helper function that creates java_library target from java_binary_host or java_test_host,
-// and returns the library target name,
-func createLibraryTarget(ctx android.TopDownMutatorContext, libInfo libraryCreationInfo) string {
- libName := libInfo.baseName + "_lib"
- var libProps bazel.BazelTargetModuleProperties
- if libInfo.hasKotlin {
- libProps = ktJvmLibraryBazelTargetModuleProperties()
- } else {
- libProps = javaLibraryBazelTargetModuleProperties()
- }
- libAttrs := &javaLibraryAttributes{
- Deps: libInfo.deps,
- javaCommonAttributes: libInfo.attrs,
- }
-
- ctx.CreateBazelTargetModule(libProps, android.CommonAttributes{Name: libName}, libAttrs)
- return libName
-}
-
-type bazelJavaImportAttributes struct {
- Jars bazel.LabelListAttribute
- Exports bazel.LabelListAttribute
-}
-
-// java_import bp2Build converter.
-func (i *Import) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- var jars bazel.LabelListAttribute
- archVariantProps := i.GetArchVariantProperties(ctx, &ImportProperties{})
- for axis, configToProps := range archVariantProps {
- for config, _props := range configToProps {
- if archProps, ok := _props.(*ImportProperties); ok {
- archJars := android.BazelLabelForModuleSrcExcludes(ctx, archProps.Jars, []string(nil))
- jars.SetSelectValue(axis, config, archJars)
- }
- }
- }
-
- attrs := &bazelJavaImportAttributes{
- Jars: jars,
- }
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "java_import",
- Bzl_load_location: "//build/bazel/rules/java:import.bzl",
- }
-
- name := android.RemoveOptionalPrebuiltPrefix(i.Name())
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: name}, attrs)
-
- neverlink := true
- neverlinkAttrs := &javaLibraryAttributes{
- Neverlink: bazel.BoolAttribute{Value: &neverlink},
- Exports: bazel.MakeSingleLabelListAttribute(bazel.Label{Label: ":" + name}),
- javaCommonAttributes: &javaCommonAttributes{
- Sdk_version: bazel.StringAttribute{Value: proptools.StringPtr("none")},
- },
- }
- ctx.CreateBazelTargetModule(
- javaLibraryBazelTargetModuleProperties(),
- android.CommonAttributes{Name: name + "-neverlink"},
- neverlinkAttrs)
-
-}
-
-var _ android.MixedBuildBuildable = (*Import)(nil)
-
-func (i *Import) getBazelModuleLabel(ctx android.BaseModuleContext) string {
- return android.RemoveOptionalPrebuiltPrefixFromBazelLabel(i.GetBazelLabel(ctx, i))
-}
-
-func (i *Import) ProcessBazelQueryResponse(ctx android.ModuleContext) {
- i.commonBuildActions(ctx)
-
- bazelCtx := ctx.Config().BazelContext
- filePaths, err := bazelCtx.GetOutputFiles(i.getBazelModuleLabel(ctx), android.GetConfigKey(ctx))
- if err != nil {
- ctx.ModuleErrorf(err.Error())
- return
- }
-
- bazelJars := android.Paths{}
- for _, bazelOutputFile := range filePaths {
- bazelJars = append(bazelJars, android.PathForBazelOut(ctx, bazelOutputFile))
- }
-
- jarName := android.RemoveOptionalPrebuiltPrefix(i.Name()) + ".jar"
- outputFile := android.PathForModuleOut(ctx, "bazelCombined", jarName)
- TransformJarsToJar(ctx, outputFile, "combine prebuilt jars", bazelJars,
- android.OptionalPath{}, // manifest
- false, // stripDirEntries
- []string{}, // filesToStrip
- []string{}, // dirsToStrip
- )
- i.combinedClasspathFile = outputFile
-
- ctx.SetProvider(JavaInfoProvider, JavaInfo{
- HeaderJars: android.PathsIfNonNil(i.combinedClasspathFile),
- ImplementationAndResourcesJars: android.PathsIfNonNil(i.combinedClasspathFile),
- ImplementationJars: android.PathsIfNonNil(i.combinedClasspathFile),
- // TODO(b/240308299) include AIDL information from Bazel
- // TODO: aconfig files?
- })
-
- i.maybeInstall(ctx, jarName, outputFile)
-}
-
-func (i *Import) QueueBazelCall(ctx android.BaseModuleContext) {
- bazelCtx := ctx.Config().BazelContext
- bazelCtx.QueueBazelRequest(i.getBazelModuleLabel(ctx), cquery.GetOutputFiles, android.GetConfigKey(ctx))
-}
-
-func (i *Import) IsMixedBuildSupported(ctx android.BaseModuleContext) bool {
- return true
+func (ap *JavaApiContributionImport) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ ap.JavaApiContribution.GenerateAndroidBuildActions(ctx)
}
diff --git a/java/java_test.go b/java/java_test.go
index 27933c3..42301d8 100644
--- a/java/java_test.go
+++ b/java/java_test.go
@@ -24,8 +24,10 @@
"strings"
"testing"
+ "github.com/google/blueprint"
"github.com/google/blueprint/proptools"
+ "android/soong/aconfig"
"android/soong/android"
"android/soong/cc"
"android/soong/dexpreopt"
@@ -47,10 +49,8 @@
cc.PrepareForTestWithCcBuildComponents,
// Include all the default java modules.
PrepareForTestWithDexpreopt,
- PrepareForTestWithOverlayBuildComponents,
- android.FixtureRegisterWithContext(func(ctx android.RegistrationContext) {
- ctx.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
- }),
+ // Include aconfig modules.
+ aconfig.PrepareForTestWithAconfigBuildComponents,
)
func TestMain(m *testing.M) {
@@ -529,6 +529,15 @@
}
}
+// A minimal context object for use with DexJarBuildPath
+type moduleErrorfTestCtx struct {
+}
+
+func (ctx moduleErrorfTestCtx) ModuleErrorf(format string, args ...interface{}) {
+}
+
+var _ android.ModuleErrorfContext = (*moduleErrorfTestCtx)(nil)
+
func TestPrebuilts(t *testing.T) {
ctx, _ := testJava(t, `
java_library {
@@ -596,7 +605,8 @@
t.Errorf("foo classpath %v does not contain %q", javac.Args["classpath"], barJar.String())
}
- barDexJar := barModule.Module().(*Import).DexJarBuildPath()
+ errCtx := moduleErrorfTestCtx{}
+ barDexJar := barModule.Module().(*Import).DexJarBuildPath(errCtx)
if barDexJar.IsSet() {
t.Errorf("bar dex jar build path expected to be set, got %s", barDexJar)
}
@@ -609,7 +619,7 @@
t.Errorf("foo combineJar inputs %v does not contain %q", combineJar.Inputs, bazJar.String())
}
- bazDexJar := bazModule.Module().(*Import).DexJarBuildPath().Path()
+ bazDexJar := bazModule.Module().(*Import).DexJarBuildPath(errCtx).Path()
expectedDexJar := "out/soong/.intermediates/baz/android_common/dex/baz.jar"
android.AssertPathRelativeToTopEquals(t, "baz dex jar build path", expectedDexJar, bazDexJar)
@@ -619,8 +629,6 @@
android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_library", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
entries = android.AndroidMkEntriesForTest(t, ctx, barModule.Module())[0]
android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_import", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
- entries = android.AndroidMkEntriesForTest(t, ctx, ctx.ModuleForTests("sdklib", "android_common").Module())[0]
- android.AssertStringEquals(t, "unexpected LOCAL_SOONG_MODULE_TYPE", "java_sdk_library_import", entries.EntryMap["LOCAL_SOONG_MODULE_TYPE"][0])
}
func assertDeepEquals(t *testing.T, message string, expected interface{}, actual interface{}) {
@@ -1206,7 +1214,7 @@
expected := "java.base=.:out/soong"
checkPatchModuleFlag(t, ctx, "bar", expected)
expected = "java.base=" + strings.Join([]string{
- ".", "out/soong", "dir", "dir2", "nested", defaultModuleToPath("ext"), defaultModuleToPath("framework")}, ":")
+ ".", "out/soong", defaultModuleToPath("ext"), defaultModuleToPath("framework")}, ":")
checkPatchModuleFlag(t, ctx, "baz", expected)
})
}
@@ -1291,43 +1299,6 @@
}
}
-func TestAidlIncludeDirFromConvertedFileGroupWithPathPropInMixedBuilds(t *testing.T) {
- // TODO(b/247782695), TODO(b/242847534) Fix mixed builds for filegroups
- t.Skip("Re-enable once filegroups are corrected for mixed builds")
- bp := `
- filegroup {
- name: "foo_aidl",
- srcs: ["aidl/foo/IFoo.aidl"],
- path: "aidl/foo",
- bazel_module: { label: "//:foo_aidl" },
- }
- java_library {
- name: "foo",
- srcs: [":foo_aidl"],
- }
-`
-
- outBaseDir := "out/bazel/output"
- result := android.GroupFixturePreparers(
- prepareForJavaTest,
- android.PrepareForTestWithFilegroup,
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: outBaseDir,
- LabelToOutputFiles: map[string][]string{
- "//:foo_aidl": []string{"aidl/foo/IFoo.aidl"},
- },
- }
- }),
- ).RunTestWithBp(t, bp)
-
- aidlCommand := result.ModuleForTests("foo", "android_common").Rule("aidl").RuleParams.Command
- expectedAidlFlag := "-I" + outBaseDir + "/execroot/__main__/aidl/foo"
- if !strings.Contains(aidlCommand, expectedAidlFlag) {
- t.Errorf("aidl command %q does not contain %q", aidlCommand, expectedAidlFlag)
- }
-}
-
func TestAidlFlagsArePassedToTheAidlCompiler(t *testing.T) {
ctx, _ := testJava(t, `
java_library {
@@ -1744,85 +1715,6 @@
}
}
-func TestImportMixedBuild(t *testing.T) {
- bp := `
- java_import {
- name: "baz",
- jars: [
- "test1.jar",
- "test2.jar",
- ],
- bazel_module: { label: "//foo/bar:baz" },
- }
- `
-
- ctx := android.GroupFixturePreparers(
- prepareForJavaTest,
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: "outputbase",
- LabelToOutputFiles: map[string][]string{
- "//foo/bar:baz": []string{"test1.jar", "test2.jar"},
- },
- }
- }),
- ).RunTestWithBp(t, bp)
-
- bazMod := ctx.ModuleForTests("baz", "android_common").Module()
- producer := bazMod.(android.OutputFileProducer)
- expectedOutputFiles := []string{".intermediates/baz/android_common/bazelCombined/baz.jar"}
-
- outputFiles, err := producer.OutputFiles("")
- if err != nil {
- t.Errorf("Unexpected error getting java_import outputfiles %s", err)
- }
- actualOutputFiles := android.NormalizePathsForTesting(outputFiles)
- android.AssertDeepEquals(t, "Output files are produced", expectedOutputFiles, actualOutputFiles)
-
- javaInfoProvider := ctx.ModuleProvider(bazMod, JavaInfoProvider)
- javaInfo, ok := javaInfoProvider.(JavaInfo)
- if !ok {
- t.Error("could not get JavaInfo from java_import module")
- }
- android.AssertDeepEquals(t, "Header JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.HeaderJars))
- android.AssertDeepEquals(t, "Implementation/Resources JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationAndResourcesJars))
- android.AssertDeepEquals(t, "Implementation JARs are produced", expectedOutputFiles, android.NormalizePathsForTesting(javaInfo.ImplementationJars))
-}
-
-func TestGenAidlIncludeFlagsForMixedBuilds(t *testing.T) {
- bazelOutputBaseDir := filepath.Join("out", "bazel")
- result := android.GroupFixturePreparers(
- PrepareForIntegrationTestWithJava,
- android.FixtureModifyConfig(func(config android.Config) {
- config.BazelContext = android.MockBazelContext{
- OutputBaseDir: bazelOutputBaseDir,
- }
- }),
- ).RunTest(t)
-
- ctx := &android.TestPathContext{TestResult: result}
-
- srcDirectory := filepath.Join("frameworks", "base")
- srcDirectoryAlreadyIncluded := filepath.Join("frameworks", "base", "core", "java")
- bazelSrcDirectory := android.PathForBazelOut(ctx, srcDirectory)
- bazelSrcDirectoryAlreadyIncluded := android.PathForBazelOut(ctx, srcDirectoryAlreadyIncluded)
- srcs := android.Paths{
- android.PathForTestingWithRel(bazelSrcDirectory.String(), "bazelAidl.aidl"),
- android.PathForTestingWithRel(bazelSrcDirectory.String(), "bazelAidl2.aidl"),
- android.PathForTestingWithRel(bazelSrcDirectoryAlreadyIncluded.String(), "bazelAidlExclude.aidl"),
- android.PathForTestingWithRel(bazelSrcDirectoryAlreadyIncluded.String(), "bazelAidl2Exclude.aidl"),
- }
- dirsAlreadyIncluded := android.Paths{
- android.PathForTesting(srcDirectoryAlreadyIncluded),
- }
-
- expectedFlags := " -Iout/bazel/execroot/__main__/frameworks/base"
- flags := genAidlIncludeFlags(ctx, srcs, dirsAlreadyIncluded)
- if flags != expectedFlags {
- t.Errorf("expected flags to be %q; was %q", expectedFlags, flags)
- }
-}
-
func TestDeviceBinaryWrapperGeneration(t *testing.T) {
// Scenario 1: java_binary has main_class property in its bp
ctx, _ := testJava(t, `
@@ -1847,9 +1739,17 @@
}
func TestJavaApiContributionEmptyApiFile(t *testing.T) {
- testJavaError(t,
+ android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern(
"Error: foo has an empty api file.",
- `java_api_contribution {
+ )).RunTestWithBp(t, `
+ java_api_contribution {
name: "foo",
}
java_api_library {
@@ -1865,14 +1765,29 @@
java_api_contribution {
name: "foo1",
api_file: "current.txt",
+ api_surface: "public",
}
`
provider_bp_b := `java_api_contribution {
name: "foo2",
api_file: "current.txt",
+ api_surface: "public",
}
`
- ctx, _ := testJavaWithFS(t, `
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ },
+ ),
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t, `
java_api_library {
name: "bar1",
api_surface: "public",
@@ -1883,13 +1798,8 @@
name: "bar2",
api_surface: "system",
api_contributions: ["foo1", "foo2"],
- api_files: ["api1/current.txt", "api2/current.txt"]
}
- `,
- map[string][]byte{
- "a/Android.bp": []byte(provider_bp_a),
- "b/Android.bp": []byte(provider_bp_b),
- })
+ `)
testcases := []struct {
moduleName string
@@ -1901,13 +1811,13 @@
},
{
moduleName: "bar2",
- sourceTextFileDirs: []string{"a/current.txt", "b/current.txt", "api1/current.txt", "api2/current.txt"},
+ sourceTextFileDirs: []string{"a/current.txt", "b/current.txt"},
},
}
for _, c := range testcases {
m := ctx.ModuleForTests(c.moduleName, "android_common")
manifest := m.Output("metalava.sbox.textproto")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest)
manifestCommand := sboxProto.Commands[0].GetCommand()
sourceFilesFlag := "--source-files " + strings.Join(c.sourceTextFileDirs, " ")
android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
@@ -1919,27 +1829,46 @@
java_api_contribution {
name: "foo1",
api_file: "current.txt",
+ api_surface: "public",
}
`
provider_bp_b := `
java_api_contribution {
name: "foo2",
api_file: "current.txt",
+ api_surface: "public",
}
`
provider_bp_c := `
java_api_contribution {
name: "foo3",
- api_file: "current.txt",
+ api_file: "system-current.txt",
+ api_surface: "system",
}
`
provider_bp_d := `
java_api_contribution {
name: "foo4",
- api_file: "current.txt",
+ api_file: "system-current.txt",
+ api_surface: "system",
}
`
- ctx, _ := testJavaWithFS(t, `
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ "c/Android.bp": []byte(provider_bp_c),
+ "d/Android.bp": []byte(provider_bp_d),
+ },
+ ),
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t, `
java_defaults {
name: "baz1",
api_surface: "public",
@@ -1969,15 +1898,8 @@
api_surface: "system",
defaults:["baz1", "baz2"],
api_contributions: ["foo4"],
- api_files: ["api1/current.txt", "api2/current.txt"]
}
- `,
- map[string][]byte{
- "a/Android.bp": []byte(provider_bp_a),
- "b/Android.bp": []byte(provider_bp_b),
- "c/Android.bp": []byte(provider_bp_c),
- "d/Android.bp": []byte(provider_bp_d),
- })
+ `)
testcases := []struct {
moduleName string
@@ -1992,14 +1914,15 @@
sourceTextFileDirs: []string{"a/current.txt", "b/current.txt"},
},
{
- moduleName: "bar3",
- sourceTextFileDirs: []string{"c/current.txt", "a/current.txt", "b/current.txt", "d/current.txt", "api1/current.txt", "api2/current.txt"},
+ moduleName: "bar3",
+ // API text files need to be sorted from the narrower api scope to the wider api scope
+ sourceTextFileDirs: []string{"a/current.txt", "b/current.txt", "c/system-current.txt", "d/system-current.txt"},
},
}
for _, c := range testcases {
m := ctx.ModuleForTests(c.moduleName, "android_common")
manifest := m.Output("metalava.sbox.textproto")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest)
manifestCommand := sboxProto.Commands[0].GetCommand()
sourceFilesFlag := "--source-files " + strings.Join(c.sourceTextFileDirs, " ")
android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
@@ -2011,15 +1934,30 @@
java_api_contribution {
name: "foo1",
api_file: "current.txt",
+ api_surface: "public",
}
`
provider_bp_b := `
java_api_contribution {
name: "foo2",
api_file: "current.txt",
+ api_surface: "public",
}
`
- ctx, _ := testJavaWithFS(t, `
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ },
+ ),
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t, `
java_api_library {
name: "bar1",
api_surface: "public",
@@ -2031,11 +1969,7 @@
api_surface: "system",
api_contributions: ["foo1", "foo2"],
}
- `,
- map[string][]byte{
- "a/Android.bp": []byte(provider_bp_a),
- "b/Android.bp": []byte(provider_bp_b),
- })
+ `)
testcases := []struct {
moduleName string
@@ -2064,12 +1998,14 @@
java_api_contribution {
name: "foo1",
api_file: "current.txt",
+ api_surface: "public",
}
`
provider_bp_b := `
java_api_contribution {
name: "foo2",
api_file: "current.txt",
+ api_surface: "public",
}
`
lib_bp_a := `
@@ -2085,7 +2021,24 @@
}
`
- ctx, _ := testJavaWithFS(t, `
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ "c/Android.bp": []byte(lib_bp_a),
+ "c/Lib.java": {},
+ "d/Android.bp": []byte(lib_bp_b),
+ "d/Lib.java": {},
+ },
+ ),
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t, `
java_api_library {
name: "bar1",
api_surface: "public",
@@ -2099,15 +2052,7 @@
api_contributions: ["foo1", "foo2"],
libs: ["lib1", "lib2", "bar1"],
}
- `,
- map[string][]byte{
- "a/Android.bp": []byte(provider_bp_a),
- "b/Android.bp": []byte(provider_bp_b),
- "c/Android.bp": []byte(lib_bp_a),
- "c/Lib.java": {},
- "d/Android.bp": []byte(lib_bp_b),
- "d/Lib.java": {},
- })
+ `)
testcases := []struct {
moduleName string
@@ -2139,12 +2084,14 @@
java_api_contribution {
name: "foo1",
api_file: "current.txt",
+ api_surface: "public",
}
`
provider_bp_b := `
java_api_contribution {
name: "foo2",
api_file: "current.txt",
+ api_surface: "public",
}
`
lib_bp_a := `
@@ -2160,7 +2107,24 @@
}
`
- ctx, _ := testJavaWithFS(t, `
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ "c/Android.bp": []byte(lib_bp_a),
+ "c/Lib.java": {},
+ "d/Android.bp": []byte(lib_bp_b),
+ "d/Lib.java": {},
+ },
+ ),
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t, `
java_api_library {
name: "bar1",
api_surface: "public",
@@ -2174,15 +2138,7 @@
api_contributions: ["foo1", "foo2"],
static_libs: ["lib1", "lib2", "bar1"],
}
- `,
- map[string][]byte{
- "a/Android.bp": []byte(provider_bp_a),
- "b/Android.bp": []byte(provider_bp_b),
- "c/Android.bp": []byte(lib_bp_a),
- "c/Lib.java": {},
- "d/Android.bp": []byte(lib_bp_b),
- "d/Lib.java": {},
- })
+ `)
testcases := []struct {
moduleName string
@@ -2213,12 +2169,14 @@
java_api_contribution {
name: "foo1",
api_file: "current.txt",
+ api_surface: "public",
}
`
provider_bp_b := `
java_api_contribution {
name: "foo2",
api_file: "current.txt",
+ api_surface: "public",
}
`
lib_bp_a := `
@@ -2229,48 +2187,57 @@
}
`
- ctx, _ := testJavaWithFS(t, `
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "a/Android.bp": []byte(provider_bp_a),
+ "b/Android.bp": []byte(provider_bp_b),
+ "c/Android.bp": []byte(lib_bp_a),
+ },
+ ),
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t, `
java_api_library {
name: "bar1",
api_surface: "public",
api_contributions: ["foo1"],
full_api_surface_stub: "lib1",
}
- `,
- map[string][]byte{
- "a/Android.bp": []byte(provider_bp_a),
- "b/Android.bp": []byte(provider_bp_b),
- "c/Android.bp": []byte(lib_bp_a),
- })
+ `)
m := ctx.ModuleForTests("bar1", "android_common")
manifest := m.Output("metalava.sbox.textproto")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, manifest)
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest)
manifestCommand := sboxProto.Commands[0].GetCommand()
android.AssertStringDoesContain(t, "Command expected to contain full_api_surface_stub output jar", manifestCommand, "lib1.jar")
}
-func TestJavaApiLibraryFilegroupInput(t *testing.T) {
- ctx, _ := testJavaWithFS(t, `
- filegroup {
- name: "default_current.txt",
- srcs: ["current.txt"],
+func TestTransitiveSrcFiles(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_library {
+ name: "a",
+ srcs: ["a.java"],
}
-
- java_api_library {
- name: "foo",
- api_files: [":default_current.txt"],
+ java_library {
+ name: "b",
+ srcs: ["b.java"],
}
- `,
- map[string][]byte{
- "current.txt": nil,
- })
-
- m := ctx.ModuleForTests("foo", "android_common")
- outputs := fmt.Sprint(m.AllOutputs())
- if !strings.Contains(outputs, "foo/foo.jar") {
- t.Errorf("Module output does not contain expected jar %s", "foo/foo.jar")
- }
+ java_library {
+ name: "c",
+ srcs: ["c.java"],
+ libs: ["a"],
+ static_libs: ["b"],
+ }
+ `)
+ c := ctx.ModuleForTests("c", "android_common").Module()
+ javaInfo, _ := android.SingletonModuleProvider(ctx, c, JavaInfoProvider)
+ transitiveSrcFiles := android.Paths(javaInfo.TransitiveSrcFiles.ToList())
+ android.AssertArrayString(t, "unexpected jar deps", []string{"b.java", "c.java"}, transitiveSrcFiles.Strings())
}
func TestTradefedOptions(t *testing.T) {
@@ -2388,3 +2355,272 @@
javac := ctx.ModuleForTests("foo", "android_common").MaybeRule("javac")
android.AssertDeepEquals(t, "javac rule", nil, javac.Rule)
}
+
+func TestJavaApiContributionImport(t *testing.T) {
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureMergeEnv(
+ map[string]string{
+ "DISABLE_STUB_VALIDATION": "true",
+ },
+ ),
+ ).RunTestWithBp(t, `
+ java_api_library {
+ name: "foo",
+ api_contributions: ["bar"],
+ }
+ java_api_contribution_import {
+ name: "bar",
+ api_file: "current.txt",
+ api_surface: "public",
+ }
+ `)
+ m := ctx.ModuleForTests("foo", "android_common")
+ manifest := m.Output("metalava.sbox.textproto")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx.TestContext, manifest)
+ manifestCommand := sboxProto.Commands[0].GetCommand()
+ sourceFilesFlag := "--source-files current.txt"
+ android.AssertStringDoesContain(t, "source text files not present", manifestCommand, sourceFilesFlag)
+}
+
+func TestJavaApiLibraryApiFilesSorting(t *testing.T) {
+ ctx, _ := testJava(t, `
+ java_api_library {
+ name: "foo",
+ api_contributions: [
+ "system-server-api-stubs-docs-non-updatable.api.contribution",
+ "test-api-stubs-docs-non-updatable.api.contribution",
+ "system-api-stubs-docs-non-updatable.api.contribution",
+ "module-lib-api-stubs-docs-non-updatable.api.contribution",
+ "api-stubs-docs-non-updatable.api.contribution",
+ ],
+ }
+ `)
+ m := ctx.ModuleForTests("foo", "android_common")
+ manifest := m.Output("metalava.sbox.textproto")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, manifest)
+ manifestCommand := sboxProto.Commands[0].GetCommand()
+
+ // Api files are sorted from the narrowest api scope to the widest api scope.
+ // test api and module lib api surface do not have subset/superset relationship,
+ // but they will never be passed as inputs at the same time.
+ sourceFilesFlag := "--source-files default/java/api/current.txt " +
+ "default/java/api/system-current.txt default/java/api/test-current.txt " +
+ "default/java/api/module-lib-current.txt default/java/api/system-server-current.txt"
+ android.AssertStringDoesContain(t, "source text files not in api scope order", manifestCommand, sourceFilesFlag)
+}
+
+func TestSdkLibraryProvidesSystemModulesToApiLibrary(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.SetApiLibraries([]string{"foo"})
+ }),
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "A.java": nil,
+ },
+ ),
+ ).RunTestWithBp(t, `
+ java_library {
+ name: "bar",
+ srcs: ["a.java"],
+ }
+ java_system_modules {
+ name: "baz",
+ libs: ["bar"],
+ }
+ java_sdk_library {
+ name: "foo",
+ srcs: ["A.java"],
+ system_modules: "baz",
+ }
+ `)
+ m := result.ModuleForTests(apiScopePublic.apiLibraryModuleName("foo"), "android_common")
+ manifest := m.Output("metalava.sbox.textproto")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, manifest)
+ manifestCommand := sboxProto.Commands[0].GetCommand()
+ classPathFlag := "--classpath __SBOX_SANDBOX_DIR__/out/soong/.intermediates/bar/android_common/turbine-combined/bar.jar"
+ android.AssertStringDoesContain(t, "command expected to contain classpath flag", manifestCommand, classPathFlag)
+}
+
+func TestApiLibraryDroidstubsDependency(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.SetApiLibraries([]string{"foo"})
+ }),
+ android.FixtureMergeMockFs(
+ map[string][]byte{
+ "A.java": nil,
+ },
+ ),
+ ).RunTestWithBp(t, `
+ java_api_library {
+ name: "foo",
+ api_contributions: [
+ "api-stubs-docs-non-updatable.api.contribution",
+ ],
+ enable_validation: true,
+ }
+ java_api_library {
+ name: "bar",
+ api_contributions: [
+ "api-stubs-docs-non-updatable.api.contribution",
+ ],
+ enable_validation: false,
+ }
+ `)
+
+ currentApiTimestampPath := "api-stubs-docs-non-updatable/android_common/everything/check_current_api.timestamp"
+ foo := result.ModuleForTests("foo", "android_common").Module().(*ApiLibrary)
+ fooValidationPathsString := strings.Join(foo.validationPaths.Strings(), " ")
+ bar := result.ModuleForTests("bar", "android_common").Module().(*ApiLibrary)
+ barValidationPathsString := strings.Join(bar.validationPaths.Strings(), " ")
+ android.AssertStringDoesContain(t,
+ "Module expected to have validation",
+ fooValidationPathsString,
+ currentApiTimestampPath,
+ )
+ android.AssertStringDoesNotContain(t,
+ "Module expected to not have validation",
+ barValidationPathsString,
+ currentApiTimestampPath,
+ )
+}
+
+func TestDisableFromTextStubForCoverageBuild(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ PrepareForTestWithJacocoInstrumentation,
+ FixtureWithLastReleaseApis("foo"),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.SetApiLibraries([]string{"foo"})
+ config.SetBuildFromTextStub(true)
+ }),
+ android.FixtureModifyEnv(func(env map[string]string) {
+ env["EMMA_INSTRUMENT"] = "true"
+ }),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["A.java"],
+ }
+ `)
+ android.AssertBoolEquals(t, "stub module expected to depend on from-source stub",
+ true, CheckModuleHasDependency(t, result.TestContext,
+ apiScopePublic.stubsLibraryModuleName("foo"), "android_common",
+ apiScopePublic.sourceStubLibraryModuleName("foo")))
+
+ android.AssertBoolEquals(t, "stub module expected to not depend on from-text stub",
+ false, CheckModuleHasDependency(t, result.TestContext,
+ apiScopePublic.stubsLibraryModuleName("foo"), "android_common",
+ apiScopePublic.apiLibraryModuleName("foo")))
+}
+
+func TestMultiplePrebuilts(t *testing.T) {
+ bp := `
+ // an rdep
+ java_library {
+ name: "foo",
+ libs: ["bar"],
+ }
+
+ // multiple variations of dep
+ // source
+ java_library {
+ name: "bar",
+ srcs: ["bar.java"],
+ }
+ // prebuilt "v1"
+ java_import {
+ name: "bar",
+ jars: ["bar.jar"],
+ }
+ // prebuilt "v2"
+ java_import {
+ name: "bar.v2",
+ source_module_name: "bar",
+ jars: ["bar.v1.jar"],
+ }
+
+ // selectors
+ apex_contributions {
+ name: "myapex_contributions",
+ contents: ["%v"],
+ }
+ `
+ hasDep := func(ctx *android.TestResult, m android.Module, wantDep android.Module) bool {
+ t.Helper()
+ var found bool
+ ctx.VisitDirectDeps(m, func(dep blueprint.Module) {
+ if dep == wantDep {
+ found = true
+ }
+ })
+ return found
+ }
+
+ hasFileWithStem := func(m android.TestingModule, stem string) bool {
+ t.Helper()
+ for _, o := range m.AllOutputs() {
+ _, file := filepath.Split(o)
+ if file == stem+".jar" {
+ return true
+ }
+ }
+ return false
+ }
+
+ testCases := []struct {
+ desc string
+ selectedDependencyName string
+ expectedDependencyName string
+ }{
+ {
+ desc: "Source library is selected using apex_contributions",
+ selectedDependencyName: "bar",
+ expectedDependencyName: "bar",
+ },
+ {
+ desc: "Prebuilt library v1 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_bar",
+ expectedDependencyName: "prebuilt_bar",
+ },
+ {
+ desc: "Prebuilt library v2 is selected using apex_contributions",
+ selectedDependencyName: "prebuilt_bar.v2",
+ expectedDependencyName: "prebuilt_bar.v2",
+ },
+ }
+
+ for _, tc := range testCases {
+ ctx := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "myapex_contributions",
+ }
+ }),
+ ).RunTestWithBp(t, fmt.Sprintf(bp, tc.selectedDependencyName))
+
+ // check that rdep gets the correct variation of dep
+ foo := ctx.ModuleForTests("foo", "android_common")
+ expectedDependency := ctx.ModuleForTests(tc.expectedDependencyName, "android_common")
+ android.AssertBoolEquals(t, fmt.Sprintf("expected dependency from %s to %s\n", foo.Module().Name(), tc.expectedDependencyName), true, hasDep(ctx, foo.Module(), expectedDependency.Module()))
+
+ // check that output file of dep is always bar.jar
+ // The filename should be agnostic to source/prebuilt/prebuilt_version
+ android.AssertBoolEquals(t, fmt.Sprintf("could not find bar.jar in outputs of %s. All Outputs %v\n", tc.expectedDependencyName, expectedDependency.AllOutputs()), true, hasFileWithStem(expectedDependency, "bar"))
+
+ // check LOCAL_MODULE of the selected module name
+ // the prebuilt should have the same LOCAL_MODULE when exported to make
+ entries := android.AndroidMkEntriesForTest(t, ctx.TestContext, expectedDependency.Module())[0]
+ android.AssertStringEquals(t, "unexpected LOCAL_MODULE", "bar", entries.EntryMap["LOCAL_MODULE"][0])
+ }
+}
diff --git a/java/jdeps.go b/java/jdeps.go
index 4c8c11c..91f7ce7 100644
--- a/java/jdeps.go
+++ b/java/jdeps.go
@@ -75,7 +75,7 @@
dpInfo.Jarjar_rules = android.FirstUniqueStrings(dpInfo.Jarjar_rules)
dpInfo.Jars = android.FirstUniqueStrings(dpInfo.Jars)
dpInfo.SrcJars = android.FirstUniqueStrings(dpInfo.SrcJars)
- dpInfo.Paths = android.FirstUniqueStrings(dpInfo.Paths)
+ dpInfo.Paths = []string{ctx.ModuleDir(module)}
dpInfo.Static_libs = android.FirstUniqueStrings(dpInfo.Static_libs)
dpInfo.Libs = android.FirstUniqueStrings(dpInfo.Libs)
moduleInfos[name] = dpInfo
@@ -89,8 +89,7 @@
dpInfo.Classes = append(dpInfo.Classes, data.Class)
}
- if ctx.ModuleHasProvider(module, JavaInfoProvider) {
- dep := ctx.ModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ if dep, ok := android.SingletonModuleProvider(ctx, module, JavaInfoProvider); ok {
dpInfo.Installed_paths = append(dpInfo.Installed_paths, dep.ImplementationJars.Strings()...)
}
dpInfo.Classes = android.FirstUniqueStrings(dpInfo.Classes)
diff --git a/java/kotlin.go b/java/kotlin.go
index 3637e2e..aa2db0e 100644
--- a/java/kotlin.go
+++ b/java/kotlin.go
@@ -145,7 +145,7 @@
`$kaptProcessorPath ` +
`$kaptProcessor ` +
`-Xbuild-file=$kotlinBuildFile && ` +
- `${config.SoongZipCmd} -jar -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` +
+ `${config.SoongZipCmd} -jar -write_if_changed -o $out -C $kaptDir/stubs -D $kaptDir/stubs && ` +
`rm -rf "$srcJarDir"`,
CommandDeps: []string{
"${config.KotlincCmd}",
@@ -157,6 +157,7 @@
},
Rspfile: "$out.rsp",
RspfileContent: `$in`,
+ Restat: true,
},
"kotlincFlags", "encodedJavacFlags", "kaptProcessorPath", "kaptProcessor",
"classpath", "srcJars", "commonSrcFilesArg", "srcJarDir", "kaptDir", "kotlinJvmTarget",
diff --git a/java/legacy_core_platform_api_usage.go b/java/legacy_core_platform_api_usage.go
index 6cb549e..4be7d04 100644
--- a/java/legacy_core_platform_api_usage.go
+++ b/java/legacy_core_platform_api_usage.go
@@ -28,6 +28,7 @@
"FloralClocks",
"framework-jobscheduler",
"framework-minus-apex",
+ "framework-minus-apex-headers",
"framework-minus-apex-intdefs",
"FrameworksCoreTests",
"HelloOslo",
diff --git a/java/lint.go b/java/lint.go
index f84f1c0..31e7f35 100644
--- a/java/lint.go
+++ b/java/lint.go
@@ -17,7 +17,6 @@
import (
"fmt"
"sort"
- "strconv"
"strings"
"github.com/google/blueprint/proptools"
@@ -56,7 +55,8 @@
// Modules that provide extra lint checks
Extra_check_modules []string
- // Name of the file that lint uses as the baseline. Defaults to "lint-baseline.xml".
+ // The lint baseline file to use. If specified, lint warnings listed in this file will be
+ // suppressed during lint checks.
Baseline_filename *string
// If true, baselining updatability lint checks (e.g. NewApi) is prohibited. Defaults to false.
@@ -66,6 +66,10 @@
// This will be true by default for test module types, false otherwise.
// If soong gets support for testonly, this flag should be replaced with that.
Test *bool
+
+ // Whether to ignore the exit code of Android lint. This is the --exit_code
+ // option. Defaults to false.
+ Suppress_exit_code *bool
}
}
@@ -80,15 +84,16 @@
classes android.Path
extraLintCheckJars android.Paths
library bool
- minSdkVersion int
- targetSdkVersion int
- compileSdkVersion int
+ minSdkVersion android.ApiLevel
+ targetSdkVersion android.ApiLevel
+ compileSdkVersion android.ApiLevel
compileSdkKind android.SdkKind
javaLanguageLevel string
kotlinLanguageLevel string
outputs lintOutputs
properties LintProperties
extraMainlineLintErrors []string
+ compile_data android.Paths
reports android.Paths
@@ -352,33 +357,26 @@
Text(`echo "<?xml version='1.0' encoding='utf-8'?>" &&`).
Text(`echo "<manifest xmlns:android='http://schemas.android.com/apk/res/android'" &&`).
Text(`echo " android:versionCode='1' android:versionName='1' >" &&`).
- Textf(`echo " <uses-sdk android:minSdkVersion='%d' android:targetSdkVersion='%d'/>" &&`,
- l.minSdkVersion, l.targetSdkVersion).
+ Textf(`echo " <uses-sdk android:minSdkVersion='%s' android:targetSdkVersion='%s'/>" &&`,
+ l.minSdkVersion.String(), l.targetSdkVersion.String()).
Text(`echo "</manifest>"`).
Text(") >").Output(manifestPath)
return manifestPath
}
-func (l *linter) getBaselineFilepath(ctx android.ModuleContext) android.OptionalPath {
- var lintBaseline android.OptionalPath
- if lintFilename := proptools.StringDefault(l.properties.Lint.Baseline_filename, "lint-baseline.xml"); lintFilename != "" {
- if String(l.properties.Lint.Baseline_filename) != "" {
- // if manually specified, we require the file to exist
- lintBaseline = android.OptionalPathForPath(android.PathForModuleSrc(ctx, lintFilename))
- } else {
- lintBaseline = android.ExistentPathForSource(ctx, ctx.ModuleDir(), lintFilename)
- }
- }
- return lintBaseline
-}
-
func (l *linter) lint(ctx android.ModuleContext) {
if !l.enabled() {
return
}
- if l.minSdkVersion != l.compileSdkVersion {
+ for _, flag := range l.properties.Lint.Flags {
+ if strings.Contains(flag, "--disable") || strings.Contains(flag, "--enable") || strings.Contains(flag, "--check") {
+ ctx.PropertyErrorf("lint.flags", "Don't use --disable, --enable, or --check in the flags field, instead use the dedicated disabled_checks, warning_checks, error_checks, or fatal_checks fields")
+ }
+ }
+
+ if l.minSdkVersion.CompareTo(l.compileSdkVersion) == -1 {
l.extraMainlineLintErrors = append(l.extraMainlineLintErrors, updatabilityChecks...)
// Skip lint warning checks for NewApi warnings for libcore where they come from source
// files that reference the API they are adding (b/208656169).
@@ -408,8 +406,7 @@
extraLintCheckModules := ctx.GetDirectDepsWithTag(extraLintCheckTag)
for _, extraLintCheckModule := range extraLintCheckModules {
- if ctx.OtherModuleHasProvider(extraLintCheckModule, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(extraLintCheckModule, JavaInfoProvider).(JavaInfo)
+ if dep, ok := android.OtherModuleProvider(ctx, extraLintCheckModule, JavaInfoProvider); ok {
l.extraLintCheckJars = append(l.extraLintCheckJars, dep.ImplementationAndResourcesJars...)
} else {
ctx.PropertyErrorf("lint.extra_check_modules",
@@ -444,7 +441,7 @@
srcsList := android.PathForModuleOut(ctx, "lint", "lint-srcs.list")
srcsListRsp := android.PathForModuleOut(ctx, "lint-srcs.list.rsp")
- rule.Command().Text("cp").FlagWithRspFileInputList("", srcsListRsp, l.srcs).Output(srcsList)
+ rule.Command().Text("cp").FlagWithRspFileInputList("", srcsListRsp, l.srcs).Output(srcsList).Implicits(l.compile_data)
lintPaths := l.writeLintProjectXML(ctx, rule, srcsList)
@@ -487,12 +484,13 @@
cmd.BuiltTool("lint").ImplicitTool(ctx.Config().HostJavaToolPath(ctx, "lint.jar")).
Flag("--quiet").
+ Flag("--include-aosp-issues").
FlagWithInput("--project ", lintPaths.projectXML).
FlagWithInput("--config ", lintPaths.configXML).
FlagWithOutput("--html ", html).
FlagWithOutput("--text ", text).
FlagWithOutput("--xml ", xml).
- FlagWithArg("--compile-sdk-version ", strconv.Itoa(l.compileSdkVersion)).
+ FlagWithArg("--compile-sdk-version ", l.compileSdkVersion.String()).
FlagWithArg("--java-language-level ", l.javaLanguageLevel).
FlagWithArg("--kotlin-language-level ", l.kotlinLanguageLevel).
FlagWithArg("--url ", fmt.Sprintf(".=.,%s=out", android.PathForOutput(ctx).String())).
@@ -504,7 +502,8 @@
rule.Temporary(lintPaths.projectXML)
rule.Temporary(lintPaths.configXML)
- if exitCode := ctx.Config().Getenv("ANDROID_LINT_SUPPRESS_EXIT_CODE"); exitCode == "" {
+ suppressExitCode := BoolDefault(l.properties.Lint.Suppress_exit_code, false)
+ if exitCode := ctx.Config().Getenv("ANDROID_LINT_SUPPRESS_EXIT_CODE"); exitCode == "" && !suppressExitCode {
cmd.Flag("--exitcode")
}
@@ -512,9 +511,8 @@
cmd.FlagWithArg("--check ", checkOnly)
}
- lintBaseline := l.getBaselineFilepath(ctx)
- if lintBaseline.Valid() {
- cmd.FlagWithInput("--baseline ", lintBaseline.Path())
+ if l.properties.Lint.Baseline_filename != nil {
+ cmd.FlagWithInput("--baseline ", android.PathForModuleSrc(ctx, *l.properties.Lint.Baseline_filename))
}
cmd.FlagWithOutput("--write-reference-baseline ", referenceBaseline)
@@ -550,6 +548,10 @@
if l.buildModuleReportZip {
l.reports = BuildModuleLintReportZips(ctx, l.LintDepSets())
}
+
+ // Create a per-module phony target to run the lint check.
+ phonyName := ctx.ModuleName() + "-lint"
+ ctx.Phony(phonyName, xml)
}
func BuildModuleLintReportZips(ctx android.ModuleContext, depSets LintDepSets) android.Paths {
@@ -654,7 +656,7 @@
}
if apex, ok := m.(android.ApexModule); ok && apex.NotAvailableForPlatform() {
- apexInfo := ctx.ModuleProvider(m, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.SingletonModuleProvider(ctx, m, android.ApexInfoProvider)
if apexInfo.IsForPlatform() {
// There are stray platform variants of modules in apexes that are not available for
// the platform, and they sometimes can't be built. Don't depend on them.
diff --git a/java/lint_defaults.txt b/java/lint_defaults.txt
index 8494d02..b8ce95c 100644
--- a/java/lint_defaults.txt
+++ b/java/lint_defaults.txt
@@ -122,10 +122,10 @@
--warning_check RemoteViewLayout
--warning_check SupportAnnotationUsage
--warning_check UniqueConstants
-
-# TODO(b/294098365): these checks fail in AOSP, but pass downstream
---warning_check ForegroundServiceType
---warning_check MutableImplicitPendingIntent
+--warning_check UseSdkSuppress
+# TODO(b/303434307) The intent is for this to be set to error severity
+# once existing violations are cleaned up
+--warning_check FlaggedApi
--warning_check ExactAlarm
--warning_check ExpiredTargetSdkVersion
diff --git a/java/lint_test.go b/java/lint_test.go
index ec901aa..751b139 100644
--- a/java/lint_test.go
+++ b/java/lint_test.go
@@ -21,7 +21,7 @@
"android/soong/android"
)
-func TestJavaLint(t *testing.T) {
+func TestJavaLintDoesntUseBaselineImplicitly(t *testing.T) {
ctx, _ := testJavaWithFS(t, `
java_library {
name: "foo",
@@ -39,31 +39,9 @@
foo := ctx.ModuleForTests("foo", "android_common")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
- if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml") {
- t.Error("did not pass --baseline flag")
- }
-}
-
-func TestJavaLintWithoutBaseline(t *testing.T) {
- ctx, _ := testJavaWithFS(t, `
- java_library {
- name: "foo",
- srcs: [
- "a.java",
- "b.java",
- "c.java",
- ],
- min_sdk_version: "29",
- sdk_version: "system_current",
- }
- `, map[string][]byte{})
-
- foo := ctx.ModuleForTests("foo", "android_common")
-
- sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
- if strings.Contains(*sboxProto.Commands[0].Command, "--baseline") {
- t.Error("passed --baseline flag for non existent file")
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, foo.Output("lint.sbox.textproto"))
+ if strings.Contains(*sboxProto.Commands[0].Command, "--baseline lint-baseline.xml") {
+ t.Error("Passed --baseline flag when baseline_filename was not set")
}
}
@@ -108,7 +86,7 @@
foo := ctx.ModuleForTests("foo", "android_common")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, ctx, foo.Output("lint.sbox.textproto"))
if !strings.Contains(*sboxProto.Commands[0].Command, "--baseline mybaseline.xml") {
t.Error("did not use the correct file for baseline")
}
@@ -276,9 +254,28 @@
RunTestWithBp(t, thisBp)
foo := result.ModuleForTests("foo", "android_common")
- sboxProto := android.RuleBuilderSboxProtoForTests(t, foo.Output("lint.sbox.textproto"))
+ sboxProto := android.RuleBuilderSboxProtoForTests(t, result.TestContext, foo.Output("lint.sbox.textproto"))
if !strings.Contains(*sboxProto.Commands[0].Command, "/"+testCase.expected_file) {
t.Error("did not use full api database for case", testCase)
}
}
}
+
+func TestCantControlCheckSeverityWithFlags(t *testing.T) {
+ bp := `
+ java_library {
+ name: "foo",
+ srcs: [
+ "a.java",
+ ],
+ min_sdk_version: "29",
+ sdk_version: "current",
+ lint: {
+ flags: ["--disabled", "NewApi"],
+ },
+ }
+ `
+ PrepareForTestWithJavaDefaultModules.
+ ExtendWithErrorHandler(android.FixtureExpectsOneErrorPattern("Don't use --disable, --enable, or --check in the flags field, instead use the dedicated disabled_checks, warning_checks, error_checks, or fatal_checks fields")).
+ RunTestWithBp(t, bp)
+}
diff --git a/java/platform_bootclasspath.go b/java/platform_bootclasspath.go
index ade7395..4db426e 100644
--- a/java/platform_bootclasspath.go
+++ b/java/platform_bootclasspath.go
@@ -57,6 +57,9 @@
// Path to the monolithic hiddenapi-unsupported.csv file.
hiddenAPIMetadataCSV android.OutputPath
+
+ // Path to a srcjar containing all the transitive sources of the bootclasspath.
+ srcjar android.OutputPath
}
type platformBootclasspathProperties struct {
@@ -95,12 +98,17 @@
return android.Paths{b.hiddenAPIIndexCSV}, nil
case "hiddenapi-metadata.csv":
return android.Paths{b.hiddenAPIMetadataCSV}, nil
+ case ".srcjar":
+ return android.Paths{b.srcjar}, nil
}
return nil, fmt.Errorf("unknown tag %s", tag)
}
func (b *platformBootclasspathModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // Create a dependency on all_apex_contributions to determine the selected mainline module
+ ctx.AddDependency(ctx.Module(), apexContributionsMetadataDepTag, "all_apex_contributions")
+
b.hiddenAPIDepsMutator(ctx)
if !dexpreopt.IsDex2oatNeeded(ctx) {
@@ -125,6 +133,8 @@
func (b *platformBootclasspathModule) BootclasspathDepsMutator(ctx android.BottomUpMutatorContext) {
// Add dependencies on all the ART jars.
global := dexpreopt.GetGlobalConfig(ctx)
+ addDependenciesOntoSelectedBootImageApexes(ctx, "com.android.art")
+ // TODO: b/308174306 - Remove the mechanism of depending on the java_sdk_library(_import) directly
addDependenciesOntoBootImageModules(ctx, global.ArtApexJars, platformBootclasspathArtBootJarDepTag)
// Add dependencies on all the non-updatable jars, which are on the platform or in non-updatable
@@ -133,6 +143,12 @@
// Add dependencies on all the updatable jars, except the ART jars.
apexJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars
+ apexes := []string{}
+ for i := 0; i < apexJars.Len(); i++ {
+ apexes = append(apexes, apexJars.Apex(i))
+ }
+ addDependenciesOntoSelectedBootImageApexes(ctx, android.FirstUniqueStrings(apexes)...)
+ // TODO: b/308174306 - Remove the mechanism of depending on the java_sdk_library(_import) directly
addDependenciesOntoBootImageModules(ctx, apexJars, platformBootclasspathApexBootJarDepTag)
// Add dependencies on all the fragments.
@@ -173,6 +189,18 @@
allModules = append(allModules, apexModules...)
b.configuredModules = allModules
+ var transitiveSrcFiles android.Paths
+ for _, module := range allModules {
+ depInfo, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
+ if depInfo.TransitiveSrcFiles != nil {
+ transitiveSrcFiles = append(transitiveSrcFiles, depInfo.TransitiveSrcFiles.ToList()...)
+ }
+ }
+ jarArgs := resourcePathsToJarArgs(transitiveSrcFiles)
+ jarArgs = append(jarArgs, "-srcjar") // Move srcfiles to the right package
+ b.srcjar = android.PathForModuleOut(ctx, ctx.ModuleName()+"-transitive.srcjar").OutputPath
+ TransformResourcesToJar(ctx, b.srcjar, jarArgs, transitiveSrcFiles)
+
// Gather all the fragments dependencies.
b.fragments = gatherApexModulePairDepsWithTag(ctx, bootclasspathFragmentDepTag)
@@ -185,8 +213,6 @@
bootDexJarByModule := b.generateHiddenAPIBuildActions(ctx, b.configuredModules, b.fragments)
buildRuleForBootJarsPackageCheck(ctx, bootDexJarByModule)
-
- b.copyApexBootJarsForAppsDexpreopt(ctx, apexModules)
}
// Generate classpaths.proto config
@@ -204,7 +230,7 @@
// Include jars from APEXes that don't populate their classpath proto config.
remainingJars := dexpreopt.GetGlobalConfig(ctx).ApexBootJars
for _, fragment := range b.fragments {
- info := ctx.OtherModuleProvider(fragment, ClasspathFragmentProtoContentInfoProvider).(ClasspathFragmentProtoContentInfo)
+ info, _ := android.OtherModuleProvider(ctx, fragment, ClasspathFragmentProtoContentInfoProvider)
if info.ClasspathFragmentProtoGenerated {
remainingJars = remainingJars.RemoveList(info.ClasspathFragmentProtoContents)
}
@@ -226,7 +252,7 @@
func (b *platformBootclasspathModule) checkPlatformModules(ctx android.ModuleContext, modules []android.Module) {
// TODO(satayev): change this check to only allow core-icu4j, all apex jars should not be here.
for _, m := range modules {
- apexInfo := ctx.OtherModuleProvider(m, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.OtherModuleProvider(ctx, m, android.ApexInfoProvider)
fromUpdatableApex := apexInfo.Updatable
if fromUpdatableApex {
// error: this jar is part of an updatable apex
@@ -240,7 +266,7 @@
// checkApexModules ensures that the apex modules supplied are not from the platform.
func (b *platformBootclasspathModule) checkApexModules(ctx android.ModuleContext, modules []android.Module) {
for _, m := range modules {
- apexInfo := ctx.OtherModuleProvider(m, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.OtherModuleProvider(ctx, m, android.ApexInfoProvider)
fromUpdatableApex := apexInfo.Updatable
if fromUpdatableApex {
// ok: this jar is part of an updatable apex
@@ -374,7 +400,7 @@
monolithicInfo := newMonolithicHiddenAPIInfo(ctx, temporaryInput.FlagFilesByCategory, classpathElements)
// Store the information for testing.
- ctx.SetProvider(MonolithicHiddenAPIInfoProvider, monolithicInfo)
+ android.SetProvider(ctx, MonolithicHiddenAPIInfoProvider, monolithicInfo)
return monolithicInfo
}
@@ -398,10 +424,3 @@
// INTERNAL_PLATFORM_HIDDENAPI_FLAGS is used by Make rules in art/ and cts/.
ctx.Strict("INTERNAL_PLATFORM_HIDDENAPI_FLAGS", b.hiddenAPIFlagsCSV.String())
}
-
-// Copy apex module dex jars to their predefined locations. They will be used for dexpreopt for apps.
-func (b *platformBootclasspathModule) copyApexBootJarsForAppsDexpreopt(ctx android.ModuleContext, apexModules []android.Module) {
- config := GetApexBootConfig(ctx)
- apexBootDexJarsByModule := extractEncodedDexJarsFromModules(ctx, apexModules)
- copyBootJarsToPredefinedLocations(ctx, apexBootDexJarsByModule, config.dexPathsByModule)
-}
diff --git a/java/platform_bootclasspath_test.go b/java/platform_bootclasspath_test.go
index ff2da4b..37ff639 100644
--- a/java/platform_bootclasspath_test.go
+++ b/java/platform_bootclasspath_test.go
@@ -81,6 +81,15 @@
RunTest(t)
})
+ fooSourceSrc := "source/a.java"
+ barSrc := "a.java"
+
+ checkSrcJarInputs := func(t *testing.T, result *android.TestResult, name string, expected []string) {
+ t.Helper()
+ srcjar := result.ModuleForTests(name, "android_common").Output(name + "-transitive.srcjar")
+ android.AssertStringDoesContain(t, "srcjar arg", srcjar.Args["jarArgs"], "-srcjar")
+ android.AssertArrayString(t, "srcjar inputs", expected, srcjar.Implicits.Strings())
+ }
t.Run("source", func(t *testing.T) {
result := android.GroupFixturePreparers(
preparer,
@@ -91,6 +100,10 @@
"platform:foo",
"platform:bar",
})
+ checkSrcJarInputs(t, result, "platform-bootclasspath", []string{
+ fooSourceSrc,
+ barSrc,
+ })
})
t.Run("prebuilt", func(t *testing.T) {
@@ -103,6 +116,10 @@
"platform:prebuilt_foo",
"platform:bar",
})
+ checkSrcJarInputs(t, result, "platform-bootclasspath", []string{
+ // TODO(b/151360309): This should also have the srcs for prebuilt_foo
+ barSrc,
+ })
})
t.Run("source+prebuilt - source preferred", func(t *testing.T) {
@@ -116,6 +133,10 @@
"platform:foo",
"platform:bar",
})
+ checkSrcJarInputs(t, result, "platform-bootclasspath", []string{
+ fooSourceSrc,
+ barSrc,
+ })
})
t.Run("source+prebuilt - prebuilt preferred", func(t *testing.T) {
@@ -129,6 +150,10 @@
"platform:prebuilt_foo",
"platform:bar",
})
+ checkSrcJarInputs(t, result, "platform-bootclasspath", []string{
+ // TODO(b/151360309): This should also have the srcs for prebuilt_foo
+ barSrc,
+ })
})
t.Run("dex import", func(t *testing.T) {
@@ -146,6 +171,10 @@
"platform:prebuilt_foo",
"platform:bar",
})
+ checkSrcJarInputs(t, result, "platform-bootclasspath", []string{
+ // TODO(b/151360309): This should also have the srcs for prebuilt_foo
+ barSrc,
+ })
})
}
diff --git a/java/platform_compat_config.go b/java/platform_compat_config.go
index 1248275..2197304 100644
--- a/java/platform_compat_config.go
+++ b/java/platform_compat_config.go
@@ -19,10 +19,7 @@
"path/filepath"
"android/soong/android"
- "android/soong/bazel"
-
"github.com/google/blueprint"
- "github.com/google/blueprint/proptools"
)
func init() {
@@ -57,7 +54,6 @@
type platformCompatConfig struct {
android.ModuleBase
- android.BazelModuleBase
properties platformCompatConfigProperties
installDirPath android.InstallPath
@@ -126,29 +122,10 @@
}}
}
-type bazelPlatformCompatConfigAttributes struct {
- Src bazel.LabelAttribute
-}
-
-func (p *platformCompatConfig) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "platform_compat_config",
- Bzl_load_location: "//build/bazel/rules/java:platform_compat_config.bzl",
- }
- attr := &bazelPlatformCompatConfigAttributes{
- Src: *bazel.MakeLabelAttribute(
- android.BazelLabelForModuleSrcSingle(ctx, proptools.String(p.properties.Src)).Label),
- }
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: p.Name(),
- }, attr)
-}
-
func PlatformCompatConfigFactory() android.Module {
module := &platformCompatConfig{}
module.AddProperties(&module.properties)
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibCommon)
- android.InitBazelModule(module)
return module
}
diff --git a/java/plugin.go b/java/plugin.go
index 5127298..9c4774a 100644
--- a/java/plugin.go
+++ b/java/plugin.go
@@ -16,7 +16,6 @@
import (
"android/soong/android"
- "android/soong/bazel"
)
func init() {
@@ -35,8 +34,6 @@
InitJavaModule(module, android.HostSupported)
- android.InitBazelModule(module)
-
return module
}
@@ -56,38 +53,3 @@
// parallelism and cause more recompilation for modules that depend on modules that use this plugin.
Generates_api *bool
}
-
-type pluginAttributes struct {
- *javaCommonAttributes
- Deps bazel.LabelListAttribute
- Processor_class *string
-}
-
-// ConvertWithBp2build is used to convert android_app to Bazel.
-func (p *Plugin) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- pluginName := p.Name()
- commonAttrs, bp2BuildInfo, supported := p.convertLibraryAttrsBp2Build(ctx)
- if !supported {
- return
- }
- depLabels := bp2BuildInfo.DepLabels
-
- deps := depLabels.Deps
- deps.Append(depLabels.StaticDeps)
-
- var processorClass *string
- if p.pluginProperties.Processor_class != nil {
- processorClass = p.pluginProperties.Processor_class
- }
-
- attrs := &pluginAttributes{
- javaCommonAttributes: commonAttrs,
- Deps: deps,
- Processor_class: processorClass,
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "java_plugin",
- }
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: pluginName}, attrs)
-}
diff --git a/java/prebuilt_apis.go b/java/prebuilt_apis.go
index 99cb99b..94e9c6c 100644
--- a/java/prebuilt_apis.go
+++ b/java/prebuilt_apis.go
@@ -127,41 +127,13 @@
func prebuiltApiModuleName(mctx android.LoadHookContext, module, scope, version string) string {
return fmt.Sprintf("%s_%s_%s_%s", mctx.ModuleName(), scope, version, module)
}
-
-func hasBazelPrebuilt(module string) bool {
- return module == "android" || module == "core-for-system-modules"
-}
-
-func bazelPrebuiltApiModuleName(module, scope, version string) string {
- bazelModule := module
- switch module {
- case "android":
- bazelModule = "android_jar"
- case "core-for-system-modules":
- bazelModule = "core_jar"
- }
- bazelVersion := version
- if version == "current" {
- bazelVersion = strconv.Itoa(android.FutureApiLevelInt)
- }
- bazelScope := scope
- switch scope {
- case "module-lib":
- bazelScope = "module"
- case "system-server":
- bazelScope = "system_server"
- }
- return fmt.Sprintf("//prebuilts/sdk:%s_%s_%s", bazelScope, bazelVersion, bazelModule)
-}
-
func createImport(mctx android.LoadHookContext, module, scope, version, path, sdkVersion string, compileDex bool) {
props := struct {
- Name *string
- Jars []string
- Sdk_version *string
- Installable *bool
- Compile_dex *bool
- Bazel_module android.BazelModuleProperties
+ Name *string
+ Jars []string
+ Sdk_version *string
+ Installable *bool
+ Compile_dex *bool
}{
Name: proptools.StringPtr(prebuiltApiModuleName(mctx, module, scope, version)),
Jars: []string{path},
@@ -169,10 +141,6 @@
Installable: proptools.BoolPtr(false),
Compile_dex: proptools.BoolPtr(compileDex),
}
- if hasBazelPrebuilt(module) {
- props.Bazel_module = android.BazelModuleProperties{
- Label: proptools.StringPtr(bazelPrebuiltApiModuleName(module, scope, version))}
- }
mctx.CreateModule(ImportFactory, &props)
}
diff --git a/java/proto.go b/java/proto.go
index 2ed7b27..e27ef2c 100644
--- a/java/proto.go
+++ b/java/proto.go
@@ -19,9 +19,6 @@
"strconv"
"android/soong/android"
- "android/soong/bazel"
-
- "github.com/google/blueprint/proptools"
)
const (
@@ -141,64 +138,3 @@
return flags
}
-
-type protoAttributes struct {
- Deps bazel.LabelListAttribute
-
- // A list of proto_library targets that the proto_library in `deps` depends on
- // This list is overestimation.
- // Overestimation is necessary since Soong includes other protos via proto.include_dirs and not
- // a specific .proto file module explicitly.
- Transitive_deps bazel.LabelListAttribute
-
- Sdk_version bazel.StringAttribute
- Java_version bazel.StringAttribute
-}
-
-func bp2buildProto(ctx android.Bp2buildMutatorContext, m *Module, protoSrcs bazel.LabelListAttribute) *bazel.Label {
- protoInfo, ok := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, protoSrcs)
- if !ok {
- return nil
- }
-
- typ := proptools.StringDefault(protoInfo.Type, protoTypeDefault)
- var rule_class string
- suffix := "_java_proto"
- switch typ {
- case "nano":
- suffix += "_nano"
- rule_class = "java_nano_proto_library"
- case "micro":
- suffix += "_micro"
- rule_class = "java_micro_proto_library"
- case "lite":
- suffix += "_lite"
- rule_class = "java_lite_proto_library"
- case "stream":
- suffix += "_stream"
- rule_class = "java_stream_proto_library"
- case "full":
- rule_class = "java_proto_library"
- default:
- ctx.PropertyErrorf("proto.type", "cannot handle conversion at this time: %q", typ)
- }
-
- protoAttrs := &protoAttributes{
- Deps: bazel.MakeLabelListAttribute(protoInfo.Proto_libs),
- Transitive_deps: bazel.MakeLabelListAttribute(protoInfo.Transitive_proto_libs),
- Java_version: bazel.StringAttribute{Value: m.properties.Java_version},
- Sdk_version: bazel.StringAttribute{Value: m.deviceProperties.Sdk_version},
- }
-
- name := m.Name() + suffix
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: rule_class,
- Bzl_load_location: "//build/bazel/rules/java:proto.bzl",
- },
- android.CommonAttributes{Name: name},
- protoAttrs)
-
- return &bazel.Label{Label: ":" + name}
-}
diff --git a/java/resourceshrinker.go b/java/resourceshrinker.go
deleted file mode 100644
index bf1b04d..0000000
--- a/java/resourceshrinker.go
+++ /dev/null
@@ -1,44 +0,0 @@
-// 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 java
-
-import (
- "android/soong/android"
-
- "github.com/google/blueprint"
-)
-
-var shrinkResources = pctx.AndroidStaticRule("shrinkResources",
- blueprint.RuleParams{
- // Note that we suppress stdout to avoid successful log confirmations.
- Command: `${config.ResourceShrinkerCmd} --output $out --input $in --raw_resources $raw_resources >/dev/null`,
- CommandDeps: []string{"${config.ResourceShrinkerCmd}"},
- }, "raw_resources")
-
-func ShrinkResources(ctx android.ModuleContext, apk android.Path, outputFile android.WritablePath) {
- protoFile := android.PathForModuleOut(ctx, apk.Base()+".proto.apk")
- aapt2Convert(ctx, protoFile, apk, "proto")
- strictModeFile := android.PathForSource(ctx, "prebuilts/cmdline-tools/shrinker.xml")
- protoOut := android.PathForModuleOut(ctx, apk.Base()+".proto.out.apk")
- ctx.Build(pctx, android.BuildParams{
- Rule: shrinkResources,
- Input: protoFile,
- Output: protoOut,
- Args: map[string]string{
- "raw_resources": strictModeFile.String(),
- },
- })
- aapt2Convert(ctx, outputFile, protoOut, "binary")
-}
diff --git a/java/resourceshrinker_test.go b/java/resourceshrinker_test.go
deleted file mode 100644
index 3bbf116..0000000
--- a/java/resourceshrinker_test.go
+++ /dev/null
@@ -1,53 +0,0 @@
-// 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 java
-
-import (
- "testing"
-
- "android/soong/android"
-)
-
-func TestShrinkResourcesArgs(t *testing.T) {
- result := android.GroupFixturePreparers(
- PrepareForTestWithJavaDefaultModules,
- ).RunTestWithBp(t, `
- android_app {
- name: "app_shrink",
- platform_apis: true,
- optimize: {
- shrink_resources: true,
- }
- }
-
- android_app {
- name: "app_no_shrink",
- platform_apis: true,
- optimize: {
- shrink_resources: false,
- }
- }
- `)
-
- appShrink := result.ModuleForTests("app_shrink", "android_common")
- appShrinkResources := appShrink.Rule("shrinkResources")
- android.AssertStringDoesContain(t, "expected shrinker.xml in app_shrink resource shrinker flags",
- appShrinkResources.Args["raw_resources"], "shrinker.xml")
-
- appNoShrink := result.ModuleForTests("app_no_shrink", "android_common")
- if appNoShrink.MaybeRule("shrinkResources").Rule != nil {
- t.Errorf("unexpected shrinkResources rule for app_no_shrink")
- }
-}
diff --git a/java/robolectric.go b/java/robolectric.go
index 0041af4..9e8850c 100644
--- a/java/robolectric.go
+++ b/java/robolectric.go
@@ -22,6 +22,7 @@
"android/soong/android"
"android/soong/java/config"
+ "android/soong/testing"
"android/soong/tradefed"
"github.com/google/blueprint/proptools"
@@ -34,7 +35,7 @@
var robolectricDefaultLibs = []string{
"mockito-robolectric-prebuilt",
- "truth-prebuilt",
+ "truth",
// TODO(ccross): this is not needed at link time
"junitxml",
}
@@ -66,7 +67,7 @@
// instead of the one built from source in external/robolectric-shadows.
Robolectric_prebuilt_version *string
- // Use /external/robolectric rather than /external/robolectric-shadows as the version of robolectri
+ // Use /external/robolectric rather than /external/robolectric-shadows as the version of robolectric
// to use. /external/robolectric closely tracks github's master, and will fully replace /external/robolectric-shadows
Upstream *bool
}
@@ -192,7 +193,7 @@
}
handleLibDeps := func(dep android.Module) {
- m := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
+ m, _ := android.OtherModuleProvider(ctx, dep, JavaInfoProvider)
r.libs = append(r.libs, ctx.OtherModuleName(dep))
if !android.InList(ctx.OtherModuleName(dep), config.FrameworkLibraries) {
combinedJarJars = append(combinedJarJars, m.ImplementationAndResourcesJars...)
@@ -225,7 +226,7 @@
}
installPath := android.PathForModuleInstall(ctx, r.BaseModuleName())
- var installDeps android.Paths
+ var installDeps android.InstallPaths
if r.manifest != nil {
r.data = append(r.data, r.manifest)
@@ -253,6 +254,7 @@
}
r.installFile = ctx.InstallFile(installPath, ctx.ModuleName()+".jar", r.combinedJar, installDeps...)
+ android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
func generateRoboTestConfig(ctx android.ModuleContext, outputFile android.WritablePath,
@@ -303,8 +305,7 @@
srcJarDeps := append(android.Paths(nil), instrumentedApp.srcJarDeps...)
for _, m := range ctx.GetDirectDepsWithTag(roboCoverageLibsTag) {
- if ctx.OtherModuleHasProvider(m, JavaInfoProvider) {
- dep := ctx.OtherModuleProvider(m, JavaInfoProvider).(JavaInfo)
+ if dep, ok := android.OtherModuleProvider(ctx, m, JavaInfoProvider); ok {
srcJarArgs = append(srcJarArgs, dep.SrcJarArgs...)
srcJarDeps = append(srcJarDeps, dep.SrcJarDeps...)
}
diff --git a/java/rro.go b/java/rro.go
index 53faca0..3e0f8e9 100644
--- a/java/rro.go
+++ b/java/rro.go
@@ -146,7 +146,13 @@
aaptLinkFlags = append(aaptLinkFlags,
"--rename-overlay-category "+*r.overridableProperties.Category)
}
- r.aapt.buildActions(ctx, r, nil, nil, false, aaptLinkFlags...)
+ r.aapt.buildActions(ctx,
+ aaptBuildActionOptions{
+ sdkContext: r,
+ enforceDefaultTargetSdkVersion: false,
+ extraLinkFlags: aaptLinkFlags,
+ },
+ )
// Sign the built package
_, _, certificates := collectAppDeps(ctx, r, false, false)
diff --git a/java/rro_test.go b/java/rro_test.go
index 8067a47..c4a4d04 100644
--- a/java/rro_test.go
+++ b/java/rro_test.go
@@ -62,7 +62,6 @@
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
- PrepareForTestWithOverlayBuildComponents,
android.FixtureModifyConfig(android.SetKatiEnabledForTests),
fs.AddToFixture(),
).RunTestWithBp(t, bp)
@@ -330,7 +329,6 @@
t.Run(testCase.name, func(t *testing.T) {
result := android.GroupFixturePreparers(
PrepareForTestWithJavaDefaultModules,
- PrepareForTestWithOverlayBuildComponents,
fs.AddToFixture(),
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.ProductResourceOverlays = productResourceOverlays
diff --git a/java/sdk.go b/java/sdk.go
index 7c702c4..81be991 100644
--- a/java/sdk.go
+++ b/java/sdk.go
@@ -17,8 +17,6 @@
import (
"fmt"
"path/filepath"
- "sort"
- "strconv"
"android/soong/android"
"android/soong/java/config"
@@ -27,12 +25,10 @@
)
func init() {
- android.RegisterPreSingletonType("sdk_versions", sdkPreSingletonFactory)
android.RegisterParallelSingletonType("sdk", sdkSingletonFactory)
android.RegisterMakeVarsProvider(pctx, sdkMakeVars)
}
-var sdkVersionsKey = android.NewOnceKey("sdkVersionsKey")
var sdkFrameworkAidlPathKey = android.NewOnceKey("sdkFrameworkAidlPathKey")
var nonUpdatableFrameworkAidlPathKey = android.NewOnceKey("nonUpdatableFrameworkAidlPathKey")
var apiFingerprintPathKey = android.NewOnceKey("apiFingerprintPathKey")
@@ -51,9 +47,7 @@
if err != nil {
ctx.PropertyErrorf("sdk_version", "%s", err)
}
- if sdk.FinalOrFutureInt() <= 23 {
- return JAVA_VERSION_7
- } else if sdk.FinalOrFutureInt() <= 29 {
+ if sdk.FinalOrFutureInt() <= 29 {
return JAVA_VERSION_8
} else if sdk.FinalOrFutureInt() <= 31 {
return JAVA_VERSION_9
@@ -76,7 +70,8 @@
// Core is by definition what is included in the system module for the public API so should
// just use its system modules.
systemModuleKind = android.SdkPublic
- } else if systemModuleKind == android.SdkSystem || systemModuleKind == android.SdkTest {
+ } else if systemModuleKind == android.SdkSystem || systemModuleKind == android.SdkTest ||
+ systemModuleKind == android.SdkTestFrameworksCore {
// The core system and test APIs are currently the same as the public API so they should use
// its system modules.
systemModuleKind = android.SdkPublic
@@ -192,7 +187,7 @@
bootclasspath: corePlatformBootclasspathLibraries(ctx),
noFrameworksLibs: true,
}
- case android.SdkPublic, android.SdkSystem, android.SdkTest:
+ case android.SdkPublic, android.SdkSystem, android.SdkTest, android.SdkTestFrameworksCore:
return toModule(sdkVersion.Kind.DefaultJavaLibraryName(), sdkFrameworkAidlPath(ctx))
case android.SdkCore:
return sdkDep{
@@ -212,44 +207,6 @@
}
}
-func sdkPreSingletonFactory() android.Singleton {
- return sdkPreSingleton{}
-}
-
-type sdkPreSingleton struct{}
-
-func (sdkPreSingleton) GenerateBuildActions(ctx android.SingletonContext) {
- sdkJars, err := ctx.GlobWithDeps("prebuilts/sdk/*/public/android.jar", nil)
- if err != nil {
- ctx.Errorf("failed to glob prebuilts/sdk/*/public/android.jar: %s", err.Error())
- }
-
- var sdkVersions []int
- for _, sdkJar := range sdkJars {
- dir := filepath.Base(filepath.Dir(filepath.Dir(sdkJar)))
- v, err := strconv.Atoi(dir)
- if scerr, ok := err.(*strconv.NumError); ok && scerr.Err == strconv.ErrSyntax {
- continue
- } else if err != nil {
- ctx.Errorf("invalid sdk jar %q, %s, %v", sdkJar, err.Error())
- }
- sdkVersions = append(sdkVersions, v)
- }
-
- sort.Ints(sdkVersions)
-
- ctx.Config().Once(sdkVersionsKey, func() interface{} { return sdkVersions })
-}
-
-func LatestSdkVersionInt(ctx android.EarlyModuleContext) int {
- sdkVersions := ctx.Config().Get(sdkVersionsKey).([]int)
- latestSdkVersion := 0
- if len(sdkVersions) > 0 {
- latestSdkVersion = sdkVersions[len(sdkVersions)-1]
- }
- return latestSdkVersion
-}
-
func sdkSingletonFactory() android.Singleton {
return sdkSingleton{}
}
@@ -303,8 +260,7 @@
ctx.VisitAllModules(func(module android.Module) {
// Collect dex jar paths for the modules listed above.
- if ctx.ModuleHasProvider(module, JavaInfoProvider) {
- j := ctx.ModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ if j, ok := android.SingletonModuleProvider(ctx, module, JavaInfoProvider); ok {
name := ctx.ModuleName(module)
if i := android.IndexList(name, stubsModules); i != -1 {
stubsJars[i] = j.HeaderJars
diff --git a/java/sdk_library.go b/java/sdk_library.go
index d1620af..49e6727 100644
--- a/java/sdk_library.go
+++ b/java/sdk_library.go
@@ -15,6 +15,7 @@
package java
import (
+ "errors"
"fmt"
"path"
"path/filepath"
@@ -24,13 +25,10 @@
"strings"
"sync"
- "android/soong/ui/metrics/bp2build_metrics_proto"
-
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel"
"android/soong/dexpreopt"
)
@@ -107,8 +105,14 @@
// The name of the property in the java_sdk_library_import
propertyName string
- // The tag to use to depend on the stubs library module.
- stubsTag scopeDependencyTag
+ // The tag to use to depend on the prebuilt stubs library module
+ prebuiltStubsTag scopeDependencyTag
+
+ // The tag to use to depend on the everything stubs library module.
+ everythingStubsTag scopeDependencyTag
+
+ // The tag to use to depend on the exportable stubs library module.
+ exportableStubsTag scopeDependencyTag
// The tag to use to depend on the stubs source module (if separate from the API module).
stubsSourceTag scopeDependencyTag
@@ -170,11 +174,21 @@
allScopeNames = append(allScopeNames, name)
scope.propertyName = strings.ReplaceAll(name, "-", "_")
scope.fieldName = proptools.FieldNameForProperty(scope.propertyName)
- scope.stubsTag = scopeDependencyTag{
+ scope.prebuiltStubsTag = scopeDependencyTag{
name: name + "-stubs",
apiScope: scope,
depInfoExtractor: (*scopePaths).extractStubsLibraryInfoFromDependency,
}
+ scope.everythingStubsTag = scopeDependencyTag{
+ name: name + "-stubs-everything",
+ apiScope: scope,
+ depInfoExtractor: (*scopePaths).extractEverythingStubsLibraryInfoFromDependency,
+ }
+ scope.exportableStubsTag = scopeDependencyTag{
+ name: name + "-stubs-exportable",
+ apiScope: scope,
+ depInfoExtractor: (*scopePaths).extractExportableStubsLibraryInfoFromDependency,
+ }
scope.stubsSourceTag = scopeDependencyTag{
name: name + "-stubs-source",
apiScope: scope,
@@ -234,6 +248,10 @@
return ".stubs" + scope.moduleSuffix
}
+func (scope *apiScope) exportableStubsLibraryModuleNameSuffix() string {
+ return ".stubs.exportable" + scope.moduleSuffix
+}
+
func (scope *apiScope) apiLibraryModuleName(baseName string) string {
return scope.stubsLibraryModuleName(baseName) + ".from-text"
}
@@ -242,10 +260,18 @@
return scope.stubsLibraryModuleName(baseName) + ".from-source"
}
+func (scope *apiScope) exportableSourceStubsLibraryModuleName(baseName string) string {
+ return scope.exportableStubsLibraryModuleName(baseName) + ".from-source"
+}
+
func (scope *apiScope) stubsLibraryModuleName(baseName string) string {
return baseName + scope.stubsLibraryModuleNameSuffix()
}
+func (scope *apiScope) exportableStubsLibraryModuleName(baseName string) string {
+ return baseName + scope.exportableStubsLibraryModuleNameSuffix()
+}
+
func (scope *apiScope) stubsSourceModuleName(baseName string) string {
return baseName + ".stubs.source" + scope.moduleSuffix
}
@@ -286,6 +312,17 @@
return list
}
+// Method that maps the apiScopes properties to the index of each apiScopes elements.
+// apiScopes property to be used as the key can be specified with the input accessor.
+// Only a string property of apiScope can be used as the key of the map.
+func (scopes apiScopes) MapToIndex(accessor func(*apiScope) string) map[string]int {
+ ret := make(map[string]int)
+ for i, scope := range scopes {
+ ret[accessor(scope)] = i
+ }
+ return ret
+}
+
var (
scopeByName = make(map[string]*apiScope)
allScopeNames []string
@@ -459,6 +496,9 @@
// or the API file. They both have to use the same sdk_version as is used for
// compiling the implementation library.
Sdk_version *string
+
+ // Extra libs used when compiling stubs for this scope.
+ Libs []string
}
type sdkLibraryProperties struct {
@@ -604,8 +644,23 @@
Api_lint struct {
// Enable api linting.
Enabled *bool
+
+ // If API lint is enabled, this flag controls whether a set of legitimate lint errors
+ // are turned off. The default is true.
+ Legacy_errors_allowed *bool
}
+ // Determines if the module contributes to any api surfaces.
+ // This property should be set to true only if the module is listed under
+ // frameworks-base-api.bootclasspath in frameworks/base/api/Android.bp.
+ // Otherwise, this property should be set to false.
+ // Defaults to false.
+ Contribute_to_android_api *bool
+
+ // a list of aconfig_declarations module names that the stubs generated in this module
+ // depend on.
+ Aconfig_declarations []string
+
// TODO: determines whether to create HTML doc or not
// Html_doc *bool
}
@@ -631,6 +686,11 @@
// This is not the implementation jar, it still only contains stubs.
stubsDexJarPath OptionalDexJarPath
+ // The exportable dex jar for the stubs.
+ // This is not the implementation jar, it still only contains stubs.
+ // Includes unflagged apis and flagged apis enabled by release configurations.
+ exportableStubsDexJarPath OptionalDexJarPath
+
// The API specification file, e.g. system_current.txt.
currentApiFilePath android.OptionalPath
@@ -651,63 +711,120 @@
}
func (paths *scopePaths) extractStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error {
- if ctx.OtherModuleHasProvider(dep, JavaInfoProvider) {
- lib := ctx.OtherModuleProvider(dep, JavaInfoProvider).(JavaInfo)
+ if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
paths.stubsHeaderPath = lib.HeaderJars
paths.stubsImplPath = lib.ImplementationJars
libDep := dep.(UsesLibraryDependency)
- paths.stubsDexJarPath = libDep.DexJarBuildPath()
+ paths.stubsDexJarPath = libDep.DexJarBuildPath(ctx)
+ paths.exportableStubsDexJarPath = libDep.DexJarBuildPath(ctx)
return nil
} else {
return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library")
}
}
-func (paths *scopePaths) treatDepAsApiStubsProvider(dep android.Module, action func(provider ApiStubsProvider)) error {
- if apiStubsProvider, ok := dep.(ApiStubsProvider); ok {
- action(apiStubsProvider)
+func (paths *scopePaths) extractEverythingStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error {
+ if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
+ paths.stubsHeaderPath = lib.HeaderJars
+ if !ctx.Config().ReleaseHiddenApiExportableStubs() {
+ paths.stubsImplPath = lib.ImplementationJars
+ }
+
+ libDep := dep.(UsesLibraryDependency)
+ paths.stubsDexJarPath = libDep.DexJarBuildPath(ctx)
return nil
} else {
- return fmt.Errorf("expected module that implements ApiStubsProvider, e.g. droidstubs")
+ return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library")
}
}
-func (paths *scopePaths) treatDepAsApiStubsSrcProvider(dep android.Module, action func(provider ApiStubsSrcProvider)) error {
+func (paths *scopePaths) extractExportableStubsLibraryInfoFromDependency(ctx android.ModuleContext, dep android.Module) error {
+ if lib, ok := android.OtherModuleProvider(ctx, dep, JavaInfoProvider); ok {
+ if ctx.Config().ReleaseHiddenApiExportableStubs() {
+ paths.stubsImplPath = lib.ImplementationJars
+ }
+
+ libDep := dep.(UsesLibraryDependency)
+ paths.exportableStubsDexJarPath = libDep.DexJarBuildPath(ctx)
+ return nil
+ } else {
+ return fmt.Errorf("expected module that has JavaInfoProvider, e.g. java_library")
+ }
+}
+
+func (paths *scopePaths) treatDepAsApiStubsProvider(dep android.Module, action func(provider ApiStubsProvider) error) error {
+ if apiStubsProvider, ok := dep.(ApiStubsProvider); ok {
+ err := action(apiStubsProvider)
+ if err != nil {
+ return err
+ }
+ return nil
+ } else {
+ return fmt.Errorf("expected module that implements ExportableApiStubsSrcProvider, e.g. droidstubs")
+ }
+}
+
+func (paths *scopePaths) treatDepAsApiStubsSrcProvider(dep android.Module, action func(provider ApiStubsSrcProvider) error) error {
if apiStubsProvider, ok := dep.(ApiStubsSrcProvider); ok {
- action(apiStubsProvider)
+ err := action(apiStubsProvider)
+ if err != nil {
+ return err
+ }
return nil
} else {
return fmt.Errorf("expected module that implements ApiStubsSrcProvider, e.g. droidstubs")
}
}
-func (paths *scopePaths) extractApiInfoFromApiStubsProvider(provider ApiStubsProvider) {
- paths.annotationsZip = android.OptionalPathForPath(provider.AnnotationsZip())
- paths.currentApiFilePath = android.OptionalPathForPath(provider.ApiFilePath())
- paths.removedApiFilePath = android.OptionalPathForPath(provider.RemovedApiFilePath())
+func (paths *scopePaths) extractApiInfoFromApiStubsProvider(provider ApiStubsProvider, stubsType StubsType) error {
+ var annotationsZip, currentApiFilePath, removedApiFilePath android.Path
+ annotationsZip, annotationsZipErr := provider.AnnotationsZip(stubsType)
+ currentApiFilePath, currentApiFilePathErr := provider.ApiFilePath(stubsType)
+ removedApiFilePath, removedApiFilePathErr := provider.RemovedApiFilePath(stubsType)
+
+ combinedError := errors.Join(annotationsZipErr, currentApiFilePathErr, removedApiFilePathErr)
+
+ if combinedError == nil {
+ paths.annotationsZip = android.OptionalPathForPath(annotationsZip)
+ paths.currentApiFilePath = android.OptionalPathForPath(currentApiFilePath)
+ paths.removedApiFilePath = android.OptionalPathForPath(removedApiFilePath)
+ }
+ return combinedError
}
func (paths *scopePaths) extractApiInfoFromDep(ctx android.ModuleContext, dep android.Module) error {
- return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) {
- paths.extractApiInfoFromApiStubsProvider(provider)
+ return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) error {
+ return paths.extractApiInfoFromApiStubsProvider(provider, Everything)
})
}
-func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider ApiStubsSrcProvider) {
- paths.stubsSrcJar = android.OptionalPathForPath(provider.StubsSrcJar())
+func (paths *scopePaths) extractStubsSourceInfoFromApiStubsProviders(provider ApiStubsSrcProvider, stubsType StubsType) error {
+ stubsSrcJar, err := provider.StubsSrcJar(stubsType)
+ if err == nil {
+ paths.stubsSrcJar = android.OptionalPathForPath(stubsSrcJar)
+ }
+ return err
}
func (paths *scopePaths) extractStubsSourceInfoFromDep(ctx android.ModuleContext, dep android.Module) error {
- return paths.treatDepAsApiStubsSrcProvider(dep, func(provider ApiStubsSrcProvider) {
- paths.extractStubsSourceInfoFromApiStubsProviders(provider)
+ return paths.treatDepAsApiStubsSrcProvider(dep, func(provider ApiStubsSrcProvider) error {
+ return paths.extractStubsSourceInfoFromApiStubsProviders(provider, Everything)
})
}
func (paths *scopePaths) extractStubsSourceAndApiInfoFromApiStubsProvider(ctx android.ModuleContext, dep android.Module) error {
- return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) {
- paths.extractApiInfoFromApiStubsProvider(provider)
- paths.extractStubsSourceInfoFromApiStubsProviders(provider)
+ if ctx.Config().ReleaseHiddenApiExportableStubs() {
+ return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) error {
+ extractApiInfoErr := paths.extractApiInfoFromApiStubsProvider(provider, Exportable)
+ extractStubsSourceInfoErr := paths.extractStubsSourceInfoFromApiStubsProviders(provider, Exportable)
+ return errors.Join(extractApiInfoErr, extractStubsSourceInfoErr)
+ })
+ }
+ return paths.treatDepAsApiStubsProvider(dep, func(provider ApiStubsProvider) error {
+ extractApiInfoErr := paths.extractApiInfoFromApiStubsProvider(provider, Everything)
+ extractStubsSourceInfoErr := paths.extractStubsSourceInfoFromApiStubsProviders(provider, Everything)
+ return errors.Join(extractApiInfoErr, extractStubsSourceInfoErr)
})
}
@@ -870,6 +987,12 @@
return c.namingScheme.stubsLibraryModuleName(apiScope, baseName)
}
+// Name of the java_library module that compiles the exportable stubs source.
+func (c *commonToSdkLibraryAndImport) exportableStubsLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.BaseModuleName()
+ return c.namingScheme.exportableStubsLibraryModuleName(apiScope, baseName)
+}
+
// Name of the droidstubs module that generates the stubs source and may also
// generate/check the API.
func (c *commonToSdkLibraryAndImport) stubsSourceModuleName(apiScope *apiScope) string {
@@ -886,9 +1009,16 @@
// Name of the java_library module that compiles the stubs
// generated from source Java files.
-func (c *commonToSdkLibraryAndImport) sourceStubLibraryModuleName(apiScope *apiScope) string {
+func (c *commonToSdkLibraryAndImport) sourceStubsLibraryModuleName(apiScope *apiScope) string {
baseName := c.module.BaseModuleName()
- return c.namingScheme.sourceStubLibraryModuleName(apiScope, baseName)
+ return c.namingScheme.sourceStubsLibraryModuleName(apiScope, baseName)
+}
+
+// Name of the java_library module that compiles the exportable stubs
+// generated from source Java files.
+func (c *commonToSdkLibraryAndImport) exportableSourceStubsLibraryModuleName(apiScope *apiScope) string {
+ baseName := c.module.BaseModuleName()
+ return c.namingScheme.exportableSourceStubsLibraryModuleName(apiScope, baseName)
}
// The component names for different outputs of the java_sdk_library.
@@ -1082,6 +1212,16 @@
}
// to satisfy SdkLibraryDependency interface
+func (c *commonToSdkLibraryAndImport) SdkApiExportableStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath {
+ paths := c.selectScopePaths(ctx, kind)
+ if paths == nil {
+ return makeUnsetDexJarPath()
+ }
+
+ return paths.exportableStubsDexJarPath
+}
+
+// to satisfy SdkLibraryDependency interface
func (c *commonToSdkLibraryAndImport) SdkRemovedTxtFile(ctx android.BaseModuleContext, kind android.SdkKind) android.OptionalPath {
apiScope := sdkKindToApiScope(kind)
paths := c.findScopePaths(apiScope)
@@ -1199,10 +1339,16 @@
// they are identical to the corresponding header jars.
SdkImplementationJars(ctx android.BaseModuleContext, sdkVersion android.SdkSpec) android.Paths
- // SdkApiStubDexJar returns the dex jar for the stubs. It is needed by the hiddenapi processing
- // tool which processes dex files.
+ // SdkApiStubDexJar returns the dex jar for the stubs for the prebuilt
+ // java_sdk_library_import module. It is needed by the hiddenapi processing tool which
+ // processes dex files.
SdkApiStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath
+ // SdkApiExportableStubDexJar returns the exportable dex jar for the stubs for
+ // java_sdk_library module. It is needed by the hiddenapi processing tool which processes
+ // dex files.
+ SdkApiExportableStubDexJar(ctx android.BaseModuleContext, kind android.SdkKind) OptionalDexJarPath
+
// SdkRemovedTxtFile returns the optional path to the removed.txt file for the specified sdk kind.
SdkRemovedTxtFile(ctx android.BaseModuleContext, kind android.SdkKind) android.OptionalPath
@@ -1213,8 +1359,6 @@
type SdkLibrary struct {
Library
- android.BazelModuleBase
-
sdkLibraryProperties sdkLibraryProperties
// Map from api scope to the scope specific property structure.
@@ -1317,8 +1461,10 @@
for _, apiScope := range module.getGeneratedApiScopes(ctx) {
// Add dependencies to the stubs library
stubModuleName := module.stubsLibraryModuleName(apiScope)
+ ctx.AddVariationDependencies(nil, apiScope.everythingStubsTag, stubModuleName)
- ctx.AddVariationDependencies(nil, apiScope.stubsTag, stubModuleName)
+ exportableStubModuleName := module.exportableStubsLibraryModuleName(apiScope)
+ ctx.AddVariationDependencies(nil, apiScope.exportableStubsTag, exportableStubModuleName)
// Add a dependency on the stubs source in order to access both stubs source and api information.
ctx.AddVariationDependencies(nil, apiScope.stubsSourceAndApiTag, module.stubsSourceModuleName(apiScope))
@@ -1431,7 +1577,7 @@
// Make the set of components exported by this module available for use elsewhere.
exportedComponentInfo := android.ExportedComponentsInfo{Components: android.SortedKeys(exportedComponents)}
- ctx.SetProvider(android.ExportedComponentsInfoProvider, exportedComponentInfo)
+ android.SetProvider(ctx, android.ExportedComponentsInfoProvider, exportedComponentInfo)
// Provide additional information for inclusion in an sdk's generated .info file.
additionalSdkInfo := map[string]interface{}{}
@@ -1451,7 +1597,7 @@
scopeInfo["latest_removed_api"] = p.Path().String()
}
}
- ctx.SetProvider(android.AdditionalSdkInfoProvider, android.AdditionalSdkInfo{additionalSdkInfo})
+ android.SetProvider(ctx, android.AdditionalSdkInfoProvider, android.AdditionalSdkInfo{additionalSdkInfo})
}
func (module *SdkLibrary) AndroidMkEntries() []android.AndroidMkEntries {
@@ -1606,42 +1752,41 @@
mctx.CreateModule(LibraryFactory, properties...)
}
-// Creates a static java library that has API stubs
-func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
- props := struct {
- Name *string
- Visibility []string
- Srcs []string
- Installable *bool
- Sdk_version *string
- System_modules *string
- Patch_module *string
- Libs []string
- Static_libs []string
- Compile_dex *bool
- Java_version *string
- Openjdk9 struct {
- Srcs []string
- Javacflags []string
- }
- Dist struct {
- Targets []string
- Dest *string
- Dir *string
- Tag *string
- }
- }{}
+type libraryProperties struct {
+ Name *string
+ Visibility []string
+ Srcs []string
+ Installable *bool
+ Sdk_version *string
+ System_modules *string
+ Patch_module *string
+ Libs []string
+ Static_libs []string
+ Compile_dex *bool
+ Java_version *string
+ Openjdk9 struct {
+ Srcs []string
+ Javacflags []string
+ }
+ Dist struct {
+ Targets []string
+ Dest *string
+ Dir *string
+ Tag *string
+ }
+}
- props.Name = proptools.StringPtr(module.sourceStubLibraryModuleName(apiScope))
+func (module *SdkLibrary) stubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties {
+ props := libraryProperties{}
props.Visibility = []string{"//visibility:override", "//visibility:private"}
// sources are generated from the droiddoc
- props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)}
sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
props.Sdk_version = proptools.StringPtr(sdkVersion)
props.System_modules = module.deviceProperties.System_modules
props.Patch_module = module.properties.Patch_module
props.Installable = proptools.BoolPtr(false)
props.Libs = module.sdkLibraryProperties.Stub_only_libs
+ props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
// The stub-annotations library contains special versions of the annotations
// with CLASS retention policy, so that they're kept.
@@ -1654,6 +1799,25 @@
// interop with older developer tools that don't support 1.9.
props.Java_version = proptools.StringPtr("1.8")
+ return props
+}
+
+// Creates a static java library that has API stubs
+func (module *SdkLibrary) createStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
+
+ props := module.stubsLibraryProps(mctx, apiScope)
+ props.Name = proptools.StringPtr(module.sourceStubsLibraryModuleName(apiScope))
+ props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope)}
+
+ mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+// Create a static java library that compiles the "exportable" stubs
+func (module *SdkLibrary) createExportableStubsLibrary(mctx android.DefaultableHookContext, apiScope *apiScope) {
+ props := module.stubsLibraryProps(mctx, apiScope)
+ props.Name = proptools.StringPtr(module.exportableSourceStubsLibraryModuleName(apiScope))
+ props.Srcs = []string{":" + module.stubsSourceModuleName(apiScope) + "{.exportable}"}
+
mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}
@@ -1678,6 +1842,7 @@
Merge_inclusion_annotations_dirs []string
Generate_stubs *bool
Previous_api *string
+ Aconfig_declarations []string
Check_api struct {
Current ApiToCheck
Last_released ApiToCheck
@@ -1714,6 +1879,7 @@
props.Libs = module.properties.Libs
props.Libs = append(props.Libs, module.properties.Static_libs...)
props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...)
+ props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
props.Aidl.Include_dirs = module.deviceProperties.Aidl.Include_dirs
props.Aidl.Local_include_dirs = module.deviceProperties.Aidl.Local_include_dirs
props.Java_version = module.properties.Java_version
@@ -1721,6 +1887,7 @@
props.Annotations_enabled = module.sdkLibraryProperties.Annotations_enabled
props.Merge_annotations_dirs = module.sdkLibraryProperties.Merge_annotations_dirs
props.Merge_inclusion_annotations_dirs = module.sdkLibraryProperties.Merge_inclusion_annotations_dirs
+ props.Aconfig_declarations = module.sdkLibraryProperties.Aconfig_declarations
droidstubsArgs := []string{}
if len(module.sdkLibraryProperties.Api_packages) != 0 {
@@ -1731,15 +1898,15 @@
android.JoinWithPrefix(module.sdkLibraryProperties.Hidden_api_packages, " --hide-package "))
}
droidstubsArgs = append(droidstubsArgs, module.sdkLibraryProperties.Droiddoc_options...)
- disabledWarnings := []string{
- "BroadcastBehavior",
- "DeprecationMismatch",
- "HiddenSuperclass",
- "HiddenTypeParameter",
- "MissingPermission",
- "SdkConstant",
- "Todo",
- "UnavailableSymbol",
+ disabledWarnings := []string{"HiddenSuperclass"}
+ if proptools.BoolDefault(module.sdkLibraryProperties.Api_lint.Legacy_errors_allowed, true) {
+ disabledWarnings = append(disabledWarnings,
+ "BroadcastBehavior",
+ "DeprecationMismatch",
+ "MissingPermission",
+ "SdkConstant",
+ "Todo",
+ )
}
droidstubsArgs = append(droidstubsArgs, android.JoinWithPrefix(disabledWarnings, "--hide "))
@@ -1815,7 +1982,7 @@
}
}
- mctx.CreateModule(DroidstubsFactory, &props).(*Droidstubs).CallHookIfAvailable(mctx)
+ mctx.CreateModule(DroidstubsFactory, &props, module.sdkComponentPropertiesForChildLibrary()).(*Droidstubs).CallHookIfAvailable(mctx)
}
func (module *SdkLibrary) createApiLibrary(mctx android.DefaultableHookContext, apiScope *apiScope, alternativeFullApiSurfaceStub string) {
@@ -1826,6 +1993,8 @@
Libs []string
Static_libs []string
Full_api_surface_stub *string
+ System_modules *string
+ Enable_validation *bool
}{}
props.Name = proptools.StringPtr(module.apiLibraryModuleName(apiScope))
@@ -1851,6 +2020,7 @@
props.Api_contributions = apiContributions
props.Libs = module.properties.Libs
props.Libs = append(props.Libs, module.sdkLibraryProperties.Stub_only_libs...)
+ props.Libs = append(props.Libs, module.scopeToProperties[apiScope].Libs...)
props.Libs = append(props.Libs, "stub-annotations")
props.Static_libs = module.sdkLibraryProperties.Stub_only_static_libs
props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName())
@@ -1864,46 +2034,29 @@
props.Full_api_surface_stub = proptools.StringPtr(apiScope.kind.DefaultJavaLibraryName() + "_full.from-text")
}
- mctx.CreateModule(ApiLibraryFactory, &props)
+ // java_sdk_library modules that set sdk_version as none does not depend on other api
+ // domains. Therefore, java_api_library created from such modules should not depend on
+ // full_api_surface_stubs but create and compile stubs by the java_api_library module
+ // itself.
+ if module.SdkVersion(mctx).Kind == android.SdkNone {
+ props.Full_api_surface_stub = nil
+ }
+
+ props.System_modules = module.deviceProperties.System_modules
+ props.Enable_validation = proptools.BoolPtr(true)
+
+ mctx.CreateModule(ApiLibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}
-func (module *SdkLibrary) createTopLevelStubsLibrary(
- mctx android.DefaultableHookContext, apiScope *apiScope, contributesToApiSurface bool) {
- props := struct {
- Name *string
- Visibility []string
- Sdk_version *string
- Static_libs []string
- System_modules *string
- Dist struct {
- Targets []string
- Dest *string
- Dir *string
- Tag *string
- }
- Compile_dex *bool
- }{}
- props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
+func (module *SdkLibrary) topLevelStubsLibraryProps(mctx android.DefaultableHookContext, apiScope *apiScope) libraryProperties {
+ props := libraryProperties{}
+
props.Visibility = childModuleVisibility(module.sdkLibraryProperties.Stubs_library_visibility)
sdkVersion := module.sdkVersionForStubsLibrary(mctx, apiScope)
props.Sdk_version = proptools.StringPtr(sdkVersion)
- // Add the stub compiling java_library/java_api_library as static lib based on build config
- staticLib := module.sourceStubLibraryModuleName(apiScope)
- if mctx.Config().BuildFromTextStub() && contributesToApiSurface {
- staticLib = module.apiLibraryModuleName(apiScope)
- }
- props.Static_libs = append(props.Static_libs, staticLib)
props.System_modules = module.deviceProperties.System_modules
- // Dist the class jar artifact for sdk builds.
- if !Bool(module.sdkLibraryProperties.No_dist) {
- props.Dist.Targets = []string{"sdk", "win_sdk"}
- props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
- props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
- props.Dist.Tag = proptools.StringPtr(".jar")
- }
-
// The imports need to be compiled to dex if the java_sdk_library requests it.
compileDex := module.dexProperties.Compile_dex
if module.stubLibrariesCompiledForDex() {
@@ -1911,6 +2064,43 @@
}
props.Compile_dex = compileDex
+ return props
+}
+
+func (module *SdkLibrary) createTopLevelStubsLibrary(
+ mctx android.DefaultableHookContext, apiScope *apiScope, contributesToApiSurface bool) {
+
+ props := module.topLevelStubsLibraryProps(mctx, apiScope)
+ props.Name = proptools.StringPtr(module.stubsLibraryModuleName(apiScope))
+
+ // Add the stub compiling java_library/java_api_library as static lib based on build config
+ staticLib := module.sourceStubsLibraryModuleName(apiScope)
+ if mctx.Config().BuildFromTextStub() && contributesToApiSurface {
+ staticLib = module.apiLibraryModuleName(apiScope)
+ }
+ props.Static_libs = append(props.Static_libs, staticLib)
+
+ mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+func (module *SdkLibrary) createTopLevelExportableStubsLibrary(
+ mctx android.DefaultableHookContext, apiScope *apiScope) {
+
+ props := module.topLevelStubsLibraryProps(mctx, apiScope)
+ props.Name = proptools.StringPtr(module.exportableStubsLibraryModuleName(apiScope))
+
+ // Dist the class jar artifact for sdk builds.
+ // "exportable" stubs are copied to dist for sdk builds instead of the "everything" stubs.
+ if !Bool(module.sdkLibraryProperties.No_dist) {
+ props.Dist.Targets = []string{"sdk", "win_sdk"}
+ props.Dist.Dest = proptools.StringPtr(fmt.Sprintf("%v.jar", module.distStem()))
+ props.Dist.Dir = proptools.StringPtr(module.apiDistPath(apiScope))
+ props.Dist.Tag = proptools.StringPtr(".jar")
+ }
+
+ staticLib := module.exportableSourceStubsLibraryModuleName(apiScope)
+ props.Static_libs = append(props.Static_libs, staticLib)
+
mctx.CreateModule(LibraryFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}
@@ -1932,6 +2122,10 @@
return module.uniqueApexVariations()
}
+func (module *SdkLibrary) ContributeToApi() bool {
+ return proptools.BoolDefault(module.sdkLibraryProperties.Contribute_to_android_api, false)
+}
+
// Creates the xml file that publicizes the runtime library
func (module *SdkLibrary) createXmlFile(mctx android.DefaultableHookContext) {
moduleMinApiLevel := module.Library.MinSdkVersion(mctx)
@@ -1948,6 +2142,7 @@
Min_device_sdk *string
Max_device_sdk *string
Sdk_library_min_api_level *string
+ Uses_libs_dependencies []string
}{
Name: proptools.StringPtr(module.xmlPermissionsModuleName()),
Lib_name: proptools.StringPtr(module.BaseModuleName()),
@@ -1957,6 +2152,7 @@
Min_device_sdk: module.commonSdkLibraryProperties.Min_device_sdk,
Max_device_sdk: module.commonSdkLibraryProperties.Max_device_sdk,
Sdk_library_min_api_level: &moduleMinApiLevelStr,
+ Uses_libs_dependencies: module.usesLibraryProperties.Uses_libs,
}
mctx.CreateModule(sdkLibraryXmlFactory, &props)
@@ -1994,8 +2190,8 @@
// If either this or the other module are on the platform then this will return
// false.
func withinSameApexesAs(ctx android.BaseModuleContext, other android.Module) bool {
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
- otherApexInfo := ctx.OtherModuleProvider(other, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ otherApexInfo, _ := android.OtherModuleProvider(ctx, other, android.ApexInfoProvider)
return len(otherApexInfo.InApexVariants) > 0 && reflect.DeepEqual(apexInfo.InApexVariants, otherApexInfo.InApexVariants)
}
@@ -2110,6 +2306,7 @@
module.createStubsSourcesAndApi(mctx, scope, module.stubsSourceModuleName(scope), scope.droidstubsArgs)
module.createStubsLibrary(mctx, scope)
+ module.createExportableStubsLibrary(mctx, scope)
alternativeFullApiSurfaceStubLib := ""
if scope == apiScopePublic {
@@ -2121,6 +2318,7 @@
}
module.createTopLevelStubsLibrary(mctx, scope, contributesToApiSurface)
+ module.createTopLevelExportableStubsLibrary(mctx, scope)
}
if module.requiresRuntimeImplementationLibrary() {
@@ -2176,7 +2374,11 @@
apiLibraryModuleName(scope *apiScope, baseName string) string
- sourceStubLibraryModuleName(scope *apiScope, baseName string) string
+ sourceStubsLibraryModuleName(scope *apiScope, baseName string) string
+
+ exportableStubsLibraryModuleName(scope *apiScope, baseName string) string
+
+ exportableSourceStubsLibraryModuleName(scope *apiScope, baseName string) string
}
type defaultNamingScheme struct {
@@ -2194,34 +2396,47 @@
return scope.apiLibraryModuleName(baseName)
}
-func (s *defaultNamingScheme) sourceStubLibraryModuleName(scope *apiScope, baseName string) string {
+func (s *defaultNamingScheme) sourceStubsLibraryModuleName(scope *apiScope, baseName string) string {
return scope.sourceStubLibraryModuleName(baseName)
}
+func (s *defaultNamingScheme) exportableStubsLibraryModuleName(scope *apiScope, baseName string) string {
+ return scope.exportableStubsLibraryModuleName(baseName)
+}
+
+func (s *defaultNamingScheme) exportableSourceStubsLibraryModuleName(scope *apiScope, baseName string) string {
+ return scope.exportableSourceStubsLibraryModuleName(baseName)
+}
+
var _ sdkLibraryComponentNamingScheme = (*defaultNamingScheme)(nil)
+func hasStubsLibrarySuffix(name string, apiScope *apiScope) bool {
+ return strings.HasSuffix(name, apiScope.stubsLibraryModuleNameSuffix()) ||
+ strings.HasSuffix(name, apiScope.exportableStubsLibraryModuleNameSuffix())
+}
+
func moduleStubLinkType(name string) (stub bool, ret sdkLinkType) {
name = strings.TrimSuffix(name, ".from-source")
// This suffix-based approach is fragile and could potentially mis-trigger.
// TODO(b/155164730): Clean this up when modules no longer reference sdk_lib stubs directly.
- if strings.HasSuffix(name, apiScopePublic.stubsLibraryModuleNameSuffix()) {
+ if hasStubsLibrarySuffix(name, apiScopePublic) {
if name == "hwbinder.stubs" || name == "libcore_private.stubs" {
// Due to a previous bug, these modules were not considered stubs, so we retain that.
return false, javaPlatform
}
return true, javaSdk
}
- if strings.HasSuffix(name, apiScopeSystem.stubsLibraryModuleNameSuffix()) {
+ if hasStubsLibrarySuffix(name, apiScopeSystem) {
return true, javaSystem
}
- if strings.HasSuffix(name, apiScopeModuleLib.stubsLibraryModuleNameSuffix()) {
+ if hasStubsLibrarySuffix(name, apiScopeModuleLib) {
return true, javaModule
}
- if strings.HasSuffix(name, apiScopeTest.stubsLibraryModuleNameSuffix()) {
+ if hasStubsLibrarySuffix(name, apiScopeTest) {
return true, javaSystem
}
- if strings.HasSuffix(name, apiScopeSystemServer.stubsLibraryModuleNameSuffix()) {
+ if hasStubsLibrarySuffix(name, apiScopeSystemServer) {
return true, javaSystemServer
}
return false, javaPlatform
@@ -2271,49 +2486,9 @@
module.CreateInternalModules(ctx)
}
})
- android.InitBazelModule(module)
return module
}
-type bazelSdkLibraryAttributes struct {
- Public bazel.StringAttribute
- System bazel.StringAttribute
- Test bazel.StringAttribute
- Module_lib bazel.StringAttribute
- System_server bazel.StringAttribute
-}
-
-// java_sdk_library bp2build converter
-func (module *SdkLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- if ctx.ModuleType() != "java_sdk_library" {
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
- return
- }
-
- nameToAttr := make(map[string]bazel.StringAttribute)
-
- for _, scope := range module.getGeneratedApiScopes(ctx) {
- apiSurfaceFile := path.Join(module.getApiDir(), scope.apiFilePrefix+"current.txt")
- var scopeStringAttribute bazel.StringAttribute
- scopeStringAttribute.SetValue(apiSurfaceFile)
- nameToAttr[scope.name] = scopeStringAttribute
- }
-
- attrs := bazelSdkLibraryAttributes{
- Public: nameToAttr["public"],
- System: nameToAttr["system"],
- Test: nameToAttr["test"],
- Module_lib: nameToAttr["module-lib"],
- System_server: nameToAttr["system-server"],
- }
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "java_sdk_library",
- Bzl_load_location: "//build/bazel/rules/java:sdk_library.bzl",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: module.Name()}, &attrs)
-}
-
//
// SDK library prebuilts
//
@@ -2377,7 +2552,8 @@
xmlPermissionsFileModule *sdkLibraryXml
// Build path to the dex implementation jar obtained from the prebuilt_apex, if any.
- dexJarFile OptionalDexJarPath
+ dexJarFile OptionalDexJarPath
+ dexJarFileErr error
// Expected install file path of the source module(sdk_library)
// or dex implementation jar obtained from the prebuilt_apex, if any.
@@ -2479,6 +2655,10 @@
if len(scopeProperties.Stub_srcs) > 0 {
module.createPrebuiltStubsSources(mctx, apiScope, scopeProperties)
}
+
+ if scopeProperties.Current_api != nil {
+ module.createPrebuiltApiContribution(mctx, apiScope, scopeProperties)
+ }
}
javaSdkLibraries := javaSdkLibraries(mctx.Config())
@@ -2531,7 +2711,26 @@
// The stubs source is preferred if the java_sdk_library_import is preferred.
props.CopyUserSuppliedPropertiesFromPrebuilt(&module.prebuilt)
- mctx.CreateModule(PrebuiltStubsSourcesFactory, &props)
+ mctx.CreateModule(PrebuiltStubsSourcesFactory, &props, module.sdkComponentPropertiesForChildLibrary())
+}
+
+func (module *SdkLibraryImport) createPrebuiltApiContribution(mctx android.DefaultableHookContext, apiScope *apiScope, scopeProperties *sdkLibraryScopeProperties) {
+ api_file := scopeProperties.Current_api
+ api_surface := &apiScope.name
+
+ props := struct {
+ Name *string
+ Api_surface *string
+ Api_file *string
+ Visibility []string
+ }{}
+
+ props.Name = proptools.StringPtr(module.stubsSourceModuleName(apiScope) + ".api.contribution")
+ props.Api_surface = api_surface
+ props.Api_file = api_file
+ props.Visibility = []string{"//visibility:override", "//visibility:public"}
+
+ mctx.CreateModule(ApiContributionImportFactory, &props, module.sdkComponentPropertiesForChildLibrary())
}
// Add the dependencies on the child module in the component deps mutator so that it
@@ -2543,7 +2742,7 @@
}
// Add dependencies to the prebuilt stubs library
- ctx.AddVariationDependencies(nil, apiScope.stubsTag, android.PrebuiltNameFromSource(module.stubsLibraryModuleName(apiScope)))
+ ctx.AddVariationDependencies(nil, apiScope.prebuiltStubsTag, android.PrebuiltNameFromSource(module.stubsLibraryModuleName(apiScope)))
if len(scopeProperties.Stub_srcs) > 0 {
// Add dependencies to the prebuilt stubs source library
@@ -2567,14 +2766,6 @@
}
}
-func (module *SdkLibraryImport) AndroidMkEntries() []android.AndroidMkEntries {
- // For an SDK library imported from a prebuilt APEX, we don't need a Make module for itself, as we
- // don't need to install it. However, we need to add its dexpreopt outputs as sub-modules, if it
- // is preopted.
- dexpreoptEntries := module.dexpreopter.AndroidMkEntriesForApex()
- return append(dexpreoptEntries, android.AndroidMkEntries{Disabled: true})
-}
-
var _ android.ApexModule = (*SdkLibraryImport)(nil)
// Implements android.ApexModule
@@ -2668,14 +2859,18 @@
if ctx.Device() {
// If this is a variant created for a prebuilt_apex then use the dex implementation jar
// obtained from the associated deapexer module.
- ai := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ ai, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if ai.ForPrebuiltApex {
// Get the path of the dex implementation jar from the `deapexer` module.
- di := android.FindDeapexerProviderForModule(ctx)
- if di == nil {
- return // An error has been reported by FindDeapexerProviderForModule.
+ di, err := android.FindDeapexerProviderForModule(ctx)
+ if err != nil {
+ // An error was found, possibly due to multiple apexes in the tree that export this library
+ // Defer the error till a client tries to call DexJarBuildPath
+ module.dexJarFileErr = err
+ module.initHiddenAPIError(err)
+ return
}
- dexJarFileApexRootRelative := apexRootRelativePathToJavaLib(module.BaseModuleName())
+ dexJarFileApexRootRelative := ApexRootRelativePathToJavaLib(module.BaseModuleName())
if dexOutputPath := di.PrebuiltExportPath(dexJarFileApexRootRelative); dexOutputPath != nil {
dexJarFile := makeDexJarPathFromPath(dexOutputPath)
module.dexJarFile = dexJarFile
@@ -2684,16 +2879,13 @@
module.installFile = installPath
module.initHiddenAPI(ctx, dexJarFile, module.findScopePaths(apiScopePublic).stubsImplPath[0], nil)
- module.dexpreopter.installPath = module.dexpreopter.getInstallPath(ctx, installPath)
+ module.dexpreopter.installPath = module.dexpreopter.getInstallPath(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), installPath)
module.dexpreopter.isSDKLibrary = true
- module.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, &module.dexpreopter)
+ module.dexpreopter.uncompressedDex = shouldUncompressDex(ctx, android.RemoveOptionalPrebuiltPrefix(ctx.ModuleName()), &module.dexpreopter)
if profilePath := di.PrebuiltExportPath(dexJarFileApexRootRelative + ".prof"); profilePath != nil {
module.dexpreopter.inputProfilePathOnHost = profilePath
}
-
- // Dexpreopting.
- module.dexpreopt(ctx, dexOutputPath)
} else {
// This should never happen as a variant for a prebuilt_apex is only created if the
// prebuilt_apex has been configured to export the java library dex file.
@@ -2732,16 +2924,19 @@
}
// to satisfy UsesLibraryDependency interface
-func (module *SdkLibraryImport) DexJarBuildPath() OptionalDexJarPath {
+func (module *SdkLibraryImport) DexJarBuildPath(ctx android.ModuleErrorfContext) OptionalDexJarPath {
// The dex implementation jar extracted from the .apex file should be used in preference to the
// source.
+ if module.dexJarFileErr != nil {
+ ctx.ModuleErrorf(module.dexJarFileErr.Error())
+ }
if module.dexJarFile.IsSet() {
return module.dexJarFile
}
if module.implLibraryModule == nil {
return makeUnsetDexJarPath()
} else {
- return module.implLibraryModule.DexJarBuildPath()
+ return module.implLibraryModule.DexJarBuildPath(ctx)
}
}
@@ -2824,6 +3019,10 @@
return requiredFilesFromPrebuiltApexForImport(name, &module.dexpreopter)
}
+func (j *SdkLibraryImport) UseProfileGuidedDexpreopt() bool {
+ return proptools.Bool(j.importDexpreoptProperties.Dex_preopt.Profile_guided)
+}
+
// java_sdk_library_xml
type sdkLibraryXml struct {
android.ModuleBase
@@ -2873,6 +3072,11 @@
//
// This value comes from the ApiLevel of the MinSdkVersion property.
Sdk_library_min_api_level *string
+
+ // Uses-libs dependencies that the shared library requires to work correctly.
+ //
+ // This will add dependency="foo:bar" to the <library> section.
+ Uses_libs_dependencies []string
}
// java_sdk_library_xml builds the permission xml file for a java_sdk_library.
@@ -2930,7 +3134,7 @@
// File path to the runtime implementation library
func (module *sdkLibraryXml) implPath(ctx android.ModuleContext) string {
implName := proptools.String(module.properties.Lib_name)
- if apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo); !apexInfo.IsForPlatform() {
+ if apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider); !apexInfo.IsForPlatform() {
// TODO(b/146468504): ApexVariationName() is only a soong module name, not apex name.
// In most cases, this works fine. But when apex_name is set or override_apex is used
// this can be wrong.
@@ -2981,6 +3185,13 @@
return fmt.Sprintf(` %s=\"%s\"\n`, attrName, *value)
}
+func formattedDependenciesAttribute(dependencies []string) string {
+ if dependencies == nil {
+ return ""
+ }
+ return fmt.Sprintf(` dependency=\"%s\"\n`, strings.Join(dependencies, ":"))
+}
+
func (module *sdkLibraryXml) permissionsContents(ctx android.ModuleContext) string {
libName := proptools.String(module.properties.Lib_name)
libNameAttr := formattedOptionalAttribute("name", &libName)
@@ -2990,6 +3201,7 @@
implicitUntilAttr := formattedOptionalSdkLevelAttribute(ctx, "on-bootclasspath-before", module.properties.On_bootclasspath_before)
minSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "min-device-sdk", module.properties.Min_device_sdk)
maxSdkAttr := formattedOptionalSdkLevelAttribute(ctx, "max-device-sdk", module.properties.Max_device_sdk)
+ dependenciesAttr := formattedDependenciesAttribute(module.properties.Uses_libs_dependencies)
// <library> is understood in all android versions whereas <apex-library> is only understood from API T (and ignored before that).
// similarly, min_device_sdk is only understood from T. So if a library is using that, we need to use the apex-library to make sure this library is not loaded before T
var libraryTag string
@@ -3023,12 +3235,14 @@
implicitUntilAttr,
minSdkAttr,
maxSdkAttr,
+ dependenciesAttr,
` />\n`,
`</permissions>\n`}, "")
}
func (module *sdkLibraryXml) GenerateAndroidBuildActions(ctx android.ModuleContext) {
- module.hideApexVariantFromMake = !ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).IsForPlatform()
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ module.hideApexVariantFromMake = !apexInfo.IsForPlatform()
libName := proptools.String(module.properties.Lib_name)
module.selfValidate(ctx)
diff --git a/java/sdk_library_test.go b/java/sdk_library_test.go
index 868d697..3326ec5 100644
--- a/java/sdk_library_test.go
+++ b/java/sdk_library_test.go
@@ -38,6 +38,11 @@
android.FixtureModifyConfig(func(config android.Config) {
config.SetApiLibraries([]string{"foo"})
}),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTestWithBp(t, `
droiddoc_exported_dir {
name: "droiddoc-templates-sdk",
@@ -74,6 +79,8 @@
name: "quuz",
public: {
jars: ["c.jar"],
+ current_api: "api/current.txt",
+ removed_api: "api/removed.txt",
},
}
java_sdk_library_import {
@@ -130,13 +137,16 @@
result.ModuleForTests("foo.api.system.28", "")
result.ModuleForTests("foo.api.test.28", "")
- exportedComponentsInfo := result.ModuleProvider(foo.Module(), android.ExportedComponentsInfoProvider).(android.ExportedComponentsInfo)
+ exportedComponentsInfo, _ := android.SingletonModuleProvider(result, foo.Module(), android.ExportedComponentsInfoProvider)
expectedFooExportedComponents := []string{
"foo-removed.api.public.latest",
"foo-removed.api.system.latest",
"foo.api.public.latest",
"foo.api.system.latest",
"foo.stubs",
+ "foo.stubs.exportable",
+ "foo.stubs.exportable.system",
+ "foo.stubs.exportable.test",
"foo.stubs.source",
"foo.stubs.source.system",
"foo.stubs.source.test",
@@ -173,6 +183,9 @@
android.AssertDeepEquals(t, "qux exports (optional)", []string{}, optionalSdkLibs)
}
+ // test if quuz have created the api_contribution module
+ result.ModuleForTests(apiScopePublic.stubsSourceModuleName("quuz")+".api.contribution", "")
+
fooDexJar := result.ModuleForTests("foo", "android_common").Rule("d8")
// tests if kotlinc generated files are NOT excluded from output of foo.
android.AssertStringDoesNotContain(t, "foo dex", fooDexJar.BuildParams.Args["mergeZipsFlags"], "-stripFile META-INF/*.kotlin_module")
@@ -524,6 +537,11 @@
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("sdklib"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
@@ -542,6 +560,7 @@
`sdklib.api.public.latest`,
`sdklib.impl`,
`sdklib.stubs`,
+ `sdklib.stubs.exportable`,
`sdklib.stubs.source`,
`sdklib.xml`,
})
@@ -914,6 +933,11 @@
prepareForJavaTest,
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("sdklib"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
@@ -940,11 +964,13 @@
`sdklib.api.public.latest`,
`sdklib.impl`,
`sdklib.stubs`,
+ `sdklib.stubs.exportable`,
`sdklib.stubs.source`,
`sdklib.xml`,
})
CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{
+ `all_apex_contributions`,
`prebuilt_sdklib.stubs`,
`sdklib.impl`,
// This should be prebuilt_sdklib.stubs but is set to sdklib.stubs because the
@@ -960,6 +986,11 @@
PrepareForTestWithJavaSdkLibraryFiles,
FixtureWithLastReleaseApis("sdklib"),
preparer,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTestWithBp(t, `
java_sdk_library {
name: "sdklib",
@@ -1012,11 +1043,13 @@
`sdklib.api.public.latest`,
`sdklib.impl`,
`sdklib.stubs`,
+ `sdklib.stubs.exportable`,
`sdklib.stubs.source`,
`sdklib.xml`,
})
CheckModuleDependencies(t, result.TestContext, "prebuilt_sdklib", "android_common", []string{
+ `all_apex_contributions`,
`dex2oatd`,
`prebuilt_sdklib.stubs`,
`prebuilt_sdklib.stubs.source`,
@@ -1063,6 +1096,131 @@
})
}
+// If a module is listed in `mainline_module_contributions, it should be used
+// It will supersede any other source vs prebuilt selection mechanism like `prefer` attribute
+func TestSdkLibraryImport_MetadataModuleSupersedesPreferred(t *testing.T) {
+ bp := `
+ apex_contributions {
+ name: "my_mainline_module_contributions",
+ api_domain: "my_mainline_module",
+ contents: [
+ // legacy mechanism prefers the prebuilt
+ // mainline_module_contributions supersedes this since source is listed explicitly
+ "sdklib.prebuilt_preferred_using_legacy_flags",
+
+ // legacy mechanism prefers the source
+ // mainline_module_contributions supersedes this since prebuilt is listed explicitly
+ "prebuilt_sdklib.source_preferred_using_legacy_flags",
+ ],
+ }
+ java_sdk_library {
+ name: "sdklib.prebuilt_preferred_using_legacy_flags",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ public: {
+ enabled: true,
+ },
+ system: {
+ enabled: true,
+ }
+ }
+ java_sdk_library_import {
+ name: "sdklib.prebuilt_preferred_using_legacy_flags",
+ prefer: true, // prebuilt is preferred using legacy mechanism
+ public: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
+ },
+ system: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
+ },
+ }
+ java_sdk_library {
+ name: "sdklib.source_preferred_using_legacy_flags",
+ srcs: ["a.java"],
+ sdk_version: "none",
+ system_modules: "none",
+ public: {
+ enabled: true,
+ },
+ system: {
+ enabled: true,
+ }
+ }
+ java_sdk_library_import {
+ name: "sdklib.source_preferred_using_legacy_flags",
+ prefer: false, // source is preferred using legacy mechanism
+ public: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
+ },
+ system: {
+ jars: ["a.jar"],
+ stub_srcs: ["a.java"],
+ current_api: "current.txt",
+ removed_api: "removed.txt",
+ annotations: "annotations.zip",
+ },
+ }
+
+ // rdeps
+ java_library {
+ name: "public",
+ srcs: ["a.java"],
+ libs: [
+ // this should get source since source is listed in my_mainline_module_contributions
+ "sdklib.prebuilt_preferred_using_legacy_flags.stubs",
+ "sdklib.prebuilt_preferred_using_legacy_flags.stubs.system",
+
+ // this should get prebuilt since source is listed in my_mainline_module_contributions
+ "sdklib.source_preferred_using_legacy_flags.stubs",
+ "sdklib.source_preferred_using_legacy_flags.stubs.system",
+
+ ],
+ }
+ `
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("sdklib.source_preferred_using_legacy_flags", "sdklib.prebuilt_preferred_using_legacy_flags"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_APEX_CONTRIBUTIONS_ADSERVICES": "my_mainline_module_contributions",
+ }
+ }),
+ ).RunTestWithBp(t, bp)
+
+ // Make sure that rdeps get the correct source vs prebuilt based on mainline_module_contributions
+ public := result.ModuleForTests("public", "android_common")
+ rule := public.Output("javac/public.jar")
+ inputs := rule.Implicits.Strings()
+ expectedInputs := []string{
+ // source
+ "out/soong/.intermediates/sdklib.prebuilt_preferred_using_legacy_flags.stubs/android_common/turbine-combined/sdklib.prebuilt_preferred_using_legacy_flags.stubs.jar",
+ "out/soong/.intermediates/sdklib.prebuilt_preferred_using_legacy_flags.stubs.system/android_common/turbine-combined/sdklib.prebuilt_preferred_using_legacy_flags.stubs.system.jar",
+
+ // prebuilt
+ "out/soong/.intermediates/prebuilt_sdklib.source_preferred_using_legacy_flags.stubs/android_common/combined/sdklib.source_preferred_using_legacy_flags.stubs.jar",
+ "out/soong/.intermediates/prebuilt_sdklib.source_preferred_using_legacy_flags.stubs.system/android_common/combined/sdklib.source_preferred_using_legacy_flags.stubs.system.jar",
+ }
+ for _, expected := range expectedInputs {
+ if !android.InList(expected, inputs) {
+ t.Errorf("expected %q to contain %q", inputs, expected)
+ }
+ }
+}
+
func TestJavaSdkLibraryEnforce(t *testing.T) {
partitionToBpOption := func(partition string) string {
switch partition {
@@ -1291,7 +1449,7 @@
for _, tt := range testCases {
t.Run(tt.module, func(t *testing.T) {
- m := result.ModuleForTests(tt.module+".stubs", "android_common").Module().(*Library)
+ m := result.ModuleForTests(apiScopePublic.exportableStubsLibraryModuleName(tt.module), "android_common").Module().(*Library)
dists := m.Dists()
if len(dists) != 1 {
t.Fatalf("expected exactly 1 dist entry, got %d", len(dists))
@@ -1416,6 +1574,32 @@
android.AssertStringListContains(t, "foo stubs should depend on bar-lib", fooStubsSources.Javadoc.properties.Libs, "bar-lib")
}
+func TestJavaSdkLibrary_Scope_Libs_PassedToDroidstubs(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ ).RunTestWithBp(t, `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java"],
+ public: {
+ enabled: true,
+ libs: ["bar-lib"],
+ },
+ }
+
+ java_library {
+ name: "bar-lib",
+ srcs: ["b.java"],
+ }
+ `)
+
+ // The foo.stubs.source should depend on bar-lib
+ fooStubsSources := result.ModuleForTests("foo.stubs.source", "android_common").Module().(*Droidstubs)
+ android.AssertStringListContains(t, "foo stubs should depend on bar-lib", fooStubsSources.Javadoc.properties.Libs, "bar-lib")
+}
+
func TestJavaSdkLibrary_ApiLibrary(t *testing.T) {
result := android.GroupFixturePreparers(
prepareForJavaTest,
@@ -1503,3 +1687,88 @@
}
`)
}
+
+func TestSdkLibraryDependency(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithPrebuiltApis(map[string][]string{
+ "30": {"bar", "foo"},
+ }),
+ ).RunTestWithBp(t,
+ `
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ }
+
+ java_sdk_library {
+ name: "bar",
+ srcs: ["c.java", "b.java"],
+ libs: [
+ "foo",
+ ],
+ uses_libs: [
+ "foo",
+ ],
+ }
+`)
+
+ barPermissions := result.ModuleForTests("bar.xml", "android_common").Rule("java_sdk_xml")
+
+ android.AssertStringDoesContain(t, "bar.xml java_sdk_xml command", barPermissions.RuleParams.Command, `dependency=\"foo\"`)
+}
+
+func TestSdkLibraryExportableStubsLibrary(t *testing.T) {
+ result := android.GroupFixturePreparers(
+ prepareForJavaTest,
+ PrepareForTestWithJavaSdkLibraryFiles,
+ FixtureWithLastReleaseApis("foo"),
+ android.FixtureModifyConfig(func(config android.Config) {
+ config.SetApiLibraries([]string{"foo"})
+ }),
+ ).RunTestWithBp(t, `
+ aconfig_declarations {
+ name: "bar",
+ package: "com.example.package",
+ srcs: [
+ "bar.aconfig",
+ ],
+ }
+ java_sdk_library {
+ name: "foo",
+ srcs: ["a.java", "b.java"],
+ api_packages: ["foo"],
+ system: {
+ enabled: true,
+ },
+ module_lib: {
+ enabled: true,
+ },
+ test: {
+ enabled: true,
+ },
+ aconfig_declarations: [
+ "bar",
+ ],
+ }
+ `)
+
+ exportableStubsLibraryModuleName := apiScopePublic.exportableStubsLibraryModuleName("foo")
+ exportableSourceStubsLibraryModuleName := apiScopePublic.exportableSourceStubsLibraryModuleName("foo")
+
+ // Check modules generation
+ topLevelModule := result.ModuleForTests(exportableStubsLibraryModuleName, "android_common")
+ result.ModuleForTests(exportableSourceStubsLibraryModuleName, "android_common")
+
+ // Check static lib dependency
+ android.AssertBoolEquals(t, "exportable top level stubs library module depends on the"+
+ "exportable source stubs library module", true,
+ CheckModuleHasDependency(t, result.TestContext, exportableStubsLibraryModuleName,
+ "android_common", exportableSourceStubsLibraryModuleName),
+ )
+ android.AssertArrayString(t, "exportable source stub library is a static lib of the"+
+ "top level exportable stubs library", []string{exportableSourceStubsLibraryModuleName},
+ topLevelModule.Module().(*Library).properties.Static_libs)
+}
diff --git a/java/sdk_version_test.go b/java/sdk_version_test.go
new file mode 100644
index 0000000..88351d2
--- /dev/null
+++ b/java/sdk_version_test.go
@@ -0,0 +1,66 @@
+// Copyright 2024 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 java
+
+import (
+ "testing"
+
+ "android/soong/android"
+)
+
+func stringPtr(v string) *string {
+ return &v
+}
+
+func TestSystemSdkFromVendor(t *testing.T) {
+ fixtures := android.GroupFixturePreparers(
+ PrepareForTestWithJavaDefaultModules,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.Platform_sdk_version = intPtr(34)
+ variables.Platform_sdk_codename = stringPtr("VanillaIceCream")
+ variables.Platform_version_active_codenames = []string{"VanillaIceCream"}
+ variables.Platform_systemsdk_versions = []string{"33", "34", "VanillaIceCream"}
+ variables.DeviceSystemSdkVersions = []string{"VanillaIceCream"}
+ }),
+ FixtureWithPrebuiltApis(map[string][]string{
+ "33": {},
+ "34": {},
+ "35": {},
+ }),
+ )
+
+ fixtures.ExtendWithErrorHandler(android.FixtureExpectsAtLeastOneErrorMatchingPattern("incompatible sdk version")).
+ RunTestWithBp(t, `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ vendor: true,
+ sdk_version: "system_35",
+ }`)
+
+ result := fixtures.RunTestWithBp(t, `
+ android_app {
+ name: "foo",
+ srcs: ["a.java"],
+ vendor: true,
+ sdk_version: "system_current",
+ }`)
+ fooModule := result.ModuleForTests("foo", "android_common")
+ fooClasspath := fooModule.Rule("javac").Args["classpath"]
+
+ android.AssertStringDoesContain(t, "foo classpath", fooClasspath, "prebuilts/sdk/34/system/android.jar")
+ android.AssertStringDoesNotContain(t, "foo classpath", fooClasspath, "prebuilts/sdk/35/system/android.jar")
+ android.AssertStringDoesNotContain(t, "foo classpath", fooClasspath, "prebuilts/sdk/current/system/android.jar")
+}
diff --git a/java/support_libraries.go b/java/support_libraries.go
index af7c3c2..c483fc1 100644
--- a/java/support_libraries.go
+++ b/java/support_libraries.go
@@ -32,7 +32,7 @@
dir := ctx.ModuleDir(module)
switch {
case strings.HasPrefix(dir, "prebuilts/sdk/current/extras"),
- dir == "prebuilts/sdk/current/androidx",
+ strings.HasPrefix(dir, "prebuilts/sdk/current/androidx"),
dir == "prebuilts/sdk/current/car",
dir == "prebuilts/sdk/current/optional",
dir == "prebuilts/sdk/current/support":
diff --git a/java/system_modules.go b/java/system_modules.go
index 0efa1a4..f344648 100644
--- a/java/system_modules.go
+++ b/java/system_modules.go
@@ -55,7 +55,8 @@
`${config.MergeZipsCmd} -j ${workDir}/module.jar ${workDir}/classes.jar $in && ` +
// Note: The version of the java.base module created must match the version
// of the jlink tool which consumes it.
- `${config.JmodCmd} create --module-version ${config.JlinkVersion} --target-platform android ` +
+ // Use LINUX-OTHER to be compatible with JDK 21+ (b/294137077)
+ `${config.JmodCmd} create --module-version ${config.JlinkVersion} --target-platform LINUX-OTHER ` +
` --class-path ${workDir}/module.jar ${workDir}/jmod/java.base.jmod && ` +
`${config.JlinkCmd} --module-path ${workDir}/jmod --add-modules java.base --output ${outDir} ` +
// Note: The system-modules jlink plugin is disabled because (a) it is not
@@ -159,7 +160,7 @@
var jars android.Paths
ctx.VisitDirectDepsWithTag(systemModulesLibsTag, func(module android.Module) {
- dep, _ := ctx.OtherModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ dep, _ := android.OtherModuleProvider(ctx, module, JavaInfoProvider)
jars = append(jars, dep.HeaderJars...)
})
diff --git a/java/system_modules_test.go b/java/system_modules_test.go
index 7b5a386..2ceca5d 100644
--- a/java/system_modules_test.go
+++ b/java/system_modules_test.go
@@ -24,7 +24,7 @@
paths := []string{}
for _, moduleName := range moduleNames {
module := result.Module(moduleName, "android_common")
- info := result.ModuleProvider(module, JavaInfoProvider).(JavaInfo)
+ info, _ := android.SingletonModuleProvider(result, module, JavaInfoProvider)
paths = append(paths, info.HeaderJars.RelativeToTop().Strings()...)
}
return paths
diff --git a/java/systemserver_classpath_fragment.go b/java/systemserver_classpath_fragment.go
index 17d301b..59c5466 100644
--- a/java/systemserver_classpath_fragment.go
+++ b/java/systemserver_classpath_fragment.go
@@ -87,9 +87,6 @@
ClasspathFragmentBase
properties systemServerClasspathFragmentProperties
-
- // Collect the module directory for IDE info in java/jdeps.go.
- modulePaths []string
}
func (s *SystemServerClasspathModule) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
@@ -129,9 +126,6 @@
configuredJars = configuredJars.AppendList(&standaloneConfiguredJars)
classpathJars = append(classpathJars, standaloneClasspathJars...)
s.classpathFragmentBase().generateClasspathProtoBuildActions(ctx, configuredJars, classpathJars)
-
- // Collect the module directory for IDE info in java/jdeps.go.
- s.modulePaths = append(s.modulePaths, ctx.ModuleDir())
}
func (s *SystemServerClasspathModule) configuredJars(ctx android.ModuleContext) android.ConfiguredJarList {
@@ -242,7 +236,6 @@
func (s *SystemServerClasspathModule) IDEInfo(dpInfo *android.IdeInfo) {
dpInfo.Deps = append(dpInfo.Deps, s.properties.Contents...)
dpInfo.Deps = append(dpInfo.Deps, s.properties.Standalone_contents...)
- dpInfo.Paths = append(dpInfo.Paths, s.modulePaths...)
}
type systemServerClasspathFragmentMemberType struct {
@@ -320,6 +313,10 @@
return nil
}
+func (module *prebuiltSystemServerClasspathModule) UseProfileGuidedDexpreopt() bool {
+ return false
+}
+
var _ android.RequiredFilesFromPrebuiltApex = (*prebuiltSystemServerClasspathModule)(nil)
func prebuiltSystemServerClasspathModuleFactory() android.Module {
diff --git a/java/test_spec_test.go b/java/test_spec_test.go
new file mode 100644
index 0000000..4144dad
--- /dev/null
+++ b/java/test_spec_test.go
@@ -0,0 +1,122 @@
+package java
+
+import (
+ "strings"
+ "testing"
+
+ "android/soong/android"
+ soongTesting "android/soong/testing"
+ "android/soong/testing/test_spec_proto"
+ "google.golang.org/protobuf/proto"
+)
+
+func TestTestSpec(t *testing.T) {
+ bp := `test_spec {
+ name: "module-name",
+ teamId: "12345",
+ tests: [
+ "java-test-module-name-one",
+ "java-test-module-name-two"
+ ]
+ }
+
+ java_test {
+ name: "java-test-module-name-one",
+ }
+
+ java_test {
+ name: "java-test-module-name-two",
+ }`
+ result := runTestSpecTest(t, android.FixtureExpectsNoErrors, bp)
+
+ module := result.ModuleForTests("module-name", "")
+
+ // Check that the provider has the right contents
+ data, _ := android.SingletonModuleProvider(result, module.Module(), soongTesting.TestSpecProviderKey)
+ if !strings.HasSuffix(
+ data.IntermediatePath.String(), "/intermediateTestSpecMetadata.pb",
+ ) {
+ t.Errorf(
+ "Missing intermediates path in provider: %s",
+ data.IntermediatePath.String(),
+ )
+ }
+
+ metadata := android.ContentFromFileRuleForTests(t, result.TestContext,
+ module.Output(data.IntermediatePath.String()))
+
+ metadataList := make([]*test_spec_proto.TestSpec_OwnershipMetadata, 0, 2)
+ teamId := "12345"
+ bpFilePath := "Android.bp"
+ targetNames := []string{
+ "java-test-module-name-one", "java-test-module-name-two",
+ }
+
+ for _, test := range targetNames {
+ targetName := test
+ metadata := test_spec_proto.TestSpec_OwnershipMetadata{
+ TrendyTeamId: &teamId,
+ TargetName: &targetName,
+ Path: &bpFilePath,
+ }
+ metadataList = append(metadataList, &metadata)
+ }
+ testSpecMetadata := test_spec_proto.TestSpec{OwnershipMetadataList: metadataList}
+ protoData, _ := proto.Marshal(&testSpecMetadata)
+ expectedMetadata := string(protoData)
+
+ if metadata != expectedMetadata {
+ t.Errorf(
+ "Retrieved metadata: %s doesn't contain expectedMetadata: %s", metadata,
+ expectedMetadata,
+ )
+ }
+
+ // Tests for all_test_spec singleton.
+ singleton := result.SingletonForTests("all_test_specs")
+ rule := singleton.Rule("all_test_specs_rule")
+ prebuiltOs := result.Config.PrebuiltOS()
+ expectedCmd := "out/soong/host/" + prebuiltOs + "/bin/metadata -rule test_spec -inputFile out/soong/all_test_spec_paths.rsp -outputFile out/soong/ownership/all_test_specs.pb"
+ expectedOutputFile := "out/soong/ownership/all_test_specs.pb"
+ expectedInputFile := "out/soong/.intermediates/module-name/intermediateTestSpecMetadata.pb"
+ if !strings.Contains(
+ strings.TrimSpace(rule.Output.String()),
+ expectedOutputFile,
+ ) {
+ t.Errorf(
+ "Retrieved singletonOutputFile: %s is not equal to expectedSingletonOutputFile: %s",
+ rule.Output.String(), expectedOutputFile,
+ )
+ }
+
+ if !strings.Contains(
+ strings.TrimSpace(rule.Inputs[0].String()),
+ expectedInputFile,
+ ) {
+ t.Errorf(
+ "Retrieved singletonInputFile: %s is not equal to expectedSingletonInputFile: %s",
+ rule.Inputs[0].String(), expectedInputFile,
+ )
+ }
+
+ if !strings.Contains(
+ strings.TrimSpace(rule.RuleParams.Command),
+ expectedCmd,
+ ) {
+ t.Errorf(
+ "Retrieved cmd: %s is not equal to expectedCmd: %s",
+ rule.RuleParams.Command, expectedCmd,
+ )
+ }
+}
+
+func runTestSpecTest(
+ t *testing.T, errorHandler android.FixtureErrorHandler, bp string,
+) *android.TestResult {
+ return android.GroupFixturePreparers(
+ soongTesting.PrepareForTestWithTestingBuildComponents,
+ PrepareForIntegrationTestWithJava,
+ ).
+ ExtendWithErrorHandler(errorHandler).
+ RunTestWithBp(t, bp)
+}
diff --git a/java/testing.go b/java/testing.go
index f2bcccf..04e8c73 100644
--- a/java/testing.go
+++ b/java/testing.go
@@ -73,10 +73,15 @@
// Needed for various deps defined in GatherRequiredDepsForTest()
defaultJavaDir + "/a.java": nil,
defaultJavaDir + "/api/current.txt": nil,
+ defaultJavaDir + "/api/removed.txt": nil,
defaultJavaDir + "/api/system-current.txt": nil,
+ defaultJavaDir + "/api/system-removed.txt": nil,
defaultJavaDir + "/api/test-current.txt": nil,
+ defaultJavaDir + "/api/test-removed.txt": nil,
defaultJavaDir + "/api/module-lib-current.txt": nil,
+ defaultJavaDir + "/api/module-lib-removed.txt": nil,
defaultJavaDir + "/api/system-server-current.txt": nil,
+ defaultJavaDir + "/api/system-server-removed.txt": nil,
// Needed for R8 rules on apps
"build/make/core/proguard.flags": nil,
@@ -113,8 +118,6 @@
dexpreopt.PrepareForTestByEnablingDexpreopt,
)
-var PrepareForTestWithOverlayBuildComponents = android.FixtureRegisterWithContext(registerOverlayBuildComponents)
-
// Prepare a fixture to use all java module types, mutators and singletons fully.
//
// This should only be used by tests that want to run with as much of the build enabled as possible.
@@ -380,6 +383,7 @@
RegisterSystemModulesBuildComponents(ctx)
registerSystemserverClasspathBuildComponents(ctx)
registerLintBuildComponents(ctx)
+ android.RegisterApexContributionsBuildComponents(ctx)
}
// gatherRequiredDepsForTest gathers the module definitions used by
@@ -403,6 +407,14 @@
"legacy.core.platform.api.stubs",
"stable.core.platform.api.stubs",
+ "android_stubs_current_exportable",
+ "android_system_stubs_current_exportable",
+ "android_test_stubs_current_exportable",
+ "android_module_lib_stubs_current_exportable",
+ "android_system_server_stubs_current_exportable",
+ "core.current.stubs.exportable",
+ "legacy.core.platform.api.stubs.exportable",
+
"kotlin-stdlib",
"kotlin-stdlib-jdk7",
"kotlin-stdlib-jdk8",
@@ -410,6 +422,7 @@
"stub-annotations",
"aconfig-annotations-lib",
+ "unsupportedappusage",
}
for _, extra := range extraModules {
@@ -424,30 +437,97 @@
`, extra)
}
- extraApiLibraryModules := map[string]string{
- "android_stubs_current.from-text": "api/current.txt",
- "android_system_stubs_current.from-text": "api/system-current.txt",
- "android_test_stubs_current.from-text": "api/test-current.txt",
- "android_module_lib_stubs_current.from-text": "api/module-lib-current.txt",
- "android_module_lib_stubs_current_full.from-text": "api/module-lib-current.txt",
- "android_system_server_stubs_current.from-text": "api/system-server-current.txt",
- "core.current.stubs.from-text": "api/current.txt",
- "legacy.core.platform.api.stubs.from-text": "api/current.txt",
- "stable.core.platform.api.stubs.from-text": "api/current.txt",
- "core-lambda-stubs.from-text": "api/current.txt",
- "android-non-updatable.stubs.from-text": "api/current.txt",
- "android-non-updatable.stubs.system.from-text": "api/system-current.txt",
- "android-non-updatable.stubs.test.from-text": "api/test-current.txt",
- "android-non-updatable.stubs.module_lib.from-text": "api/module-lib-current.txt",
+ type droidstubsStruct struct {
+ name string
+ apiSurface string
+ apiFile string
+ removedFile string
}
- for libName, apiFile := range extraApiLibraryModules {
+ var publicDroidstubs = droidstubsStruct{
+ name: "api-stubs-docs-non-updatable",
+ apiSurface: "public",
+ apiFile: "api/current.txt",
+ removedFile: "api/removed.txt",
+ }
+ var systemDroidstubs = droidstubsStruct{
+ name: "system-api-stubs-docs-non-updatable",
+ apiSurface: "system",
+ apiFile: "api/system-current.txt",
+ removedFile: "api/system-removed.txt",
+ }
+ var testDroidstubs = droidstubsStruct{
+ name: "test-api-stubs-docs-non-updatable",
+ apiSurface: "test",
+ apiFile: "api/test-current.txt",
+ removedFile: "api/test-removed.txt",
+ }
+ var moduleLibDroidstubs = droidstubsStruct{
+ name: "module-lib-api-stubs-docs-non-updatable",
+ apiSurface: "module-lib",
+ apiFile: "api/module-lib-current.txt",
+ removedFile: "api/module-lib-removed.txt",
+ }
+ var systemServerDroidstubs = droidstubsStruct{
+ // This module does not exist but is named this way for consistency
+ name: "system-server-api-stubs-docs-non-updatable",
+ apiSurface: "system-server",
+ apiFile: "api/system-server-current.txt",
+ removedFile: "api/system-server-removed.txt",
+ }
+ var droidstubsStructs = []droidstubsStruct{
+ publicDroidstubs,
+ systemDroidstubs,
+ testDroidstubs,
+ moduleLibDroidstubs,
+ systemServerDroidstubs,
+ }
+
+ extraApiLibraryModules := map[string]droidstubsStruct{
+ "android_stubs_current.from-text": publicDroidstubs,
+ "android_system_stubs_current.from-text": systemDroidstubs,
+ "android_test_stubs_current.from-text": testDroidstubs,
+ "android_module_lib_stubs_current.from-text": moduleLibDroidstubs,
+ "android_module_lib_stubs_current_full.from-text": moduleLibDroidstubs,
+ "android_system_server_stubs_current.from-text": systemServerDroidstubs,
+ "core.current.stubs.from-text": publicDroidstubs,
+ "legacy.core.platform.api.stubs.from-text": publicDroidstubs,
+ "stable.core.platform.api.stubs.from-text": publicDroidstubs,
+ "core-lambda-stubs.from-text": publicDroidstubs,
+ "android-non-updatable.stubs.from-text": publicDroidstubs,
+ "android-non-updatable.stubs.system.from-text": systemDroidstubs,
+ "android-non-updatable.stubs.test.from-text": testDroidstubs,
+ "android-non-updatable.stubs.module_lib.from-text": moduleLibDroidstubs,
+ "android-non-updatable.stubs.test_module_lib": moduleLibDroidstubs,
+ }
+
+ for _, droidstubs := range droidstubsStructs {
+ bp += fmt.Sprintf(`
+ droidstubs {
+ name: "%s",
+ api_surface: "%s",
+ check_api: {
+ current: {
+ api_file: "%s",
+ removed_api_file: "%s",
+ }
+ }
+ }
+ `,
+ droidstubs.name,
+ droidstubs.apiSurface,
+ droidstubs.apiFile,
+ droidstubs.removedFile,
+ )
+ }
+
+ for libName, droidstubs := range extraApiLibraryModules {
bp += fmt.Sprintf(`
java_api_library {
name: "%s",
- api_files: ["%s"],
+ api_contributions: ["%s"],
}
- `, libName, apiFile)
+ `, libName, droidstubs.name+".api.contribution")
}
bp += `
@@ -499,10 +579,15 @@
}
`
+ bp += `
+ all_apex_contributions {
+ name: "all_apex_contributions",
+ }
+`
return bp
}
-func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
+func getModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string) []string {
t.Helper()
module := ctx.ModuleForTests(name, variant).Module()
deps := []string{}
@@ -511,11 +596,29 @@
})
sort.Strings(deps)
+ return deps
+}
+
+// CheckModuleDependencies checks if the expected dependencies of the module are
+// identical to the actual dependencies.
+func CheckModuleDependencies(t *testing.T, ctx *android.TestContext, name, variant string, expected []string) {
+ deps := getModuleDependencies(t, ctx, name, variant)
+
if actual := deps; !reflect.DeepEqual(expected, actual) {
t.Errorf("expected %#q, found %#q", expected, actual)
}
}
+// CheckModuleHasDependency returns true if the module depends on the expected dependency.
+func CheckModuleHasDependency(t *testing.T, ctx *android.TestContext, name, variant string, expected string) bool {
+ for _, dep := range getModuleDependencies(t, ctx, name, variant) {
+ if dep == expected {
+ return true
+ }
+ }
+ return false
+}
+
// CheckPlatformBootclasspathModules returns the apex:module pair for the modules depended upon by
// the platform-bootclasspath module.
func CheckPlatformBootclasspathModules(t *testing.T, result *android.TestResult, name string, expected []string) {
@@ -528,7 +631,7 @@
func CheckClasspathFragmentProtoContentInfoProvider(t *testing.T, result *android.TestResult, generated bool, contents, outputFilename, installDir string) {
t.Helper()
p := result.Module("platform-bootclasspath", "android_common").(*platformBootclasspathModule)
- info := result.ModuleProvider(p, ClasspathFragmentProtoContentInfoProvider).(ClasspathFragmentProtoContentInfo)
+ info, _ := android.SingletonModuleProvider(result, p, ClasspathFragmentProtoContentInfoProvider)
android.AssertBoolEquals(t, "classpath proto generated", generated, info.ClasspathFragmentProtoGenerated)
android.AssertStringEquals(t, "classpath proto contents", contents, info.ClasspathFragmentProtoContents.String())
@@ -548,7 +651,7 @@
func apexNamePairFromModule(ctx *android.TestContext, module android.Module) string {
name := module.Name()
var apex string
- apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.SingletonModuleProvider(ctx, module, android.ApexInfoProvider)
if apexInfo.IsForPlatform() {
apex = "platform"
} else {
diff --git a/java/tradefed.go b/java/tradefed.go
index ebbdec1..349b327 100644
--- a/java/tradefed.go
+++ b/java/tradefed.go
@@ -30,8 +30,8 @@
return module
}
-func tradefedJavaLibraryInstall(ctx android.ModuleContext, path android.Path) android.Paths {
+func tradefedJavaLibraryInstall(ctx android.ModuleContext, path android.Path) android.InstallPaths {
installedPath := ctx.InstallFile(android.PathForModuleInstall(ctx, "tradefed"),
ctx.ModuleName()+".jar", path)
- return android.Paths{installedPath}
+ return android.InstallPaths{installedPath}
}
diff --git a/kernel/prebuilt_kernel_modules.go b/kernel/prebuilt_kernel_modules.go
index 5bcca04..e200ee2 100644
--- a/kernel/prebuilt_kernel_modules.go
+++ b/kernel/prebuilt_kernel_modules.go
@@ -50,6 +50,9 @@
// Kernel version that these modules are for. Kernel modules are installed to
// /lib/modules/<kernel_version> directory in the corresponding partition. Default is "".
Kernel_version *string
+
+ // Whether this module is directly installable to one of the partitions. Default is true
+ Installable *bool
}
// prebuilt_kernel_modules installs a set of prebuilt kernel module files to the correct directory.
@@ -62,6 +65,10 @@
return module
}
+func (pkm *prebuiltKernelModules) installable() bool {
+ return proptools.BoolDefault(pkm.properties.Installable, true)
+}
+
func (pkm *prebuiltKernelModules) KernelVersion() string {
return proptools.StringDefault(pkm.properties.Kernel_version, "")
}
@@ -71,6 +78,9 @@
}
func (pkm *prebuiltKernelModules) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ if !pkm.installable() {
+ pkm.SkipInstall()
+ }
modules := android.PathsForModuleSrc(ctx, pkm.properties.Srcs)
depmodOut := runDepmod(ctx, modules)
diff --git a/linkerconfig/linkerconfig.go b/linkerconfig/linkerconfig.go
index 165697d..78b62d9 100644
--- a/linkerconfig/linkerconfig.go
+++ b/linkerconfig/linkerconfig.go
@@ -19,11 +19,9 @@
"sort"
"strings"
- "android/soong/ui/metrics/bp2build_metrics_proto"
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel"
"android/soong/cc"
"android/soong/etc"
)
@@ -54,7 +52,6 @@
type linkerConfig struct {
android.ModuleBase
- android.BazelModuleBase
properties linkerConfigProperties
outputFilePath android.OutputPath
@@ -103,29 +100,6 @@
ctx.InstallFile(l.installDirPath, l.outputFilePath.Base(), l.outputFilePath)
}
-type linkerConfigAttributes struct {
- Src bazel.LabelAttribute
-}
-
-func (l *linkerConfig) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- if l.properties.Src == nil {
- ctx.PropertyErrorf("src", "empty src is not supported")
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_UNSUPPORTED, "")
- return
- }
- src := android.BazelLabelForModuleSrcSingle(ctx, *l.properties.Src)
- targetModuleProperties := bazel.BazelTargetModuleProperties{
- Rule_class: "linker_config",
- Bzl_load_location: "//build/bazel/rules:linker_config.bzl",
- }
- ctx.CreateBazelTargetModule(
- targetModuleProperties,
- android.CommonAttributes{Name: l.Name()},
- &linkerConfigAttributes{
- Src: bazel.LabelAttribute{Value: &src},
- })
-}
-
func BuildLinkerConfig(ctx android.ModuleContext, builder *android.RuleBuilder,
input android.Path, otherModules []android.Module, output android.OutputPath) {
@@ -166,12 +140,11 @@
// linker_config generates protobuf file from json file. This protobuf file will be used from
// linkerconfig while generating ld.config.txt. Format of this file can be found from
-// https://android.googlesource.com/platform/system/linkerconfig/+/master/README.md
+// https://android.googlesource.com/platform/system/linkerconfig/+/main/README.md
func LinkerConfigFactory() android.Module {
m := &linkerConfig{}
m.AddProperties(&m.properties)
android.InitAndroidArchModule(m, android.HostAndDeviceSupported, android.MultilibFirst)
- android.InitBazelModule(m)
return m
}
diff --git a/linkerconfig/proto/linker_config.proto b/linkerconfig/proto/linker_config.proto
index dccf311..fcbd1c5 100644
--- a/linkerconfig/proto/linker_config.proto
+++ b/linkerconfig/proto/linker_config.proto
@@ -16,7 +16,7 @@
// This format file defines configuration file for linkerconfig. Details on this
// format can be found from
-// https://android.googlesource.com/platform/system/linkerconfig/+/master/README.md
+// https://android.googlesource.com/platform/system/linkerconfig/+/main/README.md
syntax = "proto3";
diff --git a/mk2rbc/mk2rbc.go b/mk2rbc/mk2rbc.go
index 8225df6..78ab771 100644
--- a/mk2rbc/mk2rbc.go
+++ b/mk2rbc/mk2rbc.go
@@ -635,6 +635,13 @@
case "+=":
asgn.flavor = asgnAppend
case "?=":
+ if _, ok := lhs.(*productConfigVariable); ok {
+ // Make sets all product configuration variables to empty strings before running product
+ // config makefiles. ?= will have no effect on a variable that has been assigned before,
+ // even if assigned to an empty string. So just skip emitting any code for this
+ // assignment.
+ return nil
+ }
asgn.flavor = asgnMaybeSet
default:
panic(fmt.Errorf("unexpected assignment type %s", a.Type))
@@ -941,6 +948,8 @@
func (ctx *parseContext) handleInclude(v *mkparser.Directive) []starlarkNode {
loadAlways := v.Name[0] != '-'
+ v.Args.TrimRightSpaces()
+ v.Args.TrimLeftSpaces()
return ctx.handleSubConfig(v, ctx.parseMakeString(v, v.Args), loadAlways, func(im inheritedModule) starlarkNode {
return &includeNode{im, loadAlways}
})
diff --git a/mk2rbc/mk2rbc_test.go b/mk2rbc/mk2rbc_test.go
index 7e68026..0c4d213 100644
--- a/mk2rbc/mk2rbc_test.go
+++ b/mk2rbc/mk2rbc_test.go
@@ -193,6 +193,31 @@
},
{
+ desc: "Include with trailing whitespace",
+ mkname: "product.mk",
+ in: `
+# has a trailing whitespace after cfg.mk
+include vendor/$(foo)/cfg.mk
+`,
+ expected: `# has a trailing whitespace after cfg.mk
+load("//build/make/core:product_config.rbc", "rblf")
+load("//vendor/foo1:cfg.star|init", _cfg_init = "init")
+load("//vendor/bar/baz:cfg.star|init", _cfg1_init = "init")
+
+def init(g, handle):
+ cfg = rblf.cfg(handle)
+ _entry = {
+ "vendor/foo1/cfg.mk": ("vendor/foo1/cfg", _cfg_init),
+ "vendor/bar/baz/cfg.mk": ("vendor/bar/baz/cfg", _cfg1_init),
+ }.get("vendor/%s/cfg.mk" % _foo)
+ (_varmod, _varmod_init) = _entry if _entry else (None, None)
+ if not _varmod_init:
+ rblf.mkerror("product.mk", "Cannot find %s" % ("vendor/%s/cfg.mk" % _foo))
+ _varmod_init(g, handle)
+`,
+ },
+
+ {
desc: "Synonymous inherited configurations",
mkname: "path/product.mk",
in: `
@@ -898,8 +923,6 @@
cfg["PRODUCT_LIST2"] += ["a"]
cfg["PRODUCT_LIST1"] += ["b"]
cfg["PRODUCT_LIST2"] += ["b"]
- if cfg.get("PRODUCT_LIST3") == None:
- cfg["PRODUCT_LIST3"] = ["a"]
cfg["PRODUCT_LIST1"] = ["c"]
g.setdefault("PLATFORM_LIST", [])
g["PLATFORM_LIST"] += ["x"]
@@ -941,9 +964,10 @@
PRODUCT_LIST2 ?= a $(PRODUCT_LIST2)
PRODUCT_LIST3 += a
-# Now doing them again should not have a setdefault because they've already been set
+# Now doing them again should not have a setdefault because they've already been set, except 2
+# which did not emit an assignment before
PRODUCT_LIST1 = a $(PRODUCT_LIST1)
-PRODUCT_LIST2 ?= a $(PRODUCT_LIST2)
+PRODUCT_LIST2 = a $(PRODUCT_LIST2)
PRODUCT_LIST3 += a
`,
expected: `# All of these should have a setdefault because they're self-referential and not defined before
@@ -954,18 +978,15 @@
rblf.setdefault(handle, "PRODUCT_LIST1")
cfg["PRODUCT_LIST1"] = (["a"] +
cfg.get("PRODUCT_LIST1", []))
- if cfg.get("PRODUCT_LIST2") == None:
- rblf.setdefault(handle, "PRODUCT_LIST2")
- cfg["PRODUCT_LIST2"] = (["a"] +
- cfg.get("PRODUCT_LIST2", []))
rblf.setdefault(handle, "PRODUCT_LIST3")
cfg["PRODUCT_LIST3"] += ["a"]
- # Now doing them again should not have a setdefault because they've already been set
+ # Now doing them again should not have a setdefault because they've already been set, except 2
+ # which did not emit an assignment before
cfg["PRODUCT_LIST1"] = (["a"] +
cfg["PRODUCT_LIST1"])
- if cfg.get("PRODUCT_LIST2") == None:
- cfg["PRODUCT_LIST2"] = (["a"] +
- cfg["PRODUCT_LIST2"])
+ rblf.setdefault(handle, "PRODUCT_LIST2")
+ cfg["PRODUCT_LIST2"] = (["a"] +
+ cfg.get("PRODUCT_LIST2", []))
cfg["PRODUCT_LIST3"] += ["a"]
`,
},
diff --git a/mk2rbc/variable.go b/mk2rbc/variable.go
index 0a26ed8..95e1f8e 100644
--- a/mk2rbc/variable.go
+++ b/mk2rbc/variable.go
@@ -109,14 +109,11 @@
}
emitAppend()
case asgnMaybeSet:
- gctx.writef("if cfg.get(%q) == None:", pcv.nam)
- gctx.indentLevel++
- gctx.newLine()
- if needsSetDefault {
- emitSetDefault()
- }
- emitAssignment()
- gctx.indentLevel--
+ // In mk2rbc.go we never emit a maybeSet assignment for product config variables, because
+ // they are set to empty strings before running product config.
+ panic("Should never get here")
+ default:
+ panic("Unknown assignment flavor")
}
gctx.setHasBeenAssigned(&pcv)
diff --git a/multitree/api_imports.go b/multitree/api_imports.go
index 07ec7bc..51b9e07 100644
--- a/multitree/api_imports.go
+++ b/multitree/api_imports.go
@@ -64,7 +64,7 @@
SharedLibs, HeaderLibs, ApexSharedLibs map[string]string
}
-var ApiImportsProvider = blueprint.NewMutatorProvider(ApiImportInfo{}, "deps")
+var ApiImportsProvider = blueprint.NewMutatorProvider[ApiImportInfo]("deps")
// Store module lists into ApiImportInfo and share it over mutator provider.
func (imports *ApiImports) DepsMutator(ctx android.BottomUpMutatorContext) {
@@ -81,7 +81,7 @@
headerLibs := generateNameMapWithSuffix(imports.properties.Header_libs)
apexSharedLibs := generateNameMapWithSuffix(imports.properties.Apex_shared_libs)
- ctx.SetProvider(ApiImportsProvider, ApiImportInfo{
+ android.SetProvider(ctx, ApiImportsProvider, ApiImportInfo{
SharedLibs: sharedLibs,
HeaderLibs: headerLibs,
ApexSharedLibs: apexSharedLibs,
diff --git a/phony/phony.go b/phony/phony.go
index 760b79b..b8dbd00 100644
--- a/phony/phony.go
+++ b/phony/phony.go
@@ -24,6 +24,7 @@
func init() {
android.RegisterModuleType("phony", PhonyFactory)
+ android.RegisterModuleType("phony_rule", PhonyRuleFactory)
}
type phony struct {
@@ -52,7 +53,6 @@
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)", " # phony.phony")
fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
fmt.Fprintln(w, "LOCAL_MODULE :=", name)
- data.Entries.WriteLicenseVariables(w)
if p.Host() {
fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
}
@@ -68,7 +68,48 @@
fmt.Fprintln(w, "LOCAL_TARGET_REQUIRED_MODULES :=",
strings.Join(p.targetRequiredModuleNames, " "))
}
+ // AconfigUpdateAndroidMkData may have added elements to Extra. Process them here.
+ for _, extra := range data.Extra {
+ extra(w, nil)
+ }
fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
},
}
}
+
+type PhonyRule struct {
+ android.ModuleBase
+
+ properties PhonyProperties
+}
+
+type PhonyProperties struct {
+ // The Phony_deps is the set of all dependencies for this target,
+ // and it can function similarly to .PHONY in a makefile.
+ // Additionally, dependencies within it can even include genrule.
+ Phony_deps []string
+}
+
+// The phony_rule provides functionality similar to the .PHONY in a makefile.
+// It can create a phony target and include relevant dependencies associated with it.
+func PhonyRuleFactory() android.Module {
+ module := &PhonyRule{}
+ android.InitAndroidModule(module)
+ module.AddProperties(&module.properties)
+ return module
+}
+
+func (p *PhonyRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+}
+
+func (p *PhonyRule) AndroidMk() android.AndroidMkData {
+ return android.AndroidMkData{
+ Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
+ if len(p.properties.Phony_deps) > 0 {
+ depModulesStr := strings.Join(p.properties.Phony_deps, " ")
+ fmt.Fprintln(w, ".PHONY:", name)
+ fmt.Fprintln(w, name, ":", depModulesStr)
+ }
+ },
+ }
+}
diff --git a/python/Android.bp b/python/Android.bp
index 7578673..14e83c1 100644
--- a/python/Android.bp
+++ b/python/Android.bp
@@ -10,10 +10,10 @@
"soong-android",
"soong-tradefed",
"soong-cc",
+ "soong-testing",
],
srcs: [
"binary.go",
- "bp2build.go",
"builder.go",
"defaults.go",
"library.go",
diff --git a/python/binary.go b/python/binary.go
index a5db2f6..d6750c6 100644
--- a/python/binary.go
+++ b/python/binary.go
@@ -71,6 +71,9 @@
installedDest android.Path
androidMkSharedLibs []string
+
+ // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo
+ mergedAconfigFiles map[string]android.Paths
}
var _ android.AndroidMkEntriesProvider = (*PythonBinaryModule)(nil)
@@ -95,7 +98,6 @@
p.AddProperties(&p.binaryProperties)
android.InitAndroidArchModule(p, p.hod, p.multilib)
android.InitDefaultableModule(p)
- android.InitBazelModule(p)
return p
}
@@ -104,6 +106,7 @@
p.buildBinary(ctx)
p.installedDest = ctx.InstallFile(installDir(ctx, "bin", "", ""),
p.installSource.Base(), p.installSource)
+ android.CollectDependencyAconfigFiles(ctx, &p.mergedAconfigFiles)
}
func (p *PythonBinaryModule) buildBinary(ctx android.ModuleContext) {
@@ -167,6 +170,7 @@
entries.SetString("LOCAL_MODULE_STEM", stem)
entries.AddStrings("LOCAL_SHARED_LIBRARIES", p.androidMkSharedLibs...)
entries.SetBool("LOCAL_CHECK_ELF_FILES", false)
+ android.SetAconfigFileMkEntries(&p.ModuleBase, entries, p.mergedAconfigFiles)
})
return []android.AndroidMkEntries{entries}
diff --git a/python/bp2build.go b/python/bp2build.go
deleted file mode 100644
index 8bc3d0a..0000000
--- a/python/bp2build.go
+++ /dev/null
@@ -1,240 +0,0 @@
-// Copyright 2023 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 python
-
-import (
- "path/filepath"
- "strings"
-
- "github.com/google/blueprint/proptools"
-
- "android/soong/android"
- "android/soong/bazel"
-)
-
-type bazelPythonLibraryAttributes struct {
- Srcs bazel.LabelListAttribute
- Deps bazel.LabelListAttribute
- Imports bazel.StringListAttribute
- Srcs_version *string
-}
-
-type bazelPythonProtoLibraryAttributes struct {
- Deps bazel.LabelListAttribute
-
- // A list of proto_library targets that the proto_library in `deps` depends on
- // This list is overestimation.
- // Overestimation is necessary since Soong includes other protos via proto.include_dirs and not
- // a specific .proto file module explicitly.
- Transitive_deps bazel.LabelListAttribute
-}
-
-type baseAttributes struct {
- // TODO(b/200311466): Probably not translate b/c Bazel has no good equiv
- //Pkg_path bazel.StringAttribute
- // TODO: Related to Pkg_bath and similarLy gated
- //Is_internal bazel.BoolAttribute
- // Combines Srcs and Exclude_srcs
- Srcs bazel.LabelListAttribute
- Deps bazel.LabelListAttribute
- // Combines Data and Java_data (invariant)
- Data bazel.LabelListAttribute
- Imports bazel.StringListAttribute
-}
-
-func (m *PythonLibraryModule) makeArchVariantBaseAttributes(ctx android.TopDownMutatorContext) baseAttributes {
- var attrs baseAttributes
- archVariantBaseProps := m.GetArchVariantProperties(ctx, &BaseProperties{})
- for axis, configToProps := range archVariantBaseProps {
- for config, props := range configToProps {
- if baseProps, ok := props.(*BaseProperties); ok {
- attrs.Srcs.SetSelectValue(axis, config,
- android.BazelLabelForModuleSrcExcludes(ctx, baseProps.Srcs, baseProps.Exclude_srcs))
- attrs.Deps.SetSelectValue(axis, config,
- android.BazelLabelForModuleDeps(ctx, baseProps.Libs))
- data := android.BazelLabelForModuleSrc(ctx, baseProps.Data)
- data.Append(android.BazelLabelForModuleSrc(ctx, baseProps.Java_data))
- attrs.Data.SetSelectValue(axis, config, data)
- }
- }
- }
-
- partitionedSrcs := bazel.PartitionLabelListAttribute(ctx, &attrs.Srcs, bazel.LabelPartitions{
- "proto": android.ProtoSrcLabelPartition,
- "py": bazel.LabelPartition{Keep_remainder: true},
- })
- attrs.Srcs = partitionedSrcs["py"]
-
- if !partitionedSrcs["proto"].IsEmpty() {
- protoInfo, _ := android.Bp2buildProtoProperties(ctx, &m.ModuleBase, partitionedSrcs["proto"])
-
- pyProtoLibraryName := m.Name() + "_py_proto"
- ctx.CreateBazelTargetModule(bazel.BazelTargetModuleProperties{
- Rule_class: "py_proto_library",
- Bzl_load_location: "//build/bazel/rules/python:py_proto.bzl",
- }, android.CommonAttributes{
- Name: pyProtoLibraryName,
- }, &bazelPythonProtoLibraryAttributes{
- Deps: bazel.MakeLabelListAttribute(protoInfo.Proto_libs),
- Transitive_deps: bazel.MakeLabelListAttribute(protoInfo.Transitive_proto_libs),
- })
-
- attrs.Deps.Add(bazel.MakeLabelAttribute(":" + pyProtoLibraryName))
- }
-
- // Bazel normally requires `import path.from.top.of.tree` statements in
- // python code, but with soong you can directly import modules from libraries.
- // Add "imports" attributes to the bazel library so it matches soong's behavior.
- imports := "."
- if m.properties.Pkg_path != nil {
- // TODO(b/215119317) This is a hack to handle the fact that we don't convert
- // pkg_path properly right now. If the folder structure that contains this
- // Android.bp file matches pkg_path, we can set imports to an appropriate
- // number of ../..s to emulate moving the files under a pkg_path folder.
- pkg_path := filepath.Clean(*m.properties.Pkg_path)
- if strings.HasPrefix(pkg_path, "/") {
- ctx.ModuleErrorf("pkg_path cannot start with a /: %s", pkg_path)
- }
-
- if !strings.HasSuffix(ctx.ModuleDir(), "/"+pkg_path) && ctx.ModuleDir() != pkg_path {
- ctx.ModuleErrorf("Currently, bp2build only supports pkg_paths that are the same as the folders the Android.bp file is in. pkg_path: %s, module directory: %s", pkg_path, ctx.ModuleDir())
- }
- numFolders := strings.Count(pkg_path, "/") + 1
- dots := make([]string, numFolders)
- for i := 0; i < numFolders; i++ {
- dots[i] = ".."
- }
- imports = strings.Join(dots, "/")
- }
- attrs.Imports = bazel.MakeStringListAttribute([]string{imports})
-
- return attrs
-}
-
-func (m *PythonLibraryModule) bp2buildPythonVersion(ctx android.TopDownMutatorContext) *string {
- py3Enabled := proptools.BoolDefault(m.properties.Version.Py3.Enabled, true)
- py2Enabled := proptools.BoolDefault(m.properties.Version.Py2.Enabled, false)
- if py2Enabled && !py3Enabled {
- return &pyVersion2
- } else if !py2Enabled && py3Enabled {
- return &pyVersion3
- } else if !py2Enabled && !py3Enabled {
- ctx.ModuleErrorf("bp2build converter doesn't understand having neither py2 nor py3 enabled")
- return &pyVersion3
- } else {
- return &pyVersion2And3
- }
-}
-
-type bazelPythonBinaryAttributes struct {
- Main *bazel.Label
- Srcs bazel.LabelListAttribute
- Deps bazel.LabelListAttribute
- Python_version *string
- Imports bazel.StringListAttribute
-}
-
-func (p *PythonLibraryModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- // 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.
- baseAttrs := p.makeArchVariantBaseAttributes(ctx)
- pyVersion := p.bp2buildPythonVersion(ctx)
- if *pyVersion == pyVersion2And3 {
- // Libraries default to python 2 and 3
- pyVersion = nil
- }
-
- attrs := &bazelPythonLibraryAttributes{
- Srcs: baseAttrs.Srcs,
- Deps: baseAttrs.Deps,
- Srcs_version: pyVersion,
- Imports: baseAttrs.Imports,
- }
-
- props := bazel.BazelTargetModuleProperties{
- // Use the native py_library rule.
- Rule_class: "py_library",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: p.Name(),
- Data: baseAttrs.Data,
- }, attrs)
-}
-
-func (p *PythonBinaryModule) bp2buildBinaryProperties(ctx android.TopDownMutatorContext) (*bazelPythonBinaryAttributes, bazel.LabelListAttribute) {
- // 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_binary_host modules
- // under Bionic.
-
- baseAttrs := p.makeArchVariantBaseAttributes(ctx)
- pyVersion := p.bp2buildPythonVersion(ctx)
- if *pyVersion == pyVersion3 {
- // Binaries default to python 3
- pyVersion = nil
- } else if *pyVersion == pyVersion2And3 {
- ctx.ModuleErrorf("error for '%s' module: bp2build's python_binary_host converter "+
- "does not support converting a module that is enabled for both Python 2 and 3 at the "+
- "same time.", p.Name())
- }
-
- attrs := &bazelPythonBinaryAttributes{
- Main: nil,
- Srcs: baseAttrs.Srcs,
- Deps: baseAttrs.Deps,
- Python_version: pyVersion,
- Imports: baseAttrs.Imports,
- }
-
- // main is optional.
- if p.binaryProperties.Main != nil {
- main := android.BazelLabelForModuleSrcSingle(ctx, *p.binaryProperties.Main)
- attrs.Main = &main
- }
- return attrs, baseAttrs.Data
-}
-
-func (p *PythonBinaryModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- attrs, data := p.bp2buildBinaryProperties(ctx)
-
- props := bazel.BazelTargetModuleProperties{
- // Use the native py_binary rule.
- Rule_class: "py_binary",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: p.Name(),
- Data: data,
- }, attrs)
-}
-
-func (p *PythonTestModule) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- // Python tests are currently exactly the same as binaries, but with a different module type
- attrs, data := p.bp2buildBinaryProperties(ctx)
-
- props := bazel.BazelTargetModuleProperties{
- // Use the native py_binary rule.
- Rule_class: "py_test",
- Bzl_load_location: "//build/bazel/rules/python:py_test.bzl",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{
- Name: p.Name(),
- Data: data,
- }, attrs)
-}
diff --git a/python/python.go b/python/python.go
index 7d77ca7..d3cbd76 100644
--- a/python/python.go
+++ b/python/python.go
@@ -129,7 +129,6 @@
type PythonLibraryModule struct {
android.ModuleBase
android.DefaultableModuleBase
- android.BazelModuleBase
properties BaseProperties
protoProperties android.ProtoProperties
@@ -197,14 +196,6 @@
return String(p.properties.Pkg_path)
}
-// PkgPath is the "public" version of `getPkgPath` that is only available during bp2build
-func (p *PythonLibraryModule) PkgPath(ctx android.BazelConversionContext) *string {
- if ctx.Config().BuildMode != android.Bp2build {
- ctx.ModuleErrorf("PkgPath is only supported in bp2build mode")
- }
- return p.properties.Pkg_path
-}
-
func (p *PythonLibraryModule) getBaseProperties() *BaseProperties {
return &p.properties
}
@@ -215,7 +206,6 @@
p.AddProperties(&p.properties, &p.protoProperties)
android.InitAndroidArchModule(p, p.hod, p.multilib)
android.InitDefaultableModule(p)
- android.InitBazelModule(p)
return p
}
@@ -430,6 +420,7 @@
// GenerateAndroidBuildActions performs build actions common to all Python modules
func (p *PythonLibraryModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
expandedSrcs := android.PathsForModuleSrcExcludes(ctx, p.properties.Srcs, p.properties.Exclude_srcs)
+ android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: expandedSrcs.Strings()})
// expand data files from "data" property.
expandedData := android.PathsForModuleSrc(ctx, p.properties.Data)
diff --git a/python/scripts/precompile_python.py b/python/scripts/precompile_python.py
index e12e7d2..80e7c76 100644
--- a/python/scripts/precompile_python.py
+++ b/python/scripts/precompile_python.py
@@ -16,6 +16,7 @@
import argparse
import py_compile
import os
+import sys
import shutil
import tempfile
import zipfile
@@ -23,22 +24,31 @@
# This file needs to support both python 2 and 3.
-def process_one_file(name, inf, outzip):
- if not name.endswith('.py'):
- outzip.writestr(name, inf.read())
+def process_one_file(info, infile, outzip):
+ if not info.filename.endswith('.py'):
+ outzip.writestr(info, infile.read())
return
# Unfortunately py_compile requires the input/output files to be written
# out to disk.
with tempfile.NamedTemporaryFile(prefix="Soong_precompile_", delete=False) as tmp:
- shutil.copyfileobj(inf, tmp)
+ shutil.copyfileobj(infile, tmp)
in_name = tmp.name
with tempfile.NamedTemporaryFile(prefix="Soong_precompile_", delete=False) as tmp:
out_name = tmp.name
try:
- py_compile.compile(in_name, out_name, name, doraise=True)
+ # Ensure deterministic pyc by using the hash rather than timestamp.
+ # This is required to improve caching in accelerated builds.
+ # Only works on Python 3.7+ (see https://docs.python.org/3/library/py_compile.html#py_compile.PycInvalidationMode)
+ # which should cover most updated branches and developer machines.
+ if sys.version_info >= (3, 7):
+ py_compile.compile(in_name, out_name, info.filename, doraise=True, invalidation_mode=py_compile.PycInvalidationMode.CHECKED_HASH)
+ else:
+ py_compile.compile(in_name, out_name, info.filename, doraise=True)
with open(out_name, 'rb') as f:
- outzip.writestr(name + 'c', f.read())
+ info.filename = info.filename + 'c'
+ # Use ZipInfo rather than str to reuse timestamps for deterministic zip files.
+ outzip.writestr(info, f.read())
finally:
os.remove(in_name)
os.remove(out_name)
@@ -52,9 +62,9 @@
with open(args.dst_zip, 'wb') as outf, open(args.src_zip, 'rb') as inf:
with zipfile.ZipFile(outf, mode='w') as outzip, zipfile.ZipFile(inf, mode='r') as inzip:
- for name in inzip.namelist():
- with inzip.open(name, mode='r') as inzipf:
- process_one_file(name, inzipf, outzip)
+ for info in inzip.infolist():
+ with inzip.open(info.filename, mode='r') as inzipf:
+ process_one_file(info, inzipf, outzip)
if __name__ == "__main__":
diff --git a/python/test.go b/python/test.go
index 6e23a44..7eb9136 100644
--- a/python/test.go
+++ b/python/test.go
@@ -17,6 +17,7 @@
import (
"fmt"
+ "android/soong/testing"
"github.com/google/blueprint/proptools"
"android/soong/android"
@@ -101,7 +102,6 @@
p.AddProperties(&p.testProperties)
android.InitAndroidArchModule(p, p.hod, p.multilib)
android.InitDefaultableModule(p)
- android.InitBazelModule(p)
if p.isTestHost() && p.testProperties.Test_options.Unit_test == nil {
p.testProperties.Test_options.Unit_test = proptools.BoolPtr(true)
}
@@ -149,6 +149,7 @@
// just use buildBinary() so that the binary is not installed into the location
// it would be for regular binaries.
p.PythonLibraryModule.GenerateAndroidBuildActions(ctx)
+ android.CollectDependencyAconfigFiles(ctx, &p.mergedAconfigFiles)
p.buildBinary(ctx)
var configs []tradefed.Option
@@ -187,8 +188,6 @@
panic(fmt.Errorf("unknown python test runner '%s', should be 'tradefed' or 'mobly'", runner))
}
- p.installedDest = ctx.InstallFile(installDir(ctx, "nativetest", "nativetest64", ctx.ModuleName()), p.installSource.Base(), p.installSource)
-
for _, dataSrcPath := range android.PathsForModuleSrc(ctx, p.testProperties.Data) {
p.data = append(p.data, android.DataPath{SrcPath: dataSrcPath})
}
@@ -205,6 +204,12 @@
p.data = append(p.data, android.DataPath{SrcPath: javaDataSrcPath})
}
}
+
+ installDir := installDir(ctx, "nativetest", "nativetest64", ctx.ModuleName())
+ installedData := ctx.InstallTestData(installDir, p.data)
+ p.installedDest = ctx.InstallFile(installDir, p.installSource.Base(), p.installSource, installedData...)
+
+ android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
func (p *PythonTestModule) AndroidMkEntries() []android.AndroidMkEntries {
@@ -224,8 +229,7 @@
}
entries.SetBoolIfTrue("LOCAL_DISABLE_AUTO_GENERATE_TEST_CONFIG", !BoolDefault(p.binaryProperties.Auto_gen_config, true))
-
- entries.AddStrings("LOCAL_TEST_DATA", android.AndroidMkDataPaths(p.data)...)
+ android.SetAconfigFileMkEntries(&p.ModuleBase, entries, p.mergedAconfigFiles)
p.testProperties.Test_options.SetAndroidMkEntries(entries)
})
diff --git a/remoteexec/remoteexec.go b/remoteexec/remoteexec.go
index 9e7a0f1..8294c3f 100644
--- a/remoteexec/remoteexec.go
+++ b/remoteexec/remoteexec.go
@@ -15,6 +15,7 @@
package remoteexec
import (
+ "fmt"
"sort"
"strings"
)
@@ -29,7 +30,7 @@
// DefaultImage is the default container image used for Android remote execution. The
// image was built with the Dockerfile at
// https://android.googlesource.com/platform/prebuilts/remoteexecution-client/+/refs/heads/master/docker/Dockerfile
- DefaultImage = "docker://gcr.io/androidbuild-re-dockerimage/android-build-remoteexec-image@sha256:582efb38f0c229ea39952fff9e132ccbe183e14869b39888010dacf56b360d62"
+ DefaultImage = "docker://gcr.io/androidbuild-re-dockerimage/android-build-remoteexec-image@sha256:1eb7f64b9e17102b970bd7a1af7daaebdb01c3fb777715899ef462d6c6d01a45"
// DefaultWrapperPath is the default path to the remote execution wrapper.
DefaultWrapperPath = "prebuilts/remoteexecution-client/live/rewrapper"
@@ -84,6 +85,14 @@
// EnvironmentVariables is a list of environment variables whose values should be passed through
// to the remote execution.
EnvironmentVariables []string
+ // Boolean indicating whether to compare chosen exec strategy with local execution.
+ Compare bool
+ // Number of times the action should be rerun locally.
+ NumLocalRuns int
+ // Number of times the action should be rerun remotely.
+ NumRemoteRuns int
+ // Boolean indicating whether to update remote cache entry. Rewrapper defaults to true, so the name is negated here.
+ NoRemoteUpdateCache bool
}
func init() {
@@ -135,6 +144,14 @@
}
args += " --exec_strategy=" + strategy
+ if r.Compare && r.NumLocalRuns >= 0 && r.NumRemoteRuns >= 0 {
+ args += fmt.Sprintf(" --compare=true --num_local_reruns=%d --num_remote_reruns=%d", r.NumLocalRuns, r.NumRemoteRuns)
+ }
+
+ if r.NoRemoteUpdateCache {
+ args += " --remote_update_cache=false"
+ }
+
if len(r.Inputs) > 0 {
args += " --inputs=" + strings.Join(r.Inputs, ",")
}
diff --git a/rust/Android.bp b/rust/Android.bp
index b01a94a..637042d 100644
--- a/rust/Android.bp
+++ b/rust/Android.bp
@@ -7,11 +7,13 @@
pkgPath: "android/soong/rust",
deps: [
"soong",
+ "soong-aconfig",
"soong-android",
"soong-bloaty",
"soong-cc",
"soong-rust-config",
"soong-snapshot",
+ "soong-testing",
],
srcs: [
"afdo.go",
diff --git a/rust/afdo.go b/rust/afdo.go
index 3534ee6..323ee36 100644
--- a/rust/afdo.go
+++ b/rust/afdo.go
@@ -67,8 +67,7 @@
}
ctx.VisitDirectDepsWithTag(cc.FdoProfileTag, func(m android.Module) {
- if ctx.OtherModuleHasProvider(m, cc.FdoProfileProvider) {
- info := ctx.OtherModuleProvider(m, cc.FdoProfileProvider).(cc.FdoProfileInfo)
+ if info, ok := android.OtherModuleProvider(ctx, m, cc.FdoProfileProvider); ok {
path := info.Path
profileUseFlag := fmt.Sprintf(afdoFlagFormat, path.String())
flags.RustFlags = append(flags.RustFlags, profileUseFlag)
diff --git a/rust/androidmk.go b/rust/androidmk.go
index c684e81..17fd2d8 100644
--- a/rust/androidmk.go
+++ b/rust/androidmk.go
@@ -18,7 +18,6 @@
"path/filepath"
"android/soong/android"
- "android/soong/cc"
)
type AndroidMkContext interface {
@@ -67,7 +66,7 @@
if mod.UseVndk() {
entries.SetBool("LOCAL_USE_VNDK", true)
}
-
+ android.SetAconfigFileMkEntries(mod.AndroidModuleBase(), entries, mod.mergedAconfigFiles)
},
},
}
@@ -114,8 +113,6 @@
test.Properties.Test_options.SetAndroidMkEntries(entries)
})
-
- cc.AndroidMkWriteTestData(test.data, ret)
}
func (benchmark *benchmarkDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
@@ -216,33 +213,9 @@
func (fuzz *fuzzDecorator) AndroidMk(ctx AndroidMkContext, ret *android.AndroidMkEntries) {
ctx.SubAndroidMk(ret, fuzz.binaryDecorator)
- var fuzzFiles []string
- for _, d := range fuzz.fuzzPackagedModule.Corpus {
- fuzzFiles = append(fuzzFiles,
- filepath.Dir(fuzz.fuzzPackagedModule.CorpusIntermediateDir.String())+":corpus/"+d.Base())
- }
-
- for _, d := range fuzz.fuzzPackagedModule.Data {
- fuzzFiles = append(fuzzFiles,
- filepath.Dir(fuzz.fuzzPackagedModule.DataIntermediateDir.String())+":data/"+d.Rel())
- }
-
- if fuzz.fuzzPackagedModule.Dictionary != nil {
- fuzzFiles = append(fuzzFiles,
- filepath.Dir(fuzz.fuzzPackagedModule.Dictionary.String())+":"+fuzz.fuzzPackagedModule.Dictionary.Base())
- }
-
- if fuzz.fuzzPackagedModule.Config != nil {
- fuzzFiles = append(fuzzFiles,
- filepath.Dir(fuzz.fuzzPackagedModule.Config.String())+":config.json")
- }
-
ret.ExtraEntries = append(ret.ExtraEntries, func(ctx android.AndroidMkExtraEntriesContext,
entries *android.AndroidMkEntries) {
entries.SetBool("LOCAL_IS_FUZZ_TARGET", true)
- if len(fuzzFiles) > 0 {
- entries.AddStrings("LOCAL_TEST_DATA", fuzzFiles...)
- }
if fuzz.installedSharedDeps != nil {
entries.AddStrings("LOCAL_FUZZ_INSTALLED_SHARED_DEPS", fuzz.installedSharedDeps...)
}
diff --git a/rust/binary.go b/rust/binary.go
index 1e24beb..9969513 100644
--- a/rust/binary.go
+++ b/rust/binary.go
@@ -16,8 +16,6 @@
import (
"android/soong/android"
- "android/soong/bazel"
- "fmt"
)
func init() {
@@ -62,8 +60,6 @@
func NewRustBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) {
module := newModule(hod, android.MultilibFirst)
- android.InitBazelModule(module)
-
binary := &binaryDecorator{
baseCompiler: NewBaseCompiler("bin", "", InstallInSystem),
}
@@ -76,14 +72,11 @@
func (binary *binaryDecorator) compilerFlags(ctx ModuleContext, flags Flags) Flags {
flags = binary.baseCompiler.compilerFlags(ctx, flags)
- if ctx.Os().Linux() {
- flags.LinkFlags = append(flags.LinkFlags, "-Wl,--gc-sections")
- }
-
if ctx.toolchain().Bionic() {
// no-undefined-version breaks dylib compilation since __rust_*alloc* functions aren't defined,
// but we can apply this to binaries.
flags.LinkFlags = append(flags.LinkFlags,
+ "-Wl,--gc-sections",
"-Wl,-z,nocopyreloc",
"-Wl,--no-undefined-version")
@@ -137,13 +130,13 @@
func (binary *binaryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
fileName := binary.getStem(ctx) + ctx.toolchain().ExecutableSuffix()
- srcPath, _ := srcPathFromModuleSrcs(ctx, binary.baseCompiler.Properties.Srcs)
outputFile := android.PathForModuleOut(ctx, fileName)
ret := buildOutput{outputFile: outputFile}
+ crateRootPath := crateRootPath(ctx, binary)
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
- flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects.Strings()...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
if binary.stripper.NeedsStrip(ctx) {
strippedOutputFile := outputFile
@@ -154,7 +147,7 @@
}
binary.baseCompiler.unstrippedOutputFile = outputFile
- ret.kytheFile = TransformSrcToBinary(ctx, srcPath, deps, flags, outputFile).kytheFile
+ ret.kytheFile = TransformSrcToBinary(ctx, crateRootPath, deps, flags, outputFile).kytheFile
return ret
}
@@ -187,88 +180,3 @@
func (binary *binaryDecorator) testBinary() bool {
return false
}
-
-type rustBinaryLibraryAttributes struct {
- Srcs bazel.LabelListAttribute
- Compile_data bazel.LabelListAttribute
- Crate_name bazel.StringAttribute
- Edition bazel.StringAttribute
- Crate_features bazel.StringListAttribute
- Deps bazel.LabelListAttribute
- Proc_macro_deps bazel.LabelListAttribute
- Rustc_flags bazel.StringListAttribute
-}
-
-func binaryBp2build(ctx android.TopDownMutatorContext, m *Module) {
- binary := m.compiler.(*binaryDecorator)
-
- var srcs bazel.LabelList
- var compileData bazel.LabelList
-
- if binary.baseCompiler.Properties.Srcs[0] == "src/main.rs" {
- srcs = android.BazelLabelForModuleSrc(ctx, []string{"src/**/*.rs"})
- compileData = android.BazelLabelForModuleSrc(
- ctx,
- []string{
- "src/**/*.proto",
- "examples/**/*.rs",
- "**/*.md",
- "templates/**/*.template",
- },
- )
- } else {
- srcs = android.BazelLabelForModuleSrc(ctx, binary.baseCompiler.Properties.Srcs)
- }
-
- deps := android.BazelLabelForModuleDeps(ctx, append(
- binary.baseCompiler.Properties.Rustlibs,
- ))
-
- procMacroDeps := android.BazelLabelForModuleDeps(ctx, binary.baseCompiler.Properties.Proc_macros)
-
- var rustcFLags []string
- for _, cfg := range binary.baseCompiler.Properties.Cfgs {
- rustcFLags = append(rustcFLags, fmt.Sprintf("--cfg=%s", cfg))
- }
-
- attrs := &rustBinaryLibraryAttributes{
- Srcs: bazel.MakeLabelListAttribute(
- srcs,
- ),
- Compile_data: bazel.MakeLabelListAttribute(
- compileData,
- ),
- Crate_name: bazel.StringAttribute{
- Value: &binary.baseCompiler.Properties.Crate_name,
- },
- Edition: bazel.StringAttribute{
- Value: binary.baseCompiler.Properties.Edition,
- },
- Crate_features: bazel.StringListAttribute{
- Value: binary.baseCompiler.Properties.Features,
- },
- Deps: bazel.MakeLabelListAttribute(
- deps,
- ),
- Proc_macro_deps: bazel.MakeLabelListAttribute(
- procMacroDeps,
- ),
- Rustc_flags: bazel.StringListAttribute{
- Value: append(
- rustcFLags,
- binary.baseCompiler.Properties.Flags...,
- ),
- },
- }
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "rust_binary",
- Bzl_load_location: "@rules_rust//rust:defs.bzl",
- },
- android.CommonAttributes{
- Name: m.Name(),
- },
- attrs,
- )
-}
diff --git a/rust/binary_test.go b/rust/binary_test.go
index dff94ac..ef93037 100644
--- a/rust/binary_test.go
+++ b/rust/binary_test.go
@@ -150,7 +150,7 @@
bootstrap: true,
}`)
- foo := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustLink")
+ foo := ctx.ModuleForTests("foo", "android_arm64_armv8-a").Rule("rustc")
flag := "-Wl,-dynamic-linker,/system/bin/bootstrap/linker64"
if !strings.Contains(foo.Args["linkFlags"], flag) {
@@ -167,11 +167,10 @@
}`)
fizzOut := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Rule("rustc")
- fizzOutLink := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Rule("rustLink")
fizzMod := ctx.ModuleForTests("fizz", "android_arm64_armv8-a").Module().(*Module)
flags := fizzOut.Args["rustcFlags"]
- linkFlags := fizzOutLink.Args["linkFlags"]
+ linkFlags := fizzOut.Args["linkFlags"]
if !strings.Contains(flags, "-C relocation-model=static") {
t.Errorf("static binary missing '-C relocation-model=static' in rustcFlags, found: %#v", flags)
}
@@ -201,7 +200,7 @@
name: "libfoo",
}`)
- fizzBuzz := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Rule("rustLink")
+ fizzBuzz := ctx.ModuleForTests("fizz-buzz", "android_arm64_armv8-a").Rule("rustc")
linkFlags := fizzBuzz.Args["linkFlags"]
if !strings.Contains(linkFlags, "/libfoo.so") {
t.Errorf("missing shared dependency 'libfoo.so' in linkFlags: %#v", linkFlags)
diff --git a/rust/bindgen.go b/rust/bindgen.go
index a80a587..85cc220 100644
--- a/rust/bindgen.go
+++ b/rust/bindgen.go
@@ -29,7 +29,7 @@
defaultBindgenFlags = []string{""}
// bindgen should specify its own Clang revision so updating Clang isn't potentially blocked on bindgen failures.
- bindgenClangVersion = "clang-r498229b"
+ bindgenClangVersion = "clang-r510928"
_ = pctx.VariableFunc("bindgenClangVersion", func(ctx android.PackageVarContext) string {
if override := ctx.Config().Getenv("LLVM_BINDGEN_PREBUILTS_VERSION"); override != "" {
@@ -124,18 +124,20 @@
ctx.PropertyErrorf("c_std", "c_std and cpp_std cannot both be defined at the same time.")
}
- if String(b.ClangProperties.Cpp_std) != "" {
+ if b.ClangProperties.Cpp_std != nil {
+ isCpp = true
if String(b.ClangProperties.Cpp_std) == "experimental" {
stdVersion = cc_config.ExperimentalCppStdVersion
- } else if String(b.ClangProperties.Cpp_std) == "default" {
+ } else if String(b.ClangProperties.Cpp_std) == "default" || String(b.ClangProperties.Cpp_std) == "" {
stdVersion = cc_config.CppStdVersion
} else {
stdVersion = String(b.ClangProperties.Cpp_std)
}
} else if b.ClangProperties.C_std != nil {
+ isCpp = false
if String(b.ClangProperties.C_std) == "experimental" {
stdVersion = cc_config.ExperimentalCStdVersion
- } else if String(b.ClangProperties.C_std) == "default" {
+ } else if String(b.ClangProperties.C_std) == "default" || String(b.ClangProperties.C_std) == "" {
stdVersion = cc_config.CStdVersion
} else {
stdVersion = String(b.ClangProperties.C_std)
@@ -168,10 +170,19 @@
cflags = append(cflags, strings.ReplaceAll(ccToolchain.Cflags(), "${config.", "${cc_config."))
cflags = append(cflags, strings.ReplaceAll(ccToolchain.ToolchainCflags(), "${config.", "${cc_config."))
- if ctx.RustModule().UseVndk() {
+ if ctx.RustModule().InVendorOrProduct() {
cflags = append(cflags, "-D__ANDROID_VNDK__")
if ctx.RustModule().InVendor() {
cflags = append(cflags, "-D__ANDROID_VENDOR__")
+
+ vendorApiLevel := ctx.Config().VendorApiLevel()
+ if vendorApiLevel == "" {
+ // TODO(b/314036847): This is a fallback for UDC targets.
+ // This must be a build failure when UDC is no longer built
+ // from this source tree.
+ vendorApiLevel = ctx.Config().PlatformSdkVersion().String()
+ }
+ cflags = append(cflags, "-D__ANDROID_VENDOR_API__="+vendorApiLevel)
} else if ctx.RustModule().InProduct() {
cflags = append(cflags, "-D__ANDROID_PRODUCT__")
}
diff --git a/rust/bindgen_test.go b/rust/bindgen_test.go
index 12cdb3c..0ba0ff8 100644
--- a/rust/bindgen_test.go
+++ b/rust/bindgen_test.go
@@ -115,7 +115,7 @@
ctx := testRust(t, `
rust_bindgen {
name: "libbindgen_cstd",
- wrapper_src: "src/any.h",
+ wrapper_src: "src/any.hpp",
crate_name: "bindgen",
stem: "libbindgen",
source_stem: "bindings",
@@ -141,6 +141,16 @@
if !strings.Contains(libbindgen_cppstd.Args["cflags"], "-std=foo") {
t.Errorf("cpp_std value not passed in to rust_bindgen as a clang flag")
}
+
+ // Make sure specifying cpp_std emits the '-x c++' flag
+ if !strings.Contains(libbindgen_cppstd.Args["cflags"], "-x c++") {
+ t.Errorf("Setting cpp_std should cause the '-x c++' flag to be emitted")
+ }
+
+ // Make sure specifying c_std omits the '-x c++' flag
+ if strings.Contains(libbindgen_cstd.Args["cflags"], "-x c++") {
+ t.Errorf("Setting c_std should not cause the '-x c++' flag to be emitted")
+ }
}
func TestBindgenDisallowedFlags(t *testing.T) {
diff --git a/rust/builder.go b/rust/builder.go
index b1f049d..c855cfb 100644
--- a/rust/builder.go
+++ b/rust/builder.go
@@ -26,14 +26,14 @@
var (
_ = pctx.SourcePathVariable("rustcCmd", "${config.RustBin}/rustc")
- _ = pctx.SourcePathVariable("mkcraterspCmd", "build/soong/scripts/mkcratersp.py")
rustc = pctx.AndroidStaticRule("rustc",
blueprint.RuleParams{
Command: "$envVars $rustcCmd " +
- "-C linker=$mkcraterspCmd " +
+ "-C linker=${config.RustLinker} " +
+ "-C link-args=\"${crtBegin} ${earlyLinkFlags} ${linkFlags} ${crtEnd}\" " +
"--emit link -o $out --emit dep-info=$out.d.raw $in ${libFlags} $rustcFlags" +
" && grep \"^$out:\" $out.d.raw > $out.d",
- CommandDeps: []string{"$rustcCmd", "$mkcraterspCmd"},
+ CommandDeps: []string{"$rustcCmd"},
// Rustc deps-info writes out make compatible dep files: https://github.com/rust-lang/rust/issues/7633
// Rustc emits unneeded dependency lines for the .d and input .rs files.
// Those extra lines cause ninja warning:
@@ -42,12 +42,7 @@
Deps: blueprint.DepsGCC,
Depfile: "$out.d",
},
- "rustcFlags", "libFlags", "envVars")
- rustLink = pctx.AndroidStaticRule("rustLink",
- blueprint.RuleParams{
- Command: "${config.RustLinker} -o $out ${crtBegin} ${earlyLinkFlags} @$in ${linkFlags} ${crtEnd}",
- },
- "earlyLinkFlags", "linkFlags", "crtBegin", "crtEnd")
+ "rustcFlags", "earlyLinkFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "envVars")
_ = pctx.SourcePathVariable("rustdocCmd", "${config.RustBin}/rustdoc")
rustdoc = pctx.AndroidStaticRule("rustdoc",
@@ -106,13 +101,14 @@
`KYTHE_CANONICALIZE_VNAME_PATHS=prefer-relative ` +
`$rustExtractor $envVars ` +
`$rustcCmd ` +
- `-C linker=true ` +
+ `-C linker=${config.RustLinker} ` +
+ `-C link-args="${crtBegin} ${linkFlags} ${crtEnd}" ` +
`$in ${libFlags} $rustcFlags`,
CommandDeps: []string{"$rustExtractor", "$kytheVnames"},
Rspfile: "${out}.rsp",
RspfileContent: "$in",
},
- "rustcFlags", "libFlags", "envVars")
+ "rustcFlags", "linkFlags", "libFlags", "crtBegin", "crtEnd", "envVars")
)
type buildOutput struct {
@@ -200,7 +196,7 @@
}
if len(deps.SrcDeps) > 0 {
- moduleGenDir := ctx.RustModule().compiler.CargoOutDir()
+ moduleGenDir := ctx.RustModule().compiler.cargoOutDir()
// We must calculate an absolute path for OUT_DIR since Rust's include! macro (which normally consumes this)
// assumes that paths are relative to the source file.
var outDirPrefix string
@@ -219,13 +215,13 @@
envVars = append(envVars, "ANDROID_RUST_VERSION="+config.GetRustVersion(ctx))
- if ctx.RustModule().compiler.CargoEnvCompat() {
+ if ctx.RustModule().compiler.cargoEnvCompat() {
if bin, ok := ctx.RustModule().compiler.(*binaryDecorator); ok {
envVars = append(envVars, "CARGO_BIN_NAME="+bin.getStem(ctx))
}
envVars = append(envVars, "CARGO_CRATE_NAME="+ctx.RustModule().CrateName())
envVars = append(envVars, "CARGO_PKG_NAME="+ctx.RustModule().CrateName())
- pkgVersion := ctx.RustModule().compiler.CargoPkgVersion()
+ pkgVersion := ctx.RustModule().compiler.cargoPkgVersion()
if pkgVersion != "" {
envVars = append(envVars, "CARGO_PKG_VERSION="+pkgVersion)
@@ -242,8 +238,6 @@
}
}
- envVars = append(envVars, "AR=${cc_config.ClangBin}/llvm-ar")
-
if ctx.Darwin() {
envVars = append(envVars, "ANDROID_RUST_DARWIN=true")
}
@@ -255,7 +249,8 @@
outputFile android.WritablePath, crateType string) buildOutput {
var inputs android.Paths
- var implicits, linkImplicits, linkOrderOnly android.Paths
+ var implicits android.Paths
+ var orderOnly android.Paths
var output buildOutput
var rustcFlags, linkFlags []string
var earlyLinkFlags string
@@ -287,11 +282,13 @@
if ctx.Config().IsEnvTrue("SOONG_RUSTC_INCREMENTAL") {
incrementalPath := android.PathForOutput(ctx, "rustc").String()
- rustcFlags = append(rustcFlags, "-Cincremental="+incrementalPath)
+ rustcFlags = append(rustcFlags, "-C incremental="+incrementalPath)
+ } else {
+ rustcFlags = append(rustcFlags, "-C codegen-units=1")
}
// Disallow experimental features
- modulePath := android.PathForModuleSrc(ctx).String()
+ modulePath := ctx.ModuleDir()
if !(android.IsThirdPartyPath(modulePath) || strings.HasPrefix(modulePath, "prebuilts")) {
rustcFlags = append(rustcFlags, "-Zallow-features=\"\"")
}
@@ -319,18 +316,18 @@
implicits = append(implicits, rustLibsToPaths(deps.RLibs)...)
implicits = append(implicits, rustLibsToPaths(deps.DyLibs)...)
implicits = append(implicits, rustLibsToPaths(deps.ProcMacros)...)
- implicits = append(implicits, deps.AfdoProfiles...)
+ implicits = append(implicits, deps.StaticLibs...)
+ implicits = append(implicits, deps.SharedLibDeps...)
implicits = append(implicits, deps.srcProviderFiles...)
- implicits = append(implicits, deps.WholeStaticLibs...)
+ implicits = append(implicits, deps.AfdoProfiles...)
- linkImplicits = append(linkImplicits, deps.LibDeps...)
- linkImplicits = append(linkImplicits, deps.CrtBegin...)
- linkImplicits = append(linkImplicits, deps.CrtEnd...)
+ implicits = append(implicits, deps.CrtBegin...)
+ implicits = append(implicits, deps.CrtEnd...)
- linkOrderOnly = append(linkOrderOnly, deps.linkObjects...)
+ orderOnly = append(orderOnly, deps.SharedLibs...)
if len(deps.SrcDeps) > 0 {
- moduleGenDir := ctx.RustModule().compiler.CargoOutDir()
+ moduleGenDir := ctx.RustModule().compiler.cargoOutDir()
var outputs android.WritablePaths
for _, genSrc := range deps.SrcDeps {
@@ -356,11 +353,13 @@
if flags.Clippy {
clippyFile := android.PathForModuleOut(ctx, outputFile.Base()+".clippy")
ctx.Build(pctx, android.BuildParams{
- Rule: clippyDriver,
- Description: "clippy " + main.Rel(),
- Output: clippyFile,
- Inputs: inputs,
- Implicits: implicits,
+ Rule: clippyDriver,
+ Description: "clippy " + main.Rel(),
+ Output: clippyFile,
+ ImplicitOutputs: nil,
+ Inputs: inputs,
+ Implicits: implicits,
+ OrderOnly: orderOnly,
Args: map[string]string{
"rustcFlags": strings.Join(rustcFlags, " "),
"libFlags": strings.Join(libFlags, " "),
@@ -372,42 +371,24 @@
implicits = append(implicits, clippyFile)
}
- rustcOutputFile := outputFile
- usesLinker := crateType == "bin" || crateType == "dylib" || crateType == "cdylib" || crateType == "proc-macro"
- if usesLinker {
- rustcOutputFile = android.PathForModuleOut(ctx, outputFile.Base()+".rsp")
- }
-
ctx.Build(pctx, android.BuildParams{
Rule: rustc,
Description: "rustc " + main.Rel(),
- Output: rustcOutputFile,
+ Output: outputFile,
Inputs: inputs,
Implicits: implicits,
+ OrderOnly: orderOnly,
Args: map[string]string{
- "rustcFlags": strings.Join(rustcFlags, " "),
- "libFlags": strings.Join(libFlags, " "),
- "envVars": strings.Join(envVars, " "),
+ "rustcFlags": strings.Join(rustcFlags, " "),
+ "earlyLinkFlags": earlyLinkFlags,
+ "linkFlags": strings.Join(linkFlags, " "),
+ "libFlags": strings.Join(libFlags, " "),
+ "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
+ "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
+ "envVars": strings.Join(envVars, " "),
},
})
- if usesLinker {
- ctx.Build(pctx, android.BuildParams{
- Rule: rustLink,
- Description: "rustLink " + main.Rel(),
- Output: outputFile,
- Inputs: android.Paths{rustcOutputFile},
- Implicits: linkImplicits,
- OrderOnly: linkOrderOnly,
- Args: map[string]string{
- "earlyLinkFlags": earlyLinkFlags,
- "linkFlags": strings.Join(linkFlags, " "),
- "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
- "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
- },
- })
- }
-
if flags.EmitXrefs {
kytheFile := android.PathForModuleOut(ctx, outputFile.Base()+".kzip")
ctx.Build(pctx, android.BuildParams{
@@ -416,9 +397,13 @@
Output: kytheFile,
Inputs: inputs,
Implicits: implicits,
+ OrderOnly: orderOnly,
Args: map[string]string{
"rustcFlags": strings.Join(rustcFlags, " "),
+ "linkFlags": strings.Join(linkFlags, " "),
"libFlags": strings.Join(libFlags, " "),
+ "crtBegin": strings.Join(deps.CrtBegin.Strings(), " "),
+ "crtEnd": strings.Join(deps.CrtEnd.Strings(), " "),
"envVars": strings.Join(envVars, " "),
},
})
@@ -451,7 +436,7 @@
docTimestampFile := android.PathForModuleOut(ctx, "rustdoc.timestamp")
// Silence warnings about renamed lints for third-party crates
- modulePath := android.PathForModuleSrc(ctx).String()
+ modulePath := ctx.ModuleDir()
if android.IsThirdPartyPath(modulePath) {
rustdocFlags = append(rustdocFlags, " -A warnings")
}
diff --git a/rust/builder_test.go b/rust/builder_test.go
index 5c11cb7..639f6d4 100644
--- a/rust/builder_test.go
+++ b/rust/builder_test.go
@@ -14,7 +14,11 @@
package rust
-import "testing"
+import (
+ "android/soong/android"
+ "sort"
+ "testing"
+)
func TestSourceProviderCollision(t *testing.T) {
testRustError(t, "multiple source providers generate the same filename output: bindings.rs", `
@@ -40,3 +44,113 @@
}
`)
}
+
+func TestCompilationOutputFiles(t *testing.T) {
+ ctx := testRust(t, `
+ rust_library {
+ name: "libfizz_buzz",
+ crate_name:"fizz_buzz",
+ srcs: ["lib.rs"],
+ }
+ rust_binary {
+ name: "fizz_buzz",
+ crate_name:"fizz_buzz",
+ srcs: ["lib.rs"],
+ }
+ rust_ffi {
+ name: "librust_ffi",
+ crate_name: "rust_ffi",
+ srcs: ["lib.rs"],
+ }
+ `)
+ testcases := []struct {
+ testName string
+ moduleName string
+ variant string
+ expectedFiles []string
+ }{
+ {
+ testName: "dylib",
+ moduleName: "libfizz_buzz",
+ variant: "android_arm64_armv8-a_dylib",
+ expectedFiles: []string{
+ "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/libfizz_buzz.dylib.so",
+ "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/libfizz_buzz.dylib.so.clippy",
+ "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/unstripped/libfizz_buzz.dylib.so",
+ "out/soong/target/product/test_device/system/lib64/libfizz_buzz.dylib.so",
+ "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_dylib/meta_lic",
+ },
+ },
+ {
+ testName: "rlib dylib-std",
+ moduleName: "libfizz_buzz",
+ variant: "android_arm64_armv8-a_rlib_dylib-std",
+ expectedFiles: []string{
+ "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_dylib-std/libfizz_buzz.rlib",
+ "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_dylib-std/libfizz_buzz.rlib.clippy",
+ "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_dylib-std/meta_lic",
+ },
+ },
+ {
+ testName: "rlib rlib-std",
+ moduleName: "libfizz_buzz",
+ variant: "android_arm64_armv8-a_rlib_rlib-std",
+ expectedFiles: []string{
+ "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_rlib-std/libfizz_buzz.rlib",
+ "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_rlib-std/libfizz_buzz.rlib.clippy",
+ "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_rlib-std/meta_lic",
+ "out/soong/.intermediates/libfizz_buzz/android_arm64_armv8-a_rlib_rlib-std/rustdoc.timestamp",
+ },
+ },
+ {
+ testName: "rust_binary",
+ moduleName: "fizz_buzz",
+ variant: "android_arm64_armv8-a",
+ expectedFiles: []string{
+ "out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/fizz_buzz",
+ "out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/fizz_buzz.clippy",
+ "out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/unstripped/fizz_buzz",
+ "out/soong/target/product/test_device/system/bin/fizz_buzz",
+ "out/soong/.intermediates/fizz_buzz/android_arm64_armv8-a/meta_lic",
+ },
+ },
+ {
+ testName: "rust_ffi static",
+ moduleName: "librust_ffi",
+ variant: "android_arm64_armv8-a_static",
+ expectedFiles: []string{
+ "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_static/librust_ffi.a",
+ "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_static/librust_ffi.a.clippy",
+ "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_static/meta_lic",
+ "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_static/rustdoc.timestamp",
+ },
+ },
+ {
+ testName: "rust_ffi shared",
+ moduleName: "librust_ffi",
+ variant: "android_arm64_armv8-a_shared",
+ expectedFiles: []string{
+ "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/librust_ffi.so",
+ "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/librust_ffi.so.clippy",
+ "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/unstripped/librust_ffi.so",
+ "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/unstripped/librust_ffi.so.toc",
+ "out/soong/.intermediates/librust_ffi/android_arm64_armv8-a_shared/meta_lic",
+ "out/soong/target/product/test_device/system/lib64/librust_ffi.so",
+ },
+ },
+ }
+ for _, tc := range testcases {
+ t.Run(tc.testName, func(t *testing.T) {
+ modOutputs := ctx.ModuleForTests(tc.moduleName, tc.variant).AllOutputs()
+ sort.Strings(tc.expectedFiles)
+ sort.Strings(modOutputs)
+ android.AssertStringPathsRelativeToTopEquals(
+ t,
+ "incorrect outputs from rust module",
+ ctx.Config(),
+ tc.expectedFiles,
+ modOutputs,
+ )
+ })
+ }
+}
diff --git a/rust/compiler.go b/rust/compiler.go
index e6a7a93..c1bdbeb 100644
--- a/rust/compiler.go
+++ b/rust/compiler.go
@@ -16,6 +16,7 @@
import (
"android/soong/cc"
+ "errors"
"fmt"
"path/filepath"
"strings"
@@ -34,6 +35,48 @@
DylibLinkage
)
+type compiler interface {
+ initialize(ctx ModuleContext)
+ compilerFlags(ctx ModuleContext, flags Flags) Flags
+ cfgFlags(ctx ModuleContext, flags Flags) Flags
+ featureFlags(ctx ModuleContext, flags Flags) Flags
+ compilerProps() []interface{}
+ compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput
+ compilerDeps(ctx DepsContext, deps Deps) Deps
+ crateName() string
+ edition() string
+ features() []string
+ rustdoc(ctx ModuleContext, flags Flags, deps PathDeps) android.OptionalPath
+
+ // Output directory in which source-generated code from dependencies is
+ // copied. This is equivalent to Cargo's OUT_DIR variable.
+ cargoOutDir() android.OptionalPath
+
+ // cargoPkgVersion returns the value of the Cargo_pkg_version property.
+ cargoPkgVersion() string
+
+ // cargoEnvCompat returns whether Cargo environment variables should be used.
+ cargoEnvCompat() bool
+
+ inData() bool
+ install(ctx ModuleContext)
+ relativeInstallPath() string
+ everInstallable() bool
+
+ nativeCoverage() bool
+
+ Disabled() bool
+ SetDisabled()
+
+ stdLinkage(ctx *depsContext) RustLinkage
+ noStdlibs() bool
+
+ unstrippedOutputFilePath() android.Path
+ strippedOutputFilePath() android.OptionalPath
+
+ checkedCrateRootPath() (android.Path, error)
+}
+
func (compiler *baseCompiler) edition() string {
return proptools.StringDefault(compiler.Properties.Edition, config.DefaultEdition)
}
@@ -73,6 +116,15 @@
// If no source file is defined, a single generated source module can be defined to be used as the main source.
Srcs []string `android:"path,arch_variant"`
+ // Entry point that is passed to rustc to begin the compilation. E.g. main.rs or lib.rs.
+ // When this property is set,
+ // * sandboxing is enabled for this module, and
+ // * the srcs attribute is interpreted as a list of all source files potentially
+ // used in compilation, including the entrypoint, and
+ // * compile_data can be used to add additional files used in compilation that
+ // not directly used as source files.
+ Crate_root *string `android:"path,arch_variant"`
+
// name of the lint set that should be used to validate this module.
//
// Possible values are "default" (for using a sensible set of lints
@@ -151,7 +203,7 @@
Relative_install_path *string `android:"arch_variant"`
// whether to suppress inclusion of standard crates - defaults to false
- No_stdlibs *bool
+ No_stdlibs *bool `android:"arch_variant"`
// Change the rustlibs linkage to select rlib linkage by default for device targets.
// Also link libstd as an rlib as well on device targets.
@@ -187,6 +239,8 @@
distFile android.OptionalPath
+ installDeps android.InstallPaths
+
// unstripped output file.
unstrippedOutputFile android.Path
@@ -195,7 +249,16 @@
// If a crate has a source-generated dependency, a copy of the source file
// will be available in cargoOutDir (equivalent to Cargo OUT_DIR).
- cargoOutDir android.ModuleOutPath
+ // This is stored internally because it may not be available during
+ // singleton-generation passes like rustdoc/rust_project.json, but should
+ // be stashed during initial generation.
+ cachedCargoOutDir android.ModuleOutPath
+ // Calculated crate root cached internally because ModuleContext is not
+ // available to singleton targets like rustdoc/rust_project.json
+ cachedCrateRootPath android.Path
+ // If cachedCrateRootPath is nil after initialization, this will contain
+ // an explanation of why
+ cachedCrateRootError error
}
func (compiler *baseCompiler) Disabled() bool {
@@ -248,9 +311,13 @@
return flags
}
+func (compiler *baseCompiler) features() []string {
+ return compiler.Properties.Features
+}
+
func (compiler *baseCompiler) featuresToFlags() []string {
flags := []string{}
- for _, feature := range compiler.Properties.Features {
+ for _, feature := range compiler.features() {
flags = append(flags, "--cfg 'feature=\""+feature+"\"'")
}
@@ -265,7 +332,7 @@
}
func (compiler *baseCompiler) cfgFlags(ctx ModuleContext, flags Flags) Flags {
- if ctx.RustModule().UseVndk() {
+ if ctx.RustModule().InVendorOrProduct() {
compiler.Properties.Cfgs = append(compiler.Properties.Cfgs, "android_vndk")
if ctx.RustModule().InVendor() {
compiler.Properties.Cfgs = append(compiler.Properties.Cfgs, "android_vendor")
@@ -318,10 +385,15 @@
flags.LinkFlags = append(flags.LinkFlags, cc.RpathFlags(ctx)...)
}
- if !ctx.toolchain().Bionic() && ctx.Os() != android.LinuxMusl && !ctx.Windows() {
- // Add -ldl, -lpthread, -lm and -lrt to host builds to match the default behavior of device
- // builds. This is irrelevant for the Windows target as these are Posix specific.
+ if ctx.Os() == android.Linux {
+ // Add -lc, -lrt, -ldl, -lpthread, -lm and -lgcc_s to glibc builds to match
+ // the default behavior of device builds.
+ flags.LinkFlags = append(flags.LinkFlags, config.LinuxHostGlobalLinkFlags...)
+ } else if ctx.Os() == android.Darwin {
+ // Add -lc, -ldl, -lpthread and -lm to glibc darwin builds to match the default
+ // behavior of device builds.
flags.LinkFlags = append(flags.LinkFlags,
+ "-lc",
"-ldl",
"-lpthread",
"-lm",
@@ -341,18 +413,24 @@
}
func (compiler *baseCompiler) initialize(ctx ModuleContext) {
- compiler.cargoOutDir = android.PathForModuleOut(ctx, genSubDir)
+ compiler.cachedCargoOutDir = android.PathForModuleOut(ctx, genSubDir)
+ if compiler.Properties.Crate_root == nil {
+ compiler.cachedCrateRootPath, compiler.cachedCrateRootError = srcPathFromModuleSrcs(ctx, compiler.Properties.Srcs)
+ } else {
+ compiler.cachedCrateRootPath = android.PathForModuleSrc(ctx, *compiler.Properties.Crate_root)
+ compiler.cachedCrateRootError = nil
+ }
}
-func (compiler *baseCompiler) CargoOutDir() android.OptionalPath {
- return android.OptionalPathForPath(compiler.cargoOutDir)
+func (compiler *baseCompiler) cargoOutDir() android.OptionalPath {
+ return android.OptionalPathForPath(compiler.cachedCargoOutDir)
}
-func (compiler *baseCompiler) CargoEnvCompat() bool {
+func (compiler *baseCompiler) cargoEnvCompat() bool {
return Bool(compiler.Properties.Cargo_env_compat)
}
-func (compiler *baseCompiler) CargoPkgVersion() string {
+func (compiler *baseCompiler) cargoPkgVersion() string {
return String(compiler.Properties.Cargo_pkg_version)
}
@@ -442,7 +520,7 @@
dir = filepath.Join(dir, ctx.Arch().ArchType.String())
}
- if compiler.location == InstallInData && ctx.RustModule().UseVndk() {
+ if compiler.location == InstallInData && ctx.RustModule().InVendorOrProduct() {
if ctx.RustModule().InProduct() {
dir = filepath.Join(dir, "product")
} else if ctx.RustModule().InVendor() {
@@ -462,7 +540,12 @@
func (compiler *baseCompiler) install(ctx ModuleContext) {
path := ctx.RustModule().OutputFile()
- compiler.path = ctx.InstallFile(compiler.installDir(ctx), path.Path().Base(), path.Path())
+ compiler.path = ctx.InstallFile(compiler.installDir(ctx), path.Path().Base(), path.Path(), compiler.installDeps...)
+}
+
+func (compiler *baseCompiler) installTestData(ctx ModuleContext, data []android.DataPath) {
+ installedData := ctx.InstallTestData(compiler.installDir(ctx), data)
+ compiler.installDeps = append(compiler.installDeps, installedData...)
}
func (compiler *baseCompiler) getStem(ctx ModuleContext) string {
@@ -482,12 +565,20 @@
return String(compiler.Properties.Relative_install_path)
}
-// Returns the Path for the main source file along with Paths for generated source files from modules listed in srcs.
-func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, android.Paths) {
- if len(srcs) == 0 {
- ctx.PropertyErrorf("srcs", "srcs must not be empty")
- }
+func (compiler *baseCompiler) checkedCrateRootPath() (android.Path, error) {
+ return compiler.cachedCrateRootPath, compiler.cachedCrateRootError
+}
+func crateRootPath(ctx ModuleContext, compiler compiler) android.Path {
+ root, err := compiler.checkedCrateRootPath()
+ if err != nil {
+ ctx.PropertyErrorf("srcs", err.Error())
+ }
+ return root
+}
+
+// Returns the Path for the main source file along with Paths for generated source files from modules listed in srcs.
+func srcPathFromModuleSrcs(ctx ModuleContext, srcs []string) (android.Path, error) {
// The srcs can contain strings with prefix ":".
// They are dependent modules of this module, with android.SourceDepTag.
// They are not the main source file compiled by rustc.
@@ -500,17 +591,22 @@
}
}
if numSrcs > 1 {
- ctx.PropertyErrorf("srcs", incorrectSourcesError)
+ return nil, errors.New(incorrectSourcesError)
}
// If a main source file is not provided we expect only a single SourceProvider module to be defined
// within srcs, with the expectation that the first source it provides is the entry point.
if srcIndex != 0 {
- ctx.PropertyErrorf("srcs", "main source file must be the first in srcs")
+ return nil, errors.New("main source file must be the first in srcs")
} else if numSrcs > 1 {
- ctx.PropertyErrorf("srcs", "only a single generated source module can be defined without a main source file.")
+ return nil, errors.New("only a single generated source module can be defined without a main source file.")
}
+ // TODO: b/297264540 - once all modules are sandboxed, we need to select the proper
+ // entry point file from Srcs rather than taking the first one
paths := android.PathsForModuleSrc(ctx, srcs)
- return paths[srcIndex], paths[1:]
+ if len(paths) == 0 {
+ return nil, errors.New("srcs must not be empty")
+ }
+ return paths[srcIndex], nil
}
diff --git a/rust/compiler_test.go b/rust/compiler_test.go
index ec6829a..89f4d1a 100644
--- a/rust/compiler_test.go
+++ b/rust/compiler_test.go
@@ -67,6 +67,7 @@
func TestEnforceSingleSourceFile(t *testing.T) {
singleSrcError := "srcs can only contain one path for a rust file and source providers prefixed by \":\""
+ prebuiltSingleSrcError := "prebuilt libraries can only have one entry in srcs"
// Test libraries
testRustError(t, singleSrcError, `
@@ -90,7 +91,7 @@
}`)
// Test prebuilts
- testRustError(t, singleSrcError, `
+ testRustError(t, prebuiltSingleSrcError, `
rust_prebuilt_dylib {
name: "foo-bar-prebuilt",
srcs: ["liby.so", "libz.so"],
diff --git a/rust/config/arm64_device.go b/rust/config/arm64_device.go
index 08ac2ef..6c021c7 100644
--- a/rust/config/arm64_device.go
+++ b/rust/config/arm64_device.go
@@ -21,7 +21,9 @@
)
var (
- Arm64RustFlags = []string{}
+ Arm64RustFlags = []string{
+ "-C force-frame-pointers=y",
+ }
Arm64ArchFeatureRustFlags = map[string][]string{}
Arm64LinkFlags = []string{}
@@ -52,6 +54,7 @@
strings.Join(rustFlags, " "))
}
+ ExportedVars.ExportStringListStaticVariable("DEVICE_ARM64_RUSTC_FLAGS", Arm64RustFlags)
}
type toolchainArm64 struct {
diff --git a/rust/config/arm_device.go b/rust/config/arm_device.go
index 42c1c02..a5f4afb 100644
--- a/rust/config/arm_device.go
+++ b/rust/config/arm_device.go
@@ -44,6 +44,7 @@
strings.Join(rustFlags, " "))
}
+ ExportedVars.ExportStringListStaticVariable("DEVICE_ARM_RUSTC_FLAGS", ArmRustFlags)
}
type toolchainArm struct {
diff --git a/rust/config/global.go b/rust/config/global.go
index c976617..aebbb1b 100644
--- a/rust/config/global.go
+++ b/rust/config/global.go
@@ -23,9 +23,9 @@
var (
pctx = android.NewPackageContext("android/soong/rust/config")
- exportedVars = android.NewExportedVariables(pctx)
+ ExportedVars = android.NewExportedVariables(pctx)
- RustDefaultVersion = "1.72.0"
+ RustDefaultVersion = "1.74.1"
RustDefaultBase = "prebuilts/rust/"
DefaultEdition = "2021"
Stdlibs = []string{
@@ -44,7 +44,6 @@
GlobalRustFlags = []string{
"-Z stack-protector=strong",
"-Z remap-cwd-prefix=.",
- "-C codegen-units=1",
"-C debuginfo=2",
"-C opt-level=3",
"-C relocation-model=pic",
@@ -52,15 +51,27 @@
"-C force-unwind-tables=yes",
// Use v0 mangling to distinguish from C++ symbols
"-C symbol-mangling-version=v0",
- "--color always",
- "-Zdylib-lto",
+ "--color=always",
+ "-Z dylib-lto",
"-Z link-native-libraries=no",
}
+ LinuxHostGlobalLinkFlags = []string{
+ "-lc",
+ "-lrt",
+ "-ldl",
+ "-lpthread",
+ "-lm",
+ "-lgcc_s",
+ "-Wl,--compress-debug-sections=zstd",
+ }
+
deviceGlobalRustFlags = []string{
"-C panic=abort",
// Generate additional debug info for AutoFDO
"-Z debug-info-for-profiling",
+ // Android has ELF TLS on platform
+ "-Z tls-model=global-dynamic",
}
deviceGlobalLinkFlags = []string{
@@ -76,18 +87,13 @@
"-Wl,--use-android-relr-tags",
"-Wl,--no-undefined",
"-B${cc_config.ClangBin}",
+ "-Wl,--compress-debug-sections=zstd",
}
)
func init() {
pctx.SourcePathVariable("RustDefaultBase", RustDefaultBase)
- pctx.VariableConfigMethod("HostPrebuiltTag", func(config android.Config) string {
- if config.UseHostMusl() {
- return "linux-musl-x86"
- } else {
- return config.PrebuiltOS()
- }
- })
+ pctx.VariableConfigMethod("HostPrebuiltTag", HostPrebuiltTag)
pctx.VariableFunc("RustBase", func(ctx android.PackageVarContext) string {
if override := ctx.Config().Getenv("RUST_PREBUILTS_BASE"); override != "" {
@@ -106,7 +112,25 @@
pctx.StaticVariable("DeviceGlobalLinkFlags", strings.Join(deviceGlobalLinkFlags, " "))
- exportedVars.ExportStringStaticVariable("RUST_DEFAULT_VERSION", RustDefaultVersion)
+ ExportedVars.ExportStringStaticVariable("RUST_DEFAULT_VERSION", RustDefaultVersion)
+ ExportedVars.ExportStringListStaticVariable("GLOBAL_RUSTC_FLAGS", GlobalRustFlags)
+ ExportedVars.ExportStringListStaticVariable("LINUX_HOST_GLOBAL_LINK_FLAGS", LinuxHostGlobalLinkFlags)
+
+ ExportedVars.ExportStringListStaticVariable("DEVICE_GLOBAL_RUSTC_FLAGS", deviceGlobalRustFlags)
+ ExportedVars.ExportStringListStaticVariable("DEVICE_GLOBAL_LINK_FLAGS",
+ android.RemoveListFromList(deviceGlobalLinkFlags, []string{
+ // The cc_config flags are retrieved from cc_toolchain by rust rules.
+ "${cc_config.DeviceGlobalLldflags}",
+ "-B${cc_config.ClangBin}",
+ }))
+}
+
+func HostPrebuiltTag(config android.Config) string {
+ if config.UseHostMusl() {
+ return "linux-musl-x86"
+ } else {
+ return config.PrebuiltOS()
+ }
}
func getRustVersionPctx(ctx android.PackageVarContext) string {
@@ -119,8 +143,3 @@
}
return RustDefaultVersion
}
-
-// BazelRustToolchainVars returns a string with
-func BazelRustToolchainVars(config android.Config) string {
- return android.BazelToolchainVars(config, exportedVars)
-}
diff --git a/rust/config/riscv64_device.go b/rust/config/riscv64_device.go
index d014dbf..0a9c61a 100644
--- a/rust/config/riscv64_device.go
+++ b/rust/config/riscv64_device.go
@@ -21,9 +21,15 @@
)
var (
- Riscv64RustFlags = []string{}
- Riscv64ArchFeatureRustFlags = map[string][]string{"": {}}
- Riscv64LinkFlags = []string{}
+ Riscv64RustFlags = []string{
+ "-C force-frame-pointers=y",
+ }
+ Riscv64ArchFeatureRustFlags = map[string][]string{
+ "riscv64": {
+ "-C target-feature=+V,+Zba,+Zbb,+Zbs",
+ },
+ }
+ Riscv64LinkFlags = []string{}
Riscv64ArchVariantRustFlags = map[string][]string{"": {}}
)
diff --git a/rust/config/x86_64_device.go b/rust/config/x86_64_device.go
index 3458ec9..49f7c77 100644
--- a/rust/config/x86_64_device.go
+++ b/rust/config/x86_64_device.go
@@ -21,20 +21,23 @@
)
var (
- x86_64RustFlags = []string{}
+ x86_64RustFlags = []string{
+ "-C force-frame-pointers=y",
+ }
x86_64ArchFeatureRustFlags = map[string][]string{}
x86_64LinkFlags = []string{}
x86_64ArchVariantRustFlags = map[string][]string{
- "": []string{},
- "broadwell": []string{"-C target-cpu=broadwell"},
- "goldmont": []string{"-C target-cpu=goldmont"},
- "goldmont-plus": []string{"-C target-cpu=goldmont-plus"},
- "haswell": []string{"-C target-cpu=haswell"},
- "ivybridge": []string{"-C target-cpu=ivybridge"},
- "sandybridge": []string{"-C target-cpu=sandybridge"},
- "silvermont": []string{"-C target-cpu=silvermont"},
- "skylake": []string{"-C target-cpu=skylake"},
+ "": []string{},
+ "broadwell": []string{"-C target-cpu=broadwell"},
+ "goldmont": []string{"-C target-cpu=goldmont"},
+ "goldmont-plus": []string{"-C target-cpu=goldmont-plus"},
+ "goldmont-without-sha-xsaves": []string{"-C target-cpu=goldmont", "-C target-feature=-sha,-xsaves"},
+ "haswell": []string{"-C target-cpu=haswell"},
+ "ivybridge": []string{"-C target-cpu=ivybridge"},
+ "sandybridge": []string{"-C target-cpu=sandybridge"},
+ "silvermont": []string{"-C target-cpu=silvermont"},
+ "skylake": []string{"-C target-cpu=skylake"},
//TODO: Add target-cpu=stoneyridge when rustc supports it.
"stoneyridge": []string{""},
"tremont": []string{"-C target-cpu=tremont"},
@@ -51,7 +54,7 @@
pctx.StaticVariable("X86_64"+variant+"VariantRustFlags",
strings.Join(rustFlags, " "))
}
-
+ ExportedVars.ExportStringListStaticVariable("DEVICE_X86_64_RUSTC_FLAGS", x86_64RustFlags)
}
type toolchainX86_64 struct {
diff --git a/rust/config/x86_device.go b/rust/config/x86_device.go
index 43f7340..2a57e73 100644
--- a/rust/config/x86_device.go
+++ b/rust/config/x86_device.go
@@ -26,16 +26,17 @@
x86LinkFlags = []string{}
x86ArchVariantRustFlags = map[string][]string{
- "": []string{},
- "atom": []string{"-C target-cpu=atom"},
- "broadwell": []string{"-C target-cpu=broadwell"},
- "goldmont": []string{"-C target-cpu=goldmont"},
- "goldmont-plus": []string{"-C target-cpu=goldmont-plus"},
- "haswell": []string{"-C target-cpu=haswell"},
- "ivybridge": []string{"-C target-cpu=ivybridge"},
- "sandybridge": []string{"-C target-cpu=sandybridge"},
- "silvermont": []string{"-C target-cpu=silvermont"},
- "skylake": []string{"-C target-cpu=skylake"},
+ "": []string{},
+ "atom": []string{"-C target-cpu=atom"},
+ "broadwell": []string{"-C target-cpu=broadwell"},
+ "goldmont": []string{"-C target-cpu=goldmont"},
+ "goldmont-plus": []string{"-C target-cpu=goldmont-plus"},
+ "goldmont-without-sha-xsaves": []string{"-C target-cpu=goldmont", "-C target-feature=-sha,-xsaves"},
+ "haswell": []string{"-C target-cpu=haswell"},
+ "ivybridge": []string{"-C target-cpu=ivybridge"},
+ "sandybridge": []string{"-C target-cpu=sandybridge"},
+ "silvermont": []string{"-C target-cpu=silvermont"},
+ "skylake": []string{"-C target-cpu=skylake"},
//TODO: Add target-cpu=stoneyridge when rustc supports it.
"stoneyridge": []string{""},
"tremont": []string{"-C target-cpu=tremont"},
@@ -55,6 +56,7 @@
strings.Join(rustFlags, " "))
}
+ ExportedVars.ExportStringListStaticVariable("DEVICE_X86_RUSTC_FLAGS", x86RustFlags)
}
type toolchainX86 struct {
diff --git a/rust/coverage.go b/rust/coverage.go
index 5216d60..bc6504d 100644
--- a/rust/coverage.go
+++ b/rust/coverage.go
@@ -65,7 +65,7 @@
"-C instrument-coverage", "-g")
flags.LinkFlags = append(flags.LinkFlags,
profileInstrFlag, "-g", coverage.OutputFile().Path().String(), "-Wl,--wrap,open")
- deps.LibDeps = append(deps.LibDeps, coverage.OutputFile().Path())
+ deps.StaticLibs = append(deps.StaticLibs, coverage.OutputFile().Path())
// no_std modules are missing libprofiler_builtins which provides coverage, so we need to add it as a dependency.
if rustModule, ok := ctx.Module().(*Module); ok && rustModule.compiler.noStdlibs() {
diff --git a/rust/coverage_test.go b/rust/coverage_test.go
index 64077cf..0f599d7 100644
--- a/rust/coverage_test.go
+++ b/rust/coverage_test.go
@@ -55,10 +55,6 @@
libbarNoCov := ctx.ModuleForTests("libbar_nocov", "android_arm64_armv8-a_dylib").Rule("rustc")
fizzCov := ctx.ModuleForTests("fizz_cov", "android_arm64_armv8-a_cov").Rule("rustc")
buzzNoCov := ctx.ModuleForTests("buzzNoCov", "android_arm64_armv8-a").Rule("rustc")
- libfooCovLink := ctx.ModuleForTests("libfoo_cov", "android_arm64_armv8-a_dylib_cov").Rule("rustLink")
- libbarNoCovLink := ctx.ModuleForTests("libbar_nocov", "android_arm64_armv8-a_dylib").Rule("rustLink")
- fizzCovLink := ctx.ModuleForTests("fizz_cov", "android_arm64_armv8-a_cov").Rule("rustLink")
- buzzNoCovLink := ctx.ModuleForTests("buzzNoCov", "android_arm64_armv8-a").Rule("rustLink")
rustcCoverageFlags := []string{"-C instrument-coverage", " -g "}
for _, flag := range rustcCoverageFlags {
@@ -84,17 +80,17 @@
missingErrorStr := "missing rust linker flag '%s' for '%s' module with coverage enabled; rustcFlags: %#v"
containsErrorStr := "contains rust linker flag '%s' for '%s' module with coverage disabled; rustcFlags: %#v"
- if !strings.Contains(fizzCovLink.Args["linkFlags"], flag) {
- t.Fatalf(missingErrorStr, flag, "fizz_cov", fizzCovLink.Args["linkFlags"])
+ if !strings.Contains(fizzCov.Args["linkFlags"], flag) {
+ t.Fatalf(missingErrorStr, flag, "fizz_cov", fizzCov.Args["linkFlags"])
}
- if !strings.Contains(libfooCovLink.Args["linkFlags"], flag) {
- t.Fatalf(missingErrorStr, flag, "libfoo_cov dylib", libfooCovLink.Args["linkFlags"])
+ if !strings.Contains(libfooCov.Args["linkFlags"], flag) {
+ t.Fatalf(missingErrorStr, flag, "libfoo_cov dylib", libfooCov.Args["linkFlags"])
}
- if strings.Contains(buzzNoCovLink.Args["linkFlags"], flag) {
- t.Fatalf(containsErrorStr, flag, "buzzNoCov", buzzNoCovLink.Args["linkFlags"])
+ if strings.Contains(buzzNoCov.Args["linkFlags"], flag) {
+ t.Fatalf(containsErrorStr, flag, "buzzNoCov", buzzNoCov.Args["linkFlags"])
}
- if strings.Contains(libbarNoCovLink.Args["linkFlags"], flag) {
- t.Fatalf(containsErrorStr, flag, "libbar_cov", libbarNoCovLink.Args["linkFlags"])
+ if strings.Contains(libbarNoCov.Args["linkFlags"], flag) {
+ t.Fatalf(containsErrorStr, flag, "libbar_cov", libbarNoCov.Args["linkFlags"])
}
}
@@ -107,7 +103,7 @@
srcs: ["foo.rs"],
}`)
- fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a_cov").Rule("rustLink")
+ fizz := ctx.ModuleForTests("fizz", "android_arm64_armv8-a_cov").Rule("rustc")
if !strings.Contains(fizz.Args["linkFlags"], "libprofile-clang-extras.a") {
t.Fatalf("missing expected coverage 'libprofile-clang-extras' dependency in linkFlags: %#v", fizz.Args["linkFlags"])
}
diff --git a/rust/fuzz.go b/rust/fuzz.go
index 4c04ce8..1770d2e 100644
--- a/rust/fuzz.go
+++ b/rust/fuzz.go
@@ -15,12 +15,11 @@
package rust
import (
- "path/filepath"
-
"android/soong/android"
"android/soong/cc"
"android/soong/fuzz"
"android/soong/rust/config"
+ "path/filepath"
)
func init() {
@@ -131,12 +130,6 @@
}
func (fuzz *fuzzDecorator) install(ctx ModuleContext) {
- fuzz.binaryDecorator.baseCompiler.dir = filepath.Join(
- "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
- fuzz.binaryDecorator.baseCompiler.dir64 = filepath.Join(
- "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
- fuzz.binaryDecorator.baseCompiler.install(ctx)
-
fuzz.fuzzPackagedModule = cc.PackageFuzzModule(ctx, fuzz.fuzzPackagedModule, pctx)
installBase := "fuzz"
@@ -149,12 +142,38 @@
fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
cc.SharedLibraryInstallLocation(
- install, ctx.Host(), installBase, ctx.Arch().ArchType.String()))
+ install, ctx.Host(), ctx.InstallInVendor(), installBase, ctx.Arch().ArchType.String()))
// Also add the dependency on the shared library symbols dir.
if !ctx.Host() {
fuzz.installedSharedDeps = append(fuzz.installedSharedDeps,
- cc.SharedLibrarySymbolsInstallLocation(install, installBase, ctx.Arch().ArchType.String()))
+ cc.SharedLibrarySymbolsInstallLocation(install, ctx.InstallInVendor(), installBase, ctx.Arch().ArchType.String()))
}
}
+
+ var fuzzData []android.DataPath
+ for _, d := range fuzz.fuzzPackagedModule.Corpus {
+ fuzzData = append(fuzzData, android.DataPath{SrcPath: d, RelativeInstallPath: "corpus", WithoutRel: true})
+ }
+
+ for _, d := range fuzz.fuzzPackagedModule.Data {
+ fuzzData = append(fuzzData, android.DataPath{SrcPath: d, RelativeInstallPath: "data"})
+ }
+
+ if d := fuzz.fuzzPackagedModule.Dictionary; d != nil {
+ fuzzData = append(fuzzData, android.DataPath{SrcPath: d, WithoutRel: true})
+ }
+
+ if d := fuzz.fuzzPackagedModule.Config; d != nil {
+ fuzzData = append(fuzzData, android.DataPath{SrcPath: d, WithoutRel: true})
+ }
+
+ fuzz.binaryDecorator.baseCompiler.dir = filepath.Join(
+ "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
+ fuzz.binaryDecorator.baseCompiler.dir64 = filepath.Join(
+ "fuzz", ctx.Target().Arch.ArchType.String(), ctx.ModuleName())
+ fuzz.binaryDecorator.baseCompiler.installTestData(ctx, fuzzData)
+
+ fuzz.binaryDecorator.baseCompiler.install(ctx)
+
}
diff --git a/rust/image.go b/rust/image.go
index c2e250c..530c56e 100644
--- a/rust/image.go
+++ b/rust/image.go
@@ -117,20 +117,16 @@
return false
}
-func (ctx *moduleContext) SocSpecific() bool {
+func (mod *Module) InstallInVendor() bool {
// Additionally check if this module is inVendor() that means it is a "vendor" variant of a
// module. As well as SoC specific modules, vendor variants must be installed to /vendor
// unless they have "odm_available: true".
- return ctx.ModuleContext.SocSpecific() || (ctx.RustModule().InVendor() && !ctx.RustModule().VendorVariantToOdm())
+ return mod.InVendor() && !mod.VendorVariantToOdm()
}
-func (ctx *moduleContext) DeviceSpecific() bool {
+func (mod *Module) InstallInOdm() bool {
// Some vendor variants want to be installed to /odm by setting "odm_available: true".
- return ctx.ModuleContext.DeviceSpecific() || (ctx.RustModule().InVendor() && ctx.RustModule().VendorVariantToOdm())
-}
-
-func (ctx *moduleContext) SystemExtSpecific() bool {
- return ctx.ModuleContext.SystemExtSpecific()
+ return mod.InVendor() && mod.VendorVariantToOdm()
}
// Returns true when this module creates a vendor variant and wants to install the vendor variant
@@ -188,12 +184,17 @@
}
func (mod *Module) InProduct() bool {
- return mod.Properties.ImageVariationPrefix == cc.ProductVariationPrefix
+ return mod.Properties.ImageVariation == cc.ProductVariation
}
// Returns true if the module is "vendor" variant. Usually these modules are installed in /vendor
func (mod *Module) InVendor() bool {
- return mod.Properties.ImageVariationPrefix == cc.VendorVariationPrefix
+ return mod.Properties.ImageVariation == cc.VendorVariation
+}
+
+// Returns true if the module is "vendor" or "product" variant.
+func (mod *Module) InVendorOrProduct() bool {
+ return mod.InVendor() || mod.InProduct()
}
func (mod *Module) SetImageVariation(ctx android.BaseModuleContext, variant string, module android.Module) {
@@ -202,9 +203,11 @@
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)
+ } else if strings.HasPrefix(variant, cc.VendorVariation) {
+ m.Properties.ImageVariation = cc.VendorVariation
+ if strings.HasPrefix(variant, cc.VendorVariationPrefix) {
+ m.Properties.VndkVersion = strings.TrimPrefix(variant, cc.VendorVariationPrefix)
+ }
// Makefile shouldn't know vendor modules other than BOARD_VNDK_VERSION.
// Hide other vendor variants to avoid collision.
@@ -213,9 +216,11 @@
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)
+ } else if strings.HasPrefix(variant, cc.ProductVariation) {
+ m.Properties.ImageVariation = cc.ProductVariation
+ if strings.HasPrefix(variant, cc.ProductVariationPrefix) {
+ m.Properties.VndkVersion = strings.TrimPrefix(variant, cc.ProductVariationPrefix)
+ }
}
}
diff --git a/rust/library.go b/rust/library.go
index 3f031c1..7f004fc 100644
--- a/rust/library.go
+++ b/rust/library.go
@@ -15,15 +15,13 @@
package rust
import (
+ "errors"
"fmt"
"regexp"
"strings"
"android/soong/android"
- "android/soong/bazel"
"android/soong/cc"
-
- "github.com/google/blueprint/proptools"
)
var (
@@ -401,8 +399,6 @@
func NewRustLibrary(hod android.HostOrDeviceSupported) (*Module, *libraryDecorator) {
module := newModule(hod, android.MultilibBoth)
- android.InitBazelModule(module)
-
library := &libraryDecorator{
MutatedProperties: LibraryMutatedProperties{
BuildDylib: false,
@@ -489,7 +485,7 @@
var outputFile android.ModuleOutPath
var ret buildOutput
var fileName string
- srcPath := library.srcPath(ctx, deps)
+ crateRootPath := crateRootPath(ctx, library)
if library.sourceProvider != nil {
deps.srcProviderFiles = append(deps.srcProviderFiles, library.sourceProvider.Srcs()...)
@@ -525,7 +521,7 @@
flags.RustFlags = append(flags.RustFlags, deps.depFlags...)
flags.LinkFlags = append(flags.LinkFlags, deps.depLinkFlags...)
- flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects.Strings()...)
+ flags.LinkFlags = append(flags.LinkFlags, deps.linkObjects...)
if library.dylib() {
// We need prefer-dynamic for now to avoid linking in the static stdlib. See:
@@ -536,23 +532,22 @@
// Call the appropriate builder for this library type
if library.rlib() {
- ret.kytheFile = TransformSrctoRlib(ctx, srcPath, deps, flags, outputFile).kytheFile
+ ret.kytheFile = TransformSrctoRlib(ctx, crateRootPath, deps, flags, outputFile).kytheFile
} else if library.dylib() {
- ret.kytheFile = TransformSrctoDylib(ctx, srcPath, deps, flags, outputFile).kytheFile
+ ret.kytheFile = TransformSrctoDylib(ctx, crateRootPath, deps, flags, outputFile).kytheFile
} else if library.static() {
- ret.kytheFile = TransformSrctoStatic(ctx, srcPath, deps, flags, outputFile).kytheFile
+ ret.kytheFile = TransformSrctoStatic(ctx, crateRootPath, deps, flags, outputFile).kytheFile
} else if library.shared() {
- ret.kytheFile = TransformSrctoShared(ctx, srcPath, deps, flags, outputFile).kytheFile
+ ret.kytheFile = TransformSrctoShared(ctx, crateRootPath, deps, flags, outputFile).kytheFile
}
if library.rlib() || library.dylib() {
library.flagExporter.exportLinkDirs(deps.linkDirs...)
library.flagExporter.exportLinkObjects(deps.linkObjects...)
- library.flagExporter.exportLibDeps(deps.LibDeps...)
}
if library.static() || library.shared() {
- ctx.SetProvider(cc.FlagExporterInfoProvider, cc.FlagExporterInfo{
+ android.SetProvider(ctx, cc.FlagExporterInfoProvider, cc.FlagExporterInfo{
IncludeDirs: library.includeDirs,
})
}
@@ -564,7 +559,7 @@
library.tocFile = android.OptionalPathForPath(tocFile)
cc.TransformSharedObjectToToc(ctx, outputFile, tocFile)
- ctx.SetProvider(cc.SharedLibraryInfoProvider, cc.SharedLibraryInfo{
+ android.SetProvider(ctx, cc.SharedLibraryInfoProvider, cc.SharedLibraryInfo{
TableOfContents: android.OptionalPathForPath(tocFile),
SharedLibrary: outputFile,
Target: ctx.Target(),
@@ -573,7 +568,7 @@
if library.static() {
depSet := android.NewDepSetBuilder[android.Path](android.TOPOLOGICAL).Direct(outputFile).Build()
- ctx.SetProvider(cc.StaticLibraryInfoProvider, cc.StaticLibraryInfo{
+ android.SetProvider(ctx, cc.StaticLibraryInfoProvider, cc.StaticLibraryInfo{
StaticLibrary: outputFile,
TransitiveStaticLibrariesForOrdering: depSet,
@@ -585,13 +580,16 @@
return ret
}
-func (library *libraryDecorator) srcPath(ctx ModuleContext, _ PathDeps) android.Path {
+func (library *libraryDecorator) checkedCrateRootPath() (android.Path, error) {
if library.sourceProvider != nil {
+ srcs := library.sourceProvider.Srcs()
+ if len(srcs) == 0 {
+ return nil, errors.New("Source provider generated 0 sources")
+ }
// Assume the first source from the source provider is the library entry point.
- return library.sourceProvider.Srcs()[0]
+ return srcs[0], nil
} else {
- path, _ := srcPathFromModuleSrcs(ctx, library.baseCompiler.Properties.Srcs)
- return path
+ return library.baseCompiler.checkedCrateRootPath()
}
}
@@ -606,7 +604,7 @@
return android.OptionalPath{}
}
- return android.OptionalPathForPath(Rustdoc(ctx, library.srcPath(ctx, deps),
+ return android.OptionalPathForPath(Rustdoc(ctx, crateRootPath(ctx, library),
deps, flags))
}
@@ -798,155 +796,3 @@
// TODO(185577950): If support for generated headers is added, they need to be collected here as well.
l.collectedSnapshotHeaders = ret
}
-
-type rustLibraryAttributes struct {
- Srcs bazel.LabelListAttribute
- Compile_data bazel.LabelListAttribute
- Crate_name bazel.StringAttribute
- Edition bazel.StringAttribute
- Crate_features bazel.StringListAttribute
- Deps bazel.LabelListAttribute
- Rustc_flags bazel.StringListAttribute
- Proc_macro_deps bazel.LabelListAttribute
-}
-
-func libraryBp2build(ctx android.TopDownMutatorContext, m *Module) {
- lib := m.compiler.(*libraryDecorator)
-
- srcs, compileData := srcsAndCompileDataAttrs(ctx, *lib.baseCompiler)
-
- deps := android.BazelLabelForModuleDeps(ctx, append(
- lib.baseCompiler.Properties.Rustlibs,
- lib.baseCompiler.Properties.Rlibs...,
- ))
-
- cargoBuildScript := cargoBuildScriptBp2build(ctx, m)
- if cargoBuildScript != nil {
- deps.Add(&bazel.Label{
- Label: ":" + *cargoBuildScript,
- })
- }
-
- procMacroDeps := android.BazelLabelForModuleDeps(ctx, lib.baseCompiler.Properties.Proc_macros)
-
- var rustcFLags []string
- for _, cfg := range lib.baseCompiler.Properties.Cfgs {
- rustcFLags = append(rustcFLags, fmt.Sprintf("--cfg=%s", cfg))
- }
-
- attrs := &rustLibraryAttributes{
- Srcs: bazel.MakeLabelListAttribute(
- srcs,
- ),
- Compile_data: bazel.MakeLabelListAttribute(
- compileData,
- ),
- Crate_name: bazel.StringAttribute{
- Value: &lib.baseCompiler.Properties.Crate_name,
- },
- Edition: bazel.StringAttribute{
- Value: lib.baseCompiler.Properties.Edition,
- },
- Crate_features: bazel.StringListAttribute{
- Value: lib.baseCompiler.Properties.Features,
- },
- Deps: bazel.MakeLabelListAttribute(
- deps,
- ),
- Proc_macro_deps: bazel.MakeLabelListAttribute(
- procMacroDeps,
- ),
- Rustc_flags: bazel.StringListAttribute{
- Value: append(
- rustcFLags,
- lib.baseCompiler.Properties.Flags...,
- ),
- },
- }
-
- // TODO(b/290790800): Remove the restriction when rust toolchain for android is implemented
- var restriction bazel.BoolAttribute
- restriction.SetSelectValue(bazel.OsConfigurationAxis, "android", proptools.BoolPtr(false))
-
- ctx.CreateBazelTargetModuleWithRestrictions(
- bazel.BazelTargetModuleProperties{
- Rule_class: "rust_library",
- Bzl_load_location: "@rules_rust//rust:defs.bzl",
- },
- android.CommonAttributes{
- Name: m.Name(),
- },
- attrs,
- restriction,
- )
-}
-
-type cargoBuildScriptAttributes struct {
- Srcs bazel.LabelListAttribute
- Edition bazel.StringAttribute
- Version bazel.StringAttribute
-}
-
-func cargoBuildScriptBp2build(ctx android.TopDownMutatorContext, m *Module) *string {
- // Soong treats some crates like libprotobuf as special in that they have
- // cargo build script ran to produce an out folder and check it into AOSP
- // For example, https://cs.android.com/android/platform/superproject/main/+/main:external/rust/crates/protobuf/out/
- // is produced by cargo build script https://cs.android.com/android/platform/superproject/main/+/main:external/rust/crates/protobuf/build.rs
- // The out folder is then fed into `rust_library` by a genrule
- // https://cs.android.com/android/platform/superproject/main/+/main:external/rust/crates/protobuf/Android.bp;l=22
- // This allows Soong to decouple from cargo completely.
-
- // Soong decouples from cargo so that it has control over cc compilation.
- // https://cs.android.com/android/platform/superproject/main/+/main:development/scripts/cargo2android.py;l=1033-1041;drc=8449944a50a0445a5ecaf9b7aed12608c81bf3f1
- // generates a `cc_library_static` module to have custom cc flags.
- // Since bp2build will convert the cc modules to cc targets which include the cflags,
- // Bazel does not need to have this optimization.
-
- // Performance-wise: rust_library -> cargo_build_script vs rust_library -> genrule (like Soong)
- // don't have any major difference in build time in Bazel. So using cargo_build_script does not slow
- // down the build.
-
- // The benefit of using `cargo_build_script` here is that it would take care of setting correct
- // `OUT_DIR` for us - similar to what Soong does here
- // https://cs.android.com/android/platform/superproject/main/+/main:build/soong/rust/builder.go;l=202-218;drc=f29ca58e88c5846bbe8955e5192135e5ab4f14a1
-
- // TODO(b/297364081): cargo2android.py has logic for when generate/not cc_library_static and out directory
- // bp2build might be able use the same logic for when to use `cargo_build_script`.
- // For now, we're building libprotobuf_build_script as a one-off until we have a more principled solution
- if m.Name() != "libprotobuf" {
- return nil
- }
-
- lib := m.compiler.(*libraryDecorator)
-
- name := m.Name() + "_build_script"
- attrs := &cargoBuildScriptAttributes{
- Srcs: bazel.MakeLabelListAttribute(
- android.BazelLabelForModuleSrc(ctx, []string{"build.rs"}),
- ),
- Edition: bazel.StringAttribute{
- Value: lib.baseCompiler.Properties.Edition,
- },
- Version: bazel.StringAttribute{
- Value: lib.baseCompiler.Properties.Cargo_pkg_version,
- },
- }
-
- // TODO(b/290790800): Remove the restriction when rust toolchain for android is implemented
- var restriction bazel.BoolAttribute
- restriction.SetSelectValue(bazel.OsConfigurationAxis, "android", proptools.BoolPtr(false))
-
- ctx.CreateBazelTargetModuleWithRestrictions(
- bazel.BazelTargetModuleProperties{
- Rule_class: "cargo_build_script",
- Bzl_load_location: "@rules_rust//cargo:cargo_build_script.bzl",
- },
- android.CommonAttributes{
- Name: name,
- },
- attrs,
- restriction,
- )
-
- return &name
-}
diff --git a/rust/library_test.go b/rust/library_test.go
index 30ef333..e03074d 100644
--- a/rust/library_test.go
+++ b/rust/library_test.go
@@ -148,7 +148,7 @@
libfoo := ctx.ModuleForTests("libfoo", "android_arm64_armv8-a_shared")
- libfooOutput := libfoo.Rule("rustLink")
+ libfooOutput := libfoo.Rule("rustc")
if !strings.Contains(libfooOutput.Args["linkFlags"], "-Wl,-soname=libfoo.so") {
t.Errorf("missing expected -Wl,-soname linker flag for libfoo shared lib, linkFlags: %#v",
libfooOutput.Args["linkFlags"])
diff --git a/rust/prebuilt.go b/rust/prebuilt.go
index fe9d0b5..e35e510 100644
--- a/rust/prebuilt.go
+++ b/rust/prebuilt.go
@@ -76,6 +76,17 @@
var _ exportedFlagsProducer = (*prebuiltProcMacroDecorator)(nil)
var _ rustPrebuilt = (*prebuiltProcMacroDecorator)(nil)
+func prebuiltPath(ctx ModuleContext, prebuilt rustPrebuilt) android.Path {
+ srcs := android.PathsForModuleSrc(ctx, prebuilt.prebuiltSrcs())
+ if len(srcs) == 0 {
+ ctx.PropertyErrorf("srcs", "srcs must not be empty")
+ }
+ if len(srcs) > 1 {
+ ctx.PropertyErrorf("srcs", "prebuilt libraries can only have one entry in srcs (the prebuilt path)")
+ }
+ return srcs[0]
+}
+
func PrebuiltLibraryFactory() android.Module {
module, _ := NewPrebuiltLibrary(android.HostAndDeviceSupported)
return module.Init()
@@ -148,11 +159,7 @@
func (prebuilt *prebuiltLibraryDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
prebuilt.flagExporter.setProvider(ctx)
-
- srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs())
- if len(paths) > 0 {
- ctx.PropertyErrorf("srcs", "prebuilt libraries can only have one entry in srcs (the prebuilt path)")
- }
+ srcPath := prebuiltPath(ctx, prebuilt)
prebuilt.baseCompiler.unstrippedOutputFile = srcPath
return buildOutput{outputFile: srcPath}
}
@@ -205,11 +212,7 @@
func (prebuilt *prebuiltProcMacroDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
prebuilt.flagExporter.exportLinkDirs(android.PathsForModuleSrc(ctx, prebuilt.Properties.Link_dirs).Strings()...)
prebuilt.flagExporter.setProvider(ctx)
-
- srcPath, paths := srcPathFromModuleSrcs(ctx, prebuilt.prebuiltSrcs())
- if len(paths) > 0 {
- ctx.PropertyErrorf("srcs", "prebuilt libraries can only have one entry in srcs (the prebuilt path)")
- }
+ srcPath := prebuiltPath(ctx, prebuilt)
prebuilt.baseCompiler.unstrippedOutputFile = srcPath
return buildOutput{outputFile: srcPath}
}
diff --git a/rust/proc_macro.go b/rust/proc_macro.go
index 26227d0..b491449 100644
--- a/rust/proc_macro.go
+++ b/rust/proc_macro.go
@@ -16,8 +16,6 @@
import (
"android/soong/android"
- "android/soong/bazel"
- "fmt"
)
func init() {
@@ -49,8 +47,6 @@
func NewProcMacro(hod android.HostOrDeviceSupported) (*Module, *procMacroDecorator) {
module := newModule(hod, android.MultilibFirst)
- android.InitBazelModule(module)
-
procMacro := &procMacroDecorator{
baseCompiler: NewBaseCompiler("lib", "lib64", InstallInSystem),
flagExporter: NewFlagExporter(),
@@ -77,8 +73,7 @@
func (procMacro *procMacroDecorator) compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput {
fileName := procMacro.getStem(ctx) + ctx.toolchain().ProcMacroSuffix()
outputFile := android.PathForModuleOut(ctx, fileName)
-
- srcPath, _ := srcPathFromModuleSrcs(ctx, procMacro.baseCompiler.Properties.Srcs)
+ srcPath := crateRootPath(ctx, procMacro)
ret := TransformSrctoProcMacro(ctx, srcPath, deps, flags, outputFile)
procMacro.baseCompiler.unstrippedOutputFile = outputFile
return ret
@@ -103,65 +98,3 @@
// Proc_macros are never installed
return false
}
-
-type procMacroAttributes struct {
- Srcs bazel.LabelListAttribute
- Compile_data bazel.LabelListAttribute
- Crate_name bazel.StringAttribute
- Edition bazel.StringAttribute
- Crate_features bazel.StringListAttribute
- Deps bazel.LabelListAttribute
- Rustc_flags bazel.StringListAttribute
-}
-
-func procMacroBp2build(ctx android.TopDownMutatorContext, m *Module) {
- procMacro := m.compiler.(*procMacroDecorator)
- srcs, compileData := srcsAndCompileDataAttrs(ctx, *procMacro.baseCompiler)
- deps := android.BazelLabelForModuleDeps(ctx, append(
- procMacro.baseCompiler.Properties.Rustlibs,
- procMacro.baseCompiler.Properties.Rlibs...,
- ))
-
- var rustcFLags []string
- for _, cfg := range procMacro.baseCompiler.Properties.Cfgs {
- rustcFLags = append(rustcFLags, fmt.Sprintf("--cfg=%s", cfg))
- }
-
- attrs := &procMacroAttributes{
- Srcs: bazel.MakeLabelListAttribute(
- srcs,
- ),
- Compile_data: bazel.MakeLabelListAttribute(
- compileData,
- ),
- Crate_name: bazel.StringAttribute{
- Value: &procMacro.baseCompiler.Properties.Crate_name,
- },
- Edition: bazel.StringAttribute{
- Value: procMacro.baseCompiler.Properties.Edition,
- },
- Crate_features: bazel.StringListAttribute{
- Value: procMacro.baseCompiler.Properties.Features,
- },
- Deps: bazel.MakeLabelListAttribute(
- deps,
- ),
- Rustc_flags: bazel.StringListAttribute{
- Value: append(
- rustcFLags,
- procMacro.baseCompiler.Properties.Flags...,
- ),
- },
- }
- // m.IsConvertedByBp2build()
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "rust_proc_macro",
- Bzl_load_location: "@rules_rust//rust:defs.bzl",
- },
- android.CommonAttributes{
- Name: m.Name(),
- },
- attrs,
- )
-}
diff --git a/rust/project_json.go b/rust/project_json.go
index 40aa7c7..ad9b690 100644
--- a/rust/project_json.go
+++ b/rust/project_json.go
@@ -17,7 +17,6 @@
import (
"encoding/json"
"fmt"
- "path"
"android/soong/android"
)
@@ -60,8 +59,9 @@
// crateInfo is used during the processing to keep track of the known crates.
type crateInfo struct {
- Idx int // Index of the crate in rustProjectJson.Crates slice.
- Deps map[string]int // The keys are the module names and not the crate names.
+ Idx int // Index of the crate in rustProjectJson.Crates slice.
+ Deps map[string]int // The keys are the module names and not the crate names.
+ Device bool // True if the crate at idx was a device crate
}
type projectGeneratorSingleton struct {
@@ -77,85 +77,6 @@
android.RegisterParallelSingletonType("rust_project_generator", rustProjectGeneratorSingleton)
}
-// sourceProviderVariantSource returns the path to the source file if this
-// module variant should be used as a priority.
-//
-// SourceProvider modules may have multiple variants considered as source
-// (e.g., x86_64 and armv8). For a module available on device, use the source
-// generated for the target. For a host-only module, use the source generated
-// for the host.
-func sourceProviderVariantSource(ctx android.SingletonContext, rModule *Module) (string, bool) {
- rustLib, ok := rModule.compiler.(*libraryDecorator)
- if !ok {
- return "", false
- }
- if rustLib.source() {
- switch rModule.hod {
- case android.HostSupported, android.HostSupportedNoCross:
- if rModule.Target().String() == ctx.Config().BuildOSTarget.String() {
- src := rustLib.sourceProvider.Srcs()[0]
- return src.String(), true
- }
- default:
- if rModule.Target().String() == ctx.Config().AndroidFirstDeviceTarget.String() {
- src := rustLib.sourceProvider.Srcs()[0]
- return src.String(), true
- }
- }
- }
- return "", false
-}
-
-// sourceProviderSource finds the main source file of a source-provider crate.
-func sourceProviderSource(ctx android.SingletonContext, rModule *Module) (string, bool) {
- rustLib, ok := rModule.compiler.(*libraryDecorator)
- if !ok {
- return "", false
- }
- if rustLib.source() {
- // This is a source-variant, check if we are the right variant
- // depending on the module configuration.
- if src, ok := sourceProviderVariantSource(ctx, rModule); ok {
- return src, true
- }
- }
- foundSource := false
- sourceSrc := ""
- // Find the variant with the source and return its.
- ctx.VisitAllModuleVariants(rModule, func(variant android.Module) {
- if foundSource {
- return
- }
- // All variants of a source provider library are libraries.
- rVariant, _ := variant.(*Module)
- variantLib, _ := rVariant.compiler.(*libraryDecorator)
- if variantLib.source() {
- sourceSrc, ok = sourceProviderVariantSource(ctx, rVariant)
- if ok {
- foundSource = true
- }
- }
- })
- if !foundSource {
- ctx.Errorf("No valid source for source provider found: %v\n", rModule)
- }
- return sourceSrc, foundSource
-}
-
-// crateSource finds the main source file (.rs) for a crate.
-func crateSource(ctx android.SingletonContext, rModule *Module, comp *baseCompiler) (string, bool) {
- // Basic libraries, executables and tests.
- srcs := comp.Properties.Srcs
- if len(srcs) != 0 {
- return path.Join(ctx.ModuleDir(rModule), srcs[0]), true
- }
- // SourceProvider libraries.
- if rModule.sourceProvider != nil {
- return sourceProviderSource(ctx, rModule)
- }
- return "", false
-}
-
// mergeDependencies visits all the dependencies for module and updates crate and deps
// with any new dependency.
func (singleton *projectGeneratorSingleton) mergeDependencies(ctx android.SingletonContext,
@@ -167,7 +88,7 @@
return
}
// Skip unsupported modules.
- rChild, compChild, ok := isModuleSupported(ctx, child)
+ rChild, ok := isModuleSupported(ctx, child)
if !ok {
return
}
@@ -175,7 +96,7 @@
var childId int
cInfo, known := singleton.knownCrates[rChild.Name()]
if !known {
- childId, ok = singleton.addCrate(ctx, rChild, compChild)
+ childId, ok = singleton.addCrate(ctx, rChild, make(map[string]int))
if !ok {
return
}
@@ -191,41 +112,25 @@
})
}
-// isModuleSupported returns the RustModule and baseCompiler if the module
+// isModuleSupported returns the RustModule if the module
// should be considered for inclusion in rust-project.json.
-func isModuleSupported(ctx android.SingletonContext, module android.Module) (*Module, *baseCompiler, bool) {
+func isModuleSupported(ctx android.SingletonContext, module android.Module) (*Module, bool) {
rModule, ok := module.(*Module)
if !ok {
- return nil, nil, false
+ return nil, false
}
- if rModule.compiler == nil {
- return nil, nil, false
+ if !rModule.Enabled() {
+ return nil, false
}
- var comp *baseCompiler
- switch c := rModule.compiler.(type) {
- case *libraryDecorator:
- comp = c.baseCompiler
- case *binaryDecorator:
- comp = c.baseCompiler
- case *testDecorator:
- comp = c.binaryDecorator.baseCompiler
- case *procMacroDecorator:
- comp = c.baseCompiler
- case *toolchainLibraryDecorator:
- comp = c.baseCompiler
- default:
- return nil, nil, false
- }
- return rModule, comp, true
+ return rModule, true
}
// addCrate adds a crate to singleton.project.Crates ensuring that required
// dependencies are also added. It returns the index of the new crate in
// singleton.project.Crates
-func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContext, rModule *Module, comp *baseCompiler) (int, bool) {
- rootModule, ok := crateSource(ctx, rModule, comp)
- if !ok {
- ctx.Errorf("Unable to find source for valid module: %v", rModule)
+func (singleton *projectGeneratorSingleton) addCrate(ctx android.SingletonContext, rModule *Module, deps map[string]int) (int, bool) {
+ rootModule, err := rModule.compiler.checkedCrateRootPath()
+ if err != nil {
return 0, false
}
@@ -233,28 +138,33 @@
crate := rustProjectCrate{
DisplayName: rModule.Name(),
- RootModule: rootModule,
- Edition: comp.edition(),
+ RootModule: rootModule.String(),
+ Edition: rModule.compiler.edition(),
Deps: make([]rustProjectDep, 0),
Cfg: make([]string, 0),
Env: make(map[string]string),
ProcMacro: procMacro,
}
- if comp.CargoOutDir().Valid() {
- crate.Env["OUT_DIR"] = comp.CargoOutDir().String()
+ if rModule.compiler.cargoOutDir().Valid() {
+ crate.Env["OUT_DIR"] = rModule.compiler.cargoOutDir().String()
}
- for _, feature := range comp.Properties.Features {
+ for _, feature := range rModule.compiler.features() {
crate.Cfg = append(crate.Cfg, "feature=\""+feature+"\"")
}
- deps := make(map[string]int)
singleton.mergeDependencies(ctx, rModule, &crate, deps)
- idx := len(singleton.project.Crates)
- singleton.knownCrates[rModule.Name()] = crateInfo{Idx: idx, Deps: deps}
- singleton.project.Crates = append(singleton.project.Crates, crate)
+ var idx int
+ if cInfo, ok := singleton.knownCrates[rModule.Name()]; ok {
+ idx = cInfo.Idx
+ singleton.project.Crates[idx] = crate
+ } else {
+ idx = len(singleton.project.Crates)
+ singleton.project.Crates = append(singleton.project.Crates, crate)
+ }
+ singleton.knownCrates[rModule.Name()] = crateInfo{Idx: idx, Deps: deps, Device: rModule.Device()}
return idx, true
}
@@ -262,18 +172,23 @@
// It visits the dependencies of the module depth-first so the dependency ID can be added to the current module. If the
// current module is already in singleton.knownCrates, its dependencies are merged.
func (singleton *projectGeneratorSingleton) appendCrateAndDependencies(ctx android.SingletonContext, module android.Module) {
- rModule, comp, ok := isModuleSupported(ctx, module)
+ rModule, ok := isModuleSupported(ctx, module)
if !ok {
return
}
// If we have seen this crate already; merge any new dependencies.
if cInfo, ok := singleton.knownCrates[module.Name()]; ok {
+ // If we have a new device variant, override the old one
+ if !cInfo.Device && rModule.Device() {
+ singleton.addCrate(ctx, rModule, cInfo.Deps)
+ return
+ }
crate := singleton.project.Crates[cInfo.Idx]
singleton.mergeDependencies(ctx, rModule, &crate, cInfo.Deps)
singleton.project.Crates[cInfo.Idx] = crate
return
}
- singleton.addCrate(ctx, rModule, comp)
+ singleton.addCrate(ctx, rModule, make(map[string]int))
}
func (singleton *projectGeneratorSingleton) GenerateBuildActions(ctx android.SingletonContext) {
diff --git a/rust/protobuf.go b/rust/protobuf.go
index ae82844..0b26b80 100644
--- a/rust/protobuf.go
+++ b/rust/protobuf.go
@@ -19,9 +19,7 @@
"strings"
"android/soong/android"
- "android/soong/bazel"
-
- "github.com/google/blueprint/proptools"
+ "android/soong/cc"
)
var (
@@ -56,26 +54,22 @@
// List of libraries which export include paths required for this module
Header_libs []string `android:"arch_variant,variant_prepend"`
- // Use protobuf version 3.x. This will be deleted once we migrate all current users
- // of protobuf off of 2.x.
- Use_protobuf3 *bool
+ // List of exported include paths containing proto files for dependent rust_protobuf modules.
+ Exported_include_dirs []string
}
type protobufDecorator struct {
*BaseSourceProvider
- Properties ProtobufProperties
- protoNames []string
- grpcNames []string
+ Properties ProtobufProperties
+ protoNames []string
+ additionalCrates []string
+ grpcNames []string
grpcProtoFlags android.ProtoFlags
protoFlags android.ProtoFlags
}
-func (proto *protobufDecorator) useProtobuf3() bool {
- return Bool(proto.Properties.Use_protobuf3)
-}
-
func (proto *protobufDecorator) GenerateSource(ctx ModuleContext, deps PathDeps) android.Path {
var protoFlags android.ProtoFlags
var grpcProtoFlags android.ProtoFlags
@@ -85,12 +79,7 @@
protoFiles := android.PathsForModuleSrc(ctx, proto.Properties.Protos)
grpcFiles := android.PathsForModuleSrc(ctx, proto.Properties.Grpc_protos)
- // For now protobuf2 (the deprecated version) remains the default. This will change in the
- // future as we update the various users.
- protoPluginPath := ctx.Config().HostToolPath(ctx, "protoc-gen-rust-deprecated")
- if proto.useProtobuf3() == true {
- protoPluginPath = ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
- }
+ protoPluginPath := ctx.Config().HostToolPath(ctx, "protoc-gen-rust")
commonProtoFlags = append(commonProtoFlags, defaultProtobufFlags...)
commonProtoFlags = append(commonProtoFlags, proto.Properties.Proto_flags...)
@@ -184,6 +173,10 @@
// stemFile must be first here as the first path in BaseSourceProvider.OutputFiles is the library entry-point.
proto.BaseSourceProvider.OutputFiles = append(android.Paths{stemFile}, outputs.Paths()...)
+ android.SetProvider(ctx, cc.FlagExporterInfoProvider, cc.FlagExporterInfo{
+ IncludeDirs: android.PathsForModuleSrc(ctx, proto.Properties.Exported_include_dirs),
+ })
+
// mod_stem.rs is the entry-point for our library modules, so this is what we return.
return stemFile
}
@@ -192,10 +185,16 @@
lines := []string{
"// @Soong generated Source",
}
+
for _, protoName := range proto.protoNames {
lines = append(lines, fmt.Sprintf("pub mod %s;", protoName))
}
+ for _, crate := range proto.additionalCrates {
+ lines = append(lines, fmt.Sprintf("pub use %s::*;", crate))
+
+ }
+
for _, grpcName := range proto.grpcNames {
lines = append(lines, fmt.Sprintf("pub mod %s;", grpcName))
lines = append(lines, fmt.Sprintf("pub mod %s%s;", grpcName, grpcSuffix))
@@ -204,13 +203,7 @@
lines = append(
lines,
"pub mod empty {",
- " pub use protobuf::well_known_types::Empty;",
- "}",
- "pub mod wrappers {",
- " pub use protobuf::well_known_types::{",
- " DoubleValue, FloatValue, Int64Value, UInt64Value, Int32Value, UInt32Value,",
- " BoolValue, StringValue, BytesValue",
- " };",
+ " pub use protobuf::well_known_types::empty::Empty;",
"}")
}
@@ -223,20 +216,10 @@
func (proto *protobufDecorator) SourceProviderDeps(ctx DepsContext, deps Deps) Deps {
deps = proto.BaseSourceProvider.SourceProviderDeps(ctx, deps)
- useProtobuf3 := proto.useProtobuf3()
- if useProtobuf3 == true {
- deps.Rustlibs = append(deps.Rustlibs, "libprotobuf")
- } else {
- deps.Rustlibs = append(deps.Rustlibs, "libprotobuf_deprecated")
- }
+ deps.Rustlibs = append(deps.Rustlibs, "libprotobuf")
deps.HeaderLibs = append(deps.SharedLibs, proto.Properties.Header_libs...)
if len(proto.Properties.Grpc_protos) > 0 {
- if useProtobuf3 == true {
- ctx.PropertyErrorf("protos", "rust_protobuf with grpc_protos defined must currently use "+
- "`use_protobuf3: false,` in the Android.bp file. This is temporary until the "+
- "grpcio crate is updated to use the current version of the protobuf crate.")
- }
deps.Rustlibs = append(deps.Rustlibs, "libgrpcio", "libfutures")
deps.HeaderLibs = append(deps.HeaderLibs, "libprotobuf-cpp-full")
}
@@ -267,71 +250,5 @@
module := NewSourceProviderModule(hod, protobuf, false, false)
- android.InitBazelModule(module)
-
return module, protobuf
}
-
-type rustProtoAttributes struct {
- Srcs bazel.LabelListAttribute
- Crate_name bazel.StringAttribute
- Deps bazel.LabelListAttribute
-}
-
-type protoLibraryAttributes struct {
- Srcs bazel.LabelListAttribute
-}
-
-func protoLibraryBp2build(ctx android.TopDownMutatorContext, m *Module) {
- var protoFiles []string
-
- for _, propsInterface := range m.sourceProvider.SourceProviderProps() {
- if possibleProps, ok := propsInterface.(*ProtobufProperties); ok {
- protoFiles = possibleProps.Protos
- break
- }
- }
-
- protoLibraryName := m.Name() + "_proto"
-
- protoDeps := bazel.LabelListAttribute{
- Value: bazel.LabelList{
- Includes: []bazel.Label{
- {
- Label: ":" + protoLibraryName,
- OriginalModuleName: m.Name(),
- },
- },
- },
- }
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "proto_library",
- },
- android.CommonAttributes{
- Name: protoLibraryName,
- },
- &protoLibraryAttributes{
- Srcs: bazel.MakeLabelListAttribute(
- android.BazelLabelForModuleSrc(ctx, protoFiles),
- ),
- },
- )
-
- ctx.CreateBazelTargetModule(
- bazel.BazelTargetModuleProperties{
- Rule_class: "rust_proto_library",
- Bzl_load_location: "@rules_rust//proto/protobuf:defs.bzl",
- },
- android.CommonAttributes{
- Name: m.Name(),
- },
- &rustProtoAttributes{
- Crate_name: bazel.StringAttribute{
- Value: proptools.StringPtr(m.CrateName()),
- },
- Deps: protoDeps,
- },
- )
-}
diff --git a/rust/protobuf_test.go b/rust/protobuf_test.go
index b723f3f..cae071b 100644
--- a/rust/protobuf_test.go
+++ b/rust/protobuf_test.go
@@ -21,54 +21,6 @@
"android/soong/android"
)
-func TestRustProtobuf(t *testing.T) {
- ctx := testRust(t, `
- rust_protobuf {
- name: "librust_proto",
- protos: ["buf.proto", "proto.proto"],
- crate_name: "rust_proto",
- source_stem: "buf",
- shared_libs: ["libfoo_shared"],
- static_libs: ["libfoo_static"],
- }
- cc_library_shared {
- name: "libfoo_shared",
- export_include_dirs: ["shared_include"],
- }
- cc_library_static {
- name: "libfoo_static",
- export_include_dirs: ["static_include"],
- }
- `)
- // Check that libprotobuf is added as a dependency.
- librust_proto := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_dylib").Module().(*Module)
- if !android.InList("libprotobuf_deprecated", librust_proto.Properties.AndroidMkDylibs) {
- t.Errorf("libprotobuf_deprecated dependency missing for rust_protobuf (dependency missing from AndroidMkDylibs)")
- }
-
- // Make sure the correct plugin is being used.
- librust_proto_out := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").Output("buf.rs")
- cmd := librust_proto_out.RuleParams.Command
- if w := "protoc-gen-rust-deprecated"; !strings.Contains(cmd, w) {
- t.Errorf("expected %q in %q", w, cmd)
- }
-
- // Check exported include directories
- if w := "-Ishared_include"; !strings.Contains(cmd, w) {
- t.Errorf("expected %q in %q", w, cmd)
- }
- if w := "-Istatic_include"; !strings.Contains(cmd, w) {
- t.Errorf("expected %q in %q", w, cmd)
- }
-
- // Check proto.rs, the second protobuf, is listed as an output
- librust_proto_outputs := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").AllOutputs()
- if android.InList("proto.rs", librust_proto_outputs) {
- t.Errorf("rust_protobuf is not producing multiple outputs; expected 'proto.rs' in list, got: %#v ",
- librust_proto_outputs)
- }
-}
-
func TestRustProtobuf3(t *testing.T) {
ctx := testRust(t, `
rust_protobuf {
@@ -76,7 +28,6 @@
protos: ["buf.proto", "proto.proto"],
crate_name: "rust_proto",
source_stem: "buf",
- use_protobuf3: true,
shared_libs: ["libfoo_shared"],
static_libs: ["libfoo_static"],
}
@@ -118,6 +69,56 @@
}
}
+func TestRustProtobufInclude(t *testing.T) {
+ ctx := testRust(t, `
+ rust_protobuf {
+ name: "librust_proto",
+ protos: ["proto.proto"],
+ crate_name: "rust_proto",
+ source_stem: "proto",
+ rustlibs: ["librust_exported_proto", "libfoo"],
+ }
+ rust_protobuf {
+ name: "librust_exported_proto",
+ protos: ["proto.proto"],
+ crate_name: "rust_exported_proto",
+ source_stem: "exported_proto",
+ exported_include_dirs: ["proto"]
+ }
+ rust_library {
+ name: "libfoo",
+ crate_name: "foo",
+ srcs: ["foo.rs"],
+ }
+ `)
+ // Check that librust_exported_proto is added as additional crate to generate source.
+ librust_proto := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").Module().(*Module).sourceProvider.(*protobufDecorator)
+ if !android.InList("rust_exported_proto", librust_proto.additionalCrates) {
+ t.Errorf("librust_proto should have librust_exported_proto included as an additional crate for generated source, instead got: %#v", librust_proto.additionalCrates)
+ }
+
+ // Make sure the default crates aren't being included.
+ if android.InList("std", librust_proto.additionalCrates) {
+ t.Errorf("librust_proto should not have included libstd as an additional crate for generated source, instead got: %#v", librust_proto.additionalCrates)
+ }
+ if android.InList("protobuf", librust_proto.additionalCrates) {
+ t.Errorf("librust_proto should not have included libprotobuf as an additional crate for generated source, instead got: %#v", librust_proto.additionalCrates)
+ }
+
+ // And make sure that non-protobuf crates aren't getting included either.
+ if android.InList("foo", librust_proto.additionalCrates) {
+ t.Errorf("librust_proto should not have included libfoo as an additional crate for generated source, instead got: %#v", librust_proto.additionalCrates)
+ }
+
+ // Check librust_proto args includes -Iproto
+ librust_proto_rule := ctx.ModuleForTests("librust_proto", "android_arm64_armv8-a_source").Output("proto.rs")
+ cmd := librust_proto_rule.RuleParams.Command
+ if w := "-Iproto"; !strings.Contains(cmd, w) {
+ t.Errorf("expected %q in %q", w, cmd)
+ }
+
+}
+
func TestRustGrpc(t *testing.T) {
ctx := testRust(t, `
rust_protobuf {
diff --git a/rust/rust.go b/rust/rust.go
index 1ee99cd..245ed2e 100644
--- a/rust/rust.go
+++ b/rust/rust.go
@@ -15,12 +15,12 @@
package rust
import (
- "android/soong/bazel"
- "android/soong/bloaty"
- "android/soong/ui/metrics/bp2build_metrics_proto"
"fmt"
"strings"
+ "android/soong/bloaty"
+ "android/soong/testing"
+
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -70,9 +70,9 @@
AndroidMkProcMacroLibs []string `blueprint:"mutated"`
AndroidMkStaticLibs []string `blueprint:"mutated"`
- ImageVariationPrefix string `blueprint:"mutated"`
- VndkVersion string `blueprint:"mutated"`
- SubName string `blueprint:"mutated"`
+ ImageVariation string `blueprint:"mutated"`
+ VndkVersion string `blueprint:"mutated"`
+ SubName string `blueprint:"mutated"`
// SubName is used by CC for tracking image variants / SDK versions. RustSubName is used for Rust-specific
// subnaming which shouldn't be visible to CC modules (such as the rlib stdlinkage subname). This should be
@@ -143,8 +143,9 @@
Properties BaseProperties
- hod android.HostOrDeviceSupported
- multilib android.Multilib
+ hod android.HostOrDeviceSupported
+ multilib android.Multilib
+ testModule bool
makeLinkType string
@@ -172,7 +173,8 @@
transitiveAndroidMkSharedLibs *android.DepSet[string]
- android.BazelModuleBase
+ // Aconfig files for all transitive deps. Also exposed via TransitiveDeclarationsInfo
+ mergedAconfigFiles map[string]android.Paths
}
func (mod *Module) Header() bool {
@@ -266,6 +268,15 @@
return false
}
+func (mod *Module) Source() bool {
+ if mod.compiler != nil {
+ if library, ok := mod.compiler.(libraryInterface); ok && mod.sourceProvider != nil {
+ return library.source()
+ }
+ }
+ return false
+}
+
func (mod *Module) RlibStd() bool {
if mod.compiler != nil {
if library, ok := mod.compiler.(libraryInterface); ok && library.rlib() {
@@ -437,12 +448,13 @@
}
type PathDeps struct {
- DyLibs RustLibraries
- RLibs RustLibraries
- LibDeps android.Paths
- WholeStaticLibs android.Paths
- ProcMacros RustLibraries
- AfdoProfiles android.Paths
+ DyLibs RustLibraries
+ RLibs RustLibraries
+ SharedLibs android.Paths
+ SharedLibDeps android.Paths
+ StaticLibs android.Paths
+ ProcMacros RustLibraries
+ AfdoProfiles android.Paths
// depFlags and depLinkFlags are rustc and linker (clang) flags.
depFlags []string
@@ -451,7 +463,7 @@
// linkDirs are link paths passed via -L to rustc. linkObjects are objects passed directly to the linker.
// Both of these are exported and propagate to dependencies.
linkDirs []string
- linkObjects android.Paths
+ linkObjects []string
// Used by bindgen modules which call clang
depClangFlags []string
@@ -474,47 +486,9 @@
CrateName string
}
-type compiler interface {
- initialize(ctx ModuleContext)
- compilerFlags(ctx ModuleContext, flags Flags) Flags
- cfgFlags(ctx ModuleContext, flags Flags) Flags
- featureFlags(ctx ModuleContext, flags Flags) Flags
- compilerProps() []interface{}
- compile(ctx ModuleContext, flags Flags, deps PathDeps) buildOutput
- compilerDeps(ctx DepsContext, deps Deps) Deps
- crateName() string
- rustdoc(ctx ModuleContext, flags Flags, deps PathDeps) android.OptionalPath
-
- // Output directory in which source-generated code from dependencies is
- // copied. This is equivalent to Cargo's OUT_DIR variable.
- CargoOutDir() android.OptionalPath
-
- // CargoPkgVersion returns the value of the Cargo_pkg_version property.
- CargoPkgVersion() string
-
- // CargoEnvCompat returns whether Cargo environment variables should be used.
- CargoEnvCompat() bool
-
- inData() bool
- install(ctx ModuleContext)
- relativeInstallPath() string
- everInstallable() bool
-
- nativeCoverage() bool
-
- Disabled() bool
- SetDisabled()
-
- stdLinkage(ctx *depsContext) RustLinkage
- noStdlibs() bool
-
- unstrippedOutputFilePath() android.Path
- strippedOutputFilePath() android.OptionalPath
-}
-
type exportedFlagsProducer interface {
exportLinkDirs(...string)
- exportLinkObjects(...android.Path)
+ exportLinkObjects(...string)
}
type xref interface {
@@ -523,27 +497,21 @@
type flagExporter struct {
linkDirs []string
- linkObjects android.Paths
- libDeps android.Paths
+ linkObjects []string
}
func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) {
flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...))
}
-func (flagExporter *flagExporter) exportLinkObjects(flags ...android.Path) {
- flagExporter.linkObjects = android.FirstUniquePaths(append(flagExporter.linkObjects, flags...))
-}
-
-func (flagExporter *flagExporter) exportLibDeps(paths ...android.Path) {
- flagExporter.libDeps = android.FirstUniquePaths(append(flagExporter.libDeps, paths...))
+func (flagExporter *flagExporter) exportLinkObjects(flags ...string) {
+ flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...))
}
func (flagExporter *flagExporter) setProvider(ctx ModuleContext) {
- ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{
+ android.SetProvider(ctx, FlagExporterInfoProvider, FlagExporterInfo{
LinkDirs: flagExporter.linkDirs,
LinkObjects: flagExporter.linkObjects,
- LibDeps: flagExporter.libDeps,
})
}
@@ -556,11 +524,10 @@
type FlagExporterInfo struct {
Flags []string
LinkDirs []string // TODO: this should be android.Paths
- LinkObjects android.Paths
- LibDeps android.Paths
+ LinkObjects []string // TODO: this should be android.Paths
}
-var FlagExporterInfoProvider = blueprint.NewProvider(FlagExporterInfo{})
+var FlagExporterInfoProvider = blueprint.NewProvider[FlagExporterInfo]()
func (mod *Module) isCoverageVariant() bool {
return mod.coverage.Properties.IsCoverageVariant
@@ -568,7 +535,7 @@
var _ cc.Coverage = (*Module)(nil)
-func (mod *Module) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool {
+func (mod *Module) IsNativeCoverageNeeded(ctx android.IncomingTransitionContext) bool {
return mod.coverage != nil && mod.coverage.Properties.NeedCoverageVariant
}
@@ -780,7 +747,8 @@
}
func (ctx moduleContext) apexVariationName() string {
- return ctx.Provider(android.ApexInfoProvider).(android.ApexInfo).ApexVariationName
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
+ return apexInfo.ApexVariationName
}
var _ cc.LinkableInterface = (*Module)(nil)
@@ -930,7 +898,7 @@
ModuleContext: actx,
}
- apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(actx, android.ApexInfoProvider)
if !apexInfo.IsForPlatform() {
mod.hideApexVariantFromMake = true
}
@@ -983,6 +951,7 @@
sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator)
mod.sourceProvider.setOutputFiles(sourceLib.sourceProvider.Srcs())
}
+ android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: mod.sourceProvider.Srcs().Strings()})
}
if mod.compiler != nil && !mod.compiler.Disabled() {
@@ -1010,7 +979,7 @@
}
}
- apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(actx, android.ApexInfoProvider)
if !proptools.BoolDefault(mod.Installable(), mod.EverInstallable()) && !mod.ProcMacro() {
// If the module has been specifically configure to not be installed then
// hide from make as otherwise it will break when running inside make as the
@@ -1034,6 +1003,11 @@
ctx.Phony("rust", ctx.RustModule().OutputFile().Path())
}
+ if mod.testModule {
+ android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
+ }
+
+ android.CollectDependencyAconfigFiles(ctx, &mod.mergedAconfigFiles)
}
func (mod *Module) deps(ctx DepsContext) Deps {
@@ -1155,6 +1129,13 @@
return cc.MakeLibName(ctx, c, dep, depName)
}
+func collectIncludedProtos(mod *Module, dep *Module) {
+ if protoMod, ok := mod.sourceProvider.(*protobufDecorator); ok {
+ if _, ok := dep.sourceProvider.(*protobufDecorator); ok {
+ protoMod.additionalCrates = append(protoMod.additionalCrates, dep.CrateName())
+ }
+ }
+}
func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
var depPaths PathDeps
@@ -1168,7 +1149,7 @@
// For the dependency from platform to apex, use the latest stubs
mod.apexSdkVersion = android.FutureApiLevel
- apexInfo := ctx.Provider(android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.ModuleProvider(ctx, android.ApexInfoProvider)
if !apexInfo.IsForPlatform() {
mod.apexSdkVersion = apexInfo.MinSdkVersion
}
@@ -1187,7 +1168,7 @@
ctx.VisitDirectDeps(func(dep android.Module) {
if dep.Name() == "api_imports" {
- apiImportInfo = ctx.OtherModuleProvider(dep, multitree.ApiImportsProvider).(multitree.ApiImportInfo)
+ apiImportInfo, _ = android.OtherModuleProvider(ctx, dep, multitree.ApiImportsProvider)
hasApiImportInfo = true
}
})
@@ -1267,6 +1248,11 @@
case procMacroDepTag:
directProcMacroDeps = append(directProcMacroDeps, rustDep)
mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, makeLibName)
+
+ case sourceDepTag:
+ if _, ok := mod.sourceProvider.(*protobufDecorator); ok {
+ collectIncludedProtos(mod, rustDep)
+ }
}
transitiveAndroidMkSharedLibs = append(transitiveAndroidMkSharedLibs, rustDep.transitiveAndroidMkSharedLibs)
@@ -1293,11 +1279,10 @@
//Append the dependencies exportedDirs, except for proc-macros which target a different arch/OS
if depTag != procMacroDepTag {
- exportedInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
+ exportedInfo, _ := android.OtherModuleProvider(ctx, dep, FlagExporterInfoProvider)
depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...)
depPaths.depFlags = append(depPaths.depFlags, exportedInfo.Flags...)
depPaths.linkObjects = append(depPaths.linkObjects, exportedInfo.LinkObjects...)
- depPaths.LibDeps = append(depPaths.LibDeps, exportedInfo.LibDeps...)
}
if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag {
@@ -1307,7 +1292,14 @@
lib.exportLinkDirs(linkDir)
}
}
-
+ if depTag == sourceDepTag {
+ if _, ok := mod.sourceProvider.(*protobufDecorator); ok && mod.Source() {
+ if _, ok := rustDep.sourceProvider.(*protobufDecorator); ok {
+ exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
+ depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
+ }
+ }
+ }
} else if ccDep, ok := dep.(cc.LinkableInterface); ok {
//Handle C dependencies
makeLibName := cc.MakeLibName(ctx, mod, ccDep, depName)
@@ -1346,7 +1338,6 @@
depPaths.depLinkFlags = append(depPaths.depLinkFlags, []string{"-Wl,--whole-archive", linkObject.Path().String(), "-Wl,--no-whole-archive"}...)
} else if libName, ok := libNameFromFilePath(linkObject.Path()); ok {
depPaths.depFlags = append(depPaths.depFlags, "-lstatic="+libName)
- depPaths.WholeStaticLibs = append(depPaths.WholeStaticLibs, linkObject.Path())
} else {
ctx.ModuleErrorf("'%q' cannot be listed as a whole_static_library in Rust modules unless the output is prefixed by 'lib'", depName, ctx.ModuleName())
}
@@ -1354,10 +1345,10 @@
// Add this to linkObjects to pass the library directly to the linker as well. This propagates
// to dependencies to avoid having to redeclare static libraries for dependents of the dylib variant.
- depPaths.linkObjects = append(depPaths.linkObjects, linkObject.AsPaths()...)
+ depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
- exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
+ exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
@@ -1388,7 +1379,7 @@
linkPath = linkPathFromFilePath(linkObject.Path())
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
- depPaths.linkObjects = append(depPaths.linkObjects, linkObject.AsPaths()...)
+ depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
@@ -1401,7 +1392,7 @@
directAndroidMkSharedLibs = append(directAndroidMkSharedLibs, makeLibName)
exportDep = true
case cc.IsHeaderDepTag(depTag):
- exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
+ exportedInfo, _ := android.OtherModuleProvider(ctx, dep, cc.FlagExporterInfoProvider)
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
@@ -1414,9 +1405,7 @@
// Make sure these dependencies are propagated
if lib, ok := mod.compiler.(exportedFlagsProducer); ok && exportDep {
lib.exportLinkDirs(linkPath)
- if linkObject.Valid() {
- lib.exportLinkObjects(linkObject.Path())
- }
+ lib.exportLinkObjects(linkObject.String())
}
} else {
switch {
@@ -1450,16 +1439,19 @@
procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.UnstrippedOutputFile(), CrateName: dep.CrateName()})
}
- var libDepFiles android.Paths
+ var staticLibDepFiles android.Paths
for _, dep := range directStaticLibDeps {
- libDepFiles = append(libDepFiles, dep.OutputFile().Path())
+ staticLibDepFiles = append(staticLibDepFiles, dep.OutputFile().Path())
}
+ var sharedLibFiles android.Paths
+ var sharedLibDepFiles android.Paths
for _, dep := range directSharedLibDeps {
+ sharedLibFiles = append(sharedLibFiles, dep.SharedLibrary)
if dep.TableOfContents.Valid() {
- libDepFiles = append(libDepFiles, dep.TableOfContents.Path())
+ sharedLibDepFiles = append(sharedLibDepFiles, dep.TableOfContents.Path())
} else {
- libDepFiles = append(libDepFiles, dep.SharedLibrary)
+ sharedLibDepFiles = append(sharedLibDepFiles, dep.SharedLibrary)
}
}
@@ -1475,13 +1467,15 @@
depPaths.RLibs = append(depPaths.RLibs, rlibDepFiles...)
depPaths.DyLibs = append(depPaths.DyLibs, dylibDepFiles...)
- depPaths.LibDeps = append(depPaths.LibDeps, libDepFiles...)
+ depPaths.SharedLibs = append(depPaths.SharedLibs, sharedLibFiles...)
+ depPaths.SharedLibDeps = append(depPaths.SharedLibDeps, sharedLibDepFiles...)
+ depPaths.StaticLibs = append(depPaths.StaticLibs, staticLibDepFiles...)
depPaths.ProcMacros = append(depPaths.ProcMacros, procMacroDepFiles...)
depPaths.SrcDeps = append(depPaths.SrcDeps, srcProviderDepFiles...)
// Dedup exported flags from dependencies
depPaths.linkDirs = android.FirstUniqueStrings(depPaths.linkDirs)
- depPaths.linkObjects = android.FirstUniquePaths(depPaths.linkObjects)
+ depPaths.linkObjects = android.FirstUniqueStrings(depPaths.linkObjects)
depPaths.depFlags = android.FirstUniqueStrings(depPaths.depFlags)
depPaths.depClangFlags = android.FirstUniqueStrings(depPaths.depClangFlags)
depPaths.depIncludePaths = android.FirstUniquePaths(depPaths.depIncludePaths)
@@ -1571,30 +1565,43 @@
}
// rustlibs
- if deps.Rustlibs != nil && !mod.compiler.Disabled() {
- autoDep := mod.compiler.(autoDeppable).autoDep(ctx)
- for _, lib := range deps.Rustlibs {
- if autoDep.depTag == rlibDepTag {
- // Handle the rlib deptag case
- addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations)
- } else {
- // autoDep.depTag is a dylib depTag. Not all rustlibs may be available as a dylib however.
- // Check for the existence of the dylib deptag variant. Select it if available,
- // otherwise select the rlib variant.
- autoDepVariations := append(commonDepVariations,
- blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation})
-
- replacementLib := cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Dylibs)
-
- if actx.OtherModuleDependencyVariantExists(autoDepVariations, replacementLib) {
- addDylibDependency(actx, lib, mod, &snapshotInfo, autoDepVariations, autoDep.depTag)
- } else {
- // If there's no dylib dependency available, try to add the rlib dependency instead.
+ if deps.Rustlibs != nil {
+ if !mod.compiler.Disabled() {
+ for _, lib := range deps.Rustlibs {
+ autoDep := mod.compiler.(autoDeppable).autoDep(ctx)
+ if autoDep.depTag == rlibDepTag {
+ // Handle the rlib deptag case
addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations)
+ } else {
+ // autoDep.depTag is a dylib depTag. Not all rustlibs may be available as a dylib however.
+ // Check for the existence of the dylib deptag variant. Select it if available,
+ // otherwise select the rlib variant.
+ autoDepVariations := append(commonDepVariations,
+ blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation})
+
+ replacementLib := cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Dylibs)
+
+ if actx.OtherModuleDependencyVariantExists(autoDepVariations, replacementLib) {
+ addDylibDependency(actx, lib, mod, &snapshotInfo, autoDepVariations, autoDep.depTag)
+ } else {
+ // If there's no dylib dependency available, try to add the rlib dependency instead.
+ addRlibDependency(actx, lib, mod, &snapshotInfo, rlibDepVariations)
+ }
+ }
+ }
+ } else if _, ok := mod.sourceProvider.(*protobufDecorator); ok {
+ for _, lib := range deps.Rustlibs {
+ replacementLib := cc.GetReplaceModuleName(lib, cc.GetSnapshot(mod, &snapshotInfo, actx).Dylibs)
+ srcProviderVariations := append(commonDepVariations,
+ blueprint.Variation{Mutator: "rust_libraries", Variation: "source"})
+
+ if actx.OtherModuleDependencyVariantExists(srcProviderVariations, replacementLib) {
+ actx.AddVariationDependencies(srcProviderVariations, sourceDepTag, lib)
}
}
}
}
+
// stdlibs
if deps.Stdlibs != nil {
if mod.compiler.stdLinkage(ctx) == RlibLinkage {
@@ -1845,46 +1852,6 @@
return ""
}
-func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- if ctx.ModuleType() == "rust_library_host" || ctx.ModuleType() == "rust_library" {
- libraryBp2build(ctx, m)
- } else if ctx.ModuleType() == "rust_proc_macro" {
- procMacroBp2build(ctx, m)
- } else if ctx.ModuleType() == "rust_binary_host" {
- binaryBp2build(ctx, m)
- } else if ctx.ModuleType() == "rust_protobuf_host" {
- protoLibraryBp2build(ctx, m)
- } else {
- ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "")
- }
-}
-
-// This is a workaround by assuming the conventions that rust crate repos are structured
-// while waiting for the sandboxing work to complete.
-// TODO(b/297344471): When crate_root prop is set which enforces inputs sandboxing,
-// always use `srcs` and `compile_data` props to generate `srcs` and `compile_data` attributes
-// instead of using globs.
-func srcsAndCompileDataAttrs(ctx android.TopDownMutatorContext, c baseCompiler) (bazel.LabelList, bazel.LabelList) {
- var srcs bazel.LabelList
- var compileData bazel.LabelList
-
- if c.Properties.Srcs[0] == "src/lib.rs" {
- srcs = android.BazelLabelForModuleSrc(ctx, []string{"src/**/*.rs"})
- compileData = android.BazelLabelForModuleSrc(
- ctx,
- []string{
- "src/**/*.proto",
- "examples/**/*.rs",
- "**/*.md",
- },
- )
- } else {
- srcs = android.BazelLabelForModuleSrc(ctx, c.Properties.Srcs)
- }
-
- return srcs, compileData
-}
-
var Bool = proptools.Bool
var BoolDefault = proptools.BoolDefault
var String = proptools.String
diff --git a/rust/rust_test.go b/rust/rust_test.go
index 835114c..d609c2f 100644
--- a/rust/rust_test.go
+++ b/rust/rust_test.go
@@ -40,7 +40,6 @@
PrepareForTestWithRustIncludeVndk,
android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
variables.DeviceVndkVersion = StringPtr("current")
- variables.ProductVndkVersion = StringPtr("current")
variables.Platform_vndk_version = StringPtr("29")
}),
)
@@ -105,7 +104,6 @@
android.FixtureModifyProductVariables(
func(variables android.FixtureProductVariables) {
variables.DeviceVndkVersion = StringPtr(device_version)
- variables.ProductVndkVersion = StringPtr(product_version)
variables.Platform_vndk_version = StringPtr(vndk_version)
},
),
@@ -173,7 +171,6 @@
android.FixtureModifyProductVariables(
func(variables android.FixtureProductVariables) {
variables.DeviceVndkVersion = StringPtr("current")
- variables.ProductVndkVersion = StringPtr("current")
variables.Platform_vndk_version = StringPtr("VER")
},
),
@@ -256,7 +253,6 @@
`)
module := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Module().(*Module)
rustc := ctx.ModuleForTests("librlib", "linux_glibc_x86_64_rlib_rlib-std").Rule("rustc")
- rustLink := ctx.ModuleForTests("fizz-buzz", "linux_glibc_x86_64").Rule("rustLink")
// Since dependencies are added to AndroidMk* properties, we can check these to see if they've been picked up.
if !android.InList("librlib.rlib-std", module.Properties.AndroidMkRlibs) {
@@ -279,16 +275,16 @@
t.Errorf("-lstatic flag not being passed to rustc for static library %#v", rustc.Args["rustcFlags"])
}
- if !strings.Contains(rustLink.Args["linkFlags"], "cc_stubs_dep.so") {
- t.Errorf("shared cc_library not being passed to rustc linkFlags %#v", rustLink.Args["linkFlags"])
+ if !strings.Contains(rustc.Args["linkFlags"], "cc_stubs_dep.so") {
+ t.Errorf("shared cc_library not being passed to rustc linkFlags %#v", rustc.Args["linkFlags"])
}
- if !android.SuffixInList(rustLink.OrderOnly.Strings(), "cc_stubs_dep.so") {
- t.Errorf("shared cc dep not being passed as order-only to rustc %#v", rustLink.OrderOnly.Strings())
+ if !android.SuffixInList(rustc.OrderOnly.Strings(), "cc_stubs_dep.so") {
+ t.Errorf("shared cc dep not being passed as order-only to rustc %#v", rustc.OrderOnly.Strings())
}
- if !android.SuffixInList(rustLink.Implicits.Strings(), "cc_stubs_dep.so.toc") {
- t.Errorf("shared cc dep TOC not being passed as implicit to rustc %#v", rustLink.Implicits.Strings())
+ if !android.SuffixInList(rustc.Implicits.Strings(), "cc_stubs_dep.so.toc") {
+ t.Errorf("shared cc dep TOC not being passed as implicit to rustc %#v", rustc.Implicits.Strings())
}
}
diff --git a/rust/sanitize.go b/rust/sanitize.go
index 2f5afd7..9dda43f 100644
--- a/rust/sanitize.go
+++ b/rust/sanitize.go
@@ -203,6 +203,11 @@
s.Address = nil
}
+ // TODO: Remove once b/304507701 is resolved
+ if Bool(s.Address) && ctx.Host() {
+ s.Address = nil
+ }
+
// Memtag_heap is only implemented on AArch64.
if ctx.Arch().ArchType != android.Arm64 || !ctx.Os().Bionic() {
s.Memtag_heap = nil
@@ -265,7 +270,7 @@
}
// If we're using snapshots, redirect to snapshot whenever possible
// TODO(b/178470649): clean manual snapshot redirections
- snapshot := mctx.Provider(cc.SnapshotInfoProvider).(cc.SnapshotInfo)
+ snapshot, _ := android.ModuleProvider(mctx, cc.SnapshotInfoProvider)
if lib, ok := snapshot.StaticLibs[noteDep]; ok {
noteDep = lib
}
diff --git a/rust/sanitize_test.go b/rust/sanitize_test.go
index 43e95f4..d6a14b2 100644
--- a/rust/sanitize_test.go
+++ b/rust/sanitize_test.go
@@ -35,7 +35,7 @@
note_sync := "note_memtag_heap_sync"
found := None
- implicits := m.Rule("rustLink").Implicits
+ implicits := m.Rule("rustc").Implicits
for _, lib := range implicits {
if strings.Contains(lib.Rel(), note_async) {
found = Async
diff --git a/rust/test.go b/rust/test.go
index 4b5296e..2583893 100644
--- a/rust/test.go
+++ b/rust/test.go
@@ -117,7 +117,7 @@
func (test *testDecorator) install(ctx ModuleContext) {
testInstallBase := "/data/local/tests/unrestricted"
- if ctx.RustModule().InVendor() || ctx.RustModule().UseVndk() {
+ if ctx.RustModule().InVendorOrProduct() {
testInstallBase = "/data/local/tests/vendor"
}
@@ -189,6 +189,7 @@
if ctx.Host() && test.Properties.Test_options.Unit_test == nil {
test.Properties.Test_options.Unit_test = proptools.BoolPtr(true)
}
+ test.binaryDecorator.installTestData(ctx, test.data)
test.binaryDecorator.install(ctx)
}
@@ -222,11 +223,13 @@
// rustTestHostMultilib load hook to set MultilibFirst for the
// host target.
android.AddLoadHook(module, rustTestHostMultilib)
+ module.testModule = true
return module.Init()
}
func RustTestHostFactory() android.Module {
module, _ := NewRustTest(android.HostSupported)
+ module.testModule = true
return module.Init()
}
diff --git a/rust/test_test.go b/rust/test_test.go
index 8906f1c..6d0ebcf 100644
--- a/rust/test_test.go
+++ b/rust/test_test.go
@@ -38,7 +38,7 @@
dataPaths := testingModule.Module().(*Module).compiler.(*testDecorator).dataPaths()
if len(dataPaths) != 1 {
- t.Errorf("expected exactly one test data file. test data files: [%s]", dataPaths)
+ t.Errorf("expected exactly one test data file. test data files: [%v]", dataPaths)
return
}
}
@@ -116,7 +116,7 @@
t.Fatalf("expected exactly one output file. output files: [%s]", outputFiles)
}
if len(testBinary.dataPaths()) != 2 {
- t.Fatalf("expected exactly two test data files. test data files: [%s]", testBinary.dataPaths())
+ t.Fatalf("expected exactly two test data files. test data files: [%v]", testBinary.dataPaths())
}
outputPath := outputFiles[0].String()
@@ -178,7 +178,7 @@
t.Fatalf("expected exactly one output file. output files: [%s]", outputFiles)
}
if len(testBinary.dataPaths()) != 3 {
- t.Fatalf("expected exactly two test data files. test data files: [%s]", testBinary.dataPaths())
+ t.Fatalf("expected exactly two test data files. test data files: [%v]", testBinary.dataPaths())
}
outputPath := outputFiles[0].String()
diff --git a/rust/testing.go b/rust/testing.go
index 3fe751e..0b34c97 100644
--- a/rust/testing.go
+++ b/rust/testing.go
@@ -133,12 +133,6 @@
host_supported: true,
}
rust_library {
- name: "libprotobuf_deprecated",
- crate_name: "protobuf",
- srcs: ["foo.rs"],
- host_supported: true,
- }
- rust_library {
name: "libgrpcio",
crate_name: "grpcio",
srcs: ["foo.rs"],
diff --git a/rust/toolchain_library.go b/rust/toolchain_library.go
index 326d529..054104c 100644
--- a/rust/toolchain_library.go
+++ b/rust/toolchain_library.go
@@ -18,9 +18,12 @@
import (
"path"
+ "path/filepath"
"android/soong/android"
"android/soong/rust/config"
+
+ "github.com/google/blueprint/proptools"
)
// This module is used to compile the rust toolchain libraries
@@ -33,11 +36,15 @@
rustToolchainLibraryRlibFactory)
android.RegisterModuleType("rust_toolchain_library_dylib",
rustToolchainLibraryDylibFactory)
+ android.RegisterModuleType("rust_toolchain_rustc_prebuilt",
+ rustToolchainRustcPrebuiltFactory)
}
type toolchainLibraryProperties struct {
- // path to the toolchain source, relative to the top of the toolchain source
- Toolchain_src *string `android:"arch_variant"`
+ // path to the toolchain crate root, relative to the top of the toolchain source
+ Toolchain_crate_root *string `android:"arch_variant"`
+ // path to the rest of the toolchain srcs, relative to the top of the toolchain source
+ Toolchain_srcs []string `android:"arch_variant"`
}
type toolchainLibraryDecorator struct {
@@ -82,16 +89,21 @@
func rustSetToolchainSource(ctx android.LoadHookContext) {
if toolchainLib, ok := ctx.Module().(*Module).compiler.(*toolchainLibraryDecorator); ok {
- prefix := "linux-x86/" + GetRustPrebuiltVersion(ctx)
- newSrcs := []string{path.Join(prefix, android.String(toolchainLib.Properties.Toolchain_src))}
+ prefix := filepath.Join("linux-x86", GetRustPrebuiltVersion(ctx))
+ versionedCrateRoot := path.Join(prefix, android.String(toolchainLib.Properties.Toolchain_crate_root))
+ versionedSrcs := make([]string, len(toolchainLib.Properties.Toolchain_srcs))
+ for i, src := range toolchainLib.Properties.Toolchain_srcs {
+ versionedSrcs[i] = path.Join(prefix, src)
+ }
type props struct {
- Srcs []string
+ Crate_root *string
+ Srcs []string
}
p := &props{}
- p.Srcs = newSrcs
+ p.Crate_root = &versionedCrateRoot
+ p.Srcs = versionedSrcs
ctx.AppendProperties(p)
-
} else {
ctx.ModuleErrorf("Called rustSetToolchainSource on a non-Rust Module.")
}
@@ -101,3 +113,47 @@
func GetRustPrebuiltVersion(ctx android.LoadHookContext) string {
return ctx.AConfig().GetenvWithDefault("RUST_PREBUILTS_VERSION", config.RustDefaultVersion)
}
+
+type toolchainRustcPrebuiltProperties struct {
+ // path to rustc prebuilt, relative to the top of the toolchain source
+ Toolchain_prebuilt_src *string
+ // path to deps, relative to the top of the toolchain source
+ Toolchain_deps []string
+ // path to deps, relative to module directory
+ Deps []string
+}
+
+func rustToolchainRustcPrebuiltFactory() android.Module {
+ module := android.NewPrebuiltBuildTool()
+ module.AddProperties(&toolchainRustcPrebuiltProperties{})
+ android.AddLoadHook(module, func(ctx android.LoadHookContext) {
+ var toolchainProps *toolchainRustcPrebuiltProperties
+ for _, p := range ctx.Module().GetProperties() {
+ toolchainProperties, ok := p.(*toolchainRustcPrebuiltProperties)
+ if ok {
+ toolchainProps = toolchainProperties
+ }
+ }
+
+ if toolchainProps.Toolchain_prebuilt_src == nil {
+ ctx.PropertyErrorf("toolchain_prebuilt_src", "must set path to rustc prebuilt")
+ }
+
+ prefix := filepath.Join(config.HostPrebuiltTag(ctx.Config()), GetRustPrebuiltVersion(ctx))
+ deps := make([]string, 0, len(toolchainProps.Toolchain_deps)+len(toolchainProps.Deps))
+ for _, d := range toolchainProps.Toolchain_deps {
+ deps = append(deps, path.Join(prefix, d))
+ }
+ deps = append(deps, toolchainProps.Deps...)
+
+ props := struct {
+ Src *string
+ Deps []string
+ }{
+ Src: proptools.StringPtr(path.Join(prefix, *toolchainProps.Toolchain_prebuilt_src)),
+ Deps: deps,
+ }
+ ctx.AppendProperties(&props)
+ })
+ return module
+}
diff --git a/rust/vendor_snapshot_test.go b/rust/vendor_snapshot_test.go
index 1e7e7d3..7ebe66b 100644
--- a/rust/vendor_snapshot_test.go
+++ b/rust/vendor_snapshot_test.go
@@ -553,6 +553,7 @@
vendor: true,
nocrt: true,
no_libcrt: true,
+ no_crt_pad_segment: true,
stl: "none",
system_shared_libs: [],
}
@@ -857,6 +858,7 @@
target_arch: "arm64",
compile_multilib: "32",
vendor: true,
+ no_crt_pad_segment: true,
arch: {
arm: {
src: "lib32.so",
@@ -870,6 +872,7 @@
target_arch: "arm64",
compile_multilib: "64",
vendor: true,
+ no_crt_pad_segment: true,
arch: {
arm64: {
src: "lib64.so",
@@ -882,6 +885,7 @@
target_arch: "arm64",
compile_multilib: "64",
vendor: true,
+ no_crt_pad_segment: true,
arch: {
arm64: {
src: "liblog.so",
@@ -913,6 +917,7 @@
target_arch: "arm64",
compile_multilib: "both",
vendor: true,
+ no_crt_pad_segment: true,
arch: {
arm64: {
src: "libvendor_available.so",
@@ -1051,7 +1056,7 @@
ctx := testRustVndkFsVersions(t, "", mockFS, "30", "current", "31")
// libclient uses libvndk.vndk.30.arm64, libvendor.vendor_static.30.arm64, libvendor_without_snapshot
- libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("rustLink").Args["linkFlags"]
+ libclientLdFlags := ctx.ModuleForTests("libclient", sharedVariant).Rule("rustc").Args["linkFlags"]
for _, input := range [][]string{
[]string{sharedVariant, "libvndk.vndk.30.arm64"},
[]string{staticVariant, "libvendor.vendor_static.30.arm64"},
@@ -1119,7 +1124,7 @@
t.Errorf("Unexpected rust rlib name in AndroidMk: %q, expected: %q\n", rustVendorBinMkDylibName, expectedRustVendorSnapshotName)
}
- binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("rustLink").Args["linkFlags"]
+ binWithoutSnapshotLdFlags := ctx.ModuleForTests("bin_without_snapshot", binaryVariant).Rule("rustc").Args["linkFlags"]
libVndkStaticOutputPaths := cc.GetOutputPaths(ctx, staticVariant, []string{"libvndk.vendor_static.30.arm64"})
if !strings.Contains(binWithoutSnapshotLdFlags, libVndkStaticOutputPaths[0].String()) {
t.Errorf("libflags for bin_without_snapshot must contain %#v, but was %#v",
diff --git a/scripts/Android.bp b/scripts/Android.bp
index 97f6ab4..e2fd59f 100644
--- a/scripts/Android.bp
+++ b/scripts/Android.bp
@@ -143,6 +143,39 @@
}
python_library_host {
+ name: "uffd_gc_utils",
+ srcs: [
+ "uffd_gc_utils.py",
+ ],
+ visibility: [
+ "//build/make/tools:__subpackages__",
+ ],
+}
+
+python_test_host {
+ name: "uffd_gc_utils_test",
+ main: "uffd_gc_utils_test.py",
+ srcs: [
+ "uffd_gc_utils_test.py",
+ ],
+ libs: [
+ "uffd_gc_utils",
+ ],
+ test_suites: ["general-tests"],
+}
+
+python_binary_host {
+ name: "construct_uffd_gc_flag",
+ main: "construct_uffd_gc_flag.py",
+ srcs: [
+ "construct_uffd_gc_flag.py",
+ ],
+ libs: [
+ "uffd_gc_utils",
+ ],
+}
+
+python_library_host {
name: "ninja_rsp",
srcs: ["ninja_rsp.py"],
}
@@ -254,3 +287,8 @@
"modify_permissions_allowlist.py",
],
}
+
+sh_binary_host {
+ name: "keep-flagged-apis",
+ src: "keep-flagged-apis.sh",
+}
diff --git a/scripts/build-ndk-prebuilts.sh b/scripts/build-ndk-prebuilts.sh
index 0d14019..ef0f44a 100755
--- a/scripts/build-ndk-prebuilts.sh
+++ b/scripts/build-ndk-prebuilts.sh
@@ -19,9 +19,11 @@
exit 1
fi
+# Note: NDK doesn't support flagging APIs, so we hardcode it to trunk_staging.
# TODO: remove ALLOW_MISSING_DEPENDENCIES=true when all the riscv64
# dependencies exist (currently blocked by http://b/273792258).
# TODO: remove BUILD_BROKEN_DISABLE_BAZEL=1 when bazel supports riscv64 (http://b/262192655).
+TARGET_RELEASE=trunk_staging \
ALLOW_MISSING_DEPENDENCIES=true \
BUILD_BROKEN_DISABLE_BAZEL=1 \
TARGET_PRODUCT=ndk build/soong/soong_ui.bash --make-mode --soong-only ${OUT_DIR}/soong/ndk.timestamp
diff --git a/scripts/check_boot_jars/package_allowed_list.txt b/scripts/check_boot_jars/package_allowed_list.txt
index dad2b47..47eae07 100644
--- a/scripts/check_boot_jars/package_allowed_list.txt
+++ b/scripts/check_boot_jars/package_allowed_list.txt
@@ -44,6 +44,7 @@
java\.util\.jar
java\.util\.logging
java\.util\.prefs
+java\.util\.random
java\.util\.regex
java\.util\.spi
java\.util\.stream
@@ -79,8 +80,10 @@
jdk\.internal\.reflect
jdk\.internal\.util
jdk\.internal\.util\.jar
+jdk\.internal\.util\.random
jdk\.internal\.vm\.annotation
jdk\.net
+jdk\.random
org\.w3c\.dom
org\.w3c\.dom\.ls
org\.w3c\.dom\.traversal
diff --git a/scripts/check_prebuilt_presigned_apk.py b/scripts/check_prebuilt_presigned_apk.py
new file mode 100755
index 0000000..abedfb7
--- /dev/null
+++ b/scripts/check_prebuilt_presigned_apk.py
@@ -0,0 +1,70 @@
+#!/usr/bin/env python3
+
+import subprocess
+import argparse
+import re
+import sys
+import zipfile
+
+def check_target_sdk_less_than_30(args):
+ if not args.aapt2:
+ sys.exit('--aapt2 is required')
+ regex = re.compile(r"targetSdkVersion: *'([0-9]+)'")
+ output = subprocess.check_output([args.aapt2, "dump", "badging", args.apk], text=True)
+ targetSdkVersion = None
+ for line in output.splitlines():
+ match = regex.fullmatch(line.strip())
+ if match:
+ targetSdkVersion = int(match.group(1))
+ break
+
+ if targetSdkVersion is None or targetSdkVersion >= 30:
+ sys.exit(args.apk + ": Prebuilt, presigned apks with targetSdkVersion >= 30 (or a codename targetSdkVersion) must set preprocessed: true in the Android.bp definition (because they must be signed with signature v2, and the build system would wreck that signature otherwise)")
+
+def has_preprocessed_issues(args, *, fail=False):
+ if not args.zipalign:
+ sys.exit('--zipalign is required')
+ ret = subprocess.run([args.zipalign, '-c', '-p', '4', args.apk], stdout=subprocess.DEVNULL).returncode
+ if ret != 0:
+ if fail:
+ sys.exit(args.apk + ': Improper zip alignment')
+ return True
+
+ with zipfile.ZipFile(args.apk) as zf:
+ for info in zf.infolist():
+ if info.filename.startswith('lib/') and info.filename.endswith('.so') and info.compress_type != zipfile.ZIP_STORED:
+ if fail:
+ sys.exit(args.apk + ': Contains compressed JNI libraries')
+ return True
+ # It's ok for non-privileged apps to have compressed dex files, see go/gms-uncompressed-jni-slides
+ if args.privileged:
+ if info.filename.endswith('.dex') and info.compress_type != zipfile.ZIP_STORED:
+ if fail:
+ sys.exit(args.apk + ': Contains compressed dex files and is privileged')
+ return True
+ return False
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--aapt2', help = "the path to the aapt2 executable")
+ parser.add_argument('--zipalign', help = "the path to the zipalign executable")
+ parser.add_argument('--skip-preprocessed-apk-checks', action = 'store_true', help = "the value of the soong property with the same name")
+ parser.add_argument('--preprocessed', action = 'store_true', help = "the value of the soong property with the same name")
+ parser.add_argument('--privileged', action = 'store_true', help = "the value of the soong property with the same name")
+ parser.add_argument('apk', help = "the apk to check")
+ parser.add_argument('stampfile', help = "a file to touch if successful")
+ args = parser.parse_args()
+
+ if not args.preprocessed:
+ check_target_sdk_less_than_30(args)
+ elif args.skip_preprocessed_apk_checks:
+ if not has_preprocessed_issues(args):
+ sys.exit('This module sets `skip_preprocessed_apk_checks: true`, but does not actually have any issues. Please remove `skip_preprocessed_apk_checks`.')
+ else:
+ has_preprocessed_issues(args, fail=True)
+
+ subprocess.check_call(["touch", args.stampfile])
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/check_target_sdk_less_than_30.py b/scripts/check_target_sdk_less_than_30.py
deleted file mode 100755
index 69b0bf0..0000000
--- a/scripts/check_target_sdk_less_than_30.py
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/usr/bin/env python3
-
-import subprocess
-import argparse
-import re
-import sys
-
-def main():
- parser = argparse.ArgumentParser()
- parser.add_argument('aapt2', help = "the path to the aapt2 executable")
- parser.add_argument('apk', help = "the apk to check")
- parser.add_argument('stampfile', help = "a file to touch if successful")
- args = parser.parse_args()
-
- regex = re.compile(r"targetSdkVersion: *'([0-9]+)'")
- output = subprocess.check_output([args.aapt2, "dump", "badging", args.apk], text=True)
- targetSdkVersion = None
- for line in output.splitlines():
- match = regex.fullmatch(line.strip())
- if match:
- targetSdkVersion = int(match.group(1))
- break
-
- if targetSdkVersion is None or targetSdkVersion >= 30:
- sys.exit(args.apk + ": Prebuilt, presigned apks with targetSdkVersion >= 30 (or a codename targetSdkVersion) must set preprocessed: true in the Android.bp definition (because they must be signed with signature v2, and the build system would wreck that signature otherwise)")
-
- subprocess.check_call(["touch", args.stampfile])
-
-if __name__ == "__main__":
- main()
diff --git a/scripts/construct_uffd_gc_flag.py b/scripts/construct_uffd_gc_flag.py
new file mode 100644
index 0000000..f437961
--- /dev/null
+++ b/scripts/construct_uffd_gc_flag.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2024 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.
+#
+"""A tool for constructing UFFD GC flag."""
+
+import argparse
+import os
+
+from uffd_gc_utils import should_enable_uffd_gc
+
+
+def parse_args():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('kernel_version_file')
+ parser.add_argument('output')
+ return parser.parse_args()
+
+def main():
+ args = parse_args()
+ enable_uffd_gc = should_enable_uffd_gc(args.kernel_version_file)
+ flag = '--runtime-arg -Xgc:CMC' if enable_uffd_gc else ''
+ # Prevent the file's mtime from being changed if the contents don't change.
+ # This avoids unnecessary dexpreopt reruns.
+ if os.path.isfile(args.output):
+ with open(args.output, 'r') as f:
+ if f.read() == flag:
+ return
+ with open(args.output, 'w') as f:
+ f.write(flag)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/conv_linker_config.py b/scripts/conv_linker_config.py
index 3ac1b7e..ed3fbb7 100644
--- a/scripts/conv_linker_config.py
+++ b/scripts/conv_linker_config.py
@@ -62,8 +62,8 @@
if args.source:
for input in args.source.split(':'):
pb.MergeFrom(LoadJsonMessage(input))
- with open(args.output, 'wb') as f:
- f.write(pb.SerializeToString())
+
+ ValidateAndWriteAsPbFile(pb, args.output)
def Print(args):
@@ -90,8 +90,8 @@
for item in installed_libraries:
if item not in getattr(pb, 'provideLibs'):
getattr(pb, 'provideLibs').append(item)
- with open(args.output, 'wb') as f:
- f.write(pb.SerializeToString())
+
+ ValidateAndWriteAsPbFile(pb, args.output)
def Append(args):
@@ -106,8 +106,8 @@
else:
setattr(pb, args.key, args.value)
- with open(args.output, 'wb') as f:
- f.write(pb.SerializeToString())
+ ValidateAndWriteAsPbFile(pb, args.output)
+
def Merge(args):
@@ -116,10 +116,68 @@
with open(other, 'rb') as f:
pb.MergeFromString(f.read())
- with open(args.out, 'wb') as f:
+ ValidateAndWriteAsPbFile(pb, args.output)
+
+
+def Validate(args):
+ if os.path.isdir(args.input):
+ config_file = os.path.join(args.input, 'etc/linker.config.pb')
+ if os.path.exists(config_file):
+ args.input = config_file
+ Validate(args)
+ # OK if there's no linker config file.
+ return
+
+ if not os.path.isfile(args.input):
+ sys.exit(f"{args.input} is not a file")
+
+ pb = linker_config_pb2.LinkerConfig()
+ with open(args.input, 'rb') as f:
+ pb.ParseFromString(f.read())
+
+ if args.type == 'apex':
+ # Shouldn't use provideLibs/requireLibs in APEX linker.config.pb
+ if getattr(pb, 'provideLibs'):
+ sys.exit(f'{args.input}: provideLibs is set. Use provideSharedLibs in apex_manifest')
+ if getattr(pb, 'requireLibs'):
+ sys.exit(f'{args.input}: requireLibs is set. Use requireSharedLibs in apex_manifest')
+ elif args.type == 'system':
+ if getattr(pb, 'visible'):
+ sys.exit(f'{args.input}: do not use visible, which is for APEX')
+ if getattr(pb, 'permittedPaths'):
+ sys.exit(f'{args.input}: do not use permittedPaths, which is for APEX')
+ else:
+ sys.exit(f'Unknown type: {args.type}')
+
+ # Reject contributions field at build time while keeping the runtime behavior for GRF.
+ if getattr(pb, 'contributions'):
+ sys.exit(f"{args.input}: 'contributions' is set. "
+ "It's deprecated. Instead, make the APEX 'visible' and use android_dlopen_ext().")
+
+
+def ValidateAndWriteAsPbFile(pb, output_path):
+ ValidateConfiguration(pb)
+ with open(output_path, 'wb') as f:
f.write(pb.SerializeToString())
+def ValidateConfiguration(pb):
+ """
+ Validate if the configuration is valid to be used as linker configuration
+ """
+
+ # Validate if provideLibs and requireLibs have common module
+ provideLibs = set(getattr(pb, 'provideLibs'))
+ requireLibs = set(getattr(pb, 'requireLibs'))
+
+ intersectLibs = provideLibs.intersection(requireLibs)
+
+ if intersectLibs:
+ for lib in intersectLibs:
+ print(f'{lib} exists both in requireLibs and provideLibs', file=sys.stderr)
+ sys.exit(1)
+
+
def GetArgParser():
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers()
@@ -227,6 +285,18 @@
help='Linker configuration files to merge.')
append.set_defaults(func=Merge)
+ validate = subparsers.add_parser('validate', help='Validate configuration')
+ validate.add_argument(
+ '--type',
+ required=True,
+ choices=['apex', 'system'],
+ help='Type of linker configuration')
+ validate.add_argument(
+ 'input',
+ help='Input can be a directory which has etc/linker.config.pb or a path'
+ ' to the linker config file')
+ validate.set_defaults(func=Validate)
+
return parser
diff --git a/scripts/keep-flagged-apis.sh b/scripts/keep-flagged-apis.sh
new file mode 100755
index 0000000..9c48fdb
--- /dev/null
+++ b/scripts/keep-flagged-apis.sh
@@ -0,0 +1,46 @@
+#!/bin/bash -e
+#
+# Copyright 2023 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.
+
+# Convert a list of flags in the input file to a list of metalava options
+# that will keep the APIs for those flags will hiding all other flagged
+# APIs.
+
+FLAGS="$1"
+
+FLAGGED="android.annotation.FlaggedApi"
+
+# Convert the list of feature flags in the input file to Metalava options
+# of the form `--revert-annotation !android.annotation.FlaggedApi("<flag>")`
+# to prevent the annotated APIs from being hidden, i.e. include the annotated
+# APIs in the SDK snapshots. This also preserves the line comments, they will
+# be ignored by Metalava but might be useful when debugging.
+while read -r line; do
+ key=$(echo "$line" | cut -d= -f1)
+ value=$(echo "$line" | cut -d= -f2)
+
+ # Skip if value is not true and line does not start with '#'
+ if [[ ( $value != "true" ) && ( $line =~ ^[^#] )]]; then
+ continue
+ fi
+
+ # Escape and quote the key for sed
+ escaped_key=$(echo "$key" | sed "s/'/\\\'/g; s/ /\\ /g")
+
+ echo $line | sed "s|^[^#].*$|--revert-annotation '!$FLAGGED(\"$escaped_key\")'|"
+done < "$FLAGS"
+
+# Revert all flagged APIs, unless listed above.
+echo "--revert-annotation $FLAGGED"
diff --git a/scripts/lint_project_xml.py b/scripts/lint_project_xml.py
index 3b0158d..c40b07d 100755
--- a/scripts/lint_project_xml.py
+++ b/scripts/lint_project_xml.py
@@ -18,6 +18,7 @@
"""This file generates project.xml and lint.xml files used to drive the Android Lint CLI tool."""
import argparse
+import sys
from xml.dom import minidom
from ninja_rsp import NinjaRspFileReader
@@ -159,8 +160,8 @@
if args.baseline_path:
baseline = minidom.parse(args.baseline_path)
disallowed_issues = check_baseline_for_disallowed_issues(baseline, args.disallowed_issues)
- if bool(disallowed_issues):
- raise RuntimeError('disallowed issues %s found in lint baseline file %s for module %s'
+ if disallowed_issues:
+ sys.exit('disallowed issues %s found in lint baseline file %s for module %s'
% (disallowed_issues, args.baseline_path, args.name))
if args.project_out:
diff --git a/scripts/manifest_check.py b/scripts/manifest_check.py
index c8d4f76..c33b104 100755
--- a/scripts/manifest_check.py
+++ b/scripts/manifest_check.py
@@ -187,18 +187,17 @@
return required, optional, tags
-def extract_uses_libs_xml(xml): #pylint: disable=inconsistent-return-statements
+def extract_uses_libs_xml(xml):
"""Extract <uses-library> tags from the manifest."""
manifest = parse_manifest(xml)
elems = get_children_with_tag(manifest, 'application')
- application = elems[0] if len(elems) == 1 else None
- if len(elems) > 1: #pylint: disable=no-else-raise
+ if len(elems) > 1:
raise RuntimeError('found multiple <application> tags')
- elif not elems:
- if uses_libraries or optional_uses_libraries: #pylint: disable=undefined-variable
- raise ManifestMismatchError('no <application> tag found')
- return
+ if not elems:
+ return [], [], []
+
+ application = elems[0]
libs = get_children_with_tag(application, 'uses-library')
diff --git a/scripts/mkcratersp.py b/scripts/mkcratersp.py
deleted file mode 100755
index 6ef01eb..0000000
--- a/scripts/mkcratersp.py
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-#
-
-"""
-This script is used as a replacement for the Rust linker. It converts a linker
-command line into a rspfile that can be used during the link phase.
-"""
-
-import os
-import shutil
-import subprocess
-import sys
-
-def create_archive(out, objects, archives):
- mricmd = f'create {out}\n'
- for o in objects:
- mricmd += f'addmod {o}\n'
- for a in archives:
- mricmd += f'addlib {a}\n'
- mricmd += 'save\nend\n'
- subprocess.run([os.getenv('AR'), '-M'], encoding='utf-8', input=mricmd, check=True)
-
-objects = []
-archives = []
-linkdirs = []
-libs = []
-temp_archives = []
-version_script = None
-
-for i, arg in enumerate(sys.argv):
- if arg == '-o':
- out = sys.argv[i+1]
- if arg == '-L':
- linkdirs.append(sys.argv[i+1])
- if arg.startswith('-l') or arg == '-shared':
- libs.append(arg)
- if os.getenv('ANDROID_RUST_DARWIN') and (arg == '-dylib' or arg == '-dynamiclib'):
- libs.append(arg)
- if arg.startswith('-Wl,--version-script='):
- version_script = arg[21:]
- if arg[0] == '-':
- continue
- if arg.endswith('.o') or arg.endswith('.rmeta'):
- objects.append(arg)
- if arg.endswith('.rlib'):
- if arg.startswith(os.getenv('TMPDIR')):
- temp_archives.append(arg)
- else:
- archives.append(arg)
-
-create_archive(f'{out}.whole.a', objects, [])
-create_archive(f'{out}.a', [], temp_archives)
-
-with open(out, 'w') as f:
- if os.getenv("ANDROID_RUST_DARWIN"):
- print(f'-force_load', file=f)
- print(f'{out}.whole.a', file=f)
- else:
- print(f'-Wl,--whole-archive', file=f)
- print(f'{out}.whole.a', file=f)
- print(f'-Wl,--no-whole-archive', file=f)
- print(f'{out}.a', file=f)
- for a in archives:
- print(a, file=f)
- for linkdir in linkdirs:
- print(f'-L{linkdir}', file=f)
- for l in libs:
- print(l, file=f)
- if version_script:
- shutil.copyfile(version_script, f'{out}.version_script')
- print(f'-Wl,--version-script={out}.version_script', file=f)
diff --git a/scripts/run-soong-tests-with-go-tools.sh b/scripts/run-soong-tests-with-go-tools.sh
new file mode 100755
index 0000000..93c622e
--- /dev/null
+++ b/scripts/run-soong-tests-with-go-tools.sh
@@ -0,0 +1,79 @@
+#!/bin/bash -ex
+
+: "${OUT_DIR:?Must set OUT_DIR}"
+TOP=$(cd $(dirname $0)/../../..; pwd)
+cd ${TOP}
+
+UNAME="$(uname)"
+case "$UNAME" in
+Linux)
+ OS='linux'
+ ;;
+Darwin)
+ OS='darwin'
+ ;;
+*)
+ exit 1
+ ;;
+esac
+
+# Verify that go test and go build work on all the same projects that are parsed by
+# build/soong/build_kzip.bash
+declare -ar go_modules=(build/blueprint build/soong
+ build/make/tools/canoninja build/make/tools/compliance build/make/tools/rbcrun)
+export GOROOT=${TOP}/prebuilts/go/${OS}-x86
+export GOENV=off
+export GOPROXY=off
+abs_out_dir=$(cd ${OUT_DIR}; pwd)
+export GOPATH=${abs_out_dir}/gopath
+export GOCACHE=${abs_out_dir}/gocache
+export GOMODCACHE=${abs_out_dir}/gomodcache
+export TMPDIR=${abs_out_dir}/gotemp
+mkdir -p ${TMPDIR}
+${GOROOT}/bin/go env
+
+if [[ ${OS} = linux ]]; then
+ # Building with the race detector enabled uses the host linker, set the
+ # path to use the hermetic one.
+ CLANG_VERSION=$(build/soong/scripts/get_clang_version.py)
+ export CC="${TOP}/prebuilts/clang/host/${OS}-x86/${CLANG_VERSION}/bin/clang"
+ export CXX="${TOP}/prebuilts/clang/host/${OS}-x86/${CLANG_VERSION}/bin/clang++"
+fi
+
+# androidmk_test.go gets confused if ANDROID_BUILD_TOP is set.
+unset ANDROID_BUILD_TOP
+
+network_jail=""
+if [[ ${OS} = linux ]]; then
+ # The go tools often try to fetch dependencies from the network,
+ # wrap them in an nsjail to prevent network access.
+ network_jail=${TOP}/prebuilts/build-tools/linux-x86/bin/nsjail
+ # Quiet
+ network_jail="${network_jail} -q"
+ # No timeout
+ network_jail="${network_jail} -t 0"
+ # Set working directory
+ network_jail="${network_jail} --cwd=\$PWD"
+ # Pass environment variables through
+ network_jail="${network_jail} -e"
+ # Allow read-only access to everything
+ network_jail="${network_jail} -R /"
+ # Allow write access to the out directory
+ network_jail="${network_jail} -B ${abs_out_dir}"
+ # Allow write access to the /tmp directory
+ network_jail="${network_jail} -B /tmp"
+ # Set high values, as network_jail uses low defaults.
+ network_jail="${network_jail} --rlimit_as soft"
+ network_jail="${network_jail} --rlimit_core soft"
+ network_jail="${network_jail} --rlimit_cpu soft"
+ network_jail="${network_jail} --rlimit_fsize soft"
+ network_jail="${network_jail} --rlimit_nofile soft"
+fi
+
+for dir in "${go_modules[@]}"; do
+ (cd "$dir";
+ eval ${network_jail} -- ${GOROOT}/bin/go build ./...
+ eval ${network_jail} -- ${GOROOT}/bin/go test ./...
+ eval ${network_jail} -- ${GOROOT}/bin/go test -race -short ./...
+ )
+done
diff --git a/scripts/strip.sh b/scripts/strip.sh
index d09c187..8d69f0d 100755
--- a/scripts/strip.sh
+++ b/scripts/strip.sh
@@ -29,6 +29,7 @@
# --keep-symbols
# --keep-symbols-and-debug-frame
# --remove-build-id
+# --windows
set -o pipefail
@@ -43,6 +44,7 @@
--keep-symbols Keep symbols in out-file
--keep-symbols-and-debug-frame Keep symbols and .debug_frame in out-file
--remove-build-id Remove the gnu build-id section in out-file
+ --windows Input file is Windows DLL or executable
EOF
exit 1
}
@@ -50,7 +52,11 @@
do_strip() {
# GNU strip --strip-all does not strip .ARM.attributes,
# so we tell llvm-strip to keep it too.
- "${CLANG_BIN}/llvm-strip" --strip-all --keep-section=.ARM.attributes "${infile}" -o "${outfile}.tmp"
+ local keep_section=--keep-section=.ARM.attributes
+ if [ -n "${windows}" ]; then
+ keep_section=
+ fi
+ "${CLANG_BIN}/llvm-strip" --strip-all ${keep_section} "${infile}" -o "${outfile}.tmp"
}
do_strip_keep_symbols_and_debug_frame() {
@@ -98,9 +104,17 @@
"${CLANG_BIN}/llvm-strip" --strip-all --keep-section=.ARM.attributes --remove-section=.comment "${infile}" -o "${outfile}.tmp" || fail=true
if [ -z $fail ]; then
- "${CREATE_MINIDEBUGINFO}" "${infile}" "${outfile}.mini_debuginfo.xz"
+ # create_minidebuginfo has issues with compressed debug sections. Just
+ # decompress them for now using objcopy which understands compressed
+ # debug sections.
+ # b/306150780 tracks supporting this directly in create_minidebuginfo
+ decompressed="$(mktemp)"
+ "${CLANG_BIN}/llvm-objcopy" --decompress-debug-sections \
+ "${infile}" "${decompressed}"
+
+ "${CREATE_MINIDEBUGINFO}" "${decompressed}" "${outfile}.mini_debuginfo.xz"
"${CLANG_BIN}/llvm-objcopy" --add-section .gnu_debugdata="${outfile}.mini_debuginfo.xz" "${outfile}.tmp"
- rm -f "${outfile}.mini_debuginfo.xz"
+ rm -f "${outfile}.mini_debuginfo.xz" "${decompressed}"
else
cp -f "${infile}" "${outfile}.tmp"
fi
@@ -141,6 +155,7 @@
keep-symbols) keep_symbols=true ;;
keep-symbols-and-debug-frame) keep_symbols_and_debug_frame=true ;;
remove-build-id) remove_build_id=true ;;
+ windows) windows=true ;;
*) echo "Unknown option --${OPTARG}"; usage ;;
esac;;
?) usage ;;
diff --git a/scripts/uffd_gc_utils.py b/scripts/uffd_gc_utils.py
new file mode 100644
index 0000000..2d35494
--- /dev/null
+++ b/scripts/uffd_gc_utils.py
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2024 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.
+#
+"""Utils to determine whether to enable UFFD GC."""
+
+import re
+import sys
+
+
+def should_enable_uffd_gc(kernel_version_file):
+ with open(kernel_version_file, 'r') as f:
+ kernel_version = f.read().strip()
+ return should_enable_uffd_gc_impl(kernel_version)
+
+def should_enable_uffd_gc_impl(kernel_version):
+ # See https://source.android.com/docs/core/architecture/kernel/gki-versioning#determine-release
+ p = r"^(?P<w>\d+)[.](?P<x>\d+)[.](?P<y>\d+)(-android(?P<z>\d+)-(?P<k>\d+).*$)?"
+ m = re.match(p, kernel_version)
+ if m is not None:
+ if m.group('z') is not None:
+ android_release = int(m.group('z'))
+ # No need to check w, x, y because all Android 12 kernels have backports.
+ return android_release >= 12
+ else:
+ # Old kernel or non-GKI kernel.
+ version = int(m.group('w'))
+ patch_level = int(m.group('x'))
+ if version < 5:
+ # Old kernel.
+ return False
+ elif (version == 5 and patch_level >= 7) or version >= 6:
+ # New non-GKI kernel. 5.7 supports MREMAP_DONTUNMAP without the need for
+ # backports.
+ return True
+ else:
+ # Non-GKI kernel between 5 and 5.6. It may have backports.
+ raise exit_with_error(kernel_version)
+ elif kernel_version == '<unknown-kernel>':
+ # The kernel information isn't available to the build system, probably
+ # because PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS is set to false. We
+ # assume that the kernel supports UFFD GC because it is the case for most of
+ # the products today and it is the future.
+ return True
+ else:
+ # Unrecognizable non-GKI kernel.
+ raise exit_with_error(kernel_version)
+
+def exit_with_error(kernel_version):
+ sys.exit(f"""
+Unable to determine UFFD GC flag for kernel version "{kernel_version}".
+You can fix this by explicitly setting PRODUCT_ENABLE_UFFD_GC to "true" or
+"false" based on the kernel version.
+1. Set PRODUCT_ENABLE_UFFD_GC to "true" if the kernel supports userfaultfd(2)
+ and MREMAP_DONTUNMAP.
+2. Set PRODUCT_ENABLE_UFFD_GC to "false" otherwise.""")
diff --git a/scripts/uffd_gc_utils_test.py b/scripts/uffd_gc_utils_test.py
new file mode 100644
index 0000000..c86ab4b
--- /dev/null
+++ b/scripts/uffd_gc_utils_test.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2024 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 uffd_gc_utils.py."""
+
+import unittest
+
+from uffd_gc_utils import should_enable_uffd_gc_impl
+
+
+class UffdGcUtilsTest(unittest.TestCase):
+ def test_should_enable_uffd_gc_impl(self):
+ # GKI kernels in new format.
+ self.assertTrue(should_enable_uffd_gc_impl(
+ "6.1.25-android14-11-g34fde9ec08a3-ab10675345"))
+ self.assertTrue(should_enable_uffd_gc_impl(
+ "5.4.42-android12-0-something"))
+ self.assertFalse(should_enable_uffd_gc_impl(
+ "5.4.42-android11-0-something"))
+ # GKI kernels in old format.
+ self.assertFalse(should_enable_uffd_gc_impl(
+ "4.19.282-g4b749a433956-ab10893502"))
+ # Non GKI kernels.
+ self.assertTrue(should_enable_uffd_gc_impl(
+ "6.1.25-foo"))
+ self.assertTrue(should_enable_uffd_gc_impl(
+ "6.1.25"))
+ self.assertTrue(should_enable_uffd_gc_impl(
+ "5.10.19-foo"))
+ self.assertTrue(should_enable_uffd_gc_impl(
+ "5.10.19"))
+ with self.assertRaises(SystemExit):
+ should_enable_uffd_gc_impl("5.4.42-foo")
+ with self.assertRaises(SystemExit):
+ should_enable_uffd_gc_impl("5.4.42")
+ self.assertFalse(should_enable_uffd_gc_impl(
+ "4.19.282-foo"))
+ self.assertFalse(should_enable_uffd_gc_impl(
+ "4.19.282"))
+ with self.assertRaises(SystemExit):
+ should_enable_uffd_gc_impl("foo")
+ # No kernel.
+ self.assertTrue(should_enable_uffd_gc_impl(
+ "<unknown-kernel>"))
+
+
+if __name__ == '__main__':
+ unittest.main(verbosity=2)
diff --git a/sdk/Android.bp b/sdk/Android.bp
index f42b478..f436320 100644
--- a/sdk/Android.bp
+++ b/sdk/Android.bp
@@ -18,6 +18,7 @@
"bp.go",
"build_release.go",
"exports.go",
+ "genrule.go",
"member_trait.go",
"member_type.go",
"sdk.go",
@@ -30,6 +31,7 @@
"cc_sdk_test.go",
"compat_config_sdk_test.go",
"exports_test.go",
+ "genrule_test.go",
"java_sdk_test.go",
"license_sdk_test.go",
"member_trait_test.go",
diff --git a/sdk/bootclasspath_fragment_sdk_test.go b/sdk/bootclasspath_fragment_sdk_test.go
index ee1b5db..5d41958 100644
--- a/sdk/bootclasspath_fragment_sdk_test.go
+++ b/sdk/bootclasspath_fragment_sdk_test.go
@@ -206,8 +206,8 @@
checkBootJarsPackageCheckRule(t, result,
append(
[]string{
- "out/soong/.intermediates/prebuilts/apex/com.android.art.deapexer/android_common/deapexer/javalib/core1.jar",
- "out/soong/.intermediates/prebuilts/apex/com.android.art.deapexer/android_common/deapexer/javalib/core2.jar",
+ "out/soong/.intermediates/prebuilts/apex/prebuilt_com.android.art.deapexer/android_common/deapexer/javalib/core1.jar",
+ "out/soong/.intermediates/prebuilts/apex/prebuilt_com.android.art.deapexer/android_common/deapexer/javalib/core2.jar",
"out/soong/.intermediates/default/java/framework/android_common/aligned/framework.jar",
},
java.ApexBootJarDexJarPaths...,
@@ -270,6 +270,12 @@
// Add a platform_bootclasspath that depends on the fragment.
fixtureAddPlatformBootclasspathForBootclasspathFragment("myapex", "mybootclasspathfragment"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
+
android.FixtureWithRootAndroidBp(sdk+`
apex {
name: "myapex",
@@ -489,15 +495,15 @@
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv
.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar
-.intermediates/myothersdklibrary.stubs/android_common/combined/myothersdklibrary.stubs.jar -> sdk_library/public/myothersdklibrary-stubs.jar
-.intermediates/myothersdklibrary.stubs.source/android_common/metalava/myothersdklibrary.stubs.source_api.txt -> sdk_library/public/myothersdklibrary.txt
-.intermediates/myothersdklibrary.stubs.source/android_common/metalava/myothersdklibrary.stubs.source_removed.txt -> sdk_library/public/myothersdklibrary-removed.txt
-.intermediates/mysdklibrary.stubs/android_common/combined/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
-.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
-.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
-.intermediates/mycoreplatform.stubs/android_common/combined/mycoreplatform.stubs.jar -> sdk_library/public/mycoreplatform-stubs.jar
-.intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_api.txt -> sdk_library/public/mycoreplatform.txt
-.intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_removed.txt -> sdk_library/public/mycoreplatform-removed.txt
+.intermediates/myothersdklibrary.stubs.exportable/android_common/combined/myothersdklibrary.stubs.exportable.jar -> sdk_library/public/myothersdklibrary-stubs.jar
+.intermediates/myothersdklibrary.stubs.source/android_common/exportable/myothersdklibrary.stubs.source_api.txt -> sdk_library/public/myothersdklibrary.txt
+.intermediates/myothersdklibrary.stubs.source/android_common/exportable/myothersdklibrary.stubs.source_removed.txt -> sdk_library/public/myothersdklibrary-removed.txt
+.intermediates/mysdklibrary.stubs.exportable/android_common/combined/mysdklibrary.stubs.exportable.jar -> sdk_library/public/mysdklibrary-stubs.jar
+.intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
+.intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
+.intermediates/mycoreplatform.stubs.exportable/android_common/combined/mycoreplatform.stubs.exportable.jar -> sdk_library/public/mycoreplatform-stubs.jar
+.intermediates/mycoreplatform.stubs.source/android_common/exportable/mycoreplatform.stubs.source_api.txt -> sdk_library/public/mycoreplatform.txt
+.intermediates/mycoreplatform.stubs.source/android_common/exportable/mycoreplatform.stubs.source_removed.txt -> sdk_library/public/mycoreplatform-removed.txt
`)
})
@@ -509,15 +515,15 @@
.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv
.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv
.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar
-.intermediates/myothersdklibrary.stubs/android_common/combined/myothersdklibrary.stubs.jar -> sdk_library/public/myothersdklibrary-stubs.jar
-.intermediates/myothersdklibrary.stubs.source/android_common/metalava/myothersdklibrary.stubs.source_api.txt -> sdk_library/public/myothersdklibrary.txt
-.intermediates/myothersdklibrary.stubs.source/android_common/metalava/myothersdklibrary.stubs.source_removed.txt -> sdk_library/public/myothersdklibrary-removed.txt
-.intermediates/mysdklibrary.stubs/android_common/combined/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
-.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
-.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
-.intermediates/mycoreplatform.stubs/android_common/combined/mycoreplatform.stubs.jar -> sdk_library/public/mycoreplatform-stubs.jar
-.intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_api.txt -> sdk_library/public/mycoreplatform.txt
-.intermediates/mycoreplatform.stubs.source/android_common/metalava/mycoreplatform.stubs.source_removed.txt -> sdk_library/public/mycoreplatform-removed.txt
+.intermediates/myothersdklibrary.stubs.exportable/android_common/combined/myothersdklibrary.stubs.exportable.jar -> sdk_library/public/myothersdklibrary-stubs.jar
+.intermediates/myothersdklibrary.stubs.source/android_common/exportable/myothersdklibrary.stubs.source_api.txt -> sdk_library/public/myothersdklibrary.txt
+.intermediates/myothersdklibrary.stubs.source/android_common/exportable/myothersdklibrary.stubs.source_removed.txt -> sdk_library/public/myothersdklibrary-removed.txt
+.intermediates/mysdklibrary.stubs.exportable/android_common/combined/mysdklibrary.stubs.exportable.jar -> sdk_library/public/mysdklibrary-stubs.jar
+.intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
+.intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
+.intermediates/mycoreplatform.stubs.exportable/android_common/combined/mycoreplatform.stubs.exportable.jar -> sdk_library/public/mycoreplatform-stubs.jar
+.intermediates/mycoreplatform.stubs.source/android_common/exportable/mycoreplatform.stubs.source_api.txt -> sdk_library/public/mycoreplatform.txt
+.intermediates/mycoreplatform.stubs.source/android_common/exportable/mycoreplatform.stubs.source_removed.txt -> sdk_library/public/mycoreplatform-removed.txt
`
t.Run("added-via-apex", func(t *testing.T) {
testSnapshotWithBootClasspathFragment_Contents(t, `
@@ -760,6 +766,12 @@
// Add a platform_bootclasspath that depends on the fragment.
fixtureAddPlatformBootclasspathForBootclasspathFragment("myapex", "mybootclasspathfragment"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
+
android.MockFS{
"my-blocked.txt": nil,
"my-max-target-o-low-priority.txt": nil,
@@ -963,12 +975,12 @@
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv
.intermediates/mysdk/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/mybootlib.jar
-.intermediates/mynewlibrary.stubs/android_common/combined/mynewlibrary.stubs.jar -> sdk_library/public/mynewlibrary-stubs.jar
-.intermediates/mynewlibrary.stubs.source/android_common/metalava/mynewlibrary.stubs.source_api.txt -> sdk_library/public/mynewlibrary.txt
-.intermediates/mynewlibrary.stubs.source/android_common/metalava/mynewlibrary.stubs.source_removed.txt -> sdk_library/public/mynewlibrary-removed.txt
-.intermediates/mysdklibrary.stubs/android_common/combined/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
-.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
-.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
+.intermediates/mynewlibrary.stubs.exportable/android_common/combined/mynewlibrary.stubs.exportable.jar -> sdk_library/public/mynewlibrary-stubs.jar
+.intermediates/mynewlibrary.stubs.source/android_common/exportable/mynewlibrary.stubs.source_api.txt -> sdk_library/public/mynewlibrary.txt
+.intermediates/mynewlibrary.stubs.source/android_common/exportable/mynewlibrary.stubs.source_removed.txt -> sdk_library/public/mynewlibrary-removed.txt
+.intermediates/mysdklibrary.stubs.exportable/android_common/combined/mysdklibrary.stubs.exportable.jar -> sdk_library/public/mysdklibrary-stubs.jar
+.intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
+.intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
`),
snapshotTestPreparer(checkSnapshotWithoutSource, preparerForSnapshot),
snapshotTestPreparer(checkSnapshotWithSourcePreferred, preparerForSnapshot),
@@ -997,6 +1009,12 @@
"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": targetBuildRelease,
}),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
+
android.FixtureWithRootAndroidBp(`
sdk {
name: "mysdk",
@@ -1095,15 +1113,15 @@
.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/index.csv -> hiddenapi/index.csv
.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/stub-flags.csv -> hiddenapi/stub-flags.csv
.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi-for-sdk-snapshot/all-flags.csv -> hiddenapi/all-flags.csv
-.intermediates/mysdklibrary.stubs/android_common/combined/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
-.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
-.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
+.intermediates/mysdklibrary.stubs.exportable/android_common/combined/mysdklibrary.stubs.exportable.jar -> sdk_library/public/mysdklibrary-stubs.jar
+.intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
+.intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
`
// On S the stub flags should only be generated from mysdklibrary as mynewsdklibrary is not part
// of the snapshot.
expectedStubFlagsInputs := []string{
- "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar",
+ "out/soong/.intermediates/mysdklibrary.stubs.exportable/android_common/dex/mysdklibrary.stubs.exportable.jar",
"out/soong/.intermediates/mysdklibrary/android_common/aligned/mysdklibrary.jar",
}
@@ -1173,20 +1191,20 @@
.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/signature-patterns.csv -> hiddenapi/signature-patterns.csv
.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-stub-flags.csv -> hiddenapi/filtered-stub-flags.csv
.intermediates/mybootclasspathfragment/android_common_myapex/modular-hiddenapi/filtered-flags.csv -> hiddenapi/filtered-flags.csv
-.intermediates/mysdklibrary.stubs/android_common/combined/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
-.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
-.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
-.intermediates/mynewsdklibrary.stubs/android_common/combined/mynewsdklibrary.stubs.jar -> sdk_library/public/mynewsdklibrary-stubs.jar
-.intermediates/mynewsdklibrary.stubs.source/android_common/metalava/mynewsdklibrary.stubs.source_api.txt -> sdk_library/public/mynewsdklibrary.txt
-.intermediates/mynewsdklibrary.stubs.source/android_common/metalava/mynewsdklibrary.stubs.source_removed.txt -> sdk_library/public/mynewsdklibrary-removed.txt
+.intermediates/mysdklibrary.stubs.exportable/android_common/combined/mysdklibrary.stubs.exportable.jar -> sdk_library/public/mysdklibrary-stubs.jar
+.intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
+.intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
+.intermediates/mynewsdklibrary.stubs.exportable/android_common/combined/mynewsdklibrary.stubs.exportable.jar -> sdk_library/public/mynewsdklibrary-stubs.jar
+.intermediates/mynewsdklibrary.stubs.source/android_common/exportable/mynewsdklibrary.stubs.source_api.txt -> sdk_library/public/mynewsdklibrary.txt
+.intermediates/mynewsdklibrary.stubs.source/android_common/exportable/mynewsdklibrary.stubs.source_removed.txt -> sdk_library/public/mynewsdklibrary-removed.txt
`
// On tiramisu the stub flags should be generated from both mynewsdklibrary and mysdklibrary as
// they are both part of the snapshot.
expectedStubFlagsInputs := []string{
- "out/soong/.intermediates/mynewsdklibrary.stubs/android_common/dex/mynewsdklibrary.stubs.jar",
+ "out/soong/.intermediates/mynewsdklibrary.stubs.exportable/android_common/dex/mynewsdklibrary.stubs.exportable.jar",
"out/soong/.intermediates/mynewsdklibrary/android_common/aligned/mynewsdklibrary.jar",
- "out/soong/.intermediates/mysdklibrary.stubs/android_common/dex/mysdklibrary.stubs.jar",
+ "out/soong/.intermediates/mysdklibrary.stubs.exportable/android_common/dex/mysdklibrary.stubs.exportable.jar",
"out/soong/.intermediates/mysdklibrary/android_common/aligned/mysdklibrary.jar",
}
diff --git a/sdk/genrule.go b/sdk/genrule.go
new file mode 100644
index 0000000..347ab05
--- /dev/null
+++ b/sdk/genrule.go
@@ -0,0 +1,44 @@
+// Copyright 2023 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 sdk
+
+import (
+ "android/soong/android"
+ "android/soong/genrule"
+)
+
+func init() {
+ registerGenRuleBuildComponents(android.InitRegistrationContext)
+}
+
+func registerGenRuleBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("sdk_genrule", SdkGenruleFactory)
+}
+
+// sdk_genrule_host is a genrule that can depend on sdk and sdk_snapshot module types
+//
+// What this means is that it's a genrule with only the "common_os" variant.
+// sdk modules have 3 variants: host, android, and common_os. The common_os one depends
+// on the host/device ones and packages their result into a final snapshot zip.
+// Genrules probably want access to this snapshot zip when they depend on an sdk module,
+// which means they want to depend on the common_os variant and not the host/android
+// variants.
+func SdkGenruleFactory() android.Module {
+ module := genrule.NewGenRule()
+
+ android.InitCommonOSAndroidMultiTargetsArchModule(module, android.NeitherHostNorDeviceSupported, android.MultilibCommon)
+ android.InitDefaultableModule(module)
+
+ return module
+}
diff --git a/sdk/genrule_test.go b/sdk/genrule_test.go
new file mode 100644
index 0000000..6e52a3d
--- /dev/null
+++ b/sdk/genrule_test.go
@@ -0,0 +1,52 @@
+// Copyright 2018 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 sdk
+
+import (
+ "testing"
+
+ "android/soong/android"
+ "android/soong/genrule"
+ "android/soong/java"
+)
+
+func TestSdkGenrule(t *testing.T) {
+ // Test that an sdk_genrule can depend on an sdk, and that a genrule can depend on an sdk_genrule
+ bp := `
+ sdk {
+ name: "my_sdk",
+ }
+ sdk_genrule {
+ name: "my_sdk_genrule",
+ tool_files: ["tool"],
+ cmd: "$(location tool) $(in) $(out)",
+ srcs: [":my_sdk"],
+ out: ["out"],
+ }
+ genrule {
+ name: "my_regular_genrule",
+ srcs: [":my_sdk_genrule"],
+ out: ["out"],
+ cmd: "cp $(in) $(out)",
+ }
+ `
+ android.GroupFixturePreparers(
+ // if java components aren't registered, the sdk module doesn't create a snapshot for some reason.
+ java.PrepareForTestWithJavaBuildComponents,
+ genrule.PrepareForTestWithGenRuleBuildComponents,
+ PrepareForTestWithSdkBuildComponents,
+ android.FixtureRegisterWithContext(registerGenRuleBuildComponents),
+ ).RunTestWithBp(t, bp)
+}
diff --git a/sdk/java_sdk_test.go b/sdk/java_sdk_test.go
index 680494f..1b2b0f1 100644
--- a/sdk/java_sdk_test.go
+++ b/sdk/java_sdk_test.go
@@ -45,6 +45,11 @@
java.PrepareForTestWithJavaDefaultModules,
java.PrepareForTestWithJavaSdkLibraryFiles,
java.FixtureWithLastReleaseApis("myjavalib"),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
)
// Contains tests for SDK members provided by the java package.
@@ -608,6 +613,11 @@
"1": {"myjavalib"},
"2": {"myjavalib"},
}),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTestWithBp(t, `
sdk {
name: "mysdk",
@@ -696,9 +706,9 @@
checkAllCopyRules(`
.intermediates/exported-system-module/android_common/turbine-combined/exported-system-module.jar -> java/exported-system-module.jar
.intermediates/system-module/android_common/turbine-combined/system-module.jar -> java/system-module.jar
-.intermediates/myjavalib.stubs/android_common/combined/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable/android_common/combined/myjavalib.stubs.exportable.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
`),
checkInfoContents(result.Config, `
[
@@ -941,15 +951,15 @@
}
`),
checkAllCopyRules(`
-.intermediates/myjavalib.stubs/android_common/combined/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
-.intermediates/myjavalib.stubs.system/android_common/combined/myjavalib.stubs.system.jar -> sdk_library/system/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source.system/android_common/metalava/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib.txt
-.intermediates/myjavalib.stubs.source.system/android_common/metalava/myjavalib.stubs.source.system_removed.txt -> sdk_library/system/myjavalib-removed.txt
-.intermediates/myjavalib.stubs.test/android_common/combined/myjavalib.stubs.test.jar -> sdk_library/test/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source.test/android_common/metalava/myjavalib.stubs.source.test_api.txt -> sdk_library/test/myjavalib.txt
-.intermediates/myjavalib.stubs.source.test/android_common/metalava/myjavalib.stubs.source.test_removed.txt -> sdk_library/test/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable/android_common/combined/myjavalib.stubs.exportable.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable.system/android_common/combined/myjavalib.stubs.exportable.system.jar -> sdk_library/system/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source.system/android_common/exportable/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib.txt
+.intermediates/myjavalib.stubs.source.system/android_common/exportable/myjavalib.stubs.source.system_removed.txt -> sdk_library/system/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable.test/android_common/combined/myjavalib.stubs.exportable.test.jar -> sdk_library/test/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source.test/android_common/exportable/myjavalib.stubs.source.test_api.txt -> sdk_library/test/myjavalib.txt
+.intermediates/myjavalib.stubs.source.test/android_common/exportable/myjavalib.stubs.source.test_removed.txt -> sdk_library/test/myjavalib-removed.txt
`),
checkMergeZips(
".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
@@ -999,9 +1009,9 @@
}
`),
checkAllCopyRules(`
-.intermediates/myjavalib-foo.stubs/android_common/combined/myjavalib-foo.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
-.intermediates/myjavalib-foo.stubs.source/android_common/metalava/myjavalib-foo.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib-foo.stubs.source/android_common/metalava/myjavalib-foo.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib-foo.stubs.exportable/android_common/combined/myjavalib-foo.stubs.exportable.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib-foo.stubs.source/android_common/exportable/myjavalib-foo.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib-foo.stubs.source/android_common/exportable/myjavalib-foo.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
`),
checkMergeZips(
".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
@@ -1052,10 +1062,10 @@
}
`),
checkAllCopyRules(`
-.intermediates/myjavalib.stubs/android_common/combined/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source-stubs.srcjar -> sdk_library/public/myjavalib.srcjar
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable/android_common/combined/myjavalib.stubs.exportable.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source-stubs.srcjar -> sdk_library/public/myjavalib.srcjar
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
`),
)
}
@@ -1100,10 +1110,10 @@
}
`),
checkAllCopyRules(`
-.intermediates/myjavalib.stubs/android_common/combined/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_annotations.zip -> sdk_library/public/myjavalib_annotations.zip
+.intermediates/myjavalib.stubs.exportable/android_common/combined/myjavalib.stubs.exportable.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_annotations.zip -> sdk_library/public/myjavalib_annotations.zip
`),
checkMergeZips(".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip"),
)
@@ -1153,16 +1163,23 @@
}
`),
checkAllCopyRules(`
-.intermediates/myjavalib.stubs/android_common/combined/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable/android_common/combined/myjavalib.stubs.exportable.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
`),
checkMergeZips(".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip"),
)
}
func TestSnapshotWithJavaSdkLibrary_CompileDex(t *testing.T) {
- result := android.GroupFixturePreparers(prepareForSdkTestWithJavaSdkLibrary).RunTestWithBp(t, `
+ result := android.GroupFixturePreparers(
+ prepareForSdkTestWithJavaSdkLibrary,
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
+ ).RunTestWithBp(t, `
sdk {
name: "mysdk",
java_sdk_libs: ["myjavalib"],
@@ -1214,21 +1231,22 @@
ctx := android.ModuleInstallPathContextForTesting(result.Config)
dexJarBuildPath := func(name string, kind android.SdkKind) string {
dep := result.Module(name, "android_common").(java.SdkLibraryDependency)
- path := dep.SdkApiStubDexJar(ctx, kind).Path()
+ path := dep.SdkApiExportableStubDexJar(ctx, kind).Path()
return path.RelativeToTop().String()
}
dexJarPath := dexJarBuildPath("myjavalib", android.SdkPublic)
- android.AssertStringEquals(t, "source dex public stubs jar build path", "out/soong/.intermediates/myjavalib.stubs/android_common/dex/myjavalib.stubs.jar", dexJarPath)
+ android.AssertStringEquals(t, "source dex public stubs jar build path", "out/soong/.intermediates/myjavalib.stubs.exportable/android_common/dex/myjavalib.stubs.exportable.jar", dexJarPath)
dexJarPath = dexJarBuildPath("myjavalib", android.SdkSystem)
- systemDexJar := "out/soong/.intermediates/myjavalib.stubs.system/android_common/dex/myjavalib.stubs.system.jar"
+ systemDexJar := "out/soong/.intermediates/myjavalib.stubs.exportable.system/android_common/dex/myjavalib.stubs.exportable.system.jar"
android.AssertStringEquals(t, "source dex system stubs jar build path", systemDexJar, dexJarPath)
// This should fall back to system as module is not available.
dexJarPath = dexJarBuildPath("myjavalib", android.SdkModule)
android.AssertStringEquals(t, "source dex module stubs jar build path", systemDexJar, dexJarPath)
+ // Prebuilt dex jar does not come from the exportable stubs.
dexJarPath = dexJarBuildPath(android.PrebuiltNameFromSource("myjavalib"), android.SdkPublic)
android.AssertStringEquals(t, "prebuilt dex public stubs jar build path", "out/soong/.intermediates/snapshot/prebuilt_myjavalib.stubs/android_common/dex/myjavalib.stubs.jar", dexJarPath)
}),
@@ -1270,9 +1288,9 @@
}
`),
checkAllCopyRules(`
-.intermediates/myjavalib.stubs/android_common/combined/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable/android_common/combined/myjavalib.stubs.exportable.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
`),
checkMergeZips(
".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
@@ -1318,9 +1336,9 @@
}
`),
checkAllCopyRules(`
-.intermediates/myjavalib.stubs/android_common/combined/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable/android_common/combined/myjavalib.stubs.exportable.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
`),
checkMergeZips(
".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
@@ -1376,12 +1394,12 @@
}
`),
checkAllCopyRules(`
-.intermediates/myjavalib.stubs/android_common/combined/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
-.intermediates/myjavalib.stubs.system/android_common/combined/myjavalib.stubs.system.jar -> sdk_library/system/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source.system/android_common/metalava/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib.txt
-.intermediates/myjavalib.stubs.source.system/android_common/metalava/myjavalib.stubs.source.system_removed.txt -> sdk_library/system/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable/android_common/combined/myjavalib.stubs.exportable.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable.system/android_common/combined/myjavalib.stubs.exportable.system.jar -> sdk_library/system/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source.system/android_common/exportable/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib.txt
+.intermediates/myjavalib.stubs.source.system/android_common/exportable/myjavalib.stubs.source.system_removed.txt -> sdk_library/system/myjavalib-removed.txt
`),
checkMergeZips(
".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
@@ -1448,15 +1466,15 @@
}
`),
checkAllCopyRules(`
-.intermediates/myjavalib.stubs/android_common/combined/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
-.intermediates/myjavalib.stubs.system/android_common/combined/myjavalib.stubs.system.jar -> sdk_library/system/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source.system/android_common/metalava/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib.txt
-.intermediates/myjavalib.stubs.source.system/android_common/metalava/myjavalib.stubs.source.system_removed.txt -> sdk_library/system/myjavalib-removed.txt
-.intermediates/myjavalib.stubs.module_lib/android_common/combined/myjavalib.stubs.module_lib.jar -> sdk_library/module-lib/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source.module_lib/android_common/metalava/myjavalib.stubs.source.module_lib_api.txt -> sdk_library/module-lib/myjavalib.txt
-.intermediates/myjavalib.stubs.source.module_lib/android_common/metalava/myjavalib.stubs.source.module_lib_removed.txt -> sdk_library/module-lib/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable/android_common/combined/myjavalib.stubs.exportable.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable.system/android_common/combined/myjavalib.stubs.exportable.system.jar -> sdk_library/system/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source.system/android_common/exportable/myjavalib.stubs.source.system_api.txt -> sdk_library/system/myjavalib.txt
+.intermediates/myjavalib.stubs.source.system/android_common/exportable/myjavalib.stubs.source.system_removed.txt -> sdk_library/system/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable.module_lib/android_common/combined/myjavalib.stubs.exportable.module_lib.jar -> sdk_library/module-lib/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source.module_lib/android_common/exportable/myjavalib.stubs.source.module_lib_api.txt -> sdk_library/module-lib/myjavalib.txt
+.intermediates/myjavalib.stubs.source.module_lib/android_common/exportable/myjavalib.stubs.source.module_lib_removed.txt -> sdk_library/module-lib/myjavalib-removed.txt
`),
checkMergeZips(
".intermediates/mysdk/common_os/tmp/sdk_library/module-lib/myjavalib_stub_sources.zip",
@@ -1514,12 +1532,12 @@
}
`),
checkAllCopyRules(`
-.intermediates/myjavalib.stubs/android_common/combined/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
-.intermediates/myjavalib.stubs.system_server/android_common/combined/myjavalib.stubs.system_server.jar -> sdk_library/system-server/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source.system_server/android_common/metalava/myjavalib.stubs.source.system_server_api.txt -> sdk_library/system-server/myjavalib.txt
-.intermediates/myjavalib.stubs.source.system_server/android_common/metalava/myjavalib.stubs.source.system_server_removed.txt -> sdk_library/system-server/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable/android_common/combined/myjavalib.stubs.exportable.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable.system_server/android_common/combined/myjavalib.stubs.exportable.system_server.jar -> sdk_library/system-server/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source.system_server/android_common/exportable/myjavalib.stubs.source.system_server_api.txt -> sdk_library/system-server/myjavalib.txt
+.intermediates/myjavalib.stubs.source.system_server/android_common/exportable/myjavalib.stubs.source.system_server_removed.txt -> sdk_library/system-server/myjavalib-removed.txt
`),
checkMergeZips(
".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
@@ -1568,9 +1586,9 @@
}
`),
checkAllCopyRules(`
-.intermediates/myjavalib.stubs/android_common/combined/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable/android_common/combined/myjavalib.stubs.exportable.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
`),
checkMergeZips(
".intermediates/mysdk/common_os/tmp/sdk_library/public/myjavalib_stub_sources.zip",
@@ -1625,9 +1643,9 @@
}
`),
checkAllCopyRules(`
-.intermediates/myjavalib.stubs/android_common/combined/myjavalib.stubs.jar -> sdk_library/public/myjavalib-stubs.jar
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
-.intermediates/myjavalib.stubs.source/android_common/metalava/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
+.intermediates/myjavalib.stubs.exportable/android_common/combined/myjavalib.stubs.exportable.jar -> sdk_library/public/myjavalib-stubs.jar
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_api.txt -> sdk_library/public/myjavalib.txt
+.intermediates/myjavalib.stubs.source/android_common/exportable/myjavalib.stubs.source_removed.txt -> sdk_library/public/myjavalib-removed.txt
docs/known_doctags -> doctags/docs/known_doctags
`),
)
diff --git a/sdk/sdk.go b/sdk/sdk.go
index 4d4a2a2..fd16ab6 100644
--- a/sdk/sdk.go
+++ b/sdk/sdk.go
@@ -222,6 +222,18 @@
}}
}
+func (s *sdk) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case "":
+ if s.snapshotFile.Valid() {
+ return []android.Path{s.snapshotFile.Path()}, nil
+ }
+ return nil, fmt.Errorf("snapshot file not defined. This is most likely because this isn't the common_os variant of this module")
+ default:
+ return nil, fmt.Errorf("unknown tag %q", tag)
+ }
+}
+
// gatherTraits gathers the traits from the dynamically generated trait specific properties.
//
// Returns a map from member name to the set of required traits.
diff --git a/sdk/sdk_test.go b/sdk/sdk_test.go
index 5a25146..c4df146 100644
--- a/sdk/sdk_test.go
+++ b/sdk/sdk_test.go
@@ -442,6 +442,11 @@
android.FixtureMergeEnv(map[string]string{
"SOONG_SDK_SNAPSHOT_TARGET_BUILD_RELEASE": "S",
}),
+ android.FixtureModifyProductVariables(func(variables android.FixtureProductVariables) {
+ variables.BuildFlags = map[string]string{
+ "RELEASE_HIDDEN_API_EXPORTABLE_STUBS": "true",
+ }
+ }),
).RunTest(t)
CheckSnapshot(t, result, "mysdk", "",
@@ -487,9 +492,9 @@
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/index.csv -> hiddenapi/index.csv
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/stub-flags.csv -> hiddenapi/stub-flags.csv
.intermediates/mybootclasspathfragment/android_common/modular-hiddenapi/all-flags.csv -> hiddenapi/all-flags.csv
-.intermediates/mysdklibrary.stubs/android_common/combined/mysdklibrary.stubs.jar -> sdk_library/public/mysdklibrary-stubs.jar
-.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
-.intermediates/mysdklibrary.stubs.source/android_common/metalava/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
+.intermediates/mysdklibrary.stubs.exportable/android_common/combined/mysdklibrary.stubs.exportable.jar -> sdk_library/public/mysdklibrary-stubs.jar
+.intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_api.txt -> sdk_library/public/mysdklibrary.txt
+.intermediates/mysdklibrary.stubs.source/android_common/exportable/mysdklibrary.stubs.source_removed.txt -> sdk_library/public/mysdklibrary-removed.txt
`),
)
})
diff --git a/sdk/update.go b/sdk/update.go
index 4c39fae..095e0c2 100644
--- a/sdk/update.go
+++ b/sdk/update.go
@@ -166,10 +166,7 @@
// Keep track of which multilib variants are used by the sdk.
s.multilibUsages = s.multilibUsages.addArchType(child.Target().Arch.ArchType)
- var exportedComponentsInfo android.ExportedComponentsInfo
- if ctx.OtherModuleHasProvider(child, android.ExportedComponentsInfoProvider) {
- exportedComponentsInfo = ctx.OtherModuleProvider(child, android.ExportedComponentsInfoProvider).(android.ExportedComponentsInfo)
- }
+ exportedComponentsInfo, _ := android.OtherModuleProvider(ctx, child, android.ExportedComponentsInfoProvider)
var container android.Module
if parent != ctx.Module() {
@@ -607,7 +604,7 @@
name: name,
}
- additionalSdkInfo := ctx.OtherModuleProvider(module, android.AdditionalSdkInfoProvider).(android.AdditionalSdkInfo)
+ additionalSdkInfo, _ := android.OtherModuleProvider(ctx, module, android.AdditionalSdkInfoProvider)
info.memberSpecific = additionalSdkInfo.Properties
name2Info[name] = info
@@ -1171,7 +1168,7 @@
// The licenses are the same for all variants.
mctx := s.ctx
- licenseInfo := mctx.OtherModuleProvider(variant, android.LicenseInfoProvider).(android.LicenseInfo)
+ licenseInfo, _ := android.OtherModuleProvider(mctx, variant, android.LicenseInfoProvider)
if len(licenseInfo.Licenses) > 0 {
m.AddPropertyWithTag("licenses", licenseInfo.Licenses, s.OptionalSdkMemberReferencePropertyTag())
}
@@ -1417,7 +1414,7 @@
variantsByApex := make(map[string]android.Module)
conflictDetected := false
for _, variant := range list {
- apexInfo := moduleCtx.OtherModuleProvider(variant, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.OtherModuleProvider(moduleCtx, variant, android.ApexInfoProvider)
apexVariationName := apexInfo.ApexVariationName
// If there are two variants for a specific APEX variation then there is conflict.
if _, ok := variantsByApex[apexVariationName]; ok {
diff --git a/sh/Android.bp b/sh/Android.bp
index 1deedc7..930fcf5 100644
--- a/sh/Android.bp
+++ b/sh/Android.bp
@@ -11,6 +11,7 @@
"soong-android",
"soong-cc",
"soong-java",
+ "soong-testing",
"soong-tradefed",
],
srcs: [
diff --git a/sh/sh_binary.go b/sh/sh_binary.go
index 00794cd..97adeed 100644
--- a/sh/sh_binary.go
+++ b/sh/sh_binary.go
@@ -17,14 +17,13 @@
import (
"fmt"
"path/filepath"
- "sort"
"strings"
+ "android/soong/testing"
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
"android/soong/android"
- "android/soong/bazel"
"android/soong/cc"
"android/soong/snapshot"
"android/soong/tradefed"
@@ -155,7 +154,6 @@
type ShBinary struct {
android.ModuleBase
- android.BazelModuleBase
properties shBinaryProperties
@@ -173,7 +171,7 @@
installDir android.InstallPath
- data android.Paths
+ data []android.DataPath
testConfig android.Path
dataModules map[string]android.Path
@@ -190,6 +188,15 @@
return s.outputFilePath
}
+func (s *ShBinary) OutputFiles(tag string) (android.Paths, error) {
+ switch tag {
+ case "":
+ return android.Paths{s.outputFilePath}, nil
+ default:
+ return nil, fmt.Errorf("unsupported module reference tag %q", tag)
+ }
+}
+
func (s *ShBinary) SubDir() string {
return proptools.String(s.properties.Sub_dir)
}
@@ -263,6 +270,7 @@
Output: s.outputFilePath,
Input: s.sourceFilePath,
})
+ android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: []string{s.sourceFilePath.String()}})
}
func (s *ShBinary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
@@ -350,10 +358,21 @@
return
}
s.dataModules[relPath] = path
+ s.data = append(s.data, android.DataPath{SrcPath: path})
}
func (s *ShTest) GenerateAndroidBuildActions(ctx android.ModuleContext) {
s.ShBinary.generateAndroidBuildActions(ctx)
+
+ expandedData := android.PathsForModuleSrc(ctx, s.testProperties.Data)
+ // Emulate the data property for java_data dependencies.
+ for _, javaData := range ctx.GetDirectDepsWithTag(shTestJavaDataTag) {
+ expandedData = append(expandedData, android.OutputFilesForModule(ctx, javaData, "")...)
+ }
+ for _, d := range expandedData {
+ s.data = append(s.data, android.DataPath{SrcPath: d})
+ }
+
testDir := "nativetest"
if ctx.Target().Arch.ArchType.Multilib == "lib64" {
testDir = "nativetest64"
@@ -370,15 +389,6 @@
} else {
s.installDir = android.PathForModuleInstall(ctx, testDir, s.Name())
}
- s.installedFile = ctx.InstallExecutable(s.installDir, s.outputFilePath.Base(), s.outputFilePath)
-
- expandedData := android.PathsForModuleSrc(ctx, s.testProperties.Data)
-
- // Emulate the data property for java_data dependencies.
- for _, javaData := range ctx.GetDirectDepsWithTag(shTestJavaDataTag) {
- expandedData = append(expandedData, android.OutputFilesForModule(ctx, javaData, "")...)
- }
- s.data = expandedData
var configs []tradefed.Config
if Bool(s.testProperties.Require_root) {
@@ -427,7 +437,7 @@
if _, exist := s.dataModules[relPath]; exist {
return
}
- relocatedLib := android.PathForModuleOut(ctx, "relocated", relPath)
+ relocatedLib := android.PathForModuleOut(ctx, "relocated").Join(ctx, relPath)
ctx.Build(pctx, android.BuildParams{
Rule: android.Cp,
Input: cc.OutputFile().Path(),
@@ -443,6 +453,11 @@
ctx.PropertyErrorf(property, "%q of type %q is not supported", dep.Name(), ctx.OtherModuleType(dep))
}
})
+
+ installedData := ctx.InstallTestData(s.installDir, s.data)
+ s.installedFile = ctx.InstallExecutable(s.installDir, s.outputFilePath.Base(), s.outputFilePath, installedData...)
+
+ android.SetProvider(ctx, testing.TestModuleProviderKey, testing.TestModuleProviderData{})
}
func (s *ShTest) InstallInData() bool {
@@ -462,24 +477,6 @@
if s.testConfig != nil {
entries.SetPath("LOCAL_FULL_TEST_CONFIG", s.testConfig)
}
- for _, d := range s.data {
- rel := d.Rel()
- path := d.String()
- if !strings.HasSuffix(path, rel) {
- panic(fmt.Errorf("path %q does not end with %q", path, rel))
- }
- path = strings.TrimSuffix(path, rel)
- entries.AddStrings("LOCAL_TEST_DATA", path+":"+rel)
- }
- relPaths := make([]string, 0)
- for relPath, _ := range s.dataModules {
- relPaths = append(relPaths, relPath)
- }
- sort.Strings(relPaths)
- for _, relPath := range relPaths {
- dir := strings.TrimSuffix(s.dataModules[relPath].String(), relPath)
- entries.AddStrings("LOCAL_TEST_DATA", dir+":"+relPath)
- }
if s.testProperties.Data_bins != nil {
entries.AddStrings("LOCAL_TEST_DATA_BINS", s.testProperties.Data_bins...)
}
@@ -491,18 +488,15 @@
}}
}
-func initShBinaryModule(s *ShBinary, useBazel bool) {
+func initShBinaryModule(s *ShBinary) {
s.AddProperties(&s.properties)
- if useBazel {
- android.InitBazelModule(s)
- }
}
// sh_binary is for a shell script or batch file to be installed as an
// executable binary to <partition>/bin.
func ShBinaryFactory() android.Module {
module := &ShBinary{}
- initShBinaryModule(module, true)
+ initShBinaryModule(module)
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibFirst)
return module
}
@@ -511,7 +505,7 @@
// to $(HOST_OUT)/bin.
func ShBinaryHostFactory() android.Module {
module := &ShBinary{}
- initShBinaryModule(module, true)
+ initShBinaryModule(module)
android.InitAndroidArchModule(module, android.HostSupported, android.MultilibFirst)
return module
}
@@ -519,7 +513,7 @@
// sh_test defines a shell script based test module.
func ShTestFactory() android.Module {
module := &ShTest{}
- initShBinaryModule(&module.ShBinary, true)
+ initShBinaryModule(&module.ShBinary)
module.AddProperties(&module.testProperties)
android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibFirst)
@@ -529,7 +523,7 @@
// sh_test_host defines a shell script based test module that runs on a host.
func ShTestHostFactory() android.Module {
module := &ShTest{}
- initShBinaryModule(&module.ShBinary, true)
+ initShBinaryModule(&module.ShBinary)
module.AddProperties(&module.testProperties)
// Default sh_test_host to unit_tests = true
if module.testProperties.Test_options.Unit_test == nil {
@@ -540,103 +534,6 @@
return module
}
-type bazelShBinaryAttributes struct {
- Srcs bazel.LabelListAttribute
- Filename *string
- Sub_dir *string
- // Bazel also supports the attributes below, but (so far) these are not required for Bionic
- // deps
- // data
- // args
- // compatible_with
- // deprecation
- // distribs
- // env
- // exec_compatible_with
- // exec_properties
- // features
- // licenses
- // output_licenses
- // restricted_to
- // tags
- // target_compatible_with
- // testonly
- // toolchains
- // visibility
-}
-
-type bazelShTestAttributes struct {
- Srcs bazel.LabelListAttribute
- Data bazel.LabelListAttribute
- Tags bazel.StringListAttribute
- Test_config *string
- Test_config_template *string
- Auto_gen_config *bool
-}
-
-func (m *ShBinary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- srcs := bazel.MakeLabelListAttribute(
- android.BazelLabelForModuleSrc(ctx, []string{*m.properties.Src}))
-
- var filename *string
- if m.properties.Filename != nil {
- filename = m.properties.Filename
- }
-
- var subDir *string
- if m.properties.Sub_dir != nil {
- subDir = m.properties.Sub_dir
- }
-
- attrs := &bazelShBinaryAttributes{
- Srcs: srcs,
- Filename: filename,
- Sub_dir: subDir,
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "sh_binary",
- Bzl_load_location: "//build/bazel/rules:sh_binary.bzl",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
-}
-
-func (m *ShTest) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- srcs := bazel.MakeLabelListAttribute(
- android.BazelLabelForModuleSrc(ctx, []string{*m.properties.Src}))
-
- combinedData := append(m.testProperties.Data, m.testProperties.Data_bins...)
- combinedData = append(combinedData, m.testProperties.Data_libs...)
-
- data := bazel.MakeLabelListAttribute(
- android.BazelLabelForModuleSrc(ctx, combinedData))
-
- tags := bazel.MakeStringListAttribute(
- m.testProperties.Test_options.Tags)
-
- test_config := m.testProperties.Test_config
-
- test_config_template := m.testProperties.Test_config_template
-
- auto_gen_config := m.testProperties.Auto_gen_config
-
- attrs := &bazelShTestAttributes{
- Srcs: srcs,
- Data: data,
- Tags: tags,
- Test_config: test_config,
- Test_config_template: test_config_template,
- Auto_gen_config: auto_gen_config,
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "sh_test",
- Bzl_load_location: "//build/bazel/rules:sh_test.bzl",
- }
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: m.Name()}, attrs)
-}
-
var Bool = proptools.Bool
var _ snapshot.RelativeInstallPath = (*ShBinary)(nil)
diff --git a/sh/sh_binary_test.go b/sh/sh_binary_test.go
index 5fcb58d..37450b0 100644
--- a/sh/sh_binary_test.go
+++ b/sh/sh_binary_test.go
@@ -135,7 +135,7 @@
if arch == "darwin_x86_64" {
libExt = ".dylib"
}
- relocated := variant.Output("relocated/lib64/libbar" + libExt)
+ relocated := variant.Output(filepath.Join("out/soong/.intermediates/foo", arch, "relocated/lib64/libbar"+libExt))
expectedInput := "out/soong/.intermediates/libbar/" + arch + "_shared/libbar" + libExt
android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input)
@@ -204,18 +204,19 @@
`)
buildOS := config.BuildOS.String()
- variant := ctx.ModuleForTests("foo", buildOS+"_x86_64")
+ variant := buildOS + "_x86_64"
+ foo := ctx.ModuleForTests("foo", variant)
- relocated := variant.Output("relocated/lib64/libbar.so")
+ relocated := foo.Output(filepath.Join("out/soong/.intermediates/foo", variant, "relocated/lib64/libbar.so"))
expectedInput := "out/soong/.intermediates/libbar/android_arm64_armv8-a_shared/libbar.so"
android.AssertPathRelativeToTopEquals(t, "relocation input", expectedInput, relocated.Input)
- mod := variant.Module().(*ShTest)
+ mod := foo.Module().(*ShTest)
entries := android.AndroidMkEntriesForTest(t, ctx, mod)[0]
expectedData := []string{
"out/soong/.intermediates/bar/android_arm64_armv8-a/:bar",
// libbar has been relocated, and so has a variant that matches the host arch.
- "out/soong/.intermediates/foo/" + buildOS + "_x86_64/relocated/:lib64/libbar.so",
+ "out/soong/.intermediates/foo/" + variant + "/relocated/:lib64/libbar.so",
}
actualData := entries.EntryMap["LOCAL_TEST_DATA"]
android.AssertStringPathsRelativeToTopEquals(t, "LOCAL_TEST_DATA", config, expectedData, actualData)
diff --git a/snapshot/host_fake_snapshot.go b/snapshot/host_fake_snapshot.go
index c4cfbb5..63cd4e1 100644
--- a/snapshot/host_fake_snapshot.go
+++ b/snapshot/host_fake_snapshot.go
@@ -119,7 +119,7 @@
if !module.Enabled() || module.IsHideFromMake() {
return
}
- apexInfo := ctx.ModuleProvider(module, android.ApexInfoProvider).(android.ApexInfo)
+ apexInfo, _ := android.SingletonModuleProvider(ctx, module, android.ApexInfoProvider)
if !apexInfo.IsForPlatform() {
return
}
diff --git a/snapshot/recovery_snapshot.go b/snapshot/recovery_snapshot.go
index 8ff59cb..ab114b4 100644
--- a/snapshot/recovery_snapshot.go
+++ b/snapshot/recovery_snapshot.go
@@ -22,16 +22,14 @@
ExcludeFromRecoverySnapshot() bool
}
-var recoverySnapshotSingleton = SnapshotSingleton{
- "recovery", // name
- "SOONG_RECOVERY_SNAPSHOT_ZIP", // makeVar
- android.OptionalPath{}, // snapshotZipFile
- RecoverySnapshotImageSingleton, // Image
- false, // Fake
-}
-
func RecoverySnapshotSingleton() android.Singleton {
- return &recoverySnapshotSingleton
+ return &SnapshotSingleton{
+ "recovery", // name
+ "SOONG_RECOVERY_SNAPSHOT_ZIP", // makeVar
+ android.OptionalPath{}, // snapshotZipFile
+ RecoverySnapshotImageSingleton, // Image
+ false, // Fake
+ }
}
// Determine if a dir under source tree is an SoC-owned proprietary directory based
diff --git a/snapshot/vendor_snapshot.go b/snapshot/vendor_snapshot.go
index 4484c85..3e5f546 100644
--- a/snapshot/vendor_snapshot.go
+++ b/snapshot/vendor_snapshot.go
@@ -22,28 +22,24 @@
ExcludeFromVendorSnapshot() bool
}
-var vendorSnapshotSingleton = SnapshotSingleton{
- "vendor", // name
- "SOONG_VENDOR_SNAPSHOT_ZIP", // makeVar
- android.OptionalPath{}, // snapshotZipFile
- VendorSnapshotImageSingleton, // Image
- false, // Fake
-}
-
-var vendorFakeSnapshotSingleton = SnapshotSingleton{
- "vendor", // name
- "SOONG_VENDOR_FAKE_SNAPSHOT_ZIP", // makeVar
- android.OptionalPath{}, // snapshotZipFile
- VendorSnapshotImageSingleton, // Image
- true, // Fake
-}
-
func VendorSnapshotSingleton() android.Singleton {
- return &vendorSnapshotSingleton
+ return &SnapshotSingleton{
+ "vendor", // name
+ "SOONG_VENDOR_SNAPSHOT_ZIP", // makeVar
+ android.OptionalPath{}, // snapshotZipFile
+ VendorSnapshotImageSingleton, // Image
+ false, // Fake
+ }
}
func VendorFakeSnapshotSingleton() android.Singleton {
- return &vendorFakeSnapshotSingleton
+ return &SnapshotSingleton{
+ "vendor", // name
+ "SOONG_VENDOR_FAKE_SNAPSHOT_ZIP", // makeVar
+ android.OptionalPath{}, // snapshotZipFile
+ VendorSnapshotImageSingleton, // Image
+ true, // Fake
+ }
}
// Determine if a dir under source tree is an SoC-owned proprietary directory based
diff --git a/sysprop/Android.bp b/sysprop/Android.bp
index e5263fe..1d5eb31 100644
--- a/sysprop/Android.bp
+++ b/sysprop/Android.bp
@@ -9,7 +9,6 @@
"blueprint",
"soong",
"soong-android",
- "soong-bp2build",
"soong-cc",
"soong-java",
],
@@ -19,7 +18,6 @@
],
testSrcs: [
"sysprop_test.go",
- "sysprop_library_conversion_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/sysprop/sysprop_library.go b/sysprop/sysprop_library.go
index a2c0fb7..766f3e7 100644
--- a/sysprop/sysprop_library.go
+++ b/sysprop/sysprop_library.go
@@ -23,8 +23,6 @@
"path"
"sync"
- "android/soong/bazel"
-
"github.com/google/blueprint"
"github.com/google/blueprint/proptools"
@@ -127,7 +125,6 @@
type syspropLibrary struct {
android.ModuleBase
android.ApexModuleBase
- android.BazelModuleBase
properties syspropLibraryProperties
@@ -170,6 +167,12 @@
// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
// Forwarded to cc_library.min_sdk_version
Min_sdk_version *string
+
+ // C compiler flags used to build library
+ Cflags []string
+
+ // Linker flags used to build binary
+ Ldflags []string
}
Java struct {
@@ -242,12 +245,13 @@
// generated java_library will depend on these API files.
func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
baseModuleName := m.BaseModuleName()
-
- for _, syspropFile := range android.PathsForModuleSrc(ctx, m.properties.Srcs) {
+ srcs := android.PathsForModuleSrc(ctx, m.properties.Srcs)
+ for _, syspropFile := range srcs {
if syspropFile.Ext() != ".sysprop" {
ctx.PropertyErrorf("srcs", "srcs contains non-sysprop file %q", syspropFile.String())
}
}
+ android.SetProvider(ctx, blueprint.SrcsFileProviderKey, blueprint.SrcsFileProviderData{SrcPaths: srcs.Strings()})
if ctx.Failed() {
return
@@ -265,7 +269,7 @@
rule.Command().
BuiltTool("sysprop_api_dump").
Output(m.dumpedApiFile).
- Inputs(android.PathsForModuleSrc(ctx, m.properties.Srcs))
+ Inputs(srcs)
rule.Build(baseModuleName+"_api_dump", baseModuleName+" api dump")
// check API rule
@@ -339,9 +343,12 @@
// Actual implementation libraries are created on LoadHookMutator
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)", " # sysprop.syspropLibrary")
fmt.Fprintln(w, "LOCAL_MODULE :=", m.Name())
- data.Entries.WriteLicenseVariables(w)
fmt.Fprintf(w, "LOCAL_MODULE_CLASS := FAKE\n")
fmt.Fprintf(w, "LOCAL_MODULE_TAGS := optional\n")
+ // AconfigUpdateAndroidMkData may have added elements to Extra. Process them here.
+ for _, extra := range data.Extra {
+ extra(w, nil)
+ }
fmt.Fprintf(w, "include $(BUILD_SYSTEM)/base_rules.mk\n\n")
fmt.Fprintf(w, "$(LOCAL_BUILT_MODULE): %s\n", m.checkApiFileTimeStamp.String())
fmt.Fprintf(w, "\ttouch $@\n\n")
@@ -378,7 +385,6 @@
)
android.InitAndroidModule(m)
android.InitApexModule(m)
- android.InitBazelModule(m)
android.AddLoadHook(m, func(ctx android.LoadHookContext) { syspropLibraryHook(ctx, m) })
return m
}
@@ -410,9 +416,8 @@
Host_supported *bool
Apex_available []string
Min_sdk_version *string
- Bazel_module struct {
- Label *string
- }
+ Cflags []string
+ Ldflags []string
}
type javaLibraryProperties struct {
@@ -429,9 +434,6 @@
SyspropPublicStub string
Apex_available []string
Min_sdk_version *string
- Bazel_module struct {
- Bp2build_available *bool
- }
}
func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
@@ -477,14 +479,6 @@
"Unknown value %s: must be one of Platform, Vendor or Odm", m.Owner())
}
- var label *string
- if b, ok := ctx.Module().(android.Bazelable); ok && b.ShouldConvertWithBp2build(ctx) {
- // TODO: b/295566168 - this will need to change once build files are checked in to account for
- // checked in modules in mixed builds
- label = proptools.StringPtr(
- fmt.Sprintf("//%s:%s", ctx.ModuleDir(), m.CcImplementationModuleName()))
- }
-
// Generate a C++ implementation library.
// cc_library can receive *.sysprop files as their srcs, generating sources itself.
ccProps := ccLibraryProperties{}
@@ -504,7 +498,8 @@
ccProps.Host_supported = m.properties.Host_supported
ccProps.Apex_available = m.ApexProperties.Apex_available
ccProps.Min_sdk_version = m.properties.Cpp.Min_sdk_version
- ccProps.Bazel_module.Label = label
+ ccProps.Cflags = m.properties.Cpp.Cflags
+ ccProps.Ldflags = m.properties.Cpp.Ldflags
ctx.CreateModule(cc.LibraryFactory, &ccProps)
scope := "internal"
@@ -549,11 +544,6 @@
SyspropPublicStub: publicStub,
Apex_available: m.ApexProperties.Apex_available,
Min_sdk_version: m.properties.Java.Min_sdk_version,
- Bazel_module: struct {
- Bp2build_available *bool
- }{
- Bp2build_available: proptools.BoolPtr(false),
- },
})
if publicStub != "" {
@@ -571,11 +561,6 @@
Sdk_version: proptools.StringPtr("core_current"),
Libs: []string{javaSyspropStub},
Stem: proptools.StringPtr(m.BaseModuleName()),
- Bazel_module: struct {
- Bp2build_available *bool
- }{
- Bp2build_available: proptools.BoolPtr(false),
- },
})
}
@@ -589,16 +574,3 @@
*libraries = append(*libraries, "//"+ctx.ModuleDir()+":"+ctx.ModuleName())
}
}
-
-// TODO(b/240463568): Additional properties will be added for API validation
-func (m *syspropLibrary) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- labels := cc.SyspropLibraryLabels{
- SyspropLibraryLabel: m.BaseModuleName(),
- SharedLibraryLabel: m.CcImplementationModuleName(),
- StaticLibraryLabel: cc.BazelLabelNameForStaticModule(m.CcImplementationModuleName()),
- }
- cc.Bp2buildSysprop(ctx,
- labels,
- bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrc(ctx, m.properties.Srcs)),
- m.properties.Cpp.Min_sdk_version)
-}
diff --git a/sysprop/sysprop_library_conversion_test.go b/sysprop/sysprop_library_conversion_test.go
deleted file mode 100644
index 89adf7d..0000000
--- a/sysprop/sysprop_library_conversion_test.go
+++ /dev/null
@@ -1,110 +0,0 @@
-// 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 sysprop
-
-import (
- "testing"
-
- "android/soong/bp2build"
-)
-
-func TestSyspropLibrarySimple(t *testing.T) {
- bp2build.RunBp2BuildTestCaseSimple(t, bp2build.Bp2buildTestCase{
- Description: "sysprop_library simple",
- ModuleTypeUnderTest: "sysprop_library",
- ModuleTypeUnderTestFactory: syspropLibraryFactory,
- Filesystem: map[string]string{
- "foo.sysprop": "",
- "bar.sysprop": "",
- },
- Blueprint: `
-sysprop_library {
- name: "sysprop_foo",
- srcs: [
- "foo.sysprop",
- "bar.sysprop",
- ],
- property_owner: "Platform",
-}
-`,
- ExpectedBazelTargets: []string{
- bp2build.MakeBazelTargetNoRestrictions("sysprop_library",
- "sysprop_foo",
- bp2build.AttrNameToString{
- "srcs": `[
- "foo.sysprop",
- "bar.sysprop",
- ]`,
- }),
- bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_shared",
- "libsysprop_foo",
- bp2build.AttrNameToString{
- "dep": `":sysprop_foo"`,
- }),
- bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_static",
- "libsysprop_foo_bp2build_cc_library_static",
- bp2build.AttrNameToString{
- "dep": `":sysprop_foo"`,
- }),
- },
- })
-}
-
-func TestSyspropLibraryCppMinSdkVersion(t *testing.T) {
- bp2build.RunBp2BuildTestCaseSimple(t, bp2build.Bp2buildTestCase{
- Description: "sysprop_library with min_sdk_version",
- ModuleTypeUnderTest: "sysprop_library",
- ModuleTypeUnderTestFactory: syspropLibraryFactory,
- Filesystem: map[string]string{
- "foo.sysprop": "",
- "bar.sysprop": "",
- },
- Blueprint: `
-sysprop_library {
- name: "sysprop_foo",
- srcs: [
- "foo.sysprop",
- "bar.sysprop",
- ],
- cpp: {
- min_sdk_version: "5",
- },
- property_owner: "Platform",
-}
-`,
- ExpectedBazelTargets: []string{
- bp2build.MakeBazelTargetNoRestrictions("sysprop_library",
- "sysprop_foo",
- bp2build.AttrNameToString{
- "srcs": `[
- "foo.sysprop",
- "bar.sysprop",
- ]`,
- }),
- bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_shared",
- "libsysprop_foo",
- bp2build.AttrNameToString{
- "dep": `":sysprop_foo"`,
- "min_sdk_version": `"5"`,
- }),
- bp2build.MakeBazelTargetNoRestrictions("cc_sysprop_library_static",
- "libsysprop_foo_bp2build_cc_library_static",
- bp2build.AttrNameToString{
- "dep": `":sysprop_foo"`,
- "min_sdk_version": `"5"`,
- }),
- },
- })
-}
diff --git a/sysprop/sysprop_test.go b/sysprop/sysprop_test.go
index 80b86e0..e5b3dea 100644
--- a/sysprop/sysprop_test.go
+++ b/sysprop/sysprop_test.go
@@ -42,6 +42,7 @@
cc_library_headers {
name: "libbase_headers",
vendor_available: true,
+ product_available: true,
recovery_available: true,
}
@@ -124,6 +125,12 @@
variables.DeviceSystemSdkVersions = []string{"28"}
variables.DeviceVndkVersion = proptools.StringPtr("current")
variables.Platform_vndk_version = proptools.StringPtr("29")
+ variables.DeviceCurrentApiLevelForVendorModules = proptools.StringPtr("28")
+ }),
+ java.FixtureWithPrebuiltApis(map[string][]string{
+ "28": {},
+ "29": {},
+ "30": {},
}),
mockFS.AddToFixture(),
android.FixtureWithRootAndroidBp(bp),
@@ -250,6 +257,16 @@
result.ModuleForTests("libsysprop-odm", variant)
}
+ // product variant of vendor-owned sysprop_library
+ for _, variant := range []string{
+ "android_product.29_arm_armv7-a-neon_shared",
+ "android_product.29_arm_armv7-a-neon_static",
+ "android_product.29_arm64_armv8-a_shared",
+ "android_product.29_arm64_armv8-a_static",
+ } {
+ result.ModuleForTests("libsysprop-vendor-on-product", variant)
+ }
+
for _, variant := range []string{
"android_arm_armv7-a-neon_shared",
"android_arm_armv7-a-neon_static",
@@ -259,9 +276,6 @@
library := result.ModuleForTests("libsysprop-platform", variant).Module().(*cc.Module)
expectedApexAvailableOnLibrary := []string{"//apex_available:platform"}
android.AssertDeepEquals(t, "apex available property on libsysprop-platform", expectedApexAvailableOnLibrary, library.ApexProperties.Apex_available)
-
- // product variant of vendor-owned sysprop_library
- result.ModuleForTests("libsysprop-vendor-on-product", variant)
}
result.ModuleForTests("sysprop-platform", "android_common")
@@ -272,15 +286,15 @@
// Check for exported includes
coreVariant := "android_arm64_armv8-a_static"
vendorVariant := "android_vendor.29_arm64_armv8-a_static"
+ productVariant := "android_product.29_arm64_armv8-a_static"
platformInternalPath := "libsysprop-platform/android_arm64_armv8-a_static/gen/sysprop/include"
- platformPublicCorePath := "libsysprop-platform/android_arm64_armv8-a_static/gen/sysprop/public/include"
platformPublicVendorPath := "libsysprop-platform/android_vendor.29_arm64_armv8-a_static/gen/sysprop/public/include"
- platformOnProductPath := "libsysprop-platform-on-product/android_arm64_armv8-a_static/gen/sysprop/public/include"
+ platformOnProductPath := "libsysprop-platform-on-product/android_product.29_arm64_armv8-a_static/gen/sysprop/public/include"
vendorInternalPath := "libsysprop-vendor/android_vendor.29_arm64_armv8-a_static/gen/sysprop/include"
- vendorPublicPath := "libsysprop-vendor-on-product/android_arm64_armv8-a_static/gen/sysprop/public/include"
+ vendorOnProductPath := "libsysprop-vendor-on-product/android_product.29_arm64_armv8-a_static/gen/sysprop/public/include"
platformClient := result.ModuleForTests("cc-client-platform", coreVariant)
platformFlags := platformClient.Rule("cc").Args["cFlags"]
@@ -294,14 +308,14 @@
// platform-static should use platform's internal header
android.AssertStringDoesContain(t, "flags for platform-static", platformStaticFlags, platformInternalPath)
- productClient := result.ModuleForTests("cc-client-product", coreVariant)
+ productClient := result.ModuleForTests("cc-client-product", productVariant)
productFlags := productClient.Rule("cc").Args["cFlags"]
// Product should use platform's and vendor's public headers
if !strings.Contains(productFlags, platformOnProductPath) ||
- !strings.Contains(productFlags, vendorPublicPath) {
+ !strings.Contains(productFlags, vendorOnProductPath) {
t.Errorf("flags for product must contain %#v and %#v, but was %#v.",
- platformPublicCorePath, vendorPublicPath, productFlags)
+ platformOnProductPath, vendorOnProductPath, productFlags)
}
vendorClient := result.ModuleForTests("cc-client-vendor", vendorVariant)
diff --git a/testing/Android.bp b/testing/Android.bp
new file mode 100644
index 0000000..43040b0
--- /dev/null
+++ b/testing/Android.bp
@@ -0,0 +1,24 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-testing",
+ pkgPath: "android/soong/testing",
+ deps: [
+ "blueprint",
+ "soong-android",
+ "soong-testing-code_metadata_internal_proto",
+ "soong-testing-test_spec_proto",
+
+ ],
+ srcs: [
+ "all_code_metadata.go",
+ "all_test_specs.go",
+ "code_metadata.go",
+ "test_spec.go",
+ "init.go",
+ "test.go",
+ ],
+ pluginFor: ["soong_build"],
+}
diff --git a/testing/OWNERS b/testing/OWNERS
new file mode 100644
index 0000000..03bcdf1
--- /dev/null
+++ b/testing/OWNERS
@@ -0,0 +1,4 @@
+dariofreni@google.com
+joeo@google.com
+ronish@google.com
+caditya@google.com
diff --git a/testing/all_code_metadata.go b/testing/all_code_metadata.go
new file mode 100644
index 0000000..12aa7b5
--- /dev/null
+++ b/testing/all_code_metadata.go
@@ -0,0 +1,46 @@
+package testing
+
+import (
+ "android/soong/android"
+)
+
+const fileContainingCodeMetadataFilePaths = "all_code_metadata_paths.rsp"
+const allCodeMetadataFile = "all_code_metadata.pb"
+
+func AllCodeMetadataFactory() android.Singleton {
+ return &allCodeMetadataSingleton{}
+}
+
+type allCodeMetadataSingleton struct {
+ // Path where the collected metadata is stored after successful validation.
+ outputPath android.OutputPath
+}
+
+func (this *allCodeMetadataSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ var intermediateMetadataPaths android.Paths
+
+ ctx.VisitAllModules(
+ func(module android.Module) {
+ if metadata, ok := android.SingletonModuleProvider(ctx, module, CodeMetadataProviderKey); ok {
+ intermediateMetadataPaths = append(intermediateMetadataPaths, metadata.IntermediatePath)
+ }
+ },
+ )
+
+ rspFile := android.PathForOutput(ctx, fileContainingCodeMetadataFilePaths)
+ this.outputPath = android.PathForOutput(ctx, ownershipDirectory, allCodeMetadataFile)
+
+ rule := android.NewRuleBuilder(pctx, ctx)
+ cmd := rule.Command().
+ BuiltTool("metadata").
+ FlagWithArg("-rule ", "code_metadata").
+ FlagWithRspFileInputList("-inputFile ", rspFile, intermediateMetadataPaths)
+ cmd.FlagWithOutput("-outputFile ", this.outputPath)
+ rule.Build("all_code_metadata_rule", "Generate all code metadata")
+
+ ctx.Phony("all_code_metadata", this.outputPath)
+}
+
+func (this *allCodeMetadataSingleton) MakeVars(ctx android.MakeVarsContext) {
+ ctx.DistForGoal("code_metadata", this.outputPath)
+}
diff --git a/testing/all_test_specs.go b/testing/all_test_specs.go
new file mode 100644
index 0000000..b035435
--- /dev/null
+++ b/testing/all_test_specs.go
@@ -0,0 +1,44 @@
+package testing
+
+import (
+ "android/soong/android"
+)
+
+const ownershipDirectory = "ownership"
+const fileContainingFilePaths = "all_test_spec_paths.rsp"
+const allTestSpecsFile = "all_test_specs.pb"
+
+func AllTestSpecsFactory() android.Singleton {
+ return &allTestSpecsSingleton{}
+}
+
+type allTestSpecsSingleton struct {
+ // Path where the collected metadata is stored after successful validation.
+ outputPath android.OutputPath
+}
+
+func (this *allTestSpecsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
+ var intermediateMetadataPaths android.Paths
+
+ ctx.VisitAllModules(func(module android.Module) {
+ if metadata, ok := android.SingletonModuleProvider(ctx, module, TestSpecProviderKey); ok {
+ intermediateMetadataPaths = append(intermediateMetadataPaths, metadata.IntermediatePath)
+ }
+ })
+
+ rspFile := android.PathForOutput(ctx, fileContainingFilePaths)
+ this.outputPath = android.PathForOutput(ctx, ownershipDirectory, allTestSpecsFile)
+
+ rule := android.NewRuleBuilder(pctx, ctx)
+ cmd := rule.Command().
+ BuiltTool("metadata").
+ FlagWithArg("-rule ", "test_spec").
+ FlagWithRspFileInputList("-inputFile ", rspFile, intermediateMetadataPaths)
+ cmd.FlagWithOutput("-outputFile ", this.outputPath)
+ rule.Build("all_test_specs_rule", "Generate all test specifications")
+ ctx.Phony("all_test_specs", this.outputPath)
+}
+
+func (this *allTestSpecsSingleton) MakeVars(ctx android.MakeVarsContext) {
+ ctx.DistForGoal("test_specs", this.outputPath)
+}
diff --git a/testing/code_metadata.go b/testing/code_metadata.go
new file mode 100644
index 0000000..11ba430
--- /dev/null
+++ b/testing/code_metadata.go
@@ -0,0 +1,137 @@
+// Copyright 2020 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 testing
+
+import (
+ "path/filepath"
+
+ "android/soong/android"
+ "android/soong/testing/code_metadata_internal_proto"
+ "github.com/google/blueprint"
+
+ "google.golang.org/protobuf/proto"
+)
+
+func CodeMetadataFactory() android.Module {
+ module := &CodeMetadataModule{}
+
+ android.InitAndroidModule(module)
+ android.InitDefaultableModule(module)
+ module.AddProperties(&module.properties)
+
+ return module
+}
+
+type CodeMetadataModule struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+
+ // Properties for "code_metadata"
+ properties struct {
+ // Specifies the name of the code_config.
+ Name string
+ // Specifies the team ID.
+ TeamId string
+ // Specifies the list of modules that this code_metadata covers.
+ Code []string
+ // An optional field to specify if multiple ownerships for source files is allowed.
+ MultiOwnership bool
+ }
+}
+
+type codeDepTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+var codeDepTag = codeDepTagType{}
+
+func (module *CodeMetadataModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // Validate Properties
+ if len(module.properties.TeamId) == 0 {
+ ctx.PropertyErrorf(
+ "TeamId",
+ "Team Id not found in the code_metadata module. Hint: Maybe the teamId property hasn't been properly specified.",
+ )
+ }
+ if !isInt(module.properties.TeamId) {
+ ctx.PropertyErrorf(
+ "TeamId", "Invalid value for Team ID. The Team ID must be an integer.",
+ )
+ }
+ if len(module.properties.Code) == 0 {
+ ctx.PropertyErrorf(
+ "Code",
+ "Targets to be attributed cannot be empty. Hint: Maybe the code property hasn't been properly specified.",
+ )
+ }
+ ctx.AddDependency(ctx.Module(), codeDepTag, module.properties.Code...)
+}
+
+// Provider published by CodeMetadata
+type CodeMetadataProviderData struct {
+ IntermediatePath android.WritablePath
+}
+
+var CodeMetadataProviderKey = blueprint.NewProvider[CodeMetadataProviderData]()
+
+func (module *CodeMetadataModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ metadataList := make(
+ []*code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership, 0,
+ len(module.properties.Code),
+ )
+ bpFilePath := filepath.Join(ctx.ModuleDir(), ctx.BlueprintsFile())
+
+ for _, m := range ctx.GetDirectDepsWithTag(codeDepTag) {
+ targetName := m.Name()
+ var moduleSrcs []string
+ if srcsFileInfo, ok := android.OtherModuleProvider(ctx, m, blueprint.SrcsFileProviderKey); ok {
+ moduleSrcs = srcsFileInfo.SrcPaths
+ }
+ if module.properties.MultiOwnership {
+ metadata := &code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{
+ TargetName: &targetName,
+ TrendyTeamId: &module.properties.TeamId,
+ Path: &bpFilePath,
+ MultiOwnership: &module.properties.MultiOwnership,
+ SourceFiles: moduleSrcs,
+ }
+ metadataList = append(metadataList, metadata)
+ } else {
+ metadata := &code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{
+ TargetName: &targetName,
+ TrendyTeamId: &module.properties.TeamId,
+ Path: &bpFilePath,
+ SourceFiles: moduleSrcs,
+ }
+ metadataList = append(metadataList, metadata)
+ }
+
+ }
+ codeMetadata := &code_metadata_internal_proto.CodeMetadataInternal{TargetOwnershipList: metadataList}
+ protoData, err := proto.Marshal(codeMetadata)
+ if err != nil {
+ ctx.ModuleErrorf("Error marshaling code metadata: %s", err.Error())
+ return
+ }
+ intermediatePath := android.PathForModuleOut(
+ ctx, "intermediateCodeMetadata.pb",
+ )
+ android.WriteFileRuleVerbatim(ctx, intermediatePath, string(protoData))
+
+ android.SetProvider(ctx,
+ CodeMetadataProviderKey,
+ CodeMetadataProviderData{IntermediatePath: intermediatePath},
+ )
+}
diff --git a/testing/code_metadata_internal_proto/Android.bp b/testing/code_metadata_internal_proto/Android.bp
new file mode 100644
index 0000000..a534cc2
--- /dev/null
+++ b/testing/code_metadata_internal_proto/Android.bp
@@ -0,0 +1,29 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-testing-code_metadata_internal_proto",
+ pkgPath: "android/soong/testing/code_metadata_internal_proto",
+ deps: [
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ ],
+ srcs: [
+ "code_metadata_internal.pb.go",
+ ],
+}
diff --git a/testing/code_metadata_internal_proto/OWNERS b/testing/code_metadata_internal_proto/OWNERS
new file mode 100644
index 0000000..03bcdf1
--- /dev/null
+++ b/testing/code_metadata_internal_proto/OWNERS
@@ -0,0 +1,4 @@
+dariofreni@google.com
+joeo@google.com
+ronish@google.com
+caditya@google.com
diff --git a/testing/code_metadata_internal_proto/code_metadata_internal.pb.go b/testing/code_metadata_internal_proto/code_metadata_internal.pb.go
new file mode 100644
index 0000000..ecb8b86
--- /dev/null
+++ b/testing/code_metadata_internal_proto/code_metadata_internal.pb.go
@@ -0,0 +1,277 @@
+// 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc v3.21.12
+// source: code_metadata_internal.proto
+
+package code_metadata_internal_proto
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type CodeMetadataInternal struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // List of all code targets and their metadata.
+ TargetOwnershipList []*CodeMetadataInternal_TargetOwnership `protobuf:"bytes,1,rep,name=target_ownership_list,json=targetOwnershipList" json:"target_ownership_list,omitempty"`
+}
+
+func (x *CodeMetadataInternal) Reset() {
+ *x = CodeMetadataInternal{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_code_metadata_internal_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CodeMetadataInternal) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CodeMetadataInternal) ProtoMessage() {}
+
+func (x *CodeMetadataInternal) ProtoReflect() protoreflect.Message {
+ mi := &file_code_metadata_internal_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CodeMetadataInternal.ProtoReflect.Descriptor instead.
+func (*CodeMetadataInternal) Descriptor() ([]byte, []int) {
+ return file_code_metadata_internal_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *CodeMetadataInternal) GetTargetOwnershipList() []*CodeMetadataInternal_TargetOwnership {
+ if x != nil {
+ return x.TargetOwnershipList
+ }
+ return nil
+}
+
+type CodeMetadataInternal_TargetOwnership struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // REQUIRED: Name of the build target
+ TargetName *string `protobuf:"bytes,1,opt,name=target_name,json=targetName" json:"target_name,omitempty"`
+ // REQUIRED: Code location of the target.
+ // To be used to support legacy/backup systems that use OWNERS file and is
+ // also required for our dashboard to support per code location basis UI
+ Path *string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"`
+ // REQUIRED: Team ID of the team that owns this target.
+ TrendyTeamId *string `protobuf:"bytes,3,opt,name=trendy_team_id,json=trendyTeamId" json:"trendy_team_id,omitempty"`
+ // OPTIONAL: The src files of the target.
+ // To be used to determine ownership of a file for ownership
+ SourceFiles []string `protobuf:"bytes,4,rep,name=source_files,json=sourceFiles" json:"source_files,omitempty"`
+ // OPTIONAL: Specify if multiple ownerships of the source files are allowed.
+ MultiOwnership *bool `protobuf:"varint,5,opt,name=multi_ownership,json=multiOwnership" json:"multi_ownership,omitempty"`
+}
+
+func (x *CodeMetadataInternal_TargetOwnership) Reset() {
+ *x = CodeMetadataInternal_TargetOwnership{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_code_metadata_internal_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CodeMetadataInternal_TargetOwnership) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CodeMetadataInternal_TargetOwnership) ProtoMessage() {}
+
+func (x *CodeMetadataInternal_TargetOwnership) ProtoReflect() protoreflect.Message {
+ mi := &file_code_metadata_internal_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CodeMetadataInternal_TargetOwnership.ProtoReflect.Descriptor instead.
+func (*CodeMetadataInternal_TargetOwnership) Descriptor() ([]byte, []int) {
+ return file_code_metadata_internal_proto_rawDescGZIP(), []int{0, 0}
+}
+
+func (x *CodeMetadataInternal_TargetOwnership) GetTargetName() string {
+ if x != nil && x.TargetName != nil {
+ return *x.TargetName
+ }
+ return ""
+}
+
+func (x *CodeMetadataInternal_TargetOwnership) GetPath() string {
+ if x != nil && x.Path != nil {
+ return *x.Path
+ }
+ return ""
+}
+
+func (x *CodeMetadataInternal_TargetOwnership) GetTrendyTeamId() string {
+ if x != nil && x.TrendyTeamId != nil {
+ return *x.TrendyTeamId
+ }
+ return ""
+}
+
+func (x *CodeMetadataInternal_TargetOwnership) GetSourceFiles() []string {
+ if x != nil {
+ return x.SourceFiles
+ }
+ return nil
+}
+
+func (x *CodeMetadataInternal_TargetOwnership) GetMultiOwnership() bool {
+ if x != nil && x.MultiOwnership != nil {
+ return *x.MultiOwnership
+ }
+ return false
+}
+
+var File_code_metadata_internal_proto protoreflect.FileDescriptor
+
+var file_code_metadata_internal_proto_rawDesc = []byte{
+ 0x0a, 0x1c, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1c,
+ 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x69, 0x6e,
+ 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xc9, 0x02, 0x0a,
+ 0x14, 0x43, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x49, 0x6e, 0x74,
+ 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x12, 0x76, 0x0a, 0x15, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f,
+ 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01,
+ 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x72,
+ 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f,
+ 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x13, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
+ 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0xb8, 0x01,
+ 0x0a, 0x0f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69,
+ 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x61,
+ 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79,
+ 0x5f, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
+ 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x54, 0x65, 0x61, 0x6d, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c,
+ 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03,
+ 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12,
+ 0x27, 0x0a, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68,
+ 0x69, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x4f,
+ 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x42, 0x34, 0x5a, 0x32, 0x61, 0x6e, 0x64, 0x72,
+ 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e,
+ 0x67, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f,
+ 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+}
+
+var (
+ file_code_metadata_internal_proto_rawDescOnce sync.Once
+ file_code_metadata_internal_proto_rawDescData = file_code_metadata_internal_proto_rawDesc
+)
+
+func file_code_metadata_internal_proto_rawDescGZIP() []byte {
+ file_code_metadata_internal_proto_rawDescOnce.Do(func() {
+ file_code_metadata_internal_proto_rawDescData = protoimpl.X.CompressGZIP(file_code_metadata_internal_proto_rawDescData)
+ })
+ return file_code_metadata_internal_proto_rawDescData
+}
+
+var file_code_metadata_internal_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_code_metadata_internal_proto_goTypes = []interface{}{
+ (*CodeMetadataInternal)(nil), // 0: code_metadata_internal_proto.CodeMetadataInternal
+ (*CodeMetadataInternal_TargetOwnership)(nil), // 1: code_metadata_internal_proto.CodeMetadataInternal.TargetOwnership
+}
+var file_code_metadata_internal_proto_depIdxs = []int32{
+ 1, // 0: code_metadata_internal_proto.CodeMetadataInternal.target_ownership_list:type_name -> code_metadata_internal_proto.CodeMetadataInternal.TargetOwnership
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_code_metadata_internal_proto_init() }
+func file_code_metadata_internal_proto_init() {
+ if File_code_metadata_internal_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_code_metadata_internal_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CodeMetadataInternal); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_code_metadata_internal_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CodeMetadataInternal_TargetOwnership); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_code_metadata_internal_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_code_metadata_internal_proto_goTypes,
+ DependencyIndexes: file_code_metadata_internal_proto_depIdxs,
+ MessageInfos: file_code_metadata_internal_proto_msgTypes,
+ }.Build()
+ File_code_metadata_internal_proto = out.File
+ file_code_metadata_internal_proto_rawDesc = nil
+ file_code_metadata_internal_proto_goTypes = nil
+ file_code_metadata_internal_proto_depIdxs = nil
+}
diff --git a/testing/code_metadata_internal_proto/code_metadata_internal.proto b/testing/code_metadata_internal_proto/code_metadata_internal.proto
new file mode 100644
index 0000000..14edc0f
--- /dev/null
+++ b/testing/code_metadata_internal_proto/code_metadata_internal.proto
@@ -0,0 +1,40 @@
+// 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.
+
+syntax = "proto2";
+package code_metadata_internal_proto;
+option go_package = "android/soong/testing/code_metadata_internal_proto";
+
+message CodeMetadataInternal {
+
+ message TargetOwnership {
+ // REQUIRED: Name of the build target
+ optional string target_name = 1;
+
+ // REQUIRED: Code location of the target.
+ // To be used to support legacy/backup systems that use OWNERS file and is
+ // also required for our dashboard to support per code location basis UI
+ optional string path = 2;
+
+ // REQUIRED: Team ID of the team that owns this target.
+ optional string trendy_team_id = 3;
+
+ // OPTIONAL: The src files of the target.
+ // To be used to determine ownership of a file for ownership
+ repeated string source_files = 4;
+
+ // OPTIONAL: Specify if multiple ownerships of the source files are allowed.
+ optional bool multi_ownership = 5;
+ }
+
+ // List of all code targets and their metadata.
+ repeated TargetOwnership target_ownership_list = 1;
+}
diff --git a/testing/code_metadata_internal_proto/regen.sh b/testing/code_metadata_internal_proto/regen.sh
new file mode 100644
index 0000000..f101a02
--- /dev/null
+++ b/testing/code_metadata_internal_proto/regen.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+aprotoc --go_out=paths=source_relative:. code_metadata_internal.proto
diff --git a/testing/code_metadata_proto/Android.bp b/testing/code_metadata_proto/Android.bp
new file mode 100644
index 0000000..f07efff
--- /dev/null
+++ b/testing/code_metadata_proto/Android.bp
@@ -0,0 +1,43 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-testing-code_metadata_proto",
+ pkgPath: "android/soong/testing/code_metadata_proto",
+ deps: [
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ ],
+ srcs: [
+ "code_metadata.pb.go",
+ ],
+}
+
+python_library_host {
+ name: "code-metadata-proto-py",
+ pkg_path: "code_metadata",
+ srcs: [
+ "code_metadata.proto",
+ ],
+ libs: [
+ "libprotobuf-python",
+ ],
+ proto: {
+ canonical_path_from_root: false,
+ },
+}
diff --git a/testing/code_metadata_proto/OWNERS b/testing/code_metadata_proto/OWNERS
new file mode 100644
index 0000000..03bcdf1
--- /dev/null
+++ b/testing/code_metadata_proto/OWNERS
@@ -0,0 +1,4 @@
+dariofreni@google.com
+joeo@google.com
+ronish@google.com
+caditya@google.com
diff --git a/testing/code_metadata_proto/code_metadata.pb.go b/testing/code_metadata_proto/code_metadata.pb.go
new file mode 100644
index 0000000..711bf7a
--- /dev/null
+++ b/testing/code_metadata_proto/code_metadata.pb.go
@@ -0,0 +1,263 @@
+// 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc v3.21.12
+// source: code_metadata.proto
+
+package code_metadata_proto
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type CodeMetadata struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // List of all code targets and their metadata.
+ TargetOwnershipList []*CodeMetadata_TargetOwnership `protobuf:"bytes,1,rep,name=target_ownership_list,json=targetOwnershipList" json:"target_ownership_list,omitempty"`
+}
+
+func (x *CodeMetadata) Reset() {
+ *x = CodeMetadata{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_code_metadata_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CodeMetadata) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CodeMetadata) ProtoMessage() {}
+
+func (x *CodeMetadata) ProtoReflect() protoreflect.Message {
+ mi := &file_code_metadata_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CodeMetadata.ProtoReflect.Descriptor instead.
+func (*CodeMetadata) Descriptor() ([]byte, []int) {
+ return file_code_metadata_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *CodeMetadata) GetTargetOwnershipList() []*CodeMetadata_TargetOwnership {
+ if x != nil {
+ return x.TargetOwnershipList
+ }
+ return nil
+}
+
+type CodeMetadata_TargetOwnership struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // REQUIRED: Name of the build target
+ TargetName *string `protobuf:"bytes,1,opt,name=target_name,json=targetName" json:"target_name,omitempty"`
+ // REQUIRED: Code location of the target.
+ // To be used to support legacy/backup systems that use OWNERS file and is
+ // also required for our dashboard to support per code location basis UI
+ Path *string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"`
+ // REQUIRED: Team ID of the team that owns this target.
+ TrendyTeamId *string `protobuf:"bytes,3,opt,name=trendy_team_id,json=trendyTeamId" json:"trendy_team_id,omitempty"`
+ // OPTIONAL: The src files of the target.
+ // To be used to determine ownership of a file for ownership
+ SourceFiles []string `protobuf:"bytes,4,rep,name=source_files,json=sourceFiles" json:"source_files,omitempty"`
+}
+
+func (x *CodeMetadata_TargetOwnership) Reset() {
+ *x = CodeMetadata_TargetOwnership{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_code_metadata_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *CodeMetadata_TargetOwnership) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*CodeMetadata_TargetOwnership) ProtoMessage() {}
+
+func (x *CodeMetadata_TargetOwnership) ProtoReflect() protoreflect.Message {
+ mi := &file_code_metadata_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use CodeMetadata_TargetOwnership.ProtoReflect.Descriptor instead.
+func (*CodeMetadata_TargetOwnership) Descriptor() ([]byte, []int) {
+ return file_code_metadata_proto_rawDescGZIP(), []int{0, 0}
+}
+
+func (x *CodeMetadata_TargetOwnership) GetTargetName() string {
+ if x != nil && x.TargetName != nil {
+ return *x.TargetName
+ }
+ return ""
+}
+
+func (x *CodeMetadata_TargetOwnership) GetPath() string {
+ if x != nil && x.Path != nil {
+ return *x.Path
+ }
+ return ""
+}
+
+func (x *CodeMetadata_TargetOwnership) GetTrendyTeamId() string {
+ if x != nil && x.TrendyTeamId != nil {
+ return *x.TrendyTeamId
+ }
+ return ""
+}
+
+func (x *CodeMetadata_TargetOwnership) GetSourceFiles() []string {
+ if x != nil {
+ return x.SourceFiles
+ }
+ return nil
+}
+
+var File_code_metadata_proto protoreflect.FileDescriptor
+
+var file_code_metadata_proto_rawDesc = []byte{
+ 0x0a, 0x13, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e,
+ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x13, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61,
+ 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x87, 0x02, 0x0a, 0x0c, 0x43,
+ 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x65, 0x0a, 0x15, 0x74,
+ 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f,
+ 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x63, 0x6f, 0x64,
+ 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x61,
+ 0x72, 0x67, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x52, 0x13, 0x74,
+ 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x4c, 0x69,
+ 0x73, 0x74, 0x1a, 0x8f, 0x01, 0x0a, 0x0f, 0x54, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4f, 0x77, 0x6e,
+ 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74,
+ 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x74, 0x61, 0x72,
+ 0x67, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0e, 0x74,
+ 0x72, 0x65, 0x6e, 0x64, 0x79, 0x5f, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x54, 0x65, 0x61, 0x6d, 0x49,
+ 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65,
+ 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46,
+ 0x69, 0x6c, 0x65, 0x73, 0x42, 0x2b, 0x5a, 0x29, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+ 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x63, 0x6f,
+ 0x64, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f,
+}
+
+var (
+ file_code_metadata_proto_rawDescOnce sync.Once
+ file_code_metadata_proto_rawDescData = file_code_metadata_proto_rawDesc
+)
+
+func file_code_metadata_proto_rawDescGZIP() []byte {
+ file_code_metadata_proto_rawDescOnce.Do(func() {
+ file_code_metadata_proto_rawDescData = protoimpl.X.CompressGZIP(file_code_metadata_proto_rawDescData)
+ })
+ return file_code_metadata_proto_rawDescData
+}
+
+var file_code_metadata_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_code_metadata_proto_goTypes = []interface{}{
+ (*CodeMetadata)(nil), // 0: code_metadata_proto.CodeMetadata
+ (*CodeMetadata_TargetOwnership)(nil), // 1: code_metadata_proto.CodeMetadata.TargetOwnership
+}
+var file_code_metadata_proto_depIdxs = []int32{
+ 1, // 0: code_metadata_proto.CodeMetadata.target_ownership_list:type_name -> code_metadata_proto.CodeMetadata.TargetOwnership
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_code_metadata_proto_init() }
+func file_code_metadata_proto_init() {
+ if File_code_metadata_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_code_metadata_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CodeMetadata); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_code_metadata_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CodeMetadata_TargetOwnership); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_code_metadata_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_code_metadata_proto_goTypes,
+ DependencyIndexes: file_code_metadata_proto_depIdxs,
+ MessageInfos: file_code_metadata_proto_msgTypes,
+ }.Build()
+ File_code_metadata_proto = out.File
+ file_code_metadata_proto_rawDesc = nil
+ file_code_metadata_proto_goTypes = nil
+ file_code_metadata_proto_depIdxs = nil
+}
diff --git a/testing/code_metadata_proto/code_metadata.proto b/testing/code_metadata_proto/code_metadata.proto
new file mode 100644
index 0000000..2548363
--- /dev/null
+++ b/testing/code_metadata_proto/code_metadata.proto
@@ -0,0 +1,37 @@
+// 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.
+
+syntax = "proto2";
+package code_metadata_proto;
+option go_package = "android/soong/testing/code_metadata_proto";
+
+message CodeMetadata {
+
+ message TargetOwnership {
+ // REQUIRED: Name of the build target
+ optional string target_name = 1;
+
+ // REQUIRED: Code location of the target.
+ // To be used to support legacy/backup systems that use OWNERS file and is
+ // also required for our dashboard to support per code location basis UI
+ optional string path = 2;
+
+ // REQUIRED: Team ID of the team that owns this target.
+ optional string trendy_team_id = 3;
+
+ // OPTIONAL: The src files of the target.
+ // To be used to determine ownership of a file for ownership
+ repeated string source_files = 4;
+ }
+
+ // List of all code targets and their metadata.
+ repeated TargetOwnership target_ownership_list = 1;
+}
diff --git a/testing/code_metadata_proto/regen.sh b/testing/code_metadata_proto/regen.sh
new file mode 100644
index 0000000..ffe06f7
--- /dev/null
+++ b/testing/code_metadata_proto/regen.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+aprotoc --go_out=paths=source_relative:. code_metadata.proto
diff --git a/testing/init.go b/testing/init.go
new file mode 100644
index 0000000..edcbf59
--- /dev/null
+++ b/testing/init.go
@@ -0,0 +1,35 @@
+// 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 testing
+
+import (
+ "android/soong/android"
+)
+
+var (
+ pctx = android.NewPackageContext("android/soong/testing")
+)
+
+func init() {
+ RegisterBuildComponents(android.InitRegistrationContext)
+ pctx.HostBinToolVariable("metadata", "metadata")
+}
+
+func RegisterBuildComponents(ctx android.RegistrationContext) {
+ ctx.RegisterModuleType("code_metadata", CodeMetadataFactory)
+ ctx.RegisterModuleType("test_spec", TestSpecFactory)
+ ctx.RegisterParallelSingletonType("all_code_metadata", AllCodeMetadataFactory)
+ ctx.RegisterParallelSingletonType("all_test_specs", AllTestSpecsFactory)
+}
diff --git a/testing/test.go b/testing/test.go
new file mode 100644
index 0000000..cd97a8f
--- /dev/null
+++ b/testing/test.go
@@ -0,0 +1,21 @@
+// Copyright 2023 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 testing
+
+import (
+ "android/soong/android"
+)
+
+var PrepareForTestWithTestingBuildComponents = android.FixtureRegisterWithContext(RegisterBuildComponents)
diff --git a/testing/test_spec.go b/testing/test_spec.go
new file mode 100644
index 0000000..4d885c6
--- /dev/null
+++ b/testing/test_spec.go
@@ -0,0 +1,127 @@
+// Copyright 2020 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 testing
+
+import (
+ "path/filepath"
+ "strconv"
+
+ "android/soong/android"
+ "android/soong/testing/test_spec_proto"
+ "google.golang.org/protobuf/proto"
+
+ "github.com/google/blueprint"
+)
+
+// ErrTestModuleDataNotFound is the error message for missing test module provider data.
+const ErrTestModuleDataNotFound = "The module '%s' does not provide test specification data. Hint: This issue could arise if either the module is not a valid testing module or if it lacks the required 'TestModuleProviderKey' provider.\n"
+
+func TestSpecFactory() android.Module {
+ module := &TestSpecModule{}
+
+ android.InitAndroidModule(module)
+ android.InitDefaultableModule(module)
+ module.AddProperties(&module.properties)
+
+ return module
+}
+
+type TestSpecModule struct {
+ android.ModuleBase
+ android.DefaultableModuleBase
+
+ // Properties for "test_spec"
+ properties struct {
+ // Specifies the name of the test config.
+ Name string
+ // Specifies the team ID.
+ TeamId string
+ // Specifies the list of tests covered under this module.
+ Tests []string
+ }
+}
+
+type testsDepTagType struct {
+ blueprint.BaseDependencyTag
+}
+
+var testsDepTag = testsDepTagType{}
+
+func (module *TestSpecModule) DepsMutator(ctx android.BottomUpMutatorContext) {
+ // Validate Properties
+ if len(module.properties.TeamId) == 0 {
+ ctx.PropertyErrorf("TeamId", "Team Id not found in the test_spec module. Hint: Maybe the TeamId property hasn't been properly specified.")
+ }
+ if !isInt(module.properties.TeamId) {
+ ctx.PropertyErrorf("TeamId", "Invalid value for Team ID. The Team ID must be an integer.")
+ }
+ if len(module.properties.Tests) == 0 {
+ ctx.PropertyErrorf("Tests", "Expected to attribute some test but none found. Hint: Maybe the test property hasn't been properly specified.")
+ }
+ ctx.AddDependency(ctx.Module(), testsDepTag, module.properties.Tests...)
+}
+func isInt(s string) bool {
+ _, err := strconv.Atoi(s)
+ return err == nil
+}
+
+// Provider published by TestSpec
+type TestSpecProviderData struct {
+ IntermediatePath android.WritablePath
+}
+
+var TestSpecProviderKey = blueprint.NewProvider[TestSpecProviderData]()
+
+type TestModuleProviderData struct {
+}
+
+var TestModuleProviderKey = blueprint.NewProvider[TestModuleProviderData]()
+
+func (module *TestSpecModule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+ for _, m := range ctx.GetDirectDepsWithTag(testsDepTag) {
+ if _, ok := android.OtherModuleProvider(ctx, m, TestModuleProviderKey); !ok {
+ ctx.ModuleErrorf(ErrTestModuleDataNotFound, m.Name())
+ }
+ }
+ bpFilePath := filepath.Join(ctx.ModuleDir(), ctx.BlueprintsFile())
+ metadataList := make(
+ []*test_spec_proto.TestSpec_OwnershipMetadata, 0,
+ len(module.properties.Tests),
+ )
+ for _, test := range module.properties.Tests {
+ targetName := test
+ metadata := test_spec_proto.TestSpec_OwnershipMetadata{
+ TrendyTeamId: &module.properties.TeamId,
+ TargetName: &targetName,
+ Path: &bpFilePath,
+ }
+ metadataList = append(metadataList, &metadata)
+ }
+ intermediatePath := android.PathForModuleOut(
+ ctx, "intermediateTestSpecMetadata.pb",
+ )
+ testSpecMetadata := test_spec_proto.TestSpec{OwnershipMetadataList: metadataList}
+ protoData, err := proto.Marshal(&testSpecMetadata)
+ if err != nil {
+ ctx.ModuleErrorf("Error: %s", err.Error())
+ }
+ android.WriteFileRuleVerbatim(ctx, intermediatePath, string(protoData))
+
+ android.SetProvider(ctx,
+ TestSpecProviderKey, TestSpecProviderData{
+ IntermediatePath: intermediatePath,
+ },
+ )
+}
diff --git a/testing/test_spec_proto/Android.bp b/testing/test_spec_proto/Android.bp
new file mode 100644
index 0000000..d5ad70b
--- /dev/null
+++ b/testing/test_spec_proto/Android.bp
@@ -0,0 +1,43 @@
+// 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+bootstrap_go_package {
+ name: "soong-testing-test_spec_proto",
+ pkgPath: "android/soong/testing/test_spec_proto",
+ deps: [
+ "golang-protobuf-reflect-protoreflect",
+ "golang-protobuf-runtime-protoimpl",
+ ],
+ srcs: [
+ "test_spec.pb.go",
+ ],
+}
+
+python_library_host {
+ name: "test-spec-proto-py",
+ pkg_path: "test_spec",
+ srcs: [
+ "test_spec.proto",
+ ],
+ libs: [
+ "libprotobuf-python",
+ ],
+ proto: {
+ canonical_path_from_root: false,
+ },
+}
diff --git a/testing/test_spec_proto/OWNERS b/testing/test_spec_proto/OWNERS
new file mode 100644
index 0000000..03bcdf1
--- /dev/null
+++ b/testing/test_spec_proto/OWNERS
@@ -0,0 +1,4 @@
+dariofreni@google.com
+joeo@google.com
+ronish@google.com
+caditya@google.com
diff --git a/testing/test_spec_proto/regen.sh b/testing/test_spec_proto/regen.sh
new file mode 100644
index 0000000..2cf8203
--- /dev/null
+++ b/testing/test_spec_proto/regen.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+aprotoc --go_out=paths=source_relative:. test_spec.proto
diff --git a/testing/test_spec_proto/test_spec.pb.go b/testing/test_spec_proto/test_spec.pb.go
new file mode 100644
index 0000000..5cce600
--- /dev/null
+++ b/testing/test_spec_proto/test_spec.pb.go
@@ -0,0 +1,244 @@
+// 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.
+
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// protoc-gen-go v1.30.0
+// protoc v3.21.12
+// source: test_spec.proto
+
+package test_spec_proto
+
+import (
+ protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+ protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+ reflect "reflect"
+ sync "sync"
+)
+
+const (
+ // Verify that this generated code is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+ // Verify that runtime/protoimpl is sufficiently up-to-date.
+ _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+type TestSpec struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // List of all test targets and their metadata.
+ OwnershipMetadataList []*TestSpec_OwnershipMetadata `protobuf:"bytes,1,rep,name=ownership_metadata_list,json=ownershipMetadataList" json:"ownership_metadata_list,omitempty"`
+}
+
+func (x *TestSpec) Reset() {
+ *x = TestSpec{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_test_spec_proto_msgTypes[0]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *TestSpec) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TestSpec) ProtoMessage() {}
+
+func (x *TestSpec) ProtoReflect() protoreflect.Message {
+ mi := &file_test_spec_proto_msgTypes[0]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use TestSpec.ProtoReflect.Descriptor instead.
+func (*TestSpec) Descriptor() ([]byte, []int) {
+ return file_test_spec_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *TestSpec) GetOwnershipMetadataList() []*TestSpec_OwnershipMetadata {
+ if x != nil {
+ return x.OwnershipMetadataList
+ }
+ return nil
+}
+
+type TestSpec_OwnershipMetadata struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ TargetName *string `protobuf:"bytes,1,opt,name=target_name,json=targetName" json:"target_name,omitempty"`
+ Path *string `protobuf:"bytes,2,opt,name=path" json:"path,omitempty"`
+ TrendyTeamId *string `protobuf:"bytes,3,opt,name=trendy_team_id,json=trendyTeamId" json:"trendy_team_id,omitempty"`
+}
+
+func (x *TestSpec_OwnershipMetadata) Reset() {
+ *x = TestSpec_OwnershipMetadata{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_test_spec_proto_msgTypes[1]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *TestSpec_OwnershipMetadata) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*TestSpec_OwnershipMetadata) ProtoMessage() {}
+
+func (x *TestSpec_OwnershipMetadata) ProtoReflect() protoreflect.Message {
+ mi := &file_test_spec_proto_msgTypes[1]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use TestSpec_OwnershipMetadata.ProtoReflect.Descriptor instead.
+func (*TestSpec_OwnershipMetadata) Descriptor() ([]byte, []int) {
+ return file_test_spec_proto_rawDescGZIP(), []int{0, 0}
+}
+
+func (x *TestSpec_OwnershipMetadata) GetTargetName() string {
+ if x != nil && x.TargetName != nil {
+ return *x.TargetName
+ }
+ return ""
+}
+
+func (x *TestSpec_OwnershipMetadata) GetPath() string {
+ if x != nil && x.Path != nil {
+ return *x.Path
+ }
+ return ""
+}
+
+func (x *TestSpec_OwnershipMetadata) GetTrendyTeamId() string {
+ if x != nil && x.TrendyTeamId != nil {
+ return *x.TrendyTeamId
+ }
+ return ""
+}
+
+var File_test_spec_proto protoreflect.FileDescriptor
+
+var file_test_spec_proto_rawDesc = []byte{
+ 0x0a, 0x0f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74,
+ 0x6f, 0x12, 0x0f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x5f, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x22, 0xdf, 0x01, 0x0a, 0x08, 0x54, 0x65, 0x73, 0x74, 0x53, 0x70, 0x65, 0x63, 0x12,
+ 0x63, 0x0a, 0x17, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x5f, 0x6d, 0x65, 0x74,
+ 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
+ 0x32, 0x2b, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x5f, 0x70, 0x72, 0x6f,
+ 0x74, 0x6f, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x70, 0x65, 0x63, 0x2e, 0x4f, 0x77, 0x6e, 0x65,
+ 0x72, 0x73, 0x68, 0x69, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x15, 0x6f,
+ 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61,
+ 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x6e, 0x0a, 0x11, 0x4f, 0x77, 0x6e, 0x65, 0x72, 0x73, 0x68, 0x69,
+ 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x61, 0x72,
+ 0x67, 0x65, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
+ 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61,
+ 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24,
+ 0x0a, 0x0e, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x5f, 0x74, 0x65, 0x61, 0x6d, 0x5f, 0x69, 0x64,
+ 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x74, 0x72, 0x65, 0x6e, 0x64, 0x79, 0x54, 0x65,
+ 0x61, 0x6d, 0x49, 0x64, 0x42, 0x27, 0x5a, 0x25, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
+ 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x74, 0x65,
+ 0x73, 0x74, 0x5f, 0x73, 0x70, 0x65, 0x63, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+}
+
+var (
+ file_test_spec_proto_rawDescOnce sync.Once
+ file_test_spec_proto_rawDescData = file_test_spec_proto_rawDesc
+)
+
+func file_test_spec_proto_rawDescGZIP() []byte {
+ file_test_spec_proto_rawDescOnce.Do(func() {
+ file_test_spec_proto_rawDescData = protoimpl.X.CompressGZIP(file_test_spec_proto_rawDescData)
+ })
+ return file_test_spec_proto_rawDescData
+}
+
+var file_test_spec_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_test_spec_proto_goTypes = []interface{}{
+ (*TestSpec)(nil), // 0: test_spec_proto.TestSpec
+ (*TestSpec_OwnershipMetadata)(nil), // 1: test_spec_proto.TestSpec.OwnershipMetadata
+}
+var file_test_spec_proto_depIdxs = []int32{
+ 1, // 0: test_spec_proto.TestSpec.ownership_metadata_list:type_name -> test_spec_proto.TestSpec.OwnershipMetadata
+ 1, // [1:1] is the sub-list for method output_type
+ 1, // [1:1] is the sub-list for method input_type
+ 1, // [1:1] is the sub-list for extension type_name
+ 1, // [1:1] is the sub-list for extension extendee
+ 0, // [0:1] is the sub-list for field type_name
+}
+
+func init() { file_test_spec_proto_init() }
+func file_test_spec_proto_init() {
+ if File_test_spec_proto != nil {
+ return
+ }
+ if !protoimpl.UnsafeEnabled {
+ file_test_spec_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*TestSpec); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_test_spec_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*TestSpec_OwnershipMetadata); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ }
+ type x struct{}
+ out := protoimpl.TypeBuilder{
+ File: protoimpl.DescBuilder{
+ GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+ RawDescriptor: file_test_spec_proto_rawDesc,
+ NumEnums: 0,
+ NumMessages: 2,
+ NumExtensions: 0,
+ NumServices: 0,
+ },
+ GoTypes: file_test_spec_proto_goTypes,
+ DependencyIndexes: file_test_spec_proto_depIdxs,
+ MessageInfos: file_test_spec_proto_msgTypes,
+ }.Build()
+ File_test_spec_proto = out.File
+ file_test_spec_proto_rawDesc = nil
+ file_test_spec_proto_goTypes = nil
+ file_test_spec_proto_depIdxs = nil
+}
diff --git a/testing/test_spec_proto/test_spec.proto b/testing/test_spec_proto/test_spec.proto
new file mode 100644
index 0000000..86bc789
--- /dev/null
+++ b/testing/test_spec_proto/test_spec.proto
@@ -0,0 +1,33 @@
+// 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.
+
+syntax = "proto2";
+package test_spec_proto;
+option go_package = "android/soong/testing/test_spec_proto";
+
+message TestSpec {
+
+ message OwnershipMetadata {
+ // REQUIRED: Name of the build target
+ optional string target_name = 1;
+
+ // REQUIRED: Code location of the target.
+ // To be used to support legacy/backup systems that use OWNERS file and is
+ // also required for our dashboard to support per code location basis UI
+ optional string path = 2;
+
+ // REQUIRED: Team ID of the team that owns this target.
+ optional string trendy_team_id = 3;
+ }
+
+ // List of all test targets and their metadata.
+ repeated OwnershipMetadata ownership_metadata_list = 1;
+}
diff --git a/tests/b_args_test.sh b/tests/b_args_test.sh
new file mode 100755
index 0000000..0dfbabf
--- /dev/null
+++ b/tests/b_args_test.sh
@@ -0,0 +1,43 @@
+#!/bin/bash -eu
+
+# This file tests the creation of bazel commands for b usage
+set -o pipefail
+source "$(dirname "$0")/../../bazel/lib.sh"
+
+BES_UUID="blank"
+OUT_DIR="arbitrary_out"
+b_args=$(formulate_b_args "build --config=nonsense foo:bar")
+
+if [[ $b_args != "build --profile=$OUT_DIR/bazel_metrics-profile --config=bp2build --invocation_id=$BES_UUID --config=metrics_data --config=nonsense foo:bar" ]]; then
+ echo "b args are malformed"
+ echo "Expected : build --profile=$OUT_DIR/bazel_metrics-profile --config=bp2build --invocation_id=$BES_UUID --config=metrics_data --config=nonsense foo:bar"
+ echo "Actual: $b_args"
+ exit 1
+fi
+
+b_args=$(formulate_b_args "build --config=nonsense --disable_bes --package_path \"my package\" foo:bar")
+
+if [[ $b_args != "build --profile=$OUT_DIR/bazel_metrics-profile --config=bp2build --invocation_id=$BES_UUID --config=nonsense --package_path \"my package\" foo:bar" ]]; then
+ echo "b args are malformed"
+ echo "Expected : build --profile=$OUT_DIR/bazel_metrics-profile --config=bp2build --invocation_id=$BES_UUID --config=nonsense --package_path \"my package\" foo:bar"
+ echo "Actual: $b_args"
+ exit 1
+fi
+
+# Test with startup option
+b_args=$(formulate_b_args "--batch build --config=nonsense --disable_bes --package_path \"my package\" foo:bar")
+if [[ $b_args != "--batch build --profile=$OUT_DIR/bazel_metrics-profile --config=bp2build --invocation_id=$BES_UUID --config=nonsense --package_path \"my package\" foo:bar" ]]; then
+ echo "b args are malformed"
+ echo "Expected : --batch build --profile=$OUT_DIR/bazel_metrics-profile --config=bp2build --invocation_id=$BES_UUID --config=nonsense --package_path \"my package\" foo:bar"
+ echo "Actual: $b_args"
+ exit 1
+fi
+
+OUT_DIR="mock_out"
+TEST_PROFILE_OUT=$(get_profile_out_dir)
+if [[ $TEST_PROFILE_OUT != "mock_out" ]]; then
+ echo "Profile Out is malformed."
+ echo "Expected: mock_out"
+ echo "Actual: $TEST_PROFILE_OUT"
+ exit 1
+fi
diff --git a/tests/genrule_sandbox_test.py b/tests/genrule_sandbox_test.py
index 0cebc2a..3799e92 100755
--- a/tests/genrule_sandbox_test.py
+++ b/tests/genrule_sandbox_test.py
@@ -15,12 +15,14 @@
# limitations under the License.
import argparse
+import asyncio
import collections
import json
import os
+import socket
import subprocess
import sys
-import tempfile
+import textwrap
def get_top() -> str:
path = '.'
@@ -30,38 +32,65 @@
path = os.path.join(path, '..')
return os.path.abspath(path)
-def _build_with_soong(targets, target_product, *, keep_going = False, extra_env={}):
- env = {
- **os.environ,
- "TARGET_PRODUCT": target_product,
- "TARGET_BUILD_VARIANT": "userdebug",
- }
- env.update(extra_env)
+async def _build_with_soong(out_dir, targets, *, extra_env={}):
+ env = os.environ | extra_env
+
+ # Use nsjail to remap the out_dir to out/, because some genrules write the path to the out
+ # dir into their artifacts, so if the out directories were different it would cause a diff
+ # that doesn't really matter.
args = [
+ 'prebuilts/build-tools/linux-x86/bin/nsjail',
+ '-q',
+ '--cwd',
+ os.getcwd(),
+ '-e',
+ '-B',
+ '/',
+ '-B',
+ f'{os.path.abspath(out_dir)}:{os.path.abspath("out")}',
+ '--time_limit',
+ '0',
+ '--skip_setsid',
+ '--keep_caps',
+ '--disable_clone_newcgroup',
+ '--disable_clone_newnet',
+ '--rlimit_as',
+ 'soft',
+ '--rlimit_core',
+ 'soft',
+ '--rlimit_cpu',
+ 'soft',
+ '--rlimit_fsize',
+ 'soft',
+ '--rlimit_nofile',
+ 'soft',
+ '--proc_rw',
+ '--hostname',
+ socket.gethostname(),
+ '--',
"build/soong/soong_ui.bash",
"--make-mode",
"--skip-soong-tests",
]
- if keep_going:
- args.append("-k")
args.extend(targets)
- try:
- subprocess.check_output(
- args,
- env=env,
- )
- except subprocess.CalledProcessError as e:
- print(e)
- print(e.stdout)
- print(e.stderr)
- exit(1)
+ process = await asyncio.create_subprocess_exec(
+ *args,
+ stdout=asyncio.subprocess.PIPE,
+ stderr=asyncio.subprocess.PIPE,
+ env=env,
+ )
+ stdout, stderr = await process.communicate()
+ if process.returncode != 0:
+ print(stdout)
+ print(stderr)
+ sys.exit(process.returncode)
-def _find_outputs_for_modules(modules, out_dir, target_product):
- module_path = os.path.join(out_dir, "soong", "module-actions.json")
+async def _find_outputs_for_modules(modules):
+ module_path = "out/soong/module-actions.json"
if not os.path.exists(module_path):
- _build_with_soong(["json-module-graph"], target_product)
+ await _build_with_soong('out', ["json-module-graph"])
with open(module_path) as f:
action_graph = json.load(f)
@@ -70,7 +99,7 @@
for mod in action_graph:
name = mod["Name"]
if name in modules:
- for act in mod["Module"]["Actions"]:
+ for act in (mod["Module"]["Actions"] or []):
if "}generate" in act["Desc"]:
module_to_outs[name].update(act["Outputs"])
return module_to_outs
@@ -88,20 +117,19 @@
return different_modules
-def main():
+async def main():
parser = argparse.ArgumentParser()
parser.add_argument(
- "--target_product",
- "-t",
- default="aosp_cf_arm64_phone",
- help="optional, target product, always runs as eng",
- )
- parser.add_argument(
"modules",
nargs="+",
help="modules to compare builds with genrule sandboxing enabled/not",
)
parser.add_argument(
+ "--check-determinism",
+ action="store_true",
+ help="Don't check for working sandboxing. Instead, run two default builds, and compare their outputs. This is used to check for nondeterminsim, which would also affect the sandboxed test.",
+ )
+ parser.add_argument(
"--show-diff",
"-d",
action="store_true",
@@ -116,10 +144,13 @@
args = parser.parse_args()
os.chdir(get_top())
- out_dir = os.environ.get("OUT_DIR", "out")
+ if "TARGET_PRODUCT" not in os.environ:
+ sys.exit("Please run lunch first")
+ if os.environ.get("OUT_DIR", "out") != "out":
+ sys.exit(f"This script expects OUT_DIR to be 'out', got: '{os.environ.get('OUT_DIR')}'")
print("finding output files for the modules...")
- module_to_outs = _find_outputs_for_modules(set(args.modules), out_dir, args.target_product)
+ module_to_outs = await _find_outputs_for_modules(set(args.modules))
if not module_to_outs:
sys.exit("No outputs found")
@@ -129,33 +160,48 @@
sys.exit(0)
all_outs = list(set.union(*module_to_outs.values()))
+ for i, out in enumerate(all_outs):
+ if not out.startswith("out/"):
+ sys.exit("Expected output file to start with out/, found: " + out)
- print("building without sandboxing...")
- _build_with_soong(all_outs, args.target_product)
- with tempfile.TemporaryDirectory() as tempdir:
- for f in all_outs:
- subprocess.check_call(["cp", "--parents", f, tempdir])
+ other_out_dir = "out_check_determinism" if args.check_determinism else "out_not_sandboxed"
+ other_env = {"GENRULE_SANDBOXING": "false"}
+ if args.check_determinism:
+ other_env = {}
- print("building with sandboxing...")
- _build_with_soong(
- all_outs,
- args.target_product,
- # We've verified these build without sandboxing already, so do the sandboxing build
- # with keep_going = True so that we can find all the genrules that fail to build with
- # sandboxing.
- keep_going = True,
- extra_env={"GENRULE_SANDBOXING": "true"},
- )
+ # nsjail will complain if the out dir doesn't exist
+ os.makedirs("out", exist_ok=True)
+ os.makedirs(other_out_dir, exist_ok=True)
- diffs = _compare_outputs(module_to_outs, tempdir)
- if len(diffs) == 0:
- print("All modules are correct")
- elif args.show_diff:
- for m, d in diffs.items():
- print(f"Module {m} has diffs {d}")
- else:
- print(f"Modules {list(diffs.keys())} have diffs")
+ print("building...")
+ await asyncio.gather(
+ _build_with_soong("out", all_outs),
+ _build_with_soong(other_out_dir, all_outs, extra_env=other_env)
+ )
+
+ diffs = collections.defaultdict(dict)
+ for module, outs in module_to_outs.items():
+ for out in outs:
+ try:
+ subprocess.check_output(["diff", os.path.join(other_out_dir, out.removeprefix("out/")), out])
+ except subprocess.CalledProcessError as e:
+ diffs[module][out] = e.stdout
+
+ if len(diffs) == 0:
+ print("All modules are correct")
+ elif args.show_diff:
+ for m, files in diffs.items():
+ print(f"Module {m} has diffs:")
+ for f, d in files.items():
+ print(" "+f+":")
+ print(textwrap.indent(d, " "))
+ else:
+ print(f"Modules {list(diffs.keys())} have diffs in these files:")
+ all_diff_files = [f for m in diffs.values() for f in m]
+ for f in all_diff_files:
+ print(f)
+
if __name__ == "__main__":
- main()
+ asyncio.run(main())
diff --git a/tests/lib.sh b/tests/lib.sh
index 0766d85..e0b319e 100644
--- a/tests/lib.sh
+++ b/tests/lib.sh
@@ -8,10 +8,15 @@
REAL_TOP="$(readlink -f "$(dirname "$0")"/../../..)"
+function make_mock_top {
+ mock=$(mktemp -t -d st.XXXXX)
+ echo "$mock"
+}
+
if [[ -n "$HARDWIRED_MOCK_TOP" ]]; then
MOCK_TOP="$HARDWIRED_MOCK_TOP"
else
- MOCK_TOP=$(mktemp -t -d st.XXXXX)
+ MOCK_TOP=$(make_mock_top)
trap cleanup_mock_top EXIT
fi
@@ -158,6 +163,7 @@
symlink_directory external/bazelbuild-rules_python
symlink_directory external/bazelbuild-rules_java
symlink_directory external/bazelbuild-rules_rust
+ symlink_directory external/bazelbuild-rules_testing
symlink_directory external/rust/crates/tinyjson
symlink_file WORKSPACE
@@ -197,3 +203,11 @@
info "Completed test case \e[96;1m$f\e[0m"
done
}
+
+function move_mock_top {
+ MOCK_TOP2=$(make_mock_top)
+ rm -rf $MOCK_TOP2
+ mv $MOCK_TOP $MOCK_TOP2
+ MOCK_TOP=$MOCK_TOP2
+ trap cleanup_mock_top EXIT
+}
diff --git a/tests/run_integration_tests.sh b/tests/run_integration_tests.sh
index 6b9ff8b..231e18b 100755
--- a/tests/run_integration_tests.sh
+++ b/tests/run_integration_tests.sh
@@ -4,12 +4,14 @@
TOP="$(readlink -f "$(dirname "$0")"/../../..)"
"$TOP/build/soong/tests/androidmk_test.sh"
+"$TOP/build/soong/tests/b_args_test.sh"
"$TOP/build/soong/tests/bootstrap_test.sh"
"$TOP/build/soong/tests/mixed_mode_test.sh"
"$TOP/build/soong/tests/bp2build_bazel_test.sh"
"$TOP/build/soong/tests/persistent_bazel_test.sh"
"$TOP/build/soong/tests/soong_test.sh"
"$TOP/build/soong/tests/stale_metrics_files_test.sh"
+"$TOP/build/soong/tests/symlink_forest_rerun_test.sh"
"$TOP/prebuilts/build-tools/linux-x86/bin/py3-cmd" "$TOP/build/bazel/ci/rbc_dashboard.py" aosp_arm64-userdebug
# The following tests build against the full source tree and don't rely on the
@@ -23,4 +25,4 @@
"$TOP/build/soong/tests/apex_cc_module_arch_variant_tests.sh" "aosp_cf_arm64_phone" "armv8-a" "cortex-a53"
"$TOP/build/bazel/ci/b_test.sh"
-
+"$TOP/build/soong/tests/symlinks_path_test.sh"
diff --git a/tests/sbom_test.sh b/tests/sbom_test.sh
index 73fbeab..8dc1630 100755
--- a/tests/sbom_test.sh
+++ b/tests/sbom_test.sh
@@ -35,14 +35,15 @@
}
function run_soong {
- target_product="$1";shift
- out_dir="$1"; shift
- targets="$1"; shift
+ local out_dir="$1"; shift
+ local targets="$1"; shift
if [ "$#" -ge 1 ]; then
- apps=$1; shift
- TARGET_PRODUCT="${target_product}" TARGET_BUILD_VARIANT=userdebug OUT_DIR="${out_dir}" TARGET_BUILD_UNBUNDLED=true TARGET_BUILD_APPS=$apps build/soong/soong_ui.bash --make-mode ${targets}
+ local apps=$1; shift
+ TARGET_PRODUCT="${target_product}" TARGET_RELEASE="${target_release}" TARGET_BUILD_VARIANT="${target_build_variant}" OUT_DIR="${out_dir}" TARGET_BUILD_UNBUNDLED=true TARGET_BUILD_APPS=$apps \
+ build/soong/soong_ui.bash --make-mode ${targets}
else
- TARGET_PRODUCT="${target_product}" TARGET_BUILD_VARIANT=userdebug OUT_DIR="${out_dir}" build/soong/soong_ui.bash --make-mode ${targets}
+ TARGET_PRODUCT="${target_product}" TARGET_RELEASE="${target_release}" TARGET_BUILD_VARIANT="${target_build_variant}" OUT_DIR="${out_dir}" \
+ build/soong/soong_ui.bash --make-mode ${targets}
fi
}
@@ -67,7 +68,7 @@
# Test
# m droid, build sbom later in case additional dependencies might be built and included in partition images.
- run_soong "aosp_cf_x86_64_phone" "${out_dir}" "droid dump.erofs lz4"
+ run_soong "${out_dir}" "droid dump.erofs lz4"
product_out=$out_dir/target/product/vsoc_x86_64
sbom_test=$product_out/sbom_test
@@ -75,7 +76,7 @@
cp $product_out/*.img $sbom_test
# m sbom
- run_soong "aosp_cf_x86_64_phone" "${out_dir}" sbom
+ run_soong "${out_dir}" sbom
# Generate installed file list from .img files in PRODUCT_OUT
dump_erofs=$out_dir/host/linux-x86/bin/dump.erofs
@@ -217,7 +218,7 @@
out_dir="$(setup)"
# run_soong to build com.android.adbd.apex
- run_soong "module_arm64" "${out_dir}" "sbom deapexer" "com.android.adbd"
+ run_soong "${out_dir}" "sbom deapexer" "com.android.adbd"
deapexer=${out_dir}/host/linux-x86/bin/deapexer
debugfs=${out_dir}/host/linux-x86/bin/debugfs_static
@@ -249,7 +250,7 @@
out_dir="$(setup)"
# run_soong to build Browser2.apk
- run_soong "module_arm64" "${out_dir}" "sbom" "Browser2"
+ run_soong "${out_dir}" "sbom" "Browser2"
sbom_file=${out_dir}/target/product/module_arm64/system/product/app/Browser2/Browser2.apk.spdx.json
echo "============ Diffing files in Browser2.apk and SBOM"
@@ -271,6 +272,41 @@
cleanup "${out_dir}"
}
-test_sbom_aosp_cf_x86_64_phone
-test_sbom_unbundled_apex
-test_sbom_unbundled_apk
\ No newline at end of file
+target_product=aosp_cf_x86_64_phone
+target_release=trunk_staging
+target_build_variant=userdebug
+for i in "$@"; do
+ case $i in
+ TARGET_PRODUCT=*)
+ target_product=${i#*=}
+ shift
+ ;;
+ TARGET_RELEASE=*)
+ target_release=${i#*=}
+ shift
+ ;;
+ TARGET_BUILD_VARIANT=*)
+ target_build_variant=${i#*=}
+ shift
+ ;;
+ *)
+ echo "Unknown command line arguments: $i"
+ exit 1
+ ;;
+ esac
+done
+
+echo "target product: $target_product, target_release: $target_release, target build variant: $target_build_variant"
+case $target_product in
+ aosp_cf_x86_64_phone)
+ test_sbom_aosp_cf_x86_64_phone
+ ;;
+ module_arm64)
+ test_sbom_unbundled_apex
+ test_sbom_unbundled_apk
+ ;;
+ *)
+ echo "Unknown TARGET_PRODUCT: $target_product"
+ exit 1
+ ;;
+esac
\ No newline at end of file
diff --git a/tests/symlink_forest_rerun_test.sh b/tests/symlink_forest_rerun_test.sh
new file mode 100755
index 0000000..74e779e
--- /dev/null
+++ b/tests/symlink_forest_rerun_test.sh
@@ -0,0 +1,43 @@
+#!/bin/bash -eu
+
+set -o pipefail
+
+# Tests that symlink forest will replant if soong_build has changed
+# Any change to the build system should trigger a rerun
+
+source "$(dirname "$0")/lib.sh"
+
+function test_symlink_forest_reruns {
+ setup
+
+ mkdir -p a
+ touch a/g.txt
+ cat > a/Android.bp <<'EOF'
+filegroup {
+ name: "g",
+ srcs: ["g.txt"],
+ }
+EOF
+
+ run_soong g
+
+ mtime=`cat out/soong/workspace/soong_build_mtime`
+ # rerun with no changes - ensure that it hasn't changed
+ run_soong g
+ newmtime=`cat out/soong/workspace/soong_build_mtime`
+ if [[ ! "$mtime" == "$mtime" ]]; then
+ fail "symlink forest reran when it shouldn't have"
+ fi
+
+ # change exit codes to force a soong_build rebuild.
+ sed -i 's/os.Exit(1)/os.Exit(2)/g' build/soong/bp2build/symlink_forest.go
+
+ run_soong g
+ newmtime=`cat out/soong/workspace/soong_build_mtime`
+ if [[ "$mtime" == "$newmtime" ]]; then
+ fail "symlink forest did not rerun when it should have"
+ fi
+
+}
+
+scan_and_run_tests
diff --git a/tests/symlinks_path_test.sh b/tests/symlinks_path_test.sh
new file mode 100755
index 0000000..ed42911
--- /dev/null
+++ b/tests/symlinks_path_test.sh
@@ -0,0 +1,51 @@
+#!/bin/bash -eu
+
+set -o pipefail
+
+# Test that relative symlinks work by recreating the bug in b/259191764
+# In some cases, developers prefer to move their checkouts. This causes
+# issues in that symlinked files (namely, the bazel wrapper script)
+# cannot be found. As such, we implemented relative symlinks so that a
+# moved checkout doesn't need a full clean before rebuilding.
+# The bazel output base will still need to be removed, as Starlark
+# doesn't seem to support relative symlinks yet.
+
+source "$(dirname "$0")/lib.sh"
+
+function check_link_has_mock_top_prefix {
+ input_link=$1
+ link_target=`readlink $input_link`
+ if [[ $link_target != "$MOCK_TOP"* ]]; then
+ echo "Symlink for file $input_link -> $link_target doesn't start with $MOCK_TOP"
+ exit 1
+ fi
+}
+
+function test_symlinks_updated_when_top_dir_changed {
+ setup
+
+ mkdir -p a
+ touch a/g.txt
+ cat > a/Android.bp <<'EOF'
+filegroup {
+ name: "g",
+ srcs: ["g.txt"],
+ bazel_module: {bp2build_available: true},
+}
+EOF
+ # A directory under $MOCK_TOP
+ outdir=out2
+
+ # Modify OUT_DIR in a subshell so it doesn't affect the top level one.
+ (export OUT_DIR=$MOCK_TOP/$outdir; run_soong bp2build && run_bazel build --config=bp2build --config=ci //a:g)
+
+ g_txt="out2/soong/workspace/a/g.txt"
+ check_link_has_mock_top_prefix "$g_txt"
+
+ move_mock_top
+
+ (export OUT_DIR=$MOCK_TOP/$outdir; run_soong bp2build && run_bazel build --config=bp2build --config=ci //a:g)
+ check_link_has_mock_top_prefix "$g_txt"
+}
+
+scan_and_run_tests
\ No newline at end of file
diff --git a/tradefed/Android.bp b/tradefed/Android.bp
index a161108..f0336a3 100644
--- a/tradefed/Android.bp
+++ b/tradefed/Android.bp
@@ -11,7 +11,6 @@
],
srcs: [
"autogen.go",
- "autogen_bazel.go",
"config.go",
"makevars.go",
],
diff --git a/tradefed/autogen_bazel.go b/tradefed/autogen_bazel.go
deleted file mode 100644
index 8283984..0000000
--- a/tradefed/autogen_bazel.go
+++ /dev/null
@@ -1,111 +0,0 @@
-// 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 tradefed
-
-import (
- "android/soong/android"
- "android/soong/bazel"
-
- "github.com/google/blueprint/proptools"
-)
-
-const (
- InstrumentationTestConfigTemplate = "build/make/core/instrumentation_test_config_template.xml"
- JavaTestConfigTemplate = "build/make/core/java_test_config_template.xml"
- JavaHostTestConfigTemplate = "build/make/core/java_host_test_config_template.xml"
- JavaHostUnitTestConfigTemplate = "build/make/core/java_host_unit_test_config_template.xml"
- NativeBenchmarkTestConfigTemplate = "build/make/core/native_benchmark_test_config_template.xml"
- NativeHostTestConfigTemplate = "build/make/core/native_host_test_config_template.xml"
- NativeTestConfigTemplate = "build/make/core/native_test_config_template.xml"
- PythonBinaryHostTestConfigTemplate = "build/make/core/python_binary_host_test_config_template.xml"
- RustDeviceTestConfigTemplate = "build/make/core/rust_device_test_config_template.xml"
- RustHostTestConfigTemplate = "build/make/core/rust_host_test_config_template.xml"
- RustDeviceBenchmarkConfigTemplate = "build/make/core/rust_device_benchmark_config_template.xml"
- RustHostBenchmarkConfigTemplate = "build/make/core/rust_host_benchmark_config_template.xml"
- RobolectricTestConfigTemplate = "build/make/core/robolectric_test_config_template.xml"
- ShellTestConfigTemplate = "build/make/core/shell_test_config_template.xml"
-)
-
-type TestConfigAttributes struct {
- Test_config *bazel.Label
- Dynamic_config *bazel.Label
-
- Auto_generate_test_config *bool
- Template_test_config *bazel.Label
- Template_configs []string
- Template_install_base *string
-}
-
-func GetTestConfigAttributes(
- ctx android.TopDownMutatorContext,
- testConfig *string,
- extraTestConfigs []string,
- autoGenConfig *bool,
- testSuites []string,
- template *string,
- templateConfigs []Config,
- templateInstallBase *string) TestConfigAttributes {
-
- attrs := TestConfigAttributes{}
-
- dynamicConfig := "DynamicConfig.xml"
- c, _ := android.BazelStringOrLabelFromProp(ctx, &dynamicConfig)
- attrs.Dynamic_config = c.Value
-
- attrs.Test_config = GetTestConfig(ctx, testConfig)
- // do not generate a test config if
- // 1) test config already found
- // 2) autoGenConfig == false
- // 3) CTS tests and no template specified.
- // CTS Modules can be used for test data, so test config files must be explicitly specified.
- if (attrs.Template_test_config != nil) ||
- proptools.Bool(autoGenConfig) == false ||
- (template == nil && !android.InList("cts", testSuites)) {
-
- return attrs
- }
-
- // Add properties for the bazel rule to generate a test config
- // since a test config was not specified.
- templateLabel := android.BazelLabelForModuleSrcSingle(ctx, *template)
- attrs.Template_test_config = &templateLabel
- attrs.Auto_generate_test_config = autoGenConfig
- var configStrings []string
- for _, c := range templateConfigs {
- configString := proptools.NinjaAndShellEscape(c.Config())
- configStrings = append(configStrings, configString)
- }
- attrs.Template_configs = configStrings
- attrs.Template_install_base = templateInstallBase
- return attrs
-}
-
-func GetTestConfig(
- ctx android.TopDownMutatorContext,
- testConfig *string,
-) *bazel.Label {
-
- if testConfig != nil {
- c, _ := android.BazelStringOrLabelFromProp(ctx, testConfig)
- if c.Value != nil {
- return c.Value
- }
- }
-
- // check for default AndroidTest.xml
- defaultTestConfigPath := "AndroidTest.xml"
- c, _ := android.BazelStringOrLabelFromProp(ctx, &defaultTestConfigPath)
- return c.Value
-}
diff --git a/tradefed/suite_harness/tradefed_binary.go b/tradefed/suite_harness/tradefed_binary.go
index 1ce94bc..96fb354 100644
--- a/tradefed/suite_harness/tradefed_binary.go
+++ b/tradefed/suite_harness/tradefed_binary.go
@@ -35,6 +35,7 @@
Short_name string
Full_name string
Version string
+ Suite_arch string
Prepend_platform_version_name bool
}
@@ -67,6 +68,7 @@
Name: &genName,
Short_name: tfb.Short_name,
Full_name: tfb.Full_name,
+ Suite_arch: tfb.Suite_arch,
Version: version,
})
@@ -95,6 +97,7 @@
Short_name string
Full_name string
Version string
+ Suite_arch string
}
type tradefedBinaryGen struct {
@@ -127,13 +130,19 @@
func (tfg *tradefedBinaryGen) GenerateAndroidBuildActions(ctx android.ModuleContext) {
buildNumberFile := ctx.Config().BuildNumberFile(ctx)
outputFile := android.PathForModuleOut(ctx, "test-suite-info.properties")
+
+ arch := strings.ReplaceAll(tfg.properties.Suite_arch, " ", "")
+ if arch == "" {
+ arch = ctx.Config().DevicePrimaryArchType().String()
+ }
+
ctx.Build(pctx, android.BuildParams{
Rule: tradefedBinaryGenRule,
Output: outputFile,
OrderOnly: android.Paths{buildNumberFile},
Args: map[string]string{
"buildNumberFile": buildNumberFile.String(),
- "arch": ctx.Config().DevicePrimaryArchType().String(),
+ "arch": arch,
"name": tfg.properties.Short_name,
"fullname": tfg.properties.Full_name,
"version": tfg.properties.Version,
diff --git a/ui/build/Android.bp b/ui/build/Android.bp
index 959ae4c..ee286f6 100644
--- a/ui/build/Android.bp
+++ b/ui/build/Android.bp
@@ -35,6 +35,7 @@
"blueprint",
"blueprint-bootstrap",
"blueprint-microfactory",
+ "soong-android",
"soong-finder",
"soong-remoteexec",
"soong-shared",
@@ -46,7 +47,7 @@
"soong-ui-tracer",
],
srcs: [
- "bazel_metrics.go",
+ "androidmk_denylist.go",
"build.go",
"cleanbuild.go",
"config.go",
@@ -75,7 +76,6 @@
"proc_sync_test.go",
"rbe_test.go",
"staging_snapshot_test.go",
- "upload_test.go",
"util_test.go",
],
darwin: {
diff --git a/ui/build/androidmk_denylist.go b/ui/build/androidmk_denylist.go
new file mode 100644
index 0000000..e004cdc
--- /dev/null
+++ b/ui/build/androidmk_denylist.go
@@ -0,0 +1,47 @@
+// Copyright 2024 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 build
+
+import (
+ "strings"
+
+ "android/soong/android"
+)
+
+var androidmk_denylist []string = []string{
+ "chained_build_config/",
+ "cts/",
+ "dalvik/",
+ "developers/",
+ // Do not block other directories in kernel/, see b/319658303.
+ "kernel/configs/",
+ "kernel/prebuilts/",
+ "kernel/tests/",
+ "libcore/",
+ "libnativehelper/",
+ "pdk/",
+ "toolchain/",
+}
+
+func blockAndroidMks(androidMks []string) []string {
+ return android.FilterListPred(androidMks, func(s string) bool {
+ for _, d := range androidmk_denylist {
+ if strings.HasPrefix(s, d) {
+ return false
+ }
+ }
+ return true
+ })
+}
diff --git a/ui/build/bazel_metrics.go b/ui/build/bazel_metrics.go
deleted file mode 100644
index 3f9fbb1..0000000
--- a/ui/build/bazel_metrics.go
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2023 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 build
-
-// This file contains functionality to parse bazel profile data into
-// a bazel_metrics proto, defined in build/soong/ui/metrics/bazel_metrics_proto
-// These metrics are later uploaded in upload.go
-
-import (
- "bufio"
- "os"
- "strconv"
- "strings"
-
- "android/soong/shared"
- "google.golang.org/protobuf/proto"
-
- bazel_metrics_proto "android/soong/ui/metrics/bazel_metrics_proto"
-)
-
-func parseTimingToNanos(str string) int64 {
- millisString := removeDecimalPoint(str)
- timingMillis, _ := strconv.ParseInt(millisString, 10, 64)
- return timingMillis * 1000000
-}
-
-func parsePercentageToTenThousandths(str string) int32 {
- percentageString := removeDecimalPoint(str)
- //remove the % at the end of the string
- percentage := strings.ReplaceAll(percentageString, "%", "")
- percentagePortion, _ := strconv.ParseInt(percentage, 10, 32)
- return int32(percentagePortion)
-}
-
-func removeDecimalPoint(numString string) string {
- // The format is always 0.425 or 10.425
- return strings.ReplaceAll(numString, ".", "")
-}
-
-func parseTotal(line string) int64 {
- words := strings.Fields(line)
- timing := words[3]
- return parseTimingToNanos(timing)
-}
-
-func parsePhaseTiming(line string) bazel_metrics_proto.PhaseTiming {
- words := strings.Fields(line)
- getPhaseNameAndTimingAndPercentage := func([]string) (string, int64, int32) {
- // Sample lines include:
- // Total launch phase time 0.011 s 2.59%
- // Total target pattern evaluation phase time 0.011 s 2.59%
- var beginning int
- var end int
- for ind, word := range words {
- if word == "Total" {
- beginning = ind + 1
- } else if beginning > 0 && word == "phase" {
- end = ind
- break
- }
- }
- phaseName := strings.Join(words[beginning:end], " ")
-
- // end is now "phase" - advance by 2 for timing and 4 for percentage
- percentageString := words[end+4]
- timingString := words[end+2]
- timing := parseTimingToNanos(timingString)
- percentagePortion := parsePercentageToTenThousandths(percentageString)
- return phaseName, timing, percentagePortion
- }
-
- phaseName, timing, portion := getPhaseNameAndTimingAndPercentage(words)
- phaseTiming := bazel_metrics_proto.PhaseTiming{}
- phaseTiming.DurationNanos = &timing
- phaseTiming.PortionOfBuildTime = &portion
-
- phaseTiming.PhaseName = &phaseName
- return phaseTiming
-}
-
-// This method takes a file created by bazel's --analyze-profile mode and
-// writes bazel metrics data to the provided filepath.
-func ProcessBazelMetrics(bazelProfileFile string, bazelMetricsFile string, ctx Context, config Config) {
- if bazelProfileFile == "" {
- return
- }
-
- readBazelProto := func(filepath string) bazel_metrics_proto.BazelMetrics {
- //serialize the proto, write it
- bazelMetrics := bazel_metrics_proto.BazelMetrics{}
-
- file, err := os.ReadFile(filepath)
- if err != nil {
- ctx.Fatalln("Error reading metrics file\n", err)
- }
-
- scanner := bufio.NewScanner(strings.NewReader(string(file)))
- scanner.Split(bufio.ScanLines)
-
- var phaseTimings []*bazel_metrics_proto.PhaseTiming
- for scanner.Scan() {
- line := scanner.Text()
- if strings.HasPrefix(line, "Total run time") {
- total := parseTotal(line)
- bazelMetrics.Total = &total
- } else if strings.HasPrefix(line, "Total") {
- phaseTiming := parsePhaseTiming(line)
- phaseTimings = append(phaseTimings, &phaseTiming)
- }
- }
- bazelMetrics.PhaseTimings = phaseTimings
- bazelMetrics.BesId = proto.String(config.besId)
-
- return bazelMetrics
- }
-
- if _, err := os.Stat(bazelProfileFile); err != nil {
- // We can assume bazel didn't run if the profile doesn't exist
- return
- }
- bazelProto := readBazelProto(bazelProfileFile)
- bazelProto.ExitCode = proto.Int32(config.bazelExitCode)
- shared.Save(&bazelProto, bazelMetricsFile)
-}
diff --git a/ui/build/build.go b/ui/build/build.go
index 14d23a7..9a9eccd 100644
--- a/ui/build/build.go
+++ b/ui/build/build.go
@@ -15,11 +15,13 @@
package build
import (
+ "fmt"
"io/ioutil"
"os"
"path/filepath"
"sync"
"text/template"
+ "time"
"android/soong/ui/metrics"
)
@@ -29,6 +31,7 @@
func SetupOutDir(ctx Context, config Config) {
ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "Android.mk"))
ensureEmptyFileExists(ctx, filepath.Join(config.OutDir(), "CleanSpec.mk"))
+ ensureEmptyDirectoriesExist(ctx, config.TempDir())
// Potentially write a marker file for whether kati is enabled. This is used by soong_build to
// potentially run the AndroidMk singleton and postinstall commands.
@@ -56,6 +59,31 @@
} else {
ctx.Fatalln("Missing BUILD_DATETIME_FILE")
}
+
+ // BUILD_NUMBER should be set to the source control value that
+ // represents the current state of the source code. E.g., a
+ // perforce changelist number or a git hash. Can be an arbitrary string
+ // (to allow for source control that uses something other than numbers),
+ // but must be a single word and a valid file name.
+ //
+ // If no BUILD_NUMBER is set, create a useful "I am an engineering build
+ // from this date/time" value. Make it start with a non-digit so that
+ // anyone trying to parse it as an integer will probably get "0".
+ buildNumber, ok := config.environ.Get("BUILD_NUMBER")
+ if ok {
+ writeValueIfChanged(ctx, config, config.OutDir(), "file_name_tag.txt", buildNumber)
+ } else {
+ var username string
+ if username, ok = config.environ.Get("BUILD_USERNAME"); !ok {
+ ctx.Fatalln("Missing BUILD_USERNAME")
+ }
+ buildNumber = fmt.Sprintf("eng.%.6s.%s", username, time.Now().Format("20060102.150405" /* YYYYMMDD.HHMMSS */))
+ writeValueIfChanged(ctx, config, config.OutDir(), "file_name_tag.txt", username)
+ }
+ // Write the build number to a file so it can be read back in
+ // without changing the command line every time. Avoids rebuilds
+ // when using ninja.
+ writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_number.txt", buildNumber)
}
var combinedBuildNinjaTemplate = template.Must(template.New("combined").Parse(`
@@ -107,22 +135,6 @@
RunBuildTests = 1 << iota
)
-// checkBazelMode fails the build if there are conflicting arguments for which bazel
-// build mode to use.
-func checkBazelMode(ctx Context, config Config) {
- count := 0
- if config.bazelProdMode {
- count++
- }
- if config.bazelStagingMode {
- count++
- }
- if count > 1 {
- ctx.Fatalln("Conflicting bazel mode.\n" +
- "Do not specify more than one of --bazel-mode and --bazel-mode-staging ")
- }
-}
-
// checkProblematicFiles fails the build if existing Android.mk or CleanSpec.mk files are found at the root of the tree.
func checkProblematicFiles(ctx Context) {
files := []string{"Android.mk", "CleanSpec.mk"}
@@ -234,8 +246,6 @@
defer waitForDist(ctx)
- checkBazelMode(ctx, config)
-
// checkProblematicFiles aborts the build if Android.mk or CleanSpec.mk are found at the root of the tree.
checkProblematicFiles(ctx)
@@ -246,8 +256,6 @@
// checkCaseSensitivity issues a warning if a case-insensitive file system is being used.
checkCaseSensitivity(ctx, config)
- ensureEmptyDirectoriesExist(ctx, config.TempDir())
-
SetupPath(ctx, config)
what := evaluateWhatToRun(config, ctx.Verboseln)
@@ -257,11 +265,16 @@
}
rbeCh := make(chan bool)
+ var rbePanic any
if config.StartRBE() {
cleanupRBELogsDir(ctx, config)
+ checkRBERequirements(ctx, config)
go func() {
+ defer func() {
+ rbePanic = recover()
+ close(rbeCh)
+ }()
startRBE(ctx, config)
- close(rbeCh)
}()
defer DumpRBEMetrics(ctx, config, filepath.Join(config.LogsDir(), "rbe_metrics.pb"))
} else {
@@ -319,6 +332,11 @@
}
<-rbeCh
+ if rbePanic != nil {
+ // If there was a ctx.Fatal in startRBE, rethrow it.
+ panic(rbePanic)
+ }
+
if what&RunNinja != 0 {
if what&RunKati != 0 {
installCleanIfNecessary(ctx, config)
diff --git a/ui/build/config.go b/ui/build/config.go
index 084d28d..e29d239 100644
--- a/ui/build/config.go
+++ b/ui/build/config.go
@@ -22,6 +22,7 @@
"math/rand"
"os"
"os/exec"
+ "os/user"
"path/filepath"
"runtime"
"strconv"
@@ -30,6 +31,7 @@
"time"
"android/soong/shared"
+ "android/soong/ui/metrics"
"google.golang.org/protobuf/proto"
@@ -70,7 +72,6 @@
checkbuild bool
dist bool
jsonModuleGraph bool
- bp2build bool
queryview bool
reportMkMetrics bool // Collect and report mk2bp migration progress metrics.
soongDocs bool
@@ -84,10 +85,8 @@
searchApiDir bool // Scan the Android.bp files generated in out/api_surfaces
skipMetricsUpload bool
buildStartedTime int64 // For metrics-upload-only - manually specify a build-started time
- buildFromTextStub bool
- ensureAllowlistIntegrity bool // For CI builds - make sure modules are mixed-built
- bazelExitCode int32 // For b runs - necessary for updating NonZeroExit
- besId string // For b runs, to identify the BuildEventService logs
+ buildFromSourceStub bool
+ ensureAllowlistIntegrity bool // For CI builds - make sure modules are mixed-built
// From the product config
katiArgs []string
@@ -106,21 +105,21 @@
pathReplaced bool
- bazelProdMode bool
- bazelStagingMode bool
-
// Set by multiproduct_kati
emptyNinjaFile bool
metricsUploader string
- bazelForceEnabledModules string
-
includeTags []string
sourceRootDirs []string
// Data source to write ninja weight list
ninjaWeightListSource NinjaWeightListSource
+
+ // This file is a detailed dump of all soong-defined modules for debugging purposes.
+ // There's quite a bit of overlap with module-info.json and soong module graph. We
+ // could consider merging them.
+ moduleDebugFile string
}
type NinjaWeightListSource uint
@@ -204,34 +203,6 @@
return nil
}
-func defaultBazelProdMode(cfg *configImpl) bool {
- // Environment flag to disable Bazel for users which experience
- // broken bazel-handled builds, or significant performance regressions.
- if cfg.IsBazelMixedBuildForceDisabled() {
- return false
- }
- // Darwin-host builds are currently untested with Bazel.
- if runtime.GOOS == "darwin" {
- return false
- }
- return true
-}
-
-func UploadOnlyConfig(ctx Context, args ...string) Config {
- ret := &configImpl{
- environ: OsEnvironment(),
- sandboxConfig: &SandboxConfig{},
- }
- ret.parseArgs(ctx, args)
- srcDir := absPath(ctx, ".")
- bc := os.Getenv("ANDROID_BUILD_ENVIRONMENT_CONFIG")
- if err := loadEnvConfig(ctx, ret, bc); err != nil {
- ctx.Fatalln("Failed to parse env config files: %v", err)
- }
- ret.metricsUploader = GetMetricsUploader(srcDir, ret.environ)
- return Config{ret}
-}
-
func NewConfig(ctx Context, args ...string) Config {
ret := &configImpl{
environ: OsEnvironment(),
@@ -239,6 +210,11 @@
ninjaWeightListSource: DEFAULT,
}
+ // Skip soong tests by default on Linux
+ if runtime.GOOS == "linux" {
+ ret.skipSoongTests = true
+ }
+
// Default matching ninja
ret.parallel = runtime.NumCPU() + 2
ret.keepGoing = 1
@@ -302,6 +278,10 @@
ret.sandboxConfig.SetSrcDirIsRO(srcDirIsWritable == "false")
}
+ if os.Getenv("GENERATE_SOONG_DEBUG") == "true" {
+ ret.moduleDebugFile, _ = filepath.Abs(shared.JoinPath(ret.SoongOutDir(), "soong-debug-info.json"))
+ }
+
ret.environ.Unset(
// We're already using it
"USE_SOONG_UI",
@@ -354,6 +334,9 @@
"ANDROID_DEV_SCRIPTS",
"ANDROID_EMULATOR_PREBUILTS",
"ANDROID_PRE_BUILD_PATHS",
+
+ // We read it here already, don't let others share in the fun
+ "GENERATE_SOONG_DEBUG",
)
if ret.UseGoma() || ret.ForceUseGoma() {
@@ -404,13 +387,15 @@
// Configure Java-related variables, including adding it to $PATH
java8Home := filepath.Join("prebuilts/jdk/jdk8", ret.HostPrebuiltTag())
- java9Home := filepath.Join("prebuilts/jdk/jdk9", ret.HostPrebuiltTag())
- java11Home := filepath.Join("prebuilts/jdk/jdk11", ret.HostPrebuiltTag())
java17Home := filepath.Join("prebuilts/jdk/jdk17", ret.HostPrebuiltTag())
+ java21Home := filepath.Join("prebuilts/jdk/jdk21", ret.HostPrebuiltTag())
javaHome := func() string {
if override, ok := ret.environ.Get("OVERRIDE_ANDROID_JAVA_HOME"); ok {
return override
}
+ if ret.environ.IsEnvTrue("EXPERIMENTAL_USE_OPENJDK21_TOOLCHAIN") {
+ return java21Home
+ }
if toolchain11, ok := ret.environ.Get("EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN"); ok && toolchain11 != "true" {
ctx.Fatalln("The environment variable EXPERIMENTAL_USE_OPENJDK11_TOOLCHAIN is no longer supported. An OpenJDK 11 toolchain is now the global default.")
}
@@ -432,8 +417,6 @@
ret.environ.Set("JAVA_HOME", absJavaHome)
ret.environ.Set("ANDROID_JAVA_HOME", javaHome)
ret.environ.Set("ANDROID_JAVA8_HOME", java8Home)
- ret.environ.Set("ANDROID_JAVA9_HOME", java9Home)
- ret.environ.Set("ANDROID_JAVA11_HOME", java11Home)
ret.environ.Set("PATH", strings.Join(newPath, string(filepath.ListSeparator)))
// b/286885495, https://bugzilla.redhat.com/show_bug.cgi?id=2227130: some versions of Fedora include patches
@@ -455,22 +438,22 @@
ret.environ.Set("BUILD_DATETIME_FILE", buildDateTimeFile)
+ if _, ok := ret.environ.Get("BUILD_USERNAME"); !ok {
+ username := "unknown"
+ if u, err := user.Current(); err == nil {
+ username = u.Username
+ } else {
+ ctx.Println("Failed to get current user:", err)
+ }
+ ret.environ.Set("BUILD_USERNAME", username)
+ }
+
if ret.UseRBE() {
for k, v := range getRBEVars(ctx, Config{ret}) {
ret.environ.Set(k, v)
}
}
- if ret.BuildFromTextStub() {
- // TODO(b/271443071): support hidden api check for from-text stub build
- ret.environ.Set("UNSAFE_DISABLE_HIDDENAPI_FLAGS", "true")
- }
-
- bpd := ret.BazelMetricsDir()
- if err := os.RemoveAll(bpd); err != nil {
- ctx.Fatalf("Unable to remove bazel profile directory %q: %v", bpd, err)
- }
-
c := Config{ret}
storeConfigMetrics(ctx, c)
return c
@@ -482,6 +465,42 @@
return NewConfig(ctx, getConfigArgs(action, dir, ctx, args)...)
}
+// Prepare for getting make variables. For them to be accurate, we need to have
+// obtained PRODUCT_RELEASE_CONFIG_MAPS.
+//
+// Returns:
+//
+// Whether config should be called again.
+//
+// TODO: when converting product config to a declarative language, make sure
+// that PRODUCT_RELEASE_CONFIG_MAPS is properly handled as a separate step in
+// that process.
+func SetProductReleaseConfigMaps(ctx Context, config Config) bool {
+ ctx.BeginTrace(metrics.RunKati, "SetProductReleaseConfigMaps")
+ defer ctx.EndTrace()
+
+ if config.SkipConfig() {
+ // This duplicates the logic from Build to skip product config
+ // if the user has explicitly said to.
+ return false
+ }
+
+ releaseConfigVars := []string{
+ "PRODUCT_RELEASE_CONFIG_MAPS",
+ }
+
+ origValue, _ := config.environ.Get("PRODUCT_RELEASE_CONFIG_MAPS")
+ // Get the PRODUCT_RELEASE_CONFIG_MAPS for this product, to avoid polluting the environment
+ // when we run product config to get the rest of the make vars.
+ releaseMapVars, err := dumpMakeVars(ctx, config, nil, releaseConfigVars, false, "")
+ if err != nil {
+ ctx.Fatalln("Error getting PRODUCT_RELEASE_CONFIG_MAPS:", err)
+ }
+ productReleaseConfigMaps := releaseMapVars["PRODUCT_RELEASE_CONFIG_MAPS"]
+ os.Setenv("PRODUCT_RELEASE_CONFIG_MAPS", productReleaseConfigMaps)
+ return origValue != productReleaseConfigMaps
+}
+
// storeConfigMetrics selects a set of configuration information and store in
// the metrics system for further analysis.
func storeConfigMetrics(ctx Context, config Config) {
@@ -515,12 +534,10 @@
func buildConfig(config Config) *smpb.BuildConfig {
c := &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(config.ForceUseGoma()),
- UseGoma: proto.Bool(config.UseGoma()),
- UseRbe: proto.Bool(config.UseRBE()),
- BazelMixedBuild: proto.Bool(config.BazelBuildEnabled()),
- ForceDisableBazelMixedBuild: proto.Bool(config.IsBazelMixedBuildForceDisabled()),
- NinjaWeightListSource: getNinjaWeightListSourceInMetric(config.NinjaWeightListSource()),
+ ForceUseGoma: proto.Bool(config.ForceUseGoma()),
+ UseGoma: proto.Bool(config.UseGoma()),
+ UseRbe: proto.Bool(config.UseRBE()),
+ NinjaWeightListSource: getNinjaWeightListSourceInMetric(config.NinjaWeightListSource()),
}
c.Targets = append(c.Targets, config.arguments...)
@@ -766,16 +783,14 @@
c.skipConfig = true
} else if arg == "--skip-soong-tests" {
c.skipSoongTests = true
+ } else if arg == "--no-skip-soong-tests" {
+ c.skipSoongTests = false
} else if arg == "--skip-metrics-upload" {
c.skipMetricsUpload = true
} else if arg == "--mk-metrics" {
c.reportMkMetrics = true
} else if arg == "--multitree-build" {
c.multitreeBuild = true
- } else if arg == "--bazel-mode" {
- c.bazelProdMode = true
- } else if arg == "--bazel-mode-staging" {
- c.bazelStagingMode = true
} else if arg == "--search-api-dir" {
c.searchApiDir = true
} else if strings.HasPrefix(arg, "--ninja_weight_source=") {
@@ -802,16 +817,14 @@
} else {
ctx.Fatalf("unknown option for ninja_weight_source: %s", source)
}
- } else if arg == "--build-from-text-stub" {
- c.buildFromTextStub = true
+ } else if arg == "--build-from-source-stub" {
+ c.buildFromSourceStub = true
} else if strings.HasPrefix(arg, "--build-command=") {
buildCmd := strings.TrimPrefix(arg, "--build-command=")
// remove quotations
buildCmd = strings.TrimPrefix(buildCmd, "\"")
buildCmd = strings.TrimSuffix(buildCmd, "\"")
ctx.Metrics.SetBuildCommand([]string{buildCmd})
- } else if strings.HasPrefix(arg, "--bazel-force-enabled-modules=") {
- c.bazelForceEnabledModules = strings.TrimPrefix(arg, "--bazel-force-enabled-modules=")
} else if strings.HasPrefix(arg, "--build-started-time-unix-millis=") {
buildTimeStr := strings.TrimPrefix(arg, "--build-started-time-unix-millis=")
val, err := strconv.ParseInt(buildTimeStr, 10, 64)
@@ -822,16 +835,6 @@
}
} else if arg == "--ensure-allowlist-integrity" {
c.ensureAllowlistIntegrity = true
- } else if strings.HasPrefix(arg, "--bazel-exit-code=") {
- bazelExitCodeStr := strings.TrimPrefix(arg, "--bazel-exit-code=")
- val, err := strconv.Atoi(bazelExitCodeStr)
- if err == nil {
- c.bazelExitCode = int32(val)
- } else {
- ctx.Fatalf("Error parsing bazel-exit-code", err)
- }
- } else if strings.HasPrefix(arg, "--bes-id=") {
- c.besId = strings.TrimPrefix(arg, "--bes-id=")
} else if len(arg) > 0 && arg[0] == '-' {
parseArgNum := func(def int) int {
if len(arg) > 2 {
@@ -866,8 +869,6 @@
c.dist = true
} else if arg == "json-module-graph" {
c.jsonModuleGraph = true
- } else if arg == "bp2build" {
- c.bp2build = true
} else if arg == "queryview" {
c.queryview = true
} else if arg == "soong_docs" {
@@ -879,9 +880,6 @@
c.arguments = append(c.arguments, arg)
}
}
- if (!c.bazelProdMode) && (!c.bazelStagingMode) {
- c.bazelProdMode = defaultBazelProdMode(c)
- }
}
func validateNinjaWeightList(weightListFilePath string) (err error) {
@@ -967,13 +965,12 @@
return true
}
- if !c.JsonModuleGraph() && !c.Bp2Build() && !c.Queryview() && !c.SoongDocs() {
+ if !c.JsonModuleGraph() && !c.Queryview() && !c.SoongDocs() {
// Command line was empty, the default Ninja target is built
return true
}
- // bp2build + dist may be used to dist bp2build logs but does not require SoongBuildInvocation
- if c.Dist() && !c.Bp2Build() {
+ if c.Dist() {
return true
}
@@ -1003,14 +1000,6 @@
return c.ninjaArgs
}
-func (c *configImpl) BazelOutDir() string {
- return filepath.Join(c.OutDir(), "bazel")
-}
-
-func (c *configImpl) bazelOutputBase() string {
- return filepath.Join(c.BazelOutDir(), "output")
-}
-
func (c *configImpl) SoongOutDir() string {
return filepath.Join(c.OutDir(), "soong")
}
@@ -1049,14 +1038,6 @@
return shared.JoinPath(c.SoongOutDir(), usedEnvFile+"."+tag)
}
-func (c *configImpl) Bp2BuildFilesMarkerFile() string {
- return shared.JoinPath(c.SoongOutDir(), "bp2build_files_marker")
-}
-
-func (c *configImpl) Bp2BuildWorkspaceMarkerFile() string {
- return shared.JoinPath(c.SoongOutDir(), "bp2build_workspace_marker")
-}
-
func (c *configImpl) SoongDocsHtml() string {
return shared.JoinPath(c.SoongOutDir(), "docs/soong_build.html")
}
@@ -1102,10 +1083,6 @@
return c.jsonModuleGraph
}
-func (c *configImpl) Bp2Build() bool {
- return c.bp2build
-}
-
func (c *configImpl) Queryview() bool {
return c.queryview
}
@@ -1151,7 +1128,7 @@
}
func (c *configImpl) BuildFromTextStub() bool {
- return c.buildFromTextStub
+ return !c.buildFromSourceStub
}
func (c *configImpl) TargetProduct() string {
@@ -1297,7 +1274,7 @@
func (c *configImpl) UseRBE() bool {
// These alternate modes of running Soong do not use RBE / reclient.
- if c.Bp2Build() || c.Queryview() || c.JsonModuleGraph() {
+ if c.Queryview() || c.JsonModuleGraph() {
return false
}
@@ -1314,10 +1291,6 @@
return false
}
-func (c *configImpl) BazelBuildEnabled() bool {
- return c.bazelProdMode || c.bazelStagingMode
-}
-
func (c *configImpl) StartRBE() bool {
if !c.UseRBE() {
return false
@@ -1338,6 +1311,19 @@
return v
}
}
+ return c.rbeTmpDir()
+}
+
+func (c *configImpl) rbeDownloadTmpDir() string {
+ for _, f := range []string{"RBE_download_tmp_dir", "FLAG_download_tmp_dir"} {
+ if v, ok := c.environ.Get(f); ok {
+ return v
+ }
+ }
+ return c.rbeTmpDir()
+}
+
+func (c *configImpl) rbeTmpDir() string {
buildTmpDir := shared.TempDirForOutDir(c.SoongOutDir())
return filepath.Join(buildTmpDir, "rbe")
}
@@ -1544,6 +1530,10 @@
return filepath.Join(c.SoongOutDir(), "make_vars-"+c.TargetProduct()+".mk")
}
+func (c *configImpl) SoongBuildMetrics() string {
+ return filepath.Join(c.LogsDir(), "soong_build_metrics.pb")
+}
+
func (c *configImpl) ProductOut() string {
return filepath.Join(c.OutDir(), "target", "product", c.TargetDevice())
}
@@ -1653,12 +1643,6 @@
return absDir
}
-// BazelMetricsDir returns the <logs dir>/bazel_metrics directory
-// where the bazel profiles are located.
-func (c *configImpl) BazelMetricsDir() string {
- return filepath.Join(c.LogsDir(), "bazel_metrics")
-}
-
// MkFileMetrics returns the file path for make-related metrics.
func (c *configImpl) MkMetrics() string {
return filepath.Join(c.LogsDir(), "mk_metrics.pb")
@@ -1672,28 +1656,6 @@
return c.emptyNinjaFile
}
-func (c *configImpl) IsBazelMixedBuildForceDisabled() bool {
- return c.Environment().IsEnvTrue("BUILD_BROKEN_DISABLE_BAZEL")
-}
-
-func (c *configImpl) IsPersistentBazelEnabled() bool {
- return c.Environment().IsEnvTrue("USE_PERSISTENT_BAZEL")
-}
-
-// GetBazeliskBazelVersion returns the Bazel version to use for this build,
-// or the empty string if the current canonical prod Bazel should be used.
-// This environment variable should only be set to debug the build system.
-// The Bazel version, if set, will be passed to Bazelisk, and Bazelisk will
-// handle downloading and invoking the correct Bazel binary.
-func (c *configImpl) GetBazeliskBazelVersion() string {
- value, _ := c.Environment().Get("USE_BAZEL_VERSION")
- return value
-}
-
-func (c *configImpl) BazelModulesForceEnabledByFlag() string {
- return c.bazelForceEnabledModules
-}
-
func (c *configImpl) SkipMetricsUpload() bool {
return c.skipMetricsUpload
}
@@ -1711,10 +1673,6 @@
return time.UnixMilli(c.buildStartedTime)
}
-func (c *configImpl) BazelExitCode() int32 {
- return c.bazelExitCode
-}
-
func GetMetricsUploader(topDir string, env *Environment) string {
if p, ok := env.Get("METRICS_UPLOADER"); ok {
metricsUploader := filepath.Join(topDir, p)
diff --git a/ui/build/config_test.go b/ui/build/config_test.go
index 545f727..5182b12 100644
--- a/ui/build/config_test.go
+++ b/ui/build/config_test.go
@@ -1017,157 +1017,57 @@
name string
environ Environment
arguments []string
- useBazel bool
- bazelProdMode bool
- bazelStagingMode bool
expectedBuildConfig *smpb.BuildConfig
}{
{
name: "none set",
environ: Environment{},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
- ForceDisableBazelMixedBuild: proto.Bool(false),
- NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
{
name: "force use goma",
environ: Environment{"FORCE_USE_GOMA=1"},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(true),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
- ForceDisableBazelMixedBuild: proto.Bool(false),
- NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
+ ForceUseGoma: proto.Bool(true),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(false),
+ NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
{
name: "use goma",
environ: Environment{"USE_GOMA=1"},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(true),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
- ForceDisableBazelMixedBuild: proto.Bool(false),
- NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(true),
+ UseRbe: proto.Bool(false),
+ NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
{
name: "use rbe",
environ: Environment{"USE_RBE=1"},
expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(true),
- BazelMixedBuild: proto.Bool(false),
- ForceDisableBazelMixedBuild: proto.Bool(false),
- NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
- },
- },
- {
- name: "disable mixed builds",
- environ: Environment{"BUILD_BROKEN_DISABLE_BAZEL=1"},
- expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
- ForceDisableBazelMixedBuild: proto.Bool(true),
- NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
- },
- },
- {
- name: "use bazel as ninja",
- environ: Environment{},
- useBazel: true,
- expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
- ForceDisableBazelMixedBuild: proto.Bool(false),
- NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
- },
- },
- {
- name: "bazel mixed build from prod mode",
- environ: Environment{},
- bazelProdMode: true,
- expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(true),
- ForceDisableBazelMixedBuild: proto.Bool(false),
- NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
- },
- },
- {
- name: "bazel mixed build from staging mode",
- environ: Environment{},
- bazelStagingMode: true,
- expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(true),
- ForceDisableBazelMixedBuild: proto.Bool(false),
- NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
- },
- },
- {
- name: "specified targets",
- environ: Environment{},
- useBazel: true,
- arguments: []string{"droid", "dist"},
- expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(false),
- UseGoma: proto.Bool(false),
- UseRbe: proto.Bool(false),
- BazelMixedBuild: proto.Bool(false),
- Targets: []string{"droid", "dist"},
- ForceDisableBazelMixedBuild: proto.Bool(false),
- NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
- },
- },
- {
- name: "all set",
- environ: Environment{
- "FORCE_USE_GOMA=1",
- "USE_GOMA=1",
- "USE_RBE=1",
- "BUILD_BROKEN_DISABLE_BAZEL=1",
- },
- useBazel: true,
- bazelProdMode: true,
- expectedBuildConfig: &smpb.BuildConfig{
- ForceUseGoma: proto.Bool(true),
- UseGoma: proto.Bool(true),
- UseRbe: proto.Bool(true),
- BazelMixedBuild: proto.Bool(true),
- ForceDisableBazelMixedBuild: proto.Bool(true),
- NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
+ ForceUseGoma: proto.Bool(false),
+ UseGoma: proto.Bool(false),
+ UseRbe: proto.Bool(true),
+ NinjaWeightListSource: smpb.BuildConfig_NOT_USED.Enum(),
},
},
}
- ctx := testContext()
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
c := &configImpl{
- environ: &tc.environ,
- bazelProdMode: tc.bazelProdMode,
- bazelStagingMode: tc.bazelStagingMode,
- arguments: tc.arguments,
+ environ: &tc.environ,
+ arguments: tc.arguments,
}
config := Config{c}
- checkBazelMode(ctx, config)
actualBuildConfig := buildConfig(config)
if expected := tc.expectedBuildConfig; !proto.Equal(expected, actualBuildConfig) {
t.Errorf("Build config mismatch.\n"+
diff --git a/ui/build/dumpvars.go b/ui/build/dumpvars.go
index efe7478..d364542 100644
--- a/ui/build/dumpvars.go
+++ b/ui/build/dumpvars.go
@@ -191,6 +191,9 @@
"TARGET_BUILD_APPS",
"TARGET_BUILD_UNBUNDLED",
+ // Additional release config maps
+ "PRODUCT_RELEASE_CONFIG_MAPS",
+
// compiler wrappers set up by make
"CC_WRAPPER",
"CXX_WRAPPER",
diff --git a/ui/build/finder.go b/ui/build/finder.go
index 62079fe..a114079 100644
--- a/ui/build/finder.go
+++ b/ui/build/finder.go
@@ -74,10 +74,6 @@
"AndroidProducts.mk",
// General Soong build definitions, using the Blueprint syntax.
"Android.bp",
- // Bazel build definitions.
- "BUILD.bazel",
- // Bazel build definitions.
- "BUILD",
// Kati clean definitions.
"CleanSpec.mk",
// Ownership definition.
@@ -85,13 +81,11 @@
// Test configuration for modules in directories that contain this
// file.
"TEST_MAPPING",
- // Bazel top-level file to mark a directory as a Bazel workspace.
- "WORKSPACE",
// METADATA file of packages
"METADATA",
},
- // Bazel Starlark configuration files and all .mk files for product/board configuration.
- IncludeSuffixes: []string{".bzl", ".mk"},
+ // .mk files for product/board configuration.
+ IncludeSuffixes: []string{".mk"},
}
dumpDir := config.FileListDir()
f, err = finder.New(cacheParams, filesystem, logger.New(ioutil.Discard),
@@ -111,17 +105,6 @@
return dirs
}
-// Finds the list of Bazel-related files (BUILD, WORKSPACE and Starlark) in the tree.
-func findBazelFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) {
- matches := []string{}
- for _, foundName := range entries.FileNames {
- if foundName == "BUILD.bazel" || foundName == "BUILD" || foundName == "WORKSPACE" || strings.HasSuffix(foundName, ".bzl") {
- matches = append(matches, foundName)
- }
- }
- return entries.DirNames, matches
-}
-
func findProductAndBoardConfigFiles(entries finder.DirEntries) (dirNames []string, fileNames []string) {
matches := []string{}
for _, foundName := range entries.FileNames {
@@ -145,6 +128,7 @@
// Stop searching a subdirectory recursively after finding an Android.mk.
androidMks := f.FindFirstNamedAt(".", "Android.mk")
+ androidMks = blockAndroidMks(androidMks)
err := dumpListToFile(ctx, config, androidMks, filepath.Join(dumpDir, "Android.mk.list"))
if err != nil {
ctx.Fatalf("Could not export module list: %v", err)
@@ -177,13 +161,6 @@
ctx.Fatalf("Could not export product list: %v", err)
}
- // Recursively look for all Bazel related files.
- bazelFiles := f.FindMatching(".", findBazelFiles)
- err = dumpListToFile(ctx, config, bazelFiles, filepath.Join(dumpDir, "bazel.list"))
- if err != nil {
- ctx.Fatalf("Could not export bazel BUILD list: %v", err)
- }
-
// Recursively look for all OWNERS files.
owners := f.FindNamedAt(".", "OWNERS")
err = dumpListToFile(ctx, config, owners, filepath.Join(dumpDir, "OWNERS.list"))
diff --git a/ui/build/kati.go b/ui/build/kati.go
index aea56d3..d599c99 100644
--- a/ui/build/kati.go
+++ b/ui/build/kati.go
@@ -15,6 +15,8 @@
package build
import (
+ "android/soong/ui/metrics"
+ "android/soong/ui/status"
"crypto/md5"
"fmt"
"io/ioutil"
@@ -22,10 +24,6 @@
"os/user"
"path/filepath"
"strings"
- "time"
-
- "android/soong/ui/metrics"
- "android/soong/ui/status"
)
var spaceSlashReplacer = strings.NewReplacer("/", "_", " ", "_")
@@ -102,8 +100,6 @@
"--no_ninja_prelude",
// Support declaring phony outputs in AOSP Ninja.
"--use_ninja_phony_output",
- // Support declaring symlink outputs in AOSP Ninja.
- "--use_ninja_symlink_outputs",
// Regenerate the Ninja file if environment inputs have changed. e.g.
// CLI flags, .mk file timestamps, env vars, $(wildcard ..) and some
// $(shell ..) results.
@@ -198,32 +194,14 @@
}
}
writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_hostname.txt", hostname)
-
- // BUILD_NUMBER should be set to the source control value that
- // represents the current state of the source code. E.g., a
- // perforce changelist number or a git hash. Can be an arbitrary string
- // (to allow for source control that uses something other than numbers),
- // but must be a single word and a valid file name.
- //
- // If no BUILD_NUMBER is set, create a useful "I am an engineering build
- // from this date/time" value. Make it start with a non-digit so that
- // anyone trying to parse it as an integer will probably get "0".
- cmd.Environment.Unset("HAS_BUILD_NUMBER")
- buildNumber, ok := cmd.Environment.Get("BUILD_NUMBER")
+ _, ok = cmd.Environment.Get("BUILD_NUMBER")
// Unset BUILD_NUMBER during kati run to avoid kati rerun, kati will use BUILD_NUMBER from a file.
cmd.Environment.Unset("BUILD_NUMBER")
if ok {
cmd.Environment.Set("HAS_BUILD_NUMBER", "true")
- writeValueIfChanged(ctx, config, config.OutDir(), "file_name_tag.txt", buildNumber)
} else {
- buildNumber = fmt.Sprintf("eng.%.6s.%s", username, time.Now().Format("20060102.150405" /* YYYYMMDD.HHMMSS */))
cmd.Environment.Set("HAS_BUILD_NUMBER", "false")
- writeValueIfChanged(ctx, config, config.OutDir(), "file_name_tag.txt", username)
}
- // Write the build number to a file so it can be read back in
- // without changing the command line every time. Avoids rebuilds
- // when using ninja.
- writeValueIfChanged(ctx, config, config.SoongOutDir(), "build_number.txt", buildNumber)
// Apply the caller's function closure to mutate the environment variables.
envFunc(cmd.Environment)
diff --git a/ui/build/ninja.go b/ui/build/ninja.go
index b69e938..551b8ab 100644
--- a/ui/build/ninja.go
+++ b/ui/build/ninja.go
@@ -271,11 +271,13 @@
// The Ninja file hasn't been modified since the last time it was
// checked, so Ninja could be stuck. Output some diagnostics.
ctx.Verbosef("ninja may be stuck; last update to %v was %v. dumping process tree...", c.logPath, newModTime)
+ ctx.Printf("ninja may be stuck, check %v for list of running processes.",
+ filepath.Join(config.LogsDir(), config.logsPrefix+"soong.log"))
// The "pstree" command doesn't exist on Mac, but "pstree" on Linux
// gives more convenient output than "ps" So, we try pstree first, and
// ps second
- commandText := fmt.Sprintf("pstree -pal %v || ps -ef", os.Getpid())
+ commandText := fmt.Sprintf("pstree -palT %v || ps -ef", os.Getpid())
cmd := Command(ctx, config, "dump process tree", "bash", "-c", commandText)
output := cmd.CombinedOutputOrFatal()
diff --git a/ui/build/path.go b/ui/build/path.go
index 29128d8..51ebff1 100644
--- a/ui/build/path.go
+++ b/ui/build/path.go
@@ -180,7 +180,7 @@
// Compute the error message along with the process tree, including
// parents, for this log line.
procPrints := []string{
- "See https://android.googlesource.com/platform/build/+/master/Changes.md#PATH_Tools for more information.",
+ "See https://android.googlesource.com/platform/build/+/main/Changes.md#PATH_Tools for more information.",
}
if len(log.Parents) > 0 {
procPrints = append(procPrints, "Process tree:")
diff --git a/ui/build/paths/config.go b/ui/build/paths/config.go
index eba823a..2f25a8c 100644
--- a/ui/build/paths/config.go
+++ b/ui/build/paths/config.go
@@ -92,6 +92,8 @@
"expr": Allowed,
"fuser": Allowed,
"gcert": Allowed,
+ "gcertstatus": Allowed,
+ "gcloud": Allowed,
"getopt": Allowed,
"git": Allowed,
"hexdump": Allowed,
@@ -100,7 +102,6 @@
"javap": Allowed,
"lsof": Allowed,
"openssl": Allowed,
- "prodcertstatus": Allowed,
"pstree": Allowed,
"rsync": Allowed,
"sh": Allowed,
diff --git a/ui/build/rbe.go b/ui/build/rbe.go
index 3b9d301..fa04207 100644
--- a/ui/build/rbe.go
+++ b/ui/build/rbe.go
@@ -55,13 +55,14 @@
func getRBEVars(ctx Context, config Config) map[string]string {
vars := map[string]string{
- "RBE_log_dir": config.rbeProxyLogsDir(),
- "RBE_re_proxy": config.rbeReproxy(),
- "RBE_exec_root": config.rbeExecRoot(),
- "RBE_output_dir": config.rbeProxyLogsDir(),
- "RBE_proxy_log_dir": config.rbeProxyLogsDir(),
- "RBE_cache_dir": config.rbeCacheDir(),
- "RBE_platform": "container-image=" + remoteexec.DefaultImage,
+ "RBE_log_dir": config.rbeProxyLogsDir(),
+ "RBE_re_proxy": config.rbeReproxy(),
+ "RBE_exec_root": config.rbeExecRoot(),
+ "RBE_output_dir": config.rbeProxyLogsDir(),
+ "RBE_proxy_log_dir": config.rbeProxyLogsDir(),
+ "RBE_cache_dir": config.rbeCacheDir(),
+ "RBE_download_tmp_dir": config.rbeDownloadTmpDir(),
+ "RBE_platform": "container-image=" + remoteexec.DefaultImage,
}
if config.StartRBE() {
name, err := config.rbeSockAddr(absPath(ctx, config.TempDir()))
@@ -94,14 +95,10 @@
}
}
-func startRBE(ctx Context, config Config) {
+func checkRBERequirements(ctx Context, config Config) {
if !config.GoogleProdCredsExist() && prodCredsAuthType(config) {
ctx.Fatalf("Unable to start RBE reproxy\nFAILED: Missing LOAS credentials.")
}
- ctx.BeginTrace(metrics.RunSetupTool, "rbe_bootstrap")
- defer ctx.EndTrace()
-
- ctx.Status.Status("Starting rbe...")
if u := ulimitOrFatal(ctx, config, "-u"); u < rbeLeastNProcs {
ctx.Fatalf("max user processes is insufficient: %d; want >= %d.\n", u, rbeLeastNProcs)
@@ -114,6 +111,13 @@
ctx.Fatalf("Unable to create logs dir (%v) for RBE: %v", config.rbeProxyLogsDir, err)
}
}
+}
+
+func startRBE(ctx Context, config Config) {
+ ctx.BeginTrace(metrics.RunSetupTool, "rbe_bootstrap")
+ defer ctx.EndTrace()
+
+ ctx.Status.Status("Starting rbe...")
cmd := Command(ctx, config, "startRBE bootstrap", rbeCommand(ctx, config, bootstrapCmd))
diff --git a/ui/build/soong.go b/ui/build/soong.go
index 44c20a0..a201ac5 100644
--- a/ui/build/soong.go
+++ b/ui/build/soong.go
@@ -15,14 +15,20 @@
package build
import (
+ "android/soong/ui/tracer"
"fmt"
+ "io/fs"
"os"
"path/filepath"
"strconv"
"strings"
+ "sync"
+ "sync/atomic"
+ "time"
"android/soong/bazel"
"android/soong/ui/metrics"
+ "android/soong/ui/metrics/metrics_proto"
"android/soong/ui/status"
"android/soong/shared"
@@ -30,18 +36,19 @@
"github.com/google/blueprint"
"github.com/google/blueprint/bootstrap"
"github.com/google/blueprint/microfactory"
+ "github.com/google/blueprint/pathtools"
+
+ "google.golang.org/protobuf/proto"
)
const (
availableEnvFile = "soong.environment.available"
usedEnvFile = "soong.environment.used"
- soongBuildTag = "build"
- bp2buildFilesTag = "bp2build_files"
- bp2buildWorkspaceTag = "bp2build_workspace"
- jsonModuleGraphTag = "modulegraph"
- queryviewTag = "queryview"
- soongDocsTag = "soong_docs"
+ soongBuildTag = "build"
+ jsonModuleGraphTag = "modulegraph"
+ queryviewTag = "queryview"
+ soongDocsTag = "soong_docs"
// bootstrapEpoch is used to determine if an incremental build is incompatible with the current
// version of bootstrap and needs cleaning before continuing the build. Increment this for
@@ -50,6 +57,13 @@
bootstrapEpoch = 1
)
+var (
+ // Used during parallel update of symlinks in out directory to reflect new
+ // TOP dir.
+ symlinkWg sync.WaitGroup
+ numFound, numUpdated uint32
+)
+
func writeEnvironmentFile(_ Context, envFile string, envDeps map[string]string) error {
data, err := shared.EnvFileContents(envDeps)
if err != nil {
@@ -168,7 +182,15 @@
return globPathName
}
-func (pb PrimaryBuilderFactory) primaryBuilderInvocation() bootstrap.PrimaryBuilderInvocation {
+func getGlobPathNameFromPrimaryBuilderFactory(config Config, pb PrimaryBuilderFactory) string {
+ if pb.name == soongBuildTag {
+ // Glob path for soong build would be separated per product target
+ return getGlobPathName(config)
+ }
+ return pb.name
+}
+
+func (pb PrimaryBuilderFactory) primaryBuilderInvocation(config Config) bootstrap.PrimaryBuilderInvocation {
commonArgs := make([]string, 0, 0)
if !pb.config.skipSoongTests {
@@ -178,8 +200,13 @@
if pb.config.multitreeBuild {
commonArgs = append(commonArgs, "--multitree-build")
}
- if pb.config.buildFromTextStub {
- commonArgs = append(commonArgs, "--build-from-text-stub")
+ if pb.config.buildFromSourceStub {
+ commonArgs = append(commonArgs, "--build-from-source-stub")
+ }
+
+ if pb.config.moduleDebugFile != "" {
+ commonArgs = append(commonArgs, "--soong_module_debug")
+ commonArgs = append(commonArgs, pb.config.moduleDebugFile)
}
commonArgs = append(commonArgs, "-l", filepath.Join(pb.config.FileListDir(), "Android.bp.list"))
@@ -202,11 +229,7 @@
var allArgs []string
allArgs = append(allArgs, pb.specificArgs...)
- globPathName := pb.name
- // Glob path for soong build would be separated per product target
- if pb.name == soongBuildTag {
- globPathName = getGlobPathName(pb.config)
- }
+ globPathName := getGlobPathNameFromPrimaryBuilderFactory(config, pb)
allArgs = append(allArgs,
"--globListDir", globPathName,
"--globFile", pb.config.NamedGlobFile(globPathName))
@@ -221,8 +244,11 @@
}
allArgs = append(allArgs, "Android.bp")
+ globfiles := bootstrap.GlobFileListFiles(bootstrap.GlobDirectory(config.SoongOutDir(), globPathName))
+
return bootstrap.PrimaryBuilderInvocation{
Inputs: []string{"Android.bp"},
+ Implicits: globfiles,
Outputs: []string{pb.output},
Args: allArgs,
Description: pb.description,
@@ -260,7 +286,6 @@
func bootstrapGlobFileList(config Config) []string {
return []string{
config.NamedGlobFile(getGlobPathName(config)),
- config.NamedGlobFile(bp2buildFilesTag),
config.NamedGlobFile(jsonModuleGraphTag),
config.NamedGlobFile(queryviewTag),
config.NamedGlobFile(soongDocsTag),
@@ -280,23 +305,11 @@
if config.EmptyNinjaFile() {
mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--empty-ninja-file")
}
- if config.bazelProdMode {
- mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--bazel-mode")
- }
- if config.bazelStagingMode {
- mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--bazel-mode-staging")
- }
- if config.IsPersistentBazelEnabled() {
- mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--use-bazel-proxy")
- }
- if len(config.bazelForceEnabledModules) > 0 {
- mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--bazel-force-enabled-modules="+config.bazelForceEnabledModules)
- }
if config.MultitreeBuild() {
mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--multitree-build")
}
- if config.buildFromTextStub {
- mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--build-from-text-stub")
+ if config.buildFromSourceStub {
+ mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--build-from-source-stub")
}
if config.ensureAllowlistIntegrity {
mainSoongBuildExtraArgs = append(mainSoongBuildExtraArgs, "--ensure-allowlist-integrity")
@@ -313,24 +326,6 @@
specificArgs: mainSoongBuildExtraArgs,
},
{
- name: bp2buildFilesTag,
- description: fmt.Sprintf("converting Android.bp files to BUILD files at %s/bp2build", config.SoongOutDir()),
- config: config,
- output: config.Bp2BuildFilesMarkerFile(),
- specificArgs: append(baseArgs,
- "--bp2build_marker", config.Bp2BuildFilesMarkerFile(),
- ),
- },
- {
- name: bp2buildWorkspaceTag,
- description: "Creating Bazel symlink forest",
- config: config,
- output: config.Bp2BuildWorkspaceMarkerFile(),
- specificArgs: append(baseArgs,
- "--symlink_forest_marker", config.Bp2BuildWorkspaceMarkerFile(),
- ),
- },
- {
name: jsonModuleGraphTag,
description: fmt.Sprintf("generating the Soong module graph at %s", config.ModuleGraphFile()),
config: config,
@@ -394,33 +389,10 @@
if debuggedInvocations[pbf.name] {
pbf.debugPort = delvePort
}
- pbi := pbf.primaryBuilderInvocation()
- // Some invocations require adjustment:
- switch pbf.name {
- case soongBuildTag:
- if config.BazelBuildEnabled() {
- // Mixed builds call Bazel from soong_build and they therefore need the
- // Bazel workspace to be available. Make that so by adding a dependency on
- // the bp2build marker file to the action that invokes soong_build .
- pbi.OrderOnlyInputs = append(pbi.OrderOnlyInputs, config.Bp2BuildWorkspaceMarkerFile())
- }
- case bp2buildWorkspaceTag:
- pbi.Inputs = append(pbi.Inputs,
- config.Bp2BuildFilesMarkerFile(),
- filepath.Join(config.FileListDir(), "bazel.list"))
- case bp2buildFilesTag:
- pbi.Inputs = append(pbi.Inputs, filepath.Join(config.FileListDir(), "METADATA.list"))
- }
+ pbi := pbf.primaryBuilderInvocation(config)
invocations = append(invocations, pbi)
}
- // The glob .ninja files are subninja'd. However, they are generated during
- // the build itself so we write an empty file if the file does not exist yet
- // so that the subninja doesn't fail on clean builds
- for _, globFile := range bootstrapGlobFileList(config) {
- writeEmptyFile(ctx, globFile)
- }
-
blueprintArgs := bootstrap.Args{
ModuleListFile: filepath.Join(config.FileListDir(), "Android.bp.list"),
OutFile: shared.JoinPath(config.SoongOutDir(), "bootstrap.ninja"),
@@ -442,6 +414,28 @@
primaryBuilderInvocations: invocations,
}
+ // The glob ninja files are generated during the main build phase. However, the
+ // primary buildifer invocation depends on all of its glob files, even before
+ // it's been run. Generate a "empty" glob ninja file on the first run,
+ // so that the files can be there to satisfy the dependency.
+ for _, pb := range pbfs {
+ globPathName := getGlobPathNameFromPrimaryBuilderFactory(config, pb)
+ globNinjaFile := config.NamedGlobFile(globPathName)
+ if _, err := os.Stat(globNinjaFile); os.IsNotExist(err) {
+ err := bootstrap.WriteBuildGlobsNinjaFile(&bootstrap.GlobSingleton{
+ GlobLister: func() pathtools.MultipleGlobResults { return nil },
+ GlobFile: globNinjaFile,
+ GlobDir: bootstrap.GlobDirectory(config.SoongOutDir(), globPathName),
+ SrcDir: ".",
+ }, blueprintConfig)
+ if err != nil {
+ ctx.Fatal(err)
+ }
+ } else if err != nil {
+ ctx.Fatal(err)
+ }
+ }
+
// since `bootstrap.ninja` is regenerated unconditionally, we ignore the deps, i.e. little
// reason to write a `bootstrap.ninja.d` file
_, err := bootstrap.RunBlueprint(blueprintArgs, bootstrap.DoEverything, blueprintCtx, blueprintConfig)
@@ -465,10 +459,118 @@
}
}
+func updateSymlinks(ctx Context, dir, prevCWD, cwd string) error {
+ defer symlinkWg.Done()
+
+ visit := func(path string, d fs.DirEntry, err error) error {
+ if d.IsDir() && path != dir {
+ symlinkWg.Add(1)
+ go updateSymlinks(ctx, path, prevCWD, cwd)
+ return filepath.SkipDir
+ }
+ f, err := d.Info()
+ if err != nil {
+ return err
+ }
+ // If the file is not a symlink, we don't have to update it.
+ if f.Mode()&os.ModeSymlink != os.ModeSymlink {
+ return nil
+ }
+
+ atomic.AddUint32(&numFound, 1)
+ target, err := os.Readlink(path)
+ if err != nil {
+ return err
+ }
+ if strings.HasPrefix(target, prevCWD) &&
+ (len(target) == len(prevCWD) || target[len(prevCWD)] == '/') {
+ target = filepath.Join(cwd, target[len(prevCWD):])
+ if err := os.Remove(path); err != nil {
+ return err
+ }
+ if err := os.Symlink(target, path); err != nil {
+ return err
+ }
+ atomic.AddUint32(&numUpdated, 1)
+ }
+ return nil
+ }
+
+ if err := filepath.WalkDir(dir, visit); err != nil {
+ return err
+ }
+ return nil
+}
+
+func fixOutDirSymlinks(ctx Context, config Config, outDir string) error {
+ cwd, err := os.Getwd()
+ if err != nil {
+ return err
+ }
+
+ // Record the .top as the very last thing in the function.
+ tf := filepath.Join(outDir, ".top")
+ defer func() {
+ if err := os.WriteFile(tf, []byte(cwd), 0644); err != nil {
+ fmt.Fprintf(os.Stderr, fmt.Sprintf("Unable to log CWD: %v", err))
+ }
+ }()
+
+ // Find the previous working directory if it was recorded.
+ var prevCWD string
+ pcwd, err := os.ReadFile(tf)
+ if err != nil {
+ if os.IsNotExist(err) {
+ // No previous working directory recorded, nothing to do.
+ return nil
+ }
+ return err
+ }
+ prevCWD = strings.Trim(string(pcwd), "\n")
+
+ if prevCWD == cwd {
+ // We are in the same source dir, nothing to update.
+ return nil
+ }
+
+ symlinkWg.Add(1)
+ if err := updateSymlinks(ctx, outDir, prevCWD, cwd); err != nil {
+ return err
+ }
+ symlinkWg.Wait()
+ ctx.Println(fmt.Sprintf("Updated %d/%d symlinks in dir %v", numUpdated, numFound, outDir))
+ return nil
+}
+
+func migrateOutputSymlinks(ctx Context, config Config) error {
+ // Figure out the real out directory ("out" could be a symlink).
+ outDir := config.OutDir()
+ s, err := os.Lstat(outDir)
+ if err != nil {
+ if os.IsNotExist(err) {
+ // No out dir exists, no symlinks to migrate.
+ return nil
+ }
+ return err
+ }
+ if s.Mode()&os.ModeSymlink == os.ModeSymlink {
+ target, err := filepath.EvalSymlinks(outDir)
+ if err != nil {
+ return err
+ }
+ outDir = target
+ }
+ return fixOutDirSymlinks(ctx, config, outDir)
+}
+
func runSoong(ctx Context, config Config) {
ctx.BeginTrace(metrics.RunSoong, "soong")
defer ctx.EndTrace()
+ if err := migrateOutputSymlinks(ctx, config); err != nil {
+ ctx.Fatalf("failed to migrate output directory to current TOP dir: %v", err)
+ }
+
// We have two environment files: .available is the one with every variable,
// .used with the ones that were actually used. The latter is used to
// determine whether Soong needs to be re-run since why re-run it if only
@@ -480,16 +582,7 @@
soongBuildEnv := config.Environment().Copy()
soongBuildEnv.Set("TOP", os.Getenv("TOP"))
- // For Bazel mixed builds.
- soongBuildEnv.Set("BAZEL_PATH", "./build/bazel/bin/bazel")
- // Bazel's HOME var is set to an output subdirectory which doesn't exist. This
- // prevents Bazel from file I/O in the actual user HOME directory.
- soongBuildEnv.Set("BAZEL_HOME", absPath(ctx, filepath.Join(config.BazelOutDir(), "bazelhome")))
- soongBuildEnv.Set("BAZEL_OUTPUT_BASE", config.bazelOutputBase())
- soongBuildEnv.Set("BAZEL_WORKSPACE", absPath(ctx, "."))
- soongBuildEnv.Set("BAZEL_METRICS_DIR", config.BazelMetricsDir())
soongBuildEnv.Set("LOG_DIR", config.LogsDir())
- soongBuildEnv.Set("BAZEL_DEPS_FILE", absPath(ctx, filepath.Join(config.BazelOutDir(), "bazel.list")))
// For Soong bootstrapping tests
if os.Getenv("ALLOW_MISSING_DEPENDENCIES") == "true" {
@@ -507,9 +600,9 @@
checkEnvironmentFile(ctx, soongBuildEnv, config.UsedEnvFile(soongBuildTag))
- if config.BazelBuildEnabled() || config.Bp2Build() {
- checkEnvironmentFile(ctx, soongBuildEnv, config.UsedEnvFile(bp2buildFilesTag))
- }
+ // Remove bazel files in the event that bazel is disabled for the build.
+ // These files may have been left over from a previous bazel-enabled build.
+ cleanBazelFiles(config)
if config.JsonModuleGraph() {
checkEnvironmentFile(ctx, soongBuildEnv, config.UsedEnvFile(jsonModuleGraphTag))
@@ -531,14 +624,6 @@
ctx.BeginTrace(metrics.RunSoong, "bootstrap")
defer ctx.EndTrace()
- if config.IsPersistentBazelEnabled() {
- bazelProxy := bazel.NewProxyServer(ctx.Logger, config.OutDir(), filepath.Join(config.SoongOutDir(), "workspace"), config.GetBazeliskBazelVersion())
- if err := bazelProxy.Start(); err != nil {
- ctx.Fatalf("Failed to create bazel proxy")
- }
- defer bazelProxy.Close()
- }
-
fifo := filepath.Join(config.OutDir(), ".ninja_fifo")
nr := status.NewNinjaReader(ctx, ctx.Status.StartTool(), fifo)
defer nr.Close()
@@ -582,10 +667,6 @@
targets = append(targets, config.ModuleGraphFile())
}
- if config.Bp2Build() {
- targets = append(targets, config.Bp2BuildWorkspaceMarkerFile())
- }
-
if config.Queryview() {
targets = append(targets, config.QueryviewMarkerFile())
}
@@ -599,8 +680,12 @@
targets = append(targets, config.SoongNinjaFile())
}
+ beforeSoongTimestamp := time.Now()
+
ninja(targets...)
+ loadSoongBuildMetrics(ctx, config, beforeSoongTimestamp)
+
distGzipFile(ctx, config, config.SoongNinjaFile(), "soong")
distFile(ctx, config, config.SoongVarsFile(), "soong")
@@ -614,6 +699,67 @@
}
}
+// loadSoongBuildMetrics reads out/soong_build_metrics.pb if it was generated by soong_build and copies the
+// events stored in it into the soong_ui trace to provide introspection into how long the different phases of
+// soong_build are taking.
+func loadSoongBuildMetrics(ctx Context, config Config, oldTimestamp time.Time) {
+ soongBuildMetricsFile := config.SoongBuildMetrics()
+ if metricsStat, err := os.Stat(soongBuildMetricsFile); err != nil {
+ ctx.Verbosef("Failed to stat %s: %s", soongBuildMetricsFile, err)
+ return
+ } else if !metricsStat.ModTime().After(oldTimestamp) {
+ ctx.Verbosef("%s timestamp not later after running soong, expected %s > %s",
+ soongBuildMetricsFile, metricsStat.ModTime(), oldTimestamp)
+ return
+ }
+
+ metricsData, err := os.ReadFile(soongBuildMetricsFile)
+ if err != nil {
+ ctx.Verbosef("Failed to read %s: %s", soongBuildMetricsFile, err)
+ return
+ }
+
+ soongBuildMetrics := metrics_proto.SoongBuildMetrics{}
+ err = proto.Unmarshal(metricsData, &soongBuildMetrics)
+ if err != nil {
+ ctx.Verbosef("Failed to unmarshal %s: %s", soongBuildMetricsFile, err)
+ return
+ }
+ for _, event := range soongBuildMetrics.Events {
+ desc := event.GetDescription()
+ if dot := strings.LastIndexByte(desc, '.'); dot >= 0 {
+ desc = desc[dot+1:]
+ }
+ ctx.Tracer.Complete(desc, ctx.Thread,
+ event.GetStartTime(), event.GetStartTime()+event.GetRealTime())
+ }
+ for _, event := range soongBuildMetrics.PerfCounters {
+ timestamp := event.GetTime()
+ for _, group := range event.Groups {
+ counters := make([]tracer.Counter, 0, len(group.Counters))
+ for _, counter := range group.Counters {
+ counters = append(counters, tracer.Counter{
+ Name: counter.GetName(),
+ Value: counter.GetValue(),
+ })
+ }
+ ctx.Tracer.CountersAtTime(group.GetName(), ctx.Thread, timestamp, counters)
+ }
+ }
+}
+
+func cleanBazelFiles(config Config) {
+ files := []string{
+ shared.JoinPath(config.SoongOutDir(), "bp2build"),
+ shared.JoinPath(config.SoongOutDir(), "workspace"),
+ shared.JoinPath(config.SoongOutDir(), bazel.SoongInjectionDirName),
+ shared.JoinPath(config.OutDir(), "bazel")}
+
+ for _, f := range files {
+ os.RemoveAll(f)
+ }
+}
+
func runMicrofactory(ctx Context, config Config, name string, pkg string, mapping map[string]string) {
ctx.BeginTrace(metrics.RunSoong, name)
defer ctx.EndTrace()
diff --git a/ui/build/test_build.go b/ui/build/test_build.go
index 2efc732..3095139 100644
--- a/ui/build/test_build.go
+++ b/ui/build/test_build.go
@@ -15,47 +15,16 @@
package build
import (
+ "android/soong/ui/metrics"
+ "android/soong/ui/status"
"bufio"
"fmt"
"path/filepath"
- "regexp"
"runtime"
"sort"
"strings"
- "sync"
-
- "android/soong/ui/metrics"
- "android/soong/ui/status"
)
-var (
- // bazel output paths are in __main__/bazel-out/<config-specific-path>/bin
- bazelOutputPathRegexOnce sync.Once
- bazelOutputPathRegexp *regexp.Regexp
-)
-
-func bazelOutputPathPattern(config Config) *regexp.Regexp {
- bazelOutputPathRegexOnce.Do(func() {
- // Bazel output files are in <Bazel output base>/execroot/__main__/bazel-out/<config>/bin
- bazelOutRoot := filepath.Join(regexp.QuoteMeta(config.bazelOutputBase()), "execroot", "__main__", "bazel-out")
- bazelOutputPathRegexp = regexp.MustCompile(bazelOutRoot + "/[^/]+/bin")
- })
- return bazelOutputPathRegexp
-}
-
-func ignoreBazelPath(config Config, path string) bool {
- bazelRoot := filepath.Join(config.bazelOutputBase(), "execroot")
- // Don't check bazel output regexp unless it is Bazel path
- if strings.HasPrefix(path, bazelRoot) {
- bazelOutputRegexp := bazelOutputPathPattern(config)
- // if the file is a bazel path that is _not_ a Bazel generated file output, we rely on Bazel to
- // ensure the paths to exist. If it _is_ a Bazel output path, we expect that it should be built
- // by Ninja.
- return !bazelOutputRegexp.MatchString(path)
- }
- return false
-}
-
// Checks for files in the out directory that have a rule that depends on them but no rule to
// create them. This catches a common set of build failures where a rule to generate a file is
// deleted (either by deleting a module in an Android.mk file, or by modifying the build system
@@ -94,6 +63,7 @@
outDir := config.OutDir()
modulePathsDir := filepath.Join(outDir, ".module_paths")
+ rawFilesDir := filepath.Join(outDir, "soong", "raw")
variablesFilePath := filepath.Join(outDir, "soong", "soong.variables")
// dexpreopt.config is an input to the soong_docs action, which runs the
@@ -119,6 +89,7 @@
continue
}
if strings.HasPrefix(line, modulePathsDir) ||
+ strings.HasPrefix(line, rawFilesDir) ||
line == variablesFilePath ||
line == dexpreoptConfigFilePath ||
line == buildDatetimeFilePath ||
@@ -128,9 +99,6 @@
continue
}
- if ignoreBazelPath(config, line) {
- continue
- }
danglingRules[line] = true
}
diff --git a/ui/build/upload_test.go b/ui/build/upload_test.go
deleted file mode 100644
index 1fcded9..0000000
--- a/ui/build/upload_test.go
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright 2020 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 build
-
-import (
- "errors"
- "io/ioutil"
- "os"
- "path/filepath"
- "reflect"
- "sort"
- "strconv"
- "strings"
- "testing"
- "time"
-
- "android/soong/ui/logger"
-)
-
-func writeBazelProfileFile(dir string) error {
- contents := `
-
-=== PHASE SUMMARY INFORMATION ===
-
-Total launch phase time 1.193 s 15.77%
-Total init phase time 1.092 s 14.44%
-Total target pattern evaluation phase time 0.580 s 7.67%
-Total interleaved loading-and-analysis phase time 3.646 s 48.21%
-Total preparation phase time 0.022 s 0.30%
-Total execution phase time 0.993 s 13.13%
-Total finish phase time 0.036 s 0.48%
----------------------------------------------------------------------
-Total run time 7.563 s 100.00%
-
-Critical path (178 ms):
- Time Percentage Description
- 178 ms 100.00% action 'BazelWorkspaceStatusAction stable-status.txt'
-
-`
- file := filepath.Join(dir, "bazel_metrics.txt")
- return os.WriteFile(file, []byte(contents), 0666)
-}
-
-func TestPruneMetricsFiles(t *testing.T) {
- rootDir := t.TempDir()
-
- dirs := []string{
- filepath.Join(rootDir, "d1"),
- filepath.Join(rootDir, "d1", "d2"),
- filepath.Join(rootDir, "d1", "d2", "d3"),
- }
-
- files := []string{
- filepath.Join(rootDir, "d1", "f1"),
- filepath.Join(rootDir, "d1", "d2", "f1"),
- filepath.Join(rootDir, "d1", "d2", "d3", "f1"),
- }
-
- for _, d := range dirs {
- if err := os.MkdirAll(d, 0777); err != nil {
- t.Fatalf("got %v, expecting nil error for making directory %q", err, d)
- }
- }
-
- for _, f := range files {
- if err := ioutil.WriteFile(f, []byte{}, 0777); err != nil {
- t.Fatalf("got %v, expecting nil error on writing file %q", err, f)
- }
- }
-
- want := []string{
- filepath.Join(rootDir, "d1", "f1"),
- filepath.Join(rootDir, "d1", "d2", "f1"),
- filepath.Join(rootDir, "d1", "d2", "d3", "f1"),
- }
-
- got := pruneMetricsFiles([]string{rootDir})
-
- sort.Strings(got)
- sort.Strings(want)
-
- if !reflect.DeepEqual(got, want) {
- t.Errorf("got %q, want %q after pruning metrics files", got, want)
- }
-}
-
-func TestUploadMetrics(t *testing.T) {
- ctx := testContext()
- tests := []struct {
- description string
- uploader string
- createFiles bool
- files []string
- }{{
- description: "no metrics uploader",
- }, {
- description: "non-existent metrics files no upload",
- uploader: "echo",
- files: []string{"metrics_file_1", "metrics_file_2", "metrics_file_3, bazel_metrics.pb"},
- }, {
- description: "trigger upload",
- uploader: "echo",
- createFiles: true,
- files: []string{"metrics_file_1", "metrics_file_2, bazel_metrics.pb"},
- }}
-
- for _, tt := range tests {
- t.Run(tt.description, func(t *testing.T) {
- defer logger.Recover(func(err error) {
- t.Fatalf("got unexpected error: %v", err)
- })
-
- outDir, err := ioutil.TempDir("", "")
- if err != nil {
- t.Fatalf("failed to create out directory: %v", outDir)
- }
- defer os.RemoveAll(outDir)
-
- // Supply our own tmpDir to delete the temp dir once the test is done.
- orgTmpDir := tmpDir
- tmpDir = func(string, string) (string, error) {
- retDir := filepath.Join(outDir, "tmp_upload_dir")
- if err := os.Mkdir(retDir, 0755); err != nil {
- t.Fatalf("failed to create temporary directory %q: %v", retDir, err)
- }
- return retDir, nil
- }
- defer func() { tmpDir = orgTmpDir }()
-
- metricsUploadDir := filepath.Join(outDir, ".metrics_uploader")
- if err := os.Mkdir(metricsUploadDir, 0755); err != nil {
- t.Fatalf("failed to create %q directory for oauth valid check: %v", metricsUploadDir, err)
- }
-
- var metricsFiles []string
- if tt.createFiles {
- for _, f := range tt.files {
- filename := filepath.Join(outDir, f)
- metricsFiles = append(metricsFiles, filename)
- if err := ioutil.WriteFile(filename, []byte("test file"), 0644); err != nil {
- t.Fatalf("failed to create a fake metrics file %q for uploading: %v", filename, err)
- }
- }
- }
- if err := writeBazelProfileFile(outDir); err != nil {
- t.Fatalf("failed to create bazel profile file in dir: %v", outDir)
- }
-
- config := Config{&configImpl{
- environ: &Environment{
- "OUT_DIR=" + outDir,
- },
- buildDateTime: strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10),
- metricsUploader: tt.uploader,
- }}
-
- UploadMetrics(ctx, config, false, time.Now(), metricsFiles...)
- })
- }
-}
-
-func TestUploadMetricsErrors(t *testing.T) {
- ctx := testContext()
- tests := []struct {
- description string
- tmpDir string
- tmpDirErr error
- expectedErr string
- }{{
- description: "getTmpDir returned error",
- tmpDirErr: errors.New("getTmpDir failed"),
- expectedErr: "getTmpDir failed",
- }, {
- description: "copyFile operation error",
- tmpDir: "/fake_dir",
- expectedErr: "failed to copy",
- }}
-
- for _, tt := range tests {
- t.Run(tt.description, func(t *testing.T) {
- defer logger.Recover(func(err error) {
- got := err.Error()
- if !strings.Contains(got, tt.expectedErr) {
- t.Errorf("got %q, want %q to be contained in error", got, tt.expectedErr)
- }
- })
-
- outDir, err := ioutil.TempDir("", "")
- if err != nil {
- t.Fatalf("failed to create out directory: %v", outDir)
- }
- defer os.RemoveAll(outDir)
-
- orgTmpDir := tmpDir
- tmpDir = func(string, string) (string, error) {
- return tt.tmpDir, tt.tmpDirErr
- }
- defer func() { tmpDir = orgTmpDir }()
-
- metricsFile := filepath.Join(outDir, "metrics_file_1")
- if err := ioutil.WriteFile(metricsFile, []byte("test file"), 0644); err != nil {
- t.Fatalf("failed to create a fake metrics file %q for uploading: %v", metricsFile, err)
- }
-
- config := Config{&configImpl{
- environ: &Environment{
- "OUT_DIR=/bad",
- },
- metricsUploader: "echo",
- }}
-
- UploadMetrics(ctx, config, true, time.Now(), metricsFile)
- t.Errorf("got nil, expecting %q as a failure", tt.expectedErr)
- })
- }
-}
-
-func TestParsePercentageToTenThousandths(t *testing.T) {
- // 2.59% should be returned as 259 - representing 259/10000 of the build
- percentage := parsePercentageToTenThousandths("2.59%")
- if percentage != 259 {
- t.Errorf("Expected percentage to be returned as ten-thousandths. Expected 259, have %d\n", percentage)
- }
-
- // Test without a leading digit
- percentage = parsePercentageToTenThousandths(".52%")
- if percentage != 52 {
- t.Errorf("Expected percentage to be returned as ten-thousandths. Expected 52, have %d\n", percentage)
- }
-}
-
-func TestParseTimingToNanos(t *testing.T) {
- // This parses from seconds (with millis precision) and returns nanos
- timingNanos := parseTimingToNanos("0.111")
- if timingNanos != 111000000 {
- t.Errorf("Error parsing timing. Expected 111000, have %d\n", timingNanos)
- }
-
- // Test without a leading digit
- timingNanos = parseTimingToNanos(".112")
- if timingNanos != 112000000 {
- t.Errorf("Error parsing timing. Expected 112000, have %d\n", timingNanos)
- }
-}
-
-func TestParsePhaseTiming(t *testing.T) {
- // Sample lines include:
- // Total launch phase time 0.011 s 2.59%
- // Total target pattern evaluation phase time 0.012 s 4.59%
-
- line1 := "Total launch phase time 0.011 s 2.59%"
- timing := parsePhaseTiming(line1)
-
- if timing.GetPhaseName() != "launch" {
- t.Errorf("Failed to parse phase name. Expected launch, have %s\n", timing.GetPhaseName())
- } else if timing.GetDurationNanos() != 11000000 {
- t.Errorf("Failed to parse duration nanos. Expected 11000000, have %d\n", timing.GetDurationNanos())
- } else if timing.GetPortionOfBuildTime() != 259 {
- t.Errorf("Failed to parse portion of build time. Expected 259, have %d\n", timing.GetPortionOfBuildTime())
- }
-
- // Test with a multiword phase name
- line2 := "Total target pattern evaluation phase time 0.012 s 4.59%"
-
- timing = parsePhaseTiming(line2)
- if timing.GetPhaseName() != "target pattern evaluation" {
- t.Errorf("Failed to parse phase name. Expected target pattern evaluation, have %s\n", timing.GetPhaseName())
- } else if timing.GetDurationNanos() != 12000000 {
- t.Errorf("Failed to parse duration nanos. Expected 12000000, have %d\n", timing.GetDurationNanos())
- } else if timing.GetPortionOfBuildTime() != 459 {
- t.Errorf("Failed to parse portion of build time. Expected 459, have %d\n", timing.GetPortionOfBuildTime())
- }
-}
-
-func TestParseTotal(t *testing.T) {
- // Total line is in the form of:
- // Total run time 7.563 s 100.00%
-
- line := "Total run time 7.563 s 100.00%"
-
- total := parseTotal(line)
-
- // Only the seconds field is parsed, as nanos
- if total != 7563000000 {
- t.Errorf("Failed to parse total build time. Expected 7563000000, have %d\n", total)
- }
-}
diff --git a/ui/metrics/metrics.go b/ui/metrics/metrics.go
index d68ced8..4a275a8 100644
--- a/ui/metrics/metrics.go
+++ b/ui/metrics/metrics.go
@@ -32,7 +32,6 @@
// of what an event is and how the metrics system is a stack based system.
import (
- "fmt"
"os"
"runtime"
"strings"
@@ -228,20 +227,6 @@
m.metrics.BuildDateTimestamp = proto.Int64(buildTimestamp.UnixNano() / int64(time.Second))
}
-func (m *Metrics) UpdateTotalRealTimeAndNonZeroExit(data []byte, bazelExitCode int32) error {
- if err := proto.Unmarshal(data, &m.metrics); err != nil {
- return fmt.Errorf("Failed to unmarshal proto: %w", err)
- }
- startTime := *m.metrics.Total.StartTime
- endTime := uint64(time.Now().UnixNano())
-
- *m.metrics.Total.RealTime = *proto.Uint64(endTime - startTime)
-
- bazelError := bazelExitCode != 0
- m.metrics.NonZeroExit = proto.Bool(bazelError)
- return nil
-}
-
// SetBuildCommand adds the build command specified by the user to the
// list of collected metrics.
func (m *Metrics) SetBuildCommand(cmd []string) {
diff --git a/ui/metrics/metrics_proto/metrics.pb.go b/ui/metrics/metrics_proto/metrics.pb.go
index f3e677a..b75f572 100644
--- a/ui/metrics/metrics_proto/metrics.pb.go
+++ b/ui/metrics/metrics_proto/metrics.pb.go
@@ -279,7 +279,7 @@
// Deprecated: Use ModuleTypeInfo_BuildSystem.Descriptor instead.
func (ModuleTypeInfo_BuildSystem) EnumDescriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{5, 0}
+ return file_metrics_proto_rawDescGZIP(), []int{8, 0}
}
type ExpConfigFetcher_ConfigStatus int32
@@ -341,7 +341,7 @@
// Deprecated: Use ExpConfigFetcher_ConfigStatus.Descriptor instead.
func (ExpConfigFetcher_ConfigStatus) EnumDescriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{9, 0}
+ return file_metrics_proto_rawDescGZIP(), []int{12, 0}
}
type MetricsBase struct {
@@ -999,6 +999,177 @@
return ""
}
+type PerfCounters struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The timestamp of these counters in nanoseconds.
+ Time *uint64 `protobuf:"varint,1,opt,name=time" json:"time,omitempty"`
+ // A list of counter names and values.
+ Groups []*PerfCounterGroup `protobuf:"bytes,2,rep,name=groups" json:"groups,omitempty"`
+}
+
+func (x *PerfCounters) Reset() {
+ *x = PerfCounters{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_metrics_proto_msgTypes[4]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PerfCounters) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PerfCounters) ProtoMessage() {}
+
+func (x *PerfCounters) ProtoReflect() protoreflect.Message {
+ mi := &file_metrics_proto_msgTypes[4]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PerfCounters.ProtoReflect.Descriptor instead.
+func (*PerfCounters) Descriptor() ([]byte, []int) {
+ return file_metrics_proto_rawDescGZIP(), []int{4}
+}
+
+func (x *PerfCounters) GetTime() uint64 {
+ if x != nil && x.Time != nil {
+ return *x.Time
+ }
+ return 0
+}
+
+func (x *PerfCounters) GetGroups() []*PerfCounterGroup {
+ if x != nil {
+ return x.Groups
+ }
+ return nil
+}
+
+type PerfCounterGroup struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The name of this counter group (e.g. "cpu" or "memory")
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ // The counters in this group
+ Counters []*PerfCounter `protobuf:"bytes,2,rep,name=counters" json:"counters,omitempty"`
+}
+
+func (x *PerfCounterGroup) Reset() {
+ *x = PerfCounterGroup{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_metrics_proto_msgTypes[5]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PerfCounterGroup) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PerfCounterGroup) ProtoMessage() {}
+
+func (x *PerfCounterGroup) ProtoReflect() protoreflect.Message {
+ mi := &file_metrics_proto_msgTypes[5]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PerfCounterGroup.ProtoReflect.Descriptor instead.
+func (*PerfCounterGroup) Descriptor() ([]byte, []int) {
+ return file_metrics_proto_rawDescGZIP(), []int{5}
+}
+
+func (x *PerfCounterGroup) GetName() string {
+ if x != nil && x.Name != nil {
+ return *x.Name
+ }
+ return ""
+}
+
+func (x *PerfCounterGroup) GetCounters() []*PerfCounter {
+ if x != nil {
+ return x.Counters
+ }
+ return nil
+}
+
+type PerfCounter struct {
+ state protoimpl.MessageState
+ sizeCache protoimpl.SizeCache
+ unknownFields protoimpl.UnknownFields
+
+ // The name of this counter.
+ Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
+ // The value of this counter.
+ Value *int64 `protobuf:"varint,2,opt,name=value" json:"value,omitempty"`
+}
+
+func (x *PerfCounter) Reset() {
+ *x = PerfCounter{}
+ if protoimpl.UnsafeEnabled {
+ mi := &file_metrics_proto_msgTypes[6]
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ ms.StoreMessageInfo(mi)
+ }
+}
+
+func (x *PerfCounter) String() string {
+ return protoimpl.X.MessageStringOf(x)
+}
+
+func (*PerfCounter) ProtoMessage() {}
+
+func (x *PerfCounter) ProtoReflect() protoreflect.Message {
+ mi := &file_metrics_proto_msgTypes[6]
+ if protoimpl.UnsafeEnabled && x != nil {
+ ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+ if ms.LoadMessageInfo() == nil {
+ ms.StoreMessageInfo(mi)
+ }
+ return ms
+ }
+ return mi.MessageOf(x)
+}
+
+// Deprecated: Use PerfCounter.ProtoReflect.Descriptor instead.
+func (*PerfCounter) Descriptor() ([]byte, []int) {
+ return file_metrics_proto_rawDescGZIP(), []int{6}
+}
+
+func (x *PerfCounter) GetName() string {
+ if x != nil && x.Name != nil {
+ return *x.Name
+ }
+ return ""
+}
+
+func (x *PerfCounter) GetValue() int64 {
+ if x != nil && x.Value != nil {
+ return *x.Value
+ }
+ return 0
+}
+
type ProcessResourceInfo struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1029,7 +1200,7 @@
func (x *ProcessResourceInfo) Reset() {
*x = ProcessResourceInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[4]
+ mi := &file_metrics_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1042,7 +1213,7 @@
func (*ProcessResourceInfo) ProtoMessage() {}
func (x *ProcessResourceInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[4]
+ mi := &file_metrics_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1055,7 +1226,7 @@
// Deprecated: Use ProcessResourceInfo.ProtoReflect.Descriptor instead.
func (*ProcessResourceInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{4}
+ return file_metrics_proto_rawDescGZIP(), []int{7}
}
func (x *ProcessResourceInfo) GetName() string {
@@ -1149,7 +1320,7 @@
func (x *ModuleTypeInfo) Reset() {
*x = ModuleTypeInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[5]
+ mi := &file_metrics_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1162,7 +1333,7 @@
func (*ModuleTypeInfo) ProtoMessage() {}
func (x *ModuleTypeInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[5]
+ mi := &file_metrics_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1175,7 +1346,7 @@
// Deprecated: Use ModuleTypeInfo.ProtoReflect.Descriptor instead.
func (*ModuleTypeInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{5}
+ return file_metrics_proto_rawDescGZIP(), []int{8}
}
func (x *ModuleTypeInfo) GetBuildSystem() ModuleTypeInfo_BuildSystem {
@@ -1213,7 +1384,7 @@
func (x *CriticalUserJourneyMetrics) Reset() {
*x = CriticalUserJourneyMetrics{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[6]
+ mi := &file_metrics_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1226,7 +1397,7 @@
func (*CriticalUserJourneyMetrics) ProtoMessage() {}
func (x *CriticalUserJourneyMetrics) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[6]
+ mi := &file_metrics_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1239,7 +1410,7 @@
// Deprecated: Use CriticalUserJourneyMetrics.ProtoReflect.Descriptor instead.
func (*CriticalUserJourneyMetrics) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{6}
+ return file_metrics_proto_rawDescGZIP(), []int{9}
}
func (x *CriticalUserJourneyMetrics) GetName() string {
@@ -1268,7 +1439,7 @@
func (x *CriticalUserJourneysMetrics) Reset() {
*x = CriticalUserJourneysMetrics{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[7]
+ mi := &file_metrics_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1281,7 +1452,7 @@
func (*CriticalUserJourneysMetrics) ProtoMessage() {}
func (x *CriticalUserJourneysMetrics) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[7]
+ mi := &file_metrics_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1294,7 +1465,7 @@
// Deprecated: Use CriticalUserJourneysMetrics.ProtoReflect.Descriptor instead.
func (*CriticalUserJourneysMetrics) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{7}
+ return file_metrics_proto_rawDescGZIP(), []int{10}
}
func (x *CriticalUserJourneysMetrics) GetCujs() []*CriticalUserJourneyMetrics {
@@ -1323,12 +1494,14 @@
Events []*PerfInfo `protobuf:"bytes,6,rep,name=events" json:"events,omitempty"`
// Mixed Builds information
MixedBuildsInfo *MixedBuildsInfo `protobuf:"bytes,7,opt,name=mixed_builds_info,json=mixedBuildsInfo" json:"mixed_builds_info,omitempty"`
+ // Performance during for soong_build execution.
+ PerfCounters []*PerfCounters `protobuf:"bytes,8,rep,name=perf_counters,json=perfCounters" json:"perf_counters,omitempty"`
}
func (x *SoongBuildMetrics) Reset() {
*x = SoongBuildMetrics{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[8]
+ mi := &file_metrics_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1341,7 +1514,7 @@
func (*SoongBuildMetrics) ProtoMessage() {}
func (x *SoongBuildMetrics) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[8]
+ mi := &file_metrics_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1354,7 +1527,7 @@
// Deprecated: Use SoongBuildMetrics.ProtoReflect.Descriptor instead.
func (*SoongBuildMetrics) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{8}
+ return file_metrics_proto_rawDescGZIP(), []int{11}
}
func (x *SoongBuildMetrics) GetModules() uint32 {
@@ -1406,6 +1579,13 @@
return nil
}
+func (x *SoongBuildMetrics) GetPerfCounters() []*PerfCounters {
+ if x != nil {
+ return x.PerfCounters
+ }
+ return nil
+}
+
type ExpConfigFetcher struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -1425,7 +1605,7 @@
func (x *ExpConfigFetcher) Reset() {
*x = ExpConfigFetcher{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[9]
+ mi := &file_metrics_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1438,7 +1618,7 @@
func (*ExpConfigFetcher) ProtoMessage() {}
func (x *ExpConfigFetcher) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[9]
+ mi := &file_metrics_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1451,7 +1631,7 @@
// Deprecated: Use ExpConfigFetcher.ProtoReflect.Descriptor instead.
func (*ExpConfigFetcher) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{9}
+ return file_metrics_proto_rawDescGZIP(), []int{12}
}
func (x *ExpConfigFetcher) GetStatus() ExpConfigFetcher_ConfigStatus {
@@ -1489,7 +1669,7 @@
func (x *MixedBuildsInfo) Reset() {
*x = MixedBuildsInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[10]
+ mi := &file_metrics_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1502,7 +1682,7 @@
func (*MixedBuildsInfo) ProtoMessage() {}
func (x *MixedBuildsInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[10]
+ mi := &file_metrics_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1515,7 +1695,7 @@
// Deprecated: Use MixedBuildsInfo.ProtoReflect.Descriptor instead.
func (*MixedBuildsInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{10}
+ return file_metrics_proto_rawDescGZIP(), []int{13}
}
func (x *MixedBuildsInfo) GetMixedBuildEnabledModules() []string {
@@ -1552,7 +1732,7 @@
func (x *CriticalPathInfo) Reset() {
*x = CriticalPathInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[11]
+ mi := &file_metrics_proto_msgTypes[14]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1565,7 +1745,7 @@
func (*CriticalPathInfo) ProtoMessage() {}
func (x *CriticalPathInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[11]
+ mi := &file_metrics_proto_msgTypes[14]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1578,7 +1758,7 @@
// Deprecated: Use CriticalPathInfo.ProtoReflect.Descriptor instead.
func (*CriticalPathInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{11}
+ return file_metrics_proto_rawDescGZIP(), []int{14}
}
func (x *CriticalPathInfo) GetElapsedTimeMicros() uint64 {
@@ -1623,7 +1803,7 @@
func (x *JobInfo) Reset() {
*x = JobInfo{}
if protoimpl.UnsafeEnabled {
- mi := &file_metrics_proto_msgTypes[12]
+ mi := &file_metrics_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -1636,7 +1816,7 @@
func (*JobInfo) ProtoMessage() {}
func (x *JobInfo) ProtoReflect() protoreflect.Message {
- mi := &file_metrics_proto_msgTypes[12]
+ mi := &file_metrics_proto_msgTypes[15]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -1649,7 +1829,7 @@
// Deprecated: Use JobInfo.ProtoReflect.Descriptor instead.
func (*JobInfo) Descriptor() ([]byte, []int) {
- return file_metrics_proto_rawDescGZIP(), []int{12}
+ return file_metrics_proto_rawDescGZIP(), []int{15}
}
func (x *JobInfo) GetElapsedTimeMicros() uint64 {
@@ -1856,132 +2036,153 @@
0x6f, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f,
0x6e, 0x5a, 0x65, 0x72, 0x6f, 0x45, 0x78, 0x69, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72,
0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xb9,
- 0x03, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72,
- 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10, 0x75, 0x73,
- 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69,
- 0x63, 0x72, 0x6f, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74,
- 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04,
- 0x52, 0x10, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72,
- 0x6f, 0x73, 0x12, 0x1c, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b, 0x62,
- 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b, 0x62,
- 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66,
- 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e,
- 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11,
- 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74,
- 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50, 0x61,
- 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f, 0x69,
- 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x69,
- 0x6f, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f, 0x6f,
- 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a,
- 0x69, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76, 0x6f,
- 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f,
- 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18,
- 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
- 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76, 0x6f,
- 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f,
- 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a,
- 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65,
- 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, 0xe5, 0x01, 0x0a, 0x0e, 0x4d,
- 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x5b, 0x0a,
- 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c,
- 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
- 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79,
- 0x73, 0x74, 0x65, 0x6d, 0x3a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x0b, 0x62,
- 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b, 0x6d, 0x6f,
- 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x6e,
- 0x75, 0x6d, 0x5f, 0x6f, 0x66, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4f, 0x66, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
- 0x73, 0x22, 0x2f, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d,
- 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x09, 0x0a,
- 0x05, 0x53, 0x4f, 0x4f, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41, 0x4b, 0x45,
- 0x10, 0x02, 0x22, 0x6c, 0x0a, 0x1a, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73,
+ 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x61,
+ 0x0a, 0x0c, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x12, 0x12,
+ 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x74, 0x69,
+ 0x6d, 0x65, 0x12, 0x3d, 0x0a, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, 0x02, 0x20, 0x03,
+ 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64,
+ 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x52, 0x06, 0x67, 0x72, 0x6f, 0x75, 0x70,
+ 0x73, 0x22, 0x64, 0x0a, 0x10, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72,
+ 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
+ 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3c, 0x0a, 0x08, 0x63, 0x6f, 0x75,
+ 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f,
+ 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63,
+ 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x22, 0x37, 0x0a, 0x0b, 0x50, 0x65, 0x72, 0x66, 0x43,
+ 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61,
+ 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
+ 0x22, 0xb9, 0x03, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x6f,
+ 0x75, 0x72, 0x63, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
+ 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x28, 0x0a, 0x10,
+ 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73,
+ 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65,
+ 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
+ 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01,
+ 0x28, 0x04, 0x52, 0x10, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69,
+ 0x63, 0x72, 0x6f, 0x73, 0x12, 0x1c, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f,
+ 0x6b, 0x62, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73,
+ 0x4b, 0x62, 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65,
+ 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d,
+ 0x69, 0x6e, 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a,
+ 0x0a, 0x11, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75,
+ 0x6c, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72,
+ 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f,
+ 0x5f, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x09, 0x69, 0x6f, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f,
+ 0x5f, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x0a, 0x69, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a,
+ 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78,
+ 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x18, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65,
+ 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e,
+ 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78,
+ 0x74, 0x5f, 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04,
+ 0x52, 0x1a, 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e,
+ 0x74, 0x65, 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x22, 0xe5, 0x01, 0x0a,
+ 0x0e, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12,
+ 0x5b, 0x0a, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
+ 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x6f, 0x64, 0x75,
+ 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x42, 0x75, 0x69, 0x6c, 0x64,
+ 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x3a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52,
+ 0x0b, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x0a, 0x0b,
+ 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
+ 0x09, 0x52, 0x0a, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x24, 0x0a,
+ 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x6f, 0x66, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18,
+ 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x6e, 0x75, 0x6d, 0x4f, 0x66, 0x4d, 0x6f, 0x64, 0x75,
+ 0x6c, 0x65, 0x73, 0x22, 0x2f, 0x0a, 0x0b, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x79, 0x73, 0x74,
+ 0x65, 0x6d, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12,
+ 0x09, 0x0a, 0x05, 0x53, 0x4f, 0x4f, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4d, 0x41,
+ 0x4b, 0x45, 0x10, 0x02, 0x22, 0x6c, 0x0a, 0x1a, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x55, 0x73, 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f,
+ 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x42, 0x61, 0x73, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x22, 0x62, 0x0a, 0x1b, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73,
+ 0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63,
+ 0x73, 0x12, 0x43, 0x0a, 0x04, 0x63, 0x75, 0x6a, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
+ 0x2f, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65,
+ 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73,
0x65, 0x72, 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
- 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
- 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3a, 0x0a, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75,
- 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x42, 0x61, 0x73, 0x65, 0x52, 0x07, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
- 0x22, 0x62, 0x0a, 0x1b, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72,
- 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x73, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12,
- 0x43, 0x0a, 0x04, 0x63, 0x75, 0x6a, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e,
+ 0x52, 0x04, 0x63, 0x75, 0x6a, 0x73, 0x22, 0x94, 0x03, 0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67,
+ 0x42, 0x75, 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07,
+ 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d,
+ 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e,
+ 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e,
+ 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f,
+ 0x63, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74,
+ 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28,
+ 0x0a, 0x10, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69,
+ 0x7a, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41,
+ 0x6c, 0x6c, 0x6f, 0x63, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f,
+ 0x68, 0x65, 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52,
+ 0x0b, 0x6d, 0x61, 0x78, 0x48, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x35, 0x0a, 0x06,
+ 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73,
+ 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x65, 0x76, 0x65,
+ 0x6e, 0x74, 0x73, 0x12, 0x50, 0x0a, 0x11, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69,
+ 0x6c, 0x64, 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24,
+ 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73,
+ 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64,
+ 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x46, 0x0a, 0x0d, 0x70, 0x65, 0x72, 0x66, 0x5f, 0x63, 0x6f,
+ 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x73,
+ 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
+ 0x63, 0x73, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x52,
+ 0x0c, 0x70, 0x65, 0x72, 0x66, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x72, 0x73, 0x22, 0xdb, 0x01,
+ 0x0a, 0x10, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68,
+ 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01,
+ 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64,
+ 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66,
+ 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
+ 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a,
+ 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x69,
+ 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6d, 0x69, 0x63, 0x72,
+ 0x6f, 0x73, 0x22, 0x47, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74,
+ 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10,
+ 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a,
+ 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x4d, 0x49, 0x53, 0x53,
+ 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x43, 0x45, 0x52, 0x54, 0x10, 0x03, 0x22, 0x91, 0x01, 0x0a, 0x0f,
+ 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12,
+ 0x3d, 0x0a, 0x1b, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x65,
+ 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01,
+ 0x20, 0x03, 0x28, 0x09, 0x52, 0x18, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64,
+ 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x12, 0x3f,
+ 0x0a, 0x1c, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x69,
+ 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02,
+ 0x20, 0x03, 0x28, 0x09, 0x52, 0x19, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64,
+ 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22,
+ 0x8a, 0x02, 0x0a, 0x10, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68,
+ 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f,
+ 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
+ 0x04, 0x52, 0x11, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69,
+ 0x63, 0x72, 0x6f, 0x73, 0x12, 0x39, 0x0a, 0x19, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c,
+ 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f,
+ 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61,
+ 0x6c, 0x50, 0x61, 0x74, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12,
+ 0x41, 0x0a, 0x0d, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68,
+ 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62,
+ 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4a, 0x6f, 0x62,
+ 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0c, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61,
+ 0x74, 0x68, 0x12, 0x48, 0x0a, 0x11, 0x6c, 0x6f, 0x6e, 0x67, 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69,
+ 0x6e, 0x67, 0x5f, 0x6a, 0x6f, 0x62, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e,
0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72,
- 0x69, 0x63, 0x73, 0x2e, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x55, 0x73, 0x65, 0x72,
- 0x4a, 0x6f, 0x75, 0x72, 0x6e, 0x65, 0x79, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x04,
- 0x63, 0x75, 0x6a, 0x73, 0x22, 0xcc, 0x02, 0x0a, 0x11, 0x53, 0x6f, 0x6f, 0x6e, 0x67, 0x42, 0x75,
- 0x69, 0x6c, 0x64, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f,
- 0x64, 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x6d, 0x6f, 0x64,
- 0x75, 0x6c, 0x65, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73,
- 0x12, 0x2a, 0x0a, 0x11, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f,
- 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x74, 0x6f, 0x74,
- 0x61, 0x6c, 0x41, 0x6c, 0x6c, 0x6f, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x28, 0x0a, 0x10,
- 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x5f, 0x73, 0x69, 0x7a, 0x65,
- 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x41, 0x6c, 0x6c,
- 0x6f, 0x63, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x5f, 0x68, 0x65,
- 0x61, 0x70, 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x6d,
- 0x61, 0x78, 0x48, 0x65, 0x61, 0x70, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x35, 0x0a, 0x06, 0x65, 0x76,
- 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x6f, 0x6f,
- 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73,
- 0x2e, 0x50, 0x65, 0x72, 0x66, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74,
- 0x73, 0x12, 0x50, 0x0a, 0x11, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64,
- 0x73, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x73,
- 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x2e, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49, 0x6e,
- 0x66, 0x6f, 0x52, 0x0f, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x49,
- 0x6e, 0x66, 0x6f, 0x22, 0xdb, 0x01, 0x0a, 0x10, 0x45, 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69,
- 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74,
- 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67,
- 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x45,
- 0x78, 0x70, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x65, 0x74, 0x63, 0x68, 0x65, 0x72, 0x2e,
- 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74,
- 0x61, 0x74, 0x75, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65,
- 0x12, 0x16, 0x0a, 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04,
- 0x52, 0x06, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x22, 0x47, 0x0a, 0x0c, 0x43, 0x6f, 0x6e, 0x66,
- 0x69, 0x67, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x0d, 0x0a, 0x09, 0x4e, 0x4f, 0x5f, 0x43,
- 0x4f, 0x4e, 0x46, 0x49, 0x47, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x4f, 0x4e, 0x46, 0x49,
- 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x11,
- 0x0a, 0x0d, 0x4d, 0x49, 0x53, 0x53, 0x49, 0x4e, 0x47, 0x5f, 0x47, 0x43, 0x45, 0x52, 0x54, 0x10,
- 0x03, 0x22, 0x91, 0x01, 0x0a, 0x0f, 0x4d, 0x69, 0x78, 0x65, 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64,
- 0x73, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x3d, 0x0a, 0x1b, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62,
- 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64,
- 0x75, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x18, 0x6d, 0x69, 0x78, 0x65,
- 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f, 0x64,
- 0x75, 0x6c, 0x65, 0x73, 0x12, 0x3f, 0x0a, 0x1c, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x62, 0x75,
- 0x69, 0x6c, 0x64, 0x5f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x6d, 0x6f, 0x64,
- 0x75, 0x6c, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x19, 0x6d, 0x69, 0x78, 0x65,
- 0x64, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x4d, 0x6f,
- 0x64, 0x75, 0x6c, 0x65, 0x73, 0x22, 0x8a, 0x02, 0x0a, 0x10, 0x43, 0x72, 0x69, 0x74, 0x69, 0x63,
- 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x6c,
- 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f,
- 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64,
- 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x39, 0x0a, 0x19, 0x63, 0x72,
- 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x74, 0x69, 0x6d, 0x65,
- 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x16, 0x63,
- 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x4d,
- 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x41, 0x0a, 0x0d, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61,
- 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73,
- 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0c, 0x63, 0x72, 0x69, 0x74,
- 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x12, 0x48, 0x0a, 0x11, 0x6c, 0x6f, 0x6e, 0x67,
- 0x5f, 0x72, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x5f, 0x6a, 0x6f, 0x62, 0x73, 0x18, 0x05, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x5f, 0x62, 0x75, 0x69, 0x6c,
- 0x64, 0x5f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66,
- 0x6f, 0x52, 0x0f, 0x6c, 0x6f, 0x6e, 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x4a, 0x6f,
- 0x62, 0x73, 0x22, 0x62, 0x0a, 0x07, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a,
- 0x13, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69,
- 0x63, 0x72, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65, 0x6c, 0x61, 0x70,
- 0x73, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x27, 0x0a,
- 0x0f, 0x6a, 0x6f, 0x62, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6a, 0x6f, 0x62, 0x44, 0x65, 0x73, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x28, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69,
- 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69,
- 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
+ 0x69, 0x63, 0x73, 0x2e, 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0f, 0x6c, 0x6f, 0x6e,
+ 0x67, 0x52, 0x75, 0x6e, 0x6e, 0x69, 0x6e, 0x67, 0x4a, 0x6f, 0x62, 0x73, 0x22, 0x62, 0x0a, 0x07,
+ 0x4a, 0x6f, 0x62, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x2e, 0x0a, 0x13, 0x65, 0x6c, 0x61, 0x70, 0x73,
+ 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x5f, 0x6d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x18, 0x01,
+ 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x54, 0x69, 0x6d,
+ 0x65, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x6a, 0x6f, 0x62, 0x5f, 0x64,
+ 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
+ 0x52, 0x0e, 0x6a, 0x6f, 0x62, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
+ 0x42, 0x28, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f, 0x73, 0x6f, 0x6f, 0x6e,
+ 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x2f, 0x6d, 0x65, 0x74,
+ 0x72, 0x69, 0x63, 0x73, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
}
var (
@@ -1997,7 +2198,7 @@
}
var file_metrics_proto_enumTypes = make([]protoimpl.EnumInfo, 5)
-var file_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
+var file_metrics_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
var file_metrics_proto_goTypes = []interface{}{
(MetricsBase_BuildVariant)(0), // 0: soong_build_metrics.MetricsBase.BuildVariant
(MetricsBase_Arch)(0), // 1: soong_build_metrics.MetricsBase.Arch
@@ -2008,15 +2209,18 @@
(*BuildConfig)(nil), // 6: soong_build_metrics.BuildConfig
(*SystemResourceInfo)(nil), // 7: soong_build_metrics.SystemResourceInfo
(*PerfInfo)(nil), // 8: soong_build_metrics.PerfInfo
- (*ProcessResourceInfo)(nil), // 9: soong_build_metrics.ProcessResourceInfo
- (*ModuleTypeInfo)(nil), // 10: soong_build_metrics.ModuleTypeInfo
- (*CriticalUserJourneyMetrics)(nil), // 11: soong_build_metrics.CriticalUserJourneyMetrics
- (*CriticalUserJourneysMetrics)(nil), // 12: soong_build_metrics.CriticalUserJourneysMetrics
- (*SoongBuildMetrics)(nil), // 13: soong_build_metrics.SoongBuildMetrics
- (*ExpConfigFetcher)(nil), // 14: soong_build_metrics.ExpConfigFetcher
- (*MixedBuildsInfo)(nil), // 15: soong_build_metrics.MixedBuildsInfo
- (*CriticalPathInfo)(nil), // 16: soong_build_metrics.CriticalPathInfo
- (*JobInfo)(nil), // 17: soong_build_metrics.JobInfo
+ (*PerfCounters)(nil), // 9: soong_build_metrics.PerfCounters
+ (*PerfCounterGroup)(nil), // 10: soong_build_metrics.PerfCounterGroup
+ (*PerfCounter)(nil), // 11: soong_build_metrics.PerfCounter
+ (*ProcessResourceInfo)(nil), // 12: soong_build_metrics.ProcessResourceInfo
+ (*ModuleTypeInfo)(nil), // 13: soong_build_metrics.ModuleTypeInfo
+ (*CriticalUserJourneyMetrics)(nil), // 14: soong_build_metrics.CriticalUserJourneyMetrics
+ (*CriticalUserJourneysMetrics)(nil), // 15: soong_build_metrics.CriticalUserJourneysMetrics
+ (*SoongBuildMetrics)(nil), // 16: soong_build_metrics.SoongBuildMetrics
+ (*ExpConfigFetcher)(nil), // 17: soong_build_metrics.ExpConfigFetcher
+ (*MixedBuildsInfo)(nil), // 18: soong_build_metrics.MixedBuildsInfo
+ (*CriticalPathInfo)(nil), // 19: soong_build_metrics.CriticalPathInfo
+ (*JobInfo)(nil), // 20: soong_build_metrics.JobInfo
}
var file_metrics_proto_depIdxs = []int32{
0, // 0: soong_build_metrics.MetricsBase.target_build_variant:type_name -> soong_build_metrics.MetricsBase.BuildVariant
@@ -2028,27 +2232,30 @@
8, // 6: soong_build_metrics.MetricsBase.soong_runs:type_name -> soong_build_metrics.PerfInfo
8, // 7: soong_build_metrics.MetricsBase.ninja_runs:type_name -> soong_build_metrics.PerfInfo
8, // 8: soong_build_metrics.MetricsBase.total:type_name -> soong_build_metrics.PerfInfo
- 13, // 9: soong_build_metrics.MetricsBase.soong_build_metrics:type_name -> soong_build_metrics.SoongBuildMetrics
+ 16, // 9: soong_build_metrics.MetricsBase.soong_build_metrics:type_name -> soong_build_metrics.SoongBuildMetrics
6, // 10: soong_build_metrics.MetricsBase.build_config:type_name -> soong_build_metrics.BuildConfig
7, // 11: soong_build_metrics.MetricsBase.system_resource_info:type_name -> soong_build_metrics.SystemResourceInfo
8, // 12: soong_build_metrics.MetricsBase.bazel_runs:type_name -> soong_build_metrics.PerfInfo
- 14, // 13: soong_build_metrics.MetricsBase.exp_config_fetcher:type_name -> soong_build_metrics.ExpConfigFetcher
- 16, // 14: soong_build_metrics.MetricsBase.critical_path_info:type_name -> soong_build_metrics.CriticalPathInfo
+ 17, // 13: soong_build_metrics.MetricsBase.exp_config_fetcher:type_name -> soong_build_metrics.ExpConfigFetcher
+ 19, // 14: soong_build_metrics.MetricsBase.critical_path_info:type_name -> soong_build_metrics.CriticalPathInfo
2, // 15: soong_build_metrics.BuildConfig.ninja_weight_list_source:type_name -> soong_build_metrics.BuildConfig.NinjaWeightListSource
- 9, // 16: soong_build_metrics.PerfInfo.processes_resource_info:type_name -> soong_build_metrics.ProcessResourceInfo
- 3, // 17: soong_build_metrics.ModuleTypeInfo.build_system:type_name -> soong_build_metrics.ModuleTypeInfo.BuildSystem
- 5, // 18: soong_build_metrics.CriticalUserJourneyMetrics.metrics:type_name -> soong_build_metrics.MetricsBase
- 11, // 19: soong_build_metrics.CriticalUserJourneysMetrics.cujs:type_name -> soong_build_metrics.CriticalUserJourneyMetrics
- 8, // 20: soong_build_metrics.SoongBuildMetrics.events:type_name -> soong_build_metrics.PerfInfo
- 15, // 21: soong_build_metrics.SoongBuildMetrics.mixed_builds_info:type_name -> soong_build_metrics.MixedBuildsInfo
- 4, // 22: soong_build_metrics.ExpConfigFetcher.status:type_name -> soong_build_metrics.ExpConfigFetcher.ConfigStatus
- 17, // 23: soong_build_metrics.CriticalPathInfo.critical_path:type_name -> soong_build_metrics.JobInfo
- 17, // 24: soong_build_metrics.CriticalPathInfo.long_running_jobs:type_name -> soong_build_metrics.JobInfo
- 25, // [25:25] is the sub-list for method output_type
- 25, // [25:25] is the sub-list for method input_type
- 25, // [25:25] is the sub-list for extension type_name
- 25, // [25:25] is the sub-list for extension extendee
- 0, // [0:25] is the sub-list for field type_name
+ 12, // 16: soong_build_metrics.PerfInfo.processes_resource_info:type_name -> soong_build_metrics.ProcessResourceInfo
+ 10, // 17: soong_build_metrics.PerfCounters.groups:type_name -> soong_build_metrics.PerfCounterGroup
+ 11, // 18: soong_build_metrics.PerfCounterGroup.counters:type_name -> soong_build_metrics.PerfCounter
+ 3, // 19: soong_build_metrics.ModuleTypeInfo.build_system:type_name -> soong_build_metrics.ModuleTypeInfo.BuildSystem
+ 5, // 20: soong_build_metrics.CriticalUserJourneyMetrics.metrics:type_name -> soong_build_metrics.MetricsBase
+ 14, // 21: soong_build_metrics.CriticalUserJourneysMetrics.cujs:type_name -> soong_build_metrics.CriticalUserJourneyMetrics
+ 8, // 22: soong_build_metrics.SoongBuildMetrics.events:type_name -> soong_build_metrics.PerfInfo
+ 18, // 23: soong_build_metrics.SoongBuildMetrics.mixed_builds_info:type_name -> soong_build_metrics.MixedBuildsInfo
+ 9, // 24: soong_build_metrics.SoongBuildMetrics.perf_counters:type_name -> soong_build_metrics.PerfCounters
+ 4, // 25: soong_build_metrics.ExpConfigFetcher.status:type_name -> soong_build_metrics.ExpConfigFetcher.ConfigStatus
+ 20, // 26: soong_build_metrics.CriticalPathInfo.critical_path:type_name -> soong_build_metrics.JobInfo
+ 20, // 27: soong_build_metrics.CriticalPathInfo.long_running_jobs:type_name -> soong_build_metrics.JobInfo
+ 28, // [28:28] is the sub-list for method output_type
+ 28, // [28:28] is the sub-list for method input_type
+ 28, // [28:28] is the sub-list for extension type_name
+ 28, // [28:28] is the sub-list for extension extendee
+ 0, // [0:28] is the sub-list for field type_name
}
func init() { file_metrics_proto_init() }
@@ -2106,7 +2313,7 @@
}
}
file_metrics_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ProcessResourceInfo); i {
+ switch v := v.(*PerfCounters); i {
case 0:
return &v.state
case 1:
@@ -2118,7 +2325,7 @@
}
}
file_metrics_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ModuleTypeInfo); i {
+ switch v := v.(*PerfCounterGroup); i {
case 0:
return &v.state
case 1:
@@ -2130,7 +2337,7 @@
}
}
file_metrics_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CriticalUserJourneyMetrics); i {
+ switch v := v.(*PerfCounter); i {
case 0:
return &v.state
case 1:
@@ -2142,7 +2349,7 @@
}
}
file_metrics_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CriticalUserJourneysMetrics); i {
+ switch v := v.(*ProcessResourceInfo); i {
case 0:
return &v.state
case 1:
@@ -2154,7 +2361,7 @@
}
}
file_metrics_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*SoongBuildMetrics); i {
+ switch v := v.(*ModuleTypeInfo); i {
case 0:
return &v.state
case 1:
@@ -2166,7 +2373,7 @@
}
}
file_metrics_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ExpConfigFetcher); i {
+ switch v := v.(*CriticalUserJourneyMetrics); i {
case 0:
return &v.state
case 1:
@@ -2178,7 +2385,7 @@
}
}
file_metrics_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*MixedBuildsInfo); i {
+ switch v := v.(*CriticalUserJourneysMetrics); i {
case 0:
return &v.state
case 1:
@@ -2190,7 +2397,7 @@
}
}
file_metrics_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CriticalPathInfo); i {
+ switch v := v.(*SoongBuildMetrics); i {
case 0:
return &v.state
case 1:
@@ -2202,6 +2409,42 @@
}
}
file_metrics_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*ExpConfigFetcher); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_metrics_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*MixedBuildsInfo); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_metrics_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
+ switch v := v.(*CriticalPathInfo); i {
+ case 0:
+ return &v.state
+ case 1:
+ return &v.sizeCache
+ case 2:
+ return &v.unknownFields
+ default:
+ return nil
+ }
+ }
+ file_metrics_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*JobInfo); i {
case 0:
return &v.state
@@ -2220,7 +2463,7 @@
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_metrics_proto_rawDesc,
NumEnums: 5,
- NumMessages: 13,
+ NumMessages: 16,
NumExtensions: 0,
NumServices: 0,
},
diff --git a/ui/metrics/metrics_proto/metrics.proto b/ui/metrics/metrics_proto/metrics.proto
index b437da7..11fcba7 100644
--- a/ui/metrics/metrics_proto/metrics.proto
+++ b/ui/metrics/metrics_proto/metrics.proto
@@ -213,6 +213,30 @@
optional string error_message = 8;
}
+message PerfCounters {
+ // The timestamp of these counters in nanoseconds.
+ optional uint64 time = 1;
+
+ // A list of counter names and values.
+ repeated PerfCounterGroup groups = 2;
+}
+
+message PerfCounterGroup {
+ // The name of this counter group (e.g. "cpu" or "memory")
+ optional string name = 1;
+
+ // The counters in this group
+ repeated PerfCounter counters = 2;
+}
+
+message PerfCounter {
+ // The name of this counter.
+ optional string name = 1;
+
+ // The value of this counter.
+ optional int64 value = 2;
+}
+
message ProcessResourceInfo {
// The name of the process for identification.
optional string name = 1;
@@ -295,6 +319,9 @@
// Mixed Builds information
optional MixedBuildsInfo mixed_builds_info = 7;
+
+ // Performance during for soong_build execution.
+ repeated PerfCounters perf_counters = 8;
}
message ExpConfigFetcher {
diff --git a/ui/status/ninja.go b/ui/status/ninja.go
index 7b25d50..f4e3fb8 100644
--- a/ui/status/ninja.go
+++ b/ui/status/ninja.go
@@ -20,6 +20,7 @@
"io"
"os"
"regexp"
+ "runtime"
"strings"
"syscall"
"time"
@@ -178,7 +179,28 @@
// msgChan is closed
break
}
- // Ignore msg.BuildStarted
+
+ if msg.BuildStarted != nil {
+ parallelism := uint32(runtime.NumCPU())
+ if msg.BuildStarted.GetParallelism() > 0 {
+ parallelism = msg.BuildStarted.GetParallelism()
+ }
+ // It is estimated from total time / parallelism assumming the build is packing enough.
+ estimatedDurationFromTotal := time.Duration(msg.BuildStarted.GetEstimatedTotalTime()/parallelism) * time.Millisecond
+ // It is estimated from critical path time which is useful for small size build.
+ estimatedDurationFromCriticalPath := time.Duration(msg.BuildStarted.GetCriticalPathTime()) * time.Millisecond
+ // Select the longer one.
+ estimatedDuration := max(estimatedDurationFromTotal, estimatedDurationFromCriticalPath)
+
+ if estimatedDuration > 0 {
+ n.status.SetEstimatedTime(time.Now().Add(estimatedDuration))
+ n.status.Verbose(fmt.Sprintf("parallelism: %d, estimated from total time: %s, critical path time: %s",
+ parallelism,
+ estimatedDurationFromTotal,
+ estimatedDurationFromCriticalPath))
+
+ }
+ }
if msg.TotalEdges != nil {
n.status.SetTotalActions(int(msg.TotalEdges.GetTotalEdges()))
}
diff --git a/ui/status/ninja_frontend/README b/ui/status/ninja_frontend/README
index 8c4b451..767bbf1 100644
--- a/ui/status/ninja_frontend/README
+++ b/ui/status/ninja_frontend/README
@@ -1,3 +1,3 @@
-This comes from https://android.googlesource.com/platform/external/ninja/+/master/src/frontend.proto
+This comes from https://android.googlesource.com/platform/external/ninja/+/main/src/frontend.proto
The only difference is the specification of a go_package. To regenerate frontend.pb.go, run regen.sh.
diff --git a/ui/status/ninja_frontend/frontend.pb.go b/ui/status/ninja_frontend/frontend.pb.go
index d0c4953..d8344c8 100644
--- a/ui/status/ninja_frontend/frontend.pb.go
+++ b/ui/status/ninja_frontend/frontend.pb.go
@@ -14,7 +14,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
-// protoc-gen-go v1.28.1
+// protoc-gen-go v1.30.0
// protoc v3.21.12
// source: frontend.proto
@@ -240,6 +240,10 @@
Parallelism *uint32 `protobuf:"varint,1,opt,name=parallelism" json:"parallelism,omitempty"`
// Verbose value passed to ninja.
Verbose *bool `protobuf:"varint,2,opt,name=verbose" json:"verbose,omitempty"`
+ // Critical path's running time in milliseconds
+ CriticalPathTime *uint32 `protobuf:"varint,3,opt,name=critical_path_time,json=criticalPathTime" json:"critical_path_time,omitempty"`
+ // Total running time of every need-to-build edge in milliseconds
+ EstimatedTotalTime *uint32 `protobuf:"varint,4,opt,name=estimated_total_time,json=estimatedTotalTime" json:"estimated_total_time,omitempty"`
}
func (x *Status_BuildStarted) Reset() {
@@ -288,6 +292,20 @@
return false
}
+func (x *Status_BuildStarted) GetCriticalPathTime() uint32 {
+ if x != nil && x.CriticalPathTime != nil {
+ return *x.CriticalPathTime
+ }
+ return 0
+}
+
+func (x *Status_BuildStarted) GetEstimatedTotalTime() uint32 {
+ if x != nil && x.EstimatedTotalTime != nil {
+ return *x.EstimatedTotalTime
+ }
+ return 0
+}
+
type Status_BuildFinished struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -660,7 +678,7 @@
var file_frontend_proto_rawDesc = []byte{
0x0a, 0x0e, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
- 0x12, 0x05, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x22, 0xc8, 0x0a, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74,
+ 0x12, 0x05, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x22, 0xa9, 0x0b, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74,
0x75, 0x73, 0x12, 0x39, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x64, 0x67, 0x65,
0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x2e,
0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x45, 0x64, 0x67, 0x65,
@@ -687,67 +705,73 @@
0x67, 0x65, 0x1a, 0x2d, 0x0a, 0x0a, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x45, 0x64, 0x67, 0x65, 0x73,
0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x65, 0x64, 0x67, 0x65, 0x73, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x45, 0x64, 0x67, 0x65,
- 0x73, 0x1a, 0x4a, 0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65,
- 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x69, 0x73, 0x6d,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c,
- 0x69, 0x73, 0x6d, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x1a, 0x0f, 0x0a,
- 0x0d, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x1a, 0xb6,
- 0x01, 0x0a, 0x0b, 0x45, 0x64, 0x67, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x0e,
- 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1d,
- 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x0d, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x16, 0x0a,
- 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x69,
- 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73,
- 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x12,
- 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64,
- 0x65, 0x73, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18, 0x06,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x18, 0x0a,
- 0x07, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07,
- 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x1a, 0xf3, 0x03, 0x0a, 0x0c, 0x45, 0x64, 0x67, 0x65,
- 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f,
- 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54,
- 0x69, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x11, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x6f,
- 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74,
- 0x70, 0x75, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d, 0x65,
- 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d, 0x65,
- 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18,
- 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69, 0x6d,
- 0x65, 0x12, 0x1c, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b, 0x62, 0x18,
- 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b, 0x62, 0x12,
- 0x2a, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61,
- 0x75, 0x6c, 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e, 0x6f,
- 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6d,
- 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73,
- 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50, 0x61, 0x67,
- 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f, 0x69, 0x6e,
- 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x69, 0x6f,
- 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f, 0x6f, 0x75,
- 0x74, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x69,
- 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76, 0x6f, 0x6c,
- 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73,
- 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18, 0x76,
- 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x53,
- 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76, 0x6f, 0x6c,
- 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x73,
- 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x69,
- 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78,
- 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67,
- 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x1a, 0x92, 0x01,
- 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x05, 0x6c, 0x65, 0x76,
- 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x6e, 0x69, 0x6e, 0x6a, 0x61,
- 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e,
- 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x52, 0x05, 0x6c, 0x65, 0x76,
- 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x34, 0x0a, 0x05,
- 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x00, 0x12,
- 0x0b, 0x0a, 0x07, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a, 0x05,
- 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47,
- 0x10, 0x03, 0x42, 0x2a, 0x48, 0x03, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x2f,
- 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2f,
- 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64,
+ 0x73, 0x1a, 0xaa, 0x01, 0x0a, 0x0c, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x72, 0x74,
+ 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65, 0x6c, 0x69, 0x73,
+ 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0b, 0x70, 0x61, 0x72, 0x61, 0x6c, 0x6c, 0x65,
+ 0x6c, 0x69, 0x73, 0x6d, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x18,
+ 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x12, 0x2c,
+ 0x0a, 0x12, 0x63, 0x72, 0x69, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f,
+ 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x10, 0x63, 0x72, 0x69, 0x74,
+ 0x69, 0x63, 0x61, 0x6c, 0x50, 0x61, 0x74, 0x68, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x30, 0x0a, 0x14,
+ 0x65, 0x73, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f,
+ 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x12, 0x65, 0x73, 0x74, 0x69,
+ 0x6d, 0x61, 0x74, 0x65, 0x64, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x54, 0x69, 0x6d, 0x65, 0x1a, 0x0f,
+ 0x0a, 0x0d, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x1a,
+ 0xb6, 0x01, 0x0a, 0x0b, 0x45, 0x64, 0x67, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12,
+ 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12,
+ 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20,
+ 0x01, 0x28, 0x0d, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x16,
+ 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06,
+ 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74,
+ 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73,
+ 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
+ 0x64, 0x65, 0x73, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x18,
+ 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x12, 0x18,
+ 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52,
+ 0x07, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x1a, 0xf3, 0x03, 0x0a, 0x0c, 0x45, 0x64, 0x67,
+ 0x65, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
+ 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64,
+ 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x65, 0x6e, 0x64,
+ 0x54, 0x69, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03,
+ 0x20, 0x01, 0x28, 0x11, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06,
+ 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75,
+ 0x74, 0x70, 0x75, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x69, 0x6d,
+ 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x54, 0x69, 0x6d,
+ 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x74, 0x69, 0x6d, 0x65,
+ 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x54, 0x69,
+ 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x73, 0x73, 0x5f, 0x6b, 0x62,
+ 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x52, 0x73, 0x73, 0x4b, 0x62,
+ 0x12, 0x2a, 0x0a, 0x11, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66,
+ 0x61, 0x75, 0x6c, 0x74, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x69, 0x6e,
+ 0x6f, 0x72, 0x50, 0x61, 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x2a, 0x0a, 0x11,
+ 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x5f, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x66, 0x61, 0x75, 0x6c, 0x74,
+ 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0f, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x50, 0x61,
+ 0x67, 0x65, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x12, 0x1e, 0x0a, 0x0b, 0x69, 0x6f, 0x5f, 0x69,
+ 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x69,
+ 0x6f, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x20, 0x0a, 0x0c, 0x69, 0x6f, 0x5f, 0x6f,
+ 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x6b, 0x62, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a,
+ 0x69, 0x6f, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x4b, 0x62, 0x12, 0x3c, 0x0a, 0x1a, 0x76, 0x6f,
+ 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f,
+ 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x18,
+ 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
+ 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x40, 0x0a, 0x1c, 0x69, 0x6e, 0x76, 0x6f,
+ 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f,
+ 0x73, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a,
+ 0x69, 0x6e, 0x76, 0x6f, 0x6c, 0x75, 0x6e, 0x74, 0x61, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65,
+ 0x78, 0x74, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61,
+ 0x67, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x1a, 0x92,
+ 0x01, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x37, 0x0a, 0x05, 0x6c, 0x65,
+ 0x76, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x6e, 0x69, 0x6e, 0x6a,
+ 0x61, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
+ 0x2e, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x52, 0x05, 0x6c, 0x65,
+ 0x76, 0x65, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02,
+ 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x34, 0x0a,
+ 0x05, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x00,
+ 0x12, 0x0b, 0x0a, 0x07, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x09, 0x0a,
+ 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55,
+ 0x47, 0x10, 0x03, 0x42, 0x2a, 0x48, 0x03, 0x5a, 0x26, 0x61, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64,
+ 0x2f, 0x73, 0x6f, 0x6f, 0x6e, 0x67, 0x2f, 0x75, 0x69, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
+ 0x2f, 0x6e, 0x69, 0x6e, 0x6a, 0x61, 0x5f, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x64,
}
var (
diff --git a/ui/status/ninja_frontend/frontend.proto b/ui/status/ninja_frontend/frontend.proto
index 6cb4a0d..42b251b 100644
--- a/ui/status/ninja_frontend/frontend.proto
+++ b/ui/status/ninja_frontend/frontend.proto
@@ -30,6 +30,10 @@
optional uint32 parallelism = 1;
// Verbose value passed to ninja.
optional bool verbose = 2;
+ // Critical path's running time in milliseconds
+ optional uint32 critical_path_time = 3;
+ // Total running time of every need-to-build edge in milliseconds
+ optional uint32 estimated_total_time = 4;
}
message BuildFinished {
diff --git a/ui/status/status.go b/ui/status/status.go
index f3e58b6..da78994 100644
--- a/ui/status/status.go
+++ b/ui/status/status.go
@@ -19,6 +19,7 @@
import (
"sync"
+ "time"
)
// Action describes an action taken (or as Ninja calls them, Edges).
@@ -107,6 +108,8 @@
// FinishedActions are the number of actions that have been finished
// with FinishAction.
FinishedActions int
+
+ EstimatedTime time.Time
}
// ToolStatus is the interface used by tools to report on their Actions, and to
@@ -118,6 +121,7 @@
// This call be will ignored if it sets a number that is less than the
// current number of started actions.
SetTotalActions(total int)
+ SetEstimatedTime(estimatedTime time.Time)
// StartAction specifies that the associated action has been started by
// the tool.
@@ -267,6 +271,13 @@
s.counts.TotalActions += diff
}
+func (s *Status) SetEstimatedTime(estimatedTime time.Time) {
+ s.lock.Lock()
+ defer s.lock.Unlock()
+
+ s.counts.EstimatedTime = estimatedTime
+}
+
func (s *Status) startAction(action *Action) {
s.lock.Lock()
defer s.lock.Unlock()
@@ -329,6 +340,10 @@
}
}
+func (d *toolStatus) SetEstimatedTime(estimatedTime time.Time) {
+ d.status.SetEstimatedTime(estimatedTime)
+}
+
func (d *toolStatus) StartAction(action *Action) {
totalDiff := 0
diff --git a/ui/terminal/format.go b/ui/terminal/format.go
index 4205bdc..241a1dd 100644
--- a/ui/terminal/format.go
+++ b/ui/terminal/format.go
@@ -51,9 +51,22 @@
return ""
}
+func remainingTimeString(t time.Time) string {
+ now := time.Now()
+ if t.After(now) {
+ return t.Sub(now).Round(time.Duration(time.Second)).String()
+ }
+ return time.Duration(0).Round(time.Duration(time.Second)).String()
+}
func (s formatter) progress(counts status.Counts) string {
if s.format == "" {
- return fmt.Sprintf("[%3d%% %d/%d] ", 100*counts.FinishedActions/counts.TotalActions, counts.FinishedActions, counts.TotalActions)
+ output := fmt.Sprintf("[%3d%% %d/%d", 100*counts.FinishedActions/counts.TotalActions, counts.FinishedActions, counts.TotalActions)
+
+ if !counts.EstimatedTime.IsZero() {
+ output += fmt.Sprintf(" %s remaining", remainingTimeString(counts.EstimatedTime))
+ }
+ output += "] "
+ return output
}
buf := &strings.Builder{}
@@ -93,6 +106,13 @@
fmt.Fprintf(buf, "%3d%%", 100*counts.FinishedActions/counts.TotalActions)
case 'e':
fmt.Fprintf(buf, "%.3f", time.Since(s.start).Seconds())
+ case 'l':
+ if counts.EstimatedTime.IsZero() {
+ // No esitimated data
+ buf.WriteRune('?')
+ } else {
+ fmt.Fprintf(buf, "%s", remainingTimeString(counts.EstimatedTime))
+ }
default:
buf.WriteString("unknown placeholder '")
buf.WriteByte(c)
diff --git a/ui/tracer/tracer.go b/ui/tracer/tracer.go
index b8fc87b..33b3d89 100644
--- a/ui/tracer/tracer.go
+++ b/ui/tracer/tracer.go
@@ -46,6 +46,8 @@
End(thread Thread)
Complete(name string, thread Thread, begin, end uint64)
+ CountersAtTime(name string, thread Thread, time uint64, counters []Counter)
+
ImportMicrofactoryLog(filename string)
StatusTracer() status.StatusOutput
@@ -247,3 +249,48 @@
Tid: uint64(thread),
})
}
+
+type Counter struct {
+ Name string
+ Value int64
+}
+
+type countersMarshaller []Counter
+
+var _ json.Marshaler = countersMarshaller(nil)
+
+func (counters countersMarshaller) MarshalJSON() ([]byte, error) {
+ // This produces similar output to a map[string]int64, but maintains the order of the slice.
+ buf := bytes.Buffer{}
+ buf.WriteRune('{')
+ for i, counter := range counters {
+ name, err := json.Marshal(counter.Name)
+ if err != nil {
+ return nil, err
+ }
+ buf.Write(name)
+ buf.WriteByte(':')
+ value, err := json.Marshal(counter.Value)
+ if err != nil {
+ return nil, err
+ }
+ buf.Write(value)
+ if i != len(counters)-1 {
+ buf.WriteRune(',')
+ }
+ }
+ buf.WriteRune('}')
+ return buf.Bytes(), nil
+}
+
+// CountersAtTime writes a Counter event at the given timestamp in nanoseconds.
+func (t *tracerImpl) CountersAtTime(name string, thread Thread, time uint64, counters []Counter) {
+ t.writeEvent(&viewerEvent{
+ Name: name,
+ Phase: "C",
+ Time: time / 1000,
+ Pid: 0,
+ Tid: uint64(thread),
+ Arg: countersMarshaller(counters),
+ })
+}
diff --git a/xml/Android.bp b/xml/Android.bp
index d4753de..1542930 100644
--- a/xml/Android.bp
+++ b/xml/Android.bp
@@ -9,7 +9,6 @@
"blueprint",
"blueprint-pathtools",
"soong",
- "soong-bp2build",
"soong-android",
"soong-etc",
],
@@ -19,7 +18,6 @@
],
testSrcs: [
"xml_test.go",
- "xml_conversion_test.go",
],
pluginFor: ["soong_build"],
}
diff --git a/xml/xml.go b/xml/xml.go
index 20a26f5..c281078 100644
--- a/xml/xml.go
+++ b/xml/xml.go
@@ -16,7 +16,6 @@
import (
"android/soong/android"
- "android/soong/bazel"
"android/soong/etc"
"github.com/google/blueprint"
@@ -68,8 +67,6 @@
}
type prebuiltEtcXml struct {
- android.BazelModuleBase
-
etc.PrebuiltEtc
properties prebuiltEtcXmlProperties
@@ -132,44 +129,5 @@
etc.InitPrebuiltEtcModule(&module.PrebuiltEtc, "etc")
// This module is device-only
android.InitAndroidArchModule(module, android.DeviceSupported, android.MultilibFirst)
- android.InitBazelModule(module)
return module
}
-
-type bazelPrebuiltEtcXmlAttributes struct {
- Src bazel.LabelAttribute
- Filename bazel.LabelAttribute
- Dir string
- Installable bazel.BoolAttribute
- Filename_from_src bazel.BoolAttribute
- Schema *string
-}
-
-func (p *prebuiltEtcXml) ConvertWithBp2build(ctx android.TopDownMutatorContext) {
- baseAttrs, convertible := p.PrebuiltEtc.Bp2buildHelper(ctx)
-
- if !convertible {
- return
- }
-
- var schema *string
- if p.properties.Schema != nil {
- schema = p.properties.Schema
- }
-
- attrs := &bazelPrebuiltEtcXmlAttributes{
- Src: baseAttrs.Src,
- Filename: baseAttrs.Filename,
- Dir: baseAttrs.Dir,
- Installable: baseAttrs.Installable,
- Filename_from_src: baseAttrs.Filename_from_src,
- Schema: schema,
- }
-
- props := bazel.BazelTargetModuleProperties{
- Rule_class: "prebuilt_xml",
- Bzl_load_location: "//build/bazel/rules/prebuilt_xml.bzl",
- }
-
- ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: p.Name()}, attrs)
-}
diff --git a/xml/xml_conversion_test.go b/xml/xml_conversion_test.go
deleted file mode 100644
index 6606ddc..0000000
--- a/xml/xml_conversion_test.go
+++ /dev/null
@@ -1,129 +0,0 @@
-// 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 xml
-
-import (
- "android/soong/android"
- "android/soong/bp2build"
-
- "testing"
-)
-
-func runXmlPrebuiltEtcTestCase(t *testing.T, tc bp2build.Bp2buildTestCase) {
- t.Helper()
- (&tc).ModuleTypeUnderTest = "prebuilt_etc_xml"
- (&tc).ModuleTypeUnderTestFactory = PrebuiltEtcXmlFactory
- bp2build.RunBp2BuildTestCase(t, registerXmlModuleTypes, tc)
-}
-
-func registerXmlModuleTypes(ctx android.RegistrationContext) {
-}
-
-func TestXmlPrebuiltEtcSimple(t *testing.T) {
- runXmlPrebuiltEtcTestCase(t, bp2build.Bp2buildTestCase{
- Description: "prebuilt_etc_xml - simple example",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc_xml {
- name: "foo",
- src: "fooSrc",
- filename: "fooFileName",
- sub_dir: "fooDir",
- schema: "foo.dtd",
-}
-`,
- ExpectedBazelTargets: []string{
- bp2build.MakeBazelTarget("prebuilt_xml", "foo", bp2build.AttrNameToString{
- "src": `"fooSrc"`,
- "filename": `"fooFileName"`,
- "dir": `"etc/fooDir"`,
- "schema": `"foo.dtd"`,
- })}})
-}
-
-func TestXmlPrebuiltEtcFilenameFromSrc(t *testing.T) {
- runXmlPrebuiltEtcTestCase(t, bp2build.Bp2buildTestCase{
- Description: "prebuilt_etc_xml - filenameFromSrc True ",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc_xml {
- name: "foo",
- src: "fooSrc",
- filename_from_src: true,
- sub_dir: "fooDir",
- schema: "foo.dtd",
-}
-`,
- ExpectedBazelTargets: []string{
- bp2build.MakeBazelTarget("prebuilt_xml", "foo", bp2build.AttrNameToString{
- "src": `"fooSrc"`,
- "filename": `"fooSrc"`,
- "dir": `"etc/fooDir"`,
- "schema": `"foo.dtd"`,
- })}})
-}
-
-func TestXmlPrebuiltEtcFilenameAndFilenameFromSrc(t *testing.T) {
- runXmlPrebuiltEtcTestCase(t, bp2build.Bp2buildTestCase{
- Description: "prebuilt_etc_xml - filename provided and filenameFromSrc True ",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc_xml {
- name: "foo",
- src: "fooSrc",
- filename: "fooFileName",
- filename_from_src: true,
- sub_dir: "fooDir",
- schema: "foo.dtd",
-}
-`,
- ExpectedBazelTargets: []string{
- bp2build.MakeBazelTarget("prebuilt_xml", "foo", bp2build.AttrNameToString{
- "src": `"fooSrc"`,
- "filename": `"fooFileName"`,
- "dir": `"etc/fooDir"`,
- "schema": `"foo.dtd"`,
- })}})
-}
-
-func TestXmlPrebuiltEtcFileNameFromSrcMultipleSrcs(t *testing.T) {
- runXmlPrebuiltEtcTestCase(t, bp2build.Bp2buildTestCase{
- Description: "prebuilt_etc - filename_from_src is true but there are multiple srcs",
- Filesystem: map[string]string{},
- Blueprint: `
-prebuilt_etc_xml {
- name: "foo",
- filename_from_src: true,
- arch: {
- arm: {
- src: "barSrc",
- },
- arm64: {
- src: "bazSrc",
- },
- }
-}
-`,
- ExpectedBazelTargets: []string{
- bp2build.MakeBazelTarget("prebuilt_xml", "foo", bp2build.AttrNameToString{
- "filename_from_src": `True`,
- "dir": `"etc"`,
- "src": `select({
- "//build/bazel/platforms/arch:arm": "barSrc",
- "//build/bazel/platforms/arch:arm64": "bazSrc",
- "//conditions:default": None,
- })`,
- })}})
-}
diff --git a/zip/cmd/main.go b/zip/cmd/main.go
index 5231fae..37537ab 100644
--- a/zip/cmd/main.go
+++ b/zip/cmd/main.go
@@ -174,6 +174,7 @@
traceFile := flags.String("trace", "", "write trace to file")
sha256Checksum := flags.Bool("sha256", false, "add a zip header to each file containing its SHA256 digest")
doNotWrite := flags.Bool("n", false, "Nothing is written to disk -- all other work happens")
+ quiet := flags.Bool("quiet", false, "do not print warnings to console")
flags.Var(&rootPrefix{}, "P", "path prefix within the zip at which to place files")
flags.Var(&listFiles{}, "l", "file containing list of files to zip")
@@ -238,6 +239,7 @@
IgnoreMissingFiles: *ignoreMissingFiles,
Sha256Checksum: *sha256Checksum,
DoNotWrite: *doNotWrite,
+ Quiet: *quiet,
})
if err != nil {
fmt.Fprintln(os.Stderr, "error:", err.Error())
diff --git a/zip/zip.go b/zip/zip.go
index 30a2ee7..f91a5f2 100644
--- a/zip/zip.go
+++ b/zip/zip.go
@@ -283,6 +283,7 @@
IgnoreMissingFiles bool
Sha256Checksum bool
DoNotWrite bool
+ Quiet bool
Stderr io.Writer
Filesystem pathtools.FileSystem
@@ -340,7 +341,9 @@
Err: os.ErrNotExist,
}
if args.IgnoreMissingFiles {
- fmt.Fprintln(z.stderr, "warning:", err)
+ if !args.Quiet {
+ fmt.Fprintln(z.stderr, "warning:", err)
+ }
} else {
return err
}
@@ -357,7 +360,9 @@
Err: os.ErrNotExist,
}
if args.IgnoreMissingFiles {
- fmt.Fprintln(z.stderr, "warning:", err)
+ if !args.Quiet {
+ fmt.Fprintln(z.stderr, "warning:", err)
+ }
} else {
return err
}
@@ -368,7 +373,9 @@
Err: syscall.ENOTDIR,
}
if args.IgnoreMissingFiles {
- fmt.Fprintln(z.stderr, "warning:", err)
+ if !args.Quiet {
+ fmt.Fprintln(z.stderr, "warning:", err)
+ }
} else {
return err
}