Skip to content

Commit f2ab613

Browse files
committed
Use cfg_os_version_min in std
1 parent 6125af0 commit f2ab613

File tree

7 files changed

+178
-68
lines changed

7 files changed

+178
-68
lines changed

library/std/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@
281281
#![feature(cfg_sanitizer_cfi)]
282282
#![feature(cfg_target_thread_local)]
283283
#![feature(cfi_encoding)]
284+
#![feature(cfg_boolean_literals)]
285+
#![cfg_attr(not(bootstrap), feature(cfg_os_version_min))]
284286
#![feature(concat_idents)]
285287
#![feature(decl_macro)]
286288
#![feature(deprecated_suggestion)]

library/std/src/sys/pal/unix/fd.rs

Lines changed: 72 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,15 @@ impl FileDesc {
252252

253253
#[cfg(all(target_os = "android", target_pointer_width = "32"))]
254254
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
255-
super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
255+
super::weak::maybe_weak!(
256+
#[cfg_always_available_on(false)]
257+
fn preadv64(
258+
fd: libc::c_int,
259+
iov: *const libc::iovec,
260+
iovcnt: libc::c_int,
261+
offset: off64_t,
262+
) -> isize;
263+
);
256264

257265
match preadv64.get() {
258266
Some(preadv) => {
@@ -281,7 +289,33 @@ impl FileDesc {
281289
// use "weak" linking.
282290
#[cfg(target_vendor = "apple")]
283291
pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
284-
super::weak::weak!(fn preadv(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
292+
#[cfg(not(bootstrap))]
293+
super::weak::maybe_weak!(
294+
#[cfg_always_available_on(any(
295+
os_version_min("macos", "11.0"),
296+
os_version_min("ios", "14.0"),
297+
os_version_min("tvos", "14.0"),
298+
os_version_min("watchos", "7.0"),
299+
os_version_min("visionos", "1.0"),
300+
))]
301+
fn preadv(
302+
fd: libc::c_int,
303+
iov: *const libc::iovec,
304+
iovcnt: libc::c_int,
305+
offset: off64_t,
306+
) -> isize;
307+
);
308+
309+
#[cfg(bootstrap)]
310+
super::weak::maybe_weak!(
311+
#[cfg_always_available_on(false)]
312+
fn preadv(
313+
fd: libc::c_int,
314+
iov: *const libc::iovec,
315+
iovcnt: libc::c_int,
316+
offset: off64_t,
317+
) -> isize;
318+
);
285319

286320
match preadv.get() {
287321
Some(preadv) => {
@@ -445,7 +479,15 @@ impl FileDesc {
445479

446480
#[cfg(all(target_os = "android", target_pointer_width = "32"))]
447481
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
448-
super::weak::weak!(fn pwritev64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
482+
super::weak::maybe_weak!(
483+
#[cfg_always_available_on(false)]
484+
fn pwritev64(
485+
fd: libc::c_int,
486+
iov: *const libc::iovec,
487+
iovcnt: libc::c_int,
488+
offset: off64_t,
489+
) -> isize;
490+
);
449491

450492
match pwritev64.get() {
451493
Some(pwritev) => {
@@ -463,18 +505,35 @@ impl FileDesc {
463505
}
464506
}
465507

466-
// We support old MacOS, iOS, watchOS, tvOS and visionOS. `pwritev` was added in the following
467-
// Apple OS versions:
468-
// ios 14.0
469-
// tvos 14.0
470-
// macos 11.0
471-
// watchos 7.0
472-
//
473-
// These versions may be newer than the minimum supported versions of OS's we support so we must
474-
// use "weak" linking.
475508
#[cfg(target_vendor = "apple")]
476509
pub fn write_vectored_at(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
477-
super::weak::weak!(fn pwritev(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
510+
#[cfg(not(bootstrap))]
511+
super::weak::maybe_weak!(
512+
#[cfg_always_available_on(any(
513+
os_version_min("macos", "11.0"),
514+
os_version_min("ios", "14.0"),
515+
os_version_min("tvos", "14.0"),
516+
os_version_min("watchos", "7.0"),
517+
os_version_min("visionos", "1.0"),
518+
))]
519+
fn pwritev(
520+
fd: libc::c_int,
521+
iov: *const libc::iovec,
522+
iovcnt: libc::c_int,
523+
offset: off64_t,
524+
) -> isize;
525+
);
526+
527+
#[cfg(bootstrap)]
528+
super::weak::maybe_weak!(
529+
#[cfg_always_available_on(false)]
530+
fn pwritev(
531+
fd: libc::c_int,
532+
iov: *const libc::iovec,
533+
iovcnt: libc::c_int,
534+
offset: off64_t,
535+
) -> isize;
536+
);
478537

479538
match pwritev.get() {
480539
Some(pwritev) => {

library/std/src/sys/pal/unix/fs.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ use crate::sync::Arc;
8080
use crate::sys::common::small_c_string::run_path_with_cstr;
8181
use crate::sys::fd::FileDesc;
8282
use crate::sys::time::SystemTime;
83+
#[cfg(target_os = "android")]
84+
use crate::sys::weak::maybe_weak;
8385
#[cfg(all(target_os = "linux", target_env = "gnu"))]
8486
use crate::sys::weak::syscall;
85-
#[cfg(target_os = "android")]
86-
use crate::sys::weak::weak;
8787
use crate::sys::{cvt, cvt_r};
8888
pub use crate::sys_common::fs::exists;
8989
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
@@ -1508,9 +1508,13 @@ impl File {
15081508
Ok(())
15091509
} else if #[cfg(target_os = "android")] {
15101510
let times = [to_timespec(times.accessed)?, to_timespec(times.modified)?];
1511-
// futimens requires Android API level 19
15121511
cvt(unsafe {
1513-
weak!(fn futimens(c_int, *const libc::timespec) -> c_int);
1512+
maybe_weak!(
1513+
// FIXME: Once `os_version_min` supports Android, mark this as available on
1514+
// Android API level 19.
1515+
#[cfg_always_available_on(false)]
1516+
fn futimens(c_int, *const libc::timespec) -> c_int;
1517+
);
15141518
match futimens.get() {
15151519
Some(futimens) => futimens(self.as_raw_fd(), times.as_ptr()),
15161520
None => return Err(io::const_error!(
@@ -1523,10 +1527,14 @@ impl File {
15231527
} else {
15241528
#[cfg(all(target_os = "linux", target_env = "gnu", target_pointer_width = "32", not(target_arch = "riscv32")))]
15251529
{
1526-
use crate::sys::{time::__timespec64, weak::weak};
1527-
1528-
// Added in glibc 2.34
1529-
weak!(fn __futimens64(libc::c_int, *const __timespec64) -> libc::c_int);
1530+
use crate::sys::{time::__timespec64, weak::maybe_weak};
1531+
1532+
maybe_weak!(
1533+
// FIXME: Once `os_version_min` supports glibc, mark this as availabe on
1534+
// glibc 2.34.
1535+
#[cfg_always_available_on(false)]
1536+
fn __futimens64(libc::c_int, *const __timespec64) -> libc::c_int;
1537+
);
15301538

15311539
if let Some(futimens64) = __futimens64.get() {
15321540
let to_timespec = |time: Option<SystemTime>| time.map(|time| time.t.to_timespec64())

library/std/src/sys/pal/unix/process/process_unix.rs

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -454,20 +454,24 @@ impl Command {
454454

455455
cfg_if::cfg_if! {
456456
if #[cfg(target_os = "linux")] {
457-
use crate::sys::weak::weak;
457+
use crate::sys::weak::maybe_weak;
458458

459-
weak! {
459+
maybe_weak!(
460+
#[cfg_always_available_on(false)]
460461
fn pidfd_spawnp(
461-
*mut libc::c_int,
462-
*const libc::c_char,
463-
*const libc::posix_spawn_file_actions_t,
464-
*const libc::posix_spawnattr_t,
465-
*const *mut libc::c_char,
466-
*const *mut libc::c_char
467-
) -> libc::c_int
468-
}
462+
pidfd: *mut libc::c_int,
463+
path: *const libc::c_char,
464+
file_actions: *const libc::posix_spawn_file_actions_t,
465+
attrp: *const libc::posix_spawnattr_t,
466+
argv: *const *mut libc::c_char,
467+
envp: *const *mut libc::c_char,
468+
) -> libc::c_int;
469+
);
469470

470-
weak! { fn pidfd_getpid(libc::c_int) -> libc::c_int }
471+
maybe_weak!(
472+
#[cfg_always_available_on(false)]
473+
fn pidfd_getpid(fd: libc::c_int) -> libc::c_int;
474+
);
471475

472476
static PIDFD_SUPPORTED: AtomicU8 = AtomicU8::new(0);
473477
const UNKNOWN: u8 = 0;
@@ -575,38 +579,30 @@ impl Command {
575579
) -> libc::c_int;
576580

577581
/// Get the function pointer for adding a chdir action to a
578-
/// `posix_spawn_file_actions_t`, if available, assuming a dynamic libc.
582+
/// `posix_spawn_file_actions_t`, if available.
579583
///
580584
/// Some platforms can set a new working directory for a spawned process in the
581585
/// `posix_spawn` path. This function looks up the function pointer for adding
582586
/// such an action to a `posix_spawn_file_actions_t` struct.
583-
#[cfg(not(all(target_os = "linux", target_env = "musl")))]
584587
fn get_posix_spawn_addchdir() -> Option<PosixSpawnAddChdirFn> {
585-
use crate::sys::weak::weak;
586-
587-
weak! {
588+
use crate::sys::weak::maybe_weak;
589+
590+
maybe_weak!(
591+
// Weak symbol lookup doesn't work with statically linked libcs, so in cases
592+
// where static linking is possible we need to either check for the presence
593+
// of the symbol at compile time or know about it upfront.
594+
//
595+
// Our minimum required musl supports this function, so we can just use it.
596+
#[cfg_always_available_on(all(target_os = "linux", target_env = "musl"))]
588597
fn posix_spawn_file_actions_addchdir_np(
589-
*mut libc::posix_spawn_file_actions_t,
590-
*const libc::c_char
591-
) -> libc::c_int
592-
}
598+
file_actions: *mut libc::posix_spawn_file_actions_t,
599+
path: *const libc::c_char,
600+
) -> libc::c_int;
601+
);
593602

594603
posix_spawn_file_actions_addchdir_np.get()
595604
}
596605

597-
/// Get the function pointer for adding a chdir action to a
598-
/// `posix_spawn_file_actions_t`, if available, on platforms where the function
599-
/// is known to exist.
600-
///
601-
/// Weak symbol lookup doesn't work with statically linked libcs, so in cases
602-
/// where static linking is possible we need to either check for the presence
603-
/// of the symbol at compile time or know about it upfront.
604-
#[cfg(all(target_os = "linux", target_env = "musl"))]
605-
fn get_posix_spawn_addchdir() -> Option<PosixSpawnAddChdirFn> {
606-
// Our minimum required musl supports this function, so we can just use it.
607-
Some(libc::posix_spawn_file_actions_addchdir_np)
608-
}
609-
610606
let addchdir = match self.get_cwd() {
611607
Some(cwd) => {
612608
if cfg!(target_vendor = "apple") {

library/std/src/sys/pal/unix/thread.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::num::NonZero;
44
#[cfg(all(target_os = "linux", target_env = "gnu"))]
55
use crate::sys::weak::dlsym;
66
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto",))]
7-
use crate::sys::weak::weak;
7+
use crate::sys::weak::maybe_weak;
88
use crate::sys::{os, stack_overflow};
99
use crate::time::Duration;
1010
use crate::{cmp, io, ptr};
@@ -186,11 +186,13 @@ impl Thread {
186186

187187
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))]
188188
pub fn set_name(name: &CStr) {
189-
weak! {
189+
maybe_weak!(
190+
#[cfg_always_available_on(false)]
190191
fn pthread_setname_np(
191-
libc::pthread_t, *const libc::c_char
192-
) -> libc::c_int
193-
}
192+
thread: libc::pthread_t,
193+
name: *const libc::c_char,
194+
) -> libc::c_int;
195+
);
194196

195197
if let Some(f) = pthread_setname_np.get() {
196198
#[cfg(target_os = "nto")]

library/std/src/sys/pal/unix/time.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,11 +108,18 @@ impl Timespec {
108108
not(target_arch = "riscv32")
109109
))]
110110
{
111-
use crate::sys::weak::weak;
111+
use crate::sys::weak::maybe_weak;
112112

113113
// __clock_gettime64 was added to 32-bit arches in glibc 2.34,
114114
// and it handles both vDSO calls and ENOSYS fallbacks itself.
115-
weak!(fn __clock_gettime64(libc::clockid_t, *mut __timespec64) -> libc::c_int);
115+
maybe_weak!(
116+
// FIXME: Mark with `os_version_min` once that supports glibc.
117+
#[cfg_always_available_on(false)]
118+
fn __clock_gettime64(
119+
clock_id: libc::clockid_t,
120+
tp: *mut __timespec64,
121+
) -> libc::c_int;
122+
);
116123

117124
if let Some(clock_gettime64) = __clock_gettime64.get() {
118125
let mut t = MaybeUninit::uninit();

library/std/src/sys/pal/unix/weak.rs

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
// There are a variety of `#[cfg]`s controlling which targets are involved in
2020
// each instance of `weak!` and `syscall!`. Rather than trying to unify all of
2121
// that, we'll just allow that some unix targets don't use this module at all.
22-
#![allow(dead_code, unused_macros)]
22+
#![allow(dead_code, unused_macros, unused_imports)]
2323

2424
use crate::ffi::CStr;
2525
use crate::marker::PhantomData;
@@ -28,11 +28,12 @@ use crate::{mem, ptr};
2828

2929
// We can use true weak linkage on ELF targets.
3030
#[cfg(all(unix, not(target_vendor = "apple")))]
31-
pub(crate) macro weak {
32-
(fn $name:ident($($t:ty),*) -> $ret:ty) => (
31+
pub(crate) macro weak_impl {
32+
(fn $name:ident($($t:ty),*) -> $ret:ty $(, $sym:expr)?) => (
3333
let ref $name: ExternWeak<unsafe extern "C" fn($($t),*) -> $ret> = {
3434
unsafe extern "C" {
3535
#[linkage = "extern_weak"]
36+
$(#[link_name = $sym])?
3637
static $name: Option<unsafe extern "C" fn($($t),*) -> $ret>;
3738
}
3839
#[allow(unused_unsafe)]
@@ -41,9 +42,44 @@ pub(crate) macro weak {
4142
)
4243
}
4344

44-
// On non-ELF targets, use the dlsym approximation of weak linkage.
45+
// On Apple targets, we use `dlsym` instead of real weak linkage, since that requires an Xcode SDK
46+
// with the item available in `*.tbd` files for the linker, and we support compiling and linking
47+
// the standard library with older Xcode versions.
4548
#[cfg(target_vendor = "apple")]
46-
pub(crate) use self::dlsym as weak;
49+
pub(crate) use dlsym as weak_impl;
50+
51+
/// Try to use the symbol directly if always available, and fall back to weak linking if not.
52+
pub(crate) macro maybe_weak {
53+
{
54+
#[cfg_always_available_on($($cfg:tt)*)]
55+
$(#[link_name = $sym:expr])?
56+
fn $name:ident($($param:ident : $t:ty),* $(,)?) -> $ret:ty;
57+
} => {
58+
// If the symbol is known to be available at compile-time, use it directly.
59+
#[cfg($($cfg)*)]
60+
let $name = {
61+
extern "C" {
62+
$(#[link_name = $sym])?
63+
fn $name($($param : $t),*) -> $ret;
64+
}
65+
Known($name)
66+
};
67+
68+
// Otherwise it needs to be weakly linked.
69+
#[cfg(not($($cfg)*))]
70+
weak_impl!(fn $name($($t),*) -> $ret $(, $sym)?);
71+
}
72+
}
73+
74+
/// The function is statically known here.
75+
pub(crate) struct Known<F>(F);
76+
77+
impl<F: Copy> Known<F> {
78+
#[inline]
79+
pub(crate) fn get(&self) -> Option<F> {
80+
Some(self.0)
81+
}
82+
}
4783

4884
pub(crate) struct ExternWeak<F: Copy> {
4985
weak_ptr: Option<F>,
@@ -145,7 +181,7 @@ unsafe fn fetch(name: &str) -> *mut libc::c_void {
145181
pub(crate) macro syscall {
146182
(fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
147183
unsafe fn $name($($arg_name: $t),*) -> $ret {
148-
weak! { fn $name($($t),*) -> $ret }
184+
weak_impl! { fn $name($($t),*) -> $ret }
149185

150186
if let Some(fun) = $name.get() {
151187
fun($($arg_name),*)
@@ -161,7 +197,7 @@ pub(crate) macro syscall {
161197
pub(crate) macro syscall {
162198
(fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
163199
unsafe fn $name($($arg_name:$t),*) -> $ret {
164-
weak! { fn $name($($t),*) -> $ret }
200+
weak_impl! { fn $name($($t),*) -> $ret }
165201

166202
// Use a weak symbol from libc when possible, allowing `LD_PRELOAD`
167203
// interposition, but if it's not found just use a raw syscall.

0 commit comments

Comments
 (0)