• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2015 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 java
16
17import (
18	"path/filepath"
19	"strconv"
20	"strings"
21
22	"github.com/google/blueprint"
23	"github.com/google/blueprint/pathtools"
24
25	"android/soong/android"
26)
27
28func init() {
29	pctx.SourcePathVariable("logtagsCmd", "build/make/tools/java-event-log-tags.py")
30	pctx.SourcePathVariable("mergeLogtagsCmd", "build/make/tools/merge-event-log-tags.py")
31	pctx.SourcePathVariable("logtagsLib", "build/make/tools/event_log_tags.py")
32}
33
34var (
35	logtags = pctx.AndroidStaticRule("logtags",
36		blueprint.RuleParams{
37			Command:     "$logtagsCmd -o $out $in",
38			CommandDeps: []string{"$logtagsCmd", "$logtagsLib"},
39		})
40
41	mergeLogtags = pctx.AndroidStaticRule("mergeLogtags",
42		blueprint.RuleParams{
43			Command:     "$mergeLogtagsCmd -o $out $in",
44			CommandDeps: []string{"$mergeLogtagsCmd", "$logtagsLib"},
45		})
46)
47
48func genAidl(ctx android.ModuleContext, aidlFiles android.Paths, aidlGlobalFlags string, aidlIndividualFlags map[string]string, deps android.Paths) android.Paths {
49	// Shard aidl files into groups of 50 to avoid having to recompile all of them if one changes and to avoid
50	// hitting command line length limits.
51	shards := android.ShardPaths(aidlFiles, 50)
52
53	srcJarFiles := make(android.Paths, 0, len(shards))
54
55	for i, shard := range shards {
56		srcJarFile := android.PathForModuleGen(ctx, "aidl", "aidl"+strconv.Itoa(i)+".srcjar")
57		srcJarFiles = append(srcJarFiles, srcJarFile)
58
59		outDir := srcJarFile.ReplaceExtension(ctx, "tmp")
60
61		rule := android.NewRuleBuilder(pctx, ctx)
62
63		rule.Command().Text("rm -rf").Flag(outDir.String())
64		rule.Command().Text("mkdir -p").Flag(outDir.String())
65		rule.Command().Text("FLAGS=' " + aidlGlobalFlags + "'")
66
67		for _, aidlFile := range shard {
68			localFlag := aidlIndividualFlags[aidlFile.String()]
69			depFile := srcJarFile.InSameDir(ctx, aidlFile.String()+".d")
70			javaFile := outDir.Join(ctx, pathtools.ReplaceExtension(aidlFile.String(), "java"))
71			rule.Command().
72				Tool(ctx.Config().HostToolPath(ctx, "aidl")).
73				FlagWithDepFile("-d", depFile).
74				Flag("$FLAGS").
75				Flag(localFlag).
76				Input(aidlFile).
77				Output(javaFile).
78				Implicits(deps)
79			rule.Temporary(javaFile)
80		}
81
82		rule.Command().
83			Tool(ctx.Config().HostToolPath(ctx, "soong_zip")).
84			Flag("-srcjar").
85			Flag("-write_if_changed").
86			FlagWithOutput("-o ", srcJarFile).
87			FlagWithArg("-C ", outDir.String()).
88			FlagWithArg("-D ", outDir.String())
89
90		rule.Command().Text("rm -rf").Flag(outDir.String())
91
92		rule.Restat()
93
94		ruleName := "aidl"
95		ruleDesc := "aidl"
96		if len(shards) > 1 {
97			ruleName += "_" + strconv.Itoa(i)
98			ruleDesc += " " + strconv.Itoa(i)
99		}
100
101		rule.Build(ruleName, ruleDesc)
102	}
103
104	return srcJarFiles
105}
106
107func genLogtags(ctx android.ModuleContext, logtagsFile android.Path) android.Path {
108	javaFile := android.GenPathWithExt(ctx, "logtags", logtagsFile, "java")
109
110	ctx.Build(pctx, android.BuildParams{
111		Rule:        logtags,
112		Description: "logtags " + logtagsFile.Rel(),
113		Output:      javaFile,
114		Input:       logtagsFile,
115	})
116
117	return javaFile
118}
119
120// genAidlIncludeFlags returns additional include flags based on the relative path
121// of each .aidl file passed in srcFiles. excludeDirs is a list of paths relative to
122// the Android checkout root that should not be included in the returned flags.
123func genAidlIncludeFlags(ctx android.PathContext, srcFiles android.Paths, excludeDirs android.Paths) string {
124	var baseDirs []string
125	excludeDirsStrings := excludeDirs.Strings()
126	for _, srcFile := range srcFiles {
127		if srcFile.Ext() == ".aidl" {
128			baseDir := strings.TrimSuffix(srcFile.String(), srcFile.Rel())
129			baseDir = filepath.Clean(baseDir)
130			baseDirSeen := android.InList(baseDir, baseDirs) || android.InList(baseDir, excludeDirsStrings)
131
132			// For go/bp2build mixed builds, a file may be listed under a
133			// directory in the Bazel output tree that is symlinked to a
134			// directory under the android source tree. We should only
135			// include one copy of this directory so that the AIDL tool
136			// doesn't find multiple definitions of the same AIDL class.
137			// This code comes into effect when filegroups are used in mixed builds.
138			bazelPathPrefix := android.PathForBazelOut(ctx, "").String()
139			bazelBaseDir, err := filepath.Rel(bazelPathPrefix, baseDir)
140			bazelBaseDirSeen := err == nil &&
141				android.InList(bazelBaseDir, baseDirs) ||
142				android.InList(bazelBaseDir, excludeDirsStrings)
143
144			if baseDir != "" && !baseDirSeen && !bazelBaseDirSeen {
145				baseDirs = append(baseDirs, baseDir)
146			}
147		}
148	}
149	return android.JoinWithPrefix(baseDirs, " -I")
150}
151
152func (j *Module) genSources(ctx android.ModuleContext, srcFiles android.Paths,
153	flags javaBuilderFlags) android.Paths {
154
155	outSrcFiles := make(android.Paths, 0, len(srcFiles))
156	var protoSrcs android.Paths
157	var aidlSrcs android.Paths
158
159	for _, srcFile := range srcFiles {
160		switch srcFile.Ext() {
161		case ".aidl":
162			aidlSrcs = append(aidlSrcs, srcFile)
163		case ".logtags":
164			j.logtagsSrcs = append(j.logtagsSrcs, srcFile)
165			javaFile := genLogtags(ctx, srcFile)
166			outSrcFiles = append(outSrcFiles, javaFile)
167		case ".proto":
168			protoSrcs = append(protoSrcs, srcFile)
169		default:
170			outSrcFiles = append(outSrcFiles, srcFile)
171		}
172	}
173
174	// Process all proto files together to support sharding them into one or more rules that produce srcjars.
175	if len(protoSrcs) > 0 {
176		srcJarFiles := genProto(ctx, protoSrcs, flags.proto)
177		outSrcFiles = append(outSrcFiles, srcJarFiles...)
178	}
179
180	// Process all aidl files together to support sharding them into one or more rules that produce srcjars.
181	if len(aidlSrcs) > 0 {
182		individualFlags := make(map[string]string)
183		for _, aidlSrc := range aidlSrcs {
184			flags := j.individualAidlFlags(ctx, aidlSrc)
185			if flags != "" {
186				individualFlags[aidlSrc.String()] = flags
187			}
188		}
189		srcJarFiles := genAidl(ctx, aidlSrcs, flags.aidlFlags, individualFlags, flags.aidlDeps)
190		outSrcFiles = append(outSrcFiles, srcJarFiles...)
191	}
192
193	return outSrcFiles
194}
195
196func LogtagsSingleton() android.Singleton {
197	return &logtagsSingleton{}
198}
199
200type logtagsProducer interface {
201	logtags() android.Paths
202}
203
204func (j *Module) logtags() android.Paths {
205	return j.logtagsSrcs
206}
207
208var _ logtagsProducer = (*Module)(nil)
209
210type logtagsSingleton struct{}
211
212func (l *logtagsSingleton) GenerateBuildActions(ctx android.SingletonContext) {
213	var allLogtags android.Paths
214	ctx.VisitAllModules(func(module android.Module) {
215		if logtags, ok := module.(logtagsProducer); ok {
216			allLogtags = append(allLogtags, logtags.logtags()...)
217		}
218	})
219
220	ctx.Build(pctx, android.BuildParams{
221		Rule:        mergeLogtags,
222		Description: "merge logtags",
223		Output:      android.PathForIntermediates(ctx, "all-event-log-tags.txt"),
224		Inputs:      allLogtags,
225	})
226}
227