You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
6.1 KiB
Python
175 lines
6.1 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import argparse
|
|
import os
|
|
import platform
|
|
import signal
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
from typing import TypedDict
|
|
|
|
if platform.system() == "Linux":
|
|
import asyncio
|
|
|
|
|
|
class SubprocessArgs(TypedDict, total=False):
|
|
cwd: str
|
|
env: dict[str, str]
|
|
|
|
|
|
def main() -> None:
|
|
parser = argparse.ArgumentParser(
|
|
description="Generate and build a Rust project using cargo."
|
|
)
|
|
parser.add_argument("template_dir", help="Template directory")
|
|
parser.add_argument("program_type", help="Program type")
|
|
args = parser.parse_args()
|
|
|
|
match args.program_type:
|
|
case "cgroup_sockopt":
|
|
additional_args = ["-d", "sockopt_target=getsockopt"]
|
|
case "classifier", "cgroup_skb":
|
|
additional_args = ["-d", "direction=Ingress"]
|
|
case "fentry", "fexit":
|
|
additional_args = ["-d", "fn_name=try_to_wake_up"]
|
|
case "kprobe", "kretprobe":
|
|
additional_args = ["-d", "kprobe=do_unlinkat"]
|
|
case "lsm":
|
|
additional_args = ["-d", "lsm_hook=file_open"]
|
|
case "raw_tracepoint":
|
|
additional_args = ["-d", "tracepoint_name=sys_enter"]
|
|
case "sk_msg":
|
|
additional_args = ["-d", "sock_map=SOCK_MAP"]
|
|
case "tp_btf":
|
|
additional_args = ["-d", "tracepoint_name=net_dev_queue"]
|
|
case "tracepoint":
|
|
additional_args = [
|
|
"-d",
|
|
"tracepoint_category=net",
|
|
"-d",
|
|
"tracepoint_name=net_dev_queue",
|
|
]
|
|
case "uprobe", "uretprobe":
|
|
additional_args = [
|
|
"-d",
|
|
"uprobe_target=/proc/self/exe",
|
|
"-d",
|
|
"uprobe_fn_name=main",
|
|
]
|
|
case _:
|
|
additional_args = []
|
|
|
|
CRATE_NAME = "aya-test-crate"
|
|
with tempfile.TemporaryDirectory() as tmp_dir:
|
|
cmds: list[tuple[list[str], SubprocessArgs]] = [
|
|
(
|
|
[
|
|
"cargo",
|
|
"generate",
|
|
"--path",
|
|
args.template_dir,
|
|
"-n",
|
|
CRATE_NAME,
|
|
"-d",
|
|
f"program_type={args.program_type}",
|
|
]
|
|
+ additional_args,
|
|
{"cwd": tmp_dir},
|
|
),
|
|
]
|
|
project_dir = os.path.join(tmp_dir, CRATE_NAME)
|
|
match platform.system():
|
|
case "Linux":
|
|
cmds.extend(
|
|
(cmd, {"cwd": project_dir})
|
|
for cmd in (
|
|
["cargo", "+nightly", "fmt", "--all", "--", "--check"],
|
|
["cargo", "build", "--package", CRATE_NAME],
|
|
["cargo", "build", "--package", CRATE_NAME, "--release"],
|
|
# We cannot run clippy over the whole workspace at once due to feature unification.
|
|
# Since both ${CRATE_NAME} and ${CRATE_NAME}-ebpf depend on ${CRATE_NAME}-common and
|
|
# ${CRATE_NAME} activates ${CRATE_NAME}-common's aya dependency, we end up trying to
|
|
# compile the panic handler twice: once from the bpf program, and again from std via
|
|
# aya.
|
|
[
|
|
"cargo",
|
|
"--exclude",
|
|
f"{CRATE_NAME}-ebpf",
|
|
"--all-targets",
|
|
"--workspace",
|
|
"--",
|
|
"--deny",
|
|
"warnings",
|
|
],
|
|
[
|
|
"cargo",
|
|
"--package",
|
|
f"{CRATE_NAME}-ebpf",
|
|
"--all-targets",
|
|
"--",
|
|
"--deny",
|
|
"warnings",
|
|
],
|
|
)
|
|
)
|
|
case "Darwin":
|
|
arch = platform.machine()
|
|
if arch == "arm64":
|
|
arch = "aarch64"
|
|
target = f"{arch}-unknown-linux-musl"
|
|
cmds.append(
|
|
(
|
|
[
|
|
"cargo",
|
|
"build",
|
|
"--package",
|
|
CRATE_NAME,
|
|
"--release",
|
|
"--target",
|
|
target,
|
|
"--config",
|
|
f'target.{target}.linker = "rust-lld"',
|
|
],
|
|
{
|
|
"cwd": project_dir,
|
|
"env": os.environ
|
|
| {
|
|
"AYA_BUILD_EBPF": "true",
|
|
"CC": f"{arch}-linux-musl-gcc",
|
|
},
|
|
},
|
|
)
|
|
)
|
|
|
|
for cmd, kwargs in cmds:
|
|
print(f"Running command: {' '.join(cmd)} with kwargs: {kwargs}")
|
|
subprocess.check_call(cmd, **kwargs)
|
|
|
|
if platform.system() == "Linux":
|
|
|
|
async def run():
|
|
async with asyncio.create_subprocess_exec(
|
|
"cargo",
|
|
"xtask",
|
|
"run",
|
|
cwd=project_dir,
|
|
stdin=subprocess.DEVNULL,
|
|
stdout=asyncio.subprocess.PIPE,
|
|
text=True,
|
|
) as process:
|
|
async with asyncio.timeout(30):
|
|
for line in process.stdout:
|
|
sys.stdout.write(line)
|
|
if "Waiting for Ctrl-C" in line:
|
|
process.send_signal(signal.SIGINT)
|
|
retcode = await process.wait()
|
|
if retcode != 0:
|
|
raise subprocess.CalledProcessError(retcode, process.args)
|
|
|
|
asyncio.run(run())
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|