diff --git a/pkg/plugin/akka/akka_grpc/protoc_gen_akka_grpc_test.go b/pkg/plugin/akka/akka_grpc/protoc_gen_akka_grpc_test.go index d54a63031..e12832b6d 100644 --- a/pkg/plugin/akka/akka_grpc/protoc_gen_akka_grpc_test.go +++ b/pkg/plugin/akka/akka_grpc/protoc_gen_akka_grpc_test.go @@ -32,6 +32,7 @@ func TestProtoGenAkkaGrpcPlugin(t *testing.T) { ), PluginName: "akka", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/akka/akka-grpc:protoc-gen-akka-grpc"), plugintest.WithOutputs("test_akka_grpc.srcjar"), ), SkipIntegration: true, diff --git a/pkg/plugin/builtin/cpp_plugin_test.go b/pkg/plugin/builtin/cpp_plugin_test.go index a99fedf60..07c06821e 100644 --- a/pkg/plugin/builtin/cpp_plugin_test.go +++ b/pkg/plugin/builtin/cpp_plugin_test.go @@ -16,6 +16,7 @@ func TestCppPlugin(t *testing.T) { ), PluginName: "cpp", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:cpp"), plugintest.WithOutputs("test.pb.cc", "test.pb.h"), ), }, @@ -26,6 +27,7 @@ func TestCppPlugin(t *testing.T) { "proto_plugin", "cpp implementation builtin:cpp", ), Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:cpp"), plugintest.WithOutputs("test.pb.cc", "test.pb.h"), ), }, @@ -36,6 +38,7 @@ func TestCppPlugin(t *testing.T) { "proto_plugin", "cpp implementation builtin:cpp", ), Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:cpp"), plugintest.WithOutputs("test.pb.cc", "test.pb.h"), ), }, @@ -47,6 +50,7 @@ func TestCppPlugin(t *testing.T) { "proto_plugin", "cpp implementation builtin:cpp", ), Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:cpp"), plugintest.WithOutputs("rel/test.pb.cc", "rel/test.pb.h"), ), }, @@ -58,6 +62,7 @@ func TestCppPlugin(t *testing.T) { "proto_plugin", "cpp implementation builtin:cpp", ), Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:cpp"), plugintest.WithOutputs("snake_case.pb.cc", "snake_case.pb.h"), ), }, @@ -69,6 +74,7 @@ func TestCppPlugin(t *testing.T) { "proto_plugin", "cpp implementation builtin:cpp", ), Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:cpp"), plugintest.WithOutputs("PascalCase.pb.cc", "PascalCase.pb.h"), ), }, @@ -80,6 +86,7 @@ func TestCppPlugin(t *testing.T) { "proto_plugin", "cpp implementation builtin:cpp", ), Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:cpp"), plugintest.WithOutputs("camelCase.pb.cc", "camelCase.pb.h"), ), }, diff --git a/pkg/plugin/builtin/csharp_plugin_test.go b/pkg/plugin/builtin/csharp_plugin_test.go index 080f6e2c1..32e277ce4 100644 --- a/pkg/plugin/builtin/csharp_plugin_test.go +++ b/pkg/plugin/builtin/csharp_plugin_test.go @@ -17,6 +17,7 @@ func TestCsharpPlugin(t *testing.T) { ), PluginName: "csharp", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:csharp"), plugintest.WithOutputs("Test.cs"), ), }, @@ -28,6 +29,7 @@ func TestCsharpPlugin(t *testing.T) { ), PluginName: "csharp", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:csharp"), plugintest.WithOutputs("Test.cs"), ), }, @@ -39,6 +41,7 @@ func TestCsharpPlugin(t *testing.T) { ), PluginName: "csharp", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:csharp"), plugintest.WithOutputs("Test.cs"), ), }, @@ -49,6 +52,7 @@ func TestCsharpPlugin(t *testing.T) { ), PluginName: "csharp", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:csharp"), plugintest.WithOutputs("Test.cs"), ), }, @@ -60,7 +64,9 @@ func TestCsharpPlugin(t *testing.T) { ), PluginName: "csharp", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:csharp"), plugintest.WithOutputs("rel/Test.cs"), + plugintest.WithOut("rel"), ), }, "basename converted to pascal": { @@ -71,6 +77,7 @@ func TestCsharpPlugin(t *testing.T) { ), PluginName: "csharp", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:csharp"), plugintest.WithOutputs("FooBarBaz.cs"), ), }, diff --git a/pkg/plugin/builtin/java_plugin_test.go b/pkg/plugin/builtin/java_plugin_test.go index ce60181d6..1723bc84a 100644 --- a/pkg/plugin/builtin/java_plugin_test.go +++ b/pkg/plugin/builtin/java_plugin_test.go @@ -16,7 +16,9 @@ func TestJavaPlugin(t *testing.T) { ), PluginName: "java", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:java"), plugintest.WithOutputs("test.srcjar"), + plugintest.WithOut("test.srcjar"), ), }, "message with a package": { @@ -26,7 +28,9 @@ func TestJavaPlugin(t *testing.T) { ), PluginName: "java", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:java"), plugintest.WithOutputs("test.srcjar"), + plugintest.WithOut("test.srcjar"), ), }, "relative package location": { @@ -37,7 +41,9 @@ func TestJavaPlugin(t *testing.T) { ), PluginName: "java", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:java"), plugintest.WithOutputs("src/main/java/foo/test.srcjar"), + plugintest.WithOut("src/main/java/foo/test.srcjar"), ), }, }) diff --git a/pkg/plugin/builtin/js_closure_plugin_test.go b/pkg/plugin/builtin/js_closure_plugin_test.go index 12bf18568..97d34616d 100644 --- a/pkg/plugin/builtin/js_closure_plugin_test.go +++ b/pkg/plugin/builtin/js_closure_plugin_test.go @@ -16,6 +16,7 @@ func TestJsClosurePlugin(t *testing.T) { ), PluginName: "js", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:closurejs"), plugintest.WithOutputs("test.js"), plugintest.WithOptions("import_style=closure", "library=test"), ), @@ -27,6 +28,7 @@ func TestJsClosurePlugin(t *testing.T) { ), PluginName: "js", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:closurejs"), plugintest.WithOutputs("test.js"), plugintest.WithOptions("import_style=closure", "library=test"), ), @@ -38,6 +40,7 @@ func TestJsClosurePlugin(t *testing.T) { ), PluginName: "js", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:closurejs"), plugintest.WithOutputs("test.js"), plugintest.WithOptions("import_style=closure", "library=test"), ), @@ -49,6 +52,7 @@ func TestJsClosurePlugin(t *testing.T) { ), PluginName: "js", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:closurejs"), plugintest.WithOutputs("test.js"), plugintest.WithOptions("import_style=closure", "library=test"), ), @@ -61,6 +65,7 @@ func TestJsClosurePlugin(t *testing.T) { ), PluginName: "js", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:closurejs"), plugintest.WithOutputs("rel/test.js"), plugintest.WithOptions("import_style=closure", "library=rel/test"), ), diff --git a/pkg/plugin/builtin/js_common_plugin_test.go b/pkg/plugin/builtin/js_common_plugin_test.go index 79efc1bab..e1784df8a 100644 --- a/pkg/plugin/builtin/js_common_plugin_test.go +++ b/pkg/plugin/builtin/js_common_plugin_test.go @@ -16,6 +16,7 @@ func TestJsCommonPlugin(t *testing.T) { ), PluginName: "js", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:commonjs"), plugintest.WithOutputs("test_pb.js"), plugintest.WithOptions("import_style=commonjs"), ), @@ -27,6 +28,7 @@ func TestJsCommonPlugin(t *testing.T) { ), PluginName: "js", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:commonjs"), plugintest.WithOutputs("test_pb.js"), plugintest.WithOptions("import_style=commonjs"), ), @@ -38,6 +40,7 @@ func TestJsCommonPlugin(t *testing.T) { ), PluginName: "js", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:commonjs"), plugintest.WithOutputs("test_pb.js"), plugintest.WithOptions("import_style=commonjs"), ), @@ -49,6 +52,7 @@ func TestJsCommonPlugin(t *testing.T) { ), PluginName: "js", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:commonjs"), plugintest.WithOutputs("test_pb.js"), plugintest.WithOptions("import_style=commonjs"), ), @@ -61,6 +65,7 @@ func TestJsCommonPlugin(t *testing.T) { ), PluginName: "js", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:commonjs"), plugintest.WithOutputs("rel/test_pb.js"), plugintest.WithOptions("import_style=commonjs"), ), diff --git a/pkg/plugin/builtin/objc_plugin_test.go b/pkg/plugin/builtin/objc_plugin_test.go index 3db549f5e..2e168d449 100644 --- a/pkg/plugin/builtin/objc_plugin_test.go +++ b/pkg/plugin/builtin/objc_plugin_test.go @@ -16,6 +16,7 @@ func TestObjcPlugin(t *testing.T) { ), PluginName: "objc", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:objc"), plugintest.WithOutputs("Test.pbobjc.h", "Test.pbobjc.m"), ), }, @@ -26,6 +27,7 @@ func TestObjcPlugin(t *testing.T) { ), PluginName: "objc", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:objc"), plugintest.WithOutputs("Test.pbobjc.h", "Test.pbobjc.m"), ), }, @@ -36,6 +38,7 @@ func TestObjcPlugin(t *testing.T) { ), PluginName: "objc", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:objc"), plugintest.WithOutputs("Test.pbobjc.h", "Test.pbobjc.m"), ), }, @@ -46,6 +49,7 @@ func TestObjcPlugin(t *testing.T) { ), PluginName: "objc", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:objc"), plugintest.WithOutputs("Test.pbobjc.h", "Test.pbobjc.m"), ), }, @@ -57,6 +61,7 @@ func TestObjcPlugin(t *testing.T) { ), PluginName: "objc", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:objc"), plugintest.WithOutputs("rel/Test.pbobjc.h", "rel/Test.pbobjc.m"), ), }, @@ -68,6 +73,7 @@ func TestObjcPlugin(t *testing.T) { ), PluginName: "objc", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:objc"), plugintest.WithOutputs("FooBarBaz.pbobjc.h", "FooBarBaz.pbobjc.m"), ), }, diff --git a/pkg/plugin/builtin/php_plugin_test.go b/pkg/plugin/builtin/php_plugin_test.go index afbfbd1c5..3014d6ddd 100644 --- a/pkg/plugin/builtin/php_plugin_test.go +++ b/pkg/plugin/builtin/php_plugin_test.go @@ -16,6 +16,7 @@ func TestPhpPlugin(t *testing.T) { ), PluginName: "php", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:php"), plugintest.WithOutputs("GPBMetadata/Test.php"), ), }, @@ -26,6 +27,7 @@ func TestPhpPlugin(t *testing.T) { ), PluginName: "php", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:php"), plugintest.WithOutputs("GPBMetadata/Test.php", "E.php", "M.php"), ), }, @@ -36,6 +38,7 @@ func TestPhpPlugin(t *testing.T) { ), PluginName: "php", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:php"), plugintest.WithOutputs("GPBMetadata/Test.php", "P/E.php", "P/M.php"), ), }, @@ -46,6 +49,7 @@ func TestPhpPlugin(t *testing.T) { ), PluginName: "php", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:php"), plugintest.WithOutputs("GPBMetadata/Test.php", "foo/E.php", "foo/M.php"), ), }, @@ -56,6 +60,7 @@ func TestPhpPlugin(t *testing.T) { ), PluginName: "php", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:php"), plugintest.WithOutputs("bar/Test.php", "P/E.php", "P/M.php"), ), }, @@ -67,7 +72,9 @@ func TestPhpPlugin(t *testing.T) { ), PluginName: "php", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:php"), plugintest.WithOutputs("a/b/c/GPBMetadata/A/B/C/Test.php", "a/b/c/M.php"), + plugintest.WithOut("a/b/c"), ), }, }) diff --git a/pkg/plugin/builtin/pyi_plugin_test.go b/pkg/plugin/builtin/pyi_plugin_test.go index 1f8d088e4..f2d1f3a6a 100644 --- a/pkg/plugin/builtin/pyi_plugin_test.go +++ b/pkg/plugin/builtin/pyi_plugin_test.go @@ -16,6 +16,7 @@ func TestPyiPlugin(t *testing.T) { ), PluginName: "pyi", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:pyi"), plugintest.WithOutputs("test_pb2.pyi"), ), }, @@ -26,6 +27,7 @@ func TestPyiPlugin(t *testing.T) { ), PluginName: "pyi", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:pyi"), plugintest.WithOutputs("test_pb2.pyi"), ), }, @@ -36,6 +38,7 @@ func TestPyiPlugin(t *testing.T) { ), PluginName: "pyi", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:pyi"), plugintest.WithOutputs("test_pb2.pyi"), ), }, @@ -47,6 +50,7 @@ func TestPyiPlugin(t *testing.T) { ), PluginName: "pyi", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:pyi"), plugintest.WithOutputs("rel/test_pb2.pyi"), ), }, @@ -58,6 +62,7 @@ func TestPyiPlugin(t *testing.T) { ), PluginName: "pyi", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:pyi"), plugintest.WithOutputs("a_b*c+d=e|g!h#i_pb2.pyi"), ), }, diff --git a/pkg/plugin/builtin/python_plugin.go b/pkg/plugin/builtin/python_plugin.go index c3419764f..57b32c4a7 100644 --- a/pkg/plugin/builtin/python_plugin.go +++ b/pkg/plugin/builtin/python_plugin.go @@ -1,7 +1,10 @@ package builtin import ( + "flag" + "log" "path" + "path/filepath" "strings" "github.com/bazelbuild/bazel-gazelle/label" @@ -22,13 +25,25 @@ func (p *PythonPlugin) Name() string { // Configure implements part of the Plugin interface. func (p *PythonPlugin) Configure(ctx *protoc.PluginContext) *protoc.PluginConfiguration { + flags := parsePythonPluginOptions(p.Name(), ctx.PluginConfig.GetFlags()) + + pyFiles := protoc.FlatMapFiles( + pythonGeneratedFileName(ctx.Rel), + protoc.Always, + ctx.ProtoLibrary.Files()..., + ) + + pyOutputs := make([]string, 0, len(pyFiles)) + for _, pyFile := range pyFiles { + if flags.excludeOutput[filepath.Base(pyFile)] { + continue + } + pyOutputs = append(pyOutputs, pyFile) + } + return &protoc.PluginConfiguration{ - Label: label.New("build_stack_rules_proto", "plugin/builtin", "python"), - Outputs: protoc.FlatMapFiles( - pythonGeneratedFileName(ctx.Rel), - protoc.Always, - ctx.ProtoLibrary.Files()..., - ), + Label: label.New("build_stack_rules_proto", "plugin/builtin", "python"), + Outputs: pyOutputs, Options: ctx.PluginConfig.GetOptions(), } } @@ -45,3 +60,28 @@ func pythonGeneratedFileName(reldir string) func(f *protoc.File) []string { return []string{name + "_pb2.py"} } } + +// pythonPluginOptions represents the parsed flag configuration for the +// ProtocGenTsProto implementation. +type pythonPluginOptions struct { + excludeOutput map[string]bool +} + +func parsePythonPluginOptions(kindName string, args []string) *pythonPluginOptions { + flags := flag.NewFlagSet(kindName, flag.ExitOnError) + + var excludeOutput string + flags.StringVar(&excludeOutput, "exclude_output", "", "--exclude_output=pythonPluginOptions suppresses the file 'foo_pb2.py' from the output list") + + if err := flags.Parse(args); err != nil { + log.Fatalf("failed to parse flags for %q: %v", kindName, err) + } + config := &pythonPluginOptions{ + excludeOutput: make(map[string]bool), + } + for _, value := range strings.Split(excludeOutput, ",") { + config.excludeOutput[value] = true + } + + return config +} diff --git a/pkg/plugin/builtin/python_plugin_test.go b/pkg/plugin/builtin/python_plugin_test.go index 67880f170..0dd9625fe 100644 --- a/pkg/plugin/builtin/python_plugin_test.go +++ b/pkg/plugin/builtin/python_plugin_test.go @@ -16,6 +16,7 @@ func TestPythonPlugin(t *testing.T) { ), PluginName: "python", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:python"), plugintest.WithOutputs("test_pb2.py"), ), }, @@ -26,6 +27,7 @@ func TestPythonPlugin(t *testing.T) { ), PluginName: "python", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:python"), plugintest.WithOutputs("test_pb2.py"), ), }, @@ -36,6 +38,7 @@ func TestPythonPlugin(t *testing.T) { ), PluginName: "python", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:python"), plugintest.WithOutputs("test_pb2.py"), ), }, @@ -47,6 +50,7 @@ func TestPythonPlugin(t *testing.T) { ), PluginName: "python", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:python"), plugintest.WithOutputs("rel/test_pb2.py"), ), }, @@ -58,6 +62,7 @@ func TestPythonPlugin(t *testing.T) { ), PluginName: "python", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:python"), plugintest.WithOutputs("a_b*c+d=e|g!h#i_pb2.py"), ), }, diff --git a/pkg/plugin/builtin/ruby_plugin_test.go b/pkg/plugin/builtin/ruby_plugin_test.go index 412497fd8..08765f6d7 100644 --- a/pkg/plugin/builtin/ruby_plugin_test.go +++ b/pkg/plugin/builtin/ruby_plugin_test.go @@ -16,6 +16,7 @@ func TestRubyPlugin(t *testing.T) { ), PluginName: "ruby", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:ruby"), plugintest.WithOutputs("test_pb.rb"), ), }, @@ -26,6 +27,7 @@ func TestRubyPlugin(t *testing.T) { ), PluginName: "ruby", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:ruby"), plugintest.WithOutputs("test_pb.rb"), ), }, @@ -36,6 +38,7 @@ func TestRubyPlugin(t *testing.T) { ), PluginName: "ruby", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:ruby"), plugintest.WithOutputs("test_pb.rb"), ), }, @@ -47,6 +50,7 @@ func TestRubyPlugin(t *testing.T) { ), PluginName: "ruby", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/builtin:ruby"), plugintest.WithOutputs("rel/test_pb.rb"), ), }, diff --git a/pkg/plugin/golang/protobuf/protoc-gen-go_test.go b/pkg/plugin/golang/protobuf/protoc-gen-go_test.go index dbd39507c..f94e9229f 100644 --- a/pkg/plugin/golang/protobuf/protoc-gen-go_test.go +++ b/pkg/plugin/golang/protobuf/protoc-gen-go_test.go @@ -16,6 +16,7 @@ func TestProtocGenGoPlugin(t *testing.T) { ), PluginName: "protoc-gen-go", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/golang/protobuf:protoc-gen-go"), plugintest.WithOutputs("test.pb.go"), ), SkipIntegration: true, @@ -27,6 +28,7 @@ func TestProtocGenGoPlugin(t *testing.T) { ), PluginName: "protoc-gen-go", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/golang/protobuf:protoc-gen-go"), plugintest.WithOutputs("github.com/example.com/test/test.pb.go"), ), SkipIntegration: true, @@ -39,6 +41,7 @@ func TestProtocGenGoPlugin(t *testing.T) { ), PluginName: "protoc-gen-go", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/golang/protobuf:protoc-gen-go"), plugintest.WithOptions("Mtest.proto=github.com/example.com/test"), plugintest.WithOutputs("github.com/example.com/test/test.pb.go"), ), @@ -53,6 +56,7 @@ func TestProtocGenGoPlugin(t *testing.T) { ), PluginName: "protoc-gen-go", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/golang/protobuf:protoc-gen-go"), plugintest.WithOptions( "Mfoo.proto=github.com/example.com/foo", "Mtest.proto=github.com/example.com/test", diff --git a/pkg/plugin/grpc/grpc/protoc-gen-grpc-python_test.go b/pkg/plugin/grpc/grpc/protoc-gen-grpc-python_test.go index 3717f9785..c5609ebf1 100644 --- a/pkg/plugin/grpc/grpc/protoc-gen-grpc-python_test.go +++ b/pkg/plugin/grpc/grpc/protoc-gen-grpc-python_test.go @@ -31,6 +31,7 @@ func TestProtocGenGrpcPython(t *testing.T) { "proto_plugin", "python implementation grpc:grpc:protoc-gen-grpc-python", ), Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/grpc/grpc:protoc-gen-grpc-python"), plugintest.WithOutputs("test_pb2_grpc.py"), ), PluginName: "python", @@ -42,6 +43,7 @@ func TestProtocGenGrpcPython(t *testing.T) { "proto_plugin", "python implementation grpc:grpc:protoc-gen-grpc-python", ), Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/grpc/grpc:protoc-gen-grpc-python"), plugintest.WithOutputs("test_pb2_grpc.py"), ), PluginName: "python", diff --git a/pkg/plugin/scalapb/scalapb/protoc_gen_scala_test.go b/pkg/plugin/scalapb/scalapb/protoc_gen_scala_test.go index 217381bd8..d3f18b642 100644 --- a/pkg/plugin/scalapb/scalapb/protoc_gen_scala_test.go +++ b/pkg/plugin/scalapb/scalapb/protoc_gen_scala_test.go @@ -16,6 +16,7 @@ func TestProtoGenScalaPlugin(t *testing.T) { ), PluginName: "scala", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/scalapb/scalapb:protoc-gen-scala"), plugintest.WithOutputs("test_scala.srcjar"), ), SkipIntegration: true, @@ -27,6 +28,7 @@ func TestProtoGenScalaPlugin(t *testing.T) { ), PluginName: "scala", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/scalapb/scalapb:protoc-gen-scala"), plugintest.WithOutputs("test_scala.srcjar"), ), SkipIntegration: true, @@ -39,6 +41,7 @@ func TestProtoGenScalaPlugin(t *testing.T) { ), PluginName: "scala", Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/scalapb/scalapb:protoc-gen-scala"), plugintest.WithOutputs("rel/test_scala.srcjar"), ), SkipIntegration: true, diff --git a/pkg/plugin/stephenh/ts-proto/BUILD.bazel b/pkg/plugin/stephenh/ts-proto/BUILD.bazel index 0e56bd0f7..d2dd610f8 100644 --- a/pkg/plugin/stephenh/ts-proto/BUILD.bazel +++ b/pkg/plugin/stephenh/ts-proto/BUILD.bazel @@ -1,4 +1,4 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "ts-proto", @@ -11,6 +11,15 @@ go_library( ], ) +go_test( + name = "ts-proto_test", + srcs = ["protoc-gen-ts-proto_test.go"], + deps = [ + ":ts-proto", + "//pkg/plugintest", + ], +) + filegroup( name = "all_files", srcs = [ diff --git a/pkg/plugin/stephenh/ts-proto/protoc-gen-ts-proto.go b/pkg/plugin/stephenh/ts-proto/protoc-gen-ts-proto.go index 840415756..b3baf4958 100644 --- a/pkg/plugin/stephenh/ts-proto/protoc-gen-ts-proto.go +++ b/pkg/plugin/stephenh/ts-proto/protoc-gen-ts-proto.go @@ -1,7 +1,11 @@ package ts_proto import ( + "flag" + "log" "path" + "path/filepath" + "strings" "github.com/bazelbuild/bazel-gazelle/label" "github.com/stackb/rules_proto/pkg/protoc" @@ -21,18 +25,85 @@ func (p *ProtocGenTsProto) Name() string { // Configure implements part of the Plugin interface. func (p *ProtocGenTsProto) Configure(ctx *protoc.PluginContext) *protoc.PluginConfiguration { + flags := parseProtocGenTsProtoOptions(p.Name(), ctx.PluginConfig.GetFlags()) + imports := make(map[string]bool) + for _, file := range ctx.ProtoLibrary.Files() { + for _, imp := range file.Imports() { + imports[imp.Filename] = true + } + } + var emitImportedFiles bool + var options []string + for _, option := range ctx.PluginConfig.GetOptions() { + // options may be configured to include many "M=" options, but only + // include the relevant ones to avoid BUILD file clutter. + if strings.HasPrefix(option, "M=") { + keyVal := option[len("M="):] + parts := strings.SplitN(keyVal, "=", 2) + filename := parts[0] + if !imports[filename] { + continue + } + } + if option == "emitImportedFiles=true" { + emitImportedFiles = true + } + options = append(options, option) + } + tsFiles := make([]string, 0) for _, file := range ctx.ProtoLibrary.Files() { + if emitImportedFiles { + for _, imp := range file.Imports() { + if !strings.HasPrefix(imp.Filename, "google/protobuf") { + continue + } + tsFiles = append(tsFiles, strings.TrimSuffix(imp.Filename, ".proto")+".ts") + } + } + tsFile := file.Name + ".ts" + if flags.excludeOutput[filepath.Base(tsFile)] { + continue + } if ctx.Rel != "" { tsFile = path.Join(ctx.Rel, tsFile) } tsFiles = append(tsFiles, tsFile) } - return &protoc.PluginConfiguration{ + pc := &protoc.PluginConfiguration{ Label: label.New("build_stack_rules_proto", "plugin/stephenh/ts-proto", "protoc-gen-ts-proto"), - Outputs: tsFiles, - Options: ctx.PluginConfig.GetOptions(), + Outputs: protoc.DeduplicateAndSort(tsFiles), + Options: protoc.DeduplicateAndSort(options), + } + if len(pc.Outputs) == 0 { + pc.Outputs = nil } + return pc +} + +// protocGenTsProtoOptions represents the parsed flag configuration for the +// ProtocGenTsProto implementation. +type protocGenTsProtoOptions struct { + excludeOutput map[string]bool +} + +func parseProtocGenTsProtoOptions(kindName string, args []string) *protocGenTsProtoOptions { + flags := flag.NewFlagSet(kindName, flag.ExitOnError) + + var excludeOutput string + flags.StringVar(&excludeOutput, "exclude_output", "", "--exclude_output=foo.ts suppresses the file 'foo.ts' from the output list") + + if err := flags.Parse(args); err != nil { + log.Fatalf("failed to parse flags for %q: %v", kindName, err) + } + config := &protocGenTsProtoOptions{ + excludeOutput: make(map[string]bool), + } + for _, value := range strings.Split(excludeOutput, ",") { + config.excludeOutput[value] = true + } + + return config } diff --git a/pkg/plugin/stephenh/ts-proto/protoc-gen-ts-proto_test.go b/pkg/plugin/stephenh/ts-proto/protoc-gen-ts-proto_test.go new file mode 100644 index 000000000..b1ce5d964 --- /dev/null +++ b/pkg/plugin/stephenh/ts-proto/protoc-gen-ts-proto_test.go @@ -0,0 +1,68 @@ +package ts_proto_test + +import ( + "testing" + + ts_proto "github.com/stackb/rules_proto/pkg/plugin/stephenh/ts-proto" + "github.com/stackb/rules_proto/pkg/plugintest" +) + +func TestProtocGenTsProtoPlugin(t *testing.T) { + plugintest.Cases(t, &ts_proto.ProtocGenTsProto{}, map[string]plugintest.Case{ + "simple": { + Input: "message M{}", + Directives: plugintest.WithDirectives( + "proto_plugin", "protoc-gen-ts-proto implementation stephenh:ts-proto:protoc-gen-ts-proto", + ), + PluginName: "protoc-gen-ts-proto", + Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/stephenh/ts-proto:protoc-gen-ts-proto"), + plugintest.WithOutputs("test.ts"), + ), + SkipIntegration: true, + }, + "flag --exclude_output": { + Input: "message M{}", + Directives: plugintest.WithDirectives( + "proto_plugin", "protoc-gen-ts-proto implementation stephenh:ts-proto:protoc-gen-ts-proto", + "proto_plugin", "protoc-gen-ts-proto flag --exclude_output=test.ts", + ), + PluginName: "protoc-gen-ts-proto", + Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/stephenh/ts-proto:protoc-gen-ts-proto"), + plugintest.WithOutputs(), + ), + SkipIntegration: true, + }, + "includes only relevant M= options": { + Input: ` +syntax = "proto3"; + +package corp.common; + +import "google/type/datetime.proto"; +import "google/protobuf/duration.proto"; + +message M {} +`, + Directives: plugintest.WithDirectives( + "proto_plugin", "protoc-gen-ts-proto implementation stephenh:ts-proto:protoc-gen-ts-proto", + "proto_plugin", "protoc-gen-ts-proto option M=google/protobuf/empty.proto=./external/protobufapis/google/protobuf/empty", + "proto_plugin", "protoc-gen-ts-proto option M=google/protobuf/timestamp.proto=./external/protobufapis/google/protobuf/timestamp", + "proto_plugin", "protoc-gen-ts-proto option M=google/protobuf/duration.proto=./external/protobufapis/google/protobuf/duration", + "proto_plugin", "protoc-gen-ts-proto option M=google/type/timeofday.proto=./external/googleapis/google/type/timeofday", + "proto_plugin", "protoc-gen-ts-proto option M=google/type/datetime.proto=./external/googleapis/google/type/datetime", + ), + PluginName: "protoc-gen-ts-proto", + Configuration: plugintest.WithConfiguration( + plugintest.WithLabel(t, "@build_stack_rules_proto//plugin/stephenh/ts-proto:protoc-gen-ts-proto"), + plugintest.WithOutputs("test.ts"), + plugintest.WithOptions( + "M=google/protobuf/duration.proto=./external/protobufapis/google/protobuf/duration", + "M=google/type/datetime.proto=./external/googleapis/google/type/datetime", + ), + ), + SkipIntegration: true, + }, + }) +} diff --git a/pkg/plugintest/BUILD.bazel b/pkg/plugintest/BUILD.bazel index ea6932f7f..f417cbe47 100644 --- a/pkg/plugintest/BUILD.bazel +++ b/pkg/plugintest/BUILD.bazel @@ -12,7 +12,10 @@ go_library( visibility = ["//visibility:public"], deps = [ "//pkg/protoc", + "@bazel_gazelle//label:go_default_library", "@bazel_gazelle//rule:go_default_library", + "@com_github_google_go_cmp//cmp", + "@com_github_google_go_cmp//cmp/cmpopts", ], ) diff --git a/pkg/plugintest/case.go b/pkg/plugintest/case.go index 5aba756cd..5f786ead9 100644 --- a/pkg/plugintest/case.go +++ b/pkg/plugintest/case.go @@ -8,6 +8,9 @@ import ( "strings" "testing" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/bazelbuild/bazel-gazelle/rule" "github.com/stackb/rules_proto/pkg/protoc" ) @@ -66,7 +69,7 @@ func (tc *Case) Run(t *testing.T, subject protoc.Plugin) { t.Fatalf("configuration for plugin '%s' was not found", tc.PluginName) } r := rule.NewRule("proto_library", basename+"_proto") - lib := protoc.NewOtherProtoLibrary(nil, r, f) // File is nil, not needed for the test + lib := protoc.NewOtherProtoLibrary(nil /* File is nil, not needed for the test */, r, f) ctx := &protoc.PluginContext{ Rel: tc.Rel, ProtoLibrary: lib, @@ -75,36 +78,10 @@ func (tc *Case) Run(t *testing.T, subject protoc.Plugin) { } got := subject.Configure(ctx) - if got == nil && tc.Configuration == nil { - return - } - if got == nil && tc.Configuration != nil { - t.Fatalf("expected non-nil return value from %T.Configure()", subject) - } - if got != nil && tc.Configuration == nil { - t.Fatalf("unexpected non-nil return value from %T.Configure()", subject) - } + want := tc.Configuration - outputs := got.Outputs - if len(tc.Configuration.Outputs) != len(outputs) { - t.Fatalf("%T.Outputs: want %d, got %d (%v)", subject, len(tc.Configuration.Outputs), len(outputs), outputs) - } - for i, got := range outputs { - want := tc.Configuration.Outputs[i] - if want != got { - t.Errorf("%T.Outputs[%d]: want %q, got %q", subject, i, want, got) - } - } - - options := got.Options - if len(tc.Configuration.Options) != len(options) { - t.Fatalf("%T.Options: want %d, got %d (%v)", subject, len(tc.Configuration.Options), len(options), options) - } - for i, got := range options { - want := tc.Configuration.Options[i] - if want != got { - t.Errorf("%T.Options[%d]: want %q, got %q", subject, i, want, got) - } + if diff := cmp.Diff(want, got, cmpopts.EquateEmpty()); diff != "" { + t.Errorf("output configuration mismatch (-want +got): %s", diff) } if tc.SkipIntegration { diff --git a/pkg/plugintest/utils.go b/pkg/plugintest/utils.go index 37d69ad2c..dca729bfd 100644 --- a/pkg/plugintest/utils.go +++ b/pkg/plugintest/utils.go @@ -7,6 +7,7 @@ import ( "path/filepath" "testing" + "github.com/bazelbuild/bazel-gazelle/label" "github.com/bazelbuild/bazel-gazelle/rule" "github.com/stackb/rules_proto/pkg/protoc" ) @@ -38,6 +39,24 @@ func WithOptions(options ...string) PluginConfigurationOption { } } +// WithOut assigns the Out field. +func WithOut(out string) PluginConfigurationOption { + return func(c *protoc.PluginConfiguration) { + c.Out = out + } +} + +// WithLabel assigns the Label field. +func WithLabel(t *testing.T, raw string) PluginConfigurationOption { + return func(c *protoc.PluginConfiguration) { + lbl, err := label.Parse(raw) + if err != nil { + t.Fatalf("bad label %q: %v", raw, err) + } + c.Label = lbl + } +} + // WithDirectives assigns rule Directives. func WithDirectives(items ...string) (d []rule.Directive) { if len(items)%2 != 0 { diff --git a/pkg/protoc/language_plugin_config.go b/pkg/protoc/language_plugin_config.go index 5f47443ba..1a5b239f1 100644 --- a/pkg/protoc/language_plugin_config.go +++ b/pkg/protoc/language_plugin_config.go @@ -17,9 +17,11 @@ type LanguagePluginConfig struct { Label label.Label // Options is a set of option strings. Options map[string]bool + // Flags is a set of flag strings. + Flags map[string]bool // Deps is a set of dep labels. For example, consider a plugin config for // 'protoc-gen-go'. That plugin produces .go files. The 'Deps' field can - // be used by downstream Rule implmentations to gather necessary + // be used by downstream Rule implementations to gather necessary // dependencies for the .go files produced by that plugin. Deps map[string]bool // Enabled flag @@ -30,6 +32,7 @@ func newLanguagePluginConfig(name string) *LanguagePluginConfig { return &LanguagePluginConfig{ Name: name, Options: make(map[string]bool), + Flags: make(map[string]bool), Deps: make(map[string]bool), Enabled: true, } @@ -45,6 +48,11 @@ func (c *LanguagePluginConfig) GetDeps() []string { return ForIntent(c.Deps, true) } +// GetFlags returns the list of Flags configured for the plugin. +func (c *LanguagePluginConfig) GetFlags() []string { + return ForIntent(c.Flags, true) +} + func (c *LanguagePluginConfig) clone() *LanguagePluginConfig { clone := newLanguagePluginConfig(c.Name) clone.Label = c.Label @@ -53,6 +61,9 @@ func (c *LanguagePluginConfig) clone() *LanguagePluginConfig { for k, v := range c.Options { clone.Options[k] = v } + for k, v := range c.Flags { + clone.Flags[k] = v + } for k, v := range c.Deps { clone.Deps[k] = v } @@ -77,6 +88,8 @@ func (c *LanguagePluginConfig) parseDirective(cfg *PackageConfig, d, param, valu c.Label = l case "implementation": c.Implementation = value + case "flag": + c.Flags[value] = intent.Want case "option": c.Options[value] = intent.Want case "deps", "dep": @@ -95,6 +108,9 @@ func (c *LanguagePluginConfig) fromYAML(y *YPlugin) error { } c.Implementation = y.Implementation // only true intent is supported via yaml + for _, flag := range y.Flag { + c.Flags[flag] = true + } for _, option := range y.Option { c.Options[option] = true } diff --git a/pkg/protoc/proto_compile.go b/pkg/protoc/proto_compile.go index 71840b71f..ad31dacea 100644 --- a/pkg/protoc/proto_compile.go +++ b/pkg/protoc/proto_compile.go @@ -56,6 +56,9 @@ func (s *protoCompile) LoadInfo() rule.LoadInfo { // ProvideRule implements part of the LanguageRule interface. func (s *protoCompile) ProvideRule(cfg *LanguageRuleConfig, config *ProtocConfiguration) RuleProvider { + if len(config.Outputs) == 0 { + return nil + } return &protoCompileRule{ kind: "proto_compile", nameSuffix: "compile", @@ -89,12 +92,16 @@ func (s *protoCompileRule) Visibility() []string { return s.ruleConfig.GetVisibility() } +func (s *protoCompileRule) Outputs() []string { + outputs := s.config.Outputs + sort.Strings(outputs) + return outputs +} + // Rule implements part of the ruleProvider interface. func (s *protoCompileRule) Rule(otherGen ...*rule.Rule) *rule.Rule { newRule := rule.NewRule(s.Kind(), s.Name()) - - outputs := s.config.Outputs - sort.Strings(outputs) + outputs := s.Outputs() newRule.SetAttr(s.outputsAttrName, outputs) newRule.SetAttr("plugins", GetPluginLabels(s.config.Plugins)) diff --git a/pkg/protoc/yconfig.go b/pkg/protoc/yconfig.go index bd73cd07d..c320bbdf6 100644 --- a/pkg/protoc/yconfig.go +++ b/pkg/protoc/yconfig.go @@ -24,6 +24,7 @@ type YPlugin struct { Implementation string `yaml:"implementation"` Enabled *bool `yaml:"enabled,omitempty"` Option []string `yaml:"options"` + Flag []string `yaml:"flags"` Dep []string `yaml:"deps"` Label string `yaml:"label"` } diff --git a/pkg/rule/rules_nodejs/proto_ts_library.go b/pkg/rule/rules_nodejs/proto_ts_library.go index 0ec443e33..2e52aea6b 100644 --- a/pkg/rule/rules_nodejs/proto_ts_library.go +++ b/pkg/rule/rules_nodejs/proto_ts_library.go @@ -1,6 +1,7 @@ package rules_nodejs import ( + "flag" "log" "strings" @@ -37,6 +38,7 @@ func (s *protoTsLibrary) KindInfo() rule.KindInfo { "srcs": true, "tsc": true, "args": true, + "data": true, }, ResolveAttrs: map[string]bool{ "deps": true, @@ -55,6 +57,8 @@ func (s *protoTsLibrary) LoadInfo() rule.LoadInfo { // ProvideRule implements part of the LanguageRule interface. func (s *protoTsLibrary) ProvideRule(cfg *protoc.LanguageRuleConfig, pc *protoc.ProtocConfiguration) protoc.RuleProvider { + flags := parseProtoTsLibraryFlags(ProtoTsLibraryRuleName, cfg.GetOptions()) + outputs := make([]string, 0) for _, out := range pc.Outputs { if strings.HasSuffix(out, ".ts") { @@ -65,23 +69,23 @@ func (s *protoTsLibrary) ProvideRule(cfg *protoc.LanguageRuleConfig, pc *protoc. return nil } return &tsLibrary{ + flags: flags, KindName: ProtoTsLibraryRuleName, RuleNameSuffix: ProtoTsLibraryRuleSuffix, Outputs: outputs, RuleConfig: cfg, Config: pc, - Resolver: protoc.ResolveDepsAttr("deps", true), } } // tsLibrary implements RuleProvider for 'ts_library'-like rules. type tsLibrary struct { + flags *protoTsLibraryFlags KindName string RuleNameSuffix string Outputs []string Config *protoc.ProtocConfiguration RuleConfig *protoc.LanguageRuleConfig - Resolver protoc.DepsResolver } // Kind implements part of the ruleProvider interface. @@ -133,6 +137,10 @@ func (s *tsLibrary) Rule(otherGen ...*rule.Rule) *rule.Rule { newRule.SetAttr("args", args) } + if s.flags.includeProtoLibraryData { + newRule.SetAttr("data", []string{s.Config.Library.Name()}) + } + visibility := s.Visibility() if len(visibility) > 0 { newRule.SetAttr("visibility", visibility) @@ -151,8 +159,26 @@ func (s *tsLibrary) Imports(c *config.Config, r *rule.Rule, file *rule.File) []r // Resolve implements part of the RuleProvider interface. func (s *tsLibrary) Resolve(c *config.Config, ix *resolve.RuleIndex, r *rule.Rule, imports []string, from label.Label) { - if s.Resolver == nil { - return + protoc.ResolveDepsAttr("deps", false /* resolve wkts */)(c, ix, r, imports, from) +} + +// protoTsLibraryFlags represents the parsed flag configuration for the +// proto_ts_library rule. +type protoTsLibraryFlags struct { + // includeProtoLibraryData is true if the rule should populate the data + // attribute with the proto_library rule. + includeProtoLibraryData bool +} + +func parseProtoTsLibraryFlags(kindName string, args []string) *protoTsLibraryFlags { + flags := flag.NewFlagSet(kindName, flag.ExitOnError) + + var includeProtoLibraryData bool + flags.BoolVar(&includeProtoLibraryData, "include_proto_library_data", false, "--include_proto_library_data=true populates the data attribute with the proto_library rule") + + if err := flags.Parse(args); err != nil { + log.Fatalf("failed to parse flags for %q: %v", kindName, err) } - s.Resolver(c, ix, r, imports, from) + + return &protoTsLibraryFlags{includeProtoLibraryData} } diff --git a/rules/ts/proto_ts_library.bzl b/rules/ts/proto_ts_library.bzl index 3ba25dbe9..4daf1353a 100644 --- a/rules/ts/proto_ts_library.bzl +++ b/rules/ts/proto_ts_library.bzl @@ -37,9 +37,9 @@ def _proto_ts_library_impl(ctx): dts_outputs.append( ctx.actions.declare_file(base + ".d.ts", sibling = f), ) - # js_outputs.append( - # ctx.actions.declare_file(base + ".js", sibling = f), - # ) + js_outputs.append( + ctx.actions.declare_file(base + ".js", sibling = f), + ) # all outputs (.d.ts + .js) outputs = js_outputs + dts_outputs @@ -77,7 +77,13 @@ def _proto_ts_library_impl(ctx): ), # default info contains all files, in case someone wanted it for a # filegroup etc. - DefaultInfo(files = depset(direct = outputs)), + DefaultInfo( + files = depset(direct = outputs), + runfiles = ctx.runfiles( + collect_default = True, + collect_data = True, + ), + ), # js files, in the event someone would like this for js_library etc. JSModuleInfo( direct_sources = js_module, @@ -96,9 +102,13 @@ proto_ts_library = rule( allow_files = True, doc = "source .ts files", ), + "data": attr.label_list( + allow_files = True, + doc = "additional data dependencies", + ), "tsc": attr.label( allow_files = True, - cfg = "host", + cfg = "exec", mandatory = True, doc = "typescript compiler executable", executable = True,