1
Fork 0

Rollup merge of #54024 - alexcrichton:compile-to-wasm, r=petrochenkov

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!
This commit is contained in:
kennytm 2018-09-14 14:50:10 +08:00 committed by GitHub
commit 33bc6c3dae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 329 additions and 323 deletions

View file

@ -15,345 +15,351 @@
//! librustdoc, it is not production quality at all. //! librustdoc, it is not production quality at all.
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
#![allow(nonstandard_style)]
use std::io;
use std::path::Path; use std::path::Path;
pub use self::imp::Lock; cfg_if! {
if #[cfg(unix)] {
#[cfg(unix)] use std::ffi::{CString, OsStr};
mod imp { use std::os::unix::prelude::*;
use std::ffi::{CString, OsStr};
use std::os::unix::prelude::*;
use std::path::Path;
use std::io;
use libc;
#[cfg(any(target_os = "linux", target_os = "android"))]
mod os {
use libc; use libc;
#[repr(C)] #[cfg(any(target_os = "linux", target_os = "android"))]
pub struct flock { mod os {
pub l_type: libc::c_short, use libc;
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 #[repr(C)]
pub l_sysid: libc::c_int, 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,
pub const F_RDLCK: libc::c_short = 0; // not actually here, but brings in line with freebsd
pub const F_WRLCK: libc::c_short = 1; pub l_sysid: libc::c_int,
pub const F_UNLCK: libc::c_short = 2;
pub const F_SETLK: libc::c_int = 6;
pub const F_SETLKW: libc::c_int = 7;
}
#[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,
}
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;
#[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 = 8;
pub const F_SETLKW: libc::c_int = 9;
}
#[cfg(target_os = "haiku")]
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,
// 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;
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
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,
}
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 = "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,
}
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;
}
#[derive(Debug)]
pub struct Lock {
fd: libc::c_int,
}
impl Lock {
pub fn new(p: &Path,
wait: bool,
create: bool,
exclusive: bool)
-> io::Result<Lock> {
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 { pub const F_RDLCK: libc::c_short = 0;
os::F_WRLCK pub const F_WRLCK: libc::c_short = 1;
} else { pub const F_UNLCK: libc::c_short = 2;
os::F_RDLCK pub const F_SETLK: libc::c_int = 6;
}; pub const F_SETLKW: libc::c_int = 7;
}
let flock = os::flock { #[cfg(target_os = "freebsd")]
l_start: 0, mod os {
l_len: 0, use libc;
l_pid: 0,
l_whence: libc::SEEK_SET as libc::c_short, #[repr(C)]
l_type: lock_type, pub struct flock {
l_sysid: 0, pub l_start: libc::off_t,
}; pub l_len: libc::off_t,
let cmd = if wait { os::F_SETLKW } else { os::F_SETLK }; pub l_pid: libc::pid_t,
let ret = unsafe { pub l_type: libc::c_short,
libc::fcntl(fd, cmd, &flock) pub l_whence: libc::c_short,
}; pub l_sysid: libc::c_int,
if ret == -1 { }
let err = io::Error::last_os_error();
unsafe { libc::close(fd); } pub const F_RDLCK: libc::c_short = 1;
Err(err) pub const F_UNLCK: libc::c_short = 2;
} else { pub const F_WRLCK: libc::c_short = 3;
Ok(Lock { fd: fd }) 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;
#[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 = 8;
pub const F_SETLKW: libc::c_int = 9;
}
#[cfg(target_os = "haiku")]
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,
// 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;
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
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,
}
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 = "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,
}
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;
}
#[derive(Debug)]
pub struct Lock {
fd: libc::c_int,
}
impl Lock {
pub fn new(p: &Path,
wait: bool,
create: bool,
exclusive: bool)
-> io::Result<Lock> {
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 { impl Drop for Lock {
fn drop(&mut self) { fn drop(&mut self) {
let flock = os::flock { let flock = os::flock {
l_start: 0, l_start: 0,
l_len: 0, l_len: 0,
l_pid: 0, l_pid: 0,
l_whence: libc::SEEK_SET as libc::c_short, l_whence: libc::SEEK_SET as libc::c_short,
l_type: os::F_UNLCK, l_type: os::F_UNLCK,
l_sysid: 0, l_sysid: 0,
}; };
unsafe { unsafe {
libc::fcntl(self.fd, os::F_SETLK, &flock); libc::fcntl(self.fd, os::F_SETLK, &flock);
libc::close(self.fd); 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};
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,
}
extern "system" {
fn LockFileEx(hFile: HANDLE,
dwFlags: DWORD,
dwReserved: DWORD,
nNumberOfBytesToLockLow: DWORD,
nNumberOfBytesToLockHigh: DWORD,
lpOverlapped: LPOVERLAPPED) -> BOOL;
}
#[derive(Debug)]
pub struct Lock {
_file: File,
}
impl Lock {
pub fn new(p: &Path,
wait: bool,
create: bool,
exclusive: bool)
-> io::Result<Lock> {
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);
}
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 })
}
}
}
// 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<Lock>
{
let msg = "file locks not supported on this platform";
Err(io::Error::new(io::ErrorKind::Other, msg))
} }
} }
} }
} }
#[cfg(windows)] impl Lock {
#[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,
}
extern "system" {
fn LockFileEx(hFile: HANDLE,
dwFlags: DWORD,
dwReserved: DWORD,
nNumberOfBytesToLockLow: DWORD,
nNumberOfBytesToLockHigh: DWORD,
lpOverlapped: LPOVERLAPPED) -> BOOL;
}
#[derive(Debug)]
pub struct Lock {
_file: File,
}
impl Lock {
pub fn new(p: &Path,
wait: bool,
create: bool,
exclusive: bool)
-> io::Result<Lock> {
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);
}
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 })
}
}
}
// Note that we don't need a Drop impl on the Windows: The file is unlocked
// automatically when it's closed.
}
impl imp::Lock {
pub fn panicking_new(p: &Path, pub fn panicking_new(p: &Path,
wait: bool, wait: bool,
create: bool, create: bool,

View file

@ -109,7 +109,7 @@ pub fn acquire_global_lock(name: &str) -> Box<dyn Any> {
} }
} }
#[cfg(unix)] #[cfg(not(windows))]
pub fn acquire_global_lock(_name: &str) -> Box<dyn Any> { pub fn acquire_global_lock(_name: &str) -> Box<dyn Any> {
Box::new(()) Box::new(())
} }