2015-01-31 02:27:36 +01:00
|
|
|
// Copyright 2015 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.
|
|
|
|
|
2016-05-19 00:37:25 +02:00
|
|
|
package android
|
2015-01-31 02:27:36 +01:00
|
|
|
|
|
|
|
import (
|
2021-05-21 14:37:59 +02:00
|
|
|
"android/soong/bazel"
|
2019-02-12 00:11:14 +01:00
|
|
|
"encoding"
|
2015-01-31 02:27:36 +01:00
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
"runtime"
|
|
|
|
"strings"
|
2015-03-24 19:13:38 +01:00
|
|
|
|
2019-10-16 20:03:10 +02:00
|
|
|
"github.com/google/blueprint"
|
2020-08-25 03:04:09 +02:00
|
|
|
"github.com/google/blueprint/bootstrap"
|
2015-03-24 19:13:38 +01:00
|
|
|
"github.com/google/blueprint/proptools"
|
2015-01-31 02:27:36 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
/*
|
|
|
|
Example blueprints file containing all variant property groups, with comment listing what type
|
|
|
|
of variants get properties in that group:
|
|
|
|
|
|
|
|
module {
|
|
|
|
arch: {
|
|
|
|
arm: {
|
|
|
|
// Host or device variants with arm architecture
|
|
|
|
},
|
|
|
|
arm64: {
|
|
|
|
// Host or device variants with arm64 architecture
|
|
|
|
},
|
|
|
|
x86: {
|
|
|
|
// Host or device variants with x86 architecture
|
|
|
|
},
|
|
|
|
x86_64: {
|
|
|
|
// Host or device variants with x86_64 architecture
|
|
|
|
},
|
|
|
|
},
|
|
|
|
multilib: {
|
|
|
|
lib32: {
|
|
|
|
// Host or device variants for 32-bit architectures
|
|
|
|
},
|
|
|
|
lib64: {
|
|
|
|
// Host or device variants for 64-bit architectures
|
|
|
|
},
|
|
|
|
},
|
|
|
|
target: {
|
|
|
|
android: {
|
2020-09-23 22:03:27 +02:00
|
|
|
// Device variants (implies Bionic)
|
2015-01-31 02:27:36 +01:00
|
|
|
},
|
|
|
|
host: {
|
|
|
|
// Host variants
|
|
|
|
},
|
2020-09-23 22:03:27 +02:00
|
|
|
bionic: {
|
|
|
|
// Bionic (device and host) variants
|
|
|
|
},
|
|
|
|
linux_bionic: {
|
|
|
|
// Bionic host variants
|
|
|
|
},
|
|
|
|
linux: {
|
|
|
|
// Bionic (device and host) and Linux glibc variants
|
|
|
|
},
|
2017-10-03 04:42:01 +02:00
|
|
|
linux_glibc: {
|
2020-09-23 22:03:27 +02:00
|
|
|
// Linux host variants (using non-Bionic libc)
|
2015-01-31 02:27:36 +01:00
|
|
|
},
|
|
|
|
darwin: {
|
|
|
|
// Darwin host variants
|
|
|
|
},
|
|
|
|
windows: {
|
|
|
|
// Windows host variants
|
|
|
|
},
|
|
|
|
not_windows: {
|
|
|
|
// Non-windows host variants
|
|
|
|
},
|
2020-09-23 22:03:27 +02:00
|
|
|
android_arm: {
|
|
|
|
// Any <os>_<arch> combination restricts to that os and arch
|
|
|
|
},
|
2015-01-31 02:27:36 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
*/
|
2015-05-11 22:39:40 +02:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// An Arch indicates a single CPU architecture.
|
|
|
|
type Arch struct {
|
|
|
|
// The type of the architecture (arm, arm64, x86, or x86_64).
|
|
|
|
ArchType ArchType
|
2015-11-21 00:35:00 +01:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// The variant of the architecture, for example "armv7-a" or "armv7-a-neon" for arm.
|
|
|
|
ArchVariant string
|
2019-01-16 23:33:13 +01:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// The variant of the CPU, for example "cortex-a53" for arm64.
|
|
|
|
CpuVariant string
|
2019-01-12 04:02:16 +01:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// The list of Android app ABIs supported by the CPU architecture, for example "arm64-v8a".
|
|
|
|
Abi []string
|
2019-01-12 04:02:16 +01:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// The list of arch-specific features supported by the CPU architecture, for example "neon".
|
2015-11-21 00:35:00 +01:00
|
|
|
ArchFeatures []string
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// String returns the Arch as a string. The value is used as the name of the variant created
|
|
|
|
// by archMutator.
|
2015-01-31 02:27:36 +01:00
|
|
|
func (a Arch) String() string {
|
2015-05-07 23:11:29 +02:00
|
|
|
s := a.ArchType.String()
|
2015-01-31 02:27:36 +01:00
|
|
|
if a.ArchVariant != "" {
|
|
|
|
s += "_" + a.ArchVariant
|
|
|
|
}
|
|
|
|
if a.CpuVariant != "" {
|
|
|
|
s += "_" + a.CpuVariant
|
|
|
|
}
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// ArchType is used to define the 4 supported architecture types (arm, arm64, x86, x86_64), as
|
|
|
|
// well as the "common" architecture used for modules that support multiple architectures, for
|
|
|
|
// example Java modules.
|
2015-01-31 02:27:36 +01:00
|
|
|
type ArchType struct {
|
2020-11-17 00:08:19 +01:00
|
|
|
// Name is the name of the architecture type, "arm", "arm64", "x86", or "x86_64".
|
|
|
|
Name string
|
|
|
|
|
|
|
|
// Field is the name of the field used in properties that refer to the architecture, e.g. "Arm64".
|
|
|
|
Field string
|
|
|
|
|
|
|
|
// Multilib is either "lib32" or "lib64" for 32-bit or 64-bit architectures.
|
2015-07-07 02:49:43 +02:00
|
|
|
Multilib string
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// String returns the name of the ArchType.
|
|
|
|
func (a ArchType) String() string {
|
|
|
|
return a.Name
|
|
|
|
}
|
|
|
|
|
|
|
|
const COMMON_VARIANT = "common"
|
|
|
|
|
|
|
|
var (
|
|
|
|
archTypeList []ArchType
|
|
|
|
|
|
|
|
Arm = newArch("arm", "lib32")
|
|
|
|
Arm64 = newArch("arm64", "lib64")
|
|
|
|
X86 = newArch("x86", "lib32")
|
|
|
|
X86_64 = newArch("x86_64", "lib64")
|
|
|
|
|
|
|
|
Common = ArchType{
|
|
|
|
Name: COMMON_VARIANT,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
var archTypeMap = map[string]ArchType{}
|
|
|
|
|
2015-07-07 02:49:43 +02:00
|
|
|
func newArch(name, multilib string) ArchType {
|
2016-06-24 08:44:54 +02:00
|
|
|
archType := ArchType{
|
2015-07-07 02:49:43 +02:00
|
|
|
Name: name,
|
2016-06-24 08:44:54 +02:00
|
|
|
Field: proptools.FieldNameForProperty(name),
|
2015-07-07 02:49:43 +02:00
|
|
|
Multilib: multilib,
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
2016-06-24 08:44:54 +02:00
|
|
|
archTypeList = append(archTypeList, archType)
|
2020-11-17 00:08:19 +01:00
|
|
|
archTypeMap[name] = archType
|
2016-06-24 08:44:54 +02:00
|
|
|
return archType
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
|
2021-04-05 09:33:05 +02:00
|
|
|
// ArchTypeList returns the a slice copy of the 4 supported ArchTypes for arm,
|
|
|
|
// arm64, x86 and x86_64.
|
2019-08-13 23:11:33 +02:00
|
|
|
func ArchTypeList() []ArchType {
|
|
|
|
return append([]ArchType(nil), archTypeList...)
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// MarshalText allows an ArchType to be serialized through any encoder that supports
|
|
|
|
// encoding.TextMarshaler.
|
2019-02-12 00:11:14 +01:00
|
|
|
func (a ArchType) MarshalText() ([]byte, error) {
|
2021-04-15 01:55:38 +02:00
|
|
|
return []byte(a.String()), nil
|
2019-02-12 00:11:14 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
var _ encoding.TextMarshaler = ArchType{}
|
2019-02-12 00:11:14 +01:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// UnmarshalText allows an ArchType to be deserialized through any decoder that supports
|
|
|
|
// encoding.TextUnmarshaler.
|
2019-02-12 00:11:14 +01:00
|
|
|
func (a *ArchType) UnmarshalText(text []byte) error {
|
|
|
|
if u, ok := archTypeMap[string(text)]; ok {
|
|
|
|
*a = u
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return fmt.Errorf("unknown ArchType %q", text)
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
var _ encoding.TextUnmarshaler = &ArchType{}
|
2016-06-03 03:50:47 +02:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// OsClass is an enum that describes whether a variant of a module runs on the host, on the device,
|
|
|
|
// or is generic.
|
2016-06-02 02:09:44 +02:00
|
|
|
type OsClass int
|
2015-05-07 23:11:29 +02:00
|
|
|
|
2016-06-02 02:09:44 +02:00
|
|
|
const (
|
2020-11-17 00:08:19 +01:00
|
|
|
// Generic is used for variants of modules that are not OS-specific.
|
2016-11-29 02:50:06 +01:00
|
|
|
Generic OsClass = iota
|
2020-11-17 00:08:19 +01:00
|
|
|
// Device is used for variants of modules that run on the device.
|
2016-11-29 02:50:06 +01:00
|
|
|
Device
|
2020-11-17 00:08:19 +01:00
|
|
|
// Host is used for variants of modules that run on the host.
|
2016-06-02 02:09:44 +02:00
|
|
|
Host
|
2016-06-02 02:09:44 +02:00
|
|
|
)
|
2015-05-07 23:11:29 +02:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// String returns the OsClass as a string.
|
2017-05-09 22:45:28 +02:00
|
|
|
func (class OsClass) String() string {
|
|
|
|
switch class {
|
|
|
|
case Generic:
|
|
|
|
return "generic"
|
|
|
|
case Device:
|
|
|
|
return "device"
|
|
|
|
case Host:
|
|
|
|
return "host"
|
|
|
|
default:
|
|
|
|
panic(fmt.Errorf("unknown class %d", class))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// OsType describes an OS variant of a module.
|
|
|
|
type OsType struct {
|
|
|
|
// Name is the name of the OS. It is also used as the name of the property in Android.bp
|
|
|
|
// files.
|
|
|
|
Name string
|
|
|
|
|
|
|
|
// Field is the name of the OS converted to an exported field name, i.e. with the first
|
|
|
|
// character capitalized.
|
|
|
|
Field string
|
|
|
|
|
|
|
|
// Class is the OsClass of the OS.
|
|
|
|
Class OsClass
|
|
|
|
|
|
|
|
// DefaultDisabled is set when the module variants for the OS should not be created unless
|
|
|
|
// the module explicitly requests them. This is used to limit Windows cross compilation to
|
|
|
|
// only modules that need it.
|
|
|
|
DefaultDisabled bool
|
|
|
|
}
|
|
|
|
|
|
|
|
// String returns the name of the OsType.
|
2016-06-02 02:09:44 +02:00
|
|
|
func (os OsType) String() string {
|
|
|
|
return os.Name
|
2016-06-02 02:09:44 +02:00
|
|
|
}
|
2015-05-07 23:11:29 +02:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Bionic returns true if the OS uses the Bionic libc runtime, i.e. if the OS is Android or
|
|
|
|
// is Linux with Bionic.
|
2017-09-22 21:28:24 +02:00
|
|
|
func (os OsType) Bionic() bool {
|
|
|
|
return os == Android || os == LinuxBionic
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Linux returns true if the OS uses the Linux kernel, i.e. if the OS is Android or is Linux
|
|
|
|
// with or without the Bionic libc runtime.
|
2017-09-22 21:28:24 +02:00
|
|
|
func (os OsType) Linux() bool {
|
|
|
|
return os == Android || os == Linux || os == LinuxBionic
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// newOsType constructs an OsType and adds it to the global lists.
|
|
|
|
func newOsType(name string, class OsClass, defDisabled bool, archTypes ...ArchType) OsType {
|
|
|
|
checkCalledFromInit()
|
2016-06-02 02:09:44 +02:00
|
|
|
os := OsType{
|
|
|
|
Name: name,
|
2020-11-17 00:08:19 +01:00
|
|
|
Field: proptools.FieldNameForProperty(name),
|
2016-06-02 02:09:44 +02:00
|
|
|
Class: class,
|
2016-11-13 19:16:05 +01:00
|
|
|
|
|
|
|
DefaultDisabled: defDisabled,
|
2015-05-07 23:11:29 +02:00
|
|
|
}
|
2021-04-05 09:33:05 +02:00
|
|
|
osTypeList = append(osTypeList, os)
|
2017-02-27 19:12:13 +01:00
|
|
|
|
|
|
|
if _, found := commonTargetMap[name]; found {
|
|
|
|
panic(fmt.Errorf("Found Os type duplicate during OsType registration: %q", name))
|
|
|
|
} else {
|
2020-11-11 03:12:15 +01:00
|
|
|
commonTargetMap[name] = Target{Os: os, Arch: CommonArch}
|
2017-02-27 19:12:13 +01:00
|
|
|
}
|
2020-11-17 00:08:19 +01:00
|
|
|
osArchTypeMap[os] = archTypes
|
2017-02-27 19:12:13 +01:00
|
|
|
|
2016-06-02 02:09:44 +02:00
|
|
|
return os
|
2015-05-07 23:11:29 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// osByName returns the OsType that has the given name, or NoOsType if none match.
|
2016-06-02 02:09:44 +02:00
|
|
|
func osByName(name string) OsType {
|
2021-04-05 09:33:05 +02:00
|
|
|
for _, os := range osTypeList {
|
2016-06-02 02:09:44 +02:00
|
|
|
if os.Name == name {
|
|
|
|
return os
|
|
|
|
}
|
2015-11-25 02:53:15 +01:00
|
|
|
}
|
2016-06-02 02:09:44 +02:00
|
|
|
|
|
|
|
return NoOsType
|
2016-06-02 02:09:44 +02:00
|
|
|
}
|
2015-11-25 02:53:15 +01:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// BuildOs returns the OsType for the OS that the build is running on.
|
|
|
|
var BuildOs = func() OsType {
|
|
|
|
switch runtime.GOOS {
|
|
|
|
case "linux":
|
|
|
|
return Linux
|
|
|
|
case "darwin":
|
|
|
|
return Darwin
|
|
|
|
default:
|
|
|
|
panic(fmt.Sprintf("unsupported OS: %s", runtime.GOOS))
|
|
|
|
}
|
|
|
|
}()
|
2019-03-26 12:39:31 +01:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// BuildArch returns the ArchType for the CPU that the build is running on.
|
|
|
|
var BuildArch = func() ArchType {
|
|
|
|
switch runtime.GOARCH {
|
|
|
|
case "amd64":
|
|
|
|
return X86_64
|
|
|
|
default:
|
|
|
|
panic(fmt.Sprintf("unsupported Arch: %s", runtime.GOARCH))
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
var (
|
2021-04-05 09:33:05 +02:00
|
|
|
// osTypeList contains a list of all the supported OsTypes, including ones not supported
|
2020-11-17 00:08:19 +01:00
|
|
|
// by the current build host or the target device.
|
2021-04-05 09:33:05 +02:00
|
|
|
osTypeList []OsType
|
2020-11-17 00:08:19 +01:00
|
|
|
// commonTargetMap maps names of OsTypes to the corresponding common Target, i.e. the
|
|
|
|
// Target with the same OsType and the common ArchType.
|
|
|
|
commonTargetMap = make(map[string]Target)
|
|
|
|
// osArchTypeMap maps OsTypes to the list of supported ArchTypes for that OS.
|
|
|
|
osArchTypeMap = map[OsType][]ArchType{}
|
|
|
|
|
|
|
|
// NoOsType is a placeholder for when no OS is needed.
|
|
|
|
NoOsType OsType
|
|
|
|
// Linux is the OS for the Linux kernel plus the glibc runtime.
|
|
|
|
Linux = newOsType("linux_glibc", Host, false, X86, X86_64)
|
|
|
|
// Darwin is the OS for MacOS/Darwin host machines.
|
|
|
|
Darwin = newOsType("darwin", Host, false, X86_64)
|
|
|
|
// LinuxBionic is the OS for the Linux kernel plus the Bionic libc runtime, but without the
|
|
|
|
// rest of Android.
|
|
|
|
LinuxBionic = newOsType("linux_bionic", Host, false, Arm64, X86_64)
|
|
|
|
// Windows the OS for Windows host machines.
|
|
|
|
Windows = newOsType("windows", Host, true, X86, X86_64)
|
|
|
|
// Android is the OS for target devices that run all of Android, including the Linux kernel
|
|
|
|
// and the Bionic libc runtime.
|
|
|
|
Android = newOsType("android", Device, false, Arm, Arm64, X86, X86_64)
|
|
|
|
// Fuchsia is the OS for target devices that run Fuchsia.
|
|
|
|
Fuchsia = newOsType("fuchsia", Device, false, Arm64, X86_64)
|
|
|
|
|
|
|
|
// CommonOS is a pseudo OSType for a common OS variant, which is OsType agnostic and which
|
|
|
|
// has dependencies on all the OS variants.
|
|
|
|
CommonOS = newOsType("common_os", Generic, false)
|
2020-11-11 03:12:15 +01:00
|
|
|
|
|
|
|
// CommonArch is the Arch for all modules that are os-specific but not arch specific,
|
|
|
|
// for example most Java modules.
|
|
|
|
CommonArch = Arch{ArchType: Common}
|
2019-03-26 12:39:31 +01:00
|
|
|
)
|
|
|
|
|
2021-04-05 09:33:05 +02:00
|
|
|
// OsTypeList returns a slice copy of the supported OsTypes.
|
|
|
|
func OsTypeList() []OsType {
|
|
|
|
return append([]OsType(nil), osTypeList...)
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Target specifies the OS and architecture that a module is being compiled for.
|
2016-06-02 02:09:44 +02:00
|
|
|
type Target struct {
|
2020-11-17 00:08:19 +01:00
|
|
|
// Os the OS that the module is being compiled for (e.g. "linux_glibc", "android").
|
|
|
|
Os OsType
|
|
|
|
// Arch is the architecture that the module is being compiled for.
|
|
|
|
Arch Arch
|
|
|
|
// NativeBridge is NativeBridgeEnabled if the architecture is supported using NativeBridge
|
|
|
|
// (i.e. arm on x86) for this device.
|
|
|
|
NativeBridge NativeBridgeSupport
|
|
|
|
// NativeBridgeHostArchName is the name of the real architecture that is used to implement
|
|
|
|
// the NativeBridge architecture. For example, for arm on x86 this would be "x86".
|
2019-07-11 10:23:53 +02:00
|
|
|
NativeBridgeHostArchName string
|
2020-11-17 00:08:19 +01:00
|
|
|
// NativeBridgeRelativePath is the name of the subdirectory that will contain NativeBridge
|
|
|
|
// libraries and binaries.
|
2019-07-11 10:23:53 +02:00
|
|
|
NativeBridgeRelativePath string
|
2020-09-14 12:43:17 +02:00
|
|
|
|
|
|
|
// HostCross is true when the target cannot run natively on the current build host.
|
|
|
|
// For example, linux_glibc_x86 returns true on a regular x86/i686/Linux machines, but returns false
|
|
|
|
// on Mac (different OS), or on 64-bit only i686/Linux machines (unsupported arch).
|
|
|
|
HostCross bool
|
2016-06-02 02:09:44 +02:00
|
|
|
}
|
2016-06-03 03:50:47 +02:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// NativeBridgeSupport is an enum that specifies if a Target supports NativeBridge.
|
|
|
|
type NativeBridgeSupport bool
|
|
|
|
|
|
|
|
const (
|
|
|
|
NativeBridgeDisabled NativeBridgeSupport = false
|
|
|
|
NativeBridgeEnabled NativeBridgeSupport = true
|
|
|
|
)
|
|
|
|
|
|
|
|
// String returns the OS and arch variations used for the Target.
|
2016-06-02 02:09:44 +02:00
|
|
|
func (target Target) String() string {
|
2019-10-16 20:07:20 +02:00
|
|
|
return target.OsVariation() + "_" + target.ArchVariation()
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// OsVariation returns the name of the variation used by the osMutator for the Target.
|
2019-10-16 20:07:20 +02:00
|
|
|
func (target Target) OsVariation() string {
|
|
|
|
return target.Os.String()
|
2019-10-16 20:03:10 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// ArchVariation returns the name of the variation used by the archMutator for the Target.
|
2019-10-16 20:03:10 +02:00
|
|
|
func (target Target) ArchVariation() string {
|
|
|
|
var variation string
|
2019-03-26 12:39:31 +01:00
|
|
|
if target.NativeBridge {
|
2019-10-16 20:03:10 +02:00
|
|
|
variation = "native_bridge_"
|
|
|
|
}
|
|
|
|
variation += target.Arch.String()
|
|
|
|
|
2019-10-16 20:07:20 +02:00
|
|
|
return variation
|
2019-10-16 20:03:10 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Variations returns a list of blueprint.Variations for the osMutator and archMutator for the
|
|
|
|
// Target.
|
2019-10-16 20:03:10 +02:00
|
|
|
func (target Target) Variations() []blueprint.Variation {
|
|
|
|
return []blueprint.Variation{
|
2019-10-16 20:07:20 +02:00
|
|
|
{Mutator: "os", Variation: target.OsVariation()},
|
2019-10-16 20:03:10 +02:00
|
|
|
{Mutator: "arch", Variation: target.ArchVariation()},
|
2019-03-26 12:39:31 +01:00
|
|
|
}
|
2015-11-25 02:53:15 +01:00
|
|
|
}
|
|
|
|
|
2021-04-22 00:15:34 +02:00
|
|
|
func registerBp2buildArchPathDepsMutator(ctx RegisterMutatorsContext) {
|
|
|
|
ctx.BottomUp("bp2build-arch-pathdeps", bp2buildArchPathDepsMutator).Parallel()
|
|
|
|
}
|
|
|
|
|
|
|
|
// add dependencies for architecture specific properties tagged with `android:"path"`
|
|
|
|
func bp2buildArchPathDepsMutator(ctx BottomUpMutatorContext) {
|
|
|
|
var module Module
|
|
|
|
module = ctx.Module()
|
|
|
|
|
|
|
|
m := module.base()
|
|
|
|
if !m.ArchSpecific() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// addPathDepsForProps does not descend into sub structs, so we need to descend into the
|
|
|
|
// arch-specific properties ourselves
|
|
|
|
properties := []interface{}{}
|
|
|
|
for _, archProperties := range m.archProperties {
|
|
|
|
for _, archProps := range archProperties {
|
|
|
|
archPropValues := reflect.ValueOf(archProps).Elem()
|
|
|
|
// there are three "arch" variations, descend into each
|
|
|
|
for _, variant := range []string{"Arch", "Multilib", "Target"} {
|
|
|
|
// The properties are an interface, get the value (a pointer) that it points to
|
|
|
|
archProps := archPropValues.FieldByName(variant).Elem()
|
|
|
|
if archProps.IsNil() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
// And then a pointer to a struct
|
|
|
|
archProps = archProps.Elem()
|
|
|
|
for i := 0; i < archProps.NumField(); i += 1 {
|
|
|
|
f := archProps.Field(i)
|
|
|
|
// If the value of the field is a struct (as opposed to a pointer to a struct) then step
|
|
|
|
// into the BlueprintEmbed field.
|
|
|
|
if f.Kind() == reflect.Struct {
|
|
|
|
f = f.FieldByName("BlueprintEmbed")
|
|
|
|
}
|
|
|
|
if f.IsZero() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
props := f.Interface().(interface{})
|
|
|
|
properties = append(properties, props)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
addPathDepsForProps(ctx, properties)
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// osMutator splits an arch-specific module into a variant for each OS that is enabled for the
|
|
|
|
// module. It uses the HostOrDevice value passed to InitAndroidArchModule and the
|
|
|
|
// device_supported and host_supported properties to determine which OsTypes are enabled for this
|
|
|
|
// module, then searches through the Targets to determine which have enabled Targets for this
|
|
|
|
// module.
|
2020-08-25 03:04:09 +02:00
|
|
|
func osMutator(bpctx blueprint.BottomUpMutatorContext) {
|
2019-10-16 20:07:20 +02:00
|
|
|
var module Module
|
|
|
|
var ok bool
|
2020-08-25 03:04:09 +02:00
|
|
|
if module, ok = bpctx.Module().(Module); !ok {
|
2020-11-17 00:08:19 +01:00
|
|
|
// The module is not a Soong module, it is a Blueprint module.
|
2020-08-25 03:04:09 +02:00
|
|
|
if bootstrap.IsBootstrapModule(bpctx.Module()) {
|
|
|
|
// Bootstrap Go modules are always the build OS or linux bionic.
|
|
|
|
config := bpctx.Config().(Config)
|
|
|
|
osNames := []string{config.BuildOSTarget.OsVariation()}
|
|
|
|
for _, hostCrossTarget := range config.Targets[LinuxBionic] {
|
|
|
|
if hostCrossTarget.Arch.ArchType == config.BuildOSTarget.Arch.ArchType {
|
|
|
|
osNames = append(osNames, hostCrossTarget.OsVariation())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
osNames = FirstUniqueStrings(osNames)
|
|
|
|
bpctx.CreateVariations(osNames...)
|
|
|
|
}
|
2019-10-16 20:07:20 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-25 03:04:09 +02:00
|
|
|
// Bootstrap Go module support above requires this mutator to be a
|
|
|
|
// blueprint.BottomUpMutatorContext because android.BottomUpMutatorContext
|
|
|
|
// filters out non-Soong modules. Now that we've handled them, create a
|
|
|
|
// normal android.BottomUpMutatorContext.
|
2021-01-26 15:18:53 +01:00
|
|
|
mctx := bottomUpMutatorContextFactory(bpctx, module, false, false)
|
2020-08-25 03:04:09 +02:00
|
|
|
|
2019-10-16 20:07:20 +02:00
|
|
|
base := module.base()
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Nothing to do for modules that are not architecture specific (e.g. a genrule).
|
2019-10-16 20:07:20 +02:00
|
|
|
if !base.ArchSpecific() {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Collect a list of OSTypes supported by this module based on the HostOrDevice value
|
|
|
|
// passed to InitAndroidArchModule and the device_supported and host_supported properties.
|
2019-10-16 20:07:20 +02:00
|
|
|
var moduleOSList []OsType
|
2021-04-05 09:33:05 +02:00
|
|
|
for _, os := range osTypeList {
|
2020-09-14 12:43:17 +02:00
|
|
|
for _, t := range mctx.Config().Targets[os] {
|
2020-11-19 03:33:19 +01:00
|
|
|
if base.supportsTarget(t) {
|
2020-09-14 12:43:17 +02:00
|
|
|
moduleOSList = append(moduleOSList, os)
|
|
|
|
break
|
2019-10-16 20:07:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// If there are no supported OSes then disable the module.
|
2019-10-16 20:07:20 +02:00
|
|
|
if len(moduleOSList) == 0 {
|
2020-01-22 03:11:29 +01:00
|
|
|
base.Disable()
|
2019-10-16 20:07:20 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Convert the list of supported OsTypes to the variation names.
|
2019-10-16 20:07:20 +02:00
|
|
|
osNames := make([]string, len(moduleOSList))
|
|
|
|
for i, os := range moduleOSList {
|
|
|
|
osNames[i] = os.String()
|
|
|
|
}
|
|
|
|
|
2020-02-25 20:26:33 +01:00
|
|
|
createCommonOSVariant := base.commonProperties.CreateCommonOSVariant
|
|
|
|
if createCommonOSVariant {
|
2020-11-17 00:08:19 +01:00
|
|
|
// A CommonOS variant was requested so add it to the list of OS variants to
|
2020-02-25 20:26:33 +01:00
|
|
|
// create. It needs to be added to the end because it needs to depend on the
|
|
|
|
// the other variants in the list returned by CreateVariations(...) and inter
|
|
|
|
// variant dependencies can only be created from a later variant in that list to
|
|
|
|
// an earlier one. That is because variants are always processed in the order in
|
|
|
|
// which they are returned from CreateVariations(...).
|
|
|
|
osNames = append(osNames, CommonOS.Name)
|
|
|
|
moduleOSList = append(moduleOSList, CommonOS)
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Create the variations, annotate each one with which OS it was created for, and
|
|
|
|
// squash the appropriate OS-specific properties into the top level properties.
|
2019-10-16 20:07:20 +02:00
|
|
|
modules := mctx.CreateVariations(osNames...)
|
|
|
|
for i, m := range modules {
|
2020-02-25 20:26:33 +01:00
|
|
|
m.base().commonProperties.CompileOS = moduleOSList[i]
|
|
|
|
m.base().setOSProperties(mctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
if createCommonOSVariant {
|
|
|
|
// A CommonOS variant was requested so add dependencies from it (the last one in
|
|
|
|
// the list) to the OS type specific variants.
|
|
|
|
last := len(modules) - 1
|
|
|
|
commonOSVariant := modules[last]
|
|
|
|
commonOSVariant.base().commonProperties.CommonOSVariant = true
|
|
|
|
for _, module := range modules[0:last] {
|
|
|
|
// Ignore modules that are enabled. Note, this will only avoid adding
|
|
|
|
// dependencies on OsType variants that are explicitly disabled in their
|
|
|
|
// properties. The CommonOS variant will still depend on disabled variants
|
|
|
|
// if they are disabled afterwards, e.g. in archMutator if
|
|
|
|
if module.Enabled() {
|
|
|
|
mctx.AddInterVariantDependency(commonOsToOsSpecificVariantTag, commonOSVariant, module)
|
|
|
|
}
|
|
|
|
}
|
2019-10-16 20:07:20 +02:00
|
|
|
}
|
2020-02-25 20:26:33 +01:00
|
|
|
}
|
|
|
|
|
2020-10-09 19:54:15 +02:00
|
|
|
type archDepTag struct {
|
|
|
|
blueprint.BaseDependencyTag
|
|
|
|
name string
|
|
|
|
}
|
|
|
|
|
2020-02-25 20:26:33 +01:00
|
|
|
// Identifies the dependency from CommonOS variant to the os specific variants.
|
2020-10-09 19:54:15 +02:00
|
|
|
var commonOsToOsSpecificVariantTag = archDepTag{name: "common os to os specific"}
|
2020-02-25 20:26:33 +01:00
|
|
|
|
|
|
|
// Get the OsType specific variants for the current CommonOS variant.
|
|
|
|
//
|
|
|
|
// The returned list will only contain enabled OsType specific variants of the
|
|
|
|
// module referenced in the supplied context. An empty list is returned if there
|
|
|
|
// are no enabled variants or the supplied context is not for an CommonOS
|
|
|
|
// variant.
|
|
|
|
func GetOsSpecificVariantsOfCommonOSVariant(mctx BaseModuleContext) []Module {
|
|
|
|
var variants []Module
|
|
|
|
mctx.VisitDirectDeps(func(m Module) {
|
|
|
|
if mctx.OtherModuleDependencyTag(m) == commonOsToOsSpecificVariantTag {
|
|
|
|
if m.Enabled() {
|
|
|
|
variants = append(variants, m)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return variants
|
2019-10-16 20:07:20 +02:00
|
|
|
}
|
|
|
|
|
2018-10-03 07:01:37 +02:00
|
|
|
// archMutator splits a module into a variant for each Target requested by the module. Target selection
|
2020-11-17 00:08:19 +01:00
|
|
|
// for a module is in three levels, OsClass, multilib, and then Target.
|
2018-10-03 07:01:37 +02:00
|
|
|
// OsClass selection is determined by:
|
|
|
|
// - The HostOrDeviceSupported value passed in to InitAndroidArchModule by the module type factory, which selects
|
|
|
|
// whether the module type can compile for host, device or both.
|
|
|
|
// - The host_supported and device_supported properties on the module.
|
2019-06-05 15:42:57 +02:00
|
|
|
// If host is supported for the module, the Host and HostCross OsClasses are selected. If device is supported
|
2018-10-03 07:01:37 +02:00
|
|
|
// for the module, the Device OsClass is selected.
|
|
|
|
// Within each selected OsClass, the multilib selection is determined by:
|
2019-06-07 00:19:57 +02:00
|
|
|
// - The compile_multilib property if it set (which may be overridden by target.android.compile_multilib or
|
2018-10-03 07:01:37 +02:00
|
|
|
// target.host.compile_multilib).
|
|
|
|
// - The default multilib passed to InitAndroidArchModule if compile_multilib was not set.
|
|
|
|
// Valid multilib values include:
|
|
|
|
// "both": compile for all Targets supported by the OsClass (generally x86_64 and x86, or arm64 and arm).
|
|
|
|
// "first": compile for only a single preferred Target supported by the OsClass. This is generally x86_64 or arm64,
|
2020-04-18 00:49:49 +02:00
|
|
|
// but may be arm for a 32-bit only build.
|
2018-10-03 07:01:37 +02:00
|
|
|
// "32": compile for only a single 32-bit Target supported by the OsClass.
|
|
|
|
// "64": compile for only a single 64-bit Target supported by the OsClass.
|
2020-11-17 00:08:19 +01:00
|
|
|
// "common": compile a for a single Target that will work on all Targets supported by the OsClass (for example Java).
|
|
|
|
// "common_first": compile a for a Target that will work on all Targets supported by the OsClass
|
|
|
|
// (same as "common"), plus a second Target for the preferred Target supported by the OsClass
|
|
|
|
// (same as "first"). This is used for java_binary that produces a common .jar and a wrapper
|
|
|
|
// executable script.
|
2018-10-03 07:01:37 +02:00
|
|
|
//
|
|
|
|
// Once the list of Targets is determined, the module is split into a variant for each Target.
|
|
|
|
//
|
|
|
|
// Modules can be initialized with InitAndroidMultiTargetsArchModule, in which case they will be split by OsClass,
|
|
|
|
// but will have a common Target that is expected to handle all other selected Targets via ctx.MultiTargets().
|
2020-08-25 03:04:09 +02:00
|
|
|
func archMutator(bpctx blueprint.BottomUpMutatorContext) {
|
2016-05-19 00:37:25 +02:00
|
|
|
var module Module
|
2015-01-31 02:27:36 +01:00
|
|
|
var ok bool
|
2020-08-25 03:04:09 +02:00
|
|
|
if module, ok = bpctx.Module().(Module); !ok {
|
|
|
|
if bootstrap.IsBootstrapModule(bpctx.Module()) {
|
|
|
|
// Bootstrap Go modules are always the build architecture.
|
|
|
|
bpctx.CreateVariations(bpctx.Config().(Config).BuildOSTarget.ArchVariation())
|
|
|
|
}
|
2015-01-31 02:27:36 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-08-25 03:04:09 +02:00
|
|
|
// Bootstrap Go module support above requires this mutator to be a
|
|
|
|
// blueprint.BottomUpMutatorContext because android.BottomUpMutatorContext
|
|
|
|
// filters out non-Soong modules. Now that we've handled them, create a
|
|
|
|
// normal android.BottomUpMutatorContext.
|
2021-01-26 15:18:53 +01:00
|
|
|
mctx := bottomUpMutatorContextFactory(bpctx, module, false, false)
|
2020-08-25 03:04:09 +02:00
|
|
|
|
2018-10-02 23:02:10 +02:00
|
|
|
base := module.base()
|
|
|
|
|
|
|
|
if !base.ArchSpecific() {
|
2016-06-02 02:09:44 +02:00
|
|
|
return
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
|
2019-10-16 20:07:20 +02:00
|
|
|
os := base.commonProperties.CompileOS
|
2020-02-25 20:26:33 +01:00
|
|
|
if os == CommonOS {
|
|
|
|
// Make sure that the target related properties are initialized for the
|
|
|
|
// CommonOS variant.
|
|
|
|
addTargetProperties(module, commonTargetMap[os.Name], nil, true)
|
|
|
|
|
|
|
|
// Do not create arch specific variants for the CommonOS variant.
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2019-10-16 20:07:20 +02:00
|
|
|
osTargets := mctx.Config().Targets[os]
|
2019-11-21 02:12:35 +01:00
|
|
|
image := base.commonProperties.ImageVariation
|
2020-11-17 00:08:19 +01:00
|
|
|
// Filter NativeBridge targets unless they are explicitly supported.
|
|
|
|
// Skip creating native bridge variants for non-core modules.
|
2019-12-18 19:45:46 +01:00
|
|
|
if os == Android &&
|
|
|
|
!(Bool(base.commonProperties.Native_bridge_supported) && image == CoreVariation) {
|
|
|
|
|
2019-10-16 20:07:20 +02:00
|
|
|
var targets []Target
|
|
|
|
for _, t := range osTargets {
|
|
|
|
if !t.NativeBridge {
|
|
|
|
targets = append(targets, t)
|
2018-10-11 02:02:29 +02:00
|
|
|
}
|
|
|
|
}
|
2016-06-02 02:09:44 +02:00
|
|
|
|
2019-10-16 20:07:20 +02:00
|
|
|
osTargets = targets
|
|
|
|
}
|
2019-03-26 12:39:31 +01:00
|
|
|
|
2020-10-22 00:17:56 +02:00
|
|
|
// only the primary arch in the ramdisk / vendor_ramdisk / recovery partition
|
2021-04-08 14:13:22 +02:00
|
|
|
if os == Android && (module.InstallInRecovery() || module.InstallInRamdisk() || module.InstallInVendorRamdisk() || module.InstallInDebugRamdisk()) {
|
2019-10-16 20:07:20 +02:00
|
|
|
osTargets = []Target{osTargets[0]}
|
|
|
|
}
|
2019-03-26 12:39:31 +01:00
|
|
|
|
2021-02-25 02:39:54 +01:00
|
|
|
// Windows builds always prefer 32-bit
|
|
|
|
prefer32 := os == Windows
|
2018-10-02 23:02:10 +02:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Determine the multilib selection for this module.
|
2019-10-16 20:07:20 +02:00
|
|
|
multilib, extraMultilib := decodeMultilib(base, os.Class)
|
2020-11-17 00:08:19 +01:00
|
|
|
|
|
|
|
// Convert the multilib selection into a list of Targets.
|
2019-10-16 20:07:20 +02:00
|
|
|
targets, err := decodeMultilibTargets(multilib, osTargets, prefer32)
|
|
|
|
if err != nil {
|
|
|
|
mctx.ModuleErrorf("%s", err.Error())
|
|
|
|
}
|
2018-10-02 22:59:46 +02:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// If the module is using extraMultilib, decode the extraMultilib selection into
|
|
|
|
// a separate list of Targets.
|
2019-10-16 20:07:20 +02:00
|
|
|
var multiTargets []Target
|
|
|
|
if extraMultilib != "" {
|
|
|
|
multiTargets, err = decodeMultilibTargets(extraMultilib, osTargets, prefer32)
|
2016-06-03 03:50:47 +02:00
|
|
|
if err != nil {
|
|
|
|
mctx.ModuleErrorf("%s", err.Error())
|
|
|
|
}
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Recovery is always the primary architecture, filter out any other architectures.
|
2021-02-02 12:07:58 +01:00
|
|
|
// Common arch is also allowed
|
2019-11-21 02:12:35 +01:00
|
|
|
if image == RecoveryVariation {
|
|
|
|
primaryArch := mctx.Config().DevicePrimaryArchType()
|
2021-02-02 12:07:58 +01:00
|
|
|
targets = filterToArch(targets, primaryArch, Common)
|
|
|
|
multiTargets = filterToArch(multiTargets, primaryArch, Common)
|
2019-11-21 02:12:35 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// If there are no supported targets disable the module.
|
2019-10-16 20:07:20 +02:00
|
|
|
if len(targets) == 0 {
|
2020-01-22 03:11:29 +01:00
|
|
|
base.Disable()
|
2016-07-11 23:36:48 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Convert the targets into a list of arch variation names.
|
2019-10-16 20:07:20 +02:00
|
|
|
targetNames := make([]string, len(targets))
|
|
|
|
for i, target := range targets {
|
|
|
|
targetNames[i] = target.ArchVariation()
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Create the variations, annotate each one with which Target it was created for, and
|
|
|
|
// squash the appropriate arch-specific properties into the top level properties.
|
2016-06-02 02:09:44 +02:00
|
|
|
modules := mctx.CreateVariations(targetNames...)
|
2015-01-31 02:27:36 +01:00
|
|
|
for i, m := range modules {
|
2020-02-25 20:26:33 +01:00
|
|
|
addTargetProperties(m, targets[i], multiTargets, i == 0)
|
2020-08-25 03:04:09 +02:00
|
|
|
m.base().setArchProperties(mctx)
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// addTargetProperties annotates a variant with the Target is is being compiled for, the list
|
|
|
|
// of additional Targets it is supporting (if any), and whether it is the primary Target for
|
|
|
|
// the module.
|
2020-02-25 20:26:33 +01:00
|
|
|
func addTargetProperties(m Module, target Target, multiTargets []Target, primaryTarget bool) {
|
|
|
|
m.base().commonProperties.CompileTarget = target
|
|
|
|
m.base().commonProperties.CompileMultiTargets = multiTargets
|
|
|
|
m.base().commonProperties.CompilePrimary = primaryTarget
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// decodeMultilib returns the appropriate compile_multilib property for the module, or the default
|
|
|
|
// multilib from the factory's call to InitAndroidArchModule if none was set. For modules that
|
|
|
|
// called InitAndroidMultiTargetsArchModule it always returns "common" for multilib, and returns
|
|
|
|
// the actual multilib in extraMultilib.
|
2018-10-03 07:01:37 +02:00
|
|
|
func decodeMultilib(base *ModuleBase, class OsClass) (multilib, extraMultilib string) {
|
2020-11-17 00:08:19 +01:00
|
|
|
// First check the "android.compile_multilib" or "host.compile_multilib" properties.
|
2018-10-03 07:01:37 +02:00
|
|
|
switch class {
|
|
|
|
case Device:
|
|
|
|
multilib = String(base.commonProperties.Target.Android.Compile_multilib)
|
2020-09-14 12:43:17 +02:00
|
|
|
case Host:
|
2018-10-03 07:01:37 +02:00
|
|
|
multilib = String(base.commonProperties.Target.Host.Compile_multilib)
|
|
|
|
}
|
2020-11-17 00:08:19 +01:00
|
|
|
|
|
|
|
// If those aren't set, try the "compile_multilib" property.
|
2018-10-03 07:01:37 +02:00
|
|
|
if multilib == "" {
|
|
|
|
multilib = String(base.commonProperties.Compile_multilib)
|
|
|
|
}
|
2020-11-17 00:08:19 +01:00
|
|
|
|
|
|
|
// If that wasn't set, use the default multilib set by the factory.
|
2018-10-03 07:01:37 +02:00
|
|
|
if multilib == "" {
|
|
|
|
multilib = base.commonProperties.Default_multilib
|
|
|
|
}
|
|
|
|
|
|
|
|
if base.commonProperties.UseTargetVariants {
|
|
|
|
return multilib, ""
|
|
|
|
} else {
|
|
|
|
// For app modules a single arch variant will be created per OS class which is expected to handle all the
|
|
|
|
// selected arches. Return the common-type as multilib and any Android.bp provided multilib as extraMultilib
|
|
|
|
if multilib == base.commonProperties.Default_multilib {
|
|
|
|
multilib = "first"
|
|
|
|
}
|
|
|
|
return base.commonProperties.Default_multilib, multilib
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// filterToArch takes a list of Targets and an ArchType, and returns a modified list that contains
|
2021-02-02 12:07:58 +01:00
|
|
|
// only Targets that have the specified ArchTypes.
|
|
|
|
func filterToArch(targets []Target, archs ...ArchType) []Target {
|
2019-11-21 02:12:35 +01:00
|
|
|
for i := 0; i < len(targets); i++ {
|
2021-02-02 12:07:58 +01:00
|
|
|
found := false
|
|
|
|
for _, arch := range archs {
|
|
|
|
if targets[i].Arch.ArchType == arch {
|
|
|
|
found = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
2019-11-21 02:12:35 +01:00
|
|
|
targets = append(targets[:i], targets[i+1:]...)
|
|
|
|
i--
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return targets
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// archPropRoot is a struct type used as the top level of the arch-specific properties. It
|
|
|
|
// contains the "arch", "multilib", and "target" property structs. It is used to split up the
|
|
|
|
// property structs to limit how much is allocated when a single arch-specific property group is
|
|
|
|
// used. The types are interface{} because they will hold instances of runtime-created types.
|
2020-01-17 23:08:22 +01:00
|
|
|
type archPropRoot struct {
|
|
|
|
Arch, Multilib, Target interface{}
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// archPropTypeDesc holds the runtime-created types for the property structs to instantiate to
|
|
|
|
// create an archPropRoot property struct.
|
|
|
|
type archPropTypeDesc struct {
|
|
|
|
arch, multilib, target reflect.Type
|
|
|
|
}
|
|
|
|
|
2020-01-17 23:08:22 +01:00
|
|
|
// createArchPropTypeDesc takes a reflect.Type that is either a struct or a pointer to a struct, and
|
|
|
|
// returns lists of reflect.Types that contains the arch-variant properties inside structs for each
|
|
|
|
// arch, multilib and target property.
|
2020-11-17 00:08:19 +01:00
|
|
|
//
|
|
|
|
// This is a relatively expensive operation, so the results are cached in the global
|
|
|
|
// archPropTypeMap. It is constructed entirely based on compile-time data, so there is no need
|
|
|
|
// to isolate the results between multiple tests running in parallel.
|
2020-01-17 23:08:22 +01:00
|
|
|
func createArchPropTypeDesc(props reflect.Type) []archPropTypeDesc {
|
2020-01-21 20:43:29 +01:00
|
|
|
// Each property struct shard will be nested many times under the runtime generated arch struct,
|
|
|
|
// which can hit the limit of 64kB for the name of runtime generated structs. They are nested
|
|
|
|
// 97 times now, which may grow in the future, plus there is some overhead for the containing
|
|
|
|
// type. This number may need to be reduced if too many are added, but reducing it too far
|
|
|
|
// could cause problems if a single deeply nested property no longer fits in the name.
|
|
|
|
const maxArchTypeNameSize = 500
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Convert the type to a new set of types that contains only the arch-specific properties
|
|
|
|
// (those that are tagged with `android:"arch_specific"`), and sharded into multiple types
|
|
|
|
// to keep the runtime-generated names under the limit.
|
2020-01-21 20:43:29 +01:00
|
|
|
propShards, _ := proptools.FilterPropertyStructSharded(props, maxArchTypeNameSize, filterArchStruct)
|
2020-11-17 00:08:19 +01:00
|
|
|
|
|
|
|
// If the type has no arch-specific properties there is nothing to do.
|
2019-01-24 23:58:11 +01:00
|
|
|
if len(propShards) == 0 {
|
2018-10-24 21:42:09 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-01-17 23:08:22 +01:00
|
|
|
var ret []archPropTypeDesc
|
2018-10-24 21:42:09 +02:00
|
|
|
for _, props := range propShards {
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// variantFields takes a list of variant property field names and returns a list the
|
|
|
|
// StructFields with the names and the type of the current shard.
|
2018-10-24 21:42:09 +02:00
|
|
|
variantFields := func(names []string) []reflect.StructField {
|
|
|
|
ret := make([]reflect.StructField, len(names))
|
|
|
|
|
|
|
|
for i, name := range names {
|
|
|
|
ret[i].Name = name
|
|
|
|
ret[i].Type = props
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret
|
2016-06-24 08:44:54 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Create a type that contains the properties in this shard repeated for each
|
|
|
|
// architecture, architecture variant, and architecture feature.
|
2018-10-24 21:42:09 +02:00
|
|
|
archFields := make([]reflect.StructField, len(archTypeList))
|
|
|
|
for i, arch := range archTypeList {
|
2020-11-17 00:08:19 +01:00
|
|
|
var variants []string
|
2018-10-24 21:42:09 +02:00
|
|
|
|
|
|
|
for _, archVariant := range archVariants[arch] {
|
|
|
|
archVariant := variantReplacer.Replace(archVariant)
|
|
|
|
variants = append(variants, proptools.FieldNameForProperty(archVariant))
|
|
|
|
}
|
|
|
|
for _, feature := range archFeatures[arch] {
|
|
|
|
feature := variantReplacer.Replace(feature)
|
|
|
|
variants = append(variants, proptools.FieldNameForProperty(feature))
|
|
|
|
}
|
2016-06-24 08:44:54 +02:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Create the StructFields for each architecture variant architecture feature
|
|
|
|
// (e.g. "arch.arm.cortex-a53" or "arch.arm.neon").
|
2018-10-24 21:42:09 +02:00
|
|
|
fields := variantFields(variants)
|
2016-06-24 08:44:54 +02:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Create the StructField for the architecture itself (e.g. "arch.arm"). The special
|
|
|
|
// "BlueprintEmbed" name is used by Blueprint to put the properties in the
|
|
|
|
// parent struct.
|
2018-10-24 21:42:09 +02:00
|
|
|
fields = append([]reflect.StructField{{
|
|
|
|
Name: "BlueprintEmbed",
|
|
|
|
Type: props,
|
|
|
|
Anonymous: true,
|
|
|
|
}}, fields...)
|
|
|
|
|
|
|
|
archFields[i] = reflect.StructField{
|
|
|
|
Name: arch.Field,
|
|
|
|
Type: reflect.StructOf(fields),
|
|
|
|
}
|
2016-06-24 08:44:54 +02:00
|
|
|
}
|
2020-11-17 00:08:19 +01:00
|
|
|
|
|
|
|
// Create the type of the "arch" property struct for this shard.
|
2018-10-24 21:42:09 +02:00
|
|
|
archType := reflect.StructOf(archFields)
|
2016-06-24 08:44:54 +02:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Create the type for the "multilib" property struct for this shard, containing the
|
|
|
|
// "multilib.lib32" and "multilib.lib64" property structs.
|
2018-10-24 21:42:09 +02:00
|
|
|
multilibType := reflect.StructOf(variantFields([]string{"Lib32", "Lib64"}))
|
2016-06-24 08:44:54 +02:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Start with a list of the special targets
|
2018-10-24 21:42:09 +02:00
|
|
|
targets := []string{
|
|
|
|
"Host",
|
|
|
|
"Android64",
|
|
|
|
"Android32",
|
|
|
|
"Bionic",
|
|
|
|
"Linux",
|
|
|
|
"Not_windows",
|
|
|
|
"Arm_on_x86",
|
|
|
|
"Arm_on_x86_64",
|
2020-05-07 22:16:33 +02:00
|
|
|
"Native_bridge",
|
2018-10-24 21:42:09 +02:00
|
|
|
}
|
2021-04-05 09:33:05 +02:00
|
|
|
for _, os := range osTypeList {
|
2020-11-17 00:08:19 +01:00
|
|
|
// Add all the OSes.
|
2018-10-24 21:42:09 +02:00
|
|
|
targets = append(targets, os.Field)
|
2016-06-24 08:44:54 +02:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Add the OS/Arch combinations, e.g. "android_arm64".
|
2018-10-24 21:42:09 +02:00
|
|
|
for _, archType := range osArchTypeMap[os] {
|
2021-05-21 14:37:59 +02:00
|
|
|
targets = append(targets, GetCompoundTargetField(os, archType))
|
2017-09-22 21:28:24 +02:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Also add the special "linux_<arch>" and "bionic_<arch>" property structs.
|
2018-10-24 21:42:09 +02:00
|
|
|
if os.Linux() {
|
|
|
|
target := "Linux_" + archType.Name
|
|
|
|
if !InList(target, targets) {
|
|
|
|
targets = append(targets, target)
|
|
|
|
}
|
2017-09-22 21:28:24 +02:00
|
|
|
}
|
2018-10-24 21:42:09 +02:00
|
|
|
if os.Bionic() {
|
|
|
|
target := "Bionic_" + archType.Name
|
|
|
|
if !InList(target, targets) {
|
|
|
|
targets = append(targets, target)
|
|
|
|
}
|
2017-09-22 21:28:24 +02:00
|
|
|
}
|
|
|
|
}
|
2016-06-24 08:44:54 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Create the type for the "target" property struct for this shard.
|
2018-10-24 21:42:09 +02:00
|
|
|
targetType := reflect.StructOf(variantFields(targets))
|
2020-01-17 23:08:22 +01:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Return a descriptor of the 3 runtime-created types.
|
2020-01-17 23:08:22 +01:00
|
|
|
ret = append(ret, archPropTypeDesc{
|
|
|
|
arch: reflect.PtrTo(archType),
|
|
|
|
multilib: reflect.PtrTo(multilibType),
|
|
|
|
target: reflect.PtrTo(targetType),
|
|
|
|
})
|
2018-10-24 21:42:09 +02:00
|
|
|
}
|
|
|
|
return ret
|
2016-06-24 08:44:54 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// variantReplacer converts architecture variant or architecture feature names into names that
|
|
|
|
// are valid for an Android.bp file.
|
|
|
|
var variantReplacer = strings.NewReplacer("-", "_", ".", "_")
|
|
|
|
|
|
|
|
// filterArchStruct returns true if the given field is an architecture specific property.
|
2019-09-25 20:26:40 +02:00
|
|
|
func filterArchStruct(field reflect.StructField, prefix string) (bool, reflect.StructField) {
|
|
|
|
if proptools.HasTag(field, "android", "arch_variant") {
|
|
|
|
// The arch_variant field isn't necessary past this point
|
|
|
|
// Instead of wasting space, just remove it. Go also has a
|
|
|
|
// 16-bit limit on structure name length. The name is constructed
|
|
|
|
// based on the Go source representation of the structure, so
|
|
|
|
// the tag names count towards that length.
|
2020-01-21 20:38:47 +01:00
|
|
|
|
|
|
|
androidTag := field.Tag.Get("android")
|
|
|
|
values := strings.Split(androidTag, ",")
|
|
|
|
|
|
|
|
if string(field.Tag) != `android:"`+strings.Join(values, ",")+`"` {
|
|
|
|
panic(fmt.Errorf("unexpected tag format %q", field.Tag))
|
2019-09-25 20:26:40 +02:00
|
|
|
}
|
2021-04-22 00:15:34 +02:00
|
|
|
// don't delete path tag as it is needed for bp2build
|
2020-01-21 20:38:47 +01:00
|
|
|
// these tags don't need to be present in the runtime generated struct type.
|
2021-04-22 00:15:34 +02:00
|
|
|
values = RemoveListFromList(values, []string{"arch_variant", "variant_prepend"})
|
|
|
|
if len(values) > 0 && values[0] != "path" {
|
2020-01-21 20:38:47 +01:00
|
|
|
panic(fmt.Errorf("unknown tags %q in field %q", values, prefix+field.Name))
|
2021-04-22 00:15:34 +02:00
|
|
|
} else if len(values) == 1 {
|
|
|
|
field.Tag = reflect.StructTag(`android:"` + strings.Join(values, ",") + `"`)
|
|
|
|
} else {
|
|
|
|
field.Tag = ``
|
2020-01-21 20:38:47 +01:00
|
|
|
}
|
|
|
|
|
2019-09-25 20:26:40 +02:00
|
|
|
return true, field
|
|
|
|
}
|
|
|
|
return false, field
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// archPropTypeMap contains a cache of the results of createArchPropTypeDesc for each type. It is
|
|
|
|
// shared across all Contexts, but is constructed based only on compile-time information so there
|
|
|
|
// is no risk of contaminating one Context with data from another.
|
2016-06-24 08:44:54 +02:00
|
|
|
var archPropTypeMap OncePer
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// initArchModule adds the architecture-specific property structs to a Module.
|
|
|
|
func initArchModule(m Module) {
|
2015-01-31 02:27:36 +01:00
|
|
|
|
|
|
|
base := m.base()
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Store the original list of top level property structs
|
2017-06-24 00:06:31 +02:00
|
|
|
base.generalProperties = m.GetProperties()
|
2015-01-31 02:27:36 +01:00
|
|
|
|
|
|
|
for _, properties := range base.generalProperties {
|
|
|
|
propertiesValue := reflect.ValueOf(properties)
|
2016-08-09 00:49:17 +02:00
|
|
|
t := propertiesValue.Type()
|
2015-01-31 02:27:36 +01:00
|
|
|
if propertiesValue.Kind() != reflect.Ptr {
|
2016-01-04 23:34:37 +01:00
|
|
|
panic(fmt.Errorf("properties must be a pointer to a struct, got %T",
|
|
|
|
propertiesValue.Interface()))
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
propertiesValue = propertiesValue.Elem()
|
|
|
|
if propertiesValue.Kind() != reflect.Struct {
|
2016-01-04 23:34:37 +01:00
|
|
|
panic(fmt.Errorf("properties must be a pointer to a struct, got %T",
|
|
|
|
propertiesValue.Interface()))
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Get or create the arch-specific property struct types for this property struct type.
|
2019-02-04 20:22:08 +01:00
|
|
|
archPropTypes := archPropTypeMap.Once(NewCustomOnceKey(t), func() interface{} {
|
2020-01-17 23:08:22 +01:00
|
|
|
return createArchPropTypeDesc(t)
|
|
|
|
}).([]archPropTypeDesc)
|
2015-01-31 02:27:36 +01:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Instantiate one of each arch-specific property struct type and add it to the
|
|
|
|
// properties for the Module.
|
2018-10-24 21:42:09 +02:00
|
|
|
var archProperties []interface{}
|
|
|
|
for _, t := range archPropTypes {
|
2020-01-17 23:08:22 +01:00
|
|
|
archProperties = append(archProperties, &archPropRoot{
|
|
|
|
Arch: reflect.Zero(t.arch).Interface(),
|
|
|
|
Multilib: reflect.Zero(t.multilib).Interface(),
|
|
|
|
Target: reflect.Zero(t.target).Interface(),
|
|
|
|
})
|
2016-06-24 08:44:54 +02:00
|
|
|
}
|
2018-10-24 21:42:09 +02:00
|
|
|
base.archProperties = append(base.archProperties, archProperties)
|
|
|
|
m.AddProperties(archProperties...)
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Update the list of properties that can be set by a defaults module or a call to
|
|
|
|
// AppendMatchingProperties or PrependMatchingProperties.
|
2017-06-24 00:06:31 +02:00
|
|
|
base.customizableProperties = m.GetProperties()
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
|
2021-05-05 09:00:01 +02:00
|
|
|
func maybeBlueprintEmbed(src reflect.Value) reflect.Value {
|
2020-11-17 00:08:19 +01:00
|
|
|
// If the value of the field is a struct (as opposed to a pointer to a struct) then step
|
|
|
|
// into the BlueprintEmbed field.
|
2016-06-24 08:44:54 +02:00
|
|
|
if src.Kind() == reflect.Struct {
|
2021-05-05 09:00:01 +02:00
|
|
|
return src.FieldByName("BlueprintEmbed")
|
|
|
|
} else {
|
|
|
|
return src
|
2015-10-29 01:23:31 +01:00
|
|
|
}
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Merges the property struct in srcValue into dst.
|
2021-05-14 21:14:40 +02:00
|
|
|
func mergePropertyStruct(ctx ArchVariantContext, dst interface{}, srcValue reflect.Value) {
|
2021-05-05 09:00:01 +02:00
|
|
|
src := maybeBlueprintEmbed(srcValue).Interface()
|
2015-10-29 01:23:31 +01:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// order checks the `android:"variant_prepend"` tag to handle properties where the
|
|
|
|
// arch-specific value needs to come before the generic value, for example for lists of
|
|
|
|
// include directories.
|
2016-05-06 00:57:15 +02:00
|
|
|
order := func(property string,
|
|
|
|
dstField, srcField reflect.StructField,
|
|
|
|
dstValue, srcValue interface{}) (proptools.Order, error) {
|
|
|
|
if proptools.HasTag(dstField, "android", "variant_prepend") {
|
|
|
|
return proptools.Prepend, nil
|
|
|
|
} else {
|
|
|
|
return proptools.Append, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Squash the located property struct into the destination property struct.
|
2021-05-05 09:00:01 +02:00
|
|
|
err := proptools.ExtendMatchingProperties([]interface{}{dst}, src, nil, order)
|
2015-10-29 01:23:31 +01:00
|
|
|
if err != nil {
|
|
|
|
if propertyErr, ok := err.(*proptools.ExtendPropertyError); ok {
|
|
|
|
ctx.PropertyErrorf(propertyErr.Property, "%s", propertyErr.Err.Error())
|
|
|
|
} else {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
}
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
2015-11-23 22:29:51 +01:00
|
|
|
|
2021-05-05 09:00:01 +02:00
|
|
|
// Returns the immediate child of the input property struct that corresponds to
|
|
|
|
// the sub-property "field".
|
2021-05-14 21:14:40 +02:00
|
|
|
func getChildPropertyStruct(ctx ArchVariantContext,
|
2021-05-17 11:44:58 +02:00
|
|
|
src reflect.Value, field, userFriendlyField string) (reflect.Value, bool) {
|
2021-05-05 09:00:01 +02:00
|
|
|
|
|
|
|
// Step into non-nil pointers to structs in the src value.
|
|
|
|
if src.Kind() == reflect.Ptr {
|
|
|
|
if src.IsNil() {
|
2021-05-17 11:44:58 +02:00
|
|
|
return reflect.Value{}, false
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
|
|
|
src = src.Elem()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find the requested field in the src struct.
|
2021-05-17 11:44:58 +02:00
|
|
|
child := src.FieldByName(proptools.FieldNameForProperty(field))
|
|
|
|
if !child.IsValid() {
|
2021-05-05 09:00:01 +02:00
|
|
|
ctx.ModuleErrorf("field %q does not exist", userFriendlyField)
|
2021-05-17 11:44:58 +02:00
|
|
|
return reflect.Value{}, false
|
|
|
|
}
|
|
|
|
|
|
|
|
if child.IsZero() {
|
|
|
|
return reflect.Value{}, false
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
|
|
|
|
2021-05-17 11:44:58 +02:00
|
|
|
return child, true
|
2015-10-29 01:23:31 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Squash the appropriate OS-specific property structs into the matching top level property structs
|
|
|
|
// based on the CompileOS value that was annotated on the variant.
|
2019-10-16 20:07:20 +02:00
|
|
|
func (m *ModuleBase) setOSProperties(ctx BottomUpMutatorContext) {
|
|
|
|
os := m.commonProperties.CompileOS
|
|
|
|
|
|
|
|
for i := range m.generalProperties {
|
|
|
|
genProps := m.generalProperties[i]
|
|
|
|
if m.archProperties[i] == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
for _, archProperties := range m.archProperties[i] {
|
|
|
|
archPropValues := reflect.ValueOf(archProperties).Elem()
|
|
|
|
|
2020-01-17 23:08:22 +01:00
|
|
|
targetProp := archPropValues.FieldByName("Target").Elem()
|
2019-10-16 20:07:20 +02:00
|
|
|
|
|
|
|
// Handle host-specific properties in the form:
|
|
|
|
// target: {
|
|
|
|
// host: {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// },
|
2020-09-14 12:43:17 +02:00
|
|
|
if os.Class == Host {
|
2019-10-16 20:07:20 +02:00
|
|
|
field := "Host"
|
|
|
|
prefix := "target.host"
|
2021-05-17 11:44:58 +02:00
|
|
|
if hostProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok {
|
|
|
|
mergePropertyStruct(ctx, genProps, hostProperties)
|
|
|
|
}
|
2019-10-16 20:07:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Handle target OS generalities of the form:
|
|
|
|
// target: {
|
|
|
|
// bionic: {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// }
|
|
|
|
if os.Linux() {
|
|
|
|
field := "Linux"
|
|
|
|
prefix := "target.linux"
|
2021-05-17 11:44:58 +02:00
|
|
|
if linuxProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok {
|
|
|
|
mergePropertyStruct(ctx, genProps, linuxProperties)
|
|
|
|
}
|
2019-10-16 20:07:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if os.Bionic() {
|
|
|
|
field := "Bionic"
|
|
|
|
prefix := "target.bionic"
|
2021-05-17 11:44:58 +02:00
|
|
|
if bionicProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok {
|
|
|
|
mergePropertyStruct(ctx, genProps, bionicProperties)
|
|
|
|
}
|
2019-10-16 20:07:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Handle target OS properties in the form:
|
|
|
|
// target: {
|
|
|
|
// linux_glibc: {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// not_windows: {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// android {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
field := os.Field
|
|
|
|
prefix := "target." + os.Name
|
2021-05-17 11:44:58 +02:00
|
|
|
if osProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok {
|
|
|
|
mergePropertyStruct(ctx, genProps, osProperties)
|
|
|
|
}
|
2019-10-16 20:07:20 +02:00
|
|
|
|
2020-09-14 12:43:17 +02:00
|
|
|
if os.Class == Host && os != Windows {
|
2019-10-16 20:07:20 +02:00
|
|
|
field := "Not_windows"
|
|
|
|
prefix := "target.not_windows"
|
2021-05-17 11:44:58 +02:00
|
|
|
if notWindowsProperties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok {
|
|
|
|
mergePropertyStruct(ctx, genProps, notWindowsProperties)
|
|
|
|
}
|
2019-10-16 20:07:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Handle 64-bit device properties in the form:
|
|
|
|
// target {
|
|
|
|
// android64 {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// android32 {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// WARNING: this is probably not what you want to use in your blueprints file, it selects
|
|
|
|
// options for all targets on a device that supports 64-bit binaries, not just the targets
|
|
|
|
// that are being compiled for 64-bit. Its expected use case is binaries like linker and
|
|
|
|
// debuggerd that need to know when they are a 32-bit process running on a 64-bit device
|
|
|
|
if os.Class == Device {
|
|
|
|
if ctx.Config().Android64() {
|
|
|
|
field := "Android64"
|
|
|
|
prefix := "target.android64"
|
2021-05-17 11:44:58 +02:00
|
|
|
if android64Properties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok {
|
|
|
|
mergePropertyStruct(ctx, genProps, android64Properties)
|
|
|
|
}
|
2019-10-16 20:07:20 +02:00
|
|
|
} else {
|
|
|
|
field := "Android32"
|
|
|
|
prefix := "target.android32"
|
2021-05-17 11:44:58 +02:00
|
|
|
if android32Properties, ok := getChildPropertyStruct(ctx, targetProp, field, prefix); ok {
|
|
|
|
mergePropertyStruct(ctx, genProps, android32Properties)
|
|
|
|
}
|
2019-10-16 20:07:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-05 09:00:01 +02:00
|
|
|
// Returns the struct containing the properties specific to the given
|
|
|
|
// architecture type. These look like this in Blueprint files:
|
|
|
|
// arch: {
|
|
|
|
// arm64: {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// This struct will also contain sub-structs containing to the architecture/CPU
|
|
|
|
// variants and features that themselves contain properties specific to those.
|
2021-05-17 11:44:58 +02:00
|
|
|
func getArchTypeStruct(ctx ArchVariantContext, archProperties interface{}, archType ArchType) (reflect.Value, bool) {
|
2021-05-05 09:00:01 +02:00
|
|
|
archPropValues := reflect.ValueOf(archProperties).Elem()
|
|
|
|
archProp := archPropValues.FieldByName("Arch").Elem()
|
|
|
|
prefix := "arch." + archType.Name
|
2021-05-17 11:44:58 +02:00
|
|
|
return getChildPropertyStruct(ctx, archProp, archType.Name, prefix)
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Returns the struct containing the properties specific to a given multilib
|
|
|
|
// value. These look like this in the Blueprint file:
|
|
|
|
// multilib: {
|
|
|
|
// lib32: {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// },
|
2021-05-17 11:44:58 +02:00
|
|
|
func getMultilibStruct(ctx ArchVariantContext, archProperties interface{}, archType ArchType) (reflect.Value, bool) {
|
2021-05-05 09:00:01 +02:00
|
|
|
archPropValues := reflect.ValueOf(archProperties).Elem()
|
|
|
|
multilibProp := archPropValues.FieldByName("Multilib").Elem()
|
2021-05-17 11:44:58 +02:00
|
|
|
return getChildPropertyStruct(ctx, multilibProp, archType.Multilib, "multilib."+archType.Multilib)
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
|
|
|
|
2021-05-21 14:37:59 +02:00
|
|
|
func GetCompoundTargetField(os OsType, arch ArchType) string {
|
2021-05-19 12:49:02 +02:00
|
|
|
return os.Field + "_" + arch.Name
|
|
|
|
}
|
|
|
|
|
2021-05-05 09:00:01 +02:00
|
|
|
// Returns the structs corresponding to the properties specific to the given
|
|
|
|
// architecture and OS in archProperties.
|
|
|
|
func getArchProperties(ctx BaseMutatorContext, archProperties interface{}, arch Arch, os OsType, nativeBridgeEnabled bool) []reflect.Value {
|
|
|
|
result := make([]reflect.Value, 0)
|
|
|
|
archPropValues := reflect.ValueOf(archProperties).Elem()
|
|
|
|
|
|
|
|
targetProp := archPropValues.FieldByName("Target").Elem()
|
|
|
|
|
|
|
|
archType := arch.ArchType
|
|
|
|
|
|
|
|
if arch.ArchType != Common {
|
2021-05-17 11:44:58 +02:00
|
|
|
archStruct, ok := getArchTypeStruct(ctx, archProperties, arch.ArchType)
|
|
|
|
if ok {
|
|
|
|
result = append(result, archStruct)
|
|
|
|
|
|
|
|
// Handle arch-variant-specific properties in the form:
|
|
|
|
// arch: {
|
|
|
|
// arm: {
|
|
|
|
// variant: {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
v := variantReplacer.Replace(arch.ArchVariant)
|
|
|
|
if v != "" {
|
|
|
|
prefix := "arch." + archType.Name + "." + v
|
|
|
|
if variantProperties, ok := getChildPropertyStruct(ctx, archStruct, v, prefix); ok {
|
|
|
|
result = append(result, variantProperties)
|
|
|
|
}
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
|
|
|
|
2021-05-17 11:44:58 +02:00
|
|
|
// Handle cpu-variant-specific properties in the form:
|
|
|
|
// arch: {
|
|
|
|
// arm: {
|
|
|
|
// variant: {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
if arch.CpuVariant != arch.ArchVariant {
|
|
|
|
c := variantReplacer.Replace(arch.CpuVariant)
|
|
|
|
if c != "" {
|
|
|
|
prefix := "arch." + archType.Name + "." + c
|
|
|
|
if cpuVariantProperties, ok := getChildPropertyStruct(ctx, archStruct, c, prefix); ok {
|
|
|
|
result = append(result, cpuVariantProperties)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle arch-feature-specific properties in the form:
|
|
|
|
// arch: {
|
|
|
|
// arm: {
|
|
|
|
// feature: {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
for _, feature := range arch.ArchFeatures {
|
|
|
|
prefix := "arch." + archType.Name + "." + feature
|
|
|
|
if featureProperties, ok := getChildPropertyStruct(ctx, archStruct, feature, prefix); ok {
|
|
|
|
result = append(result, featureProperties)
|
|
|
|
}
|
|
|
|
}
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
|
|
|
|
2021-05-17 11:44:58 +02:00
|
|
|
if multilibProperties, ok := getMultilibStruct(ctx, archProperties, archType); ok {
|
|
|
|
result = append(result, multilibProperties)
|
|
|
|
}
|
2021-05-05 09:00:01 +02:00
|
|
|
|
|
|
|
// Handle combined OS-feature and arch specific properties in the form:
|
|
|
|
// target: {
|
|
|
|
// bionic_x86: {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// }
|
|
|
|
if os.Linux() {
|
|
|
|
field := "Linux_" + arch.ArchType.Name
|
|
|
|
userFriendlyField := "target.linux_" + arch.ArchType.Name
|
2021-05-17 11:44:58 +02:00
|
|
|
if linuxProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok {
|
|
|
|
result = append(result, linuxProperties)
|
|
|
|
}
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if os.Bionic() {
|
|
|
|
field := "Bionic_" + archType.Name
|
|
|
|
userFriendlyField := "target.bionic_" + archType.Name
|
2021-05-17 11:44:58 +02:00
|
|
|
if bionicProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok {
|
|
|
|
result = append(result, bionicProperties)
|
|
|
|
}
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Handle combined OS and arch specific properties in the form:
|
|
|
|
// target: {
|
|
|
|
// linux_glibc_x86: {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// linux_glibc_arm: {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// android_arm {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// android_x86 {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// },
|
2021-05-21 14:37:59 +02:00
|
|
|
field := GetCompoundTargetField(os, archType)
|
2021-05-05 09:00:01 +02:00
|
|
|
userFriendlyField := "target." + os.Name + "_" + archType.Name
|
2021-05-17 11:44:58 +02:00
|
|
|
if osArchProperties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok {
|
|
|
|
result = append(result, osArchProperties)
|
|
|
|
}
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Handle arm on x86 properties in the form:
|
|
|
|
// target {
|
|
|
|
// arm_on_x86 {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// arm_on_x86_64 {
|
|
|
|
// key: value,
|
|
|
|
// },
|
|
|
|
// },
|
|
|
|
if os.Class == Device {
|
|
|
|
if arch.ArchType == X86 && (hasArmAbi(arch) ||
|
|
|
|
hasArmAndroidArch(ctx.Config().Targets[Android])) {
|
|
|
|
field := "Arm_on_x86"
|
|
|
|
userFriendlyField := "target.arm_on_x86"
|
2021-05-17 11:44:58 +02:00
|
|
|
if armOnX86Properties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok {
|
|
|
|
result = append(result, armOnX86Properties)
|
|
|
|
}
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
|
|
|
if arch.ArchType == X86_64 && (hasArmAbi(arch) ||
|
|
|
|
hasArmAndroidArch(ctx.Config().Targets[Android])) {
|
|
|
|
field := "Arm_on_x86_64"
|
|
|
|
userFriendlyField := "target.arm_on_x86_64"
|
2021-05-17 11:44:58 +02:00
|
|
|
if armOnX8664Properties, ok := getChildPropertyStruct(ctx, targetProp, field, userFriendlyField); ok {
|
|
|
|
result = append(result, armOnX8664Properties)
|
|
|
|
}
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
|
|
|
if os == Android && nativeBridgeEnabled {
|
|
|
|
userFriendlyField := "Native_bridge"
|
|
|
|
prefix := "target.native_bridge"
|
2021-05-17 11:44:58 +02:00
|
|
|
if nativeBridgeProperties, ok := getChildPropertyStruct(ctx, targetProp, userFriendlyField, prefix); ok {
|
|
|
|
result = append(result, nativeBridgeProperties)
|
|
|
|
}
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Squash the appropriate arch-specific property structs into the matching top level property
|
|
|
|
// structs based on the CompileTarget value that was annotated on the variant.
|
2019-06-07 01:57:04 +02:00
|
|
|
func (m *ModuleBase) setArchProperties(ctx BottomUpMutatorContext) {
|
|
|
|
arch := m.Arch()
|
|
|
|
os := m.Os()
|
2015-05-07 23:11:29 +02:00
|
|
|
|
2019-06-07 01:57:04 +02:00
|
|
|
for i := range m.generalProperties {
|
|
|
|
genProps := m.generalProperties[i]
|
|
|
|
if m.archProperties[i] == nil {
|
2016-06-24 08:44:54 +02:00
|
|
|
continue
|
|
|
|
}
|
2015-07-07 02:49:43 +02:00
|
|
|
|
2021-05-05 09:00:01 +02:00
|
|
|
propStructs := make([]reflect.Value, 0)
|
|
|
|
for _, archProperty := range m.archProperties[i] {
|
|
|
|
propStructShard := getArchProperties(ctx, archProperty, arch, os, m.Target().NativeBridge == NativeBridgeEnabled)
|
|
|
|
propStructs = append(propStructs, propStructShard...)
|
|
|
|
}
|
2017-09-22 21:28:24 +02:00
|
|
|
|
2021-05-05 09:00:01 +02:00
|
|
|
for _, propStruct := range propStructs {
|
|
|
|
mergePropertyStruct(ctx, genProps, propStruct)
|
2016-12-09 02:23:53 +01:00
|
|
|
}
|
2015-01-31 02:27:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Convert the arch product variables into a list of targets for each OsType.
|
2018-10-11 02:02:29 +02:00
|
|
|
func decodeTargetProductVariables(config *config) (map[OsType][]Target, error) {
|
2018-03-10 06:22:06 +01:00
|
|
|
variables := config.productVariables
|
2016-06-02 02:09:44 +02:00
|
|
|
|
2018-10-11 02:02:29 +02:00
|
|
|
targets := make(map[OsType][]Target)
|
2016-06-02 02:09:44 +02:00
|
|
|
var targetErr error
|
|
|
|
|
2019-03-26 12:39:31 +01:00
|
|
|
addTarget := func(os OsType, archName string, archVariant, cpuVariant *string, abi []string,
|
2019-07-11 10:23:53 +02:00
|
|
|
nativeBridgeEnabled NativeBridgeSupport, nativeBridgeHostArchName *string,
|
|
|
|
nativeBridgeRelativePath *string) {
|
2016-06-02 02:09:44 +02:00
|
|
|
if targetErr != nil {
|
|
|
|
return
|
2015-11-25 02:53:15 +01:00
|
|
|
}
|
|
|
|
|
2019-01-12 04:02:16 +01:00
|
|
|
arch, err := decodeArch(os, archName, archVariant, cpuVariant, abi)
|
2016-06-02 02:09:44 +02:00
|
|
|
if err != nil {
|
|
|
|
targetErr = err
|
|
|
|
return
|
|
|
|
}
|
2019-07-11 10:23:53 +02:00
|
|
|
nativeBridgeRelativePathStr := String(nativeBridgeRelativePath)
|
|
|
|
nativeBridgeHostArchNameStr := String(nativeBridgeHostArchName)
|
|
|
|
|
|
|
|
// Use guest arch as relative install path by default
|
|
|
|
if nativeBridgeEnabled && nativeBridgeRelativePathStr == "" {
|
|
|
|
nativeBridgeRelativePathStr = arch.ArchType.String()
|
|
|
|
}
|
2015-11-25 02:53:15 +01:00
|
|
|
|
2020-09-14 12:43:17 +02:00
|
|
|
// A target is considered as HostCross if it's a host target which can't run natively on
|
|
|
|
// the currently configured build machine (either because the OS is different or because of
|
|
|
|
// the unsupported arch)
|
|
|
|
hostCross := false
|
|
|
|
if os.Class == Host {
|
|
|
|
var osSupported bool
|
|
|
|
if os == BuildOs {
|
|
|
|
osSupported = true
|
|
|
|
} else if BuildOs.Linux() && os.Linux() {
|
|
|
|
// LinuxBionic and Linux are compatible
|
|
|
|
osSupported = true
|
|
|
|
} else {
|
|
|
|
osSupported = false
|
|
|
|
}
|
|
|
|
|
|
|
|
var archSupported bool
|
|
|
|
if arch.ArchType == Common {
|
|
|
|
archSupported = true
|
|
|
|
} else if arch.ArchType.Name == *variables.HostArch {
|
|
|
|
archSupported = true
|
|
|
|
} else if variables.HostSecondaryArch != nil && arch.ArchType.Name == *variables.HostSecondaryArch {
|
|
|
|
archSupported = true
|
|
|
|
} else {
|
|
|
|
archSupported = false
|
|
|
|
}
|
|
|
|
if !osSupported || !archSupported {
|
|
|
|
hostCross = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-11 02:02:29 +02:00
|
|
|
targets[os] = append(targets[os],
|
2016-06-02 02:09:44 +02:00
|
|
|
Target{
|
2019-07-11 10:23:53 +02:00
|
|
|
Os: os,
|
|
|
|
Arch: arch,
|
|
|
|
NativeBridge: nativeBridgeEnabled,
|
|
|
|
NativeBridgeHostArchName: nativeBridgeHostArchNameStr,
|
|
|
|
NativeBridgeRelativePath: nativeBridgeRelativePathStr,
|
2020-09-14 12:43:17 +02:00
|
|
|
HostCross: hostCross,
|
2016-06-02 02:09:44 +02:00
|
|
|
})
|
2015-09-17 23:33:42 +02:00
|
|
|
}
|
|
|
|
|
2016-06-02 02:09:44 +02:00
|
|
|
if variables.HostArch == nil {
|
|
|
|
return nil, fmt.Errorf("No host primary architecture set")
|
2015-09-17 23:33:42 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// The primary host target, which must always exist.
|
2019-07-11 10:23:53 +02:00
|
|
|
addTarget(BuildOs, *variables.HostArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
|
2015-09-17 23:33:42 +02:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// An optional secondary host target.
|
2015-11-20 22:07:51 +01:00
|
|
|
if variables.HostSecondaryArch != nil && *variables.HostSecondaryArch != "" {
|
2019-07-11 10:23:53 +02:00
|
|
|
addTarget(BuildOs, *variables.HostSecondaryArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
|
2016-06-14 02:19:03 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Optional cross-compiled host targets, generally Windows.
|
2018-04-11 01:15:18 +02:00
|
|
|
if String(variables.CrossHost) != "" {
|
2016-06-02 02:09:44 +02:00
|
|
|
crossHostOs := osByName(*variables.CrossHost)
|
|
|
|
if crossHostOs == NoOsType {
|
|
|
|
return nil, fmt.Errorf("Unknown cross host OS %q", *variables.CrossHost)
|
2015-11-25 02:53:15 +01:00
|
|
|
}
|
|
|
|
|
2018-04-11 01:15:18 +02:00
|
|
|
if String(variables.CrossHostArch) == "" {
|
2016-06-02 02:09:44 +02:00
|
|
|
return nil, fmt.Errorf("No cross-host primary architecture set")
|
2015-11-25 02:53:15 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// The primary cross-compiled host target.
|
2019-07-11 10:23:53 +02:00
|
|
|
addTarget(crossHostOs, *variables.CrossHostArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
|
2015-11-25 02:53:15 +01:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// An optional secondary cross-compiled host target.
|
2015-11-25 02:53:15 +01:00
|
|
|
if variables.CrossHostSecondaryArch != nil && *variables.CrossHostSecondaryArch != "" {
|
2019-07-11 10:23:53 +02:00
|
|
|
addTarget(crossHostOs, *variables.CrossHostSecondaryArch, nil, nil, nil, NativeBridgeDisabled, nil, nil)
|
2015-11-25 02:53:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Optional device targets
|
2016-07-11 23:36:48 +02:00
|
|
|
if variables.DeviceArch != nil && *variables.DeviceArch != "" {
|
2019-01-16 21:06:11 +01:00
|
|
|
var target = Android
|
|
|
|
if Bool(variables.Fuchsia) {
|
|
|
|
target = Fuchsia
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// The primary device target.
|
2019-01-16 21:06:11 +01:00
|
|
|
addTarget(target, *variables.DeviceArch, variables.DeviceArchVariant,
|
2019-07-11 10:23:53 +02:00
|
|
|
variables.DeviceCpuVariant, variables.DeviceAbi, NativeBridgeDisabled, nil, nil)
|
2015-09-17 23:33:42 +02:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// An optional secondary device target.
|
2016-07-11 23:36:48 +02:00
|
|
|
if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" {
|
|
|
|
addTarget(Android, *variables.DeviceSecondaryArch,
|
|
|
|
variables.DeviceSecondaryArchVariant, variables.DeviceSecondaryCpuVariant,
|
2019-07-11 10:23:53 +02:00
|
|
|
variables.DeviceSecondaryAbi, NativeBridgeDisabled, nil, nil)
|
2016-06-03 03:50:47 +02:00
|
|
|
}
|
2019-03-26 12:39:31 +01:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// An optional NativeBridge device target.
|
2019-03-26 12:39:31 +01:00
|
|
|
if variables.NativeBridgeArch != nil && *variables.NativeBridgeArch != "" {
|
|
|
|
addTarget(Android, *variables.NativeBridgeArch,
|
|
|
|
variables.NativeBridgeArchVariant, variables.NativeBridgeCpuVariant,
|
2019-07-11 10:23:53 +02:00
|
|
|
variables.NativeBridgeAbi, NativeBridgeEnabled, variables.DeviceArch,
|
|
|
|
variables.NativeBridgeRelativePath)
|
2019-03-26 12:39:31 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// An optional secondary NativeBridge device target.
|
2019-03-26 12:39:31 +01:00
|
|
|
if variables.DeviceSecondaryArch != nil && *variables.DeviceSecondaryArch != "" &&
|
|
|
|
variables.NativeBridgeSecondaryArch != nil && *variables.NativeBridgeSecondaryArch != "" {
|
|
|
|
addTarget(Android, *variables.NativeBridgeSecondaryArch,
|
|
|
|
variables.NativeBridgeSecondaryArchVariant,
|
|
|
|
variables.NativeBridgeSecondaryCpuVariant,
|
2019-07-11 10:23:53 +02:00
|
|
|
variables.NativeBridgeSecondaryAbi,
|
|
|
|
NativeBridgeEnabled,
|
|
|
|
variables.DeviceSecondaryArch,
|
|
|
|
variables.NativeBridgeSecondaryRelativePath)
|
2019-03-26 12:39:31 +01:00
|
|
|
}
|
2015-09-17 23:33:42 +02:00
|
|
|
}
|
|
|
|
|
2016-06-02 02:09:44 +02:00
|
|
|
if targetErr != nil {
|
|
|
|
return nil, targetErr
|
|
|
|
}
|
|
|
|
|
|
|
|
return targets, nil
|
2015-09-17 23:33:42 +02:00
|
|
|
}
|
|
|
|
|
2016-12-09 02:23:53 +01:00
|
|
|
// hasArmAbi returns true if arch has at least one arm ABI
|
|
|
|
func hasArmAbi(arch Arch) bool {
|
2020-02-11 16:54:35 +01:00
|
|
|
return PrefixInList(arch.Abi, "arm")
|
2016-12-09 02:23:53 +01:00
|
|
|
}
|
|
|
|
|
2019-05-22 17:16:21 +02:00
|
|
|
// hasArmArch returns true if targets has at least non-native_bridge arm Android arch
|
2017-04-14 01:56:14 +02:00
|
|
|
func hasArmAndroidArch(targets []Target) bool {
|
|
|
|
for _, target := range targets {
|
2020-09-17 03:07:31 +02:00
|
|
|
if target.Os == Android && target.Arch.ArchType == Arm {
|
2018-03-21 20:30:54 +01:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// archConfig describes a built-in configuration.
|
2016-10-19 23:04:41 +02:00
|
|
|
type archConfig struct {
|
|
|
|
arch string
|
|
|
|
archVariant string
|
|
|
|
cpuVariant string
|
|
|
|
abi []string
|
|
|
|
}
|
|
|
|
|
2020-07-30 23:32:55 +02:00
|
|
|
// getNdkAbisConfig returns the list of archConfigs that are used for bulding
|
|
|
|
// the API stubs and static libraries that are included in the NDK. These are
|
|
|
|
// built *without Neon*, because non-Neon is still supported and building these
|
|
|
|
// with Neon will break those users.
|
2016-10-19 23:04:41 +02:00
|
|
|
func getNdkAbisConfig() []archConfig {
|
|
|
|
return []archConfig{
|
2021-01-20 18:56:33 +01:00
|
|
|
{"arm64", "armv8-a-branchprot", "", []string{"arm64-v8a"}},
|
2021-06-16 17:33:00 +02:00
|
|
|
{"arm", "armv7-a", "", []string{"armeabi-v7a"}},
|
2016-10-19 23:04:41 +02:00
|
|
|
{"x86_64", "", "", []string{"x86_64"}},
|
2021-06-16 17:33:00 +02:00
|
|
|
{"x86", "", "", []string{"x86"}},
|
2016-10-19 23:04:41 +02:00
|
|
|
}
|
|
|
|
}
|
2016-01-13 08:07:05 +01:00
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// getAmlAbisConfig returns a list of archConfigs for the ABIs supported by mainline modules.
|
Add script for building all target arch's needed in AML (Android Mainline)
prebuilts.
This runs Soong in skip-make mode, using normal in-make mode only to query
platform versions.
The same ${OUT_DIR} cannot be used for both skip-make and in-make builds,
because Soong generates a smaller build.ninja file in in-make builds where
many build targets are expected to be provided by the mk files. Thus this
script avoids using ${OUT_DIR} if it's an in-make build, defaulting instead
to out-aml/.
The script is based on build-ndk-prebuilts.sh, but uses a separate Soong
variable Aml_abis to enable the appropriate target architectures for
Mainline modules. Aml_abis is very similar to Ndk_abis, except "armeabi-v7a"
is used instead of "armeabi", which is necessary to match prebuilt
dependencies, e.g. for LLVM.
Test: build/soong/scripts/build-aml-prebuilts.sh libart libdexfile_external
(verify that libraries for arm, arm64, x86, x86_64 are built)
Test: build/soong/scripts/build-aml-prebuilts.sh \
out-aml/soong/.intermediates/external/conscrypt/conscrypt-module-sdk/android_common/conscrypt-module-sdk-current.zip
(verify that the zip file contains libconscrypt_jni.so's for all four arches)
Test: build/soong/scripts/build-aml-prebuilts.sh com.android.art.{release,debug,testing,host}
(verify that the build completes)
Test: Two identical build/soong/scripts/build-aml-prebuilts.sh runs after each other
(verify that the 2nd run completes both Soong and ninja steps quickly without any building)
Change-Id: I35712f9f8f0b1cbb77107314c5927c6720e6c3bf
2019-11-15 16:00:31 +01:00
|
|
|
func getAmlAbisConfig() []archConfig {
|
|
|
|
return []archConfig{
|
|
|
|
{"arm64", "armv8-a", "", []string{"arm64-v8a"}},
|
2021-06-16 17:33:00 +02:00
|
|
|
{"arm", "armv7-a-neon", "", []string{"armeabi-v7a"}},
|
Add script for building all target arch's needed in AML (Android Mainline)
prebuilts.
This runs Soong in skip-make mode, using normal in-make mode only to query
platform versions.
The same ${OUT_DIR} cannot be used for both skip-make and in-make builds,
because Soong generates a smaller build.ninja file in in-make builds where
many build targets are expected to be provided by the mk files. Thus this
script avoids using ${OUT_DIR} if it's an in-make build, defaulting instead
to out-aml/.
The script is based on build-ndk-prebuilts.sh, but uses a separate Soong
variable Aml_abis to enable the appropriate target architectures for
Mainline modules. Aml_abis is very similar to Ndk_abis, except "armeabi-v7a"
is used instead of "armeabi", which is necessary to match prebuilt
dependencies, e.g. for LLVM.
Test: build/soong/scripts/build-aml-prebuilts.sh libart libdexfile_external
(verify that libraries for arm, arm64, x86, x86_64 are built)
Test: build/soong/scripts/build-aml-prebuilts.sh \
out-aml/soong/.intermediates/external/conscrypt/conscrypt-module-sdk/android_common/conscrypt-module-sdk-current.zip
(verify that the zip file contains libconscrypt_jni.so's for all four arches)
Test: build/soong/scripts/build-aml-prebuilts.sh com.android.art.{release,debug,testing,host}
(verify that the build completes)
Test: Two identical build/soong/scripts/build-aml-prebuilts.sh runs after each other
(verify that the 2nd run completes both Soong and ninja steps quickly without any building)
Change-Id: I35712f9f8f0b1cbb77107314c5927c6720e6c3bf
2019-11-15 16:00:31 +01:00
|
|
|
{"x86_64", "", "", []string{"x86_64"}},
|
2021-06-16 17:33:00 +02:00
|
|
|
{"x86", "", "", []string{"x86"}},
|
Add script for building all target arch's needed in AML (Android Mainline)
prebuilts.
This runs Soong in skip-make mode, using normal in-make mode only to query
platform versions.
The same ${OUT_DIR} cannot be used for both skip-make and in-make builds,
because Soong generates a smaller build.ninja file in in-make builds where
many build targets are expected to be provided by the mk files. Thus this
script avoids using ${OUT_DIR} if it's an in-make build, defaulting instead
to out-aml/.
The script is based on build-ndk-prebuilts.sh, but uses a separate Soong
variable Aml_abis to enable the appropriate target architectures for
Mainline modules. Aml_abis is very similar to Ndk_abis, except "armeabi-v7a"
is used instead of "armeabi", which is necessary to match prebuilt
dependencies, e.g. for LLVM.
Test: build/soong/scripts/build-aml-prebuilts.sh libart libdexfile_external
(verify that libraries for arm, arm64, x86, x86_64 are built)
Test: build/soong/scripts/build-aml-prebuilts.sh \
out-aml/soong/.intermediates/external/conscrypt/conscrypt-module-sdk/android_common/conscrypt-module-sdk-current.zip
(verify that the zip file contains libconscrypt_jni.so's for all four arches)
Test: build/soong/scripts/build-aml-prebuilts.sh com.android.art.{release,debug,testing,host}
(verify that the build completes)
Test: Two identical build/soong/scripts/build-aml-prebuilts.sh runs after each other
(verify that the 2nd run completes both Soong and ninja steps quickly without any building)
Change-Id: I35712f9f8f0b1cbb77107314c5927c6720e6c3bf
2019-11-15 16:00:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// decodeArchSettings converts a list of archConfigs into a list of Targets for the given OsType.
|
2019-01-12 04:02:16 +01:00
|
|
|
func decodeArchSettings(os OsType, archConfigs []archConfig) ([]Target, error) {
|
2016-06-02 02:09:44 +02:00
|
|
|
var ret []Target
|
2016-01-13 08:07:05 +01:00
|
|
|
|
2016-10-19 23:04:41 +02:00
|
|
|
for _, config := range archConfigs {
|
2019-01-12 04:02:16 +01:00
|
|
|
arch, err := decodeArch(os, config.arch, &config.archVariant,
|
2019-01-31 23:31:51 +01:00
|
|
|
&config.cpuVariant, config.abi)
|
2016-01-13 08:07:05 +01:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-09-17 23:45:31 +02:00
|
|
|
|
2016-06-02 02:09:44 +02:00
|
|
|
ret = append(ret, Target{
|
|
|
|
Os: Android,
|
|
|
|
Arch: arch,
|
|
|
|
})
|
2016-01-13 08:07:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret, nil
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// decodeArch converts a set of strings from product variables into an Arch struct.
|
2019-01-31 23:31:51 +01:00
|
|
|
func decodeArch(os OsType, arch string, archVariant, cpuVariant *string, abi []string) (Arch, error) {
|
2020-11-17 00:08:19 +01:00
|
|
|
// Verify the arch is valid
|
2015-11-20 22:07:51 +01:00
|
|
|
archType, ok := archTypeMap[arch]
|
|
|
|
if !ok {
|
|
|
|
return Arch{}, fmt.Errorf("unknown arch %q", arch)
|
|
|
|
}
|
2015-09-17 23:33:42 +02:00
|
|
|
|
2015-11-20 22:07:51 +01:00
|
|
|
a := Arch{
|
2015-09-17 23:33:42 +02:00
|
|
|
ArchType: archType,
|
2020-11-17 00:08:19 +01:00
|
|
|
ArchVariant: String(archVariant),
|
|
|
|
CpuVariant: String(cpuVariant),
|
2019-01-31 23:31:51 +01:00
|
|
|
Abi: abi,
|
2015-11-20 22:07:51 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Convert generic arch variants into the empty string.
|
2015-11-20 22:07:51 +01:00
|
|
|
if a.ArchVariant == a.ArchType.Name || a.ArchVariant == "generic" {
|
|
|
|
a.ArchVariant = ""
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Convert generic CPU variants into the empty string.
|
2015-11-20 22:07:51 +01:00
|
|
|
if a.CpuVariant == a.ArchType.Name || a.CpuVariant == "generic" {
|
|
|
|
a.CpuVariant = ""
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// Filter empty ABIs out of the list.
|
2015-11-20 22:07:51 +01:00
|
|
|
for i := 0; i < len(a.Abi); i++ {
|
|
|
|
if a.Abi[i] == "" {
|
|
|
|
a.Abi = append(a.Abi[:i], a.Abi[i+1:]...)
|
|
|
|
i--
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-12 04:02:16 +01:00
|
|
|
if a.ArchVariant == "" {
|
2020-11-17 00:08:19 +01:00
|
|
|
// Set ArchFeatures from the default arch features.
|
2019-01-12 04:02:16 +01:00
|
|
|
if featureMap, ok := defaultArchFeatureMap[os]; ok {
|
|
|
|
a.ArchFeatures = featureMap[archType]
|
|
|
|
}
|
|
|
|
} else {
|
2020-11-17 00:08:19 +01:00
|
|
|
// Set ArchFeatures from the arch type.
|
2019-01-12 04:02:16 +01:00
|
|
|
if featureMap, ok := archFeatureMap[archType]; ok {
|
|
|
|
a.ArchFeatures = featureMap[a.ArchVariant]
|
|
|
|
}
|
2015-11-21 00:35:00 +01:00
|
|
|
}
|
|
|
|
|
2015-11-20 22:07:51 +01:00
|
|
|
return a, nil
|
2015-09-17 23:33:42 +02:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// filterMultilibTargets takes a list of Targets and a multilib value and returns a new list of
|
|
|
|
// Targets containing only those that have the given multilib value.
|
2016-09-06 19:39:07 +02:00
|
|
|
func filterMultilibTargets(targets []Target, multilib string) []Target {
|
|
|
|
var ret []Target
|
|
|
|
for _, t := range targets {
|
|
|
|
if t.Arch.ArchType.Multilib == multilib {
|
|
|
|
ret = append(ret, t)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// getCommonTargets returns the set of Os specific common architecture targets for each Os in a list
|
|
|
|
// of targets.
|
2017-02-27 19:12:13 +01:00
|
|
|
func getCommonTargets(targets []Target) []Target {
|
|
|
|
var ret []Target
|
|
|
|
set := make(map[string]bool)
|
|
|
|
|
|
|
|
for _, t := range targets {
|
|
|
|
if _, found := set[t.Os.String()]; !found {
|
|
|
|
set[t.Os.String()] = true
|
|
|
|
ret = append(ret, commonTargetMap[t.Os.String()])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// firstTarget takes a list of Targets and a list of multilib values and returns a list of Targets
|
|
|
|
// that contains zero or one Target for each OsType, selecting the one that matches the earliest
|
|
|
|
// filter.
|
2018-09-06 19:19:57 +02:00
|
|
|
func firstTarget(targets []Target, filters ...string) []Target {
|
2020-09-17 12:09:58 +02:00
|
|
|
// find the first target from each OS
|
|
|
|
var ret []Target
|
|
|
|
hasHost := false
|
|
|
|
set := make(map[OsType]bool)
|
|
|
|
|
2017-12-05 22:42:45 +01:00
|
|
|
for _, filter := range filters {
|
|
|
|
buildTargets := filterMultilibTargets(targets, filter)
|
2020-09-17 12:09:58 +02:00
|
|
|
for _, t := range buildTargets {
|
|
|
|
if _, found := set[t.Os]; !found {
|
|
|
|
hasHost = hasHost || (t.Os.Class == Host)
|
|
|
|
set[t.Os] = true
|
|
|
|
ret = append(ret, t)
|
|
|
|
}
|
2017-12-05 22:42:45 +01:00
|
|
|
}
|
|
|
|
}
|
2020-09-17 12:09:58 +02:00
|
|
|
return ret
|
2017-12-05 22:42:45 +01:00
|
|
|
}
|
|
|
|
|
2020-11-17 00:08:19 +01:00
|
|
|
// decodeMultilibTargets uses the module's multilib setting to select one or more targets from a
|
|
|
|
// list of Targets.
|
2018-10-03 07:01:37 +02:00
|
|
|
func decodeMultilibTargets(multilib string, targets []Target, prefer32 bool) ([]Target, error) {
|
2020-11-17 00:08:19 +01:00
|
|
|
var buildTargets []Target
|
2017-12-05 22:42:45 +01:00
|
|
|
|
|
|
|
switch multilib {
|
|
|
|
case "common":
|
|
|
|
buildTargets = getCommonTargets(targets)
|
|
|
|
case "common_first":
|
|
|
|
buildTargets = getCommonTargets(targets)
|
2016-09-13 18:59:14 +02:00
|
|
|
if prefer32 {
|
2018-09-06 19:19:57 +02:00
|
|
|
buildTargets = append(buildTargets, firstTarget(targets, "lib32", "lib64")...)
|
2016-09-13 18:59:14 +02:00
|
|
|
} else {
|
2018-09-06 19:19:57 +02:00
|
|
|
buildTargets = append(buildTargets, firstTarget(targets, "lib64", "lib32")...)
|
2016-09-13 18:59:14 +02:00
|
|
|
}
|
2015-09-17 23:33:42 +02:00
|
|
|
case "both":
|
2016-09-13 18:59:14 +02:00
|
|
|
if prefer32 {
|
|
|
|
buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...)
|
|
|
|
buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib64")...)
|
|
|
|
} else {
|
|
|
|
buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib64")...)
|
|
|
|
buildTargets = append(buildTargets, filterMultilibTargets(targets, "lib32")...)
|
|
|
|
}
|
2015-09-17 23:33:42 +02:00
|
|
|
case "32":
|
2016-09-06 19:39:07 +02:00
|
|
|
buildTargets = filterMultilibTargets(targets, "lib32")
|
2015-09-17 23:33:42 +02:00
|
|
|
case "64":
|
2016-09-06 19:39:07 +02:00
|
|
|
buildTargets = filterMultilibTargets(targets, "lib64")
|
2017-12-05 22:42:45 +01:00
|
|
|
case "first":
|
|
|
|
if prefer32 {
|
2018-09-06 19:19:57 +02:00
|
|
|
buildTargets = firstTarget(targets, "lib32", "lib64")
|
2017-12-05 22:42:45 +01:00
|
|
|
} else {
|
2018-09-06 19:19:57 +02:00
|
|
|
buildTargets = firstTarget(targets, "lib64", "lib32")
|
2016-09-13 18:59:14 +02:00
|
|
|
}
|
2020-09-14 16:34:16 +02:00
|
|
|
case "first_prefer32":
|
|
|
|
buildTargets = firstTarget(targets, "lib32", "lib64")
|
2017-12-05 22:42:45 +01:00
|
|
|
case "prefer32":
|
2018-09-06 19:19:57 +02:00
|
|
|
buildTargets = filterMultilibTargets(targets, "lib32")
|
|
|
|
if len(buildTargets) == 0 {
|
|
|
|
buildTargets = filterMultilibTargets(targets, "lib64")
|
|
|
|
}
|
2015-09-17 23:33:42 +02:00
|
|
|
default:
|
2020-09-14 16:34:16 +02:00
|
|
|
return nil, fmt.Errorf(`compile_multilib must be "both", "first", "32", "64", "prefer32" or "first_prefer32" found %q`,
|
2015-09-17 23:33:42 +02:00
|
|
|
multilib)
|
|
|
|
}
|
|
|
|
|
2016-06-02 02:09:44 +02:00
|
|
|
return buildTargets, nil
|
2015-09-17 23:33:42 +02:00
|
|
|
}
|
2021-02-24 13:20:12 +01:00
|
|
|
|
2021-04-30 00:06:50 +02:00
|
|
|
func (m *ModuleBase) getArchPropertySet(propertySet interface{}, archType ArchType) interface{} {
|
|
|
|
archString := archType.Field
|
2021-02-24 13:20:12 +01:00
|
|
|
for i := range m.archProperties {
|
|
|
|
if m.archProperties[i] == nil {
|
2021-04-30 00:06:50 +02:00
|
|
|
// Skip over nil properties
|
2021-02-24 13:20:12 +01:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-04-30 00:06:50 +02:00
|
|
|
// Not archProperties are usable; this function looks for properties of a very specific
|
|
|
|
// form, and ignores the rest.
|
|
|
|
for _, archProperty := range m.archProperties[i] {
|
|
|
|
// archPropValue is a property struct, we are looking for the form:
|
|
|
|
// `arch: { arm: { key: value, ... }}`
|
|
|
|
archPropValue := reflect.ValueOf(archProperty).Elem()
|
|
|
|
|
|
|
|
// Unwrap src so that it should looks like a pointer to `arm: { key: value, ... }`
|
|
|
|
src := archPropValue.FieldByName("Arch").Elem()
|
|
|
|
|
|
|
|
// Step into non-nil pointers to structs in the src value.
|
|
|
|
if src.Kind() == reflect.Ptr {
|
|
|
|
if src.IsNil() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
src = src.Elem()
|
|
|
|
}
|
2021-02-24 13:20:12 +01:00
|
|
|
|
2021-04-30 00:06:50 +02:00
|
|
|
// Find the requested field (e.g. arm, x86) in the src struct.
|
|
|
|
src = src.FieldByName(archString)
|
|
|
|
|
|
|
|
// We only care about structs.
|
|
|
|
if !src.IsValid() || src.Kind() != reflect.Struct {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the value of the field is a struct then step into the
|
|
|
|
// BlueprintEmbed field. The special "BlueprintEmbed" name is
|
|
|
|
// used by createArchPropTypeDesc to embed the arch properties
|
|
|
|
// in the parent struct, so the src arch prop should be in this
|
|
|
|
// field.
|
2021-02-24 13:20:12 +01:00
|
|
|
//
|
2021-04-30 00:06:50 +02:00
|
|
|
// See createArchPropTypeDesc for more details on how Arch-specific
|
|
|
|
// module properties are processed from the nested props and written
|
|
|
|
// into the module's archProperties.
|
|
|
|
src = src.FieldByName("BlueprintEmbed")
|
|
|
|
|
|
|
|
// Clone the destination prop, since we want a unique prop struct per arch.
|
|
|
|
propertySetClone := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
|
|
|
|
|
|
|
|
// Copy the located property struct into the cloned destination property struct.
|
|
|
|
err := proptools.ExtendMatchingProperties([]interface{}{propertySetClone}, src.Interface(), nil, proptools.OrderReplace)
|
|
|
|
if err != nil {
|
|
|
|
// This is fine, it just means the src struct doesn't match the type of propertySet.
|
|
|
|
continue
|
|
|
|
}
|
2021-02-24 13:20:12 +01:00
|
|
|
|
2021-04-30 00:06:50 +02:00
|
|
|
return propertySetClone
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// No property set was found specific to the given arch, so return an empty
|
|
|
|
// property set.
|
|
|
|
return reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
|
|
|
|
}
|
2021-02-24 13:20:12 +01:00
|
|
|
|
2021-04-30 00:06:50 +02:00
|
|
|
// getMultilibPropertySet returns a property set struct matching the type of
|
|
|
|
// `propertySet`, containing multilib-specific module properties for the given architecture.
|
|
|
|
// If no multilib-specific properties exist for the given architecture, returns an empty property
|
|
|
|
// set matching `propertySet`'s type.
|
|
|
|
func (m *ModuleBase) getMultilibPropertySet(propertySet interface{}, archType ArchType) interface{} {
|
|
|
|
// archType.Multilib is lowercase (for example, lib32) but property struct field is
|
|
|
|
// capitalized, such as Lib32, so use strings.Title to capitalize it.
|
|
|
|
multiLibString := strings.Title(archType.Multilib)
|
2021-02-24 13:20:12 +01:00
|
|
|
|
2021-04-30 00:06:50 +02:00
|
|
|
for i := range m.archProperties {
|
|
|
|
if m.archProperties[i] == nil {
|
|
|
|
// Skip over nil properties
|
|
|
|
continue
|
|
|
|
}
|
2021-02-24 13:20:12 +01:00
|
|
|
|
2021-04-30 00:06:50 +02:00
|
|
|
// Not archProperties are usable; this function looks for properties of a very specific
|
|
|
|
// form, and ignores the rest.
|
|
|
|
for _, archProperties := range m.archProperties[i] {
|
|
|
|
// archPropValue is a property struct, we are looking for the form:
|
|
|
|
// `multilib: { lib32: { key: value, ... }}`
|
|
|
|
archPropValue := reflect.ValueOf(archProperties).Elem()
|
|
|
|
|
|
|
|
// Unwrap src so that it should looks like a pointer to `lib32: { key: value, ... }`
|
|
|
|
src := archPropValue.FieldByName("Multilib").Elem()
|
2021-02-24 13:20:12 +01:00
|
|
|
|
2021-04-30 00:06:50 +02:00
|
|
|
// Step into non-nil pointers to structs in the src value.
|
|
|
|
if src.Kind() == reflect.Ptr {
|
|
|
|
if src.IsNil() {
|
|
|
|
// Ignore nil pointers.
|
2021-02-24 13:20:12 +01:00
|
|
|
continue
|
|
|
|
}
|
2021-04-30 00:06:50 +02:00
|
|
|
src = src.Elem()
|
|
|
|
}
|
2021-02-24 13:20:12 +01:00
|
|
|
|
2021-04-30 00:06:50 +02:00
|
|
|
// Find the requested field (e.g. lib32) in the src struct.
|
|
|
|
src = src.FieldByName(multiLibString)
|
2021-02-24 13:20:12 +01:00
|
|
|
|
2021-04-30 00:06:50 +02:00
|
|
|
// We only care about valid struct pointers.
|
|
|
|
if !src.IsValid() || src.Kind() != reflect.Ptr || src.Elem().Kind() != reflect.Struct {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the zero value for the requested property set.
|
|
|
|
propertySetClone := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
|
|
|
|
|
|
|
|
// Copy the located property struct into the "zero" property set struct.
|
|
|
|
err := proptools.ExtendMatchingProperties([]interface{}{propertySetClone}, src.Interface(), nil, proptools.OrderReplace)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
// This is fine, it just means the src struct doesn't match.
|
|
|
|
continue
|
2021-02-24 13:20:12 +01:00
|
|
|
}
|
2021-04-30 00:06:50 +02:00
|
|
|
|
|
|
|
return propertySetClone
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// There were no multilib properties specifically matching the given archtype.
|
|
|
|
// Return zeroed value.
|
|
|
|
return reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
|
|
|
|
}
|
|
|
|
|
2021-05-14 21:14:40 +02:00
|
|
|
// ArchVariantContext defines the limited context necessary to retrieve arch_variant properties.
|
|
|
|
type ArchVariantContext interface {
|
|
|
|
ModuleErrorf(fmt string, args ...interface{})
|
|
|
|
PropertyErrorf(property, fmt string, args ...interface{})
|
|
|
|
}
|
|
|
|
|
2021-05-21 14:37:59 +02:00
|
|
|
// ArchVariantProperties represents a map of arch-variant config strings to a property interface{}.
|
|
|
|
type ArchVariantProperties map[string]interface{}
|
|
|
|
|
|
|
|
// ConfigurationAxisToArchVariantProperties represents a map of bazel.ConfigurationAxis to
|
|
|
|
// ArchVariantProperties, such that each independent arch-variant axis maps to the
|
|
|
|
// configs/properties for that axis.
|
|
|
|
type ConfigurationAxisToArchVariantProperties map[bazel.ConfigurationAxis]ArchVariantProperties
|
|
|
|
|
|
|
|
// GetArchVariantProperties returns a ConfigurationAxisToArchVariantProperties where the
|
|
|
|
// arch-variant properties correspond to the values of the properties of the 'propertySet' struct
|
|
|
|
// that are specific to that axis/configuration. Each axis is independent, containing
|
|
|
|
// non-overlapping configs that correspond to the various "arch-variant" support, at this time:
|
|
|
|
// arches (including multilib)
|
|
|
|
// oses
|
|
|
|
// arch+os combinations
|
2021-04-30 00:06:50 +02:00
|
|
|
//
|
2021-05-21 14:37:59 +02:00
|
|
|
// For example, passing a struct { Foo bool, Bar string } will return an interface{} that can be
|
|
|
|
// type asserted back into the same struct, containing the config-specific property value specified
|
|
|
|
// by the module if defined.
|
2021-04-30 00:06:50 +02:00
|
|
|
//
|
|
|
|
// Arch-specific properties may come from an arch stanza or a multilib stanza; properties
|
|
|
|
// in these stanzas are combined.
|
|
|
|
// For example: `arch: { x86: { Foo: ["bar"] } }, multilib: { lib32: {` Foo: ["baz"] } }`
|
|
|
|
// will result in `Foo: ["bar", "baz"]` being returned for architecture x86, if the given
|
|
|
|
// propertyset contains `Foo []string`.
|
2021-05-21 14:37:59 +02:00
|
|
|
func (m *ModuleBase) GetArchVariantProperties(ctx ArchVariantContext, propertySet interface{}) ConfigurationAxisToArchVariantProperties {
|
2021-04-30 00:06:50 +02:00
|
|
|
// Return value of the arch types to the prop values for that arch.
|
2021-05-21 14:37:59 +02:00
|
|
|
axisToProps := ConfigurationAxisToArchVariantProperties{}
|
2021-04-30 00:06:50 +02:00
|
|
|
|
|
|
|
// Nothing to do for non-arch-specific modules.
|
|
|
|
if !m.ArchSpecific() {
|
2021-05-21 14:37:59 +02:00
|
|
|
return axisToProps
|
2021-04-30 00:06:50 +02:00
|
|
|
}
|
|
|
|
|
2021-05-05 09:00:01 +02:00
|
|
|
dstType := reflect.ValueOf(propertySet).Type()
|
|
|
|
var archProperties []interface{}
|
|
|
|
|
|
|
|
// First find the property set in the module that corresponds to the requested
|
|
|
|
// one. m.archProperties[i] corresponds to m.generalProperties[i].
|
|
|
|
for i, generalProp := range m.generalProperties {
|
|
|
|
srcType := reflect.ValueOf(generalProp).Type()
|
|
|
|
if srcType == dstType {
|
|
|
|
archProperties = m.archProperties[i]
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if archProperties == nil {
|
|
|
|
// This module does not have the property set requested
|
2021-05-21 14:37:59 +02:00
|
|
|
return axisToProps
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
|
|
|
|
2021-05-21 14:37:59 +02:00
|
|
|
archToProp := ArchVariantProperties{}
|
2021-05-05 09:00:01 +02:00
|
|
|
// For each arch type (x86, arm64, etc.)
|
2021-04-30 00:06:50 +02:00
|
|
|
for _, arch := range ArchTypeList() {
|
2021-05-05 09:00:01 +02:00
|
|
|
// Arch properties are sometimes sharded (see createArchPropTypeDesc() ).
|
|
|
|
// Iterate over ever shard and extract a struct with the same type as the
|
|
|
|
// input one that contains the data specific to that arch.
|
|
|
|
propertyStructs := make([]reflect.Value, 0)
|
|
|
|
for _, archProperty := range archProperties {
|
2021-05-17 11:44:58 +02:00
|
|
|
archTypeStruct, ok := getArchTypeStruct(ctx, archProperty, arch)
|
|
|
|
if ok {
|
|
|
|
propertyStructs = append(propertyStructs, archTypeStruct)
|
|
|
|
}
|
|
|
|
multilibStruct, ok := getMultilibStruct(ctx, archProperty, arch)
|
|
|
|
if ok {
|
|
|
|
propertyStructs = append(propertyStructs, multilibStruct)
|
|
|
|
}
|
2021-05-05 09:00:01 +02:00
|
|
|
}
|
2021-04-30 00:06:50 +02:00
|
|
|
|
2021-05-05 09:00:01 +02:00
|
|
|
// Create a new instance of the requested property set
|
|
|
|
value := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
|
2021-04-30 00:06:50 +02:00
|
|
|
|
2021-05-05 09:00:01 +02:00
|
|
|
// Merge all the structs together
|
|
|
|
for _, propertyStruct := range propertyStructs {
|
|
|
|
mergePropertyStruct(ctx, value, propertyStruct)
|
2021-02-24 13:20:12 +01:00
|
|
|
}
|
2021-04-30 00:06:50 +02:00
|
|
|
|
2021-05-21 14:37:59 +02:00
|
|
|
archToProp[arch.Name] = value
|
|
|
|
}
|
|
|
|
axisToProps[bazel.ArchConfigurationAxis] = archToProp
|
|
|
|
|
|
|
|
osToProp := ArchVariantProperties{}
|
|
|
|
archOsToProp := ArchVariantProperties{}
|
|
|
|
// For android, linux, ...
|
|
|
|
for _, os := range osTypeList {
|
|
|
|
if os == CommonOS {
|
|
|
|
// It looks like this OS value is not used in Blueprint files
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
osToProp[os.Name] = getTargetStruct(ctx, propertySet, archProperties, os.Field)
|
|
|
|
// For arm, x86, ...
|
|
|
|
for _, arch := range osArchTypeMap[os] {
|
|
|
|
targetField := GetCompoundTargetField(os, arch)
|
|
|
|
targetName := fmt.Sprintf("%s_%s", os.Name, arch.Name)
|
|
|
|
archOsToProp[targetName] = getTargetStruct(ctx, propertySet, archProperties, targetField)
|
|
|
|
}
|
2021-02-24 13:20:12 +01:00
|
|
|
}
|
2021-05-21 14:37:59 +02:00
|
|
|
axisToProps[bazel.OsConfigurationAxis] = osToProp
|
|
|
|
axisToProps[bazel.OsArchConfigurationAxis] = archOsToProp
|
2021-05-05 09:00:01 +02:00
|
|
|
|
2021-05-21 14:37:59 +02:00
|
|
|
return axisToProps
|
2021-02-24 13:20:12 +01:00
|
|
|
}
|
Add os/target configurable selects for label list attributes.
This CL is pretty large, so I recommend starting with reading the newly
added tests for the expected behavior.
This change works in conjunction with the linked CLs in the Gerrit topic.
Those CLs add support for new platform() definitions for OS targets
specified in Soong's arch.go, which are configurable through
Android.bp's `target {}` property. It works similary to previous CLs
adding support for the `arch {}` property.
These configurable props are keyed by the OS: android, linux_bionic,
windows, and so on. They map to `select` statements in label list
attributes, which this CL enables for cc_library_headers' header_libs
and export_header_lib_headers props.
This enables //bionic/libc:libc_headers to be generated correctly, from:
cc_library_headers {
name: "libc_headers",
target: {
android: {
header_libs: ["libc_headers_arch"],
export_header_lib_headers: ["libc_headers_arch"],
},
linux_bionic: {
header_libs: ["libc_headers_arch"],
export_header_lib_headers: ["libc_headers_arch"],
},
},
// omitted props
}
to:
cc_library_headers(
name = "libc_headers",
deps = [] + select({
"//build/bazel/platforms/os:android": [
":libc_headers_arch",
],
"//build/bazel/platforms/os:linux_bionic": [
":libc_headers_arch",
],
"//conditions:default": [],
}),
)
Test: TH
Test: Verify generated //bionic/libc:libc_headers
Fixes: 183597786
Change-Id: I01016cc2cc9a71449f02300d747f01decebf3f6e
2021-03-24 07:18:33 +01:00
|
|
|
|
2021-05-19 12:49:02 +02:00
|
|
|
// Returns a struct matching the propertySet interface, containing properties specific to the targetName
|
|
|
|
// For example, given these arguments:
|
|
|
|
// propertySet = BaseCompilerProperties
|
|
|
|
// targetName = "android_arm"
|
|
|
|
// And given this Android.bp fragment:
|
|
|
|
// target:
|
|
|
|
// android_arm: {
|
|
|
|
// srcs: ["foo.c"],
|
|
|
|
// }
|
|
|
|
// android_arm64: {
|
|
|
|
// srcs: ["bar.c"],
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// This would return a BaseCompilerProperties with BaseCompilerProperties.Srcs = ["foo.c"]
|
|
|
|
func getTargetStruct(ctx ArchVariantContext, propertySet interface{}, archProperties []interface{}, targetName string) interface{} {
|
|
|
|
propertyStructs := make([]reflect.Value, 0)
|
|
|
|
for _, archProperty := range archProperties {
|
|
|
|
archPropValues := reflect.ValueOf(archProperty).Elem()
|
|
|
|
targetProp := archPropValues.FieldByName("Target").Elem()
|
|
|
|
targetStruct, ok := getChildPropertyStruct(ctx, targetProp, targetName, targetName)
|
|
|
|
if ok {
|
|
|
|
propertyStructs = append(propertyStructs, targetStruct)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a new instance of the requested property set
|
|
|
|
value := reflect.New(reflect.ValueOf(propertySet).Elem().Type()).Interface()
|
|
|
|
|
|
|
|
// Merge all the structs together
|
|
|
|
for _, propertyStruct := range propertyStructs {
|
|
|
|
mergePropertyStruct(ctx, value, propertyStruct)
|
|
|
|
}
|
|
|
|
|
|
|
|
return value
|
|
|
|
}
|