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

Commit 0f568b12 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Refactor sdk update mechanism"

parents 19258857 0e0cf1dc
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -31,6 +31,9 @@ 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
@@ -103,6 +106,7 @@ type sdkProperties struct {
// interface. InitSdkAwareModule should be called to initialize this struct.
type SdkBase struct {
	properties sdkProperties
	module     SdkAware
}

func (s *SdkBase) sdkBase() *SdkBase {
@@ -142,9 +146,34 @@ func (s *SdkBase) RequiredSdks() SdkRefs {
	return s.properties.RequiredSdks
}

func (s *SdkBase) BuildSnapshot(sdkModuleContext ModuleContext, builder SnapshotBuilder) {
	sdkModuleContext.ModuleErrorf("module type " + sdkModuleContext.OtherModuleType(s.module) + " cannot be used in an sdk")
}

// InitSdkAwareModule initializes the SdkBase struct. This must be called by all modules including
// SdkBase.
func InitSdkAwareModule(m SdkAware) {
	base := m.sdkBase()
	base.module = m
	m.AddProperties(&base.properties)
}

// Provide support for generating the build rules which will build the snapshot.
type SnapshotBuilder interface {
	// Copy src to the dest (which is a snapshot relative path) and add the dest
	// to the zip
	CopyToSnapshot(src Path, dest string)

	// Get the AndroidBpFile for the snapshot.
	AndroidBpFile() GeneratedSnapshotFile

	// Get a versioned name appropriate for the SDK snapshot version being taken.
	VersionedSdkMemberName(unversionedName string) interface{}
}

// Provides support for generating a file, e.g. the Android.bp file.
type GeneratedSnapshotFile interface {
	Printfln(format string, args ...interface{})
	Indent()
	Dedent()
}
+51 −0
Original line number Diff line number Diff line
@@ -1664,6 +1664,57 @@ func (j *Library) DepsMutator(ctx android.BottomUpMutatorContext) {
	j.deps(ctx)
}

const (
	aidlIncludeDir     = "aidl"
	javaStubDir        = "java"
	javaStubFileSuffix = ".jar"
)

// path to the stub file of a java library. Relative to <sdk_root>/<api_dir>
func (j *Library) javaStubFilePathFor() string {
	return filepath.Join(javaStubDir, j.Name()+javaStubFileSuffix)
}

func (j *Library) BuildSnapshot(sdkModuleContext android.ModuleContext, builder android.SnapshotBuilder) {
	headerJars := j.HeaderJars()
	if len(headerJars) != 1 {
		panic(fmt.Errorf("there must be only one header jar from %q", j.Name()))
	}
	snapshotRelativeJavaLibPath := j.javaStubFilePathFor()
	builder.CopyToSnapshot(headerJars[0], snapshotRelativeJavaLibPath)

	for _, dir := range j.AidlIncludeDirs() {
		// TODO(jiyong): copy parcelable declarations only
		aidlFiles, _ := sdkModuleContext.GlobWithDeps(dir.String()+"/**/*.aidl", nil)
		for _, file := range aidlFiles {
			builder.CopyToSnapshot(android.PathForSource(sdkModuleContext, file), filepath.Join(aidlIncludeDir, file))
		}
	}

	name := j.Name()
	bp := builder.AndroidBpFile()
	bp.Printfln("java_import {")
	bp.Indent()
	bp.Printfln("name: %q,", builder.VersionedSdkMemberName(name))
	bp.Printfln("sdk_member_name: %q,", name)
	bp.Printfln("jars: [%q],", snapshotRelativeJavaLibPath)
	bp.Dedent()
	bp.Printfln("}")
	bp.Printfln("")

	// This module is for the case when the source tree for the unversioned module
	// doesn't exist (i.e. building in an unbundled tree). "prefer:" is set to false
	// so that this module does not eclipse the unversioned module if it exists.
	bp.Printfln("java_import {")
	bp.Indent()
	bp.Printfln("name: %q,", name)
	bp.Printfln("jars: [%q],", snapshotRelativeJavaLibPath)
	bp.Printfln("prefer: false,")
	bp.Dedent()
	bp.Printfln("}")
	bp.Printfln("")
}

// java_library builds and links sources into a `.jar` file for the device, and possibly for the host as well.
//
// By default, a java_library has a single variant that produces a `.jar` file containing `.class` files that were
+171 −201
Original line number Diff line number Diff line
@@ -43,17 +43,17 @@ func newGeneratedFile(ctx android.ModuleContext, path ...string) *generatedFile
	}
}

