Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit a8a88fe

Browse files
committed
Auto merge of rust-lang#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.
2 parents 78bc0a5 + 87e1dd0 commit a8a88fe

File tree

16 files changed

+46
-15
lines changed

16 files changed

+46
-15
lines changed

library/core/src/ffi/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,3 +609,13 @@ extern "rust-intrinsic" {
609609
#[rustc_nounwind]
610610
fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaListImpl<'_>) -> T;
611611
}
612+
613+
// Link the MSVC default lib
614+
#[cfg(all(windows, target_env = "msvc"))]
615+
#[link(
616+
name = "/defaultlib:msvcrt",
617+
modifiers = "+verbatim",
618+
cfg(not(target_feature = "crt-static"))
619+
)]
620+
#[link(name = "/defaultlib:libcmt", modifiers = "+verbatim", cfg(target_feature = "crt-static"))]
621+
extern "C" {}

library/core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@
178178
#![feature(ip_bits)]
179179
#![feature(is_ascii_octdigit)]
180180
#![feature(isqrt)]
181+
#![feature(link_cfg)]
181182
#![feature(maybe_uninit_uninit_array)]
182183
#![feature(non_null_convenience)]
183184
#![feature(offset_of_enum)]

library/panic_abort/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,7 @@ doc = false
1515
alloc = { path = "../alloc" }
1616
cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
1717
core = { path = "../core" }
18-
libc = { version = "0.2", default-features = false }
1918
compiler_builtins = "0.1.0"
19+
20+
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
21+
libc = { version = "0.2", default-features = false }

library/panic_unwind/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ doc = false
1414
[dependencies]
1515
alloc = { path = "../alloc" }
1616
core = { path = "../core" }
17-
libc = { version = "0.2", default-features = false }
1817
unwind = { path = "../unwind" }
1918
compiler_builtins = "0.1.0"
2019
cfg-if = "1.0"
20+
21+
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
22+
libc = { version = "0.2", default-features = false }

library/panic_unwind/src/seh.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@
4848

4949
use alloc::boxed::Box;
5050
use core::any::Any;
51+
use core::ffi::{c_int, c_uint, c_void};
5152
use core::mem::{self, ManuallyDrop};
5253
use core::ptr::{addr_of, addr_of_mut};
53-
use libc::{c_int, c_uint, c_void};
5454

5555
// NOTE(nbdd0121): The `canary` field is part of stable ABI.
5656
#[repr(C)]

library/std/Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
1717
panic_unwind = { path = "../panic_unwind", optional = true }
1818
panic_abort = { path = "../panic_abort" }
1919
core = { path = "../core", public = true }
20-
libc = { version = "0.2.153", default-features = false, features = ['rustc-dep-of-std'], public = true }
2120
compiler_builtins = { version = "0.1.105" }
2221
profiler_builtins = { path = "../profiler_builtins", optional = true }
2322
unwind = { path = "../unwind" }
@@ -31,6 +30,12 @@ rustc-demangle = { version = "0.1.21", features = ['rustc-dep-of-std'] }
3130
miniz_oxide = { version = "0.7.0", optional = true, default-features = false }
3231
addr2line = { version = "0.21.0", optional = true, default-features = false }
3332

33+
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
34+
libc = { version = "0.2.153", default-features = false, features = ['rustc-dep-of-std'], public = true }
35+
36+
[target.'cfg(all(windows, target_env = "msvc"))'.dependencies]
37+
libc = { version = "0.2.153", default-features = false }
38+
3439
[target.'cfg(all(not(target_os = "aix"), not(all(windows, target_env = "msvc", not(target_vendor = "uwp")))))'.dependencies]
3540
object = { version = "0.32.0", default-features = false, optional = true, features = ['read_core', 'elf', 'macho', 'pe', 'unaligned', 'archive'] }
3641

library/std/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,9 @@ extern crate test;
431431
#[allow(unused_imports)] // macros from `alloc` are not used on all platforms
432432
#[macro_use]
433433
extern crate alloc as alloc_crate;
434+
435+
// Many compiler tests depend on libc being pulled in by std
436+
// so include it here even if it's unused.
434437
#[doc(masked)]
435438
#[allow(unused_extern_crates)]
436439
extern crate libc;

library/std/src/os/unix/net/addr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::{fmt, io, mem, ptr};
1111
#[cfg(not(unix))]
1212
#[allow(non_camel_case_types)]
1313
mod libc {
14-
pub use libc::c_int;
14+
pub use core::ffi::c_int;
1515
pub type socklen_t = u32;
1616
pub struct sockaddr;
1717
#[derive(Clone)]

library/std/src/os/unix/net/ancillary.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::sys::net::Socket;
2020
))]
2121
#[allow(non_camel_case_types)]
2222
mod libc {
23-
pub use libc::c_int;
23+
pub use core::ffi::c_int;
2424
pub struct ucred;
2525
pub struct cmsghdr;
2626
pub struct sockcred2;

library/std/src/os/unix/net/datagram.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use libc::MSG_NOSIGNAL;
3434
target_os = "haiku",
3535
target_os = "nto",
3636
)))]
37-
const MSG_NOSIGNAL: libc::c_int = 0x0;
37+
const MSG_NOSIGNAL: core::ffi::c_int = 0x0;
3838

3939
/// A Unix datagram socket.
4040
///
@@ -317,7 +317,7 @@ impl UnixDatagram {
317317
fn recv_from_flags(
318318
&self,
319319
buf: &mut [u8],
320-
flags: libc::c_int,
320+
flags: core::ffi::c_int,
321321
) -> io::Result<(usize, SocketAddr)> {
322322
let mut count = 0;
323323
let addr = SocketAddr::new(|addr, len| unsafe {

0 commit comments

Comments
 (0)