blob: 3675031096d772c0fd4538f202a00701887400b0 [file] [log] [blame] [view]
:::{default-domain} bzl
:::
# How to expose headers from a PyPI package
When you depend on a PyPI package that includes C headers (like `numpy`), you
need to make those headers available to your `cc_library` or
`cc_binary` targets.
The recommended way to do this is to inject a `BUILD.bazel` file into the
external repository for the package. This `BUILD` file will create
a `cc_library` target that exposes the header files.
First, create a `.bzl` file that has the extra logic we'll inject. Putting it
in a separate bzl file avoids having to redownload and extract the whl file
when our logic changes.
```bzl
# pypi_extra_targets.bzl
load("@rules_cc//cc:cc_library.bzl", "cc_library")
def extra_numpy_targets():
cc_library(
name = "headers",
hdrs = glob(["**/*.h"]),
visibility = ["//visibility:public"],
)
```
## Bzlmod setup
In your `MODULE.bazel` file, use the `build_file_content` attribute of
`pip.parse` to inject the `BUILD` file content for the `numpy` package.
```bazel
# MODULE.bazel
load("@rules_python//python/extensions:pip.bzl", "parse", "whl_mods")
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
whl_mods = use_extension("@rules_python//python/extensions:pip.bzl", "whl_mods")
# Define a specific modification for a wheel
whl_mods(
hub_name = "pypi_mods",
whl_name = "numpy-1.0.0-py3-none-any.whl", # The exact wheel filename
additive_build_content = """
load("@//:pypi_extra_targets.bzl", "numpy_hdrs")
extra_numpy_targets()
""",
)
pip.parse(
hub_name = "pypi",
wheel_name = "numpy",
requirements_lock = "//:requirements.txt",
whl_modifications = {
"@pypi_mods//:numpy.json": "numpy",
},
extra_hub_aliases = {
"numpy": ["headers"],
}
)
```
## WORKSPACE setup
In your `WORKSPACE` file, use the `annotations` attribute of `pip_parse` to
inject additional `BUILD` file content, then use `extra_hub_targets` to expose
that target in the `@pypi` hub repo.
The {obj}`package_annotation` helper can be used to construct the value for the
`annotations` attribute.
```starlark
# WORKSPACE
load("@rules_python//python:pip.bzl", "package_annotation", "pip_parse")
pip_parse(
name = "pypi",
requirements_lock = "//:requirements.txt",
annotations = {
"numpy": package_annotation(
additive_build_content = """\
load("@//:pypi_extra_targets.bzl", "numpy_hdrs")
extra_numpy_targets()
"""
),
},
extra_hub_targets = {
"numpy": ["headers"],
},
)
```
## Using the headers
In your `BUILD.bazel` file, you can now depend on the generated `headers`
target.
```bazel
# BUILD.bazel
cc_library(
name = "my_c_extension",
srcs = ["my_c_extension.c"],
deps = ["@pypi//numpy:headers"],
)
```