import { $, fs, which } from "zx";
import { join } from "path";
const LINUX_X64 = "x86_64-unknown-linux-gnu",
LINUX_ARM = "aarch64-unknown-linux-gnu",
WIN = "x86_64-pc-windows-msvc",
MAC = "x86_64-apple-darwin",
TARGETS = [LINUX_X64, LINUX_ARM, WIN, MAC],
ARGS = ["test", "--all-features", "--release", "--", "--nocapture"];
const META = await (async () => {
const meta = JSON.parse(
(await $`cargo metadata --format-version 1 --no-deps`).stdout,
);
const pkg = meta.packages[0].name;
const targetDir = meta.target_directory;
const host = (await $`rustc -vV`).stdout.match(/host: (.+)/)[1];
return { pkg, targetDir, host };
})();
$.verbose = 1;
const ensureCmd = async (cmd, install) => {
if (!(await which(cmd, { nothrow: true }))) await install();
};
const ensureBinstall = () =>
ensureCmd("cargo-binstall", () => $`cargo install cargo-binstall`);
const ensureZigbuild = async () => {
await ensureBinstall();
await ensureCmd("cargo-zigbuild", () => $`cargo binstall cargo-zigbuild -y`);
};
const ensureXwin = async () => {
await ensureBinstall();
await ensureCmd("cargo-xwin", () => $`cargo binstall cargo-xwin -y`);
};
const ensureStable = async (targets) => {
const installed = (await $`rustup target list --toolchain stable --installed`)
.stdout;
for (const t of targets) {
if (!installed.includes(t)) {
await $`rustup target add ${t} --toolchain stable`;
}
}
};
const findTestBins = async (pkg, targetDir, target, ext = "") => {
const dir = join(targetDir, target, "release", "deps");
const files = await fs.readdir(dir);
return files
.filter((f) => f.startsWith(pkg) && !f.endsWith(".d") && f.endsWith(ext))
.map((f) => join(dir, f));
};
const dockerPlatform = (target) =>
target.startsWith("aarch64") ? "linux/arm64" : "linux/amd64";
const dockerTest = async (pkg, targetDir, target) => {
const platform = dockerPlatform(target);
const bins = await findTestBins(pkg, targetDir, target);
for (const bin of bins) {
await $`docker run --rm --platform ${platform} -v $(pwd):/app -v ${targetDir}:${targetDir} -w /app debian:bookworm ${bin} --nocapture`;
}
};
const wineTest = async (pkg, targetDir, target) => {
const bins = await findTestBins(pkg, targetDir, target, ".exe");
for (const bin of bins) {
await $`docker run --rm --platform linux/amd64 -v ${targetDir}:${targetDir} scottyhardy/docker-wine wine64 ${bin} --nocapture`;
}
};
const isLinux = (t) => t.includes("-linux-");
const main = async () => {
const { pkg, targetDir, host } = META;
const others = TARGETS.filter((t) => t !== host);
await $`cargo ${ARGS}`;
console.log(`✓ ${host} passed (nightly)`);
if (others.length === 0) return;
await ensureZigbuild();
await ensureXwin();
await ensureStable(others);
for (const t of others) {
if (t === WIN) {
await $`rustup run stable cargo xwin build --tests --all-features --release --target ${t}`;
} else {
await $`rustup run stable cargo zigbuild --tests --all-features --release --target ${t}`;
}
console.log(`✓ ${t} built (stable)`);
if (isLinux(t)) {
await dockerTest(pkg, targetDir, t);
console.log(`✓ ${t} tested (docker)`);
} else if (t === WIN) {
await wineTest(pkg, targetDir, t);
console.log(`✓ ${t} tested (wine)`);
} else if (t === MAC && host.includes("apple-darwin")) {
const bins = await findTestBins(pkg, targetDir, t);
for (const bin of bins) {
await $`${bin} --nocapture`;
}
console.log(`✓ ${t} tested (rosetta)`);
}
}
};
main();