Skip to content

Commit 528f6fa

Browse files
authored
GoCompilePkg: unified action for building a Go package (bazel-contrib#2027)
GoCompilePkg will be a replacement for GoCompile and several other actions. It will consolidate all the work of building a Go archive into a single Bazel action: it will run the Go compiler, the C/C++ compilers, the assembler, cgo, coverage, nogo, and pack all as one action. This should reduce sandboxing overhead for local configurations and file transfer overhead for remote configurations. This change introduces a very limited version of GoCompilePkg with most of the above functionality marked "TODO". It can only run the Go compiler. emit_archive uses this action for archives that don't require any other features. Updates bazel-contrib#1957
1 parent c6506a2 commit 528f6fa

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1846
-319
lines changed

.bazelci/presubmit.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ platforms:
329329
- "-//tests/core/cgo:cc_deps"
330330
- "-//tests/core/cgo:c_srcs"
331331
- "-//tests/core/cgo:bar_dep"
332+
- "-//tests/core/cgo:tag_test" # TODO(#2031): FindBinary does not work
332333
- "-//tests/core/coverage:coverage_test_test"
333334
- "-//tests/core/coverage:cross_cover_test_test"
334335
- "-//tests/core/cross:cross_test"

go/def.bzl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ load(
3131
)
3232
load(
3333
"@io_bazel_rules_go//go/private:go_toolchain.bzl",
34+
_declare_toolchains = "declare_toolchains",
3435
_go_toolchain = "go_toolchain",
3536
)
3637
load(
@@ -68,12 +69,13 @@ load(
6869
# check this to determine compatibility.
6970
RULES_GO_VERSION = "0.18.0"
7071

72+
declare_toolchains = _declare_toolchains
7173
go_context = _go_context
72-
go_tool_library = _go_tool_library
73-
nogo = _nogo
7474
go_embed_data = _go_embed_data
7575
go_sdk = _go_sdk
76+
go_tool_library = _go_tool_library
7677
go_toolchain = _go_toolchain
78+
nogo = _nogo
7779

7880
GoLibrary = _GoLibrary
7981
"""See go/providers.rst#GoLibrary for full documentation."""

go/platform/list.bzl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,10 @@ def declare_config_settings():
115115
"//go/toolchain:" + goarch,
116116
],
117117
)
118+
119+
def generate_toolchain_names():
120+
# Keep in sync with generate_toolchains
121+
return [
122+
"go_{}_{}".format(target_goos, target_goarch)
123+
for target_goos, target_goarch in GOOS_GOARCH
124+
]

go/private/BUILD.sdk.bazel

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
load("@io_bazel_rules_go//go/private:rules/binary.bzl", "go_tool_binary")
22
load("@io_bazel_rules_go//go/private:rules/sdk.bzl", "package_list")
3-
load("@io_bazel_rules_go//go/toolchain:toolchains.bzl", "declare_toolchains")
4-
load("@io_bazel_rules_go//go:def.bzl", "go_sdk")
3+
load("@io_bazel_rules_go//go:def.bzl", "declare_toolchains", "go_sdk")
54

65
package(default_visibility = ["//visibility:public"])
76

go/private/actions/archive.bzl

Lines changed: 112 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,33 @@ load(
2929
"@io_bazel_rules_go//go/private:providers.bzl",
3030
"GoArchive",
3131
"GoArchiveData",
32+
"effective_importpath_pkgpath",
3233
"get_archive",
3334
)
35+
load(
36+
"@io_bazel_rules_go//go/private:rules/cgo.bzl",
37+
"cgo_configure",
38+
)
39+
load(
40+
"@io_bazel_rules_go//go/private:actions/compilepkg.bzl",
41+
"emit_compilepkg",
42+
)
3443

3544
def emit_archive(go, source = None):
3645
"""See go/toolchains.rst#archive for full documentation."""
3746

3847
if source == None:
3948
fail("source is a required parameter")
4049

41-
covered = bool(go.cover and go.coverdata and source.cover)
42-
if covered:
43-
source = go.cover(go, source)
4450
split = split_srcs(source.srcs)
4551
lib_name = source.library.importmap + ".a"
4652
out_lib = go.declare_file(go, path = lib_name)
47-
out_export = None
4853
if go.nogo:
4954
# TODO(#1847): write nogo data into a new section in the .a file instead
5055
# of writing a separate file.
5156
out_export = go.declare_file(go, path = lib_name[:-len(".a")] + ".x")
57+
else:
58+
out_export = None
5259
searchpath = out_lib.path[:-len(lib_name)]
5360
testfilter = getattr(source.library, "testfilter", None)
5461

@@ -59,57 +66,117 @@ def emit_archive(go, source = None):
5966
runfiles = runfiles.merge(a.runfiles)
6067
if a.source.mode != go.mode:
6168
fail("Archive mode does not match {} is {} expected {}".format(a.data.label, mode_string(a.source.mode), mode_string(go.mode)))
62-
if covered:
63-
direct.append(go.coverdata)
6469

65-
asmhdr = None
66-
if split.asm:
67-
asmhdr = go.declare_file(go, "go_asm.h")
70+
if not source.cgo_archives:
71+
# TODO(jayconrod): We still need to support the legacy cgo path when
72+
# Objective C sources are present, since the Objective C toolchain
73+
# isn't exposed to Starlark. The legacy path runs cgo as a separate
74+
# action, then builds generated code with cc_library / objc_library.
75+
# A go_library compiles generated Go code and packs the other
76+
# objects from cgo_archives. "cgo_archives" is not supported on
77+
# the new path because we do all that in one action.
6878

69-
if len(split.asm) == 0 and not source.cgo_archives:
70-
go.compile(
79+
# TODO(jayconrod): do we need to do full Bourne tokenization here?
80+
cppopts = [f for fs in source.cppopts for f in fs.split(" ")]
81+
copts = [f for fs in source.copts for f in fs.split(" ")]
82+
cxxopts = [f for fs in source.cxxopts for f in fs.split(" ")]
83+
clinkopts = [f for fs in source.clinkopts for f in fs.split(" ")]
84+
85+
cgo_inputs = depset()
86+
cgo_deps = depset()
87+
if source.cgo:
88+
cgo = cgo_configure(
89+
go,
90+
srcs = split.go + split.c + split.asm + split.cxx + split.headers,
91+
cdeps = source.cdeps,
92+
cppopts = cppopts,
93+
copts = copts,
94+
cxxopts = cxxopts,
95+
clinkopts = clinkopts,
96+
)
97+
runfiles = runfiles.merge(cgo.runfiles)
98+
cgo_inputs = cgo.inputs
99+
cgo_deps = cgo.deps
100+
cppopts = cgo.cppopts
101+
copts = cgo.copts
102+
cxxopts = cgo.cxxopts
103+
clinkopts = cgo.clinkopts
104+
105+
emit_compilepkg(
71106
go,
72-
sources = split.go,
73-
importpath = source.library.importmap,
107+
sources = split.go + split.c + split.asm + split.cxx + split.headers,
108+
cover = source.cover,
109+
importpath = effective_importpath_pkgpath(source.library)[0],
110+
importmap = source.library.importmap,
74111
archives = direct,
75112
out_lib = out_lib,
76113
out_export = out_export,
77114
gc_goopts = source.gc_goopts,
115+
cgo = source.cgo,
116+
cgo_inputs = cgo_inputs,
117+
cppopts = cppopts,
118+
copts = copts,
119+
cxxopts = cxxopts,
120+
clinkopts = clinkopts,
121+
cgo_archives = source.cgo_archives,
78122
testfilter = testfilter,
79123
)
80124
else:
81-
# Assembly files must be passed to the compiler as sources. We need
82-
# to run the assembler to produce a symabis file that gets passed to
83-
# the compiler. The compiler builder does all this so it doesn't
84-
# need to be a separate action (but individual .o files are still
85-
# produced with separate actions).
86-
partial_lib = go.declare_file(go, path = lib_name + "~partial", ext = ".a")
87-
go.compile(
88-
go,
89-
sources = split.go + split.asm + split.headers,
90-
importpath = source.library.importmap,
91-
archives = direct,
92-
out_lib = partial_lib,
93-
out_export = out_export,
94-
gc_goopts = source.gc_goopts,
95-
testfilter = testfilter,
96-
asmhdr = asmhdr,
97-
)
125+
cgo_deps = source.cgo_deps
126+
127+
if bool(go.cover and go.coverdata and source.cover):
128+
source = go.cover(go, source)
129+
direct.append(go.coverdata)
130+
131+
asmhdr = None
132+
if split.asm:
133+
asmhdr = go.declare_file(go, "go_asm.h")
134+
135+
if len(split.asm) == 0 and not source.cgo_archives:
136+
go.compile(
137+
go,
138+
sources = split.go,
139+
importpath = source.library.importmap,
140+
archives = direct,
141+
out_lib = out_lib,
142+
out_export = out_export,
143+
gc_goopts = source.gc_goopts,
144+
testfilter = testfilter,
145+
)
146+
else:
147+
# Assembly files must be passed to the compiler as sources. We need
148+
# to run the assembler to produce a symabis file that gets passed to
149+
# the compiler. The compiler builder does all this so it doesn't
150+
# need to be a separate action (but individual .o files are still
151+
# produced with separate actions).
152+
partial_lib = go.declare_file(go, path = lib_name + "~partial", ext = ".a")
153+
go.compile(
154+
go,
155+
sources = split.go + split.asm + split.headers,
156+
importpath = source.library.importmap,
157+
archives = direct,
158+
out_lib = partial_lib,
159+
out_export = out_export,
160+
gc_goopts = source.gc_goopts,
161+
testfilter = testfilter,
162+
asmhdr = asmhdr,
163+
)
164+
165+
# include other .s as inputs, since they may be #included.
166+
# This may result in multiple copies of symbols defined in included
167+
# files, but go build allows it, so we do, too.
168+
asm_headers = split.headers + split.asm + [asmhdr]
169+
extra_objects = []
170+
for src in split.asm:
171+
extra_objects.append(go.asm(go, source = src, hdrs = asm_headers))
172+
go.pack(
173+
go,
174+
in_lib = partial_lib,
175+
out_lib = out_lib,
176+
objects = extra_objects,
177+
archives = source.cgo_archives,
178+
)
98179

99-
# include other .s as inputs, since they may be #included.
100-
# This may result in multiple copies of symbols defined in included
101-
# files, but go build allows it, so we do, too.
102-
asm_headers = split.headers + split.asm + [asmhdr]
103-
extra_objects = []
104-
for src in split.asm:
105-
extra_objects.append(go.asm(go, source = src, hdrs = asm_headers))
106-
go.pack(
107-
go,
108-
in_lib = partial_lib,
109-
out_lib = out_lib,
110-
objects = extra_objects,
111-
archives = source.cgo_archives,
112-
)
113180
data = GoArchiveData(
114181
name = source.library.name,
115182
label = source.library.label,
@@ -134,7 +201,7 @@ def emit_archive(go, source = None):
134201
libs = sets.union([out_lib], *[a.libs for a in direct]),
135202
transitive = sets.union([data], *[a.transitive for a in direct]),
136203
x_defs = x_defs,
137-
cgo_deps = sets.union(source.cgo_deps, *[a.cgo_deps for a in direct]),
204+
cgo_deps = sets.union(cgo_deps, *[a.cgo_deps for a in direct]),
138205
cgo_exports = sets.union(source.cgo_exports, *[a.cgo_exports for a in direct]),
139206
runfiles = runfiles,
140207
mode = go.mode,

go/private/actions/asm.bzl

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,23 @@ def emit_asm(
3333
out_obj = go.declare_file(go, path = source.basename[:-2], ext = ".o")
3434
inputs = hdrs + go.sdk.tools + go.sdk.headers + go.stdlib.libs + [source]
3535

36-
args = go.builder_args(go, "asm")
37-
args.add(source)
38-
args.add("--")
39-
includes = ([go.sdk.root_file.dirname + "/pkg/include"] +
40-
[f.dirname for f in hdrs])
36+
builder_args = go.builder_args(go, "asm")
37+
builder_args.add("-o", out_obj)
38+
builder_args.add(source)
4139

4240
# TODO(#1463): use uniquify=True when available.
41+
tool_args = go.tool_args(go)
42+
includes = ([go.sdk.root_file.dirname + "/pkg/include"] +
43+
[f.dirname for f in hdrs])
4344
includes = sorted({i: None for i in includes}.keys())
44-
args.add_all(includes, before_each = "-I")
45-
args.add("-trimpath", ".")
46-
args.add("-o", out_obj)
47-
args.add_all(link_mode_args(go.mode))
45+
tool_args.add_all(includes, before_each = "-I")
46+
tool_args.add_all(link_mode_args(go.mode))
4847
go.actions.run(
4948
inputs = inputs,
5049
outputs = [out_obj],
5150
mnemonic = "GoAsm",
5251
executable = go.toolchain._builder,
53-
arguments = [args],
52+
arguments = [builder_args, "--", tool_args],
5453
env = go.env,
5554
)
5655
return out_obj

go/private/actions/compile.bzl

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,6 @@ load(
1616
"@io_bazel_rules_go//go/private:mode.bzl",
1717
"link_mode_args",
1818
)
19-
load(
20-
"@io_bazel_rules_go//go/private:skylib/lib/shell.bzl",
21-
"shell",
22-
)
2319

2420
def _archive(v):
2521
return "{}={}={}={}".format(

0 commit comments

Comments
 (0)