Kaynağa Gözat

Integrate CI (#4)

* Create ci.yml

* Fix `xtask` dir not found

* Fix `xtask` dir not found

* Update CI file

* Update error handling of xtask

* Update CI config

* Update xtask

* Tweak build process

* Add missing dependency in CI

* Update caching cargo crates

* Update LLVM caching path

* Add sccache and format check
Js2xxx 1 yıl önce
ebeveyn
işleme
854bb8e336

+ 61 - 0
.github/workflows/ci.yml

@@ -0,0 +1,61 @@
+name: CI
+
+on:
+  push:
+    branches: ["master"]
+  pull_request:
+    branches: ["master"]
+
+env:
+  CARGO_TERM_COLOR: always
+
+jobs:
+  build:
+    runs-on: ubuntu-latest
+
+    steps:
+      - uses: actions/checkout@v3
+
+      - name: Install nasm and qemu-utils
+        run: sudo apt-get install nasm qemu-utils
+
+      - name: Cache LLVM
+        id: cache-llvm
+        uses: actions/cache@v3
+        with:
+          path: llvm
+          key: llvm-14.0
+
+      - name: Install LLVM
+        uses: KyleMayes/install-llvm-action@v1
+        with:
+          version: "14.0"
+          directory: llvm
+          cached: ${{ steps.cache-llvm.output.cache-hit }}
+
+      - name: Cache cargo crates
+        id: cache-cargo
+        uses: actions/cache@v3
+        with:
+          path: |
+            ~/.cargo/.crates.toml
+            ~/.cargo/.crates2.json
+            ~/.cargo/bin/
+            ~/.cargo/registry/index/
+            ~/.cargo/registry/cache/
+            ~/.cargo/git/db/
+          key: cargo-crates
+
+      - name: Configure sccache
+        uses: visvirial/sccache-action@v1
+
+      - name: Build
+        run: cargo xtask dist --release img
+
+  fmt:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+
+      - name: Check format
+        run: cargo fmt --all --check

+ 2 - 1
README.md

@@ -50,7 +50,8 @@ support aarch64 in the future.
    ```sh
    # Select the nightly channel for rust
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-   sudo apt install build-essential qemu-system-x86 llvm
+   sudo apt install build-essential qemu-system-x86 llvm-14 nasm
+   export LLVM_PATH="/usr/lib/llvm-14"
    ```
 
 2. Add the following target:

+ 2 - 1
README.zh-cn.md

@@ -45,7 +45,8 @@
    ```sh
    # 配置 Rust 时需要选择 nightly 通道
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-   sudo apt install build-essential qemu-system-x86 llvm
+   sudo apt install build-essential qemu-system-x86 llvm-14 nasm
+   export LLVM_PATH="/usr/lib/llvm-14"
    ```
 
 2. 添加下列目标:

+ 3 - 2
src/lib/bootfs/Cargo.toml

@@ -4,9 +4,10 @@ name = "bootfs"
 version = "0.1.0"
 
 [features]
-gen = []
+gen = ["dep:anyhow"]
 
 [dependencies]
+anyhow = {version = "1.0", optional = true}
 either = {version = "1.6", default-features = false}
+plain = "0.2"
 static_assertions = "1.1"
-plain = "0.2"

+ 3 - 3
src/lib/bootfs/src/gen.rs

@@ -1,4 +1,4 @@
-use std::{boxed::Box, collections::VecDeque, error::Error, io::Write, mem, vec::Vec};
+use std::{collections::VecDeque, io::Write, mem, vec::Vec};
 
 use plain::Plain;
 
@@ -59,7 +59,7 @@ fn write_typed<T: ?Sized + Plain>(
     data: &T,
     size: usize,
     output: &mut impl Write,
-) -> Result<(), Box<dyn Error>> {
+) -> anyhow::Result<()> {
     let alsize = mem::size_of_val(data);
     let size = alsize.max(size);
 
@@ -72,7 +72,7 @@ fn write_typed<T: ?Sized + Plain>(
     Ok(())
 }
 
-pub fn generate(input: &Entry, output: &mut impl Write) -> Result<(), Box<dyn Error>> {
+pub fn generate(input: &Entry, output: &mut impl Write) -> anyhow::Result<()> {
     let mut entries = Vec::new();
     let mut contents = Vec::new();
     split(input, &mut entries, &mut contents);

+ 1 - 0
xtask/Cargo.toml

@@ -12,6 +12,7 @@ path = "src/main.rs"
 # Local crates
 bootfs = {path = "../src/lib/bootfs", features = ["gen"]}
 # External crates
+anyhow = "1.0"
 cc = "1.0"
 quote = "1.0"
 rand = "0.8"

+ 4 - 6
xtask/src/check.rs

@@ -1,21 +1,19 @@
 use std::{
-    env,
-    error::Error,
-    fs,
+    env, fs,
     path::{Path, PathBuf},
     process::Command,
 };
 
 use crate::{H2O_BOOT, H2O_KERNEL, H2O_TINIT, OC_BIN, OC_DRV, OC_LIB};
 
-pub(crate) fn check() -> Result<(), Box<dyn Error>> {
+pub(crate) fn check() -> anyhow::Result<()> {
     let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
     let src_root = Path::new(env!("CARGO_MANIFEST_DIR"))
         .ancestors()
         .nth(1)
         .unwrap();
 
-    let check = |dir: PathBuf| -> Result<(), Box<dyn Error>> {
+    let check = |dir: PathBuf| -> anyhow::Result<()> {
         Command::new(&cargo)
             .current_dir(dir)
             .args(["clippy", "--message-format=json-diagnostic-short"])
@@ -24,7 +22,7 @@ pub(crate) fn check() -> Result<(), Box<dyn Error>> {
             .map_err(Into::into)
     };
 
-    let check_all = |dir: PathBuf| -> Result<(), Box<dyn Error>> {
+    let check_all = |dir: PathBuf| -> anyhow::Result<()> {
         for ent in fs::read_dir(dir)?.flatten() {
             let ty = ent.file_type()?;
             let name = ent.file_name();

+ 127 - 107
xtask/src/dist.rs

@@ -1,19 +1,32 @@
 use std::{
     collections::HashSet,
     env,
-    error::Error,
     ffi::OsString,
     fs,
     path::{Path, PathBuf},
     process::Command,
+    sync::LazyLock,
 };
 
+use anyhow::Context;
 use structopt::StructOpt;
 
 use crate::{
     BOOTFS, DEBUG_DIR, H2O_BOOT, H2O_KERNEL, H2O_SYSCALL, H2O_TINIT, OC_BIN, OC_DRV, OC_LIB,
 };
 
+static CARGO: LazyLock<OsString> =
+    LazyLock::new(|| env::var_os("CARGO").unwrap_or_else(|| "cargo".into()));
+
+static LLVM: LazyLock<OsString> =
+    LazyLock::new(|| env::var_os("LLVM_PATH").unwrap_or_else(|| "/usr/lib/llvm-14".into()));
+
+static LLVM_OBJCOPY: LazyLock<PathBuf> =
+    LazyLock::new(|| Path::new(&*LLVM).join("bin/llvm-objcopy"));
+static LLVM_OBJDUMP: LazyLock<PathBuf> =
+    LazyLock::new(|| Path::new(&*LLVM).join("bin/llvm-objdump"));
+static LLVM_IFS: LazyLock<PathBuf> = LazyLock::new(|| Path::new(&*LLVM).join("bin/llvm-ifs"));
+
 #[derive(Debug, StructOpt)]
 pub enum Type {
     Img,
@@ -36,20 +49,12 @@ impl Dist {
         }
     }
 
-    pub fn build(self) -> Result<(), Box<dyn Error>> {
-        let cargo = env::var("CARGO").unwrap_or_else(|_| "cargo".to_string());
+    pub fn build(self) -> Result<(), anyhow::Error> {
         let src_root = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap();
         let target_root = env::var("CARGO_TARGET_DIR")
             .unwrap_or_else(|_| src_root.join("target").to_string_lossy().to_string());
 
-        fs::create_dir_all(PathBuf::from(&target_root).join("bootfs/lib"))?;
-        fs::create_dir_all(PathBuf::from(&target_root).join("bootfs/drv"))?;
-        fs::create_dir_all(PathBuf::from(&target_root).join("bootfs/bin"))?;
-        fs::create_dir_all(PathBuf::from(&target_root).join("sysroot/usr/include"))?;
-        fs::create_dir_all(PathBuf::from(&target_root).join("sysroot/usr/lib"))?;
-        fs::create_dir_all(src_root.join(H2O_KERNEL).join("target"))?;
-        fs::create_dir_all(src_root.join("h2o/libs/syscall/target"))?;
-        fs::create_dir_all("debug")?;
+        create_dir_all(&target_root, src_root)?;
 
         // Generate syscall stubs
         crate::gen::gen_syscall(
@@ -58,106 +63,50 @@ impl Dist {
             src_root.join("h2o/libs/syscall/target/call.rs"),
             src_root.join("h2o/libs/syscall/target/stub.rs"),
             src_root.join("h2o/libs/syscall/target/num.rs"),
-        )?;
+        )
+        .context("failed to generate syscalls")?;
 
         // Build h2o_boot
         self.build_impl(
-            &cargo,
             "h2o_boot.efi",
             "BootX64.efi",
             src_root.join(H2O_BOOT),
             Path::new(&target_root).join("x86_64-unknown-uefi"),
             &target_root,
-        )?;
+        )
+        .context("failed to build h2o_boot")?;
 
         // Build the VDSO
-        {
-            let target_triple = src_root.join(".cargo/x86_64-pc-oceanic.json");
-            let cd = src_root.join(H2O_SYSCALL);
-            let ldscript = cd.join("syscall.ld");
-
-            println!("Building VDSO");
-
-            let mut cmd = Command::new(&cargo);
-            let cmd = cmd.current_dir(&cd).arg("rustc").args([
-                "--crate-type=cdylib",
-                &format!("--target={}", target_triple.to_string_lossy()),
-                "-Zunstable-options",
-                "-Zbuild-std=core,compiler_builtins,alloc,panic_abort",
-                "-Zbuild-std-features=compiler-builtins-mem",
-                "--release", /* VDSO can always be the release version and discard the debug
-                              * symbols. */
-                "--no-default-features",
-                "--features",
-                "call",
-                "--features",
-                "vdso",
-            ]);
-            cmd.args([
-                "--",
-                &format!("-Clink-arg=-T{}", ldscript.to_string_lossy()),
-            ])
-            .status()?
-            .exit_ok()?;
-
-            // Copy the binary to target.
-            let bin_dir = Path::new(&target_root).join("x86_64-pc-oceanic/release");
-            let path = src_root.join(H2O_KERNEL).join("target/vdso");
-            fs::copy(bin_dir.join("libsv_call.so"), &path)?;
-            Command::new("llvm-ifs")
-                .arg("--input-format=ELF")
-                .arg(format!(
-                    "--output-elf={}/sysroot/usr/lib/libh2o.so",
-                    target_root
-                ))
-                .arg(&path)
-                .status()?
-                .exit_ok()?;
-
-            let out = Command::new("llvm-objdump")
-                .arg("--syms")
-                .arg(&path)
-                .output()?
-                .stdout;
-            let s = String::from_utf8_lossy(&out);
-            let (constants_offset, _) = s
-                .split('\n')
-                .find(|s| s.ends_with("CONSTANTS"))
-                .and_then(|s| s.split_once(' '))
-                .expect("Failed to get CONSTANTS");
-
-            fs::write(
-                src_root.join(H2O_KERNEL).join("target/constant_offset.rs"),
-                format!("0x{}", constants_offset),
-            )?;
-
-            self.gen_debug("vdso", src_root.join(H2O_KERNEL).join("target"), DEBUG_DIR)?;
-        }
+        self.build_vdso(src_root, &target_root)
+            .context("failed to build VDSO")?;
 
         // Build h2o_kernel
         self.build_impl(
-            &cargo,
             "h2o",
             "KERNEL",
             src_root.join(H2O_KERNEL),
             Path::new(&target_root).join("x86_64-h2o-kernel"),
             &target_root,
-        )?;
+        )
+        .context("failed to build h2o_kernel")?;
 
         // Build h2o_tinit
         self.build_impl(
-            &cargo,
             "tinit",
             "TINIT",
             src_root.join(H2O_TINIT),
             Path::new(&target_root).join("x86_64-h2o-tinit"),
             &target_root,
-        )?;
+        )
+        .context("failed to build h2o_tinit")?;
 
-        self.build_lib(&cargo, src_root, &target_root)?;
-        self.build_bin(&cargo, src_root, &target_root)?;
+        self.build_lib(src_root, &target_root)
+            .context("failed to build libraries")?;
+        self.build_bin(src_root, &target_root)
+            .context("failed to build binaries or drivers")?;
 
-        crate::gen::gen_bootfs(Path::new(BOOTFS).join("../BOOT.fs"))?;
+        crate::gen::gen_bootfs(Path::new(BOOTFS).join("../BOOT.fs"))
+            .context("failed to generate BOOTFS")?;
 
         match &self.ty {
             Type::Img => {
@@ -173,18 +122,81 @@ impl Dist {
         Ok(())
     }
 
-    fn build_lib(
-        &self,
-        cargo: &str,
-        src_root: impl AsRef<Path>,
-        target_root: &str,
-    ) -> Result<(), Box<dyn Error>> {
+    fn build_vdso(&self, src_root: &Path, target_root: &String) -> Result<(), anyhow::Error> {
+        let target_triple = src_root.join(".cargo/x86_64-pc-oceanic.json");
+        let cd = src_root.join(H2O_SYSCALL);
+        let ldscript = cd.join("syscall.ld");
+
+        println!("Building VDSO");
+
+        let mut cmd = Command::new(&*CARGO);
+
+        let cmd = cmd.current_dir(&cd).arg("rustc").args([
+            "--crate-type=cdylib",
+            &format!("--target={}", target_triple.to_string_lossy()),
+            "-Zunstable-options",
+            "-Zbuild-std=core,compiler_builtins,alloc,panic_abort",
+            "-Zbuild-std-features=compiler-builtins-mem",
+            "--release", /* VDSO can always be the release version and discard the debug
+                          * symbols. */
+            "--no-default-features",
+            "--features",
+            "call",
+            "--features",
+            "vdso",
+        ]);
+
+        cmd.args([
+            "--",
+            &format!("-Clink-arg=-T{}", ldscript.to_string_lossy()),
+        ])
+        .status()?
+        .exit_ok()?;
+
+        let bin_dir = Path::new(target_root).join("x86_64-pc-oceanic/release");
+        let path = src_root.join(H2O_KERNEL).join("target/vdso");
+
+        fs::copy(bin_dir.join("libsv_call.so"), &path)?;
+
+        Command::new(&*LLVM_IFS)
+            .arg("--input-format=ELF")
+            .arg(format!(
+                "--output-elf={}/sysroot/usr/lib/libh2o.so",
+                target_root
+            ))
+            .arg(&path)
+            .status()?
+            .exit_ok()?;
+
+        let out = Command::new(&*LLVM_OBJDUMP)
+            .arg("--syms")
+            .arg(&path)
+            .output()?
+            .stdout;
+
+        let s = String::from_utf8_lossy(&out);
+        let (constants_offset, _) = s
+            .split('\n')
+            .find(|s| s.ends_with("CONSTANTS"))
+            .and_then(|s| s.split_once(' '))
+            .expect("Failed to get CONSTANTS");
+
+        fs::write(
+            src_root.join(H2O_KERNEL).join("target/constant_offset.rs"),
+            format!("0x{}", constants_offset),
+        )?;
+
+        self.gen_debug("vdso", src_root.join(H2O_KERNEL).join("target"), DEBUG_DIR)?;
+
+        Ok(())
+    }
+
+    fn build_lib(&self, src_root: impl AsRef<Path>, target_root: &str) -> anyhow::Result<()> {
         let src_root = src_root.as_ref().join(OC_LIB);
         let bin_dir = Path::new(target_root).join("x86_64-pc-oceanic");
         let dst_root = Path::new(target_root).join("bootfs/lib");
 
         self.build_impl(
-            cargo,
             "libldso.so",
             "ld-oceanic.so",
             src_root.join("libc/ldso"),
@@ -192,7 +204,7 @@ impl Dist {
             &dst_root,
         )?;
 
-        Command::new("llvm-ifs")
+        Command::new(&*LLVM_IFS)
             .arg("--input-format=ELF")
             .arg(format!(
                 "--output-elf={}",
@@ -205,7 +217,6 @@ impl Dist {
             .exit_ok()?;
 
         self.build_impl(
-            cargo,
             "libco2.so",
             "libco2.so",
             src_root.join("libc"),
@@ -216,12 +227,7 @@ impl Dist {
         Ok(())
     }
 
-    fn build_bin(
-        &self,
-        cargo: &str,
-        src_root: impl AsRef<Path>,
-        target_root: &str,
-    ) -> Result<(), Box<dyn Error>> {
+    fn build_bin(&self, src_root: impl AsRef<Path>, target_root: &str) -> anyhow::Result<()> {
         let bin_dir = Path::new(target_root).join("x86_64-pc-oceanic");
         let dep_root = Path::new(target_root).join("bootfs/lib");
 
@@ -233,7 +239,7 @@ impl Dist {
         let mut build = |src_root: PathBuf,
                          dst_root: PathBuf,
                          is_dylib: bool|
-         -> Result<(), Box<dyn Error>> {
+         -> anyhow::Result<()> {
             for ent in fs::read_dir(src_root)?.flatten() {
                 let ty = ent.file_type()?;
                 let name = ent.file_name();
@@ -245,7 +251,7 @@ impl Dist {
                     } else {
                         name
                     };
-                    self.build_impl(cargo, &dst_name, &dst_name, ent.path(), &bin_dir, &dst_root)?;
+                    self.build_impl(&dst_name, &dst_name, ent.path(), &bin_dir, &dst_root)?;
                     for dep in fs::read_dir(bin_dir.join(self.profile()).join("deps"))?.flatten() {
                         let name = dep.file_name();
                         match name.to_str() {
@@ -279,16 +285,15 @@ impl Dist {
 
     fn build_impl(
         &self,
-        cargo: &str,
         bin_name: impl AsRef<Path>,
         dst_name: impl AsRef<Path>,
         src_dir: impl AsRef<Path>,
         bin_dir: impl AsRef<Path>,
         target_dir: impl AsRef<Path>,
-    ) -> Result<(), Box<dyn Error>> {
+    ) -> anyhow::Result<()> {
         println!("Building {:?}", dst_name.as_ref());
 
-        let mut cmd = Command::new(cargo);
+        let mut cmd = Command::new(&*CARGO);
         let cmd = cmd.current_dir(src_dir).arg("build");
         if self.release {
             cmd.arg("--release");
@@ -305,17 +310,17 @@ impl Dist {
         target_name: impl AsRef<Path>,
         target_dir: impl AsRef<Path>,
         dbg_dir: impl AsRef<Path>,
-    ) -> Result<(), Box<dyn Error>> {
+    ) -> anyhow::Result<()> {
         let target_path = target_dir.as_ref().join(&target_name);
         {
             let mut sym_name = OsString::from(target_name.as_ref().as_os_str());
             sym_name.push(".sym");
-            Command::new("llvm-objcopy")
+            Command::new(&*LLVM_OBJCOPY)
                 .arg("--only-keep-debug")
                 .arg(&target_path)
                 .arg(dbg_dir.as_ref().join(sym_name))
                 .status()?;
-            Command::new("llvm-objcopy")
+            Command::new(&*LLVM_OBJCOPY)
                 .arg("--strip-debug")
                 .arg(&target_path)
                 .status()?;
@@ -337,7 +342,7 @@ impl Dist {
             txt_name.push(".txt");
             fs::write(
                 dbg_dir.as_ref().join(txt_name),
-                Command::new("llvm-objdump")
+                Command::new(&*LLVM_OBJDUMP)
                     .arg("-x")
                     .arg(&target_path)
                     .output()?
@@ -347,3 +352,18 @@ impl Dist {
         Ok(())
     }
 }
+
+fn create_dir_all(target_root: &String, src_root: &Path) -> Result<(), anyhow::Error> {
+    let create_dir = |path: &Path| -> anyhow::Result<()> {
+        fs::create_dir_all(path).with_context(|| format!("failed to create dir {path:?}"))
+    };
+    create_dir(&PathBuf::from(target_root).join("bootfs/lib"))?;
+    create_dir(&PathBuf::from(target_root).join("bootfs/drv"))?;
+    create_dir(&PathBuf::from(target_root).join("bootfs/bin"))?;
+    create_dir(&PathBuf::from(target_root).join("sysroot/usr/include"))?;
+    create_dir(&PathBuf::from(target_root).join("sysroot/usr/lib"))?;
+    create_dir(&src_root.join(H2O_KERNEL).join("target"))?;
+    create_dir(&src_root.join("h2o/libs/syscall/target"))?;
+    create_dir("debug".as_ref())?;
+    Ok(())
+}

+ 3 - 3
xtask/src/gen.rs

@@ -1,7 +1,7 @@
 mod bootfs;
 mod syscall;
 
-use std::{error::Error, fs, io::BufWriter, path::Path};
+use std::{fs, io::BufWriter, path::Path};
 
 use rand::{prelude::SliceRandom, thread_rng};
 
@@ -13,7 +13,7 @@ pub fn gen_syscall(
     call_file: impl AsRef<Path>,
     stub_file: impl AsRef<Path>,
     num_file: impl AsRef<Path>,
-) -> Result<(), Box<dyn Error>> {
+) -> anyhow::Result<()> {
     let Syscall {
         mut types,
         mut funcs,
@@ -33,7 +33,7 @@ pub fn gen_syscall(
     Ok(())
 }
 
-pub fn gen_bootfs(output: impl AsRef<Path>) -> Result<(), Box<dyn Error>> {
+pub fn gen_bootfs(output: impl AsRef<Path>) -> anyhow::Result<()> {
     let data = bootfs::parse(crate::BOOTFS)?;
     let mut file = BufWriter::new(fs::File::create(output)?);
     ::bootfs::gen::generate(&data, &mut file)?;

+ 5 - 5
xtask/src/gen/bootfs.rs

@@ -1,8 +1,8 @@
-use std::{error::Error, fs, io::Read, os::unix::prelude::OsStringExt, path::Path};
+use std::{fs, io::Read, os::unix::prelude::OsStringExt, path::Path};
 
 use bootfs::gen::{Content, Entry};
 
-fn parse_file(path: impl AsRef<Path>, name: Vec<u8>) -> Result<Entry, Box<dyn Error>> {
+fn parse_file(path: impl AsRef<Path>, name: Vec<u8>) -> anyhow::Result<Entry> {
     let mut content = vec![];
     fs::File::open(path)?.read_to_end(&mut content)?;
     Ok(Entry {
@@ -11,7 +11,7 @@ fn parse_file(path: impl AsRef<Path>, name: Vec<u8>) -> Result<Entry, Box<dyn Er
     })
 }
 
-fn parse_dir(path: impl AsRef<Path>, name: Vec<u8>) -> Result<Entry, Box<dyn Error>> {
+fn parse_dir(path: impl AsRef<Path>, name: Vec<u8>) -> anyhow::Result<Entry> {
     let content = fs::read_dir(path)?
         .flatten()
         .try_fold(Vec::<Entry>::new(), |mut acc, ent| {
@@ -21,7 +21,7 @@ fn parse_dir(path: impl AsRef<Path>, name: Vec<u8>) -> Result<Entry, Box<dyn Err
             } else if ty.is_dir() {
                 acc.push(parse_dir(ent.path(), ent.file_name().into_vec())?);
             }
-            Ok::<_, Box<dyn Error>>(acc)
+            Ok::<_, anyhow::Error>(acc)
         })?;
     Ok(Entry {
         name,
@@ -29,6 +29,6 @@ fn parse_dir(path: impl AsRef<Path>, name: Vec<u8>) -> Result<Entry, Box<dyn Err
     })
 }
 
-pub fn parse(root: impl AsRef<Path>) -> Result<Entry, Box<dyn Error>> {
+pub fn parse(root: impl AsRef<Path>) -> anyhow::Result<Entry> {
     parse_dir(root, "bootfs".as_bytes().to_owned())
 }

+ 6 - 7
xtask/src/gen/syscall.rs

@@ -1,5 +1,4 @@
 use std::{
-    error::Error,
     fs,
     io::{BufWriter, Write},
     path::Path,
@@ -37,13 +36,13 @@ impl Syscall {
     }
 }
 
-fn parse_file(file: impl AsRef<Path>) -> Result<Syscall, Box<dyn Error>> {
+fn parse_file(file: impl AsRef<Path>) -> anyhow::Result<Syscall> {
     // println!("parsing file {:?}", file.as_ref());
     let file = fs::File::open(file)?;
     Ok(serde_json::from_reader(&file)?)
 }
 
-pub fn parse_dir(dir: impl AsRef<Path>) -> Result<Syscall, Box<dyn Error>> {
+pub fn parse_dir(dir: impl AsRef<Path>) -> anyhow::Result<Syscall> {
     fs::read_dir(dir)?
         .flatten()
         .try_fold(Syscall::default(), |mut ret, ent| {
@@ -55,7 +54,7 @@ pub fn parse_dir(dir: impl AsRef<Path>) -> Result<Syscall, Box<dyn Error>> {
         })
 }
 
-pub fn gen_wrappers(funcs: &[SyscallFn], output: impl AsRef<Path>) -> Result<(), Box<dyn Error>> {
+pub fn gen_wrappers(funcs: &[SyscallFn], output: impl AsRef<Path>) -> anyhow::Result<()> {
     let mut output = BufWriter::new(fs::File::create(output)?);
 
     write!(output, "[")?;
@@ -77,7 +76,7 @@ pub fn gen_wrappers(funcs: &[SyscallFn], output: impl AsRef<Path>) -> Result<(),
     Ok(())
 }
 
-pub fn gen_rust_calls(funcs: &[SyscallFn], output: impl AsRef<Path>) -> Result<(), Box<dyn Error>> {
+pub fn gen_rust_calls(funcs: &[SyscallFn], output: impl AsRef<Path>) -> anyhow::Result<()> {
     let mut output = BufWriter::new(fs::File::create(output)?);
 
     for (i, func) in funcs.iter().enumerate() {
@@ -139,7 +138,7 @@ pub fn gen_rust_calls(funcs: &[SyscallFn], output: impl AsRef<Path>) -> Result<(
     Ok(())
 }
 
-pub fn gen_rust_stubs(funcs: &[SyscallFn], output: impl AsRef<Path>) -> Result<(), Box<dyn Error>> {
+pub fn gen_rust_stubs(funcs: &[SyscallFn], output: impl AsRef<Path>) -> anyhow::Result<()> {
     let mut output = BufWriter::new(fs::File::create(output)?);
 
     write!(output, "#[link(name = \"h2o\")] extern \"C\" {{")?;
@@ -180,7 +179,7 @@ pub fn gen_rust_nums(
     types: &[String],
     funcs: &[SyscallFn],
     output: impl AsRef<Path>,
-) -> Result<(), Box<dyn Error>> {
+) -> anyhow::Result<()> {
     let mut output = BufWriter::new(fs::File::create(output)?);
 
     for (i, func) in funcs.iter().enumerate() {

+ 2 - 3
xtask/src/main.rs

@@ -1,6 +1,5 @@
 #![feature(exit_status_error)]
-
-use std::error::Error;
+#![feature(once_cell)]
 
 use structopt::StructOpt;
 
@@ -26,7 +25,7 @@ enum Cmd {
     Check,
 }
 
-fn main() -> Result<(), Box<dyn Error>> {
+fn main() -> anyhow::Result<()> {
     let args = Cmd::from_args();
     match args {
         Cmd::Dist(dist) => dist.build(),