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  }