Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3a7caaa8 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge changes Ia7dbcd41,I93140450,I4d3fe18f,Ib00870dd,I10203594

* changes:
  Organize sdk member properties
  Extract the cc and java sdk related tests out into their own file
  Improve testing of sdk snapshot generation
  Separate sdk testing infrastructure from sdk tests
  Parameterize the sdk member processing
parents 7467a714 a6e737b0
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -508,7 +508,10 @@ bootstrap_go_package {
        "sdk/update.go",
    ],
    testSrcs: [
        "sdk/cc_sdk_test.go",
        "sdk/java_sdk_test.go",
        "sdk/sdk_test.go",
        "sdk/testing.go",
    ],
    pluginFor: ["soong_build"],
}
+54 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package android
import (
	"strings"

	"github.com/google/blueprint"
	"github.com/google/blueprint/proptools"
)

@@ -31,9 +32,6 @@ type SdkAware interface {
	MemberName() string
	BuildWithSdks(sdks SdkRefs)
	RequiredSdks() SdkRefs

	// Build a snapshot of the module.
	BuildSnapshot(sdkModuleContext ModuleContext, builder SnapshotBuilder)
}

// SdkRef refers to a version of an SDK
@@ -203,3 +201,56 @@ type BpPropertySet interface {
type BpModule interface {
	BpPropertySet
}

// An individual member of the SDK, includes all of the variants that the SDK
// requires.
type SdkMember interface {
	// The name of the member.
	Name() string

	// All the variants required by the SDK.
	Variants() []SdkAware
}

// Interface that must be implemented for every type that can be a member of an
// sdk.
//
// The basic implementation should look something like this, where ModuleType is
// the name of the module type being supported.
//
//    var ModuleTypeSdkMemberType = newModuleTypeSdkMemberType()
//
//    func newModuleTypeSdkMemberType() android.SdkMemberType {
//    	return &moduleTypeSdkMemberType{}
//    }
//
//    type moduleTypeSdkMemberType struct {
//    }
//
//    ...methods...
//
type SdkMemberType interface {
	// Add dependencies from the SDK module to all the variants the member
	// contributes to the SDK. The exact set of variants required is determined
	// by the SDK and its properties. The dependencies must be added with the
	// supplied tag.
	//
	// The BottomUpMutatorContext provided is for the SDK module.
	AddDependencies(mctx BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string)

	// Return true if the supplied module is an instance of this member type.
	//
	// This is used to check the type of each variant before added to the
	// SdkMember. Returning false will cause an error to be logged expaining that
	// the module is not allowed in whichever sdk property it was added.
	IsInstance(module Module) bool

	// Build the snapshot for the SDK member
	//
	// The ModuleContext provided is for the SDK module, so information for
	// variants in the supplied member can be accessed using the Other... methods.
	//
	// The SdkMember is guaranteed to contain variants for which the
	// IsInstance(Module) method returned true.
	BuildSnapshot(sdkModuleContext ModuleContext, builder SnapshotBuilder, member SdkMember)
}
+228 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import (
	"strings"
	"sync"

	"github.com/google/blueprint"
	"github.com/google/blueprint/pathtools"

	"android/soong/android"
@@ -1403,3 +1404,230 @@ func maybeInjectBoringSSLHash(ctx android.ModuleContext, outputFile android.Modu

	return outputFile
}

var LibrarySdkMemberType = &librarySdkMemberType{}

type librarySdkMemberType struct {
}

func (mt *librarySdkMemberType) 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: "image", Variation: android.CoreVariation},
				{Mutator: "link", Variation: "shared"},
				{Mutator: "version", Variation: version},
			}...), dependencyTag, name)
		}
	}
}

func (mt *librarySdkMemberType) IsInstance(module android.Module) bool {
	_, ok := module.(*Module)
	return ok
}

// copy exported header files and stub *.so files
func (mt *librarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
	info := organizeVariants(member)
	buildSharedNativeLibSnapshot(sdkModuleContext, info, builder)
}

