Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1 | # Copyright 2014 The Bazel Authors. All rights reserved. |
| 2 | # |
| 3 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | # you may not use this file except in compliance with the License. |
| 5 | # You may obtain a copy of the License at |
| 6 | # |
| 7 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | # |
| 9 | # Unless required by applicable law or agreed to in writing, software |
| 10 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | # See the License for the specific language governing permissions and |
| 13 | # limitations under the License. |
| 14 | |
| 15 | # (From https://github.com/bazelbuild/rules_go/blob/master/go/def.bzl@a6f9d0c) |
| 16 | |
| 17 | load("//go/private:repositories.bzl", "go_repositories") |
| 18 | load("//go/private:go_repository.bzl", "go_repository", "new_go_repository") |
| 19 | load("//go/private:go_prefix.bzl", "go_prefix") |
| 20 | load("//go/private:json.bzl", "json_marshal") |
| 21 | |
| 22 | """These are bare-bones Go rules. |
| 23 | |
| 24 | In order of priority: |
| 25 | |
| 26 | - BUILD file must be written by hand. |
| 27 | |
| 28 | - No support for SWIG |
| 29 | |
| 30 | - No test sharding or test XML. |
| 31 | |
| 32 | """ |
| 33 | |
| 34 | _DEFAULT_LIB = "go_default_library" |
| 35 | |
| 36 | _VENDOR_PREFIX = "/vendor/" |
| 37 | |
| 38 | go_filetype = FileType([ |
| 39 | ".go", |
| 40 | ".s", |
| 41 | ".S", |
| 42 | ".h", # may be included by .s |
| 43 | ]) |
| 44 | |
| 45 | # be consistent to cc_library. |
| 46 | hdr_exts = [ |
| 47 | ".h", |
| 48 | ".hh", |
| 49 | ".hpp", |
| 50 | ".hxx", |
| 51 | ".inc", |
| 52 | ] |
| 53 | |
| 54 | cc_hdr_filetype = FileType(hdr_exts) |
| 55 | |
| 56 | # Extensions of files we can build with the Go compiler or with cc_library. |
| 57 | # This is a subset of the extensions recognized by go/build. |
| 58 | cgo_filetype = FileType([ |
| 59 | ".go", |
| 60 | ".c", |
| 61 | ".cc", |
| 62 | ".cxx", |
| 63 | ".cpp", |
| 64 | ".s", |
| 65 | ".S", |
| 66 | ".h", |
| 67 | ".hh", |
| 68 | ".hpp", |
| 69 | ".hxx", |
| 70 | ]) |
| 71 | |
| 72 | ################ |
| 73 | |
| 74 | def go_environment_vars(ctx): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 75 | """Return a map of environment variables for use with actions, based on |
| 76 | the arguments. Uses the ctx.fragments.cpp.cpu attribute, if present, |
| 77 | and picks a default of target_os="linux" and target_arch="amd64" |
| 78 | otherwise. |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 79 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 80 | Args: |
| 81 | The starlark Context. |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 82 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 83 | Returns: |
| 84 | A dict of environment variables for running Go tool commands that build for |
| 85 | the target OS and architecture. |
| 86 | """ |
| 87 | default_toolchain = {"GOOS": "linux", "GOARCH": "amd64"} |
| 88 | bazel_to_go_toolchain = { |
| 89 | "k8": {"GOOS": "linux", "GOARCH": "amd64"}, |
| 90 | "piii": {"GOOS": "linux", "GOARCH": "386"}, |
| 91 | "darwin": {"GOOS": "darwin", "GOARCH": "amd64"}, |
| 92 | "darwin_x86_64": {"GOOS": "darwin", "GOARCH": "amd64"}, |
| 93 | "freebsd": {"GOOS": "freebsd", "GOARCH": "amd64"}, |
| 94 | "armeabi-v7a": {"GOOS": "linux", "GOARCH": "arm"}, |
| 95 | "arm": {"GOOS": "linux", "GOARCH": "arm"}, |
| 96 | } |
| 97 | env = {} |
| 98 | if hasattr(ctx.file, "go_tool"): |
| 99 | env["GOROOT"] = ctx.file.go_tool.dirname + "/.." |
| 100 | env.update(bazel_to_go_toolchain.get(ctx.fragments.cpp.cpu, default_toolchain)) |
| 101 | return env |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 102 | |
| 103 | def _is_darwin_cpu(ctx): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 104 | cpu = ctx.fragments.cpp.cpu |
| 105 | return cpu == "darwin" or cpu == "darwin_x86_64" |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 106 | |
| 107 | def _emit_generate_params_action(cmds, ctx, fn): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 108 | cmds_all = [ |
| 109 | # Use bash explicitly. /bin/sh is default, and it may be linked to a |
| 110 | # different shell, e.g., /bin/dash on Ubuntu. |
| 111 | "#!/bin/bash", |
| 112 | "set -e", |
| 113 | ] |
| 114 | cmds_all += cmds |
| 115 | cmds_all_str = "\n".join(cmds_all) + "\n" |
| 116 | f = ctx.new_file(ctx.configuration.bin_dir, fn) |
| 117 | ctx.file_action( |
| 118 | output = f, |
| 119 | content = cmds_all_str, |
| 120 | executable = True, |
| 121 | ) |
| 122 | return f |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 123 | |
| 124 | def _emit_go_asm_action(ctx, source, hdrs, out_obj): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 125 | """Construct the command line for compiling Go Assembly code. |
| 126 | Constructs a symlink tree to accomodate for workspace name. |
| 127 | Args: |
| 128 | ctx: The starlark Context. |
| 129 | source: a source code artifact |
| 130 | hdrs: list of .h files that may be included |
| 131 | out_obj: the artifact (configured target?) that should be produced |
| 132 | """ |
| 133 | params = { |
| 134 | "go_tool": ctx.file.go_tool.path, |
| 135 | "includes": [f.dirname for f in hdrs] + [ctx.file.go_include.path], |
| 136 | "source": source.path, |
| 137 | "out": out_obj.path, |
| 138 | } |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 139 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 140 | inputs = hdrs + ctx.files.toolchain + [source] |
| 141 | ctx.action( |
| 142 | inputs = inputs, |
| 143 | outputs = [out_obj], |
| 144 | mnemonic = "GoAsmCompile", |
| 145 | executable = ctx.executable._asm, |
| 146 | arguments = [json_marshal(params)], |
| 147 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 148 | |
| 149 | def _go_importpath(ctx): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 150 | """Returns the expected importpath of the go_library being built. |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 151 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 152 | Args: |
| 153 | ctx: The starlark Context |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 154 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 155 | Returns: |
| 156 | Go importpath of the library |
| 157 | """ |
| 158 | path = ctx.attr.importpath |
| 159 | if path != "": |
| 160 | return path |
| 161 | path = ctx.attr.go_prefix.go_prefix |
| 162 | if path.endswith("/"): |
| 163 | path = path[:-1] |
| 164 | if ctx.label.package: |
| 165 | path += "/" + ctx.label.package |
| 166 | if ctx.label.name != _DEFAULT_LIB: |
| 167 | path += "/" + ctx.label.name |
| 168 | if path.rfind(_VENDOR_PREFIX) != -1: |
| 169 | path = path[len(_VENDOR_PREFIX) + path.rfind(_VENDOR_PREFIX):] |
| 170 | if path[0] == "/": |
| 171 | path = path[1:] |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 172 | return path |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 173 | |
| 174 | def _emit_go_compile_action(ctx, sources, deps, libpaths, out_object, gc_goopts): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 175 | """Construct the command line for compiling Go code. |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 176 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 177 | Args: |
| 178 | ctx: The starlark Context. |
| 179 | sources: an iterable of source code artifacts (or CTs? or labels?) |
| 180 | deps: an iterable of dependencies. Each dependency d should have an |
| 181 | artifact in d.transitive_go_libraries representing all imported libraries. |
| 182 | libpaths: the set of paths to search for imported libraries. |
| 183 | out_object: the object file that should be produced |
| 184 | gc_goopts: additional flags to pass to the compiler. |
| 185 | """ |
| 186 | if ctx.coverage_instrumented(): |
| 187 | sources = _emit_go_cover_action(ctx, sources) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 188 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 189 | # Compile filtered files. |
| 190 | args = [ |
| 191 | "-cgo", |
| 192 | ctx.file.go_tool.path, |
| 193 | "tool", |
| 194 | "compile", |
| 195 | "-o", |
| 196 | out_object.path, |
| 197 | "-trimpath", |
| 198 | "-abs-.", |
| 199 | "-I", |
| 200 | "-abs-.", |
| 201 | ] |
| 202 | inputs = depset(sources + ctx.files.toolchain) |
| 203 | for dep in deps: |
| 204 | inputs += dep.transitive_go_libraries |
| 205 | for path in libpaths: |
| 206 | args += ["-I", path] |
| 207 | args += gc_goopts + [("" if i.basename.startswith("_cgo") else "-filter-") + i.path for i in sources] |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 208 | ctx.action( |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 209 | inputs = list(inputs), |
| 210 | outputs = [out_object], |
| 211 | mnemonic = "GoCompile", |
| 212 | executable = ctx.executable._filter_exec, |
| 213 | arguments = args, |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 214 | env = go_environment_vars(ctx), |
| 215 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 216 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 217 | return sources |
| 218 | |
| 219 | def _emit_go_pack_action(ctx, out_lib, objects): |
| 220 | """Construct the command line for packing objects together. |
| 221 | |
| 222 | Args: |
| 223 | ctx: The starlark Context. |
| 224 | out_lib: the archive that should be produced |
| 225 | objects: an iterable of object files to be added to the output archive file. |
| 226 | """ |
| 227 | ctx.action( |
| 228 | inputs = objects + ctx.files.toolchain, |
| 229 | outputs = [out_lib], |
| 230 | mnemonic = "GoPack", |
| 231 | executable = ctx.file.go_tool, |
| 232 | arguments = ["tool", "pack", "c", out_lib.path] + [a.path for a in objects], |
| 233 | env = go_environment_vars(ctx), |
| 234 | ) |
| 235 | |
| 236 | def _emit_go_cover_action(ctx, sources): |
| 237 | """Construct the command line for test coverage instrument. |
| 238 | |
| 239 | Args: |
| 240 | ctx: The starlark Context. |
| 241 | sources: an iterable of Go source files. |
| 242 | |
| 243 | Returns: |
| 244 | A list of Go source code files which might be coverage instrumented. |
| 245 | """ |
| 246 | outputs = [] |
| 247 | |
| 248 | # TODO(linuxerwang): make the mode configurable. |
| 249 | count = 0 |
| 250 | |
| 251 | for src in sources: |
| 252 | if not src.path.endswith(".go") or src.path.endswith("_test.go"): |
| 253 | outputs += [src] |
| 254 | continue |
| 255 | |
| 256 | cover_var = "GoCover_%d" % count |
| 257 | out = ctx.new_file(src, src.basename[:-3] + "_" + cover_var + ".cover.go") |
| 258 | outputs += [out] |
| 259 | ctx.action( |
| 260 | inputs = [src] + ctx.files.toolchain, |
| 261 | outputs = [out], |
| 262 | mnemonic = "GoCover", |
| 263 | executable = ctx.file.go_tool, |
| 264 | arguments = ["tool", "cover", "--mode=set", "-var=%s" % cover_var, "-o", out.path, src.path], |
| 265 | env = go_environment_vars(ctx), |
| 266 | ) |
| 267 | count += 1 |
| 268 | |
| 269 | return outputs |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 270 | |
| 271 | def go_library_impl(ctx): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 272 | """Implements the go_library() rule.""" |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 273 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 274 | sources = depset(ctx.files.srcs) |
| 275 | go_srcs = depset([s for s in sources if s.basename.endswith(".go")]) |
| 276 | asm_srcs = [s for s in sources if s.basename.endswith(".s") or s.basename.endswith(".S")] |
| 277 | asm_hdrs = [s for s in sources if s.basename.endswith(".h")] |
| 278 | deps = ctx.attr.deps |
| 279 | dep_runfiles = [d.data_runfiles for d in deps] |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 280 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 281 | cgo_object = None |
| 282 | if hasattr(ctx.attr, "cgo_object"): |
| 283 | cgo_object = ctx.attr.cgo_object |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 284 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 285 | if ctx.attr.library: |
| 286 | go_srcs += ctx.attr.library.go_sources |
| 287 | asm_srcs += ctx.attr.library.asm_sources |
| 288 | asm_hdrs += ctx.attr.library.asm_headers |
| 289 | deps += ctx.attr.library.direct_deps |
| 290 | dep_runfiles += [ctx.attr.library.data_runfiles] |
| 291 | if ctx.attr.library.cgo_object: |
| 292 | if cgo_object: |
| 293 | fail("go_library %s cannot have cgo_object because the package " + |
| 294 | "already has cgo_object in %s" % ( |
| 295 | ctx.label.name, |
| 296 | ctx.attr.library.name, |
| 297 | )) |
| 298 | cgo_object = ctx.attr.library.cgo_object |
| 299 | if not go_srcs: |
| 300 | fail("may not be empty", "srcs") |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 301 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 302 | transitive_cgo_deps = depset([], order = "topological") |
| 303 | if cgo_object: |
| 304 | dep_runfiles += [cgo_object.data_runfiles] |
| 305 | transitive_cgo_deps += cgo_object.cgo_deps |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 306 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 307 | extra_objects = [cgo_object.cgo_obj] if cgo_object else [] |
| 308 | for src in asm_srcs: |
| 309 | obj = ctx.new_file(src, "%s.dir/%s.o" % (ctx.label.name, src.basename[:-2])) |
| 310 | _emit_go_asm_action(ctx, src, asm_hdrs, obj) |
| 311 | extra_objects += [obj] |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 312 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 313 | lib_name = _go_importpath(ctx) + ".a" |
| 314 | out_lib = ctx.new_file(lib_name) |
| 315 | out_object = ctx.new_file(ctx.label.name + ".o") |
| 316 | search_path = out_lib.path[:-len(lib_name)] |
| 317 | gc_goopts = _gc_goopts(ctx) |
| 318 | transitive_go_libraries = depset([out_lib]) |
| 319 | transitive_go_library_paths = depset([search_path]) |
| 320 | for dep in deps: |
| 321 | transitive_go_libraries += dep.transitive_go_libraries |
| 322 | transitive_cgo_deps += dep.transitive_cgo_deps |
| 323 | transitive_go_library_paths += dep.transitive_go_library_paths |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 324 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 325 | go_srcs = _emit_go_compile_action( |
| 326 | ctx, |
| 327 | sources = go_srcs, |
| 328 | deps = deps, |
| 329 | libpaths = transitive_go_library_paths, |
| 330 | out_object = out_object, |
| 331 | gc_goopts = gc_goopts, |
| 332 | ) |
| 333 | _emit_go_pack_action(ctx, out_lib, [out_object] + extra_objects) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 334 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 335 | dylibs = [] |
| 336 | if cgo_object: |
| 337 | dylibs += [d for d in cgo_object.cgo_deps if d.path.endswith(".so")] |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 338 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 339 | runfiles = ctx.runfiles(files = dylibs, collect_data = True) |
| 340 | for d in dep_runfiles: |
| 341 | runfiles = runfiles.merge(d) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 342 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 343 | return struct( |
| 344 | label = ctx.label, |
| 345 | files = depset([out_lib]), |
| 346 | runfiles = runfiles, |
| 347 | go_sources = go_srcs, |
| 348 | asm_sources = asm_srcs, |
| 349 | asm_headers = asm_hdrs, |
| 350 | cgo_object = cgo_object, |
| 351 | direct_deps = ctx.attr.deps, |
| 352 | transitive_cgo_deps = transitive_cgo_deps, |
| 353 | transitive_go_libraries = transitive_go_libraries, |
| 354 | transitive_go_library_paths = transitive_go_library_paths, |
| 355 | gc_goopts = gc_goopts, |
| 356 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 357 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 358 | def _c_linker_options(ctx, blocklist = []): |
| 359 | """Extracts flags to pass to $(CC) on link from the current context |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 360 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 361 | Args: |
| 362 | ctx: the current context |
| 363 | blocklist: Any flags starts with any of these prefixes are filtered out from |
| 364 | the return value. |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 365 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 366 | Returns: |
| 367 | A list of command line flags |
| 368 | """ |
| 369 | cpp = ctx.fragments.cpp |
| 370 | features = ctx.features |
| 371 | options = cpp.compiler_options(features) |
| 372 | options += cpp.unfiltered_compiler_options(features) |
| 373 | options += cpp.link_options |
| 374 | options += cpp.mostly_static_link_options(ctx.features, False) |
| 375 | filtered = [] |
| 376 | for opt in options: |
| 377 | if any([opt.startswith(prefix) for prefix in blocklist]): |
| 378 | continue |
| 379 | filtered.append(opt) |
| 380 | return filtered |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 381 | |
| 382 | def _gc_goopts(ctx): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 383 | gc_goopts = [ |
| 384 | ctx.expand_make_variables("gc_goopts", f, {}) |
| 385 | for f in ctx.attr.gc_goopts |
| 386 | ] |
| 387 | if ctx.attr.library: |
| 388 | gc_goopts += ctx.attr.library.gc_goopts |
| 389 | return gc_goopts |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 390 | |
| 391 | def _gc_linkopts(ctx): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 392 | gc_linkopts = [ |
| 393 | ctx.expand_make_variables("gc_linkopts", f, {}) |
| 394 | for f in ctx.attr.gc_linkopts |
| 395 | ] |
| 396 | for k, v in ctx.attr.x_defs.items(): |
| 397 | gc_linkopts += ["-X", "%s='%s'" % (k, v)] |
| 398 | return gc_linkopts |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 399 | |
| 400 | def _extract_extldflags(gc_linkopts, extldflags): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 401 | """Extracts -extldflags from gc_linkopts and combines them into a single list. |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 402 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 403 | Args: |
| 404 | gc_linkopts: a list of flags passed in through the gc_linkopts attributes. |
| 405 | ctx.expand_make_variables should have already been applied. |
| 406 | extldflags: a list of flags to be passed to the external linker. |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 407 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 408 | Return: |
| 409 | A tuple containing the filtered gc_linkopts with external flags removed, |
| 410 | and a combined list of external flags. |
| 411 | """ |
| 412 | filtered_gc_linkopts = [] |
| 413 | is_extldflags = False |
| 414 | for opt in gc_linkopts: |
| 415 | if is_extldflags: |
| 416 | is_extldflags = False |
| 417 | extldflags += [opt] |
| 418 | elif opt == "-extldflags": |
| 419 | is_extldflags = True |
| 420 | else: |
| 421 | filtered_gc_linkopts += [opt] |
| 422 | return filtered_gc_linkopts, extldflags |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 423 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 424 | def _emit_go_link_action( |
| 425 | ctx, |
| 426 | transitive_go_library_paths, |
| 427 | transitive_go_libraries, |
| 428 | cgo_deps, |
| 429 | libs, |
| 430 | executable, |
| 431 | gc_linkopts): |
| 432 | """Sets up a symlink tree to libraries to link together.""" |
| 433 | config_strip = len(ctx.configuration.bin_dir.path) + 1 |
| 434 | pkg_depth = executable.dirname[config_strip:].count("/") + 1 |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 435 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 436 | ld = "%s" % ctx.fragments.cpp.compiler_executable |
| 437 | extldflags = _c_linker_options(ctx) + [ |
| 438 | "-Wl,-rpath,$ORIGIN/" + ("../" * pkg_depth), |
| 439 | ] |
| 440 | for d in cgo_deps: |
| 441 | if d.basename.endswith(".so"): |
| 442 | short_dir = d.dirname[len(d.root.path):] |
| 443 | extldflags += ["-Wl,-rpath,$ORIGIN/" + ("../" * pkg_depth) + short_dir] |
| 444 | gc_linkopts, extldflags = _extract_extldflags(gc_linkopts, extldflags) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 445 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 446 | link_cmd = [ |
| 447 | ctx.file.go_tool.path, |
| 448 | "tool", |
| 449 | "link", |
| 450 | "-L", |
| 451 | ".", |
| 452 | ] |
| 453 | for path in transitive_go_library_paths: |
| 454 | link_cmd += ["-L", path] |
| 455 | link_cmd += [ |
| 456 | "-o", |
| 457 | executable.path, |
| 458 | ] + gc_linkopts + ['"${STAMP_XDEFS[@]}"'] |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 459 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 460 | # workaround for a bug in ld(1) on Mac OS X. |
| 461 | # http://lists.apple.com/archives/Darwin-dev/2006/Sep/msg00084.html |
| 462 | # TODO(yugui) Remove this workaround once rules_go stops supporting XCode 7.2 |
| 463 | # or earlier. |
| 464 | if not _is_darwin_cpu(ctx): |
| 465 | link_cmd += ["-s"] |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 466 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 467 | link_cmd += [ |
| 468 | "-extld", |
| 469 | ld, |
| 470 | "-extldflags", |
| 471 | "'%s'" % " ".join(extldflags), |
| 472 | ] + [lib.path for lib in libs] |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 473 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 474 | # Avoided -s on OSX but but it requires dsymutil to be on $PATH. |
| 475 | # TODO(yugui) Remove this workaround once rules_go stops supporting XCode 7.2 |
| 476 | # or earlier. |
| 477 | cmds = ["export PATH=$PATH:/usr/bin"] |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 478 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 479 | cmds += [ |
| 480 | "STAMP_XDEFS=()", |
| 481 | ] |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 482 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 483 | stamp_inputs = [] |
| 484 | if ctx.attr.linkstamp: |
| 485 | # read workspace status files, converting "KEY value" lines |
| 486 | # to "-X $linkstamp.KEY=value" arguments to the go linker. |
| 487 | stamp_inputs = [ctx.info_file, ctx.version_file] |
| 488 | for f in stamp_inputs: |
| 489 | cmds += [ |
| 490 | "while read -r key value || [[ -n $key ]]; do", |
| 491 | " STAMP_XDEFS+=(-X \"%s.$key=$value\")" % ctx.attr.linkstamp, |
| 492 | "done < " + f.path, |
| 493 | ] |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 494 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 495 | cmds += [" ".join(link_cmd)] |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 496 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 497 | f = _emit_generate_params_action(cmds, ctx, lib.basename + ".GoLinkFile.params") |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 498 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 499 | ctx.action( |
| 500 | inputs = [f] + (list(transitive_go_libraries) + [lib] + list(cgo_deps) + |
| 501 | ctx.files.toolchain + ctx.files._crosstool) + stamp_inputs, |
| 502 | outputs = [executable], |
| 503 | command = f.path, |
| 504 | mnemonic = "GoLink", |
| 505 | env = go_environment_vars(ctx), |
| 506 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 507 | |
| 508 | def go_binary_impl(ctx): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 509 | """go_binary_impl emits actions for compiling and linking a go executable.""" |
| 510 | lib_result = go_library_impl(ctx) |
| 511 | _emit_go_link_action( |
| 512 | ctx, |
| 513 | transitive_go_libraries = lib_result.transitive_go_libraries, |
| 514 | transitive_go_library_paths = lib_result.transitive_go_library_paths, |
| 515 | cgo_deps = lib_result.transitive_cgo_deps, |
| 516 | libs = lib_result.files, |
| 517 | executable = ctx.outputs.executable, |
| 518 | gc_linkopts = _gc_linkopts(ctx), |
| 519 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 520 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 521 | return struct( |
| 522 | files = depset([ctx.outputs.executable]), |
| 523 | runfiles = lib_result.runfiles, |
| 524 | cgo_object = lib_result.cgo_object, |
| 525 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 526 | |
| 527 | def go_test_impl(ctx): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 528 | """go_test_impl implements go testing. |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 529 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 530 | It emits an action to run the test generator, and then compiles the |
| 531 | test into a binary.""" |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 532 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 533 | lib_result = go_library_impl(ctx) |
| 534 | main_go = ctx.new_file(ctx.label.name + "_main_test.go") |
| 535 | main_object = ctx.new_file(ctx.label.name + "_main_test.o") |
| 536 | main_lib = ctx.new_file(ctx.label.name + "_main_test.a") |
| 537 | go_import = _go_importpath(ctx) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 538 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 539 | cmds = [ |
| 540 | "UNFILTERED_TEST_FILES=(%s)" % |
| 541 | " ".join(["'%s'" % f.path for f in lib_result.go_sources]), |
| 542 | "FILTERED_TEST_FILES=()", |
| 543 | "while read -r line; do", |
| 544 | ' if [ -n "$line" ]; then', |
| 545 | ' FILTERED_TEST_FILES+=("$line")', |
| 546 | " fi", |
| 547 | 'done < <(\'%s\' -cgo "${UNFILTERED_TEST_FILES[@]}")' % |
| 548 | ctx.executable._filter_tags.path, |
| 549 | " ".join([ |
| 550 | "'%s'" % ctx.executable.test_generator.path, |
| 551 | "--package", |
| 552 | go_import, |
| 553 | "--output", |
| 554 | "'%s'" % main_go.path, |
| 555 | '"${FILTERED_TEST_FILES[@]}"', |
| 556 | ]), |
| 557 | ] |
| 558 | f = _emit_generate_params_action( |
| 559 | cmds, |
| 560 | ctx, |
| 561 | ctx.label.name + ".GoTestGenTest.params", |
| 562 | ) |
| 563 | inputs = (list(lib_result.go_sources) + list(ctx.files.toolchain) + |
| 564 | [f, ctx.executable._filter_tags, ctx.executable.test_generator]) |
| 565 | ctx.action( |
| 566 | inputs = inputs, |
| 567 | outputs = [main_go], |
| 568 | command = f.path, |
| 569 | mnemonic = "GoTestGenTest", |
| 570 | env = dict(go_environment_vars(ctx), RUNDIR = ctx.label.package), |
| 571 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 572 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 573 | _emit_go_compile_action( |
| 574 | ctx, |
| 575 | sources = depset([main_go]), |
| 576 | deps = ctx.attr.deps + [lib_result], |
| 577 | libpaths = lib_result.transitive_go_library_paths, |
| 578 | out_object = main_object, |
| 579 | gc_goopts = _gc_goopts(ctx), |
| 580 | ) |
| 581 | _emit_go_pack_action(ctx, main_lib, [main_object]) |
| 582 | _emit_go_link_action( |
| 583 | ctx, |
| 584 | transitive_go_library_paths = lib_result.transitive_go_library_paths, |
| 585 | transitive_go_libraries = lib_result.transitive_go_libraries, |
| 586 | cgo_deps = lib_result.transitive_cgo_deps, |
| 587 | libs = [main_lib], |
| 588 | executable = ctx.outputs.executable, |
| 589 | gc_linkopts = _gc_linkopts(ctx), |
| 590 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 591 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 592 | # TODO(bazel-team): the Go tests should do a chdir to the directory |
| 593 | # holding the data files, so open-source go tests continue to work |
| 594 | # without code changes. |
| 595 | runfiles = ctx.runfiles(files = [ctx.outputs.executable]) |
| 596 | runfiles = runfiles.merge(lib_result.runfiles) |
| 597 | return struct( |
| 598 | files = depset([ctx.outputs.executable]), |
| 599 | runfiles = runfiles, |
| 600 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 601 | |
| 602 | go_env_attrs = { |
| 603 | "toolchain": attr.label( |
| 604 | default = Label("//go/toolchain:toolchain"), |
| 605 | allow_files = True, |
| 606 | cfg = "host", |
| 607 | ), |
| 608 | "go_tool": attr.label( |
| 609 | default = Label("//go/toolchain:go_tool"), |
| 610 | single_file = True, |
| 611 | allow_files = True, |
| 612 | cfg = "host", |
| 613 | ), |
| 614 | "go_prefix": attr.label( |
| 615 | providers = ["go_prefix"], |
| 616 | default = Label( |
| 617 | "//:go_prefix", |
| 618 | relative_to_caller_repository = True, |
| 619 | ), |
| 620 | allow_files = False, |
| 621 | cfg = "host", |
| 622 | ), |
| 623 | "go_src": attr.label( |
| 624 | default = Label("//go/toolchain:go_src"), |
| 625 | allow_files = True, |
| 626 | cfg = "host", |
| 627 | ), |
| 628 | "go_include": attr.label( |
| 629 | default = Label("//go/toolchain:go_include"), |
| 630 | single_file = True, |
| 631 | allow_files = True, |
| 632 | cfg = "host", |
| 633 | ), |
| 634 | "go_root": attr.label( |
| 635 | providers = ["go_root"], |
| 636 | default = Label( |
| 637 | "//go/toolchain:go_root", |
| 638 | ), |
| 639 | allow_files = False, |
| 640 | cfg = "host", |
| 641 | ), |
| 642 | "_filter_tags": attr.label( |
| 643 | default = Label("//go/tools/filter_tags"), |
| 644 | cfg = "host", |
| 645 | executable = True, |
| 646 | single_file = True, |
| 647 | ), |
| 648 | "_filter_exec": attr.label( |
| 649 | default = Label("//go/tools/filter_exec"), |
| 650 | cfg = "host", |
| 651 | executable = True, |
| 652 | single_file = True, |
| 653 | ), |
| 654 | "_asm": attr.label( |
| 655 | default = Label("//go/tools/builders:asm"), |
| 656 | cfg = "host", |
| 657 | executable = True, |
| 658 | single_file = True, |
| 659 | ), |
| 660 | } |
| 661 | |
| 662 | go_library_attrs = go_env_attrs + { |
| 663 | "data": attr.label_list( |
| 664 | allow_files = True, |
| 665 | cfg = "data", |
| 666 | ), |
| 667 | "srcs": attr.label_list(allow_files = go_filetype), |
| 668 | "deps": attr.label_list( |
| 669 | providers = [ |
| 670 | "transitive_go_library_paths", |
| 671 | "transitive_go_libraries", |
| 672 | "transitive_cgo_deps", |
| 673 | ], |
| 674 | ), |
| 675 | "importpath": attr.string(), |
| 676 | "library": attr.label( |
| 677 | providers = [ |
| 678 | "direct_deps", |
| 679 | "go_sources", |
| 680 | "asm_sources", |
| 681 | "cgo_object", |
| 682 | "gc_goopts", |
| 683 | ], |
| 684 | ), |
| 685 | "gc_goopts": attr.string_list(), |
| 686 | } |
| 687 | |
| 688 | _crosstool_attrs = { |
| 689 | "_crosstool": attr.label( |
| 690 | default = Label("//tools/defaults:crosstool"), |
| 691 | ), |
| 692 | } |
| 693 | |
| 694 | go_link_attrs = go_library_attrs + _crosstool_attrs + { |
| 695 | "gc_linkopts": attr.string_list(), |
| 696 | "linkstamp": attr.string(), |
| 697 | "x_defs": attr.string_dict(), |
| 698 | } |
| 699 | |
| 700 | go_library = rule( |
| 701 | go_library_impl, |
| 702 | attrs = go_library_attrs + { |
| 703 | "cgo_object": attr.label( |
| 704 | providers = [ |
| 705 | "cgo_obj", |
| 706 | "cgo_deps", |
| 707 | ], |
| 708 | ), |
| 709 | }, |
| 710 | fragments = ["cpp"], |
| 711 | ) |
| 712 | |
| 713 | go_binary = rule( |
| 714 | go_binary_impl, |
| 715 | attrs = go_library_attrs + _crosstool_attrs + go_link_attrs, |
| 716 | executable = True, |
| 717 | fragments = ["cpp"], |
| 718 | ) |
| 719 | |
| 720 | go_test = rule( |
| 721 | go_test_impl, |
| 722 | attrs = go_library_attrs + _crosstool_attrs + go_link_attrs + { |
| 723 | "test_generator": attr.label( |
| 724 | executable = True, |
| 725 | default = Label( |
| 726 | "//go/tools:generate_test_main", |
| 727 | ), |
| 728 | cfg = "host", |
| 729 | ), |
| 730 | }, |
| 731 | executable = True, |
| 732 | fragments = ["cpp"], |
| 733 | test = True, |
| 734 | ) |
| 735 | |
| 736 | def _pkg_dir(workspace_root, package_name): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 737 | if workspace_root and package_name: |
| 738 | return workspace_root + "/" + package_name |
| 739 | if workspace_root: |
| 740 | return workspace_root |
| 741 | if package_name: |
| 742 | return package_name |
| 743 | return "." |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 744 | |
| 745 | def _exec_path(path): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 746 | if path.startswith("/"): |
| 747 | return path |
| 748 | return "${execroot}/" + path |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 749 | |
| 750 | def _cgo_filter_srcs_impl(ctx): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 751 | srcs = ctx.files.srcs |
| 752 | dsts = [] |
| 753 | cmds = [] |
| 754 | for src in srcs: |
| 755 | stem, _, ext = src.path.rpartition(".") |
| 756 | dst_basename = "%s.filtered.%s" % (stem, ext) |
| 757 | dst = ctx.new_file(src, dst_basename) |
| 758 | cmds += [ |
| 759 | "if '%s' -cgo -quiet '%s'; then" % |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 760 | (ctx.executable._filter_tags.path, src.path), |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 761 | " cp '%s' '%s'" % (src.path, dst.path), |
| 762 | "else", |
| 763 | " echo -n >'%s'" % dst.path, |
| 764 | "fi", |
| 765 | ] |
| 766 | dsts.append(dst) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 767 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 768 | if ctx.label.package == "": |
| 769 | script_name = ctx.label.name + ".CGoFilterSrcs.params" |
| 770 | else: |
| 771 | script_name = ctx.label.package + "/" + ctx.label.name + ".CGoFilterSrcs.params" |
| 772 | f = _emit_generate_params_action(cmds, ctx, script_name) |
| 773 | ctx.action( |
| 774 | inputs = [f, ctx.executable._filter_tags] + srcs, |
| 775 | outputs = dsts, |
| 776 | command = f.path, |
| 777 | mnemonic = "CgoFilterSrcs", |
| 778 | ) |
| 779 | return struct( |
| 780 | files = depset(dsts), |
| 781 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 782 | |
| 783 | _cgo_filter_srcs = rule( |
| 784 | implementation = _cgo_filter_srcs_impl, |
| 785 | attrs = { |
| 786 | "srcs": attr.label_list( |
| 787 | allow_files = cgo_filetype, |
| 788 | ), |
| 789 | "_filter_tags": attr.label( |
| 790 | default = Label("//go/tools/filter_tags"), |
| 791 | cfg = "host", |
| 792 | executable = True, |
| 793 | single_file = True, |
| 794 | ), |
| 795 | }, |
| 796 | fragments = ["cpp"], |
| 797 | ) |
| 798 | |
| 799 | def _cgo_codegen_impl(ctx): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 800 | go_srcs = ctx.files.srcs |
| 801 | srcs = go_srcs + ctx.files.c_hdrs |
| 802 | linkopts = ctx.attr.linkopts |
| 803 | copts = ctx.fragments.cpp.c_options + ctx.attr.copts |
| 804 | deps = depset([], order = "topological") |
| 805 | for d in ctx.attr.deps: |
| 806 | srcs += list(d.cc.transitive_headers) |
| 807 | deps += d.cc.libs |
| 808 | copts += ["-D" + define for define in d.cc.defines] |
| 809 | for inc in d.cc.include_directories: |
| 810 | copts += ["-I", _exec_path(inc)] |
| 811 | for hdr in ctx.files.c_hdrs: |
| 812 | copts += ["-iquote", hdr.dirname] |
| 813 | for inc in d.cc.quote_include_directories: |
| 814 | copts += ["-iquote", _exec_path(inc)] |
| 815 | for inc in d.cc.system_include_directories: |
| 816 | copts += ["-isystem", _exec_path(inc)] |
| 817 | for lib in d.cc.libs: |
| 818 | if lib.basename.startswith("lib") and lib.basename.endswith(".so"): |
| 819 | linkopts += ["-L", lib.dirname, "-l", lib.basename[3:-3]] |
| 820 | else: |
| 821 | linkopts += [lib.path] |
| 822 | linkopts += d.cc.link_flags |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 823 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 824 | p = _pkg_dir(ctx.label.workspace_root, ctx.label.package) + "/" |
| 825 | if p == "./": |
| 826 | p = "" # workaround when cgo_library in repository root |
| 827 | out_dir = (ctx.configuration.genfiles_dir.path + "/" + |
| 828 | p + ctx.attr.outdir) |
| 829 | cc = ctx.fragments.cpp.compiler_executable |
| 830 | cmds = [ |
| 831 | # We cannot use env for CC because $(CC) on OSX is relative |
| 832 | # and '../' does not work fine due to symlinks. |
| 833 | "export CC=$(cd $(dirname {cc}); pwd)/$(basename {cc})".format(cc = cc), |
| 834 | "export CXX=$CC", |
| 835 | 'objdir="%s/gen"' % out_dir, |
| 836 | "execroot=$(pwd)", |
| 837 | 'mkdir -p "$objdir"', |
| 838 | "unfiltered_go_files=(%s)" % " ".join(["'%s'" % f.path for f in go_srcs]), |
| 839 | "filtered_go_files=()", |
| 840 | 'for file in "${unfiltered_go_files[@]}"; do', |
| 841 | ' stem=$(basename "$file" .go)', |
| 842 | ' if %s -cgo -quiet "$file"; then' % ctx.executable._filter_tags.path, |
| 843 | ' filtered_go_files+=("$file")', |
| 844 | " else", |
| 845 | ' grep --max-count 1 "^package " "$file" >"$objdir/$stem.go"', |
| 846 | ' echo -n >"$objdir/$stem.c"', |
| 847 | " fi", |
| 848 | "done", |
| 849 | "if [ ${#filtered_go_files[@]} -eq 0 ]; then", |
| 850 | " echo no buildable Go source files in %s >&1" % str(ctx.label), |
| 851 | " exit 1", |
| 852 | "fi", |
| 853 | '"$GOROOT/bin/go" tool cgo -objdir "$objdir" -- %s "${filtered_go_files[@]}"' % |
| 854 | " ".join(['"%s"' % copt for copt in copts]), |
| 855 | # Rename the outputs using glob so we don't have to understand cgo's mangling |
| 856 | # TODO(#350): might be fixed by this?. |
| 857 | 'for file in "${filtered_go_files[@]}"; do', |
| 858 | ' stem=$(basename "$file" .go)', |
| 859 | ' mv "$objdir/"*"$stem.cgo1.go" "$objdir/$stem.go"', |
| 860 | ' mv "$objdir/"*"$stem.cgo2.c" "$objdir/$stem.c"', |
| 861 | "done", |
| 862 | "rm -f $objdir/_cgo_.o $objdir/_cgo_flags", |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 863 | ] |
| 864 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 865 | f = _emit_generate_params_action(cmds, ctx, out_dir + ".CGoCodeGenFile.params") |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 866 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 867 | inputs = (srcs + ctx.files.toolchain + ctx.files._crosstool + |
| 868 | [f, ctx.executable._filter_tags]) |
| 869 | ctx.action( |
| 870 | inputs = inputs, |
| 871 | outputs = ctx.outputs.outs, |
| 872 | mnemonic = "CGoCodeGen", |
| 873 | progress_message = "CGoCodeGen %s" % ctx.label, |
| 874 | command = f.path, |
| 875 | env = go_environment_vars(ctx) + { |
| 876 | "CGO_LDFLAGS": " ".join(linkopts), |
| 877 | }, |
| 878 | ) |
| 879 | return struct( |
| 880 | label = ctx.label, |
| 881 | files = depset(ctx.outputs.outs), |
| 882 | cgo_deps = deps, |
| 883 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 884 | |
| 885 | _cgo_codegen_rule = rule( |
| 886 | _cgo_codegen_impl, |
| 887 | attrs = go_env_attrs + _crosstool_attrs + { |
| 888 | "srcs": attr.label_list( |
| 889 | allow_files = go_filetype, |
| 890 | non_empty = True, |
| 891 | ), |
| 892 | "c_hdrs": attr.label_list( |
| 893 | allow_files = cc_hdr_filetype, |
| 894 | ), |
| 895 | "deps": attr.label_list( |
| 896 | allow_files = False, |
| 897 | providers = ["cc"], |
| 898 | ), |
| 899 | "copts": attr.string_list(), |
| 900 | "linkopts": attr.string_list(), |
| 901 | "outdir": attr.string(mandatory = True), |
| 902 | "outs": attr.output_list( |
| 903 | mandatory = True, |
| 904 | non_empty = True, |
| 905 | ), |
| 906 | }, |
| 907 | fragments = ["cpp"], |
| 908 | output_to_genfiles = True, |
| 909 | ) |
| 910 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 911 | def _cgo_codegen( |
| 912 | name, |
| 913 | srcs, |
| 914 | c_hdrs = [], |
| 915 | deps = [], |
| 916 | copts = [], |
| 917 | linkopts = [], |
| 918 | go_tool = None, |
| 919 | toolchain = None): |
| 920 | """Generates glue codes for interop between C and Go |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 921 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 922 | Args: |
| 923 | name: A unique name of the rule |
| 924 | srcs: list of Go source files. |
| 925 | Each of them must contain `import "C"`. |
| 926 | c_hdrs: C/C++ header files necessary to determine kinds of |
| 927 | C/C++ identifiers in srcs. |
| 928 | deps: A list of cc_library rules. |
| 929 | The generated codes are expected to be linked with these deps. |
| 930 | linkopts: A list of linker options, |
| 931 | These flags are passed to the linker when the generated codes |
| 932 | are linked into the target binary. |
| 933 | """ |
| 934 | outdir = name + ".dir" |
| 935 | outgen = outdir + "/gen" |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 936 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 937 | go_thunks = [] |
| 938 | c_thunks = [] |
| 939 | for s in srcs: |
| 940 | if not s.endswith(".go"): |
| 941 | fail("not a .go file: %s" % s) |
| 942 | basename = s[:-3] |
| 943 | if basename.rfind("/") >= 0: |
| 944 | basename = basename[basename.rfind("/") + 1:] |
| 945 | go_thunks.append(outgen + "/" + basename + ".go") |
| 946 | c_thunks.append(outgen + "/" + basename + ".c") |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 947 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 948 | outs = struct( |
| 949 | name = name, |
| 950 | outdir = outgen, |
| 951 | go_thunks = go_thunks, |
| 952 | c_thunks = c_thunks, |
| 953 | c_exports = [ |
| 954 | outgen + "/_cgo_export.c", |
| 955 | outgen + "/_cgo_export.h", |
| 956 | ], |
| 957 | c_dummy = outgen + "/_cgo_main.c", |
| 958 | gotypes = outgen + "/_cgo_gotypes.go", |
| 959 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 960 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 961 | _cgo_codegen_rule( |
| 962 | name = name, |
| 963 | srcs = srcs, |
| 964 | c_hdrs = c_hdrs, |
| 965 | deps = deps, |
| 966 | copts = copts, |
| 967 | linkopts = linkopts, |
| 968 | go_tool = go_tool, |
| 969 | toolchain = toolchain, |
| 970 | outdir = outdir, |
| 971 | outs = outs.go_thunks + outs.c_thunks + outs.c_exports + [ |
| 972 | outs.c_dummy, |
| 973 | outs.gotypes, |
| 974 | ], |
| 975 | visibility = ["//visibility:private"], |
| 976 | ) |
| 977 | return outs |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 978 | |
| 979 | def _cgo_import_impl(ctx): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 980 | cmds = [ |
| 981 | (ctx.file.go_tool.path + " tool cgo" + |
| 982 | " -dynout " + ctx.outputs.out.path + |
| 983 | " -dynimport " + ctx.file.cgo_o.path + |
| 984 | " -dynpackage $(%s %s)" % ( |
| 985 | ctx.executable._extract_package.path, |
| 986 | ctx.file.sample_go_src.path, |
| 987 | )), |
| 988 | ] |
| 989 | f = _emit_generate_params_action(cmds, ctx, ctx.outputs.out.path + ".CGoImportGenFile.params") |
| 990 | ctx.action( |
| 991 | inputs = (ctx.files.toolchain + |
| 992 | [ |
| 993 | f, |
| 994 | ctx.file.go_tool, |
| 995 | ctx.executable._extract_package, |
| 996 | ctx.file.cgo_o, |
| 997 | ctx.file.sample_go_src, |
| 998 | ]), |
| 999 | outputs = [ctx.outputs.out], |
| 1000 | command = f.path, |
| 1001 | mnemonic = "CGoImportGen", |
| 1002 | env = go_environment_vars(ctx), |
| 1003 | ) |
| 1004 | return struct( |
| 1005 | files = depset([ctx.outputs.out]), |
| 1006 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1007 | |
| 1008 | _cgo_import = rule( |
| 1009 | _cgo_import_impl, |
| 1010 | attrs = go_env_attrs + { |
| 1011 | "cgo_o": attr.label( |
| 1012 | allow_files = True, |
| 1013 | single_file = True, |
| 1014 | ), |
| 1015 | "sample_go_src": attr.label( |
| 1016 | allow_files = True, |
| 1017 | single_file = True, |
| 1018 | ), |
| 1019 | "out": attr.output( |
| 1020 | mandatory = True, |
| 1021 | ), |
| 1022 | "_extract_package": attr.label( |
| 1023 | default = Label("//go/tools/extract_package"), |
| 1024 | executable = True, |
| 1025 | cfg = "host", |
| 1026 | ), |
| 1027 | }, |
| 1028 | fragments = ["cpp"], |
| 1029 | ) |
| 1030 | |
| 1031 | def _cgo_genrule_impl(ctx): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1032 | return struct( |
| 1033 | label = ctx.label, |
| 1034 | go_sources = ctx.files.srcs, |
| 1035 | asm_sources = [], |
| 1036 | asm_headers = [], |
| 1037 | cgo_object = ctx.attr.cgo_object, |
| 1038 | direct_deps = ctx.attr.deps, |
| 1039 | gc_goopts = [], |
| 1040 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1041 | |
| 1042 | _cgo_genrule = rule( |
| 1043 | _cgo_genrule_impl, |
| 1044 | attrs = { |
| 1045 | "srcs": attr.label_list(allow_files = FileType([".go"])), |
| 1046 | "cgo_object": attr.label( |
| 1047 | providers = [ |
| 1048 | "cgo_obj", |
| 1049 | "cgo_deps", |
| 1050 | ], |
| 1051 | ), |
| 1052 | "deps": attr.label_list( |
| 1053 | providers = [ |
| 1054 | "direct_deps", |
| 1055 | "transitive_go_library_paths", |
| 1056 | "transitive_go_libraries", |
| 1057 | "transitive_cgo_deps", |
| 1058 | ], |
| 1059 | ), |
| 1060 | }, |
| 1061 | fragments = ["cpp"], |
| 1062 | ) |
| 1063 | |
| 1064 | """Generates symbol-import directives for cgo |
| 1065 | |
| 1066 | Args: |
| 1067 | cgo_o: The loadable object to extract dynamic symbols from. |
| 1068 | sample_go_src: A go source which is compiled together with the generated file. |
| 1069 | The generated file will have the same Go package name as this file. |
| 1070 | out: Destination of the generated codes. |
| 1071 | """ |
| 1072 | |
| 1073 | def _cgo_object_impl(ctx): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1074 | arguments = _c_linker_options(ctx, blocklist = [ |
| 1075 | # never link any dependency libraries |
| 1076 | "-l", |
| 1077 | "-L", |
| 1078 | # manage flags to ld(1) by ourselves |
| 1079 | "-Wl,", |
| 1080 | ]) |
| 1081 | arguments += [ |
| 1082 | "-o", |
| 1083 | ctx.outputs.out.path, |
| 1084 | "-nostdlib", |
| 1085 | "-Wl,-r", |
| 1086 | ] |
| 1087 | if _is_darwin_cpu(ctx): |
| 1088 | arguments += ["-shared", "-Wl,-all_load"] |
| 1089 | else: |
| 1090 | arguments += ["-Wl,-whole-archive"] |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1091 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1092 | lo = ctx.files.src[-1] |
| 1093 | arguments += [lo.path] |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1094 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1095 | ctx.action( |
| 1096 | inputs = [lo] + ctx.files._crosstool, |
| 1097 | outputs = [ctx.outputs.out], |
| 1098 | mnemonic = "CGoObject", |
| 1099 | progress_message = "Linking %s" % ctx.outputs.out.short_path, |
| 1100 | executable = ctx.fragments.cpp.compiler_executable, |
| 1101 | arguments = arguments, |
| 1102 | ) |
| 1103 | runfiles = ctx.runfiles(collect_data = True) |
| 1104 | runfiles = runfiles.merge(ctx.attr.src.data_runfiles) |
| 1105 | return struct( |
| 1106 | files = depset([ctx.outputs.out]), |
| 1107 | cgo_obj = ctx.outputs.out, |
| 1108 | cgo_deps = ctx.attr.cgogen.cgo_deps, |
| 1109 | runfiles = runfiles, |
| 1110 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1111 | |
| 1112 | _cgo_object = rule( |
| 1113 | _cgo_object_impl, |
| 1114 | attrs = _crosstool_attrs + { |
| 1115 | "src": attr.label( |
| 1116 | mandatory = True, |
| 1117 | providers = ["cc"], |
| 1118 | ), |
| 1119 | "cgogen": attr.label( |
| 1120 | mandatory = True, |
| 1121 | providers = ["cgo_deps"], |
| 1122 | ), |
| 1123 | "out": attr.output( |
| 1124 | mandatory = True, |
| 1125 | ), |
| 1126 | }, |
| 1127 | fragments = ["cpp"], |
| 1128 | ) |
| 1129 | |
| 1130 | """Generates _all.o to be archived together with Go objects. |
| 1131 | |
| 1132 | Args: |
| 1133 | src: source static library which contains objects |
| 1134 | cgogen: _cgo_codegen rule which knows the dependency cc_library() rules |
| 1135 | to be linked together with src when we generate the final go binary. |
| 1136 | """ |
| 1137 | |
| 1138 | def _setup_cgo_library(name, srcs, cdeps, copts, clinkopts, go_tool, toolchain): |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1139 | go_srcs = [s for s in srcs if s.endswith(".go")] |
| 1140 | c_hdrs = [s for s in srcs if any([s.endswith(ext) for ext in hdr_exts])] |
| 1141 | c_srcs = [s for s in srcs if not s in (go_srcs + c_hdrs)] |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1142 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1143 | # Split cgo files into .go parts and .c parts (plus some other files). |
| 1144 | cgogen = _cgo_codegen( |
| 1145 | name = name + ".cgo", |
| 1146 | srcs = go_srcs, |
| 1147 | c_hdrs = c_hdrs, |
| 1148 | deps = cdeps, |
| 1149 | copts = copts, |
| 1150 | linkopts = clinkopts, |
| 1151 | go_tool = go_tool, |
| 1152 | toolchain = toolchain, |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1153 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1154 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1155 | # Filter c_srcs with build constraints. |
| 1156 | c_filtered_srcs = [] |
| 1157 | if len(c_srcs) > 0: |
| 1158 | c_filtered_srcs_name = name + "_filter_cgo_srcs" |
| 1159 | _cgo_filter_srcs( |
| 1160 | name = c_filtered_srcs_name, |
| 1161 | srcs = c_srcs, |
| 1162 | ) |
| 1163 | c_filtered_srcs.append(":" + c_filtered_srcs_name) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1164 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1165 | pkg_dir = _pkg_dir( |
| 1166 | "external/" + REPOSITORY_NAME[1:] if len(REPOSITORY_NAME) > 1 else "", |
| 1167 | PACKAGE_NAME, |
| 1168 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1169 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1170 | # Platform-specific settings |
| 1171 | native.config_setting( |
| 1172 | name = name + "_windows_setting", |
| 1173 | values = { |
| 1174 | "cpu": "x64_windows_msvc", |
| 1175 | }, |
| 1176 | ) |
| 1177 | platform_copts = select({ |
| 1178 | ":" + name + "_windows_setting": ["-mthreads"], |
| 1179 | "//conditions:default": ["-pthread"], |
| 1180 | }) |
| 1181 | platform_linkopts = select({ |
| 1182 | ":" + name + "_windows_setting": ["-mthreads"], |
| 1183 | "//conditions:default": ["-pthread"], |
| 1184 | }) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1185 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1186 | # Bundles objects into an archive so that _cgo_.o and _all.o can share them. |
| 1187 | native.cc_library( |
| 1188 | name = cgogen.outdir + "/_cgo_lib", |
| 1189 | srcs = cgogen.c_thunks + cgogen.c_exports + c_filtered_srcs + c_hdrs, |
| 1190 | deps = cdeps, |
| 1191 | copts = copts + platform_copts + [ |
| 1192 | "-I", |
| 1193 | pkg_dir, |
| 1194 | "-I", |
| 1195 | "$(GENDIR)/" + pkg_dir + "/" + cgogen.outdir, |
| 1196 | # The generated thunks often contain unused variables. |
| 1197 | "-Wno-unused-variable", |
| 1198 | ], |
| 1199 | linkopts = clinkopts + platform_linkopts, |
| 1200 | linkstatic = 1, |
| 1201 | # _cgo_.o and _all.o keep all objects in this archive. |
| 1202 | # But it should not be very annoying in the final binary target |
| 1203 | # because _cgo_object rule does not propagate alwayslink=1 |
| 1204 | alwayslink = 1, |
| 1205 | visibility = ["//visibility:private"], |
| 1206 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1207 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1208 | # Loadable object which cgo reads when it generates _cgo_import.go |
| 1209 | native.cc_binary( |
| 1210 | name = cgogen.outdir + "/_cgo_.o", |
| 1211 | srcs = [cgogen.c_dummy], |
| 1212 | deps = cdeps + [cgogen.outdir + "/_cgo_lib"], |
| 1213 | copts = copts, |
| 1214 | linkopts = clinkopts, |
| 1215 | visibility = ["//visibility:private"], |
| 1216 | ) |
| 1217 | _cgo_import( |
| 1218 | name = "%s.cgo.importgen" % name, |
| 1219 | cgo_o = cgogen.outdir + "/_cgo_.o", |
| 1220 | out = cgogen.outdir + "/_cgo_import.go", |
| 1221 | sample_go_src = go_srcs[0], |
| 1222 | go_tool = go_tool, |
| 1223 | toolchain = toolchain, |
| 1224 | visibility = ["//visibility:private"], |
| 1225 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1226 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1227 | _cgo_object( |
| 1228 | name = cgogen.outdir + "/_cgo_object", |
| 1229 | src = cgogen.outdir + "/_cgo_lib", |
| 1230 | out = cgogen.outdir + "/_all.o", |
| 1231 | cgogen = cgogen.name, |
| 1232 | visibility = ["//visibility:private"], |
| 1233 | ) |
| 1234 | return cgogen |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1235 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1236 | def cgo_genrule( |
| 1237 | name, |
| 1238 | srcs, |
| 1239 | copts = [], |
| 1240 | clinkopts = [], |
| 1241 | cdeps = [], |
| 1242 | **kwargs): |
| 1243 | cgogen = _setup_cgo_library( |
| 1244 | name = name, |
| 1245 | srcs = srcs, |
| 1246 | cdeps = cdeps, |
| 1247 | copts = copts, |
| 1248 | clinkopts = clinkopts, |
| 1249 | toolchain = None, |
| 1250 | go_tool = None, |
| 1251 | ) |
| 1252 | _cgo_genrule( |
| 1253 | name = name, |
| 1254 | srcs = cgogen.go_thunks + [ |
| 1255 | cgogen.gotypes, |
| 1256 | cgogen.outdir + "/_cgo_import.go", |
| 1257 | ], |
| 1258 | cgo_object = cgogen.outdir + "/_cgo_object", |
| 1259 | **kwargs |
| 1260 | ) |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1261 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1262 | def cgo_library( |
| 1263 | name, |
| 1264 | srcs, |
| 1265 | toolchain = None, |
| 1266 | go_tool = None, |
| 1267 | copts = [], |
| 1268 | clinkopts = [], |
| 1269 | cdeps = [], |
| 1270 | **kwargs): |
| 1271 | """Builds a cgo-enabled go library. |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1272 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1273 | Args: |
| 1274 | name: A unique name for this rule. |
| 1275 | srcs: List of Go, C and C++ files that are processed to build a Go library. |
| 1276 | Those Go files must contain `import "C"`. |
| 1277 | C and C++ files can be anything allowed in `srcs` attribute of |
| 1278 | `cc_library`. |
| 1279 | copts: Add these flags to the C++ compiler. |
| 1280 | clinkopts: Add these flags to the C++ linker. |
| 1281 | cdeps: List of C/C++ libraries to be linked into the binary target. |
| 1282 | They must be `cc_library` rules. |
| 1283 | deps: List of other libraries to be linked to this library target. |
| 1284 | data: List of files needed by this rule at runtime. |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1285 | |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1286 | NOTE: |
| 1287 | `srcs` cannot contain pure-Go files, which do not have `import "C"`. |
| 1288 | So you need to define another `go_library` when you build a go package with |
| 1289 | both cgo-enabled and pure-Go sources. |
| 1290 | |
| 1291 | ``` |
| 1292 | cgo_library( |
| 1293 | name = "cgo_enabled", |
| 1294 | srcs = ["cgo-enabled.go", "foo.cc", "bar.S", "baz.a"], |
| 1295 | ) |
| 1296 | |
| 1297 | go_library( |
| 1298 | name = "go_default_library", |
| 1299 | srcs = ["pure-go.go"], |
| 1300 | library = ":cgo_enabled", |
| 1301 | ) |
| 1302 | ``` |
| 1303 | """ |
| 1304 | cgogen = _setup_cgo_library( |
| 1305 | name = name, |
| 1306 | srcs = srcs, |
| 1307 | cdeps = cdeps, |
| 1308 | copts = copts, |
| 1309 | clinkopts = clinkopts, |
| 1310 | go_tool = go_tool, |
| 1311 | toolchain = toolchain, |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1312 | ) |
| 1313 | |
| 1314 | go_library( |
alandonovan | f935de8 | 2021-01-22 14:46:13 -0500 | [diff] [blame] | 1315 | name = name, |
| 1316 | srcs = cgogen.go_thunks + [ |
| 1317 | cgogen.gotypes, |
| 1318 | cgogen.outdir + "/_cgo_import.go", |
| 1319 | ], |
| 1320 | cgo_object = cgogen.outdir + "/_cgo_object", |
| 1321 | go_tool = go_tool, |
| 1322 | toolchain = toolchain, |
| 1323 | **kwargs |
Alan Donovan | 312d1a5 | 2017-10-02 10:10:28 -0400 | [diff] [blame] | 1324 | ) |