blob: d9b8571f6b493cec2859ce481d138aeed79f7147 [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
27type TestLinkerProperties struct {
28 // if set, build against the gtest library. Defaults to true.
29 Gtest bool
30
31 // Create a separate binary for each source file. Useful when there is
32 // global state that can not be torn down and reset between each test suite.
33 Test_per_src *bool
34}
35
36func init() {
37 soong.RegisterModuleType("cc_test", testFactory)
38 soong.RegisterModuleType("cc_test_library", testLibraryFactory)
39 soong.RegisterModuleType("cc_benchmark", benchmarkFactory)
40 soong.RegisterModuleType("cc_test_host", testHostFactory)
41 soong.RegisterModuleType("cc_benchmark_host", benchmarkHostFactory)
42}
43
44// Module factory for tests
45func testFactory() (blueprint.Module, []interface{}) {
46 module := NewTest(android.HostAndDeviceSupported)
47 return module.Init()
48}
49
50// Module factory for test libraries
51func testLibraryFactory() (blueprint.Module, []interface{}) {
52 module := NewTestLibrary(android.HostAndDeviceSupported)
53 return module.Init()
54}
55
56// Module factory for benchmarks
57func benchmarkFactory() (blueprint.Module, []interface{}) {
58 module := NewBenchmark(android.HostAndDeviceSupported)
59 return module.Init()
60}
61
62// Module factory for host tests
63func testHostFactory() (blueprint.Module, []interface{}) {
64 module := NewTest(android.HostSupported)
65 return module.Init()
66}
67
68// Module factory for host benchmarks
69func benchmarkHostFactory() (blueprint.Module, []interface{}) {
70 module := NewBenchmark(android.HostSupported)
71 return module.Init()
72}
73
74func testPerSrcMutator(mctx android.BottomUpMutatorContext) {
75 if m, ok := mctx.Module().(*Module); ok {
76 if test, ok := m.linker.(*testBinaryLinker); ok {
77 if Bool(test.testLinker.Properties.Test_per_src) {
78 testNames := make([]string, len(m.compiler.(*baseCompiler).Properties.Srcs))
79 for i, src := range m.compiler.(*baseCompiler).Properties.Srcs {
80 testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
81 }
82 tests := mctx.CreateLocalVariations(testNames...)
83 for i, src := range m.compiler.(*baseCompiler).Properties.Srcs {
84 tests[i].(*Module).compiler.(*baseCompiler).Properties.Srcs = []string{src}
85 tests[i].(*Module).linker.(*testBinaryLinker).binaryLinker.Properties.Stem = testNames[i]
86 }
87 }
88 }
89 }
90}
91
92type testLinker struct {
93 Properties TestLinkerProperties
94}
95
Colin Cross42742b82016-08-01 13:20:05 -070096func (test *testLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
Colin Cross4d9c2d12016-07-29 12:48:20 -070097 if !test.Properties.Gtest {
98 return flags
99 }
100
101 flags.CFlags = append(flags.CFlags, "-DGTEST_HAS_STD_STRING")
102 if ctx.Host() {
103 flags.CFlags = append(flags.CFlags, "-O0", "-g")
104
105 switch ctx.Os() {
106 case android.Windows:
107 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_WINDOWS")
108 case android.Linux:
109 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX")
110 flags.LdFlags = append(flags.LdFlags, "-lpthread")
111 case android.Darwin:
112 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_MAC")
113 flags.LdFlags = append(flags.LdFlags, "-lpthread")
114 }
115 } else {
116 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX_ANDROID")
117 }
118
119 return flags
120}
121
Colin Cross42742b82016-08-01 13:20:05 -0700122func (test *testLinker) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
Colin Cross4d9c2d12016-07-29 12:48:20 -0700123 if test.Properties.Gtest {
124 if ctx.sdk() && ctx.Device() {
125 switch ctx.selectedStl() {
126 case "ndk_libc++_shared", "ndk_libc++_static":
127 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_libcxx", "libgtest_ndk_libcxx")
128 case "ndk_libgnustl_static":
129 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_gnustl", "libgtest_ndk_gnustl")
130 default:
131 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk", "libgtest_ndk")
132 }
133 } else {
134 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main", "libgtest")
135 }
136 }
137 return deps
138}
139
140type testBinaryLinker struct {
141 testLinker
142 binaryLinker
143}
144
Colin Cross42742b82016-08-01 13:20:05 -0700145func (test *testBinaryLinker) linkerInit(ctx BaseModuleContext) {
146 test.binaryLinker.linkerInit(ctx)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700147 runpath := "../../lib"
148 if ctx.toolchain().Is64Bit() {
149 runpath += "64"
150 }
151 test.dynamicProperties.RunPaths = append([]string{runpath}, test.dynamicProperties.RunPaths...)
152}
153
Colin Cross42742b82016-08-01 13:20:05 -0700154func (test *testBinaryLinker) linkerProps() []interface{} {
155 return append(test.binaryLinker.linkerProps(), &test.testLinker.Properties)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700156}
157
Colin Cross42742b82016-08-01 13:20:05 -0700158func (test *testBinaryLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
159 flags = test.binaryLinker.linkerFlags(ctx, flags)
160 flags = test.testLinker.linkerFlags(ctx, flags)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700161 return flags
162}
163
Colin Cross42742b82016-08-01 13:20:05 -0700164func (test *testBinaryLinker) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
165 deps = test.testLinker.linkerDeps(ctx, deps)
166 deps = test.binaryLinker.linkerDeps(ctx, deps)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700167 return deps
168}
169
170type testLibraryLinker struct {
171 testLinker
172 *libraryLinker
173}
174
Colin Cross42742b82016-08-01 13:20:05 -0700175func (test *testLibraryLinker) linkerProps() []interface{} {
176 return append(test.libraryLinker.linkerProps(), &test.testLinker.Properties)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700177}
178
Colin Cross42742b82016-08-01 13:20:05 -0700179func (test *testLibraryLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
180 flags = test.libraryLinker.linkerFlags(ctx, flags)
181 flags = test.testLinker.linkerFlags(ctx, flags)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700182 return flags
183}
184
Colin Cross42742b82016-08-01 13:20:05 -0700185func (test *testLibraryLinker) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
186 deps = test.testLinker.linkerDeps(ctx, deps)
187 deps = test.libraryLinker.linkerDeps(ctx, deps)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700188 return deps
189}
190
191type testInstaller struct {
192 baseInstaller
193}
194
195func (installer *testInstaller) install(ctx ModuleContext, file android.Path) {
196 installer.dir = filepath.Join(installer.dir, ctx.ModuleName())
197 installer.dir64 = filepath.Join(installer.dir64, ctx.ModuleName())
198 installer.baseInstaller.install(ctx, file)
199}
200
201func NewTest(hod android.HostOrDeviceSupported) *Module {
202 module := newModule(hod, android.MultilibBoth)
203 module.compiler = &baseCompiler{}
204 linker := &testBinaryLinker{}
205 linker.testLinker.Properties.Gtest = true
206 module.linker = linker
207 module.installer = &testInstaller{
208 baseInstaller: baseInstaller{
209 dir: "nativetest",
210 dir64: "nativetest64",
211 data: true,
212 },
213 }
214 return module
215}
216
217func NewTestLibrary(hod android.HostOrDeviceSupported) *Module {
218 module := NewLibrary(android.HostAndDeviceSupported, false, true)
219 linker := &testLibraryLinker{
220 libraryLinker: module.linker.(*libraryLinker),
221 }
222 linker.testLinker.Properties.Gtest = true
223 module.linker = linker
224 module.installer = &testInstaller{
225 baseInstaller: baseInstaller{
226 dir: "nativetest",
227 dir64: "nativetest64",
228 data: true,
229 },
230 }
231 return module
232}
233
234type benchmarkLinker struct {
235 testBinaryLinker
236}
237
Colin Cross42742b82016-08-01 13:20:05 -0700238func (benchmark *benchmarkLinker) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
239 deps = benchmark.testBinaryLinker.linkerDeps(ctx, deps)
Colin Cross4d9c2d12016-07-29 12:48:20 -0700240 deps.StaticLibs = append(deps.StaticLibs, "libgoogle-benchmark")
241 return deps
242}
243
244func NewBenchmark(hod android.HostOrDeviceSupported) *Module {
245 module := newModule(hod, android.MultilibFirst)
246 module.compiler = &baseCompiler{}
247 module.linker = &benchmarkLinker{}
248 module.installer = &testInstaller{
249 baseInstaller: baseInstaller{
250 dir: "nativetest",
251 dir64: "nativetest64",
252 data: true,
253 },
254 }
255 return module
256}