I'm trying to use Bazel (v1.0.0) rules_go to build header + library as I would with go build -buildmode=c-archive
. I have the following rule set up in my BUILD.bzl file:
go_binary(
name="go_cpp_bridge",
srcs = ["cpp_bridge.go"],
cgo = True,
gc_linkopts=["-buildmode=c-shared"],
linkmode = "c-archive",
visibility = ["//visibility:public"],
)
The current code of cpp_bridge.go
is just a hello world to see if it works:
package main
import "C"
//export Add
func Add(a, b int) int { return a + b }
func main(){}
Bazel does generate a library file, but I'm missing the associated header file in the bazel-bin output. Testing with go build yields both header file and library. How do I get Bazel to give me the same.
When linkmode = "c-shared"
and linkmode = "c-archive"
are defined, there are a few additional targets that are defined by adding a suffix to the end of the go_binary
name. So for example, you can build go_cpp_bridge.c_hdrs
to get the header file. You can build go_cpp_bridge.cc
for a cc_library
that can be linked with other C/C++ targets. The header is named after the go_binary
rule (so go_cpp_bridge.h
).
To extend your example, here's a working build file:
load("@io_bazel_rules_go//go:def.bzl", "go_binary")
go_binary(
name = "go_cpp_bridge",
srcs = ["cpp_bridge.go"],
cgo = True,
linkmode = "c-archive",
)
cc_binary(
name = "main",
srcs = ["main.c"],
deps = [":go_cpp_bridge.cc"],
)
And a C program that links against Go:
#include <stdio.h>
#include "go_cpp_bridge.h"
int main() {
printf("%lld\n", Add(21, 21));
return 0;
}
This isn't documented because it's not a great interface. Since this was implemented, Bazel has added better ways to write C/C++ compatible rules, but rules_go doesn't support that yet. #2176 is the tracking issue for that.