diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index d48ccd28..2d75d151 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -23,9 +23,19 @@ permissions: contents: read jobs: - build_x86_64: - name: "Build (x86_64/Linux)" - runs-on: ubuntu-latest + build: + strategy: + matrix: + include: + - host: "ubuntu-latest" + os: "linux" + arch: "x86_64" + - host: "macos-latest" + os: "macos" + arch: "aarch64" + + name: "Build (${{ matrix.arch }}/${{ matrix.os }})" + runs-on: ${{ matrix.host }} steps: - name: Checkout uses: actions/checkout@v4 @@ -47,7 +57,7 @@ jobs: - name: "Upload binaries" uses: actions/upload-artifact@v4 with: - name: binaries-x86_64-linux + name: binaries-${{ matrix.arch }}-${{ matrix.os }} path: target/release/brush build_cross: diff --git a/Cargo.lock b/Cargo.lock index 310eb18d..b007a5e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -251,6 +251,7 @@ dependencies = [ "async-trait", "brush-parser", "cached", + "cfg-if", "clap", "command-fds", "criterion", diff --git a/brush-core/Cargo.toml b/brush-core/Cargo.toml index 8da18790..f168fb43 100644 --- a/brush-core/Cargo.toml +++ b/brush-core/Cargo.toml @@ -21,6 +21,7 @@ async-recursion = "1.1.0" async-trait = "0.1.80" brush-parser = { version = "^0.2.3", path = "../brush-parser" } cached = "0.51.3" +cfg-if = "1.0.0" # N.B. Pin to 4.4.18 for now to keep to 1.72.0 as MSRV; 4.5.x requires a later version. clap = { version = "=4.4.18", features = ["derive", "wrap_help"] } fancy-regex = "0.13.0" @@ -57,9 +58,11 @@ whoami = "1.5.1" [target.'cfg(unix)'.dependencies] command-fds = "0.3.0" nix = { version = "0.29.0", features = ["fs", "process", "signal", "term", "user"] } -procfs = "0.16.0" uzers = "0.12.0" +[target.'cfg(target_os = "linux")'.dependencies] +procfs = "0.16.0" + [dev-dependencies] anyhow = "1.0.86" criterion = { version = "0.5.1", features = ["async_tokio", "html_reports"] } diff --git a/brush-core/src/builtins/umask.rs b/brush-core/src/builtins/umask.rs index 4c8aca0d..ad9dac48 100644 --- a/brush-core/src/builtins/umask.rs +++ b/brush-core/src/builtins/umask.rs @@ -1,5 +1,7 @@ use crate::{builtin, commands, error}; +use cfg_if::cfg_if; use clap::Parser; +use nix::sys::stat::Mode; use std::io::Write; /// Manage the process umask. @@ -53,14 +55,25 @@ impl builtin::Command for UmaskCommand { } } -fn get_umask() -> Result { - let me = procfs::process::Process::myself()?; - let status = me.status()?; - status.umask.ok_or_else(|| error::Error::InvalidUmask) +cfg_if! { + if #[cfg(target_os = "linux")] { + fn get_umask() -> Result { + let me = procfs::process::Process::myself()?; + let status = me.status()?; + status.umask.ok_or_else(|| error::Error::InvalidUmask) + } + } else { + fn get_umask() -> Result { + let u = nix::sys::stat::umask(Mode::empty()); + nix::sys::stat::umask(u); + Ok(u.bits() as u32) + } + } } fn set_umask(value: u32) -> Result<(), error::Error> { - let mode = nix::sys::stat::Mode::from_bits(value).ok_or_else(|| error::Error::InvalidUmask)?; + let mode = + nix::sys::stat::Mode::from_bits(value as _).ok_or_else(|| error::Error::InvalidUmask)?; nix::sys::stat::umask(mode); Ok(()) } diff --git a/brush-core/src/error.rs b/brush-core/src/error.rs index fd6ed79b..a1abbb9f 100644 --- a/brush-core/src/error.rs +++ b/brush-core/src/error.rs @@ -153,7 +153,7 @@ pub enum Error { InvalidUmask, /// An error occurred reading from procfs. - #[cfg(unix)] + #[cfg(target_os = "linux")] #[error("procfs error: {0}")] ProcfsError(#[from] procfs::ProcError), diff --git a/brush-core/src/interp.rs b/brush-core/src/interp.rs index 58fc755a..119076c7 100644 --- a/brush-core/src/interp.rs +++ b/brush-core/src/interp.rs @@ -2,7 +2,7 @@ use brush_parser::ast::{self, CommandPrefixOrSuffixItem}; use itertools::Itertools; use std::collections::VecDeque; use std::io::Write; -#[cfg(unix)] +#[cfg(target_os = "linux")] use std::os::fd::{AsFd, AsRawFd}; #[cfg(unix)] use std::os::unix::process::ExitStatusExt; @@ -1469,7 +1469,7 @@ fn setup_open_file_with_contents(contents: &str) -> Result