blob: 58d6ad0adb45bfed95347c9b939ffa6a086e7163 [file] [log] [blame]
// Copyright 2020 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cc
import (
"path/filepath"
"strings"
"android/soong/android"
"github.com/google/blueprint"
)
func init() {
android.RegisterSdkMemberType(ccBinarySdkMemberType)
}
var ccBinarySdkMemberType = &binarySdkMemberType{
SdkMemberTypeBase: android.SdkMemberTypeBase{
PropertyName: "native_binaries",
},
}
type binarySdkMemberType struct {
android.SdkMemberTypeBase
}
func (mt *binarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
targets := mctx.MultiTargets()
for _, lib := range names {
for _, target := range targets {
name, version := StubsLibNameAndVersion(lib)
if version == "" {
version = LatestStubsVersionFor(mctx.Config(), name)
}
mctx.AddFarVariationDependencies(append(target.Variations(), []blueprint.Variation{
{Mutator: "version", Variation: version},
}...), dependencyTag, name)
}
}
}
func (mt *binarySdkMemberType) IsInstance(module android.Module) bool {
// Check the module to see if it can be used with this module type.
if m, ok := module.(*Module); ok {
for _, allowableMemberType := range m.sdkMemberTypes {
if allowableMemberType == mt {
return true
}
}
}
return false
}
func (mt *binarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
info := mt.organizeVariants(member)
buildSharedNativeBinarySnapshot(info, builder, member)
}
// Organize the variants by architecture.
func (mt *binarySdkMemberType) organizeVariants(member android.SdkMember) *nativeBinaryInfo {
memberName := member.Name()
info := &nativeBinaryInfo{
name: memberName,
memberType: mt,
}
for _, variant := range member.Variants() {
ccModule := variant.(*Module)
info.archVariantProperties = append(info.archVariantProperties, nativeBinaryInfoProperties{
name: memberName,
archType: ccModule.Target().Arch.ArchType.String(),
outputFile: ccModule.OutputFile().Path(),
})
}
// Initialize the unexported properties that will not be set during the
// extraction process.
info.commonProperties.name = memberName
// Extract common properties from the arch specific properties.
extractCommonProperties(&info.commonProperties, info.archVariantProperties)
return info
}
func buildSharedNativeBinarySnapshot(info *nativeBinaryInfo, builder android.SnapshotBuilder, member android.SdkMember) {
pbm := builder.AddPrebuiltModule(member, "cc_prebuilt_binary")
archVariantCount := len(info.archVariantProperties)
// Choose setting for compile_multilib that is appropriate for the arch variants supplied.
var multilib string
if archVariantCount == 2 {
multilib = "both"
} else if archVariantCount == 1 {
if strings.HasSuffix(info.archVariantProperties[0].archType, "64") {
multilib = "64"
} else {
multilib = "32"
}
}
if multilib != "" {
pbm.AddProperty("compile_multilib", multilib)
}
archProperties := pbm.AddPropertySet("arch")
for _, av := range info.archVariantProperties {
archTypeProperties := archProperties.AddPropertySet(av.archType)
archTypeProperties.AddProperty("srcs", []string{nativeBinaryPathFor(av)})
builder.CopyToSnapshot(av.outputFile, nativeBinaryPathFor(av))
}
}
const (
nativeBinaryDir = "bin"
)
// path to the native binary. Relative to <sdk_root>/<api_dir>
func nativeBinaryPathFor(lib nativeBinaryInfoProperties) string {
return filepath.Join(lib.archType,
nativeBinaryDir, lib.outputFile.Base())
}
// nativeBinaryInfoProperties represents properties of a native binary
//
// The exported (capitalized) fields will be examined and may be changed during common value extraction.
// The unexported fields will be left untouched.
type nativeBinaryInfoProperties struct {
// The name of the library, is not exported as this must not be changed during optimization.
name string
// archType is not exported as if set (to a non default value) it is always arch specific.
// This is "" for common properties.
archType string
// outputFile is not exported as it is always arch specific.
outputFile android.Path
}
// nativeBinaryInfo represents a collection of arch-specific modules having the same name
type nativeBinaryInfo struct {
name string
memberType *binarySdkMemberType
archVariantProperties []nativeBinaryInfoProperties
commonProperties nativeBinaryInfoProperties
}