[bazel] Improve vendored deps, make libssh vendored (#8948)
TL;DR: kill https://github.com/wpilibsuite/bzlmodRio-libssh, update
versions, and make things easier for a script to update.
The main motivation behind this was that libssh was out of date with the
gradle version. Using these "external" dependencies can cause agita as
we churn through toolchain updates. Unlike the toolchains and opencv,
which can be used by external users (i.e. a all bazel robot, if a vendor
wanted to use bazel) a C++ wrapper around libssh maven deps almost
certainly wouldn't be pulled in, much like ceres and mrclib.
As a result of vendor'ing libssh, and knowing some potential pitfalls
and annoyances, this PR does the following:
- Vendor libssh, akin to how mrclib is pulled in
- Moves the vendor'd ceres to `shared/bazel/thirdparty`, and refactors
it to better match mrclib. To me it doesn't necessarily belong in its
`thirdparty` location because it is bazel only.
- Due to the refactoring, libssh and ceres can now be pulled into
`MODULE.bazel` instead of the `WORKSPACE.bzlmod` helper. This is good
prep for a potential upgrade to killing `--enable_workspace` / bazel 9
- Write a python script that can deal with the integrity / sha256 of the
http_archives. I suggested this be added to davo's mrclib PR, but this
one is a little bit more robust and will actually edit the files in
place. This makes upgrading versions substantially easier.
- Upgrade libssh version to what gradle is using, and mrclib to the
version in #8858. These changes have been tested against that PR.
2026-06-19 18:25:07 -04:00
|
|
|
import tempfile
|
|
|
|
|
import hashlib
|
|
|
|
|
from urllib.request import urlopen
|
|
|
|
|
import os
|
|
|
|
|
import base64
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def __try_download_sha(base_url, use_base64):
|
|
|
|
|
url = base_url + ".sha256"
|
|
|
|
|
print(f"Loading {url}")
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
url_result = urlopen(url)
|
|
|
|
|
except:
|
|
|
|
|
print(f"No uploaded sha256 hash at {url}")
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
data = url_result.read()
|
|
|
|
|
|
|
|
|
|
sha_hex = data.decode("utf-8")
|
|
|
|
|
if use_base64:
|
|
|
|
|
return "sha256-" + base64.b64encode(bytes.fromhex(sha_hex)).decode("utf-8")
|
|
|
|
|
return sha_hex
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def download_integrities(
|
|
|
|
|
module_file: str,
|
|
|
|
|
has_headers: bool,
|
|
|
|
|
classifiers: list[str],
|
|
|
|
|
url_base: str,
|
|
|
|
|
use_base64: bool,
|
|
|
|
|
):
|
|
|
|
|
hash_output = "# Generated by shared/bazel/thirdparty/integrity_helper.py\n"
|
|
|
|
|
|
|
|
|
|
hash_output += f'url_pattern = "{url_base}"\n\n'
|
|
|
|
|
|
|
|
|
|
if has_headers:
|
|
|
|
|
url = url_base % "headers"
|
|
|
|
|
sha = __try_download_sha(url, use_base64)
|
|
|
|
|
hash_output += f'headers_integrity = "{sha}"\n\n'
|
|
|
|
|
|
|
|
|
|
hash_output += "_LIB_ARTIFACTS = {\n"
|
|
|
|
|
|
|
|
|
|
static_glob_lookup = {
|
|
|
|
|
"linux": "**/*.a",
|
|
|
|
|
"osx": "**/*.a",
|
|
|
|
|
"windows": "**/*.lib",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
shared_glob_lookup = {
|
|
|
|
|
"linux": "**/*.so*",
|
|
|
|
|
"osx": "**/*.dylib",
|
|
|
|
|
"windows": "**/*.dll",
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for suffix in classifiers:
|
|
|
|
|
url = url_base % suffix
|
|
|
|
|
sha = __try_download_sha(url, use_base64)
|
|
|
|
|
|
|
|
|
|
glob_lookup = static_glob_lookup if "static" in suffix else shared_glob_lookup
|
|
|
|
|
|
|
|
|
|
if "linux" in suffix:
|
|
|
|
|
simple_suffix = "linux"
|
|
|
|
|
elif "osx" in suffix:
|
|
|
|
|
simple_suffix = "osx"
|
|
|
|
|
elif "windows" in suffix:
|
|
|
|
|
simple_suffix = "windows"
|
|
|
|
|
|
|
|
|
|
hash_output += f' "{suffix}": ("{simple_suffix}", "{glob_lookup[simple_suffix]}", "{sha}"),\n'
|
|
|
|
|
|
|
|
|
|
hash_output += "}\n"
|
|
|
|
|
hash_output += "# End auto-gen\n"
|
|
|
|
|
|
|
|
|
|
updated_contents = ""
|
|
|
|
|
with open(module_file, "r") as f:
|
|
|
|
|
# Grab all the stuff before the auto gen
|
|
|
|
|
for line in f:
|
|
|
|
|
if line.startswith(
|
|
|
|
|
"# Generated by shared/bazel/thirdparty/integrity_helper.py"
|
|
|
|
|
):
|
|
|
|
|
break
|
|
|
|
|
updated_contents += line
|
|
|
|
|
|
|
|
|
|
updated_contents += hash_output
|
|
|
|
|
|
|
|
|
|
# Skip the autogen chunk
|
|
|
|
|
for line in f:
|
|
|
|
|
if line.startswith("# End auto-gen"):
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
updated_contents += "".join(f)
|
|
|
|
|
|
|
|
|
|
with open(module_file, "w") as f:
|
|
|
|
|
f.write(updated_contents)
|
|
|
|
|
|
|
|
|
|
# print(updated_contents)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_ceres():
|
|
|
|
|
# Keep in sync with shared/ceres.gradle
|
|
|
|
|
year = "frc2026"
|
|
|
|
|
version = "2.2-1"
|
|
|
|
|
|
|
|
|
|
has_headers = True
|
|
|
|
|
classifiers = [
|
|
|
|
|
"linuxarm32static",
|
|
|
|
|
"linuxarm32staticdebug",
|
|
|
|
|
"linuxarm64static",
|
|
|
|
|
"linuxarm64staticdebug",
|
|
|
|
|
"linuxx86-64static",
|
|
|
|
|
"linuxx86-64staticdebug",
|
|
|
|
|
"osxuniversalstatic",
|
|
|
|
|
"osxuniversalstaticdebug",
|
|
|
|
|
"windowsarm64static",
|
|
|
|
|
"windowsarm64staticdebug",
|
|
|
|
|
"windowsx86-64static",
|
|
|
|
|
"windowsx86-64staticdebug",
|
|
|
|
|
]
|
|
|
|
|
url_base = f"https://frcmaven.wpi.edu/artifactory/development/edu/wpi/first/thirdparty/{year}/ceres/ceres-cpp/{version}/ceres-cpp-{version}-%s.zip"
|
|
|
|
|
|
|
|
|
|
download_integrities(
|
|
|
|
|
"shared/bazel/thirdparty/ceres/ceres.MODULE.bazel",
|
|
|
|
|
has_headers,
|
|
|
|
|
classifiers,
|
|
|
|
|
url_base,
|
|
|
|
|
True,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_libssh():
|
|
|
|
|
# Keep in sync with shared/libssh.gradle
|
|
|
|
|
version = "2027-0.120-1"
|
|
|
|
|
|
|
|
|
|
has_headers = True
|
|
|
|
|
classifiers = [
|
|
|
|
|
"linuxarm64static",
|
|
|
|
|
"linuxarm64staticdebug",
|
|
|
|
|
"linuxx86-64static",
|
|
|
|
|
"linuxx86-64staticdebug",
|
|
|
|
|
"osxuniversalstatic",
|
|
|
|
|
"osxuniversalstaticdebug",
|
|
|
|
|
"windowsx86-64static",
|
|
|
|
|
"windowsx86-64staticdebug",
|
|
|
|
|
"windowsarm64static",
|
|
|
|
|
"windowsarm64staticdebug",
|
|
|
|
|
]
|
|
|
|
|
url_base = f"https://frcmaven.wpi.edu/release/org/wpilib/thirdparty/libssh/{version}/libssh-{version}-%s.zip"
|
|
|
|
|
|
|
|
|
|
download_integrities(
|
|
|
|
|
"shared/bazel/thirdparty/libssh/libssh.MODULE.bazel",
|
|
|
|
|
has_headers,
|
|
|
|
|
classifiers,
|
|
|
|
|
url_base,
|
|
|
|
|
False,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def update_mrclib():
|
|
|
|
|
# Keep in sync with shared/libmrclib.gradle
|
2026-06-20 10:28:24 -07:00
|
|
|
version = "2027.1.0-alpha-1-65-g21f308e"
|
[bazel] Improve vendored deps, make libssh vendored (#8948)
TL;DR: kill https://github.com/wpilibsuite/bzlmodRio-libssh, update
versions, and make things easier for a script to update.
The main motivation behind this was that libssh was out of date with the
gradle version. Using these "external" dependencies can cause agita as
we churn through toolchain updates. Unlike the toolchains and opencv,
which can be used by external users (i.e. a all bazel robot, if a vendor
wanted to use bazel) a C++ wrapper around libssh maven deps almost
certainly wouldn't be pulled in, much like ceres and mrclib.
As a result of vendor'ing libssh, and knowing some potential pitfalls
and annoyances, this PR does the following:
- Vendor libssh, akin to how mrclib is pulled in
- Moves the vendor'd ceres to `shared/bazel/thirdparty`, and refactors
it to better match mrclib. To me it doesn't necessarily belong in its
`thirdparty` location because it is bazel only.
- Due to the refactoring, libssh and ceres can now be pulled into
`MODULE.bazel` instead of the `WORKSPACE.bzlmod` helper. This is good
prep for a potential upgrade to killing `--enable_workspace` / bazel 9
- Write a python script that can deal with the integrity / sha256 of the
http_archives. I suggested this be added to davo's mrclib PR, but this
one is a little bit more robust and will actually edit the files in
place. This makes upgrading versions substantially easier.
- Upgrade libssh version to what gradle is using, and mrclib to the
version in #8858. These changes have been tested against that PR.
2026-06-19 18:25:07 -04:00
|
|
|
|
|
|
|
|
has_headers = True
|
|
|
|
|
classifiers = [
|
|
|
|
|
"linuxarm64",
|
|
|
|
|
"linuxx86-64",
|
|
|
|
|
"osxuniversal",
|
|
|
|
|
"linuxsystemcore",
|
|
|
|
|
"windowsarm64",
|
|
|
|
|
"windowsx86-64",
|
|
|
|
|
]
|
|
|
|
|
url_base = f"https://frcmaven.wpi.edu/artifactory/development-2027/org/wpilib/mrclib/mrclib-cpp/{version}/mrclib-cpp-{version}-%s.zip"
|
|
|
|
|
|
|
|
|
|
download_integrities(
|
|
|
|
|
"shared/bazel/thirdparty/mrclib/mrclib.MODULE.bazel",
|
|
|
|
|
has_headers,
|
|
|
|
|
classifiers,
|
|
|
|
|
url_base,
|
|
|
|
|
False,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
update_ceres()
|
|
|
|
|
update_libssh()
|
|
|
|
|
update_mrclib()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
|
# python3 shared/bazel/thirdparty/integrity_helper.py
|
|
|
|
|
main()
|