Squash vendor sources before linkageMutator runs
linkageMutator removes srcs property of the shared variant of a lib in
order to reuse *.o files compiled for the static variant also to the
shared variant.
However, this causes problem when vendor-specific srcs are specified in
target: {vendor: {srcs: ["..."]}}. For example, let's assume
cc_library {
name: "libfoo",
srcs: ["foo.c"],
target: {
vendor: {
srcs: ["bar.c"],
},
},
}
Then,
static_vendor: inputs = foo.o, bar.o
shared_vendor: inputs = foo.o (from static_vendor), bar.o (from
static_vendor), bar.o
So, bar.o is included twice and this causes multiple symbol definition
error.
In order to handle the problem, vendor mutator is applied before the
linkage mutator and the vendor-specific srcs are squashed in the vendor
mutator.
Bug: 67731122
Test: build
Test: cc_test.go
Change-Id: I2a5390295dddfc41260e9b6f02746908cdf47228
diff --git a/android/config.go b/android/config.go
index 9061652..5abda26 100644
--- a/android/config.go
+++ b/android/config.go
@@ -193,8 +193,8 @@
config.Targets = map[OsClass][]Target{
Device: []Target{
- {Android, Arch{ArchType: Arm64, Native: true}},
- {Android, Arch{ArchType: Arm, Native: true}},
+ {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true}},
+ {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true}},
},
Host: []Target{
{BuildOs, Arch{ArchType: X86_64}},
diff --git a/cc/cc.go b/cc/cc.go
index 0404cfb..4c02e9e 100644
--- a/cc/cc.go
+++ b/cc/cc.go
@@ -34,9 +34,9 @@
android.RegisterModuleType("cc_defaults", defaultsFactory)
android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("image", vendorMutator).Parallel()
ctx.BottomUp("link", linkageMutator).Parallel()
ctx.BottomUp("vndk", vndkMutator).Parallel()
- ctx.BottomUp("image", vendorMutator).Parallel()
ctx.BottomUp("ndk_api", ndkApiMutator).Parallel()
ctx.BottomUp("test_per_src", testPerSrcMutator).Parallel()
ctx.BottomUp("begin", beginMutator).Parallel()
@@ -1297,6 +1297,16 @@
vendorMode = "vendor"
)
+func squashVendorSrcs(m *Module) {
+ if lib, ok := m.compiler.(*libraryDecorator); ok {
+ lib.baseCompiler.Properties.Srcs = append(lib.baseCompiler.Properties.Srcs,
+ lib.baseCompiler.Properties.Target.Vendor.Srcs...)
+
+ lib.baseCompiler.Properties.Exclude_srcs = append(lib.baseCompiler.Properties.Exclude_srcs,
+ lib.baseCompiler.Properties.Target.Vendor.Exclude_srcs...)
+ }
+}
+
func vendorMutator(mctx android.BottomUpMutatorContext) {
if mctx.Os() != android.Android {
return
@@ -1352,11 +1362,15 @@
// This will be available in both /system and /vendor
// or a /system directory that is available to vendor.
mod := mctx.CreateVariations(coreMode, vendorMode)
- mod[1].(*Module).Properties.UseVndk = true
+ vendor := mod[1].(*Module)
+ vendor.Properties.UseVndk = true
+ squashVendorSrcs(vendor)
} else if mctx.Vendor() && m.Properties.Sdk_version == "" {
// This will be available in /vendor only
mod := mctx.CreateVariations(vendorMode)
- mod[0].(*Module).Properties.UseVndk = true
+ vendor := mod[0].(*Module)
+ vendor.Properties.UseVndk = true
+ squashVendorSrcs(vendor)
} else {
// This is either in /system (or similar: /data), or is a
// modules built with the NDK. Modules built with the NDK
diff --git a/cc/cc_test.go b/cc/cc_test.go
index 92120a5..94e3e66 100644
--- a/cc/cc_test.go
+++ b/cc/cc_test.go
@@ -2,10 +2,136 @@
import (
"android/soong/android"
+ "io/ioutil"
+ "os"
"reflect"
"testing"
+
+ "github.com/google/blueprint/proptools"
)
+var buildDir string
+
+func setUp() {
+ var err error
+ buildDir, err = ioutil.TempDir("", "soong_cc_test")
+ if err != nil {
+ panic(err)
+ }
+}
+
+func tearDown() {
+ os.RemoveAll(buildDir)
+}
+
+func TestMain(m *testing.M) {
+ run := func() int {
+ setUp()
+ defer tearDown()
+
+ return m.Run()
+ }
+
+ os.Exit(run())
+}
+
+func testCc(t *testing.T, bp string) *android.TestContext {
+ config := android.TestArchConfig(buildDir, nil)
+ config.ProductVariables.DeviceVndkVersion = proptools.StringPtr("current")
+
+ ctx := android.NewTestArchContext()
+ ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(libraryFactory))
+ ctx.RegisterModuleType("toolchain_library", android.ModuleFactoryAdaptor(toolchainLibraryFactory))
+ ctx.RegisterModuleType("llndk_library", android.ModuleFactoryAdaptor(llndkLibraryFactory))
+ ctx.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
+ ctx.BottomUp("image", vendorMutator).Parallel()
+ ctx.BottomUp("link", linkageMutator).Parallel()
+ ctx.BottomUp("vndk", vndkMutator).Parallel()
+ })
+ ctx.Register()
+
+ ctx.MockFileSystem(map[string][]byte{
+ "Android.bp": []byte(bp),
+ "foo.c": nil,
+ "bar.c": nil,
+ })
+
+ _, errs := ctx.ParseBlueprintsFiles("Android.bp")
+ fail(t, errs)
+ _, errs = ctx.PrepareBuildActions(config)
+ fail(t, errs)
+
+ return ctx
+}
+
+func TestVendorSrc(t *testing.T) {
+ ctx := testCc(t, `
+ cc_library {
+ name: "libTest",
+ srcs: ["foo.c"],
+ no_libgcc : true,
+ nocrt : true,
+ system_shared_libs : [],
+ vendor_available: true,
+ target: {
+ vendor: {
+ srcs: ["bar.c"],
+ },
+ },
+ }
+ toolchain_library {
+ name: "libatomic",
+ vendor_available: true,
+ }
+ toolchain_library {
+ name: "libcompiler_rt-extras",
+ vendor_available: true,
+ }
+ cc_library {
+ name: "libc",
+ no_libgcc : true,
+ nocrt : true,
+ system_shared_libs: [],
+ }
+ llndk_library {
+ name: "libc",
+ symbol_file: "",
+ }
+ cc_library {
+ name: "libm",
+ no_libgcc : true,
+ nocrt : true,
+ system_shared_libs: [],
+ }
+ llndk_library {
+ name: "libm",
+ symbol_file: "",
+ }
+ cc_library {
+ name: "libdl",
+ no_libgcc : true,
+ nocrt : true,
+ system_shared_libs: [],
+ }
+ llndk_library {
+ name: "libdl",
+ symbol_file: "",
+ }
+ `)
+
+ ld := ctx.ModuleForTests("libTest", "android_arm_armv7-a-neon_vendor_shared").Rule("ld")
+ var objs []string
+ for _, o := range ld.Inputs {
+ objs = append(objs, o.Base())
+ }
+ if len(objs) != 2 {
+ t.Errorf("inputs of libTest is expected to 2, but was %d.", len(objs))
+ }
+ if objs[0] != "foo.o" || objs[1] != "bar.o" {
+ t.Errorf("inputs of libTest must be []string{\"foo.o\", \"bar.o\"}, but was %#v.", objs)
+ }
+}
+
var firstUniqueElementsTestCases = []struct {
in []string
out []string
diff --git a/cc/compiler.go b/cc/compiler.go
index a65ddf8..3b3bbbb 100644
--- a/cc/compiler.go
+++ b/cc/compiler.go
@@ -490,14 +490,6 @@
pathDeps := deps.GeneratedHeaders
pathDeps = append(pathDeps, ndkPathDeps(ctx)...)
- if ctx.vndk() {
- compiler.Properties.Srcs = append(compiler.Properties.Srcs,
- compiler.Properties.Target.Vendor.Srcs...)
-
- compiler.Properties.Exclude_srcs = append(compiler.Properties.Exclude_srcs,
- compiler.Properties.Target.Vendor.Exclude_srcs...)
- }
-
srcs := ctx.ExpandSources(compiler.Properties.Srcs, compiler.Properties.Exclude_srcs)
srcs = append(srcs, deps.GeneratedSources...)