Implement code-generation step for bp2build.
Implement bp2build codegen as a discrete step that runs after an alternatively registered pipeline of mutators, instead of a presingleton. bp2build codegen requires a Context that supports VisitAllModules and PathContext, so this CL also makes a BpToBuildWrapperContext that conforms to PathContext by adding two method implementations. Test: GENERATE_BAZEL_FILES=true m nothing && bazel query //... --config=bp2build | wc -l # 31433 Test: m queryview && bazel query //... --config=queryview # 63638 Change-Id: I0dd359746584b228046d2d0ff00895f28f9bdfc3
This commit is contained in:
@@ -37,9 +37,6 @@ type singleton struct {
|
|||||||
var singletons []singleton
|
var singletons []singleton
|
||||||
var preSingletons []singleton
|
var preSingletons []singleton
|
||||||
|
|
||||||
var bazelConverterSingletons []singleton
|
|
||||||
var bazelConverterPreSingletons []singleton
|
|
||||||
|
|
||||||
type mutator struct {
|
type mutator struct {
|
||||||
name string
|
name string
|
||||||
bottomUpMutator blueprint.BottomUpMutator
|
bottomUpMutator blueprint.BottomUpMutator
|
||||||
@@ -94,14 +91,6 @@ func RegisterPreSingletonType(name string, factory SingletonFactory) {
|
|||||||
preSingletons = append(preSingletons, singleton{name, factory})
|
preSingletons = append(preSingletons, singleton{name, factory})
|
||||||
}
|
}
|
||||||
|
|
||||||
func RegisterBazelConverterSingletonType(name string, factory SingletonFactory) {
|
|
||||||
bazelConverterSingletons = append(bazelConverterSingletons, singleton{name, factory})
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterBazelConverterPreSingletonType(name string, factory SingletonFactory) {
|
|
||||||
bazelConverterPreSingletons = append(bazelConverterPreSingletons, singleton{name, factory})
|
|
||||||
}
|
|
||||||
|
|
||||||
type Context struct {
|
type Context struct {
|
||||||
*blueprint.Context
|
*blueprint.Context
|
||||||
config Config
|
config Config
|
||||||
@@ -117,21 +106,20 @@ func NewContext(config Config) *Context {
|
|||||||
// singletons, module types and mutators to register for converting Blueprint
|
// singletons, module types and mutators to register for converting Blueprint
|
||||||
// files to semantically equivalent BUILD files.
|
// files to semantically equivalent BUILD files.
|
||||||
func (ctx *Context) RegisterForBazelConversion() {
|
func (ctx *Context) RegisterForBazelConversion() {
|
||||||
for _, t := range bazelConverterPreSingletons {
|
|
||||||
ctx.RegisterPreSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, t := range moduleTypes {
|
for _, t := range moduleTypes {
|
||||||
ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory))
|
ctx.RegisterModuleType(t.name, ModuleFactoryAdaptor(t.factory))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, t := range bazelConverterSingletons {
|
// Required for SingletonModule types, even though we are not using them.
|
||||||
|
for _, t := range singletons {
|
||||||
ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
|
ctx.RegisterSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
|
||||||
}
|
}
|
||||||
|
|
||||||
registerMutatorsForBazelConversion(ctx.Context)
|
registerMutatorsForBazelConversion(ctx.Context)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Register the pipeline of singletons, module types, and mutators for
|
||||||
|
// generating build.ninja and other files for Kati, from Android.bp files.
|
||||||
func (ctx *Context) Register() {
|
func (ctx *Context) Register() {
|
||||||
for _, t := range preSingletons {
|
for _, t := range preSingletons {
|
||||||
ctx.RegisterPreSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
|
ctx.RegisterPreSingletonType(t.name, SingletonFactoryAdaptor(ctx, t.factory))
|
||||||
|
@@ -16,52 +16,34 @@ package bp2build
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The Bazel bp2build singleton is responsible for writing .bzl files that are equivalent to
|
// The Bazel bp2build code generator is responsible for writing .bzl files that are equivalent to
|
||||||
// Android.bp files that are capable of being built with Bazel.
|
// Android.bp files that are capable of being built with Bazel.
|
||||||
func init() {
|
func Codegen(ctx CodegenContext) {
|
||||||
android.RegisterBazelConverterPreSingletonType("androidbp_to_build", AndroidBpToBuildSingleton)
|
outputDir := android.PathForOutput(ctx, "bp2build")
|
||||||
}
|
android.RemoveAllOutputDir(outputDir)
|
||||||
|
|
||||||
func AndroidBpToBuildSingleton() android.Singleton {
|
|
||||||
return &androidBpToBuildSingleton{
|
|
||||||
name: "bp2build",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type androidBpToBuildSingleton struct {
|
|
||||||
name string
|
|
||||||
outputDir android.OutputPath
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *androidBpToBuildSingleton) GenerateBuildActions(ctx android.SingletonContext) {
|
|
||||||
s.outputDir = android.PathForOutput(ctx, s.name)
|
|
||||||
android.RemoveAllOutputDir(s.outputDir)
|
|
||||||
|
|
||||||
if !ctx.Config().IsEnvTrue("CONVERT_TO_BAZEL") {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ruleShims := CreateRuleShims(android.ModuleTypeFactories())
|
ruleShims := CreateRuleShims(android.ModuleTypeFactories())
|
||||||
|
|
||||||
buildToTargets := GenerateSoongModuleTargets(ctx)
|
buildToTargets := GenerateSoongModuleTargets(ctx.Context())
|
||||||
|
|
||||||
filesToWrite := CreateBazelFiles(ruleShims, buildToTargets)
|
filesToWrite := CreateBazelFiles(ruleShims, buildToTargets)
|
||||||
for _, f := range filesToWrite {
|
for _, f := range filesToWrite {
|
||||||
if err := s.writeFile(ctx, f); err != nil {
|
if err := writeFile(outputDir, ctx, f); err != nil {
|
||||||
ctx.Errorf("Failed to write %q (dir %q) due to %q", f.Basename, f.Dir, err)
|
fmt.Errorf("Failed to write %q (dir %q) due to %q", f.Basename, f.Dir, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *androidBpToBuildSingleton) getOutputPath(ctx android.PathContext, dir string) android.OutputPath {
|
func writeFile(outputDir android.OutputPath, ctx android.PathContext, f BazelFile) error {
|
||||||
return s.outputDir.Join(ctx, dir)
|
return writeReadOnlyFile(ctx, getOutputPath(outputDir, ctx, f.Dir), f.Basename, f.Contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *androidBpToBuildSingleton) writeFile(ctx android.PathContext, f BazelFile) error {
|
func getOutputPath(outputDir android.OutputPath, ctx android.PathContext, dir string) android.OutputPath {
|
||||||
return writeReadOnlyFile(ctx, s.getOutputPath(ctx, f.Dir), f.Basename, f.Contents)
|
return outputDir.Join(ctx, dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The auto-conversion directory should be read-only, sufficient for bazel query. The files
|
// The auto-conversion directory should be read-only, sufficient for bazel query. The files
|
||||||
|
@@ -39,8 +39,26 @@ type bpToBuildContext interface {
|
|||||||
ModuleSubDir(module blueprint.Module) string
|
ModuleSubDir(module blueprint.Module) string
|
||||||
ModuleType(module blueprint.Module) string
|
ModuleType(module blueprint.Module) string
|
||||||
|
|
||||||
VisitAllModulesBlueprint(visit func(blueprint.Module))
|
VisitAllModules(visit func(blueprint.Module))
|
||||||
VisitDirectDeps(module android.Module, visit func(android.Module))
|
VisitDirectDeps(module blueprint.Module, visit func(blueprint.Module))
|
||||||
|
}
|
||||||
|
|
||||||
|
type CodegenContext struct {
|
||||||
|
config android.Config
|
||||||
|
context android.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ctx CodegenContext) AddNinjaFileDeps(...string) {}
|
||||||
|
func (ctx CodegenContext) Config() android.Config { return ctx.config }
|
||||||
|
func (ctx CodegenContext) Context() android.Context { return ctx.context }
|
||||||
|
|
||||||
|
// NewCodegenContext creates a wrapper context that conforms to PathContext for
|
||||||
|
// writing BUILD files in the output directory.
|
||||||
|
func NewCodegenContext(config android.Config, context android.Context) CodegenContext {
|
||||||
|
return CodegenContext{
|
||||||
|
context: context,
|
||||||
|
config: config,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// props is an unsorted map. This function ensures that
|
// props is an unsorted map. This function ensures that
|
||||||
@@ -57,7 +75,7 @@ func propsToAttributes(props map[string]string) string {
|
|||||||
|
|
||||||
func GenerateSoongModuleTargets(ctx bpToBuildContext) map[string][]BazelTarget {
|
func GenerateSoongModuleTargets(ctx bpToBuildContext) map[string][]BazelTarget {
|
||||||
buildFileToTargets := make(map[string][]BazelTarget)
|
buildFileToTargets := make(map[string][]BazelTarget)
|
||||||
ctx.VisitAllModulesBlueprint(func(m blueprint.Module) {
|
ctx.VisitAllModules(func(m blueprint.Module) {
|
||||||
dir := ctx.ModuleDir(m)
|
dir := ctx.ModuleDir(m)
|
||||||
t := generateSoongModuleTarget(ctx, m)
|
t := generateSoongModuleTarget(ctx, m)
|
||||||
buildFileToTargets[ctx.ModuleDir(m)] = append(buildFileToTargets[dir], t)
|
buildFileToTargets[ctx.ModuleDir(m)] = append(buildFileToTargets[dir], t)
|
||||||
@@ -75,7 +93,7 @@ func generateSoongModuleTarget(ctx bpToBuildContext, m blueprint.Module) BazelTa
|
|||||||
// out the implications of that.
|
// out the implications of that.
|
||||||
depLabels := map[string]bool{}
|
depLabels := map[string]bool{}
|
||||||
if aModule, ok := m.(android.Module); ok {
|
if aModule, ok := m.(android.Module); ok {
|
||||||
ctx.VisitDirectDeps(aModule, func(depModule android.Module) {
|
ctx.VisitDirectDeps(aModule, func(depModule blueprint.Module) {
|
||||||
depLabels[qualifiedTargetLabel(ctx, depModule)] = true
|
depLabels[qualifiedTargetLabel(ctx, depModule)] = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -200,11 +200,7 @@ func TestGenerateSoongModuleTargets(t *testing.T) {
|
|||||||
_, errs = ctx.PrepareBuildActions(config)
|
_, errs = ctx.PrepareBuildActions(config)
|
||||||
android.FailIfErrored(t, errs)
|
android.FailIfErrored(t, errs)
|
||||||
|
|
||||||
bp2BuildCtx := bp2buildBlueprintWrapContext{
|
bazelTargets := GenerateSoongModuleTargets(ctx.Context.Context)[dir]
|
||||||
bpCtx: ctx.Context.Context,
|
|
||||||
}
|
|
||||||
|
|
||||||
bazelTargets := GenerateSoongModuleTargets(&bp2BuildCtx)[dir]
|
|
||||||
if g, w := len(bazelTargets), 1; g != w {
|
if g, w := len(bazelTargets), 1; g != w {
|
||||||
t.Fatalf("Expected %d bazel target, got %d", w, g)
|
t.Fatalf("Expected %d bazel target, got %d", w, g)
|
||||||
}
|
}
|
||||||
|
@@ -2,8 +2,6 @@ package bp2build
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
|
|
||||||
"github.com/google/blueprint"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type nestedProps struct {
|
type nestedProps struct {
|
||||||
@@ -102,35 +100,3 @@ func customDefaultsModuleFactory() android.Module {
|
|||||||
android.InitDefaultsModule(m)
|
android.InitDefaultsModule(m)
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
type bp2buildBlueprintWrapContext struct {
|
|
||||||
bpCtx *blueprint.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *bp2buildBlueprintWrapContext) ModuleName(module blueprint.Module) string {
|
|
||||||
return ctx.bpCtx.ModuleName(module)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *bp2buildBlueprintWrapContext) ModuleDir(module blueprint.Module) string {
|
|
||||||
return ctx.bpCtx.ModuleDir(module)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *bp2buildBlueprintWrapContext) ModuleSubDir(module blueprint.Module) string {
|
|
||||||
return ctx.bpCtx.ModuleSubDir(module)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *bp2buildBlueprintWrapContext) ModuleType(module blueprint.Module) string {
|
|
||||||
return ctx.bpCtx.ModuleType(module)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *bp2buildBlueprintWrapContext) VisitAllModulesBlueprint(visit func(blueprint.Module)) {
|
|
||||||
ctx.bpCtx.VisitAllModules(visit)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *bp2buildBlueprintWrapContext) VisitDirectDeps(module android.Module, visit func(android.Module)) {
|
|
||||||
ctx.bpCtx.VisitDirectDeps(module, func(m blueprint.Module) {
|
|
||||||
if aModule, ok := m.(android.Module); ok {
|
|
||||||
visit(aModule)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
@@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/google/blueprint/bootstrap"
|
"github.com/google/blueprint/bootstrap"
|
||||||
|
|
||||||
"android/soong/android"
|
"android/soong/android"
|
||||||
|
"android/soong/bp2build"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -54,18 +55,12 @@ func newNameResolver(config android.Config) *android.NameResolver {
|
|||||||
// bazelConversionRequested checks that the user is intending to convert
|
// bazelConversionRequested checks that the user is intending to convert
|
||||||
// Blueprint to Bazel BUILD files.
|
// Blueprint to Bazel BUILD files.
|
||||||
func bazelConversionRequested(configuration android.Config) bool {
|
func bazelConversionRequested(configuration android.Config) bool {
|
||||||
return configuration.IsEnvTrue("CONVERT_TO_BAZEL")
|
return configuration.IsEnvTrue("GENERATE_BAZEL_FILES")
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContext(srcDir string, configuration android.Config) *android.Context {
|
func newContext(configuration android.Config) *android.Context {
|
||||||
ctx := android.NewContext(configuration)
|
ctx := android.NewContext(configuration)
|
||||||
if bazelConversionRequested(configuration) {
|
ctx.Register()
|
||||||
// Register an alternate set of singletons and mutators for bazel
|
|
||||||
// conversion for Bazel conversion.
|
|
||||||
ctx.RegisterForBazelConversion()
|
|
||||||
} else {
|
|
||||||
ctx.Register()
|
|
||||||
}
|
|
||||||
if !shouldPrepareBuildActions(configuration) {
|
if !shouldPrepareBuildActions(configuration) {
|
||||||
configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
|
configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
|
||||||
}
|
}
|
||||||
@@ -100,13 +95,22 @@ func main() {
|
|||||||
// enabled even if it completed successfully.
|
// enabled even if it completed successfully.
|
||||||
extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve"))
|
extraNinjaDeps = append(extraNinjaDeps, filepath.Join(configuration.BuildDir(), "always_rerun_for_delve"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if bazelConversionRequested(configuration) {
|
||||||
|
// Run the alternate pipeline of bp2build mutators and singleton to convert Blueprint to BUILD files
|
||||||
|
// before everything else.
|
||||||
|
runBp2Build(configuration, extraNinjaDeps)
|
||||||
|
// Short-circuit and return.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if configuration.BazelContext.BazelEnabled() {
|
if configuration.BazelContext.BazelEnabled() {
|
||||||
// Bazel-enabled mode. Soong runs in two passes.
|
// Bazel-enabled mode. Soong runs in two passes.
|
||||||
// First pass: Analyze the build tree, but only store all bazel commands
|
// First pass: Analyze the build tree, but only store all bazel commands
|
||||||
// needed to correctly evaluate the tree in the second pass.
|
// needed to correctly evaluate the tree in the second pass.
|
||||||
// TODO(cparsons): Don't output any ninja file, as the second pass will overwrite
|
// TODO(cparsons): Don't output any ninja file, as the second pass will overwrite
|
||||||
// the incorrect results from the first pass, and file I/O is expensive.
|
// the incorrect results from the first pass, and file I/O is expensive.
|
||||||
firstCtx := newContext(srcDir, configuration)
|
firstCtx := newContext(configuration)
|
||||||
configuration.SetStopBefore(bootstrap.StopBeforeWriteNinja)
|
configuration.SetStopBefore(bootstrap.StopBeforeWriteNinja)
|
||||||
bootstrap.Main(firstCtx.Context, configuration, extraNinjaDeps...)
|
bootstrap.Main(firstCtx.Context, configuration, extraNinjaDeps...)
|
||||||
// Invoke bazel commands and save results for second pass.
|
// Invoke bazel commands and save results for second pass.
|
||||||
@@ -120,10 +124,10 @@ func main() {
|
|||||||
fmt.Fprintf(os.Stderr, "%s", err)
|
fmt.Fprintf(os.Stderr, "%s", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
ctx = newContext(srcDir, secondPassConfig)
|
ctx = newContext(secondPassConfig)
|
||||||
bootstrap.Main(ctx.Context, secondPassConfig, extraNinjaDeps...)
|
bootstrap.Main(ctx.Context, secondPassConfig, extraNinjaDeps...)
|
||||||
} else {
|
} else {
|
||||||
ctx = newContext(srcDir, configuration)
|
ctx = newContext(configuration)
|
||||||
bootstrap.Main(ctx.Context, configuration, extraNinjaDeps...)
|
bootstrap.Main(ctx.Context, configuration, extraNinjaDeps...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +158,22 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Run Soong in the bp2build mode. This creates a standalone context that registers
|
||||||
|
// an alternate pipeline of mutators and singletons specifically for generating
|
||||||
|
// Bazel BUILD files instead of Ninja files.
|
||||||
|
func runBp2Build(configuration android.Config, extraNinjaDeps []string) {
|
||||||
|
// Register an alternate set of singletons and mutators for bazel
|
||||||
|
// conversion for Bazel conversion.
|
||||||
|
bp2buildCtx := android.NewContext(configuration)
|
||||||
|
bp2buildCtx.RegisterForBazelConversion()
|
||||||
|
configuration.SetStopBefore(bootstrap.StopBeforePrepareBuildActions)
|
||||||
|
bp2buildCtx.SetNameInterface(newNameResolver(configuration))
|
||||||
|
bootstrap.Main(bp2buildCtx.Context, configuration, extraNinjaDeps...)
|
||||||
|
|
||||||
|
codegenContext := bp2build.NewCodegenContext(configuration, *bp2buildCtx)
|
||||||
|
bp2build.Codegen(codegenContext)
|
||||||
|
}
|
||||||
|
|
||||||
// shouldPrepareBuildActions reads configuration and flags if build actions
|
// shouldPrepareBuildActions reads configuration and flags if build actions
|
||||||
// should be generated.
|
// should be generated.
|
||||||
func shouldPrepareBuildActions(configuration android.Config) bool {
|
func shouldPrepareBuildActions(configuration android.Config) bool {
|
||||||
|
@@ -20,48 +20,11 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/google/blueprint"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type queryviewContext struct {
|
|
||||||
bpCtx *blueprint.Context
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *queryviewContext) ModuleName(module blueprint.Module) string {
|
|
||||||
return ctx.bpCtx.ModuleName(module)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *queryviewContext) ModuleDir(module blueprint.Module) string {
|
|
||||||
return ctx.bpCtx.ModuleDir(module)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *queryviewContext) ModuleSubDir(module blueprint.Module) string {
|
|
||||||
return ctx.bpCtx.ModuleSubDir(module)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *queryviewContext) ModuleType(module blueprint.Module) string {
|
|
||||||
return ctx.bpCtx.ModuleType(module)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *queryviewContext) VisitAllModulesBlueprint(visit func(blueprint.Module)) {
|
|
||||||
ctx.bpCtx.VisitAllModules(visit)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ctx *queryviewContext) VisitDirectDeps(module android.Module, visit func(android.Module)) {
|
|
||||||
ctx.bpCtx.VisitDirectDeps(module, func(m blueprint.Module) {
|
|
||||||
if aModule, ok := m.(android.Module); ok {
|
|
||||||
visit(aModule)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func createBazelQueryView(ctx *android.Context, bazelQueryViewDir string) error {
|
func createBazelQueryView(ctx *android.Context, bazelQueryViewDir string) error {
|
||||||
qvCtx := queryviewContext{
|
|
||||||
bpCtx: ctx.Context,
|
|
||||||
}
|
|
||||||
ruleShims := bp2build.CreateRuleShims(android.ModuleTypeFactories())
|
ruleShims := bp2build.CreateRuleShims(android.ModuleTypeFactories())
|
||||||
buildToTargets := bp2build.GenerateSoongModuleTargets(&qvCtx)
|
buildToTargets := bp2build.GenerateSoongModuleTargets(*ctx)
|
||||||
|
|
||||||
filesToWrite := bp2build.CreateBazelFiles(ruleShims, buildToTargets)
|
filesToWrite := bp2build.CreateBazelFiles(ruleShims, buildToTargets)
|
||||||
for _, f := range filesToWrite {
|
for _, f := range filesToWrite {
|
||||||
|
Reference in New Issue
Block a user