blob: 426b0de842d0f046ea1c414c8d7ab9a54d3af12e [file] [log] [blame]
// Copyright 2022 Google LLC
//
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This program generates file //bazel/devicesrc.
//go:generate bazelisk run //bazel/device_specific_configs/generate -- --output-file ${PWD}/../../devicesrc
package main
import (
"flag"
"fmt"
"os"
"sort"
"strings"
"go.skia.org/skia/bazel/device_specific_configs"
)
const header = "# GENERATED FILE - Please do not edit.\n\n"
func writeFlag(sb *strings.Builder, configName, flagName, flagValue string) {
_, _ = sb.WriteString(fmt.Sprintf("test:%s %s=%s\n", configName, flagName, flagValue))
}
func writeTestArgFlag(sb *strings.Builder, configName, testArgFlag string) {
_, _ = sb.WriteString(fmt.Sprintf("test:%s --test_arg=%s\n", configName, testArgFlag))
}
func writeDeviceFlagsFile(outputFile string) error {
// Sort for determinism.
var configNames []string
for configName := range device_specific_configs.Configs {
configNames = append(configNames, configName)
}
sort.Strings(configNames)
var sb strings.Builder
_, _ = sb.WriteString(header)
for i, configName := range configNames {
if i > 0 {
sb.WriteString("\n")
}
// Force device-specific tests to run locally (as opposed to on RBE). For such tests, we assume
// Bazel is running on the device under test, or on a machine that controls the device under
// test (e.g. an Android device attached via USB). Compilation still happens on RBE.
//
// We force local execution via the --strategy flag[1]. In order to understand the --strategy
// flag, we must first understand the --spawn_strategy flag[2], which controls where and how
// commands are executed. For example:
//
// - Flag --spawn_strategy=sandboxed executes commands inside a sandbox on the local system.
// This is the default Bazel behavior on systems that support sandboxing.
//
// - Flag --spawn_strategy=local executes commands as regular, local subprocesses without any
// sandboxing.
//
// - Flag --spawn_strategy=remote executes commands remotely, provided a remote executor has
// been configured. We use this strategy when running Bazel with --config=remote. See the
// //.bazelrc file[3].
//
// The --strategy flag allows us to override --spawn_strategy on a per-mnemonic basis. In our
// case, we set --strategy=TestRunner=local to force test actions to run as a local subprocess.
// In combination with --config=remote (or any configuration that implies it, such as
// --config=linux_rbe) this has the effect of running test actions locally, while build actions
// (and any other actions) run on RBE.
//
// The "TestRunner" mnemonic for test actions is determined here[4].
//
// [1] https://bazel.build/docs/user-manual#strategy
// [2] https://bazel.build/docs/user-manual#spawn-strategy
// [3] https://skia.googlesource.com/skia/+/e5c37860c792de6bba0c9465c3f5280cb13dbbb9/.bazelrc#128
// [4] https://github.com/bazelbuild/bazel/blob/f79ca0275e14d7c8fb478bd910ad7fb127440fd8/src/main/java/com/google/devtools/build/lib/analysis/test/TestRunnerAction.java#L107
writeFlag(&sb, configName, "--strategy", "TestRunner=local")
config := device_specific_configs.Configs[configName]
for _, arg := range config.TestRunnerArgs() {
writeTestArgFlag(&sb, configName, arg)
}
}
return os.WriteFile(outputFile, []byte(sb.String()), 0644)
}
func main() {
outputFileFlag := flag.String("output-file", "", "Path to the output file.")
flag.Parse()
if *outputFileFlag == "" {
fmt.Println("Flag --output-file is required.")
os.Exit(1)
}
if err := writeDeviceFlagsFile(*outputFileFlag); err != nil {
fmt.Printf("error: %s\n", err)
os.Exit(1)
}
}