2019-12-13 11:40:56 +01:00
|
|
|
// Copyright 2019 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"
|
Add SDK member support for cc_object.
Test: m nothing
Test: Add
sdk {
name: "runtime-module-sdk",
native_shared_libs: [
"libc",
"libdl",
"libm",
"ld-android",
],
native_objects: [
"crtbegin_dynamic",
"crtbegin_static",
"crtend_android",
],
}
to bionic/apex/Android.bp. Then:
build/soong/scripts/build-aml-prebuilts.sh runtime-module-sdk
Take the generated runtime-module-sdk-current.zip and unzip into a
master-art tree without bionic/, edit the generated Android.bp to
extend cc_prebuilt_* modules with:
nocrt: true,
stl: "none",
system_shared_libs: [],
apex_available: ["//apex_available:anyapex"],
recovery_available: true,
vendor_available: true,
ramdisk_available: true,
Then "m com.android.art.debug". This passes Soong but fails in the
build step because more members are required.
Bug: 148934017
Change-Id: I2ab8f6aadb1440b325697cae4a8ed761c62d15d2
2020-03-10 23:37:59 +01:00
|
|
|
|
2019-12-13 11:40:56 +01:00
|
|
|
"github.com/google/blueprint"
|
2020-03-06 13:30:43 +01:00
|
|
|
"github.com/google/blueprint/proptools"
|
2019-12-13 11:40:56 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// This file contains support for using cc library modules within an sdk.
|
|
|
|
|
2019-12-13 20:50:38 +01:00
|
|
|
var sharedLibrarySdkMemberType = &librarySdkMemberType{
|
|
|
|
SdkMemberTypeBase: android.SdkMemberTypeBase{
|
2022-05-13 02:40:00 +02:00
|
|
|
PropertyName: "native_shared_libs",
|
|
|
|
SupportsSdk: true,
|
|
|
|
HostOsDependent: true,
|
|
|
|
SupportedLinkageNames: []string{"shared"},
|
2019-12-13 20:50:38 +01:00
|
|
|
},
|
|
|
|
prebuiltModuleType: "cc_prebuilt_library_shared",
|
|
|
|
}
|
|
|
|
|
|
|
|
var staticLibrarySdkMemberType = &librarySdkMemberType{
|
|
|
|
SdkMemberTypeBase: android.SdkMemberTypeBase{
|
2022-05-13 02:40:00 +02:00
|
|
|
PropertyName: "native_static_libs",
|
|
|
|
SupportsSdk: true,
|
|
|
|
HostOsDependent: true,
|
|
|
|
SupportedLinkageNames: []string{"static"},
|
2019-12-13 20:50:38 +01:00
|
|
|
},
|
|
|
|
prebuiltModuleType: "cc_prebuilt_library_static",
|
|
|
|
}
|
|
|
|
|
2020-03-12 11:24:35 +01:00
|
|
|
var staticAndSharedLibrarySdkMemberType = &librarySdkMemberType{
|
|
|
|
SdkMemberTypeBase: android.SdkMemberTypeBase{
|
2022-05-13 02:40:00 +02:00
|
|
|
PropertyName: "native_libs",
|
|
|
|
OverridesPropertyNames: map[string]bool{"native_shared_libs": true, "native_static_libs": true},
|
|
|
|
SupportsSdk: true,
|
|
|
|
HostOsDependent: true,
|
|
|
|
SupportedLinkageNames: []string{"static", "shared"},
|
2020-03-12 11:24:35 +01:00
|
|
|
},
|
|
|
|
prebuiltModuleType: "cc_prebuilt_library",
|
|
|
|
}
|
|
|
|
|
2019-12-13 12:22:16 +01:00
|
|
|
func init() {
|
|
|
|
// Register sdk member types.
|
2019-12-13 20:50:38 +01:00
|
|
|
android.RegisterSdkMemberType(sharedLibrarySdkMemberType)
|
|
|
|
android.RegisterSdkMemberType(staticLibrarySdkMemberType)
|
2020-03-12 11:24:35 +01:00
|
|
|
android.RegisterSdkMemberType(staticAndSharedLibrarySdkMemberType)
|
2019-12-13 11:40:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type librarySdkMemberType struct {
|
2019-12-13 12:22:16 +01:00
|
|
|
android.SdkMemberTypeBase
|
|
|
|
|
2019-12-13 11:40:56 +01:00
|
|
|
prebuiltModuleType string
|
|
|
|
|
Add SDK member support for cc_object.
Test: m nothing
Test: Add
sdk {
name: "runtime-module-sdk",
native_shared_libs: [
"libc",
"libdl",
"libm",
"ld-android",
],
native_objects: [
"crtbegin_dynamic",
"crtbegin_static",
"crtend_android",
],
}
to bionic/apex/Android.bp. Then:
build/soong/scripts/build-aml-prebuilts.sh runtime-module-sdk
Take the generated runtime-module-sdk-current.zip and unzip into a
master-art tree without bionic/, edit the generated Android.bp to
extend cc_prebuilt_* modules with:
nocrt: true,
stl: "none",
system_shared_libs: [],
apex_available: ["//apex_available:anyapex"],
recovery_available: true,
vendor_available: true,
ramdisk_available: true,
Then "m com.android.art.debug". This passes Soong but fails in the
build step because more members are required.
Bug: 148934017
Change-Id: I2ab8f6aadb1440b325697cae4a8ed761c62d15d2
2020-03-10 23:37:59 +01:00
|
|
|
noOutputFiles bool // True if there are no srcs files.
|
|
|
|
|
2019-12-13 11:40:56 +01:00
|
|
|
}
|
|
|
|
|
2021-07-14 11:29:36 +02:00
|
|
|
func (mt *librarySdkMemberType) AddDependencies(ctx android.SdkDependencyContext, dependencyTag blueprint.DependencyTag, names []string) {
|
2019-11-19 20:44:10 +01:00
|
|
|
// The base set of targets which does not include native bridge targets.
|
|
|
|
defaultTargets := ctx.MultiTargets()
|
|
|
|
|
|
|
|
// The lazily created list of native bridge targets.
|
|
|
|
var includeNativeBridgeTargets []android.Target
|
|
|
|
|
2019-12-13 11:40:56 +01:00
|
|
|
for _, lib := range names {
|
2019-11-19 20:44:10 +01:00
|
|
|
targets := defaultTargets
|
|
|
|
|
|
|
|
// If native bridge support is required in the sdk snapshot then add native bridge targets to
|
|
|
|
// the basic list of targets that are required.
|
|
|
|
nativeBridgeSupport := ctx.RequiresTrait(lib, nativeBridgeSdkTrait)
|
|
|
|
if nativeBridgeSupport && ctx.Device() {
|
|
|
|
// If not already computed then compute the list of native bridge targets.
|
|
|
|
if includeNativeBridgeTargets == nil {
|
|
|
|
includeNativeBridgeTargets = append([]android.Target{}, defaultTargets...)
|
|
|
|
allAndroidTargets := ctx.Config().Targets[android.Android]
|
|
|
|
for _, possibleNativeBridgeTarget := range allAndroidTargets {
|
|
|
|
if possibleNativeBridgeTarget.NativeBridge == android.NativeBridgeEnabled {
|
|
|
|
includeNativeBridgeTargets = append(includeNativeBridgeTargets, possibleNativeBridgeTarget)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Include the native bridge targets as well.
|
|
|
|
targets = includeNativeBridgeTargets
|
|
|
|
}
|
2021-09-09 18:06:07 +02:00
|
|
|
|
|
|
|
// memberDependency encapsulates information about the dependencies to add for this member.
|
|
|
|
type memberDependency struct {
|
|
|
|
// The targets to depend upon.
|
|
|
|
targets []android.Target
|
|
|
|
|
|
|
|
// Additional image variations to depend upon, is either nil for no image variation or
|
|
|
|
// contains a single image variation.
|
|
|
|
imageVariations []blueprint.Variation
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extract the name and version from the module name.
|
|
|
|
name, version := StubsLibNameAndVersion(lib)
|
|
|
|
if version == "" {
|
|
|
|
version = "latest"
|
|
|
|
}
|
|
|
|
|
|
|
|
// Compute the set of dependencies to add.
|
|
|
|
var memberDependencies []memberDependency
|
|
|
|
if ctx.Host() {
|
|
|
|
// Host does not support image variations so add a dependency without any.
|
|
|
|
memberDependencies = append(memberDependencies, memberDependency{
|
|
|
|
targets: targets,
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
// Otherwise, this is targeting the device so add a dependency on the core image variation
|
|
|
|
// (image:"").
|
|
|
|
memberDependencies = append(memberDependencies, memberDependency{
|
|
|
|
imageVariations: []blueprint.Variation{{Mutator: "image", Variation: android.CoreVariation}},
|
|
|
|
targets: targets,
|
|
|
|
})
|
2021-09-06 11:28:34 +02:00
|
|
|
|
2021-09-15 18:25:10 +02:00
|
|
|
// If required add additional dependencies on the image:ramdisk variants.
|
|
|
|
if ctx.RequiresTrait(lib, ramdiskImageRequiredSdkTrait) {
|
|
|
|
memberDependencies = append(memberDependencies, memberDependency{
|
|
|
|
imageVariations: []blueprint.Variation{{Mutator: "image", Variation: android.RamdiskVariation}},
|
|
|
|
// Only add a dependency on the first target as that is the only one which will have an
|
|
|
|
// image:ramdisk variant.
|
|
|
|
targets: targets[:1],
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-09-06 11:28:34 +02:00
|
|
|
// If required add additional dependencies on the image:recovery variants.
|
|
|
|
if ctx.RequiresTrait(lib, recoveryImageRequiredSdkTrait) {
|
|
|
|
memberDependencies = append(memberDependencies, memberDependency{
|
|
|
|
imageVariations: []blueprint.Variation{{Mutator: "image", Variation: android.RecoveryVariation}},
|
|
|
|
// Only add a dependency on the first target as that is the only one which will have an
|
|
|
|
// image:recovery variant.
|
|
|
|
targets: targets[:1],
|
|
|
|
})
|
|
|
|
}
|
2021-09-09 18:06:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// For each dependency in the list add dependencies on the targets with the correct variations.
|
|
|
|
for _, dependency := range memberDependencies {
|
|
|
|
// For each target add a dependency on the target with any additional dependencies.
|
|
|
|
for _, target := range dependency.targets {
|
|
|
|
// Get the variations for the target.
|
|
|
|
variations := target.Variations()
|
|
|
|
|
|
|
|
// Add any additional dependencies needed.
|
|
|
|
variations = append(variations, dependency.imageVariations...)
|
|
|
|
|
2022-05-13 02:40:00 +02:00
|
|
|
if mt.SupportedLinkageNames == nil {
|
2021-09-09 18:06:07 +02:00
|
|
|
// No link types are supported so add a dependency directly.
|
|
|
|
ctx.AddFarVariationDependencies(variations, dependencyTag, name)
|
|
|
|
} else {
|
|
|
|
// Otherwise, add a dependency on each supported link type in turn.
|
2022-05-13 02:40:00 +02:00
|
|
|
for _, linkType := range mt.SupportedLinkageNames {
|
2021-09-09 18:06:07 +02:00
|
|
|
libVariations := append(variations,
|
|
|
|
blueprint.Variation{Mutator: "link", Variation: linkType})
|
|
|
|
// If this is for the device and a shared link type then add a dependency onto the
|
|
|
|
// appropriate version specific variant of the module.
|
|
|
|
if ctx.Device() && linkType == "shared" {
|
|
|
|
libVariations = append(libVariations,
|
|
|
|
blueprint.Variation{Mutator: "version", Variation: version})
|
|
|
|
}
|
|
|
|
ctx.AddFarVariationDependencies(libVariations, dependencyTag, name)
|
2020-10-23 23:53:06 +02:00
|
|
|
}
|
2020-02-21 17:29:57 +01:00
|
|
|
}
|
2019-12-13 11:40:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mt *librarySdkMemberType) IsInstance(module android.Module) bool {
|
2019-12-13 20:50:38 +01:00
|
|
|
// 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
|
2019-12-13 11:40:56 +01:00
|
|
|
}
|
|
|
|
|
2020-03-19 17:11:18 +01:00
|
|
|
func (mt *librarySdkMemberType) AddPrebuiltModule(ctx android.SdkMemberContext, member android.SdkMember) android.BpModule {
|
|
|
|
pbm := ctx.SnapshotBuilder().AddPrebuiltModule(member, mt.prebuiltModuleType)
|
2020-03-05 15:09:58 +01:00
|
|
|
|
|
|
|
ccModule := member.Variants()[0].(*Module)
|
|
|
|
|
2019-11-19 20:44:10 +01:00
|
|
|
if ctx.RequiresTrait(nativeBridgeSdkTrait) {
|
|
|
|
pbm.AddProperty("native_bridge_supported", true)
|
|
|
|
}
|
|
|
|
|
2021-09-15 18:25:10 +02:00
|
|
|
if ctx.RequiresTrait(ramdiskImageRequiredSdkTrait) {
|
|
|
|
pbm.AddProperty("ramdisk_available", true)
|
|
|
|
}
|
|
|
|
|
2021-09-06 11:28:34 +02:00
|
|
|
if ctx.RequiresTrait(recoveryImageRequiredSdkTrait) {
|
2020-09-07 17:39:22 +02:00
|
|
|
pbm.AddProperty("recovery_available", true)
|
|
|
|
}
|
|
|
|
|
2020-08-13 20:45:31 +02:00
|
|
|
if proptools.Bool(ccModule.VendorProperties.Vendor_available) {
|
|
|
|
pbm.AddProperty("vendor_available", true)
|
|
|
|
}
|
|
|
|
|
2021-01-08 10:00:19 +01:00
|
|
|
if proptools.Bool(ccModule.VendorProperties.Odm_available) {
|
|
|
|
pbm.AddProperty("odm_available", true)
|
|
|
|
}
|
|
|
|
|
2020-10-29 08:49:43 +01:00
|
|
|
if proptools.Bool(ccModule.VendorProperties.Product_available) {
|
|
|
|
pbm.AddProperty("product_available", true)
|
|
|
|
}
|
|
|
|
|
2020-03-05 15:09:58 +01:00
|
|
|
sdkVersion := ccModule.SdkVersion()
|
|
|
|
if sdkVersion != "" {
|
|
|
|
pbm.AddProperty("sdk_version", sdkVersion)
|
|
|
|
}
|
2019-12-13 11:40:56 +01:00
|
|
|
|
2020-03-06 13:30:43 +01:00
|
|
|
stl := ccModule.stl.Properties.Stl
|
|
|
|
if stl != nil {
|
2020-03-11 19:42:08 +01:00
|
|
|
pbm.AddProperty("stl", proptools.String(stl))
|
2020-03-06 13:30:43 +01:00
|
|
|
}
|
2020-06-17 23:52:25 +02:00
|
|
|
|
|
|
|
if lib, ok := ccModule.linker.(*libraryDecorator); ok {
|
|
|
|
uhs := lib.Properties.Unique_host_soname
|
|
|
|
if uhs != nil {
|
|
|
|
pbm.AddProperty("unique_host_soname", proptools.Bool(uhs))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-11 19:42:08 +01:00
|
|
|
return pbm
|
2020-02-27 17:00:53 +01:00
|
|
|
}
|
2019-12-13 11:40:56 +01:00
|
|
|
|
2020-02-27 17:00:53 +01:00
|
|
|
func (mt *librarySdkMemberType) CreateVariantPropertiesStruct() android.SdkMemberProperties {
|
|
|
|
return &nativeLibInfoProperties{memberType: mt}
|
2019-12-13 11:40:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func isGeneratedHeaderDirectory(p android.Path) bool {
|
|
|
|
_, gen := p.(android.WritablePath)
|
2023-12-07 22:10:56 +01:00
|
|
|
return gen
|
2019-12-13 11:40:56 +01:00
|
|
|
}
|
|
|
|
|
2020-02-20 15:33:54 +01:00
|
|
|
type includeDirsProperty struct {
|
|
|
|
// Accessor to retrieve the paths
|
2020-02-27 17:00:53 +01:00
|
|
|
pathsGetter func(libInfo *nativeLibInfoProperties) android.Paths
|
2020-02-20 15:33:54 +01:00
|
|
|
|
|
|
|
// The name of the property in the prebuilt library, "" means there is no property.
|
|
|
|
propertyName string
|
|
|
|
|
|
|
|
// The directory within the snapshot directory into which items should be copied.
|
|
|
|
snapshotDir string
|
|
|
|
|
|
|
|
// True if the items on the path should be copied.
|
|
|
|
copy bool
|
|
|
|
|
|
|
|
// True if the paths represent directories, files if they represent files.
|
|
|
|
dirs bool
|
2020-01-23 12:45:03 +01:00
|
|
|
}
|
|
|
|
|
2020-02-20 15:33:54 +01:00
|
|
|
var includeDirProperties = []includeDirsProperty{
|
|
|
|
{
|
|
|
|
// ExportedIncludeDirs lists directories that contains some header files to be
|
|
|
|
// copied into a directory in the snapshot. The snapshot directories must be added to
|
|
|
|
// the export_include_dirs property in the prebuilt module in the snapshot.
|
2020-02-27 17:00:53 +01:00
|
|
|
pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.ExportedIncludeDirs },
|
2020-02-20 15:33:54 +01:00
|
|
|
propertyName: "export_include_dirs",
|
|
|
|
snapshotDir: nativeIncludeDir,
|
|
|
|
copy: true,
|
|
|
|
dirs: true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// ExportedSystemIncludeDirs lists directories that contains some system header files to
|
|
|
|
// be copied into a directory in the snapshot. The snapshot directories must be added to
|
|
|
|
// the export_system_include_dirs property in the prebuilt module in the snapshot.
|
2020-02-27 17:00:53 +01:00
|
|
|
pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.ExportedSystemIncludeDirs },
|
2020-02-20 15:33:54 +01:00
|
|
|
propertyName: "export_system_include_dirs",
|
|
|
|
snapshotDir: nativeIncludeDir,
|
|
|
|
copy: true,
|
|
|
|
dirs: true,
|
|
|
|
},
|
|
|
|
{
|
2021-02-17 13:17:40 +01:00
|
|
|
// ExportedGeneratedIncludeDirs lists directories that contains some header files
|
|
|
|
// that are explicitly listed in the ExportedGeneratedHeaders property. So, the contents
|
2020-02-20 15:33:54 +01:00
|
|
|
// of these directories do not need to be copied, but these directories do need adding to
|
|
|
|
// the export_include_dirs property in the prebuilt module in the snapshot.
|
2021-02-17 13:17:40 +01:00
|
|
|
pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.ExportedGeneratedIncludeDirs },
|
2020-02-20 15:33:54 +01:00
|
|
|
propertyName: "export_include_dirs",
|
|
|
|
snapshotDir: nativeGeneratedIncludeDir,
|
|
|
|
copy: false,
|
|
|
|
dirs: true,
|
|
|
|
},
|
|
|
|
{
|
2021-02-17 13:17:40 +01:00
|
|
|
// ExportedGeneratedHeaders lists header files that are in one of the directories
|
|
|
|
// specified in ExportedGeneratedIncludeDirs must be copied into the snapshot.
|
|
|
|
// As they are in a directory in ExportedGeneratedIncludeDirs they do not need adding to a
|
2020-02-20 15:33:54 +01:00
|
|
|
// property in the prebuilt module in the snapshot.
|
2021-02-17 13:17:40 +01:00
|
|
|
pathsGetter: func(libInfo *nativeLibInfoProperties) android.Paths { return libInfo.ExportedGeneratedHeaders },
|
2020-02-20 15:33:54 +01:00
|
|
|
propertyName: "",
|
|
|
|
snapshotDir: nativeGeneratedIncludeDir,
|
|
|
|
copy: true,
|
|
|
|
dirs: false,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add properties that may, or may not, be arch specific.
|
2020-02-27 17:00:53 +01:00
|
|
|
func addPossiblyArchSpecificProperties(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, libInfo *nativeLibInfoProperties, outputProperties android.BpPropertySet) {
|
|
|
|
|
2020-09-15 03:32:35 +02:00
|
|
|
outputProperties.AddProperty("sanitize", &libInfo.Sanitize)
|
2020-08-21 19:43:51 +02:00
|
|
|
|
2020-02-27 17:00:53 +01:00
|
|
|
// Copy the generated library to the snapshot and add a reference to it in the .bp module.
|
|
|
|
if libInfo.outputFile != nil {
|
|
|
|
nativeLibraryPath := nativeLibraryPathFor(libInfo)
|
|
|
|
builder.CopyToSnapshot(libInfo.outputFile, nativeLibraryPath)
|
|
|
|
outputProperties.AddProperty("srcs", []string{nativeLibraryPath})
|
|
|
|
}
|
2020-02-20 15:33:54 +01:00
|
|
|
|
2020-03-06 13:30:43 +01:00
|
|
|
if len(libInfo.SharedLibs) > 0 {
|
|
|
|
outputProperties.AddPropertyWithTag("shared_libs", libInfo.SharedLibs, builder.SdkMemberReferencePropertyTag(false))
|
|
|
|
}
|
|
|
|
|
2020-03-24 02:19:52 +01:00
|
|
|
// SystemSharedLibs needs to be propagated if it's a list, even if it's empty,
|
|
|
|
// so check for non-nil instead of nonzero length.
|
|
|
|
if libInfo.SystemSharedLibs != nil {
|
2020-03-06 13:30:43 +01:00
|
|
|
outputProperties.AddPropertyWithTag("system_shared_libs", libInfo.SystemSharedLibs, builder.SdkMemberReferencePropertyTag(false))
|
|
|
|
}
|
|
|
|
|
2020-02-20 15:33:54 +01:00
|
|
|
// Map from property name to the include dirs to add to the prebuilt module in the snapshot.
|
|
|
|
includeDirs := make(map[string][]string)
|
|
|
|
|
|
|
|
// Iterate over each include directory property, copying files and collating property
|
|
|
|
// values where necessary.
|
|
|
|
for _, propertyInfo := range includeDirProperties {
|
|
|
|
// Calculate the base directory in the snapshot into which the files will be copied.
|
2021-09-03 18:53:38 +02:00
|
|
|
// lib.archSubDir is "" for common properties.
|
|
|
|
targetDir := filepath.Join(libInfo.OsPrefix(), libInfo.archSubDir, propertyInfo.snapshotDir)
|
2020-02-20 15:33:54 +01:00
|
|
|
|
|
|
|
propertyName := propertyInfo.propertyName
|
|
|
|
|
|
|
|
// Iterate over each path in one of the include directory properties.
|
|
|
|
for _, path := range propertyInfo.pathsGetter(libInfo) {
|
Fix the snapshot handling of generated headers
Previously, the snapshot handling code did not preserve the directory
structure of generated include directories and instead just copied the
headers into the same module specific directory and added that single
directory to the export_include_dirs (or similar) property.
That had a couple of issues:
* The include directory was repeated in the ..._include_dirs property.
* It did not work when the include directories overlapped.
In the latter case it had a couple of issues:
* Code which compiled fine against the source would not compile against
the prebuilt.
* Header files were duplicated in the output.
e.g. assume the following generated header file structure:
foo/
foo.h
bar/
bar.h
baz/
baz.h
When the sdk snapshot was passed include directories of "foo", "bar" and
headers of "foo/foo.h", "bar/bar.h", "bar/baz/baz.h" it would generate a
snapshot with the structure:
include_gen/
foo.h
bar.h
baz/
baz.h
And:
export_include_dirs: ["include_gen", "include_gen"]
However, when the include directories overlapped and include directories
of "foo", "bar" and "bar/baz" were passed in the directory structure
would be the same and the export_include_dirs would contain 3 usages of
"include_gen".
That meant that source code which used the following would build
against the source (because it would find "baz.h" in the "bar/baz"
include directory) but would fail when built against the prebuilts
because the "include_gen" directory did not contain "baz.h":
#include "baz.h"
This change preserves the input directory structure for generated files
in a similar way to how it does it for source files. So, the snapshot
structure looks something like this:
include_gen/
foo/
foo.h
bar/
bar.h
baz/
baz.h
And:
export_include_dirs: [
"include_gen/foo",
"include_gen/bar",
"include_gen/bar/baz",
],
Bug: 180427921
Test: m nothing
Change-Id: Id69eef8cf5eecd033841d3b7cd0c044a697ce404
2021-02-22 12:35:24 +01:00
|
|
|
inputPath := path.String()
|
|
|
|
|
|
|
|
// Map the input path to a snapshot relative path. The mapping is independent of the module
|
|
|
|
// that references them so that if multiple modules within the same snapshot export the same
|
|
|
|
// header files they end up in the same place in the snapshot and so do not get duplicated.
|
|
|
|
targetRelativePath := inputPath
|
|
|
|
if isGeneratedHeaderDirectory(path) {
|
|
|
|
// Remove everything up to the .intermediates/ from the generated output directory to
|
|
|
|
// leave a module relative path.
|
|
|
|
base := android.PathForIntermediates(sdkModuleContext, "")
|
|
|
|
targetRelativePath = android.Rel(sdkModuleContext, base.String(), inputPath)
|
|
|
|
}
|
|
|
|
|
|
|
|
snapshotRelativePath := filepath.Join(targetDir, targetRelativePath)
|
2020-02-20 15:33:54 +01:00
|
|
|
|
|
|
|
// Copy the files/directories when necessary.
|
|
|
|
if propertyInfo.copy {
|
|
|
|
if propertyInfo.dirs {
|
|
|
|
// When copying a directory glob and copy all the headers within it.
|
|
|
|
// TODO(jiyong) copy headers having other suffixes
|
Fix the snapshot handling of generated headers
Previously, the snapshot handling code did not preserve the directory
structure of generated include directories and instead just copied the
headers into the same module specific directory and added that single
directory to the export_include_dirs (or similar) property.
That had a couple of issues:
* The include directory was repeated in the ..._include_dirs property.
* It did not work when the include directories overlapped.
In the latter case it had a couple of issues:
* Code which compiled fine against the source would not compile against
the prebuilt.
* Header files were duplicated in the output.
e.g. assume the following generated header file structure:
foo/
foo.h
bar/
bar.h
baz/
baz.h
When the sdk snapshot was passed include directories of "foo", "bar" and
headers of "foo/foo.h", "bar/bar.h", "bar/baz/baz.h" it would generate a
snapshot with the structure:
include_gen/
foo.h
bar.h
baz/
baz.h
And:
export_include_dirs: ["include_gen", "include_gen"]
However, when the include directories overlapped and include directories
of "foo", "bar" and "bar/baz" were passed in the directory structure
would be the same and the export_include_dirs would contain 3 usages of
"include_gen".
That meant that source code which used the following would build
against the source (because it would find "baz.h" in the "bar/baz"
include directory) but would fail when built against the prebuilts
because the "include_gen" directory did not contain "baz.h":
#include "baz.h"
This change preserves the input directory structure for generated files
in a similar way to how it does it for source files. So, the snapshot
structure looks something like this:
include_gen/
foo/
foo.h
bar/
bar.h
baz/
baz.h
And:
export_include_dirs: [
"include_gen/foo",
"include_gen/bar",
"include_gen/bar/baz",
],
Bug: 180427921
Test: m nothing
Change-Id: Id69eef8cf5eecd033841d3b7cd0c044a697ce404
2021-02-22 12:35:24 +01:00
|
|
|
headers, _ := sdkModuleContext.GlobWithDeps(inputPath+"/**/*.h", nil)
|
2020-02-20 15:33:54 +01:00
|
|
|
for _, file := range headers {
|
|
|
|
src := android.PathForSource(sdkModuleContext, file)
|
Fix the snapshot handling of generated headers
Previously, the snapshot handling code did not preserve the directory
structure of generated include directories and instead just copied the
headers into the same module specific directory and added that single
directory to the export_include_dirs (or similar) property.
That had a couple of issues:
* The include directory was repeated in the ..._include_dirs property.
* It did not work when the include directories overlapped.
In the latter case it had a couple of issues:
* Code which compiled fine against the source would not compile against
the prebuilt.
* Header files were duplicated in the output.
e.g. assume the following generated header file structure:
foo/
foo.h
bar/
bar.h
baz/
baz.h
When the sdk snapshot was passed include directories of "foo", "bar" and
headers of "foo/foo.h", "bar/bar.h", "bar/baz/baz.h" it would generate a
snapshot with the structure:
include_gen/
foo.h
bar.h
baz/
baz.h
And:
export_include_dirs: ["include_gen", "include_gen"]
However, when the include directories overlapped and include directories
of "foo", "bar" and "bar/baz" were passed in the directory structure
would be the same and the export_include_dirs would contain 3 usages of
"include_gen".
That meant that source code which used the following would build
against the source (because it would find "baz.h" in the "bar/baz"
include directory) but would fail when built against the prebuilts
because the "include_gen" directory did not contain "baz.h":
#include "baz.h"
This change preserves the input directory structure for generated files
in a similar way to how it does it for source files. So, the snapshot
structure looks something like this:
include_gen/
foo/
foo.h
bar/
bar.h
baz/
baz.h
And:
export_include_dirs: [
"include_gen/foo",
"include_gen/bar",
"include_gen/bar/baz",
],
Bug: 180427921
Test: m nothing
Change-Id: Id69eef8cf5eecd033841d3b7cd0c044a697ce404
2021-02-22 12:35:24 +01:00
|
|
|
|
|
|
|
// The destination path in the snapshot is constructed from the snapshot relative path
|
|
|
|
// of the input directory and the input directory relative path of the header file.
|
|
|
|
inputRelativePath := android.Rel(sdkModuleContext, inputPath, file)
|
|
|
|
dest := filepath.Join(snapshotRelativePath, inputRelativePath)
|
2020-02-20 15:33:54 +01:00
|
|
|
builder.CopyToSnapshot(src, dest)
|
|
|
|
}
|
|
|
|
} else {
|
Fix the snapshot handling of generated headers
Previously, the snapshot handling code did not preserve the directory
structure of generated include directories and instead just copied the
headers into the same module specific directory and added that single
directory to the export_include_dirs (or similar) property.
That had a couple of issues:
* The include directory was repeated in the ..._include_dirs property.
* It did not work when the include directories overlapped.
In the latter case it had a couple of issues:
* Code which compiled fine against the source would not compile against
the prebuilt.
* Header files were duplicated in the output.
e.g. assume the following generated header file structure:
foo/
foo.h
bar/
bar.h
baz/
baz.h
When the sdk snapshot was passed include directories of "foo", "bar" and
headers of "foo/foo.h", "bar/bar.h", "bar/baz/baz.h" it would generate a
snapshot with the structure:
include_gen/
foo.h
bar.h
baz/
baz.h
And:
export_include_dirs: ["include_gen", "include_gen"]
However, when the include directories overlapped and include directories
of "foo", "bar" and "bar/baz" were passed in the directory structure
would be the same and the export_include_dirs would contain 3 usages of
"include_gen".
That meant that source code which used the following would build
against the source (because it would find "baz.h" in the "bar/baz"
include directory) but would fail when built against the prebuilts
because the "include_gen" directory did not contain "baz.h":
#include "baz.h"
This change preserves the input directory structure for generated files
in a similar way to how it does it for source files. So, the snapshot
structure looks something like this:
include_gen/
foo/
foo.h
bar/
bar.h
baz/
baz.h
And:
export_include_dirs: [
"include_gen/foo",
"include_gen/bar",
"include_gen/bar/baz",
],
Bug: 180427921
Test: m nothing
Change-Id: Id69eef8cf5eecd033841d3b7cd0c044a697ce404
2021-02-22 12:35:24 +01:00
|
|
|
// Otherwise, just copy the file to its snapshot relative path.
|
|
|
|
builder.CopyToSnapshot(path, snapshotRelativePath)
|
2020-02-20 15:33:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only directories are added to a property.
|
|
|
|
if propertyInfo.dirs {
|
Fix the snapshot handling of generated headers
Previously, the snapshot handling code did not preserve the directory
structure of generated include directories and instead just copied the
headers into the same module specific directory and added that single
directory to the export_include_dirs (or similar) property.
That had a couple of issues:
* The include directory was repeated in the ..._include_dirs property.
* It did not work when the include directories overlapped.
In the latter case it had a couple of issues:
* Code which compiled fine against the source would not compile against
the prebuilt.
* Header files were duplicated in the output.
e.g. assume the following generated header file structure:
foo/
foo.h
bar/
bar.h
baz/
baz.h
When the sdk snapshot was passed include directories of "foo", "bar" and
headers of "foo/foo.h", "bar/bar.h", "bar/baz/baz.h" it would generate a
snapshot with the structure:
include_gen/
foo.h
bar.h
baz/
baz.h
And:
export_include_dirs: ["include_gen", "include_gen"]
However, when the include directories overlapped and include directories
of "foo", "bar" and "bar/baz" were passed in the directory structure
would be the same and the export_include_dirs would contain 3 usages of
"include_gen".
That meant that source code which used the following would build
against the source (because it would find "baz.h" in the "bar/baz"
include directory) but would fail when built against the prebuilts
because the "include_gen" directory did not contain "baz.h":
#include "baz.h"
This change preserves the input directory structure for generated files
in a similar way to how it does it for source files. So, the snapshot
structure looks something like this:
include_gen/
foo/
foo.h
bar/
bar.h
baz/
baz.h
And:
export_include_dirs: [
"include_gen/foo",
"include_gen/bar",
"include_gen/bar/baz",
],
Bug: 180427921
Test: m nothing
Change-Id: Id69eef8cf5eecd033841d3b7cd0c044a697ce404
2021-02-22 12:35:24 +01:00
|
|
|
includeDirs[propertyName] = append(includeDirs[propertyName], snapshotRelativePath)
|
2020-02-20 15:33:54 +01:00
|
|
|
}
|
|
|
|
}
|
2020-01-23 12:45:03 +01:00
|
|
|
}
|
2020-02-20 15:33:54 +01:00
|
|
|
|
|
|
|
// Add the collated include dir properties to the output.
|
2023-03-01 01:02:16 +01:00
|
|
|
for _, property := range android.SortedKeys(includeDirs) {
|
2020-09-12 00:44:31 +02:00
|
|
|
outputProperties.AddProperty(property, includeDirs[property])
|
2020-01-23 12:45:03 +01:00
|
|
|
}
|
2020-04-01 21:38:01 +02:00
|
|
|
|
2020-09-24 17:53:04 +02:00
|
|
|
if len(libInfo.StubsVersions) > 0 {
|
2020-04-01 21:38:01 +02:00
|
|
|
stubsSet := outputProperties.AddPropertySet("stubs")
|
2020-09-24 17:53:04 +02:00
|
|
|
stubsSet.AddProperty("versions", libInfo.StubsVersions)
|
2020-04-01 21:38:01 +02:00
|
|
|
}
|
2020-01-23 12:45:03 +01:00
|
|
|
}
|
|
|
|
|
2019-12-13 11:40:56 +01:00
|
|
|
const (
|
|
|
|
nativeIncludeDir = "include"
|
|
|
|
nativeGeneratedIncludeDir = "include_gen"
|
|
|
|
nativeStubDir = "lib"
|
|
|
|
)
|
|
|
|
|
|
|
|
// path to the native library. Relative to <sdk_root>/<api_dir>
|
2020-02-27 17:00:53 +01:00
|
|
|
func nativeLibraryPathFor(lib *nativeLibInfoProperties) string {
|
2021-09-03 18:53:38 +02:00
|
|
|
return filepath.Join(lib.OsPrefix(), lib.archSubDir,
|
2019-12-13 11:40:56 +01:00
|
|
|
nativeStubDir, lib.outputFile.Base())
|
|
|
|
}
|
|
|
|
|
|
|
|
// nativeLibInfoProperties represents properties of a native lib
|
|
|
|
//
|
|
|
|
// The exported (capitalized) fields will be examined and may be changed during common value extraction.
|
|
|
|
// The unexported fields will be left untouched.
|
|
|
|
type nativeLibInfoProperties struct {
|
2020-02-27 17:00:53 +01:00
|
|
|
android.SdkMemberPropertiesBase
|
|
|
|
|
|
|
|
memberType *librarySdkMemberType
|
|
|
|
|
2021-09-03 18:53:38 +02:00
|
|
|
// archSubDir is the subdirectory within the OS directory in the sdk snapshot into which arch
|
|
|
|
// specific files will be copied.
|
|
|
|
//
|
|
|
|
// It is not exported since any value other than "" is always going to be arch specific.
|
|
|
|
// This is "" for non-arch specific common properties.
|
|
|
|
archSubDir string
|
2019-12-13 11:40:56 +01:00
|
|
|
|
2020-02-20 15:33:54 +01:00
|
|
|
// The list of possibly common exported include dirs.
|
|
|
|
//
|
|
|
|
// This field is exported as its contents may not be arch specific.
|
2020-05-06 11:23:19 +02:00
|
|
|
ExportedIncludeDirs android.Paths `android:"arch_variant"`
|
2019-12-13 11:40:56 +01:00
|
|
|
|
2020-02-20 15:33:54 +01:00
|
|
|
// The list of arch specific exported generated include dirs.
|
|
|
|
//
|
2021-02-17 13:17:40 +01:00
|
|
|
// This field is exported as its contents may not be arch specific, e.g. protos.
|
|
|
|
ExportedGeneratedIncludeDirs android.Paths `android:"arch_variant"`
|
2020-02-20 15:33:54 +01:00
|
|
|
|
|
|
|
// The list of arch specific exported generated header files.
|
|
|
|
//
|
2021-02-17 13:17:40 +01:00
|
|
|
// This field is exported as its contents may not be arch specific, e.g. protos.
|
|
|
|
ExportedGeneratedHeaders android.Paths `android:"arch_variant"`
|
2019-12-13 11:40:56 +01:00
|
|
|
|
2020-02-20 15:33:54 +01:00
|
|
|
// The list of possibly common exported system include dirs.
|
|
|
|
//
|
|
|
|
// This field is exported as its contents may not be arch specific.
|
2020-05-06 11:23:19 +02:00
|
|
|
ExportedSystemIncludeDirs android.Paths `android:"arch_variant"`
|
2020-02-20 15:33:54 +01:00
|
|
|
|
|
|
|
// The list of possibly common exported flags.
|
|
|
|
//
|
|
|
|
// This field is exported as its contents may not be arch specific.
|
2020-05-06 11:23:19 +02:00
|
|
|
ExportedFlags []string `android:"arch_variant"`
|
2020-02-20 15:33:54 +01:00
|
|
|
|
2020-03-06 13:30:43 +01:00
|
|
|
// The set of shared libraries
|
|
|
|
//
|
|
|
|
// This field is exported as its contents may not be arch specific.
|
2020-05-06 11:23:19 +02:00
|
|
|
SharedLibs []string `android:"arch_variant"`
|
2020-03-06 13:30:43 +01:00
|
|
|
|
2020-03-24 02:19:52 +01:00
|
|
|
// The set of system shared libraries. Note nil and [] are semantically
|
|
|
|
// distinct - see BaseLinkerProperties.System_shared_libs.
|
2020-03-06 13:30:43 +01:00
|
|
|
//
|
|
|
|
// This field is exported as its contents may not be arch specific.
|
2020-05-06 11:23:19 +02:00
|
|
|
SystemSharedLibs []string `android:"arch_variant"`
|
2020-03-06 13:30:43 +01:00
|
|
|
|
2020-04-01 21:38:01 +02:00
|
|
|
// The specific stubs version for the lib variant, or empty string if stubs
|
|
|
|
// are not in use.
|
2020-05-04 16:32:08 +02:00
|
|
|
//
|
2020-09-24 17:53:04 +02:00
|
|
|
// Marked 'ignored-on-host' as the AllStubsVersions() from which this is
|
|
|
|
// initialized is not set on host and the stubs.versions property which this
|
|
|
|
// is written to does not vary by arch so cannot be android specific.
|
|
|
|
StubsVersions []string `sdk:"ignored-on-host"`
|
2020-04-01 21:38:01 +02:00
|
|
|
|
2020-09-15 03:32:35 +02:00
|
|
|
// Value of SanitizeProperties.Sanitize. Several - but not all - of these
|
|
|
|
// affect the expanded variants. All are propagated to avoid entangling the
|
|
|
|
// sanitizer logic with the snapshot generation.
|
|
|
|
Sanitize SanitizeUserProps `android:"arch_variant"`
|
2020-08-21 19:43:51 +02:00
|
|
|
|
2019-12-13 11:40:56 +01:00
|
|
|
// outputFile is not exported as it is always arch specific.
|
|
|
|
outputFile android.Path
|
|
|
|
}
|
|
|
|
|
2020-03-19 17:11:18 +01:00
|
|
|
func (p *nativeLibInfoProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
|
2020-10-29 00:38:33 +01:00
|
|
|
addOutputFile := true
|
2020-02-27 17:00:53 +01:00
|
|
|
ccModule := variant.(*Module)
|
|
|
|
|
2020-10-29 00:38:33 +01:00
|
|
|
if s := ccModule.sanitize; s != nil {
|
|
|
|
// We currently do not capture sanitizer flags for libs with sanitizers
|
|
|
|
// enabled, because they may vary among variants that cannot be represented
|
|
|
|
// in the input blueprint files. In particular, sanitizerDepsMutator enables
|
|
|
|
// various sanitizers on dependencies, but in many cases only on static
|
|
|
|
// ones, and we cannot specify sanitizer flags at the link type level (i.e.
|
|
|
|
// in StaticOrSharedProperties).
|
|
|
|
if s.isUnsanitizedVariant() {
|
|
|
|
// This still captures explicitly disabled sanitizers, which may be
|
|
|
|
// necessary to avoid cyclic dependencies.
|
|
|
|
p.Sanitize = s.Properties.Sanitize
|
|
|
|
} else {
|
|
|
|
// Do not add the output file to the snapshot if we don't represent it
|
|
|
|
// properly.
|
|
|
|
addOutputFile = false
|
|
|
|
}
|
2020-02-27 17:00:53 +01:00
|
|
|
}
|
|
|
|
|
2023-12-13 22:47:44 +01:00
|
|
|
exportedInfo, _ := android.OtherModuleProvider(ctx.SdkModuleContext(), variant, FlagExporterInfoProvider)
|
2020-09-18 23:15:30 +02:00
|
|
|
|
2020-02-27 17:00:53 +01:00
|
|
|
// Separate out the generated include dirs (which are arch specific) from the
|
|
|
|
// include dirs (which may not be).
|
|
|
|
exportedIncludeDirs, exportedGeneratedIncludeDirs := android.FilterPathListPredicate(
|
2020-09-18 23:15:30 +02:00
|
|
|
exportedInfo.IncludeDirs, isGeneratedHeaderDirectory)
|
2020-02-27 17:00:53 +01:00
|
|
|
|
2019-11-19 20:44:10 +01:00
|
|
|
target := ccModule.Target()
|
|
|
|
p.archSubDir = target.Arch.ArchType.String()
|
|
|
|
if target.NativeBridge == android.NativeBridgeEnabled {
|
|
|
|
p.archSubDir += "_native_bridge"
|
|
|
|
}
|
2020-03-12 11:24:35 +01:00
|
|
|
|
|
|
|
// Make sure that the include directories are unique.
|
|
|
|
p.ExportedIncludeDirs = android.FirstUniquePaths(exportedIncludeDirs)
|
2021-02-17 13:17:40 +01:00
|
|
|
p.ExportedGeneratedIncludeDirs = android.FirstUniquePaths(exportedGeneratedIncludeDirs)
|
2020-06-18 17:31:04 +02:00
|
|
|
|
|
|
|
// Take a copy before filtering out duplicates to avoid changing the slice owned by the
|
|
|
|
// ccModule.
|
2020-09-18 23:15:30 +02:00
|
|
|
dirs := append(android.Paths(nil), exportedInfo.SystemIncludeDirs...)
|
2020-06-18 17:31:04 +02:00
|
|
|
p.ExportedSystemIncludeDirs = android.FirstUniquePaths(dirs)
|
2020-03-12 11:24:35 +01:00
|
|
|
|
2020-09-18 23:15:30 +02:00
|
|
|
p.ExportedFlags = exportedInfo.Flags
|
2020-03-06 13:30:43 +01:00
|
|
|
if ccModule.linker != nil {
|
|
|
|
specifiedDeps := specifiedDeps{}
|
|
|
|
specifiedDeps = ccModule.linker.linkerSpecifiedDeps(specifiedDeps)
|
|
|
|
|
2020-10-24 02:22:06 +02:00
|
|
|
if lib := ccModule.library; lib != nil {
|
|
|
|
if !lib.hasStubsVariants() {
|
|
|
|
// Propagate dynamic dependencies for implementation libs, but not stubs.
|
|
|
|
p.SharedLibs = specifiedDeps.sharedLibs
|
|
|
|
} else {
|
|
|
|
// TODO(b/169373910): 1. Only output the specific version (from
|
|
|
|
// ccModule.StubsVersion()) if the module is versioned. 2. Ensure that all
|
|
|
|
// the versioned stub libs are retained in the prebuilt tree; currently only
|
|
|
|
// the stub corresponding to ccModule.StubsVersion() is.
|
|
|
|
p.StubsVersions = lib.allStubsVersions()
|
|
|
|
}
|
2020-04-21 21:45:35 +02:00
|
|
|
}
|
2020-03-06 13:30:43 +01:00
|
|
|
p.SystemSharedLibs = specifiedDeps.systemSharedLibs
|
|
|
|
}
|
2021-02-17 13:17:40 +01:00
|
|
|
p.ExportedGeneratedHeaders = exportedInfo.GeneratedHeaders
|
2020-04-01 21:38:01 +02:00
|
|
|
|
2020-10-29 00:38:33 +01:00
|
|
|
if !p.memberType.noOutputFiles && addOutputFile {
|
|
|
|
p.outputFile = getRequiredMemberOutputFile(ctx, ccModule)
|
2020-08-21 19:43:51 +02:00
|
|
|
}
|
2020-02-27 17:00:53 +01:00
|
|
|
}
|
|
|
|
|
2020-05-05 15:11:57 +02:00
|
|
|
func getRequiredMemberOutputFile(ctx android.SdkMemberContext, ccModule *Module) android.Path {
|
|
|
|
var path android.Path
|
|
|
|
outputFile := ccModule.OutputFile()
|
|
|
|
if outputFile.Valid() {
|
|
|
|
path = outputFile.Path()
|
|
|
|
} else {
|
|
|
|
ctx.SdkModuleContext().ModuleErrorf("member variant %s does not have a valid output file", ccModule)
|
|
|
|
}
|
|
|
|
return path
|
|
|
|
}
|
|
|
|
|
2020-03-19 17:11:18 +01:00
|
|
|
func (p *nativeLibInfoProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
|
|
|
|
addPossiblyArchSpecificProperties(ctx.SdkModuleContext(), ctx.SnapshotBuilder(), p, propertySet)
|
2019-12-13 11:40:56 +01:00
|
|
|
}
|