diff options
Diffstat (limited to 'cc')
-rw-r--r-- | cc/binary.go | 4 | ||||
-rw-r--r-- | cc/bp2build.go | 53 | ||||
-rw-r--r-- | cc/cc.go | 50 | ||||
-rw-r--r-- | cc/fdo_profile.go | 51 | ||||
-rw-r--r-- | cc/generated_cc_library.go | 5 | ||||
-rw-r--r-- | cc/library.go | 10 | ||||
-rw-r--r-- | cc/library_headers.go | 9 | ||||
-rw-r--r-- | cc/ndk_headers.go | 49 | ||||
-rw-r--r-- | cc/ndk_library.go | 68 | ||||
-rw-r--r-- | cc/ndk_prebuilt.go | 89 | ||||
-rw-r--r-- | cc/ndk_sysroot.go | 59 | ||||
-rw-r--r-- | cc/object.go | 2 | ||||
-rw-r--r-- | cc/prebuilt.go | 10 | ||||
-rw-r--r-- | cc/sanitize.go | 6 | ||||
-rw-r--r-- | cc/test.go | 2 | ||||
-rw-r--r-- | cc/testing.go | 33 |
16 files changed, 420 insertions, 80 deletions
diff --git a/cc/binary.go b/cc/binary.go index 4606b623e..0722f8110 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -599,7 +599,7 @@ func (handler *ccBinaryBazelHandler) ProcessBazelQueryResponse(ctx android.Modul handler.module.setAndroidMkVariablesFromCquery(info.CcAndroidMkInfo) } -func binaryBp2buildAttrs(ctx android.TopDownMutatorContext, m *Module) binaryAttributes { +func binaryBp2buildAttrs(ctx android.Bp2buildMutatorContext, m *Module) binaryAttributes { baseAttrs := bp2BuildParseBaseProps(ctx, m) binaryLinkerAttrs := bp2buildBinaryLinkerProps(ctx, m) @@ -661,7 +661,7 @@ func binaryBp2buildAttrs(ctx android.TopDownMutatorContext, m *Module) binaryAtt return attrs } -func binaryBp2build(ctx android.TopDownMutatorContext, m *Module) { +func binaryBp2build(ctx android.Bp2buildMutatorContext, m *Module) { // shared with cc_test binaryAttrs := binaryBp2buildAttrs(ctx, m) diff --git a/cc/bp2build.go b/cc/bp2build.go index 039a3cf74..569f721a5 100644 --- a/cc/bp2build.go +++ b/cc/bp2build.go @@ -944,7 +944,10 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) nativeCoverage = BoolPtr(false) } - productVariableProps := android.ProductVariableProperties(ctx, ctx.Module()) + productVariableProps, errs := android.ProductVariableProperties(ctx, ctx.Module()) + for _, err := range errs { + ctx.ModuleErrorf("ProductVariableProperties error: %s", err) + } (&compilerAttrs).convertProductVariables(ctx, productVariableProps) (&linkerAttrs).convertProductVariables(ctx, productVariableProps) @@ -1000,6 +1003,8 @@ func bp2BuildParseBaseProps(ctx android.Bp2buildMutatorContext, module *Module) if module.afdo != nil && module.afdo.Properties.Afdo { fdoProfileDep := bp2buildFdoProfile(ctx, module) if fdoProfileDep != nil { + // TODO(b/276287371): Only set fdo_profile for android platform + // https://cs.android.com/android/platform/superproject/main/+/main:build/soong/cc/afdo.go;l=105;drc=2dbe160d1af445de32725098570ec594e3944fc5 (&compilerAttrs).fdoProfile.SetValue(*fdoProfileDep) } } @@ -1109,22 +1114,15 @@ func bp2buildFdoProfile( ctx android.Bp2buildMutatorContext, m *Module, ) *bazel.Label { + // TODO(b/267229066): Convert to afdo boolean attribute and let Bazel handles finding + // fdo_profile target from AfdoProfiles product var 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. + // Ensure it's a Soong package + bpPath := android.ExistentPathForSource(ctx, project, "Android.bp") + if bpPath.Valid() { // 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, @@ -1583,6 +1581,12 @@ func useStubOrImplInApexWithName(ssi stubSelectionInfo) { } } +// hasNdkStubs returns true for libfoo if there exists a libfoo.ndk of type ndk_library +func hasNdkStubs(ctx android.BazelConversionPathContext, c *Module) bool { + mod, exists := ctx.ModuleFromName(c.Name() + ndkLibrarySuffix) + return exists && ctx.OtherModuleType(mod) == "ndk_library" +} + func SetStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.ConfigurationAxis, config string, apexAvailable []string, dynamicLibs bazel.LabelList, dynamicDeps *bazel.LabelListAttribute, ind int, buildNonApexWithStubs bool) { @@ -1643,6 +1647,29 @@ func SetStubsForDynamicDeps(ctx android.BazelConversionPathContext, axis bazel.C useStubOrImplInApexWithName(ssi) } } + + // If the library has an sdk variant, create additional selects to build this variant against the ndk + // The config setting for this variant will be //build/bazel/rules/apex:unbundled_app + if c, ok := ctx.Module().(*Module); ok && c.Properties.Sdk_version != nil { + for _, l := range dynamicLibs.Includes { + dep, _ := ctx.ModuleFromName(l.OriginalModuleName) + label := l // use the implementation by default + if depC, ok := dep.(*Module); ok && hasNdkStubs(ctx, depC) { + // If the dependency has ndk stubs, build against the ndk stubs + // https://cs.android.com/android/_/android/platform/build/soong/+/main:cc/cc.go;l=2642-2643;drc=e12d252e22dd8afa654325790d3298a0d67bd9d6;bpv=1;bpt=0 + ver := proptools.String(c.Properties.Sdk_version) + // TODO - b/298085502: Add bp2build support for sdk_version: "minimum" + ndkLibModule, _ := ctx.ModuleFromName(dep.Name() + ndkLibrarySuffix) + label = bazel.Label{ + Label: "//" + ctx.OtherModuleDir(ndkLibModule) + ":" + ndkLibModule.Name() + "_stub_libs-" + ver, + } + } + // add the ndk lib label to this axis + existingValue := dynamicDeps.SelectValue(bazel.OsAndInApexAxis, "unbundled_app") + existingValue.Append(bazel.MakeLabelList([]bazel.Label{label})) + dynamicDeps.SetSelectValue(bazel.OsAndInApexAxis, "unbundled_app", bazel.FirstUniqueBazelLabelList(existingValue)) + } + } } func (la *linkerAttributes) convertStripProps(ctx android.BazelConversionPathContext, module *Module) { @@ -589,6 +589,7 @@ type Generator interface { GeneratorFlags(ctx ModuleContext, flags Flags, deps PathDeps) Flags GeneratorSources(ctx ModuleContext) GeneratedSource GeneratorBuildActions(ctx ModuleContext, flags Flags, deps PathDeps) + GeneratorBp2build(ctx android.Bp2buildMutatorContext) bool } // compiler is the interface for a compiler helper object. Different module decorators may implement @@ -879,16 +880,16 @@ type Module struct { installer installer bazelHandler BazelHandler - 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 + pgo *pgo orderfile *orderfile library libraryInterface @@ -1104,6 +1105,16 @@ func (c *Module) CcLibraryInterface() bool { 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())) } @@ -4158,6 +4169,7 @@ const ( headerLibrary testBin // testBinary already declared ndkLibrary + ndkPrebuiltStl ) func (c *Module) typ() moduleType { @@ -4196,12 +4208,24 @@ func (c *Module) typ() moduleType { 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) { +func (c *Module) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { + if len(c.generators) > 0 { + allConverted := true + for _, generator := range c.generators { + allConverted = allConverted && generator.GeneratorBp2build(ctx) + } + if allConverted { + return + } + } + prebuilt := c.IsPrebuilt() switch c.typ() { case binary: @@ -4240,6 +4264,10 @@ func (c *Module) ConvertWithBp2build(ctx android.TopDownMutatorContext) { } else { sharedOrStaticLibraryBp2Build(ctx, c, false) } + case ndkPrebuiltStl: + ndkPrebuiltStlBp2build(ctx, c) + case ndkLibrary: + ndkLibraryBp2build(ctx, c) default: ctx.MarkBp2buildUnconvertible(bp2build_metrics_proto.UnconvertedReasonType_TYPE_UNSUPPORTED, "") } diff --git a/cc/fdo_profile.go b/cc/fdo_profile.go index 7fbe71940..05a8f464b 100644 --- a/cc/fdo_profile.go +++ b/cc/fdo_profile.go @@ -16,8 +16,10 @@ package cc import ( "android/soong/android" + "android/soong/bazel" "github.com/google/blueprint" + "github.com/google/blueprint/proptools" ) func init() { @@ -25,11 +27,12 @@ func init() { } func RegisterFdoProfileBuildComponents(ctx android.RegistrationContext) { - ctx.RegisterModuleType("fdo_profile", fdoProfileFactory) + ctx.RegisterModuleType("fdo_profile", FdoProfileFactory) } type fdoProfile struct { android.ModuleBase + android.BazelModuleBase properties fdoProfileProperties } @@ -38,6 +41,49 @@ type fdoProfileProperties struct { Profile *string `android:"arch_variant"` } +type bazelFdoProfileAttributes struct { + Profile bazel.StringAttribute +} + +func (fp *fdoProfile) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { + var profileAttr bazel.StringAttribute + + archVariantProps := fp.GetArchVariantProperties(ctx, &fdoProfileProperties{}) + for axis, configToProps := range archVariantProps { + for config, _props := range configToProps { + if archProps, ok := _props.(*fdoProfileProperties); ok { + if axis.String() == "arch" || axis.String() == "no_config" { + if archProps.Profile != nil { + profileAttr.SetSelectValue(axis, config, archProps.Profile) + } + } + } + } + } + + // Ideally, cc_library_shared's fdo_profile attr can be a select statement so that we + // don't lift the restriction here. However, in cc_library_shared macro, fdo_profile + // is used as a string, we need to temporarily lift the host restriction until we can + // pass use fdo_profile attr with select statement + // https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/cc/cc_library_shared.bzl;l=127;drc=cc01bdfd39857eddbab04ef69ab6db22dcb1858a + // TODO(b/276287371): Drop the restriction override after fdo_profile path is handled properly + var noRestriction bazel.BoolAttribute + noRestriction.SetSelectValue(bazel.NoConfigAxis, "", proptools.BoolPtr(true)) + + ctx.CreateBazelTargetModuleWithRestrictions( + bazel.BazelTargetModuleProperties{ + Rule_class: "fdo_profile", + }, + android.CommonAttributes{ + Name: fp.Name(), + }, + &bazelFdoProfileAttributes{ + Profile: profileAttr, + }, + noRestriction, + ) +} + // FdoProfileInfo is provided by FdoProfileProvider type FdoProfileInfo struct { Path android.Path @@ -77,9 +123,10 @@ func fdoProfileMutator(ctx android.BottomUpMutatorContext) { } } -func fdoProfileFactory() android.Module { +func FdoProfileFactory() android.Module { m := &fdoProfile{} m.AddProperties(&m.properties) android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, android.MultilibBoth) + android.InitBazelModule(m) return m } diff --git a/cc/generated_cc_library.go b/cc/generated_cc_library.go index 55e19f9a9..8428e9420 100644 --- a/cc/generated_cc_library.go +++ b/cc/generated_cc_library.go @@ -28,9 +28,8 @@ func GeneratedCcLibraryModuleFactory(moduleName string, callbacks Generator) and staticAndSharedLibrarySdkMemberType, } - // TODO: Need to be bazelable - // module.bazelable = true - // module.bazelHandler = &ccLibraryBazelHandler{module: module} + module.bazelable = true + module.bazelHandler = &ccLibraryBazelHandler{module: module} module.generators = append(module.generators, callbacks) diff --git a/cc/library.go b/cc/library.go index 2d4d60440..b9dc71b32 100644 --- a/cc/library.go +++ b/cc/library.go @@ -308,7 +308,7 @@ func stripAttrsFromLinkerAttrs(la *linkerAttributes) stripAttributes { } } -func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) { +func libraryBp2Build(ctx android.Bp2buildMutatorContext, m *Module) { sharedAttrs := bp2BuildParseSharedProps(ctx, m) staticAttrs := bp2BuildParseStaticProps(ctx, m) baseAttributes := bp2BuildParseBaseProps(ctx, m) @@ -480,7 +480,7 @@ func libraryBp2Build(ctx android.TopDownMutatorContext, m *Module) { createStubsBazelTargetIfNeeded(ctx, m, compilerAttrs, exportedIncludes, baseAttributes) } -func createStubsBazelTargetIfNeeded(ctx android.TopDownMutatorContext, m *Module, compilerAttrs compilerAttributes, exportedIncludes BazelIncludes, baseAttributes baseAttributes) { +func createStubsBazelTargetIfNeeded(ctx android.Bp2buildMutatorContext, 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", @@ -494,6 +494,7 @@ func createStubsBazelTargetIfNeeded(ctx android.TopDownMutatorContext, m *Module Soname: &soname, Source_library_label: proptools.StringPtr(m.GetBazelLabel(ctx, m)), Deps: baseAttributes.deps, + Api_surface: proptools.StringPtr("module-libapi"), } ctx.CreateBazelTargetModule(stubSuitesProps, android.CommonAttributes{Name: m.Name() + "_stub_libs"}, @@ -2885,7 +2886,7 @@ func maybeInjectBoringSSLHash(ctx android.ModuleContext, outputFile android.Modu return outputFile } -func bp2buildParseAbiCheckerProps(ctx android.TopDownMutatorContext, module *Module) bazelCcHeaderAbiCheckerAttributes { +func bp2buildParseAbiCheckerProps(ctx android.Bp2buildMutatorContext, module *Module) bazelCcHeaderAbiCheckerAttributes { lib, ok := module.linker.(*libraryDecorator) if !ok { return bazelCcHeaderAbiCheckerAttributes{} @@ -2908,7 +2909,7 @@ func bp2buildParseAbiCheckerProps(ctx android.TopDownMutatorContext, module *Mod return abiCheckerAttrs } -func sharedOrStaticLibraryBp2Build(ctx android.TopDownMutatorContext, module *Module, isStatic bool) { +func sharedOrStaticLibraryBp2Build(ctx android.Bp2buildMutatorContext, module *Module, isStatic bool) { baseAttributes := bp2BuildParseBaseProps(ctx, module) compilerAttrs := baseAttributes.compilerAttributes linkerAttrs := baseAttributes.linkerAttributes @@ -3121,6 +3122,7 @@ type bazelCcStubSuiteAttributes struct { Source_library_label *string Soname *string Deps bazel.LabelListAttribute + Api_surface *string } type bazelCcHeaderAbiCheckerAttributes struct { diff --git a/cc/library_headers.go b/cc/library_headers.go index ce9c4aacf..5eba6ab96 100644 --- a/cc/library_headers.go +++ b/cc/library_headers.go @@ -129,7 +129,7 @@ type bazelCcLibraryHeadersAttributes struct { sdkAttributes } -func libraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) { +func libraryHeadersBp2Build(ctx android.Bp2buildMutatorContext, module *Module) { baseAttributes := bp2BuildParseBaseProps(ctx, module) exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, &baseAttributes.includes) linkerAttrs := baseAttributes.linkerAttributes @@ -153,8 +153,13 @@ func libraryHeadersBp2Build(ctx android.TopDownMutatorContext, module *Module) { tags := android.ApexAvailableTagsWithoutTestApexes(ctx, module) + name := module.Name() + if module.IsPrebuilt() { + name = android.RemoveOptionalPrebuiltPrefix(name) + } + ctx.CreateBazelTargetModule(props, android.CommonAttributes{ - Name: module.Name(), + Name: name, Tags: tags, }, attrs) } diff --git a/cc/ndk_headers.go b/cc/ndk_headers.go index d0ae4a56d..da5db1c19 100644 --- a/cc/ndk_headers.go +++ b/cc/ndk_headers.go @@ -21,6 +21,7 @@ import ( "github.com/google/blueprint" "android/soong/android" + "android/soong/bazel" ) var ( @@ -79,9 +80,11 @@ type headerProperties struct { type headerModule struct { android.ModuleBase + android.BazelModuleBase properties headerProperties + srcPaths android.Paths installPaths android.Paths licensePath android.Path } @@ -125,8 +128,8 @@ func (m *headerModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 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) @@ -144,6 +147,29 @@ func (m *headerModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { } } +type bazelNdkHeadersAttributes struct { + Strip_import_prefix *string + Import_prefix *string + Hdrs bazel.LabelListAttribute +} + +func (h *headerModule) ConvertWithBp2build(ctx android.Bp2buildMutatorContext) { + props := bazel.BazelTargetModuleProperties{ + Rule_class: "ndk_headers", + Bzl_load_location: "//build/bazel/rules/cc:ndk_headers.bzl", + } + attrs := &bazelNdkHeadersAttributes{ + Strip_import_prefix: h.properties.From, + Import_prefix: h.properties.To, + Hdrs: bazel.MakeLabelListAttribute(android.BazelLabelForModuleSrcExcludes(ctx, h.properties.Srcs, h.properties.Exclude_srcs)), + } + ctx.CreateBazelTargetModule( + props, + android.CommonAttributes{Name: h.Name()}, + attrs, + ) +} + // ndk_headers installs the sets of ndk headers defined in the srcs property // to the sysroot base + "usr/include" + to directory + directory component. // ndk_headers requires the license file to be specified. Example: @@ -154,10 +180,11 @@ func (m *headerModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { // 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) + android.InitBazelModule(module) return module } @@ -193,6 +220,7 @@ type versionedHeaderModule struct { properties versionedHeaderProperties + srcPaths android.Paths installPaths android.Paths licensePath android.Path } @@ -211,9 +239,9 @@ func (m *versionedHeaderModule) GenerateAndroidBuildActions(ctx android.ModuleCo 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 +252,11 @@ func (m *versionedHeaderModule) GenerateAndroidBuildActions(ctx android.ModuleCo 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 +281,7 @@ func processHeadersWithVersioner(ctx android.ModuleContext, srcDir, outDir andro 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(), @@ -317,6 +345,7 @@ type preprocessedHeadersModule struct { properties preprocessedHeadersProperties + srcPaths android.Paths installPaths android.Paths licensePath android.Path } @@ -329,9 +358,9 @@ func (m *preprocessedHeadersModule) GenerateAndroidBuildActions(ctx android.Modu 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 9281aebb5..b3bb2da15 100644 --- a/cc/ndk_library.go +++ b/cc/ndk_library.go @@ -43,11 +43,17 @@ var ( 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{ @@ -347,14 +353,19 @@ func (this *stubDecorator) dumpAbi(ctx ModuleContext, symbolList android.Path) { 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(), }, }) } @@ -404,7 +415,7 @@ func (this *stubDecorator) diffAbi(ctx ModuleContext) { // 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 "+ @@ -424,10 +435,12 @@ func (this *stubDecorator) diffAbi(ctx ModuleContext) { } 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", }, @@ -570,3 +583,40 @@ func apiHeaderLabels(ctx android.TopDownMutatorContext, hdrLibs []string) bazel. } return android.BazelLabelForModuleDepsWithFn(ctx, hdrLibs, addSuffix) } + +func ndkLibraryBp2build(ctx android.Bp2buildMutatorContext, c *Module) { + ndk, _ := c.linker.(*stubDecorator) + props := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_stub_suite", + Bzl_load_location: "//build/bazel/rules/cc:cc_stub_library.bzl", + } + sourceLibraryName := strings.TrimSuffix(c.Name(), ".ndk") + fromApiLevel, err := android.ApiLevelFromUser(ctx, proptools.String(ndk.properties.First_version)) + if err != nil { + ctx.PropertyErrorf("first_version", "error converting first_version %v", proptools.String(ndk.properties.First_version)) + } + symbolFileLabel := android.BazelLabelForModuleSrcSingle(ctx, proptools.String(ndk.properties.Symbol_file)) + attrs := &bazelCcStubSuiteAttributes{ + // TODO - b/300504837 Add ndk headers + Symbol_file: proptools.StringPtr(symbolFileLabel.Label), + Soname: proptools.StringPtr(sourceLibraryName + ".so"), + Api_surface: proptools.StringPtr(android.PublicApi.String()), + } + if sourceLibrary, exists := ctx.ModuleFromName(sourceLibraryName); exists { + // the source library might not exist in minimal/unbuildable branches like kernel-build-tools. + // check for its existence + attrs.Source_library_label = proptools.StringPtr(c.GetBazelLabel(ctx, sourceLibrary)) + } + if ctx.Config().RawPlatformSdkVersion() != nil { + // This is a hack to populate `versions` only on branches that set a platform_sdk_version + // This prevents errors on branches such as kernel-build-tools + // This hack is acceptable since we are not required to support NDK Bazel builds on those branches + attrs.Versions = bazel.MakeStringListAttribute(ndkLibraryVersions(ctx, fromApiLevel)) + } + + ctx.CreateBazelTargetModule( + props, + android.CommonAttributes{Name: c.Name() + "_stub_libs"}, + attrs, + ) +} diff --git a/cc/ndk_prebuilt.go b/cc/ndk_prebuilt.go index d3a0a002e..c3e65106a 100644 --- a/cc/ndk_prebuilt.go +++ b/cc/ndk_prebuilt.go @@ -15,9 +15,11 @@ package cc import ( + "path/filepath" "strings" "android/soong/android" + "android/soong/bazel" ) func init() { @@ -64,6 +66,7 @@ func NdkPrebuiltSharedStlFactory() android.Module { module.Properties.Sdk_version = StringPtr("minimum") module.Properties.AlwaysSdk = true module.stl.Properties.Stl = StringPtr("none") + module.bazelable = true return module.Init() } @@ -84,12 +87,16 @@ func NdkPrebuiltStaticStlFactory() android.Module { module.Properties.AlwaysSdk = true module.Properties.Sdk_version = StringPtr("current") module.stl.Properties.Stl = StringPtr("none") + module.bazelable = true 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, @@ -128,3 +135,81 @@ func (ndk *ndkPrebuiltStlLinker) link(ctx ModuleContext, flags Flags, return lib } + +var ( + archToAbiDirMap = map[string]string{ + "android_arm": "armeabi-v7a", + "android_arm64": "arm64-v8a", + "android_riscv64": "riscv64", + "android_x86": "x86", + "android_x86_64": "x86_64", + } +) + +// stlSrcBp2build returns a bazel label for the checked-in .so/.a file +// It contains a select statement for each ABI +func stlSrcBp2build(ctx android.Bp2buildMutatorContext, c *Module) bazel.LabelAttribute { + libName := strings.TrimPrefix(c.Name(), "ndk_") + libExt := ".so" // TODO - b/201079053: Support windows + if ctx.ModuleType() == "ndk_prebuilt_static_stl" { + libExt = ".a" + } + src := bazel.LabelAttribute{} + for arch, abiDir := range archToAbiDirMap { + srcPath := filepath.Join(libDir, abiDir, libName+libExt) + src.SetSelectValue( + bazel.OsArchConfigurationAxis, + arch, + android.BazelLabelForModuleSrcSingle(ctx, srcPath), + ) + } + return src +} + +// stlIncludesBp2build returns the includes exported by the STL +func stlIncludesBp2build(c *Module) bazel.StringListAttribute { + linker, _ := c.linker.(*ndkPrebuiltStlLinker) + includeDirs := append( + []string{}, + linker.libraryDecorator.flagExporter.Properties.Export_include_dirs..., + ) + includeDirs = append( + includeDirs, + linker.libraryDecorator.flagExporter.Properties.Export_system_include_dirs..., + ) + return bazel.MakeStringListAttribute(android.FirstUniqueStrings(includeDirs)) +} + +func ndkPrebuiltStlBp2build(ctx android.Bp2buildMutatorContext, c *Module) { + if ctx.ModuleType() == "ndk_prebuilt_static_stl" { + ndkPrebuiltStaticStlBp2build(ctx, c) + } else { + ndkPrebuiltSharedStlBp2build(ctx, c) + } +} + +func ndkPrebuiltStaticStlBp2build(ctx android.Bp2buildMutatorContext, c *Module) { + props := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_prebuilt_library_static", + Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_library_static.bzl", + } + attrs := &bazelPrebuiltLibraryStaticAttributes{ + Static_library: stlSrcBp2build(ctx, c), + Export_system_includes: stlIncludesBp2build(c), // The exports are always as system + } + // TODO: min_sdk_version + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: c.Name()}, attrs) +} + +func ndkPrebuiltSharedStlBp2build(ctx android.Bp2buildMutatorContext, c *Module) { + props := bazel.BazelTargetModuleProperties{ + Rule_class: "cc_prebuilt_library_shared", + Bzl_load_location: "//build/bazel/rules/cc:cc_prebuilt_library_shared.bzl", + } + attrs := &bazelPrebuiltLibrarySharedAttributes{ + Shared_library: stlSrcBp2build(ctx, c), + Export_system_includes: stlIncludesBp2build(c), // The exports are always as system + } + // TODO: min_sdk_version + ctx.CreateBazelTargetModule(props, android.CommonAttributes{Name: c.Name()}, attrs) +} diff --git a/cc/ndk_sysroot.go b/cc/ndk_sysroot.go index feb388037..54a2ee267 100644 --- a/cc/ndk_sysroot.go +++ b/cc/ndk_sysroot.go @@ -54,6 +54,7 @@ package cc import ( "android/soong/android" + "strings" ) func init() { @@ -61,7 +62,7 @@ func init() { } 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("preprocessed_ndk_headers", preprocessedNdkHeadersFactory) @@ -96,15 +97,56 @@ func getNdkFullTimestampFile(ctx android.PathContext) android.WritablePath { 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 @@ func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) { } 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 @@ func (n *ndkSingleton) GenerateBuildActions(ctx android.SingletonContext) { 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 ca1484538..a3000e06e 100644 --- a/cc/object.go +++ b/cc/object.go @@ -156,7 +156,7 @@ type bazelObjectAttributes struct { // 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) { +func objectBp2Build(ctx android.Bp2buildMutatorContext, 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") diff --git a/cc/prebuilt.go b/cc/prebuilt.go index a4ca59050..b4819b013 100644 --- a/cc/prebuilt.go +++ b/cc/prebuilt.go @@ -363,12 +363,12 @@ type bazelPrebuiltLibraryStaticAttributes struct { // 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) { +func prebuiltLibraryBp2Build(ctx android.Bp2buildMutatorContext, module *Module) { prebuiltLibraryStaticBp2Build(ctx, module, true) prebuiltLibrarySharedBp2Build(ctx, module) } -func prebuiltLibraryStaticBp2Build(ctx android.TopDownMutatorContext, module *Module, fullBuild bool) { +func prebuiltLibraryStaticBp2Build(ctx android.Bp2buildMutatorContext, module *Module, fullBuild bool) { prebuiltAttrs := Bp2BuildParsePrebuiltLibraryProps(ctx, module, true) exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, nil) @@ -404,7 +404,7 @@ type bazelPrebuiltLibrarySharedAttributes struct { Export_system_includes bazel.StringListAttribute } -func prebuiltLibrarySharedBp2Build(ctx android.TopDownMutatorContext, module *Module) { +func prebuiltLibrarySharedBp2Build(ctx android.Bp2buildMutatorContext, module *Module) { prebuiltAttrs := Bp2BuildParsePrebuiltLibraryProps(ctx, module, false) exportedIncludes := bp2BuildParseExportedIncludes(ctx, module, nil) @@ -637,7 +637,7 @@ type bazelPrebuiltObjectAttributes struct { Src bazel.LabelAttribute } -func prebuiltObjectBp2Build(ctx android.TopDownMutatorContext, module *Module) { +func prebuiltObjectBp2Build(ctx android.Bp2buildMutatorContext, module *Module) { prebuiltAttrs := bp2BuildParsePrebuiltObjectProps(ctx, module) attrs := &bazelPrebuiltObjectAttributes{ @@ -797,7 +797,7 @@ type bazelPrebuiltBinaryAttributes struct { Strip stripAttributes } -func prebuiltBinaryBp2Build(ctx android.TopDownMutatorContext, module *Module) { +func prebuiltBinaryBp2Build(ctx android.Bp2buildMutatorContext, module *Module) { prebuiltAttrs := bp2BuildParsePrebuiltBinaryProps(ctx, module) var la linkerAttributes diff --git a/cc/sanitize.go b/cc/sanitize.go index 0abdafc32..9ceb1c8a0 100644 --- a/cc/sanitize.go +++ b/cc/sanitize.go @@ -679,12 +679,6 @@ func (sanitize *sanitize) begin(ctx BaseModuleContext) { 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 diff --git a/cc/test.go b/cc/test.go index ae621287c..7a6cf1b4e 100644 --- a/cc/test.go +++ b/cc/test.go @@ -700,7 +700,7 @@ type testBinaryAttributes struct { // 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) { +func testBinaryBp2build(ctx android.Bp2buildMutatorContext, m *Module) { var testBinaryAttrs testBinaryAttributes testBinaryAttrs.binaryAttributes = binaryBp2buildAttrs(ctx, m) diff --git a/cc/testing.go b/cc/testing.go index d1632aaa6..36bc261e0 100644 --- a/cc/testing.go +++ b/cc/testing.go @@ -35,13 +35,14 @@ func RegisterRequiredBuildComponentsForTest(ctx android.RegistrationContext) { 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 { @@ -67,6 +68,26 @@ func GatherRequiredDepsForTest(oses ...android.OsType) string { func commonDefaultModules() string { return ` + prebuilt_build_tool { + name: "clang++", + src: "bin/clang++", + } + prebuilt_build_tool { + name: "clang++.real", + src: "bin/clang++.real", + } + prebuilt_build_tool { + name: "lld", + src: "bin/lld", + } + prebuilt_build_tool { + name: "ld.lld", + src: "bin/ld.lld", + } + prebuilt_build_tool { + name: "llvm-ar", + src: "bin/llvm-ar", + } cc_defaults { name: "toolchain_libs_defaults", host_supported: true, @@ -558,7 +579,7 @@ var PrepareForTestWithCcBuildComponents = android.GroupFixturePreparers( // 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(), ) @@ -568,6 +589,12 @@ var PrepareForTestWithCcDefaultModules = android.GroupFixturePreparers( // Additional files needed in tests that disallow non-existent source. android.MockFS{ + "defaults/cc/common/bin/clang++": nil, + "defaults/cc/common/bin/clang++.real": nil, + "defaults/cc/common/bin/lld": nil, + "defaults/cc/common/bin/ld.lld": nil, + "defaults/cc/common/bin/llvm-ar": nil, + "defaults/cc/common/libc.map.txt": nil, "defaults/cc/common/libdl.map.txt": nil, "defaults/cc/common/libm.map.txt": nil, @@ -671,7 +698,7 @@ var PrepareForTestWithHostMusl = android.GroupFixturePreparers( // 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. |