diff --git a/cimery/crates/viewer/build.rs b/cimery/crates/viewer/build.rs new file mode 100644 index 0000000..80e5850 --- /dev/null +++ b/cimery/crates/viewer/build.rs @@ -0,0 +1,45 @@ +//! 빌드 타임스탬프를 환경변수 BUILD_TIMESTAMP 로 내보냄. +//! `env!("BUILD_TIMESTAMP")` 로 소비. 사용자가 실행 중인 바이너리가 최신 빌드인지 +//! 타이틀 바에서 즉시 확인할 수 있게 함. + +use std::process::Command; + +fn main() { + // 항상 재실행 → 타임스탬프가 매 빌드마다 갱신. + println!("cargo:rerun-if-changed=build.rs"); + println!("cargo:rerun-if-changed=src"); + + let ts = current_timestamp(); + println!("cargo:rustc-env=BUILD_TIMESTAMP={}", ts); +} + +fn current_timestamp() -> String { + // Windows: PowerShell / Unix: date. 실패 시 epoch 초. + #[cfg(target_os = "windows")] + let out = Command::new("powershell") + .args([ + "-NoProfile", + "-Command", + "Get-Date -Format 'yyyy-MM-dd HH:mm:ss'", + ]) + .output(); + + #[cfg(not(target_os = "windows"))] + let out = Command::new("date").args(["+%Y-%m-%d %H:%M:%S"]).output(); + + if let Ok(o) = out { + if o.status.success() { + let s = String::from_utf8_lossy(&o.stdout).trim().to_string(); + if !s.is_empty() { + return s; + } + } + } + // 폴백: Unix epoch 초 + use std::time::{SystemTime, UNIX_EPOCH}; + let secs = SystemTime::now() + .duration_since(UNIX_EPOCH) + .map(|d| d.as_secs()) + .unwrap_or(0); + format!("epoch-{secs}") +} diff --git a/cimery/crates/viewer/src/lib.rs b/cimery/crates/viewer/src/lib.rs index c833f74..37aa6d3 100644 --- a/cimery/crates/viewer/src/lib.rs +++ b/cimery/crates/viewer/src/lib.rs @@ -882,14 +882,16 @@ impl Default for CimeryApp { fn default() -> Self { Self::new() } } +/// 빌드 타임스탬프 (build.rs 에서 주입). 타이틀에 표시해서 사용자가 실행 중인 +/// 바이너리가 최신 빌드인지 즉시 확인 가능. +const BUILD_TS: &str = env!("BUILD_TIMESTAMP"); + impl ApplicationHandler for CimeryApp { fn resumed(&mut self, event_loop: &ActiveEventLoop) { + let kernel = if cfg!(feature = "occt") { "OcctKernel" } else { "PureRustKernel" }; + let title = format!("cimery viewer [{kernel}] — build {BUILD_TS}"); let attrs = Window::default_attributes() - .with_title(if cfg!(feature = "occt") { - "cimery viewer [Sprint 4 — Full Bridge / OcctKernel]" - } else { - "cimery viewer [Sprint 4 — Full Bridge / PureRustKernel]" - }) + .with_title(title) .with_inner_size(winit::dpi::LogicalSize::new(1280u32, 720u32)); let window = Arc::new( event_loop.create_window(attrs).expect("create window"),