Implement sysprop_library API stability check
sysprop_library now checks the API stability itself, cutting dependency
on java_sdk_library. Under the directory {module_dir}/api,
{module_name}-current.txt and {module_name}-latest.txt hold API
signatures.
When sysprop_library is built, or a user run "m {module_name}-check-api"
command, API check is performed. First, current.txt must have exactly
same signature with built sysprop_library module. Second, current.txt
must be compatible with latest.txt.
Build system emits a handy error message to generate/update those API
files, in case of missing or mismatching. Also, a script file for
freezing API files is introduced.
Bug: 131637873
Test: 1) m && boot blueline
Test: 2) m {sysprop_library} performs API check
Test: 3) manual test for check-api, freezing api
Change-Id: I9d25f5dc64299e666527ca8e23d7233966901c4e
Merged-In: I9d25f5dc64299e666527ca8e23d7233966901c4e
Merged-In: Ib7ad4f17e82c90da5ef3f80e2ab88c0b53112c60
(cherry picked from commit 093f0eb133
)
This commit is contained in:
parent
95515641e7
commit
4288274f14
9 changed files with 341 additions and 90 deletions
|
@ -952,9 +952,7 @@ func (library *libraryDecorator) link(ctx ModuleContext,
|
||||||
isVendor := ctx.useVndk()
|
isVendor := ctx.useVndk()
|
||||||
isOwnerPlatform := Bool(library.Properties.Sysprop.Platform)
|
isOwnerPlatform := Bool(library.Properties.Sysprop.Platform)
|
||||||
|
|
||||||
usePublic := isProduct || (isOwnerPlatform == isVendor)
|
if !ctx.inRecovery() && (isProduct || (isOwnerPlatform == isVendor)) {
|
||||||
|
|
||||||
if usePublic {
|
|
||||||
dir = android.PathForModuleGen(ctx, "sysprop/public", "include").String()
|
dir = android.PathForModuleGen(ctx, "sysprop/public", "include").String()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type syspropLibraryInterface interface {
|
type syspropLibraryInterface interface {
|
||||||
|
BaseModuleName() string
|
||||||
CcModuleName() string
|
CcModuleName() string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +43,6 @@ func SyspropMutator(mctx android.BottomUpMutatorContext) {
|
||||||
syspropImplLibrariesLock.Lock()
|
syspropImplLibrariesLock.Lock()
|
||||||
defer syspropImplLibrariesLock.Unlock()
|
defer syspropImplLibrariesLock.Unlock()
|
||||||
|
|
||||||
syspropImplLibraries[mctx.ModuleName()] = m.CcModuleName()
|
syspropImplLibraries[m.BaseModuleName()] = m.CcModuleName()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -485,9 +485,6 @@ func (j *Javadoc) genSources(ctx android.ModuleContext, srcFiles android.Paths,
|
||||||
case ".aidl":
|
case ".aidl":
|
||||||
javaFile := genAidl(ctx, srcFile, flags.aidlFlags, flags.aidlDeps)
|
javaFile := genAidl(ctx, srcFile, flags.aidlFlags, flags.aidlDeps)
|
||||||
outSrcFiles = append(outSrcFiles, javaFile)
|
outSrcFiles = append(outSrcFiles, javaFile)
|
||||||
case ".sysprop":
|
|
||||||
javaFile := genSysprop(ctx, srcFile)
|
|
||||||
outSrcFiles = append(outSrcFiles, javaFile)
|
|
||||||
case ".logtags":
|
case ".logtags":
|
||||||
javaFile := genLogtags(ctx, srcFile)
|
javaFile := genLogtags(ctx, srcFile)
|
||||||
outSrcFiles = append(outSrcFiles, javaFile)
|
outSrcFiles = append(outSrcFiles, javaFile)
|
||||||
|
|
31
java/gen.go
31
java/gen.go
|
@ -53,13 +53,13 @@ var (
|
||||||
sysprop = pctx.AndroidStaticRule("sysprop",
|
sysprop = pctx.AndroidStaticRule("sysprop",
|
||||||
blueprint.RuleParams{
|
blueprint.RuleParams{
|
||||||
Command: `rm -rf $out.tmp && mkdir -p $out.tmp && ` +
|
Command: `rm -rf $out.tmp && mkdir -p $out.tmp && ` +
|
||||||
`$syspropCmd --java-output-dir $out.tmp $in && ` +
|
`$syspropCmd --scope $scope --java-output-dir $out.tmp $in && ` +
|
||||||
`${config.SoongZipCmd} -jar -o $out -C $out.tmp -D $out.tmp && rm -rf $out.tmp`,
|
`${config.SoongZipCmd} -jar -o $out -C $out.tmp -D $out.tmp && rm -rf $out.tmp`,
|
||||||
CommandDeps: []string{
|
CommandDeps: []string{
|
||||||
"$syspropCmd",
|
"$syspropCmd",
|
||||||
"${config.SoongZipCmd}",
|
"${config.SoongZipCmd}",
|
||||||
},
|
},
|
||||||
})
|
}, "scope")
|
||||||
)
|
)
|
||||||
|
|
||||||
func genAidl(ctx android.ModuleContext, aidlFile android.Path, aidlFlags string, deps android.Paths) android.Path {
|
func genAidl(ctx android.ModuleContext, aidlFile android.Path, aidlFlags string, deps android.Paths) android.Path {
|
||||||
|
@ -98,7 +98,7 @@ func genLogtags(ctx android.ModuleContext, logtagsFile android.Path) android.Pat
|
||||||
return javaFile
|
return javaFile
|
||||||
}
|
}
|
||||||
|
|
||||||
func genSysprop(ctx android.ModuleContext, syspropFile android.Path) android.Path {
|
func genSysprop(ctx android.ModuleContext, syspropFile android.Path, scope string) android.Path {
|
||||||
srcJarFile := android.GenPathWithExt(ctx, "sysprop", syspropFile, "srcjar")
|
srcJarFile := android.GenPathWithExt(ctx, "sysprop", syspropFile, "srcjar")
|
||||||
|
|
||||||
ctx.Build(pctx, android.BuildParams{
|
ctx.Build(pctx, android.BuildParams{
|
||||||
|
@ -106,6 +106,9 @@ func genSysprop(ctx android.ModuleContext, syspropFile android.Path) android.Pat
|
||||||
Description: "sysprop_java " + syspropFile.Rel(),
|
Description: "sysprop_java " + syspropFile.Rel(),
|
||||||
Output: srcJarFile,
|
Output: srcJarFile,
|
||||||
Input: syspropFile,
|
Input: syspropFile,
|
||||||
|
Args: map[string]string{
|
||||||
|
"scope": scope,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
return srcJarFile
|
return srcJarFile
|
||||||
|
@ -129,7 +132,27 @@ func (j *Module) genSources(ctx android.ModuleContext, srcFiles android.Paths,
|
||||||
srcJarFile := genProto(ctx, srcFile, flags.proto)
|
srcJarFile := genProto(ctx, srcFile, flags.proto)
|
||||||
outSrcFiles = append(outSrcFiles, srcJarFile)
|
outSrcFiles = append(outSrcFiles, srcJarFile)
|
||||||
case ".sysprop":
|
case ".sysprop":
|
||||||
srcJarFile := genSysprop(ctx, srcFile)
|
// internal scope contains all properties
|
||||||
|
// public scope only contains public properties
|
||||||
|
// use public if the owner is different from client
|
||||||
|
scope := "internal"
|
||||||
|
if j.properties.Sysprop.Platform != nil {
|
||||||
|
isProduct := ctx.ProductSpecific()
|
||||||
|
isVendor := ctx.SocSpecific()
|
||||||
|
isOwnerPlatform := Bool(j.properties.Sysprop.Platform)
|
||||||
|
|
||||||
|
if isProduct {
|
||||||
|
// product can't own any sysprop_library now, so product must use public scope
|
||||||
|
scope = "public"
|
||||||
|
} else if isVendor && !isOwnerPlatform {
|
||||||
|
// vendor and odm can't use system's internal property.
|
||||||
|
scope = "public"
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't care about clients under system.
|
||||||
|
// They can't use sysprop_library owned by other partitions.
|
||||||
|
}
|
||||||
|
srcJarFile := genSysprop(ctx, srcFile, scope)
|
||||||
outSrcFiles = append(outSrcFiles, srcJarFile)
|
outSrcFiles = append(outSrcFiles, srcJarFile)
|
||||||
default:
|
default:
|
||||||
outSrcFiles = append(outSrcFiles, srcFile)
|
outSrcFiles = append(outSrcFiles, srcFile)
|
||||||
|
|
|
@ -183,6 +183,10 @@ type CompilerProperties struct {
|
||||||
Output_params []string
|
Output_params []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Sysprop struct {
|
||||||
|
Platform *bool
|
||||||
|
} `blueprint:"mutated"`
|
||||||
|
|
||||||
Instrument bool `blueprint:"mutated"`
|
Instrument bool `blueprint:"mutated"`
|
||||||
|
|
||||||
// List of files to include in the META-INF/services folder of the resulting jar.
|
// List of files to include in the META-INF/services folder of the resulting jar.
|
||||||
|
@ -1017,7 +1021,6 @@ func (j *Module) collectBuilderFlags(ctx android.ModuleContext, deps deps) javaB
|
||||||
}
|
}
|
||||||
|
|
||||||
func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
|
func (j *Module) compile(ctx android.ModuleContext, aaptSrcJar android.Path) {
|
||||||
|
|
||||||
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
|
j.exportAidlIncludeDirs = android.PathsForModuleSrc(ctx, j.deviceProperties.Aidl.Export_include_dirs)
|
||||||
|
|
||||||
deps := j.collectDeps(ctx)
|
deps := j.collectDeps(ctx)
|
||||||
|
|
39
scripts/freeze-sysprop-api-files.sh
Executable file
39
scripts/freeze-sysprop-api-files.sh
Executable file
|
@ -0,0 +1,39 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
# Copyright (C) 2019 The Android Open Source Project
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
# This script freezes APIs of a sysprop_library after checking compatibility
|
||||||
|
# between latest API and current API.
|
||||||
|
#
|
||||||
|
# Usage: freeze-sysprop-api-files.sh <modulePath> <moduleName>
|
||||||
|
#
|
||||||
|
# <modulePath>: the directory, either relative or absolute, which holds the
|
||||||
|
# Android.bp file defining sysprop_library.
|
||||||
|
#
|
||||||
|
# <moduleName>: the name of sysprop_library to freeze API.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# $ . build/envsetup.sh && lunch aosp_arm64-user
|
||||||
|
# $ . build/soong/scripts/freeze-sysprop-api-files.sh \
|
||||||
|
# system/libsysprop/srcs PlatformProperties
|
||||||
|
|
||||||
|
if [[ -z "$1" || -z "$2" ]]; then
|
||||||
|
echo "usage: $0 <modulePath> <moduleName>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
api_dir=$1/api
|
||||||
|
|
||||||
|
m "$2-check-api" && cp -f "${api_dir}/$2-current.txt" "${api_dir}/$2-latest.txt"
|
26
scripts/gen-sysprop-api-files.sh
Executable file
26
scripts/gen-sysprop-api-files.sh
Executable file
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
# Copyright (C) 2019 The Android Open Source Project
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
if [[ -z "$1" || -z "$2" ]]; then
|
||||||
|
echo "usage: $0 <modulePath> <moduleName>" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
api_dir=$1/api
|
||||||
|
|
||||||
|
mkdir -p "$api_dir"
|
||||||
|
touch "${api_dir}/$2-current.txt"
|
||||||
|
touch "${api_dir}/$2-latest.txt"
|
|
@ -15,12 +15,16 @@
|
||||||
package sysprop
|
package sysprop
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"android/soong/android"
|
"fmt"
|
||||||
"android/soong/cc"
|
"io"
|
||||||
"android/soong/java"
|
"path"
|
||||||
|
|
||||||
"github.com/google/blueprint"
|
"github.com/google/blueprint"
|
||||||
"github.com/google/blueprint/proptools"
|
"github.com/google/blueprint/proptools"
|
||||||
|
|
||||||
|
"android/soong/android"
|
||||||
|
"android/soong/cc"
|
||||||
|
"android/soong/java"
|
||||||
)
|
)
|
||||||
|
|
||||||
type dependencyTag struct {
|
type dependencyTag struct {
|
||||||
|
@ -29,10 +33,14 @@ type dependencyTag struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type syspropLibrary struct {
|
type syspropLibrary struct {
|
||||||
java.SdkLibrary
|
android.ModuleBase
|
||||||
|
|
||||||
commonProperties commonProperties
|
properties syspropLibraryProperties
|
||||||
syspropLibraryProperties syspropLibraryProperties
|
|
||||||
|
checkApiFileTimeStamp android.WritablePath
|
||||||
|
latestApiFile android.Path
|
||||||
|
currentApiFile android.Path
|
||||||
|
dumpedApiFile android.WritablePath
|
||||||
}
|
}
|
||||||
|
|
||||||
type syspropLibraryProperties struct {
|
type syspropLibraryProperties struct {
|
||||||
|
@ -42,17 +50,22 @@ type syspropLibraryProperties struct {
|
||||||
|
|
||||||
// list of package names that will be documented and publicized as API
|
// list of package names that will be documented and publicized as API
|
||||||
Api_packages []string
|
Api_packages []string
|
||||||
}
|
|
||||||
|
|
||||||
type commonProperties struct {
|
// If set to true, allow this module to be dexed and installed on devices.
|
||||||
Srcs []string
|
Installable *bool
|
||||||
Recovery *bool
|
|
||||||
|
// Make this module available when building for recovery
|
||||||
Recovery_available *bool
|
Recovery_available *bool
|
||||||
Vendor_available *bool
|
|
||||||
|
// Make this module available when building for vendor
|
||||||
|
Vendor_available *bool
|
||||||
|
|
||||||
|
// list of .sysprop files which defines the properties.
|
||||||
|
Srcs []string `android:"path"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Bool = proptools.Bool
|
pctx = android.NewPackageContext("android/soong/sysprop")
|
||||||
syspropCcTag = dependencyTag{name: "syspropCc"}
|
syspropCcTag = dependencyTag{name: "syspropCc"}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -60,56 +73,166 @@ func init() {
|
||||||
android.RegisterModuleType("sysprop_library", syspropLibraryFactory)
|
android.RegisterModuleType("sysprop_library", syspropLibraryFactory)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *syspropLibrary) CcModuleName() string {
|
func (m *syspropLibrary) Name() string {
|
||||||
return "lib" + m.Name()
|
return m.BaseModuleName() + "_sysprop_library"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *syspropLibrary) CcModuleName() string {
|
||||||
|
return "lib" + m.BaseModuleName()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *syspropLibrary) BaseModuleName() string {
|
||||||
|
return m.ModuleBase.Name()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *syspropLibrary) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
||||||
|
m.currentApiFile = android.PathForSource(ctx, ctx.ModuleDir(), "api", m.BaseModuleName()+"-current.txt")
|
||||||
|
m.latestApiFile = android.PathForSource(ctx, ctx.ModuleDir(), "api", m.BaseModuleName()+"-latest.txt")
|
||||||
|
|
||||||
|
// dump API rule
|
||||||
|
rule := android.NewRuleBuilder()
|
||||||
|
m.dumpedApiFile = android.PathForModuleOut(ctx, "api-dump.txt")
|
||||||
|
rule.Command().
|
||||||
|
BuiltTool(ctx, "sysprop_api_dump").
|
||||||
|
Output(m.dumpedApiFile).
|
||||||
|
Inputs(android.PathsForModuleSrc(ctx, m.properties.Srcs))
|
||||||
|
rule.Build(pctx, ctx, m.BaseModuleName()+"_api_dump", m.BaseModuleName()+" api dump")
|
||||||
|
|
||||||
|
// check API rule
|
||||||
|
rule = android.NewRuleBuilder()
|
||||||
|
|
||||||
|
// 1. current.txt <-> api_dump.txt
|
||||||
|
msg := fmt.Sprintf(`\n******************************\n`+
|
||||||
|
`API of sysprop_library %s doesn't match with current.txt\n`+
|
||||||
|
`Please update current.txt by:\n`+
|
||||||
|
`rm -rf %q && cp -f %q %q\n`+
|
||||||
|
`******************************\n`, m.BaseModuleName(),
|
||||||
|
m.currentApiFile.String(), m.dumpedApiFile.String(), m.currentApiFile.String())
|
||||||
|
|
||||||
|
rule.Command().
|
||||||
|
Text("( cmp").Flag("-s").
|
||||||
|
Input(m.dumpedApiFile).
|
||||||
|
Input(m.currentApiFile).
|
||||||
|
Text("|| ( echo").Flag("-e").
|
||||||
|
Flag(`"` + msg + `"`).
|
||||||
|
Text("; exit 38) )")
|
||||||
|
|
||||||
|
// 2. current.txt <-> latest.txt
|
||||||
|
msg = fmt.Sprintf(`\n******************************\n`+
|
||||||
|
`API of sysprop_library %s doesn't match with latest version\n`+
|
||||||
|
`Please fix the breakage and rebuild.\n`+
|
||||||
|
`******************************\n`, m.BaseModuleName())
|
||||||
|
|
||||||
|
rule.Command().
|
||||||
|
Text("( ").
|
||||||
|
BuiltTool(ctx, "sysprop_api_checker").
|
||||||
|
Input(m.latestApiFile).
|
||||||
|
Input(m.currentApiFile).
|
||||||
|
Text(" || ( echo").Flag("-e").
|
||||||
|
Flag(`"` + msg + `"`).
|
||||||
|
Text("; exit 38) )")
|
||||||
|
|
||||||
|
m.checkApiFileTimeStamp = android.PathForModuleOut(ctx, "check_api.timestamp")
|
||||||
|
|
||||||
|
rule.Command().
|
||||||
|
Text("touch").
|
||||||
|
Output(m.checkApiFileTimeStamp)
|
||||||
|
|
||||||
|
rule.Build(pctx, ctx, m.BaseModuleName()+"_check_api", m.BaseModuleName()+" check api")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *syspropLibrary) AndroidMk() android.AndroidMkData {
|
||||||
|
return android.AndroidMkData{
|
||||||
|
Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
|
||||||
|
// sysprop_library module itself is defined as a FAKE module to perform API check.
|
||||||
|
// Actual implementation libraries are created on LoadHookMutator
|
||||||
|
fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)")
|
||||||
|
fmt.Fprintf(w, "LOCAL_MODULE := %s\n", m.Name())
|
||||||
|
fmt.Fprintf(w, "LOCAL_MODULE_CLASS := FAKE\n")
|
||||||
|
fmt.Fprintf(w, "LOCAL_MODULE_TAGS := optional\n")
|
||||||
|
fmt.Fprintf(w, "include $(BUILD_SYSTEM)/base_rules.mk\n\n")
|
||||||
|
fmt.Fprintf(w, "$(LOCAL_BUILT_MODULE): %s\n", m.checkApiFileTimeStamp.String())
|
||||||
|
fmt.Fprintf(w, "\ttouch $@\n\n")
|
||||||
|
fmt.Fprintf(w, ".PHONY: %s-check-api\n\n", name)
|
||||||
|
|
||||||
|
// check API rule
|
||||||
|
fmt.Fprintf(w, "%s-check-api: %s\n\n", name, m.checkApiFileTimeStamp.String())
|
||||||
|
|
||||||
|
// "make {sysprop_library}" should also build the C++ library
|
||||||
|
fmt.Fprintf(w, "%s: %s\n\n", name, m.CcModuleName())
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sysprop_library creates schematized APIs from sysprop description files (.sysprop).
|
||||||
|
// Both Java and C++ modules can link against sysprop_library, and API stability check
|
||||||
|
// against latest APIs (see build/soong/scripts/freeze-sysprop-api-files.sh)
|
||||||
|
// is performed.
|
||||||
func syspropLibraryFactory() android.Module {
|
func syspropLibraryFactory() android.Module {
|
||||||
m := &syspropLibrary{}
|
m := &syspropLibrary{}
|
||||||
|
|
||||||
m.AddProperties(
|
m.AddProperties(
|
||||||
&m.commonProperties,
|
&m.properties,
|
||||||
&m.syspropLibraryProperties,
|
|
||||||
)
|
)
|
||||||
m.InitSdkLibraryProperties()
|
android.InitAndroidModule(m)
|
||||||
m.SetNoDist()
|
|
||||||
android.InitAndroidMultiTargetsArchModule(m, android.DeviceSupported, "common")
|
|
||||||
android.AddLoadHook(m, func(ctx android.LoadHookContext) { syspropLibraryHook(ctx, m) })
|
android.AddLoadHook(m, func(ctx android.LoadHookContext) { syspropLibraryHook(ctx, m) })
|
||||||
android.AddLoadHook(m, func(ctx android.LoadHookContext) { m.SdkLibrary.CreateInternalModules(ctx) })
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
|
func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
|
||||||
if len(m.commonProperties.Srcs) == 0 {
|
if len(m.properties.Srcs) == 0 {
|
||||||
ctx.PropertyErrorf("srcs", "sysprop_library must specify srcs")
|
ctx.PropertyErrorf("srcs", "sysprop_library must specify srcs")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(m.syspropLibraryProperties.Api_packages) == 0 {
|
missing_api := false
|
||||||
ctx.PropertyErrorf("api_packages", "sysprop_library must specify api_packages")
|
|
||||||
|
for _, txt := range []string{"-current.txt", "-latest.txt"} {
|
||||||
|
path := path.Join(ctx.ModuleDir(), "api", m.BaseModuleName()+txt)
|
||||||
|
file := android.ExistentPathForSource(ctx, path)
|
||||||
|
if !file.Valid() {
|
||||||
|
ctx.ModuleErrorf("API file %#v doesn't exist", path)
|
||||||
|
missing_api = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if missing_api {
|
||||||
|
script := "build/soong/scripts/gen-sysprop-api-files.sh"
|
||||||
|
p := android.ExistentPathForSource(ctx, script)
|
||||||
|
|
||||||
|
if !p.Valid() {
|
||||||
|
panic(fmt.Sprintf("script file %s doesn't exist", script))
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.ModuleErrorf("One or more api files are missing. "+
|
||||||
|
"You can create them by:\n"+
|
||||||
|
"%s %q %q", script, ctx.ModuleDir(), m.BaseModuleName())
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
socSpecific := ctx.SocSpecific()
|
socSpecific := ctx.SocSpecific()
|
||||||
deviceSpecific := ctx.DeviceSpecific()
|
deviceSpecific := ctx.DeviceSpecific()
|
||||||
productSpecific := ctx.ProductSpecific()
|
productSpecific := ctx.ProductSpecific()
|
||||||
|
|
||||||
owner := m.syspropLibraryProperties.Property_owner
|
owner := m.properties.Property_owner
|
||||||
|
stub := "sysprop-library-stub-"
|
||||||
|
|
||||||
switch owner {
|
switch owner {
|
||||||
case "Platform":
|
case "Platform":
|
||||||
// Every partition can access platform-defined properties
|
// Every partition can access platform-defined properties
|
||||||
break
|
stub += "platform"
|
||||||
case "Vendor":
|
case "Vendor":
|
||||||
// System can't access vendor's properties
|
// System can't access vendor's properties
|
||||||
if !socSpecific && !deviceSpecific && !productSpecific {
|
if !socSpecific && !deviceSpecific && !productSpecific {
|
||||||
ctx.ModuleErrorf("None of soc_specific, device_specific, product_specific is true. " +
|
ctx.ModuleErrorf("None of soc_specific, device_specific, product_specific is true. " +
|
||||||
"System can't access sysprop_library owned by Vendor")
|
"System can't access sysprop_library owned by Vendor")
|
||||||
}
|
}
|
||||||
|
stub += "vendor"
|
||||||
case "Odm":
|
case "Odm":
|
||||||
// Only vendor can access Odm-defined properties
|
// Only vendor can access Odm-defined properties
|
||||||
if !socSpecific && !deviceSpecific {
|
if !socSpecific && !deviceSpecific {
|
||||||
ctx.ModuleErrorf("Neither soc_speicifc nor device_specific is true. " +
|
ctx.ModuleErrorf("Neither soc_speicifc nor device_specific is true. " +
|
||||||
"Odm-defined properties should be accessed only in Vendor or Odm")
|
"Odm-defined properties should be accessed only in Vendor or Odm")
|
||||||
}
|
}
|
||||||
|
stub += "vendor"
|
||||||
default:
|
default:
|
||||||
ctx.PropertyErrorf("property_owner",
|
ctx.PropertyErrorf("property_owner",
|
||||||
"Unknown value %s: must be one of Platform, Vendor or Odm", owner)
|
"Unknown value %s: must be one of Platform, Vendor or Odm", owner)
|
||||||
|
@ -117,17 +240,23 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
|
||||||
|
|
||||||
ccProps := struct {
|
ccProps := struct {
|
||||||
Name *string
|
Name *string
|
||||||
|
Srcs []string
|
||||||
Soc_specific *bool
|
Soc_specific *bool
|
||||||
Device_specific *bool
|
Device_specific *bool
|
||||||
Product_specific *bool
|
Product_specific *bool
|
||||||
Sysprop struct {
|
Sysprop struct {
|
||||||
Platform *bool
|
Platform *bool
|
||||||
}
|
}
|
||||||
Header_libs []string
|
Header_libs []string
|
||||||
Shared_libs []string
|
Shared_libs []string
|
||||||
|
Required []string
|
||||||
|
Recovery *bool
|
||||||
|
Recovery_available *bool
|
||||||
|
Vendor_available *bool
|
||||||
}{}
|
}{}
|
||||||
|
|
||||||
ccProps.Name = proptools.StringPtr(m.CcModuleName())
|
ccProps.Name = proptools.StringPtr(m.CcModuleName())
|
||||||
|
ccProps.Srcs = m.properties.Srcs
|
||||||
ccProps.Soc_specific = proptools.BoolPtr(socSpecific)
|
ccProps.Soc_specific = proptools.BoolPtr(socSpecific)
|
||||||
ccProps.Device_specific = proptools.BoolPtr(deviceSpecific)
|
ccProps.Device_specific = proptools.BoolPtr(deviceSpecific)
|
||||||
ccProps.Product_specific = proptools.BoolPtr(productSpecific)
|
ccProps.Product_specific = proptools.BoolPtr(productSpecific)
|
||||||
|
@ -135,5 +264,41 @@ func syspropLibraryHook(ctx android.LoadHookContext, m *syspropLibrary) {
|
||||||
ccProps.Header_libs = []string{"libbase_headers"}
|
ccProps.Header_libs = []string{"libbase_headers"}
|
||||||
ccProps.Shared_libs = []string{"liblog"}
|
ccProps.Shared_libs = []string{"liblog"}
|
||||||
|
|
||||||
ctx.CreateModule(android.ModuleFactoryAdaptor(cc.LibraryFactory), &m.commonProperties, &ccProps)
|
// add sysprop_library module to perform check API
|
||||||
|
ccProps.Required = []string{m.Name()}
|
||||||
|
ccProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
|
||||||
|
ccProps.Recovery_available = m.properties.Recovery_available
|
||||||
|
ccProps.Vendor_available = m.properties.Vendor_available
|
||||||
|
|
||||||
|
ctx.CreateModule(android.ModuleFactoryAdaptor(cc.LibraryFactory), &ccProps)
|
||||||
|
|
||||||
|
javaProps := struct {
|
||||||
|
Name *string
|
||||||
|
Srcs []string
|
||||||
|
Soc_specific *bool
|
||||||
|
Device_specific *bool
|
||||||
|
Product_specific *bool
|
||||||
|
Sysprop struct {
|
||||||
|
Platform *bool
|
||||||
|
}
|
||||||
|
Required []string
|
||||||
|
Sdk_version *string
|
||||||
|
Installable *bool
|
||||||
|
Libs []string
|
||||||
|
}{}
|
||||||
|
|
||||||
|
javaProps.Name = proptools.StringPtr(m.BaseModuleName())
|
||||||
|
javaProps.Srcs = m.properties.Srcs
|
||||||
|
javaProps.Soc_specific = proptools.BoolPtr(socSpecific)
|
||||||
|
javaProps.Device_specific = proptools.BoolPtr(deviceSpecific)
|
||||||
|
javaProps.Product_specific = proptools.BoolPtr(productSpecific)
|
||||||
|
javaProps.Installable = m.properties.Installable
|
||||||
|
|
||||||
|
// add sysprop_library module to perform check API
|
||||||
|
javaProps.Required = []string{m.Name()}
|
||||||
|
javaProps.Sdk_version = proptools.StringPtr("core_current")
|
||||||
|
javaProps.Sysprop.Platform = proptools.BoolPtr(owner == "Platform")
|
||||||
|
javaProps.Libs = []string{stub}
|
||||||
|
|
||||||
|
ctx.CreateModule(android.ModuleFactoryAdaptor(java.LibraryFactory), &javaProps)
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,16 +57,11 @@ func testContext(config android.Config, bp string,
|
||||||
|
|
||||||
ctx := android.NewTestArchContext()
|
ctx := android.NewTestArchContext()
|
||||||
ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(java.AndroidAppFactory))
|
ctx.RegisterModuleType("android_app", android.ModuleFactoryAdaptor(java.AndroidAppFactory))
|
||||||
ctx.RegisterModuleType("droiddoc_template", android.ModuleFactoryAdaptor(java.ExportedDroiddocDirFactory))
|
|
||||||
ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(java.LibraryFactory))
|
ctx.RegisterModuleType("java_library", android.ModuleFactoryAdaptor(java.LibraryFactory))
|
||||||
ctx.RegisterModuleType("java_system_modules", android.ModuleFactoryAdaptor(java.SystemModulesFactory))
|
ctx.RegisterModuleType("java_system_modules", android.ModuleFactoryAdaptor(java.SystemModulesFactory))
|
||||||
ctx.RegisterModuleType("prebuilt_apis", android.ModuleFactoryAdaptor(java.PrebuiltApisFactory))
|
|
||||||
ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
|
ctx.PreArchMutators(android.RegisterPrebuiltsPreArchMutators)
|
||||||
ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
|
ctx.PreArchMutators(android.RegisterPrebuiltsPostDepsMutators)
|
||||||
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
|
ctx.PreArchMutators(android.RegisterDefaultsPreArchMutators)
|
||||||
ctx.PreArchMutators(func(ctx android.RegisterMutatorsContext) {
|
|
||||||
ctx.TopDown("prebuilt_apis", java.PrebuiltApisMutator).Parallel()
|
|
||||||
})
|
|
||||||
|
|
||||||
ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
|
ctx.RegisterModuleType("cc_library", android.ModuleFactoryAdaptor(cc.LibraryFactory))
|
||||||
ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(cc.LibraryHeaderFactory))
|
ctx.RegisterModuleType("cc_library_headers", android.ModuleFactoryAdaptor(cc.LibraryHeaderFactory))
|
||||||
|
@ -91,45 +86,20 @@ func testContext(config android.Config, bp string,
|
||||||
bp += cc.GatherRequiredDepsForTest(android.Android)
|
bp += cc.GatherRequiredDepsForTest(android.Android)
|
||||||
|
|
||||||
mockFS := map[string][]byte{
|
mockFS := map[string][]byte{
|
||||||
"Android.bp": []byte(bp),
|
"Android.bp": []byte(bp),
|
||||||
"a.java": nil,
|
"a.java": nil,
|
||||||
"b.java": nil,
|
"b.java": nil,
|
||||||
"c.java": nil,
|
"c.java": nil,
|
||||||
"d.cpp": nil,
|
"d.cpp": nil,
|
||||||
"api/current.txt": nil,
|
"api/sysprop-platform-current.txt": nil,
|
||||||
"api/removed.txt": nil,
|
"api/sysprop-platform-latest.txt": nil,
|
||||||
"api/system-current.txt": nil,
|
"api/sysprop-platform-on-product-current.txt": nil,
|
||||||
"api/system-removed.txt": nil,
|
"api/sysprop-platform-on-product-latest.txt": nil,
|
||||||
"api/test-current.txt": nil,
|
"api/sysprop-vendor-current.txt": nil,
|
||||||
"api/test-removed.txt": nil,
|
"api/sysprop-vendor-latest.txt": nil,
|
||||||
"framework/aidl/a.aidl": nil,
|
"api/sysprop-odm-current.txt": nil,
|
||||||
|
"api/sysprop-odm-latest.txt": nil,
|
||||||
"prebuilts/sdk/current/core/android.jar": nil,
|
"framework/aidl/a.aidl": nil,
|
||||||
"prebuilts/sdk/current/public/android.jar": nil,
|
|
||||||
"prebuilts/sdk/current/public/framework.aidl": nil,
|
|
||||||
"prebuilts/sdk/current/public/core.jar": nil,
|
|
||||||
"prebuilts/sdk/current/system/android.jar": nil,
|
|
||||||
"prebuilts/sdk/current/test/android.jar": nil,
|
|
||||||
"prebuilts/sdk/28/public/api/sysprop-platform.txt": nil,
|
|
||||||
"prebuilts/sdk/28/system/api/sysprop-platform.txt": nil,
|
|
||||||
"prebuilts/sdk/28/test/api/sysprop-platform.txt": nil,
|
|
||||||
"prebuilts/sdk/28/public/api/sysprop-platform-removed.txt": nil,
|
|
||||||
"prebuilts/sdk/28/system/api/sysprop-platform-removed.txt": nil,
|
|
||||||
"prebuilts/sdk/28/test/api/sysprop-platform-removed.txt": nil,
|
|
||||||
"prebuilts/sdk/28/public/api/sysprop-platform-on-product.txt": nil,
|
|
||||||
"prebuilts/sdk/28/system/api/sysprop-platform-on-product.txt": nil,
|
|
||||||
"prebuilts/sdk/28/test/api/sysprop-platform-on-product.txt": nil,
|
|
||||||
"prebuilts/sdk/28/public/api/sysprop-platform-on-product-removed.txt": nil,
|
|
||||||
"prebuilts/sdk/28/system/api/sysprop-platform-on-product-removed.txt": nil,
|
|
||||||
"prebuilts/sdk/28/test/api/sysprop-platform-on-product-removed.txt": nil,
|
|
||||||
"prebuilts/sdk/28/public/api/sysprop-vendor.txt": nil,
|
|
||||||
"prebuilts/sdk/28/system/api/sysprop-vendor.txt": nil,
|
|
||||||
"prebuilts/sdk/28/test/api/sysprop-vendor.txt": nil,
|
|
||||||
"prebuilts/sdk/28/public/api/sysprop-vendor-removed.txt": nil,
|
|
||||||
"prebuilts/sdk/28/system/api/sysprop-vendor-removed.txt": nil,
|
|
||||||
"prebuilts/sdk/28/test/api/sysprop-vendor-removed.txt": nil,
|
|
||||||
"prebuilts/sdk/tools/core-lambda-stubs.jar": nil,
|
|
||||||
"prebuilts/sdk/Android.bp": []byte(`prebuilt_apis { name: "sdk", api_dirs: ["28", "current"],}`),
|
|
||||||
|
|
||||||
// For framework-res, which is an implicit dependency for framework
|
// For framework-res, which is an implicit dependency for framework
|
||||||
"AndroidManifest.xml": nil,
|
"AndroidManifest.xml": nil,
|
||||||
|
@ -155,6 +125,7 @@ func testContext(config android.Config, bp string,
|
||||||
|
|
||||||
"android/sysprop/PlatformProperties.sysprop": nil,
|
"android/sysprop/PlatformProperties.sysprop": nil,
|
||||||
"com/android/VendorProperties.sysprop": nil,
|
"com/android/VendorProperties.sysprop": nil,
|
||||||
|
"com/android2/OdmProperties.sysprop": nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range fs {
|
for k, v := range fs {
|
||||||
|
@ -168,7 +139,7 @@ func testContext(config android.Config, bp string,
|
||||||
|
|
||||||
func run(t *testing.T, ctx *android.TestContext, config android.Config) {
|
func run(t *testing.T, ctx *android.TestContext, config android.Config) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
_, errs := ctx.ParseFileList(".", []string{"Android.bp", "prebuilts/sdk/Android.bp"})
|
_, errs := ctx.ParseFileList(".", []string{"Android.bp"})
|
||||||
android.FailIfErrored(t, errs)
|
android.FailIfErrored(t, errs)
|
||||||
_, errs = ctx.PrepareBuildActions(config)
|
_, errs = ctx.PrepareBuildActions(config)
|
||||||
android.FailIfErrored(t, errs)
|
android.FailIfErrored(t, errs)
|
||||||
|
@ -221,6 +192,14 @@ func TestSyspropLibrary(t *testing.T) {
|
||||||
vendor_available: true,
|
vendor_available: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sysprop_library {
|
||||||
|
name: "sysprop-odm",
|
||||||
|
srcs: ["com/android2/OdmProperties.sysprop"],
|
||||||
|
api_packages: ["com.android2"],
|
||||||
|
property_owner: "Odm",
|
||||||
|
device_specific: true,
|
||||||
|
}
|
||||||
|
|
||||||
java_library {
|
java_library {
|
||||||
name: "java-platform",
|
name: "java-platform",
|
||||||
srcs: ["c.java"],
|
srcs: ["c.java"],
|
||||||
|
@ -288,20 +267,40 @@ func TestSyspropLibrary(t *testing.T) {
|
||||||
name: "liblog",
|
name: "liblog",
|
||||||
symbol_file: "",
|
symbol_file: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
java_library {
|
||||||
|
name: "sysprop-library-stub-platform",
|
||||||
|
sdk_version: "core_current",
|
||||||
|
}
|
||||||
|
|
||||||
|
java_library {
|
||||||
|
name: "sysprop-library-stub-vendor",
|
||||||
|
soc_specific: true,
|
||||||
|
sdk_version: "core_current",
|
||||||
|
}
|
||||||
`)
|
`)
|
||||||
|
|
||||||
|
// Check for generated cc_library
|
||||||
|
for _, variant := range []string{
|
||||||
|
"android_arm_armv7-a-neon_vendor_shared",
|
||||||
|
"android_arm_armv7-a-neon_vendor_static",
|
||||||
|
"android_arm64_armv8-a_vendor_shared",
|
||||||
|
"android_arm64_armv8-a_vendor_static",
|
||||||
|
} {
|
||||||
|
ctx.ModuleForTests("libsysprop-platform", variant)
|
||||||
|
ctx.ModuleForTests("libsysprop-vendor", variant)
|
||||||
|
ctx.ModuleForTests("libsysprop-odm", variant)
|
||||||
|
}
|
||||||
|
|
||||||
for _, variant := range []string{
|
for _, variant := range []string{
|
||||||
"android_arm_armv7-a-neon_core_shared",
|
"android_arm_armv7-a-neon_core_shared",
|
||||||
"android_arm_armv7-a-neon_core_static",
|
"android_arm_armv7-a-neon_core_static",
|
||||||
"android_arm_armv7-a-neon_vendor_shared",
|
|
||||||
"android_arm_armv7-a-neon_vendor_static",
|
|
||||||
"android_arm64_armv8-a_core_shared",
|
"android_arm64_armv8-a_core_shared",
|
||||||
"android_arm64_armv8-a_core_static",
|
"android_arm64_armv8-a_core_static",
|
||||||
"android_arm64_armv8-a_vendor_shared",
|
|
||||||
"android_arm64_armv8-a_vendor_static",
|
|
||||||
} {
|
} {
|
||||||
// Check for generated cc_library
|
|
||||||
ctx.ModuleForTests("libsysprop-platform", variant)
|
ctx.ModuleForTests("libsysprop-platform", variant)
|
||||||
|
|
||||||
|
// core variant of vendor-owned sysprop_library is for product
|
||||||
ctx.ModuleForTests("libsysprop-vendor", variant)
|
ctx.ModuleForTests("libsysprop-vendor", variant)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue