-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updates the README to use cargo target config instead of RUSTFLAGS to avoid setting the linker for ebpf in cargo-in-cargo. Rewrite test.sh in python.
- Loading branch information
Showing
5 changed files
with
231 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import argparse | ||
import datetime | ||
import io | ||
import os | ||
import platform | ||
import signal | ||
import subprocess | ||
import sys | ||
import tempfile | ||
import time | ||
from typing import TypedDict | ||
|
||
|
||
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", | ||
"clippy", | ||
"--exclude", | ||
f"{CRATE_NAME}-ebpf", | ||
"--all-targets", | ||
"--workspace", | ||
"--", | ||
"--deny", | ||
"warnings", | ||
], | ||
[ | ||
"cargo", | ||
"clippy", | ||
"--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: | ||
sys.stdout.write(f"{cmd=} {kwargs=}\n") | ||
sys.stdout.flush() | ||
subprocess.check_call(cmd, **kwargs) | ||
|
||
if platform.system() == "Linux": | ||
with subprocess.Popen( | ||
["cargo", "xtask", "run"], | ||
cwd=project_dir, | ||
stdin=subprocess.PIPE, | ||
stdout=subprocess.PIPE, | ||
stderr=sys.stderr, | ||
) as process: | ||
assert process.stdin is not None | ||
assert process.stdout is not None | ||
start = time.monotonic_ns() | ||
for line in io.TextIOWrapper(process.stdout, encoding="utf-8"): | ||
elapsed = datetime.timedelta( | ||
milliseconds=(time.monotonic_ns() - start) / 1_000_000, | ||
) | ||
sys.stdout.write(f"{elapsed=}{line=}\n") | ||
sys.stdout.flush() | ||
if "Waiting for Ctrl-C" in line: | ||
# Send SIGINT signal to simulate Ctrl-C | ||
process.send_signal(signal.SIGINT) | ||
|
||
try: | ||
# Wait up to 5 seconds for graceful termination | ||
process.wait(timeout=5) | ||
except subprocess.TimeoutExpired: | ||
# If the process doesn't exit, forcefully kill it | ||
sys.stdout.write("Process did not exit after SIGINT, sending SIGKILL\n") | ||
sys.stdout.flush() | ||
process.kill() # Force kill | ||
process.wait() # Wait until fully terminated | ||
retcode = process.returncode | ||
if retcode != 0: | ||
raise subprocess.CalledProcessError(retcode, process.args) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |