diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c32fe17ad..e6adf22b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -33,6 +33,24 @@ jobs: aws_secret_access_key: "${{ secrets.AWS_SECRET_ACCESS_KEY }}" if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/deploy' + test_on_windows: + name: Test on Windows + runs-on: windows-latest + steps: + - name: Checkout the source code + uses: actions/checkout@v2 + with: + fetch-depth: 1 + + - name: Install latest beta + uses: actions-rs/toolchain@v1 + with: + toolchain: beta + override: true + + - name: cargo check + run: cargo check + test_benchmarks: strategy: matrix: diff --git a/Cargo.lock b/Cargo.lock index 0d0665c6c..dbfe8704f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -227,12 +227,14 @@ dependencies = [ "crossbeam-utils", "database", "env_logger", + "filetime", "futures", "intern", "jobserver", "lazy_static", "libc", "log", + "miow 0.3.6", "num_cpus", "reqwest", "rustc-artifacts", @@ -244,6 +246,8 @@ dependencies = [ "tempfile", "thiserror", "tokio", + "walkdir", + "winapi 0.3.8", "xz2", ] @@ -407,13 +411,13 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "filetime" -version = "0.2.10" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "affc17579b132fc2461adf7c575cc6e8b134ebca52c51f5411388965227dc695" +checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", - "redox_syscall", + "redox_syscall 0.2.5", "winapi 0.3.8", ] @@ -1012,7 +1016,7 @@ dependencies = [ "kernel32-sys", "libc", "log", - "miow", + "miow 0.2.1", "net2", "slab", "winapi 0.2.8", @@ -1041,6 +1045,16 @@ dependencies = [ "ws2_32-sys", ] +[[package]] +name = "miow" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897" +dependencies = [ + "socket2", + "winapi 0.3.8", +] + [[package]] name = "native-tls" version = "0.2.4" @@ -1199,7 +1213,7 @@ dependencies = [ "cfg-if 0.1.10", "cloudabi 0.0.3", "libc", - "redox_syscall", + "redox_syscall 0.1.56", "smallvec", "winapi 0.3.8", ] @@ -1214,7 +1228,7 @@ dependencies = [ "cloudabi 0.1.0", "instant", "libc", - "redox_syscall", + "redox_syscall 0.1.56", "smallvec", "winapi 0.3.8", ] @@ -1480,6 +1494,15 @@ version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +[[package]] +name = "redox_syscall" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +dependencies = [ + "bitflags", +] + [[package]] name = "regex" version = "1.3.9" @@ -1636,6 +1659,15 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.19" @@ -1831,13 +1863,12 @@ checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e" [[package]] name = "socket2" -version = "0.3.12" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" +checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", - "redox_syscall", "winapi 0.3.8", ] @@ -1894,7 +1925,7 @@ checksum = "5c058ad0bd6ccb84faa24cc44d4fc99bee8a5d7ba9ff33aa4d993122d1aeeac2" dependencies = [ "filetime", "libc", - "redox_syscall", + "redox_syscall 0.1.56", "xattr", ] @@ -1907,7 +1938,7 @@ dependencies = [ "cfg-if 0.1.10", "libc", "rand", - "redox_syscall", + "redox_syscall 0.1.56", "remove_dir_all", "winapi 0.3.8", ] @@ -2148,6 +2179,17 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +[[package]] +name = "walkdir" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" +dependencies = [ + "same-file", + "winapi 0.3.8", + "winapi-util", +] + [[package]] name = "want" version = "0.3.0" diff --git a/collector/Cargo.toml b/collector/Cargo.toml index aed978a77..cf6d4442f 100644 --- a/collector/Cargo.toml +++ b/collector/Cargo.toml @@ -29,6 +29,12 @@ num_cpus = "1.13" jobserver = "0.1.21" crossbeam-utils = "0.7" snap = "1" +filetime = "0.2.14" +walkdir = "2" + +[target.'cfg(windows)'.dependencies] +miow = "0.3" +winapi = { version = "0.3", features = ["winerror"] } [[bin]] name = "collector" diff --git a/collector/benchmarks/coercions/1-add-static-arr-item.patch b/collector/benchmarks/coercions/1-add-static-arr-item.patch index 329c902f8..91d2e9218 100644 --- a/collector/benchmarks/coercions/1-add-static-arr-item.patch +++ b/collector/benchmarks/coercions/1-add-static-arr-item.patch @@ -18,4 +18,4 @@ index 3fb7c5f..775773b 100644 + "", ]; - fn main() { } + fn main() { println!("test"); } diff --git a/collector/src/execute.rs b/collector/src/execute.rs index a1cd996c7..2eaacac6b 100644 --- a/collector/src/execute.rs +++ b/collector/src/execute.rs @@ -6,7 +6,7 @@ use collector::command_output; use database::{PatchName, QueryLabel}; use futures::stream::FuturesUnordered; use futures::stream::StreamExt; -use std::cmp; +use std::{cmp, ffi::OsStr, path::Component}; use std::collections::HashMap; use std::env; use std::fmt; @@ -23,6 +23,20 @@ use tokio::runtime::Runtime; mod rustc; +#[cfg(windows)] +fn rename, Q: AsRef>(from: P, to: Q) -> anyhow::Result<()> { + let (from, to) = (from.as_ref(), to.as_ref()); + + let ctx = format!("renaming file {:?} to {:?}", from, to); + + if fs::metadata(from)?.is_file() { + return Ok(fs::rename(from, to).with_context(|| ctx.clone())?); + } + + collector::robocopy(from, to, &[&"/move"]).with_context(|| ctx.clone()) +} + +#[cfg(unix)] fn rename, Q: AsRef>(from: P, to: Q) -> anyhow::Result<()> { let (from, to) = (from.as_ref(), to.as_ref()); if fs::rename(from, to).is_err() { @@ -44,26 +58,48 @@ fn rename, Q: AsRef>(from: P, to: Q) -> anyhow::Result<()> Ok(()) } -fn touch(root: &Path, path: &Path) -> anyhow::Result<()> { - let mut cmd = Command::new("touch"); - cmd.current_dir(root).arg(path); - command_output(&mut cmd).with_context(|| format!("touching {:?} in {:?}", path, root))?; +fn touch(path: &Path) -> anyhow::Result<()> { + log::trace!("touching file {:?}", path); + + filetime::set_file_mtime(path, filetime::FileTime::now()).with_context(|| format!("touching file {:?}", path))?; + Ok(()) } fn touch_all(path: &Path) -> anyhow::Result<()> { - let mut cmd = Command::new("bash"); - // Don't touch files in `target/`, since they're likely generated by build scripts and might be from a dependency. - // Don't touch build scripts, which confuses the wrapped rustc. - cmd.current_dir(path) - .args(&["-c", "find . -path ./target -prune -false -o -name '*.rs' | grep -v '^./build.rs$' | xargs touch"]); - command_output(&mut cmd).with_context(|| format!("touching all .rs in {:?}", path))?; - // We also delete the cmake caches to avoid errors when moving directories around. - // This might be a bit slower but at least things build - let mut cmd = Command::new("bash"); - cmd.current_dir(path) - .args(&["-c", "find . -name 'CMakeCache.txt' -delete"]); - command_output(&mut cmd).with_context(|| format!("deleting cmake caches in {:?}", path))?; + fn is_valid(path: &Path) -> bool { + let target_dir = Component::Normal(OsStr::new("target")); + + // Don't touch files in `target/`, since they're likely generated by build scripts and might be from a dependency. + if path.components().any(|component| component == target_dir) { + return false; + } + + if let Some(extn) = path.extension() { + if extn.to_str() == Some("rs") { + // Don't touch build scripts, which confuses the wrapped rustc. + return path.file_name() != Some(OsStr::new("build.rs")); + } + } + + false + } + + for entry in walkdir::WalkDir::new(path) { + let entry = entry?; + let path = entry.path(); + + // We also delete the cmake caches to avoid errors when moving directories around. + // This might be a bit slower but at least things build + if path.file_name() == Some(OsStr::new("CMakeCache.txt")) { + fs::remove_file(path).with_context(|| format!("deleting cmake caches in {:?}", path))?; + } + + if is_valid(path) { + touch(path)?; + } + } + Ok(()) } @@ -380,7 +416,7 @@ impl<'a> CargoProcess<'a> { // in-tree (e.g., in the case of the servo crates there are a lot of // other components). if let Some(file) = &self.touch_file { - touch(&self.cwd, Path::new(&file))?; + touch(&self.cwd.join(Path::new(&file)))?; } else { touch_all( &self.cwd.join( @@ -880,11 +916,13 @@ impl<'a> Processor for ProfileProcessor<'a> { rename(path, filepath(&zsp_dir, "Zsp.string_data"))?; } else if filename_str.ends_with(".string_index") { rename(path, filepath(&zsp_dir, "Zsp.string_index"))?; + } else if filename_str.ends_with(".mm_profdata") { + rename(path, filepath(&zsp_dir, "Zsp.mm_profdata"))?; } else { panic!("unexpected file {:?}", path); } } - assert_eq!(num_files, 3); + assert!(num_files == 3 || num_files == 1); // Run `summarize`. let mut summarize_cmd = Command::new("summarize"); @@ -1095,15 +1133,26 @@ impl Benchmark { self.config.supports_stable } + #[cfg(windows)] + fn copy(from: &Path, to: &Path) -> anyhow::Result<()> { + collector::robocopy(from, to, &[]) + } + + #[cfg(unix)] + fn copy(from: &Path, to: &Path) -> anyhow::Result<()> { + let mut cmd = Command::new("cp"); + cmd.arg("-pLR").arg(from).arg(to); + command_output(&mut cmd)?; + Ok(()) + } + fn make_temp_dir(&self, base: &Path) -> anyhow::Result { // Appending `.` means we copy just the contents of `base` into // `tmp_dir`, rather than `base` itself. let mut base_dot = base.to_path_buf(); base_dot.push("."); let tmp_dir = TempDir::new()?; - let mut cmd = Command::new("cp"); - cmd.arg("-pLR").arg(base_dot).arg(tmp_dir.path()); - command_output(&mut cmd).with_context(|| format!("copying {} to tmp dir", self.name))?; + Self::copy(&base_dot, tmp_dir.path()).with_context(|| format!("copying {} to tmp dir", self.name))?; Ok(tmp_dir) } @@ -1497,14 +1546,14 @@ impl Patch { } } - pub fn apply(&self, dir: &Path) -> Result<(), String> { + pub fn apply(&self, dir: &Path) -> anyhow::Result<()> { log::debug!("applying {} to {:?}", self.name, dir); - let mut cmd = Command::new("patch"); - cmd.current_dir(dir).args(&["-Np1", "-i"]).arg(&*self.path); - cmd.stdout(Stdio::null()); - if cmd.status().map(|s| !s.success()).unwrap_or(false) { - return Err(format!("could not execute {:?}.", cmd)); - } + + let mut cmd = Command::new("git"); + cmd.current_dir(dir).args(&["apply"]).args(&["-Np1"]).arg(&*self.path); + + command_output(&mut cmd)?; + Ok(()) } } diff --git a/collector/src/lib.rs b/collector/src/lib.rs index 88c7f19de..403a21403 100644 --- a/collector/src/lib.rs +++ b/collector/src/lib.rs @@ -144,7 +144,35 @@ pub fn run_command(cmd: &mut Command) -> anyhow::Result<()> { Ok(()) } -pub fn command_output(cmd: &mut Command) -> anyhow::Result { +#[cfg(windows)] +pub fn robocopy( + from: &std::path::Path, + to: &std::path::Path, + extra_args: &[&dyn AsRef] +) -> anyhow::Result<()> { + let mut cmd = Command::new("robocopy"); + cmd.arg(from).arg(to).arg("/s").arg("/e"); + + for arg in extra_args { + cmd.arg(arg.as_ref()); + } + + let output = run_command_with_output(&mut cmd)?; + + if output.status.code() >= Some(8) { + // robocopy returns 0-7 on success + return Err(anyhow::anyhow!( + "expected success, got {}\n\nstderr={}\n\n stdout={}", + output.status, + String::from_utf8_lossy(&output.stderr), + String::from_utf8_lossy(&output.stdout) + )); + } + + Ok(()) +} + +fn run_command_with_output(cmd: &mut Command) -> anyhow::Result { log::trace!("running: {:?}", cmd); let mut child = cmd.stdout(Stdio::piped()).stderr(Stdio::piped()).spawn()?; @@ -174,19 +202,25 @@ pub fn command_output(cmd: &mut Command) -> anyhow::Result { )?; let status = child.wait()?; - if !status.success() { - return Err(anyhow::anyhow!( - "expected success, got {}\n\nstderr={}\n\n stdout={}", - status, - String::from_utf8_lossy(&stderr), - String::from_utf8_lossy(&stdout) - )); - } - let output = process::Output { + Ok(process::Output { status, stdout: stdout, stderr: stderr, - }; + }) +} + +pub fn command_output(cmd: &mut Command) -> anyhow::Result { + let output = run_command_with_output(cmd)?; + + if !output.status.success() { + return Err(anyhow::anyhow!( + "expected success, got {}\n\nstderr={}\n\n stdout={}", + output.status, + String::from_utf8_lossy(&output.stderr), + String::from_utf8_lossy(&output.stdout) + )); + } + Ok(output) } diff --git a/collector/src/read2.rs b/collector/src/read2.rs index c37ff4a6d..805dcc1dd 100644 --- a/collector/src/read2.rs +++ b/collector/src/read2.rs @@ -1,74 +1,201 @@ // This is copied from // https://github.com/rust-lang/rust/blob/master/src/tools/compiletest/src/read2.rs // and falls under the MIT or Apache 2.0 licenses. +pub use self::imp::read2; -use std::io; -use std::io::prelude::*; -use std::mem; -use std::os::unix::prelude::*; -use std::process::{ChildStderr, ChildStdout}; - -pub fn read2( - mut out_pipe: ChildStdout, - mut err_pipe: ChildStderr, - data: &mut dyn FnMut(bool, &mut Vec, bool), -) -> io::Result<()> { - unsafe { - libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK); - libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK); +#[cfg(not(any(unix, windows)))] +mod imp { + use std::io::{self, Read}; + use std::process::{ChildStderr, ChildStdout}; + + pub fn read2( + out_pipe: ChildStdout, + err_pipe: ChildStderr, + data: &mut dyn FnMut(bool, &mut Vec, bool), + ) -> io::Result<()> { + let mut buffer = Vec::new(); + out_pipe.read_to_end(&mut buffer)?; + data(true, &mut buffer, true); + buffer.clear(); + err_pipe.read_to_end(&mut buffer)?; + data(false, &mut buffer, true); + Ok(()) } +} + +#[cfg(unix)] +mod imp { + use std::io; + use std::io::prelude::*; + use std::mem; + use std::os::unix::prelude::*; + use std::process::{ChildStderr, ChildStdout}; + + pub fn read2( + mut out_pipe: ChildStdout, + mut err_pipe: ChildStderr, + data: &mut dyn FnMut(bool, &mut Vec, bool), + ) -> io::Result<()> { + unsafe { + libc::fcntl(out_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK); + libc::fcntl(err_pipe.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK); + } + + let mut out_done = false; + let mut err_done = false; + let mut out = Vec::new(); + let mut err = Vec::new(); + + let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() }; + fds[0].fd = out_pipe.as_raw_fd(); + fds[0].events = libc::POLLIN; + fds[1].fd = err_pipe.as_raw_fd(); + fds[1].events = libc::POLLIN; + let mut nfds = 2; + let mut errfd = 1; + + while nfds > 0 { + // wait for either pipe to become readable using `select` + let r = unsafe { libc::poll(fds.as_mut_ptr(), nfds, -1) }; + if r == -1 { + let err = io::Error::last_os_error(); + if err.kind() == io::ErrorKind::Interrupted { + continue; + } + return Err(err); + } - let mut out_done = false; - let mut err_done = false; - let mut out = Vec::new(); - let mut err = Vec::new(); - - let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() }; - fds[0].fd = out_pipe.as_raw_fd(); - fds[0].events = libc::POLLIN; - fds[1].fd = err_pipe.as_raw_fd(); - fds[1].events = libc::POLLIN; - let mut nfds = 2; - let mut errfd = 1; - - while nfds > 0 { - // wait for either pipe to become readable using `select` - let r = unsafe { libc::poll(fds.as_mut_ptr(), nfds, -1) }; - if r == -1 { - let err = io::Error::last_os_error(); - if err.kind() == io::ErrorKind::Interrupted { - continue; + // Read as much as we can from each pipe, ignoring EWOULDBLOCK or + // EAGAIN. If we hit EOF, then this will happen because the underlying + // reader will return Ok(0), in which case we'll see `Ok` ourselves. In + // this case we flip the other fd back into blocking mode and read + // whatever's leftover on that file descriptor. + let handle = |res: io::Result<_>| match res { + Ok(_) => Ok(true), + Err(e) => { + if e.kind() == io::ErrorKind::WouldBlock { + Ok(false) + } else { + Err(e) + } + } + }; + if !err_done && fds[errfd].revents != 0 && handle(err_pipe.read_to_end(&mut err))? { + err_done = true; + nfds -= 1; + } + data(false, &mut err, err_done); + if !out_done && fds[0].revents != 0 && handle(out_pipe.read_to_end(&mut out))? { + out_done = true; + fds[0].fd = err_pipe.as_raw_fd(); + errfd = 0; + nfds -= 1; } - return Err(err); + data(true, &mut out, out_done); } + Ok(()) + } +} + +#[cfg(windows)] +mod imp { + use std::io; + use std::os::windows::prelude::*; + use std::process::{ChildStderr, ChildStdout}; + use std::slice; + + use miow::iocp::{CompletionPort, CompletionStatus}; + use miow::pipe::NamedPipe; + use miow::Overlapped; + use winapi::shared::winerror::ERROR_BROKEN_PIPE; + + struct Pipe<'a> { + dst: &'a mut Vec, + overlapped: Overlapped, + pipe: NamedPipe, + done: bool, + } + + pub fn read2( + out_pipe: ChildStdout, + err_pipe: ChildStderr, + data: &mut dyn FnMut(bool, &mut Vec, bool), + ) -> io::Result<()> { + let mut out = Vec::new(); + let mut err = Vec::new(); + + let port = CompletionPort::new(1)?; + port.add_handle(0, &out_pipe)?; + port.add_handle(1, &err_pipe)?; - // Read as much as we can from each pipe, ignoring EWOULDBLOCK or - // EAGAIN. If we hit EOF, then this will happen because the underlying - // reader will return Ok(0), in which case we'll see `Ok` ourselves. In - // this case we flip the other fd back into blocking mode and read - // whatever's leftover on that file descriptor. - let handle = |res: io::Result<_>| match res { - Ok(_) => Ok(true), - Err(e) => { - if e.kind() == io::ErrorKind::WouldBlock { - Ok(false) - } else { - Err(e) + unsafe { + let mut out_pipe = Pipe::new(out_pipe, &mut out); + let mut err_pipe = Pipe::new(err_pipe, &mut err); + + out_pipe.read()?; + err_pipe.read()?; + + let mut status = [CompletionStatus::zero(), CompletionStatus::zero()]; + + while !out_pipe.done || !err_pipe.done { + for status in port.get_many(&mut status, None)? { + if status.token() == 0 { + out_pipe.complete(status); + data(true, out_pipe.dst, out_pipe.done); + out_pipe.read()?; + } else { + err_pipe.complete(status); + data(false, err_pipe.dst, err_pipe.done); + err_pipe.read()?; + } } } - }; - if !err_done && fds[errfd].revents != 0 && handle(err_pipe.read_to_end(&mut err))? { - err_done = true; - nfds -= 1; + + Ok(()) } - data(false, &mut err, err_done); - if !out_done && fds[0].revents != 0 && handle(out_pipe.read_to_end(&mut out))? { - out_done = true; - fds[0].fd = err_pipe.as_raw_fd(); - errfd = 0; - nfds -= 1; + } + + impl<'a> Pipe<'a> { + unsafe fn new(p: P, dst: &'a mut Vec) -> Pipe<'a> { + Pipe { + dst: dst, + pipe: NamedPipe::from_raw_handle(p.into_raw_handle()), + overlapped: Overlapped::zero(), + done: false, + } + } + + unsafe fn read(&mut self) -> io::Result<()> { + let dst = slice_to_end(self.dst); + match self.pipe.read_overlapped(dst, self.overlapped.raw()) { + Ok(_) => Ok(()), + Err(e) => { + if e.raw_os_error() == Some(ERROR_BROKEN_PIPE as i32) { + self.done = true; + Ok(()) + } else { + Err(e) + } + } + } + } + + unsafe fn complete(&mut self, status: &CompletionStatus) { + let prev = self.dst.len(); + self.dst.set_len(prev + status.bytes_transferred() as usize); + if status.bytes_transferred() == 0 { + self.done = true; + } } - data(true, &mut out, out_done); } - Ok(()) -} + + unsafe fn slice_to_end(v: &mut Vec) -> &mut [u8] { + if v.capacity() == 0 { + v.reserve(16); + } + if v.capacity() == v.len() { + v.reserve(1); + } + slice::from_raw_parts_mut(v.as_mut_ptr().offset(v.len() as isize), v.capacity() - v.len()) + } +} \ No newline at end of file diff --git a/collector/src/rustc-fake.rs b/collector/src/rustc-fake.rs index 55aeaf33d..baba1d247 100644 --- a/collector/src/rustc-fake.rs +++ b/collector/src/rustc-fake.rs @@ -305,6 +305,14 @@ fn bash_command(tool: OsString, args: Vec, redirect: &str) -> Command cmd } +#[cfg(windows)] +fn exec(cmd: &mut Command) { + let cmd_d = format!("{:?}", cmd); + if let Err(e) = cmd.status() { + panic!("failed to execute `{}`: {}", cmd_d, e); + } +} + #[cfg(unix)] fn exec(cmd: &mut Command) -> ! { use std::os::unix::prelude::*; diff --git a/site/Cargo.toml b/site/Cargo.toml index 1f342b39a..48c226115 100644 --- a/site/Cargo.toml +++ b/site/Cargo.toml @@ -26,8 +26,6 @@ regex = "1" lazy_static = "1" reqwest = { version = "0.10", features = ["json", "blocking"] } toml = "0.5" -jemallocator = "0.3" -jemalloc-ctl = "0.3" rust_team_data = { git = "https://github.com/rust-lang/team" } parking_lot = "0.10" snap = "1" @@ -46,6 +44,10 @@ inferno = { version="0.10", default-features = false } mime = "0.3" prometheus = "0.11" +[target.'cfg(unix)'.dependencies] +jemallocator = "0.3" +jemalloc-ctl = "0.3" + [dependencies.collector] path = "../collector" diff --git a/site/src/main.rs b/site/src/main.rs index 15def9780..8423f686f 100644 --- a/site/src/main.rs +++ b/site/src/main.rs @@ -15,12 +15,15 @@ use site::load; use std::env; use std::sync::Arc; +#[cfg(unix)] #[global_allocator] static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; #[tokio::main] async fn main() { env_logger::init(); + + #[cfg(unix)] let _ = jemalloc_ctl::background_thread::write(true); let data: Arc>>> = Arc::new(RwLock::new(None));