Skip to content

Commit 129b056

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 129b056

3 files changed

Lines changed: 34 additions & 5 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: 23 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,27 @@ fn test_windows(target: &str) {
784785
}
785786
cfg.define("_WIN32_WINNT", Some("0x8000"));
786787

788+
let redirect_time_t = if gnu && i686 {
789+
if let Ok(v) = env::var("CARGO_CFG_LIBC_UNSTABLE_GNU_TIME_BITS") {
790+
assert_matches!(
791+
v.as_str(),
792+
"32" | "64",
793+
"Invalid value for `libc_unstable_gnu_time_bits`. Must be 32, 64 or unset."
794+
);
795+
796+
if v == "64" {
797+
cfg.cfg("gnu_time_bits64", None);
798+
true
799+
} else {
800+
false
801+
}
802+
} else {
803+
false
804+
}
805+
} else {
806+
false
807+
};
808+
787809
headers!(
788810
cfg,
789811
"direct.h",
@@ -841,7 +863,7 @@ fn test_windows(target: &str) {
841863
"SSIZE_T" if !gnu => true,
842864
"ssize_t" if !gnu => true,
843865
// FIXME(windows): The size and alignment of this type are incorrect
844-
"time_t" if gnu && i686 => true,
866+
"time_t" if gnu && i686 && !redirect_time_t => true,
845867
_ => false,
846868
});
847869

src/windows/mod.rs

Lines changed: 7 additions & 1 deletion
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;

0 commit comments

Comments
 (0)