Skip to content

Commit

Permalink
Apply runtime library workaround for snapshot toolchains on macOS (#484)
Browse files Browse the repository at this point in the history
* patch mac snapshot

* comment

* set DYLD_LIBRARY_PATH if need

* reset stdin pgrp

* revert wip default toolchain

* fix test

* desudo

* avoid setting nil

* link RegexParser

* swift_StringProcessing

* preopen on wasmtime

* fix bug in test runner option

* apply patch also command mode

* cap hack version
  • Loading branch information
omochi committed Jun 10, 2024
1 parent 2f6de6c commit 79b686c
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 25 deletions.
6 changes: 6 additions & 0 deletions Sources/CartonCore/Environment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@ public enum Environment: String, CaseIterable {
// for future dynamic linking support.
parameters.otherSwiftcFlags += ["-static-stdlib"]

#if compiler(>=6.0) && compiler(<6.1)
// A workaround for the linker issue.
// https://github.com/swiftwasm/swift/issues/5580
parameters.otherLinkerFlags += ["-lswift_RegexParser"]
#endif

switch self {
case .command: break
case .node, .browser:
Expand Down
4 changes: 4 additions & 0 deletions Sources/CartonCore/FoundationProcessEx.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,16 @@ extension Foundation.Process {
public static func checkRun(
_ executableURL: URL,
arguments: [String],
environment: [String: String]? = nil,
printsLoadingMessage: Bool = true,
forwardExit: Bool = false
) throws {
let process = Foundation.Process()
process.executableURL = executableURL
process.arguments = arguments
if let environment {
process.environment = environment
}
try process.checkRun(
printsLoadingMessage: printsLoadingMessage,
forwardExit: forwardExit
Expand Down
22 changes: 17 additions & 5 deletions Sources/CartonDriver/CartonDriverCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,19 +135,30 @@ func pluginSubcommand(subcommand: String, argv0: String, arguments: [String]) as

let terminal = InteractiveWriter.stdout
let toolchainSystem = try ToolchainSystem(fileSystem: localFileSystem)
let (swiftPath, _) = try await toolchainSystem.inferSwiftPath(terminal)
let swiftPath = try await toolchainSystem.inferSwiftPath(terminal)
let extraArguments = arguments

let swiftExec = URL(fileURLWithPath: swiftPath.pathString)
let swiftExec = URL(fileURLWithPath: swiftPath.swift.pathString)
let pluginArguments = try derivePackageCommandArguments(
swiftExec: swiftExec,
subcommand: subcommand,
scratchPath: scratchPath.path,
extraArguments: extraArguments
)

var env: [String: String] = ProcessInfo.processInfo.environment
if ToolchainSystem.isSnapshotVersion(swiftPath.verison),
swiftPath.toolchain.extension == "xctoolchain"
{
env["DYLD_LIBRARY_PATH"] = swiftPath.toolchain.appending(
components: ["usr", "lib", "swift", "macosx"]
).pathString
}

try Foundation.Process.checkRun(
swiftExec, arguments: pluginArguments,
swiftExec,
arguments: pluginArguments,
environment: env,
forwardExit: true
)
}
Expand Down Expand Up @@ -175,9 +186,10 @@ public func main(arguments: [String]) async throws {
case "package":
let terminal = InteractiveWriter.stdout
let toolchainSystem = try ToolchainSystem(fileSystem: localFileSystem)
let (swiftPath, _) = try await toolchainSystem.inferSwiftPath(terminal)
let swiftPath = try await toolchainSystem.inferSwiftPath(terminal)

try Foundation.Process.checkRun(
URL(fileURLWithPath: swiftPath.pathString),
URL(fileURLWithPath: swiftPath.swift.pathString),
arguments: ["package"] + arguments.dropFirst(),
forwardExit: true
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,16 @@ struct CommandTestRunner: TestRunner {
var arguments = [program, testFilePath.pathString]
if listTestCases {
arguments.append(contentsOf: ["--", "-l"])
} else if !testCases.isEmpty {
arguments.append("--")
arguments.append(contentsOf: testCases)
} else {
let programName = (program as NSString).lastPathComponent
if programName == "wasmtime" {
arguments += ["--dir", "."]
}

if !testCases.isEmpty {
arguments.append("--")
arguments.append(contentsOf: testCases)
}
}
try await Process.run(arguments, parser: TestsParser(), terminal)
}
Expand Down
4 changes: 3 additions & 1 deletion Sources/CartonHelpers/DefaultToolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#if compiler(>=5.10)
#if compiler(>=6.0)
public let defaultToolchainVersion = "wasm-6.0-SNAPSHOT-2024-06-08-a"
#elseif compiler(>=5.10)
public let defaultToolchainVersion = "wasm-5.10.0-RELEASE"
#else
public let defaultToolchainVersion = "wasm-5.9.2-RELEASE"
Expand Down
3 changes: 1 addition & 2 deletions Sources/CartonHelpers/Process+run.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ extension Process {

switch result.map(\.exitStatus) {
case .success(.terminated(code: EXIT_SUCCESS)):
terminal.write("\n")
if let parser = parser {
if parser.parsingConditions.contains(.success) {
parser.parse(stdoutBuffer, terminal)
Expand All @@ -103,7 +102,7 @@ extension Process {
terminal.write(stdoutBuffer)
}
terminal.write(
"\n`\(processName)` process finished successfully\n",
"`\(processName)` process finished successfully\n",
inColor: .green,
bold: false
)
Expand Down
8 changes: 4 additions & 4 deletions Sources/CartonKit/Server/StaticArchive.swift

Large diffs are not rendered by default.

29 changes: 29 additions & 0 deletions Sources/SwiftToolchain/ToolchainInstallation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import CartonCore
import CartonHelpers
import Foundation

Expand Down Expand Up @@ -65,6 +66,8 @@ extension ToolchainSystem {
stream: stdoutStream,
header: "Downloading the archive"
)
defer { terminal.write("\n") }

var previouslyReceived = 0
for try await progress in fileDownload.progressStream {
guard progress.receivedBytes - previouslyReceived >= (progress.totalOrEstimatedBytes / 100)
Expand Down Expand Up @@ -109,6 +112,32 @@ extension ToolchainSystem {
terminal.logLookup("Unpacking the archive: ", arguments.joined(separator: " "))
try await Process.run(arguments, terminal)

if ext == "pkg", Self.isSnapshotVersion(version) {
try await patchSnapshotForMac(path: installationPath, terminal: terminal)
}

return installationPath
}

func patchSnapshotForMac(path: AbsolutePath, terminal: InteractiveWriter) async throws {
let binDir = path.appending(components: ["usr", "bin"])

terminal.write(
"To avoid issues with the snapshot, the toolchain will be re-signed.\n",
inColor: .yellow
)

for file in try fileSystem.traverseRecursively(binDir) {
guard fileSystem.isFile(file) else { continue }

try Foundation.Process.checkRun(
URL(fileURLWithPath: "/usr/bin/codesign"),
arguments: [
"--force",
"--preserve-metadata=identifier,entitlements",
"--sign", "-", file.pathString
]
)
}
}
}
22 changes: 15 additions & 7 deletions Sources/SwiftToolchain/ToolchainManagement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,19 @@ public class ToolchainSystem {
}
}

public struct SwiftPath {
public var verison: String
public var swift: AbsolutePath
public var toolchain: AbsolutePath
}

/** Infer `swift` binary path matching a given version if any is present, or infer the
version from the `.swift-version` file. If neither version is installed, download it.
*/
public func inferSwiftPath(
from versionSpec: String? = nil,
_ terminal: InteractiveWriter
) async throws -> (AbsolutePath, String) {
) async throws -> SwiftPath {
let specURL = versionSpec.flatMap { (string: String) -> Foundation.URL? in
guard
let url = Foundation.URL(string: string),
Expand All @@ -254,11 +260,9 @@ public class ToolchainSystem {
let swiftVersion = try inferSwiftVersion(from: versionSpec, terminal)

for resolver in resolvers {
if let path = try checkAndLog(
installationPath: resolver.toolchain(for: swiftVersion),
terminal
) {
return (path, swiftVersion)
let toolchain = resolver.toolchain(for: swiftVersion)
if let path = try checkAndLog(installationPath: toolchain, terminal) {
return SwiftPath(verison: swiftVersion, swift: path, toolchain: toolchain)
}
}

Expand Down Expand Up @@ -291,7 +295,7 @@ public class ToolchainSystem {
throw ToolchainError.invalidInstallationArchive(installationPath)
}

return (path, swiftVersion)
return SwiftPath(verison: swiftVersion, swift: path, toolchain: installationPath)
}

public func fetchAllSwiftVersions() throws -> [String] {
Expand All @@ -311,4 +315,8 @@ public class ToolchainSystem {

return version
}

public static func isSnapshotVersion(_ version: String) -> Bool {
version.contains("SNAPSHOT")
}
}
4 changes: 2 additions & 2 deletions Tests/CartonCommandTests/FrontendDevServerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,10 @@ final class FrontendDevServerTests: XCTestCase {

if !fs.exists(wasmFile) {
let tools = try ToolchainSystem(fileSystem: fs)
let (builderSwift, _) = try await tools.inferSwiftPath(terminal)
let builderSwift = try await tools.inferSwiftPath(terminal)

var args: [String] = [
builderSwift.pathString, "build", "--triple", "wasm32-unknown-wasi"
builderSwift.swift.pathString, "build", "--triple", "wasm32-unknown-wasi"
]
args += Environment.browser.buildParameters().asBuildArguments()

Expand Down
2 changes: 1 addition & 1 deletion entrypoint/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ export const WasmRunner = (rawOptions: Options, SwiftRuntime: SwiftRuntimeConstr
};

const defaultRunnerOptions = (options: Options): Options => {
if (options.args != null) {
if (options.args == null) {
options.args = ["main.wasm"];
}
return options;
Expand Down

0 comments on commit 79b686c

Please sign in to comment.