diff --git a/bp2build/cc_library_static_conversion_test.go b/bp2build/cc_library_static_conversion_test.go index 8084a5d8e..03e9cd060 100644 --- a/bp2build/cc_library_static_conversion_test.go +++ b/bp2build/cc_library_static_conversion_test.go @@ -1003,6 +1003,38 @@ cc_library_static { }) } +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) { diff --git a/bp2build/genrule_conversion_test.go b/bp2build/genrule_conversion_test.go index 5cf4fb216..5a739699a 100644 --- a/bp2build/genrule_conversion_test.go +++ b/bp2build/genrule_conversion_test.go @@ -16,6 +16,7 @@ package bp2build import ( "fmt" + "path/filepath" "testing" "android/soong/android" @@ -695,3 +696,79 @@ func TestCcGenruleArchAndExcludeSrcs(t *testing.T) { }) }) } + +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, + }) + }) + } +} diff --git a/cc/bp2build.go b/cc/bp2build.go index 9895a2043..9e485d6d0 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -22,6 +22,7 @@ import ( "android/soong/android" "android/soong/bazel" "android/soong/cc/config" + "android/soong/genrule" "github.com/google/blueprint" @@ -45,6 +46,8 @@ const ( xsdSrcPartition = "xsd" + genrulePartition = "genrule" + hdrPartition = "hdr" stubsSuffix = "_stub_libs_current" @@ -172,8 +175,9 @@ func groupSrcsByExtension(ctx android.BazelConversionPathContext, srcs bazel.Lab func partitionHeaders(ctx android.BazelConversionPathContext, hdrs bazel.LabelListAttribute) bazel.PartitionToLabelListAttribute { labels := bazel.LabelPartitions{ - xsdSrcPartition: bazel.LabelPartition{LabelMapper: android.XsdLabelMapper(xsdConfigCppTarget)}, - hdrPartition: bazel.LabelPartition{Keep_remainder: true}, + 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) } @@ -419,6 +423,10 @@ type compilerAttributes struct { xsdSrcs bazel.LabelListAttribute exportXsdSrcs bazel.LabelListAttribute + // genrule headers + genruleHeaders bazel.LabelListAttribute + exportGenruleHeaders bazel.LabelListAttribute + // Lex sources and options lSrcs bazel.LabelListAttribute llSrcs bazel.LabelListAttribute @@ -606,6 +614,9 @@ func (ca *compilerAttributes) finalize(ctx android.BazelConversionPathContext, i 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] @@ -900,6 +911,9 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) (&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) diff --git a/genrule/genrule.go b/genrule/genrule.go index 6306c2750..69ba1e94e 100644 --- a/genrule/genrule.go +++ b/genrule/genrule.go @@ -994,6 +994,7 @@ func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { tags := android.ApexAvailableTagsWithoutTestApexes(ctx, m) + bazelName := m.Name() if ctx.ModuleType() == "gensrcs" { props := bazel.BazelTargetModuleProperties{ Rule_class: "gensrcs", @@ -1021,7 +1022,6 @@ func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { break } } - bazelName := m.Name() for _, out := range outs { if out == bazelName { // This is a workaround to circumvent a Bazel warning where a genrule's @@ -1046,6 +1046,54 @@ func (m *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { 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 } var Bool = proptools.Bool @@ -1099,6 +1147,7 @@ func getSandboxingAllowlistSets(ctx android.PathContext) *sandboxingAllowlistSet } }).(*sandboxingAllowlistSets) } + func getSandboxedRuleBuilder(ctx android.ModuleContext, r *android.RuleBuilder) *android.RuleBuilder { if !ctx.DeviceConfig().GenruleSandboxing() { return r.SandboxTools()