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 15package cc 16 17import ( 18 "path/filepath" 19 "strconv" 20 "strings" 21 22 "github.com/google/blueprint/proptools" 23 24 "android/soong/android" 25 "android/soong/tradefed" 26) 27 28type TestProperties struct { 29 // if set, build against the gtest library. Defaults to true. 30 Gtest *bool 31 32 // if set, use the isolated gtest runner. Defaults to false. 33 Isolated *bool 34} 35 36// Test option struct. 37type TestOptions struct { 38 // The UID that you want to run the test as on a device. 39 Run_test_as *string 40 41 // A list of free-formed strings without spaces that categorize the test. 42 Test_suite_tag []string 43 44 // a list of extra test configuration files that should be installed with the module. 45 Extra_test_configs []string `android:"path,arch_variant"` 46 47 // If the test is a hostside(no device required) unittest that shall be run during presubmit check. 48 Unit_test *bool 49 50 // Add ShippingApiLevelModuleController to auto generated test config. If the device properties 51 // for the shipping api level is less than the min_shipping_api_level, skip this module. 52 Min_shipping_api_level *int64 53 54 // Add ShippingApiLevelModuleController to auto generated test config. If any of the device 55 // shipping api level and vendor api level properties are less than the 56 // vsr_min_shipping_api_level, skip this module. 57 // As this includes the shipping api level check, it is not allowed to define 58 // min_shipping_api_level at the same time with this property. 59 Vsr_min_shipping_api_level *int64 60 61 // Add MinApiLevelModuleController with ro.vndk.version property. If ro.vndk.version has an 62 // integer value and the value is less than the min_vndk_version, skip this module. 63 Min_vndk_version *int64 64} 65 66type TestBinaryProperties struct { 67 // Create a separate binary for each source file. Useful when there is 68 // global state that can not be torn down and reset between each test suite. 69 Test_per_src *bool 70 71 // Disables the creation of a test-specific directory when used with 72 // relative_install_path. Useful if several tests need to be in the same 73 // directory, but test_per_src doesn't work. 74 No_named_install_directory *bool 75 76 // list of files or filegroup modules that provide data that should be installed alongside 77 // the test 78 Data []string `android:"path,arch_variant"` 79 80 // list of shared library modules that should be installed alongside the test 81 Data_libs []string `android:"arch_variant"` 82 83 // list of compatibility suites (for example "cts", "vts") that the module should be 84 // installed into. 85 Test_suites []string `android:"arch_variant"` 86 87 // the name of the test configuration (for example "AndroidTest.xml") that should be 88 // installed with the module. 89 Test_config *string `android:"path,arch_variant"` 90 91 // the name of the test configuration template (for example "AndroidTestTemplate.xml") that 92 // should be installed with the module. 93 Test_config_template *string `android:"path,arch_variant"` 94 95 // Test options. 96 Test_options TestOptions 97 98 // Add RootTargetPreparer to auto generated test config. This guarantees the test to run 99 // with root permission. 100 Require_root *bool 101 102 // Add RunCommandTargetPreparer to stop framework before the test and start it after the test. 103 Disable_framework *bool 104 105 // Add ShippingApiLevelModuleController to auto generated test config. If the device properties 106 // for the shipping api level is less than the test_min_api_level, skip this module. 107 // Deprecated (b/187258404). Use test_options.min_shipping_api_level instead. 108 Test_min_api_level *int64 109 110 // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml 111 // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true 112 // explicitly. 113 Auto_gen_config *bool 114 115 // Add parameterized mainline modules to auto generated test config. The options will be 116 // handled by TradeFed to download and install the specified modules on the device. 117 Test_mainline_modules []string 118} 119 120func init() { 121 android.RegisterModuleType("cc_test", TestFactory) 122 android.RegisterModuleType("cc_test_library", TestLibraryFactory) 123 android.RegisterModuleType("cc_benchmark", BenchmarkFactory) 124 android.RegisterModuleType("cc_test_host", TestHostFactory) 125 android.RegisterModuleType("cc_benchmark_host", BenchmarkHostFactory) 126} 127 128// cc_test generates a test config file and an executable binary file to test 129// specific functionality on a device. The executable binary gets an implicit 130// static_libs dependency on libgtests unless the gtest flag is set to false. 131func TestFactory() android.Module { 132 module := NewTest(android.HostAndDeviceSupported) 133 return module.Init() 134} 135 136// cc_test_library creates an archive of files (i.e. .o files) which is later 137// referenced by another module (such as cc_test, cc_defaults or cc_test_library) 138// for archiving or linking. 139func TestLibraryFactory() android.Module { 140 module := NewTestLibrary(android.HostAndDeviceSupported) 141 return module.Init() 142} 143 144// cc_benchmark compiles an executable binary that performs benchmark testing 145// of a specific component in a device. Additional files such as test suites 146// and test configuration are installed on the side of the compiled executed 147// binary. 148func BenchmarkFactory() android.Module { 149 module := NewBenchmark(android.HostAndDeviceSupported) 150 return module.Init() 151} 152 153// cc_test_host compiles a test host binary. 154func TestHostFactory() android.Module { 155 module := NewTest(android.HostSupported) 156 return module.Init() 157} 158 159// cc_benchmark_host compiles an executable binary that performs benchmark 160// testing of a specific component in the host. Additional files such as 161// test suites and test configuration are installed on the side of the 162// compiled executed binary. 163func BenchmarkHostFactory() android.Module { 164 module := NewBenchmark(android.HostSupported) 165 return module.Init() 166} 167 168type testPerSrc interface { 169 testPerSrc() bool 170 srcs() []string 171 isAllTestsVariation() bool 172 setSrc(string, string) 173 unsetSrc() 174} 175 176func (test *testBinary) testPerSrc() bool { 177 return Bool(test.Properties.Test_per_src) 178} 179 180func (test *testBinary) srcs() []string { 181 return test.baseCompiler.Properties.Srcs 182} 183 184func (test *testBinary) dataPaths() []android.DataPath { 185 return test.data 186} 187 188func (test *testBinary) isAllTestsVariation() bool { 189 stem := test.binaryDecorator.Properties.Stem 190 return stem != nil && *stem == "" 191} 192 193func (test *testBinary) setSrc(name, src string) { 194 test.baseCompiler.Properties.Srcs = []string{src} 195 test.binaryDecorator.Properties.Stem = StringPtr(name) 196} 197 198func (test *testBinary) unsetSrc() { 199 test.baseCompiler.Properties.Srcs = nil 200 test.binaryDecorator.Properties.Stem = StringPtr("") 201} 202 203var _ testPerSrc = (*testBinary)(nil) 204 205func TestPerSrcMutator(mctx android.BottomUpMutatorContext) { 206 if m, ok := mctx.Module().(*Module); ok { 207 if test, ok := m.linker.(testPerSrc); ok { 208 numTests := len(test.srcs()) 209 if test.testPerSrc() && numTests > 0 { 210 if duplicate, found := android.CheckDuplicate(test.srcs()); found { 211 mctx.PropertyErrorf("srcs", "found a duplicate entry %q", duplicate) 212 return 213 } 214 testNames := make([]string, numTests) 215 for i, src := range test.srcs() { 216 testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src)) 217 } 218 // In addition to creating one variation per test source file, 219 // create an additional "all tests" variation named "", and have it 220 // depends on all other test_per_src variations. This is useful to 221 // create subsequent dependencies of a given module on all 222 // test_per_src variations created above: by depending on 223 // variation "", that module will transitively depend on all the 224 // other test_per_src variations without the need to know their 225 // name or even their number. 226 testNames = append(testNames, "") 227 tests := mctx.CreateLocalVariations(testNames...) 228 allTests := tests[numTests] 229 allTests.(*Module).linker.(testPerSrc).unsetSrc() 230 // Prevent the "all tests" variation from being installable nor 231 // exporting to Make, as it won't create any output file. 232 allTests.(*Module).Properties.PreventInstall = true 233 allTests.(*Module).Properties.HideFromMake = true 234 for i, src := range test.srcs() { 235 tests[i].(*Module).linker.(testPerSrc).setSrc(testNames[i], src) 236 mctx.AddInterVariantDependency(testPerSrcDepTag, allTests, tests[i]) 237 } 238 mctx.AliasVariation("") 239 } 240 } 241 } 242} 243 244type testDecorator struct { 245 Properties TestProperties 246 linker *baseLinker 247} 248 249func (test *testDecorator) gtest() bool { 250 return BoolDefault(test.Properties.Gtest, true) 251} 252 253func (test *testDecorator) testBinary() bool { 254 return true 255} 256 257func (test *testDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags { 258 if !test.gtest() { 259 return flags 260 } 261 262 flags.Local.CFlags = append(flags.Local.CFlags, "-DGTEST_HAS_STD_STRING") 263 if ctx.Host() { 264 flags.Local.CFlags = append(flags.Local.CFlags, "-O0", "-g") 265 266 switch ctx.Os() { 267 case android.Windows: 268 flags.Local.CFlags = append(flags.Local.CFlags, "-DGTEST_OS_WINDOWS") 269 case android.Linux: 270 flags.Local.CFlags = append(flags.Local.CFlags, "-DGTEST_OS_LINUX") 271 case android.Darwin: 272 flags.Local.CFlags = append(flags.Local.CFlags, "-DGTEST_OS_MAC") 273 } 274 } else { 275 flags.Local.CFlags = append(flags.Local.CFlags, "-DGTEST_OS_LINUX_ANDROID") 276 } 277 278 return flags 279} 280 281func (test *testDecorator) linkerDeps(ctx BaseModuleContext, deps Deps) Deps { 282 if test.gtest() { 283 if ctx.useSdk() && ctx.Device() { 284 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main_ndk_c++", "libgtest_ndk_c++") 285 } else if BoolDefault(test.Properties.Isolated, false) { 286 deps.StaticLibs = append(deps.StaticLibs, "libgtest_isolated_main") 287 // The isolated library requires liblog, but adding it 288 // as a static library means unit tests cannot override 289 // liblog functions. Instead make it a shared library 290 // dependency. 291 deps.SharedLibs = append(deps.SharedLibs, "liblog") 292 } else { 293 deps.StaticLibs = append(deps.StaticLibs, "libgtest_main", "libgtest") 294 } 295 } 296 297 return deps 298} 299 300func (test *testDecorator) linkerInit(ctx BaseModuleContext, linker *baseLinker) { 301 // 1. Add ../../lib[64] to rpath so that out/host/linux-x86/nativetest/<test dir>/<test> can 302 // find out/host/linux-x86/lib[64]/library.so 303 // 2. Add ../../../lib[64] to rpath so that out/host/linux-x86/testcases/<test dir>/<CPU>/<test> can 304 // also find out/host/linux-x86/lib[64]/library.so 305 runpaths := []string{"../../lib", "../../../lib"} 306 for _, runpath := range runpaths { 307 if ctx.toolchain().Is64Bit() { 308 runpath += "64" 309 } 310 linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, runpath) 311 } 312 313 // add "" to rpath so that test binaries can find libraries in their own test directory 314 linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, "") 315} 316 317func (test *testDecorator) linkerProps() []interface{} { 318 return []interface{}{&test.Properties} 319} 320 321func NewTestInstaller() *baseInstaller { 322 return NewBaseInstaller("nativetest", "nativetest64", InstallInData) 323} 324 325type testBinary struct { 326 testDecorator 327 *binaryDecorator 328 *baseCompiler 329 Properties TestBinaryProperties 330 data []android.DataPath 331 testConfig android.Path 332 extraTestConfigs android.Paths 333} 334 335func (test *testBinary) linkerProps() []interface{} { 336 props := append(test.testDecorator.linkerProps(), test.binaryDecorator.linkerProps()...) 337 props = append(props, &test.Properties) 338 return props 339} 340 341func (test *testBinary) linkerInit(ctx BaseModuleContext) { 342 test.testDecorator.linkerInit(ctx, test.binaryDecorator.baseLinker) 343 test.binaryDecorator.linkerInit(ctx) 344} 345 346func (test *testBinary) linkerDeps(ctx DepsContext, deps Deps) Deps { 347 deps = test.testDecorator.linkerDeps(ctx, deps) 348 deps = test.binaryDecorator.linkerDeps(ctx, deps) 349 deps.DataLibs = append(deps.DataLibs, test.Properties.Data_libs...) 350 return deps 351} 352 353func (test *testBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags { 354 flags = test.binaryDecorator.linkerFlags(ctx, flags) 355 flags = test.testDecorator.linkerFlags(ctx, flags) 356 return flags 357} 358 359func (test *testBinary) install(ctx ModuleContext, file android.Path) { 360 // TODO: (b/167308193) Switch to /data/local/tests/unrestricted as the default install base. 361 testInstallBase := "/data/local/tmp" 362 if ctx.inVendor() || ctx.useVndk() { 363 testInstallBase = "/data/local/tests/vendor" 364 } 365 366 dataSrcPaths := android.PathsForModuleSrc(ctx, test.Properties.Data) 367 368 for _, dataSrcPath := range dataSrcPaths { 369 test.data = append(test.data, android.DataPath{SrcPath: dataSrcPath}) 370 } 371 372 ctx.VisitDirectDepsWithTag(dataLibDepTag, func(dep android.Module) { 373 depName := ctx.OtherModuleName(dep) 374 ccDep, ok := dep.(LinkableInterface) 375 376 if !ok { 377 ctx.ModuleErrorf("data_lib %q is not a linkable cc module", depName) 378 } 379 ccModule, ok := dep.(*Module) 380 if !ok { 381 ctx.ModuleErrorf("data_lib %q is not a cc module", depName) 382 } 383 if ccDep.OutputFile().Valid() { 384 test.data = append(test.data, 385 android.DataPath{SrcPath: ccDep.OutputFile().Path(), 386 RelativeInstallPath: ccModule.installer.relativeInstallPath()}) 387 } 388 }) 389 390 var configs []tradefed.Config 391 for _, module := range test.Properties.Test_mainline_modules { 392 configs = append(configs, tradefed.Option{Name: "config-descriptor:metadata", Key: "mainline-param", Value: module}) 393 } 394 if Bool(test.Properties.Require_root) { 395 configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil}) 396 } else { 397 var options []tradefed.Option 398 options = append(options, tradefed.Option{Name: "force-root", Value: "false"}) 399 configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", options}) 400 } 401 if Bool(test.Properties.Disable_framework) { 402 var options []tradefed.Option 403 configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.StopServicesSetup", options}) 404 } 405 if Bool(test.testDecorator.Properties.Isolated) { 406 configs = append(configs, tradefed.Option{Name: "not-shardable", Value: "true"}) 407 } 408 if test.Properties.Test_options.Run_test_as != nil { 409 configs = append(configs, tradefed.Option{Name: "run-test-as", Value: String(test.Properties.Test_options.Run_test_as)}) 410 } 411 for _, tag := range test.Properties.Test_options.Test_suite_tag { 412 configs = append(configs, tradefed.Option{Name: "test-suite-tag", Value: tag}) 413 } 414 if test.Properties.Test_options.Min_shipping_api_level != nil { 415 if test.Properties.Test_options.Vsr_min_shipping_api_level != nil { 416 ctx.PropertyErrorf("test_options.min_shipping_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.") 417 } 418 var options []tradefed.Option 419 options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Min_shipping_api_level), 10)}) 420 configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options}) 421 } else if test.Properties.Test_min_api_level != nil { 422 // TODO: (b/187258404) Remove test.Properties.Test_min_api_level 423 if test.Properties.Test_options.Vsr_min_shipping_api_level != nil { 424 ctx.PropertyErrorf("test_min_api_level", "must not be set at the same time as 'vsr_min_shipping_api_level'.") 425 } 426 var options []tradefed.Option 427 options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_min_api_level), 10)}) 428 configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options}) 429 } 430 if test.Properties.Test_options.Vsr_min_shipping_api_level != nil { 431 var options []tradefed.Option 432 options = append(options, tradefed.Option{Name: "vsr-min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Vsr_min_shipping_api_level), 10)}) 433 configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.ShippingApiLevelModuleController", options}) 434 } 435 if test.Properties.Test_options.Min_vndk_version != nil { 436 var options []tradefed.Option 437 options = append(options, tradefed.Option{Name: "min-api-level", Value: strconv.FormatInt(int64(*test.Properties.Test_options.Min_vndk_version), 10)}) 438 options = append(options, tradefed.Option{Name: "api-level-prop", Value: "ro.vndk.version"}) 439 configs = append(configs, tradefed.Object{"module_controller", "com.android.tradefed.testtype.suite.module.MinApiLevelModuleController", options}) 440 } 441 442 test.testConfig = tradefed.AutoGenNativeTestConfig(ctx, test.Properties.Test_config, 443 test.Properties.Test_config_template, test.Properties.Test_suites, configs, test.Properties.Auto_gen_config, testInstallBase) 444 445 test.extraTestConfigs = android.PathsForModuleSrc(ctx, test.Properties.Test_options.Extra_test_configs) 446 447 test.binaryDecorator.baseInstaller.dir = "nativetest" 448 test.binaryDecorator.baseInstaller.dir64 = "nativetest64" 449 450 if !Bool(test.Properties.No_named_install_directory) { 451 test.binaryDecorator.baseInstaller.relative = ctx.ModuleName() 452 } else if String(test.binaryDecorator.baseInstaller.Properties.Relative_install_path) == "" { 453 ctx.PropertyErrorf("no_named_install_directory", "Module install directory may only be disabled if relative_install_path is set") 454 } 455 456 if ctx.Host() && test.gtest() && test.Properties.Test_options.Unit_test == nil { 457 test.Properties.Test_options.Unit_test = proptools.BoolPtr(true) 458 } 459 test.binaryDecorator.baseInstaller.install(ctx, file) 460} 461 462func NewTest(hod android.HostOrDeviceSupported) *Module { 463 module, binary := NewBinary(hod) 464 module.multilib = android.MultilibBoth 465 binary.baseInstaller = NewTestInstaller() 466 467 test := &testBinary{ 468 testDecorator: testDecorator{ 469 linker: binary.baseLinker, 470 }, 471 binaryDecorator: binary, 472 baseCompiler: NewBaseCompiler(), 473 } 474 module.compiler = test 475 module.linker = test 476 module.installer = test 477 return module 478} 479 480type testLibrary struct { 481 testDecorator 482 *libraryDecorator 483} 484 485func (test *testLibrary) linkerProps() []interface{} { 486 return append(test.testDecorator.linkerProps(), test.libraryDecorator.linkerProps()...) 487} 488 489func (test *testLibrary) linkerInit(ctx BaseModuleContext) { 490 test.testDecorator.linkerInit(ctx, test.libraryDecorator.baseLinker) 491 test.libraryDecorator.linkerInit(ctx) 492} 493 494func (test *testLibrary) linkerDeps(ctx DepsContext, deps Deps) Deps { 495 deps = test.testDecorator.linkerDeps(ctx, deps) 496 deps = test.libraryDecorator.linkerDeps(ctx, deps) 497 return deps 498} 499 500func (test *testLibrary) linkerFlags(ctx ModuleContext, flags Flags) Flags { 501 flags = test.libraryDecorator.linkerFlags(ctx, flags) 502 flags = test.testDecorator.linkerFlags(ctx, flags) 503 return flags 504} 505 506func NewTestLibrary(hod android.HostOrDeviceSupported) *Module { 507 module, library := NewLibrary(android.HostAndDeviceSupported) 508 library.baseInstaller = NewTestInstaller() 509 test := &testLibrary{ 510 testDecorator: testDecorator{ 511 linker: library.baseLinker, 512 }, 513 libraryDecorator: library, 514 } 515 module.linker = test 516 return module 517} 518 519type BenchmarkProperties struct { 520 // list of files or filegroup modules that provide data that should be installed alongside 521 // the test 522 Data []string `android:"path"` 523 524 // list of compatibility suites (for example "cts", "vts") that the module should be 525 // installed into. 526 Test_suites []string `android:"arch_variant"` 527 528 // the name of the test configuration (for example "AndroidTest.xml") that should be 529 // installed with the module. 530 Test_config *string `android:"path,arch_variant"` 531 532 // the name of the test configuration template (for example "AndroidTestTemplate.xml") that 533 // should be installed with the module. 534 Test_config_template *string `android:"path,arch_variant"` 535 536 // Add RootTargetPreparer to auto generated test config. This guarantees the test to run 537 // with root permission. 538 Require_root *bool 539 540 // Flag to indicate whether or not to create test config automatically. If AndroidTest.xml 541 // doesn't exist next to the Android.bp, this attribute doesn't need to be set to true 542 // explicitly. 543 Auto_gen_config *bool 544} 545 546type benchmarkDecorator struct { 547 *binaryDecorator 548 Properties BenchmarkProperties 549 data android.Paths 550 testConfig android.Path 551} 552 553func (benchmark *benchmarkDecorator) linkerInit(ctx BaseModuleContext) { 554 runpath := "../../lib" 555 if ctx.toolchain().Is64Bit() { 556 runpath += "64" 557 } 558 benchmark.baseLinker.dynamicProperties.RunPaths = append(benchmark.baseLinker.dynamicProperties.RunPaths, runpath) 559 benchmark.binaryDecorator.linkerInit(ctx) 560} 561 562func (benchmark *benchmarkDecorator) linkerProps() []interface{} { 563 props := benchmark.binaryDecorator.linkerProps() 564 props = append(props, &benchmark.Properties) 565 return props 566} 567 568func (benchmark *benchmarkDecorator) linkerDeps(ctx DepsContext, deps Deps) Deps { 569 deps = benchmark.binaryDecorator.linkerDeps(ctx, deps) 570 deps.StaticLibs = append(deps.StaticLibs, "libgoogle-benchmark") 571 return deps 572} 573 574func (benchmark *benchmarkDecorator) install(ctx ModuleContext, file android.Path) { 575 benchmark.data = android.PathsForModuleSrc(ctx, benchmark.Properties.Data) 576 577 var configs []tradefed.Config 578 if Bool(benchmark.Properties.Require_root) { 579 configs = append(configs, tradefed.Object{"target_preparer", "com.android.tradefed.targetprep.RootTargetPreparer", nil}) 580 } 581 benchmark.testConfig = tradefed.AutoGenNativeBenchmarkTestConfig(ctx, benchmark.Properties.Test_config, 582 benchmark.Properties.Test_config_template, benchmark.Properties.Test_suites, configs, benchmark.Properties.Auto_gen_config) 583 584 benchmark.binaryDecorator.baseInstaller.dir = filepath.Join("benchmarktest", ctx.ModuleName()) 585 benchmark.binaryDecorator.baseInstaller.dir64 = filepath.Join("benchmarktest64", ctx.ModuleName()) 586 benchmark.binaryDecorator.baseInstaller.install(ctx, file) 587} 588 589func NewBenchmark(hod android.HostOrDeviceSupported) *Module { 590 module, binary := NewBinary(hod) 591 module.multilib = android.MultilibBoth 592 binary.baseInstaller = NewBaseInstaller("benchmarktest", "benchmarktest64", InstallInData) 593 594 benchmark := &benchmarkDecorator{ 595 binaryDecorator: binary, 596 } 597 module.linker = benchmark 598 module.installer = benchmark 599 return module 600} 601