aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoralandonovan <adonovan@google.com>2021-01-22 14:46:13 -0500
committerGitHub <noreply@github.com>2021-01-22 14:46:13 -0500
commitf935de8d11ef317200abeff45a7448773dcfb717 (patch)
tree1a642655e66f49e4d4a4e43887df4a150ed2f7a7
parent300301f1bd3a2e740eab5959c68cd545d653d018 (diff)
downloadstarlark-go-f935de8d11ef317200abeff45a7448773dcfb717.tar.gz
testdata: s/blacklist/blocklist/g per Google policy (#343)
See https://www.adexchanger.com/data-driven-thinking/no-more-inflammatory-jargon-change-blacklist-to-blocklist/
-rw-r--r--syntax/testdata/scan.star1825
1 files changed, 938 insertions, 887 deletions
diff --git a/syntax/testdata/scan.star b/syntax/testdata/scan.star
index 3b87c63..4f62ba9 100644
--- a/syntax/testdata/scan.star
+++ b/syntax/testdata/scan.star
@@ -72,502 +72,532 @@ cgo_filetype = FileType([
################
def go_environment_vars(ctx):
- """Return a map of environment variables for use with actions, based on
- the arguments. Uses the ctx.fragments.cpp.cpu attribute, if present,
- and picks a default of target_os="linux" and target_arch="amd64"
- otherwise.
-
- Args:
- The starlark Context.
-
- Returns:
- A dict of environment variables for running Go tool commands that build for
- the target OS and architecture.
- """
- default_toolchain = {"GOOS": "linux", "GOARCH": "amd64"}
- bazel_to_go_toolchain = {
- "k8": {"GOOS": "linux", "GOARCH": "amd64"},
- "piii": {"GOOS": "linux", "GOARCH": "386"},
- "darwin": {"GOOS": "darwin", "GOARCH": "amd64"},
- "darwin_x86_64": {"GOOS": "darwin", "GOARCH": "amd64"},
- "freebsd": {"GOOS": "freebsd", "GOARCH": "amd64"},
- "armeabi-v7a": {"GOOS": "linux", "GOARCH": "arm"},
- "arm": {"GOOS": "linux", "GOARCH": "arm"}
- }
- env = {}
- if hasattr(ctx.file, "go_tool"):
- env["GOROOT"] = ctx.file.go_tool.dirname + "/.."
- env.update(bazel_to_go_toolchain.get(ctx.fragments.cpp.cpu, default_toolchain))
- return env
+ """Return a map of environment variables for use with actions, based on
+ the arguments. Uses the ctx.fragments.cpp.cpu attribute, if present,
+ and picks a default of target_os="linux" and target_arch="amd64"
+ otherwise.
+
+ Args:
+ The starlark Context.
+
+ Returns:
+ A dict of environment variables for running Go tool commands that build for
+ the target OS and architecture.
+ """
+ default_toolchain = {"GOOS": "linux", "GOARCH": "amd64"}
+ bazel_to_go_toolchain = {
+ "k8": {"GOOS": "linux", "GOARCH": "amd64"},
+ "piii": {"GOOS": "linux", "GOARCH": "386"},
+ "darwin": {"GOOS": "darwin", "GOARCH": "amd64"},
+ "darwin_x86_64": {"GOOS": "darwin", "GOARCH": "amd64"},
+ "freebsd": {"GOOS": "freebsd", "GOARCH": "amd64"},
+ "armeabi-v7a": {"GOOS": "linux", "GOARCH": "arm"},
+ "arm": {"GOOS": "linux", "GOARCH": "arm"},
+ }
+ env = {}
+ if hasattr(ctx.file, "go_tool"):
+ env["GOROOT"] = ctx.file.go_tool.dirname + "/.."
+ env.update(bazel_to_go_toolchain.get(ctx.fragments.cpp.cpu, default_toolchain))
+ return env
def _is_darwin_cpu(ctx):
- cpu = ctx.fragments.cpp.cpu
- return cpu == "darwin" or cpu == "darwin_x86_64"
+ cpu = ctx.fragments.cpp.cpu
+ return cpu == "darwin" or cpu == "darwin_x86_64"
def _emit_generate_params_action(cmds, ctx, fn):
- cmds_all = [
- # Use bash explicitly. /bin/sh is default, and it may be linked to a
- # different shell, e.g., /bin/dash on Ubuntu.
- "#!/bin/bash",
- "set -e",
- ]
- cmds_all += cmds
- cmds_all_str = "\n".join(cmds_all) + "\n"
- f = ctx.new_file(ctx.configuration.bin_dir, fn)
- ctx.file_action(
- output = f,
- content = cmds_all_str,
- executable = True)
- return f
+ cmds_all = [
+ # Use bash explicitly. /bin/sh is default, and it may be linked to a
+ # different shell, e.g., /bin/dash on Ubuntu.
+ "#!/bin/bash",
+ "set -e",
+ ]
+ cmds_all += cmds
+ cmds_all_str = "\n".join(cmds_all) + "\n"
+ f = ctx.new_file(ctx.configuration.bin_dir, fn)
+ ctx.file_action(
+ output = f,
+ content = cmds_all_str,
+ executable = True,
+ )
+ return f
def _emit_go_asm_action(ctx, source, hdrs, out_obj):
- """Construct the command line for compiling Go Assembly code.
- Constructs a symlink tree to accomodate for workspace name.
- Args:
- ctx: The starlark Context.
- source: a source code artifact
- hdrs: list of .h files that may be included
- out_obj: the artifact (configured target?) that should be produced
- """
- params = {
- "go_tool": ctx.file.go_tool.path,
- "includes": [f.dirname for f in hdrs] + [ctx.file.go_include.path],
- "source": source.path,
- "out": out_obj.path,
- }
-
- inputs = hdrs + ctx.files.toolchain + [source]
- ctx.action(
- inputs = inputs,
- outputs = [out_obj],
- mnemonic = "GoAsmCompile",
- executable = ctx.executable._asm,
- arguments = [json_marshal(params)],
- )
+ """Construct the command line for compiling Go Assembly code.
+ Constructs a symlink tree to accomodate for workspace name.
+ Args:
+ ctx: The starlark Context.
+ source: a source code artifact
+ hdrs: list of .h files that may be included
+ out_obj: the artifact (configured target?) that should be produced
+ """
+ params = {
+ "go_tool": ctx.file.go_tool.path,
+ "includes": [f.dirname for f in hdrs] + [ctx.file.go_include.path],
+ "source": source.path,
+ "out": out_obj.path,
+ }
+
+ inputs = hdrs + ctx.files.toolchain + [source]
+ ctx.action(
+ inputs = inputs,
+ outputs = [out_obj],
+ mnemonic = "GoAsmCompile",
+ executable = ctx.executable._asm,
+ arguments = [json_marshal(params)],
+ )
def _go_importpath(ctx):
- """Returns the expected importpath of the go_library being built.
-
- Args:
- ctx: The starlark Context
-
- Returns:
- Go importpath of the library
- """
- path = ctx.attr.importpath
- if path != "":
+ """Returns the expected importpath of the go_library being built.
+
+ Args:
+ ctx: The starlark Context
+
+ Returns:
+ Go importpath of the library
+ """
+ path = ctx.attr.importpath
+ if path != "":
+ return path
+ path = ctx.attr.go_prefix.go_prefix
+ if path.endswith("/"):
+ path = path[:-1]
+ if ctx.label.package:
+ path += "/" + ctx.label.package
+ if ctx.label.name != _DEFAULT_LIB:
+ path += "/" + ctx.label.name
+ if path.rfind(_VENDOR_PREFIX) != -1:
+ path = path[len(_VENDOR_PREFIX) + path.rfind(_VENDOR_PREFIX):]
+ if path[0] == "/":
+ path = path[1:]
return path
- path = ctx.attr.go_prefix.go_prefix
- if path.endswith("/"):
- path = path[:-1]
- if ctx.label.package:
- path += "/" + ctx.label.package
- if ctx.label.name != _DEFAULT_LIB:
- path += "/" + ctx.label.name
- if path.rfind(_VENDOR_PREFIX) != -1:
- path = path[len(_VENDOR_PREFIX) + path.rfind(_VENDOR_PREFIX):]
- if path[0] == "/":
- path = path[1:]
- return path
def _emit_go_compile_action(ctx, sources, deps, libpaths, out_object, gc_goopts):
- """Construct the command line for compiling Go code.
-
- Args:
- ctx: The starlark Context.
- sources: an iterable of source code artifacts (or CTs? or labels?)
- deps: an iterable of dependencies. Each dependency d should have an
- artifact in d.transitive_go_libraries representing all imported libraries.
- libpaths: the set of paths to search for imported libraries.
- out_object: the object file that should be produced
- gc_goopts: additional flags to pass to the compiler.
- """
- if ctx.coverage_instrumented():
- sources = _emit_go_cover_action(ctx, sources)
-
- # Compile filtered files.
- args = [
- "-cgo",
- ctx.file.go_tool.path,
- "tool", "compile",
- "-o", out_object.path,
- "-trimpath", "-abs-.",
- "-I", "-abs-.",
- ]
- inputs = depset(sources + ctx.files.toolchain)
- for dep in deps:
- inputs += dep.transitive_go_libraries
- for path in libpaths:
- args += ["-I", path]
- args += gc_goopts + [("" if i.basename.startswith("_cgo") else "-filter-") + i.path for i in sources]
- ctx.action(
- inputs = list(inputs),
- outputs = [out_object],
- mnemonic = "GoCompile",
- executable = ctx.executable._filter_exec,
- arguments = args,
- env = go_environment_vars(ctx),
- )
-
- return sources
+ """Construct the command line for compiling Go code.
+
+ Args:
+ ctx: The starlark Context.
+ sources: an iterable of source code artifacts (or CTs? or labels?)
+ deps: an iterable of dependencies. Each dependency d should have an
+ artifact in d.transitive_go_libraries representing all imported libraries.
+ libpaths: the set of paths to search for imported libraries.
+ out_object: the object file that should be produced
+ gc_goopts: additional flags to pass to the compiler.
+ """
+ if ctx.coverage_instrumented():
+ sources = _emit_go_cover_action(ctx, sources)
+
+ # Compile filtered files.
+ args = [
+ "-cgo",
+ ctx.file.go_tool.path,
+ "tool",
+ "compile",
+ "-o",
+ out_object.path,
+ "-trimpath",
+ "-abs-.",
+ "-I",
+ "-abs-.",
+ ]
+ inputs = depset(sources + ctx.files.toolchain)
+ for dep in deps:
+ inputs += dep.transitive_go_libraries
+ for path in libpaths:
+ args += ["-I", path]
+ args += gc_goopts + [("" if i.basename.startswith("_cgo") else "-filter-") + i.path for i in sources]
+ ctx.action(
+ inputs = list(inputs),
+ outputs = [out_object],
+ mnemonic = "GoCompile",
+ executable = ctx.executable._filter_exec,
+ arguments = args,
+ env = go_environment_vars(ctx),
+ )
+
+ return sources
def _emit_go_pack_action(ctx, out_lib, objects):
- """Construct the command line for packing objects together.
-
- Args:
- ctx: The starlark Context.
- out_lib: the archive that should be produced
- objects: an iterable of object files to be added to the output archive file.
- """
- ctx.action(
- inputs = objects + ctx.files.toolchain,
- outputs = [out_lib],
- mnemonic = "GoPack",
- executable = ctx.file.go_tool,
- arguments = ["tool", "pack", "c", out_lib.path] + [a.path for a in objects],
- env = go_environment_vars(ctx),
- )
+ """Construct the command line for packing objects together.
-def _emit_go_cover_action(ctx, sources):
- """Construct the command line for test coverage instrument.
-
- Args:
- ctx: The starlark Context.
- sources: an iterable of Go source files.
-
- Returns:
- A list of Go source code files which might be coverage instrumented.
- """
- outputs = []
- # TODO(linuxerwang): make the mode configurable.
- count = 0
-
- for src in sources:
- if not src.path.endswith(".go") or src.path.endswith("_test.go"):
- outputs += [src]
- continue
-
- cover_var = "GoCover_%d" % count
- out = ctx.new_file(src, src.basename[:-3] + '_' + cover_var + '.cover.go')
- outputs += [out]
+ Args:
+ ctx: The starlark Context.
+ out_lib: the archive that should be produced
+ objects: an iterable of object files to be added to the output archive file.
+ """
ctx.action(
- inputs = [src] + ctx.files.toolchain,
- outputs = [out],
- mnemonic = "GoCover",
+ inputs = objects + ctx.files.toolchain,
+ outputs = [out_lib],
+ mnemonic = "GoPack",
executable = ctx.file.go_tool,
- arguments = ["tool", "cover", "--mode=set", "-var=%s" % cover_var, "-o", out.path, src.path],
+ arguments = ["tool", "pack", "c", out_lib.path] + [a.path for a in objects],
env = go_environment_vars(ctx),
)
- count += 1
- return outputs
+def _emit_go_cover_action(ctx, sources):
+ """Construct the command line for test coverage instrument.
+
+ Args:
+ ctx: The starlark Context.
+ sources: an iterable of Go source files.
+
+ Returns:
+ A list of Go source code files which might be coverage instrumented.
+ """
+ outputs = []
+
+ # TODO(linuxerwang): make the mode configurable.
+ count = 0
+
+ for src in sources:
+ if not src.path.endswith(".go") or src.path.endswith("_test.go"):
+ outputs += [src]
+ continue
+
+ cover_var = "GoCover_%d" % count
+ out = ctx.new_file(src, src.basename[:-3] + "_" + cover_var + ".cover.go")
+ outputs += [out]
+ ctx.action(
+ inputs = [src] + ctx.files.toolchain,
+ outputs = [out],
+ mnemonic = "GoCover",
+ executable = ctx.file.go_tool,
+ arguments = ["tool", "cover", "--mode=set", "-var=%s" % cover_var, "-o", out.path, src.path],
+ env = go_environment_vars(ctx),
+ )
+ count += 1
+
+ return outputs
def go_library_impl(ctx):
- """Implements the go_library() rule."""
-
- sources = depset(ctx.files.srcs)
- go_srcs = depset([s for s in sources if s.basename.endswith('.go')])
- asm_srcs = [s for s in sources if s.basename.endswith('.s') or s.basename.endswith('.S')]
- asm_hdrs = [s for s in sources if s.basename.endswith('.h')]
- deps = ctx.attr.deps
- dep_runfiles = [d.data_runfiles for d in deps]
-
- cgo_object = None
- if hasattr(ctx.attr, "cgo_object"):
- cgo_object = ctx.attr.cgo_object
-
- if ctx.attr.library:
- go_srcs += ctx.attr.library.go_sources
- asm_srcs += ctx.attr.library.asm_sources
- asm_hdrs += ctx.attr.library.asm_headers
- deps += ctx.attr.library.direct_deps
- dep_runfiles += [ctx.attr.library.data_runfiles]
- if ctx.attr.library.cgo_object:
- if cgo_object:
- fail("go_library %s cannot have cgo_object because the package " +
- "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")
-
- transitive_cgo_deps = depset([], order="topological")
- if cgo_object:
- dep_runfiles += [cgo_object.data_runfiles]
- transitive_cgo_deps += cgo_object.cgo_deps
-
- extra_objects = [cgo_object.cgo_obj] if cgo_object else []
- for src in asm_srcs:
- obj = ctx.new_file(src, "%s.dir/%s.o" % (ctx.label.name, src.basename[:-2]))
- _emit_go_asm_action(ctx, src, asm_hdrs, obj)
- extra_objects += [obj]
-
- lib_name = _go_importpath(ctx) + ".a"
- out_lib = ctx.new_file(lib_name)
- out_object = ctx.new_file(ctx.label.name + ".o")
- search_path = out_lib.path[:-len(lib_name)]
- gc_goopts = _gc_goopts(ctx)
- transitive_go_libraries = depset([out_lib])
- transitive_go_library_paths = depset([search_path])
- for dep in deps:
- transitive_go_libraries += dep.transitive_go_libraries
- transitive_cgo_deps += dep.transitive_cgo_deps
- transitive_go_library_paths += dep.transitive_go_library_paths
-
- go_srcs = _emit_go_compile_action(ctx,
- sources = go_srcs,
- deps = deps,
- libpaths = transitive_go_library_paths,
- out_object = out_object,
- gc_goopts = gc_goopts,
- )
- _emit_go_pack_action(ctx, out_lib, [out_object] + extra_objects)
-
- dylibs = []
- if cgo_object:
- dylibs += [d for d in cgo_object.cgo_deps if d.path.endswith(".so")]
-
- runfiles = ctx.runfiles(files = dylibs, collect_data = True)
- for d in dep_runfiles:
- runfiles = runfiles.merge(d)
-
- return struct(
- label = ctx.label,
- files = depset([out_lib]),
- runfiles = runfiles,
- go_sources = go_srcs,
- asm_sources = asm_srcs,
- asm_headers = asm_hdrs,
- cgo_object = cgo_object,
- direct_deps = ctx.attr.deps,
- transitive_cgo_deps = transitive_cgo_deps,
- transitive_go_libraries = transitive_go_libraries,
- transitive_go_library_paths = transitive_go_library_paths,
- gc_goopts = gc_goopts,
- )
-
-def _c_linker_options(ctx, blacklist=[]):
- """Extracts flags to pass to $(CC) on link from the current context
-
- Args:
- ctx: the current context
- blacklist: Any flags starts with any of these prefixes are filtered out from
- the return value.
-
- Returns:
- A list of command line flags
- """
- cpp = ctx.fragments.cpp
- features = ctx.features
- options = cpp.compiler_options(features)
- options += cpp.unfiltered_compiler_options(features)
- options += cpp.link_options
- options += cpp.mostly_static_link_options(ctx.features, False)
- filtered = []
- for opt in options:
- if any([opt.startswith(prefix) for prefix in blacklist]):
- continue
- filtered.append(opt)
- return filtered
+ """Implements the go_library() rule."""
+
+ sources = depset(ctx.files.srcs)
+ go_srcs = depset([s for s in sources if s.basename.endswith(".go")])
+ asm_srcs = [s for s in sources if s.basename.endswith(".s") or s.basename.endswith(".S")]
+ asm_hdrs = [s for s in sources if s.basename.endswith(".h")]
+ deps = ctx.attr.deps
+ dep_runfiles = [d.data_runfiles for d in deps]
+
+ cgo_object = None
+ if hasattr(ctx.attr, "cgo_object"):
+ cgo_object = ctx.attr.cgo_object
+
+ if ctx.attr.library:
+ go_srcs += ctx.attr.library.go_sources
+ asm_srcs += ctx.attr.library.asm_sources
+ asm_hdrs += ctx.attr.library.asm_headers
+ deps += ctx.attr.library.direct_deps
+ dep_runfiles += [ctx.attr.library.data_runfiles]
+ if ctx.attr.library.cgo_object:
+ if cgo_object:
+ fail("go_library %s cannot have cgo_object because the package " +
+ "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")
+
+ transitive_cgo_deps = depset([], order = "topological")
+ if cgo_object:
+ dep_runfiles += [cgo_object.data_runfiles]
+ transitive_cgo_deps += cgo_object.cgo_deps
+
+ extra_objects = [cgo_object.cgo_obj] if cgo_object else []
+ for src in asm_srcs:
+ obj = ctx.new_file(src, "%s.dir/%s.o" % (ctx.label.name, src.basename[:-2]))
+ _emit_go_asm_action(ctx, src, asm_hdrs, obj)
+ extra_objects += [obj]
+
+ lib_name = _go_importpath(ctx) + ".a"
+ out_lib = ctx.new_file(lib_name)
+ out_object = ctx.new_file(ctx.label.name + ".o")
+ search_path = out_lib.path[:-len(lib_name)]
+ gc_goopts = _gc_goopts(ctx)
+ transitive_go_libraries = depset([out_lib])
+ transitive_go_library_paths = depset([search_path])
+ for dep in deps:
+ transitive_go_libraries += dep.transitive_go_libraries
+ transitive_cgo_deps += dep.transitive_cgo_deps
+ transitive_go_library_paths += dep.transitive_go_library_paths
+
+ go_srcs = _emit_go_compile_action(
+ ctx,
+ sources = go_srcs,
+ deps = deps,
+ libpaths = transitive_go_library_paths,
+ out_object = out_object,
+ gc_goopts = gc_goopts,
+ )
+ _emit_go_pack_action(ctx, out_lib, [out_object] + extra_objects)
+
+ dylibs = []
+ if cgo_object:
+ dylibs += [d for d in cgo_object.cgo_deps if d.path.endswith(".so")]
+
+ runfiles = ctx.runfiles(files = dylibs, collect_data = True)
+ for d in dep_runfiles:
+ runfiles = runfiles.merge(d)
+
+ return struct(
+ label = ctx.label,
+ files = depset([out_lib]),
+ runfiles = runfiles,
+ go_sources = go_srcs,
+ asm_sources = asm_srcs,
+ asm_headers = asm_hdrs,
+ cgo_object = cgo_object,
+ direct_deps = ctx.attr.deps,
+ transitive_cgo_deps = transitive_cgo_deps,
+ transitive_go_libraries = transitive_go_libraries,
+ transitive_go_library_paths = transitive_go_library_paths,
+ gc_goopts = gc_goopts,
+ )
+
+def _c_linker_options(ctx, blocklist = []):
+ """Extracts flags to pass to $(CC) on link from the current context
+
+ Args:
+ ctx: the current context
+ blocklist: Any flags starts with any of these prefixes are filtered out from
+ the return value.
+
+ Returns:
+ A list of command line flags
+ """
+ cpp = ctx.fragments.cpp
+ features = ctx.features
+ options = cpp.compiler_options(features)
+ options += cpp.unfiltered_compiler_options(features)
+ options += cpp.link_options
+ options += cpp.mostly_static_link_options(ctx.features, False)
+ filtered = []
+ for opt in options:
+ if any([opt.startswith(prefix) for prefix in blocklist]):
+ continue
+ filtered.append(opt)
+ return filtered
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
+ 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
+ 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 _extract_extldflags(gc_linkopts, extldflags):
- """Extracts -extldflags from gc_linkopts and combines them into a single list.
-
- Args:
- gc_linkopts: a list of flags passed in through the gc_linkopts attributes.
- ctx.expand_make_variables should have already been applied.
- extldflags: a list of flags to be passed to the external linker.
-
- Return:
- A tuple containing the filtered gc_linkopts with external flags removed,
- and a combined list of external flags.
- """
- filtered_gc_linkopts = []
- is_extldflags = False
- for opt in gc_linkopts:
- if is_extldflags:
- is_extldflags = False
- extldflags += [opt]
- elif opt == "-extldflags":
- is_extldflags = True
- else:
- filtered_gc_linkopts += [opt]
- return filtered_gc_linkopts, extldflags
-
-def _emit_go_link_action(ctx, transitive_go_library_paths, transitive_go_libraries, cgo_deps, libs,
- executable, gc_linkopts):
- """Sets up a symlink tree to libraries to link together."""
- config_strip = len(ctx.configuration.bin_dir.path) + 1
- pkg_depth = executable.dirname[config_strip:].count('/') + 1
-
- ld = "%s" % ctx.fragments.cpp.compiler_executable
- extldflags = _c_linker_options(ctx) + [
- "-Wl,-rpath,$ORIGIN/" + ("../" * pkg_depth),
- ]
- for d in cgo_deps:
- if d.basename.endswith('.so'):
- short_dir = d.dirname[len(d.root.path):]
- extldflags += ["-Wl,-rpath,$ORIGIN/" + ("../" * pkg_depth) + short_dir]
- gc_linkopts, extldflags = _extract_extldflags(gc_linkopts, extldflags)
-
- link_cmd = [
- ctx.file.go_tool.path,
- "tool", "link",
- "-L", "."
- ]
- for path in transitive_go_library_paths:
- link_cmd += ["-L", path]
- link_cmd += [
- "-o", executable.path,
- ] + 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
- # TODO(yugui) Remove this workaround once rules_go stops supporting XCode 7.2
- # or earlier.
- if not _is_darwin_cpu(ctx):
- link_cmd += ["-s"]
-
- link_cmd += [
- "-extld", ld,
- "-extldflags", "'%s'" % " ".join(extldflags),
- ] + [lib.path for lib in libs]
-
- # Avoided -s on OSX but but it requires dsymutil to be on $PATH.
- # TODO(yugui) Remove this workaround once rules_go stops supporting XCode 7.2
- # or earlier.
- cmds = ["export PATH=$PATH:/usr/bin"]
-
- cmds += [
- "STAMP_XDEFS=()",
- ]
-
- stamp_inputs = []
- if ctx.attr.linkstamp:
- # read workspace status files, converting "KEY value" lines
- # to "-X $linkstamp.KEY=value" arguments to the go linker.
- stamp_inputs = [ctx.info_file, ctx.version_file]
- for f in stamp_inputs:
- cmds += [
- "while read -r key value || [[ -n $key ]]; do",
- " STAMP_XDEFS+=(-X \"%s.$key=$value\")" % ctx.attr.linkstamp,
- "done < " + f.path,
- ]
-
- cmds += [' '.join(link_cmd)]
-
- f = _emit_generate_params_action(cmds, ctx, lib.basename + ".GoLinkFile.params")
-
- ctx.action(
- inputs = [f] + (list(transitive_go_libraries) + [lib] + list(cgo_deps) +
- ctx.files.toolchain + ctx.files._crosstool) + stamp_inputs,
- outputs = [executable],
- command = f.path,
- mnemonic = "GoLink",
- env = go_environment_vars(ctx),
- )
+ """Extracts -extldflags from gc_linkopts and combines them into a single list.
+
+ Args:
+ gc_linkopts: a list of flags passed in through the gc_linkopts attributes.
+ ctx.expand_make_variables should have already been applied.
+ extldflags: a list of flags to be passed to the external linker.
+
+ Return:
+ A tuple containing the filtered gc_linkopts with external flags removed,
+ and a combined list of external flags.
+ """
+ filtered_gc_linkopts = []
+ is_extldflags = False
+ for opt in gc_linkopts:
+ if is_extldflags:
+ is_extldflags = False
+ extldflags += [opt]
+ elif opt == "-extldflags":
+ is_extldflags = True
+ else:
+ filtered_gc_linkopts += [opt]
+ return filtered_gc_linkopts, extldflags
+
+def _emit_go_link_action(
+ ctx,
+ transitive_go_library_paths,
+ transitive_go_libraries,
+ cgo_deps,
+ libs,
+ executable,
+ gc_linkopts):
+ """Sets up a symlink tree to libraries to link together."""
+ config_strip = len(ctx.configuration.bin_dir.path) + 1
+ pkg_depth = executable.dirname[config_strip:].count("/") + 1
+
+ ld = "%s" % ctx.fragments.cpp.compiler_executable
+ extldflags = _c_linker_options(ctx) + [
+ "-Wl,-rpath,$ORIGIN/" + ("../" * pkg_depth),
+ ]
+ for d in cgo_deps:
+ if d.basename.endswith(".so"):
+ short_dir = d.dirname[len(d.root.path):]
+ extldflags += ["-Wl,-rpath,$ORIGIN/" + ("../" * pkg_depth) + short_dir]
+ gc_linkopts, extldflags = _extract_extldflags(gc_linkopts, extldflags)
+
+ link_cmd = [
+ ctx.file.go_tool.path,
+ "tool",
+ "link",
+ "-L",
+ ".",
+ ]
+ for path in transitive_go_library_paths:
+ link_cmd += ["-L", path]
+ link_cmd += [
+ "-o",
+ executable.path,
+ ] + 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
+ # TODO(yugui) Remove this workaround once rules_go stops supporting XCode 7.2
+ # or earlier.
+ if not _is_darwin_cpu(ctx):
+ link_cmd += ["-s"]
+
+ link_cmd += [
+ "-extld",
+ ld,
+ "-extldflags",
+ "'%s'" % " ".join(extldflags),
+ ] + [lib.path for lib in libs]
+
+ # Avoided -s on OSX but but it requires dsymutil to be on $PATH.
+ # TODO(yugui) Remove this workaround once rules_go stops supporting XCode 7.2
+ # or earlier.
+ cmds = ["export PATH=$PATH:/usr/bin"]
+
+ cmds += [
+ "STAMP_XDEFS=()",
+ ]
+
+ stamp_inputs = []
+ if ctx.attr.linkstamp:
+ # read workspace status files, converting "KEY value" lines
+ # to "-X $linkstamp.KEY=value" arguments to the go linker.
+ stamp_inputs = [ctx.info_file, ctx.version_file]
+ for f in stamp_inputs:
+ cmds += [
+ "while read -r key value || [[ -n $key ]]; do",
+ " STAMP_XDEFS+=(-X \"%s.$key=$value\")" % ctx.attr.linkstamp,
+ "done < " + f.path,
+ ]
+
+ cmds += [" ".join(link_cmd)]
+
+ f = _emit_generate_params_action(cmds, ctx, lib.basename + ".GoLinkFile.params")
+
+ ctx.action(
+ inputs = [f] + (list(transitive_go_libraries) + [lib] + list(cgo_deps) +
+ ctx.files.toolchain + ctx.files._crosstool) + stamp_inputs,
+ outputs = [executable],
+ command = f.path,
+ mnemonic = "GoLink",
+ env = go_environment_vars(ctx),
+ )
def go_binary_impl(ctx):
- """go_binary_impl emits actions for compiling and linking a go executable."""
- lib_result = go_library_impl(ctx)
- _emit_go_link_action(
- ctx,
- transitive_go_libraries=lib_result.transitive_go_libraries,
- transitive_go_library_paths=lib_result.transitive_go_library_paths,
- cgo_deps=lib_result.transitive_cgo_deps,
- libs=lib_result.files,
- executable=ctx.outputs.executable,
- gc_linkopts=_gc_linkopts(ctx))
-
- return struct(
- files = depset([ctx.outputs.executable]),
- runfiles = lib_result.runfiles,
- cgo_object = lib_result.cgo_object,
- )
+ """go_binary_impl emits actions for compiling and linking a go executable."""
+ lib_result = go_library_impl(ctx)
+ _emit_go_link_action(
+ ctx,
+ transitive_go_libraries = lib_result.transitive_go_libraries,
+ transitive_go_library_paths = lib_result.transitive_go_library_paths,
+ cgo_deps = lib_result.transitive_cgo_deps,
+ libs = lib_result.files,
+ executable = ctx.outputs.executable,
+ gc_linkopts = _gc_linkopts(ctx),
+ )
+
+ return struct(
+ files = depset([ctx.outputs.executable]),
+ runfiles = lib_result.runfiles,
+ cgo_object = lib_result.cgo_object,
+ )
def go_test_impl(ctx):
- """go_test_impl implements go testing.
-
- It emits an action to run the test generator, and then compiles the
- test into a binary."""
-
- lib_result = go_library_impl(ctx)
- main_go = ctx.new_file(ctx.label.name + "_main_test.go")
- main_object = ctx.new_file(ctx.label.name + "_main_test.o")
- main_lib = ctx.new_file(ctx.label.name + "_main_test.a")
- go_import = _go_importpath(ctx)
-
- cmds = [
- 'UNFILTERED_TEST_FILES=(%s)' %
- ' '.join(["'%s'" % f.path for f in lib_result.go_sources]),
- 'FILTERED_TEST_FILES=()',
- 'while read -r line; do',
- ' if [ -n "$line" ]; then',
- ' FILTERED_TEST_FILES+=("$line")',
- ' fi',
- 'done < <(\'%s\' -cgo "${UNFILTERED_TEST_FILES[@]}")' %
- ctx.executable._filter_tags.path,
- ' '.join([
- "'%s'" % ctx.executable.test_generator.path,
- '--package',
- go_import,
- '--output',
- "'%s'" % main_go.path,
- '"${FILTERED_TEST_FILES[@]}"',
- ]),
- ]
- f = _emit_generate_params_action(
- cmds, ctx, ctx.label.name + ".GoTestGenTest.params")
- inputs = (list(lib_result.go_sources) + list(ctx.files.toolchain) +
- [f, ctx.executable._filter_tags, ctx.executable.test_generator])
- ctx.action(
- inputs = inputs,
- outputs = [main_go],
- command = f.path,
- mnemonic = "GoTestGenTest",
- env = dict(go_environment_vars(ctx), RUNDIR=ctx.label.package))
-
- _emit_go_compile_action(
- ctx,
- sources=depset([main_go]),
- deps=ctx.attr.deps + [lib_result],
- libpaths=lib_result.transitive_go_library_paths,
- out_object=main_object,
- gc_goopts=_gc_goopts(ctx),
- )
- _emit_go_pack_action(ctx, main_lib, [main_object])
- _emit_go_link_action(
- ctx,
- transitive_go_library_paths=lib_result.transitive_go_library_paths,
- transitive_go_libraries=lib_result.transitive_go_libraries,
- cgo_deps=lib_result.transitive_cgo_deps,
- libs=[main_lib],
- executable=ctx.outputs.executable,
- 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
- # without code changes.
- runfiles = ctx.runfiles(files = [ctx.outputs.executable])
- runfiles = runfiles.merge(lib_result.runfiles)
- return struct(
- files = depset([ctx.outputs.executable]),
- runfiles = runfiles,
- )
+ """go_test_impl implements go testing.
+
+ It emits an action to run the test generator, and then compiles the
+ test into a binary."""
+
+ lib_result = go_library_impl(ctx)
+ main_go = ctx.new_file(ctx.label.name + "_main_test.go")
+ main_object = ctx.new_file(ctx.label.name + "_main_test.o")
+ main_lib = ctx.new_file(ctx.label.name + "_main_test.a")
+ go_import = _go_importpath(ctx)
+
+ cmds = [
+ "UNFILTERED_TEST_FILES=(%s)" %
+ " ".join(["'%s'" % f.path for f in lib_result.go_sources]),
+ "FILTERED_TEST_FILES=()",
+ "while read -r line; do",
+ ' if [ -n "$line" ]; then',
+ ' FILTERED_TEST_FILES+=("$line")',
+ " fi",
+ 'done < <(\'%s\' -cgo "${UNFILTERED_TEST_FILES[@]}")' %
+ ctx.executable._filter_tags.path,
+ " ".join([
+ "'%s'" % ctx.executable.test_generator.path,
+ "--package",
+ go_import,
+ "--output",
+ "'%s'" % main_go.path,
+ '"${FILTERED_TEST_FILES[@]}"',
+ ]),
+ ]
+ f = _emit_generate_params_action(
+ cmds,
+ ctx,
+ ctx.label.name + ".GoTestGenTest.params",
+ )
+ inputs = (list(lib_result.go_sources) + list(ctx.files.toolchain) +
+ [f, ctx.executable._filter_tags, ctx.executable.test_generator])
+ ctx.action(
+ inputs = inputs,
+ outputs = [main_go],
+ command = f.path,
+ mnemonic = "GoTestGenTest",
+ env = dict(go_environment_vars(ctx), RUNDIR = ctx.label.package),
+ )
+
+ _emit_go_compile_action(
+ ctx,
+ sources = depset([main_go]),
+ deps = ctx.attr.deps + [lib_result],
+ libpaths = lib_result.transitive_go_library_paths,
+ out_object = main_object,
+ gc_goopts = _gc_goopts(ctx),
+ )
+ _emit_go_pack_action(ctx, main_lib, [main_object])
+ _emit_go_link_action(
+ ctx,
+ transitive_go_library_paths = lib_result.transitive_go_library_paths,
+ transitive_go_libraries = lib_result.transitive_go_libraries,
+ cgo_deps = lib_result.transitive_cgo_deps,
+ libs = [main_lib],
+ executable = ctx.outputs.executable,
+ 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
+ # without code changes.
+ runfiles = ctx.runfiles(files = [ctx.outputs.executable])
+ runfiles = runfiles.merge(lib_result.runfiles)
+ return struct(
+ files = depset([ctx.outputs.executable]),
+ runfiles = runfiles,
+ )
go_env_attrs = {
"toolchain": attr.label(
@@ -704,51 +734,51 @@ go_test = rule(
)
def _pkg_dir(workspace_root, package_name):
- if workspace_root and package_name:
- return workspace_root + "/" + package_name
- if workspace_root:
- return workspace_root
- if package_name:
- return package_name
- return "."
+ if workspace_root and package_name:
+ return workspace_root + "/" + package_name
+ if workspace_root:
+ return workspace_root
+ if package_name:
+ return package_name
+ return "."
def _exec_path(path):
- if path.startswith('/'):
- return path
- return '${execroot}/' + path
+ if path.startswith("/"):
+ return path
+ return "${execroot}/" + path
def _cgo_filter_srcs_impl(ctx):
- srcs = ctx.files.srcs
- dsts = []
- cmds = []
- for src in srcs:
- stem, _, ext = src.path.rpartition('.')
- dst_basename = "%s.filtered.%s" % (stem, ext)
- dst = ctx.new_file(src, dst_basename)
- cmds += [
- "if '%s' -cgo -quiet '%s'; then" %
+ srcs = ctx.files.srcs
+ dsts = []
+ cmds = []
+ for src in srcs:
+ stem, _, ext = src.path.rpartition(".")
+ dst_basename = "%s.filtered.%s" % (stem, ext)
+ dst = ctx.new_file(src, dst_basename)
+ cmds += [
+ "if '%s' -cgo -quiet '%s'; then" %
(ctx.executable._filter_tags.path, src.path),
- " cp '%s' '%s'" % (src.path, dst.path),
- "else",
- " echo -n >'%s'" % dst.path,
- "fi",
- ]
- dsts.append(dst)
-
- if ctx.label.package == "":
- script_name = ctx.label.name + ".CGoFilterSrcs.params"
- else:
- script_name = ctx.label.package + "/" + ctx.label.name + ".CGoFilterSrcs.params"
- f = _emit_generate_params_action(cmds, ctx, script_name)
- ctx.action(
- inputs = [f, ctx.executable._filter_tags] + srcs,
- outputs = dsts,
- command = f.path,
- mnemonic = "CgoFilterSrcs",
- )
- return struct(
- files = depset(dsts),
- )
+ " cp '%s' '%s'" % (src.path, dst.path),
+ "else",
+ " echo -n >'%s'" % dst.path,
+ "fi",
+ ]
+ dsts.append(dst)
+
+ if ctx.label.package == "":
+ script_name = ctx.label.name + ".CGoFilterSrcs.params"
+ else:
+ script_name = ctx.label.package + "/" + ctx.label.name + ".CGoFilterSrcs.params"
+ f = _emit_generate_params_action(cmds, ctx, script_name)
+ ctx.action(
+ inputs = [f, ctx.executable._filter_tags] + srcs,
+ outputs = dsts,
+ command = f.path,
+ mnemonic = "CgoFilterSrcs",
+ )
+ return struct(
+ files = depset(dsts),
+ )
_cgo_filter_srcs = rule(
implementation = _cgo_filter_srcs_impl,
@@ -767,90 +797,90 @@ _cgo_filter_srcs = rule(
)
def _cgo_codegen_impl(ctx):
- go_srcs = ctx.files.srcs
- srcs = go_srcs + ctx.files.c_hdrs
- linkopts = ctx.attr.linkopts
- copts = ctx.fragments.cpp.c_options + ctx.attr.copts
- deps = depset([], order="topological")
- for d in ctx.attr.deps:
- srcs += list(d.cc.transitive_headers)
- deps += d.cc.libs
- copts += ['-D' + define for define in d.cc.defines]
- for inc in d.cc.include_directories:
- copts += ['-I', _exec_path(inc)]
- for hdr in ctx.files.c_hdrs:
- copts += ['-iquote', hdr.dirname]
- for inc in d.cc.quote_include_directories:
- copts += ['-iquote', _exec_path(inc)]
- for inc in d.cc.system_include_directories:
- copts += ['-isystem', _exec_path(inc)]
- for lib in d.cc.libs:
- if lib.basename.startswith('lib') and lib.basename.endswith('.so'):
- linkopts += ['-L', lib.dirname, '-l', lib.basename[3:-3]]
- else:
- linkopts += [lib.path]
- linkopts += d.cc.link_flags
-
- p = _pkg_dir(ctx.label.workspace_root, ctx.label.package) + "/"
- if p == "./":
- p = "" # workaround when cgo_library in repository root
- out_dir = (ctx.configuration.genfiles_dir.path + '/' +
- p + ctx.attr.outdir)
- cc = ctx.fragments.cpp.compiler_executable
- cmds = [
- # We cannot use env for CC because $(CC) on OSX is relative
- # and '../' does not work fine due to symlinks.
- 'export CC=$(cd $(dirname {cc}); pwd)/$(basename {cc})'.format(cc=cc),
- 'export CXX=$CC',
- 'objdir="%s/gen"' % out_dir,
- 'execroot=$(pwd)',
- 'mkdir -p "$objdir"',
- 'unfiltered_go_files=(%s)' % ' '.join(["'%s'" % f.path for f in go_srcs]),
- 'filtered_go_files=()',
- 'for file in "${unfiltered_go_files[@]}"; do',
- ' stem=$(basename "$file" .go)',
- ' if %s -cgo -quiet "$file"; then' % ctx.executable._filter_tags.path,
- ' filtered_go_files+=("$file")',
- ' else',
- ' grep --max-count 1 "^package " "$file" >"$objdir/$stem.go"',
- ' echo -n >"$objdir/$stem.c"',
- ' fi',
- 'done',
- 'if [ ${#filtered_go_files[@]} -eq 0 ]; then',
- ' echo no buildable Go source files in %s >&1' % str(ctx.label),
- ' exit 1',
- 'fi',
- '"$GOROOT/bin/go" tool cgo -objdir "$objdir" -- %s "${filtered_go_files[@]}"' %
- ' '.join(['"%s"' % copt for copt in copts]),
- # Rename the outputs using glob so we don't have to understand cgo's mangling
- # TODO(#350): might be fixed by this?.
- 'for file in "${filtered_go_files[@]}"; do',
- ' stem=$(basename "$file" .go)',
- ' mv "$objdir/"*"$stem.cgo1.go" "$objdir/$stem.go"',
- ' mv "$objdir/"*"$stem.cgo2.c" "$objdir/$stem.c"',
- 'done',
- 'rm -f $objdir/_cgo_.o $objdir/_cgo_flags',
+ go_srcs = ctx.files.srcs
+ srcs = go_srcs + ctx.files.c_hdrs
+ linkopts = ctx.attr.linkopts
+ copts = ctx.fragments.cpp.c_options + ctx.attr.copts
+ deps = depset([], order = "topological")
+ for d in ctx.attr.deps:
+ srcs += list(d.cc.transitive_headers)
+ deps += d.cc.libs
+ copts += ["-D" + define for define in d.cc.defines]
+ for inc in d.cc.include_directories:
+ copts += ["-I", _exec_path(inc)]
+ for hdr in ctx.files.c_hdrs:
+ copts += ["-iquote", hdr.dirname]
+ for inc in d.cc.quote_include_directories:
+ copts += ["-iquote", _exec_path(inc)]
+ for inc in d.cc.system_include_directories:
+ copts += ["-isystem", _exec_path(inc)]
+ for lib in d.cc.libs:
+ if lib.basename.startswith("lib") and lib.basename.endswith(".so"):
+ linkopts += ["-L", lib.dirname, "-l", lib.basename[3:-3]]
+ else:
+ linkopts += [lib.path]
+ linkopts += d.cc.link_flags
+
+ p = _pkg_dir(ctx.label.workspace_root, ctx.label.package) + "/"
+ if p == "./":
+ p = "" # workaround when cgo_library in repository root
+ out_dir = (ctx.configuration.genfiles_dir.path + "/" +
+ p + ctx.attr.outdir)
+ cc = ctx.fragments.cpp.compiler_executable
+ cmds = [
+ # We cannot use env for CC because $(CC) on OSX is relative
+ # and '../' does not work fine due to symlinks.
+ "export CC=$(cd $(dirname {cc}); pwd)/$(basename {cc})".format(cc = cc),
+ "export CXX=$CC",
+ 'objdir="%s/gen"' % out_dir,
+ "execroot=$(pwd)",
+ 'mkdir -p "$objdir"',
+ "unfiltered_go_files=(%s)" % " ".join(["'%s'" % f.path for f in go_srcs]),
+ "filtered_go_files=()",
+ 'for file in "${unfiltered_go_files[@]}"; do',
+ ' stem=$(basename "$file" .go)',
+ ' if %s -cgo -quiet "$file"; then' % ctx.executable._filter_tags.path,
+ ' filtered_go_files+=("$file")',
+ " else",
+ ' grep --max-count 1 "^package " "$file" >"$objdir/$stem.go"',
+ ' echo -n >"$objdir/$stem.c"',
+ " fi",
+ "done",
+ "if [ ${#filtered_go_files[@]} -eq 0 ]; then",
+ " echo no buildable Go source files in %s >&1" % str(ctx.label),
+ " exit 1",
+ "fi",
+ '"$GOROOT/bin/go" tool cgo -objdir "$objdir" -- %s "${filtered_go_files[@]}"' %
+ " ".join(['"%s"' % copt for copt in copts]),
+ # Rename the outputs using glob so we don't have to understand cgo's mangling
+ # TODO(#350): might be fixed by this?.
+ 'for file in "${filtered_go_files[@]}"; do',
+ ' stem=$(basename "$file" .go)',
+ ' mv "$objdir/"*"$stem.cgo1.go" "$objdir/$stem.go"',
+ ' mv "$objdir/"*"$stem.cgo2.c" "$objdir/$stem.c"',
+ "done",
+ "rm -f $objdir/_cgo_.o $objdir/_cgo_flags",
]
- f = _emit_generate_params_action(cmds, ctx, out_dir + ".CGoCodeGenFile.params")
-
- inputs = (srcs + ctx.files.toolchain + ctx.files._crosstool +
- [f, ctx.executable._filter_tags])
- ctx.action(
- inputs = inputs,
- outputs = ctx.outputs.outs,
- mnemonic = "CGoCodeGen",
- progress_message = "CGoCodeGen %s" % ctx.label,
- command = f.path,
- env = go_environment_vars(ctx) + {
- "CGO_LDFLAGS": " ".join(linkopts),
- },
- )
- return struct(
- label = ctx.label,
- files = depset(ctx.outputs.outs),
- cgo_deps = deps,
- )
+ f = _emit_generate_params_action(cmds, ctx, out_dir + ".CGoCodeGenFile.params")
+
+ inputs = (srcs + ctx.files.toolchain + ctx.files._crosstool +
+ [f, ctx.executable._filter_tags])
+ ctx.action(
+ inputs = inputs,
+ outputs = ctx.outputs.outs,
+ mnemonic = "CGoCodeGen",
+ progress_message = "CGoCodeGen %s" % ctx.label,
+ command = f.path,
+ env = go_environment_vars(ctx) + {
+ "CGO_LDFLAGS": " ".join(linkopts),
+ },
+ )
+ return struct(
+ label = ctx.label,
+ files = depset(ctx.outputs.outs),
+ cgo_deps = deps,
+ )
_cgo_codegen_rule = rule(
_cgo_codegen_impl,
@@ -878,91 +908,102 @@ _cgo_codegen_rule = rule(
output_to_genfiles = True,
)
-def _cgo_codegen(name, srcs, c_hdrs=[], deps=[], copts=[], linkopts=[],
- go_tool=None, toolchain=None):
- """Generates glue codes for interop between C and Go
-
- Args:
- name: A unique name of the rule
- srcs: list of Go source files.
- Each of them must contain `import "C"`.
- c_hdrs: C/C++ header files necessary to determine kinds of
- C/C++ identifiers in srcs.
- deps: A list of cc_library rules.
- The generated codes are expected to be linked with these deps.
- linkopts: A list of linker options,
- These flags are passed to the linker when the generated codes
- are linked into the target binary.
- """
- outdir = name + ".dir"
- outgen = outdir + "/gen"
-
- go_thunks = []
- c_thunks = []
- for s in srcs:
- if not s.endswith('.go'):
- fail("not a .go file: %s" % s)
- basename = s[:-3]
- if basename.rfind("/") >= 0:
- basename = basename[basename.rfind("/")+1:]
- go_thunks.append(outgen + "/" + basename + ".go")
- c_thunks.append(outgen + "/" + basename + ".c")
-
- outs = struct(
- name = name,
-
- outdir = outgen,
- go_thunks = go_thunks,
- c_thunks = c_thunks,
- c_exports = [
- outgen + "/_cgo_export.c",
- outgen + "/_cgo_export.h",
- ],
- c_dummy = outgen + "/_cgo_main.c",
- gotypes = outgen + "/_cgo_gotypes.go",
- )
-
- _cgo_codegen_rule(
- name = name,
- srcs = srcs,
- c_hdrs = c_hdrs,
- deps = deps,
- copts = copts,
- linkopts = linkopts,
-
- go_tool = go_tool,
- toolchain = toolchain,
-
- outdir = outdir,
- outs = outs.go_thunks + outs.c_thunks + outs.c_exports + [
- outs.c_dummy, outs.gotypes,
- ],
-
- visibility = ["//visibility:private"],
- )
- return outs
+def _cgo_codegen(
+ name,
+ srcs,
+ c_hdrs = [],
+ deps = [],
+ copts = [],
+ linkopts = [],
+ go_tool = None,
+ toolchain = None):
+ """Generates glue codes for interop between C and Go
+
+ Args:
+ name: A unique name of the rule
+ srcs: list of Go source files.
+ Each of them must contain `import "C"`.
+ c_hdrs: C/C++ header files necessary to determine kinds of
+ C/C++ identifiers in srcs.
+ deps: A list of cc_library rules.
+ The generated codes are expected to be linked with these deps.
+ linkopts: A list of linker options,
+ These flags are passed to the linker when the generated codes
+ are linked into the target binary.
+ """
+ outdir = name + ".dir"
+ outgen = outdir + "/gen"
+
+ go_thunks = []
+ c_thunks = []
+ for s in srcs:
+ if not s.endswith(".go"):
+ fail("not a .go file: %s" % s)
+ basename = s[:-3]
+ if basename.rfind("/") >= 0:
+ basename = basename[basename.rfind("/") + 1:]
+ go_thunks.append(outgen + "/" + basename + ".go")
+ c_thunks.append(outgen + "/" + basename + ".c")
+
+ outs = struct(
+ name = name,
+ outdir = outgen,
+ go_thunks = go_thunks,
+ c_thunks = c_thunks,
+ c_exports = [
+ outgen + "/_cgo_export.c",
+ outgen + "/_cgo_export.h",
+ ],
+ c_dummy = outgen + "/_cgo_main.c",
+ gotypes = outgen + "/_cgo_gotypes.go",
+ )
+
+ _cgo_codegen_rule(
+ name = name,
+ srcs = srcs,
+ c_hdrs = c_hdrs,
+ deps = deps,
+ copts = copts,
+ linkopts = linkopts,
+ go_tool = go_tool,
+ toolchain = toolchain,
+ outdir = outdir,
+ outs = outs.go_thunks + outs.c_thunks + outs.c_exports + [
+ outs.c_dummy,
+ outs.gotypes,
+ ],
+ visibility = ["//visibility:private"],
+ )
+ return outs
def _cgo_import_impl(ctx):
- cmds = [
- (ctx.file.go_tool.path + " tool cgo" +
- " -dynout " + ctx.outputs.out.path +
- " -dynimport " + ctx.file.cgo_o.path +
- " -dynpackage $(%s %s)" % (ctx.executable._extract_package.path,
- ctx.file.sample_go_src.path)),
- ]
- f = _emit_generate_params_action(cmds, ctx, ctx.outputs.out.path + ".CGoImportGenFile.params")
- ctx.action(
- inputs = (ctx.files.toolchain +
- [f, ctx.file.go_tool, ctx.executable._extract_package,
- ctx.file.cgo_o, ctx.file.sample_go_src]),
- outputs = [ctx.outputs.out],
- command = f.path,
- mnemonic = "CGoImportGen",
- env = go_environment_vars(ctx),
- )
- return struct(
- files = depset([ctx.outputs.out]),
- )
+ cmds = [
+ (ctx.file.go_tool.path + " tool cgo" +
+ " -dynout " + ctx.outputs.out.path +
+ " -dynimport " + ctx.file.cgo_o.path +
+ " -dynpackage $(%s %s)" % (
+ ctx.executable._extract_package.path,
+ ctx.file.sample_go_src.path,
+ )),
+ ]
+ f = _emit_generate_params_action(cmds, ctx, ctx.outputs.out.path + ".CGoImportGenFile.params")
+ ctx.action(
+ inputs = (ctx.files.toolchain +
+ [
+ f,
+ ctx.file.go_tool,
+ ctx.executable._extract_package,
+ ctx.file.cgo_o,
+ ctx.file.sample_go_src,
+ ]),
+ outputs = [ctx.outputs.out],
+ command = f.path,
+ mnemonic = "CGoImportGen",
+ env = go_environment_vars(ctx),
+ )
+ return struct(
+ files = depset([ctx.outputs.out]),
+ )
_cgo_import = rule(
_cgo_import_impl,
@@ -988,15 +1029,15 @@ _cgo_import = rule(
)
def _cgo_genrule_impl(ctx):
- return struct(
- label = ctx.label,
- go_sources = ctx.files.srcs,
- asm_sources = [],
- asm_headers = [],
- cgo_object = ctx.attr.cgo_object,
- direct_deps = ctx.attr.deps,
- gc_goopts = [],
- )
+ return struct(
+ label = ctx.label,
+ go_sources = ctx.files.srcs,
+ asm_sources = [],
+ asm_headers = [],
+ cgo_object = ctx.attr.cgo_object,
+ direct_deps = ctx.attr.deps,
+ gc_goopts = [],
+ )
_cgo_genrule = rule(
_cgo_genrule_impl,
@@ -1030,40 +1071,43 @@ Args:
"""
def _cgo_object_impl(ctx):
- arguments = _c_linker_options(ctx, blacklist=[
- # never link any dependency libraries
- "-l", "-L",
- # manage flags to ld(1) by ourselves
- "-Wl,"])
- arguments += [
- "-o", ctx.outputs.out.path,
- "-nostdlib",
- "-Wl,-r",
- ]
- if _is_darwin_cpu(ctx):
- arguments += ["-shared", "-Wl,-all_load"]
- else:
- arguments += ["-Wl,-whole-archive"]
-
- lo = ctx.files.src[-1]
- arguments += [lo.path]
-
- ctx.action(
- inputs = [lo] + ctx.files._crosstool,
- outputs = [ctx.outputs.out],
- mnemonic = "CGoObject",
- progress_message = "Linking %s" % ctx.outputs.out.short_path,
- executable = ctx.fragments.cpp.compiler_executable,
- arguments = arguments,
- )
- runfiles = ctx.runfiles(collect_data = True)
- runfiles = runfiles.merge(ctx.attr.src.data_runfiles)
- return struct(
- files = depset([ctx.outputs.out]),
- cgo_obj = ctx.outputs.out,
- cgo_deps = ctx.attr.cgogen.cgo_deps,
- runfiles = runfiles,
- )
+ arguments = _c_linker_options(ctx, blocklist = [
+ # never link any dependency libraries
+ "-l",
+ "-L",
+ # manage flags to ld(1) by ourselves
+ "-Wl,",
+ ])
+ arguments += [
+ "-o",
+ ctx.outputs.out.path,
+ "-nostdlib",
+ "-Wl,-r",
+ ]
+ if _is_darwin_cpu(ctx):
+ arguments += ["-shared", "-Wl,-all_load"]
+ else:
+ arguments += ["-Wl,-whole-archive"]
+
+ lo = ctx.files.src[-1]
+ arguments += [lo.path]
+
+ ctx.action(
+ inputs = [lo] + ctx.files._crosstool,
+ outputs = [ctx.outputs.out],
+ mnemonic = "CGoObject",
+ progress_message = "Linking %s" % ctx.outputs.out.short_path,
+ executable = ctx.fragments.cpp.compiler_executable,
+ arguments = arguments,
+ )
+ runfiles = ctx.runfiles(collect_data = True)
+ runfiles = runfiles.merge(ctx.attr.src.data_runfiles)
+ return struct(
+ files = depset([ctx.outputs.out]),
+ cgo_obj = ctx.outputs.out,
+ cgo_deps = ctx.attr.cgogen.cgo_deps,
+ runfiles = runfiles,
+ )
_cgo_object = rule(
_cgo_object_impl,
@@ -1092,182 +1136,189 @@ Args:
"""
def _setup_cgo_library(name, srcs, cdeps, copts, clinkopts, go_tool, toolchain):
- go_srcs = [s for s in srcs if s.endswith('.go')]
- c_hdrs = [s for s in srcs if any([s.endswith(ext) for ext in hdr_exts])]
- c_srcs = [s for s in srcs if not s in (go_srcs + c_hdrs)]
-
- # Split cgo files into .go parts and .c parts (plus some other files).
- cgogen = _cgo_codegen(
- name = name + ".cgo",
- srcs = go_srcs,
- c_hdrs = c_hdrs,
- deps = cdeps,
- copts = copts,
- linkopts = clinkopts,
- go_tool = go_tool,
- toolchain = toolchain,
- )
-
- # Filter c_srcs with build constraints.
- c_filtered_srcs = []
- if len(c_srcs) > 0:
- c_filtered_srcs_name = name + "_filter_cgo_srcs"
- _cgo_filter_srcs(
- name = c_filtered_srcs_name,
- srcs = c_srcs,
+ go_srcs = [s for s in srcs if s.endswith(".go")]
+ c_hdrs = [s for s in srcs if any([s.endswith(ext) for ext in hdr_exts])]
+ c_srcs = [s for s in srcs if not s in (go_srcs + c_hdrs)]
+
+ # Split cgo files into .go parts and .c parts (plus some other files).
+ cgogen = _cgo_codegen(
+ name = name + ".cgo",
+ srcs = go_srcs,
+ c_hdrs = c_hdrs,
+ deps = cdeps,
+ copts = copts,
+ linkopts = clinkopts,
+ go_tool = go_tool,
+ toolchain = toolchain,
+ )
+
+ # Filter c_srcs with build constraints.
+ c_filtered_srcs = []
+ if len(c_srcs) > 0:
+ c_filtered_srcs_name = name + "_filter_cgo_srcs"
+ _cgo_filter_srcs(
+ name = c_filtered_srcs_name,
+ srcs = c_srcs,
+ )
+ c_filtered_srcs.append(":" + c_filtered_srcs_name)
+
+ pkg_dir = _pkg_dir(
+ "external/" + REPOSITORY_NAME[1:] if len(REPOSITORY_NAME) > 1 else "",
+ PACKAGE_NAME,
+ )
+
+ # Platform-specific settings
+ native.config_setting(
+ name = name + "_windows_setting",
+ values = {
+ "cpu": "x64_windows_msvc",
+ },
+ )
+ platform_copts = select({
+ ":" + name + "_windows_setting": ["-mthreads"],
+ "//conditions:default": ["-pthread"],
+ })
+ platform_linkopts = select({
+ ":" + name + "_windows_setting": ["-mthreads"],
+ "//conditions:default": ["-pthread"],
+ })
+
+ # Bundles objects into an archive so that _cgo_.o and _all.o can share them.
+ native.cc_library(
+ name = cgogen.outdir + "/_cgo_lib",
+ srcs = cgogen.c_thunks + cgogen.c_exports + c_filtered_srcs + c_hdrs,
+ deps = cdeps,
+ copts = copts + platform_copts + [
+ "-I",
+ pkg_dir,
+ "-I",
+ "$(GENDIR)/" + pkg_dir + "/" + cgogen.outdir,
+ # The generated thunks often contain unused variables.
+ "-Wno-unused-variable",
+ ],
+ linkopts = clinkopts + platform_linkopts,
+ linkstatic = 1,
+ # _cgo_.o and _all.o keep all objects in this archive.
+ # But it should not be very annoying in the final binary target
+ # because _cgo_object rule does not propagate alwayslink=1
+ alwayslink = 1,
+ visibility = ["//visibility:private"],
+ )
+
+ # Loadable object which cgo reads when it generates _cgo_import.go
+ native.cc_binary(
+ name = cgogen.outdir + "/_cgo_.o",
+ srcs = [cgogen.c_dummy],
+ deps = cdeps + [cgogen.outdir + "/_cgo_lib"],
+ copts = copts,
+ linkopts = clinkopts,
+ visibility = ["//visibility:private"],
)
- c_filtered_srcs.append(":" + c_filtered_srcs_name)
-
- pkg_dir = _pkg_dir(
- "external/" + REPOSITORY_NAME[1:] if len(REPOSITORY_NAME) > 1 else "",
- PACKAGE_NAME)
-
- # Platform-specific settings
- native.config_setting(
- name = name + "_windows_setting",
- values = {
- "cpu": "x64_windows_msvc",
- },
- )
- platform_copts = select({
- ":" + name + "_windows_setting": ["-mthreads"],
- "//conditions:default": ["-pthread"],
- })
- platform_linkopts = select({
- ":" + name + "_windows_setting": ["-mthreads"],
- "//conditions:default": ["-pthread"],
- })
-
- # Bundles objects into an archive so that _cgo_.o and _all.o can share them.
- native.cc_library(
- name = cgogen.outdir + "/_cgo_lib",
- srcs = cgogen.c_thunks + cgogen.c_exports + c_filtered_srcs + c_hdrs,
- deps = cdeps,
- copts = copts + platform_copts + [
- "-I", pkg_dir,
- "-I", "$(GENDIR)/" + pkg_dir + "/" + cgogen.outdir,
- # The generated thunks often contain unused variables.
- "-Wno-unused-variable",
- ],
- linkopts = clinkopts + platform_linkopts,
- linkstatic = 1,
- # _cgo_.o and _all.o keep all objects in this archive.
- # But it should not be very annoying in the final binary target
- # because _cgo_object rule does not propagate alwayslink=1
- alwayslink = 1,
- visibility = ["//visibility:private"],
- )
-
- # Loadable object which cgo reads when it generates _cgo_import.go
- native.cc_binary(
- name = cgogen.outdir + "/_cgo_.o",
- srcs = [cgogen.c_dummy],
- deps = cdeps + [cgogen.outdir + "/_cgo_lib"],
- copts = copts,
- linkopts = clinkopts,
- visibility = ["//visibility:private"],
- )
- _cgo_import(
- name = "%s.cgo.importgen" % name,
- cgo_o = cgogen.outdir + "/_cgo_.o",
- out = cgogen.outdir + "/_cgo_import.go",
- sample_go_src = go_srcs[0],
- go_tool = go_tool,
- toolchain = toolchain,
- visibility = ["//visibility:private"],
- )
-
- _cgo_object(
- name = cgogen.outdir + "/_cgo_object",
- src = cgogen.outdir + "/_cgo_lib",
- out = cgogen.outdir + "/_all.o",
- cgogen = cgogen.name,
- visibility = ["//visibility:private"],
- )
- return cgogen
-
-def cgo_genrule(name, srcs,
- copts=[],
- clinkopts=[],
- cdeps=[],
- **kwargs):
- cgogen = _setup_cgo_library(
- name = name,
- srcs = srcs,
- cdeps = cdeps,
- copts = copts,
- clinkopts = clinkopts,
- toolchain = None,
- go_tool = None,
- )
- _cgo_genrule(
- name = name,
- srcs = cgogen.go_thunks + [
- cgogen.gotypes,
- cgogen.outdir + "/_cgo_import.go",
- ],
- cgo_object = cgogen.outdir + "/_cgo_object",
- **kwargs
- )
-
-def cgo_library(name, srcs,
- toolchain=None,
- go_tool=None,
- copts=[],
- clinkopts=[],
- cdeps=[],
- **kwargs):
- """Builds a cgo-enabled go library.
-
- Args:
- name: A unique name for this rule.
- srcs: List of Go, C and C++ files that are processed to build a Go library.
- Those Go files must contain `import "C"`.
- C and C++ files can be anything allowed in `srcs` attribute of
- `cc_library`.
- copts: Add these flags to the C++ compiler.
- clinkopts: Add these flags to the C++ linker.
- cdeps: List of C/C++ libraries to be linked into the binary target.
- They must be `cc_library` rules.
- deps: List of other libraries to be linked to this library target.
- data: List of files needed by this rule at runtime.
-
- NOTE:
- `srcs` cannot contain pure-Go files, which do not have `import "C"`.
- So you need to define another `go_library` when you build a go package with
- both cgo-enabled and pure-Go sources.
-
- ```
- cgo_library(
- name = "cgo_enabled",
- srcs = ["cgo-enabled.go", "foo.cc", "bar.S", "baz.a"],
+ _cgo_import(
+ name = "%s.cgo.importgen" % name,
+ cgo_o = cgogen.outdir + "/_cgo_.o",
+ out = cgogen.outdir + "/_cgo_import.go",
+ sample_go_src = go_srcs[0],
+ go_tool = go_tool,
+ toolchain = toolchain,
+ visibility = ["//visibility:private"],
+ )
+
+ _cgo_object(
+ name = cgogen.outdir + "/_cgo_object",
+ src = cgogen.outdir + "/_cgo_lib",
+ out = cgogen.outdir + "/_all.o",
+ cgogen = cgogen.name,
+ visibility = ["//visibility:private"],
+ )
+ return cgogen
+
+def cgo_genrule(
+ name,
+ srcs,
+ copts = [],
+ clinkopts = [],
+ cdeps = [],
+ **kwargs):
+ cgogen = _setup_cgo_library(
+ name = name,
+ srcs = srcs,
+ cdeps = cdeps,
+ copts = copts,
+ clinkopts = clinkopts,
+ toolchain = None,
+ go_tool = None,
+ )
+ _cgo_genrule(
+ name = name,
+ srcs = cgogen.go_thunks + [
+ cgogen.gotypes,
+ cgogen.outdir + "/_cgo_import.go",
+ ],
+ cgo_object = cgogen.outdir + "/_cgo_object",
+ **kwargs
+ )
+
+def cgo_library(
+ name,
+ srcs,
+ toolchain = None,
+ go_tool = None,
+ copts = [],
+ clinkopts = [],
+ cdeps = [],
+ **kwargs):
+ """Builds a cgo-enabled go library.
+
+ Args:
+ name: A unique name for this rule.
+ srcs: List of Go, C and C++ files that are processed to build a Go library.
+ Those Go files must contain `import "C"`.
+ C and C++ files can be anything allowed in `srcs` attribute of
+ `cc_library`.
+ copts: Add these flags to the C++ compiler.
+ clinkopts: Add these flags to the C++ linker.
+ cdeps: List of C/C++ libraries to be linked into the binary target.
+ They must be `cc_library` rules.
+ deps: List of other libraries to be linked to this library target.
+ data: List of files needed by this rule at runtime.
+
+ NOTE:
+ `srcs` cannot contain pure-Go files, which do not have `import "C"`.
+ So you need to define another `go_library` when you build a go package with
+ both cgo-enabled and pure-Go sources.
+
+ ```
+ cgo_library(
+ name = "cgo_enabled",
+ srcs = ["cgo-enabled.go", "foo.cc", "bar.S", "baz.a"],
+ )
+
+ go_library(
+ name = "go_default_library",
+ srcs = ["pure-go.go"],
+ library = ":cgo_enabled",
+ )
+ ```
+ """
+ cgogen = _setup_cgo_library(
+ name = name,
+ srcs = srcs,
+ cdeps = cdeps,
+ copts = copts,
+ clinkopts = clinkopts,
+ go_tool = go_tool,
+ toolchain = toolchain,
)
go_library(
- name = "go_default_library",
- srcs = ["pure-go.go"],
- library = ":cgo_enabled",
+ name = name,
+ srcs = cgogen.go_thunks + [
+ cgogen.gotypes,
+ cgogen.outdir + "/_cgo_import.go",
+ ],
+ cgo_object = cgogen.outdir + "/_cgo_object",
+ go_tool = go_tool,
+ toolchain = toolchain,
+ **kwargs
)
- ```
- """
- cgogen = _setup_cgo_library(
- name = name,
- srcs = srcs,
- cdeps = cdeps,
- copts = copts,
- clinkopts = clinkopts,
- go_tool = go_tool,
- toolchain = toolchain,
- )
-
- go_library(
- name = name,
- srcs = cgogen.go_thunks + [
- cgogen.gotypes,
- cgogen.outdir + "/_cgo_import.go",
- ],
- cgo_object = cgogen.outdir + "/_cgo_object",
- go_tool = go_tool,
- toolchain = toolchain,
- **kwargs
- )