aboutsummaryrefslogtreecommitdiff
path: root/crates/ghostty-vt/build.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ghostty-vt/build.rs')
-rw-r--r--crates/ghostty-vt/build.rs137
1 files changed, 137 insertions, 0 deletions
diff --git a/crates/ghostty-vt/build.rs b/crates/ghostty-vt/build.rs
new file mode 100644
index 00000000..af02e0a7
--- /dev/null
+++ b/crates/ghostty-vt/build.rs
@@ -0,0 +1,137 @@
+use std::env;
+use std::fs;
+use std::path::PathBuf;
+use std::process::Command;
+
+fn zig_target(target: &str) -> &str {
+ match target {
+ "x86_64-unknown-linux-gnu" => "x86_64-linux-gnu",
+ "aarch64-unknown-linux-gnu" => "aarch64-linux-gnu",
+ "x86_64-unknown-linux-musl" => "x86_64-linux-musl",
+ "aarch64-unknown-linux-musl" => "aarch64-linux-musl",
+ "x86_64-apple-darwin" => "x86_64-macos",
+ "aarch64-apple-darwin" => "aarch64-macos",
+ "aarch64-apple-ios" => "aarch64-ios",
+ "aarch64-apple-ios-sim" => "aarch64-ios-simulator",
+ "x86_64-pc-windows-msvc" => "x86_64-windows-msvc",
+ "aarch64-pc-windows-msvc" => "aarch64-windows-msvc",
+ other => panic!("unsupported target for libghostty-vt build: {other}"),
+ }
+}
+
+fn env_bool(name: &str) -> Option<bool> {
+ match env::var(name) {
+ Ok(value) => match value.to_ascii_lowercase().as_str() {
+ "1" | "true" | "yes" | "on" => Some(true),
+ "0" | "false" | "no" | "off" => Some(false),
+ other => panic!("invalid boolean value for {name}: {other}"),
+ },
+ Err(env::VarError::NotPresent) => None,
+ Err(err) => panic!("failed to read {name}: {err}"),
+ }
+}
+
+fn main() {
+ // The vendored source stays at the repository root, shared with its maintenance scripts.
+ let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR"));
+ let vendor_dir = manifest_dir.join("../../vendor");
+ let vendored_dir = vendor_dir.join("libghostty-vt");
+
+ println!("cargo:rerun-if-changed=build.rs");
+ for path in [
+ vendor_dir.join("libghostty-vt.vendor.json"),
+ vendored_dir.join("build.zig"),
+ vendored_dir.join("build.zig.zon"),
+ vendored_dir.join("include"),
+ vendored_dir.join("pkg"),
+ vendored_dir.join("src"),
+ vendored_dir.join("VERSION"),
+ ] {
+ println!("cargo:rerun-if-changed={}", path.display());
+ }
+ println!("cargo:rerun-if-env-changed=LIBGHOSTTY_VT_OPTIMIZE");
+ println!("cargo:rerun-if-env-changed=LIBGHOSTTY_VT_SIMD");
+ println!("cargo:rerun-if-env-changed=LIBGHOSTTY_VT_ZIG_SYSTEM_DIR");
+ println!("cargo:rerun-if-env-changed=ZIG");
+ println!("cargo:rerun-if-env-changed=LIBGHOSTTY_VT_WINDOWS_LIBC");
+
+ let optimize = env::var("LIBGHOSTTY_VT_OPTIMIZE").unwrap_or_else(|_| "ReleaseFast".into());
+ let simd = env_bool("LIBGHOSTTY_VT_SIMD").unwrap_or(true);
+ let target = env::var("TARGET").expect("TARGET");
+ let zig_target = zig_target(&target);
+ let version_string = fs::read_to_string(vendored_dir.join("VERSION"))
+ .expect("failed to read vendored libghostty-vt VERSION")
+ .trim()
+ .to_string();
+
+ // Install into this build's OUT_DIR so concurrent builds for different targets
+ // from one checkout never link each other's archive.
+ let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR"));
+ let zig_prefix = out_dir.join("zig-out");
+
+ let zig = env::var("ZIG").unwrap_or_else(|_| "zig".into());
+ let mut command = Command::new(&zig);
+ command
+ .arg("build")
+ .arg("--prefix")
+ .arg(&zig_prefix)
+ .arg("-Demit-lib-vt")
+ .arg(format!("-Doptimize={optimize}"))
+ .arg(format!("-Dsimd={simd}"))
+ .arg(format!("-Dtarget={zig_target}"))
+ .arg(format!("-Dversion-string={version_string}"))
+ .arg("-Demit-xcframework=false");
+ if target.ends_with("windows-msvc") {
+ if let Some(libc_file) = env::var_os("LIBGHOSTTY_VT_WINDOWS_LIBC") {
+ println!(
+ "cargo:rerun-if-changed={}",
+ PathBuf::from(&libc_file).display()
+ );
+ command.arg("--libc").arg(libc_file);
+ }
+ }
+ if let Ok(system_dir) = env::var("LIBGHOSTTY_VT_ZIG_SYSTEM_DIR") {
+ command.arg("--system").arg(system_dir);
+ }
+
+ let status = command
+ .current_dir(&vendored_dir)
+ .status()
+ .unwrap_or_else(|err| {
+ if err.kind() == std::io::ErrorKind::NotFound {
+ panic!(
+ "zig executable not found (looked for {zig:?}; set the ZIG \
+ environment variable to point at the zig binary). Building \
+ the vendored libghostty-vt requires Zig 0.16.0: install it from \
+ https://ziglang.org/download/, then retry the build"
+ );
+ }
+ panic!("failed to execute zig build for vendored libghostty-vt: {err}");
+ });
+ assert!(
+ status.success(),
+ "zig build for vendored libghostty-vt failed: {status}. \
+ Building Herdr requires Zig 0.16.0; check `zig version` \
+ or set ZIG to the path of a Zig 0.16.0 binary, then retry"
+ );
+
+ let mut lib_dir = zig_prefix.join("lib");
+ if target.contains("-apple-") {
+ // Apple's linker prefers the sibling dylib for `-l`, so search a directory
+ // holding only the static archive.
+ let static_dir = out_dir.join("lib");
+ fs::create_dir_all(&static_dir).expect("failed to create libghostty-vt link directory");
+ fs::copy(
+ lib_dir.join("libghostty-vt.a"),
+ static_dir.join("libghostty-vt.a"),
+ )
+ .expect("failed to copy libghostty-vt static archive");
+ lib_dir = static_dir;
+ }
+ println!("cargo:rustc-link-search=native={}", lib_dir.display());
+ if target.contains("windows-msvc") {
+ println!("cargo:rustc-link-lib=static=ghostty-vt-static");
+ } else {
+ println!("cargo:rustc-link-lib=static=ghostty-vt");
+ }
+}