Vendor dependencies
Let's see how I like this workflow.
This commit is contained in:
parent
34d1830413
commit
9c435dc440
7500 changed files with 1665121 additions and 99 deletions
183
vendor/cxx/tools/buck/prelude/go/cgo_library.bzl
vendored
Normal file
183
vendor/cxx/tools/buck/prelude/go/cgo_library.bzl
vendored
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# This source code is licensed under both the MIT license found in the
|
||||
# LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
load("@prelude//:paths.bzl", "paths")
|
||||
load(
|
||||
"@prelude//cxx:compile.bzl",
|
||||
"CxxSrcWithFlags", # @unused Used as a type
|
||||
)
|
||||
load("@prelude//cxx:cxx_library.bzl", "cxx_compile_srcs")
|
||||
load("@prelude//cxx:cxx_toolchain_types.bzl", "CxxToolchainInfo")
|
||||
load(
|
||||
"@prelude//cxx:cxx_types.bzl",
|
||||
"CxxRuleConstructorParams", # @unused Used as a type
|
||||
)
|
||||
load("@prelude//cxx:headers.bzl", "cxx_get_regular_cxx_headers_layout", "prepare_headers")
|
||||
load(
|
||||
"@prelude//cxx:preprocessor.bzl",
|
||||
"CPreprocessor",
|
||||
"cxx_inherited_preprocessor_infos",
|
||||
"cxx_merge_cpreprocessors",
|
||||
"cxx_private_preprocessor_info",
|
||||
)
|
||||
load(
|
||||
"@prelude//linking:link_info.bzl",
|
||||
"Linkage",
|
||||
"MergedLinkInfo",
|
||||
"merge_link_infos",
|
||||
)
|
||||
load(
|
||||
"@prelude//linking:shared_libraries.bzl",
|
||||
"SharedLibraryInfo",
|
||||
"merge_shared_libraries",
|
||||
)
|
||||
load(
|
||||
"@prelude//utils:utils.bzl",
|
||||
"expect",
|
||||
"map_idx",
|
||||
)
|
||||
load(":compile.bzl", "GoPkgCompileInfo", "compile", "get_filtered_srcs", "get_inherited_compile_pkgs")
|
||||
load(":link.bzl", "GoPkgLinkInfo", "get_inherited_link_pkgs")
|
||||
load(":packages.bzl", "go_attr_pkg_name", "merge_pkgs")
|
||||
load(":toolchain.bzl", "GoToolchainInfo", "get_toolchain_cmd_args")
|
||||
|
||||
def _cgo(
|
||||
ctx: "context",
|
||||
srcs: ["artifact"],
|
||||
own_pre: [CPreprocessor.type],
|
||||
inherited_pre: ["CPreprocessorInfo"]) -> (["artifact"], ["artifact"], ["artifact"]):
|
||||
"""
|
||||
Run `cgo` on `.go` sources to genreate Go, C, and C-Header sources.
|
||||
"""
|
||||
|
||||
pre = cxx_merge_cpreprocessors(ctx, own_pre, inherited_pre)
|
||||
pre_args = pre.set.project_as_args("args")
|
||||
|
||||
gen_dir = "cgo_gen"
|
||||
|
||||
go_srcs = []
|
||||
c_headers = []
|
||||
c_srcs = []
|
||||
go_srcs.append(ctx.actions.declare_output(paths.join(gen_dir, "_cgo_gotypes.go")))
|
||||
c_srcs.append(ctx.actions.declare_output(paths.join(gen_dir, "_cgo_export.c")))
|
||||
c_headers.append(ctx.actions.declare_output(paths.join(gen_dir, "_cgo_export.h")))
|
||||
for src in srcs:
|
||||
go_srcs.append(ctx.actions.declare_output(paths.join(gen_dir, paths.replace_extension(src.basename, ".cgo1.go"))))
|
||||
c_srcs.append(ctx.actions.declare_output(paths.join(gen_dir, paths.replace_extension(src.basename, ".cgo2.c"))))
|
||||
|
||||
# Return a `cmd_args` to use as the generated sources.
|
||||
go_toolchain = ctx.attrs._go_toolchain[GoToolchainInfo]
|
||||
expect(go_toolchain.cgo != None)
|
||||
expect(CxxToolchainInfo in ctx.attrs._cxx_toolchain)
|
||||
cxx_toolchain = ctx.attrs._cxx_toolchain[CxxToolchainInfo]
|
||||
|
||||
cmd = get_toolchain_cmd_args(go_toolchain, go_root = False)
|
||||
cmd.add(go_toolchain.cgo_wrapper[RunInfo])
|
||||
cmd.add(cmd_args(go_toolchain.cgo, format = "--cgo={}"))
|
||||
|
||||
# TODO(agallagher): cgo outputs a dir with generated sources, but I'm not
|
||||
# sure how to pass in an output dir *and* enumerate the sources we know will
|
||||
# generated w/o v2 complaining that the output dir conflicts with the nested
|
||||
# artifacts.
|
||||
cmd.add(cmd_args(go_srcs[0].as_output(), format = "--output={}/.."))
|
||||
cmd.add(cmd_args(cxx_toolchain.c_compiler_info.preprocessor, format = "--cpp={}"))
|
||||
cmd.add(cmd_args(pre_args, format = "--cpp={}"))
|
||||
cmd.add(srcs)
|
||||
for src in go_srcs + c_headers + c_srcs:
|
||||
cmd.hidden(src.as_output())
|
||||
ctx.actions.run(cmd, category = "cgo")
|
||||
|
||||
return go_srcs, c_headers, c_srcs
|
||||
|
||||
def cgo_library_impl(ctx: "context") -> ["provider"]:
|
||||
pkg_name = go_attr_pkg_name(ctx)
|
||||
|
||||
# Gather preprocessor inputs.
|
||||
(own_pre, _) = cxx_private_preprocessor_info(
|
||||
ctx,
|
||||
cxx_get_regular_cxx_headers_layout(ctx),
|
||||
)
|
||||
inherited_pre = cxx_inherited_preprocessor_infos(ctx.attrs.deps)
|
||||
|
||||
# Seprate sources into C++ and CGO sources.
|
||||
cgo_srcs = []
|
||||
cxx_srcs = []
|
||||
for src in ctx.attrs.srcs:
|
||||
if src.extension == ".go":
|
||||
cgo_srcs.append(src)
|
||||
elif src.extension in (".c", ".cpp"):
|
||||
cxx_srcs.append(src)
|
||||
else:
|
||||
fail("unexpected extension: {}".format(src))
|
||||
|
||||
# Generate CGO and C sources.
|
||||
go_srcs, c_headers, c_srcs = _cgo(ctx, cgo_srcs, [own_pre], inherited_pre)
|
||||
cxx_srcs.extend(c_srcs)
|
||||
|
||||
# Wrap the generated CGO C headers in a CPreprocessor object for compiling.
|
||||
cgo_headers_pre = CPreprocessor(args = [
|
||||
"-I",
|
||||
prepare_headers(
|
||||
ctx,
|
||||
{h.basename: h for h in c_headers},
|
||||
"cgo-private-headers",
|
||||
).include_path,
|
||||
])
|
||||
|
||||
link_style = ctx.attrs.link_style
|
||||
if link_style == None:
|
||||
link_style = "static"
|
||||
|
||||
# Copmile C++ sources into object files.
|
||||
c_compile_cmds = cxx_compile_srcs(
|
||||
ctx,
|
||||
CxxRuleConstructorParams(
|
||||
rule_type = "cgo_library",
|
||||
headers_layout = cxx_get_regular_cxx_headers_layout(ctx),
|
||||
srcs = [CxxSrcWithFlags(file = src) for src in cxx_srcs],
|
||||
),
|
||||
# Create private header tree and propagate via args.
|
||||
[own_pre, cgo_headers_pre],
|
||||
inherited_pre,
|
||||
[],
|
||||
Linkage(link_style),
|
||||
)
|
||||
|
||||
compiled_objects = c_compile_cmds.objects
|
||||
if link_style != "static":
|
||||
compiled_objects = c_compile_cmds.pic_objects
|
||||
|
||||
# Merge all sources together to pass to the Go compile step.
|
||||
all_srcs = cmd_args(go_srcs + compiled_objects)
|
||||
if ctx.attrs.go_srcs:
|
||||
all_srcs.add(get_filtered_srcs(ctx, ctx.attrs.go_srcs))
|
||||
|
||||
# Build Go library.
|
||||
lib = compile(
|
||||
ctx,
|
||||
pkg_name,
|
||||
all_srcs,
|
||||
deps = ctx.attrs.deps + ctx.attrs.exported_deps,
|
||||
)
|
||||
|
||||
pkgs = {pkg_name: lib}
|
||||
return [
|
||||
DefaultInfo(default_outputs = [lib]),
|
||||
GoPkgCompileInfo(pkgs = merge_pkgs([
|
||||
pkgs,
|
||||
get_inherited_compile_pkgs(ctx.attrs.exported_deps),
|
||||
])),
|
||||
GoPkgLinkInfo(pkgs = merge_pkgs([
|
||||
pkgs,
|
||||
get_inherited_link_pkgs(ctx.attrs.deps + ctx.attrs.exported_deps),
|
||||
])),
|
||||
merge_link_infos(ctx, filter(None, [d.get(MergedLinkInfo) for d in ctx.attrs.deps])),
|
||||
merge_shared_libraries(
|
||||
ctx.actions,
|
||||
deps = filter(None, map_idx(SharedLibraryInfo, ctx.attrs.deps)),
|
||||
),
|
||||
]
|
||||
134
vendor/cxx/tools/buck/prelude/go/compile.bzl
vendored
Normal file
134
vendor/cxx/tools/buck/prelude/go/compile.bzl
vendored
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# This source code is licensed under both the MIT license found in the
|
||||
# LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
load("@prelude//:paths.bzl", "paths")
|
||||
load(":packages.bzl", "merge_pkgs")
|
||||
load(":toolchain.bzl", "GoToolchainInfo", "get_toolchain_cmd_args")
|
||||
|
||||
# Provider wrapping packages used for compiling.
|
||||
GoPkgCompileInfo = provider(fields = [
|
||||
"pkgs", # {str.type: "artifact"}
|
||||
])
|
||||
|
||||
# Provider for test targets that test a library. Contains information for
|
||||
# compiling the test and library code together as expected by go.
|
||||
GoTestInfo = provider(fields = [
|
||||
"deps", # ["dependency"]
|
||||
"srcs", # ["source"]
|
||||
"pkg_name", # str.type
|
||||
])
|
||||
|
||||
def get_inherited_compile_pkgs(deps: ["dependency"]) -> {str.type: "artifact"}:
|
||||
return merge_pkgs([d[GoPkgCompileInfo].pkgs for d in deps if GoPkgCompileInfo in d])
|
||||
|
||||
def get_filtered_srcs(ctx: "context", srcs: ["artifact"], tests: bool.type = False) -> "cmd_args":
|
||||
"""
|
||||
Filter the input sources based on build pragma
|
||||
"""
|
||||
|
||||
go_toolchain = ctx.attrs._go_toolchain[GoToolchainInfo]
|
||||
|
||||
# Delegate to `go list` to filter out srcs with incompatible `// +build`
|
||||
# pragmas.
|
||||
filtered_srcs = ctx.actions.declare_output("__filtered_srcs__.txt")
|
||||
srcs_dir = ctx.actions.symlinked_dir(
|
||||
"__srcs__",
|
||||
{src.short_path: src for src in srcs},
|
||||
)
|
||||
filter_cmd = get_toolchain_cmd_args(go_toolchain, go_root = False)
|
||||
filter_cmd.add(go_toolchain.filter_srcs[RunInfo])
|
||||
filter_cmd.add(cmd_args(go_toolchain.go, format = "--go={}"))
|
||||
if tests:
|
||||
filter_cmd.add("--tests")
|
||||
filter_cmd.add(cmd_args(",".join(go_toolchain.tags), format = "--tags={}"))
|
||||
filter_cmd.add(cmd_args(filtered_srcs.as_output(), format = "--output={}"))
|
||||
filter_cmd.add(srcs_dir)
|
||||
ctx.actions.run(filter_cmd, category = "go_filter_srcs")
|
||||
|
||||
# Add filtered srcs to compile command.
|
||||
return cmd_args(filtered_srcs, format = "@{}").hidden(srcs)
|
||||
|
||||
def _get_import_map(pkgs: [str.type]) -> {str.type: str.type}:
|
||||
"""
|
||||
Return the import remappings for vendor paths.
|
||||
"""
|
||||
|
||||
vendor_prefixes = []
|
||||
vendor_prefixes.append("third-party-source/go")
|
||||
|
||||
# TODO: add in implicit vendor prefixes inferred from project name.
|
||||
vendor_prefixes = reversed(sorted(vendor_prefixes))
|
||||
|
||||
mappings = {}
|
||||
for pkg in pkgs:
|
||||
for prefix in vendor_prefixes:
|
||||
if paths.starts_with(pkg, prefix):
|
||||
mappings[paths.relativize(pkg, prefix)] = pkg
|
||||
break
|
||||
|
||||
return mappings
|
||||
|
||||
def _assemble_cmd(
|
||||
ctx: "context",
|
||||
flags: [str.type] = []) -> "cmd_args":
|
||||
go_toolchain = ctx.attrs._go_toolchain[GoToolchainInfo]
|
||||
cmd = cmd_args()
|
||||
cmd.add(go_toolchain.assembler)
|
||||
cmd.add(flags)
|
||||
return cmd
|
||||
|
||||
def _compile_cmd(
|
||||
ctx: "context",
|
||||
pkg_name: str.type,
|
||||
pkgs: {str.type: "artifact"} = {},
|
||||
deps: ["dependency"] = [],
|
||||
flags: [str.type] = []) -> "cmd_args":
|
||||
go_toolchain = ctx.attrs._go_toolchain[GoToolchainInfo]
|
||||
|
||||
cmd = cmd_args()
|
||||
cmd.add(go_toolchain.compiler)
|
||||
cmd.add("-p", pkg_name)
|
||||
cmd.add("-pack")
|
||||
cmd.add("-nolocalimports")
|
||||
cmd.add(flags)
|
||||
cmd.add("-buildid=")
|
||||
|
||||
# Add Go pkgs inherited from deps to compiler search path.
|
||||
all_pkgs = merge_pkgs([pkgs, get_inherited_compile_pkgs(deps)])
|
||||
if all_pkgs:
|
||||
pkg_dir = ctx.actions.symlinked_dir(
|
||||
"__{}_compile_pkgs__".format(paths.basename(pkg_name)),
|
||||
{name + path.extension: path for name, path in all_pkgs.items()},
|
||||
)
|
||||
cmd.add("-I", pkg_dir)
|
||||
|
||||
for mapping in _get_import_map(all_pkgs.keys()).items():
|
||||
cmd.add("-importmap", "{}={}".format(*mapping))
|
||||
|
||||
return cmd
|
||||
|
||||
def compile(
|
||||
ctx: "context",
|
||||
pkg_name: str.type,
|
||||
srcs: "cmd_args",
|
||||
pkgs: {str.type: "artifact"} = {},
|
||||
deps: ["dependency"] = [],
|
||||
compile_flags: [str.type] = [],
|
||||
assemble_flags: [str.type] = []) -> "artifact":
|
||||
go_toolchain = ctx.attrs._go_toolchain[GoToolchainInfo]
|
||||
output = ctx.actions.declare_output(paths.basename(pkg_name) + ".a")
|
||||
|
||||
cmd = get_toolchain_cmd_args(go_toolchain)
|
||||
cmd.add(go_toolchain.compile_wrapper[RunInfo])
|
||||
cmd.add(cmd_args(output.as_output(), format = "--output={}"))
|
||||
cmd.add(cmd_args(_compile_cmd(ctx, pkg_name, pkgs, deps, compile_flags), format = "--compiler={}"))
|
||||
cmd.add(cmd_args(_assemble_cmd(ctx, assemble_flags), format = "--assembler={}"))
|
||||
cmd.add(cmd_args(go_toolchain.packer, format = "--packer={}"))
|
||||
cmd.add(srcs)
|
||||
ctx.actions.run(cmd, category = "go_compile", identifier = paths.basename(pkg_name))
|
||||
|
||||
return output
|
||||
46
vendor/cxx/tools/buck/prelude/go/coverage.bzl
vendored
Normal file
46
vendor/cxx/tools/buck/prelude/go/coverage.bzl
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# This source code is licensed under both the MIT license found in the
|
||||
# LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
load(":toolchain.bzl", "GoToolchainInfo")
|
||||
|
||||
GoCoverageMode = enum(
|
||||
"set",
|
||||
"count",
|
||||
"atomic",
|
||||
)
|
||||
|
||||
# The result of runnin `go tool cover` on the input sources.
|
||||
GoCoverResult = record(
|
||||
# All sources after annotating non-`_test.go` sources. This will be a
|
||||
# combination of the original `*_test.go` sources and the annotated non-
|
||||
# `*_test.go` sources.
|
||||
srcs = field("cmd_args"),
|
||||
# Coverage variables we used when annotating non-test sources.
|
||||
variables = field("cmd_args"),
|
||||
)
|
||||
|
||||
def cover_srcs(ctx: "context", pkg_name: str.type, mode: GoCoverageMode.type, srcs: "cmd_args") -> GoCoverResult.type:
|
||||
out_covered_src_dir = ctx.actions.declare_output("__covered_srcs__")
|
||||
out_srcs_argsfile = ctx.actions.declare_output("covered_srcs.txt")
|
||||
out_coverage_vars_argsfile = ctx.actions.declare_output("coverage_vars.txt")
|
||||
|
||||
go_toolchain = ctx.attrs._go_toolchain[GoToolchainInfo]
|
||||
cmd = cmd_args()
|
||||
cmd.add(go_toolchain.cover_srcs[RunInfo])
|
||||
cmd.add("--cover", go_toolchain.cover)
|
||||
cmd.add("--coverage-mode", mode.value)
|
||||
cmd.add("--coverage-var-argsfile", out_coverage_vars_argsfile.as_output())
|
||||
cmd.add("--covered-srcs-dir", out_covered_src_dir.as_output())
|
||||
cmd.add("--out-srcs-argsfile", out_srcs_argsfile.as_output())
|
||||
cmd.add("--pkg-name", pkg_name)
|
||||
cmd.add(srcs)
|
||||
ctx.actions.run(cmd, category = "go_cover")
|
||||
|
||||
return GoCoverResult(
|
||||
srcs = cmd_args(out_srcs_argsfile, format = "@{}").hidden(out_covered_src_dir).hidden(srcs),
|
||||
variables = cmd_args(out_coverage_vars_argsfile, format = "@{}"),
|
||||
)
|
||||
44
vendor/cxx/tools/buck/prelude/go/go_binary.bzl
vendored
Normal file
44
vendor/cxx/tools/buck/prelude/go/go_binary.bzl
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# This source code is licensed under both the MIT license found in the
|
||||
# LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
load(
|
||||
"@prelude//utils:utils.bzl",
|
||||
"expect",
|
||||
)
|
||||
load(":compile.bzl", "compile", "get_filtered_srcs")
|
||||
load(":link.bzl", "link")
|
||||
|
||||
def go_binary_impl(ctx: "context") -> ["provider"]:
|
||||
lib = compile(ctx, "main", get_filtered_srcs(ctx, ctx.attrs.srcs), deps = ctx.attrs.deps)
|
||||
(bin, runtime_files) = link(ctx, lib, deps = ctx.attrs.deps, link_mode = ctx.attrs.link_mode)
|
||||
|
||||
hidden = []
|
||||
for resource in ctx.attrs.resources:
|
||||
if type(resource) == "artifact":
|
||||
hidden.append(resource)
|
||||
else:
|
||||
# Otherwise, this is a dependency, so extract the resource and other
|
||||
# resources from the `DefaultInfo` provider.
|
||||
info = resource[DefaultInfo]
|
||||
expect(
|
||||
len(info.default_outputs) == 1,
|
||||
"expected exactly one default output from {} ({})"
|
||||
.format(resource, info.default_outputs),
|
||||
)
|
||||
[resource] = info.default_outputs
|
||||
other = info.other_outputs
|
||||
|
||||
hidden.append(resource)
|
||||
hidden.extend(other)
|
||||
|
||||
return [
|
||||
DefaultInfo(
|
||||
default_outputs = [bin],
|
||||
other_outputs = hidden + runtime_files,
|
||||
),
|
||||
RunInfo(args = cmd_args(bin).hidden(hidden + runtime_files)),
|
||||
]
|
||||
61
vendor/cxx/tools/buck/prelude/go/go_library.bzl
vendored
Normal file
61
vendor/cxx/tools/buck/prelude/go/go_library.bzl
vendored
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# This source code is licensed under both the MIT license found in the
|
||||
# LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
load(
|
||||
"@prelude//linking:link_info.bzl",
|
||||
"MergedLinkInfo",
|
||||
"merge_link_infos",
|
||||
)
|
||||
load(
|
||||
"@prelude//linking:shared_libraries.bzl",
|
||||
"SharedLibraryInfo",
|
||||
"merge_shared_libraries",
|
||||
)
|
||||
load(
|
||||
"@prelude//utils:utils.bzl",
|
||||
"map_idx",
|
||||
)
|
||||
load(":compile.bzl", "GoPkgCompileInfo", "GoTestInfo", "compile", "get_filtered_srcs", "get_inherited_compile_pkgs")
|
||||
load(":link.bzl", "GoPkgLinkInfo", "get_inherited_link_pkgs")
|
||||
load(":packages.bzl", "go_attr_pkg_name", "merge_pkgs")
|
||||
|
||||
def go_library_impl(ctx: "context") -> ["provider"]:
|
||||
pkgs = {}
|
||||
default_outputs = []
|
||||
pkg_name = None
|
||||
if ctx.attrs.srcs:
|
||||
pkg_name = go_attr_pkg_name(ctx)
|
||||
lib = compile(
|
||||
ctx,
|
||||
pkg_name,
|
||||
get_filtered_srcs(ctx, ctx.attrs.srcs),
|
||||
deps = ctx.attrs.deps + ctx.attrs.exported_deps,
|
||||
)
|
||||
default_outputs.append(lib)
|
||||
pkgs[pkg_name] = lib
|
||||
|
||||
return [
|
||||
DefaultInfo(default_outputs = default_outputs),
|
||||
GoPkgCompileInfo(pkgs = merge_pkgs([
|
||||
pkgs,
|
||||
get_inherited_compile_pkgs(ctx.attrs.exported_deps),
|
||||
])),
|
||||
GoPkgLinkInfo(pkgs = merge_pkgs([
|
||||
pkgs,
|
||||
get_inherited_link_pkgs(ctx.attrs.deps + ctx.attrs.exported_deps),
|
||||
])),
|
||||
GoTestInfo(
|
||||
deps = ctx.attrs.deps,
|
||||
srcs = ctx.attrs.srcs,
|
||||
pkg_name = pkg_name,
|
||||
),
|
||||
merge_link_infos(ctx, filter(None, [d.get(MergedLinkInfo) for d in ctx.attrs.deps])),
|
||||
merge_shared_libraries(
|
||||
ctx.actions,
|
||||
deps = filter(None, map_idx(SharedLibraryInfo, ctx.attrs.deps)),
|
||||
),
|
||||
]
|
||||
91
vendor/cxx/tools/buck/prelude/go/go_test.bzl
vendored
Normal file
91
vendor/cxx/tools/buck/prelude/go/go_test.bzl
vendored
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# This source code is licensed under both the MIT license found in the
|
||||
# LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
load("@prelude//test/inject_test_run_info.bzl", "inject_test_run_info")
|
||||
load(":compile.bzl", "GoTestInfo", "compile", "get_filtered_srcs")
|
||||
load(":coverage.bzl", "GoCoverageMode", "cover_srcs")
|
||||
load(":link.bzl", "link")
|
||||
load(":packages.bzl", "go_attr_pkg_name")
|
||||
|
||||
def _gen_test_main(
|
||||
ctx: "context",
|
||||
pkg_name: str.type,
|
||||
coverage_mode: [GoCoverageMode.type, None],
|
||||
coverage_vars: ["cmd_args", None],
|
||||
srcs: "cmd_args") -> "artifact":
|
||||
"""
|
||||
Generate a `main.go` which calls tests from the given sources.
|
||||
"""
|
||||
output = ctx.actions.declare_output("main.go")
|
||||
cmd = cmd_args()
|
||||
cmd.add(ctx.attrs._testmaingen[RunInfo])
|
||||
if ctx.attrs.coverage_mode:
|
||||
cmd.add(cmd_args(ctx.attrs.coverage_mode, format = "--cover-mode={}"))
|
||||
cmd.add(cmd_args(output.as_output(), format = "--output={}"))
|
||||
cmd.add(cmd_args(pkg_name, format = "--import-path={}"))
|
||||
if coverage_mode != None:
|
||||
cmd.add("--cover-mode", coverage_mode.value)
|
||||
if coverage_vars != None:
|
||||
cmd.add(coverage_vars)
|
||||
cmd.add(srcs)
|
||||
ctx.actions.run(cmd, category = "go_test_main_gen")
|
||||
return output
|
||||
|
||||
def go_test_impl(ctx: "context") -> ["provider"]:
|
||||
deps = ctx.attrs.deps
|
||||
srcs = ctx.attrs.srcs
|
||||
pkg_name = go_attr_pkg_name(ctx) + "_test"
|
||||
|
||||
# Copy the srcs, deps and pkg_name from the target library when set. The
|
||||
# library code gets compiled together with the tests.
|
||||
if ctx.attrs.library:
|
||||
lib = ctx.attrs.library[GoTestInfo]
|
||||
srcs += lib.srcs
|
||||
deps += lib.deps
|
||||
|
||||
# TODO: should we assert that pkg_name != None here?
|
||||
pkg_name = lib.pkg_name
|
||||
|
||||
srcs = get_filtered_srcs(ctx, srcs, tests = True)
|
||||
|
||||
# If coverage is enabled for this test, we need to preprocess the sources
|
||||
# with the Go cover tool.
|
||||
coverage_mode = None
|
||||
coverage_vars = None
|
||||
if ctx.attrs.coverage_mode != None:
|
||||
coverage_mode = GoCoverageMode(ctx.attrs.coverage_mode)
|
||||
cov_res = cover_srcs(ctx, pkg_name, coverage_mode, srcs)
|
||||
srcs = cov_res.srcs
|
||||
coverage_vars = cov_res.variables
|
||||
|
||||
# Compile all tests into a package.
|
||||
tests = compile(ctx, pkg_name, srcs, deps = deps)
|
||||
|
||||
# Generate a main function which runs the tests and build that into another
|
||||
# package.
|
||||
gen_main = _gen_test_main(ctx, pkg_name, coverage_mode, coverage_vars, srcs)
|
||||
main = compile(ctx, "main", cmd_args(gen_main), pkgs = {pkg_name: tests})
|
||||
|
||||
# Link the above into a Go binary.
|
||||
(bin, runtime_files) = link(ctx, main, pkgs = {pkg_name: tests}, deps = deps)
|
||||
|
||||
run_cmd = cmd_args(bin).hidden(runtime_files)
|
||||
|
||||
# As per v1, copy in resources next to binary.
|
||||
for resource in ctx.attrs.resources:
|
||||
run_cmd.hidden(ctx.actions.copy_file(resource.short_path, resource))
|
||||
|
||||
return inject_test_run_info(
|
||||
ctx,
|
||||
ExternalRunnerTestInfo(
|
||||
type = "go",
|
||||
command = [run_cmd],
|
||||
env = ctx.attrs.env,
|
||||
labels = ctx.attrs.labels,
|
||||
contacts = ctx.attrs.contacts,
|
||||
),
|
||||
) + [DefaultInfo(default_outputs = [bin], other_outputs = [gen_main] + runtime_files)]
|
||||
135
vendor/cxx/tools/buck/prelude/go/link.bzl
vendored
Normal file
135
vendor/cxx/tools/buck/prelude/go/link.bzl
vendored
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# This source code is licensed under both the MIT license found in the
|
||||
# LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
load("@prelude//cxx:cxx_library_utility.bzl", "cxx_inherited_link_info")
|
||||
load(
|
||||
"@prelude//cxx:cxx_link_utility.bzl",
|
||||
"executable_shared_lib_arguments",
|
||||
)
|
||||
load(
|
||||
"@prelude//linking:link_info.bzl",
|
||||
"LinkStyle",
|
||||
"get_link_args",
|
||||
"unpack_link_args",
|
||||
)
|
||||
load(
|
||||
"@prelude//linking:shared_libraries.bzl",
|
||||
"SharedLibraryInfo",
|
||||
"merge_shared_libraries",
|
||||
"traverse_shared_library_info",
|
||||
)
|
||||
load(
|
||||
"@prelude//utils:utils.bzl",
|
||||
"map_idx",
|
||||
)
|
||||
load(":packages.bzl", "merge_pkgs")
|
||||
load(":toolchain.bzl", "GoToolchainInfo", "get_toolchain_cmd_args")
|
||||
|
||||
# Provider wrapping packages used for linking.
|
||||
GoPkgLinkInfo = provider(fields = [
|
||||
"pkgs", # {str.type: "artifact"}
|
||||
])
|
||||
|
||||
def get_inherited_link_pkgs(deps: ["dependency"]) -> {str.type: "artifact"}:
|
||||
return merge_pkgs([d[GoPkgLinkInfo].pkgs for d in deps if GoPkgLinkInfo in d])
|
||||
|
||||
def _process_shared_dependencies(ctx: "context", artifact: "artifact", deps: ["dependency"]):
|
||||
"""
|
||||
Provides files and linker args needed to for binaries with shared library linkage.
|
||||
- the runtime files needed to run binary linked with shared libraries
|
||||
- linker arguments for shared libraries
|
||||
"""
|
||||
if ctx.attrs.link_style != "shared":
|
||||
return ([], [])
|
||||
|
||||
shlib_info = merge_shared_libraries(
|
||||
ctx.actions,
|
||||
deps = filter(None, map_idx(SharedLibraryInfo, deps)),
|
||||
)
|
||||
shared_libs = {}
|
||||
for name, shared_lib in traverse_shared_library_info(shlib_info).items():
|
||||
shared_libs[name] = shared_lib.lib
|
||||
|
||||
extra_link_args, runtime_files, _ = executable_shared_lib_arguments(
|
||||
ctx.actions,
|
||||
ctx.attrs._go_toolchain[GoToolchainInfo].cxx_toolchain_for_linking,
|
||||
artifact,
|
||||
shared_libs,
|
||||
)
|
||||
|
||||
return (runtime_files, extra_link_args)
|
||||
|
||||
def link(ctx: "context", main: "artifact", pkgs: {str.type: "artifact"} = {}, deps: ["dependency"] = [], link_mode = None):
|
||||
go_toolchain = ctx.attrs._go_toolchain[GoToolchainInfo]
|
||||
output = ctx.actions.declare_output(ctx.label.name)
|
||||
|
||||
cmd = get_toolchain_cmd_args(go_toolchain)
|
||||
|
||||
cmd.add(go_toolchain.linker)
|
||||
|
||||
cmd.add("-o", output.as_output())
|
||||
cmd.add("-buildmode", "exe") # TODO(agallagher): support other modes
|
||||
cmd.add("-buildid=") # Setting to a static buildid helps make the binary reproducible.
|
||||
|
||||
# Add inherited Go pkgs to library search path.
|
||||
all_pkgs = merge_pkgs([pkgs, get_inherited_link_pkgs(deps)])
|
||||
pkgs_dir = ctx.actions.symlinked_dir(
|
||||
"__link_pkgs__",
|
||||
{name + path.extension: path for name, path in all_pkgs.items()},
|
||||
)
|
||||
cmd.add("-L", pkgs_dir)
|
||||
|
||||
link_style = ctx.attrs.link_style
|
||||
if link_style == None:
|
||||
link_style = "static"
|
||||
|
||||
runtime_files, extra_link_args = _process_shared_dependencies(ctx, main, deps)
|
||||
|
||||
# Gather external link args from deps.
|
||||
ext_links = get_link_args(
|
||||
cxx_inherited_link_info(ctx, deps),
|
||||
LinkStyle(link_style),
|
||||
)
|
||||
ext_link_args = cmd_args(unpack_link_args(ext_links))
|
||||
ext_link_args.add(cmd_args(extra_link_args, quote = "shell"))
|
||||
|
||||
if not link_mode:
|
||||
link_mode = "external"
|
||||
cmd.add("-linkmode", link_mode)
|
||||
|
||||
if link_mode == "external":
|
||||
# Delegate to C++ linker...
|
||||
# TODO: It feels a bit inefficient to generate a wrapper file for every
|
||||
# link. Is there some way to etract the first arg of `RunInfo`? Or maybe
|
||||
# we can generate te platform-specific stuff once and re-use?
|
||||
cxx_toolchain = go_toolchain.cxx_toolchain_for_linking
|
||||
cxx_link_cmd = cmd_args(
|
||||
[
|
||||
cxx_toolchain.linker_info.linker,
|
||||
cxx_toolchain.linker_info.linker_flags,
|
||||
go_toolchain.external_linker_flags,
|
||||
ext_link_args,
|
||||
"\"$@\"",
|
||||
],
|
||||
delimiter = " ",
|
||||
)
|
||||
linker_wrapper, _ = ctx.actions.write(
|
||||
"__{}_cxx_link_wrapper__.sh".format(ctx.label.name),
|
||||
["#!/bin/sh", cxx_link_cmd],
|
||||
allow_args = True,
|
||||
is_executable = True,
|
||||
)
|
||||
cmd.add("-extld", linker_wrapper).hidden(cxx_link_cmd)
|
||||
|
||||
if ctx.attrs.linker_flags:
|
||||
cmd.add(ctx.attrs.linker_flags)
|
||||
|
||||
cmd.add(main)
|
||||
|
||||
ctx.actions.run(cmd, category = "go_link")
|
||||
|
||||
return (output, runtime_files)
|
||||
30
vendor/cxx/tools/buck/prelude/go/packages.bzl
vendored
Normal file
30
vendor/cxx/tools/buck/prelude/go/packages.bzl
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# This source code is licensed under both the MIT license found in the
|
||||
# LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
load("@prelude//utils:utils.bzl", "value_or")
|
||||
|
||||
def go_attr_pkg_name(ctx: "context") -> str.type:
|
||||
"""
|
||||
Return the Go package name for the given context corresponing to a rule.
|
||||
"""
|
||||
return value_or(ctx.attrs.package_name, ctx.label.package)
|
||||
|
||||
def merge_pkgs(pkgss: [{str.type: "artifact"}]) -> {str.type: "artifact"}:
|
||||
"""
|
||||
Merge mappings of packages into a single mapping, throwing an error on
|
||||
conflicts.
|
||||
"""
|
||||
|
||||
all_pkgs = {}
|
||||
|
||||
for pkgs in pkgss:
|
||||
for name, path in pkgs.items():
|
||||
if name in pkgs and pkgs[name] != path:
|
||||
fail("conflict for package {!r}: {} and {}".format(name, path, all_pkgs[name]))
|
||||
all_pkgs[name] = path
|
||||
|
||||
return all_pkgs
|
||||
43
vendor/cxx/tools/buck/prelude/go/toolchain.bzl
vendored
Normal file
43
vendor/cxx/tools/buck/prelude/go/toolchain.bzl
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# This source code is licensed under both the MIT license found in the
|
||||
# LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
GoToolchainInfo = provider(fields = [
|
||||
"assembler",
|
||||
"cgo",
|
||||
"cgo_wrapper",
|
||||
"compile_wrapper",
|
||||
"compiler",
|
||||
"cover",
|
||||
"cover_srcs",
|
||||
"cxx_toolchain_for_linking",
|
||||
"env_go_arch",
|
||||
"env_go_os",
|
||||
"env_go_root",
|
||||
"external_linker_flags",
|
||||
"filter_srcs",
|
||||
"go",
|
||||
"linker",
|
||||
"packer",
|
||||
"tags",
|
||||
])
|
||||
|
||||
def get_toolchain_cmd_args(toolchain: "GoToolchainInfo", go_root = True) -> "cmd_args":
|
||||
cmd = cmd_args("env")
|
||||
if toolchain.env_go_arch != None:
|
||||
cmd.add("GOARCH={}".format(toolchain.env_go_arch))
|
||||
if toolchain.env_go_os != None:
|
||||
cmd.add("GOOS={}".format(toolchain.env_go_os))
|
||||
if go_root and toolchain.env_go_root != None:
|
||||
cmd.add(cmd_args(toolchain.env_go_root, format = "GOROOT={}"))
|
||||
|
||||
# CGO is enabled by default for native compilation, but we need to set it
|
||||
# explicitly for cross-builds:
|
||||
# https://go-review.googlesource.com/c/go/+/12603/2/src/cmd/cgo/doc.go
|
||||
if toolchain.cgo != None:
|
||||
cmd.add("CGO_ENABLED=1")
|
||||
|
||||
return cmd
|
||||
35
vendor/cxx/tools/buck/prelude/go/tools/TARGETS.v2
vendored
Normal file
35
vendor/cxx/tools/buck/prelude/go/tools/TARGETS.v2
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
prelude = native
|
||||
|
||||
prelude.python_bootstrap_binary(
|
||||
name = "compile_wrapper",
|
||||
main = "compile_wrapper.py",
|
||||
visibility = ["PUBLIC"],
|
||||
)
|
||||
|
||||
prelude.python_bootstrap_binary(
|
||||
name = "cover_srcs",
|
||||
main = "cover_srcs.py",
|
||||
visibility = ["PUBLIC"],
|
||||
)
|
||||
|
||||
prelude.python_bootstrap_binary(
|
||||
name = "filter_srcs",
|
||||
main = "filter_srcs.py",
|
||||
visibility = ["PUBLIC"],
|
||||
)
|
||||
|
||||
prelude.python_bootstrap_binary(
|
||||
name = "cgo_wrapper",
|
||||
main = "cgo_wrapper.py",
|
||||
visibility = ["PUBLIC"],
|
||||
)
|
||||
|
||||
prelude.go_binary(
|
||||
name = "testmaingen",
|
||||
srcs = [
|
||||
"testmaingen.go",
|
||||
],
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
)
|
||||
44
vendor/cxx/tools/buck/prelude/go/tools/cgo_wrapper.py
vendored
Normal file
44
vendor/cxx/tools/buck/prelude/go/tools/cgo_wrapper.py
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# This source code is licensed under both the MIT license found in the
|
||||
# LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
# pyre-unsafe
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(fromfile_prefix_chars="@")
|
||||
parser.add_argument("--cgo", action="append", default=[])
|
||||
parser.add_argument("--output", required=True, type=Path)
|
||||
parser.add_argument("--cpp", action="append", default=[])
|
||||
parser.add_argument("srcs", type=Path, nargs="*")
|
||||
args = parser.parse_args(argv[1:])
|
||||
|
||||
output = args.output.resolve(strict=False)
|
||||
os.makedirs(output, exist_ok=True)
|
||||
|
||||
os.environ["CC"] = args.cpp[0]
|
||||
|
||||
cmd = []
|
||||
cmd.extend(args.cgo)
|
||||
# cmd.append("-importpath={}")
|
||||
# cmd.append("-srcdir={}")
|
||||
cmd.append(f"-objdir={output}")
|
||||
# cmd.append(cgoCompilerFlags)
|
||||
cmd.append("--")
|
||||
# cmd.append(cxxCompilerFlags)
|
||||
cmd.extend(args.cpp[1:])
|
||||
cmd.extend(args.srcs)
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
sys.exit(main(sys.argv))
|
||||
94
vendor/cxx/tools/buck/prelude/go/tools/compile_wrapper.py
vendored
Normal file
94
vendor/cxx/tools/buck/prelude/go/tools/compile_wrapper.py
vendored
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# This source code is licensed under both the MIT license found in the
|
||||
# LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
"""
|
||||
Compile the given Go sources into a Go package.
|
||||
|
||||
Example:
|
||||
|
||||
$ ./compile_wrapper.py \
|
||||
--compiler compile \
|
||||
--assember assemble \
|
||||
--output srcs.txt src/dir/
|
||||
|
||||
"""
|
||||
|
||||
# pyre-unsafe
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
|
||||
def _compile(compile_prefix: List[str], output: Path, srcs: List[Path]):
|
||||
cmd = []
|
||||
cmd.extend(compile_prefix)
|
||||
cmd.append("-trimpath={}".format(os.getcwd()))
|
||||
cmd.append("-o")
|
||||
cmd.append(output)
|
||||
cmd.extend(srcs)
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
def _pack(pack_prefix: List[str], output: Path, items: List[Path]):
|
||||
cmd = []
|
||||
cmd.extend(pack_prefix)
|
||||
cmd.append("r")
|
||||
cmd.append(output)
|
||||
cmd.extend(items)
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(fromfile_prefix_chars="@")
|
||||
parser.add_argument("--compiler", action="append", default=[])
|
||||
parser.add_argument("--assembler", action="append", default=[])
|
||||
parser.add_argument("--packer", action="append", default=[])
|
||||
parser.add_argument("--output", required=True, type=Path)
|
||||
parser.add_argument("srcs", type=Path, nargs="*")
|
||||
args = parser.parse_args(argv[1:])
|
||||
|
||||
# If there's no srcs, just leave an empty file.
|
||||
if not args.srcs:
|
||||
args.output.touch()
|
||||
return
|
||||
|
||||
go_files = [s for s in args.srcs if s.suffix == ".go"]
|
||||
s_files = [s for s in args.srcs if s.suffix == ".s"]
|
||||
o_files = [s for s in args.srcs if s.suffix == ".o"]
|
||||
|
||||
if go_files:
|
||||
compile_prefix = []
|
||||
compile_prefix.extend(args.compiler)
|
||||
|
||||
# If we have assembly files, generate the symabi file to compile against.
|
||||
if s_files:
|
||||
symabis = args.output.with_suffix(".symabis")
|
||||
_compile(args.assembler + ["-gensymabis"], symabis, s_files)
|
||||
compile_prefix.extend(["-symabis", symabis])
|
||||
|
||||
_compile(compile_prefix, args.output, go_files)
|
||||
|
||||
else:
|
||||
args.output.touch()
|
||||
|
||||
# If there are assembly files, assemble them to an object and add into the
|
||||
# output archive.
|
||||
if s_files:
|
||||
s_object = args.output.with_suffix(".o")
|
||||
_compile(args.assembler, s_object, s_files)
|
||||
o_files.append(s_object)
|
||||
|
||||
if o_files:
|
||||
_pack(args.packer, args.output, o_files)
|
||||
|
||||
|
||||
sys.exit(main(sys.argv))
|
||||
81
vendor/cxx/tools/buck/prelude/go/tools/cover_srcs.py
vendored
Normal file
81
vendor/cxx/tools/buck/prelude/go/tools/cover_srcs.py
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# This source code is licensed under both the MIT license found in the
|
||||
# LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
"""
|
||||
Run `go cover` on non-`_test.go` input sources.
|
||||
"""
|
||||
|
||||
# pyre-unsafe
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def _var(pkg_name, src):
|
||||
return "Var_" + hashlib.md5(f"{pkg_name}::{src}".encode("utf-8")).hexdigest()
|
||||
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(fromfile_prefix_chars="@")
|
||||
parser.add_argument("--cover", type=Path, required=True)
|
||||
parser.add_argument("--pkg-name", type=str, required=True)
|
||||
parser.add_argument("--coverage-mode", type=str, required=True)
|
||||
parser.add_argument("--covered-srcs-dir", type=Path, required=True)
|
||||
parser.add_argument("--out-srcs-argsfile", type=Path, required=True)
|
||||
parser.add_argument("--coverage-var-argsfile", type=Path, required=True)
|
||||
parser.add_argument("srcs", nargs="*", type=Path)
|
||||
args = parser.parse_args(argv[1:])
|
||||
|
||||
out_srcs = []
|
||||
coverage_vars = {}
|
||||
|
||||
args.covered_srcs_dir.mkdir(parents=True)
|
||||
|
||||
for src in args.srcs:
|
||||
if src.name.endswith("_test.go"):
|
||||
out_srcs.append(src)
|
||||
else:
|
||||
var = _var(args.pkg_name, src)
|
||||
covered_src = args.covered_srcs_dir / src
|
||||
covered_src.parent.mkdir(parents=True, exist_ok=True)
|
||||
subprocess.check_call(
|
||||
[
|
||||
args.cover,
|
||||
"-mode",
|
||||
args.coverage_mode,
|
||||
"-var",
|
||||
var,
|
||||
"-o",
|
||||
covered_src,
|
||||
src,
|
||||
]
|
||||
)
|
||||
# we need just the source name for the --cover-pkgs argument
|
||||
coverage_vars[var] = src.name
|
||||
out_srcs.append(covered_src)
|
||||
|
||||
with open(args.out_srcs_argsfile, mode="w") as f:
|
||||
for src in out_srcs:
|
||||
print(src, file=f)
|
||||
|
||||
with open(args.coverage_var_argsfile, mode="w") as f:
|
||||
if coverage_vars:
|
||||
print("--cover-pkgs", file=f)
|
||||
print(
|
||||
"{}:{}".format(
|
||||
args.pkg_name,
|
||||
",".join([f"{var}={name}" for var, name in coverage_vars.items()]),
|
||||
),
|
||||
file=f,
|
||||
)
|
||||
|
||||
|
||||
sys.exit(main(sys.argv))
|
||||
87
vendor/cxx/tools/buck/prelude/go/tools/filter_srcs.py
vendored
Normal file
87
vendor/cxx/tools/buck/prelude/go/tools/filter_srcs.py
vendored
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
#
|
||||
# This source code is licensed under both the MIT license found in the
|
||||
# LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
# License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
# of this source tree.
|
||||
|
||||
"""
|
||||
Run on a directory of Go source files and print out a list of srcs that should
|
||||
be compiled.
|
||||
|
||||
Example:
|
||||
|
||||
$ ./filter_srcs.py --output srcs.txt src/dir/
|
||||
|
||||
"""
|
||||
|
||||
# pyre-unsafe
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--go", default="go", type=Path)
|
||||
parser.add_argument("--tests", action="store_true")
|
||||
parser.add_argument("--tags", default="")
|
||||
parser.add_argument("--output", type=argparse.FileType("w"), default=sys.stdout)
|
||||
parser.add_argument("srcdir", type=Path)
|
||||
args = parser.parse_args(argv[1:])
|
||||
|
||||
# Find all source sub-dirs, which we'll need to run `go list` from.
|
||||
roots = set()
|
||||
for root, _dirs, _files in os.walk(args.srcdir):
|
||||
roots.add(root)
|
||||
|
||||
# Run `go list` on all source dirs to filter input sources by build pragmas.
|
||||
for root in roots:
|
||||
out = subprocess.check_output(
|
||||
[
|
||||
"env",
|
||||
"-i",
|
||||
"GOARCH={}".format(os.environ.get("GOARCH", "")),
|
||||
"GOOS={}".format(os.environ.get("GOOS", "")),
|
||||
"CGO_ENABLED={}".format(os.environ.get("CGO_ENABLED", "0")),
|
||||
"GO111MODULE=off",
|
||||
"GOCACHE=/tmp",
|
||||
args.go.resolve(),
|
||||
"list",
|
||||
"-e",
|
||||
"-json",
|
||||
"-tags",
|
||||
args.tags,
|
||||
".",
|
||||
],
|
||||
cwd=root,
|
||||
).decode("utf-8")
|
||||
|
||||
# Parse JSON output and print out sources.
|
||||
idx = 0
|
||||
decoder = json.JSONDecoder()
|
||||
while idx < len(out) - 1:
|
||||
# The raw_decode method fails if there are any leading spaces, e.g. " {}" fails
|
||||
# so manually trim the prefix of the string
|
||||
if out[idx].isspace():
|
||||
idx += 1
|
||||
continue
|
||||
|
||||
obj, idx = decoder.raw_decode(out, idx)
|
||||
if args.tests:
|
||||
types = ["GoFiles", "TestGoFiles", "XTestGoFiles"]
|
||||
else:
|
||||
types = ["GoFiles", "SFiles"]
|
||||
for typ in types:
|
||||
for src in obj.get(typ, []):
|
||||
src = Path(obj["Dir"]) / src
|
||||
src = src.resolve().relative_to(os.getcwd())
|
||||
print(src, file=args.output)
|
||||
|
||||
|
||||
sys.exit(main(sys.argv))
|
||||
531
vendor/cxx/tools/buck/prelude/go/tools/testmaingen.go
vendored
Normal file
531
vendor/cxx/tools/buck/prelude/go/tools/testmaingen.go
vendored
Normal file
|
|
@ -0,0 +1,531 @@
|
|||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under both the MIT license found in the
|
||||
* LICENSE-MIT file in the root directory of this source tree and the Apache
|
||||
* License, Version 2.0 found in the LICENSE-APACHE file in the root directory
|
||||
* of this source tree.
|
||||
*/
|
||||
|
||||
// Generates testmain.go files from a group of test files.
|
||||
//
|
||||
// Regular go tests (ones run with `go test`) don't actually define a main
|
||||
// package. Moreover, Go's reflection does not have the ability to inspect
|
||||
// packages (e.g. list functions). This script generates a main.go that
|
||||
// runs some set of tests passed in on the CLI. The code liberally borrows from
|
||||
// the `go test` implementation at https://github.com/golang/go/blob/master/src/cmd/go/test.go
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/doc"
|
||||
"go/parser"
|
||||
"go/scanner"
|
||||
"go/token"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// A map of: pkg -> [var name -> file name]
|
||||
type coverPkgFlag map[string]map[string]string
|
||||
|
||||
func (c coverPkgFlag) String() string {
|
||||
var buffer bytes.Buffer
|
||||
for k, vs := range c {
|
||||
if len(vs) > 0 {
|
||||
buffer.WriteString(k)
|
||||
buffer.WriteString(":")
|
||||
|
||||
first := true
|
||||
for f, v := range vs {
|
||||
buffer.WriteString(f)
|
||||
buffer.WriteString("=")
|
||||
buffer.WriteString(v)
|
||||
if !first {
|
||||
buffer.WriteString(",")
|
||||
}
|
||||
first = false
|
||||
}
|
||||
|
||||
buffer.WriteString(";")
|
||||
}
|
||||
}
|
||||
return buffer.String()
|
||||
}
|
||||
|
||||
func (c coverPkgFlag) Set(value string) error {
|
||||
for _, path := range strings.Split(value, ";") {
|
||||
pkgAndFiles := strings.Split(path, ":")
|
||||
if len(pkgAndFiles) != 2 {
|
||||
return errors.New("Bad format: expected path:...;...")
|
||||
}
|
||||
pkg := pkgAndFiles[0]
|
||||
for _, varAndFile := range strings.Split(pkgAndFiles[1], ",") {
|
||||
varAndFile := strings.Split(varAndFile, "=")
|
||||
if len(varAndFile) != 2 {
|
||||
return errors.New("Bad format: expected path:var1=file1,var2=file2,...")
|
||||
}
|
||||
|
||||
if c[pkg] == nil {
|
||||
c[pkg] = make(map[string]string)
|
||||
}
|
||||
|
||||
c[pkg][varAndFile[0]] = varAndFile[1]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var testCoverMode string
|
||||
var coverPkgs = make(coverPkgFlag)
|
||||
var pkgImportPath = flag.String("import-path", "test", "The import path in the test file")
|
||||
var outputFile = flag.String("output", "", "The path to the output file. Default to stdout.")
|
||||
|
||||
var cwd, _ = os.Getwd()
|
||||
var testCover bool
|
||||
var testCoverPaths []string
|
||||
|
||||
// Resolve argsfiles in args (e.g. `@file.txt`).
|
||||
func loadArgs(args []string) []string {
|
||||
newArgs := make([]string, 0, 0)
|
||||
for _, arg := range args {
|
||||
if !strings.HasPrefix(arg, "@") {
|
||||
newArgs = append(newArgs, arg)
|
||||
} else {
|
||||
file, _ := os.Open(arg[1:])
|
||||
defer file.Close()
|
||||
scanner := bufio.NewScanner(file)
|
||||
for scanner.Scan() {
|
||||
newArgs = append(newArgs, scanner.Text())
|
||||
}
|
||||
}
|
||||
}
|
||||
return newArgs
|
||||
}
|
||||
|
||||
func main() {
|
||||
os.Args = loadArgs(os.Args)
|
||||
flag.Var(coverPkgs, "cover-pkgs", "List of packages & coverage variables to gather coverage info on, in the form of IMPORT-PATH1:var1=file1,var2=file2,var3=file3;IMPORT-PATH2:...")
|
||||
flag.StringVar(&testCoverMode, "cover-mode", "", "Cover mode (see `go tool cover`)")
|
||||
flag.Parse()
|
||||
|
||||
testFuncs, err := loadTestFuncsFromFiles(*pkgImportPath, flag.Args())
|
||||
if err != nil {
|
||||
log.Fatalln("Could not read test files:", err)
|
||||
}
|
||||
|
||||
for importPath, vars := range coverPkgs {
|
||||
cover := coverInfo{&Package{importPath}, make(map[string]*CoverVar)}
|
||||
for v, f := range vars {
|
||||
cover.Vars[f] = &CoverVar{File: filepath.Join(importPath, f), Var: v}
|
||||
}
|
||||
testFuncs.Cover = append(testFuncs.Cover, cover)
|
||||
testCoverPaths = append(testCoverPaths, importPath)
|
||||
}
|
||||
testCover = testCoverMode != ""
|
||||
|
||||
out := os.Stdout
|
||||
if *outputFile != "" {
|
||||
out, err = os.Create(*outputFile)
|
||||
if err != nil {
|
||||
log.Fatalln("Could not write test main:", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := testmainTmpl.Execute(out, testFuncs); err != nil {
|
||||
log.Fatalln("Failed to generate main file:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func loadTestFuncsFromFiles(packageImportPath string, files []string) (*testFuncs, error) {
|
||||
t := &testFuncs{
|
||||
Package: &Package{
|
||||
ImportPath: packageImportPath,
|
||||
},
|
||||
}
|
||||
for _, filename := range files {
|
||||
if err := t.load(filename, "_test", &t.ImportTest, &t.NeedTest); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
// Most of the code below is a direct copy from the 'go test' command, but
|
||||
// adapted to support multiple versions of the go stdlib. This was last
|
||||
// updated for the changes in go1.8. The source for the 'go test' generator
|
||||
// for go1.8 can be found here:
|
||||
// https://github.com/golang/go/blob/release-branch.go1.8/src/cmd/go/test.go
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
// This is a fake version of the actual Package type, since we don't really need all
|
||||
// ~300 fields of it.
|
||||
type Package struct {
|
||||
ImportPath string `json:",omitempty"` // import path of package in dir
|
||||
}
|
||||
|
||||
// isTestFunc tells whether fn has the type of a testing function. arg
|
||||
// specifies the parameter type we look for: B, M or T.
|
||||
func isTestFunc(fn *ast.FuncDecl, arg string) bool {
|
||||
if fn.Type.Results != nil && len(fn.Type.Results.List) > 0 ||
|
||||
fn.Type.Params.List == nil ||
|
||||
len(fn.Type.Params.List) != 1 ||
|
||||
len(fn.Type.Params.List[0].Names) > 1 {
|
||||
return false
|
||||
}
|
||||
ptr, ok := fn.Type.Params.List[0].Type.(*ast.StarExpr)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
// We can't easily check that the type is *testing.M
|
||||
// because we don't know how testing has been imported,
|
||||
// but at least check that it's *M or *something.M.
|
||||
// Same applies for B and T.
|
||||
if name, ok := ptr.X.(*ast.Ident); ok && name.Name == arg {
|
||||
return true
|
||||
}
|
||||
if sel, ok := ptr.X.(*ast.SelectorExpr); ok && sel.Sel.Name == arg {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// isTest tells whether name looks like a test (or benchmark, according to prefix).
|
||||
// It is a Test (say) if there is a character after Test that is not a lower-case letter.
|
||||
// We don't want TesticularCancer.
|
||||
func isTest(name, prefix string) bool {
|
||||
if !strings.HasPrefix(name, prefix) {
|
||||
return false
|
||||
}
|
||||
if len(name) == len(prefix) { // "Test" is ok
|
||||
return true
|
||||
}
|
||||
rune, _ := utf8.DecodeRuneInString(name[len(prefix):])
|
||||
return !unicode.IsLower(rune)
|
||||
}
|
||||
|
||||
// shortPath returns an absolute or relative name for path, whatever is shorter.
|
||||
func shortPath(path string) string {
|
||||
if rel, err := filepath.Rel(cwd, path); err == nil && len(rel) < len(path) {
|
||||
return rel
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
// expandScanner expands a scanner.List error into all the errors in the list.
|
||||
// The default Error method only shows the first error.
|
||||
func expandScanner(err error) error {
|
||||
// Look for parser errors.
|
||||
if err, ok := err.(scanner.ErrorList); ok {
|
||||
// Prepare error with \n before each message.
|
||||
// When printed in something like context: %v
|
||||
// this will put the leading file positions each on
|
||||
// its own line. It will also show all the errors
|
||||
// instead of just the first, as err.Error does.
|
||||
var buf bytes.Buffer
|
||||
for _, e := range err {
|
||||
e.Pos.Filename = shortPath(e.Pos.Filename)
|
||||
buf.WriteString("\n")
|
||||
buf.WriteString(e.Error())
|
||||
}
|
||||
return errors.New(buf.String())
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// CoverVar holds the name of the generated coverage variables
|
||||
// targeting the named file.
|
||||
type CoverVar struct {
|
||||
File string // local file name
|
||||
Var string // name of count struct
|
||||
}
|
||||
|
||||
type coverInfo struct {
|
||||
Package *Package
|
||||
Vars map[string]*CoverVar
|
||||
}
|
||||
|
||||
type testFuncs struct {
|
||||
Tests []testFunc
|
||||
Benchmarks []testFunc
|
||||
Examples []testFunc
|
||||
TestMain *testFunc
|
||||
Package *Package
|
||||
ImportTest bool
|
||||
NeedTest bool
|
||||
ImportXtest bool
|
||||
NeedXtest bool
|
||||
Cover []coverInfo
|
||||
}
|
||||
|
||||
func (t *testFuncs) CoverMode() string {
|
||||
return testCoverMode
|
||||
}
|
||||
|
||||
func (t *testFuncs) CoverEnabled() bool {
|
||||
return testCover
|
||||
}
|
||||
|
||||
func (t *testFuncs) ReleaseTag(want string) bool {
|
||||
for _, r := range build.Default.ReleaseTags {
|
||||
if want == r {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ImportPath returns the import path of the package being tested, if it is within GOPATH.
|
||||
// This is printed by the testing package when running benchmarks.
|
||||
func (t *testFuncs) ImportPath() string {
|
||||
pkg := t.Package.ImportPath
|
||||
if strings.HasPrefix(pkg, "_/") {
|
||||
return ""
|
||||
}
|
||||
if pkg == "command-line-arguments" {
|
||||
return ""
|
||||
}
|
||||
return pkg
|
||||
}
|
||||
|
||||
// Covered returns a string describing which packages are being tested for coverage.
|
||||
// If the covered package is the same as the tested package, it returns the empty string.
|
||||
// Otherwise it is a comma-separated human-readable list of packages beginning with
|
||||
// " in", ready for use in the coverage message.
|
||||
func (t *testFuncs) Covered() string {
|
||||
if testCoverPaths == nil {
|
||||
return ""
|
||||
}
|
||||
return " in " + strings.Join(testCoverPaths, ", ")
|
||||
}
|
||||
|
||||
type testFunc struct {
|
||||
Package string // imported package name (_test or _xtest)
|
||||
Name string // function name
|
||||
Output string // output, for examples
|
||||
Unordered bool // output is allowed to be unordered.
|
||||
}
|
||||
|
||||
var testFileSet = token.NewFileSet()
|
||||
|
||||
func (t *testFuncs) load(filename, pkg string, doImport, seen *bool) error {
|
||||
f, err := parser.ParseFile(testFileSet, filename, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
return expandScanner(err)
|
||||
}
|
||||
for _, d := range f.Decls {
|
||||
n, ok := d.(*ast.FuncDecl)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if n.Recv != nil {
|
||||
continue
|
||||
}
|
||||
name := n.Name.String()
|
||||
switch {
|
||||
case name == "TestMain" && isTestFunc(n, "M"):
|
||||
if t.TestMain != nil {
|
||||
return errors.New("multiple definitions of TestMain")
|
||||
}
|
||||
t.TestMain = &testFunc{pkg, name, "", false}
|
||||
*doImport, *seen = true, true
|
||||
case isTest(name, "Test") && isTestFunc(n, "T"):
|
||||
t.Tests = append(t.Tests, testFunc{pkg, name, "", false})
|
||||
*doImport, *seen = true, true
|
||||
case isTest(name, "Benchmark"):
|
||||
err := checkTestFunc(n, "B")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.Benchmarks = append(t.Benchmarks, testFunc{pkg, name, "", false})
|
||||
*doImport, *seen = true, true
|
||||
}
|
||||
}
|
||||
ex := doc.Examples(f)
|
||||
sort.Sort(byOrder(ex))
|
||||
for _, e := range ex {
|
||||
*doImport = true // import test file whether executed or not
|
||||
if e.Output == "" && !e.EmptyOutput {
|
||||
// Don't run examples with no output.
|
||||
continue
|
||||
}
|
||||
|
||||
// Go 1.7 and beyond has support for unordered test output on examples.
|
||||
// We can use reflection to see if the Unordered field is there. This
|
||||
// can be removed when go 1.6 is not supported by buck.
|
||||
unordered := false
|
||||
v := reflect.Indirect(reflect.ValueOf(e))
|
||||
if f := v.FieldByName("Unordered"); f.IsValid() {
|
||||
unordered = f.Bool()
|
||||
}
|
||||
|
||||
t.Examples = append(t.Examples, testFunc{pkg, "Example" + e.Name, e.Output, unordered})
|
||||
*seen = true
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkTestFunc(fn *ast.FuncDecl, arg string) error {
|
||||
if !isTestFunc(fn, arg) {
|
||||
name := fn.Name.String()
|
||||
pos := testFileSet.Position(fn.Pos())
|
||||
return fmt.Errorf("%s: wrong signature for %s, must be: func %s(%s *testing.%s)", pos, name, name, strings.ToLower(arg), arg)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type byOrder []*doc.Example
|
||||
|
||||
func (x byOrder) Len() int { return len(x) }
|
||||
func (x byOrder) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
func (x byOrder) Less(i, j int) bool { return x[i].Order < x[j].Order }
|
||||
|
||||
var testmainTmpl = template.Must(template.New("main").Parse(`
|
||||
package main
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"testing"
|
||||
{{if .ReleaseTag "go1.8"}}
|
||||
internalTestDeps "testing/internal/testdeps"
|
||||
{{end}}
|
||||
{{if .ImportTest}}
|
||||
{{if .NeedTest}}_test{{else}}_{{end}} {{.Package.ImportPath | printf "%q"}}
|
||||
{{end}}
|
||||
{{if .ImportXtest}}
|
||||
{{if .NeedXtest}}_xtest{{else}}_{{end}} {{.Package.ImportPath | printf "%s_test" | printf "%q"}}
|
||||
{{end}}
|
||||
{{range $i, $p := .Cover}}
|
||||
_cover{{$i}} {{$p.Package.ImportPath | printf "%q"}}
|
||||
{{end}}
|
||||
)
|
||||
|
||||
var tests = []testing.InternalTest{
|
||||
{{range .Tests}}
|
||||
{"{{.Name}}", {{.Package}}.{{.Name}}},
|
||||
{{end}}
|
||||
}
|
||||
var benchmarks = []testing.InternalBenchmark{
|
||||
{{range .Benchmarks}}
|
||||
{"{{.Name}}", {{.Package}}.{{.Name}}},
|
||||
{{end}}
|
||||
}
|
||||
{{if .ReleaseTag "go1.18"}}
|
||||
var fuzzTargets = []testing.InternalFuzzTarget{
|
||||
}
|
||||
{{end}}
|
||||
var examples = []testing.InternalExample{
|
||||
{{range .Examples}}
|
||||
{"{{.Name}}", {{.Package}}.{{.Name}}, {{.Output | printf "%q"}}{{if $.ReleaseTag "go1.7"}}, {{.Unordered}}{{end}}},
|
||||
{{end}}
|
||||
}
|
||||
|
||||
var matchPat string
|
||||
var matchRe *regexp.Regexp
|
||||
|
||||
func matchString(pat, str string) (result bool, err error) {
|
||||
if matchRe == nil || matchPat != pat {
|
||||
matchPat = pat
|
||||
matchRe, err = regexp.Compile(matchPat)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return matchRe.MatchString(str), nil
|
||||
}
|
||||
|
||||
{{if .CoverEnabled}}
|
||||
// Only updated by init functions, so no need for atomicity.
|
||||
var (
|
||||
coverCounters = make(map[string][]uint32)
|
||||
coverBlocks = make(map[string][]testing.CoverBlock)
|
||||
)
|
||||
func init() {
|
||||
{{range $i, $p := .Cover}}
|
||||
{{range $file, $cover := $p.Vars}}
|
||||
coverRegisterFile({{printf "%q" $cover.File}}, _cover{{$i}}.{{$cover.Var}}.Count[:], _cover{{$i}}.{{$cover.Var}}.Pos[:], _cover{{$i}}.{{$cover.Var}}.NumStmt[:])
|
||||
{{end}}
|
||||
{{end}}
|
||||
}
|
||||
func coverRegisterFile(fileName string, counter []uint32, pos []uint32, numStmts []uint16) {
|
||||
if 3*len(counter) != len(pos) || len(counter) != len(numStmts) {
|
||||
panic("coverage: mismatched sizes")
|
||||
}
|
||||
if coverCounters[fileName] != nil {
|
||||
// Already registered.
|
||||
return
|
||||
}
|
||||
coverCounters[fileName] = counter
|
||||
block := make([]testing.CoverBlock, len(counter))
|
||||
for i := range counter {
|
||||
block[i] = testing.CoverBlock{
|
||||
Line0: pos[3*i+0],
|
||||
Col0: uint16(pos[3*i+2]),
|
||||
Line1: pos[3*i+1],
|
||||
Col1: uint16(pos[3*i+2]>>16),
|
||||
Stmts: numStmts[i],
|
||||
}
|
||||
}
|
||||
coverBlocks[fileName] = block
|
||||
}
|
||||
{{end}}
|
||||
func main() {
|
||||
// Buck ensures that resources defined on the test targets live in the same
|
||||
// directory as the binary. We change the working directory to this
|
||||
// directory to make sure that tests can read test fixtures relative to the
|
||||
// current working directory. This matches behavior with "go test" from the
|
||||
// test author perspective.
|
||||
execPath, err := os.Executable()
|
||||
if err != nil {
|
||||
os.Stderr.WriteString("Unable to get path to test binary executable.")
|
||||
os.Exit(1)
|
||||
}
|
||||
execDir := filepath.Dir(execPath)
|
||||
err = os.Chdir(execDir)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to change directory to %s.", execDir)
|
||||
os.Exit(1)
|
||||
}
|
||||
{{if .CoverEnabled}}
|
||||
testing.RegisterCover(testing.Cover{
|
||||
Mode: {{printf "%q" .CoverMode}},
|
||||
Counters: coverCounters,
|
||||
Blocks: coverBlocks,
|
||||
CoveredPackages: {{printf "%q" .Covered}},
|
||||
})
|
||||
{{end}}
|
||||
{{if .ReleaseTag "go1.18"}}
|
||||
m := testing.MainStart(internalTestDeps.TestDeps{}, tests, benchmarks, fuzzTargets, examples)
|
||||
{{else if .ReleaseTag "go1.8"}}
|
||||
m := testing.MainStart(internalTestDeps.TestDeps{}, tests, benchmarks, examples)
|
||||
{{else}}
|
||||
m := testing.MainStart(matchString, tests, benchmarks, examples)
|
||||
{{end}}
|
||||
{{with .TestMain}}
|
||||
{{.Package}}.{{.Name}}(m)
|
||||
{{else}}
|
||||
os.Exit(m.Run())
|
||||
{{end}}
|
||||
}
|
||||
`))
|
||||
Loading…
Add table
Add a link
Reference in a new issue