Skip to content

Commit

Permalink
Support -race flag
Browse files Browse the repository at this point in the history
Summary: Enabling [Go race detector](https://go.dev/doc/articles/race_detector)

Reviewed By: abulimov

Differential Revision: D53866218

fbshipit-source-id: 634df3c5aef13c5710a2bab18c962dcca337314f
  • Loading branch information
podtserkovskiy authored and facebook-github-bot committed Feb 20, 2024
1 parent 35f3607 commit eb9ccb3
Show file tree
Hide file tree
Showing 13 changed files with 108 additions and 14 deletions.
8 changes: 8 additions & 0 deletions prelude/decls/go_common.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,13 @@ def _cgo_enabled_arg():
"""),
}

def _race_arg():
return {
"race": attrs.bool(default = False, doc = """
If true, enable data race detection.
"""),
}

go_common = struct(
deps_arg = _deps_arg,
srcs_arg = _srcs_arg,
Expand All @@ -145,4 +152,5 @@ go_common = struct(
external_linker_flags_arg = _external_linker_flags_arg,
embedcfg_arg = _embedcfg_arg,
cgo_enabled_arg = _cgo_enabled_arg,
race_arg = _race_arg,
)
3 changes: 3 additions & 0 deletions prelude/decls/go_rules.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ go_binary = prelude_rule(
go_common.external_linker_flags_arg() |
go_common.embedcfg_arg() |
go_common.cgo_enabled_arg() |
go_common.race_arg() |
{
"resources": attrs.list(attrs.source(), default = [], doc = """
Static files to be symlinked into the working directory of the test. You can access these in your
Expand Down Expand Up @@ -270,6 +271,7 @@ go_exported_library = prelude_rule(
go_common.linker_flags_arg() |
go_common.external_linker_flags_arg() |
go_common.cgo_enabled_arg() |
go_common.race_arg() |
{
"resources": attrs.list(attrs.source(), default = [], doc = """
Static files to be symlinked into the working directory of the test. You can access these in your
Expand Down Expand Up @@ -420,6 +422,7 @@ go_test = prelude_rule(
go_common.external_linker_flags_arg() |
go_common.embedcfg_arg() |
go_common.cgo_enabled_arg() |
go_common.race_arg() |
{
"resources": attrs.list(attrs.source(), default = [], doc = """
Static files that are symlinked into the working directory of the
Expand Down
11 changes: 8 additions & 3 deletions prelude/go/cgo_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ def _cgo(

return go_srcs, c_headers, c_srcs

def _compile_with_coverage(ctx: AnalysisContext, pkg_name: str, srcs: cmd_args, coverage_mode: GoCoverageMode, shared: bool = False) -> (Artifact, cmd_args):
def _compile_with_coverage(ctx: AnalysisContext, pkg_name: str, srcs: cmd_args, coverage_mode: GoCoverageMode, shared: bool, race: bool) -> (Artifact, cmd_args):
cov_res = cover_srcs(ctx, pkg_name, coverage_mode, srcs, shared)
srcs = cov_res.srcs
coverage_vars = cov_res.variables
Expand All @@ -168,6 +168,7 @@ def _compile_with_coverage(ctx: AnalysisContext, pkg_name: str, srcs: cmd_args,
deps = ctx.attrs.deps + ctx.attrs.exported_deps,
coverage_mode = coverage_mode,
shared = shared,
race = race,
)
return (coverage_pkg, coverage_vars)

Expand Down Expand Up @@ -237,15 +238,19 @@ def cgo_library_impl(ctx: AnalysisContext) -> list[Provider]:
if ctx.attrs.go_srcs:
all_srcs.add(get_filtered_srcs(ctx, ctx.attrs.go_srcs))

shared = ctx.attrs._compile_shared
race = ctx.attrs._race

# Build Go library.
compiled_pkg = compile(
ctx,
pkg_name,
all_srcs,
deps = ctx.attrs.deps + ctx.attrs.exported_deps,
shared = ctx.attrs._compile_shared,
shared = shared,
race = race,
)
pkg_with_coverage = {mode: _compile_with_coverage(ctx, pkg_name, all_srcs, mode) for mode in GoCoverageMode}
pkg_with_coverage = {mode: _compile_with_coverage(ctx, pkg_name, all_srcs, mode, shared, race = race) for mode in GoCoverageMode}
pkgs = {
pkg_name: GoPkg(
cgo = True,
Expand Down
7 changes: 6 additions & 1 deletion prelude/go/compile.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ def _compile_cmd(
deps: list[Dependency] = [],
flags: list[str] = [],
shared: bool = False,
race: bool = False,
coverage_mode: [GoCoverageMode, None] = None) -> cmd_args:
go_toolchain = ctx.attrs._go_toolchain[GoToolchainInfo]

Expand All @@ -114,6 +115,9 @@ def _compile_cmd(
if shared:
cmd.add("-shared")

if race:
cmd.add("-race")

# Add Go pkgs inherited from deps to compiler search path.
all_pkgs = merge_pkgs([
pkgs,
Expand All @@ -135,6 +139,7 @@ def compile(
compile_flags: list[str] = [],
assemble_flags: list[str] = [],
shared: bool = False,
race: bool = False,
coverage_mode: [GoCoverageMode, None] = None) -> Artifact:
go_toolchain = ctx.attrs._go_toolchain[GoToolchainInfo]
root = _out_root(shared, coverage_mode)
Expand All @@ -143,7 +148,7 @@ def compile(
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, root, pkg_name, pkgs, deps, compile_flags, shared = shared, coverage_mode = coverage_mode), format = "--compiler={}"))
cmd.add(cmd_args(_compile_cmd(ctx, root, pkg_name, pkgs, deps, compile_flags, shared = shared, race = race, coverage_mode = coverage_mode), format = "--compiler={}"))
cmd.add(cmd_args(_assemble_cmd(ctx, pkg_name, assemble_flags, shared = shared), format = "--assembler={}"))
cmd.add(cmd_args(go_toolchain.packer, format = "--packer={}"))
if ctx.attrs.embedcfg:
Expand Down
17 changes: 17 additions & 0 deletions prelude/go/constraints/BUCK.v2
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,20 @@ constraint_value(
constraint_setting = ":compile_shared",
visibility = ["PUBLIC"],
)

constraint_setting(
name = "race",
visibility = ["PUBLIC"],
)

constraint_value(
name = "race_false",
constraint_setting = ":race",
visibility = ["PUBLIC"],
)

constraint_value(
name = "race_true",
constraint_setting = ":race",
visibility = ["PUBLIC"],
)
2 changes: 2 additions & 0 deletions prelude/go/go_binary.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def go_binary_impl(ctx: AnalysisContext) -> list[Provider]:
get_filtered_srcs(ctx, ctx.attrs.srcs),
deps = ctx.attrs.deps,
compile_flags = ctx.attrs.compiler_flags,
race = ctx.attrs.race,
)
(bin, runtime_files, external_debug_info) = link(
ctx,
Expand All @@ -34,6 +35,7 @@ def go_binary_impl(ctx: AnalysisContext) -> list[Provider]:
link_style = value_or(map_val(LinkStyle, ctx.attrs.link_style), LinkStyle("static")),
linker_flags = ctx.attrs.linker_flags,
link_mode = ctx.attrs.link_mode,
race = ctx.attrs.race,
)

# runtime_files are all the artifacts that must be present in order for this
Expand Down
2 changes: 2 additions & 0 deletions prelude/go/go_exported_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def go_exported_library_impl(ctx: AnalysisContext) -> list[Provider]:
deps = ctx.attrs.deps,
compile_flags = ctx.attrs.compiler_flags,
shared = True,
race = ctx.attrs.race,
)
(bin, runtime_files, _external_debug_info) = link(
ctx,
Expand All @@ -35,6 +36,7 @@ def go_exported_library_impl(ctx: AnalysisContext) -> list[Provider]:
linker_flags = ctx.attrs.linker_flags,
external_linker_flags = ctx.attrs.external_linker_flags,
shared = True,
race = ctx.attrs.race,
)
return [
DefaultInfo(
Expand Down
7 changes: 5 additions & 2 deletions prelude/go/go_library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ load(":coverage.bzl", "GoCoverageMode", "cover_srcs")
load(":link.bzl", "GoPkgLinkInfo", "get_inherited_link_pkgs")
load(":packages.bzl", "GoPkg", "go_attr_pkg_name", "merge_pkgs")

def _compile_with_coverage(ctx: AnalysisContext, pkg_name: str, srcs: cmd_args, coverage_mode: GoCoverageMode, shared: bool = False) -> (Artifact, cmd_args):
def _compile_with_coverage(ctx: AnalysisContext, pkg_name: str, srcs: cmd_args, coverage_mode: GoCoverageMode, shared: bool, race: bool) -> (Artifact, cmd_args):
cov_res = cover_srcs(ctx, pkg_name, coverage_mode, srcs, shared)
srcs = cov_res.srcs
coverage_vars = cov_res.variables
Expand All @@ -40,6 +40,7 @@ def _compile_with_coverage(ctx: AnalysisContext, pkg_name: str, srcs: cmd_args,
compile_flags = ctx.attrs.compiler_flags,
coverage_mode = coverage_mode,
shared = shared,
race = race,
)
return (coverage_pkg, coverage_vars)

Expand All @@ -53,6 +54,7 @@ def go_library_impl(ctx: AnalysisContext) -> list[Provider]:
# We need to set CGO_DESABLED for "pure" Go libraries, otherwise CGo files may be selected for compilation.
srcs = get_filtered_srcs(ctx, ctx.attrs.srcs, force_disable_cgo = True)
shared = ctx.attrs._compile_shared
race = ctx.attrs._race

compiled_pkg = compile(
ctx,
Expand All @@ -62,9 +64,10 @@ def go_library_impl(ctx: AnalysisContext) -> list[Provider]:
compile_flags = ctx.attrs.compiler_flags,
assemble_flags = ctx.attrs.assembler_flags,
shared = shared,
race = race,
)

pkg_with_coverage = {mode: _compile_with_coverage(ctx, pkg_name, srcs, mode, shared) for mode in GoCoverageMode}
pkg_with_coverage = {mode: _compile_with_coverage(ctx, pkg_name, srcs, mode, shared, race = race) for mode in GoCoverageMode}

default_output = compiled_pkg
pkgs[pkg_name] = GoPkg(
Expand Down
1 change: 1 addition & 0 deletions prelude/go/go_stdlib.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def go_stdlib_impl(ctx: AnalysisContext) -> list[Provider]:
cmd_args(["-gcflags=", cmd_args(compiler_flags, delimiter = " ")], delimiter = "") if compiler_flags else [],
cmd_args(["-ldflags=", cmd_args(linker_flags, delimiter = " ")], delimiter = "") if linker_flags else [],
["-tags", ",".join(tags)] if tags else [],
["-race"] if ctx.attrs._race else [],
"std",
])

Expand Down
4 changes: 3 additions & 1 deletion prelude/go/go_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,14 @@ def go_test_impl(ctx: AnalysisContext) -> list[Provider]:
pkgs = pkgs,
compile_flags = ctx.attrs.compiler_flags,
coverage_mode = coverage_mode,
race = ctx.attrs.race,
)

# 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)
pkgs[pkg_name] = tests
main = compile(ctx, "main", cmd_args(gen_main), pkgs = pkgs, coverage_mode = coverage_mode)
main = compile(ctx, "main", cmd_args(gen_main), pkgs = pkgs, coverage_mode = coverage_mode, race = ctx.attrs.race)

# Link the above into a Go binary.
(bin, runtime_files, external_debug_info) = link(
Expand All @@ -114,6 +115,7 @@ def go_test_impl(ctx: AnalysisContext) -> list[Provider]:
linker_flags = ctx.attrs.linker_flags,
shared = False,
coverage_mode = coverage_mode,
race = ctx.attrs.race,
)

run_cmd = cmd_args(bin).hidden(runtime_files, external_debug_info)
Expand Down
4 changes: 4 additions & 0 deletions prelude/go/link.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ def link(
linker_flags: list[typing.Any] = [],
external_linker_flags: list[typing.Any] = [],
shared: bool = False,
race: bool = False,
coverage_mode: [GoCoverageMode, None] = None):
go_toolchain = ctx.attrs._go_toolchain[GoToolchainInfo]
if go_toolchain.env_go_os == "windows":
Expand All @@ -134,6 +135,9 @@ def link(
cmd.add("-buildmode=" + _build_mode_param(build_mode))
cmd.add("-buildid=") # Setting to a static buildid helps make the binary reproducible.

if race:
cmd.add("-race")

# Add inherited Go pkgs to library search path.
all_pkgs = merge_pkgs([
pkgs,
Expand Down
51 changes: 45 additions & 6 deletions prelude/go/transitions/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,33 @@ def _compile_shared_transition(platform, refs, _):
configuration = new_cfg,
)

def _race_transition(platform, refs, attrs):
constraints = platform.configuration.constraints

# Cancel transition if the value already set
# to enable using configuration modifiers for overiding this option
race_setting = refs.race_false[ConstraintValueInfo].setting
if race_setting.label in constraints:
return platform

if attrs.race == True:
race_ref = refs.race_true
else:
race_ref = refs.race_false

race_value = race_ref[ConstraintValueInfo]
constraints[race_value.setting.label] = race_value

new_cfg = ConfigurationInfo(
constraints = constraints,
values = platform.configuration.values,
)

return PlatformInfo(
label = platform.label,
configuration = new_cfg,
)

def _chain_transitions(transitions):
def tr(platform, refs, attrs):
for t in transitions:
Expand All @@ -57,36 +84,42 @@ def _chain_transitions(transitions):
return tr

go_binary_transition = transition(
impl = _chain_transitions([_cgo_enabled_transition, _compile_shared_transition]),
impl = _chain_transitions([_cgo_enabled_transition, _compile_shared_transition, _race_transition]),
refs = {
"cgo_enabled_auto": "prelude//go/constraints:cgo_enabled_auto",
"cgo_enabled_false": "prelude//go/constraints:cgo_enabled_false",
"cgo_enabled_true": "prelude//go/constraints:cgo_enabled_true",
"compile_shared_value": "prelude//go/constraints:compile_shared_false",
"race_false": "prelude//go/constraints:race_false",
"race_true": "prelude//go/constraints:race_true",
},
attrs = ["cgo_enabled"],
attrs = ["cgo_enabled", "race"],
)

go_test_transition = transition(
impl = _chain_transitions([_cgo_enabled_transition, _compile_shared_transition]),
impl = _chain_transitions([_cgo_enabled_transition, _compile_shared_transition, _race_transition]),
refs = {
"cgo_enabled_auto": "prelude//go/constraints:cgo_enabled_auto",
"cgo_enabled_false": "prelude//go/constraints:cgo_enabled_false",
"cgo_enabled_true": "prelude//go/constraints:cgo_enabled_true",
"compile_shared_value": "prelude//go/constraints:compile_shared_false",
"race_false": "prelude//go/constraints:race_false",
"race_true": "prelude//go/constraints:race_true",
},
attrs = ["cgo_enabled"],
attrs = ["cgo_enabled", "race"],
)

go_exported_library_transition = transition(
impl = _chain_transitions([_cgo_enabled_transition, _compile_shared_transition]),
impl = _chain_transitions([_cgo_enabled_transition, _compile_shared_transition, _race_transition]),
refs = {
"cgo_enabled_auto": "prelude//go/constraints:cgo_enabled_auto",
"cgo_enabled_false": "prelude//go/constraints:cgo_enabled_false",
"cgo_enabled_true": "prelude//go/constraints:cgo_enabled_true",
"compile_shared_value": "prelude//go/constraints:compile_shared_true",
"race_false": "prelude//go/constraints:race_false",
"race_true": "prelude//go/constraints:race_true",
},
attrs = ["cgo_enabled"],
attrs = ["cgo_enabled", "race"],
)

cgo_enabled_attr = attrs.default_only(attrs.option(attrs.bool(), default = select({
Expand All @@ -101,3 +134,9 @@ compile_shared_attr = attrs.default_only(attrs.bool(default = select({
"prelude//go/constraints:compile_shared_false": False,
"prelude//go/constraints:compile_shared_true": True,
})))

race_attr = attrs.default_only(attrs.bool(default = select({
"DEFAULT": False,
"prelude//go/constraints:race_false": False,
"prelude//go/constraints:race_true": True,
})))
5 changes: 4 additions & 1 deletion prelude/rules_impl.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ load("@prelude//go:go_exported_library.bzl", "go_exported_library_impl")
load("@prelude//go:go_library.bzl", "go_library_impl")
load("@prelude//go:go_stdlib.bzl", "go_stdlib_impl")
load("@prelude//go:go_test.bzl", "go_test_impl")
load("@prelude//go/transitions:defs.bzl", "cgo_enabled_attr", "compile_shared_attr", "go_binary_transition", "go_exported_library_transition", "go_test_transition")
load("@prelude//go/transitions:defs.bzl", "cgo_enabled_attr", "compile_shared_attr", "go_binary_transition", "go_exported_library_transition", "go_test_transition", "race_attr")
load("@prelude//haskell:haskell.bzl", "haskell_binary_impl", "haskell_library_impl", "haskell_prebuilt_library_impl")
load("@prelude//haskell:haskell_ghci.bzl", "haskell_ghci_impl")
load("@prelude//haskell:haskell_haddock.bzl", "haskell_haddock_impl")
Expand Down Expand Up @@ -385,6 +385,7 @@ inlined_extra_attributes = {
"_exec_os_type": buck.exec_os_type_arg(),
"_go_stdlib": attrs.default_only(attrs.dep(default = "prelude//go/tools:stdlib")),
"_go_toolchain": toolchains_common.go(),
"_race": race_attr,
},
# csharp
"csharp_library": {
Expand Down Expand Up @@ -444,12 +445,14 @@ inlined_extra_attributes = {
"_compile_shared": compile_shared_attr,
"_go_stdlib": attrs.default_only(attrs.dep(default = "prelude//go/tools:stdlib")),
"_go_toolchain": toolchains_common.go(),
"_race": race_attr,
},
"go_stdlib": {
"_cgo_enabled": cgo_enabled_attr,
"_compile_shared": compile_shared_attr,
"_exec_os_type": buck.exec_os_type_arg(),
"_go_toolchain": toolchains_common.go(),
"_race": race_attr,
},
"go_test": {
"coverage_mode": attrs.option(attrs.enum(GoCoverageMode.values()), default = None),
Expand Down

0 comments on commit eb9ccb3

Please sign in to comment.