func (gf *generatedFile) indent() {
func (gf *generatedFile) Indent() {
	gf.indentLevel++
}

func (gf *generatedFile) dedent() {
func (gf *generatedFile) Dedent() {
	gf.indentLevel--
}

func (gf *generatedFile) printfln(format string, args ...interface{}) {
func (gf *generatedFile) Printfln(format string, args ...interface{}) {
	// ninja consumes newline characters in rspfile_content. Prevent it by
	// escaping the backslash in the newline character. The extra backshash
	// escaping the backslash in the newline character. The extra backslash
	// is removed when the rspfile is written to the actual script file
	fmt.Fprintf(&(gf.content), strings.Repeat("    ", gf.indentLevel)+format+"\\n", args...)
}
@@ -70,8 +70,8 @@ func (gf *generatedFile) build(pctx android.PackageContext, ctx android.BuilderC
	rb.Build(pctx, ctx, gf.path.Base(), "Build "+gf.path.Base())
}

func (s *sdk) javaLibs(ctx android.ModuleContext) []*java.Library {
	result := []*java.Library{}
func (s *sdk) javaLibs(ctx android.ModuleContext) []android.SdkAware {
	result := []android.SdkAware{}
	ctx.VisitDirectDeps(func(m android.Module) {
		if j, ok := m.(*java.Library); ok {
			result = append(result, j)
@@ -180,20 +180,12 @@ func (s *sdk) nativeMemberInfos(ctx android.ModuleContext) []*nativeLibInfo {
//            libFoo.so   : a stub library

const (
	aidlIncludeDir            = "aidl"
	javaStubDir               = "java"
	javaStubFileSuffix        = ".jar"
	nativeIncludeDir          = "include"
	nativeGeneratedIncludeDir = "include_gen"
	nativeStubDir             = "lib"
	nativeStubFileSuffix      = ".so"
)

// path to the stub file of a java library. Relative to <sdk_root>/<api_dir>
func javaStubFilePathFor(javaLib *java.Library) string {
	return filepath.Join(javaStubDir, javaLib.Name()+javaStubFileSuffix)
}

// 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,
@@ -231,163 +223,80 @@ func versionedSdkMemberName(ctx android.ModuleContext, memberName string, versio
	return ctx.ModuleName() + "_" + memberName + string(android.SdkVersionSeparator) + version
}

// buildAndroidBp creates the blueprint file that defines prebuilt modules for each of
// the SDK members, and the entire sdk_snapshot module for the specified version
// TODO(jiyong): create a meta info file (e.g. json, protobuf, etc.) instead, and convert it to
// Android.bp in the (presumably old) branch where the snapshots will be used. This will give us
// some flexibility to introduce backwards incompatible changes in soong.
func (s *sdk) buildAndroidBp(ctx android.ModuleContext, version string) android.OutputPath {
	bp := newGeneratedFile(ctx, "snapshot", "Android.bp")
	bp.printfln("// This is auto-generated. DO NOT EDIT.")
	bp.printfln("")

	javaLibModules := s.javaLibs(ctx)
	for _, m := range javaLibModules {
		name := m.Name()
		bp.printfln("java_import {")
		bp.indent()
		bp.printfln("name: %q,", versionedSdkMemberName(ctx, name, version))
		bp.printfln("sdk_member_name: %q,", name)
		bp.printfln("jars: [%q],", javaStubFilePathFor(m))
		bp.dedent()
		bp.printfln("}")
		bp.printfln("")

		// This module is for the case when the source tree for the unversioned module
		// doesn't exist (i.e. building in an unbundled tree). "prefer:" is set to false
		// so that this module does not eclipse the unversioned module if it exists.
		bp.printfln("java_import {")
		bp.indent()
		bp.printfln("name: %q,", name)
		bp.printfln("jars: [%q],", javaStubFilePathFor(m))
		bp.printfln("prefer: false,")
		bp.dedent()
		bp.printfln("}")
		bp.printfln("")
	}
// buildSnapshot is the main function in this source file. It creates rules to copy
// the contents (header files, stub libraries, etc) into the zip file.
func (s *sdk) buildSnapshot(ctx android.ModuleContext) android.OutputPath {
	snapshotDir := android.PathForModuleOut(ctx, "snapshot")

	nativeLibInfos := s.nativeMemberInfos(ctx)
	for _, info := range nativeLibInfos {
		bp.printfln("cc_prebuilt_library_shared {")
		bp.indent()
		bp.printfln("name: %q,", versionedSdkMemberName(ctx, info.name, version))
		bp.printfln("sdk_member_name: %q,", info.name)
	bp := newGeneratedFile(ctx, "snapshot", "Android.bp")
	bp.Printfln("// This is auto-generated. DO NOT EDIT.")
	bp.Printfln("")

		// a function for emitting include dirs
		printExportedDirsForNativeLibs := func(lib archSpecificNativeLibInfo, systemInclude bool) {
			includeDirs := nativeIncludeDirPathsFor(ctx, lib, systemInclude, info.hasArchSpecificFlags)
			if len(includeDirs) == 0 {
				return
			}
			if !systemInclude {
				bp.printfln("export_include_dirs: [")
			} else {
				bp.printfln("export_system_include_dirs: [")
			}
			bp.indent()
			for _, dir := range includeDirs {
				bp.printfln("%q,", dir)
			}
			bp.dedent()
			bp.printfln("],")
	builder := &snapshotBuilder{
		ctx:           ctx,
		version:       "current",
		snapshotDir:   snapshotDir.OutputPath,
		androidBpFile: bp,
		filesToZip:    []android.Path{bp.path},
	}

		if !info.hasArchSpecificFlags {
			printExportedDirsForNativeLibs(info.archVariants[0], false /*systemInclude*/)
			printExportedDirsForNativeLibs(info.archVariants[0], true /*systemInclude*/)
	// copy exported AIDL files and stub jar files
	javaLibs := s.javaLibs(ctx)
	for _, m := range javaLibs {
		m.BuildSnapshot(ctx, builder)
	}

		bp.printfln("arch: {")
		bp.indent()
		for _, av := range info.archVariants {
			bp.printfln("%s: {", av.archType)
			bp.indent()
			bp.printfln("srcs: [%q],", nativeStubFilePathFor(av))
			if info.hasArchSpecificFlags {
				// export_* properties are added inside the arch: {<arch>: {...}} block
				printExportedDirsForNativeLibs(av, false /*systemInclude*/)
				printExportedDirsForNativeLibs(av, true /*systemInclude*/)
			}
			bp.dedent()
			bp.printfln("},") // <arch>
		}
		bp.dedent()
		bp.printfln("},") // arch
		bp.printfln("stl: \"none\",")
		bp.printfln("system_shared_libs: [],")
		bp.dedent()
		bp.printfln("}") // cc_prebuilt_library_shared
		bp.printfln("")
	// copy exported header files and stub *.so files
	nativeLibInfos := s.nativeMemberInfos(ctx)
	for _, info := range nativeLibInfos {
		buildSharedNativeLibSnapshot(ctx, info, builder)
	}

	bp.printfln("sdk_snapshot {")
	bp.indent()
	bp.printfln("name: %q,", ctx.ModuleName()+string(android.SdkVersionSeparator)+version)
	if len(javaLibModules) > 0 {
		bp.printfln("java_libs: [")
		bp.indent()
		for _, m := range javaLibModules {
			bp.printfln("%q,", versionedSdkMemberName(ctx, m.Name(), version))
	// generate Android.bp

	bp.Printfln("sdk_snapshot {")
	bp.Indent()
	bp.Printfln("name: %q,", ctx.ModuleName()+string(android.SdkVersionSeparator)+builder.version)
	if len(javaLibs) > 0 {
		bp.Printfln("java_libs: [")
		bp.Indent()
		for _, m := range javaLibs {
			bp.Printfln("%q,", builder.VersionedSdkMemberName(m.Name()))
		}
		bp.dedent()
		bp.printfln("],") // java_libs
		bp.Dedent()
		bp.Printfln("],") // java_libs
	}
	if len(nativeLibInfos) > 0 {
		bp.printfln("native_shared_libs: [")
		bp.indent()
		bp.Printfln("native_shared_libs: [")
		bp.Indent()
		for _, info := range nativeLibInfos {
			bp.printfln("%q,", versionedSdkMemberName(ctx, info.name, version))
			bp.Printfln("%q,", builder.VersionedSdkMemberName(info.name))
		}
		bp.dedent()
		bp.printfln("],") // native_shared_libs
		bp.Dedent()
		bp.Printfln("],") // native_shared_libs
	}
	bp.dedent()
	bp.printfln("}") // sdk_snapshot
	bp.printfln("")
	bp.Dedent()
	bp.Printfln("}") // sdk_snapshot
	bp.Printfln("")

	bp.build(pctx, ctx, nil)
	return bp.path
}

// buildSnapshot is the main function in this source file. It creates rules to copy
// the contents (header files, stub libraries, etc) into the zip file.
func (s *sdk) buildSnapshot(ctx android.ModuleContext) android.OutputPath {
	snapshotPath := func(paths ...string) android.OutputPath {
		return android.PathForModuleOut(ctx, "snapshot").Join(ctx, paths...)
	}
	filesToZip := builder.filesToZip

	var filesToZip android.Paths
	// copy src to dest and add the dest to the zip
	copy := func(src android.Path, dest android.OutputPath) {
		ctx.Build(pctx, android.BuildParams{
			Rule:   android.Cp,
			Input:  src,
			Output: dest,
		})
		filesToZip = append(filesToZip, dest)
	}

	// copy exported AIDL files and stub jar files
	for _, m := range s.javaLibs(ctx) {
		headerJars := m.HeaderJars()
		if len(headerJars) != 1 {
			panic(fmt.Errorf("there must be only one header jar from %q", m.Name()))
		}
		copy(headerJars[0], snapshotPath(javaStubFilePathFor(m)))
	// zip them all
	zipFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"-current.zip").OutputPath
	rb := android.NewRuleBuilder()
	rb.Command().
		BuiltTool(ctx, "soong_zip").
		FlagWithArg("-C ", builder.snapshotDir.String()).
		FlagWithRspFileInputList("-l ", filesToZip).
		FlagWithOutput("-o ", zipFile)
	rb.Build(pctx, ctx, "snapshot", "Building snapshot for "+ctx.ModuleName())

		for _, dir := range m.AidlIncludeDirs() {
			// TODO(jiyong): copy parcelable declarations only
			aidlFiles, _ := ctx.GlobWithDeps(dir.String()+"/**/*.aidl", nil)
			for _, file := range aidlFiles {
				copy(android.PathForSource(ctx, file), snapshotPath(aidlIncludeDir, file))
			}
		}
	return zipFile
}

	// copy exported header files and stub *.so files
	nativeLibInfos := s.nativeMemberInfos(ctx)
	for _, info := range nativeLibInfos {

func buildSharedNativeLibSnapshot(ctx android.ModuleContext, info *nativeLibInfo, builder android.SnapshotBuilder) {
	// a function for emitting include dirs
	printExportedDirCopyCommandsForNativeLibs := func(lib archSpecificNativeLibInfo) {
		includeDirs := lib.exportedIncludeDirs
@@ -409,8 +318,8 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext) android.OutputPath {
			headers, _ := ctx.GlobWithDeps(dir.String()+"/**/*.h", nil)
			for _, file := range headers {
				src := android.PathForSource(ctx, file)
					dest := snapshotPath(targetDir, file)
					copy(src, dest)
				dest := filepath.Join(targetDir, file)
				builder.CopyToSnapshot(src, dest)
			}
		}

@@ -420,8 +329,8 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext) android.OutputPath {
			if info.hasArchSpecificFlags {
				targetDir = filepath.Join(lib.archType, targetDir)
			}
				dest := snapshotPath(targetDir, lib.name, file.Rel())
				copy(file, dest)
			dest := filepath.Join(targetDir, lib.name, file.Rel())
			builder.CopyToSnapshot(file, dest)
		}
	}

@@ -431,27 +340,88 @@ func (s *sdk) buildSnapshot(ctx android.ModuleContext) android.OutputPath {

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

		if info.hasArchSpecificFlags {
			printExportedDirCopyCommandsForNativeLibs(av)
		}
	}

	bp := builder.AndroidBpFile()
	bp.Printfln("cc_prebuilt_library_shared {")
	bp.Indent()
	bp.Printfln("name: %q,", builder.VersionedSdkMemberName(info.name))
	bp.Printfln("sdk_member_name: %q,", info.name)

	// a function for emitting include dirs
	printExportedDirsForNativeLibs := func(lib archSpecificNativeLibInfo, systemInclude bool) {
		includeDirs := nativeIncludeDirPathsFor(ctx, lib, systemInclude, info.hasArchSpecificFlags)
		if len(includeDirs) == 0 {
			return
		}
		if !systemInclude {
			bp.Printfln("export_include_dirs: [")
		} else {
			bp.Printfln("export_system_include_dirs: [")
		}
		bp.Indent()
		for _, dir := range includeDirs {
			bp.Printfln("%q,", dir)
		}
		bp.Dedent()
		bp.Printfln("],")
	}

	// generate Android.bp
	bp := s.buildAndroidBp(ctx, "current")
	filesToZip = append(filesToZip, bp)
	if !info.hasArchSpecificFlags {
		printExportedDirsForNativeLibs(info.archVariants[0], false /*systemInclude*/)
		printExportedDirsForNativeLibs(info.archVariants[0], true /*systemInclude*/)
	}

	// zip them all
	zipFile := android.PathForModuleOut(ctx, ctx.ModuleName()+"-current.zip").OutputPath
	rb := android.NewRuleBuilder()
	rb.Command().
		BuiltTool(ctx, "soong_zip").
		FlagWithArg("-C ", snapshotPath().String()).
		FlagWithRspFileInputList("-l ", filesToZip).
		FlagWithOutput("-o ", zipFile)
	rb.Build(pctx, ctx, "snapshot", "Building snapshot for "+ctx.ModuleName())
	bp.Printfln("arch: {")
	bp.Indent()
	for _, av := range info.archVariants {
		bp.Printfln("%s: {", av.archType)
		bp.Indent()
		bp.Printfln("srcs: [%q],", nativeStubFilePathFor(av))
		if info.hasArchSpecificFlags {
			// export_* properties are added inside the arch: {<arch>: {...}} block
			printExportedDirsForNativeLibs(av, false /*systemInclude*/)
			printExportedDirsForNativeLibs(av, true /*systemInclude*/)
		}
		bp.Dedent()
		bp.Printfln("},") // <arch>
	}
	bp.Dedent()
	bp.Printfln("},") // arch
	bp.Printfln("stl: \"none\",")
	bp.Printfln("system_shared_libs: [],")
	bp.Dedent()
	bp.Printfln("}") // cc_prebuilt_library_shared
	bp.Printfln("")
}

	return zipFile
type snapshotBuilder struct {
	ctx           android.ModuleContext
	version       string
	snapshotDir   android.OutputPath
	filesToZip    android.Paths
	androidBpFile *generatedFile
}

func (s *snapshotBuilder) CopyToSnapshot(src android.Path, dest string) {
	path := s.snapshotDir.Join(s.ctx, dest)
	s.ctx.Build(pctx, android.BuildParams{
		Rule:   android.Cp,
		Input:  src,
		Output: path,
	})
	s.filesToZip = append(s.filesToZip, path)
}

func (s *snapshotBuilder) AndroidBpFile() android.GeneratedSnapshotFile {
	return s.androidBpFile
}

func (s *snapshotBuilder) VersionedSdkMemberName(unversionedName string) interface{} {
	return versionedSdkMemberName(s.ctx, unversionedName, s.version)
}