How to link to libpython
This guide explains how to use the Python toolchain to get the linker
flags required for linking against libpython. This is often necessary when
embedding Python in a C/C++ application.
Currently, the :current_py_cc_libs target does not include -lpython et al
linker flags. This is intentional because it forces dynamic linking (via the
dynamic linker processing DT_NEEDED entries), which prevents users who want
to load it in some more custom way.
Exposing linker flags in a rule
You can create a rule that gets the Python version from the toolchain and
constructs the correct linker flag. This rule can then provide the flag to
other C/C++ rules via the CcInfo provider.
Here’s an example of a rule that creates the -lpython<version> flag:
# python_libs.bzl
load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "cc_common")
def _python_libs_impl(ctx):
toolchain = ctx.toolchains["@rules_python//python:toolchain_type"]
info = toolchain.py3_runtime.interpreter_version_info
link_flag = "-lpython{}.{}".format(info.major, info.minor)
cc_info = CcInfo(
linking_context = cc_common.create_linking_context(
user_link_flags = [link_flag],
),
)
return [cc_info]
python_libs = rule(
implementation = _python_libs_impl,
toolchains = ["@rules_python//python:toolchain_type"],
)
Using the rule
In your BUILD.bazel file, define a target using this rule and add it to the
deps of your cc_binary or cc_library.
# BUILD.bazel
load(":python_libs.bzl", "python_libs")
python_libs(
name = "py_libs",
)
cc_binary(
name = "my_app",
srcs = ["my_app.c"],
deps = [
":py_libs",
# Other dependencies
],
)