github.com/westcoastroms/westcoastroms-build@v0.0.0-20190928114312-2350e5a73030/build/soong/cc/test.go (about) 1 // 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 15 package cc 16 17 import ( 18 "path/filepath" 19 "runtime" 20 "strings" 21 22 "android/soong/android" 23 ) 24 25 type TestProperties struct { 26 // if set, build against the gtest library. Defaults to true. 27 Gtest *bool 28 } 29 30 type TestBinaryProperties struct { 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 // Disables the creation of a test-specific directory when used with 36 // relative_install_path. Useful if several tests need to be in the same 37 // directory, but test_per_src doesn't work. 38 No_named_install_directory *bool 39 40 // list of files or filegroup modules that provide data that should be installed alongside 41 // the test 42 Data []string 43 44 // list of compatibility suites (for example "cts", "vts") that the module should be 45 // installed into. 46 Test_suites []string `android:"arch_variant"` 47 } 48 49 func init() { 50 android.RegisterModuleType("cc_test", TestFactory) 51 android.RegisterModuleType("cc_test_library", TestLibraryFactory) 52 android.RegisterModuleType("cc_benchmark", BenchmarkFactory) 53 android.RegisterModuleType("cc_test_host", TestHostFactory) 54 android.RegisterModuleType("cc_benchmark_host", BenchmarkHostFactory) 55 } 56 57 // Module factory for tests 58 func TestFactory() android.Module { 59 module := NewTest(android.HostAndDeviceSupported) 60 return module.Init() 61 } 62 63 // Module factory for test libraries 64 func TestLibraryFactory() android.Module { 65 module := NewTestLibrary(android.HostAndDeviceSupported) 66 return module.Init() 67 } 68 69 // Module factory for benchmarks 70 func BenchmarkFactory() android.Module { 71 module := NewBenchmark(android.HostAndDeviceSupported) 72 return module.Init() 73 } 74 75 // Module factory for host tests 76 func TestHostFactory() android.Module { 77 module := NewTest(android.HostSupported) 78 return module.Init() 79 } 80 81 // Module factory for host benchmarks 82 func BenchmarkHostFactory() android.Module { 83 module := NewBenchmark(android.HostSupported) 84 return module.Init() 85 } 86 87 type testPerSrc interface { 88 testPerSrc() bool 89 srcs() []string 90 setSrc(string, string) 91 } 92 93 func (test *testBinary) testPerSrc() bool { 94 return Bool(test.Properties.Test_per_src) 95 } 96 97 func (test *testBinary) srcs() []string { 98 return test.baseCompiler.Properties.Srcs 99 } 100 101 func (test *testBinary) setSrc(name, src string) { 102 test.baseCompiler.Properties.Srcs = []string{src} 103 test.binaryDecorator.Properties.Stem = StringPtr(name) 104 } 105 106 var _ testPerSrc = (*testBinary)(nil) 107 108 func testPerSrcMutator(mctx android.BottomUpMutatorContext) { 109 if m, ok := mctx.Module().(*Module); ok { 110 if test, ok := m.linker.(testPerSrc); ok { 111 if test.testPerSrc() && len(test.srcs()) > 0 { 112 testNames := make([]string, len(test.srcs())) 113 for i, src := range test.srcs() { 114 testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src)) 115 } 116 tests := mctx.CreateLocalVariations(testNames...) 117 for i, src := range test.srcs() { 118 tests[i].(*Module).linker.(testPerSrc).setSrc(testNames[i], src) 119 } 120 } 121 } 122 } 123 } 124 125 type testDecorator struct { 126 Properties TestProperties 127 linker *baseLinker 128 } 129 130 func (test *testDecorator) gtest() bool { 131 return test.Properties.Gtest == nil || *test.Properties.Gtest == true 132 } 133 134 func (test *testDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags { 135 if !test.gtest() { 136 return flags 137 } 138 139 flags.CFlags = append(flags.CFlags, "-DGTEST_HAS_STD_STRING") 140 if ctx.Host() { 141 flags.CFlags = append(flags.CFlags, "-O0", "-g") 142 143 switch ctx.Os() { 144 case android.Windows: 145 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_WINDOWS") 146 case android.Linux: 147 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX") 148 case android.Darwin: 149 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_MAC") 150 } 151 } else { 152 flags.CFlags = append(flags.CFlags, "-DGTEST_OS_LINUX_ANDROID") 153 } 154 155 return flags 156 } 157 158 func (test *testDecorator) linkerDeps(ctx BaseModuleContext, deps Deps) Deps { 159 if test.gtest() { 160 if ctx.useSdk() && ctx.Device() { 161 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_c++", "libgtest_ndk_c++") 162 } else { 163 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main", "libgtest") 164 } 165 } 166 167 return deps 168 } 169 170 func (test *testDecorator) linkerInit(ctx BaseModuleContext, linker *baseLinker) { 171 // add ../../lib[64] to rpath so that out/host/linux-x86/nativetest/<test dir>/<test> can 172 // find out/host/linux-x86/lib[64]/library.so 173 runpath := "../../lib" 174 if ctx.toolchain().Is64Bit() { 175 runpath += "64" 176 } 177 linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, runpath) 178 179 // add "" to rpath so that test binaries can find libraries in their own test directory 180 linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, "") 181 } 182 183 func (test *testDecorator) linkerProps() []interface{} { 184 return []interface{}{&test.Properties} 185 } 186 187 func NewTestInstaller() *baseInstaller { 188 return NewBaseInstaller("nativetest", "nativetest64", InstallInData) 189 } 190 191 type testBinary struct { 192 testDecorator 193 *binaryDecorator 194 *baseCompiler 195 Properties TestBinaryProperties 196 data android.Paths 197 } 198 199 func (test *testBinary) linkerProps() []interface{} { 200 props := append(test.testDecorator.linkerProps(), test.binaryDecorator.linkerProps()...) 201 props = append(props, &test.Properties) 202 return props 203 } 204 205 func (test *testBinary) linkerInit(ctx BaseModuleContext) { 206 test.testDecorator.linkerInit(ctx, test.binaryDecorator.baseLinker) 207 test.binaryDecorator.linkerInit(ctx) 208 } 209 210 func (test *testBinary) linkerDeps(ctx DepsContext, deps Deps) Deps { 211 android.ExtractSourcesDeps(ctx, test.Properties.Data) 212 213 deps = test.testDecorator.linkerDeps(ctx, deps) 214 deps = test.binaryDecorator.linkerDeps(ctx, deps) 215 return deps 216 } 217 218 func (test *testBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags { 219 flags = test.binaryDecorator.linkerFlags(ctx, flags) 220 flags = test.testDecorator.linkerFlags(ctx, flags) 221 return flags 222 } 223 224 func (test *testBinary) install(ctx ModuleContext, file android.Path) { 225 test.data = ctx.ExpandSources(test.Properties.Data, nil) 226 227 test.binaryDecorator.baseInstaller.dir = "nativetest" 228 test.binaryDecorator.baseInstaller.dir64 = "nativetest64" 229 230 if !Bool(test.Properties.No_named_install_directory) { 231 test.binaryDecorator.baseInstaller.relative = ctx.ModuleName() 232 } else if String(test.binaryDecorator.baseInstaller.Properties.Relative_install_path) == "" { 233 ctx.PropertyErrorf("no_named_install_directory", "Module install directory may only be disabled if relative_install_path is set") 234 } 235 236 test.binaryDecorator.baseInstaller.install(ctx, file) 237 } 238 239 func NewTest(hod android.HostOrDeviceSupported) *Module { 240 module, binary := NewBinary(hod) 241 module.multilib = android.MultilibBoth 242 binary.baseInstaller = NewTestInstaller() 243 244 test := &testBinary{ 245 testDecorator: testDecorator{ 246 linker: binary.baseLinker, 247 }, 248 binaryDecorator: binary, 249 baseCompiler: NewBaseCompiler(), 250 } 251 module.compiler = test 252 module.linker = test 253 module.installer = test 254 return module 255 } 256 257 type testLibrary struct { 258 testDecorator 259 *libraryDecorator 260 } 261 262 func (test *testLibrary) linkerProps() []interface{} { 263 return append(test.testDecorator.linkerProps(), test.libraryDecorator.linkerProps()...) 264 } 265 266 func (test *testLibrary) linkerInit(ctx BaseModuleContext) { 267 test.testDecorator.linkerInit(ctx, test.libraryDecorator.baseLinker) 268 test.libraryDecorator.linkerInit(ctx) 269 } 270 271 func (test *testLibrary) linkerDeps(ctx DepsContext, deps Deps) Deps { 272 deps = test.testDecorator.linkerDeps(ctx, deps) 273 deps = test.libraryDecorator.linkerDeps(ctx, deps) 274 return deps 275 } 276 277 func (test *testLibrary) linkerFlags(ctx ModuleContext, flags Flags) Flags { 278 flags = test.libraryDecorator.linkerFlags(ctx, flags) 279 flags = test.testDecorator.linkerFlags(ctx, flags) 280 return flags 281 } 282 283 func NewTestLibrary(hod android.HostOrDeviceSupported) *Module { 284 module, library := NewLibrary(android.HostAndDeviceSupported) 285 library.baseInstaller = NewTestInstaller() 286 test := &testLibrary{ 287 testDecorator: testDecorator{ 288 linker: library.baseLinker, 289 }, 290 libraryDecorator: library, 291 } 292 module.linker = test 293 return module 294 } 295 296 type BenchmarkProperties struct { 297 // list of files or filegroup modules that provide data that should be installed alongside 298 // the test 299 Data []string 300 301 // list of compatibility suites (for example "cts", "vts") that the module should be 302 // installed into. 303 Test_suites []string 304 } 305 306 type benchmarkDecorator struct { 307 *binaryDecorator 308 Properties BenchmarkProperties 309 data android.Paths 310 } 311 312 func (benchmark *benchmarkDecorator) linkerInit(ctx BaseModuleContext) { 313 runpath := "../../lib" 314 if ctx.toolchain().Is64Bit() { 315 runpath += "64" 316 } 317 benchmark.baseLinker.dynamicProperties.RunPaths = append(benchmark.baseLinker.dynamicProperties.RunPaths, runpath) 318 benchmark.binaryDecorator.linkerInit(ctx) 319 } 320 321 func (benchmark *benchmarkDecorator) linkerProps() []interface{} { 322 props := benchmark.binaryDecorator.linkerProps() 323 props = append(props, &benchmark.Properties) 324 return props 325 } 326 327 func (benchmark *benchmarkDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps { 328 android.ExtractSourcesDeps(ctx, benchmark.Properties.Data) 329 deps = benchmark.binaryDecorator.linkerDeps(ctx, deps) 330 deps.StaticLibs = append(deps.StaticLibs, "libgoogle-benchmark") 331 return deps 332 } 333 334 func (benchmark *benchmarkDecorator) install(ctx ModuleContext, file android.Path) { 335 benchmark.data = ctx.ExpandSources(benchmark.Properties.Data, nil) 336 benchmark.binaryDecorator.baseInstaller.dir = filepath.Join("benchmarktest", ctx.ModuleName()) 337 benchmark.binaryDecorator.baseInstaller.dir64 = filepath.Join("benchmarktest64", ctx.ModuleName()) 338 benchmark.binaryDecorator.baseInstaller.install(ctx, file) 339 } 340 341 func NewBenchmark(hod android.HostOrDeviceSupported) *Module { 342 // Benchmarks aren't supported on Darwin 343 if runtime.GOOS == "darwin" { 344 switch hod { 345 case android.HostAndDeviceSupported: 346 hod = android.DeviceSupported 347 case android.HostSupported: 348 hod = android.NeitherHostNorDeviceSupported 349 } 350 } 351 352 module, binary := NewBinary(hod) 353 module.multilib = android.MultilibBoth 354 binary.baseInstaller = NewBaseInstaller("benchmarktest", "benchmarktest64", InstallInData) 355 356 benchmark := &benchmarkDecorator{ 357 binaryDecorator: binary, 358 } 359 module.linker = benchmark 360 module.installer = benchmark 361 return module 362 }