func buildSharedNativeLibSnapshot(sdkModuleContext android.ModuleContext, info *nativeLibInfo, builder android.SnapshotBuilder) {
	// a function for emitting include dirs
	printExportedDirCopyCommandsForNativeLibs := func(lib archSpecificNativeLibInfo) {
		includeDirs := lib.exportedIncludeDirs
		includeDirs = append(includeDirs, lib.exportedSystemIncludeDirs...)
		if len(includeDirs) == 0 {
			return
		}
		for _, dir := range includeDirs {
			if _, gen := dir.(android.WritablePath); gen {
				// generated headers are copied via exportedDeps. See below.
				continue
			}
			targetDir := nativeIncludeDir
			if info.hasArchSpecificFlags {
				targetDir = filepath.Join(lib.archType, targetDir)
			}

			// TODO(jiyong) copy headers having other suffixes
			headers, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.h", nil)
			for _, file := range headers {
				src := android.PathForSource(sdkModuleContext, file)
				dest := filepath.Join(targetDir, file)
				builder.CopyToSnapshot(src, dest)
			}
		}

		genHeaders := lib.exportedDeps
		for _, file := range genHeaders {
			targetDir := nativeGeneratedIncludeDir
			if info.hasArchSpecificFlags {
				targetDir = filepath.Join(lib.archType, targetDir)
			}
			dest := filepath.Join(targetDir, lib.name, file.Rel())
			builder.CopyToSnapshot(file, dest)
		}
	}

	if !info.hasArchSpecificFlags {
		printExportedDirCopyCommandsForNativeLibs(info.archVariants[0])
	}

	// for each architecture
	for _, av := range info.archVariants {
		builder.CopyToSnapshot(av.outputFile, nativeStubFilePathFor(av))

		if info.hasArchSpecificFlags {
			printExportedDirCopyCommandsForNativeLibs(av)
		}
	}

	info.generatePrebuiltLibrary(sdkModuleContext, builder)
}

func (info *nativeLibInfo) generatePrebuiltLibrary(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder) {

	// a function for emitting include dirs
	addExportedDirsForNativeLibs := func(lib archSpecificNativeLibInfo, properties android.BpPropertySet, systemInclude bool) {
		includeDirs := nativeIncludeDirPathsFor(lib, systemInclude, info.hasArchSpecificFlags)
		if len(includeDirs) == 0 {
			return
		}
		var propertyName string
		if !systemInclude {
			propertyName = "export_include_dirs"
		} else {
			propertyName = "export_system_include_dirs"
		}
		properties.AddProperty(propertyName, includeDirs)
	}

	pbm := builder.AddPrebuiltModule(info.name, "cc_prebuilt_library_shared")

	if !info.hasArchSpecificFlags {
		addExportedDirsForNativeLibs(info.archVariants[0], pbm, false /*systemInclude*/)
		addExportedDirsForNativeLibs(info.archVariants[0], pbm, true /*systemInclude*/)
	}

	archProperties := pbm.AddPropertySet("arch")
	for _, av := range info.archVariants {
		archTypeProperties := archProperties.AddPropertySet(av.archType)
		archTypeProperties.AddProperty("srcs", []string{nativeStubFilePathFor(av)})
		if info.hasArchSpecificFlags {
			// export_* properties are added inside the arch: {<arch>: {...}} block
			addExportedDirsForNativeLibs(av, archTypeProperties, false /*systemInclude*/)
			addExportedDirsForNativeLibs(av, archTypeProperties, true /*systemInclude*/)
		}
	}
	pbm.AddProperty("stl", "none")
	pbm.AddProperty("system_shared_libs", []string{})
}

const (
	nativeIncludeDir          = "include"
	nativeGeneratedIncludeDir = "include_gen"
	nativeStubDir             = "lib"
	nativeStubFileSuffix      = ".so"
)

// path to the stub file of a native shared library. Relative to <sdk_root>/<api_dir>
func nativeStubFilePathFor(lib archSpecificNativeLibInfo) string {
	return filepath.Join(lib.archType,
		nativeStubDir, lib.name+nativeStubFileSuffix)
}

// paths to the include dirs of a native shared library. Relative to <sdk_root>/<api_dir>
func nativeIncludeDirPathsFor(lib archSpecificNativeLibInfo, systemInclude bool, archSpecific bool) []string {
	var result []string
	var includeDirs []android.Path
	if !systemInclude {
		includeDirs = lib.exportedIncludeDirs
	} else {
		includeDirs = lib.exportedSystemIncludeDirs
	}
	for _, dir := range includeDirs {
		var path string
		if _, gen := dir.(android.WritablePath); gen {
			path = filepath.Join(nativeGeneratedIncludeDir, lib.name)
		} else {
			path = filepath.Join(nativeIncludeDir, dir.String())
		}
		if archSpecific {
			path = filepath.Join(lib.archType, path)
		}
		result = append(result, path)
	}
	return result
}

