diff options
Diffstat (limited to 'android/filegroup.go')
| -rw-r--r-- | android/filegroup.go | 280 |
1 files changed, 25 insertions, 255 deletions
diff --git a/android/filegroup.go b/android/filegroup.go index f30ee5143..ff0f74e99 100644 --- a/android/filegroup.go +++ b/android/filegroup.go @@ -15,14 +15,11 @@ package android import ( - "path/filepath" - "regexp" + "maps" "strings" - "android/soong/bazel" - "android/soong/bazel/cquery" - "github.com/google/blueprint" + "github.com/google/blueprint/proptools" ) func init() { @@ -38,150 +35,11 @@ func RegisterFilegroupBuildComponents(ctx RegistrationContext) { 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 - Deps bazel.LabelListAttribute -} - -// 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()) - } - 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"} - deps := bazel.MakeLabelListAttribute(BazelLabelForModuleDeps(ctx, fg.properties.Aidl.Deps)) - - attrs := &bazelAidlLibraryAttributes{ - Srcs: srcs, - Strip_import_prefix: fg.properties.Path, - Deps: deps, - } - - 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) { - attrs := &ProtoAttrs{ - Srcs: srcs, - 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", - } - ctx.CreateBazelTargetModule( - bazel.BazelTargetModuleProperties{Rule_class: "proto_library"}, - CommonAttributes{ - Name: fg.Name() + convertedProtoLibrarySuffix, - Tags: bazel.MakeStringListAttribute(tags), - }, - attrs) - } - - // 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 fileGroupProperties struct { // srcs lists files that will be included in this filegroup - Srcs []string `android:"path"` + Srcs proptools.Configurable[[]string] `android:"path"` - Exclude_srcs []string `android:"path"` + Exclude_srcs proptools.Configurable[[]string] `android:"path"` // The base path to the files. May be used by other modules to determine which portion // of the path to use. For example, when a filegroup is used as data in a cc_test rule, @@ -192,28 +50,16 @@ type fileGroupProperties struct { // Create a make variable with the specified name that contains the list of files in the // filegroup, relative to the root of the source tree. Export_to_make_var *string - - // aidl is explicitly provided for implicit aidl dependencies - // TODO(b/278298615): aidl prop is a no-op in Soong and is an escape hatch - // to include implicit aidl dependencies for bazel migration compatibility - Aidl struct { - // List of aidl files or filegroup depended on by srcs - Deps []string `android:"path"` - } } type fileGroup struct { ModuleBase - BazelModuleBase DefaultableModuleBase - FileGroupAsLibrary properties fileGroupProperties srcs Paths } -var _ MixedBuildBuildable = (*fileGroup)(nil) var _ SourceFileProducer = (*fileGroup)(nil) -var _ FileGroupAsLibrary = (*fileGroup)(nil) // filegroup contains a list of files that are referenced by other modules // properties (such as "srcs") using the syntax ":<name>". filegroup are @@ -222,7 +68,6 @@ func FileGroupFactory() Module { module := &fileGroup{} module.AddProperties(&module.properties) InitAndroidModule(module) - InitBazelModule(module) InitDefaultableModule(module) return module } @@ -245,10 +90,30 @@ func (fg *fileGroup) JSONActions() []blueprint.JSONAction { } func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) { - fg.srcs = PathsForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs) + fg.srcs = PathsForModuleSrcExcludes(ctx, fg.properties.Srcs.GetOrDefault(ctx, nil), fg.properties.Exclude_srcs.GetOrDefault(ctx, nil)) 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()}) + + var aconfigDeclarations []string + var intermediateCacheOutputPaths Paths + var srcjars Paths + modeInfos := make(map[string]ModeInfo) + ctx.VisitDirectDeps(func(module Module) { + if dep, ok := OtherModuleProvider(ctx, module, CodegenInfoProvider); ok { + aconfigDeclarations = append(aconfigDeclarations, dep.AconfigDeclarations...) + intermediateCacheOutputPaths = append(intermediateCacheOutputPaths, dep.IntermediateCacheOutputPaths...) + srcjars = append(srcjars, dep.Srcjars...) + maps.Copy(modeInfos, dep.ModeInfos) + } + }) + SetProvider(ctx, CodegenInfoProvider, CodegenInfo{ + AconfigDeclarations: aconfigDeclarations, + IntermediateCacheOutputPaths: intermediateCacheOutputPaths, + Srcjars: srcjars, + ModeInfos: modeInfos, + }) } func (fg *fileGroup) Srcs() Paths { @@ -261,101 +126,6 @@ func (fg *fileGroup) MakeVars(ctx MakeVarsModuleContext) { } } -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 |