Skip to content

Commit

Permalink
Support gc_goopts and gc_linkopts attributes
Browse files Browse the repository at this point in the history
go_library, cgo_library, go_binary, and go_test now support the
gc_goopts attribute. This is a list of flags to pass to the Go
compiler.

go_binary and go_test also support the gc_linkopts attribute. This is
a list of flags to be passed to the Go linker.

Note that _emit_go_compile_action and _emit_go_link_action have had
small interface changes and are now private. I didn't see any uses of
these functions on GitHub, and I'd like to avoid having people depend
on them in the future.

Fixes #217
  • Loading branch information
Jay Conrod committed Mar 8, 2017
1 parent aa5a431 commit be1b4e8
Show file tree
Hide file tree
Showing 9 changed files with 275 additions and 30 deletions.
74 changes: 70 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ go_prefix(prefix)
## go\_library

```bzl
go_library(name, srcs, deps, data)
go_library(name, srcs, deps, data, gc_goopts)
```
<table class="table table-condensed table-bordered table-params">
<colgroup>
Expand Down Expand Up @@ -357,14 +357,25 @@ go_library(name, srcs, deps, data)
<p>List of files needed by this rule at runtime.</p>
</td>
</tr>
<tr>
<td><code>gc_goopts</code></td>
<td>
<code>List of strings, optional</code>
<p>List of flags to add to the Go compilation command. Subject to
<a href="https://bazel.build/versions/master/docs/be/make-variables.html#make-var-substitution">Make
variable substitution</a> and
<a href="https://bazel.build/versions/master/docs/be/common-definitions.html#sh-tokenization">Bourne
shell tokenization</a>.</p>
</td>
</tr>
</tbody>
</table>

<a name="cgo_library"></a>
## cgo\_library

```bzl
cgo_library(name, srcs, copts, clinkopts, cdeps, deps, data)
cgo_library(name, srcs, copts, clinkopts, cdeps, deps, data, gc_goopts)
```
<table class="table table-condensed table-bordered table-params">
<colgroup>
Expand Down Expand Up @@ -431,6 +442,17 @@ cgo_library(name, srcs, copts, clinkopts, cdeps, deps, data)
<p>List of files needed by this rule at runtime.</p>
</td>
</tr>
<tr>
<td><code>gc_goopts</code></td>
<td>
<code>List of strings, optional</code>
<p>List of flags to add to the Go compilation command. Subject to
<a href="https://bazel.build/versions/master/docs/be/make-variables.html#make-var-substitution">Make
variable substitution</a> and
<a href="https://bazel.build/versions/master/docs/be/common-definitions.html#sh-tokenization">Bourne
shell tokenization</a>.</p>
</td>
</tr>
</tbody>
</table>

