Skip to content

Commit 4516619

Browse files
committed
fix(ios): gate Foundation.Process behind #if os(macOS) || os(Linux)
RsvgConvertRasterizer and the test helpers that probe / shell out via Process cannot compile on iOS, tvOS, watchOS, or visionOS. Wrap the default rasteriser, its use as XCAssetCompiler.init's default argument, and the test ProcessLauncher / RsvgConvertProbe in #if guards so the package builds on iOS targets. On non-Process platforms svgRasterizer: is required (no default). Also inject StubSVGRasterizer in AssetutilParseTests so the macOS CI runner doesn't need rsvg-convert installed, and fix a stale Sources/XCAssetCompiler/... doc path left over from the rebrand.
1 parent f5df44f commit 4516619

9 files changed

Lines changed: 43 additions & 11 deletions

File tree

‎.github/actions/configure-xcode/action.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ runs:
66
- name: Set up Xcode
77
shell: bash
88
run: |
9-
sudo xcode-select -s /Applications/Xcode_26.4.app
9+
sudo xcode-select -s /Applications/Xcode_26.0.app

‎Dockerfile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
FROM swift:6.3
1+
FROM swift:6.2

‎Package.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// swift-tools-version: 6.3
1+
// swift-tools-version: 6.2
22

33
import PackageDescription
44

