diff --git a/.github/workflows/mediasoup-rust.yaml b/.github/workflows/mediasoup-rust.yaml index cef42f5b36..73d3cad750 100644 --- a/.github/workflows/mediasoup-rust.yaml +++ b/.github/workflows/mediasoup-rust.yaml @@ -7,13 +7,17 @@ env: jobs: ci: - runs-on: ubuntu-20.04 strategy: matrix: + os: + - ubuntu-20.04 + - macos-10.15 rust: - stable # - nightly + runs-on: ${{ matrix.os }} + steps: - name: Checkout uses: actions/checkout@v2 @@ -37,7 +41,7 @@ jobs: ~/.cargo/registry ~/.cargo/git target - key: ${{ runner.os }}-cargo-${{ matrix.rust }}-${{ hashFiles('**/Cargo.toml') }} + key: ${{ matrix.os }}-cargo-${{ matrix.rust }}-${{ hashFiles('**/Cargo.toml') }} - name: cargo fmt uses: actions-rs/cargo@v1 diff --git a/rust/src/worker/utils.rs b/rust/src/worker/utils.rs index 45586b3c80..44faf221ca 100644 --- a/rust/src/worker/utils.rs +++ b/rust/src/worker/utils.rs @@ -36,10 +36,7 @@ fn pipe() -> [c_int; 2] { let mut fds = mem::MaybeUninit::<[c_int; 2]>::uninit(); if libc::pipe(fds.as_mut_ptr().cast::()) != 0 { - panic!( - "libc::pipe() failed with code {}", - *libc::__errno_location() - ); + panic!("libc::pipe() failed: {:?}", std::io::Error::last_os_error()); } fds.assume_init() diff --git a/worker/build.rs b/worker/build.rs index 032d72cde8..cbb91efd0c 100644 --- a/worker/build.rs +++ b/worker/build.rs @@ -7,10 +7,17 @@ fn main() { return; } + let current_dir = std::env::current_dir() + .unwrap() + .into_os_string() + .into_string() + .unwrap(); + let out_dir = env::var("OUT_DIR").unwrap(); + // Add C++ std lib #[cfg(target_os = "linux")] { - let path = Command::new(env::var("c++").unwrap_or_else(|_| "c++".to_string())) + let path = Command::new(env::var("CXX").unwrap_or_else(|_| "c++".to_string())) .arg("--print-file-name=libstdc++.a") .output() .expect("Failed to start") @@ -31,7 +38,7 @@ fn main() { target_os = "netbsd" ))] { - let path = Command::new(env::var("c++").unwrap_or_else(|_| "c++".to_string())) + let path = Command::new(env::var("CXX").unwrap_or_else(|_| "c++".to_string())) .arg("--print-file-name=libc++.a") .output() .expect("Failed to start") @@ -47,8 +54,56 @@ fn main() { } #[cfg(target_os = "macos")] { - panic!("Building on macOS is not currently supported"); - // TODO: The issue here is `libc++.a` that is not shipped with macOS's `c++` it seems + let clang_llvm_version = "clang+llvm-12.0.0-x86_64-apple-darwin"; + let status = Command::new("curl") + .args(&[ + "-L", + "-s", + "-O", + &format!("https://github.com/llvm/llvm-project/releases/download/llvmorg-12.0.0/{}.tar.xz", clang_llvm_version), + ]) + .current_dir(&out_dir) + .status() + .expect("Failed to start"); + + if !status.success() { + panic!("Failed to download libc++"); + } + + let status = Command::new("tar") + .args(&[ + "-xf", + &format!("{}.tar.xz", clang_llvm_version), + &format!("{}/lib/libc++.a", clang_llvm_version), + &format!("{}/lib/libc++abi.a", clang_llvm_version), + ]) + .current_dir(&out_dir) + .status() + .expect("Failed to start"); + if !status.success() { + panic!("Failed to download libc++"); + } + + for file in &["libc++.a", "libc++abi.a"] { + std::fs::copy( + format!("{}/{}/lib/{}", out_dir, clang_llvm_version, file), + format!("{}/{}", out_dir, file), + ) + .unwrap_or_else(|_| { + panic!( + "Failed to copy static library from {}/{}/lib/{} to {}/{}", + out_dir, clang_llvm_version, file, out_dir, file + ) + }); + } + + std::fs::remove_file(format!("{}/{}.tar.xz", out_dir, clang_llvm_version)) + .expect("Failed to remove downloaded clang+llvm archive"); + std::fs::remove_dir_all(format!("{}/{}", out_dir, clang_llvm_version)) + .expect("Failed to remove extracted clang+llvm files"); + + println!("cargo:rustc-link-lib=static=c++"); + println!("cargo:rustc-link-lib=static=c++abi"); } #[cfg(target_os = "windows")] { @@ -56,13 +111,6 @@ fn main() { // TODO: Didn't bother, feel free to PR } - let current_dir = std::env::current_dir() - .unwrap() - .into_os_string() - .into_string() - .unwrap(); - let out_dir = env::var("OUT_DIR").unwrap(); - // The build here is a bit awkward since we can't just specify custom target directory as // openssl will fail to build with `make[1]: /bin/sh: Argument list too long` due to large // number of files. So instead we build in place, copy files to out directory and then clean