Skip to content

Commit 4a46560

Browse files
committed
fix(swiftlmchat): full xcodebuild macOS compilation
generate_xcodeproj.py: - App source files use sourceTree=SOURCE_ROOT (was <group>, caused doubled paths: SwiftLMChat/SwiftLMChat/Views/...) - Core sources (../Sources) keep <group> (relative to project dir) - Assets.xcassets also moved to SOURCE_ROOT MessageBubble.swift: - Color(.systemGray5/.systemGray6) → Color(white: 0.92/0.95) (UIColor initializer not available on macOS) ModelManagementView.swift: - ModelDownloadManager.huggingFaceCacheRoot → ModelStorage.cacheRoot - .listStyle(.insetGrouped) → .listStyle(.inset) (iOS-only API) ModelPickerView.swift: - .listStyle(.insetGrouped) → .listStyle(.inset) - shouldWarnForCellular(modelId) → shouldWarnForCellular(modelId: modelId) (missing argument label) Result: xcodebuild -destination 'platform=macOS' BUILD SUCCEEDED
1 parent 8d08728 commit 4a46560

5 files changed

Lines changed: 23 additions & 14 deletions

File tree

Sources/SwiftLM/Server.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,11 +229,15 @@ struct MLXServer: AsyncParsableCommand {
229229

230230
if self.streamExperts, let modelDir = modelDirectory {
231231
setenv("EXPERIMENTAL_SSD_STREAM", modelDir.path, 1)
232+
// Activate the modern Swift ExpertStreamingConfig so Load.swift can:
233+
// 1. Initialize ExpertStreamerManager (shard index for getFile())
234+
// 2. Assign tensorName on every QuantizedSwitchLinear after quantize()
235+
// Without this, the streamedGatherMM direct-NVMe path never fires.
236+
ExpertStreamingConfig.shared.activate(
237+
modelDirectory: modelDir,
238+
useDirectIO: true // macOS: 5 GB/s pread() via moe_stream_op.cpp
239+
)
232240
// Cap Metal command buffer size to avoid the 5s Apple GPU Watchdog.
233-
// Each GatedDeltaNet kernel + attention + MLP = ~40 ops/layer max.
234-
// With 3 linear-attention layers before each full-attention layer,
235-
// we need a buffer budget of ~120-150 ops before the outer eval+sync
236-
// in partitionedLayerCall fires. Set a conservative limit.
237241
setenv("MLX_MAX_OPS_PER_BUFFER", "50", 1)
238242
print("[SwiftLM] Enabled Async SSD Streaming on directory: \(modelDir.lastPathComponent)")
239243
}

SwiftLMChat/SwiftLMChat/Views/MessageBubble.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ struct MessageBubble: View {
2929
.textSelection(.enabled)
3030
.padding(.horizontal, 12)
3131
.padding(.vertical, 8)
32-
.background(isUser ? Color.accentColor : Color(.systemGray5))
32+
.background(isUser ? Color.accentColor : Color(white: 0.92))
3333
.foregroundStyle(isUser ? .white : .primary)
3434
.clipShape(BubbleShape(isUser: isUser))
3535

@@ -69,7 +69,7 @@ struct StreamingBubble: View {
6969
.font(.caption)
7070
.foregroundStyle(.secondary)
7171
.padding(8)
72-
.background(Color(.systemGray6))
72+
.background(Color(white: 0.95))
7373
.clipShape(RoundedRectangle(cornerRadius: 8))
7474
} label: {
7575
Label("Thinking…", systemImage: "brain")
@@ -92,14 +92,14 @@ struct StreamingBubble: View {
9292
}
9393
.padding(.horizontal, 12)
9494
.padding(.vertical, 8)
95-
.background(Color(.systemGray5))
95+
.background(Color(white: 0.92))
9696
.clipShape(BubbleShape(isUser: false))
9797
} else {
9898
// Typing dots when no text yet
9999
TypingIndicator()
100100
.padding(.horizontal, 12)
101101
.padding(.vertical, 8)
102-
.background(Color(.systemGray5))
102+
.background(Color(white: 0.92))
103103
.clipShape(BubbleShape(isUser: false))
104104
}
105105
}

SwiftLMChat/SwiftLMChat/Views/ModelManagementView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ struct ModelManagementView: View {
7777
// Cache info
7878
Section {
7979
LabeledContent("Cache Location") {
80-
Text(ModelDownloadManager.huggingFaceCacheRoot.path)
80+
Text(ModelStorage.cacheRoot.path)
8181
.font(.caption)
8282
.foregroundStyle(.secondary)
8383
.lineLimit(2)
@@ -89,7 +89,7 @@ struct ModelManagementView: View {
8989
.foregroundStyle(.secondary)
9090
}
9191
}
92-
.listStyle(.insetGrouped)
92+
.listStyle(.inset)
9393
}
9494

9595
// MARK: — Storage Card

SwiftLMChat/SwiftLMChat/Views/ModelPickerView.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ struct ModelPickerView: View {
8686
}
8787
}
8888
}
89-
.listStyle(.insetGrouped)
89+
.listStyle(.inset)
9090
.navigationTitle("Models")
9191
#if os(iOS)
9292
.navigationBarTitleDisplayMode(.inline)
@@ -177,7 +177,7 @@ struct ModelPickerView: View {
177177
// Don't download if offline and not already cached
178178
if downloadManager.isOffline && !downloadManager.isDownloaded(modelId) { return }
179179
// Warn before large cellular downloads
180-
if downloadManager.shouldWarnForCellular(modelId) && !downloadManager.isDownloaded(modelId) {
180+
if downloadManager.shouldWarnForCellular(modelId: modelId) && !downloadManager.isDownloaded(modelId) {
181181
pendingCellularModelId = modelId
182182
} else {
183183
onSelect(modelId)

SwiftLMChat/generate_xcodeproj.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,15 @@ def pbxproj():
8787

8888
# PBXFileReference entries
8989
file_refs = ""
90-
for path, fref, _ in all_sources:
90+
for path, fref, _ in app_sources:
9191
name = Path(path).name
92+
# SOURCE_ROOT = project root (SwiftLMChat/) so the path is exact, no doubling
93+
file_refs += f'\t\t{fref} /* {name} */ = {{isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "{name}"; path = "{path}"; sourceTree = "SOURCE_ROOT"; }};\n'
94+
for path, fref, _ in core_sources:
95+
name = Path(path).name
96+
# <group> is fine here — these paths start with ../Sources which go up from project dir
9297
file_refs += f'\t\t{fref} /* {name} */ = {{isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "{name}"; path = "{path}"; sourceTree = "<group>"; }};\n'
93-
file_refs += f'\t\t{ASSETS_REF} /* Assets.xcassets */ = {{isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = SwiftLMChat/Assets.xcassets; sourceTree = "<group>"; }};\n'
98+
file_refs += f'\t\t{ASSETS_REF} /* Assets.xcassets */ = {{isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = SwiftLMChat/Assets.xcassets; sourceTree = "SOURCE_ROOT"; }};\n'
9499
file_refs += f'\t\t{APP_PRODUCT} /* SwiftLMChat.app */ = {{isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SwiftLMChat.app; sourceTree = BUILT_PRODUCTS_DIR; }};\n'
95100

96101
# Group children

0 commit comments

Comments
 (0)