From 0c89243fd33a7f9f0ef4ddc9796047c646e9a688 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 7 Sep 2018 00:27:20 -0700 Subject: [PATCH] Fix compiling some rustc crates to wasm I was dabbling recently seeing what it would take to compile `rustfmt` to the `wasm32-unknown-unknown` target and it turns out not much effort is needed! Currently `rustfmt` depends on a few rustc crates published to crates.io, so this commit touches up those crates to compile for wasm themselves. Notably: * The `rustc_data_structures` crate's `flock` implementation is stubbed out to unconditionally return errors on unsupported platforms. * The `rustc_errors` crate is extended to not do any locking for all non-windows platforms. In both of these cases if we port the compiler to new platforms the functionality isn't critical but will be discovered over time as it comes up, so this hopefully doesn't make it too too hard to compile to new platforms! --- src/librustc_data_structures/flock.rs | 590 +++++++++++++------------- src/librustc_errors/lock.rs | 2 +- 2 files changed, 299 insertions(+), 293 deletions(-) diff --git a/src/librustc_data_structures/flock.rs b/src/librustc_data_structures/flock.rs index f10a9a68bed5b..38ce331051fec 100644 --- a/src/librustc_data_structures/flock.rs +++ b/src/librustc_data_structures/flock.rs @@ -15,345 +15,351 @@ //! librustdoc, it is not production quality at all. #![allow(non_camel_case_types)] -use std::path::Path; - -pub use self::imp::Lock; +#![allow(nonstandard_style)] -#[cfg(unix)] -mod imp { - use std::ffi::{CString, OsStr}; - use std::os::unix::prelude::*; - use std::path::Path; - use std::io; - use libc; +use std::io; +use std::path::Path; - #[cfg(any(target_os = "linux", target_os = "android"))] - mod os { +cfg_if! { + if #[cfg(unix)] { + use std::ffi::{CString, OsStr}; + use std::os::unix::prelude::*; use libc; - #[repr(C)] - pub struct flock { - pub l_type: libc::c_short, - pub l_whence: libc::c_short, - pub l_start: libc::off_t, - pub l_len: libc::off_t, - pub l_pid: libc::pid_t, - - // not actually here, but brings in line with freebsd - pub l_sysid: libc::c_int, - } + #[cfg(any(target_os = "linux", target_os = "android"))] + mod os { + use libc; - pub const F_RDLCK: libc::c_short = 0; - pub const F_WRLCK: libc::c_short = 1; - pub const F_UNLCK: libc::c_short = 2; - pub const F_SETLK: libc::c_int = 6; - pub const F_SETLKW: libc::c_int = 7; - } + #[repr(C)] + pub struct flock { + pub l_type: libc::c_short, + pub l_whence: libc::c_short, + pub l_start: libc::off_t, + pub l_len: libc::off_t, + pub l_pid: libc::pid_t, - #[cfg(target_os = "freebsd")] - mod os { - use libc; + // not actually here, but brings in line with freebsd + pub l_sysid: libc::c_int, + } - #[repr(C)] - pub struct flock { - pub l_start: libc::off_t, - pub l_len: libc::off_t, - pub l_pid: libc::pid_t, - pub l_type: libc::c_short, - pub l_whence: libc::c_short, - pub l_sysid: libc::c_int, + pub const F_RDLCK: libc::c_short = 0; + pub const F_WRLCK: libc::c_short = 1; + pub const F_UNLCK: libc::c_short = 2; + pub const F_SETLK: libc::c_int = 6; + pub const F_SETLKW: libc::c_int = 7; } - pub const F_RDLCK: libc::c_short = 1; - pub const F_UNLCK: libc::c_short = 2; - pub const F_WRLCK: libc::c_short = 3; - pub const F_SETLK: libc::c_int = 12; - pub const F_SETLKW: libc::c_int = 13; - } - - #[cfg(any(target_os = "dragonfly", - target_os = "bitrig", - target_os = "netbsd", - target_os = "openbsd"))] - mod os { - use libc; + #[cfg(target_os = "freebsd")] + mod os { + use libc; + + #[repr(C)] + pub struct flock { + pub l_start: libc::off_t, + pub l_len: libc::off_t, + pub l_pid: libc::pid_t, + pub l_type: libc::c_short, + pub l_whence: libc::c_short, + pub l_sysid: libc::c_int, + } - #[repr(C)] - pub struct flock { - pub l_start: libc::off_t, - pub l_len: libc::off_t, - pub l_pid: libc::pid_t, - pub l_type: libc::c_short, - pub l_whence: libc::c_short, - - // not actually here, but brings in line with freebsd - pub l_sysid: libc::c_int, + pub const F_RDLCK: libc::c_short = 1; + pub const F_UNLCK: libc::c_short = 2; + pub const F_WRLCK: libc::c_short = 3; + pub const F_SETLK: libc::c_int = 12; + pub const F_SETLKW: libc::c_int = 13; } - pub const F_RDLCK: libc::c_short = 1; - pub const F_UNLCK: libc::c_short = 2; - pub const F_WRLCK: libc::c_short = 3; - pub const F_SETLK: libc::c_int = 8; - pub const F_SETLKW: libc::c_int = 9; - } - - #[cfg(target_os = "haiku")] - mod os { - use libc; + #[cfg(any(target_os = "dragonfly", + target_os = "bitrig", + target_os = "netbsd", + target_os = "openbsd"))] + mod os { + use libc; + + #[repr(C)] + pub struct flock { + pub l_start: libc::off_t, + pub l_len: libc::off_t, + pub l_pid: libc::pid_t, + pub l_type: libc::c_short, + pub l_whence: libc::c_short, + + // not actually here, but brings in line with freebsd + pub l_sysid: libc::c_int, + } - #[repr(C)] - pub struct flock { - pub l_type: libc::c_short, - pub l_whence: libc::c_short, - pub l_start: libc::off_t, - pub l_len: libc::off_t, - pub l_pid: libc::pid_t, - - // not actually here, but brings in line with freebsd - pub l_sysid: libc::c_int, + pub const F_RDLCK: libc::c_short = 1; + pub const F_UNLCK: libc::c_short = 2; + pub const F_WRLCK: libc::c_short = 3; + pub const F_SETLK: libc::c_int = 8; + pub const F_SETLKW: libc::c_int = 9; } - pub const F_RDLCK: libc::c_short = 0x0040; - pub const F_UNLCK: libc::c_short = 0x0200; - pub const F_WRLCK: libc::c_short = 0x0400; - pub const F_SETLK: libc::c_int = 0x0080; - pub const F_SETLKW: libc::c_int = 0x0100; - } + #[cfg(target_os = "haiku")] + mod os { + use libc; - #[cfg(any(target_os = "macos", target_os = "ios"))] - mod os { - use libc; + #[repr(C)] + pub struct flock { + pub l_type: libc::c_short, + pub l_whence: libc::c_short, + pub l_start: libc::off_t, + pub l_len: libc::off_t, + pub l_pid: libc::pid_t, - #[repr(C)] - pub struct flock { - pub l_start: libc::off_t, - pub l_len: libc::off_t, - pub l_pid: libc::pid_t, - pub l_type: libc::c_short, - pub l_whence: libc::c_short, - - // not actually here, but brings in line with freebsd - pub l_sysid: libc::c_int, + // not actually here, but brings in line with freebsd + pub l_sysid: libc::c_int, + } + + pub const F_RDLCK: libc::c_short = 0x0040; + pub const F_UNLCK: libc::c_short = 0x0200; + pub const F_WRLCK: libc::c_short = 0x0400; + pub const F_SETLK: libc::c_int = 0x0080; + pub const F_SETLKW: libc::c_int = 0x0100; } - pub const F_RDLCK: libc::c_short = 1; - pub const F_UNLCK: libc::c_short = 2; - pub const F_WRLCK: libc::c_short = 3; - pub const F_SETLK: libc::c_int = 8; - pub const F_SETLKW: libc::c_int = 9; - } + #[cfg(any(target_os = "macos", target_os = "ios"))] + mod os { + use libc; - #[cfg(target_os = "solaris")] - mod os { - use libc; + #[repr(C)] + pub struct flock { + pub l_start: libc::off_t, + pub l_len: libc::off_t, + pub l_pid: libc::pid_t, + pub l_type: libc::c_short, + pub l_whence: libc::c_short, - #[repr(C)] - pub struct flock { - pub l_type: libc::c_short, - pub l_whence: libc::c_short, - pub l_start: libc::off_t, - pub l_len: libc::off_t, - pub l_sysid: libc::c_int, - pub l_pid: libc::pid_t, + // not actually here, but brings in line with freebsd + pub l_sysid: libc::c_int, + } + + pub const F_RDLCK: libc::c_short = 1; + pub const F_UNLCK: libc::c_short = 2; + pub const F_WRLCK: libc::c_short = 3; + pub const F_SETLK: libc::c_int = 8; + pub const F_SETLKW: libc::c_int = 9; } - pub const F_RDLCK: libc::c_short = 1; - pub const F_WRLCK: libc::c_short = 2; - pub const F_UNLCK: libc::c_short = 3; - pub const F_SETLK: libc::c_int = 6; - pub const F_SETLKW: libc::c_int = 7; - } + #[cfg(target_os = "solaris")] + mod os { + use libc; + + #[repr(C)] + pub struct flock { + pub l_type: libc::c_short, + pub l_whence: libc::c_short, + pub l_start: libc::off_t, + pub l_len: libc::off_t, + pub l_sysid: libc::c_int, + pub l_pid: libc::pid_t, + } - #[derive(Debug)] - pub struct Lock { - fd: libc::c_int, - } + pub const F_RDLCK: libc::c_short = 1; + pub const F_WRLCK: libc::c_short = 2; + pub const F_UNLCK: libc::c_short = 3; + pub const F_SETLK: libc::c_int = 6; + pub const F_SETLKW: libc::c_int = 7; + } - impl Lock { - pub fn new(p: &Path, - wait: bool, - create: bool, - exclusive: bool) - -> io::Result { - let os: &OsStr = p.as_ref(); - let buf = CString::new(os.as_bytes()).unwrap(); - let open_flags = if create { - libc::O_RDWR | libc::O_CREAT - } else { - libc::O_RDWR - }; - - let fd = unsafe { - libc::open(buf.as_ptr(), open_flags, - libc::S_IRWXU as libc::c_int) - }; - - if fd < 0 { - return Err(io::Error::last_os_error()); - } + #[derive(Debug)] + pub struct Lock { + fd: libc::c_int, + } - let lock_type = if exclusive { - os::F_WRLCK - } else { - os::F_RDLCK - }; - - let flock = os::flock { - l_start: 0, - l_len: 0, - l_pid: 0, - l_whence: libc::SEEK_SET as libc::c_short, - l_type: lock_type, - l_sysid: 0, - }; - let cmd = if wait { os::F_SETLKW } else { os::F_SETLK }; - let ret = unsafe { - libc::fcntl(fd, cmd, &flock) - }; - if ret == -1 { - let err = io::Error::last_os_error(); - unsafe { libc::close(fd); } - Err(err) - } else { - Ok(Lock { fd: fd }) + impl Lock { + pub fn new(p: &Path, + wait: bool, + create: bool, + exclusive: bool) + -> io::Result { + let os: &OsStr = p.as_ref(); + let buf = CString::new(os.as_bytes()).unwrap(); + let open_flags = if create { + libc::O_RDWR | libc::O_CREAT + } else { + libc::O_RDWR + }; + + let fd = unsafe { + libc::open(buf.as_ptr(), open_flags, + libc::S_IRWXU as libc::c_int) + }; + + if fd < 0 { + return Err(io::Error::last_os_error()); + } + + let lock_type = if exclusive { + os::F_WRLCK + } else { + os::F_RDLCK + }; + + let flock = os::flock { + l_start: 0, + l_len: 0, + l_pid: 0, + l_whence: libc::SEEK_SET as libc::c_short, + l_type: lock_type, + l_sysid: 0, + }; + let cmd = if wait { os::F_SETLKW } else { os::F_SETLK }; + let ret = unsafe { + libc::fcntl(fd, cmd, &flock) + }; + if ret == -1 { + let err = io::Error::last_os_error(); + unsafe { libc::close(fd); } + Err(err) + } else { + Ok(Lock { fd: fd }) + } } } - } - impl Drop for Lock { - fn drop(&mut self) { - let flock = os::flock { - l_start: 0, - l_len: 0, - l_pid: 0, - l_whence: libc::SEEK_SET as libc::c_short, - l_type: os::F_UNLCK, - l_sysid: 0, - }; - unsafe { - libc::fcntl(self.fd, os::F_SETLK, &flock); - libc::close(self.fd); + impl Drop for Lock { + fn drop(&mut self) { + let flock = os::flock { + l_start: 0, + l_len: 0, + l_pid: 0, + l_whence: libc::SEEK_SET as libc::c_short, + l_type: os::F_UNLCK, + l_sysid: 0, + }; + unsafe { + libc::fcntl(self.fd, os::F_SETLK, &flock); + libc::close(self.fd); + } } } - } -} + } else if #[cfg(windows)] { + use std::mem; + use std::os::windows::prelude::*; + use std::os::windows::raw::HANDLE; + use std::fs::{File, OpenOptions}; + use std::os::raw::{c_ulong, c_int}; -#[cfg(windows)] -#[allow(nonstandard_style)] -mod imp { - use std::io; - use std::mem; - use std::os::windows::prelude::*; - use std::os::windows::raw::HANDLE; - use std::path::Path; - use std::fs::{File, OpenOptions}; - use std::os::raw::{c_ulong, c_int}; - - type DWORD = c_ulong; - type BOOL = c_int; - type ULONG_PTR = usize; - - type LPOVERLAPPED = *mut OVERLAPPED; - const LOCKFILE_EXCLUSIVE_LOCK: DWORD = 0x0000_0002; - const LOCKFILE_FAIL_IMMEDIATELY: DWORD = 0x0000_0001; - - const FILE_SHARE_DELETE: DWORD = 0x4; - const FILE_SHARE_READ: DWORD = 0x1; - const FILE_SHARE_WRITE: DWORD = 0x2; - - #[repr(C)] - struct OVERLAPPED { - Internal: ULONG_PTR, - InternalHigh: ULONG_PTR, - Offset: DWORD, - OffsetHigh: DWORD, - hEvent: HANDLE, - } + type DWORD = c_ulong; + type BOOL = c_int; + type ULONG_PTR = usize; - extern "system" { - fn LockFileEx(hFile: HANDLE, - dwFlags: DWORD, - dwReserved: DWORD, - nNumberOfBytesToLockLow: DWORD, - nNumberOfBytesToLockHigh: DWORD, - lpOverlapped: LPOVERLAPPED) -> BOOL; - } + type LPOVERLAPPED = *mut OVERLAPPED; + const LOCKFILE_EXCLUSIVE_LOCK: DWORD = 0x0000_0002; + const LOCKFILE_FAIL_IMMEDIATELY: DWORD = 0x0000_0001; - #[derive(Debug)] - pub struct Lock { - _file: File, - } + const FILE_SHARE_DELETE: DWORD = 0x4; + const FILE_SHARE_READ: DWORD = 0x1; + const FILE_SHARE_WRITE: DWORD = 0x2; - impl Lock { - pub fn new(p: &Path, - wait: bool, - create: bool, - exclusive: bool) - -> io::Result { - assert!(p.parent().unwrap().exists(), - "Parent directory of lock-file must exist: {}", - p.display()); - - let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE; - - let mut open_options = OpenOptions::new(); - open_options.read(true) - .share_mode(share_mode); - - if create { - open_options.create(true) - .write(true); - } + #[repr(C)] + struct OVERLAPPED { + Internal: ULONG_PTR, + InternalHigh: ULONG_PTR, + Offset: DWORD, + OffsetHigh: DWORD, + hEvent: HANDLE, + } - debug!("Attempting to open lock file `{}`", p.display()); - let file = match open_options.open(p) { - Ok(file) => { - debug!("Lock file opened successfully"); - file - } - Err(err) => { - debug!("Error opening lock file: {}", err); - return Err(err) - } - }; + extern "system" { + fn LockFileEx(hFile: HANDLE, + dwFlags: DWORD, + dwReserved: DWORD, + nNumberOfBytesToLockLow: DWORD, + nNumberOfBytesToLockHigh: DWORD, + lpOverlapped: LPOVERLAPPED) -> BOOL; + } - let ret = unsafe { - let mut overlapped: OVERLAPPED = mem::zeroed(); + #[derive(Debug)] + pub struct Lock { + _file: File, + } - let mut dwFlags = 0; - if !wait { - dwFlags |= LOCKFILE_FAIL_IMMEDIATELY; + impl Lock { + pub fn new(p: &Path, + wait: bool, + create: bool, + exclusive: bool) + -> io::Result { + assert!(p.parent().unwrap().exists(), + "Parent directory of lock-file must exist: {}", + p.display()); + + let share_mode = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE; + + let mut open_options = OpenOptions::new(); + open_options.read(true) + .share_mode(share_mode); + + if create { + open_options.create(true) + .write(true); } - if exclusive { - dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; + debug!("Attempting to open lock file `{}`", p.display()); + let file = match open_options.open(p) { + Ok(file) => { + debug!("Lock file opened successfully"); + file + } + Err(err) => { + debug!("Error opening lock file: {}", err); + return Err(err) + } + }; + + let ret = unsafe { + let mut overlapped: OVERLAPPED = mem::zeroed(); + + let mut dwFlags = 0; + if !wait { + dwFlags |= LOCKFILE_FAIL_IMMEDIATELY; + } + + if exclusive { + dwFlags |= LOCKFILE_EXCLUSIVE_LOCK; + } + + debug!("Attempting to acquire lock on lock file `{}`", + p.display()); + LockFileEx(file.as_raw_handle(), + dwFlags, + 0, + 0xFFFF_FFFF, + 0xFFFF_FFFF, + &mut overlapped) + }; + if ret == 0 { + let err = io::Error::last_os_error(); + debug!("Failed acquiring file lock: {}", err); + Err(err) + } else { + debug!("Successfully acquired lock."); + Ok(Lock { _file: file }) } + } + } - debug!("Attempting to acquire lock on lock file `{}`", - p.display()); - LockFileEx(file.as_raw_handle(), - dwFlags, - 0, - 0xFFFF_FFFF, - 0xFFFF_FFFF, - &mut overlapped) - }; - if ret == 0 { - let err = io::Error::last_os_error(); - debug!("Failed acquiring file lock: {}", err); - Err(err) - } else { - debug!("Successfully acquired lock."); - Ok(Lock { _file: file }) + // Note that we don't need a Drop impl on the Windows: The file is unlocked + // automatically when it's closed. + } else { + #[derive(Debug)] + pub struct Lock(()); + + impl Lock { + pub fn new(_p: &Path, _wait: bool, _create: bool, _exclusive: bool) + -> io::Result + { + let msg = "file locks not supported on this platform"; + Err(io::Error::new(io::ErrorKind::Other, msg)) } } } - - // Note that we don't need a Drop impl on the Windows: The file is unlocked - // automatically when it's closed. } -impl imp::Lock { +impl Lock { pub fn panicking_new(p: &Path, wait: bool, create: bool, diff --git a/src/librustc_errors/lock.rs b/src/librustc_errors/lock.rs index e5baf93b00064..ff323073c6235 100644 --- a/src/librustc_errors/lock.rs +++ b/src/librustc_errors/lock.rs @@ -109,7 +109,7 @@ pub fn acquire_global_lock(name: &str) -> Box { } } -#[cfg(unix)] +#[cfg(not(windows))] pub fn acquire_global_lock(_name: &str) -> Box { Box::new(()) }