Replace parallellize_cargo_check.py with Rust code (#3217)
* ci_splitter * clpo * FIX * aa
This commit is contained in:
parent
c9b0dc216f
commit
ecaa013263
2
.github/workflows/build_and_test.yml
vendored
2
.github/workflows/build_and_test.yml
vendored
@ -168,7 +168,7 @@ jobs:
|
|||||||
- name: Check each feature
|
- name: Check each feature
|
||||||
# Skipping `python` as it has to be built with the `maturin` tool
|
# Skipping `python` as it has to be built with the `maturin` tool
|
||||||
# `sancov_pcguard_edges` is tested seperatelyc
|
# `sancov_pcguard_edges` is tested seperatelyc
|
||||||
run: python3 ./scripts/parallellize_cargo_check.py ${{ matrix.instance_idx }}
|
run: LLVM_VERSION=18 CI_INSTANCES=18 cargo run --manifest-path ./utils/ci_splitter/Cargo.toml -- ${{ matrix.instance_idx }}
|
||||||
|
|
||||||
ubuntu-concolic:
|
ubuntu-concolic:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
@ -27,6 +27,7 @@ members = [
|
|||||||
"utils/libafl_benches",
|
"utils/libafl_benches",
|
||||||
"utils/libafl_jumper",
|
"utils/libafl_jumper",
|
||||||
"utils/ci_runner",
|
"utils/ci_runner",
|
||||||
|
"utils/ci_splitter",
|
||||||
]
|
]
|
||||||
|
|
||||||
default-members = [
|
default-members = [
|
||||||
|
@ -69,10 +69,7 @@ for project in "${PROJECTS[@]}"; do
|
|||||||
echo "Warning: Directory $project does not exist. Skipping."
|
echo "Warning: Directory $project does not exist. Skipping."
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
# Last run it on all
|
||||||
eval "$CLIPPY_CMD --workspace -- $RUSTC_FLAGS"
|
eval "$CLIPPY_CMD --workspace -- $RUSTC_FLAGS"
|
||||||
|
|
||||||
echo "Clippy run completed for all specified projects."
|
echo "Clippy run completed for all specified projects."
|
||||||
|
|
||||||
# Last run it on all
|
|
||||||
eval "$CLIPPY_CMD --workspace -- $RUSTC_FLAGS"
|
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
#!/usr/bin/python3
|
|
||||||
import subprocess
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import math
|
|
||||||
|
|
||||||
LLVM_VERSION = "18"
|
|
||||||
|
|
||||||
# Current CI Runner
|
|
||||||
ci_instances = 18
|
|
||||||
|
|
||||||
if len(sys.argv) != 2:
|
|
||||||
exit(1)
|
|
||||||
|
|
||||||
instance_idx = int(sys.argv[1])
|
|
||||||
|
|
||||||
# Set llvm config if it's not already set
|
|
||||||
if "LLVM_CONFIG" not in os.environ:
|
|
||||||
os.environ["LLVM_CONFIG"] = f"llvm-config-{LLVM_VERSION}"
|
|
||||||
|
|
||||||
command = (
|
|
||||||
"DOCS_RS=1 cargo hack check --workspace --each-feature --clean-per-run "
|
|
||||||
"--exclude-features=prelude,python,sancov_pcguard_edges,arm,aarch64,i386,be,systemmode,whole_archive "
|
|
||||||
"--no-dev-deps --exclude libafl_libfuzzer --exclude libafl_qemu --exclude libafl_qemu_sys --print-command-list;"
|
|
||||||
"DOCS_RS=1 cargo hack check -p libafl_qemu -p libafl_qemu_sys --each-feature --clean-per-run "
|
|
||||||
"--exclude-features=prelude,python,sancov_pcguard_edges,arm,aarch64,i386,be,systemmode,whole_archive,slirp,intel_pt,intel_pt_export_raw "
|
|
||||||
"--no-dev-deps --features usermode --print-command-list"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Run the command and capture the output
|
|
||||||
output = subprocess.check_output(command, shell=True, text=True)
|
|
||||||
output = output.strip().split("\n")[0:]
|
|
||||||
all_task_cnt = len(output) // 2 # by 2 cuz one task has two lines
|
|
||||||
task_per_core = math.ceil(all_task_cnt // ci_instances)
|
|
||||||
print(task_per_core, "tasks assigned to this instance")
|
|
||||||
|
|
||||||
for task in output[
|
|
||||||
instance_idx * 2 * task_per_core : (instance_idx + 1) * 2 * task_per_core
|
|
||||||
]:
|
|
||||||
print("Running ", task)
|
|
||||||
print(os.environ)
|
|
||||||
|
|
||||||
if (
|
|
||||||
"utils/libafl_jumper/Cargo.toml" in task
|
|
||||||
and "--no-default-features" in task
|
|
||||||
and "--features" not in task
|
|
||||||
):
|
|
||||||
# ignore libafl_jumper no std
|
|
||||||
continue
|
|
||||||
|
|
||||||
if "libafl_frida" in task:
|
|
||||||
# DOCS_RS is needed for libafl_frida to build without auto-download feature
|
|
||||||
cargo_check = subprocess.check_output(
|
|
||||||
task, shell=True, text=True, env=dict(os.environ, DOCS_RS="1")
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
cargo_check = subprocess.check_output(task, shell=True, text=True)
|
|
22
utils/ci_splitter/Cargo.toml
Normal file
22
utils/ci_splitter/Cargo.toml
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
[package]
|
||||||
|
name = "ci_splitter"
|
||||||
|
edition = "2024"
|
||||||
|
authors = ["Dongjia Zhang <tokazerkje@outlook.com>"]
|
||||||
|
version.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
description = "libafl CI tools for testing fuzzers"
|
||||||
|
repository = "https://github.com/AFLplusplus/LibAFL/"
|
||||||
|
keywords = ["fuzzing", "testing", "security"]
|
||||||
|
categories = [
|
||||||
|
"development-tools::testing",
|
||||||
|
"emulators",
|
||||||
|
"embedded",
|
||||||
|
"os",
|
||||||
|
"no-std",
|
||||||
|
]
|
||||||
|
readme = "../README.md"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
81
utils/ci_splitter/src/main.rs
Normal file
81
utils/ci_splitter/src/main.rs
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
use core::error::Error;
|
||||||
|
use std::{
|
||||||
|
env,
|
||||||
|
process::{Command, exit},
|
||||||
|
};
|
||||||
|
|
||||||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
let args: Vec<String> = env::args().collect();
|
||||||
|
if args.len() != 2 {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
let instance_idx: usize = args[1]
|
||||||
|
.parse()
|
||||||
|
.map_err(|e| format!("Failed to parse instance index '{}': {}", args[1], e))?;
|
||||||
|
|
||||||
|
let ci_instances: usize = if let Ok(val) = env::var("CI_INSTANCES") {
|
||||||
|
val.parse()
|
||||||
|
.map_err(|e| format!("CI_INSTANCES must be a positive integer, got '{val}': {e}"))?
|
||||||
|
} else {
|
||||||
|
eprintln!("Error: CI_INSTANCES environment variable not set");
|
||||||
|
exit(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
let llvm_var: usize = if let Ok(val) = env::var("LLVM_VERSION") {
|
||||||
|
val.parse()
|
||||||
|
.map_err(|e| format!("LLVM_VERSION must be a positive integer, got '{val}': {e}"))?
|
||||||
|
} else {
|
||||||
|
eprintln!("Error: LLVM_VERSION environment variable not set");
|
||||||
|
exit(1);
|
||||||
|
};
|
||||||
|
|
||||||
|
if env::var("LLVM_CONFIG").is_err() {
|
||||||
|
unsafe {
|
||||||
|
env::set_var("LLVM_CONFIG", format!("llvm-config-{llvm_var}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let the_command = concat!(
|
||||||
|
"DOCS_RS=1 cargo hack check --workspace --each-feature --clean-per-run \
|
||||||
|
--exclude-features=prelude,python,sancov_pcguard_edges,arm,aarch64,i386,be,systemmode,whole_archive \
|
||||||
|
--no-dev-deps --exclude libafl_libfuzzer --exclude libafl_qemu --exclude libafl_qemu_sys --print-command-list; ",
|
||||||
|
"DOCS_RS=1 cargo hack check -p libafl_qemu -p libafl_qemu_sys --each-feature --clean-per-run \
|
||||||
|
--exclude-features=prelude,python,sancov_pcguard_edges,arm,aarch64,i386,be,systemmode,whole_archive,slirp,intel_pt,intel_pt_export_raw \
|
||||||
|
--no-dev-deps --features usermode --print-command-list"
|
||||||
|
);
|
||||||
|
|
||||||
|
let output = Command::new("sh").arg("-c").arg(the_command).output()?;
|
||||||
|
let stdout = String::from_utf8_lossy(&output.stdout);
|
||||||
|
let lines: Vec<&str> = stdout.trim().lines().collect();
|
||||||
|
|
||||||
|
let all_task_cnt = lines.len() / 2; // one task == two lines
|
||||||
|
let task_per_core = all_task_cnt / ci_instances;
|
||||||
|
println!("{task_per_core}/{all_task_cnt} tasks assigned to this instance");
|
||||||
|
|
||||||
|
let start = instance_idx * 2 * task_per_core;
|
||||||
|
let end = ((instance_idx + 1) * 2 * task_per_core).min(lines.len());
|
||||||
|
for &task in &lines[start..end] {
|
||||||
|
println!("Running {task}");
|
||||||
|
|
||||||
|
// skip the libafl_jumper no-std case
|
||||||
|
if task.contains("utils/libafl_jumper/Cargo.toml")
|
||||||
|
&& task.contains("--no-default-features")
|
||||||
|
&& !task.contains("--features")
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// run each task, with DOCS_RS override for libafl_frida
|
||||||
|
let mut cmd = Command::new("bash");
|
||||||
|
cmd.arg("-c").arg(task);
|
||||||
|
if task.contains("libafl_frida") {
|
||||||
|
cmd.env("DOCS_RS", "1");
|
||||||
|
}
|
||||||
|
let status = cmd.status()?;
|
||||||
|
if !status.success() {
|
||||||
|
return Err(format!("Command failed (exit code {:?}): {}", status.code(), task).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user