diff --git a/Package.swift b/Package.swift index b4c4681fd43..32684b2293c 100644 --- a/Package.swift +++ b/Package.swift @@ -738,6 +738,14 @@ let package = Package( swiftLanguageVersions: [.v5] ) +#if canImport(Darwin) +package.targets.append(contentsOf: [ + .executableTarget( + name: "swiftpm-testing-helper" + ) +]) +#endif + // Workaround SPM's attempt to link in executables which does not work on all // platforms. #if !os(Windows) diff --git a/Sources/swiftpm-testing-helper/Entrypoint.swift b/Sources/swiftpm-testing-helper/Entrypoint.swift new file mode 100644 index 00000000000..84ae211a6cf --- /dev/null +++ b/Sources/swiftpm-testing-helper/Entrypoint.swift @@ -0,0 +1,49 @@ +//===----------------------------------------------------------------------===// +// +// This source file is part of the Swift open source project +// +// Copyright (c) 2014-2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +//===----------------------------------------------------------------------===// + +import Darwin.C + +@main +struct Entrypoint { + static func main() throws { + let args = CommandLine.arguments + if args.count >= 3, args[1] == "--test-bundle-path" { + let bundlePath = args[2] + guard let image = dlopen(bundlePath, RTLD_LAZY | RTLD_FIRST) else { + let errorMessage: String = dlerror().flatMap { + #if compiler(>=6) + String(validatingCString: $0) + #else + String(validatingUTF8: $0) + #endif + } ?? "An unknown error occurred." + fatalError("Failed to open test bundle at path \(bundlePath): \(errorMessage)") + } + defer { + dlclose(image) + } + + // Find and call the main function from the image. This function may + // link to the copy of Swift Testing included with Xcode, or may link to + // a copy that's included as a package dependency. + let main = dlsym(image, "main").map { + unsafeBitCast( + $0, + to: (@convention(c) (CInt, UnsafeMutablePointer?>) -> CInt).self + ) + } + if let main { + exit(main(CommandLine.argc, CommandLine.unsafeArgv)) + } + } + } +} diff --git a/Utilities/bootstrap b/Utilities/bootstrap index 63b6aa464d1..62fbbc4b21a 100755 --- a/Utilities/bootstrap +++ b/Utilities/bootstrap @@ -435,7 +435,14 @@ def install(args): def install_swiftpm(prefix, args): # Install the swift-package-manager tool and create symlinks to it. cli_tool_dest = os.path.join(prefix, "bin") + aux_tool_dest = os.path.join(prefix, "libexec", "swift", "pm") + install_binary(args, "swift-package-manager", os.path.join(cli_tool_dest, "swift-package"), destination_is_directory=False) + + # `swiftpm-testing-helper` only exists on Darwin platforms + if os.path.exists(os.path.join(args.bin_dir, "swiftpm-testing-helper")): + install_binary(args, "swiftpm-testing-helper", aux_tool_dest) + for tool in ["swift-build", "swift-test", "swift-run", "swift-package-collection", "swift-package-registry", "swift-sdk", "swift-experimental-sdk"]: src = "swift-package" dest = os.path.join(cli_tool_dest, tool)