Refactor cc modules to use decorators instead of inheritance
For example , instead of trying to have libraryLinker inherit from
baseLinker and libraryCompiler inherit from baseCompiler, create a
single decorator object that wraps both baseLinker and baseCompiler.
Test: Builds, no unexpected changes to build.ninja
Change-Id: I2468adaea8466c203a240259ba5694b8b1df7a52
diff --git a/cc/test.go b/cc/test.go
index d9b8571..3b89a10 100644
--- a/cc/test.go
+++ b/cc/test.go
@@ -24,10 +24,12 @@
"android/soong/android"
)
-type TestLinkerProperties struct {
+type TestProperties struct {
// if set, build against the gtest library. Defaults to true.
Gtest bool
+}
+type TestBinaryProperties struct {
// Create a separate binary for each source file. Useful when there is
// global state that can not be torn down and reset between each test suite.
Test_per_src *bool
@@ -71,29 +73,50 @@
return module.Init()
}
+type testPerSrc interface {
+ testPerSrc() bool
+ srcs() []string
+ setSrc(string, string)
+}
+
+func (test *testBinary) testPerSrc() bool {
+ return Bool(test.Properties.Test_per_src)
+}
+
+func (test *testBinary) srcs() []string {
+ return test.baseCompiler.Properties.Srcs
+}
+
+func (test *testBinary) setSrc(name, src string) {
+ test.baseCompiler.Properties.Srcs = []string{src}
+ test.binaryDecorator.Properties.Stem = name
+}
+
+var _ testPerSrc = (*testBinary)(nil)
+
func testPerSrcMutator(mctx android.BottomUpMutatorContext) {
if m, ok := mctx.Module().(*Module); ok {
- if test, ok := m.linker.(*testBinaryLinker); ok {
- if Bool(test.testLinker.Properties.Test_per_src) {
- testNames := make([]string, len(m.compiler.(*baseCompiler).Properties.Srcs))
- for i, src := range m.compiler.(*baseCompiler).Properties.Srcs {
+ if test, ok := m.linker.(testPerSrc); ok {
+ if test.testPerSrc() && len(test.srcs()) > 0 {
+ testNames := make([]string, len(test.srcs()))
+ for i, src := range test.srcs() {
testNames[i] = strings.TrimSuffix(filepath.Base(src), filepath.Ext(src))
}
tests := mctx.CreateLocalVariations(testNames...)
- for i, src := range m.compiler.(*baseCompiler).Properties.Srcs {
- tests[i].(*Module).compiler.(*baseCompiler).Properties.Srcs = []string{src}
- tests[i].(*Module).linker.(*testBinaryLinker).binaryLinker.Properties.Stem = testNames[i]
+ for i, src := range test.srcs() {
+ tests[i].(*Module).linker.(testPerSrc).setSrc(testNames[i], src)
}
}
}
}
}
-type testLinker struct {
- Properties TestLinkerProperties
+type testDecorator struct {
+ Properties TestProperties
+ linker *baseLinker
}
-func (test *testLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
+func (test *testDecorator) linkerFlags(ctx ModuleContext, flags Flags) Flags {
if !test.Properties.Gtest {
return flags
}
@@ -119,7 +142,7 @@
return flags
}
-func (test *testLinker) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
+func (test *testDecorator) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
if test.Properties.Gtest {
if ctx.sdk() && ctx.Device() {
switch ctx.selectedStl() {
@@ -134,123 +157,156 @@
deps.StaticLibs = append(deps.StaticLibs, "libgtest_main", "libgtest")
}
}
+
return deps
}
-type testBinaryLinker struct {
- testLinker
- binaryLinker
-}
-
-func (test *testBinaryLinker) linkerInit(ctx BaseModuleContext) {
- test.binaryLinker.linkerInit(ctx)
+func (test *testDecorator) linkerInit(ctx BaseModuleContext, linker *baseLinker) {
runpath := "../../lib"
if ctx.toolchain().Is64Bit() {
runpath += "64"
}
- test.dynamicProperties.RunPaths = append([]string{runpath}, test.dynamicProperties.RunPaths...)
+ linker.dynamicProperties.RunPaths = append(linker.dynamicProperties.RunPaths, runpath)
}
-func (test *testBinaryLinker) linkerProps() []interface{} {
- return append(test.binaryLinker.linkerProps(), &test.testLinker.Properties)
+func (test *testDecorator) linkerProps() []interface{} {
+ return []interface{}{&test.Properties}
}
-func (test *testBinaryLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
- flags = test.binaryLinker.linkerFlags(ctx, flags)
- flags = test.testLinker.linkerFlags(ctx, flags)
- return flags
+func NewTestInstaller() *baseInstaller {
+ return NewBaseInstaller("nativetest", "nativetest64", InstallInData)
}
-func (test *testBinaryLinker) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
- deps = test.testLinker.linkerDeps(ctx, deps)
- deps = test.binaryLinker.linkerDeps(ctx, deps)
+type testBinary struct {
+ testDecorator
+ *binaryDecorator
+ *baseCompiler
+ *baseInstaller
+ Properties TestBinaryProperties
+}
+
+func (test *testBinary) linkerProps() []interface{} {
+ props := append(test.testDecorator.linkerProps(), test.binaryDecorator.linkerProps()...)
+ props = append(props, &test.Properties)
+ return props
+}
+
+func (test *testBinary) linkerInit(ctx BaseModuleContext) {
+ test.testDecorator.linkerInit(ctx, test.binaryDecorator.baseLinker)
+ test.binaryDecorator.linkerInit(ctx)
+}
+
+func (test *testBinary) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
+ deps = test.testDecorator.linkerDeps(ctx, deps)
+ deps = test.binaryDecorator.linkerDeps(ctx, deps)
return deps
}
-type testLibraryLinker struct {
- testLinker
- *libraryLinker
-}
-
-func (test *testLibraryLinker) linkerProps() []interface{} {
- return append(test.libraryLinker.linkerProps(), &test.testLinker.Properties)
-}
-
-func (test *testLibraryLinker) linkerFlags(ctx ModuleContext, flags Flags) Flags {
- flags = test.libraryLinker.linkerFlags(ctx, flags)
- flags = test.testLinker.linkerFlags(ctx, flags)
+func (test *testBinary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
+ flags = test.binaryDecorator.linkerFlags(ctx, flags)
+ flags = test.testDecorator.linkerFlags(ctx, flags)
return flags
}
-func (test *testLibraryLinker) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
- deps = test.testLinker.linkerDeps(ctx, deps)
- deps = test.libraryLinker.linkerDeps(ctx, deps)
- return deps
-}
-
-type testInstaller struct {
- baseInstaller
-}
-
-func (installer *testInstaller) install(ctx ModuleContext, file android.Path) {
- installer.dir = filepath.Join(installer.dir, ctx.ModuleName())
- installer.dir64 = filepath.Join(installer.dir64, ctx.ModuleName())
- installer.baseInstaller.install(ctx, file)
+func (test *testBinary) install(ctx ModuleContext, file android.Path) {
+ test.baseInstaller.dir = filepath.Join("nativetest", ctx.ModuleName())
+ test.baseInstaller.dir64 = filepath.Join("nativetest64", ctx.ModuleName())
+ test.baseInstaller.install(ctx, file)
}
func NewTest(hod android.HostOrDeviceSupported) *Module {
- module := newModule(hod, android.MultilibBoth)
- module.compiler = &baseCompiler{}
- linker := &testBinaryLinker{}
- linker.testLinker.Properties.Gtest = true
- module.linker = linker
- module.installer = &testInstaller{
- baseInstaller: baseInstaller{
- dir: "nativetest",
- dir64: "nativetest64",
- data: true,
+ module, binary := NewBinary(hod)
+ module.multilib = android.MultilibBoth
+
+ test := &testBinary{
+ testDecorator: testDecorator{
+ linker: binary.baseLinker,
},
+ binaryDecorator: binary,
+ baseCompiler: NewBaseCompiler(),
+ baseInstaller: NewTestInstaller(),
}
+ test.testDecorator.Properties.Gtest = true
+ module.compiler = test
+ module.linker = test
+ module.installer = test
return module
}
+type testLibrary struct {
+ testDecorator
+ *libraryDecorator
+}
+
+func (test *testLibrary) linkerProps() []interface{} {
+ return append(test.testDecorator.linkerProps(), test.libraryDecorator.linkerProps()...)
+}
+
+func (test *testLibrary) linkerInit(ctx BaseModuleContext) {
+ test.testDecorator.linkerInit(ctx, test.libraryDecorator.baseLinker)
+ test.libraryDecorator.linkerInit(ctx)
+}
+
+func (test *testLibrary) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
+ deps = test.testDecorator.linkerDeps(ctx, deps)
+ deps = test.libraryDecorator.linkerDeps(ctx, deps)
+ return deps
+}
+
+func (test *testLibrary) linkerFlags(ctx ModuleContext, flags Flags) Flags {
+ flags = test.libraryDecorator.linkerFlags(ctx, flags)
+ flags = test.testDecorator.linkerFlags(ctx, flags)
+ return flags
+}
+
func NewTestLibrary(hod android.HostOrDeviceSupported) *Module {
- module := NewLibrary(android.HostAndDeviceSupported, false, true)
- linker := &testLibraryLinker{
- libraryLinker: module.linker.(*libraryLinker),
- }
- linker.testLinker.Properties.Gtest = true
- module.linker = linker
- module.installer = &testInstaller{
- baseInstaller: baseInstaller{
- dir: "nativetest",
- dir64: "nativetest64",
- data: true,
+ module, library := NewLibrary(android.HostAndDeviceSupported, false, true)
+ test := &testLibrary{
+ testDecorator: testDecorator{
+ linker: library.baseLinker,
},
+ libraryDecorator: library,
}
+ test.testDecorator.Properties.Gtest = true
+ module.linker = test
+ module.installer = nil
return module
}
-type benchmarkLinker struct {
- testBinaryLinker
+type benchmarkDecorator struct {
+ *binaryDecorator
+ *baseInstaller
}
-func (benchmark *benchmarkLinker) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
- deps = benchmark.testBinaryLinker.linkerDeps(ctx, deps)
+func (benchmark *benchmarkDecorator) linkerInit(ctx BaseModuleContext) {
+ runpath := "../../lib"
+ if ctx.toolchain().Is64Bit() {
+ runpath += "64"
+ }
+ benchmark.baseLinker.dynamicProperties.RunPaths = append(benchmark.baseLinker.dynamicProperties.RunPaths, runpath)
+ benchmark.binaryDecorator.linkerInit(ctx)
+}
+
+func (benchmark *benchmarkDecorator) linkerDeps(ctx BaseModuleContext, deps Deps) Deps {
+ deps = benchmark.binaryDecorator.linkerDeps(ctx, deps)
deps.StaticLibs = append(deps.StaticLibs, "libgoogle-benchmark")
return deps
}
+func (benchmark *benchmarkDecorator) install(ctx ModuleContext, file android.Path) {
+ benchmark.baseInstaller.dir = filepath.Join("nativetest", ctx.ModuleName())
+ benchmark.baseInstaller.dir64 = filepath.Join("nativetest64", ctx.ModuleName())
+}
+
func NewBenchmark(hod android.HostOrDeviceSupported) *Module {
- module := newModule(hod, android.MultilibFirst)
- module.compiler = &baseCompiler{}
- module.linker = &benchmarkLinker{}
- module.installer = &testInstaller{
- baseInstaller: baseInstaller{
- dir: "nativetest",
- dir64: "nativetest64",
- data: true,
- },
+ module, binary := NewBinary(hod)
+ module.multilib = android.MultilibBoth
+
+ benchmark := &benchmarkDecorator{
+ binaryDecorator: binary,
+ baseInstaller: NewTestInstaller(),
}
+ module.linker = benchmark
+ module.installer = benchmark
return module
}