Add java_boot_libs to sdk
The build has some implicit dependencies (via the boot jars configuration) on a number of modules, e.g. core-oj, apache-xml, that are part of the java boot class path and which are provided by mainline modules (e.g. art, conscrypt, runtime-i18n) but which are not otherwise used outside those mainline modules. As they are not needed outside the mainline modules adding them to the sdk/module-exports as either java_libs, or java_header_libs would end up exporting more information than was strictly necessary. This change adds the java_boot_libs property to allow those modules to be exported as part of the sdk/module_exports without exposing any unnecessary information. Some points to note: * The java_import has to have a valid file for the src property otherwise it will be disabled. * The src property is supposed to reference a jar file but the java_boot_libs property will make it reference an empty file (not an empty jar) so that any attempt to use that file as a jar, e.g. compiling against it, will cause a build failure. * The name of the file passed to the src property should make it clear that the file is not intended to be used. * The test makes sure that only the jar file is copied to the snapshot. Test: m nothing Bug: 171061220 Change-Id: I175331e4c8e3874ab70a67cdc2f76ed1576e41eb
This commit is contained in:
parent
b47dcf7f0d
commit
db170e4a92
5 changed files with 148 additions and 6 deletions
|
@ -177,6 +177,12 @@ type SnapshotBuilder interface {
|
|||
// to the zip
|
||||
CopyToSnapshot(src Path, dest string)
|
||||
|
||||
// Return the path to an empty file.
|
||||
//
|
||||
// This can be used by sdk member types that need to create an empty file in the snapshot, simply
|
||||
// pass the value returned from this to the CopyToSnapshot() method.
|
||||
EmptyFile() Path
|
||||
|
||||
// Unzip the supplied zip into the snapshot relative directory destDir.
|
||||
UnzipToSnapshot(zipPath Path, destDir string)
|
||||
|
||||
|
|
|
@ -470,6 +470,10 @@ func AndroidMkDataForTest(t *testing.T, config Config, bpPath string, mod bluepr
|
|||
// The build and source paths should be distinguishable based on their contents.
|
||||
func NormalizePathForTesting(path Path) string {
|
||||
p := path.String()
|
||||
// Allow absolute paths to /dev/
|
||||
if strings.HasPrefix(p, "/dev/") {
|
||||
return p
|
||||
}
|
||||
if w, ok := path.(WritablePath); ok {
|
||||
rel, err := filepath.Rel(w.buildDir(), p)
|
||||
if err != nil {
|
||||
|
|
73
java/java.go
73
java/java.go
|
@ -40,20 +40,55 @@ func init() {
|
|||
// Register sdk member types.
|
||||
android.RegisterSdkMemberType(javaHeaderLibsSdkMemberType)
|
||||
|
||||
// Register java implementation libraries for use only in module_exports (not sdk).
|
||||
android.RegisterSdkMemberType(&librarySdkMemberType{
|
||||
android.SdkMemberTypeBase{
|
||||
PropertyName: "java_libs",
|
||||
},
|
||||
func(j *Library) android.Path {
|
||||
func(_ android.SdkMemberContext, j *Library) android.Path {
|
||||
implementationJars := j.ImplementationAndResourcesJars()
|
||||
if len(implementationJars) != 1 {
|
||||
panic(fmt.Errorf("there must be only one implementation jar from %q", j.Name()))
|
||||
}
|
||||
|
||||
return implementationJars[0]
|
||||
},
|
||||
sdkSnapshotFilePathForJar,
|
||||
copyEverythingToSnapshot,
|
||||
})
|
||||
|
||||
// Register java boot libraries for use in sdk.
|
||||
//
|
||||
// The build has some implicit dependencies (via the boot jars configuration) on a number of
|
||||
// modules, e.g. core-oj, apache-xml, that are part of the java boot class path and which are
|
||||
// provided by mainline modules (e.g. art, conscrypt, runtime-i18n) but which are not otherwise
|
||||
// used outside those mainline modules.
|
||||
//
|
||||
// As they are not needed outside the mainline modules adding them to the sdk/module-exports as
|
||||
// either java_libs, or java_header_libs would end up exporting more information than was strictly
|
||||
// necessary. The java_boot_libs property to allow those modules to be exported as part of the
|
||||
// sdk/module_exports without exposing any unnecessary information.
|
||||
android.RegisterSdkMemberType(&librarySdkMemberType{
|
||||
android.SdkMemberTypeBase{
|
||||
PropertyName: "java_boot_libs",
|
||||
SupportsSdk: true,
|
||||
},
|
||||
func(ctx android.SdkMemberContext, j *Library) android.Path {
|
||||
// Java boot libs are only provided in the SDK to provide access to their dex implementation
|
||||
// jar for use by dexpreopting and boot jars package check. They do not need to provide an
|
||||
// actual implementation jar but the java_import will need a file that exists so just copy an
|
||||
// empty file. Any attempt to use that file as a jar will cause a build error.
|
||||
return ctx.SnapshotBuilder().EmptyFile()
|
||||
},
|
||||
func(osPrefix, name string) string {
|
||||
// Create a special name for the implementation jar to try and provide some useful information
|
||||
// to a developer that attempts to compile against this.
|
||||
// TODO(b/175714559): Provide a proper error message in Soong not ninja.
|
||||
return filepath.Join(osPrefix, "java_boot_libs", "snapshot", "jars", "are", "invalid", name+jarFileSuffix)
|
||||
},
|
||||
onlyCopyJarToSnapshot,
|
||||
})
|
||||
|
||||
// Register java test libraries for use only in module_exports (not sdk).
|
||||
android.RegisterSdkMemberType(&testSdkMemberType{
|
||||
SdkMemberTypeBase: android.SdkMemberTypeBase{
|
||||
PropertyName: "java_tests",
|
||||
|
@ -2165,9 +2200,22 @@ type librarySdkMemberType struct {
|
|||
|
||||
// Function to retrieve the appropriate output jar (implementation or header) from
|
||||
// the library.
|
||||
jarToExportGetter func(j *Library) android.Path
|
||||
jarToExportGetter func(ctx android.SdkMemberContext, j *Library) android.Path
|
||||
|
||||
// Function to compute the snapshot relative path to which the named library's
|
||||
// jar should be copied.
|
||||
snapshotPathGetter func(osPrefix, name string) string
|
||||
|
||||
// True if only the jar should be copied to the snapshot, false if the jar plus any additional
|
||||
// files like aidl files should also be copied.
|
||||
onlyCopyJarToSnapshot bool
|
||||
}
|
||||
|
||||
const (
|
||||
onlyCopyJarToSnapshot = true
|
||||
copyEverythingToSnapshot = false
|
||||
)
|
||||
|
||||
func (mt *librarySdkMemberType) AddDependencies(mctx android.BottomUpMutatorContext, dependencyTag blueprint.DependencyTag, names []string) {
|
||||
mctx.AddVariationDependencies(nil, dependencyTag, names...)
|
||||
}
|
||||
|
@ -2195,21 +2243,32 @@ type librarySdkMemberProperties struct {
|
|||
func (p *librarySdkMemberProperties) PopulateFromVariant(ctx android.SdkMemberContext, variant android.Module) {
|
||||
j := variant.(*Library)
|
||||
|
||||
p.JarToExport = ctx.MemberType().(*librarySdkMemberType).jarToExportGetter(j)
|
||||
p.JarToExport = ctx.MemberType().(*librarySdkMemberType).jarToExportGetter(ctx, j)
|
||||
|
||||
p.AidlIncludeDirs = j.AidlIncludeDirs()
|
||||
}
|
||||
|
||||
func (p *librarySdkMemberProperties) AddToPropertySet(ctx android.SdkMemberContext, propertySet android.BpPropertySet) {
|
||||
builder := ctx.SnapshotBuilder()
|
||||
|
||||
memberType := ctx.MemberType().(*librarySdkMemberType)
|
||||
|
||||
exportedJar := p.JarToExport
|
||||
if exportedJar != nil {
|
||||
snapshotRelativeJavaLibPath := sdkSnapshotFilePathForJar(p.OsPrefix(), ctx.Name())
|
||||
// Delegate the creation of the snapshot relative path to the member type.
|
||||
snapshotRelativeJavaLibPath := memberType.snapshotPathGetter(p.OsPrefix(), ctx.Name())
|
||||
|
||||
// Copy the exported jar to the snapshot.
|
||||
builder.CopyToSnapshot(exportedJar, snapshotRelativeJavaLibPath)
|
||||
|
||||
propertySet.AddProperty("jars", []string{snapshotRelativeJavaLibPath})
|
||||
}
|
||||
|
||||
// Do not copy anything else to the snapshot.
|
||||
if memberType.onlyCopyJarToSnapshot {
|
||||
return
|
||||
}
|
||||
|
||||
aidlIncludeDirs := p.AidlIncludeDirs
|
||||
if len(aidlIncludeDirs) != 0 {
|
||||
sdkModuleContext := ctx.SdkModuleContext()
|
||||
|
@ -2230,7 +2289,7 @@ var javaHeaderLibsSdkMemberType android.SdkMemberType = &librarySdkMemberType{
|
|||
PropertyName: "java_header_libs",
|
||||
SupportsSdk: true,
|
||||
},
|
||||
func(j *Library) android.Path {
|
||||
func(_ android.SdkMemberContext, j *Library) android.Path {
|
||||
headerJars := j.HeaderJars()
|
||||
if len(headerJars) != 1 {
|
||||
panic(fmt.Errorf("there must be only one header jar from %q", j.Name()))
|
||||
|
@ -2238,6 +2297,8 @@ var javaHeaderLibsSdkMemberType android.SdkMemberType = &librarySdkMemberType{
|
|||
|
||||
return headerJars[0]
|
||||
},
|
||||
sdkSnapshotFilePathForJar,
|
||||
copyEverythingToSnapshot,
|
||||
}
|
||||
|
||||
// java_library builds and links sources into a `.jar` file for the device, and possibly for the host as well.
|
||||
|
|
|
@ -472,6 +472,61 @@ aidl/foo/bar/Test.aidl -> aidl/aidl/foo/bar/Test.aidl
|
|||
)
|
||||
}
|
||||
|
||||
func TestSnapshotWithJavaBootLibrary(t *testing.T) {
|
||||
result := testSdkWithJava(t, `
|
||||
module_exports {
|
||||
name: "myexports",
|
||||
java_boot_libs: ["myjavalib"],
|
||||
}
|
||||
|
||||
java_library {
|
||||
name: "myjavalib",
|
||||
srcs: ["Test.java"],
|
||||
java_resources: ["resource.txt"],
|
||||
// The aidl files should not be copied to the snapshot because a java_boot_libs member is not
|
||||
// intended to be used for compiling Java, only for accessing the dex implementation jar.
|
||||
aidl: {
|
||||
export_include_dirs: ["aidl"],
|
||||
},
|
||||
system_modules: "none",
|
||||
sdk_version: "none",
|
||||
compile_dex: true,
|
||||
}
|
||||
`)
|
||||
|
||||
result.CheckSnapshot("myexports", "",
|
||||
checkAndroidBpContents(`
|
||||
// This is auto-generated. DO NOT EDIT.
|
||||
|
||||
java_import {
|
||||
name: "myexports_myjavalib@current",
|
||||
sdk_member_name: "myjavalib",
|
||||
visibility: ["//visibility:public"],
|
||||
apex_available: ["//apex_available:platform"],
|
||||
jars: ["java_boot_libs/snapshot/jars/are/invalid/myjavalib.jar"],
|
||||
}
|
||||
|
||||
java_import {
|
||||
name: "myjavalib",
|
||||
prefer: false,
|
||||
visibility: ["//visibility:public"],
|
||||
apex_available: ["//apex_available:platform"],
|
||||
jars: ["java_boot_libs/snapshot/jars/are/invalid/myjavalib.jar"],
|
||||
}
|
||||
|
||||
module_exports_snapshot {
|
||||
name: "myexports@current",
|
||||
visibility: ["//visibility:public"],
|
||||
java_boot_libs: ["myexports_myjavalib@current"],
|
||||
}
|
||||
|
||||
`),
|
||||
checkAllCopyRules(`
|
||||
.intermediates/myexports/common_os/empty -> java_boot_libs/snapshot/jars/are/invalid/myjavalib.jar
|
||||
`),
|
||||
)
|
||||
}
|
||||
|
||||
func TestHostSnapshotWithJavaImplLibrary(t *testing.T) {
|
||||
result := testSdkWithJava(t, `
|
||||
module_exports {
|
||||
|
|
|
@ -653,6 +653,9 @@ type snapshotBuilder struct {
|
|||
filesToZip android.Paths
|
||||
zipsToMerge android.Paths
|
||||
|
||||
// The path to an empty file.
|
||||
emptyFile android.WritablePath
|
||||
|
||||
prebuiltModules map[string]*bpModule
|
||||
prebuiltOrder []*bpModule
|
||||
|
||||
|
@ -703,6 +706,19 @@ func (s *snapshotBuilder) UnzipToSnapshot(zipPath android.Path, destDir string)
|
|||
s.zipsToMerge = append(s.zipsToMerge, tmpZipPath)
|
||||
}
|
||||
|
||||
func (s *snapshotBuilder) EmptyFile() android.Path {
|
||||
if s.emptyFile == nil {
|
||||
ctx := s.ctx
|
||||
s.emptyFile = android.PathForModuleOut(ctx, "empty")
|
||||
s.ctx.Build(pctx, android.BuildParams{
|
||||
Rule: android.Touch,
|
||||
Output: s.emptyFile,
|
||||
})
|
||||
}
|
||||
|
||||
return s.emptyFile
|
||||
}
|
||||
|
||||
func (s *snapshotBuilder) AddPrebuiltModule(member android.SdkMember, moduleType string) android.BpModule {
|
||||
name := member.Name()
|
||||
if s.prebuiltModules[name] != nil {
|
||||
|
|
Loading…
Reference in a new issue