Pass the name of Soong's checkbuild target for each module to Make so that it can depend on it from the main checkbuild rule. This will give better control over which files get built, allowing checkbuild to skip the jar combining step when transitive classpath jars are enabled. The per-module checkbuild targets are passed to make instead of added directly as a dependency of checkbuild in order to maintain the existing behavior of only building modules exposed to make in checkbuild. Also tweak the existing calls to CheckbuildFile and add InstallFileWithoutCheckbuild to match the files that are in the Make-based checkbuild. Bug: 308016794 Test: m checkbuild Change-Id: Ic5140819381d58f4d00f23a7a12447950c4cf268
326 lines
12 KiB
Go
326 lines
12 KiB
Go
// 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.
|
|
|
|
package sdk
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/google/blueprint"
|
|
"github.com/google/blueprint/proptools"
|
|
|
|
"android/soong/android"
|
|
// This package doesn't depend on the apex package, but import it to make its mutators to be
|
|
// registered before mutators in this package. See RegisterPostDepsMutators for more details.
|
|
_ "android/soong/apex"
|
|
)
|
|
|
|
func init() {
|
|
pctx.Import("android/soong/android")
|
|
pctx.Import("android/soong/java/config")
|
|
|
|
registerSdkBuildComponents(android.InitRegistrationContext)
|
|
}
|
|
|
|
func registerSdkBuildComponents(ctx android.RegistrationContext) {
|
|
ctx.RegisterModuleType("sdk", SdkModuleFactory)
|
|
ctx.RegisterModuleType("sdk_snapshot", SnapshotModuleFactory)
|
|
}
|
|
|
|
type sdk struct {
|
|
android.ModuleBase
|
|
android.DefaultableModuleBase
|
|
|
|
// The dynamically generated information about the registered SdkMemberType
|
|
dynamicSdkMemberTypes *dynamicSdkMemberTypes
|
|
|
|
// The dynamically created instance of the properties struct containing the sdk member type
|
|
// list properties, e.g. java_libs.
|
|
dynamicMemberTypeListProperties interface{}
|
|
|
|
// The dynamically generated information about the registered SdkMemberTrait
|
|
dynamicSdkMemberTraits *dynamicSdkMemberTraits
|
|
|
|
// The dynamically created instance of the properties struct containing the sdk member trait
|
|
// list properties.
|
|
dynamicMemberTraitListProperties interface{}
|
|
|
|
// Information about the OsType specific member variants depended upon by this variant.
|
|
//
|
|
// Set by OsType specific variants in the collectMembers() method and used by the
|
|
// CommonOS variant when building the snapshot. That work is all done on separate
|
|
// calls to the sdk.GenerateAndroidBuildActions method which is guaranteed to be
|
|
// called for the OsType specific variants before the CommonOS variant (because
|
|
// the latter depends on the former).
|
|
memberVariantDeps []sdkMemberVariantDep
|
|
|
|
// The multilib variants that are used by this sdk variant.
|
|
multilibUsages multilibUsage
|
|
|
|
properties sdkProperties
|
|
|
|
snapshotFile android.OptionalPath
|
|
|
|
infoFile android.OptionalPath
|
|
|
|
// The builder, preserved for testing.
|
|
builderForTests *snapshotBuilder
|
|
}
|
|
|
|
type sdkProperties struct {
|
|
Snapshot bool `blueprint:"mutated"`
|
|
|
|
// True if this is a module_exports (or module_exports_snapshot) module type.
|
|
Module_exports bool `blueprint:"mutated"`
|
|
|
|
// The additional visibility to add to the prebuilt modules to allow them to
|
|
// reference each other.
|
|
//
|
|
// This can only be used to widen the visibility of the members:
|
|
//
|
|
// * Specifying //visibility:public here will make all members visible and
|
|
// essentially ignore their own visibility.
|
|
// * Specifying //visibility:private here is an error.
|
|
// * Specifying any other rule here will add it to the members visibility and
|
|
// be output to the member prebuilt in the snapshot. Duplicates will be
|
|
// dropped. Adding a rule to members that have //visibility:private will
|
|
// cause the //visibility:private to be discarded.
|
|
Prebuilt_visibility []string
|
|
}
|
|
|
|
// sdk defines an SDK which is a logical group of modules (e.g. native libs, headers, java libs, etc.)
|
|
// which Mainline modules like APEX can choose to build with.
|
|
func SdkModuleFactory() android.Module {
|
|
return newSdkModule(false)
|
|
}
|
|
|
|
func newSdkModule(moduleExports bool) *sdk {
|
|
s := &sdk{}
|
|
s.properties.Module_exports = moduleExports
|
|
// Get the dynamic sdk member type data for the currently registered sdk member types.
|
|
sdkMemberTypeKey, sdkMemberTypes := android.RegisteredSdkMemberTypes(moduleExports)
|
|
s.dynamicSdkMemberTypes = getDynamicSdkMemberTypes(sdkMemberTypeKey, sdkMemberTypes)
|
|
// Create an instance of the dynamically created struct that contains all the
|
|
// properties for the member type specific list properties.
|
|
s.dynamicMemberTypeListProperties = s.dynamicSdkMemberTypes.createMemberTypeListProperties()
|
|
|
|
sdkMemberTraitsKey, sdkMemberTraits := android.RegisteredSdkMemberTraits()
|
|
s.dynamicSdkMemberTraits = getDynamicSdkMemberTraits(sdkMemberTraitsKey, sdkMemberTraits)
|
|
// Create an instance of the dynamically created struct that contains all the properties for the
|
|
// member trait specific list properties.
|
|
s.dynamicMemberTraitListProperties = s.dynamicSdkMemberTraits.createMemberTraitListProperties()
|
|
|
|
// Create a wrapper around the dynamic trait specific properties so that they have to be
|
|
// specified within a traits:{} section in the .bp file.
|
|
traitsWrapper := struct {
|
|
Traits interface{}
|
|
}{s.dynamicMemberTraitListProperties}
|
|
|
|
s.AddProperties(&s.properties, s.dynamicMemberTypeListProperties, &traitsWrapper)
|
|
|
|
// Make sure that the prebuilt visibility property is verified for errors.
|
|
android.AddVisibilityProperty(s, "prebuilt_visibility", &s.properties.Prebuilt_visibility)
|
|
android.InitCommonOSAndroidMultiTargetsArchModule(s, android.HostAndDeviceSupported, android.MultilibCommon)
|
|
android.InitDefaultableModule(s)
|
|
android.AddLoadHook(s, func(ctx android.LoadHookContext) {
|
|
type props struct {
|
|
Compile_multilib *string
|
|
}
|
|
p := &props{Compile_multilib: proptools.StringPtr("both")}
|
|
ctx.PrependProperties(p)
|
|
})
|
|
return s
|
|
}
|
|
|
|
// sdk_snapshot is a snapshot of an SDK. This is an auto-generated module.
|
|
func SnapshotModuleFactory() android.Module {
|
|
s := newSdkModule(false)
|
|
s.properties.Snapshot = true
|
|
return s
|
|
}
|
|
|
|
func (s *sdk) memberTypeListProperties() []*sdkMemberTypeListProperty {
|
|
return s.dynamicSdkMemberTypes.memberTypeListProperties
|
|
}
|
|
|
|
func (s *sdk) memberTypeListProperty(memberType android.SdkMemberType) *sdkMemberTypeListProperty {
|
|
return s.dynamicSdkMemberTypes.memberTypeToProperty[memberType]
|
|
}
|
|
|
|
// memberTraitListProperties returns the list of *sdkMemberTraitListProperty instances for this sdk.
|
|
func (s *sdk) memberTraitListProperties() []*sdkMemberTraitListProperty {
|
|
return s.dynamicSdkMemberTraits.memberTraitListProperties
|
|
}
|
|
|
|
func (s *sdk) snapshot() bool {
|
|
return s.properties.Snapshot
|
|
}
|
|
|
|
func (s *sdk) GenerateAndroidBuildActions(ctx android.ModuleContext) {
|
|
if s.snapshot() {
|
|
// We don't need to create a snapshot out of sdk_snapshot.
|
|
// That doesn't make sense. We need a snapshot to create sdk_snapshot.
|
|
return
|
|
}
|
|
|
|
// This method is guaranteed to be called on OsType specific variants before it is called
|
|
// on their corresponding CommonOS variant.
|
|
if !s.IsCommonOSVariant() {
|
|
// Update the OsType specific sdk variant with information about its members.
|
|
s.collectMembers(ctx)
|
|
} else {
|
|
// Get the OsType specific variants on which the CommonOS depends.
|
|
osSpecificVariants := android.GetOsSpecificVariantsOfCommonOSVariant(ctx)
|
|
var sdkVariants []*sdk
|
|
for _, m := range osSpecificVariants {
|
|
if sdkVariant, ok := m.(*sdk); ok {
|
|
sdkVariants = append(sdkVariants, sdkVariant)
|
|
}
|
|
}
|
|
|
|
// Generate the snapshot from the member info.
|
|
s.buildSnapshot(ctx, sdkVariants)
|
|
}
|
|
|
|
if s.snapshotFile.Valid() {
|
|
ctx.SetOutputFiles([]android.Path{s.snapshotFile.Path()}, "")
|
|
}
|
|
}
|
|
|
|
func (s *sdk) AndroidMkEntries() []android.AndroidMkEntries {
|
|
if !s.snapshotFile.Valid() != !s.infoFile.Valid() {
|
|
panic("Snapshot (%q) and info file (%q) should both be set or neither should be set.")
|
|
} else if !s.snapshotFile.Valid() {
|
|
return []android.AndroidMkEntries{}
|
|
}
|
|
|
|
return []android.AndroidMkEntries{android.AndroidMkEntries{
|
|
Class: "FAKE",
|
|
OutputFile: s.snapshotFile,
|
|
DistFiles: android.MakeDefaultDistFiles(s.snapshotFile.Path(), s.infoFile.Path()),
|
|
Include: "$(BUILD_PHONY_PACKAGE)",
|
|
ExtraEntries: []android.AndroidMkExtraEntriesFunc{
|
|
func(ctx android.AndroidMkExtraEntriesContext, entries *android.AndroidMkEntries) {
|
|
entries.SetBool("LOCAL_DONT_CHECK_MODULE", true)
|
|
},
|
|
},
|
|
ExtraFooters: []android.AndroidMkExtraFootersFunc{
|
|
func(w io.Writer, name, prefix, moduleDir string) {
|
|
// Allow the sdk to be built by simply passing its name on the command line.
|
|
fmt.Fprintln(w, ".PHONY:", s.Name())
|
|
fmt.Fprintln(w, s.Name()+":", s.snapshotFile.String())
|
|
|
|
// Allow the sdk info to be built by simply passing its name on the command line.
|
|
infoTarget := s.Name() + ".info"
|
|
fmt.Fprintln(w, ".PHONY:", infoTarget)
|
|
fmt.Fprintln(w, infoTarget+":", s.infoFile.String())
|
|
},
|
|
},
|
|
}}
|
|
}
|
|
|
|
// gatherTraits gathers the traits from the dynamically generated trait specific properties.
|
|
//
|
|
// Returns a map from member name to the set of required traits.
|
|
func (s *sdk) gatherTraits() map[string]android.SdkMemberTraitSet {
|
|
traitListByMember := map[string][]android.SdkMemberTrait{}
|
|
for _, memberListProperty := range s.memberTraitListProperties() {
|
|
names := memberListProperty.getter(s.dynamicMemberTraitListProperties)
|
|
for _, name := range names {
|
|
traitListByMember[name] = append(traitListByMember[name], memberListProperty.memberTrait)
|
|
}
|
|
}
|
|
|
|
traitSetByMember := map[string]android.SdkMemberTraitSet{}
|
|
for name, list := range traitListByMember {
|
|
traitSetByMember[name] = android.NewSdkMemberTraitSet(list)
|
|
}
|
|
|
|
return traitSetByMember
|
|
}
|
|
|
|
// newDependencyContext creates a new SdkDependencyContext for this sdk.
|
|
func (s *sdk) newDependencyContext(mctx android.BottomUpMutatorContext) android.SdkDependencyContext {
|
|
traits := s.gatherTraits()
|
|
|
|
return &dependencyContext{
|
|
BottomUpMutatorContext: mctx,
|
|
requiredTraits: traits,
|
|
}
|
|
}
|
|
|
|
type dependencyContext struct {
|
|
android.BottomUpMutatorContext
|
|
|
|
// Map from member name to the set of traits that the sdk requires the member provides.
|
|
requiredTraits map[string]android.SdkMemberTraitSet
|
|
}
|
|
|
|
func (d *dependencyContext) RequiredTraits(name string) android.SdkMemberTraitSet {
|
|
if s, ok := d.requiredTraits[name]; ok {
|
|
return s
|
|
} else {
|
|
return android.EmptySdkMemberTraitSet()
|
|
}
|
|
}
|
|
|
|
func (d *dependencyContext) RequiresTrait(name string, trait android.SdkMemberTrait) bool {
|
|
return d.RequiredTraits(name).Contains(trait)
|
|
}
|
|
|
|
var _ android.SdkDependencyContext = (*dependencyContext)(nil)
|
|
|
|
type dependencyTag struct {
|
|
blueprint.BaseDependencyTag
|
|
}
|
|
|
|
// Mark this tag so dependencies that use it are excluded from APEX contents.
|
|
func (t dependencyTag) ExcludeFromApexContents() {}
|
|
|
|
var _ android.ExcludeFromApexContentsTag = dependencyTag{}
|
|
|
|
func (s *sdk) DepsMutator(mctx android.BottomUpMutatorContext) {
|
|
// Add dependencies from non CommonOS variants to the sdk member variants.
|
|
if s.IsCommonOSVariant() {
|
|
return
|
|
}
|
|
|
|
ctx := s.newDependencyContext(mctx)
|
|
for _, memberListProperty := range s.memberTypeListProperties() {
|
|
if memberListProperty.getter == nil {
|
|
continue
|
|
}
|
|
names := memberListProperty.getter(s.dynamicMemberTypeListProperties)
|
|
if len(names) > 0 {
|
|
memberType := memberListProperty.memberType
|
|
|
|
// Verify that the member type supports the specified traits.
|
|
supportedTraits := memberType.SupportedTraits()
|
|
for _, name := range names {
|
|
requiredTraits := ctx.RequiredTraits(name)
|
|
unsupportedTraits := requiredTraits.Subtract(supportedTraits)
|
|
if !unsupportedTraits.Empty() {
|
|
ctx.ModuleErrorf("sdk member %q has traits %s that are unsupported by its member type %q",
|
|
name, unsupportedTraits, memberType.SdkPropertyName())
|
|
}
|
|
}
|
|
|
|
// Add dependencies using the appropriate tag.
|
|
tag := memberListProperty.dependencyTag
|
|
memberType.AddDependencies(ctx, tag, names)
|
|
}
|
|
}
|
|
}
|