diff --git a/Android.bp b/Android.bp index eefa149e9..c627fdc62 100644 --- a/Android.bp +++ b/Android.bp @@ -40,6 +40,7 @@ bootstrap_go_package { ], srcs: [ "android/androidmk.go", + "android/apex.go", "android/api_levels.go", "android/arch.go", "android/config.go", diff --git a/android/apex.go b/android/apex.go new file mode 100644 index 000000000..dae88cecc --- /dev/null +++ b/android/apex.go @@ -0,0 +1,102 @@ +// Copyright 2018 Google Inc. All rights reserved. +// +// 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 android + +// ApexModule is the interface that a module type is expected to implement if +// the module has to be built differently depending on whether the module +// is destined for an apex or not (installed to one of the regular partitions). +// +// Native shared libraries are one such module type; when it is built for an +// APEX, it should depend only on stable interfaces such as NDK, stable AIDL, +// or C APIs from other APEXs. +// +// A module implementing this interface will be mutated into multiple +// variations by the apex mutator if it is directly or indirectly included +// in one or more APEXs. Specifically, if a module is included in apex.foo and +// apex.bar then three apex variants are created: platform, apex.foo and +// apex.bar. The platform variant is for the regular partitions +// (e.g., /system or /vendor, etc.) while the other two are for the APEXs, +// respectively. +type ApexModule interface { + Module + apexModuleBase() *ApexModuleBase + + // Marks that this module should be built for the APEX of the specified name + BuildForApex(apexName string) + + // Tests whether this module will be built for the platform or not (= APEXs) + IsForPlatform() bool + + // Returns the name of APEX that this module will be built for. Empty string + // is returned when 'IsForPlatform() == true'. Note that a module can be + // included to multiple APEXs, in which case, the module is mutated into + // multiple modules each of which for an APEX. This method returns the + // name of the APEX that a variant module is for. + ApexName() string + + // Tests if this module can have APEX variants. APEX variants are + // created only for the modules that returns true here. This is useful + // for not creating APEX variants for shared libraries such as NDK stubs. + CanHaveApexVariants() bool + + // Tests if this module can be installed to APEX as a file. For example, + // this would return true for shared libs while return false for static + // libs. + IsInstallableToApex() bool +} + +type ApexProperties struct { + ApexName string `blueprint:"mutated"` +} + +// Provides default implementation for the ApexModule interface. APEX-aware +// modules are expected to include this struct and call InitApexModule(). +type ApexModuleBase struct { + ApexProperties ApexProperties + + canHaveApexVariants bool +} + +func (m *ApexModuleBase) apexModuleBase() *ApexModuleBase { + return m +} + +func (m *ApexModuleBase) BuildForApex(apexName string) { + m.ApexProperties.ApexName = apexName +} + +func (m *ApexModuleBase) IsForPlatform() bool { + return m.ApexProperties.ApexName == "" +} + +func (m *ApexModuleBase) ApexName() string { + return m.ApexProperties.ApexName +} + +func (m *ApexModuleBase) CanHaveApexVariants() bool { + return m.canHaveApexVariants +} + +func (m *ApexModuleBase) IsInstallableToApex() bool { + // should be overriden if needed + return false +} + +func InitApexModule(m ApexModule) { + base := m.apexModuleBase() + base.canHaveApexVariants = true + + m.AddProperties(&base.ApexProperties) +} diff --git a/cc/androidmk.go b/cc/androidmk.go index 5daacb7e4..324b5bc38 100644 --- a/cc/androidmk.go +++ b/cc/androidmk.go @@ -51,7 +51,7 @@ func (c *Module) subAndroidMk(data *android.AndroidMkData, obj interface{}) { } func (c *Module) AndroidMk() android.AndroidMkData { - if c.Properties.HideFromMake { + if c.Properties.HideFromMake || !c.IsForPlatform() { return android.AndroidMkData{ Disabled: true, } diff --git a/cc/cc.go b/cc/cc.go index 5f3baeacc..6320b9c36 100644 --- a/cc/cc.go +++ b/cc/cc.go @@ -320,6 +320,7 @@ var ( type Module struct { android.ModuleBase android.DefaultableModuleBase + android.ApexModuleBase Properties BaseProperties VendorProperties VendorProperties @@ -416,6 +417,8 @@ func (c *Module) Init() android.Module { android.InitDefaultableModule(c) + android.InitApexModule(c) + return c } @@ -794,7 +797,7 @@ func (c *Module) GenerateAndroidBuildActions(actx android.ModuleContext) { c.outputFile = android.OptionalPathForPath(outputFile) } - if c.installer != nil && !c.Properties.PreventInstall && c.outputFile.Valid() { + if c.installer != nil && !c.Properties.PreventInstall && c.IsForPlatform() && c.outputFile.Valid() { c.installer.install(ctx, c.outputFile.Path()) if ctx.Failed() { return @@ -1511,12 +1514,24 @@ func (c *Module) getMakeLinkType() string { } } +// Overrides ApexModule.IsInstallabeToApex() +// Only shared libraries are installable to APEX. +func (c *Module) IsInstallableToApex() bool { + if shared, ok := c.linker.(interface { + shared() bool + }); ok { + return shared.shared() + } + return false +} + // // Defaults // type Defaults struct { android.ModuleBase android.DefaultsModuleBase + android.ApexModuleBase } func (*Defaults) GenerateAndroidBuildActions(ctx android.ModuleContext) { @@ -1558,6 +1573,7 @@ func DefaultsFactory(props ...interface{}) android.Module { ) android.InitDefaultsModule(module) + android.InitApexModule(module) return module }