xref: /aosp_15_r20/external/bazelbuild-rules_go/extras/gomock.bzl (revision 9bb1b549b6a84214c53be0924760be030e66b93a)
1*9bb1b549SSpandan Das# The MIT License (MIT)
2*9bb1b549SSpandan Das# Copyright © 2018 Jeff Hodges <[email protected]>
3*9bb1b549SSpandan Das
4*9bb1b549SSpandan Das# Permission is hereby granted, free of charge, to any person obtaining a copy
5*9bb1b549SSpandan Das# of this software and associated documentation files (the “Software”), to deal
6*9bb1b549SSpandan Das# in the Software without restriction, including without limitation the rights
7*9bb1b549SSpandan Das# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8*9bb1b549SSpandan Das# copies of the Software, and to permit persons to whom the Software is
9*9bb1b549SSpandan Das# furnished to do so, subject to the following conditions:
10*9bb1b549SSpandan Das
11*9bb1b549SSpandan Das# The above copyright notice and this permission notice shall be included in
12*9bb1b549SSpandan Das# all copies or substantial portions of the Software.
13*9bb1b549SSpandan Das
14*9bb1b549SSpandan Das# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*9bb1b549SSpandan Das# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*9bb1b549SSpandan Das# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17*9bb1b549SSpandan Das# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18*9bb1b549SSpandan Das# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19*9bb1b549SSpandan Das# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20*9bb1b549SSpandan Das# THE SOFTWARE.
21*9bb1b549SSpandan Das
22*9bb1b549SSpandan Das# The rules in this files are still under development. Breaking changes are planned.
23*9bb1b549SSpandan Das# DO NOT USE IT.
24*9bb1b549SSpandan Das
25*9bb1b549SSpandan Dasload("//go/private:context.bzl", "go_context")
26*9bb1b549SSpandan Dasload("//go/private:go_toolchain.bzl", "GO_TOOLCHAIN")
27*9bb1b549SSpandan Dasload("//go/private/rules:wrappers.bzl", go_binary = "go_binary_macro")
28*9bb1b549SSpandan Dasload("//go/private:providers.bzl", "GoLibrary")
29*9bb1b549SSpandan Dasload("@bazel_skylib//lib:paths.bzl", "paths")
30*9bb1b549SSpandan Das
31*9bb1b549SSpandan Das_MOCKGEN_TOOL = Label("//extras/gomock:mockgen")
32*9bb1b549SSpandan Das_MOCKGEN_MODEL_LIB = Label("//extras/gomock:mockgen_model")
33*9bb1b549SSpandan Das
34*9bb1b549SSpandan Dasdef _gomock_source_impl(ctx):
35*9bb1b549SSpandan Das    go_ctx = go_context(ctx)
36*9bb1b549SSpandan Das
37*9bb1b549SSpandan Das    # create GOPATH and copy source into GOPATH
38*9bb1b549SSpandan Das    source_relative_path = paths.join("src", ctx.attr.library[GoLibrary].importmap, ctx.file.source.basename)
39*9bb1b549SSpandan Das    source = ctx.actions.declare_file(paths.join("gopath", source_relative_path))
40*9bb1b549SSpandan Das
41*9bb1b549SSpandan Das    # trim the relative path of source to get GOPATH
42*9bb1b549SSpandan Das    gopath = source.path[:-len(source_relative_path)]
43*9bb1b549SSpandan Das    ctx.actions.run_shell(
44*9bb1b549SSpandan Das        outputs = [source],
45*9bb1b549SSpandan Das        inputs = [ctx.file.source],
46*9bb1b549SSpandan Das        command = "mkdir -p {0} && cp -L {1} {0}".format(source.dirname, ctx.file.source.path),
47*9bb1b549SSpandan Das    )
48*9bb1b549SSpandan Das
49*9bb1b549SSpandan Das    # passed in source needs to be in gopath to not trigger module mode
50*9bb1b549SSpandan Das    args = ["-source", source.path]
51*9bb1b549SSpandan Das
52*9bb1b549SSpandan Das    args, needed_files = _handle_shared_args(ctx, args)
53*9bb1b549SSpandan Das
54*9bb1b549SSpandan Das    if len(ctx.attr.aux_files) > 0:
55*9bb1b549SSpandan Das        aux_files = []
56*9bb1b549SSpandan Das        for target, pkg in ctx.attr.aux_files.items():
57*9bb1b549SSpandan Das            f = target.files.to_list()[0]
58*9bb1b549SSpandan Das            aux = ctx.actions.declare_file(paths.join(gopath, "src", pkg, f.basename))
59*9bb1b549SSpandan Das            ctx.actions.run_shell(
60*9bb1b549SSpandan Das                outputs = [aux],
61*9bb1b549SSpandan Das                inputs = [f],
62*9bb1b549SSpandan Das                command = "mkdir -p {0} && cp -L {1} {0}".format(aux.dirname, f.path),
63*9bb1b549SSpandan Das            )
64*9bb1b549SSpandan Das            aux_files.append("{0}={1}".format(pkg, aux.path))
65*9bb1b549SSpandan Das            needed_files.append(f)
66*9bb1b549SSpandan Das        args += ["-aux_files", ",".join(aux_files)]
67*9bb1b549SSpandan Das
68*9bb1b549SSpandan Das    inputs = (
69*9bb1b549SSpandan Das        needed_files +
70*9bb1b549SSpandan Das        go_ctx.sdk.headers + go_ctx.sdk.srcs + go_ctx.sdk.tools
71*9bb1b549SSpandan Das    ) + [source]
72*9bb1b549SSpandan Das
73*9bb1b549SSpandan Das    # We can use the go binary from the stdlib for most of the environment
74*9bb1b549SSpandan Das    # variables, but our GOPATH is specific to the library target we were given.
75*9bb1b549SSpandan Das    ctx.actions.run_shell(
76*9bb1b549SSpandan Das        outputs = [ctx.outputs.out],
77*9bb1b549SSpandan Das        inputs = inputs,
78*9bb1b549SSpandan Das        tools = [
79*9bb1b549SSpandan Das            ctx.file.mockgen_tool,
80*9bb1b549SSpandan Das            go_ctx.go,
81*9bb1b549SSpandan Das        ],
82*9bb1b549SSpandan Das        command = """
83*9bb1b549SSpandan Das            export GOPATH=$(pwd)/{gopath} &&
84*9bb1b549SSpandan Das            {cmd} {args} > {out}
85*9bb1b549SSpandan Das        """.format(
86*9bb1b549SSpandan Das            gopath = gopath,
87*9bb1b549SSpandan Das            cmd = "$(pwd)/" + ctx.file.mockgen_tool.path,
88*9bb1b549SSpandan Das            args = " ".join(args),
89*9bb1b549SSpandan Das            out = ctx.outputs.out.path,
90*9bb1b549SSpandan Das            mnemonic = "GoMockSourceGen",
91*9bb1b549SSpandan Das        ),
92*9bb1b549SSpandan Das        env = {
93*9bb1b549SSpandan Das            # GOCACHE is required starting in Go 1.12
94*9bb1b549SSpandan Das            "GOCACHE": "./.gocache",
95*9bb1b549SSpandan Das        },
96*9bb1b549SSpandan Das    )
97*9bb1b549SSpandan Das
98*9bb1b549SSpandan Das_gomock_source = rule(
99*9bb1b549SSpandan Das    _gomock_source_impl,
100*9bb1b549SSpandan Das    attrs = {
101*9bb1b549SSpandan Das        "library": attr.label(
102*9bb1b549SSpandan Das            doc = "The target the Go library where this source file belongs",
103*9bb1b549SSpandan Das            providers = [GoLibrary],
104*9bb1b549SSpandan Das            mandatory = True,
105*9bb1b549SSpandan Das        ),
106*9bb1b549SSpandan Das        "source": attr.label(
107*9bb1b549SSpandan Das            doc = "A Go source file to find all the interfaces to generate mocks for. See also the docs for library.",
108*9bb1b549SSpandan Das            mandatory = False,
109*9bb1b549SSpandan Das            allow_single_file = True,
110*9bb1b549SSpandan Das        ),
111*9bb1b549SSpandan Das        "out": attr.output(
112*9bb1b549SSpandan Das            doc = "The new Go file to emit the generated mocks into",
113*9bb1b549SSpandan Das            mandatory = True,
114*9bb1b549SSpandan Das        ),
115*9bb1b549SSpandan Das        "aux_files": attr.label_keyed_string_dict(
116*9bb1b549SSpandan Das            default = {},
117*9bb1b549SSpandan Das            doc = "A map from auxilliary Go source files to their packages.",
118*9bb1b549SSpandan Das            allow_files = True,
119*9bb1b549SSpandan Das        ),
120*9bb1b549SSpandan Das        "package": attr.string(
121*9bb1b549SSpandan Das            doc = "The name of the package the generated mocks should be in. If not specified, uses mockgen's default.",
122*9bb1b549SSpandan Das        ),
123*9bb1b549SSpandan Das        "self_package": attr.string(
124*9bb1b549SSpandan Das            doc = "The full package import path for the generated code. The purpose of this flag is to prevent import cycles in the generated code by trying to include its own package. This can happen if the mock's package is set to one of its inputs (usually the main one) and the output is stdio so mockgen cannot detect the final output package. Setting this flag will then tell mockgen which import to exclude.",
125*9bb1b549SSpandan Das        ),
126*9bb1b549SSpandan Das        "imports": attr.string_dict(
127*9bb1b549SSpandan Das            doc = "Dictionary of name-path pairs of explicit imports to use.",
128*9bb1b549SSpandan Das        ),
129*9bb1b549SSpandan Das        "mock_names": attr.string_dict(
130*9bb1b549SSpandan Das            doc = "Dictionary of interface name to mock name pairs to change the output names of the mock objects. Mock names default to 'Mock' prepended to the name of the interface.",
131*9bb1b549SSpandan Das            default = {},
132*9bb1b549SSpandan Das        ),
133*9bb1b549SSpandan Das        "copyright_file": attr.label(
134*9bb1b549SSpandan Das            doc = "Optional file containing copyright to prepend to the generated contents.",
135*9bb1b549SSpandan Das            allow_single_file = True,
136*9bb1b549SSpandan Das            mandatory = False,
137*9bb1b549SSpandan Das        ),
138*9bb1b549SSpandan Das        "mockgen_tool": attr.label(
139*9bb1b549SSpandan Das            doc = "The mockgen tool to run",
140*9bb1b549SSpandan Das            default = _MOCKGEN_TOOL,
141*9bb1b549SSpandan Das            allow_single_file = True,
142*9bb1b549SSpandan Das            executable = True,
143*9bb1b549SSpandan Das            cfg = "exec",
144*9bb1b549SSpandan Das            mandatory = False,
145*9bb1b549SSpandan Das        ),
146*9bb1b549SSpandan Das        "_go_context_data": attr.label(
147*9bb1b549SSpandan Das            default = "//:go_context_data",
148*9bb1b549SSpandan Das        ),
149*9bb1b549SSpandan Das    },
150*9bb1b549SSpandan Das    toolchains = [GO_TOOLCHAIN],
151*9bb1b549SSpandan Das)
152*9bb1b549SSpandan Das
153*9bb1b549SSpandan Dasdef gomock(name, library, out, source = None, interfaces = [], package = "", self_package = "", aux_files = {}, mockgen_tool = _MOCKGEN_TOOL, imports = {}, copyright_file = None, mock_names = {}, **kwargs):
154*9bb1b549SSpandan Das    """Calls [mockgen](https://github.com/golang/mock) to generates a Go file containing mocks from the given library.
155*9bb1b549SSpandan Das
156*9bb1b549SSpandan Das    If `source` is given, the mocks are generated in source mode; otherwise in reflective mode.
157*9bb1b549SSpandan Das
158*9bb1b549SSpandan Das    Args:
159*9bb1b549SSpandan Das        name: the target name.
160*9bb1b549SSpandan Das        library: the Go library to took for the interfaces (reflecitve mode) or source (source mode).
161*9bb1b549SSpandan Das        out: the output Go file name.
162*9bb1b549SSpandan Das        source: a Go file in the given `library`. If this is given, `gomock` will call mockgen in source mode to mock all interfaces in the file.
163*9bb1b549SSpandan Das        interfaces: a list of interfaces in the given `library` to be mocked in reflective mode.
164*9bb1b549SSpandan Das        package: the name of the package the generated mocks should be in. If not specified, uses mockgen's default. See [mockgen's -package](https://github.com/golang/mock#flags) for more information.
165*9bb1b549SSpandan Das        self_package: the full package import path for the generated code. The purpose of this flag is to prevent import cycles in the generated code by trying to include its own package. See [mockgen's -self_package](https://github.com/golang/mock#flags) for more information.
166*9bb1b549SSpandan Das        aux_files: a map from source files to their package path. This only needed when `source` is provided. See [mockgen's -aux_files](https://github.com/golang/mock#flags) for more information.
167*9bb1b549SSpandan Das        mockgen_tool: the mockgen tool to run.
168*9bb1b549SSpandan Das        imports: dictionary of name-path pairs of explicit imports to use. See [mockgen's -imports](https://github.com/golang/mock#flags) for more information.
169*9bb1b549SSpandan Das        copyright_file: optional file containing copyright to prepend to the generated contents. See [mockgen's -copyright_file](https://github.com/golang/mock#flags) for more information.
170*9bb1b549SSpandan Das        mock_names: dictionary of interface name to mock name pairs to change the output names of the mock objects. Mock names default to 'Mock' prepended to the name of the interface. See [mockgen's -mock_names](https://github.com/golang/mock#flags) for more information.
171*9bb1b549SSpandan Das        kwargs: common attributes](https://bazel.build/reference/be/common-definitions#common-attributes) to all Bazel rules.
172*9bb1b549SSpandan Das    """
173*9bb1b549SSpandan Das    if source:
174*9bb1b549SSpandan Das        _gomock_source(
175*9bb1b549SSpandan Das            name = name,
176*9bb1b549SSpandan Das            library = library,
177*9bb1b549SSpandan Das            out = out,
178*9bb1b549SSpandan Das            source = source,
179*9bb1b549SSpandan Das            package = package,
180*9bb1b549SSpandan Das            self_package = self_package,
181*9bb1b549SSpandan Das            aux_files = aux_files,
182*9bb1b549SSpandan Das            mockgen_tool = mockgen_tool,
183*9bb1b549SSpandan Das            imports = imports,
184*9bb1b549SSpandan Das            copyright_file = copyright_file,
185*9bb1b549SSpandan Das            mock_names = mock_names,
186*9bb1b549SSpandan Das            **kwargs
187*9bb1b549SSpandan Das        )
188*9bb1b549SSpandan Das    else:
189*9bb1b549SSpandan Das        _gomock_reflect(
190*9bb1b549SSpandan Das            name = name,
191*9bb1b549SSpandan Das            library = library,
192*9bb1b549SSpandan Das            out = out,
193*9bb1b549SSpandan Das            interfaces = interfaces,
194*9bb1b549SSpandan Das            package = package,
195*9bb1b549SSpandan Das            self_package = self_package,
196*9bb1b549SSpandan Das            mockgen_tool = mockgen_tool,
197*9bb1b549SSpandan Das            imports = imports,
198*9bb1b549SSpandan Das            copyright_file = copyright_file,
199*9bb1b549SSpandan Das            mock_names = mock_names,
200*9bb1b549SSpandan Das            **kwargs
201*9bb1b549SSpandan Das        )
202*9bb1b549SSpandan Das
203*9bb1b549SSpandan Dasdef _gomock_reflect(name, library, out, mockgen_tool, **kwargs):
204*9bb1b549SSpandan Das    interfaces = kwargs.pop("interfaces", None)
205*9bb1b549SSpandan Das
206*9bb1b549SSpandan Das    mockgen_model_lib = _MOCKGEN_MODEL_LIB
207*9bb1b549SSpandan Das    if kwargs.get("mockgen_model_library", None):
208*9bb1b549SSpandan Das        mockgen_model_lib = kwargs["mockgen_model_library"]
209*9bb1b549SSpandan Das
210*9bb1b549SSpandan Das    prog_src = name + "_gomock_prog"
211*9bb1b549SSpandan Das    prog_src_out = prog_src + ".go"
212*9bb1b549SSpandan Das    _gomock_prog_gen(
213*9bb1b549SSpandan Das        name = prog_src,
214*9bb1b549SSpandan Das        interfaces = interfaces,
215*9bb1b549SSpandan Das        library = library,
216*9bb1b549SSpandan Das        out = prog_src_out,
217*9bb1b549SSpandan Das        mockgen_tool = mockgen_tool,
218*9bb1b549SSpandan Das    )
219*9bb1b549SSpandan Das    prog_bin = name + "_gomock_prog_bin"
220*9bb1b549SSpandan Das    go_binary(
221*9bb1b549SSpandan Das        name = prog_bin,
222*9bb1b549SSpandan Das        srcs = [prog_src_out],
223*9bb1b549SSpandan Das        deps = [library, mockgen_model_lib],
224*9bb1b549SSpandan Das    )
225*9bb1b549SSpandan Das    _gomock_prog_exec(
226*9bb1b549SSpandan Das        name = name,
227*9bb1b549SSpandan Das        interfaces = interfaces,
228*9bb1b549SSpandan Das        library = library,
229*9bb1b549SSpandan Das        out = out,
230*9bb1b549SSpandan Das        prog_bin = prog_bin,
231*9bb1b549SSpandan Das        mockgen_tool = mockgen_tool,
232*9bb1b549SSpandan Das        **kwargs
233*9bb1b549SSpandan Das    )
234*9bb1b549SSpandan Das
235*9bb1b549SSpandan Dasdef _gomock_prog_gen_impl(ctx):
236*9bb1b549SSpandan Das    args = ["-prog_only"]
237*9bb1b549SSpandan Das    args.append(ctx.attr.library[GoLibrary].importpath)
238*9bb1b549SSpandan Das    args.append(",".join(ctx.attr.interfaces))
239*9bb1b549SSpandan Das
240*9bb1b549SSpandan Das    cmd = ctx.file.mockgen_tool
241*9bb1b549SSpandan Das    out = ctx.outputs.out
242*9bb1b549SSpandan Das    ctx.actions.run_shell(
243*9bb1b549SSpandan Das        outputs = [out],
244*9bb1b549SSpandan Das        tools = [cmd],
245*9bb1b549SSpandan Das        command = """
246*9bb1b549SSpandan Das           {cmd} {args} > {out}
247*9bb1b549SSpandan Das        """.format(
248*9bb1b549SSpandan Das            cmd = "$(pwd)/" + cmd.path,
249*9bb1b549SSpandan Das            args = " ".join(args),
250*9bb1b549SSpandan Das            out = out.path,
251*9bb1b549SSpandan Das        ),
252*9bb1b549SSpandan Das        mnemonic = "GoMockReflectProgOnlyGen",
253*9bb1b549SSpandan Das    )
254*9bb1b549SSpandan Das
255*9bb1b549SSpandan Das_gomock_prog_gen = rule(
256*9bb1b549SSpandan Das    _gomock_prog_gen_impl,
257*9bb1b549SSpandan Das    attrs = {
258*9bb1b549SSpandan Das        "library": attr.label(
259*9bb1b549SSpandan Das            doc = "The target the Go library is at to look for the interfaces in. When this is set and source is not set, mockgen will use its reflect code to generate the mocks. If source is set, its dependencies will be included in the GOPATH that mockgen will be run in.",
260*9bb1b549SSpandan Das            providers = [GoLibrary],
261*9bb1b549SSpandan Das            mandatory = True,
262*9bb1b549SSpandan Das        ),
263*9bb1b549SSpandan Das        "out": attr.output(
264*9bb1b549SSpandan Das            doc = "The new Go source file put the mock generator code",
265*9bb1b549SSpandan Das            mandatory = True,
266*9bb1b549SSpandan Das        ),
267*9bb1b549SSpandan Das        "interfaces": attr.string_list(
268*9bb1b549SSpandan Das            allow_empty = False,
269*9bb1b549SSpandan Das            doc = "The names of the Go interfaces to generate mocks for. If not set, all of the interfaces in the library or source file will have mocks generated for them.",
270*9bb1b549SSpandan Das            mandatory = True,
271*9bb1b549SSpandan Das        ),
272*9bb1b549SSpandan Das        "mockgen_tool": attr.label(
273*9bb1b549SSpandan Das            doc = "The mockgen tool to run",
274*9bb1b549SSpandan Das            default = _MOCKGEN_TOOL,
275*9bb1b549SSpandan Das            allow_single_file = True,
276*9bb1b549SSpandan Das            executable = True,
277*9bb1b549SSpandan Das            cfg = "exec",
278*9bb1b549SSpandan Das            mandatory = False,
279*9bb1b549SSpandan Das        ),
280*9bb1b549SSpandan Das        "_go_context_data": attr.label(
281*9bb1b549SSpandan Das            default = "//:go_context_data",
282*9bb1b549SSpandan Das        ),
283*9bb1b549SSpandan Das    },
284*9bb1b549SSpandan Das    toolchains = [GO_TOOLCHAIN],
285*9bb1b549SSpandan Das)
286*9bb1b549SSpandan Das
287*9bb1b549SSpandan Dasdef _gomock_prog_exec_impl(ctx):
288*9bb1b549SSpandan Das    args = ["-exec_only", ctx.file.prog_bin.path]
289*9bb1b549SSpandan Das    args, needed_files = _handle_shared_args(ctx, args)
290*9bb1b549SSpandan Das
291*9bb1b549SSpandan Das    # annoyingly, the interfaces join has to go after the importpath so we can't
292*9bb1b549SSpandan Das    # share those.
293*9bb1b549SSpandan Das    args.append(ctx.attr.library[GoLibrary].importpath)
294*9bb1b549SSpandan Das    args.append(",".join(ctx.attr.interfaces))
295*9bb1b549SSpandan Das
296*9bb1b549SSpandan Das    ctx.actions.run_shell(
297*9bb1b549SSpandan Das        outputs = [ctx.outputs.out],
298*9bb1b549SSpandan Das        inputs = [ctx.file.prog_bin] + needed_files,
299*9bb1b549SSpandan Das        tools = [ctx.file.mockgen_tool],
300*9bb1b549SSpandan Das        command = """{cmd} {args} > {out}""".format(
301*9bb1b549SSpandan Das            cmd = "$(pwd)/" + ctx.file.mockgen_tool.path,
302*9bb1b549SSpandan Das            args = " ".join(args),
303*9bb1b549SSpandan Das            out = ctx.outputs.out.path,
304*9bb1b549SSpandan Das        ),
305*9bb1b549SSpandan Das        env = {
306*9bb1b549SSpandan Das            # GOCACHE is required starting in Go 1.12
307*9bb1b549SSpandan Das            "GOCACHE": "./.gocache",
308*9bb1b549SSpandan Das        },
309*9bb1b549SSpandan Das        mnemonic = "GoMockReflectExecOnlyGen",
310*9bb1b549SSpandan Das    )
311*9bb1b549SSpandan Das
312*9bb1b549SSpandan Das_gomock_prog_exec = rule(
313*9bb1b549SSpandan Das    _gomock_prog_exec_impl,
314*9bb1b549SSpandan Das    attrs = {
315*9bb1b549SSpandan Das        "library": attr.label(
316*9bb1b549SSpandan Das            doc = "The target the Go library is at to look for the interfaces in. When this is set and source is not set, mockgen will use its reflect code to generate the mocks. If source is set, its dependencies will be included in the GOPATH that mockgen will be run in.",
317*9bb1b549SSpandan Das            providers = [GoLibrary],
318*9bb1b549SSpandan Das            mandatory = True,
319*9bb1b549SSpandan Das        ),
320*9bb1b549SSpandan Das        "out": attr.output(
321*9bb1b549SSpandan Das            doc = "The new Go source file to put the generated mock code",
322*9bb1b549SSpandan Das            mandatory = True,
323*9bb1b549SSpandan Das        ),
324*9bb1b549SSpandan Das        "interfaces": attr.string_list(
325*9bb1b549SSpandan Das            allow_empty = False,
326*9bb1b549SSpandan Das            doc = "The names of the Go interfaces to generate mocks for. If not set, all of the interfaces in the library or source file will have mocks generated for them.",
327*9bb1b549SSpandan Das            mandatory = True,
328*9bb1b549SSpandan Das        ),
329*9bb1b549SSpandan Das        "package": attr.string(
330*9bb1b549SSpandan Das            doc = "The name of the package the generated mocks should be in. If not specified, uses mockgen's default.",
331*9bb1b549SSpandan Das        ),
332*9bb1b549SSpandan Das        "self_package": attr.string(
333*9bb1b549SSpandan Das            doc = "The full package import path for the generated code. The purpose of this flag is to prevent import cycles in the generated code by trying to include its own package. This can happen if the mock's package is set to one of its inputs (usually the main one) and the output is stdio so mockgen cannot detect the final output package. Setting this flag will then tell mockgen which import to exclude.",
334*9bb1b549SSpandan Das        ),
335*9bb1b549SSpandan Das        "imports": attr.string_dict(
336*9bb1b549SSpandan Das            doc = "Dictionary of name-path pairs of explicit imports to use.",
337*9bb1b549SSpandan Das        ),
338*9bb1b549SSpandan Das        "mock_names": attr.string_dict(
339*9bb1b549SSpandan Das            doc = "Dictionary of interfaceName-mockName pairs of explicit mock names to use. Mock names default to 'Mock'+ interfaceName suffix.",
340*9bb1b549SSpandan Das            default = {},
341*9bb1b549SSpandan Das        ),
342*9bb1b549SSpandan Das        "copyright_file": attr.label(
343*9bb1b549SSpandan Das            doc = "Optional file containing copyright to prepend to the generated contents.",
344*9bb1b549SSpandan Das            allow_single_file = True,
345*9bb1b549SSpandan Das            mandatory = False,
346*9bb1b549SSpandan Das        ),
347*9bb1b549SSpandan Das        "prog_bin": attr.label(
348*9bb1b549SSpandan Das            doc = "The program binary generated by mockgen's -prog_only and compiled by bazel.",
349*9bb1b549SSpandan Das            allow_single_file = True,
350*9bb1b549SSpandan Das            executable = True,
351*9bb1b549SSpandan Das            cfg = "exec",
352*9bb1b549SSpandan Das            mandatory = True,
353*9bb1b549SSpandan Das        ),
354*9bb1b549SSpandan Das        "mockgen_tool": attr.label(
355*9bb1b549SSpandan Das            doc = "The mockgen tool to run",
356*9bb1b549SSpandan Das            default = _MOCKGEN_TOOL,
357*9bb1b549SSpandan Das            allow_single_file = True,
358*9bb1b549SSpandan Das            executable = True,
359*9bb1b549SSpandan Das            cfg = "exec",
360*9bb1b549SSpandan Das            mandatory = False,
361*9bb1b549SSpandan Das        ),
362*9bb1b549SSpandan Das        "_go_context_data": attr.label(
363*9bb1b549SSpandan Das            default = "//:go_context_data",
364*9bb1b549SSpandan Das        ),
365*9bb1b549SSpandan Das    },
366*9bb1b549SSpandan Das    toolchains = [GO_TOOLCHAIN],
367*9bb1b549SSpandan Das)
368*9bb1b549SSpandan Das
369*9bb1b549SSpandan Dasdef _handle_shared_args(ctx, args):
370*9bb1b549SSpandan Das    needed_files = []
371*9bb1b549SSpandan Das
372*9bb1b549SSpandan Das    if ctx.attr.package != "":
373*9bb1b549SSpandan Das        args += ["-package", ctx.attr.package]
374*9bb1b549SSpandan Das    if ctx.attr.self_package != "":
375*9bb1b549SSpandan Das        args += ["-self_package", ctx.attr.self_package]
376*9bb1b549SSpandan Das    if len(ctx.attr.imports) > 0:
377*9bb1b549SSpandan Das        imports = ",".join(["{0}={1}".format(name, pkg) for name, pkg in ctx.attr.imports.items()])
378*9bb1b549SSpandan Das        args += ["-imports", imports]
379*9bb1b549SSpandan Das    if ctx.file.copyright_file != None:
380*9bb1b549SSpandan Das        args += ["-copyright_file", ctx.file.copyright_file.path]
381*9bb1b549SSpandan Das        needed_files.append(ctx.file.copyright_file)
382*9bb1b549SSpandan Das    if len(ctx.attr.mock_names) > 0:
383*9bb1b549SSpandan Das        mock_names = ",".join(["{0}={1}".format(name, pkg) for name, pkg in ctx.attr.mock_names.items()])
384*9bb1b549SSpandan Das        args += ["-mock_names", mock_names]
385*9bb1b549SSpandan Das
386*9bb1b549SSpandan Das    return args, needed_files
387