github.com/stackb/rules_proto@v0.0.0-20240221195024-5428336c51f1/pkg/protoc/proto_compile.go (about) 1 package protoc 2 3 import ( 4 "fmt" 5 "log" 6 "sort" 7 8 "github.com/bazelbuild/bazel-gazelle/config" 9 "github.com/bazelbuild/bazel-gazelle/label" 10 "github.com/bazelbuild/bazel-gazelle/resolve" 11 "github.com/bazelbuild/bazel-gazelle/rule" 12 ) 13 14 const ( 15 // ProtoLibraryKey stores the ProtoLibrary implementation for a rule. 16 ProtoLibraryKey = "_proto_library" 17 ) 18 19 func init() { 20 Rules().MustRegisterRule("stackb:rules_proto:proto_compile", &protoCompile{}) 21 } 22 23 // protoCompile implements LanguageRule for the 'proto_compile' rule. 24 type protoCompile struct{} 25 26 // KindInfo implements part of the LanguageRule interface. 27 func (s *protoCompile) KindInfo() rule.KindInfo { 28 return rule.KindInfo{ 29 NonEmptyAttrs: map[string]bool{ 30 "outputs": true, 31 }, 32 MergeableAttrs: map[string]bool{ 33 "outputs": true, 34 "plugins": true, 35 "output_mappings": true, 36 "options": true, 37 }, 38 SubstituteAttrs: map[string]bool{ 39 "out": true, 40 }, 41 } 42 } 43 44 // Name implements part of the LanguageRule interface. 45 func (s *protoCompile) Name() string { 46 return "proto_compile" 47 } 48 49 // LoadInfo implements part of the LanguageRule interface. 50 func (s *protoCompile) LoadInfo() rule.LoadInfo { 51 return rule.LoadInfo{ 52 Name: "@build_stack_rules_proto//rules:proto_compile.bzl", 53 Symbols: []string{"proto_compile"}, 54 } 55 } 56 57 // ProvideRule implements part of the LanguageRule interface. 58 func (s *protoCompile) ProvideRule(cfg *LanguageRuleConfig, config *ProtocConfiguration) RuleProvider { 59 if len(config.Outputs) == 0 { 60 return nil 61 } 62 return &protoCompileRule{ 63 kind: "proto_compile", 64 nameSuffix: "compile", 65 outputsAttrName: "outputs", 66 config: config, 67 ruleConfig: cfg, 68 } 69 } 70 71 // protoCompile implements RuleProvider for the 'proto_compile' rule. 72 type protoCompileRule struct { 73 kind string 74 nameSuffix string 75 outputsAttrName string 76 config *ProtocConfiguration 77 ruleConfig *LanguageRuleConfig 78 } 79 80 // Kind implements part of the ruleProvider interface. 81 func (s *protoCompileRule) Kind() string { 82 return s.kind 83 } 84 85 // Name implements part of the ruleProvider interface. 86 func (s *protoCompileRule) Name() string { 87 return fmt.Sprintf("%s_%s_%s", s.config.Library.BaseName(), s.config.Prefix, s.nameSuffix) 88 } 89 90 // Visibility provides visibility labels. 91 func (s *protoCompileRule) Visibility() []string { 92 return s.ruleConfig.GetVisibility() 93 } 94 95 func (s *protoCompileRule) Outputs() []string { 96 outputs := s.config.Outputs 97 sort.Strings(outputs) 98 return outputs 99 } 100 101 // Rule implements part of the ruleProvider interface. 102 func (s *protoCompileRule) Rule(otherGen ...*rule.Rule) *rule.Rule { 103 newRule := rule.NewRule(s.Kind(), s.Name()) 104 outputs := s.Outputs() 105 106 newRule.SetAttr(s.outputsAttrName, outputs) 107 newRule.SetAttr("plugins", GetPluginLabels(s.config.Plugins)) 108 newRule.SetAttr("proto", s.config.Library.Name()) 109 110 if s.config.LanguageConfig.Protoc != "" { 111 newRule.SetAttr("protoc", s.config.LanguageConfig.Protoc) 112 } 113 114 if len(s.config.Mappings) > 0 { 115 mappings := make([]string, len(s.config.Mappings)) 116 var i int 117 for k, v := range s.config.Mappings { 118 mappings[i] = k + "=" + v 119 i++ 120 } 121 sort.Strings(mappings) 122 newRule.SetAttr("output_mappings", mappings) 123 } 124 125 outs := GetPluginOuts(s.config.Plugins) 126 if len(outs) > 0 { 127 newRule.SetAttr("outs", MakeStringDict(outs)) 128 } 129 130 visibility := s.Visibility() 131 if len(visibility) > 0 { 132 newRule.SetAttr("visibility", visibility) 133 } 134 135 for _, name := range s.ruleConfig.GetAttrNames() { 136 vals := s.ruleConfig.GetAttr(name) 137 if len(vals) == 0 { 138 continue 139 } 140 switch name { 141 case "verbose": 142 val := vals[0] 143 if val == "True" || val == "true" { 144 newRule.SetAttr("verbose", true) 145 } else if val == "False" || val == "false" { 146 newRule.SetAttr("verbose", false) 147 } else { 148 log.Printf("bad attr 'verbose' value: %q", val) 149 } 150 default: 151 newRule.SetAttr(name, vals) 152 } 153 } 154 155 return newRule 156 } 157 158 // Imports implements part of the RuleProvider interface. 159 func (s *protoCompileRule) Imports(c *config.Config, r *rule.Rule, file *rule.File) []resolve.ImportSpec { 160 return nil 161 } 162 163 // Resolve implements part of the RuleProvider interface. 164 func (s *protoCompileRule) Resolve(c *config.Config, ix *resolve.RuleIndex, r *rule.Rule, imports []string, from label.Label) { 165 options := GetPluginOptions(s.config.Plugins, r, from) 166 if len(options) > 0 { 167 r.SetAttr("options", MakeStringListDict(options)) 168 } 169 }