From 25ce04bd3a076cf773edc6771f3baba11bb5c8f7 Mon Sep 17 00:00:00 2001 From: Paul Duffin Date: Thu, 16 Jan 2020 11:47:25 +0000 Subject: [PATCH] Add support for cc_binary in module_exports Bug: 142920869 Test: m nothing Change-Id: Ib7e16cb323806782c2186e73e13642e4485fc149 --- Android.bp | 1 + cc/binary.go | 5 ++ cc/binary_sdk_member.go | 143 ++++++++++++++++++++++++++++++++++++++++ sdk/cc_sdk_test.go | 62 +++++++++++++++++ 4 files changed, 211 insertions(+) create mode 100644 cc/binary_sdk_member.go diff --git a/Android.bp b/Android.bp index f425c3f3f..2a4653a13 100644 --- a/Android.bp +++ b/Android.bp @@ -204,6 +204,7 @@ bootstrap_go_package { "cc/linker.go", "cc/binary.go", + "cc/binary_sdk_member.go", "cc/fuzz.go", "cc/library.go", "cc/library_sdk_member.go", diff --git a/cc/binary.go b/cc/binary.go index 280d17bfb..661264eef 100644 --- a/cc/binary.go +++ b/cc/binary.go @@ -200,6 +200,11 @@ func NewBinary(hod android.HostOrDeviceSupported) (*Module, *binaryDecorator) { module.compiler = NewBaseCompiler() module.linker = binary module.installer = binary + + // Allow module to be added as member of an sdk/module_exports. + module.sdkMemberTypes = []android.SdkMemberType{ + ccBinarySdkMemberType, + } return module, binary } diff --git a/cc/binary_sdk_member.go b/cc/binary_sdk_member.go new file mode 100644 index 000000000..53bc065f9 --- /dev/null +++ b/cc/binary_sdk_member.go @@ -0,0 +1,143 @@ +// 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" + + "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") + pbm.AddProperty("compile_multilib", "both") + 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 / +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 +} diff --git a/sdk/cc_sdk_test.go b/sdk/cc_sdk_test.go index 9a75610f6..8c32d8cad 100644 --- a/sdk/cc_sdk_test.go +++ b/sdk/cc_sdk_test.go @@ -337,6 +337,68 @@ arm64/include/Arm64Test.h -> arm64/include/arm64/include/Arm64Test.h ) } +func TestSnapshotWithCcBinary(t *testing.T) { + result := testSdkWithCc(t, ` + module_exports { + name: "mymodule_exports", + native_binaries: ["mynativebinary"], + } + + cc_binary { + name: "mynativebinary", + srcs: [ + "Test.cpp", + ], + compile_multilib: "both", + system_shared_libs: [], + stl: "none", + } + `) + + result.CheckSnapshot("mymodule_exports", "android_common", "", + checkAndroidBpContents(` +// This is auto-generated. DO NOT EDIT. + +cc_prebuilt_binary { + name: "mymodule_exports_mynativebinary@current", + sdk_member_name: "mynativebinary", + compile_multilib: "both", + arch: { + arm64: { + srcs: ["arm64/bin/mynativebinary"], + }, + arm: { + srcs: ["arm/bin/mynativebinary"], + }, + }, +} + +cc_prebuilt_binary { + name: "mynativebinary", + prefer: false, + compile_multilib: "both", + arch: { + arm64: { + srcs: ["arm64/bin/mynativebinary"], + }, + arm: { + srcs: ["arm/bin/mynativebinary"], + }, + }, +} + +module_exports_snapshot { + name: "mymodule_exports@current", + native_binaries: ["mymodule_exports_mynativebinary@current"], +} +`), + checkAllCopyRules(` +.intermediates/mynativebinary/android_arm64_armv8-a/mynativebinary -> arm64/bin/mynativebinary +.intermediates/mynativebinary/android_arm_armv7-a-neon/mynativebinary -> arm/bin/mynativebinary +`), + ) +} + func TestSnapshotWithCcSharedLibrary(t *testing.T) { result := testSdkWithCc(t, ` sdk {