‎README.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ Targets CoreUI 970 (Xcode 26 / iOS 16+). See [docs/coreui-970-format.md](docs/co
1313
```swift
1414
import AssetKit
1515

16-
// `svgRasterizer` defaults to `RsvgConvertRasterizer()`, which shells out
17-
// to `rsvg-convert` (install with `apt install librsvg2-tools`,
18-
// `dnf install librsvg2-tools`, or `brew install librsvg`). Replace it
19-
// with your own `SVGRasterizer` if you'd rather not depend on a system
20-
// binary.
16+
// On macOS and Linux, `svgRasterizer` defaults to `RsvgConvertRasterizer()`,
17+
// which shells out to `rsvg-convert` (install with `apt install
18+
// librsvg2-tools`, `dnf install librsvg2-tools`, or `brew install librsvg`).
19+
// On iOS/tvOS/watchOS/visionOS there is no default (Foundation.Process is
20+
// unavailable), so callers must inject their own `SVGRasterizer`.
2121
let compiler = XCAssetCompiler(deploymentTarget: "16.0")
2222
let result = try await compiler.compile(catalog: catalogURL)
2323

‎Sources/AssetKit/Rendition/SVGRasterizer.swift‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ public protocol SVGRasterizer: Sendable {
2323
func rasterize(svgData: Data, pixelWidth: UInt32, pixelHeight: UInt32) throws -> Data
2424
}
2525

26+
#if os(macOS) || os(Linux)
27+
2628
/// Default `SVGRasterizer` implementation: shells out to `rsvg-convert`.
2729
///
2830
/// `rsvg-convert` ships with librsvg, which is available on essentially
@@ -35,6 +37,10 @@ public protocol SVGRasterizer: Sendable {
3537
/// resulting compiled `Assets.car` is NOT byte-equal across hosts running
3638
/// different librsvg versions for SVG-bearing catalogs; the vector
3739
/// rendition (DWAR-wrapped XML) remains byte-equal regardless.
40+
///
41+
/// Only available on macOS and Linux because `Foundation.Process` is not
42+
/// available on iOS, tvOS, watchOS, or visionOS. Callers on those platforms
43+
/// must inject their own `SVGRasterizer`.
3844
public struct RsvgConvertRasterizer: SVGRasterizer {
3945
/// Absolute path to the `rsvg-convert` binary. Defaults to letting
4046
/// `/usr/bin/env` resolve it from `PATH`; override if your install
@@ -137,3 +143,5 @@ public struct RsvgConvertRasterizer: SVGRasterizer {
137143
func get() -> Error? { lock.lock(); defer { lock.unlock() }; return error }
138144
}
139145
}
146+
147+
#endif

‎Sources/AssetKit/XCAssetCompiler.swift‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,23 @@ public struct XCAssetCompiler: Sendable {
6868
/// performance profile, sandbox restrictions, etc).
6969
public var svgRasterizer: any SVGRasterizer
7070

71+
#if os(macOS) || os(Linux)
7172
public init(
7273
deploymentTarget: String,
7374
svgRasterizer: any SVGRasterizer = RsvgConvertRasterizer()
7475
) {
7576
self.deploymentTarget = deploymentTarget
7677
self.svgRasterizer = svgRasterizer
7778
}
79+
#else
80+
public init(
81+
deploymentTarget: String,
82+
svgRasterizer: any SVGRasterizer
83+
) {
84+
self.deploymentTarget = deploymentTarget
85+
self.svgRasterizer = svgRasterizer
86+
}
87+
#endif
7888

7989
public func compile(catalog catalogURL: URL) async throws -> CompileResult {
8090
let loader = CatalogLoader()

‎Tests/AssetKitTests/AssetutilParseTests.swift‎

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Testing
99
///
1010
/// This is the durable verification for CoreUI format compatibility. The
1111
/// underlying byte format drifts across Xcode releases (see
12-
/// `Sources/XCAssetCompiler/CAR/KeyFormat.swift`), so this test will catch
12+
/// `Sources/AssetKit/CAR/KeyFormat.swift`), so this test will catch
1313
/// the regression on a future macOS runner before users do.
1414
@Suite("assetutil parse gate")
1515
struct AssetutilParseTests {
@@ -34,7 +34,10 @@ struct AssetutilParseTests {
3434
try FileManager.default.createDirectory(at: scratch, withIntermediateDirectories: true)
3535
defer { try? FileManager.default.removeItem(at: scratch) }
3636

37-
let compiler = XCAssetCompiler(deploymentTarget: "16.0")
37+
let compiler = XCAssetCompiler(
38+
deploymentTarget: "16.0",
39+
svgRasterizer: StubSVGRasterizer()
40+
)
3841
let result = try await compiler.compile(catalog: fixtureURL)
3942
let carURL = scratch.appendingPathComponent("Assets.car")
4043
try result.carData.write(to: carURL)
@@ -109,6 +112,7 @@ private enum ProcessLauncher {
109112
}
110113

111114
static func run(executable: String, arguments: [String]) throws -> Invocation {
115+
#if os(macOS) || os(Linux)
112116
let process = Process()
113117
process.executableURL = URL(fileURLWithPath: executable)
114118
process.arguments = arguments
@@ -123,5 +127,8 @@ private enum ProcessLauncher {
123127
stdout: stdout.fileHandleForReading.readDataToEndOfFile(),
124128
stderr: stderr.fileHandleForReading.readDataToEndOfFile()
125129
)
130+
#else
131+
return Invocation(exitCode: -1, stdout: Data(), stderr: Data())
132+
#endif
126133
}
127134
}

‎Tests/AssetKitTests/CARWriterTests.swift‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,10 @@ struct CARWriterTests {
4040
}
4141
""".utf8).write(to: colorSet.appendingPathComponent("Contents.json"))
4242

43-
let compiler = XCAssetCompiler(deploymentTarget: "16.0")
43+
let compiler = XCAssetCompiler(
44+
deploymentTarget: "16.0",
45+
svgRasterizer: StubSVGRasterizer()
46+
)
4447
let result = try await compiler.compile(catalog: tmp)
4548
#expect(result.carData.count > 600)
4649
#expect(Array(result.carData.prefix(8)) == Array("BOMStore".utf8))

‎Tests/AssetKitTests/Helpers/StubSVGRasterizer.swift‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ struct MemoryBytestreamDestination: PNG.BytestreamDestination {
4848

4949
enum RsvgConvertProbe {
5050
static var isAvailable: Bool {
51+
#if os(macOS) || os(Linux)
5152
let process = Process()
5253
process.executableURL = URL(fileURLWithPath: "/usr/bin/env")
5354
process.arguments = ["which", "rsvg-convert"]
@@ -60,5 +61,8 @@ enum RsvgConvertProbe {
6061
} catch {
6162
return false
6263
}
64+
#else
65+
return false
66+
#endif
6367
}
6468
}

0 commit comments

Comments
 (0)