| 1 | use std::path::PathBuf; |
| 2 | |
| 3 | fn main() { |
| 4 | // Shared target directories may reuse this executable in another worktree. |
| 5 | let manifest_dir = PathBuf::from( |
| 6 | std::env::var_os("CARGO_MANIFEST_DIR").expect("Cargo sets CARGO_MANIFEST_DIR"), |
| 7 | ); |
| 8 | println!("cargo:rerun-if-env-changed=CARGO_MANIFEST_DIR"); |
| 9 | codewhale_build_support::declare_rerun_conditions(&manifest_dir); |
| 10 | codewhale_build_support::configure_windows_main_stack("codewhale-tui"); |
| 11 | build_computer_use_helper(&manifest_dir); |
| 12 | codewhale_build_support::emit_build_version(&manifest_dir, env!("CARGO_PKG_VERSION")); |
| 13 | } |
| 14 | |
| 15 | /// Ship native computer-use support with macOS binaries. Requiring clang on |
| 16 | /// the customer's machine would make the built-in plugin a source-only demo. |
| 17 | fn build_computer_use_helper(manifest_dir: &std::path::Path) { |
| 18 | if std::env::var("CARGO_CFG_TARGET_OS").as_deref() != Ok("macos") { |
| 19 | return; |
| 20 | } |
| 21 | let source = manifest_dir.join("plugins/computer-use/src/backends/darwin-accessibility.m"); |
| 22 | println!("cargo:rerun-if-changed={}", source.display()); |
| 23 | println!( |
| 24 | "cargo:rerun-if-changed={}", |
| 25 | source.with_file_name("darwin-recording.h").display() |
| 26 | ); |
| 27 | println!( |
| 28 | "cargo:rerun-if-changed={}", |
| 29 | source.with_file_name("darwin-ocr.h").display() |
| 30 | ); |
| 31 | println!("cargo:rerun-if-env-changed=CODEWHALE_CU_SIGN_IDENTITY"); |
| 32 | let arch = match std::env::var("CARGO_CFG_TARGET_ARCH").as_deref() { |
| 33 | Ok("aarch64") => "arm64", |
| 34 | Ok("x86_64") => "x86_64", |
| 35 | other => panic!("unsupported macOS computer-use architecture: {other:?}"), |
| 36 | }; |
| 37 | let output = PathBuf::from(std::env::var_os("OUT_DIR").expect("Cargo sets OUT_DIR")) |
| 38 | .join("computer-use-accessibility"); |
| 39 | let compiled = std::process::Command::new("xcrun") |
| 40 | .args([ |
| 41 | "clang", |
| 42 | "-fobjc-arc", |
| 43 | "-Os", |
| 44 | "-arch", |
| 45 | arch, |
| 46 | "-mmacosx-version-min=13.0", |
| 47 | "-framework", |
| 48 | "Cocoa", |
| 49 | "-framework", |
| 50 | "ApplicationServices", |
| 51 | "-framework", |
| 52 | "ScreenCaptureKit", |
| 53 | "-framework", |
| 54 | "AVFoundation", |
| 55 | "-framework", |
| 56 | "CoreMedia", |
| 57 | "-framework", |
| 58 | "Vision", |
| 59 | ]) |
| 60 | .arg(&source) |
| 61 | .arg("-o") |
| 62 | .arg(&output) |
| 63 | .output() |
| 64 | .expect("macOS builds require Xcode Command Line Tools to package Computer Use"); |
| 65 | assert!( |
| 66 | compiled.status.success(), |
| 67 | "Computer Use helper compilation failed: {}", |
| 68 | String::from_utf8_lossy(&compiled.stderr) |
| 69 | ); |
| 70 | // Developer builds use ad-hoc signing; release builders can supply the |
| 71 | // same Developer ID as the app. No keychain lookup or credential copying. |
| 72 | let identity = std::env::var("CODEWHALE_CU_SIGN_IDENTITY").unwrap_or_else(|_| "-".into()); |
| 73 | let signed = std::process::Command::new("codesign") |
| 74 | .args([ |
| 75 | "--force", |
| 76 | if identity == "-" { |
| 77 | "--timestamp=none" |
| 78 | } else { |
| 79 | "--timestamp" |
| 80 | }, |
| 81 | "--options", |
| 82 | "runtime", |
| 83 | "--identifier", |
| 84 | "net.codewhale.computer-use.helper", |
| 85 | "--sign", |
| 86 | ]) |
| 87 | .arg(&identity) |
| 88 | .arg(&output) |
| 89 | .output() |
| 90 | .expect("macOS builds require codesign to package Computer Use"); |
| 91 | assert!( |
| 92 | signed.status.success(), |
| 93 | "Computer Use helper signing failed: {}", |
| 94 | String::from_utf8_lossy(&signed.stderr) |
| 95 | ); |
| 96 | } |
| 97 |