Apply runtime library workaround for snapshot toolchains on macOS (#484)

* 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
This commit is contained in:
omochimetaru 2024-06-11 06:57:10 +08:00 committed by GitHub
parent 2f6de6cac3
commit 79b686c73d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 92 additions and 25 deletions

View File

@ -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:

View File

@ -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

View File

@ -135,10 +135,10 @@ 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,
@ -146,8 +146,19 @@ func pluginSubcommand(subcommand: String, argv0: String, arguments: [String]) as
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
)
}
@ -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
)

View File

@ -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)
}

View File

@ -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"

View File

@ -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)
@ -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
)

File diff suppressed because one or more lines are too long

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import CartonCore
import CartonHelpers
import Foundation
@ -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)
@ -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
]
)
}
}
}

View File

@ -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),
@ -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)
}
}
@ -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] {
@ -311,4 +315,8 @@ public class ToolchainSystem {
return version
}
public static func isSnapshotVersion(_ version: String) -> Bool {
version.contains("SNAPSHOT")
}
}

View File

@ -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()

View File

@ -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;