diff --git a/qt/launcher/Cargo.toml b/qt/launcher/Cargo.toml
index fd6f2230c..32fb15991 100644
--- a/qt/launcher/Cargo.toml
+++ b/qt/launcher/Cargo.toml
@@ -14,6 +14,9 @@ anyhow.workspace = true
camino.workspace = true
dirs.workspace = true
+[target.'cfg(all(unix, not(target_os = "macos")))'.dependencies]
+libc.workspace = true
+
[target.'cfg(windows)'.dependencies]
windows.workspace = true
widestring.workspace = true
diff --git a/qt/launcher/mac/Info.plist b/qt/launcher/mac/Info.plist
index 59b67605f..6e19087d6 100644
--- a/qt/launcher/mac/Info.plist
+++ b/qt/launcher/mac/Info.plist
@@ -7,7 +7,7 @@
CFBundleShortVersionString
1.0
LSMinimumSystemVersion
- 11
+ 12
CFBundleDocumentTypes
diff --git a/qt/launcher/src/main.rs b/qt/launcher/src/main.rs
index c8cd7e052..2df5ccd15 100644
--- a/qt/launcher/src/main.rs
+++ b/qt/launcher/src/main.rs
@@ -22,6 +22,7 @@ use anki_process::CommandExt as AnkiCommandExt;
use anyhow::Context;
use anyhow::Result;
+use crate::platform::ensure_os_supported;
use crate::platform::ensure_terminal_shown;
use crate::platform::get_exe_and_resources_dirs;
use crate::platform::get_uv_binary_name;
@@ -143,6 +144,8 @@ fn run() -> Result<()> {
print!("\x1B[2J\x1B[H"); // Clear screen and move cursor to top
println!("\x1B[1mAnki Launcher\x1B[0m\n");
+ ensure_os_supported()?;
+
check_versions(&mut state);
main_menu_loop(&state)?;
diff --git a/qt/launcher/src/platform/mod.rs b/qt/launcher/src/platform/mod.rs
index bbb42df10..50a303656 100644
--- a/qt/launcher/src/platform/mod.rs
+++ b/qt/launcher/src/platform/mod.rs
@@ -128,3 +128,10 @@ pub fn ensure_terminal_shown() -> Result<()> {
print!("\x1b]2;Anki Launcher\x07");
Ok(())
}
+
+pub fn ensure_os_supported() -> Result<()> {
+ #[cfg(all(unix, not(target_os = "macos")))]
+ unix::ensure_glibc_supported()?;
+
+ Ok(())
+}
diff --git a/qt/launcher/src/platform/unix.rs b/qt/launcher/src/platform/unix.rs
index f37ec81eb..235919106 100644
--- a/qt/launcher/src/platform/unix.rs
+++ b/qt/launcher/src/platform/unix.rs
@@ -65,3 +65,34 @@ pub fn finalize_uninstall() {
let mut input = String::new();
let _ = stdin().read_line(&mut input);
}
+
+pub fn ensure_glibc_supported() -> Result<()> {
+ use std::ffi::CStr;
+ let get_glibc_version = || -> Option<(u32, u32)> {
+ let version_ptr = unsafe { libc::gnu_get_libc_version() };
+ if version_ptr.is_null() {
+ return None;
+ }
+
+ let version_cstr = unsafe { CStr::from_ptr(version_ptr) };
+ let version_str = version_cstr.to_str().ok()?;
+
+ // Parse version string (format: "2.36" or "2.36.1")
+ let version_parts: Vec<&str> = version_str.split('.').collect();
+ if version_parts.len() < 2 {
+ return None;
+ }
+
+ let major: u32 = version_parts[0].parse().ok()?;
+ let minor: u32 = version_parts[1].parse().ok()?;
+
+ Some((major, minor))
+ };
+
+ let (major, minor) = get_glibc_version().unwrap_or_default();
+ if major < 3 || (major == 2 && minor < 36) {
+ anyhow::bail!("Anki requires a modern Linux distro with glibc 2.36 or later.");
+ }
+
+ Ok(())
+}