// Copyright 2020 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 testing import ( "path/filepath" "android/soong/android" "android/soong/testing/code_metadata_internal_proto" "github.com/google/blueprint" "google.golang.org/protobuf/proto" ) func CodeMetadataFactory() android.Module { module := &CodeMetadataModule{} android.InitAndroidModule(module) android.InitDefaultableModule(module) module.AddProperties(&module.properties) return module } type CodeMetadataModule struct { android.ModuleBase android.DefaultableModuleBase android.BazelModuleBase // Properties for "code_metadata" properties struct { // Specifies the name of the code_config. Name string // Specifies the team ID. TeamId string // Specifies the list of modules that this code_metadata covers. Code []string // An optional field to specify if multiple ownerships for source files is allowed. MultiOwnership bool } } type codeDepTagType struct { blueprint.BaseDependencyTag } var codeDepTag = codeDepTagType{} func (module *CodeMetadataModule) DepsMutator(ctx android.BottomUpMutatorContext) { // Validate Properties if len(module.properties.TeamId) == 0 { ctx.PropertyErrorf( "TeamId", "Team Id not found in the code_metadata module. Hint: Maybe the teamId property hasn't been properly specified.", ) } if !isInt(module.properties.TeamId) { ctx.PropertyErrorf( "TeamId", "Invalid value for Team ID. The Team ID must be an integer.", ) } if len(module.properties.Code) == 0 { ctx.PropertyErrorf( "Code", "Targets to be attributed cannot be empty. Hint: Maybe the code property hasn't been properly specified.", ) } ctx.AddDependency(ctx.Module(), codeDepTag, module.properties.Code...) } // Provider published by CodeMetadata type CodeMetadataProviderData struct { IntermediatePath android.WritablePath } var CodeMetadataProviderKey = blueprint.NewProvider(CodeMetadataProviderData{}) func (module *CodeMetadataModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { metadataList := make( []*code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership, 0, len(module.properties.Code), ) bpFilePath := filepath.Join(ctx.ModuleDir(), ctx.BlueprintsFile()) for _, m := range ctx.GetDirectDepsWithTag(codeDepTag) { targetName := m.Name() var moduleSrcs android.Paths if ctx.OtherModuleHasProvider(m, android.SrcsFileProviderKey) { moduleSrcs = ctx.OtherModuleProvider( m, android.SrcsFileProviderKey, ).(android.SrcsFileProviderData).SrcPaths } if module.properties.MultiOwnership { metadata := &code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{ TargetName: &targetName, TrendyTeamId: &module.properties.TeamId, Path: &bpFilePath, MultiOwnership: &module.properties.MultiOwnership, SourceFiles: moduleSrcs.Strings(), } metadataList = append(metadataList, metadata) } else { metadata := &code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{ TargetName: &targetName, TrendyTeamId: &module.properties.TeamId, Path: &bpFilePath, SourceFiles: moduleSrcs.Strings(), } metadataList = append(metadataList, metadata) } } codeMetadata := &code_metadata_internal_proto.CodeMetadataInternal{TargetOwnershipList: metadataList} protoData, err := proto.Marshal(codeMetadata) if err != nil { ctx.ModuleErrorf("Error marshaling code metadata: %s", err.Error()) return } intermediatePath := android.PathForModuleOut( ctx, "intermediateCodeMetadata.pb", ) android.WriteFileRule(ctx, intermediatePath, string(protoData)) ctx.SetProvider( CodeMetadataProviderKey, CodeMetadataProviderData{IntermediatePath: intermediatePath}, ) }