Skip to content

Commit 50299b1

Browse files
committed
windows: expose cfg for 64-bit time_t
Use `gnu_time_bits64` on Windows x86 GNU to expose a 64-bit `time_t`. `time_t` is always 64-bits on Windows. The target environment matters not. There's a feature test macro to make it 32-bits wide. In `libc` we expose it as 32-bits in Windows x86 GNU. This is wrong. Folks need to experiment with correct behavior. The 32-bit routines are linked in that case.
1 parent ed3a6f9 commit 50299b1

4 files changed

Lines changed: 48 additions & 7 deletions

File tree

build.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ const ALLOWED_CFGS: &[&str] = &[
2424
"freebsd15",
2525
// Corresponds to `_FILE_OFFSET_BITS=64` in glibc
2626
"gnu_file_offset_bits64",
27-
// Corresponds to `_TIME_BITS=64` in glibc
27+
// Corresponds to `_TIME_BITS=64` in glibc. Also used in Windows to fix
28+
// faulty `time_t` bindings.
2829
"gnu_time_bits64",
2930
"libc_deny_warnings",
3031
// Corresponds to `__USE_TIME_BITS64` in UAPI
@@ -144,7 +145,7 @@ fn main() {
144145
}
145146

146147
if target_env == "gnu"
147-
&& target_os == "linux"
148+
&& matches!(target_os.as_str(), "linux" | "windows")
148149
&& target_ptr_width == "32"
149150
&& target_arch != "riscv32"
150151
&& target_arch != "x86_64"
@@ -173,7 +174,7 @@ fn main() {
173174
let (timebits, filebits) = match (tb_env.as_deref(), fb_env.as_deref()) {
174175
(Ok(_), Ok(_)) => panic!(
175176
"Do not set both libc_unstable_gnu_time_bits and \
176-
libc_unstable_gnu_file_offset_bits"
177+
libc_unstable_gnu_file_offset_bits"
177178
),
178179
(Err(_), Err(_)) => (defaultbits, defaultbits),
179180
(Ok(tb), Err(_)) if tb == "64" => (tb, tb),

libc-test/build.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::path::{
1212
PathBuf,
1313
};
1414
use std::{
15+
assert_matches,
1516
env,
1617
io,
1718
};
@@ -784,6 +785,31 @@ fn test_windows(target: &str) {
784785
}
785786
cfg.define("_WIN32_WINNT", Some("0x8000"));
786787

788+
// Needed for the Windows `time_t` test.
789+
println!("cargo::rustc-check-cfg=cfg(gnu_time_bits64)");
790+
791+
let redirect_time_t = if gnu && i686 {
792+
if let Ok(v) = env::var("CARGO_CFG_LIBC_UNSTABLE_GNU_TIME_BITS") {
793+
assert_matches!(
794+
v.as_str(),
795+
"32" | "64",
796+
"Invalid value for `libc_unstable_gnu_time_bits`. Must be 32, 64 or unset."
797+
);
798+
799+
if v == "64" {
800+
cfg.cfg("gnu_time_bits64", None);
801+
println!("cargo::rustc-cfg=gnu_time_bits64");
802+
true
803+
} else {
804+
false
805+
}
806+
} else {
807+
false
808+
}
809+
} else {
810+
false
811+
};
812+
787813
headers!(
788814
cfg,
789815
"direct.h",
@@ -841,7 +867,7 @@ fn test_windows(target: &str) {
841867
"SSIZE_T" if !gnu => true,
842868
"ssize_t" if !gnu => true,
843869
// FIXME(windows): The size and alignment of this type are incorrect
844-
"time_t" if gnu && i686 => true,
870+
"time_t" if gnu && i686 && !redirect_time_t => true,
845871
_ => false,
846872
});
847873

libc-test/tests/windows_time.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@
1111
/// functions that expect it as a parameter.
1212
#[test]
1313
fn test_bitwidth_store() {
14-
if cfg!(all(target_arch = "x86", target_env = "gnu")) {
14+
if cfg!(all(
15+
target_arch = "x86",
16+
target_env = "gnu",
17+
not(gnu_time_bits64),
18+
)) {
1519
assert_eq!(size_of::<libc::time_t>(), 4);
1620
} else {
1721
assert_eq!(size_of::<libc::time_t>(), 8);

src/windows/mod.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@ pub type clock_t = i32;
1919
pub type errno_t = c_int;
2020

2121
cfg_if! {
22-
if #[cfg(all(target_arch = "x86", target_env = "gnu"))] {
22+
// FIXME(1.0): Windows GNU has 64-bit `time_t` by default. In x86 this is
23+
// wrongly bound.
24+
if #[cfg(all(
25+
target_arch = "x86",
26+
target_env = "gnu",
27+
not(gnu_time_bits64)
28+
))] {
2329
pub type time_t = i32;
2430
} else {
2531
pub type time_t = i64;
@@ -395,7 +401,11 @@ extern "C" {
395401
// Under Windows x86 with GNU, `time_t` is still 32-bit wide on stable, so
396402
// these routines have to link with their 32-bit variants.
397403
cfg_if! {
398-
if #[cfg(all(target_arch = "x86", target_env = "gnu"))] {
404+
if #[cfg(all(
405+
target_arch = "x86",
406+
target_env = "gnu",
407+
not(gnu_time_bits64),
408+
))] {
399409
#[link_name = "_ctime32"]
400410
pub fn ctime(sourceTime: *const time_t) -> *mut c_char;
401411
#[link_name = "_difftime32"]

0 commit comments

Comments
 (0)