1// Copyright 2018 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 suite_harness
16
17import (
18	"strings"
19
20	"github.com/google/blueprint"
21
22	"android/soong/android"
23	"android/soong/java"
24)
25
26var pctx = android.NewPackageContext("android/soong/tradefed/suite_harness")
27
28func init() {
29	android.RegisterModuleType("tradefed_binary_host", tradefedBinaryFactory)
30
31	pctx.Import("android/soong/android")
32}
33
34type TradefedBinaryProperties struct {
35	Short_name                    string
36	Full_name                     string
37	Version                       string
38	Suite_arch                    string
39	Prepend_platform_version_name bool
40}
41
42// tradefedBinaryFactory creates an empty module for the tradefed_binary module type,
43// which is a java_binary with some additional processing in tradefedBinaryLoadHook.
44func tradefedBinaryFactory() android.Module {
45	props := &TradefedBinaryProperties{}
46	module := java.BinaryHostFactory()
47	module.AddProperties(props)
48	android.AddLoadHook(module, tradefedBinaryLoadHook(props))
49
50	return module
51}
52
53const genSuffix = "-gen"
54
55// tradefedBinaryLoadHook adds extra resources and libraries to tradefed_binary modules.
56func tradefedBinaryLoadHook(tfb *TradefedBinaryProperties) func(ctx android.LoadHookContext) {
57	return func(ctx android.LoadHookContext) {
58		genName := ctx.ModuleName() + genSuffix
59		version := tfb.Version
60		if tfb.Prepend_platform_version_name {
61			version = ctx.Config().PlatformVersionName() + tfb.Version
62		}
63
64		// Create a submodule that generates the test-suite-info.properties file
65		// and copies DynamicConfig.xml if it is present.
66		ctx.CreateModule(tradefedBinaryGenFactory,
67			&TradefedBinaryGenProperties{
68				Name:       &genName,
69				Short_name: tfb.Short_name,
70				Full_name:  tfb.Full_name,
71				Suite_arch: tfb.Suite_arch,
72				Version:    version,
73			})
74
75		props := struct {
76			Java_resources []string
77			Libs           []string
78		}{}
79
80		// Add dependencies required by all tradefed_binary modules.
81		props.Libs = []string{
82			"tradefed",
83			"loganalysis",
84			"compatibility-host-util",
85		}
86
87		// Add the files generated by the submodule created above to the resources.
88		props.Java_resources = []string{":" + genName}
89
90		ctx.AppendProperties(&props)
91
92	}
93}
94
95type TradefedBinaryGenProperties struct {
96	Name       *string
97	Short_name string
98	Full_name  string
99	Version    string
100	Suite_arch string
101}
102
103type tradefedBinaryGen struct {
104	android.ModuleBase
105
106	properties TradefedBinaryGenProperties
107
108	gen android.Paths
109}
110
111func tradefedBinaryGenFactory() android.Module {
112	tfg := &tradefedBinaryGen{}
113	tfg.AddProperties(&tfg.properties)
114	android.InitAndroidModule(tfg)
115	return tfg
116}
117
118func (tfg *tradefedBinaryGen) DepsMutator(android.BottomUpMutatorContext) {}
119
120var tradefedBinaryGenRule = pctx.StaticRule("tradefedBinaryGenRule", blueprint.RuleParams{
121	Command: `rm -f $out && touch $out && ` +
122		`echo "# This file is auto generated by Android.mk. Do not modify." >> $out && ` +
123		`echo "build_number = $$(cat ${buildNumberFile})" >> $out && ` +
124		`echo "target_arch = ${arch}" >> $out && ` +
125		`echo "name = ${name}" >> $out && ` +
126		`echo "fullname = ${fullname}" >> $out && ` +
127		`echo "version = ${version}" >> $out`,
128}, "buildNumberFile", "arch", "name", "fullname", "version")
129
130func (tfg *tradefedBinaryGen) GenerateAndroidBuildActions(ctx android.ModuleContext) {
131	buildNumberFile := ctx.Config().BuildNumberFile(ctx)
132	outputFile := android.PathForModuleOut(ctx, "test-suite-info.properties")
133
134	arch := strings.ReplaceAll(tfg.properties.Suite_arch, " ", "")
135	if arch == "" {
136		arch = ctx.Config().DevicePrimaryArchType().String()
137	}
138
139	ctx.Build(pctx, android.BuildParams{
140		Rule:      tradefedBinaryGenRule,
141		Output:    outputFile,
142		OrderOnly: android.Paths{buildNumberFile},
143		Args: map[string]string{
144			"buildNumberFile": buildNumberFile.String(),
145			"arch":            arch,
146			"name":            tfg.properties.Short_name,
147			"fullname":        tfg.properties.Full_name,
148			"version":         tfg.properties.Version,
149		},
150	})
151
152	tfg.gen = append(tfg.gen, outputFile)
153
154	dynamicConfig := android.ExistentPathForSource(ctx, ctx.ModuleDir(), "DynamicConfig.xml")
155	if dynamicConfig.Valid() {
156		outputFile := android.PathForModuleOut(ctx, strings.TrimSuffix(ctx.ModuleName(), genSuffix)+".dynamic")
157		ctx.Build(pctx, android.BuildParams{
158			Rule:   android.Cp,
159			Input:  dynamicConfig.Path(),
160			Output: outputFile,
161		})
162
163		tfg.gen = append(tfg.gen, outputFile)
164	}
165}
166
167func (tfg *tradefedBinaryGen) Srcs() android.Paths {
168	return append(android.Paths(nil), tfg.gen...)
169}
170
171var _ android.SourceFileProducer = (*tradefedBinaryGen)(nil)
172