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
This commit is contained in:
Jiyong Park 2017-10-12 23:05:00 +09:00
parent 432a2d4033
commit 6a43f04777
4 changed files with 145 additions and 13 deletions

View File

@ -193,8 +193,8 @@ func TestArchConfig(buildDir string, env map[string]string) Config {
config.Targets = map[OsClass][]Target{ config.Targets = map[OsClass][]Target{
Device: []Target{ Device: []Target{
{Android, Arch{ArchType: Arm64, Native: true}}, {Android, Arch{ArchType: Arm64, ArchVariant: "armv8-a", Native: true}},
{Android, Arch{ArchType: Arm, Native: true}}, {Android, Arch{ArchType: Arm, ArchVariant: "armv7-a-neon", Native: true}},
}, },
Host: []Target{ Host: []Target{
{BuildOs, Arch{ArchType: X86_64}}, {BuildOs, Arch{ArchType: X86_64}},

View File

@ -34,9 +34,9 @@ func init() {
android.RegisterModuleType("cc_defaults", defaultsFactory) android.RegisterModuleType("cc_defaults", defaultsFactory)
android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) { android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
ctx.BottomUp("image", vendorMutator).Parallel()
ctx.BottomUp("link", linkageMutator).Parallel() ctx.BottomUp("link", linkageMutator).Parallel()
ctx.BottomUp("vndk", vndkMutator).Parallel() ctx.BottomUp("vndk", vndkMutator).Parallel()
ctx.BottomUp("image", vendorMutator).Parallel()
ctx.BottomUp("ndk_api", ndkApiMutator).Parallel() ctx.BottomUp("ndk_api", ndkApiMutator).Parallel()
ctx.BottomUp("test_per_src", testPerSrcMutator).Parallel() ctx.BottomUp("test_per_src", testPerSrcMutator).Parallel()
ctx.BottomUp("begin", beginMutator).Parallel() ctx.BottomUp("begin", beginMutator).Parallel()
@ -1297,6 +1297,16 @@ const (
vendorMode = "vendor" 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) { func vendorMutator(mctx android.BottomUpMutatorContext) {
if mctx.Os() != android.Android { if mctx.Os() != android.Android {
return return
@ -1352,11 +1362,15 @@ func vendorMutator(mctx android.BottomUpMutatorContext) {
// This will be available in both /system and /vendor // This will be available in both /system and /vendor
// or a /system directory that is available to vendor. // or a /system directory that is available to vendor.
mod := mctx.CreateVariations(coreMode, vendorMode) 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 == "" { } else if mctx.Vendor() && m.Properties.Sdk_version == "" {
// This will be available in /vendor only // This will be available in /vendor only
mod := mctx.CreateVariations(vendorMode) mod := mctx.CreateVariations(vendorMode)
mod[0].(*Module).Properties.UseVndk = true vendor := mod[0].(*Module)
vendor.Properties.UseVndk = true
squashVendorSrcs(vendor)
} else { } else {
// This is either in /system (or similar: /data), or is a // This is either in /system (or similar: /data), or is a
// modules built with the NDK. Modules built with the NDK // modules built with the NDK. Modules built with the NDK

View File

@ -2,10 +2,136 @@ package cc
import ( import (
"android/soong/android" "android/soong/android"
"io/ioutil"
"os"
"reflect" "reflect"
"testing" "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 { var firstUniqueElementsTestCases = []struct {
in []string in []string
out []string out []string

View File

@ -490,14 +490,6 @@ func (compiler *baseCompiler) compile(ctx ModuleContext, flags Flags, deps PathD
pathDeps := deps.GeneratedHeaders pathDeps := deps.GeneratedHeaders
pathDeps = append(pathDeps, ndkPathDeps(ctx)...) 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 := ctx.ExpandSources(compiler.Properties.Srcs, compiler.Properties.Exclude_srcs)
srcs = append(srcs, deps.GeneratedSources...) srcs = append(srcs, deps.GeneratedSources...)