2019-08-27 21:03:00 +02:00
|
|
|
// Copyright 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.
|
|
|
|
|
|
|
|
package rust
|
|
|
|
|
|
|
|
import (
|
2019-10-18 23:18:45 +02:00
|
|
|
"fmt"
|
2019-08-27 21:03:00 +02:00
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/google/blueprint"
|
|
|
|
"github.com/google/blueprint/proptools"
|
|
|
|
|
|
|
|
"android/soong/android"
|
|
|
|
"android/soong/cc"
|
2020-08-27 13:37:29 +02:00
|
|
|
cc_config "android/soong/cc/config"
|
2019-08-27 21:03:00 +02:00
|
|
|
"android/soong/rust/config"
|
|
|
|
)
|
|
|
|
|
|
|
|
var pctx = android.NewPackageContext("android/soong/rust")
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
// Only allow rust modules to be defined for certain projects
|
|
|
|
|
|
|
|
android.AddNeverAllowRules(
|
|
|
|
android.NeverAllow().
|
2019-09-18 17:42:54 +02:00
|
|
|
NotIn(config.RustAllowedPaths...).
|
|
|
|
ModuleType(config.RustModuleTypes...))
|
2019-08-27 21:03:00 +02:00
|
|
|
|
|
|
|
android.RegisterModuleType("rust_defaults", defaultsFactory)
|
|
|
|
android.PreDepsMutators(func(ctx android.RegisterMutatorsContext) {
|
|
|
|
ctx.BottomUp("rust_libraries", LibraryMutator).Parallel()
|
2020-09-08 18:46:52 +02:00
|
|
|
ctx.BottomUp("rust_stdlinkage", LibstdMutator).Parallel()
|
2020-04-09 15:56:02 +02:00
|
|
|
ctx.BottomUp("rust_begin", BeginMutator).Parallel()
|
2019-08-27 21:03:00 +02:00
|
|
|
})
|
|
|
|
pctx.Import("android/soong/rust/config")
|
2020-08-31 10:06:16 +02:00
|
|
|
pctx.ImportAs("cc_config", "android/soong/cc/config")
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type Flags struct {
|
2020-06-16 16:26:57 +02:00
|
|
|
GlobalRustFlags []string // Flags that apply globally to rust
|
|
|
|
GlobalLinkFlags []string // Flags that apply globally to linker
|
|
|
|
RustFlags []string // Flags that apply to rust
|
|
|
|
LinkFlags []string // Flags that apply to linker
|
2020-06-22 13:28:02 +02:00
|
|
|
ClippyFlags []string // Flags that apply to clippy-driver, during the linting
|
2019-09-20 20:00:37 +02:00
|
|
|
Toolchain config.Toolchain
|
2020-04-09 15:56:02 +02:00
|
|
|
Coverage bool
|
2020-06-22 13:28:02 +02:00
|
|
|
Clippy bool
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type BaseProperties struct {
|
|
|
|
AndroidMkRlibs []string
|
|
|
|
AndroidMkDylibs []string
|
|
|
|
AndroidMkProcMacroLibs []string
|
|
|
|
AndroidMkSharedLibs []string
|
|
|
|
AndroidMkStaticLibs []string
|
2020-07-10 03:03:28 +02:00
|
|
|
|
2020-12-02 15:15:16 +01:00
|
|
|
ImageVariationPrefix string `blueprint:"mutated"`
|
|
|
|
VndkVersion string `blueprint:"mutated"`
|
|
|
|
SubName string `blueprint:"mutated"`
|
|
|
|
|
|
|
|
// Set by imageMutator
|
|
|
|
CoreVariantNeeded bool `blueprint:"mutated"`
|
|
|
|
ExtraVariants []string `blueprint:"mutated"`
|
2020-07-31 19:40:31 +02:00
|
|
|
|
2020-12-04 21:05:43 +01:00
|
|
|
// Minimum sdk version that the artifact should support when it runs as part of mainline modules(APEX).
|
|
|
|
Min_sdk_version *string
|
|
|
|
|
2020-07-10 03:03:28 +02:00
|
|
|
PreventInstall bool
|
|
|
|
HideFromMake bool
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type Module struct {
|
|
|
|
android.ModuleBase
|
|
|
|
android.DefaultableModuleBase
|
2020-11-17 14:21:02 +01:00
|
|
|
android.ApexModuleBase
|
2019-08-27 21:03:00 +02:00
|
|
|
|
2020-12-02 15:15:16 +01:00
|
|
|
VendorProperties cc.VendorProperties
|
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
Properties BaseProperties
|
|
|
|
|
|
|
|
hod android.HostOrDeviceSupported
|
|
|
|
multilib android.Multilib
|
|
|
|
|
2020-12-02 15:15:16 +01:00
|
|
|
makeLinkType string
|
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
compiler compiler
|
2020-04-09 15:56:02 +02:00
|
|
|
coverage *coverage
|
2020-06-22 13:28:02 +02:00
|
|
|
clippy *clippy
|
2019-08-27 21:03:00 +02:00
|
|
|
cachedToolchain config.Toolchain
|
2020-07-08 14:39:44 +02:00
|
|
|
sourceProvider SourceProvider
|
2020-08-05 15:36:19 +02:00
|
|
|
subAndroidMkOnce map[SubAndroidMkProvider]bool
|
2020-07-08 14:39:44 +02:00
|
|
|
|
2020-09-23 18:10:17 +02:00
|
|
|
outputFile android.OptionalPath
|
2020-11-17 14:21:02 +01:00
|
|
|
|
|
|
|
hideApexVariantFromMake bool
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
|
2020-07-10 03:03:28 +02:00
|
|
|
func (mod *Module) OutputFiles(tag string) (android.Paths, error) {
|
|
|
|
switch tag {
|
|
|
|
case "":
|
2020-08-07 00:27:45 +02:00
|
|
|
if mod.sourceProvider != nil && (mod.compiler == nil || mod.compiler.Disabled()) {
|
2020-07-10 03:03:28 +02:00
|
|
|
return mod.sourceProvider.Srcs(), nil
|
|
|
|
} else {
|
|
|
|
if mod.outputFile.Valid() {
|
|
|
|
return android.Paths{mod.outputFile.Path()}, nil
|
|
|
|
}
|
|
|
|
return android.Paths{}, nil
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
return nil, fmt.Errorf("unsupported module reference tag %q", tag)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-18 23:49:46 +02:00
|
|
|
func (mod *Module) SelectedStl() string {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2019-11-21 21:30:50 +01:00
|
|
|
func (mod *Module) NonCcVariants() bool {
|
|
|
|
if mod.compiler != nil {
|
2020-07-31 17:01:18 +02:00
|
|
|
if _, ok := mod.compiler.(libraryInterface); ok {
|
|
|
|
return false
|
2019-11-21 21:30:50 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
panic(fmt.Errorf("NonCcVariants called on non-library module: %q", mod.BaseModuleName()))
|
|
|
|
}
|
|
|
|
|
2019-10-18 23:49:46 +02:00
|
|
|
func (mod *Module) Static() bool {
|
|
|
|
if mod.compiler != nil {
|
|
|
|
if library, ok := mod.compiler.(libraryInterface); ok {
|
|
|
|
return library.static()
|
|
|
|
}
|
|
|
|
}
|
2020-07-31 17:01:18 +02:00
|
|
|
return false
|
2019-10-18 23:49:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) Shared() bool {
|
|
|
|
if mod.compiler != nil {
|
|
|
|
if library, ok := mod.compiler.(libraryInterface); ok {
|
2020-07-31 17:01:18 +02:00
|
|
|
return library.shared()
|
2019-10-18 23:49:46 +02:00
|
|
|
}
|
|
|
|
}
|
2020-07-31 17:01:18 +02:00
|
|
|
return false
|
2019-10-18 23:49:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) Toc() android.OptionalPath {
|
|
|
|
if mod.compiler != nil {
|
|
|
|
if _, ok := mod.compiler.(libraryInterface); ok {
|
|
|
|
return android.OptionalPath{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
panic(fmt.Errorf("Toc() called on non-library module: %q", mod.BaseModuleName()))
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:50:32 +02:00
|
|
|
func (mod *Module) UseSdk() bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2020-12-02 15:15:16 +01:00
|
|
|
// Returns true if the module is using VNDK libraries instead of the libraries in /system/lib or /system/lib64.
|
|
|
|
// "product" and "vendor" variant modules return true for this function.
|
|
|
|
// When BOARD_VNDK_VERSION is set, vendor variants of "vendor_available: true", "vendor: true",
|
|
|
|
// "soc_specific: true" and more vendor installed modules are included here.
|
|
|
|
// When PRODUCT_PRODUCT_VNDK_VERSION is set, product variants of "vendor_available: true" or
|
|
|
|
// "product_specific: true" modules are included here.
|
2019-10-18 23:49:46 +02:00
|
|
|
func (mod *Module) UseVndk() bool {
|
2020-12-02 15:15:16 +01:00
|
|
|
return mod.Properties.VndkVersion != ""
|
2019-10-18 23:49:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) MustUseVendorVariant() bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) IsVndk() bool {
|
2020-12-02 15:15:16 +01:00
|
|
|
// TODO(b/165791368)
|
2019-10-18 23:49:46 +02:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2020-12-02 15:00:51 +01:00
|
|
|
func (mod *Module) IsVndkExt() bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Module) IsVndkPrivate(config android.Config) bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2019-10-18 23:49:46 +02:00
|
|
|
func (mod *Module) SdkVersion() string {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
|
2020-04-07 18:50:32 +02:00
|
|
|
func (mod *Module) AlwaysSdk() bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
Don't create version variants for SDK variants
When a lib has sdk_version set, an SDK variant and a platform variant
are created by the sdkMutator. Then by the versionMutator, if the
library had 'stubs.versions' property, one or more versioned variants
and one impl variant are created for each of the two (SDK and platform)
variants. As a concrete example,
cc_library {
name: "foo",
sdk_version: "current",
stubs: { versions: ["1", "2"], },
}
would create 6 variants:
1) (sdk: "", version: "")
2) (sdk: "", version: "1")
3) (sdk: "", version: "2")
4) (sdk: "sdk", version: "")
5) (sdk: "sdk", version: "1")
6) (sdk: "sdk", version: "2")
This is somewhat uncessary because the need for the SDK mutator is to
have the platform variant (sdk:"") of a lib where sdk_version is unset,
which actually makes sens for the impl variant (version:""), but not
the versioned variants (version:"1" or version:"2").
This is not only unncessary, but also causes duplicate module
definitions in the Make side when doing an unbundled build. Specifically,
The #1 and #4 above both are emitted to Make and get the same name
"foo".
To fix the problem and not to create unnecessary variants, the versioned
variants are no longer created for the sdk variant. So, foo now has
the following variants only.
1) (sdk: "", version: "") // not emitted to Make (by versionMutator)
2) (sdk: "", version: "1") // not emitted to Make (by versionMutator)
3) (sdk: "", version: "2") // emitted to Make (by versionMutator)
4) (sdk: "sdk", version: "") // not emitted to Make (by versionMutator)
Bug: 159106705
Test: Add sdk_version:"minimum" to libnativehelper in libnativehelper/Android.bp.
m SOONG_ALLOW_MISSING_DEPENDENCIES=true TARGET_BUILD_UNBUNDLED=true libnativehelper
Change-Id: I6f02f4189e5504286174ccff1642166da82d00c9
2020-06-16 14:58:53 +02:00
|
|
|
func (mod *Module) IsSdkVariant() bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2020-10-01 22:37:16 +02:00
|
|
|
func (mod *Module) SplitPerApiLevel() bool {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
type Deps struct {
|
|
|
|
Dylibs []string
|
|
|
|
Rlibs []string
|
2020-06-29 23:34:06 +02:00
|
|
|
Rustlibs []string
|
2020-09-08 18:46:52 +02:00
|
|
|
Stdlibs []string
|
2019-08-27 21:03:00 +02:00
|
|
|
ProcMacros []string
|
|
|
|
SharedLibs []string
|
|
|
|
StaticLibs []string
|
2020-11-06 20:56:27 +01:00
|
|
|
HeaderLibs []string
|
2019-08-27 21:03:00 +02:00
|
|
|
|
|
|
|
CrtBegin, CrtEnd string
|
|
|
|
}
|
|
|
|
|
|
|
|
type PathDeps struct {
|
2020-08-25 18:48:19 +02:00
|
|
|
DyLibs RustLibraries
|
|
|
|
RLibs RustLibraries
|
|
|
|
SharedLibs android.Paths
|
|
|
|
StaticLibs android.Paths
|
|
|
|
ProcMacros RustLibraries
|
|
|
|
linkDirs []string
|
|
|
|
depFlags []string
|
|
|
|
linkObjects []string
|
2019-08-27 21:03:00 +02:00
|
|
|
//ReexportedDeps android.Paths
|
2019-09-20 20:00:37 +02:00
|
|
|
|
2020-07-24 22:05:01 +02:00
|
|
|
// Used by bindgen modules which call clang
|
|
|
|
depClangFlags []string
|
|
|
|
depIncludePaths android.Paths
|
2020-08-28 23:00:26 +02:00
|
|
|
depGeneratedHeaders android.Paths
|
2020-07-24 22:05:01 +02:00
|
|
|
depSystemIncludePaths android.Paths
|
|
|
|
|
2020-04-09 15:56:02 +02:00
|
|
|
coverageFiles android.Paths
|
|
|
|
|
2019-09-20 20:00:37 +02:00
|
|
|
CrtBegin android.OptionalPath
|
|
|
|
CrtEnd android.OptionalPath
|
2020-05-16 02:36:30 +02:00
|
|
|
|
|
|
|
// Paths to generated source files
|
2020-12-01 15:25:22 +01:00
|
|
|
SrcDeps android.Paths
|
|
|
|
srcProviderFiles android.Paths
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type RustLibraries []RustLibrary
|
|
|
|
|
|
|
|
type RustLibrary struct {
|
|
|
|
Path android.Path
|
|
|
|
CrateName string
|
|
|
|
}
|
|
|
|
|
|
|
|
type compiler interface {
|
|
|
|
compilerFlags(ctx ModuleContext, flags Flags) Flags
|
|
|
|
compilerProps() []interface{}
|
|
|
|
compile(ctx ModuleContext, flags Flags, deps PathDeps) android.Path
|
|
|
|
compilerDeps(ctx DepsContext, deps Deps) Deps
|
|
|
|
crateName() string
|
|
|
|
|
2019-12-13 04:36:05 +01:00
|
|
|
inData() bool
|
2020-08-27 13:48:36 +02:00
|
|
|
install(ctx ModuleContext)
|
2019-08-27 21:03:00 +02:00
|
|
|
relativeInstallPath() string
|
2020-04-09 15:56:02 +02:00
|
|
|
|
|
|
|
nativeCoverage() bool
|
2020-07-31 19:40:31 +02:00
|
|
|
|
|
|
|
Disabled() bool
|
|
|
|
SetDisabled()
|
2020-08-18 20:31:23 +02:00
|
|
|
|
2020-09-28 19:22:45 +02:00
|
|
|
stdLinkage(ctx *depsContext) RustLinkage
|
2020-04-09 15:56:02 +02:00
|
|
|
}
|
|
|
|
|
2020-06-25 18:34:12 +02:00
|
|
|
type exportedFlagsProducer interface {
|
|
|
|
exportLinkDirs(...string)
|
|
|
|
exportDepFlags(...string)
|
2020-08-25 18:48:19 +02:00
|
|
|
exportLinkObjects(...string)
|
2020-06-25 18:34:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type flagExporter struct {
|
2020-08-25 18:48:19 +02:00
|
|
|
depFlags []string
|
|
|
|
linkDirs []string
|
|
|
|
linkObjects []string
|
2020-06-25 18:34:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (flagExporter *flagExporter) exportLinkDirs(dirs ...string) {
|
|
|
|
flagExporter.linkDirs = android.FirstUniqueStrings(append(flagExporter.linkDirs, dirs...))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (flagExporter *flagExporter) exportDepFlags(flags ...string) {
|
|
|
|
flagExporter.depFlags = android.FirstUniqueStrings(append(flagExporter.depFlags, flags...))
|
|
|
|
}
|
|
|
|
|
2020-08-25 18:48:19 +02:00
|
|
|
func (flagExporter *flagExporter) exportLinkObjects(flags ...string) {
|
|
|
|
flagExporter.linkObjects = android.FirstUniqueStrings(append(flagExporter.linkObjects, flags...))
|
|
|
|
}
|
|
|
|
|
2020-09-18 23:15:30 +02:00
|
|
|
func (flagExporter *flagExporter) setProvider(ctx ModuleContext) {
|
|
|
|
ctx.SetProvider(FlagExporterInfoProvider, FlagExporterInfo{
|
|
|
|
Flags: flagExporter.depFlags,
|
|
|
|
LinkDirs: flagExporter.linkDirs,
|
|
|
|
LinkObjects: flagExporter.linkObjects,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2020-06-25 18:34:12 +02:00
|
|
|
var _ exportedFlagsProducer = (*flagExporter)(nil)
|
|
|
|
|
|
|
|
func NewFlagExporter() *flagExporter {
|
2020-09-18 23:15:30 +02:00
|
|
|
return &flagExporter{}
|
2020-06-25 18:34:12 +02:00
|
|
|
}
|
|
|
|
|
2020-09-18 23:15:30 +02:00
|
|
|
type FlagExporterInfo struct {
|
|
|
|
Flags []string
|
|
|
|
LinkDirs []string // TODO: this should be android.Paths
|
|
|
|
LinkObjects []string // TODO: this should be android.Paths
|
|
|
|
}
|
|
|
|
|
|
|
|
var FlagExporterInfoProvider = blueprint.NewProvider(FlagExporterInfo{})
|
|
|
|
|
2020-04-09 15:56:02 +02:00
|
|
|
func (mod *Module) isCoverageVariant() bool {
|
|
|
|
return mod.coverage.Properties.IsCoverageVariant
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ cc.Coverage = (*Module)(nil)
|
|
|
|
|
|
|
|
func (mod *Module) IsNativeCoverageNeeded(ctx android.BaseModuleContext) bool {
|
|
|
|
return mod.coverage != nil && mod.coverage.Properties.NeedCoverageVariant
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) PreventInstall() {
|
|
|
|
mod.Properties.PreventInstall = true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) HideFromMake() {
|
|
|
|
mod.Properties.HideFromMake = true
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) MarkAsCoverageVariant(coverage bool) {
|
|
|
|
mod.coverage.Properties.IsCoverageVariant = coverage
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) EnableCoverageIfNeeded() {
|
|
|
|
mod.coverage.Properties.CoverageEnabled = mod.coverage.Properties.NeedCoverageBuild
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func defaultsFactory() android.Module {
|
|
|
|
return DefaultsFactory()
|
|
|
|
}
|
|
|
|
|
|
|
|
type Defaults struct {
|
|
|
|
android.ModuleBase
|
|
|
|
android.DefaultsModuleBase
|
|
|
|
}
|
|
|
|
|
|
|
|
func DefaultsFactory(props ...interface{}) android.Module {
|
|
|
|
module := &Defaults{}
|
|
|
|
|
|
|
|
module.AddProperties(props...)
|
|
|
|
module.AddProperties(
|
|
|
|
&BaseProperties{},
|
2020-12-02 15:15:16 +01:00
|
|
|
&cc.VendorProperties{},
|
2020-09-25 22:08:34 +02:00
|
|
|
&BindgenProperties{},
|
2019-08-27 21:03:00 +02:00
|
|
|
&BaseCompilerProperties{},
|
|
|
|
&BinaryCompilerProperties{},
|
|
|
|
&LibraryCompilerProperties{},
|
|
|
|
&ProcMacroCompilerProperties{},
|
|
|
|
&PrebuiltProperties{},
|
2020-07-08 14:39:44 +02:00
|
|
|
&SourceProviderProperties{},
|
2019-11-01 04:56:47 +01:00
|
|
|
&TestProperties{},
|
2020-04-09 15:56:02 +02:00
|
|
|
&cc.CoverageProperties{},
|
2020-09-25 22:08:34 +02:00
|
|
|
&cc.RustBindgenClangProperties{},
|
2020-06-22 13:28:02 +02:00
|
|
|
&ClippyProperties{},
|
2019-08-27 21:03:00 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
android.InitDefaultsModule(module)
|
|
|
|
return module
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) CrateName() string {
|
2019-11-01 03:38:29 +01:00
|
|
|
return mod.compiler.crateName()
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
|
2019-10-18 23:18:45 +02:00
|
|
|
func (mod *Module) CcLibrary() bool {
|
|
|
|
if mod.compiler != nil {
|
|
|
|
if _, ok := mod.compiler.(*libraryDecorator); ok {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) CcLibraryInterface() bool {
|
|
|
|
if mod.compiler != nil {
|
2020-07-31 17:01:18 +02:00
|
|
|
// use build{Static,Shared}() instead of {static,shared}() here because this might be called before
|
|
|
|
// VariantIs{Static,Shared} is set.
|
|
|
|
if lib, ok := mod.compiler.(libraryInterface); ok && (lib.buildShared() || lib.buildStatic()) {
|
2019-10-18 23:18:45 +02:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2019-11-07 04:15:49 +01:00
|
|
|
func (mod *Module) IncludeDirs() android.Paths {
|
2019-10-18 23:18:45 +02:00
|
|
|
if mod.compiler != nil {
|
2019-10-18 23:49:46 +02:00
|
|
|
if library, ok := mod.compiler.(*libraryDecorator); ok {
|
2019-11-07 04:15:49 +01:00
|
|
|
return library.includeDirs
|
2019-10-18 23:18:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
panic(fmt.Errorf("IncludeDirs called on non-library module: %q", mod.BaseModuleName()))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) SetStatic() {
|
|
|
|
if mod.compiler != nil {
|
2019-10-18 23:49:46 +02:00
|
|
|
if library, ok := mod.compiler.(libraryInterface); ok {
|
|
|
|
library.setStatic()
|
2019-10-18 23:18:45 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
panic(fmt.Errorf("SetStatic called on non-library module: %q", mod.BaseModuleName()))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) SetShared() {
|
|
|
|
if mod.compiler != nil {
|
2019-10-18 23:49:46 +02:00
|
|
|
if library, ok := mod.compiler.(libraryInterface); ok {
|
|
|
|
library.setShared()
|
2019-10-18 23:18:45 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
panic(fmt.Errorf("SetShared called on non-library module: %q", mod.BaseModuleName()))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) BuildStaticVariant() bool {
|
|
|
|
if mod.compiler != nil {
|
2019-10-18 23:49:46 +02:00
|
|
|
if library, ok := mod.compiler.(libraryInterface); ok {
|
|
|
|
return library.buildStatic()
|
2019-10-18 23:18:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
panic(fmt.Errorf("BuildStaticVariant called on non-library module: %q", mod.BaseModuleName()))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) BuildSharedVariant() bool {
|
|
|
|
if mod.compiler != nil {
|
2019-10-18 23:49:46 +02:00
|
|
|
if library, ok := mod.compiler.(libraryInterface); ok {
|
|
|
|
return library.buildShared()
|
2019-10-18 23:18:45 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
panic(fmt.Errorf("BuildSharedVariant called on non-library module: %q", mod.BaseModuleName()))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) Module() android.Module {
|
|
|
|
return mod
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) OutputFile() android.OptionalPath {
|
|
|
|
return mod.outputFile
|
|
|
|
}
|
|
|
|
|
2020-04-09 15:56:02 +02:00
|
|
|
func (mod *Module) CoverageFiles() android.Paths {
|
|
|
|
if mod.compiler != nil {
|
2020-06-25 09:47:46 +02:00
|
|
|
if !mod.compiler.nativeCoverage() {
|
|
|
|
return android.Paths{}
|
|
|
|
}
|
2020-04-09 15:56:02 +02:00
|
|
|
if library, ok := mod.compiler.(*libraryDecorator); ok {
|
|
|
|
if library.coverageFile != nil {
|
|
|
|
return android.Paths{library.coverageFile}
|
|
|
|
}
|
|
|
|
return android.Paths{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
panic(fmt.Errorf("CoverageFiles called on non-library module: %q", mod.BaseModuleName()))
|
|
|
|
}
|
|
|
|
|
2019-10-18 23:18:45 +02:00
|
|
|
var _ cc.LinkableInterface = (*Module)(nil)
|
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
func (mod *Module) Init() android.Module {
|
|
|
|
mod.AddProperties(&mod.Properties)
|
2020-12-02 15:15:16 +01:00
|
|
|
mod.AddProperties(&mod.VendorProperties)
|
2019-08-27 21:03:00 +02:00
|
|
|
|
|
|
|
if mod.compiler != nil {
|
|
|
|
mod.AddProperties(mod.compiler.compilerProps()...)
|
|
|
|
}
|
2020-04-09 15:56:02 +02:00
|
|
|
if mod.coverage != nil {
|
|
|
|
mod.AddProperties(mod.coverage.props()...)
|
|
|
|
}
|
2020-06-22 13:28:02 +02:00
|
|
|
if mod.clippy != nil {
|
|
|
|
mod.AddProperties(mod.clippy.props()...)
|
|
|
|
}
|
2020-07-08 14:39:44 +02:00
|
|
|
if mod.sourceProvider != nil {
|
2020-08-05 15:36:19 +02:00
|
|
|
mod.AddProperties(mod.sourceProvider.SourceProviderProps()...)
|
2020-07-08 14:39:44 +02:00
|
|
|
}
|
2020-04-09 15:56:02 +02:00
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
android.InitAndroidArchModule(mod, mod.hod, mod.multilib)
|
2020-11-17 14:21:02 +01:00
|
|
|
android.InitApexModule(mod)
|
2019-08-27 21:03:00 +02:00
|
|
|
|
|
|
|
android.InitDefaultableModule(mod)
|
|
|
|
return mod
|
|
|
|
}
|
|
|
|
|
|
|
|
func newBaseModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
|
|
|
|
return &Module{
|
|
|
|
hod: hod,
|
|
|
|
multilib: multilib,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
func newModule(hod android.HostOrDeviceSupported, multilib android.Multilib) *Module {
|
|
|
|
module := newBaseModule(hod, multilib)
|
2020-04-09 15:56:02 +02:00
|
|
|
module.coverage = &coverage{}
|
2020-06-22 13:28:02 +02:00
|
|
|
module.clippy = &clippy{}
|
2019-08-27 21:03:00 +02:00
|
|
|
return module
|
|
|
|
}
|
|
|
|
|
|
|
|
type ModuleContext interface {
|
|
|
|
android.ModuleContext
|
|
|
|
ModuleContextIntf
|
|
|
|
}
|
|
|
|
|
|
|
|
type BaseModuleContext interface {
|
|
|
|
android.BaseModuleContext
|
|
|
|
ModuleContextIntf
|
|
|
|
}
|
|
|
|
|
|
|
|
type DepsContext interface {
|
|
|
|
android.BottomUpMutatorContext
|
|
|
|
ModuleContextIntf
|
|
|
|
}
|
|
|
|
|
|
|
|
type ModuleContextIntf interface {
|
2020-06-24 11:32:48 +02:00
|
|
|
RustModule() *Module
|
2019-08-27 21:03:00 +02:00
|
|
|
toolchain() config.Toolchain
|
|
|
|
}
|
|
|
|
|
|
|
|
type depsContext struct {
|
|
|
|
android.BottomUpMutatorContext
|
|
|
|
}
|
|
|
|
|
|
|
|
type moduleContext struct {
|
|
|
|
android.ModuleContext
|
|
|
|
}
|
|
|
|
|
2020-06-24 11:32:48 +02:00
|
|
|
type baseModuleContext struct {
|
|
|
|
android.BaseModuleContext
|
2020-04-09 15:56:02 +02:00
|
|
|
}
|
|
|
|
|
2020-06-24 11:32:48 +02:00
|
|
|
func (ctx *moduleContext) RustModule() *Module {
|
|
|
|
return ctx.Module().(*Module)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *moduleContext) toolchain() config.Toolchain {
|
|
|
|
return ctx.RustModule().toolchain(ctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *depsContext) RustModule() *Module {
|
|
|
|
return ctx.Module().(*Module)
|
2020-04-09 15:56:02 +02:00
|
|
|
}
|
|
|
|
|
2020-06-24 11:32:48 +02:00
|
|
|
func (ctx *depsContext) toolchain() config.Toolchain {
|
|
|
|
return ctx.RustModule().toolchain(ctx)
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
|
2020-06-24 11:32:48 +02:00
|
|
|
func (ctx *baseModuleContext) RustModule() *Module {
|
|
|
|
return ctx.Module().(*Module)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ctx *baseModuleContext) toolchain() config.Toolchain {
|
|
|
|
return ctx.RustModule().toolchain(ctx)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) nativeCoverage() bool {
|
|
|
|
return mod.compiler != nil && mod.compiler.nativeCoverage()
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) toolchain(ctx android.BaseModuleContext) config.Toolchain {
|
|
|
|
if mod.cachedToolchain == nil {
|
|
|
|
mod.cachedToolchain = config.FindToolchain(ctx.Os(), ctx.Arch())
|
|
|
|
}
|
|
|
|
return mod.cachedToolchain
|
|
|
|
}
|
|
|
|
|
2020-08-27 13:37:29 +02:00
|
|
|
func (mod *Module) ccToolchain(ctx android.BaseModuleContext) cc_config.Toolchain {
|
|
|
|
return cc_config.FindToolchain(ctx.Os(), ctx.Arch())
|
|
|
|
}
|
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
func (d *Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) GenerateAndroidBuildActions(actx android.ModuleContext) {
|
|
|
|
ctx := &moduleContext{
|
|
|
|
ModuleContext: actx,
|
|
|
|
}
|
|
|
|
|
2020-11-17 14:21:02 +01:00
|
|
|
apexInfo := actx.Provider(android.ApexInfoProvider).(android.ApexInfo)
|
|
|
|
if !apexInfo.IsForPlatform() {
|
|
|
|
mod.hideApexVariantFromMake = true
|
|
|
|
}
|
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
toolchain := mod.toolchain(ctx)
|
2020-12-02 15:15:16 +01:00
|
|
|
mod.makeLinkType = cc.GetMakeLinkType(actx, mod)
|
|
|
|
|
|
|
|
// Differentiate static libraries that are vendor available
|
|
|
|
if mod.UseVndk() {
|
|
|
|
mod.Properties.SubName += ".vendor"
|
|
|
|
}
|
2019-08-27 21:03:00 +02:00
|
|
|
|
|
|
|
if !toolchain.Supported() {
|
|
|
|
// This toolchain's unsupported, there's nothing to do for this mod.
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
deps := mod.depsToPaths(ctx)
|
|
|
|
flags := Flags{
|
|
|
|
Toolchain: toolchain,
|
|
|
|
}
|
|
|
|
|
|
|
|
if mod.compiler != nil {
|
|
|
|
flags = mod.compiler.compilerFlags(ctx, flags)
|
2020-04-09 15:56:02 +02:00
|
|
|
}
|
|
|
|
if mod.coverage != nil {
|
|
|
|
flags, deps = mod.coverage.flags(ctx, flags, deps)
|
|
|
|
}
|
2020-06-22 13:28:02 +02:00
|
|
|
if mod.clippy != nil {
|
|
|
|
flags, deps = mod.clippy.flags(ctx, flags, deps)
|
|
|
|
}
|
2020-04-09 15:56:02 +02:00
|
|
|
|
2020-09-23 18:10:17 +02:00
|
|
|
// SourceProvider needs to call GenerateSource() before compiler calls
|
|
|
|
// compile() so it can provide the source. A SourceProvider has
|
|
|
|
// multiple variants (e.g. source, rlib, dylib). Only the "source"
|
|
|
|
// variant is responsible for effectively generating the source. The
|
|
|
|
// remaining variants relies on the "source" variant output.
|
2020-07-31 19:40:31 +02:00
|
|
|
if mod.sourceProvider != nil {
|
2020-09-23 18:10:17 +02:00
|
|
|
if mod.compiler.(libraryInterface).source() {
|
|
|
|
mod.sourceProvider.GenerateSource(ctx, deps)
|
|
|
|
mod.sourceProvider.setSubName(ctx.ModuleSubDir())
|
|
|
|
} else {
|
|
|
|
sourceMod := actx.GetDirectDepWithTag(mod.Name(), sourceDepTag)
|
|
|
|
sourceLib := sourceMod.(*Module).compiler.(*libraryDecorator)
|
2020-10-02 06:25:05 +02:00
|
|
|
mod.sourceProvider.setOutputFiles(sourceLib.sourceProvider.Srcs())
|
2020-09-23 18:10:17 +02:00
|
|
|
}
|
2020-07-31 19:40:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if mod.compiler != nil && !mod.compiler.Disabled() {
|
2019-08-27 21:03:00 +02:00
|
|
|
outputFile := mod.compiler.compile(ctx, flags, deps)
|
2020-07-31 19:40:31 +02:00
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
mod.outputFile = android.OptionalPathForPath(outputFile)
|
2020-07-31 19:40:31 +02:00
|
|
|
if mod.outputFile.Valid() && !mod.Properties.PreventInstall {
|
2020-08-27 13:48:36 +02:00
|
|
|
mod.compiler.install(ctx)
|
2020-04-09 15:56:02 +02:00
|
|
|
}
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) deps(ctx DepsContext) Deps {
|
|
|
|
deps := Deps{}
|
|
|
|
|
|
|
|
if mod.compiler != nil {
|
|
|
|
deps = mod.compiler.compilerDeps(ctx, deps)
|
2020-07-31 19:40:31 +02:00
|
|
|
}
|
|
|
|
if mod.sourceProvider != nil {
|
2020-08-05 15:36:19 +02:00
|
|
|
deps = mod.sourceProvider.SourceProviderDeps(ctx, deps)
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
|
2020-04-09 15:56:02 +02:00
|
|
|
if mod.coverage != nil {
|
|
|
|
deps = mod.coverage.deps(ctx, deps)
|
|
|
|
}
|
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
deps.Rlibs = android.LastUniqueStrings(deps.Rlibs)
|
|
|
|
deps.Dylibs = android.LastUniqueStrings(deps.Dylibs)
|
2020-06-29 23:34:06 +02:00
|
|
|
deps.Rustlibs = android.LastUniqueStrings(deps.Rustlibs)
|
2019-08-27 21:03:00 +02:00
|
|
|
deps.ProcMacros = android.LastUniqueStrings(deps.ProcMacros)
|
|
|
|
deps.SharedLibs = android.LastUniqueStrings(deps.SharedLibs)
|
|
|
|
deps.StaticLibs = android.LastUniqueStrings(deps.StaticLibs)
|
|
|
|
|
|
|
|
return deps
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
type dependencyTag struct {
|
|
|
|
blueprint.BaseDependencyTag
|
|
|
|
name string
|
|
|
|
library bool
|
|
|
|
proc_macro bool
|
|
|
|
}
|
|
|
|
|
2020-11-25 04:44:59 +01:00
|
|
|
// InstallDepNeeded returns true for rlibs, dylibs, and proc macros so that they or their transitive
|
|
|
|
// dependencies (especially C/C++ shared libs) are installed as dependencies of a rust binary.
|
|
|
|
func (d dependencyTag) InstallDepNeeded() bool {
|
|
|
|
return d.library || d.proc_macro
|
|
|
|
}
|
|
|
|
|
|
|
|
var _ android.InstallNeededDependencyTag = dependencyTag{}
|
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
var (
|
2020-08-04 21:43:37 +02:00
|
|
|
customBindgenDepTag = dependencyTag{name: "customBindgenTag"}
|
|
|
|
rlibDepTag = dependencyTag{name: "rlibTag", library: true}
|
|
|
|
dylibDepTag = dependencyTag{name: "dylib", library: true}
|
|
|
|
procMacroDepTag = dependencyTag{name: "procMacro", proc_macro: true}
|
|
|
|
testPerSrcDepTag = dependencyTag{name: "rust_unit_tests"}
|
2020-09-23 18:10:17 +02:00
|
|
|
sourceDepTag = dependencyTag{name: "source"}
|
2019-08-27 21:03:00 +02:00
|
|
|
)
|
|
|
|
|
2020-11-17 14:21:02 +01:00
|
|
|
func IsDylibDepTag(depTag blueprint.DependencyTag) bool {
|
|
|
|
tag, ok := depTag.(dependencyTag)
|
|
|
|
return ok && tag == dylibDepTag
|
|
|
|
}
|
|
|
|
|
2020-06-29 23:34:06 +02:00
|
|
|
type autoDep struct {
|
|
|
|
variation string
|
|
|
|
depTag dependencyTag
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
2020-09-23 18:10:17 +02:00
|
|
|
rlibVariation = "rlib"
|
|
|
|
dylibVariation = "dylib"
|
|
|
|
rlibAutoDep = autoDep{variation: rlibVariation, depTag: rlibDepTag}
|
|
|
|
dylibAutoDep = autoDep{variation: dylibVariation, depTag: dylibDepTag}
|
2020-06-29 23:34:06 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type autoDeppable interface {
|
2020-08-18 20:31:23 +02:00
|
|
|
autoDep(ctx BaseModuleContext) autoDep
|
2020-06-29 23:34:06 +02:00
|
|
|
}
|
|
|
|
|
2020-04-09 15:56:02 +02:00
|
|
|
func (mod *Module) begin(ctx BaseModuleContext) {
|
|
|
|
if mod.coverage != nil {
|
|
|
|
mod.coverage.begin(ctx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
func (mod *Module) depsToPaths(ctx android.ModuleContext) PathDeps {
|
|
|
|
var depPaths PathDeps
|
|
|
|
|
|
|
|
directRlibDeps := []*Module{}
|
|
|
|
directDylibDeps := []*Module{}
|
|
|
|
directProcMacroDeps := []*Module{}
|
2019-10-18 23:49:46 +02:00
|
|
|
directSharedLibDeps := [](cc.LinkableInterface){}
|
|
|
|
directStaticLibDeps := [](cc.LinkableInterface){}
|
2020-07-22 22:09:13 +02:00
|
|
|
directSrcProvidersDeps := []*Module{}
|
|
|
|
directSrcDeps := [](android.SourceFileProducer){}
|
2019-08-27 21:03:00 +02:00
|
|
|
|
|
|
|
ctx.VisitDirectDeps(func(dep android.Module) {
|
|
|
|
depName := ctx.OtherModuleName(dep)
|
|
|
|
depTag := ctx.OtherModuleDependencyTag(dep)
|
2020-07-31 17:01:18 +02:00
|
|
|
if rustDep, ok := dep.(*Module); ok && !rustDep.CcLibraryInterface() {
|
2019-08-27 21:03:00 +02:00
|
|
|
//Handle Rust Modules
|
2019-09-13 23:23:15 +02:00
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
switch depTag {
|
|
|
|
case dylibDepTag:
|
|
|
|
dylib, ok := rustDep.compiler.(libraryInterface)
|
|
|
|
if !ok || !dylib.dylib() {
|
|
|
|
ctx.ModuleErrorf("mod %q not an dylib library", depName)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
directDylibDeps = append(directDylibDeps, rustDep)
|
|
|
|
mod.Properties.AndroidMkDylibs = append(mod.Properties.AndroidMkDylibs, depName)
|
|
|
|
case rlibDepTag:
|
2020-09-08 18:46:52 +02:00
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
rlib, ok := rustDep.compiler.(libraryInterface)
|
|
|
|
if !ok || !rlib.rlib() {
|
2020-09-08 18:46:52 +02:00
|
|
|
ctx.ModuleErrorf("mod %q not an rlib library", depName+rustDep.Properties.SubName)
|
2019-08-27 21:03:00 +02:00
|
|
|
return
|
|
|
|
}
|
2020-04-09 15:56:02 +02:00
|
|
|
depPaths.coverageFiles = append(depPaths.coverageFiles, rustDep.CoverageFiles()...)
|
2019-08-27 21:03:00 +02:00
|
|
|
directRlibDeps = append(directRlibDeps, rustDep)
|
2020-09-08 18:46:52 +02:00
|
|
|
mod.Properties.AndroidMkRlibs = append(mod.Properties.AndroidMkRlibs, depName+rustDep.Properties.SubName)
|
2019-08-27 21:03:00 +02:00
|
|
|
case procMacroDepTag:
|
|
|
|
directProcMacroDeps = append(directProcMacroDeps, rustDep)
|
|
|
|
mod.Properties.AndroidMkProcMacroLibs = append(mod.Properties.AndroidMkProcMacroLibs, depName)
|
2020-07-22 22:09:13 +02:00
|
|
|
case android.SourceDepTag:
|
|
|
|
// Since these deps are added in path_properties.go via AddDependencies, we need to ensure the correct
|
|
|
|
// OS/Arch variant is used.
|
|
|
|
var helper string
|
|
|
|
if ctx.Host() {
|
|
|
|
helper = "missing 'host_supported'?"
|
|
|
|
} else {
|
|
|
|
helper = "device module defined?"
|
|
|
|
}
|
|
|
|
|
|
|
|
if dep.Target().Os != ctx.Os() {
|
|
|
|
ctx.ModuleErrorf("OS mismatch on dependency %q (%s)", dep.Name(), helper)
|
|
|
|
return
|
|
|
|
} else if dep.Target().Arch.ArchType != ctx.Arch().ArchType {
|
|
|
|
ctx.ModuleErrorf("Arch mismatch on dependency %q (%s)", dep.Name(), helper)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
directSrcProvidersDeps = append(directSrcProvidersDeps, rustDep)
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
|
2020-08-07 15:00:50 +02:00
|
|
|
//Append the dependencies exportedDirs, except for proc-macros which target a different arch/OS
|
2020-09-18 23:15:30 +02:00
|
|
|
if depTag != procMacroDepTag {
|
|
|
|
exportedInfo := ctx.OtherModuleProvider(dep, FlagExporterInfoProvider).(FlagExporterInfo)
|
|
|
|
depPaths.linkDirs = append(depPaths.linkDirs, exportedInfo.LinkDirs...)
|
|
|
|
depPaths.depFlags = append(depPaths.depFlags, exportedInfo.Flags...)
|
|
|
|
depPaths.linkObjects = append(depPaths.linkObjects, exportedInfo.LinkObjects...)
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if depTag == dylibDepTag || depTag == rlibDepTag || depTag == procMacroDepTag {
|
2020-07-31 19:40:31 +02:00
|
|
|
linkFile := rustDep.outputFile
|
|
|
|
if !linkFile.Valid() {
|
|
|
|
ctx.ModuleErrorf("Invalid output file when adding dep %q to %q",
|
|
|
|
depName, ctx.ModuleName())
|
|
|
|
return
|
|
|
|
}
|
2019-08-27 21:03:00 +02:00
|
|
|
linkDir := linkPathFromFilePath(linkFile.Path())
|
2020-06-25 18:34:12 +02:00
|
|
|
if lib, ok := mod.compiler.(exportedFlagsProducer); ok {
|
|
|
|
lib.exportLinkDirs(linkDir)
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-31 17:01:18 +02:00
|
|
|
} else if ccDep, ok := dep.(cc.LinkableInterface); ok {
|
2019-10-18 23:49:46 +02:00
|
|
|
//Handle C dependencies
|
|
|
|
if _, ok := ccDep.(*Module); !ok {
|
|
|
|
if ccDep.Module().Target().Os != ctx.Os() {
|
|
|
|
ctx.ModuleErrorf("OS mismatch between %q and %q", ctx.ModuleName(), depName)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if ccDep.Module().Target().Arch.ArchType != ctx.Arch().ArchType {
|
|
|
|
ctx.ModuleErrorf("Arch mismatch between %q and %q", ctx.ModuleName(), depName)
|
|
|
|
return
|
|
|
|
}
|
2019-09-13 23:23:15 +02:00
|
|
|
}
|
2020-08-25 18:48:19 +02:00
|
|
|
linkObject := ccDep.OutputFile()
|
|
|
|
linkPath := linkPathFromFilePath(linkObject.Path())
|
2020-02-06 19:22:43 +01:00
|
|
|
|
2020-08-25 18:48:19 +02:00
|
|
|
if !linkObject.Valid() {
|
2019-08-27 21:03:00 +02:00
|
|
|
ctx.ModuleErrorf("Invalid output file when adding dep %q to %q", depName, ctx.ModuleName())
|
|
|
|
}
|
|
|
|
|
|
|
|
exportDep := false
|
2020-07-28 06:26:48 +02:00
|
|
|
switch {
|
|
|
|
case cc.IsStaticDepTag(depTag):
|
2019-08-27 21:03:00 +02:00
|
|
|
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
|
2020-08-25 18:48:19 +02:00
|
|
|
depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
|
2020-09-18 23:15:30 +02:00
|
|
|
exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
|
|
|
|
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
|
|
|
|
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
|
|
|
|
depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
|
|
|
|
depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
|
2020-04-09 15:56:02 +02:00
|
|
|
depPaths.coverageFiles = append(depPaths.coverageFiles, ccDep.CoverageFiles()...)
|
2019-08-27 21:03:00 +02:00
|
|
|
directStaticLibDeps = append(directStaticLibDeps, ccDep)
|
|
|
|
mod.Properties.AndroidMkStaticLibs = append(mod.Properties.AndroidMkStaticLibs, depName)
|
2020-07-28 06:26:48 +02:00
|
|
|
case cc.IsSharedDepTag(depTag):
|
2019-08-27 21:03:00 +02:00
|
|
|
depPaths.linkDirs = append(depPaths.linkDirs, linkPath)
|
2020-08-25 18:48:19 +02:00
|
|
|
depPaths.linkObjects = append(depPaths.linkObjects, linkObject.String())
|
2020-09-18 23:15:30 +02:00
|
|
|
exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
|
|
|
|
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
|
|
|
|
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
|
|
|
|
depPaths.depClangFlags = append(depPaths.depClangFlags, exportedInfo.Flags...)
|
|
|
|
depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
|
2019-08-27 21:03:00 +02:00
|
|
|
directSharedLibDeps = append(directSharedLibDeps, ccDep)
|
|
|
|
mod.Properties.AndroidMkSharedLibs = append(mod.Properties.AndroidMkSharedLibs, depName)
|
|
|
|
exportDep = true
|
2020-11-06 20:56:27 +01:00
|
|
|
case cc.IsHeaderDepTag(depTag):
|
|
|
|
exportedInfo := ctx.OtherModuleProvider(dep, cc.FlagExporterInfoProvider).(cc.FlagExporterInfo)
|
|
|
|
depPaths.depIncludePaths = append(depPaths.depIncludePaths, exportedInfo.IncludeDirs...)
|
|
|
|
depPaths.depSystemIncludePaths = append(depPaths.depSystemIncludePaths, exportedInfo.SystemIncludeDirs...)
|
|
|
|
depPaths.depGeneratedHeaders = append(depPaths.depGeneratedHeaders, exportedInfo.GeneratedHeaders...)
|
2020-07-28 06:26:48 +02:00
|
|
|
case depTag == cc.CrtBeginDepTag:
|
2020-08-25 18:48:19 +02:00
|
|
|
depPaths.CrtBegin = linkObject
|
2020-07-28 06:26:48 +02:00
|
|
|
case depTag == cc.CrtEndDepTag:
|
2020-08-25 18:48:19 +02:00
|
|
|
depPaths.CrtEnd = linkObject
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure these dependencies are propagated
|
2020-06-25 18:34:12 +02:00
|
|
|
if lib, ok := mod.compiler.(exportedFlagsProducer); ok && exportDep {
|
|
|
|
lib.exportLinkDirs(linkPath)
|
2020-08-25 18:48:19 +02:00
|
|
|
lib.exportLinkObjects(linkObject.String())
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
}
|
2020-07-31 17:01:18 +02:00
|
|
|
|
|
|
|
if srcDep, ok := dep.(android.SourceFileProducer); ok {
|
|
|
|
switch depTag {
|
|
|
|
case android.SourceDepTag:
|
|
|
|
// These are usually genrules which don't have per-target variants.
|
|
|
|
directSrcDeps = append(directSrcDeps, srcDep)
|
|
|
|
}
|
|
|
|
}
|
2019-08-27 21:03:00 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
var rlibDepFiles RustLibraries
|
|
|
|
for _, dep := range directRlibDeps {
|
|
|
|
rlibDepFiles = append(rlibDepFiles, RustLibrary{Path: dep.outputFile.Path(), CrateName: dep.CrateName()})
|
|
|
|
}
|
|
|
|
var dylibDepFiles RustLibraries
|
|
|
|
for _, dep := range directDylibDeps {
|
|
|
|
dylibDepFiles = append(dylibDepFiles, RustLibrary{Path: dep.outputFile.Path(), CrateName: dep.CrateName()})
|
|
|
|
}
|
|
|
|
var procMacroDepFiles RustLibraries
|
|
|
|
for _, dep := range directProcMacroDeps {
|
|
|
|
procMacroDepFiles = append(procMacroDepFiles, RustLibrary{Path: dep.outputFile.Path(), CrateName: dep.CrateName()})
|
|
|
|
}
|
|
|
|
|
|
|
|
var staticLibDepFiles android.Paths
|
|
|
|
for _, dep := range directStaticLibDeps {
|
|
|
|
staticLibDepFiles = append(staticLibDepFiles, dep.OutputFile().Path())
|
|
|
|
}
|
|
|
|
|
|
|
|
var sharedLibDepFiles android.Paths
|
|
|
|
for _, dep := range directSharedLibDeps {
|
|
|
|
sharedLibDepFiles = append(sharedLibDepFiles, dep.OutputFile().Path())
|
|
|
|
}
|
|
|
|
|
2020-07-22 22:09:13 +02:00
|
|
|
var srcProviderDepFiles android.Paths
|
|
|
|
for _, dep := range directSrcProvidersDeps {
|
|
|
|
srcs, _ := dep.OutputFiles("")
|
|
|
|
srcProviderDepFiles = append(srcProviderDepFiles, srcs...)
|
|
|
|
}
|
|
|
|
for _, dep := range directSrcDeps {
|
|
|
|
srcs := dep.Srcs()
|
|
|
|
srcProviderDepFiles = append(srcProviderDepFiles, srcs...)
|
|
|
|
}
|
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
depPaths.RLibs = append(depPaths.RLibs, rlibDepFiles...)
|
|
|
|
depPaths.DyLibs = append(depPaths.DyLibs, dylibDepFiles...)
|
|
|
|
depPaths.SharedLibs = append(depPaths.SharedLibs, sharedLibDepFiles...)
|
|
|
|
depPaths.StaticLibs = append(depPaths.StaticLibs, staticLibDepFiles...)
|
|
|
|
depPaths.ProcMacros = append(depPaths.ProcMacros, procMacroDepFiles...)
|
2020-07-22 22:09:13 +02:00
|
|
|
depPaths.SrcDeps = append(depPaths.SrcDeps, srcProviderDepFiles...)
|
2019-08-27 21:03:00 +02:00
|
|
|
|
|
|
|
// Dedup exported flags from dependencies
|
|
|
|
depPaths.linkDirs = android.FirstUniqueStrings(depPaths.linkDirs)
|
|
|
|
depPaths.depFlags = android.FirstUniqueStrings(depPaths.depFlags)
|
2020-07-24 22:05:01 +02:00
|
|
|
depPaths.depClangFlags = android.FirstUniqueStrings(depPaths.depClangFlags)
|
|
|
|
depPaths.depIncludePaths = android.FirstUniquePaths(depPaths.depIncludePaths)
|
|
|
|
depPaths.depSystemIncludePaths = android.FirstUniquePaths(depPaths.depSystemIncludePaths)
|
2019-08-27 21:03:00 +02:00
|
|
|
|
|
|
|
return depPaths
|
|
|
|
}
|
|
|
|
|
2019-12-13 04:36:05 +01:00
|
|
|
func (mod *Module) InstallInData() bool {
|
|
|
|
if mod.compiler == nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return mod.compiler.inData()
|
|
|
|
}
|
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
func linkPathFromFilePath(filepath android.Path) string {
|
|
|
|
return strings.Split(filepath.String(), filepath.Base())[0]
|
|
|
|
}
|
2020-02-06 18:05:10 +01:00
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
func (mod *Module) DepsMutator(actx android.BottomUpMutatorContext) {
|
|
|
|
ctx := &depsContext{
|
|
|
|
BottomUpMutatorContext: actx,
|
|
|
|
}
|
|
|
|
|
|
|
|
deps := mod.deps(ctx)
|
2020-10-01 00:34:40 +02:00
|
|
|
var commonDepVariations []blueprint.Variation
|
2020-09-28 19:22:45 +02:00
|
|
|
|
2020-09-08 18:46:52 +02:00
|
|
|
stdLinkage := "dylib-std"
|
2020-09-28 19:22:45 +02:00
|
|
|
if mod.compiler.stdLinkage(ctx) == RlibLinkage {
|
2020-09-08 18:46:52 +02:00
|
|
|
stdLinkage = "rlib-std"
|
|
|
|
}
|
|
|
|
|
|
|
|
rlibDepVariations := commonDepVariations
|
|
|
|
if lib, ok := mod.compiler.(libraryInterface); !ok || !lib.sysroot() {
|
|
|
|
rlibDepVariations = append(rlibDepVariations,
|
|
|
|
blueprint.Variation{Mutator: "rust_stdlinkage", Variation: stdLinkage})
|
|
|
|
}
|
|
|
|
|
2019-10-18 23:49:46 +02:00
|
|
|
actx.AddVariationDependencies(
|
2020-09-08 18:46:52 +02:00
|
|
|
append(rlibDepVariations, []blueprint.Variation{
|
2020-09-23 18:10:17 +02:00
|
|
|
{Mutator: "rust_libraries", Variation: rlibVariation}}...),
|
2019-10-18 23:49:46 +02:00
|
|
|
rlibDepTag, deps.Rlibs...)
|
|
|
|
actx.AddVariationDependencies(
|
|
|
|
append(commonDepVariations, []blueprint.Variation{
|
2020-09-23 18:10:17 +02:00
|
|
|
{Mutator: "rust_libraries", Variation: dylibVariation}}...),
|
2019-10-18 23:49:46 +02:00
|
|
|
dylibDepTag, deps.Dylibs...)
|
|
|
|
|
2020-08-18 20:31:23 +02:00
|
|
|
if deps.Rustlibs != nil && !mod.compiler.Disabled() {
|
|
|
|
autoDep := mod.compiler.(autoDeppable).autoDep(ctx)
|
2020-09-08 18:46:52 +02:00
|
|
|
if autoDep.depTag == rlibDepTag {
|
|
|
|
actx.AddVariationDependencies(
|
|
|
|
append(rlibDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation}),
|
|
|
|
autoDep.depTag, deps.Rustlibs...)
|
|
|
|
} else {
|
|
|
|
actx.AddVariationDependencies(
|
|
|
|
append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: autoDep.variation}),
|
|
|
|
autoDep.depTag, deps.Rustlibs...)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if deps.Stdlibs != nil {
|
2020-09-28 19:22:45 +02:00
|
|
|
if mod.compiler.stdLinkage(ctx) == RlibLinkage {
|
2020-09-08 18:46:52 +02:00
|
|
|
actx.AddVariationDependencies(
|
|
|
|
append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: "rlib"}),
|
|
|
|
rlibDepTag, deps.Stdlibs...)
|
|
|
|
} else {
|
|
|
|
actx.AddVariationDependencies(
|
|
|
|
append(commonDepVariations, blueprint.Variation{Mutator: "rust_libraries", Variation: "dylib"}),
|
|
|
|
dylibDepTag, deps.Stdlibs...)
|
|
|
|
}
|
2020-06-29 23:34:06 +02:00
|
|
|
}
|
2019-10-18 23:49:46 +02:00
|
|
|
actx.AddVariationDependencies(append(commonDepVariations,
|
|
|
|
blueprint.Variation{Mutator: "link", Variation: "shared"}),
|
2020-07-28 06:26:48 +02:00
|
|
|
cc.SharedDepTag(), deps.SharedLibs...)
|
2019-10-18 23:49:46 +02:00
|
|
|
actx.AddVariationDependencies(append(commonDepVariations,
|
|
|
|
blueprint.Variation{Mutator: "link", Variation: "static"}),
|
2020-07-28 06:26:48 +02:00
|
|
|
cc.StaticDepTag(), deps.StaticLibs...)
|
2019-09-23 19:10:40 +02:00
|
|
|
|
2020-11-06 20:56:27 +01:00
|
|
|
actx.AddVariationDependencies(nil, cc.HeaderDepTag(), deps.HeaderLibs...)
|
|
|
|
|
2020-09-26 03:47:38 +02:00
|
|
|
crtVariations := cc.GetCrtVariations(ctx, mod)
|
2019-09-20 20:00:37 +02:00
|
|
|
if deps.CrtBegin != "" {
|
2020-07-15 22:33:30 +02:00
|
|
|
actx.AddVariationDependencies(crtVariations, cc.CrtBeginDepTag, deps.CrtBegin)
|
2019-09-20 20:00:37 +02:00
|
|
|
}
|
|
|
|
if deps.CrtEnd != "" {
|
2020-07-15 22:33:30 +02:00
|
|
|
actx.AddVariationDependencies(crtVariations, cc.CrtEndDepTag, deps.CrtEnd)
|
2019-09-20 20:00:37 +02:00
|
|
|
}
|
|
|
|
|
2020-08-04 21:43:37 +02:00
|
|
|
if mod.sourceProvider != nil {
|
|
|
|
if bindgen, ok := mod.sourceProvider.(*bindgenDecorator); ok &&
|
|
|
|
bindgen.Properties.Custom_bindgen != "" {
|
|
|
|
actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), customBindgenDepTag,
|
|
|
|
bindgen.Properties.Custom_bindgen)
|
|
|
|
}
|
|
|
|
}
|
2019-09-23 19:10:40 +02:00
|
|
|
// proc_macros are compiler plugins, and so we need the host arch variant as a dependendcy.
|
2019-10-16 20:03:10 +02:00
|
|
|
actx.AddFarVariationDependencies(ctx.Config().BuildOSTarget.Variations(), procMacroDepTag, deps.ProcMacros...)
|
2019-08-27 21:03:00 +02:00
|
|
|
}
|
|
|
|
|
2020-04-09 15:56:02 +02:00
|
|
|
func BeginMutator(ctx android.BottomUpMutatorContext) {
|
|
|
|
if mod, ok := ctx.Module().(*Module); ok && mod.Enabled() {
|
|
|
|
mod.beginMutator(ctx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) beginMutator(actx android.BottomUpMutatorContext) {
|
|
|
|
ctx := &baseModuleContext{
|
|
|
|
BaseModuleContext: actx,
|
|
|
|
}
|
|
|
|
|
|
|
|
mod.begin(ctx)
|
|
|
|
}
|
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
func (mod *Module) Name() string {
|
|
|
|
name := mod.ModuleBase.Name()
|
|
|
|
if p, ok := mod.compiler.(interface {
|
|
|
|
Name(string) string
|
|
|
|
}); ok {
|
|
|
|
name = p.Name(name)
|
|
|
|
}
|
|
|
|
return name
|
|
|
|
}
|
|
|
|
|
2020-08-13 12:55:59 +02:00
|
|
|
func (mod *Module) disableClippy() {
|
2020-08-04 22:27:16 +02:00
|
|
|
if mod.clippy != nil {
|
2020-08-13 12:55:59 +02:00
|
|
|
mod.clippy.Properties.Clippy_lints = proptools.StringPtr("none")
|
2020-08-04 22:27:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-16 02:36:30 +02:00
|
|
|
var _ android.HostToolProvider = (*Module)(nil)
|
|
|
|
|
|
|
|
func (mod *Module) HostToolPath() android.OptionalPath {
|
|
|
|
if !mod.Host() {
|
|
|
|
return android.OptionalPath{}
|
|
|
|
}
|
2020-08-11 06:50:43 +02:00
|
|
|
if binary, ok := mod.compiler.(*binaryDecorator); ok {
|
|
|
|
return android.OptionalPathForPath(binary.baseCompiler.path)
|
2020-05-16 02:36:30 +02:00
|
|
|
}
|
|
|
|
return android.OptionalPath{}
|
|
|
|
}
|
|
|
|
|
2020-11-17 14:21:02 +01:00
|
|
|
var _ android.ApexModule = (*Module)(nil)
|
|
|
|
|
2020-12-04 21:05:43 +01:00
|
|
|
func (mod *Module) minSdkVersion() string {
|
|
|
|
return String(mod.Properties.Min_sdk_version)
|
|
|
|
}
|
|
|
|
|
2020-11-17 14:21:02 +01:00
|
|
|
func (mod *Module) ShouldSupportSdkVersion(ctx android.BaseModuleContext, sdkVersion android.ApiLevel) error {
|
2020-12-04 21:05:43 +01:00
|
|
|
minSdkVersion := mod.minSdkVersion()
|
|
|
|
if minSdkVersion == "apex_inherit" {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
if minSdkVersion == "" {
|
|
|
|
return fmt.Errorf("min_sdk_version is not specificed")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Not using nativeApiLevelFromUser because the context here is not
|
|
|
|
// necessarily a native context.
|
|
|
|
ver, err := android.ApiLevelFromUser(ctx, minSdkVersion)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if ver.GreaterThan(sdkVersion) {
|
|
|
|
return fmt.Errorf("newer SDK(%v)", ver)
|
|
|
|
}
|
2020-11-17 14:21:02 +01:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mod *Module) DepIsInSameApex(ctx android.BaseModuleContext, dep android.Module) bool {
|
|
|
|
depTag := ctx.OtherModuleDependencyTag(dep)
|
|
|
|
|
|
|
|
if ccm, ok := dep.(*cc.Module); ok {
|
|
|
|
if ccm.HasStubsVariants() {
|
|
|
|
if cc.IsSharedDepTag(depTag) {
|
|
|
|
// dynamic dep to a stubs lib crosses APEX boundary
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
if cc.IsRuntimeDepTag(depTag) {
|
|
|
|
// runtime dep to a stubs lib also crosses APEX boundary
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
if cc.IsHeaderDepTag(depTag) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if mod.Static() && cc.IsSharedDepTag(depTag) {
|
|
|
|
// shared_lib dependency from a static lib is considered as crossing
|
|
|
|
// the APEX boundary because the dependency doesn't actually is
|
|
|
|
// linked; the dependency is used only during the compilation phase.
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if depTag == procMacroDepTag {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// Overrides ApexModule.IsInstallabeToApex()
|
|
|
|
func (mod *Module) IsInstallableToApex() bool {
|
|
|
|
if mod.compiler != nil {
|
|
|
|
if lib, ok := mod.compiler.(*libraryDecorator); ok && (lib.shared() || lib.dylib()) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
if _, ok := mod.compiler.(*binaryDecorator); ok {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2019-08-27 21:03:00 +02:00
|
|
|
var Bool = proptools.Bool
|
|
|
|
var BoolDefault = proptools.BoolDefault
|
|
|
|
var String = proptools.String
|
|
|
|
var StringPtr = proptools.StringPtr
|
2020-07-10 03:03:28 +02:00
|
|
|
|
|
|
|
var _ android.OutputFileProducer = (*Module)(nil)
|