blob: 27b45d75efa76bc3694dea8d5f77fb3cc0bb4c3a [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"
19 "strings"
20
21 "github.com/google/blueprint"
22
23 "android/soong"
24 "android/soong/android"
25)
26
Colin Crossb916a382016-07-29 17:28:03 -070027type TestProperties struct {
Colin Cross4d9c2d12016-07-29 12:48:20 -070028 // if set, build against the gtest library. Defaults to true.
29 Gtest bool
Colin Crossb916a382016-07-29 17:28:03 -070030}
Colin Cross4d9c2d12016-07-29 12:48:20 -070031
Colin Crossb916a382016-07-29 17:28:03 -070032type TestBinaryProperties struct {
Colin Cross4d9c2d12016-07-29 12:48:20 -070033 // Create a separate binary for each source file. Useful when there is
34 // global state that can not be torn down and reset between each test suite.
35 Test_per_src *bool
36}
37
38func init() {
39 soong.RegisterModuleType("cc_test", testFactory)
40 soong.RegisterModuleType("cc_test_library", testLibraryFactory)
41 soong.RegisterModuleType("cc_benchmark", benchmarkFactory)
42 soong.RegisterModuleType("cc_test_host", testHostFactory)
43 soong.RegisterModuleType("cc_benchmark_host", benchmarkHostFactory)
44}
45
46// Module factory for tests
47func testFactory() (blueprint.Module, []interface{}) {
48 module := NewTest(android.HostAndDeviceSupported)
49 return module.Init()
50}
51
52// Module factory for test libraries
53func testLibraryFactory() (blueprint.Module, []interface{}) {
54 module := NewTestLibrary(android.HostAndDeviceSupported)
55 return module.Init()
56}
57
58// Module factory for benchmarks
59func benchmarkFactory() (blueprint.Module, []interface{}) {
60 module := NewBenchmark(android.HostAndDeviceSupported)
61 return module.Init()
62}
63
64// Module factory for host tests
65func testHostFactory() (blueprint.Module, []interface{}) {
66 module := NewTest(android.HostSupported)
67 return module.Init()
68}
69
70// Module factory for host benchmarks
71func benchmarkHostFactory() (blueprint.Module, []interface{}) {
72 module := NewBenchmark(android.HostSupported)
73 return module.Init()
74}
75
Colin Crossb916a382016-07-29 17:28:03 -070076type testPerSrc interface {
77 testPerSrc() bool
78 srcs() []string
79 setSrc(string, string)
80}
81
82func (test *testBinary) testPerSrc() bool {
83 return Bool(test.Properties.Test_per_src)
84}
85
86func (test *testBinary) srcs() []string {
87 return test.baseCompiler.Properties.Srcs
88}
89
90func (test *testBinary) setSrc(name, src string) {
91 test.baseCompiler.Properties.Srcs = []string{src}
92 test.binaryDecorator.Properties.Stem = name
93}
94
95var _ testPerSrc = (*testBinary)(nil)
96
Colin Cross4d9c2d12016-07-29 12:48:20 -070097func testPerSrcMutator(mctx android.BottomUpMutatorContext) {
98 if m, ok := mctx.Module().(*Module); ok {
Colin Crossb916a382016-07-29 17:28:03 -070099 if test, ok := m.linker.(testPerSrc); ok {
100 if test.testPerSrc() && len(test.srcs()) > 0 {
101 testNames := make([]string, len(test.srcs()))
102 for i, src := range test.srcs() {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700103 testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
104 }
105 tests := mctx.CreateLocalVariations(testNames...)
Colin Crossb916a382016-07-29 17:28:03 -0700106 for i, src := range test.srcs() {
107 tests[i].(*Module).linker.(testPerSrc).setSrc(testNames[i], src)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700108 }
109 }
110 }
111 }
112}
113
Colin Crossb916a382016-07-29 17:28:03 -0700114type testDecorator struct {
115 Properties TestProperties
116 linker *baseLinker
Colin Cross4d9c2d12016-07-29 12:48:20 -0700117}
118
Colin Crossb916a382016-07-29 17:28:03 -0700119func (test *testDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700120 if !test.Properties.Gtest {
121 return flags
122 }
123
124 flags.CFlags = append(flags.CFlags, "-DGTEST_HAS_STD_STRING")
125 if ctx.Host() {
126 flags.CFlags = append(flags.CFlags, "-O0", "-g")
127
128 switch ctx.Os() {
129 case android.Windows:
130 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_WINDOWS")
131 case android.Linux:
132 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX")
133 flags.LdFlags = append(flags.LdFlags, "-lpthread")
134 case android.Darwin:
135 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_MAC")
136 flags.LdFlags = append(flags.LdFlags, "-lpthread")
137 }
138 } else {
139 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX_ANDROID")
140 }
141
142 return flags
143}
144
Colin Crossb916a382016-07-29 17:28:03 -0700145func (test *testDecorator) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700146 if test.Properties.Gtest {
147 if ctx.sdk() && ctx.Device() {
148 switch ctx.selectedStl() {
149 case "ndk_libc++_shared", "ndk_libc++_static":
150 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_libcxx", "libgtest_ndk_libcxx")
151 case "ndk_libgnustl_static":
152 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_gnustl", "libgtest_ndk_gnustl")
153 default:
154 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk", "libgtest_ndk")
155 }
156 } else {
157 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main", "libgtest")
158 }
159 }
Colin Crossb916a382016-07-29 17:28:03 -0700160
Colin Cross4d9c2d12016-07-29 12:48:20 -0700161 return deps
162}
163
Colin Crossb916a382016-07-29 17:28:03 -0700164func (test *testDecorator) linkerInit(ctx BaseModuleContext, linker *baseLinker) {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700165 runpath := "../../lib"
166 if ctx.toolchain().Is64Bit() {
167 runpath += "64"
168 }
Colin Crossb916a382016-07-29 17:28:03 -0700169 linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, runpath)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700170}
171
Colin Crossb916a382016-07-29 17:28:03 -0700172func (test *testDecorator) linkerProps() []interface{} {
173 return []interface{}{&test.Properties}
Colin Cross4d9c2d12016-07-29 12:48:20 -0700174}
175
Colin Crossb916a382016-07-29 17:28:03 -0700176func NewTestInstaller() *baseInstaller {
177 return NewBaseInstaller("nativetest", "nativetest64", InstallInData)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700178}
179
Colin Crossb916a382016-07-29 17:28:03 -0700180type testBinary struct {
181 testDecorator
182 *binaryDecorator
183 *baseCompiler
Colin Crossb916a382016-07-29 17:28:03 -0700184 Properties TestBinaryProperties
185}
186
187func (test *testBinary) linkerProps() []interface{} {
188 props := append(test.testDecorator.linkerProps(), test.binaryDecorator.linkerProps()...)
189 props = append(props, &test.Properties)
190 return props
191}
192
193func (test *testBinary) linkerInit(ctx BaseModuleContext) {
194 test.testDecorator.linkerInit(ctx, test.binaryDecorator.baseLinker)
195 test.binaryDecorator.linkerInit(ctx)
196}
197
198func (test *testBinary) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
199 deps = test.testDecorator.linkerDeps(ctx, deps)
200 deps = test.binaryDecorator.linkerDeps(ctx, deps)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700201 return deps
202}
203
Colin Crossb916a382016-07-29 17:28:03 -0700204func (test *testBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
205 flags = test.binaryDecorator.linkerFlags(ctx, flags)
206 flags = test.testDecorator.linkerFlags(ctx, flags)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700207 return flags
208}
209
Colin Crossb916a382016-07-29 17:28:03 -0700210func (test *testBinary) install(ctx ModuleContext, file android.Path) {
Dan Willemsen1d577e22016-08-29 15:53:15 -0700211 test.binaryDecorator.baseInstaller.dir = filepath.Join("nativetest", ctx.ModuleName())
212 test.binaryDecorator.baseInstaller.dir64 = filepath.Join("nativetest64", ctx.ModuleName())
213 test.binaryDecorator.baseInstaller.install(ctx, file)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700214}
215
216func NewTest(hod android.HostOrDeviceSupported) *Module {
Colin Crossb916a382016-07-29 17:28:03 -0700217 module, binary := NewBinary(hod)
218 module.multilib = android.MultilibBoth
Dan Willemsen1d577e22016-08-29 15:53:15 -0700219 binary.baseInstaller = NewTestInstaller()
Colin Crossb916a382016-07-29 17:28:03 -0700220
221 test := &testBinary{
222 testDecorator: testDecorator{
223 linker: binary.baseLinker,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700224 },
Colin Crossb916a382016-07-29 17:28:03 -0700225 binaryDecorator: binary,
226 baseCompiler: NewBaseCompiler(),
Colin Cross4d9c2d12016-07-29 12:48:20 -0700227 }
Colin Crossb916a382016-07-29 17:28:03 -0700228 test.testDecorator.Properties.Gtest = true
229 module.compiler = test
230 module.linker = test
231 module.installer = test
Colin Cross4d9c2d12016-07-29 12:48:20 -0700232 return module
233}
234
Colin Crossb916a382016-07-29 17:28:03 -0700235type testLibrary struct {
236 testDecorator
237 *libraryDecorator
238}
239
240func (test *testLibrary) linkerProps() []interface{} {
241 return append(test.testDecorator.linkerProps(), test.libraryDecorator.linkerProps()...)
242}
243
244func (test *testLibrary) linkerInit(ctx BaseModuleContext) {
245 test.testDecorator.linkerInit(ctx, test.libraryDecorator.baseLinker)
246 test.libraryDecorator.linkerInit(ctx)
247}
248
249func (test *testLibrary) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
250 deps = test.testDecorator.linkerDeps(ctx, deps)
251 deps = test.libraryDecorator.linkerDeps(ctx, deps)
252 return deps
253}
254
255func (test *testLibrary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
256 flags = test.libraryDecorator.linkerFlags(ctx, flags)
257 flags = test.testDecorator.linkerFlags(ctx, flags)
258 return flags
259}
260
Colin Cross4d9c2d12016-07-29 12:48:20 -0700261func NewTestLibrary(hod android.HostOrDeviceSupported) *Module {
Colin Crossb916a382016-07-29 17:28:03 -0700262 module, library := NewLibrary(android.HostAndDeviceSupported, false, true)
263 test := &testLibrary{
264 testDecorator: testDecorator{
265 linker: library.baseLinker,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700266 },
Colin Crossb916a382016-07-29 17:28:03 -0700267 libraryDecorator: library,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700268 }
Colin Crossb916a382016-07-29 17:28:03 -0700269 test.testDecorator.Properties.Gtest = true
270 module.linker = test
271 module.installer = nil
Colin Cross4d9c2d12016-07-29 12:48:20 -0700272 return module
273}
274
Colin Crossb916a382016-07-29 17:28:03 -0700275type benchmarkDecorator struct {
276 *binaryDecorator
Colin Cross4d9c2d12016-07-29 12:48:20 -0700277}
278
Colin Crossb916a382016-07-29 17:28:03 -0700279func (benchmark *benchmarkDecorator) linkerInit(ctx BaseModuleContext) {
280 runpath := "../../lib"
281 if ctx.toolchain().Is64Bit() {
282 runpath += "64"
283 }
284 benchmark.baseLinker.dynamicProperties.RunPaths = append(benchmark.baseLinker.dynamicProperties.RunPaths, runpath)
285 benchmark.binaryDecorator.linkerInit(ctx)
286}
287
288func (benchmark *benchmarkDecorator) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
289 deps = benchmark.binaryDecorator.linkerDeps(ctx, deps)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700290 deps.StaticLibs = append(deps.StaticLibs, "libgoogle-benchmark")
291 return deps
292}
293
Colin Crossb916a382016-07-29 17:28:03 -0700294func (benchmark *benchmarkDecorator) install(ctx ModuleContext, file android.Path) {
Dan Willemsen1d577e22016-08-29 15:53:15 -0700295 benchmark.binaryDecorator.baseInstaller.dir = filepath.Join("nativetest", ctx.ModuleName())
296 benchmark.binaryDecorator.baseInstaller.dir64 = filepath.Join("nativetest64", ctx.ModuleName())
297 benchmark.binaryDecorator.baseInstaller.install(ctx, file)
Colin Crossb916a382016-07-29 17:28:03 -0700298}
299
Colin Cross4d9c2d12016-07-29 12:48:20 -0700300func NewBenchmark(hod android.HostOrDeviceSupported) *Module {
Colin Crossb916a382016-07-29 17:28:03 -0700301 module, binary := NewBinary(hod)
302 module.multilib = android.MultilibBoth
Dan Willemsen1d577e22016-08-29 15:53:15 -0700303 binary.baseInstaller = NewTestInstaller()
Colin Crossb916a382016-07-29 17:28:03 -0700304
305 benchmark := &benchmarkDecorator{
306 binaryDecorator: binary,
Colin Cross4d9c2d12016-07-29 12:48:20 -0700307 }
Colin Crossb916a382016-07-29 17:28:03 -0700308 module.linker = benchmark
309 module.installer = benchmark
Colin Cross4d9c2d12016-07-29 12:48:20 -0700310 return module
311}