Expand All @@ -457,7 +479,7 @@ go_library(
## go\_binary

```bzl
go_binary(name, srcs, deps, data, linkstamp)
go_binary(name, srcs, deps, data, linkstamp, gc_goopts, gc_linkopts)
```
<table class="table table-condensed table-bordered table-params">
<colgroup>
Expand Down Expand Up @@ -516,14 +538,36 @@ go_binary(name, srcs, deps, data, linkstamp)
a good template which prints Git workspace status.</p>
</td>
</tr>
<tr>
<td><code>gc_goopts</code></td>
<td>
<code>List of strings, optional</code>
<p>List of flags to add to the Go compilation command. Subject to
<a href="https://bazel.build/versions/master/docs/be/make-variables.html#make-var-substitution">Make
variable substitution</a> and
<a href="https://bazel.build/versions/master/docs/be/common-definitions.html#sh-tokenization">Bourne
shell tokenization</a>.</p>
</td>
</tr>
<tr>
<td><code>gc_linkopts</code></td>
<td>
<code>List of strings, optional</code>
<p>List of flags to add to the Go link command. Subject to
<a href="https://bazel.build/versions/master/docs/be/make-variables.html#make-var-substitution">Make
variable substitution</a> and
<a href="https://bazel.build/versions/master/docs/be/common-definitions.html#sh-tokenization">Bourne
shell tokenization</a>.</p>
</td>
</tr>
</tbody>
</table>

<a name="go_test"></a>
## go\_test

```bzl
go_test(name, srcs, deps, data)
go_test(name, srcs, deps, data, gc_goopts, gc_linkopts)
```
<table class="table table-condensed table-bordered table-params">
<colgroup>
Expand Down Expand Up @@ -565,6 +609,28 @@ go_test(name, srcs, deps, data)
<p>List of files needed by this rule at runtime.</p>
</td>
</tr>
<tr>
<td><code>gc_goopts</code></td>
<td>
<code>List of strings, optional</code>
<p>List of flags to add to the Go compilation command. Subject to
<a href="https://bazel.build/versions/master/docs/be/make-variables.html#make-var-substitution">Make
variable substitution</a> and
<a href="https://bazel.build/versions/master/docs/be/common-definitions.html#sh-tokenization">Bourne
shell tokenization</a>.</p>
</td>
</tr>
<tr>
<td><code>gc_linkopts</code></td>
<td>
<code>List of strings, optional</code>
<p>List of flags to add to the Go link command. Subject to
<a href="https://bazel.build/versions/master/docs/be/make-variables.html#make-var-substitution">Make
variable substitution</a> and
<a href="https://bazel.build/versions/master/docs/be/common-definitions.html#sh-tokenization">Bourne
shell tokenization</a>.</p>
</td>
</tr>
</tbody>
</table>

Expand Down
73 changes: 47 additions & 26 deletions go/def.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,8 @@ def _is_external(p):
"""Checks if the string starts with ../"""
return p[0:3] == '../'

def emit_go_compile_action(ctx, sources, deps, out_lib, extra_objects=[]):
def _emit_go_compile_action(ctx, sources, deps, out_lib,
extra_objects, gc_goopts):
"""Construct the command line for compiling Go code.
Constructs a symlink tree to accommodate for workspace name.
Expand All @@ -218,6 +219,7 @@ def emit_go_compile_action(ctx, sources, deps, out_lib, extra_objects=[]):
out_lib: the artifact (configured target?) that should be produced
extra_objects: an iterable of extra object files to be added to the
output archive file.
gc_goopts: additional flags to pass to the compiler.
"""
tree_layout = {}
inputs = []
Expand All @@ -243,7 +245,7 @@ def emit_go_compile_action(ctx, sources, deps, out_lib, extra_objects=[]):
"tool", "compile",
"-o", ('../' * out_depth) + out_lib.path, "-pack",
"-I", "."
]
] + gc_goopts

# Set -p to the import path of the library, ie.
# (ctx.label.package + "/" ctx.label.name) for now.
Expand Down Expand Up @@ -288,7 +290,6 @@ def go_library_impl(ctx):
"already has cgo_object in %s" % (ctx.label.name,
ctx.attr.library.name))
cgo_object = ctx.attr.library.cgo_object

if not go_srcs:
fail("may not be empty", "srcs")

Expand All @@ -303,8 +304,8 @@ def go_library_impl(ctx):
extra_objects += [obj]

out_lib = ctx.outputs.lib
emit_go_compile_action(ctx, go_srcs, deps, out_lib,
extra_objects=extra_objects)
gc_goopts = _gc_goopts(ctx)
_emit_go_compile_action(ctx, go_srcs, deps, out_lib, extra_objects, gc_goopts)

transitive_libs = set([out_lib])
transitive_importmap = {out_lib.path: _go_importpath(ctx)}
Expand All @@ -329,7 +330,8 @@ def go_library_impl(ctx):
transitive_go_library_object = transitive_libs,
cgo_object = cgo_object,
transitive_cgo_deps = transitive_cgo_deps,
transitive_go_importmap = transitive_importmap
transitive_go_importmap = transitive_importmap,
gc_goopts = gc_goopts,
)

def _c_linker_options(ctx, blacklist=[]):
Expand Down Expand Up @@ -371,8 +373,22 @@ def _short_path(f):
fail("file name %s is not prefixed with its root %s", f.path, prefix)
return f.path[len(prefix):]

def emit_go_link_action(ctx, importmap, transitive_libs, cgo_deps, lib,
executable, x_defs={}):
def _gc_goopts(ctx):
gc_goopts = [ctx.expand_make_variables("gc_goopts", f, {})
for f in ctx.attr.gc_goopts]
if ctx.attr.library:
gc_goopts += ctx.attr.library.gc_goopts
return gc_goopts

def _gc_linkopts(ctx):
gc_linkopts = [ctx.expand_make_variables("gc_linkopts", f, {})
for f in ctx.attr.gc_linkopts]
for k, v in ctx.attr.x_defs.items():
gc_linkopts += ["-X", "%s='%s'" % (k, v)]
return gc_linkopts

