blob: d3556bf97e3125e9d34bc223f8e436c05e976c7e [file] [log] [blame]
Colin Cross4d9c2d12016-07-29 12:48:20 -07001// 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 cc
16
17import (
18 "path/filepath"
Dan Willemsen0b24c742016-10-04 15:13:37 -070019 "runtime"
Colin Cross4d9c2d12016-07-29 12:48:20 -070020 "strings"
21
Colin Cross4d9c2d12016-07-29 12:48:20 -070022 "android/soong/android"
Colin Crossfaeb7aa2017-02-01 14:12:44 -080023 "github.com/google/blueprint"
Colin Cross4d9c2d12016-07-29 12:48:20 -070024)
25
Colin Crossb916a382016-07-29 17:28:03 -070026type TestProperties struct {
Colin Cross4d9c2d12016-07-29 12:48:20 -070027 // if set, build against the gtest library. Defaults to true.
Colin Cross600c9df2016-09-13 12:26:16 -070028 Gtest *bool
Colin Crossb916a382016-07-29 17:28:03 -070029}
Colin Cross4d9c2d12016-07-29 12:48:20 -070030
Colin Crossb916a382016-07-29 17:28:03 -070031type TestBinaryProperties struct {
Colin Cross4d9c2d12016-07-29 12:48:20 -070032 // Create a separate binary for each source file. Useful when there is
33 // global state that can not be torn down and reset between each test suite.
34 Test_per_src *bool
Dan Willemsen3340d602016-12-27 14:40:40 -080035
36 // Disables the creation of a test-specific directory when used with
37 // relative_install_path. Useful if several tests need to be in the same
38 // directory, but test_per_src doesn't work.
39 No_named_install_directory *bool
Colin Crossfaeb7aa2017-02-01 14:12:44 -080040
41 // list of files or filegroup modules that provide data that should be installed alongside
42 // the test
43 Data []string
Colin Cross4d9c2d12016-07-29 12:48:20 -070044}
45
46func init() {
Colin Cross798bfce2016-10-12 14:28:16 -070047 android.RegisterModuleType("cc_test", testFactory)
48 android.RegisterModuleType("cc_test_library", testLibraryFactory)
49 android.RegisterModuleType("cc_benchmark", benchmarkFactory)
50 android.RegisterModuleType("cc_test_host", testHostFactory)
51 android.RegisterModuleType("cc_benchmark_host", benchmarkHostFactory)
Colin Cross4d9c2d12016-07-29 12:48:20 -070052}
53
54// Module factory for tests
55func testFactory() (blueprint.Module, []interface{}) {
56 module := NewTest(android.HostAndDeviceSupported)
57 return module.Init()
58}
59
60// Module factory for test libraries
61func testLibraryFactory() (blueprint.Module, []interface{}) {
62 module := NewTestLibrary(android.HostAndDeviceSupported)
63 return module.Init()
64}
65
66// Module factory for benchmarks
67func benchmarkFactory() (blueprint.Module, []interface{}) {
68 module := NewBenchmark(android.HostAndDeviceSupported)
69 return module.Init()
70}
71
72// Module factory for host tests
73func testHostFactory() (blueprint.Module, []interface{}) {
74 module := NewTest(android.HostSupported)
75 return module.Init()
76}
77
78// Module factory for host benchmarks
79func benchmarkHostFactory() (blueprint.Module, []interface{}) {
80 module := NewBenchmark(android.HostSupported)
81 return module.Init()
82}
83
Colin Crossb916a382016-07-29 17:28:03 -070084type testPerSrc interface {
85 testPerSrc() bool
86 srcs() []string
87 setSrc(string, string)
88}
89
90func (test *testBinary) testPerSrc() bool {
91 return Bool(test.Properties.Test_per_src)
92}
93
94func (test *testBinary) srcs() []string {
95 return test.baseCompiler.Properties.Srcs
96}
97
98func (test *testBinary) setSrc(name, src string) {
99 test.baseCompiler.Properties.Srcs = []string{src}
100 test.binaryDecorator.Properties.Stem = name
101}
102
103var _ testPerSrc = (*testBinary)(nil)
104
Colin Cross4d9c2d12016-07-29 12:48:20 -0700105func testPerSrcMutator(mctx android.BottomUpMutatorContext) {
106 if m, ok := mctx.Module().(*Module); ok {
Colin Crossb916a382016-07-29 17:28:03 -0700107 if test, ok := m.linker.(testPerSrc); ok {
108 if test.testPerSrc() && len(test.srcs()) > 0 {
109 testNames := make([]string, len(test.srcs()))
110 for i, src := range test.srcs() {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700111 testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
112 }
113 tests := mctx.CreateLocalVariations(testNames...)
Colin Crossb916a382016-07-29 17:28:03 -0700114 for i, src := range test.srcs() {
115 tests[i].(*Module).linker.(testPerSrc).setSrc(testNames[i], src)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700116 }
117 }
118 }
119 }
120}
121
Colin Crossb916a382016-07-29 17:28:03 -0700122type testDecorator struct {
123 Properties TestProperties
124 linker *baseLinker
Colin Cross4d9c2d12016-07-29 12:48:20 -0700125}
126
Colin Cross600c9df2016-09-13 12:26:16 -0700127func (test *testDecorator) gtest() bool {
128 return test.Properties.Gtest == nil || *test.Properties.Gtest == true
129}
130
Colin Crossb916a382016-07-29 17:28:03 -0700131func (test *testDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
Colin Cross600c9df2016-09-13 12:26:16 -0700132 if !test.gtest() {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700133 return flags
134 }
135
136 flags.CFlags = append(flags.CFlags, "-DGTEST_HAS_STD_STRING")
137 if ctx.Host() {
138 flags.CFlags = append(flags.CFlags, "-O0", "-g")
139
140 switch ctx.Os() {
141 case android.Windows:
142 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_WINDOWS")
143 case android.Linux:
144 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX")
145 flags.LdFlags = append(flags.LdFlags, "-lpthread")
146 case android.Darwin:
147 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_MAC")
148 flags.LdFlags = append(flags.LdFlags, "-lpthread")
149 }
150 } else {
151 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX_ANDROID")
152 }
153
154 return flags
155}
156
Colin Crossb916a382016-07-29 17:28:03 -0700157func (test *testDecorator) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
Colin Cross600c9df2016-09-13 12:26:16 -0700158 if test.gtest() {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700159 if ctx.sdk() && ctx.Device() {
160 switch ctx.selectedStl() {
161 case "ndk_libc++_shared", "ndk_libc++_static":
162 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_libcxx", "libgtest_ndk_libcxx")
163 case "ndk_libgnustl_static":
164 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_gnustl", "libgtest_ndk_gnustl")
165 default:
166 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk", "libgtest_ndk")
167 }
168 } else {
169 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main", "libgtest")
170 }
171 }
Colin Crossb916a382016-07-29 17:28:03 -0700172
Colin Cross4d9c2d12016-07-29 12:48:20 -0700173 return deps
174}
175
Colin Crossb916a382016-07-29 17:28:03 -0700176func (test *testDecorator) linkerInit(ctx BaseModuleContext, linker *baseLinker) {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700177 runpath := "../../lib"
178 if ctx.toolchain().Is64Bit() {
179 runpath += "64"
180 }
Colin Crossb916a382016-07-29 17:28:03 -0700181 linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, runpath)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700182}
183
Colin Crossb916a382016-07-29 17:28:03 -0700184func (test *testDecorator) linkerProps() []interface{} {
185 return []interface{}{&test.Properties}
Colin Cross4d9c2d12016-07-29 12:48:20 -0700186}
187
Colin Crossb916a382016-07-29 17:28:03 -0700188func NewTestInstaller() *baseInstaller {
189 return NewBaseInstaller("nativetest", "nativetest64", InstallInData)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700190}
191
Colin Crossb916a382016-07-29 17:28:03 -0700192type testBinary struct {
193 testDecorator
194 *binaryDecorator
195 *baseCompiler
Colin Crossb916a382016-07-29 17:28:03 -0700196 Properties TestBinaryProperties
Colin Crossfaeb7aa2017-02-01 14:12:44 -0800197 data android.Paths
Colin Crossb916a382016-07-29 17:28:03 -0700198}
199
200func (test *testBinary) linkerProps() []interface{} {
201 props := append(test.testDecorator.linkerProps(), test.binaryDecorator.linkerProps()...)
202 props = append(props, &test.Properties)
203 return props
204}
205
206func (test *testBinary) linkerInit(ctx BaseModuleContext) {
207 test.testDecorator.linkerInit(ctx, test.binaryDecorator.baseLinker)
208 test.binaryDecorator.linkerInit(ctx)
209}
210
Colin Cross37047f12016-12-13 17:06:13 -0800211func (test *testBinary) linkerDeps(ctx DepsContext, deps Deps) Deps {
Colin Crossfaeb7aa2017-02-01 14:12:44 -0800212 android.ExtractSourcesDeps(ctx, test.Properties.Data)
213
Colin Crossb916a382016-07-29 17:28:03 -0700214 deps = test.testDecorator.linkerDeps(ctx, deps)
215 deps = test.binaryDecorator.linkerDeps(ctx, deps)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700216 return deps
217}
218
Colin Crossb916a382016-07-29 17:28:03 -0700219func (test *testBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
220 flags = test.binaryDecorator.linkerFlags(ctx, flags)
221 flags = test.testDecorator.linkerFlags(ctx, flags)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700222 return flags
223}
224
Colin Crossb916a382016-07-29 17:28:03 -0700225func (test *testBinary) install(ctx ModuleContext, file android.Path) {
Colin Crossfaeb7aa2017-02-01 14:12:44 -0800226 test.data = ctx.ExpandSources(test.Properties.Data, nil)
227
Colin Cross600c9df2016-09-13 12:26:16 -0700228 test.binaryDecorator.baseInstaller.dir = "nativetest"
229 test.binaryDecorator.baseInstaller.dir64 = "nativetest64"
Dan Willemsen3340d602016-12-27 14:40:40 -0800230
231 if !Bool(test.Properties.No_named_install_directory) {
232 test.binaryDecorator.baseInstaller.relative = ctx.ModuleName()
233 } else if test.binaryDecorator.baseInstaller.Properties.Relative_install_path == "" {
234 ctx.PropertyErrorf("no_named_install_directory", "Module install directory may only be disabled if relative_install_path is set")
235 }
236
Dan Willemsen1d577e22016-08-29 15:53:15 -0700237 test.binaryDecorator.baseInstaller.install(ctx, file)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700238}
239
240func NewTest(hod android.HostOrDeviceSupported) *Module {
Colin Crossb916a382016-07-29 17:28:03 -0700241 module, binary := NewBinary(hod)
242 module.multilib = android.MultilibBoth
Dan Willemsen1d577e22016-08-29 15:53:15 -0700243 binary.baseInstaller = NewTestInstaller()
Colin Crossb916a382016-07-29 17:28:03 -0700244
245 test := &testBinary{
246 testDecorator: testDecorator{
247 linker: binary.baseLinker,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700248 },
Colin Crossb916a382016-07-29 17:28:03 -0700249 binaryDecorator: binary,
250 baseCompiler: NewBaseCompiler(),
Colin Cross4d9c2d12016-07-29 12:48:20 -0700251 }
Colin Crossb916a382016-07-29 17:28:03 -0700252 module.compiler = test
253 module.linker = test
254 module.installer = test
Colin Cross4d9c2d12016-07-29 12:48:20 -0700255 return module
256}
257
Colin Crossb916a382016-07-29 17:28:03 -0700258type testLibrary struct {
259 testDecorator
260 *libraryDecorator
261}
262
263func (test *testLibrary) linkerProps() []interface{} {
264 return append(test.testDecorator.linkerProps(), test.libraryDecorator.linkerProps()...)
265}
266
267func (test *testLibrary) linkerInit(ctx BaseModuleContext) {
268 test.testDecorator.linkerInit(ctx, test.libraryDecorator.baseLinker)
269 test.libraryDecorator.linkerInit(ctx)
270}
271
Colin Cross37047f12016-12-13 17:06:13 -0800272func (test *testLibrary) linkerDeps(ctx DepsContext, deps Deps) Deps {
Colin Crossb916a382016-07-29 17:28:03 -0700273 deps = test.testDecorator.linkerDeps(ctx, deps)
274 deps = test.libraryDecorator.linkerDeps(ctx, deps)
275 return deps
276}
277
278func (test *testLibrary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
279 flags = test.libraryDecorator.linkerFlags(ctx, flags)
280 flags = test.testDecorator.linkerFlags(ctx, flags)
281 return flags
282}
283
Colin Cross4d9c2d12016-07-29 12:48:20 -0700284func NewTestLibrary(hod android.HostOrDeviceSupported) *Module {
Colin Crossab3b7322016-12-09 14:46:15 -0800285 module, library := NewLibrary(android.HostAndDeviceSupported)
Dan Willemsen28bda512016-08-31 16:32:55 -0700286 library.baseInstaller = NewTestInstaller()
Colin Crossb916a382016-07-29 17:28:03 -0700287 test := &testLibrary{
288 testDecorator: testDecorator{
289 linker: library.baseLinker,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700290 },
Colin Crossb916a382016-07-29 17:28:03 -0700291 libraryDecorator: library,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700292 }
Colin Crossb916a382016-07-29 17:28:03 -0700293 module.linker = test
Colin Cross4d9c2d12016-07-29 12:48:20 -0700294 return module
295}
296
Colin Crossb916a382016-07-29 17:28:03 -0700297type benchmarkDecorator struct {
298 *binaryDecorator
Colin Cross4d9c2d12016-07-29 12:48:20 -0700299}
300
Colin Crossb916a382016-07-29 17:28:03 -0700301func (benchmark *benchmarkDecorator) linkerInit(ctx BaseModuleContext) {
302 runpath := "../../lib"
303 if ctx.toolchain().Is64Bit() {
304 runpath += "64"
305 }
306 benchmark.baseLinker.dynamicProperties.RunPaths = append(benchmark.baseLinker.dynamicProperties.RunPaths, runpath)
307 benchmark.binaryDecorator.linkerInit(ctx)
308}
309
Colin Cross37047f12016-12-13 17:06:13 -0800310func (benchmark *benchmarkDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps {
Colin Crossb916a382016-07-29 17:28:03 -0700311 deps = benchmark.binaryDecorator.linkerDeps(ctx, deps)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700312 deps.StaticLibs = append(deps.StaticLibs, "libgoogle-benchmark")
313 return deps
314}
315
Colin Crossb916a382016-07-29 17:28:03 -0700316func (benchmark *benchmarkDecorator) install(ctx ModuleContext, file android.Path) {
Dan Willemsen1d577e22016-08-29 15:53:15 -0700317 benchmark.binaryDecorator.baseInstaller.dir = filepath.Join("nativetest", ctx.ModuleName())
318 benchmark.binaryDecorator.baseInstaller.dir64 = filepath.Join("nativetest64", ctx.ModuleName())
319 benchmark.binaryDecorator.baseInstaller.install(ctx, file)
Colin Crossb916a382016-07-29 17:28:03 -0700320}
321
Colin Cross4d9c2d12016-07-29 12:48:20 -0700322func NewBenchmark(hod android.HostOrDeviceSupported) *Module {
Dan Willemsen0b24c742016-10-04 15:13:37 -0700323 // Benchmarks aren't supported on Darwin
324 if runtime.GOOS == "darwin" {
325 switch hod {
326 case android.HostAndDeviceSupported:
327 hod = android.DeviceSupported
328 case android.HostSupported:
329 hod = android.NeitherHostNorDeviceSupported
330 }
331 }
332
Colin Crossb916a382016-07-29 17:28:03 -0700333 module, binary := NewBinary(hod)
334 module.multilib = android.MultilibBoth
Dan Willemsen1d577e22016-08-29 15:53:15 -0700335 binary.baseInstaller = NewTestInstaller()
Colin Crossb916a382016-07-29 17:28:03 -0700336
337 benchmark := &benchmarkDecorator{
338 binaryDecorator: binary,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700339 }
Colin Crossb916a382016-07-29 17:28:03 -0700340 module.linker = benchmark
341 module.installer = benchmark
Colin Cross4d9c2d12016-07-29 12:48:20 -0700342 return module
343}