Repository: rust-lang/rust
Pull request: Fix bootstrap rust build failure for vxworks

Fixes rust-lang/rust#153332 

Starting with VxWorks 25.09, struct stat was updated to use struct timespec instead of time_t for timestamp fields.

The following changes were made in libc in the commit [libc](https://github.com/rust-lang/libc/pull/4781). 

As a result, when performing a bootstrap build with VxWorks ≥ 25.09, libc no longer exposes the fields st_mtime, st_atime, and st_ctime, as they are conditionally compiled in src/vxworks/mod.rs here [libc](https://github.com/rust-lang/libc/blob/56caa81b6b433c49c5704bf0400a02d428cfacda/src/vxworks/mod.rs#L229). This causes the build to fail.

For VxWorks versions earlier than 25.09, the build completes successfully without errors.

This PR resolves the issue by detecting the WIND_RELEASE_ID environment variable (which is set in the VxWorks build environment) and conditionally guarding the affected functions in the two additional files where the errors originate.




Changed files:
filename: library/std/build.rs
patch: @@ -79,4 +79,28 @@ fn main() {
     println!("cargo:rustc-cfg=backtrace_in_libstd");
 
     println!("cargo:rustc-env=STD_ENV_ARCH={}", env::var("CARGO_CFG_TARGET_ARCH").unwrap());
+
+    println!("cargo:rustc-check-cfg=cfg(vxworks_lt_25_09)");
+
+    if target_os == "vxworks" {
+        match vxworks_version_code() {
+            Some((major, minor)) if (major, minor) < (25, 9) => {
+                println!("cargo:rustc-cfg=vxworks_lt_25_09");
+            }
+            _ => {}
+        }
+    }
+}
+
+/// Retrieve the VxWorks release version from the environment variable set by the VxWorks build
+/// environment, in `(minor, patch)` form.
+fn vxworks_version_code() -> Option<(u32, u32)> {
+    let version = env::var("WIND_RELEASE_ID").ok()?;
+
+    let mut pieces = version.trim().split(['.']);
+
+    let major: u32 = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0);
+    let minor: u32 = pieces.next().and_then(|x| x.parse().ok()).unwrap_or(0);
+
+    Some((major, minor))
 }

filename: library/std/src/os/vxworks/fs.rs
patch: @@ -69,24 +69,54 @@ impl MetadataExt for Metadata {
     fn st_size(&self) -> u64 {
         self.as_inner().as_inner().st_size as u64
     }
+    #[cfg(vxworks_lt_25_09)]
     fn st_atime(&self) -> i64 {
         self.as_inner().as_inner().st_atime as i64
     }
+    #[cfg(not(vxworks_lt_25_09))]
+    fn st_atime(&self) -> i64 {
+        self.as_inner().as_inner().st_atim.tv_sec as i64
+    }
+    #[cfg(vxworks_lt_25_09)]
     fn st_atime_nsec(&self) -> i64 {
         0
     }
+    #[cfg(not(vxworks_lt_25_09))]
+    fn st_atime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_atim.tv_nsec as i64
+    }
+    #[cfg(vxworks_lt_25_09)]
     fn st_mtime(&self) -> i64 {
         self.as_inner().as_inner().st_mtime as i64
     }
+    #[cfg(not(vxworks_lt_25_09))]
+    fn st_mtime(&self) -> i64 {
+        self.as_inner().as_inner().st_mtim.tv_sec as i64
+    }
+    #[cfg(vxworks_lt_25_09)]
     fn st_mtime_nsec(&self) -> i64 {
         0
     }
+    #[cfg(not(vxworks_lt_25_09))]
+    fn st_mtime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_mtim.tv_nsec as i64
+    }
+    #[cfg(vxworks_lt_25_09)]
     fn st_ctime(&self) -> i64 {
         self.as_inner().as_inner().st_ctime as i64
     }
+    #[cfg(not(vxworks_lt_25_09))]
+    fn st_ctime(&self) -> i64 {
+        self.as_inner().as_inner().st_ctim.tv_sec as i64
+    }
+    #[cfg(vxworks_lt_25_09)]
     fn st_ctime_nsec(&self) -> i64 {
         0
     }
+    #[cfg(not(vxworks_lt_25_09))]
+    fn st_ctime_nsec(&self) -> i64 {
+        self.as_inner().as_inner().st_ctim.tv_nsec as i64
+    }
     fn st_blksize(&self) -> u64 {
         self.as_inner().as_inner().st_blksize as u64
     }

filename: library/std/src/sys/fs/unix.rs
patch: @@ -634,7 +634,7 @@ impl FileAttr {
     }
 
     #[cfg(any(
-        target_os = "vxworks",
+        all(target_os = "vxworks", vxworks_lt_25_09),
         target_os = "espidf",
         target_os = "vita",
         target_os = "rtems",
@@ -643,7 +643,12 @@ impl FileAttr {
         SystemTime::new(self.stat.st_mtime as i64, 0)
     }
 
-    #[cfg(any(target_os = "horizon", target_os = "hurd", target_os = "nuttx"))]
+    #[cfg(any(
+        target_os = "horizon",
+        target_os = "hurd",
+        target_os = "nuttx",
+        all(target_os = "vxworks", not(vxworks_lt_25_09))
+    ))]
     pub fn modified(&self) -> io::Result<SystemTime> {
         SystemTime::new(self.stat.st_mtim.tv_sec as i64, self.stat.st_mtim.tv_nsec as i64)
     }
@@ -669,7 +674,7 @@ impl FileAttr {
     }
 
     #[cfg(any(
-        target_os = "vxworks",
+        all(target_os = "vxworks", vxworks_lt_25_09),
         target_os = "espidf",
         target_os = "vita",
         target_os = "rtems"
@@ -678,7 +683,12 @@ impl FileAttr {
         SystemTime::new(self.stat.st_atime as i64, 0)
     }
 
-    #[cfg(any(target_os = "horizon", target_os = "hurd", target_os = "nuttx"))]
+    #[cfg(any(
+        target_os = "horizon",
+        target_os = "hurd",
+        target_os = "nuttx",
+        all(target_os = "vxworks", not(vxworks_lt_25_09))
+    ))]
     pub fn accessed(&self) -> io::Result<SystemTime> {
         SystemTime::new(self.stat.st_atim.tv_sec as i64, self.stat.st_atim.tv_nsec as i64)
     }

filename: src/doc/rustc/src/platform-support/vxworks.md
patch: @@ -28,6 +28,12 @@ Target triplets available:
 
 The minimum supported version is VxWorks 7.
 
+### Environment
+
+#### `WIND_RELEASE_ID`
+
+In VxWorks build environment, the environment variable `WIND_RELEASE_ID` indicates the VxWorks release version used for the build. The `WIND_RELEASE_ID` can be used to conditionally compile features/code or handle version specific behaviour.
+
 ## Building
 
 Rust for each target can be cross-compiled with its specific target vsb configuration. Std support is added but not yet fully tested.