diff options
| author | bors <bors@rust-lang.org> | 2024-04-14 13:28:21 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-04-14 13:28:21 +0000 |
| commit | a8a88fe5243cbeb37d8a9de8c5ca63136c0604b0 (patch) | |
| tree | 4af434108516a24fcd24765b66f1f91aa273d254 | |
| parent | 78bc0a5656337478cb4163d01ee4429bab5087a9 (diff) | |
| parent | 87e1dd0dfdd7c4d5e2dba8ce12c619dd2bf73d9c (diff) | |
| download | rust-a8a88fe5243cbeb37d8a9de8c5ca63136c0604b0.tar.gz rust-a8a88fe5243cbeb37d8a9de8c5ca63136c0604b0.zip | |
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](https://github.com/rust-lang/libc/blob/a0f5b4b21391252fe38b2df9310dc65e37b07d9f/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.
| -rw-r--r-- | library/core/src/ffi/mod.rs | 10 | ||||
| -rw-r--r-- | library/core/src/lib.rs | 1 | ||||
| -rw-r--r-- | library/panic_abort/Cargo.toml | 4 | ||||
| -rw-r--r-- | library/panic_unwind/Cargo.toml | 4 | ||||
| -rw-r--r-- | library/panic_unwind/src/seh.rs | 2 | ||||
| -rw-r--r-- | library/std/Cargo.toml | 7 | ||||
| -rw-r--r-- | library/std/src/lib.rs | 3 | ||||
| -rw-r--r-- | library/std/src/os/unix/net/addr.rs | 2 | ||||
| -rw-r--r-- | library/std/src/os/unix/net/ancillary.rs | 2 | ||||
| -rw-r--r-- | library/std/src/os/unix/net/datagram.rs | 4 | ||||
| -rw-r--r-- | library/std/src/os/unix/net/listener.rs | 8 | ||||
| -rw-r--r-- | library/test/Cargo.toml | 2 | ||||
| -rw-r--r-- | library/unwind/Cargo.toml | 4 | ||||
| -rw-r--r-- | library/unwind/src/lib.rs | 4 | ||||
| -rw-r--r-- | library/unwind/src/libunwind.rs | 2 | ||||
| -rw-r--r-- | library/unwind/src/unwinding.rs | 2 |
16 files changed, 46 insertions, 15 deletions
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs index 3627e844222..cbdae2ac766 100644 --- a/library/core/src/ffi/mod.rs +++ b/library/core/src/ffi/mod.rs @@ -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" {} diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index d2618c8bb2b..154565b6fee 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -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)] diff --git a/library/panic_abort/Cargo.toml b/library/panic_abort/Cargo.toml index e6ea2b1849b..a9d1f53761c 100644 --- a/library/panic_abort/Cargo.toml +++ b/library/panic_abort/Cargo.toml @@ -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 } diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml index 85386976d63..dce2da31644 100644 --- a/library/panic_unwind/Cargo.toml +++ b/library/panic_unwind/Cargo.toml @@ -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 } diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs index 6bc0559c88f..04c3d3bf9c3 100644 --- a/library/panic_unwind/src/seh.rs +++ b/library/panic_unwind/src/seh.rs @@ -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)] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index d2804b4d20a..cba9ff4485d 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -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'] } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index e9de3b77670..72ae38cfa20 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -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; diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 1787eba0ef8..79f2c365025 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -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)] diff --git a/library/std/src/os/unix/net/ancillary.rs b/library/std/src/os/unix/net/ancillary.rs index 1d279d6adbc..0597fdcbd72 100644 --- a/library/std/src/os/unix/net/ancillary.rs +++ b/library/std/src/os/unix/net/ancillary.rs @@ -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; diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index df698c17f6c..b29f9099a11 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -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 { diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index 31286a906ea..7e53acbc387 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -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 _, diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml index 4c42e3bae56..0e2409f63ab 100644 --- a/library/test/Cargo.toml +++ b/library/test/Cargo.toml @@ -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 } diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index b7418d1189c..bbd1db8dfa5 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -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 } diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 51d31a00afe..544d9fbf1ae 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -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 diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs index 57ce3d0fa5c..e34e73a3516 100644 --- a/library/unwind/src/libunwind.rs +++ b/library/unwind/src/libunwind.rs @@ -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)] diff --git a/library/unwind/src/unwinding.rs b/library/unwind/src/unwinding.rs index 95e2eb000cc..083acaeb56a 100644 --- a/library/unwind/src/unwinding.rs +++ b/library/unwind/src/unwinding.rs @@ -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)] |
