rules_python
  • Python Rules for Bazel
  • Getting started
  • Using PyPI
  • Toolchains
  • Setting up coverage
  • Precompiling
  • Gazelle Plugin
  • REPL
  • Extending
  • How-to Guides
    • How to build a wheel
    • How to use a common set of dependencies with multiple PyPI versions
    • How to integrate a debugger
    • How to get the current Python version
    • How to link to libpython
      • Exposing linker flags in a rule
      • Using the rule
    • How-to: Multi-Platform PyPI Dependencies
    • How to expose headers from a PyPI package
    • How to get Python headers for C extensions
  • Contributing
  • Dev Guide
  • Support Policy
  • Changelog
  • API Reference
  • Environment Variables
  • Sphinxdocs
  • Glossary
  • Index
rules_python
  • How-to Guides
  • How to link to libpython
  • Edit on GitHub

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
    ],
)
Previous Next

© Copyright 2023, The Bazel Authors. Revision eef6df6d5e533c87437ebcd61f14ce0961306feb.

Built with Sphinx using a theme provided by Read the Docs.