Generate a ndk_sysroot target in bp2build
This target will have a dependency edge to every bp2build equivalent of
Soong's ndk_headers. In b builds, sdk variants will compile against this
aggregated CcInfo providing target
A non monolithic alternative was discarded after conversations in
b/300504837#comment1-5
Contents of bp2build generated target: https://paste.googleplex.com/6643820291686400
Implementation details
- Since there is no equivalent Soong module for ndk_sysroot, hardcode
bp2build/build_conversion.go to collect all ndk_headers soong modules.
Add them to `deps` of a ndk_sysroot target
- Create `ndk_sysroot` in build/bazel/rules/cc/BUILD.bazel. This is
expected to be a temporary location. This will use the
cc_library_headers macro
- Update SetStubsForDynamicDeps so that sdk variant of rdeps depends on
//build/bazel/rules/cc:ndk_sysroot. This will provide a CcInfo during
compilation. Since ndk_sysroot is of type cc_library_headers, it will
not get packaged into the apk.
- Refactor `goBazelTarget` to a generic `bTarget` so that it is
representative of the expanded usage by ndk_sysroot
Test: b build //build/bazel/examples/android_app/java/com/app:app_with_sdk_variant_of_jni_deps --config=android (with aosp/2755284)
Bug: 300504837
Change-Id: Ifa427dd78115703ab251b0e1a0b71d3f19e91008
diff --git a/bp2build/build_conversion.go b/bp2build/build_conversion.go
index e6941df..ce2a955 100644
--- a/bp2build/build_conversion.go
+++ b/bp2build/build_conversion.go
@@ -287,9 +287,9 @@
return r.buildFileToTargets
}
-// struct to store state of go bazel targets
+// struct to store state of b bazel targets (e.g. go targets which do not implement android.Module)
// this implements bp2buildModule interface and is passed to generateBazelTargets
-type goBazelTarget struct {
+type bTarget struct {
targetName string
targetPackage string
bazelRuleClass string
@@ -297,26 +297,26 @@
bazelAttributes []interface{}
}
-var _ bp2buildModule = (*goBazelTarget)(nil)
+var _ bp2buildModule = (*bTarget)(nil)
-func (g goBazelTarget) TargetName() string {
- return g.targetName
+func (b bTarget) TargetName() string {
+ return b.targetName
}
-func (g goBazelTarget) TargetPackage() string {
- return g.targetPackage
+func (b bTarget) TargetPackage() string {
+ return b.targetPackage
}
-func (g goBazelTarget) BazelRuleClass() string {
- return g.bazelRuleClass
+func (b bTarget) BazelRuleClass() string {
+ return b.bazelRuleClass
}
-func (g goBazelTarget) BazelRuleLoadLocation() string {
- return g.bazelRuleLoadLocation
+func (b bTarget) BazelRuleLoadLocation() string {
+ return b.bazelRuleLoadLocation
}
-func (g goBazelTarget) BazelAttributes() []interface{} {
- return g.bazelAttributes
+func (b bTarget) BazelAttributes() []interface{} {
+ return b.bazelAttributes
}
// Creates a target_compatible_with entry that is *not* compatible with android
@@ -421,7 +421,7 @@
Target_compatible_with: targetNotCompatibleWithAndroid(),
}
- libTest := goBazelTarget{
+ libTest := bTarget{
targetName: gp.name,
targetPackage: gp.dir,
bazelRuleClass: "go_test",
@@ -514,7 +514,7 @@
Target_compatible_with: targetNotCompatibleWithAndroid(),
}
- lib := goBazelTarget{
+ lib := bTarget{
targetName: g.Name(),
targetPackage: ctx.ModuleDir(g),
bazelRuleClass: "go_library",
@@ -555,23 +555,35 @@
Deps []string
}
+type buildConversionMetadata struct {
+ nameToGoLibraryModule nameToGoLibraryModule
+ ndkHeaders []blueprint.Module
+}
+
type nameToGoLibraryModule map[string]goLibraryModule
-// Visit each module in the graph
+// Visit each module in the graph, and collect metadata about the build 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{}
+// If a module is of type `ndk_headers`, add it to a list and return the list
+func createBuildConversionMetadata(ctx *android.Context) buildConversionMetadata {
+ goMap := nameToGoLibraryModule{}
+ ndkHeaders := []blueprint.Module{}
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{
+ goMap[m.Name()] = goLibraryModule{
Dir: ctx.ModuleDir(m),
Deps: m.(*bootstrap.GoPackage).Deps(),
}
+ } else if moduleType == "ndk_headers" {
+ ndkHeaders = append(ndkHeaders, m)
}
})
- return ret
+ return buildConversionMetadata{
+ nameToGoLibraryModule: goMap,
+ ndkHeaders: ndkHeaders,
+ }
}
// Returns the deps in the transitive closure of a go target
@@ -620,7 +632,7 @@
Deps: goDepLabels(transitiveDeps, goModulesMap),
Target_compatible_with: targetNotCompatibleWithAndroid(),
}
- libTestSource := goBazelTarget{
+ libTestSource := bTarget{
targetName: goSource,
targetPackage: ctx.ModuleDir(g),
bazelRuleClass: "go_source",
@@ -669,7 +681,7 @@
ga.Srcs = goSrcLabels(ctx.Config(), ctx.ModuleDir(g), g.Srcs(), g.LinuxSrcs(), g.DarwinSrcs())
}
- bin := goBazelTarget{
+ bin := bTarget{
targetName: g.Name(),
targetPackage: ctx.ModuleDir(g),
bazelRuleClass: "go_binary",
@@ -700,7 +712,9 @@
// 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())
+ meta := createBuildConversionMetadata(ctx.Context())
+ nameToGoLibMap := meta.nameToGoLibraryModule
+ ndkHeaders := meta.ndkHeaders
bpCtx := ctx.Context()
bpCtx.VisitAllModules(func(m blueprint.Module) {
@@ -805,6 +819,39 @@
}
})
+ // Create an ndk_sysroot target that has a dependency edge on every target corresponding to Soong's ndk_headers
+ // This root target will provide headers to sdk variants of jni libraries
+ if ctx.Mode() == Bp2Build {
+ var depLabels bazel.LabelList
+ for _, ndkHeader := range ndkHeaders {
+ depLabel := bazel.Label{
+ Label: "//" + bpCtx.ModuleDir(ndkHeader) + ":" + ndkHeader.Name(),
+ }
+ depLabels.Add(&depLabel)
+ }
+ a := struct {
+ Deps bazel.LabelListAttribute
+ System_dynamic_deps bazel.LabelListAttribute
+ }{
+ Deps: bazel.MakeLabelListAttribute(bazel.UniqueSortedBazelLabelList(depLabels)),
+ System_dynamic_deps: bazel.MakeLabelListAttribute(bazel.MakeLabelList([]bazel.Label{})),
+ }
+ ndkSysroot := bTarget{
+ targetName: "ndk_sysroot",
+ targetPackage: "build/bazel/rules/cc", // The location is subject to change, use build/bazel for now
+ bazelRuleClass: "cc_library_headers",
+ bazelRuleLoadLocation: "//build/bazel/rules/cc:cc_library_headers.bzl",
+ bazelAttributes: []interface{}{&a},
+ }
+
+ if t, err := generateBazelTarget(bpCtx, ndkSysroot); err == nil {
+ dir := ndkSysroot.targetPackage
+ buildFileToTargets[dir] = append(buildFileToTargets[dir], t)
+ } else {
+ errs = append(errs, err)
+ }
+ }
+
if len(errs) > 0 {
return conversionResults{}, errs
}