Skip to content

Commit b62d108

Browse files
authored
Merge pull request #113 from giginet/swift-510
Support Xcode 15.3 and Swift 5.10
2 parents b2d8453 + c3b18c4 commit b62d108

21 files changed

+298
-58
lines changed

.github/workflows/lint.yml

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: Lint
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
branches:
9+
- '*'
10+
jobs:
11+
SwiftLint:
12+
strategy:
13+
matrix:
14+
xcode_version: ["15.2"]
15+
env:
16+
DEVELOPER_DIR: "/Applications/Xcode_${{ matrix.xcode_version }}.app/Contents/Developer"
17+
runs-on: macos-13
18+
steps:
19+
- uses: actions/checkout@v2
20+
- name: SwiftLint
21+
run: swiftlint --strict

.github/workflows/tests.yml

+15-4
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,27 @@ jobs:
1111
Tests:
1212
strategy:
1313
matrix:
14-
xcode_version: ["14.3.1", "15.0"]
14+
xcode_version: ["15.2"]
15+
swift: ["5.8.1", "5.9.2", "5.10.0"]
1516
env:
1617
DEVELOPER_DIR: "/Applications/Xcode_${{ matrix.xcode_version }}.app/Contents/Developer"
1718
runs-on: macos-13
1819
steps:
20+
- uses: SwiftyLab/setup-swift@latest
21+
with:
22+
development: true
23+
swift-version: ${{ matrix.swift }}
24+
- name: Get swift version
25+
run: swift --version
1926
- uses: actions/checkout@v2
20-
- name: SwiftLint
21-
run: swiftlint --strict
2227
- name: Run Tests
2328
run: |
24-
swift test --verbose
29+
# If default toolchain in Xcode is used, `env.TOOLCHAINS` will be empty
30+
if [[ -n "${{ env.TOOLCHAINS }}" ]]; then
31+
xcrun --toolchain ${{ env.TOOLCHAINS }} swift test --verbose
32+
else
33+
swift test --verbose
34+
fi
2535
env:
2636
ENABLE_INTEGRATION_TESTS: 1
37+
IS_CI: 1

