You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
454 lines
17 KiB
454 lines
17 KiB
// Copyright (C) 2021 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.
|
|
|
|
package aidl
|
|
|
|
import (
|
|
"android/soong/android"
|
|
"android/soong/cc"
|
|
"android/soong/java"
|
|
"android/soong/rust"
|
|
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/google/blueprint/proptools"
|
|
)
|
|
|
|
func addLibrary(mctx android.LoadHookContext, i *aidlInterface, version string, lang string) string {
|
|
if lang == langJava {
|
|
return addJavaLibrary(mctx, i, version)
|
|
} else if lang == langRust {
|
|
return addRustLibrary(mctx, i, version)
|
|
}
|
|
return addCppLibrary(mctx, i, version, lang)
|
|
}
|
|
|
|
func addCppLibrary(mctx android.LoadHookContext, i *aidlInterface, version string, lang string) string {
|
|
cppSourceGen := i.versionedName(version) + "-" + lang + "-source"
|
|
cppModuleGen := i.versionedName(version) + "-" + lang
|
|
|
|
srcs, aidlRoot := i.srcsForVersion(mctx, version)
|
|
if len(srcs) == 0 {
|
|
// This can happen when the version is about to be frozen; the version
|
|
// directory is created but API dump hasn't been copied there.
|
|
// Don't create a library for the yet-to-be-frozen version.
|
|
return ""
|
|
}
|
|
|
|
var overrideVndkProperties cc.VndkProperties
|
|
|
|
if !i.isModuleForVndk(version) {
|
|
// We only want the VNDK to include the latest interface. For interfaces in
|
|
// development, they will be frozen, so we put their latest version in the
|
|
// VNDK. For interfaces which are already frozen, we put their latest version
|
|
// in the VNDK, and when that version is frozen, the version in the VNDK can
|
|
// be updated. Otherwise, we remove this library from the VNDK, to avoid adding
|
|
// multiple versions of the same library to the VNDK.
|
|
overrideVndkProperties.Vndk.Enabled = proptools.BoolPtr(false)
|
|
overrideVndkProperties.Vndk.Support_system_process = proptools.BoolPtr(false)
|
|
}
|
|
|
|
var commonProperties *CommonNativeBackendProperties
|
|
if lang == langCpp {
|
|
commonProperties = &i.properties.Backend.Cpp.CommonNativeBackendProperties
|
|
} else if lang == langNdk || lang == langNdkPlatform {
|
|
commonProperties = &i.properties.Backend.Ndk.CommonNativeBackendProperties
|
|
}
|
|
|
|
genLog := proptools.Bool(commonProperties.Gen_log)
|
|
genTrace := proptools.Bool(i.properties.Gen_trace)
|
|
|
|
mctx.CreateModule(aidlGenFactory, &nameProperties{
|
|
Name: proptools.StringPtr(cppSourceGen),
|
|
}, &aidlGenProperties{
|
|
Srcs: srcs,
|
|
AidlRoot: aidlRoot,
|
|
IsToT: version == i.nextVersion(),
|
|
ImportsWithoutVersion: i.properties.ImportsWithoutVersion,
|
|
Stability: i.properties.Stability,
|
|
Lang: lang,
|
|
BaseName: i.ModuleBase.Name(),
|
|
GenLog: genLog,
|
|
Version: i.versionForAidlGenRule(version),
|
|
GenTrace: genTrace,
|
|
Unstable: i.properties.Unstable,
|
|
Visibility: srcsVisibility(mctx, lang),
|
|
Flags: i.flagsForAidlGenRule(version),
|
|
})
|
|
|
|
importExportDependencies := []string{}
|
|
var sharedLibDependency []string
|
|
var headerLibs []string
|
|
var sdkVersion *string
|
|
var minSdkVersion *string
|
|
var stl *string
|
|
var cpp_std *string
|
|
var hostSupported *bool
|
|
var addCflags []string
|
|
|
|
if lang == langCpp {
|
|
importExportDependencies = append(importExportDependencies, "libbinder", "libutils")
|
|
if genTrace {
|
|
sharedLibDependency = append(sharedLibDependency, "libcutils")
|
|
}
|
|
hostSupported = i.properties.Host_supported
|
|
minSdkVersion = i.properties.Backend.Cpp.Min_sdk_version
|
|
} else if lang == langNdk {
|
|
importExportDependencies = append(importExportDependencies, "libbinder_ndk")
|
|
if genTrace {
|
|
sharedLibDependency = append(sharedLibDependency, "libandroid")
|
|
}
|
|
sdkVersion = proptools.StringPtr("current")
|
|
stl = proptools.StringPtr("c++_shared")
|
|
minSdkVersion = i.properties.Backend.Ndk.Min_sdk_version
|
|
} else if lang == langNdkPlatform {
|
|
importExportDependencies = append(importExportDependencies, "libbinder_ndk")
|
|
if genTrace {
|
|
headerLibs = append(headerLibs, "libandroid_aidltrace")
|
|
sharedLibDependency = append(sharedLibDependency, "libcutils")
|
|
}
|
|
hostSupported = i.properties.Host_supported
|
|
addCflags = append(addCflags, "-DBINDER_STABILITY_SUPPORT")
|
|
minSdkVersion = i.properties.Backend.Ndk.Min_sdk_version
|
|
} else {
|
|
panic("Unrecognized language: " + lang)
|
|
}
|
|
|
|
vendorAvailable := i.properties.Vendor_available
|
|
odmAvailable := i.properties.Odm_available
|
|
productAvailable := i.properties.Product_available
|
|
if lang == langCpp {
|
|
// Vendor and product modules cannot use the libbinder (cpp) backend of AIDL in a
|
|
// way that is stable. So, in order to prevent accidental usage of these library by
|
|
// vendor and product forcibly disabling this version of the library.
|
|
//
|
|
// It may be the case in the future that we will want to enable this (if some generic
|
|
// helper should be used by both libbinder vendor things using /dev/vndbinder as well
|
|
// as those things using /dev/binder + libbinder_ndk to talk to stable interfaces).
|
|
if "vintf" == proptools.String(i.properties.Stability) {
|
|
overrideVndkProperties.Vndk.Private = proptools.BoolPtr(true)
|
|
}
|
|
// As libbinder is not available for the product processes, we must not create
|
|
// product variant for the aidl_interface
|
|
productAvailable = nil
|
|
}
|
|
|
|
if lang == langNdk {
|
|
// TODO(b/121157555): when the NDK variant is its own variant, these wouldn't interact,
|
|
// but we can't create a vendor or product version of an NDK variant
|
|
//
|
|
// nil (unspecified) is used instead of false so that this can't conflict with
|
|
// 'vendor: true', for instance.
|
|
vendorAvailable = nil
|
|
odmAvailable = nil
|
|
productAvailable = nil
|
|
overrideVndkProperties.Vndk.Enabled = proptools.BoolPtr(false)
|
|
overrideVndkProperties.Vndk.Support_system_process = proptools.BoolPtr(false)
|
|
}
|
|
|
|
mctx.CreateModule(aidlImplementationGeneratorFactory, &nameProperties{
|
|
Name: proptools.StringPtr(cppModuleGen + "-generator"),
|
|
}, &aidlImplementationGeneratorProperties{
|
|
Lang: lang,
|
|
AidlInterfaceName: i.ModuleBase.Name(),
|
|
Version: version,
|
|
ModuleProperties: []interface{}{
|
|
&ccProperties{
|
|
Name: proptools.StringPtr(cppModuleGen),
|
|
Vendor_available: vendorAvailable,
|
|
Odm_available: odmAvailable,
|
|
Product_available: productAvailable,
|
|
Host_supported: hostSupported,
|
|
Defaults: []string{"aidl-cpp-module-defaults"},
|
|
Double_loadable: i.properties.Double_loadable,
|
|
Generated_sources: []string{cppSourceGen},
|
|
Generated_headers: []string{cppSourceGen},
|
|
Export_generated_headers: []string{cppSourceGen},
|
|
Shared_libs: append(importExportDependencies, sharedLibDependency...),
|
|
Header_libs: headerLibs,
|
|
Export_shared_lib_headers: importExportDependencies,
|
|
Sdk_version: sdkVersion,
|
|
Stl: stl,
|
|
Cpp_std: cpp_std,
|
|
Cflags: append(addCflags, "-Wextra", "-Wall", "-Werror", "-Wextra-semi"),
|
|
Apex_available: commonProperties.Apex_available,
|
|
Min_sdk_version: minSdkVersion,
|
|
UseApexNameMacro: true,
|
|
Target: ccTargetProperties{
|
|
// Currently necessary for host builds
|
|
// TODO(b/31559095): bionic on host should define this
|
|
// TODO(b/146436251): default isn't applied because the module is created
|
|
// in PreArchMutators, when import behavior becomes explicit, the logic can
|
|
// be moved back to LoadHook
|
|
Host: hostProperties{Cflags: []string{
|
|
"-D__INTRODUCED_IN(n)=",
|
|
"-D__assert(a,b,c)=",
|
|
// We want all the APIs to be available on the host.
|
|
"-D__ANDROID_API__=10000"}},
|
|
Darwin: perTargetProperties{Enabled: proptools.BoolPtr(false)}},
|
|
Tidy: proptools.BoolPtr(true),
|
|
// Do the tidy check only for the generated headers
|
|
Tidy_flags: []string{"--header-filter=" + android.PathForOutput(mctx).String() + ".*"},
|
|
Tidy_checks_as_errors: []string{"*"},
|
|
}, &i.properties.VndkProperties,
|
|
&commonProperties.VndkProperties,
|
|
&overrideVndkProperties,
|
|
},
|
|
})
|
|
|
|
return cppModuleGen
|
|
}
|
|
|
|
func addJavaLibrary(mctx android.LoadHookContext, i *aidlInterface, version string) string {
|
|
javaSourceGen := i.versionedName(version) + "-java-source"
|
|
javaModuleGen := i.versionedName(version) + "-java"
|
|
srcs, aidlRoot := i.srcsForVersion(mctx, version)
|
|
if len(srcs) == 0 {
|
|
// This can happen when the version is about to be frozen; the version
|
|
// directory is created but API dump hasn't been copied there.
|
|
// Don't create a library for the yet-to-be-frozen version.
|
|
return ""
|
|
}
|
|
|
|
sdkVersion := i.properties.Backend.Java.Sdk_version
|
|
if !proptools.Bool(i.properties.Backend.Java.Platform_apis) && sdkVersion == nil {
|
|
// platform apis requires no default
|
|
sdkVersion = proptools.StringPtr("system_current")
|
|
}
|
|
|
|
mctx.CreateModule(aidlGenFactory, &nameProperties{
|
|
Name: proptools.StringPtr(javaSourceGen),
|
|
}, &aidlGenProperties{
|
|
Srcs: srcs,
|
|
AidlRoot: aidlRoot,
|
|
IsToT: version == i.nextVersion(),
|
|
ImportsWithoutVersion: i.properties.ImportsWithoutVersion,
|
|
Stability: i.properties.Stability,
|
|
Lang: langJava,
|
|
BaseName: i.ModuleBase.Name(),
|
|
Version: i.versionForAidlGenRule(version),
|
|
GenTrace: proptools.Bool(i.properties.Gen_trace),
|
|
Unstable: i.properties.Unstable,
|
|
Visibility: srcsVisibility(mctx, langJava),
|
|
Flags: i.flagsForAidlGenRule(version),
|
|
})
|
|
|
|
mctx.CreateModule(aidlImplementationGeneratorFactory, &nameProperties{
|
|
Name: proptools.StringPtr(javaModuleGen + "-generator"),
|
|
}, &aidlImplementationGeneratorProperties{
|
|
Lang: langJava,
|
|
AidlInterfaceName: i.ModuleBase.Name(),
|
|
Version: version,
|
|
ModuleProperties: []interface{}{&javaProperties{
|
|
Name: proptools.StringPtr(javaModuleGen),
|
|
Installable: proptools.BoolPtr(true),
|
|
Defaults: []string{"aidl-java-module-defaults"},
|
|
Sdk_version: sdkVersion,
|
|
Platform_apis: i.properties.Backend.Java.Platform_apis,
|
|
Srcs: []string{":" + javaSourceGen},
|
|
Apex_available: i.properties.Backend.Java.Apex_available,
|
|
Min_sdk_version: i.properties.Backend.Java.Min_sdk_version,
|
|
}},
|
|
})
|
|
|
|
return javaModuleGen
|
|
}
|
|
|
|
func addRustLibrary(mctx android.LoadHookContext, i *aidlInterface, version string) string {
|
|
rustSourceGen := i.versionedName(version) + "-rust-source"
|
|
rustModuleGen := i.versionedName(version) + "-rust"
|
|
srcs, aidlRoot := i.srcsForVersion(mctx, version)
|
|
if len(srcs) == 0 {
|
|
// This can happen when the version is about to be frozen; the version
|
|
// directory is created but API dump hasn't been copied there.
|
|
// Don't create a library for the yet-to-be-frozen version.
|
|
return ""
|
|
}
|
|
|
|
mctx.CreateModule(aidlGenFactory, &nameProperties{
|
|
Name: proptools.StringPtr(rustSourceGen),
|
|
}, &aidlGenProperties{
|
|
Srcs: srcs,
|
|
AidlRoot: aidlRoot,
|
|
ImportsWithoutVersion: i.properties.ImportsWithoutVersion,
|
|
IsToT: version == i.nextVersion(),
|
|
Stability: i.properties.Stability,
|
|
Lang: langRust,
|
|
BaseName: i.ModuleBase.Name(),
|
|
Version: i.versionForAidlGenRule(version),
|
|
Unstable: i.properties.Unstable,
|
|
Visibility: srcsVisibility(mctx, langRust),
|
|
Flags: i.flagsForAidlGenRule(version),
|
|
})
|
|
|
|
versionedRustName := fixRustName(i.versionedName(version))
|
|
rustCrateName := fixRustName(i.ModuleBase.Name())
|
|
|
|
mctx.CreateModule(aidlRustLibraryFactory, &rustProperties{
|
|
Name: proptools.StringPtr(rustModuleGen),
|
|
Crate_name: rustCrateName,
|
|
Stem: proptools.StringPtr("lib" + versionedRustName),
|
|
Defaults: []string{"aidl-rust-module-defaults"},
|
|
Host_supported: i.properties.Host_supported,
|
|
Apex_available: i.properties.Backend.Rust.Apex_available,
|
|
Target: rustTargetProperties{Darwin: perTargetProperties{Enabled: proptools.BoolPtr(false)}},
|
|
}, &rust.SourceProviderProperties{
|
|
Source_stem: proptools.StringPtr(versionedRustName),
|
|
}, &aidlRustSourceProviderProperties{
|
|
SourceGen: rustSourceGen,
|
|
Imports: i.properties.Imports,
|
|
Version: version,
|
|
AidlInterfaceName: i.ModuleBase.Name(),
|
|
})
|
|
|
|
return rustModuleGen
|
|
}
|
|
|
|
// This function returns module name with version. Assume that there is foo of which latest version is 2
|
|
// Version -> Module name
|
|
// "1"->foo-V1
|
|
// "2"->foo-V2
|
|
// "3"->foo-V3
|
|
// And assume that there is 'bar' which is an 'unstable' interface.
|
|
// ""->bar
|
|
func (i *aidlInterface) versionedName(version string) string {
|
|
name := i.ModuleBase.Name()
|
|
if version == "" {
|
|
return name
|
|
}
|
|
return name + "-V" + version
|
|
}
|
|
|
|
func (i *aidlInterface) srcsForVersion(mctx android.LoadHookContext, version string) (srcs []string, aidlRoot string) {
|
|
if version == i.nextVersion() {
|
|
return i.properties.Srcs, i.properties.Local_include_dir
|
|
} else {
|
|
aidlRoot = filepath.Join(aidlApiDir, i.ModuleBase.Name(), version)
|
|
full_paths, err := mctx.GlobWithDeps(filepath.Join(mctx.ModuleDir(), aidlRoot, "**/*.aidl"), nil)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
for _, path := range full_paths {
|
|
// Here, we need path local to the module
|
|
srcs = append(srcs, strings.TrimPrefix(path, mctx.ModuleDir()+"/"))
|
|
}
|
|
return srcs, aidlRoot
|
|
}
|
|
}
|
|
|
|
func (i *aidlInterface) versionForAidlGenRule(version string) string {
|
|
if !i.hasVersion() {
|
|
return ""
|
|
}
|
|
return version
|
|
}
|
|
|
|
func (i *aidlInterface) flagsForAidlGenRule(version string) (flags []string) {
|
|
flags = append(flags, i.properties.Flags...)
|
|
// For ToT, turn on "-Weverything" (enable all warnings)
|
|
if version == i.nextVersion() {
|
|
flags = append(flags, "-Weverything")
|
|
}
|
|
return
|
|
}
|
|
|
|
func (i *aidlInterface) isModuleForVndk(version string) bool {
|
|
if i.properties.Vndk_use_version != nil {
|
|
if !i.hasVersion() {
|
|
panic("does not make sense, vndk_use_version specififed")
|
|
}
|
|
// Will be exactly one of the version numbers
|
|
return version == *i.properties.Vndk_use_version
|
|
}
|
|
|
|
// For an interface with no versions, this is the ToT interface.
|
|
if !i.hasVersion() {
|
|
return version == i.nextVersion()
|
|
}
|
|
|
|
return version == i.latestVersion()
|
|
}
|
|
|
|
// importing aidl_interface's version | imported aidl_interface | imported aidl_interface's version
|
|
// --------------------------------------------------------------------------------------------------
|
|
// whatever | unstable | unstable version
|
|
// ToT version(including unstable) | whatever | ToT version(unstable if unstable)
|
|
// otherwise | whatever | the latest stable version
|
|
// In the case that import specifies the version which it wants to use, use that version.
|
|
func (i *aidlInterface) getImportWithVersion(version string, anImport string, config android.Config) string {
|
|
if hasVersionSuffix(anImport) {
|
|
return anImport
|
|
}
|
|
other := lookupInterface(anImport, config)
|
|
if proptools.Bool(other.properties.Unstable) {
|
|
return anImport
|
|
}
|
|
if version == i.nextVersion() || !other.hasVersion() {
|
|
return other.versionedName(other.nextVersion())
|
|
}
|
|
return other.versionedName(other.latestVersion())
|
|
}
|
|
|
|
func aidlImplementationGeneratorFactory() android.Module {
|
|
g := &aidlImplementationGenerator{}
|
|
g.AddProperties(&g.properties)
|
|
android.InitAndroidModule(g)
|
|
return g
|
|
}
|
|
|
|
type aidlImplementationGenerator struct {
|
|
android.ModuleBase
|
|
properties aidlImplementationGeneratorProperties
|
|
}
|
|
|
|
type aidlImplementationGeneratorProperties struct {
|
|
Lang string
|
|
AidlInterfaceName string
|
|
Version string
|
|
ModuleProperties []interface{}
|
|
}
|
|
|
|
func (g *aidlImplementationGenerator) DepsMutator(ctx android.BottomUpMutatorContext) {
|
|
}
|
|
|
|
func (g *aidlImplementationGenerator) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|
}
|
|
|
|
func (g *aidlImplementationGenerator) GenerateImplementation(ctx android.TopDownMutatorContext) {
|
|
i := lookupInterface(g.properties.AidlInterfaceName, ctx.Config())
|
|
version := g.properties.Version
|
|
lang := g.properties.Lang
|
|
if g.properties.Lang == langJava {
|
|
imports := make([]string, len(i.properties.Imports))
|
|
for idx, anImport := range i.properties.Imports {
|
|
imports[idx] = i.getImportWithVersion(version, anImport, ctx.Config()) + "-" + langJava
|
|
}
|
|
if p, ok := g.properties.ModuleProperties[0].(*javaProperties); ok {
|
|
p.Static_libs = imports
|
|
}
|
|
ctx.CreateModule(java.LibraryFactory, g.properties.ModuleProperties...)
|
|
} else {
|
|
imports := make([]string, len(i.properties.Imports))
|
|
for idx, anImport := range i.properties.Imports {
|
|
imports[idx] = i.getImportWithVersion(version, anImport, ctx.Config()) + "-" + lang
|
|
}
|
|
if p, ok := g.properties.ModuleProperties[0].(*ccProperties); ok {
|
|
p.Shared_libs = append(p.Shared_libs, imports...)
|
|
p.Export_shared_lib_headers = append(p.Export_shared_lib_headers, imports...)
|
|
}
|
|
ctx.CreateModule(cc.LibraryFactory, g.properties.ModuleProperties...)
|
|
}
|
|
}
|