Auto merge of #122268 - ChrisDenton:no-libc, r=Mark-Simulacrum
Link MSVC default lib in core
## The Problem
On Windows MSVC, Rust invokes the linker directly. This means only the objects and libraries Rust explicitly passes to the linker are used. In short, this is equivalent to passing `-nodefaultlibs`, `-nostartfiles`, etc for gnu compilers.
To compensate for this [the libc crate links to the necessary libraries](a0f5b4b213/src/windows/mod.rs (L258-L261)
). The libc crate is then linked from std, thus when you use std you get the defaults back.or integrate with C/C++.
However, this has a few problems:
- For `no_std`, users are left to manually pass the default lib to the linker
- Whereas `std` has the opposite problem, using [`/nodefaultlib`](https://learn.microsoft.com/en-us/cpp/build/reference/nodefaultlib-ignore-libraries?view=msvc-170) doesn't work as expected because Rust treats them as normal libs. This is a particular problem when you want to use e.g. the debug CRT libraries in their place or integrate with C/C++..
## The solution
This PR fixes this in two ways:
- moves linking the default lib into `core`
- passes the lib to the linker using [`/defaultlib`](https://learn.microsoft.com/en-us/cpp/build/reference/defaultlib-specify-default-library?view=msvc-170). This allows users to override it in the normal way (i.e. with [`/nodefaultlib`](https://learn.microsoft.com/en-us/cpp/build/reference/nodefaultlib-ignore-libraries?view=msvc-170)).
This is more or less equivalent to what the MSVC C compiler does. You can see what this looks like in my second commit, which I'll reproduce here for convenience:
```rust
// In library/core
#[cfg(all(windows, target_env = "msvc"))]
#[link(
name = "/defaultlib:msvcrt",
modifiers = "+verbatim",
cfg(not(target_feature = "crt-static"))
)]
#[link(name = "/defaultlib:libcmt", modifiers = "+verbatim", cfg(target_feature = "crt-static"))]
extern "C" {}
```
## Alternatives
- Add the above to `unwind` and `std` but not `core`
- The status quo
- Some other kind of compiler magic maybe
This bares some discussion so I've t-libs nominated it.
This commit is contained in:
commit
a8a88fe524
@ -609,3 +609,13 @@ extern "rust-intrinsic" {
|
||||
#[rustc_nounwind]
|
||||
fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaListImpl<'_>) -> T;
|
||||
}
|
||||
|
||||
// Link the MSVC default lib
|
||||
#[cfg(all(windows, target_env = "msvc"))]
|
||||
#[link(
|
||||
name = "/defaultlib:msvcrt",
|
||||
modifiers = "+verbatim",
|
||||
cfg(not(target_feature = "crt-static"))
|
||||
)]
|
||||
#[link(name = "/defaultlib:libcmt", modifiers = "+verbatim", cfg(target_feature = "crt-static"))]
|
||||
extern "C" {}
|
||||
|
@ -178,6 +178,7 @@
|
||||
#![feature(ip_bits)]
|
||||
#![feature(is_ascii_octdigit)]
|
||||
#![feature(isqrt)]
|
||||
#![feature(link_cfg)]
|
||||
#![feature(maybe_uninit_uninit_array)]
|
||||
#![feature(non_null_convenience)]
|
||||
#![feature(offset_of_enum)]
|
||||
|
@ -15,5 +15,7 @@ doc = false
|
||||
alloc = { path = "../alloc" }
|
||||
cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
|
||||
core = { path = "../core" }
|
||||
libc = { version = "0.2", default-features = false }
|
||||
compiler_builtins = "0.1.0"
|
||||
|
||||
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
|
||||
libc = { version = "0.2", default-features = false }
|
||||
|
@ -14,7 +14,9 @@ doc = false
|
||||
[dependencies]
|
||||
alloc = { path = "../alloc" }
|
||||
core = { path = "../core" }
|
||||
libc = { version = "0.2", default-features = false }
|
||||
unwind = { path = "../unwind" }
|
||||
compiler_builtins = "0.1.0"
|
||||
cfg-if = "1.0"
|
||||
|
||||
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
|
||||
libc = { version = "0.2", default-features = false }
|
||||
|
@ -48,9 +48,9 @@
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use core::any::Any;
|
||||
use core::ffi::{c_int, c_uint, c_void};
|
||||
use core::mem::{self, ManuallyDrop};
|
||||
use core::ptr::{addr_of, addr_of_mut};
|
||||
use libc::{c_int, c_uint, c_void};
|
||||
|
||||
// NOTE(nbdd0121): The `canary` field is part of stable ABI.
|
||||
#[repr(C)]
|
||||
|
@ -17,7 +17,6 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
|
||||
panic_unwind = { path = "../panic_unwind", optional = true }
|
||||
panic_abort = { path = "../panic_abort" }
|
||||
core = { path = "../core", public = true }
|
||||
libc = { version = "0.2.153", default-features = false, features = ['rustc-dep-of-std'], public = true }
|
||||
compiler_builtins = { version = "0.1.105" }
|
||||
profiler_builtins = { path = "../profiler_builtins", optional = true }
|
||||
unwind = { path = "../unwind" }
|
||||
@ -31,6 +30,12 @@ rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] }
|
||||
miniz_oxide = { version = "0.7.0", optional = true, default-features = false }
|
||||
addr2line = { version = "0.21.0", optional = true, default-features = false }
|
||||
|
||||
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
|
||||
libc = { version = "0.2.153", default-features = false, features = ['rustc-dep-of-std'], public = true }
|
||||
|
||||
[target.'cfg(all(windows, target_env = "msvc"))'.dependencies]
|
||||
libc = { version = "0.2.153", default-features = false }
|
||||
|
||||
[target.'cfg(all(not(target_os = "aix"), not(all(windows, target_env = "msvc", not(target_vendor = "uwp")))))'.dependencies]
|
||||
object = { version = "0.32.0", default-features = false, optional = true, features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] }
|
||||
|
||||
|
@ -431,6 +431,9 @@ extern crate test;
|
||||
#[allow(unused_imports)] // macros from `alloc` are not used on all platforms
|
||||
#[macro_use]
|
||||
extern crate alloc as alloc_crate;
|
||||
|
||||
// Many compiler tests depend on libc being pulled in by std
|
||||
// so include it here even if it's unused.
|
||||
#[doc(masked)]
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate libc;
|
||||
|
@ -11,7 +11,7 @@ use crate::{fmt, io, mem, ptr};
|
||||
#[cfg(not(unix))]
|
||||
#[allow(non_camel_case_types)]
|
||||
mod libc {
|
||||
pub use libc::c_int;
|
||||
pub use core::ffi::c_int;
|
||||
pub type socklen_t = u32;
|
||||
pub struct sockaddr;
|
||||
#[derive(Clone)]
|
||||
|
@ -20,7 +20,7 @@ use crate::sys::net::Socket;
|
||||
))]
|
||||
#[allow(non_camel_case_types)]
|
||||
mod libc {
|
||||
pub use libc::c_int;
|
||||
pub use core::ffi::c_int;
|
||||
pub struct ucred;
|
||||
pub struct cmsghdr;
|
||||
pub struct sockcred2;
|
||||
|
@ -34,7 +34,7 @@ use libc::MSG_NOSIGNAL;
|
||||
target_os = "haiku",
|
||||
target_os = "nto",
|
||||
)))]
|
||||
const MSG_NOSIGNAL: libc::c_int = 0x0;
|
||||
const MSG_NOSIGNAL: core::ffi::c_int = 0x0;
|
||||
|
||||
/// A Unix datagram socket.
|
||||
///
|
||||
@ -317,7 +317,7 @@ impl UnixDatagram {
|
||||
fn recv_from_flags(
|
||||
&self,
|
||||
buf: &mut [u8],
|
||||
flags: libc::c_int,
|
||||
flags: core::ffi::c_int,
|
||||
) -> io::Result<(usize, SocketAddr)> {
|
||||
let mut count = 0;
|
||||
let addr = SocketAddr::new(|addr, len| unsafe {
|
||||
|
@ -79,14 +79,14 @@ impl UnixListener {
|
||||
target_os = "espidf",
|
||||
target_os = "horizon"
|
||||
))]
|
||||
const backlog: libc::c_int = 128;
|
||||
const backlog: core::ffi::c_int = 128;
|
||||
#[cfg(any(
|
||||
target_os = "linux",
|
||||
target_os = "freebsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "macos"
|
||||
))]
|
||||
const backlog: libc::c_int = -1;
|
||||
const backlog: core::ffi::c_int = -1;
|
||||
#[cfg(not(any(
|
||||
target_os = "windows",
|
||||
target_os = "redox",
|
||||
@ -138,9 +138,9 @@ impl UnixListener {
|
||||
unsafe {
|
||||
let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
|
||||
#[cfg(target_os = "linux")]
|
||||
const backlog: libc::c_int = -1;
|
||||
const backlog: core::ffi::c_int = -1;
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
const backlog: libc::c_int = 128;
|
||||
const backlog: core::ffi::c_int = 128;
|
||||
cvt(libc::bind(
|
||||
inner.as_raw_fd(),
|
||||
core::ptr::addr_of!(socket_addr.addr) as *const _,
|
||||
|
@ -9,4 +9,6 @@ std = { path = "../std" }
|
||||
core = { path = "../core" }
|
||||
panic_unwind = { path = "../panic_unwind" }
|
||||
panic_abort = { path = "../panic_abort" }
|
||||
|
||||
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
|
||||
libc = { version = "0.2.150", default-features = false }
|
||||
|
@ -15,10 +15,12 @@ doc = false
|
||||
|
||||
[dependencies]
|
||||
core = { path = "../core" }
|
||||
libc = { version = "0.2.140", features = ['rustc-dep-of-std'], default-features = false }
|
||||
compiler_builtins = "0.1.0"
|
||||
cfg-if = "1.0"
|
||||
|
||||
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
|
||||
libc = { version = "0.2.140", features = ['rustc-dep-of-std'], default-features = false }
|
||||
|
||||
[target.'cfg(target_os = "xous")'.dependencies]
|
||||
unwinding = { version = "0.2.1", features = ['rustc-dep-of-std', 'unwinder', 'fde-custom'], default-features = false }
|
||||
|
||||
|
@ -12,6 +12,10 @@
|
||||
)]
|
||||
#![allow(internal_features)]
|
||||
|
||||
// Force libc to be included even if unused. This is required by many platforms.
|
||||
#[cfg(not(all(windows, target_env = "msvc")))]
|
||||
extern crate libc as _;
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(target_env = "msvc")] {
|
||||
// Windows MSVC no extra unwinder support needed
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![allow(nonstandard_style)]
|
||||
|
||||
use libc::{c_int, c_void};
|
||||
use core::ffi::{c_int, c_void};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
|
@ -1,6 +1,6 @@
|
||||
#![allow(nonstandard_style)]
|
||||
|
||||
use libc::{c_int, c_void};
|
||||
use core::ffi::{c_int, c_void};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
|
Loading…
x
Reference in New Issue
Block a user