Skip to content

Commit e0ca810

Browse files
authored
Investigate On-Robot Diagnostics Through a CLI Interface (#3379)
1 parent 261716e commit e0ca810

File tree

24 files changed

+1357
-37
lines changed

24 files changed

+1357
-37
lines changed

environment_setup/setup_software.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ print_status_msg "Install clang-format"
186186
install_clang_format $arch
187187
print_status_msg "Done installing clang-format"
188188

189+
print_status_msg "Setting Up Python Development Headers"
190+
install_python_dev_cross_compile_headers $arch
191+
print_status_msg "Done Setting Up Python Development Headers"
192+
189193
print_status_msg "Setting Up PlatformIO"
190194

191195
# setup platformio to compile arduino code

environment_setup/util.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,31 @@ install_java () {
7676
mv /opt/tbotspython/jdk-21* /opt/tbotspython/bin/jdk
7777
}
7878

79+
install_python_dev_cross_compile_headers() {
80+
if is_x86 $1; then
81+
mkdir -p /opt/tbotspython/cross_compile_headers
82+
wget -N https://www.python.org/ftp/python/3.12.0/Python-3.12.0.tar.xz -O /tmp/tbots_download_cache/python-3.12.0.tar.xz
83+
tar -xf /tmp/tbots_download_cache/python-3.12.0.tar.xz -C /tmp/tbots_download_cache/
84+
cd /tmp/tbots_download_cache/Python-3.12.0
85+
86+
# The configuration is taken from the examples provided in https://docs.python.org/3.12/using/configure.html
87+
echo ac_cv_buggy_getaddrinfo=no > config.site-aarch64
88+
echo ac_cv_file__dev_ptmx=yes >> config.site-aarch64
89+
echo ac_cv_file__dev_ptc=no >> config.site-aarch64
90+
CONFIG_SITE=config.site-aarch64 ./configure \
91+
--build=x86_64-pc-linux-gnu \
92+
--host=aarch64-unknown-linux-gnu \
93+
-with-build-python=/usr/bin/python3.12 \
94+
--enable-optimizations \
95+
--prefix=/opt/tbotspython/cross_compile_headers > /dev/null
96+
make inclinstall -j$(nproc) > /dev/null
97+
98+
cd -
99+
rm -rf /tmp/tbots_download_cache/Python-3.12.0
100+
rm -rf /tmp/tbots_download_cache/python-3.12.0.tar.xz
101+
fi
102+
}
103+
79104
is_x86() {
80105
if [[ $1 == "x86_64" ]]; then
81106
return 0

scripts/compile_pip_requirements.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ bazel run //extlibs:nanopb_requirements.update
1919
bazel run //software/thunderscope:requirements.update
2020
bazel run //software/embedded/ansible:requirements.update
2121
bazel run //software/simulated_tests:requirements.update
22+
bazel run //software/embedded/robot_diagnostics_cli:requirements.update

src/BUILD

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,5 @@
11
load("@rules_python//python:defs.bzl", "py_runtime")
22
load("@rules_python//python:defs.bzl", "py_runtime_pair")
3-
4-
py_runtime(
5-
name = "python3_runtime",
6-
interpreter_path = "/opt/tbotspython/bin/python3",
7-
python_version = "PY3",
8-
visibility = ["//visibility:public"],
9-
)
10-
11-
py_runtime_pair(
12-
name = "py_runtime_pair",
13-
py2_runtime = None,
14-
py3_runtime = ":python3_runtime",
15-
)
16-
17-
toolchain(
18-
name = "py_toolchain",
19-
toolchain = ":py_runtime_pair",
20-
toolchain_type = "@bazel_tools//tools/python:toolchain_type",
21-
)
22-
233
load("@hedron_compile_commands//:refresh_compile_commands.bzl", "refresh_compile_commands")
244

255
# Generates compile_commands.json

src/MODULE.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
bazel_dep(name = "bazel_skylib", version = "1.5.0")
2+
bazel_dep(name = "rules_pkg", version = "1.0.1")

src/WORKSPACE

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,12 @@ load("@rules_python//python:repositories.bzl", "py_repositories")
2727

2828
py_repositories()
2929

30-
register_toolchains("//:py_toolchain")
30+
register_toolchains("//py_toolchain:py_toolchain")
31+
32+
register_toolchains(
33+
"//py_toolchain:k8_jetson_nano_cross_compile_py_cc_toolchain",
34+
"//py_toolchain:py_cc_toolchain_for_host_x86_64",
35+
)
3136

3237
load("@rules_python//python:pip.bzl", "pip_parse")
3338

@@ -55,10 +60,17 @@ pip_parse(
5560
requirements_lock = "//software/simulated_tests:requirements_lock.txt",
5661
)
5762

63+
pip_parse(
64+
name = "robot_diagnostics_cli_deps",
65+
python_interpreter = "/opt/tbotspython/bin/python",
66+
requirements_lock = "//software/embedded/robot_diagnostics_cli:requirements_lock.txt",
67+
)
68+
5869
load("@nanopb_deps//:requirements.bzl", nanopb_install_deps = "install_deps")
5970
load("@thunderscope_deps//:requirements.bzl", thunderscope_install_deps = "install_deps")
6071
load("@ansible_deps//:requirements.bzl", ansible_install_deps = "install_deps")
6172
load("@simulated_tests_deps//:requirements.bzl", simulated_tests_install_deps = "install_deps")
73+
load("@robot_diagnostics_cli_deps//:requirements.bzl", robot_diagnostics_cli_install_deps = "install_deps")
6274

6375
nanopb_install_deps()
6476

@@ -68,6 +80,8 @@ ansible_install_deps()
6880

6981
simulated_tests_install_deps()
7082

83+
robot_diagnostics_cli_install_deps()
84+
7185
all_contents = """filegroup(name = "all", srcs = glob(["**/**"]), visibility = ["//visibility:public"])"""
7286

7387
http_archive(
@@ -275,6 +289,20 @@ go_rules_dependencies()
275289

276290
go_register_toolchains()
277291

292+
http_archive(
293+
name = "rules_pkg",
294+
sha256 = "d20c951960ed77cb7b341c2a59488534e494d5ad1d30c4818c736d57772a9fef",
295+
strip_prefix = "rules_pkg-1.0.1/pkg",
296+
urls = [
297+
"https://mirror.bazel.build/github.com/bazelbuild/rules_pkg/releases/download/1.0.1/rules_pkg-1.0.1.tar.gz",
298+
"https://github.com/bazelbuild/rules_pkg/releases/download/1.0.1/rules_pkg-1.0.1.tar.gz",
299+
],
300+
)
301+
302+
load("@rules_pkg//:deps.bzl", "rules_pkg_dependencies")
303+
304+
rules_pkg_dependencies()
305+
278306
# Needed for bazel buildifier
279307
http_archive(
280308
name = "bazel_gazelle",
@@ -329,31 +357,24 @@ bind(
329357

330358
http_archive(
331359
name = "pybind11_bazel",
332-
sha256 = "9c2919136d7c3b4a4c4a4c0ac5eb97c101c5f59c417e4f1abe70c370b1590b73",
333-
strip_prefix = "pybind11_bazel-2e5f4a6beece3b92d2f87744f305eb52b6852aa9",
334-
urls = ["https://github.com/pybind/pybind11_bazel/archive/2e5f4a6beece3b92d2f87744f305eb52b6852aa9.zip"],
360+
sha256 = "9df284330336958c837fb70dc34c0a6254dac52a5c983b3373a8c2bbb79ac35e",
361+
strip_prefix = "pybind11_bazel-2.13.6",
362+
urls = ["https://github.com/pybind/pybind11_bazel/releases/download/v2.13.6/pybind11_bazel-2.13.6.zip"],
335363
)
336364

337365
# We still require the pybind library.
338366
http_archive(
339367
name = "pybind11",
340-
build_file = "@pybind11_bazel//:pybind11.BUILD",
368+
build_file = "@pybind11_bazel//:pybind11-BUILD.bazel",
341369
sha256 = "411f77380c43798506b39ec594fc7f2b532a13c4db674fcf2b1ca344efaefb68",
342370
strip_prefix = "pybind11-2.12.0",
343371
urls = ["https://github.com/pybind/pybind11/archive/refs/tags/v2.12.0.zip"],
344372
)
345373

346-
load("@pybind11_bazel//:python_configure.bzl", "python_configure")
347-
348-
python_configure(
349-
name = "local_config_python",
350-
python_version = "3",
351-
)
352-
353374
# These headers are used by pybind11
354375
bind(
355376
name = "python_headers",
356-
actual = "@local_config_python//:python_headers",
377+
actual = "@rules_python//python/cc:current_py_cc_headers",
357378
)
358379

359380
maybe(
@@ -398,3 +419,15 @@ register_toolchains(
398419
"//cc_toolchain:cc_toolchain_for_k8",
399420
"//cc_toolchain:cc_toolchain_for_aarch64",
400421
)
422+
423+
new_local_repository(
424+
name = "py_cc_toolchain_for_host_x86_64",
425+
build_file = "@//extlibs:py_cc_toolchain.BUILD",
426+
path = "/usr/include/python3.12/",
427+
)
428+
429+
new_local_repository(
430+
name = "py_cc_toolchain_for_k8_jetson_nano_cross_compile",
431+
build_file = "@//extlibs:py_cc_toolchain.BUILD",
432+
path = "/opt/tbotspython/cross_compile_headers/include/python3.12/",
433+
)

src/defs.bzl

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
load("@rules_pkg//:providers.bzl", "PackageFilegroupInfo", "PackageFilesInfo", "PackageSymlinkInfo")
2+
3+
# No idea how this works, refer to:
4+
# https://gist.github.com/pauldraper/7bc811ffbef6d3f3d4a4bb01afa9808f
5+
6+
# For maintaining Bazel runfile tree structure during packaging
7+
def _runfile_path(workspace_name, file):
8+
path = file.short_path
9+
return path[len("../"):] if path.startswith("../") else "%s/%s" % (workspace_name, path)
10+
11+
def _runfiles_pkg_files(workspace_name, runfiles):
12+
files = {}
13+
for file in runfiles.files.to_list():
14+
files[_runfile_path(workspace_name, file)] = file
15+
for file in runfiles.symlinks.to_list():
16+
files[file.path] = "%s/%s" % (workspace_name, files.target_file)
17+
for file in runfiles.root_symlinks.to_list():
18+
files[file.path] = files.target_file
19+
20+
return PackageFilesInfo(
21+
dest_src_map = files,
22+
attributes = {"mode": "0755"},
23+
)
24+
25+
def _pkg_runfiles_impl(ctx):
26+
runfiles = ctx.attr.runfiles[DefaultInfo]
27+
label = ctx.label
28+
workspace_name = ctx.workspace_name
29+
30+
runfiles_files = _runfiles_pkg_files(workspace_name, runfiles.default_runfiles)
31+
32+
pkg_filegroup_info = PackageFilegroupInfo(
33+
pkg_dirs = [],
34+
pkg_files = [(runfiles_files, label)],
35+
pkg_symlinks = [],
36+
)
37+
38+
default_info = DefaultInfo(files = depset(runfiles_files.dest_src_map.values()))
39+
40+
return [default_info, pkg_filegroup_info]
41+
42+
pkg_runfiles = rule(
43+
implementation = _pkg_runfiles_impl,
44+
attrs = {
45+
"runfiles": attr.label(
46+
doc = "Runfiles.",
47+
mandatory = True,
48+
),
49+
},
50+
provides = [PackageFilegroupInfo],
51+
)
52+
53+
def _pkg_executable_impl(ctx):
54+
bin = ctx.attr.bin[DefaultInfo]
55+
bin_executable = ctx.executable.bin
56+
path = ctx.attr.path
57+
label = ctx.label
58+
workspace_name = ctx.workspace_name
59+
60+
runfiles_files = _runfiles_pkg_files(workspace_name, bin.default_runfiles)
61+
runfiles_files = PackageFilesInfo(
62+
dest_src_map = {"%s.runfiles/%s" % (path, p): file for p, file in runfiles_files.dest_src_map.items()},
63+
attributes = runfiles_files.attributes,
64+
)
65+
66+
executable_symlink = PackageSymlinkInfo(
67+
attributes = {"mode": "0755"},
68+
destination = path,
69+
source = "%s.runfiles/%s" % (path, _runfile_path(workspace_name, bin_executable)),
70+
)
71+
72+
pkg_filegroup_info = PackageFilegroupInfo(
73+
pkg_dirs = [],
74+
pkg_files = [(runfiles_files, label)],
75+
pkg_symlinks = [(executable_symlink, label)],
76+
)
77+
78+
default_info = DefaultInfo(files = depset(runfiles_files.dest_src_map.values()))
79+
80+
return [default_info, pkg_filegroup_info]
81+
82+
pkg_executable = rule(
83+
implementation = _pkg_executable_impl,
84+
attrs = {
85+
"bin": attr.label(
86+
doc = "Executable.",
87+
executable = True,
88+
cfg = "target",
89+
mandatory = True,
90+
),
91+
"path": attr.string(
92+
doc = "Packaged path of executable. (Runfiles tree will be at <path>.runfiles.)",
93+
mandatory = True,
94+
),
95+
},
96+
provides = [PackageFilegroupInfo],
97+
)

src/extlibs/py_cc_toolchain.BUILD

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
filegroup(
4+
name = "header_files",
5+
srcs = glob(["**/*.h"]),
6+
)
7+
8+
cc_library(
9+
name = "headers",
10+
hdrs = [":header_files"],
11+
includes = ["."],
12+
)

src/py_toolchain/BUILD

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
load("@rules_python//python/cc:py_cc_toolchain.bzl", "py_cc_toolchain")
2+
load("@rules_python//python:defs.bzl", "py_runtime")
3+
load("@rules_python//python:defs.bzl", "py_runtime_pair")
4+
5+
py_runtime(
6+
name = "python3_runtime",
7+
interpreter_path = "/opt/tbotspython/bin/python3",
8+
python_version = "PY3",
9+
visibility = ["//visibility:public"],
10+
)
11+
12+
py_runtime_pair(
13+
name = "py_runtime_pair",
14+
py2_runtime = None,
15+
py3_runtime = ":python3_runtime",
16+
)
17+
18+
toolchain(
19+
name = "py_toolchain",
20+
toolchain = ":py_runtime_pair",
21+
toolchain_type = "@bazel_tools//tools/python:toolchain_type",
22+
)
23+
24+
toolchain(
25+
name = "py_cc_toolchain_for_host_x86_64",
26+
exec_compatible_with = [
27+
"@platforms//cpu:x86_64",
28+
"@platforms//os:linux",
29+
],
30+
target_compatible_with = [
31+
"@platforms//cpu:x86_64",
32+
"@platforms//os:linux",
33+
],
34+
toolchain = ":py_cc_toolchain_for_host_x86_64_data",
35+
toolchain_type = "@rules_python//python/cc:toolchain_type",
36+
)
37+
38+
py_cc_toolchain(
39+
name = "py_cc_toolchain_for_host_x86_64_data",
40+
headers = "@py_cc_toolchain_for_host_x86_64//:headers",
41+
libs = ":empty",
42+
python_version = "3.12",
43+
)
44+
45+
py_cc_toolchain(
46+
name = "k8_jetson_nano_cross_compile_py_cc_toolchain_data",
47+
headers = "@py_cc_toolchain_for_k8_jetson_nano_cross_compile//:headers",
48+
libs = ":empty",
49+
python_version = "3.12",
50+
)
51+
52+
# We don't need this, but it's required by the py_cc_toolchain
53+
cc_library(
54+
name = "empty",
55+
visibility = ["//visibility:private"],
56+
)
57+
58+
toolchain(
59+
name = "k8_jetson_nano_cross_compile_py_cc_toolchain",
60+
exec_compatible_with = [
61+
"@platforms//cpu:x86_64",
62+
"@platforms//os:linux",
63+
],
64+
target_compatible_with = [
65+
"@platforms//cpu:aarch64",
66+
"@platforms//os:linux",
67+
],
68+
toolchain = ":k8_jetson_nano_cross_compile_py_cc_toolchain_data",
69+
toolchain_type = "@rules_python//python/cc:toolchain_type",
70+
)

src/software/embedded/ansible/BUILD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package(default_visibility = ["//visibility:public"])
33
load("@rules_python//python:defs.bzl", "py_binary")
44
load("@rules_python//python:pip.bzl", "compile_pip_requirements")
55
load("@ansible_deps//:requirements.bzl", "requirement")
6-
load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")
76

87
compile_pip_requirements(
98
name = "requirements",
@@ -26,6 +25,7 @@ py_binary(
2625
"//software/embedded/linux_configs/pi:pi_files",
2726
"//software/embedded/linux_configs/systemd:systemd_files",
2827
"//software/embedded/redis",
28+
"//software/embedded/robot_diagnostics_cli:robot_diagnostics_cli_tar",
2929
"//software/embedded/services:robot_auto_test",
3030
"//software/power:powerloop_tar",
3131
],

0 commit comments

Comments
 (0)