Skip to content

Commit fc36273

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 not the same default as in C. This `cfg` exposes the same default as in C.
1 parent ed3a6f9 commit fc36273

4 files changed

Lines changed: 39 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 x86 Windows with
28+
// GNU to expose a 64-bit `time_t`.
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: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,23 @@ fn test_windows(target: &str) {
784784
}
785785
cfg.define("_WIN32_WINNT", Some("0x8000"));
786786

787+
let win_gnu_x86_time64 = match env::var("CARGO_CFG_LIBC_UNSTABLE_GNU_TIME_BITS") {
788+
Ok(v) if v == "64" => true,
789+
Ok(v) if v == "32" => false,
790+
Ok(_) => {
791+
panic!("Invalid value for `libc_unstable_gnu_time_bits`. Must be 32, 64 or unset.");
792+
}
793+
Err(_) => false,
794+
};
795+
796+
// Needed for the Windows `time_t` test.
797+
println!("cargo::rustc-check-cfg=cfg(gnu_time_bits64)");
798+
799+
if i686 && gnu && win_gnu_x86_time64 {
800+
cfg.cfg("gnu_time_bits64", None);
801+
println!("cargo::rustc-cfg=gnu_time_bits64");
802+
}
803+
787804
headers!(
788805
cfg,
789806
"direct.h",
@@ -841,7 +858,7 @@ fn test_windows(target: &str) {
841858
"SSIZE_T" if !gnu => true,
842859
"ssize_t" if !gnu => true,
843860
// FIXME(windows): The size and alignment of this type are incorrect
844-
"time_t" if gnu && i686 => true,
861+
"time_t" if gnu && i686 && !win_gnu_x86_time64 => true,
845862
_ => false,
846863
});
847864

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)