// archSpecificNativeLibInfo represents an arch-specific variant of a native lib
type archSpecificNativeLibInfo struct {
	name                      string
	archType                  string
	exportedIncludeDirs       android.Paths
	exportedSystemIncludeDirs android.Paths
	exportedFlags             []string
	exportedDeps              android.Paths
	outputFile                android.Path
}

func (lib *archSpecificNativeLibInfo) signature() string {
	return fmt.Sprintf("%v %v %v %v",
		lib.name,
		lib.exportedIncludeDirs.Strings(),
		lib.exportedSystemIncludeDirs.Strings(),
		lib.exportedFlags)
}

// nativeLibInfo represents a collection of arch-specific modules having the same name
type nativeLibInfo struct {
	name         string
	archVariants []archSpecificNativeLibInfo
	// hasArchSpecificFlags is set to true if modules for each architecture all have the same
	// include dirs, flags, etc, in which case only those of the first arch is selected.
	hasArchSpecificFlags bool
}

// Organize the variants by architecture.
func organizeVariants(member android.SdkMember) *nativeLibInfo {
	info := &nativeLibInfo{name: member.Name()}

	for _, variant := range member.Variants() {
		ccModule := variant.(*Module)

		info.archVariants = append(info.archVariants, archSpecificNativeLibInfo{
			name:                      ccModule.BaseModuleName(),
			archType:                  ccModule.Target().Arch.ArchType.String(),
			exportedIncludeDirs:       ccModule.ExportedIncludeDirs(),
			exportedSystemIncludeDirs: ccModule.ExportedSystemIncludeDirs(),
			exportedFlags:             ccModule.ExportedFlags(),
			exportedDeps:              ccModule.ExportedDeps(),
			outputFile:                ccModule.OutputFile().Path(),
		})
	}

	// Determine if include dirs and flags for each variant are different across arch-specific
	// variants or not. And set hasArchSpecificFlags accordingly
	// by default, include paths and flags are assumed to be the same across arches
	info.hasArchSpecificFlags = false
	oldSignature := ""
	for _, av := range info.archVariants {
		newSignature := av.signature()
		if oldSignature == "" {
			oldSignature = newSignature
		}
		if oldSignature != newSignature {
			info.hasArchSpecificFlags = true
			break
		}
	}

	return info
}
+22 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ import (
	"path/filepath"
	"strings"

	"github.com/google/blueprint"
	"github.com/google/blueprint/proptools"

	"android/soong/android"
@@ -1973,7 +1974,27 @@ func PrebuiltStubsSourcesFactory() android.Module {
	return module
}

func (d *Droidstubs) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder) {
var DroidStubsSdkMemberType = &droidStubsSdkMemberType{}

type droidStubsSdkMemberType struct {
}

func (mt *droidStubsSdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
	mctx.AddVariationDependencies(nil, dependencyTag, names...)
}

func (mt *droidStubsSdkMemberType) IsInstance(module android.Module) bool {
	_, ok := module.(*Droidstubs)
	return ok
}

func (mt *droidStubsSdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
	variants := member.Variants()
	if len(variants) != 1 {
		sdkModuleContext.ModuleErrorf("sdk contains %d variants of member %q but only one is allowed", len(variants), member.Name())
	}
	variant := variants[0]
	d, _ := variant.(*Droidstubs)
	stubsSrcJar := d.stubsSrcJar

	snapshotRelativeDir := filepath.Join("java", d.Name()+"_stubs_sources")
+25 −1
Original line number Diff line number Diff line
@@ -1721,7 +1721,31 @@ func (j *Library) javaStubFilePathFor() string {
	return filepath.Join(javaStubDir, j.Name()+javaStubFileSuffix)
}

func (j *Library) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder) {
var LibrarySdkMemberType = &librarySdkMemberType{}

type librarySdkMemberType struct {
}

func (mt *librarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
	mctx.AddVariationDependencies(nil, dependencyTag, names...)
}

func (mt *librarySdkMemberType) IsInstance(module android.Module) bool {
	_, ok := module.(*Library)
	return ok
}

func (mt *librarySdkMemberType) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder, member android.SdkMember) {
	variants := member.Variants()
	if len(variants) != 1 {
		sdkModuleContext.ModuleErrorf("sdk contains %d variants of member %q but only one is allowed", len(variants), member.Name())
		for _, variant := range variants {
			sdkModuleContext.ModuleErrorf("    %q", variant)
		}
	}
	variant := variants[0]
	j := variant.(*Library)

	headerJars := j.HeaderJars()
	if len(headerJars) != 1 {
		panic(fmt.Errorf("there must be only one header jar from %q", j.Name()))
Loading