1// Copyright 2020 Google Inc. All rights reserved. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package testing 16 17import ( 18 "path/filepath" 19 20 "android/soong/android" 21 "android/soong/testing/code_metadata_internal_proto" 22 "github.com/google/blueprint" 23 24 "google.golang.org/protobuf/proto" 25) 26 27func CodeMetadataFactory() android.Module { 28 module := &CodeMetadataModule{} 29 30 android.InitAndroidModule(module) 31 android.InitDefaultableModule(module) 32 module.AddProperties(&module.properties) 33 34 return module 35} 36 37type CodeMetadataModule struct { 38 android.ModuleBase 39 android.DefaultableModuleBase 40 41 // Properties for "code_metadata" 42 properties struct { 43 // Specifies the name of the code_config. 44 Name string 45 // Specifies the team ID. 46 TeamId string 47 // Specifies the list of modules that this code_metadata covers. 48 Code []string 49 // An optional field to specify if multiple ownerships for source files is allowed. 50 MultiOwnership bool 51 } 52} 53 54type codeDepTagType struct { 55 blueprint.BaseDependencyTag 56} 57 58var codeDepTag = codeDepTagType{} 59 60func (module *CodeMetadataModule) DepsMutator(ctx android.BottomUpMutatorContext) { 61 // Validate Properties 62 if len(module.properties.TeamId) == 0 { 63 ctx.PropertyErrorf( 64 "TeamId", 65 "Team Id not found in the code_metadata module. Hint: Maybe the teamId property hasn't been properly specified.", 66 ) 67 } 68 if !isInt(module.properties.TeamId) { 69 ctx.PropertyErrorf( 70 "TeamId", "Invalid value for Team ID. The Team ID must be an integer.", 71 ) 72 } 73 if len(module.properties.Code) == 0 { 74 ctx.PropertyErrorf( 75 "Code", 76 "Targets to be attributed cannot be empty. Hint: Maybe the code property hasn't been properly specified.", 77 ) 78 } 79 ctx.AddDependency(ctx.Module(), codeDepTag, module.properties.Code...) 80} 81 82// Provider published by CodeMetadata 83type CodeMetadataProviderData struct { 84 IntermediatePath android.WritablePath 85} 86 87var CodeMetadataProviderKey = blueprint.NewProvider[CodeMetadataProviderData]() 88 89func (module *CodeMetadataModule) GenerateAndroidBuildActions(ctx android.ModuleContext) { 90 metadataList := make( 91 []*code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership, 0, 92 len(module.properties.Code), 93 ) 94 bpFilePath := filepath.Join(ctx.ModuleDir(), ctx.BlueprintsFile()) 95 96 for _, m := range ctx.GetDirectDepsWithTag(codeDepTag) { 97 targetName := m.Name() 98 var moduleSrcs []string 99 if srcsFileInfo, ok := android.OtherModuleProvider(ctx, m, blueprint.SrcsFileProviderKey); ok { 100 moduleSrcs = srcsFileInfo.SrcPaths 101 } 102 if module.properties.MultiOwnership { 103 metadata := &code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{ 104 TargetName: &targetName, 105 TrendyTeamId: &module.properties.TeamId, 106 Path: &bpFilePath, 107 MultiOwnership: &module.properties.MultiOwnership, 108 SourceFiles: moduleSrcs, 109 } 110 metadataList = append(metadataList, metadata) 111 } else { 112 metadata := &code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{ 113 TargetName: &targetName, 114 TrendyTeamId: &module.properties.TeamId, 115 Path: &bpFilePath, 116 SourceFiles: moduleSrcs, 117 } 118 metadataList = append(metadataList, metadata) 119 } 120 121 } 122 codeMetadata := &code_metadata_internal_proto.CodeMetadataInternal{TargetOwnershipList: metadataList} 123 protoData, err := proto.Marshal(codeMetadata) 124 if err != nil { 125 ctx.ModuleErrorf("Error marshaling code metadata: %s", err.Error()) 126 return 127 } 128 intermediatePath := android.PathForModuleOut( 129 ctx, "intermediateCodeMetadata.pb", 130 ) 131 android.WriteFileRuleVerbatim(ctx, intermediatePath, string(protoData)) 132 133 android.SetProvider(ctx, 134 CodeMetadataProviderKey, 135 CodeMetadataProviderData{IntermediatePath: intermediatePath}, 136 ) 137} 138