245 lines · 8.5 KB · Rust
RawDownload
#![cfg_attr(any(not(target_os = "macos"), feature = "macos-blade"), allow(unused))] //TODO: consider generating shader code for WGSL//TODO: deprecate "runtime-shaders" and "macos-blade" use std::env; fn main() {    let target = env::var("CARGO_CFG_TARGET_OS");    println!("cargo::rustc-check-cfg=cfg(gles)");     #[cfg(any(not(target_os = "macos"), feature = "macos-blade"))]    check_wgsl_shaders();     match target.as_deref() {        Ok("macos") => {            #[cfg(target_os = "macos")]            macos::build();        }        #[cfg(target_os = "windows")]        Ok("windows") => {            let manifest = std::path::Path::new("resources/windows/gpui.manifest.xml");            let rc_file = std::path::Path::new("resources/windows/gpui.rc");            println!("cargo:rerun-if-changed={}", manifest.display());            println!("cargo:rerun-if-changed={}", rc_file.display());            embed_resource::compile(rc_file, embed_resource::NONE)                .manifest_required()                .unwrap();        }        _ => (),    };} #[allow(dead_code)]fn check_wgsl_shaders() {    use std::path::PathBuf;    use std::process;    use std::str::FromStr;     let shader_source_path = "./src/platform/blade/shaders.wgsl";    let shader_path = PathBuf::from_str(shader_source_path).unwrap();    println!("cargo:rerun-if-changed={}", &shader_path.display());     let shader_source = std::fs::read_to_string(&shader_path).unwrap();     match naga::front::wgsl::parse_str(&shader_source) {        Ok(_) => {            // All clear        }        Err(e) => {            eprintln!("WGSL shader compilation failed:\n{}", e);            process::exit(1);        }    }}#[cfg(target_os = "macos")]mod macos {    use std::{        env,        path::{Path, PathBuf},    };     use cbindgen::Config;     pub(super) fn build() {        generate_dispatch_bindings();        #[cfg(not(feature = "macos-blade"))]        {            let header_path = generate_shader_bindings();             #[cfg(feature = "runtime_shaders")]            emit_stitched_shaders(&header_path);            #[cfg(not(feature = "runtime_shaders"))]            compile_metal_shaders(&header_path);        }    }     fn generate_dispatch_bindings() {        println!("cargo:rustc-link-lib=framework=System");        println!("cargo:rustc-link-lib=framework=ScreenCaptureKit");        println!("cargo:rerun-if-changed=src/platform/mac/dispatch.h");         let bindings = bindgen::Builder::default()            .header("src/platform/mac/dispatch.h")            .allowlist_var("_dispatch_main_q")            .allowlist_var("_dispatch_source_type_data_add")            .allowlist_var("DISPATCH_QUEUE_PRIORITY_HIGH")            .allowlist_var("DISPATCH_TIME_NOW")            .allowlist_function("dispatch_get_global_queue")            .allowlist_function("dispatch_async_f")            .allowlist_function("dispatch_after_f")            .allowlist_function("dispatch_time")            .allowlist_function("dispatch_source_merge_data")            .allowlist_function("dispatch_source_create")            .allowlist_function("dispatch_source_set_event_handler_f")            .allowlist_function("dispatch_resume")            .allowlist_function("dispatch_suspend")            .allowlist_function("dispatch_source_cancel")            .allowlist_function("dispatch_set_context")            .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))            .layout_tests(false)            .generate()            .expect("unable to generate bindings");         let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());        bindings            .write_to_file(out_path.join("dispatch_sys.rs"))            .expect("couldn't write dispatch bindings");    }     fn generate_shader_bindings() -> PathBuf {        let output_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("scene.h");        let crate_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());        let mut config = Config {            include_guard: Some("SCENE_H".into()),            language: cbindgen::Language::C,            no_includes: true,            ..Default::default()        };        config.export.include.extend([            "Bounds".into(),            "Corners".into(),            "Edges".into(),            "Size".into(),            "Pixels".into(),            "PointF".into(),            "Hsla".into(),            "ContentMask".into(),            "Uniforms".into(),            "AtlasTile".into(),            "PathRasterizationInputIndex".into(),            "PathVertex_ScaledPixels".into(),            "ShadowInputIndex".into(),            "Shadow".into(),            "QuadInputIndex".into(),            "Underline".into(),            "UnderlineInputIndex".into(),            "Quad".into(),            "SpriteInputIndex".into(),            "MonochromeSprite".into(),            "PolychromeSprite".into(),            "PathSprite".into(),            "SurfaceInputIndex".into(),            "SurfaceBounds".into(),            "TransformationMatrix".into(),        ]);        config.no_includes = true;        config.enumeration.prefix_with_name = true;         let mut builder = cbindgen::Builder::new();         let src_paths = [            crate_dir.join("src/scene.rs"),            crate_dir.join("src/geometry.rs"),            crate_dir.join("src/color.rs"),            crate_dir.join("src/window.rs"),            crate_dir.join("src/platform.rs"),            crate_dir.join("src/platform/mac/metal_renderer.rs"),        ];        for src_path in src_paths {            println!("cargo:rerun-if-changed={}", src_path.display());            builder = builder.with_src(src_path);        }         builder            .with_config(config)            .generate()            .expect("Unable to generate bindings")            .write_to_file(&output_path);         output_path    }     /// To enable runtime compilation, we need to "stitch" the shaders file with the generated header    /// so that it is self-contained.    #[cfg(feature = "runtime_shaders")]    fn emit_stitched_shaders(header_path: &Path) {        use std::str::FromStr;        fn stitch_header(header: &Path, shader_path: &Path) -> std::io::Result<PathBuf> {            let header_contents = std::fs::read_to_string(header)?;            let shader_contents = std::fs::read_to_string(shader_path)?;            let stitched_contents = format!("{header_contents}\n{shader_contents}");            let out_path =                PathBuf::from(env::var("OUT_DIR").unwrap()).join("stitched_shaders.metal");            std::fs::write(&out_path, stitched_contents)?;            Ok(out_path)        }        let shader_source_path = "./src/platform/mac/shaders.metal";        let shader_path = PathBuf::from_str(shader_source_path).unwrap();        stitch_header(header_path, &shader_path).unwrap();        println!("cargo:rerun-if-changed={}", &shader_source_path);    }     #[cfg(not(feature = "runtime_shaders"))]    fn compile_metal_shaders(header_path: &Path) {        use std::process::{self, Command};        let shader_path = "./src/platform/mac/shaders.metal";        let air_output_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("shaders.air");        let metallib_output_path =            PathBuf::from(env::var("OUT_DIR").unwrap()).join("shaders.metallib");        println!("cargo:rerun-if-changed={}", shader_path);         let output = Command::new("xcrun")            .args([                "-sdk",                "macosx",                "metal",                "-gline-tables-only",                "-mmacosx-version-min=10.15.7",                "-MO",                "-c",                shader_path,                "-include",                (header_path.to_str().unwrap()),                "-o",            ])            .arg(&air_output_path)            .output()            .unwrap();         if !output.status.success() {            eprintln!(                "metal shader compilation failed:\n{}",                String::from_utf8_lossy(&output.stderr)            );            process::exit(1);        }         let output = Command::new("xcrun")            .args(["-sdk", "macosx", "metallib"])            .arg(air_output_path)            .arg("-o")            .arg(metallib_output_path)            .output()            .unwrap();         if !output.status.success() {            eprintln!(                "metallib compilation failed:\n{}",                String::from_utf8_lossy(&output.stderr)            );            process::exit(1);        }    }}