def _emit_go_link_action(ctx, importmap, transitive_libs, cgo_deps, lib,
executable, gc_linkopts):
"""Sets up a symlink tree to libraries to link together."""
out_dir = executable.path + ".dir"
out_depth = out_dir.count('/') + 1
Expand Down Expand Up @@ -412,11 +428,7 @@ def emit_go_link_action(ctx, importmap, transitive_libs, cgo_deps, lib,
('../' * out_depth) + ctx.file.go_tool.path,
"tool", "link", "-L", ".",
"-o", _go_importpath(ctx),
'"${STAMP_XDEFS[@]}"',
]

if x_defs:
link_cmd += [" -X %s='%s' " % (k, v) for k,v in x_defs.items()]
] + gc_linkopts + ['"${STAMP_XDEFS[@]}"']

# workaround for a bug in ld(1) on Mac OS X.
# http://lists.apple.com/archives/Darwin-dev/2006/Sep/msg00084.html
Expand Down Expand Up @@ -476,13 +488,13 @@ def go_binary_impl(ctx):
executable = ctx.outputs.executable
lib_out = ctx.outputs.lib

emit_go_link_action(
_emit_go_link_action(
ctx,
transitive_libs=lib_result.transitive_go_library_object,
importmap=lib_result.transitive_go_importmap,
cgo_deps=lib_result.transitive_cgo_deps,
lib=lib_out, executable=executable,
x_defs=ctx.attr.x_defs)
gc_linkopts=_gc_linkopts(ctx))

runfiles = ctx.runfiles(collect_data = True,
files = ctx.files.data)
Expand Down Expand Up @@ -514,18 +526,23 @@ def go_test_impl(ctx):
arguments = args,
env = dict(go_environment_vars(ctx), RUNDIR=ctx.label.package))

emit_go_compile_action(
ctx, set([main_go]), ctx.attr.deps + [lib_result], ctx.outputs.main_lib)
_emit_go_compile_action(
ctx,
sources=set([main_go]),
deps=ctx.attr.deps + [lib_result],
out_lib=ctx.outputs.main_lib,
extra_objects=[],
gc_goopts=_gc_goopts(ctx))

importmap = lib_result.transitive_go_importmap + {
ctx.outputs.main_lib.path: _go_importpath(ctx) + "_main_test"}
emit_go_link_action(
_emit_go_link_action(
ctx,
importmap=importmap,
transitive_libs=lib_result.transitive_go_library_object,
cgo_deps=lib_result.transitive_cgo_deps,
lib=ctx.outputs.main_lib, executable=ctx.outputs.executable,
x_defs=ctx.attr.x_defs)
gc_linkopts=_gc_linkopts(ctx))

# TODO(bazel-team): the Go tests should do a chdir to the directory
# holding the data files, so open-source go tests continue to work
Expand Down Expand Up @@ -597,8 +614,10 @@ go_library_attrs = go_env_attrs + {
"go_sources",
"asm_sources",
"cgo_object",
"gc_goopts",
],
),
"gc_goopts": attr.string_list(),
}

_crosstool_attrs = {
Expand All @@ -607,6 +626,12 @@ _crosstool_attrs = {
),
}

go_link_attrs = go_library_attrs + _crosstool_attrs + {
"gc_linkopts": attr.string_list(),
"linkstamp": attr.string(),
"x_defs": attr.string_dict(),
}

go_library_outputs = {
"lib": "%{name}.a",
}
Expand All @@ -627,27 +652,22 @@ go_library = rule(

go_binary = rule(
go_binary_impl,
attrs = go_library_attrs + _crosstool_attrs + {
"linkstamp": attr.string(default = ""),
"x_defs": attr.string_dict(),
},
attrs = go_library_attrs + _crosstool_attrs + go_link_attrs,
executable = True,
fragments = ["cpp"],
outputs = go_library_outputs,
)

go_test = rule(
go_test_impl,
attrs = go_library_attrs + _crosstool_attrs + {
attrs = go_library_attrs + _crosstool_attrs + go_link_attrs + {
"test_generator": attr.label(
executable = True,
default = Label(
"//go/tools:generate_test_main",
),
cfg = "host",
),
"linkstamp": attr.string(default = ""),
"x_defs": attr.string_dict(),
},
executable = True,
fragments = ["cpp"],
Expand Down Expand Up @@ -883,6 +903,7 @@ def _cgo_genrule_impl(ctx):
asm_sources = [],
cgo_object = ctx.attr.cgo_object,
direct_deps = ctx.attr.deps,
gc_goopts = [],
)

_cgo_genrule = rule(
Expand Down
Loading

0 comments on commit be1b4e8

Please sign in to comment.