Let’s say you are using Bazel to build a C program which links against
a system-provided version of libcurl, the multiprotocol file transfer
library. What is the best way to link your program against this library
within Bazel? This blog post provides an answer to that question.
The first option that probably comes to mind is to use cc_binary and
friend’s linkopts attribute, as in:
1
2
3
4
5
6
# BUILD file for my_programcc_binary(
name ="my_program",
srcs = [...],
linkopts = ["-lcurl"],
)
This works fine, but it does not properly integrate with
cc_binary’s linkstatic attribute which is intended to allow
a binary to choose whether to link against either the shared
or static version of a library. However, if we use cc_import
to import libcurl and use a dependency, we can make
linkstatic work as intended.
The main trick is to figure out how to reference the system-provided
library. This can be done with a little trick using an external
repository using new_local_repository(), as follows:
1
2
3
4
5
6
# WORKSPACEnew_local_repository(
name ="libcurl",
path ="/usr",
build_file ="//third_party/libcurl:libcurl.BUILD")
# BUILD file for my_programcc_binary(
name ="my_program",
srcs = [...],
deps = ["@libcurl"],
)
Recursive dependencies (e.g. in order to link lib1 you must link to lib2,
in order to link to lib2 you must also link to lib3) can be represented
as deps on the cc_import() stanza for liba, as in:
1
2
3
4
5
6
# //third_party/lib1:lib1.BUILDcc_import(
name ="lib1",
deps = ["@lib2"],
...)
1
2
3
4
5
6
# //third_party/lib2:lib2.BUILDcc_import(
name ="lib2",
deps = ["@lib3"],
...)
1
2
3
4
5
# //third_party/lib3:lib3.BUILDcc_import(
name ="lib3",
...)
I recommend using cc_import() and Bazel target dependencies over
linkopts whenever possible.