Initial prebuilt support
am: ce75d2c6a2
Change-Id: I9f56b56af7380e9da90c92c2159789428547c9fa
This commit is contained in:
@@ -72,6 +72,7 @@ bootstrap_go_package {
|
|||||||
"android/onceper.go",
|
"android/onceper.go",
|
||||||
"android/package_ctx.go",
|
"android/package_ctx.go",
|
||||||
"android/paths.go",
|
"android/paths.go",
|
||||||
|
"android/prebuilt.go",
|
||||||
"android/register.go",
|
"android/register.go",
|
||||||
"android/util.go",
|
"android/util.go",
|
||||||
"android/variable.go",
|
"android/variable.go",
|
||||||
@@ -81,6 +82,7 @@ bootstrap_go_package {
|
|||||||
],
|
],
|
||||||
testSrcs: [
|
testSrcs: [
|
||||||
"android/paths_test.go",
|
"android/paths_test.go",
|
||||||
|
"android/prebuilt_test.go",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -126,6 +128,7 @@ bootstrap_go_package {
|
|||||||
"cc/check.go",
|
"cc/check.go",
|
||||||
"cc/gen.go",
|
"cc/gen.go",
|
||||||
"cc/makevars.go",
|
"cc/makevars.go",
|
||||||
|
"cc/prebuilt.go",
|
||||||
"cc/relocation_packer.go",
|
"cc/relocation_packer.go",
|
||||||
"cc/sanitize.go",
|
"cc/sanitize.go",
|
||||||
"cc/stl.go",
|
"cc/stl.go",
|
||||||
|
@@ -34,6 +34,7 @@ func init() {
|
|||||||
|
|
||||||
type AndroidMkDataProvider interface {
|
type AndroidMkDataProvider interface {
|
||||||
AndroidMk() (AndroidMkData, error)
|
AndroidMk() (AndroidMkData, error)
|
||||||
|
BaseModuleName() string
|
||||||
}
|
}
|
||||||
|
|
||||||
type AndroidMkData struct {
|
type AndroidMkData struct {
|
||||||
@@ -142,13 +143,12 @@ func translateAndroidMk(ctx blueprint.SingletonContext, mkFile string, mods []Mo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func translateAndroidMkModule(ctx blueprint.SingletonContext, w io.Writer, mod blueprint.Module) error {
|
func translateAndroidMkModule(ctx blueprint.SingletonContext, w io.Writer, mod blueprint.Module) error {
|
||||||
name := ctx.ModuleName(mod)
|
|
||||||
|
|
||||||
provider, ok := mod.(AndroidMkDataProvider)
|
provider, ok := mod.(AndroidMkDataProvider)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name := provider.BaseModuleName()
|
||||||
amod := mod.(Module).base()
|
amod := mod.(Module).base()
|
||||||
data, err := provider.AndroidMk()
|
data, err := provider.AndroidMk()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -156,7 +156,11 @@ func translateAndroidMkModule(ctx blueprint.SingletonContext, w io.Writer, mod b
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !amod.Enabled() {
|
if !amod.Enabled() {
|
||||||
return err
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if amod.commonProperties.SkipInstall {
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if data.SubName != "" {
|
if data.SubName != "" {
|
||||||
|
@@ -151,6 +151,11 @@ func saveToConfigFile(config jsonConfigurable, filename string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestConfig returns a Config object suitable for using for tests
|
||||||
|
func TestConfig() Config {
|
||||||
|
return Config{&config{}}
|
||||||
|
}
|
||||||
|
|
||||||
// New creates a new Config object. The srcDir argument specifies the path to
|
// New creates a new Config object. The srcDir argument specifies the path to
|
||||||
// the root source directory. It also loads the config file, if found.
|
// the root source directory. It also loads the config file, if found.
|
||||||
func NewConfig(srcDir, buildDir string) (Config, error) {
|
func NewConfig(srcDir, buildDir string) (Config, error) {
|
||||||
|
@@ -147,6 +147,8 @@ type commonProperties struct {
|
|||||||
// Set by InitAndroidModule
|
// Set by InitAndroidModule
|
||||||
HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
|
HostOrDeviceSupported HostOrDeviceSupported `blueprint:"mutated"`
|
||||||
ArchSpecific bool `blueprint:"mutated"`
|
ArchSpecific bool `blueprint:"mutated"`
|
||||||
|
|
||||||
|
SkipInstall bool `blueprint:"mutated"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type hostAndDeviceProperties struct {
|
type hostAndDeviceProperties struct {
|
||||||
@@ -277,10 +279,17 @@ type ModuleBase struct {
|
|||||||
hooks hooks
|
hooks hooks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns the name of the module. It may be overridden by individual module types, for
|
||||||
|
// example prebuilts will prepend prebuilt_ to the name.
|
||||||
func (a *ModuleBase) Name() string {
|
func (a *ModuleBase) Name() string {
|
||||||
return a.nameProperties.Name
|
return a.nameProperties.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BaseModuleName returns the name of the module as specified in the blueprints file.
|
||||||
|
func (a *ModuleBase) BaseModuleName() string {
|
||||||
|
return a.nameProperties.Name
|
||||||
|
}
|
||||||
|
|
||||||
func (a *ModuleBase) base() *ModuleBase {
|
func (a *ModuleBase) base() *ModuleBase {
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
@@ -348,6 +357,10 @@ func (a *ModuleBase) Enabled() bool {
|
|||||||
return *a.commonProperties.Enabled
|
return *a.commonProperties.Enabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *ModuleBase) SkipInstall() {
|
||||||
|
a.commonProperties.SkipInstall = true
|
||||||
|
}
|
||||||
|
|
||||||
func (a *ModuleBase) computeInstallDeps(
|
func (a *ModuleBase) computeInstallDeps(
|
||||||
ctx blueprint.ModuleContext) Paths {
|
ctx blueprint.ModuleContext) Paths {
|
||||||
|
|
||||||
@@ -600,7 +613,9 @@ func (a *androidModuleContext) InstallFileName(installPath OutputPath, name stri
|
|||||||
fullInstallPath := installPath.Join(a, name)
|
fullInstallPath := installPath.Join(a, name)
|
||||||
a.module.base().hooks.runInstallHooks(a, fullInstallPath, false)
|
a.module.base().hooks.runInstallHooks(a, fullInstallPath, false)
|
||||||
|
|
||||||
if a.Host() || !a.AConfig().SkipDeviceInstall() {
|
if !a.module.base().commonProperties.SkipInstall &&
|
||||||
|
(a.Host() || !a.AConfig().SkipDeviceInstall()) {
|
||||||
|
|
||||||
deps = append(deps, a.installDeps...)
|
deps = append(deps, a.installDeps...)
|
||||||
|
|
||||||
var implicitDeps, orderOnlyDeps Paths
|
var implicitDeps, orderOnlyDeps Paths
|
||||||
@@ -636,7 +651,9 @@ func (a *androidModuleContext) InstallSymlink(installPath OutputPath, name strin
|
|||||||
fullInstallPath := installPath.Join(a, name)
|
fullInstallPath := installPath.Join(a, name)
|
||||||
a.module.base().hooks.runInstallHooks(a, fullInstallPath, true)
|
a.module.base().hooks.runInstallHooks(a, fullInstallPath, true)
|
||||||
|
|
||||||
if a.Host() || !a.AConfig().SkipDeviceInstall() {
|
if !a.module.base().commonProperties.SkipInstall &&
|
||||||
|
(a.Host() || !a.AConfig().SkipDeviceInstall()) {
|
||||||
|
|
||||||
a.ModuleBuild(pctx, ModuleBuildParams{
|
a.ModuleBuild(pctx, ModuleBuildParams{
|
||||||
Rule: Symlink,
|
Rule: Symlink,
|
||||||
Output: fullInstallPath,
|
Output: fullInstallPath,
|
||||||
|
@@ -33,6 +33,7 @@ func registerMutators() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx.TopDown("load_hooks", loadHookMutator).Parallel()
|
ctx.TopDown("load_hooks", loadHookMutator).Parallel()
|
||||||
|
ctx.BottomUp("prebuilts", prebuiltMutator).Parallel()
|
||||||
ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
|
ctx.BottomUp("defaults_deps", defaultsDepsMutator).Parallel()
|
||||||
ctx.TopDown("defaults", defaultsMutator).Parallel()
|
ctx.TopDown("defaults", defaultsMutator).Parallel()
|
||||||
|
|
||||||
@@ -45,6 +46,9 @@ func registerMutators() {
|
|||||||
|
|
||||||
ctx.BottomUp("deps", depsMutator).Parallel()
|
ctx.BottomUp("deps", depsMutator).Parallel()
|
||||||
|
|
||||||
|
ctx.BottomUp("prebuilt_replace", PrebuiltReplaceMutator).Parallel()
|
||||||
|
ctx.TopDown("prebuilt_disable", PrebuiltDisableMutator).Parallel()
|
||||||
|
|
||||||
register(postDeps)
|
register(postDeps)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
121
android/prebuilt.go
Normal file
121
android/prebuilt.go
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
// Copyright 2016 Google Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package android
|
||||||
|
|
||||||
|
import "github.com/google/blueprint"
|
||||||
|
|
||||||
|
// This file implements common functionality for handling modules that may exist as prebuilts,
|
||||||
|
// source, or both.
|
||||||
|
|
||||||
|
var prebuiltDependencyTag blueprint.BaseDependencyTag
|
||||||
|
|
||||||
|
func SourceModuleHasPrebuilt(ctx ModuleContext) OptionalPath {
|
||||||
|
var path Path
|
||||||
|
ctx.VisitDirectDeps(func(m blueprint.Module) {
|
||||||
|
if ctx.OtherModuleDependencyTag(m) == prebuiltDependencyTag {
|
||||||
|
p := m.(PrebuiltInterface).Prebuilt()
|
||||||
|
if p.usePrebuilt(ctx) {
|
||||||
|
path = p.Path(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return OptionalPathForPath(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Prebuilt struct {
|
||||||
|
Properties struct {
|
||||||
|
Srcs []string `android:"arch_variant"`
|
||||||
|
// When prefer is set to true the prebuilt will be used instead of any source module with
|
||||||
|
// a matching name.
|
||||||
|
Prefer bool `android:"arch_variant"`
|
||||||
|
|
||||||
|
SourceExists bool `blueprint:"mutated"`
|
||||||
|
}
|
||||||
|
module Module
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Prebuilt) Name(name string) string {
|
||||||
|
return "prebuilt_" + name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Prebuilt) Path(ctx ModuleContext) Path {
|
||||||
|
if len(p.Properties.Srcs) == 0 {
|
||||||
|
ctx.PropertyErrorf("srcs", "missing prebuilt source file")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.Properties.Srcs) > 1 {
|
||||||
|
ctx.PropertyErrorf("srcs", "multiple prebuilt source files")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return PathForModuleSrc(ctx, p.Properties.Srcs[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrebuiltInterface interface {
|
||||||
|
Module
|
||||||
|
Prebuilt() *Prebuilt
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrebuiltSourceInterface interface {
|
||||||
|
SkipInstall()
|
||||||
|
}
|
||||||
|
|
||||||
|
// prebuiltMutator ensures that there is always a module with an undecorated name, and marks
|
||||||
|
// prebuilt modules that have both a prebuilt and a source module.
|
||||||
|
func prebuiltMutator(ctx BottomUpMutatorContext) {
|
||||||
|
if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
|
||||||
|
p := m.Prebuilt()
|
||||||
|
name := m.base().BaseModuleName()
|
||||||
|
if ctx.OtherModuleExists(name) {
|
||||||
|
ctx.AddReverseDependency(ctx.Module(), prebuiltDependencyTag, name)
|
||||||
|
p.Properties.SourceExists = true
|
||||||
|
} else {
|
||||||
|
ctx.Rename(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrebuiltReplaceMutator replaces dependencies on the source module with dependencies on the prebuilt
|
||||||
|
// when both modules exist and the prebuilt should be used.
|
||||||
|
func PrebuiltReplaceMutator(ctx BottomUpMutatorContext) {
|
||||||
|
if m, ok := ctx.Module().(PrebuiltInterface); ok && m.Prebuilt() != nil {
|
||||||
|
p := m.Prebuilt()
|
||||||
|
name := m.base().BaseModuleName()
|
||||||
|
if p.Properties.SourceExists && p.usePrebuilt(ctx) {
|
||||||
|
ctx.ReplaceDependencies(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrebuiltDisableMutator disables source modules that have prebuilts that should be used instead.
|
||||||
|
func PrebuiltDisableMutator(ctx TopDownMutatorContext) {
|
||||||
|
if s, ok := ctx.Module().(PrebuiltSourceInterface); ok {
|
||||||
|
ctx.VisitDirectDeps(func(m blueprint.Module) {
|
||||||
|
if ctx.OtherModuleDependencyTag(m) == prebuiltDependencyTag {
|
||||||
|
p := m.(PrebuiltInterface).Prebuilt()
|
||||||
|
if p.usePrebuilt(ctx) {
|
||||||
|
s.SkipInstall()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Prebuilt) usePrebuilt(ctx BaseContext) bool {
|
||||||
|
// TODO: use p.Properties.Name and ctx.ModuleDir to override prefer
|
||||||
|
return p.Properties.Prefer && len(p.Properties.Srcs) > 0
|
||||||
|
}
|
206
android/prebuilt_test.go
Normal file
206
android/prebuilt_test.go
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
// Copyright 2016 Google Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package android
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/blueprint"
|
||||||
|
)
|
||||||
|
|
||||||
|
var prebuiltsTests = []struct {
|
||||||
|
name string
|
||||||
|
modules string
|
||||||
|
prebuilt bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "no prebuilt",
|
||||||
|
modules: `
|
||||||
|
source {
|
||||||
|
name: "bar",
|
||||||
|
}`,
|
||||||
|
prebuilt: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no source prebuilt not preferred",
|
||||||
|
modules: `
|
||||||
|
prebuilt {
|
||||||
|
name: "bar",
|
||||||
|
prefer: false,
|
||||||
|
srcs: ["prebuilt"],
|
||||||
|
}`,
|
||||||
|
prebuilt: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "no source prebuilt preferred",
|
||||||
|
modules: `
|
||||||
|
prebuilt {
|
||||||
|
name: "bar",
|
||||||
|
prefer: true,
|
||||||
|
srcs: ["prebuilt"],
|
||||||
|
}`,
|
||||||
|
prebuilt: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prebuilt not preferred",
|
||||||
|
modules: `
|
||||||
|
source {
|
||||||
|
name: "bar",
|
||||||
|
}
|
||||||
|
|
||||||
|
prebuilt {
|
||||||
|
name: "bar",
|
||||||
|
prefer: false,
|
||||||
|
srcs: ["prebuilt"],
|
||||||
|
}`,
|
||||||
|
prebuilt: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "prebuilt preferred",
|
||||||
|
modules: `
|
||||||
|
source {
|
||||||
|
name: "bar",
|
||||||
|
}
|
||||||
|
|
||||||
|
prebuilt {
|
||||||
|
name: "bar",
|
||||||
|
prefer: true,
|
||||||
|
srcs: ["prebuilt"],
|
||||||
|
}`,
|
||||||
|
prebuilt: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrebuilts(t *testing.T) {
|
||||||
|
for _, test := range prebuiltsTests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
ctx := NewContext()
|
||||||
|
ctx.RegisterModuleType("prebuilt", newPrebuiltModule)
|
||||||
|
ctx.RegisterModuleType("source", newSourceModule)
|
||||||
|
ctx.MockFileSystem(map[string][]byte{
|
||||||
|
"Blueprints": []byte(`
|
||||||
|
source {
|
||||||
|
name: "foo",
|
||||||
|
deps: ["bar"],
|
||||||
|
}
|
||||||
|
` + test.modules),
|
||||||
|
})
|
||||||
|
|
||||||
|
config := TestConfig()
|
||||||
|
|
||||||
|
_, errs := ctx.ParseBlueprintsFiles("Blueprints")
|
||||||
|
fail(t, errs)
|
||||||
|
_, errs = ctx.PrepareBuildActions(config)
|
||||||
|
fail(t, errs)
|
||||||
|
|
||||||
|
foo := findModule(ctx, "foo")
|
||||||
|
if foo == nil {
|
||||||
|
t.Fatalf("failed to find module foo")
|
||||||
|
}
|
||||||
|
|
||||||
|
if test.prebuilt {
|
||||||
|
if !foo.(*sourceModule).dependsOnPrebuiltModule {
|
||||||
|
t.Errorf("doesn't depend on prebuilt module")
|
||||||
|
}
|
||||||
|
|
||||||
|
if foo.(*sourceModule).dependsOnSourceModule {
|
||||||
|
t.Errorf("depends on source module")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if foo.(*sourceModule).dependsOnPrebuiltModule {
|
||||||
|
t.Errorf("depends on prebuilt module")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !foo.(*sourceModule).dependsOnSourceModule {
|
||||||
|
t.Errorf("doens't depend on source module")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type prebuiltModule struct {
|
||||||
|
ModuleBase
|
||||||
|
prebuilt Prebuilt
|
||||||
|
}
|
||||||
|
|
||||||
|
func newPrebuiltModule() (blueprint.Module, []interface{}) {
|
||||||
|
m := &prebuiltModule{}
|
||||||
|
return InitAndroidModule(m, &m.prebuilt.Properties)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *prebuiltModule) Name() string {
|
||||||
|
return p.prebuilt.Name(p.ModuleBase.Name())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *prebuiltModule) DepsMutator(ctx BottomUpMutatorContext) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *prebuiltModule) GenerateAndroidBuildActions(ModuleContext) {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *prebuiltModule) Prebuilt() *Prebuilt {
|
||||||
|
return &p.prebuilt
|
||||||
|
}
|
||||||
|
|
||||||
|
type sourceModule struct {
|
||||||
|
ModuleBase
|
||||||
|
properties struct {
|
||||||
|
Deps []string
|
||||||
|
}
|
||||||
|
dependsOnSourceModule, dependsOnPrebuiltModule bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSourceModule() (blueprint.Module, []interface{}) {
|
||||||
|
m := &sourceModule{}
|
||||||
|
return InitAndroidModule(m, &m.properties)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sourceModule) DepsMutator(ctx BottomUpMutatorContext) {
|
||||||
|
for _, d := range s.properties.Deps {
|
||||||
|
ctx.AddDependency(ctx.Module(), nil, d)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *sourceModule) GenerateAndroidBuildActions(ctx ModuleContext) {
|
||||||
|
ctx.VisitDirectDeps(func(m blueprint.Module) {
|
||||||
|
if _, ok := m.(*sourceModule); ok {
|
||||||
|
s.dependsOnSourceModule = true
|
||||||
|
}
|
||||||
|
if _, ok := m.(*prebuiltModule); ok {
|
||||||
|
s.dependsOnPrebuiltModule = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func findModule(ctx *blueprint.Context, name string) blueprint.Module {
|
||||||
|
var ret blueprint.Module
|
||||||
|
ctx.VisitAllModules(func(m blueprint.Module) {
|
||||||
|
if ctx.ModuleName(m) == name {
|
||||||
|
ret = m
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func fail(t *testing.T, errs []error) {
|
||||||
|
if len(errs) > 0 {
|
||||||
|
for _, err := range errs {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
}
|
@@ -81,7 +81,7 @@ func (binary *binaryDecorator) linkerProps() []interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (binary *binaryDecorator) getStem(ctx BaseModuleContext) string {
|
func (binary *binaryDecorator) getStem(ctx BaseModuleContext) string {
|
||||||
stem := ctx.ModuleName()
|
stem := ctx.baseModuleName()
|
||||||
if binary.Properties.Stem != "" {
|
if binary.Properties.Stem != "" {
|
||||||
stem = binary.Properties.Stem
|
stem = binary.Properties.Stem
|
||||||
}
|
}
|
||||||
@@ -171,7 +171,7 @@ func (binary *binaryDecorator) linkerInit(ctx BaseModuleContext) {
|
|||||||
}
|
}
|
||||||
if ctx.TargetPrimary() {
|
if ctx.TargetPrimary() {
|
||||||
binary.baseInstaller.Properties.Symlinks = append(binary.baseInstaller.Properties.Symlinks,
|
binary.baseInstaller.Properties.Symlinks = append(binary.baseInstaller.Properties.Symlinks,
|
||||||
ctx.ModuleName())
|
ctx.baseModuleName())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
42
cc/cc.go
42
cc/cc.go
@@ -19,7 +19,6 @@ package cc
|
|||||||
// is handled in builder.go
|
// is handled in builder.go
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -146,6 +145,7 @@ type ModuleContextIntf interface {
|
|||||||
sdk() bool
|
sdk() bool
|
||||||
sdkVersion() string
|
sdkVersion() string
|
||||||
selectedStl() string
|
selectedStl() string
|
||||||
|
baseModuleName() string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ModuleContext interface {
|
type ModuleContext interface {
|
||||||
@@ -354,6 +354,10 @@ func (ctx *moduleContextImpl) selectedStl() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ctx *moduleContextImpl) baseModuleName() string {
|
||||||
|
return ctx.mod.ModuleBase.BaseModuleName()
|
||||||
|
}
|
||||||
|
|
||||||
func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
|
func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
|
||||||
return &Module{
|
return &Module{
|
||||||
hod: hod,
|
hod: hod,
|
||||||
@@ -368,6 +372,21 @@ func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Mo
|
|||||||
return module
|
return module
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Module) Prebuilt() *android.Prebuilt {
|
||||||
|
if p, ok := c.linker.(prebuiltLinkerInterface); ok {
|
||||||
|
return p.prebuilt()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Module) Name() string {
|
||||||
|
name := c.ModuleBase.Name()
|
||||||
|
if p, ok := c.linker.(prebuiltLinkerInterface); ok {
|
||||||
|
name = p.Name(name)
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
||||||
ctx := &moduleContext{
|
ctx := &moduleContext{
|
||||||
ModuleContext: actx,
|
ModuleContext: actx,
|
||||||
@@ -434,12 +453,12 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.outputFile = android.OptionalPathForPath(outputFile)
|
c.outputFile = android.OptionalPathForPath(outputFile)
|
||||||
|
}
|
||||||
|
|
||||||
if c.installer != nil && !c.Properties.PreventInstall {
|
if c.installer != nil && !c.Properties.PreventInstall && c.outputFile.Valid() {
|
||||||
c.installer.install(ctx, outputFile)
|
c.installer.install(ctx, c.outputFile.Path())
|
||||||
if ctx.Failed() {
|
if ctx.Failed() {
|
||||||
return
|
return
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -792,11 +811,6 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !cc.outputFile.Valid() {
|
|
||||||
ctx.ModuleErrorf("module %q missing output file", name)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if tag == reuseObjTag {
|
if tag == reuseObjTag {
|
||||||
depPaths.ObjFiles = append(depPaths.ObjFiles,
|
depPaths.ObjFiles = append(depPaths.ObjFiles,
|
||||||
cc.compiler.(libraryInterface).reuseObjs()...)
|
cc.compiler.(libraryInterface).reuseObjs()...)
|
||||||
@@ -861,11 +875,13 @@ func (c *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|||||||
depPaths.CrtBegin = linkFile
|
depPaths.CrtBegin = linkFile
|
||||||
case crtEndDepTag:
|
case crtEndDepTag:
|
||||||
depPaths.CrtEnd = linkFile
|
depPaths.CrtEnd = linkFile
|
||||||
default:
|
|
||||||
panic(fmt.Errorf("unknown dependency tag: %s", tag))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ptr != nil {
|
if ptr != nil {
|
||||||
|
if !linkFile.Valid() {
|
||||||
|
ctx.ModuleErrorf("module %q missing output file", name)
|
||||||
|
return
|
||||||
|
}
|
||||||
*ptr = append(*ptr, linkFile.Path())
|
*ptr = append(*ptr, linkFile.Path())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -284,7 +284,7 @@ type libraryInterface interface {
|
|||||||
func (library *libraryDecorator) getLibName(ctx ModuleContext) string {
|
func (library *libraryDecorator) getLibName(ctx ModuleContext) string {
|
||||||
name := library.libName
|
name := library.libName
|
||||||
if name == "" {
|
if name == "" {
|
||||||
name = ctx.ModuleName()
|
name = ctx.baseModuleName()
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.Host() && Bool(library.Properties.Unique_host_soname) {
|
if ctx.Host() && Bool(library.Properties.Unique_host_soname) {
|
||||||
|
72
cc/prebuilt.go
Normal file
72
cc/prebuilt.go
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
// Copyright 2016 Google Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package cc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"android/soong/android"
|
||||||
|
|
||||||
|
"github.com/google/blueprint"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
android.RegisterModuleType("cc_prebuilt_shared_library", prebuiltSharedLibraryFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
type prebuiltLinkerInterface interface {
|
||||||
|
Name(string) string
|
||||||
|
prebuilt() *android.Prebuilt
|
||||||
|
}
|
||||||
|
|
||||||
|
type prebuiltLibraryLinker struct {
|
||||||
|
*libraryDecorator
|
||||||
|
android.Prebuilt
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ prebuiltLinkerInterface = (*prebuiltLibraryLinker)(nil)
|
||||||
|
|
||||||
|
func (p *prebuiltLibraryLinker) prebuilt() *android.Prebuilt {
|
||||||
|
return &p.Prebuilt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *prebuiltLibraryLinker) linkerProps() []interface{} {
|
||||||
|
props := p.libraryDecorator.linkerProps()
|
||||||
|
return append(props, &p.Prebuilt.Properties)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *prebuiltLibraryLinker) link(ctx ModuleContext,
|
||||||
|
flags Flags, deps PathDeps, objFiles android.Paths) android.Path {
|
||||||
|
// TODO(ccross): verify shared library dependencies
|
||||||
|
if len(p.Prebuilt.Properties.Srcs) > 0 {
|
||||||
|
p.libraryDecorator.exportIncludes(ctx, "-I")
|
||||||
|
p.libraryDecorator.reexportFlags(deps.ReexportedFlags)
|
||||||
|
p.libraryDecorator.reexportDeps(deps.ReexportedFlagsDeps)
|
||||||
|
// TODO(ccross): .toc optimization, stripping, packing
|
||||||
|
return p.Prebuilt.Path(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func prebuiltSharedLibraryFactory() (blueprint.Module, []interface{}) {
|
||||||
|
module, library := NewLibrary(android.HostAndDeviceSupported, true, false)
|
||||||
|
module.compiler = nil
|
||||||
|
|
||||||
|
prebuilt := &prebuiltLibraryLinker{
|
||||||
|
libraryDecorator: library,
|
||||||
|
}
|
||||||
|
module.linker = prebuilt
|
||||||
|
|
||||||
|
return module.Init()
|
||||||
|
}
|
Reference in New Issue
Block a user