Support DCLA am: e43124023c

Original change: https://android-review.googlesource.com/c/platform/build/soong/+/2393572

Change-Id: Iae2d689e9c09838a82d78d44416e1629dcb03eb6
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Yu Liu
2023-02-22 01:35:44 +00:00
committed by Automerger Merge Worker
12 changed files with 411 additions and 80 deletions

View File

@@ -1427,4 +1427,20 @@ var (
// It is implicit that all modules in ProdMixedBuildsEnabledList will
// also be built - do not add them to this list.
StagingMixedBuildsEnabledList = []string{}
// These should be the libs that are included by the apexes in the ProdMixedBuildsEnabledList
ProdDclaMixedBuildsEnabledList = []string{}
// These should be the libs that are included by the apexes in the StagingMixedBuildsEnabledList
StagingDclaMixedBuildsEnabledList = []string{
"libbase",
"libc++",
"libcrypto",
"libcutils",
}
// TODO(b/269342245): Enable the rest of the DCLA libs
// "libssl",
// "libstagefright_flacdec",
// "libutils",
)

View File

@@ -352,11 +352,13 @@ func GetBp2BuildAllowList() Bp2BuildConversionAllowlist {
// metrics reporting.
func MixedBuildsEnabled(ctx BaseModuleContext) bool {
module := ctx.Module()
apexInfo := ctx.Provider(ApexInfoProvider).(ApexInfo)
withinApex := !apexInfo.IsForPlatform()
mixedBuildEnabled := ctx.Config().IsMixedBuildsEnabled() &&
ctx.Os() != Windows && // Windows toolchains are not currently supported.
module.Enabled() &&
convertedToBazel(ctx, module) &&
ctx.Config().BazelContext.IsModuleNameAllowed(module.Name())
ctx.Config().BazelContext.IsModuleNameAllowed(module.Name(), withinApex)
ctx.Config().LogMixedBuild(ctx, mixedBuildEnabled)
return mixedBuildEnabled
}

View File

@@ -109,12 +109,29 @@ type cqueryRequest interface {
// Portion of cquery map key to describe target configuration.
type configKey struct {
arch string
osType OsType
arch string
osType OsType
apexKey ApexConfigKey
}
type ApexConfigKey struct {
WithinApex bool
ApexSdkVersion string
}
func (c ApexConfigKey) String() string {
return fmt.Sprintf("%s_%s", withinApexToString(c.WithinApex), c.ApexSdkVersion)
}
func withinApexToString(withinApex bool) string {
if withinApex {
return "within_apex"
}
return ""
}
func (c configKey) String() string {
return fmt.Sprintf("%s::%s", c.arch, c.osType)
return fmt.Sprintf("%s::%s::%s", c.arch, c.osType, c.apexKey)
}
// Map key to describe bazel cquery requests.
@@ -182,7 +199,7 @@ type BazelContext interface {
// Note that this only implies "bazel mixed build" allowlisting. The caller
// should independently verify the module is eligible for Bazel handling
// (for example, that it is MixedBuildBuildable).
IsModuleNameAllowed(moduleName string) bool
IsModuleNameAllowed(moduleName string, withinApex bool) bool
// Returns the bazel output base (the root directory for all bazel intermediate outputs).
OutputBase() string
@@ -235,6 +252,8 @@ type mixedBuildBazelContext struct {
bazelDisabledModules map[string]bool
// Per-module allowlist to opt modules in to bazel handling.
bazelEnabledModules map[string]bool
// DCLA modules are enabled when used in apex.
bazelDclaEnabledModules map[string]bool
// If true, modules are bazel-enabled by default, unless present in bazelDisabledModules.
modulesDefaultToBazel bool
@@ -258,10 +277,16 @@ type MockBazelContext struct {
LabelToPythonBinary map[string]string
LabelToApexInfo map[string]cquery.ApexInfo
LabelToCcBinary map[string]cquery.CcUnstrippedInfo
BazelRequests map[string]bool
}
func (m MockBazelContext) QueueBazelRequest(_ string, _ cqueryRequest, _ configKey) {
panic("unimplemented")
func (m MockBazelContext) QueueBazelRequest(label string, requestType cqueryRequest, cfgKey configKey) {
key := BuildMockBazelContextRequestKey(label, requestType, cfgKey.arch, cfgKey.osType, cfgKey.apexKey)
if m.BazelRequests == nil {
m.BazelRequests = make(map[string]bool)
}
m.BazelRequests[key] = true
}
func (m MockBazelContext) GetOutputFiles(label string, _ configKey) ([]string, error) {
@@ -272,10 +297,14 @@ func (m MockBazelContext) GetOutputFiles(label string, _ configKey) ([]string, e
return result, nil
}
func (m MockBazelContext) GetCcInfo(label string, _ configKey) (cquery.CcInfo, error) {
func (m MockBazelContext) GetCcInfo(label string, cfgKey configKey) (cquery.CcInfo, error) {
result, ok := m.LabelToCcInfo[label]
if !ok {
return cquery.CcInfo{}, fmt.Errorf("no target with label %q in LabelToCcInfo", label)
key := BuildMockBazelContextResultKey(label, cfgKey.arch, cfgKey.osType, cfgKey.apexKey)
result, ok = m.LabelToCcInfo[key]
if !ok {
return cquery.CcInfo{}, fmt.Errorf("no target with label %q in LabelToCcInfo", label)
}
}
return result, nil
}
@@ -308,7 +337,7 @@ func (m MockBazelContext) InvokeBazel(_ Config, _ invokeBazelContext) error {
panic("unimplemented")
}
func (m MockBazelContext) IsModuleNameAllowed(_ string) bool {
func (m MockBazelContext) IsModuleNameAllowed(_ string, _ bool) bool {
return true
}
@@ -324,6 +353,26 @@ func (m MockBazelContext) AqueryDepsets() []bazel.AqueryDepset {
var _ BazelContext = MockBazelContext{}
func BuildMockBazelContextRequestKey(label string, request cqueryRequest, arch string, osType OsType, apexKey ApexConfigKey) string {
cfgKey := configKey{
arch: arch,
osType: osType,
apexKey: apexKey,
}
return strings.Join([]string{label, request.Name(), cfgKey.String()}, "_")
}
func BuildMockBazelContextResultKey(label string, arch string, osType OsType, apexKey ApexConfigKey) string {
cfgKey := configKey{
arch: arch,
osType: osType,
apexKey: apexKey,
}
return strings.Join([]string{label, cfgKey.String()}, "_")
}
func (bazelCtx *mixedBuildBazelContext) QueueBazelRequest(label string, requestType cqueryRequest, cfgKey configKey) {
key := makeCqueryKey(label, requestType, cfgKey)
bazelCtx.requestMutex.Lock()
@@ -430,7 +479,7 @@ func (m noopBazelContext) OutputBase() string {
return ""
}
func (n noopBazelContext) IsModuleNameAllowed(_ string) bool {
func (n noopBazelContext) IsModuleNameAllowed(_ string, _ bool) bool {
return false
}
@@ -442,14 +491,15 @@ func (m noopBazelContext) AqueryDepsets() []bazel.AqueryDepset {
return []bazel.AqueryDepset{}
}
func addToStringSet(set map[string]bool, items []string) {
for _, item := range items {
set[item] = true
}
}
func GetBazelEnabledAndDisabledModules(buildMode SoongBuildMode, forceEnabled map[string]struct{}) (map[string]bool, map[string]bool) {
disabledModules := map[string]bool{}
enabledModules := map[string]bool{}
addToStringSet := func(set map[string]bool, items []string) {
for _, item := range items {
set[item] = true
}
}
switch buildMode {
case BazelProdMode:
@@ -537,15 +587,24 @@ func NewBazelContext(c *config) (BazelContext, error) {
if c.HasDeviceProduct() {
targetProduct = c.DeviceProduct()
}
dclaMixedBuildsEnabledList := []string{}
if c.BuildMode == BazelProdMode {
dclaMixedBuildsEnabledList = allowlists.ProdDclaMixedBuildsEnabledList
} else if c.BuildMode == BazelStagingMode {
dclaMixedBuildsEnabledList = append(allowlists.ProdDclaMixedBuildsEnabledList,
allowlists.StagingDclaMixedBuildsEnabledList...)
}
dclaEnabledModules := map[string]bool{}
addToStringSet(dclaEnabledModules, dclaMixedBuildsEnabledList)
return &mixedBuildBazelContext{
bazelRunner: &builtinBazelRunner{},
paths: &paths,
modulesDefaultToBazel: c.BuildMode == BazelDevMode,
bazelEnabledModules: enabledModules,
bazelDisabledModules: disabledModules,
targetProduct: targetProduct,
targetBuildVariant: targetBuildVariant,
bazelRunner: &builtinBazelRunner{},
paths: &paths,
modulesDefaultToBazel: c.BuildMode == BazelDevMode,
bazelEnabledModules: enabledModules,
bazelDisabledModules: disabledModules,
bazelDclaEnabledModules: dclaEnabledModules,
targetProduct: targetProduct,
targetBuildVariant: targetBuildVariant,
}, nil
}
@@ -553,13 +612,17 @@ func (p *bazelPaths) BazelMetricsDir() string {
return p.metricsDir
}
func (context *mixedBuildBazelContext) IsModuleNameAllowed(moduleName string) bool {
func (context *mixedBuildBazelContext) IsModuleNameAllowed(moduleName string, withinApex bool) bool {
if context.bazelDisabledModules[moduleName] {
return false
}
if context.bazelEnabledModules[moduleName] {
return true
}
if withinApex && context.bazelDclaEnabledModules[moduleName] {
return true
}
return context.modulesDefaultToBazel
}
@@ -696,21 +759,37 @@ func (context *mixedBuildBazelContext) mainBzlFileContents() []byte {
#####################################################
# This file is generated by soong_build. Do not edit.
#####################################################
def _config_node_transition_impl(settings, attr):
if attr.os == "android" and attr.arch == "target":
target = "{PRODUCT}-{VARIANT}"
else:
target = "{PRODUCT}-{VARIANT}_%s_%s" % (attr.os, attr.arch)
return {
apex_name = ""
if attr.within_apex:
# //build/bazel/rules/apex:apex_name has to be set to a non_empty value,
# otherwise //build/bazel/rules/apex:non_apex will be true and the
# "-D__ANDROID_APEX__" compiler flag will be missing. Apex_name is used
# in some validation on bazel side which don't really apply in mixed
# build because soong will do the work, so we just set it to a fixed
# value here.
apex_name = "dcla_apex"
outputs = {
"//command_line_option:platforms": "@soong_injection//product_config_platforms/products/{PRODUCT}-{VARIANT}:%s" % target,
"@//build/bazel/rules/apex:within_apex": attr.within_apex,
"@//build/bazel/rules/apex:min_sdk_version": attr.apex_sdk_version,
"@//build/bazel/rules/apex:apex_name": apex_name,
}
return outputs
_config_node_transition = transition(
implementation = _config_node_transition_impl,
inputs = [],
outputs = [
"//command_line_option:platforms",
"@//build/bazel/rules/apex:within_apex",
"@//build/bazel/rules/apex:min_sdk_version",
"@//build/bazel/rules/apex:apex_name",
],
)
@@ -720,9 +799,11 @@ def _passthrough_rule_impl(ctx):
config_node = rule(
implementation = _passthrough_rule_impl,
attrs = {
"arch" : attr.string(mandatory = True),
"os" : attr.string(mandatory = True),
"deps" : attr.label_list(cfg = _config_node_transition, allow_files = True),
"arch" : attr.string(mandatory = True),
"os" : attr.string(mandatory = True),
"within_apex" : attr.bool(default = False),
"apex_sdk_version" : attr.string(mandatory = True),
"deps" : attr.label_list(cfg = _config_node_transition, allow_files = True),
"_allowlist_function_transition": attr.label(default = "@bazel_tools//tools/allowlists/function_transition_allowlist"),
},
)
@@ -781,6 +862,8 @@ phony_root(name = "phonyroot",
config_node(name = "%s",
arch = "%s",
os = "%s",
within_apex = %s,
apex_sdk_version = "%s",
deps = [%s],
testonly = True, # Unblocks testonly deps.
)
@@ -807,15 +890,28 @@ config_node(name = "%s",
for _, configString := range sortedConfigs {
labels := labelsByConfig[configString]
configTokens := strings.Split(configString, "|")
if len(configTokens) != 2 {
if len(configTokens) < 2 {
panic(fmt.Errorf("Unexpected config string format: %s", configString))
}
archString := configTokens[0]
osString := configTokens[1]
withinApex := "False"
apexSdkVerString := ""
targetString := fmt.Sprintf("%s_%s", osString, archString)
if len(configTokens) > 2 {
targetString += "_" + configTokens[2]
if configTokens[2] == withinApexToString(true) {
withinApex = "True"
}
}
if len(configTokens) > 3 {
targetString += "_" + configTokens[3]
apexSdkVerString = configTokens[3]
}
allLabels = append(allLabels, fmt.Sprintf("\":%s\"", targetString))
labelsString := strings.Join(labels, ",\n ")
configNodesSection += fmt.Sprintf(configNodeFormatString, targetString, archString, osString, labelsString)
configNodesSection += fmt.Sprintf(configNodeFormatString, targetString, archString, osString, withinApex, apexSdkVerString,
labelsString)
}
return []byte(fmt.Sprintf(formatString, configNodesSection, strings.Join(allLabels, ",\n ")))
@@ -911,6 +1007,7 @@ def get_arch(target):
# Soong treats filegroups, but it may not be the case with manually-written
# filegroup BUILD targets.
buildoptions = build_options(target)
if buildoptions == None:
# File targets do not have buildoptions. File targets aren't associated with
# any specific platform architecture in mixed builds, so use the host.
@@ -927,15 +1024,26 @@ def get_arch(target):
if not platform_name.startswith("{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}"):
fail("expected platform name of the form '{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}_android_<arch>' or '{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}_linux_<arch>', but was " + str(platforms))
platform_name = platform_name.removeprefix("{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}").removeprefix("_")
config_key = ""
if not platform_name:
return "target|android"
config_key = "target|android"
elif platform_name.startswith("android_"):
return platform_name.removeprefix("android_") + "|android"
config_key = platform_name.removeprefix("android_") + "|android"
elif platform_name.startswith("linux_"):
return platform_name.removeprefix("linux_") + "|linux"
config_key = platform_name.removeprefix("linux_") + "|linux"
else:
fail("expected platform name of the form '{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}_android_<arch>' or '{TARGET_PRODUCT}-{TARGET_BUILD_VARIANT}_linux_<arch>', but was " + str(platforms))
within_apex = buildoptions.get("//build/bazel/rules/apex:within_apex")
apex_sdk_version = buildoptions.get("//build/bazel/rules/apex:min_sdk_version")
if within_apex:
config_key += "|within_apex"
if apex_sdk_version != None and len(apex_sdk_version) > 0:
config_key += "|" + apex_sdk_version
return config_key
def format(target):
id_string = str(target.label) + "|" + get_arch(target)
@@ -1044,8 +1152,12 @@ func (context *mixedBuildBazelContext) runCquery(config Config, ctx invokeBazelC
return err
}
cqueryCommandWithFlag := context.createBazelCommand(config, context.paths, bazel.CqueryBuildRootRunName, cqueryCmd,
"--output=starlark", "--starlark:file="+absolutePath(cqueryFileRelpath))
extraFlags := []string{"--output=starlark", "--starlark:file=" + absolutePath(cqueryFileRelpath)}
if Bool(config.productVariables.ClangCoverage) {
extraFlags = append(extraFlags, "--collect_code_coverage")
}
cqueryCommandWithFlag := context.createBazelCommand(config, context.paths, bazel.CqueryBuildRootRunName, cqueryCmd, extraFlags...)
cqueryOutput, cqueryErrorMessage, cqueryErr := context.issueBazelCommand(cqueryCommandWithFlag, eventHandler)
if cqueryErr != nil {
return cqueryErr
@@ -1325,7 +1437,16 @@ func getConfigString(key cqueryKey) string {
// Use host OS, which is currently hardcoded to be linux.
osName = "linux"
}
return arch + "|" + osName
keyString := arch + "|" + osName
if key.configKey.apexKey.WithinApex {
keyString += "|" + withinApexToString(key.configKey.apexKey.WithinApex)
}
if len(key.configKey.apexKey.ApexSdkVersion) > 0 {
keyString += "|" + key.configKey.apexKey.ApexSdkVersion
}
return keyString
}
func GetConfigKey(ctx BaseModuleContext) configKey {
@@ -1336,6 +1457,19 @@ func GetConfigKey(ctx BaseModuleContext) configKey {
}
}
func GetConfigKeyApexVariant(ctx BaseModuleContext, apexKey *ApexConfigKey) configKey {
configKey := GetConfigKey(ctx)
if apexKey != nil {
configKey.apexKey = ApexConfigKey{
WithinApex: apexKey.WithinApex,
ApexSdkVersion: apexKey.ApexSdkVersion,
}
}
return configKey
}
func bazelDepsetName(contentHash string) string {
return fmt.Sprintf("bazel_depset_%s", contentHash)
}

View File

@@ -24,20 +24,37 @@ func (t *testInvokeBazelContext) GetEventHandler() *metrics.EventHandler {
}
func TestRequestResultsAfterInvokeBazel(t *testing.T) {
label := "@//foo:bar"
cfg := configKey{"arm64_armv8-a", Android}
label_foo := "@//foo:foo"
label_bar := "@//foo:bar"
apexKey := ApexConfigKey{
WithinApex: true,
ApexSdkVersion: "29",
}
cfg_foo := configKey{"arm64_armv8-a", Android, apexKey}
cfg_bar := configKey{arch: "arm64_armv8-a", osType: Android}
cmd_results := []string{
`@//foo:foo|arm64_armv8-a|android|within_apex|29>>out/foo/foo.txt`,
`@//foo:bar|arm64_armv8-a|android>>out/foo/bar.txt`,
}
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{
bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: `@//foo:bar|arm64_armv8-a|android>>out/foo/bar.txt`,
bazelCommand{command: "cquery", expression: "deps(@soong_injection//mixed_builds:buildroot, 2)"}: strings.Join(cmd_results, "\n"),
})
bazelContext.QueueBazelRequest(label, cquery.GetOutputFiles, cfg)
bazelContext.QueueBazelRequest(label_foo, cquery.GetOutputFiles, cfg_foo)
bazelContext.QueueBazelRequest(label_bar, cquery.GetOutputFiles, cfg_bar)
err := bazelContext.InvokeBazel(testConfig, &testInvokeBazelContext{})
if err != nil {
t.Fatalf("Did not expect error invoking Bazel, but got %s", err)
}
g, err := bazelContext.GetOutputFiles(label, cfg)
verifyCqueryResult(t, bazelContext, label_foo, cfg_foo, "out/foo/foo.txt")
verifyCqueryResult(t, bazelContext, label_bar, cfg_bar, "out/foo/bar.txt")
}
func verifyCqueryResult(t *testing.T, ctx *mixedBuildBazelContext, label string, cfg configKey, result string) {
g, err := ctx.GetOutputFiles(label, cfg)
if err != nil {
t.Errorf("Expected cquery results after running InvokeBazel(), but got err %v", err)
} else if w := []string{"out/foo/bar.txt"}; !reflect.DeepEqual(w, g) {
} else if w := []string{result}; !reflect.DeepEqual(w, g) {
t.Errorf("Expected output %s, got %s", w, g)
}
}
@@ -178,14 +195,18 @@ func TestCoverageFlagsAfterInvokeBazel(t *testing.T) {
func TestBazelRequestsSorted(t *testing.T) {
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})
bazelContext.QueueBazelRequest("zzz", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
bazelContext.QueueBazelRequest("ccc", cquery.GetApexInfo, configKey{"arm64_armv8-a", Android})
bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
bazelContext.QueueBazelRequest("xxx", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Linux})
bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, configKey{"arm64_armv8-a", Android})
bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, configKey{"otherarch", Android})
bazelContext.QueueBazelRequest("bbb", cquery.GetOutputFiles, configKey{"otherarch", Android})
cfgKeyArm64Android := configKey{arch: "arm64_armv8-a", osType: Android}
cfgKeyArm64Linux := configKey{arch: "arm64_armv8-a", osType: Linux}
cfgKeyOtherAndroid := configKey{arch: "otherarch", osType: Android}
bazelContext.QueueBazelRequest("zzz", cquery.GetOutputFiles, cfgKeyArm64Android)
bazelContext.QueueBazelRequest("ccc", cquery.GetApexInfo, cfgKeyArm64Android)
bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, cfgKeyArm64Android)
bazelContext.QueueBazelRequest("duplicate", cquery.GetOutputFiles, cfgKeyArm64Android)
bazelContext.QueueBazelRequest("xxx", cquery.GetOutputFiles, cfgKeyArm64Linux)
bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, cfgKeyArm64Android)
bazelContext.QueueBazelRequest("aaa", cquery.GetOutputFiles, cfgKeyOtherAndroid)
bazelContext.QueueBazelRequest("bbb", cquery.GetOutputFiles, cfgKeyOtherAndroid)
if len(bazelContext.requests) != 7 {
t.Error("Expected 7 request elements, but got", len(bazelContext.requests))
@@ -201,6 +222,52 @@ func TestBazelRequestsSorted(t *testing.T) {
}
}
func TestIsModuleNameAllowed(t *testing.T) {
libDisabled := "lib_disabled"
libEnabled := "lib_enabled"
libDclaWithinApex := "lib_dcla_within_apex"
libDclaNonApex := "lib_dcla_non_apex"
libNotConverted := "lib_not_converted"
disabledModules := map[string]bool{
libDisabled: true,
}
enabledModules := map[string]bool{
libEnabled: true,
}
dclaEnabledModules := map[string]bool{
libDclaWithinApex: true,
libDclaNonApex: true,
}
bazelContext := &mixedBuildBazelContext{
modulesDefaultToBazel: false,
bazelEnabledModules: enabledModules,
bazelDisabledModules: disabledModules,
bazelDclaEnabledModules: dclaEnabledModules,
}
if bazelContext.IsModuleNameAllowed(libDisabled, true) {
t.Fatalf("%s shouldn't be allowed for mixed build", libDisabled)
}
if !bazelContext.IsModuleNameAllowed(libEnabled, true) {
t.Fatalf("%s should be allowed for mixed build", libEnabled)
}
if !bazelContext.IsModuleNameAllowed(libDclaWithinApex, true) {
t.Fatalf("%s should be allowed for mixed build", libDclaWithinApex)
}
if bazelContext.IsModuleNameAllowed(libDclaNonApex, false) {
t.Fatalf("%s shouldn't be allowed for mixed build", libDclaNonApex)
}
if bazelContext.IsModuleNameAllowed(libNotConverted, true) {
t.Fatalf("%s shouldn't be allowed for mixed build", libNotConverted)
}
}
func verifyExtraFlags(t *testing.T, config Config, expected string) string {
bazelContext, _ := testBazelContext(t, map[bazelCommand]string{})

View File

@@ -232,7 +232,7 @@ func (fg *fileGroup) QueueBazelCall(ctx BaseModuleContext) {
bazelCtx.QueueBazelRequest(
fg.GetBazelLabel(ctx, fg),
cquery.GetOutputFiles,
configKey{Common.String(), CommonOS})
configKey{arch: Common.String(), osType: CommonOS})
}
func (fg *fileGroup) IsMixedBuildSupported(ctx BaseModuleContext) bool {
@@ -252,7 +252,7 @@ func (fg *fileGroup) ProcessBazelQueryResponse(ctx ModuleContext) {
relativeRoot = filepath.Join(relativeRoot, *fg.properties.Path)
}
filePaths, err := bazelCtx.GetOutputFiles(fg.GetBazelLabel(ctx, fg), configKey{Common.String(), CommonOS})
filePaths, err := bazelCtx.GetOutputFiles(fg.GetBazelLabel(ctx, fg), configKey{arch: Common.String(), osType: CommonOS})
if err != nil {
ctx.ModuleErrorf(err.Error())
return