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	"android/soong/bazel"
19	"strings"
20)
21
22func init() {
23	RegisterModuleType("filegroup", FileGroupFactory)
24	RegisterBp2BuildMutator("filegroup", FilegroupBp2Build)
25}
26
27var PrepareForTestWithFilegroup = FixtureRegisterWithContext(func(ctx RegistrationContext) {
28	ctx.RegisterModuleType("filegroup", FileGroupFactory)
29})
30
31// https://docs.bazel.build/versions/master/be/general.html#filegroup
32type bazelFilegroupAttributes struct {
33	Srcs bazel.LabelListAttribute
34}
35
36type bazelFilegroup struct {
37	BazelTargetModuleBase
38	bazelFilegroupAttributes
39}
40
41func BazelFileGroupFactory() Module {
42	module := &bazelFilegroup{}
43	module.AddProperties(&module.bazelFilegroupAttributes)
44	InitBazelTargetModule(module)
45	return module
46}
47
48func (bfg *bazelFilegroup) Name() string {
49	return bfg.BaseModuleName()
50}
51
52func (bfg *bazelFilegroup) GenerateAndroidBuildActions(ctx ModuleContext) {}
53
54func FilegroupBp2Build(ctx TopDownMutatorContext) {
55	fg, ok := ctx.Module().(*fileGroup)
56	if !ok || !fg.ConvertWithBp2build(ctx) {
57		return
58	}
59
60	srcs := bazel.MakeLabelListAttribute(
61		BazelLabelForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs))
62	attrs := &bazelFilegroupAttributes{
63		Srcs: srcs,
64	}
65
66	props := bazel.BazelTargetModuleProperties{Rule_class: "filegroup"}
67
68	ctx.CreateBazelTargetModule(BazelFileGroupFactory, fg.Name(), props, attrs)
69}
70
71type fileGroupProperties struct {
72	// srcs lists files that will be included in this filegroup
73	Srcs []string `android:"path"`
74
75	Exclude_srcs []string `android:"path"`
76
77	// The base path to the files.  May be used by other modules to determine which portion
78	// of the path to use.  For example, when a filegroup is used as data in a cc_test rule,
79	// the base path is stripped off the path and the remaining path is used as the
80	// installation directory.
81	Path *string
82
83	// Create a make variable with the specified name that contains the list of files in the
84	// filegroup, relative to the root of the source tree.
85	Export_to_make_var *string
86}
87
88type fileGroup struct {
89	ModuleBase
90	BazelModuleBase
91	properties fileGroupProperties
92	srcs       Paths
93}
94
95var _ SourceFileProducer = (*fileGroup)(nil)
96
97// filegroup contains a list of files that are referenced by other modules
98// properties (such as "srcs") using the syntax ":<name>". filegroup are
99// also be used to export files across package boundaries.
100func FileGroupFactory() Module {
101	module := &fileGroup{}
102	module.AddProperties(&module.properties)
103	InitAndroidModule(module)
104	InitBazelModule(module)
105	return module
106}
107
108func (fg *fileGroup) generateBazelBuildActions(ctx ModuleContext) bool {
109	if !fg.MixedBuildsEnabled(ctx) {
110		return false
111	}
112
113	bazelCtx := ctx.Config().BazelContext
114	filePaths, ok := bazelCtx.GetOutputFiles(fg.GetBazelLabel(ctx, fg), ctx.Arch().ArchType)
115	if !ok {
116		return false
117	}
118
119	bazelOuts := make(Paths, 0, len(filePaths))
120	for _, p := range filePaths {
121		src := PathForBazelOut(ctx, p)
122		bazelOuts = append(bazelOuts, src)
123	}
124
125	fg.srcs = bazelOuts
126
127	return true
128}
129
130func (fg *fileGroup) GenerateAndroidBuildActions(ctx ModuleContext) {
131	if fg.generateBazelBuildActions(ctx) {
132		return
133	}
134
135	fg.srcs = PathsForModuleSrcExcludes(ctx, fg.properties.Srcs, fg.properties.Exclude_srcs)
136	if fg.properties.Path != nil {
137		fg.srcs = PathsWithModuleSrcSubDir(ctx, fg.srcs, String(fg.properties.Path))
138	}
139}
140
141func (fg *fileGroup) Srcs() Paths {
142	return append(Paths{}, fg.srcs...)
143}
144
145func (fg *fileGroup) MakeVars(ctx MakeVarsModuleContext) {
146	if makeVar := String(fg.properties.Export_to_make_var); makeVar != "" {
147		ctx.StrictRaw(makeVar, strings.Join(fg.srcs.Strings(), " "))
148	}
149}
150