mirror of
https://github.com/XcodesOrg/XcodesApp.git
synced 2026-03-25 08:55:46 +00:00
Merge pull request #730 from XcodesOrg/matt/multipleArch
Support Xcode 26 multiple Architectures
This commit is contained in:
commit
a434d26921
10 changed files with 244 additions and 32 deletions
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
|
|
@ -8,10 +8,10 @@ on:
|
|||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: macos-14
|
||||
runs-on: macos-15
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run tests
|
||||
env:
|
||||
DEVELOPER_DIR: /Applications/Xcode_16.app
|
||||
DEVELOPER_DIR: /Applications/Xcode_16.4.app
|
||||
run: xcodebuild test -scheme Xcodes
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@
|
|||
CAFE4AB425B7D3AF0064FE51 /* AdvancedPreferencePane.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFE4AB325B7D3AF0064FE51 /* AdvancedPreferencePane.swift */; };
|
||||
CAFE4ABC25B7D54B0064FE51 /* UpdatesPreferencePane.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFE4ABB25B7D54B0064FE51 /* UpdatesPreferencePane.swift */; };
|
||||
CAFFFED8259CDA5000903F81 /* XcodeListViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFFFED7259CDA5000903F81 /* XcodeListViewRow.swift */; };
|
||||
D93F95C12E0C8C1A00238FB5 /* TagView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D93F95C02E0C8C1A00238FB5 /* TagView.swift */; };
|
||||
E689540325BE8C64000EBCEA /* DockProgress in Frameworks */ = {isa = PBXBuildFile; productRef = E689540225BE8C64000EBCEA /* DockProgress */; };
|
||||
E81D7EA02805250100A205FC /* Collection+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E81D7E9F2805250100A205FC /* Collection+.swift */; };
|
||||
E832EAF82B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E832EAF72B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift */; };
|
||||
|
|
@ -139,6 +140,7 @@
|
|||
E8DA461125FAF7FB002E85EF /* NotificationsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8DA461025FAF7FB002E85EF /* NotificationsView.swift */; };
|
||||
E8E98A9025D8631800EC89A0 /* InstallationStepRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFBC3FF259AC17F00E2A3D8 /* InstallationStepRowView.swift */; };
|
||||
E8E98A9625D863D700EC89A0 /* InstallationStepDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E98A9525D863D700EC89A0 /* InstallationStepDetailView.swift */; };
|
||||
E8EE58C02E1CC2A50003FA9F /* RuntimeArchitecture.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8EE58BF2E1CC2A50003FA9F /* RuntimeArchitecture.swift */; };
|
||||
E8F44A1E296B4CD7002D6592 /* Path in Frameworks */ = {isa = PBXBuildFile; productRef = E8F44A1D296B4CD7002D6592 /* Path */; };
|
||||
E8FA00542B5B109800769CE0 /* com.xcodesorg.xcodesapp.Helper in Copy Helper */ = {isa = PBXBuildFile; fileRef = CA9FF8AE2595967A00E47BAF /* com.xcodesorg.xcodesapp.Helper */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
E8FD5727291EE4AC001E004C /* AsyncNetworkService in Frameworks */ = {isa = PBXBuildFile; productRef = E8FD5726291EE4AC001E004C /* AsyncNetworkService */; };
|
||||
|
|
@ -321,6 +323,7 @@
|
|||
CAFE4ABB25B7D54B0064FE51 /* UpdatesPreferencePane.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatesPreferencePane.swift; sourceTree = "<group>"; };
|
||||
CAFFFED7259CDA5000903F81 /* XcodeListViewRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcodeListViewRow.swift; sourceTree = "<group>"; };
|
||||
CAFFFEEE259CEAC400903F81 /* RingProgressViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RingProgressViewStyle.swift; sourceTree = "<group>"; };
|
||||
D93F95C02E0C8C1A00238FB5 /* TagView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagView.swift; sourceTree = "<group>"; };
|
||||
E81D7E9F2805250100A205FC /* Collection+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+.swift"; sourceTree = "<group>"; };
|
||||
E832EAF72B0FBCF4001B570D /* RuntimeInstallationStepDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimeInstallationStepDetailView.swift; sourceTree = "<group>"; };
|
||||
E84B7D0C2B296A8900DBDA2B /* NavigationSplitViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationSplitViewWrapper.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -340,6 +343,7 @@
|
|||
E8D655BF288DD04700A139C2 /* SelectedActionType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SelectedActionType.swift; sourceTree = "<group>"; };
|
||||
E8DA461025FAF7FB002E85EF /* NotificationsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsView.swift; sourceTree = "<group>"; };
|
||||
E8E98A9525D863D700EC89A0 /* InstallationStepDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallationStepDetailView.swift; sourceTree = "<group>"; };
|
||||
E8EE58BF2E1CC2A50003FA9F /* RuntimeArchitecture.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RuntimeArchitecture.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -387,6 +391,7 @@
|
|||
63EAA4E9259944340046AB8F /* Common */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D93F95C02E0C8C1A00238FB5 /* TagView.swift */,
|
||||
CAC281CC259F97FA00B8AB0B /* ObservingProgressIndicator.swift */,
|
||||
63EAA4EA259944450046AB8F /* ProgressButton.swift */,
|
||||
CA452BAF259FD9770072DFA4 /* ProgressIndicator.swift */,
|
||||
|
|
@ -657,6 +662,7 @@
|
|||
E8E98A9425D863B100EC89A0 /* InfoPane */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E8EE58BF2E1CC2A50003FA9F /* RuntimeArchitecture.swift */,
|
||||
B0403CEF2AD92D7B00137C09 /* ReleaseNotesView.swift */,
|
||||
B0403CF32AD9381D00137C09 /* SDKsView.swift */,
|
||||
B0403CF52AD9849E00137C09 /* CompilersView.swift */,
|
||||
|
|
@ -932,9 +938,11 @@
|
|||
E84E4F522B323A5F003F3959 /* CornerRadiusModifier.swift in Sources */,
|
||||
B0403CF22AD934B600137C09 /* CompatibilityView.swift in Sources */,
|
||||
B0403CFE2ADA712C00137C09 /* InfoPaneControls.swift in Sources */,
|
||||
D93F95C12E0C8C1A00238FB5 /* TagView.swift in Sources */,
|
||||
53CBAB2C263DCC9100410495 /* XcodesAlert.swift in Sources */,
|
||||
332807412CA5EA820036F691 /* SignInSecurityKeyTouchView.swift in Sources */,
|
||||
CA61A6E0259835580008926E /* Xcode.swift in Sources */,
|
||||
E8EE58C02E1CC2A50003FA9F /* RuntimeArchitecture.swift in Sources */,
|
||||
CAE4247F259A666100B8B246 /* MainWindow.swift in Sources */,
|
||||
CA452BB0259FD9770072DFA4 /* ProgressIndicator.swift in Sources */,
|
||||
B0403CF02AD92D7B00137C09 /* ReleaseNotesView.swift in Sources */,
|
||||
|
|
|
|||
24
Xcodes/Frontend/Common/TagView.swift
Normal file
24
Xcodes/Frontend/Common/TagView.swift
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
//
|
||||
// TagView.swift
|
||||
// Xcodes
|
||||
//
|
||||
// Created by Matt Kiazyk on 2025-06-25.//
|
||||
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct TagView: View {
|
||||
let text: String
|
||||
|
||||
var body: some View {
|
||||
Text(text)
|
||||
.font(.system(size: 10))
|
||||
.foregroundColor(.primary)
|
||||
.padding(.horizontal, 5)
|
||||
.padding(.vertical, 2)
|
||||
.background(
|
||||
Capsule()
|
||||
.fill(.quaternary)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -35,13 +35,7 @@ struct InfoPane: View {
|
|||
}
|
||||
.xcodesBackground()
|
||||
|
||||
VStack {
|
||||
Text("Platforms")
|
||||
.font(.title3)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
PlatformsView(xcode: xcode)
|
||||
}
|
||||
.xcodesBackground()
|
||||
PlatformsView(xcode: xcode)
|
||||
}
|
||||
.frame(minWidth: 380)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,8 @@ import XcodesKit
|
|||
|
||||
struct PlatformsView: View {
|
||||
@EnvironmentObject var appState: AppState
|
||||
|
||||
@AppStorage("selectedRuntimeArchitecture") private var selectedRuntimeArchitecture: RuntimeArchitecture = .arm64
|
||||
|
||||
let xcode: Xcode
|
||||
|
||||
var body: some View {
|
||||
|
|
@ -19,17 +20,50 @@ struct PlatformsView: View {
|
|||
let builds = xcode.sdks?.allBuilds()
|
||||
let runtimes = builds?.flatMap { sdkBuild in
|
||||
appState.downloadableRuntimes.filter {
|
||||
$0.sdkBuildUpdate?.contains(sdkBuild) ?? false
|
||||
$0.sdkBuildUpdate?.contains(sdkBuild) ?? false &&
|
||||
($0.architectures?.isEmpty ?? true ||
|
||||
$0.architectures?.contains(selectedRuntimeArchitecture.rawValue) ?? false)
|
||||
}
|
||||
}
|
||||
|
||||
ForEach(runtimes ?? [], id: \.simulatorVersion.buildUpdate) { runtime in
|
||||
runtimeView(runtime: runtime)
|
||||
.frame(minWidth: 200)
|
||||
.padding()
|
||||
.background(.quinary)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 5, style: .continuous))
|
||||
|
||||
let architectures = Set((runtimes ?? []).flatMap { $0.architectures ?? [] })
|
||||
|
||||
VStack {
|
||||
HStack {
|
||||
Text("Platforms")
|
||||
.font(.title3)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
if !architectures.isEmpty {
|
||||
Spacer()
|
||||
Button {
|
||||
switch selectedRuntimeArchitecture {
|
||||
case .arm64: selectedRuntimeArchitecture = .x86_64
|
||||
case .x86_64: selectedRuntimeArchitecture = .arm64
|
||||
}
|
||||
} label: {
|
||||
switch selectedRuntimeArchitecture {
|
||||
case .arm64:
|
||||
Label(selectedRuntimeArchitecture.displayValue, systemImage: "m4.button.horizontal")
|
||||
.labelStyle(.trailingIcon)
|
||||
case .x86_64:
|
||||
Label(selectedRuntimeArchitecture.displayValue, systemImage: "cpu.fill")
|
||||
.labelStyle(.trailingIcon)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ForEach(runtimes ?? [], id: \.identifier) { runtime in
|
||||
runtimeView(runtime: runtime)
|
||||
.frame(minWidth: 200)
|
||||
.padding()
|
||||
.background(.quinary)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 5, style: .continuous))
|
||||
}
|
||||
}
|
||||
.xcodesBackground()
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
|
|
@ -39,6 +73,9 @@ struct PlatformsView: View {
|
|||
runtime.icon()
|
||||
Text("\(runtime.visibleIdentifier)")
|
||||
.font(.headline)
|
||||
ForEach(runtime.architectures ?? [], id: \.self) { architecture in
|
||||
TagView(text: architecture)
|
||||
}
|
||||
pathIfAvailable(xcode: xcode, runtime: runtime)
|
||||
|
||||
if runtime.installState == .notInstalled {
|
||||
|
|
|
|||
17
Xcodes/Frontend/InfoPane/RuntimeArchitecture.swift
Normal file
17
Xcodes/Frontend/InfoPane/RuntimeArchitecture.swift
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// RuntimeArchitecture.swift
|
||||
// Xcodes
|
||||
//
|
||||
// Created by Matt Kiazyk on 2025-07-07.
|
||||
//
|
||||
|
||||
enum RuntimeArchitecture: String, CaseIterable, Identifiable {
|
||||
case arm64
|
||||
case x86_64
|
||||
|
||||
var id: Self { self }
|
||||
|
||||
var displayValue: String {
|
||||
return rawValue
|
||||
}
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ struct BottomStatusModifier: ViewModifier {
|
|||
}
|
||||
}
|
||||
}
|
||||
Text("\(Bundle.main.shortVersion!) (\(Bundle.main.version!))")
|
||||
Text(verbatim: "\(Bundle.main.shortVersion!) (\(Bundle.main.version!))")
|
||||
.font(.subheadline)
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: 30, alignment: .leading)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
{\rtf1\ansi\ansicpg1252\cocoartf2818
|
||||
{\rtf1\ansi\ansicpg1252\cocoartf2822
|
||||
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 .SFNS-Regular;}
|
||||
{\colortbl;\red255\green255\blue255;}
|
||||
{\*\expandedcolortbl;;}
|
||||
|
|
|
|||
|
|
@ -237,16 +237,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"%@ (%@)" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "%1$@ (%2$@)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"%@ %@ %@" : {
|
||||
"localizations" : {
|
||||
"ar" : {
|
||||
|
|
@ -17919,7 +17909,128 @@
|
|||
}
|
||||
},
|
||||
"PIN not set" : {
|
||||
|
||||
"localizations" : {
|
||||
"ar" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"ca" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"de" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"el" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"es" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"fi" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"fr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"hi" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"it" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"ko" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"nl" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"pl" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"pt-BR" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"ru" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"tr" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"uk" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"zh-Hans" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
},
|
||||
"zh-Hant" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "PIN not set"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Platforms" : {
|
||||
"localizations" : {
|
||||
|
|
@ -17947,6 +18058,12 @@
|
|||
"value" : "Πλατφόρμες"
|
||||
}
|
||||
},
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Platforms"
|
||||
}
|
||||
},
|
||||
"es" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
|
|
@ -18314,6 +18431,12 @@
|
|||
"value" : "Προτιμήσεις"
|
||||
}
|
||||
},
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Preferences"
|
||||
}
|
||||
},
|
||||
"es" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
|
|
@ -18804,6 +18927,12 @@
|
|||
"value" : "Ανανέωση"
|
||||
}
|
||||
},
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Refresh"
|
||||
}
|
||||
},
|
||||
"es" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ public struct DownloadableRuntime: Codable, Identifiable, Hashable {
|
|||
public let category: Category
|
||||
public let simulatorVersion: SimulatorVersion
|
||||
public let source: String?
|
||||
public let architectures: [String]?
|
||||
public let dictionaryVersion: Int
|
||||
public let contentType: ContentType
|
||||
public let platform: Platform
|
||||
|
|
@ -49,10 +50,11 @@ public struct DownloadableRuntime: Codable, Identifiable, Hashable {
|
|||
case name
|
||||
case authentication
|
||||
case sdkBuildUpdate
|
||||
case architectures
|
||||
}
|
||||
|
||||
var betaNumber: Int? {
|
||||
enum Regex { static let shared = try! NSRegularExpression(pattern: "b[0-9]+$") }
|
||||
enum Regex { static let shared = try! NSRegularExpression(pattern: "b[0-9]+") }
|
||||
guard var foundString = Regex.shared.firstString(in: identifier) else { return nil }
|
||||
foundString.removeFirst()
|
||||
return Int(foundString)!
|
||||
|
|
@ -94,6 +96,7 @@ public struct SDKToSimulatorMapping: Codable {
|
|||
public let sdkBuildUpdate: String
|
||||
public let simulatorBuildUpdate: String
|
||||
public let sdkIdentifier: String
|
||||
public let downloadableIdentifiers: [String]?
|
||||
}
|
||||
|
||||
extension DownloadableRuntime {
|
||||
|
|
|
|||
Loading…
Reference in a new issue