• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2016 Google Inc. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package android
16
17import (
18	"strings"
19
20	"android/soong/bazel"
21
22	"github.com/google/blueprint"
23)
24
25func init() {
26	RegisterModuleType("filegroup", FileGroupFactory)
27}
28
29var PrepareForTestWithFilegroup = FixtureRegisterWithContext(func(ctx RegistrationContext) {
30	ctx.RegisterModuleType("filegroup", FileGroupFactory)
31})
32
33// IsFilegroup checks that a module is a filegroup type
34func IsFilegroup(ctx bazel.OtherModuleContext, m blueprint.Module) bool {
35	return ctx.OtherModuleType(m) == "filegroup"
36}
37
38// https://docs.bazel.build/versions/master/be/general.html#filegroup
39type bazelFilegroupAttributes struct {
40	Srcs bazel.LabelListAttribute
41}
42
43// ConvertWithBp2build performs bp2build conversion of filegroup
44func (fg *fileGroup) ConvertWithBp2build(ctx TopDownMutatorContext) {
45	srcs := bazel.MakeLabelListAttribute(
46		BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs))
47
48	// For Bazel compatibility, don't generate the filegroup if there is only 1
49	// source file, and that the source file is named the same as the module
50	// itself. In Bazel, eponymous filegroups like this would be an error.
51	//
52	// Instead, dependents on this single-file filegroup can just depend
53	// on the file target, instead of rule target, directly.
54	//
55	// You may ask: what if a filegroup has multiple files, and one of them
56	// shares the name? The answer: we haven't seen that in the wild, and
57	// should lock Soong itself down to prevent the behavior. For now,
58	// we raise an error if bp2build sees this problem.
59	for _, f := range srcs.Value.Includes {
60		if f.Label == fg.Name() {
61			if len(srcs.Value.Includes) > 1 {
62				ctx.ModuleErrorf("filegroup '%s' cannot contain a file with the same name", fg.Name())
63			}
64			return
65		}
66	}
67
68	attrs := &bazelFilegroupAttributes{
69		Srcs: srcs,
70	}
71
72	props := bazel.BazelTargetModuleProperties{
73		Rule_class:        "filegroup",
74		Bzl_load_location: "//build/bazel/rules:filegroup.bzl",
75	}
76
77	ctx.CreateBazelTargetModule(props, CommonAttributes{Name: fg.Name()}, attrs)
78}
79
80type fileGroupProperties struct {
81	// srcs lists files that will be included in this filegroup
82	Srcs []string `android:"path"`
83
84	Exclude_srcs []string `android:"path"`
85
86	// The base path to the files.  May be used by other modules to determine which portion
87	// of the path to use.  For example, when a filegroup is used as data in a cc_test rule,
88	// the base path is stripped off the path and the remaining path is used as the
89	// installation directory.
90	Path *string
91
92	// Create a make variable with the specified name that contains the list of files in the
93	// filegroup, relative to the root of the source tree.
94	Export_to_make_var *string
95}
96
97type fileGroup struct {
98	ModuleBase
99	BazelModuleBase
100	properties fileGroupProperties
101	srcs       Paths
102}
103
104var _ SourceFileProducer = (*fileGroup)(nil)
105
106// filegroup contains a list of files that are referenced by other modules
107// properties (such as "srcs") using the syntax ":<name>". filegroup are
108// also be used to export files across package boundaries.
109func FileGroupFactory() Module {
110	module := &fileGroup{}
111	module.AddProperties(&module.properties)
112	InitAndroidModule(module)
113	InitBazelModule(module)
114	return module
115}
116
117func (fg *fileGroup) maybeGenerateBazelBuildActions(ctx ModuleContext) {
118	if !fg.MixedBuildsEnabled(ctx) {
119		return
120	}
121
122	archVariant := ctx.Arch().String()
123	osVariant := ctx.Os()
124	if len(fg.Srcs()) == 1 && fg.Srcs()[0].Base() == fg.Name() {
125		// This will be a regular file target, not filegroup, in Bazel.
126		// See FilegroupBp2Build for more information.
127		archVariant = Common.String()
128		osVariant = CommonOS
129	}
130
131	bazelCtx := ctx.Config().BazelContext
132	filePaths, ok := bazelCtx.GetOutputFiles(fg.GetBazelLabel(ctx, fg), configKey{archVariant, osVariant})
133	if !ok {
134		return
135	}
136
137	bazelOuts := make(Paths, 0, len(filePaths))
138	for _, p := range filePaths {
139		src := PathForBazelOut(ctx, p)
140		bazelOuts = append(bazelOuts, src)
141	}
142
143	fg.srcs = bazelOuts
144}
145
146func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) {
147	fg.srcs = PathsForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs)
148	if fg.properties.Path != nil {
149		fg.srcs = PathsWithModuleSrcSubDir(ctx, fg.srcs, String(fg.properties.Path))
150	}
151
152	fg.maybeGenerateBazelBuildActions(ctx)
153}
154
155func (fg *fileGroup) Srcs() Paths {
156	return append(Paths{}, fg.srcs...)
157}
158
159func (fg *fileGroup) MakeVars(ctx MakeVarsModuleContext) {
160	if makeVar := String(fg.properties.Export_to_make_var); makeVar != "" {
161		ctx.StrictRaw(makeVar, strings.Join(fg.srcs.Strings(), " "))
162	}
163}
164