diff --git a/Cargo.lock b/Cargo.lock index 3f8bf0ac8e890..7beade3888971 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1586,8 +1586,7 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" [[package]] name = "libc" version = "0.2.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10" +source = "git+https://github.com/leo60228/libc.git?branch=bindgen-horizon#9f1d51f1276ac6967065b0fd7c3d814ec86dd391" dependencies = [ "rustc-std-workspace-core", ] diff --git a/Cargo.toml b/Cargo.toml index 1936e35aa4c5d..4abe20eb30e09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -98,5 +98,7 @@ rustc-std-workspace-std = { path = 'library/rustc-std-workspace-std' } # source code for this crate. backtrace = { path = "library/backtrace" } +libc = { git = 'https://github.com/leo60228/libc.git', branch = 'bindgen-horizon' } + [patch."https://github.com/rust-lang/rust-clippy"] clippy_lints = { path = "src/tools/clippy/clippy_lints" } diff --git a/library/std/build.rs b/library/std/build.rs index 83073cc77dd1a..07653e6cd3b6e 100644 --- a/library/std/build.rs +++ b/library/std/build.rs @@ -71,6 +71,7 @@ fn main() { || target.contains("vxworks") || target.contains("wasm32") || target.contains("asmjs") + || target.contains("libnx") { // These platforms don't have any special requirements. } else { diff --git a/library/std/src/os/libnx/fs.rs b/library/std/src/os/libnx/fs.rs new file mode 100644 index 0000000000000..bd2b6bb6050c9 --- /dev/null +++ b/library/std/src/os/libnx/fs.rs @@ -0,0 +1,312 @@ +#![stable(feature = "metadata_ext", since = "1.1.0")] + +use crate::fs::Metadata; +use crate::sys_common::AsInner; + +#[allow(deprecated)] +use crate::os::libnx::raw; + +/// OS-specific extensions to [`fs::Metadata`]. +/// +/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html +#[stable(feature = "metadata_ext", since = "1.1.0")] +pub trait MetadataExt { + /// Gain a reference to the underlying `stat` structure which contains + /// the raw information returned by the OS. + /// + /// The contents of the returned [`stat`] are **not** consistent across + /// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the + /// cross-Unix abstractions contained within the raw stat. + /// + /// [`stat`]: ../../../../std/os/linux/raw/struct.stat.html + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// let stat = meta.as_raw_stat(); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext", since = "1.1.0")] + #[rustc_deprecated(since = "1.8.0", reason = "other methods of this trait are now preferred")] + #[allow(deprecated)] + fn as_raw_stat(&self) -> &raw::stat; + + /// Returns the device ID on which this file resides. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_dev()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_dev(&self) -> u64; + /// Returns the inode number. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ino()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ino(&self) -> u64; + /// Returns the file type and mode. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mode()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mode(&self) -> u32; + /// Returns the number of hard links to file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_nlink()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_nlink(&self) -> u64; + /// Returns the user ID of the file owner. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_uid()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_uid(&self) -> u32; + /// Returns the group ID of the file owner. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_gid()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_gid(&self) -> u32; + /// Returns the device ID that this file represents. Only relevant for special file. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_rdev()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_rdev(&self) -> u64; + /// Returns the size of the file (if it is a regular file or a symbolic link) in bytes. + /// + /// The size of a symbolic link is the length of the pathname it contains, + /// without a terminating null byte. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_size()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_size(&self) -> u64; + /// Returns the last access time of the file, in seconds since Unix Epoch. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_atime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_atime(&self) -> i64; + /// Returns the last modification time of the file, in seconds since Unix Epoch. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_mtime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_mtime(&self) -> i64; + /// Returns the last status change time of the file, in seconds since Unix Epoch. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_ctime()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_ctime(&self) -> i64; + /// Returns the "preferred" blocksize for efficient filesystem I/O. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blksize()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blksize(&self) -> u64; + /// Returns the number of blocks allocated to the file, 512-byte units. + /// + /// # Examples + /// + /// ```no_run + /// use std::fs; + /// use std::io; + /// use std::os::linux::fs::MetadataExt; + /// + /// fn main() -> io::Result<()> { + /// let meta = fs::metadata("some_file")?; + /// println!("{}", meta.st_blocks()); + /// Ok(()) + /// } + /// ``` + #[stable(feature = "metadata_ext2", since = "1.8.0")] + fn st_blocks(&self) -> u64; +} + +#[stable(feature = "metadata_ext", since = "1.1.0")] +impl MetadataExt for Metadata { + #[allow(deprecated)] + fn as_raw_stat(&self) -> &raw::stat { + unsafe { &*(self.as_inner().as_inner() as *const libc::stat as *const raw::stat) } + } + fn st_dev(&self) -> u64 { + self.as_inner().as_inner().st_dev as u64 + } + fn st_ino(&self) -> u64 { + self.as_inner().as_inner().st_ino as u64 + } + fn st_mode(&self) -> u32 { + self.as_inner().as_inner().st_mode as u32 + } + fn st_nlink(&self) -> u64 { + self.as_inner().as_inner().st_nlink as u64 + } + fn st_uid(&self) -> u32 { + self.as_inner().as_inner().st_uid as u32 + } + fn st_gid(&self) -> u32 { + self.as_inner().as_inner().st_gid as u32 + } + fn st_rdev(&self) -> u64 { + self.as_inner().as_inner().st_rdev as u64 + } + fn st_size(&self) -> u64 { + self.as_inner().as_inner().st_size as u64 + } + fn st_atime(&self) -> i64 { + self.as_inner().as_inner().st_atime as i64 + } + fn st_mtime(&self) -> i64 { + self.as_inner().as_inner().st_mtime as i64 + } + fn st_ctime(&self) -> i64 { + self.as_inner().as_inner().st_ctime as i64 + } + fn st_blksize(&self) -> u64 { + self.as_inner().as_inner().st_blksize as u64 + } + fn st_blocks(&self) -> u64 { + self.as_inner().as_inner().st_blocks as u64 + } +} diff --git a/library/std/src/os/libnx/mod.rs b/library/std/src/os/libnx/mod.rs new file mode 100644 index 0000000000000..e75580a3a3f3e --- /dev/null +++ b/library/std/src/os/libnx/mod.rs @@ -0,0 +1,19 @@ +//! libnx-specific definitions + +#![stable(feature = "raw_ext", since = "1.1.0")] + +pub mod fs; +pub mod raw; + +extern "C" { + fn romfsMountSelf(name: *const u8) -> u32; +} + +/// This is necessary for getting debug info (needed by backtraces). +pub(crate) fn initialize_romfs() { + unsafe { + // This will return an error if there isn't a romfs, which can be safely ignored. + // SAFETY: We're passing a valid C string to romfsMountSelf. + let _ = romfsMountSelf(b"romfs\0" as *const _); + } +} diff --git a/library/std/src/os/libnx/raw.rs b/library/std/src/os/libnx/raw.rs new file mode 100644 index 0000000000000..0caec97bb7b90 --- /dev/null +++ b/library/std/src/os/libnx/raw.rs @@ -0,0 +1,363 @@ +//! Linux-specific raw type definitions + +#![stable(feature = "raw_ext", since = "1.1.0")] +#![rustc_deprecated( + since = "1.8.0", + reason = "these type aliases are no longer supported by \ + the standard library, the `libc` crate on \ + crates.io should be used instead for the correct \ + definitions" +)] +#![allow(deprecated)] +#![allow(missing_debug_implementations)] + +use crate::os::raw::c_ulong; + +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type dev_t = u64; +#[stable(feature = "raw_ext", since = "1.1.0")] +pub type mode_t = u32; + +#[stable(feature = "pthread_t", since = "1.8.0")] +pub type pthread_t = c_ulong; + +#[doc(inline)] +#[stable(feature = "raw_ext", since = "1.1.0")] +pub use self::arch::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t}; + +#[cfg(any( + target_arch = "x86", + target_arch = "le32", + target_arch = "powerpc", + target_arch = "arm", + target_arch = "asmjs", + target_arch = "wasm32" +))] +mod arch { + use crate::os::raw::{c_long, c_short, c_uint}; + + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type blkcnt_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type blksize_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type ino_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type nlink_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type off_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type time_t = i64; + + #[repr(C)] + #[derive(Clone)] + #[stable(feature = "raw_ext", since = "1.1.0")] + pub struct stat { + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_dev: u64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub __pad1: c_short, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub __st_ino: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mode: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_nlink: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_uid: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_gid: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_rdev: u64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub __pad2: c_uint, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_size: i64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blksize: i32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blocks: i64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime: i32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime: i32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime: i32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ino: u64, + } +} + +#[cfg(target_arch = "mips")] +mod arch { + use crate::os::raw::{c_long, c_ulong}; + + #[cfg(target_env = "musl")] + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type blkcnt_t = i64; + #[cfg(not(target_env = "musl"))] + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type blkcnt_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type blksize_t = u64; + #[cfg(target_env = "musl")] + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type ino_t = u64; + #[cfg(not(target_env = "musl"))] + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type ino_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type nlink_t = u64; + #[cfg(target_env = "musl")] + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type off_t = u64; + #[cfg(not(target_env = "musl"))] + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type off_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type time_t = i64; + + #[repr(C)] + #[derive(Clone)] + #[stable(feature = "raw_ext", since = "1.1.0")] + pub struct stat { + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_dev: c_ulong, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_pad1: [c_long; 3], + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ino: u64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mode: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_nlink: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_uid: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_gid: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_rdev: c_ulong, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_pad2: [c_long; 2], + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_size: i64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime: i32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime: i32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime: i32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blksize: i32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blocks: i64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_pad5: [c_long; 14], + } +} + +#[cfg(target_arch = "hexagon")] +mod arch { + use crate::os::raw::{c_int, c_long, c_longlong, culonglong}; + + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type blkcnt_t = c_longlong; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type blksize_t = c_long; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type ino_t = c_ulonglong; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type nlink_t = c_uint; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type off_t = c_longlong; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type time_t = c_long; + + #[repr(C)] + #[derive(Clone)] + #[stable(feature = "raw_ext", since = "1.1.0")] + pub struct stat { + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_dev: ::dev_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ino: ::c_ulonglong, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mode: ::c_uint, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_nlink: ::c_uint, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_uid: ::c_uint, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_gid: ::c_uint, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_rdev: ::c_ulonglong, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub __pad1: ::c_ulong, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_size: ::c_longlong, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blksize: ::blksize_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub __pad2: ::c_int, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blocks: ::blkcnt_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime: ::time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime_nsec: ::c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime: ::time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime_nsec: ::c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime: ::time_t, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime_nsec: ::c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub __pad3: [::c_int; 2], + } +} + +#[cfg(any( + target_arch = "mips64", + target_arch = "s390x", + target_arch = "sparc64", + target_arch = "riscv64" +))] +mod arch { + pub use libc::{blkcnt_t, blksize_t, ino_t, nlink_t, off_t, stat, time_t}; +} + +#[cfg(target_arch = "aarch64")] +mod arch { + use crate::os::raw::{c_int, c_long}; + + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type blkcnt_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type blksize_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type ino_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type nlink_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type off_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type time_t = i64; + + #[repr(C)] + #[derive(Clone)] + #[stable(feature = "raw_ext", since = "1.1.0")] + pub struct stat { + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_dev: u64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ino: u64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mode: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_nlink: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_uid: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_gid: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_rdev: u64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub __pad1: u64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_size: i64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blksize: i32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub __pad2: c_int, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blocks: i64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime: i64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime: i64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime: i64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub __unused: [c_int; 2], + } +} + +#[cfg(any(target_arch = "x86_64", target_arch = "powerpc64"))] +mod arch { + use crate::os::raw::{c_int, c_long}; + + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type blkcnt_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type blksize_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type ino_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type nlink_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type off_t = u64; + #[stable(feature = "raw_ext", since = "1.1.0")] + pub type time_t = i64; + + #[repr(C)] + #[derive(Clone)] + #[stable(feature = "raw_ext", since = "1.1.0")] + pub struct stat { + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_dev: u64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ino: u64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_nlink: u64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mode: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_uid: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_gid: u32, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub __pad0: c_int, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_rdev: u64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_size: i64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blksize: i64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_blocks: i64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime: i64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_atime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime: i64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_mtime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime: i64, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub st_ctime_nsec: c_long, + #[stable(feature = "raw_ext", since = "1.1.0")] + pub __unused: [c_long; 3], + } +} diff --git a/library/std/src/os/mod.rs b/library/std/src/os/mod.rs index fd6ee088e961c..7fdcc984d0e35 100644 --- a/library/std/src/os/mod.rs +++ b/library/std/src/os/mod.rs @@ -56,6 +56,8 @@ pub mod haiku; pub mod illumos; #[cfg(target_os = "ios")] pub mod ios; +#[cfg(target_env = "libnx")] +pub mod libnx; #[cfg(target_os = "macos")] pub mod macos; #[cfg(target_os = "netbsd")] diff --git a/library/std/src/os/raw/mod.rs b/library/std/src/os/raw/mod.rs index 47daf0cce1b37..ad7accafbece2 100644 --- a/library/std/src/os/raw/mod.rs +++ b/library/std/src/os/raw/mod.rs @@ -47,7 +47,8 @@ target_arch = "powerpc" ) ), - all(target_os = "fuchsia", target_arch = "aarch64") + all(target_os = "fuchsia", target_arch = "aarch64"), + target_env = "libnx" ))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = u8; @@ -90,7 +91,8 @@ pub type c_char = u8; target_arch = "powerpc" ) ), - all(target_os = "fuchsia", target_arch = "aarch64") + all(target_os = "fuchsia", target_arch = "aarch64"), + target_env = "libnx" )))] #[stable(feature = "raw_os", since = "1.1.0")] pub type c_char = i8; diff --git a/library/std/src/sys/unix/alloc.rs b/library/std/src/sys/unix/alloc.rs index 8e193935460eb..69163364cf87b 100644 --- a/library/std/src/sys/unix/alloc.rs +++ b/library/std/src/sys/unix/alloc.rs @@ -84,7 +84,8 @@ unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { target_os = "android", target_os = "illumos", target_os = "redox", - target_os = "solaris" + target_os = "solaris", + target_env = "libnx" )))] #[inline] unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { @@ -95,3 +96,9 @@ unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { let ret = libc::posix_memalign(&mut out, align, layout.size()); if ret != 0 { ptr::null_mut() } else { out as *mut u8 } } + +#[cfg(target_env = "libnx")] +#[inline] +unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { + libc::aligned_alloc(layout.align(), layout.size()) as *mut u8 +} diff --git a/library/std/src/sys/unix/args.rs b/library/std/src/sys/unix/args.rs index 9bc44a59482a0..bf37ec418a3b7 100644 --- a/library/std/src/sys/unix/args.rs +++ b/library/std/src/sys/unix/args.rs @@ -70,7 +70,8 @@ impl DoubleEndedIterator for Args { target_os = "haiku", target_os = "l4re", target_os = "fuchsia", - target_os = "redox" + target_os = "redox", + target_env = "libnx" ))] mod imp { use super::Args; diff --git a/library/std/src/sys/unix/env.rs b/library/std/src/sys/unix/env.rs index 7f5e9b04dba4b..f3e50b153acb1 100644 --- a/library/std/src/sys/unix/env.rs +++ b/library/std/src/sys/unix/env.rs @@ -173,3 +173,14 @@ pub mod os { pub const EXE_SUFFIX: &str = ""; pub const EXE_EXTENSION: &str = ""; } + +#[cfg(target_env = "libnx")] +pub mod os { + pub const FAMILY: &str = "unix"; + pub const OS: &str = "switch"; + pub const DLL_PREFIX: &str = "lib"; + pub const DLL_SUFFIX: &str = ".so"; + pub const DLL_EXTENSION: &str = "so"; + pub const EXE_SUFFIX: &str = ".nro"; + pub const EXE_EXTENSION: &str = "nro"; +} diff --git a/library/std/src/sys/unix/ext/fs.rs b/library/std/src/sys/unix/ext/fs.rs index f174a59b49a6b..dffb9e886e0e5 100644 --- a/library/std/src/sys/unix/ext/fs.rs +++ b/library/std/src/sys/unix/ext/fs.rs @@ -213,6 +213,7 @@ pub trait FileExt { } #[stable(feature = "file_offset", since = "1.15.0")] +#[cfg(not(target_env = "libnx"))] impl FileExt for fs::File { fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result { self.as_inner().read_at(buf, offset) @@ -222,6 +223,17 @@ impl FileExt for fs::File { } } +#[stable(feature = "file_offset", since = "1.15.0")] +#[cfg(target_env = "libnx")] +impl FileExt for fs::File { + fn read_at(&self, _buf: &mut [u8], _offset: u64) -> io::Result { + unimplemented!() + } + fn write_at(&self, _buf: &[u8], _offset: u64) -> io::Result { + unimplemented!() + } +} + /// Unix-specific extensions to [`fs::Permissions`]. /// /// [`fs::Permissions`]: ../../../../std/fs/struct.Permissions.html @@ -691,21 +703,36 @@ impl MetadataExt for fs::Metadata { fn atime(&self) -> i64 { self.st_atime() } + #[cfg(not(target_env = "libnx"))] fn atime_nsec(&self) -> i64 { self.st_atime_nsec() } + #[cfg(target_env = "libnx")] + fn atime_nsec(&self) -> i64 { + 0 + } fn mtime(&self) -> i64 { self.st_mtime() } + #[cfg(not(target_env = "libnx"))] fn mtime_nsec(&self) -> i64 { self.st_mtime_nsec() } + #[cfg(target_env = "libnx")] + fn mtime_nsec(&self) -> i64 { + 0 + } fn ctime(&self) -> i64 { self.st_ctime() } + #[cfg(not(target_env = "libnx"))] fn ctime_nsec(&self) -> i64 { self.st_ctime_nsec() } + #[cfg(target_env = "libnx")] + fn ctime_nsec(&self) -> i64 { + 0 + } fn blksize(&self) -> u64 { self.st_blksize() } diff --git a/library/std/src/sys/unix/fd.rs b/library/std/src/sys/unix/fd.rs index ba169b251b0bc..cf3992211a764 100644 --- a/library/std/src/sys/unix/fd.rs +++ b/library/std/src/sys/unix/fd.rs @@ -1,3 +1,4 @@ +#![cfg_attr(target_env = "libnx", allow(unused_variables, dead_code))] #![unstable(reason = "not public", issue = "none", feature = "fd")] use crate::cmp; @@ -72,6 +73,7 @@ impl FileDesc { Ok(ret as usize) } + #[cfg(not(target_env = "libnx"))] pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { let ret = cvt(unsafe { libc::readv( @@ -83,9 +85,14 @@ impl FileDesc { Ok(ret as usize) } + #[cfg(target_env = "libnx")] + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + io::default_read_vectored(|x| self.read(x), bufs) + } + #[inline] pub fn is_read_vectored(&self) -> bool { - true + !cfg!(target_env = "libnx") } pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { @@ -93,6 +100,7 @@ impl FileDesc { (&mut me).read_to_end(buf) } + #[cfg(not(target_env = "libnx"))] pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result { #[cfg(target_os = "android")] use super::android::cvt_pread64; @@ -129,6 +137,7 @@ impl FileDesc { Ok(ret as usize) } + #[cfg(not(target_env = "libnx"))] pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result { let ret = cvt(unsafe { libc::writev( @@ -140,11 +149,17 @@ impl FileDesc { Ok(ret as usize) } + #[cfg(target_env = "libnx")] + pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result { + io::default_write_vectored(|x| self.write(x), bufs) + } + #[inline] pub fn is_write_vectored(&self) -> bool { - true + !cfg!(target_env = "libnx") } + #[cfg(not(target_env = "libnx"))] pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result { #[cfg(target_os = "android")] use super::android::cvt_pwrite64; @@ -180,7 +195,7 @@ impl FileDesc { } #[cfg(not(any( - target_env = "newlib", + target_env = "libnx", target_os = "solaris", target_os = "illumos", target_os = "emscripten", @@ -197,7 +212,7 @@ impl FileDesc { } } #[cfg(any( - target_env = "newlib", + target_env = "libnx", target_os = "solaris", target_os = "illumos", target_os = "emscripten", diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs index acb18e6d064e6..1b030760bf2ec 100644 --- a/library/std/src/sys/unix/fs.rs +++ b/library/std/src/sys/unix/fs.rs @@ -155,12 +155,14 @@ cfg_has_statx! {{ stat.st_blksize = buf.stx_blksize as libc::blksize_t; stat.st_blocks = buf.stx_blocks as libc::blkcnt64_t; stat.st_atime = buf.stx_atime.tv_sec as libc::time_t; - // `i64` on gnu-x86_64-x32, `c_ulong` otherwise. - stat.st_atime_nsec = buf.stx_atime.tv_nsec as _; stat.st_mtime = buf.stx_mtime.tv_sec as libc::time_t; - stat.st_mtime_nsec = buf.stx_mtime.tv_nsec as _; stat.st_ctime = buf.stx_ctime.tv_sec as libc::time_t; - stat.st_ctime_nsec = buf.stx_ctime.tv_nsec as _; + // `i64` on gnu-x86_64-x32, `c_ulong` otherwise. + #[cfg(not(target_env = "libnx"))] { + stat.st_atime_nsec = buf.stx_atime.tv_nsec as _; + stat.st_mtime_nsec = buf.stx_mtime.tv_nsec as _; + stat.st_ctime_nsec = buf.stx_ctime.tv_nsec as _; + } let extra = StatxExtraFields { stx_mask: buf.stx_mask, @@ -295,6 +297,9 @@ impl FileAttr { pub fn modified(&self) -> io::Result { Ok(SystemTime::from(libc::timespec { tv_sec: self.stat.st_mtime as libc::time_t, + #[cfg(target_env = "libnx")] + tv_nsec: 0, + #[cfg(not(target_env = "libnx"))] tv_nsec: self.stat.st_mtime_nsec as _, })) } @@ -302,6 +307,9 @@ impl FileAttr { pub fn accessed(&self) -> io::Result { Ok(SystemTime::from(libc::timespec { tv_sec: self.stat.st_atime as libc::time_t, + #[cfg(target_env = "libnx")] + tv_nsec: 0, + #[cfg(not(target_env = "libnx"))] tv_nsec: self.stat.st_atime_nsec as _, })) } @@ -560,7 +568,8 @@ impl DirEntry { target_os = "haiku", target_os = "l4re", target_os = "fuchsia", - target_os = "redox" + target_os = "redox", + target_env = "libnx" ))] pub fn ino(&self) -> u64 { self.entry.d_ino as u64 @@ -598,7 +607,8 @@ impl DirEntry { target_os = "linux", target_os = "emscripten", target_os = "l4re", - target_os = "haiku" + target_os = "haiku", + target_env = "libnx" ))] fn name_bytes(&self) -> &[u8] { unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes() } @@ -788,6 +798,7 @@ impl File { self.0.is_read_vectored() } + #[cfg(not(target_env = "libnx"))] pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result { self.0.read_at(buf, offset) } @@ -805,6 +816,7 @@ impl File { self.0.is_write_vectored() } + #[cfg(not(target_env = "libnx"))] pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result { self.0.write_at(buf, offset) } @@ -974,6 +986,7 @@ pub fn rmdir(p: &Path) -> io::Result<()> { Ok(()) } +#[cfg(not(target_os = "switch"))] pub fn readlink(p: &Path) -> io::Result { let c_path = cstr(p)?; let p = c_path.as_ptr(); @@ -1001,6 +1014,12 @@ pub fn readlink(p: &Path) -> io::Result { } } +#[cfg(target_os = "switch")] +pub fn readlink(p: &Path) -> io::Result { + Ok(p.to_path_buf()) // switch doesn't have symlinks +} + +#[cfg(not(target_os = "switch"))] pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { let src = cstr(src)?; let dst = cstr(dst)?; @@ -1008,6 +1027,11 @@ pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> { Ok(()) } +#[cfg(target_os = "switch")] +pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> { + Err(io::Error::new(io::ErrorKind::Other, "not supported")) // switch doesn't have symlinks +} + pub fn link(src: &Path, dst: &Path) -> io::Result<()> { let src = cstr(src)?; let dst = cstr(dst)?; @@ -1053,6 +1077,7 @@ pub fn lstat(p: &Path) -> io::Result { Ok(FileAttr::from_stat64(stat)) } +#[cfg(not(target_os = "switch"))] pub fn canonicalize(p: &Path) -> io::Result { let path = CString::new(p.as_os_str().as_bytes())?; let buf; @@ -1067,6 +1092,14 @@ pub fn canonicalize(p: &Path) -> io::Result { Ok(PathBuf::from(OsString::from_vec(buf))) } +#[cfg(target_os = "switch")] +pub fn canonicalize(p: &Path) -> io::Result { + // switch has no symlinks or realpath + let mut cwd = crate::env::current_dir()?; + cwd.push(p); + Ok(cwd) +} + fn open_from(from: &Path) -> io::Result<(crate::fs::File, crate::fs::Metadata)> { use crate::fs::File; diff --git a/library/std/src/sys/unix/mod.rs b/library/std/src/sys/unix/mod.rs index eddf00d3979f5..465ac1f8065d8 100644 --- a/library/std/src/sys/unix/mod.rs +++ b/library/std/src/sys/unix/mod.rs @@ -21,6 +21,8 @@ pub use crate::os::haiku as platform; pub use crate::os::illumos as platform; #[cfg(all(not(doc), target_os = "ios"))] pub use crate::os::ios as platform; +#[cfg(all(not(doc), target_env = "libnx"))] +pub use crate::os::libnx as platform; #[cfg(all(not(doc), target_os = "l4re"))] pub use crate::os::linux as platform; #[cfg(all(not(doc), target_os = "macos"))] @@ -75,6 +77,10 @@ pub use crate::sys_common::os_str_bytes as os_str; #[cfg(not(test))] pub fn init() { + // Load romfs (which contains debug info) on libnx + #[cfg(target_env = "libnx")] + platform::initialize_romfs(); + // By default, some platforms will send a *signal* when an EPIPE error // would otherwise be delivered. This runtime doesn't install a SIGPIPE // handler, causing it to kill the program, which isn't exactly what we diff --git a/library/std/src/sys/unix/net.rs b/library/std/src/sys/unix/net.rs index 011325fddc5b9..6952f11e5b34f 100644 --- a/library/std/src/sys/unix/net.rs +++ b/library/std/src/sys/unix/net.rs @@ -1,3 +1,5 @@ +#![cfg_attr(target_os = "switch", allow(unused_variables, dead_code))] + use crate::cmp; use crate::ffi::CStr; use crate::io::{self, IoSlice, IoSliceMut}; @@ -305,14 +307,27 @@ impl Socket { } pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { - setsockopt(self, libc::IPPROTO_TCP, libc::TCP_NODELAY, nodelay as c_int) + #[cfg(not(target_os = "switch"))] + { + setsockopt(self, libc::IPPROTO_TCP, libc::TCP_NODELAY, nodelay as c_int) + } + #[cfg(target_os = "switch")] + { + Ok(()) + } } + #[cfg(not(target_os = "switch"))] pub fn nodelay(&self) -> io::Result { let raw: c_int = getsockopt(self, libc::IPPROTO_TCP, libc::TCP_NODELAY)?; Ok(raw != 0) } + #[cfg(target_os = "switch")] + pub fn nodelay(&self) -> io::Result { + Ok(false) + } + #[cfg(not(any(target_os = "solaris", target_os = "illumos")))] pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { let mut nonblocking = nonblocking as libc::c_int; diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs index 2fcb5b9c4e66e..16db75264553a 100644 --- a/library/std/src/sys/unix/os.rs +++ b/library/std/src/sys/unix/os.rs @@ -50,7 +50,7 @@ extern "C" { target_os = "openbsd", target_os = "android", target_os = "redox", - target_env = "newlib" + target_env = "libnx" ), link_name = "__errno" )] @@ -101,7 +101,7 @@ pub fn set_errno(e: i32) { /// Gets a detailed string description for the given error number. pub fn error_string(errno: i32) -> String { extern "C" { - #[cfg_attr(any(target_os = "linux", target_env = "newlib"), link_name = "__xpg_strerror_r")] + #[cfg_attr(any(target_os = "linux", target_env = "libnx"), link_name = "__xpg_strerror_r")] fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t) -> c_int; } @@ -436,6 +436,16 @@ pub fn current_exe() -> io::Result { Err(io::Error::new(ErrorKind::Other, "Not yet implemented!")) } +#[cfg(target_env = "libnx")] +pub fn current_exe() -> io::Result { + use crate::env; + // guaranteed by abi to be an absolute path to the executable + env::args_os() + .next() + .map(From::from) + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "no current exe available")) +} + pub struct Env { iter: vec::IntoIter<(OsString, OsString)>, _dont_send_or_sync_me: PhantomData<*mut ()>, @@ -545,10 +555,16 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> { } } +#[cfg(not(target_os = "switch"))] pub fn page_size() -> usize { unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize } } +#[cfg(target_os = "switch")] +pub fn page_size() -> usize { + 0x1000 +} + pub fn temp_dir() -> PathBuf { crate::env::var_os("TMPDIR").map(PathBuf::from).unwrap_or_else(|| { if cfg!(target_os = "android") { @@ -566,7 +582,8 @@ pub fn home_dir() -> Option { target_os = "android", target_os = "ios", target_os = "emscripten", - target_os = "redox" + target_os = "redox", + target_os = "switch" ))] unsafe fn fallback() -> Option { None @@ -575,7 +592,8 @@ pub fn home_dir() -> Option { target_os = "android", target_os = "ios", target_os = "emscripten", - target_os = "redox" + target_os = "redox", + target_os = "switch" )))] unsafe fn fallback() -> Option { let amt = match libc::sysconf(libc::_SC_GETPW_R_SIZE_MAX) { @@ -610,10 +628,16 @@ pub fn getpid() -> u32 { unsafe { libc::getpid() as u32 } } +#[cfg(not(target_os = "switch"))] pub fn getppid() -> u32 { unsafe { libc::getppid() as u32 } } +#[cfg(target_os = "switch")] +pub fn getppid() -> u32 { + 1 // switch doesn't have a process hierarchy +} + #[cfg(target_env = "gnu")] pub fn glibc_version() -> Option<(usize, usize)> { if let Some(Ok(version_str)) = glibc_version_cstr().map(CStr::to_str) { diff --git a/library/std/src/sys/unix/process/mod.rs b/library/std/src/sys/unix/process/mod.rs index 553e980f08e97..c7c90f1aba152 100644 --- a/library/std/src/sys/unix/process/mod.rs +++ b/library/std/src/sys/unix/process/mod.rs @@ -3,11 +3,14 @@ pub use self::process_inner::{ExitStatus, Process}; pub use crate::ffi::OsString as EnvKey; mod process_common; -#[cfg(not(target_os = "fuchsia"))] +#[cfg(not(any(target_os = "fuchsia", target_env = "libnx")))] #[path = "process_unix.rs"] mod process_inner; #[cfg(target_os = "fuchsia")] #[path = "process_fuchsia.rs"] mod process_inner; +#[cfg(target_env = "libnx")] +#[path = "process_dummy.rs"] +mod process_inner; #[cfg(target_os = "fuchsia")] mod zircon; diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index 6e33cdd3c4826..646f3486bbf36 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -1,3 +1,5 @@ +#![cfg_attr(target_env = "libnx", allow(unused_variables, dead_code))] + use crate::os::unix::prelude::*; use crate::collections::BTreeMap; diff --git a/library/std/src/sys/unix/process/process_dummy.rs b/library/std/src/sys/unix/process/process_dummy.rs new file mode 100644 index 0000000000000..5d7a9e0bda95b --- /dev/null +++ b/library/std/src/sys/unix/process/process_dummy.rs @@ -0,0 +1,97 @@ +//! libnx has very limited support for multiple processes, so a dummy implementation is used +//! there (similar to WebAssembly). + +use crate::fmt; +use crate::io; +use crate::os::raw::c_int; +use crate::sys::process::process_common::*; + +pub use crate::ffi::OsString as EnvKey; + +fn unsupported() -> io::Result { + Err(unsupported_err()) +} + +fn unsupported_err() -> io::Error { + io::Error::new(io::ErrorKind::Other, "operation not supported") +} + +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] +pub enum Void {} + +//////////////////////////////////////////////////////////////////////////////// +// Command +//////////////////////////////////////////////////////////////////////////////// + +impl Command { + pub fn spawn( + &mut self, + _default: Stdio, + _needs_stdin: bool, + ) -> io::Result<(Process, StdioPipes)> { + unsupported() + } + + pub fn exec(&mut self, _default: Stdio) -> io::Error { + unsupported_err() + } +} + +/// Unix exit statuses +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub struct ExitStatus(c_int); + +impl ExitStatus { + fn exited(&self) -> bool { + libc::WIFEXITED(self.0) + } + + pub fn success(&self) -> bool { + self.code() == Some(0) + } + + pub fn code(&self) -> Option { + if self.exited() { Some(libc::WEXITSTATUS(self.0)) } else { None } + } + + pub fn signal(&self) -> Option { + if !self.exited() { Some(libc::WTERMSIG(self.0)) } else { None } + } +} + +impl From for ExitStatus { + fn from(a: c_int) -> ExitStatus { + ExitStatus(a) + } +} + +impl fmt::Display for ExitStatus { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if let Some(code) = self.code() { + write!(f, "exit code: {}", code) + } else { + let signal = self.signal().unwrap(); + write!(f, "signal: {}", signal) + } + } +} + +pub struct Process(Void); + +impl Process { + pub fn id(&self) -> u32 { + match self.0 {} + } + + pub fn kill(&mut self) -> io::Result<()> { + match self.0 {} + } + + pub fn wait(&mut self) -> io::Result { + match self.0 {} + } + + pub fn try_wait(&mut self) -> io::Result> { + match self.0 {} + } +} diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index c1bda6b430e13..acfd50a53ca84 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -148,14 +148,14 @@ impl Thread { } #[cfg(any( - target_env = "newlib", + target_env = "libnx", target_os = "haiku", target_os = "l4re", target_os = "emscripten", target_os = "redox" ))] pub fn set_name(_name: &CStr) { - // Newlib, Haiku, and Emscripten have no way to set a thread name. + // libnx, Haiku, and Emscripten have no way to set a thread name. } #[cfg(target_os = "fuchsia")] pub fn set_name(_name: &CStr) { diff --git a/library/std/src/sys/unix/time.rs b/library/std/src/sys/unix/time.rs index 6707f790cab0a..6e720a2f187f9 100644 --- a/library/std/src/sys/unix/time.rs +++ b/library/std/src/sys/unix/time.rs @@ -339,9 +339,9 @@ mod inner { } } - #[cfg(not(target_os = "dragonfly"))] + #[cfg(not(any(target_os = "dragonfly", target_env = "libnx")))] pub type clock_t = libc::c_int; - #[cfg(target_os = "dragonfly")] + #[cfg(any(target_os = "dragonfly", target_env = "libnx"))] pub type clock_t = libc::c_ulong; fn now(clock: clock_t) -> Timespec { diff --git a/library/std/src/sys/unix/weak.rs b/library/std/src/sys/unix/weak.rs index f4b33a00f7c85..4283de44e9d0b 100644 --- a/library/std/src/sys/unix/weak.rs +++ b/library/std/src/sys/unix/weak.rs @@ -58,6 +58,7 @@ impl Weak { } } +#[cfg(not(target_env = "libnx"))] unsafe fn fetch(name: &str) -> usize { let name = match CStr::from_bytes_with_nul(name.as_bytes()) { Ok(cstr) => cstr, @@ -66,6 +67,11 @@ unsafe fn fetch(name: &str) -> usize { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr()) as usize } +#[cfg(target_env = "libnx")] +unsafe fn fetch(_name: &str) -> usize { + 0 +} + #[cfg(not(target_os = "linux"))] macro_rules! syscall { (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => ( diff --git a/library/std/src/sys_common/net.rs b/library/std/src/sys_common/net.rs index 81a5ef95e82dc..4ef7ffda05b8e 100644 --- a/library/std/src/sys_common/net.rs +++ b/library/std/src/sys_common/net.rs @@ -1,3 +1,5 @@ +#![cfg_attr(target_os = "switch", allow(unused_variables, dead_code))] + use crate::cmp; use crate::convert::{TryFrom, TryInto}; use crate::ffi::CString; @@ -21,7 +23,7 @@ cfg_if::cfg_if! { target_os = "solaris", target_os = "haiku", target_os = "l4re"))] { use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP; use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP; - } else { + } else if #[cfg(not(target_os = "switch"))] { use crate::sys::net::netc::IPV6_ADD_MEMBERSHIP; use crate::sys::net::netc::IPV6_DROP_MEMBERSHIP; } @@ -312,11 +314,21 @@ impl TcpStream { } pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { - setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) + #[cfg(not(target_os = "switch"))] + { + setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) + } + #[cfg(target_os = "switch")] + { + Ok(()) + } } pub fn ttl(&self) -> io::Result { + #[cfg(not(target_os = "switch"))] let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?; + #[cfg(target_os = "switch")] + let raw: c_int = 64; Ok(raw as u32) } @@ -412,21 +424,43 @@ impl TcpListener { } pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { - setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) + #[cfg(not(target_os = "switch"))] + { + setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) + } + #[cfg(target_os = "switch")] + { + Ok(()) + } } pub fn ttl(&self) -> io::Result { + #[cfg(not(target_os = "switch"))] let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?; + #[cfg(target_os = "switch")] + let raw: c_int = 64; Ok(raw as u32) } pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> { - setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int) + #[cfg(not(target_os = "switch"))] + { + setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int) + } + #[cfg(target_os = "switch")] + { + Err(io::Error::new(io::ErrorKind::Other, "operation not supported")) + } } pub fn only_v6(&self) -> io::Result { - let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY)?; - Ok(raw != 0) + #[cfg(not(target_os = "switch"))] + { + let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY)?; + Ok(raw != 0) + } + #[cfg(target_os = "switch")] + Err(io::Error::new(io::ErrorKind::Other, "operation not supported")) } pub fn take_error(&self) -> io::Result> { @@ -547,80 +581,155 @@ impl UdpSocket { } pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> { - setsockopt( - &self.inner, - c::IPPROTO_IP, - c::IP_MULTICAST_LOOP, - multicast_loop_v4 as IpV4MultiCastType, - ) + #[cfg(not(target_os = "switch"))] + { + setsockopt( + &self.inner, + c::IPPROTO_IP, + c::IP_MULTICAST_LOOP, + multicast_loop_v4 as IpV4MultiCastType, + ) + } + #[cfg(target_os = "switch")] + { + Err(io::Error::new(io::ErrorKind::Other, "operation not supported")) + } } pub fn multicast_loop_v4(&self) -> io::Result { - let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)?; - Ok(raw != 0) + #[cfg(not(target_os = "switch"))] + { + let raw: IpV4MultiCastType = + getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)?; + Ok(raw != 0) + } + #[cfg(target_os = "switch")] + { + Err(io::Error::new(io::ErrorKind::Other, "operation not supported")) + } } pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> { - setsockopt( - &self.inner, - c::IPPROTO_IP, - c::IP_MULTICAST_TTL, - multicast_ttl_v4 as IpV4MultiCastType, - ) + #[cfg(not(target_os = "switch"))] + { + setsockopt( + &self.inner, + c::IPPROTO_IP, + c::IP_MULTICAST_TTL, + multicast_ttl_v4 as IpV4MultiCastType, + ) + } + #[cfg(target_os = "switch")] + { + Err(io::Error::new(io::ErrorKind::Other, "operation not supported")) + } } pub fn multicast_ttl_v4(&self) -> io::Result { - let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)?; - Ok(raw as u32) + #[cfg(not(target_os = "switch"))] + { + let raw: IpV4MultiCastType = + getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)?; + Ok(raw as u32) + } + #[cfg(target_os = "switch")] + Err(io::Error::new(io::ErrorKind::Other, "operation not supported")) } pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> { - setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP, multicast_loop_v6 as c_int) + #[cfg(not(target_os = "switch"))] + { + setsockopt( + &self.inner, + c::IPPROTO_IPV6, + c::IPV6_MULTICAST_LOOP, + multicast_loop_v6 as c_int, + ) + } + #[cfg(target_os = "switch")] + { + Err(io::Error::new(io::ErrorKind::Other, "operation not supported")) + } } pub fn multicast_loop_v6(&self) -> io::Result { - let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP)?; - Ok(raw != 0) + #[cfg(not(target_os = "switch"))] + { + let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP)?; + Ok(raw != 0) + } + #[cfg(target_os = "switch")] + Err(io::Error::new(io::ErrorKind::Other, "operation not supported")) } pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { - let mreq = c::ip_mreq { - imr_multiaddr: *multiaddr.as_inner(), - imr_interface: *interface.as_inner(), - }; - setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq) + #[cfg(not(target_os = "switch"))] + { + let mreq = c::ip_mreq { + imr_multiaddr: *multiaddr.as_inner(), + imr_interface: *interface.as_inner(), + }; + setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq) + } + #[cfg(target_os = "switch")] + Err(io::Error::new(io::ErrorKind::Other, "operation not supported")) } pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { - let mreq = c::ipv6_mreq { - ipv6mr_multiaddr: *multiaddr.as_inner(), - ipv6mr_interface: to_ipv6mr_interface(interface), - }; - setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq) + #[cfg(not(target_os = "switch"))] + { + let mreq = c::ipv6_mreq { + ipv6mr_multiaddr: *multiaddr.as_inner(), + ipv6mr_interface: to_ipv6mr_interface(interface), + }; + setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq) + } + #[cfg(target_os = "switch")] + Err(io::Error::new(io::ErrorKind::Other, "operation not supported")) } pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> { - let mreq = c::ip_mreq { - imr_multiaddr: *multiaddr.as_inner(), - imr_interface: *interface.as_inner(), - }; - setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq) + #[cfg(not(target_os = "switch"))] + { + let mreq = c::ip_mreq { + imr_multiaddr: *multiaddr.as_inner(), + imr_interface: *interface.as_inner(), + }; + setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq) + } + #[cfg(target_os = "switch")] + Err(io::Error::new(io::ErrorKind::Other, "operation not supported")) } pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { - let mreq = c::ipv6_mreq { - ipv6mr_multiaddr: *multiaddr.as_inner(), - ipv6mr_interface: to_ipv6mr_interface(interface), - }; - setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq) + #[cfg(not(target_os = "switch"))] + { + let mreq = c::ipv6_mreq { + ipv6mr_multiaddr: *multiaddr.as_inner(), + ipv6mr_interface: to_ipv6mr_interface(interface), + }; + setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq) + } + #[cfg(target_os = "switch")] + Err(io::Error::new(io::ErrorKind::Other, "operation not supported")) } pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { - setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) + #[cfg(not(target_os = "switch"))] + { + setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) + } + #[cfg(target_os = "switch")] + { + Ok(()) + } } pub fn ttl(&self) -> io::Result { + #[cfg(not(target_os = "switch"))] let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?; + #[cfg(target_os = "switch")] + let raw: c_int = 64; Ok(raw as u32) } diff --git a/library/test/src/helpers/concurrency.rs b/library/test/src/helpers/concurrency.rs index 7ca27bf0dc15e..672335fd3d46b 100644 --- a/library/test/src/helpers/concurrency.rs +++ b/library/test/src/helpers/concurrency.rs @@ -109,7 +109,7 @@ cfg_if::cfg_if! { cpus as usize } } else { - // FIXME: implement on vxWorks, Redox, HermitCore, Haiku, l4re + // FIXME: implement on vxWorks, Redox, HermitCore, Haiku, l4re, libnx fn num_cpus() -> usize { 1 } diff --git a/library/unwind/build.rs b/library/unwind/build.rs index ab09a6e324d8b..bbc54f7b6f712 100644 --- a/library/unwind/build.rs +++ b/library/unwind/build.rs @@ -48,6 +48,8 @@ fn main() { // redox is handled in lib.rs } else if target.contains("cloudabi") { println!("cargo:rustc-link-lib=unwind"); + } else if target.contains("libnx") { + llvm_libunwind::compile(); } } @@ -120,6 +122,12 @@ mod llvm_libunwind { cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None); } + if target_env == "libnx" { + cfg.define("_LIBUNWIND_IS_BAREMETAL", None); + cfg.define("_LIBUNWIND_SUPPORT_DWARF_UNWIND", None); + cfg.define("_LIBUNWIND_SUPPORT_DWARF_INDEX", None); + } + let mut unwind_sources = vec![ "Unwind-EHABI.cpp", "Unwind-seh.cpp", diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000000000..0a9ce4f3e2c93 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1 @@ +libc diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index c3f1bac177de7..f8077980c08de 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -470,8 +470,6 @@ def fix_bin_or_dylib(self, fname): if not os.path.exists("/etc/NIXOS"): return - if os.path.exists("/lib"): - return # At this point we're pretty sure the user is running NixOS nix_os_msg = "info: you seem to be running NixOS. Attempting to patch" diff --git a/src/ci/docker/host-x86_64/disabled/aarch64-libnx/Dockerfile b/src/ci/docker/host-x86_64/disabled/aarch64-libnx/Dockerfile new file mode 100644 index 0000000000000..6b317ece1dabd --- /dev/null +++ b/src/ci/docker/host-x86_64/disabled/aarch64-libnx/Dockerfile @@ -0,0 +1,26 @@ +FROM devkitpro/devkita64:20200528 + +COPY scripts/cross-apt-packages.sh /scripts/ +RUN sh /scripts/cross-apt-packages.sh + +COPY scripts/rustbuild-setup.sh /scripts/ +RUN sh /scripts/rustbuild-setup.sh +USER rustbuild +WORKDIR /tmp + +USER root + +COPY scripts/sccache.sh /scripts/ +RUN sh /scripts/sccache.sh + +ENV PATH=$PATH:/opt/devkitpro/devkitA64/bin/ + +ENV CC_aarch64_unknown_switch_libnx=aarch64-none-elf-gcc \ + AR_aarch64_unknown_switch_libnx=aarch64-none-elf-ar \ + CXX_aarch64_unknown_switch_libnx=aarch64-none-elf-g++ + +ENV TARGETS=aarch64-unknown-switch-libnx + +ENV RUST_CONFIGURE_ARGS \ + --disable-docs +ENV SCRIPT python3 ../x.py dist --target $TARGETS diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index d725a60118e3c..e5f9af4af139c 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1349,8 +1349,15 @@ fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_ty sess.fatal(&format!("failed to write link script to {}: {}", path.display(), e)); } - cmd.arg("--script"); - cmd.arg(path); + if sess.target.target.linker_flavor == LinkerFlavor::Gcc { + cmd.arg("-Wl,--script"); + let mut arg = OsString::from("-Wl,"); + arg.push(path); + cmd.arg(&arg); + } else { + cmd.arg("--script"); + cmd.arg(path); + } } _ => {} } diff --git a/src/librustc_target/spec/aarch64_unknown_switch_libnx.rs b/src/librustc_target/spec/aarch64_unknown_switch_libnx.rs new file mode 100644 index 0000000000000..8976ed649a9d1 --- /dev/null +++ b/src/librustc_target/spec/aarch64_unknown_switch_libnx.rs @@ -0,0 +1,78 @@ +//! libnx Nintendo Switch homebrew toolchain. +//! +//! # Building +//! The recommended way to build Rust for this target is using Docker. You can start a build in a +//! container with `./src/ci/docker/run.sh aarch64-libnx` from the Rust source tree. For +//! development, you can add `--dev` as the first argument to get a shell inside the container. + +use super::{LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, Target, TargetOptions}; + +// libnx has custom linker requirements. +const LINKER_SCRIPT: &str = include_str!("./aarch64_unknown_switch_libnx_script.ld"); + +pub fn target() -> Result { + let mut link_args = LinkArgs::new(); + link_args.insert( + LinkerFlavor::Gcc, + vec![ + "-march=armv8-a".to_string(), + "-mtune=cortex-a57".to_string(), + "-mtp=soft".to_string(), + "-nodefaultlibs".to_string(), + "-nostdlib".to_string(), + "-nostartfiles".to_string(), + "-L/opt/devkitpro/portlibs/switch/lib".to_string(), + "-L/opt/devkitpro/libnx/lib".to_string(), + "-Wl,--start-group".to_string(), + "-lgcc".to_string(), + "-lc".to_string(), + "-lnx".to_string(), + "-lsysbase".to_string(), + "-lm".to_string(), + "-l:crtbegin.o".to_string(), + "-l:crtend.o".to_string(), + "-l:crti.o".to_string(), + "-l:crtn.o".to_string(), + "-Wl,--end-group".to_string(), + "-fPIE".to_string(), + "-pie".to_string(), + "-Wl,-z,text".to_string(), + "-Wl,-z,muldefs".to_string(), + "-Wl,--export-dynamic".to_string(), + "-Wl,--eh-frame-hdr".to_string(), + ], + ); + let opts = TargetOptions { + linker: Some("aarch64-none-elf-gcc".to_owned()), + features: "+a53,+strict-align,+crc".to_string(), + executables: true, + relocation_model: RelocModel::Pic, + disable_redzone: true, + linker_is_gnu: true, + max_atomic_width: Some(128), + panic_strategy: PanicStrategy::Unwind, + unsupported_abis: super::arm_base::unsupported_abis(), + target_family: Some("unix".to_string()), + position_independent_executables: true, + has_elf_tls: false, + trap_unreachable: true, + emit_debug_gdb_scripts: true, + requires_uwtable: true, + post_link_args: link_args, + link_script: Some(LINKER_SCRIPT.to_string()), + ..Default::default() + }; + Ok(Target { + llvm_target: "aarch64-unknown-none".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + target_c_int_width: "32".to_string(), + target_os: "switch".to_string(), + target_env: "libnx".to_string(), + target_vendor: "unknown".to_string(), + data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".to_string(), + arch: "aarch64".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: opts, + }) +} diff --git a/src/librustc_target/spec/aarch64_unknown_switch_libnx_script.ld b/src/librustc_target/spec/aarch64_unknown_switch_libnx_script.ld new file mode 100644 index 0000000000000..2b0842fc359c4 --- /dev/null +++ b/src/librustc_target/spec/aarch64_unknown_switch_libnx_script.ld @@ -0,0 +1,217 @@ +OUTPUT_ARCH(aarch64) +ENTRY(_start) + +PHDRS +{ + code PT_LOAD FLAGS(5) /* Read | Execute */; + rodata PT_LOAD FLAGS(4) /* Read */; + data PT_LOAD FLAGS(6) /* Read | Write */; + dyn PT_DYNAMIC; +} + +SECTIONS +{ + /* =========== CODE section =========== */ + PROVIDE(__start__ = 0x0); + . = __start__; + __code_start = . ; + + .crt0 : + { + KEEP (*(.crt0)) + . = ALIGN(8); + } :code + + .init : + { + KEEP( *(.init) ) + . = ALIGN(8); + } :code + + .plt : + { + *(.plt) + *(.iplt) + . = ALIGN(8); + } :code + + .text : + { + *(.text.unlikely .text.*_unlikely .text.unlikely.*) + *(.text.exit .text.exit.*) + *(.text.startup .text.startup.*) + *(.text.hot .text.hot.*) + *(.text .stub .text.* .gnu.linkonce.t.*) + . = ALIGN(8); + } :code + + .fini : + { + KEEP( *(.fini) ) + . = ALIGN(8); + } :code + + /* =========== RODATA section =========== */ + . = ALIGN(0x1000); + __rodata_start = . ; + + .nx-module-name : { KEEP (*(.nx-module-name)) } :rodata + + .rodata : + { + *(.rodata .rodata.* .gnu.linkonce.r.*) + . = ALIGN(8); + } :rodata + + .eh_frame_hdr : { __eh_frame_hdr_start = .; KEEP(*(.eh_frame_hdr)) KEEP(*(.eh_frame_entry .eh_frame_entry.*)) __eh_frame_hdr_end = .; } :rodata + .eh_frame : ONLY_IF_RO { __eh_frame_start = .; KEEP (*(.eh_frame)) *(.eh_frame.*) __eh_frame_end = .; } :rodata + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } :rodata + .gnu_extab : ONLY_IF_RO { *(.gnu_extab*) } : rodata + + .dynamic : { *(.dynamic) } :rodata :dyn + .dynsym : { *(.dynsym) } :rodata + .dynstr : { *(.dynstr) } :rodata + .rela.dyn : { *(.rela.*) } :rodata + .interp : { *(.interp) } :rodata + .hash : { *(.hash) } :rodata + .gnu.hash : { *(.gnu.hash) } :rodata + .gnu.version : { *(.gnu.version) } :rodata + .gnu.version_d : { *(.gnu.version_d) } :rodata + .gnu.version_r : { *(.gnu.version_r) } :rodata + .note.gnu.build-id : { *(.note.gnu.build-id) } :rodata + + /* =========== DATA section =========== */ + . = ALIGN(0x1000); + __data_start = . ; + + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) } :data + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } :data + .gnu_extab : ONLY_IF_RW { *(.gnu_extab*) } : data + .exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) } :data + + .tdata ALIGN(8) : + { + __tdata_lma = .; + *(.tdata .tdata.* .gnu.linkonce.td.*) + . = ALIGN(8); + __tdata_lma_end = .; + } :data + + .tbss ALIGN(8) : + { + *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) + . = ALIGN(8); + } :data + + .preinit_array ALIGN(8) : + { + PROVIDE (__preinit_array_start = .); + KEEP (*(.preinit_array)) + PROVIDE (__preinit_array_end = .); + } :data + + .init_array ALIGN(8) : + { + PROVIDE (__init_array_start = .); + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + PROVIDE (__init_array_end = .); + } :data + + .fini_array ALIGN(8) : + { + PROVIDE (__fini_array_start = .); + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + PROVIDE (__fini_array_end = .); + } :data + + .ctors ALIGN(8) : + { + KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */ + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } :data + + .dtors ALIGN(8) : + { + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } :data + + __got_start__ = .; + + .got : { *(.got) *(.igot) } :data + .got.plt : { *(.got.plt) *(.igot.plt) } :data + + __got_end__ = .; + + .data ALIGN(8) : + { + *(.data .data.* .gnu.linkonce.d.*) + SORT(CONSTRUCTORS) + } :data + + __bss_start__ = .; + .bss ALIGN(8) : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(8); + + /* Reserve space for the TLS segment of the main thread */ + __tls_start = .; + . += + SIZEOF(.tdata) + SIZEOF(.tbss); + __tls_end = .; + } : data + __bss_end__ = .; + + __end__ = ABSOLUTE(.) ; + + . = ALIGN(0x1000); + __argdata__ = ABSOLUTE(.) ; + + /* ================== + ==== Metadata ==== + ================== */ + + /* Discard sections that difficult post-processing */ + /DISCARD/ : { *(.group .comment .note) } + + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 961a438fd233c..b4ed6533367a9 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -678,6 +678,7 @@ supported_targets! { ("mipsel-sony-psp", mipsel_sony_psp), ("thumbv4t-none-eabi", thumbv4t_none_eabi), + ("aarch64-unknown-switch-libnx", aarch64_unknown_switch_libnx), } /// Everything `rustc` knows about how to compile for a specific target. diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs index 1cf0d24e26ff5..4353dcc59f023 100644 --- a/src/tools/tidy/src/extdeps.rs +++ b/src/tools/tidy/src/extdeps.rs @@ -4,7 +4,10 @@ use std::fs; use std::path::Path; /// List of allowed sources for packages. -const ALLOWED_SOURCES: &[&str] = &["\"registry+https://github.com/rust-lang/crates.io-index\""]; +const ALLOWED_SOURCES: &[&str] = &[ + "\"registry+https://github.com/rust-lang/crates.io-index\"", + "\"git+https://github.com/leo60228/libc.git?branch=bindgen-horizon#9f1d51f1276ac6967065b0fd7c3d814ec86dd391\"", +]; /// Checks for external package sources. `root` is the path to the directory that contains the /// workspace `Cargo.toml`.