|
| 1 | +import Foundation |
| 2 | +import PackagePlugin |
| 3 | + |
| 4 | +@main |
| 5 | +struct CargoBuildPlugin: BuildToolPlugin { |
| 6 | + func createBuildCommands(context: PluginContext, target: Target) throws -> [Command] { |
| 7 | + // Paths |
| 8 | + let packageDir = context.package.directoryURL |
| 9 | + let capiDir = packageDir.appendingPathComponent("capi") |
| 10 | + // Use the plugin's work directory (sandboxed) to avoid macOS permission issues |
| 11 | + let scratchTarget = context.pluginWorkDirectoryURL.appendingPathComponent("cargo-target") |
| 12 | + |
| 13 | + // Auto-build is enabled by default. To disable automatic Cargo build, set `LIBCHEWING_AUTO_BUILD_CARGO=0`. |
| 14 | + if ProcessInfo.processInfo.environment["LIBCHEWING_AUTO_BUILD_CARGO"] == "0" { |
| 15 | + return [] |
| 16 | + } |
| 17 | + |
| 18 | + // Prefer common cargo install locations; if not found, abort with a clear error |
| 19 | + let fm = FileManager.default |
| 20 | + let home = fm.homeDirectoryForCurrentUser.path |
| 21 | + let candidates: [URL] = [ |
| 22 | + URL(fileURLWithPath: "/usr/bin/cargo"), |
| 23 | + URL(fileURLWithPath: "/usr/local/bin/cargo"), |
| 24 | + URL(fileURLWithPath: "/opt/homebrew/bin/cargo"), |
| 25 | + URL(fileURLWithPath: "\(home)/.cargo/bin/cargo"), |
| 26 | + ] |
| 27 | + |
| 28 | + var cargoURL: URL? = nil |
| 29 | + for url in candidates { |
| 30 | + if fm.fileExists(atPath: url.path) { |
| 31 | + cargoURL = url |
| 32 | + break |
| 33 | + } |
| 34 | + } |
| 35 | + |
| 36 | + guard let cargo = cargoURL else { |
| 37 | + struct UserError: Error, CustomStringConvertible { |
| 38 | + let description: String |
| 39 | + init(_ s: String) { description = s } |
| 40 | + } |
| 41 | + throw UserError( |
| 42 | + "`cargo` not found on the system. Please install Rust (https://rustup.rs/) to enable automatic builds, or disable automatic Cargo build by setting `LIBCHEWING_AUTO_BUILD_CARGO=0` and run `swift/scripts/build-cargo.sh` manually to produce the library before running `swift build`." |
| 43 | + ) |
| 44 | + } |
| 45 | + |
| 46 | + let manifestPath = capiDir.appendingPathComponent("Cargo.toml").path |
| 47 | + let targetDir = scratchTarget.path |
| 48 | + |
| 49 | + // Arguments: build the chewing_capi crate in release mode into the plugin workdir target |
| 50 | + let args = [ |
| 51 | + "build", |
| 52 | + "--release", |
| 53 | + "--manifest-path", |
| 54 | + manifestPath, |
| 55 | + "--target-dir", |
| 56 | + targetDir, |
| 57 | + ] |
| 58 | + |
| 59 | + return [ |
| 60 | + .prebuildCommand( |
| 61 | + displayName: "Building chewing_capi via cargo", |
| 62 | + executable: cargo, |
| 63 | + arguments: args, |
| 64 | + environment: [:], |
| 65 | + outputFilesDirectory: scratchTarget |
| 66 | + ) |
| 67 | + ] |
| 68 | + } |
| 69 | +} |
0 commit comments