blob: 11ba43037ebbc81897c02d3f4d30e25aec9a0ec5 [file] [log] [blame]
// 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
// 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 []string
if srcsFileInfo, ok := android.OtherModuleProvider(ctx, m, blueprint.SrcsFileProviderKey); ok {
moduleSrcs = srcsFileInfo.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,
}
metadataList = append(metadataList, metadata)
} else {
metadata := &code_metadata_internal_proto.CodeMetadataInternal_TargetOwnership{
TargetName: &targetName,
TrendyTeamId: &module.properties.TeamId,
Path: &bpFilePath,
SourceFiles: moduleSrcs,
}
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.WriteFileRuleVerbatim(ctx, intermediatePath, string(protoData))
android.SetProvider(ctx,
CodeMetadataProviderKey,
CodeMetadataProviderData{IntermediatePath: intermediatePath},
)
}