[python] Improve robotpy generation (#8867)

The initial build file generation for robotpy projects was relatively
naive and purpose built to get `allwpilib` compiling, without supporting
all the available features.

This modifies the generation scripts to be able to support multiple
embedded libraries, which will be necessary for #8858, since `mrclib.so`
will need to be bundled along with the hal libraries. In addition some
cleanup was done to get the wheels looking more like what is in pypi.
This commit is contained in:
PJ Reiniger
2026-05-15 00:52:39 -04:00
committed by GitHub
parent 3f1cf3cabe
commit 68d24bb29e
57 changed files with 530 additions and 254 deletions

View File

@@ -0,0 +1,201 @@
load("@aspect_bazel_lib//lib:copy_file.bzl", "copy_file")
load("@pybind11_bazel//:build_defs.bzl", "pybind_extension", "pybind_library")
load("@rules_pycross//pycross:defs.bzl", "pycross_wheel_library")
load("@rules_python//python:defs.bzl", "py_library")
load("@rules_python//python:packaging.bzl", "py_wheel")
load("//shared/bazel/rules/robotpy:compatibility_select.bzl", "robotpy_compatibility_select")
def create_pybind_library(
name,
extension_name,
install_path,
generated_srcs = [],
extra_hdrs = [],
extra_srcs = [],
deps = [],
dynamic_deps = [],
semiwrap_header = [],
includes = [],
local_defines = []):
"""
Function to create a pybind C++ extension library that has been defined by a semiwrap config
Outputs:
<name>_pybind_library - A pybind_library that functions like a header-only cc_library. It will include all
of the extra_hdrs, resolve the include paths, and add a dependency on the semiwrap headers
<install_path + extension_name> - A pybind_extension that wraps the pybind_library and compiles all the source files.
Params:
extension_name - The name of the pybind extension. Should be sourced from pyproject
install_path - The subpath where the library will be installed. Should be source from pyproject
generated_srcs - List of auto-generated sources to be compiled into the extension.
extra_hdrs - Any non-autogenerated headers
extra_srcs - Any non-autogenerated sources
deps - cc_library deps used to create the pybind_library
dynamic_deps - cc_shared_library deps used to filter objects from the pybind_extension
semiwrap_header - Auto-generated file used to initialize the extension
includes - see cc_library#includes. Used during the creating of the pybind_library
local_defines - see cc_library#local_defines. Used during the compilation of the extension
"""
pybind_library(
name = "{}_pybind_library".format(name),
hdrs = extra_hdrs,
target_compatible_with = robotpy_compatibility_select(),
deps = deps + [
"//shared/bazel/rules/robotpy:semiwrap_headers",
],
includes = includes,
visibility = ["//visibility:public"],
tags = ["robotpy"],
)
extension_name = extension_name or "_{}".format(name)
pybind_extension(
name = install_path + extension_name,
srcs = extra_srcs + generated_srcs,
deps = [":{}_pybind_library".format(name)] + semiwrap_header,
dynamic_deps = dynamic_deps,
copts = select({
"@bazel_tools//src/conditions:darwin": [
"-Wno-deprecated-declarations",
"-Wno-overloaded-virtual",
"-Wno-pessimizing-move",
"-Wno-unused-value",
],
"@bazel_tools//src/conditions:linux_x86_64": [
"-Wno-attributes",
"-Wno-unused-value",
"-Wno-deprecated",
"-Wno-deprecated-declarations",
"-Wno-unused-parameter",
"-Wno-redundant-move",
"-Wno-unused-but-set-variable",
"-Wno-unused-variable",
"-Wno-pessimizing-move",
"-Wno-overloaded-virtual",
],
"@bazel_tools//src/conditions:windows": [
],
}),
target_compatible_with = robotpy_compatibility_select(),
local_defines = local_defines,
tags = ["robotpy"],
)
def robotpy_library(
name,
deps = [],
data = [],
strip_path_prefixes = None,
distribution = None,
summary = None,
project_urls = None,
author_email = None,
entry_points = None,
requires = None,
description_file = None,
python_requires = None,
**kwargs):
"""
Defines a python library that is wrapping a series of pybind extensions.
Outputs:
<name> - The python library
<name>-wheel - A wheel for the library
"""
py_library(
name = name + "-lib",
data = data,
deps = deps,
tags = ["robotpy"],
**kwargs
)
py_wheel(
name = "{}-wheel".format(name),
distribution = distribution,
stamp = 1,
version = "$(ROBOTPY_VERSION)",
summary = summary,
requires = requires,
project_urls = project_urls,
author_email = author_email,
deps = data + [":{}-lib".format(name)],
strip_path_prefixes = strip_path_prefixes,
entry_points = entry_points,
description_file = description_file,
python_requires = python_requires,
license = "BSD-3-Clause",
tags = ["robotpy"],
)
pycross_wheel_library(
name = "{}".format(name),
wheel = "{}-wheel".format(name),
deps = deps,
visibility = ["//visibility:public"],
tags = ["manual"],
)
def copy_native_file(name, library, base_path):
"""
Copies a compiled shared library into a naming format that can be used by robotpy rules. The libraries are named
differently on OSX / Linux / Windows and this creates a handy alias to for easier use downstream
"""
copy_file(
name = name + ".win_copy_lib",
src = library,
out = "{}lib/{}.dll".format(base_path, name),
tags = ["manual"],
visibility = ["//visibility:public"],
)
copy_file(
name = name + ".osx_copy_lib",
src = library,
out = "{}lib/lib{}.dylib".format(base_path, name),
tags = ["manual"],
visibility = ["//visibility:public"],
)
copy_file(
name = name + ".linux_copy_lib",
src = library,
out = "{}lib/lib{}.so".format(base_path, name),
tags = ["manual"],
visibility = ["//visibility:public"],
)
native.alias(
name = "{}.copy_lib".format(name),
actual = select({
"@bazel_tools//src/conditions:darwin": name + ".osx_copy_lib",
"@bazel_tools//src/conditions:windows": name + ".win_copy_lib",
"//conditions:default": name + ".linux_copy_lib",
}),
visibility = ["//visibility:public"],
tags = ["robotpy"],
)
def generate_native_files(name, pyproject_toml, pc_deps, libinit_files, pc_files):
cmd = "$(locations //shared/bazel/rules/robotpy/hatchlib_native_port:generate_native_lib_files) "
cmd += " $(location " + pyproject_toml + ")"
cmd += " $(location " + pc_files[0] + ") "
for pc_dep in pc_deps:
cmd += " $(location " + pc_dep + ")"
native.genrule(
name = name + ".gen",
srcs = [pyproject_toml],
outs = libinit_files + pc_files,
cmd = cmd,
tools = ["//shared/bazel/rules/robotpy/hatchlib_native_port:generate_native_lib_files"] + pc_deps,
visibility = ["//visibility:public"],
tags = ["robotpy"],
target_compatible_with = robotpy_compatibility_select(),
)
native.filegroup(
name = name + ".pc_wrapper",
srcs = pc_files,
)