Package.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ let package = Package(
2121
],
2222
dependencies: [
2323
.package(url: "https://github.com/apple/swift-package-manager.git",
24-
revision: "swift-5.9-RELEASE"),
24+
revision: "swift-5.10-DEVELOPMENT-SNAPSHOT-2024-01-25-a"),
2525
.package(url: "https://github.com/apple/swift-log.git",
2626
.upToNextMinor(from: "1.4.2")),
2727
.package(url: "https://github.com/apple/swift-collections",

[email protected]

+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// swift-tools-version: 5.6
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
import PackageDescription
5+
import Foundation
6+
7+
let package = Package(
8+
name: "Scipio",
9+
platforms: [
10+
.macOS(.v12),
11+
],
12+
products: [
13+
.executable(name: "scipio",
14+
targets: ["scipio"]),
15+
.library(
16+
name: "ScipioKit",
17+
targets: ["ScipioKit"]),
18+
.library(
19+
name: "ScipioS3Storage",
20+
targets: ["ScipioS3Storage"]),
21+
],
22+
dependencies: [
23+
.package(url: "https://github.com/apple/swift-package-manager.git",
24+
revision: "swift-5.9-RELEASE"),
25+
.package(url: "https://github.com/apple/swift-log.git",
26+
.upToNextMinor(from: "1.4.2")),
27+
.package(url: "https://github.com/apple/swift-collections",
28+
from: "1.0.4"),
29+
.package(url: "https://github.com/apple/swift-argument-parser.git",
30+
from: "1.1.0"),
31+
.package(url: "https://github.com/apple/swift-algorithms.git",
32+
from: "1.0.0"),
33+
.package(url: "https://github.com/onevcat/Rainbow",
34+
.upToNextMinor(from: "4.0.1")),
35+
.package(url: "https://github.com/soto-project/soto-codegenerator",
36+
from: "0.6.0"),
37+
.package(url: "https://github.com/soto-project/soto-core.git",
38+
from: "6.4.0"),
39+
],
40+
targets: [
41+
.executableTarget(name: "scipio",
42+
dependencies: [
43+
.target(name: "ScipioKit"),
44+
.product(name: "ArgumentParser", package: "swift-argument-parser"),
45+
]),
46+
.target(
47+
name: "ScipioKit",
48+
dependencies: [
49+
.product(name: "SwiftPMDataModel-auto", package: "swift-package-manager"),
50+
.product(name: "XCBuildSupport", package: "swift-package-manager"),
51+
.product(name: "Logging", package: "swift-log"),
52+
.product(name: "Collections", package: "swift-collections"),
53+
.product(name: "Algorithms", package: "swift-algorithms"),
54+
.product(name: "Rainbow", package: "Rainbow"),
55+
],
56+
plugins: [
57+
.plugin(name: "GenerateScipioVersion")
58+
]
59+
),
60+
.plugin(
61+
name: "GenerateScipioVersion",
62+
capability: .buildTool()
63+
),
64+
.target(
65+
name: "ScipioS3Storage",
66+
dependencies: [
67+
.target(name: "ScipioKit"),
68+
.product(name: "SotoCore", package: "soto-core"),
69+
],
70+
plugins: [
71+
.plugin(name: "SotoCodeGeneratorPlugin", package: "soto-codegenerator"),
72+
]
73+
),
74+
.testTarget(
75+
name: "ScipioKitTests",
76+
dependencies: [
77+
.target(name: "ScipioKit"),
78+
],
79+
exclude: ["Resources/Fixtures/"],
80+
resources: [.copy("Resources/Fixtures")]),
81+
.testTarget(
82+
name: "ScipioS3StorageTests",
83+
dependencies: ["ScipioS3Storage"]),
84+
]
85+
)
86+
87+
let isDevelopment = ProcessInfo.processInfo.environment["SCIPIO_DEVELOPMENT"] == "1"
88+
89+
// swift-docs is not needed for package users
90+
if isDevelopment {
91+
package.dependencies += [
92+
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.3.0"),
93+
]
94+
}

README.md

+15-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
# Scipio
22

33
![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/giginet/Scipio/tests.yml?style=flat-square&logo=github)
4+
![Swift 5.10](https://img.shields.io/badge/Swift-5.10-FA7343?logo=swift&style=flat-square)
45
![Swift 5.9](https://img.shields.io/badge/Swift-5.9-FA7343?logo=swift&style=flat-square)
56
![Swift 5.8](https://img.shields.io/badge/Swift-5.8-FA7343?logo=swift&style=flat-square)
6-
[![Xcode 15.0](https://img.shields.io/badge/Xcode-15.0-147EFB?style=flat-square&logo=xcode&link=https%3A%2F%2Fdeveloper.apple.com%2Fxcode%2F)](https://developer.apple.com/xcode/)
7+
[![Xcode 15.3](https://img.shields.io/badge/Xcode-15.3-147EFB?style=flat-square&logo=xcode&link=https%3A%2F%2Fdeveloper.apple.com%2Fxcode%2F)](https://developer.apple.com/xcode/)
8+
[![Xcode 15.2](https://img.shields.io/badge/Xcode-15.2-147EFB?style=flat-square&logo=xcode&link=https%3A%2F%2Fdeveloper.apple.com%2Fxcode%2F)](https://developer.apple.com/xcode/)
79
[![Xcode 14.3](https://img.shields.io/badge/Xcode-14.3-147EFB?style=flat-square&logo=xcode&link=https%3A%2F%2Fdeveloper.apple.com%2Fxcode%2F)](https://developer.apple.com/xcode/)
810
[![SwiftPM](https://img.shields.io/badge/SwiftPM-compatible-green?logo=swift&style=flat-square)](https://swift.org/package-manager/)
911
[![Documentation](https://img.shields.io/badge/Documentation-available-green?style=flat-square)](https://giginet.github.io/Scipio/documentation/scipio/)
@@ -132,6 +134,18 @@ $ scipio create path/to/MyPackage
132134

133135
See [Convert Single Swift Package to XCFramework](https://giginet.github.io/Scipio/documentation/scipio/create-frameworks) for detail.
134136

137+
## Supported Xcode and Swift version
138+
139+
Currently, we support Swift 5.8, 5.9, and 5.10.
140+
141+
Swift 5.8 support will be dropped in the future.
142+
143+
| | Xcode | Swift |
144+
|----|--------------|-------|
145+
|| 15.3(Beta 1) | 5.10 |
146+
|| 15.0<=15.2 | 5.9 |
147+
|| 14.3 | 5.8 |
148+
135149
## Reliability
136150

137151
Scipio only builts with standard dependencies and Apple official tools to keep reliability.

Sources/ScipioKit/DescriptionPackage.swift

+18-14
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Basics
88

99
struct DescriptionPackage {
1010
let mode: Runner.Mode
11-
let packageDirectory: AbsolutePath
11+
let packageDirectory: ScipioAbsolutePath
1212
private let toolchain: UserToolchain
1313
let workspace: Workspace
1414
let graph: PackageGraph
@@ -34,32 +34,32 @@ struct DescriptionPackage {
3434
manifest.displayName
3535
}
3636

37-
var buildDirectory: AbsolutePath {
37+
var buildDirectory: ScipioAbsolutePath {
3838
packageDirectory.appending(component: ".build")
3939
}
4040

41-
var workspaceDirectory: AbsolutePath {
41+
var workspaceDirectory: ScipioAbsolutePath {
4242
buildDirectory.appending(component: "scipio")
4343
}
4444

4545
var supportedSDKs: Set<SDK> {
4646
Set(manifest.platforms.map(\.platformName).compactMap(SDK.init(platformName:)))
4747
}
4848

49-
var derivedDataPath: AbsolutePath {
49+
var derivedDataPath: ScipioAbsolutePath {
5050
workspaceDirectory.appending(component: "DerivedData")
5151
}
5252

53-
func generatedModuleMapPath(of target: ResolvedTarget, sdk: SDK) throws -> AbsolutePath {
54-
let relativePath = try RelativePath(validating: "ModuleMapsForFramework/\(sdk.settingValue)")
53+
func generatedModuleMapPath(of target: ResolvedTarget, sdk: SDK) throws -> ScipioAbsolutePath {
54+
let relativePath = try TSCBasic.RelativePath(validating: "ModuleMapsForFramework/\(sdk.settingValue)")
5555
return workspaceDirectory
5656
.appending(relativePath)
5757
.appending(component: target.modulemapName)
5858
}
5959

6060
/// Returns an Products directory path
6161
/// It should be the default setting of `TARGET_BUILD_DIR`
62-
func productsDirectory(buildConfiguration: BuildConfiguration, sdk: SDK) -> AbsolutePath {
62+
func productsDirectory(buildConfiguration: BuildConfiguration, sdk: SDK) -> ScipioAbsolutePath {
6363
let intermediateDirectoryName = productDirectoryName(
6464
buildConfiguration: buildConfiguration,
6565
sdk: sdk
@@ -68,12 +68,12 @@ struct DescriptionPackage {
6868
}
6969

7070
/// Returns a directory path which contains assembled frameworks
71-
var assembledFrameworksRootDirectory: AbsolutePath {
71+
var assembledFrameworksRootDirectory: ScipioAbsolutePath {
7272
workspaceDirectory.appending(component: "AssembledFrameworks")
7373
}
7474

7575
/// Returns a directory path of the assembled frameworks path for the specific Configuration/Platform
76-
func assembledFrameworksDirectory(buildConfiguration: BuildConfiguration, sdk: SDK) -> AbsolutePath {
76+
func assembledFrameworksDirectory(buildConfiguration: BuildConfiguration, sdk: SDK) -> ScipioAbsolutePath {
7777
let intermediateDirName = productDirectoryName(buildConfiguration: buildConfiguration, sdk: sdk)
7878
return assembledFrameworksRootDirectory
7979
.appending(component: intermediateDirName)
@@ -91,7 +91,7 @@ struct DescriptionPackage {
9191

9292
// MARK: Initializer
9393

94-
private static func makeWorkspace(toolchain: UserToolchain, packagePath: AbsolutePath) throws -> Workspace {
94+
private static func makeWorkspace(toolchain: UserToolchain, packagePath: ScipioAbsolutePath) throws -> Workspace {
9595
var workspaceConfiguration: WorkspaceConfiguration = .default
9696
// override default configuration to treat XIB files
9797
workspaceConfiguration.additionalFileRules = FileRuleDescription.xcbuildFileTypes
@@ -101,7 +101,7 @@ struct DescriptionPackage {
101101
.makeAuthorizationProvider(fileSystem: fileSystem, observabilityScope: observabilitySystem.topScope)
102102
let workspace = try Workspace(
103103
fileSystem: fileSystem,
104-
location: Workspace.Location(forRootPackage: packagePath, fileSystem: fileSystem),
104+
location: Workspace.Location(forRootPackage: packagePath.spmAbsolutePath, fileSystem: fileSystem),
105105
authorizationProvider: authorizationProvider,
106106
configuration: workspaceConfiguration,
107107
customHostToolchain: toolchain
@@ -116,25 +116,29 @@ struct DescriptionPackage {
116116
/// Then, use package versions only from existing Package.resolved.
117117
/// If it is `true`, Package.resolved never be updated.
118118
/// Instead, the resolving will fail if the Package.resolved is mis-matched with the workspace.
119-
init(packageDirectory: AbsolutePath, mode: Runner.Mode, onlyUseVersionsFromResolvedFile: Bool) throws {
119+
init(packageDirectory: ScipioAbsolutePath, mode: Runner.Mode, onlyUseVersionsFromResolvedFile: Bool) throws {
120120
self.packageDirectory = packageDirectory
121121
self.mode = mode
122122

123+
#if swift(>=5.10)
124+
let toolchain = try UserToolchain(swiftSDK: try .hostSwiftSDK())
125+
#else
123126
let toolchain = try UserToolchain(destination: try .hostDestination())
127+
#endif
124128
self.toolchain = toolchain
125129

126130
let workspace = try Self.makeWorkspace(toolchain: toolchain, packagePath: packageDirectory)
127131
let scope = observabilitySystem.topScope
128132
self.graph = try workspace.loadPackageGraph(
129-
rootInput: PackageGraphRootInput(packages: [packageDirectory]),
133+
rootInput: PackageGraphRootInput(packages: [packageDirectory.spmAbsolutePath]),
130134
// This option is same with resolver option `--disable-automatic-resolution`
131135
// Never update Package.resolved of the package
132136
forceResolvedVersions: onlyUseVersionsFromResolvedFile,
133137
observabilityScope: scope
134138
)
135139
self.manifest = try tsc_await {
136140
workspace.loadRootManifest(
137-
at: packageDirectory,
141+
at: packageDirectory.spmAbsolutePath,
138142
observabilityScope: scope,
139143
completion: $0
140144
)

Sources/ScipioKit/Producer/BinaryExtractor.swift

+4-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ struct BinaryExtractor {
1818
logger.info("🗑️ Delete \(frameworkName)", metadata: .color(.red))
1919
try fileSystem.removeFileTree(destinationPath.absolutePath)
2020
}
21-
try fileSystem.copy(from: sourcePath, to: destinationPath.absolutePath)
21+
try fileSystem.copy(
22+
from: sourcePath,
23+
to: destinationPath.absolutePath.spmAbsolutePath
24+
)
2225

2326
return destinationPath
2427
}

Sources/ScipioKit/Producer/Cache/CacheSystem.swift

+11-2
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,10 @@ struct CacheSystem {
194194

195195
let data = try jsonEncoder.encode(cacheKey)
196196
let versionFilePath = outputDirectory.appendingPathComponent(versionFileName(for: target.buildProduct.target.name))
197-
try fileSystem.writeFileContents(versionFilePath.absolutePath, data: data)
197+
try fileSystem.writeFileContents(
198+
versionFilePath.absolutePath.spmAbsolutePath,
199+
data: data
200+
)
198201
}
199202

200203
func existsValidCache(cacheKey: CacheKey) async -> Bool {
@@ -254,9 +257,15 @@ struct CacheSystem {
254257

255258
private func retrievePin(product: BuildProduct) throws -> PinsStore.Pin {
256259
let pinsStore = try descriptionPackage.workspace.pinsStore.load()
260+
#if swift(>=5.10)
261+
guard let pin = pinsStore.pins[product.package.identity] else {
262+
throw Error.revisionNotDetected(product.package.manifest.displayName)
263+
}
264+
#else
257265
guard let pin = pinsStore.pinsMap[product.package.identity] else {
258266
throw Error.revisionNotDetected(product.package.manifest.displayName)
259267
}
268+
#endif
260269
return pin
261270
}
262271

@@ -285,7 +294,7 @@ public struct VersionFileDecoder {
285294

286295
public func decode(versionFile: URL) throws -> CacheKey {
287296
try jsonDecoder.decode(
288-
path: versionFile.absolutePath,
297+
path: versionFile.absolutePath.spmAbsolutePath,
289298
fileSystem: fileSystem,
290299
as: CacheKey.self
291300
)

Sources/ScipioKit/Producer/InfoPlistGenerator.swift

+4-1
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ struct InfoPlistGenerator {
1010

1111
func generateForResourceBundle(at path: AbsolutePath) throws {
1212
let body = resourceBundleBody
13-
13+
#if swift(>=5.10)
14+
try fileSystem.writeFileContents(path.spmAbsolutePath, string: body)
15+
#else
1416
try fileSystem.writeFileContents(path, string: body)
17+
#endif
1518
}
1619

1720
private var resourceBundleBody: String {

Sources/ScipioKit/Producer/PIF/BuildParametersGenerator.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ struct BuildParametersGenerator {
3636
}
3737

3838
func generate(for sdk: SDK, buildParameters: BuildParameters, destinationDir: AbsolutePath) throws -> AbsolutePath {
39-
#if swift(>=5.9)
39+
#if swift(>=5.10)
40+
let targetArchitecture = buildParameters.targetTriple.arch?.rawValue ?? "arm64"
41+
#elseif swift(>=5.9)
4042
let targetArchitecture = buildParameters.triple.arch?.rawValue ?? "arm64"
4143
#else
4244
let targetArchitecture = buildParameters.triple.arch.rawValue

Sources/ScipioKit/Producer/PIF/FrameworkComponentsCollector.swift

+1
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ struct FrameworkComponentsCollector {
155155
.headers
156156
.filter { $0.isDescendant(of: clangTarget.includeDir) }
157157
let notSymlinks = publicHeaders.filter { !fileSystem.isSymlink($0) }
158+
.map { $0.scipioAbsolutePath }
158159
let symlinks = publicHeaders.filter { fileSystem.isSymlink($0) }
159160

160161
// Sometimes, public headers include a file and its symlink both.

0 commit comments

Comments
 (0)